@dynamic-field-kit/react 1.3.0 → 1.5.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/CHANGELOG.md +180 -0
- package/LICENSE +21 -0
- package/README.md +161 -4
- package/dist/index.d.mts +88 -18
- package/dist/index.d.ts +88 -18
- package/dist/index.js +843 -62
- package/dist/index.mjs +832 -48
- package/package.json +38 -24
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -61,17 +61,36 @@ function resolve(layout) {
|
|
|
61
61
|
return { type: layout.type, config: layout };
|
|
62
62
|
}
|
|
63
63
|
function checkIsMobile(breakpoint) {
|
|
64
|
-
|
|
64
|
+
if (typeof window === "undefined") {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
if (typeof window.matchMedia === "function") {
|
|
68
|
+
return window.matchMedia(`(max-width: ${breakpoint - 1}px)`).matches;
|
|
69
|
+
}
|
|
70
|
+
return window.innerWidth < breakpoint;
|
|
65
71
|
}
|
|
66
72
|
layoutRegistry.register("responsive", ({ children, config }) => {
|
|
67
73
|
const responsiveConfig = config;
|
|
68
74
|
const breakpoint = responsiveConfig.breakpoint ?? 768;
|
|
69
75
|
const [isMobile, setIsMobile] = useState(() => checkIsMobile(breakpoint));
|
|
70
76
|
useEffect(() => {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
77
|
+
if (typeof window === "undefined") {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (typeof window.matchMedia !== "function") {
|
|
81
|
+
const handleResize = () => setIsMobile(checkIsMobile(breakpoint));
|
|
82
|
+
window.addEventListener("resize", handleResize);
|
|
83
|
+
return () => window.removeEventListener("resize", handleResize);
|
|
84
|
+
}
|
|
85
|
+
const mediaQuery = window.matchMedia(`(max-width: ${breakpoint - 1}px)`);
|
|
86
|
+
const handleChange = (e) => setIsMobile(e.matches);
|
|
87
|
+
setIsMobile(mediaQuery.matches);
|
|
88
|
+
if (mediaQuery.addEventListener) {
|
|
89
|
+
mediaQuery.addEventListener("change", handleChange);
|
|
90
|
+
return () => mediaQuery.removeEventListener("change", handleChange);
|
|
91
|
+
}
|
|
92
|
+
mediaQuery.addListener(handleChange);
|
|
93
|
+
return () => mediaQuery.removeListener(handleChange);
|
|
75
94
|
}, [breakpoint]);
|
|
76
95
|
const current = isMobile ? responsiveConfig.mobile : responsiveConfig.desktop;
|
|
77
96
|
if (!current) {
|
|
@@ -92,7 +111,311 @@ layoutRegistry.register("responsive", ({ children, config }) => {
|
|
|
92
111
|
});
|
|
93
112
|
|
|
94
113
|
// src/components/DynamicInput.tsx
|
|
95
|
-
import
|
|
114
|
+
import React3, { useMemo } from "react";
|
|
115
|
+
|
|
116
|
+
// src/defaultRenderers.tsx
|
|
117
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
118
|
+
var DefaultTextRenderer = ({
|
|
119
|
+
value,
|
|
120
|
+
onValueChange,
|
|
121
|
+
onBlur,
|
|
122
|
+
disabled,
|
|
123
|
+
readOnly,
|
|
124
|
+
required,
|
|
125
|
+
placeholder,
|
|
126
|
+
id,
|
|
127
|
+
className,
|
|
128
|
+
ariaInvalid,
|
|
129
|
+
ariaDescribedBy,
|
|
130
|
+
ariaRequired,
|
|
131
|
+
inputType = "text"
|
|
132
|
+
}) => /* @__PURE__ */ jsx3(
|
|
133
|
+
"input",
|
|
134
|
+
{
|
|
135
|
+
type: inputType,
|
|
136
|
+
id,
|
|
137
|
+
className,
|
|
138
|
+
value: value ?? "",
|
|
139
|
+
onChange: (e) => onValueChange?.(e.target.value),
|
|
140
|
+
onBlur,
|
|
141
|
+
disabled,
|
|
142
|
+
readOnly,
|
|
143
|
+
required,
|
|
144
|
+
placeholder,
|
|
145
|
+
"aria-invalid": ariaInvalid,
|
|
146
|
+
"aria-describedby": ariaDescribedBy,
|
|
147
|
+
"aria-required": ariaRequired
|
|
148
|
+
}
|
|
149
|
+
);
|
|
150
|
+
var DefaultNumberRenderer = ({
|
|
151
|
+
value,
|
|
152
|
+
onValueChange,
|
|
153
|
+
onBlur,
|
|
154
|
+
disabled,
|
|
155
|
+
readOnly,
|
|
156
|
+
required,
|
|
157
|
+
placeholder,
|
|
158
|
+
id,
|
|
159
|
+
className,
|
|
160
|
+
ariaInvalid,
|
|
161
|
+
ariaDescribedBy,
|
|
162
|
+
ariaRequired
|
|
163
|
+
}) => /* @__PURE__ */ jsx3(
|
|
164
|
+
"input",
|
|
165
|
+
{
|
|
166
|
+
type: "number",
|
|
167
|
+
id,
|
|
168
|
+
className,
|
|
169
|
+
value: value ?? "",
|
|
170
|
+
onChange: (e) => onValueChange?.(
|
|
171
|
+
e.target.value === "" ? void 0 : Number(e.target.value)
|
|
172
|
+
),
|
|
173
|
+
onBlur,
|
|
174
|
+
disabled,
|
|
175
|
+
readOnly,
|
|
176
|
+
required,
|
|
177
|
+
placeholder,
|
|
178
|
+
"aria-invalid": ariaInvalid,
|
|
179
|
+
"aria-describedby": ariaDescribedBy,
|
|
180
|
+
"aria-required": ariaRequired
|
|
181
|
+
}
|
|
182
|
+
);
|
|
183
|
+
var DefaultPasswordRenderer = (props) => /* @__PURE__ */ jsx3(DefaultTextRenderer, { ...props, inputType: "password" });
|
|
184
|
+
var DefaultEmailRenderer = (props) => /* @__PURE__ */ jsx3(DefaultTextRenderer, { ...props, inputType: "email" });
|
|
185
|
+
var DefaultTextareaRenderer = ({
|
|
186
|
+
value,
|
|
187
|
+
onValueChange,
|
|
188
|
+
onBlur,
|
|
189
|
+
disabled,
|
|
190
|
+
readOnly,
|
|
191
|
+
required,
|
|
192
|
+
placeholder,
|
|
193
|
+
id,
|
|
194
|
+
className,
|
|
195
|
+
ariaInvalid,
|
|
196
|
+
ariaDescribedBy,
|
|
197
|
+
ariaRequired
|
|
198
|
+
}) => /* @__PURE__ */ jsx3(
|
|
199
|
+
"textarea",
|
|
200
|
+
{
|
|
201
|
+
id,
|
|
202
|
+
className,
|
|
203
|
+
value: value ?? "",
|
|
204
|
+
onChange: (e) => onValueChange?.(e.target.value),
|
|
205
|
+
onBlur,
|
|
206
|
+
disabled,
|
|
207
|
+
readOnly,
|
|
208
|
+
required,
|
|
209
|
+
placeholder,
|
|
210
|
+
"aria-invalid": ariaInvalid,
|
|
211
|
+
"aria-describedby": ariaDescribedBy,
|
|
212
|
+
"aria-required": ariaRequired
|
|
213
|
+
}
|
|
214
|
+
);
|
|
215
|
+
var DefaultCheckboxRenderer = ({
|
|
216
|
+
value,
|
|
217
|
+
onValueChange,
|
|
218
|
+
onBlur,
|
|
219
|
+
disabled,
|
|
220
|
+
readOnly,
|
|
221
|
+
required,
|
|
222
|
+
id,
|
|
223
|
+
className,
|
|
224
|
+
ariaInvalid,
|
|
225
|
+
ariaDescribedBy,
|
|
226
|
+
ariaRequired
|
|
227
|
+
}) => /* @__PURE__ */ jsx3(
|
|
228
|
+
"input",
|
|
229
|
+
{
|
|
230
|
+
type: "checkbox",
|
|
231
|
+
id,
|
|
232
|
+
className,
|
|
233
|
+
checked: Boolean(value),
|
|
234
|
+
onChange: (e) => onValueChange?.(e.target.checked),
|
|
235
|
+
onBlur,
|
|
236
|
+
disabled: disabled || readOnly,
|
|
237
|
+
required,
|
|
238
|
+
"aria-invalid": ariaInvalid,
|
|
239
|
+
"aria-describedby": ariaDescribedBy,
|
|
240
|
+
"aria-required": ariaRequired
|
|
241
|
+
}
|
|
242
|
+
);
|
|
243
|
+
var DefaultSelectRenderer = ({
|
|
244
|
+
value,
|
|
245
|
+
onValueChange,
|
|
246
|
+
onBlur,
|
|
247
|
+
disabled,
|
|
248
|
+
readOnly,
|
|
249
|
+
required,
|
|
250
|
+
options = [],
|
|
251
|
+
id,
|
|
252
|
+
className,
|
|
253
|
+
ariaInvalid,
|
|
254
|
+
ariaDescribedBy,
|
|
255
|
+
ariaRequired
|
|
256
|
+
}) => /* @__PURE__ */ jsxs2(
|
|
257
|
+
"select",
|
|
258
|
+
{
|
|
259
|
+
id,
|
|
260
|
+
className,
|
|
261
|
+
value: value ?? "",
|
|
262
|
+
onChange: (e) => onValueChange?.(e.target.value),
|
|
263
|
+
onBlur,
|
|
264
|
+
disabled: disabled || readOnly,
|
|
265
|
+
required,
|
|
266
|
+
"aria-invalid": ariaInvalid,
|
|
267
|
+
"aria-describedby": ariaDescribedBy,
|
|
268
|
+
"aria-required": ariaRequired,
|
|
269
|
+
children: [
|
|
270
|
+
/* @__PURE__ */ jsx3("option", { value: "", disabled: true, children: "-- Select --" }),
|
|
271
|
+
options.map((opt, i) => {
|
|
272
|
+
const optVal = opt.value ?? opt.id ?? opt;
|
|
273
|
+
const optLabel = opt.label ?? opt.name ?? String(optVal);
|
|
274
|
+
return /* @__PURE__ */ jsx3("option", { value: String(optVal), children: String(optLabel) }, String(optVal) + i);
|
|
275
|
+
})
|
|
276
|
+
]
|
|
277
|
+
}
|
|
278
|
+
);
|
|
279
|
+
var DefaultRadioRenderer = ({
|
|
280
|
+
value,
|
|
281
|
+
onValueChange,
|
|
282
|
+
onBlur,
|
|
283
|
+
disabled,
|
|
284
|
+
readOnly,
|
|
285
|
+
required,
|
|
286
|
+
options = [],
|
|
287
|
+
id,
|
|
288
|
+
className,
|
|
289
|
+
ariaInvalid,
|
|
290
|
+
ariaDescribedBy
|
|
291
|
+
}) => /* @__PURE__ */ jsx3("div", { className: `dfk-radio-group ${className || ""}`, id, onBlur, children: options.map((opt, i) => {
|
|
292
|
+
const optVal = opt.value ?? opt.id ?? opt;
|
|
293
|
+
const optLabel = opt.label ?? opt.name ?? String(optVal);
|
|
294
|
+
const isChecked = String(value) === String(optVal);
|
|
295
|
+
const radioId = `${id || "radio"}-${i}`;
|
|
296
|
+
return /* @__PURE__ */ jsxs2(
|
|
297
|
+
"label",
|
|
298
|
+
{
|
|
299
|
+
htmlFor: radioId,
|
|
300
|
+
style: {
|
|
301
|
+
marginRight: "12px",
|
|
302
|
+
display: "inline-flex",
|
|
303
|
+
alignItems: "center"
|
|
304
|
+
},
|
|
305
|
+
children: [
|
|
306
|
+
/* @__PURE__ */ jsx3(
|
|
307
|
+
"input",
|
|
308
|
+
{
|
|
309
|
+
type: "radio",
|
|
310
|
+
id: radioId,
|
|
311
|
+
name: id,
|
|
312
|
+
value: String(optVal),
|
|
313
|
+
checked: isChecked,
|
|
314
|
+
onChange: () => onValueChange?.(optVal),
|
|
315
|
+
disabled: disabled || readOnly,
|
|
316
|
+
required,
|
|
317
|
+
"aria-invalid": ariaInvalid,
|
|
318
|
+
"aria-describedby": ariaDescribedBy
|
|
319
|
+
}
|
|
320
|
+
),
|
|
321
|
+
/* @__PURE__ */ jsx3("span", { style: { marginLeft: "4px" }, children: String(optLabel) })
|
|
322
|
+
]
|
|
323
|
+
},
|
|
324
|
+
String(optVal) + i
|
|
325
|
+
);
|
|
326
|
+
}) });
|
|
327
|
+
var DefaultRangeRenderer = ({
|
|
328
|
+
value,
|
|
329
|
+
onValueChange,
|
|
330
|
+
onBlur,
|
|
331
|
+
disabled,
|
|
332
|
+
readOnly,
|
|
333
|
+
required,
|
|
334
|
+
min,
|
|
335
|
+
max,
|
|
336
|
+
step,
|
|
337
|
+
id,
|
|
338
|
+
className,
|
|
339
|
+
ariaInvalid,
|
|
340
|
+
ariaDescribedBy
|
|
341
|
+
}) => /* @__PURE__ */ jsx3(
|
|
342
|
+
"input",
|
|
343
|
+
{
|
|
344
|
+
type: "range",
|
|
345
|
+
id,
|
|
346
|
+
className,
|
|
347
|
+
value: value ?? min ?? 0,
|
|
348
|
+
min,
|
|
349
|
+
max,
|
|
350
|
+
step,
|
|
351
|
+
onChange: (e) => onValueChange?.(Number(e.target.value)),
|
|
352
|
+
onBlur,
|
|
353
|
+
disabled: disabled || readOnly,
|
|
354
|
+
required,
|
|
355
|
+
"aria-invalid": ariaInvalid,
|
|
356
|
+
"aria-describedby": ariaDescribedBy
|
|
357
|
+
}
|
|
358
|
+
);
|
|
359
|
+
var DefaultFileRenderer = ({
|
|
360
|
+
onValueChange,
|
|
361
|
+
onBlur,
|
|
362
|
+
disabled,
|
|
363
|
+
readOnly,
|
|
364
|
+
required,
|
|
365
|
+
accept,
|
|
366
|
+
multiple,
|
|
367
|
+
id,
|
|
368
|
+
className,
|
|
369
|
+
ariaInvalid,
|
|
370
|
+
ariaDescribedBy
|
|
371
|
+
}) => /* @__PURE__ */ jsx3(
|
|
372
|
+
"input",
|
|
373
|
+
{
|
|
374
|
+
type: "file",
|
|
375
|
+
id,
|
|
376
|
+
className,
|
|
377
|
+
accept,
|
|
378
|
+
multiple,
|
|
379
|
+
onChange: (e) => {
|
|
380
|
+
const files = e.target.files;
|
|
381
|
+
if (!files) {
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
onValueChange?.(multiple ? Array.from(files) : files[0] || null);
|
|
385
|
+
},
|
|
386
|
+
onBlur,
|
|
387
|
+
disabled: disabled || readOnly,
|
|
388
|
+
required,
|
|
389
|
+
"aria-invalid": ariaInvalid,
|
|
390
|
+
"aria-describedby": ariaDescribedBy
|
|
391
|
+
}
|
|
392
|
+
);
|
|
393
|
+
var DefaultDateRenderer = (props) => /* @__PURE__ */ jsx3(DefaultTextRenderer, { ...props, inputType: "date" });
|
|
394
|
+
var DefaultTimeRenderer = (props) => /* @__PURE__ */ jsx3(DefaultTextRenderer, { ...props, inputType: "time" });
|
|
395
|
+
var DefaultDateTimeLocalRenderer = (props) => /* @__PURE__ */ jsx3(DefaultTextRenderer, { ...props, inputType: "datetime-local" });
|
|
396
|
+
var DefaultSwitchRenderer = (props) => /* @__PURE__ */ jsx3(DefaultCheckboxRenderer, { ...props });
|
|
397
|
+
var defaultRenderersMap = {
|
|
398
|
+
text: DefaultTextRenderer,
|
|
399
|
+
number: DefaultNumberRenderer,
|
|
400
|
+
password: DefaultPasswordRenderer,
|
|
401
|
+
email: DefaultEmailRenderer,
|
|
402
|
+
textarea: DefaultTextareaRenderer,
|
|
403
|
+
checkbox: DefaultCheckboxRenderer,
|
|
404
|
+
select: DefaultSelectRenderer,
|
|
405
|
+
radio: DefaultRadioRenderer,
|
|
406
|
+
range: DefaultRangeRenderer,
|
|
407
|
+
file: DefaultFileRenderer,
|
|
408
|
+
date: DefaultDateRenderer,
|
|
409
|
+
time: DefaultTimeRenderer,
|
|
410
|
+
"datetime-local": DefaultDateTimeLocalRenderer,
|
|
411
|
+
switch: DefaultSwitchRenderer
|
|
412
|
+
};
|
|
413
|
+
function getDefaultRenderer(type) {
|
|
414
|
+
return defaultRenderersMap[type];
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// src/FieldRegistryContext.tsx
|
|
418
|
+
import { createContext, useContext } from "react";
|
|
96
419
|
|
|
97
420
|
// src/fieldRegistry.ts
|
|
98
421
|
import {
|
|
@@ -100,43 +423,85 @@ import {
|
|
|
100
423
|
} from "@dynamic-field-kit/core";
|
|
101
424
|
var fieldRegistry = coreFieldRegistry;
|
|
102
425
|
|
|
426
|
+
// src/FieldRegistryContext.tsx
|
|
427
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
428
|
+
var FieldRegistryContext = createContext(fieldRegistry);
|
|
429
|
+
var FieldRegistryProvider = ({
|
|
430
|
+
registry,
|
|
431
|
+
children
|
|
432
|
+
}) => /* @__PURE__ */ jsx4(FieldRegistryContext.Provider, { value: registry, children });
|
|
433
|
+
function useFieldRegistry() {
|
|
434
|
+
return useContext(FieldRegistryContext);
|
|
435
|
+
}
|
|
436
|
+
|
|
103
437
|
// src/components/DynamicInput.tsx
|
|
104
|
-
import { jsxs as
|
|
438
|
+
import { jsxs as jsxs3 } from "react/jsx-runtime";
|
|
105
439
|
var DynamicInputInner = ({
|
|
106
440
|
type,
|
|
107
441
|
value,
|
|
108
442
|
onChange,
|
|
443
|
+
onBlur,
|
|
109
444
|
label,
|
|
110
445
|
options,
|
|
111
446
|
className,
|
|
112
|
-
description
|
|
447
|
+
description,
|
|
448
|
+
disabled,
|
|
449
|
+
readOnly,
|
|
450
|
+
required,
|
|
451
|
+
touched,
|
|
452
|
+
dirty,
|
|
453
|
+
error,
|
|
454
|
+
id,
|
|
455
|
+
ariaInvalid,
|
|
456
|
+
ariaDescribedBy,
|
|
457
|
+
ariaRequired,
|
|
458
|
+
extraProps
|
|
113
459
|
}) => {
|
|
460
|
+
const registry = useFieldRegistry();
|
|
114
461
|
const Renderer = useMemo(
|
|
115
|
-
() =>
|
|
116
|
-
[type]
|
|
462
|
+
() => registry.get(type) || getDefaultRenderer(type),
|
|
463
|
+
[registry, type]
|
|
117
464
|
);
|
|
118
465
|
if (!Renderer) {
|
|
119
|
-
return /* @__PURE__ */
|
|
466
|
+
return /* @__PURE__ */ jsxs3("div", { children: [
|
|
120
467
|
"Unknown field type: ",
|
|
121
468
|
type
|
|
122
469
|
] });
|
|
123
470
|
}
|
|
124
|
-
return
|
|
471
|
+
return React3.createElement(Renderer, {
|
|
472
|
+
...extraProps,
|
|
125
473
|
value,
|
|
126
474
|
onValueChange: onChange,
|
|
475
|
+
onBlur,
|
|
127
476
|
label,
|
|
128
477
|
options,
|
|
129
478
|
className,
|
|
130
|
-
description
|
|
479
|
+
description,
|
|
480
|
+
disabled,
|
|
481
|
+
readOnly,
|
|
482
|
+
required,
|
|
483
|
+
touched,
|
|
484
|
+
dirty,
|
|
485
|
+
error,
|
|
486
|
+
id,
|
|
487
|
+
ariaInvalid,
|
|
488
|
+
ariaDescribedBy,
|
|
489
|
+
ariaRequired
|
|
131
490
|
});
|
|
132
491
|
};
|
|
133
|
-
var DynamicInput =
|
|
492
|
+
var DynamicInput = /* @__PURE__ */ React3.memo(
|
|
134
493
|
DynamicInputInner
|
|
135
494
|
);
|
|
136
495
|
var DynamicInput_default = DynamicInput;
|
|
137
496
|
|
|
138
497
|
// src/components/FieldInput.tsx
|
|
139
|
-
import
|
|
498
|
+
import {
|
|
499
|
+
resolveDisabled,
|
|
500
|
+
resolveOptions,
|
|
501
|
+
resolveReadOnly,
|
|
502
|
+
validateField
|
|
503
|
+
} from "@dynamic-field-kit/core";
|
|
504
|
+
import React6, { useCallback as useCallback3 } from "react";
|
|
140
505
|
|
|
141
506
|
// src/components/FieldGroupInput.tsx
|
|
142
507
|
import {
|
|
@@ -148,7 +513,8 @@ import { useCallback as useCallback2 } from "react";
|
|
|
148
513
|
|
|
149
514
|
// src/components/MultiFieldInput.tsx
|
|
150
515
|
import {
|
|
151
|
-
applyComputedValues
|
|
516
|
+
applyComputedValues,
|
|
517
|
+
validateFields
|
|
152
518
|
} from "@dynamic-field-kit/core";
|
|
153
519
|
import {
|
|
154
520
|
useCallback,
|
|
@@ -157,7 +523,7 @@ import {
|
|
|
157
523
|
useRef,
|
|
158
524
|
useState as useState2
|
|
159
525
|
} from "react";
|
|
160
|
-
import { jsx as
|
|
526
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
161
527
|
function resolveLayout(layout) {
|
|
162
528
|
if (!layout) {
|
|
163
529
|
return { type: "column", config: {} };
|
|
@@ -171,19 +537,27 @@ var MultiFieldInput = ({
|
|
|
171
537
|
fieldDescriptions,
|
|
172
538
|
properties,
|
|
173
539
|
onChange,
|
|
174
|
-
layout
|
|
540
|
+
layout,
|
|
541
|
+
rootData,
|
|
542
|
+
onValidityChange,
|
|
543
|
+
onBlurField
|
|
175
544
|
}) => {
|
|
176
545
|
const [data, setData] = useState2({});
|
|
546
|
+
const [touchedFields, setTouchedFields] = useState2(
|
|
547
|
+
{}
|
|
548
|
+
);
|
|
549
|
+
const initialPropertiesRef = useRef(properties ?? {});
|
|
177
550
|
useEffect2(() => {
|
|
178
551
|
if (properties) {
|
|
179
|
-
setData(applyComputedValues(fieldDescriptions, properties));
|
|
552
|
+
setData(applyComputedValues(fieldDescriptions, properties, rootData));
|
|
180
553
|
}
|
|
181
554
|
}, [properties]);
|
|
555
|
+
const effectiveRoot = rootData ?? data;
|
|
182
556
|
const visibleFields = useMemo2(
|
|
183
557
|
() => fieldDescriptions.filter(
|
|
184
|
-
(f) => !f.appearCondition || f.appearCondition(data)
|
|
558
|
+
(f) => !f.appearCondition || f.appearCondition(data, effectiveRoot)
|
|
185
559
|
),
|
|
186
|
-
[fieldDescriptions, data]
|
|
560
|
+
[fieldDescriptions, data, effectiveRoot]
|
|
187
561
|
);
|
|
188
562
|
const dataRef = useRef(data);
|
|
189
563
|
dataRef.current = data;
|
|
@@ -191,25 +565,46 @@ var MultiFieldInput = ({
|
|
|
191
565
|
onChangeRef.current = onChange;
|
|
192
566
|
const fieldDescriptionsRef = useRef(fieldDescriptions);
|
|
193
567
|
fieldDescriptionsRef.current = fieldDescriptions;
|
|
568
|
+
const rootDataRef = useRef(rootData);
|
|
569
|
+
rootDataRef.current = rootData;
|
|
570
|
+
const onValidityChangeRef = useRef(onValidityChange);
|
|
571
|
+
onValidityChangeRef.current = onValidityChange;
|
|
572
|
+
const onBlurFieldRef = useRef(onBlurField);
|
|
573
|
+
onBlurFieldRef.current = onBlurField;
|
|
574
|
+
useEffect2(() => {
|
|
575
|
+
onValidityChangeRef.current?.(
|
|
576
|
+
validateFields(fieldDescriptions, data, rootData)
|
|
577
|
+
);
|
|
578
|
+
}, [data, fieldDescriptions, rootData]);
|
|
194
579
|
const handleValueChangeField = useCallback((value, key) => {
|
|
195
|
-
const
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
580
|
+
const merged = { ...dataRef.current, [key]: value };
|
|
581
|
+
const next = applyComputedValues(
|
|
582
|
+
fieldDescriptionsRef.current,
|
|
583
|
+
merged,
|
|
584
|
+
rootDataRef.current
|
|
585
|
+
);
|
|
199
586
|
dataRef.current = next;
|
|
200
587
|
setData(next);
|
|
201
588
|
onChangeRef.current?.(next);
|
|
202
589
|
}, []);
|
|
590
|
+
const handleBlurField = useCallback((key) => {
|
|
591
|
+
setTouchedFields((prev) => prev[key] ? prev : { ...prev, [key]: true });
|
|
592
|
+
onBlurFieldRef.current?.(key);
|
|
593
|
+
}, []);
|
|
203
594
|
const { type, config } = resolveLayout(layout);
|
|
204
595
|
const Layout = layoutRegistry.get(type);
|
|
205
596
|
if (!Layout) {
|
|
206
597
|
throw new Error(`Unknown layout: ${type}`);
|
|
207
598
|
}
|
|
208
|
-
return /* @__PURE__ */
|
|
599
|
+
return /* @__PURE__ */ jsx5(Layout, { config, children: visibleFields.map((f) => /* @__PURE__ */ jsx5(
|
|
209
600
|
FieldInput_default,
|
|
210
601
|
{
|
|
211
602
|
fieldDescription: f,
|
|
212
603
|
renderInfos: data,
|
|
604
|
+
rootData: effectiveRoot,
|
|
605
|
+
touched: Boolean(touchedFields[f.name]),
|
|
606
|
+
dirty: data[f.name] !== initialPropertiesRef.current[f.name],
|
|
607
|
+
onBlurField: handleBlurField,
|
|
213
608
|
onValueChangeField: handleValueChangeField
|
|
214
609
|
},
|
|
215
610
|
f.name
|
|
@@ -218,9 +613,24 @@ var MultiFieldInput = ({
|
|
|
218
613
|
var MultiFieldInput_default = MultiFieldInput;
|
|
219
614
|
|
|
220
615
|
// src/components/FieldGroupInput.tsx
|
|
221
|
-
import { jsx as
|
|
222
|
-
var FieldGroupInput = ({
|
|
223
|
-
|
|
616
|
+
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
617
|
+
var FieldGroupInput = ({
|
|
618
|
+
fieldDescription,
|
|
619
|
+
items,
|
|
620
|
+
rootData,
|
|
621
|
+
onChange
|
|
622
|
+
}) => {
|
|
623
|
+
const {
|
|
624
|
+
fields = [],
|
|
625
|
+
label,
|
|
626
|
+
addLabel,
|
|
627
|
+
removeLabel,
|
|
628
|
+
keyField
|
|
629
|
+
} = fieldDescription;
|
|
630
|
+
const itemKey = (item, index) => keyField ? item[keyField] ?? index : index;
|
|
631
|
+
const addText = addLabel ?? "Add";
|
|
632
|
+
const removeText = removeLabel ?? "Remove";
|
|
633
|
+
const groupName = label ?? fieldDescription.name;
|
|
224
634
|
const handleItemChange = useCallback2(
|
|
225
635
|
(index, next) => {
|
|
226
636
|
const nextItems = items.slice();
|
|
@@ -244,41 +654,44 @@ var FieldGroupInput = ({ fieldDescription, items, onChange }) => {
|
|
|
244
654
|
},
|
|
245
655
|
[fieldDescription, items, onChange]
|
|
246
656
|
);
|
|
247
|
-
return /* @__PURE__ */
|
|
248
|
-
label && /* @__PURE__ */
|
|
249
|
-
items.map((item, index) => /* @__PURE__ */
|
|
657
|
+
return /* @__PURE__ */ jsxs4("div", { className: fieldDescription.className, children: [
|
|
658
|
+
label && /* @__PURE__ */ jsx6("div", { children: label }),
|
|
659
|
+
items.map((item, index) => /* @__PURE__ */ jsxs4(
|
|
250
660
|
"div",
|
|
251
661
|
{
|
|
252
662
|
style: { display: "flex", alignItems: "flex-start", gap: 8 },
|
|
253
663
|
children: [
|
|
254
|
-
/* @__PURE__ */
|
|
664
|
+
/* @__PURE__ */ jsx6("div", { style: { flex: 1 }, children: /* @__PURE__ */ jsx6(
|
|
255
665
|
MultiFieldInput_default,
|
|
256
666
|
{
|
|
257
667
|
fieldDescriptions: fields,
|
|
258
668
|
properties: item,
|
|
669
|
+
rootData,
|
|
259
670
|
onChange: (next) => handleItemChange(index, next)
|
|
260
671
|
}
|
|
261
672
|
) }),
|
|
262
|
-
/* @__PURE__ */
|
|
673
|
+
/* @__PURE__ */ jsx6(
|
|
263
674
|
"button",
|
|
264
675
|
{
|
|
265
676
|
type: "button",
|
|
677
|
+
"aria-label": `${removeText} ${groupName} ${index + 1}`,
|
|
266
678
|
onClick: () => handleRemove(index),
|
|
267
679
|
disabled: !canRemoveGroupItem(fieldDescription, items),
|
|
268
|
-
children:
|
|
680
|
+
children: removeText
|
|
269
681
|
}
|
|
270
682
|
)
|
|
271
683
|
]
|
|
272
684
|
},
|
|
273
|
-
index
|
|
685
|
+
itemKey(item, index)
|
|
274
686
|
)),
|
|
275
|
-
/* @__PURE__ */
|
|
687
|
+
/* @__PURE__ */ jsx6(
|
|
276
688
|
"button",
|
|
277
689
|
{
|
|
278
690
|
type: "button",
|
|
691
|
+
"aria-label": `${addText} ${groupName}`,
|
|
279
692
|
onClick: handleAdd,
|
|
280
693
|
disabled: !canAddGroupItem(fieldDescription, items),
|
|
281
|
-
children:
|
|
694
|
+
children: addText
|
|
282
695
|
}
|
|
283
696
|
)
|
|
284
697
|
] });
|
|
@@ -286,51 +699,422 @@ var FieldGroupInput = ({ fieldDescription, items, onChange }) => {
|
|
|
286
699
|
var FieldGroupInput_default = FieldGroupInput;
|
|
287
700
|
|
|
288
701
|
// src/components/FieldInput.tsx
|
|
289
|
-
import { jsx as
|
|
702
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
290
703
|
var FieldInputInner = ({
|
|
291
704
|
fieldDescription,
|
|
292
705
|
renderInfos,
|
|
706
|
+
rootData,
|
|
707
|
+
touched,
|
|
708
|
+
dirty,
|
|
709
|
+
onBlurField,
|
|
293
710
|
onValueChangeField
|
|
294
711
|
}) => {
|
|
295
|
-
const { name, type, label,
|
|
712
|
+
const { name, type, label, className, description, props, fields, required } = fieldDescription;
|
|
296
713
|
const handleChange = useCallback3(
|
|
297
714
|
(v) => onValueChangeField(v, name),
|
|
298
715
|
[onValueChangeField, name]
|
|
299
716
|
);
|
|
717
|
+
const handleBlur = useCallback3(
|
|
718
|
+
() => onBlurField?.(name),
|
|
719
|
+
[onBlurField, name]
|
|
720
|
+
);
|
|
300
721
|
if (fields) {
|
|
301
722
|
const items = Array.isArray(renderInfos[name]) ? renderInfos[name] : [];
|
|
302
|
-
return /* @__PURE__ */
|
|
723
|
+
return /* @__PURE__ */ jsx7(
|
|
303
724
|
FieldGroupInput_default,
|
|
304
725
|
{
|
|
305
726
|
fieldDescription,
|
|
306
727
|
items,
|
|
728
|
+
rootData,
|
|
307
729
|
onChange: handleChange
|
|
308
730
|
}
|
|
309
731
|
);
|
|
310
732
|
}
|
|
311
|
-
|
|
733
|
+
const effectiveDisabled = resolveDisabled(
|
|
734
|
+
fieldDescription,
|
|
735
|
+
renderInfos,
|
|
736
|
+
rootData
|
|
737
|
+
);
|
|
738
|
+
const readOnly = resolveReadOnly(fieldDescription, renderInfos, rootData);
|
|
739
|
+
const resolvedOptionsList = resolveOptions(
|
|
740
|
+
fieldDescription,
|
|
741
|
+
renderInfos,
|
|
742
|
+
rootData
|
|
743
|
+
);
|
|
744
|
+
const errors = effectiveDisabled ? [] : validateField(fieldDescription, renderInfos[name], renderInfos, rootData);
|
|
745
|
+
const error = errors.length > 0 ? errors : void 0;
|
|
746
|
+
const fieldId = `dfk-field-${name}`;
|
|
747
|
+
return /* @__PURE__ */ jsx7(
|
|
312
748
|
DynamicInput_default,
|
|
313
749
|
{
|
|
750
|
+
id: fieldId,
|
|
314
751
|
type,
|
|
315
752
|
label,
|
|
316
753
|
value: renderInfos[name],
|
|
317
|
-
options,
|
|
754
|
+
options: resolvedOptionsList,
|
|
318
755
|
className,
|
|
319
756
|
description,
|
|
320
|
-
|
|
757
|
+
disabled: effectiveDisabled,
|
|
758
|
+
readOnly,
|
|
759
|
+
required,
|
|
760
|
+
touched,
|
|
761
|
+
dirty,
|
|
762
|
+
error,
|
|
763
|
+
ariaInvalid: Boolean(error),
|
|
764
|
+
ariaRequired: Boolean(required),
|
|
765
|
+
extraProps: props,
|
|
766
|
+
onChange: handleChange,
|
|
767
|
+
onBlur: handleBlur
|
|
321
768
|
}
|
|
322
769
|
);
|
|
323
770
|
};
|
|
324
|
-
var FieldInput =
|
|
771
|
+
var FieldInput = /* @__PURE__ */ React6.memo(FieldInputInner, (prev, next) => {
|
|
325
772
|
const name = prev.fieldDescription.name;
|
|
326
|
-
return prev.fieldDescription === next.fieldDescription && prev.onValueChangeField === next.onValueChangeField && prev.renderInfos[name] === next.renderInfos[name];
|
|
773
|
+
return prev.fieldDescription === next.fieldDescription && prev.onValueChangeField === next.onValueChangeField && prev.onBlurField === next.onBlurField && prev.rootData === next.rootData && prev.touched === next.touched && prev.dirty === next.dirty && prev.renderInfos[name] === next.renderInfos[name];
|
|
327
774
|
});
|
|
328
775
|
var FieldInput_default = FieldInput;
|
|
776
|
+
|
|
777
|
+
// src/components/DynamicFormDevTools.tsx
|
|
778
|
+
import { useState as useState3 } from "react";
|
|
779
|
+
import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
780
|
+
var DynamicFormDevTools = ({
|
|
781
|
+
data,
|
|
782
|
+
errors = {},
|
|
783
|
+
touched = {},
|
|
784
|
+
isDirty = false,
|
|
785
|
+
fields = [],
|
|
786
|
+
position = "bottom-right"
|
|
787
|
+
}) => {
|
|
788
|
+
const [isOpen, setIsOpen] = useState3(false);
|
|
789
|
+
const [activeTab, setActiveTab] = useState3("data");
|
|
790
|
+
const errorCount = Object.keys(errors).length;
|
|
791
|
+
const posStyle = position === "bottom-left" ? { left: "16px", bottom: "16px" } : { right: "16px", bottom: "16px" };
|
|
792
|
+
if (!isOpen) {
|
|
793
|
+
return /* @__PURE__ */ jsxs5(
|
|
794
|
+
"button",
|
|
795
|
+
{
|
|
796
|
+
type: "button",
|
|
797
|
+
onClick: () => setIsOpen(true),
|
|
798
|
+
style: {
|
|
799
|
+
position: "fixed",
|
|
800
|
+
...posStyle,
|
|
801
|
+
zIndex: 99999,
|
|
802
|
+
background: "#1e293b",
|
|
803
|
+
color: "#f8fafc",
|
|
804
|
+
border: "1px solid #334155",
|
|
805
|
+
borderRadius: "20px",
|
|
806
|
+
padding: "8px 14px",
|
|
807
|
+
fontSize: "12px",
|
|
808
|
+
fontWeight: 600,
|
|
809
|
+
cursor: "pointer",
|
|
810
|
+
boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
|
|
811
|
+
display: "flex",
|
|
812
|
+
alignItems: "center",
|
|
813
|
+
gap: "6px"
|
|
814
|
+
},
|
|
815
|
+
children: [
|
|
816
|
+
/* @__PURE__ */ jsx8("span", { children: "\u{1F50D} DevTools" }),
|
|
817
|
+
errorCount > 0 && /* @__PURE__ */ jsx8(
|
|
818
|
+
"span",
|
|
819
|
+
{
|
|
820
|
+
style: {
|
|
821
|
+
background: "#ef4444",
|
|
822
|
+
color: "#fff",
|
|
823
|
+
borderRadius: "10px",
|
|
824
|
+
padding: "2px 6px",
|
|
825
|
+
fontSize: "10px"
|
|
826
|
+
},
|
|
827
|
+
children: errorCount
|
|
828
|
+
}
|
|
829
|
+
)
|
|
830
|
+
]
|
|
831
|
+
}
|
|
832
|
+
);
|
|
833
|
+
}
|
|
834
|
+
return /* @__PURE__ */ jsxs5(
|
|
835
|
+
"div",
|
|
836
|
+
{
|
|
837
|
+
style: {
|
|
838
|
+
position: "fixed",
|
|
839
|
+
...posStyle,
|
|
840
|
+
zIndex: 99999,
|
|
841
|
+
width: "360px",
|
|
842
|
+
maxHeight: "420px",
|
|
843
|
+
background: "#0f172a",
|
|
844
|
+
color: "#f8fafc",
|
|
845
|
+
border: "1px solid #334155",
|
|
846
|
+
borderRadius: "12px",
|
|
847
|
+
boxShadow: "0 10px 25px rgba(0,0,0,0.3)",
|
|
848
|
+
display: "flex",
|
|
849
|
+
flexDirection: "column",
|
|
850
|
+
fontFamily: "monospace, sans-serif",
|
|
851
|
+
fontSize: "12px",
|
|
852
|
+
overflow: "hidden"
|
|
853
|
+
},
|
|
854
|
+
children: [
|
|
855
|
+
/* @__PURE__ */ jsxs5(
|
|
856
|
+
"div",
|
|
857
|
+
{
|
|
858
|
+
style: {
|
|
859
|
+
padding: "10px 14px",
|
|
860
|
+
background: "#1e293b",
|
|
861
|
+
display: "flex",
|
|
862
|
+
justifyContent: "space-between",
|
|
863
|
+
alignItems: "center",
|
|
864
|
+
borderBottom: "1px solid #334155"
|
|
865
|
+
},
|
|
866
|
+
children: [
|
|
867
|
+
/* @__PURE__ */ jsx8("span", { style: { fontWeight: "bold", color: "#38bdf8" }, children: "\u{1F6E0}\uFE0F Form DevTools" }),
|
|
868
|
+
/* @__PURE__ */ jsx8(
|
|
869
|
+
"button",
|
|
870
|
+
{
|
|
871
|
+
type: "button",
|
|
872
|
+
onClick: () => setIsOpen(false),
|
|
873
|
+
style: {
|
|
874
|
+
background: "transparent",
|
|
875
|
+
border: "none",
|
|
876
|
+
color: "#94a3b8",
|
|
877
|
+
fontSize: "14px",
|
|
878
|
+
cursor: "pointer"
|
|
879
|
+
},
|
|
880
|
+
children: "\u2715"
|
|
881
|
+
}
|
|
882
|
+
)
|
|
883
|
+
]
|
|
884
|
+
}
|
|
885
|
+
),
|
|
886
|
+
/* @__PURE__ */ jsx8(
|
|
887
|
+
"div",
|
|
888
|
+
{
|
|
889
|
+
style: {
|
|
890
|
+
display: "flex",
|
|
891
|
+
background: "#1e293b",
|
|
892
|
+
borderBottom: "1px solid #334155"
|
|
893
|
+
},
|
|
894
|
+
children: ["data", "errors", "meta", "fields"].map((tab) => /* @__PURE__ */ jsxs5(
|
|
895
|
+
"button",
|
|
896
|
+
{
|
|
897
|
+
type: "button",
|
|
898
|
+
onClick: () => setActiveTab(tab),
|
|
899
|
+
style: {
|
|
900
|
+
flex: 1,
|
|
901
|
+
padding: "6px 0",
|
|
902
|
+
background: activeTab === tab ? "#0f172a" : "transparent",
|
|
903
|
+
color: activeTab === tab ? "#38bdf8" : "#94a3b8",
|
|
904
|
+
border: "none",
|
|
905
|
+
cursor: "pointer",
|
|
906
|
+
textTransform: "capitalize",
|
|
907
|
+
fontSize: "11px",
|
|
908
|
+
fontWeight: activeTab === tab ? "bold" : "normal"
|
|
909
|
+
},
|
|
910
|
+
children: [
|
|
911
|
+
tab,
|
|
912
|
+
" ",
|
|
913
|
+
tab === "errors" && errorCount > 0 ? `(${errorCount})` : ""
|
|
914
|
+
]
|
|
915
|
+
},
|
|
916
|
+
tab
|
|
917
|
+
))
|
|
918
|
+
}
|
|
919
|
+
),
|
|
920
|
+
/* @__PURE__ */ jsxs5("div", { style: { padding: "12px", overflowY: "auto", flex: 1 }, children: [
|
|
921
|
+
activeTab === "data" && /* @__PURE__ */ jsx8(
|
|
922
|
+
"pre",
|
|
923
|
+
{
|
|
924
|
+
style: {
|
|
925
|
+
margin: 0,
|
|
926
|
+
whiteSpace: "pre-wrap",
|
|
927
|
+
wordBreak: "break-all",
|
|
928
|
+
color: "#a7f3d0"
|
|
929
|
+
},
|
|
930
|
+
children: JSON.stringify(data, null, 2)
|
|
931
|
+
}
|
|
932
|
+
),
|
|
933
|
+
activeTab === "errors" && /* @__PURE__ */ jsx8("div", { children: Object.keys(errors).length === 0 ? /* @__PURE__ */ jsx8("span", { style: { color: "#4ade80" }, children: "\u2713 No validation errors" }) : Object.entries(errors).map(([field, msgs]) => /* @__PURE__ */ jsxs5("div", { style: { marginBottom: "8px" }, children: [
|
|
934
|
+
/* @__PURE__ */ jsxs5("span", { style: { color: "#f87171", fontWeight: "bold" }, children: [
|
|
935
|
+
field,
|
|
936
|
+
":"
|
|
937
|
+
] }),
|
|
938
|
+
/* @__PURE__ */ jsx8("ul", { style: { margin: "4px 0 0 16px", padding: 0 }, children: msgs.map((m, i) => /* @__PURE__ */ jsx8("li", { style: { color: "#fca5a5" }, children: m }, i)) })
|
|
939
|
+
] }, field)) }),
|
|
940
|
+
activeTab === "meta" && /* @__PURE__ */ jsxs5("div", { children: [
|
|
941
|
+
/* @__PURE__ */ jsxs5("div", { style: { marginBottom: "6px" }, children: [
|
|
942
|
+
/* @__PURE__ */ jsx8("span", { style: { color: "#94a3b8" }, children: "isDirty: " }),
|
|
943
|
+
/* @__PURE__ */ jsx8("span", { style: { color: isDirty ? "#facc15" : "#4ade80" }, children: String(isDirty) })
|
|
944
|
+
] }),
|
|
945
|
+
/* @__PURE__ */ jsxs5("div", { children: [
|
|
946
|
+
/* @__PURE__ */ jsx8("span", { style: { color: "#94a3b8" }, children: "Touched Fields:" }),
|
|
947
|
+
/* @__PURE__ */ jsx8("pre", { style: { margin: "4px 0 0 0", color: "#cbd5e1" }, children: JSON.stringify(touched, null, 2) })
|
|
948
|
+
] })
|
|
949
|
+
] }),
|
|
950
|
+
activeTab === "fields" && /* @__PURE__ */ jsx8("div", { children: fields.length === 0 ? /* @__PURE__ */ jsx8("span", { style: { color: "#94a3b8" }, children: "No field descriptions passed" }) : fields.map((f) => /* @__PURE__ */ jsxs5(
|
|
951
|
+
"div",
|
|
952
|
+
{
|
|
953
|
+
style: {
|
|
954
|
+
padding: "6px",
|
|
955
|
+
marginBottom: "6px",
|
|
956
|
+
background: "#1e293b",
|
|
957
|
+
borderRadius: "4px"
|
|
958
|
+
},
|
|
959
|
+
children: [
|
|
960
|
+
/* @__PURE__ */ jsx8("div", { style: { color: "#38bdf8", fontWeight: "bold" }, children: f.name }),
|
|
961
|
+
/* @__PURE__ */ jsxs5("div", { style: { color: "#94a3b8", fontSize: "10px" }, children: [
|
|
962
|
+
"type: ",
|
|
963
|
+
f.type,
|
|
964
|
+
" | required: ",
|
|
965
|
+
String(Boolean(f.required))
|
|
966
|
+
] })
|
|
967
|
+
]
|
|
968
|
+
},
|
|
969
|
+
f.name
|
|
970
|
+
)) })
|
|
971
|
+
] })
|
|
972
|
+
]
|
|
973
|
+
}
|
|
974
|
+
);
|
|
975
|
+
};
|
|
976
|
+
|
|
977
|
+
// src/useDynamicForm.ts
|
|
978
|
+
import {
|
|
979
|
+
applyComputedValues as applyComputedValues2,
|
|
980
|
+
validateFields as validateFields2
|
|
981
|
+
} from "@dynamic-field-kit/core";
|
|
982
|
+
import { useCallback as useCallback4, useState as useState4 } from "react";
|
|
983
|
+
function useDynamicForm({
|
|
984
|
+
fields,
|
|
985
|
+
initialValues = {},
|
|
986
|
+
validateOnBlur = true,
|
|
987
|
+
validateOnChange = false
|
|
988
|
+
}) {
|
|
989
|
+
const [data, setData] = useState4(
|
|
990
|
+
() => applyComputedValues2(fields, initialValues)
|
|
991
|
+
);
|
|
992
|
+
const [errors, setErrors] = useState4({});
|
|
993
|
+
const [isDirty, setIsDirty] = useState4(false);
|
|
994
|
+
const [touched, setTouched] = useState4({});
|
|
995
|
+
const [isSubmitting, setIsSubmitting] = useState4(false);
|
|
996
|
+
const [isSubmitted, setIsSubmitted] = useState4(false);
|
|
997
|
+
const validate = useCallback4(() => {
|
|
998
|
+
const res = validateFields2(fields, data);
|
|
999
|
+
setErrors(res.errors);
|
|
1000
|
+
return res.valid;
|
|
1001
|
+
}, [fields, data]);
|
|
1002
|
+
const handleChange = useCallback4(
|
|
1003
|
+
(newData) => {
|
|
1004
|
+
const next = applyComputedValues2(fields, newData);
|
|
1005
|
+
setData(next);
|
|
1006
|
+
setIsDirty(true);
|
|
1007
|
+
if (validateOnChange) {
|
|
1008
|
+
const res = validateFields2(fields, next);
|
|
1009
|
+
setErrors(res.errors);
|
|
1010
|
+
}
|
|
1011
|
+
},
|
|
1012
|
+
[fields, validateOnChange]
|
|
1013
|
+
);
|
|
1014
|
+
const setFieldValue = useCallback4(
|
|
1015
|
+
(name, value) => {
|
|
1016
|
+
handleChange({ ...data, [name]: value });
|
|
1017
|
+
},
|
|
1018
|
+
[data, handleChange]
|
|
1019
|
+
);
|
|
1020
|
+
const setFieldTouched = useCallback4((name, isTouched = true) => {
|
|
1021
|
+
setTouched((prev) => ({ ...prev, [name]: isTouched }));
|
|
1022
|
+
}, []);
|
|
1023
|
+
const handleBlur = useCallback4(
|
|
1024
|
+
(fieldName) => {
|
|
1025
|
+
setFieldTouched(fieldName, true);
|
|
1026
|
+
if (validateOnBlur) {
|
|
1027
|
+
const res = validateFields2(fields, data);
|
|
1028
|
+
setErrors(res.errors);
|
|
1029
|
+
}
|
|
1030
|
+
},
|
|
1031
|
+
[fields, data, validateOnBlur, setFieldTouched]
|
|
1032
|
+
);
|
|
1033
|
+
const reset = useCallback4(
|
|
1034
|
+
(newValues) => {
|
|
1035
|
+
const seed = newValues ?? initialValues;
|
|
1036
|
+
const next = applyComputedValues2(fields, seed);
|
|
1037
|
+
setData(next);
|
|
1038
|
+
setErrors({});
|
|
1039
|
+
setIsDirty(false);
|
|
1040
|
+
setTouched({});
|
|
1041
|
+
setIsSubmitting(false);
|
|
1042
|
+
setIsSubmitted(false);
|
|
1043
|
+
},
|
|
1044
|
+
[fields, initialValues]
|
|
1045
|
+
);
|
|
1046
|
+
const handleSubmit = useCallback4(
|
|
1047
|
+
(onValid, onInvalid) => async (e) => {
|
|
1048
|
+
if (e && typeof e.preventDefault === "function") {
|
|
1049
|
+
e.preventDefault();
|
|
1050
|
+
}
|
|
1051
|
+
setIsSubmitting(true);
|
|
1052
|
+
try {
|
|
1053
|
+
const res = validateFields2(fields, data);
|
|
1054
|
+
setErrors(res.errors);
|
|
1055
|
+
setIsSubmitted(true);
|
|
1056
|
+
if (res.valid) {
|
|
1057
|
+
await onValid(data);
|
|
1058
|
+
} else if (onInvalid) {
|
|
1059
|
+
onInvalid(res.errors);
|
|
1060
|
+
}
|
|
1061
|
+
} finally {
|
|
1062
|
+
setIsSubmitting(false);
|
|
1063
|
+
}
|
|
1064
|
+
},
|
|
1065
|
+
[fields, data]
|
|
1066
|
+
);
|
|
1067
|
+
const isValid = Object.keys(errors).length === 0;
|
|
1068
|
+
return {
|
|
1069
|
+
data,
|
|
1070
|
+
errors,
|
|
1071
|
+
isValid,
|
|
1072
|
+
isDirty,
|
|
1073
|
+
isSubmitting,
|
|
1074
|
+
isSubmitted,
|
|
1075
|
+
touched,
|
|
1076
|
+
setData,
|
|
1077
|
+
setFieldValue,
|
|
1078
|
+
setFieldTouched,
|
|
1079
|
+
handleChange,
|
|
1080
|
+
handleBlur,
|
|
1081
|
+
reset,
|
|
1082
|
+
validate,
|
|
1083
|
+
handleSubmit
|
|
1084
|
+
};
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
// src/index.ts
|
|
1088
|
+
import { FieldRegistry } from "@dynamic-field-kit/core";
|
|
1089
|
+
import {
|
|
1090
|
+
validateField as validateField2,
|
|
1091
|
+
validateFieldAsync,
|
|
1092
|
+
validateFields as validateFields3,
|
|
1093
|
+
validateFieldsAsync,
|
|
1094
|
+
resolveDisabled as resolveDisabled2,
|
|
1095
|
+
resolveReadOnly as resolveReadOnly2,
|
|
1096
|
+
resolveOptions as resolveOptions2,
|
|
1097
|
+
validators
|
|
1098
|
+
} from "@dynamic-field-kit/core";
|
|
329
1099
|
export {
|
|
1100
|
+
DynamicFormDevTools,
|
|
330
1101
|
DynamicInput_default as DynamicInput,
|
|
331
1102
|
FieldInput_default as FieldInput,
|
|
1103
|
+
FieldRegistry,
|
|
1104
|
+
FieldRegistryProvider,
|
|
332
1105
|
MultiFieldInput_default as MultiFieldInput,
|
|
1106
|
+
defaultRenderersMap,
|
|
333
1107
|
fieldRegistry,
|
|
334
|
-
|
|
1108
|
+
getDefaultRenderer,
|
|
1109
|
+
layoutRegistry,
|
|
1110
|
+
resolveDisabled2 as resolveDisabled,
|
|
1111
|
+
resolveOptions2 as resolveOptions,
|
|
1112
|
+
resolveReadOnly2 as resolveReadOnly,
|
|
1113
|
+
useDynamicForm,
|
|
1114
|
+
useFieldRegistry,
|
|
1115
|
+
validateField2 as validateField,
|
|
1116
|
+
validateFieldAsync,
|
|
1117
|
+
validateFields3 as validateFields,
|
|
1118
|
+
validateFieldsAsync,
|
|
1119
|
+
validators
|
|
335
1120
|
};
|
|
336
|
-
//# sourceMappingURL=index.mjs.map
|