@mitcsutt/kiln-ui 0.5.0 → 0.7.0
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.
- package/dist/components/actions/CopyButton/CopyButton.d.ts +58 -0
- package/dist/components/actions/CopyButton/CopyButton.js +63 -0
- package/dist/components/actions/CopyButton/CopyButton.js.map +1 -0
- package/dist/components/actions/CopyButton/CopyButton.module.js +9 -0
- package/dist/components/actions/CopyButton/CopyButton.module.js.map +1 -0
- package/dist/components/actions/CopyButton/index.d.ts +4 -0
- package/dist/components/actions/CopyButton/useClipboard.d.ts +35 -0
- package/dist/components/actions/CopyButton/useClipboard.js +62 -0
- package/dist/components/actions/CopyButton/useClipboard.js.map +1 -0
- package/dist/components/actions/ToggleChip/ToggleChip.d.ts +6 -0
- package/dist/components/actions/ToggleChip/ToggleChip.js +26 -24
- package/dist/components/actions/ToggleChip/ToggleChip.js.map +1 -1
- package/dist/components/display/Badge/Badge.d.ts +6 -0
- package/dist/components/display/Badge/Badge.js +16 -15
- package/dist/components/display/Badge/Badge.js.map +1 -1
- package/dist/components/display/CodeBlock/CodeBlock.d.ts +44 -3
- package/dist/components/display/CodeBlock/CodeBlock.js +39 -47
- package/dist/components/display/CodeBlock/CodeBlock.js.map +1 -1
- package/dist/components/display/CodeBlock/CodeBlock.module.js +4 -3
- package/dist/components/display/CodeBlock/CodeBlock.module.js.map +1 -1
- package/dist/components/display/CodeBlock/index.d.ts +1 -1
- package/dist/components/display/Swatch/Swatch.d.ts +52 -0
- package/dist/components/display/Swatch/Swatch.js +27 -0
- package/dist/components/display/Swatch/Swatch.js.map +1 -0
- package/dist/components/display/Swatch/Swatch.module.js +6 -0
- package/dist/components/display/Swatch/Swatch.module.js.map +1 -0
- package/dist/components/display/Swatch/index.d.ts +2 -0
- package/dist/components/display/Tag/Tag.d.ts +7 -0
- package/dist/components/display/Tag/Tag.js +31 -26
- package/dist/components/display/Tag/Tag.js.map +1 -1
- package/dist/components/feedback/Indicator/Indicator.d.ts +74 -0
- package/dist/components/feedback/Indicator/Indicator.js +50 -0
- package/dist/components/feedback/Indicator/Indicator.js.map +1 -0
- package/dist/components/feedback/Indicator/Indicator.module.js +12 -0
- package/dist/components/feedback/Indicator/Indicator.module.js.map +1 -0
- package/dist/components/feedback/Indicator/index.d.ts +2 -0
- package/dist/components/feedback/Toaster/Toaster.d.ts +71 -0
- package/dist/components/feedback/Toaster/Toaster.js +121 -0
- package/dist/components/feedback/Toaster/Toaster.js.map +1 -0
- package/dist/components/feedback/Toaster/Toaster.module.js +20 -0
- package/dist/components/feedback/Toaster/Toaster.module.js.map +1 -0
- package/dist/components/feedback/Toaster/index.d.ts +4 -0
- package/dist/components/feedback/Toaster/toast.d.ts +96 -0
- package/dist/components/feedback/Toaster/toast.js +131 -0
- package/dist/components/feedback/Toaster/toast.js.map +1 -0
- package/dist/components/inputs/Calendar/Calendar.d.ts +87 -0
- package/dist/components/inputs/Calendar/Calendar.js +217 -0
- package/dist/components/inputs/Calendar/Calendar.js.map +1 -0
- package/dist/components/inputs/Calendar/Calendar.module.js +18 -0
- package/dist/components/inputs/Calendar/Calendar.module.js.map +1 -0
- package/dist/components/inputs/Calendar/index.d.ts +2 -0
- package/dist/components/inputs/Combobox/Combobox.js +36 -44
- package/dist/components/inputs/Combobox/Combobox.js.map +1 -1
- package/dist/components/inputs/DateField/DateField.d.ts +17 -0
- package/dist/components/inputs/DateField/DateField.js +26 -0
- package/dist/components/inputs/DateField/DateField.js.map +1 -0
- package/dist/components/inputs/DateField/index.d.ts +2 -0
- package/dist/components/inputs/DateInput/DateInput.d.ts +75 -0
- package/dist/components/inputs/DateInput/DateInput.js +139 -0
- package/dist/components/inputs/DateInput/DateInput.js.map +1 -0
- package/dist/components/inputs/DateInput/index.d.ts +3 -0
- package/dist/components/inputs/DateRangeField/DateRangeField.d.ts +18 -3
- package/dist/components/inputs/DateRangeField/DateRangeField.js.map +1 -1
- package/dist/components/inputs/DateRangeField/DateRangeField.module.js +8 -3
- package/dist/components/inputs/DateRangeField/DateRangeField.module.js.map +1 -1
- package/dist/components/inputs/DateRangeField/DateRangePickerField.d.ts +48 -0
- package/dist/components/inputs/DateRangeField/DateRangePickerField.js +246 -0
- package/dist/components/inputs/DateRangeField/DateRangePickerField.js.map +1 -0
- package/dist/components/inputs/DateRangeField/index.d.ts +2 -0
- package/dist/components/inputs/DateTimeField/DateTimeField.d.ts +17 -0
- package/dist/components/inputs/DateTimeField/DateTimeField.js +26 -0
- package/dist/components/inputs/DateTimeField/DateTimeField.js.map +1 -0
- package/dist/components/inputs/DateTimeField/index.d.ts +2 -0
- package/dist/components/inputs/DateTimeInput/DateTimeInput.d.ts +83 -0
- package/dist/components/inputs/DateTimeInput/DateTimeInput.js +216 -0
- package/dist/components/inputs/DateTimeInput/DateTimeInput.js.map +1 -0
- package/dist/components/inputs/DateTimeInput/index.d.ts +2 -0
- package/dist/components/inputs/JsonField/JsonField.d.ts +23 -0
- package/dist/components/inputs/JsonField/JsonField.js +33 -0
- package/dist/components/inputs/JsonField/JsonField.js.map +1 -0
- package/dist/components/inputs/JsonField/index.d.ts +2 -0
- package/dist/components/inputs/JsonInput/JsonInput.d.ts +119 -0
- package/dist/components/inputs/JsonInput/JsonInput.js +282 -0
- package/dist/components/inputs/JsonInput/JsonInput.js.map +1 -0
- package/dist/components/inputs/JsonInput/JsonInput.module.js +16 -0
- package/dist/components/inputs/JsonInput/JsonInput.module.js.map +1 -0
- package/dist/components/inputs/JsonInput/index.d.ts +4 -0
- package/dist/components/inputs/JsonInput/json.d.ts +59 -0
- package/dist/components/inputs/JsonInput/json.js +231 -0
- package/dist/components/inputs/JsonInput/json.js.map +1 -0
- package/dist/components/inputs/TagsInput/TagsInput.js +5 -5
- package/dist/components/inputs/TimeField/TimeField.d.ts +17 -0
- package/dist/components/inputs/TimeField/TimeField.js +26 -0
- package/dist/components/inputs/TimeField/TimeField.js.map +1 -0
- package/dist/components/inputs/TimeField/index.d.ts +2 -0
- package/dist/components/inputs/TimeInput/TimeInput.d.ts +54 -0
- package/dist/components/inputs/TimeInput/TimeInput.js +107 -0
- package/dist/components/inputs/TimeInput/TimeInput.js.map +1 -0
- package/dist/components/inputs/TimeInput/index.d.ts +2 -0
- package/dist/components/inputs/internal/DateSegments.d.ts +80 -0
- package/dist/components/inputs/internal/DateSegments.js +345 -0
- package/dist/components/inputs/internal/DateSegments.js.map +1 -0
- package/dist/components/inputs/internal/dates.d.ts +101 -0
- package/dist/components/inputs/internal/dates.js +262 -0
- package/dist/components/inputs/internal/dates.js.map +1 -0
- package/dist/components/inputs/internal/filterOptions.d.ts +22 -1
- package/dist/components/inputs/internal/filterOptions.js +32 -1
- package/dist/components/inputs/internal/filterOptions.js.map +1 -1
- package/dist/components/inputs/internal/picker.d.ts +31 -0
- package/dist/components/inputs/internal/picker.js +29 -0
- package/dist/components/inputs/internal/picker.js.map +1 -0
- package/dist/components/inputs/internal/picker.module.js +15 -0
- package/dist/components/inputs/internal/picker.module.js.map +1 -0
- package/dist/components/inputs/internal/segments.module.js +10 -0
- package/dist/components/inputs/internal/segments.module.js.map +1 -0
- package/dist/components/layout/Collapse/Collapse.d.ts +39 -0
- package/dist/components/layout/Collapse/Collapse.js +24 -0
- package/dist/components/layout/Collapse/Collapse.js.map +1 -0
- package/dist/components/layout/Collapse/Collapse.module.js +6 -0
- package/dist/components/layout/Collapse/Collapse.module.js.map +1 -0
- package/dist/components/layout/Collapse/index.d.ts +2 -0
- package/dist/components/layout/Collapse/useHeightMotion.d.ts +16 -0
- package/dist/components/layout/Collapse/useHeightMotion.js +60 -0
- package/dist/components/layout/Collapse/useHeightMotion.js.map +1 -0
- package/dist/components/layout/ShowMore/ShowMore.d.ts +59 -0
- package/dist/components/layout/ShowMore/ShowMore.js +114 -0
- package/dist/components/layout/ShowMore/ShowMore.js.map +1 -0
- package/dist/components/layout/ShowMore/ShowMore.module.js +12 -0
- package/dist/components/layout/ShowMore/ShowMore.module.js.map +1 -0
- package/dist/components/layout/ShowMore/index.d.ts +2 -0
- package/dist/components/layout/Transition/Transition.d.ts +63 -0
- package/dist/components/layout/Transition/Transition.js +63 -0
- package/dist/components/layout/Transition/Transition.js.map +1 -0
- package/dist/components/layout/Transition/Transition.module.js +17 -0
- package/dist/components/layout/Transition/Transition.module.js.map +1 -0
- package/dist/components/layout/Transition/index.d.ts +2 -0
- package/dist/components/navigation/Collapsible/Collapsible.d.ts +49 -0
- package/dist/components/navigation/Collapsible/Collapsible.js +83 -0
- package/dist/components/navigation/Collapsible/Collapsible.js.map +1 -0
- package/dist/components/navigation/Collapsible/Collapsible.module.js +11 -0
- package/dist/components/navigation/Collapsible/Collapsible.module.js.map +1 -0
- package/dist/components/navigation/Collapsible/index.d.ts +2 -0
- package/dist/components/navigation/NavLinks/NavLinks.d.ts +32 -4
- package/dist/components/navigation/NavLinks/NavLinks.js +69 -39
- package/dist/components/navigation/NavLinks/NavLinks.js.map +1 -1
- package/dist/components/navigation/NavLinks/NavLinks.module.js +13 -3
- package/dist/components/navigation/NavLinks/NavLinks.module.js.map +1 -1
- package/dist/components/navigation/NavLinks/NavLinksGroup.d.ts +49 -0
- package/dist/components/navigation/NavLinks/NavLinksGroup.js +185 -0
- package/dist/components/navigation/NavLinks/NavLinksGroup.js.map +1 -0
- package/dist/components/navigation/NavLinks/context.d.ts +28 -0
- package/dist/components/navigation/NavLinks/context.js +13 -0
- package/dist/components/navigation/NavLinks/context.js.map +1 -0
- package/dist/components/navigation/NavLinks/index.d.ts +2 -0
- package/dist/components/navigation/NavLinks/treeKeys.d.ts +8 -0
- package/dist/components/navigation/NavLinks/treeKeys.js +57 -0
- package/dist/components/navigation/NavLinks/treeKeys.js.map +1 -0
- package/dist/components/overlays/CommandPalette/CommandPalette.d.ts +120 -0
- package/dist/components/overlays/CommandPalette/CommandPalette.js +386 -0
- package/dist/components/overlays/CommandPalette/CommandPalette.js.map +1 -0
- package/dist/components/overlays/CommandPalette/CommandPalette.module.js +31 -0
- package/dist/components/overlays/CommandPalette/CommandPalette.module.js.map +1 -0
- package/dist/components/overlays/CommandPalette/index.d.ts +2 -0
- package/dist/components/overlays/CommandPalette/shortcut.d.ts +28 -0
- package/dist/components/overlays/CommandPalette/shortcut.js +104 -0
- package/dist/components/overlays/CommandPalette/shortcut.js.map +1 -0
- package/dist/highlight/index.d.ts +18 -0
- package/dist/highlight/index.js +103 -0
- package/dist/highlight/index.js.map +1 -0
- package/dist/index.d.ts +41 -5
- package/dist/index.js +123 -100
- package/dist/styles.css +1 -1
- package/dist/themes/fiesta.css +1 -1
- package/dist/themes/flightdeck.css +1 -1
- package/dist/themes/ledger.css +1 -1
- package/dist/themes/monograph.css +1 -1
- package/dist/themes/riso.css +1 -1
- package/dist/utils/newlines.d.ts +2 -0
- package/dist/utils/newlines.js +10 -0
- package/dist/utils/newlines.js.map +1 -0
- package/package.json +13 -2
- package/skills/custom-theme/SKILL.md +32 -0
- package/skills/custom-theme/references/colour.md +20 -0
- package/skills/custom-theme/references/motion.md +9 -0
- package/skills/custom-theme/references/tokens.md +35 -0
- package/skills/design-rules/SKILL.md +5 -2
- package/skills/setup-and-theming/SKILL.md +2 -1
- package/skills/setup-and-theming/references/paper.md +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Combobox.js","names":["PopoverPrimitive","styles","control","messageStyles","messages_module_default","control_module_default","Combobox_module_default","buildView","matched","shouldFilter","filterOptions","options","query","sections","byKey","option","key","section","defaultRemoveLabel","label","splitMode","props","base","defaultValue","onValueChange","next","removeLabel","multiple","value","themeScopeOf","scope","node","countMessage","count","ComboboxPopup","forwardRef","theme","usePortalTheme","Popover","Combobox","markFieldAware","mode","inputValueProp","openProp","invalidProp","idProp","disabledProp","requiredProp","readOnlyProp","describedByProp","ariaInvalid","ariaLabel","ariaLabelledBy","rest","field","useResolvedField","autoId","useId","inputId","listboxId","statusId","interactive","inputRef","useRef","boxRef","composedInputRef","useMergedRefs","ref","labelCache","labelOf","useCallback","values","setValues","useControllableState","selectedLabel","setQueryState","defaultInputValue","onInputValueChange","queryRef","setQuery","dirty","setDirty","useState","openState","setOpenState","defaultOpen","onOpenChange","openRef","setOpen","activeValue","setActiveValue","filter","useMemo","indexOf","index","optionId","atMax","maxSelected","isSelected","isDisabled","enabled","ordered","trimmedQuery","freeText","creatable","showEmpty","loading","hasPopupContent","expanded","autoHighlight","activeOption","active","announcement","setAnnouncement","countText","emptyMessage","timer","activeId","selectOption","commitText","folded","foldText","match","removeValue","v","clear","initialActive","fromEnd","move","delta","openList","highlight","handleChange","text","event","handleKeyDown","onKeyDown","handleBlur","onBlur","handleBoxPointerDown","target","handleInputClick","onClick","handleInteractOutside","listLabelledBy","showPlaceholder","canClear","clearable","renderOption","selected","disabled","CheckIcon","PortalAnchorContext","cx","className","size","TagList","Tag","placeholder","Spinner","clearLabel","CloseIcon","ChevronDownIcon","name","loadingMessage"],"sources":["../../../../src/components/inputs/Combobox/Combobox.tsx"],"sourcesContent":["import {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type FocusEvent,\n type FocusEventHandler,\n type InputHTMLAttributes,\n type KeyboardEvent,\n type MouseEvent,\n type PointerEvent,\n type ReactNode,\n} from 'react'\nimport { Popover as PopoverPrimitive } from 'radix-ui'\nimport { CheckIcon, ChevronDownIcon, CloseIcon } from '#icons'\nimport { cx } from '#utils/cx'\nimport type { Size } from '#utils/tokens'\nimport { Spinner } from '#components/feedback/Spinner'\nimport { Tag, TagList } from '#components/display/Tag'\nimport { PortalAnchorContext, usePortalTheme } from '#components/overlays/usePortalTheme'\nimport { markFieldAware, useResolvedField } from '#components/inputs/internal/FieldContext'\nimport { filterOptions, foldText } from '#components/inputs/internal/filterOptions'\nimport { useMergedRefs } from '#components/inputs/internal/refs'\nimport control from '#components/inputs/internal/control.module.css'\nimport messageStyles from '#components/inputs/internal/messages.module.css'\nimport { useControllableState } from './useControllableState'\nimport styles from './Combobox.module.css'\n\nexport interface ComboboxOption {\n value: string\n label: string\n /** A second, quieter line under the label. Also searched. */\n description?: string\n /** Extra search terms that aren't shown (\"USA\", \"Holland\"). An exact keyword ranks first. */\n keywords?: readonly string[]\n /** Heading the option is listed under. Groups appear in order of their first option. */\n group?: string\n disabled?: boolean\n}\n\nexport interface ComboboxBase extends Omit<\n InputHTMLAttributes<HTMLInputElement>,\n 'value' | 'defaultValue' | 'onChange' | 'size' | 'type' | 'multiple' | 'onBlur'\n> {\n options: readonly ComboboxOption[]\n /** The text in the box (the query). Controlled. */\n inputValue?: string\n defaultInputValue?: string\n onInputValueChange?: (query: string) => void\n /**\n * `auto` (default) filters and ranks `options` by the query. `none` shows `options` as\n * given — for async search, where the loader has already filtered.\n */\n filter?: 'auto' | 'none'\n /** Options are being fetched: a spinner in the box and `loadingMessage` in an empty list. */\n loading?: boolean\n loadingMessage?: ReactNode\n /** Shown in the list when nothing matches. Default \"No matches\". */\n emptyMessage?: ReactNode\n open?: boolean\n defaultOpen?: boolean\n onOpenChange?: (open: boolean) => void\n /**\n * Free text is allowed: whatever is typed becomes the value when committed (Enter, or\n * leaving the field). A typed label that matches an option picks that option instead.\n */\n creatable?: boolean\n /** Shows a clear button while there's a value. */\n clearable?: boolean\n /** Accessible name of the clear button. Default \"Clear\". */\n clearLabel?: string\n size?: Size\n /** Critical border + `aria-invalid`. Inside a `<Field error>` this is set for you. */\n invalid?: boolean\n /** Fires once focus leaves the whole control (input, chips, clear button, list). */\n onBlur?: FocusEventHandler<HTMLElement>\n}\n\nexport interface ComboboxSingleProps extends ComboboxBase {\n multiple?: false\n value?: string | null\n defaultValue?: string | null\n onValueChange?: (value: string | null) => void\n}\n\nexport interface ComboboxMultipleProps extends ComboboxBase {\n multiple: true\n value?: readonly string[]\n defaultValue?: readonly string[]\n onValueChange?: (value: string[]) => void\n /** Once this many are chosen, the rest of the list is disabled. */\n maxSelected?: number\n /** Accessible name of a chip's remove button. Default `Remove <label>`. */\n removeLabel?: (label: string) => string\n}\n\nexport type ComboboxProps = ComboboxSingleProps | ComboboxMultipleProps\n\n/* ─── Pure helpers ────────────────────────────────────────────────────────── */\n\ninterface Section {\n key: string\n label?: string\n options: ComboboxOption[]\n}\n\n/** Visible options, in groups (ordered by each group's first/best option), and flattened. */\nfunction buildView(options: readonly ComboboxOption[], query: string, shouldFilter: boolean) {\n const matched = shouldFilter ? filterOptions(options, query) : [...options]\n const sections: Section[] = []\n const byKey = new Map<string, Section>()\n for (const option of matched) {\n const key = option.group === undefined ? '' : `g:${option.group}`\n let section = byKey.get(key)\n if (!section) {\n section = { key, label: option.group, options: [] }\n byKey.set(key, section)\n sections.push(section)\n }\n section.options.push(option)\n }\n return { sections, ordered: sections.flatMap((section) => section.options) }\n}\n\ninterface ModeProps {\n multiple: boolean\n value: readonly string[] | undefined\n defaultValue: readonly string[]\n emit: (next: readonly string[]) => void\n maxSelected: number | undefined\n removeLabel: (label: string) => string\n}\n\nconst defaultRemoveLabel = (label: string) => `Remove ${label}`\n\n/** Splits the single/multiple union into one normalised shape (values are always arrays). */\nfunction splitMode(props: ComboboxProps): [ComboboxBase, ModeProps] {\n if (props.multiple === true) {\n const { multiple, value, defaultValue, onValueChange, maxSelected, removeLabel, ...base } =\n props\n return [\n base,\n {\n multiple,\n value,\n defaultValue: defaultValue ?? [],\n emit: (next) => onValueChange?.([...next]),\n maxSelected,\n removeLabel: removeLabel ?? defaultRemoveLabel,\n },\n ]\n }\n const { multiple, value, defaultValue, onValueChange, ...base } = props\n return [\n base,\n {\n multiple: Boolean(multiple),\n value: value === undefined ? undefined : value === null ? [] : [value],\n defaultValue: defaultValue == null ? [] : [defaultValue],\n emit: (next) => onValueChange?.(next[0] ?? null),\n maxSelected: undefined,\n removeLabel: defaultRemoveLabel,\n },\n ]\n}\n\n/** The nearest theme scope below `<html>` — the portal target, so the list opens in that theme. */\nfunction themeScopeOf(node: HTMLElement | null): HTMLElement | undefined {\n const scope = node?.closest<HTMLElement>('[data-theme]')\n return scope && scope !== node?.ownerDocument.documentElement ? scope : undefined\n}\n\nfunction countMessage(count: number): string {\n return `${String(count)} ${count === 1 ? 'option' : 'options'} available`\n}\n\n/* ─── Popup (mounts on open, so it reads the theme at open time) ─────────── */\n\ninterface PopupProps {\n children: ReactNode\n onInteractOutside: (event: Event) => void\n}\n\n// forwardRef: Radix Presence hands the popup a ref (React 18 warns without it).\nconst ComboboxPopup = forwardRef<HTMLDivElement, PopupProps>(function ComboboxPopup(\n { children, onInteractOutside },\n ref,\n) {\n const theme = usePortalTheme()\n return (\n <PopoverPrimitive.Content\n ref={ref}\n className={styles.popup}\n // A wrapper, not a dialog: the listbox inside carries the semantics.\n role={undefined}\n side=\"bottom\"\n align=\"start\"\n sideOffset={6}\n collisionPadding={8}\n // Focus never leaves the input (ARIA combobox): no auto-focus in or back.\n onOpenAutoFocus={(event) => {\n event.preventDefault()\n }}\n onCloseAutoFocus={(event) => {\n event.preventDefault()\n }}\n // The input's own keydown handles Escape (close, then clear).\n onEscapeKeyDown={(event) => {\n event.preventDefault()\n }}\n onInteractOutside={onInteractOutside}\n // Clicks on padding / messages must not take focus from the input.\n onMouseDown={(event) => {\n event.preventDefault()\n }}\n {...theme}\n >\n {children}\n </PopoverPrimitive.Content>\n )\n})\n\n/* ─── Combobox ────────────────────────────────────────────────────────────── */\n\n/**\n * Type to filter and pick from a list. Single or multiple, free text if you allow it, ready for\n * async options.\n *\n * @remarks\n * `Combobox` is an ARIA 1.2 combobox: a text input that filters a listbox as you type. With\n * `multiple`, chosen values become removable chips in the box. With `creatable`, typed text that\n * matches nothing can be added as a value.\n *\n * @privateRemarks\n * Type to filter, pick from a list (ARIA 1.2 combobox with a listbox popup). Single or\n * `multiple` (chosen values become removable chips), `creatable` for free text, and\n * async-ready: pass `filter=\"none\"`, `loading` and the loader's results as `options`.\n * The ref and native input props go to the text input; `className`/`style` go to the box.\n *\n * <Combobox options={projects} placeholder=\"Search projects\" onValueChange={setProject} />\n * <Combobox multiple options={labels} maxSelected={3} />\n */\nexport const Combobox = markFieldAware(\n forwardRef<HTMLInputElement, ComboboxProps>(function Combobox(props, ref) {\n const [base, mode] = splitMode(props)\n const {\n options,\n inputValue: inputValueProp,\n defaultInputValue,\n onInputValueChange,\n filter = 'auto',\n loading = false,\n loadingMessage = 'Loading…',\n emptyMessage = 'No matches',\n open: openProp,\n defaultOpen = false,\n onOpenChange,\n creatable = false,\n clearable = false,\n clearLabel = 'Clear',\n size = 'md',\n invalid: invalidProp,\n id: idProp,\n disabled: disabledProp,\n required: requiredProp,\n readOnly: readOnlyProp,\n name,\n form,\n placeholder,\n className,\n style,\n onKeyDown,\n onBlur,\n onClick,\n 'aria-describedby': describedByProp,\n 'aria-invalid': ariaInvalid,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n ...rest\n } = base\n const { multiple, maxSelected, removeLabel } = mode\n\n const field = useResolvedField({\n id: idProp,\n describedBy: describedByProp,\n invalid: invalidProp,\n ariaInvalid,\n required: requiredProp,\n disabled: disabledProp,\n readOnly: readOnlyProp,\n })\n const autoId = useId()\n const inputId = field.id ?? `${autoId}combobox`\n const listboxId = `${inputId}-listbox`\n const statusId = `${inputId}-status`\n const interactive = !field.disabled && !field.readOnly\n\n const inputRef = useRef<HTMLInputElement>(null)\n const boxRef = useRef<HTMLDivElement>(null)\n const composedInputRef = useMergedRefs(ref, inputRef)\n\n /* Labels of chosen values survive the options changing (async results, creatable). */\n const labelCache = useRef(new Map<string, string>())\n for (const option of options) labelCache.current.set(option.value, option.label)\n const labelOf = useCallback(\n (value: string) =>\n options.find((option) => option.value === value)?.label ??\n labelCache.current.get(value) ??\n value,\n [options],\n )\n\n const [values, setValues] = useControllableState<readonly string[]>(\n mode.value,\n mode.defaultValue,\n mode.emit,\n )\n const selectedLabel = !multiple && values[0] !== undefined ? labelOf(values[0]) : ''\n\n const [query, setQueryState] = useControllableState<string>(\n inputValueProp,\n defaultInputValue ??\n (multiple || mode.defaultValue[0] === undefined ? '' : labelOf(mode.defaultValue[0])),\n onInputValueChange,\n )\n const queryRef = useRef(query)\n queryRef.current = query\n const setQuery = useCallback(\n (next: string) => {\n if (next !== queryRef.current) setQueryState(next)\n },\n [setQueryState],\n )\n /** The user has typed since the last pick (single: the text is a query, not the label). */\n const [dirty, setDirty] = useState(false)\n\n const [openState, setOpenState] = useControllableState<boolean>(\n openProp,\n defaultOpen,\n onOpenChange,\n )\n const openRef = useRef(openState)\n openRef.current = openState\n const setOpen = useCallback(\n (next: boolean) => {\n if (next !== openRef.current) setOpenState(next)\n },\n [setOpenState],\n )\n\n const [activeValue, setActiveValue] = useState<string | null>(null)\n\n // Single: show the chosen option's label whenever the user isn't mid-edit (covers\n // external value changes such as a form reset).\n useEffect(() => {\n if (!multiple && !dirty) setQuery(selectedLabel)\n }, [multiple, dirty, selectedLabel, setQuery])\n\n /* ─── Derived view ─── */\n const shouldFilter = filter === 'auto' && (multiple || dirty)\n const { sections, ordered } = useMemo(\n () => buildView(options, query, shouldFilter),\n [options, query, shouldFilter],\n )\n const indexOf = useMemo(\n () => new Map(options.map((option, index) => [option.value, index])),\n [options],\n )\n const optionId = (value: string) => `${inputId}-option-${String(indexOf.get(value) ?? 0)}`\n\n const atMax = multiple && maxSelected !== undefined && values.length >= maxSelected\n const isSelected = (value: string) => values.includes(value)\n const isDisabled = (option: ComboboxOption) =>\n Boolean(option.disabled) || (atMax && !isSelected(option.value))\n const enabled = ordered.filter((option) => !isDisabled(option))\n\n const trimmedQuery = query.trim()\n const freeText = creatable && trimmedQuery !== '' && (multiple || dirty)\n const showEmpty = !loading && ordered.length === 0 && !freeText\n const hasPopupContent = ordered.length > 0 || loading || showEmpty\n const expanded = openState && interactive && hasPopupContent\n\n // Non-creatable: typing highlights the best match, so Enter picks it. Not while loading:\n // the list still shows the previous query's results, and Enter must not commit one of them.\n const autoHighlight =\n expanded && !loading && !creatable && trimmedQuery !== '' && (multiple || dirty)\n const activeOption =\n enabled.find((option) => option.value === activeValue) ??\n (autoHighlight ? enabled[0] : undefined)\n const active = expanded ? activeOption : undefined\n\n /* ─── Live region: result count, debounced ─── */\n const [announcement, setAnnouncement] = useState('')\n const countText = loading\n ? ''\n : ordered.length === 0\n ? typeof emptyMessage === 'string'\n ? emptyMessage\n : 'No matches'\n : countMessage(ordered.length)\n useEffect(() => {\n if (!expanded || countText === '') {\n if (!expanded) setAnnouncement('')\n return\n }\n const timer = setTimeout(() => {\n setAnnouncement(countText)\n }, 500)\n return () => {\n clearTimeout(timer)\n }\n }, [expanded, countText])\n\n /* Keep the highlighted row in view. */\n const activeId = active ? optionId(active.value) : undefined\n useEffect(() => {\n if (!activeId) return\n const node = inputRef.current?.ownerDocument.getElementById(activeId)\n node?.scrollIntoView({ block: 'nearest' })\n }, [activeId])\n\n /* ─── Actions ─── */\n const selectOption = (option: ComboboxOption) => {\n if (!interactive || isDisabled(option)) return\n labelCache.current.set(option.value, option.label)\n if (multiple) {\n const next = isSelected(option.value)\n ? values.filter((value) => value !== option.value)\n : [...values, option.value]\n setValues(next)\n setQuery('')\n setDirty(false)\n setActiveValue(option.value)\n } else {\n setValues([option.value])\n setQuery(option.label)\n setDirty(false)\n setActiveValue(null)\n setOpen(false)\n }\n }\n\n /** Creatable: turn the typed text into a value. Returns whether anything changed. */\n const commitText = (): boolean => {\n if (!creatable || trimmedQuery === '') return false\n const folded = foldText(trimmedQuery)\n const match = options.find((option) => !option.disabled && foldText(option.label) === folded)\n const value = match?.value ?? trimmedQuery\n const label = match?.label ?? trimmedQuery\n labelCache.current.set(value, label)\n if (multiple) {\n setQuery('')\n setDirty(false)\n if (isSelected(value) || atMax) return false\n setValues([...values, value])\n return true\n }\n setDirty(false)\n setQuery(label)\n if (values[0] === value) return false\n setValues([value])\n return true\n }\n\n const removeValue = (value: string) => {\n if (!interactive) return\n setValues(values.filter((v) => v !== value))\n }\n\n const clear = () => {\n if (!interactive) return\n setValues([])\n setQuery('')\n setDirty(false)\n setActiveValue(null)\n inputRef.current?.focus()\n }\n\n /** First visible selected option, else the first/last enabled one. */\n const initialActive = (fromEnd: boolean) =>\n enabled.find((option) => isSelected(option.value)) ??\n (fromEnd ? enabled[enabled.length - 1] : enabled[0])\n\n const move = (delta: 1 | -1) => {\n if (enabled.length === 0) return\n const index = active ? enabled.indexOf(active) : -1\n const next =\n index === -1\n ? delta === 1\n ? enabled[0]\n : enabled[enabled.length - 1]\n : enabled[(index + delta + enabled.length) % enabled.length]\n setActiveValue(next?.value ?? null)\n }\n\n const openList = (highlight: 'first' | 'last' | 'keep') => {\n if (!interactive) return\n setOpen(true)\n if (highlight !== 'keep') setActiveValue(initialActive(highlight === 'last')?.value ?? null)\n }\n\n /* ─── Events ─── */\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\n const text = event.target.value\n setQuery(text)\n setDirty(true)\n setActiveValue(null)\n if (interactive) setOpen(true)\n }\n\n const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\n onKeyDown?.(event)\n if (event.nativeEvent.isComposing) return\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault()\n if (event.altKey) openList('keep')\n else if (expanded) move(1)\n else openList('first')\n return\n case 'ArrowUp':\n event.preventDefault()\n if (event.altKey) setOpen(false)\n else if (expanded) move(-1)\n else openList('last')\n return\n case 'Home':\n case 'End':\n if (!expanded || enabled.length === 0) return\n event.preventDefault()\n setActiveValue(\n (event.key === 'Home' ? enabled[0] : enabled[enabled.length - 1])?.value ?? null,\n )\n return\n case 'Enter':\n if (expanded && active) {\n event.preventDefault()\n selectOption(active)\n } else if (freeText) {\n event.preventDefault()\n commitText()\n if (!multiple) setOpen(false)\n } else if (expanded) {\n event.preventDefault()\n }\n return\n case 'Escape':\n if (expanded) {\n event.preventDefault()\n setOpen(false)\n } else if (query !== '' && interactive) {\n event.preventDefault()\n setQuery('')\n setDirty(!multiple)\n }\n return\n case 'Tab':\n setOpen(false)\n return\n case 'Backspace':\n if (multiple && query === '' && interactive && values.length > 0) {\n event.preventDefault()\n setValues(values.slice(0, -1))\n }\n return\n }\n }\n\n /** Focus left the whole control: settle the text, close, then tell the consumer. */\n const handleBlur = (event: FocusEvent<HTMLDivElement>) => {\n const next = event.relatedTarget as Node | null\n if (next && boxRef.current?.contains(next)) return\n if (interactive) {\n if (multiple) {\n if (!commitText()) setQuery('')\n } else if (dirty) {\n if (creatable && trimmedQuery !== '') commitText()\n else if (trimmedQuery === '') {\n if (values.length > 0) setValues([])\n setQuery('')\n } else setQuery(selectedLabel)\n }\n setDirty(false)\n }\n setOpen(false)\n setActiveValue(null)\n onBlur?.(event)\n }\n\n // Clicking the box's padding or chevron focuses the input and toggles the list.\n const handleBoxPointerDown = (event: PointerEvent<HTMLDivElement>) => {\n const target = event.target as HTMLElement\n if (target === inputRef.current || target.closest('button, a, input')) return\n event.preventDefault()\n inputRef.current?.focus()\n if (openRef.current) setOpen(false)\n else openList('keep')\n }\n\n const handleInputClick = (event: MouseEvent<HTMLInputElement>) => {\n onClick?.(event)\n if (!openRef.current) openList('keep')\n }\n\n const handleInteractOutside = (event: Event) => {\n const target = event.target as Node | null\n if (target && boxRef.current?.contains(target)) event.preventDefault()\n }\n\n /* ─── Render ─── */\n const listLabelledBy = ariaLabelledBy ?? field.labelId\n const showPlaceholder = !multiple || values.length === 0\n const canClear = clearable && interactive && (values.length > 0 || query !== '')\n\n const renderOption = (option: ComboboxOption) => {\n const selected = isSelected(option.value)\n const disabled = isDisabled(option)\n return (\n // The input owns focus and the keyboard (aria-activedescendant points here), so an\n // option is never focused itself and its click is the pointer path only.\n // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/interactive-supports-focus\n <div\n key={option.value}\n id={optionId(option.value)}\n role=\"option\"\n aria-selected={selected}\n aria-disabled={disabled || undefined}\n className={styles.option}\n data-active={active?.value === option.value || undefined}\n data-selected={selected || undefined}\n data-disabled={disabled || undefined}\n onMouseDown={(event) => {\n event.preventDefault()\n }}\n onPointerMove={() => {\n if (!disabled && activeValue !== option.value) setActiveValue(option.value)\n }}\n onClick={() => {\n selectOption(option)\n }}\n >\n {multiple ? (\n <span className={styles.box} aria-hidden=\"true\">\n {selected ? <CheckIcon /> : null}\n </span>\n ) : null}\n <span className={styles.optionText}>\n <span className={styles.optionLabel}>{option.label}</span>\n {option.description ? (\n <span className={styles.optionDescription}>{option.description}</span>\n ) : null}\n </span>\n {!multiple && selected ? <CheckIcon className={styles.check} /> : null}\n </div>\n )\n }\n\n return (\n <PopoverPrimitive.Root\n open={expanded}\n onOpenChange={(next) => {\n if (!next) setOpen(false)\n }}\n >\n <PortalAnchorContext.Provider value={boxRef}>\n <PopoverPrimitive.Anchor asChild>\n <div\n ref={boxRef}\n className={cx(control.box, styles.root, className)}\n style={style}\n data-size={size}\n data-multiple={multiple || undefined}\n data-state={expanded ? 'open' : 'closed'}\n data-invalid={field.invalid || undefined}\n data-disabled={field.disabled || undefined}\n data-readonly={field.readOnly || undefined}\n onPointerDown={handleBoxPointerDown}\n onBlur={handleBlur}\n >\n <div className={styles.values}>\n {multiple && values.length > 0 ? (\n <TagList className={styles.chips}>\n {values.map((value) => {\n const label = labelOf(value)\n return (\n <Tag\n key={value}\n className={styles.chip}\n onRemove={\n interactive\n ? () => {\n removeValue(value)\n inputRef.current?.focus()\n }\n : undefined\n }\n removeLabel={removeLabel(label)}\n >\n {label}\n </Tag>\n )\n })}\n </TagList>\n ) : null}\n <input\n ref={composedInputRef}\n id={inputId}\n type=\"text\"\n role=\"combobox\"\n className={styles.input}\n value={query}\n placeholder={showPlaceholder ? placeholder : undefined}\n autoComplete=\"off\"\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n disabled={field.disabled}\n readOnly={field.readOnly}\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n aria-expanded={expanded}\n aria-controls={listboxId}\n aria-activedescendant={activeId}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-describedby={field.describedBy}\n aria-invalid={field.invalid || undefined}\n aria-required={field.required || undefined}\n aria-busy={field.busy || undefined}\n {...rest}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n onClick={handleInputClick}\n />\n </div>\n <span className={styles.trailing}>\n {loading ? <Spinner size=\"sm\" label={null} className={styles.spinner} /> : null}\n {canClear ? (\n <button\n type=\"button\"\n className={styles.clear}\n aria-label={clearLabel}\n onMouseDown={(event) => {\n event.preventDefault()\n }}\n onClick={clear}\n >\n <CloseIcon />\n </button>\n ) : null}\n <ChevronDownIcon className={styles.chevron} />\n </span>\n {name !== undefined ? (\n multiple ? (\n values.map((value) => (\n <input\n key={value}\n type=\"hidden\"\n name={name}\n value={value}\n form={form}\n disabled={field.disabled || undefined}\n />\n ))\n ) : (\n <input\n type=\"hidden\"\n name={name}\n value={values[0] ?? ''}\n form={form}\n disabled={field.disabled || undefined}\n />\n )\n ) : null}\n <div\n id={statusId}\n role=\"status\"\n aria-live=\"polite\"\n className={messageStyles.visuallyHidden}\n >\n {announcement}\n </div>\n </div>\n </PopoverPrimitive.Anchor>\n <PopoverPrimitive.Portal container={expanded ? themeScopeOf(boxRef.current) : undefined}>\n <ComboboxPopup onInteractOutside={handleInteractOutside}>\n <div\n id={listboxId}\n role=\"listbox\"\n aria-labelledby={listLabelledBy}\n aria-label={listLabelledBy ? undefined : ariaLabel}\n aria-multiselectable={multiple || undefined}\n aria-busy={loading || undefined}\n className={styles.listbox}\n >\n {sections.map((section) =>\n section.label === undefined ? (\n section.options.map(renderOption)\n ) : (\n <div\n key={section.key}\n role=\"group\"\n aria-labelledby={`${inputId}-group-${String(sections.indexOf(section))}`}\n className={styles.group}\n >\n <div\n id={`${inputId}-group-${String(sections.indexOf(section))}`}\n role=\"presentation\"\n className={styles.groupLabel}\n >\n {section.label}\n </div>\n {section.options.map(renderOption)}\n </div>\n ),\n )}\n </div>\n {loading && ordered.length === 0 ? (\n <div className={styles.message}>\n <Spinner size=\"sm\" label={null} />\n <span>{loadingMessage}</span>\n </div>\n ) : null}\n {showEmpty ? <div className={styles.message}>{emptyMessage}</div> : null}\n </ComboboxPopup>\n </PopoverPrimitive.Portal>\n </PortalAnchorContext.Provider>\n </PopoverPrimitive.Root>\n )\n }),\n)\n"],"mappings":";;;;;;;;;;;;;;;;AA+GA,SAASO,GAAU,GAAoC,GAAe,GAAuB;CAC3F,IAAMC,IAAUC,IAAeC,EAAcC,GAASC,CAAK,IAAI,CAAC,GAAGD,CAAO,GACpEE,IAAsB,CAAC,GACvBC,oBAAQ,IAAI,IAAqB;CACvC,KAAK,IAAMC,KAAUP,GAAS;EAC5B,IAAMQ,IAAMD,EAAO,UAAU,KAAA,IAAY,KAAK,KAAKA,EAAO,SACtDE,IAAUH,EAAM,IAAIE,CAAG;EAM3B,AALKC,MACH,IAAU;GAAE;GAAK,OAAOF,EAAO;GAAO,SAAS,CAAC;EAAE,GAClDD,EAAM,IAAIE,GAAKC,CAAO,GACtBJ,EAAS,KAAKI,CAAO,IAEvBA,EAAQ,QAAQ,KAAKF,CAAM;CAC7B;CACA,OAAO;EAAE;EAAU,SAASF,EAAS,SAAS,MAAYI,EAAQ,OAAO;CAAE;AAC7E;AAWA,IAAMC,KAAsB,MAAkB,UAAUC;AAGxD,SAASC,GAAU,GAAiD;CAClE,IAAIC,EAAM,aAAa,IAAM;EAC3B,IAAM,EAAE,aAAU,UAAO,iBAAc,kBAAe,gBAAa,gBAAa,GAAGC,OACjFD;EACF,OAAO,CACLC,IACA;GACE;GACA;GACA,cAAcC,KAAgB,CAAC;GAC/B,OAAO,MAASC,IAAgB,CAAC,GAAGC,CAAI,CAAC;GACzC;GACA,aAAaC,KAAeR;EAC9B,CACF;CACF;CACA,IAAM,EAAE,aAAU,UAAO,iBAAc,kBAAe,GAAGI,MAASD;CAClE,OAAO,CACLC,GACA;EACE,UAAU,EAAQK;EAClB,OAAOC,MAAU,KAAA,IAAY,KAAA,IAAYA,MAAU,OAAO,CAAC,IAAI,CAACA,CAAK;EACrE,cAAcL,KAAgB,OAAO,CAAC,IAAI,CAACA,CAAY;EACvD,OAAO,MAASC,IAAgBC,EAAK,MAAM,IAAI;EAC/C,aAAa,KAAA;EACb,aAAaP;CACf,CACF;AACF;AAGA,SAASW,GAAa,GAAmD;CACvE,IAAMC,IAAQC,GAAM,QAAqB,cAAc;CACvD,OAAOD,KAASA,MAAUC,GAAM,cAAc,kBAAkBD,IAAQ,KAAA;AAC1E;AAEA,SAASE,GAAa,GAAuB;CAC3C,OAAO,GAAG,OAAOC,CAAK,EAAE,GAAGA,MAAU,IAAI,WAAW,UAAU;AAChE;AAUA,IAAMC,KAAgBC,EAAuC,SAC3D,EAAE,aAAU,wBACZ,GACA;CACA,IAAMC,IAAQC,GAAe;CAC7B,OACE,kBAACrC,EAAiB,SAAlB;EACO;EACL,WAAWC,EAAO;EAElB,MAAM,KAAA;EACN,MAAK;EACL,OAAM;EACN,YAAY;EACZ,kBAAkB;EAElB,kBAAkB,MAAU;GAC1B,EAAM,eAAe;EACvB;EACA,mBAAmB,MAAU;GAC3B,EAAM,eAAe;EACvB;EAEA,kBAAkB,MAAU;GAC1B,EAAM,eAAe;EACvB;EACmB;EAEnB,cAAc,MAAU;GACtB,EAAM,eAAe;EACvB;EACA,GAAImC;EAEH;CACuB,CAAA;AAE9B,CAAC,GAsBYG,KAAWC,EACtBL,EAA4C,SAAkB,GAAO,IAAK;CACxE,IAAM,CAACb,GAAMmB,KAAQrB,GAAUC,CAAK,GAC9B,EACJ,YACA,YAAYqB,IACZ,uBACA,wBACA,aAAS,QACT,aAAU,IACV,qBAAiB,YACjB,kBAAe,cACf,MAAMC,IACN,kBAAc,IACd,kBACA,eAAY,IACZ,gBAAY,IACZ,iBAAa,SACb,WAAO,MACP,SAASC,IACT,IAAIC,IACJ,UAAUC,IACV,UAAUC,IACV,UAAUC,IACV,SACA,UACA,iBACA,eACA,WACA,eACA,YACA,aACA,oBAAoBC,IACpB,gBAAgBC,IAChB,cAAcC,IACd,mBAAmBC,IACnB,GAAGC,OACD/B,GACE,EAAE,aAAU,iBAAa,oBAAgBmB,GAEzCa,IAAQC,GAAiB;EAC7B,IAAIV;EACJ,aAAaI;EACb,SAASL;EACT;EACA,UAAUG;EACV,UAAUD;EACV,UAAUE;CACZ,CAAC,GACKQ,KAASC,GAAM,GACfC,IAAUJ,EAAM,MAAM,GAAGE,GAAO,WAChCG,KAAY,GAAGD,EAAQ,WACvBE,KAAW,GAAGF,EAAQ,UACtBG,IAAc,CAACP,EAAM,YAAY,CAACA,EAAM,UAExCQ,IAAWC,EAAyB,IAAI,GACxCC,IAASD,EAAuB,IAAI,GACpCE,KAAmBC,EAAcC,IAAKL,CAAQ,GAG9CM,IAAaL,kBAAO,IAAI,IAAoB,CAAC;CACnD,KAAK,IAAMhD,KAAUJ,GAAS,EAAW,QAAQ,IAAII,EAAO,OAAOA,EAAO,KAAK;CAC/E,IAAMsD,IAAUC,GACb,MACC3D,EAAQ,MAAM,MAAWI,EAAO,UAAUa,CAAK,CAAC,EAAE,SAClDwC,EAAW,QAAQ,IAAIxC,CAAK,KAC5BA,GACF,CAACjB,CAAO,CACV,GAEM,CAAC4D,GAAQC,KAAaC,EAC1BhC,EAAK,OACLA,EAAK,cACLA,EAAK,IACP,GACMiC,IAAgB,CAAC/C,KAAY4C,EAAO,OAAO,KAAA,IAAYF,EAAQE,EAAO,EAAE,IAAI,IAE5E,CAAC3D,GAAO+D,MAAiBF,EAC7B/B,IACAkC,OACGjD,KAAYc,EAAK,aAAa,OAAO,KAAA,IAAY,KAAK4B,EAAQ5B,EAAK,aAAa,EAAE,IACrFoC,EACF,GACMC,KAAWf,EAAOnD,CAAK;CAC7B,GAAS,UAAUA;CACnB,IAAMmE,IAAWT,GACd,MAAiB;EAChB,AAAI7C,MAASqD,GAAS,WAASH,GAAclD,CAAI;CACnD,GACA,CAACkD,EAAa,CAChB,GAEM,CAACK,GAAOC,KAAYC,EAAS,EAAK,GAElC,CAACC,GAAWC,MAAgBX,EAChC9B,IACA0C,IACAC,EACF,GACMC,IAAUxB,EAAOoB,CAAS;CAChC,EAAQ,UAAUA;CAClB,IAAMK,IAAUlB,GACb,MAAkB;EACjB,AAAI7C,MAAS8D,EAAQ,WAASH,GAAa3D,CAAI;CACjD,GACA,CAAC2D,EAAY,CACf,GAEM,CAACK,IAAaC,KAAkBR,EAAwB,IAAI;CAIlE,QAAgB;EACd,AAAI,CAACvD,KAAY,CAACqD,KAAOD,EAASL,CAAa;CACjD,GAAG;EAAC/C;EAAUqD;EAAON;EAAeK;CAAQ,CAAC;CAG7C,IAAMtE,KAAekF,OAAW,WAAWhE,KAAYqD,IACjD,EAAE,aAAU,eAAYY,SACtBrF,GAAUI,GAASC,GAAOH,EAAY,GAC5C;EAACE;EAASC;EAAOH;CAAY,CAC/B,GACMoF,KAAUD,SACR,IAAI,IAAIjF,EAAQ,KAAK,GAAQ,MAAU,CAACI,EAAO,OAAO+E,CAAK,CAAC,CAAC,GACnE,CAACnF,CAAO,CACV,GACMoF,MAAY,MAAkB,GAAGrC,EAAQ,UAAU,OAAOmC,GAAQ,IAAIjE,CAAK,KAAK,CAAC,KAEjFoE,KAAQrE,KAAYsE,OAAgB,KAAA,KAAa1B,EAAO,UAAU0B,IAClEC,KAAc,MAAkB3B,EAAO,SAAS3C,CAAK,GACrDuE,KAAc,MAClB,EAAQpF,EAAO,YAAciF,MAAS,CAACE,EAAWnF,EAAO,KAAK,GAC1DqF,IAAUC,EAAQ,QAAQ,MAAW,CAACF,EAAWpF,CAAM,CAAC,GAExDuF,IAAe1F,EAAM,KAAK,GAC1B2F,KAAWC,KAAaF,MAAiB,OAAO3E,KAAYqD,IAC5DyB,KAAY,CAACC,KAAWL,EAAQ,WAAW,KAAK,CAACE,IACjDI,KAAkBN,EAAQ,SAAS,KAAKK,KAAWD,IACnDG,IAAWzB,KAAatB,KAAe8C,IAIvCE,KACJD,KAAY,CAACF,KAAW,CAACF,KAAaF,MAAiB,OAAO3E,KAAYqD,IACtE8B,KACJV,EAAQ,MAAM,MAAWrF,EAAO,UAAU0E,EAAW,MACpDoB,KAAgBT,EAAQ,KAAK,KAAA,IAC1BW,IAASH,IAAWE,KAAe,KAAA,GAGnC,CAACE,IAAcC,MAAmB/B,EAAS,EAAE,GAC7CgC,IAAYR,IACd,KACAL,EAAQ,WAAW,IACjB,OAAOc,KAAiB,WACtBA,IACA,eACFnF,GAAaqE,EAAQ,MAAM;CACjC,QAAgB;EACd,IAAI,CAACO,KAAYM,MAAc,IAAI;GACjC,AAAKN,KAAUK,GAAgB,EAAE;GACjC;EACF;EACA,IAAMG,IAAQ,iBAAiB;GAC7B,GAAgBF,CAAS;EAC3B,GAAG,GAAG;EACN,aAAa;GACX,aAAaE,CAAK;EACpB;CACF,GAAG,CAACR,GAAUM,CAAS,CAAC;CAGxB,IAAMG,IAAWN,IAAShB,GAASgB,EAAO,KAAK,IAAI,KAAA;CACnD,QAAgB;EACd,AAAKM,MACQvD,EAAS,SAAS,cAAc,eAAeuD,CAAQ,EAAA,EAC9D,eAAe,EAAE,OAAO,UAAU,CAAC;CAC3C,GAAG,CAACA,CAAQ,CAAC;CAGb,IAAMC,MAAgB,MAA2B;EAC/C,IAAKzD,KAAe,GAAW9C,CAAM,GAErC;OADAqD,EAAW,QAAQ,IAAIrD,EAAO,OAAOA,EAAO,KAAK,GAC7CY,GAAU;IACZ,IAAMF,IAAOyE,EAAWnF,EAAO,KAAK,IAChCwD,EAAO,QAAQ,MAAU3C,MAAUb,EAAO,KAAK,IAC/C,CAAC,GAAGwD,GAAQxD,EAAO,KAAK;IAI5B,AAHAyD,EAAU/C,CAAI,GACdsD,EAAS,EAAE,GACXE,EAAS,EAAK,GACdS,EAAe3E,EAAO,KAAK;GAC7B,OAKE,AAJAyD,EAAU,CAACzD,EAAO,KAAK,CAAC,GACxBgE,EAAShE,EAAO,KAAK,GACrBkE,EAAS,EAAK,GACdS,EAAe,IAAI,GACnBF,EAAQ,EAAK;EACf;CACF,GAGM+B,UAA4B;EAChC,IAAI,CAACf,KAAaF,MAAiB,IAAI,OAAO;EAC9C,IAAMkB,IAASC,GAASnB,CAAY,GAC9BoB,IAAQ/G,EAAQ,MAAM,MAAW,CAACI,EAAO,YAAY0G,GAAS1G,EAAO,KAAK,MAAMyG,CAAM,GACtF5F,IAAQ8F,GAAO,SAASpB,GACxBnF,IAAQuG,GAAO,SAASpB;EAa9B,OAZAlC,EAAW,QAAQ,IAAIxC,GAAOT,CAAK,GAC/BQ,KACFoD,EAAS,EAAE,GACXE,EAAS,EAAK,GACViB,EAAWtE,CAAK,KAAKoE,KAAc,MACvCxB,EAAU,CAAC,GAAGD,GAAQ3C,CAAK,CAAC,GACrB,QAETqD,EAAS,EAAK,GACdF,EAAS5D,CAAK,GACVoD,EAAO,OAAO3C,MAClB4C,EAAU,CAAC5C,CAAK,CAAC,GACV;CACT,GAEM+F,MAAe,MAAkB;EACrC,AAAK9D,KACLW,EAAUD,EAAO,QAAQ,MAAMqD,MAAMhG,CAAK,CAAC;CAC7C,GAEMiG,WAAc;EAClB,AAAKhE,MACLW,EAAU,CAAC,CAAC,GACZO,EAAS,EAAE,GACXE,EAAS,EAAK,GACdS,EAAe,IAAI,GACnB5B,EAAS,SAAS,MAAM;CAC1B,GAGMgE,MAAiB,MACrB1B,EAAQ,MAAM,MAAWF,EAAWnF,EAAO,KAAK,CAAC,MAChDgH,IAAU3B,EAAQA,EAAQ,SAAS,KAAKA,EAAQ,KAE7C4B,MAAQ,MAAkB;EAC9B,IAAI5B,EAAQ,WAAW,GAAG;EAC1B,IAAMN,IAAQiB,IAASX,EAAQ,QAAQW,CAAM,IAAI,IAC3CtF,IACJqE,MAAU,KACNmC,MAAU,IACR7B,EAAQ,KACRA,EAAQA,EAAQ,SAAS,KAC3BA,GAASN,IAAQmC,IAAQ7B,EAAQ,UAAUA,EAAQ;EACzD,EAAe3E,GAAM,SAAS,IAAI;CACpC,GAEMyG,KAAY,MAAyC;EACzD,AAAKrE,MACL2B,EAAQ,EAAI,GACR2C,MAAc,UAAQzC,EAAeoC,GAAcK,MAAc,MAAM,CAAC,EAAE,SAAS,IAAI;CAC7F,GAGMC,MAAgB,MAAyC;EAC7D,IAAMC,IAAOC,EAAM,OAAO;EAI1B,AAHAvD,EAASsD,CAAI,GACbpD,EAAS,EAAI,GACbS,EAAe,IAAI,GACf7B,KAAa2B,EAAQ,EAAI;CAC/B,GAEM+C,MAAiB,MAA2C;EAEhE,IADAC,KAAYF,CAAK,GACb,GAAM,YAAY,aACtB,QAAQA,EAAM,KAAd;GACE,KAAK;IAEH,AADAA,EAAM,eAAe,GACjBA,EAAM,SAAQJ,EAAS,MAAM,IACxBtB,IAAUoB,GAAK,CAAC,IACpBE,EAAS,OAAO;IACrB;GACF,KAAK;IAEH,AADAI,EAAM,eAAe,GACjBA,EAAM,SAAQ9C,EAAQ,EAAK,IACtBoB,IAAUoB,GAAK,EAAE,IACrBE,EAAS,MAAM;IACpB;GACF,KAAK;GACL,KAAK;IACH,IAAI,CAACtB,KAAYR,EAAQ,WAAW,GAAG;IAEvC,AADAkC,EAAM,eAAe,GACrB5C,GACG4C,EAAM,QAAQ,SAASlC,EAAQ,KAAKA,EAAQA,EAAQ,SAAS,GAAA,EAAK,SAAS,IAC9E;IACA;GACF,KAAK;IACH,AAAIQ,KAAYG,KACduB,EAAM,eAAe,GACrBhB,GAAaP,CAAM,KACVR,MACT+B,EAAM,eAAe,GACrBf,EAAW,GACN5F,KAAU6D,EAAQ,EAAK,KACnBoB,KACT0B,EAAM,eAAe;IAEvB;GACF,KAAK;IACH,AAAI1B,KACF0B,EAAM,eAAe,GACrB9C,EAAQ,EAAK,KACJ5E,MAAU,MAAMiD,MACzByE,EAAM,eAAe,GACrBvD,EAAS,EAAE,GACXE,EAAS,CAACtD,CAAQ;IAEpB;GACF,KAAK;IACH,EAAQ,EAAK;IACb;GACF,KAAK;IACH,AAAIA,KAAYf,MAAU,MAAMiD,KAAeU,EAAO,SAAS,MAC7D+D,EAAM,eAAe,GACrB9D,EAAUD,EAAO,MAAM,GAAG,EAAE,CAAC;IAE/B;EACJ;CACF,GAGMkE,MAAc,MAAsC;EACxD,IAAMhH,IAAO6G,EAAM;EACnB,AAAI7G,KAAQuC,EAAO,SAAS,SAASvC,CAAI,MACrCoC,MACElC,IACG4F,EAAW,KAAGxC,EAAS,EAAE,IACrBC,MACLwB,KAAaF,MAAiB,KAAIiB,EAAW,IACxCjB,MAAiB,MACpB/B,EAAO,SAAS,KAAGC,EAAU,CAAC,CAAC,GACnCO,EAAS,EAAE,KACNA,EAASL,CAAa,IAE/BO,EAAS,EAAK,IAEhBO,EAAQ,EAAK,GACbE,EAAe,IAAI,GACnBgD,KAASJ,CAAK;CAChB,GAGMK,MAAwB,MAAwC;EACpE,IAAMC,IAASN,EAAM;EACrB,AAAIM,MAAW9E,EAAS,WAAW8E,EAAO,QAAQ,kBAAkB,MACpEN,EAAM,eAAe,GACrBxE,EAAS,SAAS,MAAM,GACpByB,EAAQ,UAASC,EAAQ,EAAK,IAC7B0C,EAAS,MAAM;CACtB,GAEMW,MAAoB,MAAwC;EAEhE,AADAC,KAAUR,CAAK,GACV/C,EAAQ,WAAS2C,EAAS,MAAM;CACvC,GAEMa,MAAyB,MAAiB;EAC9C,IAAMH,IAASN,EAAM;EACrB,AAAIM,KAAU5E,EAAO,SAAS,SAAS4E,CAAM,KAAGN,EAAM,eAAe;CACvE,GAGMU,KAAiB5F,MAAkBE,EAAM,SACzC2F,KAAkB,CAACtH,KAAY4C,EAAO,WAAW,GACjD2E,KAAWC,MAAatF,MAAgBU,EAAO,SAAS,KAAK3D,MAAU,KAEvEwI,MAAgB,MAA2B;EAC/C,IAAMC,IAAWnD,EAAWnF,EAAO,KAAK,GAClCuI,IAAWnD,EAAWpF,CAAM;EAClC,OAIE,kBAAC,OAAD;GAEE,IAAIgF,GAAShF,EAAO,KAAK;GACzB,MAAK;GACL,iBAAesI;GACf,iBAAeC,KAAY,KAAA;GAC3B,WAAWrJ,EAAO;GAClB,eAAa8G,GAAQ,UAAUhG,EAAO,SAAS,KAAA;GAC/C,iBAAesI,KAAY,KAAA;GAC3B,iBAAeC,KAAY,KAAA;GAC3B,cAAc,MAAU;IACtB,EAAM,eAAe;GACvB;GACA,qBAAqB;IACnB,AAAI,CAACA,KAAY7D,OAAgB1E,EAAO,SAAO2E,EAAe3E,EAAO,KAAK;GAC5E;GACA,eAAe;IACb,GAAaA,CAAM;GACrB;GAlBF,UAAA;IAoBGY,IACC,kBAAC,QAAD;KAAM,WAAW1B,EAAO;KAAK,eAAY;KACtC,UAAAoJ,IAAW,kBAACE,GAAD,CAAY,CAAA,IAAI;IACxB,CAAA,IACJ;IACJ,kBAAC,QAAD;KAAM,WAAWtJ,EAAO;KAAxB,UAAA,CACE,kBAAC,QAAD;MAAM,WAAWA,EAAO;MAAc,UAAAc,EAAO;KAAY,CAAA,GACxDA,EAAO,cACN,kBAAC,QAAD;MAAM,WAAWd,EAAO;MAAoB,UAAAc,EAAO;KAAkB,CAAA,IACnE,IACA;;IACL,CAACY,KAAY0H,IAAW,kBAACE,GAAD,EAAW,WAAWtJ,EAAO,MAAQ,CAAA,IAAI;GAC/D;EA/BE,GAAAc,EAAO,KA+BT;CAET;CAEA,OACE,kBAACf,EAAiB,MAAlB;EACE,MAAM4G;EACN,eAAe,MAAS;GACtB,AAAKnF,KAAM+D,EAAQ,EAAK;EAC1B;EAEA,UAAA,kBAACgE,GAAoB,UAArB;GAA8B,OAAOxF;GAArC,UAAA,CACE,kBAAChE,EAAiB,QAAlB;IAAyB,SAAA;IACvB,UAAA,kBAAC,OAAD;KACE,KAAKgE;KACL,WAAWyF,EAAGvJ,GAAQ,KAAKD,EAAO,MAAMyJ,EAAS;KAC1C;KACP,aAAWC;KACX,iBAAehI,KAAY,KAAA;KAC3B,cAAYiF,IAAW,SAAS;KAChC,gBAActD,EAAM,WAAW,KAAA;KAC/B,iBAAeA,EAAM,YAAY,KAAA;KACjC,iBAAeA,EAAM,YAAY,KAAA;KACjC,eAAeqF;KACf,QAAQF;KAXV,UAAA;MAaE,kBAAC,OAAD;OAAK,WAAWxI,EAAO;OAAvB,UAAA,CACG0B,KAAY4C,EAAO,SAAS,IAC3B,kBAACqF,IAAD;QAAS,WAAW3J,EAAO;QACxB,UAAAsE,EAAO,KAAK,MAAU;SACrB,IAAMpD,IAAQkD,EAAQzC,CAAK;SAC3B,OACE,kBAACiI,IAAD;UAEE,WAAW5J,EAAO;UAClB,UACE4D,UACU;WAEJ,AADA8D,GAAY/F,CAAK,GACjBkC,EAAS,SAAS,MAAM;UAC1B,IACA,KAAA;UAEN,aAAapC,GAAYP,CAAK;UAE7B,UAAAA;SACE,GAbES,CAaF;QAET,CAAC;OACM,CAAA,IACP,MACJ,kBAAC,SAAD;QACE,KAAKqC;QACL,IAAIP;QACJ,MAAK;QACL,MAAK;QACL,WAAWzD,EAAO;QAClB,OAAOW;QACP,aAAaqI,KAAkBa,KAAc,KAAA;QAC7C,cAAa;QACb,gBAAe;QACf,aAAY;QACZ,YAAY;QACZ,UAAUxG,EAAM;QAChB,UAAUA,EAAM;QAChB,qBAAkB;QAClB,iBAAc;QACd,iBAAesD;QACf,iBAAejD;QACf,yBAAuB0D;QACvB,cAAYlE;QACZ,mBAAiBC;QACjB,oBAAkBE,EAAM;QACxB,gBAAcA,EAAM,WAAW,KAAA;QAC/B,iBAAeA,EAAM,YAAY,KAAA;QACjC,aAAWA,EAAM,QAAQ,KAAA;QACzB,GAAID;QACJ,UAAU+E;QACV,WAAWG;QACX,SAASM;OACV,CAAA,CACE;;MACL,kBAAC,QAAD;OAAM,WAAW5I,EAAO;OAAxB,UAAA;QACGyG,IAAU,kBAACqD,GAAD;SAAS,MAAK;SAAK,OAAO;SAAM,WAAW9J,EAAO;QAAU,CAAA,IAAI;QAC1EiJ,KACC,kBAAC,UAAD;SACE,MAAK;SACL,WAAWjJ,EAAO;SAClB,cAAY+J;SACZ,cAAc,MAAU;UACtB,EAAM,eAAe;SACvB;SACA,SAASnC;SAET,UAAA,kBAACoC,GAAD,CAAY,CAAA;QACN,CAAA,IACN;QACJ,kBAACC,GAAD,EAAiB,WAAWjK,EAAO,QAAU,CAAA;OACzC;;MACLkK,MAAS,KAAA,IAqBN,OApBFxI,IACE4C,EAAO,KAAK,MACV,kBAAC,SAAD;OAEE,MAAK;OACC;OACC;OACD;OACN,UAAUjB,EAAM,YAAY,KAAA;MAC7B,GANM1B,CAMN,CACF,IAED,kBAAC,SAAD;OACE,MAAK;OACC;OACN,OAAO2C,EAAO,MAAM;OACd;OACN,UAAUjB,EAAM,YAAY,KAAA;MAC7B,CAAA;MAGL,kBAAC,OAAD;OACE,IAAIM;OACJ,MAAK;OACL,aAAU;OACV,WAAWzD,GAAc;OAExB,UAAA6G;MACE,CAAA;KACF;;GACkB,CAAA,GACzB,kBAAChH,EAAiB,QAAlB;IAAyB,WAAW4G,IAAW/E,GAAamC,EAAO,OAAO,IAAI,KAAA;IAC5E,UAAA,kBAAC9B,IAAD;KAAe,mBAAmB6G;KAAlC,UAAA;MACE,kBAAC,OAAD;OACE,IAAIpF;OACJ,MAAK;OACL,mBAAiBqF;OACjB,cAAYA,KAAiB,KAAA,IAAY7F;OACzC,wBAAsBxB,KAAY,KAAA;OAClC,aAAW+E,KAAW,KAAA;OACtB,WAAWzG,EAAO;OAEjB,UAAAY,EAAS,KAAK,MACbI,EAAQ,UAAU,KAAA,IAChBA,EAAQ,QAAQ,IAAImI,EAAY,IAEhC,kBAAC,OAAD;QAEE,MAAK;QACL,mBAAiB,GAAG1F,EAAQ,SAAS,OAAO7C,EAAS,QAAQI,CAAO,CAAC;QACrE,WAAWhB,EAAO;QAJpB,UAAA,CAME,kBAAC,OAAD;SACE,IAAI,GAAGyD,EAAQ,SAAS,OAAO7C,EAAS,QAAQI,CAAO,CAAC;SACxD,MAAK;SACL,WAAWhB,EAAO;SAEjB,UAAAgB,EAAQ;QACN,CAAA,GACJA,EAAQ,QAAQ,IAAImI,EAAY,CAC9B;OAbE,GAAAnI,EAAQ,GAaV,CAET;MACG,CAAA;MACJyF,KAAWL,EAAQ,WAAW,IAC7B,kBAAC,OAAD;OAAK,WAAWpG,EAAO;OAAvB,UAAA,CACE,kBAAC8J,GAAD;QAAS,MAAK;QAAK,OAAO;OAAO,CAAA,GACjC,kBAAC,QAAD,EAAA,UAAOK,GAAqB,CAAA,CACzB;MACH,CAAA,IAAA;MACH3D,KAAY,kBAAC,OAAD;OAAK,WAAWxG,EAAO;OAAU,UAAAkH;MAAkB,CAAA,IAAI;KACvD;;GACQ,CAAA,CACG;;CACT,CAAA;AAE3B,CAAC,CACH"}
|
|
1
|
+
{"version":3,"file":"Combobox.js","names":["PopoverPrimitive","styles","control","messageStyles","messages_module_default","control_module_default","Combobox_module_default","buildView","matched","shouldFilter","filterOptions","options","query","sections","groupOptions","section","defaultRemoveLabel","label","splitMode","props","base","defaultValue","onValueChange","next","removeLabel","multiple","value","themeScopeOf","scope","node","countMessage","count","ComboboxPopup","forwardRef","theme","usePortalTheme","Popover","Combobox","markFieldAware","mode","inputValueProp","openProp","invalidProp","idProp","disabledProp","requiredProp","readOnlyProp","describedByProp","ariaInvalid","ariaLabel","ariaLabelledBy","rest","field","useResolvedField","autoId","useId","inputId","listboxId","statusId","interactive","inputRef","useRef","boxRef","composedInputRef","useMergedRefs","ref","labelCache","option","labelOf","useCallback","values","setValues","useControllableState","selectedLabel","setQueryState","defaultInputValue","onInputValueChange","queryRef","setQuery","dirty","setDirty","useState","openState","setOpenState","defaultOpen","onOpenChange","openRef","setOpen","activeValue","setActiveValue","filter","useMemo","indexOf","index","optionId","atMax","maxSelected","isSelected","isDisabled","enabled","ordered","trimmedQuery","freeText","creatable","showEmpty","loading","hasPopupContent","expanded","autoHighlight","activeOption","active","announcement","setAnnouncement","countText","emptyMessage","timer","activeId","selectOption","commitText","folded","foldText","match","removeValue","v","clear","initialActive","fromEnd","move","delta","openList","highlight","handleChange","text","event","handleKeyDown","onKeyDown","handleBlur","onBlur","handleBoxPointerDown","target","handleInputClick","onClick","handleInteractOutside","listLabelledBy","showPlaceholder","canClear","clearable","renderOption","selected","disabled","CheckIcon","PortalAnchorContext","cx","className","size","TagList","Tag","placeholder","Spinner","clearLabel","CloseIcon","ChevronDownIcon","name","loadingMessage"],"sources":["../../../../src/components/inputs/Combobox/Combobox.tsx"],"sourcesContent":["import {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type FocusEvent,\n type FocusEventHandler,\n type InputHTMLAttributes,\n type KeyboardEvent,\n type MouseEvent,\n type PointerEvent,\n type ReactNode,\n} from 'react'\nimport { Popover as PopoverPrimitive } from 'radix-ui'\nimport { CheckIcon, ChevronDownIcon, CloseIcon } from '#icons'\nimport { cx } from '#utils/cx'\nimport type { Size } from '#utils/tokens'\nimport { Spinner } from '#components/feedback/Spinner'\nimport { Tag, TagList } from '#components/display/Tag'\nimport { PortalAnchorContext, usePortalTheme } from '#components/overlays/usePortalTheme'\nimport { markFieldAware, useResolvedField } from '#components/inputs/internal/FieldContext'\nimport { filterOptions, foldText, groupOptions } from '#components/inputs/internal/filterOptions'\nimport { useMergedRefs } from '#components/inputs/internal/refs'\nimport control from '#components/inputs/internal/control.module.css'\nimport messageStyles from '#components/inputs/internal/messages.module.css'\nimport { useControllableState } from './useControllableState'\nimport styles from './Combobox.module.css'\n\nexport interface ComboboxOption {\n value: string\n label: string\n /** A second, quieter line under the label. Also searched. */\n description?: string\n /** Extra search terms that aren't shown (\"USA\", \"Holland\"). An exact keyword ranks first. */\n keywords?: readonly string[]\n /** Heading the option is listed under. Groups appear in order of their first option. */\n group?: string\n disabled?: boolean\n}\n\nexport interface ComboboxBase extends Omit<\n InputHTMLAttributes<HTMLInputElement>,\n 'value' | 'defaultValue' | 'onChange' | 'size' | 'type' | 'multiple' | 'onBlur'\n> {\n options: readonly ComboboxOption[]\n /** The text in the box (the query). Controlled. */\n inputValue?: string\n defaultInputValue?: string\n onInputValueChange?: (query: string) => void\n /**\n * `auto` (default) filters and ranks `options` by the query. `none` shows `options` as\n * given — for async search, where the loader has already filtered.\n */\n filter?: 'auto' | 'none'\n /** Options are being fetched: a spinner in the box and `loadingMessage` in an empty list. */\n loading?: boolean\n loadingMessage?: ReactNode\n /** Shown in the list when nothing matches. Default \"No matches\". */\n emptyMessage?: ReactNode\n open?: boolean\n defaultOpen?: boolean\n onOpenChange?: (open: boolean) => void\n /**\n * Free text is allowed: whatever is typed becomes the value when committed (Enter, or\n * leaving the field). A typed label that matches an option picks that option instead.\n */\n creatable?: boolean\n /** Shows a clear button while there's a value. */\n clearable?: boolean\n /** Accessible name of the clear button. Default \"Clear\". */\n clearLabel?: string\n size?: Size\n /** Critical border + `aria-invalid`. Inside a `<Field error>` this is set for you. */\n invalid?: boolean\n /** Fires once focus leaves the whole control (input, chips, clear button, list). */\n onBlur?: FocusEventHandler<HTMLElement>\n}\n\nexport interface ComboboxSingleProps extends ComboboxBase {\n multiple?: false\n value?: string | null\n defaultValue?: string | null\n onValueChange?: (value: string | null) => void\n}\n\nexport interface ComboboxMultipleProps extends ComboboxBase {\n multiple: true\n value?: readonly string[]\n defaultValue?: readonly string[]\n onValueChange?: (value: string[]) => void\n /** Once this many are chosen, the rest of the list is disabled. */\n maxSelected?: number\n /** Accessible name of a chip's remove button. Default `Remove <label>`. */\n removeLabel?: (label: string) => string\n}\n\nexport type ComboboxProps = ComboboxSingleProps | ComboboxMultipleProps\n\n/* ─── Pure helpers ────────────────────────────────────────────────────────── */\n\n/** Visible options, in groups (ordered by each group's first/best option), and flattened. */\nfunction buildView(options: readonly ComboboxOption[], query: string, shouldFilter: boolean) {\n const matched = shouldFilter ? filterOptions(options, query) : [...options]\n const sections = groupOptions(matched)\n return { sections, ordered: sections.flatMap((section) => section.options) }\n}\n\ninterface ModeProps {\n multiple: boolean\n value: readonly string[] | undefined\n defaultValue: readonly string[]\n emit: (next: readonly string[]) => void\n maxSelected: number | undefined\n removeLabel: (label: string) => string\n}\n\nconst defaultRemoveLabel = (label: string) => `Remove ${label}`\n\n/** Splits the single/multiple union into one normalised shape (values are always arrays). */\nfunction splitMode(props: ComboboxProps): [ComboboxBase, ModeProps] {\n if (props.multiple === true) {\n const { multiple, value, defaultValue, onValueChange, maxSelected, removeLabel, ...base } =\n props\n return [\n base,\n {\n multiple,\n value,\n defaultValue: defaultValue ?? [],\n emit: (next) => onValueChange?.([...next]),\n maxSelected,\n removeLabel: removeLabel ?? defaultRemoveLabel,\n },\n ]\n }\n const { multiple, value, defaultValue, onValueChange, ...base } = props\n return [\n base,\n {\n multiple: Boolean(multiple),\n value: value === undefined ? undefined : value === null ? [] : [value],\n defaultValue: defaultValue == null ? [] : [defaultValue],\n emit: (next) => onValueChange?.(next[0] ?? null),\n maxSelected: undefined,\n removeLabel: defaultRemoveLabel,\n },\n ]\n}\n\n/** The nearest theme scope below `<html>` — the portal target, so the list opens in that theme. */\nfunction themeScopeOf(node: HTMLElement | null): HTMLElement | undefined {\n const scope = node?.closest<HTMLElement>('[data-theme]')\n return scope && scope !== node?.ownerDocument.documentElement ? scope : undefined\n}\n\nfunction countMessage(count: number): string {\n return `${String(count)} ${count === 1 ? 'option' : 'options'} available`\n}\n\n/* ─── Popup (mounts on open, so it reads the theme at open time) ─────────── */\n\ninterface PopupProps {\n children: ReactNode\n onInteractOutside: (event: Event) => void\n}\n\n// forwardRef: Radix Presence hands the popup a ref (React 18 warns without it).\nconst ComboboxPopup = forwardRef<HTMLDivElement, PopupProps>(function ComboboxPopup(\n { children, onInteractOutside },\n ref,\n) {\n const theme = usePortalTheme()\n return (\n <PopoverPrimitive.Content\n ref={ref}\n className={styles.popup}\n // A wrapper, not a dialog: the listbox inside carries the semantics.\n role={undefined}\n side=\"bottom\"\n align=\"start\"\n sideOffset={6}\n collisionPadding={8}\n // Focus never leaves the input (ARIA combobox): no auto-focus in or back.\n onOpenAutoFocus={(event) => {\n event.preventDefault()\n }}\n onCloseAutoFocus={(event) => {\n event.preventDefault()\n }}\n // The input's own keydown handles Escape (close, then clear).\n onEscapeKeyDown={(event) => {\n event.preventDefault()\n }}\n onInteractOutside={onInteractOutside}\n // Clicks on padding / messages must not take focus from the input.\n onMouseDown={(event) => {\n event.preventDefault()\n }}\n {...theme}\n >\n {children}\n </PopoverPrimitive.Content>\n )\n})\n\n/* ─── Combobox ────────────────────────────────────────────────────────────── */\n\n/**\n * Type to filter and pick from a list. Single or multiple, free text if you allow it, ready for\n * async options.\n *\n * @remarks\n * `Combobox` is an ARIA 1.2 combobox: a text input that filters a listbox as you type. With\n * `multiple`, chosen values become removable chips in the box. With `creatable`, typed text that\n * matches nothing can be added as a value.\n *\n * @privateRemarks\n * Type to filter, pick from a list (ARIA 1.2 combobox with a listbox popup). Single or\n * `multiple` (chosen values become removable chips), `creatable` for free text, and\n * async-ready: pass `filter=\"none\"`, `loading` and the loader's results as `options`.\n * The ref and native input props go to the text input; `className`/`style` go to the box.\n *\n * <Combobox options={projects} placeholder=\"Search projects\" onValueChange={setProject} />\n * <Combobox multiple options={labels} maxSelected={3} />\n */\nexport const Combobox = markFieldAware(\n forwardRef<HTMLInputElement, ComboboxProps>(function Combobox(props, ref) {\n const [base, mode] = splitMode(props)\n const {\n options,\n inputValue: inputValueProp,\n defaultInputValue,\n onInputValueChange,\n filter = 'auto',\n loading = false,\n loadingMessage = 'Loading…',\n emptyMessage = 'No matches',\n open: openProp,\n defaultOpen = false,\n onOpenChange,\n creatable = false,\n clearable = false,\n clearLabel = 'Clear',\n size = 'md',\n invalid: invalidProp,\n id: idProp,\n disabled: disabledProp,\n required: requiredProp,\n readOnly: readOnlyProp,\n name,\n form,\n placeholder,\n className,\n style,\n onKeyDown,\n onBlur,\n onClick,\n 'aria-describedby': describedByProp,\n 'aria-invalid': ariaInvalid,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n ...rest\n } = base\n const { multiple, maxSelected, removeLabel } = mode\n\n const field = useResolvedField({\n id: idProp,\n describedBy: describedByProp,\n invalid: invalidProp,\n ariaInvalid,\n required: requiredProp,\n disabled: disabledProp,\n readOnly: readOnlyProp,\n })\n const autoId = useId()\n const inputId = field.id ?? `${autoId}combobox`\n const listboxId = `${inputId}-listbox`\n const statusId = `${inputId}-status`\n const interactive = !field.disabled && !field.readOnly\n\n const inputRef = useRef<HTMLInputElement>(null)\n const boxRef = useRef<HTMLDivElement>(null)\n const composedInputRef = useMergedRefs(ref, inputRef)\n\n /* Labels of chosen values survive the options changing (async results, creatable). */\n const labelCache = useRef(new Map<string, string>())\n for (const option of options) labelCache.current.set(option.value, option.label)\n const labelOf = useCallback(\n (value: string) =>\n options.find((option) => option.value === value)?.label ??\n labelCache.current.get(value) ??\n value,\n [options],\n )\n\n const [values, setValues] = useControllableState<readonly string[]>(\n mode.value,\n mode.defaultValue,\n mode.emit,\n )\n const selectedLabel = !multiple && values[0] !== undefined ? labelOf(values[0]) : ''\n\n const [query, setQueryState] = useControllableState<string>(\n inputValueProp,\n defaultInputValue ??\n (multiple || mode.defaultValue[0] === undefined ? '' : labelOf(mode.defaultValue[0])),\n onInputValueChange,\n )\n const queryRef = useRef(query)\n queryRef.current = query\n const setQuery = useCallback(\n (next: string) => {\n if (next !== queryRef.current) setQueryState(next)\n },\n [setQueryState],\n )\n /** The user has typed since the last pick (single: the text is a query, not the label). */\n const [dirty, setDirty] = useState(false)\n\n const [openState, setOpenState] = useControllableState<boolean>(\n openProp,\n defaultOpen,\n onOpenChange,\n )\n const openRef = useRef(openState)\n openRef.current = openState\n const setOpen = useCallback(\n (next: boolean) => {\n if (next !== openRef.current) setOpenState(next)\n },\n [setOpenState],\n )\n\n const [activeValue, setActiveValue] = useState<string | null>(null)\n\n // Single: show the chosen option's label whenever the user isn't mid-edit (covers\n // external value changes such as a form reset).\n useEffect(() => {\n if (!multiple && !dirty) setQuery(selectedLabel)\n }, [multiple, dirty, selectedLabel, setQuery])\n\n /* ─── Derived view ─── */\n const shouldFilter = filter === 'auto' && (multiple || dirty)\n const { sections, ordered } = useMemo(\n () => buildView(options, query, shouldFilter),\n [options, query, shouldFilter],\n )\n const indexOf = useMemo(\n () => new Map(options.map((option, index) => [option.value, index])),\n [options],\n )\n const optionId = (value: string) => `${inputId}-option-${String(indexOf.get(value) ?? 0)}`\n\n const atMax = multiple && maxSelected !== undefined && values.length >= maxSelected\n const isSelected = (value: string) => values.includes(value)\n const isDisabled = (option: ComboboxOption) =>\n Boolean(option.disabled) || (atMax && !isSelected(option.value))\n const enabled = ordered.filter((option) => !isDisabled(option))\n\n const trimmedQuery = query.trim()\n const freeText = creatable && trimmedQuery !== '' && (multiple || dirty)\n const showEmpty = !loading && ordered.length === 0 && !freeText\n const hasPopupContent = ordered.length > 0 || loading || showEmpty\n const expanded = openState && interactive && hasPopupContent\n\n // Non-creatable: typing highlights the best match, so Enter picks it. Not while loading:\n // the list still shows the previous query's results, and Enter must not commit one of them.\n const autoHighlight =\n expanded && !loading && !creatable && trimmedQuery !== '' && (multiple || dirty)\n const activeOption =\n enabled.find((option) => option.value === activeValue) ??\n (autoHighlight ? enabled[0] : undefined)\n const active = expanded ? activeOption : undefined\n\n /* ─── Live region: result count, debounced ─── */\n const [announcement, setAnnouncement] = useState('')\n const countText = loading\n ? ''\n : ordered.length === 0\n ? typeof emptyMessage === 'string'\n ? emptyMessage\n : 'No matches'\n : countMessage(ordered.length)\n useEffect(() => {\n if (!expanded || countText === '') {\n if (!expanded) setAnnouncement('')\n return\n }\n const timer = setTimeout(() => {\n setAnnouncement(countText)\n }, 500)\n return () => {\n clearTimeout(timer)\n }\n }, [expanded, countText])\n\n /* Keep the highlighted row in view. */\n const activeId = active ? optionId(active.value) : undefined\n useEffect(() => {\n if (!activeId) return\n const node = inputRef.current?.ownerDocument.getElementById(activeId)\n node?.scrollIntoView({ block: 'nearest' })\n }, [activeId])\n\n /* ─── Actions ─── */\n const selectOption = (option: ComboboxOption) => {\n if (!interactive || isDisabled(option)) return\n labelCache.current.set(option.value, option.label)\n if (multiple) {\n const next = isSelected(option.value)\n ? values.filter((value) => value !== option.value)\n : [...values, option.value]\n setValues(next)\n setQuery('')\n setDirty(false)\n setActiveValue(option.value)\n } else {\n setValues([option.value])\n setQuery(option.label)\n setDirty(false)\n setActiveValue(null)\n setOpen(false)\n }\n }\n\n /** Creatable: turn the typed text into a value. Returns whether anything changed. */\n const commitText = (): boolean => {\n if (!creatable || trimmedQuery === '') return false\n const folded = foldText(trimmedQuery)\n const match = options.find((option) => !option.disabled && foldText(option.label) === folded)\n const value = match?.value ?? trimmedQuery\n const label = match?.label ?? trimmedQuery\n labelCache.current.set(value, label)\n if (multiple) {\n setQuery('')\n setDirty(false)\n if (isSelected(value) || atMax) return false\n setValues([...values, value])\n return true\n }\n setDirty(false)\n setQuery(label)\n if (values[0] === value) return false\n setValues([value])\n return true\n }\n\n const removeValue = (value: string) => {\n if (!interactive) return\n setValues(values.filter((v) => v !== value))\n }\n\n const clear = () => {\n if (!interactive) return\n setValues([])\n setQuery('')\n setDirty(false)\n setActiveValue(null)\n inputRef.current?.focus()\n }\n\n /** First visible selected option, else the first/last enabled one. */\n const initialActive = (fromEnd: boolean) =>\n enabled.find((option) => isSelected(option.value)) ??\n (fromEnd ? enabled[enabled.length - 1] : enabled[0])\n\n const move = (delta: 1 | -1) => {\n if (enabled.length === 0) return\n const index = active ? enabled.indexOf(active) : -1\n const next =\n index === -1\n ? delta === 1\n ? enabled[0]\n : enabled[enabled.length - 1]\n : enabled[(index + delta + enabled.length) % enabled.length]\n setActiveValue(next?.value ?? null)\n }\n\n const openList = (highlight: 'first' | 'last' | 'keep') => {\n if (!interactive) return\n setOpen(true)\n if (highlight !== 'keep') setActiveValue(initialActive(highlight === 'last')?.value ?? null)\n }\n\n /* ─── Events ─── */\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\n const text = event.target.value\n setQuery(text)\n setDirty(true)\n setActiveValue(null)\n if (interactive) setOpen(true)\n }\n\n const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\n onKeyDown?.(event)\n if (event.nativeEvent.isComposing) return\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault()\n if (event.altKey) openList('keep')\n else if (expanded) move(1)\n else openList('first')\n return\n case 'ArrowUp':\n event.preventDefault()\n if (event.altKey) setOpen(false)\n else if (expanded) move(-1)\n else openList('last')\n return\n case 'Home':\n case 'End':\n if (!expanded || enabled.length === 0) return\n event.preventDefault()\n setActiveValue(\n (event.key === 'Home' ? enabled[0] : enabled[enabled.length - 1])?.value ?? null,\n )\n return\n case 'Enter':\n if (expanded && active) {\n event.preventDefault()\n selectOption(active)\n } else if (freeText) {\n event.preventDefault()\n commitText()\n if (!multiple) setOpen(false)\n } else if (expanded) {\n event.preventDefault()\n }\n return\n case 'Escape':\n if (expanded) {\n event.preventDefault()\n setOpen(false)\n } else if (query !== '' && interactive) {\n event.preventDefault()\n setQuery('')\n setDirty(!multiple)\n }\n return\n case 'Tab':\n setOpen(false)\n return\n case 'Backspace':\n if (multiple && query === '' && interactive && values.length > 0) {\n event.preventDefault()\n setValues(values.slice(0, -1))\n }\n return\n }\n }\n\n /** Focus left the whole control: settle the text, close, then tell the consumer. */\n const handleBlur = (event: FocusEvent<HTMLDivElement>) => {\n const next = event.relatedTarget as Node | null\n if (next && boxRef.current?.contains(next)) return\n if (interactive) {\n if (multiple) {\n if (!commitText()) setQuery('')\n } else if (dirty) {\n if (creatable && trimmedQuery !== '') commitText()\n else if (trimmedQuery === '') {\n if (values.length > 0) setValues([])\n setQuery('')\n } else setQuery(selectedLabel)\n }\n setDirty(false)\n }\n setOpen(false)\n setActiveValue(null)\n onBlur?.(event)\n }\n\n // Clicking the box's padding or chevron focuses the input and toggles the list.\n const handleBoxPointerDown = (event: PointerEvent<HTMLDivElement>) => {\n const target = event.target as HTMLElement\n if (target === inputRef.current || target.closest('button, a, input')) return\n event.preventDefault()\n inputRef.current?.focus()\n if (openRef.current) setOpen(false)\n else openList('keep')\n }\n\n const handleInputClick = (event: MouseEvent<HTMLInputElement>) => {\n onClick?.(event)\n if (!openRef.current) openList('keep')\n }\n\n const handleInteractOutside = (event: Event) => {\n const target = event.target as Node | null\n if (target && boxRef.current?.contains(target)) event.preventDefault()\n }\n\n /* ─── Render ─── */\n const listLabelledBy = ariaLabelledBy ?? field.labelId\n const showPlaceholder = !multiple || values.length === 0\n const canClear = clearable && interactive && (values.length > 0 || query !== '')\n\n const renderOption = (option: ComboboxOption) => {\n const selected = isSelected(option.value)\n const disabled = isDisabled(option)\n return (\n // The input owns focus and the keyboard (aria-activedescendant points here), so an\n // option is never focused itself and its click is the pointer path only.\n // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/interactive-supports-focus\n <div\n key={option.value}\n id={optionId(option.value)}\n role=\"option\"\n aria-selected={selected}\n aria-disabled={disabled || undefined}\n className={styles.option}\n data-active={active?.value === option.value || undefined}\n data-selected={selected || undefined}\n data-disabled={disabled || undefined}\n onMouseDown={(event) => {\n event.preventDefault()\n }}\n onPointerMove={() => {\n if (!disabled && activeValue !== option.value) setActiveValue(option.value)\n }}\n onClick={() => {\n selectOption(option)\n }}\n >\n {multiple ? (\n <span className={styles.box} aria-hidden=\"true\">\n {selected ? <CheckIcon /> : null}\n </span>\n ) : null}\n <span className={styles.optionText}>\n <span className={styles.optionLabel}>{option.label}</span>\n {option.description ? (\n <span className={styles.optionDescription}>{option.description}</span>\n ) : null}\n </span>\n {!multiple && selected ? <CheckIcon className={styles.check} /> : null}\n </div>\n )\n }\n\n return (\n <PopoverPrimitive.Root\n open={expanded}\n onOpenChange={(next) => {\n if (!next) setOpen(false)\n }}\n >\n <PortalAnchorContext.Provider value={boxRef}>\n <PopoverPrimitive.Anchor asChild>\n <div\n ref={boxRef}\n className={cx(control.box, styles.root, className)}\n style={style}\n data-size={size}\n data-multiple={multiple || undefined}\n data-state={expanded ? 'open' : 'closed'}\n data-invalid={field.invalid || undefined}\n data-disabled={field.disabled || undefined}\n data-readonly={field.readOnly || undefined}\n onPointerDown={handleBoxPointerDown}\n onBlur={handleBlur}\n >\n <div className={styles.values}>\n {multiple && values.length > 0 ? (\n <TagList className={styles.chips}>\n {values.map((value) => {\n const label = labelOf(value)\n return (\n <Tag\n key={value}\n className={styles.chip}\n onRemove={\n interactive\n ? () => {\n removeValue(value)\n inputRef.current?.focus()\n }\n : undefined\n }\n removeLabel={removeLabel(label)}\n >\n {label}\n </Tag>\n )\n })}\n </TagList>\n ) : null}\n <input\n ref={composedInputRef}\n id={inputId}\n type=\"text\"\n role=\"combobox\"\n className={styles.input}\n value={query}\n placeholder={showPlaceholder ? placeholder : undefined}\n autoComplete=\"off\"\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n disabled={field.disabled}\n readOnly={field.readOnly}\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n aria-expanded={expanded}\n aria-controls={listboxId}\n aria-activedescendant={activeId}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-describedby={field.describedBy}\n aria-invalid={field.invalid || undefined}\n aria-required={field.required || undefined}\n aria-busy={field.busy || undefined}\n {...rest}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n onClick={handleInputClick}\n />\n </div>\n <span className={styles.trailing}>\n {loading ? <Spinner size=\"sm\" label={null} className={styles.spinner} /> : null}\n {canClear ? (\n <button\n type=\"button\"\n className={styles.clear}\n aria-label={clearLabel}\n onMouseDown={(event) => {\n event.preventDefault()\n }}\n onClick={clear}\n >\n <CloseIcon />\n </button>\n ) : null}\n <ChevronDownIcon className={styles.chevron} />\n </span>\n {name !== undefined ? (\n multiple ? (\n values.map((value) => (\n <input\n key={value}\n type=\"hidden\"\n name={name}\n value={value}\n form={form}\n disabled={field.disabled || undefined}\n />\n ))\n ) : (\n <input\n type=\"hidden\"\n name={name}\n value={values[0] ?? ''}\n form={form}\n disabled={field.disabled || undefined}\n />\n )\n ) : null}\n <div\n id={statusId}\n role=\"status\"\n aria-live=\"polite\"\n className={messageStyles.visuallyHidden}\n >\n {announcement}\n </div>\n </div>\n </PopoverPrimitive.Anchor>\n <PopoverPrimitive.Portal container={expanded ? themeScopeOf(boxRef.current) : undefined}>\n <ComboboxPopup onInteractOutside={handleInteractOutside}>\n <div\n id={listboxId}\n role=\"listbox\"\n aria-labelledby={listLabelledBy}\n aria-label={listLabelledBy ? undefined : ariaLabel}\n aria-multiselectable={multiple || undefined}\n aria-busy={loading || undefined}\n className={styles.listbox}\n >\n {sections.map((section) =>\n section.label === undefined ? (\n section.options.map(renderOption)\n ) : (\n <div\n key={section.key}\n role=\"group\"\n aria-labelledby={`${inputId}-group-${String(sections.indexOf(section))}`}\n className={styles.group}\n >\n <div\n id={`${inputId}-group-${String(sections.indexOf(section))}`}\n role=\"presentation\"\n className={styles.groupLabel}\n >\n {section.label}\n </div>\n {section.options.map(renderOption)}\n </div>\n ),\n )}\n </div>\n {loading && ordered.length === 0 ? (\n <div className={styles.message}>\n <Spinner size=\"sm\" label={null} />\n <span>{loadingMessage}</span>\n </div>\n ) : null}\n {showEmpty ? <div className={styles.message}>{emptyMessage}</div> : null}\n </ComboboxPopup>\n </PopoverPrimitive.Portal>\n </PortalAnchorContext.Provider>\n </PopoverPrimitive.Root>\n )\n }),\n)\n"],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type FieldLabelProps } from '../Field/index.js';
|
|
2
|
+
import { type DateInputProps } from '../DateInput/index.js';
|
|
3
|
+
export interface DateFieldProps extends FieldLabelProps, Omit<DateInputProps, 'invalid' | keyof FieldLabelProps> {
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* A labelled date, typed part by part or picked from a calendar.
|
|
7
|
+
*
|
|
8
|
+
* @remarks
|
|
9
|
+
* `DateField` is a {@link Field | Field} around a {@link DateInput | DateInput}.
|
|
10
|
+
*
|
|
11
|
+
* @privateRemarks
|
|
12
|
+
* Label + DateInput + description + error. Input props (`value`, `min`, `max`…) and the ref go
|
|
13
|
+
* to the input's box; `className`/`style` go to the wrapper.
|
|
14
|
+
*
|
|
15
|
+
* <DateField label="Due date" value={due} onValueChange={setDue} min="2026-10-01" />
|
|
16
|
+
*/
|
|
17
|
+
export declare const DateField: import("react").ForwardRefExoticComponent<DateFieldProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Field as e } from "../Field/Field.js";
|
|
2
|
+
import { splitFieldLabelProps as t } from "../internal/fieldProps.js";
|
|
3
|
+
import { DateInput as n } from "../DateInput/DateInput.js";
|
|
4
|
+
import { forwardRef as r } from "react";
|
|
5
|
+
import { jsx as i } from "react/jsx-runtime";
|
|
6
|
+
//#region src/components/inputs/DateField/DateField.tsx
|
|
7
|
+
var a = r(function(r, a) {
|
|
8
|
+
let [o, s] = t(r), { id: c, disabled: l, className: u, style: d, ...f } = s;
|
|
9
|
+
return /* @__PURE__ */ i(e, {
|
|
10
|
+
...o,
|
|
11
|
+
htmlFor: c,
|
|
12
|
+
disabled: l,
|
|
13
|
+
className: u,
|
|
14
|
+
style: d,
|
|
15
|
+
children: /* @__PURE__ */ i(n, {
|
|
16
|
+
ref: a,
|
|
17
|
+
id: c,
|
|
18
|
+
disabled: l,
|
|
19
|
+
...f
|
|
20
|
+
})
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
//#endregion
|
|
24
|
+
export { a as DateField };
|
|
25
|
+
|
|
26
|
+
//# sourceMappingURL=DateField.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DateField.js","names":["DateField","forwardRef","fieldProps","rest","splitFieldLabelProps","props","inputRest","Field","id","DateInput"],"sources":["../../../../src/components/inputs/DateField/DateField.tsx"],"sourcesContent":["import { forwardRef } from 'react'\nimport { Field, type FieldLabelProps } from '#components/inputs/Field'\nimport { DateInput, type DateInputProps } from '#components/inputs/DateInput'\nimport { splitFieldLabelProps } from '#components/inputs/internal/fieldProps'\n\nexport interface DateFieldProps\n extends FieldLabelProps, Omit<DateInputProps, 'invalid' | keyof FieldLabelProps> {}\n\n/**\n * A labelled date, typed part by part or picked from a calendar.\n *\n * @remarks\n * `DateField` is a {@link Field | Field} around a {@link DateInput | DateInput}.\n *\n * @privateRemarks\n * Label + DateInput + description + error. Input props (`value`, `min`, `max`…) and the ref go\n * to the input's box; `className`/`style` go to the wrapper.\n *\n * <DateField label=\"Due date\" value={due} onValueChange={setDue} min=\"2026-10-01\" />\n */\nexport const DateField = forwardRef<HTMLDivElement, DateFieldProps>(function DateField(props, ref) {\n const [fieldProps, rest] = splitFieldLabelProps(props)\n const { id, disabled, className, style, ...inputRest } = rest\n return (\n <Field {...fieldProps} htmlFor={id} disabled={disabled} className={className} style={style}>\n <DateInput ref={ref} id={id} disabled={disabled} {...inputRest} />\n </Field>\n )\n})\n"],"mappings":";;;;;;AAoBA,IAAaA,IAAYC,EAA2C,SAAmB,GAAO,GAAK;CACjG,IAAM,CAACC,GAAYC,KAAQC,EAAqBC,CAAK,GAC/C,EAAE,OAAI,aAAU,cAAW,UAAO,GAAGC,MAAcH;CACzD,OACE,kBAACI,GAAD;EAAO,GAAIL;EAAY,SAASM;EAAc;EAAqB;EAAkB;EACnF,UAAA,kBAACC,GAAD;GAAgB;GAAS;GAAc;GAAU,GAAIH;EAAY,CAAA;CAC5D,CAAA;AAEX,CAAC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { type FocusEventHandler, type HTMLAttributes } from 'react';
|
|
2
|
+
import type { Size } from '../../../utils/tokens.js';
|
|
3
|
+
import { type DateTimeLabels } from '../internal/picker.js';
|
|
4
|
+
export interface DateInputProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange' | 'defaultValue' | 'onBlur' | 'onFocus'> {
|
|
5
|
+
/** `YYYY-MM-DD`, or `''` until every part is filled in. */
|
|
6
|
+
value?: string;
|
|
7
|
+
defaultValue?: string;
|
|
8
|
+
onValueChange?: (value: string) => void;
|
|
9
|
+
/** Earliest date (`YYYY-MM-DD`). Earlier dates can't be picked and mark a typed one invalid. */
|
|
10
|
+
min?: string;
|
|
11
|
+
/** Latest date (`YYYY-MM-DD`). */
|
|
12
|
+
max?: string;
|
|
13
|
+
/** Marks other dates unavailable, in the calendar and when typed. */
|
|
14
|
+
isDateDisabled?: (date: string) => boolean;
|
|
15
|
+
/** 0 (Sunday) to 6 (Saturday). Defaults to the locale's own week. */
|
|
16
|
+
firstDayOfWeek?: number;
|
|
17
|
+
/** BCP 47 locale for the order of the parts and the calendar's names. Default `en-AU`. */
|
|
18
|
+
locale?: string;
|
|
19
|
+
/** The zone "today" is read in: the calendar's marker and where arrow keys start. */
|
|
20
|
+
timeZone?: string;
|
|
21
|
+
/** Show the calendar button. Default `true`. Typing always works. */
|
|
22
|
+
calendar?: boolean;
|
|
23
|
+
/** Show a clear button while there's a value. */
|
|
24
|
+
clearable?: boolean;
|
|
25
|
+
/** Submits the ISO date (`''` when incomplete). */
|
|
26
|
+
name?: string;
|
|
27
|
+
form?: string;
|
|
28
|
+
size?: Size;
|
|
29
|
+
disabled?: boolean;
|
|
30
|
+
readOnly?: boolean;
|
|
31
|
+
required?: boolean;
|
|
32
|
+
/** Critical border + `aria-invalid`. Inside a `<Field error>` this is set for you. */
|
|
33
|
+
invalid?: boolean;
|
|
34
|
+
/** Whether the calendar is open. Controlled. */
|
|
35
|
+
open?: boolean;
|
|
36
|
+
defaultOpen?: boolean;
|
|
37
|
+
onOpenChange?: (open: boolean) => void;
|
|
38
|
+
/** Fires once focus leaves the whole control, calendar included. */
|
|
39
|
+
onBlur?: FocusEventHandler<HTMLElement>;
|
|
40
|
+
onFocus?: FocusEventHandler<HTMLElement>;
|
|
41
|
+
labels?: Partial<DateTimeLabels>;
|
|
42
|
+
}
|
|
43
|
+
/** Whether `value` is a date outside `min`/`max` or one `isDateDisabled` rules out. */
|
|
44
|
+
export declare function isDateOutOfRange(value: string, min: string | undefined, max: string | undefined, isDateDisabled?: (date: string) => boolean): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* A date typed part by part in the locale's order, with a calendar to pick from.
|
|
47
|
+
*
|
|
48
|
+
* @remarks
|
|
49
|
+
* `DateInput` holds a date as an ISO string (`2026-10-15`). The day, month and year are separate
|
|
50
|
+
* parts in the locale's order: type the digits and it moves to the next part on its own, or use
|
|
51
|
+
* the arrow keys to step a part up and down. The calendar button opens a {@link Calendar | Calendar}
|
|
52
|
+
* for anyone who'd rather pick, and Alt + Down Arrow opens it from the keyboard. Until every part
|
|
53
|
+
* is filled in the value stays `''`.
|
|
54
|
+
*
|
|
55
|
+
* A date outside `min`/`max`, or one `isDateDisabled` rules out, can't be picked in the calendar
|
|
56
|
+
* and marks a typed one invalid. For the usual labelled field, use {@link DateField | DateField}.
|
|
57
|
+
*
|
|
58
|
+
* ## Keyboard
|
|
59
|
+
*
|
|
60
|
+
* | Key | Does |
|
|
61
|
+
* | --- | --- |
|
|
62
|
+
* | Digits | Fill the focused part, moving on when it's full |
|
|
63
|
+
* | Up / Down Arrow | Step the focused part (an empty part starts from today) |
|
|
64
|
+
* | Left / Right Arrow | Move between parts |
|
|
65
|
+
* | Backspace | Clear the focused part |
|
|
66
|
+
* | Alt + Down Arrow | Open the calendar |
|
|
67
|
+
*
|
|
68
|
+
* @privateRemarks
|
|
69
|
+
* Each part is a `role="spinbutton"` inside a `role="group"` box named by the Field label; the
|
|
70
|
+
* first part takes the Field's `id`. The ref goes to the box. Value ↔ draft lives in
|
|
71
|
+
* `useSegmentDraft`: a new value from outside (controlled, or a calendar pick) resets the parts.
|
|
72
|
+
*
|
|
73
|
+
* <DateInput value={due} onValueChange={setDue} min="2026-10-01" clearable />
|
|
74
|
+
*/
|
|
75
|
+
export declare const DateInput: import("react").ForwardRefExoticComponent<DateInputProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { cx as e } from "../../../utils/cx.js";
|
|
2
|
+
import { CalendarIcon as t, CloseIcon as n } from "../../../icons/icons.js";
|
|
3
|
+
import { useMergedRefs as r } from "../internal/refs.js";
|
|
4
|
+
import { markFieldAware as i, useResolvedField as a } from "../internal/FieldContext.js";
|
|
5
|
+
import o from "../internal/control.module.js";
|
|
6
|
+
import { Popover as s } from "../../overlays/Popover/Popover.js";
|
|
7
|
+
import { DEFAULT_LOCALE as ee, compareDates as c, formatDate as l, parseDate as u, todayIn as te } from "../internal/dates.js";
|
|
8
|
+
import { Calendar as ne } from "../Calendar/Calendar.js";
|
|
9
|
+
import { useControllableState as d } from "../Combobox/useControllableState.js";
|
|
10
|
+
import { DateSegments as re, draftDate as f, draftFromParts as p, segmentPattern as ie, useSegmentDraft as ae } from "../internal/DateSegments.js";
|
|
11
|
+
import { DEFAULT_DATE_TIME_LABELS as oe, focusSegment as se, handleBoxPointerDown as ce, isLeaving as m } from "../internal/picker.js";
|
|
12
|
+
import h from "../internal/picker.module.js";
|
|
13
|
+
import { forwardRef as g, useMemo as le, useRef as _ } from "react";
|
|
14
|
+
import { jsx as v, jsxs as y } from "react/jsx-runtime";
|
|
15
|
+
//#region src/components/inputs/DateInput/DateInput.tsx
|
|
16
|
+
var ue = (e) => p(u(e)), de = (e) => {
|
|
17
|
+
let t = f(e);
|
|
18
|
+
return t ? l(t) : "";
|
|
19
|
+
};
|
|
20
|
+
function b(e, t, n, r) {
|
|
21
|
+
let i = u(e);
|
|
22
|
+
if (!i) return !1;
|
|
23
|
+
let a = u(t ?? ""), o = u(n ?? "");
|
|
24
|
+
return a !== null && c(i, a) < 0 || o !== null && c(i, o) > 0 || (r?.(e) ?? !1);
|
|
25
|
+
}
|
|
26
|
+
var x = i(g(function({ value: i, defaultValue: c, onValueChange: l, min: f, max: g, isDateDisabled: x, firstDayOfWeek: fe, locale: S = ee, timeZone: C, calendar: w = !0, clearable: T = !1, name: E, form: pe, size: me = "md", id: D, disabled: O, readOnly: k, required: A, invalid: j, open: M, defaultOpen: N, onOpenChange: P, onBlur: F, onFocus: I, onKeyDown: L, labels: R, className: z, "aria-describedby": he, "aria-invalid": B, "aria-labelledby": ge, ..._e }, ve) {
|
|
27
|
+
let V = {
|
|
28
|
+
...oe,
|
|
29
|
+
...R
|
|
30
|
+
}, H = a({
|
|
31
|
+
id: D,
|
|
32
|
+
describedBy: he,
|
|
33
|
+
invalid: j,
|
|
34
|
+
ariaInvalid: B,
|
|
35
|
+
disabled: O,
|
|
36
|
+
readOnly: k,
|
|
37
|
+
required: A
|
|
38
|
+
}), U = _(null), W = _(null), ye = r(ve, U), [G, K] = d(i, c ?? "", l), [be, q] = d(M, N ?? !1, P), xe = le(() => ie("date", S, "minute", 24), [S]), [J, Y] = ae(G, ue, de, K), X = !H.disabled && !H.readOnly, Z = H.invalid || b(G, f, g, x), Q = Object.keys(J).length > 0, Se = p(te(C)), Ce = (e) => {
|
|
39
|
+
L?.(e), !e.defaultPrevented && w && X && e.altKey && e.key === "ArrowDown" && (e.preventDefault(), q(!0));
|
|
40
|
+
}, $ = /* @__PURE__ */ y("div", {
|
|
41
|
+
ref: ye,
|
|
42
|
+
role: "group",
|
|
43
|
+
className: e(o.box, h.root, z),
|
|
44
|
+
"data-size": me,
|
|
45
|
+
"data-invalid": Z || void 0,
|
|
46
|
+
"data-disabled": H.disabled || void 0,
|
|
47
|
+
"data-readonly": H.readOnly || void 0,
|
|
48
|
+
"aria-labelledby": ge ?? H.labelId,
|
|
49
|
+
"aria-describedby": H.describedBy,
|
|
50
|
+
"aria-busy": H.busy || void 0,
|
|
51
|
+
..._e,
|
|
52
|
+
onPointerDown: ce,
|
|
53
|
+
onKeyDown: Ce,
|
|
54
|
+
onFocus: (e) => {
|
|
55
|
+
m(e, U, W) && I?.(e);
|
|
56
|
+
},
|
|
57
|
+
onBlur: (e) => {
|
|
58
|
+
m(e, U, W) && F?.(e);
|
|
59
|
+
},
|
|
60
|
+
children: [
|
|
61
|
+
/* @__PURE__ */ v(re, {
|
|
62
|
+
pattern: xe,
|
|
63
|
+
draft: J,
|
|
64
|
+
onDraftChange: Y,
|
|
65
|
+
hourCycle: 24,
|
|
66
|
+
periodNames: ["", ""],
|
|
67
|
+
labels: V,
|
|
68
|
+
reference: Se,
|
|
69
|
+
firstId: H.id,
|
|
70
|
+
disabled: H.disabled,
|
|
71
|
+
readOnly: H.readOnly,
|
|
72
|
+
invalid: Z,
|
|
73
|
+
required: H.required
|
|
74
|
+
}),
|
|
75
|
+
T && X && Q || w ? /* @__PURE__ */ y("span", {
|
|
76
|
+
className: h.trailing,
|
|
77
|
+
children: [T && X && Q ? /* @__PURE__ */ v("button", {
|
|
78
|
+
type: "button",
|
|
79
|
+
className: h.button,
|
|
80
|
+
"aria-label": V.clear,
|
|
81
|
+
onClick: () => {
|
|
82
|
+
Y({}), se(U.current, "first");
|
|
83
|
+
},
|
|
84
|
+
children: /* @__PURE__ */ v(n, {})
|
|
85
|
+
}) : null, w ? /* @__PURE__ */ v(s.Trigger, {
|
|
86
|
+
asChild: !0,
|
|
87
|
+
children: /* @__PURE__ */ v("button", {
|
|
88
|
+
type: "button",
|
|
89
|
+
className: h.button,
|
|
90
|
+
"aria-label": V.openCalendar,
|
|
91
|
+
disabled: !X,
|
|
92
|
+
children: /* @__PURE__ */ v(t, {})
|
|
93
|
+
})
|
|
94
|
+
}) : null]
|
|
95
|
+
}) : null,
|
|
96
|
+
E === void 0 ? null : /* @__PURE__ */ v("input", {
|
|
97
|
+
type: "hidden",
|
|
98
|
+
name: E,
|
|
99
|
+
form: pe,
|
|
100
|
+
value: G,
|
|
101
|
+
disabled: H.disabled || void 0
|
|
102
|
+
})
|
|
103
|
+
]
|
|
104
|
+
});
|
|
105
|
+
return w ? /* @__PURE__ */ y(s, {
|
|
106
|
+
open: be && X,
|
|
107
|
+
onOpenChange: q,
|
|
108
|
+
children: [/* @__PURE__ */ v(s.Anchor, {
|
|
109
|
+
asChild: !0,
|
|
110
|
+
children: $
|
|
111
|
+
}), /* @__PURE__ */ v(s.Content, {
|
|
112
|
+
ref: W,
|
|
113
|
+
className: h.popover,
|
|
114
|
+
align: "start",
|
|
115
|
+
"aria-label": V.openCalendar,
|
|
116
|
+
onOpenAutoFocus: (e) => {
|
|
117
|
+
e.preventDefault();
|
|
118
|
+
},
|
|
119
|
+
children: /* @__PURE__ */ v(ne, {
|
|
120
|
+
autoFocus: !0,
|
|
121
|
+
value: u(G) ? G : "",
|
|
122
|
+
min: f,
|
|
123
|
+
max: g,
|
|
124
|
+
isDateDisabled: x,
|
|
125
|
+
firstDayOfWeek: fe,
|
|
126
|
+
locale: S,
|
|
127
|
+
timeZone: C,
|
|
128
|
+
labels: V,
|
|
129
|
+
onValueChange: (e) => {
|
|
130
|
+
K(e), q(!1);
|
|
131
|
+
}
|
|
132
|
+
})
|
|
133
|
+
})]
|
|
134
|
+
}) : $;
|
|
135
|
+
}));
|
|
136
|
+
//#endregion
|
|
137
|
+
export { x as DateInput, b as isDateOutOfRange };
|
|
138
|
+
|
|
139
|
+
//# sourceMappingURL=DateInput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DateInput.js","names":["control","picker","control_module_default","picker_module_default","toDraft","draftFromParts","parseDate","value","fromDraft","date","draftDate","draft","formatDate","isDateOutOfRange","minDate","min","maxDate","max","compareDates","isDateDisabled","DateInput","markFieldAware","forwardRef","valueProp","DEFAULT_LOCALE","idProp","disabledProp","readOnlyProp","requiredProp","invalidProp","openProp","labelsProp","describedByProp","ariaInvalid","ariaLabelledBy","rest","labels","DEFAULT_DATE_TIME_LABELS","field","useResolvedField","rootRef","useRef","panelRef","composedRef","useMergedRefs","ref","setValue","useControllableState","defaultValue","onValueChange","open","setOpen","defaultOpen","onOpenChange","pattern","useMemo","segmentPattern","locale","setDraft","useSegmentDraft","interactive","invalid","hasEntry","reference","todayIn","timeZone","handleKeyDown","onKeyDown","event","calendar","box","cx","className","size","handleBoxPointerDown","isLeaving","onFocus","onBlur","DateSegments","clearable","focusSegment","CloseIcon","Popover","CalendarIcon","name","Calendar","next"],"sources":["../../../../src/components/inputs/DateInput/DateInput.tsx"],"sourcesContent":["import {\n forwardRef,\n useMemo,\n useRef,\n type FocusEventHandler,\n type HTMLAttributes,\n type KeyboardEvent,\n} from 'react'\nimport { CalendarIcon, CloseIcon } from '#icons'\nimport { cx } from '#utils/cx'\nimport type { Size } from '#utils/tokens'\nimport { Popover } from '#components/overlays/Popover'\nimport { Calendar } from '#components/inputs/Calendar'\nimport { useControllableState } from '#components/inputs/Combobox/useControllableState'\nimport { markFieldAware, useResolvedField } from '#components/inputs/internal/FieldContext'\nimport { useMergedRefs } from '#components/inputs/internal/refs'\nimport {\n DateSegments,\n draftDate,\n draftFromParts,\n segmentPattern,\n useSegmentDraft,\n type Draft,\n} from '#components/inputs/internal/DateSegments'\nimport {\n DEFAULT_LOCALE,\n compareDates,\n formatDate,\n parseDate,\n todayIn,\n} from '#components/inputs/internal/dates'\nimport {\n DEFAULT_DATE_TIME_LABELS,\n focusSegment,\n handleBoxPointerDown,\n isLeaving,\n type DateTimeLabels,\n} from '#components/inputs/internal/picker'\nimport control from '#components/inputs/internal/control.module.css'\nimport picker from '#components/inputs/internal/picker.module.css'\n\nexport interface DateInputProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n 'onChange' | 'defaultValue' | 'onBlur' | 'onFocus'\n> {\n /** `YYYY-MM-DD`, or `''` until every part is filled in. */\n value?: string\n defaultValue?: string\n onValueChange?: (value: string) => void\n /** Earliest date (`YYYY-MM-DD`). Earlier dates can't be picked and mark a typed one invalid. */\n min?: string\n /** Latest date (`YYYY-MM-DD`). */\n max?: string\n /** Marks other dates unavailable, in the calendar and when typed. */\n isDateDisabled?: (date: string) => boolean\n /** 0 (Sunday) to 6 (Saturday). Defaults to the locale's own week. */\n firstDayOfWeek?: number\n /** BCP 47 locale for the order of the parts and the calendar's names. Default `en-AU`. */\n locale?: string\n /** The zone \"today\" is read in: the calendar's marker and where arrow keys start. */\n timeZone?: string\n /** Show the calendar button. Default `true`. Typing always works. */\n calendar?: boolean\n /** Show a clear button while there's a value. */\n clearable?: boolean\n /** Submits the ISO date (`''` when incomplete). */\n name?: string\n form?: string\n size?: Size\n disabled?: boolean\n readOnly?: boolean\n required?: boolean\n /** Critical border + `aria-invalid`. Inside a `<Field error>` this is set for you. */\n invalid?: boolean\n /** Whether the calendar is open. Controlled. */\n open?: boolean\n defaultOpen?: boolean\n onOpenChange?: (open: boolean) => void\n /** Fires once focus leaves the whole control, calendar included. */\n onBlur?: FocusEventHandler<HTMLElement>\n onFocus?: FocusEventHandler<HTMLElement>\n labels?: Partial<DateTimeLabels>\n}\n\nconst toDraft = (value: string): Draft => draftFromParts(parseDate(value))\nconst fromDraft = (draft: Draft): string => {\n const date = draftDate(draft)\n return date ? formatDate(date) : ''\n}\n\n/** Whether `value` is a date outside `min`/`max` or one `isDateDisabled` rules out. */\nexport function isDateOutOfRange(\n value: string,\n min: string | undefined,\n max: string | undefined,\n isDateDisabled?: (date: string) => boolean,\n): boolean {\n const date = parseDate(value)\n if (!date) return false\n const minDate = parseDate(min ?? '')\n const maxDate = parseDate(max ?? '')\n return (\n (minDate !== null && compareDates(date, minDate) < 0) ||\n (maxDate !== null && compareDates(date, maxDate) > 0) ||\n (isDateDisabled?.(value) ?? false)\n )\n}\n\n/**\n * A date typed part by part in the locale's order, with a calendar to pick from.\n *\n * @remarks\n * `DateInput` holds a date as an ISO string (`2026-10-15`). The day, month and year are separate\n * parts in the locale's order: type the digits and it moves to the next part on its own, or use\n * the arrow keys to step a part up and down. The calendar button opens a {@link Calendar | Calendar}\n * for anyone who'd rather pick, and Alt + Down Arrow opens it from the keyboard. Until every part\n * is filled in the value stays `''`.\n *\n * A date outside `min`/`max`, or one `isDateDisabled` rules out, can't be picked in the calendar\n * and marks a typed one invalid. For the usual labelled field, use {@link DateField | DateField}.\n *\n * ## Keyboard\n *\n * | Key | Does |\n * | --- | --- |\n * | Digits | Fill the focused part, moving on when it's full |\n * | Up / Down Arrow | Step the focused part (an empty part starts from today) |\n * | Left / Right Arrow | Move between parts |\n * | Backspace | Clear the focused part |\n * | Alt + Down Arrow | Open the calendar |\n *\n * @privateRemarks\n * Each part is a `role=\"spinbutton\"` inside a `role=\"group\"` box named by the Field label; the\n * first part takes the Field's `id`. The ref goes to the box. Value ↔ draft lives in\n * `useSegmentDraft`: a new value from outside (controlled, or a calendar pick) resets the parts.\n *\n * <DateInput value={due} onValueChange={setDue} min=\"2026-10-01\" clearable />\n */\nexport const DateInput = markFieldAware(\n forwardRef<HTMLDivElement, DateInputProps>(function DateInput(\n {\n value: valueProp,\n defaultValue,\n onValueChange,\n min,\n max,\n isDateDisabled,\n firstDayOfWeek,\n locale = DEFAULT_LOCALE,\n timeZone,\n calendar = true,\n clearable = false,\n name,\n form,\n size = 'md',\n id: idProp,\n disabled: disabledProp,\n readOnly: readOnlyProp,\n required: requiredProp,\n invalid: invalidProp,\n open: openProp,\n defaultOpen,\n onOpenChange,\n onBlur,\n onFocus,\n onKeyDown,\n labels: labelsProp,\n className,\n 'aria-describedby': describedByProp,\n 'aria-invalid': ariaInvalid,\n 'aria-labelledby': ariaLabelledBy,\n ...rest\n },\n ref,\n ) {\n const labels = { ...DEFAULT_DATE_TIME_LABELS, ...labelsProp }\n const field = useResolvedField({\n id: idProp,\n describedBy: describedByProp,\n invalid: invalidProp,\n ariaInvalid,\n disabled: disabledProp,\n readOnly: readOnlyProp,\n required: requiredProp,\n })\n const rootRef = useRef<HTMLDivElement>(null)\n const panelRef = useRef<HTMLDivElement>(null)\n const composedRef = useMergedRefs(ref, rootRef)\n const [value, setValue] = useControllableState(valueProp, defaultValue ?? '', onValueChange)\n const [open, setOpen] = useControllableState(openProp, defaultOpen ?? false, onOpenChange)\n const pattern = useMemo(() => segmentPattern('date', locale, 'minute', 24), [locale])\n const [draft, setDraft] = useSegmentDraft(value, toDraft, fromDraft, setValue)\n const interactive = !field.disabled && !field.readOnly\n const invalid = field.invalid || isDateOutOfRange(value, min, max, isDateDisabled)\n const hasEntry = Object.keys(draft).length > 0\n const reference = draftFromParts(todayIn(timeZone))\n\n const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(event)\n if (event.defaultPrevented) return\n if (calendar && interactive && event.altKey && event.key === 'ArrowDown') {\n event.preventDefault()\n setOpen(true)\n }\n }\n\n const box = (\n // The group only routes what its parts don't handle: a click on its padding, and\n // Alt + Down Arrow from any part to open the calendar.\n // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions\n <div\n ref={composedRef}\n role=\"group\"\n className={cx(control.box, picker.root, className)}\n data-size={size}\n data-invalid={invalid || undefined}\n data-disabled={field.disabled || undefined}\n data-readonly={field.readOnly || undefined}\n aria-labelledby={ariaLabelledBy ?? field.labelId}\n aria-describedby={field.describedBy}\n aria-busy={field.busy || undefined}\n {...rest}\n onPointerDown={handleBoxPointerDown}\n onKeyDown={handleKeyDown}\n onFocus={(event) => {\n if (isLeaving(event, rootRef, panelRef)) onFocus?.(event)\n }}\n onBlur={(event) => {\n if (isLeaving(event, rootRef, panelRef)) onBlur?.(event)\n }}\n >\n <DateSegments\n pattern={pattern}\n draft={draft}\n onDraftChange={setDraft}\n hourCycle={24}\n periodNames={['', '']}\n labels={labels}\n reference={reference}\n firstId={field.id}\n disabled={field.disabled}\n readOnly={field.readOnly}\n invalid={invalid}\n required={field.required}\n />\n {(clearable && interactive && hasEntry) || calendar ? (\n <span className={picker.trailing}>\n {clearable && interactive && hasEntry ? (\n <button\n type=\"button\"\n className={picker.button}\n aria-label={labels.clear}\n onClick={() => {\n setDraft({})\n focusSegment(rootRef.current, 'first')\n }}\n >\n <CloseIcon />\n </button>\n ) : null}\n {calendar ? (\n <Popover.Trigger asChild>\n <button\n type=\"button\"\n className={picker.button}\n aria-label={labels.openCalendar}\n disabled={!interactive}\n >\n <CalendarIcon />\n </button>\n </Popover.Trigger>\n ) : null}\n </span>\n ) : null}\n {name !== undefined ? (\n <input\n type=\"hidden\"\n name={name}\n form={form}\n value={value}\n disabled={field.disabled || undefined}\n />\n ) : null}\n </div>\n )\n\n if (!calendar) return box\n\n return (\n <Popover open={open && interactive} onOpenChange={setOpen}>\n <Popover.Anchor asChild>{box}</Popover.Anchor>\n <Popover.Content\n ref={panelRef}\n className={picker.popover}\n align=\"start\"\n aria-label={labels.openCalendar}\n onOpenAutoFocus={(event) => {\n // The calendar focuses its own day instead of the first button.\n event.preventDefault()\n }}\n >\n <Calendar\n // The panel is a dialog: opening it moves focus to its current day.\n // eslint-disable-next-line jsx-a11y/no-autofocus\n autoFocus\n value={parseDate(value) ? value : ''}\n min={min}\n max={max}\n isDateDisabled={isDateDisabled}\n firstDayOfWeek={firstDayOfWeek}\n locale={locale}\n timeZone={timeZone}\n labels={labels}\n onValueChange={(next) => {\n setValue(next)\n setOpen(false)\n }}\n />\n </Popover.Content>\n </Popover>\n )\n }),\n)\n"],"mappings":"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"}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { type FocusEventHandler, type HTMLAttributes } from 'react';
|
|
2
2
|
import type { Size } from '../../../utils/tokens.js';
|
|
3
3
|
import { type FieldLabelProps } from '../Field/index.js';
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* Two ISO dates (`YYYY-MM-DD`); `''` for an unset end. With a time `granularity` on
|
|
6
|
+
* `DateRangePickerField`, each end is a date-time in the same form as
|
|
7
|
+
* {@link DateTimeInput | DateTimeInput}'s value.
|
|
8
|
+
*/
|
|
5
9
|
export interface DateRangeValue {
|
|
6
10
|
start: string;
|
|
7
11
|
end: string;
|
|
@@ -27,17 +31,28 @@ export interface DateRangeFieldProps extends FieldLabelProps, Omit<HTMLAttribute
|
|
|
27
31
|
size?: Size;
|
|
28
32
|
}
|
|
29
33
|
/**
|
|
30
|
-
* A start and end date
|
|
34
|
+
* A start and end date under one legend: two native date inputs, or with `DateRangePickerField`
|
|
35
|
+
* typed dates with one calendar for the range, optional times and preset ranges.
|
|
31
36
|
*
|
|
32
37
|
* @remarks
|
|
33
38
|
* `DateRangeField` is two native date inputs, side by side and wrapping on a phone, under one
|
|
34
39
|
* legend. Native inputs mean the platform's own date picker and its accessibility.
|
|
35
40
|
*
|
|
41
|
+
* `DateRangePickerField` takes the same props and types the two ends like
|
|
42
|
+
* {@link DateInput | DateInput}, and one button opens a two-month {@link Calendar | Calendar}: the
|
|
43
|
+
* first pick sets the start, the second the end. `granularity="minute"` adds a time to each end (a
|
|
44
|
+
* new range runs from the start of its first day to the end of its last), and `presets` lists
|
|
45
|
+
* ranges such as "Last 7 days" beside the calendar. It's a separate import, so a native
|
|
46
|
+
* `DateRangeField` doesn't carry the calendar.
|
|
47
|
+
*
|
|
48
|
+
* Whichever you use, the start can't pass the end and the end can't come before the start.
|
|
49
|
+
*
|
|
36
50
|
* @privateRemarks
|
|
37
51
|
* A date range as two native date inputs under one legend, side by side and wrapping
|
|
38
52
|
* when narrow. The start can't pass the end and the end can't come before the start
|
|
39
53
|
* (each input's `min`/`max` follows the other). `id` goes to the start input; the ref to
|
|
40
|
-
* the fieldset.
|
|
54
|
+
* the fieldset. The calendar picker is its own component, DateRangePickerField, so the native
|
|
55
|
+
* markup, behaviour and import size stay exactly as they were for existing callers (ADR 0044).
|
|
41
56
|
*
|
|
42
57
|
* <DateRangeField label="Trip dates" value={dates} onValueChange={setDates} />
|
|
43
58
|
*/
|