@radix-ui/react-one-time-password-field 0.1.0-rc.1744661316162 → 0.1.0-rc.1744830756566

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.
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts", "../src/one-time-password-field.tsx"],
4
- "sourcesContent": ["'use client';\nexport type {\n OneTimePasswordFieldProps,\n OneTimePasswordFieldInputProps,\n OneTimePasswordFieldHiddenInputProps,\n InputValidationType,\n} from './one-time-password-field';\nexport {\n OneTimePasswordField,\n OneTimePasswordFieldInput,\n OneTimePasswordFieldHiddenInput,\n //\n Root,\n Input,\n HiddenInput,\n} from './one-time-password-field';\n", "import { Primitive } from '@radix-ui/react-primitive';\nimport { useComposedRefs } from '@radix-ui/react-compose-refs';\nimport { useControllableState } from '@radix-ui/react-use-controllable-state';\nimport { composeEventHandlers } from '@radix-ui/primitive';\nimport { unstable_createCollection as createCollection } from '@radix-ui/react-collection';\nimport * as RovingFocusGroup from '@radix-ui/react-roving-focus';\nimport { createRovingFocusGroupScope } from '@radix-ui/react-roving-focus';\nimport { useIsHydrated } from '@radix-ui/react-use-is-hydrated';\nimport * as React from 'react';\nimport { flushSync } from 'react-dom';\nimport type { Scope } from '@radix-ui/react-context';\nimport { createContextScope } from '@radix-ui/react-context';\nimport { useDirection } from '@radix-ui/react-direction';\nimport { clamp } from '@radix-ui/number';\nimport { useEffectEvent } from '@radix-ui/react-use-effect-event';\n\ntype InputType = 'password' | 'text';\ntype AutoComplete = 'off' | 'one-time-code';\n\ntype KeyboardActionDetails =\n | {\n type: 'keydown';\n key: 'Backspace' | 'Delete' | 'Char';\n metaKey: boolean;\n ctrlKey: boolean;\n }\n | { type: 'cut' };\n\ntype UpdateAction =\n | {\n type: 'SET_CHAR';\n char: string;\n index: number;\n event: React.KeyboardEvent | React.ChangeEvent;\n }\n | { type: 'CLEAR_CHAR'; index: number; reason: 'Backspace' | 'Delete' | 'Cut' }\n | { type: 'CLEAR'; reason: 'Reset' | 'Backspace' | 'Delete' }\n | { type: 'PASTE'; value: string };\ntype Dispatcher = React.Dispatch<UpdateAction>;\n\ntype InputValidationType = 'alpha' | 'numeric' | 'alphanumeric' | 'none';\ntype InputValidation = Record<\n Exclude<InputValidationType, 'none'>,\n { type: InputValidationType; regexp: RegExp; pattern: string; inputMode: string }\n>;\n\nconst INPUT_VALIDATION_MAP = {\n numeric: {\n type: 'numeric',\n regexp: /[^\\d]/g,\n pattern: '\\\\d{1}',\n inputMode: 'numeric',\n },\n alpha: {\n type: 'alpha',\n regexp: /[^a-zA-Z]/g,\n pattern: '[a-zA-Z]{1}',\n inputMode: 'text',\n },\n alphanumeric: {\n type: 'alphanumeric',\n regexp: /[^a-zA-Z0-9]/g,\n pattern: '[a-zA-Z0-9]{1}',\n inputMode: 'text',\n },\n} satisfies InputValidation;\n\ninterface OneTimePasswordFieldContextValue {\n value: string[];\n attemptSubmit: () => void;\n hiddenInputRef: React.RefObject<HTMLInputElement | null>;\n validationType: InputValidationType;\n disabled: boolean;\n readOnly: boolean;\n autoComplete: AutoComplete;\n autoFocus: boolean;\n form: string | undefined;\n name: string | undefined;\n placeholder: string | undefined;\n required: boolean;\n type: InputType;\n userActionRef: React.RefObject<KeyboardActionDetails | null>;\n dispatch: Dispatcher;\n orientation: Exclude<RovingFocusGroupProps['orientation'], undefined>;\n preHydrationIndexTracker: React.RefObject<number>;\n isHydrated: boolean;\n}\n\nconst ONE_TIME_PASSWORD_FIELD_NAME = 'OneTimePasswordField';\nconst [Collection, useCollection, createCollectionScope] = createCollection<HTMLInputElement>(\n ONE_TIME_PASSWORD_FIELD_NAME\n);\nconst [createOneTimePasswordFieldContext] = createContextScope(ONE_TIME_PASSWORD_FIELD_NAME, [\n createCollectionScope,\n createRovingFocusGroupScope,\n]);\nconst useRovingFocusGroupScope = createRovingFocusGroupScope();\n\nconst [OneTimePasswordFieldContext, useOneTimePasswordFieldContext] =\n createOneTimePasswordFieldContext<OneTimePasswordFieldContextValue>(ONE_TIME_PASSWORD_FIELD_NAME);\n\ntype RovingFocusGroupProps = React.ComponentPropsWithoutRef<typeof RovingFocusGroup.Root>;\n\ninterface OneTimePasswordFieldOwnProps {\n onValueChange?: (value: string) => void;\n id?: string;\n value?: string;\n defaultValue?: string;\n autoSubmit?: boolean;\n onAutoSubmit?: (value: string) => void;\n validationType?: InputValidationType;\n disabled?: boolean;\n readOnly?: boolean;\n autoComplete?: AutoComplete;\n autoFocus?: boolean;\n form?: string | undefined;\n name?: string | undefined;\n placeholder?: string | undefined;\n required?: boolean;\n type?: InputType;\n //\n dir?: RovingFocusGroupProps['dir'];\n orientation?: RovingFocusGroupProps['orientation'];\n}\n\ntype ScopedProps<P> = P & { __scopeOneTimePasswordField?: Scope };\n\nconst OneTimePasswordFieldCollectionProvider = ({\n __scopeOneTimePasswordField,\n children,\n}: ScopedProps<{ children: React.ReactNode }>) => {\n return (\n <Collection.Provider scope={__scopeOneTimePasswordField}>\n <Collection.Slot scope={__scopeOneTimePasswordField}>{children}</Collection.Slot>\n </Collection.Provider>\n );\n};\n\ninterface OneTimePasswordFieldProps\n extends OneTimePasswordFieldOwnProps,\n Omit<\n React.ComponentPropsWithoutRef<typeof Primitive.div>,\n keyof OneTimePasswordFieldOwnProps\n > {}\n\nconst OneTimePasswordFieldImpl = React.forwardRef<HTMLDivElement, OneTimePasswordFieldProps>(\n function OneTimePasswordFieldImpl(\n {\n __scopeOneTimePasswordField,\n id,\n defaultValue,\n value: valueProp,\n onValueChange,\n autoSubmit,\n children,\n onPaste,\n onAutoSubmit,\n disabled = false,\n readOnly = false,\n autoComplete = 'one-time-code',\n autoFocus = false,\n form,\n name,\n placeholder,\n required = false,\n type = 'password',\n // TODO: Change default to vertical when inputs use vertical writing mode\n orientation = 'horizontal',\n dir,\n validationType = 'numeric',\n ...domProps\n }: ScopedProps<OneTimePasswordFieldProps>,\n forwardedRef\n ) {\n const rovingFocusGroupScope = useRovingFocusGroupScope(__scopeOneTimePasswordField);\n const direction = useDirection(dir);\n const collection = useCollection(__scopeOneTimePasswordField);\n\n const validation =\n validationType in INPUT_VALIDATION_MAP\n ? INPUT_VALIDATION_MAP[validationType as keyof InputValidation]\n : undefined;\n\n const controlledValue = React.useMemo(() => {\n return valueProp != null ? sanitizeValue(valueProp, validation?.regexp) : undefined;\n }, [valueProp, validation?.regexp]);\n\n const [value, setValue] = useControllableState({\n caller: 'OneTimePasswordField',\n prop: controlledValue,\n defaultProp: defaultValue != null ? sanitizeValue(defaultValue, validation?.regexp) : [],\n onChange: (value) => onValueChange?.(value.filter(Boolean).join('')),\n });\n\n // Update function *specifically* for event handlers.\n const dispatch = useEffectEvent<Dispatcher>((action) => {\n switch (action.type) {\n case 'SET_CHAR': {\n const { index, char } = action;\n const currentTarget = collection.at(index)?.element;\n if (value[index] === char) {\n const next = currentTarget && collection.from(currentTarget, 1)?.element;\n focusInput(next);\n return;\n }\n\n // empty values should be handled in the CLEAR_CHAR action\n if (char === '') {\n return;\n }\n\n if (validation) {\n const regexp = new RegExp(validation.regexp);\n const clean = char.replace(regexp, '');\n if (clean !== char) {\n // not valid; ignore\n return;\n }\n }\n\n // no more space\n if (value.length >= collection.size) {\n // replace current value; move to next input\n const newValue = [...value];\n newValue[index] = char;\n flushSync(() => setValue(newValue));\n const next = currentTarget && collection.from(currentTarget, 1)?.element;\n focusInput(next);\n return;\n }\n\n const newValue = [\n //\n ...value.slice(0, index),\n char,\n ...value.slice(index),\n ];\n\n const lastElement = collection.at(-1)?.element;\n flushSync(() => setValue(newValue));\n if (currentTarget !== lastElement) {\n const next = currentTarget && collection.from(currentTarget, 1)?.element;\n focusInput(next);\n } else {\n currentTarget?.select();\n }\n return;\n }\n\n case 'CLEAR_CHAR': {\n const { index, reason } = action;\n if (!value[index]) {\n return;\n }\n\n const newValue = value.filter((_, i) => i !== index);\n const currentTarget = collection.at(index)?.element;\n const previous = currentTarget && collection.from(currentTarget, -1)?.element;\n\n flushSync(() => setValue(newValue));\n if (reason === 'Backspace') {\n focusInput(previous);\n } else if (reason === 'Delete' || reason === 'Cut') {\n focusInput(currentTarget);\n }\n return;\n }\n\n case 'CLEAR': {\n if (value.length === 0) {\n return;\n }\n\n if (action.reason === 'Backspace' || action.reason === 'Delete') {\n flushSync(() => setValue([]));\n focusInput(collection.at(0)?.element);\n } else {\n setValue([]);\n }\n return;\n }\n\n case 'PASTE': {\n const { value: pastedValue } = action;\n const value = sanitizeValue(pastedValue, validation?.regexp);\n if (!value) {\n return;\n }\n\n flushSync(() => setValue(value));\n focusInput(collection.at(value.length - 1)?.element);\n return;\n }\n }\n });\n\n // re-validate when the validation type changes\n const validationTypeRef = React.useRef(validation);\n React.useEffect(() => {\n if (!validation) {\n return;\n }\n\n if (validationTypeRef.current?.type !== validation.type) {\n validationTypeRef.current = validation;\n setValue(sanitizeValue(value, validation.regexp));\n }\n }, [setValue, validation, value]);\n\n const hiddenInputRef = React.useRef<HTMLInputElement>(null);\n\n const userActionRef = React.useRef<KeyboardActionDetails | null>(null);\n const rootRef = React.useRef<HTMLDivElement | null>(null);\n const composedRefs = useComposedRefs(forwardedRef, rootRef);\n\n const firstInput = collection.at(0)?.element;\n const locateForm = React.useCallback(() => {\n let formElement: HTMLFormElement | null | undefined;\n if (form) {\n const associatedElement = (rootRef.current?.ownerDocument ?? document).getElementById(form);\n if (isFormElement(associatedElement)) {\n formElement = associatedElement;\n }\n } else if (hiddenInputRef.current) {\n formElement = hiddenInputRef.current.form;\n } else if (firstInput) {\n formElement = firstInput.form;\n }\n\n return formElement ?? null;\n }, [form, firstInput]);\n\n const attemptSubmit = React.useCallback(() => {\n const formElement = locateForm();\n formElement?.requestSubmit();\n }, [locateForm]);\n\n React.useEffect(() => {\n const form = locateForm();\n if (form) {\n const reset = () => dispatch({ type: 'CLEAR', reason: 'Reset' });\n form.addEventListener('reset', reset);\n return () => form.removeEventListener('reset', reset);\n }\n }, [dispatch, locateForm]);\n\n const currentValue = value.join('');\n const valueRef = React.useRef(currentValue);\n const length = collection.size;\n React.useEffect(() => {\n const previousValue = valueRef.current;\n valueRef.current = currentValue;\n if (previousValue === currentValue) {\n return;\n }\n\n if (autoSubmit && value.every((char) => char !== '') && value.length === length) {\n onAutoSubmit?.(value.join(''));\n attemptSubmit();\n }\n }, [attemptSubmit, autoSubmit, currentValue, length, onAutoSubmit, value]);\n\n // Before hydration (and in SSR) we can track the index of an input during\n // render, as indices calculated by the collection package should almost\n // always align with render order anyway. This ensures that index-dependent\n // attributes are immediately rendered, in case browser extensions rely on\n // those for auto-complete functionality and JS has not hydrated.\n const preHydrationIndexTracker = React.useRef<number>(0);\n const isHydrated = useIsHydrated();\n\n return (\n <OneTimePasswordFieldContext\n scope={__scopeOneTimePasswordField}\n value={value}\n attemptSubmit={attemptSubmit}\n disabled={disabled}\n readOnly={readOnly}\n autoComplete={autoComplete}\n autoFocus={autoFocus}\n form={form}\n name={name}\n placeholder={placeholder}\n required={required}\n type={type}\n hiddenInputRef={hiddenInputRef}\n userActionRef={userActionRef}\n dispatch={dispatch}\n validationType={validationType}\n orientation={orientation}\n preHydrationIndexTracker={preHydrationIndexTracker}\n isHydrated={isHydrated}\n >\n <RovingFocusGroup.Root\n asChild\n {...rovingFocusGroupScope}\n orientation={orientation}\n dir={direction}\n >\n <Primitive.div\n {...domProps}\n role=\"group\"\n ref={composedRefs}\n onPaste={composeEventHandlers(\n onPaste,\n (event: React.ClipboardEvent<HTMLDivElement>) => {\n event.preventDefault();\n const pastedValue = event.clipboardData.getData('Text');\n const value = sanitizeValue(pastedValue, validation?.regexp);\n if (!value) {\n return;\n }\n dispatch({ type: 'PASTE', value: pastedValue });\n }\n )}\n >\n {children}\n </Primitive.div>\n </RovingFocusGroup.Root>\n </OneTimePasswordFieldContext>\n );\n }\n);\n\nconst OneTimePasswordField = React.forwardRef<HTMLDivElement, OneTimePasswordFieldProps>(\n function OneTimePasswordField(props, ref) {\n return (\n <OneTimePasswordFieldCollectionProvider>\n <OneTimePasswordFieldImpl {...props} ref={ref} />\n </OneTimePasswordFieldCollectionProvider>\n );\n }\n);\n\ninterface OneTimePasswordFieldHiddenInputProps\n extends Omit<\n React.ComponentProps<'input'>,\n | keyof 'value'\n | 'defaultValue'\n | 'type'\n | 'onChange'\n | 'readOnly'\n | 'disabled'\n | 'autoComplete'\n | 'autoFocus'\n > {}\n\nconst OneTimePasswordFieldHiddenInput = React.forwardRef<\n HTMLInputElement,\n OneTimePasswordFieldHiddenInputProps\n>(function OneTimePasswordFieldHiddenInput(\n { __scopeOneTimePasswordField, ...props }: ScopedProps<OneTimePasswordFieldHiddenInputProps>,\n forwardedRef\n) {\n const { value, hiddenInputRef } = useOneTimePasswordFieldContext(\n 'OneTimePasswordFieldHiddenInput',\n __scopeOneTimePasswordField\n );\n const ref = useComposedRefs(hiddenInputRef, forwardedRef);\n return (\n <input\n ref={ref}\n {...props}\n type=\"hidden\"\n readOnly\n value={value.join('').trim()}\n autoComplete=\"off\"\n autoFocus={false}\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n autoSave=\"off\"\n spellCheck={false}\n />\n );\n});\n\ninterface OneTimePasswordFieldInputOwnProps {\n autoComplete?: 'one-time-code' | 'off';\n}\n\ninterface OneTimePasswordFieldInputProps\n extends OneTimePasswordFieldInputOwnProps,\n Omit<React.ComponentProps<typeof Primitive.input>, keyof OneTimePasswordFieldInputOwnProps> {}\n\nconst OneTimePasswordFieldInput = React.forwardRef<\n HTMLInputElement,\n OneTimePasswordFieldInputProps\n>(function OneTimePasswordFieldInput(\n { __scopeOneTimePasswordField, ...props }: ScopedProps<OneTimePasswordFieldInputProps>,\n forwardedRef\n) {\n // TODO: warn if these values are passed\n const {\n value: _value,\n defaultValue: _defaultValue,\n disabled: _disabled,\n readOnly: _readOnly,\n autoComplete: _autoComplete,\n autoFocus: _autoFocus,\n form: _form,\n name: _name,\n placeholder: _placeholder,\n required: _required,\n type: _type,\n ...domProps\n } = props as any;\n\n const context = useOneTimePasswordFieldContext(\n 'OneTimePasswordFieldInput',\n __scopeOneTimePasswordField\n );\n const { dispatch, userActionRef, validationType, preHydrationIndexTracker, isHydrated } = context;\n const collection = useCollection(__scopeOneTimePasswordField);\n const rovingFocusGroupScope = useRovingFocusGroupScope(__scopeOneTimePasswordField);\n\n const inputRef = React.useRef<HTMLInputElement>(null);\n const [element, setElement] = React.useState<HTMLInputElement | null>(null);\n\n let index: number;\n if (!isHydrated) {\n index = preHydrationIndexTracker.current;\n preHydrationIndexTracker.current++;\n } else {\n index = element ? collection.indexOf(element) : -1;\n }\n\n const composedInputRef = useComposedRefs(forwardedRef, inputRef, setElement);\n const char = context.value[index] ?? '';\n\n const keyboardActionTimeoutRef = React.useRef<number | null>(null);\n React.useEffect(() => {\n return () => {\n window.clearTimeout(keyboardActionTimeoutRef.current!);\n };\n }, []);\n\n const totalValue = context.value.join('').trim();\n const lastSelectableIndex = clamp(totalValue.length, [0, collection.size - 1]);\n const isFocusable = index <= lastSelectableIndex;\n\n const validation =\n validationType in INPUT_VALIDATION_MAP\n ? INPUT_VALIDATION_MAP[validationType as keyof InputValidation]\n : undefined;\n\n return (\n <Collection.ItemSlot scope={__scopeOneTimePasswordField}>\n <RovingFocusGroup.Item\n {...rovingFocusGroupScope}\n asChild\n focusable={!context.disabled && isFocusable}\n active={index === lastSelectableIndex}\n >\n <Primitive.input\n ref={composedInputRef}\n type=\"text\"\n aria-label={`Character ${index + 1} of ${collection.size}`}\n autoComplete={index === 0 ? context.autoComplete : 'off'}\n inputMode={validation?.inputMode}\n maxLength={1}\n pattern={validation?.pattern}\n readOnly={context.readOnly}\n value={char}\n data-radix-otp-input=\"\"\n data-radix-index={index}\n {...domProps}\n onFocus={composeEventHandlers(props.onFocus, (event) => {\n event.currentTarget.select();\n })}\n onCut={composeEventHandlers(props.onCut, (event) => {\n const currentValue = event.currentTarget.value;\n if (currentValue !== '') {\n // In this case the value will be cleared, but we don't want to\n // set it directly because the user may want to prevent default\n // behavior in the onChange handler. The userActionRef will\n // is set temporarily so the change handler can behave correctly\n // in response to the action.\n userActionRef.current = {\n type: 'cut',\n };\n // Set a short timeout to clear the action tracker after the change\n // handler has had time to complete.\n keyboardActionTimeoutRef.current = window.setTimeout(() => {\n userActionRef.current = null;\n }, 10);\n }\n })}\n onChange={composeEventHandlers(props.onChange, (event) => {\n const action = userActionRef.current;\n userActionRef.current = null;\n\n if (action) {\n switch (action.type) {\n case 'cut':\n // TODO: do we want to assume the user wantt to clear the\n // entire value here and copy the code to the clipboard instead\n // of just the value of the given input?\n dispatch({ type: 'CLEAR_CHAR', index, reason: 'Cut' });\n return;\n case 'keydown': {\n if (action.key === 'Char') {\n // update resulting from a keydown event that set a value\n // directly. Ignore.\n return;\n }\n\n const isClearing =\n action.key === 'Backspace' && (action.metaKey || action.ctrlKey);\n if (isClearing) {\n dispatch({ type: 'CLEAR', reason: 'Backspace' });\n } else {\n dispatch({ type: 'CLEAR_CHAR', index, reason: action.key });\n }\n return;\n }\n default:\n return;\n }\n }\n\n // Only update the value if it matches the input pattern\n if (event.target.validity.valid) {\n if (event.target.value === '') {\n let reason: 'Backspace' | 'Delete' | 'Cut' = 'Backspace';\n if (isInputEvent(event.nativeEvent)) {\n const inputType = event.nativeEvent.inputType;\n if (inputType === 'deleteContentBackward') {\n reason = 'Backspace';\n } else if (inputType === 'deleteByCut') {\n reason = 'Cut';\n }\n }\n dispatch({ type: 'CLEAR_CHAR', index, reason });\n } else {\n dispatch({ type: 'SET_CHAR', char: event.target.value, index, event });\n }\n } else {\n const element = event.target;\n requestAnimationFrame(() => {\n if (element.ownerDocument.activeElement === element) {\n element.select();\n }\n });\n }\n })}\n onKeyDown={composeEventHandlers(props.onKeyDown, (event) => {\n switch (event.key) {\n case 'Delete':\n case 'Backspace': {\n const currentValue = event.currentTarget.value;\n // if current value is empty, no change event will fire\n if (currentValue === '') {\n // if the user presses delete when there is no value, noop\n if (event.key === 'Delete') return;\n\n const isClearing = event.metaKey || event.ctrlKey;\n if (isClearing) {\n dispatch({ type: 'CLEAR', reason: 'Backspace' });\n } else {\n const element = event.currentTarget;\n requestAnimationFrame(() => {\n focusInput(collection.from(element, -1)?.element);\n });\n }\n } else {\n // In this case the value will be cleared, but we don't want\n // to set it directly because the user may want to prevent\n // default behavior in the onChange handler. The userActionRef\n // will is set temporarily so the change handler can behave\n // correctly in response to the key vs. clearing the value by\n // setting state externally.\n userActionRef.current = {\n type: 'keydown',\n key: event.key,\n metaKey: event.metaKey,\n ctrlKey: event.ctrlKey,\n };\n // Set a short timeout to clear the action tracker after the change\n // handler has had time to complete.\n keyboardActionTimeoutRef.current = window.setTimeout(() => {\n userActionRef.current = null;\n }, 10);\n }\n\n return;\n }\n case 'Enter': {\n event.preventDefault();\n context.attemptSubmit();\n return;\n }\n case 'ArrowDown':\n case 'ArrowUp': {\n if (context.orientation === 'horizontal') {\n // in horizontal orientation, the up/down will de-select the\n // input instead of moving focus\n event.preventDefault();\n }\n return;\n }\n // TODO: Handle left/right arrow keys in vertical writing mode\n default: {\n if (event.currentTarget.value === event.key) {\n // if current value is same as the key press, no change event\n // will fire. Focus the next input.\n const element = event.currentTarget;\n event.preventDefault();\n focusInput(collection.from(element, 1)?.element);\n return;\n } else if (\n // input already has a value, but...\n event.currentTarget.value &&\n // the value is not selected\n !(\n event.currentTarget.selectionStart === 0 &&\n event.currentTarget.selectionEnd != null &&\n event.currentTarget.selectionEnd > 0\n )\n ) {\n const attemptedValue = event.key;\n if (event.key.length > 1 || event.key === ' ') {\n // not a character; do nothing\n return;\n } else {\n // user is attempting to enter a character, but the input\n // will not update by default since it's limited to a single\n // character.\n const nextInput = collection.from(event.currentTarget, 1)?.element;\n const lastInput = collection.at(-1)?.element;\n if (nextInput !== lastInput && event.currentTarget !== lastInput) {\n // if selection is before the value, set the value of the\n // current input. Otherwise set the value of the next\n // input.\n if (event.currentTarget.selectionStart === 0) {\n dispatch({ type: 'SET_CHAR', char: attemptedValue, index, event });\n } else {\n dispatch({\n type: 'SET_CHAR',\n char: attemptedValue,\n index: index + 1,\n event,\n });\n }\n\n userActionRef.current = {\n type: 'keydown',\n key: 'Char',\n metaKey: event.metaKey,\n ctrlKey: event.ctrlKey,\n };\n keyboardActionTimeoutRef.current = window.setTimeout(() => {\n userActionRef.current = null;\n }, 10);\n }\n }\n }\n }\n }\n })}\n onPointerDown={composeEventHandlers(props.onPointerDown, (event) => {\n if (index > lastSelectableIndex) {\n event.preventDefault();\n const element = collection.at(lastSelectableIndex)?.element;\n focusInput(element);\n }\n })}\n />\n </RovingFocusGroup.Item>\n </Collection.ItemSlot>\n );\n});\n\nconst Root = OneTimePasswordField;\nconst Input = OneTimePasswordFieldInput;\nconst HiddenInput = OneTimePasswordFieldHiddenInput;\n\nexport {\n OneTimePasswordField,\n OneTimePasswordFieldInput,\n OneTimePasswordFieldHiddenInput,\n //\n Root,\n Input,\n HiddenInput,\n};\nexport type {\n OneTimePasswordFieldProps,\n OneTimePasswordFieldInputProps,\n OneTimePasswordFieldHiddenInputProps,\n InputValidationType,\n};\n\nfunction isFormElement(element: Element | null | undefined): element is HTMLFormElement {\n return element?.tagName === 'FORM';\n}\n\nfunction sanitizeValue(value: string | string[], regexp: RegExp | undefined | null) {\n if (Array.isArray(value)) {\n value = value.join('');\n }\n if (regexp) {\n // global regexp is stateful, so we clone it for each call\n regexp = new RegExp(regexp);\n return value.replace(regexp, '').split('').filter(Boolean);\n }\n return value.split('').filter(Boolean);\n}\n\nfunction focusInput(element: HTMLInputElement | null | undefined) {\n if (!element) return;\n if (element.ownerDocument.activeElement === element) {\n // if the element is already focused, select the value in the next\n // animation frame\n window.requestAnimationFrame(() => {\n element.select?.();\n });\n } else {\n element.focus();\n }\n}\n\nfunction isInputEvent(event: Event): event is InputEvent {\n return event.type === 'input';\n}\n"],
5
- "mappings": "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",
6
- "names": ["Root", "createCollection", "OneTimePasswordFieldImpl", "value", "newValue", "form", "OneTimePasswordField", "OneTimePasswordFieldHiddenInput", "OneTimePasswordFieldInput", "element", "Root"]
4
+ "sourcesContent": ["'use client';\nexport type {\n OneTimePasswordFieldProps,\n OneTimePasswordFieldInputProps,\n OneTimePasswordFieldHiddenInputProps,\n InputValidationType,\n} from './one-time-password-field';\nexport {\n OneTimePasswordField,\n OneTimePasswordFieldInput,\n OneTimePasswordFieldHiddenInput,\n //\n Root,\n Input,\n HiddenInput,\n} from './one-time-password-field';\n", "import * as Primitive from '@radix-ui/react-primitive';\nimport { useComposedRefs } from '@radix-ui/react-compose-refs';\nimport { useControllableState } from '@radix-ui/react-use-controllable-state';\nimport { composeEventHandlers } from '@radix-ui/primitive';\nimport { unstable_createCollection as createCollection } from '@radix-ui/react-collection';\nimport * as RovingFocusGroup from '@radix-ui/react-roving-focus';\nimport { createRovingFocusGroupScope } from '@radix-ui/react-roving-focus';\nimport { useIsHydrated } from '@radix-ui/react-use-is-hydrated';\nimport * as React from 'react';\nimport { flushSync } from 'react-dom';\nimport type { Scope } from '@radix-ui/react-context';\nimport { createContextScope } from '@radix-ui/react-context';\nimport { useDirection } from '@radix-ui/react-direction';\nimport { clamp } from '@radix-ui/number';\nimport { useEffectEvent } from '@radix-ui/react-use-effect-event';\n\ntype InputValidationType = 'alpha' | 'numeric' | 'alphanumeric' | 'none';\n\nconst INPUT_VALIDATION_MAP = {\n numeric: {\n type: 'numeric',\n regexp: /[^\\d]/g,\n pattern: '\\\\d{1}',\n inputMode: 'numeric',\n },\n alpha: {\n type: 'alpha',\n regexp: /[^a-zA-Z]/g,\n pattern: '[a-zA-Z]{1}',\n inputMode: 'text',\n },\n alphanumeric: {\n type: 'alphanumeric',\n regexp: /[^a-zA-Z0-9]/g,\n pattern: '[a-zA-Z0-9]{1}',\n inputMode: 'text',\n },\n none: null,\n} satisfies InputValidation;\n\n/* -------------------------------------------------------------------------------------------------\n * OneTimePasswordFieldProvider\n * -----------------------------------------------------------------------------------------------*/\n\ntype RovingFocusGroupProps = RovingFocusGroup.RovingFocusGroupProps;\n\ninterface OneTimePasswordFieldContextValue {\n attemptSubmit: () => void;\n autoComplete: AutoComplete;\n autoFocus: boolean;\n disabled: boolean;\n dispatch: Dispatcher;\n form: string | undefined;\n hiddenInputRef: React.RefObject<HTMLInputElement | null>;\n isHydrated: boolean;\n name: string | undefined;\n orientation: Exclude<RovingFocusGroupProps['orientation'], undefined>;\n placeholder: string | undefined;\n preHydrationIndexTracker: React.RefObject<number>;\n readOnly: boolean;\n type: InputType;\n userActionRef: React.RefObject<KeyboardActionDetails | null>;\n validationType: InputValidationType;\n value: string[];\n}\n\nconst ONE_TIME_PASSWORD_FIELD_NAME = 'OneTimePasswordField';\nconst [Collection, { useCollection, createCollectionScope, useInitCollection }] =\n createCollection<HTMLInputElement>(ONE_TIME_PASSWORD_FIELD_NAME);\nconst [createOneTimePasswordFieldContext] = createContextScope(ONE_TIME_PASSWORD_FIELD_NAME, [\n createCollectionScope,\n createRovingFocusGroupScope,\n]);\nconst useRovingFocusGroupScope = createRovingFocusGroupScope();\n\nconst [OneTimePasswordFieldContext, useOneTimePasswordFieldContext] =\n createOneTimePasswordFieldContext<OneTimePasswordFieldContextValue>(ONE_TIME_PASSWORD_FIELD_NAME);\n\n/* -------------------------------------------------------------------------------------------------\n * OneTimePasswordField\n * -----------------------------------------------------------------------------------------------*/\n\ninterface OneTimePasswordFieldOwnProps {\n /**\n * Specifies what\u2014if any\u2014permission the user agent has to provide automated\n * assistance in filling out form field values, as well as guidance to the\n * browser as to the type of information expected in the field. Allows\n * `\"one-time-code\"` or `\"off\"`.\n *\n * @defaultValue `\"one-time-code\"`\n * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/autocomplete\n */\n autoComplete?: AutoComplete;\n /**\n * Whether or not the first fillable input should be focused on page-load.\n *\n * @defaultValue `false`\n * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/autofocus\n */\n autoFocus?: boolean;\n /**\n * Whether or not the component should attempt to automatically submit when\n * all fields are filled. If the field is associated with an HTML `form`\n * element, the form's `requestSubmit` method will be called.\n *\n * @defaultValue `false`\n */\n autoSubmit?: boolean;\n /**\n * The initial value of the uncontrolled field.\n */\n defaultValue?: string;\n /**\n * Indicates the horizontal directionality of the parent element's text.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/dir\n */\n dir?: RovingFocusGroupProps['dir'];\n /**\n * Whether or not the the field's input elements are disabled.\n */\n disabled?: boolean;\n /**\n * A string specifying the `form` element with which the input is associated.\n * This string's value, if present, must match the id of a `form` element in\n * the same document.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input#form\n */\n form?: string | undefined;\n /**\n * A string specifying a name for the input control. This name is submitted\n * along with the control's value when the form data is submitted.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input#name\n */\n name?: string | undefined;\n /**\n * When the `autoSubmit` prop is set to `true`, this callback will be fired\n * before attempting to submit the associated form. It will be called whether\n * or not a form is located, or if submission is not allowed.\n */\n onAutoSubmit?: (value: string) => void;\n /**\n * A callback fired when the field's value changes. When the component is\n * controlled, this should update the state passed to the `value` prop.\n */\n onValueChange?: (value: string) => void;\n /**\n * Indicates the vertical directionality of the input elements.\n *\n * @defaultValue `\"horizontal\"`\n */\n orientation?: RovingFocusGroupProps['orientation'];\n /**\n * Defines the text displayed in a form control when the control has no value.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/placeholder\n */\n placeholder?: string | undefined;\n /**\n * Whether or not the input elements can be updated by the user.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/readonly\n */\n readOnly?: boolean;\n /**\n * Function for custom sanitization when `validationType` is set to `\"none\"`.\n * This function will be called before updating values in response to user\n * interactions.\n */\n sanitizeValue?: (value: string) => string;\n /**\n * The input type of the field's input elements. Can be `\"password\"` or `\"text\"`.\n */\n type?: InputType;\n /**\n * Specifies the type of input validation to be used. Can be `\"alpha\"`,\n * `\"numeric\"`, `\"alphanumeric\"` or `\"none\"`.\n *\n * @defaultValue `\"numeric\"`\n */\n validationType?: InputValidationType;\n /**\n * The controlled value of the field.\n */\n value?: string;\n}\n\ntype ScopedProps<P> = P & { __scopeOneTimePasswordField?: Scope };\n\ninterface OneTimePasswordFieldProps\n extends OneTimePasswordFieldOwnProps,\n Omit<Primitive.PrimitivePropsWithRef<'div'>, keyof OneTimePasswordFieldOwnProps> {}\n\nconst OneTimePasswordField = React.forwardRef<HTMLDivElement, OneTimePasswordFieldProps>(\n function OneTimePasswordFieldImpl(\n {\n __scopeOneTimePasswordField,\n defaultValue,\n value: valueProp,\n onValueChange,\n autoSubmit = false,\n children,\n onPaste,\n onAutoSubmit,\n disabled = false,\n readOnly = false,\n autoComplete = 'one-time-code',\n autoFocus = false,\n form,\n name,\n placeholder,\n type = 'password',\n // TODO: Change default to vertical when inputs use vertical writing mode\n orientation = 'horizontal',\n dir,\n validationType = 'numeric',\n sanitizeValue: sanitizeValueProp,\n ...domProps\n }: ScopedProps<OneTimePasswordFieldProps>,\n forwardedRef\n ) {\n const rovingFocusGroupScope = useRovingFocusGroupScope(__scopeOneTimePasswordField);\n const direction = useDirection(dir);\n const collectionState = useInitCollection();\n const [collection] = collectionState;\n\n const validation = INPUT_VALIDATION_MAP[validationType]\n ? INPUT_VALIDATION_MAP[validationType as keyof InputValidation]\n : null;\n\n const sanitizeValue = React.useCallback(\n (value: string | string[]) => {\n if (Array.isArray(value)) {\n value = value.map(removeWhitespace).join('');\n } else {\n value = removeWhitespace(value);\n }\n\n if (validation) {\n // global regexp is stateful, so we clone it for each call\n const regexp = new RegExp(validation.regexp);\n value = value.replace(regexp, '');\n } else if (sanitizeValueProp) {\n value = sanitizeValueProp(value);\n }\n\n return value.split('');\n },\n [validation, sanitizeValueProp]\n );\n\n const controlledValue = React.useMemo(() => {\n return valueProp != null ? sanitizeValue(valueProp) : undefined;\n }, [valueProp, sanitizeValue]);\n\n const [value, setValue] = useControllableState({\n caller: 'OneTimePasswordField',\n prop: controlledValue,\n defaultProp: defaultValue != null ? sanitizeValue(defaultValue) : [],\n onChange: React.useCallback(\n (value: string[]) => onValueChange?.(value.join('')),\n [onValueChange]\n ),\n });\n\n // Update function *specifically* for event handlers.\n const dispatch = useEffectEvent<Dispatcher>((action) => {\n switch (action.type) {\n case 'SET_CHAR': {\n const { index, char } = action;\n const currentTarget = collection.at(index)?.element;\n if (value[index] === char) {\n const next = currentTarget && collection.from(currentTarget, 1)?.element;\n focusInput(next);\n return;\n }\n\n // empty values should be handled in the CLEAR_CHAR action\n if (char === '') {\n return;\n }\n\n if (validation) {\n const regexp = new RegExp(validation.regexp);\n const clean = char.replace(regexp, '');\n if (clean !== char) {\n // not valid; ignore\n return;\n }\n }\n\n // no more space\n if (value.length >= collection.size) {\n // replace current value; move to next input\n const newValue = [...value];\n newValue[index] = char;\n flushSync(() => setValue(newValue));\n const next = currentTarget && collection.from(currentTarget, 1)?.element;\n focusInput(next);\n return;\n }\n\n const newValue = [...value];\n newValue[index] = char;\n\n const lastElement = collection.at(-1)?.element;\n flushSync(() => setValue(newValue));\n if (currentTarget !== lastElement) {\n const next = currentTarget && collection.from(currentTarget, 1)?.element;\n focusInput(next);\n } else {\n currentTarget?.select();\n }\n return;\n }\n\n case 'CLEAR_CHAR': {\n const { index, reason } = action;\n if (!value[index]) {\n return;\n }\n\n const newValue = value.filter((_, i) => i !== index);\n const currentTarget = collection.at(index)?.element;\n const previous = currentTarget && collection.from(currentTarget, -1)?.element;\n\n flushSync(() => setValue(newValue));\n if (reason === 'Backspace') {\n focusInput(previous);\n } else if (reason === 'Delete' || reason === 'Cut') {\n focusInput(currentTarget);\n }\n return;\n }\n\n case 'CLEAR': {\n if (value.length === 0) {\n return;\n }\n\n if (action.reason === 'Backspace' || action.reason === 'Delete') {\n flushSync(() => setValue([]));\n focusInput(collection.at(0)?.element);\n } else {\n setValue([]);\n }\n return;\n }\n\n case 'PASTE': {\n const { value: pastedValue } = action;\n const value = sanitizeValue(pastedValue);\n if (!value) {\n return;\n }\n\n flushSync(() => setValue(value));\n focusInput(collection.at(value.length - 1)?.element);\n return;\n }\n }\n });\n\n // re-validate when the validation type changes\n const validationTypeRef = React.useRef(validation);\n React.useEffect(() => {\n if (!validation) {\n return;\n }\n\n if (validationTypeRef.current?.type !== validation.type) {\n validationTypeRef.current = validation;\n setValue(sanitizeValue(value.join('')));\n }\n }, [sanitizeValue, setValue, validation, value]);\n\n const hiddenInputRef = React.useRef<HTMLInputElement>(null);\n\n const userActionRef = React.useRef<KeyboardActionDetails | null>(null);\n const rootRef = React.useRef<HTMLDivElement | null>(null);\n const composedRefs = useComposedRefs(forwardedRef, rootRef);\n\n const firstInput = collection.at(0)?.element;\n const locateForm = React.useCallback(() => {\n let formElement: HTMLFormElement | null | undefined;\n if (form) {\n const associatedElement = (rootRef.current?.ownerDocument ?? document).getElementById(form);\n if (isFormElement(associatedElement)) {\n formElement = associatedElement;\n }\n } else if (hiddenInputRef.current) {\n formElement = hiddenInputRef.current.form;\n } else if (firstInput) {\n formElement = firstInput.form;\n }\n\n return formElement ?? null;\n }, [form, firstInput]);\n\n const attemptSubmit = React.useCallback(() => {\n const formElement = locateForm();\n formElement?.requestSubmit();\n }, [locateForm]);\n\n React.useEffect(() => {\n const form = locateForm();\n if (form) {\n const reset = () => dispatch({ type: 'CLEAR', reason: 'Reset' });\n form.addEventListener('reset', reset);\n return () => form.removeEventListener('reset', reset);\n }\n }, [dispatch, locateForm]);\n\n const currentValue = value.join('');\n const valueRef = React.useRef(currentValue);\n const length = collection.size;\n React.useEffect(() => {\n const previousValue = valueRef.current;\n valueRef.current = currentValue;\n if (previousValue === currentValue) {\n return;\n }\n\n if (autoSubmit && value.every((char) => char !== '') && value.length === length) {\n onAutoSubmit?.(value.join(''));\n attemptSubmit();\n }\n }, [attemptSubmit, autoSubmit, currentValue, length, onAutoSubmit, value]);\n\n // Before hydration (and in SSR) we can track the index of an input during\n // render, as indices calculated by the collection package should almost\n // always align with render order anyway. This ensures that index-dependent\n // attributes are immediately rendered, in case browser extensions rely on\n // those for auto-complete functionality and JS has not hydrated.\n const preHydrationIndexTracker = React.useRef<number>(0);\n const isHydrated = useIsHydrated();\n\n return (\n <OneTimePasswordFieldContext\n scope={__scopeOneTimePasswordField}\n value={value}\n attemptSubmit={attemptSubmit}\n disabled={disabled}\n readOnly={readOnly}\n autoComplete={autoComplete}\n autoFocus={autoFocus}\n form={form}\n name={name}\n placeholder={placeholder}\n type={type}\n hiddenInputRef={hiddenInputRef}\n userActionRef={userActionRef}\n dispatch={dispatch}\n validationType={validationType}\n orientation={orientation}\n preHydrationIndexTracker={preHydrationIndexTracker}\n isHydrated={isHydrated}\n >\n <Collection.Provider scope={__scopeOneTimePasswordField} state={collectionState}>\n <Collection.Slot scope={__scopeOneTimePasswordField}>\n <RovingFocusGroup.Root\n asChild\n {...rovingFocusGroupScope}\n orientation={orientation}\n dir={direction}\n >\n <Primitive.Root.div\n {...domProps}\n role=\"group\"\n ref={composedRefs}\n onPaste={composeEventHandlers(\n onPaste,\n (event: React.ClipboardEvent<HTMLDivElement>) => {\n event.preventDefault();\n const pastedValue = event.clipboardData.getData('Text');\n const value = sanitizeValue(pastedValue);\n if (!value) {\n return;\n }\n dispatch({ type: 'PASTE', value: pastedValue });\n }\n )}\n >\n {children}\n </Primitive.Root.div>\n </RovingFocusGroup.Root>\n </Collection.Slot>\n </Collection.Provider>\n </OneTimePasswordFieldContext>\n );\n }\n);\n\n/* -------------------------------------------------------------------------------------------------\n * OneTimePasswordFieldHiddenInput\n * -----------------------------------------------------------------------------------------------*/\n\ninterface OneTimePasswordFieldHiddenInputProps\n extends Omit<\n React.ComponentProps<'input'>,\n | keyof 'value'\n | 'defaultValue'\n | 'type'\n | 'onChange'\n | 'readOnly'\n | 'disabled'\n | 'autoComplete'\n | 'autoFocus'\n > {}\n\nconst OneTimePasswordFieldHiddenInput = React.forwardRef<\n HTMLInputElement,\n OneTimePasswordFieldHiddenInputProps\n>(function OneTimePasswordFieldHiddenInput(\n { __scopeOneTimePasswordField, ...props }: ScopedProps<OneTimePasswordFieldHiddenInputProps>,\n forwardedRef\n) {\n const { value, hiddenInputRef, name } = useOneTimePasswordFieldContext(\n 'OneTimePasswordFieldHiddenInput',\n __scopeOneTimePasswordField\n );\n const ref = useComposedRefs(hiddenInputRef, forwardedRef);\n return (\n <input\n ref={ref}\n name={name}\n value={value.join('').trim()}\n autoComplete=\"off\"\n autoFocus={false}\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n autoSave=\"off\"\n spellCheck={false}\n {...props}\n type=\"hidden\"\n readOnly\n />\n );\n});\n\n/* -------------------------------------------------------------------------------------------------\n * OneTimePasswordFieldInput\n * -----------------------------------------------------------------------------------------------*/\n\ninterface OneTimePasswordFieldInputProps\n extends Omit<\n Primitive.PrimitivePropsWithRef<'input'>,\n | 'value'\n | 'defaultValue'\n | 'disabled'\n | 'readOnly'\n | 'autoComplete'\n | 'autoFocus'\n | 'form'\n | 'name'\n | 'placeholder'\n | 'type'\n > {\n /**\n * Callback fired when the user input fails native HTML input validation.\n */\n onInvalidChange?: (character: string) => void;\n}\n\nconst OneTimePasswordFieldInput = React.forwardRef<\n HTMLInputElement,\n OneTimePasswordFieldInputProps\n>(function OneTimePasswordFieldInput(\n {\n __scopeOneTimePasswordField,\n onInvalidChange,\n ...props\n }: ScopedProps<OneTimePasswordFieldInputProps>,\n forwardedRef\n) {\n // TODO: warn if these values are passed\n const {\n value: _value,\n defaultValue: _defaultValue,\n disabled: _disabled,\n readOnly: _readOnly,\n autoComplete: _autoComplete,\n autoFocus: _autoFocus,\n form: _form,\n name: _name,\n placeholder: _placeholder,\n type: _type,\n ...domProps\n } = props as Primitive.PrimitivePropsWithRef<'input'>;\n\n const context = useOneTimePasswordFieldContext(\n 'OneTimePasswordFieldInput',\n __scopeOneTimePasswordField\n );\n const { dispatch, userActionRef, validationType, preHydrationIndexTracker, isHydrated } = context;\n const collection = useCollection(__scopeOneTimePasswordField);\n const rovingFocusGroupScope = useRovingFocusGroupScope(__scopeOneTimePasswordField);\n\n const inputRef = React.useRef<HTMLInputElement>(null);\n const [element, setElement] = React.useState<HTMLInputElement | null>(null);\n\n let placeholder: string | undefined;\n let index: number;\n if (!isHydrated) {\n index = preHydrationIndexTracker.current;\n preHydrationIndexTracker.current++;\n } else {\n index = element ? collection.indexOf(element) : -1;\n if (context.placeholder && context.value.length === 0) {\n // only set placeholder after hydration to prevent flickering when indices\n // are re-calculated\n placeholder = context.placeholder[index];\n }\n }\n\n const composedInputRef = useComposedRefs(forwardedRef, inputRef, setElement);\n const char = context.value[index] ?? '';\n\n const keyboardActionTimeoutRef = React.useRef<number | null>(null);\n React.useEffect(() => {\n return () => {\n window.clearTimeout(keyboardActionTimeoutRef.current!);\n };\n }, []);\n\n const totalValue = context.value.join('').trim();\n const lastSelectableIndex = clamp(totalValue.length, [0, collection.size - 1]);\n const isFocusable = index <= lastSelectableIndex;\n\n const validation =\n validationType in INPUT_VALIDATION_MAP\n ? INPUT_VALIDATION_MAP[validationType as keyof InputValidation]\n : undefined;\n\n return (\n <Collection.ItemSlot scope={__scopeOneTimePasswordField}>\n <RovingFocusGroup.Item\n {...rovingFocusGroupScope}\n asChild\n focusable={!context.disabled && isFocusable}\n active={index === lastSelectableIndex}\n >\n <Primitive.Root.input\n ref={composedInputRef}\n type=\"text\"\n aria-label={`Character ${index + 1} of ${collection.size}`}\n autoComplete={index === 0 ? context.autoComplete : 'off'}\n inputMode={validation?.inputMode}\n maxLength={1}\n pattern={validation?.pattern}\n readOnly={context.readOnly}\n value={char}\n placeholder={placeholder}\n data-radix-otp-input=\"\"\n data-radix-index={index}\n {...domProps}\n onFocus={composeEventHandlers(props.onFocus, (event) => {\n event.currentTarget.select();\n })}\n onCut={composeEventHandlers(props.onCut, (event) => {\n const currentValue = event.currentTarget.value;\n if (currentValue !== '') {\n // In this case the value will be cleared, but we don't want to\n // set it directly because the user may want to prevent default\n // behavior in the onChange handler. The userActionRef will\n // is set temporarily so the change handler can behave correctly\n // in response to the action.\n userActionRef.current = {\n type: 'cut',\n };\n // Set a short timeout to clear the action tracker after the change\n // handler has had time to complete.\n keyboardActionTimeoutRef.current = window.setTimeout(() => {\n userActionRef.current = null;\n }, 10);\n }\n })}\n onChange={composeEventHandlers(props.onChange, (event) => {\n const action = userActionRef.current;\n userActionRef.current = null;\n\n if (action) {\n switch (action.type) {\n case 'cut':\n // TODO: do we want to assume the user wantt to clear the\n // entire value here and copy the code to the clipboard instead\n // of just the value of the given input?\n dispatch({ type: 'CLEAR_CHAR', index, reason: 'Cut' });\n return;\n case 'keydown': {\n if (action.key === 'Char') {\n // update resulting from a keydown event that set a value\n // directly. Ignore.\n return;\n }\n\n const isClearing =\n action.key === 'Backspace' && (action.metaKey || action.ctrlKey);\n if (action.key === 'Clear' || isClearing) {\n dispatch({ type: 'CLEAR', reason: 'Backspace' });\n } else {\n dispatch({ type: 'CLEAR_CHAR', index, reason: action.key });\n }\n return;\n }\n default:\n return;\n }\n }\n\n // Only update the value if it matches the input pattern\n if (event.target.validity.valid) {\n if (event.target.value === '') {\n let reason: 'Backspace' | 'Delete' | 'Cut' = 'Backspace';\n if (isInputEvent(event.nativeEvent)) {\n const inputType = event.nativeEvent.inputType;\n if (inputType === 'deleteContentBackward') {\n reason = 'Backspace';\n } else if (inputType === 'deleteByCut') {\n reason = 'Cut';\n }\n }\n dispatch({ type: 'CLEAR_CHAR', index, reason });\n } else {\n dispatch({ type: 'SET_CHAR', char: event.target.value, index, event });\n }\n } else {\n const element = event.target;\n onInvalidChange?.(element.value);\n requestAnimationFrame(() => {\n if (element.ownerDocument.activeElement === element) {\n element.select();\n }\n });\n }\n })}\n onKeyDown={composeEventHandlers(props.onKeyDown, (event) => {\n switch (event.key) {\n case 'Clear':\n case 'Delete':\n case 'Backspace': {\n const currentValue = event.currentTarget.value;\n // if current value is empty, no change event will fire\n if (currentValue === '') {\n // if the user presses delete when there is no value, noop\n if (event.key === 'Delete') return;\n\n const isClearing = event.key === 'Clear' || event.metaKey || event.ctrlKey;\n if (isClearing) {\n dispatch({ type: 'CLEAR', reason: 'Backspace' });\n } else {\n const element = event.currentTarget;\n requestAnimationFrame(() => {\n focusInput(collection.from(element, -1)?.element);\n });\n }\n } else {\n // In this case the value will be cleared, but we don't want\n // to set it directly because the user may want to prevent\n // default behavior in the onChange handler. The userActionRef\n // will is set temporarily so the change handler can behave\n // correctly in response to the key vs. clearing the value by\n // setting state externally.\n userActionRef.current = {\n type: 'keydown',\n key: event.key,\n metaKey: event.metaKey,\n ctrlKey: event.ctrlKey,\n };\n // Set a short timeout to clear the action tracker after the change\n // handler has had time to complete.\n keyboardActionTimeoutRef.current = window.setTimeout(() => {\n userActionRef.current = null;\n }, 10);\n }\n\n return;\n }\n case 'Enter': {\n event.preventDefault();\n context.attemptSubmit();\n return;\n }\n case 'ArrowDown':\n case 'ArrowUp': {\n if (context.orientation === 'horizontal') {\n // in horizontal orientation, the up/down will de-select the\n // input instead of moving focus\n event.preventDefault();\n }\n return;\n }\n // TODO: Handle left/right arrow keys in vertical writing mode\n default: {\n if (event.currentTarget.value === event.key) {\n // if current value is same as the key press, no change event\n // will fire. Focus the next input.\n const element = event.currentTarget;\n event.preventDefault();\n focusInput(collection.from(element, 1)?.element);\n return;\n } else if (\n // input already has a value, but...\n event.currentTarget.value &&\n // the value is not selected\n !(\n event.currentTarget.selectionStart === 0 &&\n event.currentTarget.selectionEnd != null &&\n event.currentTarget.selectionEnd > 0\n )\n ) {\n const attemptedValue = event.key;\n if (event.key.length > 1 || event.key === ' ') {\n // not a character; do nothing\n return;\n } else {\n // user is attempting to enter a character, but the input\n // will not update by default since it's limited to a single\n // character.\n const nextInput = collection.from(event.currentTarget, 1)?.element;\n const lastInput = collection.at(-1)?.element;\n if (nextInput !== lastInput && event.currentTarget !== lastInput) {\n // if selection is before the value, set the value of the\n // current input. Otherwise set the value of the next\n // input.\n if (event.currentTarget.selectionStart === 0) {\n dispatch({ type: 'SET_CHAR', char: attemptedValue, index, event });\n } else {\n dispatch({\n type: 'SET_CHAR',\n char: attemptedValue,\n index: index + 1,\n event,\n });\n }\n\n userActionRef.current = {\n type: 'keydown',\n key: 'Char',\n metaKey: event.metaKey,\n ctrlKey: event.ctrlKey,\n };\n keyboardActionTimeoutRef.current = window.setTimeout(() => {\n userActionRef.current = null;\n }, 10);\n }\n }\n }\n }\n }\n })}\n onPointerDown={composeEventHandlers(props.onPointerDown, (event) => {\n if (index > lastSelectableIndex) {\n event.preventDefault();\n const element = collection.at(lastSelectableIndex)?.element;\n focusInput(element);\n }\n })}\n />\n </RovingFocusGroup.Item>\n </Collection.ItemSlot>\n );\n});\n\nexport {\n OneTimePasswordField,\n OneTimePasswordFieldInput,\n OneTimePasswordFieldHiddenInput,\n //\n OneTimePasswordField as Root,\n OneTimePasswordFieldInput as Input,\n OneTimePasswordFieldHiddenInput as HiddenInput,\n};\nexport type {\n OneTimePasswordFieldProps,\n OneTimePasswordFieldInputProps,\n OneTimePasswordFieldHiddenInputProps,\n InputValidationType,\n};\n\n/* -----------------------------------------------------------------------------------------------*/\n\nfunction isFormElement(element: Element | null | undefined): element is HTMLFormElement {\n return element?.tagName === 'FORM';\n}\n\nfunction removeWhitespace(value: string) {\n return value.replace(/\\s/g, '');\n}\n\nfunction focusInput(element: HTMLInputElement | null | undefined) {\n if (!element) return;\n if (element.ownerDocument.activeElement === element) {\n // if the element is already focused, select the value in the next\n // animation frame\n window.requestAnimationFrame(() => {\n element.select?.();\n });\n } else {\n element.focus();\n }\n}\n\nfunction isInputEvent(event: Event): event is InputEvent {\n return event.type === 'input';\n}\n\ntype InputType = 'password' | 'text';\ntype AutoComplete = 'off' | 'one-time-code';\ntype KeyboardActionDetails =\n | {\n type: 'keydown';\n key: 'Backspace' | 'Delete' | 'Clear' | 'Char';\n metaKey: boolean;\n ctrlKey: boolean;\n }\n | { type: 'cut' };\n\ntype UpdateAction =\n | {\n type: 'SET_CHAR';\n char: string;\n index: number;\n event: React.KeyboardEvent | React.ChangeEvent;\n }\n | { type: 'CLEAR_CHAR'; index: number; reason: 'Backspace' | 'Delete' | 'Cut' }\n | { type: 'CLEAR'; reason: 'Reset' | 'Backspace' | 'Delete' | 'Clear' }\n | { type: 'PASTE'; value: string };\ntype Dispatcher = React.Dispatch<UpdateAction>;\ntype InputValidation = Record<\n InputValidationType,\n {\n type: InputValidationType;\n regexp: RegExp;\n pattern: string;\n inputMode: 'text' | 'numeric';\n } | null\n>;\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,gBAA2B;AAC3B,gCAAgC;AAChC,0CAAqC;AACrC,uBAAqC;AACrC,8BAA8D;AAC9D,uBAAkC;AAClC,gCAA4C;AAC5C,mCAA8B;AAC9B,YAAuB;AACvB,uBAA0B;AAE1B,2BAAmC;AACnC,6BAA6B;AAC7B,oBAAsB;AACtB,oCAA+B;AAscjB;AAlcd,IAAM,uBAAuB;AAAA,EAC3B,SAAS;AAAA,IACP,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,WAAW;AAAA,EACb;AAAA,EACA,OAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,WAAW;AAAA,EACb;AAAA,EACA,cAAc;AAAA,IACZ,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,WAAW;AAAA,EACb;AAAA,EACA,MAAM;AACR;AA4BA,IAAM,+BAA+B;AACrC,IAAM,CAAC,YAAY,EAAE,eAAe,uBAAuB,kBAAkB,CAAC,QAC5E,wBAAAA,2BAAmC,4BAA4B;AACjE,IAAM,CAAC,iCAAiC,QAAI,yCAAmB,8BAA8B;AAAA,EAC3F;AAAA,EACA;AACF,CAAC;AACD,IAAM,+BAA2B,uDAA4B;AAE7D,IAAM,CAAC,6BAA6B,8BAA8B,IAChE,kCAAoE,4BAA4B;AAuHlG,IAAM,uBAA6B;AAAA,EACjC,SAAS,yBACP;AAAA,IACE;AAAA,IACA;AAAA,IACA,OAAO;AAAA,IACP;AAAA,IACA,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,WAAW;AAAA,IACX,eAAe;AAAA,IACf,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO;AAAA;AAAA,IAEP,cAAc;AAAA,IACd;AAAA,IACA,iBAAiB;AAAA,IACjB,eAAe;AAAA,IACf,GAAG;AAAA,EACL,GACA,cACA;AACA,UAAM,wBAAwB,yBAAyB,2BAA2B;AAClF,UAAM,gBAAY,qCAAa,GAAG;AAClC,UAAM,kBAAkB,kBAAkB;AAC1C,UAAM,CAAC,UAAU,IAAI;AAErB,UAAM,aAAa,qBAAqB,cAAc,IAClD,qBAAqB,cAAuC,IAC5D;AAEJ,UAAM,gBAAsB;AAAA,MAC1B,CAACC,WAA6B;AAC5B,YAAI,MAAM,QAAQA,MAAK,GAAG;AACxB,UAAAA,SAAQA,OAAM,IAAI,gBAAgB,EAAE,KAAK,EAAE;AAAA,QAC7C,OAAO;AACL,UAAAA,SAAQ,iBAAiBA,MAAK;AAAA,QAChC;AAEA,YAAI,YAAY;AAEd,gBAAM,SAAS,IAAI,OAAO,WAAW,MAAM;AAC3C,UAAAA,SAAQA,OAAM,QAAQ,QAAQ,EAAE;AAAA,QAClC,WAAW,mBAAmB;AAC5B,UAAAA,SAAQ,kBAAkBA,MAAK;AAAA,QACjC;AAEA,eAAOA,OAAM,MAAM,EAAE;AAAA,MACvB;AAAA,MACA,CAAC,YAAY,iBAAiB;AAAA,IAChC;AAEA,UAAM,kBAAwB,cAAQ,MAAM;AAC1C,aAAO,aAAa,OAAO,cAAc,SAAS,IAAI;AAAA,IACxD,GAAG,CAAC,WAAW,aAAa,CAAC;AAE7B,UAAM,CAAC,OAAO,QAAQ,QAAI,0DAAqB;AAAA,MAC7C,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,aAAa,gBAAgB,OAAO,cAAc,YAAY,IAAI,CAAC;AAAA,MACnE,UAAgB;AAAA,QACd,CAACA,WAAoB,gBAAgBA,OAAM,KAAK,EAAE,CAAC;AAAA,QACnD,CAAC,aAAa;AAAA,MAChB;AAAA,IACF,CAAC;AAGD,UAAM,eAAW,8CAA2B,CAAC,WAAW;AACtD,cAAQ,OAAO,MAAM;AAAA,QACnB,KAAK,YAAY;AACf,gBAAM,EAAE,OAAO,KAAK,IAAI;AACxB,gBAAM,gBAAgB,WAAW,GAAG,KAAK,GAAG;AAC5C,cAAI,MAAM,KAAK,MAAM,MAAM;AACzB,kBAAM,OAAO,iBAAiB,WAAW,KAAK,eAAe,CAAC,GAAG;AACjE,uBAAW,IAAI;AACf;AAAA,UACF;AAGA,cAAI,SAAS,IAAI;AACf;AAAA,UACF;AAEA,cAAI,YAAY;AACd,kBAAM,SAAS,IAAI,OAAO,WAAW,MAAM;AAC3C,kBAAM,QAAQ,KAAK,QAAQ,QAAQ,EAAE;AACrC,gBAAI,UAAU,MAAM;AAElB;AAAA,YACF;AAAA,UACF;AAGA,cAAI,MAAM,UAAU,WAAW,MAAM;AAEnC,kBAAMC,YAAW,CAAC,GAAG,KAAK;AAC1B,YAAAA,UAAS,KAAK,IAAI;AAClB,4CAAU,MAAM,SAASA,SAAQ,CAAC;AAClC,kBAAM,OAAO,iBAAiB,WAAW,KAAK,eAAe,CAAC,GAAG;AACjE,uBAAW,IAAI;AACf;AAAA,UACF;AAEA,gBAAM,WAAW,CAAC,GAAG,KAAK;AAC1B,mBAAS,KAAK,IAAI;AAElB,gBAAM,cAAc,WAAW,GAAG,EAAE,GAAG;AACvC,0CAAU,MAAM,SAAS,QAAQ,CAAC;AAClC,cAAI,kBAAkB,aAAa;AACjC,kBAAM,OAAO,iBAAiB,WAAW,KAAK,eAAe,CAAC,GAAG;AACjE,uBAAW,IAAI;AAAA,UACjB,OAAO;AACL,2BAAe,OAAO;AAAA,UACxB;AACA;AAAA,QACF;AAAA,QAEA,KAAK,cAAc;AACjB,gBAAM,EAAE,OAAO,OAAO,IAAI;AAC1B,cAAI,CAAC,MAAM,KAAK,GAAG;AACjB;AAAA,UACF;AAEA,gBAAM,WAAW,MAAM,OAAO,CAAC,GAAG,MAAM,MAAM,KAAK;AACnD,gBAAM,gBAAgB,WAAW,GAAG,KAAK,GAAG;AAC5C,gBAAM,WAAW,iBAAiB,WAAW,KAAK,eAAe,EAAE,GAAG;AAEtE,0CAAU,MAAM,SAAS,QAAQ,CAAC;AAClC,cAAI,WAAW,aAAa;AAC1B,uBAAW,QAAQ;AAAA,UACrB,WAAW,WAAW,YAAY,WAAW,OAAO;AAClD,uBAAW,aAAa;AAAA,UAC1B;AACA;AAAA,QACF;AAAA,QAEA,KAAK,SAAS;AACZ,cAAI,MAAM,WAAW,GAAG;AACtB;AAAA,UACF;AAEA,cAAI,OAAO,WAAW,eAAe,OAAO,WAAW,UAAU;AAC/D,4CAAU,MAAM,SAAS,CAAC,CAAC,CAAC;AAC5B,uBAAW,WAAW,GAAG,CAAC,GAAG,OAAO;AAAA,UACtC,OAAO;AACL,qBAAS,CAAC,CAAC;AAAA,UACb;AACA;AAAA,QACF;AAAA,QAEA,KAAK,SAAS;AACZ,gBAAM,EAAE,OAAO,YAAY,IAAI;AAC/B,gBAAMD,SAAQ,cAAc,WAAW;AACvC,cAAI,CAACA,QAAO;AACV;AAAA,UACF;AAEA,0CAAU,MAAM,SAASA,MAAK,CAAC;AAC/B,qBAAW,WAAW,GAAGA,OAAM,SAAS,CAAC,GAAG,OAAO;AACnD;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAGD,UAAM,oBAA0B,aAAO,UAAU;AACjD,IAAM,gBAAU,MAAM;AACpB,UAAI,CAAC,YAAY;AACf;AAAA,MACF;AAEA,UAAI,kBAAkB,SAAS,SAAS,WAAW,MAAM;AACvD,0BAAkB,UAAU;AAC5B,iBAAS,cAAc,MAAM,KAAK,EAAE,CAAC,CAAC;AAAA,MACxC;AAAA,IACF,GAAG,CAAC,eAAe,UAAU,YAAY,KAAK,CAAC;AAE/C,UAAM,iBAAuB,aAAyB,IAAI;AAE1D,UAAM,gBAAsB,aAAqC,IAAI;AACrE,UAAM,UAAgB,aAA8B,IAAI;AACxD,UAAM,mBAAe,2CAAgB,cAAc,OAAO;AAE1D,UAAM,aAAa,WAAW,GAAG,CAAC,GAAG;AACrC,UAAM,aAAmB,kBAAY,MAAM;AACzC,UAAI;AACJ,UAAI,MAAM;AACR,cAAM,qBAAqB,QAAQ,SAAS,iBAAiB,UAAU,eAAe,IAAI;AAC1F,YAAI,cAAc,iBAAiB,GAAG;AACpC,wBAAc;AAAA,QAChB;AAAA,MACF,WAAW,eAAe,SAAS;AACjC,sBAAc,eAAe,QAAQ;AAAA,MACvC,WAAW,YAAY;AACrB,sBAAc,WAAW;AAAA,MAC3B;AAEA,aAAO,eAAe;AAAA,IACxB,GAAG,CAAC,MAAM,UAAU,CAAC;AAErB,UAAM,gBAAsB,kBAAY,MAAM;AAC5C,YAAM,cAAc,WAAW;AAC/B,mBAAa,cAAc;AAAA,IAC7B,GAAG,CAAC,UAAU,CAAC;AAEf,IAAM,gBAAU,MAAM;AACpB,YAAME,QAAO,WAAW;AACxB,UAAIA,OAAM;AACR,cAAM,QAAQ,MAAM,SAAS,EAAE,MAAM,SAAS,QAAQ,QAAQ,CAAC;AAC/D,QAAAA,MAAK,iBAAiB,SAAS,KAAK;AACpC,eAAO,MAAMA,MAAK,oBAAoB,SAAS,KAAK;AAAA,MACtD;AAAA,IACF,GAAG,CAAC,UAAU,UAAU,CAAC;AAEzB,UAAM,eAAe,MAAM,KAAK,EAAE;AAClC,UAAM,WAAiB,aAAO,YAAY;AAC1C,UAAM,SAAS,WAAW;AAC1B,IAAM,gBAAU,MAAM;AACpB,YAAM,gBAAgB,SAAS;AAC/B,eAAS,UAAU;AACnB,UAAI,kBAAkB,cAAc;AAClC;AAAA,MACF;AAEA,UAAI,cAAc,MAAM,MAAM,CAAC,SAAS,SAAS,EAAE,KAAK,MAAM,WAAW,QAAQ;AAC/E,uBAAe,MAAM,KAAK,EAAE,CAAC;AAC7B,sBAAc;AAAA,MAChB;AAAA,IACF,GAAG,CAAC,eAAe,YAAY,cAAc,QAAQ,cAAc,KAAK,CAAC;AAOzE,UAAM,2BAAiC,aAAe,CAAC;AACvD,UAAM,iBAAa,4CAAc;AAEjC,WACE;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,QACP;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QAEA,sDAAC,WAAW,UAAX,EAAoB,OAAO,6BAA6B,OAAO,iBAC9D,sDAAC,WAAW,MAAX,EAAgB,OAAO,6BACtB;AAAA,UAAkB;AAAA,UAAjB;AAAA,YACC,SAAO;AAAA,YACN,GAAG;AAAA,YACJ;AAAA,YACA,KAAK;AAAA,YAEL;AAAA,cAAW,eAAK;AAAA,cAAf;AAAA,gBACE,GAAG;AAAA,gBACJ,MAAK;AAAA,gBACL,KAAK;AAAA,gBACL,aAAS;AAAA,kBACP;AAAA,kBACA,CAAC,UAAgD;AAC/C,0BAAM,eAAe;AACrB,0BAAM,cAAc,MAAM,cAAc,QAAQ,MAAM;AACtD,0BAAMF,SAAQ,cAAc,WAAW;AACvC,wBAAI,CAACA,QAAO;AACV;AAAA,oBACF;AACA,6BAAS,EAAE,MAAM,SAAS,OAAO,YAAY,CAAC;AAAA,kBAChD;AAAA,gBACF;AAAA,gBAEC;AAAA;AAAA,YACH;AAAA;AAAA,QACF,GACF,GACF;AAAA;AAAA,IACF;AAAA,EAEJ;AACF;AAmBA,IAAM,kCAAwC,iBAG5C,SAASG,iCACT,EAAE,6BAA6B,GAAG,MAAM,GACxC,cACA;AACA,QAAM,EAAE,OAAO,gBAAgB,KAAK,IAAI;AAAA,IACtC;AAAA,IACA;AAAA,EACF;AACA,QAAM,UAAM,2CAAgB,gBAAgB,YAAY;AACxD,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,OAAO,MAAM,KAAK,EAAE,EAAE,KAAK;AAAA,MAC3B,cAAa;AAAA,MACb,WAAW;AAAA,MACX,gBAAe;AAAA,MACf,aAAY;AAAA,MACZ,UAAS;AAAA,MACT,YAAY;AAAA,MACX,GAAG;AAAA,MACJ,MAAK;AAAA,MACL,UAAQ;AAAA;AAAA,EACV;AAEJ,CAAC;AA0BD,IAAM,4BAAkC,iBAGtC,SAASC,2BACT;AAAA,EACE;AAAA,EACA;AAAA,EACA,GAAG;AACL,GACA,cACA;AAEA,QAAM;AAAA,IACJ,OAAO;AAAA,IACP,cAAc;AAAA,IACd,UAAU;AAAA,IACV,UAAU;AAAA,IACV,cAAc;AAAA,IACd,WAAW;AAAA,IACX,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,GAAG;AAAA,EACL,IAAI;AAEJ,QAAM,UAAU;AAAA,IACd;AAAA,IACA;AAAA,EACF;AACA,QAAM,EAAE,UAAU,eAAe,gBAAgB,0BAA0B,WAAW,IAAI;AAC1F,QAAM,aAAa,cAAc,2BAA2B;AAC5D,QAAM,wBAAwB,yBAAyB,2BAA2B;AAElF,QAAM,WAAiB,aAAyB,IAAI;AACpD,QAAM,CAAC,SAAS,UAAU,IAAU,eAAkC,IAAI;AAE1E,MAAI;AACJ,MAAI;AACJ,MAAI,CAAC,YAAY;AACf,YAAQ,yBAAyB;AACjC,6BAAyB;AAAA,EAC3B,OAAO;AACL,YAAQ,UAAU,WAAW,QAAQ,OAAO,IAAI;AAChD,QAAI,QAAQ,eAAe,QAAQ,MAAM,WAAW,GAAG;AAGrD,oBAAc,QAAQ,YAAY,KAAK;AAAA,IACzC;AAAA,EACF;AAEA,QAAM,uBAAmB,2CAAgB,cAAc,UAAU,UAAU;AAC3E,QAAM,OAAO,QAAQ,MAAM,KAAK,KAAK;AAErC,QAAM,2BAAiC,aAAsB,IAAI;AACjE,EAAM,gBAAU,MAAM;AACpB,WAAO,MAAM;AACX,aAAO,aAAa,yBAAyB,OAAQ;AAAA,IACvD;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,aAAa,QAAQ,MAAM,KAAK,EAAE,EAAE,KAAK;AAC/C,QAAM,0BAAsB,qBAAM,WAAW,QAAQ,CAAC,GAAG,WAAW,OAAO,CAAC,CAAC;AAC7E,QAAM,cAAc,SAAS;AAE7B,QAAM,aACJ,kBAAkB,uBACd,qBAAqB,cAAuC,IAC5D;AAEN,SACE,4CAAC,WAAW,UAAX,EAAoB,OAAO,6BAC1B;AAAA,IAAkB;AAAA,IAAjB;AAAA,MACE,GAAG;AAAA,MACJ,SAAO;AAAA,MACP,WAAW,CAAC,QAAQ,YAAY;AAAA,MAChC,QAAQ,UAAU;AAAA,MAElB;AAAA,QAAW,eAAK;AAAA,QAAf;AAAA,UACC,KAAK;AAAA,UACL,MAAK;AAAA,UACL,cAAY,aAAa,QAAQ,CAAC,OAAO,WAAW,IAAI;AAAA,UACxD,cAAc,UAAU,IAAI,QAAQ,eAAe;AAAA,UACnD,WAAW,YAAY;AAAA,UACvB,WAAW;AAAA,UACX,SAAS,YAAY;AAAA,UACrB,UAAU,QAAQ;AAAA,UAClB,OAAO;AAAA,UACP;AAAA,UACA,wBAAqB;AAAA,UACrB,oBAAkB;AAAA,UACjB,GAAG;AAAA,UACJ,aAAS,uCAAqB,MAAM,SAAS,CAAC,UAAU;AACtD,kBAAM,cAAc,OAAO;AAAA,UAC7B,CAAC;AAAA,UACD,WAAO,uCAAqB,MAAM,OAAO,CAAC,UAAU;AAClD,kBAAM,eAAe,MAAM,cAAc;AACzC,gBAAI,iBAAiB,IAAI;AAMvB,4BAAc,UAAU;AAAA,gBACtB,MAAM;AAAA,cACR;AAGA,uCAAyB,UAAU,OAAO,WAAW,MAAM;AACzD,8BAAc,UAAU;AAAA,cAC1B,GAAG,EAAE;AAAA,YACP;AAAA,UACF,CAAC;AAAA,UACD,cAAU,uCAAqB,MAAM,UAAU,CAAC,UAAU;AACxD,kBAAM,SAAS,cAAc;AAC7B,0BAAc,UAAU;AAExB,gBAAI,QAAQ;AACV,sBAAQ,OAAO,MAAM;AAAA,gBACnB,KAAK;AAIH,2BAAS,EAAE,MAAM,cAAc,OAAO,QAAQ,MAAM,CAAC;AACrD;AAAA,gBACF,KAAK,WAAW;AACd,sBAAI,OAAO,QAAQ,QAAQ;AAGzB;AAAA,kBACF;AAEA,wBAAM,aACJ,OAAO,QAAQ,gBAAgB,OAAO,WAAW,OAAO;AAC1D,sBAAI,OAAO,QAAQ,WAAW,YAAY;AACxC,6BAAS,EAAE,MAAM,SAAS,QAAQ,YAAY,CAAC;AAAA,kBACjD,OAAO;AACL,6BAAS,EAAE,MAAM,cAAc,OAAO,QAAQ,OAAO,IAAI,CAAC;AAAA,kBAC5D;AACA;AAAA,gBACF;AAAA,gBACA;AACE;AAAA,cACJ;AAAA,YACF;AAGA,gBAAI,MAAM,OAAO,SAAS,OAAO;AAC/B,kBAAI,MAAM,OAAO,UAAU,IAAI;AAC7B,oBAAI,SAAyC;AAC7C,oBAAI,aAAa,MAAM,WAAW,GAAG;AACnC,wBAAM,YAAY,MAAM,YAAY;AACpC,sBAAI,cAAc,yBAAyB;AACzC,6BAAS;AAAA,kBACX,WAAW,cAAc,eAAe;AACtC,6BAAS;AAAA,kBACX;AAAA,gBACF;AACA,yBAAS,EAAE,MAAM,cAAc,OAAO,OAAO,CAAC;AAAA,cAChD,OAAO;AACL,yBAAS,EAAE,MAAM,YAAY,MAAM,MAAM,OAAO,OAAO,OAAO,MAAM,CAAC;AAAA,cACvE;AAAA,YACF,OAAO;AACL,oBAAMC,WAAU,MAAM;AACtB,gCAAkBA,SAAQ,KAAK;AAC/B,oCAAsB,MAAM;AAC1B,oBAAIA,SAAQ,cAAc,kBAAkBA,UAAS;AACnD,kBAAAA,SAAQ,OAAO;AAAA,gBACjB;AAAA,cACF,CAAC;AAAA,YACH;AAAA,UACF,CAAC;AAAA,UACD,eAAW,uCAAqB,MAAM,WAAW,CAAC,UAAU;AAC1D,oBAAQ,MAAM,KAAK;AAAA,cACjB,KAAK;AAAA,cACL,KAAK;AAAA,cACL,KAAK,aAAa;AAChB,sBAAM,eAAe,MAAM,cAAc;AAEzC,oBAAI,iBAAiB,IAAI;AAEvB,sBAAI,MAAM,QAAQ,SAAU;AAE5B,wBAAM,aAAa,MAAM,QAAQ,WAAW,MAAM,WAAW,MAAM;AACnE,sBAAI,YAAY;AACd,6BAAS,EAAE,MAAM,SAAS,QAAQ,YAAY,CAAC;AAAA,kBACjD,OAAO;AACL,0BAAMA,WAAU,MAAM;AACtB,0CAAsB,MAAM;AAC1B,iCAAW,WAAW,KAAKA,UAAS,EAAE,GAAG,OAAO;AAAA,oBAClD,CAAC;AAAA,kBACH;AAAA,gBACF,OAAO;AAOL,gCAAc,UAAU;AAAA,oBACtB,MAAM;AAAA,oBACN,KAAK,MAAM;AAAA,oBACX,SAAS,MAAM;AAAA,oBACf,SAAS,MAAM;AAAA,kBACjB;AAGA,2CAAyB,UAAU,OAAO,WAAW,MAAM;AACzD,kCAAc,UAAU;AAAA,kBAC1B,GAAG,EAAE;AAAA,gBACP;AAEA;AAAA,cACF;AAAA,cACA,KAAK,SAAS;AACZ,sBAAM,eAAe;AACrB,wBAAQ,cAAc;AACtB;AAAA,cACF;AAAA,cACA,KAAK;AAAA,cACL,KAAK,WAAW;AACd,oBAAI,QAAQ,gBAAgB,cAAc;AAGxC,wBAAM,eAAe;AAAA,gBACvB;AACA;AAAA,cACF;AAAA;AAAA,cAEA,SAAS;AACP,oBAAI,MAAM,cAAc,UAAU,MAAM,KAAK;AAG3C,wBAAMA,WAAU,MAAM;AACtB,wBAAM,eAAe;AACrB,6BAAW,WAAW,KAAKA,UAAS,CAAC,GAAG,OAAO;AAC/C;AAAA,gBACF;AAAA;AAAA,kBAEE,MAAM,cAAc;AAAA,kBAEpB,EACE,MAAM,cAAc,mBAAmB,KACvC,MAAM,cAAc,gBAAgB,QACpC,MAAM,cAAc,eAAe;AAAA,kBAErC;AACA,wBAAM,iBAAiB,MAAM;AAC7B,sBAAI,MAAM,IAAI,SAAS,KAAK,MAAM,QAAQ,KAAK;AAE7C;AAAA,kBACF,OAAO;AAIL,0BAAM,YAAY,WAAW,KAAK,MAAM,eAAe,CAAC,GAAG;AAC3D,0BAAM,YAAY,WAAW,GAAG,EAAE,GAAG;AACrC,wBAAI,cAAc,aAAa,MAAM,kBAAkB,WAAW;AAIhE,0BAAI,MAAM,cAAc,mBAAmB,GAAG;AAC5C,iCAAS,EAAE,MAAM,YAAY,MAAM,gBAAgB,OAAO,MAAM,CAAC;AAAA,sBACnE,OAAO;AACL,iCAAS;AAAA,0BACP,MAAM;AAAA,0BACN,MAAM;AAAA,0BACN,OAAO,QAAQ;AAAA,0BACf;AAAA,wBACF,CAAC;AAAA,sBACH;AAEA,oCAAc,UAAU;AAAA,wBACtB,MAAM;AAAA,wBACN,KAAK;AAAA,wBACL,SAAS,MAAM;AAAA,wBACf,SAAS,MAAM;AAAA,sBACjB;AACA,+CAAyB,UAAU,OAAO,WAAW,MAAM;AACzD,sCAAc,UAAU;AAAA,sBAC1B,GAAG,EAAE;AAAA,oBACP;AAAA,kBACF;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AAAA,UACF,CAAC;AAAA,UACD,mBAAe,uCAAqB,MAAM,eAAe,CAAC,UAAU;AAClE,gBAAI,QAAQ,qBAAqB;AAC/B,oBAAM,eAAe;AACrB,oBAAMA,WAAU,WAAW,GAAG,mBAAmB,GAAG;AACpD,yBAAWA,QAAO;AAAA,YACpB;AAAA,UACF,CAAC;AAAA;AAAA,MACH;AAAA;AAAA,EACF,GACF;AAEJ,CAAC;AAoBD,SAAS,cAAc,SAAiE;AACtF,SAAO,SAAS,YAAY;AAC9B;AAEA,SAAS,iBAAiB,OAAe;AACvC,SAAO,MAAM,QAAQ,OAAO,EAAE;AAChC;AAEA,SAAS,WAAW,SAA8C;AAChE,MAAI,CAAC,QAAS;AACd,MAAI,QAAQ,cAAc,kBAAkB,SAAS;AAGnD,WAAO,sBAAsB,MAAM;AACjC,cAAQ,SAAS;AAAA,IACnB,CAAC;AAAA,EACH,OAAO;AACL,YAAQ,MAAM;AAAA,EAChB;AACF;AAEA,SAAS,aAAa,OAAmC;AACvD,SAAO,MAAM,SAAS;AACxB;",
6
+ "names": ["createCollection", "value", "newValue", "form", "OneTimePasswordFieldHiddenInput", "OneTimePasswordFieldInput", "element"]
7
7
  }
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  // src/one-time-password-field.tsx
4
- import { Primitive } from "@radix-ui/react-primitive";
4
+ import * as Primitive from "@radix-ui/react-primitive";
5
5
  import { useComposedRefs } from "@radix-ui/react-compose-refs";
6
6
  import { useControllableState } from "@radix-ui/react-use-controllable-state";
7
7
  import { composeEventHandlers } from "@radix-ui/primitive";
@@ -34,32 +34,24 @@ var INPUT_VALIDATION_MAP = {
34
34
  regexp: /[^a-zA-Z0-9]/g,
35
35
  pattern: "[a-zA-Z0-9]{1}",
36
36
  inputMode: "text"
37
- }
37
+ },
38
+ none: null
38
39
  };
39
40
  var ONE_TIME_PASSWORD_FIELD_NAME = "OneTimePasswordField";
40
- var [Collection, useCollection, createCollectionScope] = createCollection(
41
- ONE_TIME_PASSWORD_FIELD_NAME
42
- );
41
+ var [Collection, { useCollection, createCollectionScope, useInitCollection }] = createCollection(ONE_TIME_PASSWORD_FIELD_NAME);
43
42
  var [createOneTimePasswordFieldContext] = createContextScope(ONE_TIME_PASSWORD_FIELD_NAME, [
44
43
  createCollectionScope,
45
44
  createRovingFocusGroupScope
46
45
  ]);
47
46
  var useRovingFocusGroupScope = createRovingFocusGroupScope();
48
47
  var [OneTimePasswordFieldContext, useOneTimePasswordFieldContext] = createOneTimePasswordFieldContext(ONE_TIME_PASSWORD_FIELD_NAME);
49
- var OneTimePasswordFieldCollectionProvider = ({
50
- __scopeOneTimePasswordField,
51
- children
52
- }) => {
53
- return /* @__PURE__ */ jsx(Collection.Provider, { scope: __scopeOneTimePasswordField, children: /* @__PURE__ */ jsx(Collection.Slot, { scope: __scopeOneTimePasswordField, children }) });
54
- };
55
- var OneTimePasswordFieldImpl = React.forwardRef(
56
- function OneTimePasswordFieldImpl2({
48
+ var OneTimePasswordField = React.forwardRef(
49
+ function OneTimePasswordFieldImpl({
57
50
  __scopeOneTimePasswordField,
58
- id,
59
51
  defaultValue,
60
52
  value: valueProp,
61
53
  onValueChange,
62
- autoSubmit,
54
+ autoSubmit = false,
63
55
  children,
64
56
  onPaste,
65
57
  onAutoSubmit,
@@ -70,26 +62,47 @@ var OneTimePasswordFieldImpl = React.forwardRef(
70
62
  form,
71
63
  name,
72
64
  placeholder,
73
- required = false,
74
65
  type = "password",
75
66
  // TODO: Change default to vertical when inputs use vertical writing mode
76
67
  orientation = "horizontal",
77
68
  dir,
78
69
  validationType = "numeric",
70
+ sanitizeValue: sanitizeValueProp,
79
71
  ...domProps
80
72
  }, forwardedRef) {
81
73
  const rovingFocusGroupScope = useRovingFocusGroupScope(__scopeOneTimePasswordField);
82
74
  const direction = useDirection(dir);
83
- const collection = useCollection(__scopeOneTimePasswordField);
84
- const validation = validationType in INPUT_VALIDATION_MAP ? INPUT_VALIDATION_MAP[validationType] : void 0;
75
+ const collectionState = useInitCollection();
76
+ const [collection] = collectionState;
77
+ const validation = INPUT_VALIDATION_MAP[validationType] ? INPUT_VALIDATION_MAP[validationType] : null;
78
+ const sanitizeValue = React.useCallback(
79
+ (value2) => {
80
+ if (Array.isArray(value2)) {
81
+ value2 = value2.map(removeWhitespace).join("");
82
+ } else {
83
+ value2 = removeWhitespace(value2);
84
+ }
85
+ if (validation) {
86
+ const regexp = new RegExp(validation.regexp);
87
+ value2 = value2.replace(regexp, "");
88
+ } else if (sanitizeValueProp) {
89
+ value2 = sanitizeValueProp(value2);
90
+ }
91
+ return value2.split("");
92
+ },
93
+ [validation, sanitizeValueProp]
94
+ );
85
95
  const controlledValue = React.useMemo(() => {
86
- return valueProp != null ? sanitizeValue(valueProp, validation?.regexp) : void 0;
87
- }, [valueProp, validation?.regexp]);
96
+ return valueProp != null ? sanitizeValue(valueProp) : void 0;
97
+ }, [valueProp, sanitizeValue]);
88
98
  const [value, setValue] = useControllableState({
89
99
  caller: "OneTimePasswordField",
90
100
  prop: controlledValue,
91
- defaultProp: defaultValue != null ? sanitizeValue(defaultValue, validation?.regexp) : [],
92
- onChange: (value2) => onValueChange?.(value2.filter(Boolean).join(""))
101
+ defaultProp: defaultValue != null ? sanitizeValue(defaultValue) : [],
102
+ onChange: React.useCallback(
103
+ (value2) => onValueChange?.(value2.join("")),
104
+ [onValueChange]
105
+ )
93
106
  });
94
107
  const dispatch = useEffectEvent((action) => {
95
108
  switch (action.type) {
@@ -119,12 +132,8 @@ var OneTimePasswordFieldImpl = React.forwardRef(
119
132
  focusInput(next);
120
133
  return;
121
134
  }
122
- const newValue = [
123
- //
124
- ...value.slice(0, index),
125
- char,
126
- ...value.slice(index)
127
- ];
135
+ const newValue = [...value];
136
+ newValue[index] = char;
128
137
  const lastElement = collection.at(-1)?.element;
129
138
  flushSync(() => setValue(newValue));
130
139
  if (currentTarget !== lastElement) {
@@ -165,7 +174,7 @@ var OneTimePasswordFieldImpl = React.forwardRef(
165
174
  }
166
175
  case "PASTE": {
167
176
  const { value: pastedValue } = action;
168
- const value2 = sanitizeValue(pastedValue, validation?.regexp);
177
+ const value2 = sanitizeValue(pastedValue);
169
178
  if (!value2) {
170
179
  return;
171
180
  }
@@ -182,9 +191,9 @@ var OneTimePasswordFieldImpl = React.forwardRef(
182
191
  }
183
192
  if (validationTypeRef.current?.type !== validation.type) {
184
193
  validationTypeRef.current = validation;
185
- setValue(sanitizeValue(value, validation.regexp));
194
+ setValue(sanitizeValue(value.join("")));
186
195
  }
187
- }, [setValue, validation, value]);
196
+ }, [sanitizeValue, setValue, validation, value]);
188
197
  const hiddenInputRef = React.useRef(null);
189
198
  const userActionRef = React.useRef(null);
190
199
  const rootRef = React.useRef(null);
@@ -245,7 +254,6 @@ var OneTimePasswordFieldImpl = React.forwardRef(
245
254
  form,
246
255
  name,
247
256
  placeholder,
248
- required,
249
257
  type,
250
258
  hiddenInputRef,
251
259
  userActionRef,
@@ -254,7 +262,7 @@ var OneTimePasswordFieldImpl = React.forwardRef(
254
262
  orientation,
255
263
  preHydrationIndexTracker,
256
264
  isHydrated,
257
- children: /* @__PURE__ */ jsx(
265
+ children: /* @__PURE__ */ jsx(Collection.Provider, { scope: __scopeOneTimePasswordField, state: collectionState, children: /* @__PURE__ */ jsx(Collection.Slot, { scope: __scopeOneTimePasswordField, children: /* @__PURE__ */ jsx(
258
266
  RovingFocusGroup.Root,
259
267
  {
260
268
  asChild: true,
@@ -262,7 +270,7 @@ var OneTimePasswordFieldImpl = React.forwardRef(
262
270
  orientation,
263
271
  dir: direction,
264
272
  children: /* @__PURE__ */ jsx(
265
- Primitive.div,
273
+ Primitive.Root.div,
266
274
  {
267
275
  ...domProps,
268
276
  role: "group",
@@ -272,7 +280,7 @@ var OneTimePasswordFieldImpl = React.forwardRef(
272
280
  (event) => {
273
281
  event.preventDefault();
274
282
  const pastedValue = event.clipboardData.getData("Text");
275
- const value2 = sanitizeValue(pastedValue, validation?.regexp);
283
+ const value2 = sanitizeValue(pastedValue);
276
284
  if (!value2) {
277
285
  return;
278
286
  }
@@ -283,18 +291,13 @@ var OneTimePasswordFieldImpl = React.forwardRef(
283
291
  }
284
292
  )
285
293
  }
286
- )
294
+ ) }) })
287
295
  }
288
296
  );
289
297
  }
290
298
  );
291
- var OneTimePasswordField = React.forwardRef(
292
- function OneTimePasswordField2(props, ref) {
293
- return /* @__PURE__ */ jsx(OneTimePasswordFieldCollectionProvider, { children: /* @__PURE__ */ jsx(OneTimePasswordFieldImpl, { ...props, ref }) });
294
- }
295
- );
296
299
  var OneTimePasswordFieldHiddenInput = React.forwardRef(function OneTimePasswordFieldHiddenInput2({ __scopeOneTimePasswordField, ...props }, forwardedRef) {
297
- const { value, hiddenInputRef } = useOneTimePasswordFieldContext(
300
+ const { value, hiddenInputRef, name } = useOneTimePasswordFieldContext(
298
301
  "OneTimePasswordFieldHiddenInput",
299
302
  __scopeOneTimePasswordField
300
303
  );
@@ -303,20 +306,25 @@ var OneTimePasswordFieldHiddenInput = React.forwardRef(function OneTimePasswordF
303
306
  "input",
304
307
  {
305
308
  ref,
306
- ...props,
307
- type: "hidden",
308
- readOnly: true,
309
+ name,
309
310
  value: value.join("").trim(),
310
311
  autoComplete: "off",
311
312
  autoFocus: false,
312
313
  autoCapitalize: "off",
313
314
  autoCorrect: "off",
314
315
  autoSave: "off",
315
- spellCheck: false
316
+ spellCheck: false,
317
+ ...props,
318
+ type: "hidden",
319
+ readOnly: true
316
320
  }
317
321
  );
318
322
  });
319
- var OneTimePasswordFieldInput = React.forwardRef(function OneTimePasswordFieldInput2({ __scopeOneTimePasswordField, ...props }, forwardedRef) {
323
+ var OneTimePasswordFieldInput = React.forwardRef(function OneTimePasswordFieldInput2({
324
+ __scopeOneTimePasswordField,
325
+ onInvalidChange,
326
+ ...props
327
+ }, forwardedRef) {
320
328
  const {
321
329
  value: _value,
322
330
  defaultValue: _defaultValue,
@@ -327,7 +335,6 @@ var OneTimePasswordFieldInput = React.forwardRef(function OneTimePasswordFieldIn
327
335
  form: _form,
328
336
  name: _name,
329
337
  placeholder: _placeholder,
330
- required: _required,
331
338
  type: _type,
332
339
  ...domProps
333
340
  } = props;
@@ -340,12 +347,16 @@ var OneTimePasswordFieldInput = React.forwardRef(function OneTimePasswordFieldIn
340
347
  const rovingFocusGroupScope = useRovingFocusGroupScope(__scopeOneTimePasswordField);
341
348
  const inputRef = React.useRef(null);
342
349
  const [element, setElement] = React.useState(null);
350
+ let placeholder;
343
351
  let index;
344
352
  if (!isHydrated) {
345
353
  index = preHydrationIndexTracker.current;
346
354
  preHydrationIndexTracker.current++;
347
355
  } else {
348
356
  index = element ? collection.indexOf(element) : -1;
357
+ if (context.placeholder && context.value.length === 0) {
358
+ placeholder = context.placeholder[index];
359
+ }
349
360
  }
350
361
  const composedInputRef = useComposedRefs(forwardedRef, inputRef, setElement);
351
362
  const char = context.value[index] ?? "";
@@ -367,7 +378,7 @@ var OneTimePasswordFieldInput = React.forwardRef(function OneTimePasswordFieldIn
367
378
  focusable: !context.disabled && isFocusable,
368
379
  active: index === lastSelectableIndex,
369
380
  children: /* @__PURE__ */ jsx(
370
- Primitive.input,
381
+ Primitive.Root.input,
371
382
  {
372
383
  ref: composedInputRef,
373
384
  type: "text",
@@ -378,6 +389,7 @@ var OneTimePasswordFieldInput = React.forwardRef(function OneTimePasswordFieldIn
378
389
  pattern: validation?.pattern,
379
390
  readOnly: context.readOnly,
380
391
  value: char,
392
+ placeholder,
381
393
  "data-radix-otp-input": "",
382
394
  "data-radix-index": index,
383
395
  ...domProps,
@@ -408,7 +420,7 @@ var OneTimePasswordFieldInput = React.forwardRef(function OneTimePasswordFieldIn
408
420
  return;
409
421
  }
410
422
  const isClearing = action.key === "Backspace" && (action.metaKey || action.ctrlKey);
411
- if (isClearing) {
423
+ if (action.key === "Clear" || isClearing) {
412
424
  dispatch({ type: "CLEAR", reason: "Backspace" });
413
425
  } else {
414
426
  dispatch({ type: "CLEAR_CHAR", index, reason: action.key });
@@ -436,6 +448,7 @@ var OneTimePasswordFieldInput = React.forwardRef(function OneTimePasswordFieldIn
436
448
  }
437
449
  } else {
438
450
  const element2 = event.target;
451
+ onInvalidChange?.(element2.value);
439
452
  requestAnimationFrame(() => {
440
453
  if (element2.ownerDocument.activeElement === element2) {
441
454
  element2.select();
@@ -445,12 +458,13 @@ var OneTimePasswordFieldInput = React.forwardRef(function OneTimePasswordFieldIn
445
458
  }),
446
459
  onKeyDown: composeEventHandlers(props.onKeyDown, (event) => {
447
460
  switch (event.key) {
461
+ case "Clear":
448
462
  case "Delete":
449
463
  case "Backspace": {
450
464
  const currentValue = event.currentTarget.value;
451
465
  if (currentValue === "") {
452
466
  if (event.key === "Delete") return;
453
- const isClearing = event.metaKey || event.ctrlKey;
467
+ const isClearing = event.key === "Clear" || event.metaKey || event.ctrlKey;
454
468
  if (isClearing) {
455
469
  dispatch({ type: "CLEAR", reason: "Backspace" });
456
470
  } else {
@@ -540,21 +554,11 @@ var OneTimePasswordFieldInput = React.forwardRef(function OneTimePasswordFieldIn
540
554
  }
541
555
  ) });
542
556
  });
543
- var Root2 = OneTimePasswordField;
544
- var Input = OneTimePasswordFieldInput;
545
- var HiddenInput = OneTimePasswordFieldHiddenInput;
546
557
  function isFormElement(element) {
547
558
  return element?.tagName === "FORM";
548
559
  }
549
- function sanitizeValue(value, regexp) {
550
- if (Array.isArray(value)) {
551
- value = value.join("");
552
- }
553
- if (regexp) {
554
- regexp = new RegExp(regexp);
555
- return value.replace(regexp, "").split("").filter(Boolean);
556
- }
557
- return value.split("").filter(Boolean);
560
+ function removeWhitespace(value) {
561
+ return value.replace(/\s/g, "");
558
562
  }
559
563
  function focusInput(element) {
560
564
  if (!element) return;
@@ -570,11 +574,11 @@ function isInputEvent(event) {
570
574
  return event.type === "input";
571
575
  }
572
576
  export {
573
- HiddenInput,
574
- Input,
577
+ OneTimePasswordFieldHiddenInput as HiddenInput,
578
+ OneTimePasswordFieldInput as Input,
575
579
  OneTimePasswordField,
576
580
  OneTimePasswordFieldHiddenInput,
577
581
  OneTimePasswordFieldInput,
578
- Root2 as Root
582
+ OneTimePasswordField as Root
579
583
  };
580
584
  //# sourceMappingURL=index.mjs.map