Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | 1x 1x 5x 5x 5x 5x 5x 5x 3x 5x 3x 5x 5x 5x 30x 5x 5x 1x 1x | import {forwardRef, useCallback, useEffect, useRef} from 'react' import PropTypes from 'prop-types' import useMergeRefs from '@s-ui/react-hooks/lib/useMergeRefs' import useKeyPress from './hooks/useKeyPress.js' import useUpdateEffect from './hooks/useUpdateEffect.js' import {actions as pinInputActions, usePinInputReducer} from './reducer/index.js' import {BASE_CLASSNAME, getValueType, MASK, SIZES, STATUS} from './config.js' import PinInputChildren from './PinInputChildren.js' import {PinInputContextProvider} from './PinInputContext.js' import PinInputField from './PinInputField.js' const CLASSNAME = BASE_CLASSNAME const PinInput = forwardRef( ( { autoFocus = false, children, defaultValue = '', disabled, inputMode, isOneTimeCode = true, isPassword = false, length = 6, mask, onChange, placeholder = '', size = SIZES.MEDIUM, status, value, ...props }, forwardedRef ) => { const innerRef = useRef() const targetRef = useRef() const [reducerStore, dispatch] = usePinInputReducer({ mask, defaultValue, value, disabled }) const {innerValue, focusPosition, elements} = reducerStore useUpdateEffect(() => { const innerValue = typeof value === 'string' ? value.split('') : value || [] dispatch(pinInputActions.setValue({innerValue})) }, [`${value}`, dispatch]) useEffect(() => { dispatch(pinInputActions.setDisabled({disabled})) }, [disabled, dispatch]) useEffect(() => { dispatch(pinInputActions.setMask({mask})) }, [mask, dispatch]) const setFocus = useCallback( position => { dispatch(pinInputActions.setFocus({focusPosition: position})) }, [dispatch] ) useKeyPress( event => { dispatch(pinInputActions.setKey({event, onChange})) }, {target: targetRef, onChange} ) const getIndex = useCallback( node => { return elements.indexOf(node) }, [elements] ) useUpdateEffect(() => { setFocus(focusPosition) }, [focusPosition]) return ( <div className={CLASSNAME} ref={targetRef}> <PinInputContextProvider disabled={reducerStore.disabled} dispatch={dispatch} getIndex={getIndex} inputMode={inputMode} isOneTimeCode={isOneTimeCode} isPassword={isPassword} mask={reducerStore.mask} placeholder={placeholder} setFocus={setFocus} size={size} status={status} targetRef={innerRef} value={innerValue} > <PinInputChildren length={length} autoFocus={autoFocus}> {children} </PinInputChildren> </PinInputContextProvider> <input type="hidden" value={innerValue.filter(Boolean).join('')} ref={useMergeRefs(innerRef, forwardedRef)} /> </div> ) } ) PinInput.displayName = 'PinInput' PinInput.propTypes = { /** boolean to autoFocus the first input */ autoFocus: PropTypes.bool, /** children the components is gonna have */ children: PropTypes.node, /** default value for the input */ defaultValue: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]), /** true for disabled false for default */ disabled: PropTypes.bool, /** inputmode **/ inputMode: PropTypes.string, /** true for autocomplete from keyboard false for default */ isOneTimeCode: PropTypes.bool, /** true to make the input type password false for text */ isPassword: PropTypes.bool, /** defines the number of cells */ length: PropTypes.number, /** name of the custom mask (NUMBER, ALPHABETIC, ALPHANUMERIC) */ mask: PropTypes.oneOfType([PropTypes.oneOf(Object.values(MASK)), PropTypes.string]), /** function executed on value change */ onChange: PropTypes.func, /** placeholder for the input */ placeholder: PropTypes.string, /** set the size of the input (XXSMALL, XSMALL, SMALL, MEDIUM, LARGE, XLARGE, XXLARGE) */ size: PropTypes.oneOf(Object.values(SIZES)), /** set the input status (ERROR, SUCCESS, WARNING) */ status: PropTypes.oneOf(Object.values(BASE_CLASSNAME)), /** input value */ value: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]) } export default PinInput export { PinInputField, MASK as pinInputMask, SIZES as pinInputSizes, STATUS as pinInputStatus, getValueType as getPinInputValueType } |