UNPKG

@m3-moretv/react-code-input

Version:

Typescript implementation of some code/pin-code input

127 lines (126 loc) 5.51 kB
"use strict"; var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result["default"] = mod; return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const react_1 = __importStar(require("react")); const classnames_1 = __importDefault(require("classnames")); const utils_1 = require("./utils"); const BACKSPACE_KEY = 8; const LEFT_ARROW_KEY = 37; const UP_ARROW_KEY = 38; const RIGHT_ARROW_KEY = 39; const DOWN_ARROW_KEY = 40; const E_KEY = 69; const DOT_KEY = 190; const COMMA_KEY = 188; var Types; (function (Types) { Types["text"] = "text"; Types["number"] = "number"; })(Types = exports.Types || (exports.Types = {})); const CodeInput = ({ fields, value, name, onChange, onBlur, onFocus = utils_1.defaultOnFocus, autoFocus, type = Types.text, disabled, isValid = true, className, inputClassName, invalidInputClassName }) => { const [inputsValues, setInputsValues] = react_1.useState(utils_1.fillEmptyArray(fields).map((element, i) => value.split('')[i] || element)); const [inputsKeys, setInputsKeys] = react_1.useState(utils_1.fillEmptyArray(fields).map((element, i) => utils_1.uuid())); const inputsRefs = inputsValues.map(() => react_1.useRef({})); const handleChange = (event) => { const target = event.target; const value = target.value; if (value === '') { return; } const currInputIndex = Number(target.dataset.id); const nextInputIndex = currInputIndex + 1; let nextTarget = inputsRefs[nextInputIndex]; const copiedInputsValues = inputsValues.slice(); /** throwing focus on next input when the new value is equal to previous cause onChange doesn't fire in this case */ if (value.length > 1) { value.split('').forEach((chart, i) => { if (currInputIndex + i < copiedInputsValues.length) { copiedInputsValues[currInputIndex + i] = chart; /**Set focus on last input with value after ctrl + v */ nextTarget = inputsRefs[currInputIndex + i]; } }); } else { copiedInputsValues[currInputIndex] = value; } if (nextTarget) { utils_1.moveToNewTarget(nextTarget); } setInputsValues(copiedInputsValues); if (onChange) { const fullValue = copiedInputsValues.join(''); onChange(fullValue); } }; const handleKeyDown = (event) => { const target = event.currentTarget; const currInputIndex = Number(target.dataset.id); const nextInput = inputsRefs[currInputIndex + 1]; const prevInput = inputsRefs[currInputIndex - 1]; const currInput = inputsRefs[currInputIndex]; switch (event.keyCode) { case BACKSPACE_KEY: const copiedInputsValues = inputsValues.slice(); copiedInputsValues[currInputIndex] = ''; //to completely update input; helpfull on adroid when comma not beeing registered const newKeys = inputsKeys.slice(); newKeys[currInputIndex] = utils_1.uuid(); setInputsValues(copiedInputsValues); setInputsKeys(newKeys); if (prevInput) { utils_1.moveToNewTarget(prevInput); } else { utils_1.updateFocus(currInput); } if (onChange) { const fullValue = copiedInputsValues.join(''); onChange(fullValue); } break; case LEFT_ARROW_KEY: event.preventDefault(); if (prevInput) { utils_1.moveToNewTarget(prevInput); } break; case RIGHT_ARROW_KEY: event.preventDefault(); if (nextInput) { utils_1.moveToNewTarget(nextInput); } break; case UP_ARROW_KEY: event.preventDefault(); break; case DOWN_ARROW_KEY: event.preventDefault(); break; case E_KEY: case DOT_KEY: case COMMA_KEY: if (type === Types.number) { event.preventDefault(); break; } default: break; } }; const inputClasses = classnames_1.default(inputClassName, invalidInputClassName && { [invalidInputClassName]: !isValid }); return (react_1.default.createElement("div", { className: className }, inputsValues.map((value, i) => { return (react_1.default.createElement("input", { ref: inputsRefs[i], id: utils_1.uuid(), name: name, "data-id": i, autoFocus: autoFocus && i === 0, value: value, key: inputsKeys[i], type: type, disabled: disabled, className: inputClasses, onBlur: onBlur, onChange: handleChange, onKeyDown: handleKeyDown, onFocus: onFocus, pattern: type === Types.number ? '[0-9]*' : undefined })); }))); }; exports.default = CodeInput;