@spark-ui/components 10.0.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 (296) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/LICENSE.md +21 -0
  3. package/README.md +19 -0
  4. package/dist/DialogTrigger-5SI4dvpK.d.mts +142 -0
  5. package/dist/DialogTrigger-5SI4dvpK.d.ts +142 -0
  6. package/dist/Input-g0LpWuv0.d.mts +17 -0
  7. package/dist/Input-g0LpWuv0.d.ts +17 -0
  8. package/dist/InputGroup-aoaZxCLk.d.mts +28 -0
  9. package/dist/InputGroup-aoaZxCLk.d.ts +28 -0
  10. package/dist/InputTrailingIcon-BBp7sE6D.d.mts +20 -0
  11. package/dist/InputTrailingIcon-ZZx8PoJy.d.ts +20 -0
  12. package/dist/LabelRequiredIndicator-DRnCzHMU.d.mts +19 -0
  13. package/dist/LabelRequiredIndicator-DRnCzHMU.d.ts +19 -0
  14. package/dist/accordion/index.d.mts +85 -0
  15. package/dist/accordion/index.d.ts +85 -0
  16. package/dist/accordion/index.js +461 -0
  17. package/dist/accordion/index.js.map +1 -0
  18. package/dist/accordion/index.mjs +249 -0
  19. package/dist/accordion/index.mjs.map +1 -0
  20. package/dist/alert-dialog/index.d.mts +119 -0
  21. package/dist/alert-dialog/index.d.ts +119 -0
  22. package/dist/alert-dialog/index.js +1451 -0
  23. package/dist/alert-dialog/index.js.map +1 -0
  24. package/dist/alert-dialog/index.mjs +177 -0
  25. package/dist/alert-dialog/index.mjs.map +1 -0
  26. package/dist/badge/index.d.mts +47 -0
  27. package/dist/badge/index.d.ts +47 -0
  28. package/dist/badge/index.js +122 -0
  29. package/dist/badge/index.js.map +1 -0
  30. package/dist/badge/index.mjs +95 -0
  31. package/dist/badge/index.mjs.map +1 -0
  32. package/dist/breadcrumb/index.d.mts +64 -0
  33. package/dist/breadcrumb/index.d.ts +64 -0
  34. package/dist/breadcrumb/index.js +326 -0
  35. package/dist/breadcrumb/index.js.map +1 -0
  36. package/dist/breadcrumb/index.mjs +149 -0
  37. package/dist/breadcrumb/index.mjs.map +1 -0
  38. package/dist/button/index.d.mts +40 -0
  39. package/dist/button/index.d.ts +40 -0
  40. package/dist/button/index.js +877 -0
  41. package/dist/button/index.js.map +1 -0
  42. package/dist/button/index.mjs +10 -0
  43. package/dist/button/index.mjs.map +1 -0
  44. package/dist/carousel/index.d.mts +253 -0
  45. package/dist/carousel/index.d.ts +253 -0
  46. package/dist/carousel/index.js +1678 -0
  47. package/dist/carousel/index.js.map +1 -0
  48. package/dist/carousel/index.mjs +716 -0
  49. package/dist/carousel/index.mjs.map +1 -0
  50. package/dist/checkbox/index.d.mts +120 -0
  51. package/dist/checkbox/index.d.ts +120 -0
  52. package/dist/checkbox/index.js +873 -0
  53. package/dist/checkbox/index.js.map +1 -0
  54. package/dist/checkbox/index.mjs +349 -0
  55. package/dist/checkbox/index.mjs.map +1 -0
  56. package/dist/chip/index.d.mts +97 -0
  57. package/dist/chip/index.d.ts +97 -0
  58. package/dist/chip/index.js +905 -0
  59. package/dist/chip/index.js.map +1 -0
  60. package/dist/chip/index.mjs +793 -0
  61. package/dist/chip/index.mjs.map +1 -0
  62. package/dist/chunk-2KPFQEAA.mjs +52 -0
  63. package/dist/chunk-2KPFQEAA.mjs.map +1 -0
  64. package/dist/chunk-4F5DOL57.mjs +26 -0
  65. package/dist/chunk-4F5DOL57.mjs.map +1 -0
  66. package/dist/chunk-6JOA37TZ.mjs +742 -0
  67. package/dist/chunk-6JOA37TZ.mjs.map +1 -0
  68. package/dist/chunk-7PMPYEHJ.mjs +379 -0
  69. package/dist/chunk-7PMPYEHJ.mjs.map +1 -0
  70. package/dist/chunk-AESXFMCC.mjs +68 -0
  71. package/dist/chunk-AESXFMCC.mjs.map +1 -0
  72. package/dist/chunk-B42LOFIZ.mjs +308 -0
  73. package/dist/chunk-B42LOFIZ.mjs.map +1 -0
  74. package/dist/chunk-FGOZHKBT.mjs +97 -0
  75. package/dist/chunk-FGOZHKBT.mjs.map +1 -0
  76. package/dist/chunk-HLXYG643.mjs +52 -0
  77. package/dist/chunk-HLXYG643.mjs.map +1 -0
  78. package/dist/chunk-JKNBJHD5.mjs +601 -0
  79. package/dist/chunk-JKNBJHD5.mjs.map +1 -0
  80. package/dist/chunk-K7VP7DH3.mjs +66 -0
  81. package/dist/chunk-K7VP7DH3.mjs.map +1 -0
  82. package/dist/chunk-MUNDKRAE.mjs +80 -0
  83. package/dist/chunk-MUNDKRAE.mjs.map +1 -0
  84. package/dist/chunk-NBZKMCHF.mjs +36 -0
  85. package/dist/chunk-NBZKMCHF.mjs.map +1 -0
  86. package/dist/chunk-PZWESKAR.mjs +314 -0
  87. package/dist/chunk-PZWESKAR.mjs.map +1 -0
  88. package/dist/collapsible/index.d.mts +60 -0
  89. package/dist/collapsible/index.d.ts +60 -0
  90. package/dist/collapsible/index.js +140 -0
  91. package/dist/collapsible/index.js.map +1 -0
  92. package/dist/collapsible/index.mjs +8 -0
  93. package/dist/collapsible/index.mjs.map +1 -0
  94. package/dist/combobox/index.d.mts +285 -0
  95. package/dist/combobox/index.d.ts +285 -0
  96. package/dist/combobox/index.js +2920 -0
  97. package/dist/combobox/index.js.map +1 -0
  98. package/dist/combobox/index.mjs +1267 -0
  99. package/dist/combobox/index.mjs.map +1 -0
  100. package/dist/dialog/index.d.mts +33 -0
  101. package/dist/dialog/index.d.ts +33 -0
  102. package/dist/dialog/index.js +1286 -0
  103. package/dist/dialog/index.js.map +1 -0
  104. package/dist/dialog/index.mjs +13 -0
  105. package/dist/dialog/index.mjs.map +1 -0
  106. package/dist/divider/index.d.mts +61 -0
  107. package/dist/divider/index.d.ts +61 -0
  108. package/dist/divider/index.js +223 -0
  109. package/dist/divider/index.js.map +1 -0
  110. package/dist/divider/index.mjs +196 -0
  111. package/dist/divider/index.mjs.map +1 -0
  112. package/dist/drawer/index.d.mts +148 -0
  113. package/dist/drawer/index.d.ts +148 -0
  114. package/dist/drawer/index.js +1266 -0
  115. package/dist/drawer/index.js.map +1 -0
  116. package/dist/drawer/index.mjs +299 -0
  117. package/dist/drawer/index.mjs.map +1 -0
  118. package/dist/dropdown/index.d.mts +233 -0
  119. package/dist/dropdown/index.d.ts +233 -0
  120. package/dist/dropdown/index.js +2402 -0
  121. package/dist/dropdown/index.js.map +1 -0
  122. package/dist/dropdown/index.mjs +741 -0
  123. package/dist/dropdown/index.mjs.map +1 -0
  124. package/dist/form-field/index.d.mts +176 -0
  125. package/dist/form-field/index.d.ts +176 -0
  126. package/dist/form-field/index.js +540 -0
  127. package/dist/form-field/index.js.map +1 -0
  128. package/dist/form-field/index.mjs +13 -0
  129. package/dist/form-field/index.mjs.map +1 -0
  130. package/dist/icon/index.d.mts +28 -0
  131. package/dist/icon/index.d.ts +28 -0
  132. package/dist/icon/index.js +127 -0
  133. package/dist/icon/index.js.map +1 -0
  134. package/dist/icon/index.mjs +9 -0
  135. package/dist/icon/index.mjs.map +1 -0
  136. package/dist/icon-button/index.d.mts +16 -0
  137. package/dist/icon-button/index.d.ts +16 -0
  138. package/dist/icon-button/index.js +921 -0
  139. package/dist/icon-button/index.js.map +1 -0
  140. package/dist/icon-button/index.mjs +11 -0
  141. package/dist/icon-button/index.mjs.map +1 -0
  142. package/dist/input/index.d.mts +78 -0
  143. package/dist/input/index.d.ts +78 -0
  144. package/dist/input/index.js +1119 -0
  145. package/dist/input/index.js.map +1 -0
  146. package/dist/input/index.mjs +16 -0
  147. package/dist/input/index.mjs.map +1 -0
  148. package/dist/kbd/index.d.mts +9 -0
  149. package/dist/kbd/index.d.ts +9 -0
  150. package/dist/kbd/index.js +46 -0
  151. package/dist/kbd/index.js.map +1 -0
  152. package/dist/kbd/index.mjs +19 -0
  153. package/dist/kbd/index.mjs.map +1 -0
  154. package/dist/label/index.d.mts +11 -0
  155. package/dist/label/index.d.ts +11 -0
  156. package/dist/label/index.js +78 -0
  157. package/dist/label/index.js.map +1 -0
  158. package/dist/label/index.mjs +7 -0
  159. package/dist/label/index.mjs.map +1 -0
  160. package/dist/link-box/index.d.mts +34 -0
  161. package/dist/link-box/index.d.ts +34 -0
  162. package/dist/link-box/index.js +92 -0
  163. package/dist/link-box/index.js.map +1 -0
  164. package/dist/link-box/index.mjs +58 -0
  165. package/dist/link-box/index.mjs.map +1 -0
  166. package/dist/pagination/index.d.mts +143 -0
  167. package/dist/pagination/index.d.ts +143 -0
  168. package/dist/pagination/index.js +1303 -0
  169. package/dist/pagination/index.js.map +1 -0
  170. package/dist/pagination/index.mjs +326 -0
  171. package/dist/pagination/index.mjs.map +1 -0
  172. package/dist/popover/index.d.mts +93 -0
  173. package/dist/popover/index.d.ts +93 -0
  174. package/dist/popover/index.js +1280 -0
  175. package/dist/popover/index.js.map +1 -0
  176. package/dist/popover/index.mjs +13 -0
  177. package/dist/popover/index.mjs.map +1 -0
  178. package/dist/portal/index.d.mts +13 -0
  179. package/dist/portal/index.d.ts +13 -0
  180. package/dist/portal/index.js +37 -0
  181. package/dist/portal/index.js.map +1 -0
  182. package/dist/portal/index.mjs +10 -0
  183. package/dist/portal/index.mjs.map +1 -0
  184. package/dist/progress/index.d.mts +48 -0
  185. package/dist/progress/index.d.ts +48 -0
  186. package/dist/progress/index.js +201 -0
  187. package/dist/progress/index.js.map +1 -0
  188. package/dist/progress/index.mjs +174 -0
  189. package/dist/progress/index.mjs.map +1 -0
  190. package/dist/progress-tracker/index.d.mts +81 -0
  191. package/dist/progress-tracker/index.d.ts +81 -0
  192. package/dist/progress-tracker/index.js +834 -0
  193. package/dist/progress-tracker/index.js.map +1 -0
  194. package/dist/progress-tracker/index.mjs +716 -0
  195. package/dist/progress-tracker/index.mjs.map +1 -0
  196. package/dist/radio-group/index.d.mts +100 -0
  197. package/dist/radio-group/index.d.ts +100 -0
  198. package/dist/radio-group/index.js +824 -0
  199. package/dist/radio-group/index.js.map +1 -0
  200. package/dist/radio-group/index.mjs +297 -0
  201. package/dist/radio-group/index.mjs.map +1 -0
  202. package/dist/rating/index.d.mts +78 -0
  203. package/dist/rating/index.d.ts +78 -0
  204. package/dist/rating/index.js +362 -0
  205. package/dist/rating/index.js.map +1 -0
  206. package/dist/rating/index.mjs +247 -0
  207. package/dist/rating/index.mjs.map +1 -0
  208. package/dist/scrolling-list/index.d.mts +105 -0
  209. package/dist/scrolling-list/index.d.ts +105 -0
  210. package/dist/scrolling-list/index.js +1367 -0
  211. package/dist/scrolling-list/index.js.map +1 -0
  212. package/dist/scrolling-list/index.mjs +407 -0
  213. package/dist/scrolling-list/index.mjs.map +1 -0
  214. package/dist/select/index.d.mts +167 -0
  215. package/dist/select/index.d.ts +167 -0
  216. package/dist/select/index.js +991 -0
  217. package/dist/select/index.js.map +1 -0
  218. package/dist/select/index.mjs +470 -0
  219. package/dist/select/index.mjs.map +1 -0
  220. package/dist/skeleton/index.d.mts +67 -0
  221. package/dist/skeleton/index.d.ts +67 -0
  222. package/dist/skeleton/index.js +206 -0
  223. package/dist/skeleton/index.js.map +1 -0
  224. package/dist/skeleton/index.mjs +147 -0
  225. package/dist/skeleton/index.mjs.map +1 -0
  226. package/dist/slider/index.d.mts +97 -0
  227. package/dist/slider/index.d.ts +97 -0
  228. package/dist/slider/index.js +209 -0
  229. package/dist/slider/index.js.map +1 -0
  230. package/dist/slider/index.mjs +182 -0
  231. package/dist/slider/index.mjs.map +1 -0
  232. package/dist/slot/index.d.mts +17 -0
  233. package/dist/slot/index.d.ts +17 -0
  234. package/dist/slot/index.js +51 -0
  235. package/dist/slot/index.js.map +1 -0
  236. package/dist/slot/index.mjs +11 -0
  237. package/dist/slot/index.mjs.map +1 -0
  238. package/dist/snackbar/index.d.mts +158 -0
  239. package/dist/snackbar/index.d.ts +158 -0
  240. package/dist/snackbar/index.js +1693 -0
  241. package/dist/snackbar/index.js.map +1 -0
  242. package/dist/snackbar/index.mjs +733 -0
  243. package/dist/snackbar/index.mjs.map +1 -0
  244. package/dist/spinner/index.d.mts +21 -0
  245. package/dist/spinner/index.d.ts +21 -0
  246. package/dist/spinner/index.js +139 -0
  247. package/dist/spinner/index.js.map +1 -0
  248. package/dist/spinner/index.mjs +9 -0
  249. package/dist/spinner/index.mjs.map +1 -0
  250. package/dist/stepper/index.d.mts +82 -0
  251. package/dist/stepper/index.d.ts +82 -0
  252. package/dist/stepper/index.js +2178 -0
  253. package/dist/stepper/index.js.map +1 -0
  254. package/dist/stepper/index.mjs +229 -0
  255. package/dist/stepper/index.mjs.map +1 -0
  256. package/dist/switch/index.d.mts +64 -0
  257. package/dist/switch/index.d.ts +64 -0
  258. package/dist/switch/index.js +768 -0
  259. package/dist/switch/index.js.map +1 -0
  260. package/dist/switch/index.mjs +245 -0
  261. package/dist/switch/index.mjs.map +1 -0
  262. package/dist/tabs/index.d.mts +103 -0
  263. package/dist/tabs/index.d.ts +103 -0
  264. package/dist/tabs/index.js +1315 -0
  265. package/dist/tabs/index.js.map +1 -0
  266. package/dist/tabs/index.mjs +391 -0
  267. package/dist/tabs/index.mjs.map +1 -0
  268. package/dist/tag/index.d.mts +27 -0
  269. package/dist/tag/index.d.ts +27 -0
  270. package/dist/tag/index.js +269 -0
  271. package/dist/tag/index.js.map +1 -0
  272. package/dist/tag/index.mjs +237 -0
  273. package/dist/tag/index.mjs.map +1 -0
  274. package/dist/text-link/index.d.mts +20 -0
  275. package/dist/text-link/index.d.ts +20 -0
  276. package/dist/text-link/index.js +99 -0
  277. package/dist/text-link/index.js.map +1 -0
  278. package/dist/text-link/index.mjs +8 -0
  279. package/dist/text-link/index.mjs.map +1 -0
  280. package/dist/textarea/index.d.mts +47 -0
  281. package/dist/textarea/index.d.ts +47 -0
  282. package/dist/textarea/index.js +1180 -0
  283. package/dist/textarea/index.js.map +1 -0
  284. package/dist/textarea/index.mjs +77 -0
  285. package/dist/textarea/index.mjs.map +1 -0
  286. package/dist/visually-hidden/index.d.mts +16 -0
  287. package/dist/visually-hidden/index.d.ts +16 -0
  288. package/dist/visually-hidden/index.js +67 -0
  289. package/dist/visually-hidden/index.js.map +1 -0
  290. package/dist/visually-hidden/index.mjs +8 -0
  291. package/dist/visually-hidden/index.mjs.map +1 -0
  292. package/global.d.ts +12 -0
  293. package/package.json +75 -0
  294. package/tsconfig.build.json +9 -0
  295. package/tsconfig.json +9 -0
  296. package/tsup.config.ts +11 -0
@@ -0,0 +1,1267 @@
1
+ import {
2
+ Popover
3
+ } from "../chunk-B42LOFIZ.mjs";
4
+ import {
5
+ IconButton
6
+ } from "../chunk-2KPFQEAA.mjs";
7
+ import "../chunk-6JOA37TZ.mjs";
8
+ import {
9
+ Spinner
10
+ } from "../chunk-MUNDKRAE.mjs";
11
+ import {
12
+ useFormFieldControl
13
+ } from "../chunk-7PMPYEHJ.mjs";
14
+ import "../chunk-HLXYG643.mjs";
15
+ import {
16
+ Icon
17
+ } from "../chunk-AESXFMCC.mjs";
18
+ import {
19
+ VisuallyHidden
20
+ } from "../chunk-NBZKMCHF.mjs";
21
+ import "../chunk-4F5DOL57.mjs";
22
+
23
+ // src/combobox/ComboboxContext.tsx
24
+ import { useCombinedState } from "@spark-ui/use-combined-state";
25
+ import { useCombobox as useCombobox3, useMultipleSelection } from "downshift";
26
+ import {
27
+ createContext,
28
+ Fragment,
29
+ useContext,
30
+ useEffect,
31
+ useId,
32
+ useRef,
33
+ useState
34
+ } from "react";
35
+
36
+ // src/combobox/useCombobox/multipleSelectionReducer.ts
37
+ import { useCombobox } from "downshift";
38
+
39
+ // src/combobox/utils/index.ts
40
+ import { isValidElement, Children } from "react";
41
+ function getIndexByKey(map, targetKey) {
42
+ let index = 0;
43
+ for (const [key] of map.entries()) {
44
+ if (key === targetKey) {
45
+ return index;
46
+ }
47
+ index++;
48
+ }
49
+ return -1;
50
+ }
51
+ var getKeyAtIndex = (map, index) => {
52
+ let i = 0;
53
+ for (const key of map.keys()) {
54
+ if (i === index) return key;
55
+ i++;
56
+ }
57
+ return void 0;
58
+ };
59
+ var getElementByIndex = (map, index) => {
60
+ const key = getKeyAtIndex(map, index);
61
+ return key !== void 0 ? map.get(key) : void 0;
62
+ };
63
+ var getElementDisplayName = (element) => {
64
+ return element ? element.type.displayName : "";
65
+ };
66
+ var getOrderedItems = (children, result = []) => {
67
+ Children.forEach(children, (child) => {
68
+ if (!isValidElement(child)) return;
69
+ if (getElementDisplayName(child) === "Combobox.Item") {
70
+ const childProps = child.props;
71
+ result.push({
72
+ value: childProps.value,
73
+ disabled: !!childProps.disabled,
74
+ text: getItemText(childProps.children)
75
+ });
76
+ }
77
+ if (child.props.children) {
78
+ getOrderedItems(child.props.children, result);
79
+ }
80
+ });
81
+ return result;
82
+ };
83
+ var findNestedItemText = (children) => {
84
+ if (!children) return "";
85
+ for (const child of Children.toArray(children)) {
86
+ if (isValidElement(child)) {
87
+ const childElement = child;
88
+ if (getElementDisplayName(childElement) === "Combobox.ItemText") {
89
+ return childElement.props.children;
90
+ }
91
+ const foundText = findNestedItemText(childElement.props.children);
92
+ if (foundText) return foundText;
93
+ }
94
+ }
95
+ return "";
96
+ };
97
+ var getItemText = (children) => {
98
+ return typeof children === "string" ? children : findNestedItemText(children);
99
+ };
100
+ var getItemsFromChildren = (children) => {
101
+ const newMap = /* @__PURE__ */ new Map();
102
+ getOrderedItems(children).forEach((itemData) => {
103
+ newMap.set(itemData.value, itemData);
104
+ });
105
+ return newMap;
106
+ };
107
+ var hasChildComponent = (children, displayName) => {
108
+ return Children.toArray(children).some((child) => {
109
+ if (!isValidElement(child)) return false;
110
+ if (getElementDisplayName(child) === displayName) {
111
+ return true;
112
+ } else if (child.props.children) {
113
+ return hasChildComponent(child.props.children, displayName);
114
+ }
115
+ return false;
116
+ });
117
+ };
118
+ var findElement = (children, value) => {
119
+ return Children.toArray(children).filter(isValidElement).find((child) => value === getElementDisplayName(child) || "");
120
+ };
121
+
122
+ // src/combobox/useCombobox/multipleSelectionReducer.ts
123
+ var multipleSelectionReducer = ({
124
+ multiselect,
125
+ selectedItems,
126
+ allowCustomValue = false,
127
+ setSelectedItems,
128
+ triggerAreaRef,
129
+ items
130
+ }) => {
131
+ const reducer = (_, { changes, type }) => {
132
+ const isFocusInsideTriggerArea = triggerAreaRef.current?.contains?.(document.activeElement);
133
+ switch (type) {
134
+ case useCombobox.stateChangeTypes.InputClick:
135
+ return {
136
+ ...changes,
137
+ isOpen: true
138
+ // keep menu opened
139
+ };
140
+ case useCombobox.stateChangeTypes.InputKeyDownEnter:
141
+ case useCombobox.stateChangeTypes.ItemClick: {
142
+ const newState = { ...changes };
143
+ if (changes.selectedItem != null) {
144
+ newState.inputValue = "";
145
+ newState.isOpen = true;
146
+ const highlightedIndex = getIndexByKey(items, changes.selectedItem.value);
147
+ newState.highlightedIndex = highlightedIndex;
148
+ const isAlreadySelected = multiselect.selectedItems.some(
149
+ (selectedItem) => selectedItem.value === changes.selectedItem?.value
150
+ );
151
+ const updatedItems = isAlreadySelected ? selectedItems.filter((item) => item.value !== changes.selectedItem?.value) : [...selectedItems, changes.selectedItem];
152
+ setSelectedItems(updatedItems);
153
+ }
154
+ return newState;
155
+ }
156
+ case useCombobox.stateChangeTypes.ToggleButtonClick:
157
+ return {
158
+ ...changes,
159
+ inputValue: allowCustomValue ? changes.inputValue : ""
160
+ };
161
+ case useCombobox.stateChangeTypes.InputChange:
162
+ return {
163
+ ...changes,
164
+ selectedItem: changes.highlightedIndex === -1 ? null : changes.selectedItem
165
+ };
166
+ case useCombobox.stateChangeTypes.InputBlur:
167
+ return {
168
+ ...changes,
169
+ inputValue: allowCustomValue ? changes.inputValue : "",
170
+ isOpen: isFocusInsideTriggerArea
171
+ };
172
+ default:
173
+ return changes;
174
+ }
175
+ };
176
+ return reducer;
177
+ };
178
+
179
+ // src/combobox/useCombobox/singleSelectionReducer.ts
180
+ import { useCombobox as useCombobox2 } from "downshift";
181
+ var singleSelectionReducer = ({
182
+ filteredItems,
183
+ allowCustomValue = false,
184
+ setSelectedItem
185
+ }) => {
186
+ const reducer = (state, { changes, type }) => {
187
+ const exactMatch = filteredItems.find(
188
+ (item) => item.text.toLowerCase() === state.inputValue.toLowerCase()
189
+ );
190
+ switch (type) {
191
+ case useCombobox2.stateChangeTypes.InputKeyDownEscape:
192
+ if (!changes.selectedItem) {
193
+ setSelectedItem(null);
194
+ }
195
+ return changes;
196
+ case useCombobox2.stateChangeTypes.ItemClick:
197
+ case useCombobox2.stateChangeTypes.InputKeyDownEnter:
198
+ if (changes.selectedItem) {
199
+ setSelectedItem(changes.selectedItem);
200
+ }
201
+ return changes;
202
+ case useCombobox2.stateChangeTypes.InputClick:
203
+ return { ...changes, isOpen: true };
204
+ case useCombobox2.stateChangeTypes.ToggleButtonClick:
205
+ case useCombobox2.stateChangeTypes.InputBlur:
206
+ if (allowCustomValue) return changes;
207
+ if (state.inputValue === "") {
208
+ setSelectedItem(null);
209
+ return { ...changes, selectedItem: null };
210
+ }
211
+ if (exactMatch) {
212
+ setSelectedItem(exactMatch);
213
+ return { ...changes, selectedItem: exactMatch, inputValue: exactMatch.text };
214
+ }
215
+ if (state.selectedItem) {
216
+ return { ...changes, inputValue: state.selectedItem.text };
217
+ }
218
+ return { ...changes, inputValue: "" };
219
+ default:
220
+ return changes;
221
+ }
222
+ };
223
+ return reducer;
224
+ };
225
+
226
+ // src/combobox/ComboboxContext.tsx
227
+ import { jsx } from "react/jsx-runtime";
228
+ var ComboboxContext = createContext(null);
229
+ var getFilteredItemsMap = (map, inputValue) => {
230
+ if (!inputValue) return map;
231
+ return new Map(
232
+ Array.from(map).filter(([_, { text }]) => text.toLowerCase().includes(inputValue.toLowerCase()))
233
+ );
234
+ };
235
+ var ID_PREFIX = ":combobox";
236
+ var ComboboxProvider = ({
237
+ children,
238
+ state: stateProp,
239
+ allowCustomValue = false,
240
+ filtering = "auto",
241
+ disabled: disabledProp = false,
242
+ multiple = false,
243
+ readOnly: readOnlyProp = false,
244
+ wrap = true,
245
+ // Value
246
+ value: controlledValue,
247
+ defaultValue,
248
+ onValueChange,
249
+ // Open
250
+ open: controlledOpen,
251
+ defaultOpen,
252
+ onOpenChange,
253
+ isLoading
254
+ }) => {
255
+ const isMounted = useRef(false);
256
+ const [inputValue, setInputValue] = useState("");
257
+ const [isTyping, setIsTyping] = useState(filtering === "strict");
258
+ const triggerAreaRef = useRef(null);
259
+ const innerInputRef = useRef(null);
260
+ const [onInputValueChange, setOnInputValueChange] = useState(null);
261
+ const [comboboxValue] = useCombinedState(controlledValue, defaultValue);
262
+ const shouldFilterItems = filtering === "strict" || filtering === "auto" && isTyping;
263
+ const [itemsMap, setItemsMap] = useState(getItemsFromChildren(children));
264
+ const [filteredItemsMap, setFilteredItems] = useState(
265
+ shouldFilterItems ? getFilteredItemsMap(itemsMap, inputValue) : itemsMap
266
+ );
267
+ const [selectedItem, setSelectedItem] = useState(
268
+ itemsMap.get(comboboxValue) || null
269
+ );
270
+ const [selectedItems, setSelectedItems] = useState(
271
+ comboboxValue ? [...itemsMap.values()].filter((item) => comboboxValue.includes(item.value)) : []
272
+ );
273
+ const onInternalSelectedItemChange = (item) => {
274
+ setIsTyping(false);
275
+ if (item?.value !== selectedItem?.value) {
276
+ setSelectedItem(item);
277
+ setTimeout(() => {
278
+ onValueChange?.(item?.value);
279
+ }, 0);
280
+ }
281
+ };
282
+ const onInternalSelectedItemsChange = (items) => {
283
+ setSelectedItems(items);
284
+ setTimeout(() => {
285
+ onValueChange?.(items.map((i) => i.value));
286
+ }, 0);
287
+ };
288
+ useEffect(() => {
289
+ if (!isMounted.current) {
290
+ isMounted.current = true;
291
+ return;
292
+ }
293
+ if (multiple) {
294
+ const newSelectedItems = comboboxValue.reduce(
295
+ (accum, value) => {
296
+ const match = itemsMap.get(value);
297
+ return match ? [...accum, match] : accum;
298
+ },
299
+ []
300
+ );
301
+ setSelectedItems(comboboxValue ? newSelectedItems : []);
302
+ } else {
303
+ setSelectedItem(itemsMap.get(comboboxValue) || null);
304
+ }
305
+ }, [multiple ? JSON.stringify(comboboxValue) : comboboxValue]);
306
+ const field = useFormFieldControl();
307
+ const internalFieldLabelID = `${ID_PREFIX}-label-${useId()}`;
308
+ const internalFieldID = `${ID_PREFIX}-field-${useId()}`;
309
+ const id = field.id || internalFieldID;
310
+ const labelId = field.labelId || internalFieldLabelID;
311
+ const state = field.state || stateProp;
312
+ const disabled = field.disabled ?? disabledProp;
313
+ const readOnly = field.readOnly ?? readOnlyProp;
314
+ const [hasPopover, setHasPopover] = useState(
315
+ hasChildComponent(children, "Combobox.Popover")
316
+ );
317
+ const [lastInteractionType, setLastInteractionType] = useState("mouse");
318
+ useEffect(() => {
319
+ setFilteredItems(shouldFilterItems ? getFilteredItemsMap(itemsMap, inputValue) : itemsMap);
320
+ }, [inputValue, itemsMap]);
321
+ const multiselect = useMultipleSelection({
322
+ selectedItems,
323
+ stateReducer: (state2, { type, changes }) => {
324
+ const types = useMultipleSelection.stateChangeTypes;
325
+ switch (type) {
326
+ case types.SelectedItemKeyDownBackspace:
327
+ case types.SelectedItemKeyDownDelete: {
328
+ onInternalSelectedItemsChange(changes.selectedItems || []);
329
+ let activeIndex;
330
+ if (type === types.SelectedItemKeyDownDelete) {
331
+ const isLastItem = state2?.activeIndex === changes.selectedItems?.length;
332
+ activeIndex = isLastItem ? -1 : state2.activeIndex;
333
+ } else {
334
+ const hasItemBefore = (changes?.activeIndex || 0) - 1 >= 0;
335
+ activeIndex = hasItemBefore ? state2.activeIndex - 1 : changes?.activeIndex;
336
+ }
337
+ return {
338
+ ...changes,
339
+ activeIndex
340
+ };
341
+ }
342
+ case types.SelectedItemClick:
343
+ if (innerInputRef.current) {
344
+ innerInputRef.current.focus();
345
+ }
346
+ return {
347
+ ...changes,
348
+ activeIndex: -1
349
+ // the focus will remain on the input
350
+ };
351
+ case types.FunctionRemoveSelectedItem:
352
+ return {
353
+ ...changes,
354
+ activeIndex: -1
355
+ // the focus will remain on the input
356
+ };
357
+ case types.DropdownKeyDownNavigationPrevious:
358
+ downshift.closeMenu();
359
+ return changes;
360
+ default:
361
+ return changes;
362
+ }
363
+ }
364
+ });
365
+ const filteredItems = Array.from(filteredItemsMap.values());
366
+ useEffect(() => {
367
+ onInputValueChange?.(inputValue || "");
368
+ }, [inputValue]);
369
+ const downshift = useCombobox3({
370
+ inputId: id,
371
+ items: filteredItems,
372
+ selectedItem: multiple ? void 0 : selectedItem,
373
+ id,
374
+ labelId,
375
+ // Input
376
+ inputValue,
377
+ onInputValueChange: ({ inputValue: newInputValue }) => {
378
+ setInputValue(newInputValue);
379
+ if (shouldFilterItems) {
380
+ const filtered = getFilteredItemsMap(itemsMap, newInputValue || "");
381
+ setFilteredItems(filtered);
382
+ }
383
+ },
384
+ // Open
385
+ initialIsOpen: defaultOpen,
386
+ ...controlledOpen != null && { isOpen: controlledOpen },
387
+ onIsOpenChange: (changes) => {
388
+ if (changes.isOpen != null) {
389
+ onOpenChange?.(changes.isOpen);
390
+ }
391
+ },
392
+ // Custom Spark item object parsing
393
+ itemToString: (item) => {
394
+ return item?.text;
395
+ },
396
+ isItemDisabled: (item) => {
397
+ const isFilteredOut = !!inputValue && !filteredItems.some((filteredItem) => {
398
+ return item.value === filteredItem.value;
399
+ });
400
+ return item.disabled || isFilteredOut;
401
+ },
402
+ // Main reducer
403
+ stateReducer: multiple ? multipleSelectionReducer({
404
+ multiselect,
405
+ selectedItems,
406
+ allowCustomValue,
407
+ setSelectedItems: onInternalSelectedItemsChange,
408
+ triggerAreaRef,
409
+ items: itemsMap
410
+ }) : singleSelectionReducer({
411
+ allowCustomValue,
412
+ setSelectedItem: onInternalSelectedItemChange,
413
+ filteredItems: [...filteredItemsMap.values()]
414
+ }),
415
+ /**
416
+ * Downshift default behaviour is to scroll into view the highlighted item when the dropdown opens. This behaviour is not stable and scrolls the dropdown to the bottom of the screen.
417
+ */
418
+ scrollIntoView: (node) => {
419
+ if (node) {
420
+ node.scrollIntoView({ block: "nearest" });
421
+ }
422
+ return void 0;
423
+ }
424
+ });
425
+ useEffect(() => {
426
+ const newMap = getItemsFromChildren(children);
427
+ const previousItems = [...itemsMap.values()];
428
+ const newItems = [...newMap.values()];
429
+ const hasItemsChanges = previousItems.length !== newItems.length || previousItems.some((item, index) => {
430
+ const hasUpdatedValue = item.value !== newItems[index]?.value;
431
+ const hasUpdatedText = item.text !== newItems[index]?.text;
432
+ return hasUpdatedValue || hasUpdatedText;
433
+ });
434
+ if (hasItemsChanges) {
435
+ setItemsMap(newMap);
436
+ }
437
+ }, [children]);
438
+ const [WrapperComponent, wrapperProps] = hasPopover ? [Popover, { open: true }] : [Fragment, {}];
439
+ return /* @__PURE__ */ jsx(
440
+ ComboboxContext.Provider,
441
+ {
442
+ value: {
443
+ // Data
444
+ itemsMap,
445
+ filteredItemsMap,
446
+ highlightedItem: getElementByIndex(filteredItemsMap, downshift.highlightedIndex),
447
+ // State
448
+ multiple,
449
+ disabled,
450
+ readOnly,
451
+ hasPopover,
452
+ setHasPopover,
453
+ state,
454
+ lastInteractionType,
455
+ setLastInteractionType,
456
+ wrap,
457
+ // Refs
458
+ innerInputRef,
459
+ triggerAreaRef,
460
+ // Downshift state
461
+ ...downshift,
462
+ ...multiselect,
463
+ setInputValue,
464
+ selectItem: onInternalSelectedItemChange,
465
+ setSelectedItems: onInternalSelectedItemsChange,
466
+ isLoading,
467
+ setOnInputValueChange,
468
+ isTyping,
469
+ setIsTyping
470
+ },
471
+ children: /* @__PURE__ */ jsx(WrapperComponent, { ...wrapperProps, children })
472
+ }
473
+ );
474
+ };
475
+ var useComboboxContext = () => {
476
+ const context = useContext(ComboboxContext);
477
+ if (!context) {
478
+ throw Error("useComboboxContext must be used within a Combobox provider");
479
+ }
480
+ return context;
481
+ };
482
+
483
+ // src/combobox/Combobox.tsx
484
+ import { jsx as jsx2 } from "react/jsx-runtime";
485
+ var Combobox = ({ children, ...props }) => {
486
+ return /* @__PURE__ */ jsx2(ComboboxProvider, { ...props, children });
487
+ };
488
+ Combobox.displayName = "Combobox";
489
+
490
+ // src/combobox/ComboboxClearButton.tsx
491
+ import { DeleteOutline } from "@spark-ui/icons/DeleteOutline";
492
+ import { cx } from "class-variance-authority";
493
+ import { jsx as jsx3 } from "react/jsx-runtime";
494
+ var ClearButton = ({
495
+ className,
496
+ tabIndex = -1,
497
+ onClick,
498
+ ref,
499
+ ...others
500
+ }) => {
501
+ const ctx = useComboboxContext();
502
+ const handleClick = (event) => {
503
+ event.stopPropagation();
504
+ if (ctx.multiple) {
505
+ ctx.setSelectedItems([]);
506
+ } else {
507
+ ctx.selectItem(null);
508
+ }
509
+ ctx.setInputValue("");
510
+ if (ctx.innerInputRef.current) {
511
+ ctx.innerInputRef.current.focus();
512
+ }
513
+ if (onClick) {
514
+ onClick(event);
515
+ }
516
+ };
517
+ return /* @__PURE__ */ jsx3(
518
+ "button",
519
+ {
520
+ ref,
521
+ className: cx(className, "h-sz-44 text-neutral hover:text-neutral-hovered"),
522
+ tabIndex,
523
+ onClick: handleClick,
524
+ type: "button",
525
+ ...others,
526
+ children: /* @__PURE__ */ jsx3(Icon, { size: "sm", children: /* @__PURE__ */ jsx3(DeleteOutline, {}) })
527
+ }
528
+ );
529
+ };
530
+ ClearButton.displayName = "Combobox.ClearButton";
531
+
532
+ // src/combobox/ComboboxDisclosure.tsx
533
+ import { ArrowHorizontalDown } from "@spark-ui/icons/ArrowHorizontalDown";
534
+ import { useMergeRefs } from "@spark-ui/use-merge-refs";
535
+ import { cx as cx2 } from "class-variance-authority";
536
+ import { jsx as jsx4 } from "react/jsx-runtime";
537
+ var Disclosure = ({
538
+ className,
539
+ closedLabel,
540
+ openedLabel,
541
+ intent = "neutral",
542
+ design = "ghost",
543
+ size = "sm",
544
+ ref: forwardedRef,
545
+ ...props
546
+ }) => {
547
+ const ctx = useComboboxContext();
548
+ const { ref: downshiftRef, ...downshiftDisclosureProps } = ctx.getToggleButtonProps({
549
+ disabled: ctx.disabled || ctx.readOnly,
550
+ onClick: (event) => {
551
+ event.stopPropagation();
552
+ }
553
+ });
554
+ const isExpanded = downshiftDisclosureProps["aria-expanded"];
555
+ const ref = useMergeRefs(forwardedRef, downshiftRef);
556
+ return /* @__PURE__ */ jsx4(
557
+ IconButton,
558
+ {
559
+ ref,
560
+ className: cx2(className, "mt-[calc((44px-32px)/2)]"),
561
+ intent,
562
+ design,
563
+ size,
564
+ ...downshiftDisclosureProps,
565
+ ...props,
566
+ "aria-label": isExpanded ? openedLabel : closedLabel,
567
+ disabled: ctx.disabled,
568
+ children: /* @__PURE__ */ jsx4(
569
+ Icon,
570
+ {
571
+ className: cx2("shrink-0", "rotate-0 transition duration-100 ease-in", {
572
+ "rotate-180": isExpanded
573
+ }),
574
+ size: "sm",
575
+ children: /* @__PURE__ */ jsx4(ArrowHorizontalDown, {})
576
+ }
577
+ )
578
+ }
579
+ );
580
+ };
581
+ Disclosure.displayName = "Combobox.Disclosure";
582
+
583
+ // src/combobox/ComboboxEmpty.tsx
584
+ import { cx as cx3 } from "class-variance-authority";
585
+ import { jsx as jsx5 } from "react/jsx-runtime";
586
+ var Empty = ({ className, children, ref: forwardedRef }) => {
587
+ const ctx = useComboboxContext();
588
+ const hasNoItemVisible = ctx.filteredItemsMap.size === 0;
589
+ return hasNoItemVisible ? /* @__PURE__ */ jsx5(
590
+ "div",
591
+ {
592
+ ref: forwardedRef,
593
+ className: cx3("px-lg py-md text-body-1 text-on-surface/dim-1", className),
594
+ children
595
+ }
596
+ ) : null;
597
+ };
598
+ Empty.displayName = "Combobox.Empty";
599
+
600
+ // src/combobox/ComboboxGroup.tsx
601
+ import { cx as cx4 } from "class-variance-authority";
602
+ import { Children as Children2, isValidElement as isValidElement2 } from "react";
603
+
604
+ // src/combobox/ComboboxItemsGroupContext.tsx
605
+ import { createContext as createContext2, useContext as useContext2, useId as useId2 } from "react";
606
+ import { jsx as jsx6 } from "react/jsx-runtime";
607
+ var ComboboxGroupContext = createContext2(null);
608
+ var ComboboxGroupProvider = ({ children }) => {
609
+ const groupLabelId = `${ID_PREFIX}-group-label-${useId2()}`;
610
+ return /* @__PURE__ */ jsx6(ComboboxGroupContext.Provider, { value: { groupLabelId }, children });
611
+ };
612
+ var useComboboxGroupContext = () => {
613
+ const context = useContext2(ComboboxGroupContext);
614
+ if (!context) {
615
+ throw Error("useComboboxGroupContext must be used within a ComboboxGroup provider");
616
+ }
617
+ return context;
618
+ };
619
+
620
+ // src/combobox/ComboboxGroup.tsx
621
+ import { jsx as jsx7 } from "react/jsx-runtime";
622
+ var Group = ({ children, ref: forwardedRef, ...props }) => {
623
+ return /* @__PURE__ */ jsx7(ComboboxGroupProvider, { children: /* @__PURE__ */ jsx7(GroupContent, { ref: forwardedRef, ...props, children }) });
624
+ };
625
+ var GroupContent = ({ children, className, ref: forwardedRef }) => {
626
+ const ctx = useComboboxContext();
627
+ const groupCtx = useComboboxGroupContext();
628
+ const hasVisibleOptions = Children2.toArray(children).some((child) => {
629
+ return isValidElement2(child) && ctx.filteredItemsMap.get(child.props.value);
630
+ });
631
+ return hasVisibleOptions ? /* @__PURE__ */ jsx7(
632
+ "div",
633
+ {
634
+ ref: forwardedRef,
635
+ role: "group",
636
+ "aria-labelledby": groupCtx.groupLabelId,
637
+ className: cx4(className),
638
+ children
639
+ }
640
+ ) : null;
641
+ };
642
+ Group.displayName = "Combobox.Group";
643
+
644
+ // src/combobox/ComboboxInput.tsx
645
+ import { useCombinedState as useCombinedState2 } from "@spark-ui/use-combined-state";
646
+ import { useMergeRefs as useMergeRefs2 } from "@spark-ui/use-merge-refs";
647
+ import { cx as cx5 } from "class-variance-authority";
648
+ import {
649
+ Fragment as Fragment2,
650
+ useEffect as useEffect2
651
+ } from "react";
652
+ import { Fragment as Fragment3, jsx as jsx8, jsxs } from "react/jsx-runtime";
653
+ var Input = ({
654
+ "aria-label": ariaLabel,
655
+ className,
656
+ placeholder,
657
+ value,
658
+ defaultValue,
659
+ onValueChange,
660
+ ref: forwardedRef,
661
+ ...props
662
+ }) => {
663
+ const ctx = useComboboxContext();
664
+ const [inputValue] = useCombinedState2(value, defaultValue);
665
+ useEffect2(() => {
666
+ if (inputValue != null) {
667
+ ctx.setInputValue(inputValue);
668
+ }
669
+ }, [inputValue]);
670
+ useEffect2(() => {
671
+ if (onValueChange) {
672
+ ctx.setOnInputValueChange(() => onValueChange);
673
+ }
674
+ if (!ctx.multiple && ctx.selectedItem) {
675
+ ctx.setInputValue(ctx.selectedItem.text);
676
+ }
677
+ }, []);
678
+ const [PopoverTrigger, popoverTriggerProps] = ctx.hasPopover ? [Popover.Trigger, { asChild: true, type: void 0 }] : [Fragment2, {}];
679
+ const multiselectInputProps = ctx.getDropdownProps();
680
+ const inputRef = useMergeRefs2(forwardedRef, ctx.innerInputRef, multiselectInputProps.ref);
681
+ const downshiftInputProps = ctx.getInputProps({
682
+ disabled: ctx.disabled || ctx.readOnly,
683
+ ...multiselectInputProps,
684
+ onKeyDown: (event) => {
685
+ multiselectInputProps.onKeyDown?.(event);
686
+ ctx.setLastInteractionType("keyboard");
687
+ ctx.setIsTyping(true);
688
+ },
689
+ /**
690
+ *
691
+ * Important:
692
+ * - without this, the input cursor is moved to the end after every change.
693
+ * @see https://github.com/downshift-js/downshift/issues/1108#issuecomment-674180157
694
+ */
695
+ onChange: (e) => {
696
+ ctx.setInputValue(e.target.value);
697
+ },
698
+ ref: inputRef
699
+ });
700
+ const hasPlaceholder = ctx.multiple ? ctx.selectedItems.length === 0 : ctx.selectedItem === null;
701
+ function mergeHandlers(handlerA, handlerB) {
702
+ return (event) => {
703
+ handlerA?.(event);
704
+ handlerB?.(event);
705
+ };
706
+ }
707
+ const mergedEventProps = {
708
+ onBlur: mergeHandlers(props.onBlur, downshiftInputProps.onBlur),
709
+ onChange: mergeHandlers(props.onChange, downshiftInputProps.onChange),
710
+ onClick: mergeHandlers(props.onClick, downshiftInputProps.onClick),
711
+ onKeyDown: mergeHandlers(props.onKeyDown, downshiftInputProps.onKeyDown)
712
+ };
713
+ return /* @__PURE__ */ jsxs(Fragment3, { children: [
714
+ ariaLabel && /* @__PURE__ */ jsx8(VisuallyHidden, { children: /* @__PURE__ */ jsx8("label", { ...ctx.getLabelProps(), children: ariaLabel }) }),
715
+ /* @__PURE__ */ jsx8(PopoverTrigger, { ...popoverTriggerProps, children: /* @__PURE__ */ jsx8(
716
+ "input",
717
+ {
718
+ "data-spark-component": "combobox-input",
719
+ type: "text",
720
+ ...hasPlaceholder && { placeholder },
721
+ className: cx5(
722
+ "max-w-full shrink-0 grow basis-[80px]",
723
+ "h-sz-28 bg-surface px-sm text-body-1 text-ellipsis outline-hidden",
724
+ "disabled:text-on-surface/dim-3 disabled:cursor-not-allowed disabled:bg-transparent",
725
+ "read-only:text-on-surface read-only:cursor-default read-only:bg-transparent",
726
+ className
727
+ ),
728
+ ...props,
729
+ ...downshiftInputProps,
730
+ ...mergedEventProps,
731
+ value: ctx.inputValue,
732
+ "aria-label": ariaLabel,
733
+ disabled: ctx.disabled,
734
+ readOnly: ctx.readOnly
735
+ }
736
+ ) })
737
+ ] });
738
+ };
739
+ Input.displayName = "Combobox.Input";
740
+
741
+ // src/combobox/ComboboxItem.tsx
742
+ import { useMergeRefs as useMergeRefs3 } from "@spark-ui/use-merge-refs";
743
+ import { cva, cx as cx6 } from "class-variance-authority";
744
+
745
+ // src/combobox/ComboboxItemContext.tsx
746
+ import {
747
+ createContext as createContext3,
748
+ useContext as useContext3,
749
+ useState as useState2
750
+ } from "react";
751
+ import { jsx as jsx9 } from "react/jsx-runtime";
752
+ var ComboboxItemContext = createContext3(null);
753
+ var ComboboxItemProvider = ({
754
+ value,
755
+ disabled = false,
756
+ children
757
+ }) => {
758
+ const ctx = useComboboxContext();
759
+ const [textId, setTextId] = useState2(void 0);
760
+ const index = getIndexByKey(ctx.filteredItemsMap, value);
761
+ const itemData = { disabled, value, text: getItemText(children) };
762
+ const isSelected = ctx.multiple ? ctx.selectedItems.some((selectedItem) => selectedItem.value === value) : ctx.selectedItem?.value === value;
763
+ return /* @__PURE__ */ jsx9(
764
+ ComboboxItemContext.Provider,
765
+ {
766
+ value: { textId, setTextId, isSelected, itemData, index, disabled },
767
+ children
768
+ }
769
+ );
770
+ };
771
+ var useComboboxItemContext = () => {
772
+ const context = useContext3(ComboboxItemContext);
773
+ if (!context) {
774
+ throw Error("useComboboxItemContext must be used within a ComboboxItem provider");
775
+ }
776
+ return context;
777
+ };
778
+
779
+ // src/combobox/ComboboxItem.tsx
780
+ import { jsx as jsx10 } from "react/jsx-runtime";
781
+ var Item = ({ children, ref: forwardedRef, ...props }) => {
782
+ const { value, disabled } = props;
783
+ return /* @__PURE__ */ jsx10(ComboboxItemProvider, { value, disabled, children: /* @__PURE__ */ jsx10(ItemContent, { ref: forwardedRef, ...props, children }) });
784
+ };
785
+ var styles = cva("px-lg py-md text-body-1", {
786
+ variants: {
787
+ selected: {
788
+ true: "font-bold"
789
+ },
790
+ disabled: {
791
+ true: "opacity-dim-3 cursor-not-allowed",
792
+ false: "cursor-pointer"
793
+ },
794
+ highlighted: {
795
+ true: ""
796
+ },
797
+ interactionType: {
798
+ mouse: "",
799
+ keyboard: ""
800
+ }
801
+ },
802
+ compoundVariants: [
803
+ {
804
+ highlighted: true,
805
+ interactionType: "mouse",
806
+ class: "bg-surface-hovered"
807
+ },
808
+ {
809
+ highlighted: true,
810
+ interactionType: "keyboard",
811
+ class: "u-outline"
812
+ }
813
+ ]
814
+ });
815
+ var ItemContent = ({
816
+ className,
817
+ disabled = false,
818
+ value,
819
+ children,
820
+ ref: forwardedRef
821
+ }) => {
822
+ const ctx = useComboboxContext();
823
+ const itemCtx = useComboboxItemContext();
824
+ const isVisible = !!ctx.filteredItemsMap.get(value);
825
+ const { ref: downshiftRef, ...downshiftItemProps } = ctx.getItemProps({
826
+ item: itemCtx.itemData,
827
+ index: itemCtx.index
828
+ });
829
+ const ref = useMergeRefs3(forwardedRef, downshiftRef);
830
+ if (!isVisible) return null;
831
+ return /* @__PURE__ */ jsx10(
832
+ "li",
833
+ {
834
+ ref,
835
+ className: cx6(
836
+ styles({
837
+ selected: itemCtx.isSelected,
838
+ disabled,
839
+ highlighted: ctx.highlightedItem?.value === value,
840
+ interactionType: ctx.lastInteractionType,
841
+ className
842
+ })
843
+ ),
844
+ ...downshiftItemProps,
845
+ "aria-selected": itemCtx.isSelected,
846
+ "aria-labelledby": itemCtx.textId,
847
+ children
848
+ },
849
+ value
850
+ );
851
+ };
852
+ Item.displayName = "Combobox.Item";
853
+
854
+ // src/combobox/ComboboxItemIndicator.tsx
855
+ import { Check } from "@spark-ui/icons/Check";
856
+ import { cx as cx7 } from "class-variance-authority";
857
+ import { jsx as jsx11 } from "react/jsx-runtime";
858
+ var ItemIndicator = ({
859
+ className,
860
+ children,
861
+ label,
862
+ ref: forwardedRef
863
+ }) => {
864
+ const { disabled, isSelected } = useComboboxItemContext();
865
+ const childElement = children || /* @__PURE__ */ jsx11(Icon, { size: "sm", children: /* @__PURE__ */ jsx11(Check, { "aria-label": label }) });
866
+ return /* @__PURE__ */ jsx11(
867
+ "span",
868
+ {
869
+ ref: forwardedRef,
870
+ className: cx7("min-h-sz-16 min-w-sz-16 flex", disabled && "opacity-dim-3", className),
871
+ children: isSelected && childElement
872
+ }
873
+ );
874
+ };
875
+ ItemIndicator.displayName = "Combobox.ItemIndicator";
876
+
877
+ // src/combobox/ComboboxItems.tsx
878
+ import { useMergeRefs as useMergeRefs4 } from "@spark-ui/use-merge-refs";
879
+ import { cx as cx8 } from "class-variance-authority";
880
+ import { useLayoutEffect, useRef as useRef2 } from "react";
881
+ import { jsx as jsx12 } from "react/jsx-runtime";
882
+ var Items = ({ children, className, ref: forwardedRef, ...props }) => {
883
+ const ctx = useComboboxContext();
884
+ const { ref: downshiftRef, ...downshiftMenuProps } = ctx.getMenuProps({
885
+ onMouseMove: () => {
886
+ ctx.setLastInteractionType("mouse");
887
+ }
888
+ });
889
+ const innerRef = useRef2(null);
890
+ const ref = useMergeRefs4(forwardedRef, downshiftRef, innerRef);
891
+ const isOpen = ctx.hasPopover ? ctx.isOpen : true;
892
+ const isPointerEventsDisabled = ctx.hasPopover && !isOpen;
893
+ useLayoutEffect(() => {
894
+ if (innerRef.current?.parentElement) {
895
+ innerRef.current.parentElement.style.pointerEvents = isPointerEventsDisabled ? "none" : "";
896
+ innerRef.current.style.pointerEvents = isPointerEventsDisabled ? "none" : "";
897
+ }
898
+ }, [isPointerEventsDisabled]);
899
+ return /* @__PURE__ */ jsx12(
900
+ "ul",
901
+ {
902
+ ref,
903
+ className: cx8(
904
+ className,
905
+ "flex flex-col",
906
+ isOpen ? "block" : "pointer-events-none invisible opacity-0",
907
+ ctx.hasPopover && "p-lg",
908
+ ctx.isLoading && "items-center overflow-y-auto"
909
+ ),
910
+ ...props,
911
+ ...downshiftMenuProps,
912
+ "aria-busy": ctx.isLoading,
913
+ "data-spark-component": "combobox-items",
914
+ children: ctx.isLoading ? /* @__PURE__ */ jsx12(Spinner, { size: "sm" }) : children
915
+ }
916
+ );
917
+ };
918
+ Items.displayName = "Combobox.Items";
919
+
920
+ // src/combobox/ComboboxItemText.tsx
921
+ import { cx as cx9 } from "class-variance-authority";
922
+ import { useEffect as useEffect3, useId as useId3 } from "react";
923
+ import { jsx as jsx13 } from "react/jsx-runtime";
924
+ var ItemText = ({ children, className, ref: forwardedRef }) => {
925
+ const id = `${ID_PREFIX}-item-text-${useId3()}`;
926
+ const { setTextId } = useComboboxItemContext();
927
+ useEffect3(() => {
928
+ setTextId(id);
929
+ return () => setTextId(void 0);
930
+ });
931
+ return /* @__PURE__ */ jsx13("span", { id, className: cx9("inline", className), ref: forwardedRef, children });
932
+ };
933
+ ItemText.displayName = "Combobox.ItemText";
934
+
935
+ // src/combobox/ComboboxLabel.tsx
936
+ import { cx as cx10 } from "class-variance-authority";
937
+ import { jsx as jsx14 } from "react/jsx-runtime";
938
+ var Label = ({ children, className, ref: forwardedRef }) => {
939
+ const groupCtx = useComboboxGroupContext();
940
+ return /* @__PURE__ */ jsx14(
941
+ "div",
942
+ {
943
+ ref: forwardedRef,
944
+ id: groupCtx.groupLabelId,
945
+ className: cx10("px-md py-sm text-body-2 text-neutral italic", className),
946
+ children
947
+ }
948
+ );
949
+ };
950
+ Label.displayName = "Combobox.Label";
951
+
952
+ // src/combobox/ComboboxLeadingIcon.tsx
953
+ import { jsx as jsx15 } from "react/jsx-runtime";
954
+ var LeadingIcon = ({ children }) => {
955
+ return /* @__PURE__ */ jsx15(Icon, { size: "sm", className: "h-sz-44 shrink-0", children });
956
+ };
957
+ LeadingIcon.displayName = "Combobox.LeadingIcon";
958
+
959
+ // src/combobox/ComboboxPopover.tsx
960
+ import { cx as cx11 } from "class-variance-authority";
961
+ import { useEffect as useEffect4 } from "react";
962
+ import { jsx as jsx16 } from "react/jsx-runtime";
963
+ var Popover2 = ({
964
+ children,
965
+ matchTriggerWidth = true,
966
+ sideOffset = 4,
967
+ className,
968
+ ref: forwardedRef,
969
+ ...props
970
+ }) => {
971
+ const ctx = useComboboxContext();
972
+ useEffect4(() => {
973
+ ctx.setHasPopover(true);
974
+ return () => ctx.setHasPopover(false);
975
+ }, []);
976
+ return /* @__PURE__ */ jsx16(
977
+ Popover.Content,
978
+ {
979
+ ref: forwardedRef,
980
+ inset: true,
981
+ asChild: true,
982
+ matchTriggerWidth,
983
+ className: cx11("z-dropdown! relative", className),
984
+ sideOffset,
985
+ onOpenAutoFocus: (e) => {
986
+ e.preventDefault();
987
+ },
988
+ ...props,
989
+ "data-spark-component": "combobox-popover",
990
+ children
991
+ }
992
+ );
993
+ };
994
+ Popover2.displayName = "Combobox.Popover";
995
+
996
+ // src/combobox/ComboboxPortal.tsx
997
+ import { jsx as jsx17 } from "react/jsx-runtime";
998
+ var Portal = ({ children, ...rest }) => /* @__PURE__ */ jsx17(Popover.Portal, { ...rest, children });
999
+ Portal.displayName = "Combobox.Portal";
1000
+
1001
+ // src/combobox/ComboboxSelectedItems.tsx
1002
+ import { DeleteOutline as DeleteOutline2 } from "@spark-ui/icons/DeleteOutline";
1003
+ import { cx as cx12 } from "class-variance-authority";
1004
+ import { Fragment as Fragment4, jsx as jsx18, jsxs as jsxs2 } from "react/jsx-runtime";
1005
+ var SelectedItem = ({ item: selectedItem, index }) => {
1006
+ const ctx = useComboboxContext();
1007
+ const isCleanable = !ctx.disabled && !ctx.readOnly;
1008
+ const handleFocus = (e) => {
1009
+ const element = e.target;
1010
+ if (ctx.lastInteractionType === "keyboard") {
1011
+ element.scrollIntoView({
1012
+ behavior: "smooth",
1013
+ block: "nearest",
1014
+ inline: "nearest"
1015
+ });
1016
+ }
1017
+ };
1018
+ const { disabled, ...selectedItemProps } = ctx.getSelectedItemProps({
1019
+ disabled: ctx.disabled || ctx.readOnly,
1020
+ selectedItem,
1021
+ index
1022
+ });
1023
+ const Element = disabled ? "button" : "span";
1024
+ return /* @__PURE__ */ jsxs2(
1025
+ Element,
1026
+ {
1027
+ role: "presentation",
1028
+ "data-spark-component": "combobox-selected-item",
1029
+ className: cx12(
1030
+ "h-sz-28 bg-neutral-container flex items-center rounded-md align-middle",
1031
+ "text-body-2 text-on-neutral-container",
1032
+ "disabled:opacity-dim-3 disabled:cursor-not-allowed",
1033
+ "focus-visible:u-outline-inset outline-hidden",
1034
+ { "px-md": !isCleanable, "pl-md": isCleanable }
1035
+ ),
1036
+ ...selectedItemProps,
1037
+ tabIndex: -1,
1038
+ ...disabled && { disabled: true },
1039
+ onFocus: handleFocus,
1040
+ children: [
1041
+ /* @__PURE__ */ jsx18(
1042
+ "span",
1043
+ {
1044
+ className: cx12("line-clamp-1 overflow-x-hidden leading-normal break-all text-ellipsis", {
1045
+ "w-max": !ctx.wrap
1046
+ }),
1047
+ children: selectedItem.text
1048
+ }
1049
+ ),
1050
+ ctx.disabled,
1051
+ isCleanable && /* @__PURE__ */ jsx18(
1052
+ "button",
1053
+ {
1054
+ type: "button",
1055
+ tabIndex: -1,
1056
+ "aria-hidden": true,
1057
+ className: "px-md h-full cursor-pointer",
1058
+ onClick: (e) => {
1059
+ e.stopPropagation();
1060
+ const updatedSelectedItems = ctx.selectedItems.filter(
1061
+ (item) => item.value !== selectedItem.value
1062
+ );
1063
+ ctx.setSelectedItems(updatedSelectedItems);
1064
+ if (ctx.innerInputRef.current) {
1065
+ ctx.innerInputRef.current.focus({ preventScroll: true });
1066
+ }
1067
+ },
1068
+ children: /* @__PURE__ */ jsx18(Icon, { size: "sm", children: /* @__PURE__ */ jsx18(DeleteOutline2, {}) })
1069
+ }
1070
+ )
1071
+ ]
1072
+ },
1073
+ `selected-item-${index}`
1074
+ );
1075
+ };
1076
+ var SelectedItems = () => {
1077
+ const ctx = useComboboxContext();
1078
+ return ctx.multiple && ctx.selectedItems.length ? /* @__PURE__ */ jsx18(Fragment4, { children: ctx.selectedItems.map((item, index) => /* @__PURE__ */ jsx18(SelectedItem, { item, index }, item.value)) }) : null;
1079
+ };
1080
+ SelectedItems.displayName = "Combobox.SelectedItems";
1081
+
1082
+ // src/combobox/ComboboxTrigger.tsx
1083
+ import { useMergeRefs as useMergeRefs5 } from "@spark-ui/use-merge-refs";
1084
+ import { cx as cx13 } from "class-variance-authority";
1085
+ import { Fragment as Fragment5, useEffect as useEffect6, useRef as useRef4 } from "react";
1086
+
1087
+ // src/combobox/ComboboxTrigger.styles.tsx
1088
+ import { cva as cva2 } from "class-variance-authority";
1089
+ var styles2 = cva2(
1090
+ [
1091
+ "flex items-start gap-md min-h-sz-44 text-body-1",
1092
+ "h-fit rounded-lg px-lg",
1093
+ // outline styles
1094
+ "ring-1 outline-hidden ring-inset focus-within:ring-2"
1095
+ ],
1096
+ {
1097
+ variants: {
1098
+ allowWrap: {
1099
+ true: "",
1100
+ false: "h-sz-44"
1101
+ },
1102
+ state: {
1103
+ undefined: "ring-outline focus-within:ring-outline-high",
1104
+ error: "ring-error",
1105
+ alert: "ring-alert",
1106
+ success: "ring-success"
1107
+ },
1108
+ disabled: {
1109
+ true: "cursor-not-allowed border-outline bg-on-surface/dim-5 text-on-surface/dim-3"
1110
+ },
1111
+ readOnly: {
1112
+ true: "cursor-default bg-on-surface/dim-5 text-on-surface"
1113
+ }
1114
+ },
1115
+ compoundVariants: [
1116
+ {
1117
+ disabled: false,
1118
+ state: void 0,
1119
+ class: "hover:ring-outline-high"
1120
+ },
1121
+ {
1122
+ disabled: false,
1123
+ readOnly: false,
1124
+ class: "bg-surface text-on-surface cursor-text"
1125
+ }
1126
+ ],
1127
+ defaultVariants: {
1128
+ state: void 0,
1129
+ disabled: false,
1130
+ readOnly: false
1131
+ }
1132
+ }
1133
+ );
1134
+
1135
+ // src/combobox/utils/useWidthIncreaseCallback.ts
1136
+ import { useEffect as useEffect5, useRef as useRef3 } from "react";
1137
+ var useWidthIncreaseCallback = (elementRef, callback) => {
1138
+ const prevWidthRef = useRef3(null);
1139
+ useEffect5(() => {
1140
+ const checkWidthIncrease = () => {
1141
+ const currentWidth = elementRef.current?.scrollWidth || null;
1142
+ if (prevWidthRef.current && currentWidth && currentWidth > prevWidthRef.current) {
1143
+ callback();
1144
+ }
1145
+ prevWidthRef.current = currentWidth;
1146
+ requestAnimationFrame(checkWidthIncrease);
1147
+ };
1148
+ const interval = requestAnimationFrame(checkWidthIncrease);
1149
+ return () => cancelAnimationFrame(interval);
1150
+ }, [elementRef]);
1151
+ };
1152
+
1153
+ // src/combobox/ComboboxTrigger.tsx
1154
+ import { Fragment as Fragment6, jsx as jsx19, jsxs as jsxs3 } from "react/jsx-runtime";
1155
+ var Trigger = ({ className, children, ref: forwardedRef }) => {
1156
+ const ctx = useComboboxContext();
1157
+ const field = useFormFieldControl();
1158
+ const leadingIcon = findElement(children, "Combobox.LeadingIcon");
1159
+ const selectedItems = findElement(children, "Combobox.SelectedItems");
1160
+ const input = findElement(children, "Combobox.Input");
1161
+ const clearButton = findElement(children, "Combobox.ClearButton");
1162
+ const disclosure = findElement(children, "Combobox.Disclosure");
1163
+ const [PopoverAnchor, popoverAnchorProps] = ctx.hasPopover ? [Popover.Anchor, { asChild: true, type: void 0 }] : [Fragment5, {}];
1164
+ const ref = useMergeRefs5(forwardedRef, ctx.triggerAreaRef);
1165
+ const scrollableAreaRef = useRef4(null);
1166
+ const disabled = field.disabled || ctx.disabled;
1167
+ const readOnly = field.readOnly || ctx.readOnly;
1168
+ const hasClearButton = !!clearButton && !disabled && !readOnly;
1169
+ const scrollToRight = () => {
1170
+ if (scrollableAreaRef.current && !ctx.wrap) {
1171
+ const { scrollWidth, clientWidth } = scrollableAreaRef.current;
1172
+ scrollableAreaRef.current.scrollLeft = scrollWidth - clientWidth;
1173
+ }
1174
+ };
1175
+ useWidthIncreaseCallback(scrollableAreaRef, scrollToRight);
1176
+ useEffect6(() => {
1177
+ const resizeObserver = new ResizeObserver(scrollToRight);
1178
+ if (scrollableAreaRef.current) {
1179
+ resizeObserver.observe(scrollableAreaRef.current);
1180
+ }
1181
+ return () => {
1182
+ resizeObserver.disconnect();
1183
+ };
1184
+ }, []);
1185
+ return /* @__PURE__ */ jsx19(Fragment6, { children: /* @__PURE__ */ jsx19(PopoverAnchor, { ...popoverAnchorProps, children: /* @__PURE__ */ jsxs3(
1186
+ "div",
1187
+ {
1188
+ ref,
1189
+ className: styles2({
1190
+ className,
1191
+ state: ctx.state,
1192
+ disabled,
1193
+ readOnly,
1194
+ allowWrap: ctx.wrap
1195
+ }),
1196
+ onClick: () => {
1197
+ if (!ctx.isOpen && !disabled && !readOnly) {
1198
+ ctx.openMenu();
1199
+ if (ctx.innerInputRef.current) {
1200
+ ctx.innerInputRef.current.focus();
1201
+ }
1202
+ }
1203
+ },
1204
+ children: [
1205
+ leadingIcon,
1206
+ /* @__PURE__ */ jsxs3(
1207
+ "div",
1208
+ {
1209
+ ref: scrollableAreaRef,
1210
+ className: cx13(
1211
+ "min-w-none gap-sm py-md inline-flex grow items-start",
1212
+ ctx.wrap ? "flex-wrap" : "u-no-scrollbar overflow-x-auto p-[2px]"
1213
+ ),
1214
+ children: [
1215
+ selectedItems,
1216
+ input
1217
+ ]
1218
+ }
1219
+ ),
1220
+ hasClearButton && clearButton,
1221
+ disclosure
1222
+ ]
1223
+ }
1224
+ ) }) });
1225
+ };
1226
+ Trigger.displayName = "Combobox.Trigger";
1227
+
1228
+ // src/combobox/index.ts
1229
+ var Combobox2 = Object.assign(Combobox, {
1230
+ Group,
1231
+ Item,
1232
+ Items,
1233
+ ItemText,
1234
+ ItemIndicator,
1235
+ Label,
1236
+ Popover: Popover2,
1237
+ Trigger,
1238
+ LeadingIcon,
1239
+ Empty,
1240
+ Input,
1241
+ Disclosure,
1242
+ SelectedItems,
1243
+ ClearButton,
1244
+ Portal
1245
+ });
1246
+ Combobox2.displayName = "Combobox";
1247
+ Group.displayName = "Combobox.Group";
1248
+ Items.displayName = "Combobox.Items";
1249
+ Item.displayName = "Combobox.Item";
1250
+ ItemText.displayName = "Combobox.ItemText";
1251
+ ItemIndicator.displayName = "Combobox.ItemIndicator";
1252
+ Label.displayName = "Combobox.Label";
1253
+ Popover2.displayName = "Combobox.Popover";
1254
+ Trigger.displayName = "Combobox.Trigger";
1255
+ LeadingIcon.displayName = "Combobox.LeadingIcon";
1256
+ Empty.displayName = "Combobox.Empty";
1257
+ Input.displayName = "Combobox.Input";
1258
+ Disclosure.displayName = "Combobox.Disclosure";
1259
+ SelectedItems.displayName = "Combobox.SelectedItems";
1260
+ ClearButton.displayName = "Combobox.ClearButton";
1261
+ Portal.displayName = "Combobox.Portal";
1262
+ export {
1263
+ Combobox2 as Combobox,
1264
+ ComboboxProvider,
1265
+ useComboboxContext
1266
+ };
1267
+ //# sourceMappingURL=index.mjs.map