@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":"NumberInput.js","sources":["../src/number-input/NumberInput.tsx"],"sourcesContent":["import {\n Button,\n capitalize,\n makePrefixer,\n StatusAdornment,\n useControlled,\n useForkRef,\n useFormFieldProps,\n useIcon,\n useId,\n type ValidationStatus,\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 forwardRef,\n type InputHTMLAttributes,\n type KeyboardEvent,\n type ReactNode,\n type Ref,\n type SyntheticEvent,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\nimport useCaret from \"./internal/useCaret\";\nimport {\n clampToRange,\n getNumberPrecision,\n isEmpty,\n isOutOfRange,\n sanitizeInput,\n toFloat,\n} from \"./internal/utils\";\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 * 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":["NumberInput","numberInputCss","value"],"mappings":"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"}
1
+ {"version":3,"file":"NumberInput.js","sources":["../src/number-input/NumberInput.tsx"],"sourcesContent":["import {\n Button,\n capitalize,\n makePrefixer,\n StatusAdornment,\n useControlled,\n useForkRef,\n useFormFieldProps,\n useIcon,\n useId,\n type ValidationStatus,\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 forwardRef,\n type InputHTMLAttributes,\n type KeyboardEvent,\n type MouseEventHandler,\n type ReactNode,\n type Ref,\n type SyntheticEvent,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { useActivateWhileMouseDown } from \"./internal/useActivateWhileMouseDown\";\nimport numberInputCss from \"./NumberInput.css\";\n\nconst withBaseName = makePrefixer(\"saltNumberInput\");\n\nexport interface NumberInputProps\n extends Omit<\n ComponentPropsWithoutRef<\"div\">,\n \"onChange\" | \"defaultValue\" | \"value\"\n > {\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 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 * 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 * @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 * value : string\n */\n format?: (value: string) => string;\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 * Callback that matches on values as you type and determines whether the value can be entered.\n */\n pattern?: (inputValue: string) => boolean;\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 changes via user input or increment/decrement.\n * Use `onNumberChange` if you want stable number, after blur or through increment/decrement\n *\n * @param event - The event that triggers the value change, can be null if called by long-press of increment/decrement\n * @param value - value as string\n */\n onChange?: (event: SyntheticEvent | null, value: string) => void;\n /**\n * Callback function that is triggered when the value changes via increment/decrement or on blur.\n *\n * @param event - The event that triggers the change, can be null if called by long-press of increment/decrement\n * @param value - The committed, parsed number value or null if an empty value\n */\n onNumberChange?: (event: SyntheticEvent | null, value: number | null) => void;\n /**\n *\n * A callback to parse the value of the `NumberInput`. To be used alongside the `format` callback.\n * Return null if you want the NumberInput to be empty.\n */\n parse?: (value: string) => number | null;\n /**\n * A string displayed in a dimmed color when the `NumberInput` value is empty.\n */\n placeholder?: string;\n /**\n * A boolean property that controls the read-only state 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 isOutOfRange = (\n value: number | string,\n min: number,\n max: number,\n) => {\n if (typeof value === \"string\" && !value.length) {\n return true;\n }\n const floatValue =\n typeof value === \"string\" ? Number.parseFloat(value) : value;\n return Number.isNaN(floatValue) || floatValue > max || floatValue < min;\n};\n\nfunction getNumberPrecision(num: number | string) {\n const numStr = String(num);\n\n if (numStr.includes(\"e\") || numStr.includes(\"E\")) {\n const [base, exponent] = numStr.split(/[eE]/);\n const decimalPart = base.split(\".\")[1] || \"\";\n const precision = decimalPart.length - Number.parseInt(exponent, 10);\n return Math.max(0, precision);\n }\n\n if (numStr.includes(\".\")) {\n return numStr.split(\".\")[1].length;\n }\n\n return 0;\n}\n\nconst defaultPattern: NumberInputProps[\"pattern\"] = (inputValue) =>\n /^[+-]?(\\d+(\\.\\d*)?|\\.\\d*)?$/.test(inputValue);\n\nexport const NumberInput = forwardRef<HTMLDivElement, NumberInputProps>(\n function NumberInput(\n {\n \"aria-valuetext\": ariaValueTextProp,\n bordered,\n className: classNameProp,\n clamp,\n decimalScale: decimalScaleProp,\n disabled,\n emptyReadOnlyMarker = \"—\",\n endAdornment,\n format: formatProp,\n hideButtons,\n id: idProp,\n pattern = defaultPattern,\n inputProps: inputPropsProp = {},\n inputRef: inputRefProp,\n max = Number.MAX_SAFE_INTEGER,\n min = Number.MIN_SAFE_INTEGER,\n onBlur,\n onChange,\n onMouseUp,\n onNumberChange: onNumberChangeProp,\n parse: parseProp,\n placeholder,\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 validationStatusId = useId(idProp);\n const inputRef = useRef<HTMLInputElement>(null);\n const handleInputRef = useForkRef(inputRefProp, inputRef);\n\n const {\n \"aria-describedby\": inputDescribedBy,\n \"aria-labelledby\": inputLabelledBy,\n className: inputClassName,\n onBlur: inputOnBlur,\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 [isFocused, setIsFocused] = useState(false);\n const [isEditing, setIsEditing] = useState(false);\n const { DecreaseIcon, IncreaseIcon } = useIcon();\n\n const [value, setValue] = useControlled({\n controlled: valueProp !== undefined ? String(valueProp) : undefined,\n default: String(defaultValueProp ?? \"\"),\n name: \"NumberInput\",\n state: \"value\",\n });\n\n const decimalScale =\n decimalScaleProp ||\n Math.max(getNumberPrecision(value), getNumberPrecision(step));\n\n const defaultFormat = (value: string): string => {\n const sanitized = value.trim();\n if (!sanitized.length) {\n return \"\";\n }\n const floatValue = Number.parseFloat(sanitized);\n const updatedValue = Number.isNaN(floatValue)\n ? sanitized\n : floatValue.toFixed(decimalScale);\n return String(updatedValue);\n };\n\n const defaultParse = (value: string) => {\n const sanitizedValue = value.trim();\n if (!sanitizedValue.length) {\n return null;\n }\n if (\n sanitizedValue === \".\" ||\n sanitizedValue === \"+\" ||\n sanitizedValue === \"-\"\n ) {\n return 0;\n }\n const floatString = Number.parseFloat(value).toFixed(decimalScale);\n return Number.parseFloat(floatString);\n };\n\n const format = formatProp ?? defaultFormat;\n const parse = parseProp ?? defaultParse;\n\n // Committed values are complete numbers, created through blur or increment/decrement, not partial entries such as \"0.\" created by input/onChange.\n const lastCommitValue = useRef<string>(value);\n const commit = (\n event: SyntheticEvent | null,\n newNumber: number | null,\n newInputValue: string,\n ) => {\n let safeNumber = newNumber;\n if (safeNumber !== null && !Number.isNaN(safeNumber)) {\n safeNumber = Math.max(\n Number.MIN_SAFE_INTEGER,\n Math.min(Number.MAX_SAFE_INTEGER, safeNumber),\n );\n if (clamp) {\n safeNumber = Math.max(min, Math.min(max, safeNumber));\n }\n }\n const commitValue =\n safeNumber !== null && !Number.isNaN(safeNumber)\n ? safeNumber.toFixed(decimalScale)\n : newInputValue;\n\n if (commitValue !== value) {\n setValue(commitValue);\n }\n\n if (lastCommitValue.current !== commitValue) {\n onChange?.(event, commitValue);\n onNumberChangeProp?.(event, safeNumber);\n }\n lastCommitValue.current = commitValue;\n };\n\n const handleBlur = (event: FocusEvent<HTMLInputElement>) => {\n setIsFocused(false);\n onBlur?.(event);\n };\n\n const handleInputBlur = (event: FocusEvent<HTMLInputElement>) => {\n setIsEditing(false);\n inputOnBlur?.(event);\n const parsedValue = parse(value);\n commit(event, parsedValue, value);\n };\n\n const handleInputFocus = (event: FocusEvent<HTMLInputElement>) => {\n setIsEditing(false);\n inputOnFocus?.(event);\n };\n\n const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {\n const inputValue = event.currentTarget.value;\n\n if (!inputValue.length) {\n setValue(\"\");\n onChange?.(event, \"\");\n return;\n }\n const validValue = pattern ? pattern(inputValue) : true;\n\n if (validValue) {\n setIsEditing(true);\n onChange?.(event, event.target.value);\n setValue(inputValue);\n } else {\n event.preventDefault();\n }\n };\n\n const decrementValue = (event?: SyntheticEvent, block?: boolean) => {\n const decrementStep = (block ? stepMultiplier : 1) * step;\n let adjustedValue = parse(value) ?? 0;\n if (Number.isNaN(adjustedValue)) {\n return;\n }\n adjustedValue -= decrementStep;\n commit(event ?? null, adjustedValue, String(adjustedValue));\n };\n\n let floatValue = parse(value) ?? 0;\n floatValue = Math.max(\n Number.MIN_SAFE_INTEGER,\n Math.min(Number.MAX_SAFE_INTEGER, floatValue),\n );\n if (clamp) {\n floatValue = Math.max(min, Math.min(max, floatValue));\n }\n\n const { activate: activateDecrement } = useActivateWhileMouseDown(\n decrementValue,\n floatValue <= min,\n );\n\n const incrementValue = (event?: SyntheticEvent, block?: boolean) => {\n const incrementStep = (block ? stepMultiplier : 1) * step;\n let adjustedValue = parse(value) ?? 0;\n if (Number.isNaN(adjustedValue)) {\n return;\n }\n adjustedValue += incrementStep;\n commit(event ?? null, adjustedValue, String(adjustedValue));\n };\n\n useEffect(() => {\n if (isFocused) {\n inputRef.current?.focus();\n }\n }, [isFocused]);\n\n const { activate: activateIncrement } = useActivateWhileMouseDown(\n incrementValue,\n floatValue >= max,\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 const newValue = String(min);\n setValue(newValue);\n commit(event, min, newValue);\n break;\n }\n case \"End\": {\n event.preventDefault();\n const newValue = String(max);\n setValue(newValue);\n commit(event, max, newValue);\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 handleIncrementMouseDown = (\n event: SyntheticEvent,\n disableIncrement: boolean,\n ) => {\n event.preventDefault();\n if (!disableIncrement) {\n setIsEditing(false);\n activateIncrement(event);\n } else if (inputRef.current) {\n inputRef.current.select();\n }\n };\n\n const handleDecrementMouseDown = (\n event: SyntheticEvent,\n disableDecrement: boolean,\n ) => {\n event.preventDefault();\n if (!disableDecrement) {\n setIsEditing(false);\n activateDecrement(event);\n } else if (inputRef.current) {\n inputRef.current.select();\n }\n };\n\n const handleContainerMouseUp: MouseEventHandler<HTMLDivElement> = (\n event,\n ) => {\n setIsFocused(true);\n onMouseUp?.(event);\n };\n\n let renderedValue: string;\n if (isEditing) {\n renderedValue = value;\n } else if (!value?.length) {\n renderedValue = \"\";\n } else {\n renderedValue = format(\n Number.isNaN(floatValue) ? value : String(floatValue),\n );\n }\n\n const disableDecrement = disabled || floatValue - step < min;\n const disableIncrement = disabled || floatValue + step > max;\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 onBlur={handleBlur}\n onMouseUp={handleContainerMouseUp}\n {...restProps}\n ref={ref}\n >\n {startAdornment && (\n <div className={withBaseName(\"startAdornmentContainer\")}>\n {startAdornment}\n </div>\n )}\n <input\n aria-describedby={\n clsx(formFieldDescribedBy, inputDescribedBy) || undefined\n }\n aria-labelledby={\n clsx(formFieldLabelledBy, inputLabelledBy) || undefined\n }\n aria-invalid={\n !isReadOnly && renderedValue.length\n ? isOutOfRange(floatValue, min, max) ||\n validationStatus === \"error\"\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={handleInputFocus}\n onKeyDown={isReadOnly ? undefined : handleInputKeyDown}\n placeholder={placeholder}\n readOnly={isReadOnly}\n aria-readonly={isReadOnly ? \"true\" : undefined}\n ref={handleInputRef}\n required={isRequired}\n aria-valuemax={!isReadOnly && renderedValue.length ? max : undefined}\n aria-valuemin={!isReadOnly && renderedValue.length ? min : undefined}\n aria-valuenow={!isReadOnly ? floatValue : undefined}\n aria-valuetext={\n !isReadOnly\n ? renderedValue.length\n ? (ariaValueTextProp ?? renderedValue)\n : \"Empty\"\n : undefined\n }\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={\n isReadOnly && renderedValue.length === 0\n ? emptyReadOnlyMarker\n : renderedValue\n }\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 aria-hidden={true}\n appearance=\"transparent\"\n tabIndex={-1}\n disabled={disableIncrement}\n className={withBaseName(\"increment\")}\n onMouseDown={(event) =>\n handleIncrementMouseDown(event, disableIncrement)\n }\n >\n <IncreaseIcon aria-hidden />\n </Button>\n <Button\n aria-hidden={true}\n appearance=\"transparent\"\n tabIndex={-1}\n disabled={disableDecrement}\n className={withBaseName(\"decrement\")}\n onMouseDown={(event) =>\n handleDecrementMouseDown(event, disableDecrement)\n }\n >\n <DecreaseIcon aria-hidden />\n </Button>\n </div>\n )}\n </div>\n );\n },\n);\n"],"names":["NumberInput","numberInputCss","value","floatValue","disableIncrement","disableDecrement"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- var css_248z = ".saltTabNextTrigger {\n all: unset;\n display: flex;\n gap: var(--salt-spacing-100);\n align-items: center;\n justify-content: center;\n flex: 1;\n overflow: hidden;\n}\n\n/* The action should be triggered by clicking anywhere on the tab. */\n.saltTabNextTrigger::before {\n content: \"\";\n position: absolute;\n width: 100%;\n height: 100%;\n left: 0;\n top: 0;\n}\n";
1
+ var css_248z = ".saltTabNextTrigger {\n all: unset;\n display: flex;\n gap: var(--salt-spacing-100);\n align-items: center;\n justify-content: center;\n flex: 1;\n overflow: hidden;\n}\n\n/* The action should be triggered by clicking anywhere on the tab. */\n.saltTabNextTrigger::before {\n content: \"\";\n position: absolute;\n width: 100%;\n height: 100%;\n left: 0;\n top: 0;\n}\n\n.saltTabNextTrigger:focus-visible {\n outline: none;\n}\n";
2
2
 
3
3
  export { css_248z as default };
4
4
  //# sourceMappingURL=TabNextTrigger.css.js.map
@@ -1,6 +1,6 @@
1
1
  import { type ValidationStatus } from "@salt-ds/core";
2
2
  import { type ComponentPropsWithoutRef, type InputHTMLAttributes, type ReactNode, type Ref, type SyntheticEvent } from "react";
3
- export interface NumberInputProps extends Omit<ComponentPropsWithoutRef<"div">, "onChange"> {
3
+ export interface NumberInputProps extends Omit<ComponentPropsWithoutRef<"div">, "onChange" | "defaultValue" | "value"> {
4
4
  /**
5
5
  * Styling variant with full border.
6
6
  * @default false
@@ -11,6 +11,10 @@ export interface NumberInputProps extends Omit<ComponentPropsWithoutRef<"div">,
11
11
  * @default false
12
12
  */
13
13
  clamp?: boolean;
14
+ /**
15
+ * The number of decimal places allowed. Defaults to the decimal scale of either the initial value provided or the step, whichever is greater.
16
+ */
17
+ decimalScale?: number;
14
18
  /**
15
19
  * The default value. Use when the component is uncontrolled.
16
20
  */
@@ -22,7 +26,6 @@ export interface NumberInputProps extends Omit<ComponentPropsWithoutRef<"div">,
22
26
  disabled?: boolean;
23
27
  /**
24
28
  * The marker to use in an empty read only Input.
25
- * Use `''` to disable this feature.
26
29
  * @default "—"
27
30
  */
28
31
  emptyReadOnlyMarker?: string;
@@ -32,8 +35,9 @@ export interface NumberInputProps extends Omit<ComponentPropsWithoutRef<"div">,
32
35
  endAdornment?: ReactNode;
33
36
  /**
34
37
  * A callback to format the value of the `NumberInput`.
38
+ * value : string
35
39
  */
36
- format?: (value: number | string) => string | number;
40
+ format?: (value: string) => string;
37
41
  /**
38
42
  * Hide the number buttons.
39
43
  * @default false
@@ -47,6 +51,10 @@ export interface NumberInputProps extends Omit<ComponentPropsWithoutRef<"div">,
47
51
  * Optional ref for the input component.
48
52
  */
49
53
  inputRef?: Ref<HTMLInputElement>;
54
+ /**
55
+ * Callback that matches on values as you type and determines whether the value can be entered.
56
+ */
57
+ pattern?: (inputValue: string) => boolean;
50
58
  /**
51
59
  * The maximum value that can be selected.
52
60
  * @default Number.MAX_SAFE_INTEGER
@@ -58,28 +66,32 @@ export interface NumberInputProps extends Omit<ComponentPropsWithoutRef<"div">,
58
66
  */
59
67
  min?: number;
60
68
  /**
61
- * Callback function that is triggered when the value of the `NumberInput` changes.
69
+ * Callback function that is triggered when the value changes via user input or increment/decrement.
70
+ * Use `onNumberChange` if you want stable number, after blur or through increment/decrement
62
71
  *
63
- * @param event - The event that triggers the value change. This may be `undefined` during a long press on the increment or decrement buttons.
64
- * @param value - The new value of the `NumberInput`, which can be a number or a string.
72
+ * @param event - The event that triggers the value change, can be null if called by long-press of increment/decrement
73
+ * @param value - value as string
65
74
  */
66
- onChange?: (event: SyntheticEvent | undefined, value: number | string) => void;
75
+ onChange?: (event: SyntheticEvent | null, value: string) => void;
67
76
  /**
77
+ * Callback function that is triggered when the value changes via increment/decrement or on blur.
68
78
  *
69
- * A callback to parse the value of the `NumberInput`. To be used alongside
70
- * the `format` callback.
79
+ * @param event - The event that triggers the change, can be null if called by long-press of increment/decrement
80
+ * @param value - The committed, parsed number value or null if an empty value
71
81
  */
72
- parse?: (value: number | string) => string | number;
82
+ onNumberChange?: (event: SyntheticEvent | null, value: number | null) => void;
73
83
  /**
74
- * A string displayed in a dimmed color when the `NumberInput` value is empty.
84
+ *
85
+ * A callback to parse the value of the `NumberInput`. To be used alongside the `format` callback.
86
+ * Return null if you want the NumberInput to be empty.
75
87
  */
76
- placeholder?: string;
88
+ parse?: (value: string) => number | null;
77
89
  /**
78
- * The number of decimal places allowed. Defaults to the decimal scale of either the initial value provided or the step, whichever is greater.
90
+ * A string displayed in a dimmed color when the `NumberInput` value is empty.
79
91
  */
80
- decimalScale?: number;
92
+ placeholder?: string;
81
93
  /**
82
- * A boolean property that controls the editability of the `NumberInput`.
94
+ * A boolean property that controls the read-only state of the `NumberInput`.
83
95
  * - When set to `true`, the `NumberInput` becomes read-only, preventing user edits.
84
96
  * - When set to `false` or omitted, the `NumberInput` is editable by the user.
85
97
  */
@@ -119,4 +131,5 @@ export interface NumberInputProps extends Omit<ComponentPropsWithoutRef<"div">,
119
131
  */
120
132
  value?: number | string;
121
133
  }
134
+ export declare const isOutOfRange: (value: number | string, min: number, max: number) => boolean;
122
135
  export declare const NumberInput: import("react").ForwardRefExoticComponent<NumberInputProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -1,2 +1 @@
1
1
  export * from "./NumberInput";
2
- export * from "./useNumberInput";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salt-ds/lab",
3
- "version": "1.0.0-alpha.77",
3
+ "version": "1.0.0-alpha.79",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -21,9 +21,9 @@
21
21
  ],
22
22
  "dependencies": {
23
23
  "@floating-ui/react": "^0.26.28",
24
- "@salt-ds/core": "^1.49.0",
25
- "@salt-ds/date-adapters": "0.1.0-alpha.5",
26
- "@salt-ds/icons": "^1.14.0",
24
+ "@salt-ds/core": "^1.51.0",
25
+ "@salt-ds/date-adapters": "0.1.0-alpha.6",
26
+ "@salt-ds/icons": "^1.15.0",
27
27
  "@salt-ds/styles": "0.2.1",
28
28
  "@salt-ds/window": "0.1.1",
29
29
  "@types/react-window": "^1.8.2",
@@ -1,34 +0,0 @@
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
@@ -1 +0,0 @@
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,CAAA,KAEM;AACJ,EAAA,MAAM,gBAAA,GAAmBA,aAGf,IAAI,CAAA;AAGd,EAAA,MAAM,WAAA,GAAcC,kBAAY,MAAM;AACpC,IAAA,IAAI,SAAS,OAAA,EAAS;AACpB,MAAA,MAAM,EAAE,cAAA,EAAgB,KAAA,EAAO,YAAA,EAAc,GAAA,KAAQ,QAAA,CAAS,OAAA;AAC9D,MAAA,gBAAA,CAAiB,OAAA,GAAU;AAAA,QACzB,KAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAGL,EAAA,MAAM,YAAA,GAAeA,kBAAY,MAAM;AACrC,IAAA,IAAI,QAAA,CAAS,OAAA,IAAW,gBAAA,CAAiB,OAAA,EAAS;AAChD,MAAA,MAAM,EAAE,KAAA,EAAO,GAAA,EAAI,GAAI,gBAAA,CAAiB,OAAA;AACxC,MAAA,QAAA,CAAS,OAAA,CAAQ,iBAAA,CAAkB,KAAA,EAAO,GAAG,CAAA;AAAA,IAC/C;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAGL,EAAA,MAAM,UAAA,GAAaA,kBAAY,MAAM;AACnC,IAAA,IAAI,SAAS,OAAA,EAAS;AACpB,MAAA,MAAM,SAAA,GAAY,QAAA,CAAS,OAAA,CAAQ,KAAA,CAAM,MAAA;AACzC,MAAA,gBAAA,CAAiB,OAAA,GAAU,EAAE,KAAA,EAAO,SAAA,EAAW,KAAK,SAAA,EAAU;AAAA,IAChE;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,OAAO,CAAC,WAAA,EAAa,YAAA,EAAc,UAAU,CAAA;AAC/C;;;;"}
@@ -1,78 +0,0 @@
1
- 'use strict';
2
-
3
- const isAllowedNonNumeric = (inputCharacter) => {
4
- if (typeof inputCharacter === "number") return;
5
- return "-+".includes(inputCharacter) && inputCharacter.length === 1 || inputCharacter === "";
6
- };
7
- const toFloat = (inputValue) => {
8
- if (isAllowedNonNumeric(inputValue)) return 0;
9
- return Number.parseFloat(inputValue.toString());
10
- };
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
- );
24
- };
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;
39
- };
40
- const isOutOfRange = (value, min, max) => {
41
- if (value === void 0) return true;
42
- const floatValue = toFloat(value);
43
- return floatValue > max || floatValue < min;
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
- };
69
-
70
- exports.clampToRange = clampToRange;
71
- exports.getNumberPrecision = getNumberPrecision;
72
- exports.isAllowedNonNumeric = isAllowedNonNumeric;
73
- exports.isEmpty = isEmpty;
74
- exports.isOutOfRange = isOutOfRange;
75
- exports.isValidNumber = isValidNumber;
76
- exports.sanitizeInput = sanitizeInput;
77
- exports.toFloat = toFloat;
78
- //# sourceMappingURL=utils.js.map
@@ -1 +0,0 @@
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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"}
@@ -1,107 +0,0 @@
1
- 'use strict';
2
-
3
- var react = require('react');
4
- var useActivateWhileMouseDown = require('./internal/useActivateWhileMouseDown.js');
5
- var utils = require('./internal/utils.js');
6
-
7
- const useNumberInput = ({
8
- clampAndFix,
9
- decimalScale,
10
- disabled,
11
- format,
12
- inputRef,
13
- isAdjustingRef,
14
- max = Number.MAX_SAFE_INTEGER,
15
- min = Number.MIN_SAFE_INTEGER,
16
- onChange,
17
- parse,
18
- readOnly,
19
- setIsEditing,
20
- setValue,
21
- step = 1,
22
- stepMultiplier = 2,
23
- value
24
- }) => {
25
- const updateValue = react.useCallback(
26
- (event, nextValue) => {
27
- if (readOnly) return;
28
- isAdjustingRef.current = true;
29
- const updatedValue = clampAndFix(nextValue);
30
- setValue(utils.toFloat(updatedValue));
31
- onChange == null ? void 0 : onChange(event, utils.toFloat(updatedValue));
32
- },
33
- [onChange, readOnly, setValue, decimalScale, format]
34
- );
35
- const decrementValue = react.useCallback(
36
- (event, block) => {
37
- const decrementStep = block ? stepMultiplier * step : step;
38
- const parsedValue = (parse == null ? void 0 : parse(value)) || value;
39
- const nextValue = utils.toFloat(parsedValue) - decrementStep;
40
- if (nextValue < min) return;
41
- updateValue(event, nextValue);
42
- },
43
- [value, min, step, stepMultiplier, updateValue, parse]
44
- );
45
- const incrementValue = react.useCallback(
46
- (event, block) => {
47
- const incrementStep = block ? stepMultiplier * step : step;
48
- const parsedValue = (parse == null ? void 0 : parse(value)) || value;
49
- const nextValue = utils.toFloat(parsedValue) + incrementStep;
50
- if (nextValue > max) return;
51
- updateValue(event, nextValue);
52
- },
53
- [value, max, step, stepMultiplier, updateValue, parse]
54
- );
55
- const { activate: decrementSpinner } = useActivateWhileMouseDown.useActivateWhileMouseDown(
56
- (event) => decrementValue(event),
57
- utils.toFloat(value) <= min
58
- );
59
- const { activate: incrementSpinner } = useActivateWhileMouseDown.useActivateWhileMouseDown(
60
- (event) => incrementValue(event),
61
- utils.toFloat(value) >= max
62
- );
63
- const handleButtonMouseUp = () => {
64
- var _a;
65
- return (_a = inputRef.current) == null ? void 0 : _a.focus();
66
- };
67
- const commonButtonProps = {
68
- "aria-hidden": true,
69
- tabIndex: -1,
70
- onMouseUp: handleButtonMouseUp
71
- };
72
- const incrementButtonProps = {
73
- ...commonButtonProps,
74
- "aria-label": "increment value",
75
- disabled: disabled || utils.toFloat(value) + step > max,
76
- onMouseDown: (event) => {
77
- event.preventDefault();
78
- setIsEditing(true);
79
- if (event.nativeEvent.button !== 0) {
80
- return;
81
- }
82
- incrementSpinner(event);
83
- }
84
- };
85
- const decrementButtonProps = {
86
- ...commonButtonProps,
87
- "aria-label": "decrement value",
88
- disabled: disabled || utils.toFloat(value) - step < min,
89
- onMouseDown: (event) => {
90
- event.preventDefault();
91
- setIsEditing(true);
92
- if (event.nativeEvent.button !== 0) {
93
- return;
94
- }
95
- decrementSpinner(event);
96
- }
97
- };
98
- return {
99
- incrementButtonProps,
100
- decrementButtonProps,
101
- incrementValue,
102
- decrementValue
103
- };
104
- };
105
-
106
- exports.useNumberInput = useNumberInput;
107
- //# sourceMappingURL=useNumberInput.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useNumberInput.js","sources":["../src/number-input/useNumberInput.ts"],"sourcesContent":["import {\n type Dispatch,\n type MouseEvent,\n type MutableRefObject,\n type SetStateAction,\n type SyntheticEvent,\n useCallback,\n} from \"react\";\nimport { useActivateWhileMouseDown } from \"./internal/useActivateWhileMouseDown\";\nimport { toFloat } from \"./internal/utils\";\nimport type { NumberInputProps } from \"./NumberInput\";\n\nexport interface UseNumberInputProps\n extends Pick<\n NumberInputProps,\n | \"decimalScale\"\n | \"disabled\"\n | \"format\"\n | \"inputRef\"\n | \"max\"\n | \"min\"\n | \"onChange\"\n | \"parse\"\n | \"readOnly\"\n | \"step\"\n | \"stepMultiplier\"\n > {\n clampAndFix: (value: number) => string | number;\n inputRef: MutableRefObject<HTMLInputElement | null>;\n isAdjustingRef: MutableRefObject<boolean>;\n setIsEditing: Dispatch<SetStateAction<boolean>>;\n setValue: Dispatch<SetStateAction<string | number>>;\n value: string | number;\n}\n\n/**\n * Manages increment / decrement logic\n */\nexport const useNumberInput = ({\n clampAndFix,\n decimalScale,\n disabled,\n format,\n inputRef,\n isAdjustingRef,\n max = Number.MAX_SAFE_INTEGER,\n min = Number.MIN_SAFE_INTEGER,\n onChange,\n parse,\n readOnly,\n setIsEditing,\n setValue,\n step = 1,\n stepMultiplier = 2,\n value,\n}: UseNumberInputProps) => {\n // biome-ignore lint/correctness/useExhaustiveDependencies: Refs cannot be added to dependency arrays\n const updateValue = useCallback(\n (event: SyntheticEvent | undefined, nextValue: number) => {\n if (readOnly) return;\n isAdjustingRef.current = true;\n\n const updatedValue = clampAndFix(nextValue);\n setValue(toFloat(updatedValue));\n onChange?.(event, toFloat(updatedValue));\n },\n [onChange, readOnly, setValue, decimalScale, format],\n );\n\n const decrementValue = useCallback(\n (event?: SyntheticEvent, block?: boolean) => {\n const decrementStep = block ? stepMultiplier * step : step;\n const parsedValue = parse?.(value) || value;\n const nextValue = toFloat(parsedValue) - decrementStep;\n if (nextValue < min) return;\n updateValue(event, nextValue);\n },\n [value, min, step, stepMultiplier, updateValue, parse],\n );\n\n const incrementValue = useCallback(\n (event?: SyntheticEvent, block?: boolean) => {\n const incrementStep = block ? stepMultiplier * step : step;\n const parsedValue = parse?.(value) || value;\n const nextValue = toFloat(parsedValue) + incrementStep;\n if (nextValue > max) return;\n updateValue(event, nextValue);\n },\n [value, max, step, stepMultiplier, updateValue, parse],\n );\n\n const { activate: decrementSpinner } = useActivateWhileMouseDown(\n (event?: SyntheticEvent) => decrementValue(event),\n toFloat(value) <= min,\n );\n\n const { activate: incrementSpinner } = useActivateWhileMouseDown(\n (event?: SyntheticEvent) => incrementValue(event),\n toFloat(value) >= max,\n );\n\n const handleButtonMouseUp = () => inputRef.current?.focus();\n\n const commonButtonProps = {\n \"aria-hidden\": true,\n tabIndex: -1,\n onMouseUp: handleButtonMouseUp,\n };\n\n const incrementButtonProps = {\n ...commonButtonProps,\n \"aria-label\": \"increment value\",\n disabled: disabled || toFloat(value) + step > max,\n onMouseDown: (event: MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n setIsEditing(true);\n if (event.nativeEvent.button !== 0) {\n // To match closely with <input type='input'>\n return;\n }\n incrementSpinner(event);\n },\n };\n\n const decrementButtonProps = {\n ...commonButtonProps,\n \"aria-label\": \"decrement value\",\n disabled: disabled || toFloat(value) - step < min,\n onMouseDown: (event: MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n setIsEditing(true);\n if (event.nativeEvent.button !== 0) {\n // To match closely with <input type='input'>\n return;\n }\n decrementSpinner(event);\n },\n };\n\n return {\n incrementButtonProps,\n decrementButtonProps,\n incrementValue,\n decrementValue,\n };\n};\n"],"names":["useCallback","toFloat","useActivateWhileMouseDown"],"mappings":"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"}
@@ -1,32 +0,0 @@
1
- import { useRef, useCallback } from 'react';
2
-
3
- const useCaret = ({
4
- inputRef
5
- }) => {
6
- const caretPositionRef = useRef(null);
7
- const recordCaret = useCallback(() => {
8
- if (inputRef.current) {
9
- const { selectionStart: start, selectionEnd: end } = inputRef.current;
10
- caretPositionRef.current = {
11
- start,
12
- end
13
- };
14
- }
15
- }, []);
16
- const restoreCaret = useCallback(() => {
17
- if (inputRef.current && caretPositionRef.current) {
18
- const { start, end } = caretPositionRef.current;
19
- inputRef.current.setSelectionRange(start, end);
20
- }
21
- }, []);
22
- const resetCaret = useCallback(() => {
23
- if (inputRef.current) {
24
- const txtLength = inputRef.current.value.length;
25
- caretPositionRef.current = { start: txtLength, end: txtLength };
26
- }
27
- }, []);
28
- return [recordCaret, restoreCaret, resetCaret];
29
- };
30
-
31
- export { useCaret as default };
32
- //# sourceMappingURL=useCaret.js.map
@@ -1 +0,0 @@
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":[],"mappings":";;AAEA,MAAM,WAAW,CAAC;AAAA,EAChB;AACF,CAAA,KAEM;AACJ,EAAA,MAAM,gBAAA,GAAmB,OAGf,IAAI,CAAA;AAGd,EAAA,MAAM,WAAA,GAAc,YAAY,MAAM;AACpC,IAAA,IAAI,SAAS,OAAA,EAAS;AACpB,MAAA,MAAM,EAAE,cAAA,EAAgB,KAAA,EAAO,YAAA,EAAc,GAAA,KAAQ,QAAA,CAAS,OAAA;AAC9D,MAAA,gBAAA,CAAiB,OAAA,GAAU;AAAA,QACzB,KAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAGL,EAAA,MAAM,YAAA,GAAe,YAAY,MAAM;AACrC,IAAA,IAAI,QAAA,CAAS,OAAA,IAAW,gBAAA,CAAiB,OAAA,EAAS;AAChD,MAAA,MAAM,EAAE,KAAA,EAAO,GAAA,EAAI,GAAI,gBAAA,CAAiB,OAAA;AACxC,MAAA,QAAA,CAAS,OAAA,CAAQ,iBAAA,CAAkB,KAAA,EAAO,GAAG,CAAA;AAAA,IAC/C;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAGL,EAAA,MAAM,UAAA,GAAa,YAAY,MAAM;AACnC,IAAA,IAAI,SAAS,OAAA,EAAS;AACpB,MAAA,MAAM,SAAA,GAAY,QAAA,CAAS,OAAA,CAAQ,KAAA,CAAM,MAAA;AACzC,MAAA,gBAAA,CAAiB,OAAA,GAAU,EAAE,KAAA,EAAO,SAAA,EAAW,KAAK,SAAA,EAAU;AAAA,IAChE;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,OAAO,CAAC,WAAA,EAAa,YAAA,EAAc,UAAU,CAAA;AAC/C;;;;"}