fictoan-react 0.45.2 → 0.45.4

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # CHANGELOG
2
2
 
3
+ ### 0.45.4
4
+ - Fix PinInputField behaviour on paste or replace at position
5
+
6
+ ### 0.45.3
7
+ - Add optional `isDismissable` prop for showing a close button for `BottomDrawer` *(true by default)*
8
+
3
9
  ### 0.45.2
4
10
  - Fix prop name for disable copy/paste to pasteFromClipboard which takes either enabled or disabled as parameters for `PinInput Field`
5
11
 
@@ -7,6 +7,7 @@ export interface BottomDrawerCustomProps {
7
7
  overlayColour?: ColourPropTypes;
8
8
  overlayColor?: ColourPropTypes;
9
9
  closeOnClickOutside?: boolean;
10
+ isDismissable?: boolean;
10
11
  }
11
12
  export declare type BottomDrawerElementType = HTMLDivElement;
12
13
  export declare type BottomDrawerProps = Omit<CommonAndHTMLProps<BottomDrawerElementType>, keyof BottomDrawerCustomProps> & BottomDrawerCustomProps;
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("../../external/Element.js"),t=require("react"),r=require("./BottomDrawer.styled.js");function l(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}require("styled-components"),require("../../external/helpers.js"),require("../../external/DefaultColours.js");var a=/*#__PURE__*/l(t);const o=a.default.forwardRef(((t,l)=>{var{isOpen:o,children:s,onCloseCallback:n,closeOnClickOutside:u,padding:d,bgColor:c,bgColour:i}=t,m=e.__rest(t,["isOpen","children","onCloseCallback","closeOnClickOutside","padding","bgColor","bgColour"]);let f=[];o&&f.push("open");const p=()=>{n&&n()};return!!o&&a.default.createElement(a.default.Fragment,null,a.default.createElement(e.Element,Object.assign({as:r.BottomDrawerStyled,ref:l,classNames:f},m),a.default.createElement(e.Element,{as:"div",classNames:[...f,"rest-of-page-overlay"],onClick:()=>{u&&p()}}),a.default.createElement(e.Element,{as:"div",className:"bottom-drawer-content-wrapper",padding:d,bgColor:c,bgColour:i},a.default.createElement(e.Element,{as:"div",className:"dismiss-button",onClick:p,role:"button"}),s)))}));exports.BottomDrawer=o;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("../../external/Element.js"),t=require("react"),l=require("./BottomDrawer.styled.js");function r(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}require("styled-components"),require("../../external/helpers.js"),require("../../external/DefaultColours.js");var a=/*#__PURE__*/r(t);const s=a.default.forwardRef(((t,r)=>{var{isOpen:s,children:o,onCloseCallback:n,closeOnClickOutside:i,padding:u,bgColor:d,bgColour:c,isDismissable:m=!0}=t,f=e.__rest(t,["isOpen","children","onCloseCallback","closeOnClickOutside","padding","bgColor","bgColour","isDismissable"]);let b=[];s&&b.push("open");const p=()=>{n&&n()};return!!s&&a.default.createElement(a.default.Fragment,null,a.default.createElement(e.Element,Object.assign({as:l.BottomDrawerStyled,ref:r,classNames:b},f),a.default.createElement(e.Element,{as:"div",classNames:[...b,"rest-of-page-overlay"],onClick:()=>{i&&p()}}),a.default.createElement(e.Element,{as:"div",className:"bottom-drawer-content-wrapper",padding:u,bgColor:d,bgColour:c},m&&a.default.createElement(e.Element,{as:"div",className:"dismiss-button",onClick:p,role:"button"}),o)))}));exports.BottomDrawer=s;
2
2
  //# sourceMappingURL=BottomDrawer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"BottomDrawer.js","sources":["../../../../src/components/BottomDrawer/BottomDrawer.tsx"],"sourcesContent":["import React from \"react\";\n\nimport { Element } from \"../Element/Element\";\nimport { ColourPropTypes, CommonAndHTMLProps } from \"../Element/constants\";\n\nimport { BottomDrawerStyled } from \"./BottomDrawer.styled\";\n\n// prettier-ignore\nexport interface BottomDrawerCustomProps {\n isOpen ? : boolean;\n onCloseCallback ? : () => void;\n overlayOpacity ? : number;\n overlayColour ? : ColourPropTypes;\n overlayColor ? : ColourPropTypes;\n closeOnClickOutside ? : boolean;\n}\n\nexport type BottomDrawerElementType = HTMLDivElement;\nexport type BottomDrawerProps = Omit<CommonAndHTMLProps<BottomDrawerElementType>, keyof BottomDrawerCustomProps> &\n BottomDrawerCustomProps;\n\nexport const BottomDrawer = React.forwardRef(\n (\n {\n isOpen,\n children,\n onCloseCallback,\n closeOnClickOutside,\n padding,\n bgColor,\n bgColour,\n ...props\n }: BottomDrawerProps,\n ref: React.Ref<BottomDrawerElementType>\n ) => {\n let classNames = [];\n\n if (isOpen) {\n classNames.push(\"open\");\n }\n\n const closeBottomDrawer = () => {\n if (onCloseCallback) {\n onCloseCallback();\n }\n };\n\n return (\n !!isOpen && (\n <>\n <Element<BottomDrawerElementType>\n as={BottomDrawerStyled}\n ref={ref}\n classNames={classNames}\n {...props}\n >\n <Element\n as=\"div\"\n classNames={[...classNames, `rest-of-page-overlay`]}\n onClick={() => {\n if (closeOnClickOutside) closeBottomDrawer();\n }}\n />\n\n <Element\n as=\"div\"\n className=\"bottom-drawer-content-wrapper\"\n padding={padding}\n bgColor={bgColor}\n bgColour={bgColour}\n >\n <Element as=\"div\" className=\"dismiss-button\" onClick={closeBottomDrawer} role=\"button\" />\n {children}\n </Element>\n </Element>\n </>\n )\n );\n }\n);\n"],"names":["BottomDrawer","React","forwardRef","_a","ref","isOpen","children","onCloseCallback","closeOnClickOutside","padding","bgColor","bgColour","props","classNames","push","closeBottomDrawer","Element","as","BottomDrawerStyled","onClick","className","role"],"mappings":"4XAqBaA,EAAeC,UAAMC,YAC9B,CACIC,EAUAC,SAVAC,OACIA,EADJC,SAEIA,EAFJC,gBAGIA,EAHJC,oBAIIA,EAJJC,QAKIA,EALJC,QAMIA,EANJC,SAOIA,KACGC,aARP,kGAYIC,EAAa,GAEbR,GACAQ,EAAWC,KAAK,cAGdC,EAAoB,KAClBR,GACAA,aAKFF,GACEJ,gDACIA,wBAACe,yBACGC,GAAIC,qBACJd,IAAKA,EACLS,WAAYA,GACRD,GAEJX,wBAACe,WACGC,GAAG,MACHJ,WAAY,IAAIA,0BAChBM,QAAS,KACDX,GAAqBO,OAIjCd,wBAACe,WACGC,GAAG,MACHG,UAAU,gCACVX,QAASA,EACTC,QAASA,EACTC,SAAUA,GAEVV,wBAACe,WAAQC,GAAG,MAAMG,UAAU,iBAAiBD,QAASJ,EAAmBM,KAAK,WAC7Ef"}
1
+ {"version":3,"file":"BottomDrawer.js","sources":["../../../../src/components/BottomDrawer/BottomDrawer.tsx"],"sourcesContent":["import React from \"react\";\n\nimport { Element } from \"../Element/Element\";\nimport { ColourPropTypes, CommonAndHTMLProps } from \"../Element/constants\";\n\nimport { BottomDrawerStyled } from \"./BottomDrawer.styled\";\n\n// prettier-ignore\nexport interface BottomDrawerCustomProps {\n isOpen ? : boolean;\n onCloseCallback ? : () => void;\n overlayOpacity ? : number;\n overlayColour ? : ColourPropTypes;\n overlayColor ? : ColourPropTypes;\n closeOnClickOutside ? : boolean;\n isDismissable ? : boolean;\n}\n\nexport type BottomDrawerElementType = HTMLDivElement;\nexport type BottomDrawerProps = Omit<CommonAndHTMLProps<BottomDrawerElementType>, keyof BottomDrawerCustomProps> &\n BottomDrawerCustomProps;\n\nexport const BottomDrawer = React.forwardRef(\n (\n {\n isOpen,\n children,\n onCloseCallback,\n closeOnClickOutside,\n padding,\n bgColor,\n bgColour,\n isDismissable = true,\n ...props\n }: BottomDrawerProps,\n ref: React.Ref<BottomDrawerElementType>\n ) => {\n let classNames = [];\n\n if (isOpen) {\n classNames.push(\"open\");\n }\n\n const closeBottomDrawer = () => {\n if (onCloseCallback) {\n onCloseCallback();\n }\n };\n\n return (\n !!isOpen && (\n <>\n <Element<BottomDrawerElementType>\n as={BottomDrawerStyled}\n ref={ref}\n classNames={classNames}\n {...props}\n >\n <Element\n as=\"div\"\n classNames={[...classNames, `rest-of-page-overlay`]}\n onClick={() => {\n if (closeOnClickOutside) closeBottomDrawer();\n }}\n />\n\n <Element\n as=\"div\"\n className=\"bottom-drawer-content-wrapper\"\n padding={padding}\n bgColor={bgColor}\n bgColour={bgColour}\n >\n {isDismissable && (\n <Element\n as=\"div\"\n className=\"dismiss-button\"\n onClick={closeBottomDrawer}\n role=\"button\"\n />\n )}\n {children}\n </Element>\n </Element>\n </>\n )\n );\n }\n);\n"],"names":["BottomDrawer","React","forwardRef","_a","ref","isOpen","children","onCloseCallback","closeOnClickOutside","padding","bgColor","bgColour","isDismissable","props","classNames","push","closeBottomDrawer","Element","as","BottomDrawerStyled","onClick","className","role"],"mappings":"4XAsBaA,EAAeC,UAAMC,YAC9B,CACIC,EAWAC,SAXAC,OACIA,EADJC,SAEIA,EAFJC,gBAGIA,EAHJC,oBAIIA,EAJJC,QAKIA,EALJC,QAMIA,EANJC,SAOIA,EAPJC,cAQIA,GAAgB,KACbC,aATP,kHAaIC,EAAa,GAEbT,GACAS,EAAWC,KAAK,cAGdC,EAAoB,KAClBT,GACAA,aAKFF,GACEJ,gDACIA,wBAACgB,yBACGC,GAAIC,qBACJf,IAAKA,EACLU,WAAYA,GACRD,GAEJZ,wBAACgB,WACGC,GAAG,MACHJ,WAAY,IAAIA,0BAChBM,QAAS,KACDZ,GAAqBQ,OAIjCf,wBAACgB,WACGC,GAAG,MACHG,UAAU,gCACVZ,QAASA,EACTC,QAASA,EACTC,SAAUA,GAETC,GACGX,wBAACgB,WACGC,GAAG,MACHG,UAAU,iBACVD,QAASJ,EACTM,KAAK,WAGZhB"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),t=require("../../external/Element.js"),r=require("../Form/InputField/InputField.js"),l=require("./PinInputField.styled.js");function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}require("../Form/BaseInputComponent/BaseInputComponent.js"),require("../Form/InputLabel/InputLabel.js"),require("../Form/FormItem/FormItem.js"),require("../Form/FormItem/FormItem.styled.js"),require("styled-components"),require("../Form/InputField/InputField.styled.js"),require("../Form/Select/Select.styled.js"),require("../Form/TextArea/TextArea.styled.js"),require("../../external/theme.js"),require("../../external/DefaultColours.js");var u=/*#__PURE__*/n(e);function a(e,t){return("alphanumeric"===t?/^[a-zA-Z0-9]+$/i:/^[0-9]+$/).test(e)}const s=u.default.forwardRef((({numberOfFields:n,onChange:s,type:o="number",mask:i=!1,otp:c=!1,autoFocus:p=!1,pasteFromClipboard:d="enabled",spacing:m="small"},f)=>{const[F,y]=e.useState([]),[v,g]=e.useState([]),[h,b]=e.useState(!0),[j,I]=e.useState(-1),q=e.useCallback((e=>{var t;const r=F[e];null===(t=null==r?void 0:r.current)||void 0===t||t.focus()}),[F]);e.useEffect((()=>{y((t=>Array(n).fill(0).map(((r,l)=>{var n;const u=t[l]||e.createRef();return p&&0===l&&(null===(n=u.current)||void 0===n||n.focus()),u}))))}),[n,p]);const C=e.useCallback((e=>{if(!h)return;const t=e+1<n?e+1:null;t&&q(t)}),[q,n,h]),k=e.useCallback(((e,t)=>{const r=[...v];r[t]=e,g(r),null==s||s(r.join(""));""!==e&&r.length===n&&r.every((e=>null!=e&&""!==e))||C(t)}),[C,n,s,v]),A=e.useCallback(((e,t)=>{let r=t;return(null==e?void 0:e.length)>0&&(e[0]===t.charAt(0)?r=t.charAt(1):e[0]===t.charAt(1)&&(r=t.charAt(0))),r}),[]),x=()=>{I(-1)};let S=[];return m&&S.push(`spacing-${m}`),u.default.createElement(t.Element,{as:l.PinInputStyled,classNames:S,ref:f},[...Array(n)].map(((e,t)=>u.default.createElement(r.InputField,{key:t,className:"pin-input-field",ref:F[t],type:i?"password":"number"===o?"tel":"text",inputMode:"number"===o?"numeric":"text",onChange:e=>((e,t)=>{const r=e.currentTarget.value,l=v[t],u=A(l,r);if(""!==u)if(r.length>1&&t<n-1){if(a(r,o)){const e=r.split("").filter(((e,t)=>t<n));g(e),q(t+e.length<n?t+e.length:n-1),null==s||s(e.join(""))}}else a(u,o)&&k(u,t),b(!0);else k("",t)})(e,t),onKeyDown:e=>((e,t)=>{var r;if("Backspace"===e.key)if(""===e.target.value){if(t>0){const e=t-1;k("",e),q(e),b(!0)}}else b(!1);else"Escape"===e.key?(null===(r=F[t].current)||void 0===r||r.blur(),x()):"ArrowRight"===e.key?t<n-1&&q(t+1):"ArrowLeft"===e.key&&t>0&&q(t-1)})(e,t),onFocus:e=>((e,t)=>{I(t),setTimeout((()=>{e.target.setSelectionRange(e.target.value.length,e.target.value.length)}),0)})(e,t),onBlur:x,placeholder:j!==t?"⦁":void 0,autoComplete:c?"one-time-code":"off",value:v[t]||"",autoFocus:p&&0===t,onCopy:e=>"disabled"===d&&e.preventDefault(),onPaste:e=>"disabled"===d&&e.preventDefault()}))))}));exports.PinInputField=s;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),t=require("../../external/Element.js"),r=require("../Form/InputField/InputField.js"),l=require("./PinInputField.styled.js");function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}require("../Form/BaseInputComponent/BaseInputComponent.js"),require("../Form/InputLabel/InputLabel.js"),require("../Form/FormItem/FormItem.js"),require("../Form/FormItem/FormItem.styled.js"),require("styled-components"),require("../Form/InputField/InputField.styled.js"),require("../Form/Select/Select.styled.js"),require("../Form/TextArea/TextArea.styled.js"),require("../../external/theme.js"),require("../../external/DefaultColours.js");var u=/*#__PURE__*/n(e);function a(e,t){return("alphanumeric"===t?/^[a-zA-Z0-9]+$/i:/^[0-9]+$/).test(e)}const s=u.default.forwardRef((({numberOfFields:n,onChange:s,type:o="number",mask:i=!1,otp:c=!1,autoFocus:p=!1,pasteFromClipboard:d="enabled",spacing:m="small"},f)=>{const[F,h]=e.useState([]),[y,g]=e.useState([]),[v,b]=e.useState(!0),[j,I]=e.useState(-1),q=e.useCallback((e=>{var t;const r=F[e];null===(t=null==r?void 0:r.current)||void 0===t||t.focus()}),[F]);e.useEffect((()=>{h((t=>Array(n).fill(0).map(((r,l)=>{var n;const u=t[l]||e.createRef();return p&&0===l&&(null===(n=u.current)||void 0===n||n.focus()),u}))))}),[n,p]);const A=e.useCallback((e=>{if(!v)return;const t=e+1<n?e+1:null;t&&q(t)}),[q,n,v]),C=e.useCallback(((e,t)=>{const r=[...y];r[t]=e,g(r),null==s||s(r.join(""));""!==e&&r.length===n&&r.every((e=>null!=e&&""!==e))&&t==n-1||(b(!0),A(t))}),[A,n,s,y]),k=()=>{I(-1)};let x=[];return m&&x.push(`spacing-${m}`),u.default.createElement(t.Element,{as:l.PinInputStyled,classNames:x,ref:f},[...Array(n)].map(((e,t)=>u.default.createElement(r.InputField,{key:t,className:"pin-input-field",ref:F[t],type:i?"password":"number"===o?"tel":"text",inputMode:"number"===o?"numeric":"text",onChange:e=>((e,t)=>{const r=e.currentTarget.value,l=y[t];if(""!==r)if(r.length>1&&t<n-1){if(a(r,o)){let u=[];u=""==l?r.split("").filter(((e,r)=>t+r<n)):e.currentTarget.selectionEnd===r.length?r.split("").filter(((e,r)=>r>0&&t+r-1<n)):r.split("").filter(((e,l)=>l<r.length-1&&t+l<n)),g((e=>e.map(((e,r)=>r>=t&&r<t+u.length?u[r-t]:e)))),q(t+u.length<n?t+u.length:n-1),null==s||s(u.join(""))}}else{let e=r;(null==l?void 0:l.length)>0&&(l[0]===r.charAt(0)?e=r.charAt(1):l[0]===r.charAt(1)&&(e=r.charAt(0))),a(e,o)&&C(e,t)}else C("",t)})(e,t),onKeyDown:e=>((e,t)=>{var r;if("Backspace"===e.key)if(""===e.target.value){if(t>0){const e=t-1;C("",e),q(e),b(!0)}}else b(!1);else"Escape"===e.key?(null===(r=F[t].current)||void 0===r||r.blur(),k()):"ArrowRight"===e.key?t<n-1&&q(t+1):"ArrowLeft"===e.key&&t>0&&q(t-1)})(e,t),onFocus:e=>((e,t)=>{I(t)})(0,t),onSelect:e=>(e=>{const t=e.target;setTimeout((()=>{t.setSelectionRange(t.value.length,t.value.length)}),0)})(e),onBlur:k,placeholder:j!==t?"⦁":void 0,autoComplete:c?"one-time-code":"off",value:y[t]||"",autoFocus:p&&0===t,onCopy:e=>"disabled"===d&&e.preventDefault(),onPaste:e=>"disabled"===d&&e.preventDefault()}))))}));exports.PinInputField=s;
2
2
  //# sourceMappingURL=PinInputField.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PinInputField.js","sources":["../../../../src/components/PinInputField/PinInputField.tsx"],"sourcesContent":["import React, { createRef, useCallback, useEffect, useState } from \"react\";\n\nimport { Element } from \"../Element/Element\";\nimport { CommonAndHTMLProps, SpacingTypes } from \"../Element/constants\";\nimport { InputField } from \"../Form/InputField/InputField\";\n\nimport { PinInputStyled } from \"./PinInputField.styled\";\n\n// prettier-ignore\ntype PinInputFieldCustomProps = {\n numberOfFields : number;\n onChange ? : (value : string) => void;\n type ? : \"alphanumeric\" | \"number\";\n mask ? : boolean;\n otp ? : boolean;\n autoFocus ? : boolean;\n pasteFromClipboard ? : \"enabled\" | \"disabled\";\n spacing ? : SpacingTypes;\n};\n\nexport type PinInputFieldElementType = HTMLDivElement;\nexport type PinInputFieldProps = Omit<CommonAndHTMLProps<PinInputFieldElementType>, keyof PinInputFieldCustomProps> &\n PinInputFieldCustomProps;\n\nfunction validate(value: string, type: \"alphanumeric\" | \"number\") {\n const NUMERIC_REGEX = /^[0-9]+$/;\n const ALPHA_NUMERIC_REGEX = /^[a-zA-Z0-9]+$/i;\n const regex = type === \"alphanumeric\" ? ALPHA_NUMERIC_REGEX : NUMERIC_REGEX;\n return regex.test(value);\n}\n\nexport const PinInputField = React.forwardRef(\n (\n {\n numberOfFields: length,\n onChange,\n type = \"number\",\n mask = false,\n otp = false,\n autoFocus = false,\n pasteFromClipboard = \"enabled\",\n spacing = \"small\",\n }: PinInputFieldProps,\n ref: React.Ref<PinInputFieldElementType>\n ) => {\n const [inputRefs, setInputRefs] = useState<React.RefObject<HTMLInputElement>[]>([]);\n const [values, setValues] = useState<string[]>([]);\n const [moveFocus, setMoveFocus] = useState<boolean>(true);\n const [focusedIndex, setFocusedIndex] = useState<number>(-1);\n\n const focus = useCallback(\n (index: number) => {\n const ref = inputRefs[index];\n ref?.current?.focus();\n },\n [inputRefs]\n );\n\n useEffect(() => {\n setInputRefs((inputRefs) => {\n const refs = Array(length)\n .fill(0)\n .map((_, i) => {\n const ref = inputRefs[i] || createRef();\n if (autoFocus && i === 0) {\n ref.current?.focus();\n }\n return ref;\n });\n return refs;\n });\n }, [length, autoFocus]);\n\n const focusNext = useCallback(\n (index: number) => {\n if (!moveFocus) return;\n const next = index + 1 < length ? index + 1 : null;\n if (next) {\n focus(next);\n }\n },\n [focus, length, moveFocus]\n );\n\n const setValue = useCallback(\n (value: string, index: number) => {\n const nextValues = [...values];\n nextValues[index] = value;\n setValues(nextValues);\n onChange?.(nextValues.join(\"\"));\n\n const isComplete =\n value !== \"\" &&\n nextValues.length === length &&\n nextValues.every((inputValue) => inputValue != null && inputValue !== \"\");\n\n if (!isComplete) {\n focusNext(index);\n }\n },\n [focusNext, length, onChange, values]\n );\n\n const getNextValue = useCallback((value: string, eventValue: string) => {\n let nextValue = eventValue;\n if (value?.length > 0) {\n if (value[0] === eventValue.charAt(0)) {\n nextValue = eventValue.charAt(1);\n } else if (value[0] === eventValue.charAt(1)) {\n nextValue = eventValue.charAt(0);\n }\n }\n return nextValue;\n }, []);\n\n const handleInputChange = (event: React.FormEvent<HTMLInputElement>, i: number) => {\n const eventValue = event.currentTarget.value;\n const currentValue = values[i];\n const nextValue = getNextValue(currentValue, eventValue);\n\n if (nextValue === \"\") {\n setValue(\"\", i);\n return;\n }\n\n if (eventValue.length > 1 && i < length - 1) {\n if (validate(eventValue, type)) {\n const nextValue = eventValue.split(\"\").filter((_, index) => index < length);\n setValues(nextValue);\n focus(i + nextValue.length < length ? i + nextValue.length : length - 1);\n onChange?.(nextValue.join(\"\"));\n }\n } else {\n if (validate(nextValue, type)) {\n setValue(nextValue, i);\n }\n setMoveFocus(true);\n }\n };\n\n const onKeyDown = (event: React.KeyboardEvent, i: number) => {\n if (event.key === \"Backspace\") {\n if ((event.target as HTMLInputElement).value === \"\") {\n if (i > 0) {\n const newIndex = i - 1;\n setValue(\"\", newIndex);\n focus(newIndex);\n setMoveFocus(true);\n }\n } else {\n setMoveFocus(false);\n }\n } else if (event.key === \"Escape\") {\n inputRefs[i].current?.blur();\n onBlur();\n } else if (event.key === \"ArrowRight\") {\n if (i < length - 1) {\n focus(i + 1);\n }\n } else if (event.key === \"ArrowLeft\") {\n if (i > 0) {\n focus(i - 1);\n }\n }\n };\n\n const onFocus = (e: React.FocusEvent<HTMLInputElement>, i: number) => {\n setFocusedIndex(i);\n setTimeout(() => {\n // https://github.com/facebook/react/issues/6483\n e.target.setSelectionRange(e.target.value.length, e.target.value.length);\n }, 0);\n };\n\n const onBlur = () => {\n setFocusedIndex(-1);\n };\n\n let classNames = [];\n\n if (spacing) {\n classNames.push(`spacing-${spacing}`);\n }\n\n return (\n <Element<PinInputFieldElementType> as={PinInputStyled} classNames={classNames} ref={ref}>\n {[...Array(length)].map((_, i) => (\n <InputField\n key={i}\n className=\"pin-input-field\"\n ref={inputRefs[i]}\n type={mask ? \"password\" : type === \"number\" ? \"tel\" : \"text\"}\n inputMode={type === \"number\" ? \"numeric\" : \"text\"}\n onChange={(e) => handleInputChange(e, i)}\n onKeyDown={(e) => onKeyDown(e, i)}\n onFocus={(e) => onFocus(e, i)}\n onBlur={onBlur}\n placeholder={focusedIndex !== i ? `\\u2981` : undefined}\n autoComplete={otp ? \"one-time-code\" : \"off\"}\n value={values[i] || \"\"}\n autoFocus={autoFocus && i === 0}\n onCopy={e=> pasteFromClipboard === \"disabled\" && e.preventDefault()}\n onPaste={e=> pasteFromClipboard === \"disabled\" && e.preventDefault()}\n />\n ))}\n </Element>\n );\n }\n);\n"],"names":["validate","value","type","test","PinInputField","React","forwardRef","numberOfFields","length","onChange","mask","otp","autoFocus","pasteFromClipboard","spacing","ref","inputRefs","setInputRefs","useState","values","setValues","moveFocus","setMoveFocus","focusedIndex","setFocusedIndex","focus","useCallback","index","current","useEffect","Array","fill","map","_","i","createRef","focusNext","next","setValue","nextValues","join","every","inputValue","getNextValue","eventValue","nextValue","charAt","onBlur","classNames","push","Element","as","PinInputStyled","InputField","key","className","inputMode","e","event","currentTarget","currentValue","split","filter","handleInputChange","onKeyDown","target","newIndex","blur","onFocus","setTimeout","setSelectionRange","placeholder","undefined","autoComplete","onCopy","preventDefault","onPaste"],"mappings":"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"}
1
+ {"version":3,"file":"PinInputField.js","sources":["../../../../src/components/PinInputField/PinInputField.tsx"],"sourcesContent":["import React, { createRef, useCallback, useEffect, useState } from \"react\";\n\nimport { Element } from \"../Element/Element\";\nimport { CommonAndHTMLProps, SpacingTypes } from \"../Element/constants\";\nimport { InputField } from \"../Form/InputField/InputField\";\n\nimport { PinInputStyled } from \"./PinInputField.styled\";\n\n// prettier-ignore\ntype PinInputFieldCustomProps = {\n numberOfFields : number;\n onChange ? : (value : string) => void;\n type ? : \"alphanumeric\" | \"number\";\n mask ? : boolean;\n otp ? : boolean;\n autoFocus ? : boolean;\n pasteFromClipboard ? : \"enabled\" | \"disabled\";\n spacing ? : SpacingTypes;\n};\n\nexport type PinInputFieldElementType = HTMLDivElement;\nexport type PinInputFieldProps = Omit<CommonAndHTMLProps<PinInputFieldElementType>, keyof PinInputFieldCustomProps> &\n PinInputFieldCustomProps;\n\nfunction validate(value: string, type: \"alphanumeric\" | \"number\") {\n const NUMERIC_REGEX = /^[0-9]+$/;\n const ALPHA_NUMERIC_REGEX = /^[a-zA-Z0-9]+$/i;\n const regex = type === \"alphanumeric\" ? ALPHA_NUMERIC_REGEX : NUMERIC_REGEX;\n return regex.test(value);\n}\n\nexport const PinInputField = React.forwardRef(\n (\n {\n numberOfFields: length,\n onChange,\n type = \"number\",\n mask = false,\n otp = false,\n autoFocus = false,\n pasteFromClipboard = \"enabled\",\n spacing = \"small\",\n }: PinInputFieldProps,\n ref: React.Ref<PinInputFieldElementType>\n ) => {\n const [inputRefs, setInputRefs] = useState<React.RefObject<HTMLInputElement>[]>([]);\n const [values, setValues] = useState<string[]>([]);\n const [moveFocus, setMoveFocus] = useState<boolean>(true);\n const [focusedIndex, setFocusedIndex] = useState<number>(-1);\n\n const focus = useCallback(\n (index: number) => {\n const ref = inputRefs[index];\n ref?.current?.focus();\n },\n [inputRefs]\n );\n\n useEffect(() => {\n setInputRefs((inputRefs) => {\n const refs = Array(length)\n .fill(0)\n .map((_, i) => {\n const ref = inputRefs[i] || createRef();\n if (autoFocus && i === 0) {\n ref.current?.focus();\n }\n return ref;\n });\n return refs;\n });\n }, [length, autoFocus]);\n\n const focusNext = useCallback(\n (index: number) => {\n if (!moveFocus) return;\n const next = index + 1 < length ? index + 1 : null;\n if (next) {\n focus(next);\n }\n },\n [focus, length, moveFocus]\n );\n\n const setValue = useCallback(\n (value: string, index: number) => {\n const nextValues = [...values];\n nextValues[index] = value;\n setValues(nextValues);\n onChange?.(nextValues.join(\"\"));\n\n const isComplete =\n value !== \"\" &&\n nextValues.length === length &&\n nextValues.every((inputValue) => inputValue != null && inputValue !== \"\") &&\n index == length - 1;\n\n if (!isComplete) {\n setMoveFocus(true);\n focusNext(index);\n }\n },\n [focusNext, length, onChange, values]\n );\n\n const handleInputChange = (event: React.FormEvent<HTMLInputElement>, inputFieldIndex: number) => {\n const eventValue = event.currentTarget.value;\n const currentValue = values[inputFieldIndex];\n\n if (eventValue === \"\") {\n setValue(\"\", inputFieldIndex);\n return;\n }\n\n // Handle scenario where multiple characters are entered in a single InputField\n if (eventValue.length > 1 && inputFieldIndex < length - 1) {\n if (validate(eventValue, type)) {\n let nextValue: string[] = [];\n // In all cases, we need to ensure characters longer than the remaining fields are removed.\n if (currentValue == \"\") {\n // Case: Current input field is empty\n nextValue = eventValue.split(\"\").filter((_, j) => inputFieldIndex + j < length);\n } else if (event.currentTarget.selectionEnd === eventValue.length) {\n // Case: Current field has a value and cursor is after it\n nextValue = eventValue.split(\"\").filter((_, j) => j > 0 && inputFieldIndex + j - 1 < length);\n } else {\n // Case: Current field has a value and cursor is before it\n nextValue = eventValue\n .split(\"\")\n .filter((_, j) => j < eventValue.length - 1 && inputFieldIndex + j < length);\n }\n setValues((values) =>\n values.map((v, j) =>\n j >= inputFieldIndex && j < inputFieldIndex + nextValue.length\n ? nextValue[j - inputFieldIndex]\n : v\n )\n );\n focus(\n inputFieldIndex + nextValue.length < length ? inputFieldIndex + nextValue.length : length - 1\n );\n onChange?.(nextValue.join(\"\"));\n }\n } else {\n let nextValue = eventValue;\n if (currentValue?.length > 0) {\n if (currentValue[0] === eventValue.charAt(0)) {\n nextValue = eventValue.charAt(1);\n } else if (currentValue[0] === eventValue.charAt(1)) {\n nextValue = eventValue.charAt(0);\n }\n }\n if (validate(nextValue, type)) {\n setValue(nextValue, inputFieldIndex);\n }\n }\n };\n\n const onKeyDown = (event: React.KeyboardEvent, i: number) => {\n if (event.key === \"Backspace\") {\n if ((event.target as HTMLInputElement).value === \"\") {\n if (i > 0) {\n const newIndex = i - 1;\n setValue(\"\", newIndex);\n focus(newIndex);\n setMoveFocus(true);\n }\n } else {\n setMoveFocus(false);\n }\n } else if (event.key === \"Escape\") {\n inputRefs[i].current?.blur();\n onBlur();\n } else if (event.key === \"ArrowRight\") {\n if (i < length - 1) {\n focus(i + 1);\n }\n } else if (event.key === \"ArrowLeft\") {\n if (i > 0) {\n focus(i - 1);\n }\n }\n };\n\n const onFocus = (e: React.FocusEvent<HTMLInputElement>, i: number) => {\n setFocusedIndex(i);\n };\n\n // When moving around the InputElements using tab key, browsers automatically select\n // the value (if it exists) in the InputElement - which we want to disable. Additionally,\n // when an existing value is selected/highlighted and pasted over, there is no way to\n // clearly distinguish between the other 2 scenarios of pasting by keeping the cursor before\n // and after the existing value. Specific example: If the existing value is 5, the event\n // when highlighting and pasting '567' is the same as placing the cursor before the existing\n // value and pasting '67'. By disabling this, we eliminate one of these cases.\n // Is this a hack? Yes. Is there a better way? IDK. Does it matter? Not unless there is a\n // valid reason for users to need selecting a single InputElement within a PinInput.\n const onSelect = (e: React.SyntheticEvent<HTMLInputElement, Event>) => {\n const target = e.target as HTMLInputElement;\n setTimeout(() => {\n // https://github.com/facebook/react/issues/6483\n target.setSelectionRange(target.value.length, target.value.length);\n }, 0);\n };\n\n const onBlur = () => {\n setFocusedIndex(-1);\n };\n\n let classNames = [];\n\n if (spacing) {\n classNames.push(`spacing-${spacing}`);\n }\n\n return (\n <Element<PinInputFieldElementType> as={PinInputStyled} classNames={classNames} ref={ref}>\n {[...Array(length)].map((_, i) => (\n <InputField\n key={i}\n className=\"pin-input-field\"\n ref={inputRefs[i]}\n type={mask ? \"password\" : type === \"number\" ? \"tel\" : \"text\"}\n inputMode={type === \"number\" ? \"numeric\" : \"text\"}\n onChange={(e) => handleInputChange(e, i)}\n onKeyDown={(e) => onKeyDown(e, i)}\n onFocus={(e) => onFocus(e, i)}\n onSelect={(e) => onSelect(e)}\n onBlur={onBlur}\n placeholder={focusedIndex !== i ? `\\u2981` : undefined}\n autoComplete={otp ? \"one-time-code\" : \"off\"}\n value={values[i] || \"\"}\n autoFocus={autoFocus && i === 0}\n onCopy={(e) => pasteFromClipboard === \"disabled\" && e.preventDefault()}\n onPaste={(e) => pasteFromClipboard === \"disabled\" && e.preventDefault()}\n />\n ))}\n </Element>\n );\n }\n);\n"],"names":["validate","value","type","test","PinInputField","React","forwardRef","numberOfFields","length","onChange","mask","otp","autoFocus","pasteFromClipboard","spacing","ref","inputRefs","setInputRefs","useState","values","setValues","moveFocus","setMoveFocus","focusedIndex","setFocusedIndex","focus","useCallback","index","current","useEffect","Array","fill","map","_","i","createRef","focusNext","next","setValue","nextValues","join","every","inputValue","onBlur","classNames","push","Element","as","PinInputStyled","InputField","key","className","inputMode","e","event","inputFieldIndex","eventValue","currentTarget","currentValue","nextValue","split","filter","j","selectionEnd","v","charAt","handleInputChange","onKeyDown","target","newIndex","blur","onFocus","onSelect","setTimeout","setSelectionRange","placeholder","undefined","autoComplete","onCopy","preventDefault","onPaste"],"mappings":"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"}
@@ -7,6 +7,7 @@ export interface BottomDrawerCustomProps {
7
7
  overlayColour?: ColourPropTypes;
8
8
  overlayColor?: ColourPropTypes;
9
9
  closeOnClickOutside?: boolean;
10
+ isDismissable?: boolean;
10
11
  }
11
12
  export declare type BottomDrawerElementType = HTMLDivElement;
12
13
  export declare type BottomDrawerProps = Omit<CommonAndHTMLProps<BottomDrawerElementType>, keyof BottomDrawerCustomProps> & BottomDrawerCustomProps;
@@ -1,2 +1,2 @@
1
- import{_ as e,E as o}from"../../external/Element.js";import r from"react";import{BottomDrawerStyled as t}from"./BottomDrawer.styled.js";import"styled-components";import"../../external/helpers.js";import"../../external/DefaultColours.js";const l=/*#__PURE__*/r.forwardRef(((l,s)=>{var{isOpen:a,children:n,onCloseCallback:c,closeOnClickOutside:i,padding:m,bgColor:p,bgColour:d}=l,C=e(l,["isOpen","children","onCloseCallback","closeOnClickOutside","padding","bgColor","bgColour"]);let b=[];a&&b.push("open");const g=()=>{c&&c()};return!!a&&/*#__PURE__*/r.createElement(r.Fragment,null,/*#__PURE__*/r.createElement(o,Object.assign({as:t,ref:s,classNames:b},C),/*#__PURE__*/r.createElement(o,{as:"div",classNames:[...b,"rest-of-page-overlay"],onClick:()=>{i&&g()}}),/*#__PURE__*/r.createElement(o,{as:"div",className:"bottom-drawer-content-wrapper",padding:m,bgColor:p,bgColour:d},/*#__PURE__*/r.createElement(o,{as:"div",className:"dismiss-button",onClick:g,role:"button"}),n)))}));export{l as BottomDrawer};
1
+ import{_ as e,E as s}from"../../external/Element.js";import o from"react";import{BottomDrawerStyled as l}from"./BottomDrawer.styled.js";import"styled-components";import"../../external/helpers.js";import"../../external/DefaultColours.js";const r=/*#__PURE__*/o.forwardRef(((r,t)=>{var{isOpen:a,children:n,onCloseCallback:i,closeOnClickOutside:m,padding:c,bgColor:p,bgColour:d,isDismissable:C=!0}=r,b=e(r,["isOpen","children","onCloseCallback","closeOnClickOutside","padding","bgColor","bgColour","isDismissable"]);let g=[];a&&g.push("open");const u=()=>{i&&i()};return!!a&&/*#__PURE__*/o.createElement(o.Fragment,null,/*#__PURE__*/o.createElement(s,Object.assign({as:l,ref:t,classNames:g},b),/*#__PURE__*/o.createElement(s,{as:"div",classNames:[...g,"rest-of-page-overlay"],onClick:()=>{m&&u()}}),/*#__PURE__*/o.createElement(s,{as:"div",className:"bottom-drawer-content-wrapper",padding:c,bgColor:p,bgColour:d},C&&/*#__PURE__*/o.createElement(s,{as:"div",className:"dismiss-button",onClick:u,role:"button"}),n)))}));export{r as BottomDrawer};
2
2
  //# sourceMappingURL=BottomDrawer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"BottomDrawer.js","sources":["../../../../src/components/BottomDrawer/BottomDrawer.tsx"],"sourcesContent":["import React from \"react\";\n\nimport { Element } from \"../Element/Element\";\nimport { ColourPropTypes, CommonAndHTMLProps } from \"../Element/constants\";\n\nimport { BottomDrawerStyled } from \"./BottomDrawer.styled\";\n\n// prettier-ignore\nexport interface BottomDrawerCustomProps {\n isOpen ? : boolean;\n onCloseCallback ? : () => void;\n overlayOpacity ? : number;\n overlayColour ? : ColourPropTypes;\n overlayColor ? : ColourPropTypes;\n closeOnClickOutside ? : boolean;\n}\n\nexport type BottomDrawerElementType = HTMLDivElement;\nexport type BottomDrawerProps = Omit<CommonAndHTMLProps<BottomDrawerElementType>, keyof BottomDrawerCustomProps> &\n BottomDrawerCustomProps;\n\nexport const BottomDrawer = React.forwardRef(\n (\n {\n isOpen,\n children,\n onCloseCallback,\n closeOnClickOutside,\n padding,\n bgColor,\n bgColour,\n ...props\n }: BottomDrawerProps,\n ref: React.Ref<BottomDrawerElementType>\n ) => {\n let classNames = [];\n\n if (isOpen) {\n classNames.push(\"open\");\n }\n\n const closeBottomDrawer = () => {\n if (onCloseCallback) {\n onCloseCallback();\n }\n };\n\n return (\n !!isOpen && (\n <>\n <Element<BottomDrawerElementType>\n as={BottomDrawerStyled}\n ref={ref}\n classNames={classNames}\n {...props}\n >\n <Element\n as=\"div\"\n classNames={[...classNames, `rest-of-page-overlay`]}\n onClick={() => {\n if (closeOnClickOutside) closeBottomDrawer();\n }}\n />\n\n <Element\n as=\"div\"\n className=\"bottom-drawer-content-wrapper\"\n padding={padding}\n bgColor={bgColor}\n bgColour={bgColour}\n >\n <Element as=\"div\" className=\"dismiss-button\" onClick={closeBottomDrawer} role=\"button\" />\n {children}\n </Element>\n </Element>\n </>\n )\n );\n }\n);\n"],"names":["BottomDrawer","React","forwardRef","_a","ref","isOpen","children","onCloseCallback","closeOnClickOutside","padding","bgColor","bgColour","props","classNames","push","closeBottomDrawer","Element","as","BottomDrawerStyled","onClick","className","role"],"mappings":"mPAqBaA,eAAeC,EAAMC,YAC9B,CACIC,EAUAC,SAVAC,OACIA,EADJC,SAEIA,EAFJC,gBAGIA,EAHJC,oBAIIA,EAJJC,QAKIA,EALJC,QAMIA,EANJC,SAOIA,KACGC,MARP,kGAYIC,EAAa,GAEbR,GACAQ,EAAWC,KAAK,cAGdC,EAAoB,KAClBR,GACAA,aAKFF,gBACEJ,6CACIA,gBAACe,iBACGC,GAAIC,EACJd,IAAKA,EACLS,WAAYA,GACRD,gBAEJX,gBAACe,GACGC,GAAG,MACHJ,WAAY,IAAIA,0BAChBM,QAAS,KACDX,GAAqBO,oBAIjCd,gBAACe,GACGC,GAAG,MACHG,UAAU,gCACVX,QAASA,EACTC,QAASA,EACTC,SAAUA,gBAEVV,gBAACe,GAAQC,GAAG,MAAMG,UAAU,iBAAiBD,QAASJ,EAAmBM,KAAK,WAC7Ef"}
1
+ {"version":3,"file":"BottomDrawer.js","sources":["../../../../src/components/BottomDrawer/BottomDrawer.tsx"],"sourcesContent":["import React from \"react\";\n\nimport { Element } from \"../Element/Element\";\nimport { ColourPropTypes, CommonAndHTMLProps } from \"../Element/constants\";\n\nimport { BottomDrawerStyled } from \"./BottomDrawer.styled\";\n\n// prettier-ignore\nexport interface BottomDrawerCustomProps {\n isOpen ? : boolean;\n onCloseCallback ? : () => void;\n overlayOpacity ? : number;\n overlayColour ? : ColourPropTypes;\n overlayColor ? : ColourPropTypes;\n closeOnClickOutside ? : boolean;\n isDismissable ? : boolean;\n}\n\nexport type BottomDrawerElementType = HTMLDivElement;\nexport type BottomDrawerProps = Omit<CommonAndHTMLProps<BottomDrawerElementType>, keyof BottomDrawerCustomProps> &\n BottomDrawerCustomProps;\n\nexport const BottomDrawer = React.forwardRef(\n (\n {\n isOpen,\n children,\n onCloseCallback,\n closeOnClickOutside,\n padding,\n bgColor,\n bgColour,\n isDismissable = true,\n ...props\n }: BottomDrawerProps,\n ref: React.Ref<BottomDrawerElementType>\n ) => {\n let classNames = [];\n\n if (isOpen) {\n classNames.push(\"open\");\n }\n\n const closeBottomDrawer = () => {\n if (onCloseCallback) {\n onCloseCallback();\n }\n };\n\n return (\n !!isOpen && (\n <>\n <Element<BottomDrawerElementType>\n as={BottomDrawerStyled}\n ref={ref}\n classNames={classNames}\n {...props}\n >\n <Element\n as=\"div\"\n classNames={[...classNames, `rest-of-page-overlay`]}\n onClick={() => {\n if (closeOnClickOutside) closeBottomDrawer();\n }}\n />\n\n <Element\n as=\"div\"\n className=\"bottom-drawer-content-wrapper\"\n padding={padding}\n bgColor={bgColor}\n bgColour={bgColour}\n >\n {isDismissable && (\n <Element\n as=\"div\"\n className=\"dismiss-button\"\n onClick={closeBottomDrawer}\n role=\"button\"\n />\n )}\n {children}\n </Element>\n </Element>\n </>\n )\n );\n }\n);\n"],"names":["BottomDrawer","React","forwardRef","_a","ref","isOpen","children","onCloseCallback","closeOnClickOutside","padding","bgColor","bgColour","isDismissable","props","classNames","push","closeBottomDrawer","Element","as","BottomDrawerStyled","onClick","className","role"],"mappings":"mPAsBaA,eAAeC,EAAMC,YAC9B,CACIC,EAWAC,SAXAC,OACIA,EADJC,SAEIA,EAFJC,gBAGIA,EAHJC,oBAIIA,EAJJC,QAKIA,EALJC,QAMIA,EANJC,SAOIA,EAPJC,cAQIA,GAAgB,KACbC,MATP,kHAaIC,EAAa,GAEbT,GACAS,EAAWC,KAAK,cAGdC,EAAoB,KAClBT,GACAA,aAKFF,gBACEJ,6CACIA,gBAACgB,iBACGC,GAAIC,EACJf,IAAKA,EACLU,WAAYA,GACRD,gBAEJZ,gBAACgB,GACGC,GAAG,MACHJ,WAAY,IAAIA,0BAChBM,QAAS,KACDZ,GAAqBQ,oBAIjCf,gBAACgB,GACGC,GAAG,MACHG,UAAU,gCACVZ,QAASA,EACTC,QAASA,EACTC,SAAUA,GAETC,gBACGX,gBAACgB,GACGC,GAAG,MACHG,UAAU,iBACVD,QAASJ,EACTM,KAAK,WAGZhB"}
@@ -1,2 +1,2 @@
1
- import e,{useState as t,useCallback as r,useEffect as o,createRef as n}from"react";import{E as l}from"../../external/Element.js";import{InputField as a}from"../Form/InputField/InputField.js";import{PinInputStyled as s}from"./PinInputField.styled.js";import"../Form/BaseInputComponent/BaseInputComponent.js";import"../Form/InputLabel/InputLabel.js";import"../Form/FormItem/FormItem.js";import"../Form/FormItem/FormItem.styled.js";import"styled-components";import"../Form/InputField/InputField.styled.js";import"../Form/Select/Select.styled.js";import"../Form/TextArea/TextArea.styled.js";import"../../external/theme.js";import"../../external/DefaultColours.js";function m(e,t){return("alphanumeric"===t?/^[a-zA-Z0-9]+$/i:/^[0-9]+$/).test(e)}const u=/*#__PURE__*/e.forwardRef((({numberOfFields:u,onChange:i,type:p="number",mask:c=!1,otp:d=!1,autoFocus:f=!1,pasteFromClipboard:F="enabled",spacing:g="small"},h)=>{const[y,v]=t([]),[j,I]=t([]),[b,A]=t(!0),[x,C]=t(-1),k=r((e=>{var t;const r=y[e];null===(t=null==r?void 0:r.current)||void 0===t||t.focus()}),[y]);o((()=>{v((e=>Array(u).fill(0).map(((t,r)=>{var o;const l=e[r]||/*#__PURE__*/n();return f&&0===r&&(null===(o=l.current)||void 0===o||o.focus()),l}))))}),[u,f]);const w=r((e=>{if(!b)return;const t=e+1<u?e+1:null;t&&k(t)}),[k,u,b]),E=r(((e,t)=>{const r=[...j];r[t]=e,I(r),null==i||i(r.join(""));""!==e&&r.length===u&&r.every((e=>null!=e&&""!==e))||w(t)}),[w,u,i,j]),B=r(((e,t)=>{let r=t;return(null==e?void 0:e.length)>0&&(e[0]===t.charAt(0)?r=t.charAt(1):e[0]===t.charAt(1)&&(r=t.charAt(0))),r}),[]),D=()=>{C(-1)};let T=[];return g&&T.push(`spacing-${g}`),/*#__PURE__*/e.createElement(l,{as:s,classNames:T,ref:h},[...Array(u)].map(((t,r)=>/*#__PURE__*/e.createElement(a,{key:r,className:"pin-input-field",ref:y[r],type:c?"password":"number"===p?"tel":"text",inputMode:"number"===p?"numeric":"text",onChange:e=>((e,t)=>{const r=e.currentTarget.value,o=j[t],n=B(o,r);if(""!==n)if(r.length>1&&t<u-1){if(m(r,p)){const e=r.split("").filter(((e,t)=>t<u));I(e),k(t+e.length<u?t+e.length:u-1),null==i||i(e.join(""))}}else m(n,p)&&E(n,t),A(!0);else E("",t)})(e,r),onKeyDown:e=>((e,t)=>{var r;if("Backspace"===e.key)if(""===e.target.value){if(t>0){const e=t-1;E("",e),k(e),A(!0)}}else A(!1);else"Escape"===e.key?(null===(r=y[t].current)||void 0===r||r.blur(),D()):"ArrowRight"===e.key?t<u-1&&k(t+1):"ArrowLeft"===e.key&&t>0&&k(t-1)})(e,r),onFocus:e=>((e,t)=>{C(t),setTimeout((()=>{e.target.setSelectionRange(e.target.value.length,e.target.value.length)}),0)})(e,r),onBlur:D,placeholder:x!==r?"⦁":void 0,autoComplete:d?"one-time-code":"off",value:j[r]||"",autoFocus:f&&0===r,onCopy:e=>"disabled"===F&&e.preventDefault(),onPaste:e=>"disabled"===F&&e.preventDefault()}))))}));export{u as PinInputField};
1
+ import e,{useState as t,useCallback as r,useEffect as n,createRef as l}from"react";import{E as o}from"../../external/Element.js";import{InputField as s}from"../Form/InputField/InputField.js";import{PinInputStyled as a}from"./PinInputField.styled.js";import"../Form/BaseInputComponent/BaseInputComponent.js";import"../Form/InputLabel/InputLabel.js";import"../Form/FormItem/FormItem.js";import"../Form/FormItem/FormItem.styled.js";import"styled-components";import"../Form/InputField/InputField.styled.js";import"../Form/Select/Select.styled.js";import"../Form/TextArea/TextArea.styled.js";import"../../external/theme.js";import"../../external/DefaultColours.js";function i(e,t){return("alphanumeric"===t?/^[a-zA-Z0-9]+$/i:/^[0-9]+$/).test(e)}const m=/*#__PURE__*/e.forwardRef((({numberOfFields:m,onChange:u,type:p="number",mask:c=!1,otp:d=!1,autoFocus:f=!1,pasteFromClipboard:F="enabled",spacing:h="small"},g)=>{const[y,v]=t([]),[j,I]=t([]),[b,A]=t(!0),[x,C]=t(-1),k=r((e=>{var t;const r=y[e];null===(t=null==r?void 0:r.current)||void 0===t||t.focus()}),[y]);n((()=>{v((e=>Array(m).fill(0).map(((t,r)=>{var n;const o=e[r]||/*#__PURE__*/l();return f&&0===r&&(null===(n=o.current)||void 0===n||n.focus()),o}))))}),[m,f]);const E=r((e=>{if(!b)return;const t=e+1<m?e+1:null;t&&k(t)}),[k,m,b]),w=r(((e,t)=>{const r=[...j];r[t]=e,I(r),null==u||u(r.join(""));""!==e&&r.length===m&&r.every((e=>null!=e&&""!==e))&&t==m-1||(A(!0),E(t))}),[E,m,u,j]),T=()=>{C(-1)};let B=[];return h&&B.push(`spacing-${h}`),/*#__PURE__*/e.createElement(o,{as:a,classNames:B,ref:g},[...Array(m)].map(((t,r)=>/*#__PURE__*/e.createElement(s,{key:r,className:"pin-input-field",ref:y[r],type:c?"password":"number"===p?"tel":"text",inputMode:"number"===p?"numeric":"text",onChange:e=>((e,t)=>{const r=e.currentTarget.value,n=j[t];if(""!==r)if(r.length>1&&t<m-1){if(i(r,p)){let l=[];l=""==n?r.split("").filter(((e,r)=>t+r<m)):e.currentTarget.selectionEnd===r.length?r.split("").filter(((e,r)=>r>0&&t+r-1<m)):r.split("").filter(((e,n)=>n<r.length-1&&t+n<m)),I((e=>e.map(((e,r)=>r>=t&&r<t+l.length?l[r-t]:e)))),k(t+l.length<m?t+l.length:m-1),null==u||u(l.join(""))}}else{let e=r;(null==n?void 0:n.length)>0&&(n[0]===r.charAt(0)?e=r.charAt(1):n[0]===r.charAt(1)&&(e=r.charAt(0))),i(e,p)&&w(e,t)}else w("",t)})(e,r),onKeyDown:e=>((e,t)=>{var r;if("Backspace"===e.key)if(""===e.target.value){if(t>0){const e=t-1;w("",e),k(e),A(!0)}}else A(!1);else"Escape"===e.key?(null===(r=y[t].current)||void 0===r||r.blur(),T()):"ArrowRight"===e.key?t<m-1&&k(t+1):"ArrowLeft"===e.key&&t>0&&k(t-1)})(e,r),onFocus:e=>((e,t)=>{C(t)})(0,r),onSelect:e=>(e=>{const t=e.target;setTimeout((()=>{t.setSelectionRange(t.value.length,t.value.length)}),0)})(e),onBlur:T,placeholder:x!==r?"⦁":void 0,autoComplete:d?"one-time-code":"off",value:j[r]||"",autoFocus:f&&0===r,onCopy:e=>"disabled"===F&&e.preventDefault(),onPaste:e=>"disabled"===F&&e.preventDefault()}))))}));export{m as PinInputField};
2
2
  //# sourceMappingURL=PinInputField.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PinInputField.js","sources":["../../../../src/components/PinInputField/PinInputField.tsx"],"sourcesContent":["import React, { createRef, useCallback, useEffect, useState } from \"react\";\n\nimport { Element } from \"../Element/Element\";\nimport { CommonAndHTMLProps, SpacingTypes } from \"../Element/constants\";\nimport { InputField } from \"../Form/InputField/InputField\";\n\nimport { PinInputStyled } from \"./PinInputField.styled\";\n\n// prettier-ignore\ntype PinInputFieldCustomProps = {\n numberOfFields : number;\n onChange ? : (value : string) => void;\n type ? : \"alphanumeric\" | \"number\";\n mask ? : boolean;\n otp ? : boolean;\n autoFocus ? : boolean;\n pasteFromClipboard ? : \"enabled\" | \"disabled\";\n spacing ? : SpacingTypes;\n};\n\nexport type PinInputFieldElementType = HTMLDivElement;\nexport type PinInputFieldProps = Omit<CommonAndHTMLProps<PinInputFieldElementType>, keyof PinInputFieldCustomProps> &\n PinInputFieldCustomProps;\n\nfunction validate(value: string, type: \"alphanumeric\" | \"number\") {\n const NUMERIC_REGEX = /^[0-9]+$/;\n const ALPHA_NUMERIC_REGEX = /^[a-zA-Z0-9]+$/i;\n const regex = type === \"alphanumeric\" ? ALPHA_NUMERIC_REGEX : NUMERIC_REGEX;\n return regex.test(value);\n}\n\nexport const PinInputField = React.forwardRef(\n (\n {\n numberOfFields: length,\n onChange,\n type = \"number\",\n mask = false,\n otp = false,\n autoFocus = false,\n pasteFromClipboard = \"enabled\",\n spacing = \"small\",\n }: PinInputFieldProps,\n ref: React.Ref<PinInputFieldElementType>\n ) => {\n const [inputRefs, setInputRefs] = useState<React.RefObject<HTMLInputElement>[]>([]);\n const [values, setValues] = useState<string[]>([]);\n const [moveFocus, setMoveFocus] = useState<boolean>(true);\n const [focusedIndex, setFocusedIndex] = useState<number>(-1);\n\n const focus = useCallback(\n (index: number) => {\n const ref = inputRefs[index];\n ref?.current?.focus();\n },\n [inputRefs]\n );\n\n useEffect(() => {\n setInputRefs((inputRefs) => {\n const refs = Array(length)\n .fill(0)\n .map((_, i) => {\n const ref = inputRefs[i] || createRef();\n if (autoFocus && i === 0) {\n ref.current?.focus();\n }\n return ref;\n });\n return refs;\n });\n }, [length, autoFocus]);\n\n const focusNext = useCallback(\n (index: number) => {\n if (!moveFocus) return;\n const next = index + 1 < length ? index + 1 : null;\n if (next) {\n focus(next);\n }\n },\n [focus, length, moveFocus]\n );\n\n const setValue = useCallback(\n (value: string, index: number) => {\n const nextValues = [...values];\n nextValues[index] = value;\n setValues(nextValues);\n onChange?.(nextValues.join(\"\"));\n\n const isComplete =\n value !== \"\" &&\n nextValues.length === length &&\n nextValues.every((inputValue) => inputValue != null && inputValue !== \"\");\n\n if (!isComplete) {\n focusNext(index);\n }\n },\n [focusNext, length, onChange, values]\n );\n\n const getNextValue = useCallback((value: string, eventValue: string) => {\n let nextValue = eventValue;\n if (value?.length > 0) {\n if (value[0] === eventValue.charAt(0)) {\n nextValue = eventValue.charAt(1);\n } else if (value[0] === eventValue.charAt(1)) {\n nextValue = eventValue.charAt(0);\n }\n }\n return nextValue;\n }, []);\n\n const handleInputChange = (event: React.FormEvent<HTMLInputElement>, i: number) => {\n const eventValue = event.currentTarget.value;\n const currentValue = values[i];\n const nextValue = getNextValue(currentValue, eventValue);\n\n if (nextValue === \"\") {\n setValue(\"\", i);\n return;\n }\n\n if (eventValue.length > 1 && i < length - 1) {\n if (validate(eventValue, type)) {\n const nextValue = eventValue.split(\"\").filter((_, index) => index < length);\n setValues(nextValue);\n focus(i + nextValue.length < length ? i + nextValue.length : length - 1);\n onChange?.(nextValue.join(\"\"));\n }\n } else {\n if (validate(nextValue, type)) {\n setValue(nextValue, i);\n }\n setMoveFocus(true);\n }\n };\n\n const onKeyDown = (event: React.KeyboardEvent, i: number) => {\n if (event.key === \"Backspace\") {\n if ((event.target as HTMLInputElement).value === \"\") {\n if (i > 0) {\n const newIndex = i - 1;\n setValue(\"\", newIndex);\n focus(newIndex);\n setMoveFocus(true);\n }\n } else {\n setMoveFocus(false);\n }\n } else if (event.key === \"Escape\") {\n inputRefs[i].current?.blur();\n onBlur();\n } else if (event.key === \"ArrowRight\") {\n if (i < length - 1) {\n focus(i + 1);\n }\n } else if (event.key === \"ArrowLeft\") {\n if (i > 0) {\n focus(i - 1);\n }\n }\n };\n\n const onFocus = (e: React.FocusEvent<HTMLInputElement>, i: number) => {\n setFocusedIndex(i);\n setTimeout(() => {\n // https://github.com/facebook/react/issues/6483\n e.target.setSelectionRange(e.target.value.length, e.target.value.length);\n }, 0);\n };\n\n const onBlur = () => {\n setFocusedIndex(-1);\n };\n\n let classNames = [];\n\n if (spacing) {\n classNames.push(`spacing-${spacing}`);\n }\n\n return (\n <Element<PinInputFieldElementType> as={PinInputStyled} classNames={classNames} ref={ref}>\n {[...Array(length)].map((_, i) => (\n <InputField\n key={i}\n className=\"pin-input-field\"\n ref={inputRefs[i]}\n type={mask ? \"password\" : type === \"number\" ? \"tel\" : \"text\"}\n inputMode={type === \"number\" ? \"numeric\" : \"text\"}\n onChange={(e) => handleInputChange(e, i)}\n onKeyDown={(e) => onKeyDown(e, i)}\n onFocus={(e) => onFocus(e, i)}\n onBlur={onBlur}\n placeholder={focusedIndex !== i ? `\\u2981` : undefined}\n autoComplete={otp ? \"one-time-code\" : \"off\"}\n value={values[i] || \"\"}\n autoFocus={autoFocus && i === 0}\n onCopy={e=> pasteFromClipboard === \"disabled\" && e.preventDefault()}\n onPaste={e=> pasteFromClipboard === \"disabled\" && e.preventDefault()}\n />\n ))}\n </Element>\n );\n }\n);\n"],"names":["validate","value","type","test","PinInputField","React","forwardRef","numberOfFields","length","onChange","mask","otp","autoFocus","pasteFromClipboard","spacing","ref","inputRefs","setInputRefs","useState","values","setValues","moveFocus","setMoveFocus","focusedIndex","setFocusedIndex","focus","useCallback","index","current","useEffect","Array","fill","map","_","i","createRef","focusNext","next","setValue","nextValues","join","every","inputValue","getNextValue","eventValue","nextValue","charAt","onBlur","classNames","push","Element","as","PinInputStyled","InputField","key","className","inputMode","e","event","currentTarget","currentValue","split","filter","handleInputChange","onKeyDown","target","newIndex","blur","onFocus","setTimeout","setSelectionRange","placeholder","undefined","autoComplete","onCopy","preventDefault","onPaste"],"mappings":"opBAwBA,SAASA,EAASC,EAAeC,UAGN,iBAATA,EADc,kBADN,YAGTC,KAAKF,SAGTG,eAAgBC,EAAMC,YAC/B,EAEQC,eAAgBC,EAChBC,SAAAA,EACAP,KAAAA,EAAO,SACPQ,KAAAA,GAAO,EACPC,IAAAA,GAAM,EACNC,UAAAA,GAAY,EACZC,mBAAAA,EAAqB,UACrBC,QAAAA,EAAU,SAEdC,WAEOC,EAAWC,GAAgBC,EAA8C,KACzEC,EAAQC,GAAaF,EAAmB,KACxCG,EAAWC,GAAgBJ,GAAkB,IAC7CK,EAAcC,GAAmBN,GAAkB,GAEpDO,EAAQC,GACTC,gBACSZ,EAAMC,EAAUW,aACtBZ,MAAAA,SAAAA,EAAKa,wBAASH,UAElB,CAACT,IAGLa,GAAU,KACNZ,GAAcD,GACGc,MAAMtB,GACduB,KAAK,GACLC,KAAI,CAACC,EAAGC,iBACCnB,EAAMC,EAAUkB,iBAAMC,WACxBvB,GAAmB,IAANsB,cACbnB,EAAIa,wBAASH,SAEVV,SAIpB,CAACP,EAAQI,UAENwB,EAAYV,GACbC,QACQN,EAAW,aACVgB,EAAOV,EAAQ,EAAInB,EAASmB,EAAQ,EAAI,KAC1CU,GACAZ,EAAMY,KAGd,CAACZ,EAAOjB,EAAQa,IAGdiB,EAAWZ,GACb,CAACzB,EAAe0B,WACNY,EAAa,IAAIpB,GACvBoB,EAAWZ,GAAS1B,EACpBmB,EAAUmB,GACV9B,MAAAA,GAAAA,EAAW8B,EAAWC,KAAK,KAGb,KAAVvC,GACAsC,EAAW/B,SAAWA,GACtB+B,EAAWE,OAAOC,GAA6B,MAAdA,GAAqC,KAAfA,KAGvDN,EAAUT,KAGlB,CAACS,EAAW5B,EAAQC,EAAUU,IAG5BwB,EAAejB,GAAY,CAACzB,EAAe2C,SACzCC,EAAYD,SACZ3C,MAAAA,SAAAA,EAAOO,QAAS,IACZP,EAAM,KAAO2C,EAAWE,OAAO,GAC/BD,EAAYD,EAAWE,OAAO,GACvB7C,EAAM,KAAO2C,EAAWE,OAAO,KACtCD,EAAYD,EAAWE,OAAO,KAG/BD,IACR,IA6DGE,EAAS,KACXvB,GAAiB,QAGjBwB,EAAa,UAEblC,GACAkC,EAAWC,gBAAgBnC,kBAI3BT,gBAAC6C,GAAkCC,GAAIC,EAAgBJ,WAAYA,EAAYjC,IAAKA,GAC/E,IAAIe,MAAMtB,IAASwB,KAAI,CAACC,EAAGC,iBACxB7B,gBAACgD,GACGC,IAAKpB,EACLqB,UAAU,kBACVxC,IAAKC,EAAUkB,GACfhC,KAAMQ,EAAO,WAAsB,WAATR,EAAoB,MAAQ,OACtDsD,UAAoB,WAATtD,EAAoB,UAAY,OAC3CO,SAAWgD,GA9ED,EAACC,EAA0CxB,WAC3DU,EAAac,EAAMC,cAAc1D,MACjC2D,EAAezC,EAAOe,GACtBW,EAAYF,EAAaiB,EAAchB,MAE3B,KAAdC,KAKAD,EAAWpC,OAAS,GAAK0B,EAAI1B,EAAS,MAClCR,EAAS4C,EAAY1C,GAAO,OACtB2C,EAAYD,EAAWiB,MAAM,IAAIC,QAAO,CAAC7B,EAAGN,IAAUA,EAAQnB,IACpEY,EAAUyB,GACVpB,EAAMS,EAAIW,EAAUrC,OAASA,EAAS0B,EAAIW,EAAUrC,OAASA,EAAS,GACtEC,MAAAA,GAAAA,EAAWoC,EAAUL,KAAK,WAG1BxC,EAAS6C,EAAW3C,IACpBoC,EAASO,EAAWX,GAExBZ,GAAa,QAfbgB,EAAS,GAAIJ,IAwEY6B,CAAkBN,EAAGvB,GACtC8B,UAAYP,GAtDV,EAACC,EAA4BxB,cACzB,cAAdwB,EAAMJ,OAC2C,KAA5CI,EAAMO,OAA4BhE,UAC/BiC,EAAI,EAAG,OACDgC,EAAWhC,EAAI,EACrBI,EAAS,GAAI4B,GACbzC,EAAMyC,GACN5C,GAAa,SAGjBA,GAAa,OAEI,WAAdoC,EAAMJ,eACbtC,EAAUkB,GAAGN,wBAASuC,OACtBpB,KACqB,eAAdW,EAAMJ,IACTpB,EAAI1B,EAAS,GACbiB,EAAMS,EAAI,GAEO,cAAdwB,EAAMJ,KACTpB,EAAI,GACJT,EAAMS,EAAI,IAiCY8B,CAAUP,EAAGvB,GAC/BkC,QAAUX,GA7BV,EAACA,EAAuCvB,KACpDV,EAAgBU,GAChBmC,YAAW,KAEPZ,EAAEQ,OAAOK,kBAAkBb,EAAEQ,OAAOhE,MAAMO,OAAQiD,EAAEQ,OAAOhE,MAAMO,UAClE,IAwByB4D,CAAQX,EAAGvB,GAC3Ba,OAAQA,EACRwB,YAAahD,IAAiBW,WAAesC,EAC7CC,aAAc9D,EAAM,gBAAkB,MACtCV,MAAOkB,EAAOe,IAAM,GACpBtB,UAAWA,GAAmB,IAANsB,EACxBwC,OAAQjB,GAA2B,aAAvB5C,GAAqC4C,EAAEkB,iBACnDC,QAASnB,GAA2B,aAAvB5C,GAAqC4C,EAAEkB"}
1
+ {"version":3,"file":"PinInputField.js","sources":["../../../../src/components/PinInputField/PinInputField.tsx"],"sourcesContent":["import React, { createRef, useCallback, useEffect, useState } from \"react\";\n\nimport { Element } from \"../Element/Element\";\nimport { CommonAndHTMLProps, SpacingTypes } from \"../Element/constants\";\nimport { InputField } from \"../Form/InputField/InputField\";\n\nimport { PinInputStyled } from \"./PinInputField.styled\";\n\n// prettier-ignore\ntype PinInputFieldCustomProps = {\n numberOfFields : number;\n onChange ? : (value : string) => void;\n type ? : \"alphanumeric\" | \"number\";\n mask ? : boolean;\n otp ? : boolean;\n autoFocus ? : boolean;\n pasteFromClipboard ? : \"enabled\" | \"disabled\";\n spacing ? : SpacingTypes;\n};\n\nexport type PinInputFieldElementType = HTMLDivElement;\nexport type PinInputFieldProps = Omit<CommonAndHTMLProps<PinInputFieldElementType>, keyof PinInputFieldCustomProps> &\n PinInputFieldCustomProps;\n\nfunction validate(value: string, type: \"alphanumeric\" | \"number\") {\n const NUMERIC_REGEX = /^[0-9]+$/;\n const ALPHA_NUMERIC_REGEX = /^[a-zA-Z0-9]+$/i;\n const regex = type === \"alphanumeric\" ? ALPHA_NUMERIC_REGEX : NUMERIC_REGEX;\n return regex.test(value);\n}\n\nexport const PinInputField = React.forwardRef(\n (\n {\n numberOfFields: length,\n onChange,\n type = \"number\",\n mask = false,\n otp = false,\n autoFocus = false,\n pasteFromClipboard = \"enabled\",\n spacing = \"small\",\n }: PinInputFieldProps,\n ref: React.Ref<PinInputFieldElementType>\n ) => {\n const [inputRefs, setInputRefs] = useState<React.RefObject<HTMLInputElement>[]>([]);\n const [values, setValues] = useState<string[]>([]);\n const [moveFocus, setMoveFocus] = useState<boolean>(true);\n const [focusedIndex, setFocusedIndex] = useState<number>(-1);\n\n const focus = useCallback(\n (index: number) => {\n const ref = inputRefs[index];\n ref?.current?.focus();\n },\n [inputRefs]\n );\n\n useEffect(() => {\n setInputRefs((inputRefs) => {\n const refs = Array(length)\n .fill(0)\n .map((_, i) => {\n const ref = inputRefs[i] || createRef();\n if (autoFocus && i === 0) {\n ref.current?.focus();\n }\n return ref;\n });\n return refs;\n });\n }, [length, autoFocus]);\n\n const focusNext = useCallback(\n (index: number) => {\n if (!moveFocus) return;\n const next = index + 1 < length ? index + 1 : null;\n if (next) {\n focus(next);\n }\n },\n [focus, length, moveFocus]\n );\n\n const setValue = useCallback(\n (value: string, index: number) => {\n const nextValues = [...values];\n nextValues[index] = value;\n setValues(nextValues);\n onChange?.(nextValues.join(\"\"));\n\n const isComplete =\n value !== \"\" &&\n nextValues.length === length &&\n nextValues.every((inputValue) => inputValue != null && inputValue !== \"\") &&\n index == length - 1;\n\n if (!isComplete) {\n setMoveFocus(true);\n focusNext(index);\n }\n },\n [focusNext, length, onChange, values]\n );\n\n const handleInputChange = (event: React.FormEvent<HTMLInputElement>, inputFieldIndex: number) => {\n const eventValue = event.currentTarget.value;\n const currentValue = values[inputFieldIndex];\n\n if (eventValue === \"\") {\n setValue(\"\", inputFieldIndex);\n return;\n }\n\n // Handle scenario where multiple characters are entered in a single InputField\n if (eventValue.length > 1 && inputFieldIndex < length - 1) {\n if (validate(eventValue, type)) {\n let nextValue: string[] = [];\n // In all cases, we need to ensure characters longer than the remaining fields are removed.\n if (currentValue == \"\") {\n // Case: Current input field is empty\n nextValue = eventValue.split(\"\").filter((_, j) => inputFieldIndex + j < length);\n } else if (event.currentTarget.selectionEnd === eventValue.length) {\n // Case: Current field has a value and cursor is after it\n nextValue = eventValue.split(\"\").filter((_, j) => j > 0 && inputFieldIndex + j - 1 < length);\n } else {\n // Case: Current field has a value and cursor is before it\n nextValue = eventValue\n .split(\"\")\n .filter((_, j) => j < eventValue.length - 1 && inputFieldIndex + j < length);\n }\n setValues((values) =>\n values.map((v, j) =>\n j >= inputFieldIndex && j < inputFieldIndex + nextValue.length\n ? nextValue[j - inputFieldIndex]\n : v\n )\n );\n focus(\n inputFieldIndex + nextValue.length < length ? inputFieldIndex + nextValue.length : length - 1\n );\n onChange?.(nextValue.join(\"\"));\n }\n } else {\n let nextValue = eventValue;\n if (currentValue?.length > 0) {\n if (currentValue[0] === eventValue.charAt(0)) {\n nextValue = eventValue.charAt(1);\n } else if (currentValue[0] === eventValue.charAt(1)) {\n nextValue = eventValue.charAt(0);\n }\n }\n if (validate(nextValue, type)) {\n setValue(nextValue, inputFieldIndex);\n }\n }\n };\n\n const onKeyDown = (event: React.KeyboardEvent, i: number) => {\n if (event.key === \"Backspace\") {\n if ((event.target as HTMLInputElement).value === \"\") {\n if (i > 0) {\n const newIndex = i - 1;\n setValue(\"\", newIndex);\n focus(newIndex);\n setMoveFocus(true);\n }\n } else {\n setMoveFocus(false);\n }\n } else if (event.key === \"Escape\") {\n inputRefs[i].current?.blur();\n onBlur();\n } else if (event.key === \"ArrowRight\") {\n if (i < length - 1) {\n focus(i + 1);\n }\n } else if (event.key === \"ArrowLeft\") {\n if (i > 0) {\n focus(i - 1);\n }\n }\n };\n\n const onFocus = (e: React.FocusEvent<HTMLInputElement>, i: number) => {\n setFocusedIndex(i);\n };\n\n // When moving around the InputElements using tab key, browsers automatically select\n // the value (if it exists) in the InputElement - which we want to disable. Additionally,\n // when an existing value is selected/highlighted and pasted over, there is no way to\n // clearly distinguish between the other 2 scenarios of pasting by keeping the cursor before\n // and after the existing value. Specific example: If the existing value is 5, the event\n // when highlighting and pasting '567' is the same as placing the cursor before the existing\n // value and pasting '67'. By disabling this, we eliminate one of these cases.\n // Is this a hack? Yes. Is there a better way? IDK. Does it matter? Not unless there is a\n // valid reason for users to need selecting a single InputElement within a PinInput.\n const onSelect = (e: React.SyntheticEvent<HTMLInputElement, Event>) => {\n const target = e.target as HTMLInputElement;\n setTimeout(() => {\n // https://github.com/facebook/react/issues/6483\n target.setSelectionRange(target.value.length, target.value.length);\n }, 0);\n };\n\n const onBlur = () => {\n setFocusedIndex(-1);\n };\n\n let classNames = [];\n\n if (spacing) {\n classNames.push(`spacing-${spacing}`);\n }\n\n return (\n <Element<PinInputFieldElementType> as={PinInputStyled} classNames={classNames} ref={ref}>\n {[...Array(length)].map((_, i) => (\n <InputField\n key={i}\n className=\"pin-input-field\"\n ref={inputRefs[i]}\n type={mask ? \"password\" : type === \"number\" ? \"tel\" : \"text\"}\n inputMode={type === \"number\" ? \"numeric\" : \"text\"}\n onChange={(e) => handleInputChange(e, i)}\n onKeyDown={(e) => onKeyDown(e, i)}\n onFocus={(e) => onFocus(e, i)}\n onSelect={(e) => onSelect(e)}\n onBlur={onBlur}\n placeholder={focusedIndex !== i ? `\\u2981` : undefined}\n autoComplete={otp ? \"one-time-code\" : \"off\"}\n value={values[i] || \"\"}\n autoFocus={autoFocus && i === 0}\n onCopy={(e) => pasteFromClipboard === \"disabled\" && e.preventDefault()}\n onPaste={(e) => pasteFromClipboard === \"disabled\" && e.preventDefault()}\n />\n ))}\n </Element>\n );\n }\n);\n"],"names":["validate","value","type","test","PinInputField","React","forwardRef","numberOfFields","length","onChange","mask","otp","autoFocus","pasteFromClipboard","spacing","ref","inputRefs","setInputRefs","useState","values","setValues","moveFocus","setMoveFocus","focusedIndex","setFocusedIndex","focus","useCallback","index","current","useEffect","Array","fill","map","_","i","createRef","focusNext","next","setValue","nextValues","join","every","inputValue","onBlur","classNames","push","Element","as","PinInputStyled","InputField","key","className","inputMode","e","event","inputFieldIndex","eventValue","currentTarget","currentValue","nextValue","split","filter","j","selectionEnd","v","charAt","handleInputChange","onKeyDown","target","newIndex","blur","onFocus","onSelect","setTimeout","setSelectionRange","placeholder","undefined","autoComplete","onCopy","preventDefault","onPaste"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fictoan-react",
3
- "version": "0.45.2",
3
+ "version": "0.45.4",
4
4
  "private": false,
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/es/index.js",