@mantine/core
Version:
React components library focused on usability, accessibility and developer experience
262 lines (261 loc) • 9.02 kB
JavaScript
"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