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
@@ -2,36 +2,35 @@ import React__default, { createContext, useState, useRef, useCallback, useEffect
2
2
  import { FormLabel } from '../FormLabel/FormLabel.js';
3
3
  import { timePickerTheme } from './TimePicker.theme.js';
4
4
  import { cn } from '../../../utils/cn.js';
5
- import { useClickOutside } from '../../../utils/useClickOutside.js';
6
5
  import { TimePickerTrigger } from './TimePickerTrigger.js';
7
6
  import { TimePickerContent } from './TimePickerContent.js';
7
+ import { WheelColumn } from './WheelColumn.js';
8
+ import { formatTimeInput, isValidTimeInput } from '../Input/inputMasks.js';
8
9
 
9
10
  const TimePickerContext = createContext(undefined);
10
11
  /**
11
12
  * Utility functions for time handling
12
13
  */
13
14
  // Parse time string into components - enhanced to handle various input formats
14
- const parseTime = (timeString, format = '24h') => {
15
- if (!timeString || timeString.trim() === '')
15
+ const parseTime = (timeString, format = "24h") => {
16
+ if (!timeString || timeString.trim() === "")
16
17
  return null;
17
18
  // Clean the input string
18
19
  const cleanTime = timeString.trim().toUpperCase();
19
20
  // Handle various input formats
20
21
  let parsedHour = 0;
21
22
  let parsedMinute = 0;
22
- let parsedSecond = 0;
23
23
  let parsedPeriod;
24
24
  // Try different parsing strategies
25
- // Strategy 1: Standard format with colons (14:30, 2:30 PM, 14:30:45)
26
- const standardRegex = format === '12h'
27
- ? /^(\d{1,2}):(\d{2})(?::(\d{2}))?\s*(AM|PM)?$/i
28
- : /^(\d{1,2}):(\d{2})(?::(\d{2}))?$/;
25
+ // Strategy 1: Standard format with colons (14:30, 2:30 PM)
26
+ const standardRegex = format === "12h"
27
+ ? /^(\d{1,2}):(\d{2})\s*(AM|PM)?$/i
28
+ : /^(\d{1,2}):(\d{2})$/;
29
29
  let match = cleanTime.match(standardRegex);
30
30
  if (match) {
31
31
  parsedHour = parseInt(match[1], 10);
32
32
  parsedMinute = parseInt(match[2], 10);
33
- parsedSecond = match[3] ? parseInt(match[3], 10) : 0;
34
- parsedPeriod = match[4] ? match[4] : undefined;
33
+ parsedPeriod = match[3] ? match[3] : undefined;
35
34
  }
36
35
  else {
37
36
  // Strategy 2: Flexible format (230, 230p, 1430, etc.)
@@ -39,7 +38,11 @@ const parseTime = (timeString, format = '24h') => {
39
38
  match = cleanTime.match(flexibleRegex);
40
39
  if (match) {
41
40
  const digits = match[1];
42
- parsedPeriod = match[2] ? (match[2].length === 1 ? `${match[2]}M` : match[2]) : undefined;
41
+ parsedPeriod = match[2]
42
+ ? match[2].length === 1
43
+ ? `${match[2]}M`
44
+ : match[2]
45
+ : undefined;
43
46
  if (digits.length <= 2) {
44
47
  // Just hours (2, 14)
45
48
  parsedHour = parseInt(digits, 10);
@@ -61,55 +64,51 @@ const parseTime = (timeString, format = '24h') => {
61
64
  }
62
65
  }
63
66
  // Convert 12-hour to 24-hour for internal consistency
64
- if (format === '12h' && parsedPeriod) {
65
- if (parsedPeriod === 'AM' && parsedHour === 12) {
67
+ if (format === "12h" && parsedPeriod) {
68
+ if (parsedPeriod === "AM" && parsedHour === 12) {
66
69
  parsedHour = 0;
67
70
  }
68
- else if (parsedPeriod === 'PM' && parsedHour !== 12) {
71
+ else if (parsedPeriod === "PM" && parsedHour !== 12) {
69
72
  parsedHour += 12;
70
73
  }
71
74
  }
72
75
  // Validate parsed values
73
- if (parsedHour < 0 || parsedHour > 23 || parsedMinute < 0 || parsedMinute > 59 || parsedSecond < 0 || parsedSecond > 59) {
76
+ if (parsedHour < 0 ||
77
+ parsedHour > 23 ||
78
+ parsedMinute < 0 ||
79
+ parsedMinute > 59) {
74
80
  return null;
75
81
  }
76
82
  return {
77
83
  hour: parsedHour,
78
84
  minute: parsedMinute,
79
- second: parsedSecond,
80
- period: format === '12h' ? (parsedHour >= 12 ? 'PM' : 'AM') : undefined
85
+ period: format === "12h" ? (parsedHour >= 12 ? "PM" : "AM") : undefined,
81
86
  };
82
87
  };
83
88
  // Format time components into string
84
- const formatTime = (time, format = '24h', showSeconds = false) => {
85
- let { hour, minute, second = 0, period } = time;
86
- if (format === '12h') {
89
+ const formatTime = (time, format = "24h") => {
90
+ let { hour, minute, period } = time;
91
+ if (format === "12h") {
87
92
  // Convert to 12-hour format
88
93
  if (hour === 0) {
89
94
  hour = 12;
90
- period = 'AM';
95
+ period = "AM";
91
96
  }
92
97
  else if (hour === 12) {
93
- period = 'PM';
98
+ period = "PM";
94
99
  }
95
100
  else if (hour > 12) {
96
101
  hour = hour - 12;
97
- period = 'PM';
102
+ period = "PM";
98
103
  }
99
104
  else {
100
- period = 'AM';
105
+ period = "AM";
101
106
  }
102
- const timeStr = showSeconds
103
- ? `${hour}:${minute.toString().padStart(2, '0')}:${second.toString().padStart(2, '0')}`
104
- : `${hour}:${minute.toString().padStart(2, '0')}`;
105
- return `${timeStr} ${period}`;
107
+ return `${hour}:${minute.toString().padStart(2, "0")} ${period}`;
106
108
  }
107
109
  else {
108
110
  // 24-hour format
109
- const timeStr = showSeconds
110
- ? `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}:${second.toString().padStart(2, '0')}`
111
- : `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`;
112
- return timeStr;
111
+ return `${hour.toString().padStart(2, "0")}:${minute.toString().padStart(2, "0")}`;
113
112
  }
114
113
  };
115
114
  // Validate time against constraints
@@ -117,12 +116,12 @@ const validateTime = (time, minTime, maxTime) => {
117
116
  const { hour, minute } = time;
118
117
  // Basic validation
119
118
  if (hour < 0 || hour > 23 || minute < 0 || minute > 59) {
120
- return { isValid: false, error: 'Invalid time' };
119
+ return { isValid: false, error: "Invalid time" };
121
120
  }
122
121
  // Convert to minutes for comparison
123
122
  const timeMinutes = hour * 60 + minute;
124
123
  if (minTime) {
125
- const minParsed = parseTime(minTime, '24h');
124
+ const minParsed = parseTime(minTime, "24h");
126
125
  if (minParsed) {
127
126
  const minMinutes = minParsed.hour * 60 + minParsed.minute;
128
127
  if (timeMinutes < minMinutes) {
@@ -131,7 +130,7 @@ const validateTime = (time, minTime, maxTime) => {
131
130
  }
132
131
  }
133
132
  if (maxTime) {
134
- const maxParsed = parseTime(maxTime, '24h');
133
+ const maxParsed = parseTime(maxTime, "24h");
135
134
  if (maxParsed) {
136
135
  const maxMinutes = maxParsed.hour * 60 + maxParsed.minute;
137
136
  if (timeMinutes > maxMinutes) {
@@ -143,7 +142,7 @@ const validateTime = (time, minTime, maxTime) => {
143
142
  };
144
143
  // Generate time options for selectors
145
144
  const generateHours = (format) => {
146
- if (format === '12h') {
145
+ if (format === "12h") {
147
146
  return Array.from({ length: 12 }, (_, i) => i + 1);
148
147
  }
149
148
  return Array.from({ length: 24 }, (_, i) => i);
@@ -151,141 +150,303 @@ const generateHours = (format) => {
151
150
  const generateMinutes = (step) => {
152
151
  return Array.from({ length: 60 / step }, (_, i) => i * step);
153
152
  };
154
- const generateSeconds = () => {
155
- return Array.from({ length: 60 }, (_, i) => i);
156
- };
157
- const TimeSelectorColumn = ({ label, value, options, onChange, disabled = false, size = 'md', theme }) => {
158
- const scrollRef = useRef(null);
159
- // Auto-scroll to selected value
160
- useEffect(() => {
161
- if (scrollRef.current) {
162
- const selectedIndex = options.findIndex(option => option === value);
163
- if (selectedIndex >= 0) {
164
- const itemHeight = 40; // Approximate item height
165
- const scrollTop = selectedIndex * itemHeight - 80; // Center in view
166
- scrollRef.current.scrollTop = Math.max(0, scrollTop);
167
- }
168
- }
169
- }, [value, options]);
170
- return (React__default.createElement("div", { className: cn(theme.selectorColumnStyle) },
171
- React__default.createElement("div", { className: cn(theme.selectorHeaderStyle) },
172
- React__default.createElement("span", { className: cn(theme.selectorHeaderLabelStyle) }, label)),
173
- React__default.createElement("div", { ref: scrollRef, className: "flex-1 overflow-y-auto", style: { scrollbarWidth: 'thin' } }, options.map((option) => {
174
- var _a;
175
- return (React__default.createElement("button", { key: option, type: "button", "data-selected": value === option, "data-disabled": disabled, className: cn(theme.selectorItemStyle, (_a = theme.selectorItemSizes) === null || _a === void 0 ? void 0 : _a[size]), onClick: () => !disabled && onChange(option), disabled: disabled }, typeof option === 'number' ? option.toString().padStart(2, '0') : option));
176
- }))));
177
- };
178
153
  /**
179
154
  * Main TimePicker Component
155
+ *
156
+ * Features:
157
+ * - iOS-style scroll wheel picker
158
+ * - Combobox-style masked input trigger with direct keyboard entry
159
+ * - Live bidirectional sync between input and wheels
160
+ * - 12h and 24h format support with AM/PM toggle
161
+ * - Cancel/Save workflow for confirming selection
162
+ * - Validation with min/max time constraints
180
163
  */
181
- const TimePicker = ({ value, defaultValue, onChange, format = '24h', step = 1, minTime, maxTime, showSeconds = false, disabled = false, placeholder = format === '12h' ? 'Select time (e.g. 2:30 PM)' : 'Select time (e.g. 14:30)', size = 'md', state = 'default', clearable = true, label, helperText, iconStart, iconEnd, className, labelClassName, helperTextClassName, theme = {}, id, ...props }) => {
164
+ const TimePicker = ({ value, defaultValue, onChange, format = "24h", step = 1, minTime, maxTime, disabled = false, placeholder = format === "12h"
165
+ ? "HH:MM"
166
+ : "HH:MM", size = "md", state = "default", clearable = true, label, helperText, iconStart, iconEnd, className, labelClassName, helperTextClassName, theme = {}, id, ...props }) => {
182
167
  var _a;
183
168
  // Internal state
184
169
  const [isOpen, setIsOpen] = useState(false);
185
170
  const [internalValue, setInternalValue] = useState(defaultValue);
186
171
  const [validationError, setValidationError] = useState();
187
- const [isTyping, setIsTyping] = useState(false);
172
+ // Pending state for wheel picker (before Save is clicked)
173
+ const [pendingTime, setPendingTime] = useState(null);
174
+ // Masked input value
175
+ const [maskedValue, setMaskedValue] = useState("");
176
+ // Track whether the input or wheels initiated the last change (prevent feedback loops)
177
+ const syncSourceRef = useRef(null);
188
178
  // Refs
189
179
  const containerRef = useRef(null);
190
180
  const triggerRef = useRef(null);
191
- // Hooks
192
- useClickOutside(containerRef, () => setIsOpen(false));
181
+ const inputRef = useRef(null);
182
+ const dropdownRef = useRef(null);
193
183
  // Determine current value (controlled vs uncontrolled)
194
184
  const currentValue = value !== undefined ? value : internalValue;
195
- const [inputValue, setInputValue] = useState(currentValue || '');
196
- // Parse current time
185
+ // Parse current time for display
197
186
  const currentTime = parseTime(currentValue, format) || {
198
- hour: format === '12h' ? 12 : 0,
187
+ hour: format === "12h" ? 12 : 0,
199
188
  minute: 0,
200
- second: 0,
201
- period: format === '12h' ? 'AM' : undefined
189
+ period: format === "12h" ? "AM" : undefined,
202
190
  };
191
+ // Get display value for trigger
192
+ const displayValue = currentValue ? formatTime(currentTime, format) : "";
203
193
  // Merge theme with defaults
204
194
  const mergedTheme = { ...timePickerTheme, ...theme };
205
195
  // Generate unique ID
206
196
  const inputId = id || `timepicker-${Math.random().toString(36).substr(2, 9)}`;
207
197
  // Determine if component is in error state
208
- const isInvalid = state === 'invalid' || Boolean(validationError);
209
- const finalState = isInvalid ? 'invalid' : state;
210
- // Handle time change
211
- const handleTimeChange = useCallback((newTime) => {
212
- const formattedTime = formatTime(newTime, format, showSeconds);
213
- // Validate time
214
- const validation = validateTime(newTime, minTime, maxTime);
215
- if (!validation.isValid) {
216
- setValidationError(validation.error);
217
- return;
198
+ const isInvalid = state === "invalid" || Boolean(validationError);
199
+ const finalState = isInvalid ? "invalid" : state;
200
+ // Generate selector options
201
+ const hourOptions = generateHours(format);
202
+ const minuteOptions = generateMinutes(step);
203
+ const periodOptions = ["AM", "PM"];
204
+ // Get the time to show in wheel picker (pending or current)
205
+ const wheelTime = pendingTime || currentTime;
206
+ // Convert 24h hour to 12h display hour for wheel
207
+ const getDisplayHour = (hour24) => {
208
+ if (format === "12h") {
209
+ if (hour24 === 0)
210
+ return 12;
211
+ if (hour24 > 12)
212
+ return hour24 - 12;
213
+ return hour24;
214
+ }
215
+ return hour24;
216
+ };
217
+ // Convert 12h display hour back to 24h for storage
218
+ const get24Hour = (displayHour, period) => {
219
+ if (period === "AM") {
220
+ return displayHour === 12 ? 0 : displayHour;
218
221
  }
219
222
  else {
220
- setValidationError(undefined);
223
+ return displayHour === 12 ? 12 : displayHour + 12;
221
224
  }
222
- // Update internal state if uncontrolled
223
- if (value === undefined) {
224
- setInternalValue(formattedTime);
225
+ };
226
+ // ============================================
227
+ // Input handlers
228
+ // ============================================
229
+ // Handle masked input change
230
+ const handleInputChange = useCallback((rawValue) => {
231
+ const formatKey = format === "12h" ? "12h" : "24h";
232
+ const formatted = formatTimeInput(rawValue, formatKey);
233
+ setMaskedValue(formatted);
234
+ // If complete valid time, sync to wheels
235
+ if (isValidTimeInput(formatted, formatKey)) {
236
+ const match = formatted.match(/^(\d{2}):(\d{2})$/);
237
+ if (match) {
238
+ let hour = parseInt(match[1], 10);
239
+ const minute = parseInt(match[2], 10);
240
+ // For 12h, convert display hour to 24h using current period
241
+ if (format === "12h") {
242
+ const currentPeriod = (pendingTime === null || pendingTime === void 0 ? void 0 : pendingTime.period) || currentTime.period || "AM";
243
+ hour = get24Hour(hour, currentPeriod);
244
+ }
245
+ syncSourceRef.current = "input";
246
+ setPendingTime((prev) => ({
247
+ hour,
248
+ minute,
249
+ period: format === "12h" ? ((prev === null || prev === void 0 ? void 0 : prev.period) || currentTime.period || "AM") : undefined,
250
+ }));
251
+ }
225
252
  }
226
- // Call onChange callback
227
- onChange === null || onChange === void 0 ? void 0 : onChange(formattedTime);
228
- }, [format, showSeconds, minTime, maxTime, value, onChange]);
229
- // Handle dropdown trigger click (button click)
230
- const handleDropdownToggle = () => {
231
- if (!disabled) {
232
- setIsOpen(!isOpen);
253
+ // Open dropdown if not already open
254
+ if (!isOpen) {
255
+ setPendingTime((prev) => prev || { ...currentTime });
256
+ setIsOpen(true);
233
257
  }
234
- };
258
+ }, [format, isOpen, pendingTime, currentTime]);
259
+ // Handle input focus — open dropdown
260
+ const handleInputFocus = useCallback(() => {
261
+ if (disabled)
262
+ return;
263
+ if (!isOpen) {
264
+ setPendingTime({ ...currentTime });
265
+ setIsOpen(true);
266
+ // Initialize maskedValue from current display
267
+ if (currentValue) {
268
+ const displayHour = getDisplayHour(currentTime.hour);
269
+ const formatted = `${displayHour.toString().padStart(2, "0")}:${currentTime.minute.toString().padStart(2, "0")}`;
270
+ setMaskedValue(formatted);
271
+ }
272
+ }
273
+ }, [disabled, isOpen, currentTime, currentValue]);
274
+ // Handle input key down
275
+ const handleInputKeyDown = useCallback((e) => {
276
+ var _a;
277
+ if (e.key === "Enter") {
278
+ e.preventDefault();
279
+ handleSave();
280
+ }
281
+ else if (e.key === "Escape") {
282
+ e.preventDefault();
283
+ handleCancel();
284
+ }
285
+ else if (e.key === "Tab") {
286
+ handleCancel();
287
+ }
288
+ else if (e.key === "Backspace") {
289
+ // Handle backspace across the colon: if cursor is right after ":",
290
+ // delete both the colon and the preceding digit
291
+ const input = e.currentTarget;
292
+ const cursorPos = (_a = input.selectionStart) !== null && _a !== void 0 ? _a : 0;
293
+ if (cursorPos === 3 && maskedValue[2] === ":") {
294
+ e.preventDefault();
295
+ // Remove the digit before colon and the colon itself → keep just first char
296
+ const newValue = maskedValue.slice(0, 1);
297
+ setMaskedValue(newValue);
298
+ }
299
+ }
300
+ }, [maskedValue]);
301
+ // Handle AM/PM period toggle
302
+ const handlePeriodToggle = useCallback(() => {
303
+ setPendingTime((prev) => {
304
+ const current = prev || currentTime;
305
+ const newPeriod = current.period === "AM" ? "PM" : "AM";
306
+ const displayHour = getDisplayHour(current.hour);
307
+ const hour24 = get24Hour(displayHour, newPeriod);
308
+ syncSourceRef.current = "wheel";
309
+ return { ...current, hour: hour24, period: newPeriod };
310
+ });
311
+ }, [currentTime, format]);
312
+ // ============================================
313
+ // Wheel handlers
314
+ // ============================================
315
+ // Handle hour change from wheel
316
+ const handleHourChange = useCallback((newHour) => {
317
+ const hour = typeof newHour === "string" ? parseInt(newHour) : newHour;
318
+ syncSourceRef.current = "wheel";
319
+ setPendingTime((prev) => {
320
+ const current = prev || currentTime;
321
+ if (format === "12h") {
322
+ // Convert back to 24h
323
+ const hour24 = get24Hour(hour, current.period || "AM");
324
+ return { ...current, hour: hour24 };
325
+ }
326
+ return { ...current, hour };
327
+ });
328
+ }, [currentTime, format]);
329
+ // Handle minute change from wheel
330
+ const handleMinuteChange = useCallback((newMinute) => {
331
+ const minute = typeof newMinute === "string" ? parseInt(newMinute) : newMinute;
332
+ syncSourceRef.current = "wheel";
333
+ setPendingTime((prev) => {
334
+ const current = prev || currentTime;
335
+ return { ...current, minute };
336
+ });
337
+ }, [currentTime]);
338
+ // Handle period change from wheel (12h format only)
339
+ const handlePeriodChange = useCallback((newPeriod) => {
340
+ const period = newPeriod;
341
+ syncSourceRef.current = "wheel";
342
+ setPendingTime((prev) => {
343
+ const current = prev || currentTime;
344
+ // Recalculate hour based on new period
345
+ const displayHour = getDisplayHour(current.hour);
346
+ const hour24 = get24Hour(displayHour, period);
347
+ return { ...current, hour: hour24, period };
348
+ });
349
+ }, [currentTime, format]);
350
+ // ============================================
351
+ // Save / Cancel / Clear
352
+ // ============================================
353
+ // Handle Save button - commit pending time
354
+ const handleSave = useCallback(() => {
355
+ if (pendingTime) {
356
+ // Validate time
357
+ const validation = validateTime(pendingTime, minTime, maxTime);
358
+ if (!validation.isValid) {
359
+ setValidationError(validation.error);
360
+ return;
361
+ }
362
+ else {
363
+ setValidationError(undefined);
364
+ }
365
+ const formattedTime = formatTime(pendingTime, format);
366
+ // Update internal state if uncontrolled
367
+ if (value === undefined) {
368
+ setInternalValue(formattedTime);
369
+ }
370
+ // Call onChange callback
371
+ onChange === null || onChange === void 0 ? void 0 : onChange(formattedTime);
372
+ }
373
+ setIsOpen(false);
374
+ setPendingTime(null);
375
+ setMaskedValue("");
376
+ }, [pendingTime, format, minTime, maxTime, value, onChange]);
377
+ // Handle Cancel button - discard pending time
378
+ const handleCancel = useCallback(() => {
379
+ setIsOpen(false);
380
+ setPendingTime(null);
381
+ setMaskedValue("");
382
+ }, []);
383
+ // Portal-aware click-outside detection (matches Select/Combobox pattern)
384
+ useEffect(() => {
385
+ if (!isOpen)
386
+ return;
387
+ const handleClickOutside = (event) => {
388
+ if (dropdownRef.current &&
389
+ !dropdownRef.current.contains(event.target) &&
390
+ containerRef.current &&
391
+ !containerRef.current.contains(event.target)) {
392
+ handleCancel();
393
+ }
394
+ };
395
+ document.addEventListener("mousedown", handleClickOutside);
396
+ return () => document.removeEventListener("mousedown", handleClickOutside);
397
+ }, [isOpen, handleCancel]);
235
398
  // Handle clear button click
236
399
  const handleClear = () => {
237
- setInputValue('');
238
400
  if (value === undefined) {
239
401
  setInternalValue(undefined);
240
402
  }
241
- onChange === null || onChange === void 0 ? void 0 : onChange('');
403
+ onChange === null || onChange === void 0 ? void 0 : onChange("");
404
+ setMaskedValue("");
242
405
  setValidationError(undefined);
243
406
  };
244
- // Sync input value with current value when it changes externally
245
- React__default.useEffect(() => {
246
- if (!isTyping) {
247
- setInputValue(currentValue ? formatTime(currentTime, format, showSeconds) : '');
407
+ // ============================================
408
+ // Bidirectional sync: wheels → input
409
+ // ============================================
410
+ useEffect(() => {
411
+ if (pendingTime && syncSourceRef.current === "wheel") {
412
+ const displayHour = getDisplayHour(pendingTime.hour);
413
+ const formatted = `${displayHour.toString().padStart(2, "0")}:${pendingTime.minute.toString().padStart(2, "0")}`;
414
+ setMaskedValue(formatted);
248
415
  }
249
- }, [currentValue, format, showSeconds, isTyping, currentTime]);
250
- // Generate selector options
251
- const hourOptions = generateHours(format);
252
- const minuteOptions = generateMinutes(step);
253
- const secondOptions = generateSeconds();
254
- const periodOptions = ['AM', 'PM'];
416
+ // Reset sync source after processing
417
+ syncSourceRef.current = null;
418
+ }, [pendingTime, format]);
255
419
  // Context value
256
420
  const contextValue = {
257
421
  isOpen,
258
422
  setIsOpen,
259
423
  theme: mergedTheme,
260
424
  triggerRef,
261
- hasValue: Boolean(inputValue),
425
+ inputRef,
426
+ hasValue: Boolean(displayValue),
262
427
  size,
263
428
  state: finalState,
264
429
  };
430
+ // Current period for trigger display
431
+ const currentPeriod = (pendingTime === null || pendingTime === void 0 ? void 0 : pendingTime.period) || currentTime.period || (format === "12h" ? "AM" : undefined);
432
+ // Compute the value shown in the input:
433
+ // - When open: show maskedValue (user is editing)
434
+ // - When closed with a committed value: show formatted HH:MM from currentValue
435
+ // - When closed without a value: show "" (placeholder visible)
436
+ const closedInputDisplay = currentValue
437
+ ? `${getDisplayHour(currentTime.hour).toString().padStart(2, "0")}:${currentTime.minute.toString().padStart(2, "0")}`
438
+ : "";
439
+ const inputDisplayValue = isOpen ? maskedValue : closedInputDisplay;
265
440
  return (React__default.createElement(TimePickerContext.Provider, { value: contextValue },
266
441
  React__default.createElement("div", { ref: containerRef, className: cn(mergedTheme.containerStyle, className) },
267
442
  label && (React__default.createElement(FormLabel, { htmlFor: inputId, className: labelClassName, state: finalState, required: props.required }, label)),
268
- React__default.createElement(TimePickerTrigger, { id: inputId, disabled: disabled, isOpen: isOpen, state: finalState, size: size, clearable: clearable, onClear: handleClear, onClick: handleDropdownToggle, iconStart: iconStart, iconEnd: iconEnd }, inputValue || placeholder),
269
- React__default.createElement(TimePickerContent, { isOpen: isOpen, onClose: () => setIsOpen(false), portal: true, placement: "bottom-start", offset: 4 },
270
- React__default.createElement("div", { className: cn(mergedTheme.selectorContainerStyle) },
271
- React__default.createElement(TimeSelectorColumn, { label: "Hour", value: currentTime.hour, options: hourOptions, onChange: (hour) => handleTimeChange({
272
- ...currentTime,
273
- hour: typeof hour === 'string' ? parseInt(hour) : hour
274
- }), disabled: disabled, size: size, theme: mergedTheme }),
275
- React__default.createElement(TimeSelectorColumn, { label: "Min", value: currentTime.minute, options: minuteOptions, onChange: (minute) => handleTimeChange({
276
- ...currentTime,
277
- minute: typeof minute === 'string' ? parseInt(minute) : minute
278
- }), disabled: disabled, size: size, theme: mergedTheme }),
279
- showSeconds && (React__default.createElement(TimeSelectorColumn, { label: "Sec", value: currentTime.second || 0, options: secondOptions, onChange: (second) => handleTimeChange({
280
- ...currentTime,
281
- second: typeof second === 'string' ? parseInt(second) : second
282
- }), disabled: disabled, size: size, theme: mergedTheme })),
283
- format === '12h' && (React__default.createElement(TimeSelectorColumn, { label: "Period", value: currentTime.period || 'AM', options: periodOptions, onChange: (period) => handleTimeChange({
284
- ...currentTime,
285
- period: period
286
- }), disabled: disabled, size: size, theme: mergedTheme })))),
443
+ React__default.createElement(TimePickerTrigger, { id: inputId, disabled: disabled, isOpen: isOpen, state: finalState, size: size, clearable: clearable, onClear: handleClear, iconStart: iconStart, iconEnd: iconEnd, inputValue: inputDisplayValue, onInputChange: handleInputChange, onInputFocus: handleInputFocus, onInputKeyDown: handleInputKeyDown, format: format, period: currentPeriod, onPeriodToggle: handlePeriodToggle, placeholder: placeholder }),
444
+ React__default.createElement(TimePickerContent, { isOpen: isOpen, onCancel: handleCancel, onSave: handleSave, portal: true, placement: "bottom-start", offset: 4, dropdownRef: dropdownRef },
445
+ React__default.createElement(WheelColumn, { label: "Hour", options: hourOptions, value: getDisplayHour(wheelTime.hour), onChange: handleHourChange, theme: mergedTheme }),
446
+ React__default.createElement(WheelColumn, { label: "Min", options: minuteOptions, value: wheelTime.minute, onChange: handleMinuteChange, theme: mergedTheme }),
447
+ format === "12h" && (React__default.createElement(WheelColumn, { label: "", options: periodOptions, value: wheelTime.period || "AM", onChange: handlePeriodChange, theme: mergedTheme }))),
287
448
  (helperText || validationError) && (React__default.createElement("p", { className: cn(mergedTheme.helperTextStyle, (_a = mergedTheme.helperTextStates) === null || _a === void 0 ? void 0 : _a[finalState], helperTextClassName) }, validationError || helperText)))));
288
449
  };
289
- TimePicker.displayName = 'TimePicker';
450
+ TimePicker.displayName = "TimePicker";
290
451
 
291
452
  export { TimePicker, TimePickerContext };
@@ -1,4 +1,4 @@
1
- import { TimePickerThemeOverrides } from './TimePicker.types';
1
+ import { TimePickerThemeOverrides } from "./TimePicker.types";
2
2
  /**
3
3
  * Default theme configuration for TimePicker component
4
4
  *
@@ -9,8 +9,8 @@ import { formsBaseTheme } from '../forms.theme.js';
9
9
  const timePickerTheme = {
10
10
  // Container wrapper
11
11
  containerStyle: formsBaseTheme.wrapperStyle,
12
- // Trigger base styles - extends common form input group style (same as Select/DatePicker)
13
- baseStyle: formsBaseTheme.inputGroupBaseStyle + " justify-between cursor-pointer",
12
+ // Trigger base styles - extends common form input group style (same as Input/Select/DatePicker)
13
+ baseStyle: formsBaseTheme.inputGroupBaseStyle,
14
14
  // Trigger size variants - composed from atomic tokens
15
15
  triggerSizes: {
16
16
  sm: `${formsBaseTheme.sizes.sm.text} ${formsBaseTheme.sizes.sm.padding} ${formsBaseTheme.sizes.sm.height}`,
@@ -30,41 +30,58 @@ const timePickerTheme = {
30
30
  // Icon padding styles - inherited from common form theme
31
31
  iconStartPadding: formsBaseTheme.iconStyles.padding.left,
32
32
  iconEndPadding: formsBaseTheme.iconStyles.padding.right,
33
+ // Placeholder text style - matches Select/Combobox placeholder styling
34
+ placeholderTextStyle: formsBaseTheme.placeholderStyle,
35
+ // Selected value text style
36
+ valueTextStyle: "text-[var(--color-text-primary)] dark:text-[var(--color-neutral-200)]",
33
37
  // Clear button styles (positioned between left content and right icon)
34
38
  clearButtonStyle: "absolute right-8 top-1/2 -translate-y-1/2 p-1 rounded text-[var(--color-text-muted)] hover:text-[var(--color-text-primary)] hover:bg-[var(--color-background-secondary)] transition-colors z-10",
35
39
  // Dropdown container styles (TimePicker-specific)
36
40
  // Width is controlled by trigger size via estimatedWidth parameter
37
- dropdownStyle: "fixed z-[1000] mt-2 bg-white border border-[var(--color-border)] rounded-[var(--form-rounded)] shadow-lg animate-in fade-in-0 zoom-in-95 duration-200",
41
+ dropdownStyle: "fixed z-[1000] bg-white border border-[var(--color-border)] rounded-[var(--form-rounded)] shadow-lg overflow-hidden " +
42
+ "dark:bg-[var(--color-background-secondary)] ",
38
43
  // Dropdown size variants - primarily for internal spacing/padding
39
44
  dropdownSizes: {
40
45
  sm: "",
41
46
  md: "",
42
47
  lg: "",
43
48
  },
44
- // Time selector container
45
- selectorContainerStyle: "flex divide-x divide-[var(--color-border)] h-48 overflow-hidden",
46
- // Individual selector column
47
- selectorColumnStyle: "flex-1 flex flex-col overflow-hidden scroll-smooth",
48
- // Column header styles
49
- selectorHeaderStyle: "sticky top-0 bg-white/95 backdrop-blur-sm p-2 border-b border-[var(--color-border)]",
50
- // Column header label styles
51
- selectorHeaderLabelStyle: "text-xs font-semibold text-[var(--color-text-secondary)] uppercase tracking-wide",
52
- // Time selector items
53
- selectorItemStyle: "flex items-center justify-center py-2 px-3 text-sm font-medium text-[var(--color-text-secondary)] hover:bg-[var(--color-background-secondary)] cursor-pointer transition-colors border-b border-[var(--color-border)] last:border-b-0 min-h-[2.5rem] data-[selected=true]:bg-[var(--color-primary-50)] data-[selected=true]:text-[var(--color-primary-700)] data-[selected=true]:font-semibold data-[selected=true]:border-l-2 data-[selected=true]:border-l-[var(--color-primary-600)] data-[disabled=true]:text-[var(--color-text-disabled)] data-[disabled=true]:cursor-not-allowed data-[disabled=true]:hover:bg-transparent",
54
- // Selector item size variants
55
- selectorItemSizes: {
56
- sm: "py-1.5 px-2 text-xs min-h-[2rem]",
57
- md: "py-2 px-3 text-sm min-h-[2.5rem]",
58
- lg: "py-3 px-4 text-base min-h-[3rem]",
59
- },
60
49
  // Helper text style - inherited from common form theme
61
50
  helperTextStyle: formsBaseTheme.helperText,
62
51
  // Helper text state variants
63
52
  helperTextStates: {
64
- default: "text-[var(--color-text-muted)]",
65
- disabled: "text-[var(--color-text-disabled)]",
66
- invalid: "text-red-600",
53
+ default: "text-[var(--color-text-muted)] dark:text-[var(--color-neutral-400)]",
54
+ disabled: "text-[var(--color-text-disabled)] dark:text-[var(--color-neutral-600)]",
55
+ invalid: "text-[var(--color-danger)] dark:text-[var(--color-danger-400)]",
67
56
  },
57
+ // ============================================
58
+ // Wheel Picker Styles (iOS-style scroll wheel)
59
+ // ============================================
60
+ // Wheel columns container - horizontal flex with dividers
61
+ wheelContainerStyle: "flex overflow-hidden",
62
+ // Individual wheel column - relative positioning for highlight overlay
63
+ wheelColumnStyle: "flex-1 flex flex-col relative",
64
+ // Wheel column header label
65
+ wheelHeaderStyle: "text-center py-2 text-xs font-semibold text-[var(--color-text-muted)] uppercase",
66
+ // Center highlight row - positioned behind selected item
67
+ wheelHighlightStyle: "absolute -mt-4 inset-x-0 bg-[var(--color-border)] pointer-events-none z-0",
68
+ // Wheel item - centered with transition for smooth opacity/color changes
69
+ wheelItemStyle: "flex items-center justify-center text-[var(--color-text-muted)] transition-colors select-none cursor-pointer relative z-10",
70
+ // Wheel item active (selected) style - stronger text color and weight
71
+ wheelItemActiveStyle: "text-[var(--color-text-primary)] font-semibold",
72
+ // Footer container - flexbox for action buttons
73
+ footerStyle: "flex justify-between items-center gap-2 px-2 py-2 border-t border-[var(--color-border)] " +
74
+ "dark:border-[var(--color-neutral-700)]",
75
+ // Inner input element style - transparent bg, no outline, tabular-nums for aligned digits
76
+ inputStyle: "bg-transparent outline-none flex-1 tabular-nums min-w-0 " +
77
+ "text-[var(--color-text-primary)] placeholder:text-[var(--color-text-placeholder)] " +
78
+ "dark:text-[var(--color-neutral-200)] dark:placeholder:text-[var(--color-neutral-500)]",
79
+ // AM/PM period toggle button
80
+ periodToggleStyle: "px-1.5 py-0.5 text-xs font-semibold rounded " +
81
+ "bg-[var(--color-background-tertiary)] text-[var(--color-text-primary)] " +
82
+ "hover:bg-[var(--color-background-quaternary)] transition-colors cursor-pointer select-none " +
83
+ "dark:bg-[var(--color-neutral-700)] dark:text-[var(--color-neutral-200)] " +
84
+ "dark:hover:bg-[var(--color-neutral-600)]",
68
85
  };
69
86
 
70
87
  export { timePickerTheme };