@devalok/shilp-sutra 0.53.0 → 0.54.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 (90) hide show
  1. package/AGENTS.md +7 -1
  2. package/BREAKING.json +29 -0
  3. package/MIGRATION.md +55 -0
  4. package/dist/composed/avatar-group.d.ts +11 -9
  5. package/dist/composed/avatar-group.d.ts.map +1 -1
  6. package/dist/composed/avatar-group.js +108 -140
  7. package/dist/composed/avatar-group.js.map +1 -1
  8. package/dist/composed/bulk-action-bar.d.ts +19 -11
  9. package/dist/composed/bulk-action-bar.d.ts.map +1 -1
  10. package/dist/composed/bulk-action-bar.js +81 -110
  11. package/dist/composed/bulk-action-bar.js.map +1 -1
  12. package/dist/composed/error-boundary.d.ts +15 -3
  13. package/dist/composed/error-boundary.d.ts.map +1 -1
  14. package/dist/composed/error-boundary.js +43 -26
  15. package/dist/composed/error-boundary.js.map +1 -1
  16. package/dist/composed/loading-skeleton.d.ts +2 -0
  17. package/dist/composed/loading-skeleton.d.ts.map +1 -1
  18. package/dist/composed/loading-skeleton.js +79 -56
  19. package/dist/composed/loading-skeleton.js.map +1 -1
  20. package/dist/composed/master-detail.d.ts +21 -8
  21. package/dist/composed/master-detail.d.ts.map +1 -1
  22. package/dist/composed/master-detail.js +91 -77
  23. package/dist/composed/master-detail.js.map +1 -1
  24. package/dist/composed/page-skeletons.d.ts +6 -0
  25. package/dist/composed/page-skeletons.d.ts.map +1 -1
  26. package/dist/composed/page-skeletons.js +93 -71
  27. package/dist/composed/page-skeletons.js.map +1 -1
  28. package/dist/shell/index.d.ts +5 -3
  29. package/dist/shell/index.d.ts.map +1 -1
  30. package/dist/shell/index.js +2 -3
  31. package/dist/shell/notification-preferences.d.ts.map +1 -1
  32. package/dist/shell/notification-preferences.js +2 -0
  33. package/dist/shell/notification-preferences.js.map +1 -1
  34. package/dist/ui/combobox.d.ts +1 -1
  35. package/dist/ui/combobox.d.ts.map +1 -1
  36. package/dist/ui/combobox.js +133 -128
  37. package/dist/ui/combobox.js.map +1 -1
  38. package/dist/ui/file-upload.d.ts.map +1 -1
  39. package/dist/ui/file-upload.js +124 -138
  40. package/dist/ui/file-upload.js.map +1 -1
  41. package/dist/ui/form.d.ts +7 -0
  42. package/dist/ui/form.d.ts.map +1 -1
  43. package/dist/ui/form.js +4 -2
  44. package/dist/ui/form.js.map +1 -1
  45. package/dist/ui/icon-button.d.ts +2 -1
  46. package/dist/ui/icon-button.d.ts.map +1 -1
  47. package/dist/ui/icon-button.js +1 -1
  48. package/dist/ui/icon-button.js.map +1 -1
  49. package/dist/ui/label.d.ts.map +1 -1
  50. package/dist/ui/label.js +7 -6
  51. package/dist/ui/label.js.map +1 -1
  52. package/dist/ui/spinner.d.ts.map +1 -1
  53. package/dist/ui/spinner.js +50 -44
  54. package/dist/ui/spinner.js.map +1 -1
  55. package/dist/ui/switch.d.ts.map +1 -1
  56. package/dist/ui/switch.js +24 -24
  57. package/dist/ui/switch.js.map +1 -1
  58. package/dist/ui/table.js +1 -1
  59. package/dist/ui/table.js.map +1 -1
  60. package/docs/components/composed/bulk-action-bar.md +9 -3
  61. package/docs/components/composed/error-boundary.md +18 -2
  62. package/docs/components/composed/master-detail.md +12 -2
  63. package/docs/components/composed/page-skeletons.md +2 -2
  64. package/docs/components/composed/rich-chat-input.md +18 -6
  65. package/docs/components/composed/simple-tooltip.md +1 -1
  66. package/docs/components/shell/app-command-palette.md +2 -1
  67. package/docs/components/shell/bottom-navbar.md +4 -4
  68. package/docs/components/shell/command-registry.md +2 -2
  69. package/docs/components/shell/link-context.md +2 -2
  70. package/docs/components/shell/top-bar.md +1 -1
  71. package/docs/components/ui/search-input.md +2 -2
  72. package/docs/components/ui/slider.md +2 -2
  73. package/docs/components/ui/split-button.md +3 -3
  74. package/llms.txt +2 -2
  75. package/make-kit/Guidelines.md +1 -1
  76. package/make-kit/components/overview.md +2 -2
  77. package/make-kit/foundations/surfaces.md +1 -1
  78. package/mcp-manifest.json +403 -147
  79. package/package.json +1 -6
  80. package/skill/SKILL.md +1 -1
  81. package/skill/chat-skill/README.md +18 -0
  82. package/skill/chat-skill/SKILL.md +78 -0
  83. package/skill/chat-skill/chatgpt-instructions.md +26 -0
  84. package/skill/chat-skill/gemini-instructions.md +25 -0
  85. package/skill/references/components.md +2 -2
  86. package/dist/shell/sidebar.d.ts +0 -113
  87. package/dist/shell/sidebar.d.ts.map +0 -1
  88. package/dist/shell/sidebar.js +0 -293
  89. package/dist/shell/sidebar.js.map +0 -1
  90. package/docs/components/shell/sidebar.md +0 -103
@@ -1,28 +1,28 @@
1
1
  "use client";
2
2
  import { Content2$6 as e, Portal$3 as t, Root2$8 as n, Trigger$8 as r } from "../_chunks/primitives.js";
3
- import { IconProvider as ee } from "./icon-context.js";
4
- import { springs as i, tweens as a } from "./lib/motion.js";
5
- import { cva as o } from "../_chunks/vendor-utils.js";
6
- import { cn as s } from "./lib/utils.js";
7
- import { Icon as c } from "./icon.js";
8
- import { useFormField as te } from "./form.js";
9
- import { resolveFieldState as ne } from "../_chunks/field-state.js";
10
- import { normalizeIcon as re } from "../_chunks/normalize-icon.js";
11
- import * as l from "react";
12
- import { Fragment as u, jsx as d, jsxs as f } from "react/jsx-runtime";
13
- import { IconCheck as p, IconChevronDown as m, IconSearch as ie, IconX as ae } from "@tabler/icons-react";
14
- import { motion as oe } from "framer-motion";
3
+ import { IconProvider as i } from "./icon-context.js";
4
+ import { springs as a, tweens as o } from "./lib/motion.js";
5
+ import { cva as s } from "../_chunks/vendor-utils.js";
6
+ import { cn as c } from "./lib/utils.js";
7
+ import { Icon as l } from "./icon.js";
8
+ import { useFormField as ee } from "./form.js";
9
+ import { resolveFieldState as te } from "../_chunks/field-state.js";
10
+ import { normalizeIcon as u } from "../_chunks/normalize-icon.js";
11
+ import * as d from "react";
12
+ import { Fragment as f, jsx as p, jsxs as m } from "react/jsx-runtime";
13
+ import { IconCheck as h, IconChevronDown as g, IconSearch as ne, IconX as re } from "@tabler/icons-react";
14
+ import { motion as ie } from "framer-motion";
15
15
  //#region src/ui/combobox.tsx
16
- var se = {
16
+ var ae = {
17
17
  error: "border-error-7",
18
18
  warning: "border-warning-7",
19
19
  success: "border-success-7"
20
- }, h = o([
20
+ }, _ = s([
21
21
  "flex w-full items-center justify-between whitespace-nowrap rounded-control",
22
22
  "border border-surface-border-strong bg-surface-raised-hover",
23
23
  "transition-colors duration-fast-01 ease-productive-standard",
24
24
  "focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2 focus-visible:border-accent-7",
25
- "disabled:cursor-not-allowed disabled:opacity-action-disabled"
25
+ "data-[disabled]:cursor-not-allowed data-[disabled]:opacity-action-disabled"
26
26
  ], {
27
27
  variants: { size: {
28
28
  xs: "h-ds-xs-plus text-body-sm px-ds-02",
@@ -31,122 +31,122 @@ var se = {
31
31
  lg: "h-ds-lg text-body-md px-ds-05"
32
32
  } },
33
33
  defaultVariants: { size: "md" }
34
- }), g = {
34
+ }), v = {
35
35
  xs: "xs",
36
36
  sm: "sm",
37
37
  md: "sm",
38
38
  lg: "md"
39
- }, _ = {
39
+ }, y = {
40
40
  xs: "px-ds-02 py-0 text-body-xs",
41
41
  sm: "px-ds-02 py-0 text-body-xs",
42
42
  md: "px-ds-03 py-[1px] text-body-sm",
43
43
  lg: "px-ds-03 py-[2px] text-body-sm"
44
- }, v = {
44
+ }, b = {
45
45
  xs: "text-body-xs",
46
46
  sm: "text-body-xs",
47
47
  md: "text-body-sm",
48
48
  lg: "text-body-sm"
49
- }, y = 2, b = 36, x = l.forwardRef(({ options: o, value: x, onValueChange: S, placeholder: C = "Select...", searchPlaceholder: w = "Search...", emptyMessage: T = "No results found", multiple: E = !1, disabled: D = !1, className: ce, triggerClassName: le, maxVisible: O = 6, renderOption: k, accessibleLabel: A, id: j, size: M = "md", state: N, ...P }, F) => {
50
- let I = M ?? "md", [L, R] = l.useState(!1), [z, B] = l.useState(""), [V, H] = l.useState(-1), U = l.useRef(null), W = l.useRef(null), G = l.useId(), K = l.useId(), q = l.useMemo(() => x == null ? [] : Array.isArray(x) ? x : [x], [x]), J = l.useMemo(() => z ? o.filter((e) => e.label.toLowerCase().includes(z.toLowerCase())) : o, [o, z]), ue = l.useCallback((e) => q.includes(e), [q]), Y = l.useCallback((e) => {
51
- E ? S(q.includes(e) ? q.filter((t) => t !== e) : [...q, e]) : (S(e), R(!1));
49
+ }, x = 2, S = 36, C = d.forwardRef(({ options: s, value: C, onValueChange: w, placeholder: T = "Select...", searchPlaceholder: oe = "Search...", emptyMessage: se = "No results found", multiple: E = !1, disabled: D = !1, className: ce, triggerClassName: le, maxVisible: ue = 6, renderOption: O, accessibleLabel: k, id: A, size: j = "md", state: M, ...N }, P) => {
50
+ let F = j ?? "md", [I, L] = d.useState(!1), [R, z] = d.useState(""), [B, V] = d.useState(-1), H = d.useRef(null), U = d.useRef(null), W = d.useId(), G = d.useId(), K = d.useMemo(() => C == null ? [] : Array.isArray(C) ? C : [C], [C]), q = d.useMemo(() => R ? s.filter((e) => e.label.toLowerCase().includes(R.toLowerCase())) : s, [s, R]), de = d.useCallback((e) => K.includes(e), [K]), J = d.useCallback((e) => {
51
+ E ? w(K.includes(e) ? K.filter((t) => t !== e) : [...K, e]) : (w(e), L(!1));
52
52
  }, [
53
53
  E,
54
- q,
55
- S
56
- ]), de = l.useCallback((e, t) => {
57
- e.stopPropagation(), e.preventDefault(), S(q.filter((e) => e !== t));
58
- }, [q, S]), fe = l.useCallback((e) => {
59
- D || (R(e), e || (B(""), H(-1)));
54
+ K,
55
+ w
56
+ ]), fe = d.useCallback((e, t) => {
57
+ e.stopPropagation(), e.preventDefault(), w(K.filter((e) => e !== t));
58
+ }, [K, w]), Y = d.useCallback((e) => {
59
+ D || (L(e), e || (z(""), V(-1)));
60
60
  }, [D]);
61
- l.useEffect(() => {
62
- if (L) {
61
+ d.useEffect(() => {
62
+ if (I) {
63
63
  let e = setTimeout(() => {
64
- U.current?.focus();
64
+ H.current?.focus();
65
65
  }, 0);
66
66
  return () => clearTimeout(e);
67
67
  }
68
- }, [L]);
69
- let X = l.useCallback((e, t) => {
70
- let n = J.length;
68
+ }, [I]);
69
+ let X = d.useCallback((e, t) => {
70
+ let n = q.length;
71
71
  if (n === 0) return -1;
72
72
  let r = e + t;
73
73
  for (; r >= 0 && r < n;) {
74
- if (!J[r].disabled) return r;
74
+ if (!q[r].disabled) return r;
75
75
  r += t;
76
76
  }
77
77
  return e;
78
- }, [J]), pe = l.useCallback((e) => {
78
+ }, [q]), pe = d.useCallback((e) => {
79
79
  switch (e.key) {
80
80
  case "ArrowDown": {
81
81
  e.preventDefault();
82
- let t = X(V, 1);
83
- H(t);
82
+ let t = X(B, 1);
83
+ V(t);
84
84
  break;
85
85
  }
86
86
  case "ArrowUp": {
87
87
  e.preventDefault();
88
- let t = X(V, -1);
89
- H(t);
88
+ let t = X(B, -1);
89
+ V(t);
90
90
  break;
91
91
  }
92
92
  case "Home": {
93
93
  e.preventDefault();
94
- let t = J.findIndex((e) => !e.disabled);
95
- H(t);
94
+ let t = q.findIndex((e) => !e.disabled);
95
+ V(t);
96
96
  break;
97
97
  }
98
98
  case "End": {
99
99
  e.preventDefault();
100
100
  let t = -1;
101
- for (let e = J.length - 1; e >= 0; e--) if (!J[e].disabled) {
101
+ for (let e = q.length - 1; e >= 0; e--) if (!q[e].disabled) {
102
102
  t = e;
103
103
  break;
104
104
  }
105
- H(t);
105
+ V(t);
106
106
  break;
107
107
  }
108
108
  case "Enter":
109
- e.preventDefault(), V >= 0 && V < J.length && !J[V].disabled && Y(J[V].value);
109
+ e.preventDefault(), B >= 0 && B < q.length && !q[B].disabled && J(q[B].value);
110
110
  break;
111
111
  case "Escape":
112
- e.preventDefault(), R(!1), B(""), H(-1);
112
+ e.preventDefault(), L(!1), z(""), V(-1);
113
113
  break;
114
114
  }
115
115
  }, [
116
- V,
117
- J,
116
+ B,
117
+ q,
118
118
  X,
119
- Y
119
+ J
120
120
  ]);
121
- l.useEffect(() => {
122
- if (V >= 0 && W.current) {
123
- let e = W.current.children[V];
121
+ d.useEffect(() => {
122
+ if (B >= 0 && U.current) {
123
+ let e = U.current.children[B];
124
124
  e && e.scrollIntoView?.({ block: "nearest" });
125
125
  }
126
- }, [V]);
127
- let me = l.useCallback(() => q.length === 0 ? null : o.find((e) => e.value === q[0])?.label ?? null, [q, o]), Z = g[I], he = _[I], ge = v[I], _e = () => {
128
- if (E && q.length > 0) {
129
- let e = q.slice(0, y), t = q.length - y;
130
- return /* @__PURE__ */ f("span", {
126
+ }, [B]);
127
+ let me = d.useCallback(() => K.length === 0 ? null : s.find((e) => e.value === K[0])?.label ?? null, [K, s]), Z = v[F], he = y[F], ge = b[F], _e = () => {
128
+ if (E && K.length > 0) {
129
+ let e = K.slice(0, x), t = K.length - x;
130
+ return /* @__PURE__ */ m("span", {
131
131
  className: "flex flex-1 flex-wrap items-center gap-ds-02 overflow-hidden",
132
132
  children: [e.map((e) => {
133
- let t = o.find((t) => t.value === e);
134
- return t ? /* @__PURE__ */ f("span", {
135
- className: s("inline-flex items-center gap-ds-01 rounded-control-inner bg-accent-2", he),
136
- children: [t.label, /* @__PURE__ */ d("button", {
133
+ let t = s.find((t) => t.value === e);
134
+ return t ? /* @__PURE__ */ m("span", {
135
+ className: c("inline-flex items-center gap-ds-01 rounded-control-inner bg-accent-2", he),
136
+ children: [t.label, /* @__PURE__ */ p("button", {
137
137
  type: "button",
138
138
  className: "inline-flex items-center justify-center rounded-pill outline-hidden hover:bg-surface-raised-hover transition-colors duration-fast-01 ease-productive-standard",
139
- onClick: (t) => de(t, e),
139
+ onClick: (t) => fe(t, e),
140
140
  "aria-label": `Remove ${t.label}`,
141
141
  tabIndex: -1,
142
- children: /* @__PURE__ */ d(c, {
143
- icon: ae,
142
+ children: /* @__PURE__ */ p(l, {
143
+ icon: re,
144
144
  size: Z
145
145
  })
146
146
  })]
147
147
  }, e) : null;
148
- }), t > 0 && /* @__PURE__ */ f("span", {
149
- className: s("text-surface-fg-muted", ge),
148
+ }), t > 0 && /* @__PURE__ */ m("span", {
149
+ className: c("text-surface-fg-muted", ge),
150
150
  children: [
151
151
  "+",
152
152
  t,
@@ -155,55 +155,60 @@ var se = {
155
155
  })]
156
156
  });
157
157
  }
158
- if (!E && q.length === 1) {
158
+ if (!E && K.length === 1) {
159
159
  let e = me();
160
- if (e) return /* @__PURE__ */ d("span", {
160
+ if (e) return /* @__PURE__ */ p("span", {
161
161
  className: "min-w-0 flex-1 truncate text-left",
162
162
  children: e
163
163
  });
164
164
  }
165
- return /* @__PURE__ */ d("span", {
165
+ return /* @__PURE__ */ p("span", {
166
166
  className: "min-w-0 flex-1 truncate text-left text-surface-fg-subtle",
167
- children: C
167
+ children: T
168
168
  });
169
- }, Q = te(), $ = ne(N, Q.state), ve = $ === "error", ye = Q.helperTextId, be = Q.required;
170
- return /* @__PURE__ */ d(n, {
171
- open: L,
172
- onOpenChange: fe,
173
- children: /* @__PURE__ */ f("div", {
174
- className: s("relative", ce),
175
- ...P,
176
- children: [/* @__PURE__ */ d(r, {
169
+ }, Q = ee(), $ = te(M, Q.state), ve = $ === "error", ye = Q.helperTextId, be = Q.required;
170
+ return /* @__PURE__ */ p(n, {
171
+ open: I,
172
+ onOpenChange: Y,
173
+ children: /* @__PURE__ */ m("div", {
174
+ className: c("relative", ce),
175
+ ...N,
176
+ children: [/* @__PURE__ */ p(r, {
177
177
  asChild: !0,
178
178
  disabled: D,
179
- children: /* @__PURE__ */ f("button", {
180
- ref: F,
181
- type: "button",
179
+ children: /* @__PURE__ */ m("div", {
180
+ ref: P,
182
181
  role: "combobox",
183
- id: j ?? Q.inputId,
184
- "aria-expanded": L,
185
- "aria-controls": K,
182
+ tabIndex: D ? -1 : 0,
183
+ "data-disabled": D || void 0,
184
+ id: A,
185
+ "aria-expanded": I,
186
+ "aria-controls": G,
186
187
  "aria-haspopup": "listbox",
187
- "aria-label": A ?? (Q.inputId ? void 0 : C),
188
+ "aria-disabled": D || void 0,
189
+ "aria-labelledby": k ? void 0 : Q.labelId,
190
+ "aria-label": k ?? (Q.labelId ? void 0 : T),
188
191
  "aria-invalid": ve || void 0,
189
192
  "aria-describedby": ye,
190
193
  "aria-required": be || void 0,
191
- disabled: D,
192
- className: s(h({ size: I }), L && "border-accent-7", $ && se[$], le),
193
- children: [_e(), /* @__PURE__ */ d(c, {
194
- icon: m,
194
+ onKeyDown: (e) => {
195
+ D || (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") && (e.preventDefault(), Y(!0));
196
+ },
197
+ className: c(_({ size: F }), "cursor-pointer", I && "border-accent-7", $ && ae[$], le),
198
+ children: [_e(), /* @__PURE__ */ p(l, {
199
+ icon: g,
195
200
  size: Z,
196
- className: s("ml-ds-02 shrink-0 opacity-50 transition-transform duration-fast-01 ease-productive-standard", L && "rotate-180")
201
+ className: c("ml-ds-02 shrink-0 opacity-50 transition-transform duration-fast-01 ease-productive-standard", I && "rotate-180")
197
202
  })]
198
203
  })
199
- }), /* @__PURE__ */ d(t, { children: /* @__PURE__ */ d(e, {
204
+ }), /* @__PURE__ */ p(t, { children: /* @__PURE__ */ p(e, {
200
205
  asChild: !0,
201
206
  sideOffset: 4,
202
207
  align: "start",
203
208
  onOpenAutoFocus: (e) => {
204
- e.preventDefault(), U.current?.focus();
209
+ e.preventDefault(), H.current?.focus();
205
210
  },
206
- children: /* @__PURE__ */ f(oe.div, {
211
+ children: /* @__PURE__ */ m(ie.div, {
207
212
  initial: {
208
213
  opacity: 0,
209
214
  scale: .95
@@ -213,75 +218,75 @@ var se = {
213
218
  scale: 1
214
219
  },
215
220
  transition: {
216
- ...i.snappy,
217
- opacity: a.fade
221
+ ...a.snappy,
222
+ opacity: o.fade
218
223
  },
219
- className: s("z-popover w-[var(--radix-popover-trigger-width)] overflow-hidden rounded-overlay bg-surface-overlay shadow-floating"),
220
- children: [/* @__PURE__ */ f("div", {
224
+ className: c("z-popover w-[var(--radix-popover-trigger-width)] overflow-hidden rounded-overlay bg-surface-overlay shadow-floating"),
225
+ children: [/* @__PURE__ */ m("div", {
221
226
  className: "flex items-center gap-ds-02 border-b border-surface-border px-ds-04",
222
- children: [/* @__PURE__ */ d(c, {
223
- icon: ie,
227
+ children: [/* @__PURE__ */ p(l, {
228
+ icon: ne,
224
229
  size: "sm",
225
230
  className: "shrink-0 text-surface-fg-subtle"
226
- }), /* @__PURE__ */ d("input", {
227
- ref: U,
231
+ }), /* @__PURE__ */ p("input", {
232
+ ref: H,
228
233
  type: "text",
229
234
  className: "flex-1 bg-transparent py-ds-03 text-body-md outline-hidden placeholder:text-surface-fg-subtle",
230
- placeholder: w,
231
- value: z,
235
+ placeholder: oe,
236
+ value: R,
232
237
  onChange: (e) => {
233
- B(e.target.value), H(-1);
238
+ z(e.target.value), V(-1);
234
239
  },
235
240
  onKeyDown: pe,
236
241
  "aria-autocomplete": "list",
237
- "aria-controls": K,
238
- "aria-activedescendant": V >= 0 ? `${G}-option-${V}` : void 0,
242
+ "aria-controls": G,
243
+ "aria-activedescendant": B >= 0 ? `${W}-option-${B}` : void 0,
239
244
  "aria-label": "Search options"
240
245
  })]
241
- }), J.length === 0 ? /* @__PURE__ */ d("div", {
246
+ }), q.length === 0 ? /* @__PURE__ */ p("div", {
242
247
  className: "px-ds-04 py-ds-05 text-center text-body-md text-surface-fg-subtle",
243
- children: T
244
- }) : /* @__PURE__ */ d("ul", {
245
- ref: W,
246
- id: K,
248
+ children: se
249
+ }) : /* @__PURE__ */ p("ul", {
250
+ ref: U,
251
+ id: G,
247
252
  role: "listbox",
248
253
  "aria-multiselectable": E || void 0,
249
254
  className: "overflow-auto p-ds-02",
250
- style: { maxHeight: `${O * b}px` },
251
- children: J.map((e, t) => {
252
- let n = ue(e.value);
253
- return /* @__PURE__ */ f("li", {
254
- id: `${G}-option-${t}`,
255
+ style: { maxHeight: `${ue * S}px` },
256
+ children: q.map((e, t) => {
257
+ let n = de(e.value);
258
+ return /* @__PURE__ */ m("li", {
259
+ id: `${W}-option-${t}`,
255
260
  role: "option",
256
261
  "aria-selected": n,
257
262
  "aria-disabled": e.disabled || void 0,
258
- className: s("relative flex cursor-pointer select-none items-center gap-ds-03 rounded-control px-ds-04 py-ds-03 text-body-md outline-hidden", "transition-colors duration-fast-01 ease-productive-standard", V === t && "bg-accent-2", n && "text-accent-11", e.disabled && "pointer-events-none opacity-action-disabled"),
263
+ className: c("relative flex cursor-pointer select-none items-center gap-ds-03 rounded-control px-ds-04 py-ds-03 text-body-md outline-hidden", "transition-colors duration-fast-01 ease-productive-standard", B === t && "bg-accent-2", n && "text-accent-11", e.disabled && "pointer-events-none opacity-action-disabled"),
259
264
  onClick: () => {
260
- e.disabled || Y(e.value);
265
+ e.disabled || J(e.value);
261
266
  },
262
267
  onKeyDown: (t) => {
263
- !e.disabled && (t.key === "Enter" || t.key === " ") && (t.preventDefault(), Y(e.value));
268
+ !e.disabled && (t.key === "Enter" || t.key === " ") && (t.preventDefault(), J(e.value));
264
269
  },
265
270
  onMouseEnter: () => {
266
- e.disabled || H(t);
271
+ e.disabled || V(t);
267
272
  },
268
273
  children: [
269
- e.icon && /* @__PURE__ */ d("span", {
274
+ e.icon && /* @__PURE__ */ p("span", {
270
275
  className: "flex h-ico-sm w-ico-sm items-center justify-center shrink-0",
271
- children: /* @__PURE__ */ d(ee, {
276
+ children: /* @__PURE__ */ p(i, {
272
277
  size: Z,
273
- children: re(e.icon)
278
+ children: u(e.icon)
274
279
  })
275
280
  }),
276
- /* @__PURE__ */ d("span", {
281
+ /* @__PURE__ */ p("span", {
277
282
  className: "flex flex-1 flex-col",
278
- children: k ? k(e, n) : /* @__PURE__ */ f(u, { children: [/* @__PURE__ */ d("span", { children: e.label }), e.description && /* @__PURE__ */ d("span", {
283
+ children: O ? O(e, n) : /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p("span", { children: e.label }), e.description && /* @__PURE__ */ p("span", {
279
284
  className: "text-body-sm text-surface-fg-muted",
280
285
  children: e.description
281
286
  })] })
282
287
  }),
283
- n && /* @__PURE__ */ d(c, {
284
- icon: p,
288
+ n && /* @__PURE__ */ p(l, {
289
+ icon: h,
285
290
  size: "sm",
286
291
  className: "shrink-0"
287
292
  })
@@ -294,6 +299,6 @@ var se = {
294
299
  })
295
300
  });
296
301
  });
297
- x.displayName = "Combobox";
302
+ C.displayName = "Combobox";
298
303
  //#endregion
299
- export { x as Combobox, h as comboboxTriggerVariants };
304
+ export { C as Combobox, _ as comboboxTriggerVariants };
@@ -1 +1 @@
1
- {"version":3,"file":"combobox.js","names":[],"sources":["../../src/ui/combobox.tsx"],"sourcesContent":["'use client'\n\nimport * as PopoverPrimitive from '@primitives/react-popover'\nimport { IconCheck, IconChevronDown, IconSearch, IconX } from '@tabler/icons-react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { useFormField } from './form'\nimport { Icon } from './icon'\nimport { IconProvider, type IconSize } from './icon-context'\nimport { type FieldState, resolveFieldState } from './lib/field-state'\nimport type { IconInput } from './lib/icon-input'\nimport { springs, tweens } from './lib/motion'\nimport { normalizeIcon } from './lib/normalize-icon'\nimport { cn } from './lib/utils'\n\n/** Border tint per validation state, applied to the trigger. */\nconst stateBorderClasses: Record<Exclude<FieldState, 'default'>, string> = {\n error: 'border-error-7',\n warning: 'border-warning-7',\n success: 'border-success-7',\n}\n\nexport const comboboxTriggerVariants = cva(\n [\n 'flex w-full items-center justify-between whitespace-nowrap rounded-control',\n 'border border-surface-border-strong bg-surface-raised-hover',\n 'transition-colors duration-fast-01 ease-productive-standard',\n 'focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2 focus-visible:border-accent-7',\n 'disabled:cursor-not-allowed disabled:opacity-action-disabled',\n ],\n {\n variants: {\n size: {\n xs: 'h-ds-xs-plus text-body-sm px-ds-02',\n sm: 'h-ds-sm text-body-sm px-ds-03',\n md: 'h-ds-md text-body-md px-ds-04',\n lg: 'h-ds-lg text-body-md px-ds-05',\n },\n },\n defaultVariants: { size: 'md' },\n },\n)\n\nexport type ComboboxSize = NonNullable<VariantProps<typeof comboboxTriggerVariants>['size']>\n\n/** Maps combobox size to Icon component size for chevron / check icons */\nconst iconSizeMap: Record<NonNullable<ComboboxSize>, IconSize> = {\n xs: 'xs',\n sm: 'sm',\n md: 'sm',\n lg: 'md',\n}\n\n/** Maps combobox size to pill text + padding classes */\nconst pillSizeMap: Record<NonNullable<ComboboxSize>, string> = {\n xs: 'px-ds-02 py-0 text-body-xs',\n sm: 'px-ds-02 py-0 text-body-xs',\n md: 'px-ds-03 py-[1px] text-body-sm',\n lg: 'px-ds-03 py-[2px] text-body-sm',\n}\n\n/** Maps combobox size to overflow text classes */\nconst overflowTextMap: Record<NonNullable<ComboboxSize>, string> = {\n xs: 'text-body-xs',\n sm: 'text-body-xs',\n md: 'text-body-sm',\n lg: 'text-body-sm',\n}\n\n/**\n * Option shape for a Combobox dropdown item.\n * `value` must be unique across all options — it is the key used in selection state.\n */\nexport interface ComboboxOption {\n value: string\n label: string\n description?: string\n icon?: IconInput\n disabled?: boolean\n}\n\n/**\n * Props for Combobox — a searchable single or multi-select dropdown with built-in keyboard\n * navigation, pill overflow (\"+ N more\"), and an optional custom option renderer.\n *\n * **Single vs multi:** `multiple={false}` (default) — `value` is a `string` and `onValueChange`\n * receives a `string`. When `multiple={true}`, `value` is `string[]`, `onValueChange` receives\n * `string[]`, and selected items appear as dismissible pills in the trigger.\n *\n * The props form a **discriminated union** on `multiple` — TypeScript will narrow `value` and\n * `onValueChange` automatically, so no manual casts are needed.\n *\n * **Custom rendering:** Use `renderOption` to return custom JSX per option (e.g. avatars, badges).\n *\n * @example\n * // Single-select country picker:\n * <Combobox\n * options={[{ value: 'in', label: 'India' }, { value: 'us', label: 'United States' }]}\n * value={country}\n * onValueChange={(v) => setCountry(v)}\n * placeholder=\"Select country\"\n * />\n *\n * @example\n * // Multi-select tag picker with pill display:\n * <Combobox\n * multiple\n * options={tagOptions}\n * value={selectedTags}\n * onValueChange={(v) => setSelectedTags(v)}\n * placeholder=\"Select tags...\"\n * />\n *\n * @example\n * // Custom option renderer (user avatars in assignee picker):\n * <Combobox\n * options={users.map(u => ({ value: u.id, label: u.name }))}\n * value={assigneeId}\n * onValueChange={(v) => setAssigneeId(v)}\n * renderOption={(option, selected) => (\n * <span className=\"flex items-center gap-ds-03\">\n * <Avatar size=\"xs\"><AvatarFallback>{option.label[0]}</AvatarFallback></Avatar>\n * {option.label}\n * </span>\n * )}\n * />\n * // These are just a few ways — feel free to combine props creatively!\n */\ninterface ComboboxBaseProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> {\n /** Available options shown in the dropdown. */\n options: ComboboxOption[]\n /** Placeholder shown in the trigger when no value is selected. */\n placeholder?: string\n /** Placeholder for the search input inside the dropdown. */\n searchPlaceholder?: string\n /** Message shown when the search yields no results. */\n emptyMessage?: string\n disabled?: boolean\n triggerClassName?: string\n /** Max visible items in the dropdown before scroll (default 6). */\n maxVisible?: number\n /** Custom renderer for each option row. Receives the option and whether it's currently selected. */\n renderOption?: (option: ComboboxOption, selected: boolean) => React.ReactNode\n /** Accessible label for the trigger button. Falls back to `placeholder` if not provided. */\n accessibleLabel?: string\n /** Size of the trigger. Controls height, text size, padding, and pill sizing. */\n size?: ComboboxSize\n /** Validation/feedback state. `'error'` also sets `aria-invalid`. Inherited from `FormField` when omitted. */\n state?: FieldState\n}\n\ninterface ComboboxSingleProps extends ComboboxBaseProps {\n multiple?: false\n value?: string\n onValueChange: (value: string) => void\n}\n\ninterface ComboboxMultipleProps extends ComboboxBaseProps {\n multiple: true\n value?: string[]\n onValueChange: (value: string[]) => void\n}\n\nexport type ComboboxProps = ComboboxSingleProps | ComboboxMultipleProps\n\n/** Max pills shown in the trigger before \"+N more\" overflow */\nconst MAX_VISIBLE_PILLS = 2\n\n/** Approximate height of a single option item in px */\nconst ITEM_HEIGHT_PX = 36\n\nconst Combobox = React.forwardRef<HTMLButtonElement, ComboboxProps>(\n (\n {\n options,\n value,\n onValueChange,\n placeholder = 'Select...',\n searchPlaceholder = 'Search...',\n emptyMessage = 'No results found',\n multiple = false,\n disabled = false,\n className,\n triggerClassName,\n maxVisible = 6,\n renderOption,\n accessibleLabel,\n id: externalId,\n size: sizeProp = 'md',\n state: stateProp,\n ...rest\n },\n ref,\n ) => {\n const size = sizeProp ?? 'md'\n const [open, setOpen] = React.useState(false)\n const [search, setSearch] = React.useState('')\n const [highlightedIndex, setHighlightedIndex] = React.useState(-1)\n const searchInputRef = React.useRef<HTMLInputElement>(null)\n const listRef = React.useRef<HTMLUListElement>(null)\n const optionIdPrefix = React.useId()\n const listboxId = React.useId()\n\n const selectedValues = React.useMemo<string[]>(() => {\n if (value === undefined || value === null) return []\n if (Array.isArray(value)) return value\n return [value]\n }, [value])\n\n const filteredOptions = React.useMemo(\n () =>\n search\n ? options.filter((o) =>\n o.label.toLowerCase().includes(search.toLowerCase()),\n )\n : options,\n [options, search],\n )\n\n const isSelected = React.useCallback(\n (optionValue: string) => selectedValues.includes(optionValue),\n [selectedValues],\n )\n\n const handleSelect = React.useCallback(\n (optionValue: string) => {\n if (multiple) {\n const newValue = selectedValues.includes(optionValue)\n ? selectedValues.filter((v) => v !== optionValue)\n : [...selectedValues, optionValue]\n ;(onValueChange as (value: string[]) => void)(newValue)\n } else {\n ;(onValueChange as (value: string) => void)(optionValue)\n setOpen(false)\n }\n },\n [multiple, selectedValues, onValueChange],\n )\n\n const handleRemovePill = React.useCallback(\n (e: React.SyntheticEvent, optionValue: string) => {\n e.stopPropagation()\n e.preventDefault()\n const newValue = selectedValues.filter((v) => v !== optionValue)\n ;(onValueChange as (value: string[]) => void)(newValue)\n },\n [selectedValues, onValueChange],\n )\n\n const handleOpenChange = React.useCallback(\n (nextOpen: boolean) => {\n if (disabled) return\n setOpen(nextOpen)\n if (!nextOpen) {\n setSearch('')\n setHighlightedIndex(-1)\n }\n },\n [disabled],\n )\n\n // Auto-focus search input when popover opens\n React.useEffect(() => {\n if (open) {\n // Use a small timeout to allow the popover to render\n const timer = setTimeout(() => {\n searchInputRef.current?.focus()\n }, 0)\n return () => clearTimeout(timer)\n }\n }, [open])\n\n const findNextEnabledIndex = React.useCallback(\n (currentIndex: number, direction: 1 | -1): number => {\n const len = filteredOptions.length\n if (len === 0) return -1\n\n let nextIndex = currentIndex + direction\n while (nextIndex >= 0 && nextIndex < len) {\n if (!filteredOptions[nextIndex].disabled) return nextIndex\n nextIndex += direction\n }\n return currentIndex\n },\n [filteredOptions],\n )\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent) => {\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault()\n const nextIdx = findNextEnabledIndex(highlightedIndex, 1)\n setHighlightedIndex(nextIdx)\n break\n }\n case 'ArrowUp': {\n e.preventDefault()\n const prevIdx = findNextEnabledIndex(highlightedIndex, -1)\n setHighlightedIndex(prevIdx)\n break\n }\n case 'Home': {\n e.preventDefault()\n const firstEnabled = filteredOptions.findIndex((o) => !o.disabled)\n setHighlightedIndex(firstEnabled)\n break\n }\n case 'End': {\n e.preventDefault()\n let lastEnabled = -1\n for (let i = filteredOptions.length - 1; i >= 0; i--) {\n if (!filteredOptions[i].disabled) {\n lastEnabled = i\n break\n }\n }\n setHighlightedIndex(lastEnabled)\n break\n }\n case 'Enter': {\n e.preventDefault()\n if (\n highlightedIndex >= 0 &&\n highlightedIndex < filteredOptions.length &&\n !filteredOptions[highlightedIndex].disabled\n ) {\n handleSelect(filteredOptions[highlightedIndex].value)\n }\n break\n }\n case 'Escape': {\n e.preventDefault()\n setOpen(false)\n setSearch('')\n setHighlightedIndex(-1)\n break\n }\n }\n },\n [highlightedIndex, filteredOptions, findNextEnabledIndex, handleSelect],\n )\n\n // Scroll highlighted option into view\n React.useEffect(() => {\n if (highlightedIndex >= 0 && listRef.current) {\n const optionEl = listRef.current.children[highlightedIndex] as HTMLElement\n if (optionEl) {\n optionEl.scrollIntoView?.({ block: 'nearest' })\n }\n }\n }, [highlightedIndex])\n\n const getSelectedLabel = React.useCallback(() => {\n if (selectedValues.length === 0) return null\n const option = options.find((o) => o.value === selectedValues[0])\n return option?.label ?? null\n }, [selectedValues, options])\n\n const resolvedIconSize = iconSizeMap[size]\n const resolvedPillClasses = pillSizeMap[size]\n const resolvedOverflowText = overflowTextMap[size]\n\n const renderTriggerContent = () => {\n if (multiple && selectedValues.length > 0) {\n const visiblePills = selectedValues.slice(0, MAX_VISIBLE_PILLS)\n const remaining = selectedValues.length - MAX_VISIBLE_PILLS\n\n return (\n <span className=\"flex flex-1 flex-wrap items-center gap-ds-02 overflow-hidden\">\n {visiblePills.map((val) => {\n const option = options.find((o) => o.value === val)\n if (!option) return null\n return (\n <span\n key={val}\n className={cn('inline-flex items-center gap-ds-01 rounded-control-inner bg-accent-2', resolvedPillClasses)}\n >\n {option.label}\n <button\n type=\"button\"\n className=\"inline-flex items-center justify-center rounded-pill outline-hidden hover:bg-surface-raised-hover transition-colors duration-fast-01 ease-productive-standard\"\n onClick={(e) => handleRemovePill(e, val)}\n aria-label={`Remove ${option.label}`}\n tabIndex={-1}\n >\n <Icon icon={IconX} size={resolvedIconSize} />\n </button>\n </span>\n )\n })}\n {remaining > 0 && (\n <span className={cn('text-surface-fg-muted', resolvedOverflowText)}>\n +{remaining} more\n </span>\n )}\n </span>\n )\n }\n\n if (!multiple && selectedValues.length === 1) {\n const label = getSelectedLabel()\n if (label) {\n return <span className=\"min-w-0 flex-1 truncate text-left\">{label}</span>\n }\n }\n\n return (\n <span className=\"min-w-0 flex-1 truncate text-left text-surface-fg-subtle\">\n {placeholder}\n </span>\n )\n }\n\n const fieldCtx = useFormField()\n const state = resolveFieldState(stateProp, fieldCtx.state)\n const isError = state === 'error'\n const ariaDescribedBy = fieldCtx.helperTextId\n const ariaRequired = fieldCtx.required\n\n return (\n <PopoverPrimitive.Root open={open} onOpenChange={handleOpenChange}>\n <div className={cn('relative', className)} {...rest}>\n <PopoverPrimitive.Trigger asChild disabled={disabled}>\n <button\n ref={ref}\n type=\"button\"\n role=\"combobox\"\n // Explicit id wins; otherwise adopt FormField's inputId so <Label htmlFor> resolves.\n id={externalId ?? fieldCtx.inputId}\n aria-expanded={open}\n aria-controls={listboxId}\n aria-haspopup=\"listbox\"\n // Explicit accessibleLabel wins. Inside a FormField, let the visible <Label>\n // provide the name (via htmlFor); only fall back to placeholder when standalone.\n aria-label={accessibleLabel ?? (fieldCtx.inputId ? undefined : placeholder)}\n aria-invalid={isError || undefined}\n aria-describedby={ariaDescribedBy}\n aria-required={ariaRequired || undefined}\n disabled={disabled}\n className={cn(\n comboboxTriggerVariants({ size }),\n open && 'border-accent-7',\n state && stateBorderClasses[state],\n triggerClassName,\n )}\n >\n {renderTriggerContent()}\n <Icon icon={IconChevronDown} size={resolvedIconSize} className={cn(\"ml-ds-02 shrink-0 opacity-50 transition-transform duration-fast-01 ease-productive-standard\", open && 'rotate-180')} />\n </button>\n </PopoverPrimitive.Trigger>\n\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n asChild\n sideOffset={4}\n align=\"start\"\n onOpenAutoFocus={(e) => {\n e.preventDefault()\n searchInputRef.current?.focus()\n }}\n >\n <motion.div\n initial={{ opacity: 0, scale: 0.95 }}\n animate={{ opacity: 1, scale: 1 }}\n transition={{ ...springs.snappy, opacity: tweens.fade }}\n className={cn(\n 'z-popover w-[var(--radix-popover-trigger-width)] overflow-hidden rounded-overlay bg-surface-overlay shadow-floating',\n )}\n >\n {/* Search input */}\n <div className=\"flex items-center gap-ds-02 border-b border-surface-border px-ds-04\">\n <Icon icon={IconSearch} size=\"sm\" className=\"shrink-0 text-surface-fg-subtle\" />\n <input\n ref={searchInputRef}\n type=\"text\"\n className=\"flex-1 bg-transparent py-ds-03 text-body-md outline-hidden placeholder:text-surface-fg-subtle\"\n placeholder={searchPlaceholder}\n value={search}\n onChange={(e) => {\n setSearch(e.target.value)\n setHighlightedIndex(-1)\n }}\n onKeyDown={handleKeyDown}\n aria-autocomplete=\"list\"\n aria-controls={listboxId}\n aria-activedescendant={\n highlightedIndex >= 0\n ? `${optionIdPrefix}-option-${highlightedIndex}`\n : undefined\n }\n aria-label=\"Search options\"\n />\n </div>\n\n {/* Options list */}\n {filteredOptions.length === 0 ? (\n <div className=\"px-ds-04 py-ds-05 text-center text-body-md text-surface-fg-subtle\">\n {emptyMessage}\n </div>\n ) : (\n <ul\n ref={listRef}\n id={listboxId}\n role=\"listbox\"\n aria-multiselectable={multiple || undefined}\n className=\"overflow-auto p-ds-02\"\n style={{ maxHeight: `${maxVisible * ITEM_HEIGHT_PX}px` }}\n >\n {filteredOptions.map((option, index) => {\n const selected = isSelected(option.value)\n return (\n <li\n key={option.value}\n id={`${optionIdPrefix}-option-${index}`}\n role=\"option\"\n aria-selected={selected}\n aria-disabled={option.disabled || undefined}\n className={cn(\n 'relative flex cursor-pointer select-none items-center gap-ds-03 rounded-control px-ds-04 py-ds-03 text-body-md outline-hidden',\n 'transition-colors duration-fast-01 ease-productive-standard',\n highlightedIndex === index &&\n 'bg-accent-2',\n selected && 'text-accent-11',\n option.disabled &&\n 'pointer-events-none opacity-action-disabled',\n )}\n onClick={() => {\n if (!option.disabled) {\n handleSelect(option.value)\n }\n }}\n onKeyDown={(e) => {\n if (!option.disabled && (e.key === 'Enter' || e.key === ' ')) {\n e.preventDefault()\n handleSelect(option.value)\n }\n }}\n onMouseEnter={() => {\n if (!option.disabled) {\n setHighlightedIndex(index)\n }\n }}\n >\n {option.icon && (\n <span className=\"flex h-ico-sm w-ico-sm items-center justify-center shrink-0\">\n <IconProvider size={resolvedIconSize}>\n {normalizeIcon(option.icon)}\n </IconProvider>\n </span>\n )}\n <span className=\"flex flex-1 flex-col\">\n {renderOption ? (\n renderOption(option, selected)\n ) : (\n <>\n <span>{option.label}</span>\n {option.description && (\n <span className=\"text-body-sm text-surface-fg-muted\">\n {option.description}\n </span>\n )}\n </>\n )}\n </span>\n {selected && (\n <Icon icon={IconCheck} size=\"sm\" className=\"shrink-0\" />\n )}\n </li>\n )\n })}\n </ul>\n )}\n </motion.div>\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n </div>\n </PopoverPrimitive.Root>\n )\n },\n)\nCombobox.displayName = 'Combobox'\n\nexport { Combobox }\n"],"mappings":";;;;;;;;;;;;;;;AAkBA,IAAM,KAAqE;CACzE,OAAO;CACP,SAAS;CACT,SAAS;AACX,GAEa,IAA0B,EACrC;CACE;CACA;CACA;CACA;CACA;AACF,GACA;CACE,UAAU,EACR,MAAM;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;CACN,EACF;CACA,iBAAiB,EAAE,MAAM,KAAK;AAChC,CACF,GAKM,IAA2D;CAC/D,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACN,GAGM,IAAyD;CAC7D,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACN,GAGM,IAA6D;CACjE,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACN,GAmGM,IAAoB,GAGpB,IAAiB,IAEjB,IAAW,EAAM,YAEnB,EACE,YACA,UACA,kBACA,iBAAc,aACd,uBAAoB,aACpB,kBAAe,oBACf,cAAW,IACX,cAAW,IACX,eACA,sBACA,gBAAa,GACb,iBACA,oBACA,IAAI,GACJ,MAAM,IAAW,MACjB,OAAO,GACP,GAAG,KAEL,MACG;CACH,IAAM,IAAO,KAAY,MACnB,CAAC,GAAM,KAAW,EAAM,SAAS,EAAK,GACtC,CAAC,GAAQ,KAAa,EAAM,SAAS,EAAE,GACvC,CAAC,GAAkB,KAAuB,EAAM,SAAS,EAAE,GAC3D,IAAiB,EAAM,OAAyB,IAAI,GACpD,IAAU,EAAM,OAAyB,IAAI,GAC7C,IAAiB,EAAM,MAAM,GAC7B,IAAY,EAAM,MAAM,GAExB,IAAiB,EAAM,cACvB,KAAiC,OAAa,CAAC,IAC/C,MAAM,QAAQ,CAAK,IAAU,IAC1B,CAAC,CAAK,GACZ,CAAC,CAAK,CAAC,GAEJ,IAAkB,EAAM,cAE1B,IACI,EAAQ,QAAQ,MACd,EAAE,MAAM,YAAY,CAAC,CAAC,SAAS,EAAO,YAAY,CAAC,CACrD,IACA,GACN,CAAC,GAAS,CAAM,CAClB,GAEM,KAAa,EAAM,aACtB,MAAwB,EAAe,SAAS,CAAW,GAC5D,CAAC,CAAc,CACjB,GAEM,IAAe,EAAM,aACxB,MAAwB;EACvB,AAAI,IAID,EAHgB,EAAe,SAAS,CAAW,IAChD,EAAe,QAAQ,MAAM,MAAM,CAAW,IAC9C,CAAC,GAAG,GAAgB,CAAW,CACmB,KAErD,EAA2C,CAAW,GACvD,EAAQ,EAAK;CAEjB,GACA;EAAC;EAAU;EAAgB;CAAa,CAC1C,GAEM,KAAmB,EAAM,aAC5B,GAAyB,MAAwB;EAI/C,AAHD,EAAE,gBAAgB,GAClB,EAAE,eAAe,GAEhB,EADgB,EAAe,QAAQ,MAAM,MAAM,CACN,CAAQ;CACxD,GACA,CAAC,GAAgB,CAAa,CAChC,GAEM,KAAmB,EAAM,aAC5B,MAAsB;EACjB,MACJ,EAAQ,CAAQ,GACX,MACH,EAAU,EAAE,GACZ,EAAoB,EAAE;CAE1B,GACA,CAAC,CAAQ,CACX;CAGA,EAAM,gBAAgB;EACpB,IAAI,GAAM;GAER,IAAM,IAAQ,iBAAiB;IAC7B,EAAe,SAAS,MAAM;GAChC,GAAG,CAAC;GACJ,aAAa,aAAa,CAAK;EACjC;CACF,GAAG,CAAC,CAAI,CAAC;CAET,IAAM,IAAuB,EAAM,aAChC,GAAsB,MAA8B;EACnD,IAAM,IAAM,EAAgB;EAC5B,IAAI,MAAQ,GAAG,OAAO;EAEtB,IAAI,IAAY,IAAe;EAC/B,OAAO,KAAa,KAAK,IAAY,IAAK;GACxC,IAAI,CAAC,EAAgB,EAAU,CAAC,UAAU,OAAO;GACjD,KAAa;EACf;EACA,OAAO;CACT,GACA,CAAC,CAAe,CAClB,GAEM,KAAgB,EAAM,aACzB,MAA2B;EAC1B,QAAQ,EAAE,KAAV;GACE,KAAK,aAAa;IAChB,EAAE,eAAe;IACjB,IAAM,IAAU,EAAqB,GAAkB,CAAC;IACxD,EAAoB,CAAO;IAC3B;GACF;GACA,KAAK,WAAW;IACd,EAAE,eAAe;IACjB,IAAM,IAAU,EAAqB,GAAkB,EAAE;IACzD,EAAoB,CAAO;IAC3B;GACF;GACA,KAAK,QAAQ;IACX,EAAE,eAAe;IACjB,IAAM,IAAe,EAAgB,WAAW,MAAM,CAAC,EAAE,QAAQ;IACjE,EAAoB,CAAY;IAChC;GACF;GACA,KAAK,OAAO;IACV,EAAE,eAAe;IACjB,IAAI,IAAc;IAClB,KAAK,IAAI,IAAI,EAAgB,SAAS,GAAG,KAAK,GAAG,KAC/C,IAAI,CAAC,EAAgB,EAAE,CAAC,UAAU;KAChC,IAAc;KACd;IACF;IAEF,EAAoB,CAAW;IAC/B;GACF;GACA,KAAK;IAEH,AADA,EAAE,eAAe,GAEf,KAAoB,KACpB,IAAmB,EAAgB,UACnC,CAAC,EAAgB,EAAiB,CAAC,YAEnC,EAAa,EAAgB,EAAiB,CAAC,KAAK;IAEtD;GAEF,KAAK;IAIH,AAHA,EAAE,eAAe,GACjB,EAAQ,EAAK,GACb,EAAU,EAAE,GACZ,EAAoB,EAAE;IACtB;EAEJ;CACF,GACA;EAAC;EAAkB;EAAiB;EAAsB;CAAY,CACxE;CAGA,EAAM,gBAAgB;EACpB,IAAI,KAAoB,KAAK,EAAQ,SAAS;GAC5C,IAAM,IAAW,EAAQ,QAAQ,SAAS;GAC1C,AAAI,KACF,EAAS,iBAAiB,EAAE,OAAO,UAAU,CAAC;EAElD;CACF,GAAG,CAAC,CAAgB,CAAC;CAErB,IAAM,KAAmB,EAAM,kBACzB,EAAe,WAAW,IAAU,OACzB,EAAQ,MAAM,MAAM,EAAE,UAAU,EAAe,EACvD,CAAA,EAAQ,SAAS,MACvB,CAAC,GAAgB,CAAO,CAAC,GAEtB,IAAmB,EAAY,IAC/B,KAAsB,EAAY,IAClC,KAAuB,EAAgB,IAEvC,WAA6B;EACjC,IAAI,KAAY,EAAe,SAAS,GAAG;GACzC,IAAM,IAAe,EAAe,MAAM,GAAG,CAAiB,GACxD,IAAY,EAAe,SAAS;GAE1C,OACE,kBAAC,QAAD;IAAM,WAAU;cAAhB,CACG,EAAa,KAAK,MAAQ;KACzB,IAAM,IAAS,EAAQ,MAAM,MAAM,EAAE,UAAU,CAAG;KAElD,OADK,IAEH,kBAAC,QAAD;MAEE,WAAW,EAAG,wEAAwE,EAAmB;gBAF3G,CAIG,EAAO,OACR,kBAAC,UAAD;OACE,MAAK;OACL,WAAU;OACV,UAAU,MAAM,GAAiB,GAAG,CAAG;OACvC,cAAY,UAAU,EAAO;OAC7B,UAAU;iBAEV,kBAAC,GAAD;QAAM,MAAM;QAAO,MAAM;OAAmB,CAAA;MACtC,CAAA,CACJ;QAbC,CAaD,IAhBY;IAkBtB,CAAC,GACA,IAAY,KACX,kBAAC,QAAD;KAAM,WAAW,EAAG,yBAAyB,EAAoB;eAAjE;MAAoE;MAChE;MAAU;KACR;MAEJ;;EAEV;EAEA,IAAI,CAAC,KAAY,EAAe,WAAW,GAAG;GAC5C,IAAM,IAAQ,GAAiB;GAC/B,IAAI,GACF,OAAO,kBAAC,QAAD;IAAM,WAAU;cAAqC;GAAY,CAAA;EAE5E;EAEA,OACE,kBAAC,QAAD;GAAM,WAAU;aACb;EACG,CAAA;CAEV,GAEM,IAAW,GAAa,GACxB,IAAQ,GAAkB,GAAW,EAAS,KAAK,GACnD,KAAU,MAAU,SACpB,KAAkB,EAAS,cAC3B,KAAe,EAAS;CAE9B,OACE,kBAAC,GAAD;EAA6B;EAAM,cAAc;YAC/C,kBAAC,OAAD;GAAK,WAAW,EAAG,YAAY,EAAS;GAAG,GAAI;aAA/C,CACA,kBAAC,GAAD;IAA0B,SAAA;IAAkB;cAC1C,kBAAC,UAAD;KACO;KACL,MAAK;KACL,MAAK;KAEL,IAAI,KAAc,EAAS;KAC3B,iBAAe;KACf,iBAAe;KACf,iBAAc;KAGd,cAAY,MAAoB,EAAS,UAAU,KAAA,IAAY;KAC/D,gBAAc,MAAW,KAAA;KACzB,oBAAkB;KAClB,iBAAe,MAAgB,KAAA;KACrB;KACV,WAAW,EACT,EAAwB,EAAE,QAAK,CAAC,GAChC,KAAQ,mBACR,KAAS,GAAmB,IAC5B,EACF;eArBF,CAuBG,GAAqB,GACtB,kBAAC,GAAD;MAAM,MAAM;MAAiB,MAAM;MAAkB,WAAW,EAAG,+FAA+F,KAAQ,YAAY;KAAI,CAAA,CACpL;;GACgB,CAAA,GAE1B,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;IACE,SAAA;IACA,YAAY;IACZ,OAAM;IACN,kBAAkB,MAAM;KAEtB,AADA,EAAE,eAAe,GACjB,EAAe,SAAS,MAAM;IAChC;cAEA,kBAAC,GAAO,KAAR;KACE,SAAS;MAAE,SAAS;MAAG,OAAO;KAAK;KACnC,SAAS;MAAE,SAAS;MAAG,OAAO;KAAE;KAChC,YAAY;MAAE,GAAG,EAAQ;MAAQ,SAAS,EAAO;KAAK;KACtD,WAAW,EACT,qHACF;eANF,CASM,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,GAAD;OAAM,MAAM;OAAY,MAAK;OAAK,WAAU;MAAmC,CAAA,GAC/E,kBAAC,SAAD;OACE,KAAK;OACL,MAAK;OACL,WAAU;OACV,aAAa;OACb,OAAO;OACP,WAAW,MAAM;QAEf,AADA,EAAU,EAAE,OAAO,KAAK,GACxB,EAAoB,EAAE;OACxB;OACA,WAAW;OACX,qBAAkB;OAClB,iBAAe;OACf,yBACE,KAAoB,IAChB,GAAG,EAAe,UAAU,MAC5B,KAAA;OAEN,cAAW;MACZ,CAAA,CACE;SAGJ,EAAgB,WAAW,IAC1B,kBAAC,OAAD;MAAK,WAAU;gBACZ;KACE,CAAA,IAEL,kBAAC,MAAD;MACE,KAAK;MACL,IAAI;MACJ,MAAK;MACL,wBAAsB,KAAY,KAAA;MAClC,WAAU;MACV,OAAO,EAAE,WAAW,GAAG,IAAa,EAAe,IAAI;gBAEtD,EAAgB,KAAK,GAAQ,MAAU;OACtC,IAAM,IAAW,GAAW,EAAO,KAAK;OACxC,OACE,kBAAC,MAAD;QAEE,IAAI,GAAG,EAAe,UAAU;QAChC,MAAK;QACL,iBAAe;QACf,iBAAe,EAAO,YAAY,KAAA;QAClC,WAAW,EACT,iIACA,+DACA,MAAqB,KACnB,eACF,KAAY,kBACZ,EAAO,YACL,6CACJ;QACA,eAAe;SACb,AAAK,EAAO,YACV,EAAa,EAAO,KAAK;QAE7B;QACA,YAAY,MAAM;SAChB,AAAI,CAAC,EAAO,aAAa,EAAE,QAAQ,WAAW,EAAE,QAAQ,SACtD,EAAE,eAAe,GACjB,EAAa,EAAO,KAAK;QAE7B;QACA,oBAAoB;SAClB,AAAK,EAAO,YACV,EAAoB,CAAK;QAE7B;kBA9BF;SAgCG,EAAO,QACN,kBAAC,QAAD;UAAM,WAAU;oBACd,kBAAC,IAAD;WAAc,MAAM;qBACjB,GAAc,EAAO,IAAI;UACd,CAAA;SACV,CAAA;SAER,kBAAC,QAAD;UAAM,WAAU;oBACb,IACC,EAAa,GAAQ,CAAQ,IAE7B,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,QAAD,EAAA,UAAO,EAAO,MAAY,CAAA,GACzB,EAAO,eACN,kBAAC,QAAD;WAAM,WAAU;qBACb,EAAO;UACJ,CAAA,CAER,EAAA,CAAA;SAEA,CAAA;SACL,KACC,kBAAC,GAAD;UAAM,MAAM;UAAW,MAAK;UAAK,WAAU;SAAY,CAAA;QAEvD;UAvDG,EAAO,KAuDV;MAER,CAAC;KACC,CAAA,CAEI;;GACQ,CAAA,EACH,CAAA,CACpB;;CACgB,CAAA;AAE3B,CACF;AACA,EAAS,cAAc"}
1
+ {"version":3,"file":"combobox.js","names":[],"sources":["../../src/ui/combobox.tsx"],"sourcesContent":["'use client'\n\nimport * as PopoverPrimitive from '@primitives/react-popover'\nimport { IconCheck, IconChevronDown, IconSearch, IconX } from '@tabler/icons-react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { useFormField } from './form'\nimport { Icon } from './icon'\nimport { IconProvider, type IconSize } from './icon-context'\nimport { type FieldState, resolveFieldState } from './lib/field-state'\nimport type { IconInput } from './lib/icon-input'\nimport { springs, tweens } from './lib/motion'\nimport { normalizeIcon } from './lib/normalize-icon'\nimport { cn } from './lib/utils'\n\n/** Border tint per validation state, applied to the trigger. */\nconst stateBorderClasses: Record<Exclude<FieldState, 'default'>, string> = {\n error: 'border-error-7',\n warning: 'border-warning-7',\n success: 'border-success-7',\n}\n\nexport const comboboxTriggerVariants = cva(\n [\n 'flex w-full items-center justify-between whitespace-nowrap rounded-control',\n 'border border-surface-border-strong bg-surface-raised-hover',\n 'transition-colors duration-fast-01 ease-productive-standard',\n 'focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2 focus-visible:border-accent-7',\n // Trigger is a div[role=combobox] (so chip remove-buttons in multi-select\n // aren't nested in a <button>), so disabled styling keys off data-disabled,\n // not the :disabled pseudo-class.\n 'data-[disabled]:cursor-not-allowed data-[disabled]:opacity-action-disabled',\n ],\n {\n variants: {\n size: {\n xs: 'h-ds-xs-plus text-body-sm px-ds-02',\n sm: 'h-ds-sm text-body-sm px-ds-03',\n md: 'h-ds-md text-body-md px-ds-04',\n lg: 'h-ds-lg text-body-md px-ds-05',\n },\n },\n defaultVariants: { size: 'md' },\n },\n)\n\nexport type ComboboxSize = NonNullable<VariantProps<typeof comboboxTriggerVariants>['size']>\n\n/** Maps combobox size to Icon component size for chevron / check icons */\nconst iconSizeMap: Record<NonNullable<ComboboxSize>, IconSize> = {\n xs: 'xs',\n sm: 'sm',\n md: 'sm',\n lg: 'md',\n}\n\n/** Maps combobox size to pill text + padding classes */\nconst pillSizeMap: Record<NonNullable<ComboboxSize>, string> = {\n xs: 'px-ds-02 py-0 text-body-xs',\n sm: 'px-ds-02 py-0 text-body-xs',\n md: 'px-ds-03 py-[1px] text-body-sm',\n lg: 'px-ds-03 py-[2px] text-body-sm',\n}\n\n/** Maps combobox size to overflow text classes */\nconst overflowTextMap: Record<NonNullable<ComboboxSize>, string> = {\n xs: 'text-body-xs',\n sm: 'text-body-xs',\n md: 'text-body-sm',\n lg: 'text-body-sm',\n}\n\n/**\n * Option shape for a Combobox dropdown item.\n * `value` must be unique across all options — it is the key used in selection state.\n */\nexport interface ComboboxOption {\n value: string\n label: string\n description?: string\n icon?: IconInput\n disabled?: boolean\n}\n\n/**\n * Props for Combobox — a searchable single or multi-select dropdown with built-in keyboard\n * navigation, pill overflow (\"+ N more\"), and an optional custom option renderer.\n *\n * **Single vs multi:** `multiple={false}` (default) — `value` is a `string` and `onValueChange`\n * receives a `string`. When `multiple={true}`, `value` is `string[]`, `onValueChange` receives\n * `string[]`, and selected items appear as dismissible pills in the trigger.\n *\n * The props form a **discriminated union** on `multiple` — TypeScript will narrow `value` and\n * `onValueChange` automatically, so no manual casts are needed.\n *\n * **Custom rendering:** Use `renderOption` to return custom JSX per option (e.g. avatars, badges).\n *\n * @example\n * // Single-select country picker:\n * <Combobox\n * options={[{ value: 'in', label: 'India' }, { value: 'us', label: 'United States' }]}\n * value={country}\n * onValueChange={(v) => setCountry(v)}\n * placeholder=\"Select country\"\n * />\n *\n * @example\n * // Multi-select tag picker with pill display:\n * <Combobox\n * multiple\n * options={tagOptions}\n * value={selectedTags}\n * onValueChange={(v) => setSelectedTags(v)}\n * placeholder=\"Select tags...\"\n * />\n *\n * @example\n * // Custom option renderer (user avatars in assignee picker):\n * <Combobox\n * options={users.map(u => ({ value: u.id, label: u.name }))}\n * value={assigneeId}\n * onValueChange={(v) => setAssigneeId(v)}\n * renderOption={(option, selected) => (\n * <span className=\"flex items-center gap-ds-03\">\n * <Avatar size=\"xs\"><AvatarFallback>{option.label[0]}</AvatarFallback></Avatar>\n * {option.label}\n * </span>\n * )}\n * />\n * // These are just a few ways — feel free to combine props creatively!\n */\ninterface ComboboxBaseProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> {\n /** Available options shown in the dropdown. */\n options: ComboboxOption[]\n /** Placeholder shown in the trigger when no value is selected. */\n placeholder?: string\n /** Placeholder for the search input inside the dropdown. */\n searchPlaceholder?: string\n /** Message shown when the search yields no results. */\n emptyMessage?: string\n disabled?: boolean\n triggerClassName?: string\n /** Max visible items in the dropdown before scroll (default 6). */\n maxVisible?: number\n /** Custom renderer for each option row. Receives the option and whether it's currently selected. */\n renderOption?: (option: ComboboxOption, selected: boolean) => React.ReactNode\n /** Accessible label for the trigger button. Falls back to `placeholder` if not provided. */\n accessibleLabel?: string\n /** Size of the trigger. Controls height, text size, padding, and pill sizing. */\n size?: ComboboxSize\n /** Validation/feedback state. `'error'` also sets `aria-invalid`. Inherited from `FormField` when omitted. */\n state?: FieldState\n}\n\ninterface ComboboxSingleProps extends ComboboxBaseProps {\n multiple?: false\n value?: string\n onValueChange: (value: string) => void\n}\n\ninterface ComboboxMultipleProps extends ComboboxBaseProps {\n multiple: true\n value?: string[]\n onValueChange: (value: string[]) => void\n}\n\nexport type ComboboxProps = ComboboxSingleProps | ComboboxMultipleProps\n\n/** Max pills shown in the trigger before \"+N more\" overflow */\nconst MAX_VISIBLE_PILLS = 2\n\n/** Approximate height of a single option item in px */\nconst ITEM_HEIGHT_PX = 36\n\nconst Combobox = React.forwardRef<HTMLDivElement, ComboboxProps>(\n (\n {\n options,\n value,\n onValueChange,\n placeholder = 'Select...',\n searchPlaceholder = 'Search...',\n emptyMessage = 'No results found',\n multiple = false,\n disabled = false,\n className,\n triggerClassName,\n maxVisible = 6,\n renderOption,\n accessibleLabel,\n id: externalId,\n size: sizeProp = 'md',\n state: stateProp,\n ...rest\n },\n ref,\n ) => {\n const size = sizeProp ?? 'md'\n const [open, setOpen] = React.useState(false)\n const [search, setSearch] = React.useState('')\n const [highlightedIndex, setHighlightedIndex] = React.useState(-1)\n const searchInputRef = React.useRef<HTMLInputElement>(null)\n const listRef = React.useRef<HTMLUListElement>(null)\n const optionIdPrefix = React.useId()\n const listboxId = React.useId()\n\n const selectedValues = React.useMemo<string[]>(() => {\n if (value === undefined || value === null) return []\n if (Array.isArray(value)) return value\n return [value]\n }, [value])\n\n const filteredOptions = React.useMemo(\n () =>\n search\n ? options.filter((o) =>\n o.label.toLowerCase().includes(search.toLowerCase()),\n )\n : options,\n [options, search],\n )\n\n const isSelected = React.useCallback(\n (optionValue: string) => selectedValues.includes(optionValue),\n [selectedValues],\n )\n\n const handleSelect = React.useCallback(\n (optionValue: string) => {\n if (multiple) {\n const newValue = selectedValues.includes(optionValue)\n ? selectedValues.filter((v) => v !== optionValue)\n : [...selectedValues, optionValue]\n ;(onValueChange as (value: string[]) => void)(newValue)\n } else {\n ;(onValueChange as (value: string) => void)(optionValue)\n setOpen(false)\n }\n },\n [multiple, selectedValues, onValueChange],\n )\n\n const handleRemovePill = React.useCallback(\n (e: React.SyntheticEvent, optionValue: string) => {\n e.stopPropagation()\n e.preventDefault()\n const newValue = selectedValues.filter((v) => v !== optionValue)\n ;(onValueChange as (value: string[]) => void)(newValue)\n },\n [selectedValues, onValueChange],\n )\n\n const handleOpenChange = React.useCallback(\n (nextOpen: boolean) => {\n if (disabled) return\n setOpen(nextOpen)\n if (!nextOpen) {\n setSearch('')\n setHighlightedIndex(-1)\n }\n },\n [disabled],\n )\n\n // Auto-focus search input when popover opens\n React.useEffect(() => {\n if (open) {\n // Use a small timeout to allow the popover to render\n const timer = setTimeout(() => {\n searchInputRef.current?.focus()\n }, 0)\n return () => clearTimeout(timer)\n }\n }, [open])\n\n const findNextEnabledIndex = React.useCallback(\n (currentIndex: number, direction: 1 | -1): number => {\n const len = filteredOptions.length\n if (len === 0) return -1\n\n let nextIndex = currentIndex + direction\n while (nextIndex >= 0 && nextIndex < len) {\n if (!filteredOptions[nextIndex].disabled) return nextIndex\n nextIndex += direction\n }\n return currentIndex\n },\n [filteredOptions],\n )\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent) => {\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault()\n const nextIdx = findNextEnabledIndex(highlightedIndex, 1)\n setHighlightedIndex(nextIdx)\n break\n }\n case 'ArrowUp': {\n e.preventDefault()\n const prevIdx = findNextEnabledIndex(highlightedIndex, -1)\n setHighlightedIndex(prevIdx)\n break\n }\n case 'Home': {\n e.preventDefault()\n const firstEnabled = filteredOptions.findIndex((o) => !o.disabled)\n setHighlightedIndex(firstEnabled)\n break\n }\n case 'End': {\n e.preventDefault()\n let lastEnabled = -1\n for (let i = filteredOptions.length - 1; i >= 0; i--) {\n if (!filteredOptions[i].disabled) {\n lastEnabled = i\n break\n }\n }\n setHighlightedIndex(lastEnabled)\n break\n }\n case 'Enter': {\n e.preventDefault()\n if (\n highlightedIndex >= 0 &&\n highlightedIndex < filteredOptions.length &&\n !filteredOptions[highlightedIndex].disabled\n ) {\n handleSelect(filteredOptions[highlightedIndex].value)\n }\n break\n }\n case 'Escape': {\n e.preventDefault()\n setOpen(false)\n setSearch('')\n setHighlightedIndex(-1)\n break\n }\n }\n },\n [highlightedIndex, filteredOptions, findNextEnabledIndex, handleSelect],\n )\n\n // Scroll highlighted option into view\n React.useEffect(() => {\n if (highlightedIndex >= 0 && listRef.current) {\n const optionEl = listRef.current.children[highlightedIndex] as HTMLElement\n if (optionEl) {\n optionEl.scrollIntoView?.({ block: 'nearest' })\n }\n }\n }, [highlightedIndex])\n\n const getSelectedLabel = React.useCallback(() => {\n if (selectedValues.length === 0) return null\n const option = options.find((o) => o.value === selectedValues[0])\n return option?.label ?? null\n }, [selectedValues, options])\n\n const resolvedIconSize = iconSizeMap[size]\n const resolvedPillClasses = pillSizeMap[size]\n const resolvedOverflowText = overflowTextMap[size]\n\n const renderTriggerContent = () => {\n if (multiple && selectedValues.length > 0) {\n const visiblePills = selectedValues.slice(0, MAX_VISIBLE_PILLS)\n const remaining = selectedValues.length - MAX_VISIBLE_PILLS\n\n return (\n <span className=\"flex flex-1 flex-wrap items-center gap-ds-02 overflow-hidden\">\n {visiblePills.map((val) => {\n const option = options.find((o) => o.value === val)\n if (!option) return null\n return (\n <span\n key={val}\n className={cn('inline-flex items-center gap-ds-01 rounded-control-inner bg-accent-2', resolvedPillClasses)}\n >\n {option.label}\n <button\n type=\"button\"\n className=\"inline-flex items-center justify-center rounded-pill outline-hidden hover:bg-surface-raised-hover transition-colors duration-fast-01 ease-productive-standard\"\n onClick={(e) => handleRemovePill(e, val)}\n aria-label={`Remove ${option.label}`}\n tabIndex={-1}\n >\n <Icon icon={IconX} size={resolvedIconSize} />\n </button>\n </span>\n )\n })}\n {remaining > 0 && (\n <span className={cn('text-surface-fg-muted', resolvedOverflowText)}>\n +{remaining} more\n </span>\n )}\n </span>\n )\n }\n\n if (!multiple && selectedValues.length === 1) {\n const label = getSelectedLabel()\n if (label) {\n return <span className=\"min-w-0 flex-1 truncate text-left\">{label}</span>\n }\n }\n\n return (\n <span className=\"min-w-0 flex-1 truncate text-left text-surface-fg-subtle\">\n {placeholder}\n </span>\n )\n }\n\n const fieldCtx = useFormField()\n const state = resolveFieldState(stateProp, fieldCtx.state)\n const isError = state === 'error'\n const ariaDescribedBy = fieldCtx.helperTextId\n const ariaRequired = fieldCtx.required\n\n return (\n <PopoverPrimitive.Root open={open} onOpenChange={handleOpenChange}>\n <div className={cn('relative', className)} {...rest}>\n <PopoverPrimitive.Trigger asChild disabled={disabled}>\n {/* role=combobox on a <div>, NOT a <button> — a native button can't\n legally contain the chip remove-<button>s rendered in multi-select\n (invalid HTML + a11y break). This is the W3C select-only combobox\n pattern. Radix Trigger wires click/toggle; we add the keyboard-open\n (Enter/Space/ArrowDown) a real button would have given for free. */}\n <div\n ref={ref}\n role=\"combobox\"\n tabIndex={disabled ? -1 : 0}\n data-disabled={disabled || undefined}\n id={externalId}\n aria-expanded={open}\n aria-controls={listboxId}\n aria-haspopup=\"listbox\"\n aria-disabled={disabled || undefined}\n // The trigger is a div[role=combobox] — non-labellable, so `<Label htmlFor>`\n // can't target it. Inside a FormField, adopt the label's id via\n // aria-labelledby; explicit accessibleLabel wins; placeholder is the\n // standalone fallback.\n aria-labelledby={accessibleLabel ? undefined : fieldCtx.labelId}\n aria-label={accessibleLabel ?? (fieldCtx.labelId ? undefined : placeholder)}\n aria-invalid={isError || undefined}\n aria-describedby={ariaDescribedBy}\n aria-required={ariaRequired || undefined}\n onKeyDown={(e) => {\n if (disabled) return\n if (e.key === 'Enter' || e.key === ' ' || e.key === 'ArrowDown') {\n e.preventDefault()\n handleOpenChange(true)\n }\n }}\n className={cn(\n comboboxTriggerVariants({ size }),\n 'cursor-pointer',\n open && 'border-accent-7',\n state && stateBorderClasses[state],\n triggerClassName,\n )}\n >\n {renderTriggerContent()}\n <Icon icon={IconChevronDown} size={resolvedIconSize} className={cn(\"ml-ds-02 shrink-0 opacity-50 transition-transform duration-fast-01 ease-productive-standard\", open && 'rotate-180')} />\n </div>\n </PopoverPrimitive.Trigger>\n\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n asChild\n sideOffset={4}\n align=\"start\"\n onOpenAutoFocus={(e) => {\n e.preventDefault()\n searchInputRef.current?.focus()\n }}\n >\n <motion.div\n initial={{ opacity: 0, scale: 0.95 }}\n animate={{ opacity: 1, scale: 1 }}\n transition={{ ...springs.snappy, opacity: tweens.fade }}\n className={cn(\n 'z-popover w-[var(--radix-popover-trigger-width)] overflow-hidden rounded-overlay bg-surface-overlay shadow-floating',\n )}\n >\n {/* Search input */}\n <div className=\"flex items-center gap-ds-02 border-b border-surface-border px-ds-04\">\n <Icon icon={IconSearch} size=\"sm\" className=\"shrink-0 text-surface-fg-subtle\" />\n <input\n ref={searchInputRef}\n type=\"text\"\n className=\"flex-1 bg-transparent py-ds-03 text-body-md outline-hidden placeholder:text-surface-fg-subtle\"\n placeholder={searchPlaceholder}\n value={search}\n onChange={(e) => {\n setSearch(e.target.value)\n setHighlightedIndex(-1)\n }}\n onKeyDown={handleKeyDown}\n aria-autocomplete=\"list\"\n aria-controls={listboxId}\n aria-activedescendant={\n highlightedIndex >= 0\n ? `${optionIdPrefix}-option-${highlightedIndex}`\n : undefined\n }\n aria-label=\"Search options\"\n />\n </div>\n\n {/* Options list */}\n {filteredOptions.length === 0 ? (\n <div className=\"px-ds-04 py-ds-05 text-center text-body-md text-surface-fg-subtle\">\n {emptyMessage}\n </div>\n ) : (\n <ul\n ref={listRef}\n id={listboxId}\n role=\"listbox\"\n aria-multiselectable={multiple || undefined}\n className=\"overflow-auto p-ds-02\"\n style={{ maxHeight: `${maxVisible * ITEM_HEIGHT_PX}px` }}\n >\n {filteredOptions.map((option, index) => {\n const selected = isSelected(option.value)\n return (\n <li\n key={option.value}\n id={`${optionIdPrefix}-option-${index}`}\n role=\"option\"\n aria-selected={selected}\n aria-disabled={option.disabled || undefined}\n className={cn(\n 'relative flex cursor-pointer select-none items-center gap-ds-03 rounded-control px-ds-04 py-ds-03 text-body-md outline-hidden',\n 'transition-colors duration-fast-01 ease-productive-standard',\n highlightedIndex === index &&\n 'bg-accent-2',\n selected && 'text-accent-11',\n option.disabled &&\n 'pointer-events-none opacity-action-disabled',\n )}\n onClick={() => {\n if (!option.disabled) {\n handleSelect(option.value)\n }\n }}\n onKeyDown={(e) => {\n if (!option.disabled && (e.key === 'Enter' || e.key === ' ')) {\n e.preventDefault()\n handleSelect(option.value)\n }\n }}\n onMouseEnter={() => {\n if (!option.disabled) {\n setHighlightedIndex(index)\n }\n }}\n >\n {option.icon && (\n <span className=\"flex h-ico-sm w-ico-sm items-center justify-center shrink-0\">\n <IconProvider size={resolvedIconSize}>\n {normalizeIcon(option.icon)}\n </IconProvider>\n </span>\n )}\n <span className=\"flex flex-1 flex-col\">\n {renderOption ? (\n renderOption(option, selected)\n ) : (\n <>\n <span>{option.label}</span>\n {option.description && (\n <span className=\"text-body-sm text-surface-fg-muted\">\n {option.description}\n </span>\n )}\n </>\n )}\n </span>\n {selected && (\n <Icon icon={IconCheck} size=\"sm\" className=\"shrink-0\" />\n )}\n </li>\n )\n })}\n </ul>\n )}\n </motion.div>\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n </div>\n </PopoverPrimitive.Root>\n )\n },\n)\nCombobox.displayName = 'Combobox'\n\nexport { Combobox }\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"file-upload.d.ts","sourceRoot":"","sources":["../../src/ui/file-upload.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAO9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,MAAM,WAAW,eACf,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,SAAS,CAAC;IAC7D,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,2BAA2B;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,0BAA0B;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,+CAA+C;IAC/C,OAAO,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAA;IAChC,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,wDAAwD;IACxD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,eAAe;IACf,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,mBAAmB;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,sBAAsB;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAuBD,QAAA,MAAM,UAAU,wFAkUf,CAAA;AAGD,OAAO,EAAE,UAAU,EAAE,CAAA"}
1
+ {"version":3,"file":"file-upload.d.ts","sourceRoot":"","sources":["../../src/ui/file-upload.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAO9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,MAAM,WAAW,eACf,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,SAAS,CAAC;IAC7D,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,2BAA2B;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,0BAA0B;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,+CAA+C;IAC/C,OAAO,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAA;IAChC,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,wDAAwD;IACxD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,eAAe;IACf,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,mBAAmB;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,sBAAsB;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAuBD,QAAA,MAAM,UAAU,wFAmUf,CAAA;AAGD,OAAO,EAAE,UAAU,EAAE,CAAA"}