@seekalfred/primitives 0.7.1 → 0.7.4

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.
Files changed (147) hide show
  1. package/README.md +255 -5
  2. package/dist/alert/alert.d.ts +49 -4
  3. package/dist/alert/alert.js +66 -38
  4. package/dist/alert/alert.js.map +1 -1
  5. package/dist/alert/index.d.ts +2 -2
  6. package/dist/alert/index.js +2 -2
  7. package/dist/alert-dialog/alert-dialog.d.ts +31 -4
  8. package/dist/alert-dialog/alert-dialog.js +75 -26
  9. package/dist/alert-dialog/alert-dialog.js.map +1 -1
  10. package/dist/announcement-bar/announcement-bar.d.ts +15 -4
  11. package/dist/announcement-bar/announcement-bar.js +31 -6
  12. package/dist/announcement-bar/announcement-bar.js.map +1 -1
  13. package/dist/avatar/avatar.d.ts +7 -0
  14. package/dist/avatar/avatar.js +33 -12
  15. package/dist/avatar/avatar.js.map +1 -1
  16. package/dist/badge/badge.d.ts +1 -1
  17. package/dist/bar-chart/bar-chart-series.d.ts +75 -0
  18. package/dist/bar-chart/bar-chart-series.js +401 -0
  19. package/dist/bar-chart/bar-chart-series.js.map +1 -0
  20. package/dist/bar-chart/bar-chart.d.ts +25 -1
  21. package/dist/bar-chart/bar-chart.js +26 -1
  22. package/dist/bar-chart/bar-chart.js.map +1 -1
  23. package/dist/bar-chart/index.d.ts +2 -1
  24. package/dist/button/button.d.ts +1 -1
  25. package/dist/calendar/calendar.d.ts +1 -1
  26. package/dist/card/card.d.ts +22 -1
  27. package/dist/card/card.js +60 -7
  28. package/dist/card/card.js.map +1 -1
  29. package/dist/carousel/carousel.d.ts +21 -0
  30. package/dist/carousel/carousel.js +34 -8
  31. package/dist/carousel/carousel.js.map +1 -1
  32. package/dist/chip-group/chip-group.d.ts +11 -0
  33. package/dist/chip-group/chip-group.js +50 -34
  34. package/dist/chip-group/chip-group.js.map +1 -1
  35. package/dist/chip-group/index.d.ts +2 -2
  36. package/dist/copy-button/copy-button.d.ts +37 -5
  37. package/dist/copy-button/copy-button.js +35 -11
  38. package/dist/copy-button/copy-button.js.map +1 -1
  39. package/dist/donut-chart/donut-chart.d.ts +22 -0
  40. package/dist/donut-chart/donut-chart.js +35 -18
  41. package/dist/donut-chart/donut-chart.js.map +1 -1
  42. package/dist/donut-chart/index.d.ts +2 -2
  43. package/dist/empty-state/empty-state.d.ts +21 -0
  44. package/dist/empty-state/empty-state.js +16 -4
  45. package/dist/empty-state/empty-state.js.map +1 -1
  46. package/dist/empty-state/index.d.ts +2 -2
  47. package/dist/empty-state/index.js +2 -2
  48. package/dist/file-drop-zone/file-drop-zone.d.ts +29 -3
  49. package/dist/file-drop-zone/file-drop-zone.js +26 -8
  50. package/dist/file-drop-zone/file-drop-zone.js.map +1 -1
  51. package/dist/filter-bar/filter-bar.d.ts +4 -1
  52. package/dist/filter-bar/filter-bar.js +53 -9
  53. package/dist/filter-bar/filter-bar.js.map +1 -1
  54. package/dist/gauge/gauge.d.ts +18 -1
  55. package/dist/gauge/gauge.js +35 -21
  56. package/dist/gauge/gauge.js.map +1 -1
  57. package/dist/gauge/index.d.ts +2 -2
  58. package/dist/index.d.ts +15 -14
  59. package/dist/index.js +9 -9
  60. package/dist/input/input.d.ts +7 -0
  61. package/dist/input/input.js +7 -5
  62. package/dist/input/input.js.map +1 -1
  63. package/dist/lib/field-shell.js +6 -3
  64. package/dist/lib/field-shell.js.map +1 -1
  65. package/dist/lib/field-surface.js +22 -1
  66. package/dist/lib/field-surface.js.map +1 -1
  67. package/dist/lib/required-marker.js +20 -0
  68. package/dist/lib/required-marker.js.map +1 -0
  69. package/dist/lib/use-copy-feedback.js +17 -3
  70. package/dist/lib/use-copy-feedback.js.map +1 -1
  71. package/dist/line-chart/index.d.ts +2 -2
  72. package/dist/line-chart/line-chart.d.ts +144 -2
  73. package/dist/line-chart/line-chart.js +314 -46
  74. package/dist/line-chart/line-chart.js.map +1 -1
  75. package/dist/money-input/index.d.ts +2 -2
  76. package/dist/money-input/money-input.d.ts +36 -1
  77. package/dist/money-input/money-input.js +30 -14
  78. package/dist/money-input/money-input.js.map +1 -1
  79. package/dist/morph-select/morph-select.d.ts +26 -1
  80. package/dist/morph-select/morph-select.js +28 -6
  81. package/dist/morph-select/morph-select.js.map +1 -1
  82. package/dist/multi-select/index.d.ts +2 -2
  83. package/dist/multi-select/index.js +2 -2
  84. package/dist/multi-select/multi-select.d.ts +74 -2
  85. package/dist/multi-select/multi-select.js +213 -39
  86. package/dist/multi-select/multi-select.js.map +1 -1
  87. package/dist/password-field/password-field.d.ts +16 -0
  88. package/dist/password-field/password-field.js +37 -8
  89. package/dist/password-field/password-field.js.map +1 -1
  90. package/dist/popover/index.d.ts +2 -2
  91. package/dist/popover/index.js +2 -2
  92. package/dist/popover/popover.d.ts +39 -2
  93. package/dist/popover/popover.js +29 -2
  94. package/dist/popover/popover.js.map +1 -1
  95. package/dist/progress/index.d.ts +2 -2
  96. package/dist/progress/index.js +2 -2
  97. package/dist/progress/progress.d.ts +68 -3
  98. package/dist/progress/progress.js +156 -39
  99. package/dist/progress/progress.js.map +1 -1
  100. package/dist/radio-group/index.d.ts +2 -2
  101. package/dist/radio-group/index.js +2 -2
  102. package/dist/radio-group/radio-group.d.ts +33 -3
  103. package/dist/radio-group/radio-group.js +109 -9
  104. package/dist/radio-group/radio-group.js.map +1 -1
  105. package/dist/scroll-area/scroll-area.js +4 -3
  106. package/dist/scroll-area/scroll-area.js.map +1 -1
  107. package/dist/scrub-input/scrub-input.d.ts +11 -1
  108. package/dist/scrub-input/scrub-input.js +22 -10
  109. package/dist/scrub-input/scrub-input.js.map +1 -1
  110. package/dist/search-field/search-field.d.ts +22 -1
  111. package/dist/search-field/search-field.js +22 -7
  112. package/dist/search-field/search-field.js.map +1 -1
  113. package/dist/select/select.d.ts +10 -1
  114. package/dist/select/select.js +11 -8
  115. package/dist/select/select.js.map +1 -1
  116. package/dist/separator/separator.d.ts +21 -9
  117. package/dist/separator/separator.js +33 -11
  118. package/dist/separator/separator.js.map +1 -1
  119. package/dist/sparkline/sparkline.d.ts +27 -2
  120. package/dist/sparkline/sparkline.js +115 -18
  121. package/dist/sparkline/sparkline.js.map +1 -1
  122. package/dist/stat-card/index.d.ts +2 -2
  123. package/dist/stat-card/index.js +2 -2
  124. package/dist/stat-card/stat-card.d.ts +65 -1
  125. package/dist/stat-card/stat-card.js +98 -25
  126. package/dist/stat-card/stat-card.js.map +1 -1
  127. package/dist/styles.css +1 -1
  128. package/dist/table/index.d.ts +2 -2
  129. package/dist/table/index.js +2 -2
  130. package/dist/table/table.d.ts +115 -5
  131. package/dist/table/table.js +374 -94
  132. package/dist/table/table.js.map +1 -1
  133. package/dist/text-shimmer/text-shimmer.d.ts +18 -2
  134. package/dist/text-shimmer/text-shimmer.js +5 -2
  135. package/dist/text-shimmer/text-shimmer.js.map +1 -1
  136. package/dist/textarea/textarea.d.ts +7 -0
  137. package/dist/textarea/textarea.js +3 -1
  138. package/dist/textarea/textarea.js.map +1 -1
  139. package/dist/time-picker/time-picker.d.ts +36 -1
  140. package/dist/time-picker/time-picker.js +33 -5
  141. package/dist/time-picker/time-picker.js.map +1 -1
  142. package/dist/toast/toast.d.ts +2 -2
  143. package/dist/usage-meter/index.d.ts +2 -2
  144. package/dist/usage-meter/usage-meter.d.ts +30 -0
  145. package/dist/usage-meter/usage-meter.js +56 -38
  146. package/dist/usage-meter/usage-meter.js.map +1 -1
  147. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"morph-select.js","names":[],"sources":["../../src/morph-select/morph-select.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n type FocusEvent,\n type KeyboardEvent,\n type ReactNode,\n} from \"react\";\n\nimport { labelVariants } from \"../label/label.js\";\nimport { cn, cnAll } from \"../lib/cn.js\";\nimport {\n prefersReducedMotion,\n useExitBackstop,\n useIsomorphicLayoutEffect,\n useLeavingItems,\n type Rect,\n} from \"../lib/motion.js\";\n\n/** One choice. */\nexport interface MorphSelectOption {\n value: string;\n label: string;\n /** A 20px mark shown before the label, in the list and in the trigger. An avatar or a plain icon. */\n icon?: ReactNode;\n /** Short trailing detail such as an offset or a count. Rendered with tabular numerals. */\n meta?: string;\n /** Extra words that match this option when searching. */\n keywords?: string;\n disabled?: boolean;\n}\n\n/** A labelled run of options. */\nexport interface MorphSelectGroup {\n label: string;\n options: MorphSelectOption[];\n}\n\nexport type MorphSelectItem = MorphSelectOption | MorphSelectGroup;\n\n/**\n * MorphSelect: a select whose trigger is the list. Opening grows the trigger itself\n * into the options surface (its width, height and corners spring from the closed\n * control to the open panel), a highlight glides between options, and the chosen\n * option's label lifts out of the list and settles into the trigger while the trigger\n * springs to its new width. Supports groups, type-ahead, search for long lists, and the\n * full listbox keyboard model: arrows, Home, End, PageUp, PageDown, Enter, Space,\n * Escape and Alt+ArrowUp.\n *\n * Use it for compact property pickers and form fields with up to a few hundred options.\n * Prefer a combobox when people mostly type free text, and Select when the list should\n * float over the page instead of growing from the trigger.\n *\n * It is its own listbox rather than a React Aria Select: a Select's list lives in a\n * popover, a separate surface that cannot be the trigger.\n */\nexport interface MorphSelectProps {\n /** Visible label, also the accessible name of the trigger and the list. */\n label: string;\n /** Keeps the label for assistive technology only. */\n labelHidden?: boolean;\n items: MorphSelectItem[];\n /** The chosen value. Controlled when given; `null` is nothing chosen. */\n value?: string | null;\n defaultValue?: string | null;\n onValueChange?: (value: string, option: MorphSelectOption) => void;\n /** Shown while nothing is chosen. @default \"Select\" */\n placeholder?: string;\n /** Shows a search field in place of the trigger when open. \"auto\" turns it on above eight options. @default \"auto\" */\n searchable?: boolean | \"auto\";\n searchPlaceholder?: string;\n /** Width of the open surface in px. It never gets narrower than the trigger. @default 272 */\n panelWidth?: number;\n /** Tallest the option list gets before it scrolls, in px. @default 296 */\n maxListHeight?: number;\n /** Which edge of the trigger stays put while the surface grows. @default \"start\" */\n align?: \"start\" | \"end\";\n /**\n * Control scale: the same heights as Select and Input.\n * @default \"md\"\n */\n size?: \"sm\" | \"md\" | \"lg\";\n /** Adds a hidden input for native form submission. */\n name?: string;\n disabled?: boolean;\n /** Extra classes for the wrapper. Merged last. */\n className?: string;\n}\n\ninterface Section {\n key: string;\n label?: string;\n options: MorphSelectOption[];\n}\ninterface Change {\n value: string | null;\n dir: number;\n fly: { x: number; y: number } | null;\n}\n\nconst TYPEAHEAD_RESET = 600;\nconst PAGE = 8;\n\nconst isGroup = (item: MorphSelectItem): item is MorphSelectGroup => \"options\" in item;\n\n/** Loose options between groups gather into unlabelled sections, so the list keeps the order it was given. */\nfunction normalize(items: MorphSelectItem[]): Section[] {\n const out: Section[] = [];\n items.forEach((item, index) => {\n if (isGroup(item)) {\n out.push({ key: `group-${index}`, label: item.label, options: item.options });\n return;\n }\n const last = out[out.length - 1];\n if (last && !last.label) last.options.push(item);\n else out.push({ key: `loose-${index}`, options: [item] });\n });\n return out;\n}\n\nconst matches = (option: MorphSelectOption, needle: string) =>\n `${option.label} ${option.meta ?? \"\"} ${option.keywords ?? \"\"}`.toLowerCase().includes(needle);\n\n/** The closed trigger's width, rounded up. offsetWidth rounds to the nearest pixel, and half a pixel short is enough to ellipsize the label. */\nfunction triggerWidth(node: HTMLElement) {\n const exact = node.getBoundingClientRect().width;\n const rounded = node.offsetWidth;\n // Under a scaled ancestor the rect is scaled too, so fall back to the layout width with a pixel of slack.\n return Math.abs(exact - rounded) <= 0.5 ? Math.ceil(exact - 0.01) : rounded + 1;\n}\n\n/** The layout the closed trigger and its invisible measuring copy share, so the copy's width is the trigger's. */\nconst triggerLayout =\n \"box-border flex h-(--ms-h) items-center gap-2 ps-(--ms-pad) pe-10 font-medium whitespace-nowrap\";\n\nconst iconClass =\n \"grid size-5 flex-none place-items-center text-text-secondary [&>svg]:size-4 [&>img]:size-5 [&>img]:rounded-full [&>img]:object-cover\";\n\n/** The label a layer shows: the icon, then the text, or the placeholder. */\nfunction Value({ option, placeholder }: { option: MorphSelectOption | undefined; placeholder: string }) {\n if (!option) return <span className=\"font-normal text-muted-foreground\">{placeholder}</span>;\n return (\n <>\n {option.icon ? (\n <span className={iconClass} aria-hidden=\"true\">\n {option.icon}\n </span>\n ) : null}\n <span className=\"min-w-0 truncate\">{option.label}</span>\n </>\n );\n}\n\n/** A replaced label on its way out, popped out of flow where it stood and lifting away. */\nfunction LeavingLayer({\n id,\n rect,\n dir,\n fly,\n onDone,\n children,\n}: {\n id: number;\n rect: Rect;\n dir: number;\n fly: boolean;\n onDone: (id: number) => void;\n children: ReactNode;\n}) {\n const remove = useCallback(() => onDone(id), [onDone, id]);\n useExitBackstop(true, remove);\n return (\n <span\n aria-hidden=\"true\"\n data-leaving=\"\"\n onAnimationEnd={(event) => {\n if (event.target === event.currentTarget) remove();\n }}\n // field-swap-out lifts by 0.3em times --dir: a label that flew to the trigger lifts 0.3em, one that rolled lifts 0.45em the way the list ran.\n style={{ ...rect, \"--dir\": fly ? 1 : dir * 1.5 } as CSSProperties}\n className=\"absolute flex min-w-0 items-center gap-2 motion-safe:animate-field-swap-out motion-reduce:animate-fade-out\"\n >\n {children}\n </span>\n );\n}\n\nexport function MorphSelect({\n label,\n labelHidden = false,\n items,\n value,\n defaultValue = null,\n onValueChange,\n placeholder = \"Select\",\n searchable = \"auto\",\n searchPlaceholder,\n panelWidth = 272,\n maxListHeight = 296,\n align = \"start\",\n size = \"md\",\n name,\n disabled = false,\n className,\n}: MorphSelectProps) {\n const uid = useId();\n const labelId = `${uid}-label`;\n const listId = `${uid}-list`;\n const optionId = (index: number) => `${uid}-option-${index}`;\n\n const rootRef = useRef<HTMLDivElement>(null);\n const anchorRef = useRef<HTMLDivElement>(null);\n const shapeRef = useRef<HTMLDivElement>(null);\n const measureRef = useRef<HTMLSpanElement>(null);\n const faceRef = useRef<HTMLDivElement>(null);\n const scrollRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLButtonElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const slotRef = useRef<HTMLSpanElement>(null);\n const layerRef = useRef<HTMLSpanElement>(null);\n const highlightRef = useRef<HTMLSpanElement>(null);\n const searchRowRef = useRef<HTMLDivElement>(null);\n const optionRefs = useRef(new Map<string, HTMLElement>());\n\n const sections = useMemo(() => normalize(items), [items]);\n const all = useMemo(() => sections.flatMap((section) => section.options), [sections]);\n const indexOf = useMemo(() => new Map(all.map((option, index) => [option.value, index])), [all]);\n const canSearch = searchable === \"auto\" ? all.length > 8 : searchable;\n\n const [inner, setInner] = useState<string | null>(defaultValue);\n const selected = value !== undefined ? value : inner;\n const selectedOption = selected === null ? undefined : all.find((option) => option.value === selected);\n\n const [open, setOpen] = useState(false);\n const [query, setQuery] = useState(\"\");\n const [active, setActive] = useState<string | null>(null);\n const [change, setChange] = useState<Change>({ value: null, dir: 1, fly: null });\n\n const needle = query.trim().toLowerCase();\n const visibleSections = useMemo(\n () =>\n needle\n ? sections\n .map((section) => ({\n ...section,\n options: section.options.filter((option) => matches(option, needle)),\n }))\n .filter((section) => section.options.length)\n : sections,\n [needle, sections],\n );\n const enabled = useMemo(\n () => visibleSections.flatMap((section) => section.options).filter((option) => !option.disabled),\n [visibleSections],\n );\n const current =\n active !== null && enabled.some((option) => option.value === active)\n ? active\n : (enabled[0]?.value ?? null);\n const resultCount = visibleSections.reduce((sum, section) => sum + section.options.length, 0);\n\n /* ---------------------------------------------- The shape ---------------------------------------------- */\n\n // One surface whose width and height follow the trigger and the open list. The sizes are written straight to the\n // two boxes, and the transitions in CSS do the moving, so a new label never waits on a render. Nothing animates\n // until the first measurement has landed (data-ready).\n const sizes = useRef({ trigger: 0, lid: 0, listW: 0, listH: 0 });\n const live = useRef({ open: false, anchorW: 0 });\n\n const place = useCallback(() => {\n const { trigger, lid, listW, listH } = sizes.current;\n const shape = shapeRef.current;\n const anchor = anchorRef.current;\n if (!trigger || !lid || !shape || !anchor) return;\n const isOpen = live.current.open;\n // A trigger that widens springs; one that narrows never overshoots, so it never dips under its label.\n if (trigger !== live.current.anchorW) {\n anchor.toggleAttribute(\"data-widening\", trigger > live.current.anchorW);\n live.current.anchorW = trigger;\n }\n anchor.style.width = `${trigger}px`;\n shape.style.width = `${isOpen ? Math.max(trigger, listW) : trigger}px`;\n shape.style.height = `${isOpen ? lid + listH : lid}px`;\n }, []);\n\n const read = useCallback(() => {\n const measure = measureRef.current;\n const face = faceRef.current;\n const root = rootRef.current;\n if (!measure || !face || !root) return;\n // The list is never narrower than the trigger; the width goes to CSS directly so a new label never waits on a render.\n const trigger = triggerWidth(measure);\n root.style.setProperty(\"--ms-trigger-w\", `${trigger}px`);\n sizes.current = {\n trigger,\n lid: measure.offsetHeight,\n listW: face.offsetWidth,\n listH: face.offsetHeight,\n };\n place();\n }, [place]);\n\n useIsomorphicLayoutEffect(() => {\n const measure = measureRef.current;\n const face = faceRef.current;\n const root = rootRef.current;\n if (!measure || !face || !root) return;\n read();\n // The first sizes are in place: from here on a change of size moves.\n void shapeRef.current?.offsetWidth;\n root.setAttribute(\"data-ready\", \"\");\n if (typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(read);\n observer.observe(measure);\n observer.observe(face);\n return () => observer.disconnect();\n }, [read]);\n\n useIsomorphicLayoutEffect(() => {\n if (live.current.open === open) return;\n live.current.open = open;\n // A pick changes the label and closes in the same commit, so both faces are read fresh before the shape moves.\n read();\n }, [open, read]);\n\n /* ---------------------------------------------- The highlight ---------------------------------------------- */\n\n const scrollIntent = useRef(false);\n useIsomorphicLayoutEffect(() => {\n const highlight = highlightRef.current;\n if (!highlight) return;\n const node = open && current !== null ? optionRefs.current.get(current) : undefined;\n if (!node) {\n highlight.removeAttribute(\"data-on\");\n return;\n }\n const top = node.offsetTop;\n const height = node.offsetHeight;\n // It appears where it is needed, and glides from there.\n highlight.toggleAttribute(\"data-jump\", !highlight.hasAttribute(\"data-on\") || prefersReducedMotion());\n highlight.style.translate = `0 ${top}px`;\n highlight.style.height = `${height}px`;\n highlight.setAttribute(\"data-on\", \"\");\n const scroller = scrollRef.current;\n if (scroller && scrollIntent.current) {\n scrollIntent.current = false;\n const pad = 6;\n if (top < scroller.scrollTop + pad) scroller.scrollTop = top - pad;\n else if (top + height > scroller.scrollTop + scroller.clientHeight - pad)\n scroller.scrollTop = top + height - scroller.clientHeight + pad;\n }\n }, [current, open, visibleSections]);\n\n /* ---------------------------------------------- Focus and keys ---------------------------------------------- */\n\n const showSearch = open && canSearch;\n // Written as attributes, since React 18 and 19 disagree about the `inert` prop and both agree about the attribute: the\n // closed list and the idle search row take no focus and are hidden from assistive technology; a search row in use replaces the trigger.\n useIsomorphicLayoutEffect(() => {\n triggerRef.current?.toggleAttribute(\"inert\", showSearch);\n searchRowRef.current?.toggleAttribute(\"inert\", !showSearch);\n const face = faceRef.current;\n if (!face) return;\n face.toggleAttribute(\"inert\", !open);\n if (open) face.removeAttribute(\"aria-hidden\");\n else face.setAttribute(\"aria-hidden\", \"true\");\n }, [open, showSearch]);\n\n // Focus lands in the lid: the search field when there is one, otherwise the trigger that keeps the active option.\n const pendingFocus = useRef<\"trigger\" | \"input\" | null>(null);\n useIsomorphicLayoutEffect(() => {\n const target = pendingFocus.current;\n pendingFocus.current = null;\n if (target === \"input\") inputRef.current?.focus({ preventScroll: true });\n if (target === \"trigger\") triggerRef.current?.focus({ preventScroll: true });\n }, [open]);\n\n const typeahead = useRef({ buffer: \"\", at: 0 });\n /** Space opens and picks on keydown; the click a button fires on the matching keyup must not undo it. */\n const suppressClick = useRef(false);\n const [announcement, setAnnouncement] = useState(\"\");\n\n function openList(focus?: string | null, seed = \"\") {\n if (disabled || open) return;\n setQuery(seed);\n setActive(focus !== undefined ? focus : selected);\n scrollIntent.current = true;\n pendingFocus.current = canSearch ? \"input\" : \"trigger\";\n setAnnouncement(\"\");\n setOpen(true);\n }\n\n const close = useCallback((restoreFocus: boolean) => {\n typeahead.current.buffer = \"\";\n if (restoreFocus) pendingFocus.current = \"trigger\";\n setOpen(false);\n }, []);\n\n function commit(option: MorphSelectOption | undefined, source?: HTMLElement | null) {\n if (!option || option.disabled) return;\n if (option.value !== selected) {\n // The chosen label starts where it stood in the list and settles into the trigger.\n let fly: Change[\"fly\"] = null;\n const slot = slotRef.current;\n const part = source?.querySelector<HTMLElement>(\"[data-part='value']\");\n if (!prefersReducedMotion() && part && slot) {\n const from = part.getBoundingClientRect();\n const to = slot.getBoundingClientRect();\n fly = { x: from.left - to.left, y: from.top + from.height / 2 - (to.top + to.height / 2) };\n }\n const from = selected === null ? -1 : (indexOf.get(selected) ?? -1);\n const to = indexOf.get(option.value) ?? 0;\n setChange({ value: option.value, dir: from < 0 ? 1 : Math.sign(to - from) || 1, fly });\n if (value === undefined) setInner(option.value);\n onValueChange?.(option.value, option);\n }\n close(true);\n }\n\n function typeTo(char: string) {\n const now = performance.now();\n const state = typeahead.current;\n state.buffer = now - state.at > TYPEAHEAD_RESET ? char : state.buffer + char;\n state.at = now;\n const buffer = state.buffer.toLowerCase();\n const repeated = buffer.split(\"\").every((letter) => letter === buffer[0]);\n const search = repeated ? buffer[0]! : buffer;\n const pool = all.filter((option) => !option.disabled);\n const from = open ? current : selected;\n const at = pool.findIndex((option) => option.value === from);\n const offset = repeated || buffer.length === 1 ? 1 : 0;\n const ordered = [...pool.slice(at + offset), ...pool.slice(0, at + offset)];\n return ordered.find((option) => option.label.toLowerCase().startsWith(search));\n }\n\n function move(to: string | null | undefined) {\n if (to === undefined || to === null) return;\n scrollIntent.current = true;\n setActive(to);\n }\n\n function onKey(event: KeyboardEvent<HTMLElement>, fromInput: boolean) {\n const { key } = event;\n if (key === \" \" && !fromInput) suppressClick.current = true;\n const printable = key.length === 1 && !event.metaKey && !event.ctrlKey && !event.altKey;\n const typing =\n performance.now() - typeahead.current.at < TYPEAHEAD_RESET && typeahead.current.buffer.length > 0;\n\n if (!open) {\n if (key === \"ArrowDown\" || key === \"ArrowUp\" || key === \"Enter\" || (key === \" \" && !typing)) {\n event.preventDefault();\n openList();\n return;\n }\n if (key === \"Home\" || key === \"End\") {\n event.preventDefault();\n const pool = all.filter((option) => !option.disabled);\n openList((key === \"Home\" ? pool[0] : pool[pool.length - 1])?.value ?? null);\n return;\n }\n if (printable) {\n event.preventDefault();\n if (canSearch) openList(undefined, key);\n else {\n const hit = typeTo(key);\n openList(hit?.value ?? selected);\n }\n }\n return;\n }\n\n const at = enabled.findIndex((option) => option.value === current);\n const caretKeys = fromInput && query.length > 0;\n const pick = () => commit(enabled[at], optionRefs.current.get(current ?? \"\"));\n switch (key) {\n case \"ArrowDown\":\n event.preventDefault();\n move(enabled[Math.min(enabled.length - 1, at + 1)]?.value);\n return;\n case \"ArrowUp\":\n event.preventDefault();\n if (event.altKey) {\n pick();\n return;\n }\n move(enabled[Math.max(0, at - 1)]?.value);\n return;\n case \"PageDown\":\n event.preventDefault();\n move(enabled[Math.min(enabled.length - 1, at + PAGE)]?.value);\n return;\n case \"PageUp\":\n event.preventDefault();\n move(enabled[Math.max(0, at - PAGE)]?.value);\n return;\n case \"Home\":\n if (caretKeys) return;\n event.preventDefault();\n move(enabled[0]?.value);\n return;\n case \"End\":\n if (caretKeys) return;\n event.preventDefault();\n move(enabled[enabled.length - 1]?.value);\n return;\n case \"Enter\":\n event.preventDefault();\n pick();\n return;\n case \"Escape\":\n event.preventDefault();\n event.stopPropagation();\n close(true);\n return;\n case \"Tab\":\n close(false);\n return;\n }\n if (fromInput) return;\n if (key === \" \" && !typing) {\n event.preventDefault();\n pick();\n return;\n }\n if (printable) {\n event.preventDefault();\n move(typeTo(key)?.value);\n }\n }\n\n // A press outside or focus leaving the control folds the list back into the trigger.\n useEffect(() => {\n if (!open) return;\n const down = (event: PointerEvent) => {\n if (!rootRef.current?.contains(event.target as Node)) close(false);\n };\n document.addEventListener(\"pointerdown\", down);\n return () => document.removeEventListener(\"pointerdown\", down);\n }, [close, open]);\n function onBlur(event: FocusEvent<HTMLDivElement>) {\n const next = event.relatedTarget as Node | null;\n if (open && next && !event.currentTarget.contains(next)) close(false);\n }\n\n function onQuery(next: string) {\n setQuery(next);\n setActive(null);\n scrollIntent.current = true;\n if (scrollRef.current) scrollRef.current.scrollTop = 0;\n const text = next.trim().toLowerCase();\n const count = text ? all.filter((option) => matches(option, text)).length : all.length;\n setAnnouncement(text ? (count ? `${count} ${count === 1 ? \"option\" : \"options\"}` : \"No matches\") : \"\");\n }\n\n /* ---------------------------------------------- The chosen label ---------------------------------------------- */\n\n // The trigger's value is a layer: a new one flies in from the list (or rolls, when it cannot) while the old one lifts away.\n const layerKey = selected ?? \"__empty\";\n const flying = change.value === selected ? change.fly : null;\n const { leaving, changed, remove } = useLeavingItems(\n layerKey,\n { key: layerKey, node: <Value option={selectedOption} placeholder={placeholder} />, dir: change.dir, fly: Boolean(flying) },\n () => layerRef.current,\n );\n\n const rootStyle = {\n \"--ms-panel-w\": `${panelWidth}px`,\n \"--ms-list-max\": `${maxListHeight}px`,\n } as CSSProperties;\n const layerStyle = {\n \"--dir\": change.dir,\n ...(flying ? { \"--fly-x\": `${flying.x}px`, \"--fly-y\": `${flying.y}px` } : {}),\n } as CSSProperties;\n\n return (\n <div\n ref={rootRef}\n data-slot=\"morph-select\"\n data-open={open || undefined}\n data-align={align}\n data-size={size}\n data-disabled={disabled || undefined}\n style={rootStyle}\n onBlur={onBlur}\n className={cn(\n \"morph-select-root group/ms relative inline-grid min-w-0 justify-items-start gap-2 font-sans leading-(--leading-normal) text-foreground data-[align=end]:justify-items-end data-[open]:z-30 data-[size=sm]:text-sm data-[size=md]:text-base data-[size=lg]:text-base\",\n className,\n )}\n >\n <span id={labelId} data-slot=\"morph-select-label\" className={cnAll(labelVariants(), labelHidden && \"sr-only\")}>\n {label}\n </span>\n\n <div ref={anchorRef} className=\"morph-select-anchor\">\n {/* Sizes the closed trigger. It holds the chosen label with the trigger's own padding, so the width has a target before anything moves. */}\n <span ref={measureRef} aria-hidden=\"true\" className={cnAll(triggerLayout, \"morph-select-measure\")}>\n <Value option={selectedOption} placeholder={placeholder} />\n </span>\n\n <div\n ref={shapeRef}\n data-slot=\"morph-select-shape\"\n data-open={open || undefined}\n data-disabled={disabled || undefined}\n className=\"morph-select-shape\"\n >\n {/* The lid is the trigger row. It stays at the top of the surface in both states and sits above the list, so a lifted label passes over it. */}\n <div className=\"absolute inset-x-0 top-0 z-10 h-(--ms-h)\">\n <button\n ref={triggerRef}\n type=\"button\"\n role=\"combobox\"\n data-slot=\"morph-select-trigger\"\n aria-labelledby={labelId}\n aria-haspopup=\"listbox\"\n aria-expanded={open}\n aria-controls={listId}\n aria-activedescendant={\n open && !canSearch && current !== null ? optionId(indexOf.get(current) ?? 0) : undefined\n }\n disabled={disabled}\n tabIndex={showSearch ? -1 : 0}\n onClick={() => {\n if (suppressClick.current) {\n suppressClick.current = false;\n return;\n }\n if (open) close(true);\n else openList();\n }}\n onKeyDown={(event) => onKey(event, false)}\n onKeyUp={(event) => {\n if (event.key === \" \")\n window.setTimeout(() => {\n suppressClick.current = false;\n });\n }}\n className={cnAll(\n triggerLayout,\n \"absolute inset-0 w-full cursor-pointer border-0 bg-transparent text-start text-foreground outline-none [font-family:inherit] [font-size:inherit] [line-height:inherit] [letter-spacing:inherit] [-webkit-tap-highlight-color:transparent] [touch-action:manipulation] disabled:cursor-not-allowed\",\n )}\n >\n <span\n ref={slotRef}\n data-hidden={showSearch || undefined}\n className=\"relative block h-full min-w-0 flex-1 data-[hidden]:opacity-0 motion-safe:transition-opacity motion-safe:duration-(--duration-instant) motion-safe:ease-settle\"\n >\n {leaving.map((item) => (\n <LeavingLayer\n key={item.id}\n id={item.id}\n rect={item.rect}\n dir={item.value.dir}\n fly={item.value.fly}\n onDone={remove}\n >\n {item.value.node}\n </LeavingLayer>\n ))}\n <span\n key={layerKey}\n ref={layerRef}\n style={layerStyle}\n className={cnAll(\n \"absolute inset-0 flex min-w-0 items-center gap-2\",\n changed &&\n (flying\n ? \"motion-safe:animate-morph-select-fly motion-reduce:animate-fade-in\"\n : \"motion-safe:animate-select-value-in motion-reduce:animate-fade-in\"),\n )}\n >\n <Value option={selectedOption} placeholder={placeholder} />\n </span>\n </span>\n </button>\n\n {canSearch ? (\n <div\n ref={searchRowRef}\n className={cnAll(\n \"absolute inset-0 flex items-center gap-2 ps-(--ms-pad) pe-1.5 motion-safe:transition-opacity motion-safe:duration-(--duration-quick) motion-safe:ease-settle\",\n showSearch ? \"opacity-100\" : \"pointer-events-none opacity-0\",\n )}\n >\n <svg\n aria-hidden=\"true\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.75\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"size-4 flex-none text-muted-foreground\"\n >\n <circle cx=\"7\" cy=\"7\" r=\"4.25\" />\n <path d=\"m10.5 10.5 3 3\" />\n </svg>\n <input\n ref={inputRef}\n type=\"text\"\n role=\"combobox\"\n data-slot=\"morph-select-search\"\n aria-label={`Search ${label.toLowerCase()}`}\n aria-expanded={open}\n aria-controls={listId}\n aria-autocomplete=\"list\"\n aria-activedescendant={\n open && current !== null ? optionId(indexOf.get(current) ?? 0) : undefined\n }\n placeholder={searchPlaceholder ?? selectedOption?.label ?? \"Search\"}\n value={query}\n autoComplete=\"off\"\n spellCheck={false}\n onChange={(event) => onQuery(event.target.value)}\n onKeyDown={(event) => onKey(event, true)}\n className=\"h-full min-w-0 flex-1 border-0 bg-transparent p-0 [font:inherit] text-foreground outline-none placeholder:text-muted-foreground\"\n />\n {query ? (\n <button\n type=\"button\"\n aria-label=\"Clear search\"\n onPointerDown={(event) => event.preventDefault()}\n onClick={() => {\n onQuery(\"\");\n inputRef.current?.focus();\n }}\n className=\"grid size-6 flex-none cursor-pointer place-items-center rounded-pill border-0 bg-muted p-0 text-text-secondary outline-none motion-safe:animate-field-clear-in motion-reduce:animate-fade-in hover:text-foreground\"\n >\n <svg\n aria-hidden=\"true\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.75\"\n strokeLinecap=\"round\"\n className=\"size-3.5\"\n >\n <path d=\"m4 4 8 8M12 4l-8 8\" />\n </svg>\n </button>\n ) : null}\n {/* Sits exactly over the shared chevron, so the chevron closes the list in both lid states. */}\n <button\n type=\"button\"\n aria-label={`Close ${label.toLowerCase()}`}\n onClick={() => close(true)}\n className=\"size-9 flex-none cursor-pointer rounded-pill border-0 bg-transparent p-0 outline-none motion-safe:transition-[background-color] motion-safe:duration-(--duration-quick) motion-safe:ease-settle hover:bg-muted\"\n />\n </div>\n ) : null}\n\n <svg\n aria-hidden=\"true\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.75\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"pointer-events-none absolute end-4 top-1/2 -mt-2 size-4 text-muted-foreground motion-safe:transition-[rotate] motion-safe:duration-(--duration-gentle) motion-safe:ease-gentle group-data-[open]/ms:rotate-180\"\n >\n <path d=\"m4 6 4 4 4-4\" />\n </svg>\n </div>\n\n <div\n ref={faceRef}\n data-open={open || undefined}\n className=\"morph-select-face\"\n >\n <div\n ref={scrollRef}\n className=\"max-h-(--ms-list-max) overflow-y-auto overscroll-contain pt-1.5 [scrollbar-width:thin]\"\n >\n <div id={listId} role=\"listbox\" aria-labelledby={labelId} className=\"relative grid grid-cols-1 gap-0.5\">\n <span ref={highlightRef} aria-hidden=\"true\" className=\"morph-select-highlight\" />\n {visibleSections.map((section) => {\n const rows = section.options.map((option) => {\n const index = indexOf.get(option.value) ?? 0;\n const isSelected = option.value === selected;\n return (\n <div\n key={option.value}\n id={optionId(index)}\n role=\"option\"\n aria-selected={isSelected}\n aria-disabled={option.disabled || undefined}\n data-slot=\"morph-select-option\"\n data-active={option.value === current || undefined}\n ref={(node) => {\n if (node) optionRefs.current.set(option.value, node);\n else optionRefs.current.delete(option.value);\n }}\n onPointerMove={(event) => {\n if (event.pointerType === \"mouse\" && !option.disabled && option.value !== current)\n setActive(option.value);\n }}\n onPointerDown={(event) => event.preventDefault()}\n onClick={(event) => commit(option, event.currentTarget)}\n className=\"morph-select-option relative box-border flex min-h-9 cursor-pointer select-none items-center gap-2 rounded-lg text-text-secondary outline-none data-[active]:text-foreground aria-selected:text-foreground aria-disabled:cursor-not-allowed aria-disabled:opacity-(--opacity-disabled) motion-safe:transition-colors motion-safe:duration-(--duration-quick) motion-safe:ease-settle\"\n >\n <span data-part=\"value\" className=\"flex min-w-0 flex-1 items-center gap-2 font-medium\">\n {option.icon ? (\n <span className={iconClass} aria-hidden=\"true\">\n {option.icon}\n </span>\n ) : null}\n <span className=\"min-w-0 truncate\">{option.label}</span>\n </span>\n {option.meta ? (\n <span className=\"flex-none text-xs tabular-nums text-muted-foreground\">\n {option.meta}\n </span>\n ) : null}\n <span\n aria-hidden=\"true\"\n data-on={isSelected || undefined}\n className=\"grid size-4 flex-none scale-60 place-items-center text-foreground opacity-0 data-[on]:scale-100 data-[on]:opacity-100 motion-safe:transition-[opacity,scale] motion-safe:duration-(--duration-quick) motion-safe:ease-settle\"\n >\n <svg\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.75\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"size-4\"\n >\n <path d=\"m3.5 8.5 3 3 6-6\" />\n </svg>\n </span>\n </div>\n );\n });\n return section.label ? (\n <div\n key={section.key}\n role=\"group\"\n aria-labelledby={`${uid}-${section.key}`}\n className=\"grid grid-cols-1 gap-0.5 not-first:mt-1\"\n >\n <div\n id={`${uid}-${section.key}`}\n role=\"presentation\"\n className=\"px-2.5 pt-2 pb-1 text-xs text-muted-foreground\"\n >\n {section.label}\n </div>\n {rows}\n </div>\n ) : (\n <div key={section.key} role=\"presentation\" className=\"grid grid-cols-1 gap-0.5 not-first:mt-1\">\n {rows}\n </div>\n );\n })}\n {resultCount === 0 ? (\n <p className=\"m-0 px-2.5 pt-3 pb-3.5 text-sm text-muted-foreground\">\n No matches for “{query.trim()}”\n </p>\n ) : null}\n </div>\n </div>\n </div>\n </div>\n </div>\n\n {name ? <input type=\"hidden\" name={name} value={selected ?? \"\"} /> : null}\n <span className=\"sr-only\" role=\"status\" aria-live=\"polite\">\n {announcement}\n </span>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"morph-select.js","names":[],"sources":["../../src/morph-select/morph-select.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n type FocusEvent,\n type KeyboardEvent,\n type ReactNode,\n} from \"react\";\n\nimport { labelVariants } from \"../label/label.js\";\nimport { cn, cnAll } from \"../lib/cn.js\";\nimport {\n prefersReducedMotion,\n useExitBackstop,\n useIsomorphicLayoutEffect,\n useLeavingItems,\n type Rect,\n} from \"../lib/motion.js\";\n\n/** One choice. */\nexport interface MorphSelectOption {\n value: string;\n label: string;\n /** A 20px mark shown before the label, in the list and in the trigger. An avatar or a plain icon. */\n icon?: ReactNode;\n /** Short trailing detail such as an offset or a count. Rendered with tabular numerals. */\n meta?: string;\n /** Extra words that match this option when searching. */\n keywords?: string;\n disabled?: boolean;\n}\n\n/** A labelled run of options. */\nexport interface MorphSelectGroup {\n label: string;\n options: MorphSelectOption[];\n}\n\nexport type MorphSelectItem = MorphSelectOption | MorphSelectGroup;\n\n/**\n * MorphSelect: a select whose trigger is the list. Opening grows the trigger itself\n * into the options surface (its width, height and corners spring from the closed\n * control to the open panel), a highlight glides between options, and the chosen\n * option's label lifts out of the list and settles into the trigger while the trigger\n * springs to its new width. Supports groups, type-ahead, search for long lists, and the\n * full listbox keyboard model: arrows, Home, End, PageUp, PageDown, Enter, Space,\n * Escape and Alt+ArrowUp.\n *\n * Use it for compact property pickers and form fields with up to a few hundred options.\n * Prefer a combobox when people mostly type free text, and Select when the list should\n * float over the page instead of growing from the trigger.\n *\n * It is its own listbox rather than a React Aria Select: a Select's list lives in a\n * popover, a separate surface that cannot be the trigger.\n */\nexport interface MorphSelectProps {\n /** Visible label, also the accessible name of the trigger and the list. */\n label: string;\n /** Keeps the label for assistive technology only. */\n labelHidden?: boolean;\n items: MorphSelectItem[];\n /** The chosen value. Controlled when given; `null` is nothing chosen. */\n value?: string | null;\n defaultValue?: string | null;\n onValueChange?: (value: string, option: MorphSelectOption) => void;\n /** Shown while nothing is chosen. @default \"Select\" */\n placeholder?: string;\n /** Shows a search field in place of the trigger when open. \"auto\" turns it on above eight options. @default \"auto\" */\n searchable?: boolean | \"auto\";\n searchPlaceholder?: string;\n /** Width of the open surface in px. It never gets narrower than the trigger. @default 272 */\n panelWidth?: number;\n /** Tallest the option list gets before it scrolls, in px. @default 296 */\n maxListHeight?: number;\n /** Which edge of the trigger stays put while the surface grows. @default \"start\" */\n align?: \"start\" | \"end\";\n /**\n * Control scale: the same heights as Select and Input.\n * @default \"md\"\n */\n size?: \"sm\" | \"md\" | \"lg\";\n /** Adds a hidden input for native form submission. */\n name?: string;\n disabled?: boolean;\n /**\n * The trigger's `id`, so a `<label htmlFor>` outside the select (or a form\n * library that focuses a field by id) reaches the real control. When such a\n * label exists it NAMES the trigger: the trigger then drops its\n * `aria-labelledby` to the inner `label`, which would otherwise outrank the\n * outside label in the accessible-name computation.\n */\n id?: string;\n /**\n * Marks the choice as wrong: the trigger takes the invalid border and is\n * `aria-invalid`. Pair it with `errorMessage`, or the state is shown visually in colour only.\n */\n isInvalid?: boolean;\n /**\n * Why the choice is wrong, under the control. It shows only while `isInvalid`\n * is set, and is named in the trigger's and the search field's `aria-describedby`.\n */\n errorMessage?: ReactNode;\n /**\n * Stretches the trigger to fill its container, like Input and Select, instead of hugging\n * its content up to 20rem. The open surface is then as wide as the trigger. `panelWidth`\n * does not apply.\n * @default false\n */\n fullWidth?: boolean;\n /** Extra classes for the wrapper. Merged last. */\n className?: string;\n}\n\ninterface Section {\n key: string;\n label?: string;\n options: MorphSelectOption[];\n}\ninterface Change {\n value: string | null;\n dir: number;\n fly: { x: number; y: number } | null;\n}\n\nconst TYPEAHEAD_RESET = 600;\nconst PAGE = 8;\n\nconst isGroup = (item: MorphSelectItem): item is MorphSelectGroup => \"options\" in item;\n\n/** Loose options between groups gather into unlabelled sections, so the list keeps the order it was given. */\nfunction normalize(items: MorphSelectItem[]): Section[] {\n const out: Section[] = [];\n items.forEach((item, index) => {\n if (isGroup(item)) {\n out.push({ key: `group-${index}`, label: item.label, options: item.options });\n return;\n }\n const last = out[out.length - 1];\n if (last && !last.label) last.options.push(item);\n else out.push({ key: `loose-${index}`, options: [item] });\n });\n return out;\n}\n\nconst matches = (option: MorphSelectOption, needle: string) =>\n `${option.label} ${option.meta ?? \"\"} ${option.keywords ?? \"\"}`.toLowerCase().includes(needle);\n\n/** The closed trigger's width, rounded up. offsetWidth rounds to the nearest pixel, and half a pixel short is enough to ellipsize the label. */\nfunction triggerWidth(node: HTMLElement) {\n const exact = node.getBoundingClientRect().width;\n const rounded = node.offsetWidth;\n // Under a scaled ancestor the rect is scaled too, so fall back to the layout width with a pixel of slack.\n return Math.abs(exact - rounded) <= 0.5 ? Math.ceil(exact - 0.01) : rounded + 1;\n}\n\n/** The layout the closed trigger and its invisible measuring copy share, so the copy's width is the trigger's. */\nconst triggerLayout =\n \"box-border flex h-(--ms-h) items-center gap-2 ps-(--ms-pad) pe-10 font-medium whitespace-nowrap\";\n\nconst iconClass =\n \"grid size-5 flex-none place-items-center text-text-secondary [&>svg]:size-4 [&>img]:size-5 [&>img]:rounded-full [&>img]:object-cover\";\n\n/** The label a layer shows: the icon, then the text, or the placeholder. */\nfunction Value({ option, placeholder }: { option: MorphSelectOption | undefined; placeholder: string }) {\n if (!option) return <span className=\"font-normal text-muted-foreground\">{placeholder}</span>;\n return (\n <>\n {option.icon ? (\n <span className={iconClass} aria-hidden=\"true\">\n {option.icon}\n </span>\n ) : null}\n <span className=\"min-w-0 truncate\">{option.label}</span>\n </>\n );\n}\n\n/** A replaced label on its way out, popped out of flow where it stood and lifting away. */\nfunction LeavingLayer({\n id,\n rect,\n dir,\n fly,\n onDone,\n children,\n}: {\n id: number;\n rect: Rect;\n dir: number;\n fly: boolean;\n onDone: (id: number) => void;\n children: ReactNode;\n}) {\n const remove = useCallback(() => onDone(id), [onDone, id]);\n useExitBackstop(true, remove);\n return (\n <span\n aria-hidden=\"true\"\n data-leaving=\"\"\n onAnimationEnd={(event) => {\n if (event.target === event.currentTarget) remove();\n }}\n // field-swap-out lifts by 0.3em times --dir: a label that flew to the trigger lifts 0.3em, one that rolled lifts 0.45em the way the list ran.\n style={{ ...rect, \"--dir\": fly ? 1 : dir * 1.5 } as CSSProperties}\n className=\"absolute flex min-w-0 items-center gap-2 motion-safe:animate-field-swap-out motion-reduce:animate-fade-out\"\n >\n {children}\n </span>\n );\n}\n\nexport function MorphSelect({\n label,\n labelHidden = false,\n items,\n value,\n defaultValue = null,\n onValueChange,\n placeholder = \"Select\",\n searchable = \"auto\",\n searchPlaceholder,\n panelWidth = 272,\n maxListHeight = 296,\n align = \"start\",\n size = \"md\",\n name,\n disabled = false,\n id,\n isInvalid = false,\n errorMessage,\n fullWidth = false,\n className,\n}: MorphSelectProps) {\n const uid = useId();\n const labelId = `${uid}-label`;\n const errorId = `${uid}-error`;\n // As on Select: the message shows only while the field is invalid.\n const showError = isInvalid && errorMessage != null;\n const listId = `${uid}-list`;\n const optionId = (index: number) => `${uid}-option-${index}`;\n\n const rootRef = useRef<HTMLDivElement>(null);\n const anchorRef = useRef<HTMLDivElement>(null);\n const shapeRef = useRef<HTMLDivElement>(null);\n const measureRef = useRef<HTMLSpanElement>(null);\n const faceRef = useRef<HTMLDivElement>(null);\n const scrollRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLButtonElement>(null);\n // An outside <label htmlFor={id}> names the trigger natively. aria-labelledby\n // outranks it, so while one exists the trigger does not point at the inner label.\n const [outsideLabel, setOutsideLabel] = useState(false);\n const inputRef = useRef<HTMLInputElement>(null);\n const slotRef = useRef<HTMLSpanElement>(null);\n const layerRef = useRef<HTMLSpanElement>(null);\n const highlightRef = useRef<HTMLSpanElement>(null);\n const searchRowRef = useRef<HTMLDivElement>(null);\n const optionRefs = useRef(new Map<string, HTMLElement>());\n\n const sections = useMemo(() => normalize(items), [items]);\n const all = useMemo(() => sections.flatMap((section) => section.options), [sections]);\n const indexOf = useMemo(() => new Map(all.map((option, index) => [option.value, index])), [all]);\n const canSearch = searchable === \"auto\" ? all.length > 8 : searchable;\n\n const [inner, setInner] = useState<string | null>(defaultValue);\n const selected = value !== undefined ? value : inner;\n const selectedOption = selected === null ? undefined : all.find((option) => option.value === selected);\n\n const [open, setOpen] = useState(false);\n const [query, setQuery] = useState(\"\");\n const [active, setActive] = useState<string | null>(null);\n const [change, setChange] = useState<Change>({ value: null, dir: 1, fly: null });\n\n const needle = query.trim().toLowerCase();\n const visibleSections = useMemo(\n () =>\n needle\n ? sections\n .map((section) => ({\n ...section,\n options: section.options.filter((option) => matches(option, needle)),\n }))\n .filter((section) => section.options.length)\n : sections,\n [needle, sections],\n );\n const enabled = useMemo(\n () => visibleSections.flatMap((section) => section.options).filter((option) => !option.disabled),\n [visibleSections],\n );\n const current =\n active !== null && enabled.some((option) => option.value === active)\n ? active\n : (enabled[0]?.value ?? null);\n const resultCount = visibleSections.reduce((sum, section) => sum + section.options.length, 0);\n\n /* ---------------------------------------------- The shape ---------------------------------------------- */\n\n // One surface whose width and height follow the trigger and the open list. The sizes are written straight to the\n // two boxes, and the transitions in CSS do the moving, so a new label never waits on a render. Nothing animates\n // until the first measurement has landed (data-ready).\n const sizes = useRef({ trigger: 0, lid: 0, listW: 0, listH: 0 });\n const live = useRef({ open: false, anchorW: 0, full: fullWidth });\n\n const place = useCallback(() => {\n const { trigger, lid, listW, listH } = sizes.current;\n const shape = shapeRef.current;\n const anchor = anchorRef.current;\n if (!trigger || !lid || !shape || !anchor) return;\n const isOpen = live.current.open;\n // A trigger that widens springs; one that narrows never overshoots, so it never dips under its label.\n if (trigger !== live.current.anchorW) {\n anchor.toggleAttribute(\"data-widening\", trigger > live.current.anchorW);\n live.current.anchorW = trigger;\n }\n // Full width: the anchor is 100% in CSS, so it follows the container; only the shape needs the pixel width.\n anchor.style.width = live.current.full ? \"\" : `${trigger}px`;\n shape.style.width = `${isOpen ? Math.max(trigger, listW) : trigger}px`;\n shape.style.height = `${isOpen ? lid + listH : lid}px`;\n }, []);\n\n const read = useCallback(() => {\n const measure = measureRef.current;\n const face = faceRef.current;\n const root = rootRef.current;\n if (!measure || !face || !root) return;\n // The list is never narrower than the trigger; the width goes to CSS directly so a new label never waits on a render.\n const trigger = triggerWidth(measure);\n root.style.setProperty(\"--ms-trigger-w\", `${trigger}px`);\n sizes.current = {\n trigger,\n lid: measure.offsetHeight,\n listW: face.offsetWidth,\n listH: face.offsetHeight,\n };\n place();\n }, [place]);\n\n useIsomorphicLayoutEffect(() => {\n live.current.full = fullWidth;\n const measure = measureRef.current;\n const face = faceRef.current;\n const root = rootRef.current;\n if (!measure || !face || !root) return;\n read();\n // The first sizes are in place: from here on a change of size moves.\n void shapeRef.current?.offsetWidth;\n root.setAttribute(\"data-ready\", \"\");\n if (typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(read);\n observer.observe(measure);\n observer.observe(face);\n return () => observer.disconnect();\n }, [read, fullWidth]);\n\n useIsomorphicLayoutEffect(() => {\n if (live.current.open === open) return;\n live.current.open = open;\n // A pick changes the label and closes in the same commit, so both faces are read fresh before the shape moves.\n read();\n }, [open, read]);\n\n /* ---------------------------------------------- The highlight ---------------------------------------------- */\n\n const scrollIntent = useRef(false);\n useIsomorphicLayoutEffect(() => {\n const highlight = highlightRef.current;\n if (!highlight) return;\n const node = open && current !== null ? optionRefs.current.get(current) : undefined;\n if (!node) {\n highlight.removeAttribute(\"data-on\");\n return;\n }\n const top = node.offsetTop;\n const height = node.offsetHeight;\n // It appears where it is needed, and glides from there.\n highlight.toggleAttribute(\"data-jump\", !highlight.hasAttribute(\"data-on\") || prefersReducedMotion());\n highlight.style.translate = `0 ${top}px`;\n highlight.style.height = `${height}px`;\n highlight.setAttribute(\"data-on\", \"\");\n const scroller = scrollRef.current;\n if (scroller && scrollIntent.current) {\n scrollIntent.current = false;\n const pad = 6;\n if (top < scroller.scrollTop + pad) scroller.scrollTop = top - pad;\n else if (top + height > scroller.scrollTop + scroller.clientHeight - pad)\n scroller.scrollTop = top + height - scroller.clientHeight + pad;\n }\n }, [current, open, visibleSections]);\n\n /* ---------------------------------------------- Focus and keys ---------------------------------------------- */\n\n useIsomorphicLayoutEffect(() => {\n setOutsideLabel(id != null && (triggerRef.current?.labels?.length ?? 0) > 0);\n }, [id]);\n\n const showSearch = open && canSearch;\n // Written as attributes, since React 18 and 19 disagree about the `inert` prop and both agree about the attribute: the\n // closed list and the idle search row take no focus and are hidden from assistive technology; a search row in use replaces the trigger.\n useIsomorphicLayoutEffect(() => {\n triggerRef.current?.toggleAttribute(\"inert\", showSearch);\n searchRowRef.current?.toggleAttribute(\"inert\", !showSearch);\n const face = faceRef.current;\n if (!face) return;\n face.toggleAttribute(\"inert\", !open);\n if (open) face.removeAttribute(\"aria-hidden\");\n else face.setAttribute(\"aria-hidden\", \"true\");\n }, [open, showSearch]);\n\n // Focus lands in the lid: the search field when there is one, otherwise the trigger that keeps the active option.\n const pendingFocus = useRef<\"trigger\" | \"input\" | null>(null);\n useIsomorphicLayoutEffect(() => {\n const target = pendingFocus.current;\n pendingFocus.current = null;\n if (target === \"input\") inputRef.current?.focus({ preventScroll: true });\n if (target === \"trigger\") triggerRef.current?.focus({ preventScroll: true });\n }, [open]);\n\n const typeahead = useRef({ buffer: \"\", at: 0 });\n /** Space opens and picks on keydown; the click a button fires on the matching keyup must not undo it. */\n const suppressClick = useRef(false);\n const [announcement, setAnnouncement] = useState(\"\");\n\n function openList(focus?: string | null, seed = \"\") {\n if (disabled || open) return;\n setQuery(seed);\n setActive(focus !== undefined ? focus : selected);\n scrollIntent.current = true;\n pendingFocus.current = canSearch ? \"input\" : \"trigger\";\n setAnnouncement(\"\");\n setOpen(true);\n }\n\n const close = useCallback((restoreFocus: boolean) => {\n typeahead.current.buffer = \"\";\n if (restoreFocus) pendingFocus.current = \"trigger\";\n setOpen(false);\n }, []);\n\n function commit(option: MorphSelectOption | undefined, source?: HTMLElement | null) {\n if (!option || option.disabled) return;\n if (option.value !== selected) {\n // The chosen label starts where it stood in the list and settles into the trigger.\n let fly: Change[\"fly\"] = null;\n const slot = slotRef.current;\n const part = source?.querySelector<HTMLElement>(\"[data-part='value']\");\n if (!prefersReducedMotion() && part && slot) {\n const from = part.getBoundingClientRect();\n const to = slot.getBoundingClientRect();\n fly = { x: from.left - to.left, y: from.top + from.height / 2 - (to.top + to.height / 2) };\n }\n const from = selected === null ? -1 : (indexOf.get(selected) ?? -1);\n const to = indexOf.get(option.value) ?? 0;\n setChange({ value: option.value, dir: from < 0 ? 1 : Math.sign(to - from) || 1, fly });\n if (value === undefined) setInner(option.value);\n onValueChange?.(option.value, option);\n }\n close(true);\n }\n\n function typeTo(char: string) {\n const now = performance.now();\n const state = typeahead.current;\n state.buffer = now - state.at > TYPEAHEAD_RESET ? char : state.buffer + char;\n state.at = now;\n const buffer = state.buffer.toLowerCase();\n const repeated = buffer.split(\"\").every((letter) => letter === buffer[0]);\n const search = repeated ? buffer[0]! : buffer;\n const pool = all.filter((option) => !option.disabled);\n const from = open ? current : selected;\n const at = pool.findIndex((option) => option.value === from);\n const offset = repeated || buffer.length === 1 ? 1 : 0;\n const ordered = [...pool.slice(at + offset), ...pool.slice(0, at + offset)];\n return ordered.find((option) => option.label.toLowerCase().startsWith(search));\n }\n\n function move(to: string | null | undefined) {\n if (to === undefined || to === null) return;\n scrollIntent.current = true;\n setActive(to);\n }\n\n function onKey(event: KeyboardEvent<HTMLElement>, fromInput: boolean) {\n const { key } = event;\n if (key === \" \" && !fromInput) suppressClick.current = true;\n const printable = key.length === 1 && !event.metaKey && !event.ctrlKey && !event.altKey;\n const typing =\n performance.now() - typeahead.current.at < TYPEAHEAD_RESET && typeahead.current.buffer.length > 0;\n\n if (!open) {\n if (key === \"ArrowDown\" || key === \"ArrowUp\" || key === \"Enter\" || (key === \" \" && !typing)) {\n event.preventDefault();\n openList();\n return;\n }\n if (key === \"Home\" || key === \"End\") {\n event.preventDefault();\n const pool = all.filter((option) => !option.disabled);\n openList((key === \"Home\" ? pool[0] : pool[pool.length - 1])?.value ?? null);\n return;\n }\n if (printable) {\n event.preventDefault();\n if (canSearch) openList(undefined, key);\n else {\n const hit = typeTo(key);\n openList(hit?.value ?? selected);\n }\n }\n return;\n }\n\n const at = enabled.findIndex((option) => option.value === current);\n const caretKeys = fromInput && query.length > 0;\n const pick = () => commit(enabled[at], optionRefs.current.get(current ?? \"\"));\n switch (key) {\n case \"ArrowDown\":\n event.preventDefault();\n move(enabled[Math.min(enabled.length - 1, at + 1)]?.value);\n return;\n case \"ArrowUp\":\n event.preventDefault();\n if (event.altKey) {\n pick();\n return;\n }\n move(enabled[Math.max(0, at - 1)]?.value);\n return;\n case \"PageDown\":\n event.preventDefault();\n move(enabled[Math.min(enabled.length - 1, at + PAGE)]?.value);\n return;\n case \"PageUp\":\n event.preventDefault();\n move(enabled[Math.max(0, at - PAGE)]?.value);\n return;\n case \"Home\":\n if (caretKeys) return;\n event.preventDefault();\n move(enabled[0]?.value);\n return;\n case \"End\":\n if (caretKeys) return;\n event.preventDefault();\n move(enabled[enabled.length - 1]?.value);\n return;\n case \"Enter\":\n event.preventDefault();\n pick();\n return;\n case \"Escape\":\n event.preventDefault();\n event.stopPropagation();\n close(true);\n return;\n case \"Tab\":\n close(false);\n return;\n }\n if (fromInput) return;\n if (key === \" \" && !typing) {\n event.preventDefault();\n pick();\n return;\n }\n if (printable) {\n event.preventDefault();\n move(typeTo(key)?.value);\n }\n }\n\n // A press outside or focus leaving the control folds the list back into the trigger.\n useEffect(() => {\n if (!open) return;\n const down = (event: PointerEvent) => {\n if (!rootRef.current?.contains(event.target as Node)) close(false);\n };\n document.addEventListener(\"pointerdown\", down);\n return () => document.removeEventListener(\"pointerdown\", down);\n }, [close, open]);\n function onBlur(event: FocusEvent<HTMLDivElement>) {\n const next = event.relatedTarget as Node | null;\n if (open && next && !event.currentTarget.contains(next)) close(false);\n }\n\n function onQuery(next: string) {\n setQuery(next);\n setActive(null);\n scrollIntent.current = true;\n if (scrollRef.current) scrollRef.current.scrollTop = 0;\n const text = next.trim().toLowerCase();\n const count = text ? all.filter((option) => matches(option, text)).length : all.length;\n setAnnouncement(text ? (count ? `${count} ${count === 1 ? \"option\" : \"options\"}` : \"No matches\") : \"\");\n }\n\n /* ---------------------------------------------- The chosen label ---------------------------------------------- */\n\n // The trigger's value is a layer: a new one flies in from the list (or rolls, when it cannot) while the old one lifts away.\n const layerKey = selected ?? \"__empty\";\n const flying = change.value === selected ? change.fly : null;\n const { leaving, changed, remove } = useLeavingItems(\n layerKey,\n { key: layerKey, node: <Value option={selectedOption} placeholder={placeholder} />, dir: change.dir, fly: Boolean(flying) },\n () => layerRef.current,\n );\n\n const rootStyle = {\n \"--ms-panel-w\": `${panelWidth}px`,\n \"--ms-list-max\": `${maxListHeight}px`,\n } as CSSProperties;\n const layerStyle = {\n \"--dir\": change.dir,\n ...(flying ? { \"--fly-x\": `${flying.x}px`, \"--fly-y\": `${flying.y}px` } : {}),\n } as CSSProperties;\n\n return (\n <div\n ref={rootRef}\n data-slot=\"morph-select\"\n data-open={open || undefined}\n data-align={align}\n data-full={fullWidth || undefined}\n data-size={size}\n data-disabled={disabled || undefined}\n data-invalid={isInvalid || undefined}\n style={rootStyle}\n onBlur={onBlur}\n className={cn(\n \"morph-select-root group/ms relative inline-grid data-[full]:grid data-[full]:w-full min-w-0 justify-items-start gap-2 font-sans leading-(--leading-normal) text-foreground data-[align=end]:justify-items-end data-[open]:z-30 data-[size=sm]:text-sm data-[size=md]:text-base data-[size=lg]:text-base\",\n className,\n )}\n >\n <span id={labelId} data-slot=\"morph-select-label\" className={cnAll(labelVariants(), labelHidden && \"sr-only\")}>\n {label}\n </span>\n\n <div ref={anchorRef} className=\"morph-select-anchor\">\n {/* Sizes the closed trigger. It holds the chosen label with the trigger's own padding, so the width has a target before anything moves. */}\n <span ref={measureRef} aria-hidden=\"true\" className={cnAll(triggerLayout, \"morph-select-measure\")}>\n <Value option={selectedOption} placeholder={placeholder} />\n </span>\n\n <div\n ref={shapeRef}\n data-slot=\"morph-select-shape\"\n data-open={open || undefined}\n data-disabled={disabled || undefined}\n data-invalid={isInvalid || undefined}\n className=\"morph-select-shape\"\n >\n {/* The lid is the trigger row. It stays at the top of the surface in both states and sits above the list, so a lifted label passes over it. */}\n <div className=\"absolute inset-x-0 top-0 z-10 h-(--ms-h)\">\n <button\n ref={triggerRef}\n id={id}\n type=\"button\"\n role=\"combobox\"\n data-slot=\"morph-select-trigger\"\n aria-labelledby={outsideLabel ? undefined : labelId}\n aria-invalid={isInvalid || undefined}\n aria-describedby={showError ? errorId : undefined}\n aria-haspopup=\"listbox\"\n aria-expanded={open}\n aria-controls={listId}\n aria-activedescendant={\n open && !canSearch && current !== null ? optionId(indexOf.get(current) ?? 0) : undefined\n }\n disabled={disabled}\n tabIndex={showSearch ? -1 : 0}\n onClick={() => {\n if (suppressClick.current) {\n suppressClick.current = false;\n return;\n }\n if (open) close(true);\n else openList();\n }}\n onKeyDown={(event) => onKey(event, false)}\n onKeyUp={(event) => {\n if (event.key === \" \")\n window.setTimeout(() => {\n suppressClick.current = false;\n });\n }}\n className={cnAll(\n triggerLayout,\n \"absolute inset-0 w-full cursor-pointer border-0 bg-transparent text-start text-foreground outline-none [font-family:inherit] [font-size:inherit] [line-height:inherit] [letter-spacing:inherit] [-webkit-tap-highlight-color:transparent] [touch-action:manipulation] disabled:cursor-not-allowed\",\n )}\n >\n <span\n ref={slotRef}\n data-hidden={showSearch || undefined}\n className=\"relative block h-full min-w-0 flex-1 data-[hidden]:opacity-0 motion-safe:transition-opacity motion-safe:duration-(--duration-instant) motion-safe:ease-settle\"\n >\n {leaving.map((item) => (\n <LeavingLayer\n key={item.id}\n id={item.id}\n rect={item.rect}\n dir={item.value.dir}\n fly={item.value.fly}\n onDone={remove}\n >\n {item.value.node}\n </LeavingLayer>\n ))}\n <span\n key={layerKey}\n ref={layerRef}\n style={layerStyle}\n className={cnAll(\n \"absolute inset-0 flex min-w-0 items-center gap-2\",\n changed &&\n (flying\n ? \"motion-safe:animate-morph-select-fly motion-reduce:animate-fade-in\"\n : \"motion-safe:animate-select-value-in motion-reduce:animate-fade-in\"),\n )}\n >\n <Value option={selectedOption} placeholder={placeholder} />\n </span>\n </span>\n </button>\n\n {canSearch ? (\n <div\n ref={searchRowRef}\n className={cnAll(\n \"absolute inset-0 flex items-center gap-2 ps-(--ms-pad) pe-1.5 motion-safe:transition-opacity motion-safe:duration-(--duration-quick) motion-safe:ease-settle\",\n showSearch ? \"opacity-100\" : \"pointer-events-none opacity-0\",\n )}\n >\n <svg\n aria-hidden=\"true\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.75\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"size-4 flex-none text-muted-foreground\"\n >\n <circle cx=\"7\" cy=\"7\" r=\"4.25\" />\n <path d=\"m10.5 10.5 3 3\" />\n </svg>\n <input\n ref={inputRef}\n type=\"text\"\n role=\"combobox\"\n data-slot=\"morph-select-search\"\n aria-label={`Search ${label.toLowerCase()}`}\n aria-invalid={isInvalid || undefined}\n aria-describedby={showError ? errorId : undefined}\n aria-expanded={open}\n aria-controls={listId}\n aria-autocomplete=\"list\"\n aria-activedescendant={\n open && current !== null ? optionId(indexOf.get(current) ?? 0) : undefined\n }\n placeholder={searchPlaceholder ?? selectedOption?.label ?? \"Search\"}\n value={query}\n autoComplete=\"off\"\n spellCheck={false}\n onChange={(event) => onQuery(event.target.value)}\n onKeyDown={(event) => onKey(event, true)}\n className=\"h-full min-w-0 flex-1 border-0 bg-transparent p-0 [font:inherit] text-foreground outline-none placeholder:text-muted-foreground\"\n />\n {query ? (\n <button\n type=\"button\"\n aria-label=\"Clear search\"\n onPointerDown={(event) => event.preventDefault()}\n onClick={() => {\n onQuery(\"\");\n inputRef.current?.focus();\n }}\n className=\"grid size-6 flex-none cursor-pointer place-items-center rounded-pill border-0 bg-muted p-0 text-text-secondary outline-none motion-safe:animate-field-clear-in motion-reduce:animate-fade-in hover:text-foreground\"\n >\n <svg\n aria-hidden=\"true\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.75\"\n strokeLinecap=\"round\"\n className=\"size-3.5\"\n >\n <path d=\"m4 4 8 8M12 4l-8 8\" />\n </svg>\n </button>\n ) : null}\n {/* Sits exactly over the shared chevron, so the chevron closes the list in both lid states. */}\n <button\n type=\"button\"\n aria-label={`Close ${label.toLowerCase()}`}\n onClick={() => close(true)}\n className=\"size-9 flex-none cursor-pointer rounded-pill border-0 bg-transparent p-0 outline-none motion-safe:transition-[background-color] motion-safe:duration-(--duration-quick) motion-safe:ease-settle hover:bg-muted\"\n />\n </div>\n ) : null}\n\n <svg\n aria-hidden=\"true\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.75\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"pointer-events-none absolute end-4 top-1/2 -mt-2 size-4 text-muted-foreground motion-safe:transition-[rotate] motion-safe:duration-(--duration-gentle) motion-safe:ease-gentle group-data-[open]/ms:rotate-180\"\n >\n <path d=\"m4 6 4 4 4-4\" />\n </svg>\n </div>\n\n <div\n ref={faceRef}\n data-open={open || undefined}\n className=\"morph-select-face\"\n >\n <div\n ref={scrollRef}\n className=\"max-h-(--ms-list-max) overflow-y-auto overscroll-contain pt-1.5 [scrollbar-width:thin]\"\n >\n <div id={listId} role=\"listbox\" aria-labelledby={labelId} className=\"relative grid grid-cols-1 gap-0.5\">\n <span ref={highlightRef} aria-hidden=\"true\" className=\"morph-select-highlight\" />\n {visibleSections.map((section) => {\n const rows = section.options.map((option) => {\n const index = indexOf.get(option.value) ?? 0;\n const isSelected = option.value === selected;\n return (\n <div\n key={option.value}\n id={optionId(index)}\n role=\"option\"\n aria-selected={isSelected}\n aria-disabled={option.disabled || undefined}\n data-slot=\"morph-select-option\"\n data-active={option.value === current || undefined}\n ref={(node) => {\n if (node) optionRefs.current.set(option.value, node);\n else optionRefs.current.delete(option.value);\n }}\n onPointerMove={(event) => {\n if (event.pointerType === \"mouse\" && !option.disabled && option.value !== current)\n setActive(option.value);\n }}\n onPointerDown={(event) => event.preventDefault()}\n onClick={(event) => commit(option, event.currentTarget)}\n className=\"morph-select-option relative box-border flex min-h-9 cursor-pointer select-none items-center gap-2 rounded-lg text-text-secondary outline-none data-[active]:text-foreground aria-selected:text-foreground aria-disabled:cursor-not-allowed aria-disabled:opacity-(--opacity-disabled) motion-safe:transition-colors motion-safe:duration-(--duration-quick) motion-safe:ease-settle\"\n >\n <span data-part=\"value\" className=\"flex min-w-0 flex-1 items-center gap-2 font-medium\">\n {option.icon ? (\n <span className={iconClass} aria-hidden=\"true\">\n {option.icon}\n </span>\n ) : null}\n <span className=\"min-w-0 truncate\">{option.label}</span>\n </span>\n {option.meta ? (\n <span className=\"flex-none text-xs tabular-nums text-muted-foreground\">\n {option.meta}\n </span>\n ) : null}\n <span\n aria-hidden=\"true\"\n data-on={isSelected || undefined}\n className=\"grid size-4 flex-none scale-60 place-items-center text-foreground opacity-0 data-[on]:scale-100 data-[on]:opacity-100 motion-safe:transition-[opacity,scale] motion-safe:duration-(--duration-quick) motion-safe:ease-settle\"\n >\n <svg\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.75\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"size-4\"\n >\n <path d=\"m3.5 8.5 3 3 6-6\" />\n </svg>\n </span>\n </div>\n );\n });\n return section.label ? (\n <div\n key={section.key}\n role=\"group\"\n aria-labelledby={`${uid}-${section.key}`}\n className=\"grid grid-cols-1 gap-0.5 not-first:mt-1\"\n >\n <div\n id={`${uid}-${section.key}`}\n role=\"presentation\"\n className=\"px-2.5 pt-2 pb-1 text-xs text-muted-foreground\"\n >\n {section.label}\n </div>\n {rows}\n </div>\n ) : (\n <div key={section.key} role=\"presentation\" className=\"grid grid-cols-1 gap-0.5 not-first:mt-1\">\n {rows}\n </div>\n );\n })}\n {resultCount === 0 ? (\n <p className=\"m-0 px-2.5 pt-3 pb-3.5 text-sm text-muted-foreground\">\n No matches for “{query.trim()}”\n </p>\n ) : null}\n </div>\n </div>\n </div>\n </div>\n </div>\n\n {showError ? (\n <span\n id={errorId}\n data-slot=\"morph-select-error\"\n className=\"text-sm leading-(--leading-normal) text-destructive-strong\"\n >\n {errorMessage}\n </span>\n ) : null}\n {name ? <input type=\"hidden\" name={name} value={selected ?? \"\"} /> : null}\n <span className=\"sr-only\" role=\"status\" aria-live=\"polite\">\n {announcement}\n </span>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import { MultiSelect, MultiSelectProps } from "./multi-select.js";
2
- export { MultiSelect, type MultiSelectProps };
1
+ import { MultiSelect, MultiSelectGroup, MultiSelectGroupProps, MultiSelectProps, multiSelectGroupHeaderVariants, multiSelectGroupVariants } from "./multi-select.js";
2
+ export { MultiSelect, MultiSelectGroup, type MultiSelectGroupProps, type MultiSelectProps, multiSelectGroupHeaderVariants, multiSelectGroupVariants };
@@ -1,2 +1,2 @@
1
- import { MultiSelect } from "./multi-select.js";
2
- export { MultiSelect };
1
+ import { MultiSelect, MultiSelectGroup, multiSelectGroupHeaderVariants, multiSelectGroupVariants } from "./multi-select.js";
2
+ export { MultiSelect, MultiSelectGroup, multiSelectGroupHeaderVariants, multiSelectGroupVariants };
@@ -1,5 +1,5 @@
1
1
  import { ReactNode } from "react";
2
- import { SelectProps } from "react-aria-components";
2
+ import { Key, SelectProps } from "react-aria-components";
3
3
  //#region src/multi-select/multi-select.d.ts
4
4
  /**
5
5
  * MultiSelect: pick several options from a list. A Select in multiple mode
@@ -10,7 +10,13 @@ import { SelectProps } from "react-aria-components";
10
10
  * fades up from a blur and grows in on the snappy spring while the chips beside
11
11
  * it glide over; the count rolls up or down as it changes. A clear button scales
12
12
  * in beside the chevron when anything is picked. Options are `SelectItem`s, whose
13
- * tick pops in as an option is picked.
13
+ * tick pops in as an option is picked; `MultiSelectGroup` gathers them under a
14
+ * heading.
15
+ *
16
+ * Opt in to `searchable` for a search field at the top of the list that filters
17
+ * the options as you type (React Aria's Autocomplete, so the arrow keys and Enter
18
+ * work from the field). Pass `onCreate` to also offer a "Create “…”" row when the
19
+ * typed text matches no option.
14
20
  */
15
21
  export interface MultiSelectProps extends Omit<SelectProps<object, "multiple">, "className" | "style" | "children" | "items" | "selectionMode"> {
16
22
  /** `SelectItem` children. */
@@ -24,13 +30,79 @@ export interface MultiSelectProps extends Omit<SelectProps<object, "multiple">,
24
30
  errorMessage?: ReactNode;
25
31
  /** Chips shown in the trigger before the rest become "+N". @default 2 */
26
32
  maxVisible?: number;
33
+ /**
34
+ * Words after the overflow count, so `"more"` reads "+2 more". Off by default:
35
+ * the count alone, "+2".
36
+ */
37
+ moreLabel?: string;
38
+ /**
39
+ * While some picks are folded into "+N", hovering or focusing the trigger shows
40
+ * a tooltip listing them. Off by default.
41
+ *
42
+ * @default false
43
+ */
44
+ overflowTooltip?: boolean;
27
45
  /** Accessible name of the clear button. @default "Clear selections" */
28
46
  clearLabel?: string;
29
47
  /** @default "md" */
30
48
  size?: "sm" | "md" | "lg";
31
49
  /** Extra classes for the wrapper. Merged last. */
32
50
  className?: string;
51
+ /**
52
+ * Puts a search field at the top of the list. Typing filters the options (and
53
+ * groups) by their text, ignoring case and accents; the arrow keys and Enter
54
+ * work from the field. Cleared each time the list closes. Off by default.
55
+ * Turned on by `onCreate` too.
56
+ *
57
+ * @default false
58
+ */
59
+ searchable?: boolean;
60
+ /** Accessible name of the search field. @default "Search options" */
61
+ searchLabel?: string;
62
+ /** Placeholder of the search field. @default "Search" */
63
+ searchPlaceholder?: string;
64
+ /** Shown in the list while the search matches nothing. @default "No options found" */
65
+ emptyLabel?: string;
66
+ /**
67
+ * Makes the list creatable, and searchable. While the typed text (trimmed)
68
+ * matches no option's text or id nor a picked value, ignoring case, the list ends
69
+ * with a "Create “text”" row. Picking it calls `onCreate` with the text, adds
70
+ * the text itself as a picked key (through `onChange`, as any pick) and clears
71
+ * the search. Render a `SelectItem` whose `id` is that text so it lists like
72
+ * the others; until then its chip shows the text.
73
+ */
74
+ onCreate?: (value: string) => void;
75
+ /** The create row's text for the typed value. @default (value) => `Create “${value}”` */
76
+ createLabel?: (value: string) => string;
33
77
  }
34
78
  export declare const MultiSelect: import("react").ForwardRefExoticComponent<MultiSelectProps & import("react").RefAttributes<HTMLButtonElement>>;
79
+ export declare const multiSelectGroupVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
80
+ export declare const multiSelectGroupHeaderVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
81
+ /**
82
+ * A run of options under a heading, such as "Countries" and "Regions". React
83
+ * Aria's ListBoxSection, so the heading names the group for assistive tech and
84
+ * the arrow keys move straight through from one group to the next.
85
+ *
86
+ * @example
87
+ * <MultiSelect label="Markets">
88
+ * <MultiSelectGroup title="Countries">
89
+ * <SelectItem id="IN">India</SelectItem>
90
+ * </MultiSelectGroup>
91
+ * <MultiSelectGroup title="Regions">
92
+ * <SelectItem id="europe">Europe</SelectItem>
93
+ * </MultiSelectGroup>
94
+ * </MultiSelect>
95
+ */
96
+ export interface MultiSelectGroupProps {
97
+ /** The heading drawn above the group, and the group's accessible name. */
98
+ title: ReactNode;
99
+ /** `SelectItem` children. */
100
+ children?: ReactNode;
101
+ /** Identifies the group in the collection. Defaults to a generated id. */
102
+ id?: Key;
103
+ /** Extra classes for the group. Merged last. */
104
+ className?: string;
105
+ }
106
+ export declare const MultiSelectGroup: import("react").ForwardRefExoticComponent<MultiSelectGroupProps & import("react").RefAttributes<HTMLElement>>;
35
107
  //#endregion
36
108
  //# sourceMappingURL=multi-select.d.ts.map