@samline/forms 1.0.3 → 2.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.
- package/README.md +87 -199
- package/dist/browser/global.d.ts +152 -0
- package/dist/browser/global.global.js +788 -474
- package/dist/browser/global.global.js.map +1 -1
- package/dist/index.cjs +763 -470
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +141 -3
- package/dist/index.d.ts +141 -3
- package/dist/index.js +970 -13
- package/dist/index.js.map +1 -1
- package/package.json +8 -43
- package/dist/chunk-4NEGCRY2.js +0 -125
- package/dist/chunk-4NEGCRY2.js.map +0 -1
- package/dist/chunk-PCKGH2WA.js +0 -11
- package/dist/chunk-PCKGH2WA.js.map +0 -1
- package/dist/chunk-WM2CL7IO.js +0 -576
- package/dist/chunk-WM2CL7IO.js.map +0 -1
- package/dist/core/index.cjs +0 -154
- package/dist/core/index.cjs.map +0 -1
- package/dist/core/index.d.cts +0 -11
- package/dist/core/index.d.ts +0 -11
- package/dist/core/index.js +0 -13
- package/dist/core/index.js.map +0 -1
- package/dist/react/index.cjs +0 -734
- package/dist/react/index.cjs.map +0 -1
- package/dist/react/index.d.cts +0 -10
- package/dist/react/index.d.ts +0 -10
- package/dist/react/index.js +0 -43
- package/dist/react/index.js.map +0 -1
- package/dist/svelte/index.cjs +0 -764
- package/dist/svelte/index.cjs.map +0 -1
- package/dist/svelte/index.d.cts +0 -20
- package/dist/svelte/index.d.ts +0 -20
- package/dist/svelte/index.js +0 -72
- package/dist/svelte/index.js.map +0 -1
- package/dist/types-jYB7Wp7C.d.cts +0 -95
- package/dist/types-jYB7Wp7C.d.ts +0 -95
- package/dist/vanilla/index.cjs +0 -705
- package/dist/vanilla/index.cjs.map +0 -1
- package/dist/vanilla/index.d.cts +0 -7
- package/dist/vanilla/index.d.ts +0 -7
- package/dist/vanilla/index.js +0 -12
- package/dist/vanilla/index.js.map +0 -1
- package/dist/vue/index.cjs +0 -741
- package/dist/vue/index.cjs.map +0 -1
- package/dist/vue/index.d.cts +0 -13
- package/dist/vue/index.d.ts +0 -13
- package/dist/vue/index.js +0 -56
- package/dist/vue/index.js.map +0 -1
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
2
|
+
var Forms = (() => {
|
|
3
|
+
var __create = Object.create;
|
|
3
4
|
var __defProp = Object.defineProperty;
|
|
4
5
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
6
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
10
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
11
|
+
}) : x)(function(x) {
|
|
12
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
13
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
14
|
+
});
|
|
7
15
|
var __export = (target, all) => {
|
|
8
16
|
for (var name in all)
|
|
9
17
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -16,6 +24,14 @@ var SamlineForms = (() => {
|
|
|
16
24
|
}
|
|
17
25
|
return to;
|
|
18
26
|
};
|
|
27
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
28
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
29
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
30
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
31
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
32
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
33
|
+
mod
|
|
34
|
+
));
|
|
19
35
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
36
|
|
|
21
37
|
// src/browser/global.ts
|
|
@@ -24,6 +40,353 @@ var SamlineForms = (() => {
|
|
|
24
40
|
default: () => global_default
|
|
25
41
|
});
|
|
26
42
|
|
|
43
|
+
// src/api/append.ts
|
|
44
|
+
var createAppend = (state2, helpers) => ({ tag, content, class: className, atStart = false }) => {
|
|
45
|
+
if (!state2.element) return null;
|
|
46
|
+
helpers.clearFieldCache();
|
|
47
|
+
if (className) {
|
|
48
|
+
const classSelector = className.trim().split(/\s+/)[0];
|
|
49
|
+
const existing = classSelector ? state2.element.querySelector(`.${classSelector}`) : null;
|
|
50
|
+
existing?.remove();
|
|
51
|
+
}
|
|
52
|
+
const node = document.createElement(tag);
|
|
53
|
+
if (className) node.className = className;
|
|
54
|
+
node.innerHTML = content;
|
|
55
|
+
if (atStart && state2.element.firstChild) {
|
|
56
|
+
state2.element.insertBefore(node, state2.element.firstChild);
|
|
57
|
+
} else {
|
|
58
|
+
state2.element.appendChild(node);
|
|
59
|
+
}
|
|
60
|
+
return node;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// src/api/auto-submit.ts
|
|
64
|
+
var createAutoSubmit = (state2, helpers) => (next = true) => {
|
|
65
|
+
state2.autoSubmitEnabled = next !== false;
|
|
66
|
+
state2.autoSubmitDebounce = typeof next === "object" && next ? next.debounce ?? 0 : 0;
|
|
67
|
+
helpers.notifySubscribers();
|
|
68
|
+
return state2.api;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// src/api/clear-errors.ts
|
|
72
|
+
var createClearErrors = (state2, helpers) => (fields) => {
|
|
73
|
+
if (!fields) {
|
|
74
|
+
state2.manualErrors = {};
|
|
75
|
+
helpers.syncVisualState();
|
|
76
|
+
helpers.notifySubscribers();
|
|
77
|
+
return state2.api;
|
|
78
|
+
}
|
|
79
|
+
for (const field of fields) {
|
|
80
|
+
delete state2.manualErrors[field];
|
|
81
|
+
}
|
|
82
|
+
helpers.syncVisualState(fields);
|
|
83
|
+
helpers.notifySubscribers();
|
|
84
|
+
return state2.api;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// src/core/format-helpers.ts
|
|
88
|
+
var FORMATTER_RAW_ATTRIBUTE = "data-formatter-raw-for";
|
|
89
|
+
var cssEscape = (value) => {
|
|
90
|
+
if (typeof CSS !== "undefined" && typeof CSS.escape === "function") {
|
|
91
|
+
return CSS.escape(value);
|
|
92
|
+
}
|
|
93
|
+
return value.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g, "\\$1");
|
|
94
|
+
};
|
|
95
|
+
var findRawMirror = (form2, fieldName) => {
|
|
96
|
+
const byAttr = form2.querySelector(
|
|
97
|
+
`[${FORMATTER_RAW_ATTRIBUTE}="${cssEscape(fieldName)}"]`
|
|
98
|
+
);
|
|
99
|
+
if (byAttr) return byAttr;
|
|
100
|
+
const byName = form2.querySelector(
|
|
101
|
+
`[name="${cssEscape(`${fieldName}_raw`)}"]`
|
|
102
|
+
);
|
|
103
|
+
if (byName) return byName;
|
|
104
|
+
const byNameOld = form2.querySelector(
|
|
105
|
+
`[name="${cssEscape(`${fieldName}Raw`)}"]`
|
|
106
|
+
);
|
|
107
|
+
if (byNameOld) return byNameOld;
|
|
108
|
+
return null;
|
|
109
|
+
};
|
|
110
|
+
var ensureRawMirror = (form2, fieldName) => {
|
|
111
|
+
const existing = findRawMirror(form2, fieldName);
|
|
112
|
+
if (existing) return existing;
|
|
113
|
+
const input = document.createElement("input");
|
|
114
|
+
input.type = "hidden";
|
|
115
|
+
input.name = `${fieldName}_raw`;
|
|
116
|
+
input.setAttribute("aria-hidden", "true");
|
|
117
|
+
input.tabIndex = -1;
|
|
118
|
+
input.setAttribute(FORMATTER_RAW_ATTRIBUTE, fieldName);
|
|
119
|
+
form2.appendChild(input);
|
|
120
|
+
return input;
|
|
121
|
+
};
|
|
122
|
+
var applyFormattedValue = (visible, mirror, formatted, raw) => {
|
|
123
|
+
const rawInput = visible.value;
|
|
124
|
+
const caret = clamp(
|
|
125
|
+
visible.selectionStart ?? rawInput.length,
|
|
126
|
+
0,
|
|
127
|
+
rawInput.length
|
|
128
|
+
);
|
|
129
|
+
if (rawInput === formatted) {
|
|
130
|
+
if (mirror && mirror.value !== raw) mirror.value = raw;
|
|
131
|
+
return caret;
|
|
132
|
+
}
|
|
133
|
+
visible.value = formatted;
|
|
134
|
+
if (mirror) mirror.value = raw;
|
|
135
|
+
const newCaret = computeCursorPosition(caret, rawInput, formatted);
|
|
136
|
+
restoreCursor(visible, newCaret);
|
|
137
|
+
return newCaret;
|
|
138
|
+
};
|
|
139
|
+
var clamp = (value, min, max) => Math.max(min, Math.min(max, value));
|
|
140
|
+
var computeCursorPosition = (caretPos, rawInput, newValue) => {
|
|
141
|
+
if (newValue.length === 0) return 0;
|
|
142
|
+
if (caretPos >= rawInput.length) return newValue.length;
|
|
143
|
+
const targetNonFormat = countNonFormat(rawInput.slice(0, caretPos));
|
|
144
|
+
if (targetNonFormat === 0) {
|
|
145
|
+
let i = 0;
|
|
146
|
+
while (i < newValue.length && isFormatChar(newValue[i])) i += 1;
|
|
147
|
+
return i;
|
|
148
|
+
}
|
|
149
|
+
let seen = 0;
|
|
150
|
+
for (let i = 0; i < newValue.length; i += 1) {
|
|
151
|
+
if (!isFormatChar(newValue[i])) {
|
|
152
|
+
seen += 1;
|
|
153
|
+
if (seen === targetNonFormat) {
|
|
154
|
+
return Math.min(i + 1, newValue.length);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return newValue.length;
|
|
159
|
+
};
|
|
160
|
+
var countNonFormat = (value) => {
|
|
161
|
+
let count = 0;
|
|
162
|
+
for (const char of value) {
|
|
163
|
+
if (!isFormatChar(char)) count += 1;
|
|
164
|
+
}
|
|
165
|
+
return count;
|
|
166
|
+
};
|
|
167
|
+
var isFormatChar = (char) => {
|
|
168
|
+
if (!char) return false;
|
|
169
|
+
if (char >= "0" && char <= "9") return false;
|
|
170
|
+
if (char >= "a" && char <= "z" || char >= "A" && char <= "Z") return false;
|
|
171
|
+
return true;
|
|
172
|
+
};
|
|
173
|
+
var restoreCursor = (field, position) => {
|
|
174
|
+
const max = field.value.length;
|
|
175
|
+
const safe = clamp(position, 0, max);
|
|
176
|
+
const apply = () => {
|
|
177
|
+
try {
|
|
178
|
+
field.setSelectionRange(safe, safe);
|
|
179
|
+
} catch {
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
if (typeof navigator !== "undefined" && /Android/i.test(navigator.userAgent)) {
|
|
183
|
+
if (typeof requestAnimationFrame === "function") {
|
|
184
|
+
requestAnimationFrame(apply);
|
|
185
|
+
} else {
|
|
186
|
+
setTimeout(apply, 1);
|
|
187
|
+
}
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
apply();
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
// src/core/formatter-loader.ts
|
|
194
|
+
var state = null;
|
|
195
|
+
var MISSING_MESSAGE = "[samline/forms] The `format()` and `formatAll()` methods require the @samline/formatter package. Install it with: npm i @samline/formatter (or pnpm/bun/yarn equivalent).";
|
|
196
|
+
var warned = false;
|
|
197
|
+
var warnOnce = () => {
|
|
198
|
+
if (warned) return;
|
|
199
|
+
warned = true;
|
|
200
|
+
console.error(MISSING_MESSAGE);
|
|
201
|
+
};
|
|
202
|
+
var loadFormatter = () => {
|
|
203
|
+
if (state && state.status === "resolved") {
|
|
204
|
+
if (!state.module) warnOnce();
|
|
205
|
+
return Promise.resolve(state.module);
|
|
206
|
+
}
|
|
207
|
+
if (state && state.status === "pending") {
|
|
208
|
+
return state.promise;
|
|
209
|
+
}
|
|
210
|
+
const promise = (async () => {
|
|
211
|
+
try {
|
|
212
|
+
const mod = await import(
|
|
213
|
+
/* @vite-ignore */
|
|
214
|
+
"@samline/formatter"
|
|
215
|
+
);
|
|
216
|
+
state = { status: "resolved", module: mod };
|
|
217
|
+
return mod;
|
|
218
|
+
} catch {
|
|
219
|
+
warnOnce();
|
|
220
|
+
state = { status: "resolved", module: null };
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
})();
|
|
224
|
+
state = { status: "pending", promise };
|
|
225
|
+
return promise;
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
// src/api/format.ts
|
|
229
|
+
var registry = /* @__PURE__ */ new WeakMap();
|
|
230
|
+
var getRegistry = (state2) => {
|
|
231
|
+
let bucket = registry.get(state2);
|
|
232
|
+
if (!bucket) {
|
|
233
|
+
bucket = /* @__PURE__ */ new Map();
|
|
234
|
+
registry.set(state2, bucket);
|
|
235
|
+
}
|
|
236
|
+
return bucket;
|
|
237
|
+
};
|
|
238
|
+
var resolveFieldNames = (config) => Array.isArray(config.field) ? config.field : [config.field];
|
|
239
|
+
var addListener = (state2, target, type, handler) => {
|
|
240
|
+
target.addEventListener(type, handler);
|
|
241
|
+
state2.listeners.push({ element: target, type, handler });
|
|
242
|
+
};
|
|
243
|
+
var buildHandler = (field, mirror, formatFn, formatType, formatOptions, mirrorFieldName) => {
|
|
244
|
+
const handler = (event) => {
|
|
245
|
+
if (!field.isConnected) return;
|
|
246
|
+
if (event.target !== field) return;
|
|
247
|
+
const rawInput = event.target.value;
|
|
248
|
+
const { formatted, raw } = formatFn(rawInput, formatType, formatOptions);
|
|
249
|
+
if (!formatted && !raw) {
|
|
250
|
+
field.value = "";
|
|
251
|
+
if (mirror && mirror.value !== "") mirror.value = "";
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
applyFormattedValue(field, mirror, formatted, raw);
|
|
255
|
+
void mirrorFieldName;
|
|
256
|
+
};
|
|
257
|
+
return handler;
|
|
258
|
+
};
|
|
259
|
+
var applyFormat = async (state2, helpers, config) => {
|
|
260
|
+
if (!state2.element || !state2.api) return;
|
|
261
|
+
const formatter = await loadFormatter();
|
|
262
|
+
if (!formatter) return;
|
|
263
|
+
const formatType = config.type;
|
|
264
|
+
const formatOptions = config.options;
|
|
265
|
+
const fieldNames = resolveFieldNames(config);
|
|
266
|
+
const bucket = getRegistry(state2);
|
|
267
|
+
for (const fieldName of fieldNames) {
|
|
268
|
+
const fields = helpers.getFieldsByName(fieldName);
|
|
269
|
+
if (fields.length === 0) continue;
|
|
270
|
+
const writable = fields.filter(
|
|
271
|
+
(f) => f instanceof HTMLInputElement && f.type !== "checkbox" && f.type !== "radio" && f.type !== "file" && f.type !== "submit" && f.type !== "button" || f instanceof HTMLTextAreaElement
|
|
272
|
+
);
|
|
273
|
+
if (writable.length === 0) continue;
|
|
274
|
+
for (const field of writable) {
|
|
275
|
+
const existing = bucket.get(fieldName);
|
|
276
|
+
const mirrorName = config.rawField ?? `${fieldName}_raw`;
|
|
277
|
+
let mirror = findRawMirror(state2.element, fieldName) ?? null;
|
|
278
|
+
const mirrorIsOwned = !mirror;
|
|
279
|
+
if (!mirror) mirror = ensureRawMirror(state2.element, fieldName);
|
|
280
|
+
if (mirror && mirror.name !== mirrorName) mirror.name = mirrorName;
|
|
281
|
+
const trackerMirrorName = mirror?.name ?? mirrorName;
|
|
282
|
+
if (existing) {
|
|
283
|
+
existing.mirrorName = trackerMirrorName;
|
|
284
|
+
existing.mirrorIsOwned = mirrorIsOwned;
|
|
285
|
+
state2.formattedFields.set(fieldName, {
|
|
286
|
+
config,
|
|
287
|
+
mirrorName: trackerMirrorName,
|
|
288
|
+
mirrorIsOwned
|
|
289
|
+
});
|
|
290
|
+
const current = field.value;
|
|
291
|
+
if (current !== "") {
|
|
292
|
+
const { formatted, raw } = formatter.format(current, formatType, formatOptions);
|
|
293
|
+
applyFormattedValue(field, mirror, formatted, raw);
|
|
294
|
+
}
|
|
295
|
+
continue;
|
|
296
|
+
}
|
|
297
|
+
const handler = buildHandler(
|
|
298
|
+
field,
|
|
299
|
+
mirror,
|
|
300
|
+
formatter.format,
|
|
301
|
+
formatType,
|
|
302
|
+
formatOptions,
|
|
303
|
+
trackerMirrorName
|
|
304
|
+
);
|
|
305
|
+
addListener(state2, state2.element, "input", handler);
|
|
306
|
+
bucket.set(fieldName, {
|
|
307
|
+
fields: /* @__PURE__ */ new Set([field]),
|
|
308
|
+
mirrorName: trackerMirrorName,
|
|
309
|
+
handler,
|
|
310
|
+
mirrorIsOwned
|
|
311
|
+
});
|
|
312
|
+
state2.formattedFields.set(fieldName, {
|
|
313
|
+
config,
|
|
314
|
+
mirrorName: trackerMirrorName,
|
|
315
|
+
mirrorIsOwned
|
|
316
|
+
});
|
|
317
|
+
const initial = field.value;
|
|
318
|
+
if (initial !== "") {
|
|
319
|
+
const { formatted, raw } = formatter.format(initial, formatType, formatOptions);
|
|
320
|
+
applyFormattedValue(field, mirror, formatted, raw);
|
|
321
|
+
} else if (mirrorIsOwned && mirror && mirror.value !== "") {
|
|
322
|
+
mirror.value = "";
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
var createFormat = (state2, helpers) => (config) => {
|
|
328
|
+
if (state2.isDestroyed) return state2.api;
|
|
329
|
+
if (!state2.element) return state2.api;
|
|
330
|
+
void applyFormat(state2, helpers, config);
|
|
331
|
+
return state2.api;
|
|
332
|
+
};
|
|
333
|
+
var createFormatAll = createFormat;
|
|
334
|
+
var cleanupFormatRegistry = (state2) => {
|
|
335
|
+
if (!state2.element) {
|
|
336
|
+
registry.delete(state2);
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
const bucket = registry.get(state2);
|
|
340
|
+
if (!bucket) {
|
|
341
|
+
state2.element.querySelectorAll(`[${FORMATTER_RAW_ATTRIBUTE}]`).forEach((node) => node.remove());
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
for (const [fieldName, entry] of bucket) {
|
|
345
|
+
state2.element.removeEventListener("input", entry.handler);
|
|
346
|
+
if (entry.mirrorIsOwned) {
|
|
347
|
+
const mirror = findRawMirror(state2.element, entry.mirrorName);
|
|
348
|
+
mirror?.remove();
|
|
349
|
+
}
|
|
350
|
+
bucket.delete(fieldName);
|
|
351
|
+
state2.formattedFields.delete(fieldName);
|
|
352
|
+
}
|
|
353
|
+
state2.element.querySelectorAll(`[${FORMATTER_RAW_ATTRIBUTE}]`).forEach((node) => node.remove());
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
// src/api/destroy.ts
|
|
357
|
+
var createDestroy = (state2, _helpers) => () => {
|
|
358
|
+
if (state2.isDestroyed) return;
|
|
359
|
+
state2.isDestroyed = true;
|
|
360
|
+
for (const listener of state2.listeners) {
|
|
361
|
+
listener.element.removeEventListener(listener.type, listener.handler);
|
|
362
|
+
}
|
|
363
|
+
state2.listeners.length = 0;
|
|
364
|
+
if (state2.autoSubmitTimer) {
|
|
365
|
+
clearTimeout(state2.autoSubmitTimer);
|
|
366
|
+
state2.autoSubmitTimer = null;
|
|
367
|
+
}
|
|
368
|
+
state2.mutationObserver?.disconnect();
|
|
369
|
+
state2.mutationObserver = null;
|
|
370
|
+
state2.watchedFields.clear();
|
|
371
|
+
state2.subscribers.clear();
|
|
372
|
+
state2.submitHandlers.clear();
|
|
373
|
+
state2.fieldCache.clear();
|
|
374
|
+
state2.manualErrors = {};
|
|
375
|
+
state2.validationErrors = {};
|
|
376
|
+
cleanupFormatRegistry(state2);
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
// src/api/disable-auto-submit.ts
|
|
380
|
+
var createDisableAutoSubmit = (state2, helpers) => () => {
|
|
381
|
+
state2.autoSubmitEnabled = false;
|
|
382
|
+
if (state2.autoSubmitTimer) {
|
|
383
|
+
clearTimeout(state2.autoSubmitTimer);
|
|
384
|
+
state2.autoSubmitTimer = null;
|
|
385
|
+
}
|
|
386
|
+
helpers.notifySubscribers();
|
|
387
|
+
return state2.api;
|
|
388
|
+
};
|
|
389
|
+
|
|
27
390
|
// src/core/serialize.ts
|
|
28
391
|
var isEmptyFile = (value) => value instanceof File && value.size === 0 && value.name === "";
|
|
29
392
|
var appendValue = (data, key, value) => {
|
|
@@ -39,19 +402,30 @@ var SamlineForms = (() => {
|
|
|
39
402
|
data[key] = [current, value];
|
|
40
403
|
};
|
|
41
404
|
var parseFormData = (formElement) => {
|
|
42
|
-
const
|
|
405
|
+
const raw = new FormData(formElement);
|
|
43
406
|
const formData = new FormData();
|
|
44
407
|
const data = {};
|
|
45
|
-
|
|
46
|
-
if (isEmptyFile(value))
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
408
|
+
raw.forEach((value, key) => {
|
|
409
|
+
if (isEmptyFile(value)) return;
|
|
49
410
|
formData.append(key, value);
|
|
50
411
|
appendValue(data, key, value);
|
|
51
412
|
});
|
|
52
413
|
return { data, formData };
|
|
53
414
|
};
|
|
54
415
|
|
|
416
|
+
// src/api/get-data.ts
|
|
417
|
+
var createGetData = (_state, _helpers) => () => {
|
|
418
|
+
if (!_state.element) return { data: {}, formData: new FormData() };
|
|
419
|
+
return parseFormData(_state.element);
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
// src/api/get-field.ts
|
|
423
|
+
var createGetField = (state2, helpers) => (name) => {
|
|
424
|
+
const fields = helpers.getFieldsByName(name);
|
|
425
|
+
if (fields.length === 0) return null;
|
|
426
|
+
return fields.length === 1 ? fields[0] : fields;
|
|
427
|
+
};
|
|
428
|
+
|
|
55
429
|
// src/core/state.ts
|
|
56
430
|
var createEmptyFormState = () => ({
|
|
57
431
|
values: {},
|
|
@@ -62,98 +436,47 @@ var SamlineForms = (() => {
|
|
|
62
436
|
autoSubmit: false,
|
|
63
437
|
submitCount: 0
|
|
64
438
|
});
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
return { value: rule.value, message: rule.message };
|
|
73
|
-
}
|
|
74
|
-
return { value: rule, message: void 0 };
|
|
75
|
-
};
|
|
76
|
-
var hasValue = (value) => {
|
|
77
|
-
if (Array.isArray(value)) {
|
|
78
|
-
return value.length > 0;
|
|
79
|
-
}
|
|
80
|
-
return typeof value === "string" ? value.trim().length > 0 : value !== void 0;
|
|
81
|
-
};
|
|
82
|
-
var getValueLength = (value) => {
|
|
83
|
-
if (Array.isArray(value)) {
|
|
84
|
-
return value.length;
|
|
85
|
-
}
|
|
86
|
-
if (typeof value === "string") {
|
|
87
|
-
return value.length;
|
|
88
|
-
}
|
|
89
|
-
return 0;
|
|
90
|
-
};
|
|
91
|
-
var toPatternTarget = (value) => {
|
|
92
|
-
if (typeof value === "string") {
|
|
93
|
-
return value;
|
|
94
|
-
}
|
|
95
|
-
if (Array.isArray(value)) {
|
|
96
|
-
return value.map((entry) => typeof entry === "string" ? entry : entry.name).join(",");
|
|
97
|
-
}
|
|
98
|
-
return "";
|
|
99
|
-
};
|
|
100
|
-
var validateFieldValue = (field, value, rules, values) => {
|
|
101
|
-
const errors = [];
|
|
102
|
-
const context = { field, value, values };
|
|
103
|
-
const required = resolveRule(rules.required);
|
|
104
|
-
const minLength = resolveRule(rules.minLength);
|
|
105
|
-
const maxLength = resolveRule(rules.maxLength);
|
|
106
|
-
const pattern = resolveRule(rules.pattern);
|
|
107
|
-
if (required.value && !hasValue(value)) {
|
|
108
|
-
errors.push(required.message ?? "This field is required.");
|
|
109
|
-
}
|
|
110
|
-
if (minLength.value !== void 0 && getValueLength(value) < minLength.value) {
|
|
111
|
-
errors.push(minLength.message ?? `Minimum length is ${minLength.value}.`);
|
|
112
|
-
}
|
|
113
|
-
if (maxLength.value !== void 0 && getValueLength(value) > maxLength.value) {
|
|
114
|
-
errors.push(maxLength.message ?? `Maximum length is ${maxLength.value}.`);
|
|
115
|
-
}
|
|
116
|
-
if (pattern.value && hasValue(value) && !pattern.value.test(toPatternTarget(value))) {
|
|
117
|
-
errors.push(pattern.message ?? "Value does not match the required pattern.");
|
|
118
|
-
}
|
|
119
|
-
const customValidators = rules.validate ? Array.isArray(rules.validate) ? rules.validate : [rules.validate] : [];
|
|
120
|
-
for (const validator of customValidators) {
|
|
121
|
-
const result = validator(context);
|
|
122
|
-
if (typeof result === "string" && result.length > 0) {
|
|
123
|
-
errors.push(result);
|
|
124
|
-
}
|
|
125
|
-
if (result === false) {
|
|
126
|
-
errors.push("Validation failed.");
|
|
127
|
-
}
|
|
439
|
+
var cloneErrors = (errors) => Object.fromEntries(
|
|
440
|
+
Object.entries(errors).map(([field, messages]) => [field, [...messages]])
|
|
441
|
+
);
|
|
442
|
+
var mergeErrors = (left, right) => {
|
|
443
|
+
const merged = { ...left };
|
|
444
|
+
for (const [field, messages] of Object.entries(right)) {
|
|
445
|
+
merged[field] = merged[field] ? [...merged[field], ...messages] : [...messages];
|
|
128
446
|
}
|
|
129
|
-
return
|
|
447
|
+
return merged;
|
|
130
448
|
};
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
449
|
+
|
|
450
|
+
// src/api/get-state.ts
|
|
451
|
+
var createGetState = (state2, helpers) => () => {
|
|
452
|
+
const values = helpers.getValues();
|
|
453
|
+
const errors = cloneErrors(helpers.getMergedErrors());
|
|
454
|
+
const filledFields = helpers.getTrackedFieldNames().filter((name) => {
|
|
455
|
+
const value = values[name];
|
|
456
|
+
if (Array.isArray(value)) return value.length > 0;
|
|
457
|
+
if (typeof value === "string") return value.trim().length > 0;
|
|
458
|
+
return value !== void 0;
|
|
459
|
+
});
|
|
139
460
|
return {
|
|
461
|
+
...createEmptyFormState(),
|
|
462
|
+
values,
|
|
463
|
+
errors,
|
|
464
|
+
filledFields,
|
|
140
465
|
isValid: Object.keys(errors).length === 0,
|
|
141
|
-
|
|
466
|
+
isValidated: state2.isValidated,
|
|
467
|
+
autoSubmit: state2.autoSubmitEnabled,
|
|
468
|
+
submitCount: state2.submitCount
|
|
142
469
|
};
|
|
143
470
|
};
|
|
144
471
|
|
|
145
|
-
// src/
|
|
472
|
+
// src/core/dom.ts
|
|
146
473
|
var isFormFieldElement = (value) => value instanceof HTMLInputElement || value instanceof HTMLSelectElement || value instanceof HTMLTextAreaElement;
|
|
147
474
|
var resolveFormElement = (target) => {
|
|
148
|
-
if (!target)
|
|
149
|
-
|
|
150
|
-
}
|
|
151
|
-
if (target instanceof HTMLFormElement) {
|
|
152
|
-
return target;
|
|
153
|
-
}
|
|
475
|
+
if (!target) return null;
|
|
476
|
+
if (target instanceof HTMLFormElement) return target;
|
|
154
477
|
if (typeof target === "string") {
|
|
155
|
-
const
|
|
156
|
-
return
|
|
478
|
+
const node = document.getElementById(target);
|
|
479
|
+
return node instanceof HTMLFormElement ? node : null;
|
|
157
480
|
}
|
|
158
481
|
if ("current" in target) {
|
|
159
482
|
return target.current instanceof HTMLFormElement ? target.current : null;
|
|
@@ -164,14 +487,11 @@ var SamlineForms = (() => {
|
|
|
164
487
|
isFormFieldElement
|
|
165
488
|
);
|
|
166
489
|
var queryNamedFields = (form2, name) => getNamedFields(form2).filter((field) => field.name === name);
|
|
490
|
+
var isFieldElement = (value) => isFormFieldElement(value);
|
|
167
491
|
var isFieldFilled = (field) => {
|
|
168
492
|
if (field instanceof HTMLInputElement) {
|
|
169
|
-
if (field.type === "checkbox" || field.type === "radio")
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
if (field.type === "file") {
|
|
173
|
-
return Boolean(field.files && field.files.length > 0);
|
|
174
|
-
}
|
|
493
|
+
if (field.type === "checkbox" || field.type === "radio") return field.checked;
|
|
494
|
+
if (field.type === "file") return Boolean(field.files && field.files.length > 0);
|
|
175
495
|
return field.value.trim() !== "";
|
|
176
496
|
}
|
|
177
497
|
return field.value !== "";
|
|
@@ -179,35 +499,35 @@ var SamlineForms = (() => {
|
|
|
179
499
|
var applyBooleanAttribute = (field, attribute, enabled) => {
|
|
180
500
|
if (enabled) {
|
|
181
501
|
field.setAttribute(attribute, "");
|
|
182
|
-
|
|
502
|
+
} else {
|
|
503
|
+
field.removeAttribute(attribute);
|
|
183
504
|
}
|
|
184
|
-
field.removeAttribute(attribute);
|
|
185
505
|
};
|
|
186
506
|
var readFieldValue = (fields) => {
|
|
187
|
-
if (fields.length === 0)
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
return void 0;
|
|
193
|
-
}
|
|
194
|
-
if (firstField instanceof HTMLSelectElement || firstField instanceof HTMLTextAreaElement) {
|
|
195
|
-
return firstField.value;
|
|
507
|
+
if (fields.length === 0) return void 0;
|
|
508
|
+
const first = fields[0];
|
|
509
|
+
if (!first) return void 0;
|
|
510
|
+
if (first instanceof HTMLSelectElement || first instanceof HTMLTextAreaElement) {
|
|
511
|
+
return first.value;
|
|
196
512
|
}
|
|
197
|
-
if (
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
513
|
+
if (first instanceof HTMLInputElement) {
|
|
514
|
+
if (first.type === "radio") {
|
|
515
|
+
const checked = fields.find(
|
|
516
|
+
(f) => f instanceof HTMLInputElement && f.checked
|
|
517
|
+
);
|
|
518
|
+
return checked?.value ?? "";
|
|
519
|
+
}
|
|
520
|
+
if (first.type === "checkbox") {
|
|
521
|
+
const values = fields.filter(
|
|
522
|
+
(f) => f instanceof HTMLInputElement && f.checked
|
|
523
|
+
).map((f) => f.value);
|
|
524
|
+
return values.length > 1 ? values : values[0] ?? "";
|
|
525
|
+
}
|
|
526
|
+
if (first.type === "file") {
|
|
527
|
+
return first.files ? Array.from(first.files) : [];
|
|
528
|
+
}
|
|
209
529
|
}
|
|
210
|
-
return
|
|
530
|
+
return first.value;
|
|
211
531
|
};
|
|
212
532
|
var writeFieldValue = (fields, value) => {
|
|
213
533
|
const normalizedArray = Array.isArray(value) ? value.map((item) => String(item)) : null;
|
|
@@ -223,9 +543,7 @@ var SamlineForms = (() => {
|
|
|
223
543
|
continue;
|
|
224
544
|
}
|
|
225
545
|
if (field.type === "file") {
|
|
226
|
-
if (Array.isArray(value) && value.length === 0)
|
|
227
|
-
field.value = "";
|
|
228
|
-
}
|
|
546
|
+
if (Array.isArray(value) && value.length === 0) field.value = "";
|
|
229
547
|
continue;
|
|
230
548
|
}
|
|
231
549
|
field.value = normalizedValue;
|
|
@@ -236,9 +554,7 @@ var SamlineForms = (() => {
|
|
|
236
554
|
};
|
|
237
555
|
var clearAttributes = (form2, attributes) => {
|
|
238
556
|
for (const attribute of attributes) {
|
|
239
|
-
form2.querySelectorAll(`[${attribute}]`).forEach((
|
|
240
|
-
element.removeAttribute(attribute);
|
|
241
|
-
});
|
|
557
|
+
form2.querySelectorAll(`[${attribute}]`).forEach((node) => node.removeAttribute(attribute));
|
|
242
558
|
}
|
|
243
559
|
};
|
|
244
560
|
var submitForm = (form2) => {
|
|
@@ -256,26 +572,194 @@ var SamlineForms = (() => {
|
|
|
256
572
|
form2.submit();
|
|
257
573
|
};
|
|
258
574
|
|
|
259
|
-
// src/
|
|
575
|
+
// src/api/get-value.ts
|
|
576
|
+
var createGetValue = (state2, helpers) => (name) => readFieldValue(helpers.getFieldsByName(name));
|
|
577
|
+
|
|
578
|
+
// src/api/observe.ts
|
|
579
|
+
var createObserve = (state2, helpers) => (field, callback) => {
|
|
580
|
+
const callbacks = state2.watchedFields.get(field) ?? /* @__PURE__ */ new Set();
|
|
581
|
+
callbacks.add(callback);
|
|
582
|
+
state2.watchedFields.set(field, callbacks);
|
|
583
|
+
if (state2.element) {
|
|
584
|
+
callback(state2.api.getValue(field), state2.api.getField(field), state2.element, state2.api.getState());
|
|
585
|
+
}
|
|
586
|
+
return () => {
|
|
587
|
+
const current = state2.watchedFields.get(field);
|
|
588
|
+
current?.delete(callback);
|
|
589
|
+
if (current && current.size === 0) {
|
|
590
|
+
state2.watchedFields.delete(field);
|
|
591
|
+
}
|
|
592
|
+
};
|
|
593
|
+
};
|
|
594
|
+
|
|
595
|
+
// src/api/on-submit.ts
|
|
596
|
+
var createOnSubmit = (state2, _helpers) => (callback, preventDefault = true) => {
|
|
597
|
+
state2.submitHandlers.add({ callback, preventDefault });
|
|
598
|
+
return state2.api;
|
|
599
|
+
};
|
|
600
|
+
|
|
601
|
+
// src/api/prefill.ts
|
|
602
|
+
var createPrefill = (state2, _helpers) => (fieldName) => {
|
|
603
|
+
if (!state2.element) return state2.api;
|
|
604
|
+
const params = new URLSearchParams(window.location.search);
|
|
605
|
+
params.forEach((value, key) => {
|
|
606
|
+
if (fieldName && fieldName !== key) return;
|
|
607
|
+
state2.api.setValue(key, value);
|
|
608
|
+
});
|
|
609
|
+
return state2.api;
|
|
610
|
+
};
|
|
611
|
+
|
|
612
|
+
// src/api/reset.ts
|
|
613
|
+
var createReset = (state2, helpers) => () => {
|
|
614
|
+
if (!state2.element) return state2.api;
|
|
615
|
+
state2.element.reset();
|
|
616
|
+
state2.manualErrors = {};
|
|
617
|
+
state2.validationErrors = {};
|
|
618
|
+
clearAttributes(state2.element, [state2.attributes.error, state2.attributes.filled]);
|
|
619
|
+
if (state2.isValidated) helpers.syncVisualState();
|
|
620
|
+
helpers.notifySubscribers();
|
|
621
|
+
return state2.api;
|
|
622
|
+
};
|
|
623
|
+
|
|
624
|
+
// src/api/validate.ts
|
|
625
|
+
var createValidate = (state2, helpers) => (fields) => {
|
|
626
|
+
state2.isValidated = true;
|
|
627
|
+
helpers.syncVisualState(fields);
|
|
628
|
+
return helpers.validateNames(fields);
|
|
629
|
+
};
|
|
630
|
+
|
|
631
|
+
// src/api/revalidate.ts
|
|
632
|
+
var createRevalidate = createValidate;
|
|
633
|
+
|
|
634
|
+
// src/api/set-errors.ts
|
|
635
|
+
var createSetErrors = (state2, helpers) => (fields) => {
|
|
636
|
+
if (Array.isArray(fields)) {
|
|
637
|
+
state2.manualErrors = {
|
|
638
|
+
...state2.manualErrors,
|
|
639
|
+
...Object.fromEntries(fields.map((field) => [field, ["Invalid value."]]))
|
|
640
|
+
};
|
|
641
|
+
} else {
|
|
642
|
+
state2.manualErrors = {
|
|
643
|
+
...state2.manualErrors,
|
|
644
|
+
...cloneErrors(fields)
|
|
645
|
+
};
|
|
646
|
+
}
|
|
647
|
+
helpers.syncVisualState(Array.isArray(fields) ? fields : Object.keys(fields));
|
|
648
|
+
helpers.notifySubscribers();
|
|
649
|
+
return state2.api;
|
|
650
|
+
};
|
|
651
|
+
|
|
652
|
+
// src/api/set-value.ts
|
|
653
|
+
var createSetValue = (state2, helpers) => (name, value) => {
|
|
654
|
+
const fields = helpers.getFieldsByName(name);
|
|
655
|
+
if (fields.length === 0) return state2.api;
|
|
656
|
+
writeFieldValue(fields, value);
|
|
657
|
+
const firstField = fields[0];
|
|
658
|
+
if (!firstField) return state2.api;
|
|
659
|
+
const eventType = firstField instanceof HTMLSelectElement || firstField instanceof HTMLInputElement && (firstField.type === "checkbox" || firstField.type === "radio") ? "change" : "input";
|
|
660
|
+
firstField.dispatchEvent(new Event(eventType, { bubbles: true }));
|
|
661
|
+
return state2.api;
|
|
662
|
+
};
|
|
663
|
+
|
|
664
|
+
// src/api/subscribe.ts
|
|
665
|
+
var createSubscribe = (state2, _helpers) => (listener) => {
|
|
666
|
+
state2.subscribers.add(listener);
|
|
667
|
+
listener(state2.api.getState());
|
|
668
|
+
return () => {
|
|
669
|
+
state2.subscribers.delete(listener);
|
|
670
|
+
};
|
|
671
|
+
};
|
|
672
|
+
|
|
673
|
+
// src/api/unwatch.ts
|
|
674
|
+
var createUnwatch = (state2, _helpers) => (field, callback) => {
|
|
675
|
+
if (!field) {
|
|
676
|
+
state2.watchedFields.clear();
|
|
677
|
+
return state2.api;
|
|
678
|
+
}
|
|
679
|
+
if (!callback) {
|
|
680
|
+
state2.watchedFields.delete(field);
|
|
681
|
+
return state2.api;
|
|
682
|
+
}
|
|
683
|
+
const callbacks = state2.watchedFields.get(field);
|
|
684
|
+
callbacks?.delete(callback);
|
|
685
|
+
if (callbacks && callbacks.size === 0) {
|
|
686
|
+
state2.watchedFields.delete(field);
|
|
687
|
+
}
|
|
688
|
+
return state2.api;
|
|
689
|
+
};
|
|
690
|
+
|
|
691
|
+
// src/api/watch.ts
|
|
692
|
+
var createWatch = (state2, helpers) => (field, callback) => {
|
|
693
|
+
const observe = createObserve(state2, helpers);
|
|
694
|
+
observe(field, callback);
|
|
695
|
+
return state2.api;
|
|
696
|
+
};
|
|
697
|
+
|
|
698
|
+
// src/core/validation.ts
|
|
699
|
+
var resolveRule = (rule) => {
|
|
700
|
+
if (rule === void 0) {
|
|
701
|
+
return { value: void 0, message: void 0 };
|
|
702
|
+
}
|
|
703
|
+
if (typeof rule === "object" && rule !== null && "value" in rule) {
|
|
704
|
+
return { value: rule.value, message: rule.message };
|
|
705
|
+
}
|
|
706
|
+
return { value: rule, message: void 0 };
|
|
707
|
+
};
|
|
708
|
+
var hasValue = (value) => {
|
|
709
|
+
if (Array.isArray(value)) return value.length > 0;
|
|
710
|
+
if (typeof value === "string") return value.trim().length > 0;
|
|
711
|
+
return value !== void 0;
|
|
712
|
+
};
|
|
713
|
+
var getValueLength = (value) => {
|
|
714
|
+
if (Array.isArray(value)) return value.length;
|
|
715
|
+
if (typeof value === "string") return value.length;
|
|
716
|
+
return 0;
|
|
717
|
+
};
|
|
718
|
+
var toPatternTarget = (value) => {
|
|
719
|
+
if (typeof value === "string") return value;
|
|
720
|
+
if (Array.isArray(value)) {
|
|
721
|
+
return value.map((entry) => typeof entry === "string" ? entry : entry.name).join(",");
|
|
722
|
+
}
|
|
723
|
+
return "";
|
|
724
|
+
};
|
|
725
|
+
var validateFieldValue = (field, value, rules, values) => {
|
|
726
|
+
const errors = [];
|
|
727
|
+
const context = { field, value, values };
|
|
728
|
+
const required = resolveRule(rules.required);
|
|
729
|
+
const minLength = resolveRule(rules.minLength);
|
|
730
|
+
const maxLength = resolveRule(rules.maxLength);
|
|
731
|
+
const pattern = resolveRule(rules.pattern);
|
|
732
|
+
if (required.value && !hasValue(value)) {
|
|
733
|
+
errors.push(required.message ?? "This field is required.");
|
|
734
|
+
}
|
|
735
|
+
if (minLength.value !== void 0 && getValueLength(value) < minLength.value) {
|
|
736
|
+
errors.push(minLength.message ?? `Minimum length is ${minLength.value}.`);
|
|
737
|
+
}
|
|
738
|
+
if (maxLength.value !== void 0 && getValueLength(value) > maxLength.value) {
|
|
739
|
+
errors.push(maxLength.message ?? `Maximum length is ${maxLength.value}.`);
|
|
740
|
+
}
|
|
741
|
+
if (pattern.value && hasValue(value) && !pattern.value.test(toPatternTarget(value))) {
|
|
742
|
+
errors.push(pattern.message ?? "Value does not match the required pattern.");
|
|
743
|
+
}
|
|
744
|
+
const custom = rules.validate ? Array.isArray(rules.validate) ? rules.validate : [rules.validate] : [];
|
|
745
|
+
for (const validator of custom) {
|
|
746
|
+
const result = validator(context);
|
|
747
|
+
if (typeof result === "string" && result.length > 0) errors.push(result);
|
|
748
|
+
if (result === false) errors.push("Validation failed.");
|
|
749
|
+
}
|
|
750
|
+
return errors;
|
|
751
|
+
};
|
|
752
|
+
|
|
753
|
+
// src/core/controller.ts
|
|
260
754
|
var DEFAULT_ATTRIBUTES = {
|
|
261
755
|
filled: "css-filled",
|
|
262
756
|
error: "css-error"
|
|
263
757
|
};
|
|
264
758
|
var DEFAULT_OPTIONS = {
|
|
265
759
|
autoValidate: true,
|
|
266
|
-
|
|
267
|
-
|
|
760
|
+
clearErrorsOnSubmit: true,
|
|
761
|
+
clearManualErrorsOnChange: true
|
|
268
762
|
};
|
|
269
|
-
var mergeErrors = (left, right) => {
|
|
270
|
-
const merged = { ...left };
|
|
271
|
-
for (const [field, messages] of Object.entries(right)) {
|
|
272
|
-
merged[field] = merged[field] ? [...merged[field], ...messages] : [...messages];
|
|
273
|
-
}
|
|
274
|
-
return merged;
|
|
275
|
-
};
|
|
276
|
-
var cloneErrors = (errors) => Object.fromEntries(
|
|
277
|
-
Object.entries(errors).map(([field, messages]) => [field, [...messages]])
|
|
278
|
-
);
|
|
279
763
|
var createFormController = (target, options = {}) => {
|
|
280
764
|
const element = resolveFormElement(target);
|
|
281
765
|
const attributes = { ...DEFAULT_ATTRIBUTES, ...options.attributes };
|
|
@@ -284,47 +768,49 @@ var SamlineForms = (() => {
|
|
|
284
768
|
...options,
|
|
285
769
|
attributes
|
|
286
770
|
};
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
771
|
+
const state2 = {
|
|
772
|
+
element,
|
|
773
|
+
options: normalizedOptions,
|
|
774
|
+
attributes,
|
|
775
|
+
validators: normalizedOptions.validators ?? {},
|
|
776
|
+
watchedFields: /* @__PURE__ */ new Map(),
|
|
777
|
+
subscribers: /* @__PURE__ */ new Set(),
|
|
778
|
+
submitHandlers: /* @__PURE__ */ new Set(),
|
|
779
|
+
fieldCache: /* @__PURE__ */ new Map(),
|
|
780
|
+
manualErrors: {},
|
|
781
|
+
validationErrors: {},
|
|
782
|
+
isValidated: Boolean(normalizedOptions.autoValidate),
|
|
783
|
+
autoSubmitEnabled: false,
|
|
784
|
+
autoSubmitDebounce: 0,
|
|
785
|
+
submitCount: 0,
|
|
786
|
+
autoSubmitTimer: null,
|
|
787
|
+
isDestroyed: false,
|
|
788
|
+
listeners: [],
|
|
789
|
+
mutationObserver: null,
|
|
790
|
+
formattedFields: /* @__PURE__ */ new Map(),
|
|
791
|
+
api: null
|
|
305
792
|
};
|
|
306
|
-
const
|
|
307
|
-
|
|
308
|
-
|
|
793
|
+
const notifySubscribers = () => {
|
|
794
|
+
if (!state2.api) return;
|
|
795
|
+
const snapshot = state2.api.getState();
|
|
796
|
+
state2.subscribers.forEach((listener) => listener(snapshot));
|
|
309
797
|
};
|
|
310
|
-
const
|
|
311
|
-
|
|
798
|
+
const addListener2 = (node, type, handler) => {
|
|
799
|
+
node.addEventListener(type, handler);
|
|
800
|
+
state2.listeners.push({ element: node, type, handler });
|
|
312
801
|
};
|
|
802
|
+
const clearFieldCache = () => state2.fieldCache.clear();
|
|
313
803
|
const getFieldsByName = (name) => {
|
|
314
|
-
if (!element)
|
|
315
|
-
|
|
804
|
+
if (!state2.element) return [];
|
|
805
|
+
if (!state2.fieldCache.has(name)) {
|
|
806
|
+
state2.fieldCache.set(name, queryNamedFields(state2.element, name));
|
|
316
807
|
}
|
|
317
|
-
|
|
318
|
-
fieldCache.set(name, queryNamedFields(element, name));
|
|
319
|
-
}
|
|
320
|
-
return fieldCache.get(name) ?? [];
|
|
808
|
+
return state2.fieldCache.get(name) ?? [];
|
|
321
809
|
};
|
|
322
810
|
const getTrackedFieldNames = () => {
|
|
323
|
-
if (!element)
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
const names = new Set(Object.keys(validators));
|
|
327
|
-
for (const field of getNamedFields(element)) {
|
|
811
|
+
if (!state2.element) return Object.keys(state2.validators);
|
|
812
|
+
const names = new Set(Object.keys(state2.validators));
|
|
813
|
+
for (const field of getNamedFields(state2.element)) {
|
|
328
814
|
names.add(field.name);
|
|
329
815
|
}
|
|
330
816
|
return Array.from(names);
|
|
@@ -332,15 +818,13 @@ var SamlineForms = (() => {
|
|
|
332
818
|
const getValues = () => {
|
|
333
819
|
const values = {};
|
|
334
820
|
for (const name of getTrackedFieldNames()) {
|
|
335
|
-
values[name] =
|
|
821
|
+
values[name] = readFieldValue(getFieldsByName(name));
|
|
336
822
|
}
|
|
337
823
|
return values;
|
|
338
824
|
};
|
|
339
|
-
const getMergedErrors = () => mergeErrors(validationErrors, manualErrors);
|
|
825
|
+
const getMergedErrors = () => mergeErrors(state2.validationErrors, state2.manualErrors);
|
|
340
826
|
const syncVisualState = (names) => {
|
|
341
|
-
if (!element)
|
|
342
|
-
return;
|
|
343
|
-
}
|
|
827
|
+
if (!state2.element) return;
|
|
344
828
|
const targetNames = names ?? getTrackedFieldNames();
|
|
345
829
|
const errors = getMergedErrors();
|
|
346
830
|
for (const name of targetNames) {
|
|
@@ -352,24 +836,23 @@ var SamlineForms = (() => {
|
|
|
352
836
|
}
|
|
353
837
|
}
|
|
354
838
|
};
|
|
839
|
+
void readFieldValue;
|
|
840
|
+
void writeFieldValue;
|
|
355
841
|
const validateNames = (names) => {
|
|
356
|
-
const targetNames = names ?? Object.keys(validators);
|
|
842
|
+
const targetNames = names ?? Object.keys(state2.validators);
|
|
357
843
|
const values = getValues();
|
|
358
|
-
const nextValidationErrors = names ? cloneErrors(validationErrors) : {};
|
|
844
|
+
const nextValidationErrors = names ? cloneErrors(state2.validationErrors) : {};
|
|
359
845
|
for (const name of targetNames) {
|
|
360
|
-
const rules = validators[name];
|
|
846
|
+
const rules = state2.validators[name];
|
|
361
847
|
if (!rules) {
|
|
362
848
|
delete nextValidationErrors[name];
|
|
363
849
|
continue;
|
|
364
850
|
}
|
|
365
|
-
const
|
|
366
|
-
if (
|
|
367
|
-
|
|
368
|
-
} else {
|
|
369
|
-
delete nextValidationErrors[name];
|
|
370
|
-
}
|
|
851
|
+
const messages = validateFieldValue(name, values[name], rules, values);
|
|
852
|
+
if (messages.length > 0) nextValidationErrors[name] = messages;
|
|
853
|
+
else delete nextValidationErrors[name];
|
|
371
854
|
}
|
|
372
|
-
validationErrors = nextValidationErrors;
|
|
855
|
+
state2.validationErrors = nextValidationErrors;
|
|
373
856
|
syncVisualState(names);
|
|
374
857
|
return {
|
|
375
858
|
isValid: Object.keys(getMergedErrors()).length === 0,
|
|
@@ -377,45 +860,49 @@ var SamlineForms = (() => {
|
|
|
377
860
|
};
|
|
378
861
|
};
|
|
379
862
|
const emitFieldWatchers = (name) => {
|
|
380
|
-
if (!element)
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
const
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
const value = api.getValue(name);
|
|
388
|
-
const state = api.getState();
|
|
389
|
-
callbacks.forEach((callback) => callback(value, element, state));
|
|
863
|
+
if (!state2.element || !state2.api) return;
|
|
864
|
+
const callbacks = state2.watchedFields.get(name);
|
|
865
|
+
if (!callbacks || callbacks.size === 0) return;
|
|
866
|
+
const value = state2.api.getValue(name);
|
|
867
|
+
const fieldElement = state2.api.getField(name);
|
|
868
|
+
const snapshot = state2.api.getState();
|
|
869
|
+
callbacks.forEach((callback) => callback(value, fieldElement, state2.element, snapshot));
|
|
390
870
|
};
|
|
391
871
|
const scheduleAutoSubmit = () => {
|
|
392
|
-
if (!element || !autoSubmitEnabled)
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
autoSubmitTimer = setTimeout(() => submitForm(element), autoSubmitDebounce);
|
|
872
|
+
if (!state2.element || !state2.autoSubmitEnabled) return;
|
|
873
|
+
if (state2.autoSubmitTimer) clearTimeout(state2.autoSubmitTimer);
|
|
874
|
+
if (state2.autoSubmitDebounce > 0) {
|
|
875
|
+
state2.autoSubmitTimer = setTimeout(
|
|
876
|
+
() => submitForm(state2.element),
|
|
877
|
+
state2.autoSubmitDebounce
|
|
878
|
+
);
|
|
400
879
|
return;
|
|
401
880
|
}
|
|
402
|
-
submitForm(element);
|
|
881
|
+
submitForm(state2.element);
|
|
882
|
+
};
|
|
883
|
+
const helpers = {
|
|
884
|
+
notifySubscribers,
|
|
885
|
+
clearFieldCache,
|
|
886
|
+
getFieldsByName,
|
|
887
|
+
getTrackedFieldNames,
|
|
888
|
+
getValues,
|
|
889
|
+
getMergedErrors,
|
|
890
|
+
syncVisualState,
|
|
891
|
+
validateNames,
|
|
892
|
+
emitFieldWatchers,
|
|
893
|
+
scheduleAutoSubmit
|
|
403
894
|
};
|
|
404
895
|
const handleDelegatedEvent = (event) => {
|
|
405
896
|
const target2 = event.target;
|
|
406
|
-
if (!(target2 instanceof Element) || !isFieldElement(target2))
|
|
407
|
-
return;
|
|
408
|
-
}
|
|
897
|
+
if (!(target2 instanceof Element) || !isFieldElement(target2)) return;
|
|
409
898
|
const name = target2.name;
|
|
410
|
-
if (!name)
|
|
411
|
-
return;
|
|
412
|
-
}
|
|
899
|
+
if (!name) return;
|
|
413
900
|
clearFieldCache();
|
|
414
901
|
if (normalizedOptions.clearManualErrorsOnChange) {
|
|
415
|
-
delete manualErrors[name];
|
|
902
|
+
delete state2.manualErrors[name];
|
|
416
903
|
}
|
|
417
904
|
syncVisualState([name]);
|
|
418
|
-
if (isValidated && validators[name]) {
|
|
905
|
+
if (state2.isValidated && state2.validators[name]) {
|
|
419
906
|
validateNames([name]);
|
|
420
907
|
}
|
|
421
908
|
emitFieldWatchers(name);
|
|
@@ -423,305 +910,132 @@ var SamlineForms = (() => {
|
|
|
423
910
|
scheduleAutoSubmit();
|
|
424
911
|
};
|
|
425
912
|
const handleSubmitEvent = (event) => {
|
|
426
|
-
if (!element || isDestroyed)
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
manualErrors = {};
|
|
431
|
-
}
|
|
432
|
-
const validation = api.validate();
|
|
433
|
-
const handlers = Array.from(submitHandlers);
|
|
913
|
+
if (!state2.element || state2.isDestroyed || !state2.api) return;
|
|
914
|
+
if (normalizedOptions.clearErrorsOnSubmit) state2.manualErrors = {};
|
|
915
|
+
const validation = state2.api.validate();
|
|
916
|
+
const handlers = Array.from(state2.submitHandlers);
|
|
434
917
|
const shouldPrevent = validation.isValid ? handlers.some((handler) => handler.preventDefault) : true;
|
|
435
|
-
if (shouldPrevent)
|
|
436
|
-
|
|
437
|
-
}
|
|
438
|
-
submitCount += 1;
|
|
918
|
+
if (shouldPrevent) event.preventDefault();
|
|
919
|
+
state2.submitCount += 1;
|
|
439
920
|
notifySubscribers();
|
|
440
|
-
if (!validation.isValid)
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
921
|
+
if (!validation.isValid) return;
|
|
922
|
+
const { data, formData } = state2.api.getData();
|
|
923
|
+
const snapshot = state2.api.getState();
|
|
924
|
+
handlers.forEach(
|
|
925
|
+
(handler) => handler.callback(state2.element, data, formData, snapshot)
|
|
926
|
+
);
|
|
446
927
|
};
|
|
447
928
|
const startMutationObserver = () => {
|
|
448
|
-
if (!element || typeof MutationObserver === "undefined")
|
|
449
|
-
|
|
450
|
-
}
|
|
451
|
-
mutationObserver = new MutationObserver(() => {
|
|
929
|
+
if (!state2.element || typeof MutationObserver === "undefined") return;
|
|
930
|
+
state2.mutationObserver = new MutationObserver(() => {
|
|
452
931
|
clearFieldCache();
|
|
453
|
-
if (isValidated) {
|
|
932
|
+
if (state2.isValidated) {
|
|
454
933
|
syncVisualState();
|
|
455
934
|
validateNames();
|
|
456
935
|
}
|
|
457
936
|
notifySubscribers();
|
|
458
937
|
});
|
|
459
|
-
mutationObserver.observe(element, {
|
|
938
|
+
state2.mutationObserver.observe(state2.element, {
|
|
460
939
|
childList: true,
|
|
461
940
|
subtree: true,
|
|
462
941
|
attributes: true,
|
|
463
942
|
attributeFilter: ["name", "type"]
|
|
464
943
|
});
|
|
465
944
|
};
|
|
466
|
-
const isFieldElement = (value) => value instanceof HTMLInputElement || value instanceof HTMLSelectElement || value instanceof HTMLTextAreaElement;
|
|
467
945
|
const api = {
|
|
468
|
-
element
|
|
469
|
-
|
|
470
|
-
options: normalizedOptions,
|
|
471
|
-
onSubmit(callback, preventDefault = true) {
|
|
472
|
-
submitHandlers.add({ callback, preventDefault });
|
|
473
|
-
return api;
|
|
946
|
+
get element() {
|
|
947
|
+
return state2.element;
|
|
474
948
|
},
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
return api;
|
|
949
|
+
get f() {
|
|
950
|
+
return state2.element;
|
|
478
951
|
},
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
callbacks.add(callback);
|
|
482
|
-
watchedFields.set(field, callbacks);
|
|
483
|
-
if (element) {
|
|
484
|
-
callback(api.getValue(field), element, api.getState());
|
|
485
|
-
}
|
|
486
|
-
return () => {
|
|
487
|
-
const currentCallbacks = watchedFields.get(field);
|
|
488
|
-
currentCallbacks?.delete(callback);
|
|
489
|
-
if (currentCallbacks && currentCallbacks.size === 0) {
|
|
490
|
-
watchedFields.delete(field);
|
|
491
|
-
}
|
|
492
|
-
};
|
|
493
|
-
},
|
|
494
|
-
unwatch(field, callback) {
|
|
495
|
-
if (!field) {
|
|
496
|
-
watchedFields.clear();
|
|
497
|
-
return api;
|
|
498
|
-
}
|
|
499
|
-
if (!callback) {
|
|
500
|
-
watchedFields.delete(field);
|
|
501
|
-
return api;
|
|
502
|
-
}
|
|
503
|
-
const callbacks = watchedFields.get(field);
|
|
504
|
-
callbacks?.delete(callback);
|
|
505
|
-
if (callbacks && callbacks.size === 0) {
|
|
506
|
-
watchedFields.delete(field);
|
|
507
|
-
}
|
|
508
|
-
return api;
|
|
509
|
-
},
|
|
510
|
-
subscribe(listener) {
|
|
511
|
-
subscribers.add(listener);
|
|
512
|
-
listener(api.getState());
|
|
513
|
-
return () => {
|
|
514
|
-
subscribers.delete(listener);
|
|
515
|
-
};
|
|
516
|
-
},
|
|
517
|
-
prefill(fieldName) {
|
|
518
|
-
if (!element) {
|
|
519
|
-
return api;
|
|
520
|
-
}
|
|
521
|
-
const queryParams = new URLSearchParams(window.location.search);
|
|
522
|
-
queryParams.forEach((value, key) => {
|
|
523
|
-
if (fieldName && fieldName !== key) {
|
|
524
|
-
return;
|
|
525
|
-
}
|
|
526
|
-
api.setValue(key, value);
|
|
527
|
-
});
|
|
528
|
-
return api;
|
|
952
|
+
get options() {
|
|
953
|
+
return state2.options;
|
|
529
954
|
},
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
if (Array.isArray(fields)) {
|
|
553
|
-
manualErrors = {
|
|
554
|
-
...manualErrors,
|
|
555
|
-
...Object.fromEntries(fields.map((field) => [field, ["Invalid value."]]))
|
|
556
|
-
};
|
|
557
|
-
} else {
|
|
558
|
-
manualErrors = {
|
|
559
|
-
...manualErrors,
|
|
560
|
-
...cloneErrors(fields)
|
|
561
|
-
};
|
|
562
|
-
}
|
|
563
|
-
syncVisualState(Array.isArray(fields) ? fields : Object.keys(fields));
|
|
564
|
-
notifySubscribers();
|
|
565
|
-
return api;
|
|
566
|
-
},
|
|
567
|
-
clearErrors(fields) {
|
|
568
|
-
if (!fields) {
|
|
569
|
-
manualErrors = {};
|
|
570
|
-
syncVisualState();
|
|
571
|
-
notifySubscribers();
|
|
572
|
-
return api;
|
|
573
|
-
}
|
|
574
|
-
for (const field of fields) {
|
|
575
|
-
delete manualErrors[field];
|
|
576
|
-
}
|
|
577
|
-
syncVisualState(fields);
|
|
578
|
-
notifySubscribers();
|
|
579
|
-
return api;
|
|
580
|
-
},
|
|
581
|
-
setValue(name, value) {
|
|
582
|
-
const fields = getFieldsByName(name);
|
|
583
|
-
if (fields.length === 0) {
|
|
584
|
-
return api;
|
|
585
|
-
}
|
|
586
|
-
writeFieldValue(fields, value);
|
|
587
|
-
const firstField = fields[0];
|
|
588
|
-
if (!firstField) {
|
|
589
|
-
return api;
|
|
590
|
-
}
|
|
591
|
-
const eventType = firstField instanceof HTMLSelectElement || firstField instanceof HTMLInputElement && (firstField.type === "checkbox" || firstField.type === "radio") ? "change" : "input";
|
|
592
|
-
firstField.dispatchEvent(new Event(eventType, { bubbles: true }));
|
|
593
|
-
return api;
|
|
594
|
-
},
|
|
595
|
-
validate(fields) {
|
|
596
|
-
isValidated = true;
|
|
597
|
-
syncVisualState(fields);
|
|
598
|
-
return validateNames(fields);
|
|
599
|
-
},
|
|
600
|
-
revalidate(fields) {
|
|
601
|
-
return api.validate(fields);
|
|
602
|
-
},
|
|
603
|
-
reset() {
|
|
604
|
-
if (!element) {
|
|
605
|
-
return api;
|
|
606
|
-
}
|
|
607
|
-
element.reset();
|
|
608
|
-
manualErrors = {};
|
|
609
|
-
validationErrors = {};
|
|
610
|
-
clearAttributes(element, [attributes.error, attributes.filled]);
|
|
611
|
-
if (isValidated) {
|
|
612
|
-
syncVisualState();
|
|
613
|
-
}
|
|
614
|
-
notifySubscribers();
|
|
615
|
-
return api;
|
|
616
|
-
},
|
|
617
|
-
autoSubmit(nextOptions = true) {
|
|
618
|
-
autoSubmitEnabled = nextOptions !== false;
|
|
619
|
-
autoSubmitDebounce = typeof nextOptions === "object" && nextOptions ? nextOptions.debounce ?? 0 : 0;
|
|
620
|
-
notifySubscribers();
|
|
621
|
-
return api;
|
|
622
|
-
},
|
|
623
|
-
disableAutoSubmit() {
|
|
624
|
-
autoSubmitEnabled = false;
|
|
625
|
-
if (autoSubmitTimer) {
|
|
626
|
-
clearTimeout(autoSubmitTimer);
|
|
627
|
-
autoSubmitTimer = null;
|
|
628
|
-
}
|
|
629
|
-
notifySubscribers();
|
|
630
|
-
return api;
|
|
631
|
-
},
|
|
632
|
-
getValue(name) {
|
|
633
|
-
return readFieldValue(getFieldsByName(name));
|
|
634
|
-
},
|
|
635
|
-
getField(name) {
|
|
636
|
-
const fields = getFieldsByName(name);
|
|
637
|
-
if (fields.length === 0) {
|
|
638
|
-
return null;
|
|
639
|
-
}
|
|
640
|
-
const [firstField] = fields;
|
|
641
|
-
if (!firstField) {
|
|
642
|
-
return null;
|
|
643
|
-
}
|
|
644
|
-
return fields.length === 1 ? firstField : fields;
|
|
645
|
-
},
|
|
646
|
-
getData() {
|
|
647
|
-
if (!element) {
|
|
648
|
-
return { data: {}, formData: new FormData() };
|
|
649
|
-
}
|
|
650
|
-
return parseFormData(element);
|
|
651
|
-
},
|
|
652
|
-
getState() {
|
|
653
|
-
const values = getValues();
|
|
654
|
-
const errors = cloneErrors(getMergedErrors());
|
|
655
|
-
const filledFields = getTrackedFieldNames().filter((name) => {
|
|
656
|
-
const value = values[name];
|
|
657
|
-
return Array.isArray(value) ? value.length > 0 : typeof value === "string" ? value.trim().length > 0 : value !== void 0;
|
|
658
|
-
});
|
|
659
|
-
return {
|
|
660
|
-
...createEmptyFormState(),
|
|
661
|
-
values,
|
|
662
|
-
errors,
|
|
663
|
-
filledFields,
|
|
664
|
-
isValid: Object.keys(errors).length === 0,
|
|
665
|
-
isValidated,
|
|
666
|
-
autoSubmit: autoSubmitEnabled,
|
|
667
|
-
submitCount
|
|
668
|
-
};
|
|
669
|
-
},
|
|
670
|
-
destroy() {
|
|
671
|
-
if (isDestroyed) {
|
|
672
|
-
return;
|
|
673
|
-
}
|
|
674
|
-
isDestroyed = true;
|
|
675
|
-
for (const listener of listeners) {
|
|
676
|
-
listener.element.removeEventListener(listener.type, listener.handler);
|
|
677
|
-
}
|
|
678
|
-
listeners.length = 0;
|
|
679
|
-
if (autoSubmitTimer) {
|
|
680
|
-
clearTimeout(autoSubmitTimer);
|
|
681
|
-
autoSubmitTimer = null;
|
|
682
|
-
}
|
|
683
|
-
mutationObserver?.disconnect();
|
|
684
|
-
mutationObserver = null;
|
|
685
|
-
watchedFields.clear();
|
|
686
|
-
subscribers.clear();
|
|
687
|
-
submitHandlers.clear();
|
|
688
|
-
clearFieldCache();
|
|
689
|
-
manualErrors = {};
|
|
690
|
-
validationErrors = {};
|
|
691
|
-
}
|
|
955
|
+
onSubmit: createOnSubmit(state2, helpers),
|
|
956
|
+
watch: createWatch(state2, helpers),
|
|
957
|
+
observe: createObserve(state2, helpers),
|
|
958
|
+
unwatch: createUnwatch(state2, helpers),
|
|
959
|
+
subscribe: createSubscribe(state2, helpers),
|
|
960
|
+
prefill: createPrefill(state2, helpers),
|
|
961
|
+
append: createAppend(state2, helpers),
|
|
962
|
+
setErrors: createSetErrors(state2, helpers),
|
|
963
|
+
clearErrors: createClearErrors(state2, helpers),
|
|
964
|
+
setValue: createSetValue(state2, helpers),
|
|
965
|
+
getValue: createGetValue(state2, helpers),
|
|
966
|
+
getField: createGetField(state2, helpers),
|
|
967
|
+
validate: createValidate(state2, helpers),
|
|
968
|
+
revalidate: createRevalidate(state2, helpers),
|
|
969
|
+
reset: createReset(state2, helpers),
|
|
970
|
+
autoSubmit: createAutoSubmit(state2, helpers),
|
|
971
|
+
disableAutoSubmit: createDisableAutoSubmit(state2, helpers),
|
|
972
|
+
getData: createGetData(state2, helpers),
|
|
973
|
+
getState: createGetState(state2, helpers),
|
|
974
|
+
format: createFormat(state2, helpers),
|
|
975
|
+
formatAll: createFormatAll(state2, helpers),
|
|
976
|
+
destroy: createDestroy(state2, helpers)
|
|
692
977
|
};
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
978
|
+
state2.api = api;
|
|
979
|
+
if (state2.element) {
|
|
980
|
+
addListener2(state2.element, "input", handleDelegatedEvent);
|
|
981
|
+
addListener2(state2.element, "change", handleDelegatedEvent);
|
|
982
|
+
addListener2(state2.element, "submit", handleSubmitEvent);
|
|
697
983
|
startMutationObserver();
|
|
698
984
|
}
|
|
699
985
|
if (normalizedOptions.autoSubmit) {
|
|
700
|
-
|
|
701
|
-
|
|
986
|
+
api.autoSubmit(normalizedOptions.autoSubmit);
|
|
987
|
+
}
|
|
988
|
+
if (normalizedOptions.formats) {
|
|
989
|
+
for (const config of Object.values(normalizedOptions.formats)) {
|
|
990
|
+
api.format(config);
|
|
991
|
+
}
|
|
702
992
|
}
|
|
703
|
-
if (isValidated) {
|
|
993
|
+
if (state2.isValidated) {
|
|
704
994
|
syncVisualState();
|
|
705
995
|
validateNames();
|
|
706
996
|
}
|
|
707
997
|
return api;
|
|
708
998
|
};
|
|
709
999
|
|
|
710
|
-
// src/
|
|
711
|
-
var form = (target, options) => createFormController(target, options);
|
|
1000
|
+
// src/api/form.ts
|
|
1001
|
+
var form = (target, options = {}) => createFormController(target, options);
|
|
712
1002
|
|
|
713
1003
|
// src/browser/global.ts
|
|
714
|
-
var
|
|
715
|
-
|
|
1004
|
+
var available = {};
|
|
1005
|
+
var newForm = (input) => {
|
|
1006
|
+
const { id, options } = input;
|
|
1007
|
+
if (!id) {
|
|
1008
|
+
console.error("Form ID is required");
|
|
1009
|
+
return;
|
|
1010
|
+
}
|
|
1011
|
+
const controller = form(id, { ...options });
|
|
1012
|
+
available[id] = controller;
|
|
1013
|
+
return controller;
|
|
1014
|
+
};
|
|
1015
|
+
var destroyForm = (id) => {
|
|
1016
|
+
if (!id) {
|
|
1017
|
+
console.error("Form ID is required");
|
|
1018
|
+
return;
|
|
1019
|
+
}
|
|
1020
|
+
const controller = available[id];
|
|
1021
|
+
if (controller) {
|
|
1022
|
+
controller.destroy();
|
|
1023
|
+
delete available[id];
|
|
1024
|
+
} else {
|
|
1025
|
+
console.warn(`Form with ID ${id} not found`);
|
|
1026
|
+
}
|
|
1027
|
+
};
|
|
1028
|
+
var Forms = {
|
|
716
1029
|
form,
|
|
717
|
-
|
|
718
|
-
|
|
1030
|
+
newForm,
|
|
1031
|
+
destroyForm,
|
|
1032
|
+
available
|
|
719
1033
|
};
|
|
720
1034
|
if (typeof globalThis !== "undefined") {
|
|
721
1035
|
;
|
|
722
|
-
globalThis.
|
|
1036
|
+
globalThis.Forms = Forms;
|
|
723
1037
|
}
|
|
724
|
-
var global_default =
|
|
1038
|
+
var global_default = Forms;
|
|
725
1039
|
return __toCommonJS(global_exports);
|
|
726
1040
|
})();
|
|
727
1041
|
//# sourceMappingURL=global.global.js.map
|