@samline/forms 1.0.2 → 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 +88 -186
- package/dist/browser/global.d.ts +152 -0
- package/dist/browser/global.global.js +780 -472
- package/dist/browser/global.global.js.map +1 -1
- package/dist/index.cjs +755 -468
- 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-KIJEFIHP.js +0 -572
- package/dist/chunk-KIJEFIHP.js.map +0 -1
- package/dist/chunk-KKQD25KI.js +0 -11
- package/dist/chunk-KKQD25KI.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 -730
- 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 -760
- 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-C0_1rYlm.d.cts +0 -94
- package/dist/types-C0_1rYlm.d.ts +0 -94
- package/dist/vanilla/index.cjs +0 -701
- 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 -737
- 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;
|
|
193
|
-
}
|
|
194
|
-
if (firstField instanceof HTMLSelectElement || firstField instanceof HTMLTextAreaElement) {
|
|
195
|
-
return firstField.value;
|
|
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;
|
|
196
502
|
}
|
|
197
|
-
if (
|
|
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,25 +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
|
-
clearErrorsOnSubmit: true
|
|
750
|
+
clearErrorsOnSubmit: true,
|
|
751
|
+
clearManualErrorsOnChange: true
|
|
267
752
|
};
|
|
268
|
-
var mergeErrors = (left, right) => {
|
|
269
|
-
const merged = { ...left };
|
|
270
|
-
for (const [field, messages] of Object.entries(right)) {
|
|
271
|
-
merged[field] = merged[field] ? [...merged[field], ...messages] : [...messages];
|
|
272
|
-
}
|
|
273
|
-
return merged;
|
|
274
|
-
};
|
|
275
|
-
var cloneErrors = (errors) => Object.fromEntries(
|
|
276
|
-
Object.entries(errors).map(([field, messages]) => [field, [...messages]])
|
|
277
|
-
);
|
|
278
753
|
var createFormController = (target, options = {}) => {
|
|
279
754
|
const element = resolveFormElement(target);
|
|
280
755
|
const attributes = { ...DEFAULT_ATTRIBUTES, ...options.attributes };
|
|
@@ -283,47 +758,49 @@ var SamlineForms = (() => {
|
|
|
283
758
|
...options,
|
|
284
759
|
attributes
|
|
285
760
|
};
|
|
286
|
-
const
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
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
|
|
304
782
|
};
|
|
305
|
-
const
|
|
306
|
-
|
|
307
|
-
|
|
783
|
+
const notifySubscribers = () => {
|
|
784
|
+
if (!state2.api) return;
|
|
785
|
+
const snapshot = state2.api.getState();
|
|
786
|
+
state2.subscribers.forEach((listener) => listener(snapshot));
|
|
308
787
|
};
|
|
309
|
-
const
|
|
310
|
-
|
|
788
|
+
const addListener2 = (node, type, handler) => {
|
|
789
|
+
node.addEventListener(type, handler);
|
|
790
|
+
state2.listeners.push({ element: node, type, handler });
|
|
311
791
|
};
|
|
792
|
+
const clearFieldCache = () => state2.fieldCache.clear();
|
|
312
793
|
const getFieldsByName = (name) => {
|
|
313
|
-
if (!element)
|
|
314
|
-
|
|
794
|
+
if (!state2.element) return [];
|
|
795
|
+
if (!state2.fieldCache.has(name)) {
|
|
796
|
+
state2.fieldCache.set(name, queryNamedFields(state2.element, name));
|
|
315
797
|
}
|
|
316
|
-
|
|
317
|
-
fieldCache.set(name, queryNamedFields(element, name));
|
|
318
|
-
}
|
|
319
|
-
return fieldCache.get(name) ?? [];
|
|
798
|
+
return state2.fieldCache.get(name) ?? [];
|
|
320
799
|
};
|
|
321
800
|
const getTrackedFieldNames = () => {
|
|
322
|
-
if (!element)
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
const names = new Set(Object.keys(validators));
|
|
326
|
-
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)) {
|
|
327
804
|
names.add(field.name);
|
|
328
805
|
}
|
|
329
806
|
return Array.from(names);
|
|
@@ -331,15 +808,13 @@ var SamlineForms = (() => {
|
|
|
331
808
|
const getValues = () => {
|
|
332
809
|
const values = {};
|
|
333
810
|
for (const name of getTrackedFieldNames()) {
|
|
334
|
-
values[name] =
|
|
811
|
+
values[name] = readFieldValue(getFieldsByName(name));
|
|
335
812
|
}
|
|
336
813
|
return values;
|
|
337
814
|
};
|
|
338
|
-
const getMergedErrors = () => mergeErrors(validationErrors, manualErrors);
|
|
815
|
+
const getMergedErrors = () => mergeErrors(state2.validationErrors, state2.manualErrors);
|
|
339
816
|
const syncVisualState = (names) => {
|
|
340
|
-
if (!element)
|
|
341
|
-
return;
|
|
342
|
-
}
|
|
817
|
+
if (!state2.element) return;
|
|
343
818
|
const targetNames = names ?? getTrackedFieldNames();
|
|
344
819
|
const errors = getMergedErrors();
|
|
345
820
|
for (const name of targetNames) {
|
|
@@ -351,24 +826,23 @@ var SamlineForms = (() => {
|
|
|
351
826
|
}
|
|
352
827
|
}
|
|
353
828
|
};
|
|
829
|
+
void readFieldValue;
|
|
830
|
+
void writeFieldValue;
|
|
354
831
|
const validateNames = (names) => {
|
|
355
|
-
const targetNames = names ?? Object.keys(validators);
|
|
832
|
+
const targetNames = names ?? Object.keys(state2.validators);
|
|
356
833
|
const values = getValues();
|
|
357
|
-
const nextValidationErrors = names ? cloneErrors(validationErrors) : {};
|
|
834
|
+
const nextValidationErrors = names ? cloneErrors(state2.validationErrors) : {};
|
|
358
835
|
for (const name of targetNames) {
|
|
359
|
-
const rules = validators[name];
|
|
836
|
+
const rules = state2.validators[name];
|
|
360
837
|
if (!rules) {
|
|
361
838
|
delete nextValidationErrors[name];
|
|
362
839
|
continue;
|
|
363
840
|
}
|
|
364
|
-
const
|
|
365
|
-
if (
|
|
366
|
-
|
|
367
|
-
} else {
|
|
368
|
-
delete nextValidationErrors[name];
|
|
369
|
-
}
|
|
841
|
+
const messages = validateFieldValue(name, values[name], rules, values);
|
|
842
|
+
if (messages.length > 0) nextValidationErrors[name] = messages;
|
|
843
|
+
else delete nextValidationErrors[name];
|
|
370
844
|
}
|
|
371
|
-
validationErrors = nextValidationErrors;
|
|
845
|
+
state2.validationErrors = nextValidationErrors;
|
|
372
846
|
syncVisualState(names);
|
|
373
847
|
return {
|
|
374
848
|
isValid: Object.keys(getMergedErrors()).length === 0,
|
|
@@ -376,42 +850,49 @@ var SamlineForms = (() => {
|
|
|
376
850
|
};
|
|
377
851
|
};
|
|
378
852
|
const emitFieldWatchers = (name) => {
|
|
379
|
-
if (!element)
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
const
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
const value = api.getValue(name);
|
|
387
|
-
const state = api.getState();
|
|
388
|
-
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));
|
|
389
860
|
};
|
|
390
861
|
const scheduleAutoSubmit = () => {
|
|
391
|
-
if (!element || !autoSubmitEnabled)
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
autoSubmitTimer = setTimeout(() => submitForm(element), autoSubmitDebounce);
|
|
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
|
+
);
|
|
399
869
|
return;
|
|
400
870
|
}
|
|
401
|
-
submitForm(element);
|
|
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
|
|
402
884
|
};
|
|
403
885
|
const handleDelegatedEvent = (event) => {
|
|
404
886
|
const target2 = event.target;
|
|
405
|
-
if (!(target2 instanceof Element) || !isFieldElement(target2))
|
|
406
|
-
return;
|
|
407
|
-
}
|
|
887
|
+
if (!(target2 instanceof Element) || !isFieldElement(target2)) return;
|
|
408
888
|
const name = target2.name;
|
|
409
|
-
if (!name)
|
|
410
|
-
return;
|
|
411
|
-
}
|
|
889
|
+
if (!name) return;
|
|
412
890
|
clearFieldCache();
|
|
891
|
+
if (normalizedOptions.clearManualErrorsOnChange) {
|
|
892
|
+
delete state2.manualErrors[name];
|
|
893
|
+
}
|
|
413
894
|
syncVisualState([name]);
|
|
414
|
-
if (isValidated && validators[name]) {
|
|
895
|
+
if (state2.isValidated && state2.validators[name]) {
|
|
415
896
|
validateNames([name]);
|
|
416
897
|
}
|
|
417
898
|
emitFieldWatchers(name);
|
|
@@ -419,305 +900,132 @@ var SamlineForms = (() => {
|
|
|
419
900
|
scheduleAutoSubmit();
|
|
420
901
|
};
|
|
421
902
|
const handleSubmitEvent = (event) => {
|
|
422
|
-
if (!element || isDestroyed)
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
manualErrors = {};
|
|
427
|
-
}
|
|
428
|
-
const validation = api.validate();
|
|
429
|
-
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);
|
|
430
907
|
const shouldPrevent = validation.isValid ? handlers.some((handler) => handler.preventDefault) : true;
|
|
431
|
-
if (shouldPrevent)
|
|
432
|
-
|
|
433
|
-
}
|
|
434
|
-
submitCount += 1;
|
|
908
|
+
if (shouldPrevent) event.preventDefault();
|
|
909
|
+
state2.submitCount += 1;
|
|
435
910
|
notifySubscribers();
|
|
436
|
-
if (!validation.isValid)
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
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
|
+
);
|
|
442
917
|
};
|
|
443
918
|
const startMutationObserver = () => {
|
|
444
|
-
if (!element || typeof MutationObserver === "undefined")
|
|
445
|
-
|
|
446
|
-
}
|
|
447
|
-
mutationObserver = new MutationObserver(() => {
|
|
919
|
+
if (!state2.element || typeof MutationObserver === "undefined") return;
|
|
920
|
+
state2.mutationObserver = new MutationObserver(() => {
|
|
448
921
|
clearFieldCache();
|
|
449
|
-
if (isValidated) {
|
|
922
|
+
if (state2.isValidated) {
|
|
450
923
|
syncVisualState();
|
|
451
924
|
validateNames();
|
|
452
925
|
}
|
|
453
926
|
notifySubscribers();
|
|
454
927
|
});
|
|
455
|
-
mutationObserver.observe(element, {
|
|
928
|
+
state2.mutationObserver.observe(state2.element, {
|
|
456
929
|
childList: true,
|
|
457
930
|
subtree: true,
|
|
458
931
|
attributes: true,
|
|
459
932
|
attributeFilter: ["name", "type"]
|
|
460
933
|
});
|
|
461
934
|
};
|
|
462
|
-
const isFieldElement = (value) => value instanceof HTMLInputElement || value instanceof HTMLSelectElement || value instanceof HTMLTextAreaElement;
|
|
463
935
|
const api = {
|
|
464
|
-
element
|
|
465
|
-
|
|
466
|
-
options: normalizedOptions,
|
|
467
|
-
onSubmit(callback, preventDefault = true) {
|
|
468
|
-
submitHandlers.add({ callback, preventDefault });
|
|
469
|
-
return api;
|
|
470
|
-
},
|
|
471
|
-
watch(field, callback) {
|
|
472
|
-
api.observe(field, callback);
|
|
473
|
-
return api;
|
|
474
|
-
},
|
|
475
|
-
observe(field, callback) {
|
|
476
|
-
const callbacks = watchedFields.get(field) ?? /* @__PURE__ */ new Set();
|
|
477
|
-
callbacks.add(callback);
|
|
478
|
-
watchedFields.set(field, callbacks);
|
|
479
|
-
if (element) {
|
|
480
|
-
callback(api.getValue(field), element, api.getState());
|
|
481
|
-
}
|
|
482
|
-
return () => {
|
|
483
|
-
const currentCallbacks = watchedFields.get(field);
|
|
484
|
-
currentCallbacks?.delete(callback);
|
|
485
|
-
if (currentCallbacks && currentCallbacks.size === 0) {
|
|
486
|
-
watchedFields.delete(field);
|
|
487
|
-
}
|
|
488
|
-
};
|
|
489
|
-
},
|
|
490
|
-
unwatch(field, callback) {
|
|
491
|
-
if (!field) {
|
|
492
|
-
watchedFields.clear();
|
|
493
|
-
return api;
|
|
494
|
-
}
|
|
495
|
-
if (!callback) {
|
|
496
|
-
watchedFields.delete(field);
|
|
497
|
-
return api;
|
|
498
|
-
}
|
|
499
|
-
const callbacks = watchedFields.get(field);
|
|
500
|
-
callbacks?.delete(callback);
|
|
501
|
-
if (callbacks && callbacks.size === 0) {
|
|
502
|
-
watchedFields.delete(field);
|
|
503
|
-
}
|
|
504
|
-
return api;
|
|
505
|
-
},
|
|
506
|
-
subscribe(listener) {
|
|
507
|
-
subscribers.add(listener);
|
|
508
|
-
listener(api.getState());
|
|
509
|
-
return () => {
|
|
510
|
-
subscribers.delete(listener);
|
|
511
|
-
};
|
|
512
|
-
},
|
|
513
|
-
prefill(fieldName) {
|
|
514
|
-
if (!element) {
|
|
515
|
-
return api;
|
|
516
|
-
}
|
|
517
|
-
const queryParams = new URLSearchParams(window.location.search);
|
|
518
|
-
queryParams.forEach((value, key) => {
|
|
519
|
-
if (fieldName && fieldName !== key) {
|
|
520
|
-
return;
|
|
521
|
-
}
|
|
522
|
-
api.setValue(key, value);
|
|
523
|
-
});
|
|
524
|
-
return api;
|
|
525
|
-
},
|
|
526
|
-
append({ tag, content, class: className, atStart = false }) {
|
|
527
|
-
if (!element) {
|
|
528
|
-
return null;
|
|
529
|
-
}
|
|
530
|
-
clearFieldCache();
|
|
531
|
-
if (className) {
|
|
532
|
-
const classSelector = className.trim().split(/\s+/)[0];
|
|
533
|
-
element.querySelector(`.${classSelector}`)?.remove();
|
|
534
|
-
}
|
|
535
|
-
const node = document.createElement(tag);
|
|
536
|
-
if (className) {
|
|
537
|
-
node.className = className;
|
|
538
|
-
}
|
|
539
|
-
node.innerHTML = content;
|
|
540
|
-
if (atStart && element.firstChild) {
|
|
541
|
-
element.insertBefore(node, element.firstChild);
|
|
542
|
-
} else {
|
|
543
|
-
element.appendChild(node);
|
|
544
|
-
}
|
|
545
|
-
return node;
|
|
546
|
-
},
|
|
547
|
-
setErrors(fields) {
|
|
548
|
-
if (Array.isArray(fields)) {
|
|
549
|
-
manualErrors = {
|
|
550
|
-
...manualErrors,
|
|
551
|
-
...Object.fromEntries(fields.map((field) => [field, ["Invalid value."]]))
|
|
552
|
-
};
|
|
553
|
-
} else {
|
|
554
|
-
manualErrors = {
|
|
555
|
-
...manualErrors,
|
|
556
|
-
...cloneErrors(fields)
|
|
557
|
-
};
|
|
558
|
-
}
|
|
559
|
-
syncVisualState(Array.isArray(fields) ? fields : Object.keys(fields));
|
|
560
|
-
notifySubscribers();
|
|
561
|
-
return api;
|
|
936
|
+
get element() {
|
|
937
|
+
return state2.element;
|
|
562
938
|
},
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
manualErrors = {};
|
|
566
|
-
syncVisualState();
|
|
567
|
-
notifySubscribers();
|
|
568
|
-
return api;
|
|
569
|
-
}
|
|
570
|
-
for (const field of fields) {
|
|
571
|
-
delete manualErrors[field];
|
|
572
|
-
}
|
|
573
|
-
syncVisualState(fields);
|
|
574
|
-
notifySubscribers();
|
|
575
|
-
return api;
|
|
576
|
-
},
|
|
577
|
-
setValue(name, value) {
|
|
578
|
-
const fields = getFieldsByName(name);
|
|
579
|
-
if (fields.length === 0) {
|
|
580
|
-
return api;
|
|
581
|
-
}
|
|
582
|
-
writeFieldValue(fields, value);
|
|
583
|
-
const firstField = fields[0];
|
|
584
|
-
if (!firstField) {
|
|
585
|
-
return api;
|
|
586
|
-
}
|
|
587
|
-
const eventType = firstField instanceof HTMLSelectElement || firstField instanceof HTMLInputElement && (firstField.type === "checkbox" || firstField.type === "radio") ? "change" : "input";
|
|
588
|
-
firstField.dispatchEvent(new Event(eventType, { bubbles: true }));
|
|
589
|
-
return api;
|
|
590
|
-
},
|
|
591
|
-
validate(fields) {
|
|
592
|
-
isValidated = true;
|
|
593
|
-
syncVisualState(fields);
|
|
594
|
-
return validateNames(fields);
|
|
595
|
-
},
|
|
596
|
-
revalidate(fields) {
|
|
597
|
-
return api.validate(fields);
|
|
939
|
+
get f() {
|
|
940
|
+
return state2.element;
|
|
598
941
|
},
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
return api;
|
|
602
|
-
}
|
|
603
|
-
element.reset();
|
|
604
|
-
manualErrors = {};
|
|
605
|
-
validationErrors = {};
|
|
606
|
-
clearAttributes(element, [attributes.error, attributes.filled]);
|
|
607
|
-
if (isValidated) {
|
|
608
|
-
syncVisualState();
|
|
609
|
-
}
|
|
610
|
-
notifySubscribers();
|
|
611
|
-
return api;
|
|
612
|
-
},
|
|
613
|
-
autoSubmit(nextOptions = true) {
|
|
614
|
-
autoSubmitEnabled = nextOptions !== false;
|
|
615
|
-
autoSubmitDebounce = typeof nextOptions === "object" && nextOptions ? nextOptions.debounce ?? 0 : 0;
|
|
616
|
-
notifySubscribers();
|
|
617
|
-
return api;
|
|
942
|
+
get options() {
|
|
943
|
+
return state2.options;
|
|
618
944
|
},
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
},
|
|
642
|
-
getData() {
|
|
643
|
-
if (!element) {
|
|
644
|
-
return { data: {}, formData: new FormData() };
|
|
645
|
-
}
|
|
646
|
-
return parseFormData(element);
|
|
647
|
-
},
|
|
648
|
-
getState() {
|
|
649
|
-
const values = getValues();
|
|
650
|
-
const errors = cloneErrors(getMergedErrors());
|
|
651
|
-
const filledFields = getTrackedFieldNames().filter((name) => {
|
|
652
|
-
const value = values[name];
|
|
653
|
-
return Array.isArray(value) ? value.length > 0 : typeof value === "string" ? value.trim().length > 0 : value !== void 0;
|
|
654
|
-
});
|
|
655
|
-
return {
|
|
656
|
-
...createEmptyFormState(),
|
|
657
|
-
values,
|
|
658
|
-
errors,
|
|
659
|
-
filledFields,
|
|
660
|
-
isValid: Object.keys(errors).length === 0,
|
|
661
|
-
isValidated,
|
|
662
|
-
autoSubmit: autoSubmitEnabled,
|
|
663
|
-
submitCount
|
|
664
|
-
};
|
|
665
|
-
},
|
|
666
|
-
destroy() {
|
|
667
|
-
if (isDestroyed) {
|
|
668
|
-
return;
|
|
669
|
-
}
|
|
670
|
-
isDestroyed = true;
|
|
671
|
-
for (const listener of listeners) {
|
|
672
|
-
listener.element.removeEventListener(listener.type, listener.handler);
|
|
673
|
-
}
|
|
674
|
-
listeners.length = 0;
|
|
675
|
-
if (autoSubmitTimer) {
|
|
676
|
-
clearTimeout(autoSubmitTimer);
|
|
677
|
-
autoSubmitTimer = null;
|
|
678
|
-
}
|
|
679
|
-
mutationObserver?.disconnect();
|
|
680
|
-
mutationObserver = null;
|
|
681
|
-
watchedFields.clear();
|
|
682
|
-
subscribers.clear();
|
|
683
|
-
submitHandlers.clear();
|
|
684
|
-
clearFieldCache();
|
|
685
|
-
manualErrors = {};
|
|
686
|
-
validationErrors = {};
|
|
687
|
-
}
|
|
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)
|
|
688
967
|
};
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
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);
|
|
693
973
|
startMutationObserver();
|
|
694
974
|
}
|
|
695
975
|
if (normalizedOptions.autoSubmit) {
|
|
696
|
-
|
|
697
|
-
|
|
976
|
+
api.autoSubmit(normalizedOptions.autoSubmit);
|
|
977
|
+
}
|
|
978
|
+
if (normalizedOptions.formats) {
|
|
979
|
+
for (const config of Object.values(normalizedOptions.formats)) {
|
|
980
|
+
api.format(config);
|
|
981
|
+
}
|
|
698
982
|
}
|
|
699
|
-
if (isValidated) {
|
|
983
|
+
if (state2.isValidated) {
|
|
700
984
|
syncVisualState();
|
|
701
985
|
validateNames();
|
|
702
986
|
}
|
|
703
987
|
return api;
|
|
704
988
|
};
|
|
705
989
|
|
|
706
|
-
// src/
|
|
707
|
-
var form = (target, options) => createFormController(target, options);
|
|
990
|
+
// src/api/form.ts
|
|
991
|
+
var form = (target, options = {}) => createFormController(target, options);
|
|
708
992
|
|
|
709
993
|
// src/browser/global.ts
|
|
710
|
-
var
|
|
711
|
-
|
|
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 = {
|
|
712
1019
|
form,
|
|
713
|
-
|
|
714
|
-
|
|
1020
|
+
newForm,
|
|
1021
|
+
destroyForm,
|
|
1022
|
+
available
|
|
715
1023
|
};
|
|
716
1024
|
if (typeof globalThis !== "undefined") {
|
|
717
1025
|
;
|
|
718
|
-
globalThis.
|
|
1026
|
+
globalThis.Forms = Forms;
|
|
719
1027
|
}
|
|
720
|
-
var global_default =
|
|
1028
|
+
var global_default = Forms;
|
|
721
1029
|
return __toCommonJS(global_exports);
|
|
722
1030
|
})();
|
|
723
1031
|
//# sourceMappingURL=global.global.js.map
|