elements-kit 0.19.0 → 0.20.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 +14 -0
- package/dist/await.d.mts +53 -0
- package/dist/await.mjs +70 -0
- package/dist/custom-elements.d.mts +1 -1
- package/dist/{element-xQwq4ulc.mjs → element-D3om9yA6.mjs} +71 -4
- package/dist/for.d.mts +20 -26
- package/dist/for.mjs +29 -4
- package/dist/fragment-ROPRBJQd.mjs +61 -0
- package/dist/hydrate/index.d.mts +41 -0
- package/dist/hydrate/index.mjs +2 -0
- package/dist/hydrate-6Qx4n4Su.mjs +380 -0
- package/dist/integrations/astro-client.d.mts +17 -0
- package/dist/integrations/astro-client.mjs +23 -0
- package/dist/integrations/astro-server.d.mts +15 -0
- package/dist/integrations/astro-server.mjs +39 -0
- package/dist/integrations/astro-slots.d.mts +12 -0
- package/dist/integrations/astro-slots.mjs +30 -0
- package/dist/integrations/astro.d.mts +46 -0
- package/dist/integrations/astro.mjs +64 -0
- package/dist/integrations/react.d.mts +1 -1
- package/dist/integrations/react.mjs +2 -2
- package/dist/jsx-runtime/index.d.mts +1 -1
- package/dist/jsx-runtime/index.mjs +2 -20
- package/dist/{lib-Dkc7cV5F.mjs → lib-DYypKhxk.mjs} +63 -5
- package/dist/render.mjs +1 -1
- package/dist/{scope-CnEvL9Nd.mjs → scope-zbEG299F.mjs} +1 -1
- package/dist/server/index.d.mts +43 -0
- package/dist/server/index.mjs +2 -0
- package/dist/server-iFSng50i.mjs +385 -0
- package/dist/signals/index.d.mts +2 -2
- package/dist/signals/index.mjs +5 -3
- package/dist/{slot-B8y0aEoz.d.mts → slot-BFWXeFRl.d.mts} +6 -0
- package/dist/{slot-Cne__au7.mjs → slot-Dvf30O0B.mjs} +12 -1
- package/dist/slot.d.mts +1 -1
- package/dist/slot.mjs +1 -1
- package/dist/{infer-B7T5hi_D.d.mts → types-ncUK9rki.d.mts} +140 -141
- package/dist/ui/overlay/index.mjs +1 -1
- package/dist/utilities/_observe.mjs +1 -1
- package/dist/utilities/active-element.d.mts +1 -1
- package/dist/utilities/active-element.mjs +1 -1
- package/dist/utilities/async.d.mts +19 -2
- package/dist/utilities/async.mjs +49 -2
- package/dist/utilities/context.mjs +1 -1
- package/dist/utilities/debounced.d.mts +1 -1
- package/dist/utilities/debounced.mjs +1 -1
- package/dist/utilities/dom-lifecycle.bench.mjs +3255 -1
- package/dist/utilities/dom-lifecycle.mjs +1 -1
- package/dist/utilities/element-rect.d.mts +1 -1
- package/dist/utilities/element-rect.mjs +1 -1
- package/dist/utilities/element-scroll.d.mts +1 -1
- package/dist/utilities/event-driven.d.mts +1 -1
- package/dist/utilities/event-driven.mjs +1 -1
- package/dist/utilities/event-listener.d.mts +1 -1
- package/dist/utilities/event-listener.mjs +1 -1
- package/dist/utilities/focus-within.d.mts +1 -1
- package/dist/utilities/focus-within.mjs +1 -1
- package/dist/utilities/hover.d.mts +1 -1
- package/dist/utilities/hover.mjs +1 -1
- package/dist/utilities/interval.d.mts +1 -1
- package/dist/utilities/interval.mjs +1 -1
- package/dist/utilities/location.d.mts +1 -1
- package/dist/utilities/location.mjs +1 -1
- package/dist/utilities/media-devices.d.mts +1 -1
- package/dist/utilities/media-devices.mjs +1 -1
- package/dist/utilities/media-player.d.mts +1 -1
- package/dist/utilities/media-query.d.mts +1 -1
- package/dist/utilities/media-query.mjs +1 -1
- package/dist/utilities/network.d.mts +1 -1
- package/dist/utilities/network.mjs +1 -1
- package/dist/utilities/orientation.d.mts +1 -1
- package/dist/utilities/orientation.mjs +1 -1
- package/dist/utilities/previous.d.mts +1 -1
- package/dist/utilities/previous.mjs +1 -1
- package/dist/utilities/promise.d.mts +19 -2
- package/dist/utilities/promise.mjs +33 -3
- package/dist/utilities/retry.mjs +1 -1
- package/dist/utilities/routing.d.mts +1 -1
- package/dist/utilities/routing.mjs +1 -1
- package/dist/utilities/search-params.d.mts +1 -1
- package/dist/utilities/storage.d.mts +1 -1
- package/dist/utilities/throttled.d.mts +1 -1
- package/dist/utilities/throttled.mjs +1 -1
- package/dist/utilities/timeout.d.mts +1 -1
- package/dist/utilities/timeout.mjs +1 -1
- package/dist/utilities/window-focus.d.mts +1 -1
- package/dist/utilities/window-focus.mjs +1 -1
- package/dist/utilities/window-size.d.mts +1 -1
- package/dist/utilities/window-size.mjs +1 -1
- package/package.json +16 -1
- package/dist/benchmark.CX_oY03V-CSLAXL5f.mjs +0 -5145
- package/dist/magic-string.es-CXefOmkB.mjs +0 -1011
- package/dist/test.BmQO5GaM-Ddz9cDxc.mjs +0 -8266
- package/dist/utilities/active-element.test.d.mts +0 -1
- package/dist/utilities/active-element.test.mjs +0 -25
- package/dist/utilities/async.test.d.mts +0 -1
- package/dist/utilities/async.test.mjs +0 -275
- package/dist/utilities/context.test.d.mts +0 -1
- package/dist/utilities/context.test.mjs +0 -171
- package/dist/utilities/debounced.test.d.mts +0 -1
- package/dist/utilities/debounced.test.mjs +0 -68
- package/dist/utilities/dom-lifecycle.test.d.mts +0 -1
- package/dist/utilities/dom-lifecycle.test.mjs +0 -228
- package/dist/utilities/element-rect.test.d.mts +0 -1
- package/dist/utilities/element-rect.test.mjs +0 -101
- package/dist/utilities/element-scroll.test.d.mts +0 -1
- package/dist/utilities/element-scroll.test.mjs +0 -27
- package/dist/utilities/event-listener.test.d.mts +0 -1
- package/dist/utilities/event-listener.test.mjs +0 -60
- package/dist/utilities/focus-within.test.d.mts +0 -1
- package/dist/utilities/focus-within.test.mjs +0 -51
- package/dist/utilities/form-object.test.d.mts +0 -1
- package/dist/utilities/form-object.test.mjs +0 -408
- package/dist/utilities/hover.test.d.mts +0 -1
- package/dist/utilities/hover.test.mjs +0 -54
- package/dist/utilities/intersection-observer.test.d.mts +0 -1
- package/dist/utilities/intersection-observer.test.mjs +0 -46
- package/dist/utilities/interval.test.d.mts +0 -1
- package/dist/utilities/interval.test.mjs +0 -115
- package/dist/utilities/location.test.d.mts +0 -1
- package/dist/utilities/location.test.mjs +0 -61
- package/dist/utilities/long-press.test.d.mts +0 -1
- package/dist/utilities/long-press.test.mjs +0 -54
- package/dist/utilities/media-devices.test.d.mts +0 -1
- package/dist/utilities/media-devices.test.mjs +0 -44
- package/dist/utilities/media-player.test.d.mts +0 -1
- package/dist/utilities/media-player.test.mjs +0 -102
- package/dist/utilities/mutation-observer.test.d.mts +0 -1
- package/dist/utilities/mutation-observer.test.mjs +0 -48
- package/dist/utilities/network.test.d.mts +0 -1
- package/dist/utilities/network.test.mjs +0 -30
- package/dist/utilities/on-click-outside.test.d.mts +0 -1
- package/dist/utilities/on-click-outside.test.mjs +0 -45
- package/dist/utilities/previous.test.d.mts +0 -1
- package/dist/utilities/previous.test.mjs +0 -90
- package/dist/utilities/promise.test.d.mts +0 -1
- package/dist/utilities/promise.test.mjs +0 -158
- package/dist/utilities/retry.test.d.mts +0 -1
- package/dist/utilities/retry.test.mjs +0 -85
- package/dist/utilities/routing.test.d.mts +0 -1
- package/dist/utilities/routing.test.mjs +0 -129
- package/dist/utilities/search-params.test.d.mts +0 -1
- package/dist/utilities/search-params.test.mjs +0 -37
- package/dist/utilities/ssr.test.d.mts +0 -1
- package/dist/utilities/ssr.test.mjs +0 -65
- package/dist/utilities/storage.test.d.mts +0 -1
- package/dist/utilities/storage.test.mjs +0 -139
- package/dist/utilities/throttled.test.d.mts +0 -1
- package/dist/utilities/throttled.test.mjs +0 -58
- package/dist/utilities/timeout.test.d.mts +0 -1
- package/dist/utilities/timeout.test.mjs +0 -121
- package/dist/utilities/window-size.test.d.mts +0 -1
- package/dist/utilities/window-size.test.mjs +0 -43
- /package/dist/{custom-elements-D5CgfNKc.d.mts → custom-elements-DK5VUcWA.d.mts} +0 -0
|
@@ -1,408 +0,0 @@
|
|
|
1
|
-
import { f as it, l as describe, o as afterEach } from "../benchmark.CX_oY03V-CSLAXL5f.mjs";
|
|
2
|
-
import { t as globalExpect } from "../test.BmQO5GaM-Ddz9cDxc.mjs";
|
|
3
|
-
import { FormObject, defaultTransforms, dropUnchecked, skipButtons, skipEmpty, uncheckedAs } from "./form-object.mjs";
|
|
4
|
-
//#region src/utilities/form-object.test.ts
|
|
5
|
-
afterEach(() => {
|
|
6
|
-
document.body.innerHTML = "";
|
|
7
|
-
});
|
|
8
|
-
/** Build a form from an HTML string and attach it to the document. */
|
|
9
|
-
function makeForm(html) {
|
|
10
|
-
const form = document.createElement("form");
|
|
11
|
-
form.innerHTML = html;
|
|
12
|
-
document.body.appendChild(form);
|
|
13
|
-
return form;
|
|
14
|
-
}
|
|
15
|
-
describe("FormObject.toObject", () => {
|
|
16
|
-
it("reads flat fields into a flat object", () => {
|
|
17
|
-
globalExpect(new FormObject(makeForm(`
|
|
18
|
-
<input name="email" value="a@b.com" />
|
|
19
|
-
<input name="age" value="30" />
|
|
20
|
-
`)).toObject()).toEqual({
|
|
21
|
-
email: "a@b.com",
|
|
22
|
-
age: "30"
|
|
23
|
-
});
|
|
24
|
-
});
|
|
25
|
-
it("nests dot-notation names into nested objects", () => {
|
|
26
|
-
globalExpect(new FormObject(makeForm(`
|
|
27
|
-
<input name="user.name" value="Wael" />
|
|
28
|
-
<input name="user.address.city" value="Tunis" />
|
|
29
|
-
`)).toObject()).toEqual({ user: {
|
|
30
|
-
name: "Wael",
|
|
31
|
-
address: { city: "Tunis" }
|
|
32
|
-
} });
|
|
33
|
-
});
|
|
34
|
-
it("builds arrays from numeric segments", () => {
|
|
35
|
-
globalExpect(new FormObject(makeForm(`
|
|
36
|
-
<input name="tags.0" value="a" />
|
|
37
|
-
<input name="tags.1" value="b" />
|
|
38
|
-
`)).toObject()).toEqual({ tags: ["a", "b"] });
|
|
39
|
-
});
|
|
40
|
-
it("builds arrays of objects from mixed numeric + key segments", () => {
|
|
41
|
-
globalExpect(new FormObject(makeForm(`
|
|
42
|
-
<input name="items.0.id" value="1" />
|
|
43
|
-
<input name="items.1.id" value="2" />
|
|
44
|
-
`)).toObject()).toEqual({ items: [{ id: "1" }, { id: "2" }] });
|
|
45
|
-
});
|
|
46
|
-
it("reads textarea values", () => {
|
|
47
|
-
globalExpect(new FormObject(makeForm(`<textarea name="bio">hello</textarea>`)).toObject()).toEqual({ bio: "hello" });
|
|
48
|
-
});
|
|
49
|
-
it("uses a checked checkbox's value, defaulting to 'on'", () => {
|
|
50
|
-
globalExpect(new FormObject(makeForm(`<input type="checkbox" name="agree" checked />`)).toObject()).toEqual({ agree: "on" });
|
|
51
|
-
});
|
|
52
|
-
it("omits an unchecked checkbox by default", () => {
|
|
53
|
-
globalExpect(new FormObject(makeForm(`<input type="checkbox" name="agree" />`)).toObject()).toEqual({});
|
|
54
|
-
});
|
|
55
|
-
it("includes an unchecked checkbox as false via uncheckedAs", () => {
|
|
56
|
-
globalExpect(new FormObject(makeForm(`<input type="checkbox" name="agree" />`), { transforms: [skipButtons, uncheckedAs(false)] }).toObject()).toEqual({ agree: false });
|
|
57
|
-
});
|
|
58
|
-
it("collects a `[]` checkbox group into an array of checked values", () => {
|
|
59
|
-
globalExpect(new FormObject(makeForm(`
|
|
60
|
-
<input type="checkbox" name="colors[]" value="red" checked />
|
|
61
|
-
<input type="checkbox" name="colors[]" value="green" />
|
|
62
|
-
<input type="checkbox" name="colors[]" value="blue" checked />
|
|
63
|
-
`)).toObject()).toEqual({ colors: ["red", "blue"] });
|
|
64
|
-
});
|
|
65
|
-
it("reads the selected radio value", () => {
|
|
66
|
-
globalExpect(new FormObject(makeForm(`
|
|
67
|
-
<input type="radio" name="plan" value="free" />
|
|
68
|
-
<input type="radio" name="plan" value="pro" checked />
|
|
69
|
-
`)).toObject()).toEqual({ plan: "pro" });
|
|
70
|
-
});
|
|
71
|
-
it("reads a single select value", () => {
|
|
72
|
-
globalExpect(new FormObject(makeForm(`
|
|
73
|
-
<select name="country">
|
|
74
|
-
<option value="tn">Tunisia</option>
|
|
75
|
-
<option value="fr" selected>France</option>
|
|
76
|
-
</select>
|
|
77
|
-
`)).toObject()).toEqual({ country: "fr" });
|
|
78
|
-
});
|
|
79
|
-
it("reads a multiple select as an array", () => {
|
|
80
|
-
globalExpect(new FormObject(makeForm(`
|
|
81
|
-
<select name="langs" multiple>
|
|
82
|
-
<option value="js" selected>JS</option>
|
|
83
|
-
<option value="ts" selected>TS</option>
|
|
84
|
-
<option value="go">Go</option>
|
|
85
|
-
</select>
|
|
86
|
-
`)).toObject()).toEqual({ langs: ["js", "ts"] });
|
|
87
|
-
});
|
|
88
|
-
it("skips disabled controls by default", () => {
|
|
89
|
-
globalExpect(new FormObject(makeForm(`
|
|
90
|
-
<input name="a" value="1" />
|
|
91
|
-
<input name="b" value="2" disabled />
|
|
92
|
-
`)).toObject()).toEqual({ a: "1" });
|
|
93
|
-
});
|
|
94
|
-
it("includes disabled controls when skipDisabled is omitted", () => {
|
|
95
|
-
globalExpect(new FormObject(makeForm(`
|
|
96
|
-
<input name="a" value="1" />
|
|
97
|
-
<input name="b" value="2" disabled />
|
|
98
|
-
`), { transforms: [skipButtons, dropUnchecked] }).toObject()).toEqual({
|
|
99
|
-
a: "1",
|
|
100
|
-
b: "2"
|
|
101
|
-
});
|
|
102
|
-
});
|
|
103
|
-
it("skips unnamed controls", () => {
|
|
104
|
-
globalExpect(new FormObject(makeForm(`
|
|
105
|
-
<input value="ignored" />
|
|
106
|
-
<input name="kept" value="ok" />
|
|
107
|
-
`)).toObject()).toEqual({ kept: "ok" });
|
|
108
|
-
});
|
|
109
|
-
it("yields File objects for file inputs", () => {
|
|
110
|
-
const form = makeForm(`<input type="file" name="doc" />`);
|
|
111
|
-
const input = form.elements.namedItem("doc");
|
|
112
|
-
const file = new File(["data"], "report.txt", { type: "text/plain" });
|
|
113
|
-
const dt = new DataTransfer();
|
|
114
|
-
dt.items.add(file);
|
|
115
|
-
input.files = dt.files;
|
|
116
|
-
const result = new FormObject(form).toObject();
|
|
117
|
-
globalExpect(result.doc).toBeInstanceOf(File);
|
|
118
|
-
globalExpect(result.doc.name).toBe("report.txt");
|
|
119
|
-
});
|
|
120
|
-
});
|
|
121
|
-
describe("FormObject same-name controls (bare name → last value wins)", () => {
|
|
122
|
-
it("keeps the last value when repeated text inputs share a bare name", () => {
|
|
123
|
-
globalExpect(new FormObject(makeForm(`
|
|
124
|
-
<input name="x" value="a" />
|
|
125
|
-
<input name="x" value="b" />
|
|
126
|
-
`)).toObject()).toEqual({ x: "b" });
|
|
127
|
-
});
|
|
128
|
-
it("keeps the last value across mixed control kinds with a bare name", () => {
|
|
129
|
-
globalExpect(new FormObject(makeForm(`
|
|
130
|
-
<input name="y" value="a" />
|
|
131
|
-
<select name="y"><option value="b" selected>b</option></select>
|
|
132
|
-
`)).toObject()).toEqual({ y: "b" });
|
|
133
|
-
});
|
|
134
|
-
it("keeps the last checked value for a bare checkbox group", () => {
|
|
135
|
-
globalExpect(new FormObject(makeForm(`
|
|
136
|
-
<input type="checkbox" name="c" value="r" checked />
|
|
137
|
-
<input type="checkbox" name="c" value="g" checked />
|
|
138
|
-
`)).toObject()).toEqual({ c: "g" });
|
|
139
|
-
});
|
|
140
|
-
it("lets a checked checkbox override a preceding hidden fallback (idiom)", () => {
|
|
141
|
-
globalExpect(new FormObject(makeForm(`
|
|
142
|
-
<input type="hidden" name="agree" value="0" />
|
|
143
|
-
<input type="checkbox" name="agree" value="1" checked />
|
|
144
|
-
`)).toObject()).toEqual({ agree: "1" });
|
|
145
|
-
});
|
|
146
|
-
it("keeps the hidden fallback when the checkbox is unchecked", () => {
|
|
147
|
-
globalExpect(new FormObject(makeForm(`
|
|
148
|
-
<input type="hidden" name="agree" value="0" />
|
|
149
|
-
<input type="checkbox" name="agree" value="1" />
|
|
150
|
-
`)).toObject()).toEqual({ agree: "0" });
|
|
151
|
-
});
|
|
152
|
-
it("keeps a pure radio group as a scalar", () => {
|
|
153
|
-
globalExpect(new FormObject(makeForm(`
|
|
154
|
-
<input type="radio" name="r" value="a" />
|
|
155
|
-
<input type="radio" name="r" value="b" checked />
|
|
156
|
-
`)).toObject()).toEqual({ r: "b" });
|
|
157
|
-
});
|
|
158
|
-
});
|
|
159
|
-
describe("FormObject `[]` array fields", () => {
|
|
160
|
-
it("wraps a single `[]` control in an array", () => {
|
|
161
|
-
globalExpect(new FormObject(makeForm(`<input type="checkbox" name="c[]" value="x" checked />`)).toObject()).toEqual({ c: ["x"] });
|
|
162
|
-
});
|
|
163
|
-
it("appends every surviving `[]` control in document order", () => {
|
|
164
|
-
globalExpect(new FormObject(makeForm(`
|
|
165
|
-
<input type="checkbox" name="c[]" value="x" checked />
|
|
166
|
-
<input type="checkbox" name="c[]" value="y" checked />
|
|
167
|
-
`)).toObject()).toEqual({ c: ["x", "y"] });
|
|
168
|
-
});
|
|
169
|
-
it("yields an empty array for a declared-but-empty `[]` field", () => {
|
|
170
|
-
globalExpect(new FormObject(makeForm(`<input type="checkbox" name="c[]" value="x" />`)).toObject()).toEqual({ c: [] });
|
|
171
|
-
});
|
|
172
|
-
it("nests a `[]` array under a dot-path", () => {
|
|
173
|
-
globalExpect(new FormObject(makeForm(`
|
|
174
|
-
<input name="user.tags[]" value="a" />
|
|
175
|
-
<input name="user.tags[]" value="b" />
|
|
176
|
-
`)).toObject()).toEqual({ user: { tags: ["a", "b"] } });
|
|
177
|
-
});
|
|
178
|
-
it("hidden + `[]` checkbox: array with both when checked, hidden-only when unchecked", () => {
|
|
179
|
-
const checked = makeForm(`
|
|
180
|
-
<input type="hidden" name="a[]" value="0" />
|
|
181
|
-
<input type="checkbox" name="a[]" value="1" checked />
|
|
182
|
-
`);
|
|
183
|
-
const unchecked = makeForm(`
|
|
184
|
-
<input type="hidden" name="a[]" value="0" />
|
|
185
|
-
<input type="checkbox" name="a[]" value="1" />
|
|
186
|
-
`);
|
|
187
|
-
globalExpect(new FormObject(checked).toObject()).toEqual({ a: ["0", "1"] });
|
|
188
|
-
globalExpect(new FormObject(unchecked).toObject()).toEqual({ a: ["0"] });
|
|
189
|
-
});
|
|
190
|
-
it("builds an array of objects via explicit indices", () => {
|
|
191
|
-
globalExpect(new FormObject(makeForm(`
|
|
192
|
-
<input name="items.0.id" value="1" />
|
|
193
|
-
<input name="items.1.id" value="2" />
|
|
194
|
-
`)).toObject()).toEqual({ items: [{ id: "1" }, { id: "2" }] });
|
|
195
|
-
});
|
|
196
|
-
});
|
|
197
|
-
describe("FormObject disabled controls", () => {
|
|
198
|
-
it("skips a disabled checked checkbox under the default pipeline", () => {
|
|
199
|
-
globalExpect(new FormObject(makeForm(`<input type="checkbox" name="a" value="1" checked disabled />`)).toObject()).toEqual({});
|
|
200
|
-
});
|
|
201
|
-
it("includes a disabled checked checkbox when skipDisabled is omitted", () => {
|
|
202
|
-
globalExpect(new FormObject(makeForm(`<input type="checkbox" name="a" value="1" checked disabled />`), { transforms: [skipButtons, dropUnchecked] }).toObject()).toEqual({ a: "1" });
|
|
203
|
-
});
|
|
204
|
-
it("still drops a disabled UNCHECKED checkbox via dropUnchecked even without skipDisabled", () => {
|
|
205
|
-
globalExpect(new FormObject(makeForm(`<input type="checkbox" name="a" value="1" disabled />`), { transforms: [skipButtons, dropUnchecked] }).toObject()).toEqual({});
|
|
206
|
-
});
|
|
207
|
-
it("appends an included disabled member to a `[]` array", () => {
|
|
208
|
-
globalExpect(new FormObject(makeForm(`
|
|
209
|
-
<input type="checkbox" name="g[]" value="1" checked />
|
|
210
|
-
<input type="checkbox" name="g[]" value="2" checked disabled />
|
|
211
|
-
`), { transforms: [skipButtons, dropUnchecked] }).toObject()).toEqual({ g: ["1", "2"] });
|
|
212
|
-
});
|
|
213
|
-
it("drops a disabled `[]` member under the default pipeline, keeping the array", () => {
|
|
214
|
-
globalExpect(new FormObject(makeForm(`
|
|
215
|
-
<input type="checkbox" name="g[]" value="1" checked />
|
|
216
|
-
<input type="checkbox" name="g[]" value="2" checked disabled />
|
|
217
|
-
`)).toObject()).toEqual({ g: ["1"] });
|
|
218
|
-
});
|
|
219
|
-
it("a disabled bare checkbox leaves only the hidden value under the default pipeline", () => {
|
|
220
|
-
globalExpect(new FormObject(makeForm(`
|
|
221
|
-
<input type="hidden" name="a" value="0" />
|
|
222
|
-
<input type="checkbox" name="a" value="1" checked disabled />
|
|
223
|
-
`)).toObject()).toEqual({ a: "0" });
|
|
224
|
-
});
|
|
225
|
-
it("an included disabled checkbox overrides the hidden value (bare, last wins)", () => {
|
|
226
|
-
globalExpect(new FormObject(makeForm(`
|
|
227
|
-
<input type="hidden" name="a" value="0" />
|
|
228
|
-
<input type="checkbox" name="a" value="1" checked disabled />
|
|
229
|
-
`), { transforms: [skipButtons, dropUnchecked] }).toObject()).toEqual({ a: "1" });
|
|
230
|
-
});
|
|
231
|
-
it("does not write disabled controls in fromObject", () => {
|
|
232
|
-
const form = makeForm(`<input name="a" value="orig" disabled />`);
|
|
233
|
-
new FormObject(form).fromObject({ a: "changed" });
|
|
234
|
-
globalExpect(form.elements.namedItem("a").value).toBe("orig");
|
|
235
|
-
});
|
|
236
|
-
});
|
|
237
|
-
describe("FormObject path edge cases", () => {
|
|
238
|
-
it("does not pollute Object.prototype via __proto__ segments", () => {
|
|
239
|
-
globalExpect(new FormObject(makeForm(`<input name="__proto__.polluted" value="yes" />`)).toObject()).toEqual({});
|
|
240
|
-
globalExpect({}.polluted).toBeUndefined();
|
|
241
|
-
});
|
|
242
|
-
it("ignores constructor / prototype segments", () => {
|
|
243
|
-
globalExpect(new FormObject(makeForm(`
|
|
244
|
-
<input name="constructor.prototype.x" value="bad" />
|
|
245
|
-
<input name="a.prototype.b" value="bad" />
|
|
246
|
-
`)).toObject()).toEqual({});
|
|
247
|
-
});
|
|
248
|
-
it("leaves gaps in sparse array indices as holes", () => {
|
|
249
|
-
globalExpect(new FormObject(makeForm(`
|
|
250
|
-
<input name="t.0" value="a" />
|
|
251
|
-
<input name="t.2" value="c" />
|
|
252
|
-
`)).toObject()).toEqual({ t: [
|
|
253
|
-
"a",
|
|
254
|
-
void 0,
|
|
255
|
-
"c"
|
|
256
|
-
] });
|
|
257
|
-
});
|
|
258
|
-
it("builds deeply nested arrays of objects", () => {
|
|
259
|
-
globalExpect(new FormObject(makeForm(`
|
|
260
|
-
<input name="a.0.b.0.c" value="1" />
|
|
261
|
-
<input name="a.0.b.1.c" value="2" />
|
|
262
|
-
`)).toObject()).toEqual({ a: [{ b: [{ c: "1" }, { c: "2" }] }] });
|
|
263
|
-
});
|
|
264
|
-
it("treats numeric top-level names as object keys, not an array", () => {
|
|
265
|
-
globalExpect(new FormObject(makeForm(`
|
|
266
|
-
<input name="0" value="a" />
|
|
267
|
-
<input name="1" value="b" />
|
|
268
|
-
`)).toObject()).toEqual({
|
|
269
|
-
"0": "a",
|
|
270
|
-
"1": "b"
|
|
271
|
-
});
|
|
272
|
-
});
|
|
273
|
-
});
|
|
274
|
-
describe("FormObject transforms", () => {
|
|
275
|
-
it("skips named buttons by default", () => {
|
|
276
|
-
globalExpect(new FormObject(makeForm(`
|
|
277
|
-
<input name="email" value="a@b.com" />
|
|
278
|
-
<button name="action" value="save">Save</button>
|
|
279
|
-
<input type="submit" name="submit" value="go" />
|
|
280
|
-
`)).toObject()).toEqual({ email: "a@b.com" });
|
|
281
|
-
});
|
|
282
|
-
it("drops unchecked checkboxes and radios by default", () => {
|
|
283
|
-
globalExpect(new FormObject(makeForm(`
|
|
284
|
-
<input type="checkbox" name="agree" />
|
|
285
|
-
<input type="radio" name="plan" value="free" />
|
|
286
|
-
<input type="radio" name="plan" value="pro" />
|
|
287
|
-
`)).toObject()).toEqual({});
|
|
288
|
-
});
|
|
289
|
-
it("uncheckedAs(false) includes unchecked checkbox but still drops unchecked radio", () => {
|
|
290
|
-
globalExpect(new FormObject(makeForm(`
|
|
291
|
-
<input type="checkbox" name="agree" />
|
|
292
|
-
<input type="radio" name="plan" value="free" />
|
|
293
|
-
<input type="radio" name="plan" value="pro" />
|
|
294
|
-
`), { transforms: [skipButtons, uncheckedAs(false)] }).toObject()).toEqual({ agree: false });
|
|
295
|
-
});
|
|
296
|
-
it("skipEmpty drops empty-string fields", () => {
|
|
297
|
-
globalExpect(new FormObject(makeForm(`
|
|
298
|
-
<input name="filled" value="x" />
|
|
299
|
-
<input name="blank" value="" />
|
|
300
|
-
`), { transforms: [...defaultTransforms, skipEmpty] }).toObject()).toEqual({ filled: "x" });
|
|
301
|
-
});
|
|
302
|
-
it("runs a custom transform that rewrites the value", () => {
|
|
303
|
-
const form = makeForm(`<input name="name" value=" Wael " />`);
|
|
304
|
-
const trim = (f) => ({
|
|
305
|
-
...f,
|
|
306
|
-
value: typeof f.value === "string" ? f.value.trim() : f.value
|
|
307
|
-
});
|
|
308
|
-
globalExpect(new FormObject(form, { transforms: [...defaultTransforms, trim] }).toObject()).toEqual({ name: "Wael" });
|
|
309
|
-
});
|
|
310
|
-
it("runs a custom transform that renames the field path", () => {
|
|
311
|
-
const form = makeForm(`<input name="legacy" value="v" />`);
|
|
312
|
-
const rename = (f) => f.name === "legacy" ? {
|
|
313
|
-
...f,
|
|
314
|
-
name: "modern"
|
|
315
|
-
} : f;
|
|
316
|
-
globalExpect(new FormObject(form, { transforms: [...defaultTransforms, rename] }).toObject()).toEqual({ modern: "v" });
|
|
317
|
-
});
|
|
318
|
-
it("with an empty pipeline emits everything (disabled, buttons, unchecked)", () => {
|
|
319
|
-
globalExpect(new FormObject(makeForm(`
|
|
320
|
-
<input name="a" value="1" disabled />
|
|
321
|
-
<button name="b" value="x">x</button>
|
|
322
|
-
<input type="checkbox" name="c" value="on" />
|
|
323
|
-
`), { transforms: [] }).toObject()).toEqual({
|
|
324
|
-
a: "1",
|
|
325
|
-
b: "x",
|
|
326
|
-
c: "on"
|
|
327
|
-
});
|
|
328
|
-
});
|
|
329
|
-
});
|
|
330
|
-
describe("FormObject.fromObject", () => {
|
|
331
|
-
it("writes nested values back onto controls", () => {
|
|
332
|
-
const form = makeForm(`
|
|
333
|
-
<input name="user.name" />
|
|
334
|
-
<input name="user.address.city" />
|
|
335
|
-
`);
|
|
336
|
-
new FormObject(form).fromObject({ user: {
|
|
337
|
-
name: "Wael",
|
|
338
|
-
address: { city: "Tunis" }
|
|
339
|
-
} });
|
|
340
|
-
globalExpect(form.elements.namedItem("user.name").value).toBe("Wael");
|
|
341
|
-
globalExpect(form.elements.namedItem("user.address.city").value).toBe("Tunis");
|
|
342
|
-
});
|
|
343
|
-
it("writes array values back into numeric-segment controls", () => {
|
|
344
|
-
const form = makeForm(`
|
|
345
|
-
<input name="tags.0" />
|
|
346
|
-
<input name="tags.1" />
|
|
347
|
-
`);
|
|
348
|
-
new FormObject(form).fromObject({ tags: ["a", "b"] });
|
|
349
|
-
globalExpect(form.elements.namedItem("tags.0").value).toBe("a");
|
|
350
|
-
globalExpect(form.elements.namedItem("tags.1").value).toBe("b");
|
|
351
|
-
});
|
|
352
|
-
it("round-trips a `[]` checkbox group through fromObject", () => {
|
|
353
|
-
const form = makeForm(`
|
|
354
|
-
<input type="checkbox" name="colors[]" value="red" />
|
|
355
|
-
<input type="checkbox" name="colors[]" value="green" />
|
|
356
|
-
<input type="checkbox" name="colors[]" value="blue" />
|
|
357
|
-
`);
|
|
358
|
-
new FormObject(form).fromObject({ colors: ["red", "blue"] });
|
|
359
|
-
globalExpect(new FormObject(form).toObject()).toEqual({ colors: ["red", "blue"] });
|
|
360
|
-
});
|
|
361
|
-
it("sets checkbox checked state from a boolean-ish value", () => {
|
|
362
|
-
const form = makeForm(`<input type="checkbox" name="agree" value="yes" />`);
|
|
363
|
-
new FormObject(form).fromObject({ agree: "yes" });
|
|
364
|
-
globalExpect(form.elements.namedItem("agree").checked).toBe(true);
|
|
365
|
-
});
|
|
366
|
-
it("selects the matching radio", () => {
|
|
367
|
-
const form = makeForm(`
|
|
368
|
-
<input type="radio" name="plan" value="free" />
|
|
369
|
-
<input type="radio" name="plan" value="pro" />
|
|
370
|
-
`);
|
|
371
|
-
new FormObject(form).fromObject({ plan: "pro" });
|
|
372
|
-
globalExpect(form.querySelector("input[name=plan]:checked")?.value).toBe("pro");
|
|
373
|
-
});
|
|
374
|
-
it("leaves controls untouched when the path is missing", () => {
|
|
375
|
-
const form = makeForm(`<input name="keep" value="original" />`);
|
|
376
|
-
new FormObject(form).fromObject({ other: "x" });
|
|
377
|
-
globalExpect(form.elements.namedItem("keep").value).toBe("original");
|
|
378
|
-
});
|
|
379
|
-
it("round-trips a form through toObject -> fromObject -> toObject", () => {
|
|
380
|
-
const html = `
|
|
381
|
-
<input name="user.name" value="Wael" />
|
|
382
|
-
<input name="tags.0" value="a" />
|
|
383
|
-
<input name="tags.1" value="b" />
|
|
384
|
-
<input type="checkbox" name="agree" checked />
|
|
385
|
-
<select name="country">
|
|
386
|
-
<option value="tn">Tunisia</option>
|
|
387
|
-
<option value="fr" selected>France</option>
|
|
388
|
-
</select>
|
|
389
|
-
`;
|
|
390
|
-
const source = new FormObject(makeForm(html)).toObject();
|
|
391
|
-
const target = makeForm(html);
|
|
392
|
-
new FormObject(target).clear();
|
|
393
|
-
globalExpect(new FormObject(target).fromObject(source).toObject()).toEqual(source);
|
|
394
|
-
});
|
|
395
|
-
it("returns this for chaining", () => {
|
|
396
|
-
const data = new FormObject(makeForm(`<input name="a" />`));
|
|
397
|
-
globalExpect(data.fromObject({ a: "1" })).toBe(data);
|
|
398
|
-
globalExpect(data.clear()).toBe(data);
|
|
399
|
-
});
|
|
400
|
-
});
|
|
401
|
-
describe("FormObject serialization", () => {
|
|
402
|
-
it("supports JSON.stringify via toJSON", () => {
|
|
403
|
-
const form = makeForm(`<input name="user.name" value="Wael" />`);
|
|
404
|
-
globalExpect(JSON.stringify(new FormObject(form))).toBe(JSON.stringify({ user: { name: "Wael" } }));
|
|
405
|
-
});
|
|
406
|
-
});
|
|
407
|
-
//#endregion
|
|
408
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { };
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { c as effectScope } from "../lib-Dkc7cV5F.mjs";
|
|
2
|
-
import "../signals/index.mjs";
|
|
3
|
-
import { f as it, l as describe, o as afterEach } from "../benchmark.CX_oY03V-CSLAXL5f.mjs";
|
|
4
|
-
import { n as vi, t as globalExpect } from "../test.BmQO5GaM-Ddz9cDxc.mjs";
|
|
5
|
-
import { createHover } from "./hover.mjs";
|
|
6
|
-
//#region src/utilities/hover.test.ts
|
|
7
|
-
afterEach(() => {
|
|
8
|
-
document.body.innerHTML = "";
|
|
9
|
-
vi.restoreAllMocks();
|
|
10
|
-
});
|
|
11
|
-
describe("createHover", () => {
|
|
12
|
-
it("starts as false", () => {
|
|
13
|
-
const el = document.createElement("div");
|
|
14
|
-
document.body.appendChild(el);
|
|
15
|
-
let hovered;
|
|
16
|
-
effectScope(() => {
|
|
17
|
-
hovered = createHover(el);
|
|
18
|
-
});
|
|
19
|
-
globalExpect(hovered()).toBe(false);
|
|
20
|
-
});
|
|
21
|
-
it("becomes true on pointerenter", () => {
|
|
22
|
-
const el = document.createElement("div");
|
|
23
|
-
document.body.appendChild(el);
|
|
24
|
-
let hovered;
|
|
25
|
-
effectScope(() => {
|
|
26
|
-
hovered = createHover(el);
|
|
27
|
-
});
|
|
28
|
-
el.dispatchEvent(new PointerEvent("pointerenter"));
|
|
29
|
-
globalExpect(hovered()).toBe(true);
|
|
30
|
-
});
|
|
31
|
-
it("becomes false on pointerleave", () => {
|
|
32
|
-
const el = document.createElement("div");
|
|
33
|
-
document.body.appendChild(el);
|
|
34
|
-
let hovered;
|
|
35
|
-
effectScope(() => {
|
|
36
|
-
hovered = createHover(el);
|
|
37
|
-
});
|
|
38
|
-
el.dispatchEvent(new PointerEvent("pointerenter"));
|
|
39
|
-
el.dispatchEvent(new PointerEvent("pointerleave"));
|
|
40
|
-
globalExpect(hovered()).toBe(false);
|
|
41
|
-
});
|
|
42
|
-
it("removes listeners on scope disposal", () => {
|
|
43
|
-
const el = document.createElement("div");
|
|
44
|
-
document.body.appendChild(el);
|
|
45
|
-
let hovered;
|
|
46
|
-
effectScope(() => {
|
|
47
|
-
hovered = createHover(el);
|
|
48
|
-
})();
|
|
49
|
-
el.dispatchEvent(new PointerEvent("pointerenter"));
|
|
50
|
-
globalExpect(hovered()).toBe(false);
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
//#endregion
|
|
54
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { };
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { c as effectScope } from "../lib-Dkc7cV5F.mjs";
|
|
2
|
-
import "../signals/index.mjs";
|
|
3
|
-
import { f as it, l as describe, o as afterEach } from "../benchmark.CX_oY03V-CSLAXL5f.mjs";
|
|
4
|
-
import { n as vi, t as globalExpect } from "../test.BmQO5GaM-Ddz9cDxc.mjs";
|
|
5
|
-
import { createIntersectionObserver } from "./intersection-observer.mjs";
|
|
6
|
-
//#region src/utilities/intersection-observer.test.ts
|
|
7
|
-
afterEach(() => {
|
|
8
|
-
document.body.innerHTML = "";
|
|
9
|
-
vi.unstubAllGlobals();
|
|
10
|
-
});
|
|
11
|
-
describe("createIntersectionObserver", () => {
|
|
12
|
-
it("observes a target element", () => {
|
|
13
|
-
const target = document.createElement("div");
|
|
14
|
-
document.body.appendChild(target);
|
|
15
|
-
const observe = vi.fn();
|
|
16
|
-
vi.stubGlobal("IntersectionObserver", function MockIO() {
|
|
17
|
-
return {
|
|
18
|
-
observe,
|
|
19
|
-
disconnect: vi.fn()
|
|
20
|
-
};
|
|
21
|
-
});
|
|
22
|
-
effectScope(() => {
|
|
23
|
-
createIntersectionObserver(target, vi.fn());
|
|
24
|
-
});
|
|
25
|
-
globalExpect(observe).toHaveBeenCalledWith(target);
|
|
26
|
-
});
|
|
27
|
-
it("disconnects on Symbol.dispose", () => {
|
|
28
|
-
const target = document.createElement("div");
|
|
29
|
-
document.body.appendChild(target);
|
|
30
|
-
const disconnect = vi.fn();
|
|
31
|
-
vi.stubGlobal("IntersectionObserver", function MockIO() {
|
|
32
|
-
return {
|
|
33
|
-
observe: vi.fn(),
|
|
34
|
-
disconnect
|
|
35
|
-
};
|
|
36
|
-
});
|
|
37
|
-
let io;
|
|
38
|
-
effectScope(() => {
|
|
39
|
-
io = createIntersectionObserver(target, vi.fn());
|
|
40
|
-
});
|
|
41
|
-
io[Symbol.dispose]();
|
|
42
|
-
globalExpect(disconnect).toHaveBeenCalledOnce();
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
//#endregion
|
|
46
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { };
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import { c as effectScope } from "../lib-Dkc7cV5F.mjs";
|
|
2
|
-
import "../signals/index.mjs";
|
|
3
|
-
import { f as it, l as describe, o as afterEach } from "../benchmark.CX_oY03V-CSLAXL5f.mjs";
|
|
4
|
-
import { n as vi, t as globalExpect } from "../test.BmQO5GaM-Ddz9cDxc.mjs";
|
|
5
|
-
import { async } from "./async.mjs";
|
|
6
|
-
import { createInterval } from "./interval.mjs";
|
|
7
|
-
//#region src/utilities/interval.test.ts
|
|
8
|
-
afterEach(() => {
|
|
9
|
-
document.body.innerHTML = "";
|
|
10
|
-
vi.useRealTimers();
|
|
11
|
-
});
|
|
12
|
-
describe("createInterval", () => {
|
|
13
|
-
it("calls callback on each tick", () => {
|
|
14
|
-
vi.useFakeTimers();
|
|
15
|
-
const cb = vi.fn();
|
|
16
|
-
effectScope(() => {
|
|
17
|
-
createInterval(cb, 100);
|
|
18
|
-
});
|
|
19
|
-
vi.advanceTimersByTime(350);
|
|
20
|
-
globalExpect(cb).toHaveBeenCalledTimes(3);
|
|
21
|
-
});
|
|
22
|
-
it("stop() pauses the interval", () => {
|
|
23
|
-
vi.useFakeTimers();
|
|
24
|
-
const cb = vi.fn();
|
|
25
|
-
let iv;
|
|
26
|
-
effectScope(() => {
|
|
27
|
-
iv = createInterval(cb, 100);
|
|
28
|
-
});
|
|
29
|
-
iv.stop();
|
|
30
|
-
vi.advanceTimersByTime(500);
|
|
31
|
-
globalExpect(cb).toHaveBeenCalledTimes(0);
|
|
32
|
-
globalExpect(iv.pending()).toBe(false);
|
|
33
|
-
});
|
|
34
|
-
it("start() resumes after stop", () => {
|
|
35
|
-
vi.useFakeTimers();
|
|
36
|
-
const cb = vi.fn();
|
|
37
|
-
let iv;
|
|
38
|
-
effectScope(() => {
|
|
39
|
-
iv = createInterval(cb, 100);
|
|
40
|
-
});
|
|
41
|
-
iv.stop();
|
|
42
|
-
iv.start();
|
|
43
|
-
vi.advanceTimersByTime(250);
|
|
44
|
-
globalExpect(cb).toHaveBeenCalledTimes(2);
|
|
45
|
-
});
|
|
46
|
-
it("reset() restarts the interval", () => {
|
|
47
|
-
vi.useFakeTimers();
|
|
48
|
-
const cb = vi.fn();
|
|
49
|
-
let iv;
|
|
50
|
-
effectScope(() => {
|
|
51
|
-
iv = createInterval(cb, 100);
|
|
52
|
-
});
|
|
53
|
-
vi.advanceTimersByTime(50);
|
|
54
|
-
iv.reset();
|
|
55
|
-
vi.advanceTimersByTime(100);
|
|
56
|
-
globalExpect(cb).toHaveBeenCalledTimes(1);
|
|
57
|
-
});
|
|
58
|
-
it("Symbol.dispose cleans up", () => {
|
|
59
|
-
vi.useFakeTimers();
|
|
60
|
-
const cb = vi.fn();
|
|
61
|
-
let iv;
|
|
62
|
-
effectScope(() => {
|
|
63
|
-
iv = createInterval(cb, 100);
|
|
64
|
-
});
|
|
65
|
-
iv[Symbol.dispose]();
|
|
66
|
-
vi.advanceTimersByTime(500);
|
|
67
|
-
globalExpect(cb).toHaveBeenCalledTimes(0);
|
|
68
|
-
});
|
|
69
|
-
it("no-callback form updates timestamp on each tick", () => {
|
|
70
|
-
vi.useFakeTimers();
|
|
71
|
-
let iv;
|
|
72
|
-
effectScope(() => {
|
|
73
|
-
iv = createInterval(100);
|
|
74
|
-
});
|
|
75
|
-
const before = iv.timestamp();
|
|
76
|
-
vi.advanceTimersByTime(100);
|
|
77
|
-
globalExpect(iv.timestamp()).toBeGreaterThan(before);
|
|
78
|
-
});
|
|
79
|
-
it("dynamic delay form is called each tick", () => {
|
|
80
|
-
vi.useFakeTimers();
|
|
81
|
-
const cb = vi.fn();
|
|
82
|
-
const getDelay = vi.fn().mockReturnValue(100);
|
|
83
|
-
effectScope(() => {
|
|
84
|
-
createInterval(cb, getDelay);
|
|
85
|
-
});
|
|
86
|
-
vi.advanceTimersByTime(300);
|
|
87
|
-
globalExpect(cb).toHaveBeenCalledTimes(3);
|
|
88
|
-
});
|
|
89
|
-
it("stops when scope is disposed", () => {
|
|
90
|
-
vi.useFakeTimers();
|
|
91
|
-
const cb = vi.fn();
|
|
92
|
-
effectScope(() => {
|
|
93
|
-
createInterval(cb, 100);
|
|
94
|
-
})();
|
|
95
|
-
vi.advanceTimersByTime(500);
|
|
96
|
-
globalExpect(cb).toHaveBeenCalledTimes(0);
|
|
97
|
-
});
|
|
98
|
-
it("composes with async() — reruns on each tick", async () => {
|
|
99
|
-
vi.useFakeTimers();
|
|
100
|
-
const asyncOp = async;
|
|
101
|
-
let runCount = 0;
|
|
102
|
-
const timer = createInterval(100);
|
|
103
|
-
const op = asyncOp(() => {
|
|
104
|
-
timer.timestamp();
|
|
105
|
-
runCount++;
|
|
106
|
-
return Promise.resolve(runCount);
|
|
107
|
-
}).start();
|
|
108
|
-
await vi.advanceTimersByTimeAsync(350);
|
|
109
|
-
globalExpect(runCount).toBeGreaterThan(1);
|
|
110
|
-
timer[Symbol.dispose]();
|
|
111
|
-
op.stop();
|
|
112
|
-
});
|
|
113
|
-
});
|
|
114
|
-
//#endregion
|
|
115
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { };
|