UNPKG

@mantine/core

Version:

React components library focused on usability, accessibility and developer experience

276 lines (272 loc) 9.1 kB
'use client'; 'use strict'; var React = require('react'); var cx = require('clsx'); var reactNumberFormat = require('react-number-format'); var hooks = require('@mantine/hooks'); var getSize = require('../../core/utils/get-size/get-size.cjs'); var createVarsResolver = require('../../core/styles-api/create-vars-resolver/create-vars-resolver.cjs'); var useResolvedStylesApi = require('../../core/styles-api/use-resolved-styles-api/use-resolved-styles-api.cjs'); var useStyles = require('../../core/styles-api/use-styles/use-styles.cjs'); require('../../core/MantineProvider/Mantine.context.cjs'); require('../../core/MantineProvider/default-theme.cjs'); require('../../core/MantineProvider/MantineProvider.cjs'); require('../../core/MantineProvider/MantineThemeProvider/MantineThemeProvider.cjs'); var useProps = require('../../core/MantineProvider/use-props/use-props.cjs'); require('../../core/Box/Box.cjs'); var factory = require('../../core/factory/factory.cjs'); require('../../core/DirectionProvider/DirectionProvider.cjs'); var InputBase = require('../InputBase/InputBase.cjs'); var UnstyledButton = require('../UnstyledButton/UnstyledButton.cjs'); var NumberInputChevron = require('./NumberInputChevron.cjs'); var NumberInput_module = require('./NumberInput.module.css.cjs'); const partialNegativeNumberPattern = /^-0(\.0*)?$/; const leadingZerosPattern = /^-?0\d+$/; function isValidNumber(value) { return (typeof value === "number" ? value < Number.MAX_SAFE_INTEGER : !Number.isNaN(Number(value))) && !Number.isNaN(value); } function getDecrementedValue({ value, min, step = 1, allowNegative }) { const nextValue = value - step; if (min !== void 0 && nextValue < min) { return min; } if (!allowNegative && nextValue < 0 && min === void 0) { return value; } if (min !== void 0 && min >= 0 && nextValue <= min) { return nextValue; } return nextValue; } function isInRange(value, min, max) { if (value === void 0) { return true; } const minValid = min === void 0 || value >= min; const maxValid = max === void 0 || value <= max; return minValid && maxValid; } const defaultProps = { step: 1, clampBehavior: "blur", allowDecimal: true, allowNegative: true, startValue: 0 }; const varsResolver = createVarsResolver.createVarsResolver((_, { size }) => ({ controls: { "--ni-chevron-size": getSize.getSize(size, "ni-chevron-size") } })); const NumberInput = factory.factory((_props, ref) => { const props = useProps.useProps("NumberInput", defaultProps, _props); const { className, classNames, styles, unstyled, vars, onChange, onValueChange, value, defaultValue, max, min, step, hideControls, rightSection, isAllowed, clampBehavior, onBlur, allowDecimal, decimalScale, onKeyDown, handlersRef, startValue, disabled, rightSectionPointerEvents, allowNegative, readOnly, size, rightSectionWidth, stepHoldInterval, stepHoldDelay, allowLeadingZeros, ...others } = props; const getStyles = useStyles.useStyles({ name: "NumberInput", classes: NumberInput_module, props, classNames, styles, unstyled, vars, varsResolver }); const { resolvedClassNames, resolvedStyles } = useResolvedStylesApi.useResolvedStylesApi({ classNames, styles, props }); const [_value, setValue] = hooks.useUncontrolled({ value, defaultValue, onChange }); const shouldUseStepInterval = stepHoldDelay !== void 0 && stepHoldInterval !== void 0; const inputRef = React.useRef(null); const onStepTimeoutRef = React.useRef(null); const stepCountRef = React.useRef(0); const handleValueChange = (payload, event) => { if (event.source === "event") { setValue( isValidNumber(payload.floatValue) && !partialNegativeNumberPattern.test(payload.value) && !(allowLeadingZeros ? leadingZerosPattern.test(payload.value) : false) ? payload.floatValue : payload.value ); } onValueChange?.(payload, event); }; const incrementRef = React.useRef(); incrementRef.current = () => { if (typeof _value !== "number" || Number.isNaN(_value)) { setValue(hooks.clamp(startValue, min, max)); } else if (max !== void 0) { setValue(_value + step <= max ? _value + step : max); } else { setValue(_value + step); } }; const decrementRef = React.useRef(); decrementRef.current = () => { if (typeof _value !== "number" || Number.isNaN(_value)) { setValue(hooks.clamp(startValue, min, max)); } else { setValue(getDecrementedValue({ value: _value, min, step, allowNegative })); } }; const handleKeyDown = (event) => { onKeyDown?.(event); if (readOnly) { return; } if (event.key === "ArrowUp") { event.preventDefault(); incrementRef.current(); } if (event.key === "ArrowDown") { event.preventDefault(); decrementRef.current(); } }; hooks.assignRef(handlersRef, { increment: incrementRef.current, decrement: decrementRef.current }); const onStepHandleChange = (isIncrement) => { if (isIncrement) { incrementRef.current(); } else { decrementRef.current(); } stepCountRef.current += 1; }; const onStepLoop = (isIncrement) => { onStepHandleChange(isIncrement); if (shouldUseStepInterval) { const interval = typeof stepHoldInterval === "number" ? stepHoldInterval : stepHoldInterval(stepCountRef.current); onStepTimeoutRef.current = window.setTimeout(() => onStepLoop(isIncrement), interval); } }; const onStep = (event, isIncrement) => { event.preventDefault(); inputRef.current?.focus(); onStepHandleChange(isIncrement); if (shouldUseStepInterval) { onStepTimeoutRef.current = window.setTimeout(() => onStepLoop(isIncrement), stepHoldDelay); } }; const onStepDone = () => { if (onStepTimeoutRef.current) { window.clearTimeout(onStepTimeoutRef.current); } onStepTimeoutRef.current = null; stepCountRef.current = 0; }; const controls = /* @__PURE__ */ React.createElement("div", { ...getStyles("controls") }, /* @__PURE__ */ React.createElement( UnstyledButton.UnstyledButton, { ...getStyles("control"), tabIndex: -1, "aria-hidden": true, disabled: disabled || typeof _value === "number" && max !== void 0 && _value >= max, mod: { direction: "up" }, onMouseDown: (event) => event.preventDefault(), onPointerDown: (event) => { onStep(event, true); }, onPointerUp: onStepDone, onPointerLeave: onStepDone }, /* @__PURE__ */ React.createElement(NumberInputChevron.NumberInputChevron, { direction: "up" }) ), /* @__PURE__ */ React.createElement( UnstyledButton.UnstyledButton, { ...getStyles("control"), tabIndex: -1, "aria-hidden": true, disabled: disabled || typeof _value === "number" && min !== void 0 && _value <= min, mod: { direction: "down" }, onMouseDown: (event) => event.preventDefault(), onPointerDown: (event) => { onStep(event, false); }, onPointerUp: onStepDone, onPointerLeave: onStepDone }, /* @__PURE__ */ React.createElement(NumberInputChevron.NumberInputChevron, { direction: "down" }) )); return /* @__PURE__ */ React.createElement( InputBase.InputBase, { component: reactNumberFormat.NumericFormat, allowNegative, className: cx(NumberInput_module.root, className), size, ...others, readOnly, disabled, value: _value, getInputRef: hooks.useMergedRef(ref, inputRef), onValueChange: handleValueChange, rightSection: hideControls || readOnly ? rightSection : rightSection || controls, classNames: resolvedClassNames, styles: resolvedStyles, unstyled, __staticSelector: "NumberInput", decimalScale: allowDecimal ? decimalScale : 0, onKeyDown: handleKeyDown, rightSectionPointerEvents: rightSectionPointerEvents ?? (disabled ? "none" : void 0), rightSectionWidth: rightSectionWidth ?? `var(--ni-right-section-width-${size || "sm"})`, allowLeadingZeros, onBlur: (event) => { onBlur?.(event); if (clampBehavior === "blur" && typeof _value === "number") { const clampedValue = hooks.clamp(_value, min, max); if (clampedValue !== _value) { setValue(hooks.clamp(_value, min, max)); } } }, isAllowed: (val) => { if (clampBehavior === "strict") { if (isAllowed) { return isAllowed(val) && isInRange(val.floatValue, min, max); } return isInRange(val.floatValue, min, max); } return isAllowed ? isAllowed(val) : true; } } ); }); NumberInput.classes = { ...InputBase.InputBase.classes, ...NumberInput_module }; NumberInput.displayName = "@mantine/core/NumberInput"; exports.NumberInput = NumberInput; //# sourceMappingURL=NumberInput.cjs.map