@astryxdesign/core 0.4.4 → 0.4.5-canary.0472ec1

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 (522) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/dist/AvatarGroup/AvatarGroupOverflow.js +1 -1
  3. package/dist/Blockquote/Blockquote.d.ts +4 -3
  4. package/dist/Blockquote/Blockquote.d.ts.map +1 -1
  5. package/dist/Blockquote/Blockquote.js +9 -10
  6. package/dist/BottomSheet/BottomSheet.d.ts +11 -2
  7. package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
  8. package/dist/BottomSheet/BottomSheet.js +4 -0
  9. package/dist/BottomSheet/BottomSheetPanel.d.ts +5 -2
  10. package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
  11. package/dist/BottomSheet/BottomSheetPanel.js +77 -18
  12. package/dist/BottomSheet/index.d.ts +1 -1
  13. package/dist/BottomSheet/index.d.ts.map +1 -1
  14. package/dist/BottomSheet/snapOffsets.d.ts +57 -20
  15. package/dist/BottomSheet/snapOffsets.d.ts.map +1 -1
  16. package/dist/BottomSheet/snapOffsets.js +106 -30
  17. package/dist/BottomSheet/useSheetGestures.d.ts +13 -8
  18. package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
  19. package/dist/BottomSheet/useSheetGestures.js +160 -64
  20. package/dist/Breadcrumbs/BreadcrumbItem.js +6 -6
  21. package/dist/Button/Button.js +5 -5
  22. package/dist/Calendar/Calendar.d.ts +17 -0
  23. package/dist/Calendar/Calendar.d.ts.map +1 -1
  24. package/dist/Calendar/Calendar.js +55 -15
  25. package/dist/Calendar/getStandaloneShortWeekdayNames.d.ts +14 -0
  26. package/dist/Calendar/getStandaloneShortWeekdayNames.d.ts.map +1 -0
  27. package/dist/Calendar/getStandaloneShortWeekdayNames.js +26 -0
  28. package/dist/Calendar/hooks/useCalendarConstraints.d.ts +22 -1
  29. package/dist/Calendar/hooks/useCalendarConstraints.d.ts.map +1 -1
  30. package/dist/Calendar/hooks/useCalendarConstraints.js +26 -4
  31. package/dist/Calendar/hooks/useCalendarDays.d.ts.map +1 -1
  32. package/dist/Calendar/hooks/useCalendarDays.js +14 -10
  33. package/dist/Calendar/hooks/useCalendarNavigation.d.ts.map +1 -1
  34. package/dist/Calendar/hooks/useCalendarNavigation.js +8 -4
  35. package/dist/Calendar/standaloneShortWeekdayNames.generated.d.ts +47 -0
  36. package/dist/Calendar/standaloneShortWeekdayNames.generated.d.ts.map +1 -0
  37. package/dist/Calendar/standaloneShortWeekdayNames.generated.js +40 -0
  38. package/dist/Calendar/styles.js +3 -3
  39. package/dist/Center/Center.d.ts +23 -1
  40. package/dist/Center/Center.d.ts.map +1 -1
  41. package/dist/Center/Center.js +12 -6
  42. package/dist/Chat/ChatComposer.d.ts.map +1 -1
  43. package/dist/Chat/ChatComposer.js +2 -2
  44. package/dist/Chat/ChatToolCalls.js +1 -1
  45. package/dist/Chat/useChatDictation.d.ts +1 -1
  46. package/dist/Chat/useChatDictation.d.ts.map +1 -1
  47. package/dist/Chat/useSpeechRecognition.d.ts +1 -1
  48. package/dist/Chat/useSpeechRecognition.d.ts.map +1 -1
  49. package/dist/Chat/useSpeechRecognition.js +4 -3
  50. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  51. package/dist/CheckboxInput/CheckboxInput.js +9 -0
  52. package/dist/Citation/Citation.js +3 -3
  53. package/dist/ClickableCard/ClickableCard.js +2 -2
  54. package/dist/CommandPalette/CommandPaletteItem.js +1 -1
  55. package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
  56. package/dist/ComplexSelector/ComplexSelector.js +8 -3
  57. package/dist/DateInput/DateInput.d.ts +31 -2
  58. package/dist/DateInput/DateInput.d.ts.map +1 -1
  59. package/dist/DateInput/DateInput.js +92 -19
  60. package/dist/DateInput/MonthScroller.d.ts +35 -0
  61. package/dist/DateInput/MonthScroller.d.ts.map +1 -0
  62. package/dist/DateInput/MonthScroller.js +573 -0
  63. package/dist/DateInput/MonthYearWheels.d.ts +24 -0
  64. package/dist/DateInput/MonthYearWheels.d.ts.map +1 -0
  65. package/dist/DateInput/MonthYearWheels.js +114 -0
  66. package/dist/DateInput/TouchDateField.d.ts +10 -0
  67. package/dist/DateInput/TouchDateField.d.ts.map +1 -0
  68. package/dist/DateInput/TouchDateField.js +810 -0
  69. package/dist/DateInput/Wheel.d.ts +41 -0
  70. package/dist/DateInput/Wheel.d.ts.map +1 -0
  71. package/dist/DateInput/Wheel.js +315 -0
  72. package/dist/DateInput/monthGeometry.d.ts +65 -0
  73. package/dist/DateInput/monthGeometry.d.ts.map +1 -0
  74. package/dist/DateInput/monthGeometry.js +98 -0
  75. package/dist/DateInput/tokens.stylex.d.ts +63 -0
  76. package/dist/DateInput/tokens.stylex.d.ts.map +1 -0
  77. package/dist/DateInput/tokens.stylex.js +74 -0
  78. package/dist/DateInput/useOwnScrollGesture.d.ts +41 -0
  79. package/dist/DateInput/useOwnScrollGesture.d.ts.map +1 -0
  80. package/dist/DateInput/useOwnScrollGesture.js +202 -0
  81. package/dist/DateInput/usePointerDragScroll.d.ts +15 -0
  82. package/dist/DateInput/usePointerDragScroll.d.ts.map +1 -0
  83. package/dist/DateInput/usePointerDragScroll.js +216 -0
  84. package/dist/DateInput/useScrollSettle.d.ts +26 -0
  85. package/dist/DateInput/useScrollSettle.d.ts.map +1 -0
  86. package/dist/DateInput/useScrollSettle.js +149 -0
  87. package/dist/DateRangeInput/DateRangeInput.d.ts +23 -1
  88. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  89. package/dist/DateRangeInput/DateRangeInput.js +47 -9
  90. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  91. package/dist/DateTimeInput/DateTimeInput.js +18 -10
  92. package/dist/Dialog/Dialog.d.ts.map +1 -1
  93. package/dist/Dialog/Dialog.js +3 -3
  94. package/dist/Field/FieldLabel.d.ts +2 -1
  95. package/dist/Field/FieldLabel.d.ts.map +1 -1
  96. package/dist/Field/FieldLabel.js +21 -3
  97. package/dist/Field/InputClearButton.d.ts +2 -1
  98. package/dist/Field/InputClearButton.d.ts.map +1 -1
  99. package/dist/Field/InputClearButton.js +12 -1
  100. package/dist/Field/inputStyles.stylex.d.ts.map +1 -1
  101. package/dist/Field/inputStyles.stylex.js +4 -4
  102. package/dist/FileInput/FileInput.d.ts.map +1 -1
  103. package/dist/FileInput/FileInput.js +2 -2
  104. package/dist/FormLayout/FormLayout.d.ts +24 -2
  105. package/dist/FormLayout/FormLayout.d.ts.map +1 -1
  106. package/dist/FormLayout/FormLayout.js +7 -2
  107. package/dist/FormLayout/FormLayoutContext.d.ts +15 -2
  108. package/dist/FormLayout/FormLayoutContext.d.ts.map +1 -1
  109. package/dist/FormLayout/FormLayoutContext.js +19 -4
  110. package/dist/FormLayout/index.d.ts +1 -1
  111. package/dist/FormLayout/index.d.ts.map +1 -1
  112. package/dist/HoverCard/HoverCard.d.ts +13 -3
  113. package/dist/HoverCard/HoverCard.d.ts.map +1 -1
  114. package/dist/HoverCard/HoverCard.js +2 -0
  115. package/dist/HoverCard/index.d.ts +1 -1
  116. package/dist/HoverCard/index.d.ts.map +1 -1
  117. package/dist/HoverCard/useHoverCard.d.ts +17 -2
  118. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  119. package/dist/HoverCard/useHoverCard.js +78 -9
  120. package/dist/Item/Item.d.ts +9 -1
  121. package/dist/Item/Item.d.ts.map +1 -1
  122. package/dist/Item/Item.js +46 -8
  123. package/dist/Layer/index.d.ts +4 -2
  124. package/dist/Layer/index.d.ts.map +1 -1
  125. package/dist/Layer/index.js +2 -0
  126. package/dist/Layer/useLayer.d.ts.map +1 -1
  127. package/dist/Layer/useLayer.js +3 -2
  128. package/dist/Layer/useTouchTrigger.d.ts +113 -0
  129. package/dist/Layer/useTouchTrigger.d.ts.map +1 -0
  130. package/dist/Layer/useTouchTrigger.js +241 -0
  131. package/dist/Layout/container.stylex.d.ts +4 -2
  132. package/dist/Layout/container.stylex.d.ts.map +1 -1
  133. package/dist/Layout/container.stylex.js +19 -11
  134. package/dist/Layout/index.d.ts +1 -0
  135. package/dist/Layout/index.d.ts.map +1 -1
  136. package/dist/Layout/index.js +4 -0
  137. package/dist/Layout/padding.stylex.d.ts +315 -12
  138. package/dist/Layout/padding.stylex.d.ts.map +1 -1
  139. package/dist/Layout/padding.stylex.js +389 -12
  140. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  141. package/dist/Lightbox/Lightbox.js +2 -1
  142. package/dist/Link/Link.js +4 -4
  143. package/dist/Markdown/Markdown.d.ts +8 -0
  144. package/dist/Markdown/Markdown.d.ts.map +1 -1
  145. package/dist/Markdown/Markdown.js +31 -3
  146. package/dist/Markdown/parser.d.ts +14 -2
  147. package/dist/Markdown/parser.d.ts.map +1 -1
  148. package/dist/Markdown/parser.js +50 -2
  149. package/dist/MobileNav/MobileNav.d.ts +1 -0
  150. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  151. package/dist/MobileNav/MobileNav.js +24 -6
  152. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  153. package/dist/MultiSelector/MultiSelector.js +8 -3
  154. package/dist/NavItem/navItemStyles.stylex.d.ts +2 -2
  155. package/dist/NavItem/navItemStyles.stylex.js +2 -2
  156. package/dist/NavMenu/NavHeadingMenuItem.js +1 -1
  157. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  158. package/dist/NumberInput/NumberInput.js +38 -5
  159. package/dist/Outline/Outline.js +2 -2
  160. package/dist/Outline/parseOutlineFromMarkdown.d.ts +2 -0
  161. package/dist/Outline/parseOutlineFromMarkdown.d.ts.map +1 -1
  162. package/dist/Outline/parseOutlineFromMarkdown.js +5 -31
  163. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  164. package/dist/PowerSearch/PowerSearch.js +11 -12
  165. package/dist/PowerSearch/PowerSearchToken.d.ts.map +1 -1
  166. package/dist/PowerSearch/PowerSearchToken.js +3 -1
  167. package/dist/PowerSearch/formatFilterValue.d.ts +11 -2
  168. package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
  169. package/dist/PowerSearch/formatFilterValue.js +23 -8
  170. package/dist/RadioList/RadioList.d.ts.map +1 -1
  171. package/dist/RadioList/RadioList.js +12 -1
  172. package/dist/RadioList/RadioListItem.d.ts +2 -2
  173. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  174. package/dist/RadioList/RadioListItem.js +68 -38
  175. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  176. package/dist/Resizable/ResizeHandle.js +3 -3
  177. package/dist/Section/Section.d.ts +36 -1
  178. package/dist/Section/Section.d.ts.map +1 -1
  179. package/dist/Section/Section.js +12 -2
  180. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  181. package/dist/SegmentedControl/SegmentedControlItem.js +6 -1
  182. package/dist/SelectableCard/SelectableCard.js +1 -1
  183. package/dist/Selector/Selector.d.ts +26 -1
  184. package/dist/Selector/Selector.d.ts.map +1 -1
  185. package/dist/Selector/Selector.js +95 -17
  186. package/dist/Selector/SelectorOption.d.ts +14 -1
  187. package/dist/Selector/SelectorOption.d.ts.map +1 -1
  188. package/dist/Selector/SelectorOption.js +6 -0
  189. package/dist/Selector/SelectorRowLayoutContext.d.ts +8 -0
  190. package/dist/Selector/SelectorRowLayoutContext.d.ts.map +1 -0
  191. package/dist/Selector/SelectorRowLayoutContext.js +27 -0
  192. package/dist/Selector/types.d.ts +1 -0
  193. package/dist/Selector/types.d.ts.map +1 -1
  194. package/dist/SideNav/SideNavHeading.js +1 -1
  195. package/dist/SideNav/SideNavItem.js +1 -1
  196. package/dist/Slider/Slider.d.ts.map +1 -1
  197. package/dist/Slider/Slider.js +3 -3
  198. package/dist/Stack/Stack.d.ts +23 -1
  199. package/dist/Stack/Stack.d.ts.map +1 -1
  200. package/dist/Stack/Stack.js +12 -6
  201. package/dist/StatusDot/StatusDot.d.ts +43 -3
  202. package/dist/StatusDot/StatusDot.d.ts.map +1 -1
  203. package/dist/StatusDot/StatusDot.js +42 -5
  204. package/dist/Switch/Switch.d.ts.map +1 -1
  205. package/dist/Switch/Switch.js +9 -0
  206. package/dist/TabList/TabMenu.js +1 -1
  207. package/dist/Table/TableRow.js +4 -4
  208. package/dist/Table/plugins/columnResize/useTableColumnResize.d.ts.map +1 -1
  209. package/dist/Table/plugins/columnResize/useTableColumnResize.js +1 -1
  210. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  211. package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +1 -1
  212. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  213. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +7 -2
  214. package/dist/Table/plugins/sortable/useTableSortableState.d.ts +5 -3
  215. package/dist/Table/plugins/sortable/useTableSortableState.d.ts.map +1 -1
  216. package/dist/Table/plugins/sortable/useTableSortableState.js +12 -9
  217. package/dist/Table/plugins/tree/useTableTreeData.js +2 -2
  218. package/dist/TextArea/TextArea.d.ts.map +1 -1
  219. package/dist/TextArea/TextArea.js +6 -1
  220. package/dist/TextInput/TextInput.d.ts.map +1 -1
  221. package/dist/TextInput/TextInput.js +6 -1
  222. package/dist/Thumbnail/Thumbnail.js +1 -1
  223. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  224. package/dist/TimeInput/TimeInput.js +6 -1
  225. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  226. package/dist/Timestamp/Timestamp.js +6 -4
  227. package/dist/Timestamp/formatInstant.d.ts +3 -2
  228. package/dist/Timestamp/formatInstant.d.ts.map +1 -1
  229. package/dist/Timestamp/formatInstant.js +8 -8
  230. package/dist/Timestamp/tooltipEntries.d.ts +2 -1
  231. package/dist/Timestamp/tooltipEntries.d.ts.map +1 -1
  232. package/dist/Timestamp/tooltipEntries.js +5 -3
  233. package/dist/Token/Token.js +1 -1
  234. package/dist/Tooltip/Tooltip.d.ts +16 -3
  235. package/dist/Tooltip/Tooltip.d.ts.map +1 -1
  236. package/dist/Tooltip/Tooltip.js +2 -0
  237. package/dist/Tooltip/index.d.ts +1 -1
  238. package/dist/Tooltip/index.d.ts.map +1 -1
  239. package/dist/Tooltip/useTooltip.d.ts +21 -2
  240. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  241. package/dist/Tooltip/useTooltip.js +71 -13
  242. package/dist/TopNav/TopNavHeading.js +2 -2
  243. package/dist/TopNav/TopNavItem.js +2 -2
  244. package/dist/TopNav/TopNavMegaMenu.js +1 -1
  245. package/dist/TopNav/TopNavMegaMenuItem.js +1 -1
  246. package/dist/TopNav/TopNavMenu.js +2 -2
  247. package/dist/TreeList/TreeListItem.js +1 -1
  248. package/dist/astryx.css +123 -60
  249. package/dist/hooks/containerReveal.stylex.d.ts.map +1 -1
  250. package/dist/hooks/containerReveal.stylex.js +18 -18
  251. package/dist/hooks/scrollbarGutter.d.ts +28 -0
  252. package/dist/hooks/scrollbarGutter.d.ts.map +1 -0
  253. package/dist/hooks/scrollbarGutter.js +103 -0
  254. package/dist/hooks/useResolvedRequired.d.ts +19 -0
  255. package/dist/hooks/useResolvedRequired.d.ts.map +1 -0
  256. package/dist/hooks/useResolvedRequired.js +40 -0
  257. package/dist/hooks/useScrollLock.d.ts +4 -0
  258. package/dist/hooks/useScrollLock.d.ts.map +1 -1
  259. package/dist/hooks/useScrollLock.js +13 -1
  260. package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
  261. package/dist/i18n/InternationalizationContext.js +2 -0
  262. package/dist/i18n/index.d.ts +6 -0
  263. package/dist/i18n/index.d.ts.map +1 -1
  264. package/dist/i18n/index.js +6 -0
  265. package/dist/i18n/useCollator.d.ts +12 -0
  266. package/dist/i18n/useCollator.d.ts.map +1 -0
  267. package/dist/i18n/useCollator.js +40 -0
  268. package/dist/i18n/useLocale.d.ts +3 -0
  269. package/dist/i18n/useLocale.d.ts.map +1 -0
  270. package/dist/i18n/useLocale.js +31 -0
  271. package/dist/theme/defineTheme.d.ts +5 -0
  272. package/dist/theme/defineTheme.d.ts.map +1 -1
  273. package/dist/theme/defineTheme.js +5 -0
  274. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  275. package/dist/theme/derivedVarRegistry.js +7 -0
  276. package/dist/theme/generateThemeRules.d.ts.map +1 -1
  277. package/dist/theme/generateThemeRules.js +66 -5
  278. package/dist/theme/syntax/index.d.ts +6 -0
  279. package/dist/theme/syntax/index.d.ts.map +1 -1
  280. package/dist/theme/syntax/index.js +7 -2
  281. package/dist/utils/dateParser.d.ts +4 -3
  282. package/dist/utils/dateParser.d.ts.map +1 -1
  283. package/dist/utils/dateParser.js +8 -8
  284. package/dist/utils/index.d.ts +1 -1
  285. package/dist/utils/index.d.ts.map +1 -1
  286. package/dist/utils/index.js +1 -1
  287. package/dist/utils/plainDate.d.ts +11 -2
  288. package/dist/utils/plainDate.d.ts.map +1 -1
  289. package/dist/utils/plainDate.js +32 -4
  290. package/locales/af-ZA.json +958 -0
  291. package/locales/ar-SA.json +998 -0
  292. package/locales/ca-ES.json +974 -0
  293. package/locales/cs-CZ.json +990 -0
  294. package/locales/da-DK.json +966 -0
  295. package/locales/de-DE.json +966 -0
  296. package/locales/el-GR.json +990 -0
  297. package/locales/en.json +32 -0
  298. package/locales/es-ES.json +978 -0
  299. package/locales/fi-FI.json +990 -0
  300. package/locales/fr-FR.json +928 -0
  301. package/locales/he-IL.json +990 -0
  302. package/locales/hu-HU.json +990 -0
  303. package/locales/it-IT.json +978 -0
  304. package/locales/ja-JP.json +998 -0
  305. package/locales/ko-KR.json +990 -0
  306. package/locales/nl-NL.json +954 -0
  307. package/locales/no-NO.json +978 -0
  308. package/locales/pl-PL.json +982 -0
  309. package/locales/pseudo.json +24 -0
  310. package/locales/pt-BR.json +982 -0
  311. package/locales/pt-PT.json +982 -0
  312. package/locales/ro-RO.json +982 -0
  313. package/locales/ru-RU.json +990 -0
  314. package/locales/sr-SP.json +990 -0
  315. package/locales/sv-SE.json +986 -0
  316. package/locales/tr-TR.json +990 -0
  317. package/locales/uk-UA.json +990 -0
  318. package/locales/vi-VN.json +986 -0
  319. package/locales/zh-CN.json +998 -0
  320. package/locales/zh-TW.json +998 -0
  321. package/package.json +3 -3
  322. package/src/AvatarGroup/AvatarGroupOverflow.tsx +1 -1
  323. package/src/Banner/Banner.doc.mjs +2 -0
  324. package/src/Blockquote/Blockquote.doc.mjs +30 -7
  325. package/src/Blockquote/Blockquote.test.tsx +34 -3
  326. package/src/Blockquote/Blockquote.tsx +11 -9
  327. package/src/BottomSheet/BottomSheet.doc.mjs +36 -3
  328. package/src/BottomSheet/BottomSheet.test.tsx +177 -2
  329. package/src/BottomSheet/BottomSheet.tsx +16 -2
  330. package/src/BottomSheet/BottomSheetPanel.test.tsx +91 -0
  331. package/src/BottomSheet/BottomSheetPanel.tsx +121 -15
  332. package/src/BottomSheet/index.ts +5 -1
  333. package/src/BottomSheet/snapOffsets.test.ts +114 -47
  334. package/src/BottomSheet/snapOffsets.ts +119 -33
  335. package/src/BottomSheet/useSheetGestures.test.ts +113 -15
  336. package/src/BottomSheet/useSheetGestures.ts +196 -100
  337. package/src/Breadcrumbs/BreadcrumbItem.tsx +1 -1
  338. package/src/Button/Button.tsx +7 -7
  339. package/src/Calendar/Calendar.doc.mjs +16 -0
  340. package/src/Calendar/Calendar.test.tsx +137 -0
  341. package/src/Calendar/Calendar.tsx +80 -11
  342. package/src/Calendar/getStandaloneShortWeekdayNames.test.ts +54 -0
  343. package/src/Calendar/getStandaloneShortWeekdayNames.ts +38 -0
  344. package/src/Calendar/hooks/useCalendarConstraints.ts +54 -3
  345. package/src/Calendar/hooks/useCalendarDays.ts +13 -10
  346. package/src/Calendar/hooks/useCalendarNavigation.ts +6 -4
  347. package/src/Calendar/standaloneShortWeekdayNames.generated.ts +50 -0
  348. package/src/Calendar/styles.ts +3 -3
  349. package/src/Center/Center.doc.mjs +48 -0
  350. package/src/Center/Center.test.tsx +158 -0
  351. package/src/Center/Center.tsx +50 -9
  352. package/src/Chat/ChatComposer.tsx +7 -4
  353. package/src/Chat/ChatToolCalls.tsx +1 -1
  354. package/src/Chat/{useChatDictation.test.ts → useChatDictation.test.tsx} +29 -14
  355. package/src/Chat/useChatDictation.ts +1 -1
  356. package/src/Chat/useSpeechRecognition.ts +5 -3
  357. package/src/CheckboxInput/CheckboxInput.tsx +6 -0
  358. package/src/Citation/Citation.tsx +3 -3
  359. package/src/ClickableCard/ClickableCard.tsx +2 -2
  360. package/src/CommandPalette/CommandPaletteItem.tsx +1 -1
  361. package/src/ComplexSelector/ComplexSelector.doc.mjs +10 -0
  362. package/src/ComplexSelector/ComplexSelector.tsx +8 -5
  363. package/src/DateInput/DateInput.test.tsx +17 -1
  364. package/src/DateInput/DateInput.tsx +90 -19
  365. package/src/DateInput/DateInputTouch.test.tsx +2393 -0
  366. package/src/DateInput/MonthScroller.tsx +784 -0
  367. package/src/DateInput/MonthYearWheels.tsx +147 -0
  368. package/src/DateInput/TouchDateField.tsx +1214 -0
  369. package/src/DateInput/Wheel.tsx +470 -0
  370. package/src/DateInput/monthGeometry.ts +118 -0
  371. package/src/DateInput/tokens.stylex.ts +99 -0
  372. package/src/DateInput/useOwnScrollGesture.ts +227 -0
  373. package/src/DateInput/usePointerDragScroll.ts +220 -0
  374. package/src/DateInput/useScrollSettle.ts +164 -0
  375. package/src/DateRangeInput/DateRangeInput.doc.mjs +16 -0
  376. package/src/DateRangeInput/DateRangeInput.test.tsx +81 -1
  377. package/src/DateRangeInput/DateRangeInput.tsx +88 -8
  378. package/src/DateTimeInput/DateTimeInput.tsx +23 -8
  379. package/src/Dialog/Dialog.test.tsx +24 -0
  380. package/src/Dialog/Dialog.tsx +3 -0
  381. package/src/Field/Field.doc.mjs +3 -0
  382. package/src/Field/FieldLabel.tsx +20 -4
  383. package/src/Field/InputClearButton.test.tsx +134 -2
  384. package/src/Field/InputClearButton.tsx +42 -1
  385. package/src/Field/inputStyles.stylex.ts +16 -12
  386. package/src/FileInput/FileInput.tsx +5 -4
  387. package/src/FormLayout/FormLayout.doc.mjs +13 -0
  388. package/src/FormLayout/FormLayout.test.tsx +181 -4
  389. package/src/FormLayout/FormLayout.tsx +33 -2
  390. package/src/FormLayout/FormLayoutContext.ts +22 -7
  391. package/src/FormLayout/index.ts +1 -1
  392. package/src/HoverCard/HoverCard.doc.mjs +18 -0
  393. package/src/HoverCard/HoverCard.test.tsx +189 -0
  394. package/src/HoverCard/HoverCard.tsx +22 -2
  395. package/src/HoverCard/index.ts +1 -0
  396. package/src/HoverCard/useHoverCard.doc.mjs +2 -0
  397. package/src/HoverCard/useHoverCard.tsx +103 -7
  398. package/src/Item/Item.doc.mjs +1 -0
  399. package/src/Item/Item.test.tsx +50 -0
  400. package/src/Item/Item.tsx +41 -2
  401. package/src/Layer/index.ts +10 -0
  402. package/src/Layer/useLayer.tsx +13 -2
  403. package/src/Layer/useTouchTrigger.test.ts +70 -0
  404. package/src/Layer/useTouchTrigger.ts +366 -0
  405. package/src/Layout/Layout.doc.mjs +18 -0
  406. package/src/Layout/container.stylex.ts +11 -3
  407. package/src/Layout/index.ts +4 -0
  408. package/src/Layout/overlayPaddingReset.test.tsx +222 -0
  409. package/src/Layout/padding.stylex.ts +192 -12
  410. package/src/Lightbox/Lightbox.tsx +2 -1
  411. package/src/Link/Link.tsx +4 -4
  412. package/src/Markdown/Markdown.doc.mjs +3 -0
  413. package/src/Markdown/Markdown.test.tsx +78 -0
  414. package/src/Markdown/Markdown.tsx +41 -1
  415. package/src/Markdown/parser.ts +60 -2
  416. package/src/MobileNav/MobileNav.tsx +61 -5
  417. package/src/MobileNav/MobileNavEntryAnimation.test.tsx +212 -0
  418. package/src/MobileNav/MobileNavScrollbarGutter.test.tsx +109 -0
  419. package/src/MultiSelector/MultiSelector.test.tsx +1 -1
  420. package/src/MultiSelector/MultiSelector.tsx +8 -5
  421. package/src/NavItem/navItemStyles.stylex.ts +2 -2
  422. package/src/NavMenu/NavHeadingMenuItem.tsx +1 -1
  423. package/src/NumberInput/NumberInput.doc.mjs +24 -0
  424. package/src/NumberInput/NumberInput.test.tsx +138 -0
  425. package/src/NumberInput/NumberInput.tsx +44 -6
  426. package/src/Outline/Outline.doc.mjs +2 -0
  427. package/src/Outline/Outline.tsx +1 -1
  428. package/src/Outline/parseOutlineFromMarkdown.ts +10 -40
  429. package/src/PowerSearch/PowerSearch.tsx +17 -8
  430. package/src/PowerSearch/PowerSearchToken.tsx +3 -0
  431. package/src/PowerSearch/formatFilterValue.test.ts +22 -2
  432. package/src/PowerSearch/formatFilterValue.ts +31 -6
  433. package/src/RadioList/RadioList.doc.mjs +1 -1
  434. package/src/RadioList/RadioList.test.tsx +170 -2
  435. package/src/RadioList/RadioList.tsx +9 -1
  436. package/src/RadioList/RadioListItem.tsx +83 -51
  437. package/src/Resizable/ResizeHandle.test.tsx +22 -0
  438. package/src/Resizable/ResizeHandle.tsx +9 -3
  439. package/src/Section/Section.doc.mjs +55 -0
  440. package/src/Section/Section.test.tsx +201 -4
  441. package/src/Section/Section.tsx +69 -0
  442. package/src/SegmentedControl/SegmentedControl.test.tsx +31 -0
  443. package/src/SegmentedControl/SegmentedControlItem.tsx +11 -2
  444. package/src/SelectableCard/SelectableCard.tsx +1 -1
  445. package/src/Selector/Selector.doc.mjs +16 -2
  446. package/src/Selector/Selector.test.tsx +525 -1
  447. package/src/Selector/Selector.tsx +166 -21
  448. package/src/Selector/SelectorOption.doc.mjs +7 -0
  449. package/src/Selector/SelectorOption.tsx +21 -0
  450. package/src/Selector/SelectorRowLayoutContext.ts +32 -0
  451. package/src/Selector/types.ts +4 -4
  452. package/src/SideNav/SideNavHeading.tsx +2 -2
  453. package/src/SideNav/SideNavItem.tsx +1 -1
  454. package/src/Slider/Slider.tsx +11 -1
  455. package/src/Stack/Stack.doc.mjs +72 -0
  456. package/src/Stack/Stack.test.tsx +156 -0
  457. package/src/Stack/Stack.tsx +50 -8
  458. package/src/StatusDot/StatusDot.doc.mjs +13 -0
  459. package/src/StatusDot/StatusDot.test.tsx +115 -8
  460. package/src/StatusDot/StatusDot.tsx +74 -9
  461. package/src/Switch/Switch.tsx +6 -0
  462. package/src/TabList/TabMenu.tsx +1 -1
  463. package/src/Table/TableRow.tsx +4 -4
  464. package/src/Table/plugins/columnResize/useTableColumnResize.tsx +2 -1
  465. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +2 -1
  466. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +22 -4
  467. package/src/Table/plugins/sortable/useTableSortableState.test.tsx +34 -0
  468. package/src/Table/plugins/sortable/useTableSortableState.tsx +26 -23
  469. package/src/Table/plugins/tree/useTableTreeData.tsx +2 -2
  470. package/src/TextArea/TextArea.doc.mjs +1 -1
  471. package/src/TextArea/TextArea.tsx +3 -1
  472. package/src/TextInput/TextInput.tsx +3 -1
  473. package/src/Thumbnail/Thumbnail.tsx +1 -1
  474. package/src/TimeInput/TimeInput.tsx +3 -1
  475. package/src/Timestamp/Timestamp.test.tsx +27 -7
  476. package/src/Timestamp/Timestamp.tsx +8 -4
  477. package/src/Timestamp/formatInstant.ts +9 -7
  478. package/src/Timestamp/tooltipEntries.test.ts +11 -6
  479. package/src/Timestamp/tooltipEntries.ts +6 -2
  480. package/src/Token/Token.tsx +1 -1
  481. package/src/Tooltip/Tooltip.doc.mjs +18 -0
  482. package/src/Tooltip/Tooltip.test.tsx +254 -1
  483. package/src/Tooltip/Tooltip.tsx +22 -2
  484. package/src/Tooltip/index.ts +1 -0
  485. package/src/Tooltip/useTooltip.doc.mjs +2 -0
  486. package/src/Tooltip/useTooltip.tsx +99 -21
  487. package/src/TopNav/TopNavHeading.tsx +1 -1
  488. package/src/TopNav/TopNavItem.tsx +2 -2
  489. package/src/TopNav/TopNavMegaMenu.tsx +1 -1
  490. package/src/TopNav/TopNavMegaMenuItem.tsx +1 -1
  491. package/src/TopNav/TopNavMenu.tsx +2 -2
  492. package/src/TreeList/TreeListItem.tsx +1 -1
  493. package/src/hooks/containerReveal.stylex.ts +54 -18
  494. package/src/hooks/scrollbarGutter.test.ts +167 -0
  495. package/src/hooks/scrollbarGutter.ts +121 -0
  496. package/src/hooks/useResolvedRequired.ts +42 -0
  497. package/src/hooks/useScrollLock.doc.mjs +4 -4
  498. package/src/hooks/useScrollLock.test.ts +73 -0
  499. package/src/hooks/useScrollLock.ts +14 -0
  500. package/src/i18n/InternationalizationContext.ts +2 -0
  501. package/src/i18n/__tests__/e2e-powersearch.test.tsx +37 -1
  502. package/src/i18n/__tests__/useCollator.test.tsx +115 -0
  503. package/src/i18n/__tests__/useLocale.test.tsx +52 -0
  504. package/src/i18n/index.ts +6 -0
  505. package/src/i18n/useCollator.doc.mjs +84 -0
  506. package/src/i18n/useCollator.ts +44 -0
  507. package/src/i18n/useLocale.doc.mjs +70 -0
  508. package/src/i18n/useLocale.ts +34 -0
  509. package/src/i18n/useTranslator.doc.mjs +1 -1
  510. package/src/theme/defineTheme.test.ts +9 -3
  511. package/src/theme/defineTheme.ts +5 -0
  512. package/src/theme/derivedVarRegistry.test.ts +19 -5
  513. package/src/theme/derivedVarRegistry.ts +4 -0
  514. package/src/theme/generateThemeRules.test.ts +118 -0
  515. package/src/theme/generateThemeRules.ts +83 -5
  516. package/src/theme/syntax/index.ts +6 -2
  517. package/src/theme/syntax/serverSafeSyntax.test.ts +68 -0
  518. package/src/utils/dateParser.test.ts +20 -0
  519. package/src/utils/dateParser.ts +14 -7
  520. package/src/utils/index.ts +2 -0
  521. package/src/utils/plainDate.test.ts +56 -0
  522. package/src/utils/plainDate.ts +33 -4
@@ -61,13 +61,13 @@ const hoverRowStyles = stylex.create({
61
61
  row: {
62
62
  backgroundColor: {
63
63
  default: null,
64
- ':hover': {
64
+ ':hover:where(:not(:disabled,[aria-disabled="true"]))': {
65
65
  '@media (hover: hover)': colorVars['--color-overlay-hover'],
66
66
  },
67
67
  },
68
68
  '--table-row-overlay': {
69
69
  default: null,
70
- ':hover': {
70
+ ':hover:where(:not(:disabled,[aria-disabled="true"]))': {
71
71
  '@media (hover: hover)': colorVars['--color-overlay-hover'],
72
72
  },
73
73
  },
@@ -82,14 +82,14 @@ const stripedHoverRowStyles = stylex.create({
82
82
  backgroundColor: {
83
83
  default: null,
84
84
  ':nth-child(even)': colorVars['--color-background-muted'],
85
- ':hover': {
85
+ ':hover:where(:not(:disabled,[aria-disabled="true"]))': {
86
86
  '@media (hover: hover)': colorVars['--color-overlay-hover'],
87
87
  },
88
88
  },
89
89
  '--table-row-overlay': {
90
90
  default: null,
91
91
  ':nth-child(even)': colorVars['--color-background-muted'],
92
- ':hover': {
92
+ ':hover:where(:not(:disabled,[aria-disabled="true"]))': {
93
93
  '@media (hover: hover)': colorVars['--color-overlay-hover'],
94
94
  },
95
95
  },
@@ -216,7 +216,8 @@ const handleStyles = stylex.create({
216
216
  // can't receive :hover directly.
217
217
  '--indicator-color': {
218
218
  default: 'transparent',
219
- ':hover': colorVars['--color-accent'],
219
+ ':hover:where(:not(:disabled,[aria-disabled="true"]))':
220
+ colorVars['--color-accent'],
220
221
  ':focus-visible': colorVars['--color-accent'],
221
222
  },
222
223
  '@media (pointer: coarse)': {
@@ -148,7 +148,8 @@ const styles = stylex.create({
148
148
  cursor: 'pointer',
149
149
  color: {
150
150
  default: colorVars['--color-icon-secondary'],
151
- ':hover': colorVars['--color-icon-primary'],
151
+ ':hover:where(:not(:disabled,[aria-disabled="true"]))':
152
+ colorVars['--color-icon-primary'],
152
153
  },
153
154
  },
154
155
  chevronIcon: {
@@ -23,6 +23,7 @@ import {spacingVars, colorVars, radiusVars} from '../../../theme/tokens.stylex';
23
23
  import {Icon} from '../../../Icon';
24
24
  import {resolveContextActions} from '../../tableContextMenu';
25
25
  import {useTranslator} from '../../../i18n';
26
+ import {rtlStyles} from '../../../utils';
26
27
  import type {
27
28
  TablePlugin,
28
29
  TableColumn,
@@ -84,16 +85,28 @@ const expansionStyles = stylex.create({
84
85
  // Match IconButton ghost hover: subtle overlay background.
85
86
  backgroundImage: {
86
87
  default: null,
87
- ':hover': {
88
+ ':hover:where(:not(:disabled,[aria-disabled="true"]))': {
88
89
  '@media (hover: hover)': `linear-gradient(${colorVars['--color-overlay-hover']}, ${colorVars['--color-overlay-hover']})`,
89
90
  },
90
91
  },
91
- ':hover': {
92
+ ':hover:where(:not(:disabled,[aria-disabled="true"]))': {
92
93
  color: colorVars['--color-icon-primary'],
93
94
  },
94
95
  },
96
+ // The RTL mirror is folded into each state's transform rather than living
97
+ // on a parent span, matching TreeListItem's chevron (both are `transform`,
98
+ // so on one element the later value would win).
95
99
  chevronExpanded: {
96
- transform: 'rotate(90deg)',
100
+ transform: {
101
+ default: 'rotate(90deg)',
102
+ ':is([dir="rtl"] *)': 'scaleX(-1) rotate(90deg)',
103
+ },
104
+ },
105
+ chevronCollapsed: {
106
+ transform: {
107
+ default: 'rotate(0deg)',
108
+ ':is([dir="rtl"] *)': 'scaleX(-1) rotate(0deg)',
109
+ },
97
110
  },
98
111
  expandedRow: {
99
112
  backgroundColor: colorVars['--color-background-muted'],
@@ -121,7 +134,9 @@ function ExpansionChevron({
121
134
  type="button"
122
135
  {...stylex.props(
123
136
  expansionStyles.chevronButton,
124
- isExpanded && expansionStyles.chevronExpanded,
137
+ isExpanded
138
+ ? expansionStyles.chevronExpanded
139
+ : expansionStyles.chevronCollapsed,
125
140
  )}
126
141
  onClick={e => {
127
142
  e.stopPropagation();
@@ -249,6 +264,9 @@ export function useTableRowExpansion<T extends Record<string, unknown>>(
249
264
  icon={isExpanded ? 'chevronDown' : 'chevronRight'}
250
265
  size="xsm"
251
266
  aria-hidden
267
+ // chevronDown needs no mirroring; chevronRight (collapsed,
268
+ // pointing toward the reveal direction) does.
269
+ xstyle={!isExpanded && rtlStyles.mirror}
252
270
  />
253
271
  ),
254
272
  onSelect: () => onToggle(key),
@@ -17,6 +17,7 @@ import {useTableSortable} from './useTableSortable';
17
17
  import type {TableSortState} from './useTableSortable';
18
18
  import {useTableSortableState} from './useTableSortableState';
19
19
  import type {UseTableSortableStateConfig} from './useTableSortableState';
20
+ import {InternationalizationProvider} from '../../../i18n';
20
21
 
21
22
  // =============================================================================
22
23
  // Test Data
@@ -119,6 +120,39 @@ describe('useTableSortableState', () => {
119
120
  ]);
120
121
  });
121
122
 
123
+ it('re-sorts strings when the provider locale changes', () => {
124
+ const localeData: Employee[] = [
125
+ {
126
+ id: '1',
127
+ name: 'z',
128
+ age: 1,
129
+ department: 'Test',
130
+ salary: 1,
131
+ },
132
+ {
133
+ id: '2',
134
+ name: 'ä',
135
+ age: 2,
136
+ department: 'Test',
137
+ salary: 2,
138
+ },
139
+ ];
140
+ const table = (locale: string) => (
141
+ <InternationalizationProvider locale={locale}>
142
+ <SortableStateTable
143
+ data={localeData}
144
+ defaultSort={[{sortKey: 'name', direction: 'ascending'}]}
145
+ />
146
+ </InternationalizationProvider>
147
+ );
148
+
149
+ const {rerender} = render(table('sv-SE'));
150
+ expect(getNameColumnValues()).toEqual(['z', 'ä']);
151
+
152
+ rerender(table('de-DE'));
153
+ expect(getNameColumnValues()).toEqual(['ä', 'z']);
154
+ });
155
+
122
156
  it('renders unsorted when no defaultSort', () => {
123
157
  render(<SortableStateTable />);
124
158
 
@@ -18,10 +18,8 @@
18
18
  */
19
19
 
20
20
  import {useState, useMemo, useCallback, useRef} from 'react';
21
- import type {
22
- TableSortState,
23
- UseTableSortableConfig,
24
- } from './useTableSortable';
21
+ import type {TableSortState, UseTableSortableConfig} from './useTableSortable';
22
+ import {useCollator} from '../../../i18n/useCollator';
25
23
 
26
24
  // =============================================================================
27
25
  // Comparator Types
@@ -104,14 +102,16 @@ export interface UseTableSortableStateConfig<
104
102
  * two row items. Comparators should sort ascending — the hook flips the
105
103
  * sign for descending.
106
104
  *
107
- * For keys not in this map, the hook falls back to `localeCompare` with
108
- * `{ numeric: true }` on the stringified values.
105
+ * For keys not in this map, the hook falls back to an `Intl.Collator`
106
+ * comparison (`{numeric: true}`) on the stringified values, bound to the
107
+ * active `InternationalizationProvider` locale.
109
108
  *
110
109
  * @example
111
110
  * ```
111
+ * const collator = useCollator({numeric: true});
112
112
  * comparators: {
113
113
  * age: (a, b) => a.age - b.age,
114
- * name: (a, b) => a.name.localeCompare(b.name),
114
+ * name: (a, b) => collator.compare(a.name, b.name),
115
115
  * }
116
116
  * ```
117
117
  */
@@ -164,6 +164,7 @@ function defaultCompare<T extends Record<string, unknown>>(
164
164
  a: T,
165
165
  b: T,
166
166
  sortKey: string,
167
+ collator: Intl.Collator,
167
168
  ): number {
168
169
  const aVal = a[sortKey];
169
170
  const bVal = b[sortKey];
@@ -171,8 +172,10 @@ function defaultCompare<T extends Record<string, unknown>>(
171
172
  // null/undefined/NaN sort to the end. NaN must not reach the numeric fast
172
173
  // path: a NaN comparator result reads as "equal" to Array.sort, which makes
173
174
  // the comparator inconsistent and corrupts the order of the other rows.
174
- const aMissing = aVal == null || (typeof aVal === 'number' && Number.isNaN(aVal));
175
- const bMissing = bVal == null || (typeof bVal === 'number' && Number.isNaN(bVal));
175
+ const aMissing =
176
+ aVal == null || (typeof aVal === 'number' && Number.isNaN(aVal));
177
+ const bMissing =
178
+ bVal == null || (typeof bVal === 'number' && Number.isNaN(bVal));
176
179
  if (aMissing && bMissing) {
177
180
  return 0;
178
181
  }
@@ -188,14 +191,9 @@ function defaultCompare<T extends Record<string, unknown>>(
188
191
  return aVal - bVal;
189
192
  }
190
193
 
191
- // string comparison with numeric collation
192
- return toSortableString(aVal).localeCompare(
193
- toSortableString(bVal),
194
- undefined,
195
- {
196
- numeric: true,
197
- },
198
- );
194
+ // string comparison with numeric collation, bound to the provider locale
195
+ // via useCollator() rather than a raw localeCompare(value, locale) call.
196
+ return collator.compare(toSortableString(aVal), toSortableString(bVal));
199
197
  }
200
198
 
201
199
  // =============================================================================
@@ -208,7 +206,8 @@ function sortData<
208
206
  >(
209
207
  data: T[],
210
208
  sortState: TableSortState<TSortKey>,
211
- comparators?: Partial<Record<TSortKey, TableSortComparator<T>>>,
209
+ comparators: Partial<Record<TSortKey, TableSortComparator<T>>> | undefined,
210
+ collator: Intl.Collator,
212
211
  ): T[] {
213
212
  if (sortState.length === 0) {
214
213
  return data;
@@ -218,7 +217,9 @@ function sortData<
218
217
  for (const entry of sortState) {
219
218
  const {sortKey, direction} = entry;
220
219
  const customCmp = comparators?.[sortKey];
221
- const cmp = customCmp ? customCmp(a, b) : defaultCompare(a, b, sortKey);
220
+ const cmp = customCmp
221
+ ? customCmp(a, b)
222
+ : defaultCompare(a, b, sortKey, collator);
222
223
 
223
224
  if (cmp !== 0) {
224
225
  return direction === 'ascending' ? cmp : -cmp;
@@ -265,6 +266,7 @@ export function useTableSortableState<
265
266
  allowUnsortedState,
266
267
  isMultiSortEnabled,
267
268
  } = config;
269
+ const collator = useCollator({numeric: true});
268
270
 
269
271
  // Internal state (used in uncontrolled mode)
270
272
  const [internalSort, setInternalSort] =
@@ -287,14 +289,15 @@ export function useTableSortableState<
287
289
 
288
290
  // Sorted data — memoized on sort state + data identity
289
291
  const sortedData = useMemo(
290
- () => sortData(data, sort, comparatorsRef.current),
291
- [data, sort],
292
+ () => sortData(data, sort, comparatorsRef.current, collator),
293
+ [data, sort, collator],
292
294
  );
293
295
 
294
296
  // applySort — lets consumers sort arbitrary data with the current state
295
297
  const applySort = useCallback(
296
- (inputData: T[]): T[] => sortData(inputData, sort, comparatorsRef.current),
297
- [sort],
298
+ (inputData: T[]): T[] =>
299
+ sortData(inputData, sort, comparatorsRef.current, collator),
300
+ [sort, collator],
298
301
  );
299
302
 
300
303
  // Config ready for useTableSortable
@@ -251,11 +251,11 @@ const treeStyles = stylex.create({
251
251
  // Match IconButton ghost hover: subtle overlay background
252
252
  backgroundImage: {
253
253
  default: null,
254
- ':hover': {
254
+ ':hover:where(:not(:disabled,[aria-disabled="true"]))': {
255
255
  '@media (hover: hover)': `linear-gradient(${colorVars['--color-overlay-hover']}, ${colorVars['--color-overlay-hover']})`,
256
256
  },
257
257
  },
258
- ':hover': {
258
+ ':hover:where(:not(:disabled,[aria-disabled="true"]))': {
259
259
  color: colorVars['--color-icon-primary'],
260
260
  },
261
261
  },
@@ -105,7 +105,7 @@ export const docs = {
105
105
  name: 'maxLength',
106
106
  type: 'number',
107
107
  description:
108
- 'Maximum number of characters allowed, counted as user-perceived characters — an emoji or flag sequence counts as one. When set, a character counter (current/max) is displayed inside the input container, anchored to the bottom-right beneath the text. Does not enforce the limit natively; when exceeded the counter turns red and shows a warning icon (a non-color cue), and screen-reader users hear the remaining/over-limit count announced. Consumers validating the limit should count with characterCount (exported from the package) so enforcement matches the displayed count.',
108
+ 'Maximum number of characters allowed, counted as user-perceived characters: an emoji or flag sequence counts as one. When set, a character counter (current/max) is displayed inside the input container, anchored to the bottom-right beneath the text. Does not enforce the limit natively; when exceeded the counter turns red and shows a warning icon (a non-color cue), and screen-reader users hear the remaining/over-limit count announced. Consumers validating the limit should count with characterCount (exported from the package) so enforcement matches the displayed count.',
109
109
  },
110
110
  {
111
111
  name: 'status',
@@ -52,6 +52,7 @@ import type {SizeValue} from '../utils/types';
52
52
  import {useInputContainer} from '../hooks/useInputContainer';
53
53
  import {useInputStatusIcon} from '../hooks/useInputStatusIcon';
54
54
  import {useAnnounce} from '../hooks/useAnnounce';
55
+ import {useResolvedRequired} from '../hooks/useResolvedRequired';
55
56
  import {useSize} from '../SizeContext/SizeContext';
56
57
  import {themeProps} from '../utils/themeProps';
57
58
  import {characterCount} from '../utils/characters';
@@ -394,6 +395,7 @@ export function TextArea({
394
395
  }: TextAreaProps) {
395
396
  const size = useSize(sizeProp, 'md');
396
397
  const t = useTranslator();
398
+ const isEffectivelyRequired = useResolvedRequired({isRequired, isOptional});
397
399
  const announce = useAnnounce();
398
400
  const id = useId();
399
401
  const descriptionID = useId();
@@ -598,7 +600,7 @@ export function TextArea({
598
600
  autoFocus={hasAutoFocus}
599
601
  data-autofocus={hasAutoFocus || undefined}
600
602
  aria-describedby={ariaDescribedBy}
601
- aria-required={isRequired && !isOptional ? 'true' : undefined}
603
+ aria-required={isEffectivelyRequired ? 'true' : undefined}
602
604
  aria-invalid={
603
605
  status?.type === 'error' ||
604
606
  (maxLength != null && valueLength > maxLength)
@@ -101,6 +101,7 @@ import {mergeProps, mergeRefs} from '../utils';
101
101
  import {useSize} from '../SizeContext/SizeContext';
102
102
  import {useInputContainer} from '../hooks/useInputContainer';
103
103
  import {useInputStatusIcon} from '../hooks/useInputStatusIcon';
104
+ import {useResolvedRequired} from '../hooks/useResolvedRequired';
104
105
  import {useInputGroup} from '../InputGroup/InputGroupContext';
105
106
  import type {BaseProps} from '../BaseProps';
106
107
  import type {SizeValue} from '../utils/types';
@@ -301,6 +302,7 @@ export function TextInput({
301
302
  ...rest
302
303
  }: TextInputProps) {
303
304
  const t = useTranslator();
305
+ const isEffectivelyRequired = useResolvedRequired({isRequired, isOptional});
304
306
  const size = useSize(sizeProp, 'md');
305
307
 
306
308
  const id = useId();
@@ -445,7 +447,7 @@ export function TextInput({
445
447
  autoFocus={hasAutoFocus}
446
448
  data-autofocus={hasAutoFocus || undefined}
447
449
  aria-describedby={ariaDescribedBy}
448
- aria-required={isRequired === true ? 'true' : undefined}
450
+ aria-required={isEffectivelyRequired ? 'true' : undefined}
449
451
  aria-invalid={status?.type === 'error' ? 'true' : undefined}
450
452
  aria-busy={isBusy || undefined}
451
453
  aria-labelledby={ariaLabelledBy}
@@ -183,7 +183,7 @@ const styles = stylex.create({
183
183
  },
184
184
  hoverOnPointer: {
185
185
  '@media (hover: hover)': {
186
- ':hover::after': {
186
+ ':hover:where(:not(:disabled,[aria-disabled="true"]))::after': {
187
187
  backgroundColor: colorVars['--color-overlay-hover'],
188
188
  },
189
189
  },
@@ -67,6 +67,7 @@ import {useSize} from '../SizeContext/SizeContext';
67
67
  import {useAnnounce} from '../hooks/useAnnounce';
68
68
  import {useInputContainer} from '../hooks/useInputContainer';
69
69
  import {useInputStatusIcon} from '../hooks/useInputStatusIcon';
70
+ import {useResolvedRequired} from '../hooks/useResolvedRequired';
70
71
  import {useInputGroup} from '../InputGroup/InputGroupContext';
71
72
  import {groupStyles} from '../InputGroup/groupStyles';
72
73
  import {useTooltip} from '../Tooltip';
@@ -347,6 +348,7 @@ export function TimeInput({
347
348
  ref,
348
349
  }: TimeInputProps) {
349
350
  const t = useTranslator();
351
+ const isEffectivelyRequired = useResolvedRequired({isRequired, isOptional});
350
352
  const placeholder =
351
353
  placeholderFromProps ?? t('@astryx.timeInput.placeholder');
352
354
  const size = useSize(sizeProp, 'md');
@@ -664,7 +666,7 @@ export function TimeInput({
664
666
  autoFocus={hasAutoFocus}
665
667
  data-autofocus={hasAutoFocus || undefined}
666
668
  aria-describedby={ariaDescribedBy}
667
- aria-required={isRequired === true ? 'true' : undefined}
669
+ aria-required={isEffectivelyRequired ? 'true' : undefined}
668
670
  aria-invalid={
669
671
  status?.type === 'error' || !isInputValid ? 'true' : undefined
670
672
  }
@@ -257,6 +257,26 @@ describe('Timestamp', () => {
257
257
 
258
258
  // --- Standard display formats ---
259
259
 
260
+ it('updates absolute output when the provider locale changes', () => {
261
+ const value = '2026-01-25T12:00:00Z';
262
+ const timestamp = (locale: string) => (
263
+ <InternationalizationProvider locale={locale}>
264
+ <Timestamp
265
+ value={value}
266
+ format="date_long"
267
+ hasTooltip={false}
268
+ data-testid="ts"
269
+ />
270
+ </InternationalizationProvider>
271
+ );
272
+
273
+ const {rerender} = render(timestamp('en-US'));
274
+ expect(screen.getByTestId('ts')).toHaveTextContent('January 25, 2026');
275
+
276
+ rerender(timestamp('de-DE'));
277
+ expect(screen.getByTestId('ts')).toHaveTextContent('25. Januar 2026');
278
+ });
279
+
260
280
  it('renders date format', () => {
261
281
  render(
262
282
  <Timestamp value="2026-02-19T17:00:00Z" format="date" data-testid="ts" />,
@@ -441,7 +461,7 @@ describe('Timestamp', () => {
441
461
  );
442
462
 
443
463
  const longTz =
444
- new Intl.DateTimeFormat(undefined, {timeZoneName: 'long'})
464
+ new Intl.DateTimeFormat('en', {timeZoneName: 'long'})
445
465
  .formatToParts(oneHourAgo)
446
466
  .find(p => p.type === 'timeZoneName')?.value ?? '';
447
467
  expect(longTz).not.toBe('');
@@ -462,7 +482,7 @@ describe('Timestamp', () => {
462
482
  );
463
483
 
464
484
  const tzPart = (form: 'short' | 'long') =>
465
- new Intl.DateTimeFormat(undefined, {timeZoneName: form})
485
+ new Intl.DateTimeFormat('en', {timeZoneName: form})
466
486
  .formatToParts(date)
467
487
  .find(p => p.type === 'timeZoneName')?.value ?? '';
468
488
  const text = screen.getByTestId('ts').textContent ?? '';
@@ -673,7 +693,7 @@ describe('Timestamp', () => {
673
693
  // no-break spaces that jest-dom's matcher normalization would break on.
674
694
  const normalize = (s: string) => s.replace(/\s+/g, ' ');
675
695
  const datetime = new Date(el.getAttribute('datetime') ?? '');
676
- const expected = new Intl.DateTimeFormat(undefined, {
696
+ const expected = new Intl.DateTimeFormat('en', {
677
697
  year: 'numeric',
678
698
  month: 'long',
679
699
  day: 'numeric',
@@ -789,7 +809,7 @@ describe('Timestamp', () => {
789
809
  const datetime = new Date(
790
810
  screen.getByTestId('ts').getAttribute('datetime') ?? '',
791
811
  );
792
- const expected = new Intl.DateTimeFormat(undefined, {
812
+ const expected = new Intl.DateTimeFormat('en', {
793
813
  year: 'numeric',
794
814
  month: 'long',
795
815
  day: 'numeric',
@@ -1252,7 +1272,7 @@ describe('Timestamp', () => {
1252
1272
  data-testid="ts"
1253
1273
  />,
1254
1274
  );
1255
- const [line] = formatTooltipLines(new Date(VALUE), [{format}]);
1275
+ const [line] = formatTooltipLines(new Date(VALUE), [{format}], 'en');
1256
1276
  expect(line.value).toBe(screen.getByTestId('ts').textContent);
1257
1277
  },
1258
1278
  );
@@ -1275,10 +1295,10 @@ describe('Timestamp', () => {
1275
1295
  );
1276
1296
  const date = new Date(VALUE);
1277
1297
  const tzPart = (form: 'short' | 'long') =>
1278
- new Intl.DateTimeFormat(undefined, {timeZoneName: form})
1298
+ new Intl.DateTimeFormat('en', {timeZoneName: form})
1279
1299
  .formatToParts(date)
1280
1300
  .find(p => p.type === 'timeZoneName')?.value ?? '';
1281
- const [line] = formatTooltipLines(date, [{format: 'full'}]);
1301
+ const [line] = formatTooltipLines(date, [{format: 'full'}], 'en');
1282
1302
  expect(screen.getByTestId('ts').getAttribute('aria-label')).toBe(
1283
1303
  line.value.replace(tzPart('short'), tzPart('long')),
1284
1304
  );
@@ -23,6 +23,7 @@ import type {TextType, TextSize, TextColor, TextWeight} from '../theme/types';
23
23
  import {mergeProps, mergeRefs} from '../utils';
24
24
  import {useDevWarning} from '../hooks/useDevWarning';
25
25
  import {useTranslator} from '../i18n';
26
+ import {useLocale} from '../i18n/useLocale';
26
27
  import type {BaseProps} from '../BaseProps';
27
28
  import {themeProps} from '../utils/themeProps';
28
29
  import {formatInstant} from './formatInstant';
@@ -419,6 +420,7 @@ export function Timestamp({
419
420
  'data-testid': testId,
420
421
  }: TimestampProps) {
421
422
  const t = useTranslator();
423
+ const locale = useLocale();
422
424
  const timeRef = useRef<HTMLTimeElement>(null);
423
425
  const [now, setNow] = useState(() => new Date());
424
426
 
@@ -448,16 +450,18 @@ export function Timestamp({
448
450
  : effectiveFormat === 'relative_short'
449
451
  ? getRelativeTimeShortString(date, now)
450
452
  : isAbsoluteFormat(effectiveFormat)
451
- ? formatInstant(date, effectiveFormat, {isTimezoneShown})
453
+ ? formatInstant(date, effectiveFormat, locale, {isTimezoneShown})
452
454
  : '';
453
455
 
454
456
  // Full absolute text for the tooltip (visible — keeps the compact timezone
455
457
  // abbreviation) and for the AT-facing aria-label, which spells the timezone
456
458
  // out in full: abbreviations like "PST" or "GMT+2" are unexpanded
457
459
  // abbreviations to a screen-reader user (WCAG 3.1.4).
458
- const fullAbsoluteText = isValidDate ? formatInstant(date, 'full') : '';
460
+ const fullAbsoluteText = isValidDate
461
+ ? formatInstant(date, 'full', locale)
462
+ : '';
459
463
  const ariaLabelText = isValidDate
460
- ? formatInstant(date, 'full', {timeZoneNameStyle: 'long'})
464
+ ? formatInstant(date, 'full', locale, {timeZoneNameStyle: 'long'})
461
465
  : '';
462
466
 
463
467
  // Live updates
@@ -506,7 +510,7 @@ export function Timestamp({
506
510
  const lines: ReadonlyArray<TimestampTooltipLine> =
507
511
  entries === undefined
508
512
  ? [{value: fullAbsoluteText, isCopyable: true}]
509
- : formatTooltipLines(date, entries);
513
+ : formatTooltipLines(date, entries, locale);
510
514
 
511
515
  const timestampProps = mergeProps(
512
516
  themeProps('timestamp', {format: effectiveFormat}),
@@ -30,6 +30,7 @@
30
30
  */
31
31
 
32
32
  import {SHARED_DATE_FORMAT_OPTIONS, getTimeZoneParts} from '../utils/plainDate';
33
+ import type {Locale} from '../i18n/types';
33
34
  import type {TimestampFormat} from './Timestamp';
34
35
 
35
36
  // =============================================================================
@@ -159,12 +160,13 @@ function getWallClock(date: Date, timeZone: string | undefined): WallClock {
159
160
  /**
160
161
  * Renders one instant in one absolute format.
161
162
  *
162
- * Pure: the same arguments always produce the same string for a given host
163
+ * Pure: the same arguments always produce the same string for the requested
163
164
  * locale (and, when no `timeZone` is given, host zone).
164
165
  */
165
166
  export function formatInstant(
166
167
  date: Date,
167
168
  format: InstantFormat,
169
+ locale: Locale,
168
170
  {
169
171
  timeZone,
170
172
  isTimezoneShown = false,
@@ -176,39 +178,39 @@ export function formatInstant(
176
178
 
177
179
  switch (format) {
178
180
  case 'full':
179
- return new Intl.DateTimeFormat(undefined, {
181
+ return new Intl.DateTimeFormat(locale, {
180
182
  ...FULL_OPTIONS,
181
183
  timeZoneName: timeZoneNameStyle,
182
184
  ...zone,
183
185
  }).format(date);
184
186
 
185
187
  case 'date':
186
- return new Intl.DateTimeFormat(undefined, {
188
+ return new Intl.DateTimeFormat(locale, {
187
189
  ...SHARED_DATE_FORMAT_OPTIONS.date,
188
190
  ...zone,
189
191
  }).format(date);
190
192
 
191
193
  case 'date_long':
192
- return new Intl.DateTimeFormat(undefined, {
194
+ return new Intl.DateTimeFormat(locale, {
193
195
  ...SHARED_DATE_FORMAT_OPTIONS.date_long,
194
196
  ...zone,
195
197
  }).format(date);
196
198
 
197
199
  case 'date_weekday':
198
- return new Intl.DateTimeFormat(undefined, {
200
+ return new Intl.DateTimeFormat(locale, {
199
201
  ...SHARED_DATE_FORMAT_OPTIONS.date_weekday,
200
202
  ...zone,
201
203
  }).format(date);
202
204
 
203
205
  case 'date_time':
204
- return new Intl.DateTimeFormat(undefined, {
206
+ return new Intl.DateTimeFormat(locale, {
205
207
  ...DATE_TIME_OPTIONS,
206
208
  ...zoneName,
207
209
  ...zone,
208
210
  }).format(date);
209
211
 
210
212
  case 'time':
211
- return new Intl.DateTimeFormat(undefined, {
213
+ return new Intl.DateTimeFormat(locale, {
212
214
  ...TIME_OPTIONS,
213
215
  ...zoneName,
214
216
  ...zone,
@@ -16,12 +16,17 @@
16
16
 
17
17
  import {describe, it, expect, vi} from 'vitest';
18
18
  import {SHARED_DATE_FORMAT_OPTIONS} from '../utils/plainDate';
19
- import {formatTooltipLines} from './tooltipEntries';
19
+ import {formatTooltipLines as formatTooltipLinesForLocale} from './tooltipEntries';
20
+
21
+ const formatTooltipLines = (
22
+ date: Parameters<typeof formatTooltipLinesForLocale>[0],
23
+ entries: Parameters<typeof formatTooltipLinesForLocale>[1],
24
+ ) => formatTooltipLinesForLocale(date, entries, 'en-US');
20
25
 
21
26
  /** 2026-02-19T17:00:00Z — chosen so several zones land on different dates. */
22
27
  const INSTANT = new Date('2026-02-19T17:00:00Z');
23
28
 
24
- const LOCAL_ZONE = Intl.DateTimeFormat().resolvedOptions().timeZone;
29
+ const LOCAL_ZONE = Intl.DateTimeFormat('en-US').resolvedOptions().timeZone;
25
30
 
26
31
  describe('formatTooltipLines', () => {
27
32
  // --- Explicit zones: exact, locale-free, TZ-agnostic ---
@@ -86,7 +91,7 @@ describe('formatTooltipLines', () => {
86
91
  for (const timezoneID of ['UTC', 'Asia/Tokyo']) {
87
92
  const [line] = formatTooltipLines(INSTANT, [{timezoneID, format}]);
88
93
  expect(line.value).toBe(
89
- new Intl.DateTimeFormat(undefined, {
94
+ new Intl.DateTimeFormat('en-US', {
90
95
  ...SHARED_DATE_FORMAT_OPTIONS[format],
91
96
  timeZone: timezoneID,
92
97
  }).format(INSTANT),
@@ -208,7 +213,7 @@ describe('formatTooltipLines', () => {
208
213
  {format: 'date_time'},
209
214
  {format: 'system_date_time'},
210
215
  ]);
211
- const localName = new Intl.DateTimeFormat(undefined, {
216
+ const localName = new Intl.DateTimeFormat('en-US', {
212
217
  timeZoneName: 'short',
213
218
  })
214
219
  .formatToParts(INSTANT)
@@ -230,7 +235,7 @@ describe('formatTooltipLines', () => {
230
235
  // aria-describedby, and that element's accessible name is the LOCAL
231
236
  // absolute time. A lone foreign-zone line with no marker is therefore
232
237
  // announced right after a local time, with nothing to say it is not one.
233
- const zoneName = new Intl.DateTimeFormat(undefined, {
238
+ const zoneName = new Intl.DateTimeFormat('en-US', {
234
239
  timeZone: 'Asia/Tokyo',
235
240
  timeZoneName: 'short',
236
241
  })
@@ -248,7 +253,7 @@ describe('formatTooltipLines', () => {
248
253
  // The consumer never named a zone, so there is nothing to disambiguate
249
254
  // against — this must stay as bare as the visible text is by default.
250
255
  const [line] = formatTooltipLines(INSTANT, [{format: 'date_time'}]);
251
- const localName = new Intl.DateTimeFormat(undefined, {
256
+ const localName = new Intl.DateTimeFormat('en-US', {
252
257
  timeZoneName: 'short',
253
258
  })
254
259
  .formatToParts(INSTANT)