UNPKG

react-input-pin-code

Version:

Pin input built with React component and styled-components

144 lines (133 loc) 10.2 kB
import { jsx } from 'react/jsx-runtime'; import { useRef, useMemo, useEffect } from 'react'; import cx from 'clsx'; import { SIZE_LARGE, SIZE_MEDIUM, SIZE_SMALL, SIZE_EXTRA_SMALL, INPUT_KEY_BACKSPACE } from '../constants/index.js'; import { validateToPattern } from '../utils/string/index.js'; function styleInject(css, ref) { if ( ref === void 0 ) ref = {}; var insertAt = ref.insertAt; if (!css || typeof document === 'undefined') { return; } var head = document.head || document.getElementsByTagName('head')[0]; var style = document.createElement('style'); style.type = 'text/css'; if (insertAt === 'top') { if (head.firstChild) { head.insertBefore(style, head.firstChild); } else { head.appendChild(style); } } else { head.appendChild(style); } if (style.styleSheet) { style.styleSheet.cssText = css; } else { style.appendChild(document.createTextNode(css)); } } var css_248z = "input.styles-module_inputWrapper__USKTA {\n margin-right: 0.375rem;\n outline: transparent solid 2px;\n outline-offset: 2px;\n text-align: center;\n border-radius: 0.375rem;\n border-width: 1px;\n border-style: solid;\n border-color: var(--ripc-input-border-color);\n background-color: inherit;\n box-sizing: border-box;\n}\ninput.styles-module_inputWrapper__USKTA.styles-module_isExtraSmall__oAc-h {\n width: 1.5rem;\n height: 1.5rem;\n font-size: 0.75rem;\n}\ninput.styles-module_inputWrapper__USKTA.styles-module_isSmall__6FtvA {\n width: 2rem;\n height: 2rem;\n font-size: 0.875rem;\n}\ninput.styles-module_inputWrapper__USKTA.styles-module_isMedium__6rur1 {\n width: 2.5rem;\n height: 2.5rem;\n font-size: 1rem;\n}\ninput.styles-module_inputWrapper__USKTA.styles-module_isLarge__oSLPp {\n width: 3rem;\n height: 3rem;\n font-size: 1.125rem;\n}\ninput.styles-module_inputWrapper__USKTA:focus {\n border-color: var(--ripc-focus-input-border-color);\n box-shadow: var(--ripc-focus-input-border-color) 0px 0px 0px 1px;\n}\ninput.styles-module_inputWrapper__USKTA:last-child {\n margin-right: 0;\n}\ninput.styles-module_inputWrapper__USKTA.styles-module_hasCompleted__GpQi5.styles-module_showState__InvUY:valid {\n border-color: var(--ripc-valid-input-border-color);\n box-shadow: var(--ripc-valid-input-border-color) 0px 0px 0px 1px;\n background-color: var(--ripc-valid-input-background-color);\n}\ninput.styles-module_inputWrapper__USKTA.styles-module_showState__InvUY:invalid {\n border-color: var(--ripc-error-input-border-color);\n box-shadow: var(--ripc-error-input-border-color) 0px 0px 0px 1px;\n background-color: var(--ripc-error-input-background-color);\n}\ninput.styles-module_inputWrapper__USKTA:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0eWxlcy5tb2R1bGUuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLHNCQUFzQjtFQUN0Qiw4QkFBOEI7RUFDOUIsbUJBQW1CO0VBQ25CLGtCQUFrQjtFQUNsQix1QkFBdUI7RUFDdkIsaUJBQWlCO0VBQ2pCLG1CQUFtQjtFQUNuQiw0Q0FBNEM7RUFDNUMseUJBQXlCO0VBQ3pCLHNCQUFzQjtBQUN4QjtBQUNBO0VBQ0UsYUFBYTtFQUNiLGNBQWM7RUFDZCxrQkFBa0I7QUFDcEI7QUFDQTtFQUNFLFdBQVc7RUFDWCxZQUFZO0VBQ1osbUJBQW1CO0FBQ3JCO0FBQ0E7RUFDRSxhQUFhO0VBQ2IsY0FBYztFQUNkLGVBQWU7QUFDakI7QUFDQTtFQUNFLFdBQVc7RUFDWCxZQUFZO0VBQ1osbUJBQW1CO0FBQ3JCO0FBQ0E7RUFDRSxrREFBa0Q7RUFDbEQsZ0VBQWdFO0FBQ2xFO0FBQ0E7RUFDRSxlQUFlO0FBQ2pCO0FBQ0E7RUFDRSxrREFBa0Q7RUFDbEQsZ0VBQWdFO0VBQ2hFLDBEQUEwRDtBQUM1RDtBQUNBO0VBQ0Usa0RBQWtEO0VBQ2xELGdFQUFnRTtFQUNoRSwwREFBMEQ7QUFDNUQ7QUFDQTtFQUNFLFlBQVk7RUFDWixtQkFBbUI7QUFDckIiLCJmaWxlIjoic3R5bGVzLm1vZHVsZS5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiaW5wdXQuaW5wdXRXcmFwcGVyIHtcbiAgbWFyZ2luLXJpZ2h0OiAwLjM3NXJlbTtcbiAgb3V0bGluZTogdHJhbnNwYXJlbnQgc29saWQgMnB4O1xuICBvdXRsaW5lLW9mZnNldDogMnB4O1xuICB0ZXh0LWFsaWduOiBjZW50ZXI7XG4gIGJvcmRlci1yYWRpdXM6IDAuMzc1cmVtO1xuICBib3JkZXItd2lkdGg6IDFweDtcbiAgYm9yZGVyLXN0eWxlOiBzb2xpZDtcbiAgYm9yZGVyLWNvbG9yOiB2YXIoLS1yaXBjLWlucHV0LWJvcmRlci1jb2xvcik7XG4gIGJhY2tncm91bmQtY29sb3I6IGluaGVyaXQ7XG4gIGJveC1zaXppbmc6IGJvcmRlci1ib3g7XG59XG5pbnB1dC5pbnB1dFdyYXBwZXIuaXNFeHRyYVNtYWxsIHtcbiAgd2lkdGg6IDEuNXJlbTtcbiAgaGVpZ2h0OiAxLjVyZW07XG4gIGZvbnQtc2l6ZTogMC43NXJlbTtcbn1cbmlucHV0LmlucHV0V3JhcHBlci5pc1NtYWxsIHtcbiAgd2lkdGg6IDJyZW07XG4gIGhlaWdodDogMnJlbTtcbiAgZm9udC1zaXplOiAwLjg3NXJlbTtcbn1cbmlucHV0LmlucHV0V3JhcHBlci5pc01lZGl1bSB7XG4gIHdpZHRoOiAyLjVyZW07XG4gIGhlaWdodDogMi41cmVtO1xuICBmb250LXNpemU6IDFyZW07XG59XG5pbnB1dC5pbnB1dFdyYXBwZXIuaXNMYXJnZSB7XG4gIHdpZHRoOiAzcmVtO1xuICBoZWlnaHQ6IDNyZW07XG4gIGZvbnQtc2l6ZTogMS4xMjVyZW07XG59XG5pbnB1dC5pbnB1dFdyYXBwZXI6Zm9jdXMge1xuICBib3JkZXItY29sb3I6IHZhcigtLXJpcGMtZm9jdXMtaW5wdXQtYm9yZGVyLWNvbG9yKTtcbiAgYm94LXNoYWRvdzogdmFyKC0tcmlwYy1mb2N1cy1pbnB1dC1ib3JkZXItY29sb3IpIDBweCAwcHggMHB4IDFweDtcbn1cbmlucHV0LmlucHV0V3JhcHBlcjpsYXN0LWNoaWxkIHtcbiAgbWFyZ2luLXJpZ2h0OiAwO1xufVxuaW5wdXQuaW5wdXRXcmFwcGVyLmhhc0NvbXBsZXRlZC5zaG93U3RhdGU6dmFsaWQge1xuICBib3JkZXItY29sb3I6IHZhcigtLXJpcGMtdmFsaWQtaW5wdXQtYm9yZGVyLWNvbG9yKTtcbiAgYm94LXNoYWRvdzogdmFyKC0tcmlwYy12YWxpZC1pbnB1dC1ib3JkZXItY29sb3IpIDBweCAwcHggMHB4IDFweDtcbiAgYmFja2dyb3VuZC1jb2xvcjogdmFyKC0tcmlwYy12YWxpZC1pbnB1dC1iYWNrZ3JvdW5kLWNvbG9yKTtcbn1cbmlucHV0LmlucHV0V3JhcHBlci5zaG93U3RhdGU6aW52YWxpZCB7XG4gIGJvcmRlci1jb2xvcjogdmFyKC0tcmlwYy1lcnJvci1pbnB1dC1ib3JkZXItY29sb3IpO1xuICBib3gtc2hhZG93OiB2YXIoLS1yaXBjLWVycm9yLWlucHV0LWJvcmRlci1jb2xvcikgMHB4IDBweCAwcHggMXB4O1xuICBiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1yaXBjLWVycm9yLWlucHV0LWJhY2tncm91bmQtY29sb3IpO1xufVxuaW5wdXQuaW5wdXRXcmFwcGVyOmRpc2FibGVkIHtcbiAgb3BhY2l0eTogMC41O1xuICBjdXJzb3I6IG5vdC1hbGxvd2VkO1xufSJdfQ== */"; var styles = {"inputWrapper":"styles-module_inputWrapper__USKTA","isExtraSmall":"styles-module_isExtraSmall__oAc-h","isSmall":"styles-module_isSmall__6FtvA","isMedium":"styles-module_isMedium__6rur1","isLarge":"styles-module_isLarge__oSLPp","hasCompleted":"styles-module_hasCompleted__GpQi5","showState":"styles-module_showState__InvUY"}; styleInject(css_248z); const normalizeNewValue = (currentValue, eventValue) => { if (!currentValue) { return eventValue.split(''); } if (eventValue.length > 2) { return eventValue.split(''); } if (eventValue === '') { return []; } if (currentValue[0] === eventValue[0]) { return [eventValue[1]]; } return [eventValue[0]]; }; const sizeConfigMap = { [SIZE_EXTRA_SMALL]: { className: 'isExSmall', }, [SIZE_SMALL]: { className: 'isSmall', }, [SIZE_MEDIUM]: { className: 'isMedium', }, [SIZE_LARGE]: { className: 'isLarge', }, }; const PinInputField = ({ index, value, values, completed, type = 'number', mask, size = SIZE_MEDIUM, validate, format, showState = true, autoFocus = false, autoTab = true, 'aria-describedby': ariaDescribedby, 'aria-label': ariaLabel = 'Please enter pin code', 'aria-labelledby': ariaLabelledby, autoComplete = 'off', disabled, inputMode, id, name, placeholder = 'o', required, inputClassName, inputStyle = {}, onChange, onBlur, onFocus, onKeyDown, }) => { const inputRef = useRef(null); const handleInputChange = (e) => { const currentValue = values[index]; const eventValue = e.target.value; const newValues = [...values]; const rawValue = normalizeNewValue(currentValue, eventValue).slice(0, newValues.length - index); const regex = type === 'number' ? /(^$)|(\d+)/ : /.*/; const shouldFireChange = rawValue.every((val) => regex.test(val)); if (!onChange) { return; } // apply formatter to transform const newValue = format ? rawValue.map((val) => format(val)) : rawValue; if (newValue.length) { newValue.forEach((val, idx) => (newValues[index + idx] = val)); } else { newValues[index] = ''; } if (!shouldFireChange) { return; } onChange(newValue, index, newValues); // auto-tab to the specified pin input let inputEl = inputRef.current; for (let i = 0; i < newValue.length; i++) { if (inputEl) { inputEl = inputEl.nextElementSibling; } } if (newValue && autoTab && inputEl instanceof HTMLInputElement) { inputEl.focus(); } }; const handleKeyDown = (e) => { if (inputRef.current && e.key === INPUT_KEY_BACKSPACE && autoTab && values[index] === '' && index > 0) { const prevInput = inputRef.current.previousElementSibling; if (prevInput instanceof HTMLInputElement) { prevInput.focus(); } } if (onKeyDown) { onKeyDown(e); } }; const handleInputFocus = (e) => { e.target.placeholder = ''; if (onFocus) { onFocus(e); } }; const handleInputBlur = (e) => { e.target.placeholder = placeholder; if (onBlur) { onBlur(e); } }; const pattern = useMemo(() => validateToPattern(validate), [validate]); // auto-focus on mount useEffect(() => { if (inputRef.current && autoFocus && index === 0) { inputRef.current.focus(); } }, [autoFocus, index]); const { [size]: { className: sizeClassName, }, } = sizeConfigMap; return (jsx("input", { ref: inputRef, type: mask ? 'password' : 'text', "aria-describedby": ariaDescribedby, "aria-disabled": disabled, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, "aria-required": required, autoComplete: autoComplete, disabled: disabled, name: name, id: id && `${id}-${index}`, className: cx(styles.inputWrapper, styles[sizeClassName], completed && styles.hasCompleted, showState && styles.showState, inputClassName), inputMode: inputMode || (type === 'number' ? 'numeric' : 'text'), required: required, placeholder: placeholder, pattern: pattern, value: value, onChange: handleInputChange, onKeyDown: handleKeyDown, onFocus: handleInputFocus, onBlur: handleInputBlur, style: inputStyle, "data-index": index })); }; export { PinInputField as P, styleInject as s }; //# sourceMappingURL=component-B3MV4PJV.js.map