Skip to content

Commit

Permalink
updated otp input (#147)
Browse files Browse the repository at this point in the history
  • Loading branch information
ankitmlesmagico authored Jul 11, 2024
1 parent ff815df commit cdfcd7d
Show file tree
Hide file tree
Showing 7 changed files with 217 additions and 93 deletions.
2 changes: 1 addition & 1 deletion packages/chatui/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@samagra-x/stencil-chatui",
"version": "0.0.1",
"version": "0.0.7",
"description": "The React library for Chatbot UI",
"main": "lib/index.js",
"module": "es/index.js",
Expand Down
2 changes: 1 addition & 1 deletion packages/config-manager/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@samagra-x/stencil-config-manager",
"version": "0.0.1",
"version": "0.0.7",
"main": "dist/index.js",
"scripts": {
"clean": "rimraf dist es lib",
Expand Down
4 changes: 2 additions & 2 deletions packages/hooks/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@samagra-x/stencil-hooks",
"version": "0.0.1",
"version": "0.0.8",
"main": "dist/index.js",
"scripts": {
"clean": "rimraf dist es lib",
Expand All @@ -13,7 +13,7 @@
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"@samagra-x/stencil-provider": "0.0.1"
"@samagra-x/stencil-provider": "0.0.7"
},
"devDependencies": {
"build": "tsup",
Expand Down
16 changes: 10 additions & 6 deletions packages/molecules/package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
{
"name": "@samagra-x/stencil-molecules",
"version": "0.0.1",
"version": "0.0.11",
"description": "The React library for Chatbot UI",
"main": "./src/index.ts",
"main": "lib/index.js",
"module": "es/index.js",
"browser": "dist/index.js",
"style": "dist/index.css",
"typings": "lib/index.d.ts",
"scripts": {
"clean": "rimraf dist es lib",
"prebuild": "npm run clean",
Expand Down Expand Up @@ -38,10 +42,10 @@
"@mui/material": "^5.15.15",
"@mui/system": "^5.15.13",
"@next/bundle-analyzer": "^13.3.0",
"@samagra-x/stencil-chatui": "0.0.1",
"@samagra-x/stencil-config-manager": "0.0.1",
"@samagra-x/stencil-hooks": "0.0.1",
"@samagra-x/stencil-provider": "0.0.1",
"@samagra-x/stencil-chatui": "0.0.7",
"@samagra-x/stencil-config-manager": "0.0.7",
"@samagra-x/stencil-hooks": "0.0.8",
"@samagra-x/stencil-provider": "0.0.7",
"@samagra-x/xmessage": "^1.1.0",
"@storybook/react": "^8.1.4",
"@storybook/test": "^8.1.4",
Expand Down
141 changes: 60 additions & 81 deletions packages/molecules/src/otp-input/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as React from "react";
import { Box, styled } from "@mui/material";
import { Input as BaseInput } from "@mui/material";
import * as React from 'react';
import { Input as BaseInput } from '@mui/base/Input';
import { Box, styled } from '@mui/system';

export function OTPInput({
separator,
length,
Expand All @@ -12,9 +13,7 @@ export function OTPInput({
value: string;
onChange: React.Dispatch<React.SetStateAction<string>>;
}) {
const inputRefs = React.useRef<HTMLInputElement[]>(
new Array(length).fill(null)
);
const inputRefs = React.useRef<HTMLInputElement[]>(new Array(length).fill(null));

const focusInput = (targetIndex: number) => {
const targetInput = inputRefs.current[targetIndex];
Expand All @@ -26,49 +25,44 @@ export function OTPInput({
targetInput.select();
};

const handleKeyDown = (
event: React.KeyboardEvent<HTMLInputElement>,
currentIndex: number
) => {
const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>, currentIndex: number) => {
switch (event.key) {
case "ArrowUp":
case "ArrowDown":
case " ":
case 'ArrowUp':
case 'ArrowDown':
case ' ':
event.preventDefault();
break;
case "ArrowLeft":
case 'ArrowLeft':
event.preventDefault();
if (currentIndex > 0) {
focusInput(currentIndex - 1);
selectInput(currentIndex - 1);
}
break;
case "ArrowRight":
case 'ArrowRight':
event.preventDefault();
if (currentIndex < length - 1) {
focusInput(currentIndex + 1);
selectInput(currentIndex + 1);
}
break;
case "Delete":
case 'Delete':
event.preventDefault();
onChange((prevOtp) => {
const otp =
prevOtp.slice(0, currentIndex) + prevOtp.slice(currentIndex + 1);
const otp = prevOtp.slice(0, currentIndex) + prevOtp.slice(currentIndex + 1);
return otp;
});

break;
case "Backspace":
case 'Backspace':
event.preventDefault();
if (currentIndex > 0) {
focusInput(currentIndex - 1);
selectInput(currentIndex - 1);
}

onChange((prevOtp) => {
const otp =
prevOtp.slice(0, currentIndex) + prevOtp.slice(currentIndex + 1);
const otp = prevOtp.slice(0, currentIndex) + prevOtp.slice(currentIndex + 1);
return otp;
});
break;
Expand All @@ -78,30 +72,24 @@ export function OTPInput({
}
};

const handleChange = (
event: React.ChangeEvent<HTMLInputElement>,
currentIndex: number
) => {
const handleChange = (event: React.ChangeEvent<HTMLInputElement>, currentIndex: number) => {
const currentValue = event.target.value;
let indexToEnter = 0;

while (indexToEnter <= currentIndex) {
if (
inputRefs.current[indexToEnter].value &&
indexToEnter < currentIndex
) {
if (inputRefs.current[indexToEnter].value && indexToEnter < currentIndex) {
indexToEnter += 1;
} else {
break;
}
}
onChange((prev) => {
const otpArray = prev.split("");
const otpArray = prev.split('');
const lastValue = currentValue[currentValue.length - 1];
otpArray[indexToEnter] = lastValue;
return otpArray.join("");
return otpArray.join('');
});
if (currentValue !== "") {
if (currentValue !== '') {
if (currentIndex < length - 1) {
focusInput(currentIndex + 1);
}
Expand All @@ -110,48 +98,41 @@ export function OTPInput({

const handleClick = (
_event: React.MouseEvent<HTMLInputElement, MouseEvent>,
currentIndex: number
currentIndex: number,
) => {
selectInput(currentIndex);
};

const handlePaste = (
event: React.ClipboardEvent<HTMLInputElement>,
currentIndex: number
) => {
const handlePaste = (event: React.ClipboardEvent<HTMLInputElement>, currentIndex: number) => {
event.preventDefault();
const clipboardData = event.clipboardData;

// Check if there is text data in the clipboard
if (clipboardData.types.includes("text/plain")) {
let pastedText = clipboardData.getData("text/plain");
if (clipboardData.types.includes('text/plain')) {
let pastedText = clipboardData.getData('text/plain');
pastedText = pastedText.substring(0, length).trim();
let indexToEnter = 0;

while (indexToEnter <= currentIndex) {
if (
inputRefs.current[indexToEnter].value &&
indexToEnter < currentIndex
) {
if (inputRefs.current[indexToEnter].value && indexToEnter < currentIndex) {
indexToEnter += 1;
} else {
break;
}
}

const otpArray = value.split("");
const otpArray = value.split('');

for (let i = indexToEnter; i < length; i += 1) {
const lastValue = pastedText[i - indexToEnter] ?? " ";
const lastValue = pastedText[i - indexToEnter] ?? ' ';
otpArray[i] = lastValue;
}

onChange(otpArray.join(""));
onChange(otpArray.join(''));
}
};

return (
<Box sx={{ display: "flex", gap: 1, alignItems: "center",border:'none' }}>
<Box sx={{ display: 'flex', gap: 2, alignItems: 'center' }} data-testid="otp-input-field">
{new Array(length).fill(null).map((_, index) => (
<React.Fragment key={index}>
<BaseInput
Expand All @@ -162,15 +143,14 @@ export function OTPInput({
aria-label={`Digit ${index + 1} of OTP`}
slotProps={{
input: {
// @ts-ignore
ref: (ele) => {
inputRefs.current[index] = ele!;
},
onKeyDown: (event) => handleKeyDown(event, index),
onChange: (event) => handleChange(event, index),
onClick: (event) => handleClick(event, index),
onPaste: (event) => handlePaste(event, index),
value: value[index] ?? "",
value: value[index] ?? '',
},
}}
/>
Expand All @@ -182,58 +162,57 @@ export function OTPInput({
}

const blue = {
100: "#DAECFF",
200: "#80BFFF",
400: "#3399FF",
500: "#007FFF",
600: "#0072E5",
700: "#0059B2",
100: '#DAECFF',
200: '#80BFFF',
400: '#3399FF',
500: '#007FFF',
600: '#0072E5',
700: '#0059B2',
};

const grey = {
50: "#F3F6F9",
100: "#E5EAF2",
200: "#DAE2ED",
300: "#C7D0DD",
400: "#B0B8C4",
500: "#9DA8B7",
600: "#6B7A90",
700: "#434D5B",
800: "#303740",
900: "#1C2025",
50: '#F3F6F9',
100: '#E5EAF2',
200: '#DAE2ED',
300: '#C7D0DD',
400: '#B0B8C4',
500: '#9DA8B7',
600: '#6B7A90',
700: '#434D5B',
800: '#303740',
900: '#1C2025',
};

const InputElement = styled("input")(
const InputElement = styled('input')(
({ theme }) => `
width: 40px;
width: 56px;
height: 52px;
font-family: 'IBM Plex Sans', sans-serif;
font-size: 0.875rem;
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
padding: 8px 0px;
padding: 4px 0px;
border-radius: 8px;
text-align: center;
color: ${theme.palette.mode === "dark" ? grey[300] : grey[900]};
background: ${theme.palette.mode === "dark" ? grey[900] : "#fff"};
border: 1px solid ${theme.palette.mode === "dark" ? grey[700] : grey[200]};
color: ${theme.palette.mode === 'dark' ? grey[300] : grey[900]};
background: ${theme.palette.mode === 'dark' ? grey[900] : '#fff'};
border: 1px solid ${theme.palette.mode === 'dark' ? grey[700] : grey[200]};
box-shadow: 0px 2px 4px ${
theme.palette.mode === "dark" ? "rgba(0,0,0, 0.5)" : "rgba(0,0,0, 0.05)"
theme.palette.mode === 'dark' ? 'rgba(0,0,0, 0.5)' : 'rgba(0,0,0, 0.05)'
};
// &:hover {
// border-color: ${blue[400]};
// }
&:hover {
border-color: ${blue[400]};
}
&:focus {
border-color: ${blue[400]};
box-shadow: 0 0 0 3px ${
theme.palette.mode === "dark" ? blue[600] : blue[200]
};
box-shadow: 0 0 0 3px ${theme.palette.mode === 'dark' ? blue[600] : blue[200]};
}
// firefox
&:focus-visible {
outline: 0;
}
`
`,
);
4 changes: 2 additions & 2 deletions packages/provider/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@samagra-x/stencil-provider",
"version": "0.0.1",
"version": "0.0.7",
"main": "dist/index.js",
"scripts": {
"clean": "rimraf dist es lib",
Expand All @@ -14,7 +14,7 @@
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.5",
"@mui/material": "^5.15.15",
"@samagra-x/stencil-config-manager": "0.0.1",
"@samagra-x/stencil-config-manager": "0.0.7",
"esbuild-plugin-polyfill-node": "^0.3.0",
"lodash": "^4.17.21",
"react": "^18.2.0",
Expand Down
Loading

0 comments on commit cdfcd7d

Please sign in to comment.