metis-desk/packages/shadcn-ui/src/components/select-with-action.tsx
David 5adbe81364 feat: enhance access management with quick create functionality and improved forms
- Added QuickCreateDialog for creating systems and environments quickly.
- Implemented quickCreatePlan to handle creation logic based on context.
- Updated AccessForm to support quick creation and related modals.
- Enhanced i18n support for new quick add features in both English and Spanish.
- Refactored AssignmentForm to allow department creation directly from the form.
- Introduced SelectWithAction component for better user interaction with selections.
- Added tests for new components and functionalities to ensure reliability.
2026-10-04 15:46:39 +02:00

87 lines
2.2 KiB
TypeScript

import { PlusIcon } from "lucide-react";
import { Button } from "./button";
import { ButtonGroup } from "./button-group";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./select";
export type SelectOption = { value: string; label: string; disabled?: boolean };
export type SelectAction = { label: string; onClick: () => void; disabled?: boolean };
/** Selección controlada con una acción adyacente; el consumidor gestiona el alta y su contexto. */
export function SelectWithAction({
id,
label,
options,
placeholder,
value,
onValueChange,
disabled = false,
action,
required = false,
invalid = false,
describedBy,
}: {
id: string;
label: string;
options: readonly SelectOption[];
placeholder: string;
value: string;
onValueChange: (value: string) => void;
disabled?: boolean;
action?: SelectAction | undefined;
required?: boolean;
invalid?: boolean;
describedBy?: string | undefined;
}) {
const select = (
<Select
disabled={disabled}
items={[{ value: "", label: placeholder }, ...options]}
onValueChange={(selected) => {
if (typeof selected === "string") {
onValueChange(selected);
}
}}
required={required}
value={value}
>
<SelectTrigger
aria-describedby={describedBy}
aria-invalid={invalid || undefined}
aria-label={label}
className="w-full min-w-0 flex-1"
id={id}
>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="">{placeholder}</SelectItem>
{options.map((option) => (
<SelectItem disabled={option.disabled} key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
);
if (!action) {
return select;
}
return (
<ButtonGroup aria-label={label} className="w-full min-w-0">
{select}
<Button
aria-label={action.label}
disabled={disabled || action.disabled}
onClick={action.onClick}
size="icon"
title={action.label}
type="button"
variant="outline"
>
<PlusIcon aria-hidden="true" />
</Button>
</ButtonGroup>
);
}