mother-mask 1.4.1 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -20
- package/dist/mother-mask.cjs +2 -0
- package/dist/mother-mask.cjs.map +1 -0
- package/dist/mother-mask.d.cts +48 -0
- package/dist/mother-mask.d.mts +48 -0
- package/dist/mother-mask.mjs +2 -0
- package/dist/mother-mask.mjs.map +1 -0
- package/dist/mother-mask.umd.js +2 -0
- package/dist/mother-mask.umd.js.map +1 -0
- package/package.json +56 -45
- package/.1.gitignore +0 -7
- package/.eslintrc.json +0 -14
- package/@types/main.d.ts +0 -5
- package/@types/simple.d.ts +0 -34
- package/LICENSE +0 -21
- package/dist/main.js +0 -1
- package/gulpfile.js +0 -119
- package/lib/main.js +0 -33
- package/lib/main.js.map +0 -1
- package/lib/simple.js +0 -276
- package/lib/simple.js.map +0 -1
- package/src/main.test.ts +0 -1
- package/src/main.ts +0 -29
- package/src/simple.ts +0 -264
- package/test/index.html +0 -58
package/README.md
CHANGED
|
@@ -1,30 +1,23 @@
|
|
|
1
|
-
#
|
|
2
|
-
The Mother-Mask is a simple and definitive Js library to implement text mask using a pattern.
|
|
1
|
+
# tsdown-starter
|
|
3
2
|
|
|
3
|
+
A starter for creating a TypeScript package.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Development
|
|
6
|
+
|
|
7
|
+
- Install dependencies:
|
|
6
8
|
|
|
7
9
|
```bash
|
|
8
|
-
|
|
10
|
+
npm install
|
|
9
11
|
```
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
```javascript
|
|
14
|
-
// get the input element
|
|
15
|
-
// vanilla javascript
|
|
16
|
-
var phoneInputElement = document.getElementById("myphoneinput");
|
|
17
|
-
// Jquery
|
|
18
|
-
var phoneInputElement = $("#myphoneinput")[0];
|
|
19
|
-
|
|
20
|
-
// bind the element with the mask
|
|
21
|
-
MotherMask.bind(phoneInputElement, "999.999.999-99");
|
|
22
|
-
|
|
23
|
-
// create dynamic mask
|
|
24
|
-
MotherMask.bind(phoneInputElement, ["(99) 9999-9999", "(99) 99999-9999"]);
|
|
13
|
+
- Run the unit tests:
|
|
25
14
|
|
|
15
|
+
```bash
|
|
16
|
+
npm run test
|
|
26
17
|
```
|
|
27
18
|
|
|
28
|
-
|
|
19
|
+
- Build the library:
|
|
29
20
|
|
|
30
|
-
|
|
21
|
+
```bash
|
|
22
|
+
npm run build
|
|
23
|
+
```
|
|
@@ -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
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
3
|
+
"private": false,
|
|
4
|
+
"version": "2.0.1",
|
|
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
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
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
package/.eslintrc.json
DELETED
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;
|
package/@types/simple.d.ts
DELETED
|
@@ -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={})),void 0!==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}]);
|
package/gulpfile.js
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
// core
|
|
2
|
-
var fs = require('fs');
|
|
3
|
-
var pack = JSON.parse(fs.readFileSync('./package.json'));
|
|
4
|
-
|
|
5
|
-
var
|
|
6
|
-
gulp = require('gulp'),
|
|
7
|
-
browserify = require('gulp-browserify'),
|
|
8
|
-
babel = require('gulp-babel'),
|
|
9
|
-
rename = require('gulp-rename'),
|
|
10
|
-
uglify = require('gulp-uglify'),
|
|
11
|
-
minify = require('gulp-minify'),
|
|
12
|
-
pump = require('pump'),
|
|
13
|
-
runSequence = require('run-sequence'),
|
|
14
|
-
del = require('del'),
|
|
15
|
-
merge = require('merge2');
|
|
16
|
-
// typescript
|
|
17
|
-
var
|
|
18
|
-
ts = require("gulp-typescript"),
|
|
19
|
-
tsProject = ts.createProject("tsconfig.json");
|
|
20
|
-
// styles
|
|
21
|
-
var
|
|
22
|
-
sassImport = require('gulp-sass-import'),
|
|
23
|
-
sass = require('gulp-sass'),
|
|
24
|
-
rename = require('gulp-rename'),
|
|
25
|
-
sourcemaps = require('gulp-sourcemaps'),
|
|
26
|
-
cleanCSS = require('gulp-clean-css');
|
|
27
|
-
// browserSync
|
|
28
|
-
var browserSync = require('browser-sync').create();
|
|
29
|
-
// Static server
|
|
30
|
-
gulp.task('browse-sync', () => {
|
|
31
|
-
browserSync.init({
|
|
32
|
-
server: {
|
|
33
|
-
baseDir: "./"
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
gulp.task('clean', () => {
|
|
39
|
-
return del([
|
|
40
|
-
'@types/**/*',
|
|
41
|
-
'dist/**/*',
|
|
42
|
-
'lib/**/*',
|
|
43
|
-
'!dist/do-not-delete-this.json'
|
|
44
|
-
]);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
gulp.task('dist', () => {
|
|
48
|
-
runSequence('clean', ['typescript', 'sass'], ['lib_css', 'lib_js'], () => {
|
|
49
|
-
console.log("well, it's done");
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
gulp.task('default', ["dist"], () => {
|
|
54
|
-
|
|
55
|
-
gulp.watch('src/**/*.scss', ['sass']);
|
|
56
|
-
gulp.watch('src/**/*.ts', ['typescript']);
|
|
57
|
-
|
|
58
|
-
gulp.watch('lib/main.css', ['lib_css']);
|
|
59
|
-
gulp.watch('lib/**/*.js', ['lib_js']);
|
|
60
|
-
|
|
61
|
-
gulp.watch(["**/*.html", "dist/*.js"]).on('change', browserSync.reload);
|
|
62
|
-
});
|
|
63
|
-
// src => lib
|
|
64
|
-
gulp.task('sass', () => {
|
|
65
|
-
return gulp
|
|
66
|
-
.src(['./src/**/*.scss', './src/**/*.css'])
|
|
67
|
-
.pipe(sourcemaps.init())
|
|
68
|
-
.pipe(sass().on('error', sass.logError))
|
|
69
|
-
.pipe(sourcemaps.write('./'))
|
|
70
|
-
.pipe(gulp.dest('./lib'));
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
gulp.task("typescript", () => {
|
|
74
|
-
// const tsResult = tsProject.src(["src/**/*.ts", "src/**/*.tsx"])
|
|
75
|
-
// .pipe(sourcemaps.init())
|
|
76
|
-
// .pipe(tsProject());
|
|
77
|
-
const tsResult = tsProject.src()
|
|
78
|
-
.pipe(sourcemaps.init())
|
|
79
|
-
.pipe(tsProject());
|
|
80
|
-
return merge([
|
|
81
|
-
tsResult.js.pipe(sourcemaps.write()).pipe(gulp.dest("./lib")),
|
|
82
|
-
tsResult.dts.pipe(gulp.dest("./@types"))]
|
|
83
|
-
);
|
|
84
|
-
});
|
|
85
|
-
// lib => dist
|
|
86
|
-
gulp.task('lib_css', () => {
|
|
87
|
-
return gulp.src('./lib/main.css')
|
|
88
|
-
.pipe(cleanCSS({
|
|
89
|
-
format: 'beautify',
|
|
90
|
-
compatibility: 'ie9'
|
|
91
|
-
}))
|
|
92
|
-
.pipe(rename(pack.name + ".css"))
|
|
93
|
-
.pipe(gulp.dest('dist'))
|
|
94
|
-
.pipe(cleanCSS({
|
|
95
|
-
compatibility: 'ie9'
|
|
96
|
-
}))
|
|
97
|
-
.pipe(rename(pack.name + ".min.css"))
|
|
98
|
-
.pipe(gulp.dest('dist'))
|
|
99
|
-
.pipe(browserSync.stream());
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
gulp.task('lib_js', () => {
|
|
103
|
-
var options = {
|
|
104
|
-
ext: {
|
|
105
|
-
min: ".min.js",
|
|
106
|
-
ignoreFiles: ['.combo.js', '.min.js']
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
return gulp.src('lib/main.js')
|
|
110
|
-
.pipe(browserify({
|
|
111
|
-
insertGlobals: false,
|
|
112
|
-
sourceMapsAbsolute: true,
|
|
113
|
-
presets: ["@babel/preset-env", "@babel/preset-react"]
|
|
114
|
-
}))
|
|
115
|
-
.pipe(rename(pack.name + ".js"))
|
|
116
|
-
.pipe(gulp.dest('./dist'))
|
|
117
|
-
.pipe(minify(options))
|
|
118
|
-
.pipe(gulp.dest('./dist'))
|
|
119
|
-
});
|
package/lib/main.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
var simple_1 = require("./simple");
|
|
4
|
-
// import "setimmediate";
|
|
5
|
-
var MotherMask;
|
|
6
|
-
(function (MotherMask) {
|
|
7
|
-
var MASKED = "masked";
|
|
8
|
-
function process(value, pattern) {
|
|
9
|
-
return simple_1.default.process(value, pattern);
|
|
10
|
-
}
|
|
11
|
-
MotherMask.process = process;
|
|
12
|
-
function bind(input, pattern, callback) {
|
|
13
|
-
if (callback === void 0) { callback = null; }
|
|
14
|
-
var masked = input.getAttribute(MASKED);
|
|
15
|
-
if (masked === null) {
|
|
16
|
-
var strPattern = "";
|
|
17
|
-
if (Array.isArray(pattern)) {
|
|
18
|
-
strPattern = pattern.join("|");
|
|
19
|
-
}
|
|
20
|
-
else {
|
|
21
|
-
strPattern = pattern;
|
|
22
|
-
}
|
|
23
|
-
input.setAttribute(MASKED, strPattern);
|
|
24
|
-
simple_1.default.bind(input, pattern, callback);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
MotherMask.bind = bind;
|
|
28
|
-
})(MotherMask = exports.MotherMask || (exports.MotherMask = {}));
|
|
29
|
-
if (window !== undefined) {
|
|
30
|
-
window.MotherMask = MotherMask;
|
|
31
|
-
}
|
|
32
|
-
exports.default = MotherMask;
|
|
33
|
-
//# sourceMappingURL=main.js.map
|
package/lib/main.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";;AAAA,mCAA8B;AAC9B,yBAAyB;AAEzB,IAAc,UAAU,CAqBvB;AArBD,WAAc,UAAU;IACtB,IAAM,MAAM,GAAG,QAAQ,CAAC;IACxB,iBAAwB,KAAa,EAAE,OAA0B;QAC/D,OAAO,gBAAM,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACxC,CAAC;IAFe,kBAAO,UAEtB,CAAA;IACD,cACE,KAA+C,EAC/C,OAA0B,EAC1B,QAAiD;QAAjD,yBAAA,EAAA,eAAiD;QACjD,IAAM,MAAM,GAAG,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QAC1C,IAAI,MAAM,KAAK,IAAI,EAAE;YACnB,IAAI,UAAU,GAAW,EAAE,CAAC;YAC5B,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;gBAC1B,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;aAChC;iBAAM;gBACL,UAAU,GAAG,OAAO,CAAC;aACtB;YACD,KAAK,CAAC,YAAY,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;YACvC,gBAAM,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;SACvC;IACH,CAAC;IAfe,eAAI,OAenB,CAAA;AACH,CAAC,EArBa,UAAU,GAAV,kBAAU,KAAV,kBAAU,QAqBvB;AACD,IAAI,MAAM,KAAK,SAAS,EAAE;IACvB,MAAc,CAAC,UAAU,GAAG,UAAU,CAAC;CACzC;AACD,kBAAe,UAAU,CAAC"}
|
package/lib/simple.js
DELETED
|
@@ -1,276 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
// made by Danilo Celestino de Castro (dan2dev)
|
|
4
|
-
// import { Is } from "utility-collection/src/is";
|
|
5
|
-
var Is;
|
|
6
|
-
(function (Is) {
|
|
7
|
-
function empty(value) {
|
|
8
|
-
if (value === undefined || value === null || value === "") {
|
|
9
|
-
return true;
|
|
10
|
-
}
|
|
11
|
-
else {
|
|
12
|
-
return false;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
Is.empty = empty;
|
|
16
|
-
// is Number
|
|
17
|
-
var numberRegex = /\D/;
|
|
18
|
-
function number(value) {
|
|
19
|
-
return !numberRegex.test(value);
|
|
20
|
-
}
|
|
21
|
-
Is.number = number;
|
|
22
|
-
// is Letter
|
|
23
|
-
var letterRegex = /[a-zA-Z]/;
|
|
24
|
-
function letter(value) {
|
|
25
|
-
return letterRegex.test(value);
|
|
26
|
-
}
|
|
27
|
-
Is.letter = letter;
|
|
28
|
-
})(Is = exports.Is || (exports.Is = {}));
|
|
29
|
-
var Simple;
|
|
30
|
-
(function (Simple) {
|
|
31
|
-
// detect ios for fix
|
|
32
|
-
var isIos;
|
|
33
|
-
function ios() {
|
|
34
|
-
if (isIos !== undefined) {
|
|
35
|
-
return isIos;
|
|
36
|
-
}
|
|
37
|
-
else {
|
|
38
|
-
isIos = /iPad|iPhone|iPod/i.test(navigator.userAgent);
|
|
39
|
-
return isIos;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
// ------
|
|
43
|
-
var CharType;
|
|
44
|
-
(function (CharType) {
|
|
45
|
-
CharType[CharType["NUMBER"] = 0] = "NUMBER";
|
|
46
|
-
CharType[CharType["LETTER"] = 1] = "LETTER";
|
|
47
|
-
})(CharType = Simple.CharType || (Simple.CharType = {}));
|
|
48
|
-
// -----------
|
|
49
|
-
var Mask = /** @class */ (function () {
|
|
50
|
-
// -----------------------
|
|
51
|
-
function Mask(value, mask, caret) {
|
|
52
|
-
if (caret === void 0) { caret = 0; }
|
|
53
|
-
this.caret = 0;
|
|
54
|
-
this.maskChar = {
|
|
55
|
-
position: -1,
|
|
56
|
-
char: null,
|
|
57
|
-
};
|
|
58
|
-
this.valueChar = {
|
|
59
|
-
position: -1,
|
|
60
|
-
char: null,
|
|
61
|
-
};
|
|
62
|
-
this.value = value;
|
|
63
|
-
this.mask = mask;
|
|
64
|
-
this.caret = caret;
|
|
65
|
-
}
|
|
66
|
-
Mask.prototype.process = function () {
|
|
67
|
-
if (Is.empty(this.value)) {
|
|
68
|
-
return "";
|
|
69
|
-
}
|
|
70
|
-
var output = "";
|
|
71
|
-
var oldCaret = this.caret;
|
|
72
|
-
var shadowLatestIMaskChars = [];
|
|
73
|
-
while (this.nextIMaskChar()) {
|
|
74
|
-
if (typeof this.maskChar.char === "string") {
|
|
75
|
-
shadowLatestIMaskChars.push(this.maskChar.char);
|
|
76
|
-
}
|
|
77
|
-
else {
|
|
78
|
-
if (this.nextIValueChar(this.maskChar.char) && !Is.empty(this.valueChar.char)) {
|
|
79
|
-
while (shadowLatestIMaskChars.length > 0) {
|
|
80
|
-
if (this.maskChar.position <= this.caret + 1 &&
|
|
81
|
-
this.maskChar.position >= this.caret) {
|
|
82
|
-
this.caret++;
|
|
83
|
-
}
|
|
84
|
-
output += shadowLatestIMaskChars.shift();
|
|
85
|
-
}
|
|
86
|
-
output += this.valueChar.char;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
return output;
|
|
91
|
-
};
|
|
92
|
-
Mask.prototype.nextIMaskChar = function () {
|
|
93
|
-
this.maskChar.position++;
|
|
94
|
-
if (this.maskChar.position > this.mask.length) {
|
|
95
|
-
return false;
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
// what to return
|
|
99
|
-
this.maskChar.char = this.mask.charAt(this.maskChar.position);
|
|
100
|
-
if (this.maskChar.char === "9") {
|
|
101
|
-
this.maskChar.char = Simple.CharType.NUMBER;
|
|
102
|
-
}
|
|
103
|
-
else if (this.maskChar.char === "Z") {
|
|
104
|
-
this.maskChar.char = Simple.CharType.LETTER;
|
|
105
|
-
}
|
|
106
|
-
return true;
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
// value
|
|
110
|
-
Mask.prototype.nextIValueChar = function (type) {
|
|
111
|
-
this.valueChar.position++;
|
|
112
|
-
if (this.valueChar.position > this.value.length) {
|
|
113
|
-
return false;
|
|
114
|
-
}
|
|
115
|
-
else {
|
|
116
|
-
this.valueChar.char = this.value.charAt(this.valueChar.position);
|
|
117
|
-
if (type === Simple.CharType.NUMBER) {
|
|
118
|
-
if (Is.number(this.valueChar.char)) {
|
|
119
|
-
return true;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
else if (type === Simple.CharType.LETTER) {
|
|
123
|
-
if (Is.letter(this.valueChar.char)) {
|
|
124
|
-
return true;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
return this.nextIValueChar(type);
|
|
128
|
-
}
|
|
129
|
-
};
|
|
130
|
-
return Mask;
|
|
131
|
-
}());
|
|
132
|
-
Simple.Mask = Mask;
|
|
133
|
-
function process(value, mask) {
|
|
134
|
-
var m = maskBuilder(value, mask);
|
|
135
|
-
return m.process();
|
|
136
|
-
}
|
|
137
|
-
Simple.process = process;
|
|
138
|
-
function getMaskString(value, mask) {
|
|
139
|
-
if (Array.isArray(mask)) {
|
|
140
|
-
var i = 0;
|
|
141
|
-
while (value.length > mask[i].length && i < mask.length) {
|
|
142
|
-
i++;
|
|
143
|
-
}
|
|
144
|
-
return mask[i];
|
|
145
|
-
}
|
|
146
|
-
else {
|
|
147
|
-
return mask;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
function getMaxLength(mask) {
|
|
151
|
-
var maxLength = 0;
|
|
152
|
-
if (Array.isArray(mask)) {
|
|
153
|
-
mask.forEach(function (m) {
|
|
154
|
-
if (maxLength < m.length) {
|
|
155
|
-
maxLength = m.length;
|
|
156
|
-
}
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
else {
|
|
160
|
-
maxLength = mask.length;
|
|
161
|
-
}
|
|
162
|
-
return maxLength;
|
|
163
|
-
}
|
|
164
|
-
function maskBuilder(value, mask, caret) {
|
|
165
|
-
if (caret === void 0) { caret = 0; }
|
|
166
|
-
return new Mask(value, getMaskString(value, mask), caret);
|
|
167
|
-
}
|
|
168
|
-
Simple.maskBuilder = maskBuilder;
|
|
169
|
-
var lockInput = false;
|
|
170
|
-
function bind(inputElement, mask, callback) {
|
|
171
|
-
if (callback === void 0) { callback = null; }
|
|
172
|
-
inputElement.setAttribute("autocomplete", "off");
|
|
173
|
-
inputElement.setAttribute("autocorrect", "off");
|
|
174
|
-
inputElement.setAttribute("autocapitalize", "off");
|
|
175
|
-
inputElement.setAttribute("spellcheck", "false");
|
|
176
|
-
inputElement.setAttribute("maxlength", getMaxLength(mask).toString());
|
|
177
|
-
inputElement.addEventListener("paste", function (e) {
|
|
178
|
-
var target = e.target;
|
|
179
|
-
var oldValue = target.value.toString();
|
|
180
|
-
requestAnimationFrame(function () {
|
|
181
|
-
// target.value = process(target.value, mask);
|
|
182
|
-
var m = maskBuilder(target.value, mask);
|
|
183
|
-
target.value = m.process();
|
|
184
|
-
if (callback != null) {
|
|
185
|
-
callback(target.value);
|
|
186
|
-
}
|
|
187
|
-
});
|
|
188
|
-
});
|
|
189
|
-
inputElement.addEventListener((ios() ? "keyup" : "keydown"), function (e) {
|
|
190
|
-
var target = e.target;
|
|
191
|
-
if (e.key === undefined) {
|
|
192
|
-
lockInput = true;
|
|
193
|
-
requestAnimationFrame(function () {
|
|
194
|
-
var selStartAfter = target.selectionStart || 999;
|
|
195
|
-
var m = maskBuilder(target.value, mask, selStartAfter);
|
|
196
|
-
target.value = m.process();
|
|
197
|
-
if (e.which === 8) {
|
|
198
|
-
target.setSelectionRange(selStartAfter, selStartAfter);
|
|
199
|
-
}
|
|
200
|
-
else {
|
|
201
|
-
target.setSelectionRange(m.caret, m.caret);
|
|
202
|
-
}
|
|
203
|
-
requestAnimationFrame(function () {
|
|
204
|
-
lockInput = false;
|
|
205
|
-
});
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
else {
|
|
209
|
-
var oldValue_1 = target.value.toString();
|
|
210
|
-
// chars -------------------
|
|
211
|
-
var isMeta = (e.key !== undefined) ? ("Meta" === e.key) : true;
|
|
212
|
-
var isBackspace_1 = (e.key !== undefined) ? ("Backspace" === e.key || e.keyCode === 8) : true;
|
|
213
|
-
var isDelete_1 = (e.key !== undefined) ? ("Delete" === e.key) : true;
|
|
214
|
-
var isCharInsert_1 = (e.key !== undefined) ? (e.key.length === 1 && !e.ctrlKey && !e.altKey && !e.metaKey) : true;
|
|
215
|
-
var isUnidentified_1 = (e.key !== undefined) ? (e.key === "Unidentified") : false;
|
|
216
|
-
// don't allow to insert more if it's full
|
|
217
|
-
if (isCharInsert_1 && target.selectionStart === target.selectionEnd) {
|
|
218
|
-
if (oldValue_1.length >= getMaxLength(mask)) {
|
|
219
|
-
if (!ios()) {
|
|
220
|
-
e.preventDefault();
|
|
221
|
-
return false;
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
if (lockInput) {
|
|
226
|
-
e.preventDefault();
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
lockInput = true;
|
|
230
|
-
requestAnimationFrame(function () {
|
|
231
|
-
var selStartAfter = target.selectionStart || 999;
|
|
232
|
-
// const m = new Mask(target.value, mask, selStartAfter);
|
|
233
|
-
var m = maskBuilder(target.value, mask, selStartAfter);
|
|
234
|
-
target.value = m.process();
|
|
235
|
-
// requestAnimationFrame(() => {
|
|
236
|
-
target.value = target.value;
|
|
237
|
-
// fix caret position
|
|
238
|
-
if (isUnidentified_1) {
|
|
239
|
-
if (target.value.length > oldValue_1.length) {
|
|
240
|
-
target.setSelectionRange(m.caret, m.caret);
|
|
241
|
-
}
|
|
242
|
-
else {
|
|
243
|
-
target.setSelectionRange(selStartAfter, selStartAfter);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
else {
|
|
247
|
-
if (isDelete_1) {
|
|
248
|
-
if (oldValue_1.length === target.value.length) {
|
|
249
|
-
target.setSelectionRange(selStartAfter + 1, selStartAfter + 1);
|
|
250
|
-
}
|
|
251
|
-
else {
|
|
252
|
-
target.setSelectionRange(selStartAfter, selStartAfter);
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
if (isBackspace_1) {
|
|
256
|
-
target.setSelectionRange(selStartAfter, selStartAfter);
|
|
257
|
-
}
|
|
258
|
-
if (isCharInsert_1) {
|
|
259
|
-
target.setSelectionRange(m.caret, m.caret);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
if (callback != null) {
|
|
263
|
-
callback(target.value);
|
|
264
|
-
}
|
|
265
|
-
requestAnimationFrame(function () {
|
|
266
|
-
lockInput = false;
|
|
267
|
-
});
|
|
268
|
-
// });
|
|
269
|
-
});
|
|
270
|
-
}
|
|
271
|
-
});
|
|
272
|
-
}
|
|
273
|
-
Simple.bind = bind;
|
|
274
|
-
})(Simple = exports.Simple || (exports.Simple = {}));
|
|
275
|
-
exports.default = Simple;
|
|
276
|
-
//# sourceMappingURL=simple.js.map
|
package/lib/simple.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"simple.js","sourceRoot":"","sources":["../src/simple.ts"],"names":[],"mappings":"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"}
|
package/src/main.test.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import "./main";
|
package/src/main.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import Simple from "./simple";
|
|
2
|
-
// import "setimmediate";
|
|
3
|
-
|
|
4
|
-
export module MotherMask {
|
|
5
|
-
const MASKED = "masked";
|
|
6
|
-
export function process(value: string, pattern: string | string[]): string {
|
|
7
|
-
return Simple.process(value, pattern);
|
|
8
|
-
}
|
|
9
|
-
export function bind(
|
|
10
|
-
input: HTMLInputElement | HTMLElement | Element,
|
|
11
|
-
pattern: string | string[],
|
|
12
|
-
callback: ((value: string) => void) | null = null): void {
|
|
13
|
-
const masked = input.getAttribute(MASKED);
|
|
14
|
-
if (masked === null) {
|
|
15
|
-
let strPattern: string = "";
|
|
16
|
-
if (Array.isArray(pattern)) {
|
|
17
|
-
strPattern = pattern.join("|");
|
|
18
|
-
} else {
|
|
19
|
-
strPattern = pattern;
|
|
20
|
-
}
|
|
21
|
-
input.setAttribute(MASKED, strPattern);
|
|
22
|
-
Simple.bind(input, pattern, callback);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
if (window !== undefined) {
|
|
27
|
-
(window as any).MotherMask = MotherMask;
|
|
28
|
-
}
|
|
29
|
-
export default MotherMask;
|
package/src/simple.ts
DELETED
|
@@ -1,264 +0,0 @@
|
|
|
1
|
-
// made by Danilo Celestino de Castro (dan2dev)
|
|
2
|
-
// import { Is } from "utility-collection/src/is";
|
|
3
|
-
export module Is {
|
|
4
|
-
export function empty(value: any): boolean {
|
|
5
|
-
if (value === undefined || value === null || value === "") {
|
|
6
|
-
return true;
|
|
7
|
-
} else {
|
|
8
|
-
return false;
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
// is Number
|
|
12
|
-
const numberRegex: RegExp = /\D/;
|
|
13
|
-
export function number(value: string): boolean {
|
|
14
|
-
return !numberRegex.test(value);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// is Letter
|
|
18
|
-
const letterRegex: RegExp = /[a-zA-Z]/;
|
|
19
|
-
export function letter(value: string): boolean {
|
|
20
|
-
return letterRegex.test(value);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export namespace Simple {
|
|
25
|
-
// detect ios for fix
|
|
26
|
-
let isIos: boolean | undefined;
|
|
27
|
-
function ios(): boolean {
|
|
28
|
-
if (isIos !== undefined) {
|
|
29
|
-
return isIos;
|
|
30
|
-
} else {
|
|
31
|
-
isIos = /iPad|iPhone|iPod/i.test(navigator.userAgent);
|
|
32
|
-
return isIos;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
// ------
|
|
36
|
-
export enum CharType { NUMBER, LETTER }
|
|
37
|
-
export interface IMaskChar {
|
|
38
|
-
position: number;
|
|
39
|
-
char: string | null | CharType;
|
|
40
|
-
}
|
|
41
|
-
export interface IValueChar {
|
|
42
|
-
position: number;
|
|
43
|
-
char: string | null;
|
|
44
|
-
}
|
|
45
|
-
// -----------
|
|
46
|
-
export class Mask {
|
|
47
|
-
public caret: number = 0;
|
|
48
|
-
private mask: string;
|
|
49
|
-
private value: string;
|
|
50
|
-
private maskChar: Simple.IMaskChar = {
|
|
51
|
-
position: -1,
|
|
52
|
-
char: null,
|
|
53
|
-
};
|
|
54
|
-
private valueChar: Simple.IValueChar = {
|
|
55
|
-
position: -1,
|
|
56
|
-
char: null,
|
|
57
|
-
};
|
|
58
|
-
// -----------------------
|
|
59
|
-
|
|
60
|
-
constructor(value: string, mask: string, caret: number = 0) {
|
|
61
|
-
this.value = value;
|
|
62
|
-
this.mask = mask;
|
|
63
|
-
this.caret = caret;
|
|
64
|
-
}
|
|
65
|
-
public process(): string {
|
|
66
|
-
if (Is.empty(this.value)) {
|
|
67
|
-
return "";
|
|
68
|
-
}
|
|
69
|
-
let output: string = "";
|
|
70
|
-
const oldCaret: number = this.caret;
|
|
71
|
-
const shadowLatestIMaskChars: string[] = [];
|
|
72
|
-
while (this.nextIMaskChar()) {
|
|
73
|
-
if (typeof this.maskChar.char === "string") {
|
|
74
|
-
shadowLatestIMaskChars.push(this.maskChar.char);
|
|
75
|
-
} else {
|
|
76
|
-
if (this.nextIValueChar(this.maskChar.char!) && !Is.empty(this.valueChar.char)) {
|
|
77
|
-
while (shadowLatestIMaskChars.length > 0) {
|
|
78
|
-
if (
|
|
79
|
-
this.maskChar.position <= this.caret + 1 &&
|
|
80
|
-
this.maskChar.position >= this.caret
|
|
81
|
-
) {
|
|
82
|
-
this.caret++;
|
|
83
|
-
}
|
|
84
|
-
output += shadowLatestIMaskChars.shift();
|
|
85
|
-
}
|
|
86
|
-
output += this.valueChar.char;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
return output;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
private nextIMaskChar(): boolean {
|
|
94
|
-
this.maskChar.position++;
|
|
95
|
-
if (this.maskChar.position > this.mask.length) {
|
|
96
|
-
return false;
|
|
97
|
-
} else {
|
|
98
|
-
// what to return
|
|
99
|
-
this.maskChar.char = this.mask.charAt(this.maskChar.position);
|
|
100
|
-
if (this.maskChar.char === "9") {
|
|
101
|
-
this.maskChar.char = Simple.CharType.NUMBER;
|
|
102
|
-
} else if (this.maskChar.char === "Z") {
|
|
103
|
-
this.maskChar.char = Simple.CharType.LETTER;
|
|
104
|
-
}
|
|
105
|
-
return true;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
// value
|
|
109
|
-
|
|
110
|
-
private nextIValueChar(type: Simple.CharType): string | boolean {
|
|
111
|
-
this.valueChar.position++;
|
|
112
|
-
if (this.valueChar.position > this.value.length) {
|
|
113
|
-
return false;
|
|
114
|
-
} else {
|
|
115
|
-
this.valueChar.char = this.value.charAt(this.valueChar.position);
|
|
116
|
-
if (type === Simple.CharType.NUMBER) {
|
|
117
|
-
if (Is.number(this.valueChar.char)) { return true; }
|
|
118
|
-
} else if (type === Simple.CharType.LETTER) {
|
|
119
|
-
if (Is.letter(this.valueChar.char)) { return true; }
|
|
120
|
-
}
|
|
121
|
-
return this.nextIValueChar(type);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
export function process(value: string, mask: string | string[]) {
|
|
128
|
-
const m = maskBuilder(value, mask);
|
|
129
|
-
return m.process();
|
|
130
|
-
}
|
|
131
|
-
function getMaskString(value: string, mask: string | string[]) {
|
|
132
|
-
if (Array.isArray(mask)) {
|
|
133
|
-
let i: number = 0;
|
|
134
|
-
while (value.length > mask[i].length && i < mask.length) {
|
|
135
|
-
i++;
|
|
136
|
-
}
|
|
137
|
-
return mask[i];
|
|
138
|
-
} else {
|
|
139
|
-
return mask;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
function getMaxLength(mask: string | string[]): number {
|
|
143
|
-
let maxLength: number = 0;
|
|
144
|
-
if (Array.isArray(mask)) {
|
|
145
|
-
mask.forEach((m) => {
|
|
146
|
-
if (maxLength < m.length) {
|
|
147
|
-
maxLength = m.length;
|
|
148
|
-
}
|
|
149
|
-
});
|
|
150
|
-
} else {
|
|
151
|
-
maxLength = mask.length;
|
|
152
|
-
}
|
|
153
|
-
return maxLength;
|
|
154
|
-
}
|
|
155
|
-
export function maskBuilder(value: string, mask: string | string[], caret: number = 0): Mask {
|
|
156
|
-
return new Mask(value, getMaskString(value, mask), caret);
|
|
157
|
-
}
|
|
158
|
-
let lockInput: boolean = false;
|
|
159
|
-
export function bind(
|
|
160
|
-
inputElement: HTMLInputElement | Element,
|
|
161
|
-
mask: string | string[],
|
|
162
|
-
callback: ((output: string) => void) | null = null) {
|
|
163
|
-
inputElement.setAttribute("autocomplete", "off");
|
|
164
|
-
inputElement.setAttribute("autocorrect", "off");
|
|
165
|
-
inputElement.setAttribute("autocapitalize", "off");
|
|
166
|
-
inputElement.setAttribute("spellcheck", "false");
|
|
167
|
-
|
|
168
|
-
inputElement.setAttribute("maxlength", getMaxLength(mask).toString());
|
|
169
|
-
inputElement.addEventListener("paste", (e: Event) => {
|
|
170
|
-
const target = e.target as HTMLInputElement;
|
|
171
|
-
const oldValue = target.value.toString();
|
|
172
|
-
requestAnimationFrame(() => {
|
|
173
|
-
// target.value = process(target.value, mask);
|
|
174
|
-
const m = maskBuilder(target.value, mask);
|
|
175
|
-
target.value = m.process();
|
|
176
|
-
if (callback != null) {
|
|
177
|
-
callback(target.value);
|
|
178
|
-
}
|
|
179
|
-
});
|
|
180
|
-
});
|
|
181
|
-
inputElement.addEventListener((ios() ? "keyup" : "keydown"), (e: KeyboardEvent) => {
|
|
182
|
-
|
|
183
|
-
const target = e.target as HTMLInputElement;
|
|
184
|
-
|
|
185
|
-
if (e.key === undefined) {
|
|
186
|
-
lockInput = true;
|
|
187
|
-
requestAnimationFrame(() => {
|
|
188
|
-
const selStartAfter = target.selectionStart || 999;
|
|
189
|
-
const m = maskBuilder(target.value, mask, selStartAfter);
|
|
190
|
-
target.value = m.process();
|
|
191
|
-
if (e.which === 8) {
|
|
192
|
-
target.setSelectionRange(selStartAfter, selStartAfter);
|
|
193
|
-
} else {
|
|
194
|
-
target.setSelectionRange(m.caret, m.caret);
|
|
195
|
-
}
|
|
196
|
-
requestAnimationFrame(() => {
|
|
197
|
-
lockInput = false;
|
|
198
|
-
});
|
|
199
|
-
});
|
|
200
|
-
} else {
|
|
201
|
-
const oldValue = target.value.toString();
|
|
202
|
-
// chars -------------------
|
|
203
|
-
const isMeta = (e.key !== undefined) ? ("Meta" === e.key) : true;
|
|
204
|
-
const isBackspace = (e.key !== undefined) ? ("Backspace" === e.key || e.keyCode === 8) : true;
|
|
205
|
-
const isDelete = (e.key !== undefined) ? ("Delete" === e.key) : true;
|
|
206
|
-
const isCharInsert = (e.key !== undefined) ? (e.key.length === 1 && !e.ctrlKey && !e.altKey && !e.metaKey) : true;
|
|
207
|
-
const isUnidentified = (e.key !== undefined) ? (e.key === "Unidentified") : false;
|
|
208
|
-
// don't allow to insert more if it's full
|
|
209
|
-
if (isCharInsert && target.selectionStart === target.selectionEnd) {
|
|
210
|
-
if (oldValue.length >= getMaxLength(mask)) {
|
|
211
|
-
if (!ios()) {
|
|
212
|
-
e.preventDefault();
|
|
213
|
-
return false;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
if (lockInput) {
|
|
218
|
-
e.preventDefault();
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
|
-
lockInput = true;
|
|
222
|
-
requestAnimationFrame(() => {
|
|
223
|
-
const selStartAfter = target.selectionStart || 999;
|
|
224
|
-
// const m = new Mask(target.value, mask, selStartAfter);
|
|
225
|
-
const m = maskBuilder(target.value, mask, selStartAfter);
|
|
226
|
-
target.value = m.process();
|
|
227
|
-
// requestAnimationFrame(() => {
|
|
228
|
-
target.value = target.value;
|
|
229
|
-
// fix caret position
|
|
230
|
-
if (isUnidentified) {
|
|
231
|
-
if (target.value.length > oldValue.length) {
|
|
232
|
-
target.setSelectionRange(m.caret, m.caret);
|
|
233
|
-
} else {
|
|
234
|
-
target.setSelectionRange(selStartAfter, selStartAfter);
|
|
235
|
-
}
|
|
236
|
-
} else {
|
|
237
|
-
if (isDelete) {
|
|
238
|
-
if (oldValue.length === target.value.length) {
|
|
239
|
-
target.setSelectionRange(selStartAfter + 1, selStartAfter + 1);
|
|
240
|
-
} else {
|
|
241
|
-
target.setSelectionRange(selStartAfter, selStartAfter);
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
if (isBackspace) {
|
|
245
|
-
target.setSelectionRange(selStartAfter, selStartAfter);
|
|
246
|
-
}
|
|
247
|
-
if (isCharInsert) {
|
|
248
|
-
target.setSelectionRange(m.caret, m.caret);
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
if (callback != null) {
|
|
252
|
-
callback(target.value);
|
|
253
|
-
}
|
|
254
|
-
requestAnimationFrame(() => {
|
|
255
|
-
lockInput = false;
|
|
256
|
-
});
|
|
257
|
-
// });
|
|
258
|
-
});
|
|
259
|
-
}
|
|
260
|
-
});
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
export default Simple;
|
package/test/index.html
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
2
|
-
|
|
3
|
-
<head>
|
|
4
|
-
<title>Mother Mask Test</title>
|
|
5
|
-
<script type="text/javascript" src="../dist/main.js"></script>
|
|
6
|
-
<meta name="mobile-web-app-capable" content="yes">
|
|
7
|
-
<meta name="viewport"
|
|
8
|
-
content="width=device-width,height=device-height,initial-scale=1,maximum-scale=1,user-scalable=no,minimal-ui">
|
|
9
|
-
<meta name="mobile-web-app-capable" content="yes">
|
|
10
|
-
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
11
|
-
<meta name="format-detection" content="telephone=no">
|
|
12
|
-
<meta name="theme-color" content="#f0f0f0">
|
|
13
|
-
<style>
|
|
14
|
-
body {
|
|
15
|
-
background-color: #f0f0f0;
|
|
16
|
-
margin: 0;
|
|
17
|
-
padding: 0;
|
|
18
|
-
}
|
|
19
|
-
</style>
|
|
20
|
-
</head>
|
|
21
|
-
|
|
22
|
-
<body>
|
|
23
|
-
<ul>
|
|
24
|
-
<li>
|
|
25
|
-
<label>Date</label>
|
|
26
|
-
<input id="date" placeholder="dd/mm/yyyy" />
|
|
27
|
-
</li>
|
|
28
|
-
<li>
|
|
29
|
-
<label>phone (US)</label>
|
|
30
|
-
<input id="phoneus" placeholder="(999) 999-9999" />
|
|
31
|
-
</li>
|
|
32
|
-
<li>
|
|
33
|
-
<label>ZIP Code</label>
|
|
34
|
-
<input id="zipcode" placeholder="99999-999" />
|
|
35
|
-
</li>
|
|
36
|
-
|
|
37
|
-
<li>
|
|
38
|
-
<label>phone (BR)</label>
|
|
39
|
-
<input id="phonebr" placeholder="(99) 99999-9999 ou (99) 9999-9999" />
|
|
40
|
-
</li>
|
|
41
|
-
<li>
|
|
42
|
-
<label>CPF (BR)</label>
|
|
43
|
-
<input id="cpf" placeholder="999.999.999-99" />
|
|
44
|
-
</li>
|
|
45
|
-
|
|
46
|
-
</ul>
|
|
47
|
-
<div id="c">---</div>
|
|
48
|
-
|
|
49
|
-
<script type="text/javascript" async="async">
|
|
50
|
-
MotherMask.bind(document.getElementById("phoneus"), "(999) 999-9999");
|
|
51
|
-
MotherMask.bind(document.getElementById("zipcode"), "99999-999");
|
|
52
|
-
MotherMask.bind(document.getElementById("date"), "99/99/9999");
|
|
53
|
-
MotherMask.bind(document.getElementById("phonebr"), ["(99) 9999-9999", "(99) 99999-9999"]);
|
|
54
|
-
MotherMask.bind(document.getElementById("cpf"), "999.999.999-99");
|
|
55
|
-
</script>
|
|
56
|
-
</body>
|
|
57
|
-
|
|
58
|
-
</html>
|