@devalok/shilp-sutra 0.57.0 → 0.59.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 (258) hide show
  1. package/MIGRATION.md +91 -0
  2. package/dist/_chunks/badge-group.js +75 -188
  3. package/dist/_chunks/badge-group.js.map +1 -1
  4. package/dist/_chunks/chat.js +244 -243
  5. package/dist/_chunks/chat.js.map +1 -1
  6. package/dist/_chunks/image-preview.js +71 -70
  7. package/dist/_chunks/image-preview.js.map +1 -1
  8. package/dist/_chunks/motion-preference.js +15 -0
  9. package/dist/_chunks/motion-preference.js.map +1 -0
  10. package/dist/_chunks/motion-provider.js +1 -1
  11. package/dist/_chunks/motion-provider.js.map +1 -1
  12. package/dist/_chunks/popover.js +50 -49
  13. package/dist/_chunks/popover.js.map +1 -1
  14. package/dist/_chunks/primitives-internal.js +29 -29
  15. package/dist/_chunks/primitives-internal.js.map +1 -1
  16. package/dist/_chunks/shared.js +48 -47
  17. package/dist/_chunks/shared.js.map +1 -1
  18. package/dist/_chunks/success.js +34 -34
  19. package/dist/_chunks/tree-view.js +1 -1
  20. package/dist/_chunks/tree-view.js.map +1 -1
  21. package/dist/ai/block-renderer.js +8 -8
  22. package/dist/ai/command-bar.js +65 -65
  23. package/dist/ai/command-bar.js.map +1 -1
  24. package/dist/ai/conversation.js +35 -35
  25. package/dist/ai/conversation.js.map +1 -1
  26. package/dist/ai/index.js +4 -4
  27. package/dist/composed/activity-feed.d.ts.map +1 -1
  28. package/dist/composed/activity-feed.js +108 -107
  29. package/dist/composed/activity-feed.js.map +1 -1
  30. package/dist/composed/command-palette.js +137 -137
  31. package/dist/composed/command-palette.js.map +1 -1
  32. package/dist/composed/content-card.js +1 -1
  33. package/dist/composed/content-card.js.map +1 -1
  34. package/dist/composed/date-picker/index.js +5 -5
  35. package/dist/composed/date-picker/index.js.map +1 -1
  36. package/dist/composed/empty-state.js +4 -4
  37. package/dist/composed/file-preview/image-preview.d.ts.map +1 -1
  38. package/dist/composed/file-preview/shared.d.ts.map +1 -1
  39. package/dist/composed/file-preview/video-preview.d.ts.map +1 -1
  40. package/dist/composed/file-preview.js +151 -150
  41. package/dist/composed/file-preview.js.map +1 -1
  42. package/dist/composed/filter-bar.d.ts.map +1 -1
  43. package/dist/composed/filter-bar.js +53 -52
  44. package/dist/composed/filter-bar.js.map +1 -1
  45. package/dist/composed/form-section.d.ts.map +1 -1
  46. package/dist/composed/form-section.js +38 -37
  47. package/dist/composed/form-section.js.map +1 -1
  48. package/dist/composed/master-detail.d.ts.map +1 -1
  49. package/dist/composed/master-detail.js +1 -1
  50. package/dist/composed/master-detail.js.map +1 -1
  51. package/dist/composed/multi-select-popover.d.ts.map +1 -1
  52. package/dist/composed/multi-select-popover.js +109 -108
  53. package/dist/composed/multi-select-popover.js.map +1 -1
  54. package/dist/composed/rich-chat-input/attachment-strip.d.ts.map +1 -1
  55. package/dist/composed/rich-chat-input/reply-banner.d.ts.map +1 -1
  56. package/dist/composed/rich-chat-input/schedule-send.d.ts.map +1 -1
  57. package/dist/composed/rich-chat-input.d.ts.map +1 -1
  58. package/dist/composed/rich-chat-input.js +467 -466
  59. package/dist/composed/rich-chat-input.js.map +1 -1
  60. package/dist/composed/rich-text-editor.js +3 -3
  61. package/dist/composed/rich-text-editor.js.map +1 -1
  62. package/dist/composed/schedule-view.js +2 -2
  63. package/dist/composed/schedule-view.js.map +1 -1
  64. package/dist/composed/status-badge.d.ts.map +1 -1
  65. package/dist/composed/status-badge.js +29 -28
  66. package/dist/composed/status-badge.js.map +1 -1
  67. package/dist/motion/index.d.ts +1 -0
  68. package/dist/motion/index.d.ts.map +1 -1
  69. package/dist/motion/index.js +2 -15
  70. package/dist/motion/motion-preference.d.ts +36 -0
  71. package/dist/motion/motion-preference.d.ts.map +1 -0
  72. package/dist/motion/motion-provider.d.ts +2 -1
  73. package/dist/motion/motion-provider.d.ts.map +1 -1
  74. package/dist/motion/primitives-index.js +103 -102
  75. package/dist/motion/primitives-index.js.map +1 -1
  76. package/dist/motion/primitives.d.ts.map +1 -1
  77. package/dist/shell/bottom-navbar.js +19 -19
  78. package/dist/shell/bottom-navbar.js.map +1 -1
  79. package/dist/shell/index.d.ts +1 -1
  80. package/dist/shell/index.d.ts.map +1 -1
  81. package/dist/shell/notification-center.d.ts +17 -0
  82. package/dist/shell/notification-center.d.ts.map +1 -1
  83. package/dist/shell/notification-center.js +109 -104
  84. package/dist/shell/notification-center.js.map +1 -1
  85. package/dist/shell/notification-preferences.js +1 -1
  86. package/dist/shell/notification-preferences.js.map +1 -1
  87. package/dist/shell/top-bar.js +1 -1
  88. package/dist/shell/top-bar.js.map +1 -1
  89. package/dist/tokens/index.css +1 -0
  90. package/dist/tokens/palettes.css +292 -0
  91. package/dist/tokens/semantic.css +72 -8
  92. package/dist/tokens/shilp-sutra.css +1 -0
  93. package/dist/tokens/utilities.css +10 -7
  94. package/dist/ui/accordion.d.ts.map +1 -1
  95. package/dist/ui/accordion.js +27 -26
  96. package/dist/ui/accordion.js.map +1 -1
  97. package/dist/ui/alert-dialog.d.ts.map +1 -1
  98. package/dist/ui/alert-dialog.js +60 -59
  99. package/dist/ui/alert-dialog.js.map +1 -1
  100. package/dist/ui/alert.d.ts.map +1 -1
  101. package/dist/ui/alert.js +55 -113
  102. package/dist/ui/alert.js.map +1 -1
  103. package/dist/ui/autocomplete.js +80 -80
  104. package/dist/ui/autocomplete.js.map +1 -1
  105. package/dist/ui/avatar.d.ts.map +1 -1
  106. package/dist/ui/avatar.js +69 -68
  107. package/dist/ui/avatar.js.map +1 -1
  108. package/dist/ui/badge-indicator.d.ts +4 -8
  109. package/dist/ui/badge-indicator.d.ts.map +1 -1
  110. package/dist/ui/badge-indicator.js +3 -8
  111. package/dist/ui/badge-indicator.js.map +1 -1
  112. package/dist/ui/badge.d.ts +8 -1
  113. package/dist/ui/badge.d.ts.map +1 -1
  114. package/dist/ui/banner.d.ts.map +1 -1
  115. package/dist/ui/banner.js +42 -40
  116. package/dist/ui/banner.js.map +1 -1
  117. package/dist/ui/button-group.d.ts.map +1 -1
  118. package/dist/ui/button-group.js +3 -23
  119. package/dist/ui/button-group.js.map +1 -1
  120. package/dist/ui/button.d.ts +10 -1
  121. package/dist/ui/button.d.ts.map +1 -1
  122. package/dist/ui/button.js +79 -212
  123. package/dist/ui/button.js.map +1 -1
  124. package/dist/ui/card.d.ts.map +1 -1
  125. package/dist/ui/card.js +75 -72
  126. package/dist/ui/card.js.map +1 -1
  127. package/dist/ui/charts/radar-chart.d.ts.map +1 -1
  128. package/dist/ui/charts/radar-chart.js +1 -1
  129. package/dist/ui/charts/radar-chart.js.map +1 -1
  130. package/dist/ui/chat/message-list.d.ts.map +1 -1
  131. package/dist/ui/chat/message.d.ts.map +1 -1
  132. package/dist/ui/chat/typing-indicator.d.ts.map +1 -1
  133. package/dist/ui/code.js +1 -1
  134. package/dist/ui/code.js.map +1 -1
  135. package/dist/ui/color-input.d.ts.map +1 -1
  136. package/dist/ui/color-input.js +151 -150
  137. package/dist/ui/color-input.js.map +1 -1
  138. package/dist/ui/combobox.d.ts +14 -0
  139. package/dist/ui/combobox.d.ts.map +1 -1
  140. package/dist/ui/combobox.js +152 -148
  141. package/dist/ui/combobox.js.map +1 -1
  142. package/dist/ui/context-menu.d.ts.map +1 -1
  143. package/dist/ui/context-menu.js +70 -69
  144. package/dist/ui/context-menu.js.map +1 -1
  145. package/dist/ui/data-table-body.js +2 -2
  146. package/dist/ui/data-table-body.js.map +1 -1
  147. package/dist/ui/data-table-context.js +2 -2
  148. package/dist/ui/data-table-context.js.map +1 -1
  149. package/dist/ui/data-table-header.d.ts.map +1 -1
  150. package/dist/ui/data-table-header.js +41 -40
  151. package/dist/ui/data-table-header.js.map +1 -1
  152. package/dist/ui/data-table-pagination.js +2 -2
  153. package/dist/ui/data-table-pagination.js.map +1 -1
  154. package/dist/ui/dialog.d.ts.map +1 -1
  155. package/dist/ui/dialog.js +61 -60
  156. package/dist/ui/dialog.js.map +1 -1
  157. package/dist/ui/dot.d.ts.map +1 -1
  158. package/dist/ui/dot.js +10 -41
  159. package/dist/ui/dot.js.map +1 -1
  160. package/dist/ui/dropdown-menu.d.ts.map +1 -1
  161. package/dist/ui/dropdown-menu.js +79 -78
  162. package/dist/ui/dropdown-menu.js.map +1 -1
  163. package/dist/ui/file-upload.d.ts.map +1 -1
  164. package/dist/ui/file-upload.js +116 -115
  165. package/dist/ui/file-upload.js.map +1 -1
  166. package/dist/ui/form.d.ts.map +1 -1
  167. package/dist/ui/form.js +27 -26
  168. package/dist/ui/form.js.map +1 -1
  169. package/dist/ui/hover-card.d.ts.map +1 -1
  170. package/dist/ui/hover-card.js +26 -25
  171. package/dist/ui/hover-card.js.map +1 -1
  172. package/dist/ui/icon.js +7 -7
  173. package/dist/ui/index.d.ts +2 -2
  174. package/dist/ui/index.d.ts.map +1 -1
  175. package/dist/ui/index.js +3 -3
  176. package/dist/ui/index.js.map +1 -1
  177. package/dist/ui/input.js +1 -1
  178. package/dist/ui/input.js.map +1 -1
  179. package/dist/ui/menubar.d.ts.map +1 -1
  180. package/dist/ui/menubar.js +73 -72
  181. package/dist/ui/menubar.js.map +1 -1
  182. package/dist/ui/navigation-menu.d.ts.map +1 -1
  183. package/dist/ui/navigation-menu.js +80 -79
  184. package/dist/ui/navigation-menu.js.map +1 -1
  185. package/dist/ui/popover.d.ts.map +1 -1
  186. package/dist/ui/progress.d.ts.map +1 -1
  187. package/dist/ui/progress.js +72 -68
  188. package/dist/ui/progress.js.map +1 -1
  189. package/dist/ui/radio.d.ts.map +1 -1
  190. package/dist/ui/radio.js +32 -31
  191. package/dist/ui/radio.js.map +1 -1
  192. package/dist/ui/search-input.d.ts.map +1 -1
  193. package/dist/ui/search-input.js +28 -27
  194. package/dist/ui/search-input.js.map +1 -1
  195. package/dist/ui/select.d.ts.map +1 -1
  196. package/dist/ui/select.js +64 -63
  197. package/dist/ui/select.js.map +1 -1
  198. package/dist/ui/sidebar.d.ts.map +1 -1
  199. package/dist/ui/sidebar.js +4 -4
  200. package/dist/ui/sidebar.js.map +1 -1
  201. package/dist/ui/slider.d.ts +63 -9
  202. package/dist/ui/slider.d.ts.map +1 -1
  203. package/dist/ui/slider.js +74 -32
  204. package/dist/ui/slider.js.map +1 -1
  205. package/dist/ui/split-button.d.ts +8 -2
  206. package/dist/ui/split-button.d.ts.map +1 -1
  207. package/dist/ui/split-button.js +49 -95
  208. package/dist/ui/split-button.js.map +1 -1
  209. package/dist/ui/stat-card.d.ts.map +1 -1
  210. package/dist/ui/stat-card.js +89 -88
  211. package/dist/ui/stat-card.js.map +1 -1
  212. package/dist/ui/stat-flash.js +16 -16
  213. package/dist/ui/stepper.d.ts.map +1 -1
  214. package/dist/ui/stepper.js +63 -62
  215. package/dist/ui/stepper.js.map +1 -1
  216. package/dist/ui/table.js +3 -3
  217. package/dist/ui/table.js.map +1 -1
  218. package/dist/ui/tabs.d.ts.map +1 -1
  219. package/dist/ui/tabs.js +67 -66
  220. package/dist/ui/tabs.js.map +1 -1
  221. package/dist/ui/textarea.js +1 -1
  222. package/dist/ui/textarea.js.map +1 -1
  223. package/dist/ui/toast.d.ts.map +1 -1
  224. package/dist/ui/toast.js +195 -194
  225. package/dist/ui/toast.js.map +1 -1
  226. package/dist/ui/toggle.d.ts.map +1 -1
  227. package/dist/ui/toggle.js +24 -22
  228. package/dist/ui/toggle.js.map +1 -1
  229. package/dist/ui/tooltip.d.ts.map +1 -1
  230. package/dist/ui/tooltip.js +37 -36
  231. package/dist/ui/tooltip.js.map +1 -1
  232. package/dist/ui/tree-view/tree-item.d.ts.map +1 -1
  233. package/docs/recipes/customize-brand.md +58 -0
  234. package/docs/recipes/install-astro.md +1 -1
  235. package/docs/recipes/install-next-app-router.md +1 -1
  236. package/docs/recipes/install-next-pages.md +22 -1
  237. package/docs/recipes/install-remix.md +1 -1
  238. package/docs/recipes/install-tanstack-start.md +1 -1
  239. package/docs/recipes/install-vite.md +2 -1
  240. package/docs/recipes/server-components.md +7 -4
  241. package/docs/recipes/troubleshoot.md +1 -0
  242. package/llms.txt +1 -1
  243. package/mcp-manifest.json +9 -4
  244. package/package.json +3 -2
  245. package/skill/SKILL.md +1 -1
  246. package/skill/references/components.md +1 -1
  247. package/skill/references/customize-brand.md +58 -0
  248. package/skill/references/server-components.md +7 -4
  249. package/skill/references/setup-astro.md +1 -1
  250. package/skill/references/setup-next-app-router.md +1 -1
  251. package/skill/references/setup-next-pages.md +22 -1
  252. package/skill/references/setup-remix.md +1 -1
  253. package/skill/references/setup-tanstack-start.md +1 -1
  254. package/skill/references/setup-vite.md +2 -1
  255. package/skill/references/troubleshoot.md +1 -0
  256. package/dist/motion/check-motion-provider.d.ts +0 -2
  257. package/dist/motion/check-motion-provider.d.ts.map +0 -1
  258. package/dist/motion/index.js.map +0 -1
@@ -1,23 +1,24 @@
1
1
  "use client";
2
- import { IconProvider as e } from "./icon-context.js";
3
- import { springs as t, tweens as n } from "./lib/motion.js";
4
- import { cn as r } from "./lib/utils.js";
5
- import { Icon as i } from "./icon.js";
6
- import { useFormField as a } from "./form.js";
7
- import { resolveFieldState as o } from "../_chunks/field-state.js";
8
- import { normalizeIcon as s } from "../_chunks/normalize-icon.js";
9
- import { Content2 as c, Portal as ee, Root2 as te, Trigger as ne } from "../_chunks/primitives/react-popover.js";
10
- import * as l from "react";
11
- import { Fragment as u, jsx as d, jsxs as f } from "react/jsx-runtime";
12
- import { IconCheck as p, IconChevronDown as m, IconSearch as h, IconX as re } from "@tabler/icons-react";
13
- import { motion as ie } from "framer-motion";
2
+ import { springs as e, tweens as t } from "./lib/motion.js";
3
+ import { MotionPreference as n } from "../_chunks/motion-preference.js";
4
+ import { IconProvider as r } from "./icon-context.js";
5
+ import { cn as i } from "./lib/utils.js";
6
+ import { Icon as a } from "./icon.js";
7
+ import { useFormField as ee } from "./form.js";
8
+ import { resolveFieldState as te } from "../_chunks/field-state.js";
9
+ import { normalizeIcon as ne } from "../_chunks/normalize-icon.js";
10
+ import { Content2 as o, Portal as s, Root2 as re, Trigger as ie } from "../_chunks/primitives/react-popover.js";
11
+ import * as c from "react";
12
+ import { Fragment as ae, jsx as l, jsxs as u } from "react/jsx-runtime";
13
+ import { IconCheck as d, IconChevronDown as f, IconSearch as p, IconX as m } from "@tabler/icons-react";
14
+ import { motion as h } from "framer-motion";
14
15
  import { cva as g } from "class-variance-authority";
15
16
  //#region src/ui/combobox.tsx
16
- var ae = {
17
+ var _ = {
17
18
  error: "border-error-7",
18
19
  warning: "border-warning-7",
19
20
  success: "border-success-7"
20
- }, _ = g([
21
+ }, v = g([
21
22
  "flex w-full items-center justify-between whitespace-nowrap rounded-control",
22
23
  "border border-surface-border-interactive bg-surface-panel-hover",
23
24
  "transition-colors duration-fast-01 ease-productive-standard",
@@ -31,122 +32,125 @@ var ae = {
31
32
  lg: "h-ds-lg text-body-md px-ds-05"
32
33
  } },
33
34
  defaultVariants: { size: "md" }
34
- }), v = {
35
+ }), oe = {
36
+ neutral: "bg-surface-panel-active text-surface-fg",
37
+ accent: "bg-accent-4 text-accent-11"
38
+ }, se = {
35
39
  xs: "xs",
36
40
  sm: "sm",
37
41
  md: "sm",
38
42
  lg: "md"
39
- }, y = {
43
+ }, ce = {
40
44
  xs: "px-ds-02 py-0 text-body-xs",
41
45
  sm: "px-ds-02 py-0 text-body-xs",
42
46
  md: "px-ds-03 py-[1px] text-body-sm",
43
47
  lg: "px-ds-03 py-[2px] text-body-sm"
44
- }, b = {
48
+ }, le = {
45
49
  xs: "text-body-xs",
46
50
  sm: "text-body-xs",
47
51
  md: "text-body-sm",
48
52
  lg: "text-body-sm"
49
- }, x = 2, S = 36, C = l.forwardRef(({ options: g, 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] = l.useState(!1), [R, z] = l.useState(""), [B, V] = l.useState(-1), H = l.useRef(null), U = l.useRef(null), W = l.useId(), G = l.useId(), K = l.useMemo(() => C == null ? [] : Array.isArray(C) ? C : [C], [C]), q = l.useMemo(() => R ? g.filter((e) => e.label.toLowerCase().includes(R.toLowerCase())) : g, [g, R]), de = l.useCallback((e) => K.includes(e), [K]), J = l.useCallback((e) => {
51
- E ? w(K.includes(e) ? K.filter((t) => t !== e) : [...K, e]) : (w(e), L(!1));
53
+ }, y = 2, ue = 36, b = c.forwardRef(({ options: g, value: b, onValueChange: x, placeholder: S = "Select...", searchPlaceholder: de = "Search...", emptyMessage: fe = "No results found", multiple: C = !1, disabled: w = !1, className: pe, triggerClassName: me, maxVisible: T = 6, renderOption: E, accessibleLabel: D, id: O, size: k = "md", state: A, pillTone: j = "neutral", ...M }, N) => {
54
+ let P = k ?? "md", [F, I] = c.useState(!1), [L, R] = c.useState(""), [z, B] = c.useState(-1), V = c.useRef(null), H = c.useRef(null), U = c.useId(), W = c.useId(), G = c.useMemo(() => b == null ? [] : Array.isArray(b) ? b : [b], [b]), K = c.useMemo(() => L ? g.filter((e) => e.label.toLowerCase().includes(L.toLowerCase())) : g, [g, L]), he = c.useCallback((e) => G.includes(e), [G]), q = c.useCallback((e) => {
55
+ C ? x(G.includes(e) ? G.filter((t) => t !== e) : [...G, e]) : (x(e), I(!1));
52
56
  }, [
53
- E,
54
- K,
55
- w
56
- ]), fe = l.useCallback((e, t) => {
57
- e.stopPropagation(), e.preventDefault(), w(K.filter((e) => e !== t));
58
- }, [K, w]), Y = l.useCallback((e) => {
59
- D || (L(e), e || (z(""), V(-1)));
60
- }, [D]);
61
- l.useEffect(() => {
62
- if (I) {
57
+ C,
58
+ G,
59
+ x
60
+ ]), ge = c.useCallback((e, t) => {
61
+ e.stopPropagation(), e.preventDefault(), x(G.filter((e) => e !== t));
62
+ }, [G, x]), J = c.useCallback((e) => {
63
+ w || (I(e), e || (R(""), B(-1)));
64
+ }, [w]);
65
+ c.useEffect(() => {
66
+ if (F) {
63
67
  let e = setTimeout(() => {
64
- H.current?.focus();
68
+ V.current?.focus();
65
69
  }, 0);
66
70
  return () => clearTimeout(e);
67
71
  }
68
- }, [I]);
69
- let X = l.useCallback((e, t) => {
70
- let n = q.length;
72
+ }, [F]);
73
+ let Y = c.useCallback((e, t) => {
74
+ let n = K.length;
71
75
  if (n === 0) return -1;
72
76
  let r = e + t;
73
77
  for (; r >= 0 && r < n;) {
74
- if (!q[r].disabled) return r;
78
+ if (!K[r].disabled) return r;
75
79
  r += t;
76
80
  }
77
81
  return e;
78
- }, [q]), pe = l.useCallback((e) => {
82
+ }, [K]), _e = c.useCallback((e) => {
79
83
  switch (e.key) {
80
84
  case "ArrowDown": {
81
85
  e.preventDefault();
82
- let t = X(B, 1);
83
- V(t);
86
+ let t = Y(z, 1);
87
+ B(t);
84
88
  break;
85
89
  }
86
90
  case "ArrowUp": {
87
91
  e.preventDefault();
88
- let t = X(B, -1);
89
- V(t);
92
+ let t = Y(z, -1);
93
+ B(t);
90
94
  break;
91
95
  }
92
96
  case "Home": {
93
97
  e.preventDefault();
94
- let t = q.findIndex((e) => !e.disabled);
95
- V(t);
98
+ let t = K.findIndex((e) => !e.disabled);
99
+ B(t);
96
100
  break;
97
101
  }
98
102
  case "End": {
99
103
  e.preventDefault();
100
104
  let t = -1;
101
- for (let e = q.length - 1; e >= 0; e--) if (!q[e].disabled) {
105
+ for (let e = K.length - 1; e >= 0; e--) if (!K[e].disabled) {
102
106
  t = e;
103
107
  break;
104
108
  }
105
- V(t);
109
+ B(t);
106
110
  break;
107
111
  }
108
112
  case "Enter":
109
- e.preventDefault(), B >= 0 && B < q.length && !q[B].disabled && J(q[B].value);
113
+ e.preventDefault(), z >= 0 && z < K.length && !K[z].disabled && q(K[z].value);
110
114
  break;
111
115
  case "Escape":
112
- e.preventDefault(), L(!1), z(""), V(-1);
116
+ e.preventDefault(), I(!1), R(""), B(-1);
113
117
  break;
114
118
  }
115
119
  }, [
116
- B,
117
- q,
118
- X,
119
- J
120
+ z,
121
+ K,
122
+ Y,
123
+ q
120
124
  ]);
121
- l.useEffect(() => {
122
- if (B >= 0 && U.current) {
123
- let e = U.current.children[B];
125
+ c.useEffect(() => {
126
+ if (z >= 0 && H.current) {
127
+ let e = H.current.children[z];
124
128
  e && e.scrollIntoView?.({ block: "nearest" });
125
129
  }
126
- }, [B]);
127
- let me = l.useCallback(() => K.length === 0 ? null : g.find((e) => e.value === K[0])?.label ?? null, [K, g]), 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__ */ f("span", {
130
+ }, [z]);
131
+ let ve = c.useCallback(() => G.length === 0 ? null : g.find((e) => e.value === G[0])?.label ?? null, [G, g]), X = se[P], Z = ce[P], ye = le[P], be = () => {
132
+ if (C && G.length > 0) {
133
+ let e = G.slice(0, y), t = G.length - y;
134
+ return /* @__PURE__ */ u("span", {
131
135
  className: "flex flex-1 flex-wrap items-center gap-ds-02 overflow-hidden",
132
136
  children: [e.map((e) => {
133
137
  let t = g.find((t) => t.value === e);
134
- return t ? /* @__PURE__ */ f("span", {
135
- className: r("inline-flex items-center gap-ds-01 rounded-control-inner bg-accent-2", he),
136
- children: [t.label, /* @__PURE__ */ d("button", {
138
+ return t ? /* @__PURE__ */ u("span", {
139
+ className: i("inline-flex items-center gap-ds-01 rounded-control-inner", oe[j], Z),
140
+ children: [t.label, /* @__PURE__ */ l("button", {
137
141
  type: "button",
138
142
  className: "inline-flex items-center justify-center rounded-pill outline-hidden hover:bg-surface-panel-hover transition-colors duration-fast-01 ease-productive-standard",
139
- onClick: (t) => fe(t, e),
143
+ onClick: (t) => ge(t, e),
140
144
  "aria-label": `Remove ${t.label}`,
141
145
  tabIndex: -1,
142
- children: /* @__PURE__ */ d(i, {
143
- icon: re,
144
- size: Z
146
+ children: /* @__PURE__ */ l(a, {
147
+ icon: m,
148
+ size: X
145
149
  })
146
150
  })]
147
151
  }, e) : null;
148
- }), t > 0 && /* @__PURE__ */ f("span", {
149
- className: r("text-surface-fg-muted", ge),
152
+ }), t > 0 && /* @__PURE__ */ u("span", {
153
+ className: i("text-surface-fg-muted", ye),
150
154
  children: [
151
155
  "+",
152
156
  t,
@@ -155,60 +159,60 @@ var ae = {
155
159
  })]
156
160
  });
157
161
  }
158
- if (!E && K.length === 1) {
159
- let e = me();
160
- if (e) return /* @__PURE__ */ d("span", {
162
+ if (!C && G.length === 1) {
163
+ let e = ve();
164
+ if (e) return /* @__PURE__ */ l("span", {
161
165
  className: "min-w-0 flex-1 truncate text-left",
162
166
  children: e
163
167
  });
164
168
  }
165
- return /* @__PURE__ */ d("span", {
169
+ return /* @__PURE__ */ l("span", {
166
170
  className: "min-w-0 flex-1 truncate text-left text-surface-fg-muted",
167
- children: T
171
+ children: S
168
172
  });
169
- }, Q = a(), $ = o(M, Q.state), ve = $ === "error", ye = Q.helperTextId, be = Q.required;
170
- return /* @__PURE__ */ d(te, {
171
- open: I,
172
- onOpenChange: Y,
173
- children: /* @__PURE__ */ f("div", {
174
- className: r("relative", ce),
175
- ...N,
176
- children: [/* @__PURE__ */ d(ne, {
173
+ }, Q = ee(), $ = te(A, Q.state), xe = $ === "error", Se = Q.helperTextId, Ce = Q.required;
174
+ return /* @__PURE__ */ l(n, { children: /* @__PURE__ */ l(re, {
175
+ open: F,
176
+ onOpenChange: J,
177
+ children: /* @__PURE__ */ u("div", {
178
+ className: i("relative", pe),
179
+ ...M,
180
+ children: [/* @__PURE__ */ l(ie, {
177
181
  asChild: !0,
178
- disabled: D,
179
- children: /* @__PURE__ */ f("div", {
180
- ref: P,
182
+ disabled: w,
183
+ children: /* @__PURE__ */ u("div", {
184
+ ref: N,
181
185
  role: "combobox",
182
- tabIndex: D ? -1 : 0,
183
- "data-disabled": D || void 0,
184
- id: A,
185
- "aria-expanded": I,
186
- "aria-controls": G,
186
+ tabIndex: w ? -1 : 0,
187
+ "data-disabled": w || void 0,
188
+ id: O,
189
+ "aria-expanded": F,
190
+ "aria-controls": W,
187
191
  "aria-haspopup": "listbox",
188
- "aria-disabled": D || void 0,
189
- "aria-labelledby": k ? void 0 : Q.labelId,
190
- "aria-label": k ?? (Q.labelId ? void 0 : T),
191
- "aria-invalid": ve || void 0,
192
- "aria-describedby": ye,
193
- "aria-required": be || void 0,
192
+ "aria-disabled": w || void 0,
193
+ "aria-labelledby": D ? void 0 : Q.labelId,
194
+ "aria-label": D ?? (Q.labelId ? void 0 : S),
195
+ "aria-invalid": xe || void 0,
196
+ "aria-describedby": Se,
197
+ "aria-required": Ce || void 0,
194
198
  onKeyDown: (e) => {
195
- D || (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") && (e.preventDefault(), Y(!0));
199
+ w || (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") && (e.preventDefault(), J(!0));
196
200
  },
197
- className: r(_({ size: F }), "cursor-pointer", I && "border-accent-7", $ && ae[$], le),
198
- children: [_e(), /* @__PURE__ */ d(i, {
199
- icon: m,
200
- size: Z,
201
- className: r("ml-ds-02 shrink-0 opacity-50 transition-transform duration-fast-01 ease-productive-standard", I && "rotate-180")
201
+ className: i(v({ size: P }), "cursor-pointer", F && "border-accent-7", $ && _[$], me),
202
+ children: [be(), /* @__PURE__ */ l(a, {
203
+ icon: f,
204
+ size: X,
205
+ className: i("ml-ds-02 shrink-0 opacity-50 transition-transform duration-fast-01 ease-productive-standard", F && "rotate-180")
202
206
  })]
203
207
  })
204
- }), /* @__PURE__ */ d(ee, { children: /* @__PURE__ */ d(c, {
208
+ }), /* @__PURE__ */ l(s, { children: /* @__PURE__ */ l(o, {
205
209
  asChild: !0,
206
210
  sideOffset: 4,
207
211
  align: "start",
208
212
  onOpenAutoFocus: (e) => {
209
- e.preventDefault(), H.current?.focus();
213
+ e.preventDefault(), V.current?.focus();
210
214
  },
211
- children: /* @__PURE__ */ f(ie.div, {
215
+ children: /* @__PURE__ */ u(h.div, {
212
216
  initial: {
213
217
  opacity: 0,
214
218
  scale: .95
@@ -218,87 +222,87 @@ var ae = {
218
222
  scale: 1
219
223
  },
220
224
  transition: {
221
- ...t.snappy,
222
- opacity: n.fade
225
+ ...e.snappy,
226
+ opacity: t.fade
223
227
  },
224
- className: r("z-popover w-[var(--radix-popover-trigger-width)] overflow-hidden rounded-overlay bg-surface-overlay shadow-floating"),
225
- children: [/* @__PURE__ */ f("div", {
228
+ className: i("z-popover w-[var(--radix-popover-trigger-width)] overflow-hidden rounded-overlay bg-surface-overlay shadow-floating"),
229
+ children: [/* @__PURE__ */ u("div", {
226
230
  className: "flex items-center gap-ds-02 border-b border-surface-border px-ds-04",
227
- children: [/* @__PURE__ */ d(i, {
228
- icon: h,
231
+ children: [/* @__PURE__ */ l(a, {
232
+ icon: p,
229
233
  size: "sm",
230
234
  className: "shrink-0 text-surface-fg-subtle"
231
- }), /* @__PURE__ */ d("input", {
232
- ref: H,
235
+ }), /* @__PURE__ */ l("input", {
236
+ ref: V,
233
237
  type: "text",
234
238
  className: "flex-1 bg-transparent py-ds-03 text-body-md outline-hidden placeholder:text-surface-fg-muted",
235
- placeholder: oe,
236
- value: R,
239
+ placeholder: de,
240
+ value: L,
237
241
  onChange: (e) => {
238
- z(e.target.value), V(-1);
242
+ R(e.target.value), B(-1);
239
243
  },
240
- onKeyDown: pe,
244
+ onKeyDown: _e,
241
245
  "aria-autocomplete": "list",
242
- "aria-controls": G,
243
- "aria-activedescendant": B >= 0 ? `${W}-option-${B}` : void 0,
246
+ "aria-controls": W,
247
+ "aria-activedescendant": z >= 0 ? `${U}-option-${z}` : void 0,
244
248
  "aria-label": "Search options"
245
249
  })]
246
- }), q.length === 0 ? /* @__PURE__ */ d("div", {
250
+ }), K.length === 0 ? /* @__PURE__ */ l("div", {
247
251
  className: "px-ds-04 py-ds-05 text-center text-body-md text-surface-fg-subtle",
248
- children: se
249
- }) : /* @__PURE__ */ d("ul", {
250
- ref: U,
251
- id: G,
252
+ children: fe
253
+ }) : /* @__PURE__ */ l("ul", {
254
+ ref: H,
255
+ id: W,
252
256
  role: "listbox",
253
- "aria-multiselectable": E || void 0,
257
+ "aria-multiselectable": C || void 0,
254
258
  className: "overflow-auto p-ds-02",
255
- style: { maxHeight: `${ue * S}px` },
256
- children: q.map((t, n) => {
257
- let a = de(t.value);
258
- return /* @__PURE__ */ f("li", {
259
- id: `${W}-option-${n}`,
259
+ style: { maxHeight: `${T * ue}px` },
260
+ children: K.map((e, t) => {
261
+ let n = he(e.value);
262
+ return /* @__PURE__ */ u("li", {
263
+ id: `${U}-option-${t}`,
260
264
  role: "option",
261
- "aria-selected": a,
262
- "aria-disabled": t.disabled || void 0,
263
- className: r("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 === n && "bg-accent-2", a && "text-accent-11", t.disabled && "pointer-events-none opacity-action-disabled"),
265
+ "aria-selected": n,
266
+ "aria-disabled": e.disabled || void 0,
267
+ className: i("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", z === t && "bg-accent-4", n && "text-accent-11", e.disabled && "pointer-events-none opacity-action-disabled"),
264
268
  onClick: () => {
265
- t.disabled || J(t.value);
269
+ e.disabled || q(e.value);
266
270
  },
267
- onKeyDown: (e) => {
268
- !t.disabled && (e.key === "Enter" || e.key === " ") && (e.preventDefault(), J(t.value));
271
+ onKeyDown: (t) => {
272
+ !e.disabled && (t.key === "Enter" || t.key === " ") && (t.preventDefault(), q(e.value));
269
273
  },
270
274
  onMouseEnter: () => {
271
- t.disabled || V(n);
275
+ e.disabled || B(t);
272
276
  },
273
277
  children: [
274
- t.icon && /* @__PURE__ */ d("span", {
278
+ e.icon && /* @__PURE__ */ l("span", {
275
279
  className: "flex h-ico-sm w-ico-sm items-center justify-center shrink-0",
276
- children: /* @__PURE__ */ d(e, {
277
- size: Z,
278
- children: s(t.icon)
280
+ children: /* @__PURE__ */ l(r, {
281
+ size: X,
282
+ children: ne(e.icon)
279
283
  })
280
284
  }),
281
- /* @__PURE__ */ d("span", {
285
+ /* @__PURE__ */ l("span", {
282
286
  className: "flex flex-1 flex-col",
283
- children: O ? O(t, a) : /* @__PURE__ */ f(u, { children: [/* @__PURE__ */ d("span", { children: t.label }), t.description && /* @__PURE__ */ d("span", {
287
+ children: E ? E(e, n) : /* @__PURE__ */ u(ae, { children: [/* @__PURE__ */ l("span", { children: e.label }), e.description && /* @__PURE__ */ l("span", {
284
288
  className: "text-body-sm text-surface-fg-muted",
285
- children: t.description
289
+ children: e.description
286
290
  })] })
287
291
  }),
288
- a && /* @__PURE__ */ d(i, {
289
- icon: p,
292
+ n && /* @__PURE__ */ l(a, {
293
+ icon: d,
290
294
  size: "sm",
291
295
  className: "shrink-0"
292
296
  })
293
297
  ]
294
- }, t.value);
298
+ }, e.value);
295
299
  })
296
300
  })]
297
301
  })
298
302
  }) })]
299
303
  })
300
- });
304
+ }) });
301
305
  });
302
- C.displayName = "Combobox";
306
+ b.displayName = "Combobox";
303
307
  //#endregion
304
- export { C as Combobox, _ as comboboxTriggerVariants };
308
+ export { b as Combobox, v 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-interactive bg-surface-panel-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-panel-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-muted\">\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-muted\"\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
+ {"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 { MotionPreference } from '../motion/motion-preference'\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-interactive bg-surface-panel-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/** Colour treatment for a selected pill. See `ComboboxProps.pillTone`. */\nexport type ComboboxPillTone = 'neutral' | 'accent'\n\n// accent-2 was the previous fixed value and is not offered: in LIGHT it is the\n// same lightness as the trigger behind it (1.006:1), so the pill vanished\n// entirely, and in dark it sits below the panel. Both options below clear their\n// ground in both themes.\nconst PILL_TONES: Record<ComboboxPillTone, string> = {\n neutral: 'bg-surface-panel-active text-surface-fg',\n accent: 'bg-accent-4 text-accent-11',\n}\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 * How a selected pill is coloured.\n *\n * - `neutral` (default) — grey. A pill here is a removable token, not a\n * selection, so the brand colour stays reserved for things that ARE\n * selected. 1.12:1 light / 1.16:1 dark against the trigger.\n * - `accent` — brand-tinted, for pickers where the tokens should feel like\n * part of the brand. 1.30:1 light / 1.05:1 dark.\n *\n * @default 'neutral'\n */\n pillTone?: ComboboxPillTone\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 pillTone = 'neutral',\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', PILL_TONES[pillTone], 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-panel-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-muted\">\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 <MotionPreference>\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-muted\"\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-4',\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 </MotionPreference>\n )\n },\n)\nCombobox.displayName = 'Combobox'\n\nexport { Combobox }\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"context-menu.d.ts","sourceRoot":"","sources":["../../src/ui/context-menu.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,oBAAoB,MAAM,gCAAgC,CAAA;AAGtE,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAW9B,QAAA,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,wBAAwB,CAAC,OAAO,oBAAoB,CAAC,IAAI,CAAC,CAmB3F,CAAA;AAGD,QAAA,MAAM,kBAAkB,sHAA+B,CAAA;AAEvD,QAAA,MAAM,gBAAgB,mHAA6B,CAAA;AAEnD,QAAA,MAAM,iBAAiB,uDAA8B,CAAA;AAErD,QAAA,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,wBAAwB,CAAC,OAAO,oBAAoB,CAAC,GAAG,CAAC,CAuB7F,CAAA;AAGD,QAAA,MAAM,qBAAqB,wHAAkC,CAAA;AAE7D,QAAA,MAAM,qBAAqB;YAGf,OAAO;wCAejB,CAAA;AAGF,QAAA,MAAM,qBAAqB,2KA+BzB,CAAA;AAGF,QAAA,MAAM,kBAAkB,wKAiCtB,CAAA;AAGF,QAAA,MAAM,eAAe;YAGT,OAAO;wCAYjB,CAAA;AAGF,QAAA,MAAM,uBAAuB,6KAoB3B,CAAA;AAIF,QAAA,MAAM,oBAAoB,0KAmBxB,CAAA;AAGF,QAAA,MAAM,gBAAgB;YAGV,OAAO;wCAYjB,CAAA;AAGF,QAAA,MAAM,oBAAoB,0KASxB,CAAA;AAGF,QAAA,MAAM,mBAAmB;8BAGtB,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC;;CAUvC,CAAA;AAGD,MAAM,MAAM,uBAAuB,GAAG,KAAK,CAAC,wBAAwB,CAAC,OAAO,oBAAoB,CAAC,OAAO,CAAC,CAAA;AACzG,MAAM,MAAM,oBAAoB,GAAG,KAAK,CAAC,wBAAwB,CAAC,OAAO,oBAAoB,CAAC,IAAI,CAAC,CAAA;AAEnG,OAAO,EACL,WAAW,EACX,uBAAuB,EACvB,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACnB,cAAc,EACd,qBAAqB,EACrB,qBAAqB,EACrB,kBAAkB,GACnB,CAAA"}
1
+ {"version":3,"file":"context-menu.d.ts","sourceRoot":"","sources":["../../src/ui/context-menu.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,oBAAoB,MAAM,gCAAgC,CAAA;AAGtE,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAY9B,QAAA,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,wBAAwB,CAAC,OAAO,oBAAoB,CAAC,IAAI,CAAC,CAmB3F,CAAA;AAGD,QAAA,MAAM,kBAAkB,sHAA+B,CAAA;AAEvD,QAAA,MAAM,gBAAgB,mHAA6B,CAAA;AAEnD,QAAA,MAAM,iBAAiB,uDAA8B,CAAA;AAErD,QAAA,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,wBAAwB,CAAC,OAAO,oBAAoB,CAAC,GAAG,CAAC,CAuB7F,CAAA;AAGD,QAAA,MAAM,qBAAqB,wHAAkC,CAAA;AAE7D,QAAA,MAAM,qBAAqB;YAGf,OAAO;wCAejB,CAAA;AAGF,QAAA,MAAM,qBAAqB,2KAiCzB,CAAA;AAGF,QAAA,MAAM,kBAAkB,wKAmCtB,CAAA;AAGF,QAAA,MAAM,eAAe;YAGT,OAAO;wCAYjB,CAAA;AAGF,QAAA,MAAM,uBAAuB,6KAoB3B,CAAA;AAIF,QAAA,MAAM,oBAAoB,0KAmBxB,CAAA;AAGF,QAAA,MAAM,gBAAgB;YAGV,OAAO;wCAYjB,CAAA;AAGF,QAAA,MAAM,oBAAoB,0KASxB,CAAA;AAGF,QAAA,MAAM,mBAAmB;8BAGtB,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC;;CAUvC,CAAA;AAGD,MAAM,MAAM,uBAAuB,GAAG,KAAK,CAAC,wBAAwB,CAAC,OAAO,oBAAoB,CAAC,OAAO,CAAC,CAAA;AACzG,MAAM,MAAM,oBAAoB,GAAG,KAAK,CAAC,wBAAwB,CAAC,OAAO,oBAAoB,CAAC,IAAI,CAAC,CAAA;AAEnG,OAAO,EACL,WAAW,EACX,uBAAuB,EACvB,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACnB,cAAc,EACd,qBAAqB,EACrB,qBAAqB,EACrB,kBAAkB,GACnB,CAAA"}