@astryxdesign/core 0.5.0 → 0.5.1-canary.046f6ea

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 (622) hide show
  1. package/CHANGELOG.md +222 -0
  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/AspectRatio/AspectRatio.d.ts +6 -6
  6. package/dist/Avatar/Avatar.d.ts +25 -1
  7. package/dist/Avatar/Avatar.d.ts.map +1 -1
  8. package/dist/Avatar/Avatar.js +43 -9
  9. package/dist/Avatar/index.d.ts +2 -2
  10. package/dist/Avatar/index.d.ts.map +1 -1
  11. package/dist/Avatar/index.js +1 -1
  12. package/dist/AvatarGroup/AvatarGroup.d.ts +9 -2
  13. package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
  14. package/dist/AvatarGroup/AvatarGroup.js +5 -2
  15. package/dist/AvatarGroup/AvatarGroupContext.d.ts +2 -1
  16. package/dist/AvatarGroup/AvatarGroupContext.d.ts.map +1 -1
  17. package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
  18. package/dist/AvatarGroup/AvatarGroupOverflow.js +11 -7
  19. package/dist/Badge/Badge.d.ts.map +1 -1
  20. package/dist/Badge/Badge.js +26 -2
  21. package/dist/Banner/Banner.d.ts +10 -1
  22. package/dist/Banner/Banner.d.ts.map +1 -1
  23. package/dist/Banner/Banner.js +11 -2
  24. package/dist/Button/Button.d.ts.map +1 -1
  25. package/dist/Button/Button.js +8 -7
  26. package/dist/Calendar/Calendar.d.ts +4 -2
  27. package/dist/Calendar/Calendar.d.ts.map +1 -1
  28. package/dist/Calendar/Calendar.js +15 -21
  29. package/dist/Calendar/hooks/useCalendarDays.js +4 -6
  30. package/dist/Calendar/hooks/useCalendarNavigation.js +4 -6
  31. package/dist/Calendar/styles.d.ts +5 -20
  32. package/dist/Calendar/styles.d.ts.map +1 -1
  33. package/dist/Calendar/styles.js +15 -17
  34. package/dist/Card/Card.d.ts +12 -12
  35. package/dist/Card/Card.d.ts.map +1 -1
  36. package/dist/Card/Card.js +17 -9
  37. package/dist/Card/index.d.ts +35 -1
  38. package/dist/Card/index.d.ts.map +1 -1
  39. package/dist/Card/index.js +21 -1
  40. package/dist/Carousel/Carousel.d.ts.map +1 -1
  41. package/dist/Carousel/Carousel.js +108 -7
  42. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  43. package/dist/CheckboxInput/CheckboxInput.js +7 -1
  44. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  45. package/dist/CodeBlock/CodeBlock.js +15 -4
  46. package/dist/CodeBlock/highlightRanges.js +1 -1
  47. package/dist/CodeBlock/highlightStyles.js +13 -13
  48. package/dist/CommandPalette/CommandPaletteItem.d.ts.map +1 -1
  49. package/dist/CommandPalette/CommandPaletteItem.js +2 -7
  50. package/dist/ComplexSelector/ComplexSelector.d.ts +10 -2
  51. package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
  52. package/dist/ComplexSelector/ComplexSelector.js +14 -7
  53. package/dist/DateInput/DateInput.d.ts +43 -0
  54. package/dist/DateInput/DateInput.d.ts.map +1 -1
  55. package/dist/DateInput/DateInput.js +22 -5
  56. package/dist/DateInput/MonthScroller.d.ts.map +1 -1
  57. package/dist/DateInput/MonthScroller.js +5 -3
  58. package/dist/DateInput/MonthYearWheels.d.ts.map +1 -1
  59. package/dist/DateInput/MonthYearWheels.js +6 -4
  60. package/dist/DateInput/NativeDateField.d.ts +10 -0
  61. package/dist/DateInput/NativeDateField.d.ts.map +1 -0
  62. package/dist/DateInput/NativeDateField.js +494 -0
  63. package/dist/DateInput/TouchDateField.d.ts.map +1 -1
  64. package/dist/DateInput/TouchDateField.js +52 -25
  65. package/dist/DateInput/Wheel.d.ts.map +1 -1
  66. package/dist/DateInput/Wheel.js +1 -0
  67. package/dist/DateInput/index.d.ts +1 -1
  68. package/dist/DateInput/index.d.ts.map +1 -1
  69. package/dist/DateInput/nativeDateSegments.d.ts +22 -0
  70. package/dist/DateInput/nativeDateSegments.d.ts.map +1 -0
  71. package/dist/DateInput/nativeDateSegments.js +111 -0
  72. package/dist/DateRangeInput/DateRangeInput.d.ts +4 -2
  73. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  74. package/dist/DateRangeInput/DateRangeInput.js +3 -5
  75. package/dist/DateTimeInput/DateTimeInput.d.ts +23 -24
  76. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  77. package/dist/DateTimeInput/DateTimeInput.js +35 -10
  78. package/dist/DateTimeInput/TouchDateTimeField.d.ts +6 -0
  79. package/dist/DateTimeInput/TouchDateTimeField.d.ts.map +1 -0
  80. package/dist/DateTimeInput/TouchDateTimeField.js +1021 -0
  81. package/dist/Dialog/Dialog.d.ts +16 -2
  82. package/dist/Dialog/Dialog.d.ts.map +1 -1
  83. package/dist/Dialog/Dialog.js +28 -7
  84. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  85. package/dist/DropdownMenu/DropdownMenu.js +4 -13
  86. package/dist/Field/FieldLabel.d.ts.map +1 -1
  87. package/dist/Field/FieldLabel.js +9 -1
  88. package/dist/Field/InputClearButton.d.ts +9 -3
  89. package/dist/Field/InputClearButton.d.ts.map +1 -1
  90. package/dist/Field/InputClearButton.js +14 -3
  91. package/dist/Heading/Heading.d.ts.map +1 -1
  92. package/dist/Heading/Heading.js +0 -1
  93. package/dist/HoverCard/HoverCard.d.ts.map +1 -1
  94. package/dist/HoverCard/HoverCard.js +104 -3
  95. package/dist/HoverCard/useHoverCard.d.ts +14 -2
  96. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  97. package/dist/HoverCard/useHoverCard.js +7 -1
  98. package/dist/Icon/Icon.d.ts +4 -2
  99. package/dist/Icon/Icon.d.ts.map +1 -1
  100. package/dist/Icon/defaultIcons.d.ts +3 -2
  101. package/dist/Icon/defaultIcons.d.ts.map +1 -1
  102. package/dist/Icon/defaultIcons.js +7 -0
  103. package/dist/Icon/globalIconRegistry.d.ts +13 -0
  104. package/dist/Icon/globalIconRegistry.d.ts.map +1 -1
  105. package/dist/Icon/globalIconRegistry.js +34 -6
  106. package/dist/Icon/index.d.ts +1 -1
  107. package/dist/Icon/index.d.ts.map +1 -1
  108. package/dist/Icon/useIcon.d.ts +5 -2
  109. package/dist/Icon/useIcon.d.ts.map +1 -1
  110. package/dist/Icon/useIcon.js +3 -0
  111. package/dist/Indicator/CheckboxIndicator.d.ts.map +1 -1
  112. package/dist/Indicator/CheckboxIndicator.js +6 -2
  113. package/dist/Item/Item.d.ts.map +1 -1
  114. package/dist/Item/Item.js +2 -2
  115. package/dist/Kbd/Kbd.d.ts.map +1 -1
  116. package/dist/Kbd/Kbd.js +2 -26
  117. package/dist/Layer/gestureCounter.d.ts +8 -0
  118. package/dist/Layer/gestureCounter.d.ts.map +1 -0
  119. package/dist/Layer/gestureCounter.js +53 -0
  120. package/dist/Layer/useLayer.d.ts +23 -13
  121. package/dist/Layer/useLayer.d.ts.map +1 -1
  122. package/dist/Layer/useLayer.js +146 -24
  123. package/dist/List/List.d.ts +1 -1
  124. package/dist/List/List.d.ts.map +1 -1
  125. package/dist/List/List.js +15 -4
  126. package/dist/Markdown/Markdown.d.ts +1 -1
  127. package/dist/Markdown/Markdown.d.ts.map +1 -1
  128. package/dist/Markdown/Markdown.js +20 -7
  129. package/dist/Markdown/parser.d.ts.map +1 -1
  130. package/dist/Markdown/parser.js +5 -3
  131. package/dist/MetadataList/MetadataListItem.d.ts +1 -1
  132. package/dist/MetadataList/MetadataListItem.d.ts.map +1 -1
  133. package/dist/MetadataList/MetadataListItem.js +4 -1
  134. package/dist/MultiSelector/MultiSelector.d.ts +18 -1
  135. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  136. package/dist/MultiSelector/MultiSelector.js +58 -11
  137. package/dist/MultiSelector/hooks.d.ts +7 -1
  138. package/dist/MultiSelector/hooks.d.ts.map +1 -1
  139. package/dist/MultiSelector/hooks.js +3 -2
  140. package/dist/NavIcon/NavIcon.d.ts.map +1 -1
  141. package/dist/NavIcon/NavIcon.js +5 -1
  142. package/dist/NavItem/navItemStyles.stylex.d.ts +0 -8
  143. package/dist/NavItem/navItemStyles.stylex.d.ts.map +1 -1
  144. package/dist/NavItem/navItemStyles.stylex.js +0 -2
  145. package/dist/NavMenu/NavHeadingMenu.d.ts +1 -1
  146. package/dist/NavMenu/NavHeadingMenu.d.ts.map +1 -1
  147. package/dist/NavMenu/NavHeadingMenu.js +7 -4
  148. package/dist/NumberInput/NumberInput.d.ts +6 -1
  149. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  150. package/dist/NumberInput/NumberInput.js +95 -126
  151. package/dist/NumberInput/numberInputCommit.d.ts +34 -0
  152. package/dist/NumberInput/numberInputCommit.d.ts.map +1 -0
  153. package/dist/NumberInput/numberInputCommit.js +71 -0
  154. package/dist/NumberInput/numberParser.d.ts +64 -0
  155. package/dist/NumberInput/numberParser.d.ts.map +1 -0
  156. package/dist/NumberInput/numberParser.js +350 -0
  157. package/dist/Outline/Outline.d.ts.map +1 -1
  158. package/dist/Outline/Outline.js +2 -3
  159. package/dist/OverflowList/OverflowList.d.ts +41 -1
  160. package/dist/OverflowList/OverflowList.d.ts.map +1 -1
  161. package/dist/OverflowList/OverflowList.js +43 -2
  162. package/dist/Popover/Popover.d.ts.map +1 -1
  163. package/dist/Popover/Popover.js +8 -14
  164. package/dist/Popover/usePopover.d.ts +15 -41
  165. package/dist/Popover/usePopover.d.ts.map +1 -1
  166. package/dist/Popover/usePopover.js +26 -7
  167. package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
  168. package/dist/PowerSearch/PowerSearchValueEditor.js +91 -18
  169. package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
  170. package/dist/PowerSearch/formatFilterValue.js +4 -2
  171. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  172. package/dist/ProgressBar/ProgressBar.js +18 -5
  173. package/dist/Resizable/useResizable.d.ts +19 -1
  174. package/dist/Resizable/useResizable.d.ts.map +1 -1
  175. package/dist/Resizable/useResizable.js +104 -38
  176. package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
  177. package/dist/SelectableCard/SelectableCard.js +9 -0
  178. package/dist/Selector/Selector.d.ts +18 -1
  179. package/dist/Selector/Selector.d.ts.map +1 -1
  180. package/dist/Selector/Selector.js +92 -21
  181. package/dist/Selector/hooks.d.ts +7 -1
  182. package/dist/Selector/hooks.d.ts.map +1 -1
  183. package/dist/Selector/hooks.js +3 -2
  184. package/dist/SideNav/SideNav.d.ts +6 -1
  185. package/dist/SideNav/SideNav.d.ts.map +1 -1
  186. package/dist/SideNav/SideNav.js +57 -27
  187. package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
  188. package/dist/SideNav/SideNavHeading.js +5 -4
  189. package/dist/SideNav/SideNavItem.d.ts +29 -4
  190. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  191. package/dist/SideNav/SideNavItem.js +75 -20
  192. package/dist/Slider/Slider.d.ts.map +1 -1
  193. package/dist/Slider/Slider.js +34 -2
  194. package/dist/Spinner/Spinner.d.ts +3 -1
  195. package/dist/Spinner/Spinner.d.ts.map +1 -1
  196. package/dist/Spinner/Spinner.js +199 -20
  197. package/dist/StatusDot/StatusDot.d.ts.map +1 -1
  198. package/dist/StatusDot/StatusDot.js +6 -1
  199. package/dist/Stepper/Step.d.ts.map +1 -1
  200. package/dist/Stepper/Step.js +7 -6
  201. package/dist/Switch/Switch.d.ts.map +1 -1
  202. package/dist/Switch/Switch.js +5 -1
  203. package/dist/Table/BaseTable.d.ts.map +1 -1
  204. package/dist/Table/BaseTable.js +6 -1
  205. package/dist/Table/Table.d.ts.map +1 -1
  206. package/dist/Table/Table.js +3 -6
  207. package/dist/Table/plugins/filtering/useTableFiltering.d.ts.map +1 -1
  208. package/dist/Table/plugins/filtering/useTableFiltering.js +73 -4
  209. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts +26 -0
  210. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  211. package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +34 -3
  212. package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
  213. package/dist/Table/plugins/selection/useTableSelection.js +25 -1
  214. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -1
  215. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +3 -4
  216. package/dist/Text/Text.d.ts.map +1 -1
  217. package/dist/Text/Text.js +0 -1
  218. package/dist/TextArea/TextArea.d.ts.map +1 -1
  219. package/dist/TextArea/TextArea.js +13 -8
  220. package/dist/Timestamp/Timestamp.d.ts +1 -1
  221. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  222. package/dist/Timestamp/Timestamp.js +10 -18
  223. package/dist/Timestamp/formatInstant.d.ts.map +1 -1
  224. package/dist/Timestamp/formatInstant.js +10 -5
  225. package/dist/Toast/Toast.d.ts +17 -2
  226. package/dist/Toast/Toast.d.ts.map +1 -1
  227. package/dist/Toast/Toast.js +77 -11
  228. package/dist/Toast/ToastViewport.d.ts +1 -0
  229. package/dist/Toast/ToastViewport.d.ts.map +1 -1
  230. package/dist/Toast/ToastViewport.js +76 -21
  231. package/dist/Toast/index.d.ts +1 -1
  232. package/dist/Toast/index.d.ts.map +1 -1
  233. package/dist/Toast/types.d.ts +38 -0
  234. package/dist/Toast/types.d.ts.map +1 -1
  235. package/dist/Toast/useToastGesture.d.ts +26 -0
  236. package/dist/Toast/useToastGesture.d.ts.map +1 -0
  237. package/dist/Toast/useToastGesture.js +223 -0
  238. package/dist/Token/Token.d.ts +1 -1
  239. package/dist/Token/Token.d.ts.map +1 -1
  240. package/dist/Token/Token.js +23 -12
  241. package/dist/Token/TokenLink.d.ts +1 -1
  242. package/dist/Token/TokenLink.d.ts.map +1 -1
  243. package/dist/Token/TokenLink.js +5 -2
  244. package/dist/Tokenizer/Tokenizer.d.ts +12 -1
  245. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  246. package/dist/Tokenizer/Tokenizer.js +31 -21
  247. package/dist/TopNav/TopNavHeading.js +2 -2
  248. package/dist/TopNav/TopNavItem.d.ts.map +1 -1
  249. package/dist/TopNav/TopNavItem.js +3 -3
  250. package/dist/TopNav/TopNavMegaMenu.d.ts +1 -1
  251. package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
  252. package/dist/TopNav/TopNavMegaMenu.js +30 -9
  253. package/dist/TopNav/TopNavMegaMenuItem.d.ts.map +1 -1
  254. package/dist/TopNav/TopNavMegaMenuItem.js +3 -3
  255. package/dist/TopNav/TopNavMenu.d.ts +1 -1
  256. package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
  257. package/dist/TopNav/TopNavMenu.js +21 -6
  258. package/dist/TreeList/TreeList.d.ts +1 -1
  259. package/dist/TreeList/TreeList.d.ts.map +1 -1
  260. package/dist/TreeList/TreeList.js +7 -2
  261. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  262. package/dist/TreeList/TreeListItem.js +2 -2
  263. package/dist/Typeahead/BaseTypeahead.d.ts +33 -0
  264. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  265. package/dist/Typeahead/BaseTypeahead.js +51 -8
  266. package/dist/Typeahead/Typeahead.d.ts +8 -1
  267. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  268. package/dist/Typeahead/Typeahead.js +2 -0
  269. package/dist/Typeahead/TypeaheadItem.d.ts +1 -1
  270. package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
  271. package/dist/Typeahead/TypeaheadItem.js +7 -2
  272. package/dist/astryx.css +87 -22
  273. package/dist/hooks/useHotkeys.d.ts.map +1 -1
  274. package/dist/hooks/useHotkeys.js +3 -25
  275. package/dist/hooks/useOverflow.d.ts.map +1 -1
  276. package/dist/hooks/useOverflow.js +14 -4
  277. package/dist/i18n/InternationalizationContext.d.ts +2 -0
  278. package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
  279. package/dist/i18n/InternationalizationContext.js +3 -1
  280. package/dist/i18n/InternationalizationProvider.d.ts.map +1 -1
  281. package/dist/i18n/InternationalizationProvider.js +3 -1
  282. package/dist/i18n/resolve.d.ts +1 -1
  283. package/dist/i18n/resolve.d.ts.map +1 -1
  284. package/dist/i18n/resolve.js +37 -38
  285. package/dist/i18n/useTranslator.d.ts.map +1 -1
  286. package/dist/i18n/useTranslator.js +2 -3
  287. package/dist/index.d.ts +1 -1
  288. package/dist/index.d.ts.map +1 -1
  289. package/dist/theme/Theme.d.ts.map +1 -1
  290. package/dist/theme/Theme.js +46 -10
  291. package/dist/theme/defineTheme.d.ts +9 -3
  292. package/dist/theme/defineTheme.d.ts.map +1 -1
  293. package/dist/theme/defineTheme.js +5 -0
  294. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  295. package/dist/theme/derivedVarRegistry.js +24 -4
  296. package/dist/theme/generateThemeRules.d.ts +21 -0
  297. package/dist/theme/generateThemeRules.d.ts.map +1 -1
  298. package/dist/theme/generateThemeRules.js +26 -0
  299. package/dist/theme/syntax/tokens.d.ts +1 -1
  300. package/dist/theme/syntax/tokens.d.ts.map +1 -1
  301. package/dist/theme/syntax/tokens.js +5 -2
  302. package/dist/theme/useTheme.d.ts.map +1 -1
  303. package/dist/theme/useTheme.js +6 -7
  304. package/dist/utils/dateParser.d.ts +5 -8
  305. package/dist/utils/dateParser.d.ts.map +1 -1
  306. package/dist/utils/dateParser.js +10 -11
  307. package/dist/utils/focusOutline.stylex.d.ts +25 -0
  308. package/dist/utils/focusOutline.stylex.d.ts.map +1 -1
  309. package/dist/utils/focusOutline.stylex.js +15 -0
  310. package/dist/utils/interactionOverlay.stylex.d.ts +26 -0
  311. package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -0
  312. package/dist/utils/interactionOverlay.stylex.js +42 -0
  313. package/dist/utils/isApplePlatform.d.ts +18 -0
  314. package/dist/utils/isApplePlatform.d.ts.map +1 -0
  315. package/dist/utils/isApplePlatform.js +37 -0
  316. package/dist/utils/plainDate.d.ts +11 -0
  317. package/dist/utils/plainDate.d.ts.map +1 -1
  318. package/dist/utils/plainDate.js +20 -4
  319. package/locales/af-ZA.json +7 -7
  320. package/locales/ar-SA.json +7 -7
  321. package/locales/ca-ES.json +6 -6
  322. package/locales/cs-CZ.json +7 -7
  323. package/locales/da-DK.json +7 -7
  324. package/locales/de-DE.json +7 -7
  325. package/locales/el-GR.json +7 -7
  326. package/locales/en.json +178 -6
  327. package/locales/es-ES.json +6 -6
  328. package/locales/fi-FI.json +7 -7
  329. package/locales/fr-FR.json +7 -7
  330. package/locales/he-IL.json +7 -7
  331. package/locales/hu-HU.json +7 -7
  332. package/locales/it-IT.json +7 -7
  333. package/locales/ja-JP.json +7 -7
  334. package/locales/ko-KR.json +7 -7
  335. package/locales/nl-NL.json +7 -7
  336. package/locales/no-NO.json +7 -7
  337. package/locales/pl-PL.json +7 -7
  338. package/locales/pseudo.json +130 -1
  339. package/locales/pt-BR.json +7 -7
  340. package/locales/pt-PT.json +7 -7
  341. package/locales/ro-RO.json +7 -7
  342. package/locales/ru-RU.json +7 -7
  343. package/locales/sr-SP.json +7 -7
  344. package/locales/sv-SE.json +7 -7
  345. package/locales/tr-TR.json +7 -7
  346. package/locales/uk-UA.json +7 -7
  347. package/locales/vi-VN.json +7 -7
  348. package/locales/zh-CN.json +7 -7
  349. package/locales/zh-TW.json +7 -7
  350. package/package.json +4 -5
  351. package/src/AlertDialog/AlertDialog.doc.mjs +114 -30
  352. package/src/AlertDialog/AlertDialog.test.tsx +211 -2
  353. package/src/AlertDialog/AlertDialog.tsx +62 -20
  354. package/src/AspectRatio/AspectRatio.doc.mjs +3 -3
  355. package/src/AspectRatio/AspectRatio.tsx +6 -6
  356. package/src/Avatar/Avatar.doc.mjs +12 -2
  357. package/src/Avatar/Avatar.test.tsx +80 -0
  358. package/src/Avatar/Avatar.tsx +64 -14
  359. package/src/Avatar/index.ts +2 -2
  360. package/src/AvatarGroup/AvatarGroup.doc.mjs +8 -2
  361. package/src/AvatarGroup/AvatarGroup.test.tsx +24 -0
  362. package/src/AvatarGroup/AvatarGroup.tsx +12 -4
  363. package/src/AvatarGroup/AvatarGroupContext.ts +5 -3
  364. package/src/AvatarGroup/AvatarGroupOverflow.tsx +12 -12
  365. package/src/Badge/Badge.doc.mjs +3 -2
  366. package/src/Badge/Badge.test.tsx +32 -3
  367. package/src/Badge/Badge.tsx +42 -1
  368. package/src/Banner/Banner.doc.mjs +9 -0
  369. package/src/Banner/Banner.test.tsx +76 -11
  370. package/src/Banner/Banner.tsx +21 -2
  371. package/src/Button/Button.doc.mjs +2 -1
  372. package/src/Button/Button.test.tsx +19 -4
  373. package/src/Button/Button.tsx +9 -29
  374. package/src/ButtonGroup/ButtonGroup.doc.mjs +2 -2
  375. package/src/ButtonGroup/ButtonGroup.test.tsx +13 -0
  376. package/src/Calendar/Calendar.doc.mjs +4 -4
  377. package/src/Calendar/Calendar.test.tsx +112 -0
  378. package/src/Calendar/Calendar.tsx +18 -16
  379. package/src/Calendar/hooks/useCalendarDays.ts +4 -4
  380. package/src/Calendar/hooks/useCalendarNavigation.ts +4 -4
  381. package/src/Calendar/styles.ts +48 -42
  382. package/src/Card/Card.doc.mjs +10 -7
  383. package/src/Card/Card.test.tsx +113 -19
  384. package/src/Card/Card.tsx +67 -89
  385. package/src/Card/index.ts +36 -1
  386. package/src/Carousel/Carousel.doc.mjs +3 -0
  387. package/src/Carousel/Carousel.test.tsx +360 -0
  388. package/src/Carousel/Carousel.tsx +116 -15
  389. package/src/CheckboxInput/CheckboxInput.doc.mjs +3 -1
  390. package/src/CheckboxInput/CheckboxInput.test.tsx +15 -0
  391. package/src/CheckboxInput/CheckboxInput.tsx +5 -0
  392. package/src/CheckboxList/CheckboxList.doc.mjs +1 -1
  393. package/src/CodeBlock/CodeBlock.doc.mjs +10 -4
  394. package/src/CodeBlock/CodeBlock.test.tsx +37 -0
  395. package/src/CodeBlock/CodeBlock.tsx +20 -4
  396. package/src/CodeBlock/highlightRanges.ts +1 -1
  397. package/src/CodeBlock/highlightStyles.ts +13 -13
  398. package/src/CommandPalette/CommandPaletteItem.tsx +2 -12
  399. package/src/ComplexSelector/ComplexSelector.doc.mjs +9 -2
  400. package/src/ComplexSelector/ComplexSelector.test.tsx +183 -0
  401. package/src/ComplexSelector/ComplexSelector.tsx +22 -12
  402. package/src/DateInput/DateInput.doc.mjs +17 -1
  403. package/src/DateInput/DateInput.test.tsx +9 -4
  404. package/src/DateInput/DateInput.tsx +54 -3
  405. package/src/DateInput/DateInputTouch.test.tsx +146 -32
  406. package/src/DateInput/MonthScroller.tsx +5 -1
  407. package/src/DateInput/MonthYearWheels.tsx +7 -4
  408. package/src/DateInput/NativeDateField.test.tsx +635 -0
  409. package/src/DateInput/NativeDateField.tsx +641 -0
  410. package/src/DateInput/TouchDateField.tsx +83 -33
  411. package/src/DateInput/Wheel.tsx +1 -0
  412. package/src/DateInput/index.ts +1 -0
  413. package/src/DateInput/nativeDateSegments.ts +127 -0
  414. package/src/DateRangeInput/DateRangeInput.doc.mjs +3 -3
  415. package/src/DateRangeInput/DateRangeInput.test.tsx +46 -0
  416. package/src/DateRangeInput/DateRangeInput.tsx +8 -13
  417. package/src/DateTimeInput/DateTimeInput.doc.mjs +39 -22
  418. package/src/DateTimeInput/DateTimeInput.test.tsx +76 -0
  419. package/src/DateTimeInput/DateTimeInput.tsx +54 -20
  420. package/src/DateTimeInput/DateTimeInputTouch.test.tsx +980 -0
  421. package/src/DateTimeInput/TouchDateTimeField.tsx +1437 -0
  422. package/src/Dialog/Dialog.test.tsx +185 -18
  423. package/src/Dialog/Dialog.tsx +35 -11
  424. package/src/DropdownMenu/DropdownMenu.test.tsx +44 -10
  425. package/src/DropdownMenu/DropdownMenu.tsx +4 -13
  426. package/src/Field/Field.doc.mjs +1 -1
  427. package/src/Field/FieldLabel.test.tsx +29 -0
  428. package/src/Field/FieldLabel.tsx +7 -0
  429. package/src/Field/InputClearButton.test.tsx +15 -1
  430. package/src/Field/InputClearButton.tsx +28 -4
  431. package/src/FieldStatus/FieldStatus.doc.mjs +1 -1
  432. package/src/FileInput/FileInput.doc.mjs +1 -1
  433. package/src/Heading/Heading.tsx +0 -1
  434. package/src/HoverCard/HoverCard.doc.mjs +8 -2
  435. package/src/HoverCard/HoverCard.test.tsx +154 -4
  436. package/src/HoverCard/HoverCard.tsx +137 -3
  437. package/src/HoverCard/useHoverCard.tsx +23 -3
  438. package/src/Icon/Icon.test.tsx +55 -1
  439. package/src/Icon/Icon.tsx +5 -3
  440. package/src/Icon/defaultIcons.tsx +11 -2
  441. package/src/Icon/globalIconRegistry.test.tsx +16 -3
  442. package/src/Icon/globalIconRegistry.tsx +37 -6
  443. package/src/Icon/index.ts +1 -0
  444. package/src/Icon/useIcon.ts +9 -2
  445. package/src/Indicator/CheckboxIndicator.tsx +14 -8
  446. package/src/Indicator/Indicator.doc.mjs +3 -1
  447. package/src/InputGroup/InputGroup.doc.mjs +1 -1
  448. package/src/Item/Item.tsx +2 -7
  449. package/src/Kbd/Kbd.test.tsx +0 -17
  450. package/src/Kbd/Kbd.tsx +2 -26
  451. package/src/Layer/gestureCounter.ts +57 -0
  452. package/src/Layer/useLayer.test.tsx +368 -16
  453. package/src/Layer/useLayer.tsx +208 -35
  454. package/src/Layout/__tests__/edgeCompensation.test.tsx +1 -1
  455. package/src/List/List.test.tsx +38 -0
  456. package/src/List/List.tsx +8 -1
  457. package/src/Markdown/Markdown.test.tsx +37 -0
  458. package/src/Markdown/Markdown.tsx +16 -5
  459. package/src/Markdown/parser.test.ts +33 -0
  460. package/src/Markdown/parser.ts +9 -3
  461. package/src/MetadataList/MetadataList.test.tsx +75 -2
  462. package/src/MetadataList/MetadataListItem.tsx +5 -2
  463. package/src/MultiSelector/MultiSelector.doc.mjs +23 -2
  464. package/src/MultiSelector/MultiSelector.test.tsx +205 -0
  465. package/src/MultiSelector/MultiSelector.tsx +103 -16
  466. package/src/MultiSelector/hooks.ts +9 -2
  467. package/src/NavIcon/NavIcon.doc.mjs +8 -2
  468. package/src/NavIcon/NavIcon.test.tsx +9 -0
  469. package/src/NavIcon/NavIcon.tsx +5 -1
  470. package/src/NavItem/navItemStyles.stylex.ts +0 -8
  471. package/src/NavMenu/NavHeadingMenu.test.tsx +30 -0
  472. package/src/NavMenu/NavHeadingMenu.tsx +7 -4
  473. package/src/NumberInput/NumberInput.doc.mjs +27 -8
  474. package/src/NumberInput/NumberInput.test.tsx +563 -8
  475. package/src/NumberInput/NumberInput.tsx +77 -131
  476. package/src/NumberInput/numberInputCommit.test.ts +72 -0
  477. package/src/NumberInput/numberInputCommit.ts +103 -0
  478. package/src/NumberInput/numberParser.docblock.test.ts +234 -0
  479. package/src/NumberInput/numberParser.test.ts +222 -0
  480. package/src/NumberInput/numberParser.ts +403 -0
  481. package/src/Outline/Outline.tsx +2 -4
  482. package/src/OverflowList/OverflowList.doc.mjs +102 -21
  483. package/src/OverflowList/OverflowList.test.tsx +550 -4
  484. package/src/OverflowList/OverflowList.tsx +100 -2
  485. package/src/Pagination/Pagination.test.tsx +3 -2
  486. package/src/Popover/Popover.doc.mjs +2 -2
  487. package/src/Popover/Popover.test.tsx +38 -0
  488. package/src/Popover/Popover.tsx +28 -66
  489. package/src/Popover/usePopover.tsx +44 -5
  490. package/src/PowerSearch/PowerSearch.doc.mjs +1 -1
  491. package/src/PowerSearch/PowerSearchEditPopover.test.tsx +87 -0
  492. package/src/PowerSearch/PowerSearchValueEditor.test.tsx +64 -0
  493. package/src/PowerSearch/PowerSearchValueEditor.tsx +109 -10
  494. package/src/PowerSearch/formatFilterValue.test.ts +16 -1
  495. package/src/PowerSearch/formatFilterValue.ts +2 -0
  496. package/src/ProgressBar/ProgressBar.doc.mjs +42 -6
  497. package/src/ProgressBar/ProgressBar.test.tsx +24 -0
  498. package/src/ProgressBar/ProgressBar.tsx +28 -8
  499. package/src/RadioList/RadioList.doc.mjs +1 -1
  500. package/src/Resizable/Resizable.doc.mjs +2 -2
  501. package/src/Resizable/useResizable.doc.mjs +21 -2
  502. package/src/Resizable/useResizable.test.ts +421 -0
  503. package/src/Resizable/useResizable.ts +133 -48
  504. package/src/SelectableCard/SelectableCard.doc.mjs +3 -0
  505. package/src/SelectableCard/SelectableCard.tsx +16 -0
  506. package/src/Selector/Selector.doc.mjs +15 -1
  507. package/src/Selector/Selector.source-build.test.mjs +65 -0
  508. package/src/Selector/Selector.test.tsx +301 -0
  509. package/src/Selector/Selector.tsx +145 -32
  510. package/src/Selector/hooks.ts +17 -2
  511. package/src/SideNav/SideNav.doc.mjs +2 -2
  512. package/src/SideNav/SideNav.test.tsx +1069 -6
  513. package/src/SideNav/SideNav.tsx +109 -38
  514. package/src/SideNav/SideNavHeading.tsx +5 -2
  515. package/src/SideNav/SideNavItem.doc.mjs +24 -3
  516. package/src/SideNav/SideNavItem.tsx +134 -44
  517. package/src/Slider/Slider.doc.mjs +2 -2
  518. package/src/Slider/Slider.test.tsx +106 -1
  519. package/src/Slider/Slider.tsx +52 -1
  520. package/src/Spinner/Spinner.doc.mjs +17 -5
  521. package/src/Spinner/Spinner.test.tsx +164 -0
  522. package/src/Spinner/Spinner.tsx +252 -22
  523. package/src/StatusDot/StatusDot.doc.mjs +8 -2
  524. package/src/StatusDot/StatusDot.test.tsx +9 -0
  525. package/src/StatusDot/StatusDot.tsx +7 -1
  526. package/src/Stepper/Step.doc.mjs +1 -1
  527. package/src/Stepper/Step.tsx +7 -14
  528. package/src/Switch/Switch.doc.mjs +3 -1
  529. package/src/Switch/Switch.test.tsx +10 -0
  530. package/src/Switch/Switch.tsx +3 -0
  531. package/src/Table/BaseTable.tsx +6 -1
  532. package/src/Table/Table.doc.mjs +5 -3
  533. package/src/Table/Table.tsx +3 -8
  534. package/src/Table/TableBody.doc.mjs +2 -2
  535. package/src/Table/TableFooter.doc.mjs +1 -1
  536. package/src/Table/TableHeader.doc.mjs +1 -1
  537. package/src/Table/plugins/filtering/useTableFiltering.test.tsx +44 -6
  538. package/src/Table/plugins/filtering/useTableFiltering.tsx +100 -4
  539. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +50 -4
  540. package/src/Table/plugins/selection/useTableSelection.test.tsx +62 -0
  541. package/src/Table/plugins/selection/useTableSelection.tsx +25 -2
  542. package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +1 -2
  543. package/src/Table/useTableGroupedRows.doc.mjs +3 -3
  544. package/src/Table/useTablePagination.doc.mjs +1 -1
  545. package/src/Table/useTableSelection.doc.mjs +1 -1
  546. package/src/Text/Text.test.tsx +44 -0
  547. package/src/Text/Text.tsx +0 -1
  548. package/src/TextArea/TextArea.doc.mjs +13 -3
  549. package/src/TextArea/TextArea.test.tsx +11 -0
  550. package/src/TextArea/TextArea.tsx +34 -22
  551. package/src/TextInput/TextInput.doc.mjs +1 -1
  552. package/src/TimeInput/TimeInput.doc.mjs +1 -1
  553. package/src/Timestamp/Timestamp.test.tsx +89 -0
  554. package/src/Timestamp/Timestamp.tsx +8 -8
  555. package/src/Timestamp/formatInstant.ts +5 -0
  556. package/src/Toast/Toast.doc.mjs +213 -44
  557. package/src/Toast/Toast.tsx +118 -23
  558. package/src/Toast/ToastViewport.test.tsx +1434 -8
  559. package/src/Toast/ToastViewport.tsx +85 -14
  560. package/src/Toast/index.ts +2 -0
  561. package/src/Toast/types.ts +43 -5
  562. package/src/Toast/useToastGesture.ts +361 -0
  563. package/src/Token/Token.test.tsx +95 -0
  564. package/src/Token/Token.tsx +19 -17
  565. package/src/Token/TokenLink.tsx +12 -3
  566. package/src/Tokenizer/Tokenizer.doc.mjs +17 -4
  567. package/src/Tokenizer/Tokenizer.test.tsx +161 -0
  568. package/src/Tokenizer/Tokenizer.tsx +49 -24
  569. package/src/TopNav/TopNavHeading.tsx +2 -2
  570. package/src/TopNav/TopNavItem.tsx +3 -7
  571. package/src/TopNav/TopNavMegaMenu.test.tsx +104 -0
  572. package/src/TopNav/TopNavMegaMenu.tsx +47 -4
  573. package/src/TopNav/TopNavMegaMenuItem.tsx +10 -9
  574. package/src/TopNav/TopNavMenu.test.tsx +133 -1
  575. package/src/TopNav/TopNavMenu.tsx +38 -5
  576. package/src/TreeList/TreeList.test.tsx +49 -0
  577. package/src/TreeList/TreeList.tsx +7 -2
  578. package/src/TreeList/TreeListItem.tsx +2 -7
  579. package/src/Typeahead/BaseTypeahead.doc.mjs +13 -0
  580. package/src/Typeahead/BaseTypeahead.tsx +96 -6
  581. package/src/Typeahead/Typeahead.doc.mjs +7 -1
  582. package/src/Typeahead/Typeahead.test.tsx +154 -0
  583. package/src/Typeahead/Typeahead.tsx +9 -0
  584. package/src/Typeahead/TypeaheadItem.test.tsx +43 -0
  585. package/src/Typeahead/TypeaheadItem.tsx +8 -1
  586. package/src/hooks/useAnnounce.doc.mjs +96 -0
  587. package/src/hooks/useDevWarning.doc.mjs +96 -0
  588. package/src/hooks/useHotkeys.test.ts +0 -18
  589. package/src/hooks/useHotkeys.ts +3 -25
  590. package/src/hooks/useIndicatorFocusRing.doc.mjs +104 -0
  591. package/src/hooks/useInputStatusIcon.doc.mjs +142 -0
  592. package/src/hooks/useInteractiveRole.doc.mjs +119 -0
  593. package/src/hooks/useLongPress.doc.mjs +123 -0
  594. package/src/hooks/useOverflow.doc.mjs +58 -17
  595. package/src/hooks/useOverflow.ts +16 -4
  596. package/src/hooks/useTypeahead.doc.mjs +153 -0
  597. package/src/i18n/InternationalizationContext.ts +3 -0
  598. package/src/i18n/InternationalizationProvider.tsx +8 -1
  599. package/src/i18n/__tests__/resolve.test.ts +23 -1
  600. package/src/i18n/resolve.ts +46 -49
  601. package/src/i18n/useTranslator.ts +2 -7
  602. package/src/index.ts +2 -0
  603. package/src/raw-import.d.ts +14 -0
  604. package/src/theme/Theme.test.tsx +104 -2
  605. package/src/theme/Theme.tsx +49 -14
  606. package/src/theme/defineTheme.test.ts +23 -0
  607. package/src/theme/defineTheme.ts +12 -3
  608. package/src/theme/derivedVarRegistry.test.ts +87 -3
  609. package/src/theme/derivedVarRegistry.ts +23 -4
  610. package/src/theme/generateThemeRules.test.ts +99 -1
  611. package/src/theme/generateThemeRules.ts +28 -0
  612. package/src/theme/syntax/tokens.ts +5 -2
  613. package/src/theme/useTheme.test.tsx +10 -0
  614. package/src/theme/useTheme.ts +16 -10
  615. package/src/utils/dateParser.test.ts +34 -2
  616. package/src/utils/dateParser.ts +11 -14
  617. package/src/utils/focusOutline.stylex.ts +50 -0
  618. package/src/utils/interactionOverlay.stylex.ts +74 -0
  619. package/src/utils/isApplePlatform.test.ts +61 -0
  620. package/src/utils/isApplePlatform.ts +37 -0
  621. package/src/utils/plainDate.test.ts +46 -0
  622. package/src/utils/plainDate.ts +18 -3
@@ -8,7 +8,7 @@ export const docs = {
8
8
  displayName: 'Table Header',
9
9
  isHiddenFromOverview: true,
10
10
  description:
11
- '<thead> wrapper for children mode. Holds the header row, whose cells are TableHeaderCell. A row must sit inside a section — <table> cannot contain a <tr> directly, because the HTML parser inserts an implied <tbody> when it parses server-rendered markup and React does not when it renders on the client, so the two trees mismatch on hydration. The data-driven data={...} mode renders this element itself whenever columns are supplied; in children mode it is yours to supply.',
11
+ '<thead> wrapper for children mode. Holds the header row, whose cells are TableHeaderCell. A row must sit inside a section: <table> cannot contain a <tr> directly, because the HTML parser inserts an implied <tbody> when it parses server-rendered markup and React does not when it renders on the client, so the two trees mismatch on hydration. The data-driven data={...} mode renders this element itself whenever columns are supplied; in children mode it is yours to supply.',
12
12
  props: [
13
13
  {
14
14
  name: 'children',
@@ -142,12 +142,15 @@ function FilterTable({
142
142
  });
143
143
 
144
144
  return (
145
- <Table
146
- data={testData}
147
- columns={columns}
148
- idKey="id"
149
- plugins={{filter: filterPlugin}}
150
- />
145
+ <>
146
+ <Table
147
+ data={testData}
148
+ columns={columns}
149
+ idKey="id"
150
+ plugins={{filter: filterPlugin}}
151
+ />
152
+ <output data-testid="filters">{JSON.stringify(filters)}</output>
153
+ </>
151
154
  );
152
155
  }
153
156
 
@@ -210,6 +213,41 @@ describe('useTableFiltering', () => {
210
213
  await user.type(textInputs[0], 'Alice');
211
214
  expect(textInputs[0]).toHaveValue('Alice');
212
215
  });
216
+
217
+ it('updates a number filter while typing', async () => {
218
+ const user = userEvent.setup();
219
+ render(<FilterTable variant="inline" />);
220
+ const input = screen.getByRole('spinbutton', {name: 'Filter Age'});
221
+
222
+ await user.type(input, '30');
223
+
224
+ expect(screen.getByTestId('filters')).toHaveTextContent('{"age":30}');
225
+ });
226
+
227
+ it('restores the pre-edit number filter when an invalid draft blurs', async () => {
228
+ const user = userEvent.setup();
229
+ render(<FilterTable variant="inline" />);
230
+ const input = screen.getByRole('spinbutton', {name: 'Filter Age'});
231
+
232
+ await user.type(input, '3·');
233
+ expect(screen.getByTestId('filters')).toHaveTextContent('{"age":3}');
234
+ await user.tab();
235
+
236
+ expect(screen.getByTestId('filters')).toHaveTextContent('{}');
237
+ });
238
+
239
+ it('restores the pre-edit number filter when Enter rejects a draft', async () => {
240
+ const user = userEvent.setup();
241
+ render(<FilterTable variant="inline" />);
242
+ const input = screen.getByRole('spinbutton', {name: 'Filter Age'});
243
+
244
+ await user.type(input, '3·');
245
+ await user.keyboard('{Enter}');
246
+
247
+ expect(input).toHaveValue('3·');
248
+ expect(input).toHaveAttribute('aria-invalid', 'true');
249
+ expect(screen.getByTestId('filters')).toHaveTextContent('{}');
250
+ });
213
251
  });
214
252
 
215
253
  describe('field reference forms', () => {
@@ -20,6 +20,9 @@ import {
20
20
  useMemo,
21
21
  useState,
22
22
  useCallback,
23
+ type FocusEvent,
24
+ type FormEvent,
25
+ type KeyboardEvent,
23
26
  type ReactNode,
24
27
  } from 'react';
25
28
  import * as stylex from '@stylexjs/stylex';
@@ -29,6 +32,10 @@ import {Button} from '../../../Button';
29
32
  import {Popover} from '../../../Popover';
30
33
  import {TextInput} from '../../../TextInput';
31
34
  import {NumberInput} from '../../../NumberInput';
35
+ import {
36
+ parseNumberInput,
37
+ resolveNumberInputCommit,
38
+ } from '../../../NumberInput/numberInputCommit';
32
39
  import {DateInput} from '../../../DateInput';
33
40
  import type {ISODateString} from '../../../utils/dateTypes';
34
41
  import {TimeInput} from '../../../TimeInput';
@@ -42,7 +49,7 @@ import type {
42
49
  HeaderCellRenderProps,
43
50
  } from '../../types';
44
51
  import {proportional} from '../../columnUtils';
45
- import {useTranslator} from '../../../i18n';
52
+ import {useLocale, useTranslator} from '../../../i18n';
46
53
  import type {
47
54
  PowerSearchConfig,
48
55
  PowerSearchField,
@@ -445,6 +452,80 @@ function TextFilterControl({
445
452
  );
446
453
  }
447
454
 
455
+ function useLiveNumberFilter({
456
+ value,
457
+ min,
458
+ max,
459
+ hasClear,
460
+ onChange,
461
+ }: {
462
+ value: number | null;
463
+ min?: number | null;
464
+ max?: number | null;
465
+ hasClear: boolean;
466
+ onChange: (value: number | null) => void;
467
+ }) {
468
+ const locale = useLocale();
469
+ const editStartValueRef = useRef(value);
470
+
471
+ const handleChange = useCallback(
472
+ (nextValue: number | null) => {
473
+ editStartValueRef.current = nextValue;
474
+ onChange(nextValue);
475
+ },
476
+ [onChange],
477
+ );
478
+ const handleFocus = useCallback(() => {
479
+ editStartValueRef.current = value;
480
+ }, [value]);
481
+ const handleInput = useCallback(
482
+ (event: FormEvent<HTMLElement>) => {
483
+ const nextValue = parseNumberInput(
484
+ (event.currentTarget as HTMLInputElement).value,
485
+ {
486
+ min,
487
+ max,
488
+ locale,
489
+ },
490
+ );
491
+ if (nextValue !== null && nextValue !== value) {
492
+ onChange(nextValue);
493
+ }
494
+ },
495
+ [locale, max, min, onChange, value],
496
+ );
497
+ const restoreRejectedDraft = useCallback(
498
+ (input: HTMLInputElement) => {
499
+ const decision = resolveNumberInputCommit(input.value, {
500
+ min,
501
+ max,
502
+ locale,
503
+ hasClear,
504
+ });
505
+ if (decision.type === 'revert' && value !== editStartValueRef.current) {
506
+ onChange(editStartValueRef.current);
507
+ }
508
+ },
509
+ [hasClear, locale, max, min, onChange, value],
510
+ );
511
+ const handleBlur = useCallback(
512
+ (event: FocusEvent<HTMLInputElement>) => {
513
+ restoreRejectedDraft(event.currentTarget);
514
+ },
515
+ [restoreRejectedDraft],
516
+ );
517
+ const handleKeyDown = useCallback(
518
+ (event: KeyboardEvent<HTMLInputElement>) => {
519
+ if (event.key === 'Enter') {
520
+ restoreRejectedDraft(event.currentTarget);
521
+ }
522
+ },
523
+ [restoreRejectedDraft],
524
+ );
525
+
526
+ return {handleBlur, handleChange, handleFocus, handleInput, handleKeyDown};
527
+ }
528
+
448
529
  function NumberFilterControl({
449
530
  columnKey,
450
531
  header,
@@ -466,12 +547,19 @@ function NumberFilterControl({
466
547
 
467
548
  const step = operatorValue.type === 'integer' ? 1 : null;
468
549
 
469
- const handleChange = useCallback(
550
+ const updateFilter = useCallback(
470
551
  (newValue: number | null) => {
471
552
  store.getConfig().onFilterChange(columnKey, newValue);
472
553
  },
473
554
  [store, columnKey],
474
555
  );
556
+ const liveFilter = useLiveNumberFilter({
557
+ value: numValue,
558
+ min: operatorValue.minValue,
559
+ max: operatorValue.maxValue,
560
+ hasClear: !!hasClear,
561
+ onChange: updateFilter,
562
+ });
475
563
 
476
564
  if (hasClear) {
477
565
  return (
@@ -479,7 +567,11 @@ function NumberFilterControl({
479
567
  label={t('@astryx.tableFiltering.filterByColumn', {header})}
480
568
  isLabelHidden
481
569
  value={numValue}
482
- onChange={handleChange}
570
+ onChange={liveFilter.handleChange}
571
+ onFocus={liveFilter.handleFocus}
572
+ onInput={liveFilter.handleInput}
573
+ onBlur={liveFilter.handleBlur}
574
+ onKeyDown={liveFilter.handleKeyDown}
483
575
  placeholder={t('@astryx.tableFiltering.filterByColumn', {header})}
484
576
  min={operatorValue.minValue ?? null}
485
577
  max={operatorValue.maxValue ?? null}
@@ -495,7 +587,11 @@ function NumberFilterControl({
495
587
  label={t('@astryx.tableFiltering.filterByColumn', {header})}
496
588
  isLabelHidden
497
589
  value={numValue}
498
- onChange={handleChange}
590
+ onChange={liveFilter.handleChange}
591
+ onFocus={liveFilter.handleFocus}
592
+ onInput={liveFilter.handleInput}
593
+ onBlur={liveFilter.handleBlur}
594
+ onKeyDown={liveFilter.handleKeyDown}
499
595
  placeholder={t('@astryx.tableFiltering.filterByColumn', {header})}
500
596
  min={operatorValue.minValue ?? null}
501
597
  max={operatorValue.maxValue ?? null}
@@ -126,15 +126,31 @@ const styles = stylex.create({
126
126
  },
127
127
  headerCell: {
128
128
  paddingBlock: spacingVars['--spacing-2'],
129
- // No inline start padding so the chevron aligns with the table's leading
130
- // edge (Ernest review #1).
131
- paddingInlineStart: spacingVars['--spacing-1'],
129
+ // The start gutter lives on headerInner instead, so that it travels with
130
+ // the heading when the heading pins. Left here, the heading would sit one
131
+ // gutter in at rest and jump flush the moment it stuck.
132
+ paddingInlineStart: 0,
132
133
  paddingInlineEnd: spacingVars['--spacing-3'],
133
134
  },
135
+ // The cell spans every column, so on a table scrolled sideways the heading
136
+ // would slide out of view while the columns it names stay pinned. Sticking
137
+ // the inner span to the start edge keeps the chevron and the label together
138
+ // and on screen.
134
139
  headerInner: {
135
140
  display: 'flex',
136
141
  alignItems: 'center',
137
142
  gap: spacingVars['--spacing-1'],
143
+ insetInlineStart: 0,
144
+ position: 'sticky',
145
+ // No inline start padding on the cell, so the chevron aligns with the
146
+ // table's leading edge (Ernest review #1).
147
+ paddingInlineStart: spacingVars['--spacing-1'],
148
+ },
149
+ // Applied alongside headerInner when using the built-in default heading.
150
+ // A custom `renderGroupHeader` may need the full column width, so the
151
+ // shrink-wrap is opt-in rather than unconditional.
152
+ headerInnerFitContent: {
153
+ width: 'fit-content',
138
154
  },
139
155
  // Standalone chevron button with no heavy chrome (transparent, borderless,
140
156
  // zero padding) so the icon sits flush with the start of the table
@@ -222,6 +238,32 @@ const styles = stylex.create({
222
238
  * plugins={{grouped: grouped.plugin}}
223
239
  * />;
224
240
  * ```
241
+ *
242
+ * ## Pairing with pagination
243
+ *
244
+ * Grouping runs on the rows it is handed, so the order is filter, sort, slice,
245
+ * then group. Sort by the group key first and the reader's own keys second —
246
+ * the same `ORDER BY group, sort` a backend would run. That keeps a section's
247
+ * rows contiguous in the result set, so pages fill sections in order and new
248
+ * rows always land at the bottom of the table. Slice a differently-ordered
249
+ * list and every page holds a scatter of sections instead, so loading more
250
+ * splices rows into the middle and new headings appear above the fold.
251
+ *
252
+ * @example
253
+ * ```
254
+ * const ordered = useMemo(
255
+ * () => [...filtered].sort((a, b) => byTeam(a, b) || bySortKeys(a, b)),
256
+ * [filtered, sortKeys],
257
+ * );
258
+ * const page = ordered.slice(0, loadedCount);
259
+ *
260
+ * const grouped = useTableGroupedRows({
261
+ * data: page,
262
+ * groupBy: r => r.team,
263
+ * collapsedGroups,
264
+ * onToggleGroup,
265
+ * });
266
+ * ```
225
267
  */
226
268
  export function useTableGroupedRows<T extends Record<string, unknown>>(
227
269
  config: UseTableGroupedRowsConfig<T>,
@@ -342,7 +384,11 @@ export function useTableGroupedRows<T extends Record<string, unknown>>(
342
384
  // to the actual number of columns, so the header always spans the
343
385
  // full width without the plugin knowing the column count.
344
386
  <td colSpan={999} {...stylex.props(styles.headerCell)}>
345
- <span {...stylex.props(styles.headerInner)}>
387
+ <span
388
+ {...stylex.props(
389
+ styles.headerInner,
390
+ !renderGroupHeader && styles.headerInnerFitContent,
391
+ )}>
346
392
  {/* Standalone chevron button, flush with the table's start
347
393
  edge (no heavy button chrome) — the keyboard control. */}
348
394
  <button
@@ -285,6 +285,68 @@ describe('useTableSelection', () => {
285
285
  'aria-selected',
286
286
  );
287
287
  });
288
+
289
+ // A pinned cell paints over the row, then replays whatever the row
290
+ // published as --table-row-overlay. Without the variable the wash simply
291
+ // stops at the freeze line, so it has to track the background exactly.
292
+ describe('--table-row-overlay', () => {
293
+ const readOverlay = (row: HTMLElement) =>
294
+ row.style.getPropertyValue('--table-row-overlay');
295
+
296
+ it('publishes the wash so pinned cells can replay it', async () => {
297
+ const user = userEvent.setup();
298
+ render(<SelectionTable />);
299
+
300
+ await user.click(screen.getAllByLabelText('Select row')[0]);
301
+
302
+ expect(readOverlay(screen.getAllByRole('row')[1])).toBe(
303
+ selectedBgColor,
304
+ );
305
+ });
306
+
307
+ it('publishes nothing when the row is not painted', async () => {
308
+ const user = userEvent.setup();
309
+ render(<SelectionTable hasRowHighlight={false} />);
310
+
311
+ await user.click(screen.getAllByLabelText('Select row')[0]);
312
+
313
+ expect(readOverlay(screen.getAllByRole('row')[1])).toBe('');
314
+ });
315
+
316
+ it('withdraws the variable when a row is unchecked', async () => {
317
+ const user = userEvent.setup();
318
+ render(<SelectionTable />);
319
+
320
+ const checkbox = screen.getAllByLabelText('Select row')[0];
321
+ await user.click(checkbox);
322
+ await user.click(checkbox);
323
+
324
+ expect(readOverlay(screen.getAllByRole('row')[1])).toBe('');
325
+ });
326
+
327
+ it('tracks the background when the flag flips', async () => {
328
+ const user = userEvent.setup();
329
+ const {rerender} = render(<SelectionTable />);
330
+
331
+ await user.click(screen.getAllByLabelText('Select row')[0]);
332
+ rerender(<SelectionTable hasRowHighlight={false} />);
333
+ expect(readOverlay(screen.getAllByRole('row')[1])).toBe('');
334
+
335
+ rerender(<SelectionTable hasRowHighlight />);
336
+ expect(readOverlay(screen.getAllByRole('row')[1])).toBe(
337
+ selectedBgColor,
338
+ );
339
+ });
340
+
341
+ it('leaves unchecked rows without the variable', async () => {
342
+ const user = userEvent.setup();
343
+ render(<SelectionTable />);
344
+
345
+ await user.click(screen.getAllByLabelText('Select row')[0]);
346
+
347
+ expect(readOverlay(screen.getAllByRole('row')[2])).toBe('');
348
+ });
349
+ });
288
350
  });
289
351
 
290
352
  it('unsubscribes detached row refs instead of accumulating listeners', () => {
@@ -159,8 +159,24 @@ function applyRowSelectionStyle(
159
159
  }
160
160
  // Written on every pass, not just when painting: the flag can flip while a
161
161
  // row is already selected, and the wash has to come back off.
162
- el.style.backgroundColor =
163
- isSelected && hasRowHighlight ? selectedBgColor : '';
162
+ const wash = isSelected && hasRowHighlight ? selectedBgColor : '';
163
+ if (el.style.backgroundColor !== wash) {
164
+ el.style.backgroundColor = wash;
165
+ }
166
+ // A pinned column paints its own opaque background over the row, so the
167
+ // wash alone stops at the freeze line. Publishing it as the row overlay is
168
+ // what lets useTableStickyColumns replay it on those cells — the same
169
+ // contract TableRow honours for striping and hover.
170
+ const currentOverlay = el.style.getPropertyValue(ROW_OVERLAY_VAR);
171
+ if (wash === '') {
172
+ if (currentOverlay !== '') {
173
+ el.style.removeProperty(ROW_OVERLAY_VAR);
174
+ }
175
+ } else {
176
+ if (currentOverlay !== wash) {
177
+ el.style.setProperty(ROW_OVERLAY_VAR, wash);
178
+ }
179
+ }
164
180
  }
165
181
 
166
182
  // =============================================================================
@@ -306,6 +322,13 @@ function SelectionCellContentInner<T extends Record<string, unknown>>({
306
322
 
307
323
  const selectedBgColor = colorVars['--color-accent-muted'];
308
324
 
325
+ /**
326
+ * The row's current fill, republished for pinned cells to read. Declared as a
327
+ * literal rather than imported because StyleX needs the same name as a static
328
+ * key on the reading side, so there is no one constant both ends can share.
329
+ */
330
+ const ROW_OVERLAY_VAR = '--table-row-overlay';
331
+
309
332
  const selectionColumnStyles = stylex.create({
310
333
  center: {
311
334
  display: 'flex',
@@ -210,8 +210,7 @@ const stickyStyles = stylex.create({
210
210
  // ::after gradient strip just past the pinned edge (visible thanks to the cell's
211
211
  // overflow: visible). Opacity is gated by the scroll-state variable above.
212
212
  const SHADOW_WIDTH = '6px';
213
- // --color-shadow is only ~10% alpha (too faint here); use a slightly stronger soft tint.
214
- const SHADOW_TINT = 'light-dark(rgba(0, 0, 0, 0.12), rgba(0, 0, 0, 0.32))';
213
+ const SHADOW_TINT = colorVars['--color-shadow'];
215
214
  const shadowStyles = stylex.create({
216
215
  // start-pinned: shadow falls toward inline-end (over scrolled content).
217
216
  // insetInlineEnd anchors the strip to the column's inline-end edge; the strip
@@ -7,7 +7,7 @@ export const docs = {
7
7
  subComponentOf: 'Table',
8
8
  displayName: 'useTableGroupedRows',
9
9
  description:
10
- "Hook that groups a flat data array into collapsible section rows. Each distinct groupBy value becomes a full-width section-header row with a chevron toggle, the group label, and a member count; collapsing hides that group's data rows while keeping the header visible. Mirrors useTableTreeState: the consumer owns the collapsedGroups set and the hook returns {data, plugin, idKey}: pass them to Table as data, plugins, and idKey respectively.",
10
+ "Hook that groups a flat data array into collapsible section rows. Each distinct groupBy value becomes a full-width section-header row with a chevron toggle, the group label, and a member count; collapsing hides that group's data rows while keeping the header visible. Mirrors useTableTreeState: the consumer owns the collapsedGroups set and the hook returns {data, plugin, idKey}: pass them to Table as data, plugins, and idKey respectively. Grouping runs on the rows you hand it, so with pagination the order is filter, sort, slice, then group \u2014 sort by the group key first and the user's keys second, so a section's rows stay contiguous and each page appends to the bottom of the table instead of splicing rows in above the reader. A page that ends on a row count still cuts mid-section, and the heading then counts what has loaded rather than what exists \u2014 \"6\" quietly becoming \"10\". Where the full result set is in hand, carry the cut forward to the end of the section it lands in: every rendered section is then whole and its count is a total.",
11
11
  props: [
12
12
  {
13
13
  name: 'data',
@@ -58,14 +58,14 @@ export const docs = {
58
58
  /** @type {import('@astryxdesign/cli/authoring').ComponentTranslationDoc} */
59
59
  export const docsDense = {
60
60
  description:
61
- 'Groups a flat data array into collapsible section rows. Each groupBy value becomes a full-width header (chevron + label + count); collapsing hides its rows. Returns {data, plugin, idKey}: pass them to Table data / plugins / idKey. Consumer owns the collapsedGroups set.',
61
+ 'Groups a flat data array into collapsible section rows. Each groupBy value becomes a full-width header (chevron + label + count); collapsing hides its rows. Returns {data, plugin, idKey}: pass them to Table data / plugins / idKey. Consumer owns the collapsedGroups set. Under pagination the order is filter, sort, slice, group \u2014 sort by the group key first so sections stay contiguous and pages append at the bottom. A row-count cut lands mid-section and the heading counts the page, not the section; where the whole result set is in hand, carry the cut to the end of the section it lands in so every rendered section is complete.',
62
62
  propDescriptions: {
63
63
  data: 'The flat data to group.',
64
64
  groupBy: "Derive a row's group key. Same key = same section.",
65
65
  collapsedGroups: 'Set of currently-collapsed group keys.',
66
66
  onToggleGroup: 'Called with the group key when a header is toggled.',
67
67
  renderGroupHeader:
68
- "Custom header content (right of chevron). Default '<key> (<count>)'.",
68
+ "Custom header content (right of chevron). Default '<key> (<count>)'. Args: (key, count, collapsed).",
69
69
  getRowKey: 'Stable key for a real row; positional fallback when omitted.',
70
70
  groupOrder: 'Pin these group keys first; others keep first-seen order.',
71
71
  },
@@ -75,7 +75,7 @@ export const docs = {
75
75
  {
76
76
  name: 'label',
77
77
  type: 'string',
78
- description: "Accessible name for the pagination nav landmark. With position='both' the two navs get distinct names — the label suffixed as '(top)' and '(bottom)' — so same-type landmarks stay unique (axe landmark-unique).",
78
+ description: "Accessible name for the pagination nav landmark. With position='both' the two navs get distinct names (the label suffixed as '(top)' and '(bottom)') so same-type landmarks stay unique (axe landmark-unique).",
79
79
  default: "'Table pagination'",
80
80
  },
81
81
  ],
@@ -65,7 +65,7 @@ export const docs = {
65
65
  name: 'hasRowHighlight',
66
66
  type: 'boolean',
67
67
  description:
68
- 'Paints checked rows with the accent wash. Set false when the surrounding UI already uses row background to mean something else (a row open in a detail panel, say) — the wash is an inline style, so it cannot be overridden from userland. Only the background is dropped: aria-selected is still set on checked rows either way.',
68
+ 'Paints checked rows with the accent wash. Set false when the surrounding UI already uses row background to mean something else (a row open in a detail panel, say). The wash is an inline style, so it cannot be overridden from userland. Only the background is dropped: aria-selected is still set on checked rows either way.',
69
69
  default: 'true',
70
70
  },
71
71
  ],
@@ -297,3 +297,47 @@ describe('Text custom colors', () => {
297
297
  expect(screen.getByText('Accent').className).toContain('accent');
298
298
  });
299
299
  });
300
+
301
+ // A truncated Text rendered its own Tooltip AND set `title` with the same
302
+ // string, so the browser drew a second, unstyled tooltip on top of ours.
303
+ describe('truncated text shows one tooltip, not two', () => {
304
+ function withOverflow() {
305
+ const proto = window.HTMLElement.prototype;
306
+ const original = {
307
+ scrollWidth: Object.getOwnPropertyDescriptor(proto, 'scrollWidth'),
308
+ offsetWidth: Object.getOwnPropertyDescriptor(proto, 'offsetWidth'),
309
+ };
310
+ Object.defineProperty(proto, 'scrollWidth', {
311
+ configurable: true,
312
+ get: () => 400,
313
+ });
314
+ Object.defineProperty(proto, 'offsetWidth', {
315
+ configurable: true,
316
+ get: () => 100,
317
+ });
318
+ return () => {
319
+ if (original.scrollWidth) {
320
+ Object.defineProperty(proto, 'scrollWidth', original.scrollWidth);
321
+ }
322
+ if (original.offsetWidth) {
323
+ Object.defineProperty(proto, 'offsetWidth', original.offsetWidth);
324
+ }
325
+ };
326
+ }
327
+
328
+ it('leaves the native title to the tooltip it already renders', () => {
329
+ const restore = withOverflow();
330
+ try {
331
+ render(
332
+ <Text type="body" maxLines={1}>
333
+ A label far wider than the space it has been given
334
+ </Text>,
335
+ );
336
+ expect(
337
+ screen.getByText('A label far wider than the space it has been given'),
338
+ ).not.toHaveAttribute('title');
339
+ } finally {
340
+ restore();
341
+ }
342
+ });
343
+ });
package/src/Text/Text.tsx CHANGED
@@ -313,7 +313,6 @@ export function Text({
313
313
  className,
314
314
  {...style, ...inlineStyle},
315
315
  )}
316
- title={tooltipEnabled ? truncation.fullText : undefined}
317
316
  {...props}>
318
317
  {children}
319
318
  </Component>
@@ -5,7 +5,7 @@
5
5
  export const docs = {
6
6
  name: 'TextArea',
7
7
  displayName: 'Text Area',
8
- category: 'Data Input',
8
+ category: 'Form Controls',
9
9
  keywords: ["textarea","textfield","multiline","comment","message","autoresize","autosize","charlimit"],
10
10
  props: [
11
11
  {
@@ -186,7 +186,12 @@ export const docs = {
186
186
  ],
187
187
  theming: {
188
188
  targets: [
189
- {className: 'astryx-textarea', visualProps: ['size', 'status'], states: ['disabled', 'readonly']},
189
+ {className: 'astryx-text-area', visualProps: ['size', 'status'], states: ['disabled', 'readonly']},
190
+ {className: 'astryx-text-area-control'},
191
+ {className: 'astryx-text-area-counter'},
192
+ // Still emitted beside the names above, so themes written against
193
+ // them keep working. Drop in the next major.
194
+ {className: 'astryx-textarea', visualProps: ['size', 'status'], states: ['disabled', 'readonly'], deprecatedFor: 'text-area'},
190
195
  ],
191
196
  vars: [
192
197
  {
@@ -381,7 +386,12 @@ export const docsZh = {
381
386
  ],
382
387
  theming: {
383
388
  targets: [
384
- {className: 'astryx-textarea', visualProps: ['size', 'status'], states: ['disabled', 'readonly']},
389
+ {className: 'astryx-text-area', visualProps: ['size', 'status'], states: ['disabled', 'readonly']},
390
+ {className: 'astryx-text-area-control'},
391
+ {className: 'astryx-text-area-counter'},
392
+ // Still emitted beside the names above, so themes written against
393
+ // them keep working. Drop in the next major.
394
+ {className: 'astryx-textarea', visualProps: ['size', 'status'], states: ['disabled', 'readonly'], deprecatedFor: 'text-area'},
385
395
  ],
386
396
  vars: [
387
397
  {
@@ -1155,3 +1155,14 @@ describe('TextArea readonly theme state', () => {
1155
1155
  expect(root).not.toHaveAttribute('data-readonly');
1156
1156
  });
1157
1157
  });
1158
+
1159
+ describe('TextArea theme target names', () => {
1160
+ it('renders the deprecated class beside the current one', () => {
1161
+ const {container} = render(
1162
+ <TextArea label="Notes" value="" onChange={() => {}} />,
1163
+ );
1164
+ const root = container.querySelector('.astryx-text-area');
1165
+ expect(root).not.toBeNull();
1166
+ expect(root).toHaveClass('astryx-textarea');
1167
+ });
1168
+ });