@astryxdesign/core 0.4.7 → 0.5.0-canary.009bcb3

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 (730) hide show
  1. package/CHANGELOG.md +161 -1
  2. package/dist/AlertDialog/AlertDialog.d.ts +1 -1
  3. package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
  4. package/dist/AlertDialog/AlertDialog.js +45 -20
  5. package/dist/AppShell/AppShell.d.ts.map +1 -1
  6. package/dist/AppShell/AppShell.js +3 -2
  7. package/dist/AspectRatio/AspectRatio.d.ts +24 -0
  8. package/dist/AspectRatio/AspectRatio.d.ts.map +1 -1
  9. package/dist/AspectRatio/AspectRatio.js +23 -4
  10. package/dist/Avatar/Avatar.d.ts +25 -1
  11. package/dist/Avatar/Avatar.d.ts.map +1 -1
  12. package/dist/Avatar/Avatar.js +58 -19
  13. package/dist/Avatar/index.d.ts +2 -2
  14. package/dist/Avatar/index.d.ts.map +1 -1
  15. package/dist/Avatar/index.js +1 -1
  16. package/dist/AvatarGroup/AvatarGroup.d.ts +9 -2
  17. package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
  18. package/dist/AvatarGroup/AvatarGroup.js +8 -4
  19. package/dist/AvatarGroup/AvatarGroupContext.d.ts +2 -1
  20. package/dist/AvatarGroup/AvatarGroupContext.d.ts.map +1 -1
  21. package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
  22. package/dist/AvatarGroup/AvatarGroupOverflow.js +10 -6
  23. package/dist/Banner/Banner.d.ts +49 -15
  24. package/dist/Banner/Banner.d.ts.map +1 -1
  25. package/dist/Banner/Banner.js +62 -20
  26. package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
  27. package/dist/BottomSheet/BottomSheet.js +17 -4
  28. package/dist/BottomSheet/BottomSheetSwitcher.d.ts.map +1 -1
  29. package/dist/BottomSheet/BottomSheetSwitcher.js +3 -2
  30. package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
  31. package/dist/Breadcrumbs/BreadcrumbItem.js +11 -10
  32. package/dist/Button/Button.d.ts.map +1 -1
  33. package/dist/Button/Button.js +11 -6
  34. package/dist/ButtonGroup/ButtonGroup.d.ts +5 -1
  35. package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
  36. package/dist/ButtonGroup/ButtonGroup.js +26 -7
  37. package/dist/Calendar/Calendar.d.ts +7 -3
  38. package/dist/Calendar/Calendar.d.ts.map +1 -1
  39. package/dist/Calendar/Calendar.js +21 -23
  40. package/dist/Calendar/getInitialFocusDate.d.ts +46 -0
  41. package/dist/Calendar/getInitialFocusDate.d.ts.map +1 -0
  42. package/dist/Calendar/getInitialFocusDate.js +62 -0
  43. package/dist/Calendar/styles.d.ts +5 -14
  44. package/dist/Calendar/styles.d.ts.map +1 -1
  45. package/dist/Calendar/styles.js +15 -15
  46. package/dist/Card/Card.d.ts +12 -12
  47. package/dist/Card/Card.d.ts.map +1 -1
  48. package/dist/Card/Card.js +17 -9
  49. package/dist/Card/index.d.ts +35 -1
  50. package/dist/Card/index.d.ts.map +1 -1
  51. package/dist/Card/index.js +21 -1
  52. package/dist/Carousel/Carousel.d.ts.map +1 -1
  53. package/dist/Carousel/Carousel.js +3 -3
  54. package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
  55. package/dist/Chat/ChatComposerInput.js +2 -3
  56. package/dist/Chat/ChatLayout.d.ts.map +1 -1
  57. package/dist/Chat/ChatLayout.js +3 -3
  58. package/dist/Chat/ChatMessageList.d.ts +22 -3
  59. package/dist/Chat/ChatMessageList.d.ts.map +1 -1
  60. package/dist/Chat/ChatMessageList.js +6 -3
  61. package/dist/Chat/ChatTokenizedText.d.ts +2 -0
  62. package/dist/Chat/ChatTokenizedText.d.ts.map +1 -1
  63. package/dist/Chat/ChatTokenizedText.js +11 -6
  64. package/dist/Chat/useChatComposerTokens.js +1 -1
  65. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  66. package/dist/CheckboxInput/CheckboxInput.js +10 -3
  67. package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
  68. package/dist/ClickableCard/ClickableCard.js +3 -3
  69. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  70. package/dist/CodeBlock/CodeBlock.js +15 -4
  71. package/dist/CodeBlock/highlightRanges.js +1 -1
  72. package/dist/CodeBlock/highlightStyles.js +13 -13
  73. package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
  74. package/dist/CommandPalette/CommandPaletteInput.js +3 -2
  75. package/dist/CommandPalette/CommandPaletteItem.d.ts.map +1 -1
  76. package/dist/CommandPalette/CommandPaletteItem.js +3 -2
  77. package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
  78. package/dist/ComplexSelector/ComplexSelector.js +1 -3
  79. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  80. package/dist/ContextMenu/ContextMenu.js +4 -3
  81. package/dist/DateInput/DateInput.d.ts +43 -0
  82. package/dist/DateInput/DateInput.d.ts.map +1 -1
  83. package/dist/DateInput/DateInput.js +22 -2
  84. package/dist/DateInput/NativeDateField.d.ts +10 -0
  85. package/dist/DateInput/NativeDateField.d.ts.map +1 -0
  86. package/dist/DateInput/NativeDateField.js +494 -0
  87. package/dist/DateInput/TouchDateField.d.ts.map +1 -1
  88. package/dist/DateInput/TouchDateField.js +82 -23
  89. package/dist/DateInput/index.d.ts +1 -1
  90. package/dist/DateInput/index.d.ts.map +1 -1
  91. package/dist/DateInput/nativeDateSegments.d.ts +22 -0
  92. package/dist/DateInput/nativeDateSegments.d.ts.map +1 -0
  93. package/dist/DateInput/nativeDateSegments.js +111 -0
  94. package/dist/DateRangeInput/DateRangeInput.d.ts +4 -2
  95. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  96. package/dist/DateTimeInput/DateTimeInput.d.ts +21 -1
  97. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  98. package/dist/DateTimeInput/DateTimeInput.js +406 -12
  99. package/dist/DateTimeInput/index.d.ts +1 -1
  100. package/dist/DateTimeInput/index.d.ts.map +1 -1
  101. package/dist/Dialog/Dialog.d.ts +21 -1
  102. package/dist/Dialog/Dialog.d.ts.map +1 -1
  103. package/dist/Dialog/Dialog.js +110 -58
  104. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  105. package/dist/DropdownMenu/DropdownMenu.js +4 -13
  106. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
  107. package/dist/DropdownMenu/DropdownMenuSubMenu.js +6 -5
  108. package/dist/Field/FieldLabel.d.ts.map +1 -1
  109. package/dist/Field/FieldLabel.js +9 -1
  110. package/dist/Field/InputClearButton.d.ts +9 -3
  111. package/dist/Field/InputClearButton.d.ts.map +1 -1
  112. package/dist/Field/InputClearButton.js +14 -3
  113. package/dist/FileInput/FileInput.d.ts.map +1 -1
  114. package/dist/FileInput/FileInput.js +3 -2
  115. package/dist/Heading/Heading.d.ts.map +1 -1
  116. package/dist/Heading/Heading.js +6 -3
  117. package/dist/HoverCard/HoverCard.d.ts +6 -0
  118. package/dist/HoverCard/HoverCard.d.ts.map +1 -1
  119. package/dist/HoverCard/HoverCard.js +104 -3
  120. package/dist/HoverCard/useHoverCard.d.ts +19 -2
  121. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  122. package/dist/HoverCard/useHoverCard.js +74 -26
  123. package/dist/Indicator/CheckboxIndicator.d.ts.map +1 -1
  124. package/dist/Indicator/CheckboxIndicator.js +6 -2
  125. package/dist/Item/Item.d.ts.map +1 -1
  126. package/dist/Item/Item.js +4 -2
  127. package/dist/Kbd/Kbd.d.ts.map +1 -1
  128. package/dist/Kbd/Kbd.js +2 -19
  129. package/dist/Layer/LayerDepthContext.d.ts +52 -0
  130. package/dist/Layer/LayerDepthContext.d.ts.map +1 -0
  131. package/dist/Layer/LayerDepthContext.js +66 -0
  132. package/dist/Layer/gestureCounter.d.ts +8 -0
  133. package/dist/Layer/gestureCounter.d.ts.map +1 -0
  134. package/dist/Layer/gestureCounter.js +53 -0
  135. package/dist/Layer/index.d.ts +3 -0
  136. package/dist/Layer/index.d.ts.map +1 -1
  137. package/dist/Layer/index.js +4 -0
  138. package/dist/Layer/layerStack.d.ts +98 -0
  139. package/dist/Layer/layerStack.d.ts.map +1 -0
  140. package/dist/Layer/layerStack.js +306 -0
  141. package/dist/Layer/useLayer.d.ts +23 -13
  142. package/dist/Layer/useLayer.d.ts.map +1 -1
  143. package/dist/Layer/useLayer.js +128 -8
  144. package/dist/Layer/useLayerDismissal.d.ts +93 -0
  145. package/dist/Layer/useLayerDismissal.d.ts.map +1 -0
  146. package/dist/Layer/useLayerDismissal.js +91 -0
  147. package/dist/Lightbox/Lightbox.d.ts +1 -0
  148. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  149. package/dist/Lightbox/Lightbox.js +103 -81
  150. package/dist/List/List.d.ts +1 -1
  151. package/dist/List/List.d.ts.map +1 -1
  152. package/dist/List/List.js +15 -4
  153. package/dist/Markdown/Markdown.d.ts +1 -1
  154. package/dist/Markdown/Markdown.d.ts.map +1 -1
  155. package/dist/Markdown/Markdown.js +20 -7
  156. package/dist/Markdown/index.d.ts +1 -1
  157. package/dist/Markdown/index.d.ts.map +1 -1
  158. package/dist/Markdown/parser.d.ts +38 -1
  159. package/dist/Markdown/parser.d.ts.map +1 -1
  160. package/dist/Markdown/parser.js +182 -32
  161. package/dist/MetadataList/MetadataListItem.d.ts +1 -1
  162. package/dist/MetadataList/MetadataListItem.d.ts.map +1 -1
  163. package/dist/MetadataList/MetadataListItem.js +4 -1
  164. package/dist/MobileNav/MobileNav.d.ts +6 -1
  165. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  166. package/dist/MobileNav/MobileNav.js +61 -36
  167. package/dist/MultiSelector/MultiSelector.d.ts +32 -1
  168. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  169. package/dist/MultiSelector/MultiSelector.js +73 -15
  170. package/dist/MultiSelector/hooks.d.ts +7 -1
  171. package/dist/MultiSelector/hooks.d.ts.map +1 -1
  172. package/dist/MultiSelector/hooks.js +3 -2
  173. package/dist/MultiSelector/index.d.ts +1 -1
  174. package/dist/MultiSelector/index.d.ts.map +1 -1
  175. package/dist/NavIcon/NavIcon.d.ts.map +1 -1
  176. package/dist/NavIcon/NavIcon.js +5 -1
  177. package/dist/NavMenu/NavHeadingMenu.d.ts +1 -1
  178. package/dist/NavMenu/NavHeadingMenu.d.ts.map +1 -1
  179. package/dist/NavMenu/NavHeadingMenu.js +9 -5
  180. package/dist/NumberInput/NumberInput.d.ts +6 -1
  181. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  182. package/dist/NumberInput/NumberInput.js +54 -104
  183. package/dist/NumberInput/numberInputCommit.d.ts +34 -0
  184. package/dist/NumberInput/numberInputCommit.d.ts.map +1 -0
  185. package/dist/NumberInput/numberInputCommit.js +71 -0
  186. package/dist/NumberInput/numberParser.d.ts +64 -0
  187. package/dist/NumberInput/numberParser.d.ts.map +1 -0
  188. package/dist/NumberInput/numberParser.js +350 -0
  189. package/dist/Outline/Outline.d.ts.map +1 -1
  190. package/dist/Outline/Outline.js +3 -2
  191. package/dist/OverflowList/OverflowList.d.ts.map +1 -1
  192. package/dist/OverflowList/OverflowList.js +3 -2
  193. package/dist/Overlay/Overlay.d.ts.map +1 -1
  194. package/dist/Overlay/Overlay.js +3 -2
  195. package/dist/Popover/Popover.d.ts.map +1 -1
  196. package/dist/Popover/Popover.js +1 -9
  197. package/dist/Popover/usePopover.d.ts +7 -41
  198. package/dist/Popover/usePopover.d.ts.map +1 -1
  199. package/dist/Popover/usePopover.js +40 -21
  200. package/dist/PowerSearch/PowerSearch.d.ts +8 -2
  201. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  202. package/dist/PowerSearch/PowerSearch.js +19 -6
  203. package/dist/PowerSearch/PowerSearchEditPopover.d.ts +3 -1
  204. package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
  205. package/dist/PowerSearch/PowerSearchEditPopover.js +28 -6
  206. package/dist/PowerSearch/PowerSearchValueEditor.d.ts +3 -1
  207. package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
  208. package/dist/PowerSearch/PowerSearchValueEditor.js +110 -27
  209. package/dist/PowerSearch/types.d.ts +2 -0
  210. package/dist/PowerSearch/types.d.ts.map +1 -1
  211. package/dist/PowerSearch/usePowerSearchSource.d.ts +6 -1
  212. package/dist/PowerSearch/usePowerSearchSource.d.ts.map +1 -1
  213. package/dist/PowerSearch/usePowerSearchSource.js +14 -5
  214. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  215. package/dist/ProgressBar/ProgressBar.js +18 -5
  216. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  217. package/dist/Resizable/ResizeHandle.js +3 -2
  218. package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
  219. package/dist/SegmentedControl/SegmentedControl.js +3 -2
  220. package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
  221. package/dist/SelectableCard/SelectableCard.js +12 -3
  222. package/dist/Selector/Selector.d.ts +18 -1
  223. package/dist/Selector/Selector.d.ts.map +1 -1
  224. package/dist/Selector/Selector.js +91 -18
  225. package/dist/Selector/hooks.d.ts +7 -1
  226. package/dist/Selector/hooks.d.ts.map +1 -1
  227. package/dist/Selector/hooks.js +3 -2
  228. package/dist/SideNav/SideNav.d.ts.map +1 -1
  229. package/dist/SideNav/SideNav.js +4 -3
  230. package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
  231. package/dist/SideNav/SideNavHeading.js +8 -7
  232. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  233. package/dist/SideNav/SideNavItem.js +4 -3
  234. package/dist/Slider/Slider.d.ts.map +1 -1
  235. package/dist/Slider/Slider.js +37 -5
  236. package/dist/Spinner/Spinner.d.ts +3 -3
  237. package/dist/Spinner/Spinner.d.ts.map +1 -1
  238. package/dist/Spinner/Spinner.js +130 -78
  239. package/dist/StatusDot/StatusDot.d.ts.map +1 -1
  240. package/dist/StatusDot/StatusDot.js +6 -1
  241. package/dist/Stepper/Step.d.ts +140 -0
  242. package/dist/Stepper/Step.d.ts.map +1 -0
  243. package/dist/Stepper/Step.js +1045 -0
  244. package/dist/Stepper/StepStatus.d.ts +24 -0
  245. package/dist/Stepper/StepStatus.d.ts.map +1 -0
  246. package/dist/Stepper/StepStatus.js +1 -0
  247. package/dist/Stepper/Stepper.d.ts +93 -0
  248. package/dist/Stepper/Stepper.d.ts.map +1 -0
  249. package/dist/Stepper/Stepper.js +184 -0
  250. package/dist/Stepper/StepperContext.d.ts +41 -0
  251. package/dist/Stepper/StepperContext.d.ts.map +1 -0
  252. package/dist/Stepper/StepperContext.js +34 -0
  253. package/dist/Stepper/index.d.ts +8 -0
  254. package/dist/Stepper/index.d.ts.map +1 -0
  255. package/dist/Stepper/index.js +7 -0
  256. package/dist/Stepper/stepper.stylex.d.ts +15 -0
  257. package/dist/Stepper/stepper.stylex.d.ts.map +1 -0
  258. package/dist/Stepper/stepper.stylex.js +20 -0
  259. package/dist/Switch/Switch.d.ts.map +1 -1
  260. package/dist/Switch/Switch.js +8 -3
  261. package/dist/TabList/Tab.d.ts +15 -2
  262. package/dist/TabList/Tab.d.ts.map +1 -1
  263. package/dist/TabList/Tab.js +32 -7
  264. package/dist/TabList/TabList.d.ts +46 -7
  265. package/dist/TabList/TabList.d.ts.map +1 -1
  266. package/dist/TabList/TabList.js +353 -23
  267. package/dist/TabList/TabListContext.d.ts +11 -1
  268. package/dist/TabList/TabListContext.d.ts.map +1 -1
  269. package/dist/TabList/TabListContext.js +11 -2
  270. package/dist/TabList/TabMenu.d.ts.map +1 -1
  271. package/dist/TabList/TabMenu.js +3 -2
  272. package/dist/TabList/index.d.ts +2 -2
  273. package/dist/TabList/index.d.ts.map +1 -1
  274. package/dist/Table/BaseTable.d.ts.map +1 -1
  275. package/dist/Table/BaseTable.js +10 -2
  276. package/dist/Table/Table.d.ts.map +1 -1
  277. package/dist/Table/Table.js +3 -6
  278. package/dist/Table/TableRow.d.ts +16 -5
  279. package/dist/Table/TableRow.d.ts.map +1 -1
  280. package/dist/Table/TableRow.js +16 -5
  281. package/dist/Table/plugins/filtering/useTableFiltering.d.ts.map +1 -1
  282. package/dist/Table/plugins/filtering/useTableFiltering.js +73 -4
  283. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts +26 -0
  284. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  285. package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +54 -11
  286. package/dist/Table/plugins/pagination/useTablePagination.d.ts +3 -0
  287. package/dist/Table/plugins/pagination/useTablePagination.d.ts.map +1 -1
  288. package/dist/Table/plugins/pagination/useTablePagination.js +21 -4
  289. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  290. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +7 -2
  291. package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts.map +1 -1
  292. package/dist/Table/plugins/rowStatus/useTableRowStatus.js +10 -3
  293. package/dist/Table/plugins/selection/useTableSelection.d.ts +16 -0
  294. package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
  295. package/dist/Table/plugins/selection/useTableSelection.js +43 -5
  296. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -1
  297. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +3 -4
  298. package/dist/Table/types.d.ts +22 -4
  299. package/dist/Table/types.d.ts.map +1 -1
  300. package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
  301. package/dist/Table/useBaseTablePlugins.js +5 -0
  302. package/dist/Text/Text.d.ts.map +1 -1
  303. package/dist/Text/Text.js +6 -3
  304. package/dist/TextArea/TextArea.d.ts.map +1 -1
  305. package/dist/TextArea/TextArea.js +16 -10
  306. package/dist/TextInput/TextInput.d.ts.map +1 -1
  307. package/dist/TextInput/TextInput.js +3 -2
  308. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  309. package/dist/TimeInput/TimeInput.js +3 -2
  310. package/dist/Timestamp/Timestamp.d.ts +1 -1
  311. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  312. package/dist/Timestamp/Timestamp.js +15 -21
  313. package/dist/Toast/Toast.d.ts.map +1 -1
  314. package/dist/Toast/Toast.js +22 -7
  315. package/dist/Toast/ToastViewport.d.ts +1 -0
  316. package/dist/Toast/ToastViewport.d.ts.map +1 -1
  317. package/dist/Toast/ToastViewport.js +71 -18
  318. package/dist/Token/Token.d.ts +1 -1
  319. package/dist/Token/Token.d.ts.map +1 -1
  320. package/dist/Token/Token.js +20 -9
  321. package/dist/Token/TokenLink.d.ts +1 -1
  322. package/dist/Token/TokenLink.d.ts.map +1 -1
  323. package/dist/Token/TokenLink.js +7 -4
  324. package/dist/Tokenizer/Tokenizer.d.ts +14 -1
  325. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  326. package/dist/Tokenizer/Tokenizer.js +33 -21
  327. package/dist/Tooltip/Tooltip.d.ts +5 -0
  328. package/dist/Tooltip/Tooltip.d.ts.map +1 -1
  329. package/dist/Tooltip/useTooltip.d.ts +5 -0
  330. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  331. package/dist/Tooltip/useTooltip.js +39 -24
  332. package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
  333. package/dist/TopNav/TopNavHeading.js +5 -4
  334. package/dist/TopNav/TopNavMegaMenu.d.ts +1 -1
  335. package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
  336. package/dist/TopNav/TopNavMegaMenu.js +31 -11
  337. package/dist/TopNav/TopNavMenu.d.ts +1 -1
  338. package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
  339. package/dist/TopNav/TopNavMenu.js +22 -7
  340. package/dist/TreeList/TreeList.d.ts +1 -1
  341. package/dist/TreeList/TreeList.d.ts.map +1 -1
  342. package/dist/TreeList/TreeList.js +7 -2
  343. package/dist/Typeahead/BaseTypeahead.d.ts +35 -0
  344. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  345. package/dist/Typeahead/BaseTypeahead.js +119 -37
  346. package/dist/Typeahead/Typeahead.d.ts +8 -1
  347. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  348. package/dist/Typeahead/Typeahead.js +5 -2
  349. package/dist/Typeahead/TypeaheadItem.d.ts +1 -1
  350. package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
  351. package/dist/Typeahead/TypeaheadItem.js +7 -2
  352. package/dist/astryx.css +113 -11
  353. package/dist/hooks/index.d.ts +1 -0
  354. package/dist/hooks/index.d.ts.map +1 -1
  355. package/dist/hooks/index.js +1 -0
  356. package/dist/hooks/useFocusTrap.d.ts +7 -4
  357. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  358. package/dist/hooks/useFocusTrap.js +60 -95
  359. package/dist/hooks/useHotkeys.d.ts.map +1 -1
  360. package/dist/hooks/useHotkeys.js +3 -18
  361. package/dist/hooks/useMergedRefs.d.ts +18 -0
  362. package/dist/hooks/useMergedRefs.d.ts.map +1 -0
  363. package/dist/hooks/useMergedRefs.js +25 -0
  364. package/dist/index.d.ts +1 -0
  365. package/dist/index.d.ts.map +1 -1
  366. package/dist/index.js +1 -0
  367. package/dist/theme/Theme.d.ts.map +1 -1
  368. package/dist/theme/Theme.js +46 -10
  369. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  370. package/dist/theme/derivedVarRegistry.js +24 -4
  371. package/dist/theme/generateThemeRules.d.ts +21 -0
  372. package/dist/theme/generateThemeRules.d.ts.map +1 -1
  373. package/dist/theme/generateThemeRules.js +26 -0
  374. package/dist/theme/syntax/tokens.d.ts +1 -1
  375. package/dist/theme/syntax/tokens.d.ts.map +1 -1
  376. package/dist/theme/syntax/tokens.js +5 -2
  377. package/dist/utils/groupItems.d.ts +5 -1
  378. package/dist/utils/groupItems.d.ts.map +1 -1
  379. package/dist/utils/groupItems.js +9 -9
  380. package/dist/utils/index.d.ts +1 -1
  381. package/dist/utils/index.d.ts.map +1 -1
  382. package/dist/utils/isApplePlatform.d.ts +18 -0
  383. package/dist/utils/isApplePlatform.d.ts.map +1 -0
  384. package/dist/utils/isApplePlatform.js +37 -0
  385. package/dist/utils/sharedResizeObserver.d.ts.map +1 -1
  386. package/dist/utils/sharedResizeObserver.js +10 -1
  387. package/dist/utils/timeParser.d.ts +1 -1
  388. package/dist/utils/timeParser.d.ts.map +1 -1
  389. package/dist/utils/timeParser.js +26 -12
  390. package/locales/af-ZA.json +6 -6
  391. package/locales/ar-SA.json +6 -6
  392. package/locales/ca-ES.json +5 -5
  393. package/locales/cs-CZ.json +6 -6
  394. package/locales/da-DK.json +6 -6
  395. package/locales/de-DE.json +6 -6
  396. package/locales/el-GR.json +6 -6
  397. package/locales/en.json +163 -11
  398. package/locales/es-ES.json +5 -5
  399. package/locales/fi-FI.json +6 -6
  400. package/locales/fr-FR.json +6 -6
  401. package/locales/he-IL.json +6 -6
  402. package/locales/hu-HU.json +6 -6
  403. package/locales/it-IT.json +6 -6
  404. package/locales/ja-JP.json +6 -6
  405. package/locales/ko-KR.json +6 -6
  406. package/locales/nl-NL.json +6 -6
  407. package/locales/no-NO.json +6 -6
  408. package/locales/pl-PL.json +6 -6
  409. package/locales/pseudo.json +114 -0
  410. package/locales/pt-BR.json +6 -6
  411. package/locales/pt-PT.json +6 -6
  412. package/locales/ro-RO.json +6 -6
  413. package/locales/ru-RU.json +6 -6
  414. package/locales/sr-SP.json +6 -6
  415. package/locales/sv-SE.json +6 -6
  416. package/locales/tr-TR.json +6 -6
  417. package/locales/uk-UA.json +6 -6
  418. package/locales/vi-VN.json +6 -6
  419. package/locales/zh-CN.json +6 -6
  420. package/locales/zh-TW.json +6 -6
  421. package/package.json +8 -3
  422. package/src/AlertDialog/AlertDialog.doc.mjs +114 -30
  423. package/src/AlertDialog/AlertDialog.test.tsx +211 -2
  424. package/src/AlertDialog/AlertDialog.tsx +62 -20
  425. package/src/AppShell/AppShell.tsx +3 -2
  426. package/src/AspectRatio/AspectRatio.doc.mjs +6 -3
  427. package/src/AspectRatio/AspectRatio.test.tsx +57 -10
  428. package/src/AspectRatio/AspectRatio.tsx +40 -1
  429. package/src/Avatar/Avatar.doc.mjs +14 -3
  430. package/src/Avatar/Avatar.test.tsx +97 -0
  431. package/src/Avatar/Avatar.tsx +125 -52
  432. package/src/Avatar/index.ts +2 -2
  433. package/src/AvatarGroup/AvatarGroup.doc.mjs +8 -2
  434. package/src/AvatarGroup/AvatarGroup.test.tsx +24 -0
  435. package/src/AvatarGroup/AvatarGroup.tsx +15 -6
  436. package/src/AvatarGroup/AvatarGroupContext.ts +5 -3
  437. package/src/AvatarGroup/AvatarGroupOverflow.tsx +10 -4
  438. package/src/Banner/Banner.doc.mjs +22 -11
  439. package/src/Banner/Banner.test.tsx +177 -25
  440. package/src/Banner/Banner.tsx +93 -27
  441. package/src/BottomSheet/BottomSheet.test.tsx +123 -0
  442. package/src/BottomSheet/BottomSheet.tsx +17 -4
  443. package/src/BottomSheet/BottomSheetSwitcher.tsx +3 -2
  444. package/src/Breadcrumbs/BreadcrumbItem.tsx +9 -5
  445. package/src/Button/Button.doc.mjs +24 -1
  446. package/src/Button/Button.test.tsx +32 -4
  447. package/src/Button/Button.tsx +12 -5
  448. package/src/ButtonGroup/ButtonGroup.doc.mjs +10 -1
  449. package/src/ButtonGroup/ButtonGroup.test.tsx +404 -1
  450. package/src/ButtonGroup/ButtonGroup.tsx +23 -5
  451. package/src/Calendar/Calendar.doc.mjs +7 -6
  452. package/src/Calendar/Calendar.test.tsx +143 -0
  453. package/src/Calendar/Calendar.tsx +30 -26
  454. package/src/Calendar/getInitialFocusDate.test.ts +94 -0
  455. package/src/Calendar/getInitialFocusDate.ts +93 -0
  456. package/src/Calendar/styles.ts +49 -31
  457. package/src/Card/Card.doc.mjs +10 -7
  458. package/src/Card/Card.test.tsx +113 -19
  459. package/src/Card/Card.tsx +67 -89
  460. package/src/Card/index.ts +36 -1
  461. package/src/Carousel/Carousel.tsx +3 -2
  462. package/src/Chat/ChatComposerInput.tsx +5 -1
  463. package/src/Chat/ChatLayout.tsx +3 -2
  464. package/src/Chat/ChatMessageList.doc.mjs +9 -1
  465. package/src/Chat/ChatMessageList.test.tsx +46 -0
  466. package/src/Chat/ChatMessageList.tsx +28 -4
  467. package/src/Chat/ChatTokenizedText.tsx +17 -10
  468. package/src/Chat/useChatComposerTokens.ts +1 -1
  469. package/src/CheckboxInput/CheckboxInput.doc.mjs +2 -0
  470. package/src/CheckboxInput/CheckboxInput.test.tsx +15 -0
  471. package/src/CheckboxInput/CheckboxInput.tsx +8 -2
  472. package/src/ClickableCard/ClickableCard.tsx +3 -2
  473. package/src/CodeBlock/CodeBlock.doc.mjs +16 -4
  474. package/src/CodeBlock/CodeBlock.test.tsx +37 -0
  475. package/src/CodeBlock/CodeBlock.tsx +20 -4
  476. package/src/CodeBlock/highlightRanges.ts +1 -1
  477. package/src/CodeBlock/highlightStyles.ts +13 -13
  478. package/src/CommandPalette/CommandPaletteInput.tsx +3 -2
  479. package/src/CommandPalette/CommandPaletteItem.tsx +3 -2
  480. package/src/ComplexSelector/ComplexSelector.test.tsx +32 -0
  481. package/src/ComplexSelector/ComplexSelector.tsx +1 -3
  482. package/src/ContextMenu/ContextMenu.doc.mjs +5 -0
  483. package/src/ContextMenu/ContextMenu.tsx +4 -3
  484. package/src/DateInput/DateInput.doc.mjs +16 -0
  485. package/src/DateInput/DateInput.tsx +55 -2
  486. package/src/DateInput/DateInputTouch.test.tsx +146 -32
  487. package/src/DateInput/NativeDateField.test.tsx +635 -0
  488. package/src/DateInput/NativeDateField.tsx +641 -0
  489. package/src/DateInput/TouchDateField.tsx +108 -24
  490. package/src/DateInput/index.ts +1 -0
  491. package/src/DateInput/nativeDateSegments.ts +127 -0
  492. package/src/DateRangeInput/DateRangeInput.doc.mjs +2 -2
  493. package/src/DateRangeInput/DateRangeInput.test.tsx +22 -0
  494. package/src/DateRangeInput/DateRangeInput.tsx +4 -2
  495. package/src/DateTimeInput/DateTimeInput.doc.mjs +18 -0
  496. package/src/DateTimeInput/DateTimeInput.test.tsx +1088 -0
  497. package/src/DateTimeInput/DateTimeInput.tsx +556 -24
  498. package/src/DateTimeInput/index.ts +1 -0
  499. package/src/Dialog/Dialog.doc.mjs +8 -3
  500. package/src/Dialog/Dialog.test.tsx +429 -2
  501. package/src/Dialog/Dialog.tsx +133 -58
  502. package/src/DropdownMenu/DropdownMenu.doc.mjs +6 -0
  503. package/src/DropdownMenu/DropdownMenu.test.tsx +44 -10
  504. package/src/DropdownMenu/DropdownMenu.tsx +4 -13
  505. package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +8 -5
  506. package/src/DropdownMenu/DropdownMenuSubMenu.tsx +8 -11
  507. package/src/Field/Field.doc.mjs +13 -2
  508. package/src/Field/FieldLabel.test.tsx +29 -0
  509. package/src/Field/FieldLabel.tsx +7 -0
  510. package/src/Field/InputClearButton.test.tsx +15 -1
  511. package/src/Field/InputClearButton.tsx +28 -4
  512. package/src/FileInput/FileInput.tsx +3 -2
  513. package/src/Heading/Heading.test.tsx +23 -1
  514. package/src/Heading/Heading.tsx +6 -3
  515. package/src/HoverCard/HoverCard.doc.mjs +13 -2
  516. package/src/HoverCard/HoverCard.test.tsx +154 -4
  517. package/src/HoverCard/HoverCard.tsx +143 -3
  518. package/src/HoverCard/useHoverCard.tsx +104 -33
  519. package/src/Indicator/CheckboxIndicator.tsx +14 -8
  520. package/src/Indicator/Indicator.doc.mjs +2 -0
  521. package/src/Item/Item.tsx +5 -4
  522. package/src/Kbd/Kbd.tsx +2 -19
  523. package/src/Layer/LayerDepthContext.tsx +62 -0
  524. package/src/Layer/gestureCounter.ts +57 -0
  525. package/src/Layer/index.ts +9 -0
  526. package/src/Layer/layerDismissalFamilies.test.tsx +359 -0
  527. package/src/Layer/layerDismissalInvariants.test.tsx +417 -0
  528. package/src/Layer/layerStack.ts +362 -0
  529. package/src/Layer/useLayer.test.tsx +324 -15
  530. package/src/Layer/useLayer.tsx +164 -8
  531. package/src/Layer/useLayerDismissal.test.tsx +469 -0
  532. package/src/Layer/useLayerDismissal.ts +173 -0
  533. package/src/Layout/Layout.doc.mjs +2 -2
  534. package/src/Layout/__tests__/edgeCompensation.test.tsx +1 -1
  535. package/src/Lightbox/Lightbox.doc.mjs +12 -0
  536. package/src/Lightbox/Lightbox.tsx +124 -102
  537. package/src/Link/Link.doc.mjs +39 -0
  538. package/src/List/List.test.tsx +38 -0
  539. package/src/List/List.tsx +8 -1
  540. package/src/Markdown/Markdown.doc.mjs +5 -0
  541. package/src/Markdown/Markdown.test.tsx +37 -0
  542. package/src/Markdown/Markdown.tsx +16 -5
  543. package/src/Markdown/incremental.test.ts +16 -2
  544. package/src/Markdown/index.ts +1 -0
  545. package/src/Markdown/parser.perf.test.ts +96 -1
  546. package/src/Markdown/parser.test.ts +178 -2
  547. package/src/Markdown/parser.ts +253 -32
  548. package/src/MetadataList/MetadataList.test.tsx +75 -2
  549. package/src/MetadataList/MetadataListItem.tsx +5 -2
  550. package/src/MobileNav/MobileNav.tsx +62 -36
  551. package/src/MoreMenu/MoreMenu.doc.mjs +7 -1
  552. package/src/MultiSelector/MultiSelector.doc.mjs +49 -1
  553. package/src/MultiSelector/MultiSelector.test.tsx +311 -0
  554. package/src/MultiSelector/MultiSelector.tsx +151 -15
  555. package/src/MultiSelector/hooks.ts +9 -2
  556. package/src/MultiSelector/index.ts +1 -0
  557. package/src/NavIcon/NavIcon.doc.mjs +8 -2
  558. package/src/NavIcon/NavIcon.test.tsx +9 -0
  559. package/src/NavIcon/NavIcon.tsx +5 -1
  560. package/src/NavMenu/NavHeadingMenu.test.tsx +30 -0
  561. package/src/NavMenu/NavHeadingMenu.tsx +9 -5
  562. package/src/NumberInput/NumberInput.doc.mjs +31 -7
  563. package/src/NumberInput/NumberInput.test.tsx +436 -8
  564. package/src/NumberInput/NumberInput.tsx +62 -114
  565. package/src/NumberInput/numberInputCommit.test.ts +72 -0
  566. package/src/NumberInput/numberInputCommit.ts +103 -0
  567. package/src/NumberInput/numberParser.docblock.test.ts +234 -0
  568. package/src/NumberInput/numberParser.test.ts +222 -0
  569. package/src/NumberInput/numberParser.ts +403 -0
  570. package/src/Outline/Outline.tsx +3 -2
  571. package/src/OverflowList/OverflowList.tsx +3 -2
  572. package/src/Overlay/Overlay.tsx +3 -2
  573. package/src/Pagination/Pagination.test.tsx +3 -2
  574. package/src/Popover/Popover.test.tsx +14 -0
  575. package/src/Popover/Popover.tsx +1 -9
  576. package/src/Popover/usePopover.tsx +57 -32
  577. package/src/PowerSearch/PowerSearch.doc.mjs +160 -28
  578. package/src/PowerSearch/PowerSearch.test.tsx +240 -1
  579. package/src/PowerSearch/PowerSearch.tsx +34 -5
  580. package/src/PowerSearch/PowerSearchEditPopover.test.tsx +288 -0
  581. package/src/PowerSearch/PowerSearchEditPopover.tsx +29 -2
  582. package/src/PowerSearch/PowerSearchValueEditor.test.tsx +111 -1
  583. package/src/PowerSearch/PowerSearchValueEditor.tsx +124 -10
  584. package/src/PowerSearch/types.ts +2 -0
  585. package/src/PowerSearch/usePowerSearchSource.test.ts +82 -2
  586. package/src/PowerSearch/usePowerSearchSource.ts +13 -3
  587. package/src/ProgressBar/ProgressBar.doc.mjs +42 -6
  588. package/src/ProgressBar/ProgressBar.test.tsx +24 -0
  589. package/src/ProgressBar/ProgressBar.tsx +28 -8
  590. package/src/Resizable/ResizeHandle.tsx +3 -2
  591. package/src/SegmentedControl/SegmentedControl.tsx +3 -2
  592. package/src/SelectableCard/SelectableCard.doc.mjs +3 -0
  593. package/src/SelectableCard/SelectableCard.tsx +19 -2
  594. package/src/Selector/Selector.doc.mjs +26 -1
  595. package/src/Selector/Selector.test.tsx +346 -1
  596. package/src/Selector/Selector.tsx +148 -21
  597. package/src/Selector/hooks.ts +17 -2
  598. package/src/SideNav/SideNav.doc.mjs +6 -6
  599. package/src/SideNav/SideNav.tsx +4 -2
  600. package/src/SideNav/SideNavHeading.tsx +12 -12
  601. package/src/SideNav/SideNavItem.tsx +4 -2
  602. package/src/Slider/Slider.test.tsx +106 -1
  603. package/src/Slider/Slider.tsx +55 -3
  604. package/src/Spinner/Spinner.test.tsx +147 -1
  605. package/src/Spinner/Spinner.tsx +120 -101
  606. package/src/StatusDot/StatusDot.doc.mjs +8 -2
  607. package/src/StatusDot/StatusDot.test.tsx +9 -0
  608. package/src/StatusDot/StatusDot.tsx +7 -1
  609. package/src/Stepper/Step.doc.mjs +98 -0
  610. package/src/Stepper/Step.tsx +1638 -0
  611. package/src/Stepper/StepStatus.ts +26 -0
  612. package/src/Stepper/Stepper.doc.mjs +370 -0
  613. package/src/Stepper/Stepper.test.tsx +1024 -0
  614. package/src/Stepper/Stepper.tsx +258 -0
  615. package/src/Stepper/StepperContext.ts +71 -0
  616. package/src/Stepper/index.ts +18 -0
  617. package/src/Stepper/stepper.stylex.ts +19 -0
  618. package/src/Switch/Switch.doc.mjs +2 -0
  619. package/src/Switch/Switch.test.tsx +10 -0
  620. package/src/Switch/Switch.tsx +6 -2
  621. package/src/TabList/Tab.doc.mjs +13 -1
  622. package/src/TabList/Tab.tsx +67 -7
  623. package/src/TabList/TabList.doc.mjs +22 -6
  624. package/src/TabList/TabList.test.tsx +559 -0
  625. package/src/TabList/TabList.tsx +490 -22
  626. package/src/TabList/TabListContext.ts +13 -2
  627. package/src/TabList/TabMenu.tsx +3 -2
  628. package/src/TabList/index.ts +6 -2
  629. package/src/Table/BaseTable.tsx +12 -4
  630. package/src/Table/Table.doc.mjs +9 -2
  631. package/src/Table/Table.test.tsx +132 -14
  632. package/src/Table/Table.tsx +3 -8
  633. package/src/Table/TableBody.doc.mjs +40 -0
  634. package/src/Table/TableFooter.doc.mjs +40 -0
  635. package/src/Table/TableHeader.doc.mjs +40 -0
  636. package/src/Table/TableRow.tsx +16 -5
  637. package/src/Table/plugins/filtering/useTableFiltering.test.tsx +44 -6
  638. package/src/Table/plugins/filtering/useTableFiltering.tsx +100 -4
  639. package/src/Table/plugins/groupedRows/useTableGroupedRows-perf.test.tsx +112 -0
  640. package/src/Table/plugins/groupedRows/useTableGroupedRows.test.tsx +100 -0
  641. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +67 -12
  642. package/src/Table/plugins/pagination/useTablePagination.test.tsx +34 -4
  643. package/src/Table/plugins/pagination/useTablePagination.tsx +35 -3
  644. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +9 -2
  645. package/src/Table/plugins/rowStatus/useTableRowStatus.test.tsx +13 -7
  646. package/src/Table/plugins/rowStatus/useTableRowStatus.tsx +12 -3
  647. package/src/Table/plugins/selection/useTableSelection.test.tsx +138 -0
  648. package/src/Table/plugins/selection/useTableSelection.tsx +63 -7
  649. package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +1 -2
  650. package/src/Table/types.ts +22 -4
  651. package/src/Table/useBaseTablePlugins.ts +5 -0
  652. package/src/Table/useTableGroupedRows.doc.mjs +5 -4
  653. package/src/Table/useTablePagination.doc.mjs +7 -0
  654. package/src/Table/useTableRowStatus.doc.mjs +1 -1
  655. package/src/Table/useTableSelection.doc.mjs +31 -0
  656. package/src/Text/Text.test.tsx +67 -1
  657. package/src/Text/Text.tsx +6 -3
  658. package/src/TextArea/TextArea.doc.mjs +12 -2
  659. package/src/TextArea/TextArea.test.tsx +11 -0
  660. package/src/TextArea/TextArea.tsx +37 -24
  661. package/src/TextInput/TextInput.doc.mjs +10 -0
  662. package/src/TextInput/TextInput.tsx +3 -2
  663. package/src/Thumbnail/Thumbnail.doc.mjs +1 -1
  664. package/src/TimeInput/TimeInput.tsx +2 -2
  665. package/src/Timestamp/Timestamp.test.tsx +58 -0
  666. package/src/Timestamp/Timestamp.tsx +12 -10
  667. package/src/Toast/Toast.doc.mjs +26 -12
  668. package/src/Toast/Toast.tsx +28 -4
  669. package/src/Toast/ToastViewport.test.tsx +536 -8
  670. package/src/Toast/ToastViewport.tsx +81 -12
  671. package/src/Token/Token.test.tsx +95 -0
  672. package/src/Token/Token.tsx +15 -10
  673. package/src/Token/TokenLink.tsx +14 -5
  674. package/src/Tokenizer/Tokenizer.doc.mjs +43 -3
  675. package/src/Tokenizer/Tokenizer.test.tsx +161 -0
  676. package/src/Tokenizer/Tokenizer.tsx +53 -24
  677. package/src/Toolbar/Toolbar.doc.mjs +5 -0
  678. package/src/Tooltip/Tooltip.doc.mjs +5 -0
  679. package/src/Tooltip/Tooltip.test.tsx +32 -0
  680. package/src/Tooltip/Tooltip.tsx +5 -0
  681. package/src/Tooltip/useTooltip.tsx +47 -24
  682. package/src/TopNav/TopNavHeading.tsx +5 -4
  683. package/src/TopNav/TopNavMegaMenu.test.tsx +104 -0
  684. package/src/TopNav/TopNavMegaMenu.tsx +47 -5
  685. package/src/TopNav/TopNavMenu.test.tsx +133 -1
  686. package/src/TopNav/TopNavMenu.tsx +38 -7
  687. package/src/TreeList/TreeList.test.tsx +49 -0
  688. package/src/TreeList/TreeList.tsx +7 -2
  689. package/src/Typeahead/BaseTypeahead.doc.mjs +24 -0
  690. package/src/Typeahead/BaseTypeahead.tsx +181 -39
  691. package/src/Typeahead/Typeahead.doc.mjs +11 -0
  692. package/src/Typeahead/Typeahead.test.tsx +203 -0
  693. package/src/Typeahead/Typeahead.tsx +12 -2
  694. package/src/Typeahead/TypeaheadItem.test.tsx +43 -0
  695. package/src/Typeahead/TypeaheadItem.tsx +8 -1
  696. package/src/hooks/index.ts +2 -0
  697. package/src/hooks/useAnnounce.doc.mjs +96 -0
  698. package/src/hooks/useContainerReveal.doc.mjs +2 -2
  699. package/src/hooks/useDevWarning.doc.mjs +96 -0
  700. package/src/hooks/useFocusTrap.test.tsx +14 -0
  701. package/src/hooks/useFocusTrap.ts +62 -111
  702. package/src/hooks/useFocusTrapEscapeShim.test.tsx +165 -0
  703. package/src/hooks/useHotkeys.ts +3 -18
  704. package/src/hooks/useIndicatorFocusRing.doc.mjs +104 -0
  705. package/src/hooks/useInputStatusIcon.doc.mjs +142 -0
  706. package/src/hooks/useInteractiveRole.doc.mjs +119 -0
  707. package/src/hooks/useLongPress.doc.mjs +123 -0
  708. package/src/hooks/useMergedRefs.doc.mjs +79 -0
  709. package/src/hooks/useMergedRefs.test.tsx +62 -0
  710. package/src/hooks/useMergedRefs.ts +36 -0
  711. package/src/hooks/useTypeahead.doc.mjs +153 -0
  712. package/src/index.ts +1 -0
  713. package/src/raw-import.d.ts +14 -0
  714. package/src/theme/MediaTheme.doc.mjs +5 -5
  715. package/src/theme/Theme.test.tsx +104 -2
  716. package/src/theme/Theme.tsx +49 -14
  717. package/src/theme/defineTheme.test.ts +23 -0
  718. package/src/theme/derivedVarRegistry.test.ts +26 -3
  719. package/src/theme/derivedVarRegistry.ts +23 -4
  720. package/src/theme/generateThemeRules.test.ts +99 -1
  721. package/src/theme/generateThemeRules.ts +28 -0
  722. package/src/theme/syntax/tokens.ts +5 -2
  723. package/src/utils/groupItems.ts +12 -6
  724. package/src/utils/index.ts +1 -1
  725. package/src/utils/isApplePlatform.test.ts +61 -0
  726. package/src/utils/isApplePlatform.ts +37 -0
  727. package/src/utils/sharedResizeObserver.ts +10 -2
  728. package/src/utils/timeParser.test.ts +6 -1
  729. package/src/utils/timeParser.ts +35 -13
  730. package/src/__tests__/inputWidthContract.test.tsx +0 -69
@@ -21,10 +21,12 @@ import {
21
21
  useId,
22
22
  useState,
23
23
  useCallback,
24
+ useEffect,
24
25
  useRef,
25
26
  useMemo,
26
27
  useOptimistic,
27
28
  useTransition,
29
+ type FocusEvent,
28
30
  type KeyboardEvent,
29
31
  } from 'react';
30
32
  import * as stylex from '@stylexjs/stylex';
@@ -35,6 +37,7 @@ import {
35
37
  spacingVars,
36
38
  typographyVars,
37
39
  typeScaleVars,
40
+ fontWeightVars,
38
41
  borderVars,
39
42
  } from '../theme/tokens.stylex';
40
43
  import {
@@ -64,6 +67,7 @@ import {useInputStatusIcon} from '../hooks/useInputStatusIcon';
64
67
  import {
65
68
  type ISOTimeString,
66
69
  parseDateInput,
70
+ parseISOTime,
67
71
  parseTimeInput,
68
72
  formatDisplayTime12h,
69
73
  formatDisplayTime24h,
@@ -72,7 +76,6 @@ import {
72
76
  adjustTime,
73
77
  isImeKeyEvent,
74
78
  mergeProps,
75
- mergeRefs,
76
79
  isFocusDetached,
77
80
  } from '../utils';
78
81
  import {
@@ -91,6 +94,7 @@ import {themeProps} from '../utils/themeProps';
91
94
  import {focusOutlineStyles} from '../utils/focusOutline.stylex';
92
95
  import {useTranslator, InternationalizationContext} from '../i18n';
93
96
 
97
+ import {useMergedRefs} from '../hooks/useMergedRefs';
94
98
  export type ISODateTimeString = string & {
95
99
  readonly __brand: 'ISODateTimeString';
96
100
  };
@@ -102,6 +106,12 @@ export type DateTimeInputSize = 'sm' | 'md' | 'lg';
102
106
  /** Supported minute increments for arrow-key stepping of the time field. */
103
107
  export type DateTimeInputTimeIncrement = 1 | 5 | 10 | 15 | 30;
104
108
 
109
+ /**
110
+ * Supported minute cadences for the preset-time dropdown. Every value divides
111
+ * an hour evenly, so each option lands on a round clock time.
112
+ */
113
+ export type DateTimeInputTimeOptionInterval = 5 | 10 | 15 | 30 | 60;
114
+
105
115
  export type {
106
116
  InputStatus as DateTimeInputStatus,
107
117
  InputStatusType as DateTimeInputStatusType,
@@ -170,6 +180,57 @@ const styles = stylex.create({
170
180
  flex: 1,
171
181
  flexBasis: 0,
172
182
  },
183
+ // Preset-time list. Paddings and states mirror BaseTypeahead's dropdown and
184
+ // Selector's options so every list in the system reads the same.
185
+ timeListbox: {
186
+ boxSizing: 'border-box',
187
+ maxHeight: 300,
188
+ overflowY: 'auto',
189
+ padding: spacingVars['--spacing-1'],
190
+ minWidth: 'anchor-size(width)',
191
+ },
192
+ timeOption: {
193
+ boxSizing: 'border-box',
194
+ display: 'flex',
195
+ alignItems: 'center',
196
+ width: '100%',
197
+ paddingBlock: spacingVars['--spacing-1-5'],
198
+ paddingInline: spacingVars['--spacing-2'],
199
+ borderRadius: radiusVars['--radius-element'],
200
+ cursor: {
201
+ default: 'pointer',
202
+ ':is(:disabled,[aria-disabled="true"])': 'default',
203
+ },
204
+ textAlign: 'start',
205
+ fontFamily: typographyVars['--font-family-body'],
206
+ fontSize: typeScaleVars['--text-body-size'],
207
+ lineHeight: typeScaleVars['--text-body-leading'],
208
+ color: colorVars['--color-text-primary'],
209
+ backgroundColor: 'transparent',
210
+ },
211
+ timeOptionHighlighted: {
212
+ backgroundColor: colorVars['--color-overlay-hover'],
213
+ },
214
+ timeOptionSelected: {
215
+ fontWeight: fontWeightVars['--font-weight-medium'],
216
+ },
217
+ });
218
+
219
+ /**
220
+ * Size-specific padding for the preset-time options, so an `sm` field gets a
221
+ * compact list. Matches DropdownMenuItem / Selector / BaseTypeahead.
222
+ */
223
+ const timeOptionSizeStyles = stylex.create({
224
+ sm: {
225
+ paddingBlock: spacingVars['--spacing-1'],
226
+ paddingInline: spacingVars['--spacing-2'],
227
+ },
228
+ md: {
229
+ paddingBlock: spacingVars['--spacing-1-5'],
230
+ },
231
+ lg: {
232
+ paddingBlock: spacingVars['--spacing-2'],
233
+ },
173
234
  });
174
235
 
175
236
  const sizeStyles = stylex.create({
@@ -307,6 +368,22 @@ export interface DateTimeInputProps extends Omit<
307
368
  */
308
369
  timeIncrement?: DateTimeInputTimeIncrement;
309
370
 
371
+ /**
372
+ * Minute cadence for a dropdown of preset times on the time field. Set it to
373
+ * turn the time field into a combobox listing every valid time at that
374
+ * cadence (`60` gives the 12 AM - 11 PM list, `15` a quarter-hour list).
375
+ *
376
+ * Omitted, the time field stays a plain text input: typed entry and
377
+ * arrow-key stepping only, with no combobox semantics added to the
378
+ * accessibility tree. Typed entry keeps working when the dropdown is on —
379
+ * the list is a shortcut, not a restriction, so a time between two options
380
+ * can still be typed.
381
+ *
382
+ * Independent of `timeIncrement`, which governs arrow-key stepping. Setting
383
+ * both to the same value is the usual choice for scheduling flows.
384
+ */
385
+ timeOptionInterval?: DateTimeInputTimeOptionInterval;
386
+
310
387
  /**
311
388
  * Whether to show a clear button when a value is set.
312
389
  * @default false
@@ -396,6 +473,8 @@ function combineDateTime(
396
473
  return `${date}T${time}` as ISODateTimeString;
397
474
  }
398
475
 
476
+ const MINUTES_PER_DAY = 24 * 60;
477
+
399
478
  function getDefaultTime(hasSeconds: boolean): ISOTimeString {
400
479
  const now = new Date();
401
480
  return formatISOTime(
@@ -436,6 +515,7 @@ export function DateTimeInput({
436
515
  hasSeconds = false,
437
516
  hourFormat = '12h',
438
517
  timeIncrement = 1,
518
+ timeOptionInterval,
439
519
  hasClear = false,
440
520
  placeholder: placeholderFromProps,
441
521
  timePlaceholder: timePlaceholderFromProps,
@@ -613,6 +693,46 @@ export function DateTimeInput({
613
693
  return timePlaceholder;
614
694
  }, [isTimeFocused, timeDisplayValue, hourFormat, timePlaceholder, t]);
615
695
 
696
+ // The time field's own accessible name. The option list is named from this
697
+ // rather than from `label`, so a consumer-supplied timeLabel renames both
698
+ // together instead of leaving the list announcing the old name.
699
+ const resolvedTimeLabel =
700
+ timeLabel ?? t('@astryx.dateTimeInput.timeSuffix', {label});
701
+
702
+ // --- Preset time options (#2727) ---
703
+ // Opt-in: without timeOptionInterval the time field keeps exactly the
704
+ // semantics it shipped with — a plain text input, no combobox role, no
705
+ // second listbox in the accessibility tree.
706
+ const hasTimeOptions = timeOptionInterval !== undefined;
707
+
708
+ const timeOptions = useMemo(() => {
709
+ if (timeOptionInterval === undefined) {
710
+ return [];
711
+ }
712
+ const options: {time: ISOTimeString; label: string}[] = [];
713
+ for (
714
+ let minutes = 0;
715
+ minutes < MINUTES_PER_DAY;
716
+ minutes += timeOptionInterval
717
+ ) {
718
+ const time = formatISOTime(
719
+ {
720
+ hour: Math.floor(minutes / 60),
721
+ minute: minutes % 60,
722
+ second: 0,
723
+ },
724
+ hasSeconds,
725
+ );
726
+ // The same bound the typed path enforces, so the list can never offer a
727
+ // time that typing the identical string would reject.
728
+ if (!isTimeInRange(time, timeMin, timeMax)) {
729
+ continue;
730
+ }
731
+ options.push({time, label: formatDisplayTime(time, hasSeconds)});
732
+ }
733
+ return options;
734
+ }, [timeOptionInterval, hasSeconds, timeMin, timeMax, formatDisplayTime]);
735
+
616
736
  // --- Unified change handler ---
617
737
  const fireChange = useCallback(
618
738
  (newValue: ISODateTimeString | undefined) => {
@@ -789,6 +909,222 @@ export function DateTimeInput({
789
909
  [popover, commitDatePendingInput, isEffectivelyDisabled],
790
910
  );
791
911
 
912
+ // --- Time-option popover (#2727) ---
913
+ const timeListboxId = useId();
914
+ const [highlightedTimeIndex, setHighlightedTimeIndex] = useState(-1);
915
+
916
+ // With popover="auto", showing the popover between pointerdown and
917
+ // pointerup/click lets the browser's light-dismiss treat that same click as
918
+ // "outside" and close it again. Defer the show past the click, as
919
+ // BaseTypeahead does for the same reason.
920
+ const timePointerActiveRef = useRef(false);
921
+
922
+ // Whether the highlight is still the one typing derived, or the user has
923
+ // since moved it themselves. Enter honours typed text only in the former
924
+ // case — otherwise the field would commit something other than the option
925
+ // it is showing as active.
926
+ const timeHighlightFollowsTypingRef = useRef(true);
927
+
928
+ const markTimePointerActive = useCallback(() => {
929
+ timePointerActiveRef.current = true;
930
+ document.addEventListener(
931
+ 'click',
932
+ () => {
933
+ timePointerActiveRef.current = false;
934
+ },
935
+ {once: true},
936
+ );
937
+ }, []);
938
+
939
+ const timePopover = usePopover({
940
+ hasLightDismiss: true,
941
+ hasCloseButton: false,
942
+ hasAutoFocus: false,
943
+ // The popup's own role="listbox" carries the semantics; the input keeps
944
+ // DOM focus, so announcing a dialog here would misrepresent it.
945
+ role: 'none',
946
+ onHide: () => setHighlightedTimeIndex(-1),
947
+ });
948
+
949
+ // Anchor the list to the time wrapper, not the date input the field's own
950
+ // trigger ref points at.
951
+ useEffect(() => {
952
+ if (!hasTimeOptions) {
953
+ return;
954
+ }
955
+ const el = timeContainerRef.current;
956
+ if (el) {
957
+ timePopover.triggerRef(el);
958
+ }
959
+ return () => {
960
+ timePopover.triggerRef(null);
961
+ };
962
+ }, [timePopover, hasTimeOptions]);
963
+
964
+ const timeOptionId = useCallback(
965
+ (index: number) => `${timeListboxId}-option-${index}`,
966
+ [timeListboxId],
967
+ );
968
+
969
+ // A field can go disabled or busy while its list is open — a changeAction
970
+ // starting elsewhere in the form is enough. Leave it up and the dropdown
971
+ // hangs over a control that no longer accepts input.
972
+ // The same applies to a list that empties after it opened, which a narrowing
973
+ // min/max window does. An open-but-empty list gates the keyboard switch off,
974
+ // so the arrows quietly fall back to stepping the value instead.
975
+ useEffect(() => {
976
+ if (
977
+ timePopover.isOpen &&
978
+ (isEffectivelyDisabled || timeOptions.length === 0)
979
+ ) {
980
+ timePopover.hide();
981
+ }
982
+ }, [isEffectivelyDisabled, timeOptions.length, timePopover]);
983
+
984
+ // The option list can shrink under an open popover — min/max tighten when
985
+ // the date moves onto a boundary day, or the cadence prop changes. A stale
986
+ // index past the new end shows no highlight at all and makes the arrow keys
987
+ // look dead until the user walks it back into range.
988
+ // Clamped as it is read rather than synced through an effect: no extra
989
+ // render, and the index can never point past the end even for the paint
990
+ // where the list shrank.
991
+ const activeTimeIndex =
992
+ highlightedTimeIndex > timeOptions.length - 1
993
+ ? timeOptions.length - 1
994
+ : highlightedTimeIndex;
995
+
996
+ // Keep the active option visible. The listbox is a fixed-height scroll
997
+ // container, so without this a list opens at midnight with the highlight far
998
+ // below the fold, and keyboard navigation walks off-screen. Mirrors
999
+ // BaseTypeahead's scrollIntoView({block: 'nearest'}).
1000
+ useEffect(() => {
1001
+ if (
1002
+ !timePopover.isOpen ||
1003
+ activeTimeIndex < 0 ||
1004
+ activeTimeIndex >= timeOptions.length
1005
+ ) {
1006
+ return;
1007
+ }
1008
+ document
1009
+ .getElementById(timeOptionId(activeTimeIndex))
1010
+ ?.scrollIntoView?.({block: 'nearest'});
1011
+ }, [timePopover.isOpen, activeTimeIndex, timeOptionId, timeOptions.length]);
1012
+
1013
+ /**
1014
+ * The selected time in the same shape the options carry. splitDateTime slices
1015
+ * whatever follows the `T`, so a caller passing `14:00:00` with hasSeconds
1016
+ * off leaves `"14:00:00"` against options of `"14:00"` — comparing raw would
1017
+ * mark nothing selected, silently.
1018
+ */
1019
+ const selectedOptionTime = useMemo(() => {
1020
+ if (!valueParts.time) {
1021
+ return undefined;
1022
+ }
1023
+ const parsed = parseISOTime(valueParts.time);
1024
+ return parsed ? formatISOTime(parsed, hasSeconds) : undefined;
1025
+ }, [valueParts.time, hasSeconds]);
1026
+
1027
+ /**
1028
+ * Index of the option at or immediately before `time`, so opening on a value
1029
+ * that is not itself an option (13:07 in a 15-minute list) still lands the
1030
+ * highlight somewhere sensible instead of nowhere.
1031
+ */
1032
+ const closestOptionIndex = useCallback(
1033
+ (time: ISOTimeString | undefined) => {
1034
+ if (timeOptions.length === 0) {
1035
+ return -1;
1036
+ }
1037
+ // No time yet — the state a field lands in once a date is picked. The
1038
+ // list still opens on the first option, per the APG listbox pattern;
1039
+ // leaving it inactive made ArrowUp and Enter do nothing at all.
1040
+ if (!time) {
1041
+ return 0;
1042
+ }
1043
+ let candidate = -1;
1044
+ for (let i = 0; i < timeOptions.length; i++) {
1045
+ if (timeOptions[i].time <= time) {
1046
+ candidate = i;
1047
+ } else {
1048
+ break;
1049
+ }
1050
+ }
1051
+ // A value below every option (min pushes the list past it) still gets the
1052
+ // first option rather than an empty highlight.
1053
+ return candidate === -1 ? 0 : candidate;
1054
+ },
1055
+ [timeOptions],
1056
+ );
1057
+
1058
+ const showTimeOptions = useCallback(() => {
1059
+ if (
1060
+ !hasTimeOptions ||
1061
+ isEffectivelyDisabled ||
1062
+ timePopover.isOpen ||
1063
+ // A min/max window narrower than the cadence survives no option at all.
1064
+ // Opening on that would show an empty panel with nothing to pick.
1065
+ timeOptions.length === 0
1066
+ ) {
1067
+ return;
1068
+ }
1069
+ setHighlightedTimeIndex(closestOptionIndex(selectedOptionTime));
1070
+ // useInputContainer routes wrapper clicks through input.click() once the
1071
+ // input advertises a popup, and a programmatic click does not focus. The
1072
+ // input must hold DOM focus or aria-activedescendant announces nothing.
1073
+ timeInputRef.current?.focus();
1074
+ if (timePointerActiveRef.current) {
1075
+ document.addEventListener(
1076
+ 'click',
1077
+ () =>
1078
+ requestAnimationFrame(() => timePopover.show({skipAutoFocus: true})),
1079
+ {once: true},
1080
+ );
1081
+ } else {
1082
+ timePopover.show({skipAutoFocus: true});
1083
+ }
1084
+ }, [
1085
+ hasTimeOptions,
1086
+ isEffectivelyDisabled,
1087
+ timePopover,
1088
+ timeOptions.length,
1089
+ closestOptionIndex,
1090
+ selectedOptionTime,
1091
+ ]);
1092
+
1093
+ /**
1094
+ * The single commit path for a time chosen from the list. Deliberately the
1095
+ * same shape as the typed path: same range check, same date requirement, so
1096
+ * picking 9:00 AM and typing "9:00 AM" are indistinguishable downstream.
1097
+ */
1098
+ const commitTimeOption = useCallback(
1099
+ (time: ISOTimeString) => {
1100
+ if (isEffectivelyDisabled || !isTimeInRange(time, timeMin, timeMax)) {
1101
+ return;
1102
+ }
1103
+ setTimePendingInput(null);
1104
+ // Compared against the normalised time, the same one the selected marker
1105
+ // uses. Comparing the raw value instead made clicking the option that
1106
+ // renders as selected emit a change, whenever the value carried seconds
1107
+ // the field does not display.
1108
+ if (time !== selectedOptionTime && valueParts.date) {
1109
+ const combined = combineDateTime(valueParts.date, time);
1110
+ if (combined) {
1111
+ fireChange(combined);
1112
+ }
1113
+ }
1114
+ timePopover.hide();
1115
+ timeInputRef.current?.focus();
1116
+ },
1117
+ [
1118
+ isEffectivelyDisabled,
1119
+ timeMin,
1120
+ timeMax,
1121
+ selectedOptionTime,
1122
+ valueParts.date,
1123
+ fireChange,
1124
+ timePopover,
1125
+ ],
1126
+ );
1127
+
792
1128
  // --- Time handlers ---
793
1129
  const handleTimeInputChange = useCallback(
794
1130
  (e: React.ChangeEvent<HTMLInputElement>) => {
@@ -801,6 +1137,15 @@ export function DateTimeInput({
801
1137
  setTimePendingInput(text);
802
1138
 
803
1139
  const parsed = parseTimeInput(text, hasSeconds);
1140
+
1141
+ // Typing narrows nothing — free-form entry is the contract, and a time
1142
+ // between two options must stay reachable. The list instead follows the
1143
+ // typed value so Enter lands somewhere the user expects.
1144
+ if (timePopover.isOpen && parsed) {
1145
+ timeHighlightFollowsTypingRef.current = true;
1146
+ setHighlightedTimeIndex(closestOptionIndex(parsed));
1147
+ }
1148
+
804
1149
  if (
805
1150
  parsed &&
806
1151
  isTimeInRange(parsed, timeMin, timeMax) &&
@@ -822,6 +1167,8 @@ export function DateTimeInput({
822
1167
  valueParts.date,
823
1168
  fireChange,
824
1169
  isEffectivelyDisabled,
1170
+ timePopover.isOpen,
1171
+ closestOptionIndex,
825
1172
  ],
826
1173
  );
827
1174
 
@@ -835,29 +1182,59 @@ export function DateTimeInput({
835
1182
  setIsTimeFocused(true);
836
1183
  }, [isEffectivelyDisabled]);
837
1184
 
838
- const handleTimeBlur = useCallback(() => {
839
- setIsTimeFocused(false);
840
- if (timePendingInput === null) {
841
- return;
842
- }
1185
+ const handleTimeBlur = useCallback(
1186
+ (e: FocusEvent<HTMLInputElement>) => {
1187
+ setIsTimeFocused(false);
1188
+
1189
+ // Native light dismiss only fires on outside clicks and Escape, so a focus
1190
+ // move that is neither — Tab handled elsewhere, or a programmatic focus —
1191
+ // would strand the listbox open in the top layer. Focus landing inside the
1192
+ // field or the popup itself is not a leave. Mirrors BaseTypeahead.
1193
+ if (timePopover.isOpen) {
1194
+ const next = e.relatedTarget as Node | null;
1195
+ const popoverEl = next ? document.getElementById(timePopover.id) : null;
1196
+ if (
1197
+ !next ||
1198
+ !(
1199
+ timeContainerRef.current?.contains(next) ||
1200
+ popoverEl?.contains(next)
1201
+ )
1202
+ ) {
1203
+ timePopover.hide();
1204
+ }
1205
+ }
843
1206
 
844
- if (!timePendingInput.trim()) {
845
- // Empty time: revert display to previous value (don't emit partial datetime)
846
- setTimePendingInput(null);
847
- return;
848
- }
1207
+ if (timePendingInput === null) {
1208
+ return;
1209
+ }
849
1210
 
850
- const parsed = parseTimeInput(timePendingInput, hasSeconds);
851
- if (parsed && isTimeInRange(parsed, timeMin, timeMax)) {
852
- if (parsed !== valueParts.time && valueParts.date) {
853
- const combined = combineDateTime(valueParts.date, parsed);
854
- if (combined) {
855
- fireChange(combined);
1211
+ if (!timePendingInput.trim()) {
1212
+ // Empty time: revert display to previous value (don't emit partial datetime)
1213
+ setTimePendingInput(null);
1214
+ return;
1215
+ }
1216
+
1217
+ const parsed = parseTimeInput(timePendingInput, hasSeconds);
1218
+ if (parsed && isTimeInRange(parsed, timeMin, timeMax)) {
1219
+ if (parsed !== valueParts.time && valueParts.date) {
1220
+ const combined = combineDateTime(valueParts.date, parsed);
1221
+ if (combined) {
1222
+ fireChange(combined);
1223
+ }
856
1224
  }
857
1225
  }
858
- }
859
- setTimePendingInput(null);
860
- }, [timePendingInput, hasSeconds, timeMin, timeMax, valueParts, fireChange]);
1226
+ setTimePendingInput(null);
1227
+ },
1228
+ [
1229
+ timePendingInput,
1230
+ hasSeconds,
1231
+ timeMin,
1232
+ timeMax,
1233
+ valueParts,
1234
+ fireChange,
1235
+ timePopover,
1236
+ ],
1237
+ );
861
1238
 
862
1239
  const handleTimeKeyDown = useCallback(
863
1240
  (e: KeyboardEvent<HTMLInputElement>) => {
@@ -868,6 +1245,84 @@ export function DateTimeInput({
868
1245
  if (isImeKeyEvent(e.nativeEvent)) {
869
1246
  return;
870
1247
  }
1248
+
1249
+ // The dropdown claims the arrow keys only while it is open. Closed, they
1250
+ // keep stepping the value by timeIncrement exactly as they always have —
1251
+ // that behaviour is documented and tested, so the list borrows Alt+Arrow
1252
+ // Down (the APG "open without moving" binding) to open instead.
1253
+ if (hasTimeOptions && !isEffectivelyDisabled) {
1254
+ if (e.key === 'Escape' && timePopover.isOpen) {
1255
+ e.preventDefault();
1256
+ timePopover.hide();
1257
+ return;
1258
+ }
1259
+
1260
+ if (e.key === 'ArrowDown' && e.altKey) {
1261
+ e.preventDefault();
1262
+ // A keyboard open is never mid-click, so clear the deferral flag. A
1263
+ // press that ended without a click would otherwise leave it set and
1264
+ // hold every later open hostage to the next click anywhere.
1265
+ timePointerActiveRef.current = false;
1266
+ showTimeOptions();
1267
+ return;
1268
+ }
1269
+
1270
+ if (timePopover.isOpen && timeOptions.length > 0) {
1271
+ switch (e.key) {
1272
+ case 'ArrowDown':
1273
+ e.preventDefault();
1274
+ timeHighlightFollowsTypingRef.current = false;
1275
+ setHighlightedTimeIndex(
1276
+ activeTimeIndex < timeOptions.length - 1
1277
+ ? activeTimeIndex + 1
1278
+ : activeTimeIndex,
1279
+ );
1280
+ return;
1281
+ case 'ArrowUp':
1282
+ e.preventDefault();
1283
+ timeHighlightFollowsTypingRef.current = false;
1284
+ setHighlightedTimeIndex(
1285
+ activeTimeIndex > 0 ? activeTimeIndex - 1 : activeTimeIndex,
1286
+ );
1287
+ return;
1288
+ case 'Home':
1289
+ e.preventDefault();
1290
+ timeHighlightFollowsTypingRef.current = false;
1291
+ setHighlightedTimeIndex(0);
1292
+ return;
1293
+ case 'End':
1294
+ e.preventDefault();
1295
+ timeHighlightFollowsTypingRef.current = false;
1296
+ setHighlightedTimeIndex(timeOptions.length - 1);
1297
+ return;
1298
+ case 'Enter': {
1299
+ e.preventDefault();
1300
+ // Typed text wins over the highlight. The highlight only tracks
1301
+ // the option at or before what was typed, so committing it here
1302
+ // would round 1:07 PM down to 1:00 PM and discard the entry.
1303
+ const typed =
1304
+ timeHighlightFollowsTypingRef.current &&
1305
+ timePendingInput !== null
1306
+ ? parseTimeInput(timePendingInput, hasSeconds)
1307
+ : null;
1308
+ const option = timeOptions[activeTimeIndex];
1309
+ if (typed) {
1310
+ commitTimeOption(typed);
1311
+ } else if (option) {
1312
+ commitTimeOption(option.time);
1313
+ }
1314
+ return;
1315
+ }
1316
+ case 'Tab':
1317
+ // Let focus leave; blur commits any typed text as usual.
1318
+ timePopover.hide();
1319
+ return;
1320
+ default:
1321
+ break;
1322
+ }
1323
+ }
1324
+ }
1325
+
871
1326
  if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
872
1327
  e.preventDefault();
873
1328
 
@@ -907,6 +1362,14 @@ export function DateTimeInput({
907
1362
  fireChange,
908
1363
  announce,
909
1364
  formatDisplayTime,
1365
+ hasTimeOptions,
1366
+ isEffectivelyDisabled,
1367
+ timePopover,
1368
+ timeOptions,
1369
+ activeTimeIndex,
1370
+ timePendingInput,
1371
+ showTimeOptions,
1372
+ commitTimeOption,
910
1373
  ],
911
1374
  );
912
1375
 
@@ -1009,7 +1472,7 @@ export function DateTimeInput({
1009
1472
  />
1010
1473
  </button>
1011
1474
  <input
1012
- ref={mergeRefs(ref, dateInputRef)}
1475
+ ref={useMergedRefs(ref, dateInputRef)}
1013
1476
  id={dateInputId}
1014
1477
  type="text"
1015
1478
  role="combobox"
@@ -1067,6 +1530,10 @@ export function DateTimeInput({
1067
1530
  ref={timeContainerRef}
1068
1531
  onClick={handleTimeWrapperClick}
1069
1532
  onMouseUp={handleTimeWrapperMouseUp}
1533
+ // On the wrapper, not just the input: clicking the clock icon or the
1534
+ // padding is routed to the input as a synthetic click, which would
1535
+ // otherwise open the list mid-gesture and let light dismiss eat it.
1536
+ onPointerDown={hasTimeOptions ? markTimePointerActive : undefined}
1070
1537
  {...mergeProps(
1071
1538
  themeProps('date-time-input-time-segment', {
1072
1539
  size,
@@ -1105,16 +1572,32 @@ export function DateTimeInput({
1105
1572
  onFocus={handleTimeFocus}
1106
1573
  onBlur={handleTimeBlur}
1107
1574
  onKeyDown={handleTimeKeyDown}
1575
+ onClick={hasTimeOptions ? showTimeOptions : undefined}
1576
+ onPointerDown={hasTimeOptions ? markTimePointerActive : undefined}
1108
1577
  placeholder={resolvedTimePlaceholder}
1578
+ // Combobox semantics appear only with the dropdown opted in, so a
1579
+ // field without it keeps a single combobox on the date half.
1580
+ role={hasTimeOptions ? 'combobox' : undefined}
1581
+ aria-expanded={hasTimeOptions ? timePopover.isOpen : undefined}
1582
+ aria-controls={
1583
+ hasTimeOptions && timePopover.isOpen ? timeListboxId : undefined
1584
+ }
1585
+ aria-autocomplete={hasTimeOptions ? 'list' : undefined}
1586
+ aria-activedescendant={
1587
+ hasTimeOptions &&
1588
+ timePopover.isOpen &&
1589
+ activeTimeIndex >= 0 &&
1590
+ activeTimeIndex < timeOptions.length
1591
+ ? timeOptionId(activeTimeIndex)
1592
+ : undefined
1593
+ }
1109
1594
  // With a disabledMessage the input keeps focusability via
1110
1595
  // aria-disabled so the reason is focus-discoverable; typing is
1111
1596
  // blocked with readOnly and the mutation guards.
1112
1597
  disabled={isEffectivelyDisabled && !showsDisabledMessage}
1113
1598
  aria-disabled={showsDisabledMessage ? 'true' : undefined}
1114
1599
  readOnly={showsDisabledMessage || undefined}
1115
- aria-label={
1116
- timeLabel ?? t('@astryx.dateTimeInput.timeSuffix', {label})
1117
- }
1600
+ aria-label={resolvedTimeLabel}
1118
1601
  aria-describedby={ariaDescribedBy}
1119
1602
  aria-required={isEffectivelyRequired ? 'true' : undefined}
1120
1603
  aria-invalid={
@@ -1152,6 +1635,55 @@ export function DateTimeInput({
1152
1635
  {placement: 'below', alignment: 'start'},
1153
1636
  )}
1154
1637
 
1638
+ {hasTimeOptions &&
1639
+ timePopover.render(
1640
+ // The layer renders its children open or closed, so mount the list
1641
+ // only while it is open — a 5-minute cadence is 288 nodes that would
1642
+ // otherwise sit in the DOM of every opted-in field for its lifetime.
1643
+ !timePopover.isOpen ? null : (
1644
+ <div
1645
+ id={timeListboxId}
1646
+ role="listbox"
1647
+ aria-label={t('@astryx.dateTimeInput.timeOptionsLabel', {
1648
+ label: resolvedTimeLabel,
1649
+ })}
1650
+ {...mergeProps(
1651
+ themeProps('date-time-input-time-listbox'),
1652
+ stylex.props(styles.timeListbox),
1653
+ )}>
1654
+ {timeOptions.map((option, index) => {
1655
+ const isSelected = option.time === selectedOptionTime;
1656
+ return (
1657
+ <div
1658
+ key={option.time}
1659
+ id={timeOptionId(index)}
1660
+ role="option"
1661
+ aria-selected={isSelected}
1662
+ tabIndex={-1}
1663
+ // Pointer-down commit: the input must not lose focus to the
1664
+ // option, or blur would fire its own commit first.
1665
+ onPointerDown={e => e.preventDefault()}
1666
+ onClick={() => commitTimeOption(option.time)}
1667
+ onMouseEnter={() => setHighlightedTimeIndex(index)}
1668
+ {...mergeProps(
1669
+ themeProps('date-time-input-time-option'),
1670
+ stylex.props(
1671
+ styles.timeOption,
1672
+ timeOptionSizeStyles[size],
1673
+ index === activeTimeIndex &&
1674
+ styles.timeOptionHighlighted,
1675
+ isSelected && styles.timeOptionSelected,
1676
+ ),
1677
+ )}>
1678
+ {option.label}
1679
+ </div>
1680
+ );
1681
+ })}
1682
+ </div>
1683
+ ),
1684
+ {placement: 'below', alignment: 'start'},
1685
+ )}
1686
+
1155
1687
  {showsDisabledMessage &&
1156
1688
  disabledMessageTooltip.renderTooltip(disabledMessage)}
1157
1689
  </Field>