@salt-ds/lab 1.0.0-alpha.70 → 1.0.0-alpha.71

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 (280) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/css/salt-lab.css +192 -302
  3. package/dist-cjs/app-header/AppHeader.css.js +1 -1
  4. package/dist-cjs/calendar/CalendarWeekHeader.css.js +1 -1
  5. package/dist-cjs/calendar/internal/CalendarDay.css.js +1 -1
  6. package/dist-cjs/calendar/internal/CalendarMonth.css.js +1 -1
  7. package/dist-cjs/cascading-menu/CascadingMenuItem.css.js +1 -1
  8. package/dist-cjs/color-chooser/ColorChooser.css.js +1 -1
  9. package/dist-cjs/color-chooser/ColorPicker.css.js +1 -1
  10. package/dist-cjs/color-chooser/HexInput.css.js +1 -1
  11. package/dist-cjs/color-chooser/RGBAInput.css.js +1 -1
  12. package/dist-cjs/color-chooser/Swatch.css.js +1 -1
  13. package/dist-cjs/combo-box/useCombobox.js.map +1 -1
  14. package/dist-cjs/common-hooks/selectionTypes.js.map +1 -1
  15. package/dist-cjs/common-hooks/useCollapsibleGroups.js.map +1 -1
  16. package/dist-cjs/common-hooks/useKeyboardNavigation.js.map +1 -1
  17. package/dist-cjs/common-hooks/useKeyboardNavigationPanel.js.map +1 -1
  18. package/dist-cjs/date-input/DateInput.css.js +1 -1
  19. package/dist-cjs/date-picker/DatePickerOverlay.css.js +1 -1
  20. package/dist-cjs/date-picker/DatePickerPanel.css.js +1 -1
  21. package/dist-cjs/form-field-legacy/FormFieldLegacy.css.js +1 -1
  22. package/dist-cjs/form-field-legacy/FormLabel.css.js +1 -1
  23. package/dist-cjs/index.js +0 -8
  24. package/dist-cjs/index.js.map +1 -1
  25. package/dist-cjs/input-legacy/InputLegacy.css.js +1 -1
  26. package/dist-cjs/list/List.css.js +1 -1
  27. package/dist-cjs/list/ListItem.css.js +1 -1
  28. package/dist-cjs/list/useList.js.map +1 -1
  29. package/dist-cjs/list-deprecated/List.css.js +1 -1
  30. package/dist-cjs/list-deprecated/ListItem.css.js +1 -1
  31. package/dist-cjs/list-next/ListItemNext.css.js +1 -1
  32. package/dist-cjs/list-next/ListNext.css.js +1 -1
  33. package/dist-cjs/logo/LogoSeparator.css.js +1 -1
  34. package/dist-cjs/number-input/NumberInput.css.js +1 -1
  35. package/dist-cjs/number-input/NumberInput.js +146 -79
  36. package/dist-cjs/number-input/NumberInput.js.map +1 -1
  37. package/dist-cjs/number-input/internal/useCaret.js +34 -0
  38. package/dist-cjs/number-input/internal/useCaret.js.map +1 -0
  39. package/dist-cjs/number-input/internal/utils.js +56 -14
  40. package/dist-cjs/number-input/internal/utils.js.map +1 -1
  41. package/dist-cjs/number-input/useNumberInput.js +34 -26
  42. package/dist-cjs/number-input/useNumberInput.js.map +1 -1
  43. package/dist-cjs/portal/Portal.js.map +1 -1
  44. package/dist-cjs/query-input/QueryInput.css.js +1 -1
  45. package/dist-cjs/responsive/OverflowReducer.js.map +1 -1
  46. package/dist-cjs/system-status/SystemStatus.css.js +1 -1
  47. package/dist-cjs/tabs/Tabstrip.css.js +1 -1
  48. package/dist-cjs/tabs/drag-drop/Draggable.css.js +1 -1
  49. package/dist-cjs/tabs-next/TabBar.css.js +1 -1
  50. package/dist-cjs/tabs-next/TabNext.css.js +1 -1
  51. package/dist-cjs/tabs-next/TabOverflowList.css.js +1 -1
  52. package/dist-cjs/tokenized-input/TokenizedInput.css.js +1 -1
  53. package/dist-cjs/tokenized-input-next/TokenizedInputNext.css.js +1 -1
  54. package/dist-cjs/toolbar/overflow-panel/OverflowPanel.css.js +1 -1
  55. package/dist-cjs/toolbar/overflow-panel/OverflowSeparator.css.js +1 -1
  56. package/dist-cjs/tree/useTree.js.map +1 -1
  57. package/dist-es/app-header/AppHeader.css.js +1 -1
  58. package/dist-es/calendar/CalendarWeekHeader.css.js +1 -1
  59. package/dist-es/calendar/internal/CalendarDay.css.js +1 -1
  60. package/dist-es/calendar/internal/CalendarMonth.css.js +1 -1
  61. package/dist-es/cascading-menu/CascadingMenuItem.css.js +1 -1
  62. package/dist-es/color-chooser/ColorChooser.css.js +1 -1
  63. package/dist-es/color-chooser/ColorPicker.css.js +1 -1
  64. package/dist-es/color-chooser/HexInput.css.js +1 -1
  65. package/dist-es/color-chooser/RGBAInput.css.js +1 -1
  66. package/dist-es/color-chooser/Swatch.css.js +1 -1
  67. package/dist-es/combo-box/useCombobox.js.map +1 -1
  68. package/dist-es/common-hooks/selectionTypes.js.map +1 -1
  69. package/dist-es/common-hooks/useCollapsibleGroups.js.map +1 -1
  70. package/dist-es/common-hooks/useKeyboardNavigation.js.map +1 -1
  71. package/dist-es/common-hooks/useKeyboardNavigationPanel.js.map +1 -1
  72. package/dist-es/date-input/DateInput.css.js +1 -1
  73. package/dist-es/date-picker/DatePickerOverlay.css.js +1 -1
  74. package/dist-es/date-picker/DatePickerPanel.css.js +1 -1
  75. package/dist-es/form-field-legacy/FormFieldLegacy.css.js +1 -1
  76. package/dist-es/form-field-legacy/FormLabel.css.js +1 -1
  77. package/dist-es/index.js +0 -4
  78. package/dist-es/index.js.map +1 -1
  79. package/dist-es/input-legacy/InputLegacy.css.js +1 -1
  80. package/dist-es/list/List.css.js +1 -1
  81. package/dist-es/list/ListItem.css.js +1 -1
  82. package/dist-es/list/useList.js.map +1 -1
  83. package/dist-es/list-deprecated/List.css.js +1 -1
  84. package/dist-es/list-deprecated/ListItem.css.js +1 -1
  85. package/dist-es/list-next/ListItemNext.css.js +1 -1
  86. package/dist-es/list-next/ListNext.css.js +1 -1
  87. package/dist-es/logo/LogoSeparator.css.js +1 -1
  88. package/dist-es/number-input/NumberInput.css.js +1 -1
  89. package/dist-es/number-input/NumberInput.js +149 -82
  90. package/dist-es/number-input/NumberInput.js.map +1 -1
  91. package/dist-es/number-input/internal/useCaret.js +32 -0
  92. package/dist-es/number-input/internal/useCaret.js.map +1 -0
  93. package/dist-es/number-input/internal/utils.js +52 -10
  94. package/dist-es/number-input/internal/utils.js.map +1 -1
  95. package/dist-es/number-input/useNumberInput.js +35 -27
  96. package/dist-es/number-input/useNumberInput.js.map +1 -1
  97. package/dist-es/portal/Portal.js.map +1 -1
  98. package/dist-es/query-input/QueryInput.css.js +1 -1
  99. package/dist-es/responsive/OverflowReducer.js.map +1 -1
  100. package/dist-es/system-status/SystemStatus.css.js +1 -1
  101. package/dist-es/tabs/Tabstrip.css.js +1 -1
  102. package/dist-es/tabs/drag-drop/Draggable.css.js +1 -1
  103. package/dist-es/tabs-next/TabBar.css.js +1 -1
  104. package/dist-es/tabs-next/TabNext.css.js +1 -1
  105. package/dist-es/tabs-next/TabOverflowList.css.js +1 -1
  106. package/dist-es/tokenized-input/TokenizedInput.css.js +1 -1
  107. package/dist-es/tokenized-input-next/TokenizedInputNext.css.js +1 -1
  108. package/dist-es/toolbar/overflow-panel/OverflowPanel.css.js +1 -1
  109. package/dist-es/toolbar/overflow-panel/OverflowSeparator.css.js +1 -1
  110. package/dist-es/tree/useTree.js.map +1 -1
  111. package/dist-types/app-header/AppHeader.d.ts +1 -1
  112. package/dist-types/button-bar/ButtonBar.d.ts +3 -3
  113. package/dist-types/calendar/Calendar.d.ts +1 -1
  114. package/dist-types/calendar/CalendarWeekHeader.d.ts +1 -1
  115. package/dist-types/calendar/useCalendar.d.ts +1 -1
  116. package/dist-types/calendar/useCalendarDay.d.ts +2 -1
  117. package/dist-types/calendar/useCalendarSelection.d.ts +5 -5
  118. package/dist-types/cascading-menu/internal/CascadingMenuAction.d.ts +2 -2
  119. package/dist-types/cascading-menu/internal/menuPositioning.d.ts +1 -1
  120. package/dist-types/cascading-menu/internal/stateUtils.d.ts +2 -2
  121. package/dist-types/cascading-menu/internal/useClickAway.d.ts +1 -1
  122. package/dist-types/cascading-menu/internal/useRefsManager.d.ts +1 -1
  123. package/dist-types/cascading-menu/internal/useStateReducer.d.ts +2 -2
  124. package/dist-types/cascading-menu/stateChangeTypes.d.ts +1 -1
  125. package/dist-types/color-chooser/Color.d.ts +1 -1
  126. package/dist-types/color-chooser/DictTabs.d.ts +1 -1
  127. package/dist-types/color-chooser/color-utils.d.ts +1 -1
  128. package/dist-types/combo-box/ComboBox.d.ts +3 -3
  129. package/dist-types/combo-box/useCombobox.d.ts +1 -1
  130. package/dist-types/combo-box-deprecated/ComboBoxDeprecated.d.ts +3 -3
  131. package/dist-types/combo-box-deprecated/filterHelpers.d.ts +1 -1
  132. package/dist-types/combo-box-deprecated/internal/DefaultComboBox.d.ts +1 -1
  133. package/dist-types/combo-box-deprecated/internal/MultiSelectComboBox.d.ts +1 -1
  134. package/dist-types/combo-box-deprecated/internal/useComboBox.d.ts +98 -97
  135. package/dist-types/combo-box-deprecated/internal/useMultiSelectComboBox.d.ts +214 -212
  136. package/dist-types/combo-box-deprecated/internal/usePopperStatus.d.ts +3 -3
  137. package/dist-types/common-hooks/collectionTypes.d.ts +3 -3
  138. package/dist-types/common-hooks/itemToString.d.ts +1 -1
  139. package/dist-types/common-hooks/navigationTypes.d.ts +4 -4
  140. package/dist-types/common-hooks/selectionTypes.d.ts +10 -10
  141. package/dist-types/common-hooks/useKeyboardNavigation.d.ts +1 -1
  142. package/dist-types/common-hooks/useSelection.d.ts +2 -2
  143. package/dist-types/common-hooks/utils/collection-item-utils.d.ts +2 -2
  144. package/dist-types/common-hooks/utils/filter-utils.d.ts +2 -2
  145. package/dist-types/contact-details/ContactAction.d.ts +1 -1
  146. package/dist-types/contact-details/ContactAvatar.d.ts +1 -1
  147. package/dist-types/contact-details/ContactDetails.d.ts +1 -1
  148. package/dist-types/date-input/DateInputRange.d.ts +2 -2
  149. package/dist-types/date-input/DateInputSingle.d.ts +1 -1
  150. package/dist-types/date-picker/DatePicker.d.ts +1 -1
  151. package/dist-types/date-picker/DatePickerActions.d.ts +1 -1
  152. package/dist-types/date-picker/DatePickerContext.d.ts +1 -1
  153. package/dist-types/date-picker/DatePickerOverlayProvider.d.ts +1 -1
  154. package/dist-types/date-picker/DatePickerRangeGridPanel.d.ts +1 -1
  155. package/dist-types/date-picker/DatePickerSingleGridPanel.d.ts +1 -1
  156. package/dist-types/date-picker/DatePickerSinglePanel.d.ts +1 -1
  157. package/dist-types/date-picker/useDatePicker.d.ts +1 -1
  158. package/dist-types/deck-layout/DeckLayout.d.ts +3 -3
  159. package/dist-types/dropdown/Dropdown.d.ts +3 -3
  160. package/dist-types/dropdown/DropdownBase.d.ts +1 -1
  161. package/dist-types/dropdown/dropdownTypes.d.ts +1 -1
  162. package/dist-types/dropdown/useClickAway.d.ts +1 -1
  163. package/dist-types/dropdown/useDropdown.d.ts +1 -1
  164. package/dist-types/focus-manager/internal/findAllTabbableElements.d.ts +1 -1
  165. package/dist-types/form-field-legacy/FormFieldLegacy.d.ts +5 -5
  166. package/dist-types/form-field-legacy/NecessityIndicator.d.ts +1 -1
  167. package/dist-types/form-field-legacy/StatusIndicator.d.ts +1 -1
  168. package/dist-types/formatted-input/FormattedInput.d.ts +1 -1
  169. package/dist-types/index.d.ts +0 -1
  170. package/dist-types/input-legacy/StaticInputAdornment.d.ts +1 -1
  171. package/dist-types/layer-layout/LayerLayout.d.ts +1 -1
  172. package/dist-types/list/List.d.ts +3 -3
  173. package/dist-types/list/ListItem.d.ts +1 -1
  174. package/dist-types/list/VirtualizedList.d.ts +3 -3
  175. package/dist-types/list/listTypes.d.ts +2 -2
  176. package/dist-types/list/useList.d.ts +1 -1
  177. package/dist-types/list/useVirtualization.d.ts +1 -1
  178. package/dist-types/list-deprecated/List.d.ts +2 -2
  179. package/dist-types/list-deprecated/ListBase.d.ts +2 -2
  180. package/dist-types/list-deprecated/ListItem.d.ts +1 -1
  181. package/dist-types/list-deprecated/ListItemContext.d.ts +1 -1
  182. package/dist-types/list-deprecated/ListProps.d.ts +5 -5
  183. package/dist-types/list-deprecated/itemToString.d.ts +1 -1
  184. package/dist-types/list-deprecated/useListItem.d.ts +2 -2
  185. package/dist-types/localization-provider/LocalizationProvider.d.ts +3 -3
  186. package/dist-types/logo/Logo.d.ts +1 -1
  187. package/dist-types/logo/LogoSeparator.d.ts +1 -1
  188. package/dist-types/number-input/NumberInput.d.ts +49 -27
  189. package/dist-types/number-input/internal/useCaret.d.ts +5 -0
  190. package/dist-types/number-input/internal/useInterval.d.ts +1 -1
  191. package/dist-types/number-input/internal/utils.d.ts +5 -5
  192. package/dist-types/number-input/useNumberInput.d.ts +11 -6
  193. package/dist-types/query-input/useQueryInput.d.ts +1 -1
  194. package/dist-types/responsive/OverflowReducer.d.ts +4 -4
  195. package/dist-types/responsive/overflowTypes.d.ts +20 -20
  196. package/dist-types/responsive/overflowUtils.d.ts +3 -3
  197. package/dist-types/responsive/useOverflowCollectionItems.d.ts +1 -1
  198. package/dist-types/responsive/useOverflowLayout.d.ts +1 -1
  199. package/dist-types/responsive/useResizeObserver.d.ts +2 -2
  200. package/dist-types/responsive/utils.d.ts +3 -3
  201. package/dist-types/tabs/Tab.d.ts +20 -19
  202. package/dist-types/tabs/Tabs.d.ts +1 -1
  203. package/dist-types/tabs/TabsTypes.d.ts +7 -7
  204. package/dist-types/tabs/drag-drop/Draggable.d.ts +2 -2
  205. package/dist-types/tabs/drag-drop/DropIndicator.d.ts +1 -1
  206. package/dist-types/tabs/drag-drop/drag-utils.d.ts +26 -22
  207. package/dist-types/tabs/drag-drop/dragDropTypes.d.ts +5 -5
  208. package/dist-types/tabs/drag-drop/useDragSpacers.d.ts +1 -1
  209. package/dist-types/tabs/useActivationIndicator.d.ts +1 -1
  210. package/dist-types/tabs/useEditableItem.d.ts +1 -1
  211. package/dist-types/tabs/useKeyboardNavigation.d.ts +1 -1
  212. package/dist-types/tabs/useSelection.d.ts +3 -3
  213. package/dist-types/tabs-next/hooks/useCollection.d.ts +1 -1
  214. package/dist-types/tokenized-input/TokenizedInput.d.ts +2 -2
  215. package/dist-types/tokenized-input/TokenizedInputBase.d.ts +5 -5
  216. package/dist-types/tokenized-input/internal/InputPill.d.ts +1 -1
  217. package/dist-types/tokenized-input/internal/isPlainObject.d.ts +1 -1
  218. package/dist-types/tokenized-input/useTokenizedInput.d.ts +1 -1
  219. package/dist-types/tokenized-input-next/TokenizedInputNext.d.ts +2 -2
  220. package/dist-types/tokenized-input-next/internal/InputPill.d.ts +1 -1
  221. package/dist-types/toolbar/ToolbarButton.d.ts +3 -3
  222. package/dist-types/toolbar/ToolbarProps.d.ts +1 -1
  223. package/dist-types/toolbar/TooltrayProps.d.ts +2 -2
  224. package/dist-types/toolbar/internal/ToolbarButtonRefsContext.d.ts +1 -1
  225. package/dist-types/toolbar/internal/renderTrayTools.d.ts +1 -1
  226. package/dist-types/tree/useTree.d.ts +1 -1
  227. package/dist-types/utils/forwardCallbackProps.d.ts +1 -1
  228. package/dist-types/utils/isEmail.d.ts +1 -1
  229. package/dist-types/utils/useClickOutside.d.ts +1 -1
  230. package/dist-types/utils/useSlideSelection.d.ts +1 -1
  231. package/dist-types/window/ElectronWindow.d.ts +1 -1
  232. package/dist-types/window/WindowContext.d.ts +4 -4
  233. package/package.json +2 -2
  234. package/dist-cjs/carousel/Carousel.css.js +0 -6
  235. package/dist-cjs/carousel/Carousel.css.js.map +0 -1
  236. package/dist-cjs/carousel/Carousel.js +0 -62
  237. package/dist-cjs/carousel/Carousel.js.map +0 -1
  238. package/dist-cjs/carousel/CarouselContext.js +0 -62
  239. package/dist-cjs/carousel/CarouselContext.js.map +0 -1
  240. package/dist-cjs/carousel/CarouselControls.css.js +0 -6
  241. package/dist-cjs/carousel/CarouselControls.css.js.map +0 -1
  242. package/dist-cjs/carousel/CarouselControls.js +0 -122
  243. package/dist-cjs/carousel/CarouselControls.js.map +0 -1
  244. package/dist-cjs/carousel/CarouselReducer.js +0 -77
  245. package/dist-cjs/carousel/CarouselReducer.js.map +0 -1
  246. package/dist-cjs/carousel/CarouselSlide.css.js +0 -6
  247. package/dist-cjs/carousel/CarouselSlide.css.js.map +0 -1
  248. package/dist-cjs/carousel/CarouselSlide.js +0 -110
  249. package/dist-cjs/carousel/CarouselSlide.js.map +0 -1
  250. package/dist-cjs/carousel/CarouselSlider.css.js +0 -6
  251. package/dist-cjs/carousel/CarouselSlider.css.js.map +0 -1
  252. package/dist-cjs/carousel/CarouselSlider.js +0 -93
  253. package/dist-cjs/carousel/CarouselSlider.js.map +0 -1
  254. package/dist-es/carousel/Carousel.css.js +0 -4
  255. package/dist-es/carousel/Carousel.css.js.map +0 -1
  256. package/dist-es/carousel/Carousel.js +0 -60
  257. package/dist-es/carousel/Carousel.js.map +0 -1
  258. package/dist-es/carousel/CarouselContext.js +0 -58
  259. package/dist-es/carousel/CarouselContext.js.map +0 -1
  260. package/dist-es/carousel/CarouselControls.css.js +0 -4
  261. package/dist-es/carousel/CarouselControls.css.js.map +0 -1
  262. package/dist-es/carousel/CarouselControls.js +0 -120
  263. package/dist-es/carousel/CarouselControls.js.map +0 -1
  264. package/dist-es/carousel/CarouselReducer.js +0 -75
  265. package/dist-es/carousel/CarouselReducer.js.map +0 -1
  266. package/dist-es/carousel/CarouselSlide.css.js +0 -4
  267. package/dist-es/carousel/CarouselSlide.css.js.map +0 -1
  268. package/dist-es/carousel/CarouselSlide.js +0 -108
  269. package/dist-es/carousel/CarouselSlide.js.map +0 -1
  270. package/dist-es/carousel/CarouselSlider.css.js +0 -4
  271. package/dist-es/carousel/CarouselSlider.css.js.map +0 -1
  272. package/dist-es/carousel/CarouselSlider.js +0 -91
  273. package/dist-es/carousel/CarouselSlider.js.map +0 -1
  274. package/dist-types/carousel/Carousel.d.ts +0 -23
  275. package/dist-types/carousel/CarouselContext.d.ts +0 -11
  276. package/dist-types/carousel/CarouselControls.d.ts +0 -26
  277. package/dist-types/carousel/CarouselReducer.d.ts +0 -30
  278. package/dist-types/carousel/CarouselSlide.d.ts +0 -32
  279. package/dist-types/carousel/CarouselSlider.d.ts +0 -13
  280. package/dist-types/carousel/index.d.ts +0 -4
@@ -8,33 +8,38 @@ var clsx = require('clsx');
8
8
  var react = require('react');
9
9
  var utils = require('./internal/utils.js');
10
10
  var NumberInput$1 = require('./NumberInput.css.js');
11
+ var useCaret = require('./internal/useCaret.js');
11
12
  var useNumberInput = require('./useNumberInput.js');
12
13
 
13
14
  const withBaseName = core.makePrefixer("saltNumberInput");
14
15
  const NumberInput = react.forwardRef(
15
16
  function NumberInput2({
16
- bordered,
17
+ bordered = false,
17
18
  className: classNameProp,
18
- decimalPlaces = 0,
19
- defaultValue: defaultValueProp,
19
+ clamp = false,
20
20
  disabled,
21
21
  emptyReadOnlyMarker = "\u2014",
22
22
  endAdornment,
23
+ format,
23
24
  hideButtons,
25
+ id: idProp,
24
26
  inputProps: inputPropsProp = {},
25
27
  inputRef: inputRefProp,
26
28
  max = Number.MAX_SAFE_INTEGER,
27
29
  min = Number.MIN_SAFE_INTEGER,
28
30
  onChange: onChangeProp,
31
+ parse,
29
32
  placeholder,
33
+ decimalScale: decimalScaleProp,
30
34
  readOnly: readOnlyProp,
31
35
  startAdornment,
32
36
  step = 1,
33
- stepBlock = 10,
37
+ stepMultiplier = 2,
34
38
  textAlign = "left",
35
39
  validationStatus: validationStatusProp,
36
40
  value: valueProp,
37
41
  variant = "primary",
42
+ defaultValue: defaultValueProp = "",
38
43
  ...restProps
39
44
  }, ref) {
40
45
  const targetWindow = window.useWindow();
@@ -43,7 +48,6 @@ const NumberInput = react.forwardRef(
43
48
  css: NumberInput$1,
44
49
  window: targetWindow
45
50
  });
46
- const { IncreaseIcon, DecreaseIcon } = core.useIcon();
47
51
  const {
48
52
  a11yProps: {
49
53
  "aria-describedby": formFieldDescribedBy,
@@ -57,6 +61,12 @@ const NumberInput = react.forwardRef(
57
61
  const isDisabled = disabled || formFieldDisabled;
58
62
  const isReadOnly = readOnlyProp || formFieldReadOnly;
59
63
  const validationStatus = formFieldValidationStatus ?? validationStatusProp;
64
+ const isEmptyReadOnly = isReadOnly && !defaultValueProp && !valueProp;
65
+ const defaultValue = isEmptyReadOnly ? emptyReadOnlyMarker : defaultValueProp;
66
+ const validationStatusId = core.useId(idProp);
67
+ const inputRef = react.useRef(null);
68
+ const handleInputRef = core.useForkRef(inputRefProp, inputRef);
69
+ const { IncreaseIcon, DecreaseIcon } = core.useIcon();
60
70
  const {
61
71
  "aria-describedby": inputDescribedBy,
62
72
  "aria-labelledby": inputLabelledBy,
@@ -69,60 +79,112 @@ const NumberInput = react.forwardRef(
69
79
  ...restInputProps
70
80
  } = inputPropsProp;
71
81
  const isRequired = formFieldRequired ? ["required", "asterisk"].includes(formFieldRequired) : inputRequired;
82
+ const isAdjustingRef = react.useRef(false);
83
+ const [isEditing, setIsEditing] = react.useState(false);
84
+ const [isFocused, setIsFocused] = react.useState(false);
85
+ const [recordCaret, restoreCaret, resetCaret] = useCaret({
86
+ inputRef
87
+ });
72
88
  const [value, setValue] = core.useControlled({
73
89
  controlled: valueProp,
74
- default: typeof defaultValueProp === "number" ? utils.toFixedDecimalPlaces(defaultValueProp, decimalPlaces) : defaultValueProp,
90
+ default: defaultValue,
75
91
  name: "NumberInput",
76
92
  state: "value"
77
93
  });
78
- const [focused, setFocused] = react.useState(false);
79
- const inputRef = react.useRef(null);
80
- const forkedInputRef = core.useForkRef(inputRef, inputRefProp);
94
+ const decimalScale = decimalScaleProp || Math.max(utils.getNumberPrecision(value), utils.getNumberPrecision(step));
95
+ const [displayValue, setDisplayValue] = react.useState(value);
96
+ const clampAndFix = (value2) => {
97
+ const clampedValue = clamp ? utils.clampToRange(min, max, value2) : value2;
98
+ return !format ? clampedValue.toFixed(decimalScale) : clampedValue;
99
+ };
81
100
  const {
82
101
  decrementButtonProps,
83
102
  decrementValue,
84
103
  incrementButtonProps,
85
104
  incrementValue
86
105
  } = useNumberInput.useNumberInput({
87
- inputRef,
88
- setValue,
89
- decimalPlaces,
106
+ clampAndFix,
107
+ decimalScale,
90
108
  disabled,
109
+ format,
110
+ inputRef,
111
+ isAdjustingRef,
91
112
  max,
92
113
  min,
93
114
  onChange: onChangeProp,
115
+ parse,
94
116
  readOnly: isReadOnly,
117
+ setIsEditing,
118
+ setValue,
95
119
  step,
96
- stepBlock,
120
+ stepMultiplier,
97
121
  value
98
122
  });
123
+ react.useEffect(() => {
124
+ const formatValue = () => {
125
+ const sanitizedValue = utils.sanitizeInput(value);
126
+ const floatValue = utils.toFloat(sanitizedValue);
127
+ if (!isAdjustingRef.current && (isEditing || utils.isEmpty(value) || Number.isNaN(floatValue) || isReadOnly)) {
128
+ return value;
129
+ }
130
+ if (isAdjustingRef.current) {
131
+ return clampAndFix(utils.toFloat(value));
132
+ }
133
+ const clampedValue = clampAndFix(floatValue);
134
+ return format ? format(clampedValue) : clampedValue;
135
+ };
136
+ const updatedValue = formatValue();
137
+ setDisplayValue(updatedValue);
138
+ }, [value, isEditing, isReadOnly, format, clamp, decimalScale, min, max]);
139
+ react.useLayoutEffect(() => {
140
+ if (isAdjustingRef.current) {
141
+ resetCaret();
142
+ } else {
143
+ restoreCaret();
144
+ }
145
+ }, [displayValue, value]);
99
146
  const handleInputFocus = (event) => {
100
- setFocused(true);
147
+ setIsFocused(true);
148
+ if (isReadOnly) return;
149
+ const parsedValue = (parse == null ? void 0 : parse(value)) ?? value;
150
+ const updatedValue = !utils.isEmpty(parsedValue) ? clampAndFix(utils.toFloat(parsedValue)) : parsedValue;
151
+ setDisplayValue(updatedValue);
101
152
  inputOnFocus == null ? void 0 : inputOnFocus(event);
102
153
  };
103
154
  const handleInputBlur = (event) => {
104
- setFocused(false);
105
- if (value === void 0) return;
106
- const floatValue = utils.toFloat(value);
107
- if (Number.isNaN(floatValue)) {
108
- setValue(value);
109
- onChangeProp == null ? void 0 : onChangeProp(event, value);
110
- } else {
111
- const roundedValue = utils.toFixedDecimalPlaces(floatValue, decimalPlaces);
112
- if (value !== "" && !utils.isAllowedNonNumeric(value)) {
113
- setValue(roundedValue);
114
- }
115
- onChangeProp == null ? void 0 : onChangeProp(event, roundedValue);
155
+ setIsFocused(false);
156
+ if (isReadOnly) return;
157
+ setIsEditing(false);
158
+ isAdjustingRef.current = false;
159
+ resetCaret();
160
+ const inputValue = event.target.value;
161
+ if (utils.isEmpty(inputValue)) {
162
+ return;
116
163
  }
164
+ const sanitizedValue = utils.sanitizeInput(event.target.value);
165
+ const floatValue = utils.toFloat(sanitizedValue);
166
+ const clampedValue = clampAndFix(floatValue);
167
+ if (clampedValue.toString() !== value.toString()) {
168
+ setValue(clampedValue);
169
+ onChangeProp == null ? void 0 : onChangeProp(event, clampedValue);
170
+ }
171
+ const formattedValue = format ? format(clampedValue) : clampedValue;
172
+ setDisplayValue(formattedValue);
117
173
  inputOnBlur == null ? void 0 : inputOnBlur(event);
118
174
  };
119
175
  const handleInputChange = (event) => {
120
- const changedValue = event.target.value;
121
- setValue(utils.sanitizedInput(changedValue));
122
- onChangeProp == null ? void 0 : onChangeProp(event, utils.sanitizedInput(changedValue));
123
- inputOnChange == null ? void 0 : inputOnChange(event);
176
+ recordCaret();
177
+ const raw = utils.sanitizeInput(event.target.value);
178
+ if (raw.toString() === value.toString()) {
179
+ return;
180
+ }
181
+ const parsed = parse && !isEditing ? parse(raw) : raw;
182
+ setValue(parsed);
183
+ onChangeProp == null ? void 0 : onChangeProp(event, parsed);
124
184
  };
125
185
  const handleInputKeyDown = (event) => {
186
+ setIsEditing(true);
187
+ isAdjustingRef.current = false;
126
188
  switch (event.key) {
127
189
  case "ArrowUp": {
128
190
  event.preventDefault();
@@ -161,66 +223,69 @@ const NumberInput = react.forwardRef(
161
223
  }
162
224
  inputOnKeyDown == null ? void 0 : inputOnKeyDown(event);
163
225
  };
226
+ const handleBeforeInput = () => {
227
+ setIsEditing(true);
228
+ };
164
229
  return /* @__PURE__ */ jsxRuntime.jsxs(
165
230
  "div",
166
231
  {
167
- className: clsx.clsx(withBaseName(), classNameProp),
232
+ className: clsx.clsx(
233
+ withBaseName(),
234
+ withBaseName(variant),
235
+ {
236
+ [withBaseName("focused")]: isFocused,
237
+ [withBaseName("disabled")]: isDisabled,
238
+ [withBaseName("readOnly")]: isReadOnly,
239
+ [withBaseName("hiddenButtons")]: hideButtons,
240
+ [withBaseName(validationStatus || "")]: validationStatus,
241
+ [withBaseName("bordered")]: bordered
242
+ },
243
+ classNameProp
244
+ ),
168
245
  ...restProps,
169
246
  ref,
170
247
  children: [
171
- /* @__PURE__ */ jsxRuntime.jsxs(
172
- "div",
248
+ startAdornment && /* @__PURE__ */ jsxRuntime.jsx("div", { className: withBaseName("startAdornmentContainer"), children: startAdornment }),
249
+ /* @__PURE__ */ jsxRuntime.jsx(
250
+ "input",
173
251
  {
252
+ "aria-describedby": clsx.clsx(
253
+ validationStatusId,
254
+ formFieldDescribedBy,
255
+ inputDescribedBy
256
+ ),
257
+ "aria-labelledby": clsx.clsx(formFieldLabelledBy, inputLabelledBy),
258
+ "aria-invalid": !isReadOnly ? utils.isOutOfRange(value, min, max) || validationStatus === "error" : void 0,
259
+ "aria-valuemax": !isReadOnly ? max : void 0,
260
+ "aria-valuemin": !isReadOnly ? min : void 0,
261
+ "aria-valuenow": value && !Number.isNaN(utils.toFloat(value)) && !isReadOnly ? utils.toFloat((parse == null ? void 0 : parse(value)) || value) : void 0,
262
+ ...!isReadOnly && { "aria-valuetext": value.toString() },
174
263
  className: clsx.clsx(
175
- withBaseName("inputContainer"),
176
- withBaseName(variant),
177
- {
178
- [withBaseName("focused")]: !isDisabled && focused,
179
- [withBaseName("disabled")]: isDisabled,
180
- [withBaseName("readOnly")]: isReadOnly,
181
- [withBaseName(validationStatus || "")]: validationStatus,
182
- [withBaseName("bordered")]: bordered
183
- }
264
+ withBaseName("input"),
265
+ withBaseName(`inputTextAlign${core.capitalize(textAlign)}`),
266
+ inputClassName
184
267
  ),
185
- children: [
186
- startAdornment && /* @__PURE__ */ jsxRuntime.jsx("div", { className: withBaseName("startAdornmentContainer"), children: startAdornment }),
187
- /* @__PURE__ */ jsxRuntime.jsx(
188
- "input",
189
- {
190
- "aria-describedby": clsx.clsx(formFieldDescribedBy, inputDescribedBy),
191
- "aria-labelledby": clsx.clsx(formFieldLabelledBy, inputLabelledBy),
192
- "aria-invalid": !isReadOnly ? utils.isOutOfRange(value, min, max) : void 0,
193
- "aria-valuemax": !isReadOnly ? utils.toFloat(utils.toFixedDecimalPlaces(max, decimalPlaces)) : void 0,
194
- "aria-valuemin": !isReadOnly ? utils.toFloat(utils.toFixedDecimalPlaces(min, decimalPlaces)) : void 0,
195
- "aria-valuenow": value && !Number.isNaN(utils.toFloat(value)) && !isReadOnly ? utils.toFloat(utils.toFixedDecimalPlaces(utils.toFloat(value), decimalPlaces)) : void 0,
196
- className: clsx.clsx(
197
- withBaseName("input"),
198
- withBaseName(`inputTextAlign${core.capitalize(textAlign)}`),
199
- inputClassName
200
- ),
201
- disabled: isDisabled,
202
- onBlur: handleInputBlur,
203
- onChange: handleInputChange,
204
- onFocus: !isDisabled ? handleInputFocus : void 0,
205
- onKeyDown: handleInputKeyDown,
206
- placeholder,
207
- readOnly: isReadOnly,
208
- "aria-readonly": isReadOnly ? "true" : void 0,
209
- ref: forkedInputRef,
210
- required: isRequired,
211
- role: isReadOnly ? "textbox" : "spinbutton",
212
- tabIndex: isDisabled ? -1 : 0,
213
- value,
214
- ...restInputProps
215
- }
216
- ),
217
- !isDisabled && validationStatus && /* @__PURE__ */ jsxRuntime.jsx(core.StatusAdornment, { status: validationStatus }),
218
- endAdornment && /* @__PURE__ */ jsxRuntime.jsx("div", { className: withBaseName("endAdornmentContainer"), children: endAdornment }),
219
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: withBaseName("activationIndicator") })
220
- ]
268
+ disabled: isDisabled,
269
+ onBlur: handleInputBlur,
270
+ onChange: handleInputChange,
271
+ onFocus: handleInputFocus,
272
+ onKeyDown: handleInputKeyDown,
273
+ onBeforeInput: handleBeforeInput,
274
+ placeholder,
275
+ readOnly: isReadOnly,
276
+ "aria-readonly": isReadOnly ? "true" : void 0,
277
+ ref: handleInputRef,
278
+ required: isRequired,
279
+ role: isReadOnly ? "textbox" : "spinbutton",
280
+ tabIndex: isDisabled ? -1 : 0,
281
+ value: displayValue,
282
+ ...restInputProps
221
283
  }
222
284
  ),
223
- !hideButtons && !isReadOnly && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: withBaseName("buttonContainer"), children: [
285
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: withBaseName("activationIndicator") }),
286
+ !isDisabled && validationStatus && /* @__PURE__ */ jsxRuntime.jsx(core.StatusAdornment, { status: validationStatus, id: validationStatusId }),
287
+ endAdornment && /* @__PURE__ */ jsxRuntime.jsx("div", { className: withBaseName("endAdornmentContainer"), children: endAdornment }),
288
+ !isReadOnly && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: clsx.clsx(withBaseName("buttonContainer")), children: [
224
289
  /* @__PURE__ */ jsxRuntime.jsx(
225
290
  core.Button,
226
291
  {
@@ -228,6 +293,7 @@ const NumberInput = react.forwardRef(
228
293
  withBaseName("numberButton"),
229
294
  withBaseName("numberButtonIncrement")
230
295
  ),
296
+ appearance: "transparent",
231
297
  ...incrementButtonProps,
232
298
  children: /* @__PURE__ */ jsxRuntime.jsx(IncreaseIcon, { "aria-hidden": true })
233
299
  }
@@ -239,6 +305,7 @@ const NumberInput = react.forwardRef(
239
305
  withBaseName("numberButton"),
240
306
  withBaseName("numberButtonDecrement")
241
307
  ),
308
+ appearance: "transparent",
242
309
  ...decrementButtonProps,
243
310
  children: /* @__PURE__ */ jsxRuntime.jsx(DecreaseIcon, { "aria-hidden": true })
244
311
  }
@@ -1 +1 @@
1
- {"version":3,"file":"NumberInput.js","sources":["../src/number-input/NumberInput.tsx"],"sourcesContent":["import {\n Button,\n StatusAdornment,\n type ValidationStatus,\n capitalize,\n makePrefixer,\n useControlled,\n useForkRef,\n useFormFieldProps,\n useIcon,\n} from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ChangeEvent,\n type ComponentPropsWithoutRef,\n type FocusEvent,\n type InputHTMLAttributes,\n type KeyboardEvent,\n type ReactNode,\n type Ref,\n type SyntheticEvent,\n forwardRef,\n useRef,\n useState,\n} from \"react\";\nimport {\n isAllowedNonNumeric,\n isOutOfRange,\n sanitizedInput,\n toFixedDecimalPlaces,\n toFloat,\n} from \"./internal/utils\";\n\nimport numberInputCss from \"./NumberInput.css\";\nimport { useNumberInput } from \"./useNumberInput\";\n\nconst withBaseName = makePrefixer(\"saltNumberInput\");\n\nexport interface NumberInputProps\n extends Omit<ComponentPropsWithoutRef<\"div\">, \"onChange\"> {\n /**\n * A boolean. When `true`, the input will receive a full border.\n */\n bordered?: boolean;\n /**\n * The number of decimal places to display.\n */\n decimalPlaces?: number;\n /**\n * Sets the initial default value of the component.\n */\n defaultValue?: number | string;\n /**\n * If `true`, the number input will be disabled.\n */\n disabled?: boolean;\n /**\n * The marker to use in an empty read only Input.\n * Use `''` to disable this feature. Defaults to '—'.\n * @default '—'\n */\n emptyReadOnlyMarker?: string;\n /**\n * End adornment component\n */\n endAdornment?: ReactNode;\n /**\n * Whether to hide the number buttons. Defaults to `false`.\n * @default false\n */\n hideButtons?: boolean;\n /**\n * [Attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Attributes) applied to the `input` element.\n */\n inputProps?: InputHTMLAttributes<HTMLInputElement>;\n /**\n * Optional ref for the input component\n */\n inputRef?: Ref<HTMLInputElement>;\n /**\n * The maximum value that can be selected. Defaults to Number.MAX_SAFE_INTEGER.\n * @default Number.MAX_SAFE_INTEGER\n */\n max?: number;\n /**\n * The minimum value that can be selected. Defaults to Number.MIN_SAFE_INTEGER.\n * @default Number.MIN_SAFE_INTEGER\n */\n min?: number;\n /**\n * Callback when number input value is changed.\n * @param event - the event triggers value change, could be undefined during increment / decrement button long press\n */\n onChange?: (\n event: SyntheticEvent | undefined,\n value: number | string,\n ) => void;\n /**\n * A string. Displayed in a dimmed color when the input value is empty.\n */\n placeholder?: string | undefined;\n /**\n * A boolean. If `true`, the component is not editable by the user.\n */\n readOnly?: boolean;\n /**\n * Start adornment component\n */\n startAdornment?: ReactNode;\n /**\n * The amount to increment or decrement the value by when using the number buttons or Up Arrow and Down Arrow keys. Default to 1.\n * @default 1\n */\n step?: number;\n /**\n * The amount to change the value when the value is incremented or decremented by holding Shift and pressing Up arrow or Down arrow keys.\n * Defaults to 10.\n * @default 10\n */\n stepBlock?: number;\n /**\n * Alignment of text within container. Defaults to \"left\".\n * @default \"left\"\n */\n textAlign?: \"left\" | \"center\" | \"right\";\n /**\n * Validation status.\n */\n validationStatus?: Extract<ValidationStatus, \"error\" | \"warning\" | \"success\">;\n /**\n * Styling variant. Defaults to \"primary\".\n * @default \"primary\"\n */\n variant?: \"primary\" | \"secondary\";\n /**\n * The value of the number input. The component will be controlled if this prop is provided.\n */\n value?: number | string | undefined;\n}\n\nexport const NumberInput = forwardRef<HTMLDivElement, NumberInputProps>(\n function NumberInput(\n {\n bordered,\n className: classNameProp,\n decimalPlaces = 0,\n defaultValue: defaultValueProp,\n disabled,\n emptyReadOnlyMarker = \"—\",\n endAdornment,\n hideButtons,\n inputProps: inputPropsProp = {},\n inputRef: inputRefProp,\n max = Number.MAX_SAFE_INTEGER,\n min = Number.MIN_SAFE_INTEGER,\n onChange: onChangeProp,\n placeholder,\n readOnly: readOnlyProp,\n startAdornment,\n step = 1,\n stepBlock = 10,\n textAlign = \"left\",\n validationStatus: validationStatusProp,\n value: valueProp,\n variant = \"primary\",\n ...restProps\n },\n ref,\n ) {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-number-input\",\n css: numberInputCss,\n window: targetWindow,\n });\n\n const { IncreaseIcon, DecreaseIcon } = useIcon();\n\n const {\n a11yProps: {\n \"aria-describedby\": formFieldDescribedBy,\n \"aria-labelledby\": formFieldLabelledBy,\n } = {},\n disabled: formFieldDisabled,\n readOnly: formFieldReadOnly,\n necessity: formFieldRequired,\n validationStatus: formFieldValidationStatus,\n } = useFormFieldProps();\n\n const isDisabled = disabled || formFieldDisabled;\n const isReadOnly = readOnlyProp || formFieldReadOnly;\n const validationStatus = formFieldValidationStatus ?? validationStatusProp;\n\n const {\n \"aria-describedby\": inputDescribedBy,\n \"aria-labelledby\": inputLabelledBy,\n className: inputClassName,\n onBlur: inputOnBlur,\n onChange: inputOnChange,\n onFocus: inputOnFocus,\n required: inputRequired,\n onKeyDown: inputOnKeyDown,\n ...restInputProps\n } = inputPropsProp;\n\n const isRequired = formFieldRequired\n ? [\"required\", \"asterisk\"].includes(formFieldRequired)\n : inputRequired;\n\n const [value, setValue] = useControlled({\n controlled: valueProp,\n default:\n typeof defaultValueProp === \"number\"\n ? toFixedDecimalPlaces(defaultValueProp, decimalPlaces)\n : defaultValueProp,\n name: \"NumberInput\",\n state: \"value\",\n });\n\n // Won't be needed when `:has` css can be used\n const [focused, setFocused] = useState(false);\n\n const inputRef = useRef<HTMLInputElement | null>(null);\n const forkedInputRef = useForkRef(inputRef, inputRefProp);\n\n const {\n decrementButtonProps,\n decrementValue,\n incrementButtonProps,\n incrementValue,\n } = useNumberInput({\n inputRef,\n setValue,\n decimalPlaces,\n disabled,\n max,\n min,\n onChange: onChangeProp,\n readOnly: isReadOnly,\n step,\n stepBlock,\n value,\n });\n\n const handleInputFocus = (event: FocusEvent<HTMLInputElement>) => {\n setFocused(true);\n\n inputOnFocus?.(event);\n };\n\n const handleInputBlur = (event: FocusEvent<HTMLInputElement>) => {\n setFocused(false);\n\n if (value === undefined) return;\n\n const floatValue = toFloat(value);\n if (Number.isNaN(floatValue)) {\n // Keep original value if NaN\n setValue(value);\n onChangeProp?.(event, value);\n } else {\n const roundedValue = toFixedDecimalPlaces(floatValue, decimalPlaces);\n\n if (value !== \"\" && !isAllowedNonNumeric(value)) {\n setValue(roundedValue);\n }\n\n onChangeProp?.(event, roundedValue);\n }\n\n inputOnBlur?.(event);\n };\n\n const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {\n const changedValue = event.target.value;\n\n setValue(sanitizedInput(changedValue));\n\n onChangeProp?.(event, sanitizedInput(changedValue));\n inputOnChange?.(event);\n };\n\n const handleInputKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\n switch (event.key) {\n case \"ArrowUp\": {\n event.preventDefault();\n const block = event.shiftKey;\n incrementValue(event, block);\n break;\n }\n case \"ArrowDown\": {\n event.preventDefault();\n const block = event.shiftKey;\n decrementValue(event, block);\n break;\n }\n case \"Home\": {\n event.preventDefault();\n setValue(min);\n onChangeProp?.(event, min);\n break;\n }\n case \"End\": {\n event.preventDefault();\n setValue(max);\n onChangeProp?.(event, max);\n break;\n }\n case \"PageUp\": {\n event.preventDefault();\n incrementValue(event, true);\n break;\n }\n case \"PageDown\": {\n event.preventDefault();\n decrementValue(event, true);\n break;\n }\n }\n\n inputOnKeyDown?.(event);\n };\n\n return (\n <div\n className={clsx(withBaseName(), classNameProp)}\n {...restProps}\n ref={ref}\n >\n <div\n className={clsx(\n withBaseName(\"inputContainer\"),\n withBaseName(variant),\n {\n [withBaseName(\"focused\")]: !isDisabled && focused,\n [withBaseName(\"disabled\")]: isDisabled,\n [withBaseName(\"readOnly\")]: isReadOnly,\n [withBaseName(validationStatus || \"\")]: validationStatus,\n [withBaseName(\"bordered\")]: bordered,\n },\n )}\n >\n {startAdornment && (\n <div className={withBaseName(\"startAdornmentContainer\")}>\n {startAdornment}\n </div>\n )}\n <input\n aria-describedby={clsx(formFieldDescribedBy, inputDescribedBy)}\n aria-labelledby={clsx(formFieldLabelledBy, inputLabelledBy)}\n aria-invalid={\n !isReadOnly ? isOutOfRange(value, min, max) : undefined\n }\n aria-valuemax={\n !isReadOnly\n ? toFloat(toFixedDecimalPlaces(max, decimalPlaces))\n : undefined\n }\n aria-valuemin={\n !isReadOnly\n ? toFloat(toFixedDecimalPlaces(min, decimalPlaces))\n : undefined\n }\n aria-valuenow={\n value && !Number.isNaN(toFloat(value)) && !isReadOnly\n ? toFloat(toFixedDecimalPlaces(toFloat(value), decimalPlaces))\n : undefined\n }\n className={clsx(\n withBaseName(\"input\"),\n withBaseName(`inputTextAlign${capitalize(textAlign)}`),\n inputClassName,\n )}\n disabled={isDisabled}\n onBlur={handleInputBlur}\n onChange={handleInputChange}\n onFocus={!isDisabled ? handleInputFocus : undefined}\n onKeyDown={handleInputKeyDown}\n placeholder={placeholder}\n readOnly={isReadOnly}\n aria-readonly={isReadOnly ? \"true\" : undefined}\n ref={forkedInputRef}\n required={isRequired}\n // Workaround to have readonly conveyed by screen readers (https://github.com/jpmorganchase/salt-ds/issues/4586)\n role={isReadOnly ? \"textbox\" : \"spinbutton\"}\n tabIndex={isDisabled ? -1 : 0}\n value={value}\n {...restInputProps}\n />\n {!isDisabled && validationStatus && (\n <StatusAdornment status={validationStatus} />\n )}\n {endAdornment && (\n <div className={withBaseName(\"endAdornmentContainer\")}>\n {endAdornment}\n </div>\n )}\n <div className={withBaseName(\"activationIndicator\")} />\n </div>\n\n {!hideButtons && !isReadOnly && (\n <div className={withBaseName(\"buttonContainer\")}>\n <Button\n className={clsx(\n withBaseName(\"numberButton\"),\n withBaseName(\"numberButtonIncrement\"),\n )}\n {...incrementButtonProps}\n >\n <IncreaseIcon aria-hidden />\n </Button>\n <Button\n className={clsx(\n withBaseName(\"numberButton\"),\n withBaseName(\"numberButtonDecrement\"),\n )}\n {...decrementButtonProps}\n >\n <DecreaseIcon aria-hidden />\n </Button>\n </div>\n )}\n </div>\n );\n },\n);\n"],"names":["makePrefixer","forwardRef","NumberInput","useWindow","useComponentCssInjection","numberInputCss","useIcon","useFormFieldProps","useControlled","toFixedDecimalPlaces","useState","useRef","useForkRef","useNumberInput","toFloat","isAllowedNonNumeric","sanitizedInput","jsxs","clsx","jsx","isOutOfRange","capitalize","StatusAdornment","Button"],"mappings":";;;;;;;;;;;;AAsCA,MAAM,YAAA,GAAeA,kBAAa,iBAAiB,CAAA;AAwG5C,MAAM,WAAc,GAAAC,gBAAA;AAAA,EACzB,SAASC,YACP,CAAA;AAAA,IACE,QAAA;AAAA,IACA,SAAW,EAAA,aAAA;AAAA,IACX,aAAgB,GAAA,CAAA;AAAA,IAChB,YAAc,EAAA,gBAAA;AAAA,IACd,QAAA;AAAA,IACA,mBAAsB,GAAA,QAAA;AAAA,IACtB,YAAA;AAAA,IACA,WAAA;AAAA,IACA,UAAA,EAAY,iBAAiB,EAAC;AAAA,IAC9B,QAAU,EAAA,YAAA;AAAA,IACV,MAAM,MAAO,CAAA,gBAAA;AAAA,IACb,MAAM,MAAO,CAAA,gBAAA;AAAA,IACb,QAAU,EAAA,YAAA;AAAA,IACV,WAAA;AAAA,IACA,QAAU,EAAA,YAAA;AAAA,IACV,cAAA;AAAA,IACA,IAAO,GAAA,CAAA;AAAA,IACP,SAAY,GAAA,EAAA;AAAA,IACZ,SAAY,GAAA,MAAA;AAAA,IACZ,gBAAkB,EAAA,oBAAA;AAAA,IAClB,KAAO,EAAA,SAAA;AAAA,IACP,OAAU,GAAA,SAAA;AAAA,IACV,GAAG;AAAA,KAEL,GACA,EAAA;AACA,IAAA,MAAM,eAAeC,gBAAU,EAAA;AAC/B,IAAyBC,+BAAA,CAAA;AAAA,MACvB,MAAQ,EAAA,mBAAA;AAAA,MACR,GAAK,EAAAC,aAAA;AAAA,MACL,MAAQ,EAAA;AAAA,KACT,CAAA;AAED,IAAA,MAAM,EAAE,YAAA,EAAc,YAAa,EAAA,GAAIC,YAAQ,EAAA;AAE/C,IAAM,MAAA;AAAA,MACJ,SAAW,EAAA;AAAA,QACT,kBAAoB,EAAA,oBAAA;AAAA,QACpB,iBAAmB,EAAA;AAAA,UACjB,EAAC;AAAA,MACL,QAAU,EAAA,iBAAA;AAAA,MACV,QAAU,EAAA,iBAAA;AAAA,MACV,SAAW,EAAA,iBAAA;AAAA,MACX,gBAAkB,EAAA;AAAA,QAChBC,sBAAkB,EAAA;AAEtB,IAAA,MAAM,aAAa,QAAY,IAAA,iBAAA;AAC/B,IAAA,MAAM,aAAa,YAAgB,IAAA,iBAAA;AACnC,IAAA,MAAM,mBAAmB,yBAA6B,IAAA,oBAAA;AAEtD,IAAM,MAAA;AAAA,MACJ,kBAAoB,EAAA,gBAAA;AAAA,MACpB,iBAAmB,EAAA,eAAA;AAAA,MACnB,SAAW,EAAA,cAAA;AAAA,MACX,MAAQ,EAAA,WAAA;AAAA,MACR,QAAU,EAAA,aAAA;AAAA,MACV,OAAS,EAAA,YAAA;AAAA,MACT,QAAU,EAAA,aAAA;AAAA,MACV,SAAW,EAAA,cAAA;AAAA,MACX,GAAG;AAAA,KACD,GAAA,cAAA;AAEJ,IAAM,MAAA,UAAA,GAAa,oBACf,CAAC,UAAA,EAAY,UAAU,CAAE,CAAA,QAAA,CAAS,iBAAiB,CACnD,GAAA,aAAA;AAEJ,IAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIC,kBAAc,CAAA;AAAA,MACtC,UAAY,EAAA,SAAA;AAAA,MACZ,SACE,OAAO,gBAAA,KAAqB,WACxBC,0BAAqB,CAAA,gBAAA,EAAkB,aAAa,CACpD,GAAA,gBAAA;AAAA,MACN,IAAM,EAAA,aAAA;AAAA,MACN,KAAO,EAAA;AAAA,KACR,CAAA;AAGD,IAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIC,eAAS,KAAK,CAAA;AAE5C,IAAM,MAAA,QAAA,GAAWC,aAAgC,IAAI,CAAA;AACrD,IAAM,MAAA,cAAA,GAAiBC,eAAW,CAAA,QAAA,EAAU,YAAY,CAAA;AAExD,IAAM,MAAA;AAAA,MACJ,oBAAA;AAAA,MACA,cAAA;AAAA,MACA,oBAAA;AAAA,MACA;AAAA,QACEC,6BAAe,CAAA;AAAA,MACjB,QAAA;AAAA,MACA,QAAA;AAAA,MACA,aAAA;AAAA,MACA,QAAA;AAAA,MACA,GAAA;AAAA,MACA,GAAA;AAAA,MACA,QAAU,EAAA,YAAA;AAAA,MACV,QAAU,EAAA,UAAA;AAAA,MACV,IAAA;AAAA,MACA,SAAA;AAAA,MACA;AAAA,KACD,CAAA;AAED,IAAM,MAAA,gBAAA,GAAmB,CAAC,KAAwC,KAAA;AAChE,MAAA,UAAA,CAAW,IAAI,CAAA;AAEf,MAAe,YAAA,IAAA,IAAA,GAAA,MAAA,GAAA,YAAA,CAAA,KAAA,CAAA;AAAA,KACjB;AAEA,IAAM,MAAA,eAAA,GAAkB,CAAC,KAAwC,KAAA;AAC/D,MAAA,UAAA,CAAW,KAAK,CAAA;AAEhB,MAAA,IAAI,UAAU,MAAW,EAAA;AAEzB,MAAM,MAAA,UAAA,GAAaC,cAAQ,KAAK,CAAA;AAChC,MAAI,IAAA,MAAA,CAAO,KAAM,CAAA,UAAU,CAAG,EAAA;AAE5B,QAAA,QAAA,CAAS,KAAK,CAAA;AACd,QAAA,YAAA,IAAA,IAAA,GAAA,MAAA,GAAA,YAAA,CAAe,KAAO,EAAA,KAAA,CAAA;AAAA,OACjB,MAAA;AACL,QAAM,MAAA,YAAA,GAAeL,0BAAqB,CAAA,UAAA,EAAY,aAAa,CAAA;AAEnE,QAAA,IAAI,KAAU,KAAA,EAAA,IAAM,CAACM,yBAAA,CAAoB,KAAK,CAAG,EAAA;AAC/C,UAAA,QAAA,CAAS,YAAY,CAAA;AAAA;AAGvB,QAAA,YAAA,IAAA,IAAA,GAAA,MAAA,GAAA,YAAA,CAAe,KAAO,EAAA,YAAA,CAAA;AAAA;AAGxB,MAAc,WAAA,IAAA,IAAA,GAAA,MAAA,GAAA,WAAA,CAAA,KAAA,CAAA;AAAA,KAChB;AAEA,IAAM,MAAA,iBAAA,GAAoB,CAAC,KAAyC,KAAA;AAClE,MAAM,MAAA,YAAA,GAAe,MAAM,MAAO,CAAA,KAAA;AAElC,MAAS,QAAA,CAAAC,oBAAA,CAAe,YAAY,CAAC,CAAA;AAErC,MAAe,YAAA,IAAA,IAAA,GAAA,MAAA,GAAA,YAAA,CAAA,KAAA,EAAOA,qBAAe,YAAY,CAAA,CAAA;AACjD,MAAgB,aAAA,IAAA,IAAA,GAAA,MAAA,GAAA,aAAA,CAAA,KAAA,CAAA;AAAA,KAClB;AAEA,IAAM,MAAA,kBAAA,GAAqB,CAAC,KAA2C,KAAA;AACrE,MAAA,QAAQ,MAAM,GAAK;AAAA,QACjB,KAAK,SAAW,EAAA;AACd,UAAA,KAAA,CAAM,cAAe,EAAA;AACrB,UAAA,MAAM,QAAQ,KAAM,CAAA,QAAA;AACpB,UAAA,cAAA,CAAe,OAAO,KAAK,CAAA;AAC3B,UAAA;AAAA;AACF,QACA,KAAK,WAAa,EAAA;AAChB,UAAA,KAAA,CAAM,cAAe,EAAA;AACrB,UAAA,MAAM,QAAQ,KAAM,CAAA,QAAA;AACpB,UAAA,cAAA,CAAe,OAAO,KAAK,CAAA;AAC3B,UAAA;AAAA;AACF,QACA,KAAK,MAAQ,EAAA;AACX,UAAA,KAAA,CAAM,cAAe,EAAA;AACrB,UAAA,QAAA,CAAS,GAAG,CAAA;AACZ,UAAA,YAAA,IAAA,IAAA,GAAA,MAAA,GAAA,YAAA,CAAe,KAAO,EAAA,GAAA,CAAA;AACtB,UAAA;AAAA;AACF,QACA,KAAK,KAAO,EAAA;AACV,UAAA,KAAA,CAAM,cAAe,EAAA;AACrB,UAAA,QAAA,CAAS,GAAG,CAAA;AACZ,UAAA,YAAA,IAAA,IAAA,GAAA,MAAA,GAAA,YAAA,CAAe,KAAO,EAAA,GAAA,CAAA;AACtB,UAAA;AAAA;AACF,QACA,KAAK,QAAU,EAAA;AACb,UAAA,KAAA,CAAM,cAAe,EAAA;AACrB,UAAA,cAAA,CAAe,OAAO,IAAI,CAAA;AAC1B,UAAA;AAAA;AACF,QACA,KAAK,UAAY,EAAA;AACf,UAAA,KAAA,CAAM,cAAe,EAAA;AACrB,UAAA,cAAA,CAAe,OAAO,IAAI,CAAA;AAC1B,UAAA;AAAA;AACF;AAGF,MAAiB,cAAA,IAAA,IAAA,GAAA,MAAA,GAAA,cAAA,CAAA,KAAA,CAAA;AAAA,KACnB;AAEA,IACE,uBAAAC,eAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,SAAW,EAAAC,SAAA,CAAK,YAAa,EAAA,EAAG,aAAa,CAAA;AAAA,QAC5C,GAAG,SAAA;AAAA,QACJ,GAAA;AAAA,QAEA,QAAA,EAAA;AAAA,0BAAAD,eAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACC,SAAW,EAAAC,SAAA;AAAA,gBACT,aAAa,gBAAgB,CAAA;AAAA,gBAC7B,aAAa,OAAO,CAAA;AAAA,gBACpB;AAAA,kBACE,CAAC,YAAa,CAAA,SAAS,CAAC,GAAG,CAAC,UAAc,IAAA,OAAA;AAAA,kBAC1C,CAAC,YAAA,CAAa,UAAU,CAAC,GAAG,UAAA;AAAA,kBAC5B,CAAC,YAAA,CAAa,UAAU,CAAC,GAAG,UAAA;AAAA,kBAC5B,CAAC,YAAA,CAAa,gBAAoB,IAAA,EAAE,CAAC,GAAG,gBAAA;AAAA,kBACxC,CAAC,YAAA,CAAa,UAAU,CAAC,GAAG;AAAA;AAC9B,eACF;AAAA,cAEC,QAAA,EAAA;AAAA,gBAAA,cAAA,mCACE,KAAI,EAAA,EAAA,SAAA,EAAW,YAAa,CAAA,yBAAyB,GACnD,QACH,EAAA,cAAA,EAAA,CAAA;AAAA,gCAEFC,cAAA;AAAA,kBAAC,OAAA;AAAA,kBAAA;AAAA,oBACC,kBAAA,EAAkBD,SAAK,CAAA,oBAAA,EAAsB,gBAAgB,CAAA;AAAA,oBAC7D,iBAAA,EAAiBA,SAAK,CAAA,mBAAA,EAAqB,eAAe,CAAA;AAAA,oBAC1D,gBACE,CAAC,UAAA,GAAaE,mBAAa,KAAO,EAAA,GAAA,EAAK,GAAG,CAAI,GAAA,MAAA;AAAA,oBAEhD,eAAA,EACE,CAAC,UACG,GAAAN,aAAA,CAAQL,2BAAqB,GAAK,EAAA,aAAa,CAAC,CAChD,GAAA,MAAA;AAAA,oBAEN,eAAA,EACE,CAAC,UACG,GAAAK,aAAA,CAAQL,2BAAqB,GAAK,EAAA,aAAa,CAAC,CAChD,GAAA,MAAA;AAAA,oBAEN,iBACE,KAAS,IAAA,CAAC,OAAO,KAAM,CAAAK,aAAA,CAAQ,KAAK,CAAC,CAAA,IAAK,CAAC,UAAA,GACvCA,cAAQL,0BAAqB,CAAAK,aAAA,CAAQ,KAAK,CAAG,EAAA,aAAa,CAAC,CAC3D,GAAA,MAAA;AAAA,oBAEN,SAAW,EAAAI,SAAA;AAAA,sBACT,aAAa,OAAO,CAAA;AAAA,sBACpB,YAAa,CAAA,CAAA,cAAA,EAAiBG,eAAW,CAAA,SAAS,CAAC,CAAE,CAAA,CAAA;AAAA,sBACrD;AAAA,qBACF;AAAA,oBACA,QAAU,EAAA,UAAA;AAAA,oBACV,MAAQ,EAAA,eAAA;AAAA,oBACR,QAAU,EAAA,iBAAA;AAAA,oBACV,OAAA,EAAS,CAAC,UAAA,GAAa,gBAAmB,GAAA,MAAA;AAAA,oBAC1C,SAAW,EAAA,kBAAA;AAAA,oBACX,WAAA;AAAA,oBACA,QAAU,EAAA,UAAA;AAAA,oBACV,eAAA,EAAe,aAAa,MAAS,GAAA,MAAA;AAAA,oBACrC,GAAK,EAAA,cAAA;AAAA,oBACL,QAAU,EAAA,UAAA;AAAA,oBAEV,IAAA,EAAM,aAAa,SAAY,GAAA,YAAA;AAAA,oBAC/B,QAAA,EAAU,aAAa,EAAK,GAAA,CAAA;AAAA,oBAC5B,KAAA;AAAA,oBACC,GAAG;AAAA;AAAA,iBACN;AAAA,gBACC,CAAC,UAAc,IAAA,gBAAA,oBACbF,cAAA,CAAAG,oBAAA,EAAA,EAAgB,QAAQ,gBAAkB,EAAA,CAAA;AAAA,gBAE5C,gCACEH,cAAA,CAAA,KAAA,EAAA,EAAI,WAAW,YAAa,CAAA,uBAAuB,GACjD,QACH,EAAA,YAAA,EAAA,CAAA;AAAA,gCAEDA,cAAA,CAAA,KAAA,EAAA,EAAI,SAAW,EAAA,YAAA,CAAa,qBAAqB,CAAG,EAAA;AAAA;AAAA;AAAA,WACvD;AAAA,UAEC,CAAC,eAAe,CAAC,UAAA,oCACf,KAAI,EAAA,EAAA,SAAA,EAAW,YAAa,CAAA,iBAAiB,CAC5C,EAAA,QAAA,EAAA;AAAA,4BAAAA,cAAA;AAAA,cAACI,WAAA;AAAA,cAAA;AAAA,gBACC,SAAW,EAAAL,SAAA;AAAA,kBACT,aAAa,cAAc,CAAA;AAAA,kBAC3B,aAAa,uBAAuB;AAAA,iBACtC;AAAA,gBACC,GAAG,oBAAA;AAAA,gBAEJ,QAAA,kBAAAC,cAAA,CAAC,YAAa,EAAA,EAAA,aAAA,EAAW,IAAC,EAAA;AAAA;AAAA,aAC5B;AAAA,4BACAA,cAAA;AAAA,cAACI,WAAA;AAAA,cAAA;AAAA,gBACC,SAAW,EAAAL,SAAA;AAAA,kBACT,aAAa,cAAc,CAAA;AAAA,kBAC3B,aAAa,uBAAuB;AAAA,iBACtC;AAAA,gBACC,GAAG,oBAAA;AAAA,gBAEJ,QAAA,kBAAAC,cAAA,CAAC,YAAa,EAAA,EAAA,aAAA,EAAW,IAAC,EAAA;AAAA;AAAA;AAC5B,WACF,EAAA;AAAA;AAAA;AAAA,KAEJ;AAAA;AAGN;;;;"}
1
+ {"version":3,"file":"NumberInput.js","sources":["../src/number-input/NumberInput.tsx"],"sourcesContent":["import {\n Button,\n StatusAdornment,\n type ValidationStatus,\n capitalize,\n makePrefixer,\n useControlled,\n useForkRef,\n useFormFieldProps,\n useIcon,\n useId,\n} from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ChangeEvent,\n type ComponentPropsWithoutRef,\n type FocusEvent,\n type InputHTMLAttributes,\n type KeyboardEvent,\n type ReactNode,\n type Ref,\n type SyntheticEvent,\n forwardRef,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\nimport {\n clampToRange,\n getNumberPrecision,\n isEmpty,\n isOutOfRange,\n sanitizeInput,\n toFloat,\n} from \"./internal/utils\";\n\nimport numberInputCss from \"./NumberInput.css\";\nimport useCaret from \"./internal/useCaret\";\nimport { useNumberInput } from \"./useNumberInput\";\n\nconst withBaseName = makePrefixer(\"saltNumberInput\");\n\nexport interface NumberInputProps\n extends Omit<ComponentPropsWithoutRef<\"div\">, \"onChange\"> {\n /**\n * Styling variant with full border.\n * @default false\n */\n bordered?: boolean;\n /**\n * A boolean that, when true, ensures the input value is clamped within the specified min and max range upon losing focus.\n * @default false\n */\n clamp?: boolean;\n /**\n * The default value. Use when the component is uncontrolled.\n */\n defaultValue?: number | string;\n /**\n * Disable the `NumberInput`.\n * @default false\n */\n disabled?: boolean;\n /**\n * The marker to use in an empty read only Input.\n * Use `''` to disable this feature.\n * @default \"—\"\n */\n emptyReadOnlyMarker?: string;\n /**\n * End adornment component.\n */\n endAdornment?: ReactNode;\n /**\n * A callback to format the value of the `NumberInput`.\n */\n format?: (value: number | string) => string | number;\n /**\n * Hide the number buttons.\n * @default false\n */\n hideButtons?: boolean;\n /**\n * [Attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Attributes) applied to the `input` element.\n */\n inputProps?: InputHTMLAttributes<HTMLInputElement>;\n /**\n * Optional ref for the input component.\n */\n inputRef?: Ref<HTMLInputElement>;\n /**\n * The maximum value that can be selected.\n * @default Number.MAX_SAFE_INTEGER\n */\n max?: number;\n /**\n * The minimum value that can be selected.\n * @default Number.MIN_SAFE_INTEGER\n */\n min?: number;\n /**\n * Callback function that is triggered when the value of the `NumberInput` changes.\n *\n * @param event - The event that triggers the value change. This may be `undefined` during a long press on the increment or decrement buttons.\n * @param value - The new value of the `NumberInput`, which can be a number or a string.\n */\n onChange?: (\n event: SyntheticEvent | undefined,\n value: number | string,\n ) => void;\n /**\n *\n * A callback to parse the value of the `NumberInput`. To be used alongside\n * the `format` callback.\n */\n parse?: (value: number | string) => string | number;\n /**\n * A string displayed in a dimmed color when the `NumberInput` value is empty.\n */\n placeholder?: string;\n /**\n * The number of decimal places allowed. Defaults to the decimal scale of either the initial value provided or the step, whichever is greater.\n */\n decimalScale?: number;\n /**\n * A boolean property that controls the editability of the `NumberInput`.\n * - When set to `true`, the `NumberInput` becomes read-only, preventing user edits.\n * - When set to `false` or omitted, the `NumberInput` is editable by the user.\n */\n readOnly?: boolean;\n /**\n * Start adornment component.\n */\n startAdornment?: ReactNode;\n /**\n * The amount to increment or decrement the value by when using the `NumberInput` buttons or Up Arrow and Down Arrow keys.\n * @default 1\n */\n step?: number;\n /**\n * Defines the factor by which the step value is multiplied to determine the maximum increment or decrement when the Shift key\n * is held while pressing the Up Arrow or Down Arrow keys for faster adjustments of the value.\n * @default 2\n */\n stepMultiplier?: number;\n /**\n * Specifies the alignment of the text within the `NumberInput`.\n *\n * @default \"left\"\n */\n textAlign?: \"left\" | \"center\" | \"right\";\n /**\n * Validation status.\n */\n validationStatus?: Extract<ValidationStatus, \"error\" | \"warning\" | \"success\">;\n /**\n * Styling variant.\n * @default \"primary\"\n */\n variant?: \"primary\" | \"secondary\";\n /**\n * Value of the `NumberInput`, to be used when in a controlled state.\n */\n value?: number | string;\n}\n\nexport const NumberInput = forwardRef<HTMLDivElement, NumberInputProps>(\n function NumberInput(\n {\n bordered = false,\n className: classNameProp,\n clamp = false,\n disabled,\n emptyReadOnlyMarker = \"—\",\n endAdornment,\n format,\n hideButtons,\n id: idProp,\n inputProps: inputPropsProp = {},\n inputRef: inputRefProp,\n max = Number.MAX_SAFE_INTEGER,\n min = Number.MIN_SAFE_INTEGER,\n onChange: onChangeProp,\n parse,\n placeholder,\n decimalScale: decimalScaleProp,\n readOnly: readOnlyProp,\n startAdornment,\n step = 1,\n stepMultiplier = 2,\n textAlign = \"left\",\n validationStatus: validationStatusProp,\n value: valueProp,\n variant = \"primary\",\n defaultValue: defaultValueProp = \"\",\n ...restProps\n },\n ref,\n ) {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-number-input\",\n css: numberInputCss,\n window: targetWindow,\n });\n\n const {\n a11yProps: {\n \"aria-describedby\": formFieldDescribedBy,\n \"aria-labelledby\": formFieldLabelledBy,\n } = {},\n disabled: formFieldDisabled,\n readOnly: formFieldReadOnly,\n necessity: formFieldRequired,\n validationStatus: formFieldValidationStatus,\n } = useFormFieldProps();\n\n const isDisabled = disabled || formFieldDisabled;\n const isReadOnly = readOnlyProp || formFieldReadOnly;\n const validationStatus = formFieldValidationStatus ?? validationStatusProp;\n const isEmptyReadOnly = isReadOnly && !defaultValueProp && !valueProp;\n const defaultValue = isEmptyReadOnly\n ? emptyReadOnlyMarker\n : defaultValueProp;\n\n const validationStatusId = useId(idProp);\n const inputRef = useRef<HTMLInputElement>(null);\n const handleInputRef = useForkRef(inputRefProp, inputRef);\n const { IncreaseIcon, DecreaseIcon } = useIcon();\n\n const {\n \"aria-describedby\": inputDescribedBy,\n \"aria-labelledby\": inputLabelledBy,\n className: inputClassName,\n onBlur: inputOnBlur,\n onChange: inputOnChange,\n onFocus: inputOnFocus,\n required: inputRequired,\n onKeyDown: inputOnKeyDown,\n ...restInputProps\n } = inputPropsProp;\n\n const isRequired = formFieldRequired\n ? [\"required\", \"asterisk\"].includes(formFieldRequired)\n : inputRequired;\n\n const isAdjustingRef = useRef<boolean>(false);\n const [isEditing, setIsEditing] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n\n const [recordCaret, restoreCaret, resetCaret] = useCaret({\n inputRef,\n });\n\n const [value, setValue] = useControlled({\n controlled: valueProp,\n default: defaultValue,\n name: \"NumberInput\",\n state: \"value\",\n });\n\n const decimalScale =\n decimalScaleProp ||\n Math.max(getNumberPrecision(value), getNumberPrecision(step));\n\n const [displayValue, setDisplayValue] = useState<string | number>(value);\n\n const clampAndFix = (value: number) => {\n const clampedValue = clamp ? clampToRange(min, max, value) : value;\n return !format ? clampedValue.toFixed(decimalScale) : clampedValue;\n };\n\n const {\n decrementButtonProps,\n decrementValue,\n incrementButtonProps,\n incrementValue,\n } = useNumberInput({\n clampAndFix,\n decimalScale,\n disabled,\n format,\n inputRef,\n isAdjustingRef,\n max,\n min,\n onChange: onChangeProp,\n parse,\n readOnly: isReadOnly,\n setIsEditing,\n setValue,\n step,\n stepMultiplier,\n value,\n });\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: We do not want to re-render when display value changes\n useEffect(() => {\n const formatValue = () => {\n const sanitizedValue = sanitizeInput(value);\n const floatValue = toFloat(sanitizedValue);\n if (\n !isAdjustingRef.current &&\n (isEditing ||\n isEmpty(value) ||\n Number.isNaN(floatValue) ||\n isReadOnly)\n ) {\n return value;\n }\n if (isAdjustingRef.current) {\n return clampAndFix(toFloat(value));\n }\n const clampedValue = clampAndFix(floatValue);\n return format ? format(clampedValue) : clampedValue;\n };\n const updatedValue = formatValue();\n setDisplayValue(updatedValue);\n }, [value, isEditing, isReadOnly, format, clamp, decimalScale, min, max]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: Need to restore caret position when value changes.\n useLayoutEffect(() => {\n if (isAdjustingRef.current) {\n resetCaret();\n } else {\n restoreCaret();\n }\n }, [displayValue, value]);\n\n const handleInputFocus = (event: FocusEvent<HTMLInputElement>) => {\n setIsFocused(true);\n if (isReadOnly) return;\n const parsedValue = parse?.(value) ?? value;\n const updatedValue = !isEmpty(parsedValue)\n ? clampAndFix(toFloat(parsedValue))\n : parsedValue;\n setDisplayValue(updatedValue);\n inputOnFocus?.(event);\n };\n\n const handleInputBlur = (event: FocusEvent<HTMLInputElement>) => {\n setIsFocused(false);\n if (isReadOnly) return;\n setIsEditing(false);\n isAdjustingRef.current = false;\n resetCaret();\n const inputValue = event.target.value;\n if (isEmpty(inputValue)) {\n return;\n }\n const sanitizedValue = sanitizeInput(event.target.value);\n const floatValue = toFloat(sanitizedValue);\n const clampedValue = clampAndFix(floatValue);\n // Update the value if it has changed\n if (clampedValue.toString() !== value.toString()) {\n setValue(clampedValue);\n onChangeProp?.(event, clampedValue);\n }\n // Ensure the displayValue is updated with the formatted value\n const formattedValue = format ? format(clampedValue) : clampedValue;\n setDisplayValue(formattedValue);\n inputOnBlur?.(event);\n };\n\n const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {\n recordCaret();\n const raw = sanitizeInput(event.target.value);\n if (raw.toString() === value.toString()) {\n return;\n }\n const parsed = parse && !isEditing ? parse(raw) : raw;\n setValue(parsed);\n onChangeProp?.(event, parsed);\n };\n\n const handleInputKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\n setIsEditing(true);\n isAdjustingRef.current = false;\n\n switch (event.key) {\n case \"ArrowUp\": {\n event.preventDefault();\n const block = event.shiftKey;\n incrementValue(event, block);\n break;\n }\n case \"ArrowDown\": {\n event.preventDefault();\n const block = event.shiftKey;\n decrementValue(event, block);\n break;\n }\n case \"Home\": {\n event.preventDefault();\n setValue(min);\n onChangeProp?.(event, min);\n break;\n }\n case \"End\": {\n event.preventDefault();\n setValue(max);\n onChangeProp?.(event, max);\n break;\n }\n case \"PageUp\": {\n event.preventDefault();\n incrementValue(event, true);\n break;\n }\n case \"PageDown\": {\n event.preventDefault();\n decrementValue(event, true);\n break;\n }\n }\n inputOnKeyDown?.(event);\n };\n\n const handleBeforeInput = () => {\n setIsEditing(true);\n };\n\n return (\n <div\n className={clsx(\n withBaseName(),\n withBaseName(variant),\n {\n [withBaseName(\"focused\")]: isFocused,\n [withBaseName(\"disabled\")]: isDisabled,\n [withBaseName(\"readOnly\")]: isReadOnly,\n [withBaseName(\"hiddenButtons\")]: hideButtons,\n [withBaseName(validationStatus || \"\")]: validationStatus,\n [withBaseName(\"bordered\")]: bordered,\n },\n classNameProp,\n )}\n {...restProps}\n ref={ref}\n >\n {startAdornment && (\n <div className={withBaseName(\"startAdornmentContainer\")}>\n {startAdornment}\n </div>\n )}\n <input\n aria-describedby={clsx(\n validationStatusId,\n formFieldDescribedBy,\n inputDescribedBy,\n )}\n aria-labelledby={clsx(formFieldLabelledBy, inputLabelledBy)}\n aria-invalid={\n !isReadOnly\n ? isOutOfRange(value, min, max) || validationStatus === \"error\"\n : undefined\n }\n aria-valuemax={!isReadOnly ? max : undefined}\n aria-valuemin={!isReadOnly ? min : undefined}\n aria-valuenow={\n value && !Number.isNaN(toFloat(value)) && !isReadOnly\n ? toFloat(parse?.(value) || value)\n : undefined\n }\n // Workaround to have the value announced by screen reader on Safari.\n {...(!isReadOnly && { \"aria-valuetext\": value.toString() })}\n className={clsx(\n withBaseName(\"input\"),\n withBaseName(`inputTextAlign${capitalize(textAlign)}`),\n inputClassName,\n )}\n disabled={isDisabled}\n onBlur={handleInputBlur}\n onChange={handleInputChange}\n onFocus={handleInputFocus}\n onKeyDown={handleInputKeyDown}\n onBeforeInput={handleBeforeInput}\n placeholder={placeholder}\n readOnly={isReadOnly}\n aria-readonly={isReadOnly ? \"true\" : undefined}\n ref={handleInputRef}\n required={isRequired}\n // Workaround to have readonly conveyed by screen readers (https://github.com/jpmorganchase/salt-ds/issues/4586)\n role={isReadOnly ? \"textbox\" : \"spinbutton\"}\n tabIndex={isDisabled ? -1 : 0}\n value={displayValue}\n {...restInputProps}\n />\n <div className={withBaseName(\"activationIndicator\")} />\n {!isDisabled && validationStatus && (\n <StatusAdornment status={validationStatus} id={validationStatusId} />\n )}\n {endAdornment && (\n <div className={withBaseName(\"endAdornmentContainer\")}>\n {endAdornment}\n </div>\n )}\n {!isReadOnly && (\n <div className={clsx(withBaseName(\"buttonContainer\"))}>\n <Button\n className={clsx(\n withBaseName(\"numberButton\"),\n withBaseName(\"numberButtonIncrement\"),\n )}\n appearance=\"transparent\"\n {...incrementButtonProps}\n >\n <IncreaseIcon aria-hidden />\n </Button>\n <Button\n className={clsx(\n withBaseName(\"numberButton\"),\n withBaseName(\"numberButtonDecrement\"),\n )}\n appearance=\"transparent\"\n {...decrementButtonProps}\n >\n <DecreaseIcon aria-hidden />\n </Button>\n </div>\n )}\n </div>\n );\n },\n);\n"],"names":["makePrefixer","forwardRef","NumberInput","useWindow","useComponentCssInjection","numberInputCss","useFormFieldProps","useId","useRef","useForkRef","useIcon","useState","useControlled","getNumberPrecision","value","clampToRange","useNumberInput","useEffect","sanitizeInput","toFloat","isEmpty","useLayoutEffect","jsxs","clsx","jsx","isOutOfRange","capitalize","StatusAdornment","Button"],"mappings":";;;;;;;;;;;;;AA2CA,MAAM,YAAA,GAAeA,kBAAa,iBAAiB,CAAA;AA8H5C,MAAM,WAAc,GAAAC,gBAAA;AAAA,EACzB,SAASC,YACP,CAAA;AAAA,IACE,QAAW,GAAA,KAAA;AAAA,IACX,SAAW,EAAA,aAAA;AAAA,IACX,KAAQ,GAAA,KAAA;AAAA,IACR,QAAA;AAAA,IACA,mBAAsB,GAAA,QAAA;AAAA,IACtB,YAAA;AAAA,IACA,MAAA;AAAA,IACA,WAAA;AAAA,IACA,EAAI,EAAA,MAAA;AAAA,IACJ,UAAA,EAAY,iBAAiB,EAAC;AAAA,IAC9B,QAAU,EAAA,YAAA;AAAA,IACV,MAAM,MAAO,CAAA,gBAAA;AAAA,IACb,MAAM,MAAO,CAAA,gBAAA;AAAA,IACb,QAAU,EAAA,YAAA;AAAA,IACV,KAAA;AAAA,IACA,WAAA;AAAA,IACA,YAAc,EAAA,gBAAA;AAAA,IACd,QAAU,EAAA,YAAA;AAAA,IACV,cAAA;AAAA,IACA,IAAO,GAAA,CAAA;AAAA,IACP,cAAiB,GAAA,CAAA;AAAA,IACjB,SAAY,GAAA,MAAA;AAAA,IACZ,gBAAkB,EAAA,oBAAA;AAAA,IAClB,KAAO,EAAA,SAAA;AAAA,IACP,OAAU,GAAA,SAAA;AAAA,IACV,cAAc,gBAAmB,GAAA,EAAA;AAAA,IACjC,GAAG;AAAA,KAEL,GACA,EAAA;AACA,IAAA,MAAM,eAAeC,gBAAU,EAAA;AAC/B,IAAyBC,+BAAA,CAAA;AAAA,MACvB,MAAQ,EAAA,mBAAA;AAAA,MACR,GAAK,EAAAC,aAAA;AAAA,MACL,MAAQ,EAAA;AAAA,KACT,CAAA;AAED,IAAM,MAAA;AAAA,MACJ,SAAW,EAAA;AAAA,QACT,kBAAoB,EAAA,oBAAA;AAAA,QACpB,iBAAmB,EAAA;AAAA,UACjB,EAAC;AAAA,MACL,QAAU,EAAA,iBAAA;AAAA,MACV,QAAU,EAAA,iBAAA;AAAA,MACV,SAAW,EAAA,iBAAA;AAAA,MACX,gBAAkB,EAAA;AAAA,QAChBC,sBAAkB,EAAA;AAEtB,IAAA,MAAM,aAAa,QAAY,IAAA,iBAAA;AAC/B,IAAA,MAAM,aAAa,YAAgB,IAAA,iBAAA;AACnC,IAAA,MAAM,mBAAmB,yBAA6B,IAAA,oBAAA;AACtD,IAAA,MAAM,eAAkB,GAAA,UAAA,IAAc,CAAC,gBAAA,IAAoB,CAAC,SAAA;AAC5D,IAAM,MAAA,YAAA,GAAe,kBACjB,mBACA,GAAA,gBAAA;AAEJ,IAAM,MAAA,kBAAA,GAAqBC,WAAM,MAAM,CAAA;AACvC,IAAM,MAAA,QAAA,GAAWC,aAAyB,IAAI,CAAA;AAC9C,IAAM,MAAA,cAAA,GAAiBC,eAAW,CAAA,YAAA,EAAc,QAAQ,CAAA;AACxD,IAAA,MAAM,EAAE,YAAA,EAAc,YAAa,EAAA,GAAIC,YAAQ,EAAA;AAE/C,IAAM,MAAA;AAAA,MACJ,kBAAoB,EAAA,gBAAA;AAAA,MACpB,iBAAmB,EAAA,eAAA;AAAA,MACnB,SAAW,EAAA,cAAA;AAAA,MACX,MAAQ,EAAA,WAAA;AAAA,MACR,QAAU,EAAA,aAAA;AAAA,MACV,OAAS,EAAA,YAAA;AAAA,MACT,QAAU,EAAA,aAAA;AAAA,MACV,SAAW,EAAA,cAAA;AAAA,MACX,GAAG;AAAA,KACD,GAAA,cAAA;AAEJ,IAAM,MAAA,UAAA,GAAa,oBACf,CAAC,UAAA,EAAY,UAAU,CAAE,CAAA,QAAA,CAAS,iBAAiB,CACnD,GAAA,aAAA;AAEJ,IAAM,MAAA,cAAA,GAAiBF,aAAgB,KAAK,CAAA;AAC5C,IAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAIG,eAAS,KAAK,CAAA;AAChD,IAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAIA,eAAS,KAAK,CAAA;AAEhD,IAAA,MAAM,CAAC,WAAA,EAAa,YAAc,EAAA,UAAU,IAAI,QAAS,CAAA;AAAA,MACvD;AAAA,KACD,CAAA;AAED,IAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIC,kBAAc,CAAA;AAAA,MACtC,UAAY,EAAA,SAAA;AAAA,MACZ,OAAS,EAAA,YAAA;AAAA,MACT,IAAM,EAAA,aAAA;AAAA,MACN,KAAO,EAAA;AAAA,KACR,CAAA;AAED,IAAM,MAAA,YAAA,GACJ,oBACA,IAAK,CAAA,GAAA,CAAIC,yBAAmB,KAAK,CAAA,EAAGA,wBAAmB,CAAA,IAAI,CAAC,CAAA;AAE9D,IAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAIF,eAA0B,KAAK,CAAA;AAEvE,IAAM,MAAA,WAAA,GAAc,CAACG,MAAkB,KAAA;AACrC,MAAA,MAAM,eAAe,KAAQ,GAAAC,kBAAA,CAAa,GAAK,EAAA,GAAA,EAAKD,MAAK,CAAIA,GAAAA,MAAAA;AAC7D,MAAA,OAAO,CAAC,MAAA,GAAS,YAAa,CAAA,OAAA,CAAQ,YAAY,CAAI,GAAA,YAAA;AAAA,KACxD;AAEA,IAAM,MAAA;AAAA,MACJ,oBAAA;AAAA,MACA,cAAA;AAAA,MACA,oBAAA;AAAA,MACA;AAAA,QACEE,6BAAe,CAAA;AAAA,MACjB,WAAA;AAAA,MACA,YAAA;AAAA,MACA,QAAA;AAAA,MACA,MAAA;AAAA,MACA,QAAA;AAAA,MACA,cAAA;AAAA,MACA,GAAA;AAAA,MACA,GAAA;AAAA,MACA,QAAU,EAAA,YAAA;AAAA,MACV,KAAA;AAAA,MACA,QAAU,EAAA,UAAA;AAAA,MACV,YAAA;AAAA,MACA,QAAA;AAAA,MACA,IAAA;AAAA,MACA,cAAA;AAAA,MACA;AAAA,KACD,CAAA;AAGD,IAAAC,eAAA,CAAU,MAAM;AACd,MAAA,MAAM,cAAc,MAAM;AACxB,QAAM,MAAA,cAAA,GAAiBC,oBAAc,KAAK,CAAA;AAC1C,QAAM,MAAA,UAAA,GAAaC,cAAQ,cAAc,CAAA;AACzC,QACE,IAAA,CAAC,cAAe,CAAA,OAAA,KACf,SACC,IAAAC,aAAA,CAAQ,KAAK,CAAA,IACb,MAAO,CAAA,KAAA,CAAM,UAAU,CAAA,IACvB,UACF,CAAA,EAAA;AACA,UAAO,OAAA,KAAA;AAAA;AAET,QAAA,IAAI,eAAe,OAAS,EAAA;AAC1B,UAAO,OAAA,WAAA,CAAYD,aAAQ,CAAA,KAAK,CAAC,CAAA;AAAA;AAEnC,QAAM,MAAA,YAAA,GAAe,YAAY,UAAU,CAAA;AAC3C,QAAO,OAAA,MAAA,GAAS,MAAO,CAAA,YAAY,CAAI,GAAA,YAAA;AAAA,OACzC;AACA,MAAA,MAAM,eAAe,WAAY,EAAA;AACjC,MAAA,eAAA,CAAgB,YAAY,CAAA;AAAA,KAC9B,EAAG,CAAC,KAAA,EAAO,SAAW,EAAA,UAAA,EAAY,QAAQ,KAAO,EAAA,YAAA,EAAc,GAAK,EAAA,GAAG,CAAC,CAAA;AAGxE,IAAAE,qBAAA,CAAgB,MAAM;AACpB,MAAA,IAAI,eAAe,OAAS,EAAA;AAC1B,QAAW,UAAA,EAAA;AAAA,OACN,MAAA;AACL,QAAa,YAAA,EAAA;AAAA;AACf,KACC,EAAA,CAAC,YAAc,EAAA,KAAK,CAAC,CAAA;AAExB,IAAM,MAAA,gBAAA,GAAmB,CAAC,KAAwC,KAAA;AAChE,MAAA,YAAA,CAAa,IAAI,CAAA;AACjB,MAAA,IAAI,UAAY,EAAA;AAChB,MAAM,MAAA,WAAA,GAAA,CAAc,+BAAQ,KAAU,CAAA,KAAA,KAAA;AACtC,MAAM,MAAA,YAAA,GAAe,CAACD,aAAQ,CAAA,WAAW,IACrC,WAAY,CAAAD,aAAA,CAAQ,WAAW,CAAC,CAChC,GAAA,WAAA;AACJ,MAAA,eAAA,CAAgB,YAAY,CAAA;AAC5B,MAAe,YAAA,IAAA,IAAA,GAAA,MAAA,GAAA,YAAA,CAAA,KAAA,CAAA;AAAA,KACjB;AAEA,IAAM,MAAA,eAAA,GAAkB,CAAC,KAAwC,KAAA;AAC/D,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA,IAAI,UAAY,EAAA;AAChB,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA,cAAA,CAAe,OAAU,GAAA,KAAA;AACzB,MAAW,UAAA,EAAA;AACX,MAAM,MAAA,UAAA,GAAa,MAAM,MAAO,CAAA,KAAA;AAChC,MAAI,IAAAC,aAAA,CAAQ,UAAU,CAAG,EAAA;AACvB,QAAA;AAAA;AAEF,MAAA,MAAM,cAAiB,GAAAF,mBAAA,CAAc,KAAM,CAAA,MAAA,CAAO,KAAK,CAAA;AACvD,MAAM,MAAA,UAAA,GAAaC,cAAQ,cAAc,CAAA;AACzC,MAAM,MAAA,YAAA,GAAe,YAAY,UAAU,CAAA;AAE3C,MAAA,IAAI,YAAa,CAAA,QAAA,EAAe,KAAA,KAAA,CAAM,UAAY,EAAA;AAChD,QAAA,QAAA,CAAS,YAAY,CAAA;AACrB,QAAA,YAAA,IAAA,IAAA,GAAA,MAAA,GAAA,YAAA,CAAe,KAAO,EAAA,YAAA,CAAA;AAAA;AAGxB,MAAA,MAAM,cAAiB,GAAA,MAAA,GAAS,MAAO,CAAA,YAAY,CAAI,GAAA,YAAA;AACvD,MAAA,eAAA,CAAgB,cAAc,CAAA;AAC9B,MAAc,WAAA,IAAA,IAAA,GAAA,MAAA,GAAA,WAAA,CAAA,KAAA,CAAA;AAAA,KAChB;AAEA,IAAM,MAAA,iBAAA,GAAoB,CAAC,KAAyC,KAAA;AAClE,MAAY,WAAA,EAAA;AACZ,MAAA,MAAM,GAAM,GAAAD,mBAAA,CAAc,KAAM,CAAA,MAAA,CAAO,KAAK,CAAA;AAC5C,MAAA,IAAI,GAAI,CAAA,QAAA,EAAe,KAAA,KAAA,CAAM,UAAY,EAAA;AACvC,QAAA;AAAA;AAEF,MAAA,MAAM,SAAS,KAAS,IAAA,CAAC,SAAY,GAAA,KAAA,CAAM,GAAG,CAAI,GAAA,GAAA;AAClD,MAAA,QAAA,CAAS,MAAM,CAAA;AACf,MAAA,YAAA,IAAA,IAAA,GAAA,MAAA,GAAA,YAAA,CAAe,KAAO,EAAA,MAAA,CAAA;AAAA,KACxB;AAEA,IAAM,MAAA,kBAAA,GAAqB,CAAC,KAA2C,KAAA;AACrE,MAAA,YAAA,CAAa,IAAI,CAAA;AACjB,MAAA,cAAA,CAAe,OAAU,GAAA,KAAA;AAEzB,MAAA,QAAQ,MAAM,GAAK;AAAA,QACjB,KAAK,SAAW,EAAA;AACd,UAAA,KAAA,CAAM,cAAe,EAAA;AACrB,UAAA,MAAM,QAAQ,KAAM,CAAA,QAAA;AACpB,UAAA,cAAA,CAAe,OAAO,KAAK,CAAA;AAC3B,UAAA;AAAA;AACF,QACA,KAAK,WAAa,EAAA;AAChB,UAAA,KAAA,CAAM,cAAe,EAAA;AACrB,UAAA,MAAM,QAAQ,KAAM,CAAA,QAAA;AACpB,UAAA,cAAA,CAAe,OAAO,KAAK,CAAA;AAC3B,UAAA;AAAA;AACF,QACA,KAAK,MAAQ,EAAA;AACX,UAAA,KAAA,CAAM,cAAe,EAAA;AACrB,UAAA,QAAA,CAAS,GAAG,CAAA;AACZ,UAAA,YAAA,IAAA,IAAA,GAAA,MAAA,GAAA,YAAA,CAAe,KAAO,EAAA,GAAA,CAAA;AACtB,UAAA;AAAA;AACF,QACA,KAAK,KAAO,EAAA;AACV,UAAA,KAAA,CAAM,cAAe,EAAA;AACrB,UAAA,QAAA,CAAS,GAAG,CAAA;AACZ,UAAA,YAAA,IAAA,IAAA,GAAA,MAAA,GAAA,YAAA,CAAe,KAAO,EAAA,GAAA,CAAA;AACtB,UAAA;AAAA;AACF,QACA,KAAK,QAAU,EAAA;AACb,UAAA,KAAA,CAAM,cAAe,EAAA;AACrB,UAAA,cAAA,CAAe,OAAO,IAAI,CAAA;AAC1B,UAAA;AAAA;AACF,QACA,KAAK,UAAY,EAAA;AACf,UAAA,KAAA,CAAM,cAAe,EAAA;AACrB,UAAA,cAAA,CAAe,OAAO,IAAI,CAAA;AAC1B,UAAA;AAAA;AACF;AAEF,MAAiB,cAAA,IAAA,IAAA,GAAA,MAAA,GAAA,cAAA,CAAA,KAAA,CAAA;AAAA,KACnB;AAEA,IAAA,MAAM,oBAAoB,MAAM;AAC9B,MAAA,YAAA,CAAa,IAAI,CAAA;AAAA,KACnB;AAEA,IACE,uBAAAI,eAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,SAAW,EAAAC,SAAA;AAAA,UACT,YAAa,EAAA;AAAA,UACb,aAAa,OAAO,CAAA;AAAA,UACpB;AAAA,YACE,CAAC,YAAA,CAAa,SAAS,CAAC,GAAG,SAAA;AAAA,YAC3B,CAAC,YAAA,CAAa,UAAU,CAAC,GAAG,UAAA;AAAA,YAC5B,CAAC,YAAA,CAAa,UAAU,CAAC,GAAG,UAAA;AAAA,YAC5B,CAAC,YAAA,CAAa,eAAe,CAAC,GAAG,WAAA;AAAA,YACjC,CAAC,YAAA,CAAa,gBAAoB,IAAA,EAAE,CAAC,GAAG,gBAAA;AAAA,YACxC,CAAC,YAAA,CAAa,UAAU,CAAC,GAAG;AAAA,WAC9B;AAAA,UACA;AAAA,SACF;AAAA,QACC,GAAG,SAAA;AAAA,QACJ,GAAA;AAAA,QAEC,QAAA,EAAA;AAAA,UAAA,cAAA,mCACE,KAAI,EAAA,EAAA,SAAA,EAAW,YAAa,CAAA,yBAAyB,GACnD,QACH,EAAA,cAAA,EAAA,CAAA;AAAA,0BAEFC,cAAA;AAAA,YAAC,OAAA;AAAA,YAAA;AAAA,cACC,kBAAkB,EAAAD,SAAA;AAAA,gBAChB,kBAAA;AAAA,gBACA,oBAAA;AAAA,gBACA;AAAA,eACF;AAAA,cACA,iBAAA,EAAiBA,SAAK,CAAA,mBAAA,EAAqB,eAAe,CAAA;AAAA,cAC1D,cAAA,EACE,CAAC,UACG,GAAAE,kBAAA,CAAa,OAAO,GAAK,EAAA,GAAG,CAAK,IAAA,gBAAA,KAAqB,OACtD,GAAA,MAAA;AAAA,cAEN,eAAA,EAAe,CAAC,UAAA,GAAa,GAAM,GAAA,MAAA;AAAA,cACnC,eAAA,EAAe,CAAC,UAAA,GAAa,GAAM,GAAA,MAAA;AAAA,cACnC,eACE,EAAA,KAAA,IAAS,CAAC,MAAA,CAAO,MAAMN,aAAQ,CAAA,KAAK,CAAC,CAAA,IAAK,CAAC,UACvC,GAAAA,aAAA,CAAA,CAAQ,KAAQ,IAAA,IAAA,GAAA,MAAA,GAAA,KAAA,CAAA,KAAA,CAAA,KAAU,KAAK,CAC/B,GAAA,MAAA;AAAA,cAGL,GAAI,CAAC,UAAA,IAAc,EAAE,gBAAkB,EAAA,KAAA,CAAM,UAAW,EAAA;AAAA,cACzD,SAAW,EAAAI,SAAA;AAAA,gBACT,aAAa,OAAO,CAAA;AAAA,gBACpB,YAAa,CAAA,CAAA,cAAA,EAAiBG,eAAW,CAAA,SAAS,CAAC,CAAE,CAAA,CAAA;AAAA,gBACrD;AAAA,eACF;AAAA,cACA,QAAU,EAAA,UAAA;AAAA,cACV,MAAQ,EAAA,eAAA;AAAA,cACR,QAAU,EAAA,iBAAA;AAAA,cACV,OAAS,EAAA,gBAAA;AAAA,cACT,SAAW,EAAA,kBAAA;AAAA,cACX,aAAe,EAAA,iBAAA;AAAA,cACf,WAAA;AAAA,cACA,QAAU,EAAA,UAAA;AAAA,cACV,eAAA,EAAe,aAAa,MAAS,GAAA,MAAA;AAAA,cACrC,GAAK,EAAA,cAAA;AAAA,cACL,QAAU,EAAA,UAAA;AAAA,cAEV,IAAA,EAAM,aAAa,SAAY,GAAA,YAAA;AAAA,cAC/B,QAAA,EAAU,aAAa,EAAK,GAAA,CAAA;AAAA,cAC5B,KAAO,EAAA,YAAA;AAAA,cACN,GAAG;AAAA;AAAA,WACN;AAAA,0BACCF,cAAA,CAAA,KAAA,EAAA,EAAI,SAAW,EAAA,YAAA,CAAa,qBAAqB,CAAG,EAAA,CAAA;AAAA,UACpD,CAAC,cAAc,gBACd,oBAAAA,cAAA,CAACG,wBAAgB,MAAQ,EAAA,gBAAA,EAAkB,IAAI,kBAAoB,EAAA,CAAA;AAAA,UAEpE,gCACEH,cAAA,CAAA,KAAA,EAAA,EAAI,WAAW,YAAa,CAAA,uBAAuB,GACjD,QACH,EAAA,YAAA,EAAA,CAAA;AAAA,UAED,CAAC,8BACCF,eAAA,CAAA,KAAA,EAAA,EAAI,WAAWC,SAAK,CAAA,YAAA,CAAa,iBAAiB,CAAC,CAClD,EAAA,QAAA,EAAA;AAAA,4BAAAC,cAAA;AAAA,cAACI,WAAA;AAAA,cAAA;AAAA,gBACC,SAAW,EAAAL,SAAA;AAAA,kBACT,aAAa,cAAc,CAAA;AAAA,kBAC3B,aAAa,uBAAuB;AAAA,iBACtC;AAAA,gBACA,UAAW,EAAA,aAAA;AAAA,gBACV,GAAG,oBAAA;AAAA,gBAEJ,QAAA,kBAAAC,cAAA,CAAC,YAAa,EAAA,EAAA,aAAA,EAAW,IAAC,EAAA;AAAA;AAAA,aAC5B;AAAA,4BACAA,cAAA;AAAA,cAACI,WAAA;AAAA,cAAA;AAAA,gBACC,SAAW,EAAAL,SAAA;AAAA,kBACT,aAAa,cAAc,CAAA;AAAA,kBAC3B,aAAa,uBAAuB;AAAA,iBACtC;AAAA,gBACA,UAAW,EAAA,aAAA;AAAA,gBACV,GAAG,oBAAA;AAAA,gBAEJ,QAAA,kBAAAC,cAAA,CAAC,YAAa,EAAA,EAAA,aAAA,EAAW,IAAC,EAAA;AAAA;AAAA;AAC5B,WACF,EAAA;AAAA;AAAA;AAAA,KAEJ;AAAA;AAGN;;;;"}
@@ -0,0 +1,34 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+
5
+ const useCaret = ({
6
+ inputRef
7
+ }) => {
8
+ const caretPositionRef = react.useRef(null);
9
+ const recordCaret = react.useCallback(() => {
10
+ if (inputRef.current) {
11
+ const { selectionStart: start, selectionEnd: end } = inputRef.current;
12
+ caretPositionRef.current = {
13
+ start,
14
+ end
15
+ };
16
+ }
17
+ }, []);
18
+ const restoreCaret = react.useCallback(() => {
19
+ if (inputRef.current && caretPositionRef.current) {
20
+ const { start, end } = caretPositionRef.current;
21
+ inputRef.current.setSelectionRange(start, end);
22
+ }
23
+ }, []);
24
+ const resetCaret = react.useCallback(() => {
25
+ if (inputRef.current) {
26
+ const txtLength = inputRef.current.value.length;
27
+ caretPositionRef.current = { start: txtLength, end: txtLength };
28
+ }
29
+ }, []);
30
+ return [recordCaret, restoreCaret, resetCaret];
31
+ };
32
+
33
+ module.exports = useCaret;
34
+ //# sourceMappingURL=useCaret.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCaret.js","sources":["../src/number-input/internal/useCaret.ts"],"sourcesContent":["import { type MutableRefObject, useCallback, useRef } from \"react\";\n\nconst useCaret = ({\n inputRef,\n}: {\n inputRef: MutableRefObject<HTMLInputElement | null>;\n}) => {\n const caretPositionRef = useRef<{\n start: number | null;\n end: number | null;\n } | null>(null);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: Refs shouldn't be used in dependency arrays\n const recordCaret = useCallback(() => {\n if (inputRef.current) {\n const { selectionStart: start, selectionEnd: end } = inputRef.current;\n caretPositionRef.current = {\n start,\n end,\n };\n }\n }, []);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: Refs shouldn't be used in dependency arrays\n const restoreCaret = useCallback(() => {\n if (inputRef.current && caretPositionRef.current) {\n const { start, end } = caretPositionRef.current;\n inputRef.current.setSelectionRange(start, end);\n }\n }, []);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: Refs shouldn't be used in dependency arrays\n const resetCaret = useCallback(() => {\n if (inputRef.current) {\n const txtLength = inputRef.current.value.length;\n caretPositionRef.current = { start: txtLength, end: txtLength };\n }\n }, []);\n\n return [recordCaret, restoreCaret, resetCaret];\n};\n\nexport default useCaret;\n"],"names":["useRef","useCallback"],"mappings":";;;;AAEA,MAAM,WAAW,CAAC;AAAA,EAChB;AACF,CAEM,KAAA;AACJ,EAAM,MAAA,gBAAA,GAAmBA,aAGf,IAAI,CAAA;AAGd,EAAM,MAAA,WAAA,GAAcC,kBAAY,MAAM;AACpC,IAAA,IAAI,SAAS,OAAS,EAAA;AACpB,MAAA,MAAM,EAAE,cAAgB,EAAA,KAAA,EAAO,YAAc,EAAA,GAAA,KAAQ,QAAS,CAAA,OAAA;AAC9D,MAAA,gBAAA,CAAiB,OAAU,GAAA;AAAA,QACzB,KAAA;AAAA,QACA;AAAA,OACF;AAAA;AACF,GACF,EAAG,EAAE,CAAA;AAGL,EAAM,MAAA,YAAA,GAAeA,kBAAY,MAAM;AACrC,IAAI,IAAA,QAAA,CAAS,OAAW,IAAA,gBAAA,CAAiB,OAAS,EAAA;AAChD,MAAA,MAAM,EAAE,KAAA,EAAO,GAAI,EAAA,GAAI,gBAAiB,CAAA,OAAA;AACxC,MAAS,QAAA,CAAA,OAAA,CAAQ,iBAAkB,CAAA,KAAA,EAAO,GAAG,CAAA;AAAA;AAC/C,GACF,EAAG,EAAE,CAAA;AAGL,EAAM,MAAA,UAAA,GAAaA,kBAAY,MAAM;AACnC,IAAA,IAAI,SAAS,OAAS,EAAA;AACpB,MAAM,MAAA,SAAA,GAAY,QAAS,CAAA,OAAA,CAAQ,KAAM,CAAA,MAAA;AACzC,MAAA,gBAAA,CAAiB,OAAU,GAAA,EAAE,KAAO,EAAA,SAAA,EAAW,KAAK,SAAU,EAAA;AAAA;AAChE,GACF,EAAG,EAAE,CAAA;AAEL,EAAO,OAAA,CAAC,WAAa,EAAA,YAAA,EAAc,UAAU,CAAA;AAC/C;;;;"}
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
- const ACCEPT_INPUT = /^[-+]?[0-9]*\.?([0-9]+)?/g;
4
- const toFixedDecimalPlaces = (inputNumber, decimalPlaces) => inputNumber.toFixed(decimalPlaces);
5
3
  const isAllowedNonNumeric = (inputCharacter) => {
6
4
  if (typeof inputCharacter === "number") return;
7
5
  return "-+".includes(inputCharacter) && inputCharacter.length === 1 || inputCharacter === "";
@@ -10,27 +8,71 @@ const toFloat = (inputValue) => {
10
8
  if (isAllowedNonNumeric(inputValue)) return 0;
11
9
  return Number.parseFloat(inputValue.toString());
12
10
  };
13
- const sanitizedInput = (numberString) => (numberString.match(ACCEPT_INPUT) || []).join("");
14
- const isAtMax = (value, max) => {
15
- if (value === void 0) return true;
16
- return toFloat(value) >= max;
11
+ const isValidNumber = (num) => {
12
+ if (typeof num === "number") {
13
+ return !Number.isNaN(num);
14
+ }
15
+ if (!num) {
16
+ return false;
17
+ }
18
+ return (
19
+ // Normal type: 11.28
20
+ /^\s*-?\d+(\.\d+)?\s*$/.test(num) || // Pre-number: 1.
21
+ /^\s*-?\d+\.\s*$/.test(num) || // Post-number: .1
22
+ /^\s*-?\.\d+\s*$/.test(num)
23
+ );
17
24
  };
18
- const isAtMin = (value, min) => {
19
- if (value === void 0) return true;
20
- return toFloat(value) <= min;
25
+ const sanitizeInput = (value) => {
26
+ if (typeof value === "number") return value;
27
+ let sanitizedInput = value.replace(/[^0-9.+-]/g, "");
28
+ sanitizedInput = sanitizedInput.replace(
29
+ /^([+-]?)(.*)$/,
30
+ (match, sign, rest) => {
31
+ return sign + rest.replace(/[+-]/g, "");
32
+ }
33
+ );
34
+ const parts = sanitizedInput.split(".");
35
+ if (parts.length > 2) {
36
+ sanitizedInput = `${parts[0]}.${parts.slice(1).join("")}`;
37
+ }
38
+ return sanitizedInput;
21
39
  };
22
40
  const isOutOfRange = (value, min, max) => {
23
41
  if (value === void 0) return true;
24
42
  const floatValue = toFloat(value);
25
43
  return floatValue > max || floatValue < min;
26
44
  };
45
+ const clampToRange = (min, max, value) => {
46
+ if (value < min) return min;
47
+ if (value > max) return max;
48
+ return value;
49
+ };
50
+ const isExponential = (number) => {
51
+ const str = String(number);
52
+ return !Number.isNaN(Number(str)) && str.includes("e");
53
+ };
54
+ const getNumberPrecision = (number) => {
55
+ const numStr = String(sanitizeInput(number));
56
+ if (isExponential(number)) {
57
+ let precision = Number(numStr.slice(numStr.indexOf("e-") + 2));
58
+ const decimalMatch = numStr.match(/\.(\d+)/);
59
+ if (decimalMatch == null ? void 0 : decimalMatch[1]) {
60
+ precision += decimalMatch[1].length;
61
+ }
62
+ return precision;
63
+ }
64
+ return numStr.includes(".") && isValidNumber(numStr) ? numStr.length - numStr.indexOf(".") - 1 : 0;
65
+ };
66
+ const isEmpty = (value) => {
67
+ return value === "";
68
+ };
27
69
 
28
- exports.ACCEPT_INPUT = ACCEPT_INPUT;
70
+ exports.clampToRange = clampToRange;
71
+ exports.getNumberPrecision = getNumberPrecision;
29
72
  exports.isAllowedNonNumeric = isAllowedNonNumeric;
30
- exports.isAtMax = isAtMax;
31
- exports.isAtMin = isAtMin;
73
+ exports.isEmpty = isEmpty;
32
74
  exports.isOutOfRange = isOutOfRange;
33
- exports.sanitizedInput = sanitizedInput;
34
- exports.toFixedDecimalPlaces = toFixedDecimalPlaces;
75
+ exports.isValidNumber = isValidNumber;
76
+ exports.sanitizeInput = sanitizeInput;
35
77
  exports.toFloat = toFloat;
36
78
  //# sourceMappingURL=utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sources":["../src/number-input/internal/utils.ts"],"sourcesContent":["// The input should only accept numbers, decimal points, and plus/minus symbols\nexport const ACCEPT_INPUT = /^[-+]?[0-9]*\\.?([0-9]+)?/g;\n\nexport const toFixedDecimalPlaces = (\n inputNumber: number,\n decimalPlaces: number,\n) => inputNumber.toFixed(decimalPlaces);\n\nexport const isAllowedNonNumeric = (inputCharacter: number | string) => {\n if (typeof inputCharacter === \"number\") return;\n return (\n (\"-+\".includes(inputCharacter) && inputCharacter.length === 1) ||\n inputCharacter === \"\"\n );\n};\n\nexport const toFloat = (inputValue: number | string) => {\n // Plus, minus, and empty characters are treated as 0\n if (isAllowedNonNumeric(inputValue)) return 0;\n return Number.parseFloat(inputValue.toString());\n};\n\nexport const sanitizedInput = (numberString: string) =>\n (numberString.match(ACCEPT_INPUT) || []).join(\"\");\n\nexport const isAtMax = (value: number | string | undefined, max: number) => {\n if (value === undefined) return true;\n return toFloat(value) >= max;\n};\n\nexport const isAtMin = (value: number | string | undefined, min: number) => {\n if (value === undefined) return true;\n return toFloat(value) <= min;\n};\n\nexport const isOutOfRange = (\n value: number | string | undefined,\n min: number,\n max: number,\n) => {\n if (value === undefined) return true;\n const floatValue = toFloat(value);\n return floatValue > max || floatValue < min;\n};\n"],"names":[],"mappings":";;AACO,MAAM,YAAe,GAAA;AAErB,MAAM,uBAAuB,CAClC,WAAA,EACA,aACG,KAAA,WAAA,CAAY,QAAQ,aAAa;AAEzB,MAAA,mBAAA,GAAsB,CAAC,cAAoC,KAAA;AACtE,EAAI,IAAA,OAAO,mBAAmB,QAAU,EAAA;AACxC,EAAA,OACG,KAAK,QAAS,CAAA,cAAc,KAAK,cAAe,CAAA,MAAA,KAAW,KAC5D,cAAmB,KAAA,EAAA;AAEvB;AAEa,MAAA,OAAA,GAAU,CAAC,UAAgC,KAAA;AAEtD,EAAI,IAAA,mBAAA,CAAoB,UAAU,CAAA,EAAU,OAAA,CAAA;AAC5C,EAAA,OAAO,MAAO,CAAA,UAAA,CAAW,UAAW,CAAA,QAAA,EAAU,CAAA;AAChD;AAEa,MAAA,cAAA,GAAiB,CAAC,YAAA,KAAA,CAC5B,YAAa,CAAA,KAAA,CAAM,YAAY,CAAK,IAAA,EAAI,EAAA,IAAA,CAAK,EAAE;AAErC,MAAA,OAAA,GAAU,CAAC,KAAA,EAAoC,GAAgB,KAAA;AAC1E,EAAI,IAAA,KAAA,KAAU,QAAkB,OAAA,IAAA;AAChC,EAAO,OAAA,OAAA,CAAQ,KAAK,CAAK,IAAA,GAAA;AAC3B;AAEa,MAAA,OAAA,GAAU,CAAC,KAAA,EAAoC,GAAgB,KAAA;AAC1E,EAAI,IAAA,KAAA,KAAU,QAAkB,OAAA,IAAA;AAChC,EAAO,OAAA,OAAA,CAAQ,KAAK,CAAK,IAAA,GAAA;AAC3B;AAEO,MAAM,YAAe,GAAA,CAC1B,KACA,EAAA,GAAA,EACA,GACG,KAAA;AACH,EAAI,IAAA,KAAA,KAAU,QAAkB,OAAA,IAAA;AAChC,EAAM,MAAA,UAAA,GAAa,QAAQ,KAAK,CAAA;AAChC,EAAO,OAAA,UAAA,GAAa,OAAO,UAAa,GAAA,GAAA;AAC1C;;;;;;;;;;;"}
1
+ {"version":3,"file":"utils.js","sources":["../src/number-input/internal/utils.ts"],"sourcesContent":["// The input should only accept numbers, decimal points, and plus/minus symbols\nexport const isAllowedNonNumeric = (inputCharacter: number | string) => {\n if (typeof inputCharacter === \"number\") return;\n return (\n (\"-+\".includes(inputCharacter) && inputCharacter.length === 1) ||\n inputCharacter === \"\"\n );\n};\n\nexport const toFloat = (inputValue: number | string) => {\n // Plus, minus, and empty characters are treated as 0\n if (isAllowedNonNumeric(inputValue)) return 0;\n return Number.parseFloat(inputValue.toString());\n};\n\nexport const isValidNumber = (num: string | number) => {\n if (typeof num === \"number\") {\n return !Number.isNaN(num);\n }\n\n // Empty\n if (!num) {\n return false;\n }\n\n return (\n // Normal type: 11.28\n /^\\s*-?\\d+(\\.\\d+)?\\s*$/.test(num) ||\n // Pre-number: 1.\n /^\\s*-?\\d+\\.\\s*$/.test(num) ||\n // Post-number: .1\n /^\\s*-?\\.\\d+\\s*$/.test(num)\n );\n};\n\nexport const sanitizeInput = (value: string | number) => {\n if (typeof value === \"number\") return value;\n let sanitizedInput = value.replace(/[^0-9.+-]/g, \"\");\n sanitizedInput = sanitizedInput.replace(\n /^([+-]?)(.*)$/,\n (match, sign, rest) => {\n return sign + rest.replace(/[+-]/g, \"\");\n },\n );\n const parts = sanitizedInput.split(\".\");\n if (parts.length > 2) {\n sanitizedInput = `${parts[0]}.${parts.slice(1).join(\"\")}`;\n }\n\n return sanitizedInput;\n};\n\nexport const isOutOfRange = (\n value: number | string | undefined,\n min: number,\n max: number,\n) => {\n if (value === undefined) return true;\n const floatValue = toFloat(value);\n return floatValue > max || floatValue < min;\n};\n\nexport const clampToRange = (min: number, max: number, value: number) => {\n if (value < min) return min;\n if (value > max) return max;\n return value;\n};\n\nconst isExponential = (number: string | number) => {\n const str = String(number);\n\n return !Number.isNaN(Number(str)) && str.includes(\"e\");\n};\n\nexport const getNumberPrecision = (number: string | number) => {\n const numStr: string = String(sanitizeInput(number));\n\n if (isExponential(number)) {\n let precision = Number(numStr.slice(numStr.indexOf(\"e-\") + 2));\n\n const decimalMatch = numStr.match(/\\.(\\d+)/);\n if (decimalMatch?.[1]) {\n precision += decimalMatch[1].length;\n }\n return precision;\n }\n\n return numStr.includes(\".\") && isValidNumber(numStr)\n ? numStr.length - numStr.indexOf(\".\") - 1\n : 0;\n};\n\nexport const isEmpty = (value: number | string) => {\n return value === \"\";\n};\n"],"names":[],"mappings":"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"}