@yamada-ui/pin-input 1.2.4-dev-20241214144625 → 1.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -43,8 +43,9 @@ var PinInput = forwardRef(
43
43
  focusBorderColor,
44
44
  ...props
45
45
  });
46
- let {
47
- id,
46
+ const uuid = useId();
47
+ const {
48
+ id = uuid,
48
49
  type = "number",
49
50
  className,
50
51
  autoFocus,
@@ -69,22 +70,19 @@ var PinInput = forwardRef(
69
70
  },
70
71
  containerProps
71
72
  ] = splitObject(rest, formControlProperties);
72
- const uuid = useId();
73
- id != null ? id : id = uuid;
74
73
  const descendants = useDescendants();
75
74
  const [moveFocus, setMoveFocus] = useState(true);
76
75
  const [focusedIndex, setFocusedIndex] = useState(-1);
77
- useEffect(() => {
78
- if (!autoFocus) return;
79
- const firstValue = descendants.firstValue();
80
- if (!firstValue) return;
81
- requestAnimationFrame(() => firstValue.node.focus());
82
- }, [autoFocus, descendants]);
83
76
  const [values, setValues] = useControllableState({
84
77
  defaultValue: toArray(defaultValue) || [],
85
78
  value: toArray(value),
86
79
  onChange: (values2) => onChangeProp == null ? void 0 : onChangeProp(values2.join(""))
87
80
  });
81
+ const css = {
82
+ alignItems: "center",
83
+ display: "flex",
84
+ ...styles.container
85
+ };
88
86
  const focusNext = useCallback(
89
87
  (index) => {
90
88
  if (!moveFocus || !manageFocus) return;
@@ -204,6 +202,12 @@ var PinInput = forwardRef(
204
202
  []
205
203
  );
206
204
  const onBlur = useCallback(() => setFocusedIndex(-1), []);
205
+ useEffect(() => {
206
+ if (!autoFocus) return;
207
+ const firstValue = descendants.firstValue();
208
+ if (!firstValue) return;
209
+ requestAnimationFrame(() => firstValue.node.focus());
210
+ }, [autoFocus, descendants]);
207
211
  const getInputProps = useCallback(
208
212
  ({
209
213
  index,
@@ -241,11 +245,6 @@ var PinInput = forwardRef(
241
245
  placeholder
242
246
  ]
243
247
  );
244
- const css = {
245
- alignItems: "center",
246
- display: "flex",
247
- ...styles.container
248
- };
249
248
  let cloneChildren = getValidChildren(children);
250
249
  if (!cloneChildren.length)
251
250
  for (let i = 0; i < items; i++) {
@@ -271,8 +270,8 @@ var PinInputField = forwardRef(
271
270
  ({ className, ...rest }, ref) => {
272
271
  const { styles, getInputProps } = usePinInputContext();
273
272
  const { index, register } = useDescendant();
274
- rest = useFormControlProps(rest);
275
273
  const css = { ...styles.field };
274
+ rest = useFormControlProps(rest);
276
275
  return /* @__PURE__ */ jsx(
277
276
  ui.input,
278
277
  {
@@ -290,4 +289,4 @@ export {
290
289
  PinInput,
291
290
  PinInputField
292
291
  };
293
- //# sourceMappingURL=chunk-TU5BZGLV.mjs.map
292
+ //# sourceMappingURL=chunk-SUK2AVTG.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/pin-input.tsx"],"sourcesContent":["import type {\n ColorModeToken,\n CSS,\n CSSUIObject,\n HTMLUIProps,\n ThemeProps,\n} from \"@yamada-ui/core\"\nimport type { FormControlOptions } from \"@yamada-ui/form-control\"\nimport type { ChangeEvent, KeyboardEvent, Ref } from \"react\"\nimport {\n forwardRef,\n omitThemeProps,\n ui,\n useComponentMultiStyle,\n} from \"@yamada-ui/core\"\nimport {\n formControlProperties,\n useFormControlProps,\n} from \"@yamada-ui/form-control\"\nimport { useControllableState } from \"@yamada-ui/use-controllable-state\"\nimport { createDescendant } from \"@yamada-ui/use-descendant\"\nimport {\n createContext,\n cx,\n filterUndefined,\n getValidChildren,\n handlerAll,\n mergeRefs,\n splitObject,\n} from \"@yamada-ui/utils\"\nimport { useCallback, useEffect, useId, useState } from \"react\"\n\nconst toArray = (value?: string) => value?.split(\"\")\n\nconst validate = (value: string, type: PinInputProps[\"type\"]) => {\n const NUMERIC_REGEX = /^[0-9]+$/\n const ALPHA_NUMERIC_REGEX = /^[a-zA-Z0-9]+$/i\n\n const regex = type === \"alphanumeric\" ? ALPHA_NUMERIC_REGEX : NUMERIC_REGEX\n\n return regex.test(value)\n}\n\ninterface PinInputContext {\n styles: { [key: string]: CSSUIObject | undefined }\n getInputProps: (\n props: {\n index: number\n ref?: Ref<HTMLInputElement>\n } & PinInputFieldProps,\n ) => PinInputFieldProps\n}\n\nconst [PinInputProvider, usePinInputContext] = createContext<PinInputContext>({\n name: \"PinInputContext\",\n errorMessage: `PinInputContext returned is 'undefined'. Seems you forgot to wrap the components in \"<PinInput />\"`,\n})\n\nconst { DescendantsContextProvider, useDescendant, useDescendants } =\n createDescendant<HTMLInputElement>()\n\ninterface PinInputOptions {\n /**\n * The top-level id string that will be applied to the input fields.\n * The index of the input will be appended to this top-level id.\n */\n id?: string\n /**\n * The type of values the pin-input should allow.\n *\n * @default 'number'\n */\n type?: \"alphanumeric\" | \"number\"\n /**\n * If `true`, the pin input receives focus on mount.\n *\n * @default false\n */\n autoFocus?: boolean\n /**\n * The initial value of the pin input.\n */\n defaultValue?: string\n /**\n * The border color when the input is invalid.\n */\n errorBorderColor?: ColorModeToken<CSS.Property.BorderColor, \"colors\">\n /**\n * The border color when the input is focused.\n */\n focusBorderColor?: ColorModeToken<CSS.Property.BorderColor, \"colors\">\n /**\n * The number of inputs to display.\n *\n * @default 4\n */\n items?: number\n /**\n * If `true`, focus will move automatically to the next input once filled.\n *\n * @default true\n */\n manageFocus?: boolean\n /**\n * If `true`, the input's value will be masked just like `type=password`.\n */\n mask?: boolean\n /**\n * If `true`, the pin input component signals to its fields that they should.\n */\n otp?: boolean\n /**\n * The placeholder for the pin input.\n *\n * @default '○'\n */\n placeholder?: string\n /**\n * The value of the pin input.\n */\n value?: string\n /**\n * Function called on input change.\n */\n onChange?: (value: string) => void\n /**\n * Function called when all inputs have valid values.\n */\n onComplete?: (value: string) => void\n}\n\nexport interface PinInputProps\n extends Omit<HTMLUIProps, \"defaultValue\" | \"mask\" | \"onChange\">,\n ThemeProps<\"PinInput\">,\n FormControlOptions,\n PinInputOptions {}\n\n/**\n * `PinInput` is a component used to capture pin codes or OTP (One-Time Password) inputs.\n *\n * @see Docs https://yamada-ui.com/components/forms/pin-input\n */\nexport const PinInput = forwardRef<PinInputProps, \"div\">(\n ({ errorBorderColor, focusBorderColor, ...props }, ref) => {\n const [styles, mergedProps] = useComponentMultiStyle(\"PinInput\", {\n errorBorderColor,\n focusBorderColor,\n ...props,\n })\n const uuid = useId()\n const {\n id = uuid,\n type = \"number\",\n className,\n autoFocus,\n children,\n defaultValue,\n items = 4,\n manageFocus = true,\n mask,\n otp = false,\n placeholder = \"○\",\n value,\n onChange: onChangeProp,\n onComplete,\n ...rest\n } = useFormControlProps(omitThemeProps(mergedProps))\n const [\n {\n \"aria-readonly\": _ariaReadonly,\n disabled,\n readOnly,\n ...formControlProps\n },\n containerProps,\n ] = splitObject(rest, formControlProperties)\n const descendants = useDescendants()\n const [moveFocus, setMoveFocus] = useState<boolean>(true)\n const [focusedIndex, setFocusedIndex] = useState<number>(-1)\n const [values, setValues] = useControllableState<string[]>({\n defaultValue: toArray(defaultValue) || [],\n value: toArray(value),\n onChange: (values) => onChangeProp?.(values.join(\"\")),\n })\n const css: CSSUIObject = {\n alignItems: \"center\",\n display: \"flex\",\n ...styles.container,\n }\n\n const focusNext = useCallback(\n (index: number) => {\n if (!moveFocus || !manageFocus) return\n\n const next = descendants.nextValue(index, undefined, false)\n\n if (!next) return\n\n requestAnimationFrame(() => next.node.focus())\n },\n [descendants, moveFocus, manageFocus],\n )\n\n const focusInputField = useCallback(\n (direction: \"next\" | \"prev\", index: number) => {\n const input =\n direction === \"next\"\n ? descendants.nextValue(index, undefined, false)\n : descendants.prevValue(index, undefined, false)\n\n if (!input) return\n\n const valueLength = input.node.value.length\n\n requestAnimationFrame(() => {\n input.node.focus()\n input.node.setSelectionRange(0, valueLength)\n })\n },\n [descendants],\n )\n\n const setValue = useCallback(\n (value: string, index: number, isFocus = true) => {\n let nextValues = [...values]\n\n nextValues[index] = value\n\n setValues(nextValues)\n\n nextValues = nextValues.filter(Boolean)\n\n const isComplete =\n value !== \"\" && nextValues.length === descendants.count()\n\n if (isComplete) {\n onComplete?.(nextValues.join(\"\"))\n descendants.value(index)?.node.blur()\n } else if (isFocus) {\n focusNext(index)\n }\n },\n [values, setValues, descendants, onComplete, focusNext],\n )\n\n const getNextValue = useCallback(\n (value: string | undefined, eventValue: string) => {\n let nextValue = eventValue\n\n if (!value?.length) return nextValue\n\n if (value.startsWith(eventValue.charAt(0))) {\n nextValue = eventValue.charAt(1)\n } else if (value.startsWith(eventValue.charAt(1))) {\n nextValue = eventValue.charAt(0)\n }\n\n return nextValue\n },\n [],\n )\n\n const onChange = useCallback(\n (index: number) =>\n ({ target }: ChangeEvent<HTMLInputElement>) => {\n const eventValue = target.value\n const currentValue = values[index]\n const nextValue = getNextValue(currentValue, eventValue)\n\n if (nextValue === \"\") {\n setValue(\"\", index)\n\n return\n }\n\n if (eventValue.length > 2) {\n if (!validate(eventValue, type)) return\n\n const nextValue = eventValue\n .split(\"\")\n .filter((_, index) => index < descendants.count())\n\n setValues(nextValue)\n\n if (nextValue.length === descendants.count()) {\n onComplete?.(nextValue.join(\"\"))\n descendants.value(index)?.node.blur()\n }\n } else {\n if (validate(nextValue, type)) setValue(nextValue, index)\n\n setMoveFocus(true)\n }\n },\n [\n descendants,\n getNextValue,\n onComplete,\n setValue,\n setValues,\n type,\n values,\n ],\n )\n\n const onKeyDown = useCallback(\n (index: number) => (ev: KeyboardEvent<HTMLInputElement>) => {\n if (!manageFocus) return\n\n const actions: { [key: string]: Function | undefined } = {\n ArrowLeft: () => {\n ev.preventDefault()\n focusInputField(\"prev\", index)\n },\n ArrowRight: () => {\n ev.preventDefault()\n focusInputField(\"next\", index)\n },\n Backspace: () => {\n if ((ev.target as HTMLInputElement).value === \"\") {\n const prevInput = descendants.prevValue(index, undefined, false)\n\n if (!prevInput) return\n\n setValue(\"\", index - 1, false)\n prevInput.node.focus()\n setMoveFocus(true)\n } else {\n setMoveFocus(false)\n }\n },\n }\n\n const action = actions[ev.key]\n\n if (!action) return\n\n action()\n },\n [descendants, focusInputField, manageFocus, setValue],\n )\n\n const onFocus = useCallback(\n (index: number) => () => setFocusedIndex(index),\n [],\n )\n\n const onBlur = useCallback(() => setFocusedIndex(-1), [])\n\n useEffect(() => {\n if (!autoFocus) return\n\n const firstValue = descendants.firstValue()\n\n if (!firstValue) return\n\n requestAnimationFrame(() => firstValue.node.focus())\n }, [autoFocus, descendants])\n\n const getInputProps = useCallback(\n ({\n index,\n ...props\n }: {\n index: number\n ref?: Ref<HTMLInputElement>\n } & PinInputFieldProps): PinInputFieldProps => ({\n type: mask ? \"password\" : type === \"number\" ? \"tel\" : \"text\",\n disabled,\n inputMode: type === \"number\" ? \"numeric\" : \"text\",\n readOnly,\n ...formControlProps,\n ...filterUndefined(props),\n id: `${id}-${index}`,\n autoComplete: otp ? \"one-time-code\" : \"off\",\n placeholder:\n focusedIndex === index && !readOnly && !props.readOnly\n ? \"\"\n : placeholder,\n value: values[index] || \"\",\n onBlur: handlerAll(props.onBlur, onBlur),\n onChange: handlerAll(props.onChange, onChange(index)),\n onFocus: handlerAll(props.onFocus, onFocus(index)),\n onKeyDown: handlerAll(props.onKeyDown, onKeyDown(index)),\n }),\n [\n type,\n mask,\n formControlProps,\n id,\n values,\n onChange,\n onKeyDown,\n onFocus,\n onBlur,\n otp,\n focusedIndex,\n disabled,\n readOnly,\n placeholder,\n ],\n )\n\n let cloneChildren = getValidChildren(children)\n\n if (!cloneChildren.length)\n for (let i = 0; i < items; i++) {\n cloneChildren.push(<PinInputField key={i} />)\n }\n\n return (\n <DescendantsContextProvider value={descendants}>\n <PinInputProvider value={{ styles, getInputProps }}>\n <ui.div\n ref={ref}\n className={cx(\"ui-pin-input\", className)}\n role=\"group\"\n __css={css}\n {...formControlProps}\n {...containerProps}\n >\n {cloneChildren}\n </ui.div>\n </PinInputProvider>\n </DescendantsContextProvider>\n )\n },\n)\n\nPinInput.displayName = \"PinInput\"\nPinInput.__ui__ = \"PinInput\"\n\nexport interface PinInputFieldProps\n extends HTMLUIProps<\"input\">,\n FormControlOptions {}\n\nexport const PinInputField = forwardRef<PinInputFieldProps, \"input\">(\n ({ className, ...rest }, ref) => {\n const { styles, getInputProps } = usePinInputContext()\n const { index, register } = useDescendant()\n const css: CSSUIObject = { ...styles.field }\n\n rest = useFormControlProps(rest)\n\n return (\n <ui.input\n className={cx(\"ui-pin-input__field\", className)}\n {...getInputProps({ ...rest, ref: mergeRefs(register, ref), index })}\n __css={css}\n />\n )\n },\n)\n\nPinInputField.displayName = \"PinInputField\"\nPinInputField.__ui__ = \"PinInputField\"\n"],"mappings":"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","names":["values","value","nextValue","index","props"]}
package/dist/index.js CHANGED
@@ -53,8 +53,9 @@ var PinInput = (0, import_core.forwardRef)(
53
53
  focusBorderColor,
54
54
  ...props
55
55
  });
56
- let {
57
- id,
56
+ const uuid = (0, import_react.useId)();
57
+ const {
58
+ id = uuid,
58
59
  type = "number",
59
60
  className,
60
61
  autoFocus,
@@ -79,22 +80,19 @@ var PinInput = (0, import_core.forwardRef)(
79
80
  },
80
81
  containerProps
81
82
  ] = (0, import_utils.splitObject)(rest, import_form_control.formControlProperties);
82
- const uuid = (0, import_react.useId)();
83
- id != null ? id : id = uuid;
84
83
  const descendants = useDescendants();
85
84
  const [moveFocus, setMoveFocus] = (0, import_react.useState)(true);
86
85
  const [focusedIndex, setFocusedIndex] = (0, import_react.useState)(-1);
87
- (0, import_react.useEffect)(() => {
88
- if (!autoFocus) return;
89
- const firstValue = descendants.firstValue();
90
- if (!firstValue) return;
91
- requestAnimationFrame(() => firstValue.node.focus());
92
- }, [autoFocus, descendants]);
93
86
  const [values, setValues] = (0, import_use_controllable_state.useControllableState)({
94
87
  defaultValue: toArray(defaultValue) || [],
95
88
  value: toArray(value),
96
89
  onChange: (values2) => onChangeProp == null ? void 0 : onChangeProp(values2.join(""))
97
90
  });
91
+ const css = {
92
+ alignItems: "center",
93
+ display: "flex",
94
+ ...styles.container
95
+ };
98
96
  const focusNext = (0, import_react.useCallback)(
99
97
  (index) => {
100
98
  if (!moveFocus || !manageFocus) return;
@@ -214,6 +212,12 @@ var PinInput = (0, import_core.forwardRef)(
214
212
  []
215
213
  );
216
214
  const onBlur = (0, import_react.useCallback)(() => setFocusedIndex(-1), []);
215
+ (0, import_react.useEffect)(() => {
216
+ if (!autoFocus) return;
217
+ const firstValue = descendants.firstValue();
218
+ if (!firstValue) return;
219
+ requestAnimationFrame(() => firstValue.node.focus());
220
+ }, [autoFocus, descendants]);
217
221
  const getInputProps = (0, import_react.useCallback)(
218
222
  ({
219
223
  index,
@@ -251,11 +255,6 @@ var PinInput = (0, import_core.forwardRef)(
251
255
  placeholder
252
256
  ]
253
257
  );
254
- const css = {
255
- alignItems: "center",
256
- display: "flex",
257
- ...styles.container
258
- };
259
258
  let cloneChildren = (0, import_utils.getValidChildren)(children);
260
259
  if (!cloneChildren.length)
261
260
  for (let i = 0; i < items; i++) {
@@ -281,8 +280,8 @@ var PinInputField = (0, import_core.forwardRef)(
281
280
  ({ className, ...rest }, ref) => {
282
281
  const { styles, getInputProps } = usePinInputContext();
283
282
  const { index, register } = useDescendant();
284
- rest = (0, import_form_control.useFormControlProps)(rest);
285
283
  const css = { ...styles.field };
284
+ rest = (0, import_form_control.useFormControlProps)(rest);
286
285
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
287
286
  import_core.ui.input,
288
287
  {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/pin-input.tsx"],"sourcesContent":["export { PinInput, PinInputField } from \"./pin-input\"\nexport type { PinInputFieldProps, PinInputProps } from \"./pin-input\"\n","import type {\n ColorModeToken,\n CSS,\n CSSUIObject,\n HTMLUIProps,\n ThemeProps,\n} from \"@yamada-ui/core\"\nimport type { FormControlOptions } from \"@yamada-ui/form-control\"\nimport type { ChangeEvent, KeyboardEvent, Ref } from \"react\"\nimport {\n forwardRef,\n omitThemeProps,\n ui,\n useComponentMultiStyle,\n} from \"@yamada-ui/core\"\nimport {\n formControlProperties,\n useFormControlProps,\n} from \"@yamada-ui/form-control\"\nimport { useControllableState } from \"@yamada-ui/use-controllable-state\"\nimport { createDescendant } from \"@yamada-ui/use-descendant\"\nimport {\n createContext,\n cx,\n filterUndefined,\n getValidChildren,\n handlerAll,\n mergeRefs,\n splitObject,\n} from \"@yamada-ui/utils\"\nimport { useCallback, useEffect, useId, useState } from \"react\"\n\nconst toArray = (value?: string) => value?.split(\"\")\n\nconst validate = (value: string, type: PinInputProps[\"type\"]) => {\n const NUMERIC_REGEX = /^[0-9]+$/\n const ALPHA_NUMERIC_REGEX = /^[a-zA-Z0-9]+$/i\n\n const regex = type === \"alphanumeric\" ? ALPHA_NUMERIC_REGEX : NUMERIC_REGEX\n\n return regex.test(value)\n}\n\ninterface PinInputContext {\n styles: { [key: string]: CSSUIObject | undefined }\n getInputProps: (\n props: {\n index: number\n ref?: Ref<HTMLInputElement>\n } & PinInputFieldProps,\n ) => PinInputFieldProps\n}\n\nconst [PinInputProvider, usePinInputContext] = createContext<PinInputContext>({\n name: \"PinInputContext\",\n errorMessage: `PinInputContext returned is 'undefined'. Seems you forgot to wrap the components in \"<PinInput />\"`,\n})\n\nconst { DescendantsContextProvider, useDescendant, useDescendants } =\n createDescendant<HTMLInputElement>()\n\ninterface PinInputOptions {\n /**\n * The top-level id string that will be applied to the input fields.\n * The index of the input will be appended to this top-level id.\n */\n id?: string\n /**\n * The type of values the pin-input should allow.\n *\n * @default 'number'\n */\n type?: \"alphanumeric\" | \"number\"\n /**\n * If `true`, the pin input receives focus on mount.\n *\n * @default false\n */\n autoFocus?: boolean\n /**\n * The initial value of the pin input.\n */\n defaultValue?: string\n /**\n * The border color when the input is invalid.\n */\n errorBorderColor?: ColorModeToken<CSS.Property.BorderColor, \"colors\">\n /**\n * The border color when the input is focused.\n */\n focusBorderColor?: ColorModeToken<CSS.Property.BorderColor, \"colors\">\n /**\n * The number of inputs to display.\n *\n * @default 4\n */\n items?: number\n /**\n * If `true`, focus will move automatically to the next input once filled.\n *\n * @default true\n */\n manageFocus?: boolean\n /**\n * If `true`, the input's value will be masked just like `type=password`.\n */\n mask?: boolean\n /**\n * If `true`, the pin input component signals to its fields that they should.\n */\n otp?: boolean\n /**\n * The placeholder for the pin input.\n *\n * @default '○'\n */\n placeholder?: string\n /**\n * The value of the pin input.\n */\n value?: string\n /**\n * Function called on input change.\n */\n onChange?: (value: string) => void\n /**\n * Function called when all inputs have valid values.\n */\n onComplete?: (value: string) => void\n}\n\nexport interface PinInputProps\n extends Omit<HTMLUIProps, \"defaultValue\" | \"mask\" | \"onChange\">,\n ThemeProps<\"PinInput\">,\n FormControlOptions,\n PinInputOptions {}\n\n/**\n * `PinInput` is a component used to capture pin codes or OTP (One-Time Password) inputs.\n *\n * @see Docs https://yamada-ui.com/components/forms/pin-input\n */\nexport const PinInput = forwardRef<PinInputProps, \"div\">(\n ({ errorBorderColor, focusBorderColor, ...props }, ref) => {\n const [styles, mergedProps] = useComponentMultiStyle(\"PinInput\", {\n errorBorderColor,\n focusBorderColor,\n ...props,\n })\n let {\n id,\n type = \"number\",\n className,\n autoFocus,\n children,\n defaultValue,\n items = 4,\n manageFocus = true,\n mask,\n otp = false,\n placeholder = \"○\",\n value,\n onChange: onChangeProp,\n onComplete,\n ...rest\n } = useFormControlProps(omitThemeProps(mergedProps))\n const [\n {\n \"aria-readonly\": _ariaReadonly,\n disabled,\n readOnly,\n ...formControlProps\n },\n containerProps,\n ] = splitObject(rest, formControlProperties)\n const uuid = useId()\n\n id ??= uuid\n\n const descendants = useDescendants()\n\n const [moveFocus, setMoveFocus] = useState<boolean>(true)\n const [focusedIndex, setFocusedIndex] = useState<number>(-1)\n\n useEffect(() => {\n if (!autoFocus) return\n\n const firstValue = descendants.firstValue()\n\n if (!firstValue) return\n\n requestAnimationFrame(() => firstValue.node.focus())\n }, [autoFocus, descendants])\n\n const [values, setValues] = useControllableState<string[]>({\n defaultValue: toArray(defaultValue) || [],\n value: toArray(value),\n onChange: (values) => onChangeProp?.(values.join(\"\")),\n })\n\n const focusNext = useCallback(\n (index: number) => {\n if (!moveFocus || !manageFocus) return\n\n const next = descendants.nextValue(index, undefined, false)\n\n if (!next) return\n\n requestAnimationFrame(() => next.node.focus())\n },\n [descendants, moveFocus, manageFocus],\n )\n\n const focusInputField = useCallback(\n (direction: \"next\" | \"prev\", index: number) => {\n const input =\n direction === \"next\"\n ? descendants.nextValue(index, undefined, false)\n : descendants.prevValue(index, undefined, false)\n\n if (!input) return\n\n const valueLength = input.node.value.length\n\n requestAnimationFrame(() => {\n input.node.focus()\n input.node.setSelectionRange(0, valueLength)\n })\n },\n [descendants],\n )\n\n const setValue = useCallback(\n (value: string, index: number, isFocus = true) => {\n let nextValues = [...values]\n\n nextValues[index] = value\n\n setValues(nextValues)\n\n nextValues = nextValues.filter(Boolean)\n\n const isComplete =\n value !== \"\" && nextValues.length === descendants.count()\n\n if (isComplete) {\n onComplete?.(nextValues.join(\"\"))\n descendants.value(index)?.node.blur()\n } else if (isFocus) {\n focusNext(index)\n }\n },\n [values, setValues, descendants, onComplete, focusNext],\n )\n\n const getNextValue = useCallback(\n (value: string | undefined, eventValue: string) => {\n let nextValue = eventValue\n\n if (!value?.length) return nextValue\n\n if (value.startsWith(eventValue.charAt(0))) {\n nextValue = eventValue.charAt(1)\n } else if (value.startsWith(eventValue.charAt(1))) {\n nextValue = eventValue.charAt(0)\n }\n\n return nextValue\n },\n [],\n )\n\n const onChange = useCallback(\n (index: number) =>\n ({ target }: ChangeEvent<HTMLInputElement>) => {\n const eventValue = target.value\n const currentValue = values[index]\n const nextValue = getNextValue(currentValue, eventValue)\n\n if (nextValue === \"\") {\n setValue(\"\", index)\n\n return\n }\n\n if (eventValue.length > 2) {\n if (!validate(eventValue, type)) return\n\n const nextValue = eventValue\n .split(\"\")\n .filter((_, index) => index < descendants.count())\n\n setValues(nextValue)\n\n if (nextValue.length === descendants.count()) {\n onComplete?.(nextValue.join(\"\"))\n descendants.value(index)?.node.blur()\n }\n } else {\n if (validate(nextValue, type)) setValue(nextValue, index)\n\n setMoveFocus(true)\n }\n },\n [\n descendants,\n getNextValue,\n onComplete,\n setValue,\n setValues,\n type,\n values,\n ],\n )\n\n const onKeyDown = useCallback(\n (index: number) => (ev: KeyboardEvent<HTMLInputElement>) => {\n if (!manageFocus) return\n\n const actions: { [key: string]: Function | undefined } = {\n ArrowLeft: () => {\n ev.preventDefault()\n focusInputField(\"prev\", index)\n },\n ArrowRight: () => {\n ev.preventDefault()\n focusInputField(\"next\", index)\n },\n Backspace: () => {\n if ((ev.target as HTMLInputElement).value === \"\") {\n const prevInput = descendants.prevValue(index, undefined, false)\n\n if (!prevInput) return\n\n setValue(\"\", index - 1, false)\n prevInput.node.focus()\n setMoveFocus(true)\n } else {\n setMoveFocus(false)\n }\n },\n }\n\n const action = actions[ev.key]\n\n if (!action) return\n\n action()\n },\n [descendants, focusInputField, manageFocus, setValue],\n )\n\n const onFocus = useCallback(\n (index: number) => () => setFocusedIndex(index),\n [],\n )\n\n const onBlur = useCallback(() => setFocusedIndex(-1), [])\n\n const getInputProps = useCallback(\n ({\n index,\n ...props\n }: {\n index: number\n ref?: Ref<HTMLInputElement>\n } & PinInputFieldProps): PinInputFieldProps => ({\n type: mask ? \"password\" : type === \"number\" ? \"tel\" : \"text\",\n disabled,\n inputMode: type === \"number\" ? \"numeric\" : \"text\",\n readOnly,\n ...formControlProps,\n ...filterUndefined(props),\n id: `${id}-${index}`,\n autoComplete: otp ? \"one-time-code\" : \"off\",\n placeholder:\n focusedIndex === index && !readOnly && !props.readOnly\n ? \"\"\n : placeholder,\n value: values[index] || \"\",\n onBlur: handlerAll(props.onBlur, onBlur),\n onChange: handlerAll(props.onChange, onChange(index)),\n onFocus: handlerAll(props.onFocus, onFocus(index)),\n onKeyDown: handlerAll(props.onKeyDown, onKeyDown(index)),\n }),\n [\n type,\n mask,\n formControlProps,\n id,\n values,\n onChange,\n onKeyDown,\n onFocus,\n onBlur,\n otp,\n focusedIndex,\n disabled,\n readOnly,\n placeholder,\n ],\n )\n\n const css: CSSUIObject = {\n alignItems: \"center\",\n display: \"flex\",\n ...styles.container,\n }\n\n let cloneChildren = getValidChildren(children)\n\n if (!cloneChildren.length)\n for (let i = 0; i < items; i++) {\n cloneChildren.push(<PinInputField key={i} />)\n }\n\n return (\n <DescendantsContextProvider value={descendants}>\n <PinInputProvider value={{ styles, getInputProps }}>\n <ui.div\n ref={ref}\n className={cx(\"ui-pin-input\", className)}\n role=\"group\"\n __css={css}\n {...formControlProps}\n {...containerProps}\n >\n {cloneChildren}\n </ui.div>\n </PinInputProvider>\n </DescendantsContextProvider>\n )\n },\n)\n\nPinInput.displayName = \"PinInput\"\nPinInput.__ui__ = \"PinInput\"\n\nexport interface PinInputFieldProps\n extends HTMLUIProps<\"input\">,\n FormControlOptions {}\n\nexport const PinInputField = forwardRef<PinInputFieldProps, \"input\">(\n ({ className, ...rest }, ref) => {\n const { styles, getInputProps } = usePinInputContext()\n const { index, register } = useDescendant()\n\n rest = useFormControlProps(rest)\n\n const css: CSSUIObject = { ...styles.field }\n\n return (\n <ui.input\n className={cx(\"ui-pin-input__field\", className)}\n {...getInputProps({ ...rest, ref: mergeRefs(register, ref), index })}\n __css={css}\n />\n )\n },\n)\n\nPinInputField.displayName = \"PinInputField\"\nPinInputField.__ui__ = \"PinInputField\"\n"],"mappings":"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","names":["values","value","nextValue","index","props"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/pin-input.tsx"],"sourcesContent":["export { PinInput, PinInputField } from \"./pin-input\"\nexport type { PinInputFieldProps, PinInputProps } from \"./pin-input\"\n","import type {\n ColorModeToken,\n CSS,\n CSSUIObject,\n HTMLUIProps,\n ThemeProps,\n} from \"@yamada-ui/core\"\nimport type { FormControlOptions } from \"@yamada-ui/form-control\"\nimport type { ChangeEvent, KeyboardEvent, Ref } from \"react\"\nimport {\n forwardRef,\n omitThemeProps,\n ui,\n useComponentMultiStyle,\n} from \"@yamada-ui/core\"\nimport {\n formControlProperties,\n useFormControlProps,\n} from \"@yamada-ui/form-control\"\nimport { useControllableState } from \"@yamada-ui/use-controllable-state\"\nimport { createDescendant } from \"@yamada-ui/use-descendant\"\nimport {\n createContext,\n cx,\n filterUndefined,\n getValidChildren,\n handlerAll,\n mergeRefs,\n splitObject,\n} from \"@yamada-ui/utils\"\nimport { useCallback, useEffect, useId, useState } from \"react\"\n\nconst toArray = (value?: string) => value?.split(\"\")\n\nconst validate = (value: string, type: PinInputProps[\"type\"]) => {\n const NUMERIC_REGEX = /^[0-9]+$/\n const ALPHA_NUMERIC_REGEX = /^[a-zA-Z0-9]+$/i\n\n const regex = type === \"alphanumeric\" ? ALPHA_NUMERIC_REGEX : NUMERIC_REGEX\n\n return regex.test(value)\n}\n\ninterface PinInputContext {\n styles: { [key: string]: CSSUIObject | undefined }\n getInputProps: (\n props: {\n index: number\n ref?: Ref<HTMLInputElement>\n } & PinInputFieldProps,\n ) => PinInputFieldProps\n}\n\nconst [PinInputProvider, usePinInputContext] = createContext<PinInputContext>({\n name: \"PinInputContext\",\n errorMessage: `PinInputContext returned is 'undefined'. Seems you forgot to wrap the components in \"<PinInput />\"`,\n})\n\nconst { DescendantsContextProvider, useDescendant, useDescendants } =\n createDescendant<HTMLInputElement>()\n\ninterface PinInputOptions {\n /**\n * The top-level id string that will be applied to the input fields.\n * The index of the input will be appended to this top-level id.\n */\n id?: string\n /**\n * The type of values the pin-input should allow.\n *\n * @default 'number'\n */\n type?: \"alphanumeric\" | \"number\"\n /**\n * If `true`, the pin input receives focus on mount.\n *\n * @default false\n */\n autoFocus?: boolean\n /**\n * The initial value of the pin input.\n */\n defaultValue?: string\n /**\n * The border color when the input is invalid.\n */\n errorBorderColor?: ColorModeToken<CSS.Property.BorderColor, \"colors\">\n /**\n * The border color when the input is focused.\n */\n focusBorderColor?: ColorModeToken<CSS.Property.BorderColor, \"colors\">\n /**\n * The number of inputs to display.\n *\n * @default 4\n */\n items?: number\n /**\n * If `true`, focus will move automatically to the next input once filled.\n *\n * @default true\n */\n manageFocus?: boolean\n /**\n * If `true`, the input's value will be masked just like `type=password`.\n */\n mask?: boolean\n /**\n * If `true`, the pin input component signals to its fields that they should.\n */\n otp?: boolean\n /**\n * The placeholder for the pin input.\n *\n * @default '○'\n */\n placeholder?: string\n /**\n * The value of the pin input.\n */\n value?: string\n /**\n * Function called on input change.\n */\n onChange?: (value: string) => void\n /**\n * Function called when all inputs have valid values.\n */\n onComplete?: (value: string) => void\n}\n\nexport interface PinInputProps\n extends Omit<HTMLUIProps, \"defaultValue\" | \"mask\" | \"onChange\">,\n ThemeProps<\"PinInput\">,\n FormControlOptions,\n PinInputOptions {}\n\n/**\n * `PinInput` is a component used to capture pin codes or OTP (One-Time Password) inputs.\n *\n * @see Docs https://yamada-ui.com/components/forms/pin-input\n */\nexport const PinInput = forwardRef<PinInputProps, \"div\">(\n ({ errorBorderColor, focusBorderColor, ...props }, ref) => {\n const [styles, mergedProps] = useComponentMultiStyle(\"PinInput\", {\n errorBorderColor,\n focusBorderColor,\n ...props,\n })\n const uuid = useId()\n const {\n id = uuid,\n type = \"number\",\n className,\n autoFocus,\n children,\n defaultValue,\n items = 4,\n manageFocus = true,\n mask,\n otp = false,\n placeholder = \"○\",\n value,\n onChange: onChangeProp,\n onComplete,\n ...rest\n } = useFormControlProps(omitThemeProps(mergedProps))\n const [\n {\n \"aria-readonly\": _ariaReadonly,\n disabled,\n readOnly,\n ...formControlProps\n },\n containerProps,\n ] = splitObject(rest, formControlProperties)\n const descendants = useDescendants()\n const [moveFocus, setMoveFocus] = useState<boolean>(true)\n const [focusedIndex, setFocusedIndex] = useState<number>(-1)\n const [values, setValues] = useControllableState<string[]>({\n defaultValue: toArray(defaultValue) || [],\n value: toArray(value),\n onChange: (values) => onChangeProp?.(values.join(\"\")),\n })\n const css: CSSUIObject = {\n alignItems: \"center\",\n display: \"flex\",\n ...styles.container,\n }\n\n const focusNext = useCallback(\n (index: number) => {\n if (!moveFocus || !manageFocus) return\n\n const next = descendants.nextValue(index, undefined, false)\n\n if (!next) return\n\n requestAnimationFrame(() => next.node.focus())\n },\n [descendants, moveFocus, manageFocus],\n )\n\n const focusInputField = useCallback(\n (direction: \"next\" | \"prev\", index: number) => {\n const input =\n direction === \"next\"\n ? descendants.nextValue(index, undefined, false)\n : descendants.prevValue(index, undefined, false)\n\n if (!input) return\n\n const valueLength = input.node.value.length\n\n requestAnimationFrame(() => {\n input.node.focus()\n input.node.setSelectionRange(0, valueLength)\n })\n },\n [descendants],\n )\n\n const setValue = useCallback(\n (value: string, index: number, isFocus = true) => {\n let nextValues = [...values]\n\n nextValues[index] = value\n\n setValues(nextValues)\n\n nextValues = nextValues.filter(Boolean)\n\n const isComplete =\n value !== \"\" && nextValues.length === descendants.count()\n\n if (isComplete) {\n onComplete?.(nextValues.join(\"\"))\n descendants.value(index)?.node.blur()\n } else if (isFocus) {\n focusNext(index)\n }\n },\n [values, setValues, descendants, onComplete, focusNext],\n )\n\n const getNextValue = useCallback(\n (value: string | undefined, eventValue: string) => {\n let nextValue = eventValue\n\n if (!value?.length) return nextValue\n\n if (value.startsWith(eventValue.charAt(0))) {\n nextValue = eventValue.charAt(1)\n } else if (value.startsWith(eventValue.charAt(1))) {\n nextValue = eventValue.charAt(0)\n }\n\n return nextValue\n },\n [],\n )\n\n const onChange = useCallback(\n (index: number) =>\n ({ target }: ChangeEvent<HTMLInputElement>) => {\n const eventValue = target.value\n const currentValue = values[index]\n const nextValue = getNextValue(currentValue, eventValue)\n\n if (nextValue === \"\") {\n setValue(\"\", index)\n\n return\n }\n\n if (eventValue.length > 2) {\n if (!validate(eventValue, type)) return\n\n const nextValue = eventValue\n .split(\"\")\n .filter((_, index) => index < descendants.count())\n\n setValues(nextValue)\n\n if (nextValue.length === descendants.count()) {\n onComplete?.(nextValue.join(\"\"))\n descendants.value(index)?.node.blur()\n }\n } else {\n if (validate(nextValue, type)) setValue(nextValue, index)\n\n setMoveFocus(true)\n }\n },\n [\n descendants,\n getNextValue,\n onComplete,\n setValue,\n setValues,\n type,\n values,\n ],\n )\n\n const onKeyDown = useCallback(\n (index: number) => (ev: KeyboardEvent<HTMLInputElement>) => {\n if (!manageFocus) return\n\n const actions: { [key: string]: Function | undefined } = {\n ArrowLeft: () => {\n ev.preventDefault()\n focusInputField(\"prev\", index)\n },\n ArrowRight: () => {\n ev.preventDefault()\n focusInputField(\"next\", index)\n },\n Backspace: () => {\n if ((ev.target as HTMLInputElement).value === \"\") {\n const prevInput = descendants.prevValue(index, undefined, false)\n\n if (!prevInput) return\n\n setValue(\"\", index - 1, false)\n prevInput.node.focus()\n setMoveFocus(true)\n } else {\n setMoveFocus(false)\n }\n },\n }\n\n const action = actions[ev.key]\n\n if (!action) return\n\n action()\n },\n [descendants, focusInputField, manageFocus, setValue],\n )\n\n const onFocus = useCallback(\n (index: number) => () => setFocusedIndex(index),\n [],\n )\n\n const onBlur = useCallback(() => setFocusedIndex(-1), [])\n\n useEffect(() => {\n if (!autoFocus) return\n\n const firstValue = descendants.firstValue()\n\n if (!firstValue) return\n\n requestAnimationFrame(() => firstValue.node.focus())\n }, [autoFocus, descendants])\n\n const getInputProps = useCallback(\n ({\n index,\n ...props\n }: {\n index: number\n ref?: Ref<HTMLInputElement>\n } & PinInputFieldProps): PinInputFieldProps => ({\n type: mask ? \"password\" : type === \"number\" ? \"tel\" : \"text\",\n disabled,\n inputMode: type === \"number\" ? \"numeric\" : \"text\",\n readOnly,\n ...formControlProps,\n ...filterUndefined(props),\n id: `${id}-${index}`,\n autoComplete: otp ? \"one-time-code\" : \"off\",\n placeholder:\n focusedIndex === index && !readOnly && !props.readOnly\n ? \"\"\n : placeholder,\n value: values[index] || \"\",\n onBlur: handlerAll(props.onBlur, onBlur),\n onChange: handlerAll(props.onChange, onChange(index)),\n onFocus: handlerAll(props.onFocus, onFocus(index)),\n onKeyDown: handlerAll(props.onKeyDown, onKeyDown(index)),\n }),\n [\n type,\n mask,\n formControlProps,\n id,\n values,\n onChange,\n onKeyDown,\n onFocus,\n onBlur,\n otp,\n focusedIndex,\n disabled,\n readOnly,\n placeholder,\n ],\n )\n\n let cloneChildren = getValidChildren(children)\n\n if (!cloneChildren.length)\n for (let i = 0; i < items; i++) {\n cloneChildren.push(<PinInputField key={i} />)\n }\n\n return (\n <DescendantsContextProvider value={descendants}>\n <PinInputProvider value={{ styles, getInputProps }}>\n <ui.div\n ref={ref}\n className={cx(\"ui-pin-input\", className)}\n role=\"group\"\n __css={css}\n {...formControlProps}\n {...containerProps}\n >\n {cloneChildren}\n </ui.div>\n </PinInputProvider>\n </DescendantsContextProvider>\n )\n },\n)\n\nPinInput.displayName = \"PinInput\"\nPinInput.__ui__ = \"PinInput\"\n\nexport interface PinInputFieldProps\n extends HTMLUIProps<\"input\">,\n FormControlOptions {}\n\nexport const PinInputField = forwardRef<PinInputFieldProps, \"input\">(\n ({ className, ...rest }, ref) => {\n const { styles, getInputProps } = usePinInputContext()\n const { index, register } = useDescendant()\n const css: CSSUIObject = { ...styles.field }\n\n rest = useFormControlProps(rest)\n\n return (\n <ui.input\n className={cx(\"ui-pin-input__field\", className)}\n {...getInputProps({ ...rest, ref: mergeRefs(register, ref), index })}\n __css={css}\n />\n )\n },\n)\n\nPinInputField.displayName = \"PinInputField\"\nPinInputField.__ui__ = \"PinInputField\"\n"],"mappings":"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","names":["values","value","nextValue","index","props"]}
package/dist/index.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  PinInput,
4
4
  PinInputField
5
- } from "./chunk-TU5BZGLV.mjs";
5
+ } from "./chunk-SUK2AVTG.mjs";
6
6
  export {
7
7
  PinInput,
8
8
  PinInputField
package/dist/pin-input.js CHANGED
@@ -51,8 +51,9 @@ var PinInput = (0, import_core.forwardRef)(
51
51
  focusBorderColor,
52
52
  ...props
53
53
  });
54
- let {
55
- id,
54
+ const uuid = (0, import_react.useId)();
55
+ const {
56
+ id = uuid,
56
57
  type = "number",
57
58
  className,
58
59
  autoFocus,
@@ -77,22 +78,19 @@ var PinInput = (0, import_core.forwardRef)(
77
78
  },
78
79
  containerProps
79
80
  ] = (0, import_utils.splitObject)(rest, import_form_control.formControlProperties);
80
- const uuid = (0, import_react.useId)();
81
- id != null ? id : id = uuid;
82
81
  const descendants = useDescendants();
83
82
  const [moveFocus, setMoveFocus] = (0, import_react.useState)(true);
84
83
  const [focusedIndex, setFocusedIndex] = (0, import_react.useState)(-1);
85
- (0, import_react.useEffect)(() => {
86
- if (!autoFocus) return;
87
- const firstValue = descendants.firstValue();
88
- if (!firstValue) return;
89
- requestAnimationFrame(() => firstValue.node.focus());
90
- }, [autoFocus, descendants]);
91
84
  const [values, setValues] = (0, import_use_controllable_state.useControllableState)({
92
85
  defaultValue: toArray(defaultValue) || [],
93
86
  value: toArray(value),
94
87
  onChange: (values2) => onChangeProp == null ? void 0 : onChangeProp(values2.join(""))
95
88
  });
89
+ const css = {
90
+ alignItems: "center",
91
+ display: "flex",
92
+ ...styles.container
93
+ };
96
94
  const focusNext = (0, import_react.useCallback)(
97
95
  (index) => {
98
96
  if (!moveFocus || !manageFocus) return;
@@ -212,6 +210,12 @@ var PinInput = (0, import_core.forwardRef)(
212
210
  []
213
211
  );
214
212
  const onBlur = (0, import_react.useCallback)(() => setFocusedIndex(-1), []);
213
+ (0, import_react.useEffect)(() => {
214
+ if (!autoFocus) return;
215
+ const firstValue = descendants.firstValue();
216
+ if (!firstValue) return;
217
+ requestAnimationFrame(() => firstValue.node.focus());
218
+ }, [autoFocus, descendants]);
215
219
  const getInputProps = (0, import_react.useCallback)(
216
220
  ({
217
221
  index,
@@ -249,11 +253,6 @@ var PinInput = (0, import_core.forwardRef)(
249
253
  placeholder
250
254
  ]
251
255
  );
252
- const css = {
253
- alignItems: "center",
254
- display: "flex",
255
- ...styles.container
256
- };
257
256
  let cloneChildren = (0, import_utils.getValidChildren)(children);
258
257
  if (!cloneChildren.length)
259
258
  for (let i = 0; i < items; i++) {
@@ -279,8 +278,8 @@ var PinInputField = (0, import_core.forwardRef)(
279
278
  ({ className, ...rest }, ref) => {
280
279
  const { styles, getInputProps } = usePinInputContext();
281
280
  const { index, register } = useDescendant();
282
- rest = (0, import_form_control.useFormControlProps)(rest);
283
281
  const css = { ...styles.field };
282
+ rest = (0, import_form_control.useFormControlProps)(rest);
284
283
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
285
284
  import_core.ui.input,
286
285
  {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/pin-input.tsx"],"sourcesContent":["import type {\n ColorModeToken,\n CSS,\n CSSUIObject,\n HTMLUIProps,\n ThemeProps,\n} from \"@yamada-ui/core\"\nimport type { FormControlOptions } from \"@yamada-ui/form-control\"\nimport type { ChangeEvent, KeyboardEvent, Ref } from \"react\"\nimport {\n forwardRef,\n omitThemeProps,\n ui,\n useComponentMultiStyle,\n} from \"@yamada-ui/core\"\nimport {\n formControlProperties,\n useFormControlProps,\n} from \"@yamada-ui/form-control\"\nimport { useControllableState } from \"@yamada-ui/use-controllable-state\"\nimport { createDescendant } from \"@yamada-ui/use-descendant\"\nimport {\n createContext,\n cx,\n filterUndefined,\n getValidChildren,\n handlerAll,\n mergeRefs,\n splitObject,\n} from \"@yamada-ui/utils\"\nimport { useCallback, useEffect, useId, useState } from \"react\"\n\nconst toArray = (value?: string) => value?.split(\"\")\n\nconst validate = (value: string, type: PinInputProps[\"type\"]) => {\n const NUMERIC_REGEX = /^[0-9]+$/\n const ALPHA_NUMERIC_REGEX = /^[a-zA-Z0-9]+$/i\n\n const regex = type === \"alphanumeric\" ? ALPHA_NUMERIC_REGEX : NUMERIC_REGEX\n\n return regex.test(value)\n}\n\ninterface PinInputContext {\n styles: { [key: string]: CSSUIObject | undefined }\n getInputProps: (\n props: {\n index: number\n ref?: Ref<HTMLInputElement>\n } & PinInputFieldProps,\n ) => PinInputFieldProps\n}\n\nconst [PinInputProvider, usePinInputContext] = createContext<PinInputContext>({\n name: \"PinInputContext\",\n errorMessage: `PinInputContext returned is 'undefined'. Seems you forgot to wrap the components in \"<PinInput />\"`,\n})\n\nconst { DescendantsContextProvider, useDescendant, useDescendants } =\n createDescendant<HTMLInputElement>()\n\ninterface PinInputOptions {\n /**\n * The top-level id string that will be applied to the input fields.\n * The index of the input will be appended to this top-level id.\n */\n id?: string\n /**\n * The type of values the pin-input should allow.\n *\n * @default 'number'\n */\n type?: \"alphanumeric\" | \"number\"\n /**\n * If `true`, the pin input receives focus on mount.\n *\n * @default false\n */\n autoFocus?: boolean\n /**\n * The initial value of the pin input.\n */\n defaultValue?: string\n /**\n * The border color when the input is invalid.\n */\n errorBorderColor?: ColorModeToken<CSS.Property.BorderColor, \"colors\">\n /**\n * The border color when the input is focused.\n */\n focusBorderColor?: ColorModeToken<CSS.Property.BorderColor, \"colors\">\n /**\n * The number of inputs to display.\n *\n * @default 4\n */\n items?: number\n /**\n * If `true`, focus will move automatically to the next input once filled.\n *\n * @default true\n */\n manageFocus?: boolean\n /**\n * If `true`, the input's value will be masked just like `type=password`.\n */\n mask?: boolean\n /**\n * If `true`, the pin input component signals to its fields that they should.\n */\n otp?: boolean\n /**\n * The placeholder for the pin input.\n *\n * @default '○'\n */\n placeholder?: string\n /**\n * The value of the pin input.\n */\n value?: string\n /**\n * Function called on input change.\n */\n onChange?: (value: string) => void\n /**\n * Function called when all inputs have valid values.\n */\n onComplete?: (value: string) => void\n}\n\nexport interface PinInputProps\n extends Omit<HTMLUIProps, \"defaultValue\" | \"mask\" | \"onChange\">,\n ThemeProps<\"PinInput\">,\n FormControlOptions,\n PinInputOptions {}\n\n/**\n * `PinInput` is a component used to capture pin codes or OTP (One-Time Password) inputs.\n *\n * @see Docs https://yamada-ui.com/components/forms/pin-input\n */\nexport const PinInput = forwardRef<PinInputProps, \"div\">(\n ({ errorBorderColor, focusBorderColor, ...props }, ref) => {\n const [styles, mergedProps] = useComponentMultiStyle(\"PinInput\", {\n errorBorderColor,\n focusBorderColor,\n ...props,\n })\n let {\n id,\n type = \"number\",\n className,\n autoFocus,\n children,\n defaultValue,\n items = 4,\n manageFocus = true,\n mask,\n otp = false,\n placeholder = \"○\",\n value,\n onChange: onChangeProp,\n onComplete,\n ...rest\n } = useFormControlProps(omitThemeProps(mergedProps))\n const [\n {\n \"aria-readonly\": _ariaReadonly,\n disabled,\n readOnly,\n ...formControlProps\n },\n containerProps,\n ] = splitObject(rest, formControlProperties)\n const uuid = useId()\n\n id ??= uuid\n\n const descendants = useDescendants()\n\n const [moveFocus, setMoveFocus] = useState<boolean>(true)\n const [focusedIndex, setFocusedIndex] = useState<number>(-1)\n\n useEffect(() => {\n if (!autoFocus) return\n\n const firstValue = descendants.firstValue()\n\n if (!firstValue) return\n\n requestAnimationFrame(() => firstValue.node.focus())\n }, [autoFocus, descendants])\n\n const [values, setValues] = useControllableState<string[]>({\n defaultValue: toArray(defaultValue) || [],\n value: toArray(value),\n onChange: (values) => onChangeProp?.(values.join(\"\")),\n })\n\n const focusNext = useCallback(\n (index: number) => {\n if (!moveFocus || !manageFocus) return\n\n const next = descendants.nextValue(index, undefined, false)\n\n if (!next) return\n\n requestAnimationFrame(() => next.node.focus())\n },\n [descendants, moveFocus, manageFocus],\n )\n\n const focusInputField = useCallback(\n (direction: \"next\" | \"prev\", index: number) => {\n const input =\n direction === \"next\"\n ? descendants.nextValue(index, undefined, false)\n : descendants.prevValue(index, undefined, false)\n\n if (!input) return\n\n const valueLength = input.node.value.length\n\n requestAnimationFrame(() => {\n input.node.focus()\n input.node.setSelectionRange(0, valueLength)\n })\n },\n [descendants],\n )\n\n const setValue = useCallback(\n (value: string, index: number, isFocus = true) => {\n let nextValues = [...values]\n\n nextValues[index] = value\n\n setValues(nextValues)\n\n nextValues = nextValues.filter(Boolean)\n\n const isComplete =\n value !== \"\" && nextValues.length === descendants.count()\n\n if (isComplete) {\n onComplete?.(nextValues.join(\"\"))\n descendants.value(index)?.node.blur()\n } else if (isFocus) {\n focusNext(index)\n }\n },\n [values, setValues, descendants, onComplete, focusNext],\n )\n\n const getNextValue = useCallback(\n (value: string | undefined, eventValue: string) => {\n let nextValue = eventValue\n\n if (!value?.length) return nextValue\n\n if (value.startsWith(eventValue.charAt(0))) {\n nextValue = eventValue.charAt(1)\n } else if (value.startsWith(eventValue.charAt(1))) {\n nextValue = eventValue.charAt(0)\n }\n\n return nextValue\n },\n [],\n )\n\n const onChange = useCallback(\n (index: number) =>\n ({ target }: ChangeEvent<HTMLInputElement>) => {\n const eventValue = target.value\n const currentValue = values[index]\n const nextValue = getNextValue(currentValue, eventValue)\n\n if (nextValue === \"\") {\n setValue(\"\", index)\n\n return\n }\n\n if (eventValue.length > 2) {\n if (!validate(eventValue, type)) return\n\n const nextValue = eventValue\n .split(\"\")\n .filter((_, index) => index < descendants.count())\n\n setValues(nextValue)\n\n if (nextValue.length === descendants.count()) {\n onComplete?.(nextValue.join(\"\"))\n descendants.value(index)?.node.blur()\n }\n } else {\n if (validate(nextValue, type)) setValue(nextValue, index)\n\n setMoveFocus(true)\n }\n },\n [\n descendants,\n getNextValue,\n onComplete,\n setValue,\n setValues,\n type,\n values,\n ],\n )\n\n const onKeyDown = useCallback(\n (index: number) => (ev: KeyboardEvent<HTMLInputElement>) => {\n if (!manageFocus) return\n\n const actions: { [key: string]: Function | undefined } = {\n ArrowLeft: () => {\n ev.preventDefault()\n focusInputField(\"prev\", index)\n },\n ArrowRight: () => {\n ev.preventDefault()\n focusInputField(\"next\", index)\n },\n Backspace: () => {\n if ((ev.target as HTMLInputElement).value === \"\") {\n const prevInput = descendants.prevValue(index, undefined, false)\n\n if (!prevInput) return\n\n setValue(\"\", index - 1, false)\n prevInput.node.focus()\n setMoveFocus(true)\n } else {\n setMoveFocus(false)\n }\n },\n }\n\n const action = actions[ev.key]\n\n if (!action) return\n\n action()\n },\n [descendants, focusInputField, manageFocus, setValue],\n )\n\n const onFocus = useCallback(\n (index: number) => () => setFocusedIndex(index),\n [],\n )\n\n const onBlur = useCallback(() => setFocusedIndex(-1), [])\n\n const getInputProps = useCallback(\n ({\n index,\n ...props\n }: {\n index: number\n ref?: Ref<HTMLInputElement>\n } & PinInputFieldProps): PinInputFieldProps => ({\n type: mask ? \"password\" : type === \"number\" ? \"tel\" : \"text\",\n disabled,\n inputMode: type === \"number\" ? \"numeric\" : \"text\",\n readOnly,\n ...formControlProps,\n ...filterUndefined(props),\n id: `${id}-${index}`,\n autoComplete: otp ? \"one-time-code\" : \"off\",\n placeholder:\n focusedIndex === index && !readOnly && !props.readOnly\n ? \"\"\n : placeholder,\n value: values[index] || \"\",\n onBlur: handlerAll(props.onBlur, onBlur),\n onChange: handlerAll(props.onChange, onChange(index)),\n onFocus: handlerAll(props.onFocus, onFocus(index)),\n onKeyDown: handlerAll(props.onKeyDown, onKeyDown(index)),\n }),\n [\n type,\n mask,\n formControlProps,\n id,\n values,\n onChange,\n onKeyDown,\n onFocus,\n onBlur,\n otp,\n focusedIndex,\n disabled,\n readOnly,\n placeholder,\n ],\n )\n\n const css: CSSUIObject = {\n alignItems: \"center\",\n display: \"flex\",\n ...styles.container,\n }\n\n let cloneChildren = getValidChildren(children)\n\n if (!cloneChildren.length)\n for (let i = 0; i < items; i++) {\n cloneChildren.push(<PinInputField key={i} />)\n }\n\n return (\n <DescendantsContextProvider value={descendants}>\n <PinInputProvider value={{ styles, getInputProps }}>\n <ui.div\n ref={ref}\n className={cx(\"ui-pin-input\", className)}\n role=\"group\"\n __css={css}\n {...formControlProps}\n {...containerProps}\n >\n {cloneChildren}\n </ui.div>\n </PinInputProvider>\n </DescendantsContextProvider>\n )\n },\n)\n\nPinInput.displayName = \"PinInput\"\nPinInput.__ui__ = \"PinInput\"\n\nexport interface PinInputFieldProps\n extends HTMLUIProps<\"input\">,\n FormControlOptions {}\n\nexport const PinInputField = forwardRef<PinInputFieldProps, \"input\">(\n ({ className, ...rest }, ref) => {\n const { styles, getInputProps } = usePinInputContext()\n const { index, register } = useDescendant()\n\n rest = useFormControlProps(rest)\n\n const css: CSSUIObject = { ...styles.field }\n\n return (\n <ui.input\n className={cx(\"ui-pin-input__field\", className)}\n {...getInputProps({ ...rest, ref: mergeRefs(register, ref), index })}\n __css={css}\n />\n )\n },\n)\n\nPinInputField.displayName = \"PinInputField\"\nPinInputField.__ui__ = \"PinInputField\"\n"],"mappings":"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","names":["values","value","nextValue","index","props"]}
1
+ {"version":3,"sources":["../src/pin-input.tsx"],"sourcesContent":["import type {\n ColorModeToken,\n CSS,\n CSSUIObject,\n HTMLUIProps,\n ThemeProps,\n} from \"@yamada-ui/core\"\nimport type { FormControlOptions } from \"@yamada-ui/form-control\"\nimport type { ChangeEvent, KeyboardEvent, Ref } from \"react\"\nimport {\n forwardRef,\n omitThemeProps,\n ui,\n useComponentMultiStyle,\n} from \"@yamada-ui/core\"\nimport {\n formControlProperties,\n useFormControlProps,\n} from \"@yamada-ui/form-control\"\nimport { useControllableState } from \"@yamada-ui/use-controllable-state\"\nimport { createDescendant } from \"@yamada-ui/use-descendant\"\nimport {\n createContext,\n cx,\n filterUndefined,\n getValidChildren,\n handlerAll,\n mergeRefs,\n splitObject,\n} from \"@yamada-ui/utils\"\nimport { useCallback, useEffect, useId, useState } from \"react\"\n\nconst toArray = (value?: string) => value?.split(\"\")\n\nconst validate = (value: string, type: PinInputProps[\"type\"]) => {\n const NUMERIC_REGEX = /^[0-9]+$/\n const ALPHA_NUMERIC_REGEX = /^[a-zA-Z0-9]+$/i\n\n const regex = type === \"alphanumeric\" ? ALPHA_NUMERIC_REGEX : NUMERIC_REGEX\n\n return regex.test(value)\n}\n\ninterface PinInputContext {\n styles: { [key: string]: CSSUIObject | undefined }\n getInputProps: (\n props: {\n index: number\n ref?: Ref<HTMLInputElement>\n } & PinInputFieldProps,\n ) => PinInputFieldProps\n}\n\nconst [PinInputProvider, usePinInputContext] = createContext<PinInputContext>({\n name: \"PinInputContext\",\n errorMessage: `PinInputContext returned is 'undefined'. Seems you forgot to wrap the components in \"<PinInput />\"`,\n})\n\nconst { DescendantsContextProvider, useDescendant, useDescendants } =\n createDescendant<HTMLInputElement>()\n\ninterface PinInputOptions {\n /**\n * The top-level id string that will be applied to the input fields.\n * The index of the input will be appended to this top-level id.\n */\n id?: string\n /**\n * The type of values the pin-input should allow.\n *\n * @default 'number'\n */\n type?: \"alphanumeric\" | \"number\"\n /**\n * If `true`, the pin input receives focus on mount.\n *\n * @default false\n */\n autoFocus?: boolean\n /**\n * The initial value of the pin input.\n */\n defaultValue?: string\n /**\n * The border color when the input is invalid.\n */\n errorBorderColor?: ColorModeToken<CSS.Property.BorderColor, \"colors\">\n /**\n * The border color when the input is focused.\n */\n focusBorderColor?: ColorModeToken<CSS.Property.BorderColor, \"colors\">\n /**\n * The number of inputs to display.\n *\n * @default 4\n */\n items?: number\n /**\n * If `true`, focus will move automatically to the next input once filled.\n *\n * @default true\n */\n manageFocus?: boolean\n /**\n * If `true`, the input's value will be masked just like `type=password`.\n */\n mask?: boolean\n /**\n * If `true`, the pin input component signals to its fields that they should.\n */\n otp?: boolean\n /**\n * The placeholder for the pin input.\n *\n * @default '○'\n */\n placeholder?: string\n /**\n * The value of the pin input.\n */\n value?: string\n /**\n * Function called on input change.\n */\n onChange?: (value: string) => void\n /**\n * Function called when all inputs have valid values.\n */\n onComplete?: (value: string) => void\n}\n\nexport interface PinInputProps\n extends Omit<HTMLUIProps, \"defaultValue\" | \"mask\" | \"onChange\">,\n ThemeProps<\"PinInput\">,\n FormControlOptions,\n PinInputOptions {}\n\n/**\n * `PinInput` is a component used to capture pin codes or OTP (One-Time Password) inputs.\n *\n * @see Docs https://yamada-ui.com/components/forms/pin-input\n */\nexport const PinInput = forwardRef<PinInputProps, \"div\">(\n ({ errorBorderColor, focusBorderColor, ...props }, ref) => {\n const [styles, mergedProps] = useComponentMultiStyle(\"PinInput\", {\n errorBorderColor,\n focusBorderColor,\n ...props,\n })\n const uuid = useId()\n const {\n id = uuid,\n type = \"number\",\n className,\n autoFocus,\n children,\n defaultValue,\n items = 4,\n manageFocus = true,\n mask,\n otp = false,\n placeholder = \"○\",\n value,\n onChange: onChangeProp,\n onComplete,\n ...rest\n } = useFormControlProps(omitThemeProps(mergedProps))\n const [\n {\n \"aria-readonly\": _ariaReadonly,\n disabled,\n readOnly,\n ...formControlProps\n },\n containerProps,\n ] = splitObject(rest, formControlProperties)\n const descendants = useDescendants()\n const [moveFocus, setMoveFocus] = useState<boolean>(true)\n const [focusedIndex, setFocusedIndex] = useState<number>(-1)\n const [values, setValues] = useControllableState<string[]>({\n defaultValue: toArray(defaultValue) || [],\n value: toArray(value),\n onChange: (values) => onChangeProp?.(values.join(\"\")),\n })\n const css: CSSUIObject = {\n alignItems: \"center\",\n display: \"flex\",\n ...styles.container,\n }\n\n const focusNext = useCallback(\n (index: number) => {\n if (!moveFocus || !manageFocus) return\n\n const next = descendants.nextValue(index, undefined, false)\n\n if (!next) return\n\n requestAnimationFrame(() => next.node.focus())\n },\n [descendants, moveFocus, manageFocus],\n )\n\n const focusInputField = useCallback(\n (direction: \"next\" | \"prev\", index: number) => {\n const input =\n direction === \"next\"\n ? descendants.nextValue(index, undefined, false)\n : descendants.prevValue(index, undefined, false)\n\n if (!input) return\n\n const valueLength = input.node.value.length\n\n requestAnimationFrame(() => {\n input.node.focus()\n input.node.setSelectionRange(0, valueLength)\n })\n },\n [descendants],\n )\n\n const setValue = useCallback(\n (value: string, index: number, isFocus = true) => {\n let nextValues = [...values]\n\n nextValues[index] = value\n\n setValues(nextValues)\n\n nextValues = nextValues.filter(Boolean)\n\n const isComplete =\n value !== \"\" && nextValues.length === descendants.count()\n\n if (isComplete) {\n onComplete?.(nextValues.join(\"\"))\n descendants.value(index)?.node.blur()\n } else if (isFocus) {\n focusNext(index)\n }\n },\n [values, setValues, descendants, onComplete, focusNext],\n )\n\n const getNextValue = useCallback(\n (value: string | undefined, eventValue: string) => {\n let nextValue = eventValue\n\n if (!value?.length) return nextValue\n\n if (value.startsWith(eventValue.charAt(0))) {\n nextValue = eventValue.charAt(1)\n } else if (value.startsWith(eventValue.charAt(1))) {\n nextValue = eventValue.charAt(0)\n }\n\n return nextValue\n },\n [],\n )\n\n const onChange = useCallback(\n (index: number) =>\n ({ target }: ChangeEvent<HTMLInputElement>) => {\n const eventValue = target.value\n const currentValue = values[index]\n const nextValue = getNextValue(currentValue, eventValue)\n\n if (nextValue === \"\") {\n setValue(\"\", index)\n\n return\n }\n\n if (eventValue.length > 2) {\n if (!validate(eventValue, type)) return\n\n const nextValue = eventValue\n .split(\"\")\n .filter((_, index) => index < descendants.count())\n\n setValues(nextValue)\n\n if (nextValue.length === descendants.count()) {\n onComplete?.(nextValue.join(\"\"))\n descendants.value(index)?.node.blur()\n }\n } else {\n if (validate(nextValue, type)) setValue(nextValue, index)\n\n setMoveFocus(true)\n }\n },\n [\n descendants,\n getNextValue,\n onComplete,\n setValue,\n setValues,\n type,\n values,\n ],\n )\n\n const onKeyDown = useCallback(\n (index: number) => (ev: KeyboardEvent<HTMLInputElement>) => {\n if (!manageFocus) return\n\n const actions: { [key: string]: Function | undefined } = {\n ArrowLeft: () => {\n ev.preventDefault()\n focusInputField(\"prev\", index)\n },\n ArrowRight: () => {\n ev.preventDefault()\n focusInputField(\"next\", index)\n },\n Backspace: () => {\n if ((ev.target as HTMLInputElement).value === \"\") {\n const prevInput = descendants.prevValue(index, undefined, false)\n\n if (!prevInput) return\n\n setValue(\"\", index - 1, false)\n prevInput.node.focus()\n setMoveFocus(true)\n } else {\n setMoveFocus(false)\n }\n },\n }\n\n const action = actions[ev.key]\n\n if (!action) return\n\n action()\n },\n [descendants, focusInputField, manageFocus, setValue],\n )\n\n const onFocus = useCallback(\n (index: number) => () => setFocusedIndex(index),\n [],\n )\n\n const onBlur = useCallback(() => setFocusedIndex(-1), [])\n\n useEffect(() => {\n if (!autoFocus) return\n\n const firstValue = descendants.firstValue()\n\n if (!firstValue) return\n\n requestAnimationFrame(() => firstValue.node.focus())\n }, [autoFocus, descendants])\n\n const getInputProps = useCallback(\n ({\n index,\n ...props\n }: {\n index: number\n ref?: Ref<HTMLInputElement>\n } & PinInputFieldProps): PinInputFieldProps => ({\n type: mask ? \"password\" : type === \"number\" ? \"tel\" : \"text\",\n disabled,\n inputMode: type === \"number\" ? \"numeric\" : \"text\",\n readOnly,\n ...formControlProps,\n ...filterUndefined(props),\n id: `${id}-${index}`,\n autoComplete: otp ? \"one-time-code\" : \"off\",\n placeholder:\n focusedIndex === index && !readOnly && !props.readOnly\n ? \"\"\n : placeholder,\n value: values[index] || \"\",\n onBlur: handlerAll(props.onBlur, onBlur),\n onChange: handlerAll(props.onChange, onChange(index)),\n onFocus: handlerAll(props.onFocus, onFocus(index)),\n onKeyDown: handlerAll(props.onKeyDown, onKeyDown(index)),\n }),\n [\n type,\n mask,\n formControlProps,\n id,\n values,\n onChange,\n onKeyDown,\n onFocus,\n onBlur,\n otp,\n focusedIndex,\n disabled,\n readOnly,\n placeholder,\n ],\n )\n\n let cloneChildren = getValidChildren(children)\n\n if (!cloneChildren.length)\n for (let i = 0; i < items; i++) {\n cloneChildren.push(<PinInputField key={i} />)\n }\n\n return (\n <DescendantsContextProvider value={descendants}>\n <PinInputProvider value={{ styles, getInputProps }}>\n <ui.div\n ref={ref}\n className={cx(\"ui-pin-input\", className)}\n role=\"group\"\n __css={css}\n {...formControlProps}\n {...containerProps}\n >\n {cloneChildren}\n </ui.div>\n </PinInputProvider>\n </DescendantsContextProvider>\n )\n },\n)\n\nPinInput.displayName = \"PinInput\"\nPinInput.__ui__ = \"PinInput\"\n\nexport interface PinInputFieldProps\n extends HTMLUIProps<\"input\">,\n FormControlOptions {}\n\nexport const PinInputField = forwardRef<PinInputFieldProps, \"input\">(\n ({ className, ...rest }, ref) => {\n const { styles, getInputProps } = usePinInputContext()\n const { index, register } = useDescendant()\n const css: CSSUIObject = { ...styles.field }\n\n rest = useFormControlProps(rest)\n\n return (\n <ui.input\n className={cx(\"ui-pin-input__field\", className)}\n {...getInputProps({ ...rest, ref: mergeRefs(register, ref), index })}\n __css={css}\n />\n )\n },\n)\n\nPinInputField.displayName = \"PinInputField\"\nPinInputField.__ui__ = \"PinInputField\"\n"],"mappings":"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","names":["values","value","nextValue","index","props"]}
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  PinInput,
4
4
  PinInputField
5
- } from "./chunk-TU5BZGLV.mjs";
5
+ } from "./chunk-SUK2AVTG.mjs";
6
6
  export {
7
7
  PinInput,
8
8
  PinInputField
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yamada-ui/pin-input",
3
- "version": "1.2.4-dev-20241214144625",
3
+ "version": "1.2.4",
4
4
  "description": "Yamada UI pin input component",
5
5
  "keywords": [
6
6
  "yamada",
@@ -36,11 +36,11 @@
36
36
  "url": "https://github.com/yamada-ui/yamada-ui/issues"
37
37
  },
38
38
  "dependencies": {
39
- "@yamada-ui/core": "1.16.2-dev-20241214144625",
40
- "@yamada-ui/form-control": "2.1.11-dev-20241214144625",
41
- "@yamada-ui/use-controllable-state": "1.0.26-dev-20241214144625",
42
- "@yamada-ui/use-descendant": "1.0.28-dev-20241214144625",
43
- "@yamada-ui/utils": "1.6.2-dev-20241214144625"
39
+ "@yamada-ui/core": "1.16.2",
40
+ "@yamada-ui/use-controllable-state": "1.0.26",
41
+ "@yamada-ui/use-descendant": "1.0.28",
42
+ "@yamada-ui/utils": "1.6.2",
43
+ "@yamada-ui/form-control": "2.1.11"
44
44
  },
45
45
  "devDependencies": {
46
46
  "clean-package": "2.2.0",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/pin-input.tsx"],"sourcesContent":["import type {\n ColorModeToken,\n CSS,\n CSSUIObject,\n HTMLUIProps,\n ThemeProps,\n} from \"@yamada-ui/core\"\nimport type { FormControlOptions } from \"@yamada-ui/form-control\"\nimport type { ChangeEvent, KeyboardEvent, Ref } from \"react\"\nimport {\n forwardRef,\n omitThemeProps,\n ui,\n useComponentMultiStyle,\n} from \"@yamada-ui/core\"\nimport {\n formControlProperties,\n useFormControlProps,\n} from \"@yamada-ui/form-control\"\nimport { useControllableState } from \"@yamada-ui/use-controllable-state\"\nimport { createDescendant } from \"@yamada-ui/use-descendant\"\nimport {\n createContext,\n cx,\n filterUndefined,\n getValidChildren,\n handlerAll,\n mergeRefs,\n splitObject,\n} from \"@yamada-ui/utils\"\nimport { useCallback, useEffect, useId, useState } from \"react\"\n\nconst toArray = (value?: string) => value?.split(\"\")\n\nconst validate = (value: string, type: PinInputProps[\"type\"]) => {\n const NUMERIC_REGEX = /^[0-9]+$/\n const ALPHA_NUMERIC_REGEX = /^[a-zA-Z0-9]+$/i\n\n const regex = type === \"alphanumeric\" ? ALPHA_NUMERIC_REGEX : NUMERIC_REGEX\n\n return regex.test(value)\n}\n\ninterface PinInputContext {\n styles: { [key: string]: CSSUIObject | undefined }\n getInputProps: (\n props: {\n index: number\n ref?: Ref<HTMLInputElement>\n } & PinInputFieldProps,\n ) => PinInputFieldProps\n}\n\nconst [PinInputProvider, usePinInputContext] = createContext<PinInputContext>({\n name: \"PinInputContext\",\n errorMessage: `PinInputContext returned is 'undefined'. Seems you forgot to wrap the components in \"<PinInput />\"`,\n})\n\nconst { DescendantsContextProvider, useDescendant, useDescendants } =\n createDescendant<HTMLInputElement>()\n\ninterface PinInputOptions {\n /**\n * The top-level id string that will be applied to the input fields.\n * The index of the input will be appended to this top-level id.\n */\n id?: string\n /**\n * The type of values the pin-input should allow.\n *\n * @default 'number'\n */\n type?: \"alphanumeric\" | \"number\"\n /**\n * If `true`, the pin input receives focus on mount.\n *\n * @default false\n */\n autoFocus?: boolean\n /**\n * The initial value of the pin input.\n */\n defaultValue?: string\n /**\n * The border color when the input is invalid.\n */\n errorBorderColor?: ColorModeToken<CSS.Property.BorderColor, \"colors\">\n /**\n * The border color when the input is focused.\n */\n focusBorderColor?: ColorModeToken<CSS.Property.BorderColor, \"colors\">\n /**\n * The number of inputs to display.\n *\n * @default 4\n */\n items?: number\n /**\n * If `true`, focus will move automatically to the next input once filled.\n *\n * @default true\n */\n manageFocus?: boolean\n /**\n * If `true`, the input's value will be masked just like `type=password`.\n */\n mask?: boolean\n /**\n * If `true`, the pin input component signals to its fields that they should.\n */\n otp?: boolean\n /**\n * The placeholder for the pin input.\n *\n * @default '○'\n */\n placeholder?: string\n /**\n * The value of the pin input.\n */\n value?: string\n /**\n * Function called on input change.\n */\n onChange?: (value: string) => void\n /**\n * Function called when all inputs have valid values.\n */\n onComplete?: (value: string) => void\n}\n\nexport interface PinInputProps\n extends Omit<HTMLUIProps, \"defaultValue\" | \"mask\" | \"onChange\">,\n ThemeProps<\"PinInput\">,\n FormControlOptions,\n PinInputOptions {}\n\n/**\n * `PinInput` is a component used to capture pin codes or OTP (One-Time Password) inputs.\n *\n * @see Docs https://yamada-ui.com/components/forms/pin-input\n */\nexport const PinInput = forwardRef<PinInputProps, \"div\">(\n ({ errorBorderColor, focusBorderColor, ...props }, ref) => {\n const [styles, mergedProps] = useComponentMultiStyle(\"PinInput\", {\n errorBorderColor,\n focusBorderColor,\n ...props,\n })\n let {\n id,\n type = \"number\",\n className,\n autoFocus,\n children,\n defaultValue,\n items = 4,\n manageFocus = true,\n mask,\n otp = false,\n placeholder = \"○\",\n value,\n onChange: onChangeProp,\n onComplete,\n ...rest\n } = useFormControlProps(omitThemeProps(mergedProps))\n const [\n {\n \"aria-readonly\": _ariaReadonly,\n disabled,\n readOnly,\n ...formControlProps\n },\n containerProps,\n ] = splitObject(rest, formControlProperties)\n const uuid = useId()\n\n id ??= uuid\n\n const descendants = useDescendants()\n\n const [moveFocus, setMoveFocus] = useState<boolean>(true)\n const [focusedIndex, setFocusedIndex] = useState<number>(-1)\n\n useEffect(() => {\n if (!autoFocus) return\n\n const firstValue = descendants.firstValue()\n\n if (!firstValue) return\n\n requestAnimationFrame(() => firstValue.node.focus())\n }, [autoFocus, descendants])\n\n const [values, setValues] = useControllableState<string[]>({\n defaultValue: toArray(defaultValue) || [],\n value: toArray(value),\n onChange: (values) => onChangeProp?.(values.join(\"\")),\n })\n\n const focusNext = useCallback(\n (index: number) => {\n if (!moveFocus || !manageFocus) return\n\n const next = descendants.nextValue(index, undefined, false)\n\n if (!next) return\n\n requestAnimationFrame(() => next.node.focus())\n },\n [descendants, moveFocus, manageFocus],\n )\n\n const focusInputField = useCallback(\n (direction: \"next\" | \"prev\", index: number) => {\n const input =\n direction === \"next\"\n ? descendants.nextValue(index, undefined, false)\n : descendants.prevValue(index, undefined, false)\n\n if (!input) return\n\n const valueLength = input.node.value.length\n\n requestAnimationFrame(() => {\n input.node.focus()\n input.node.setSelectionRange(0, valueLength)\n })\n },\n [descendants],\n )\n\n const setValue = useCallback(\n (value: string, index: number, isFocus = true) => {\n let nextValues = [...values]\n\n nextValues[index] = value\n\n setValues(nextValues)\n\n nextValues = nextValues.filter(Boolean)\n\n const isComplete =\n value !== \"\" && nextValues.length === descendants.count()\n\n if (isComplete) {\n onComplete?.(nextValues.join(\"\"))\n descendants.value(index)?.node.blur()\n } else if (isFocus) {\n focusNext(index)\n }\n },\n [values, setValues, descendants, onComplete, focusNext],\n )\n\n const getNextValue = useCallback(\n (value: string | undefined, eventValue: string) => {\n let nextValue = eventValue\n\n if (!value?.length) return nextValue\n\n if (value.startsWith(eventValue.charAt(0))) {\n nextValue = eventValue.charAt(1)\n } else if (value.startsWith(eventValue.charAt(1))) {\n nextValue = eventValue.charAt(0)\n }\n\n return nextValue\n },\n [],\n )\n\n const onChange = useCallback(\n (index: number) =>\n ({ target }: ChangeEvent<HTMLInputElement>) => {\n const eventValue = target.value\n const currentValue = values[index]\n const nextValue = getNextValue(currentValue, eventValue)\n\n if (nextValue === \"\") {\n setValue(\"\", index)\n\n return\n }\n\n if (eventValue.length > 2) {\n if (!validate(eventValue, type)) return\n\n const nextValue = eventValue\n .split(\"\")\n .filter((_, index) => index < descendants.count())\n\n setValues(nextValue)\n\n if (nextValue.length === descendants.count()) {\n onComplete?.(nextValue.join(\"\"))\n descendants.value(index)?.node.blur()\n }\n } else {\n if (validate(nextValue, type)) setValue(nextValue, index)\n\n setMoveFocus(true)\n }\n },\n [\n descendants,\n getNextValue,\n onComplete,\n setValue,\n setValues,\n type,\n values,\n ],\n )\n\n const onKeyDown = useCallback(\n (index: number) => (ev: KeyboardEvent<HTMLInputElement>) => {\n if (!manageFocus) return\n\n const actions: { [key: string]: Function | undefined } = {\n ArrowLeft: () => {\n ev.preventDefault()\n focusInputField(\"prev\", index)\n },\n ArrowRight: () => {\n ev.preventDefault()\n focusInputField(\"next\", index)\n },\n Backspace: () => {\n if ((ev.target as HTMLInputElement).value === \"\") {\n const prevInput = descendants.prevValue(index, undefined, false)\n\n if (!prevInput) return\n\n setValue(\"\", index - 1, false)\n prevInput.node.focus()\n setMoveFocus(true)\n } else {\n setMoveFocus(false)\n }\n },\n }\n\n const action = actions[ev.key]\n\n if (!action) return\n\n action()\n },\n [descendants, focusInputField, manageFocus, setValue],\n )\n\n const onFocus = useCallback(\n (index: number) => () => setFocusedIndex(index),\n [],\n )\n\n const onBlur = useCallback(() => setFocusedIndex(-1), [])\n\n const getInputProps = useCallback(\n ({\n index,\n ...props\n }: {\n index: number\n ref?: Ref<HTMLInputElement>\n } & PinInputFieldProps): PinInputFieldProps => ({\n type: mask ? \"password\" : type === \"number\" ? \"tel\" : \"text\",\n disabled,\n inputMode: type === \"number\" ? \"numeric\" : \"text\",\n readOnly,\n ...formControlProps,\n ...filterUndefined(props),\n id: `${id}-${index}`,\n autoComplete: otp ? \"one-time-code\" : \"off\",\n placeholder:\n focusedIndex === index && !readOnly && !props.readOnly\n ? \"\"\n : placeholder,\n value: values[index] || \"\",\n onBlur: handlerAll(props.onBlur, onBlur),\n onChange: handlerAll(props.onChange, onChange(index)),\n onFocus: handlerAll(props.onFocus, onFocus(index)),\n onKeyDown: handlerAll(props.onKeyDown, onKeyDown(index)),\n }),\n [\n type,\n mask,\n formControlProps,\n id,\n values,\n onChange,\n onKeyDown,\n onFocus,\n onBlur,\n otp,\n focusedIndex,\n disabled,\n readOnly,\n placeholder,\n ],\n )\n\n const css: CSSUIObject = {\n alignItems: \"center\",\n display: \"flex\",\n ...styles.container,\n }\n\n let cloneChildren = getValidChildren(children)\n\n if (!cloneChildren.length)\n for (let i = 0; i < items; i++) {\n cloneChildren.push(<PinInputField key={i} />)\n }\n\n return (\n <DescendantsContextProvider value={descendants}>\n <PinInputProvider value={{ styles, getInputProps }}>\n <ui.div\n ref={ref}\n className={cx(\"ui-pin-input\", className)}\n role=\"group\"\n __css={css}\n {...formControlProps}\n {...containerProps}\n >\n {cloneChildren}\n </ui.div>\n </PinInputProvider>\n </DescendantsContextProvider>\n )\n },\n)\n\nPinInput.displayName = \"PinInput\"\nPinInput.__ui__ = \"PinInput\"\n\nexport interface PinInputFieldProps\n extends HTMLUIProps<\"input\">,\n FormControlOptions {}\n\nexport const PinInputField = forwardRef<PinInputFieldProps, \"input\">(\n ({ className, ...rest }, ref) => {\n const { styles, getInputProps } = usePinInputContext()\n const { index, register } = useDescendant()\n\n rest = useFormControlProps(rest)\n\n const css: CSSUIObject = { ...styles.field }\n\n return (\n <ui.input\n className={cx(\"ui-pin-input__field\", className)}\n {...getInputProps({ ...rest, ref: mergeRefs(register, ref), index })}\n __css={css}\n />\n )\n },\n)\n\nPinInputField.displayName = \"PinInputField\"\nPinInputField.__ui__ = \"PinInputField\"\n"],"mappings":"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","names":["values","value","nextValue","index","props"]}