UNPKG

@yamada-ui/react

Version:

React UI components of the Yamada, by the Yamada, for the Yamada built with React and Emotion

186 lines (182 loc) 6.68 kB
"use client"; const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs'); const require_dom = require('../../utils/dom.cjs'); const require_utils_index = require('../../utils/index.cjs'); const require_hooks_use_controllable_state_index = require('../../hooks/use-controllable-state/index.cjs'); const require_hooks_use_descendants_index = require('../../hooks/use-descendants/index.cjs'); const require_use_field_props = require('../field/use-field-props.cjs'); let react = require("react"); react = require_rolldown_runtime.__toESM(react); //#region src/components/pin-input/use-pin-input.ts const { DescendantsContext: PinInputDescendantsContext, useDescendant: usePinInputDescendant, useDescendants: usePinInputDescendants } = require_hooks_use_descendants_index.createDescendants(); const toArray = (value) => value?.split(""); const validate = (value, type) => { return (type === "alphanumeric" ? /^[a-zA-Z0-9]+$/i : /^[0-9]+$/).test(value); }; const usePinInput = (props = {}) => { const uuid = (0, react.useId)(); const { props: { id = uuid, type = "number", autoFocus, defaultValue, disabled, manageFocus = true, mask, otp = false, placeholder = "◯", readOnly, value, onChange: onChangeProp, onComplete,...rest }, ariaProps, dataProps, eventProps } = require_use_field_props.useFieldProps(props); const descendants = usePinInputDescendants(); const [moveFocus, setMoveFocus] = (0, react.useState)(true); const [focusedIndex, setFocusedIndex] = (0, react.useState)(-1); const [values, setValues] = require_hooks_use_controllable_state_index.useControllableState({ defaultValue: toArray(defaultValue) || [], value: toArray(value), onChange: (values$1) => onChangeProp?.(values$1.join("")) }); const focusNext = (0, react.useCallback)((index) => { if (!moveFocus || !manageFocus) return; const next = descendants.nextValue(index, false); if (!next) return; requestAnimationFrame(() => next.node.focus()); }, [ descendants, moveFocus, manageFocus ]); const focusInputField = (0, react.useCallback)((direction, index) => { const input = direction === "next" ? descendants.nextValue(index, false) : descendants.prevValue(index, false); if (!input) return; const valueLength = input.node.value.length; requestAnimationFrame(() => { input.node.focus(); input.node.setSelectionRange(0, valueLength); }); }, [descendants]); const setValue = (0, react.useCallback)((value$1, index, focus = true) => { let nextValues = [...values]; nextValues[index] = value$1; setValues(nextValues); nextValues = nextValues.filter(Boolean); if (value$1 !== "" && nextValues.length === descendants.count()) { onComplete?.(nextValues.join("")); descendants.value(index)?.node.blur(); } else if (focus) focusNext(index); }, [ values, setValues, descendants, onComplete, focusNext ]); const getNextValue = (0, react.useCallback)((value$1, eventValue) => { let nextValue = eventValue; if (!value$1?.length) return nextValue; if (value$1.startsWith(eventValue.charAt(0))) nextValue = eventValue.charAt(1); else if (value$1.startsWith(eventValue.charAt(1))) nextValue = eventValue.charAt(0); return nextValue; }, []); const onChange = (0, react.useCallback)((index) => ({ target }) => { const eventValue = target.value; const currentValue = values[index]; const nextValue = getNextValue(currentValue, eventValue); if (nextValue === "") { setValue("", index); return; } if (eventValue.length > 2) { if (!validate(eventValue, type)) return; const nextValue$1 = eventValue.split("").filter((_, index$1) => index$1 < descendants.count()); setValues(nextValue$1); if (nextValue$1.length === descendants.count()) { onComplete?.(nextValue$1.join("")); descendants.value(index)?.node.blur(); } } else { if (validate(nextValue, type)) setValue(nextValue, index); setMoveFocus(true); } }, [ descendants, getNextValue, onComplete, setValue, setValues, type, values ]); const onKeyDown = (0, react.useCallback)((index) => (ev) => { if (!manageFocus) return; require_dom.runKeyAction(ev, { ArrowLeft: (ev$1) => { ev$1.preventDefault(); focusInputField("prev", index); }, ArrowRight: (ev$1) => { ev$1.preventDefault(); focusInputField("next", index); }, Backspace: (ev$1) => { if (ev$1.target.value === "") { const prevInput = descendants.prevValue(index, false); if (!prevInput) return; setValue("", index - 1, false); prevInput.node.focus(); setMoveFocus(true); } else setMoveFocus(false); } }, { preventDefault: false }); }, [ descendants, focusInputField, manageFocus, setValue ]); const onFocus = (0, react.useCallback)((index) => () => setFocusedIndex(index), []); const onBlur = (0, react.useCallback)(() => setFocusedIndex(-1), []); (0, react.useEffect)(() => { if (!autoFocus) return; const firstValue = descendants.firstValue(); if (!firstValue) return; requestAnimationFrame(() => firstValue.node.focus()); }, [autoFocus, descendants]); const getRootProps = (0, react.useCallback)((props$1) => ({ role: "group", ...rest, ...props$1 }), [rest]); return { descendants, getInputProps: (0, react.useCallback)(({ index,...props$1 }) => ({ ...ariaProps, ...dataProps, type: mask ? "password" : type === "number" ? "tel" : "text", autoComplete: otp ? "one-time-code" : "off", disabled, inputMode: type === "number" ? "numeric" : "text", placeholder: focusedIndex === index && !readOnly && !props$1.readOnly ? "" : placeholder, readOnly, value: values[index] || "", ...(0, require_utils_index.utils_exports.filterUndefined)(props$1), id: `${id}${index ? `-${index}` : ""}`, onBlur: (0, require_utils_index.utils_exports.handlerAll)(eventProps.onBlur, props$1.onBlur, onBlur), onChange: (0, require_utils_index.utils_exports.handlerAll)(props$1.onChange, onChange(index)), onFocus: (0, require_utils_index.utils_exports.handlerAll)(eventProps.onFocus, props$1.onFocus, onFocus(index)), onKeyDown: (0, require_utils_index.utils_exports.handlerAll)(props$1.onKeyDown, onKeyDown(index)) }), [ ariaProps, dataProps, eventProps, mask, type, disabled, readOnly, id, otp, focusedIndex, placeholder, values, onBlur, onChange, onFocus, onKeyDown ]), getRootProps }; }; //#endregion exports.PinInputDescendantsContext = PinInputDescendantsContext; exports.usePinInput = usePinInput; exports.usePinInputDescendant = usePinInputDescendant; exports.usePinInputDescendants = usePinInputDescendants; //# sourceMappingURL=use-pin-input.cjs.map