mother-mask 1.4.2 → 2.0.2

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
@@ -1,30 +1,120 @@
1
1
  # mother-mask
2
- The Mother-Mask is a simple and definitive Js library to implement text mask using a pattern.
3
2
 
3
+ Lightweight input mask library for browsers. Zero dependencies, TypeScript-first, ships ESM + CJS + UMD.
4
4
 
5
- ## How to Install
5
+ ## Install
6
6
 
7
7
  ```bash
8
- $ npm install mother-mask --save
8
+ npm install mother-mask
9
+ # or
10
+ pnpm add mother-mask
9
11
  ```
10
12
 
11
- ### How to Use ###
13
+ ## Usage
12
14
 
13
- ```javascript
14
- // get the input element
15
- // vanilla javascript
16
- var phoneInputElement = document.getElementById("myphoneinput");
17
- // Jquery
18
- var phoneInputElement = $("#myphoneinput")[0];
15
+ ### `bind(input, mask, callback?)` — DOM binding
19
16
 
20
- // bind the element with the mask
21
- MotherMask.bind(phoneInputElement, "999.999.999-99");
17
+ Attach a mask to any input element. Idempotent — calling `bind()` twice on the same element has no effect.
22
18
 
23
- // create dynamic mask
24
- MotherMask.bind(phoneInputElement, ["(99) 9999-9999", "(99) 99999-9999"]);
19
+ ```ts
20
+ import { bind } from 'mother-mask'
25
21
 
22
+ const input = document.getElementById('phone') as HTMLInputElement
23
+
24
+ // Fixed mask
25
+ bind(input, '(99) 99999-9999')
26
+
27
+ // Dynamic mask — switches automatically as the user types
28
+ bind(input, ['(99) 9999-9999', '(99) 99999-9999'])
29
+
30
+ // Optional callback — receives the masked value on every change
31
+ bind(input, '999.999.999-99', (value) => {
32
+ console.log(value) // e.g. "123.456.789-01"
33
+ })
34
+ ```
35
+
36
+ ### `process(value, mask)` — pure function
37
+
38
+ Apply a mask to a raw string without touching the DOM. Useful for formatting stored values.
39
+
40
+ ```ts
41
+ import { process } from 'mother-mask'
42
+
43
+ process('12345678901', '999.999.999-99') // → "123.456.789-01"
44
+ process('01012024', '99/99/9999') // → "01/01/2024"
45
+ process('01310100', '99999-999') // → "01310-100"
46
+ ```
47
+
48
+ ## Pattern syntax
49
+
50
+ | Character | Matches |
51
+ |-----------|----------------|
52
+ | `9` | Digit (0–9) |
53
+ | `Z` | Letter (a–z, A–Z) |
54
+ | anything else | Literal — inserted automatically |
55
+
56
+ ## Array masks
57
+
58
+ Pass an ordered array (shortest → longest) to support variable-length inputs. The mask is selected by comparing the current value length against each mask's total length.
59
+
60
+ ```ts
61
+ // Brazilian phone: 8-digit → 9-digit landline / mobile
62
+ bind(input, ['(99) 9999-9999', '(99) 99999-9999'])
63
+
64
+ // CPF / CNPJ
65
+ bind(input, ['999.999.999-99', '99.999.999/9999-99'])
66
+ ```
67
+
68
+ ## UMD / CDN
69
+
70
+ ```html
71
+ <script src="https://unpkg.com/mother-mask/dist/mother-mask.umd.js"></script>
72
+ <script>
73
+ MotherMask.bind(document.getElementById('cpf'), '999.999.999-99')
74
+ </script>
75
+ ```
76
+
77
+ ## API reference
78
+
79
+ ```ts
80
+ // Apply mask to a string — no DOM required
81
+ process(value: string, mask: MaskPattern): string
82
+
83
+ // Bind a mask to an input element (idempotent)
84
+ bind(
85
+ input: HTMLInputElement | Element,
86
+ mask: MaskPattern,
87
+ callback?: ((value: string) => void) | null,
88
+ ): void
89
+
90
+ // Build a Mask instance directly (advanced use)
91
+ buildMask(value: string, mask: MaskPattern, caret?: number): Mask
92
+
93
+ // Maximum allowed input length for a given mask
94
+ getMaxLength(mask: MaskPattern): number
95
+
96
+ // Pattern type
97
+ type MaskPattern = string | string[]
98
+ ```
99
+
100
+ ## Development
101
+
102
+ ```bash
103
+ make install # install dependencies
104
+ make test # run tests + coverage
105
+ make build # build ESM + CJS + UMD
106
+ make dev # watch mode
107
+ make lint # lint source files
108
+ ```
109
+
110
+ ## Release
111
+
112
+ ```bash
113
+ make publish # bump patch, publish, commit, tag, push
114
+ make publish BUMP=minor
115
+ make publish BUMP=major
26
116
  ```
27
117
 
28
- ### Simple Working demo
118
+ ## License
29
119
 
30
- **[Working demo!](https://stackblitz.com/edit/mother-mask-sample)**
120
+ MIT — [Danilo Celestino de Castro](https://github.com/dan2dev)
@@ -0,0 +1,2 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=/\D/,t=/[a-zA-Z]/;function n(t){return!e.test(t)}function r(e){return t.test(e)}var i=function(e){return e[e.NUMBER=0]=`NUMBER`,e[e.LETTER=1]=`LETTER`,e}(i||{}),a=class{caret;_mask;_value;_maskPos=-1;_maskChar=``;_valuePos=-1;_valueChar=``;constructor(e,t,n=0){this._value=e,this._mask=t,this.caret=n}process(){if(!this._value)return``;let e=``,t=[];for(;this._nextMaskChar();)if(typeof this._maskChar==`string`)t.push(this._maskChar);else if(this._nextValueChar(this._maskChar)&&this._valueChar){for(;t.length>0;)this._maskPos<=this.caret+1&&this._maskPos>=this.caret&&this.caret++,e+=t.shift();e+=this._valueChar}return e}_nextMaskChar(){if(this._maskPos++,this._maskPos>this._mask.length)return!1;let e=this._mask.charAt(this._maskPos);return e===`9`?this._maskChar=i.NUMBER:e===`Z`?this._maskChar=i.LETTER:this._maskChar=e,!0}_nextValueChar(e){if(this._valuePos++,this._valuePos>this._value.length)return!1;let t=this._value.charAt(this._valuePos);return this._valueChar=t,e===i.NUMBER&&n(t)||e===i.LETTER&&r(t)?!0:this._nextValueChar(e)}};function o(e,t){if(!Array.isArray(t))return t;let n=0;for(;n<t.length-1&&e.length>t[n].length;)n++;return t[n]}function s(e){return Array.isArray(e)?Math.max(...e.map(e=>e.length)):e.length}function c(e,t,n=0){return new a(e,o(e,t),n)}function l(e,t){return c(e,t).process()}const u=`data-masked`;let d;function f(){return d===void 0&&(d=typeof navigator<`u`&&/iPad|iPhone|iPod/i.test(navigator.userAgent)),d}function p(e,t,n=null){if(e.getAttribute(u)!==null)return;e.setAttribute(u,Array.isArray(t)?t.join(`|`):t),e.setAttribute(`autocomplete`,`off`),e.setAttribute(`autocorrect`,`off`),e.setAttribute(`autocapitalize`,`off`),e.setAttribute(`spellcheck`,`false`),e.setAttribute(`maxlength`,String(s(t)));let r=!1;e.addEventListener(`paste`,e=>{let r=e.target;requestAnimationFrame(()=>{r.value=c(r.value,t).process(),n?.(r.value)})}),e.addEventListener(f()?`keyup`:`keydown`,e=>{let i=e,a=i.target,o=a.value;if(!i.key){r=!0,requestAnimationFrame(()=>{let e=a.selectionStart??999,n=c(a.value,t,e);a.value=n.process(),a.setSelectionRange(n.caret,n.caret),requestAnimationFrame(()=>{r=!1})});return}if(i.key===`Meta`)return;let l=i.key===`Backspace`,u=i.key===`Delete`,d=i.key.length===1&&!i.ctrlKey&&!i.altKey&&!i.metaKey,p=i.key===`Unidentified`;if(d&&a.selectionStart===a.selectionEnd&&o.length>=s(t)&&!f()){i.preventDefault();return}if(r){i.preventDefault();return}r=!0,requestAnimationFrame(()=>{let e=a.selectionStart??999,i=c(a.value,t,e);if(a.value=i.process(),p){let t=a.value.length>o.length?i.caret:e;a.setSelectionRange(t,t)}else if(u){let t=o.length===a.value.length?e+1:e;a.setSelectionRange(t,t)}else l?a.setSelectionRange(e,e):d&&a.setSelectionRange(i.caret,i.caret);n?.(a.value),requestAnimationFrame(()=>{r=!1})})})}exports.Mask=a,exports.bind=p,exports.buildMask=c,exports.getMaxLength=s,exports.process=l;
2
+ //# sourceMappingURL=mother-mask.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mother-mask.cjs","names":[],"sources":["../src/mask.ts","../src/bind.ts"],"sourcesContent":["/**\n * Mask pattern — a single pattern string or an array ordered from shortest to longest.\n * `9` matches a digit, `Z` matches a letter, anything else is a literal character.\n *\n * @example\n * '(99) 99999-9999'\n * ['(99) 9999-9999', '(99) 99999-9999']\n */\nexport type MaskPattern = string | string[]\n\nconst numberRegex = /\\D/\nconst letterRegex = /[a-zA-Z]/\n\nfunction isDigit(ch: string): boolean {\n return !numberRegex.test(ch)\n}\n\nfunction isLetter(ch: string): boolean {\n return letterRegex.test(ch)\n}\n\nenum CharType {\n NUMBER,\n LETTER,\n}\n\n/** Low-level mask processor. Tracks caret position after masking. */\nexport class Mask {\n /** Caret position after `process()` runs. */\n caret: number\n\n private readonly _mask: string\n private readonly _value: string\n\n private _maskPos = -1\n private _maskChar: string | CharType = ''\n private _valuePos = -1\n private _valueChar = ''\n\n constructor(value: string, mask: string, caret = 0) {\n this._value = value\n this._mask = mask\n this.caret = caret\n }\n\n /** Apply the mask to the value and return the masked string. */\n process(): string {\n if (!this._value) return ''\n\n let output = ''\n const pending: string[] = []\n\n while (this._nextMaskChar()) {\n if (typeof this._maskChar === 'string') {\n pending.push(this._maskChar)\n } else if (this._nextValueChar(this._maskChar) && this._valueChar) {\n while (pending.length > 0) {\n if (this._maskPos <= this.caret + 1 && this._maskPos >= this.caret) {\n this.caret++\n }\n output += pending.shift()\n }\n output += this._valueChar\n }\n }\n\n return output\n }\n\n private _nextMaskChar(): boolean {\n this._maskPos++\n if (this._maskPos > this._mask.length) return false\n\n const ch = this._mask.charAt(this._maskPos)\n if (ch === '9') {\n this._maskChar = CharType.NUMBER\n } else if (ch === 'Z') {\n this._maskChar = CharType.LETTER\n } else {\n this._maskChar = ch\n }\n return true\n }\n\n private _nextValueChar(type: CharType): boolean {\n this._valuePos++\n if (this._valuePos > this._value.length) return false\n\n const ch = this._value.charAt(this._valuePos)\n this._valueChar = ch\n\n if (type === CharType.NUMBER && isDigit(ch)) return true\n if (type === CharType.LETTER && isLetter(ch)) return true\n\n return this._nextValueChar(type)\n }\n}\n\n/** Select the right mask string for the current value length. */\nfunction resolveMask(value: string, mask: MaskPattern): string {\n if (!Array.isArray(mask)) return mask\n\n let i = 0\n while (i < mask.length - 1 && value.length > mask[i].length) {\n i++\n }\n return mask[i]\n}\n\n/** Maximum allowed input length for the given mask. */\nexport function getMaxLength(mask: MaskPattern): number {\n if (Array.isArray(mask)) return Math.max(...mask.map((m) => m.length))\n return mask.length\n}\n\n/** Build a `Mask` instance, resolving array patterns by value length. */\nexport function buildMask(value: string, mask: MaskPattern, caret = 0): Mask {\n return new Mask(value, resolveMask(value, mask), caret)\n}\n\n/** Apply a mask pattern to a raw value string and return the masked result. */\nexport function process(value: string, mask: MaskPattern): string {\n return buildMask(value, mask).process()\n}\n","import type { MaskPattern } from './mask'\nimport { buildMask, getMaxLength } from './mask'\n\nconst MASKED_ATTR = 'data-masked'\n\nlet cachedIsIos: boolean | undefined\n\nfunction isIos(): boolean {\n if (cachedIsIos !== undefined) return cachedIsIos\n cachedIsIos =\n typeof navigator !== 'undefined' && /iPad|iPhone|iPod/i.test(navigator.userAgent)\n return cachedIsIos\n}\n\n/**\n * Bind a mask pattern to an input element.\n *\n * Idempotent — calling `bind()` on an already-bound element has no effect.\n * The element receives a `data-masked` attribute marking it as bound.\n *\n * @param input - Any `HTMLInputElement` or `Element` that behaves like one.\n * @param mask - A single pattern string or an ordered array (shortest → longest).\n * @param callback - Optional callback called with the masked value on every change.\n */\nexport function bind(\n input: HTMLInputElement | Element,\n mask: MaskPattern,\n callback: ((value: string) => void) | null = null,\n): void {\n if (input.getAttribute(MASKED_ATTR) !== null) return\n\n input.setAttribute(MASKED_ATTR, Array.isArray(mask) ? mask.join('|') : mask)\n input.setAttribute('autocomplete', 'off')\n input.setAttribute('autocorrect', 'off')\n input.setAttribute('autocapitalize', 'off')\n input.setAttribute('spellcheck', 'false')\n input.setAttribute('maxlength', String(getMaxLength(mask)))\n\n let lockInput = false\n\n input.addEventListener('paste', (e: Event) => {\n const target = e.target as HTMLInputElement\n requestAnimationFrame(() => {\n const m = buildMask(target.value, mask)\n target.value = m.process()\n callback?.(target.value)\n })\n })\n\n input.addEventListener(isIos() ? 'keyup' : 'keydown', (e: Event) => {\n const ke = e as KeyboardEvent\n const target = ke.target as HTMLInputElement\n const oldValue = target.value\n\n // Older Android WebViews may fire key events without a `key` value.\n if (!(ke as { key?: string }).key) {\n lockInput = true\n requestAnimationFrame(() => {\n const pos = target.selectionStart ?? 999\n const m = buildMask(target.value, mask, pos)\n target.value = m.process()\n target.setSelectionRange(m.caret, m.caret)\n requestAnimationFrame(() => {\n lockInput = false\n })\n })\n return\n }\n\n if (ke.key === 'Meta') return\n\n const isBackspace = ke.key === 'Backspace'\n const isDelete = ke.key === 'Delete'\n const isCharInsert = ke.key.length === 1 && !ke.ctrlKey && !ke.altKey && !ke.metaKey\n const isUnidentified = ke.key === 'Unidentified'\n\n // Block inserting when mask is full (desktop only — iOS handles this natively)\n if (isCharInsert && target.selectionStart === target.selectionEnd) {\n if (oldValue.length >= getMaxLength(mask) && !isIos()) {\n ke.preventDefault()\n return\n }\n }\n\n if (lockInput) {\n ke.preventDefault()\n return\n }\n\n lockInput = true\n requestAnimationFrame(() => {\n const pos = target.selectionStart ?? 999\n const m = buildMask(target.value, mask, pos)\n target.value = m.process()\n\n if (isUnidentified) {\n const newPos = target.value.length > oldValue.length ? m.caret : pos\n target.setSelectionRange(newPos, newPos)\n } else if (isDelete) {\n const newPos = oldValue.length === target.value.length ? pos + 1 : pos\n target.setSelectionRange(newPos, newPos)\n } else if (isBackspace) {\n target.setSelectionRange(pos, pos)\n } else if (isCharInsert) {\n target.setSelectionRange(m.caret, m.caret)\n }\n\n callback?.(target.value)\n requestAnimationFrame(() => {\n lockInput = false\n })\n })\n })\n}\n"],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ //#region src/mask.d.ts
2
+ /**
3
+ * Mask pattern — a single pattern string or an array ordered from shortest to longest.
4
+ * `9` matches a digit, `Z` matches a letter, anything else is a literal character.
5
+ *
6
+ * @example
7
+ * '(99) 99999-9999'
8
+ * ['(99) 9999-9999', '(99) 99999-9999']
9
+ */
10
+ type MaskPattern = string | string[];
11
+ /** Low-level mask processor. Tracks caret position after masking. */
12
+ declare class Mask {
13
+ /** Caret position after `process()` runs. */
14
+ caret: number;
15
+ private readonly _mask;
16
+ private readonly _value;
17
+ private _maskPos;
18
+ private _maskChar;
19
+ private _valuePos;
20
+ private _valueChar;
21
+ constructor(value: string, mask: string, caret?: number);
22
+ /** Apply the mask to the value and return the masked string. */
23
+ process(): string;
24
+ private _nextMaskChar;
25
+ private _nextValueChar;
26
+ }
27
+ /** Maximum allowed input length for the given mask. */
28
+ declare function getMaxLength(mask: MaskPattern): number;
29
+ /** Build a `Mask` instance, resolving array patterns by value length. */
30
+ declare function buildMask(value: string, mask: MaskPattern, caret?: number): Mask;
31
+ /** Apply a mask pattern to a raw value string and return the masked result. */
32
+ declare function process(value: string, mask: MaskPattern): string;
33
+ //#endregion
34
+ //#region src/bind.d.ts
35
+ /**
36
+ * Bind a mask pattern to an input element.
37
+ *
38
+ * Idempotent — calling `bind()` on an already-bound element has no effect.
39
+ * The element receives a `data-masked` attribute marking it as bound.
40
+ *
41
+ * @param input - Any `HTMLInputElement` or `Element` that behaves like one.
42
+ * @param mask - A single pattern string or an ordered array (shortest → longest).
43
+ * @param callback - Optional callback called with the masked value on every change.
44
+ */
45
+ declare function bind(input: HTMLInputElement | Element, mask: MaskPattern, callback?: ((value: string) => void) | null): void;
46
+ //#endregion
47
+ export { Mask, type MaskPattern, bind, buildMask, getMaxLength, process };
48
+ //# sourceMappingURL=mother-mask.d.cts.map
@@ -0,0 +1,48 @@
1
+ //#region src/mask.d.ts
2
+ /**
3
+ * Mask pattern — a single pattern string or an array ordered from shortest to longest.
4
+ * `9` matches a digit, `Z` matches a letter, anything else is a literal character.
5
+ *
6
+ * @example
7
+ * '(99) 99999-9999'
8
+ * ['(99) 9999-9999', '(99) 99999-9999']
9
+ */
10
+ type MaskPattern = string | string[];
11
+ /** Low-level mask processor. Tracks caret position after masking. */
12
+ declare class Mask {
13
+ /** Caret position after `process()` runs. */
14
+ caret: number;
15
+ private readonly _mask;
16
+ private readonly _value;
17
+ private _maskPos;
18
+ private _maskChar;
19
+ private _valuePos;
20
+ private _valueChar;
21
+ constructor(value: string, mask: string, caret?: number);
22
+ /** Apply the mask to the value and return the masked string. */
23
+ process(): string;
24
+ private _nextMaskChar;
25
+ private _nextValueChar;
26
+ }
27
+ /** Maximum allowed input length for the given mask. */
28
+ declare function getMaxLength(mask: MaskPattern): number;
29
+ /** Build a `Mask` instance, resolving array patterns by value length. */
30
+ declare function buildMask(value: string, mask: MaskPattern, caret?: number): Mask;
31
+ /** Apply a mask pattern to a raw value string and return the masked result. */
32
+ declare function process(value: string, mask: MaskPattern): string;
33
+ //#endregion
34
+ //#region src/bind.d.ts
35
+ /**
36
+ * Bind a mask pattern to an input element.
37
+ *
38
+ * Idempotent — calling `bind()` on an already-bound element has no effect.
39
+ * The element receives a `data-masked` attribute marking it as bound.
40
+ *
41
+ * @param input - Any `HTMLInputElement` or `Element` that behaves like one.
42
+ * @param mask - A single pattern string or an ordered array (shortest → longest).
43
+ * @param callback - Optional callback called with the masked value on every change.
44
+ */
45
+ declare function bind(input: HTMLInputElement | Element, mask: MaskPattern, callback?: ((value: string) => void) | null): void;
46
+ //#endregion
47
+ export { Mask, type MaskPattern, bind, buildMask, getMaxLength, process };
48
+ //# sourceMappingURL=mother-mask.d.mts.map
@@ -0,0 +1,2 @@
1
+ const e=/\D/,t=/[a-zA-Z]/;function n(t){return!e.test(t)}function r(e){return t.test(e)}var i=function(e){return e[e.NUMBER=0]=`NUMBER`,e[e.LETTER=1]=`LETTER`,e}(i||{}),a=class{caret;_mask;_value;_maskPos=-1;_maskChar=``;_valuePos=-1;_valueChar=``;constructor(e,t,n=0){this._value=e,this._mask=t,this.caret=n}process(){if(!this._value)return``;let e=``,t=[];for(;this._nextMaskChar();)if(typeof this._maskChar==`string`)t.push(this._maskChar);else if(this._nextValueChar(this._maskChar)&&this._valueChar){for(;t.length>0;)this._maskPos<=this.caret+1&&this._maskPos>=this.caret&&this.caret++,e+=t.shift();e+=this._valueChar}return e}_nextMaskChar(){if(this._maskPos++,this._maskPos>this._mask.length)return!1;let e=this._mask.charAt(this._maskPos);return e===`9`?this._maskChar=i.NUMBER:e===`Z`?this._maskChar=i.LETTER:this._maskChar=e,!0}_nextValueChar(e){if(this._valuePos++,this._valuePos>this._value.length)return!1;let t=this._value.charAt(this._valuePos);return this._valueChar=t,e===i.NUMBER&&n(t)||e===i.LETTER&&r(t)?!0:this._nextValueChar(e)}};function o(e,t){if(!Array.isArray(t))return t;let n=0;for(;n<t.length-1&&e.length>t[n].length;)n++;return t[n]}function s(e){return Array.isArray(e)?Math.max(...e.map(e=>e.length)):e.length}function c(e,t,n=0){return new a(e,o(e,t),n)}function l(e,t){return c(e,t).process()}const u=`data-masked`;let d;function f(){return d===void 0&&(d=typeof navigator<`u`&&/iPad|iPhone|iPod/i.test(navigator.userAgent)),d}function p(e,t,n=null){if(e.getAttribute(u)!==null)return;e.setAttribute(u,Array.isArray(t)?t.join(`|`):t),e.setAttribute(`autocomplete`,`off`),e.setAttribute(`autocorrect`,`off`),e.setAttribute(`autocapitalize`,`off`),e.setAttribute(`spellcheck`,`false`),e.setAttribute(`maxlength`,String(s(t)));let r=!1;e.addEventListener(`paste`,e=>{let r=e.target;requestAnimationFrame(()=>{r.value=c(r.value,t).process(),n?.(r.value)})}),e.addEventListener(f()?`keyup`:`keydown`,e=>{let i=e,a=i.target,o=a.value;if(!i.key){r=!0,requestAnimationFrame(()=>{let e=a.selectionStart??999,n=c(a.value,t,e);a.value=n.process(),a.setSelectionRange(n.caret,n.caret),requestAnimationFrame(()=>{r=!1})});return}if(i.key===`Meta`)return;let l=i.key===`Backspace`,u=i.key===`Delete`,d=i.key.length===1&&!i.ctrlKey&&!i.altKey&&!i.metaKey,p=i.key===`Unidentified`;if(d&&a.selectionStart===a.selectionEnd&&o.length>=s(t)&&!f()){i.preventDefault();return}if(r){i.preventDefault();return}r=!0,requestAnimationFrame(()=>{let e=a.selectionStart??999,i=c(a.value,t,e);if(a.value=i.process(),p){let t=a.value.length>o.length?i.caret:e;a.setSelectionRange(t,t)}else if(u){let t=o.length===a.value.length?e+1:e;a.setSelectionRange(t,t)}else l?a.setSelectionRange(e,e):d&&a.setSelectionRange(i.caret,i.caret);n?.(a.value),requestAnimationFrame(()=>{r=!1})})})}export{a as Mask,p as bind,c as buildMask,s as getMaxLength,l as process};
2
+ //# sourceMappingURL=mother-mask.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mother-mask.mjs","names":[],"sources":["../src/mask.ts","../src/bind.ts"],"sourcesContent":["/**\n * Mask pattern — a single pattern string or an array ordered from shortest to longest.\n * `9` matches a digit, `Z` matches a letter, anything else is a literal character.\n *\n * @example\n * '(99) 99999-9999'\n * ['(99) 9999-9999', '(99) 99999-9999']\n */\nexport type MaskPattern = string | string[]\n\nconst numberRegex = /\\D/\nconst letterRegex = /[a-zA-Z]/\n\nfunction isDigit(ch: string): boolean {\n return !numberRegex.test(ch)\n}\n\nfunction isLetter(ch: string): boolean {\n return letterRegex.test(ch)\n}\n\nenum CharType {\n NUMBER,\n LETTER,\n}\n\n/** Low-level mask processor. Tracks caret position after masking. */\nexport class Mask {\n /** Caret position after `process()` runs. */\n caret: number\n\n private readonly _mask: string\n private readonly _value: string\n\n private _maskPos = -1\n private _maskChar: string | CharType = ''\n private _valuePos = -1\n private _valueChar = ''\n\n constructor(value: string, mask: string, caret = 0) {\n this._value = value\n this._mask = mask\n this.caret = caret\n }\n\n /** Apply the mask to the value and return the masked string. */\n process(): string {\n if (!this._value) return ''\n\n let output = ''\n const pending: string[] = []\n\n while (this._nextMaskChar()) {\n if (typeof this._maskChar === 'string') {\n pending.push(this._maskChar)\n } else if (this._nextValueChar(this._maskChar) && this._valueChar) {\n while (pending.length > 0) {\n if (this._maskPos <= this.caret + 1 && this._maskPos >= this.caret) {\n this.caret++\n }\n output += pending.shift()\n }\n output += this._valueChar\n }\n }\n\n return output\n }\n\n private _nextMaskChar(): boolean {\n this._maskPos++\n if (this._maskPos > this._mask.length) return false\n\n const ch = this._mask.charAt(this._maskPos)\n if (ch === '9') {\n this._maskChar = CharType.NUMBER\n } else if (ch === 'Z') {\n this._maskChar = CharType.LETTER\n } else {\n this._maskChar = ch\n }\n return true\n }\n\n private _nextValueChar(type: CharType): boolean {\n this._valuePos++\n if (this._valuePos > this._value.length) return false\n\n const ch = this._value.charAt(this._valuePos)\n this._valueChar = ch\n\n if (type === CharType.NUMBER && isDigit(ch)) return true\n if (type === CharType.LETTER && isLetter(ch)) return true\n\n return this._nextValueChar(type)\n }\n}\n\n/** Select the right mask string for the current value length. */\nfunction resolveMask(value: string, mask: MaskPattern): string {\n if (!Array.isArray(mask)) return mask\n\n let i = 0\n while (i < mask.length - 1 && value.length > mask[i].length) {\n i++\n }\n return mask[i]\n}\n\n/** Maximum allowed input length for the given mask. */\nexport function getMaxLength(mask: MaskPattern): number {\n if (Array.isArray(mask)) return Math.max(...mask.map((m) => m.length))\n return mask.length\n}\n\n/** Build a `Mask` instance, resolving array patterns by value length. */\nexport function buildMask(value: string, mask: MaskPattern, caret = 0): Mask {\n return new Mask(value, resolveMask(value, mask), caret)\n}\n\n/** Apply a mask pattern to a raw value string and return the masked result. */\nexport function process(value: string, mask: MaskPattern): string {\n return buildMask(value, mask).process()\n}\n","import type { MaskPattern } from './mask'\nimport { buildMask, getMaxLength } from './mask'\n\nconst MASKED_ATTR = 'data-masked'\n\nlet cachedIsIos: boolean | undefined\n\nfunction isIos(): boolean {\n if (cachedIsIos !== undefined) return cachedIsIos\n cachedIsIos =\n typeof navigator !== 'undefined' && /iPad|iPhone|iPod/i.test(navigator.userAgent)\n return cachedIsIos\n}\n\n/**\n * Bind a mask pattern to an input element.\n *\n * Idempotent — calling `bind()` on an already-bound element has no effect.\n * The element receives a `data-masked` attribute marking it as bound.\n *\n * @param input - Any `HTMLInputElement` or `Element` that behaves like one.\n * @param mask - A single pattern string or an ordered array (shortest → longest).\n * @param callback - Optional callback called with the masked value on every change.\n */\nexport function bind(\n input: HTMLInputElement | Element,\n mask: MaskPattern,\n callback: ((value: string) => void) | null = null,\n): void {\n if (input.getAttribute(MASKED_ATTR) !== null) return\n\n input.setAttribute(MASKED_ATTR, Array.isArray(mask) ? mask.join('|') : mask)\n input.setAttribute('autocomplete', 'off')\n input.setAttribute('autocorrect', 'off')\n input.setAttribute('autocapitalize', 'off')\n input.setAttribute('spellcheck', 'false')\n input.setAttribute('maxlength', String(getMaxLength(mask)))\n\n let lockInput = false\n\n input.addEventListener('paste', (e: Event) => {\n const target = e.target as HTMLInputElement\n requestAnimationFrame(() => {\n const m = buildMask(target.value, mask)\n target.value = m.process()\n callback?.(target.value)\n })\n })\n\n input.addEventListener(isIos() ? 'keyup' : 'keydown', (e: Event) => {\n const ke = e as KeyboardEvent\n const target = ke.target as HTMLInputElement\n const oldValue = target.value\n\n // Older Android WebViews may fire key events without a `key` value.\n if (!(ke as { key?: string }).key) {\n lockInput = true\n requestAnimationFrame(() => {\n const pos = target.selectionStart ?? 999\n const m = buildMask(target.value, mask, pos)\n target.value = m.process()\n target.setSelectionRange(m.caret, m.caret)\n requestAnimationFrame(() => {\n lockInput = false\n })\n })\n return\n }\n\n if (ke.key === 'Meta') return\n\n const isBackspace = ke.key === 'Backspace'\n const isDelete = ke.key === 'Delete'\n const isCharInsert = ke.key.length === 1 && !ke.ctrlKey && !ke.altKey && !ke.metaKey\n const isUnidentified = ke.key === 'Unidentified'\n\n // Block inserting when mask is full (desktop only — iOS handles this natively)\n if (isCharInsert && target.selectionStart === target.selectionEnd) {\n if (oldValue.length >= getMaxLength(mask) && !isIos()) {\n ke.preventDefault()\n return\n }\n }\n\n if (lockInput) {\n ke.preventDefault()\n return\n }\n\n lockInput = true\n requestAnimationFrame(() => {\n const pos = target.selectionStart ?? 999\n const m = buildMask(target.value, mask, pos)\n target.value = m.process()\n\n if (isUnidentified) {\n const newPos = target.value.length > oldValue.length ? m.caret : pos\n target.setSelectionRange(newPos, newPos)\n } else if (isDelete) {\n const newPos = oldValue.length === target.value.length ? pos + 1 : pos\n target.setSelectionRange(newPos, newPos)\n } else if (isBackspace) {\n target.setSelectionRange(pos, pos)\n } else if (isCharInsert) {\n target.setSelectionRange(m.caret, m.caret)\n }\n\n callback?.(target.value)\n requestAnimationFrame(() => {\n lockInput = false\n })\n })\n })\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ (function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports):typeof define==`function`&&define.amd?define([`exports`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.MotherMask={}))})(this,function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});let t=/\D/,n=/[a-zA-Z]/;function r(e){return!t.test(e)}function i(e){return n.test(e)}var a=function(e){return e[e.NUMBER=0]=`NUMBER`,e[e.LETTER=1]=`LETTER`,e}(a||{}),o=class{caret;_mask;_value;_maskPos=-1;_maskChar=``;_valuePos=-1;_valueChar=``;constructor(e,t,n=0){this._value=e,this._mask=t,this.caret=n}process(){if(!this._value)return``;let e=``,t=[];for(;this._nextMaskChar();)if(typeof this._maskChar==`string`)t.push(this._maskChar);else if(this._nextValueChar(this._maskChar)&&this._valueChar){for(;t.length>0;)this._maskPos<=this.caret+1&&this._maskPos>=this.caret&&this.caret++,e+=t.shift();e+=this._valueChar}return e}_nextMaskChar(){if(this._maskPos++,this._maskPos>this._mask.length)return!1;let e=this._mask.charAt(this._maskPos);return e===`9`?this._maskChar=a.NUMBER:e===`Z`?this._maskChar=a.LETTER:this._maskChar=e,!0}_nextValueChar(e){if(this._valuePos++,this._valuePos>this._value.length)return!1;let t=this._value.charAt(this._valuePos);return this._valueChar=t,e===a.NUMBER&&r(t)||e===a.LETTER&&i(t)?!0:this._nextValueChar(e)}};function s(e,t){if(!Array.isArray(t))return t;let n=0;for(;n<t.length-1&&e.length>t[n].length;)n++;return t[n]}function c(e){return Array.isArray(e)?Math.max(...e.map(e=>e.length)):e.length}function l(e,t,n=0){return new o(e,s(e,t),n)}function u(e,t){return l(e,t).process()}let d=`data-masked`,f;function p(){return f===void 0&&(f=typeof navigator<`u`&&/iPad|iPhone|iPod/i.test(navigator.userAgent)),f}function m(e,t,n=null){if(e.getAttribute(d)!==null)return;e.setAttribute(d,Array.isArray(t)?t.join(`|`):t),e.setAttribute(`autocomplete`,`off`),e.setAttribute(`autocorrect`,`off`),e.setAttribute(`autocapitalize`,`off`),e.setAttribute(`spellcheck`,`false`),e.setAttribute(`maxlength`,String(c(t)));let r=!1;e.addEventListener(`paste`,e=>{let r=e.target;requestAnimationFrame(()=>{r.value=l(r.value,t).process(),n?.(r.value)})}),e.addEventListener(p()?`keyup`:`keydown`,e=>{let i=e,a=i.target,o=a.value;if(!i.key){r=!0,requestAnimationFrame(()=>{let e=a.selectionStart??999,n=l(a.value,t,e);a.value=n.process(),a.setSelectionRange(n.caret,n.caret),requestAnimationFrame(()=>{r=!1})});return}if(i.key===`Meta`)return;let s=i.key===`Backspace`,u=i.key===`Delete`,d=i.key.length===1&&!i.ctrlKey&&!i.altKey&&!i.metaKey,f=i.key===`Unidentified`;if(d&&a.selectionStart===a.selectionEnd&&o.length>=c(t)&&!p()){i.preventDefault();return}if(r){i.preventDefault();return}r=!0,requestAnimationFrame(()=>{let e=a.selectionStart??999,i=l(a.value,t,e);if(a.value=i.process(),f){let t=a.value.length>o.length?i.caret:e;a.setSelectionRange(t,t)}else if(u){let t=o.length===a.value.length?e+1:e;a.setSelectionRange(t,t)}else s?a.setSelectionRange(e,e):d&&a.setSelectionRange(i.caret,i.caret);n?.(a.value),requestAnimationFrame(()=>{r=!1})})})}e.Mask=o,e.bind=m,e.buildMask=l,e.getMaxLength=c,e.process=u});
2
+ //# sourceMappingURL=mother-mask.umd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mother-mask.umd.js","names":[],"sources":["../src/mask.ts","../src/bind.ts"],"sourcesContent":["/**\n * Mask pattern — a single pattern string or an array ordered from shortest to longest.\n * `9` matches a digit, `Z` matches a letter, anything else is a literal character.\n *\n * @example\n * '(99) 99999-9999'\n * ['(99) 9999-9999', '(99) 99999-9999']\n */\nexport type MaskPattern = string | string[]\n\nconst numberRegex = /\\D/\nconst letterRegex = /[a-zA-Z]/\n\nfunction isDigit(ch: string): boolean {\n return !numberRegex.test(ch)\n}\n\nfunction isLetter(ch: string): boolean {\n return letterRegex.test(ch)\n}\n\nenum CharType {\n NUMBER,\n LETTER,\n}\n\n/** Low-level mask processor. Tracks caret position after masking. */\nexport class Mask {\n /** Caret position after `process()` runs. */\n caret: number\n\n private readonly _mask: string\n private readonly _value: string\n\n private _maskPos = -1\n private _maskChar: string | CharType = ''\n private _valuePos = -1\n private _valueChar = ''\n\n constructor(value: string, mask: string, caret = 0) {\n this._value = value\n this._mask = mask\n this.caret = caret\n }\n\n /** Apply the mask to the value and return the masked string. */\n process(): string {\n if (!this._value) return ''\n\n let output = ''\n const pending: string[] = []\n\n while (this._nextMaskChar()) {\n if (typeof this._maskChar === 'string') {\n pending.push(this._maskChar)\n } else if (this._nextValueChar(this._maskChar) && this._valueChar) {\n while (pending.length > 0) {\n if (this._maskPos <= this.caret + 1 && this._maskPos >= this.caret) {\n this.caret++\n }\n output += pending.shift()\n }\n output += this._valueChar\n }\n }\n\n return output\n }\n\n private _nextMaskChar(): boolean {\n this._maskPos++\n if (this._maskPos > this._mask.length) return false\n\n const ch = this._mask.charAt(this._maskPos)\n if (ch === '9') {\n this._maskChar = CharType.NUMBER\n } else if (ch === 'Z') {\n this._maskChar = CharType.LETTER\n } else {\n this._maskChar = ch\n }\n return true\n }\n\n private _nextValueChar(type: CharType): boolean {\n this._valuePos++\n if (this._valuePos > this._value.length) return false\n\n const ch = this._value.charAt(this._valuePos)\n this._valueChar = ch\n\n if (type === CharType.NUMBER && isDigit(ch)) return true\n if (type === CharType.LETTER && isLetter(ch)) return true\n\n return this._nextValueChar(type)\n }\n}\n\n/** Select the right mask string for the current value length. */\nfunction resolveMask(value: string, mask: MaskPattern): string {\n if (!Array.isArray(mask)) return mask\n\n let i = 0\n while (i < mask.length - 1 && value.length > mask[i].length) {\n i++\n }\n return mask[i]\n}\n\n/** Maximum allowed input length for the given mask. */\nexport function getMaxLength(mask: MaskPattern): number {\n if (Array.isArray(mask)) return Math.max(...mask.map((m) => m.length))\n return mask.length\n}\n\n/** Build a `Mask` instance, resolving array patterns by value length. */\nexport function buildMask(value: string, mask: MaskPattern, caret = 0): Mask {\n return new Mask(value, resolveMask(value, mask), caret)\n}\n\n/** Apply a mask pattern to a raw value string and return the masked result. */\nexport function process(value: string, mask: MaskPattern): string {\n return buildMask(value, mask).process()\n}\n","import type { MaskPattern } from './mask'\nimport { buildMask, getMaxLength } from './mask'\n\nconst MASKED_ATTR = 'data-masked'\n\nlet cachedIsIos: boolean | undefined\n\nfunction isIos(): boolean {\n if (cachedIsIos !== undefined) return cachedIsIos\n cachedIsIos =\n typeof navigator !== 'undefined' && /iPad|iPhone|iPod/i.test(navigator.userAgent)\n return cachedIsIos\n}\n\n/**\n * Bind a mask pattern to an input element.\n *\n * Idempotent — calling `bind()` on an already-bound element has no effect.\n * The element receives a `data-masked` attribute marking it as bound.\n *\n * @param input - Any `HTMLInputElement` or `Element` that behaves like one.\n * @param mask - A single pattern string or an ordered array (shortest → longest).\n * @param callback - Optional callback called with the masked value on every change.\n */\nexport function bind(\n input: HTMLInputElement | Element,\n mask: MaskPattern,\n callback: ((value: string) => void) | null = null,\n): void {\n if (input.getAttribute(MASKED_ATTR) !== null) return\n\n input.setAttribute(MASKED_ATTR, Array.isArray(mask) ? mask.join('|') : mask)\n input.setAttribute('autocomplete', 'off')\n input.setAttribute('autocorrect', 'off')\n input.setAttribute('autocapitalize', 'off')\n input.setAttribute('spellcheck', 'false')\n input.setAttribute('maxlength', String(getMaxLength(mask)))\n\n let lockInput = false\n\n input.addEventListener('paste', (e: Event) => {\n const target = e.target as HTMLInputElement\n requestAnimationFrame(() => {\n const m = buildMask(target.value, mask)\n target.value = m.process()\n callback?.(target.value)\n })\n })\n\n input.addEventListener(isIos() ? 'keyup' : 'keydown', (e: Event) => {\n const ke = e as KeyboardEvent\n const target = ke.target as HTMLInputElement\n const oldValue = target.value\n\n // Older Android WebViews may fire key events without a `key` value.\n if (!(ke as { key?: string }).key) {\n lockInput = true\n requestAnimationFrame(() => {\n const pos = target.selectionStart ?? 999\n const m = buildMask(target.value, mask, pos)\n target.value = m.process()\n target.setSelectionRange(m.caret, m.caret)\n requestAnimationFrame(() => {\n lockInput = false\n })\n })\n return\n }\n\n if (ke.key === 'Meta') return\n\n const isBackspace = ke.key === 'Backspace'\n const isDelete = ke.key === 'Delete'\n const isCharInsert = ke.key.length === 1 && !ke.ctrlKey && !ke.altKey && !ke.metaKey\n const isUnidentified = ke.key === 'Unidentified'\n\n // Block inserting when mask is full (desktop only — iOS handles this natively)\n if (isCharInsert && target.selectionStart === target.selectionEnd) {\n if (oldValue.length >= getMaxLength(mask) && !isIos()) {\n ke.preventDefault()\n return\n }\n }\n\n if (lockInput) {\n ke.preventDefault()\n return\n }\n\n lockInput = true\n requestAnimationFrame(() => {\n const pos = target.selectionStart ?? 999\n const m = buildMask(target.value, mask, pos)\n target.value = m.process()\n\n if (isUnidentified) {\n const newPos = target.value.length > oldValue.length ? m.caret : pos\n target.setSelectionRange(newPos, newPos)\n } else if (isDelete) {\n const newPos = oldValue.length === target.value.length ? pos + 1 : pos\n target.setSelectionRange(newPos, newPos)\n } else if (isBackspace) {\n target.setSelectionRange(pos, pos)\n } else if (isCharInsert) {\n target.setSelectionRange(m.caret, m.caret)\n }\n\n callback?.(target.value)\n requestAnimationFrame(() => {\n lockInput = false\n })\n })\n })\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,58 +1,69 @@
1
1
  {
2
2
  "name": "mother-mask",
3
- "version": "1.4.2",
4
- "description": "",
5
- "main": "lib/main",
6
- "types": "@types/main",
7
- "scripts": {
8
- "link": "",
9
- "test": "jest --no-cache",
10
- "dev": "npm-run-all --parallel tsc-w webpack-dev-w && exit 0",
11
- "tsc-w": "tsc -w",
12
- "webpack-dev": "webpack lib/main.js --progress --color",
13
- "webpack-prod": "webpack lib/main.js -p --progress --color",
14
- "webpack-dev-w": "webpack lib/main.js -w --progress --color",
15
- "webpack-prod-w": "webpack lib/main.js -w -p --progress --color",
16
- "build": "yarn run clean && tsc && yarn run webpack-dev && yarn run webpack-prod && exit 0",
17
- "clean": "rimraf lib/* dist/* @types/* && exit 0",
18
- "clean-node": "rimraf package-lock.json node_modules/* && exit 0"
3
+ "private": false,
4
+ "version": "2.0.2",
5
+ "type": "module",
6
+ "description": "Lightweight input mask library for browsers",
7
+ "author": "Danilo Celestino de Castro <dan2dev>",
8
+ "license": "MIT",
9
+ "keywords": [
10
+ "input",
11
+ "mask",
12
+ "form"
13
+ ],
14
+ "main": "./dist/mother-mask.cjs",
15
+ "module": "./dist/mother-mask.mjs",
16
+ "browser": "./dist/mother-mask.umd.js",
17
+ "types": "./dist/mother-mask.d.mts",
18
+ "exports": {
19
+ ".": {
20
+ "import": {
21
+ "types": "./dist/mother-mask.d.mts",
22
+ "default": "./dist/mother-mask.mjs"
23
+ },
24
+ "require": {
25
+ "types": "./dist/mother-mask.d.cts",
26
+ "default": "./dist/mother-mask.cjs"
27
+ }
28
+ },
29
+ "./package.json": "./package.json"
30
+ },
31
+ "files": [
32
+ "dist"
33
+ ],
34
+ "devDependencies": {
35
+ "@eslint/js": "^10.0.1",
36
+ "@eslint/json": "^1.2.0",
37
+ "@eslint/markdown": "^8.0.1",
38
+ "@types/node": "^25.5.2",
39
+ "@typescript/native-preview": "7.0.0-dev.20260405.1",
40
+ "@vitest/coverage-v8": "^4.1.2",
41
+ "bumpp": "^11.0.1",
42
+ "eslint": "^10.1.0",
43
+ "globals": "^17.4.0",
44
+ "jsdom": "^29.0.1",
45
+ "tsdown": "^0.21.7",
46
+ "typescript": "^6.0.2",
47
+ "typescript-eslint": "^8.58.0",
48
+ "vitest": "^4.1.2"
19
49
  },
20
50
  "repository": {
21
51
  "type": "git",
22
52
  "url": "git+https://github.com/dan2dev/mother-mask.git"
23
53
  },
24
- "keywords": [
25
- "input",
26
- "mask"
27
- ],
28
- "author": "Dan C Castro",
29
- "license": "MIT",
30
54
  "bugs": {
31
55
  "url": "https://github.com/dan2dev/mother-mask/issues"
32
56
  },
33
57
  "homepage": "https://github.com/dan2dev/mother-mask#readme",
34
- "dependencies": {
35
- "@types/setimmediate": "^1.0.0",
36
- "setimmediate": "^1.0.5",
37
- "utility-collection": "^2.1.3"
38
- },
39
- "devDependencies": {
40
- "@babel/core": "^7.0.0-beta.46",
41
- "@babel/preset-env": "^7.0.0-beta.46",
42
- "@types/jest": "^22.2.2",
43
- "@types/jquery": "^3.3.1",
44
- "@types/jsx-chai": "^3.0.16",
45
- "@types/lodash": "^4.14.107",
46
- "@types/node": "^13.5.0",
47
- "@types/react": "^16.3.12",
48
- "@types/react-dom": "^16.0.5",
49
- "@types/window-or-global": "^1.0.0",
50
- "babel-core": "^6.26.0",
51
- "npm-run-all": "^4.1.5",
52
- "rimraf": "^2.6.2",
53
- "run-sequence": "^2.2.1",
54
- "typescript": "^2.8.3",
55
- "webpack": "^4.41.5",
56
- "webpack-cli": "^3.3.10"
58
+ "scripts": {
59
+ "build": "tsdown",
60
+ "dev": "tsdown --watch",
61
+ "clean": "rm -rf dist *.tsbuildinfo",
62
+ "test": "vitest run --coverage",
63
+ "test:watch": "vitest --watch --coverage",
64
+ "typecheck": "tsc --noEmit",
65
+ "lint": "eslint .",
66
+ "lint:fix": "eslint . --fix",
67
+ "release": "bumpp"
57
68
  }
58
69
  }
package/.1.gitignore DELETED
@@ -1,7 +0,0 @@
1
- node_modules
2
- .git
3
- .vs
4
- .vscode
5
- desktop.ini
6
- bin
7
- obj
package/.eslintrc.json DELETED
@@ -1,14 +0,0 @@
1
- {
2
- "parserOptions": {
3
- "ecmaVersion": 6,
4
- "sourceType": "module",
5
- "ecmaFeatures": {
6
- "jsx": true
7
- }
8
- },
9
- "rules": {
10
- "indent": "off",
11
- "no-tabs": "off",
12
- "semi": "off"
13
- }
14
- }
package/@types/main.d.ts DELETED
@@ -1,5 +0,0 @@
1
- export declare module MotherMask {
2
- function process(value: string, pattern: string | string[]): string;
3
- function bind(input: HTMLInputElement | HTMLElement | Element, pattern: string | string[], callback?: ((value: string) => void) | null): void;
4
- }
5
- export default MotherMask;
@@ -1,34 +0,0 @@
1
- export declare module Is {
2
- function empty(value: any): boolean;
3
- function number(value: string): boolean;
4
- function letter(value: string): boolean;
5
- }
6
- export declare namespace Simple {
7
- enum CharType {
8
- NUMBER = 0,
9
- LETTER = 1
10
- }
11
- interface IMaskChar {
12
- position: number;
13
- char: string | null | CharType;
14
- }
15
- interface IValueChar {
16
- position: number;
17
- char: string | null;
18
- }
19
- class Mask {
20
- caret: number;
21
- private mask;
22
- private value;
23
- private maskChar;
24
- private valueChar;
25
- constructor(value: string, mask: string, caret?: number);
26
- process(): string;
27
- private nextIMaskChar;
28
- private nextIValueChar;
29
- }
30
- function process(value: string, mask: string | string[]): string;
31
- function maskBuilder(value: string, mask: string | string[], caret?: number): Mask;
32
- function bind(inputElement: HTMLInputElement | Element, mask: string | string[], callback?: ((output: string) => void) | null): void;
33
- }
34
- export default Simple;
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2017 Dan
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
package/dist/main.js DELETED
@@ -1 +0,0 @@
1
- !function(e){var t={};function r(n){if(t[n])return t[n].exports;var a=t[n]={i:n,l:!1,exports:{}};return e[n].call(a.exports,a,a.exports,r),a.l=!0,a.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var a in e)r.d(n,a,function(t){return e[t]}.bind(null,a));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=0)}([function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n,a=r(1);!function(e){e.process=function(e,t){return a.default.process(e,t)},e.bind=function(e,t,r){if(void 0===r&&(r=null),null===e.getAttribute("masked")){var n="";n=Array.isArray(t)?t.join("|"):t,e.setAttribute("masked",n),a.default.bind(e,t,r)}}}(n=t.MotherMask||(t.MotherMask={})),"undefined"!=typeof window&&(window.MotherMask=n),t.default=n},function(e,t,r){"use strict";var n,a;Object.defineProperty(t,"__esModule",{value:!0}),function(e){e.empty=function(e){return null==e||""===e};var t=/\D/;e.number=function(e){return!t.test(e)};var r=/[a-zA-Z]/;e.letter=function(e){return r.test(e)}}(n=t.Is||(t.Is={})),function(e){var t;function r(){return void 0!==t?t:t=/iPad|iPhone|iPod/i.test(navigator.userAgent)}!function(e){e[e.NUMBER=0]="NUMBER",e[e.LETTER=1]="LETTER"}(e.CharType||(e.CharType={}));var a=function(){function t(e,t,r){void 0===r&&(r=0),this.caret=0,this.maskChar={position:-1,char:null},this.valueChar={position:-1,char:null},this.value=e,this.mask=t,this.caret=r}return t.prototype.process=function(){if(n.empty(this.value))return"";for(var e="",t=(this.caret,[]);this.nextIMaskChar();)if("string"==typeof this.maskChar.char)t.push(this.maskChar.char);else if(this.nextIValueChar(this.maskChar.char)&&!n.empty(this.valueChar.char)){for(;t.length>0;)this.maskChar.position<=this.caret+1&&this.maskChar.position>=this.caret&&this.caret++,e+=t.shift();e+=this.valueChar.char}return e},t.prototype.nextIMaskChar=function(){return this.maskChar.position++,!(this.maskChar.position>this.mask.length)&&(this.maskChar.char=this.mask.charAt(this.maskChar.position),"9"===this.maskChar.char?this.maskChar.char=e.CharType.NUMBER:"Z"===this.maskChar.char&&(this.maskChar.char=e.CharType.LETTER),!0)},t.prototype.nextIValueChar=function(t){if(this.valueChar.position++,this.valueChar.position>this.value.length)return!1;if(this.valueChar.char=this.value.charAt(this.valueChar.position),t===e.CharType.NUMBER){if(n.number(this.valueChar.char))return!0}else if(t===e.CharType.LETTER&&n.letter(this.valueChar.char))return!0;return this.nextIValueChar(t)},t}();function i(e){var t=0;return Array.isArray(e)?e.forEach((function(e){t<e.length&&(t=e.length)})):t=e.length,t}function o(e,t,r){return void 0===r&&(r=0),new a(e,function(e,t){if(Array.isArray(t)){for(var r=0;e.length>t[r].length&&r<t.length;)r++;return t[r]}return t}(e,t),r)}e.Mask=a,e.process=function(e,t){return o(e,t).process()},e.maskBuilder=o;var u=!1;e.bind=function(e,t,n){void 0===n&&(n=null),e.setAttribute("autocomplete","off"),e.setAttribute("autocorrect","off"),e.setAttribute("autocapitalize","off"),e.setAttribute("spellcheck","false"),e.setAttribute("maxlength",i(t).toString()),e.addEventListener("paste",(function(e){var r=e.target;r.value.toString();requestAnimationFrame((function(){var e=o(r.value,t);r.value=e.process(),null!=n&&n(r.value)}))})),e.addEventListener(r()?"keyup":"keydown",(function(e){var a=e.target;if(void 0===e.key)u=!0,requestAnimationFrame((function(){var r=a.selectionStart||999,n=o(a.value,t,r);a.value=n.process(),8===e.which?a.setSelectionRange(r,r):a.setSelectionRange(n.caret,n.caret),requestAnimationFrame((function(){u=!1}))}));else{var s=a.value.toString(),l=(void 0===e.key||e.key,void 0===e.key||("Backspace"===e.key||8===e.keyCode)),h=void 0===e.key||"Delete"===e.key,c=void 0===e.key||1===e.key.length&&!e.ctrlKey&&!e.altKey&&!e.metaKey,f=void 0!==e.key&&"Unidentified"===e.key;if(c&&a.selectionStart===a.selectionEnd&&s.length>=i(t)&&!r())return e.preventDefault(),!1;if(u)return void e.preventDefault();u=!0,requestAnimationFrame((function(){var e=a.selectionStart||999,r=o(a.value,t,e);a.value=r.process(),a.value=a.value,f?a.value.length>s.length?a.setSelectionRange(r.caret,r.caret):a.setSelectionRange(e,e):(h&&(s.length===a.value.length?a.setSelectionRange(e+1,e+1):a.setSelectionRange(e,e)),l&&a.setSelectionRange(e,e),c&&a.setSelectionRange(r.caret,r.caret)),null!=n&&n(a.value),requestAnimationFrame((function(){u=!1}))}))}}))}}(a=t.Simple||(t.Simple={})),t.default=a}]);