UNPKG

@mantine/core

Version:

React components library focused on usability, accessibility and developer experience

248 lines (244 loc) 7.51 kB
'use client'; 'use strict'; var React = require('react'); 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'); require('clsx'); 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 Group = require('../Group/Group.cjs'); var Input = require('../Input/Input.cjs'); require('../Input/InputWrapper/InputWrapper.cjs'); require('../Input/InputDescription/InputDescription.cjs'); require('../Input/InputError/InputError.cjs'); require('../Input/InputLabel/InputLabel.cjs'); require('../Input/InputPlaceholder/InputPlaceholder.cjs'); require('../Input/InputWrapper.context.cjs'); var InputBase = require('../InputBase/InputBase.cjs'); var createPinArray = require('./create-pin-array/create-pin-array.cjs'); var PinInput_module = require('./PinInput.module.css.cjs'); const regex = { number: /^[0-9]+$/, alphanumeric: /^[a-zA-Z0-9]+$/i }; const defaultProps = { gap: "sm", length: 4, manageFocus: true, oneTimeCode: true, placeholder: "\u25CB", type: "alphanumeric", ariaLabel: "PinInput" }; const varsResolver = createVarsResolver.createVarsResolver((_, { size }) => ({ root: { "--pin-input-size": getSize.getSize(size ?? defaultProps.size, "pin-input-size") } })); const PinInput = factory.factory((props, ref) => { const { name, form, className, value, defaultValue, variant, gap, style, size, classNames, styles, unstyled, length, onChange, onComplete, manageFocus, autoFocus, error, radius, disabled, oneTimeCode, placeholder, type, mask, readOnly, inputType, inputMode, ariaLabel, vars, id, hiddenInputProps, ...others } = useProps.useProps("PinInput", defaultProps, props); const uuid = hooks.useId(id); const getStyles = useStyles.useStyles({ name: "PinInput", classes: PinInput_module, props, className, style, classNames, styles, unstyled, vars, varsResolver }); const { resolvedClassNames, resolvedStyles } = useResolvedStylesApi.useResolvedStylesApi({ classNames, styles, props }); const [focusedIndex, setFocusedIndex] = React.useState(-1); const [_value, setValues] = hooks.useUncontrolled({ value, defaultValue, finalValue: "", onChange }); const inputsRef = React.useRef([]); const validate = (code) => { const re = type instanceof RegExp ? type : type && type in regex ? regex[type] : null; return re?.test(code); }; const focusInputField = (dir, index) => { if (!manageFocus) return; if (dir === "next") { const nextIndex = index + 1; inputsRef.current[nextIndex < (length ?? 0) ? nextIndex : index].focus(); } if (dir === "prev") { const nextIndex = index - 1; inputsRef.current[nextIndex > -1 ? nextIndex : index].focus(); } }; const setFieldValue = (val, index) => { const values = [...createPinArray.createPinArray(length ?? 0, _value)]; values[index] = val; setValues(values.join("")); }; const handleChange = (event, index) => { const inputValue = event.target.value; const nextCharOrValue = inputValue.length === 2 ? inputValue.split("")[inputValue.length - 1] : inputValue; const isValid = validate(nextCharOrValue); if (nextCharOrValue.length < 2) { if (isValid) { setFieldValue(nextCharOrValue, index); focusInputField("next", index); } else { setFieldValue("", index); } } else if (isValid) { setValues(inputValue); } }; const handleKeyDown = (event, index) => { if (event.key === "ArrowLeft") { event.preventDefault(); focusInputField("prev", index); } else if (event.key === "ArrowRight") { event.preventDefault(); focusInputField("next", index); } else if (event.key === "Delete") { event.preventDefault(); setFieldValue("", index); } else if (event.key === "Backspace") { event.preventDefault(); setFieldValue("", index); if (length === index + 1) { if (event.target.value === "") { focusInputField("prev", index); } } else { focusInputField("prev", index); } } }; const handleFocus = (event, index) => { event.target.select(); setFocusedIndex(index); }; const handleBlur = () => { setFocusedIndex(-1); }; const handlePaste = (event) => { event.preventDefault(); const copyValue = event.clipboardData.getData("Text"); const isValid = validate(copyValue.trim()); if (isValid) { setValues(copyValue); } }; React.useEffect(() => { if (_value.length !== length) return; onComplete?.(_value); }, [_value]); return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement( Group.Group, { ...others, ...getStyles("root"), role: "group", id: uuid, gap, unstyled, wrap: "nowrap", variant, __size: size }, createPinArray.createPinArray(length ?? 0, _value).map((char, index) => /* @__PURE__ */ React.createElement( Input.Input, { component: "input", ...getStyles("pinInput", { style: { "--_input-padding": "0", "--_input-text-align": "center" } }), classNames: resolvedClassNames, styles: resolvedStyles, size, __staticSelector: "PinInput", id: `${uuid}-${index + 1}`, key: `${uuid}-${index}`, inputMode: inputMode || (type === "number" ? "numeric" : "text"), onChange: (event) => handleChange(event, index), onKeyDown: (event) => handleKeyDown(event, index), onFocus: (event) => handleFocus(event, index), onBlur: handleBlur, onPaste: handlePaste, type: inputType || (mask ? "password" : type === "number" ? "tel" : "text"), radius, error, variant, disabled, ref: (node) => { index === 0 && hooks.assignRef(ref, node); inputsRef.current[index] = node; }, autoComplete: oneTimeCode ? "one-time-code" : "off", placeholder: focusedIndex === index ? "" : placeholder, value: char, autoFocus: autoFocus && index === 0, unstyled, "aria-label": ariaLabel, readOnly } )) ), /* @__PURE__ */ React.createElement("input", { type: "hidden", name, form, value: _value, ...hiddenInputProps })); }); PinInput.classes = { ...PinInput_module, ...InputBase.InputBase.classes }; PinInput.displayName = "@mantine/core/PinInput"; exports.PinInput = PinInput; //# sourceMappingURL=PinInput.cjs.map