{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "select", "title": "Integrated Select", "description": "Flat-props Select covering dropdown, searchable, multi-select, and remote-loading modes in a single component. Built on shadcn's Combobox primitive.", "registryDependencies": [ "combobox", "button", "input-group", "@easy-shadcn/use-select-items", "@easy-shadcn/use-select-loader" ], "files": [ { "path": "registry/ui/select.tsx", "content": "\"use client\";\n\nimport { Combobox as ComboboxPrimitive } from \"@base-ui/react\";\nimport {\n ArrowDown01Icon,\n Cancel01Icon,\n SearchList01Icon,\n} from \"@hugeicons/core-free-icons\";\nimport { HugeiconsIcon } from \"@hugeicons/react\";\nimport type { ClassValue } from \"clsx\";\nimport type { AriaAttributes, FocusEvent, ReactNode } from \"react\";\nimport { useCallback, useMemo, useState } from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n Combobox,\n ComboboxChip,\n ComboboxChips,\n ComboboxChipsInput,\n ComboboxContent,\n ComboboxEmpty,\n ComboboxItem,\n ComboboxList,\n ComboboxValue,\n useComboboxAnchor,\n} from \"@/components/ui/combobox\";\nimport {\n InputGroup,\n InputGroupAddon,\n InputGroupInput,\n} from \"@/components/ui/input-group\";\nimport { cn } from \"@/lib/utils\";\nimport type { SelectItem } from \"@/registry/hooks/use-select-items\";\nimport { useSelectItems } from \"@/registry/hooks/use-select-items\";\nimport type { SelectItemsLoader } from \"@/registry/hooks/use-select-loader\";\nimport { useSelectLoader } from \"@/registry/hooks/use-select-loader\";\n\nexport type { SelectItem } from \"@/registry/hooks/use-select-items\";\nexport type { SelectItemsLoader } from \"@/registry/hooks/use-select-loader\";\n\ninterface SelectBaseProps {\n /** Forwarded to the focusable control for screen-reader descriptions. */\n \"aria-describedby\"?: string;\n /** Forwarded to the focusable control for invalid-state semantics. */\n \"aria-invalid\"?: AriaAttributes[\"aria-invalid\"];\n /** Chip className for `multiple` mode. */\n chipClassName?: ClassValue;\n /** Root wrapper className. */\n className?: ClassValue;\n /**\n * Show an inline clear button when the field has a value and the user hovers\n * the right-side icon area. Works in all three modes.\n */\n clearable?: boolean;\n /** Popover content className. */\n contentClassName?: ClassValue;\n /**\n * Debounce for `loadItems` calls when `serverSideFilter` is true, in milliseconds.\n * Ignored when `serverSideFilter` is false.\n * @default 250\n */\n debounceMs?: number;\n /** Uncontrolled initial open state. */\n defaultOpen?: boolean;\n /** Disable all interaction. */\n disabled?: boolean;\n /** `` className. */\n emptyClassName?: ClassValue;\n /** Content rendered when no items match the query. @default \"No results\" */\n emptyMessage?: ReactNode;\n /**\n * Message shown when `loadItems` rejects.\n * - `ReactNode`: static content.\n * - `(error) => ReactNode`: receives the rejected value.\n *\n * The default formatter extracts `error.message` or `error.error` from the rejected value,\n * falling back to `\"Failed to load options\"`.\n */\n errorMessage?: ReactNode | ((error: unknown) => ReactNode);\n /**\n * Custom filter predicate. Applies only in static / eager-async modes.\n * Ignored when `serverSideFilter` is `true` (the server is the filter).\n * @default case-insensitive `contains` against `label`\n */\n filter?: (item: SelectItem, query: string) => boolean;\n /**\n * Id applied to the focusable control (trigger button or input), so a\n * `