@mitcsutt/kiln-ui 0.6.0 → 0.8.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.
Files changed (184) hide show
  1. package/dist/components/actions/CopyButton/CopyButton.d.ts +58 -0
  2. package/dist/components/actions/CopyButton/CopyButton.js +63 -0
  3. package/dist/components/actions/CopyButton/CopyButton.js.map +1 -0
  4. package/dist/components/actions/CopyButton/CopyButton.module.js +9 -0
  5. package/dist/components/actions/CopyButton/CopyButton.module.js.map +1 -0
  6. package/dist/components/actions/CopyButton/index.d.ts +4 -0
  7. package/dist/components/actions/CopyButton/useClipboard.d.ts +35 -0
  8. package/dist/components/actions/CopyButton/useClipboard.js +62 -0
  9. package/dist/components/actions/CopyButton/useClipboard.js.map +1 -0
  10. package/dist/components/actions/ToggleChip/ToggleChip.d.ts +6 -0
  11. package/dist/components/actions/ToggleChip/ToggleChip.js +26 -24
  12. package/dist/components/actions/ToggleChip/ToggleChip.js.map +1 -1
  13. package/dist/components/display/Badge/Badge.d.ts +6 -0
  14. package/dist/components/display/Badge/Badge.js +16 -15
  15. package/dist/components/display/Badge/Badge.js.map +1 -1
  16. package/dist/components/display/CodeBlock/CodeBlock.js +45 -58
  17. package/dist/components/display/CodeBlock/CodeBlock.js.map +1 -1
  18. package/dist/components/display/Swatch/Swatch.d.ts +52 -0
  19. package/dist/components/display/Swatch/Swatch.js +27 -0
  20. package/dist/components/display/Swatch/Swatch.js.map +1 -0
  21. package/dist/components/display/Swatch/Swatch.module.js +6 -0
  22. package/dist/components/display/Swatch/Swatch.module.js.map +1 -0
  23. package/dist/components/display/Swatch/index.d.ts +2 -0
  24. package/dist/components/display/Tag/Tag.d.ts +7 -0
  25. package/dist/components/display/Tag/Tag.js +31 -26
  26. package/dist/components/display/Tag/Tag.js.map +1 -1
  27. package/dist/components/display/TreeTable/TreeTable.d.ts +69 -0
  28. package/dist/components/display/TreeTable/TreeTable.js +152 -0
  29. package/dist/components/display/TreeTable/TreeTable.js.map +1 -0
  30. package/dist/components/display/TreeTable/TreeTable.module.js +12 -0
  31. package/dist/components/display/TreeTable/TreeTable.module.js.map +1 -0
  32. package/dist/components/display/TreeTable/index.d.ts +2 -0
  33. package/dist/components/feedback/Indicator/Indicator.d.ts +74 -0
  34. package/dist/components/feedback/Indicator/Indicator.js +50 -0
  35. package/dist/components/feedback/Indicator/Indicator.js.map +1 -0
  36. package/dist/components/feedback/Indicator/Indicator.module.js +12 -0
  37. package/dist/components/feedback/Indicator/Indicator.module.js.map +1 -0
  38. package/dist/components/feedback/Indicator/index.d.ts +2 -0
  39. package/dist/components/feedback/Toaster/Toaster.d.ts +71 -0
  40. package/dist/components/feedback/Toaster/Toaster.js +121 -0
  41. package/dist/components/feedback/Toaster/Toaster.js.map +1 -0
  42. package/dist/components/feedback/Toaster/Toaster.module.js +20 -0
  43. package/dist/components/feedback/Toaster/Toaster.module.js.map +1 -0
  44. package/dist/components/feedback/Toaster/index.d.ts +4 -0
  45. package/dist/components/feedback/Toaster/toast.d.ts +96 -0
  46. package/dist/components/feedback/Toaster/toast.js +131 -0
  47. package/dist/components/feedback/Toaster/toast.js.map +1 -0
  48. package/dist/components/inputs/Calendar/Calendar.d.ts +87 -0
  49. package/dist/components/inputs/Calendar/Calendar.js +217 -0
  50. package/dist/components/inputs/Calendar/Calendar.js.map +1 -0
  51. package/dist/components/inputs/Calendar/Calendar.module.js +18 -0
  52. package/dist/components/inputs/Calendar/Calendar.module.js.map +1 -0
  53. package/dist/components/inputs/Calendar/index.d.ts +2 -0
  54. package/dist/components/inputs/Combobox/Combobox.js +36 -44
  55. package/dist/components/inputs/Combobox/Combobox.js.map +1 -1
  56. package/dist/components/inputs/DateField/DateField.d.ts +17 -0
  57. package/dist/components/inputs/DateField/DateField.js +26 -0
  58. package/dist/components/inputs/DateField/DateField.js.map +1 -0
  59. package/dist/components/inputs/DateField/index.d.ts +2 -0
  60. package/dist/components/inputs/DateInput/DateInput.d.ts +75 -0
  61. package/dist/components/inputs/DateInput/DateInput.js +139 -0
  62. package/dist/components/inputs/DateInput/DateInput.js.map +1 -0
  63. package/dist/components/inputs/DateInput/index.d.ts +3 -0
  64. package/dist/components/inputs/DateRangeField/DateRangeField.d.ts +18 -3
  65. package/dist/components/inputs/DateRangeField/DateRangeField.js.map +1 -1
  66. package/dist/components/inputs/DateRangeField/DateRangeField.module.js +8 -3
  67. package/dist/components/inputs/DateRangeField/DateRangeField.module.js.map +1 -1
  68. package/dist/components/inputs/DateRangeField/DateRangePickerField.d.ts +48 -0
  69. package/dist/components/inputs/DateRangeField/DateRangePickerField.js +246 -0
  70. package/dist/components/inputs/DateRangeField/DateRangePickerField.js.map +1 -0
  71. package/dist/components/inputs/DateRangeField/index.d.ts +2 -0
  72. package/dist/components/inputs/DateTimeField/DateTimeField.d.ts +17 -0
  73. package/dist/components/inputs/DateTimeField/DateTimeField.js +26 -0
  74. package/dist/components/inputs/DateTimeField/DateTimeField.js.map +1 -0
  75. package/dist/components/inputs/DateTimeField/index.d.ts +2 -0
  76. package/dist/components/inputs/DateTimeInput/DateTimeInput.d.ts +83 -0
  77. package/dist/components/inputs/DateTimeInput/DateTimeInput.js +216 -0
  78. package/dist/components/inputs/DateTimeInput/DateTimeInput.js.map +1 -0
  79. package/dist/components/inputs/DateTimeInput/index.d.ts +2 -0
  80. package/dist/components/inputs/JsonField/JsonField.d.ts +23 -0
  81. package/dist/components/inputs/JsonField/JsonField.js +33 -0
  82. package/dist/components/inputs/JsonField/JsonField.js.map +1 -0
  83. package/dist/components/inputs/JsonField/index.d.ts +2 -0
  84. package/dist/components/inputs/JsonInput/JsonInput.d.ts +119 -0
  85. package/dist/components/inputs/JsonInput/JsonInput.js +282 -0
  86. package/dist/components/inputs/JsonInput/JsonInput.js.map +1 -0
  87. package/dist/components/inputs/JsonInput/JsonInput.module.js +16 -0
  88. package/dist/components/inputs/JsonInput/JsonInput.module.js.map +1 -0
  89. package/dist/components/inputs/JsonInput/index.d.ts +4 -0
  90. package/dist/components/inputs/JsonInput/json.d.ts +59 -0
  91. package/dist/components/inputs/JsonInput/json.js +231 -0
  92. package/dist/components/inputs/JsonInput/json.js.map +1 -0
  93. package/dist/components/inputs/TagsInput/TagsInput.js +5 -5
  94. package/dist/components/inputs/TimeField/TimeField.d.ts +17 -0
  95. package/dist/components/inputs/TimeField/TimeField.js +26 -0
  96. package/dist/components/inputs/TimeField/TimeField.js.map +1 -0
  97. package/dist/components/inputs/TimeField/index.d.ts +2 -0
  98. package/dist/components/inputs/TimeInput/TimeInput.d.ts +54 -0
  99. package/dist/components/inputs/TimeInput/TimeInput.js +107 -0
  100. package/dist/components/inputs/TimeInput/TimeInput.js.map +1 -0
  101. package/dist/components/inputs/TimeInput/index.d.ts +2 -0
  102. package/dist/components/inputs/internal/DateSegments.d.ts +80 -0
  103. package/dist/components/inputs/internal/DateSegments.js +345 -0
  104. package/dist/components/inputs/internal/DateSegments.js.map +1 -0
  105. package/dist/components/inputs/internal/dates.d.ts +101 -0
  106. package/dist/components/inputs/internal/dates.js +262 -0
  107. package/dist/components/inputs/internal/dates.js.map +1 -0
  108. package/dist/components/inputs/internal/filterOptions.d.ts +22 -1
  109. package/dist/components/inputs/internal/filterOptions.js +32 -1
  110. package/dist/components/inputs/internal/filterOptions.js.map +1 -1
  111. package/dist/components/inputs/internal/picker.d.ts +31 -0
  112. package/dist/components/inputs/internal/picker.js +29 -0
  113. package/dist/components/inputs/internal/picker.js.map +1 -0
  114. package/dist/components/inputs/internal/picker.module.js +15 -0
  115. package/dist/components/inputs/internal/picker.module.js.map +1 -0
  116. package/dist/components/inputs/internal/segments.module.js +10 -0
  117. package/dist/components/inputs/internal/segments.module.js.map +1 -0
  118. package/dist/components/layout/Collapse/Collapse.d.ts +39 -0
  119. package/dist/components/layout/Collapse/Collapse.js +24 -0
  120. package/dist/components/layout/Collapse/Collapse.js.map +1 -0
  121. package/dist/components/layout/Collapse/Collapse.module.js +6 -0
  122. package/dist/components/layout/Collapse/Collapse.module.js.map +1 -0
  123. package/dist/components/layout/Collapse/index.d.ts +2 -0
  124. package/dist/components/layout/Collapse/useHeightMotion.d.ts +16 -0
  125. package/dist/components/layout/Collapse/useHeightMotion.js +60 -0
  126. package/dist/components/layout/Collapse/useHeightMotion.js.map +1 -0
  127. package/dist/components/layout/ShowMore/ShowMore.d.ts +59 -0
  128. package/dist/components/layout/ShowMore/ShowMore.js +114 -0
  129. package/dist/components/layout/ShowMore/ShowMore.js.map +1 -0
  130. package/dist/components/layout/ShowMore/ShowMore.module.js +12 -0
  131. package/dist/components/layout/ShowMore/ShowMore.module.js.map +1 -0
  132. package/dist/components/layout/ShowMore/index.d.ts +2 -0
  133. package/dist/components/layout/Transition/Transition.d.ts +63 -0
  134. package/dist/components/layout/Transition/Transition.js +63 -0
  135. package/dist/components/layout/Transition/Transition.js.map +1 -0
  136. package/dist/components/layout/Transition/Transition.module.js +17 -0
  137. package/dist/components/layout/Transition/Transition.module.js.map +1 -0
  138. package/dist/components/layout/Transition/index.d.ts +2 -0
  139. package/dist/components/navigation/Collapsible/Collapsible.d.ts +49 -0
  140. package/dist/components/navigation/Collapsible/Collapsible.js +83 -0
  141. package/dist/components/navigation/Collapsible/Collapsible.js.map +1 -0
  142. package/dist/components/navigation/Collapsible/Collapsible.module.js +11 -0
  143. package/dist/components/navigation/Collapsible/Collapsible.module.js.map +1 -0
  144. package/dist/components/navigation/Collapsible/index.d.ts +2 -0
  145. package/dist/components/navigation/NavLinks/NavLinks.d.ts +32 -4
  146. package/dist/components/navigation/NavLinks/NavLinks.js +69 -39
  147. package/dist/components/navigation/NavLinks/NavLinks.js.map +1 -1
  148. package/dist/components/navigation/NavLinks/NavLinks.module.js +13 -3
  149. package/dist/components/navigation/NavLinks/NavLinks.module.js.map +1 -1
  150. package/dist/components/navigation/NavLinks/NavLinksGroup.d.ts +49 -0
  151. package/dist/components/navigation/NavLinks/NavLinksGroup.js +185 -0
  152. package/dist/components/navigation/NavLinks/NavLinksGroup.js.map +1 -0
  153. package/dist/components/navigation/NavLinks/context.d.ts +28 -0
  154. package/dist/components/navigation/NavLinks/context.js +13 -0
  155. package/dist/components/navigation/NavLinks/context.js.map +1 -0
  156. package/dist/components/navigation/NavLinks/index.d.ts +2 -0
  157. package/dist/components/navigation/NavLinks/treeKeys.d.ts +8 -0
  158. package/dist/components/navigation/NavLinks/treeKeys.js +57 -0
  159. package/dist/components/navigation/NavLinks/treeKeys.js.map +1 -0
  160. package/dist/components/overlays/CommandPalette/CommandPalette.d.ts +120 -0
  161. package/dist/components/overlays/CommandPalette/CommandPalette.js +386 -0
  162. package/dist/components/overlays/CommandPalette/CommandPalette.js.map +1 -0
  163. package/dist/components/overlays/CommandPalette/CommandPalette.module.js +31 -0
  164. package/dist/components/overlays/CommandPalette/CommandPalette.module.js.map +1 -0
  165. package/dist/components/overlays/CommandPalette/index.d.ts +2 -0
  166. package/dist/components/overlays/CommandPalette/shortcut.d.ts +28 -0
  167. package/dist/components/overlays/CommandPalette/shortcut.js +104 -0
  168. package/dist/components/overlays/CommandPalette/shortcut.js.map +1 -0
  169. package/dist/index.d.ts +42 -4
  170. package/dist/index.js +124 -100
  171. package/dist/styles.css +1 -1
  172. package/dist/themes/fiesta.css +1 -1
  173. package/dist/themes/flightdeck.css +1 -1
  174. package/dist/themes/ledger.css +1 -1
  175. package/dist/themes/monograph.css +1 -1
  176. package/dist/themes/riso.css +1 -1
  177. package/package.json +2 -1
  178. package/skills/custom-theme/SKILL.md +32 -0
  179. package/skills/custom-theme/references/colour.md +20 -0
  180. package/skills/custom-theme/references/motion.md +9 -0
  181. package/skills/custom-theme/references/tokens.md +35 -0
  182. package/skills/design-rules/SKILL.md +5 -2
  183. package/skills/setup-and-theming/SKILL.md +1 -1
  184. package/skills/setup-and-theming/references/paper.md +1 -1
@@ -2,44 +2,36 @@ import { cx as e } from "../../../utils/cx.js";
2
2
  import { CheckIcon as t, ChevronDownIcon as n, CloseIcon as r } from "../../../icons/icons.js";
3
3
  import { useMergedRefs as i } from "../internal/refs.js";
4
4
  import { Spinner as a } from "../../feedback/Spinner/Spinner.js";
5
- import { markFieldAware as o, useResolvedField as ee } from "../internal/FieldContext.js";
6
- import te from "../internal/messages.module.js";
7
- import ne from "../internal/control.module.js";
8
- import { Tag as re, TagList as ie } from "../../display/Tag/Tag.js";
9
- import { PortalAnchorContext as ae, usePortalTheme as oe } from "../../overlays/usePortalTheme.js";
10
- import { filterOptions as s, foldText as se } from "../internal/filterOptions.js";
11
- import { useControllableState as c } from "./useControllableState.js";
5
+ import { PortalAnchorContext as ee, usePortalTheme as o } from "../../overlays/usePortalTheme.js";
6
+ import { markFieldAware as te, useResolvedField as ne } from "../internal/FieldContext.js";
7
+ import re from "../internal/messages.module.js";
8
+ import ie from "../internal/control.module.js";
9
+ import { useControllableState as s } from "./useControllableState.js";
10
+ import { Tag as ae, TagList as oe } from "../../display/Tag/Tag.js";
11
+ import { filterOptions as se, foldText as ce, groupOptions as c } from "../internal/filterOptions.js";
12
12
  import l from "./Combobox.module.js";
13
- import { forwardRef as u, useCallback as d, useEffect as f, useId as ce, useMemo as le, useRef as p, useState as m } from "react";
13
+ import { forwardRef as u, useCallback as d, useEffect as f, useId as le, useMemo as ue, useRef as p, useState as m } from "react";
14
14
  import { jsx as h, jsxs as g } from "react/jsx-runtime";
15
15
  import { Popover as _ } from "radix-ui";
16
16
  //#region src/components/inputs/Combobox/Combobox.tsx
17
- function ue(e, t, n) {
18
- let r = n ? s(e, t) : [...e], i = [], a = /* @__PURE__ */ new Map();
19
- for (let e of r) {
20
- let t = e.group === void 0 ? "" : `g:${e.group}`, n = a.get(t);
21
- n || (n = {
22
- key: t,
23
- label: e.group,
24
- options: []
25
- }, a.set(t, n), i.push(n)), n.options.push(e);
26
- }
17
+ function de(e, t, n) {
18
+ let r = n ? se(e, t) : [...e], i = c(r);
27
19
  return {
28
20
  sections: i,
29
21
  ordered: i.flatMap((e) => e.options)
30
22
  };
31
23
  }
32
24
  var v = (e) => `Remove ${e}`;
33
- function de(e) {
25
+ function fe(e) {
34
26
  if (e.multiple === !0) {
35
- let { multiple: t, value: n, defaultValue: r, onValueChange: i, maxSelected: a, removeLabel: o, ...ee } = e;
36
- return [ee, {
27
+ let { multiple: t, value: n, defaultValue: r, onValueChange: i, maxSelected: a, removeLabel: ee, ...o } = e;
28
+ return [o, {
37
29
  multiple: t,
38
30
  value: n,
39
31
  defaultValue: r ?? [],
40
32
  emit: (e) => i?.([...e]),
41
33
  maxSelected: a,
42
- removeLabel: o ?? v
34
+ removeLabel: ee ?? v
43
35
  }];
44
36
  }
45
37
  let { multiple: t, value: n, defaultValue: r, onValueChange: i, ...a } = e;
@@ -52,15 +44,15 @@ function de(e) {
52
44
  removeLabel: v
53
45
  }];
54
46
  }
55
- function fe(e) {
47
+ function pe(e) {
56
48
  let t = e?.closest("[data-theme]");
57
49
  return t && t !== e?.ownerDocument.documentElement ? t : void 0;
58
50
  }
59
- function pe(e) {
51
+ function me(e) {
60
52
  return `${String(e)} ${e === 1 ? "option" : "options"} available`;
61
53
  }
62
- var me = u(function({ children: e, onInteractOutside: t }, n) {
63
- let r = oe();
54
+ var he = u(function({ children: e, onInteractOutside: t }, n) {
55
+ let r = o();
64
56
  return /* @__PURE__ */ h(_.Content, {
65
57
  ref: n,
66
58
  className: l.popup,
@@ -85,8 +77,8 @@ var me = u(function({ children: e, onInteractOutside: t }, n) {
85
77
  ...r,
86
78
  children: e
87
79
  });
88
- }), he = o(u(function(o, oe) {
89
- let [s, u] = de(o), { options: v, inputValue: he, defaultInputValue: ge, onInputValueChange: _e, filter: ve = "auto", loading: y = !1, loadingMessage: ye = "Loading…", emptyMessage: b = "No matches", open: be, defaultOpen: xe = !1, onOpenChange: Se, creatable: x = !1, clearable: Ce = !1, clearLabel: we = "Clear", size: Te = "md", invalid: Ee, id: De, disabled: Oe, required: ke, readOnly: Ae, name: S, form: je, placeholder: Me, className: Ne, style: Pe, onKeyDown: Fe, onBlur: Ie, onClick: Le, "aria-describedby": Re, "aria-invalid": ze, "aria-label": Be, "aria-labelledby": Ve, ...He } = s, { multiple: C, maxSelected: Ue, removeLabel: We } = u, w = ee({
80
+ }), ge = te(u(function(o, te) {
81
+ let [se, c] = fe(o), { options: u, inputValue: v, defaultInputValue: ge, onInputValueChange: _e, filter: ve = "auto", loading: y = !1, loadingMessage: ye = "Loading…", emptyMessage: b = "No matches", open: be, defaultOpen: xe = !1, onOpenChange: Se, creatable: x = !1, clearable: Ce = !1, clearLabel: we = "Clear", size: Te = "md", invalid: Ee, id: De, disabled: Oe, required: ke, readOnly: Ae, name: S, form: je, placeholder: Me, className: Ne, style: Pe, onKeyDown: Fe, onBlur: Ie, onClick: Le, "aria-describedby": Re, "aria-invalid": ze, "aria-label": Be, "aria-labelledby": Ve, ...He } = se, { multiple: C, maxSelected: Ue, removeLabel: We } = c, w = ne({
90
82
  id: De,
91
83
  describedBy: Re,
92
84
  invalid: Ee,
@@ -94,13 +86,13 @@ var me = u(function({ children: e, onInteractOutside: t }, n) {
94
86
  required: ke,
95
87
  disabled: Oe,
96
88
  readOnly: Ae
97
- }), Ge = ce(), T = w.id ?? `${Ge}combobox`, Ke = `${T}-listbox`, qe = `${T}-status`, E = !w.disabled && !w.readOnly, D = p(null), O = p(null), Je = i(oe, D), k = p(/* @__PURE__ */ new Map());
98
- for (let e of v) k.current.set(e.value, e.label);
99
- let A = d((e) => v.find((t) => t.value === e)?.label ?? k.current.get(e) ?? e, [v]), [j, M] = c(u.value, u.defaultValue, u.emit), N = !C && j[0] !== void 0 ? A(j[0]) : "", [P, Ye] = c(he, ge ?? (C || u.defaultValue[0] === void 0 ? "" : A(u.defaultValue[0])), _e), Xe = p(P);
89
+ }), Ge = le(), T = w.id ?? `${Ge}combobox`, Ke = `${T}-listbox`, qe = `${T}-status`, E = !w.disabled && !w.readOnly, D = p(null), O = p(null), Je = i(te, D), k = p(/* @__PURE__ */ new Map());
90
+ for (let e of u) k.current.set(e.value, e.label);
91
+ let A = d((e) => u.find((t) => t.value === e)?.label ?? k.current.get(e) ?? e, [u]), [j, M] = s(c.value, c.defaultValue, c.emit), N = !C && j[0] !== void 0 ? A(j[0]) : "", [P, Ye] = s(v, ge ?? (C || c.defaultValue[0] === void 0 ? "" : A(c.defaultValue[0])), _e), Xe = p(P);
100
92
  Xe.current = P;
101
93
  let F = d((e) => {
102
94
  e !== Xe.current && Ye(e);
103
- }, [Ye]), [I, L] = m(!1), [R, Ze] = c(be, xe, Se), z = p(R);
95
+ }, [Ye]), [I, L] = m(!1), [R, Ze] = s(be, xe, Se), z = p(R);
104
96
  z.current = R;
105
97
  let B = d((e) => {
106
98
  e !== z.current && Ze(e);
@@ -113,11 +105,11 @@ var me = u(function({ children: e, onInteractOutside: t }, n) {
113
105
  N,
114
106
  F
115
107
  ]);
116
- let $e = ve === "auto" && (C || I), { sections: H, ordered: U } = le(() => ue(v, P, $e), [
117
- v,
108
+ let $e = ve === "auto" && (C || I), { sections: H, ordered: U } = ue(() => de(u, P, $e), [
109
+ u,
118
110
  P,
119
111
  $e
120
- ]), et = le(() => new Map(v.map((e, t) => [e.value, t])), [v]), tt = (e) => `${T}-option-${String(et.get(e) ?? 0)}`, nt = C && Ue !== void 0 && j.length >= Ue, W = (e) => j.includes(e), G = (e) => !!e.disabled || nt && !W(e.value), K = U.filter((e) => !G(e)), q = P.trim(), rt = x && q !== "" && (C || I), it = !y && U.length === 0 && !rt, at = U.length > 0 || y || it, J = R && E && at, ot = J && !y && !x && q !== "" && (C || I), st = K.find((e) => e.value === Qe) ?? (ot ? K[0] : void 0), Y = J ? st : void 0, [ct, lt] = m(""), X = y ? "" : U.length === 0 ? typeof b == "string" ? b : "No matches" : pe(U.length);
112
+ ]), et = ue(() => new Map(u.map((e, t) => [e.value, t])), [u]), tt = (e) => `${T}-option-${String(et.get(e) ?? 0)}`, nt = C && Ue !== void 0 && j.length >= Ue, W = (e) => j.includes(e), G = (e) => !!e.disabled || nt && !W(e.value), K = U.filter((e) => !G(e)), q = P.trim(), rt = x && q !== "" && (C || I), it = !y && U.length === 0 && !rt, at = U.length > 0 || y || it, J = R && E && at, ot = J && !y && !x && q !== "" && (C || I), st = K.find((e) => e.value === Qe) ?? (ot ? K[0] : void 0), Y = J ? st : void 0, [ct, lt] = m(""), X = y ? "" : U.length === 0 ? typeof b == "string" ? b : "No matches" : me(U.length);
121
113
  f(() => {
122
114
  if (!J || X === "") {
123
115
  J || lt("");
@@ -143,7 +135,7 @@ var me = u(function({ children: e, onInteractOutside: t }, n) {
143
135
  }
144
136
  }, Q = () => {
145
137
  if (!x || q === "") return !1;
146
- let e = se(q), t = v.find((t) => !t.disabled && se(t.label) === e), n = t?.value ?? q, r = t?.label ?? q;
138
+ let e = ce(q), t = u.find((t) => !t.disabled && ce(t.label) === e), n = t?.value ?? q, r = t?.label ?? q;
147
139
  return k.current.set(n, r), C ? (F(""), L(!1), W(n) || nt ? !1 : (M([...j, n]), !0)) : (L(!1), F(r), j[0] !== n && (M([n]), !0));
148
140
  }, dt = (e) => {
149
141
  E && M(j.filter((t) => t !== e));
@@ -240,13 +232,13 @@ var me = u(function({ children: e, onInteractOutside: t }, n) {
240
232
  onOpenChange: (e) => {
241
233
  e || B(!1);
242
234
  },
243
- children: /* @__PURE__ */ g(ae.Provider, {
235
+ children: /* @__PURE__ */ g(ee.Provider, {
244
236
  value: O,
245
237
  children: [/* @__PURE__ */ h(_.Anchor, {
246
238
  asChild: !0,
247
239
  children: /* @__PURE__ */ g("div", {
248
240
  ref: O,
249
- className: e(ne.box, l.root, Ne),
241
+ className: e(ie.box, l.root, Ne),
250
242
  style: Pe,
251
243
  "data-size": Te,
252
244
  "data-multiple": C || void 0,
@@ -259,11 +251,11 @@ var me = u(function({ children: e, onInteractOutside: t }, n) {
259
251
  children: [
260
252
  /* @__PURE__ */ g("div", {
261
253
  className: l.values,
262
- children: [C && j.length > 0 ? /* @__PURE__ */ h(ie, {
254
+ children: [C && j.length > 0 ? /* @__PURE__ */ h(oe, {
263
255
  className: l.chips,
264
256
  children: j.map((e) => {
265
257
  let t = A(e);
266
- return /* @__PURE__ */ h(re, {
258
+ return /* @__PURE__ */ h(ae, {
267
259
  className: l.chip,
268
260
  onRemove: E ? () => {
269
261
  dt(e), D.current?.focus();
@@ -341,14 +333,14 @@ var me = u(function({ children: e, onInteractOutside: t }, n) {
341
333
  id: qe,
342
334
  role: "status",
343
335
  "aria-live": "polite",
344
- className: te.visuallyHidden,
336
+ className: re.visuallyHidden,
345
337
  children: ct
346
338
  })
347
339
  ]
348
340
  })
349
341
  }), /* @__PURE__ */ h(_.Portal, {
350
- container: J ? fe(O.current) : void 0,
351
- children: /* @__PURE__ */ g(me, {
342
+ container: J ? pe(O.current) : void 0,
343
+ children: /* @__PURE__ */ g(he, {
352
344
  onInteractOutside: bt,
353
345
  children: [
354
346
  /* @__PURE__ */ h("div", {
@@ -389,6 +381,6 @@ var me = u(function({ children: e, onInteractOutside: t }, n) {
389
381
  });
390
382
  }));
391
383
  //#endregion
392
- export { he as Combobox };
384
+ export { ge as Combobox };
393
385
 
394
386
  //# sourceMappingURL=Combobox.js.map
@@ -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":"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"}
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,2 @@
1
+ export { DateField } from './DateField.js';
2
+ export type { DateFieldProps } from './DateField.js';
@@ -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>>;