From e197cbdfa175c721daf3eaa68d52ab8ee5b19b1d Mon Sep 17 00:00:00 2001 From: keyurparalkar Date: Sun, 1 Oct 2023 23:19:33 +0530 Subject: [PATCH 1/7] chore: updated readme with count param --- README.md | 109 +++++++++++++++++++++++++++--------------------------- 1 file changed, 55 insertions(+), 54 deletions(-) diff --git a/README.md b/README.md index 238e29b..1397cd4 100644 --- a/README.md +++ b/README.md @@ -4,14 +4,14 @@ A headless UI for building easy to use passcode component. -*What is an passcode component?* +_What is an passcode component?_ It is a group of input elements with each element only accepting one character. This component is generally used in authentication flows. -* [Installation](#installation) -* [Usage](#usage) -* [Features](#features) -* [API](#api) -* [License](#license) +- [Installation](#installation) +- [Usage](#usage) +- [Features](#features) +- [API](#api) +- [License](#license) ## Installation @@ -19,80 +19,81 @@ It is a group of input elements with each element only accepting one character. yarn add react-headless-passcode ``` - ## Usage ```tsx import { usePasscode } from "react-headless-passcode"; ``` -With the `usePasscode` hook you just need to pass the `arrayValue` default property and in return you get the `array` in which the actual passcode value is stored, various event hanlders that handles the focus management between multiple inputs and `refs` that references each input element. +With the `usePasscode` hook you just need to pass the `count` property and in return you get the `array` in which the actual passcode value is stored, various event hanlders that handles the focus management logic between multiple inputs and `refs` that references each input element. For example: ```tsx const PasscodeComponent = () => { - const { array, getEventHandlers, refs } = usePasscode({ - arrayValue: [0, 0, 0, 0, 0, 0], - }); - - return ( - <> - {array.map((value, index) => { - const { ...rest } = getEventHandlers(index); - return ( - el && (refs.current[index] = el)} - type="text" - inputMode="numeric" - autoComplete="one-time-code" - maxLength={1} - pattern="\d{1}" - value={String(value)} - key={`index-${index}`} - {...rest} - /> - ); - })} - - ); + const { array, getEventHandlers, refs } = usePasscode({ + count: 4, + }); + + return ( + <> + {array.map((value, index) => { + const { ...rest } = getEventHandlers(index); + return ( + el && (refs.current[index] = el)} + type="text" + inputMode="numeric" + autoComplete="one-time-code" + maxLength={1} + pattern="\d{1}" + value={String(value)} + key={`index-${index}`} + {...rest} + /> + ); + })} + + ); }; - ``` ->**NOTE:** +> **NOTE:** > It is important to initialize the `refs` object with the current input element because this is how the `usepasscode` is able to track the current index and manage the focused state across multiple inputs. Make sure to assign this element to the `refs` or else the focus won't change!! + ```tsx ref={(el) => el && (refs.current[index] = el)} ``` ## Features -- Allow entering alpha numeric characters -- Expose a flag: `isComplete` that tells whether all the input boxes are filled or not -- Expose a state variable: `currentFocusedIndex`. It tells us the currently focused index of the passcode component. -- Exposes event handlers that can be seamlessly used with the input element. -- Passcode value can be pasted partially, fully, from start, or from middle. + +- Allow entering alpha numeric characters +- Expose a flag: `isComplete` that tells whether all the input boxes are filled or not +- Expose a state variable: `currentFocusedIndex`. It tells us the currently focused index of the passcode component. +- Exposes event handlers that can be seamlessly used with the input element. +- Passcode value can be pasted partially, fully, from start, or from middle. ## API The `usePasscode` hook accepts following props -| Prop Name | Type | Description | -|---------------- |------------------------ |----------------------------------------------------------------------- | -| arrayValue | `(number \| string)[]` | Default array value that helps to determine the size of the component | -| isAlphaNumeric | `boolean` | If `true`, allows to enter alpha numeric value in the component | +| Prop Name | Type | Description | +|---------------- |------------------------ |----------------------------------------------------------------------- | +| count | `number` | Number of input boxes to create in the passcode component | +| isAlphaNumeric | `boolean` | If `true`, allows to enter alpha numeric value in the component | The hook returns an object that consists of: -| Property | Type | Description | -|------------------------ |------------------------ |------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| array | `(string \| number)[]` | The current array value of the entire component. | -| setArray | `function` | A function that sets the internal state variable:`array`'s value inside the hook. | -| currentFocusedIndex | `number` | Index of the currently focused input element. | -| setCurrentFocusedIndex | `function` | A function that sets the internal state variable: `currentFocusedIndex`'s value inside the hook. | -| getEventHandler | `function` | A function that accepts an index as a parameter. It returns the following event handlers for the input positioned at index `i`: `onChange` `onFocus` `onKeyUp` `onKeyDown` | -| refs | `React.MutableRefObject` | A ref array that contains reference of all the input boxes. | -| isComplete | `boolean` | A boolean flag that tells if all the input boxes are filled or not. | +| Property | Type | Description | +| ---------------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| array | `(string \| number)[]` | The current array value of the entire component. | +| setArray | `function` | A function that sets the internal state variable:`array`'s value inside the hook. | +| currentFocusedIndex | `number` | Index of the currently focused input element. | +| setCurrentFocusedIndex | `function` | A function that sets the internal state variable: `currentFocusedIndex`'s value inside the hook. | +| getEventHandler | `function` | A function that accepts an index as a parameter. It returns the following event handlers for the input positioned at index `i`: `onChange` `onFocus` `onKeyUp` `onKeyDown` | +| refs | `React.MutableRefObject` | A ref array that contains reference of all the input boxes. | +| isComplete | `boolean` | A boolean flag that tells if all the input boxes are filled or not. | ## License -React is [MIT licensed](./LICENSE). \ No newline at end of file + +React is [MIT licensed](./LICENSE). From c12524395c8e504c8bd7a99b42db119cd201882e Mon Sep 17 00:00:00 2001 From: keyurparalkar Date: Mon, 2 Oct 2023 09:28:22 +0530 Subject: [PATCH 2/7] fix: added paste event listener to the current focused input rather than document, to resolve pasting issues --- package/lib/hook/usePasscode.ts | 89 +++++++++++++++++---------------- 1 file changed, 46 insertions(+), 43 deletions(-) diff --git a/package/lib/hook/usePasscode.ts b/package/lib/hook/usePasscode.ts index ce1f775..0f7c130 100644 --- a/package/lib/hook/usePasscode.ts +++ b/package/lib/hook/usePasscode.ts @@ -106,52 +106,55 @@ const usePasscode = (props: PasscodeProps) => { }; useEffect(() => { - document.addEventListener("paste", async () => { - const copyPermission = await getClipboardReadPermission(); - if (copyPermission.state === "denied") { - throw new Error("Not allowed to read clipboard."); - } - - const clipboardContent = await getClipboardContent(); - try { - // We convert the clipboard conent into an array of string or number depending upon isAlphaNumeric; - let newArray: Array = - clipboardContent.split(""); - newArray = isAlphaNumeric - ? newArray - : newArray.map((num) => Number(num)); - /** - * We start pasting the clipboard content from the currentFocusedIndex with the help of below block. - * Pasting of this content is stopped when the last input is reached. - **/ - const filledArray = getFilledArray( - array, - newArray, - currentFocusedIndex - ); - setArray(filledArray); + if (inputRefs.current) { + const currentElement = inputRefs.current[currentFocusedIndex]; + currentElement.addEventListener("paste", async () => { + const copyPermission = await getClipboardReadPermission(); + if (copyPermission.state === "denied") { + throw new Error("Not allowed to read clipboard."); + } - // Below we update the current focused index and also focus to the last input - if ( - newArray.length < array.length && - currentFocusedIndex === 0 - ) { - setCurrentFocusedIndex(newArray.length - 1); - inputRefs.current[newArray.length - 1].focus(); - } else { - setCurrentFocusedIndex(array.length - 1); - inputRefs.current[array.length - 1].focus(); + const clipboardContent = await getClipboardContent(); + try { + // We convert the clipboard conent into an array of string or number depending upon isAlphaNumeric; + let newArray: Array = + clipboardContent.split(""); + newArray = isAlphaNumeric + ? newArray + : newArray.map((num) => Number(num)); + /** + * We start pasting the clipboard content from the currentFocusedIndex with the help of below block. + * Pasting of this content is stopped when the last input is reached. + **/ + const filledArray = getFilledArray( + array, + newArray, + currentFocusedIndex + ); + setArray(filledArray); + + // Below we update the current focused index and also focus to the last input + if ( + newArray.length < array.length && + currentFocusedIndex === 0 + ) { + setCurrentFocusedIndex(newArray.length - 1); + inputRefs.current[newArray.length - 1].focus(); + } else { + setCurrentFocusedIndex(array.length - 1); + inputRefs.current[array.length - 1].focus(); + } + } catch (err) { + console.error(err); } - } catch (err) { - console.error(err); - } - }); + }); - return () => { - document.removeEventListener("paste", () => - console.log("Removed paste listner") - ); - }; + return () => { + currentElement.removeEventListener("paste", () => + console.log("Removed paste listner") + ); + }; + } }, [currentFocusedIndex, array, isAlphaNumeric]); return { From cc95bc978cb47f9481a12fd05c6a3a7bd5c4020d Mon Sep 17 00:00:00 2001 From: keyurparalkar Date: Tue, 3 Oct 2023 09:34:57 +0530 Subject: [PATCH 3/7] fix: * removed e.target.focus from onFocus handler; * renamed internal state variable array to passcode; * updated README; --- README.md | 4 ++-- package/lib/hook/usePasscode.test.tsx | 10 ++++----- package/lib/hook/usePasscode.ts | 31 ++++++++++++++------------- 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 1397cd4..b8e1797 100644 --- a/README.md +++ b/README.md @@ -86,8 +86,8 @@ The hook returns an object that consists of: | Property | Type | Description | | ---------------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| array | `(string \| number)[]` | The current array value of the entire component. | -| setArray | `function` | A function that sets the internal state variable:`array`'s value inside the hook. | +| passcode | `(string \| number)[]` | The current array value of the entire component. | +| setPasscode | `function` | A function that sets the internal state variable:`passcode`'s value inside the hook. | | currentFocusedIndex | `number` | Index of the currently focused input element. | | setCurrentFocusedIndex | `function` | A function that sets the internal state variable: `currentFocusedIndex`'s value inside the hook. | | getEventHandler | `function` | A function that accepts an index as a parameter. It returns the following event handlers for the input positioned at index `i`: `onChange` `onFocus` `onKeyUp` `onKeyDown` | diff --git a/package/lib/hook/usePasscode.test.tsx b/package/lib/hook/usePasscode.test.tsx index 868f0bd..7bafe19 100644 --- a/package/lib/hook/usePasscode.test.tsx +++ b/package/lib/hook/usePasscode.test.tsx @@ -4,14 +4,14 @@ import userEvent from "@testing-library/user-event"; import usePasscode from "./usePasscode"; const TestComponent = (props: { isAlphaNumeric: boolean }) => { - const { array, getEventHandlers, refs } = usePasscode({ + const { passcode, getEventHandlers, refs } = usePasscode({ count: 4, isAlphaNumeric: props.isAlphaNumeric, }); return ( <> - {array.map((value: string | number, index: number) => ( + {passcode.map((value: string | number, index: number) => ( el && (refs.current[index] = el)} type="text" @@ -30,9 +30,9 @@ const TestComponent = (props: { isAlphaNumeric: boolean }) => { }; describe("test basic workflow", () => { - it("1. test whether passing no. of inputs creates an array of equal number ", () => { - const { result } = renderHook(() => usePasscode({ count: 4 })); - expect(result.current.array).toHaveLength(4); + it("1. test whether passing count prop creates an array(input elements) with size count", () => { + render(); + expect(screen.getAllByTestId(/index-[0-9]/)).toHaveLength(4); }); it("2. test if the focus changes to next element when typed", async () => { diff --git a/package/lib/hook/usePasscode.ts b/package/lib/hook/usePasscode.ts index 0f7c130..47c4e26 100644 --- a/package/lib/hook/usePasscode.ts +++ b/package/lib/hook/usePasscode.ts @@ -22,11 +22,13 @@ type PasscodeProps = { const usePasscode = (props: PasscodeProps) => { const { count, isAlphaNumeric = false } = props; const filledArray = useMemo(() => Array(count).fill("", 0, count), [count]); - const [array, setArray] = useState(filledArray); + const [passcode, setPasscode] = useState(filledArray); const [currentFocusedIndex, setCurrentFocusedIndex] = useState(0); const inputRefs = useRef | []>([]); - const isComplete = array?.every((value: string | number) => value !== ""); + const isComplete = passcode?.every( + (value: string | number) => value !== "" + ); /** * A function that returns the necessary event handlers based on index. @@ -34,7 +36,7 @@ const usePasscode = (props: PasscodeProps) => { const getEventHandlers = (index: number) => { const onChange = (e: BaseSyntheticEvent) => { // Change the arrayValue and update only when number key is pressed - setArray((preValue: (string | number)[]) => { + setPasscode((preValue: (string | number)[]) => { const newArray = [...preValue]; if (parseInt(e.target.value)) { @@ -49,7 +51,6 @@ const usePasscode = (props: PasscodeProps) => { const onFocus = (e: BaseSyntheticEvent) => { setCurrentFocusedIndex(index); - e.target.focus(); }; const onKeyUp = (e: KeyboardEvent) => { @@ -70,13 +71,13 @@ const usePasscode = (props: PasscodeProps) => { /** * Update focus only when number key is pressed * We do a -2 below because we don't want the last input to update the currentFocusedIndex - * If we allow it then we get array out of bound error. + * If we allow it then we get passcode out of bound error. * */ if ( (isAlphaNumeric ? ALPHANUMERIC_REGEX.test(e.key) : parseInt(e.key)) && - index <= array.length - 2 + index <= passcode.length - 2 ) { setCurrentFocusedIndex(index + 1); if ( @@ -116,7 +117,7 @@ const usePasscode = (props: PasscodeProps) => { const clipboardContent = await getClipboardContent(); try { - // We convert the clipboard conent into an array of string or number depending upon isAlphaNumeric; + // We convert the clipboard conent into an passcode of string or number depending upon isAlphaNumeric; let newArray: Array = clipboardContent.split(""); newArray = isAlphaNumeric @@ -127,22 +128,22 @@ const usePasscode = (props: PasscodeProps) => { * Pasting of this content is stopped when the last input is reached. **/ const filledArray = getFilledArray( - array, + passcode, newArray, currentFocusedIndex ); - setArray(filledArray); + setPasscode(filledArray); // Below we update the current focused index and also focus to the last input if ( - newArray.length < array.length && + newArray.length < passcode.length && currentFocusedIndex === 0 ) { setCurrentFocusedIndex(newArray.length - 1); inputRefs.current[newArray.length - 1].focus(); } else { - setCurrentFocusedIndex(array.length - 1); - inputRefs.current[array.length - 1].focus(); + setCurrentFocusedIndex(passcode.length - 1); + inputRefs.current[passcode.length - 1].focus(); } } catch (err) { console.error(err); @@ -155,11 +156,11 @@ const usePasscode = (props: PasscodeProps) => { ); }; } - }, [currentFocusedIndex, array, isAlphaNumeric]); + }, [currentFocusedIndex, passcode, isAlphaNumeric]); return { - array, - setArray, + passcode, + setPasscode, currentFocusedIndex, setCurrentFocusedIndex, getEventHandlers, From ed4d231b272467dda1cf665448ab08b3ec4a7752 Mon Sep 17 00:00:00 2001 From: keyurparalkar Date: Tue, 3 Oct 2023 11:24:54 +0530 Subject: [PATCH 4/7] fix: remove depricated usage of which keyboard property and replaced with key property --- package/lib/hook/usePasscode.ts | 2 +- package/lib/utils/index.ts | 70 +++++++++++++++------------------ 2 files changed, 33 insertions(+), 39 deletions(-) diff --git a/package/lib/hook/usePasscode.ts b/package/lib/hook/usePasscode.ts index 47c4e26..90d0be4 100644 --- a/package/lib/hook/usePasscode.ts +++ b/package/lib/hook/usePasscode.ts @@ -93,7 +93,7 @@ const usePasscode = (props: PasscodeProps) => { // Preventing typing of any other keys except for 1 to 9 And backspace const onKeyDown = (e: KeyboardEvent) => { - if (shouldPreventDefault(e.which, isAlphaNumeric, e.metaKey)) { + if (shouldPreventDefault(e.key, isAlphaNumeric, e.metaKey)) { e.preventDefault(); } }; diff --git a/package/lib/utils/index.ts b/package/lib/utils/index.ts index cf1cc93..17c5698 100644 --- a/package/lib/utils/index.ts +++ b/package/lib/utils/index.ts @@ -1,43 +1,37 @@ export const ALPHANUMERIC_REGEX = /^[a-z0-9]$/i; export const shouldPreventDefault = ( - keyCode: number, - isAlphaNumeric: boolean = false, - isMeta: boolean = false + key: string, + isAlphaNumeric: boolean = false, + isMeta: boolean = false ) => { - const isAlphabet = keyCode >= 64 && keyCode <= 90; + const parsed = Number(key); - // Below flag also checks if the typeed key is from numpad - const isNumeric = - (keyCode >= 48 && keyCode <= 57) || (keyCode >= 96 && keyCode <= 105); + // By default we only allow numbers to be pressed = DONE + if (parsed) return false; - //Crtl + v: - if (isMeta && keyCode === 86) { - return false; - } + // Crtl + V + if (isMeta && key === "v") return false; - // By default we only allow numbers to be pressed - if (isNumeric) return false; + // Allow Backspace + if (key === "Backspace") return false; - // We only allow alphabets to be pressed when the isAplhaNumeric flag is true - if (isAlphabet && isAlphaNumeric) return false; - - // Backspace - if (keyCode === 8) { - return false; - } + // We only allow alphabets to be pressed when the isAplhaNumeric flag is true = DONE + if (isAlphaNumeric && isNaN(parsed)) { + return false; + } - return true; + return true; }; export const getClipboardReadPermission = () => { - return navigator.permissions.query({ - name: "clipboard-read" as PermissionName, - }); + return navigator.permissions.query({ + name: "clipboard-read" as PermissionName, + }); }; export const getClipboardContent = () => { - return navigator.clipboard.readText(); + return navigator.clipboard.readText(); }; /** @@ -48,19 +42,19 @@ export const getClipboardContent = () => { * The array before the focused index will be filled with existing values. */ export const getFilledArray = ( - arr: (number | string)[], - pastingArr: (number | string)[], - currentFocusedIndex: number + arr: (number | string)[], + pastingArr: (number | string)[], + currentFocusedIndex: number ) => { - const lastIndex = arr.length - 1; - - if (currentFocusedIndex > 0) { - for (let i = currentFocusedIndex; i <= lastIndex; i++) { - arr[i] = pastingArr[i - currentFocusedIndex] ?? ""; + const lastIndex = arr.length - 1; + + if (currentFocusedIndex > 0) { + for (let i = currentFocusedIndex; i <= lastIndex; i++) { + arr[i] = pastingArr[i - currentFocusedIndex] ?? ""; + } + return arr; + } else { + // Starts pasting the values in the array from 0th index + return [...pastingArr, ...arr.slice(pastingArr.length - 1, lastIndex)]; } - return arr; - } else { - // Starts pasting the values in the array from 0th index - return [...pastingArr, ...arr.slice(pastingArr.length - 1, lastIndex)]; - } }; From 51e3cc9811ecba917410106758bef14892b5d060 Mon Sep 17 00:00:00 2001 From: keyurparalkar Date: Tue, 3 Oct 2023 11:36:32 +0530 Subject: [PATCH 5/7] test: added unit test for utils shouldPreventDefault --- package/lib/utils/utils.test.ts | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 package/lib/utils/utils.test.ts diff --git a/package/lib/utils/utils.test.ts b/package/lib/utils/utils.test.ts new file mode 100644 index 0000000..acc589f --- /dev/null +++ b/package/lib/utils/utils.test.ts @@ -0,0 +1,31 @@ +import { shouldPreventDefault } from "./index"; + +describe("test shouldPreventDefault", () => { + test("1. Should return false if key that is pressed is: Ctrl + V, Backspace, and digits 1-9 when isAlphaNumeric = false", () => { + let key = "1"; + expect(shouldPreventDefault(key)).toBeFalsy(); + + key = "v"; + expect(shouldPreventDefault(key, false, true)).toBeFalsy(); + + key = "Backspace"; + expect(shouldPreventDefault(key)).toBeFalsy(); + + key = "a"; + expect(shouldPreventDefault(key)).toBeTruthy(); + }); + + test("2. Should return false if key that is pressed is: Ctrl + V, Backspace, and digits 1-9 when isAlphaNumeric = true", () => { + let key = "1"; + expect(shouldPreventDefault(key, true)).toBeFalsy(); + + key = "v"; // Ctrl + v + expect(shouldPreventDefault(key, true, true)).toBeFalsy(); + + key = "Backspace"; + expect(shouldPreventDefault(key, true)).toBeFalsy(); + + key = "a"; + expect(shouldPreventDefault(key, true)).toBeFalsy(); + }); +}); From ee1bf89dcd2bd44b3f26c4982d31dc85ebae22f7 Mon Sep 17 00:00:00 2001 From: keyurparalkar Date: Wed, 4 Oct 2023 14:30:30 +0530 Subject: [PATCH 6/7] fix: moved the pasting logic from useEffect to onPaste event --- package/lib/hook/usePasscode.ts | 96 +++++++++++++++------------------ 1 file changed, 43 insertions(+), 53 deletions(-) diff --git a/package/lib/hook/usePasscode.ts b/package/lib/hook/usePasscode.ts index 90d0be4..869982c 100644 --- a/package/lib/hook/usePasscode.ts +++ b/package/lib/hook/usePasscode.ts @@ -1,7 +1,6 @@ import { BaseSyntheticEvent, KeyboardEvent, - useEffect, useRef, useState, useMemo, @@ -98,66 +97,57 @@ const usePasscode = (props: PasscodeProps) => { } }; + const onPaste = async (e: BaseSyntheticEvent) => { + const copyPermission = await getClipboardReadPermission(); + if (copyPermission.state === "denied") { + throw new Error("Not allowed to read clipboard."); + } + + const clipboardContent = await getClipboardContent(); + try { + // We convert the clipboard conent into an passcode of string or number depending upon isAlphaNumeric; + let newArray: Array = + clipboardContent.split(""); + newArray = isAlphaNumeric + ? newArray + : newArray.map((num) => Number(num)); + /** + * We start pasting the clipboard content from the currentFocusedIndex with the help of below block. + * Pasting of this content is stopped when the last input is reached. + **/ + const filledArray = getFilledArray( + passcode, + newArray, + currentFocusedIndex + ); + + setPasscode(filledArray); + + const newFocusedIndex = currentFocusedIndex + newArray.length; + if ( + newFocusedIndex >= 0 && + newFocusedIndex < passcode.length - 1 + ) { + setCurrentFocusedIndex(newFocusedIndex); + inputRefs.current[newFocusedIndex].focus(); + } else { + setCurrentFocusedIndex(passcode.length - 1); + inputRefs.current[passcode.length - 1].focus(); + } + } catch (err) { + console.error(err); + } + }; + return { onKeyUp, onKeyDown, onFocus, onChange, + onPaste, }; }; - useEffect(() => { - if (inputRefs.current) { - const currentElement = inputRefs.current[currentFocusedIndex]; - currentElement.addEventListener("paste", async () => { - const copyPermission = await getClipboardReadPermission(); - if (copyPermission.state === "denied") { - throw new Error("Not allowed to read clipboard."); - } - - const clipboardContent = await getClipboardContent(); - try { - // We convert the clipboard conent into an passcode of string or number depending upon isAlphaNumeric; - let newArray: Array = - clipboardContent.split(""); - newArray = isAlphaNumeric - ? newArray - : newArray.map((num) => Number(num)); - /** - * We start pasting the clipboard content from the currentFocusedIndex with the help of below block. - * Pasting of this content is stopped when the last input is reached. - **/ - const filledArray = getFilledArray( - passcode, - newArray, - currentFocusedIndex - ); - setPasscode(filledArray); - - // Below we update the current focused index and also focus to the last input - if ( - newArray.length < passcode.length && - currentFocusedIndex === 0 - ) { - setCurrentFocusedIndex(newArray.length - 1); - inputRefs.current[newArray.length - 1].focus(); - } else { - setCurrentFocusedIndex(passcode.length - 1); - inputRefs.current[passcode.length - 1].focus(); - } - } catch (err) { - console.error(err); - } - }); - - return () => { - currentElement.removeEventListener("paste", () => - console.log("Removed paste listner") - ); - }; - } - }, [currentFocusedIndex, passcode, isAlphaNumeric]); - return { passcode, setPasscode, From 19abf2942912fd69c8d12fb0786ce1df3b8b4ee4 Mon Sep 17 00:00:00 2001 From: keyurparalkar Date: Wed, 4 Oct 2023 14:32:25 +0530 Subject: [PATCH 7/7] doc: updated README for getEventhandlers --- README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index b8e1797..5379543 100644 --- a/README.md +++ b/README.md @@ -84,15 +84,15 @@ The `usePasscode` hook accepts following props The hook returns an object that consists of: -| Property | Type | Description | -| ---------------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| passcode | `(string \| number)[]` | The current array value of the entire component. | -| setPasscode | `function` | A function that sets the internal state variable:`passcode`'s value inside the hook. | -| currentFocusedIndex | `number` | Index of the currently focused input element. | -| setCurrentFocusedIndex | `function` | A function that sets the internal state variable: `currentFocusedIndex`'s value inside the hook. | -| getEventHandler | `function` | A function that accepts an index as a parameter. It returns the following event handlers for the input positioned at index `i`: `onChange` `onFocus` `onKeyUp` `onKeyDown` | -| refs | `React.MutableRefObject` | A ref array that contains reference of all the input boxes. | -| isComplete | `boolean` | A boolean flag that tells if all the input boxes are filled or not. | +| Property | Type | Description | +| ---------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| passcode | `(string \| number)[]` | The current array value of the entire component. | +| setPasscode | `function` | A function that sets the internal state variable:`passcode`'s value inside the hook. | +| currentFocusedIndex | `number` | Index of the currently focused input element. | +| setCurrentFocusedIndex | `function` | A function that sets the internal state variable: `currentFocusedIndex`'s value inside the hook. | +| getEventHandler | `function` | A function that accepts an index as a parameter. It returns the following event handlers for the input positioned at index `i`: `onChange` `onFocus` `onKeyUp` `onKeyDown` `onPaste` | +| refs | `React.MutableRefObject` | A ref array that contains reference of all the input boxes. | +| isComplete | `boolean` | A boolean flag that tells if all the input boxes are filled or not. | ## License