react-pin-field
Version:
React component for entering PIN codes
1 lines • 19.6 kB
Source Map (JSON)
{"version":3,"file":"react-pin-field.umd.cjs","sources":["../src/utils.ts","../src/props.ts","../src/state.ts","../src/reducer.ts","../src/hook.ts","../src/pin-field.tsx"],"sourcesContent":["export const BACKSPACE_KEY_CODE = 8;\nexport const DELETE_KEY_CODE = 46;\n\nexport function noop(): void {}\n\nexport function range(start: number, length: number): number[] {\n return Array.from({ length }, (_, i) => i + start);\n}\n\nexport function hasFocus(el: HTMLElement): boolean {\n try {\n const matches = el.webkitMatchesSelector || el.matches;\n return matches.call(el, \":focus\");\n } catch (err: any) {\n return false;\n }\n}\n","import { InputHTMLAttributes } from \"react\";\n\nimport { noop } from \"./utils\";\nimport { Handler } from \"./hook\";\n\nexport type InnerProps = {\n length: number;\n format: (char: string) => string;\n formatAriaLabel: (index: number, total: number) => string;\n onChange: (value: string) => void;\n onComplete: (value: string) => void;\n};\n\nexport const defaultProps: InnerProps = {\n length: 5,\n format: char => char,\n formatAriaLabel: (index: number, total: number) => `PIN field ${index} of ${total}`,\n onChange: noop,\n onComplete: noop,\n};\n\nexport type NativeProps = Omit<\n InputHTMLAttributes<HTMLInputElement>,\n \"onChange\" | \"onKeyDown\" | \"onCompositionStart\" | \"onCompositionEnd\"\n>;\n\nexport const defaultNativeProps: NativeProps = {\n type: \"text\",\n inputMode: \"text\",\n autoCapitalize: \"off\",\n autoCorrect: \"off\",\n autoComplete: \"off\",\n};\n\nexport type Props = NativeProps &\n Partial<InnerProps> & {\n handler?: Handler;\n };\n","import { defaultProps, InnerProps, NativeProps } from \"./props\";\n\nexport type StateProps = Pick<NativeProps, \"dir\"> & Pick<InnerProps, \"length\" | \"format\">;\n\nexport type State = StateProps & {\n cursor: number;\n values: string[];\n backspace: boolean;\n composition: boolean;\n ready: boolean;\n dirty: boolean;\n};\n\nexport const defaultState: State = {\n length: defaultProps.length,\n format: defaultProps.format,\n dir: \"ltr\",\n cursor: 0,\n values: Array(defaultProps.length),\n backspace: false,\n composition: false,\n ready: false,\n dirty: false,\n};\n","import { BACKSPACE_KEY_CODE, DELETE_KEY_CODE } from \"./utils\";\nimport { Action } from \"./actions\";\nimport { State } from \"./state\";\n\nexport function reducer(prevState: State, action: Action): State {\n switch (action.type) {\n case \"update-props\": {\n // merge previous state with action's props\n const state = { ...prevState, ...action.props };\n\n // adjust cursor in case the new length exceed the previous one\n state.cursor = Math.min(state.cursor, state.length - 1);\n\n // slice values according to the new length\n //\n // NOTE: use slice because splice does not keep empty items and\n // therefore messes up with values length\n state.values = state.values.slice(0, state.cursor + 1);\n\n // state is now ready\n state.ready = true;\n\n return state;\n }\n\n case \"start-composition\": {\n return { ...prevState, dirty: true, composition: true };\n }\n\n case \"end-composition\": {\n const state: State = { ...prevState };\n\n if (action.value) {\n state.values[action.index] = action.value;\n } else {\n delete state.values[action.index];\n }\n\n const dir = state.values[action.index] ? 1 : 0;\n state.cursor = Math.min(action.index + dir, state.length - 1);\n\n state.composition = false;\n state.dirty = true;\n\n return state;\n }\n\n case \"handle-change\": {\n if (prevState.composition) {\n break;\n }\n\n const state: State = { ...prevState };\n\n if (action.reset) {\n state.values.splice(action.index, state.length);\n }\n\n if (action.value) {\n const values = action.value.split(\"\").map(state.format);\n const length = Math.min(state.length - action.index, values.length);\n state.values.splice(action.index, length, ...values.slice(0, length));\n state.cursor = Math.min(action.index + length, state.length - 1);\n } else {\n delete state.values[action.index];\n const dir = state.backspace ? 0 : 1;\n state.cursor = Math.max(0, action.index - dir);\n }\n\n state.backspace = false;\n state.dirty = true;\n\n return state;\n }\n\n case \"handle-key-down\": {\n // determine if a deletion key is pressed\n const fromKey = action.key === \"Backspace\" || action.key === \"Delete\";\n const fromCode = action.code === \"Backspace\" || action.code === \"Delete\";\n const fromKeyCode =\n action.keyCode === BACKSPACE_KEY_CODE || action.keyCode === DELETE_KEY_CODE;\n const fromWhich = action.which === BACKSPACE_KEY_CODE || action.which === DELETE_KEY_CODE;\n const deletion = fromKey || fromCode || fromKeyCode || fromWhich;\n\n // return the same state reference if no deletion detected\n if (!deletion) {\n break;\n }\n\n // Deletion is a bit tricky and requires special attention.\n //\n // When the field under cusor has a value and a deletion key is\n // pressed, we want to let the browser to do the deletion for\n // us, like a regular deletion in a normal input via the\n // `onchange` event. For this to happen, we need to return the\n // same state reference in order not to trigger any change. The\n // state will be automatically updated by the handle-change\n // action, when the deleted value will trigger the `onchange`\n // event.\n if (prevState.values[action.index]) {\n break;\n }\n\n // But when the field under cursor is empty, deletion cannot\n // happen by itself. The trick is to manually move the cursor\n // backwards: the browser will then delete the value under this\n // new cursor and perform the changes via the triggered\n // `onchange` event.\n else {\n const state: State = { ...prevState };\n\n state.cursor = Math.max(0, action.index - 1);\n\n // let know the handle-change action that we already moved\n // backwards and that we don't need to touch the cursor\n // anymore\n state.backspace = true;\n\n state.dirty = true;\n\n return state;\n }\n }\n\n case \"noop\":\n default:\n break;\n }\n\n return prevState;\n}\n","import { ActionDispatch, RefObject, useCallback, useMemo, useReducer, useRef } from \"react\";\n\nimport { defaultState, State } from \"./state\";\nimport { Action } from \"./actions\";\nimport { reducer } from \"./reducer\";\n\nexport type Handler = {\n refs: RefObject<HTMLInputElement[]>;\n state: State;\n dispatch: ActionDispatch<[Action]>;\n value: string;\n setValue: (value: string) => void;\n};\n\nexport function usePinField(): Handler {\n const refs = useRef<HTMLInputElement[]>([]);\n const [state, dispatch] = useReducer(reducer, defaultState);\n\n const value = useMemo(() => {\n let value = \"\";\n for (let index = 0; index < state.length; index++) {\n value += index in state.values ? state.values[index] : \"\";\n }\n return value;\n }, [state]);\n\n const setValue = useCallback(\n (value: string) => {\n dispatch({ type: \"handle-change\", index: 0, value, reset: true });\n },\n [dispatch, state.cursor],\n );\n\n return useMemo(\n () => ({ refs, state, dispatch, value, setValue }),\n [refs, state, dispatch, value, setValue],\n );\n}\n","import {\n useEffect,\n KeyboardEventHandler,\n ChangeEventHandler,\n CompositionEventHandler,\n forwardRef,\n useImperativeHandle,\n} from \"react\";\n\nimport { hasFocus, range } from \"./utils\";\nimport { defaultNativeProps, defaultProps, Props } from \"./props\";\nimport { usePinField } from \"./hook\";\n\nexport const PinField = forwardRef<HTMLInputElement[], Props>(\n (\n {\n length = defaultProps.length,\n format = defaultProps.format,\n formatAriaLabel = defaultProps.formatAriaLabel,\n onChange: handleChange = defaultProps.onChange,\n onComplete: handleComplete = defaultProps.onComplete,\n handler: customHandler,\n autoFocus,\n ...nativeProps\n },\n fwdRef,\n ) => {\n const internalHandler = usePinField();\n const { refs, state, dispatch } = customHandler || internalHandler;\n\n useImperativeHandle(fwdRef, () => refs.current, [refs]);\n\n function setRefAt(index: number): (ref: HTMLInputElement) => void {\n return ref => {\n if (ref) {\n refs.current[index] = ref;\n }\n };\n }\n\n function handleKeyDownAt(index: number): KeyboardEventHandler<HTMLInputElement> {\n return event => {\n const { key, code, keyCode, which } = event;\n dispatch({ type: \"handle-key-down\", index, key, code, keyCode, which });\n };\n }\n\n function handleChangeAt(index: number): ChangeEventHandler<HTMLInputElement> {\n return event => {\n if (event.nativeEvent instanceof InputEvent) {\n const value = event.nativeEvent.data;\n dispatch({ type: \"handle-change\", index, value });\n } else {\n const { value } = event.target;\n dispatch({ type: \"handle-change\", index, value, reset: true });\n }\n };\n }\n\n function startCompositionAt(index: number): CompositionEventHandler<HTMLInputElement> {\n return () => {\n dispatch({ type: \"start-composition\", index });\n };\n }\n\n function endCompositionAt(index: number): CompositionEventHandler<HTMLInputElement> {\n return event => {\n dispatch({ type: \"end-composition\", index, value: event.data });\n };\n }\n\n // initial props to state update\n useEffect(() => {\n if (state.ready) return;\n const dir =\n nativeProps.dir?.toLowerCase() ||\n document.documentElement.getAttribute(\"dir\")?.toLowerCase();\n dispatch({ type: \"update-props\", props: { length, format, dir } });\n }, [state.ready, dispatch, length, format]);\n\n // props.length to state update\n useEffect(() => {\n if (!state.ready) return;\n if (length === state.length) return;\n dispatch({ type: \"update-props\", props: { length } });\n }, [state.ready, length, state.length, dispatch]);\n\n // props.format to state update\n useEffect(() => {\n if (!state.ready) return;\n if (format === state.format) return;\n dispatch({ type: \"update-props\", props: { format } });\n }, [state.ready, format, state.format, dispatch]);\n\n // nativeProps.dir to state update\n useEffect(() => {\n if (!state.ready) return;\n const dir =\n nativeProps.dir?.toLowerCase() ||\n document.documentElement.getAttribute(\"dir\")?.toLowerCase();\n if (dir === state.dir) return;\n dispatch({ type: \"update-props\", props: { dir } });\n }, [state.ready, nativeProps.dir, state.dir, dispatch]);\n\n // state to view update\n useEffect(() => {\n if (!refs.current) return;\n if (!state.ready) return;\n if (!state.dirty) return;\n\n let innerFocus = false;\n let completed = state.values.length == state.length;\n let value = \"\";\n\n for (let index = 0; index < state.length; index++) {\n const char = index in state.values ? state.values[index] : \"\";\n refs.current[index].value = char;\n innerFocus = innerFocus || hasFocus(refs.current[index]);\n completed = completed && index in state.values && refs.current[index].checkValidity();\n value += char;\n }\n\n if (innerFocus) {\n refs.current[state.cursor].focus();\n }\n\n if (handleChange) {\n handleChange(value);\n }\n\n if (handleComplete && completed) {\n handleComplete(value);\n }\n }, [refs, state, handleChange, handleComplete]);\n\n if (!state.ready) {\n return null;\n }\n\n const inputs = range(0, state.length).map(index => (\n <input\n {...defaultNativeProps}\n {...nativeProps}\n key={index}\n ref={setRefAt(index)}\n value={index in state.values ? state.values[index] : \"\"}\n autoFocus={index === 0 && autoFocus}\n onKeyDown={handleKeyDownAt(index)}\n onChange={handleChangeAt(index)}\n onCompositionStart={startCompositionAt(index)}\n onCompositionEnd={endCompositionAt(index)}\n aria-label={formatAriaLabel(index + 1, state.length)}\n aria-required={nativeProps.required ? \"true\" : undefined}\n aria-disabled={nativeProps.disabled ? \"true\" : undefined}\n aria-readonly={nativeProps.readOnly ? \"true\" : undefined}\n />\n ));\n\n if (state.dir === \"rtl\") {\n inputs.reverse();\n }\n\n return inputs;\n },\n);\n\nexport default PinField;\n"],"names":["noop","range","start","length","_","i","hasFocus","el","defaultProps","char","index","total","defaultNativeProps","defaultState","reducer","prevState","action","state","dir","values","fromKey","fromCode","fromKeyCode","fromWhich","usePinField","refs","useRef","dispatch","useReducer","value","useMemo","setValue","useCallback","PinField","forwardRef","format","formatAriaLabel","handleChange","handleComplete","customHandler","autoFocus","nativeProps","fwdRef","internalHandler","useImperativeHandle","setRefAt","ref","handleKeyDownAt","event","key","code","keyCode","which","handleChangeAt","startCompositionAt","endCompositionAt","useEffect","_a","_b","innerFocus","completed","inputs","createElement"],"mappings":"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"}