@tounsoo/input-number-mask 1.0.7 → 1.0.9

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/README.md CHANGED
@@ -112,6 +112,7 @@ To start the development server with Storybook:
112
112
  pnpm install
113
113
  pnpm storybook
114
114
  ```
115
+ <!-- Trigger release test -->
115
116
 
116
117
  ### Release Process
117
118
 
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const y=require("react"),S=e=>/\d/.test(e),d=(e,s)=>{let l="",n=0;for(let g=0;g<e.length;g++){const c=e[g];if(n>=s.length)break;if(s[n]==="d")S(c)&&(l+=c,n++);else if(s[n]===c)n++;else{let u=n;for(;u<s.length&&s[u]!=="d"&&s[u]!==c;)u++;u<s.length&&s[u]==="d"?S(c)&&(l+=c,n=u+1):u<s.length&&s[u]===c&&(n=u+1)}}return l},h=(e,s,l)=>{let n="",g=0;for(let c=0;c<s.length;c++)if(s[c]==="d"){if(g<e.length)n+=e[g++];else if(l&&c<l.length)n+=l[c];else if(!l)break}else n+=s[c];return n};function R({template:e,placeholder:s,keepPosition:l=!1}){const[n,g]=y.useState(()=>h("",e,s)),[c,u]=y.useState(null),C=y.useRef(null);y.useLayoutEffect(()=>{C.current&&c!==null&&C.current.setSelectionRange(c,c)},[c,n]),y.useLayoutEffect(()=>{const V=C.current;if(!V)return;const k=a=>{const v=a.target,f=v.selectionStart||0,w=v.selectionEnd||0,b=f!==w;if(a.key==="Backspace"){if(f===0&&!b)return;a.preventDefault();let i=f-1;if(b)if(l){let r=n;for(let t=f;t<w;t++)if(e[t]==="d"){const o=s&&t<s.length?s[t]:"_";r=r.substring(0,t)+o+r.substring(t+1)}g(r),u(f);return}else{const r=n.slice(0,f)+n.slice(w),t=d(r,e),o=h(t,e,s);g(o),u(f);return}for(;i>=0&&e[i]!=="d";)i--;if(i<0)return;if(l){const r=s&&i<s.length?s[i]:"_",t=n.substring(0,i)+r+n.substring(i+1);g(t),u(i)}else{const r=n.slice(0,i)+n.slice(i+1),t=d(r,e),o=h(t,e,s);g(o),u(i)}}else if(a.key==="Delete"){if(a.preventDefault(),b)if(l){let r=n;for(let t=f;t<w;t++)if(e[t]==="d"){const o=s&&t<s.length?s[t]:"_";r=r.substring(0,t)+o+r.substring(t+1)}g(r),u(f);return}else{const r=n.slice(0,f)+n.slice(w),t=d(r,e),o=h(t,e,s);g(o),u(f);return}let i=f;for(;i<e.length&&e[i]!=="d";)i++;if(i>=n.length)return;if(l){const r=s&&i<s.length?s[i]:"_",t=n.substring(0,i)+r+n.substring(i+1);g(t),u(f)}else{const r=n.slice(0,i)+n.slice(i+1),t=d(r,e),o=h(t,e,s);g(o),u(f)}}},I=a=>{const v=a.target,f=v.value,w=v.selectionStart||0,b=()=>{const i=f.slice(0,w),r=d(i,e).length,t=d(f,e),o=h(t,e,s);g(o);let x=0,D=0;for(let L=0;L<o.length&&!(x>=r);L++)S(o[L])&&e[L]==="d"&&x++,D++;for(;D<o.length&&e[D]!=="d";)D++;u(D)};if(l&&f.length>n.length){const i=w-1,r=f[i];if(!S(r)){b();return}let t=i;for(;t<e.length&&e[t]!=="d";)t++;if(t>=e.length){b();return}const o=n.substring(0,t)+r+n.substring(t+1);g(o),u(t+1);return}b()};return V.addEventListener("keydown",k),V.addEventListener("input",I),()=>{V.removeEventListener("keydown",k),V.removeEventListener("input",I)}},[n,e,s,l]);const E=d(n,e);return{value:n,displayValue:n,rawValue:E,ref:C}}exports.useInputNumberMask=R;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const k=require("react"),S=e=>/\d/.test(e),E=(e,t)=>{let f="",n=0;for(let g=0;g<e.length;g++){const o=e[g];if(n>=t.length)break;if(t[n]==="d")S(o)&&(f+=o,n++);else if(t[n]===o)n++;else{let s=n;for(;s<t.length&&t[s]!=="d"&&t[s]!==o;)s++;s<t.length&&t[s]==="d"?S(o)&&(f+=o,n=s+1):s<t.length&&t[s]===o&&(n=s+1)}}return f},V=(e,t,f)=>{let n="",g=0;for(let o=0;o<t.length;o++)if(t[o]==="d"){if(g<e.length)n+=e[g++];else if(f&&o<f.length)n+=f[o];else if(!f)break}else n+=t[o];return n},K=(e,t,f,n,g,o)=>{let s=e,v=n;if(o===""){for(let d=n;d<g;d++)if(t[d]==="d"){const c=f&&d<f.length?f[d]:"_";s=s.substring(0,d)+c+s.substring(d+1)}return{value:s,cursor:n}}if(n!==g){let d=n;if(S(o)&&e[n]===o)for(d=n+1;d<g&&t[d]!=="d";)d++;for(let b=d;b<g;b++)if(t[b]==="d"){const x=f&&b<f.length?f[b]:"_";s=s.substring(0,b)+x+s.substring(b+1)}let c=d;for(;c<t.length&&t[c]!=="d";)c++;return c<t.length&&S(o)?(s=s.substring(0,c)+o+s.substring(c+1),v=c+1):v=n,{value:s,cursor:v}}let a=n;for(;a<t.length&&t[a]!=="d";)a++;return a<t.length&&S(o)?(s=s.substring(0,a)+o+s.substring(a+1),v=a+1):v=n,{value:s,cursor:v}};function N({template:e,placeholder:t,keepPosition:f=!1}){const[n,g]=k.useState(()=>V("",e,t)),[o,s]=k.useState(null),v=k.useRef(null),a=k.useRef({start:0,end:0});k.useLayoutEffect(()=>{v.current&&o!==null&&v.current.setSelectionRange(o,o)},[o,n]),k.useLayoutEffect(()=>{const c=v.current;if(!c)return;const b=()=>{c&&(a.current={start:c.selectionStart||0,end:c.selectionEnd||0})},x=C=>{b();const D=C.target,l=D.selectionStart||0,L=D.selectionEnd||0,I=l!==L;if(C.key==="Backspace"){if(l===0&&!I)return;C.preventDefault();let r=l-1;if(I)if(f){let u=n;for(let i=l;i<L;i++)if(e[i]==="d"){const w=t&&i<t.length?t[i]:"_";u=u.substring(0,i)+w+u.substring(i+1)}g(u),s(l);return}else{const u=n.slice(0,l)+n.slice(L),i=E(u,e),w=V(i,e,t);g(w),s(l);return}for(;r>=0&&e[r]!=="d";)r--;if(r<0)return;if(f){const u=t&&r<t.length?t[r]:"_",i=n.substring(0,r)+u+n.substring(r+1);g(i),s(r)}else{const u=n.slice(0,r)+n.slice(r+1),i=E(u,e),w=V(i,e,t);g(w),s(r)}}else if(C.key==="Delete"){if(C.preventDefault(),I)if(f){let u=n;for(let i=l;i<L;i++)if(e[i]==="d"){const w=t&&i<t.length?t[i]:"_";u=u.substring(0,i)+w+u.substring(i+1)}g(u),s(l);return}else{const u=n.slice(0,l)+n.slice(L),i=E(u,e),w=V(i,e,t);g(w),s(l);return}let r=l;for(;r<e.length&&e[r]!=="d";)r++;if(r>=n.length)return;if(f){const u=t&&r<t.length?t[r]:"_",i=n.substring(0,r)+u+n.substring(r+1);g(i),s(l)}else{const u=n.slice(0,r)+n.slice(r+1),i=E(u,e),w=V(i,e,t);g(w),s(l)}}},T=C=>{const D=C.target,l=D.value,L=D.selectionStart||0,I=()=>{const r=l.slice(0,L),u=E(r,e).length,i=E(l,e),w=V(i,e,t);g(w);let R=0,h=0;for(let y=0;y<w.length&&!(R>=u);y++)S(w[y])&&e[y]==="d"&&R++,h++;for(;h<w.length&&e[h]!=="d";)h++;s(h)};if(f){const r=a.current.start,u=a.current.end,i=r!==u,w=u-r;if(l.length-n.length+w===1&&L>0){const h=L-1,y=l[h];if(S(y)){const _=i?r:h,B=i?u:h;if(_<e.length){const M=K(n,e,t,_,B,y);g(M.value),s(M.cursor);return}}}}I()};return c.addEventListener("keydown",x),c.addEventListener("input",T),c.addEventListener("select",b),c.addEventListener("click",b),c.addEventListener("keyup",b),()=>{c.removeEventListener("keydown",x),c.removeEventListener("input",T),c.removeEventListener("select",b),c.removeEventListener("click",b),c.removeEventListener("keyup",b)}},[n,e,t,f]);const d=E(n,e);return{value:n,displayValue:n,rawValue:d,ref:v}}exports.useInputNumberMask=N;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/utils/maskUtils.ts","../src/useInputNumberMask.ts"],"sourcesContent":["export const isDigit = (char: string) => /\\d/.test(char);\n\nexport const cleanInput = (input: string, template: string): string => {\n let extracted = '';\n let t = 0;\n\n for (let i = 0; i < input.length; i++) {\n const char = input[i];\n\n if (t >= template.length) {\n break;\n }\n\n if (template[t] === 'd') {\n if (isDigit(char)) {\n extracted += char;\n t++;\n } else {\n // Ignore placeholders or garbage\n }\n } else if (template[t] === char) {\n t++;\n } else {\n let nextT = t;\n while (nextT < template.length && template[nextT] !== 'd' && template[nextT] !== char) {\n nextT++;\n }\n if (nextT < template.length && template[nextT] === 'd') {\n if (isDigit(char)) {\n extracted += char;\n t = nextT + 1;\n }\n } else if (nextT < template.length && template[nextT] === char) {\n t = nextT + 1;\n }\n }\n }\n return extracted;\n};\n\nexport const formatWithMask = (digits: string, template: string, placeholder?: string): string => {\n let res = '';\n let dIdx = 0;\n\n for (let i = 0; i < template.length; i++) {\n const isSlot = template[i] === 'd';\n\n if (isSlot) {\n if (dIdx < digits.length) {\n res += digits[dIdx++];\n } else {\n // Empty slot\n if (placeholder && i < placeholder.length) {\n res += placeholder[i];\n } else {\n if (!placeholder) {\n break;\n }\n }\n }\n } else {\n res += template[i];\n }\n }\n return res;\n};\n","import { useRef, useState, useLayoutEffect } from 'react';\nimport { cleanInput, formatWithMask, isDigit } from './utils/maskUtils';\n\nexport interface UseInputNumberMaskProps {\n /**\n * The mask template. 'd' represents a digit slot.\n * All other characters are treated as literals.\n * @example \"+1 (ddd) ddd-dddd\" for US phone numbers\n */\n template: string;\n\n /**\n * Optional full-length placeholder shown in empty slots.\n * Should match the template length.\n * @example \"mm/dd/yyyy\" for a date mask\n */\n placeholder?: string;\n\n /**\n * If true, deletion replaces with placeholder char\n * instead of shifting subsequent digits left.\n * @default false\n */\n keepPosition?: boolean;\n}\n\nexport interface UseInputNumberMaskReturn {\n /** \n * The raw value with formatting applied \n * @example \"+1 (234) 567-8900\" \n */\n value: string;\n /** \n * Deprecated: alias for value. The value to display in the input. \n * @example \"+1 (234) 567-8900\" \n */\n displayValue: string;\n /** \n * The unmasked digits only \n * @example \"1234567890\" \n */\n rawValue: string;\n /** \n * Ref to be attached to the HTML input element \n */\n ref: React.RefObject<HTMLInputElement | null>;\n}\n\nexport function useInputNumberMask({\n template,\n placeholder,\n keepPosition = false,\n}: UseInputNumberMaskProps): UseInputNumberMaskReturn {\n\n const [value, setValue] = useState(() => formatWithMask('', template, placeholder));\n const [cursor, setCursor] = useState<number | null>(null);\n const ref = useRef<HTMLInputElement>(null);\n\n useLayoutEffect(() => {\n if (ref.current && cursor !== null) {\n ref.current.setSelectionRange(cursor, cursor);\n }\n }, [cursor, value]);\n\n // Ref-based Event Handling\n useLayoutEffect(() => {\n const input = ref.current;\n if (!input) return;\n\n const handleKeyDown = (e: globalThis.KeyboardEvent) => {\n const el = e.target as HTMLInputElement;\n const start = el.selectionStart || 0;\n const end = el.selectionEnd || 0;\n const isSelection = start !== end;\n\n if (e.key === 'Backspace') {\n if (start === 0 && !isSelection) return;\n // We prevent default to handle the state update manually\n e.preventDefault();\n\n let deleteIndex = start - 1;\n\n if (isSelection) {\n if (keepPosition) {\n // Replace range with placeholders\n let newVal = value;\n for (let i = start; i < end; i++) {\n if (template[i] === 'd') {\n const pChar = placeholder && i < placeholder.length ? placeholder[i] : '_';\n newVal = newVal.substring(0, i) + pChar + newVal.substring(i + 1);\n }\n }\n setValue(newVal);\n setCursor(start);\n return;\n } else {\n // Standard delete range (shift)\n const newValRaw = value.slice(0, start) + value.slice(end);\n const newDigits = cleanInput(newValRaw, template);\n const formatted = formatWithMask(newDigits, template, placeholder);\n setValue(formatted);\n setCursor(start);\n return;\n }\n }\n\n // Single char backspace\n while (deleteIndex >= 0) {\n const isTemplateLiteral = template[deleteIndex] !== 'd';\n if (isTemplateLiteral) {\n deleteIndex--;\n } else {\n break;\n }\n }\n\n if (deleteIndex < 0) return; // Nothing to delete\n\n if (keepPosition) {\n const pChar = placeholder && deleteIndex < placeholder.length ? placeholder[deleteIndex] : '_';\n const newVal = value.substring(0, deleteIndex) + pChar + value.substring(deleteIndex + 1);\n setValue(newVal);\n setCursor(deleteIndex);\n } else {\n // Shift behavior\n const newValRaw = value.slice(0, deleteIndex) + value.slice(deleteIndex + 1);\n const newDigits = cleanInput(newValRaw, template);\n const formatted = formatWithMask(newDigits, template, placeholder);\n setValue(formatted);\n setCursor(deleteIndex);\n }\n } else if (e.key === 'Delete') {\n e.preventDefault();\n // Delete forward\n if (isSelection) {\n if (keepPosition) {\n let newVal = value;\n for (let i = start; i < end; i++) {\n if (template[i] === 'd') {\n const pChar = placeholder && i < placeholder.length ? placeholder[i] : '_';\n newVal = newVal.substring(0, i) + pChar + newVal.substring(i + 1);\n }\n }\n setValue(newVal);\n setCursor(start);\n return;\n } else {\n const newValRaw = value.slice(0, start) + value.slice(end);\n const newDigits = cleanInput(newValRaw, template);\n const formatted = formatWithMask(newDigits, template, placeholder);\n setValue(formatted);\n setCursor(start);\n return;\n }\n }\n\n // Single char delete\n let deleteIndex = start;\n while (deleteIndex < template.length) {\n const isTemplateLiteral = template[deleteIndex] !== 'd';\n if (isTemplateLiteral) {\n deleteIndex++;\n } else {\n break;\n }\n }\n\n if (deleteIndex >= value.length) return;\n\n if (keepPosition) {\n const pChar = placeholder && deleteIndex < placeholder.length ? placeholder[deleteIndex] : '_';\n const newVal = value.substring(0, deleteIndex) + pChar + value.substring(deleteIndex + 1);\n setValue(newVal);\n setCursor(start);\n } else {\n // Shift behavior\n const newValRaw = value.slice(0, deleteIndex) + value.slice(deleteIndex + 1);\n const newDigits = cleanInput(newValRaw, template);\n const formatted = formatWithMask(newDigits, template, placeholder);\n setValue(formatted);\n setCursor(start);\n }\n }\n };\n\n const handleInput = (e: Event) => {\n // We cast to InputEvent or basic Event. target is HTMLInputElement.\n const target = e.target as HTMLInputElement;\n const inputVal = target.value;\n const rawCursor = target.selectionStart || 0;\n\n // Standard behavior logic\n const standardChange = () => {\n const beforeCursor = inputVal.slice(0, rawCursor);\n const digitsBeforeCursor = cleanInput(beforeCursor, template).length;\n\n const newDigits = cleanInput(inputVal, template);\n const newFormatted = formatWithMask(newDigits, template, placeholder);\n\n setValue(newFormatted);\n\n let currentDigits = 0;\n let newCursor = 0;\n for (let i = 0; i < newFormatted.length; i++) {\n if (currentDigits >= digitsBeforeCursor) {\n break;\n }\n if (isDigit(newFormatted[i]) && template[i] === 'd') {\n currentDigits++;\n }\n newCursor++;\n }\n\n while (newCursor < newFormatted.length && template[newCursor] !== 'd') {\n newCursor++;\n }\n\n setCursor(newCursor);\n };\n\n if (keepPosition) {\n // Measure diff against current state `value` (mapped in closure)\n // NOTE: `value` in this closure is stale if not included in dependency array.\n // We need strict dependency on `value`.\n if (inputVal.length > value.length) {\n const insertIndex = rawCursor - 1;\n const char = inputVal[insertIndex];\n\n if (!isDigit(char)) {\n standardChange();\n return;\n }\n\n let targetIndex = insertIndex;\n while (targetIndex < template.length) {\n if (template[targetIndex] === 'd') {\n break;\n }\n targetIndex++;\n }\n\n if (targetIndex >= template.length) {\n standardChange();\n return;\n }\n\n const newValue = value.substring(0, targetIndex) + char + value.substring(targetIndex + 1);\n\n setValue(newValue);\n setCursor(targetIndex + 1);\n return;\n }\n }\n\n standardChange();\n };\n\n input.addEventListener('keydown', handleKeyDown);\n input.addEventListener('input', handleInput);\n\n return () => {\n input.removeEventListener('keydown', handleKeyDown);\n input.removeEventListener('input', handleInput);\n };\n }, [value, template, placeholder, keepPosition]); // Re-bind when value changes to have fresh closure\n\n const rawValue = cleanInput(value, template);\n\n return {\n value,\n displayValue: value,\n rawValue,\n ref\n };\n}\n"],"names":["isDigit","char","cleanInput","input","template","extracted","t","i","nextT","formatWithMask","digits","placeholder","res","dIdx","useInputNumberMask","keepPosition","value","setValue","useState","cursor","setCursor","ref","useRef","useLayoutEffect","handleKeyDown","e","el","start","end","isSelection","deleteIndex","newVal","pChar","newValRaw","newDigits","formatted","handleInput","target","inputVal","rawCursor","standardChange","beforeCursor","digitsBeforeCursor","newFormatted","currentDigits","newCursor","insertIndex","targetIndex","newValue","rawValue"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/utils/maskUtils.ts","../src/useInputNumberMask.ts"],"sourcesContent":["export const isDigit = (char: string) => /\\d/.test(char);\n\nexport const cleanInput = (input: string, template: string): string => {\n let extracted = '';\n let t = 0;\n\n for (let i = 0; i < input.length; i++) {\n const char = input[i];\n\n if (t >= template.length) {\n break;\n }\n\n if (template[t] === 'd') {\n if (isDigit(char)) {\n extracted += char;\n t++;\n } else {\n // Ignore placeholders or garbage\n }\n } else if (template[t] === char) {\n t++;\n } else {\n let nextT = t;\n while (nextT < template.length && template[nextT] !== 'd' && template[nextT] !== char) {\n nextT++;\n }\n if (nextT < template.length && template[nextT] === 'd') {\n if (isDigit(char)) {\n extracted += char;\n t = nextT + 1;\n }\n } else if (nextT < template.length && template[nextT] === char) {\n t = nextT + 1;\n }\n }\n }\n return extracted;\n};\n\nexport const formatWithMask = (digits: string, template: string, placeholder?: string): string => {\n let res = '';\n let dIdx = 0;\n\n for (let i = 0; i < template.length; i++) {\n const isSlot = template[i] === 'd';\n\n if (isSlot) {\n if (dIdx < digits.length) {\n res += digits[dIdx++];\n } else {\n // Empty slot\n if (placeholder && i < placeholder.length) {\n res += placeholder[i];\n } else {\n if (!placeholder) {\n break;\n }\n }\n }\n } else {\n res += template[i];\n }\n }\n return res;\n};\n\nexport const applyKeepPositionChange = (\n value: string,\n template: string,\n placeholder: string | undefined,\n start: number,\n end: number,\n char: string\n): { value: string; cursor: number } => {\n let newValue = value;\n let newCursor = start;\n\n // Deletion\n if (char === '') {\n for (let i = start; i < end; i++) {\n if (template[i] === 'd') {\n const pChar = placeholder && i < placeholder.length ? placeholder[i] : '_';\n newValue = newValue.substring(0, i) + pChar + newValue.substring(i + 1);\n }\n }\n return { value: newValue, cursor: start };\n }\n\n // Replacement (Selection)\n if (start !== end) {\n // 1. Replace the first digit slot at start (if it's a digit slot)\n // Actually, if we selected a range, we typically want to replace the *entire* range content\n // with the new char *at the beginning*, and clear the rest.\n // But we must respect the template chars.\n\n // Strategy:\n // - Clear the entire range first (replace with placeholders)\n // - Insert the char at the first available digit slot within the range (or shortly after if range starts on literal?)\n // Wait, standard input behavior replacing a selection \"12/34\" with \"5\":\n // \"12/5...\"\n // So effectively: delete range, then insert char.\n\n // Let's implement it as:\n // 1. Check if first char of selection matches the typed char\n // If so, skip it and insert at the next digit slot\n let insertStart = start;\n if (isDigit(char) && value[start] === char) {\n // The first position already has the same digit, so skip it\n insertStart = start + 1;\n // Skip any literals to find the next digit slot\n while (insertStart < end && template[insertStart] !== 'd') {\n insertStart++;\n }\n }\n\n // 2. Clear the range from insertStart to end (fill with placeholders)\n for (let i = insertStart; i < end; i++) {\n if (template[i] === 'd') {\n const pChar = placeholder && i < placeholder.length ? placeholder[i] : '_';\n newValue = newValue.substring(0, i) + pChar + newValue.substring(i + 1);\n }\n }\n\n // 3. Insert the char at insertStart (finding closest digit slot)\n let targetIndex = insertStart;\n while (targetIndex < template.length) {\n if (template[targetIndex] === 'd') {\n break;\n }\n targetIndex++;\n }\n\n if (targetIndex < template.length && isDigit(char)) {\n newValue = newValue.substring(0, targetIndex) + char + newValue.substring(targetIndex + 1);\n newCursor = targetIndex + 1;\n } else {\n newCursor = start;\n }\n\n return { value: newValue, cursor: newCursor };\n }\n\n // Insertion (No selection)\n // Find next digit slot\n let targetIndex = start;\n while (targetIndex < template.length) {\n if (template[targetIndex] === 'd') {\n break;\n }\n targetIndex++;\n }\n\n if (targetIndex < template.length && isDigit(char)) {\n newValue = newValue.substring(0, targetIndex) + char + newValue.substring(targetIndex + 1);\n newCursor = targetIndex + 1;\n } else {\n newCursor = start; // No change\n }\n\n return { value: newValue, cursor: newCursor };\n};\n","import { useRef, useState, useLayoutEffect } from 'react';\nimport { cleanInput, formatWithMask, isDigit, applyKeepPositionChange } from './utils/maskUtils';\n\nexport interface UseInputNumberMaskProps {\n /**\n * The mask template. 'd' represents a digit slot.\n * All other characters are treated as literals.\n * @example \"+1 (ddd) ddd-dddd\" for US phone numbers\n */\n template: string;\n\n /**\n * Optional full-length placeholder shown in empty slots.\n * Should match the template length.\n * @example \"mm/dd/yyyy\" for a date mask\n */\n placeholder?: string;\n\n /**\n * If true, deletion replaces with placeholder char\n * instead of shifting subsequent digits left.\n * @default false\n */\n keepPosition?: boolean;\n}\n\nexport interface UseInputNumberMaskReturn {\n /** \n * The raw value with formatting applied \n * @example \"+1 (234) 567-8900\" \n */\n value: string;\n /** \n * Deprecated: alias for value. The value to display in the input. \n * @example \"+1 (234) 567-8900\" \n */\n displayValue: string;\n /** \n * The unmasked digits only \n * @example \"1234567890\" \n */\n rawValue: string;\n /** \n * Ref to be attached to the HTML input element \n */\n ref: React.RefObject<HTMLInputElement | null>;\n}\n\nexport function useInputNumberMask({\n template,\n placeholder,\n keepPosition = false,\n}: UseInputNumberMaskProps): UseInputNumberMaskReturn {\n\n const [value, setValue] = useState(() => formatWithMask('', template, placeholder));\n const [cursor, setCursor] = useState<number | null>(null);\n const ref = useRef<HTMLInputElement>(null);\n const selectionRef = useRef<{ start: number; end: number }>({ start: 0, end: 0 });\n\n useLayoutEffect(() => {\n if (ref.current && cursor !== null) {\n ref.current.setSelectionRange(cursor, cursor);\n }\n }, [cursor, value]);\n\n // Ref-based Event Handling\n useLayoutEffect(() => {\n const input = ref.current;\n if (!input) return;\n\n const updateSelection = () => {\n if (input) {\n selectionRef.current = {\n start: input.selectionStart || 0,\n end: input.selectionEnd || 0,\n };\n }\n };\n\n const handleKeyDown = (e: globalThis.KeyboardEvent) => {\n updateSelection();\n const el = e.target as HTMLInputElement;\n const start = el.selectionStart || 0;\n const end = el.selectionEnd || 0;\n const isSelection = start !== end;\n\n if (e.key === 'Backspace') {\n if (start === 0 && !isSelection) return;\n // We prevent default to handle the state update manually\n e.preventDefault();\n\n let deleteIndex = start - 1;\n\n if (isSelection) {\n if (keepPosition) {\n // Replace range with placeholders\n let newVal = value;\n for (let i = start; i < end; i++) {\n if (template[i] === 'd') {\n const pChar = placeholder && i < placeholder.length ? placeholder[i] : '_';\n newVal = newVal.substring(0, i) + pChar + newVal.substring(i + 1);\n }\n }\n setValue(newVal);\n setCursor(start);\n return;\n } else {\n // Standard delete range (shift)\n const newValRaw = value.slice(0, start) + value.slice(end);\n const newDigits = cleanInput(newValRaw, template);\n const formatted = formatWithMask(newDigits, template, placeholder);\n setValue(formatted);\n setCursor(start);\n return;\n }\n }\n\n // Single char backspace\n while (deleteIndex >= 0) {\n const isTemplateLiteral = template[deleteIndex] !== 'd';\n if (isTemplateLiteral) {\n deleteIndex--;\n } else {\n break;\n }\n }\n\n if (deleteIndex < 0) return; // Nothing to delete\n\n if (keepPosition) {\n const pChar = placeholder && deleteIndex < placeholder.length ? placeholder[deleteIndex] : '_';\n const newVal = value.substring(0, deleteIndex) + pChar + value.substring(deleteIndex + 1);\n setValue(newVal);\n setCursor(deleteIndex);\n } else {\n // Shift behavior\n const newValRaw = value.slice(0, deleteIndex) + value.slice(deleteIndex + 1);\n const newDigits = cleanInput(newValRaw, template);\n const formatted = formatWithMask(newDigits, template, placeholder);\n setValue(formatted);\n setCursor(deleteIndex);\n }\n } else if (e.key === 'Delete') {\n e.preventDefault();\n // Delete forward\n if (isSelection) {\n if (keepPosition) {\n let newVal = value;\n for (let i = start; i < end; i++) {\n if (template[i] === 'd') {\n const pChar = placeholder && i < placeholder.length ? placeholder[i] : '_';\n newVal = newVal.substring(0, i) + pChar + newVal.substring(i + 1);\n }\n }\n setValue(newVal);\n setCursor(start);\n return;\n } else {\n const newValRaw = value.slice(0, start) + value.slice(end);\n const newDigits = cleanInput(newValRaw, template);\n const formatted = formatWithMask(newDigits, template, placeholder);\n setValue(formatted);\n setCursor(start);\n return;\n }\n }\n\n // Single char delete\n let deleteIndex = start;\n while (deleteIndex < template.length) {\n const isTemplateLiteral = template[deleteIndex] !== 'd';\n if (isTemplateLiteral) {\n deleteIndex++;\n } else {\n break;\n }\n }\n\n if (deleteIndex >= value.length) return;\n\n if (keepPosition) {\n const pChar = placeholder && deleteIndex < placeholder.length ? placeholder[deleteIndex] : '_';\n const newVal = value.substring(0, deleteIndex) + pChar + value.substring(deleteIndex + 1);\n setValue(newVal);\n setCursor(start);\n } else {\n // Shift behavior\n const newValRaw = value.slice(0, deleteIndex) + value.slice(deleteIndex + 1);\n const newDigits = cleanInput(newValRaw, template);\n const formatted = formatWithMask(newDigits, template, placeholder);\n setValue(formatted);\n setCursor(start);\n }\n }\n };\n\n const handleInput = (e: Event) => {\n // We cast to InputEvent or basic Event. target is HTMLInputElement.\n const target = e.target as HTMLInputElement;\n const inputVal = target.value;\n const rawCursor = target.selectionStart || 0;\n\n // Standard behavior logic\n const standardChange = () => {\n const beforeCursor = inputVal.slice(0, rawCursor);\n const digitsBeforeCursor = cleanInput(beforeCursor, template).length;\n\n const newDigits = cleanInput(inputVal, template);\n const newFormatted = formatWithMask(newDigits, template, placeholder);\n\n setValue(newFormatted);\n\n let currentDigits = 0;\n let newCursor = 0;\n for (let i = 0; i < newFormatted.length; i++) {\n if (currentDigits >= digitsBeforeCursor) {\n break;\n }\n if (isDigit(newFormatted[i]) && template[i] === 'd') {\n currentDigits++;\n }\n newCursor++;\n }\n\n while (newCursor < newFormatted.length && template[newCursor] !== 'd') {\n newCursor++;\n }\n\n setCursor(newCursor);\n };\n\n if (keepPosition) {\n const prevStart = selectionRef.current.start;\n const prevEnd = selectionRef.current.end;\n const wasSelection = prevStart !== prevEnd;\n const selectionLength = prevEnd - prevStart;\n const typedChars = inputVal.length - value.length + selectionLength;\n\n // Handle single character input (typing one digit)\n if (typedChars === 1 && rawCursor > 0) {\n const insertIndex = rawCursor - 1;\n const char = inputVal[insertIndex];\n\n if (isDigit(char)) {\n // For selection replacement, use the selection range\n // For cursor insertion (no selection), use the cursor position\n const startPos = wasSelection ? prevStart : insertIndex;\n const endPos = wasSelection ? prevEnd : insertIndex;\n\n // Only apply keepPosition if within template bounds\n // If cursor is at/beyond template length (e.g., typing at end),\n // fall through to standardChange() for normal fill behavior\n if (startPos < template.length) {\n const result = applyKeepPositionChange(\n value,\n template,\n placeholder,\n startPos,\n endPos,\n char\n );\n\n setValue(result.value);\n setCursor(result.cursor);\n return;\n }\n }\n }\n }\n\n standardChange();\n };\n\n input.addEventListener('keydown', handleKeyDown);\n input.addEventListener('input', handleInput);\n input.addEventListener('select', updateSelection);\n input.addEventListener('click', updateSelection);\n input.addEventListener('keyup', updateSelection);\n\n return () => {\n input.removeEventListener('keydown', handleKeyDown);\n input.removeEventListener('input', handleInput);\n input.removeEventListener('select', updateSelection);\n input.removeEventListener('click', updateSelection);\n input.removeEventListener('keyup', updateSelection);\n };\n }, [value, template, placeholder, keepPosition]); // Re-bind when value changes to have fresh closure\n\n const rawValue = cleanInput(value, template);\n\n return {\n value,\n displayValue: value,\n rawValue,\n ref\n };\n}\n"],"names":["isDigit","char","cleanInput","input","template","extracted","t","i","nextT","formatWithMask","digits","placeholder","res","dIdx","applyKeepPositionChange","value","start","end","newValue","newCursor","pChar","insertStart","targetIndex","useInputNumberMask","keepPosition","setValue","useState","cursor","setCursor","ref","useRef","selectionRef","useLayoutEffect","updateSelection","handleKeyDown","e","el","isSelection","deleteIndex","newVal","newValRaw","newDigits","formatted","handleInput","target","inputVal","rawCursor","standardChange","beforeCursor","digitsBeforeCursor","newFormatted","currentDigits","prevStart","prevEnd","wasSelection","selectionLength","insertIndex","startPos","endPos","result","rawValue"],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -1,149 +1,188 @@
1
- import { useState as S, useRef as T, useLayoutEffect as E } from "react";
2
- const k = (e) => /\d/.test(e), d = (e, t) => {
3
- let l = "", n = 0;
1
+ import { useState as B, useRef as K, useLayoutEffect as M } from "react";
2
+ const V = (e) => /\d/.test(e), k = (e, s) => {
3
+ let f = "", n = 0;
4
4
  for (let g = 0; g < e.length; g++) {
5
- const f = e[g];
6
- if (n >= t.length)
5
+ const o = e[g];
6
+ if (n >= s.length)
7
7
  break;
8
- if (t[n] === "d")
9
- k(f) && (l += f, n++);
10
- else if (t[n] === f)
8
+ if (s[n] === "d")
9
+ V(o) && (f += o, n++);
10
+ else if (s[n] === o)
11
11
  n++;
12
12
  else {
13
- let u = n;
14
- for (; u < t.length && t[u] !== "d" && t[u] !== f; )
15
- u++;
16
- u < t.length && t[u] === "d" ? k(f) && (l += f, n = u + 1) : u < t.length && t[u] === f && (n = u + 1);
13
+ let t = n;
14
+ for (; t < s.length && s[t] !== "d" && s[t] !== o; )
15
+ t++;
16
+ t < s.length && s[t] === "d" ? V(o) && (f += o, n = t + 1) : t < s.length && s[t] === o && (n = t + 1);
17
17
  }
18
18
  }
19
- return l;
20
- }, h = (e, t, l) => {
19
+ return f;
20
+ }, y = (e, s, f) => {
21
21
  let n = "", g = 0;
22
- for (let f = 0; f < t.length; f++)
23
- if (t[f] === "d") {
22
+ for (let o = 0; o < s.length; o++)
23
+ if (s[o] === "d") {
24
24
  if (g < e.length)
25
25
  n += e[g++];
26
- else if (l && f < l.length)
27
- n += l[f];
28
- else if (!l)
26
+ else if (f && o < f.length)
27
+ n += f[o];
28
+ else if (!f)
29
29
  break;
30
30
  } else
31
- n += t[f];
31
+ n += s[o];
32
32
  return n;
33
+ }, N = (e, s, f, n, g, o) => {
34
+ let t = e, v = n;
35
+ if (o === "") {
36
+ for (let d = n; d < g; d++)
37
+ if (s[d] === "d") {
38
+ const c = f && d < f.length ? f[d] : "_";
39
+ t = t.substring(0, d) + c + t.substring(d + 1);
40
+ }
41
+ return { value: t, cursor: n };
42
+ }
43
+ if (n !== g) {
44
+ let d = n;
45
+ if (V(o) && e[n] === o)
46
+ for (d = n + 1; d < g && s[d] !== "d"; )
47
+ d++;
48
+ for (let b = d; b < g; b++)
49
+ if (s[b] === "d") {
50
+ const x = f && b < f.length ? f[b] : "_";
51
+ t = t.substring(0, b) + x + t.substring(b + 1);
52
+ }
53
+ let c = d;
54
+ for (; c < s.length && s[c] !== "d"; )
55
+ c++;
56
+ return c < s.length && V(o) ? (t = t.substring(0, c) + o + t.substring(c + 1), v = c + 1) : v = n, { value: t, cursor: v };
57
+ }
58
+ let h = n;
59
+ for (; h < s.length && s[h] !== "d"; )
60
+ h++;
61
+ return h < s.length && V(o) ? (t = t.substring(0, h) + o + t.substring(h + 1), v = h + 1) : v = n, { value: t, cursor: v };
33
62
  };
34
- function B({
63
+ function j({
35
64
  template: e,
36
- placeholder: t,
37
- keepPosition: l = !1
65
+ placeholder: s,
66
+ keepPosition: f = !1
38
67
  }) {
39
- const [n, g] = S(() => h("", e, t)), [f, u] = S(null), C = T(null);
40
- E(() => {
41
- C.current && f !== null && C.current.setSelectionRange(f, f);
42
- }, [f, n]), E(() => {
43
- const V = C.current;
44
- if (!V) return;
45
- const x = (a) => {
46
- const D = a.target, c = D.selectionStart || 0, w = D.selectionEnd || 0, b = c !== w;
68
+ const [n, g] = B(() => y("", e, s)), [o, t] = B(null), v = K(null), h = K({ start: 0, end: 0 });
69
+ M(() => {
70
+ v.current && o !== null && v.current.setSelectionRange(o, o);
71
+ }, [o, n]), M(() => {
72
+ const c = v.current;
73
+ if (!c) return;
74
+ const b = () => {
75
+ c && (h.current = {
76
+ start: c.selectionStart || 0,
77
+ end: c.selectionEnd || 0
78
+ });
79
+ }, x = (a) => {
80
+ b();
81
+ const S = a.target, l = S.selectionStart || 0, C = S.selectionEnd || 0, D = l !== C;
47
82
  if (a.key === "Backspace") {
48
- if (c === 0 && !b) return;
83
+ if (l === 0 && !D) return;
49
84
  a.preventDefault();
50
- let i = c - 1;
51
- if (b)
52
- if (l) {
53
- let r = n;
54
- for (let s = c; s < w; s++)
55
- if (e[s] === "d") {
56
- const o = t && s < t.length ? t[s] : "_";
57
- r = r.substring(0, s) + o + r.substring(s + 1);
85
+ let r = l - 1;
86
+ if (D)
87
+ if (f) {
88
+ let u = n;
89
+ for (let i = l; i < C; i++)
90
+ if (e[i] === "d") {
91
+ const w = s && i < s.length ? s[i] : "_";
92
+ u = u.substring(0, i) + w + u.substring(i + 1);
58
93
  }
59
- g(r), u(c);
94
+ g(u), t(l);
60
95
  return;
61
96
  } else {
62
- const r = n.slice(0, c) + n.slice(w), s = d(r, e), o = h(s, e, t);
63
- g(o), u(c);
97
+ const u = n.slice(0, l) + n.slice(C), i = k(u, e), w = y(i, e, s);
98
+ g(w), t(l);
64
99
  return;
65
100
  }
66
- for (; i >= 0 && e[i] !== "d"; )
67
- i--;
68
- if (i < 0) return;
69
- if (l) {
70
- const r = t && i < t.length ? t[i] : "_", s = n.substring(0, i) + r + n.substring(i + 1);
71
- g(s), u(i);
101
+ for (; r >= 0 && e[r] !== "d"; )
102
+ r--;
103
+ if (r < 0) return;
104
+ if (f) {
105
+ const u = s && r < s.length ? s[r] : "_", i = n.substring(0, r) + u + n.substring(r + 1);
106
+ g(i), t(r);
72
107
  } else {
73
- const r = n.slice(0, i) + n.slice(i + 1), s = d(r, e), o = h(s, e, t);
74
- g(o), u(i);
108
+ const u = n.slice(0, r) + n.slice(r + 1), i = k(u, e), w = y(i, e, s);
109
+ g(w), t(r);
75
110
  }
76
111
  } else if (a.key === "Delete") {
77
- if (a.preventDefault(), b)
78
- if (l) {
79
- let r = n;
80
- for (let s = c; s < w; s++)
81
- if (e[s] === "d") {
82
- const o = t && s < t.length ? t[s] : "_";
83
- r = r.substring(0, s) + o + r.substring(s + 1);
112
+ if (a.preventDefault(), D)
113
+ if (f) {
114
+ let u = n;
115
+ for (let i = l; i < C; i++)
116
+ if (e[i] === "d") {
117
+ const w = s && i < s.length ? s[i] : "_";
118
+ u = u.substring(0, i) + w + u.substring(i + 1);
84
119
  }
85
- g(r), u(c);
120
+ g(u), t(l);
86
121
  return;
87
122
  } else {
88
- const r = n.slice(0, c) + n.slice(w), s = d(r, e), o = h(s, e, t);
89
- g(o), u(c);
123
+ const u = n.slice(0, l) + n.slice(C), i = k(u, e), w = y(i, e, s);
124
+ g(w), t(l);
90
125
  return;
91
126
  }
92
- let i = c;
93
- for (; i < e.length && e[i] !== "d"; )
94
- i++;
95
- if (i >= n.length) return;
96
- if (l) {
97
- const r = t && i < t.length ? t[i] : "_", s = n.substring(0, i) + r + n.substring(i + 1);
98
- g(s), u(c);
127
+ let r = l;
128
+ for (; r < e.length && e[r] !== "d"; )
129
+ r++;
130
+ if (r >= n.length) return;
131
+ if (f) {
132
+ const u = s && r < s.length ? s[r] : "_", i = n.substring(0, r) + u + n.substring(r + 1);
133
+ g(i), t(l);
99
134
  } else {
100
- const r = n.slice(0, i) + n.slice(i + 1), s = d(r, e), o = h(s, e, t);
101
- g(o), u(c);
135
+ const u = n.slice(0, r) + n.slice(r + 1), i = k(u, e), w = y(i, e, s);
136
+ g(w), t(l);
102
137
  }
103
138
  }
104
- }, I = (a) => {
105
- const D = a.target, c = D.value, w = D.selectionStart || 0, b = () => {
106
- const i = c.slice(0, w), r = d(i, e).length, s = d(c, e), o = h(s, e, t);
107
- g(o);
108
- let y = 0, v = 0;
109
- for (let L = 0; L < o.length && !(y >= r); L++)
110
- k(o[L]) && e[L] === "d" && y++, v++;
111
- for (; v < o.length && e[v] !== "d"; )
112
- v++;
113
- u(v);
139
+ }, R = (a) => {
140
+ const S = a.target, l = S.value, C = S.selectionStart || 0, D = () => {
141
+ const r = l.slice(0, C), u = k(r, e).length, i = k(l, e), w = y(i, e, s);
142
+ g(w);
143
+ let I = 0, L = 0;
144
+ for (let E = 0; E < w.length && !(I >= u); E++)
145
+ V(w[E]) && e[E] === "d" && I++, L++;
146
+ for (; L < w.length && e[L] !== "d"; )
147
+ L++;
148
+ t(L);
114
149
  };
115
- if (l && c.length > n.length) {
116
- const i = w - 1, r = c[i];
117
- if (!k(r)) {
118
- b();
119
- return;
120
- }
121
- let s = i;
122
- for (; s < e.length && e[s] !== "d"; )
123
- s++;
124
- if (s >= e.length) {
125
- b();
126
- return;
150
+ if (f) {
151
+ const r = h.current.start, u = h.current.end, i = r !== u, w = u - r;
152
+ if (l.length - n.length + w === 1 && C > 0) {
153
+ const L = C - 1, E = l[L];
154
+ if (V(E)) {
155
+ const _ = i ? r : L, F = i ? u : L;
156
+ if (_ < e.length) {
157
+ const T = N(
158
+ n,
159
+ e,
160
+ s,
161
+ _,
162
+ F,
163
+ E
164
+ );
165
+ g(T.value), t(T.cursor);
166
+ return;
167
+ }
168
+ }
127
169
  }
128
- const o = n.substring(0, s) + r + n.substring(s + 1);
129
- g(o), u(s + 1);
130
- return;
131
170
  }
132
- b();
171
+ D();
133
172
  };
134
- return V.addEventListener("keydown", x), V.addEventListener("input", I), () => {
135
- V.removeEventListener("keydown", x), V.removeEventListener("input", I);
173
+ return c.addEventListener("keydown", x), c.addEventListener("input", R), c.addEventListener("select", b), c.addEventListener("click", b), c.addEventListener("keyup", b), () => {
174
+ c.removeEventListener("keydown", x), c.removeEventListener("input", R), c.removeEventListener("select", b), c.removeEventListener("click", b), c.removeEventListener("keyup", b);
136
175
  };
137
- }, [n, e, t, l]);
138
- const R = d(n, e);
176
+ }, [n, e, s, f]);
177
+ const d = k(n, e);
139
178
  return {
140
179
  value: n,
141
180
  displayValue: n,
142
- rawValue: R,
143
- ref: C
181
+ rawValue: d,
182
+ ref: v
144
183
  };
145
184
  }
146
185
  export {
147
- B as useInputNumberMask
186
+ j as useInputNumberMask
148
187
  };
149
188
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../src/utils/maskUtils.ts","../src/useInputNumberMask.ts"],"sourcesContent":["export const isDigit = (char: string) => /\\d/.test(char);\n\nexport const cleanInput = (input: string, template: string): string => {\n let extracted = '';\n let t = 0;\n\n for (let i = 0; i < input.length; i++) {\n const char = input[i];\n\n if (t >= template.length) {\n break;\n }\n\n if (template[t] === 'd') {\n if (isDigit(char)) {\n extracted += char;\n t++;\n } else {\n // Ignore placeholders or garbage\n }\n } else if (template[t] === char) {\n t++;\n } else {\n let nextT = t;\n while (nextT < template.length && template[nextT] !== 'd' && template[nextT] !== char) {\n nextT++;\n }\n if (nextT < template.length && template[nextT] === 'd') {\n if (isDigit(char)) {\n extracted += char;\n t = nextT + 1;\n }\n } else if (nextT < template.length && template[nextT] === char) {\n t = nextT + 1;\n }\n }\n }\n return extracted;\n};\n\nexport const formatWithMask = (digits: string, template: string, placeholder?: string): string => {\n let res = '';\n let dIdx = 0;\n\n for (let i = 0; i < template.length; i++) {\n const isSlot = template[i] === 'd';\n\n if (isSlot) {\n if (dIdx < digits.length) {\n res += digits[dIdx++];\n } else {\n // Empty slot\n if (placeholder && i < placeholder.length) {\n res += placeholder[i];\n } else {\n if (!placeholder) {\n break;\n }\n }\n }\n } else {\n res += template[i];\n }\n }\n return res;\n};\n","import { useRef, useState, useLayoutEffect } from 'react';\nimport { cleanInput, formatWithMask, isDigit } from './utils/maskUtils';\n\nexport interface UseInputNumberMaskProps {\n /**\n * The mask template. 'd' represents a digit slot.\n * All other characters are treated as literals.\n * @example \"+1 (ddd) ddd-dddd\" for US phone numbers\n */\n template: string;\n\n /**\n * Optional full-length placeholder shown in empty slots.\n * Should match the template length.\n * @example \"mm/dd/yyyy\" for a date mask\n */\n placeholder?: string;\n\n /**\n * If true, deletion replaces with placeholder char\n * instead of shifting subsequent digits left.\n * @default false\n */\n keepPosition?: boolean;\n}\n\nexport interface UseInputNumberMaskReturn {\n /** \n * The raw value with formatting applied \n * @example \"+1 (234) 567-8900\" \n */\n value: string;\n /** \n * Deprecated: alias for value. The value to display in the input. \n * @example \"+1 (234) 567-8900\" \n */\n displayValue: string;\n /** \n * The unmasked digits only \n * @example \"1234567890\" \n */\n rawValue: string;\n /** \n * Ref to be attached to the HTML input element \n */\n ref: React.RefObject<HTMLInputElement | null>;\n}\n\nexport function useInputNumberMask({\n template,\n placeholder,\n keepPosition = false,\n}: UseInputNumberMaskProps): UseInputNumberMaskReturn {\n\n const [value, setValue] = useState(() => formatWithMask('', template, placeholder));\n const [cursor, setCursor] = useState<number | null>(null);\n const ref = useRef<HTMLInputElement>(null);\n\n useLayoutEffect(() => {\n if (ref.current && cursor !== null) {\n ref.current.setSelectionRange(cursor, cursor);\n }\n }, [cursor, value]);\n\n // Ref-based Event Handling\n useLayoutEffect(() => {\n const input = ref.current;\n if (!input) return;\n\n const handleKeyDown = (e: globalThis.KeyboardEvent) => {\n const el = e.target as HTMLInputElement;\n const start = el.selectionStart || 0;\n const end = el.selectionEnd || 0;\n const isSelection = start !== end;\n\n if (e.key === 'Backspace') {\n if (start === 0 && !isSelection) return;\n // We prevent default to handle the state update manually\n e.preventDefault();\n\n let deleteIndex = start - 1;\n\n if (isSelection) {\n if (keepPosition) {\n // Replace range with placeholders\n let newVal = value;\n for (let i = start; i < end; i++) {\n if (template[i] === 'd') {\n const pChar = placeholder && i < placeholder.length ? placeholder[i] : '_';\n newVal = newVal.substring(0, i) + pChar + newVal.substring(i + 1);\n }\n }\n setValue(newVal);\n setCursor(start);\n return;\n } else {\n // Standard delete range (shift)\n const newValRaw = value.slice(0, start) + value.slice(end);\n const newDigits = cleanInput(newValRaw, template);\n const formatted = formatWithMask(newDigits, template, placeholder);\n setValue(formatted);\n setCursor(start);\n return;\n }\n }\n\n // Single char backspace\n while (deleteIndex >= 0) {\n const isTemplateLiteral = template[deleteIndex] !== 'd';\n if (isTemplateLiteral) {\n deleteIndex--;\n } else {\n break;\n }\n }\n\n if (deleteIndex < 0) return; // Nothing to delete\n\n if (keepPosition) {\n const pChar = placeholder && deleteIndex < placeholder.length ? placeholder[deleteIndex] : '_';\n const newVal = value.substring(0, deleteIndex) + pChar + value.substring(deleteIndex + 1);\n setValue(newVal);\n setCursor(deleteIndex);\n } else {\n // Shift behavior\n const newValRaw = value.slice(0, deleteIndex) + value.slice(deleteIndex + 1);\n const newDigits = cleanInput(newValRaw, template);\n const formatted = formatWithMask(newDigits, template, placeholder);\n setValue(formatted);\n setCursor(deleteIndex);\n }\n } else if (e.key === 'Delete') {\n e.preventDefault();\n // Delete forward\n if (isSelection) {\n if (keepPosition) {\n let newVal = value;\n for (let i = start; i < end; i++) {\n if (template[i] === 'd') {\n const pChar = placeholder && i < placeholder.length ? placeholder[i] : '_';\n newVal = newVal.substring(0, i) + pChar + newVal.substring(i + 1);\n }\n }\n setValue(newVal);\n setCursor(start);\n return;\n } else {\n const newValRaw = value.slice(0, start) + value.slice(end);\n const newDigits = cleanInput(newValRaw, template);\n const formatted = formatWithMask(newDigits, template, placeholder);\n setValue(formatted);\n setCursor(start);\n return;\n }\n }\n\n // Single char delete\n let deleteIndex = start;\n while (deleteIndex < template.length) {\n const isTemplateLiteral = template[deleteIndex] !== 'd';\n if (isTemplateLiteral) {\n deleteIndex++;\n } else {\n break;\n }\n }\n\n if (deleteIndex >= value.length) return;\n\n if (keepPosition) {\n const pChar = placeholder && deleteIndex < placeholder.length ? placeholder[deleteIndex] : '_';\n const newVal = value.substring(0, deleteIndex) + pChar + value.substring(deleteIndex + 1);\n setValue(newVal);\n setCursor(start);\n } else {\n // Shift behavior\n const newValRaw = value.slice(0, deleteIndex) + value.slice(deleteIndex + 1);\n const newDigits = cleanInput(newValRaw, template);\n const formatted = formatWithMask(newDigits, template, placeholder);\n setValue(formatted);\n setCursor(start);\n }\n }\n };\n\n const handleInput = (e: Event) => {\n // We cast to InputEvent or basic Event. target is HTMLInputElement.\n const target = e.target as HTMLInputElement;\n const inputVal = target.value;\n const rawCursor = target.selectionStart || 0;\n\n // Standard behavior logic\n const standardChange = () => {\n const beforeCursor = inputVal.slice(0, rawCursor);\n const digitsBeforeCursor = cleanInput(beforeCursor, template).length;\n\n const newDigits = cleanInput(inputVal, template);\n const newFormatted = formatWithMask(newDigits, template, placeholder);\n\n setValue(newFormatted);\n\n let currentDigits = 0;\n let newCursor = 0;\n for (let i = 0; i < newFormatted.length; i++) {\n if (currentDigits >= digitsBeforeCursor) {\n break;\n }\n if (isDigit(newFormatted[i]) && template[i] === 'd') {\n currentDigits++;\n }\n newCursor++;\n }\n\n while (newCursor < newFormatted.length && template[newCursor] !== 'd') {\n newCursor++;\n }\n\n setCursor(newCursor);\n };\n\n if (keepPosition) {\n // Measure diff against current state `value` (mapped in closure)\n // NOTE: `value` in this closure is stale if not included in dependency array.\n // We need strict dependency on `value`.\n if (inputVal.length > value.length) {\n const insertIndex = rawCursor - 1;\n const char = inputVal[insertIndex];\n\n if (!isDigit(char)) {\n standardChange();\n return;\n }\n\n let targetIndex = insertIndex;\n while (targetIndex < template.length) {\n if (template[targetIndex] === 'd') {\n break;\n }\n targetIndex++;\n }\n\n if (targetIndex >= template.length) {\n standardChange();\n return;\n }\n\n const newValue = value.substring(0, targetIndex) + char + value.substring(targetIndex + 1);\n\n setValue(newValue);\n setCursor(targetIndex + 1);\n return;\n }\n }\n\n standardChange();\n };\n\n input.addEventListener('keydown', handleKeyDown);\n input.addEventListener('input', handleInput);\n\n return () => {\n input.removeEventListener('keydown', handleKeyDown);\n input.removeEventListener('input', handleInput);\n };\n }, [value, template, placeholder, keepPosition]); // Re-bind when value changes to have fresh closure\n\n const rawValue = cleanInput(value, template);\n\n return {\n value,\n displayValue: value,\n rawValue,\n ref\n };\n}\n"],"names":["isDigit","char","cleanInput","input","template","extracted","t","i","nextT","formatWithMask","digits","placeholder","res","dIdx","useInputNumberMask","keepPosition","value","setValue","useState","cursor","setCursor","ref","useRef","useLayoutEffect","handleKeyDown","e","el","start","end","isSelection","deleteIndex","newVal","pChar","newValRaw","newDigits","formatted","handleInput","target","inputVal","rawCursor","standardChange","beforeCursor","digitsBeforeCursor","newFormatted","currentDigits","newCursor","insertIndex","targetIndex","newValue","rawValue"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","sources":["../src/utils/maskUtils.ts","../src/useInputNumberMask.ts"],"sourcesContent":["export const isDigit = (char: string) => /\\d/.test(char);\n\nexport const cleanInput = (input: string, template: string): string => {\n let extracted = '';\n let t = 0;\n\n for (let i = 0; i < input.length; i++) {\n const char = input[i];\n\n if (t >= template.length) {\n break;\n }\n\n if (template[t] === 'd') {\n if (isDigit(char)) {\n extracted += char;\n t++;\n } else {\n // Ignore placeholders or garbage\n }\n } else if (template[t] === char) {\n t++;\n } else {\n let nextT = t;\n while (nextT < template.length && template[nextT] !== 'd' && template[nextT] !== char) {\n nextT++;\n }\n if (nextT < template.length && template[nextT] === 'd') {\n if (isDigit(char)) {\n extracted += char;\n t = nextT + 1;\n }\n } else if (nextT < template.length && template[nextT] === char) {\n t = nextT + 1;\n }\n }\n }\n return extracted;\n};\n\nexport const formatWithMask = (digits: string, template: string, placeholder?: string): string => {\n let res = '';\n let dIdx = 0;\n\n for (let i = 0; i < template.length; i++) {\n const isSlot = template[i] === 'd';\n\n if (isSlot) {\n if (dIdx < digits.length) {\n res += digits[dIdx++];\n } else {\n // Empty slot\n if (placeholder && i < placeholder.length) {\n res += placeholder[i];\n } else {\n if (!placeholder) {\n break;\n }\n }\n }\n } else {\n res += template[i];\n }\n }\n return res;\n};\n\nexport const applyKeepPositionChange = (\n value: string,\n template: string,\n placeholder: string | undefined,\n start: number,\n end: number,\n char: string\n): { value: string; cursor: number } => {\n let newValue = value;\n let newCursor = start;\n\n // Deletion\n if (char === '') {\n for (let i = start; i < end; i++) {\n if (template[i] === 'd') {\n const pChar = placeholder && i < placeholder.length ? placeholder[i] : '_';\n newValue = newValue.substring(0, i) + pChar + newValue.substring(i + 1);\n }\n }\n return { value: newValue, cursor: start };\n }\n\n // Replacement (Selection)\n if (start !== end) {\n // 1. Replace the first digit slot at start (if it's a digit slot)\n // Actually, if we selected a range, we typically want to replace the *entire* range content\n // with the new char *at the beginning*, and clear the rest.\n // But we must respect the template chars.\n\n // Strategy:\n // - Clear the entire range first (replace with placeholders)\n // - Insert the char at the first available digit slot within the range (or shortly after if range starts on literal?)\n // Wait, standard input behavior replacing a selection \"12/34\" with \"5\":\n // \"12/5...\"\n // So effectively: delete range, then insert char.\n\n // Let's implement it as:\n // 1. Check if first char of selection matches the typed char\n // If so, skip it and insert at the next digit slot\n let insertStart = start;\n if (isDigit(char) && value[start] === char) {\n // The first position already has the same digit, so skip it\n insertStart = start + 1;\n // Skip any literals to find the next digit slot\n while (insertStart < end && template[insertStart] !== 'd') {\n insertStart++;\n }\n }\n\n // 2. Clear the range from insertStart to end (fill with placeholders)\n for (let i = insertStart; i < end; i++) {\n if (template[i] === 'd') {\n const pChar = placeholder && i < placeholder.length ? placeholder[i] : '_';\n newValue = newValue.substring(0, i) + pChar + newValue.substring(i + 1);\n }\n }\n\n // 3. Insert the char at insertStart (finding closest digit slot)\n let targetIndex = insertStart;\n while (targetIndex < template.length) {\n if (template[targetIndex] === 'd') {\n break;\n }\n targetIndex++;\n }\n\n if (targetIndex < template.length && isDigit(char)) {\n newValue = newValue.substring(0, targetIndex) + char + newValue.substring(targetIndex + 1);\n newCursor = targetIndex + 1;\n } else {\n newCursor = start;\n }\n\n return { value: newValue, cursor: newCursor };\n }\n\n // Insertion (No selection)\n // Find next digit slot\n let targetIndex = start;\n while (targetIndex < template.length) {\n if (template[targetIndex] === 'd') {\n break;\n }\n targetIndex++;\n }\n\n if (targetIndex < template.length && isDigit(char)) {\n newValue = newValue.substring(0, targetIndex) + char + newValue.substring(targetIndex + 1);\n newCursor = targetIndex + 1;\n } else {\n newCursor = start; // No change\n }\n\n return { value: newValue, cursor: newCursor };\n};\n","import { useRef, useState, useLayoutEffect } from 'react';\nimport { cleanInput, formatWithMask, isDigit, applyKeepPositionChange } from './utils/maskUtils';\n\nexport interface UseInputNumberMaskProps {\n /**\n * The mask template. 'd' represents a digit slot.\n * All other characters are treated as literals.\n * @example \"+1 (ddd) ddd-dddd\" for US phone numbers\n */\n template: string;\n\n /**\n * Optional full-length placeholder shown in empty slots.\n * Should match the template length.\n * @example \"mm/dd/yyyy\" for a date mask\n */\n placeholder?: string;\n\n /**\n * If true, deletion replaces with placeholder char\n * instead of shifting subsequent digits left.\n * @default false\n */\n keepPosition?: boolean;\n}\n\nexport interface UseInputNumberMaskReturn {\n /** \n * The raw value with formatting applied \n * @example \"+1 (234) 567-8900\" \n */\n value: string;\n /** \n * Deprecated: alias for value. The value to display in the input. \n * @example \"+1 (234) 567-8900\" \n */\n displayValue: string;\n /** \n * The unmasked digits only \n * @example \"1234567890\" \n */\n rawValue: string;\n /** \n * Ref to be attached to the HTML input element \n */\n ref: React.RefObject<HTMLInputElement | null>;\n}\n\nexport function useInputNumberMask({\n template,\n placeholder,\n keepPosition = false,\n}: UseInputNumberMaskProps): UseInputNumberMaskReturn {\n\n const [value, setValue] = useState(() => formatWithMask('', template, placeholder));\n const [cursor, setCursor] = useState<number | null>(null);\n const ref = useRef<HTMLInputElement>(null);\n const selectionRef = useRef<{ start: number; end: number }>({ start: 0, end: 0 });\n\n useLayoutEffect(() => {\n if (ref.current && cursor !== null) {\n ref.current.setSelectionRange(cursor, cursor);\n }\n }, [cursor, value]);\n\n // Ref-based Event Handling\n useLayoutEffect(() => {\n const input = ref.current;\n if (!input) return;\n\n const updateSelection = () => {\n if (input) {\n selectionRef.current = {\n start: input.selectionStart || 0,\n end: input.selectionEnd || 0,\n };\n }\n };\n\n const handleKeyDown = (e: globalThis.KeyboardEvent) => {\n updateSelection();\n const el = e.target as HTMLInputElement;\n const start = el.selectionStart || 0;\n const end = el.selectionEnd || 0;\n const isSelection = start !== end;\n\n if (e.key === 'Backspace') {\n if (start === 0 && !isSelection) return;\n // We prevent default to handle the state update manually\n e.preventDefault();\n\n let deleteIndex = start - 1;\n\n if (isSelection) {\n if (keepPosition) {\n // Replace range with placeholders\n let newVal = value;\n for (let i = start; i < end; i++) {\n if (template[i] === 'd') {\n const pChar = placeholder && i < placeholder.length ? placeholder[i] : '_';\n newVal = newVal.substring(0, i) + pChar + newVal.substring(i + 1);\n }\n }\n setValue(newVal);\n setCursor(start);\n return;\n } else {\n // Standard delete range (shift)\n const newValRaw = value.slice(0, start) + value.slice(end);\n const newDigits = cleanInput(newValRaw, template);\n const formatted = formatWithMask(newDigits, template, placeholder);\n setValue(formatted);\n setCursor(start);\n return;\n }\n }\n\n // Single char backspace\n while (deleteIndex >= 0) {\n const isTemplateLiteral = template[deleteIndex] !== 'd';\n if (isTemplateLiteral) {\n deleteIndex--;\n } else {\n break;\n }\n }\n\n if (deleteIndex < 0) return; // Nothing to delete\n\n if (keepPosition) {\n const pChar = placeholder && deleteIndex < placeholder.length ? placeholder[deleteIndex] : '_';\n const newVal = value.substring(0, deleteIndex) + pChar + value.substring(deleteIndex + 1);\n setValue(newVal);\n setCursor(deleteIndex);\n } else {\n // Shift behavior\n const newValRaw = value.slice(0, deleteIndex) + value.slice(deleteIndex + 1);\n const newDigits = cleanInput(newValRaw, template);\n const formatted = formatWithMask(newDigits, template, placeholder);\n setValue(formatted);\n setCursor(deleteIndex);\n }\n } else if (e.key === 'Delete') {\n e.preventDefault();\n // Delete forward\n if (isSelection) {\n if (keepPosition) {\n let newVal = value;\n for (let i = start; i < end; i++) {\n if (template[i] === 'd') {\n const pChar = placeholder && i < placeholder.length ? placeholder[i] : '_';\n newVal = newVal.substring(0, i) + pChar + newVal.substring(i + 1);\n }\n }\n setValue(newVal);\n setCursor(start);\n return;\n } else {\n const newValRaw = value.slice(0, start) + value.slice(end);\n const newDigits = cleanInput(newValRaw, template);\n const formatted = formatWithMask(newDigits, template, placeholder);\n setValue(formatted);\n setCursor(start);\n return;\n }\n }\n\n // Single char delete\n let deleteIndex = start;\n while (deleteIndex < template.length) {\n const isTemplateLiteral = template[deleteIndex] !== 'd';\n if (isTemplateLiteral) {\n deleteIndex++;\n } else {\n break;\n }\n }\n\n if (deleteIndex >= value.length) return;\n\n if (keepPosition) {\n const pChar = placeholder && deleteIndex < placeholder.length ? placeholder[deleteIndex] : '_';\n const newVal = value.substring(0, deleteIndex) + pChar + value.substring(deleteIndex + 1);\n setValue(newVal);\n setCursor(start);\n } else {\n // Shift behavior\n const newValRaw = value.slice(0, deleteIndex) + value.slice(deleteIndex + 1);\n const newDigits = cleanInput(newValRaw, template);\n const formatted = formatWithMask(newDigits, template, placeholder);\n setValue(formatted);\n setCursor(start);\n }\n }\n };\n\n const handleInput = (e: Event) => {\n // We cast to InputEvent or basic Event. target is HTMLInputElement.\n const target = e.target as HTMLInputElement;\n const inputVal = target.value;\n const rawCursor = target.selectionStart || 0;\n\n // Standard behavior logic\n const standardChange = () => {\n const beforeCursor = inputVal.slice(0, rawCursor);\n const digitsBeforeCursor = cleanInput(beforeCursor, template).length;\n\n const newDigits = cleanInput(inputVal, template);\n const newFormatted = formatWithMask(newDigits, template, placeholder);\n\n setValue(newFormatted);\n\n let currentDigits = 0;\n let newCursor = 0;\n for (let i = 0; i < newFormatted.length; i++) {\n if (currentDigits >= digitsBeforeCursor) {\n break;\n }\n if (isDigit(newFormatted[i]) && template[i] === 'd') {\n currentDigits++;\n }\n newCursor++;\n }\n\n while (newCursor < newFormatted.length && template[newCursor] !== 'd') {\n newCursor++;\n }\n\n setCursor(newCursor);\n };\n\n if (keepPosition) {\n const prevStart = selectionRef.current.start;\n const prevEnd = selectionRef.current.end;\n const wasSelection = prevStart !== prevEnd;\n const selectionLength = prevEnd - prevStart;\n const typedChars = inputVal.length - value.length + selectionLength;\n\n // Handle single character input (typing one digit)\n if (typedChars === 1 && rawCursor > 0) {\n const insertIndex = rawCursor - 1;\n const char = inputVal[insertIndex];\n\n if (isDigit(char)) {\n // For selection replacement, use the selection range\n // For cursor insertion (no selection), use the cursor position\n const startPos = wasSelection ? prevStart : insertIndex;\n const endPos = wasSelection ? prevEnd : insertIndex;\n\n // Only apply keepPosition if within template bounds\n // If cursor is at/beyond template length (e.g., typing at end),\n // fall through to standardChange() for normal fill behavior\n if (startPos < template.length) {\n const result = applyKeepPositionChange(\n value,\n template,\n placeholder,\n startPos,\n endPos,\n char\n );\n\n setValue(result.value);\n setCursor(result.cursor);\n return;\n }\n }\n }\n }\n\n standardChange();\n };\n\n input.addEventListener('keydown', handleKeyDown);\n input.addEventListener('input', handleInput);\n input.addEventListener('select', updateSelection);\n input.addEventListener('click', updateSelection);\n input.addEventListener('keyup', updateSelection);\n\n return () => {\n input.removeEventListener('keydown', handleKeyDown);\n input.removeEventListener('input', handleInput);\n input.removeEventListener('select', updateSelection);\n input.removeEventListener('click', updateSelection);\n input.removeEventListener('keyup', updateSelection);\n };\n }, [value, template, placeholder, keepPosition]); // Re-bind when value changes to have fresh closure\n\n const rawValue = cleanInput(value, template);\n\n return {\n value,\n displayValue: value,\n rawValue,\n ref\n };\n}\n"],"names":["isDigit","char","cleanInput","input","template","extracted","t","i","nextT","formatWithMask","digits","placeholder","res","dIdx","applyKeepPositionChange","value","start","end","newValue","newCursor","pChar","insertStart","targetIndex","useInputNumberMask","keepPosition","setValue","useState","cursor","setCursor","ref","useRef","selectionRef","useLayoutEffect","updateSelection","handleKeyDown","e","el","isSelection","deleteIndex","newVal","newValRaw","newDigits","formatted","handleInput","target","inputVal","rawCursor","standardChange","beforeCursor","digitsBeforeCursor","newFormatted","currentDigits","prevStart","prevEnd","wasSelection","selectionLength","insertIndex","startPos","endPos","result","rawValue"],"mappings":"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"}
package/package.json CHANGED
@@ -1,8 +1,7 @@
1
1
  {
2
2
  "name": "@tounsoo/input-number-mask",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "A lightweight, dependency-free React hook for masking input values. Perfect for phone numbers, dates, credit cards, and more.",
5
- "packageManager": "pnpm@10.23.0",
6
5
  "type": "module",
7
6
  "main": "./dist/index.cjs",
8
7
  "module": "./dist/index.mjs",
@@ -24,21 +23,6 @@
24
23
  "README.md",
25
24
  "LICENSE"
26
25
  ],
27
- "scripts": {
28
- "dev": "vite",
29
- "build": "tsc -b && vite build",
30
- "build:lib": "tsc -p tsconfig.lib.json && vite build --config vite.config.lib.ts",
31
- "lint": "eslint .",
32
- "preview": "vite preview",
33
- "storybook": "storybook dev -p 6006",
34
- "build-storybook": "storybook build",
35
- "test": "vitest run",
36
- "test:ci": "vitest run --config vitest.config.ci.ts",
37
- "prepublishOnly": "pnpm build:lib",
38
- "changeset": "changeset",
39
- "version": "changeset version",
40
- "release": "pnpm build:lib && npm publish --access public --provenance && git push --follow-tags origin main"
41
- },
42
26
  "peerDependencies": {
43
27
  "react": "^18.0.0 || ^19.0.0",
44
28
  "react-dom": "^18.0.0 || ^19.0.0"
@@ -101,5 +85,19 @@
101
85
  "publishConfig": {
102
86
  "access": "public",
103
87
  "provenance": true
88
+ },
89
+ "scripts": {
90
+ "dev": "vite",
91
+ "build": "tsc -b && vite build",
92
+ "build:lib": "tsc -p tsconfig.lib.json && vite build --config vite.config.lib.ts",
93
+ "lint": "eslint .",
94
+ "preview": "vite preview",
95
+ "storybook": "storybook dev -p 6006",
96
+ "build-storybook": "storybook build",
97
+ "test": "vitest run",
98
+ "test:ci": "vitest run --config vitest.config.ci.ts",
99
+ "changeset": "changeset",
100
+ "version": "changeset version",
101
+ "release": "pnpm build:lib && changeset publish"
104
102
  }
105
103
  }