metis-desk/packages/rdx-ui/src/components/option-picker-list.tsx
David db57346c24 feat: add PickerHelp component and browser fixture for picker UI
- Introduced PickerHelp component for contextual help in pickers.
- Created PickerBrowserFixture for testing picker components in a browser-like environment.
- Implemented a comprehensive regression test suite for picker UI using Playwright.
- Added support for localization in picker components and tests.
2026-10-22 09:35:02 +02:00

88 lines
2.2 KiB
TypeScript

import { RadioGroup, RadioGroupItem } from "@repo/shadcn-ui/components/radio-group";
import { EntityTable } from "./entity-list";
import type { PickerOption } from "./option-picker-dialog";
/** Listado de selección única con búsqueda; el diálogo conserva la confirmación provisional. */
export function OptionPickerList({
title,
options,
value,
onChange,
labels,
locale,
loading = false,
}: {
title: string;
options: readonly PickerOption[];
value: string;
onChange: (id: string) => void;
labels: {
selection: string;
name: string;
entity: (count: number) => string;
description: string;
search: string;
};
locale: string;
loading?: boolean;
}) {
const choose = (id: string) => {
if (!loading && options.some((option) => option.id === id && !option.disabled)) {
onChange(id);
}
};
return (
<RadioGroup
aria-label={title}
className="flex min-h-0 flex-1 flex-col"
onValueChange={(id) => {
if (typeof id === "string") {
choose(id);
}
}}
value={value}
>
<EntityTable
columns={[
{
id: "selection",
label: labels.selection,
hideable: false,
render: (option) => (
<RadioGroupItem
aria-label={option.label}
disabled={loading || option.disabled}
value={option.id}
/>
),
},
{
id: "name",
label: labels.name,
hideable: false,
value: (option) => option.label,
render: (option) => <span className="font-medium">{option.label}</span>,
},
{
id: "description",
label: labels.description,
value: (option) => option.description,
render: (option) => option.description || "—",
},
]}
entityLabel={labels.entity}
items={options}
layout="fill"
loading={loading}
locale={locale}
onRowClick={(option) => choose(option.id)}
rowClassName={(option) => (option.disabled ? "cursor-not-allowed!" : "")}
searchPlaceholder={labels.search}
title={title}
/>
</RadioGroup>
);
}