@mekari/pixel3-mask 0.1.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.
@@ -0,0 +1,22 @@
1
+ // src/tokens.ts
2
+ var tokens = {
3
+ "#": {
4
+ pattern: /[0-9]/
5
+ },
6
+ "S": {
7
+ pattern: /[a-zA-Z]/
8
+ },
9
+ "X": {
10
+ pattern: /[a-zA-Z0-9]/
11
+ },
12
+ "A": {
13
+ pattern: /[A-Z]/
14
+ },
15
+ "a": {
16
+ pattern: /[a-z]/
17
+ }
18
+ };
19
+
20
+ export {
21
+ tokens
22
+ };
@@ -0,0 +1,138 @@
1
+ import {
2
+ Mask
3
+ } from "./chunk-YR2EYYGF.mjs";
4
+ import {
5
+ parseInput
6
+ } from "./chunk-MAURZ3LV.mjs";
7
+ import {
8
+ __name,
9
+ __publicField
10
+ } from "./chunk-VYPKVKAE.mjs";
11
+
12
+ // src/input.ts
13
+ var _MaskInput = class _MaskInput {
14
+ constructor(target, options = {}) {
15
+ this.options = options;
16
+ __publicField(this, "items", /* @__PURE__ */ new Map());
17
+ __publicField(this, "eventAbortController");
18
+ __publicField(this, "onInput", /* @__PURE__ */ __name((e) => {
19
+ if (e instanceof CustomEvent && e.type === "input" && !e.isTrusted && !e.bubbles) {
20
+ return;
21
+ }
22
+ const input = e.target;
23
+ const mask = this.items.get(input);
24
+ const isDelete = "inputType" in e && e.inputType.startsWith("delete");
25
+ const isEager = mask.isEager();
26
+ const value = isDelete && isEager && mask.unmasked(input.value) === "" ? "" : input.value;
27
+ this.fixCursor(input, isDelete, () => this.setValue(input, value));
28
+ }, "onInput"));
29
+ this.eventAbortController = new AbortController();
30
+ this.init(this.getInputs(target));
31
+ }
32
+ update(options = {}) {
33
+ this.options = {
34
+ ...options
35
+ };
36
+ this.init(Array.from(this.items.keys()));
37
+ }
38
+ updateValue(input) {
39
+ if (input.value !== "" && input.value !== this.processInput(input).masked) {
40
+ this.setValue(input, input.value);
41
+ }
42
+ }
43
+ destroy() {
44
+ this.eventAbortController.abort();
45
+ this.items.clear();
46
+ }
47
+ init(inputs) {
48
+ const defaults = this.getOptions(this.options);
49
+ for (const input of inputs) {
50
+ if (!this.items.has(input)) {
51
+ const {
52
+ signal
53
+ } = this.eventAbortController;
54
+ input.addEventListener("input", this.onInput, {
55
+ capture: true,
56
+ signal
57
+ });
58
+ }
59
+ const mask = new Mask(parseInput(input, defaults));
60
+ this.items.set(input, mask);
61
+ queueMicrotask(() => this.updateValue(input));
62
+ if (input.selectionStart === null && mask.isEager()) {
63
+ console.warn("Mask: input of `%s` type is not supported", input.type);
64
+ }
65
+ }
66
+ }
67
+ getInputs(target) {
68
+ if (typeof target === "string") {
69
+ return Array.from(document.querySelectorAll(target));
70
+ }
71
+ return "length" in target ? Array.from(target) : [target];
72
+ }
73
+ getOptions(options) {
74
+ const {
75
+ onUpdate,
76
+ preProcess,
77
+ postProcess,
78
+ ...opts
79
+ } = options;
80
+ return opts;
81
+ }
82
+ fixCursor(input, isDelete, closure) {
83
+ const pos = input.selectionStart;
84
+ const value = input.value;
85
+ closure();
86
+ if (pos === null || pos === value.length && !isDelete)
87
+ return;
88
+ const valueNew = input.value;
89
+ const leftPart = value.slice(0, pos);
90
+ const leftPartNew = valueNew.slice(0, pos);
91
+ const unmasked = this.processInput(input, leftPart).unmasked;
92
+ const unmaskedNew = this.processInput(input, leftPartNew).unmasked;
93
+ let posFixed = pos;
94
+ if (leftPart !== leftPartNew) {
95
+ posFixed += isDelete ? valueNew.length - value.length : unmasked.length - unmaskedNew.length;
96
+ }
97
+ input.setSelectionRange(posFixed, posFixed);
98
+ }
99
+ setValue(input, value) {
100
+ const detail = this.processInput(input, value);
101
+ input.value = detail.masked;
102
+ if (this.options.onUpdate != null) {
103
+ if (Array.isArray(this.options.onUpdate)) {
104
+ this.options.onUpdate.forEach((f) => f(detail));
105
+ } else {
106
+ this.options.onUpdate(detail);
107
+ }
108
+ }
109
+ input.dispatchEvent(new CustomEvent("maska", {
110
+ detail
111
+ }));
112
+ input.dispatchEvent(new CustomEvent("input", {
113
+ detail: detail.masked
114
+ }));
115
+ }
116
+ processInput(input, value) {
117
+ const mask = this.items.get(input);
118
+ let valueNew = value != null ? value : input.value;
119
+ if (this.options.preProcess != null) {
120
+ valueNew = this.options.preProcess(valueNew);
121
+ }
122
+ let masked = mask.masked(valueNew);
123
+ if (this.options.postProcess != null) {
124
+ masked = this.options.postProcess(masked);
125
+ }
126
+ return {
127
+ masked,
128
+ unmasked: mask.unmasked(valueNew),
129
+ completed: mask.completed(valueNew)
130
+ };
131
+ }
132
+ };
133
+ __name(_MaskInput, "MaskInput");
134
+ var MaskInput = _MaskInput;
135
+
136
+ export {
137
+ MaskInput
138
+ };
@@ -0,0 +1,62 @@
1
+ import {
2
+ __name
3
+ } from "./chunk-VYPKVKAE.mjs";
4
+
5
+ // src/parser.ts
6
+ var parseJson = /* @__PURE__ */ __name((value) => JSON.parse(value.replaceAll("'", '"')), "parseJson");
7
+ var parseInput = /* @__PURE__ */ __name((input, defaults = {}) => {
8
+ const opts = {
9
+ ...defaults
10
+ };
11
+ if (input.dataset.maska != null && input.dataset.maska !== "") {
12
+ opts.mask = parseMask(input.dataset.maska);
13
+ }
14
+ if (input.dataset.maskaEager != null) {
15
+ opts.eager = parseBool(input.dataset.maskaEager);
16
+ }
17
+ if (input.dataset.maskaReversed != null) {
18
+ opts.reversed = parseBool(input.dataset.maskaReversed);
19
+ }
20
+ if (input.dataset.maskaTokensReplace != null) {
21
+ opts.tokensReplace = parseBool(input.dataset.maskaTokensReplace);
22
+ }
23
+ if (input.dataset.maskaTokens != null) {
24
+ opts.tokens = parseTokens(input.dataset.maskaTokens);
25
+ }
26
+ const number = {};
27
+ if (input.dataset.maskaNumberLocale != null) {
28
+ number.locale = input.dataset.maskaNumberLocale;
29
+ }
30
+ if (input.dataset.maskaNumberFraction != null) {
31
+ number.fraction = parseInt(input.dataset.maskaNumberFraction);
32
+ }
33
+ if (input.dataset.maskaNumberUnsigned != null) {
34
+ number.unsigned = parseBool(input.dataset.maskaNumberUnsigned);
35
+ }
36
+ if (input.dataset.maskaNumber != null || Object.values(number).length > 0) {
37
+ opts.number = number;
38
+ }
39
+ return opts;
40
+ }, "parseInput");
41
+ var parseBool = /* @__PURE__ */ __name((value) => value !== "" ? Boolean(JSON.parse(value)) : true, "parseBool");
42
+ var parseMask = /* @__PURE__ */ __name((value) => value.startsWith("[") && value.endsWith("]") ? parseJson(value) : value, "parseMask");
43
+ var parseTokens = /* @__PURE__ */ __name((value) => {
44
+ if (value.startsWith("{") && value.endsWith("}")) {
45
+ return parseJson(value);
46
+ }
47
+ const tokens = {};
48
+ value.split("|").forEach((token) => {
49
+ const parts = token.split(":");
50
+ tokens[parts[0]] = {
51
+ pattern: new RegExp(parts[1]),
52
+ optional: parts[2] === "optional",
53
+ multiple: parts[2] === "multiple",
54
+ repeated: parts[2] === "repeated"
55
+ };
56
+ });
57
+ return tokens;
58
+ }, "parseTokens");
59
+
60
+ export {
61
+ parseInput
62
+ };
@@ -0,0 +1,43 @@
1
+ import {
2
+ __name
3
+ } from "./chunk-VYPKVKAE.mjs";
4
+
5
+ // src/number.ts
6
+ var prepare = /* @__PURE__ */ __name((input, group, decimal) => input.replaceAll(group, "").replace(decimal, ".").replace("..", ".").replace(/[^.\d]/g, ""), "prepare");
7
+ var createFormatter = /* @__PURE__ */ __name((min, max, opts) => {
8
+ var _a, _b;
9
+ return new Intl.NumberFormat((_b = (_a = opts.number) == null ? void 0 : _a.locale) != null ? _b : "en", {
10
+ minimumFractionDigits: min,
11
+ maximumFractionDigits: max,
12
+ roundingMode: "trunc"
13
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
+ });
15
+ }, "createFormatter");
16
+ var processNumber = /* @__PURE__ */ __name((value, masked = true, opts) => {
17
+ var _a, _b, _c, _d, _e, _f, _g;
18
+ const sign = ((_a = opts.number) == null ? void 0 : _a.unsigned) !== true && value.startsWith("-") ? "-" : "";
19
+ const fraction = (_c = (_b = opts.number) == null ? void 0 : _b.fraction) != null ? _c : 0;
20
+ let formatter = createFormatter(0, fraction, opts);
21
+ const parts = formatter.formatToParts(1000.12);
22
+ const group = (_e = (_d = parts.find((part) => part.type === "group")) == null ? void 0 : _d.value) != null ? _e : " ";
23
+ const decimal = (_g = (_f = parts.find((part) => part.type === "decimal")) == null ? void 0 : _f.value) != null ? _g : ".";
24
+ const float = prepare(value, group, decimal);
25
+ if (Number.isNaN(parseFloat(float)))
26
+ return sign;
27
+ const floatParts = float.split(".");
28
+ if (floatParts[1] != null && floatParts[1].length >= 1) {
29
+ const min = floatParts[1].length <= fraction ? floatParts[1].length : fraction;
30
+ formatter = createFormatter(min, fraction, opts);
31
+ }
32
+ let result = formatter.format(parseFloat(float));
33
+ if (!masked) {
34
+ result = prepare(result, group, decimal);
35
+ } else if (fraction > 0 && float.endsWith(".") && !float.slice(0, -1).includes(".")) {
36
+ result += decimal;
37
+ }
38
+ return sign + result;
39
+ }, "processNumber");
40
+
41
+ export {
42
+ processNumber
43
+ };
@@ -0,0 +1,49 @@
1
+ import {
2
+ MaskInput
3
+ } from "./chunk-GPEHQJAT.mjs";
4
+ import {
5
+ __name
6
+ } from "./chunk-VYPKVKAE.mjs";
7
+
8
+ // src/directive.ts
9
+ var masks = /* @__PURE__ */ new WeakMap();
10
+ var setArg = /* @__PURE__ */ __name((binding, value) => {
11
+ if (binding.arg == null || binding.instance == null)
12
+ return;
13
+ const isComposition = "setup" in binding.instance.$.type;
14
+ if (binding.arg in binding.instance) {
15
+ binding.instance[binding.arg] = value;
16
+ } else if (isComposition) {
17
+ console.warn("Mask: please expose `%s` using defineExpose", binding.arg);
18
+ }
19
+ }, "setArg");
20
+ var vMask = /* @__PURE__ */ __name((el, binding) => {
21
+ var _a;
22
+ const input = el instanceof HTMLInputElement ? el : el.querySelector("input");
23
+ if (input == null || (input == null ? void 0 : input.type) === "file")
24
+ return;
25
+ let opts = {};
26
+ if (binding.value != null) {
27
+ opts = typeof binding.value === "string" ? {
28
+ mask: binding.value
29
+ } : {
30
+ ...binding.value
31
+ };
32
+ }
33
+ if (binding.arg != null) {
34
+ const updateArg = /* @__PURE__ */ __name((detail) => {
35
+ const value = binding.modifiers.unmasked ? detail.unmasked : binding.modifiers.completed ? detail.completed : detail.masked;
36
+ setArg(binding, value);
37
+ }, "updateArg");
38
+ opts.onUpdate = opts.onUpdate == null ? updateArg : Array.isArray(opts.onUpdate) ? [...opts.onUpdate, updateArg] : [opts.onUpdate, updateArg];
39
+ }
40
+ if (masks.has(input)) {
41
+ (_a = masks.get(input)) == null ? void 0 : _a.update(opts);
42
+ } else {
43
+ masks.set(input, new MaskInput(input, opts));
44
+ }
45
+ }, "vMask");
46
+
47
+ export {
48
+ vMask
49
+ };
@@ -0,0 +1,12 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
4
+ var __publicField = (obj, key, value) => {
5
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
6
+ return value;
7
+ };
8
+
9
+ export {
10
+ __name,
11
+ __publicField
12
+ };
@@ -0,0 +1,196 @@
1
+ import {
2
+ processNumber
3
+ } from "./chunk-SPWFCSFT.mjs";
4
+ import {
5
+ tokens
6
+ } from "./chunk-5TJYDLDA.mjs";
7
+ import {
8
+ __name,
9
+ __publicField
10
+ } from "./chunk-VYPKVKAE.mjs";
11
+
12
+ // src/mask.ts
13
+ var _Mask = class _Mask {
14
+ constructor(defaults = {}) {
15
+ __publicField(this, "opts", {});
16
+ __publicField(this, "memo", /* @__PURE__ */ new Map());
17
+ var _a;
18
+ const opts = {
19
+ ...defaults
20
+ };
21
+ if (opts.tokens != null) {
22
+ opts.tokens = opts.tokensReplace ? {
23
+ ...opts.tokens
24
+ } : {
25
+ ...tokens,
26
+ ...opts.tokens
27
+ };
28
+ for (const token of Object.values(opts.tokens)) {
29
+ if (typeof token.pattern === "string") {
30
+ token.pattern = new RegExp(token.pattern);
31
+ }
32
+ }
33
+ } else {
34
+ opts.tokens = tokens;
35
+ }
36
+ if (Array.isArray(opts.mask)) {
37
+ if (opts.mask.length > 1) {
38
+ opts.mask = [...opts.mask].sort((a, b) => a.length - b.length);
39
+ } else {
40
+ opts.mask = (_a = opts.mask[0]) != null ? _a : "";
41
+ }
42
+ }
43
+ if (opts.mask === "") {
44
+ opts.mask = null;
45
+ }
46
+ this.opts = opts;
47
+ }
48
+ masked(value) {
49
+ return this.process(String(value), this.findMask(String(value)));
50
+ }
51
+ unmasked(value) {
52
+ return this.process(String(value), this.findMask(String(value)), false);
53
+ }
54
+ isEager() {
55
+ return this.opts.eager === true;
56
+ }
57
+ isReversed() {
58
+ return this.opts.reversed === true;
59
+ }
60
+ completed(value) {
61
+ const mask = this.findMask(String(value));
62
+ if (this.opts.mask == null || mask == null)
63
+ return false;
64
+ const length = this.process(String(value), mask).length;
65
+ if (typeof this.opts.mask === "string") {
66
+ return length >= this.opts.mask.length;
67
+ }
68
+ return length >= mask.length;
69
+ }
70
+ findMask(value) {
71
+ var _a, _b;
72
+ const mask = this.opts.mask;
73
+ if (mask == null) {
74
+ return null;
75
+ } else if (typeof mask === "string") {
76
+ return mask;
77
+ } else if (typeof mask === "function") {
78
+ return mask(value);
79
+ }
80
+ const l = this.process(value, (_a = mask.slice(-1).pop()) != null ? _a : "", false);
81
+ return (_b = mask.find((el) => this.process(value, el, false).length >= l.length)) != null ? _b : "";
82
+ }
83
+ escapeMask(maskRaw) {
84
+ const chars = [];
85
+ const escaped = [];
86
+ maskRaw.split("").forEach((ch, i) => {
87
+ if (ch === "!" && maskRaw[i - 1] !== "!") {
88
+ escaped.push(i - escaped.length);
89
+ } else {
90
+ chars.push(ch);
91
+ }
92
+ });
93
+ return {
94
+ mask: chars.join(""),
95
+ escaped
96
+ };
97
+ }
98
+ process(value, maskRaw, masked = true) {
99
+ if (this.opts.number != null)
100
+ return processNumber(value, masked, this.opts);
101
+ if (maskRaw == null)
102
+ return value;
103
+ const memoKey = `v=${value},mr=${maskRaw},m=${masked ? 1 : 0}`;
104
+ if (this.memo.has(memoKey))
105
+ return this.memo.get(memoKey);
106
+ const {
107
+ mask,
108
+ escaped
109
+ } = this.escapeMask(maskRaw);
110
+ const result = [];
111
+ const tokens2 = this.opts.tokens != null ? this.opts.tokens : {};
112
+ const offset = this.isReversed() ? -1 : 1;
113
+ const method = this.isReversed() ? "unshift" : "push";
114
+ const lastMaskChar = this.isReversed() ? 0 : mask.length - 1;
115
+ const check = this.isReversed() ? () => m > -1 && v > -1 : () => m < mask.length && v < value.length;
116
+ const notLastMaskChar = /* @__PURE__ */ __name((m2) => !this.isReversed() && m2 <= lastMaskChar || this.isReversed() && m2 >= lastMaskChar, "notLastMaskChar");
117
+ let lastRawMaskChar;
118
+ let repeatedPos = -1;
119
+ let m = this.isReversed() ? mask.length - 1 : 0;
120
+ let v = this.isReversed() ? value.length - 1 : 0;
121
+ let multipleMatched = false;
122
+ while (check()) {
123
+ const maskChar = mask.charAt(m);
124
+ const token = tokens2[maskChar];
125
+ const valueChar = (token == null ? void 0 : token.transform) != null ? token.transform(value.charAt(v)) : value.charAt(v);
126
+ if (!escaped.includes(m) && token != null) {
127
+ if (valueChar.match(token.pattern) != null) {
128
+ result[method](valueChar);
129
+ if (token.repeated) {
130
+ if (repeatedPos === -1) {
131
+ repeatedPos = m;
132
+ } else if (m === lastMaskChar && m !== repeatedPos) {
133
+ m = repeatedPos - offset;
134
+ }
135
+ if (lastMaskChar === repeatedPos) {
136
+ m -= offset;
137
+ }
138
+ } else if (token.multiple) {
139
+ multipleMatched = true;
140
+ m -= offset;
141
+ }
142
+ m += offset;
143
+ } else if (token.multiple) {
144
+ if (multipleMatched) {
145
+ m += offset;
146
+ v -= offset;
147
+ multipleMatched = false;
148
+ } else {
149
+ }
150
+ } else if (valueChar === lastRawMaskChar) {
151
+ lastRawMaskChar = void 0;
152
+ } else if (token.optional) {
153
+ m += offset;
154
+ v -= offset;
155
+ } else {
156
+ }
157
+ v += offset;
158
+ } else {
159
+ if (masked && !this.isEager()) {
160
+ result[method](maskChar);
161
+ }
162
+ if (valueChar === maskChar && !this.isEager()) {
163
+ v += offset;
164
+ } else {
165
+ lastRawMaskChar = maskChar;
166
+ }
167
+ if (!this.isEager()) {
168
+ m += offset;
169
+ }
170
+ }
171
+ if (this.isEager()) {
172
+ while (notLastMaskChar(m) && (tokens2[mask.charAt(m)] == null || escaped.includes(m))) {
173
+ if (masked) {
174
+ result[method](mask.charAt(m));
175
+ if (value.charAt(v) === mask.charAt(m)) {
176
+ m += offset;
177
+ v += offset;
178
+ continue;
179
+ }
180
+ } else if (mask.charAt(m) === value.charAt(v)) {
181
+ v += offset;
182
+ }
183
+ m += offset;
184
+ }
185
+ }
186
+ }
187
+ this.memo.set(memoKey, result.join(""));
188
+ return this.memo.get(memoKey);
189
+ }
190
+ };
191
+ __name(_Mask, "Mask");
192
+ var Mask = _Mask;
193
+
194
+ export {
195
+ Mask
196
+ };
@@ -0,0 +1,9 @@
1
+ import { Directive } from 'vue';
2
+ import { MaskInputOptions } from './input.mjs';
3
+ import './mask.mjs';
4
+ import './tokens.mjs';
5
+
6
+ type MaskDirective = Directive<HTMLElement, MaskInputOptions | string | undefined>;
7
+ declare const vMask: MaskDirective;
8
+
9
+ export { vMask };
@@ -0,0 +1,9 @@
1
+ import { Directive } from 'vue';
2
+ import { MaskInputOptions } from './input.js';
3
+ import './mask.js';
4
+ import './tokens.js';
5
+
6
+ type MaskDirective = Directive<HTMLElement, MaskInputOptions | string | undefined>;
7
+ declare const vMask: MaskDirective;
8
+
9
+ export { vMask };