@magiclabs/ui-components 1.48.0 → 1.48.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var k=require("react/jsx-runtime"),P=require("./text-input.js"),I=require("@styled/css"),_=require("@styled/css/cx"),f=require("react");const h=/\D/g,j=({pinLength:u,onComplete:w=o=>o,onChange:m=o=>o,originName:C,id:v="pin-code-input",autoFocus:x=!0,className:T})=>{const[o,y]=f.useState(()=>Array.from({length:u},()=>"")),c=f.useRef(Array(u).fill(null));f.useEffect(()=>{y(e=>u<e.length?e.slice(0,u):u>e.length?[...e,...Array(u-e.length).fill("")]:e)},[u]),f.useEffect(()=>{var e;x&&c.current[0]&&((e=c.current[0])===null||e===void 0||e.focus())},[x,u]);const d=(e,r)=>{var n;y(r),m(r);const t=r.join("");t.length===u&&((n=c.current[e])===null||n===void 0||n.blur(),w(t))},q=f.useCallback((e,r)=>{const n=[...o];r.replace(h,"").split("").forEach(t=>{var a,i;e>=u||(n[e]=t,e++,(i=(a=c?.current)===null||a===void 0?void 0:a[e])===null||i===void 0||i.focus())}),d(e,n)},[o,d]),A=f.useCallback(e=>{var r,n;const t=parseInt(e.currentTarget.dataset.id||"",10),a=e.target.value.replace(h,"");if(a.length>1)return q(t,a);const i=[...o];i[t]=a,a.length&&((n=(r=c?.current)===null||r===void 0?void 0:r[t+1])===null||n===void 0||n.focus()),d(t,i)},[d]),N=f.useCallback(e=>{var r,n,t,a,i;const b=e.currentTarget.value.length,s=parseInt(e.currentTarget.dataset.id||"",10),p=[...o];switch(e.key){case"Backspace":{if(b&&(p[s]="",d(s,p)),s){const l=p.reduceRight((g,R,E)=>g!==-1?g:R!==""?E:g,-1);(r=c?.current[l>=0?l:0])===null||r===void 0||r.focus()}return}case"ArrowLeft":{const l=s?s-1:u-1;(n=c?.current[l])===null||n===void 0||n.focus();return}case"ArrowRight":{const l=s===u-1?0:s+1;(t=c?.current[l])===null||t===void 0||t.focus();return}default:{const l=e.key.replace(h,"");b&&l.length&&l!==e.currentTarget.value&&(p[s]=l,d(s,p),(i=(a=c?.current)===null||a===void 0?void 0:a[s+1])===null||i===void 0||i.focus())}}},[m,d]),$=C?`${C} `:"";return k.jsx("form",{id:v,className:I.css({margin:0,minWidth:0,display:"flex",width:"100%",justifyContent:"space-between",maxWidth:"30rem",gap:2}),children:o.map((e,r)=>k.jsx(P.TextInput.Char,{id:v?`${v}-${r}`:void 0,"aria-label":`${$}one time password input ${r+1}`,"data-id":r,name:`${$}one time password input ${r+1}`,value:o[r]||"",className:_.cx(I.css({caretColor:"transparent"}),T),attr:{onChange:A,onKeyUp:N,autoComplete:r===0?"one-time-code":"off",inputMode:"numeric"},ref:n=>{c?.current&&(c.current[r]=n)}},`${v||void 0}-${r}`))})};exports.PinCodeInput=j,exports.default=j;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var b=require("react/jsx-runtime"),E=require("./text-input.js"),k=require("@styled/css"),N=require("@styled/css/cx"),f=require("react");const g=/\D/g,$=({pinLength:a,onComplete:j=o=>o,onChange:m=o=>o,id:v="pin-code-input",autoFocus:C=!0,className:w})=>{const[o,x]=f.useState(()=>Array.from({length:a},()=>"")),c=f.useRef(Array(a).fill(null));f.useEffect(()=>{x(e=>a<e.length?e.slice(0,a):a>e.length?[...e,...Array(a-e.length).fill("")]:e)},[a]),f.useEffect(()=>{var e;C&&c.current[0]&&((e=c.current[0])===null||e===void 0||e.focus())},[C,a]);const d=(e,r)=>{var n;x(r),m(r);const t=r.join("");t.length===a&&((n=c.current[e])===null||n===void 0||n.blur(),j(t))},I=f.useCallback((e,r)=>{const n=[...o];r.replace(g,"").split("").forEach(t=>{var u,s;e>=a||(n[e]=t,e++,(s=(u=c?.current)===null||u===void 0?void 0:u[e])===null||s===void 0||s.focus())}),d(e,n)},[o,d]),q=f.useCallback(e=>{var r,n;const t=parseInt(e.currentTarget.dataset.id||"",10),u=e.target.value.replace(g,"");if(u.length>1)return I(t,u);const s=[...o];s[t]=u,u.length&&((n=(r=c?.current)===null||r===void 0?void 0:r[t+1])===null||n===void 0||n.focus()),d(t,s)},[d]),A=f.useCallback(e=>{var r,n,t,u,s;const y=e.currentTarget.value.length,i=parseInt(e.currentTarget.dataset.id||"",10),p=[...o];switch(e.key){case"Backspace":{if(y&&(p[i]="",d(i,p)),i){const l=p.reduceRight((h,T,R)=>h!==-1?h:T!==""?R:h,-1);(r=c?.current[l>=0?l:0])===null||r===void 0||r.focus()}return}case"ArrowLeft":{const l=i?i-1:a-1;(n=c?.current[l])===null||n===void 0||n.focus();return}case"ArrowRight":{const l=i===a-1?0:i+1;(t=c?.current[l])===null||t===void 0||t.focus();return}default:{const l=e.key.replace(g,"");y&&l.length&&l!==e.currentTarget.value&&(p[i]=l,d(i,p),(s=(u=c?.current)===null||u===void 0?void 0:u[i+1])===null||s===void 0||s.focus())}}},[m,d]);return b.jsx("form",{id:v,className:k.css({margin:0,minWidth:0,display:"flex",width:"100%",justifyContent:"space-between",maxWidth:"30rem",gap:2}),children:o.map((e,r)=>b.jsx(E.TextInput.Char,{id:v?`${v}-${r}`:void 0,"aria-label":`one time password input ${r+1}`,"data-id":r,name:`one time password input ${r+1}`,value:o[r]||"",className:N.cx(k.css({caretColor:"transparent"}),w),attr:{onChange:q,onKeyUp:A,autoComplete:r===0?"one-time-code":"off",inputMode:"numeric"},ref:n=>{c?.current&&(c.current[r]=n)}},`${v||void 0}-${r}`))})};exports.PinCodeInput=$,exports.default=$;
2
2
  //# sourceMappingURL=pincode-input.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pincode-input.js","sources":["../../../../src/components/inputs/pincode-input.tsx"],"sourcesContent":["import { TextInput } from '@components/inputs/text-input';\nimport { css } from '@styled/css';\nimport { cx } from '@styled/css/cx';\n\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\n\nexport type PinCodeInputProps = {\n pinLength: 3 | 6;\n onComplete: (pins: string) => void;\n onChange: (pins: Array<string>) => void;\n id?: string;\n originName?: string;\n autoFocus?: boolean;\n className?: string;\n};\n\nconst REGEX_NUMBER_CLEANER = /\\D/g;\n\nexport const PinCodeInput = ({\n pinLength,\n onComplete = pins => pins,\n onChange = pins => pins,\n originName,\n id = 'pin-code-input',\n autoFocus = true,\n className,\n}: PinCodeInputProps) => {\n const [pinNumbers, setPinNumbers] = useState(() => Array.from({ length: pinLength }, () => ''));\n const inputRefs = useRef<(HTMLInputElement | null)[]>(Array(pinLength).fill(null));\n\n useEffect(() => {\n setPinNumbers(prevPinNumbers => {\n if (pinLength < prevPinNumbers.length) {\n return prevPinNumbers.slice(0, pinLength);\n } else if (pinLength > prevPinNumbers.length) {\n return [...prevPinNumbers, ...Array(pinLength - prevPinNumbers.length).fill('')];\n }\n return prevPinNumbers;\n });\n }, [pinLength]);\n\n useEffect(() => {\n if (autoFocus && inputRefs.current[0]) {\n inputRefs.current[0]?.focus();\n }\n }, [autoFocus, pinLength]);\n\n const updatePincode = (currentIndex: number, pins: string[]) => {\n setPinNumbers(pins);\n onChange(pins);\n\n const strPin = pins.join('');\n\n if (strPin.length === pinLength) {\n inputRefs.current[currentIndex]?.blur();\n onComplete(strPin);\n }\n };\n\n const bulkUpdatePincode = useCallback(\n (currentIndex: number, text: string) => {\n const newPins = [...pinNumbers];\n text\n .replace(REGEX_NUMBER_CLEANER, '')\n .split('')\n .forEach(code => {\n if (currentIndex >= pinLength) {\n return;\n }\n newPins[currentIndex] = code;\n currentIndex++;\n inputRefs?.current?.[currentIndex]?.focus();\n });\n\n updatePincode(currentIndex, newPins);\n },\n [pinNumbers, updatePincode],\n );\n\n const onChangeProp = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const currentIndex = parseInt(e.currentTarget.dataset.id || '', 10);\n const value = e.target.value.replace(REGEX_NUMBER_CLEANER, '');\n\n // handle cases when user pastes multiple characters\n if (value.length > 1) {\n return bulkUpdatePincode(currentIndex, value);\n }\n const newPins = [...pinNumbers];\n\n newPins[currentIndex] = value;\n\n if (value.length) {\n inputRefs?.current?.[currentIndex + 1]?.focus();\n }\n\n updatePincode(currentIndex, newPins);\n },\n [updatePincode],\n );\n\n const onKeyUp = useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n const inputHasValue = e.currentTarget.value.length;\n const currentIndex = parseInt(e.currentTarget.dataset.id || '', 10);\n const newPins = [...pinNumbers];\n\n switch (e.key) {\n case 'Backspace': {\n // Always delete value of selected input\n if (inputHasValue) {\n newPins[currentIndex] = '';\n updatePincode(currentIndex, newPins);\n }\n\n // Select the last input with a value\n if (currentIndex) {\n const lastIndexWithDigit = newPins.reduceRight((acc, current, index) => {\n if (acc !== -1) return acc;\n if (current !== '') return index;\n return acc;\n }, -1);\n\n inputRefs?.current[lastIndexWithDigit >= 0 ? lastIndexWithDigit : 0]?.focus();\n }\n return;\n }\n\n case 'ArrowLeft': {\n // Navigate left in a loop\n const newIndex = currentIndex ? currentIndex - 1 : pinLength - 1;\n inputRefs?.current[newIndex]?.focus();\n return;\n }\n\n case 'ArrowRight': {\n // Navigate right in a loop\n const newIndex = currentIndex === pinLength - 1 ? 0 : currentIndex + 1;\n inputRefs?.current[newIndex]?.focus();\n return;\n }\n\n default: {\n // Overwrite existing value if a new number value is pressed\n const value = e.key.replace(REGEX_NUMBER_CLEANER, '');\n\n if (inputHasValue && value.length && value !== e.currentTarget.value) {\n newPins[currentIndex] = value;\n updatePincode(currentIndex, newPins);\n inputRefs?.current?.[currentIndex + 1]?.focus();\n }\n }\n }\n },\n [onChange, updatePincode],\n );\n\n const formattedOriginName = originName ? `${originName} ` : '';\n\n return (\n <form\n id={id}\n className={css({\n margin: 0,\n minWidth: 0,\n display: 'flex',\n width: '100%',\n justifyContent: 'space-between',\n maxWidth: '30rem',\n gap: 2,\n })}\n >\n {pinNumbers.map((_, i) => (\n <TextInput.Char\n id={id ? `${id}-${i}` : undefined}\n aria-label={`${formattedOriginName}one time password input ${i + 1}`}\n data-id={i}\n key={`${id || undefined}-${i}`}\n name={`${formattedOriginName}one time password input ${i + 1}`}\n value={pinNumbers[i] || ''}\n className={cx(css({ caretColor: 'transparent' }), className)}\n attr={{\n onChange: onChangeProp,\n onKeyUp,\n autoComplete: i === 0 ? 'one-time-code' : 'off',\n inputMode: 'numeric',\n }}\n ref={el => {\n if (inputRefs?.current) {\n inputRefs.current[i] = el;\n }\n }}\n />\n ))}\n </form>\n );\n};\n\nexport default PinCodeInput;\n"],"names":["REGEX_NUMBER_CLEANER","PinCodeInput","pinLength","onComplete","pins","onChange","originName","id","autoFocus","className","pinNumbers","setPinNumbers","useState","inputRefs","useRef","useEffect","prevPinNumbers","_a","updatePincode","currentIndex","strPin","bulkUpdatePincode","useCallback","text","newPins","code","_b","onChangeProp","e","value","onKeyUp","inputHasValue","lastIndexWithDigit","acc","current","index","newIndex","_c","_e","_d","formattedOriginName","_jsx","css","_","i","TextInput","cx","el"],"mappings":"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"}
1
+ {"version":3,"file":"pincode-input.js","sources":["../../../../src/components/inputs/pincode-input.tsx"],"sourcesContent":["import { TextInput } from '@components/inputs/text-input';\nimport { css } from '@styled/css';\nimport { cx } from '@styled/css/cx';\n\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\n\nexport type PinCodeInputProps = {\n pinLength: 3 | 6;\n onComplete: (pins: string) => void;\n onChange: (pins: Array<string>) => void;\n id?: string;\n originName?: string;\n autoFocus?: boolean;\n className?: string;\n};\n\nconst REGEX_NUMBER_CLEANER = /\\D/g;\n\nexport const PinCodeInput = ({\n pinLength,\n onComplete = pins => pins,\n onChange = pins => pins,\n id = 'pin-code-input',\n autoFocus = true,\n className,\n}: PinCodeInputProps) => {\n const [pinNumbers, setPinNumbers] = useState(() => Array.from({ length: pinLength }, () => ''));\n const inputRefs = useRef<(HTMLInputElement | null)[]>(Array(pinLength).fill(null));\n\n useEffect(() => {\n setPinNumbers(prevPinNumbers => {\n if (pinLength < prevPinNumbers.length) {\n return prevPinNumbers.slice(0, pinLength);\n } else if (pinLength > prevPinNumbers.length) {\n return [...prevPinNumbers, ...Array(pinLength - prevPinNumbers.length).fill('')];\n }\n return prevPinNumbers;\n });\n }, [pinLength]);\n\n useEffect(() => {\n if (autoFocus && inputRefs.current[0]) {\n inputRefs.current[0]?.focus();\n }\n }, [autoFocus, pinLength]);\n\n const updatePincode = (currentIndex: number, pins: string[]) => {\n setPinNumbers(pins);\n onChange(pins);\n\n const strPin = pins.join('');\n\n if (strPin.length === pinLength) {\n inputRefs.current[currentIndex]?.blur();\n onComplete(strPin);\n }\n };\n\n const bulkUpdatePincode = useCallback(\n (currentIndex: number, text: string) => {\n const newPins = [...pinNumbers];\n text\n .replace(REGEX_NUMBER_CLEANER, '')\n .split('')\n .forEach(code => {\n if (currentIndex >= pinLength) {\n return;\n }\n newPins[currentIndex] = code;\n currentIndex++;\n inputRefs?.current?.[currentIndex]?.focus();\n });\n\n updatePincode(currentIndex, newPins);\n },\n [pinNumbers, updatePincode],\n );\n\n const onChangeProp = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const currentIndex = parseInt(e.currentTarget.dataset.id || '', 10);\n const value = e.target.value.replace(REGEX_NUMBER_CLEANER, '');\n\n // handle cases when user pastes multiple characters\n if (value.length > 1) {\n return bulkUpdatePincode(currentIndex, value);\n }\n const newPins = [...pinNumbers];\n\n newPins[currentIndex] = value;\n\n if (value.length) {\n inputRefs?.current?.[currentIndex + 1]?.focus();\n }\n\n updatePincode(currentIndex, newPins);\n },\n [updatePincode],\n );\n\n const onKeyUp = useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n const inputHasValue = e.currentTarget.value.length;\n const currentIndex = parseInt(e.currentTarget.dataset.id || '', 10);\n const newPins = [...pinNumbers];\n\n switch (e.key) {\n case 'Backspace': {\n // Always delete value of selected input\n if (inputHasValue) {\n newPins[currentIndex] = '';\n updatePincode(currentIndex, newPins);\n }\n\n // Select the last input with a value\n if (currentIndex) {\n const lastIndexWithDigit = newPins.reduceRight((acc, current, index) => {\n if (acc !== -1) return acc;\n if (current !== '') return index;\n return acc;\n }, -1);\n\n inputRefs?.current[lastIndexWithDigit >= 0 ? lastIndexWithDigit : 0]?.focus();\n }\n return;\n }\n\n case 'ArrowLeft': {\n // Navigate left in a loop\n const newIndex = currentIndex ? currentIndex - 1 : pinLength - 1;\n inputRefs?.current[newIndex]?.focus();\n return;\n }\n\n case 'ArrowRight': {\n // Navigate right in a loop\n const newIndex = currentIndex === pinLength - 1 ? 0 : currentIndex + 1;\n inputRefs?.current[newIndex]?.focus();\n return;\n }\n\n default: {\n // Overwrite existing value if a new number value is pressed\n const value = e.key.replace(REGEX_NUMBER_CLEANER, '');\n\n if (inputHasValue && value.length && value !== e.currentTarget.value) {\n newPins[currentIndex] = value;\n updatePincode(currentIndex, newPins);\n inputRefs?.current?.[currentIndex + 1]?.focus();\n }\n }\n }\n },\n [onChange, updatePincode],\n );\n\n return (\n <form\n id={id}\n className={css({\n margin: 0,\n minWidth: 0,\n display: 'flex',\n width: '100%',\n justifyContent: 'space-between',\n maxWidth: '30rem',\n gap: 2,\n })}\n >\n {pinNumbers.map((_, i) => (\n <TextInput.Char\n id={id ? `${id}-${i}` : undefined}\n aria-label={`one time password input ${i + 1}`}\n data-id={i}\n key={`${id || undefined}-${i}`}\n name={`one time password input ${i + 1}`}\n value={pinNumbers[i] || ''}\n className={cx(css({ caretColor: 'transparent' }), className)}\n attr={{\n onChange: onChangeProp,\n onKeyUp,\n autoComplete: i === 0 ? 'one-time-code' : 'off',\n inputMode: 'numeric',\n }}\n ref={el => {\n if (inputRefs?.current) {\n inputRefs.current[i] = el;\n }\n }}\n />\n ))}\n </form>\n );\n};\n\nexport default PinCodeInput;\n"],"names":["REGEX_NUMBER_CLEANER","PinCodeInput","pinLength","onComplete","pins","onChange","id","autoFocus","className","pinNumbers","setPinNumbers","useState","inputRefs","useRef","useEffect","prevPinNumbers","_a","updatePincode","currentIndex","strPin","bulkUpdatePincode","useCallback","text","newPins","code","_b","onChangeProp","e","value","onKeyUp","inputHasValue","lastIndexWithDigit","acc","current","index","newIndex","_c","_e","_d","_jsx","css","_","i","TextInput","cx","el"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{jsx as T}from"react/jsx-runtime";import{TextInput as B}from"./text-input.js";import{css as k}from"@styled/css";import{cx as D}from"@styled/css/cx";import{useState as F,useRef as K,useEffect as A,useCallback as g}from"react";const v=/\D/g,I=({pinLength:o,onComplete:b=u=>u,onChange:h=u=>u,originName:$,id:p="pin-code-input",autoFocus:y=!0,className:N})=>{const[u,C]=F(()=>Array.from({length:o},()=>"")),c=K(Array(o).fill(null));A(()=>{C(e=>o<e.length?e.slice(0,o):o>e.length?[...e,...Array(o-e.length).fill("")]:e)},[o]),A(()=>{var e;y&&c.current[0]&&((e=c.current[0])===null||e===void 0||e.focus())},[y,o]);const d=(e,n)=>{var r;C(n),h(n);const t=n.join("");t.length===o&&((r=c.current[e])===null||r===void 0||r.blur(),b(t))},j=g((e,n)=>{const r=[...u];n.replace(v,"").split("").forEach(t=>{var a,i;e>=o||(r[e]=t,e++,(i=(a=c?.current)===null||a===void 0?void 0:a[e])===null||i===void 0||i.focus())}),d(e,r)},[u,d]),R=g(e=>{var n,r;const t=parseInt(e.currentTarget.dataset.id||"",10),a=e.target.value.replace(v,"");if(a.length>1)return j(t,a);const i=[...u];i[t]=a,a.length&&((r=(n=c?.current)===null||n===void 0?void 0:n[t+1])===null||r===void 0||r.focus()),d(t,i)},[d]),E=g(e=>{var n,r,t,a,i;const w=e.currentTarget.value.length,s=parseInt(e.currentTarget.dataset.id||"",10),f=[...u];switch(e.key){case"Backspace":{if(w&&(f[s]="",d(s,f)),s){const l=f.reduceRight((m,L,W)=>m!==-1?m:L!==""?W:m,-1);(n=c?.current[l>=0?l:0])===null||n===void 0||n.focus()}return}case"ArrowLeft":{const l=s?s-1:o-1;(r=c?.current[l])===null||r===void 0||r.focus();return}case"ArrowRight":{const l=s===o-1?0:s+1;(t=c?.current[l])===null||t===void 0||t.focus();return}default:{const l=e.key.replace(v,"");w&&l.length&&l!==e.currentTarget.value&&(f[s]=l,d(s,f),(i=(a=c?.current)===null||a===void 0?void 0:a[s+1])===null||i===void 0||i.focus())}}},[h,d]),x=$?`${$} `:"";return T("form",{id:p,className:k({margin:0,minWidth:0,display:"flex",width:"100%",justifyContent:"space-between",maxWidth:"30rem",gap:2}),children:u.map((e,n)=>T(B.Char,{id:p?`${p}-${n}`:void 0,"aria-label":`${x}one time password input ${n+1}`,"data-id":n,name:`${x}one time password input ${n+1}`,value:u[n]||"",className:D(k({caretColor:"transparent"}),N),attr:{onChange:R,onKeyUp:E,autoComplete:n===0?"one-time-code":"off",inputMode:"numeric"},ref:r=>{c?.current&&(c.current[n]=r)}},`${p||void 0}-${n}`))})};export{I as PinCodeInput,I as default};
1
+ import{jsx as $}from"react/jsx-runtime";import{TextInput as L}from"./text-input.js";import{css as w}from"@styled/css";import{cx as W}from"@styled/css/cx";import{useState as B,useRef as D,useEffect as b,useCallback as h}from"react";const v=/\D/g,k=({pinLength:o,onComplete:A=u=>u,onChange:g=u=>u,id:p="pin-code-input",autoFocus:C=!0,className:T})=>{const[u,y]=B(()=>Array.from({length:o},()=>"")),c=D(Array(o).fill(null));b(()=>{y(e=>o<e.length?e.slice(0,o):o>e.length?[...e,...Array(o-e.length).fill("")]:e)},[o]),b(()=>{var e;C&&c.current[0]&&((e=c.current[0])===null||e===void 0||e.focus())},[C,o]);const d=(e,n)=>{var r;y(n),g(n);const t=n.join("");t.length===o&&((r=c.current[e])===null||r===void 0||r.blur(),A(t))},I=h((e,n)=>{const r=[...u];n.replace(v,"").split("").forEach(t=>{var a,i;e>=o||(r[e]=t,e++,(i=(a=c?.current)===null||a===void 0?void 0:a[e])===null||i===void 0||i.focus())}),d(e,r)},[u,d]),j=h(e=>{var n,r;const t=parseInt(e.currentTarget.dataset.id||"",10),a=e.target.value.replace(v,"");if(a.length>1)return I(t,a);const i=[...u];i[t]=a,a.length&&((r=(n=c?.current)===null||n===void 0?void 0:n[t+1])===null||r===void 0||r.focus()),d(t,i)},[d]),N=h(e=>{var n,r,t,a,i;const x=e.currentTarget.value.length,s=parseInt(e.currentTarget.dataset.id||"",10),f=[...u];switch(e.key){case"Backspace":{if(x&&(f[s]="",d(s,f)),s){const l=f.reduceRight((m,R,E)=>m!==-1?m:R!==""?E:m,-1);(n=c?.current[l>=0?l:0])===null||n===void 0||n.focus()}return}case"ArrowLeft":{const l=s?s-1:o-1;(r=c?.current[l])===null||r===void 0||r.focus();return}case"ArrowRight":{const l=s===o-1?0:s+1;(t=c?.current[l])===null||t===void 0||t.focus();return}default:{const l=e.key.replace(v,"");x&&l.length&&l!==e.currentTarget.value&&(f[s]=l,d(s,f),(i=(a=c?.current)===null||a===void 0?void 0:a[s+1])===null||i===void 0||i.focus())}}},[g,d]);return $("form",{id:p,className:w({margin:0,minWidth:0,display:"flex",width:"100%",justifyContent:"space-between",maxWidth:"30rem",gap:2}),children:u.map((e,n)=>$(L.Char,{id:p?`${p}-${n}`:void 0,"aria-label":`one time password input ${n+1}`,"data-id":n,name:`one time password input ${n+1}`,value:u[n]||"",className:W(w({caretColor:"transparent"}),T),attr:{onChange:j,onKeyUp:N,autoComplete:n===0?"one-time-code":"off",inputMode:"numeric"},ref:r=>{c?.current&&(c.current[n]=r)}},`${p||void 0}-${n}`))})};export{k as PinCodeInput,k as default};
2
2
  //# sourceMappingURL=pincode-input.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pincode-input.js","sources":["../../../../src/components/inputs/pincode-input.tsx"],"sourcesContent":["import { TextInput } from '@components/inputs/text-input';\nimport { css } from '@styled/css';\nimport { cx } from '@styled/css/cx';\n\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\n\nexport type PinCodeInputProps = {\n pinLength: 3 | 6;\n onComplete: (pins: string) => void;\n onChange: (pins: Array<string>) => void;\n id?: string;\n originName?: string;\n autoFocus?: boolean;\n className?: string;\n};\n\nconst REGEX_NUMBER_CLEANER = /\\D/g;\n\nexport const PinCodeInput = ({\n pinLength,\n onComplete = pins => pins,\n onChange = pins => pins,\n originName,\n id = 'pin-code-input',\n autoFocus = true,\n className,\n}: PinCodeInputProps) => {\n const [pinNumbers, setPinNumbers] = useState(() => Array.from({ length: pinLength }, () => ''));\n const inputRefs = useRef<(HTMLInputElement | null)[]>(Array(pinLength).fill(null));\n\n useEffect(() => {\n setPinNumbers(prevPinNumbers => {\n if (pinLength < prevPinNumbers.length) {\n return prevPinNumbers.slice(0, pinLength);\n } else if (pinLength > prevPinNumbers.length) {\n return [...prevPinNumbers, ...Array(pinLength - prevPinNumbers.length).fill('')];\n }\n return prevPinNumbers;\n });\n }, [pinLength]);\n\n useEffect(() => {\n if (autoFocus && inputRefs.current[0]) {\n inputRefs.current[0]?.focus();\n }\n }, [autoFocus, pinLength]);\n\n const updatePincode = (currentIndex: number, pins: string[]) => {\n setPinNumbers(pins);\n onChange(pins);\n\n const strPin = pins.join('');\n\n if (strPin.length === pinLength) {\n inputRefs.current[currentIndex]?.blur();\n onComplete(strPin);\n }\n };\n\n const bulkUpdatePincode = useCallback(\n (currentIndex: number, text: string) => {\n const newPins = [...pinNumbers];\n text\n .replace(REGEX_NUMBER_CLEANER, '')\n .split('')\n .forEach(code => {\n if (currentIndex >= pinLength) {\n return;\n }\n newPins[currentIndex] = code;\n currentIndex++;\n inputRefs?.current?.[currentIndex]?.focus();\n });\n\n updatePincode(currentIndex, newPins);\n },\n [pinNumbers, updatePincode],\n );\n\n const onChangeProp = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const currentIndex = parseInt(e.currentTarget.dataset.id || '', 10);\n const value = e.target.value.replace(REGEX_NUMBER_CLEANER, '');\n\n // handle cases when user pastes multiple characters\n if (value.length > 1) {\n return bulkUpdatePincode(currentIndex, value);\n }\n const newPins = [...pinNumbers];\n\n newPins[currentIndex] = value;\n\n if (value.length) {\n inputRefs?.current?.[currentIndex + 1]?.focus();\n }\n\n updatePincode(currentIndex, newPins);\n },\n [updatePincode],\n );\n\n const onKeyUp = useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n const inputHasValue = e.currentTarget.value.length;\n const currentIndex = parseInt(e.currentTarget.dataset.id || '', 10);\n const newPins = [...pinNumbers];\n\n switch (e.key) {\n case 'Backspace': {\n // Always delete value of selected input\n if (inputHasValue) {\n newPins[currentIndex] = '';\n updatePincode(currentIndex, newPins);\n }\n\n // Select the last input with a value\n if (currentIndex) {\n const lastIndexWithDigit = newPins.reduceRight((acc, current, index) => {\n if (acc !== -1) return acc;\n if (current !== '') return index;\n return acc;\n }, -1);\n\n inputRefs?.current[lastIndexWithDigit >= 0 ? lastIndexWithDigit : 0]?.focus();\n }\n return;\n }\n\n case 'ArrowLeft': {\n // Navigate left in a loop\n const newIndex = currentIndex ? currentIndex - 1 : pinLength - 1;\n inputRefs?.current[newIndex]?.focus();\n return;\n }\n\n case 'ArrowRight': {\n // Navigate right in a loop\n const newIndex = currentIndex === pinLength - 1 ? 0 : currentIndex + 1;\n inputRefs?.current[newIndex]?.focus();\n return;\n }\n\n default: {\n // Overwrite existing value if a new number value is pressed\n const value = e.key.replace(REGEX_NUMBER_CLEANER, '');\n\n if (inputHasValue && value.length && value !== e.currentTarget.value) {\n newPins[currentIndex] = value;\n updatePincode(currentIndex, newPins);\n inputRefs?.current?.[currentIndex + 1]?.focus();\n }\n }\n }\n },\n [onChange, updatePincode],\n );\n\n const formattedOriginName = originName ? `${originName} ` : '';\n\n return (\n <form\n id={id}\n className={css({\n margin: 0,\n minWidth: 0,\n display: 'flex',\n width: '100%',\n justifyContent: 'space-between',\n maxWidth: '30rem',\n gap: 2,\n })}\n >\n {pinNumbers.map((_, i) => (\n <TextInput.Char\n id={id ? `${id}-${i}` : undefined}\n aria-label={`${formattedOriginName}one time password input ${i + 1}`}\n data-id={i}\n key={`${id || undefined}-${i}`}\n name={`${formattedOriginName}one time password input ${i + 1}`}\n value={pinNumbers[i] || ''}\n className={cx(css({ caretColor: 'transparent' }), className)}\n attr={{\n onChange: onChangeProp,\n onKeyUp,\n autoComplete: i === 0 ? 'one-time-code' : 'off',\n inputMode: 'numeric',\n }}\n ref={el => {\n if (inputRefs?.current) {\n inputRefs.current[i] = el;\n }\n }}\n />\n ))}\n </form>\n );\n};\n\nexport default PinCodeInput;\n"],"names":["REGEX_NUMBER_CLEANER","PinCodeInput","pinLength","onComplete","pins","onChange","originName","id","autoFocus","className","pinNumbers","setPinNumbers","useState","inputRefs","useRef","useEffect","prevPinNumbers","_a","updatePincode","currentIndex","strPin","bulkUpdatePincode","useCallback","text","newPins","code","_b","onChangeProp","e","value","onKeyUp","inputHasValue","lastIndexWithDigit","acc","current","index","newIndex","_c","_e","_d","formattedOriginName","_jsx","css","_","i","TextInput","cx","el"],"mappings":"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"}
1
+ {"version":3,"file":"pincode-input.js","sources":["../../../../src/components/inputs/pincode-input.tsx"],"sourcesContent":["import { TextInput } from '@components/inputs/text-input';\nimport { css } from '@styled/css';\nimport { cx } from '@styled/css/cx';\n\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\n\nexport type PinCodeInputProps = {\n pinLength: 3 | 6;\n onComplete: (pins: string) => void;\n onChange: (pins: Array<string>) => void;\n id?: string;\n originName?: string;\n autoFocus?: boolean;\n className?: string;\n};\n\nconst REGEX_NUMBER_CLEANER = /\\D/g;\n\nexport const PinCodeInput = ({\n pinLength,\n onComplete = pins => pins,\n onChange = pins => pins,\n id = 'pin-code-input',\n autoFocus = true,\n className,\n}: PinCodeInputProps) => {\n const [pinNumbers, setPinNumbers] = useState(() => Array.from({ length: pinLength }, () => ''));\n const inputRefs = useRef<(HTMLInputElement | null)[]>(Array(pinLength).fill(null));\n\n useEffect(() => {\n setPinNumbers(prevPinNumbers => {\n if (pinLength < prevPinNumbers.length) {\n return prevPinNumbers.slice(0, pinLength);\n } else if (pinLength > prevPinNumbers.length) {\n return [...prevPinNumbers, ...Array(pinLength - prevPinNumbers.length).fill('')];\n }\n return prevPinNumbers;\n });\n }, [pinLength]);\n\n useEffect(() => {\n if (autoFocus && inputRefs.current[0]) {\n inputRefs.current[0]?.focus();\n }\n }, [autoFocus, pinLength]);\n\n const updatePincode = (currentIndex: number, pins: string[]) => {\n setPinNumbers(pins);\n onChange(pins);\n\n const strPin = pins.join('');\n\n if (strPin.length === pinLength) {\n inputRefs.current[currentIndex]?.blur();\n onComplete(strPin);\n }\n };\n\n const bulkUpdatePincode = useCallback(\n (currentIndex: number, text: string) => {\n const newPins = [...pinNumbers];\n text\n .replace(REGEX_NUMBER_CLEANER, '')\n .split('')\n .forEach(code => {\n if (currentIndex >= pinLength) {\n return;\n }\n newPins[currentIndex] = code;\n currentIndex++;\n inputRefs?.current?.[currentIndex]?.focus();\n });\n\n updatePincode(currentIndex, newPins);\n },\n [pinNumbers, updatePincode],\n );\n\n const onChangeProp = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const currentIndex = parseInt(e.currentTarget.dataset.id || '', 10);\n const value = e.target.value.replace(REGEX_NUMBER_CLEANER, '');\n\n // handle cases when user pastes multiple characters\n if (value.length > 1) {\n return bulkUpdatePincode(currentIndex, value);\n }\n const newPins = [...pinNumbers];\n\n newPins[currentIndex] = value;\n\n if (value.length) {\n inputRefs?.current?.[currentIndex + 1]?.focus();\n }\n\n updatePincode(currentIndex, newPins);\n },\n [updatePincode],\n );\n\n const onKeyUp = useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n const inputHasValue = e.currentTarget.value.length;\n const currentIndex = parseInt(e.currentTarget.dataset.id || '', 10);\n const newPins = [...pinNumbers];\n\n switch (e.key) {\n case 'Backspace': {\n // Always delete value of selected input\n if (inputHasValue) {\n newPins[currentIndex] = '';\n updatePincode(currentIndex, newPins);\n }\n\n // Select the last input with a value\n if (currentIndex) {\n const lastIndexWithDigit = newPins.reduceRight((acc, current, index) => {\n if (acc !== -1) return acc;\n if (current !== '') return index;\n return acc;\n }, -1);\n\n inputRefs?.current[lastIndexWithDigit >= 0 ? lastIndexWithDigit : 0]?.focus();\n }\n return;\n }\n\n case 'ArrowLeft': {\n // Navigate left in a loop\n const newIndex = currentIndex ? currentIndex - 1 : pinLength - 1;\n inputRefs?.current[newIndex]?.focus();\n return;\n }\n\n case 'ArrowRight': {\n // Navigate right in a loop\n const newIndex = currentIndex === pinLength - 1 ? 0 : currentIndex + 1;\n inputRefs?.current[newIndex]?.focus();\n return;\n }\n\n default: {\n // Overwrite existing value if a new number value is pressed\n const value = e.key.replace(REGEX_NUMBER_CLEANER, '');\n\n if (inputHasValue && value.length && value !== e.currentTarget.value) {\n newPins[currentIndex] = value;\n updatePincode(currentIndex, newPins);\n inputRefs?.current?.[currentIndex + 1]?.focus();\n }\n }\n }\n },\n [onChange, updatePincode],\n );\n\n return (\n <form\n id={id}\n className={css({\n margin: 0,\n minWidth: 0,\n display: 'flex',\n width: '100%',\n justifyContent: 'space-between',\n maxWidth: '30rem',\n gap: 2,\n })}\n >\n {pinNumbers.map((_, i) => (\n <TextInput.Char\n id={id ? `${id}-${i}` : undefined}\n aria-label={`one time password input ${i + 1}`}\n data-id={i}\n key={`${id || undefined}-${i}`}\n name={`one time password input ${i + 1}`}\n value={pinNumbers[i] || ''}\n className={cx(css({ caretColor: 'transparent' }), className)}\n attr={{\n onChange: onChangeProp,\n onKeyUp,\n autoComplete: i === 0 ? 'one-time-code' : 'off',\n inputMode: 'numeric',\n }}\n ref={el => {\n if (inputRefs?.current) {\n inputRefs.current[i] = el;\n }\n }}\n />\n ))}\n </form>\n );\n};\n\nexport default PinCodeInput;\n"],"names":["REGEX_NUMBER_CLEANER","PinCodeInput","pinLength","onComplete","pins","onChange","id","autoFocus","className","pinNumbers","setPinNumbers","useState","inputRefs","useRef","useEffect","prevPinNumbers","_a","updatePincode","currentIndex","strPin","bulkUpdatePincode","useCallback","text","newPins","code","_b","onChangeProp","e","value","onKeyUp","inputHasValue","lastIndexWithDigit","acc","current","index","newIndex","_c","_e","_d","_jsx","css","_","i","TextInput","cx","el"],"mappings":"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"}
@@ -7,6 +7,6 @@ export type PinCodeInputProps = {
7
7
  autoFocus?: boolean;
8
8
  className?: string;
9
9
  };
10
- export declare const PinCodeInput: ({ pinLength, onComplete, onChange, originName, id, autoFocus, className, }: PinCodeInputProps) => import("react/jsx-runtime").JSX.Element;
10
+ export declare const PinCodeInput: ({ pinLength, onComplete, onChange, id, autoFocus, className, }: PinCodeInputProps) => import("react/jsx-runtime").JSX.Element;
11
11
  export default PinCodeInput;
12
12
  //# sourceMappingURL=pincode-input.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pincode-input.d.ts","sourceRoot":"","sources":["../../../../src/components/inputs/pincode-input.tsx"],"names":[],"mappings":"AAMA,MAAM,MAAM,iBAAiB,GAAG;IAC9B,SAAS,EAAE,CAAC,GAAG,CAAC,CAAC;IACjB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;IACxC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAIF,eAAO,MAAM,YAAY,+EAQtB,iBAAiB,4CA0KnB,CAAC;AAEF,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"pincode-input.d.ts","sourceRoot":"","sources":["../../../../src/components/inputs/pincode-input.tsx"],"names":[],"mappings":"AAMA,MAAM,MAAM,iBAAiB,GAAG;IAC9B,SAAS,EAAE,CAAC,GAAG,CAAC,CAAC;IACjB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;IACxC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAIF,eAAO,MAAM,YAAY,mEAOtB,iBAAiB,4CAwKnB,CAAC;AAEF,eAAe,YAAY,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@magiclabs/ui-components",
3
- "version": "1.48.0",
3
+ "version": "1.48.1",
4
4
  "description": "💅 A theme-able library of reusable UI components",
5
5
  "author": "Magic Labs <open-source@magic.link>",
6
6
  "repository": {