flikkui 0.2.0-beta.2 → 0.2.0-beta.5

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 (269) hide show
  1. package/README.md +92 -0
  2. package/dist/components/ai/PromptInput/PromptInput.js +23 -15
  3. package/dist/components/ai/PromptSuggestions/PromptSuggestion.d.ts +27 -0
  4. package/dist/components/ai/PromptSuggestions/PromptSuggestion.js +62 -0
  5. package/dist/components/ai/PromptSuggestions/PromptSuggestion.theme.d.ts +10 -0
  6. package/dist/components/ai/PromptSuggestions/PromptSuggestion.theme.js +12 -0
  7. package/dist/components/ai/PromptSuggestions/PromptSuggestion.types.d.ts +53 -0
  8. package/dist/components/ai/PromptSuggestions/index.d.ts +4 -2
  9. package/dist/components/ai/index.d.ts +2 -12
  10. package/dist/components/charts/ActivityRings/ActivityRings.js +70 -58
  11. package/dist/components/charts/ActivityRings/ActivityRings.theme.js +0 -1
  12. package/dist/components/charts/ActivityRings/ActivityRings.types.d.ts +17 -0
  13. package/dist/components/charts/BarChart/BarChart.js +8 -4
  14. package/dist/components/charts/BarChart/BarChart.types.d.ts +14 -0
  15. package/dist/components/charts/DonutChart/DonutChart.js +11 -8
  16. package/dist/components/charts/DonutChart/DonutChart.theme.d.ts +3 -0
  17. package/dist/components/charts/DonutChart/DonutChart.theme.js +5 -4
  18. package/dist/components/charts/DonutChart/donut-utils.d.ts +5 -0
  19. package/dist/components/charts/DonutChart/donut-utils.js +26 -1
  20. package/dist/components/charts/Heatmap/Heatmap.theme.js +2 -2
  21. package/dist/components/charts/shared/ChartAxis/XAxis.d.ts +2 -2
  22. package/dist/components/charts/shared/ChartAxis/XAxis.js +4 -4
  23. package/dist/components/charts/shared/ChartAxis/YAxis.d.ts +2 -2
  24. package/dist/components/charts/shared/ChartAxis/YAxis.js +8 -7
  25. package/dist/components/charts/shared/ChartGrid/HorizontalGrid.d.ts +1 -1
  26. package/dist/components/charts/shared/ChartGrid/HorizontalGrid.js +2 -2
  27. package/dist/components/charts/theme/chart.theme.d.ts +1 -1
  28. package/dist/components/charts/theme/chart.theme.js +39 -39
  29. package/dist/components/core/Accordion/Accordion.d.ts +1 -1
  30. package/dist/components/core/Accordion/Accordion.js +2 -2
  31. package/dist/components/core/Accordion/Accordion.types.d.ts +8 -0
  32. package/dist/components/core/Badge/Badge.js +11 -15
  33. package/dist/components/core/Badge/Badge.theme.js +7 -21
  34. package/dist/components/core/Badge/Badge.types.d.ts +9 -1
  35. package/dist/components/core/Button/Button.js +2 -2
  36. package/dist/components/core/Button/Button.theme.js +1 -1
  37. package/dist/components/core/Button/Button.types.d.ts +8 -0
  38. package/dist/components/core/Card/Card.js +8 -2
  39. package/dist/components/core/Card/Card.theme.js +1 -1
  40. package/dist/components/core/Card/Card.types.d.ts +24 -1
  41. package/dist/components/core/Drawer/Drawer.d.ts +1 -1
  42. package/dist/components/core/Drawer/Drawer.js +10 -40
  43. package/dist/components/core/Drawer/Drawer.theme.js +2 -1
  44. package/dist/components/core/Drawer/Drawer.types.d.ts +8 -0
  45. package/dist/components/core/Dropdown/Dropdown.d.ts +1 -1
  46. package/dist/components/core/Dropdown/Dropdown.js +2 -2
  47. package/dist/components/core/Dropdown/Dropdown.types.d.ts +8 -0
  48. package/dist/components/core/Metric/Metric.d.ts +1 -1
  49. package/dist/components/core/Metric/Metric.js +9 -5
  50. package/dist/components/core/Metric/Metric.theme.d.ts +1 -1
  51. package/dist/components/core/Metric/Metric.theme.js +38 -28
  52. package/dist/components/core/Metric/Metric.types.d.ts +27 -8
  53. package/dist/components/core/Modal/Modal.d.ts +1 -1
  54. package/dist/components/core/Modal/Modal.js +17 -40
  55. package/dist/components/core/Modal/Modal.theme.js +8 -3
  56. package/dist/components/core/Modal/Modal.types.d.ts +18 -0
  57. package/dist/components/core/Modal/index.d.ts +1 -1
  58. package/dist/components/core/Notification/Notification.js +2 -0
  59. package/dist/components/core/Pill/Pill.d.ts +6 -11
  60. package/dist/components/core/Pill/Pill.theme.d.ts +2 -2
  61. package/dist/components/core/Pill/Pill.types.d.ts +9 -22
  62. package/dist/components/core/Pill/index.d.ts +1 -1
  63. package/dist/components/core/Popover/Popover.d.ts +1 -1
  64. package/dist/components/core/Popover/Popover.js +2 -2
  65. package/dist/components/core/Popover/Popover.types.d.ts +8 -0
  66. package/dist/components/core/Progress/Progress.d.ts +28 -0
  67. package/dist/components/core/Progress/Progress.js +114 -0
  68. package/dist/components/core/Progress/Progress.theme.d.ts +5 -0
  69. package/dist/components/core/Progress/Progress.theme.js +33 -0
  70. package/dist/components/core/Progress/Progress.types.d.ts +92 -0
  71. package/dist/components/core/Progress/index.d.ts +2 -0
  72. package/dist/components/core/Table/Table.animations.d.ts +5 -16
  73. package/dist/components/core/Table/Table.animations.js +46 -0
  74. package/dist/components/core/Table/Table.d.ts +0 -27
  75. package/dist/components/core/Table/Table.js +58 -156
  76. package/dist/components/core/Table/Table.theme.js +28 -19
  77. package/dist/components/core/Table/Table.types.d.ts +95 -8
  78. package/dist/components/core/Table/Table.utils.d.ts +7 -0
  79. package/dist/components/core/Table/Table.utils.js +11 -1
  80. package/dist/components/core/Table/{components/TableActions/TableActions.d.ts → TableActions.d.ts} +3 -3
  81. package/dist/components/core/Table/{components/TableActions/TableActions.js → TableActions.js} +14 -24
  82. package/dist/components/core/Table/{components/TableActions/TableActionsMenu.d.ts → TableActionsMenu.d.ts} +1 -1
  83. package/dist/components/core/Table/{components/TableActions/TableActionsMenu.js → TableActionsMenu.js} +4 -4
  84. package/dist/components/core/Table/{components/core/TableBody.d.ts → TableBody.d.ts} +1 -1
  85. package/dist/components/core/Table/{components/core/TableBody.js → TableBody.js} +14 -20
  86. package/dist/components/core/Table/{components/core/TableCell.d.ts → TableCell.d.ts} +1 -9
  87. package/dist/components/core/Table/{components/core/TableCell.js → TableCell.js} +5 -13
  88. package/dist/components/core/Table/TableColumnManager.d.ts +3 -0
  89. package/dist/components/core/Table/TableColumnManager.js +34 -0
  90. package/dist/components/core/Table/{components/DeclarativeComponents.d.ts → TableDeclarative.d.ts} +1 -1
  91. package/dist/components/core/Table/{components/DeclarativeComponents.js → TableDeclarative.js} +6 -56
  92. package/dist/components/core/Table/TableFilter.d.ts +3 -0
  93. package/dist/components/core/Table/TableFilter.js +122 -0
  94. package/dist/components/core/Table/{components/core/TableHeader.d.ts → TableHeader.d.ts} +1 -1
  95. package/dist/components/core/Table/{components/core/TableHeader.js → TableHeader.js} +15 -29
  96. package/dist/components/core/Table/TablePagination.d.ts +7 -0
  97. package/dist/components/core/Table/{components/TablePagination/TablePagination.js → TablePagination.js} +5 -16
  98. package/dist/components/core/Table/TableRow.d.ts +8 -0
  99. package/dist/components/core/Table/TableRow.js +45 -0
  100. package/dist/components/core/Table/TableSelectionHeader.d.ts +7 -0
  101. package/dist/components/core/Table/{components/TableSelectionHeader/TableSelectionHeader.js → TableSelectionHeader.js} +4 -5
  102. package/dist/components/core/Table/hooks/index.d.ts +10 -0
  103. package/dist/components/core/Table/hooks/useTableColumns.d.ts +16 -0
  104. package/dist/components/core/Table/hooks/useTableColumns.js +67 -0
  105. package/dist/components/core/Table/hooks/useTableExpansion.d.ts +8 -0
  106. package/dist/components/core/Table/hooks/useTableExpansion.js +15 -0
  107. package/dist/components/core/Table/hooks/useTableFilter.d.ts +12 -0
  108. package/dist/components/core/Table/hooks/useTableFilter.js +37 -0
  109. package/dist/components/core/Table/hooks/useTablePagination.d.ts +12 -0
  110. package/dist/components/core/Table/hooks/useTablePagination.js +13 -0
  111. package/dist/components/core/Table/hooks/useTableSelection.d.ts +17 -0
  112. package/dist/components/core/Table/hooks/useTableSelection.js +40 -0
  113. package/dist/components/core/Table/index.d.ts +9 -8
  114. package/dist/components/core/Table/index.js +7 -5
  115. package/dist/components/core/Tabs/Tabs.js +2 -2
  116. package/dist/components/core/Tabs/Tabs.types.d.ts +8 -0
  117. package/dist/components/core/Tag/Tag.animations.d.ts +3 -0
  118. package/dist/components/core/Tag/Tag.animations.js +31 -0
  119. package/dist/components/core/Tag/Tag.d.ts +14 -0
  120. package/dist/components/core/Tag/Tag.js +45 -0
  121. package/dist/components/core/Tag/Tag.theme.d.ts +2 -0
  122. package/dist/components/core/Tag/Tag.theme.js +21 -0
  123. package/dist/components/core/Tag/Tag.types.d.ts +40 -0
  124. package/dist/components/core/Tag/index.d.ts +3 -0
  125. package/dist/components/core/Tooltip/Tooltip.d.ts +1 -1
  126. package/dist/components/core/Tooltip/Tooltip.js +3 -3
  127. package/dist/components/core/Tooltip/Tooltip.theme.js +1 -1
  128. package/dist/components/core/Tooltip/Tooltip.types.d.ts +17 -0
  129. package/dist/components/core/index.d.ts +2 -1
  130. package/dist/components/core/index.js +12 -5
  131. package/dist/components/effects/CustomCursor/CustomCursor.d.ts +0 -13
  132. package/dist/components/effects/CustomCursor/CustomCursor.js +26 -2
  133. package/dist/components/effects/CustomCursor/CustomCursor.theme.js +12 -1
  134. package/dist/components/effects/CustomCursor/CustomCursor.types.d.ts +14 -1
  135. package/dist/components/forms/Combobox/Combobox.d.ts +25 -0
  136. package/dist/components/forms/Combobox/Combobox.js +412 -0
  137. package/dist/components/forms/Combobox/Combobox.theme.d.ts +6 -0
  138. package/dist/components/forms/Combobox/Combobox.theme.js +60 -0
  139. package/dist/components/forms/Combobox/Combobox.types.d.ts +111 -0
  140. package/dist/components/forms/Combobox/index.d.ts +3 -0
  141. package/dist/components/forms/FileUpload/FileUpload.js +2 -0
  142. package/dist/components/forms/Input/Input.js +25 -28
  143. package/dist/components/forms/Input/inputMasks.d.ts +15 -0
  144. package/dist/components/forms/Input/inputMasks.js +72 -1
  145. package/dist/components/forms/InputTag/InputTag.d.ts +40 -0
  146. package/dist/components/forms/InputTag/InputTag.js +491 -0
  147. package/dist/components/forms/InputTag/InputTag.theme.d.ts +2 -0
  148. package/dist/components/forms/InputTag/InputTag.theme.js +16 -0
  149. package/dist/components/forms/InputTag/InputTag.types.d.ts +107 -0
  150. package/dist/components/forms/InputTag/index.d.ts +3 -0
  151. package/dist/components/forms/Select/Select.d.ts +101 -2
  152. package/dist/components/forms/Select/Select.js +128 -132
  153. package/dist/components/forms/Select/Select.theme.js +10 -14
  154. package/dist/components/forms/Select/Select.types.d.ts +6 -2
  155. package/dist/components/forms/Select/index.d.ts +7 -4
  156. package/dist/components/forms/Select/useSelectState.d.ts +66 -0
  157. package/dist/components/forms/Select/useSelectState.js +134 -0
  158. package/dist/components/forms/SelectExpand/SelectExpand.animations.d.ts +20 -0
  159. package/dist/components/forms/SelectExpand/SelectExpand.animations.js +74 -0
  160. package/dist/components/forms/SelectExpand/SelectExpand.d.ts +9 -0
  161. package/dist/components/forms/SelectExpand/SelectExpand.js +223 -0
  162. package/dist/components/forms/SelectExpand/SelectExpand.theme.d.ts +5 -0
  163. package/dist/components/forms/SelectExpand/SelectExpand.theme.js +74 -0
  164. package/dist/components/forms/SelectExpand/SelectExpand.types.d.ts +126 -0
  165. package/dist/components/forms/SelectExpand/index.d.ts +4 -0
  166. package/dist/components/forms/Switch/Switch.js +3 -3
  167. package/dist/components/forms/Switch/Switch.theme.d.ts +1 -1
  168. package/dist/components/forms/Switch/Switch.theme.js +2 -2
  169. package/dist/components/forms/TimePicker/TimePicker.animations.d.ts +0 -46
  170. package/dist/components/forms/TimePicker/TimePicker.d.ts +15 -6
  171. package/dist/components/forms/TimePicker/TimePicker.js +285 -124
  172. package/dist/components/forms/TimePicker/TimePicker.theme.d.ts +1 -1
  173. package/dist/components/forms/TimePicker/TimePicker.theme.js +39 -22
  174. package/dist/components/forms/TimePicker/TimePicker.types.d.ts +88 -34
  175. package/dist/components/forms/TimePicker/TimePickerContent.d.ts +7 -10
  176. package/dist/components/forms/TimePicker/TimePickerContent.js +149 -16
  177. package/dist/components/forms/TimePicker/TimePickerTrigger.d.ts +3 -3
  178. package/dist/components/forms/TimePicker/TimePickerTrigger.js +22 -19
  179. package/dist/components/forms/TimePicker/WheelColumn.d.ts +14 -0
  180. package/dist/components/forms/TimePicker/WheelColumn.js +90 -0
  181. package/dist/components/forms/TimePicker/index.d.ts +4 -1
  182. package/dist/components/forms/TimePicker/useWheelPicker.d.ts +37 -0
  183. package/dist/components/forms/TimePicker/useWheelPicker.js +138 -0
  184. package/dist/components/forms/forms.theme.d.ts +14 -0
  185. package/dist/components/forms/forms.theme.js +31 -0
  186. package/dist/components/forms/index.d.ts +9 -3
  187. package/dist/components/forms/index.js +73 -2
  188. package/dist/hooks/index.d.ts +0 -4
  189. package/dist/icons/Icon.d.ts +7 -0
  190. package/dist/icons/Icon.js +6 -2
  191. package/dist/index.js +21 -19
  192. package/dist/styles.css +1 -1
  193. package/dist/utils/index.d.ts +0 -1
  194. package/dist/utils/optimisticErrors.js +1 -70
  195. package/package.json +1 -1
  196. package/dist/components/ai/EditingIndicator/EditingIndicator.animations.d.ts +0 -31
  197. package/dist/components/ai/EditingIndicator/EditingIndicator.animations.js +0 -115
  198. package/dist/components/ai/EditingIndicator/EditingIndicator.d.ts +0 -35
  199. package/dist/components/ai/EditingIndicator/EditingIndicator.js +0 -94
  200. package/dist/components/ai/EditingIndicator/EditingIndicator.theme.d.ts +0 -2
  201. package/dist/components/ai/EditingIndicator/EditingIndicator.theme.js +0 -13
  202. package/dist/components/ai/EditingIndicator/EditingIndicator.types.d.ts +0 -54
  203. package/dist/components/ai/EditingIndicator/index.d.ts +0 -9
  204. package/dist/components/ai/GenerativeRenderer/GenerativeRenderer.d.ts +0 -3
  205. package/dist/components/ai/GenerativeRenderer/GenerativeRenderer.js +0 -126
  206. package/dist/components/ai/GenerativeRenderer/GenerativeRenderer.theme.d.ts +0 -2
  207. package/dist/components/ai/GenerativeRenderer/GenerativeRenderer.theme.js +0 -8
  208. package/dist/components/ai/GenerativeRenderer/GenerativeRenderer.types.d.ts +0 -45
  209. package/dist/components/ai/GenerativeRenderer/index.d.ts +0 -3
  210. package/dist/components/ai/PresenceIndicator/PresenceIndicator.animations.d.ts +0 -17
  211. package/dist/components/ai/PresenceIndicator/PresenceIndicator.animations.js +0 -56
  212. package/dist/components/ai/PresenceIndicator/PresenceIndicator.d.ts +0 -38
  213. package/dist/components/ai/PresenceIndicator/PresenceIndicator.js +0 -110
  214. package/dist/components/ai/PresenceIndicator/PresenceIndicator.theme.d.ts +0 -2
  215. package/dist/components/ai/PresenceIndicator/PresenceIndicator.theme.js +0 -13
  216. package/dist/components/ai/PresenceIndicator/PresenceIndicator.types.d.ts +0 -53
  217. package/dist/components/ai/PresenceIndicator/index.d.ts +0 -8
  218. package/dist/components/ai/PresenceProvider/PresenceContext.d.ts +0 -24
  219. package/dist/components/ai/PresenceProvider/PresenceContext.js +0 -34
  220. package/dist/components/ai/PresenceProvider/PresenceProvider.d.ts +0 -32
  221. package/dist/components/ai/PresenceProvider/PresenceProvider.js +0 -321
  222. package/dist/components/ai/PresenceProvider/PresenceProvider.types.d.ts +0 -140
  223. package/dist/components/ai/PresenceProvider/adapters/MockAdapter.d.ts +0 -102
  224. package/dist/components/ai/PresenceProvider/adapters/MockAdapter.js +0 -331
  225. package/dist/components/ai/PresenceProvider/adapters/PresenceAdapter.d.ts +0 -93
  226. package/dist/components/ai/PresenceProvider/adapters/SupabaseAdapter.d.ts +0 -134
  227. package/dist/components/ai/PresenceProvider/adapters/WebSocketAdapter.d.ts +0 -149
  228. package/dist/components/ai/PresenceProvider/adapters/index.d.ts +0 -11
  229. package/dist/components/ai/PresenceProvider/index.d.ts +0 -10
  230. package/dist/components/ai/PromptSuggestions/PromptSuggestions.d.ts +0 -27
  231. package/dist/components/ai/PromptSuggestions/PromptSuggestions.js +0 -61
  232. package/dist/components/ai/PromptSuggestions/PromptSuggestions.types.d.ts +0 -65
  233. package/dist/components/ai/VersionSlider/VersionSlider.d.ts +0 -3
  234. package/dist/components/ai/VersionSlider/VersionSlider.js +0 -97
  235. package/dist/components/ai/VersionSlider/VersionSlider.theme.d.ts +0 -2
  236. package/dist/components/ai/VersionSlider/VersionSlider.theme.js +0 -18
  237. package/dist/components/ai/VersionSlider/VersionSlider.types.d.ts +0 -77
  238. package/dist/components/ai/VersionSlider/index.d.ts +0 -3
  239. package/dist/components/core/Pill/Pill.animations.js +0 -25
  240. package/dist/components/core/Pill/Pill.js +0 -145
  241. package/dist/components/core/Pill/Pill.theme.js +0 -65
  242. package/dist/components/core/RetryBoundary/RetryBoundary.d.ts +0 -35
  243. package/dist/components/core/RetryBoundary/RetryBoundary.js +0 -154
  244. package/dist/components/core/RetryBoundary/RetryBoundary.theme.d.ts +0 -2
  245. package/dist/components/core/RetryBoundary/RetryBoundary.theme.js +0 -7
  246. package/dist/components/core/RetryBoundary/RetryBoundary.types.d.ts +0 -51
  247. package/dist/components/core/RetryBoundary/index.d.ts +0 -3
  248. package/dist/components/core/Table/components/TableActions/TableActions.types.d.ts +0 -40
  249. package/dist/components/core/Table/components/TableActions/index.d.ts +0 -3
  250. package/dist/components/core/Table/components/TableActionsMenu.d.ts +0 -6
  251. package/dist/components/core/Table/components/TablePagination/TablePagination.d.ts +0 -17
  252. package/dist/components/core/Table/components/TablePagination/TablePagination.types.d.ts +0 -21
  253. package/dist/components/core/Table/components/TablePagination/index.d.ts +0 -2
  254. package/dist/components/core/Table/components/TableSelectionHeader/TableSelectionHeader.d.ts +0 -15
  255. package/dist/components/core/Table/components/TableSelectionHeader/index.d.ts +0 -3
  256. package/dist/components/core/Table/components/core/TableRow.d.ts +0 -3
  257. package/dist/components/core/Table/components/core/TableRow.js +0 -44
  258. package/dist/components/core/Table/components/core/index.d.ts +0 -4
  259. package/dist/components/forms/OptimisticForm/OptimisticForm.d.ts +0 -33
  260. package/dist/components/forms/OptimisticForm/OptimisticForm.js +0 -87
  261. package/dist/components/forms/OptimisticForm/OptimisticForm.theme.d.ts +0 -2
  262. package/dist/components/forms/OptimisticForm/OptimisticForm.theme.js +0 -8
  263. package/dist/components/forms/OptimisticForm/OptimisticForm.types.d.ts +0 -74
  264. package/dist/components/forms/OptimisticForm/index.d.ts +0 -3
  265. package/dist/hooks/useOptimisticMutation.d.ts +0 -109
  266. package/dist/hooks/useOptimisticMutation.js +0 -171
  267. package/dist/hooks/usePresence.d.ts +0 -88
  268. package/dist/utils/presenceUtils.d.ts +0 -66
  269. package/dist/utils/presenceUtils.js +0 -107
@@ -0,0 +1,66 @@
1
+ import type { SelectOption } from "./Select.types";
2
+ /**
3
+ * Props for the useSelectState hook
4
+ */
5
+ export interface UseSelectStateProps<T = any> {
6
+ /** Array of available options */
7
+ options: SelectOption<T>[];
8
+ /** Currently selected value (controlled) */
9
+ value?: T;
10
+ /** Callback when selection changes */
11
+ onChange?: (value: T) => void;
12
+ /** Whether filtering/search is enabled */
13
+ searchable?: boolean;
14
+ /** Whether new options can be created */
15
+ creatable?: boolean;
16
+ /** Callback when creating a new option */
17
+ onCreateOption?: (inputValue: string) => void;
18
+ /** Label template for create option */
19
+ createLabel?: string | ((inputValue: string) => string);
20
+ /** Whether typeahead is enabled (default: true) */
21
+ enableTypeahead?: boolean;
22
+ }
23
+ /**
24
+ * Return type for the useSelectState hook
25
+ */
26
+ export interface UseSelectStateReturn<T = any> {
27
+ isOpen: boolean;
28
+ setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
29
+ highlightedIndex: number;
30
+ setHighlightedIndex: React.Dispatch<React.SetStateAction<number>>;
31
+ searchValue: string;
32
+ setSearchValue: React.Dispatch<React.SetStateAction<string>>;
33
+ selectedValue: T | undefined;
34
+ setSelectedValue: React.Dispatch<React.SetStateAction<T | undefined>>;
35
+ typeaheadValue: string;
36
+ setTypeaheadValue: React.Dispatch<React.SetStateAction<string>>;
37
+ typeaheadTimeoutRef: React.MutableRefObject<NodeJS.Timeout | null>;
38
+ filteredOptions: SelectOption<T>[];
39
+ selectedOption: SelectOption<T> | undefined;
40
+ hasCreateOption: boolean;
41
+ selectOption: (value: T, isCreateAction?: boolean) => void;
42
+ getOptionByValue: (searchValue: T) => SelectOption<T> | undefined;
43
+ triggerRef: React.MutableRefObject<HTMLElement | null>;
44
+ optionsRef: React.MutableRefObject<HTMLDivElement | null>;
45
+ options: SelectOption<T>[];
46
+ }
47
+ /**
48
+ * useSelectState
49
+ *
50
+ * A headless hook that manages all state for select/dropdown components.
51
+ * This hook can be used by Select, Combobox, MultiSelect, TagInput, etc.
52
+ *
53
+ * @example
54
+ * ```tsx
55
+ * const selectState = useSelectState({
56
+ * options,
57
+ * value,
58
+ * onChange,
59
+ * searchable: true,
60
+ * });
61
+ *
62
+ * // Use in your component:
63
+ * const { isOpen, setIsOpen, filteredOptions, selectOption } = selectState;
64
+ * ```
65
+ */
66
+ export declare function useSelectState<T = any>({ options, value, onChange, searchable, creatable, onCreateOption, createLabel, enableTypeahead, }: UseSelectStateProps<T>): UseSelectStateReturn<T>;
@@ -0,0 +1,134 @@
1
+ import { useState, useRef, useEffect, useCallback, useMemo } from 'react';
2
+
3
+ /**
4
+ * useSelectState
5
+ *
6
+ * A headless hook that manages all state for select/dropdown components.
7
+ * This hook can be used by Select, Combobox, MultiSelect, TagInput, etc.
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * const selectState = useSelectState({
12
+ * options,
13
+ * value,
14
+ * onChange,
15
+ * searchable: true,
16
+ * });
17
+ *
18
+ * // Use in your component:
19
+ * const { isOpen, setIsOpen, filteredOptions, selectOption } = selectState;
20
+ * ```
21
+ */
22
+ function useSelectState({ options = [], value, onChange, searchable = false, creatable = false, onCreateOption, createLabel, enableTypeahead = true, }) {
23
+ // Core state
24
+ const [isOpen, setIsOpen] = useState(false);
25
+ const [selectedValue, setSelectedValue] = useState(value);
26
+ const [highlightedIndex, setHighlightedIndex] = useState(-1);
27
+ const [searchValue, setSearchValue] = useState("");
28
+ // Typeahead state
29
+ const [typeaheadValue, setTypeaheadValue] = useState("");
30
+ const typeaheadTimeoutRef = useRef(null);
31
+ // Refs for trigger and options container
32
+ const triggerRef = useRef(null);
33
+ const optionsRef = useRef(null);
34
+ // Sync internal state with controlled value
35
+ useEffect(() => {
36
+ setSelectedValue(value);
37
+ }, [value]);
38
+ // Get option by value
39
+ const getOptionByValue = useCallback((searchVal) => {
40
+ return options.find((option) => option.value === searchVal);
41
+ }, [options]);
42
+ // Selected option derived from selectedValue
43
+ const selectedOption = useMemo(() => {
44
+ return selectedValue !== undefined
45
+ ? getOptionByValue(selectedValue)
46
+ : undefined;
47
+ }, [selectedValue, getOptionByValue]);
48
+ // Filter options based on search query
49
+ const baseFilteredOptions = useMemo(() => {
50
+ if (!searchValue)
51
+ return options;
52
+ return options.filter((option) => option.label.toLowerCase().includes(searchValue.toLowerCase()));
53
+ }, [options, searchValue]);
54
+ // Check if we should show the create option
55
+ const hasCreateOption = useMemo(() => {
56
+ return (creatable &&
57
+ searchable &&
58
+ searchValue.trim() !== "" &&
59
+ !baseFilteredOptions.some((option) => option.label.toLowerCase() === searchValue.toLowerCase()));
60
+ }, [creatable, searchable, searchValue, baseFilteredOptions]);
61
+ // Final filtered options with create option if applicable
62
+ const filteredOptions = useMemo(() => {
63
+ if (!hasCreateOption)
64
+ return baseFilteredOptions;
65
+ const createOptionLabel = typeof createLabel === "function"
66
+ ? createLabel(searchValue)
67
+ : createLabel || `Create "${searchValue}"`;
68
+ return [
69
+ {
70
+ id: "__create__",
71
+ label: createOptionLabel,
72
+ value: searchValue,
73
+ },
74
+ ...baseFilteredOptions,
75
+ ];
76
+ }, [hasCreateOption, baseFilteredOptions, searchValue, createLabel]);
77
+ // Select an option
78
+ const selectOption = useCallback((newValue, isCreateAction = false) => {
79
+ // Handle create action callback
80
+ if (isCreateAction && onCreateOption) {
81
+ onCreateOption(String(newValue));
82
+ }
83
+ // Update state if value changed
84
+ if (newValue !== selectedValue) {
85
+ setSelectedValue(newValue);
86
+ onChange === null || onChange === void 0 ? void 0 : onChange(newValue);
87
+ }
88
+ // Close and reset
89
+ setIsOpen(false);
90
+ setSearchValue("");
91
+ }, [selectedValue, onChange, onCreateOption]);
92
+ // Reset state when closing
93
+ useEffect(() => {
94
+ if (!isOpen) {
95
+ setSearchValue("");
96
+ setHighlightedIndex(-1);
97
+ setTypeaheadValue("");
98
+ // Clear any pending typeahead timeout
99
+ if (typeaheadTimeoutRef.current) {
100
+ clearTimeout(typeaheadTimeoutRef.current);
101
+ typeaheadTimeoutRef.current = null;
102
+ }
103
+ }
104
+ }, [isOpen]);
105
+ return {
106
+ // Core state
107
+ isOpen,
108
+ setIsOpen,
109
+ highlightedIndex,
110
+ setHighlightedIndex,
111
+ searchValue,
112
+ setSearchValue,
113
+ selectedValue,
114
+ setSelectedValue,
115
+ // Typeahead state
116
+ typeaheadValue,
117
+ setTypeaheadValue,
118
+ typeaheadTimeoutRef,
119
+ // Derived state
120
+ filteredOptions,
121
+ selectedOption,
122
+ hasCreateOption,
123
+ // Actions
124
+ selectOption,
125
+ getOptionByValue,
126
+ // Refs
127
+ triggerRef,
128
+ optionsRef,
129
+ // Original options
130
+ options,
131
+ };
132
+ }
133
+
134
+ export { useSelectState };
@@ -0,0 +1,20 @@
1
+ import type { Variants } from "motion/react";
2
+ /**
3
+ * Container expand/collapse animation variants
4
+ * Uses scale animation from center with spring physics
5
+ */
6
+ export declare const containerAnimations: Variants;
7
+ /**
8
+ * Options panel content animation variants
9
+ * Scale and fade from center with spring physics
10
+ */
11
+ export declare const optionsPanelAnimations: Variants;
12
+ /**
13
+ * Chevron rotation animation variants with spring
14
+ */
15
+ export declare const chevronAnimations: Variants;
16
+ /**
17
+ * Individual option animation for staggered reveal
18
+ * Can be used with staggerChildren on parent
19
+ */
20
+ export declare const optionAnimations: Variants;
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Spring configuration for smooth, natural animations
3
+ */
4
+ const springConfig = {
5
+ type: "spring",
6
+ stiffness: 400,
7
+ damping: 30,
8
+ mass: 1,
9
+ };
10
+ /**
11
+ * Container expand/collapse animation variants
12
+ * Uses scale animation from center with spring physics
13
+ */
14
+ const containerAnimations = {
15
+ collapsed: {
16
+ scaleY: 1,
17
+ transition: springConfig,
18
+ },
19
+ expanded: {
20
+ scaleY: 1,
21
+ transition: springConfig,
22
+ },
23
+ };
24
+ /**
25
+ * Options panel content animation variants
26
+ * Scale and fade from center with spring physics
27
+ */
28
+ const optionsPanelAnimations = {
29
+ collapsed: {
30
+ opacity: 0,
31
+ scaleY: 0.8,
32
+ scaleX: 0.98,
33
+ transition: {
34
+ type: "spring",
35
+ stiffness: 500,
36
+ damping: 30,
37
+ mass: 0.8,
38
+ },
39
+ },
40
+ expanded: {
41
+ opacity: 1,
42
+ scaleY: 1,
43
+ scaleX: 1,
44
+ transition: {
45
+ type: "spring",
46
+ stiffness: 400,
47
+ damping: 25,
48
+ mass: 0.8,
49
+ },
50
+ },
51
+ };
52
+ /**
53
+ * Chevron rotation animation variants with spring
54
+ */
55
+ const chevronAnimations = {
56
+ collapsed: {
57
+ rotate: 0,
58
+ transition: {
59
+ type: "spring",
60
+ stiffness: 400,
61
+ damping: 25,
62
+ },
63
+ },
64
+ expanded: {
65
+ rotate: 180,
66
+ transition: {
67
+ type: "spring",
68
+ stiffness: 400,
69
+ damping: 25,
70
+ },
71
+ },
72
+ };
73
+
74
+ export { chevronAnimations, containerAnimations, optionsPanelAnimations };
@@ -0,0 +1,9 @@
1
+ import React from "react";
2
+ import type { SelectExpandProps } from "./SelectExpand.types";
3
+ /**
4
+ * SelectExpand component - an in-place expanding select
5
+ * Instead of a dropdown, options expand below the trigger with smooth animation
6
+ *
7
+ * @template T - The type of the option values
8
+ */
9
+ export declare const SelectExpand: <T extends string | number = string>({ options, value, onChange, placeholder, multiple, searchable, searchPlaceholder, size, maxHeight, disabled, state, label, helperText, iconStart, iconEnd, id, name, required, className, wrapperClassName, theme: themeOverrides, ...restProps }: SelectExpandProps<T>) => React.JSX.Element;
@@ -0,0 +1,223 @@
1
+ import React__default, { useState, useRef, useMemo, useCallback, useEffect } from 'react';
2
+ import { motion, AnimatePresence } from 'motion/react';
3
+ import { ChevronDownIcon, MagnifyingGlassIcon, CheckIcon } from '@heroicons/react/24/outline';
4
+ import { selectExpandTheme } from './SelectExpand.theme.js';
5
+ import { containerAnimations, chevronAnimations, optionsPanelAnimations } from './SelectExpand.animations.js';
6
+ import { FormLabel } from '../FormLabel/FormLabel.js';
7
+ import { cn } from '../../../utils/cn.js';
8
+
9
+ /**
10
+ * SelectExpand component - an in-place expanding select
11
+ * Instead of a dropdown, options expand below the trigger with smooth animation
12
+ *
13
+ * @template T - The type of the option values
14
+ */
15
+ const SelectExpand = ({ options, value, onChange, placeholder = "Select an option", multiple = false, searchable = false, searchPlaceholder = "Search...", size = "md", maxHeight = "20rem", disabled = false, state = "default", label, helperText, iconStart, iconEnd, id, name, required = false, className, wrapperClassName, theme: themeOverrides, ...restProps }) => {
16
+ var _a;
17
+ // Merge theme with overrides
18
+ const theme = {
19
+ ...selectExpandTheme,
20
+ ...themeOverrides,
21
+ };
22
+ // State
23
+ const [isOpen, setIsOpen] = useState(false);
24
+ const [searchQuery, setSearchQuery] = useState("");
25
+ const [highlightedIndex, setHighlightedIndex] = useState(-1);
26
+ // Refs
27
+ const containerRef = useRef(null);
28
+ const triggerRef = useRef(null);
29
+ const searchInputRef = useRef(null);
30
+ const optionsListRef = useRef(null);
31
+ // Determine if disabled
32
+ const isDisabled = disabled || state === "disabled";
33
+ // Generate unique ID
34
+ const componentId = id || `select-expand-${Math.random().toString(36).substring(2, 9)}`;
35
+ // Parse value to array for consistent handling
36
+ const selectedValues = useMemo(() => {
37
+ if (value === undefined || value === null)
38
+ return [];
39
+ return Array.isArray(value) ? value : [value];
40
+ }, [value]);
41
+ // Filter options based on search query
42
+ const filteredOptions = useMemo(() => {
43
+ if (!searchQuery.trim())
44
+ return options;
45
+ const query = searchQuery.toLowerCase();
46
+ return options.filter((option) => {
47
+ var _a, _b;
48
+ return option.label.toLowerCase().includes(query) ||
49
+ ((_b = (_a = option.description) === null || _a === void 0 ? void 0 : _a.toLowerCase().includes(query)) !== null && _b !== void 0 ? _b : false);
50
+ });
51
+ }, [options, searchQuery]);
52
+ // Get display value for trigger
53
+ const displayValue = useMemo(() => {
54
+ var _a, _b;
55
+ if (selectedValues.length === 0)
56
+ return null;
57
+ if (multiple) {
58
+ if (selectedValues.length === 1) {
59
+ const option = options.find((o) => o.value === selectedValues[0]);
60
+ return (_a = option === null || option === void 0 ? void 0 : option.label) !== null && _a !== void 0 ? _a : String(selectedValues[0]);
61
+ }
62
+ return `${selectedValues.length} selected`;
63
+ }
64
+ const option = options.find((o) => o.value === selectedValues[0]);
65
+ return (_b = option === null || option === void 0 ? void 0 : option.label) !== null && _b !== void 0 ? _b : String(selectedValues[0]);
66
+ }, [selectedValues, options, multiple]);
67
+ // Check if a value is selected
68
+ const isSelected = useCallback((optionValue) => {
69
+ return selectedValues.includes(optionValue);
70
+ }, [selectedValues]);
71
+ // Handle option selection
72
+ const handleSelect = useCallback((optionValue) => {
73
+ if (!onChange)
74
+ return;
75
+ if (multiple) {
76
+ const newValues = isSelected(optionValue)
77
+ ? selectedValues.filter((v) => v !== optionValue)
78
+ : [...selectedValues, optionValue];
79
+ onChange(newValues);
80
+ }
81
+ else {
82
+ onChange(optionValue);
83
+ setIsOpen(false);
84
+ }
85
+ }, [multiple, selectedValues, onChange, isSelected]);
86
+ // Handle trigger click
87
+ const handleTriggerClick = () => {
88
+ if (isDisabled)
89
+ return;
90
+ setIsOpen((prev) => !prev);
91
+ };
92
+ // Handle click outside
93
+ useEffect(() => {
94
+ if (!isOpen)
95
+ return;
96
+ const handleClickOutside = (event) => {
97
+ if (containerRef.current &&
98
+ !containerRef.current.contains(event.target)) {
99
+ setIsOpen(false);
100
+ }
101
+ };
102
+ document.addEventListener("mousedown", handleClickOutside);
103
+ return () => document.removeEventListener("mousedown", handleClickOutside);
104
+ }, [isOpen]);
105
+ // Focus search input when opening
106
+ useEffect(() => {
107
+ if (isOpen && searchable && searchInputRef.current) {
108
+ // Small delay to allow animation to start
109
+ const timer = setTimeout(() => {
110
+ var _a;
111
+ (_a = searchInputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
112
+ }, 50);
113
+ return () => clearTimeout(timer);
114
+ }
115
+ }, [isOpen, searchable]);
116
+ // Reset search and highlighted index when closing
117
+ useEffect(() => {
118
+ if (!isOpen) {
119
+ setSearchQuery("");
120
+ setHighlightedIndex(-1);
121
+ }
122
+ }, [isOpen]);
123
+ // Handle keyboard navigation
124
+ useEffect(() => {
125
+ if (!isOpen)
126
+ return;
127
+ const handleKeyDown = (event) => {
128
+ var _a;
129
+ switch (event.key) {
130
+ case "Escape":
131
+ event.preventDefault();
132
+ setIsOpen(false);
133
+ (_a = triggerRef.current) === null || _a === void 0 ? void 0 : _a.focus();
134
+ break;
135
+ case "Tab":
136
+ setIsOpen(false);
137
+ break;
138
+ case "ArrowDown":
139
+ event.preventDefault();
140
+ setHighlightedIndex((prev) => prev >= filteredOptions.length - 1 ? 0 : prev + 1);
141
+ break;
142
+ case "ArrowUp":
143
+ event.preventDefault();
144
+ setHighlightedIndex((prev) => prev <= 0 ? filteredOptions.length - 1 : prev - 1);
145
+ break;
146
+ case "Enter":
147
+ case " ":
148
+ if (highlightedIndex >= 0 && highlightedIndex < filteredOptions.length) {
149
+ event.preventDefault();
150
+ const option = filteredOptions[highlightedIndex];
151
+ if (!option.disabled) {
152
+ handleSelect(option.value);
153
+ }
154
+ }
155
+ break;
156
+ }
157
+ };
158
+ document.addEventListener("keydown", handleKeyDown);
159
+ return () => document.removeEventListener("keydown", handleKeyDown);
160
+ }, [isOpen, highlightedIndex, filteredOptions, handleSelect]);
161
+ // Scroll highlighted option into view
162
+ useEffect(() => {
163
+ if (highlightedIndex >= 0 && optionsListRef.current) {
164
+ const option = optionsListRef.current.querySelector(`[data-option-index="${highlightedIndex}"]`);
165
+ if (option) {
166
+ option.scrollIntoView({ block: "nearest" });
167
+ }
168
+ }
169
+ }, [highlightedIndex]);
170
+ // Calculate max height value
171
+ const maxHeightValue = typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight;
172
+ // CSS variable for collapsed height based on size
173
+ const collapsedHeightMap = {
174
+ sm: "var(--form-min-h-sm)",
175
+ md: "var(--form-min-h-md)",
176
+ lg: "var(--form-min-h-lg)",
177
+ };
178
+ return (React__default.createElement("div", { className: cn(theme.wrapperStyle, isOpen && "z-[100]", wrapperClassName), ...restProps },
179
+ label && (React__default.createElement(FormLabel, { htmlFor: componentId, required: required }, label)),
180
+ React__default.createElement("div", { className: "invisible", "aria-hidden": "true", style: { height: collapsedHeightMap[size] } }),
181
+ React__default.createElement(motion.div, { ref: containerRef, className: cn(theme.containerStyle, isOpen && theme.containerExpandedStyle, isDisabled && theme.disabledStyle), style: {
182
+ "--collapsed-height": collapsedHeightMap[size],
183
+ }, variants: containerAnimations, initial: "collapsed", animate: isOpen ? "expanded" : "collapsed" },
184
+ React__default.createElement("button", { ref: triggerRef, id: componentId, type: "button", className: cn(theme.triggerStyle, (_a = theme.triggerSizes) === null || _a === void 0 ? void 0 : _a[size], className), onClick: handleTriggerClick, disabled: isDisabled, "aria-expanded": isOpen, "aria-haspopup": "listbox", "aria-controls": `${componentId}-options` },
185
+ iconStart && (React__default.createElement("span", { className: cn(theme.iconStartStyle, "mr-2") }, iconStart)),
186
+ React__default.createElement("span", { className: cn("flex-1 truncate text-left", displayValue ? theme.valueStyle : theme.placeholderStyle) }, displayValue || placeholder),
187
+ React__default.createElement(motion.span, { className: theme.iconEndStyle, variants: chevronAnimations, initial: "collapsed", animate: isOpen ? "expanded" : "collapsed" }, iconEnd || React__default.createElement(ChevronDownIcon, { className: "size-4" }))),
188
+ React__default.createElement(AnimatePresence, null, isOpen && (React__default.createElement(motion.div, { className: theme.optionsPanelStyle, style: { transformOrigin: "top center" }, variants: optionsPanelAnimations, initial: "collapsed", animate: "expanded", exit: "collapsed" },
189
+ searchable && (React__default.createElement("div", { className: theme.searchContainerStyle },
190
+ React__default.createElement("div", { className: "flex items-center gap-2" },
191
+ React__default.createElement(MagnifyingGlassIcon, { className: "size-4 shrink-0 text-[var(--color-text-muted)]" }),
192
+ React__default.createElement("input", { ref: searchInputRef, type: "text", className: theme.searchInputStyle, placeholder: searchPlaceholder, value: searchQuery, onChange: (e) => {
193
+ setSearchQuery(e.target.value);
194
+ setHighlightedIndex(-1);
195
+ }, "aria-label": "Search options" })))),
196
+ React__default.createElement("div", { ref: optionsListRef, id: `${componentId}-options`, role: "listbox", "aria-multiselectable": multiple, className: theme.optionsListStyle, style: { maxHeight: maxHeightValue } }, filteredOptions.length === 0 ? (React__default.createElement("div", { className: "py-3 px-3 text-center text-sm text-[var(--color-text-muted)]" }, "No options found")) : (filteredOptions.map((option, index) => {
197
+ const optionSelected = isSelected(option.value);
198
+ const isHighlighted = index === highlightedIndex;
199
+ return (React__default.createElement("div", { key: option.id, role: "option", "aria-selected": optionSelected, "aria-disabled": option.disabled, "data-option-index": index, className: cn(theme.optionStyle, theme.optionHoverStyle, optionSelected && !multiple && theme.optionSelectedStyle, option.disabled && theme.optionDisabledStyle, isHighlighted &&
200
+ "bg-[var(--color-primary-50)]/50 text-[var(--color-primary)] dark:bg-[var(--color-primary-900)]/20"), onClick: () => {
201
+ if (!option.disabled) {
202
+ handleSelect(option.value);
203
+ }
204
+ }, onMouseEnter: () => {
205
+ if (!option.disabled) {
206
+ setHighlightedIndex(index);
207
+ }
208
+ } },
209
+ multiple && (React__default.createElement("span", { className: cn(theme.checkboxStyle, optionSelected && theme.checkboxCheckedStyle) }, optionSelected && (React__default.createElement(CheckIcon, { className: "size-3", strokeWidth: 3 })))),
210
+ React__default.createElement("div", { className: "flex-1 min-w-0" },
211
+ React__default.createElement("span", { className: "block truncate" }, option.label),
212
+ option.description && (React__default.createElement("span", { className: "block text-xs text-[var(--color-text-muted)] truncate" }, option.description))),
213
+ !multiple && optionSelected && (React__default.createElement(CheckIcon, { className: "size-4 shrink-0 text-[var(--color-primary)]", strokeWidth: 2 }))));
214
+ }))))))),
215
+ helperText && (React__default.createElement("p", { className: theme.helperTextStyle }, helperText)),
216
+ name && (React__default.createElement("input", { type: "hidden", name: name, value: multiple
217
+ ? selectedValues.join(",")
218
+ : selectedValues[0] !== undefined
219
+ ? String(selectedValues[0])
220
+ : "" }))));
221
+ };
222
+
223
+ export { SelectExpand };
@@ -0,0 +1,5 @@
1
+ import { SelectExpandTheme } from "./SelectExpand.types";
2
+ /**
3
+ * Default theme for the SelectExpand component
4
+ */
5
+ export declare const selectExpandTheme: SelectExpandTheme;
@@ -0,0 +1,74 @@
1
+ import { formsBaseTheme } from '../forms.theme.js';
2
+
3
+ /**
4
+ * Default theme for the SelectExpand component
5
+ */
6
+ const selectExpandTheme = {
7
+ // Wrapper style - maintains layout footprint
8
+ wrapperStyle: "relative inline-block w-full",
9
+ // Container style - the animated expanding container
10
+ containerStyle: "absolute top-0 left-0 w-full z-[100] overflow-hidden rounded-[var(--form-rounded)] " +
11
+ "border border-[var(--color-border)] bg-white transition-shadow " +
12
+ "dark:bg-[var(--color-neutral-900)] dark:border-[var(--color-neutral-700)]",
13
+ // Container expanded state
14
+ containerExpandedStyle: "ring-2 ring-[var(--color-primary)] border-[var(--color-primary)] shadow-lg " +
15
+ "dark:ring-[var(--color-primary-500)] dark:border-[var(--color-primary-500)]",
16
+ // Trigger button style
17
+ triggerStyle: "w-full flex items-center justify-between cursor-pointer bg-transparent " +
18
+ "text-left focus:outline-none",
19
+ // Trigger size variants
20
+ triggerSizes: {
21
+ sm: `${formsBaseTheme.sizes.sm.text} ${formsBaseTheme.sizes.sm.padding} ${formsBaseTheme.sizes.sm.height}`,
22
+ md: `${formsBaseTheme.sizes.md.text} ${formsBaseTheme.sizes.md.padding} ${formsBaseTheme.sizes.md.height}`,
23
+ lg: `${formsBaseTheme.sizes.lg.text} ${formsBaseTheme.sizes.lg.padding} ${formsBaseTheme.sizes.lg.height}`,
24
+ },
25
+ // Placeholder text style
26
+ placeholderStyle: "text-[var(--color-text-placeholder)] dark:text-[var(--color-neutral-500)]",
27
+ // Selected value text style
28
+ valueStyle: "text-[var(--color-text-primary)] dark:text-[var(--color-neutral-200)]",
29
+ // Options panel container
30
+ optionsPanelStyle: "border-t border-[var(--color-border)] dark:border-[var(--color-neutral-700)]",
31
+ // Scrollable options list
32
+ optionsListStyle: "overflow-y-auto overscroll-contain",
33
+ // Individual option style
34
+ optionStyle: "flex items-center gap-2 py-2 px-3 cursor-pointer select-none " +
35
+ "text-[var(--color-text-primary)] transition-colors " +
36
+ "dark:text-[var(--color-neutral-200)]",
37
+ // Selected option style
38
+ optionSelectedStyle: "bg-[var(--color-primary-50)] text-[var(--color-primary)] font-medium " +
39
+ "dark:bg-[var(--color-primary-900)]/30 dark:text-[var(--color-primary-400)]",
40
+ // Disabled option style
41
+ optionDisabledStyle: "cursor-not-allowed opacity-50 hover:bg-transparent",
42
+ // Option hover style
43
+ optionHoverStyle: "hover:bg-[var(--color-primary-50)]/50 hover:text-[var(--color-primary)] " +
44
+ "dark:hover:bg-[var(--color-primary-900)]/20 dark:hover:text-[var(--color-primary-400)]",
45
+ // Checkbox style for multi-select
46
+ checkboxStyle: "size-4 shrink-0 rounded border border-[var(--color-border)] bg-white " +
47
+ "flex items-center justify-center transition-colors " +
48
+ "dark:bg-[var(--color-neutral-800)] dark:border-[var(--color-neutral-600)]",
49
+ // Checkbox checked style
50
+ checkboxCheckedStyle: "bg-[var(--color-primary)] border-[var(--color-primary)] text-white " +
51
+ "dark:bg-[var(--color-primary-500)] dark:border-[var(--color-primary-500)]",
52
+ // Search input container
53
+ searchContainerStyle: "px-3 py-2 border-b border-[var(--color-border)] " +
54
+ "dark:border-[var(--color-neutral-700)]",
55
+ // Search input style
56
+ searchInputStyle: "w-full bg-transparent text-sm text-[var(--color-text-primary)] " +
57
+ "placeholder:text-[var(--color-text-placeholder)] focus:outline-none " +
58
+ "dark:text-[var(--color-neutral-200)] dark:placeholder:text-[var(--color-neutral-500)]",
59
+ // Icon start style
60
+ iconStartStyle: "shrink-0 text-[var(--color-text-muted)] dark:text-[var(--color-neutral-500)]",
61
+ // Icon end style
62
+ iconEndStyle: "shrink-0 text-[var(--color-text-muted)] transition-transform duration-200 " +
63
+ "dark:text-[var(--color-neutral-500)]",
64
+ // Label style
65
+ labelStyle: "block text-sm font-medium text-[var(--color-text-primary)] mb-1.5 " +
66
+ "dark:text-[var(--color-neutral-200)]",
67
+ // Helper text style
68
+ helperTextStyle: "text-xs text-[var(--color-text-muted)] mt-1.5 " +
69
+ "dark:text-[var(--color-neutral-400)]",
70
+ // Disabled state style
71
+ disabledStyle: "cursor-not-allowed opacity-60 pointer-events-none",
72
+ };
73
+
74
+ export { selectExpandTheme };