mother-mask 3.0.1 → 3.2.0
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 +82 -184
- package/dist/mother-mask.cjs +1 -1
- package/dist/mother-mask.cjs.map +1 -1
- package/dist/mother-mask.d.cts +26 -3
- package/dist/mother-mask.d.mts +26 -3
- package/dist/mother-mask.mjs +1 -1
- package/dist/mother-mask.mjs.map +1 -1
- package/dist/mother-mask.umd.js +1 -1
- package/dist/mother-mask.umd.js.map +1 -1
- package/package.json +17 -15
package/README.md
CHANGED
|
@@ -1,250 +1,148 @@
|
|
|
1
1
|
# mother-mask
|
|
2
2
|
|
|
3
|
-
Lightweight input
|
|
3
|
+
Lightweight input masks for browser forms. Zero runtime dependencies, written in TypeScript, and published with ESM, CJS, and UMD builds.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## Live demo
|
|
8
|
-
|
|
9
|
-
**[Try it on StackBlitz →](https://stackblitz.com/edit/mother-mask-simple-demo?file=src%2Fmain.ts)**
|
|
5
|
+
[npm](https://www.npmjs.com/package/mother-mask) | [Live demo](https://stackblitz.com/edit/mother-mask-simple-demo?file=src%2Fmain.ts)
|
|
10
6
|
|
|
11
7
|
## Install
|
|
12
8
|
|
|
13
9
|
```bash
|
|
14
10
|
npm install mother-mask
|
|
15
|
-
# or
|
|
16
|
-
pnpm add mother-mask
|
|
17
11
|
```
|
|
18
12
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
Attach a mask to any input element — this is the main API.
|
|
13
|
+
```bash
|
|
14
|
+
pnpm add mother-mask
|
|
15
|
+
```
|
|
24
16
|
|
|
25
|
-
|
|
26
|
-
- **Returns a dispose function** — call it to remove listeners and attributes so you can bind again later.
|
|
27
|
-
- Sets sensible defaults when missing: `autocomplete`, `autocorrect`, `autocapitalize`, `spellcheck`, and `maxlength` from the mask.
|
|
17
|
+
## Basic Usage
|
|
28
18
|
|
|
29
19
|
```ts
|
|
30
20
|
import { bind } from 'mother-mask'
|
|
31
21
|
|
|
32
|
-
const input = document.
|
|
22
|
+
const input = document.querySelector<HTMLInputElement>('#phone')!
|
|
33
23
|
|
|
34
|
-
// Fixed mask
|
|
35
24
|
const dispose = bind(input, '(99) 99999-9999')
|
|
36
25
|
|
|
37
|
-
//
|
|
38
|
-
bind(input, ['(99) 9999-9999', '(99) 99999-9999'])
|
|
39
|
-
|
|
40
|
-
// Callback after paste or keyboard-driven changes
|
|
41
|
-
bind(input, '999.999.999-99', (value) => {
|
|
42
|
-
console.log(value) // e.g. "123.456.789-01"
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
// Or options object (same as callback for a single `onChange`)
|
|
46
|
-
bind(input, '999.999.999-99', { onChange: (value) => console.log(value) })
|
|
47
|
-
|
|
48
|
-
// Later: allow rebinding
|
|
26
|
+
// Later, remove listeners and allow rebinding.
|
|
49
27
|
dispose()
|
|
50
28
|
```
|
|
51
29
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
By default, every mask treats its literal separators as hard boundaries
|
|
55
|
-
between independent fields. Selecting "12" in `25/12/2025` and typing a
|
|
56
|
-
shorter or longer replacement stays scoped to the month — it never bleeds
|
|
57
|
-
digits into the year, and deleting a whole field just leaves it empty
|
|
58
|
-
instead of pulling the next field left across the separator:
|
|
30
|
+
Use an ordered mask array for values with more than one length:
|
|
59
31
|
|
|
60
32
|
```ts
|
|
61
|
-
bind(input, '99
|
|
33
|
+
bind(input, ['(99) 9999-9999', '(99) 99999-9999'])
|
|
62
34
|
```
|
|
63
35
|
|
|
64
|
-
|
|
65
|
-
times — and it's a safe default everywhere else too, since it never
|
|
66
|
-
*discards* data (typing past a field's capacity still flows forward into
|
|
67
|
-
the next one; only backward bleed is blocked). A fully raw, unformatted
|
|
68
|
-
paste (e.g. `25122025`) still fills every field in one pass, and array
|
|
69
|
-
masks that switch pattern width (see below) still reflow correctly.
|
|
70
|
-
|
|
71
|
-
Pass `segmented: false` to opt into the classic flat/reflow behavior
|
|
72
|
-
instead, where deleting or replacing characters anywhere shifts everything
|
|
73
|
-
after it to close the gap — useful when a mask really is one continuous
|
|
74
|
-
number with cosmetic separators (e.g. formatting a running total) rather
|
|
75
|
-
than independent fields:
|
|
36
|
+
Listen for changes with either a callback or an options object:
|
|
76
37
|
|
|
77
38
|
```ts
|
|
78
|
-
bind(input, '999.999.999-99',
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
`segmented` is also accepted by `applyMask`, `buildMask`, and `process` as
|
|
82
|
-
part of an options object.
|
|
39
|
+
bind(input, '999.999.999-99', (value) => {
|
|
40
|
+
document.querySelector<HTMLInputElement>('#cpf-value')!.value = value
|
|
41
|
+
})
|
|
83
42
|
|
|
84
|
-
|
|
43
|
+
bind(input, '999.999.999-99', {
|
|
44
|
+
onChange: (value) => {
|
|
45
|
+
document.querySelector<HTMLInputElement>('#cpf-value')!.value = value
|
|
46
|
+
},
|
|
47
|
+
})
|
|
48
|
+
```
|
|
85
49
|
|
|
86
|
-
|
|
87
|
-
pattern-slot strings. There's no fixed template: the integer part grows and
|
|
88
|
-
shrinks freely as the user types, and formatting (grouping, decimal places,
|
|
89
|
-
prefix/suffix) is driven entirely by `options`. Same contract as `bind()`:
|
|
90
|
-
idempotent, marked with `data-masked`, returns a dispose function.
|
|
50
|
+
## Decimal Inputs
|
|
91
51
|
|
|
92
|
-
|
|
93
|
-
digits fill the integer part until you type the decimal separator, and the
|
|
94
|
-
fixed-width fraction is always shown zero-padded. A lone placeholder "0" in
|
|
95
|
-
the integer part (an untouched field showing e.g. "$0.00") is overwritten,
|
|
96
|
-
not extended, by the next digit — typing "2" anywhere against that "0" gives
|
|
97
|
-
"$2.00", never "$20.00" or "$02.00".
|
|
52
|
+
Use `bindDecimal` for numbers, currency fields, and values where the integer part should grow freely.
|
|
98
53
|
|
|
99
54
|
```ts
|
|
100
55
|
import { bindDecimal } from 'mother-mask'
|
|
101
56
|
|
|
102
|
-
const input = document.querySelector<HTMLInputElement>('#decimal')!
|
|
103
|
-
|
|
104
57
|
bindDecimal(input, {
|
|
105
|
-
decimalPlaces: 2,
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
decimalSeparator: '.', // integer/fraction separator, and its typing trigger — default '.'
|
|
58
|
+
decimalPlaces: 2,
|
|
59
|
+
separator: ',',
|
|
60
|
+
decimalSeparator: '.',
|
|
109
61
|
prefix: '$',
|
|
110
|
-
|
|
111
|
-
|
|
62
|
+
allowNegative: false,
|
|
63
|
+
onChange: (value, numericValue) => {
|
|
64
|
+
document.querySelector<HTMLInputElement>('#amount-label')!.value = value
|
|
65
|
+
document.querySelector<HTMLInputElement>('#amount-value')!.value = String(numericValue)
|
|
66
|
+
},
|
|
112
67
|
})
|
|
68
|
+
```
|
|
113
69
|
|
|
114
|
-
|
|
115
|
-
// Typing "423" → "$423.00"
|
|
116
|
-
// Typing "423." → "$423.00" (the separator opens the fraction segment)
|
|
117
|
-
// Typing "423.4" → "$423.40"
|
|
118
|
-
// Typing "423.42" → "$423.42"
|
|
119
|
-
|
|
120
|
-
// Editing is segmented, same as bind(): shortening "423.42" to "423.4"
|
|
121
|
-
// (deleting the trailing "2") re-pads the fraction instead of reflowing
|
|
122
|
-
// digits from the integer part → "$423.40"
|
|
123
|
-
|
|
124
|
-
// Either "." or "," opens the fraction, regardless of decimalSeparator —
|
|
125
|
-
// handy since numeric keypads often only have ".".
|
|
70
|
+
For Brazilian-style formatting:
|
|
126
71
|
|
|
127
|
-
|
|
72
|
+
```ts
|
|
128
73
|
bindDecimal(input, {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
console.log(value, numericValue) // "$423.42", 423.42
|
|
132
|
-
},
|
|
74
|
+
separator: '.',
|
|
75
|
+
decimalSeparator: ',',
|
|
133
76
|
})
|
|
134
|
-
|
|
135
|
-
// Or a bare callback (legacy style, same as bind())
|
|
136
|
-
bindDecimal(input, (value, numericValue) => console.log(value, numericValue))
|
|
137
77
|
```
|
|
138
78
|
|
|
139
|
-
|
|
140
|
-
`{ separator: '.', decimalSeparator: ',' }` gives the `1.234,56` format
|
|
141
|
-
common outside the US.
|
|
142
|
-
|
|
143
|
-
## Pattern syntax
|
|
79
|
+
## Pattern Syntax
|
|
144
80
|
|
|
145
81
|
| Character | Matches |
|
|
146
|
-
|
|
147
|
-
| `9` | Digit
|
|
148
|
-
| `Z` | Letter
|
|
149
|
-
| `A` |
|
|
150
|
-
| Anything else | Literal
|
|
82
|
+
| --- | --- |
|
|
83
|
+
| `9` | Digit |
|
|
84
|
+
| `Z` | Letter |
|
|
85
|
+
| `A` | Letter or digit |
|
|
86
|
+
| Anything else | Literal separator |
|
|
151
87
|
|
|
152
|
-
|
|
88
|
+
Examples:
|
|
153
89
|
|
|
154
|
-
|
|
90
|
+
```ts
|
|
91
|
+
bind(input, '999.999.999-99')
|
|
92
|
+
bind(input, '99/99/9999')
|
|
93
|
+
bind(input, 'AA.AAA.AAA/AAAA-99')
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Segmented Editing
|
|
97
|
+
|
|
98
|
+
Masks are segmented by default. Separators behave like boundaries, which keeps fields such as dates from bleeding into each other while editing:
|
|
155
99
|
|
|
156
100
|
```ts
|
|
157
|
-
bind(input,
|
|
158
|
-
bind(input, ['999.999.999-99', 'AA.AAA.AAA/AAAA-99'])
|
|
101
|
+
bind(input, '99/99/9999')
|
|
159
102
|
```
|
|
160
103
|
|
|
161
|
-
|
|
104
|
+
For classic reflow behavior, pass `segmented: false`:
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
bind(input, '999.999.999-99', { segmented: false })
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## CDN
|
|
162
111
|
|
|
163
112
|
```html
|
|
164
113
|
<script src="https://unpkg.com/mother-mask/dist/mother-mask.umd.js"></script>
|
|
165
114
|
<script>
|
|
166
|
-
|
|
115
|
+
MotherMask.bind(document.getElementById('cpf'), '999.999.999-99')
|
|
167
116
|
</script>
|
|
168
117
|
```
|
|
169
118
|
|
|
170
|
-
The global name is
|
|
171
|
-
|
|
172
|
-
## API reference
|
|
173
|
-
|
|
174
|
-
### `bind` (primary)
|
|
175
|
-
|
|
176
|
-
| | |
|
|
177
|
-
|--|--|
|
|
178
|
-
| **Signature** | `bind(input, mask, options?)` |
|
|
179
|
-
| **Returns** | `() => void` — call to remove listeners and attributes so the input can be bound again |
|
|
180
|
-
| **Third argument** | `{ onChange?: (value: string) => void }`, or a legacy `(value) => void` callback |
|
|
181
|
-
|
|
182
|
-
### Other exports
|
|
119
|
+
The global name is `MotherMask`.
|
|
183
120
|
|
|
184
|
-
|
|
185
|
-
|--------|-------------|
|
|
186
|
-
| `buildMask(value, mask, caret?, options?)` | Build a `Mask` instance (array `mask` is resolved to one string first). |
|
|
187
|
-
| `getMaxLength(mask)` | Maximum string length for the mask (for array masks, the longest pattern). |
|
|
188
|
-
| `applyMask(value, mask, inputCaret?, options?)` | Low-level: apply a **single** mask string; returns `{ value, caret }`. |
|
|
189
|
-
| `process(value, mask, options?)` | Apply a mask pattern to a raw value and return just the masked string. |
|
|
121
|
+
## API
|
|
190
122
|
|
|
191
|
-
|
|
123
|
+
Main exports:
|
|
192
124
|
|
|
193
|
-
|
|
125
|
+
- `bind(input, mask, options?)`
|
|
126
|
+
- `bindDecimal(input, options?)`
|
|
127
|
+
- `applyMask(value, mask, inputCaret?, options?)`
|
|
128
|
+
- `process(value, mask, options?)`
|
|
129
|
+
- `buildMask(value, mask, caret?, options?)`
|
|
130
|
+
- `getMaxLength(mask)`
|
|
131
|
+
- `applyDecimalMask(value, inputCaret?, options?)`
|
|
132
|
+
- `processDecimal(value, options?)`
|
|
133
|
+
- `unmaskDecimal(value, options?)`
|
|
134
|
+
- `formatDecimalValue(value, options?)`
|
|
135
|
+
- `Mask`
|
|
194
136
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
| | |
|
|
198
|
-
|--|--|
|
|
199
|
-
| **Signature** | `bindDecimal(input, options?)` |
|
|
200
|
-
| **Returns** | `() => void` — call to remove listeners and attributes so the input can be bound again |
|
|
201
|
-
| **Second argument** | `DecimalMaskOptions & { onChange?: (value: string, numericValue: number) => void }`, or a legacy `(value, numericValue) => void` callback |
|
|
202
|
-
|
|
203
|
-
### Other decimal exports
|
|
204
|
-
|
|
205
|
-
| Export | Description |
|
|
206
|
-
|--------|-------------|
|
|
207
|
-
| `applyDecimalMask(value, inputCaret?, options?)` | Low-level: format a raw/already-masked value; returns `{ value, caret }`. |
|
|
208
|
-
| `processDecimal(value, options?)` | Apply a decimal mask to a raw value and return just the masked string. |
|
|
209
|
-
| `unmaskDecimal(value, options?)` | Parse a raw or masked decimal string back into a JS `number` (`0` if it has no digits). |
|
|
210
|
-
| `formatDecimalValue(value, options?)` | Format a plain JS `number` into its masked display string — useful to pre-populate an input. |
|
|
211
|
-
|
|
212
|
-
### Types
|
|
213
|
-
|
|
214
|
-
```ts
|
|
215
|
-
type MaskPattern = string | string[]
|
|
216
|
-
|
|
217
|
-
interface MaskResult {
|
|
218
|
-
readonly value: string
|
|
219
|
-
readonly caret: number
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
interface ApplyMaskOptions {
|
|
223
|
-
/** Hard boundaries between fields — on by default. Pass `false` for flat/reflow. */
|
|
224
|
-
segmented?: boolean
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
interface BindOptions extends ApplyMaskOptions {
|
|
228
|
-
onChange?: (value: string) => void
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
interface DecimalMaskOptions {
|
|
232
|
-
decimalPlaces?: number // default 2
|
|
233
|
-
segmented?: boolean // group into thousands — default true
|
|
234
|
-
separator?: string // thousands separator — default ','
|
|
235
|
-
decimalSeparator?: string // default '.'
|
|
236
|
-
prefix?: string // default ''
|
|
237
|
-
suffix?: string // default ''
|
|
238
|
-
allowNegative?: boolean // default false
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
interface BindDecimalOptions extends DecimalMaskOptions {
|
|
242
|
-
onChange?: (value: string, numericValue: number) => void
|
|
243
|
-
}
|
|
244
|
-
```
|
|
137
|
+
Exported types:
|
|
245
138
|
|
|
246
|
-
`MaskPattern
|
|
139
|
+
- `MaskPattern`
|
|
140
|
+
- `MaskResult`
|
|
141
|
+
- `ApplyMaskOptions`
|
|
142
|
+
- `BindOptions`
|
|
143
|
+
- `DecimalMaskOptions`
|
|
144
|
+
- `BindDecimalOptions`
|
|
247
145
|
|
|
248
146
|
## License
|
|
249
147
|
|
|
250
|
-
MIT
|
|
148
|
+
MIT - [Danilo Celestino de Castro](https://github.com/dan2dev)
|
package/dist/mother-mask.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});function e(e){return e>=`0`&&e<=`9`}function t(e){return e>=`a`&&e<=`z`||e>=`A`&&e<=`Z`}function n(e){return e===`9`||e===`Z`||e===`A`}function r(n,r){return r===`9`?e(n):r===`Z`?t(n):e(n)||t(n)}function i(e,t,n){let i=``,a=``,o=0,s=0,c=!1;for(let l=0;l<t.length;l++){let u=t[l];if(u!==`9`&&u!==`Z`&&u!==`A`){a+=u;continue}let d=!1;for(;o<e.length;){let t=e[o++];if(r(t,u)){i+=a+t,a=``,d=!0,c||(o<=n?s=i.length:c=!0);break}}if(!d)break}return c||(s=i.length),{value:i,caret:s}}function
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});function e(e){return e>=`0`&&e<=`9`}function t(e){return e>=`a`&&e<=`z`||e>=`A`&&e<=`Z`}function n(e){return e===`9`||e===`Z`||e===`A`}function r(n,r){return r===`9`?e(n):r===`Z`?t(n):e(n)||t(n)}function i(e,t,n){let i=``,a=``,o=0,s=0,c=!1;for(let l=0;l<t.length;l++){let u=t[l];if(u!==`9`&&u!==`Z`&&u!==`A`){a+=u;continue}let d=!1;for(;o<e.length;){let t=e[o++];if(r(t,u)){i+=a+t,a=``,d=!0,c||(o<=n?s=i.length:c=!0);break}}if(!d)break}return c||(s=i.length),{value:i,caret:s}}const a=new Map;function o(e){let t=a.get(e);if(t)return t;let r=[],i=0;for(;i<e.length;){let t=i,a=n(e[i]);for(;i<e.length&&n(e[i])===a;)i++;let o=e.slice(t,i);r.push(a?{kind:`slots`,chars:o}:{kind:`literal`,text:o})}return a.set(e,r),r}function s(e,t){let n=0;for(let r=t;r<e.length;r++){let t=e[r];t.kind===`slots`&&(n+=t.chars.length)}return n}function c(n,r){let i=0;for(let a=r;a<n.length;a++){let r=n[a];(e(r)||t(r))&&i++}return i}function l(e,t,n){let i=o(t),a=``,l=``,u=0,d=0,f=!1,p=!1;for(let t=0;t<i.length&&!p;t++){let o=i[t];if(o.kind===`literal`){l+=o.text,e.startsWith(o.text,u)&&(u+=o.text.length);continue}let m=i[t+1],h=s(i,t+1);for(let t=0;t<o.chars.length;t++){let i=o.chars[t],s=!1;for(;u<e.length;){let t=e[u];if(r(t,i)){u++,a+=l+t,l=``,s=!0,f||(u<=n?d=a.length:f=!0);break}if(m?.kind===`literal`&&e.startsWith(m.text,u)&&c(e,u)<=h)break;u++}if(!s){u>=e.length&&(p=!0);break}}}return f||(d=a.length),{value:a,caret:d}}function u(e,t,n=0,r){return e?r?.segmented===!1?i(e,t,n):l(e,t,n):{value:``,caret:0}}function d(e){let t=0;for(let n of e)(n>=`0`&&n<=`9`||n>=`a`&&n<=`z`||n>=`A`&&n<=`Z`)&&t++;return t}function f(e){let t=0;for(let n of e)(n===`9`||n===`Z`||n===`A`)&&t++;return t}function p(e,t){if(!Array.isArray(t))return t;let n=d(e),r=0;for(;r<t.length-1&&n>f(t[r]);)r++;return t[r]}function m(e){return Array.isArray(e)?e.length>0?Math.max(...e.map(e=>e.length)):0:e.length}var h=class{caret;_value;_mask;_options;constructor(e,t,n=0,r){this._value=e,this._mask=t,this.caret=n,this._options=r}process(){let e=u(this._value,this._mask,this.caret,this._options);return this.caret=e.caret,e.value}};function g(e,t,n=0,r){return new h(e,p(e,t),n,r)}function _(e,t,n){return g(e,t,0,n).process()}let v;function y(){return v===void 0&&(v=typeof navigator<`u`&&/iPad|iPhone|iPod/i.test(navigator.userAgent)),v}const b=`data-masked`;function x(e){return e==null?{}:typeof e==`function`?{onChange:e}:e}function S(e,t,n){if(e.getAttribute(b)!==null)return()=>{};let{onChange:r,segmented:i}=x(n),a=[],o=(t,n)=>{e.hasAttribute(t)||(e.setAttribute(t,n),a.push(t))},s=m(t);e.setAttribute(b,Array.isArray(t)?t.join(`|`):t),o(`autocomplete`,`off`),o(`autocorrect`,`off`),o(`autocapitalize`,`off`),o(`spellcheck`,`false`),o(`maxlength`,String(s));let c=!1,l=y()?`keyup`:`keydown`,u=new Set,d=e=>{let t=requestAnimationFrame(()=>{u.delete(t),e()});u.add(t)},f=e=>{let n=e.target;d(()=>{n.value=g(n.value,t,0,{segmented:i}).process(),r?.(n.value)})},p=e=>{let n=e,a=n.target,o=a.value;if(!n.key){c=!0,d(()=>{let e=a.selectionStart??999,n=g(a.value,t,e,{segmented:i});a.value=n.process(),a.setSelectionRange(n.caret,n.caret),d(()=>{c=!1})});return}if(n.key===`Meta`)return;let l=n.key===`Backspace`,u=n.key===`Delete`,f=n.key.length===1&&!n.ctrlKey&&!n.altKey&&!n.metaKey,p=n.key===`Unidentified`;if(f&&a.selectionStart===a.selectionEnd&&o.length>=s&&!y()){n.preventDefault();return}if(c){n.preventDefault();return}d(()=>{let e=a.selectionStart??999,n=g(a.value,t,e,{segmented:i});if(a.value=n.process(),p){let t=a.value.length>o.length?n.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):f&&a.setSelectionRange(n.caret,n.caret);r?.(a.value)})};return e.addEventListener(`paste`,f),e.addEventListener(l,p),()=>{e.removeEventListener(`paste`,f),e.removeEventListener(l,p),e.removeAttribute(b);for(let t of a)e.removeAttribute(t);for(let e of u)cancelAnimationFrame(e);u.clear()}}function C(e){return e>=`0`&&e<=`9`}function w(e){let t=e?.decimalPlaces,n=t!=null&&Number.isFinite(t)?Math.max(0,Math.floor(t)):void 0,r=e?.numberPlaces;return{decimalPlaces:n,numberPlaces:r!=null&&Number.isFinite(r)?Math.max(1,Math.floor(r)):void 0,segmented:e?.segmented??!0,separator:e?.separator??`,`,decimalSeparator:e?.decimalSeparator??`.`,prefix:e?.prefix??``,suffix:e?.suffix??``,allowNegative:e?.allowNegative??!1}}function T(e){let t=0;for(;t<e.length-1&&e[t]===`0`;)t++;return e.slice(t)}function E(e,t){if(!t||e.length<=3)return e;let n=[],r=e.length;for(;r>3;)n.unshift(e.slice(r-3,r)),r-=3;return n.unshift(e.slice(0,r)),n.join(t)}function D(e,t){if(t<=0)return 0;let n=0;for(let r=0;r<e.length;r++)if(C(e[r])&&(n++,n===t))return r+1;return e.length}function O(e,t){let n=``,r=``,i=!1,a=!1,o=t.decimalPlaces!==0;for(let s of e){if(C(s)){a?(t.decimalPlaces==null||r.length<t.decimalPlaces)&&(r+=s):(t.numberPlaces==null||n.length<t.numberPlaces)&&(n+=s);continue}if(o&&!a&&s===t.decimalSeparator){a=!0;continue}s===`-`&&t.allowNegative&&(i=!0)}return{isNegative:i,intDigits:n,fracDigits:r,hasSeparator:a}}function k(e,t,n){let r=n.decimalPlaces!==0,i=!1,a=0;for(let o=0;o<t;o++){let t=e[o];if(C(t)){i?(n.decimalPlaces==null||a<n.decimalPlaces)&&a++:(n.numberPlaces==null||a<n.numberPlaces)&&a++;continue}r&&!i&&t===n.decimalSeparator&&(i=!0,a=0)}return{inFraction:i,digitsBefore:a}}function A(e,t=0,n){let r=w(n);if(!e)return{value:``,caret:0};let{isNegative:i,intDigits:a,fracDigits:o,hasSeparator:s}=O(e,r);if(a===``&&o===``&&!s)return{value:``,caret:0};let c=T(a||`0`),l=r.numberPlaces==null?c:c.padStart(r.numberPlaces,`0`),u=r.segmented?E(l,r.separator):l,d=r.decimalPlaces!=null&&r.decimalPlaces>0?o.padEnd(r.decimalPlaces,`0`):o,f=u+(r.decimalPlaces!==0&&(r.decimalPlaces!=null||s)?r.decimalSeparator+d:``),p=i?`-`:``,m=p+r.prefix+f+r.suffix,{inFraction:h,digitsBefore:g}=k(e,Math.max(0,Math.min(t,e.length)),r),_=p.length+r.prefix.length,v=l.length-c.length;return{value:m,caret:h?_+u.length+r.decimalSeparator.length+g:_+D(u,g+v)}}function j(e,t){return A(e,e.length,t).value}function M(e,t){let{isNegative:n,intDigits:r,fracDigits:i}=O(e,w(t)),a=Number(i?`${r||`0`}.${i}`:r||`0`);return n?-a:a}function N(e,t){let n=w(t);if(n.decimalPlaces==null||n.decimalPlaces<=0)return null;let{isNegative:r,intDigits:i,hasSeparator:a}=O(e,n);if(a||i.length<n.decimalPlaces+1)return null;let o=i.length-n.decimalPlaces,s=i.slice(o),c=i.slice(0,o-1),l=r?`-`:``;return A(l+c+n.decimalSeparator+s,l.length+c.length,n)}function P(e,t,n,r){let i=w(r),a=t-1;if(a<0||e[a]!==n)return null;let{isNegative:o,intDigits:s,fracDigits:c,hasSeparator:l}=O(e.slice(0,a)+e.slice(t),i),u=T(s||`0`),d=u!==`0`,f=d&&i.numberPlaces!=null&&u.length<i.numberPlaces;if(d&&!f)return null;let p=+!!o+i.prefix.length;if(a<p||a>p+s.length)return null;let m=o?`-`:``,h=(d?u:``)+n;return A(m+h+(l?i.decimalSeparator+c:``),m.length+h.length,i)}function F(e,t){let n=w(t);if(!Number.isFinite(e))return``;let r=n.allowNegative&&e<0,i=Math.abs(e),a=n.decimalPlaces==null?String(i):i.toFixed(n.decimalPlaces),o=a.indexOf(`.`),s=o===-1?a:a.slice(0,o),c=o===-1?``:a.slice(o+1),l=T(s||`0`),u=n.numberPlaces==null?l:l.padStart(n.numberPlaces,`0`),d=(n.segmented?E(u,n.separator):u)+(n.decimalPlaces!==0&&c!==``?n.decimalSeparator+c:``);return(r?`-`:``)+n.prefix+d+n.suffix}const I=`data-masked`;function L(e){return e==null?{}:typeof e==`function`?{onChange:e}:e}function R(e){return e.length===1&&e>=`0`&&e<=`9`}function z(e,t){if(e.getAttribute(I)!==null)return()=>{};let{onChange:n,...r}=L(t),i=r,{decimalSeparator:a,decimalPlaces:o}=w(i),s=[],c=(t,n)=>{e.hasAttribute(t)||(e.setAttribute(t,n),s.push(t))};e.setAttribute(I,`decimal`),c(`autocomplete`,`off`),c(`autocorrect`,`off`),c(`autocapitalize`,`off`),c(`spellcheck`,`false`);let l=!1,u=y()?`keyup`:`keydown`,d=new Set,f=e=>{let t=requestAnimationFrame(()=>{d.delete(t),e()});d.add(t)},p=(e,t)=>{e.value=t.value,e.setSelectionRange(t.caret,t.caret),n?.(t.value,M(t.value,i))},m=e=>{let t=e.target;f(()=>{p(t,A(t.value,t.value.length,i))})},h=e=>{let t=e,n=t.target;if(!t.key){l=!0,f(()=>{let e=n.selectionStart??n.value.length;p(n,A(n.value,e,i)),f(()=>{l=!1})});return}if(t.key===`Meta`)return;if(l){t.preventDefault();return}let r=t.key===`Backspace`,s=t.key===`Delete`,c=t.key.length===1&&!t.ctrlKey&&!t.altKey&&!t.metaKey;!r&&!s&&!c||f(()=>{let e=n.selectionStart??n.value.length;if(r){let e=N(n.value,i);if(e){p(n,e);return}}o!==0&&(t.key===`.`||t.key===`,`)&&t.key!==a&&e>0&&n.value[e-1]===t.key&&(n.value=n.value.slice(0,e-1)+a+n.value.slice(e)),p(n,(R(t.key)?P(n.value,e,t.key,i):null)??A(n.value,e,i))})};return e.addEventListener(`paste`,m),e.addEventListener(u,h),()=>{e.removeEventListener(`paste`,m),e.removeEventListener(u,h),e.removeAttribute(I);for(let t of s)e.removeAttribute(t);for(let e of d)cancelAnimationFrame(e);d.clear()}}exports.Mask=h,exports.applyDecimalMask=A,exports.applyMask=u,exports.bind=S,exports.bindDecimal=z,exports.buildMask=g,exports.formatDecimalValue=F,exports.getMaxLength=m,exports.process=_,exports.processDecimal=j,exports.unmaskDecimal=M;
|
|
2
2
|
//# sourceMappingURL=mother-mask.cjs.map
|