UNPKG

@mantine/core

Version:

React components library focused on usability, accessibility and developer experience

262 lines (261 loc) 9.02 kB
"use client"; require("../../_virtual/_rolldown/runtime.cjs"); const require_get_size = require("../../core/utils/get-size/get-size.cjs"); const require_create_vars_resolver = require("../../core/styles-api/create-vars-resolver/create-vars-resolver.cjs"); const require_use_props = require("../../core/MantineProvider/use-props/use-props.cjs"); const require_use_resolved_styles_api = require("../../core/styles-api/use-resolved-styles-api/use-resolved-styles-api.cjs"); const require_use_styles = require("../../core/styles-api/use-styles/use-styles.cjs"); const require_factory = require("../../core/factory/factory.cjs"); const require_Group = require("../Group/Group.cjs"); const require_Input = require("../Input/Input.cjs"); const require_InputBase = require("../InputBase/InputBase.cjs"); const require_create_pin_array = require("./create-pin-array/create-pin-array.cjs"); const require_PinInput_module = require("./PinInput.module.cjs"); let react = require("react"); let _mantine_hooks = require("@mantine/hooks"); let react_jsx_runtime = require("react/jsx-runtime"); //#region packages/@mantine/core/src/components/PinInput/PinInput.tsx const regex = { number: /^[0-9]+$/, alphanumeric: /^[a-zA-Z0-9]+$/i }; const defaultProps = { gap: "sm", length: 4, manageFocus: true, oneTimeCode: true, placeholder: "○", type: "alphanumeric", ariaLabel: "PinInput", size: "sm" }; const varsResolver = require_create_vars_resolver.createVarsResolver((_, { size }) => ({ root: { "--pin-input-size": require_get_size.getSize(size ?? "sm", "pin-input-size") } })); const PinInput = require_factory.factory((props) => { 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, rootRef, getInputProps, attributes, ref, ...others } = require_use_props.useProps("PinInput", defaultProps, props); const uuid = (0, _mantine_hooks.useId)(id); const getStyles = require_use_styles.useStyles({ name: "PinInput", classes: require_PinInput_module.default, props, className, style, classNames, styles, unstyled, attributes, vars, varsResolver }); const { resolvedClassNames, resolvedStyles } = require_use_resolved_styles_api.useResolvedStylesApi({ classNames, styles, props }); const [focusedIndex, setFocusedIndex] = (0, react.useState)(-1); const inputsRef = (0, react.useRef)([]); const currentLength = length ?? 4; const completedRef = (0, react.useRef)(false); const [_value, setValues] = (0, _mantine_hooks.useUncontrolled)({ value: value !== void 0 ? require_create_pin_array.createPinArray(currentLength, value) : void 0, defaultValue: defaultValue?.split("").slice(0, currentLength), finalValue: require_create_pin_array.createPinArray(currentLength, ""), onChange: (val) => { const stringValue = val.join("").trim(); onChange?.(stringValue); if (stringValue.length === currentLength && !completedRef.current) { completedRef.current = true; onComplete?.(stringValue); } else if (stringValue.length < currentLength) completedRef.current = false; } }); const currentValue = _value.length !== currentLength ? require_create_pin_array.createPinArray(currentLength, _value.join("")) : _value; const _valueToString = currentValue.join("").trim(); const validate = (code) => { return (type instanceof RegExp ? type : type && type in regex ? regex[type] : null)?.test(code); }; const focusInputField = (dir, index) => { if (!manageFocus) return; if (dir === "next") { const nextIndex = index + 1; if (nextIndex < currentLength) inputsRef.current[nextIndex]?.focus(); } else if (dir === "prev") { const prevIndex = index - 1; if (prevIndex >= 0) inputsRef.current[prevIndex]?.focus(); } }; const setFieldValue = (val, index) => { const values = [...currentValue]; values[index] = val; setValues(values); return values; }; const handleChange = (event, index) => { const inputValue = event.target.value; if (inputValue.length > 1) { if (inputValue.length > 2) { if (validate(inputValue)) { setValues(require_create_pin_array.createPinArray(currentLength, inputValue)); const filledCount = Math.min(inputValue.length, currentLength); if (filledCount < currentLength) focusInputField("next", filledCount - 1); } return; } const newChar = inputValue.split("")[inputValue.length - 1]; if (validate(newChar)) { setFieldValue(newChar, index); focusInputField("next", index); } return; } if (inputValue.length === 1) if (validate(inputValue)) { setFieldValue(inputValue, index); focusInputField("next", index); } else setFieldValue("", index); else if (inputValue.length === 0) setFieldValue("", index); }; const handleKeyDown = (event, index) => { const { ctrlKey, metaKey, key, shiftKey, target } = event; const inputValue = target.value; if (inputMode === "numeric") { const allowedKeys = [ "Backspace", "Tab", "Control", "Delete", "ArrowLeft", "ArrowRight" ]; const isPasteShortcut = (ctrlKey || metaKey) && key === "v"; if (!(allowedKeys.includes(key) || isPasteShortcut || !Number.isNaN(Number(key)))) { event.preventDefault(); return; } } switch (key) { case "ArrowLeft": event.preventDefault(); focusInputField("prev", index); break; case "ArrowRight": event.preventDefault(); focusInputField("next", index); break; case "Tab": if (shiftKey) { if (index > 0 && manageFocus) { event.preventDefault(); focusInputField("prev", index); } } break; case " ": event.preventDefault(); focusInputField("next", index); break; case "Delete": event.preventDefault(); setFieldValue("", index); break; case "Backspace": if (inputValue === "") { event.preventDefault(); focusInputField("prev", index); } else { setFieldValue("", index); if (index < currentLength - 1) { event.preventDefault(); focusInputField("prev", index); } } break; default: if (inputValue.length > 0 && key === currentValue[index]) { event.preventDefault(); focusInputField("next", index); } } }; const handleFocus = (event, index) => { event.target.select(); setFocusedIndex(index); }; const handleBlur = () => { setFocusedIndex(-1); }; const handlePaste = (event) => { event.preventDefault(); const pasteData = event.clipboardData.getData("text/plain").replace(/[\n\r\s]+/g, ""); if (validate(pasteData.trim())) { const pasteArray = require_create_pin_array.createPinArray(currentLength, pasteData); setValues(pasteArray); const filledCount = pasteArray.filter((val) => val !== "").length; if (filledCount >= currentLength) inputsRef.current[currentLength - 1]?.focus(); else inputsRef.current[filledCount]?.focus(); } }; return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Group.Group, { ...others, ...getStyles("root"), ref: rootRef, role: "group", id: uuid, gap, unstyled, wrap: "nowrap", variant, __size: size, dir: "ltr", children: currentValue.map((char, index) => /* @__PURE__ */ (0, react.createElement)(require_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) => { if (node) { index === 0 && (0, _mantine_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, ...getInputProps?.(index) })) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", { type: "hidden", name, form, value: _valueToString, ...hiddenInputProps })] }); }); PinInput.classes = { ...require_PinInput_module.default, ...require_InputBase.InputBase.classes }; PinInput.varsResolver = varsResolver; PinInput.displayName = "@mantine/core/PinInput"; //#endregion exports.PinInput = PinInput; //# sourceMappingURL=PinInput.cjs.map