@salt-ds/lab 1.0.0-alpha.77 → 1.0.0-alpha.79

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 (40) hide show
  1. package/CHANGELOG.md +80 -0
  2. package/css/salt-lab.css +17 -13
  3. package/dist-cjs/calendar/useCalendarDay.js +3 -2
  4. package/dist-cjs/calendar/useCalendarDay.js.map +1 -1
  5. package/dist-cjs/form-field-legacy/FormHelperText.css.js +1 -1
  6. package/dist-cjs/form-field-legacy/FormLabel.css.js +1 -1
  7. package/dist-cjs/index.js +1 -2
  8. package/dist-cjs/index.js.map +1 -1
  9. package/dist-cjs/number-input/NumberInput.css.js +1 -1
  10. package/dist-cjs/number-input/NumberInput.js +201 -131
  11. package/dist-cjs/number-input/NumberInput.js.map +1 -1
  12. package/dist-cjs/tabs-next/TabNextTrigger.css.js +1 -1
  13. package/dist-es/calendar/useCalendarDay.js +3 -2
  14. package/dist-es/calendar/useCalendarDay.js.map +1 -1
  15. package/dist-es/form-field-legacy/FormHelperText.css.js +1 -1
  16. package/dist-es/form-field-legacy/FormLabel.css.js +1 -1
  17. package/dist-es/index.js +1 -2
  18. package/dist-es/index.js.map +1 -1
  19. package/dist-es/number-input/NumberInput.css.js +1 -1
  20. package/dist-es/number-input/NumberInput.js +201 -132
  21. package/dist-es/number-input/NumberInput.js.map +1 -1
  22. package/dist-es/tabs-next/TabNextTrigger.css.js +1 -1
  23. package/dist-types/number-input/NumberInput.d.ts +28 -15
  24. package/dist-types/number-input/index.d.ts +0 -1
  25. package/package.json +4 -4
  26. package/dist-cjs/number-input/internal/useCaret.js +0 -34
  27. package/dist-cjs/number-input/internal/useCaret.js.map +0 -1
  28. package/dist-cjs/number-input/internal/utils.js +0 -78
  29. package/dist-cjs/number-input/internal/utils.js.map +0 -1
  30. package/dist-cjs/number-input/useNumberInput.js +0 -107
  31. package/dist-cjs/number-input/useNumberInput.js.map +0 -1
  32. package/dist-es/number-input/internal/useCaret.js +0 -32
  33. package/dist-es/number-input/internal/useCaret.js.map +0 -1
  34. package/dist-es/number-input/internal/utils.js +0 -69
  35. package/dist-es/number-input/internal/utils.js.map +0 -1
  36. package/dist-es/number-input/useNumberInput.js +0 -105
  37. package/dist-es/number-input/useNumberInput.js.map +0 -1
  38. package/dist-types/number-input/internal/useCaret.d.ts +0 -5
  39. package/dist-types/number-input/internal/utils.d.ts +0 -8
  40. package/dist-types/number-input/useNumberInput.d.ts +0 -33
@@ -1 +1 @@
1
- {"version":3,"file":"useCalendarDay.js","sources":["../src/calendar/useCalendarDay.ts"],"sourcesContent":["import type { DateFrameworkType } from \"@salt-ds/date-adapters\";\nimport type {\n ComponentPropsWithoutRef,\n FocusEventHandler,\n KeyboardEventHandler,\n MouseEventHandler,\n} from \"react\";\nimport { useLocalization } from \"../localization-provider\";\nimport { useCalendarContext } from \"./internal/CalendarContext\";\nimport { useFocusManagement } from \"./internal/useFocusManagement\";\nimport { useCalendarSelectionDay } from \"./useCalendarSelection\";\n\n/**\n * Interface representing the status of a day in the Calendar.\n */\nexport interface DayStatus {\n /**\n * If `true`, the day is selectable but outside of current month.\n */\n outOfRange?: boolean;\n /**\n * If `true`, the day is selected.\n */\n selected?: boolean;\n /**\n * If `true`, the day is today.\n */\n today?: boolean;\n /**\n * If set, the day is unselectable with a reason.\n */\n unselectable?: string | false;\n /**\n * If set, the day is highlighted with a reason.\n */\n highlighted?: string | false;\n /**\n * If `true`, the day is focused.\n */\n focused?: boolean;\n /**\n * If `true`, the day is hidden.\n */\n hidden?: boolean;\n}\n\n/**\n * UseCalendar hook props to return a calendar day's status\n * @template TDate - The type of the date object.\n */\nexport interface useCalendarDayProps<TDate> {\n /**\n * The date of the calendar day.\n */\n date: TDate;\n /**\n * The month of the calendar day.\n */\n month: TDate;\n}\n\nexport function useCalendarDay<TDate extends DateFrameworkType>(\n props: useCalendarDayProps<TDate>,\n) {\n const { date, month } = props;\n const { dateAdapter } = useLocalization<TDate>();\n const {\n state: {\n focusedDate,\n focusedDateRef,\n hideOutOfRangeDates,\n timezone,\n focusableDates,\n },\n helpers: {\n setHoveredDate,\n isDayUnselectable,\n isDayHighlighted,\n isOutsideAllowedMonths,\n },\n } = useCalendarContext<TDate>();\n const selectionManager = useCalendarSelectionDay<TDate>({ date });\n const focusManager = useFocusManagement<TDate>({ date });\n\n const handleClick: MouseEventHandler<HTMLButtonElement> = (event) => {\n selectionManager.handleClick(event);\n focusManager.handleClick(event);\n };\n\n const handleKeyDown: KeyboardEventHandler<HTMLButtonElement> = (event) => {\n focusManager.handleKeyDown(event);\n selectionManager.handleKeyDown(event);\n };\n\n const handleFocus: FocusEventHandler<HTMLButtonElement> = (event) => {\n focusManager.handleFocus(event);\n setHoveredDate(event, date);\n };\n\n const handleMouseMove: MouseEventHandler<HTMLButtonElement> = (event) => {\n setHoveredDate(event, date);\n };\n\n const eventHandlers = {\n onClick: handleClick,\n onKeyDown: handleKeyDown,\n onFocus: handleFocus,\n onMouseMove: handleMouseMove,\n };\n\n const focused = focusedDate && dateAdapter.isSame(date, focusedDate, \"day\");\n const tabIndex = focusableDates.find((tabbableDate) =>\n dateAdapter.isSame(date, tabbableDate, \"day\"),\n )\n ? 0\n : -1;\n const today = dateAdapter.isSame(dateAdapter.today(timezone), date, \"day\");\n\n const unselectableReason = isDayUnselectable(date);\n const highlightedReason = isDayHighlighted(date);\n\n const outOfRange = !dateAdapter.isSame(date, month, \"month\");\n const unselectable =\n Boolean(unselectableReason) || isOutsideAllowedMonths(date);\n const highlighted = Boolean(highlightedReason);\n const hidden = hideOutOfRangeDates ? outOfRange : false;\n\n return {\n status: {\n outOfRange,\n today,\n unselectable,\n focused,\n hidden,\n highlighted,\n ...selectionManager.status,\n } as DayStatus,\n dayProps: {\n tabIndex,\n \"aria-current\": today ? \"date\" : undefined,\n \"aria-hidden\": hidden ? \"true\" : undefined,\n ...eventHandlers,\n ...selectionManager.dayProps,\n } as ComponentPropsWithoutRef<\"button\">,\n focusedDateRef: focused ? focusedDateRef : null,\n unselectableReason,\n highlightedReason,\n };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useCalendarDay.js","sources":["../src/calendar/useCalendarDay.ts"],"sourcesContent":["import type { DateFrameworkType } from \"@salt-ds/date-adapters\";\nimport type {\n ComponentPropsWithoutRef,\n FocusEventHandler,\n KeyboardEventHandler,\n MouseEventHandler,\n} from \"react\";\nimport { useLocalization } from \"../localization-provider\";\nimport { useCalendarContext } from \"./internal/CalendarContext\";\nimport { useFocusManagement } from \"./internal/useFocusManagement\";\nimport { useCalendarSelectionDay } from \"./useCalendarSelection\";\n\n/**\n * Interface representing the status of a day in the Calendar.\n */\nexport interface DayStatus {\n /**\n * If `true`, the day is selectable but outside of current month.\n */\n outOfRange?: boolean;\n /**\n * If `true`, the day is selected.\n */\n selected?: boolean;\n /**\n * If `true`, the day is today.\n */\n today?: boolean;\n /**\n * If set, the day is unselectable with a reason.\n */\n unselectable?: string | false;\n /**\n * If set, the day is highlighted with a reason.\n */\n highlighted?: string | false;\n /**\n * If `true`, the day is focused.\n */\n focused?: boolean;\n /**\n * If `true`, the day is hidden.\n */\n hidden?: boolean;\n}\n\n/**\n * UseCalendar hook props to return a calendar day's status\n * @template TDate - The type of the date object.\n */\nexport interface useCalendarDayProps<TDate> {\n /**\n * The date of the calendar day.\n */\n date: TDate;\n /**\n * The month of the calendar day.\n */\n month: TDate;\n}\n\nexport function useCalendarDay<TDate extends DateFrameworkType>(\n props: useCalendarDayProps<TDate>,\n) {\n const { date, month } = props;\n const { dateAdapter } = useLocalization<TDate>();\n const {\n state: {\n focusedDate,\n focusedDateRef,\n hideOutOfRangeDates,\n timezone,\n focusableDates,\n },\n helpers: {\n setHoveredDate,\n isDayUnselectable,\n isDayHighlighted,\n isOutsideAllowedMonths,\n isOutsideAllowedDates,\n },\n } = useCalendarContext<TDate>();\n const selectionManager = useCalendarSelectionDay<TDate>({ date });\n const focusManager = useFocusManagement<TDate>({ date });\n\n const handleClick: MouseEventHandler<HTMLButtonElement> = (event) => {\n selectionManager.handleClick(event);\n focusManager.handleClick(event);\n };\n\n const handleKeyDown: KeyboardEventHandler<HTMLButtonElement> = (event) => {\n focusManager.handleKeyDown(event);\n selectionManager.handleKeyDown(event);\n };\n\n const handleFocus: FocusEventHandler<HTMLButtonElement> = (event) => {\n focusManager.handleFocus(event);\n setHoveredDate(event, date);\n };\n\n const handleMouseMove: MouseEventHandler<HTMLButtonElement> = (event) => {\n setHoveredDate(event, date);\n };\n\n const eventHandlers = {\n onClick: handleClick,\n onKeyDown: handleKeyDown,\n onFocus: handleFocus,\n onMouseMove: handleMouseMove,\n };\n\n const focused = focusedDate && dateAdapter.isSame(date, focusedDate, \"day\");\n const tabIndex = focusableDates.find((tabbableDate) =>\n dateAdapter.isSame(date, tabbableDate, \"day\"),\n )\n ? 0\n : -1;\n const today = dateAdapter.isSame(dateAdapter.today(timezone), date, \"day\");\n\n const unselectableReason = isDayUnselectable(date);\n const highlightedReason = isDayHighlighted(date);\n\n const outOfRange = !dateAdapter.isSame(date, month, \"month\");\n const unselectable =\n Boolean(unselectableReason) ||\n isOutsideAllowedMonths(date) ||\n isOutsideAllowedDates(date);\n const highlighted = Boolean(highlightedReason);\n const hidden = hideOutOfRangeDates ? outOfRange : false;\n\n return {\n status: {\n outOfRange,\n today,\n unselectable,\n focused,\n hidden,\n highlighted,\n ...selectionManager.status,\n } as DayStatus,\n dayProps: {\n tabIndex,\n \"aria-current\": today ? \"date\" : undefined,\n \"aria-hidden\": hidden ? \"true\" : undefined,\n ...eventHandlers,\n ...selectionManager.dayProps,\n } as ComponentPropsWithoutRef<\"button\">,\n focusedDateRef: focused ? focusedDateRef : null,\n unselectableReason,\n highlightedReason,\n };\n}\n"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- var css_248z = "/* Styles applied to the root element dependent on density */\n.salt-density-high {\n --formFieldLegacy-helperText-marginTop-default: 2px;\n --formFieldLegacy-helperText-marginTop-fullWidth: 3px;\n\n --formFieldLegacy-helperText-background-offset-height: 17px;\n}\n.salt-density-medium {\n --formFieldLegacy-helperText-marginTop-default: 2px;\n --formFieldLegacy-helperText-marginTop-fullWidth: 3px;\n --formFieldLegacy-helperText-transform: translate(0, 2px);\n\n --formFieldLegacy-helperText-background-offset-height: 19px;\n}\n.salt-density-touch {\n --formFieldLegacy-helperText-marginTop-default: 8px;\n --formFieldLegacy-helperText-marginTop-fullWidth: 5px;\n --formFieldLegacy-helperText-transform: translate(0, -3px);\n\n --formFieldLegacy-helperText-background-offset-height: 21px;\n}\n.salt-density-low {\n --formFieldLegacy-helperText-marginTop-default: 4px;\n --formFieldLegacy-helperText-marginTop-fullWidth: 5px;\n --formFieldLegacy-helperText-transform: translate(0, 1px);\n\n --formFieldLegacy-helperText-background-offset-height: 21px;\n}\n\n/* Class applied if `fullWidth={true}` */\n.saltFormFieldLegacy-fullWidth {\n --formFieldLegacy-helperText-transform: none;\n}\n\n/* Class applied to the helper text container */\n.saltFormHelperText {\n --formFieldLegacy-helperText-opacity: 1;\n\n color: var(--saltFormFieldLegacy-helperText-color, var(--salt-content-secondary-foreground));\n font-size: var(--formFieldLegacy-helperText-fontSize);\n font-style: var(--saltFormFieldLegacy-helperText-fontStyle, var(--salt-editable-help-fontStyle));\n letter-spacing: var(--saltFormFieldLegacy-helperText-letterSpacing, 0);\n line-height: var(--saltFormFieldLegacy-helperText-lineHeight, var(--salt-text-lineHeight));\n min-height: var(--saltFormFieldLegacy-helperText-minHeight, var(--salt-text-label-minHeight));\n margin-bottom: var(--saltFormFieldLegacy-helperText-marginBottom, 0);\n margin-top: var(--saltFormFieldLegacy-helperText-marginTop, var(--formFieldLegacy-helperText-marginTop));\n opacity: var(--saltFormFieldLegacy-helperText-opacity, var(--formFieldLegacy-helperText-opacity));\n padding-left: var(--saltFormFieldLegacy-helperText-paddingLeft, var(--salt-size-unit));\n padding-right: var(--saltFormFieldLegacy-helperText-paddingRight, var(--salt-size-unit));\n transform: var(--saltFormFieldLegacy-helperText-transform, var(--formFieldLegacy-helperText-transform, none));\n}\n";
1
+ var css_248z = "/* Styles applied to the root element dependent on density */\n.salt-density-high {\n --formFieldLegacy-helperText-marginTop-default: 2px;\n --formFieldLegacy-helperText-marginTop-fullWidth: 3px;\n\n --formFieldLegacy-helperText-background-offset-height: 17px;\n}\n.salt-density-medium {\n --formFieldLegacy-helperText-marginTop-default: 2px;\n --formFieldLegacy-helperText-marginTop-fullWidth: 3px;\n --formFieldLegacy-helperText-transform: translate(0, 2px);\n\n --formFieldLegacy-helperText-background-offset-height: 19px;\n}\n.salt-density-touch {\n --formFieldLegacy-helperText-marginTop-default: 8px;\n --formFieldLegacy-helperText-marginTop-fullWidth: 5px;\n --formFieldLegacy-helperText-transform: translate(0, -3px);\n\n --formFieldLegacy-helperText-background-offset-height: 21px;\n}\n.salt-density-low {\n --formFieldLegacy-helperText-marginTop-default: 4px;\n --formFieldLegacy-helperText-marginTop-fullWidth: 5px;\n --formFieldLegacy-helperText-transform: translate(0, 1px);\n\n --formFieldLegacy-helperText-background-offset-height: 21px;\n}\n\n/* Class applied if `fullWidth={true}` */\n.saltFormFieldLegacy-fullWidth {\n --formFieldLegacy-helperText-transform: none;\n}\n\n/* Class applied to the helper text container */\n.saltFormHelperText {\n --formFieldLegacy-helperText-opacity: 1;\n\n color: var(--saltFormFieldLegacy-helperText-color, var(--salt-content-secondary-foreground));\n font-size: var(--formFieldLegacy-helperText-fontSize);\n font-style: var(--saltFormFieldLegacy-helperText-fontStyle, var(--salt-typography-textDecoration-italic));\n letter-spacing: var(--saltFormFieldLegacy-helperText-letterSpacing, 0);\n line-height: var(--saltFormFieldLegacy-helperText-lineHeight, var(--salt-text-lineHeight));\n min-height: var(--saltFormFieldLegacy-helperText-minHeight, var(--salt-text-label-minHeight));\n margin-bottom: var(--saltFormFieldLegacy-helperText-marginBottom, 0);\n margin-top: var(--saltFormFieldLegacy-helperText-marginTop, var(--formFieldLegacy-helperText-marginTop));\n opacity: var(--saltFormFieldLegacy-helperText-opacity, var(--formFieldLegacy-helperText-opacity));\n padding-left: var(--saltFormFieldLegacy-helperText-paddingLeft, var(--salt-size-unit));\n padding-right: var(--saltFormFieldLegacy-helperText-paddingRight, var(--salt-size-unit));\n transform: var(--saltFormFieldLegacy-helperText-transform, var(--formFieldLegacy-helperText-transform, none));\n}\n";
2
2
 
3
3
  export { css_248z as default };
4
4
  //# sourceMappingURL=FormHelperText.css.js.map
@@ -1,4 +1,4 @@
1
- var css_248z = "/* Styles applied to root element */\n.salt-density-touch {\n --formFieldLegacy-label-default-top: 11px;\n --formFieldLegacy-label-left-top: 16px;\n --formFieldLegacy-label-minHeight: 16px;\n}\n.salt-density-low {\n --formFieldLegacy-label-default-top: 7px;\n --formFieldLegacy-label-left-top: 12px;\n}\n.salt-density-medium {\n --formFieldLegacy-label-default-top: 5px;\n --formFieldLegacy-label-left-top: 8px;\n}\n.salt-density-high {\n --formFieldLegacy-label-default-top: 3px;\n --formFieldLegacy-label-left-top: 4px;\n}\n\n.saltFormLabel {\n --formFieldLegacy-label-fontSize: var(--saltFormFieldLegacy-label-fontSize, var(--salt-text-label-fontSize));\n --formFieldLegacy-label-top: var(--formFieldLegacy-label-default-top);\n --formFieldLegacy-label-width: 100%;\n}\n\n.saltFormFieldLegacy-labelLeft .saltFormLabel {\n --formFieldLegacy-label-top: var(--formFieldLegacy-label-left-top);\n --formFieldLegacy-label-width: auto;\n}\n\n.saltFormLabel {\n align-items: center;\n color: var(--saltFormFieldLegacy-label-text-color, var(--salt-content-secondary-foreground));\n display: block;\n font-size: var(--formFieldLegacy-label-fontSize);\n margin-bottom: var(--saltFormFieldLegacy-label-marginBottom, var(--formFieldLegacy-label-marginBottom));\n min-height: var(--saltFormFieldLegacy-label-minHeight, var(--formFieldLegacy-label-minHeight, var(--salt-text-label-minHeight)));\n margin-top: var(--saltFormFieldLegacy-label-marginTop, 0px);\n line-height: var(--saltFormFieldLegacy-label-lineHeight, var(--salt-text-label-lineHeight));\n overflow: hidden;\n padding-left: var(--saltFormFieldLegacy-label-paddingLeft, var(--formFieldLegacy-label-paddingLeft));\n padding-right: var(--saltFormFieldLegacy-label-paddingRight, var(--formFieldLegacy-label-paddingRight));\n padding-top: var(--saltFormFieldLegacy-label-paddingTop, 0);\n padding-bottom: var(--saltFormFieldLegacy-label-paddingBottom, 0);\n text-overflow: ellipsis;\n top: var(--saltFormFieldLegacy-label-top, var(--formFieldLegacy-label-top));\n transform: translate(var(--saltFormFieldLegacy-label-transform-x, 0), var(--saltFormFieldLegacy-label-transform-y, var(--formFieldLegacy-label-top)));\n white-space: nowrap;\n width: var(--saltFormFieldLegacy-label-width, var(--formFieldLegacy-label-width, 100%));\n box-sizing: border-box;\n}\n\n.saltFormLabel ~ * {\n z-index: 1;\n}\n\n/* Styles applied when `disabled={true}` */\n.saltFormLabel-disabled {\n color: var(--saltFormFieldLegacy-label-text-color-disabled, var(--salt-content-secondary-foreground-disabled));\n cursor: var(--salt-cursor-disabled);\n}\n\n/* Styles applied when displayedNecessity or necessityText provided */\n.saltFormLabel-necessityIndicator {\n font-style: var(--saltFormFieldLegacy-label-necessityIndicator-fontStyle, var(--salt-editable-help-fontStyle));\n margin-left: 1ch;\n}\n\n/* Styles applied if `hasStatusIndicator={true}` */\n.saltFormLabel-statusIndicator.saltIcon {\n margin-left: 6px;\n vertical-align: top;\n}\n";
1
+ var css_248z = "/* Styles applied to root element */\n.salt-density-touch {\n --formFieldLegacy-label-default-top: 11px;\n --formFieldLegacy-label-left-top: 16px;\n --formFieldLegacy-label-minHeight: 16px;\n}\n.salt-density-low {\n --formFieldLegacy-label-default-top: 7px;\n --formFieldLegacy-label-left-top: 12px;\n}\n.salt-density-medium {\n --formFieldLegacy-label-default-top: 5px;\n --formFieldLegacy-label-left-top: 8px;\n}\n.salt-density-high {\n --formFieldLegacy-label-default-top: 3px;\n --formFieldLegacy-label-left-top: 4px;\n}\n\n.saltFormLabel {\n --formFieldLegacy-label-fontSize: var(--saltFormFieldLegacy-label-fontSize, var(--salt-text-label-fontSize));\n --formFieldLegacy-label-top: var(--formFieldLegacy-label-default-top);\n --formFieldLegacy-label-width: 100%;\n}\n\n.saltFormFieldLegacy-labelLeft .saltFormLabel {\n --formFieldLegacy-label-top: var(--formFieldLegacy-label-left-top);\n --formFieldLegacy-label-width: auto;\n}\n\n.saltFormLabel {\n align-items: center;\n color: var(--saltFormFieldLegacy-label-text-color, var(--salt-content-secondary-foreground));\n display: block;\n font-size: var(--formFieldLegacy-label-fontSize);\n margin-bottom: var(--saltFormFieldLegacy-label-marginBottom, var(--formFieldLegacy-label-marginBottom));\n min-height: var(--saltFormFieldLegacy-label-minHeight, var(--formFieldLegacy-label-minHeight, var(--salt-text-label-minHeight)));\n margin-top: var(--saltFormFieldLegacy-label-marginTop, 0px);\n line-height: var(--saltFormFieldLegacy-label-lineHeight, var(--salt-text-label-lineHeight));\n overflow: hidden;\n padding-left: var(--saltFormFieldLegacy-label-paddingLeft, var(--formFieldLegacy-label-paddingLeft));\n padding-right: var(--saltFormFieldLegacy-label-paddingRight, var(--formFieldLegacy-label-paddingRight));\n padding-top: var(--saltFormFieldLegacy-label-paddingTop, 0);\n padding-bottom: var(--saltFormFieldLegacy-label-paddingBottom, 0);\n text-overflow: ellipsis;\n top: var(--saltFormFieldLegacy-label-top, var(--formFieldLegacy-label-top));\n transform: translate(var(--saltFormFieldLegacy-label-transform-x, 0), var(--saltFormFieldLegacy-label-transform-y, var(--formFieldLegacy-label-top)));\n white-space: nowrap;\n width: var(--saltFormFieldLegacy-label-width, var(--formFieldLegacy-label-width, 100%));\n box-sizing: border-box;\n}\n\n.saltFormLabel ~ * {\n z-index: 1;\n}\n\n/* Styles applied when `disabled={true}` */\n.saltFormLabel-disabled {\n color: var(--saltFormFieldLegacy-label-text-color-disabled, var(--salt-content-secondary-foreground-disabled));\n cursor: var(--salt-cursor-disabled);\n}\n\n/* Styles applied when displayedNecessity or necessityText provided */\n.saltFormLabel-necessityIndicator {\n font-style: var(--saltFormFieldLegacy-label-necessityIndicator-fontStyle, var(--salt-typography-textDecoration-italic));\n margin-left: 1ch;\n}\n\n/* Styles applied if `hasStatusIndicator={true}` */\n.saltFormLabel-statusIndicator.saltIcon {\n margin-left: 6px;\n vertical-align: top;\n}\n";
2
2
 
3
3
  export { css_248z as default };
4
4
  //# sourceMappingURL=FormLabel.css.js.map
package/dist-es/index.js CHANGED
@@ -103,8 +103,7 @@ export { MenuButton } from './menu-button/MenuButton.js';
103
103
  export { Metric } from './metric/Metric.js';
104
104
  export { MetricContent } from './metric/MetricContent.js';
105
105
  export { MetricHeader } from './metric/MetricHeader.js';
106
- export { NumberInput } from './number-input/NumberInput.js';
107
- export { useNumberInput } from './number-input/useNumberInput.js';
106
+ export { NumberInput, isOutOfRange } from './number-input/NumberInput.js';
108
107
  export { Portal } from './portal/Portal.js';
109
108
  export { QueryInput } from './query-input/QueryInput.js';
110
109
  export { useQueryInput } from './query-input/useQueryInput.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,4 +1,4 @@
1
- var css_248z = "/* Styles applied to number container */\n.saltNumberInput {\n --numberInput-border: var(--salt-size-fixed-100) var(--salt-borderStyle-solid) var(--numberInput-borderColor);\n --numberInput-borderColor: var(--salt-editable-borderColor);\n --numberInput-borderStyle: var(--salt-borderStyle-solid);\n --numberInput-outlineColor: var(--salt-focused-outlineColor);\n --numberInput-borderWidth: var(--salt-size-fixed-100);\n --numberInput-outline: none;\n\n align-items: center;\n background: var(--numberInput-background);\n border-radius: var(--salt-palette-corner-weak, 0);\n box-sizing: border-box;\n color: var(--salt-content-primary-foreground);\n display: inline-flex;\n font-family: var(--salt-text-fontFamily);\n font-size: var(--salt-text-fontSize);\n gap: var(--salt-spacing-50);\n height: var(--salt-size-base);\n min-height: var(--salt-size-base);\n min-width: 4em;\n overflow: hidden;\n outline: var(--numberInput-outline);\n padding-left: var(--salt-spacing-100);\n padding-right: var(--salt-spacing-50);\n padding-top: var(--salt-spacing-50);\n padding-bottom: var(--salt-spacing-50);\n position: relative;\n width: 100%;\n}\n\n.saltNumberInput:hover {\n --numberInput-borderStyle: var(--salt-borderStyle-solid);\n --numberInput-borderColor: var(--salt-editable-borderColor-hover);\n\n background: var(--numberInput-background-hover);\n cursor: var(--salt-cursor-text);\n}\n\n.saltNumberInput:active {\n --numberInput-borderColor: var(--salt-editable-borderColor-active);\n --numberInput-borderStyle: var(--salt-borderStyle-solid);\n --numberInput-borderWidth: var(--salt-size-fixed-200);\n\n background: var(--numberInput-background-active);\n}\n\n/* Class applied if `variant=\"primary\"` */\n.saltNumberInput-primary {\n --numberInput-background: var(--salt-editable-primary-background);\n --numberInput-background-active: var(--salt-editable-primary-background-active);\n --numberInput-background-hover: var(--salt-editable-primary-background-hover);\n --numberInput-background-disabled: var(--salt-editable-primary-background-disabled);\n --numberInput-background-readonly: var(--salt-editable-primary-background-readonly);\n}\n\n/* Class applied if `variant=\"secondary\"` */\n.saltNumberInput-secondary {\n --numberInput-background: var(--salt-editable-secondary-background);\n --numberInput-background-active: var(--salt-editable-secondary-background-active);\n --numberInput-background-hover: var(--salt-editable-secondary-background-active);\n --numberInput-background-disabled: var(--salt-editable-secondary-background-disabled);\n --numberInput-background-readonly: var(--salt-editable-secondary-background-readonly);\n}\n\n/* Style applied to input if `validationState=\"error\"` */\n.saltNumberInput-error,\n.saltNumberInput-error:hover {\n --numberInput-background: var(--salt-status-error-background);\n --numberInput-background-active: var(--salt-status-error-background);\n --numberInput-background-hover: var(--salt-status-error-background);\n --numberInput-borderColor: var(--salt-status-error-borderColor);\n --numberInput-outlineColor: var(--salt-status-error-borderColor);\n --numberInput-background-readonly: var(--salt-status-error-background);\n}\n\n/* Style applied to input if `validationState=\"warning\"` */\n.saltNumberInput-warning,\n.saltNumberInput-warning:hover {\n --numberInput-background: var(--salt-status-warning-background);\n --numberInput-background-active: var(--salt-status-warning-background);\n --numberInput-background-hover: var(--salt-status-warning-background);\n --numberInput-borderColor: var(--salt-status-warning-borderColor);\n --numberInput-outlineColor: var(--salt-status-warning-borderColor);\n --numberInput-background-readonly: var(--salt-status-warning-background);\n}\n\n/* Style applied to input if `validationState=\"success\"` */\n.saltNumberInput-success,\n.saltNumberInput-success:hover {\n --numberInput-background: var(--salt-status-success-background);\n --numberInput-background-active: var(--salt-status-success-background);\n --numberInput-background-hover: var(--salt-status-success-background);\n --numberInput-borderColor: var(--salt-status-success-borderColor);\n --numberInput-outlineColor: var(--salt-status-success-borderColor);\n --numberInput-background-readonly: var(--salt-status-success-background);\n}\n\n/* Style applied to inner input component */\n.saltNumberInput-input {\n background: none;\n border: none;\n box-sizing: content-box;\n color: inherit;\n cursor: inherit;\n display: block;\n flex: 1;\n font: inherit;\n letter-spacing: var(--salt-text-letterSpacing);\n line-height: var(--salt-text-lineHeight);\n margin: 0;\n min-width: 0;\n padding: 0;\n text-align: var(--numberInput-textAlign);\n width: 100%;\n}\n\n.saltNumberInput-input:focus {\n outline: none;\n}\n\n/* Style applied to placeholder text */\n.saltNumberInput-input::placeholder {\n color: var(--salt-content-secondary-foreground);\n font-weight: var(--salt-text-fontWeight-small);\n}\n\n/* Styling when focused */\n.saltNumberInput-focused {\n --numberInput-borderColor: var(--numberInput-outlineColor);\n --numberInput-borderWidth: var(--salt-size-fixed-200);\n\n outline: var(--saltNumberInput-outline, var(--salt-focused-outlineWidth) var(--salt-focused-outlineStyle) var(--numberInput-outlineColor));\n}\n\n/* Style applied if `bordered={true}` */\n.saltNumberInput-bordered {\n --numberInput-border: var(--salt-size-fixed-100) var(--salt-borderStyle-solid) var(--numberInput-borderColor);\n --numberInput-borderWidth: 0;\n\n border: var(--numberInput-border);\n}\n\n/* Style applied if focused or active when `bordered={true}` */\n.saltNumberInput-bordered.saltNumberInput-focused,\n.saltNumberInput-bordered:active {\n --numberInput-borderWidth: var(--salt-size-fixed-200);\n}\n\n/* Styling when focused if `disabled={true}` or `readOnly={true}` when `bordered={true}` */\n.saltNumberInput-bordered.saltNumberInput-readOnly,\n.saltNumberInput-bordered.saltNumberInput-disabled:hover {\n --numberInput-borderWidth: 0;\n}\n\n/* Styling when focused and hovered when `bordered={true}` */\n.saltNumberInput-bordered.saltNumberInput-focused:hover {\n --numberInput-borderColor: var(--salt-editable-borderColor-active);\n}\n\n/* Style applied if `readOnly={true}` */\n.saltNumberInput-readOnly,\n.saltNumberInput-bordered.saltNumberInput-readOnly {\n --numberInput-borderColor: var(--salt-editable-borderColor-readonly);\n --numberInput-borderStyle: var(--salt-borderStyle-solid);\n --numberInput-borderWidth: var(--salt-size-fixed-100);\n\n background: var(--numberInput-background-readonly);\n cursor: var(--salt-cursor-readonly);\n}\n\n/* Styling when focused if `disabled={true}` */\n.saltNumberInput-focused.saltNumberInput-disabled {\n --numberInput-borderWidth: var(--salt-size-fixed-100);\n outline: none;\n}\n\n/* Styling when focused if `readOnly={true}` */\n.saltNumberInput-focused.saltNumberInput-readOnly {\n --numberInput-borderWidth: var(--salt-size-fixed-100);\n}\n\n.saltNumberInput:hover.saltNumberInput-readOnly {\n --numberInput-borderColor: var(--salt-editable-borderColor-readonly);\n}\n\n/* Style applied to selected input if `disabled={true}` */\n.saltNumberInput-disabled .saltNumberInput-input::selection {\n background: none;\n}\n\n/* Style applied to input if `disabled={true}` */\n.saltNumberInput-disabled,\n.saltNumberInput-disabled:hover,\n.saltNumberInput-disabled:active {\n --numberInput-borderColor: var(--salt-editable-borderColor-disabled);\n --numberInput-borderStyle: var(--salt-borderStyle-solid);\n --numberInput-borderWidth: var(--salt-size-fixed-100);\n\n background: var(--numberInput-background-disabled);\n cursor: var(--salt-cursor-disabled);\n color: var(--saltNumberInput-color-disabled, var(--salt-content-primary-foreground-disabled));\n}\n\n/* Style applied to start adornments */\n.saltNumberInput-startAdornmentContainer {\n align-items: center;\n display: inline-flex;\n padding-right: var(--salt-spacing-100);\n column-gap: var(--salt-spacing-100);\n}\n\n/* Style applied to end adornments */\n.saltNumberInput-endAdornmentContainer {\n align-items: center;\n display: inline-flex;\n padding-left: var(--salt-spacing-100);\n column-gap: var(--salt-spacing-100);\n}\n\n.saltNumberInput-startAdornmentContainer {\n margin-left: calc(var(--salt-spacing-50) * -1);\n}\n\n.saltNumberInput-startAdornmentContainer > .saltButton,\n.saltNumberInput-endAdornmentContainer > .saltButton {\n --saltButton-padding: calc(var(--salt-spacing-50) - var(--button-borderWidth));\n --saltButton-height: calc(var(--salt-size-base) - var(--salt-spacing-100));\n --saltButton-borderRadius: var(--salt-palette-corner-weaker);\n}\n\n.saltNumberInput-inputTextAlignLeft {\n --numberInput-textAlign: left;\n}\n\n.saltNumberInput-inputTextAlignCenter {\n --numberInput-textAlign: center;\n}\n\n.saltNumberInput-inputTextAlignRight {\n --numberInput-textAlign: right;\n}\n\n/* --- Buttons --- */\n\n/* Styles applied to number buttons container */\n.saltNumberInput-buttonContainer {\n --numberInput-buttonGap: var(--salt-spacing-fixed-200);\n display: flex;\n flex-direction: column;\n gap: var(--numberInput-buttonGap);\n justify-content: center;\n}\n\n.saltNumberInput-hiddenButtons .saltNumberInput-buttonContainer {\n display: none;\n}\n\n/* Styles applied to number buttons */\n.saltNumberInput-numberButton {\n --saltButton-height: calc((var(--salt-size-base) - (var(--salt-spacing-50) * 2) - var(--salt-size-fixed-200)) / 2);\n --saltButton-padding: calc(var(--salt-spacing-50) - var(--button-borderWidth));\n}\n\n.saltNumberInput-numberButtonIncrement {\n --saltButton-borderRadius: var(--salt-palette-corner-weaker, 0) var(--salt-palette-corner-weaker, 0) 0 0;\n}\n.saltNumberInput-numberButtonDecrement {\n --saltButton-borderRadius: 0 0 var(--salt-palette-corner-weaker, 0) var(--salt-palette-corner-weaker, 0);\n}\n\n.saltNumberInput-activationIndicator {\n left: 0;\n bottom: 0;\n width: 100%;\n position: absolute;\n border-bottom: var(--salt-size-fixed-100) var(--salt-borderStyle-solid) var(--numberInput-borderColor);\n}\n\n.saltNumberInput-focused .saltNumberInput-activationIndicator {\n border-bottom: var(--salt-size-fixed-200) var(--salt-borderStyle-solid) var(--salt-editable-borderColor-active);\n}\n\n.saltNumberInput-bordered.saltNumberInput-focused .saltNumberInput-activationIndicator {\n /* Activation indicator width minus the border from the number input. */\n border-bottom-width: var(--salt-size-fixed-100);\n}\n\n.saltNumberInput-bordered .saltNumberInput-activationIndicator,\n.saltNumberInput-readOnly.saltNumberInput-focused .saltNumberInput-activationIndicator {\n border-bottom-width: 0;\n}\n";
1
+ var css_248z = "/* Styles applied to number container */\n.saltNumberInput {\n --numberInput-border: var(--salt-size-fixed-100) var(--salt-borderStyle-solid) var(--numberInput-borderColor);\n --numberInput-borderColor: var(--salt-editable-borderColor);\n --numberInput-borderStyle: var(--salt-borderStyle-solid);\n --numberInput-outlineColor: var(--salt-focused-outlineColor);\n --numberInput-borderWidth: var(--salt-size-fixed-100);\n --numberInput-outline: none;\n\n align-items: center;\n background: var(--numberInput-background);\n border-radius: var(--salt-palette-corner-weak, 0);\n box-sizing: border-box;\n color: var(--salt-content-primary-foreground);\n display: inline-flex;\n font-family: var(--salt-text-fontFamily);\n font-size: var(--salt-text-fontSize);\n gap: var(--salt-spacing-50);\n height: var(--salt-size-base);\n min-height: var(--salt-size-base);\n min-width: 4em;\n overflow: hidden;\n outline: var(--numberInput-outline);\n padding-left: var(--salt-spacing-100);\n padding-right: var(--salt-spacing-50);\n padding-top: var(--salt-spacing-50);\n padding-bottom: var(--salt-spacing-50);\n position: relative;\n width: 100%;\n}\n\n.saltNumberInput:hover {\n --numberInput-borderStyle: var(--salt-borderStyle-solid);\n --numberInput-borderColor: var(--salt-editable-borderColor-hover);\n\n background: var(--numberInput-background-hover);\n cursor: var(--salt-cursor-text);\n}\n\n.saltNumberInput:active {\n --numberInput-borderColor: var(--salt-editable-borderColor-active);\n --numberInput-borderStyle: var(--salt-borderStyle-solid);\n --numberInput-borderWidth: var(--salt-size-fixed-200);\n\n background: var(--numberInput-background-active);\n}\n\n/* Class applied if `variant=\"primary\"` */\n.saltNumberInput-primary {\n --numberInput-background: var(--salt-editable-primary-background);\n --numberInput-background-active: var(--salt-editable-primary-background-active);\n --numberInput-background-hover: var(--salt-editable-primary-background-hover);\n --numberInput-background-disabled: var(--salt-editable-primary-background-disabled);\n --numberInput-background-readonly: var(--salt-editable-primary-background-readonly);\n}\n\n/* Class applied if `variant=\"secondary\"` */\n.saltNumberInput-secondary {\n --numberInput-background: var(--salt-editable-secondary-background);\n --numberInput-background-active: var(--salt-editable-secondary-background-active);\n --numberInput-background-hover: var(--salt-editable-secondary-background-active);\n --numberInput-background-disabled: var(--salt-editable-secondary-background-disabled);\n --numberInput-background-readonly: var(--salt-editable-secondary-background-readonly);\n}\n\n/* Style applied to input if `validationState=\"error\"` */\n.saltNumberInput-error,\n.saltNumberInput-error:hover {\n --numberInput-background: var(--salt-status-error-background);\n --numberInput-background-active: var(--salt-status-error-background);\n --numberInput-background-hover: var(--salt-status-error-background);\n --numberInput-borderColor: var(--salt-status-error-borderColor);\n --numberInput-outlineColor: var(--salt-status-error-borderColor);\n --numberInput-background-readonly: var(--salt-status-error-background);\n}\n\n/* Style applied to input if `validationState=\"warning\"` */\n.saltNumberInput-warning,\n.saltNumberInput-warning:hover {\n --numberInput-background: var(--salt-status-warning-background);\n --numberInput-background-active: var(--salt-status-warning-background);\n --numberInput-background-hover: var(--salt-status-warning-background);\n --numberInput-borderColor: var(--salt-status-warning-borderColor);\n --numberInput-outlineColor: var(--salt-status-warning-borderColor);\n --numberInput-background-readonly: var(--salt-status-warning-background);\n}\n\n/* Style applied to input if `validationState=\"success\"` */\n.saltNumberInput-success,\n.saltNumberInput-success:hover {\n --numberInput-background: var(--salt-status-success-background);\n --numberInput-background-active: var(--salt-status-success-background);\n --numberInput-background-hover: var(--salt-status-success-background);\n --numberInput-borderColor: var(--salt-status-success-borderColor);\n --numberInput-outlineColor: var(--salt-status-success-borderColor);\n --numberInput-background-readonly: var(--salt-status-success-background);\n}\n\n/* Style applied to inner input component */\n.saltNumberInput-input {\n background: none;\n border: none;\n box-sizing: content-box;\n color: inherit;\n cursor: inherit;\n display: block;\n flex: 1;\n font: inherit;\n letter-spacing: var(--salt-text-letterSpacing);\n line-height: var(--salt-text-lineHeight);\n margin: 0;\n min-width: 0;\n padding: 0;\n text-align: var(--numberInput-textAlign);\n width: 100%;\n}\n\n.saltNumberInput-input:focus {\n outline: none;\n}\n\n/* Style applied to placeholder text */\n.saltNumberInput-input::placeholder {\n color: var(--salt-content-secondary-foreground);\n font-weight: var(--salt-text-fontWeight-small);\n}\n\n/* Styling when focused */\n.saltNumberInput-focused {\n --numberInput-borderColor: var(--numberInput-outlineColor);\n --numberInput-borderWidth: var(--salt-size-fixed-200);\n\n outline: var(--saltNumberInput-outline, var(--salt-focused-outlineWidth) var(--salt-focused-outlineStyle) var(--numberInput-outlineColor));\n}\n\n/* Style applied if `bordered={true}` */\n.saltNumberInput-bordered {\n --numberInput-border: var(--salt-size-fixed-100) var(--salt-borderStyle-solid) var(--numberInput-borderColor);\n --numberInput-borderWidth: 0;\n\n border: var(--numberInput-border);\n}\n\n/* Style applied if focused or active when `bordered={true}` */\n.saltNumberInput-bordered.saltNumberInput-focused,\n.saltNumberInput-bordered:active {\n --numberInput-borderWidth: var(--salt-size-fixed-200);\n}\n\n/* Styling when focused if `disabled={true}` or `readOnly={true}` when `bordered={true}` */\n.saltNumberInput-bordered.saltNumberInput-readOnly,\n.saltNumberInput-bordered.saltNumberInput-disabled:hover {\n --numberInput-borderWidth: 0;\n}\n\n/* Styling when focused and hovered when `bordered={true}` */\n.saltNumberInput-bordered.saltNumberInput-focused:hover {\n --numberInput-borderColor: var(--salt-editable-borderColor-active);\n}\n\n/* Style applied if `readOnly={true}` */\n.saltNumberInput-readOnly,\n.saltNumberInput-bordered.saltNumberInput-readOnly {\n --numberInput-borderColor: var(--salt-editable-borderColor-readonly);\n --numberInput-borderStyle: var(--salt-borderStyle-solid);\n --numberInput-borderWidth: var(--salt-size-fixed-100);\n\n background: var(--numberInput-background-readonly);\n cursor: var(--salt-cursor-readonly);\n}\n\n/* Styling when focused if `disabled={true}` */\n.saltNumberInput-focused.saltNumberInput-disabled {\n --numberInput-borderWidth: var(--salt-size-fixed-100);\n outline: none;\n}\n\n/* Styling when focused if `readOnly={true}` */\n.saltNumberInput-focused.saltNumberInput-readOnly {\n --numberInput-borderWidth: var(--salt-size-fixed-100);\n}\n\n.saltNumberInput:hover.saltNumberInput-readOnly {\n --numberInput-borderColor: var(--salt-editable-borderColor-readonly);\n}\n\n/* Style applied to selected input if `disabled={true}` */\n.saltNumberInput-disabled .saltNumberInput-input::selection {\n background: none;\n}\n\n/* Style applied to input if `disabled={true}` */\n.saltNumberInput-disabled,\n.saltNumberInput-disabled:hover,\n.saltNumberInput-disabled:active {\n --numberInput-borderColor: var(--salt-editable-borderColor-disabled);\n --numberInput-borderStyle: var(--salt-borderStyle-solid);\n --numberInput-borderWidth: var(--salt-size-fixed-100);\n\n background: var(--numberInput-background-disabled);\n cursor: var(--salt-cursor-disabled);\n color: var(--saltNumberInput-color-disabled, var(--salt-content-primary-foreground-disabled));\n}\n\n/* Style applied to start adornments */\n.saltNumberInput-startAdornmentContainer {\n align-items: center;\n display: inline-flex;\n padding-right: var(--salt-spacing-100);\n column-gap: var(--salt-spacing-100);\n}\n\n/* Style applied to end adornments */\n.saltNumberInput-endAdornmentContainer {\n align-items: center;\n display: inline-flex;\n padding-left: var(--salt-spacing-100);\n column-gap: var(--salt-spacing-100);\n}\n\n.saltNumberInput-startAdornmentContainer {\n margin-left: calc(var(--salt-spacing-50) * -1);\n}\n\n.saltNumberInput-startAdornmentContainer > .saltButton,\n.saltNumberInput-endAdornmentContainer > .saltButton {\n --saltButton-padding: calc(var(--salt-spacing-50) - var(--button-borderWidth));\n --saltButton-height: calc(var(--salt-size-base) - var(--salt-spacing-100));\n --saltButton-borderRadius: var(--salt-palette-corner-weaker);\n}\n\n.saltNumberInput-inputTextAlignLeft {\n --numberInput-textAlign: left;\n}\n\n.saltNumberInput-inputTextAlignCenter {\n --numberInput-textAlign: center;\n}\n\n.saltNumberInput-inputTextAlignRight {\n --numberInput-textAlign: right;\n}\n\n/* --- Buttons --- */\n\n/* Styles applied to number buttons container */\n.saltNumberInput-buttonContainer {\n --numberInput-buttonGap: var(--salt-spacing-fixed-200);\n display: flex;\n flex-direction: column;\n gap: var(--numberInput-buttonGap);\n justify-content: center;\n}\n\n.saltNumberInput-hiddenButtons .saltNumberInput-buttonContainer {\n display: none;\n}\n\n.saltNumberInput-activationIndicator {\n left: 0;\n bottom: 0;\n width: 100%;\n position: absolute;\n border-bottom: var(--salt-size-fixed-100) var(--salt-borderStyle-solid) var(--numberInput-borderColor);\n}\n\n.saltNumberInput-focused .saltNumberInput-activationIndicator {\n border-bottom: var(--salt-size-fixed-200) var(--salt-borderStyle-solid) var(--salt-editable-borderColor-active);\n}\n\n.saltNumberInput-bordered.saltNumberInput-focused .saltNumberInput-activationIndicator {\n /* Activation indicator width minus the border from the number input. */\n border-bottom-width: var(--salt-size-fixed-100);\n}\n\n.saltNumberInput-bordered .saltNumberInput-activationIndicator,\n.saltNumberInput-readOnly.saltNumberInput-focused .saltNumberInput-activationIndicator {\n border-bottom-width: 0;\n}\n\n.saltNumberInput-increment {\n --saltButton-borderRadius: var(--salt-palette-corner-weaker, 0) var(--salt-palette-corner-weaker, 0) 0 0;\n}\n\n.saltNumberInput-decrement {\n --saltButton-borderRadius: 0 0 var(--salt-palette-corner-weaker, 0) var(--salt-palette-corner-weaker, 0);\n}\n\n/* Styles applied to number buttons */\n.saltNumberInput-increment,\n.saltNumberInput-decrement {\n --saltButton-height: calc((var(--salt-size-base) - (var(--salt-spacing-50) * 2) - var(--salt-size-fixed-200)) / 2);\n --saltButton-padding: calc(var(--salt-spacing-50) - var(--button-borderWidth));\n}\n";
2
2
 
3
3
  export { css_248z as default };
4
4
  //# sourceMappingURL=NumberInput.css.js.map
@@ -3,32 +3,56 @@ import { makePrefixer, useFormFieldProps, useId, useForkRef, useIcon, useControl
3
3
  import { useComponentCssInjection } from '@salt-ds/styles';
4
4
  import { useWindow } from '@salt-ds/window';
5
5
  import { clsx } from 'clsx';
6
- import { forwardRef, useRef, useState, useEffect, useLayoutEffect } from 'react';
7
- import useCaret from './internal/useCaret.js';
8
- import { getNumberPrecision, toFloat, isOutOfRange, sanitizeInput, isEmpty, clampToRange } from './internal/utils.js';
6
+ import { forwardRef, useRef, useState, useEffect } from 'react';
7
+ import { useActivateWhileMouseDown } from './internal/useActivateWhileMouseDown.js';
9
8
  import css_248z from './NumberInput.css.js';
10
- import { useNumberInput } from './useNumberInput.js';
11
9
 
12
10
  const withBaseName = makePrefixer("saltNumberInput");
11
+ const isOutOfRange = (value, min, max) => {
12
+ if (typeof value === "string" && !value.length) {
13
+ return true;
14
+ }
15
+ const floatValue = typeof value === "string" ? Number.parseFloat(value) : value;
16
+ return Number.isNaN(floatValue) || floatValue > max || floatValue < min;
17
+ };
18
+ function getNumberPrecision(num) {
19
+ const numStr = String(num);
20
+ if (numStr.includes("e") || numStr.includes("E")) {
21
+ const [base, exponent] = numStr.split(/[eE]/);
22
+ const decimalPart = base.split(".")[1] || "";
23
+ const precision = decimalPart.length - Number.parseInt(exponent, 10);
24
+ return Math.max(0, precision);
25
+ }
26
+ if (numStr.includes(".")) {
27
+ return numStr.split(".")[1].length;
28
+ }
29
+ return 0;
30
+ }
31
+ const defaultPattern = (inputValue) => /^[+-]?(\d+(\.\d*)?|\.\d*)?$/.test(inputValue);
13
32
  const NumberInput = forwardRef(
14
33
  function NumberInput2({
15
- bordered = false,
34
+ "aria-valuetext": ariaValueTextProp,
35
+ bordered,
16
36
  className: classNameProp,
17
- clamp = false,
37
+ clamp,
38
+ decimalScale: decimalScaleProp,
18
39
  disabled,
19
40
  emptyReadOnlyMarker = "\u2014",
20
41
  endAdornment,
21
- format,
42
+ format: formatProp,
22
43
  hideButtons,
23
44
  id: idProp,
45
+ pattern = defaultPattern,
24
46
  inputProps: inputPropsProp = {},
25
47
  inputRef: inputRefProp,
26
48
  max = Number.MAX_SAFE_INTEGER,
27
49
  min = Number.MIN_SAFE_INTEGER,
28
- onChange: onChangeProp,
29
- parse,
50
+ onBlur,
51
+ onChange,
52
+ onMouseUp,
53
+ onNumberChange: onNumberChangeProp,
54
+ parse: parseProp,
30
55
  placeholder,
31
- decimalScale: decimalScaleProp,
32
56
  readOnly: readOnlyProp,
33
57
  startAdornment,
34
58
  step = 1,
@@ -37,7 +61,7 @@ const NumberInput = forwardRef(
37
61
  validationStatus: validationStatusProp,
38
62
  value: valueProp,
39
63
  variant = "primary",
40
- defaultValue: defaultValueProp = "",
64
+ defaultValue: defaultValueProp,
41
65
  ...restProps
42
66
  }, ref) {
43
67
  const targetWindow = useWindow();
@@ -59,130 +83,145 @@ const NumberInput = forwardRef(
59
83
  const isDisabled = disabled || formFieldDisabled;
60
84
  const isReadOnly = readOnlyProp || formFieldReadOnly;
61
85
  const validationStatus = formFieldValidationStatus ?? validationStatusProp;
62
- const isEmptyReadOnly = isReadOnly && !defaultValueProp && !valueProp;
63
- const defaultValue = isEmptyReadOnly ? emptyReadOnlyMarker : defaultValueProp;
64
86
  const validationStatusId = useId(idProp);
65
87
  const inputRef = useRef(null);
66
88
  const handleInputRef = useForkRef(inputRefProp, inputRef);
67
- const { IncreaseIcon, DecreaseIcon } = useIcon();
68
89
  const {
69
90
  "aria-describedby": inputDescribedBy,
70
91
  "aria-labelledby": inputLabelledBy,
71
92
  className: inputClassName,
72
93
  onBlur: inputOnBlur,
73
- onChange: inputOnChange,
74
94
  onFocus: inputOnFocus,
75
95
  required: inputRequired,
76
96
  onKeyDown: inputOnKeyDown,
77
97
  ...restInputProps
78
98
  } = inputPropsProp;
79
99
  const isRequired = formFieldRequired ? ["required", "asterisk"].includes(formFieldRequired) : inputRequired;
80
- const isAdjustingRef = useRef(false);
81
- const [isEditing, setIsEditing] = useState(false);
82
100
  const [isFocused, setIsFocused] = useState(false);
83
- const [recordCaret, restoreCaret, resetCaret] = useCaret({
84
- inputRef
85
- });
101
+ const [isEditing, setIsEditing] = useState(false);
102
+ const { DecreaseIcon, IncreaseIcon } = useIcon();
86
103
  const [value, setValue] = useControlled({
87
- controlled: valueProp,
88
- default: defaultValue,
104
+ controlled: valueProp !== void 0 ? String(valueProp) : void 0,
105
+ default: String(defaultValueProp ?? ""),
89
106
  name: "NumberInput",
90
107
  state: "value"
91
108
  });
92
109
  const decimalScale = decimalScaleProp || Math.max(getNumberPrecision(value), getNumberPrecision(step));
93
- const [displayValue, setDisplayValue] = useState(value);
94
- const clampAndFix = (value2) => {
95
- const clampedValue = clamp ? clampToRange(min, max, value2) : value2;
96
- return !format ? clampedValue.toFixed(decimalScale) : clampedValue;
110
+ const defaultFormat = (value2) => {
111
+ const sanitized = value2.trim();
112
+ if (!sanitized.length) {
113
+ return "";
114
+ }
115
+ const floatValue2 = Number.parseFloat(sanitized);
116
+ const updatedValue = Number.isNaN(floatValue2) ? sanitized : floatValue2.toFixed(decimalScale);
117
+ return String(updatedValue);
97
118
  };
98
- const {
99
- decrementButtonProps,
100
- decrementValue,
101
- incrementButtonProps,
102
- incrementValue
103
- } = useNumberInput({
104
- clampAndFix,
105
- decimalScale,
106
- disabled,
107
- format,
108
- inputRef,
109
- isAdjustingRef,
110
- max,
111
- min,
112
- onChange: onChangeProp,
113
- parse,
114
- readOnly: isReadOnly,
115
- setIsEditing,
116
- setValue,
117
- step,
118
- stepMultiplier,
119
- value
120
- });
121
- useEffect(() => {
122
- const formatValue = () => {
123
- const sanitizedValue = sanitizeInput(value);
124
- const floatValue = toFloat(sanitizedValue);
125
- if (!isAdjustingRef.current && (isEditing || isEmpty(value) || Number.isNaN(floatValue) || isReadOnly)) {
126
- return value;
127
- }
128
- if (isAdjustingRef.current) {
129
- return clampAndFix(toFloat(value));
119
+ const defaultParse = (value2) => {
120
+ const sanitizedValue = value2.trim();
121
+ if (!sanitizedValue.length) {
122
+ return null;
123
+ }
124
+ if (sanitizedValue === "." || sanitizedValue === "+" || sanitizedValue === "-") {
125
+ return 0;
126
+ }
127
+ const floatString = Number.parseFloat(value2).toFixed(decimalScale);
128
+ return Number.parseFloat(floatString);
129
+ };
130
+ const format = formatProp ?? defaultFormat;
131
+ const parse = parseProp ?? defaultParse;
132
+ const lastCommitValue = useRef(value);
133
+ const commit = (event, newNumber, newInputValue) => {
134
+ let safeNumber = newNumber;
135
+ if (safeNumber !== null && !Number.isNaN(safeNumber)) {
136
+ safeNumber = Math.max(
137
+ Number.MIN_SAFE_INTEGER,
138
+ Math.min(Number.MAX_SAFE_INTEGER, safeNumber)
139
+ );
140
+ if (clamp) {
141
+ safeNumber = Math.max(min, Math.min(max, safeNumber));
130
142
  }
131
- const clampedValue = clampAndFix(floatValue);
132
- return format ? format(clampedValue) : clampedValue;
133
- };
134
- const updatedValue = formatValue();
135
- setDisplayValue(updatedValue);
136
- }, [value, isEditing, isReadOnly, format, clamp, decimalScale, min, max]);
137
- useLayoutEffect(() => {
138
- if (isAdjustingRef.current) {
139
- resetCaret();
140
- } else {
141
- restoreCaret();
142
143
  }
143
- }, [displayValue, value]);
144
- const handleInputFocus = (event) => {
145
- setIsFocused(true);
146
- if (isReadOnly) return;
147
- const parsedValue = (parse == null ? void 0 : parse(value)) ?? value;
148
- const updatedValue = !isEmpty(parsedValue) ? clampAndFix(toFloat(parsedValue)) : parsedValue;
149
- setDisplayValue(updatedValue);
150
- inputOnFocus == null ? void 0 : inputOnFocus(event);
144
+ const commitValue = safeNumber !== null && !Number.isNaN(safeNumber) ? safeNumber.toFixed(decimalScale) : newInputValue;
145
+ if (commitValue !== value) {
146
+ setValue(commitValue);
147
+ }
148
+ if (lastCommitValue.current !== commitValue) {
149
+ onChange == null ? void 0 : onChange(event, commitValue);
150
+ onNumberChangeProp == null ? void 0 : onNumberChangeProp(event, safeNumber);
151
+ }
152
+ lastCommitValue.current = commitValue;
151
153
  };
152
- const handleInputBlur = (event) => {
154
+ const handleBlur = (event) => {
153
155
  setIsFocused(false);
154
- if (isReadOnly) return;
156
+ onBlur == null ? void 0 : onBlur(event);
157
+ };
158
+ const handleInputBlur = (event) => {
155
159
  setIsEditing(false);
156
- isAdjustingRef.current = false;
157
- resetCaret();
158
- const inputValue = event.target.value;
159
- if (isEmpty(inputValue)) {
160
+ inputOnBlur == null ? void 0 : inputOnBlur(event);
161
+ const parsedValue = parse(value);
162
+ commit(event, parsedValue, value);
163
+ };
164
+ const handleInputFocus = (event) => {
165
+ setIsEditing(false);
166
+ inputOnFocus == null ? void 0 : inputOnFocus(event);
167
+ };
168
+ const handleInputChange = (event) => {
169
+ const inputValue = event.currentTarget.value;
170
+ if (!inputValue.length) {
171
+ setValue("");
172
+ onChange == null ? void 0 : onChange(event, "");
160
173
  return;
161
174
  }
162
- const sanitizedValue = sanitizeInput(event.target.value);
163
- const floatValue = toFloat(sanitizedValue);
164
- const clampedValue = clampAndFix(floatValue);
165
- if (clampedValue.toString() !== value.toString()) {
166
- setValue(clampedValue);
167
- onChangeProp == null ? void 0 : onChangeProp(event, clampedValue);
175
+ const validValue = pattern ? pattern(inputValue) : true;
176
+ if (validValue) {
177
+ setIsEditing(true);
178
+ onChange == null ? void 0 : onChange(event, event.target.value);
179
+ setValue(inputValue);
180
+ } else {
181
+ event.preventDefault();
168
182
  }
169
- const formattedValue = format ? format(clampedValue) : clampedValue;
170
- setDisplayValue(formattedValue);
171
- inputOnBlur == null ? void 0 : inputOnBlur(event);
172
183
  };
173
- const handleInputChange = (event) => {
174
- recordCaret();
175
- const raw = sanitizeInput(event.target.value);
176
- if (raw.toString() === value.toString()) {
184
+ const decrementValue = (event, block) => {
185
+ const decrementStep = (block ? stepMultiplier : 1) * step;
186
+ let adjustedValue = parse(value) ?? 0;
187
+ if (Number.isNaN(adjustedValue)) {
177
188
  return;
178
189
  }
179
- const parsed = parse && !isEditing ? parse(raw) : raw;
180
- setValue(parsed);
181
- onChangeProp == null ? void 0 : onChangeProp(event, parsed);
190
+ adjustedValue -= decrementStep;
191
+ commit(event ?? null, adjustedValue, String(adjustedValue));
182
192
  };
193
+ let floatValue = parse(value) ?? 0;
194
+ floatValue = Math.max(
195
+ Number.MIN_SAFE_INTEGER,
196
+ Math.min(Number.MAX_SAFE_INTEGER, floatValue)
197
+ );
198
+ if (clamp) {
199
+ floatValue = Math.max(min, Math.min(max, floatValue));
200
+ }
201
+ const { activate: activateDecrement } = useActivateWhileMouseDown(
202
+ decrementValue,
203
+ floatValue <= min
204
+ );
205
+ const incrementValue = (event, block) => {
206
+ const incrementStep = (block ? stepMultiplier : 1) * step;
207
+ let adjustedValue = parse(value) ?? 0;
208
+ if (Number.isNaN(adjustedValue)) {
209
+ return;
210
+ }
211
+ adjustedValue += incrementStep;
212
+ commit(event ?? null, adjustedValue, String(adjustedValue));
213
+ };
214
+ useEffect(() => {
215
+ var _a;
216
+ if (isFocused) {
217
+ (_a = inputRef.current) == null ? void 0 : _a.focus();
218
+ }
219
+ }, [isFocused]);
220
+ const { activate: activateIncrement } = useActivateWhileMouseDown(
221
+ incrementValue,
222
+ floatValue >= max
223
+ );
183
224
  const handleInputKeyDown = (event) => {
184
- setIsEditing(true);
185
- isAdjustingRef.current = false;
186
225
  switch (event.key) {
187
226
  case "ArrowUp": {
188
227
  event.preventDefault();
@@ -198,14 +237,16 @@ const NumberInput = forwardRef(
198
237
  }
199
238
  case "Home": {
200
239
  event.preventDefault();
201
- setValue(min);
202
- onChangeProp == null ? void 0 : onChangeProp(event, min);
240
+ const newValue = String(min);
241
+ setValue(newValue);
242
+ commit(event, min, newValue);
203
243
  break;
204
244
  }
205
245
  case "End": {
206
246
  event.preventDefault();
207
- setValue(max);
208
- onChangeProp == null ? void 0 : onChangeProp(event, max);
247
+ const newValue = String(max);
248
+ setValue(newValue);
249
+ commit(event, max, newValue);
209
250
  break;
210
251
  }
211
252
  case "PageUp": {
@@ -221,9 +262,40 @@ const NumberInput = forwardRef(
221
262
  }
222
263
  inputOnKeyDown == null ? void 0 : inputOnKeyDown(event);
223
264
  };
224
- const handleBeforeInput = () => {
225
- setIsEditing(true);
265
+ const handleIncrementMouseDown = (event, disableIncrement2) => {
266
+ event.preventDefault();
267
+ if (!disableIncrement2) {
268
+ setIsEditing(false);
269
+ activateIncrement(event);
270
+ } else if (inputRef.current) {
271
+ inputRef.current.select();
272
+ }
273
+ };
274
+ const handleDecrementMouseDown = (event, disableDecrement2) => {
275
+ event.preventDefault();
276
+ if (!disableDecrement2) {
277
+ setIsEditing(false);
278
+ activateDecrement(event);
279
+ } else if (inputRef.current) {
280
+ inputRef.current.select();
281
+ }
226
282
  };
283
+ const handleContainerMouseUp = (event) => {
284
+ setIsFocused(true);
285
+ onMouseUp == null ? void 0 : onMouseUp(event);
286
+ };
287
+ let renderedValue;
288
+ if (isEditing) {
289
+ renderedValue = value;
290
+ } else if (!(value == null ? void 0 : value.length)) {
291
+ renderedValue = "";
292
+ } else {
293
+ renderedValue = format(
294
+ Number.isNaN(floatValue) ? value : String(floatValue)
295
+ );
296
+ }
297
+ const disableDecrement = disabled || floatValue - step < min;
298
+ const disableIncrement = disabled || floatValue + step > max;
227
299
  return /* @__PURE__ */ jsxs(
228
300
  "div",
229
301
  {
@@ -240,6 +312,8 @@ const NumberInput = forwardRef(
240
312
  },
241
313
  classNameProp
242
314
  ),
315
+ onBlur: handleBlur,
316
+ onMouseUp: handleContainerMouseUp,
243
317
  ...restProps,
244
318
  ref,
245
319
  children: [
@@ -247,17 +321,9 @@ const NumberInput = forwardRef(
247
321
  /* @__PURE__ */ jsx(
248
322
  "input",
249
323
  {
250
- "aria-describedby": clsx(
251
- validationStatusId,
252
- formFieldDescribedBy,
253
- inputDescribedBy
254
- ),
255
- "aria-labelledby": clsx(formFieldLabelledBy, inputLabelledBy),
256
- "aria-invalid": !isReadOnly ? isOutOfRange(value, min, max) || validationStatus === "error" : void 0,
257
- "aria-valuemax": !isReadOnly ? max : void 0,
258
- "aria-valuemin": !isReadOnly ? min : void 0,
259
- "aria-valuenow": value && !Number.isNaN(toFloat(value)) && !isReadOnly ? toFloat((parse == null ? void 0 : parse(value)) || value) : void 0,
260
- ...!isReadOnly && { "aria-valuetext": value.toString() },
324
+ "aria-describedby": clsx(formFieldDescribedBy, inputDescribedBy) || void 0,
325
+ "aria-labelledby": clsx(formFieldLabelledBy, inputLabelledBy) || void 0,
326
+ "aria-invalid": !isReadOnly && renderedValue.length ? isOutOfRange(floatValue, min, max) || validationStatus === "error" : void 0,
261
327
  className: clsx(
262
328
  withBaseName("input"),
263
329
  withBaseName(`inputTextAlign${capitalize(textAlign)}`),
@@ -267,16 +333,19 @@ const NumberInput = forwardRef(
267
333
  onBlur: handleInputBlur,
268
334
  onChange: handleInputChange,
269
335
  onFocus: handleInputFocus,
270
- onKeyDown: handleInputKeyDown,
271
- onBeforeInput: handleBeforeInput,
336
+ onKeyDown: isReadOnly ? void 0 : handleInputKeyDown,
272
337
  placeholder,
273
338
  readOnly: isReadOnly,
274
339
  "aria-readonly": isReadOnly ? "true" : void 0,
275
340
  ref: handleInputRef,
276
341
  required: isRequired,
342
+ "aria-valuemax": !isReadOnly && renderedValue.length ? max : void 0,
343
+ "aria-valuemin": !isReadOnly && renderedValue.length ? min : void 0,
344
+ "aria-valuenow": !isReadOnly ? floatValue : void 0,
345
+ "aria-valuetext": !isReadOnly ? renderedValue.length ? ariaValueTextProp ?? renderedValue : "Empty" : void 0,
277
346
  role: isReadOnly ? "textbox" : "spinbutton",
278
347
  tabIndex: isDisabled ? -1 : 0,
279
- value: displayValue,
348
+ value: isReadOnly && renderedValue.length === 0 ? emptyReadOnlyMarker : renderedValue,
280
349
  ...restInputProps
281
350
  }
282
351
  ),
@@ -287,24 +356,24 @@ const NumberInput = forwardRef(
287
356
  /* @__PURE__ */ jsx(
288
357
  Button,
289
358
  {
290
- className: clsx(
291
- withBaseName("numberButton"),
292
- withBaseName("numberButtonIncrement")
293
- ),
359
+ "aria-hidden": true,
294
360
  appearance: "transparent",
295
- ...incrementButtonProps,
361
+ tabIndex: -1,
362
+ disabled: disableIncrement,
363
+ className: withBaseName("increment"),
364
+ onMouseDown: (event) => handleIncrementMouseDown(event, disableIncrement),
296
365
  children: /* @__PURE__ */ jsx(IncreaseIcon, { "aria-hidden": true })
297
366
  }
298
367
  ),
299
368
  /* @__PURE__ */ jsx(
300
369
  Button,
301
370
  {
302
- className: clsx(
303
- withBaseName("numberButton"),
304
- withBaseName("numberButtonDecrement")
305
- ),
371
+ "aria-hidden": true,
306
372
  appearance: "transparent",
307
- ...decrementButtonProps,
373
+ tabIndex: -1,
374
+ disabled: disableDecrement,
375
+ className: withBaseName("decrement"),
376
+ onMouseDown: (event) => handleDecrementMouseDown(event, disableDecrement),
308
377
  children: /* @__PURE__ */ jsx(DecreaseIcon, { "aria-hidden": true })
309
378
  }
310
379
  )
@@ -315,5 +384,5 @@ const NumberInput = forwardRef(
315
384
  }
316
385
  );
317
386
 
318
- export { NumberInput };
387
+ export { NumberInput, isOutOfRange };
319
388
  //# sourceMappingURL=NumberInput.js.map