mother-mask 3.42.0 → 3.44.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 +41 -24
- package/dist/vue.cjs +1 -1
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.d.cts +48 -77
- package/dist/vue.d.mts +48 -77
- package/dist/vue.mjs +1 -1
- package/dist/vue.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -171,14 +171,14 @@ for a runnable app and browser lifecycle/memory tests.
|
|
|
171
171
|
|
|
172
172
|
## Vue
|
|
173
173
|
|
|
174
|
-
Import the
|
|
174
|
+
Import the custom directives from the separate `mother-mask/vue` entry:
|
|
175
175
|
|
|
176
176
|
```vue
|
|
177
177
|
<script setup lang="ts">
|
|
178
178
|
import { ref } from 'vue'
|
|
179
|
-
import {
|
|
179
|
+
import { vMotherMask, vMotherMaskDecimal, formatDecimalValue } from 'mother-mask/vue'
|
|
180
180
|
|
|
181
|
-
// Keep
|
|
181
|
+
// Keep the options object stable across renders.
|
|
182
182
|
const currency = { decimalPlaces: 2, prefix: '$', allowNegative: true }
|
|
183
183
|
|
|
184
184
|
const phone = ref('')
|
|
@@ -187,10 +187,19 @@ const amount = ref('')
|
|
|
187
187
|
|
|
188
188
|
<template>
|
|
189
189
|
<label for="phone">Phone</label>
|
|
190
|
-
<
|
|
190
|
+
<input
|
|
191
|
+
id="phone"
|
|
192
|
+
name="phone"
|
|
193
|
+
inputmode="tel"
|
|
194
|
+
v-mother-mask="{ mask: '(99) 99999-9999', value: phone, onValueChange: (v) => (phone = v) }"
|
|
195
|
+
/>
|
|
191
196
|
|
|
192
197
|
<label for="amount">Amount</label>
|
|
193
|
-
<
|
|
198
|
+
<input
|
|
199
|
+
id="amount"
|
|
200
|
+
name="amount"
|
|
201
|
+
v-mother-mask-decimal="{ options: currency, value: amount, onValueChange: (v) => (amount = v) }"
|
|
202
|
+
/>
|
|
194
203
|
|
|
195
204
|
<button type="button" @click="amount = formatDecimalValue(1234.5, currency)">
|
|
196
205
|
Set amount
|
|
@@ -199,25 +208,33 @@ const amount = ref('')
|
|
|
199
208
|
```
|
|
200
209
|
|
|
201
210
|
`mother-mask/vue` re-exports every core function, class, and type as well as
|
|
202
|
-
`
|
|
203
|
-
sharing the same implementation and caches. The
|
|
204
|
-
builds remain independent of Vue. Vue is an
|
|
205
|
-
only when importing `mother-mask/vue`; the
|
|
206
|
-
`^3.5.0`. Vue is not bundled.
|
|
207
|
-
|
|
208
|
-
-
|
|
209
|
-
`
|
|
210
|
-
`
|
|
211
|
-
`
|
|
212
|
-
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
`
|
|
211
|
+
the `vMotherMask` and `vMotherMaskDecimal` directives. Its core exports are
|
|
212
|
+
aliases to `mother-mask`, sharing the same implementation and caches. The
|
|
213
|
+
core ESM, CommonJS, and UMD builds remain independent of Vue. Vue is an
|
|
214
|
+
optional peer dependency required only when importing `mother-mask/vue`; the
|
|
215
|
+
supported version range is `^3.5.0`. Vue is not bundled.
|
|
216
|
+
|
|
217
|
+
- `vMotherMask` takes `{ mask, options?, value?, onValueChange? }`;
|
|
218
|
+
`vMotherMaskDecimal` takes `{ options?, value?, onValueChange? }` and calls
|
|
219
|
+
`onValueChange(value, numericValue)`. `vMotherMaskDecimal` always sets
|
|
220
|
+
`inputmode="decimal"` on mount.
|
|
221
|
+
- Both are exported pre-named `v` + PascalCase — Vue's own convention for a
|
|
222
|
+
local directive in `<script setup>` — so `import { vMotherMask } from
|
|
223
|
+
'mother-mask/vue'` alone makes `v-mother-mask="..."` available in the
|
|
224
|
+
template with no import rename. Register it globally instead with
|
|
225
|
+
`app.directive('mother-mask', vMotherMask)` to make `v-mother-mask`
|
|
226
|
+
available in every component.
|
|
227
|
+
- `mounted` runs only once Vue mounts the element to the live DOM — Vue
|
|
228
|
+
never invokes directive hooks during server-side rendering, so this is
|
|
229
|
+
SSR-safe with no `typeof window` guard needed. `updated` runs on every
|
|
230
|
+
re-render of the owning component (not only when the bound value actually
|
|
231
|
+
changes), so it rebinds only if the mask, options, or an externally-set
|
|
232
|
+
value actually changed — an echo of the directive's own `onValueChange` is
|
|
233
|
+
ignored. `beforeUnmount` guarantees `dispose()` runs exactly once.
|
|
234
|
+
- A `declare module 'vue' { interface GlobalDirectives { ... } }`
|
|
235
|
+
augmentation ships alongside each directive, so a globally-registered
|
|
236
|
+
`v-mother-mask`/`v-mother-mask-decimal` also type-checks in templates
|
|
237
|
+
without extra setup.
|
|
221
238
|
|
|
222
239
|
See the [Vue example](https://github.com/dan2dev/mother-mask/tree/main/examples/vue-simple)
|
|
223
240
|
for a runnable app.
|
package/dist/vue.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("mother-mask")
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("mother-mask");const t=new WeakMap;function n(e){e.dispose?.(),e.dispose=null}function r(t,r){n(r);let{mask:i,options:a,value:o}=r.current,s=o??t.value,c=(0,e.process)(s,i,a);t.value!==c&&(t.value=c),r.dispose=(0,e.bind)(t,i,{...a,onChange:e=>{r.lastEmitted=e,r.current.onValueChange?.(e)}})}function i(e,t,n){let i=t.current,a=n.mask!==i.mask||n.options!==i.options,o=n.value!==void 0&&n.value!==t.lastEmitted&&n.value!==e.value;t.current=n,(a||o)&&r(e,t)}const a={mounted(e,n){let i={current:n.value,dispose:null,lastEmitted:null};t.set(e,i),r(e,i)},updated(e,n){i(e,t.get(e),n.value)},beforeUnmount(e){n(t.get(e)),t.delete(e)}},o=new WeakMap;function s(e){e.dispose?.(),e.dispose=null}function c(t,n){s(n);let{options:r,value:i}=n.current,a=i??t.value,o=(0,e.processDecimal)(a,r);t.value!==o&&(t.value=o),n.dispose=(0,e.bindDecimal)(t,{...r,onChange:(e,t)=>{n.lastEmitted=e,n.current.onValueChange?.(e,t)}})}function l(e,t,n){let r=t.current,i=n.options!==r.options,a=n.value!==void 0&&n.value!==t.lastEmitted&&n.value!==e.value;t.current=n,(i||a)&&c(e,t)}const u={mounted(e,t){e.setAttribute(`inputmode`,`decimal`);let n={current:t.value,dispose:null,lastEmitted:null};o.set(e,n),c(e,n)},updated(e,t){l(e,o.get(e),t.value)},beforeUnmount(e){s(o.get(e)),o.delete(e)}};exports.vMotherMask=a,exports.vMotherMaskDecimal=u,Object.keys(e).forEach(function(t){t!=="default"&&!Object.prototype.hasOwnProperty.call(exports,t)&&Object.defineProperty(exports,t,{enumerable:!0,get:function(){return e[t]}})});
|
|
2
2
|
//# sourceMappingURL=vue.cjs.map
|
package/dist/vue.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vue.cjs","names":["
|
|
1
|
+
{"version":3,"file":"vue.cjs","names":["states","release","rebind","process","bind","sync","processDecimal","bindDecimal"],"sources":["../src/vue/mask-directive.ts","../src/vue/decimal-directive.ts"],"sourcesContent":["import type { Directive } from 'vue'\nimport { bind, process } from 'mother-mask'\nimport type { BindOptions, MaskPattern } from 'mother-mask'\n\nexport interface MaskDirectiveParams {\n mask: MaskPattern\n options?: Omit<BindOptions, 'onChange'>\n value?: string\n onValueChange?: (value: string) => void\n}\n\ninterface MaskDirectiveState {\n current: MaskDirectiveParams\n dispose: (() => void) | null\n lastEmitted: string | null\n}\n\n// A Vue directive definition object is shared across every element it's\n// bound to (unlike a Svelte action or Solid directive, both invoked fresh\n// per element with their own closure) — per-element state is keyed here by\n// the element instead.\nconst states = new WeakMap<HTMLInputElement, MaskDirectiveState>()\n\nfunction release(state: MaskDirectiveState) {\n state.dispose?.()\n state.dispose = null\n}\n\nfunction rebind(element: HTMLInputElement, state: MaskDirectiveState) {\n release(state)\n const { mask, options, value } = state.current\n const source = value ?? element.value\n const next = process(source, mask, options)\n if (element.value !== next) element.value = next\n state.dispose = bind(element, mask, {\n ...options,\n onChange: (maskedValue) => {\n state.lastEmitted = maskedValue\n state.current.onValueChange?.(maskedValue)\n },\n })\n}\n\nfunction sync(element: HTMLInputElement, state: MaskDirectiveState, next: MaskDirectiveParams) {\n const prev = state.current\n // An echo of our own onChange shows up as an update with an unchanged\n // mask/options and a value we just emitted — leave the live binding and\n // its editing state alone.\n const configChanged = next.mask !== prev.mask || next.options !== prev.options\n const externalValueChange = next.value !== undefined && next.value !== state.lastEmitted && next.value !== element.value\n state.current = next\n if (configChanged || externalValueChange) rebind(element, state)\n}\n\n/**\n * Vue custom directive wrapping {@link bind}: `v-mother-mask=\"{ mask, options, value, onValueChange }\"`.\n *\n * Exported pre-named `vMotherMask` — Vue's own convention for a local\n * directive in `<script setup>` is a top-level binding whose name is\n * `v` + PascalCase, so `import { vMotherMask } from 'mother-mask/vue'`\n * makes `v-mother-mask` available with no import rename. Register it\n * globally instead with `app.directive('mother-mask', vMotherMask)` to make\n * `v-mother-mask` available in every component.\n *\n * `mounted` runs only once Vue mounts the element to the live DOM — Vue\n * never invokes directive hooks during server-side rendering, so this is\n * SSR-safe with no `typeof window` guard needed. `updated` runs on every\n * re-render of the owning component (not only when the bound value actually\n * changes), so it rebinds only if the mask, options, or an externally-set\n * value actually changed. `beforeUnmount` guarantees `dispose()` runs\n * exactly once.\n */\nexport const vMotherMask: Directive<HTMLInputElement, MaskDirectiveParams> = {\n mounted(element, binding) {\n const state: MaskDirectiveState = { current: binding.value, dispose: null, lastEmitted: null }\n states.set(element, state)\n rebind(element, state)\n },\n updated(element, binding) {\n // `mounted` always runs first and seeds this element's entry, so it's\n // never missing here — Vue never calls `updated` on an element it\n // hasn't mounted the directive on.\n sync(element, states.get(element)!, binding.value)\n },\n beforeUnmount(element) {\n const state = states.get(element)!\n release(state)\n states.delete(element)\n },\n}\n\ndeclare module 'vue' {\n interface GlobalDirectives {\n vMotherMask: Directive<HTMLInputElement, MaskDirectiveParams>\n }\n}\n","import type { Directive } from 'vue'\nimport { bindDecimal, processDecimal } from 'mother-mask'\nimport type { BindDecimalOptions } from 'mother-mask'\n\nexport interface DecimalDirectiveParams {\n options?: Omit<BindDecimalOptions, 'onChange'>\n value?: string\n onValueChange?: (value: string, numericValue: number) => void\n}\n\ninterface DecimalDirectiveState {\n current: DecimalDirectiveParams\n dispose: (() => void) | null\n lastEmitted: string | null\n}\n\nconst states = new WeakMap<HTMLInputElement, DecimalDirectiveState>()\n\nfunction release(state: DecimalDirectiveState) {\n state.dispose?.()\n state.dispose = null\n}\n\nfunction rebind(element: HTMLInputElement, state: DecimalDirectiveState) {\n release(state)\n const { options, value } = state.current\n const source = value ?? element.value\n const next = processDecimal(source, options)\n if (element.value !== next) element.value = next\n state.dispose = bindDecimal(element, {\n ...options,\n onChange: (maskedValue, numericValue) => {\n state.lastEmitted = maskedValue\n state.current.onValueChange?.(maskedValue, numericValue)\n },\n })\n}\n\nfunction sync(element: HTMLInputElement, state: DecimalDirectiveState, next: DecimalDirectiveParams) {\n const prev = state.current\n const configChanged = next.options !== prev.options\n const externalValueChange = next.value !== undefined && next.value !== state.lastEmitted && next.value !== element.value\n state.current = next\n if (configChanged || externalValueChange) rebind(element, state)\n}\n\n/**\n * Vue custom directive wrapping {@link bindDecimal}: `v-mother-mask-decimal=\"{ options, value, onValueChange }\"`.\n * Exported pre-named `vMotherMaskDecimal`, same naming rationale and\n * directive lifecycle contract as {@link vMotherMask}: `mounted` binds\n * once, `updated` rebinds reactively, `beforeUnmount` guarantees\n * `dispose()`. Always sets `inputmode=\"decimal\"` on mount.\n */\nexport const vMotherMaskDecimal: Directive<HTMLInputElement, DecimalDirectiveParams> = {\n mounted(element, binding) {\n element.setAttribute('inputmode', 'decimal')\n const state: DecimalDirectiveState = { current: binding.value, dispose: null, lastEmitted: null }\n states.set(element, state)\n rebind(element, state)\n },\n updated(element, binding) {\n // `mounted` always runs first and seeds this element's entry, so it's\n // never missing here — Vue never calls `updated` on an element it\n // hasn't mounted the directive on.\n sync(element, states.get(element)!, binding.value)\n },\n beforeUnmount(element) {\n const state = states.get(element)!\n release(state)\n states.delete(element)\n },\n}\n\ndeclare module 'vue' {\n interface GlobalDirectives {\n vMotherMaskDecimal: Directive<HTMLInputElement, DecimalDirectiveParams>\n }\n}\n"],"mappings":"gGAqBA,MAAMA,EAAS,IAAI,QAEnB,SAASC,EAAQ,EAA2B,CAC1C,EAAM,UAAU,EAChB,EAAM,QAAU,IAClB,CAEA,SAASC,EAAO,EAA2B,EAA2B,CACpE,EAAQ,CAAK,EACb,GAAM,CAAE,OAAM,UAAS,SAAU,EAAM,QACjC,EAAS,GAAS,EAAQ,MAC1B,GAAA,EAAOC,EAAAA,QAAAA,CAAQ,EAAQ,EAAM,CAAO,EACtC,EAAQ,QAAU,IAAM,EAAQ,MAAQ,GAC5C,EAAM,SAAA,EAAUC,EAAAA,KAAAA,CAAK,EAAS,EAAM,CAClC,GAAG,EACH,SAAW,GAAgB,CACzB,EAAM,YAAc,EACpB,EAAM,QAAQ,gBAAgB,CAAW,CAC3C,CACF,CAAC,CACH,CAEA,SAASC,EAAK,EAA2B,EAA2B,EAA2B,CAC7F,IAAM,EAAO,EAAM,QAIb,EAAgB,EAAK,OAAS,EAAK,MAAQ,EAAK,UAAY,EAAK,QACjE,EAAsB,EAAK,QAAU,IAAA,IAAa,EAAK,QAAU,EAAM,aAAe,EAAK,QAAU,EAAQ,MACnH,EAAM,QAAU,GACZ,GAAiB,IAAqB,EAAO,EAAS,CAAK,CACjE,CAoBA,MAAa,EAAgE,CAC3E,QAAQ,EAAS,EAAS,CACxB,IAAM,EAA4B,CAAE,QAAS,EAAQ,MAAO,QAAS,KAAM,YAAa,IAAK,EAC7F,EAAO,IAAI,EAAS,CAAK,EACzB,EAAO,EAAS,CAAK,CACvB,EACA,QAAQ,EAAS,EAAS,CAIxB,EAAK,EAASL,EAAO,IAAI,CAAO,EAAI,EAAQ,KAAK,CACnD,EACA,cAAc,EAAS,CAErB,EADcA,EAAO,IAAI,CACb,CAAC,EACb,EAAO,OAAO,CAAO,CACvB,CACF,ECzEM,EAAS,IAAI,QAEnB,SAAS,EAAQ,EAA8B,CAC7C,EAAM,UAAU,EAChB,EAAM,QAAU,IAClB,CAEA,SAAS,EAAO,EAA2B,EAA8B,CACvE,EAAQ,CAAK,EACb,GAAM,CAAE,UAAS,SAAU,EAAM,QAC3B,EAAS,GAAS,EAAQ,MAC1B,GAAA,EAAOM,EAAAA,eAAAA,CAAe,EAAQ,CAAO,EACvC,EAAQ,QAAU,IAAM,EAAQ,MAAQ,GAC5C,EAAM,SAAA,EAAUC,EAAAA,YAAAA,CAAY,EAAS,CACnC,GAAG,EACH,UAAW,EAAa,IAAiB,CACvC,EAAM,YAAc,EACpB,EAAM,QAAQ,gBAAgB,EAAa,CAAY,CACzD,CACF,CAAC,CACH,CAEA,SAAS,EAAK,EAA2B,EAA8B,EAA8B,CACnG,IAAM,EAAO,EAAM,QACb,EAAgB,EAAK,UAAY,EAAK,QACtC,EAAsB,EAAK,QAAU,IAAA,IAAa,EAAK,QAAU,EAAM,aAAe,EAAK,QAAU,EAAQ,MACnH,EAAM,QAAU,GACZ,GAAiB,IAAqB,EAAO,EAAS,CAAK,CACjE,CASA,MAAa,EAA0E,CACrF,QAAQ,EAAS,EAAS,CACxB,EAAQ,aAAa,YAAa,SAAS,EAC3C,IAAM,EAA+B,CAAE,QAAS,EAAQ,MAAO,QAAS,KAAM,YAAa,IAAK,EAChG,EAAO,IAAI,EAAS,CAAK,EACzB,EAAO,EAAS,CAAK,CACvB,EACA,QAAQ,EAAS,EAAS,CAIxB,EAAK,EAAS,EAAO,IAAI,CAAO,EAAI,EAAQ,KAAK,CACnD,EACA,cAAc,EAAS,CAErB,EADc,EAAO,IAAI,CACb,CAAC,EACb,EAAO,OAAO,CAAO,CACvB,CACF"}
|
package/dist/vue.d.cts
CHANGED
|
@@ -1,86 +1,57 @@
|
|
|
1
1
|
import { BindDecimalOptions, BindOptions, MaskPattern } from "mother-mask";
|
|
2
|
-
import {
|
|
2
|
+
import { Directive } from "vue";
|
|
3
3
|
export * from "mother-mask";
|
|
4
|
-
//#region src/vue/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
//#region src/vue/mask-directive.d.ts
|
|
5
|
+
interface MaskDirectiveParams {
|
|
6
|
+
mask: MaskPattern;
|
|
7
|
+
options?: Omit<BindOptions, 'onChange'>;
|
|
8
|
+
value?: string;
|
|
9
|
+
onValueChange?: (value: string) => void;
|
|
10
|
+
}
|
|
8
11
|
/**
|
|
9
|
-
* Vue
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
+
* Vue custom directive wrapping {@link bind}: `v-mother-mask="{ mask, options, value, onValueChange }"`.
|
|
13
|
+
*
|
|
14
|
+
* Exported pre-named `vMotherMask` — Vue's own convention for a local
|
|
15
|
+
* directive in `<script setup>` is a top-level binding whose name is
|
|
16
|
+
* `v` + PascalCase, so `import { vMotherMask } from 'mother-mask/vue'`
|
|
17
|
+
* makes `v-mother-mask` available with no import rename. Register it
|
|
18
|
+
* globally instead with `app.directive('mother-mask', vMotherMask)` to make
|
|
19
|
+
* `v-mother-mask` available in every component.
|
|
20
|
+
*
|
|
21
|
+
* `mounted` runs only once Vue mounts the element to the live DOM — Vue
|
|
22
|
+
* never invokes directive hooks during server-side rendering, so this is
|
|
23
|
+
* SSR-safe with no `typeof window` guard needed. `updated` runs on every
|
|
24
|
+
* re-render of the owning component (not only when the bound value actually
|
|
25
|
+
* changes), so it rebinds only if the mask, options, or an externally-set
|
|
26
|
+
* value actually changed. `beforeUnmount` guarantees `dispose()` runs
|
|
27
|
+
* exactly once.
|
|
12
28
|
*/
|
|
13
|
-
declare const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
type: PropType<Omit<BindOptions, 'onChange'>>;
|
|
20
|
-
default: undefined;
|
|
21
|
-
};
|
|
22
|
-
modelValue: {
|
|
23
|
-
type: StringConstructor;
|
|
24
|
-
default: undefined;
|
|
25
|
-
};
|
|
26
|
-
}>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
27
|
-
[key: string]: any;
|
|
28
|
-
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "update:modelValue"[], "update:modelValue", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
29
|
-
mask: {
|
|
30
|
-
type: PropType<MaskPattern>;
|
|
31
|
-
required: true;
|
|
32
|
-
};
|
|
33
|
-
options: {
|
|
34
|
-
type: PropType<Omit<BindOptions, 'onChange'>>;
|
|
35
|
-
default: undefined;
|
|
36
|
-
};
|
|
37
|
-
modelValue: {
|
|
38
|
-
type: StringConstructor;
|
|
39
|
-
default: undefined;
|
|
40
|
-
};
|
|
41
|
-
}>> & Readonly<{
|
|
42
|
-
"onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
|
|
43
|
-
}>, {
|
|
44
|
-
options: Omit<BindOptions, "onChange">;
|
|
45
|
-
modelValue: string;
|
|
46
|
-
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
29
|
+
declare const vMotherMask: Directive<HTMLInputElement, MaskDirectiveParams>;
|
|
30
|
+
declare module 'vue' {
|
|
31
|
+
interface GlobalDirectives {
|
|
32
|
+
vMotherMask: Directive<HTMLInputElement, MaskDirectiveParams>;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
47
35
|
//#endregion
|
|
48
|
-
//#region src/vue/
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
36
|
+
//#region src/vue/decimal-directive.d.ts
|
|
37
|
+
interface DecimalDirectiveParams {
|
|
38
|
+
options?: Omit<BindDecimalOptions, 'onChange'>;
|
|
39
|
+
value?: string;
|
|
40
|
+
onValueChange?: (value: string, numericValue: number) => void;
|
|
41
|
+
}
|
|
52
42
|
/**
|
|
53
|
-
* Vue
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
43
|
+
* Vue custom directive wrapping {@link bindDecimal}: `v-mother-mask-decimal="{ options, value, onValueChange }"`.
|
|
44
|
+
* Exported pre-named `vMotherMaskDecimal`, same naming rationale and
|
|
45
|
+
* directive lifecycle contract as {@link vMotherMask}: `mounted` binds
|
|
46
|
+
* once, `updated` rebinds reactively, `beforeUnmount` guarantees
|
|
47
|
+
* `dispose()`. Always sets `inputmode="decimal"` on mount.
|
|
57
48
|
*/
|
|
58
|
-
declare const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
type: StringConstructor;
|
|
65
|
-
default: undefined;
|
|
66
|
-
};
|
|
67
|
-
}>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
68
|
-
[key: string]: any;
|
|
69
|
-
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "update:modelValue"[], "update:modelValue", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
70
|
-
options: {
|
|
71
|
-
type: PropType<Omit<BindDecimalOptions, 'onChange'>>;
|
|
72
|
-
default: undefined;
|
|
73
|
-
};
|
|
74
|
-
modelValue: {
|
|
75
|
-
type: StringConstructor;
|
|
76
|
-
default: undefined;
|
|
77
|
-
};
|
|
78
|
-
}>> & Readonly<{
|
|
79
|
-
"onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
|
|
80
|
-
}>, {
|
|
81
|
-
options: Omit<BindDecimalOptions, "onChange">;
|
|
82
|
-
modelValue: string;
|
|
83
|
-
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
49
|
+
declare const vMotherMaskDecimal: Directive<HTMLInputElement, DecimalDirectiveParams>;
|
|
50
|
+
declare module 'vue' {
|
|
51
|
+
interface GlobalDirectives {
|
|
52
|
+
vMotherMaskDecimal: Directive<HTMLInputElement, DecimalDirectiveParams>;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
84
55
|
//#endregion
|
|
85
|
-
export {
|
|
56
|
+
export { type DecimalDirectiveParams, type MaskDirectiveParams, vMotherMask, vMotherMaskDecimal };
|
|
86
57
|
//# sourceMappingURL=vue.d.cts.map
|
package/dist/vue.d.mts
CHANGED
|
@@ -1,86 +1,57 @@
|
|
|
1
1
|
import { BindDecimalOptions, BindOptions, MaskPattern } from "mother-mask";
|
|
2
|
-
import {
|
|
2
|
+
import { Directive } from "vue";
|
|
3
3
|
export * from "mother-mask";
|
|
4
|
-
//#region src/vue/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
//#region src/vue/mask-directive.d.ts
|
|
5
|
+
interface MaskDirectiveParams {
|
|
6
|
+
mask: MaskPattern;
|
|
7
|
+
options?: Omit<BindOptions, 'onChange'>;
|
|
8
|
+
value?: string;
|
|
9
|
+
onValueChange?: (value: string) => void;
|
|
10
|
+
}
|
|
8
11
|
/**
|
|
9
|
-
* Vue
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
+
* Vue custom directive wrapping {@link bind}: `v-mother-mask="{ mask, options, value, onValueChange }"`.
|
|
13
|
+
*
|
|
14
|
+
* Exported pre-named `vMotherMask` — Vue's own convention for a local
|
|
15
|
+
* directive in `<script setup>` is a top-level binding whose name is
|
|
16
|
+
* `v` + PascalCase, so `import { vMotherMask } from 'mother-mask/vue'`
|
|
17
|
+
* makes `v-mother-mask` available with no import rename. Register it
|
|
18
|
+
* globally instead with `app.directive('mother-mask', vMotherMask)` to make
|
|
19
|
+
* `v-mother-mask` available in every component.
|
|
20
|
+
*
|
|
21
|
+
* `mounted` runs only once Vue mounts the element to the live DOM — Vue
|
|
22
|
+
* never invokes directive hooks during server-side rendering, so this is
|
|
23
|
+
* SSR-safe with no `typeof window` guard needed. `updated` runs on every
|
|
24
|
+
* re-render of the owning component (not only when the bound value actually
|
|
25
|
+
* changes), so it rebinds only if the mask, options, or an externally-set
|
|
26
|
+
* value actually changed. `beforeUnmount` guarantees `dispose()` runs
|
|
27
|
+
* exactly once.
|
|
12
28
|
*/
|
|
13
|
-
declare const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
type: PropType<Omit<BindOptions, 'onChange'>>;
|
|
20
|
-
default: undefined;
|
|
21
|
-
};
|
|
22
|
-
modelValue: {
|
|
23
|
-
type: StringConstructor;
|
|
24
|
-
default: undefined;
|
|
25
|
-
};
|
|
26
|
-
}>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
27
|
-
[key: string]: any;
|
|
28
|
-
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "update:modelValue"[], "update:modelValue", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
29
|
-
mask: {
|
|
30
|
-
type: PropType<MaskPattern>;
|
|
31
|
-
required: true;
|
|
32
|
-
};
|
|
33
|
-
options: {
|
|
34
|
-
type: PropType<Omit<BindOptions, 'onChange'>>;
|
|
35
|
-
default: undefined;
|
|
36
|
-
};
|
|
37
|
-
modelValue: {
|
|
38
|
-
type: StringConstructor;
|
|
39
|
-
default: undefined;
|
|
40
|
-
};
|
|
41
|
-
}>> & Readonly<{
|
|
42
|
-
"onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
|
|
43
|
-
}>, {
|
|
44
|
-
options: Omit<BindOptions, "onChange">;
|
|
45
|
-
modelValue: string;
|
|
46
|
-
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
29
|
+
declare const vMotherMask: Directive<HTMLInputElement, MaskDirectiveParams>;
|
|
30
|
+
declare module 'vue' {
|
|
31
|
+
interface GlobalDirectives {
|
|
32
|
+
vMotherMask: Directive<HTMLInputElement, MaskDirectiveParams>;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
47
35
|
//#endregion
|
|
48
|
-
//#region src/vue/
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
36
|
+
//#region src/vue/decimal-directive.d.ts
|
|
37
|
+
interface DecimalDirectiveParams {
|
|
38
|
+
options?: Omit<BindDecimalOptions, 'onChange'>;
|
|
39
|
+
value?: string;
|
|
40
|
+
onValueChange?: (value: string, numericValue: number) => void;
|
|
41
|
+
}
|
|
52
42
|
/**
|
|
53
|
-
* Vue
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
43
|
+
* Vue custom directive wrapping {@link bindDecimal}: `v-mother-mask-decimal="{ options, value, onValueChange }"`.
|
|
44
|
+
* Exported pre-named `vMotherMaskDecimal`, same naming rationale and
|
|
45
|
+
* directive lifecycle contract as {@link vMotherMask}: `mounted` binds
|
|
46
|
+
* once, `updated` rebinds reactively, `beforeUnmount` guarantees
|
|
47
|
+
* `dispose()`. Always sets `inputmode="decimal"` on mount.
|
|
57
48
|
*/
|
|
58
|
-
declare const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
type: StringConstructor;
|
|
65
|
-
default: undefined;
|
|
66
|
-
};
|
|
67
|
-
}>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
68
|
-
[key: string]: any;
|
|
69
|
-
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "update:modelValue"[], "update:modelValue", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
70
|
-
options: {
|
|
71
|
-
type: PropType<Omit<BindDecimalOptions, 'onChange'>>;
|
|
72
|
-
default: undefined;
|
|
73
|
-
};
|
|
74
|
-
modelValue: {
|
|
75
|
-
type: StringConstructor;
|
|
76
|
-
default: undefined;
|
|
77
|
-
};
|
|
78
|
-
}>> & Readonly<{
|
|
79
|
-
"onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
|
|
80
|
-
}>, {
|
|
81
|
-
options: Omit<BindDecimalOptions, "onChange">;
|
|
82
|
-
modelValue: string;
|
|
83
|
-
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
49
|
+
declare const vMotherMaskDecimal: Directive<HTMLInputElement, DecimalDirectiveParams>;
|
|
50
|
+
declare module 'vue' {
|
|
51
|
+
interface GlobalDirectives {
|
|
52
|
+
vMotherMaskDecimal: Directive<HTMLInputElement, DecimalDirectiveParams>;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
84
55
|
//#endregion
|
|
85
|
-
export {
|
|
56
|
+
export { type DecimalDirectiveParams, type MaskDirectiveParams, vMotherMask, vMotherMaskDecimal };
|
|
86
57
|
//# sourceMappingURL=vue.d.mts.map
|
package/dist/vue.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{bind as e,bindDecimal as t,process as n,processDecimal as r}from"mother-mask";
|
|
1
|
+
import{bind as e,bindDecimal as t,process as n,processDecimal as r}from"mother-mask";export*from"mother-mask";const i=new WeakMap;function a(e){e.dispose?.(),e.dispose=null}function o(t,r){a(r);let{mask:i,options:o,value:s}=r.current,c=s??t.value,l=n(c,i,o);t.value!==l&&(t.value=l),r.dispose=e(t,i,{...o,onChange:e=>{r.lastEmitted=e,r.current.onValueChange?.(e)}})}function s(e,t,n){let r=t.current,i=n.mask!==r.mask||n.options!==r.options,a=n.value!==void 0&&n.value!==t.lastEmitted&&n.value!==e.value;t.current=n,(i||a)&&o(e,t)}const c={mounted(e,t){let n={current:t.value,dispose:null,lastEmitted:null};i.set(e,n),o(e,n)},updated(e,t){s(e,i.get(e),t.value)},beforeUnmount(e){a(i.get(e)),i.delete(e)}},l=new WeakMap;function u(e){e.dispose?.(),e.dispose=null}function d(e,n){u(n);let{options:i,value:a}=n.current,o=a??e.value,s=r(o,i);e.value!==s&&(e.value=s),n.dispose=t(e,{...i,onChange:(e,t)=>{n.lastEmitted=e,n.current.onValueChange?.(e,t)}})}function f(e,t,n){let r=t.current,i=n.options!==r.options,a=n.value!==void 0&&n.value!==t.lastEmitted&&n.value!==e.value;t.current=n,(i||a)&&d(e,t)}const p={mounted(e,t){e.setAttribute(`inputmode`,`decimal`);let n={current:t.value,dispose:null,lastEmitted:null};l.set(e,n),d(e,n)},updated(e,t){f(e,l.get(e),t.value)},beforeUnmount(e){u(l.get(e)),l.delete(e)}};export{c as vMotherMask,p as vMotherMaskDecimal};
|
|
2
2
|
//# sourceMappingURL=vue.mjs.map
|
package/dist/vue.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vue.mjs","names":[],"sources":["../src/vue/
|
|
1
|
+
{"version":3,"file":"vue.mjs","names":["states","release","rebind","sync"],"sources":["../src/vue/mask-directive.ts","../src/vue/decimal-directive.ts"],"sourcesContent":["import type { Directive } from 'vue'\nimport { bind, process } from 'mother-mask'\nimport type { BindOptions, MaskPattern } from 'mother-mask'\n\nexport interface MaskDirectiveParams {\n mask: MaskPattern\n options?: Omit<BindOptions, 'onChange'>\n value?: string\n onValueChange?: (value: string) => void\n}\n\ninterface MaskDirectiveState {\n current: MaskDirectiveParams\n dispose: (() => void) | null\n lastEmitted: string | null\n}\n\n// A Vue directive definition object is shared across every element it's\n// bound to (unlike a Svelte action or Solid directive, both invoked fresh\n// per element with their own closure) — per-element state is keyed here by\n// the element instead.\nconst states = new WeakMap<HTMLInputElement, MaskDirectiveState>()\n\nfunction release(state: MaskDirectiveState) {\n state.dispose?.()\n state.dispose = null\n}\n\nfunction rebind(element: HTMLInputElement, state: MaskDirectiveState) {\n release(state)\n const { mask, options, value } = state.current\n const source = value ?? element.value\n const next = process(source, mask, options)\n if (element.value !== next) element.value = next\n state.dispose = bind(element, mask, {\n ...options,\n onChange: (maskedValue) => {\n state.lastEmitted = maskedValue\n state.current.onValueChange?.(maskedValue)\n },\n })\n}\n\nfunction sync(element: HTMLInputElement, state: MaskDirectiveState, next: MaskDirectiveParams) {\n const prev = state.current\n // An echo of our own onChange shows up as an update with an unchanged\n // mask/options and a value we just emitted — leave the live binding and\n // its editing state alone.\n const configChanged = next.mask !== prev.mask || next.options !== prev.options\n const externalValueChange = next.value !== undefined && next.value !== state.lastEmitted && next.value !== element.value\n state.current = next\n if (configChanged || externalValueChange) rebind(element, state)\n}\n\n/**\n * Vue custom directive wrapping {@link bind}: `v-mother-mask=\"{ mask, options, value, onValueChange }\"`.\n *\n * Exported pre-named `vMotherMask` — Vue's own convention for a local\n * directive in `<script setup>` is a top-level binding whose name is\n * `v` + PascalCase, so `import { vMotherMask } from 'mother-mask/vue'`\n * makes `v-mother-mask` available with no import rename. Register it\n * globally instead with `app.directive('mother-mask', vMotherMask)` to make\n * `v-mother-mask` available in every component.\n *\n * `mounted` runs only once Vue mounts the element to the live DOM — Vue\n * never invokes directive hooks during server-side rendering, so this is\n * SSR-safe with no `typeof window` guard needed. `updated` runs on every\n * re-render of the owning component (not only when the bound value actually\n * changes), so it rebinds only if the mask, options, or an externally-set\n * value actually changed. `beforeUnmount` guarantees `dispose()` runs\n * exactly once.\n */\nexport const vMotherMask: Directive<HTMLInputElement, MaskDirectiveParams> = {\n mounted(element, binding) {\n const state: MaskDirectiveState = { current: binding.value, dispose: null, lastEmitted: null }\n states.set(element, state)\n rebind(element, state)\n },\n updated(element, binding) {\n // `mounted` always runs first and seeds this element's entry, so it's\n // never missing here — Vue never calls `updated` on an element it\n // hasn't mounted the directive on.\n sync(element, states.get(element)!, binding.value)\n },\n beforeUnmount(element) {\n const state = states.get(element)!\n release(state)\n states.delete(element)\n },\n}\n\ndeclare module 'vue' {\n interface GlobalDirectives {\n vMotherMask: Directive<HTMLInputElement, MaskDirectiveParams>\n }\n}\n","import type { Directive } from 'vue'\nimport { bindDecimal, processDecimal } from 'mother-mask'\nimport type { BindDecimalOptions } from 'mother-mask'\n\nexport interface DecimalDirectiveParams {\n options?: Omit<BindDecimalOptions, 'onChange'>\n value?: string\n onValueChange?: (value: string, numericValue: number) => void\n}\n\ninterface DecimalDirectiveState {\n current: DecimalDirectiveParams\n dispose: (() => void) | null\n lastEmitted: string | null\n}\n\nconst states = new WeakMap<HTMLInputElement, DecimalDirectiveState>()\n\nfunction release(state: DecimalDirectiveState) {\n state.dispose?.()\n state.dispose = null\n}\n\nfunction rebind(element: HTMLInputElement, state: DecimalDirectiveState) {\n release(state)\n const { options, value } = state.current\n const source = value ?? element.value\n const next = processDecimal(source, options)\n if (element.value !== next) element.value = next\n state.dispose = bindDecimal(element, {\n ...options,\n onChange: (maskedValue, numericValue) => {\n state.lastEmitted = maskedValue\n state.current.onValueChange?.(maskedValue, numericValue)\n },\n })\n}\n\nfunction sync(element: HTMLInputElement, state: DecimalDirectiveState, next: DecimalDirectiveParams) {\n const prev = state.current\n const configChanged = next.options !== prev.options\n const externalValueChange = next.value !== undefined && next.value !== state.lastEmitted && next.value !== element.value\n state.current = next\n if (configChanged || externalValueChange) rebind(element, state)\n}\n\n/**\n * Vue custom directive wrapping {@link bindDecimal}: `v-mother-mask-decimal=\"{ options, value, onValueChange }\"`.\n * Exported pre-named `vMotherMaskDecimal`, same naming rationale and\n * directive lifecycle contract as {@link vMotherMask}: `mounted` binds\n * once, `updated` rebinds reactively, `beforeUnmount` guarantees\n * `dispose()`. Always sets `inputmode=\"decimal\"` on mount.\n */\nexport const vMotherMaskDecimal: Directive<HTMLInputElement, DecimalDirectiveParams> = {\n mounted(element, binding) {\n element.setAttribute('inputmode', 'decimal')\n const state: DecimalDirectiveState = { current: binding.value, dispose: null, lastEmitted: null }\n states.set(element, state)\n rebind(element, state)\n },\n updated(element, binding) {\n // `mounted` always runs first and seeds this element's entry, so it's\n // never missing here — Vue never calls `updated` on an element it\n // hasn't mounted the directive on.\n sync(element, states.get(element)!, binding.value)\n },\n beforeUnmount(element) {\n const state = states.get(element)!\n release(state)\n states.delete(element)\n },\n}\n\ndeclare module 'vue' {\n interface GlobalDirectives {\n vMotherMaskDecimal: Directive<HTMLInputElement, DecimalDirectiveParams>\n }\n}\n"],"mappings":"8GAqBA,MAAMA,EAAS,IAAI,QAEnB,SAASC,EAAQ,EAA2B,CAC1C,EAAM,UAAU,EAChB,EAAM,QAAU,IAClB,CAEA,SAASC,EAAO,EAA2B,EAA2B,CACpE,EAAQ,CAAK,EACb,GAAM,CAAE,OAAM,UAAS,SAAU,EAAM,QACjC,EAAS,GAAS,EAAQ,MAC1B,EAAO,EAAQ,EAAQ,EAAM,CAAO,EACtC,EAAQ,QAAU,IAAM,EAAQ,MAAQ,GAC5C,EAAM,QAAU,EAAK,EAAS,EAAM,CAClC,GAAG,EACH,SAAW,GAAgB,CACzB,EAAM,YAAc,EACpB,EAAM,QAAQ,gBAAgB,CAAW,CAC3C,CACF,CAAC,CACH,CAEA,SAASC,EAAK,EAA2B,EAA2B,EAA2B,CAC7F,IAAM,EAAO,EAAM,QAIb,EAAgB,EAAK,OAAS,EAAK,MAAQ,EAAK,UAAY,EAAK,QACjE,EAAsB,EAAK,QAAU,IAAA,IAAa,EAAK,QAAU,EAAM,aAAe,EAAK,QAAU,EAAQ,MACnH,EAAM,QAAU,GACZ,GAAiB,IAAqB,EAAO,EAAS,CAAK,CACjE,CAoBA,MAAa,EAAgE,CAC3E,QAAQ,EAAS,EAAS,CACxB,IAAM,EAA4B,CAAE,QAAS,EAAQ,MAAO,QAAS,KAAM,YAAa,IAAK,EAC7F,EAAO,IAAI,EAAS,CAAK,EACzB,EAAO,EAAS,CAAK,CACvB,EACA,QAAQ,EAAS,EAAS,CAIxB,EAAK,EAASH,EAAO,IAAI,CAAO,EAAI,EAAQ,KAAK,CACnD,EACA,cAAc,EAAS,CAErB,EADcA,EAAO,IAAI,CACb,CAAC,EACb,EAAO,OAAO,CAAO,CACvB,CACF,ECzEM,EAAS,IAAI,QAEnB,SAAS,EAAQ,EAA8B,CAC7C,EAAM,UAAU,EAChB,EAAM,QAAU,IAClB,CAEA,SAAS,EAAO,EAA2B,EAA8B,CACvE,EAAQ,CAAK,EACb,GAAM,CAAE,UAAS,SAAU,EAAM,QAC3B,EAAS,GAAS,EAAQ,MAC1B,EAAO,EAAe,EAAQ,CAAO,EACvC,EAAQ,QAAU,IAAM,EAAQ,MAAQ,GAC5C,EAAM,QAAU,EAAY,EAAS,CACnC,GAAG,EACH,UAAW,EAAa,IAAiB,CACvC,EAAM,YAAc,EACpB,EAAM,QAAQ,gBAAgB,EAAa,CAAY,CACzD,CACF,CAAC,CACH,CAEA,SAAS,EAAK,EAA2B,EAA8B,EAA8B,CACnG,IAAM,EAAO,EAAM,QACb,EAAgB,EAAK,UAAY,EAAK,QACtC,EAAsB,EAAK,QAAU,IAAA,IAAa,EAAK,QAAU,EAAM,aAAe,EAAK,QAAU,EAAQ,MACnH,EAAM,QAAU,GACZ,GAAiB,IAAqB,EAAO,EAAS,CAAK,CACjE,CASA,MAAa,EAA0E,CACrF,QAAQ,EAAS,EAAS,CACxB,EAAQ,aAAa,YAAa,SAAS,EAC3C,IAAM,EAA+B,CAAE,QAAS,EAAQ,MAAO,QAAS,KAAM,YAAa,IAAK,EAChG,EAAO,IAAI,EAAS,CAAK,EACzB,EAAO,EAAS,CAAK,CACvB,EACA,QAAQ,EAAS,EAAS,CAIxB,EAAK,EAAS,EAAO,IAAI,CAAO,EAAI,EAAQ,KAAK,CACnD,EACA,cAAc,EAAS,CAErB,EADc,EAAO,IAAI,CACb,CAAC,EACb,EAAO,OAAO,CAAO,CACvB,CACF"}
|