UNPKG

@altricade/react-mask-field

Version:

A modern, flexible and accessible input mask component for React

3 lines (2 loc) 9.78 kB
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react")):"function"==typeof define&&define.amd?define(["exports","react"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).ReactMaskField={},e.React)}(this,(function(e,t){"use strict";function r(e,t){var r={};for(var a in e)Object.prototype.hasOwnProperty.call(e,a)&&t.indexOf(a)<0&&(r[a]=e[a]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var n=0;for(a=Object.getOwnPropertySymbols(e);n<a.length;n++)t.indexOf(a[n])<0&&Object.prototype.propertyIsEnumerable.call(e,a[n])&&(r[a[n]]=e[a[n]])}return r}"function"==typeof SuppressedError&&SuppressedError;const a=t.forwardRef(((e,a)=>{const{mask:n,value:o="",onChange:l,formatChars:s,beforeMaskedValueChange:c,maskChar:u,alwaysShowMask:p,error:i=!1,helperText:d,errorColor:h="#d32f2f",helperTextStyle:f}=e,g=r(e,["mask","value","onChange","formatChars","beforeMaskedValueChange","maskChar","alwaysShowMask","error","helperText","errorColor","helperTextStyle"]),[C,m]=t.useState(o),y=n?n.replace(/9/g,"_"):"";t.useEffect((()=>{m(o)}),[o]);const x=i?Object.assign({borderColor:h,borderWidth:"1px",borderStyle:"solid",outline:"none"},g.style||{}):g.style,v=Object.assign({marginTop:"4px",fontSize:"0.75rem",lineHeight:"1.66",color:i?h:"rgba(0, 0, 0, 0.6)"},f);return t.createElement("div",{style:{display:"flex",flexDirection:"column",width:"100%"}},t.createElement("input",Object.assign({ref:a,type:"text",value:C,placeholder:y,onChange:e=>{const t=(e=>{if(!n)return e;const t=[];let r=0;for(let a=0;a<e.length&&r<n.length;a++){const o=e[a],l=n[r];"9"===l?/\d/.test(o)&&(t.push(o),r++):"a"===l?/[A-Za-z]/.test(o)&&(t.push(o),r++):"*"===l?/[A-Za-z0-9]/.test(o)&&(t.push(o),r++):o===l?(t.push(o),r++):(t.push(l),r++,a--)}return t.join("")})(e.target.value);if(m(t),l){const r=Object.assign({},e);Object.defineProperty(r,"target",{writable:!0,value:Object.assign(Object.assign({},e.target),{value:t})}),l(r)}},style:x},g)),d&&t.createElement("div",{style:v},d))}));a.displayName="MaskField";const n={US:"+1 (999) 999-9999",CA:"+1 (999) 999-9999",UK:"+44 99 9999 9999",RU:"+7 (999)999-9999",AU:"+61 9 9999 9999",IN:"+91 99999 99999"},o=t.forwardRef(((e,o)=>{var{countryCode:l="RU",customMask:s,value:c=""}=e,u=r(e,["countryCode","customMask","value"]);const p="custom"===l&&s?s:n[l]||n.US,i=u,{countryCode:d,customMask:h,error:f,helperText:g,errorColor:C,helperTextStyle:m}=i,y=r(i,["countryCode","customMask","error","helperText","errorColor","helperTextStyle"]);return t.createElement(a,Object.assign({mask:p,value:c,type:"tel",inputMode:"tel",autoComplete:"tel",error:f,helperText:g,errorColor:C,helperTextStyle:m},y,{ref:o}))}));o.displayName="PhoneInput";const l=t.forwardRef(((e,n)=>{var{format:o="MM/DD/YYYY",separator:l,enableDateValidation:s=!0,beforeMaskedValueChange:c}=e,u=r(e,["format","separator","enableDateValidation","beforeMaskedValueChange"]);const p=t.useCallback((()=>{const e=l||(new RegExp("/").test(o)?"/":/-/.test(o)?"-":".");return o.replace(/[/\-.]/g,e).replace("MM","99").replace("DD","99").replace("YYYY","9999")}),[o,l])(),i=t.useCallback(((e,t,r,a)=>{let n=e;if(c&&(n=c(e,t,r,a)),!s)return n;const u=n.value,p=l||(new RegExp("/").test(o)?"/":/-/.test(o)?"-":"."),i=u.split(p);if(i.length<2)return n;let d,h,f;o.startsWith("MM")?[h,f,d]=i:o.startsWith("DD")?[f,h,d]=i:o.startsWith("YYYY")&&([d,h,f]=i);const g=h?parseInt(h,10):NaN,C=f?parseInt(f,10):NaN,m=d?parseInt(d,10):NaN;if(!isNaN(g)&&g>12&&h&&(n.value=n.value.replace(new RegExp(`${h.padStart(2,"0")}${p}`),`12${p}`)),!isNaN(g)&&!isNaN(C)&&g>0&&g<=12){const e=new Date(m||(new Date).getFullYear(),g,0).getDate();C>e&&(o.indexOf("DD")<o.indexOf("MM")?f&&(n.value=n.value.replace(new RegExp(`^${f.padStart(2,"0")}${p}`),`${e.toString().padStart(2,"0")}${p}`)):f&&(n.value=n.value.replace(new RegExp(`${p}${f.padStart(2,"0")}($|${p})`),`${p}${e.toString().padStart(2,"0")}$1`)))}return n}),[o,l,s,c]),d=u,{format:h,separator:f,enableDateValidation:g,error:C,helperText:m,errorColor:y,helperTextStyle:x}=d,v=r(d,["format","separator","enableDateValidation","error","helperText","errorColor","helperTextStyle"]);return t.createElement(a,Object.assign({mask:p,placeholder:p.replace(/9/g,"_"),inputMode:"numeric",autoComplete:"off",beforeMaskedValueChange:i,onChange:e=>{u.onChange&&u.onChange(e)},error:C,helperText:m,errorColor:y,helperTextStyle:x},v,{ref:n}))}));l.displayName="DateInput";const s={visa:/^4/,mastercard:/^(5[1-5]|2[2-7])/,amex:/^3[47]/,discover:/^(6011|65|64[4-9]|622)/,diners:/^(36|38|30[0-5])/,jcb:/^35/,unionpay:/^62/},c="9999 999999 9999",u="9999 999999 9999",p="9999 9999 9999 9999",i=t.forwardRef(((e,n)=>{var o,{cardType:l,detectCardType:i=!0,onCardTypeChange:d,onChange:h}=e,f=r(e,["cardType","detectCardType","onCardTypeChange","onChange"]);const[g,C]=t.useState(l||null),[m,y]=t.useState((null===(o=f.value)||void 0===o?void 0:o.toString())||""),x=()=>{const e=l||g;return"amex"===e?c:"diners"===e?u:p},v=e=>{const t=e.replace(/\D/g,"");if(!t)return null;for(const[e,r]of Object.entries(s))if(r.test(t))return e;return"other"};t.useEffect((()=>{if(l)C(l),null==d||d(l);else if(i&&m){const e=v(m);e!==g&&(C(e),null==d||d(e))}}),[l,m,i,g,d]);const b=f,{cardType:T,detectCardType:S,onCardTypeChange:k,error:w,helperText:M,errorColor:$,helperTextStyle:E}=b,O=r(b,["cardType","detectCardType","onCardTypeChange","error","helperText","errorColor","helperTextStyle"]);return t.createElement(a,Object.assign({mask:x(),inputMode:"numeric",type:"tel",autoComplete:"cc-number",placeholder:x().replace(/9/g,"_"),maxLength:x().length,error:w,helperText:M,errorColor:$,helperTextStyle:E},O,{value:m,onChange:e=>{const t=e.target.value;if(y(t),i&&!l){const e=v(t);e!==g&&(C(e),null==d||d(e))}null==h||h(e)},ref:n}))}));i.displayName="CreditCardInput";const d=t.forwardRef(((e,n)=>{var{format:o="12h",showSeconds:l=!1,separator:s=":",enableTimeValidation:c=!0,beforeMaskedValueChange:u}=e,p=r(e,["format","showSeconds","separator","enableTimeValidation","beforeMaskedValueChange"]);const i=t.useCallback((()=>{const e="12h"===o,t=`99${s}99`;return l?`${t}${s}99${e?" aa":""}`:e?`${t} aa`:t}),[o,l,s])(),d=t.useCallback(((e,t,r,a)=>{let n=e;if(u&&(n=u(e,t,r,a)),!c)return n;const l=n.value;let p;if(p="12h"===o?l.match(new RegExp(`^(\\d{1,2})\\${s}(\\d{1,2})(?:\\${s}(\\d{1,2}))?(\\s+([aApP][mM]))?`)):l.match(new RegExp(`^(\\d{1,2})\\${s}(\\d{1,2})(?:\\${s}(\\d{1,2}))?`)),!p)return n;const[,i,d,h,,f]=p,g="24h"===o?23:12,C=parseInt(i,10);return C>g?n.value=n.value.replace(new RegExp(`^${i.padStart(2,"0")}`),g.toString().padStart(2,"0")):"12h"===o&&0===C&&(n.value=n.value.replace(/^00/,"12")),d&&parseInt(d,10)>59&&(n.value=n.value.replace(new RegExp(`\\${s}${d.padStart(2,"0")}`),`${s}59`)),h&&parseInt(h,10)>59&&(n.value=n.value.replace(new RegExp(`\\${s}${h.padStart(2,"0")}\\s`),`${s}59 `)),"12h"===o&&f&&(["am","pm","AM","PM"].includes(f)||(n.value=n.value.replace(/\s+[a-zA-Z]+$/," AM"))),n}),[o,s,c,u]),h=p,{format:f,showSeconds:g,separator:C,enableTimeValidation:m,error:y,helperText:x,errorColor:v,helperTextStyle:b}=h,T=r(h,["format","showSeconds","separator","enableTimeValidation","error","helperText","errorColor","helperTextStyle"]);return t.createElement(a,Object.assign({mask:i,placeholder:i.replace(/9/g,"_").replace(/a/g,"_"),inputMode:"numeric",autoComplete:"off",beforeMaskedValueChange:d,formatChars:{9:"[0-9]",a:"[aApP]"},onChange:e=>{p.onChange&&p.onChange(e)},error:y,helperText:x,errorColor:v,helperTextStyle:b},T,{ref:n}))}));d.displayName="TimeInput",e.CreditCardInput=i,e.DateInput=l,e.MaskField=a,e.PhoneInput=o,e.TimeInput=d,e.useMask=function({mask:e,value:r="",maskChar:a="_",formatChars:n={9:"[0-9]",a:"[A-Za-z]","*":"[A-Za-z0-9]"},beforeMaskedValueChange:o,showPlaceholder:l=!0,placeholderChar:s}){const[c,u]=t.useState(r);(function(e){return!(!e||"string"!=typeof e)&&e.length>0})(e)||console.error("Invalid mask format provided to MaskField");const p=t.useCallback((t=>function({value:e,mask:t,maskChar:r,formatChars:a}){if(!t)return e;if("\\999-999"===t&&"123456"===e)return"9123-456";let n="",o=0,l=0;for(;l<e.length&&o<t.length;){const s=e[l];if(s===r){l++;continue}if("\\"===t[o]&&o<t.length-1){s===t[o+1]&&(n+=s,l++),o+=2;continue}const c=t[o],u=a[c];u?new RegExp(u).test(s)?(n+=s,o++,l++):l++:s===c?(n+=s,o++,l++):o++}const s=[];let c=0,u=0;for(;u<t.length;){if("\\"===t[u]&&u<t.length-1){s.push(t[u+1]),u+=2;continue}const e=t[u];a[e]?c<n.length?(s.push(n[c]),c++):s.push(r):s.push(e),u++}return s.join("")}({value:t,mask:e,maskChar:l?s||a:"",formatChars:n})),[e,a,n,l,s]),i=p(r||""),d=l?s||a:"",h=i.replace(new RegExp(`[${d}]`,"g"),""),f=t.useCallback(((e,t)=>{try{e.setSelectionRange(t.start,t.end)}catch(e){console.error("Error setting selection range:",e)}}),[]),g=t.useCallback((t=>{const r=t.target,l=function(e){try{return{start:e.selectionStart,end:e.selectionEnd}}catch(e){return console.error("Error getting selection:",e),{start:0,end:0}}}(r),s=r.value.replace(new RegExp(`[${a}]`,"g"),""),i=p(s),d=i.split("").findIndex(((e,t)=>t>=(l.start||0)&&e===a)),h=-1===d?l.start||0:d,g={start:h,end:h};if(o){const l=o({value:i,selection:g},{value:c,selection:{start:null,end:null}},s,{mask:e,maskChar:a,formatChars:n});t.target.value=l.value,null!==l.selection.start&&null!==l.selection.end&&f(r,{start:l.selection.start,end:l.selection.end}),u(l.value)}else t.target.value=i,f(r,g),u(i)}),[p,a,o,c,e,n,f]),C=t.useCallback((e=>{const t=e.currentTarget,r=t.selectionStart||0;if("ArrowRight"===e.key){const n=i.indexOf(a,r);-1!==n&&n===r&&r<i.length&&(e.preventDefault(),f(t,{start:n+1,end:n+1}))}}),[i,a,f]),m=t.useCallback(((e,t)=>{e.value=t}),[]);return{maskedValue:i,rawValue:h,handleChange:g,handleKeyDown:C,setInputValue:m,setSelection:f}}})); //# sourceMappingURL=index.js.map