@radix-ui/react-one-time-password-field 0.1.8 → 0.1.9-rc.1762290574118

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 CHANGED
@@ -394,7 +394,9 @@ var OneTimePasswordFieldInput = React.forwardRef(function OneTimePasswordFieldIn
394
394
  const keyboardActionTimeoutRef = React.useRef(null);
395
395
  React.useEffect(() => {
396
396
  return () => {
397
- window.clearTimeout(keyboardActionTimeoutRef.current);
397
+ if (keyboardActionTimeoutRef.current) {
398
+ window.clearTimeout(keyboardActionTimeoutRef.current);
399
+ }
398
400
  };
399
401
  }, []);
400
402
  const totalValue = context.value.join("").trim();
@@ -423,7 +425,7 @@ var OneTimePasswordFieldInput = React.forwardRef(function OneTimePasswordFieldIn
423
425
  "data-protonpass-ignore": supportsAutoComplete ? void 0 : "true",
424
426
  "data-bwignore": supportsAutoComplete ? void 0 : "true",
425
427
  inputMode: validation?.inputMode,
426
- maxLength: 1,
428
+ maxLength: supportsAutoComplete ? collection.size : 1,
427
429
  pattern: validation?.pattern,
428
430
  readOnly: context.readOnly,
429
431
  value: char,
@@ -437,9 +439,7 @@ var OneTimePasswordFieldInput = React.forwardRef(function OneTimePasswordFieldIn
437
439
  onCut: (0, import_primitive.composeEventHandlers)(props.onCut, (event) => {
438
440
  const currentValue = event.currentTarget.value;
439
441
  if (currentValue !== "") {
440
- userActionRef.current = {
441
- type: "cut"
442
- };
442
+ userActionRef.current = { type: "cut" };
443
443
  keyboardActionTimeoutRef.current = window.setTimeout(() => {
444
444
  userActionRef.current = null;
445
445
  }, 10);
@@ -449,7 +449,11 @@ var OneTimePasswordFieldInput = React.forwardRef(function OneTimePasswordFieldIn
449
449
  const value = event.currentTarget.value;
450
450
  if (value.length > 1) {
451
451
  event.preventDefault();
452
+ userActionRef.current = { type: "autocomplete-paste" };
452
453
  dispatch({ type: "PASTE", value });
454
+ keyboardActionTimeoutRef.current = window.setTimeout(() => {
455
+ userActionRef.current = null;
456
+ }, 10);
453
457
  }
454
458
  }),
455
459
  onChange: (0, import_primitive.composeEventHandlers)(props.onChange, (event) => {
@@ -462,6 +466,8 @@ var OneTimePasswordFieldInput = React.forwardRef(function OneTimePasswordFieldIn
462
466
  case "cut":
463
467
  dispatch({ type: "CLEAR_CHAR", index, reason: "Cut" });
464
468
  return;
469
+ case "autocomplete-paste":
470
+ return;
465
471
  case "keydown": {
466
472
  if (action.key === "Char") {
467
473
  return;
@@ -475,6 +481,7 @@ var OneTimePasswordFieldInput = React.forwardRef(function OneTimePasswordFieldIn
475
481
  return;
476
482
  }
477
483
  default:
484
+ action;
478
485
  return;
479
486
  }
480
487
  }
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 * 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 readOnly: boolean;\n type: InputType;\n userActionRef: React.RefObject<KeyboardActionDetails | null>;\n validationType: InputValidationType;\n value: string[];\n sanitizeValue: (arg: string | string[]) => 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 = 'text',\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 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 isHydrated={isHydrated}\n sanitizeValue={sanitizeValue}\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 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 * User-provided index to determine the order of the inputs. This is useful if\n * you need certain index-based attributes to be set on the initial render,\n * often to prevent flickering after hydration.\n */\n index?: number;\n}\n\nconst OneTimePasswordFieldInput = React.forwardRef<\n HTMLInputElement,\n OneTimePasswordFieldInputProps\n>(function OneTimePasswordFieldInput(\n {\n __scopeOneTimePasswordField,\n onInvalidChange,\n index: indexProp,\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, isHydrated, disabled } = 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 const index = indexProp ?? (element ? collection.indexOf(element) : -1);\n const canSetPlaceholder = indexProp != null || isHydrated;\n let placeholder: string | undefined;\n if (canSetPlaceholder && 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 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 {({ hasTabStop, isCurrentTabStop }) => {\n const supportsAutoComplete = hasTabStop ? isCurrentTabStop : index === 0;\n return (\n <Primitive.Root.input\n ref={composedInputRef}\n type={context.type}\n disabled={disabled}\n aria-label={`Character ${index + 1} of ${collection.size}`}\n autoComplete={supportsAutoComplete ? context.autoComplete : 'off'}\n data-1p-ignore={supportsAutoComplete ? undefined : 'true'}\n data-lpignore={supportsAutoComplete ? undefined : 'true'}\n data-protonpass-ignore={supportsAutoComplete ? undefined : 'true'}\n data-bwignore={supportsAutoComplete ? undefined : 'true'}\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 onInput={composeEventHandlers(props.onInput, (event) => {\n const value = event.currentTarget.value;\n if (value.length > 1) {\n // Password managers may try to insert the code into a single\n // input, in which case form validation will fail to prevent\n // additional input. Handle this the same as if a user were\n // pasting a value.\n event.preventDefault();\n dispatch({ type: 'PASTE', value });\n }\n })}\n onChange={composeEventHandlers(props.onChange, (event) => {\n const value = event.target.value;\n event.preventDefault();\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 (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: 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 event.preventDefault();\n const indexToFocus = Math.min(index, lastSelectableIndex);\n const element = collection.at(indexToFocus)?.element;\n focusInput(element);\n })}\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": "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",
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 readOnly: boolean;\n type: InputType;\n userActionRef: React.RefObject<KeyboardActionDetails | null>;\n validationType: InputValidationType;\n value: string[];\n sanitizeValue: (arg: string | string[]) => 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 = 'text',\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 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 isHydrated={isHydrated}\n sanitizeValue={sanitizeValue}\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 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 * User-provided index to determine the order of the inputs. This is useful if\n * you need certain index-based attributes to be set on the initial render,\n * often to prevent flickering after hydration.\n */\n index?: number;\n}\n\nconst OneTimePasswordFieldInput = React.forwardRef<\n HTMLInputElement,\n OneTimePasswordFieldInputProps\n>(function OneTimePasswordFieldInput(\n {\n __scopeOneTimePasswordField,\n onInvalidChange,\n index: indexProp,\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, isHydrated, disabled } = 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 const index = indexProp ?? (element ? collection.indexOf(element) : -1);\n const canSetPlaceholder = indexProp != null || isHydrated;\n let placeholder: string | undefined;\n if (canSetPlaceholder && 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 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 if (keyboardActionTimeoutRef.current) {\n window.clearTimeout(keyboardActionTimeoutRef.current);\n }\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 {({ hasTabStop, isCurrentTabStop }) => {\n const supportsAutoComplete = hasTabStop ? isCurrentTabStop : index === 0;\n return (\n <Primitive.Root.input\n ref={composedInputRef}\n type={context.type}\n disabled={disabled}\n aria-label={`Character ${index + 1} of ${collection.size}`}\n autoComplete={supportsAutoComplete ? context.autoComplete : 'off'}\n data-1p-ignore={supportsAutoComplete ? undefined : 'true'}\n data-lpignore={supportsAutoComplete ? undefined : 'true'}\n data-protonpass-ignore={supportsAutoComplete ? undefined : 'true'}\n data-bwignore={supportsAutoComplete ? undefined : 'true'}\n inputMode={validation?.inputMode}\n maxLength={supportsAutoComplete ? collection.size : 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 // be set temporarily so the change handler can behave correctly\n // in response to the action.\n userActionRef.current = { type: 'cut' };\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 onInput={composeEventHandlers(props.onInput, (event) => {\n const value = event.currentTarget.value;\n if (value.length > 1) {\n // Password managers may try to insert the code into a single\n // input, in which case form validation will fail to prevent\n // additional input. Handle this the same as if a user were\n // pasting a value.\n event.preventDefault();\n userActionRef.current = { type: 'autocomplete-paste' };\n dispatch({ type: 'PASTE', value });\n keyboardActionTimeoutRef.current = window.setTimeout(() => {\n userActionRef.current = null;\n }, 10);\n }\n })}\n onChange={composeEventHandlers(props.onChange, (event) => {\n const value = event.target.value;\n event.preventDefault();\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 wants 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 'autocomplete-paste':\n // the PASTE handler will already set the value and focus the final\n // input; we want to skip focusing the wrong element if the browser fires\n // onChange for the first input. This sometimes happens during autocomplete.\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 action satisfies never;\n return;\n }\n }\n\n // Only update the value if it matches the input pattern\n if (event.target.validity.valid) {\n if (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: 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 event.preventDefault();\n const indexToFocus = Math.min(index, lastSelectableIndex);\n const element = collection.at(indexToFocus)?.element;\n focusInput(element);\n })}\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 | { type: 'autocomplete-paste' };\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": "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",
6
6
  "names": ["createCollection", "value", "newValue", "form", "OneTimePasswordFieldHiddenInput", "OneTimePasswordFieldInput", "element"]
7
7
  }
package/dist/index.mjs CHANGED
@@ -354,7 +354,9 @@ var OneTimePasswordFieldInput = React.forwardRef(function OneTimePasswordFieldIn
354
354
  const keyboardActionTimeoutRef = React.useRef(null);
355
355
  React.useEffect(() => {
356
356
  return () => {
357
- window.clearTimeout(keyboardActionTimeoutRef.current);
357
+ if (keyboardActionTimeoutRef.current) {
358
+ window.clearTimeout(keyboardActionTimeoutRef.current);
359
+ }
358
360
  };
359
361
  }, []);
360
362
  const totalValue = context.value.join("").trim();
@@ -383,7 +385,7 @@ var OneTimePasswordFieldInput = React.forwardRef(function OneTimePasswordFieldIn
383
385
  "data-protonpass-ignore": supportsAutoComplete ? void 0 : "true",
384
386
  "data-bwignore": supportsAutoComplete ? void 0 : "true",
385
387
  inputMode: validation?.inputMode,
386
- maxLength: 1,
388
+ maxLength: supportsAutoComplete ? collection.size : 1,
387
389
  pattern: validation?.pattern,
388
390
  readOnly: context.readOnly,
389
391
  value: char,
@@ -397,9 +399,7 @@ var OneTimePasswordFieldInput = React.forwardRef(function OneTimePasswordFieldIn
397
399
  onCut: composeEventHandlers(props.onCut, (event) => {
398
400
  const currentValue = event.currentTarget.value;
399
401
  if (currentValue !== "") {
400
- userActionRef.current = {
401
- type: "cut"
402
- };
402
+ userActionRef.current = { type: "cut" };
403
403
  keyboardActionTimeoutRef.current = window.setTimeout(() => {
404
404
  userActionRef.current = null;
405
405
  }, 10);
@@ -409,7 +409,11 @@ var OneTimePasswordFieldInput = React.forwardRef(function OneTimePasswordFieldIn
409
409
  const value = event.currentTarget.value;
410
410
  if (value.length > 1) {
411
411
  event.preventDefault();
412
+ userActionRef.current = { type: "autocomplete-paste" };
412
413
  dispatch({ type: "PASTE", value });
414
+ keyboardActionTimeoutRef.current = window.setTimeout(() => {
415
+ userActionRef.current = null;
416
+ }, 10);
413
417
  }
414
418
  }),
415
419
  onChange: composeEventHandlers(props.onChange, (event) => {
@@ -422,6 +426,8 @@ var OneTimePasswordFieldInput = React.forwardRef(function OneTimePasswordFieldIn
422
426
  case "cut":
423
427
  dispatch({ type: "CLEAR_CHAR", index, reason: "Cut" });
424
428
  return;
429
+ case "autocomplete-paste":
430
+ return;
425
431
  case "keydown": {
426
432
  if (action.key === "Char") {
427
433
  return;
@@ -435,6 +441,7 @@ var OneTimePasswordFieldInput = React.forwardRef(function OneTimePasswordFieldIn
435
441
  return;
436
442
  }
437
443
  default:
444
+ action;
438
445
  return;
439
446
  }
440
447
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/one-time-password-field.tsx"],
4
- "sourcesContent": ["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 readOnly: boolean;\n type: InputType;\n userActionRef: React.RefObject<KeyboardActionDetails | null>;\n validationType: InputValidationType;\n value: string[];\n sanitizeValue: (arg: string | string[]) => 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 = 'text',\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 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 isHydrated={isHydrated}\n sanitizeValue={sanitizeValue}\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 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 * User-provided index to determine the order of the inputs. This is useful if\n * you need certain index-based attributes to be set on the initial render,\n * often to prevent flickering after hydration.\n */\n index?: number;\n}\n\nconst OneTimePasswordFieldInput = React.forwardRef<\n HTMLInputElement,\n OneTimePasswordFieldInputProps\n>(function OneTimePasswordFieldInput(\n {\n __scopeOneTimePasswordField,\n onInvalidChange,\n index: indexProp,\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, isHydrated, disabled } = 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 const index = indexProp ?? (element ? collection.indexOf(element) : -1);\n const canSetPlaceholder = indexProp != null || isHydrated;\n let placeholder: string | undefined;\n if (canSetPlaceholder && 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 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 {({ hasTabStop, isCurrentTabStop }) => {\n const supportsAutoComplete = hasTabStop ? isCurrentTabStop : index === 0;\n return (\n <Primitive.Root.input\n ref={composedInputRef}\n type={context.type}\n disabled={disabled}\n aria-label={`Character ${index + 1} of ${collection.size}`}\n autoComplete={supportsAutoComplete ? context.autoComplete : 'off'}\n data-1p-ignore={supportsAutoComplete ? undefined : 'true'}\n data-lpignore={supportsAutoComplete ? undefined : 'true'}\n data-protonpass-ignore={supportsAutoComplete ? undefined : 'true'}\n data-bwignore={supportsAutoComplete ? undefined : 'true'}\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 onInput={composeEventHandlers(props.onInput, (event) => {\n const value = event.currentTarget.value;\n if (value.length > 1) {\n // Password managers may try to insert the code into a single\n // input, in which case form validation will fail to prevent\n // additional input. Handle this the same as if a user were\n // pasting a value.\n event.preventDefault();\n dispatch({ type: 'PASTE', value });\n }\n })}\n onChange={composeEventHandlers(props.onChange, (event) => {\n const value = event.target.value;\n event.preventDefault();\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 (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: 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 event.preventDefault();\n const indexToFocus = Math.min(index, lastSelectableIndex);\n const element = collection.at(indexToFocus)?.element;\n focusInput(element);\n })}\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": "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",
4
+ "sourcesContent": ["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 readOnly: boolean;\n type: InputType;\n userActionRef: React.RefObject<KeyboardActionDetails | null>;\n validationType: InputValidationType;\n value: string[];\n sanitizeValue: (arg: string | string[]) => 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 = 'text',\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 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 isHydrated={isHydrated}\n sanitizeValue={sanitizeValue}\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 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 * User-provided index to determine the order of the inputs. This is useful if\n * you need certain index-based attributes to be set on the initial render,\n * often to prevent flickering after hydration.\n */\n index?: number;\n}\n\nconst OneTimePasswordFieldInput = React.forwardRef<\n HTMLInputElement,\n OneTimePasswordFieldInputProps\n>(function OneTimePasswordFieldInput(\n {\n __scopeOneTimePasswordField,\n onInvalidChange,\n index: indexProp,\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, isHydrated, disabled } = 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 const index = indexProp ?? (element ? collection.indexOf(element) : -1);\n const canSetPlaceholder = indexProp != null || isHydrated;\n let placeholder: string | undefined;\n if (canSetPlaceholder && 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 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 if (keyboardActionTimeoutRef.current) {\n window.clearTimeout(keyboardActionTimeoutRef.current);\n }\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 {({ hasTabStop, isCurrentTabStop }) => {\n const supportsAutoComplete = hasTabStop ? isCurrentTabStop : index === 0;\n return (\n <Primitive.Root.input\n ref={composedInputRef}\n type={context.type}\n disabled={disabled}\n aria-label={`Character ${index + 1} of ${collection.size}`}\n autoComplete={supportsAutoComplete ? context.autoComplete : 'off'}\n data-1p-ignore={supportsAutoComplete ? undefined : 'true'}\n data-lpignore={supportsAutoComplete ? undefined : 'true'}\n data-protonpass-ignore={supportsAutoComplete ? undefined : 'true'}\n data-bwignore={supportsAutoComplete ? undefined : 'true'}\n inputMode={validation?.inputMode}\n maxLength={supportsAutoComplete ? collection.size : 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 // be set temporarily so the change handler can behave correctly\n // in response to the action.\n userActionRef.current = { type: 'cut' };\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 onInput={composeEventHandlers(props.onInput, (event) => {\n const value = event.currentTarget.value;\n if (value.length > 1) {\n // Password managers may try to insert the code into a single\n // input, in which case form validation will fail to prevent\n // additional input. Handle this the same as if a user were\n // pasting a value.\n event.preventDefault();\n userActionRef.current = { type: 'autocomplete-paste' };\n dispatch({ type: 'PASTE', value });\n keyboardActionTimeoutRef.current = window.setTimeout(() => {\n userActionRef.current = null;\n }, 10);\n }\n })}\n onChange={composeEventHandlers(props.onChange, (event) => {\n const value = event.target.value;\n event.preventDefault();\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 wants 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 'autocomplete-paste':\n // the PASTE handler will already set the value and focus the final\n // input; we want to skip focusing the wrong element if the browser fires\n // onChange for the first input. This sometimes happens during autocomplete.\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 action satisfies never;\n return;\n }\n }\n\n // Only update the value if it matches the input pattern\n if (event.target.validity.valid) {\n if (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: 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 event.preventDefault();\n const indexToFocus = Math.min(index, lastSelectableIndex);\n const element = collection.at(indexToFocus)?.element;\n focusInput(element);\n })}\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 | { type: 'autocomplete-paste' };\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": "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",
6
6
  "names": ["value", "newValue", "form", "OneTimePasswordFieldHiddenInput", "OneTimePasswordFieldInput", "element"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@radix-ui/react-one-time-password-field",
3
- "version": "0.1.8",
3
+ "version": "0.1.9-rc.1762290574118",
4
4
  "license": "MIT",
5
5
  "source": "./src/index.ts",
6
6
  "main": "./dist/index.js",
@@ -13,27 +13,27 @@
13
13
  "sideEffects": false,
14
14
  "dependencies": {
15
15
  "@radix-ui/primitive": "1.1.3",
16
- "@radix-ui/react-collection": "1.1.7",
16
+ "@radix-ui/react-collection": "1.1.9-rc.1762290574118",
17
17
  "@radix-ui/react-compose-refs": "1.1.2",
18
+ "@radix-ui/react-context": "1.1.3",
18
19
  "@radix-ui/react-direction": "1.1.1",
19
- "@radix-ui/react-context": "1.1.2",
20
- "@radix-ui/react-primitive": "2.1.3",
21
20
  "@radix-ui/number": "1.1.1",
22
- "@radix-ui/react-roving-focus": "1.1.11",
21
+ "@radix-ui/react-primitive": "2.1.4",
22
+ "@radix-ui/react-roving-focus": "1.1.12-rc.1762290574118",
23
23
  "@radix-ui/react-use-controllable-state": "1.2.2",
24
24
  "@radix-ui/react-use-effect-event": "0.0.2",
25
25
  "@radix-ui/react-use-is-hydrated": "0.1.0",
26
26
  "@radix-ui/react-use-layout-effect": "1.1.1"
27
27
  },
28
28
  "devDependencies": {
29
- "@types/react": "^19.0.7",
30
- "@types/react-dom": "^19.0.3",
31
- "eslint": "^9.18.0",
32
- "react": "^19.1.0",
33
- "react-dom": "^19.1.0",
34
- "typescript": "^5.7.3",
35
- "@repo/eslint-config": "0.0.0",
29
+ "@types/react": "^19.2.2",
30
+ "@types/react-dom": "^19.2.2",
31
+ "eslint": "^9.38.0",
32
+ "react": "^19.2.0",
33
+ "react-dom": "^19.2.0",
34
+ "typescript": "^5.9.3",
36
35
  "@repo/builder": "0.0.0",
36
+ "@repo/eslint-config": "0.0.0",
37
37
  "@repo/typescript-config": "0.0.0"
38
38
  },
39
39
  "peerDependencies": {
@@ -61,6 +61,7 @@
61
61
  "scripts": {
62
62
  "lint": "eslint --max-warnings 0 src",
63
63
  "clean": "rm -rf dist",
64
+ "reset": "rm -rf dist node_modules",
64
65
  "typecheck": "tsc --noEmit",
65
66
  "build": "radix-build"
66
67
  },
@@ -22,7 +22,7 @@ describe('given a default OneTimePasswordField', () => {
22
22
  <OneTimePasswordField.Input />
23
23
  <OneTimePasswordField.Input />
24
24
  <OneTimePasswordField.HiddenInput name="code" />
25
- </OneTimePasswordField.Root>
25
+ </OneTimePasswordField.Root>,
26
26
  );
27
27
  });
28
28
 
@@ -37,18 +37,18 @@ describe('given a default OneTimePasswordField', () => {
37
37
  <OneTimePasswordField.Root type="password">
38
38
  <OneTimePasswordField.Input />
39
39
  <OneTimePasswordField.HiddenInput name="code" />
40
- </OneTimePasswordField.Root>
40
+ </OneTimePasswordField.Root>,
41
41
  );
42
42
 
43
43
  const input = rendered.container.querySelector(
44
- 'input:not([type="hidden"])'
44
+ 'input:not([type="hidden"])',
45
45
  ) as HTMLInputElement;
46
46
 
47
47
  await userEvent.type(input, '1');
48
48
  expect(input.type).toBe('password');
49
49
 
50
50
  const hiddenInput = rendered.container.querySelector(
51
- 'input[type="hidden"]'
51
+ 'input[type="hidden"]',
52
52
  ) as HTMLInputElement;
53
53
  expect(hiddenInput.value).toBe('1');
54
54
  });
@@ -59,11 +59,11 @@ describe('given a default OneTimePasswordField', () => {
59
59
  <OneTimePasswordField.Input />
60
60
  <OneTimePasswordField.Input />
61
61
  <OneTimePasswordField.HiddenInput name="code" />
62
- </OneTimePasswordField.Root>
62
+ </OneTimePasswordField.Root>,
63
63
  );
64
64
 
65
65
  const inputs = rendered.container.querySelectorAll('input:not([type="hidden"])');
66
- inputs.forEach(input => {
66
+ inputs.forEach((input) => {
67
67
  expect(input).toBeDisabled();
68
68
  });
69
69
  });
@@ -219,7 +219,7 @@ const OneTimePasswordField = React.forwardRef<HTMLDivElement, OneTimePasswordFie
219
219
  sanitizeValue: sanitizeValueProp,
220
220
  ...domProps
221
221
  }: ScopedProps<OneTimePasswordFieldProps>,
222
- forwardedRef
222
+ forwardedRef,
223
223
  ) {
224
224
  const rovingFocusGroupScope = useRovingFocusGroupScope(__scopeOneTimePasswordField);
225
225
  const direction = useDirection(dir);
@@ -248,7 +248,7 @@ const OneTimePasswordField = React.forwardRef<HTMLDivElement, OneTimePasswordFie
248
248
 
249
249
  return value.split('');
250
250
  },
251
- [validation, sanitizeValueProp]
251
+ [validation, sanitizeValueProp],
252
252
  );
253
253
 
254
254
  const controlledValue = React.useMemo(() => {
@@ -261,7 +261,7 @@ const OneTimePasswordField = React.forwardRef<HTMLDivElement, OneTimePasswordFie
261
261
  defaultProp: defaultValue != null ? sanitizeValue(defaultValue) : [],
262
262
  onChange: React.useCallback(
263
263
  (value: string[]) => onValueChange?.(value.join('')),
264
- [onValueChange]
264
+ [onValueChange],
265
265
  ),
266
266
  });
267
267
 
@@ -469,7 +469,7 @@ const OneTimePasswordField = React.forwardRef<HTMLDivElement, OneTimePasswordFie
469
469
  event.preventDefault();
470
470
  const pastedValue = event.clipboardData.getData('Text');
471
471
  dispatch({ type: 'PASTE', value: pastedValue });
472
- }
472
+ },
473
473
  )}
474
474
  >
475
475
  {children}
@@ -479,7 +479,7 @@ const OneTimePasswordField = React.forwardRef<HTMLDivElement, OneTimePasswordFie
479
479
  </Collection.Provider>
480
480
  </OneTimePasswordFieldContext>
481
481
  );
482
- }
482
+ },
483
483
  );
484
484
 
485
485
  /* -------------------------------------------------------------------------------------------------
@@ -504,11 +504,11 @@ const OneTimePasswordFieldHiddenInput = React.forwardRef<
504
504
  OneTimePasswordFieldHiddenInputProps
505
505
  >(function OneTimePasswordFieldHiddenInput(
506
506
  { __scopeOneTimePasswordField, ...props }: ScopedProps<OneTimePasswordFieldHiddenInputProps>,
507
- forwardedRef
507
+ forwardedRef,
508
508
  ) {
509
509
  const { value, hiddenInputRef, name } = useOneTimePasswordFieldContext(
510
510
  'OneTimePasswordFieldHiddenInput',
511
- __scopeOneTimePasswordField
511
+ __scopeOneTimePasswordField,
512
512
  );
513
513
  const ref = useComposedRefs(hiddenInputRef, forwardedRef);
514
514
  return (
@@ -569,7 +569,7 @@ const OneTimePasswordFieldInput = React.forwardRef<
569
569
  index: indexProp,
570
570
  ...props
571
571
  }: ScopedProps<OneTimePasswordFieldInputProps>,
572
- forwardedRef
572
+ forwardedRef,
573
573
  ) {
574
574
  // TODO: warn if these values are passed
575
575
  const {
@@ -588,7 +588,7 @@ const OneTimePasswordFieldInput = React.forwardRef<
588
588
 
589
589
  const context = useOneTimePasswordFieldContext(
590
590
  'OneTimePasswordFieldInput',
591
- __scopeOneTimePasswordField
591
+ __scopeOneTimePasswordField,
592
592
  );
593
593
  const { dispatch, userActionRef, validationType, isHydrated, disabled } = context;
594
594
  const collection = useCollection(__scopeOneTimePasswordField);
@@ -612,7 +612,9 @@ const OneTimePasswordFieldInput = React.forwardRef<
612
612
  const keyboardActionTimeoutRef = React.useRef<number | null>(null);
613
613
  React.useEffect(() => {
614
614
  return () => {
615
- window.clearTimeout(keyboardActionTimeoutRef.current!);
615
+ if (keyboardActionTimeoutRef.current) {
616
+ window.clearTimeout(keyboardActionTimeoutRef.current);
617
+ }
616
618
  };
617
619
  }, []);
618
620
 
@@ -647,7 +649,7 @@ const OneTimePasswordFieldInput = React.forwardRef<
647
649
  data-protonpass-ignore={supportsAutoComplete ? undefined : 'true'}
648
650
  data-bwignore={supportsAutoComplete ? undefined : 'true'}
649
651
  inputMode={validation?.inputMode}
650
- maxLength={1}
652
+ maxLength={supportsAutoComplete ? collection.size : 1}
651
653
  pattern={validation?.pattern}
652
654
  readOnly={context.readOnly}
653
655
  value={char}
@@ -664,11 +666,9 @@ const OneTimePasswordFieldInput = React.forwardRef<
664
666
  // In this case the value will be cleared, but we don't want to
665
667
  // set it directly because the user may want to prevent default
666
668
  // behavior in the onChange handler. The userActionRef will
667
- // is set temporarily so the change handler can behave correctly
669
+ // be set temporarily so the change handler can behave correctly
668
670
  // in response to the action.
669
- userActionRef.current = {
670
- type: 'cut',
671
- };
671
+ userActionRef.current = { type: 'cut' };
672
672
  // Set a short timeout to clear the action tracker after the change
673
673
  // handler has had time to complete.
674
674
  keyboardActionTimeoutRef.current = window.setTimeout(() => {
@@ -684,7 +684,11 @@ const OneTimePasswordFieldInput = React.forwardRef<
684
684
  // additional input. Handle this the same as if a user were
685
685
  // pasting a value.
686
686
  event.preventDefault();
687
+ userActionRef.current = { type: 'autocomplete-paste' };
687
688
  dispatch({ type: 'PASTE', value });
689
+ keyboardActionTimeoutRef.current = window.setTimeout(() => {
690
+ userActionRef.current = null;
691
+ }, 10);
688
692
  }
689
693
  })}
690
694
  onChange={composeEventHandlers(props.onChange, (event) => {
@@ -696,11 +700,16 @@ const OneTimePasswordFieldInput = React.forwardRef<
696
700
  if (action) {
697
701
  switch (action.type) {
698
702
  case 'cut':
699
- // TODO: do we want to assume the user wantt to clear the
703
+ // TODO: do we want to assume the user wants to clear the
700
704
  // entire value here and copy the code to the clipboard instead
701
705
  // of just the value of the given input?
702
706
  dispatch({ type: 'CLEAR_CHAR', index, reason: 'Cut' });
703
707
  return;
708
+ case 'autocomplete-paste':
709
+ // the PASTE handler will already set the value and focus the final
710
+ // input; we want to skip focusing the wrong element if the browser fires
711
+ // onChange for the first input. This sometimes happens during autocomplete.
712
+ return;
704
713
  case 'keydown': {
705
714
  if (action.key === 'Char') {
706
715
  // update resulting from a keydown event that set a value
@@ -718,6 +727,7 @@ const OneTimePasswordFieldInput = React.forwardRef<
718
727
  return;
719
728
  }
720
729
  default:
730
+ action satisfies never;
721
731
  return;
722
732
  }
723
733
  }
@@ -929,7 +939,8 @@ type KeyboardActionDetails =
929
939
  metaKey: boolean;
930
940
  ctrlKey: boolean;
931
941
  }
932
- | { type: 'cut' };
942
+ | { type: 'cut' }
943
+ | { type: 'autocomplete-paste' };
933
944
 
934
945
  type UpdateAction =
935
946
  | {