elements-kit 0.18.2 → 0.19.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/dist/ui/overlay/index.css +70 -0
- package/dist/ui/overlay/index.d.mts +209 -0
- package/dist/ui/overlay/index.mjs +1001 -0
- package/dist/ui/overlay/overlay.css +332 -0
- package/dist/utilities/form-object.d.mts +96 -0
- package/dist/utilities/form-object.mjs +285 -0
- package/dist/utilities/form-object.test.d.mts +1 -0
- package/dist/utilities/form-object.test.mjs +408 -0
- package/package.json +5 -5
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
.x-overlay {
|
|
2
|
+
color: var(--neutral-12);
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.x-overlay:where([open])::backdrop {
|
|
6
|
+
background: var(--overlay-backdrop, var(--color-overlay));
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.x-overlay > .x-card {
|
|
10
|
+
contain: none;
|
|
11
|
+
touch-action: pan-y;
|
|
12
|
+
position: static;
|
|
13
|
+
overflow-y: auto;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
:where(.x-overlay:not([data-material-background], [data-material-background] .x-overlay)) {
|
|
17
|
+
--color-material: var(--color-material-solid);
|
|
18
|
+
--backdrop-filter-material: none;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.x-overlay:where([data-resize], [data-draggable]):before, .x-overlay:where([data-resize], [data-draggable]):after {
|
|
22
|
+
content: "";
|
|
23
|
+
z-index: 1;
|
|
24
|
+
pointer-events: none;
|
|
25
|
+
position: absolute;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.x-overlay:where([data-draggable]:not([data-resize^="end-"])):after {
|
|
29
|
+
width: var(--space-3);
|
|
30
|
+
height: var(--space-3);
|
|
31
|
+
border-radius: var(--overlay-grip-radius, var(--radius-5));
|
|
32
|
+
background-color: var(--neutral-a8);
|
|
33
|
+
inset-block-start: var(--space-2);
|
|
34
|
+
inset-inline-start: var(--space-2);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.x-overlay:where([data-draggable][data-resize="start-start"]):after {
|
|
38
|
+
inset-inline-start: auto;
|
|
39
|
+
inset-inline-end: var(--space-2);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.x-overlay:where([data-draggable][data-resize^="end-"]):after {
|
|
43
|
+
top: var(--space-2);
|
|
44
|
+
width: var(--space-8);
|
|
45
|
+
height: var(--space-1);
|
|
46
|
+
border-radius: max(var(--radius-1), var(--radius-pill));
|
|
47
|
+
background-color: var(--neutral-a8);
|
|
48
|
+
margin-inline: auto;
|
|
49
|
+
inset-inline: 0;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.x-overlay:where([data-resize^="block-"]):before {
|
|
53
|
+
width: var(--space-8);
|
|
54
|
+
height: var(--space-1);
|
|
55
|
+
border-radius: max(var(--radius-1), var(--radius-pill));
|
|
56
|
+
background-color: var(--neutral-a8);
|
|
57
|
+
margin-inline: auto;
|
|
58
|
+
inset-inline: 0;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.x-overlay:where([data-resize="block-start"]):before {
|
|
62
|
+
top: var(--space-2);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.x-overlay:where([data-resize="block-end"]):before {
|
|
66
|
+
bottom: var(--space-2);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.x-overlay:where([data-resize^="inline-"]):before {
|
|
70
|
+
width: var(--space-1);
|
|
71
|
+
height: var(--space-8);
|
|
72
|
+
border-radius: max(var(--radius-1), var(--radius-pill));
|
|
73
|
+
background-color: var(--neutral-a8);
|
|
74
|
+
margin-block: auto;
|
|
75
|
+
inset-block: 0;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.x-overlay:where([data-resize="inline-start"]):before {
|
|
79
|
+
inset-inline-start: var(--space-2);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.x-overlay:where([data-resize="inline-end"]):before {
|
|
83
|
+
inset-inline-end: var(--space-2);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.x-overlay:where([data-resize^="start-"], [data-resize^="end-"]):before {
|
|
87
|
+
--_grip-r: max(calc(var(--overlay-grip-radius, var(--radius-5)) - var(--space-1)),
|
|
88
|
+
0px);
|
|
89
|
+
--_cap: min(var(--space-1), calc(var(--_grip-r) * 9999));
|
|
90
|
+
--_gx: 1;
|
|
91
|
+
--_gy: 1;
|
|
92
|
+
content: "";
|
|
93
|
+
z-index: 1;
|
|
94
|
+
pointer-events: none;
|
|
95
|
+
width: max(calc(var(--_grip-r) + var(--space-1)), calc(var(--space-1) * 3));
|
|
96
|
+
height: max(calc(var(--_grip-r) + var(--space-1)), calc(var(--space-1) * 3));
|
|
97
|
+
border: var(--space-1) solid var(--neutral-a8);
|
|
98
|
+
border-bottom-right-radius: var(--_grip-r);
|
|
99
|
+
transform: scale(var(--_gx), var(--_gy));
|
|
100
|
+
-webkit-mask: /* tails, cut flat at the cap centers (full length when capless) */
|
|
101
|
+
linear-gradient(#000, #000) right 0 top calc(var(--_cap) / 2) /
|
|
102
|
+
var(--space-1) calc(100% - var(--_cap) / 2) no-repeat,
|
|
103
|
+
linear-gradient(#000, #000) left calc(var(--_cap) / 2) bottom 0 /
|
|
104
|
+
calc(100% - var(--_cap) / 2) var(--space-1) no-repeat,
|
|
105
|
+
/* arc quadrant — the border's own curve shows through */
|
|
106
|
+
linear-gradient(#000, #000) 100% 100% / var(--_grip-r) var(--_grip-r)
|
|
107
|
+
no-repeat,
|
|
108
|
+
/* round caps, centered on the flat cuts over solid border ink */
|
|
109
|
+
radial-gradient(circle closest-side,
|
|
110
|
+
#000 calc(100% - .5px),
|
|
111
|
+
transparent)
|
|
112
|
+
right 0 top 0 / var(--_cap) var(--_cap) no-repeat,
|
|
113
|
+
radial-gradient(circle closest-side,
|
|
114
|
+
#000 calc(100% - .5px),
|
|
115
|
+
transparent)
|
|
116
|
+
left 0 bottom 0 / var(--_cap) var(--_cap) no-repeat;
|
|
117
|
+
mask: /* tails, cut flat at the cap centers (full length when capless) */
|
|
118
|
+
linear-gradient(#000, #000) right 0 top calc(var(--_cap) / 2) /
|
|
119
|
+
var(--space-1) calc(100% - var(--_cap) / 2) no-repeat,
|
|
120
|
+
linear-gradient(#000, #000) left calc(var(--_cap) / 2) bottom 0 /
|
|
121
|
+
calc(100% - var(--_cap) / 2) var(--space-1) no-repeat,
|
|
122
|
+
/* arc quadrant — the border's own curve shows through */
|
|
123
|
+
linear-gradient(#000, #000) 100% 100% / var(--_grip-r) var(--_grip-r)
|
|
124
|
+
no-repeat,
|
|
125
|
+
/* round caps, centered on the flat cuts over solid border ink */
|
|
126
|
+
radial-gradient(circle closest-side,
|
|
127
|
+
#000 calc(100% - .5px),
|
|
128
|
+
transparent)
|
|
129
|
+
right 0 top 0 / var(--_cap) var(--_cap) no-repeat,
|
|
130
|
+
radial-gradient(circle closest-side,
|
|
131
|
+
#000 calc(100% - .5px),
|
|
132
|
+
transparent)
|
|
133
|
+
left 0 bottom 0 / var(--_cap) var(--_cap) no-repeat;
|
|
134
|
+
position: absolute;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.x-overlay:where([data-resize="start-end"], [data-resize="end-end"]):before {
|
|
138
|
+
inset-inline-end: var(--space-1);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.x-overlay:where([data-resize="start-start"], [data-resize="end-start"]):before {
|
|
142
|
+
--_gx: -1;
|
|
143
|
+
inset-inline-start: var(--space-1);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.x-overlay:where([data-resize^="end-"]):before {
|
|
147
|
+
bottom: var(--space-1);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.x-overlay:where([data-resize^="start-"]):before {
|
|
151
|
+
top: var(--space-1);
|
|
152
|
+
--_gy: -1;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.x-overlay:where([data-resize="start-end"], [data-resize="end-end"]):where(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))):before {
|
|
156
|
+
--_gx: -1;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.x-overlay:where([data-resize="start-start"], [data-resize="end-start"]):where(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))):before {
|
|
160
|
+
--_gx: 1;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
@supports (transition-behavior: allow-discrete) {
|
|
164
|
+
.x-overlay {
|
|
165
|
+
transition-property: top, left, translate, width, height, opacity, scale, display;
|
|
166
|
+
transition-duration: var(--overlay-duration);
|
|
167
|
+
transition-timing-function: var(--overlay-easing);
|
|
168
|
+
transition-behavior: allow-discrete;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.x-overlay:where(:not([data-resize]), [data-resize^="start-"], [data-resize^="end-"]) {
|
|
172
|
+
opacity: 0;
|
|
173
|
+
scale: .97;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.x-overlay:where(:not([data-resize]), [data-resize^="start-"], [data-resize^="end-"]):where([open], :popover-open) {
|
|
177
|
+
opacity: 1;
|
|
178
|
+
scale: 1;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
@starting-style {
|
|
182
|
+
.x-overlay:where(:not([data-resize]), [data-resize^="start-"], [data-resize^="end-"]):where([open], :popover-open) {
|
|
183
|
+
opacity: 0;
|
|
184
|
+
scale: .97;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.x-overlay:where([data-resize="block-start"]) {
|
|
189
|
+
--_ey: 100%;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.x-overlay:where([data-resize="block-start"]):where([open], :popover-open) {
|
|
193
|
+
--_ey: 0%;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
@starting-style {
|
|
197
|
+
.x-overlay:where([data-resize="block-start"]):where([open], :popover-open) {
|
|
198
|
+
--_ey: 100%;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.x-overlay:where([data-resize="block-end"]) {
|
|
203
|
+
--_ey: -100%;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.x-overlay:where([data-resize="block-end"]):where([open], :popover-open) {
|
|
207
|
+
--_ey: 0%;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
@starting-style {
|
|
211
|
+
.x-overlay:where([data-resize="block-end"]):where([open], :popover-open) {
|
|
212
|
+
--_ey: -100%;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.x-overlay:where([data-resize="inline-start"]) {
|
|
217
|
+
--_ex: 100%;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.x-overlay:where([data-resize="inline-start"]):where([open], :popover-open) {
|
|
221
|
+
--_ex: 0%;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
@starting-style {
|
|
225
|
+
.x-overlay:where([data-resize="inline-start"]):where([open], :popover-open) {
|
|
226
|
+
--_ex: 100%;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
.x-overlay:where([data-resize="inline-start"]):where(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
|
|
231
|
+
--_ex: -100%;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
.x-overlay:where([data-resize="inline-start"]):where(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))):where([open], :popover-open) {
|
|
235
|
+
--_ex: 0%;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
@starting-style {
|
|
239
|
+
.x-overlay:where([data-resize="inline-start"]):where(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))):where([open], :popover-open) {
|
|
240
|
+
--_ex: -100%;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.x-overlay:where([data-resize="inline-end"]) {
|
|
245
|
+
--_ex: -100%;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.x-overlay:where([data-resize="inline-end"]):where([open], :popover-open) {
|
|
249
|
+
--_ex: 0%;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
@starting-style {
|
|
253
|
+
.x-overlay:where([data-resize="inline-end"]):where([open], :popover-open) {
|
|
254
|
+
--_ex: -100%;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.x-overlay:where([data-resize="inline-end"]):where(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
|
|
259
|
+
--_ex: 100%;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
.x-overlay:where([data-resize="inline-end"]):where(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))):where([open], :popover-open) {
|
|
263
|
+
--_ex: 0%;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
@starting-style {
|
|
267
|
+
.x-overlay:where([data-resize="inline-end"]):where(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))):where([open], :popover-open) {
|
|
268
|
+
--_ex: 100%;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
.x-overlay::backdrop {
|
|
273
|
+
opacity: 0;
|
|
274
|
+
transition-property: opacity, display;
|
|
275
|
+
transition-duration: var(--overlay-duration);
|
|
276
|
+
transition-timing-function: var(--overlay-easing);
|
|
277
|
+
transition-behavior: allow-discrete;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
.x-overlay:where([open])::backdrop {
|
|
281
|
+
opacity: 1;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
@starting-style {
|
|
285
|
+
.x-overlay:where([open])::backdrop {
|
|
286
|
+
opacity: 0;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
@supports (overlay: auto) {
|
|
291
|
+
.x-overlay {
|
|
292
|
+
transition-property: top, left, translate, width, height, opacity, scale, display, overlay;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.x-overlay::backdrop {
|
|
296
|
+
transition-property: opacity, display, overlay;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
@supports selector(:has(*)) {
|
|
302
|
+
[data-overlay-deck] {
|
|
303
|
+
transform-origin: 50% 0;
|
|
304
|
+
transition-property: scale, translate, border-radius;
|
|
305
|
+
transition-duration: var(--overlay-duration, .3s);
|
|
306
|
+
transition-timing-function: var(--overlay-easing, cubic-bezier(.32, .72, 0, 1));
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
:root:has(.x-overlay[data-resize="block-start"][open]) [data-overlay-deck] {
|
|
310
|
+
scale: .96;
|
|
311
|
+
translate: 0 var(--space-2);
|
|
312
|
+
border-radius: var(--radius-4);
|
|
313
|
+
overflow: clip;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
@media (prefers-reduced-motion: reduce) {
|
|
318
|
+
.x-overlay, .x-overlay::backdrop, [data-overlay-deck] {
|
|
319
|
+
transition: none;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
@media (forced-colors: active) {
|
|
324
|
+
.x-overlay:where([data-resize]):before {
|
|
325
|
+
background-color: buttontext;
|
|
326
|
+
border-color: buttontext;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
.x-overlay:where([data-draggable]):after {
|
|
330
|
+
background-color: buttontext;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
//#region src/utilities/form-object.d.ts
|
|
2
|
+
/** Leaf value a single control contributes to the extracted object. */
|
|
3
|
+
type FormObjectValue = string | number | boolean | File | null;
|
|
4
|
+
/** A nested plain object built from a form's dot-notation field names. */
|
|
5
|
+
type FormValues = {
|
|
6
|
+
[key: string]: unknown;
|
|
7
|
+
};
|
|
8
|
+
/** Named controls FormObject reads from and writes to. */
|
|
9
|
+
type NamedControl = HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;
|
|
10
|
+
/**
|
|
11
|
+
* One control's contribution, as seen by transforms before the nested object
|
|
12
|
+
* is assembled. `value` is the raw extracted value; `checked` is present only
|
|
13
|
+
* for checkbox / radio controls.
|
|
14
|
+
*/
|
|
15
|
+
interface Field {
|
|
16
|
+
control: NamedControl;
|
|
17
|
+
/** Dot-notation path. Transforms may rewrite it to remap the output key. */
|
|
18
|
+
name: string;
|
|
19
|
+
/** `string | string[] | File | File[] | boolean` depending on control type. */
|
|
20
|
+
value: unknown;
|
|
21
|
+
/** Whether the control is checked — checkbox / radio only. */
|
|
22
|
+
checked?: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Per-field transform. Return the (possibly modified) field to keep it, or
|
|
26
|
+
* `null` to drop it from the output. Run in order during {@link FormObject.toObject}.
|
|
27
|
+
*/
|
|
28
|
+
type FormFieldTransform = (field: Field) => Field | null;
|
|
29
|
+
interface FormObjectOptions {
|
|
30
|
+
/**
|
|
31
|
+
* Pipeline applied to each field during `toObject()`. Defaults to
|
|
32
|
+
* {@link defaultTransforms}. Providing this **replaces** the defaults —
|
|
33
|
+
* spread `...defaultTransforms` to extend them.
|
|
34
|
+
*/
|
|
35
|
+
transforms?: FormFieldTransform[];
|
|
36
|
+
}
|
|
37
|
+
/** Drop disabled controls (mirrors native `FormData`). */
|
|
38
|
+
declare const skipDisabled: FormFieldTransform;
|
|
39
|
+
/** Drop submit / reset / button / image controls and `<button>` elements. */
|
|
40
|
+
declare const skipButtons: FormFieldTransform;
|
|
41
|
+
/** Drop fields whose control is an unchecked checkbox / radio. */
|
|
42
|
+
declare const dropUnchecked: FormFieldTransform;
|
|
43
|
+
/**
|
|
44
|
+
* Include unchecked **checkboxes** with the given `value` instead of dropping
|
|
45
|
+
* them. Unchecked **radios** are still dropped (only the selected radio is
|
|
46
|
+
* meaningful). Use this **in place of** {@link dropUnchecked}.
|
|
47
|
+
*
|
|
48
|
+
* @example transforms: [skipDisabled, skipButtons, uncheckedAs(false)]
|
|
49
|
+
*/
|
|
50
|
+
declare function uncheckedAs(value: unknown): FormFieldTransform;
|
|
51
|
+
/** Drop fields whose value is empty: `""`, `null`, or an empty array. */
|
|
52
|
+
declare const skipEmpty: FormFieldTransform;
|
|
53
|
+
/** Default pipeline: skip disabled controls, buttons, and unchecked checkboxes/radios. */
|
|
54
|
+
declare const defaultTransforms: FormFieldTransform[];
|
|
55
|
+
/**
|
|
56
|
+
* Extracts an {@link HTMLFormElement} into a nested plain object (and writes one
|
|
57
|
+
* back) using dot-notation field names — `name="user.address.city"` nests into
|
|
58
|
+
* objects, numeric segments like `name="tags.0"` build arrays. A static snapshot:
|
|
59
|
+
* values are read/written at call time, no reactivity.
|
|
60
|
+
*
|
|
61
|
+
* Extraction runs each field through a composable {@link FormFieldTransform}
|
|
62
|
+
* pipeline ({@link defaultTransforms} by default), which decides inclusion and
|
|
63
|
+
* may rewrite names/values. Mirrors the ergonomics of the native `FormData`
|
|
64
|
+
* constructor.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```ts
|
|
68
|
+
* import { FormObject, defaultTransforms, uncheckedAs }
|
|
69
|
+
* from "elements-kit/utilities/form-object";
|
|
70
|
+
*
|
|
71
|
+
* // <input name="user.name"> <input name="tags.0"> <input name="tags.1">
|
|
72
|
+
* const data = new FormObject(form).toObject();
|
|
73
|
+
* // => { user: { name: "..." }, tags: ["...", "..."] }
|
|
74
|
+
*
|
|
75
|
+
* // Replace the pipeline — include unchecked checkboxes as false
|
|
76
|
+
* new FormObject(form, {
|
|
77
|
+
* transforms: [...defaultTransforms.slice(0, 2), uncheckedAs(false)],
|
|
78
|
+
* }).toObject();
|
|
79
|
+
*
|
|
80
|
+
* new FormObject(form).fromObject({ user: { name: "Wael" }, tags: ["a", "b"] });
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
declare class FormObject {
|
|
84
|
+
#private;
|
|
85
|
+
constructor(form: HTMLFormElement, options?: FormObjectOptions);
|
|
86
|
+
/** Snapshot the form into a nested object built from dot-notation names. */
|
|
87
|
+
toObject(): FormValues;
|
|
88
|
+
/** Alias for {@link toObject} — lets `JSON.stringify(instance)` work. */
|
|
89
|
+
toJSON(): FormValues;
|
|
90
|
+
/** Write values from a nested object back onto the form's named controls. */
|
|
91
|
+
fromObject(data: FormValues): this;
|
|
92
|
+
/** Reset every named control to its empty/default state. */
|
|
93
|
+
clear(): this;
|
|
94
|
+
}
|
|
95
|
+
//#endregion
|
|
96
|
+
export { Field, FormFieldTransform, FormObject, FormObjectOptions, FormObjectValue, FormValues, NamedControl, defaultTransforms, dropUnchecked, skipButtons, skipDisabled, skipEmpty, uncheckedAs };
|