@duestel/ui 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -62,7 +62,7 @@ function h({ className: t, onClick: r, ...i }) {
62
62
  onClick: (e) => {
63
63
  r?.(e), e.defaultPrevented || o.current?.focus();
64
64
  },
65
- className: e("flex min-h-14 w-full cursor-text flex-wrap items-center gap-1.5 py-1 pl-4 pr-2", "rounded-extra-small border border-outline bg-surface text-on-surface", "transition-colors", "focus-within:border-primary focus-within:outline-2 focus-within:-outline-offset-2 focus-within:outline-primary", a && "pointer-events-none opacity-[0.38]", t),
65
+ className: e("flex min-h-14 w-full cursor-text flex-wrap items-center gap-1.5 py-1 pl-4 pr-2", "rounded-small border border-outline bg-surface text-on-surface", "transition-colors", "focus-within:border-primary focus-within:outline-2 focus-within:-outline-offset-2 focus-within:outline-primary", a && "pointer-events-none opacity-[0.38]", t),
66
66
  ...i
67
67
  });
68
68
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ChipInput.js","names":[],"sources":["../../../src/components/chip-input/ChipInput.tsx"],"sourcesContent":["import {\n createContext,\n useCallback,\n useContext,\n useId,\n useMemo,\n useRef,\n useState,\n} from 'react'\nimport { X } from 'lucide-react'\nimport { cn } from '#/lib/cn'\n\nimport type {\n ClipboardEvent,\n ComponentProps,\n KeyboardEvent,\n ReactNode,\n RefObject,\n} from 'react'\n\n/**\n * ChipInput — Material 3 input-chips field: free text typed into an outlined\n * text field is committed as removable M3 input chips (tags). No headless\n * primitive exists for this in Base UI, so behaviour is implemented here:\n * Enter or comma commits the trimmed text as a chip (duplicates ignored),\n * Backspace in an empty input removes the last chip, and pasted text is split\n * on commas/newlines into multiple chips. `name` renders one hidden input per\n * chip for native form submission.\n * Visuals match the library's existing chip language (Combobox multi-select):\n * outlined 56px field container (extra-small corner, outline → primary on\n * focus-within) wrapping 32px input chips (small corner, outline-variant\n * border, surface-container-low) with a trailing remove target.\n * M3 ref: https://m3.material.io/components/chips (input chips).\n *\n * Compound API:\n * <ChipInput.Root defaultValue={['Design']} name=\"tags\">\n * <ChipInput.Label>Tags</ChipInput.Label>\n * <ChipInput.Group>\n * <ChipInput.Chips />\n * <ChipInput.Input placeholder=\"Add a tag…\" />\n * <ChipInput.Clear />\n * </ChipInput.Group>\n * </ChipInput.Root>\n */\n\ntype ChipInputContextValue = {\n value: string[]\n add: (chip: string) => void\n remove: (chip: string) => void\n clear: () => void\n disabled: boolean\n inputValue: string\n setInputValue: (text: string) => void\n inputId: string\n inputRef: RefObject<HTMLInputElement | null>\n}\n\nconst ChipInputContext = createContext<ChipInputContextValue | null>(null)\n\nfunction useChipInput() {\n const ctx = useContext(ChipInputContext)\n if (!ctx) throw new Error('ChipInput parts must be used within <ChipInput.Root>')\n return ctx\n}\n\ntype RootProps = {\n children: ReactNode\n /** The committed chips — controlled. */\n value?: string[]\n /** The committed chips — uncontrolled initial. */\n defaultValue?: string[]\n onValueChange?: (value: string[]) => void\n /** Renders one hidden input per chip for native form submission. */\n name?: string\n disabled?: boolean\n}\n\nfunction Root({ children, value, defaultValue, onValueChange, name, disabled = false }: RootProps) {\n const [internalValue, setInternalValue] = useState<string[]>(defaultValue ?? [])\n const controlled = value !== undefined\n const currentValue = controlled ? value : internalValue\n\n const [inputValue, setInputValue] = useState('')\n const inputId = useId()\n const inputRef = useRef<HTMLInputElement>(null)\n\n const commitValue = useCallback(\n (next: string[]) => {\n if (!controlled) setInternalValue(next)\n onValueChange?.(next)\n },\n [controlled, onValueChange],\n )\n\n const add = useCallback(\n (chip: string) => {\n const trimmed = chip.trim()\n if (!trimmed || currentValue.includes(trimmed)) return\n commitValue([...currentValue, trimmed])\n },\n [currentValue, commitValue],\n )\n\n const remove = useCallback(\n (chip: string) => {\n commitValue(currentValue.filter((v) => v !== chip))\n },\n [currentValue, commitValue],\n )\n\n const clear = useCallback(() => {\n commitValue([])\n setInputValue('')\n inputRef.current?.focus()\n }, [commitValue])\n\n const ctx = useMemo<ChipInputContextValue>(\n () => ({\n value: currentValue,\n add,\n remove,\n clear,\n disabled,\n inputValue,\n setInputValue,\n inputId,\n inputRef,\n }),\n [currentValue, add, remove, clear, disabled, inputValue, inputId],\n )\n\n return (\n <ChipInputContext.Provider value={ctx}>\n {children}\n {name &&\n currentValue.map((chip) => (\n <input key={chip} type=\"hidden\" name={name} value={chip} disabled={disabled} />\n ))}\n </ChipInputContext.Provider>\n )\n}\n\n/** M3 label above the field (label-large, on-surface); focuses the input. */\nfunction Label({ className, ...props }: ComponentProps<'label'>) {\n const { inputId } = useChipInput()\n return (\n <label\n htmlFor={inputId}\n className={cn('mb-1.5 block text-label-large text-on-surface', className)}\n {...props}\n />\n )\n}\n\n/**\n * The M3 outlined text-field container: draws the 56px outlined box around the\n * chips and the input; turns primary on focus-within. Clicking the empty area\n * focuses the input.\n */\nfunction Group({ className, onClick, ...props }: ComponentProps<'div'>) {\n const { disabled, inputRef } = useChipInput()\n return (\n <div\n onClick={(event) => {\n onClick?.(event)\n if (!event.defaultPrevented) inputRef.current?.focus()\n }}\n className={cn(\n 'flex min-h-14 w-full cursor-text flex-wrap items-center gap-1.5 py-1 pl-4 pr-2',\n 'rounded-extra-small border border-outline bg-surface text-on-surface',\n 'transition-colors',\n 'focus-within:border-primary focus-within:outline-2 focus-within:-outline-offset-2 focus-within:outline-primary',\n disabled && 'pointer-events-none opacity-[0.38]',\n className,\n )}\n {...props}\n />\n )\n}\n\n/**\n * The committed chips. With no children renders each chip as\n * `<Chip>{chip}<ChipRemove /></Chip>`; pass a render prop to customise.\n */\nfunction Chips({\n className,\n children,\n ...props\n}: Omit<ComponentProps<'div'>, 'children'> & {\n children?: ((chip: string) => ReactNode) | ReactNode\n}) {\n const { value } = useChipInput()\n return (\n <div className={cn('contents', className)} {...props}>\n {typeof children === 'function'\n ? value.map((chip) => children(chip))\n : (children ??\n value.map((chip) => (\n <Chip key={chip} value={chip}>\n {chip}\n <ChipRemove />\n </Chip>\n )))}\n </div>\n )\n}\n\nconst ChipContext = createContext<string | null>(null)\n\n/** M3 input chip: 32px, small corner, outlined, surface-container-low. */\nfunction Chip({\n className,\n value,\n ...props\n}: ComponentProps<'div'> & {\n /** The committed value this chip represents (consumed by ChipRemove). */\n value: string\n}) {\n return (\n <ChipContext.Provider value={value}>\n <div\n className={cn(\n 'flex h-8 cursor-default items-center gap-1 rounded-small border border-outline-variant',\n 'bg-surface-container-low pl-3 pr-1 text-label-large text-on-surface',\n className,\n )}\n {...props}\n />\n </ChipContext.Provider>\n )\n}\n\n/** The chip's trailing remove target (M3 input-chip trailing icon). */\nfunction ChipRemove({ className, children, ...props }: ComponentProps<'button'>) {\n const { remove, disabled } = useChipInput()\n const chip = useContext(ChipContext)\n if (chip === null) throw new Error('<ChipInput.ChipRemove> must be used within <ChipInput.Chip>')\n return (\n <button\n type=\"button\"\n aria-label={`Remove ${chip}`}\n disabled={disabled}\n onClick={() => remove(chip)}\n className={cn(\n 'flex size-6 cursor-pointer items-center justify-center rounded-full',\n 'text-on-surface-variant transition-colors hover:bg-on-surface/[0.08]',\n 'focus-visible:outline-2 focus-visible:outline-primary',\n 'disabled:cursor-not-allowed',\n className,\n )}\n {...props}\n >\n {children ?? <X aria-hidden className=\"size-4\" />}\n </button>\n )\n}\n\n/**\n * Borderless by design — the surrounding Group draws the M3 field box.\n * Enter/comma commits the text as a chip; Backspace in an empty input removes\n * the last chip; pasted text splits on commas/newlines.\n */\nfunction Input({\n className,\n onKeyDown,\n onPaste,\n ...props\n}: Omit<ComponentProps<'input'>, 'value' | 'onChange'>) {\n const { value, add, remove, disabled, inputValue, setInputValue, inputId, inputRef } =\n useChipInput()\n\n const commit = () => {\n add(inputValue)\n setInputValue('')\n }\n\n const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\n onKeyDown?.(event)\n if (event.defaultPrevented) return\n if (event.key === 'Enter' || event.key === ',') {\n event.preventDefault()\n commit()\n } else if (event.key === 'Backspace' && inputValue === '' && value.length > 0) {\n remove(value[value.length - 1])\n }\n }\n\n const handlePaste = (event: ClipboardEvent<HTMLInputElement>) => {\n onPaste?.(event)\n if (event.defaultPrevented) return\n const text = event.clipboardData.getData('text')\n if (!/[,\\n]/.test(text)) return\n event.preventDefault()\n for (const part of `${inputValue}${text}`.split(/[,\\n]/)) add(part)\n setInputValue('')\n }\n\n return (\n <input\n id={inputId}\n ref={inputRef}\n type=\"text\"\n value={inputValue}\n onChange={(event) => setInputValue(event.target.value)}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n disabled={disabled}\n className={cn(\n 'h-12 min-w-12 flex-1 bg-transparent text-body-large text-on-surface',\n 'outline-none placeholder:text-on-surface-variant',\n 'disabled:cursor-not-allowed',\n className,\n )}\n {...props}\n />\n )\n}\n\n/** Clears all chips and the pending text; only mounted while there is something to clear. */\nfunction Clear({ className, children, ...props }: ComponentProps<'button'>) {\n const { value, inputValue, clear, disabled } = useChipInput()\n if (value.length === 0 && inputValue === '') return null\n return (\n <button\n type=\"button\"\n aria-label=\"Clear\"\n disabled={disabled}\n onClick={clear}\n className={cn(\n 'flex size-8 shrink-0 cursor-pointer items-center justify-center rounded-full',\n 'text-on-surface-variant transition-colors hover:bg-on-surface/[0.08]',\n 'focus-visible:outline-2 focus-visible:outline-primary',\n 'disabled:cursor-not-allowed',\n className,\n )}\n {...props}\n >\n {children ?? <X aria-hidden className=\"size-4\" />}\n </button>\n )\n}\n\nexport const ChipInput = {\n Root,\n Label,\n Group,\n Chips,\n Chip,\n ChipRemove,\n Input,\n Clear,\n}\nexport { Root, Label, Group, Chips, Chip, ChipRemove, Input, Clear, useChipInput }\nexport type { RootProps as ChipInputRootProps }\n"],"mappings":"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"}
1
+ {"version":3,"file":"ChipInput.js","names":[],"sources":["../../../src/components/chip-input/ChipInput.tsx"],"sourcesContent":["import {\n createContext,\n useCallback,\n useContext,\n useId,\n useMemo,\n useRef,\n useState,\n} from 'react'\nimport { X } from 'lucide-react'\nimport { cn } from '#/lib/cn'\n\nimport type {\n ClipboardEvent,\n ComponentProps,\n KeyboardEvent,\n ReactNode,\n RefObject,\n} from 'react'\n\n/**\n * ChipInput — Material 3 input-chips field: free text typed into an outlined\n * text field is committed as removable M3 input chips (tags). No headless\n * primitive exists for this in Base UI, so behaviour is implemented here:\n * Enter or comma commits the trimmed text as a chip (duplicates ignored),\n * Backspace in an empty input removes the last chip, and pasted text is split\n * on commas/newlines into multiple chips. `name` renders one hidden input per\n * chip for native form submission.\n * Visuals match the library's existing chip language (Combobox multi-select):\n * outlined 56px field container (extra-small corner, outline → primary on\n * focus-within) wrapping 32px input chips (small corner, outline-variant\n * border, surface-container-low) with a trailing remove target.\n * M3 ref: https://m3.material.io/components/chips (input chips).\n *\n * Compound API:\n * <ChipInput.Root defaultValue={['Design']} name=\"tags\">\n * <ChipInput.Label>Tags</ChipInput.Label>\n * <ChipInput.Group>\n * <ChipInput.Chips />\n * <ChipInput.Input placeholder=\"Add a tag…\" />\n * <ChipInput.Clear />\n * </ChipInput.Group>\n * </ChipInput.Root>\n */\n\ntype ChipInputContextValue = {\n value: string[]\n add: (chip: string) => void\n remove: (chip: string) => void\n clear: () => void\n disabled: boolean\n inputValue: string\n setInputValue: (text: string) => void\n inputId: string\n inputRef: RefObject<HTMLInputElement | null>\n}\n\nconst ChipInputContext = createContext<ChipInputContextValue | null>(null)\n\nfunction useChipInput() {\n const ctx = useContext(ChipInputContext)\n if (!ctx) throw new Error('ChipInput parts must be used within <ChipInput.Root>')\n return ctx\n}\n\ntype RootProps = {\n children: ReactNode\n /** The committed chips — controlled. */\n value?: string[]\n /** The committed chips — uncontrolled initial. */\n defaultValue?: string[]\n onValueChange?: (value: string[]) => void\n /** Renders one hidden input per chip for native form submission. */\n name?: string\n disabled?: boolean\n}\n\nfunction Root({ children, value, defaultValue, onValueChange, name, disabled = false }: RootProps) {\n const [internalValue, setInternalValue] = useState<string[]>(defaultValue ?? [])\n const controlled = value !== undefined\n const currentValue = controlled ? value : internalValue\n\n const [inputValue, setInputValue] = useState('')\n const inputId = useId()\n const inputRef = useRef<HTMLInputElement>(null)\n\n const commitValue = useCallback(\n (next: string[]) => {\n if (!controlled) setInternalValue(next)\n onValueChange?.(next)\n },\n [controlled, onValueChange],\n )\n\n const add = useCallback(\n (chip: string) => {\n const trimmed = chip.trim()\n if (!trimmed || currentValue.includes(trimmed)) return\n commitValue([...currentValue, trimmed])\n },\n [currentValue, commitValue],\n )\n\n const remove = useCallback(\n (chip: string) => {\n commitValue(currentValue.filter((v) => v !== chip))\n },\n [currentValue, commitValue],\n )\n\n const clear = useCallback(() => {\n commitValue([])\n setInputValue('')\n inputRef.current?.focus()\n }, [commitValue])\n\n const ctx = useMemo<ChipInputContextValue>(\n () => ({\n value: currentValue,\n add,\n remove,\n clear,\n disabled,\n inputValue,\n setInputValue,\n inputId,\n inputRef,\n }),\n [currentValue, add, remove, clear, disabled, inputValue, inputId],\n )\n\n return (\n <ChipInputContext.Provider value={ctx}>\n {children}\n {name &&\n currentValue.map((chip) => (\n <input key={chip} type=\"hidden\" name={name} value={chip} disabled={disabled} />\n ))}\n </ChipInputContext.Provider>\n )\n}\n\n/** M3 label above the field (label-large, on-surface); focuses the input. */\nfunction Label({ className, ...props }: ComponentProps<'label'>) {\n const { inputId } = useChipInput()\n return (\n <label\n htmlFor={inputId}\n className={cn('mb-1.5 block text-label-large text-on-surface', className)}\n {...props}\n />\n )\n}\n\n/**\n * The M3 outlined text-field container: draws the 56px outlined box around the\n * chips and the input; turns primary on focus-within. Clicking the empty area\n * focuses the input.\n */\nfunction Group({ className, onClick, ...props }: ComponentProps<'div'>) {\n const { disabled, inputRef } = useChipInput()\n return (\n <div\n onClick={(event) => {\n onClick?.(event)\n if (!event.defaultPrevented) inputRef.current?.focus()\n }}\n className={cn(\n 'flex min-h-14 w-full cursor-text flex-wrap items-center gap-1.5 py-1 pl-4 pr-2',\n 'rounded-small border border-outline bg-surface text-on-surface',\n 'transition-colors',\n 'focus-within:border-primary focus-within:outline-2 focus-within:-outline-offset-2 focus-within:outline-primary',\n disabled && 'pointer-events-none opacity-[0.38]',\n className,\n )}\n {...props}\n />\n )\n}\n\n/**\n * The committed chips. With no children renders each chip as\n * `<Chip>{chip}<ChipRemove /></Chip>`; pass a render prop to customise.\n */\nfunction Chips({\n className,\n children,\n ...props\n}: Omit<ComponentProps<'div'>, 'children'> & {\n children?: ((chip: string) => ReactNode) | ReactNode\n}) {\n const { value } = useChipInput()\n return (\n <div className={cn('contents', className)} {...props}>\n {typeof children === 'function'\n ? value.map((chip) => children(chip))\n : (children ??\n value.map((chip) => (\n <Chip key={chip} value={chip}>\n {chip}\n <ChipRemove />\n </Chip>\n )))}\n </div>\n )\n}\n\nconst ChipContext = createContext<string | null>(null)\n\n/** M3 input chip: 32px, small corner, outlined, surface-container-low. */\nfunction Chip({\n className,\n value,\n ...props\n}: ComponentProps<'div'> & {\n /** The committed value this chip represents (consumed by ChipRemove). */\n value: string\n}) {\n return (\n <ChipContext.Provider value={value}>\n <div\n className={cn(\n 'flex h-8 cursor-default items-center gap-1 rounded-small border border-outline-variant',\n 'bg-surface-container-low pl-3 pr-1 text-label-large text-on-surface',\n className,\n )}\n {...props}\n />\n </ChipContext.Provider>\n )\n}\n\n/** The chip's trailing remove target (M3 input-chip trailing icon). */\nfunction ChipRemove({ className, children, ...props }: ComponentProps<'button'>) {\n const { remove, disabled } = useChipInput()\n const chip = useContext(ChipContext)\n if (chip === null) throw new Error('<ChipInput.ChipRemove> must be used within <ChipInput.Chip>')\n return (\n <button\n type=\"button\"\n aria-label={`Remove ${chip}`}\n disabled={disabled}\n onClick={() => remove(chip)}\n className={cn(\n 'flex size-6 cursor-pointer items-center justify-center rounded-full',\n 'text-on-surface-variant transition-colors hover:bg-on-surface/[0.08]',\n 'focus-visible:outline-2 focus-visible:outline-primary',\n 'disabled:cursor-not-allowed',\n className,\n )}\n {...props}\n >\n {children ?? <X aria-hidden className=\"size-4\" />}\n </button>\n )\n}\n\n/**\n * Borderless by design — the surrounding Group draws the M3 field box.\n * Enter/comma commits the text as a chip; Backspace in an empty input removes\n * the last chip; pasted text splits on commas/newlines.\n */\nfunction Input({\n className,\n onKeyDown,\n onPaste,\n ...props\n}: Omit<ComponentProps<'input'>, 'value' | 'onChange'>) {\n const { value, add, remove, disabled, inputValue, setInputValue, inputId, inputRef } =\n useChipInput()\n\n const commit = () => {\n add(inputValue)\n setInputValue('')\n }\n\n const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\n onKeyDown?.(event)\n if (event.defaultPrevented) return\n if (event.key === 'Enter' || event.key === ',') {\n event.preventDefault()\n commit()\n } else if (event.key === 'Backspace' && inputValue === '' && value.length > 0) {\n remove(value[value.length - 1])\n }\n }\n\n const handlePaste = (event: ClipboardEvent<HTMLInputElement>) => {\n onPaste?.(event)\n if (event.defaultPrevented) return\n const text = event.clipboardData.getData('text')\n if (!/[,\\n]/.test(text)) return\n event.preventDefault()\n for (const part of `${inputValue}${text}`.split(/[,\\n]/)) add(part)\n setInputValue('')\n }\n\n return (\n <input\n id={inputId}\n ref={inputRef}\n type=\"text\"\n value={inputValue}\n onChange={(event) => setInputValue(event.target.value)}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n disabled={disabled}\n className={cn(\n 'h-12 min-w-12 flex-1 bg-transparent text-body-large text-on-surface',\n 'outline-none placeholder:text-on-surface-variant',\n 'disabled:cursor-not-allowed',\n className,\n )}\n {...props}\n />\n )\n}\n\n/** Clears all chips and the pending text; only mounted while there is something to clear. */\nfunction Clear({ className, children, ...props }: ComponentProps<'button'>) {\n const { value, inputValue, clear, disabled } = useChipInput()\n if (value.length === 0 && inputValue === '') return null\n return (\n <button\n type=\"button\"\n aria-label=\"Clear\"\n disabled={disabled}\n onClick={clear}\n className={cn(\n 'flex size-8 shrink-0 cursor-pointer items-center justify-center rounded-full',\n 'text-on-surface-variant transition-colors hover:bg-on-surface/[0.08]',\n 'focus-visible:outline-2 focus-visible:outline-primary',\n 'disabled:cursor-not-allowed',\n className,\n )}\n {...props}\n >\n {children ?? <X aria-hidden className=\"size-4\" />}\n </button>\n )\n}\n\nexport const ChipInput = {\n Root,\n Label,\n Group,\n Chips,\n Chip,\n ChipRemove,\n Input,\n Clear,\n}\nexport { Root, Label, Group, Chips, Chip, ChipRemove, Input, Clear, useChipInput }\nexport type { RootProps as ChipInputRootProps }\n"],"mappings":"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"}
@@ -12,7 +12,7 @@ function f({ className: t, ...n }) {
12
12
  }
13
13
  function p({ className: t, ...n }) {
14
14
  return /* @__PURE__ */ i(a.InputGroup, {
15
- className: e("flex min-h-14 w-full flex-wrap items-center gap-1 py-1 pl-4 pr-2", "rounded-extra-small border border-outline bg-surface text-on-surface", "transition-colors", "focus-within:border-primary focus-within:outline-2 focus-within:-outline-offset-2 focus-within:outline-primary", "data-[disabled]:pointer-events-none data-[disabled]:opacity-[0.38]", t),
15
+ className: e("flex min-h-14 w-full flex-wrap items-center gap-1 py-1 pl-4 pr-2", "rounded-small border border-outline bg-surface text-on-surface", "transition-colors", "focus-within:border-primary focus-within:outline-2 focus-within:-outline-offset-2 focus-within:outline-primary", "data-[disabled]:pointer-events-none data-[disabled]:opacity-[0.38]", t),
16
16
  ...n
17
17
  });
18
18
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Combobox.js","names":[],"sources":["../../../src/components/combobox/Combobox.tsx"],"sourcesContent":["import { Combobox as BaseCombobox } from '@base-ui/react/combobox'\nimport { Check, ChevronDown, X } from 'lucide-react'\nimport { cn } from '#/lib/cn'\n\nimport type { ComponentProps } from 'react'\n\n/**\n * Combobox — Material 3 styled wrapper over Base UI's headless Combobox.\n * Behaviour/accessibility (filtering, listbox semantics, typeahead, chips for\n * multiple selection): Base UI (https://base-ui.com/react/components/combobox).\n * Visuals: M3 \"menu anchored to a text field\" anatomy — outlined text-field\n * container (56px, extra-small corner, outline → primary on focus), menu popup\n * on surface-container with small corner + level-2 elevation, 48px list items\n * with state layers, input chips for multi-select.\n * Design refs: port/core/ui/components/dropdown, port/core/ui/components/text-field\n * (see CLAUDE.md).\n *\n * Compound API mirrors Base UI:\n * <Combobox.Root items={items}>\n * <Combobox.Label>Fruit</Combobox.Label>\n * <Combobox.InputGroup>\n * <Combobox.Input placeholder=\"Search…\" />\n * <Combobox.Clear />\n * <Combobox.Trigger />\n * </Combobox.InputGroup>\n * <Combobox.Portal>\n * <Combobox.Positioner>\n * <Combobox.Popup>\n * <Combobox.Empty>No results.</Combobox.Empty>\n * <Combobox.List>\n * {(item) => (\n * <Combobox.Item key={item} value={item}>\n * {item}\n * <Combobox.ItemIndicator />\n * </Combobox.Item>\n * )}\n * </Combobox.List>\n * </Combobox.Popup>\n * </Combobox.Positioner>\n * </Combobox.Portal>\n * </Combobox.Root>\n */\n\n// These parts render no HTML element of their own (Root/Portal/Value/Collection),\n// so there is nothing to style — re-export them directly (preserves Root's generics).\nconst Root = BaseCombobox.Root\nconst Portal = BaseCombobox.Portal\nconst Value = BaseCombobox.Value\nconst Collection = BaseCombobox.Collection\n\n// Filtering hooks, re-exported for convenience.\nconst useFilter = BaseCombobox.useFilter\nconst useFilteredItems = BaseCombobox.useFilteredItems\n\nfunction Label({ className, ...props }: ComponentProps<typeof BaseCombobox.Label>) {\n return (\n <BaseCombobox.Label\n className={cn('mb-1.5 block text-label-large text-on-surface', className)}\n {...props}\n />\n )\n}\n\n/**\n * The M3 outlined text-field container: draws the 56px outlined box around the\n * input and its trailing controls; turns primary on focus-within.\n */\nfunction InputGroup({ className, ...props }: ComponentProps<typeof BaseCombobox.InputGroup>) {\n return (\n <BaseCombobox.InputGroup\n className={cn(\n 'flex min-h-14 w-full flex-wrap items-center gap-1 py-1 pl-4 pr-2',\n 'rounded-extra-small border border-outline bg-surface text-on-surface',\n 'transition-colors',\n 'focus-within:border-primary focus-within:outline-2 focus-within:-outline-offset-2 focus-within:outline-primary',\n 'data-[disabled]:pointer-events-none data-[disabled]:opacity-[0.38]',\n className,\n )}\n {...props}\n />\n )\n}\n\n/** Borderless by design — the surrounding InputGroup draws the M3 field box. */\nfunction Input({ className, ...props }: ComponentProps<typeof BaseCombobox.Input>) {\n return (\n <BaseCombobox.Input\n className={cn(\n 'h-12 min-w-12 flex-1 bg-transparent text-body-large text-on-surface',\n 'outline-none placeholder:text-on-surface-variant',\n 'disabled:cursor-not-allowed',\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction Trigger({ className, children, ...props }: ComponentProps<typeof BaseCombobox.Trigger>) {\n return (\n <BaseCombobox.Trigger\n className={cn(\n 'group flex size-8 shrink-0 cursor-pointer items-center justify-center rounded-full',\n 'text-on-surface-variant transition-colors hover:bg-on-surface/[0.08]',\n 'focus-visible:outline-2 focus-visible:outline-primary',\n 'disabled:cursor-not-allowed disabled:opacity-[0.38]',\n className,\n )}\n {...props}\n >\n {children ?? (\n <Icon>\n <ChevronDown aria-hidden className=\"size-5\" />\n </Icon>\n )}\n </BaseCombobox.Trigger>\n )\n}\n\n/** Chevron wrapper; flips while the popup is open (parent Trigger is `group`). */\nfunction Icon({ className, ...props }: ComponentProps<typeof BaseCombobox.Icon>) {\n return (\n <BaseCombobox.Icon\n className={cn(\n 'flex transition-transform duration-200 ease-out group-data-[popup-open]:rotate-180',\n className,\n )}\n {...props}\n />\n )\n}\n\n/** Clears the value; only mounted while there is something to clear. */\nfunction Clear({ className, children, ...props }: ComponentProps<typeof BaseCombobox.Clear>) {\n return (\n <BaseCombobox.Clear\n className={cn(\n 'flex size-8 shrink-0 cursor-pointer items-center justify-center rounded-full',\n 'text-on-surface-variant transition-opacity hover:bg-on-surface/[0.08]',\n 'focus-visible:outline-2 focus-visible:outline-primary',\n 'data-[ending-style]:opacity-0 data-[starting-style]:opacity-0',\n 'disabled:cursor-not-allowed disabled:opacity-[0.38]',\n className,\n )}\n {...props}\n >\n {children ?? <X aria-hidden className=\"size-4\" />}\n </BaseCombobox.Clear>\n )\n}\n\nfunction Backdrop({ className, ...props }: ComponentProps<typeof BaseCombobox.Backdrop>) {\n return <BaseCombobox.Backdrop className={cn('fixed inset-0 z-40', className)} {...props} />\n}\n\nfunction Positioner({ className, ...props }: ComponentProps<typeof BaseCombobox.Positioner>) {\n return (\n <BaseCombobox.Positioner\n sideOffset={4}\n className={cn('z-50 outline-none', className)}\n {...props}\n />\n )\n}\n\n/** M3 menu container: surface-container, small corner, level-2 elevation. */\nfunction Popup({ className, ...props }: ComponentProps<typeof BaseCombobox.Popup>) {\n return (\n <BaseCombobox.Popup\n className={cn(\n 'max-h-[min(24rem,var(--available-height))] w-(--anchor-width) overflow-y-auto overscroll-contain',\n 'rounded-small bg-surface-container py-2 text-on-surface shadow-mm-2',\n 'origin-(--transform-origin) transition-[transform,opacity] duration-150 ease-out',\n 'outline-none data-[ending-style]:scale-95 data-[ending-style]:opacity-0',\n 'data-[starting-style]:scale-95 data-[starting-style]:opacity-0',\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction Arrow({ className, ...props }: ComponentProps<typeof BaseCombobox.Arrow>) {\n return <BaseCombobox.Arrow className={cn('flex', className)} {...props} />\n}\n\nfunction List({ className, ...props }: ComponentProps<typeof BaseCombobox.List>) {\n return <BaseCombobox.List className={cn('outline-none', className)} {...props} />\n}\n\n/** Polite screen-reader status region (e.g. async loading); stays mounted. */\nfunction Status({ className, ...props }: ComponentProps<typeof BaseCombobox.Status>) {\n return (\n <BaseCombobox.Status\n className={cn('px-4 py-2 text-body-small text-on-surface-variant empty:p-0', className)}\n {...props}\n />\n )\n}\n\n/** Shown only when the filtered list is empty; collapses otherwise. */\nfunction Empty({ className, ...props }: ComponentProps<typeof BaseCombobox.Empty>) {\n return (\n <BaseCombobox.Empty\n className={cn('px-4 py-3 text-body-medium text-on-surface-variant empty:p-0', className)}\n {...props}\n />\n )\n}\n\nfunction Group({ className, ...props }: ComponentProps<typeof BaseCombobox.Group>) {\n return <BaseCombobox.Group className={cn(className)} {...props} />\n}\n\n/** M3 list subheader. */\nfunction GroupLabel({ className, ...props }: ComponentProps<typeof BaseCombobox.GroupLabel>) {\n return (\n <BaseCombobox.GroupLabel\n className={cn('px-4 pb-1 pt-3 text-label-medium text-on-surface-variant', className)}\n {...props}\n />\n )\n}\n\n/** M3 menu item: 48px row, label-large, hover/highlight state layers. */\nfunction Item({ className, ...props }: ComponentProps<typeof BaseCombobox.Item>) {\n return (\n <BaseCombobox.Item\n className={cn(\n 'flex min-h-12 cursor-pointer select-none items-center gap-3 px-4',\n 'text-label-large text-on-surface outline-none transition-colors',\n 'data-[highlighted]:bg-on-surface/[0.08]',\n 'data-[disabled]:cursor-not-allowed data-[disabled]:opacity-[0.38]',\n className,\n )}\n {...props}\n />\n )\n}\n\n/** Trailing selected check (primary role); only mounted while selected. */\nfunction ItemIndicator({\n className,\n children,\n ...props\n}: ComponentProps<typeof BaseCombobox.ItemIndicator>) {\n return (\n <BaseCombobox.ItemIndicator\n className={cn('ml-auto flex shrink-0 items-center text-primary', className)}\n {...props}\n >\n {children ?? <Check aria-hidden className=\"size-5\" />}\n </BaseCombobox.ItemIndicator>\n )\n}\n\n/** Wraps selected-value chips and the inline input in multiple mode. */\nfunction Chips({ className, ...props }: ComponentProps<typeof BaseCombobox.Chips>) {\n return (\n <BaseCombobox.Chips\n className={cn('flex flex-1 flex-wrap items-center gap-1.5', className)}\n {...props}\n />\n )\n}\n\n/** M3 input chip: 32px, small corner, outlined. */\nfunction Chip({ className, ...props }: ComponentProps<typeof BaseCombobox.Chip>) {\n return (\n <BaseCombobox.Chip\n className={cn(\n 'flex h-8 cursor-default items-center gap-1 rounded-small border border-outline-variant',\n 'bg-surface-container-low pl-3 pr-1 text-label-large text-on-surface',\n 'data-[disabled]:cursor-not-allowed data-[disabled]:opacity-[0.38]',\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction ChipRemove({\n className,\n children,\n ...props\n}: ComponentProps<typeof BaseCombobox.ChipRemove>) {\n return (\n <BaseCombobox.ChipRemove\n className={cn(\n 'flex size-6 cursor-pointer items-center justify-center rounded-full',\n 'text-on-surface-variant transition-colors hover:bg-on-surface/[0.08]',\n 'focus-visible:outline-2 focus-visible:outline-primary',\n className,\n )}\n {...props}\n >\n {children ?? <X aria-hidden className=\"size-4\" />}\n </BaseCombobox.ChipRemove>\n )\n}\n\n/** Single row of items when the listbox is in grid mode. */\nfunction Row({ className, ...props }: ComponentProps<typeof BaseCombobox.Row>) {\n return <BaseCombobox.Row className={cn('flex', className)} {...props} />\n}\n\nfunction Separator({ className, ...props }: ComponentProps<typeof BaseCombobox.Separator>) {\n return (\n <BaseCombobox.Separator\n className={cn('mx-4 my-2 h-px bg-outline-variant', className)}\n {...props}\n />\n )\n}\n\nexport const Combobox = {\n Root,\n Label,\n Value,\n Input,\n InputGroup,\n Trigger,\n List,\n Status,\n Portal,\n Backdrop,\n Positioner,\n Popup,\n Arrow,\n Icon,\n Group,\n GroupLabel,\n Item,\n ItemIndicator,\n Chips,\n Chip,\n ChipRemove,\n Row,\n Collection,\n Empty,\n Clear,\n Separator,\n useFilter,\n useFilteredItems,\n}\nexport {\n Root,\n Label,\n Value,\n Input,\n InputGroup,\n Trigger,\n List,\n Status,\n Portal,\n Backdrop,\n Positioner,\n Popup,\n Arrow,\n Icon,\n Group,\n GroupLabel,\n Item,\n ItemIndicator,\n Chips,\n Chip,\n ChipRemove,\n Row,\n Collection,\n Empty,\n Clear,\n Separator,\n useFilter,\n useFilteredItems,\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"Combobox.js","names":[],"sources":["../../../src/components/combobox/Combobox.tsx"],"sourcesContent":["import { Combobox as BaseCombobox } from '@base-ui/react/combobox'\nimport { Check, ChevronDown, X } from 'lucide-react'\nimport { cn } from '#/lib/cn'\n\nimport type { ComponentProps } from 'react'\n\n/**\n * Combobox — Material 3 styled wrapper over Base UI's headless Combobox.\n * Behaviour/accessibility (filtering, listbox semantics, typeahead, chips for\n * multiple selection): Base UI (https://base-ui.com/react/components/combobox).\n * Visuals: M3 \"menu anchored to a text field\" anatomy — outlined text-field\n * container (56px, extra-small corner, outline → primary on focus), menu popup\n * on surface-container with small corner + level-2 elevation, 48px list items\n * with state layers, input chips for multi-select.\n * Design refs: port/core/ui/components/dropdown, port/core/ui/components/text-field\n * (see CLAUDE.md).\n *\n * Compound API mirrors Base UI:\n * <Combobox.Root items={items}>\n * <Combobox.Label>Fruit</Combobox.Label>\n * <Combobox.InputGroup>\n * <Combobox.Input placeholder=\"Search…\" />\n * <Combobox.Clear />\n * <Combobox.Trigger />\n * </Combobox.InputGroup>\n * <Combobox.Portal>\n * <Combobox.Positioner>\n * <Combobox.Popup>\n * <Combobox.Empty>No results.</Combobox.Empty>\n * <Combobox.List>\n * {(item) => (\n * <Combobox.Item key={item} value={item}>\n * {item}\n * <Combobox.ItemIndicator />\n * </Combobox.Item>\n * )}\n * </Combobox.List>\n * </Combobox.Popup>\n * </Combobox.Positioner>\n * </Combobox.Portal>\n * </Combobox.Root>\n */\n\n// These parts render no HTML element of their own (Root/Portal/Value/Collection),\n// so there is nothing to style — re-export them directly (preserves Root's generics).\nconst Root = BaseCombobox.Root\nconst Portal = BaseCombobox.Portal\nconst Value = BaseCombobox.Value\nconst Collection = BaseCombobox.Collection\n\n// Filtering hooks, re-exported for convenience.\nconst useFilter = BaseCombobox.useFilter\nconst useFilteredItems = BaseCombobox.useFilteredItems\n\nfunction Label({ className, ...props }: ComponentProps<typeof BaseCombobox.Label>) {\n return (\n <BaseCombobox.Label\n className={cn('mb-1.5 block text-label-large text-on-surface', className)}\n {...props}\n />\n )\n}\n\n/**\n * The M3 outlined text-field container: draws the 56px outlined box around the\n * input and its trailing controls; turns primary on focus-within.\n */\nfunction InputGroup({ className, ...props }: ComponentProps<typeof BaseCombobox.InputGroup>) {\n return (\n <BaseCombobox.InputGroup\n className={cn(\n 'flex min-h-14 w-full flex-wrap items-center gap-1 py-1 pl-4 pr-2',\n 'rounded-small border border-outline bg-surface text-on-surface',\n 'transition-colors',\n 'focus-within:border-primary focus-within:outline-2 focus-within:-outline-offset-2 focus-within:outline-primary',\n 'data-[disabled]:pointer-events-none data-[disabled]:opacity-[0.38]',\n className,\n )}\n {...props}\n />\n )\n}\n\n/** Borderless by design — the surrounding InputGroup draws the M3 field box. */\nfunction Input({ className, ...props }: ComponentProps<typeof BaseCombobox.Input>) {\n return (\n <BaseCombobox.Input\n className={cn(\n 'h-12 min-w-12 flex-1 bg-transparent text-body-large text-on-surface',\n 'outline-none placeholder:text-on-surface-variant',\n 'disabled:cursor-not-allowed',\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction Trigger({ className, children, ...props }: ComponentProps<typeof BaseCombobox.Trigger>) {\n return (\n <BaseCombobox.Trigger\n className={cn(\n 'group flex size-8 shrink-0 cursor-pointer items-center justify-center rounded-full',\n 'text-on-surface-variant transition-colors hover:bg-on-surface/[0.08]',\n 'focus-visible:outline-2 focus-visible:outline-primary',\n 'disabled:cursor-not-allowed disabled:opacity-[0.38]',\n className,\n )}\n {...props}\n >\n {children ?? (\n <Icon>\n <ChevronDown aria-hidden className=\"size-5\" />\n </Icon>\n )}\n </BaseCombobox.Trigger>\n )\n}\n\n/** Chevron wrapper; flips while the popup is open (parent Trigger is `group`). */\nfunction Icon({ className, ...props }: ComponentProps<typeof BaseCombobox.Icon>) {\n return (\n <BaseCombobox.Icon\n className={cn(\n 'flex transition-transform duration-200 ease-out group-data-[popup-open]:rotate-180',\n className,\n )}\n {...props}\n />\n )\n}\n\n/** Clears the value; only mounted while there is something to clear. */\nfunction Clear({ className, children, ...props }: ComponentProps<typeof BaseCombobox.Clear>) {\n return (\n <BaseCombobox.Clear\n className={cn(\n 'flex size-8 shrink-0 cursor-pointer items-center justify-center rounded-full',\n 'text-on-surface-variant transition-opacity hover:bg-on-surface/[0.08]',\n 'focus-visible:outline-2 focus-visible:outline-primary',\n 'data-[ending-style]:opacity-0 data-[starting-style]:opacity-0',\n 'disabled:cursor-not-allowed disabled:opacity-[0.38]',\n className,\n )}\n {...props}\n >\n {children ?? <X aria-hidden className=\"size-4\" />}\n </BaseCombobox.Clear>\n )\n}\n\nfunction Backdrop({ className, ...props }: ComponentProps<typeof BaseCombobox.Backdrop>) {\n return <BaseCombobox.Backdrop className={cn('fixed inset-0 z-40', className)} {...props} />\n}\n\nfunction Positioner({ className, ...props }: ComponentProps<typeof BaseCombobox.Positioner>) {\n return (\n <BaseCombobox.Positioner\n sideOffset={4}\n className={cn('z-50 outline-none', className)}\n {...props}\n />\n )\n}\n\n/** M3 menu container: surface-container, small corner, level-2 elevation. */\nfunction Popup({ className, ...props }: ComponentProps<typeof BaseCombobox.Popup>) {\n return (\n <BaseCombobox.Popup\n className={cn(\n 'max-h-[min(24rem,var(--available-height))] w-(--anchor-width) overflow-y-auto overscroll-contain',\n 'rounded-small bg-surface-container py-2 text-on-surface shadow-mm-2',\n 'origin-(--transform-origin) transition-[transform,opacity] duration-150 ease-out',\n 'outline-none data-[ending-style]:scale-95 data-[ending-style]:opacity-0',\n 'data-[starting-style]:scale-95 data-[starting-style]:opacity-0',\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction Arrow({ className, ...props }: ComponentProps<typeof BaseCombobox.Arrow>) {\n return <BaseCombobox.Arrow className={cn('flex', className)} {...props} />\n}\n\nfunction List({ className, ...props }: ComponentProps<typeof BaseCombobox.List>) {\n return <BaseCombobox.List className={cn('outline-none', className)} {...props} />\n}\n\n/** Polite screen-reader status region (e.g. async loading); stays mounted. */\nfunction Status({ className, ...props }: ComponentProps<typeof BaseCombobox.Status>) {\n return (\n <BaseCombobox.Status\n className={cn('px-4 py-2 text-body-small text-on-surface-variant empty:p-0', className)}\n {...props}\n />\n )\n}\n\n/** Shown only when the filtered list is empty; collapses otherwise. */\nfunction Empty({ className, ...props }: ComponentProps<typeof BaseCombobox.Empty>) {\n return (\n <BaseCombobox.Empty\n className={cn('px-4 py-3 text-body-medium text-on-surface-variant empty:p-0', className)}\n {...props}\n />\n )\n}\n\nfunction Group({ className, ...props }: ComponentProps<typeof BaseCombobox.Group>) {\n return <BaseCombobox.Group className={cn(className)} {...props} />\n}\n\n/** M3 list subheader. */\nfunction GroupLabel({ className, ...props }: ComponentProps<typeof BaseCombobox.GroupLabel>) {\n return (\n <BaseCombobox.GroupLabel\n className={cn('px-4 pb-1 pt-3 text-label-medium text-on-surface-variant', className)}\n {...props}\n />\n )\n}\n\n/** M3 menu item: 48px row, label-large, hover/highlight state layers. */\nfunction Item({ className, ...props }: ComponentProps<typeof BaseCombobox.Item>) {\n return (\n <BaseCombobox.Item\n className={cn(\n 'flex min-h-12 cursor-pointer select-none items-center gap-3 px-4',\n 'text-label-large text-on-surface outline-none transition-colors',\n 'data-[highlighted]:bg-on-surface/[0.08]',\n 'data-[disabled]:cursor-not-allowed data-[disabled]:opacity-[0.38]',\n className,\n )}\n {...props}\n />\n )\n}\n\n/** Trailing selected check (primary role); only mounted while selected. */\nfunction ItemIndicator({\n className,\n children,\n ...props\n}: ComponentProps<typeof BaseCombobox.ItemIndicator>) {\n return (\n <BaseCombobox.ItemIndicator\n className={cn('ml-auto flex shrink-0 items-center text-primary', className)}\n {...props}\n >\n {children ?? <Check aria-hidden className=\"size-5\" />}\n </BaseCombobox.ItemIndicator>\n )\n}\n\n/** Wraps selected-value chips and the inline input in multiple mode. */\nfunction Chips({ className, ...props }: ComponentProps<typeof BaseCombobox.Chips>) {\n return (\n <BaseCombobox.Chips\n className={cn('flex flex-1 flex-wrap items-center gap-1.5', className)}\n {...props}\n />\n )\n}\n\n/** M3 input chip: 32px, small corner, outlined. */\nfunction Chip({ className, ...props }: ComponentProps<typeof BaseCombobox.Chip>) {\n return (\n <BaseCombobox.Chip\n className={cn(\n 'flex h-8 cursor-default items-center gap-1 rounded-small border border-outline-variant',\n 'bg-surface-container-low pl-3 pr-1 text-label-large text-on-surface',\n 'data-[disabled]:cursor-not-allowed data-[disabled]:opacity-[0.38]',\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction ChipRemove({\n className,\n children,\n ...props\n}: ComponentProps<typeof BaseCombobox.ChipRemove>) {\n return (\n <BaseCombobox.ChipRemove\n className={cn(\n 'flex size-6 cursor-pointer items-center justify-center rounded-full',\n 'text-on-surface-variant transition-colors hover:bg-on-surface/[0.08]',\n 'focus-visible:outline-2 focus-visible:outline-primary',\n className,\n )}\n {...props}\n >\n {children ?? <X aria-hidden className=\"size-4\" />}\n </BaseCombobox.ChipRemove>\n )\n}\n\n/** Single row of items when the listbox is in grid mode. */\nfunction Row({ className, ...props }: ComponentProps<typeof BaseCombobox.Row>) {\n return <BaseCombobox.Row className={cn('flex', className)} {...props} />\n}\n\nfunction Separator({ className, ...props }: ComponentProps<typeof BaseCombobox.Separator>) {\n return (\n <BaseCombobox.Separator\n className={cn('mx-4 my-2 h-px bg-outline-variant', className)}\n {...props}\n />\n )\n}\n\nexport const Combobox = {\n Root,\n Label,\n Value,\n Input,\n InputGroup,\n Trigger,\n List,\n Status,\n Portal,\n Backdrop,\n Positioner,\n Popup,\n Arrow,\n Icon,\n Group,\n GroupLabel,\n Item,\n ItemIndicator,\n Chips,\n Chip,\n ChipRemove,\n Row,\n Collection,\n Empty,\n Clear,\n Separator,\n useFilter,\n useFilteredItems,\n}\nexport {\n Root,\n Label,\n Value,\n Input,\n InputGroup,\n Trigger,\n List,\n Status,\n Portal,\n Backdrop,\n Positioner,\n Popup,\n Arrow,\n Icon,\n Group,\n GroupLabel,\n Item,\n ItemIndicator,\n Chips,\n Chip,\n ChipRemove,\n Row,\n Collection,\n Empty,\n Clear,\n Separator,\n useFilter,\n useFilteredItems,\n}\n"],"mappings":";;;;;AA6CA,IAAM,IAAO,EAAa,MACpB,IAAS,EAAa,QACtB,IAAQ,EAAa,OACrB,IAAa,EAAa,YAG1B,IAAY,EAAa,WACzB,IAAmB,EAAa;AAEtC,SAAS,EAAM,EAAE,cAAW,GAAG,KAAoD;CACjF,OACE,kBAAC,EAAa,OAAd;EACE,WAAW,EAAG,iDAAiD,CAAS;EACxE,GAAI;CACL,CAAA;AAEL;AAMA,SAAS,EAAW,EAAE,cAAW,GAAG,KAAyD;CAC3F,OACE,kBAAC,EAAa,YAAd;EACE,WAAW,EACT,oEACA,kEACA,qBACA,kHACA,sEACA,CACF;EACA,GAAI;CACL,CAAA;AAEL;AAGA,SAAS,EAAM,EAAE,cAAW,GAAG,KAAoD;CACjF,OACE,kBAAC,EAAa,OAAd;EACE,WAAW,EACT,uEACA,oDACA,+BACA,CACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,EAAQ,EAAE,cAAW,aAAU,GAAG,KAAsD;CAC/F,OACE,kBAAC,EAAa,SAAd;EACE,WAAW,EACT,sFACA,wEACA,yDACA,uDACA,CACF;EACA,GAAI;YAEH,KACC,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;GAAa,eAAA;GAAY,WAAU;EAAU,CAAA,EACzC,CAAA;CAEY,CAAA;AAE1B;AAGA,SAAS,EAAK,EAAE,cAAW,GAAG,KAAmD;CAC/E,OACE,kBAAC,EAAa,MAAd;EACE,WAAW,EACT,sFACA,CACF;EACA,GAAI;CACL,CAAA;AAEL;AAGA,SAAS,EAAM,EAAE,cAAW,aAAU,GAAG,KAAoD;CAC3F,OACE,kBAAC,EAAa,OAAd;EACE,WAAW,EACT,gFACA,yEACA,yDACA,iEACA,uDACA,CACF;EACA,GAAI;YAEH,KAAY,kBAAC,GAAD;GAAG,eAAA;GAAY,WAAU;EAAU,CAAA;CAC9B,CAAA;AAExB;AAEA,SAAS,EAAS,EAAE,cAAW,GAAG,KAAuD;CACvF,OAAO,kBAAC,EAAa,UAAd;EAAuB,WAAW,EAAG,sBAAsB,CAAS;EAAG,GAAI;CAAQ,CAAA;AAC5F;AAEA,SAAS,EAAW,EAAE,cAAW,GAAG,KAAyD;CAC3F,OACE,kBAAC,EAAa,YAAd;EACE,YAAY;EACZ,WAAW,EAAG,qBAAqB,CAAS;EAC5C,GAAI;CACL,CAAA;AAEL;AAGA,SAAS,EAAM,EAAE,cAAW,GAAG,KAAoD;CACjF,OACE,kBAAC,EAAa,OAAd;EACE,WAAW,EACT,oGACA,uEACA,oFACA,2EACA,kEACA,CACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,EAAM,EAAE,cAAW,GAAG,KAAoD;CACjF,OAAO,kBAAC,EAAa,OAAd;EAAoB,WAAW,EAAG,QAAQ,CAAS;EAAG,GAAI;CAAQ,CAAA;AAC3E;AAEA,SAAS,EAAK,EAAE,cAAW,GAAG,KAAmD;CAC/E,OAAO,kBAAC,EAAa,MAAd;EAAmB,WAAW,EAAG,gBAAgB,CAAS;EAAG,GAAI;CAAQ,CAAA;AAClF;AAGA,SAAS,EAAO,EAAE,cAAW,GAAG,KAAqD;CACnF,OACE,kBAAC,EAAa,QAAd;EACE,WAAW,EAAG,+DAA+D,CAAS;EACtF,GAAI;CACL,CAAA;AAEL;AAGA,SAAS,EAAM,EAAE,cAAW,GAAG,KAAoD;CACjF,OACE,kBAAC,EAAa,OAAd;EACE,WAAW,EAAG,gEAAgE,CAAS;EACvF,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,EAAM,EAAE,cAAW,GAAG,KAAoD;CACjF,OAAO,kBAAC,EAAa,OAAd;EAAoB,WAAW,EAAG,CAAS;EAAG,GAAI;CAAQ,CAAA;AACnE;AAGA,SAAS,EAAW,EAAE,cAAW,GAAG,KAAyD;CAC3F,OACE,kBAAC,EAAa,YAAd;EACE,WAAW,EAAG,4DAA4D,CAAS;EACnF,GAAI;CACL,CAAA;AAEL;AAGA,SAAS,EAAK,EAAE,cAAW,GAAG,KAAmD;CAC/E,OACE,kBAAC,EAAa,MAAd;EACE,WAAW,EACT,oEACA,mEACA,2CACA,qEACA,CACF;EACA,GAAI;CACL,CAAA;AAEL;AAGA,SAAS,EAAc,EACrB,cACA,aACA,GAAG,KACiD;CACpD,OACE,kBAAC,EAAa,eAAd;EACE,WAAW,EAAG,mDAAmD,CAAS;EAC1E,GAAI;YAEH,KAAY,kBAAC,GAAD;GAAO,eAAA;GAAY,WAAU;EAAU,CAAA;CAC1B,CAAA;AAEhC;AAGA,SAAS,EAAM,EAAE,cAAW,GAAG,KAAoD;CACjF,OACE,kBAAC,EAAa,OAAd;EACE,WAAW,EAAG,8CAA8C,CAAS;EACrE,GAAI;CACL,CAAA;AAEL;AAGA,SAAS,EAAK,EAAE,cAAW,GAAG,KAAmD;CAC/E,OACE,kBAAC,EAAa,MAAd;EACE,WAAW,EACT,0FACA,uEACA,qEACA,CACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,EAAW,EAClB,cACA,aACA,GAAG,KAC8C;CACjD,OACE,kBAAC,EAAa,YAAd;EACE,WAAW,EACT,uEACA,wEACA,yDACA,CACF;EACA,GAAI;YAEH,KAAY,kBAAC,GAAD;GAAG,eAAA;GAAY,WAAU;EAAU,CAAA;CACzB,CAAA;AAE7B;AAGA,SAAS,EAAI,EAAE,cAAW,GAAG,KAAkD;CAC7E,OAAO,kBAAC,EAAa,KAAd;EAAkB,WAAW,EAAG,QAAQ,CAAS;EAAG,GAAI;CAAQ,CAAA;AACzE;AAEA,SAAS,EAAU,EAAE,cAAW,GAAG,KAAwD;CACzF,OACE,kBAAC,EAAa,WAAd;EACE,WAAW,EAAG,qCAAqC,CAAS;EAC5D,GAAI;CACL,CAAA;AAEL;AAEA,IAAa,IAAW;CACtB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF"}
@@ -11,7 +11,7 @@ function o({ className: t, ...n }) {
11
11
  }
12
12
  function s({ className: t, ...n }) {
13
13
  return /* @__PURE__ */ i(a.Group, {
14
- className: e("flex h-14 items-stretch overflow-hidden rounded-extra-small border border-outline bg-surface", "transition-colors hover:border-on-surface", "focus-within:border-primary focus-within:ring-1 focus-within:ring-primary focus-within:hover:border-primary", "data-[disabled]:pointer-events-none data-[disabled]:opacity-[0.38]", t),
14
+ className: e("flex h-14 items-stretch overflow-hidden rounded-small border border-outline bg-surface", "transition-colors hover:border-on-surface", "focus-within:border-primary focus-within:ring-1 focus-within:ring-primary focus-within:hover:border-primary", "data-[disabled]:pointer-events-none data-[disabled]:opacity-[0.38]", t),
15
15
  ...n
16
16
  });
17
17
  }
@@ -1 +1 @@
1
- {"version":3,"file":"NumberField.js","names":[],"sources":["../../../src/components/number-field/NumberField.tsx"],"sourcesContent":["import { NumberField as BaseNumberField } from '@base-ui/react/number-field'\nimport { Minus, MoveHorizontal, Plus } from 'lucide-react'\nimport { cn } from '#/lib/cn'\n\nimport type { ComponentProps } from 'react'\n\n/**\n * NumberField — Material 3 styled wrapper over Base UI's headless Number Field.\n * Behaviour/accessibility (spinbutton semantics, locale-aware parsing/formatting,\n * pointer scrubbing, wheel + keyboard stepping): Base UI\n * (https://base-ui.com/react/components/number-field).\n * Visuals: M3 outlined text field anatomy — 56px field box, extra-small corner,\n * outline border (primary on focus), body-large input text, on-surface-variant\n * stepper icons with state layers.\n * Design ref: port/core/ui/components/text-field (see CLAUDE.md).\n *\n * Compound API mirrors Base UI:\n * <NumberField.Root defaultValue={100}>\n * <NumberField.ScrubArea>\n * <label>Amount</label>\n * <NumberField.ScrubAreaCursor />\n * </NumberField.ScrubArea>\n * <NumberField.Group>\n * <NumberField.Decrement />\n * <NumberField.Input />\n * <NumberField.Increment />\n * </NumberField.Group>\n * </NumberField.Root>\n */\n\nfunction Root({ className, ...props }: ComponentProps<typeof BaseNumberField.Root>) {\n return (\n <BaseNumberField.Root\n className={cn('flex flex-col items-start gap-1 text-on-surface', className)}\n {...props}\n />\n )\n}\n\n/**\n * The visual field box (M3 outlined text field container): outline border,\n * extra-small corner, primary border + ring while the input inside has focus.\n */\nfunction Group({ className, ...props }: ComponentProps<typeof BaseNumberField.Group>) {\n return (\n <BaseNumberField.Group\n className={cn(\n 'flex h-14 items-stretch overflow-hidden rounded-extra-small border border-outline bg-surface',\n 'transition-colors hover:border-on-surface',\n 'focus-within:border-primary focus-within:ring-1 focus-within:ring-primary focus-within:hover:border-primary',\n 'data-[disabled]:pointer-events-none data-[disabled]:opacity-[0.38]',\n className,\n )}\n {...props}\n />\n )\n}\n\n/** Stepper button that decreases the value; renders a minus icon by default. */\nfunction Decrement({\n className,\n children,\n ...props\n}: ComponentProps<typeof BaseNumberField.Decrement>) {\n return (\n <BaseNumberField.Decrement\n className={cn(\n 'flex w-12 shrink-0 cursor-pointer items-center justify-center',\n 'border-r border-outline-variant text-on-surface-variant transition-colors',\n 'hover:bg-on-surface/[0.08] active:bg-on-surface/[0.12]',\n 'focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary',\n 'disabled:cursor-not-allowed disabled:opacity-[0.38] disabled:hover:bg-transparent',\n className,\n )}\n {...props}\n >\n {children ?? <Minus aria-hidden className=\"size-5\" />}\n </BaseNumberField.Decrement>\n )\n}\n\n/** Stepper button that increases the value; renders a plus icon by default. */\nfunction Increment({\n className,\n children,\n ...props\n}: ComponentProps<typeof BaseNumberField.Increment>) {\n return (\n <BaseNumberField.Increment\n className={cn(\n 'flex w-12 shrink-0 cursor-pointer items-center justify-center',\n 'border-l border-outline-variant text-on-surface-variant transition-colors',\n 'hover:bg-on-surface/[0.08] active:bg-on-surface/[0.12]',\n 'focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary',\n 'disabled:cursor-not-allowed disabled:opacity-[0.38] disabled:hover:bg-transparent',\n className,\n )}\n {...props}\n >\n {children ?? <Plus aria-hidden className=\"size-5\" />}\n </BaseNumberField.Increment>\n )\n}\n\nfunction Input({ className, ...props }: ComponentProps<typeof BaseNumberField.Input>) {\n return (\n <BaseNumberField.Input\n className={cn(\n 'h-full w-full min-w-0 bg-transparent px-3 text-center text-body-large tabular-nums',\n 'text-on-surface placeholder:text-on-surface-variant focus:outline-none',\n className,\n )}\n {...props}\n />\n )\n}\n\n/**\n * Click-and-drag area (usually wrapping the label) that scrubs the value\n * horizontally, like a video-editing slider.\n */\nfunction ScrubArea({ className, ...props }: ComponentProps<typeof BaseNumberField.ScrubArea>) {\n return (\n <BaseNumberField.ScrubArea\n className={cn(\n 'cursor-ew-resize select-none text-label-medium text-on-surface-variant',\n className,\n )}\n {...props}\n />\n )\n}\n\n/** Virtual cursor shown while scrubbing; renders a horizontal-move icon by default. */\nfunction ScrubAreaCursor({\n className,\n children,\n ...props\n}: ComponentProps<typeof BaseNumberField.ScrubAreaCursor>) {\n return (\n <BaseNumberField.ScrubAreaCursor\n className={cn('text-on-surface drop-shadow-sm', className)}\n {...props}\n >\n {children ?? <MoveHorizontal aria-hidden className=\"size-5\" />}\n </BaseNumberField.ScrubAreaCursor>\n )\n}\n\nexport const NumberField = {\n Root,\n Group,\n Decrement,\n Input,\n Increment,\n ScrubArea,\n ScrubAreaCursor,\n}\nexport { Root, Group, Decrement, Input, Increment, ScrubArea, ScrubAreaCursor }\n"],"mappings":";;;;;AA8BA,SAAS,EAAK,EAAE,cAAW,GAAG,KAAsD;CAClF,OACE,kBAAC,EAAgB,MAAjB;EACE,WAAW,EAAG,mDAAmD,CAAS;EAC1E,GAAI;CACL,CAAA;AAEL;AAMA,SAAS,EAAM,EAAE,cAAW,GAAG,KAAuD;CACpF,OACE,kBAAC,EAAgB,OAAjB;EACE,WAAW,EACT,gGACA,6CACA,+GACA,sEACA,CACF;EACA,GAAI;CACL,CAAA;AAEL;AAGA,SAAS,EAAU,EACjB,cACA,aACA,GAAG,KACgD;CACnD,OACE,kBAAC,EAAgB,WAAjB;EACE,WAAW,EACT,iEACA,6EACA,0DACA,yFACA,qFACA,CACF;EACA,GAAI;YAEH,KAAY,kBAAC,GAAD;GAAO,eAAA;GAAY,WAAU;EAAU,CAAA;CAC3B,CAAA;AAE/B;AAGA,SAAS,EAAU,EACjB,cACA,aACA,GAAG,KACgD;CACnD,OACE,kBAAC,EAAgB,WAAjB;EACE,WAAW,EACT,iEACA,6EACA,0DACA,yFACA,qFACA,CACF;EACA,GAAI;YAEH,KAAY,kBAAC,GAAD;GAAM,eAAA;GAAY,WAAU;EAAU,CAAA;CAC1B,CAAA;AAE/B;AAEA,SAAS,EAAM,EAAE,cAAW,GAAG,KAAuD;CACpF,OACE,kBAAC,EAAgB,OAAjB;EACE,WAAW,EACT,sFACA,0EACA,CACF;EACA,GAAI;CACL,CAAA;AAEL;AAMA,SAAS,EAAU,EAAE,cAAW,GAAG,KAA2D;CAC5F,OACE,kBAAC,EAAgB,WAAjB;EACE,WAAW,EACT,0EACA,CACF;EACA,GAAI;CACL,CAAA;AAEL;AAGA,SAAS,EAAgB,EACvB,cACA,aACA,GAAG,KACsD;CACzD,OACE,kBAAC,EAAgB,iBAAjB;EACE,WAAW,EAAG,kCAAkC,CAAS;EACzD,GAAI;YAEH,KAAY,kBAAC,GAAD;GAAgB,eAAA;GAAY,WAAU;EAAU,CAAA;CAC9B,CAAA;AAErC;AAEA,IAAa,IAAc;CACzB;CACA;CACA;CACA;CACA;CACA;CACA;AACF"}
1
+ {"version":3,"file":"NumberField.js","names":[],"sources":["../../../src/components/number-field/NumberField.tsx"],"sourcesContent":["import { NumberField as BaseNumberField } from '@base-ui/react/number-field'\nimport { Minus, MoveHorizontal, Plus } from 'lucide-react'\nimport { cn } from '#/lib/cn'\n\nimport type { ComponentProps } from 'react'\n\n/**\n * NumberField — Material 3 styled wrapper over Base UI's headless Number Field.\n * Behaviour/accessibility (spinbutton semantics, locale-aware parsing/formatting,\n * pointer scrubbing, wheel + keyboard stepping): Base UI\n * (https://base-ui.com/react/components/number-field).\n * Visuals: M3 outlined text field anatomy — 56px field box, extra-small corner,\n * outline border (primary on focus), body-large input text, on-surface-variant\n * stepper icons with state layers.\n * Design ref: port/core/ui/components/text-field (see CLAUDE.md).\n *\n * Compound API mirrors Base UI:\n * <NumberField.Root defaultValue={100}>\n * <NumberField.ScrubArea>\n * <label>Amount</label>\n * <NumberField.ScrubAreaCursor />\n * </NumberField.ScrubArea>\n * <NumberField.Group>\n * <NumberField.Decrement />\n * <NumberField.Input />\n * <NumberField.Increment />\n * </NumberField.Group>\n * </NumberField.Root>\n */\n\nfunction Root({ className, ...props }: ComponentProps<typeof BaseNumberField.Root>) {\n return (\n <BaseNumberField.Root\n className={cn('flex flex-col items-start gap-1 text-on-surface', className)}\n {...props}\n />\n )\n}\n\n/**\n * The visual field box (M3 outlined text field container): outline border,\n * extra-small corner, primary border + ring while the input inside has focus.\n */\nfunction Group({ className, ...props }: ComponentProps<typeof BaseNumberField.Group>) {\n return (\n <BaseNumberField.Group\n className={cn(\n 'flex h-14 items-stretch overflow-hidden rounded-small border border-outline bg-surface',\n 'transition-colors hover:border-on-surface',\n 'focus-within:border-primary focus-within:ring-1 focus-within:ring-primary focus-within:hover:border-primary',\n 'data-[disabled]:pointer-events-none data-[disabled]:opacity-[0.38]',\n className,\n )}\n {...props}\n />\n )\n}\n\n/** Stepper button that decreases the value; renders a minus icon by default. */\nfunction Decrement({\n className,\n children,\n ...props\n}: ComponentProps<typeof BaseNumberField.Decrement>) {\n return (\n <BaseNumberField.Decrement\n className={cn(\n 'flex w-12 shrink-0 cursor-pointer items-center justify-center',\n 'border-r border-outline-variant text-on-surface-variant transition-colors',\n 'hover:bg-on-surface/[0.08] active:bg-on-surface/[0.12]',\n 'focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary',\n 'disabled:cursor-not-allowed disabled:opacity-[0.38] disabled:hover:bg-transparent',\n className,\n )}\n {...props}\n >\n {children ?? <Minus aria-hidden className=\"size-5\" />}\n </BaseNumberField.Decrement>\n )\n}\n\n/** Stepper button that increases the value; renders a plus icon by default. */\nfunction Increment({\n className,\n children,\n ...props\n}: ComponentProps<typeof BaseNumberField.Increment>) {\n return (\n <BaseNumberField.Increment\n className={cn(\n 'flex w-12 shrink-0 cursor-pointer items-center justify-center',\n 'border-l border-outline-variant text-on-surface-variant transition-colors',\n 'hover:bg-on-surface/[0.08] active:bg-on-surface/[0.12]',\n 'focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary',\n 'disabled:cursor-not-allowed disabled:opacity-[0.38] disabled:hover:bg-transparent',\n className,\n )}\n {...props}\n >\n {children ?? <Plus aria-hidden className=\"size-5\" />}\n </BaseNumberField.Increment>\n )\n}\n\nfunction Input({ className, ...props }: ComponentProps<typeof BaseNumberField.Input>) {\n return (\n <BaseNumberField.Input\n className={cn(\n 'h-full w-full min-w-0 bg-transparent px-3 text-center text-body-large tabular-nums',\n 'text-on-surface placeholder:text-on-surface-variant focus:outline-none',\n className,\n )}\n {...props}\n />\n )\n}\n\n/**\n * Click-and-drag area (usually wrapping the label) that scrubs the value\n * horizontally, like a video-editing slider.\n */\nfunction ScrubArea({ className, ...props }: ComponentProps<typeof BaseNumberField.ScrubArea>) {\n return (\n <BaseNumberField.ScrubArea\n className={cn(\n 'cursor-ew-resize select-none text-label-medium text-on-surface-variant',\n className,\n )}\n {...props}\n />\n )\n}\n\n/** Virtual cursor shown while scrubbing; renders a horizontal-move icon by default. */\nfunction ScrubAreaCursor({\n className,\n children,\n ...props\n}: ComponentProps<typeof BaseNumberField.ScrubAreaCursor>) {\n return (\n <BaseNumberField.ScrubAreaCursor\n className={cn('text-on-surface drop-shadow-sm', className)}\n {...props}\n >\n {children ?? <MoveHorizontal aria-hidden className=\"size-5\" />}\n </BaseNumberField.ScrubAreaCursor>\n )\n}\n\nexport const NumberField = {\n Root,\n Group,\n Decrement,\n Input,\n Increment,\n ScrubArea,\n ScrubAreaCursor,\n}\nexport { Root, Group, Decrement, Input, Increment, ScrubArea, ScrubAreaCursor }\n"],"mappings":";;;;;AA8BA,SAAS,EAAK,EAAE,cAAW,GAAG,KAAsD;CAClF,OACE,kBAAC,EAAgB,MAAjB;EACE,WAAW,EAAG,mDAAmD,CAAS;EAC1E,GAAI;CACL,CAAA;AAEL;AAMA,SAAS,EAAM,EAAE,cAAW,GAAG,KAAuD;CACpF,OACE,kBAAC,EAAgB,OAAjB;EACE,WAAW,EACT,0FACA,6CACA,+GACA,sEACA,CACF;EACA,GAAI;CACL,CAAA;AAEL;AAGA,SAAS,EAAU,EACjB,cACA,aACA,GAAG,KACgD;CACnD,OACE,kBAAC,EAAgB,WAAjB;EACE,WAAW,EACT,iEACA,6EACA,0DACA,yFACA,qFACA,CACF;EACA,GAAI;YAEH,KAAY,kBAAC,GAAD;GAAO,eAAA;GAAY,WAAU;EAAU,CAAA;CAC3B,CAAA;AAE/B;AAGA,SAAS,EAAU,EACjB,cACA,aACA,GAAG,KACgD;CACnD,OACE,kBAAC,EAAgB,WAAjB;EACE,WAAW,EACT,iEACA,6EACA,0DACA,yFACA,qFACA,CACF;EACA,GAAI;YAEH,KAAY,kBAAC,GAAD;GAAM,eAAA;GAAY,WAAU;EAAU,CAAA;CAC1B,CAAA;AAE/B;AAEA,SAAS,EAAM,EAAE,cAAW,GAAG,KAAuD;CACpF,OACE,kBAAC,EAAgB,OAAjB;EACE,WAAW,EACT,sFACA,0EACA,CACF;EACA,GAAI;CACL,CAAA;AAEL;AAMA,SAAS,EAAU,EAAE,cAAW,GAAG,KAA2D;CAC5F,OACE,kBAAC,EAAgB,WAAjB;EACE,WAAW,EACT,0EACA,CACF;EACA,GAAI;CACL,CAAA;AAEL;AAGA,SAAS,EAAgB,EACvB,cACA,aACA,GAAG,KACsD;CACzD,OACE,kBAAC,EAAgB,iBAAjB;EACE,WAAW,EAAG,kCAAkC,CAAS;EACzD,GAAI;YAEH,KAAY,kBAAC,GAAD;GAAgB,eAAA;GAAY,WAAU;EAAU,CAAA;CAC9B,CAAA;AAErC;AAEA,IAAa,IAAc;CACzB;CACA;CACA;CACA;CACA;CACA;CACA;AACF"}
@@ -10,7 +10,7 @@ function r({ className: r, ...i }) {
10
10
  }
11
11
  function i({ className: r, ...i }) {
12
12
  return /* @__PURE__ */ t(n.Input, {
13
- className: e("h-14 w-11 rounded-extra-small border border-outline bg-transparent", "text-center text-title-large text-on-surface caret-primary", "transition-colors selection:bg-primary/[0.12]", "not-disabled:hover:border-on-surface", "focus:border-primary focus:outline-2 focus:-outline-offset-1 focus:outline-primary", "data-[invalid]:border-error data-[invalid]:caret-error", "data-[invalid]:not-disabled:hover:border-error", "data-[invalid]:focus:border-error data-[invalid]:focus:outline-error", "disabled:cursor-not-allowed disabled:opacity-[0.38]", r),
13
+ className: e("h-14 w-11 rounded-small border border-outline bg-transparent", "text-center text-title-large text-on-surface caret-primary", "transition-colors selection:bg-primary/[0.12]", "not-disabled:hover:border-on-surface", "focus:border-primary focus:outline-2 focus:-outline-offset-1 focus:outline-primary", "data-[invalid]:border-error data-[invalid]:caret-error", "data-[invalid]:not-disabled:hover:border-error", "data-[invalid]:focus:border-error data-[invalid]:focus:outline-error", "disabled:cursor-not-allowed disabled:opacity-[0.38]", r),
14
14
  ...i
15
15
  });
16
16
  }
@@ -1 +1 @@
1
- {"version":3,"file":"OtpField.js","names":[],"sources":["../../../src/components/otp-field/OtpField.tsx"],"sourcesContent":["import { OTPFieldPreview as BaseOtpField } from '@base-ui/react/otp-field'\nimport { cn } from '#/lib/cn'\n\nimport type { ComponentProps } from 'react'\n\n/**\n * OtpField — Material 3 styled wrapper over Base UI's headless OTP Field.\n * Behaviour/accessibility (per-slot inputs, paste distribution, keyboard\n * navigation, hidden validation input, autofill via `one-time-code`):\n * Base UI (https://base-ui.com/react/components/otp-field).\n * Visuals: each slot is a compact M3 outlined text field — extra-small corner,\n * outline border, primary focus indicator, error role when invalid,\n * title-large centered digit. Design ref: port/core/ui/components/text-field\n * (see CLAUDE.md).\n *\n * Compound API mirrors Base UI:\n * <OtpField.Root length={6}>\n * <OtpField.Input />\n * <OtpField.Input />\n * <OtpField.Input />\n * <OtpField.Separator />\n * <OtpField.Input />\n * <OtpField.Input />\n * <OtpField.Input />\n * </OtpField.Root>\n */\n\nfunction Root({ className, ...props }: ComponentProps<typeof BaseOtpField.Root>) {\n return (\n <BaseOtpField.Root\n className={cn('flex items-center gap-2 text-on-surface', className)}\n {...props}\n />\n )\n}\n\nfunction Input({ className, ...props }: ComponentProps<typeof BaseOtpField.Input>) {\n return (\n <BaseOtpField.Input\n className={cn(\n // Slot box: compact M3 outlined text field.\n 'h-14 w-11 rounded-extra-small border border-outline bg-transparent',\n 'text-center text-title-large text-on-surface caret-primary',\n 'transition-colors selection:bg-primary/[0.12]',\n // Hover (enabled): outline shifts to the on-surface role.\n 'not-disabled:hover:border-on-surface',\n // Focused: 2px primary indicator hugging the border (no layout shift).\n 'focus:border-primary focus:outline-2 focus:-outline-offset-1 focus:outline-primary',\n // Invalid: error role replaces outline/indicator/caret.\n 'data-[invalid]:border-error data-[invalid]:caret-error',\n 'data-[invalid]:not-disabled:hover:border-error',\n 'data-[invalid]:focus:border-error data-[invalid]:focus:outline-error',\n // Disabled.\n 'disabled:cursor-not-allowed disabled:opacity-[0.38]',\n className,\n )}\n {...props}\n />\n )\n}\n\n/** Dash between slot groups (e.g. 123-456); accessible separator role. */\nfunction Separator({ className, ...props }: ComponentProps<typeof BaseOtpField.Separator>) {\n return (\n <BaseOtpField.Separator\n className={cn('h-0.5 w-3 shrink-0 rounded-full bg-outline-variant', className)}\n {...props}\n />\n )\n}\n\nexport const OtpField = { Root, Input, Separator }\nexport { Root, Input, Separator }\n"],"mappings":";;;;AA2BA,SAAS,EAAK,EAAE,cAAW,GAAG,KAAmD;CAC/E,OACE,kBAAC,EAAa,MAAd;EACE,WAAW,EAAG,2CAA2C,CAAS;EAClE,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,EAAM,EAAE,cAAW,GAAG,KAAoD;CACjF,OACE,kBAAC,EAAa,OAAd;EACE,WAAW,EAET,sEACA,8DACA,iDAEA,wCAEA,sFAEA,0DACA,kDACA,wEAEA,uDACA,CACF;EACA,GAAI;CACL,CAAA;AAEL;AAGA,SAAS,EAAU,EAAE,cAAW,GAAG,KAAwD;CACzF,OACE,kBAAC,EAAa,WAAd;EACE,WAAW,EAAG,sDAAsD,CAAS;EAC7E,GAAI;CACL,CAAA;AAEL;AAEA,IAAa,IAAW;CAAE;CAAM;CAAO;AAAU"}
1
+ {"version":3,"file":"OtpField.js","names":[],"sources":["../../../src/components/otp-field/OtpField.tsx"],"sourcesContent":["import { OTPFieldPreview as BaseOtpField } from '@base-ui/react/otp-field'\nimport { cn } from '#/lib/cn'\n\nimport type { ComponentProps } from 'react'\n\n/**\n * OtpField — Material 3 styled wrapper over Base UI's headless OTP Field.\n * Behaviour/accessibility (per-slot inputs, paste distribution, keyboard\n * navigation, hidden validation input, autofill via `one-time-code`):\n * Base UI (https://base-ui.com/react/components/otp-field).\n * Visuals: each slot is a compact M3 outlined text field — extra-small corner,\n * outline border, primary focus indicator, error role when invalid,\n * title-large centered digit. Design ref: port/core/ui/components/text-field\n * (see CLAUDE.md).\n *\n * Compound API mirrors Base UI:\n * <OtpField.Root length={6}>\n * <OtpField.Input />\n * <OtpField.Input />\n * <OtpField.Input />\n * <OtpField.Separator />\n * <OtpField.Input />\n * <OtpField.Input />\n * <OtpField.Input />\n * </OtpField.Root>\n */\n\nfunction Root({ className, ...props }: ComponentProps<typeof BaseOtpField.Root>) {\n return (\n <BaseOtpField.Root\n className={cn('flex items-center gap-2 text-on-surface', className)}\n {...props}\n />\n )\n}\n\nfunction Input({ className, ...props }: ComponentProps<typeof BaseOtpField.Input>) {\n return (\n <BaseOtpField.Input\n className={cn(\n // Slot box: compact M3 outlined text field.\n 'h-14 w-11 rounded-small border border-outline bg-transparent',\n 'text-center text-title-large text-on-surface caret-primary',\n 'transition-colors selection:bg-primary/[0.12]',\n // Hover (enabled): outline shifts to the on-surface role.\n 'not-disabled:hover:border-on-surface',\n // Focused: 2px primary indicator hugging the border (no layout shift).\n 'focus:border-primary focus:outline-2 focus:-outline-offset-1 focus:outline-primary',\n // Invalid: error role replaces outline/indicator/caret.\n 'data-[invalid]:border-error data-[invalid]:caret-error',\n 'data-[invalid]:not-disabled:hover:border-error',\n 'data-[invalid]:focus:border-error data-[invalid]:focus:outline-error',\n // Disabled.\n 'disabled:cursor-not-allowed disabled:opacity-[0.38]',\n className,\n )}\n {...props}\n />\n )\n}\n\n/** Dash between slot groups (e.g. 123-456); accessible separator role. */\nfunction Separator({ className, ...props }: ComponentProps<typeof BaseOtpField.Separator>) {\n return (\n <BaseOtpField.Separator\n className={cn('h-0.5 w-3 shrink-0 rounded-full bg-outline-variant', className)}\n {...props}\n />\n )\n}\n\nexport const OtpField = { Root, Input, Separator }\nexport { Root, Input, Separator }\n"],"mappings":";;;;AA2BA,SAAS,EAAK,EAAE,cAAW,GAAG,KAAmD;CAC/E,OACE,kBAAC,EAAa,MAAd;EACE,WAAW,EAAG,2CAA2C,CAAS;EAClE,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,EAAM,EAAE,cAAW,GAAG,KAAoD;CACjF,OACE,kBAAC,EAAa,OAAd;EACE,WAAW,EAET,gEACA,8DACA,iDAEA,wCAEA,sFAEA,0DACA,kDACA,wEAEA,uDACA,CACF;EACA,GAAI;CACL,CAAA;AAEL;AAGA,SAAS,EAAU,EAAE,cAAW,GAAG,KAAwD;CACzF,OACE,kBAAC,EAAa,WAAd;EACE,WAAW,EAAG,sDAAsD,CAAS;EAC7E,GAAI;CACL,CAAA;AAEL;AAEA,IAAa,IAAW;CAAE;CAAM;CAAO;AAAU"}
@@ -12,7 +12,7 @@ function c({ className: t, ...n }) {
12
12
  }
13
13
  function l({ className: t, ...n }) {
14
14
  return /* @__PURE__ */ i(a.Trigger, {
15
- className: e("group flex h-14 min-w-48 cursor-pointer select-none items-center justify-between gap-3 pl-4 pr-3", "rounded-extra-small border border-outline bg-surface text-body-large text-on-surface", "transition-colors hover:bg-on-surface/[0.08]", "focus-visible:border-primary focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary", "data-[popup-open]:border-primary", "data-[disabled]:cursor-not-allowed data-[disabled]:opacity-[0.38]", t),
15
+ className: e("group flex h-14 min-w-48 cursor-pointer select-none items-center justify-between gap-3 pl-4 pr-3", "rounded-small border border-outline bg-surface text-body-large text-on-surface", "transition-colors hover:bg-on-surface/[0.08]", "focus-visible:border-primary focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary", "data-[popup-open]:border-primary", "data-[disabled]:cursor-not-allowed data-[disabled]:opacity-[0.38]", t),
16
16
  ...n
17
17
  });
18
18
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Select.js","names":[],"sources":["../../../src/components/select/Select.tsx"],"sourcesContent":["import { Select as BaseSelect } from '@base-ui/react/select'\nimport { Check, ChevronDown, ChevronUp } from 'lucide-react'\nimport { cn } from '#/lib/cn'\n\nimport type { ComponentProps } from 'react'\n\n/**\n * Select — Material 3 styled wrapper over Base UI's headless Select.\n * Behaviour/accessibility (listbox semantics, typeahead, keyboard navigation,\n * form integration via hidden input): Base UI\n * (https://base-ui.com/react/components/select).\n * Visuals: M3 \"exposed dropdown menu\" anatomy — outlined text-field trigger\n * (56px, extra-small corner, outline → primary while open/focused, trailing\n * chevron), menu popup on surface-container with small corner + level-2\n * elevation, 48px list items with state layers and a trailing selected check.\n * Design refs: port/core/ui/components/dropdown, port/core/ui/components/text-field\n * (see CLAUDE.md).\n *\n * Compound API mirrors Base UI:\n * <Select.Root>\n * <Select.Label>Fruit</Select.Label>\n * <Select.Trigger>\n * <Select.Value placeholder=\"Pick a fruit\" />\n * <Select.Icon />\n * </Select.Trigger>\n * <Select.Portal>\n * <Select.Positioner>\n * <Select.Popup>\n * <Select.List>\n * <Select.Item value=\"apple\">\n * <Select.ItemText>Apple</Select.ItemText>\n * <Select.ItemIndicator />\n * </Select.Item>\n * </Select.List>\n * </Select.Popup>\n * </Select.Positioner>\n * </Select.Portal>\n * </Select.Root>\n */\n\n// These parts render no HTML element of their own, so there is nothing to\n// style — re-export them directly (preserves Root's value generics).\nconst Root = BaseSelect.Root\nconst Portal = BaseSelect.Portal\n\n/** M3 label above the field (label-large, on-surface). */\nfunction Label({ className, ...props }: ComponentProps<typeof BaseSelect.Label>) {\n return (\n <BaseSelect.Label\n className={cn('mb-1.5 block text-label-large text-on-surface', className)}\n {...props}\n />\n )\n}\n\n/**\n * The M3 outlined text-field box (56px, extra-small corner): outline turns\n * primary while focused or while the popup is open.\n */\nfunction Trigger({ className, ...props }: ComponentProps<typeof BaseSelect.Trigger>) {\n return (\n <BaseSelect.Trigger\n className={cn(\n 'group flex h-14 min-w-48 cursor-pointer select-none items-center justify-between gap-3 pl-4 pr-3',\n 'rounded-extra-small border border-outline bg-surface text-body-large text-on-surface',\n 'transition-colors hover:bg-on-surface/[0.08]',\n 'focus-visible:border-primary focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary',\n 'data-[popup-open]:border-primary',\n 'data-[disabled]:cursor-not-allowed data-[disabled]:opacity-[0.38]',\n className,\n )}\n {...props}\n />\n )\n}\n\n/** Selected-item text; shows the on-surface-variant placeholder when empty. */\nfunction Value({ className, ...props }: ComponentProps<typeof BaseSelect.Value>) {\n return (\n <BaseSelect.Value\n className={cn('truncate text-left data-[placeholder]:text-on-surface-variant', className)}\n {...props}\n />\n )\n}\n\n/** Trailing chevron; flips while the popup is open (parent Trigger is `group`). */\nfunction Icon({ className, children, ...props }: ComponentProps<typeof BaseSelect.Icon>) {\n return (\n <BaseSelect.Icon\n className={cn(\n 'flex shrink-0 text-on-surface-variant',\n 'transition-transform duration-200 ease-out group-data-[popup-open]:rotate-180',\n className,\n )}\n {...props}\n >\n {children ?? <ChevronDown aria-hidden className=\"size-5\" />}\n </BaseSelect.Icon>\n )\n}\n\nfunction Backdrop({ className, ...props }: ComponentProps<typeof BaseSelect.Backdrop>) {\n return <BaseSelect.Backdrop className={cn('fixed inset-0 z-40', className)} {...props} />\n}\n\n/**\n * Positions the popup as an M3 menu below the field (4px gap) instead of\n * Base UI's native-like \"align selected item with trigger\" default.\n */\nfunction Positioner({ className, ...props }: ComponentProps<typeof BaseSelect.Positioner>) {\n return (\n <BaseSelect.Positioner\n sideOffset={4}\n alignItemWithTrigger={false}\n className={cn('z-50 outline-none', className)}\n {...props}\n />\n )\n}\n\n/** M3 menu container: surface-container, small corner, level-2 elevation. */\nfunction Popup({ className, ...props }: ComponentProps<typeof BaseSelect.Popup>) {\n return (\n <BaseSelect.Popup\n className={cn(\n 'max-h-[min(24rem,var(--available-height))] w-(--anchor-width) overflow-y-auto overscroll-contain',\n 'rounded-small bg-surface-container py-2 text-on-surface shadow-mm-2',\n 'origin-(--transform-origin) transition-[transform,opacity] duration-150 ease-out',\n 'outline-none data-[ending-style]:scale-95 data-[ending-style]:opacity-0',\n 'data-[starting-style]:scale-95 data-[starting-style]:opacity-0',\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction Arrow({ className, ...props }: ComponentProps<typeof BaseSelect.Arrow>) {\n return <BaseSelect.Arrow className={cn('flex', className)} {...props} />\n}\n\nfunction List({ className, ...props }: ComponentProps<typeof BaseSelect.List>) {\n return <BaseSelect.List className={cn('outline-none', className)} {...props} />\n}\n\n/** M3 menu item: 48px row, label-large, hover/highlight state layers. */\nfunction Item({ className, ...props }: ComponentProps<typeof BaseSelect.Item>) {\n return (\n <BaseSelect.Item\n className={cn(\n 'grid min-h-12 cursor-pointer select-none grid-cols-[1fr_auto] items-center gap-3 px-4',\n 'text-label-large text-on-surface outline-none transition-colors',\n 'data-[highlighted]:bg-on-surface/[0.08]',\n 'data-[selected]:bg-secondary-container data-[selected]:text-on-secondary-container',\n 'data-[disabled]:cursor-not-allowed data-[disabled]:opacity-[0.38]',\n className,\n )}\n {...props}\n />\n )\n}\n\n/** The item's label text; mirrored into the trigger's Value when selected. */\nfunction ItemText({ className, ...props }: ComponentProps<typeof BaseSelect.ItemText>) {\n return <BaseSelect.ItemText className={cn('truncate', className)} {...props} />\n}\n\n/** Trailing selected check (primary role); only mounted while selected. */\nfunction ItemIndicator({\n className,\n children,\n ...props\n}: ComponentProps<typeof BaseSelect.ItemIndicator>) {\n return (\n <BaseSelect.ItemIndicator\n className={cn('col-start-2 flex shrink-0 items-center text-primary', className)}\n {...props}\n >\n {children ?? <Check aria-hidden className=\"size-5\" />}\n </BaseSelect.ItemIndicator>\n )\n}\n\n/** Hover-to-scroll affordance pinned to the top of an overflowing popup. */\nfunction ScrollUpArrow({\n className,\n children,\n ...props\n}: ComponentProps<typeof BaseSelect.ScrollUpArrow>) {\n return (\n <BaseSelect.ScrollUpArrow\n className={cn(\n 'sticky top-0 z-10 flex w-full items-center justify-center py-1',\n 'bg-surface-container text-on-surface-variant',\n className,\n )}\n {...props}\n >\n {children ?? <ChevronUp aria-hidden className=\"size-4\" />}\n </BaseSelect.ScrollUpArrow>\n )\n}\n\n/** Hover-to-scroll affordance pinned to the bottom of an overflowing popup. */\nfunction ScrollDownArrow({\n className,\n children,\n ...props\n}: ComponentProps<typeof BaseSelect.ScrollDownArrow>) {\n return (\n <BaseSelect.ScrollDownArrow\n className={cn(\n 'sticky bottom-0 z-10 flex w-full items-center justify-center py-1',\n 'bg-surface-container text-on-surface-variant',\n className,\n )}\n {...props}\n >\n {children ?? <ChevronDown aria-hidden className=\"size-4\" />}\n </BaseSelect.ScrollDownArrow>\n )\n}\n\nfunction Group({ className, ...props }: ComponentProps<typeof BaseSelect.Group>) {\n return <BaseSelect.Group className={cn(className)} {...props} />\n}\n\n/** M3 list subheader. */\nfunction GroupLabel({ className, ...props }: ComponentProps<typeof BaseSelect.GroupLabel>) {\n return (\n <BaseSelect.GroupLabel\n className={cn('px-4 pb-1 pt-3 text-label-medium text-on-surface-variant', className)}\n {...props}\n />\n )\n}\n\nfunction Separator({ className, ...props }: ComponentProps<typeof BaseSelect.Separator>) {\n return (\n <BaseSelect.Separator\n className={cn('mx-4 my-2 h-px bg-outline-variant', className)}\n {...props}\n />\n )\n}\n\nexport const Select = {\n Root,\n Label,\n Trigger,\n Value,\n Icon,\n Portal,\n Backdrop,\n Positioner,\n Popup,\n Arrow,\n List,\n Item,\n ItemText,\n ItemIndicator,\n ScrollUpArrow,\n ScrollDownArrow,\n Group,\n GroupLabel,\n Separator,\n}\nexport {\n Root,\n Label,\n Trigger,\n Value,\n Icon,\n Portal,\n Backdrop,\n Positioner,\n Popup,\n Arrow,\n List,\n Item,\n ItemText,\n ItemIndicator,\n ScrollUpArrow,\n ScrollDownArrow,\n Group,\n GroupLabel,\n Separator,\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"Select.js","names":[],"sources":["../../../src/components/select/Select.tsx"],"sourcesContent":["import { Select as BaseSelect } from '@base-ui/react/select'\nimport { Check, ChevronDown, ChevronUp } from 'lucide-react'\nimport { cn } from '#/lib/cn'\n\nimport type { ComponentProps } from 'react'\n\n/**\n * Select — Material 3 styled wrapper over Base UI's headless Select.\n * Behaviour/accessibility (listbox semantics, typeahead, keyboard navigation,\n * form integration via hidden input): Base UI\n * (https://base-ui.com/react/components/select).\n * Visuals: M3 \"exposed dropdown menu\" anatomy — outlined text-field trigger\n * (56px, extra-small corner, outline → primary while open/focused, trailing\n * chevron), menu popup on surface-container with small corner + level-2\n * elevation, 48px list items with state layers and a trailing selected check.\n * Design refs: port/core/ui/components/dropdown, port/core/ui/components/text-field\n * (see CLAUDE.md).\n *\n * Compound API mirrors Base UI:\n * <Select.Root>\n * <Select.Label>Fruit</Select.Label>\n * <Select.Trigger>\n * <Select.Value placeholder=\"Pick a fruit\" />\n * <Select.Icon />\n * </Select.Trigger>\n * <Select.Portal>\n * <Select.Positioner>\n * <Select.Popup>\n * <Select.List>\n * <Select.Item value=\"apple\">\n * <Select.ItemText>Apple</Select.ItemText>\n * <Select.ItemIndicator />\n * </Select.Item>\n * </Select.List>\n * </Select.Popup>\n * </Select.Positioner>\n * </Select.Portal>\n * </Select.Root>\n */\n\n// These parts render no HTML element of their own, so there is nothing to\n// style — re-export them directly (preserves Root's value generics).\nconst Root = BaseSelect.Root\nconst Portal = BaseSelect.Portal\n\n/** M3 label above the field (label-large, on-surface). */\nfunction Label({ className, ...props }: ComponentProps<typeof BaseSelect.Label>) {\n return (\n <BaseSelect.Label\n className={cn('mb-1.5 block text-label-large text-on-surface', className)}\n {...props}\n />\n )\n}\n\n/**\n * The M3 outlined text-field box (56px, extra-small corner): outline turns\n * primary while focused or while the popup is open.\n */\nfunction Trigger({ className, ...props }: ComponentProps<typeof BaseSelect.Trigger>) {\n return (\n <BaseSelect.Trigger\n className={cn(\n 'group flex h-14 min-w-48 cursor-pointer select-none items-center justify-between gap-3 pl-4 pr-3',\n 'rounded-small border border-outline bg-surface text-body-large text-on-surface',\n 'transition-colors hover:bg-on-surface/[0.08]',\n 'focus-visible:border-primary focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary',\n 'data-[popup-open]:border-primary',\n 'data-[disabled]:cursor-not-allowed data-[disabled]:opacity-[0.38]',\n className,\n )}\n {...props}\n />\n )\n}\n\n/** Selected-item text; shows the on-surface-variant placeholder when empty. */\nfunction Value({ className, ...props }: ComponentProps<typeof BaseSelect.Value>) {\n return (\n <BaseSelect.Value\n className={cn('truncate text-left data-[placeholder]:text-on-surface-variant', className)}\n {...props}\n />\n )\n}\n\n/** Trailing chevron; flips while the popup is open (parent Trigger is `group`). */\nfunction Icon({ className, children, ...props }: ComponentProps<typeof BaseSelect.Icon>) {\n return (\n <BaseSelect.Icon\n className={cn(\n 'flex shrink-0 text-on-surface-variant',\n 'transition-transform duration-200 ease-out group-data-[popup-open]:rotate-180',\n className,\n )}\n {...props}\n >\n {children ?? <ChevronDown aria-hidden className=\"size-5\" />}\n </BaseSelect.Icon>\n )\n}\n\nfunction Backdrop({ className, ...props }: ComponentProps<typeof BaseSelect.Backdrop>) {\n return <BaseSelect.Backdrop className={cn('fixed inset-0 z-40', className)} {...props} />\n}\n\n/**\n * Positions the popup as an M3 menu below the field (4px gap) instead of\n * Base UI's native-like \"align selected item with trigger\" default.\n */\nfunction Positioner({ className, ...props }: ComponentProps<typeof BaseSelect.Positioner>) {\n return (\n <BaseSelect.Positioner\n sideOffset={4}\n alignItemWithTrigger={false}\n className={cn('z-50 outline-none', className)}\n {...props}\n />\n )\n}\n\n/** M3 menu container: surface-container, small corner, level-2 elevation. */\nfunction Popup({ className, ...props }: ComponentProps<typeof BaseSelect.Popup>) {\n return (\n <BaseSelect.Popup\n className={cn(\n 'max-h-[min(24rem,var(--available-height))] w-(--anchor-width) overflow-y-auto overscroll-contain',\n 'rounded-small bg-surface-container py-2 text-on-surface shadow-mm-2',\n 'origin-(--transform-origin) transition-[transform,opacity] duration-150 ease-out',\n 'outline-none data-[ending-style]:scale-95 data-[ending-style]:opacity-0',\n 'data-[starting-style]:scale-95 data-[starting-style]:opacity-0',\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction Arrow({ className, ...props }: ComponentProps<typeof BaseSelect.Arrow>) {\n return <BaseSelect.Arrow className={cn('flex', className)} {...props} />\n}\n\nfunction List({ className, ...props }: ComponentProps<typeof BaseSelect.List>) {\n return <BaseSelect.List className={cn('outline-none', className)} {...props} />\n}\n\n/** M3 menu item: 48px row, label-large, hover/highlight state layers. */\nfunction Item({ className, ...props }: ComponentProps<typeof BaseSelect.Item>) {\n return (\n <BaseSelect.Item\n className={cn(\n 'grid min-h-12 cursor-pointer select-none grid-cols-[1fr_auto] items-center gap-3 px-4',\n 'text-label-large text-on-surface outline-none transition-colors',\n 'data-[highlighted]:bg-on-surface/[0.08]',\n 'data-[selected]:bg-secondary-container data-[selected]:text-on-secondary-container',\n 'data-[disabled]:cursor-not-allowed data-[disabled]:opacity-[0.38]',\n className,\n )}\n {...props}\n />\n )\n}\n\n/** The item's label text; mirrored into the trigger's Value when selected. */\nfunction ItemText({ className, ...props }: ComponentProps<typeof BaseSelect.ItemText>) {\n return <BaseSelect.ItemText className={cn('truncate', className)} {...props} />\n}\n\n/** Trailing selected check (primary role); only mounted while selected. */\nfunction ItemIndicator({\n className,\n children,\n ...props\n}: ComponentProps<typeof BaseSelect.ItemIndicator>) {\n return (\n <BaseSelect.ItemIndicator\n className={cn('col-start-2 flex shrink-0 items-center text-primary', className)}\n {...props}\n >\n {children ?? <Check aria-hidden className=\"size-5\" />}\n </BaseSelect.ItemIndicator>\n )\n}\n\n/** Hover-to-scroll affordance pinned to the top of an overflowing popup. */\nfunction ScrollUpArrow({\n className,\n children,\n ...props\n}: ComponentProps<typeof BaseSelect.ScrollUpArrow>) {\n return (\n <BaseSelect.ScrollUpArrow\n className={cn(\n 'sticky top-0 z-10 flex w-full items-center justify-center py-1',\n 'bg-surface-container text-on-surface-variant',\n className,\n )}\n {...props}\n >\n {children ?? <ChevronUp aria-hidden className=\"size-4\" />}\n </BaseSelect.ScrollUpArrow>\n )\n}\n\n/** Hover-to-scroll affordance pinned to the bottom of an overflowing popup. */\nfunction ScrollDownArrow({\n className,\n children,\n ...props\n}: ComponentProps<typeof BaseSelect.ScrollDownArrow>) {\n return (\n <BaseSelect.ScrollDownArrow\n className={cn(\n 'sticky bottom-0 z-10 flex w-full items-center justify-center py-1',\n 'bg-surface-container text-on-surface-variant',\n className,\n )}\n {...props}\n >\n {children ?? <ChevronDown aria-hidden className=\"size-4\" />}\n </BaseSelect.ScrollDownArrow>\n )\n}\n\nfunction Group({ className, ...props }: ComponentProps<typeof BaseSelect.Group>) {\n return <BaseSelect.Group className={cn(className)} {...props} />\n}\n\n/** M3 list subheader. */\nfunction GroupLabel({ className, ...props }: ComponentProps<typeof BaseSelect.GroupLabel>) {\n return (\n <BaseSelect.GroupLabel\n className={cn('px-4 pb-1 pt-3 text-label-medium text-on-surface-variant', className)}\n {...props}\n />\n )\n}\n\nfunction Separator({ className, ...props }: ComponentProps<typeof BaseSelect.Separator>) {\n return (\n <BaseSelect.Separator\n className={cn('mx-4 my-2 h-px bg-outline-variant', className)}\n {...props}\n />\n )\n}\n\nexport const Select = {\n Root,\n Label,\n Trigger,\n Value,\n Icon,\n Portal,\n Backdrop,\n Positioner,\n Popup,\n Arrow,\n List,\n Item,\n ItemText,\n ItemIndicator,\n ScrollUpArrow,\n ScrollDownArrow,\n Group,\n GroupLabel,\n Separator,\n}\nexport {\n Root,\n Label,\n Trigger,\n Value,\n Icon,\n Portal,\n Backdrop,\n Positioner,\n Popup,\n Arrow,\n List,\n Item,\n ItemText,\n ItemIndicator,\n ScrollUpArrow,\n ScrollDownArrow,\n Group,\n GroupLabel,\n Separator,\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@duestel/ui",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Material 3 (M3) React component library — a port of the Duestel design guide.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",