@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
@@ -9,6 +9,8 @@
9
9
  * @position Core implementation; consumed by index.ts, tested by NumberInput.test.tsx
10
10
  *
11
11
  * SYNC: When modified, update these files to stay in sync:
12
+ * - /packages/core/src/NumberInput/numberParser.ts (locale-aware parsing)
13
+ * - /packages/core/src/NumberInput/numberInputCommit.ts (draft commit policy)
12
14
  * - /packages/core/src/NumberInput/NumberInput.doc.mjs (props table, features, implementation notes)
13
15
  * - /packages/core/src/NumberInput/NumberInput.test.tsx (tests for new/changed behavior)
14
16
  * - /packages/core/src/NumberInput/index.ts (exports if types change)
@@ -49,6 +51,7 @@ import {Icon, renderIconSlot, type IconType} from '../Icon';
49
51
  import {VisuallyHidden} from '../VisuallyHidden';
50
52
  import {useTooltip} from '../Tooltip';
51
53
  import {getInputARIA} from '../utils';
54
+ import {interactionOverlayStyles} from '../utils/interactionOverlay.stylex';
52
55
  import {useSize} from '../SizeContext/SizeContext';
53
56
  import {useInputContainer} from '../hooks/useInputContainer';
54
57
  import {useInputStatusIcon} from '../hooks/useInputStatusIcon';
@@ -159,13 +162,6 @@ const styles = stylex.create({
159
162
  borderStyle: 'none',
160
163
  color: colorVars['--color-icon-secondary'],
161
164
  backgroundColor: colorVars['--color-background-surface'],
162
- backgroundImage: {
163
- default: null,
164
- ':hover:where(:not(:disabled,[aria-disabled="true"]))': {
165
- '@media (hover: hover)': `linear-gradient(${colorVars['--color-overlay-hover']}, ${colorVars['--color-overlay-hover']})`,
166
- },
167
- ':active': `linear-gradient(${colorVars['--color-overlay-pressed']}, ${colorVars['--color-overlay-pressed']})`,
168
- },
169
165
  cursor: {
170
166
  default: 'pointer',
171
167
  ':is(:disabled,[aria-disabled="true"])': 'default',
@@ -213,7 +209,9 @@ import {isImeKeyEvent, mergeProps, mergeRefs} from '../utils';
213
209
  import type {BaseProps} from '../BaseProps';
214
210
  import type {SizeValue} from '../utils/types';
215
211
  import {themeProps} from '../utils/themeProps';
216
- import {useTranslator} from '../i18n';
212
+ import {useTranslator, useLocale} from '../i18n';
213
+ import {formatEditableNumber} from './numberParser';
214
+ import {parseNumberInput, resolveNumberInputCommit} from './numberInputCommit';
217
215
 
218
216
  interface NumberInputPropsBase extends Omit<
219
217
  BaseProps,
@@ -348,10 +346,12 @@ interface NumberInputPropsBase extends Omit<
348
346
  autoComplete?: string;
349
347
  /**
350
348
  * The minimum value allowed.
349
+ * A smaller entry commits at this value on blur or Enter.
351
350
  */
352
351
  min?: number | null;
353
352
  /**
354
353
  * The maximum value allowed.
354
+ * A larger entry commits at this value on blur or Enter.
355
355
  */
356
356
  max?: number | null;
357
357
  /**
@@ -425,46 +425,6 @@ type NumberInputPropsClearable = NumberInputPropsBase & {
425
425
  export type NumberInputProps =
426
426
  NumberInputPropsNonClearable | NumberInputPropsClearable;
427
427
 
428
- /**
429
- * Parse and validate a string input as a number.
430
- * Returns null if the input is not a valid number or fails validation.
431
- */
432
- function parseNumberInput(
433
- input: string,
434
- options: {
435
- min?: number | null;
436
- max?: number | null;
437
- isIntegerOnly?: boolean;
438
- },
439
- ): number | null {
440
- const trimmed = input.trim();
441
- if (trimmed === '' || trimmed === '-') {
442
- return null;
443
- }
444
-
445
- const num = Number(trimmed);
446
- if (!Number.isFinite(num)) {
447
- return null;
448
- }
449
-
450
- // Check integer constraint
451
- if (options.isIntegerOnly && !Number.isInteger(num)) {
452
- return null;
453
- }
454
-
455
- // Check min constraint
456
- if (options.min != null && num < options.min) {
457
- return null;
458
- }
459
-
460
- // Check max constraint
461
- if (options.max != null && num > options.max) {
462
- return null;
463
- }
464
-
465
- return num;
466
- }
467
-
468
428
  type StepDirection = -1 | 1;
469
429
 
470
430
  function getDecimalPlaces(value: number): number {
@@ -525,6 +485,14 @@ function getSteppedValue({
525
485
  nextValue = stepBase + nextStepPosition * effectiveStep;
526
486
  }
527
487
 
488
+ const precision = Math.min(
489
+ 12,
490
+ Math.max(getDecimalPlaces(effectiveStep), getDecimalPlaces(stepBase)),
491
+ );
492
+ nextValue = Number(nextValue.toFixed(precision));
493
+
494
+ // Clamp after rounding so a bound with finer precision than the step cannot
495
+ // be rounded back out of its own range.
528
496
  if (min != null) {
529
497
  nextValue = Math.max(min, nextValue);
530
498
  }
@@ -535,21 +503,16 @@ function getSteppedValue({
535
503
  if (!Number.isFinite(nextValue)) {
536
504
  return currentValue;
537
505
  }
538
-
539
- const precision = Math.min(
540
- 12,
541
- Math.max(getDecimalPlaces(effectiveStep), getDecimalPlaces(stepBase)),
542
- );
543
- const roundedValue = Number(nextValue.toFixed(precision));
544
- if (isIntegerOnly && !Number.isInteger(roundedValue)) {
506
+ if (isIntegerOnly && !Number.isInteger(nextValue)) {
545
507
  return currentValue;
546
508
  }
547
- return Object.is(roundedValue, -0) ? 0 : roundedValue;
509
+ return Object.is(nextValue, -0) ? 0 : nextValue;
548
510
  }
549
511
 
550
512
  /**
551
513
  * A number input component for collecting numeric user input.
552
- * Only calls onChange when the entered value passes validation.
514
+ * Commits text edits on blur or Enter and only calls onChange when the whole
515
+ * draft passes validation.
553
516
  *
554
517
  * @example
555
518
  * ```
@@ -599,6 +562,7 @@ export function NumberInput({
599
562
  ...rest
600
563
  }: NumberInputProps) {
601
564
  const t = useTranslator();
565
+ const locale = useLocale();
602
566
  const isEffectivelyRequired = useResolvedRequired({isRequired, isOptional});
603
567
  const size = useSize(sizeProp, 'md');
604
568
  const id = useId();
@@ -653,6 +617,11 @@ export function NumberInput({
653
617
  inputGroup,
654
618
  );
655
619
 
620
+ const parseInput = useCallback(
621
+ (text: string) => parseNumberInput(text, {min, max, isIntegerOnly, locale}),
622
+ [isIntegerOnly, locale, max, min],
623
+ );
624
+
656
625
  const formattedValue = useMemo(() => {
657
626
  if (value == null) {
658
627
  return '';
@@ -669,36 +638,29 @@ export function NumberInput({
669
638
  if (value == null) {
670
639
  return '';
671
640
  }
672
- return isFocused ? String(value) : formattedValue;
673
- }, [formattedValue, isFocused, pendingInput, value]);
641
+ return isFocused ? formatEditableNumber(value, locale) : formattedValue;
642
+ }, [formattedValue, isFocused, locale, pendingInput, value]);
674
643
 
675
644
  // Check if current pending input is valid (for styling purposes)
676
645
  const isInputValid = useMemo(() => {
677
646
  if (pendingInput === null || !pendingInput.trim()) {
678
647
  return true;
679
648
  }
680
- return parseNumberInput(pendingInput, {min, max, isIntegerOnly}) !== null;
681
- }, [pendingInput, min, max, isIntegerOnly]);
649
+ return parseInput(pendingInput) !== null;
650
+ }, [pendingInput, parseInput]);
682
651
 
683
- // Handle input text change - update immediately if valid
652
+ // Keep the whole text edit as a draft until an explicit commit boundary.
684
653
  const handleInputChange = useCallback(
685
654
  (e: React.ChangeEvent<HTMLInputElement>) => {
686
655
  // Value can't change while showing a disabled message (the field is
687
656
  // read-only and non-native-disabled), but guard the handler too so the
688
- // pending value and onChange never fire.
657
+ // pending value never changes.
689
658
  if (isDisabled || isReadOnly) {
690
659
  return;
691
660
  }
692
- const newValue = e.target.value;
693
- setPendingInput(newValue);
694
-
695
- // If the input is valid, update immediately
696
- const parsed = parseNumberInput(newValue, {min, max, isIntegerOnly});
697
- if (parsed !== null && parsed !== value) {
698
- onChange(parsed);
699
- }
661
+ setPendingInput(e.target.value);
700
662
  },
701
- [value, onChange, min, max, isIntegerOnly, isDisabled, isReadOnly],
663
+ [isDisabled, isReadOnly],
702
664
  );
703
665
 
704
666
  // Handle focus
@@ -710,34 +672,45 @@ export function NumberInput({
710
672
  [onFocus],
711
673
  );
712
674
 
713
- // Handle blur - validate and clear pending input
714
- const handleBlur = useCallback(
715
- (e: FocusEvent<HTMLInputElement>) => {
716
- if (pendingInput !== null) {
717
- if (hasClear && pendingInput.trim() === '') {
718
- // Keyboard clearing honors the clearable contract: an emptied
719
- // input commits null instead of silently reverting on blur.
720
- if (value != null) {
721
- onChange(null);
722
- }
723
- } else {
724
- const parsed = parseNumberInput(pendingInput, {
725
- min,
726
- max,
727
- isIntegerOnly,
728
- });
729
- if (parsed !== null && parsed !== value) {
730
- onChange(parsed);
731
- }
675
+ const commitPendingInput = useCallback(
676
+ (trigger: 'blur' | 'Enter') => {
677
+ if (pendingInput === null) {
678
+ return;
679
+ }
680
+
681
+ const decision = resolveNumberInputCommit(pendingInput, {
682
+ min,
683
+ max,
684
+ isIntegerOnly,
685
+ locale,
686
+ hasClear: !!hasClear,
687
+ });
688
+ if (
689
+ trigger === 'blur' ||
690
+ (decision.type === 'commit' && decision.didClamp)
691
+ ) {
692
+ setPendingInput(null);
693
+ }
694
+
695
+ if (decision.type === 'clear') {
696
+ if (hasClear && value != null) {
697
+ onChange(null);
732
698
  }
699
+ } else if (decision.type === 'commit' && decision.value !== value) {
700
+ onChange(decision.value);
733
701
  }
702
+ },
703
+ [hasClear, isIntegerOnly, locale, max, min, onChange, pendingInput, value],
704
+ );
734
705
 
735
- // Clear pending input - display will revert to formatted value
736
- setPendingInput(null);
706
+ // Blur ends the edit and displays the resulting committed value.
707
+ const handleBlur = useCallback(
708
+ (e: FocusEvent<HTMLInputElement>) => {
709
+ commitPendingInput('blur');
737
710
  setIsFocused(false);
738
711
  onBlur?.(e);
739
712
  },
740
- [pendingInput, value, onChange, min, max, isIntegerOnly, onBlur, hasClear],
713
+ [commitPendingInput, onBlur],
741
714
  );
742
715
 
743
716
  const valueForStepping = useMemo(() => {
@@ -747,10 +720,8 @@ export function NumberInput({
747
720
  if (pendingInput.trim() === '') {
748
721
  return null;
749
722
  }
750
- return (
751
- parseNumberInput(pendingInput, {min, max, isIntegerOnly}) ?? value ?? null
752
- );
753
- }, [isIntegerOnly, max, min, pendingInput, value]);
723
+ return parseInput(pendingInput) ?? value ?? null;
724
+ }, [parseInput, pendingInput, value]);
754
725
 
755
726
  const getNextValue = useCallback(
756
727
  (direction: StepDirection) =>
@@ -806,41 +777,12 @@ export function NumberInput({
806
777
  return;
807
778
  }
808
779
  if (e.key === 'Enter') {
809
- // Validate and commit on Enter
810
- if (pendingInput !== null) {
811
- if (hasClear && pendingInput.trim() === '') {
812
- // Same clearable contract as blur: Enter on an emptied input
813
- // commits null instead of reverting.
814
- if (value != null) {
815
- onChange(null);
816
- }
817
- } else {
818
- const parsed = parseNumberInput(pendingInput, {
819
- min,
820
- max,
821
- isIntegerOnly,
822
- });
823
- if (parsed !== null && parsed !== value) {
824
- onChange(parsed);
825
- }
826
- }
827
- }
780
+ commitPendingInput('Enter');
828
781
  onEnter?.();
829
782
  }
830
783
  onKeyDown?.(e);
831
784
  },
832
- [
833
- pendingInput,
834
- value,
835
- onChange,
836
- min,
837
- max,
838
- isIntegerOnly,
839
- onEnter,
840
- onKeyDown,
841
- hasClear,
842
- stepValue,
843
- ],
785
+ [commitPendingInput, onEnter, onKeyDown, stepValue],
844
786
  );
845
787
 
846
788
  // React's delegated wheel listener can be passive, so use a native,
@@ -963,6 +905,8 @@ export function NumberInput({
963
905
  data-autofocus={hasAutoFocus || undefined}
964
906
  aria-valuemin={min ?? undefined}
965
907
  aria-valuemax={max ?? undefined}
908
+ // The ARIA value and hidden form input expose the committed value;
909
+ // pendingInput is still an uncommitted edit and may be invalid.
966
910
  aria-valuenow={value ?? undefined}
967
911
  aria-valuetext={
968
912
  value == null || !formatValue ? undefined : formattedValue
@@ -1020,11 +964,12 @@ export function NumberInput({
1020
964
  }}
1021
965
  {...stylex.props(
1022
966
  styles.numberStepperButton,
967
+ interactionOverlayStyles.backgroundImage,
1023
968
  (isDisabled || isReadOnly || !canIncrement) &&
1024
969
  styles.numberStepperButtonDisabled,
1025
970
  )}>
1026
971
  <Icon
1027
- icon="chevronDown"
972
+ icon="numberInput:stepperDown"
1028
973
  size="xsm"
1029
974
  color="inherit"
1030
975
  xstyle={styles.incrementIcon}
@@ -1042,11 +987,12 @@ export function NumberInput({
1042
987
  }}
1043
988
  {...stylex.props(
1044
989
  styles.numberStepperButton,
990
+ interactionOverlayStyles.backgroundImage,
1045
991
  styles.decrementButton,
1046
992
  (isDisabled || isReadOnly || !canDecrement) &&
1047
993
  styles.numberStepperButtonDisabled,
1048
994
  )}>
1049
- <Icon icon="chevronDown" size="xsm" color="inherit" />
995
+ <Icon icon="numberInput:stepperDown" size="xsm" color="inherit" />
1050
996
  </button>
1051
997
  </div>
1052
998
  )}
@@ -0,0 +1,72 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file numberInputCommit.test.ts
5
+ * @input Uses Vitest and the NumberInput draft commit policy
6
+ * @output Focused tests for commit, clear, clamp, and revert decisions
7
+ * @position Testing; validates numberInputCommit.ts independently of React
8
+ */
9
+
10
+ import {describe, expect, it} from 'vitest';
11
+ import {parseNumberInput, resolveNumberInputCommit} from './numberInputCommit';
12
+
13
+ describe('parseNumberInput', () => {
14
+ it('validates the complete localized draft', () => {
15
+ expect(parseNumberInput('1.234.567', {locale: 'de-DE'})).toBe(1234567);
16
+ expect(parseNumberInput('1·234·567', {locale: 'de-DE'})).toBeNull();
17
+ });
18
+ });
19
+
20
+ describe('resolveNumberInputCommit', () => {
21
+ it('commits one valid localized draft', () => {
22
+ expect(
23
+ resolveNumberInputCommit('1.234.567', {
24
+ locale: 'de-DE',
25
+ hasClear: false,
26
+ }),
27
+ ).toEqual({
28
+ type: 'commit',
29
+ value: 1234567,
30
+ didClamp: false,
31
+ });
32
+ });
33
+
34
+ it('reverts the whole draft when parsing fails', () => {
35
+ expect(
36
+ resolveNumberInputCommit('1·234·567', {
37
+ locale: 'en-US',
38
+ hasClear: false,
39
+ }),
40
+ ).toEqual({type: 'revert'});
41
+ });
42
+
43
+ it('clamps an out-of-range draft and requests normalization', () => {
44
+ expect(
45
+ resolveNumberInputCommit('100', {
46
+ min: 1,
47
+ max: 2,
48
+ isIntegerOnly: true,
49
+ hasClear: false,
50
+ }),
51
+ ).toEqual({type: 'commit', value: 2, didClamp: true});
52
+ });
53
+
54
+ it('distinguishes a clearable empty draft from a revert', () => {
55
+ expect(resolveNumberInputCommit('', {hasClear: true})).toEqual({
56
+ type: 'clear',
57
+ });
58
+ expect(resolveNumberInputCommit('', {hasClear: false})).toEqual({
59
+ type: 'revert',
60
+ });
61
+ });
62
+
63
+ it('reverts when no value can satisfy the bounds', () => {
64
+ expect(
65
+ resolveNumberInputCommit('10', {
66
+ min: 5,
67
+ max: 2,
68
+ hasClear: false,
69
+ }),
70
+ ).toEqual({type: 'revert'});
71
+ });
72
+ });
@@ -0,0 +1,103 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file numberInputCommit.ts
5
+ * @input A NumberInput draft and the field's validation constraints
6
+ * @output A single commit, clear, or revert decision for the whole draft
7
+ * @position Shared internal draft validation and commit policy for NumberInput and its live consumers
8
+ *
9
+ * SYNC: When modified, update these files to stay in sync:
10
+ * - /packages/core/src/NumberInput/NumberInput.tsx
11
+ * - /packages/core/src/NumberInput/numberInputCommit.test.ts
12
+ * - /packages/core/src/Table/plugins/filtering/useTableFiltering.tsx
13
+ * - /packages/core/src/PowerSearch/PowerSearchValueEditor.tsx
14
+ */
15
+
16
+ import type {Locale} from '../i18n';
17
+ import {parseLocaleNumber} from './numberParser';
18
+
19
+ interface NumberInputValidationOptions {
20
+ min?: number | null;
21
+ max?: number | null;
22
+ isIntegerOnly?: boolean;
23
+ locale?: Locale;
24
+ }
25
+
26
+ export type NumberInputCommitDecision =
27
+ | {type: 'commit'; value: number; didClamp: boolean}
28
+ | {type: 'clear'}
29
+ | {type: 'revert'};
30
+
31
+ function parseNumericInput(
32
+ input: string,
33
+ options: Pick<NumberInputValidationOptions, 'isIntegerOnly' | 'locale'>,
34
+ ): number | null {
35
+ const trimmed = input.trim();
36
+ if (trimmed === '') {
37
+ return null;
38
+ }
39
+
40
+ const value = parseLocaleNumber(trimmed, options.locale);
41
+ if (value == null || !Number.isFinite(value)) {
42
+ return null;
43
+ }
44
+ if (options.isIntegerOnly && !Number.isInteger(value)) {
45
+ return null;
46
+ }
47
+ return value;
48
+ }
49
+
50
+ export function parseNumberInput(
51
+ input: string,
52
+ options: NumberInputValidationOptions,
53
+ ): number | null {
54
+ const value = parseNumericInput(input, options);
55
+ if (value === null) {
56
+ return null;
57
+ }
58
+ if (options.min != null && value < options.min) {
59
+ return null;
60
+ }
61
+ if (options.max != null && value > options.max) {
62
+ return null;
63
+ }
64
+ return value;
65
+ }
66
+
67
+ export function resolveNumberInputCommit(
68
+ input: string,
69
+ options: NumberInputValidationOptions & {hasClear: boolean},
70
+ ): NumberInputCommitDecision {
71
+ if (input.trim() === '') {
72
+ return options.hasClear ? {type: 'clear'} : {type: 'revert'};
73
+ }
74
+
75
+ const value = parseNumericInput(input, options);
76
+ if (value === null) {
77
+ return {type: 'revert'};
78
+ }
79
+
80
+ const min =
81
+ options.min == null
82
+ ? null
83
+ : options.isIntegerOnly
84
+ ? Math.ceil(options.min)
85
+ : options.min;
86
+ const max =
87
+ options.max == null
88
+ ? null
89
+ : options.isIntegerOnly
90
+ ? Math.floor(options.max)
91
+ : options.max;
92
+ if (min != null && max != null && min > max) {
93
+ return {type: 'revert'};
94
+ }
95
+
96
+ const committedValue =
97
+ min != null && value < min ? min : max != null && value > max ? max : value;
98
+ return {
99
+ type: 'commit',
100
+ value: committedValue,
101
+ didClamp: committedValue !== value,
102
+ };
103
+ }