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