@dynamic-field-kit/react 1.4.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 +107 -2
- package/dist/index.d.mts +50 -6
- package/dist/index.d.ts +50 -6
- package/dist/index.js +650 -31
- package/dist/index.mjs +641 -23
- package/package.json +31 -18
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
package/dist/index.js
CHANGED
|
@@ -30,22 +30,26 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
DynamicFormDevTools: () => DynamicFormDevTools,
|
|
33
34
|
DynamicInput: () => DynamicInput_default,
|
|
34
35
|
FieldInput: () => FieldInput_default,
|
|
35
|
-
FieldRegistry: () =>
|
|
36
|
+
FieldRegistry: () => import_core6.FieldRegistry,
|
|
36
37
|
FieldRegistryProvider: () => FieldRegistryProvider,
|
|
37
38
|
MultiFieldInput: () => MultiFieldInput_default,
|
|
39
|
+
defaultRenderersMap: () => defaultRenderersMap,
|
|
38
40
|
fieldRegistry: () => fieldRegistry,
|
|
41
|
+
getDefaultRenderer: () => getDefaultRenderer,
|
|
39
42
|
layoutRegistry: () => layoutRegistry,
|
|
40
|
-
resolveDisabled: () =>
|
|
41
|
-
resolveOptions: () =>
|
|
42
|
-
resolveReadOnly: () =>
|
|
43
|
+
resolveDisabled: () => import_core7.resolveDisabled,
|
|
44
|
+
resolveOptions: () => import_core7.resolveOptions,
|
|
45
|
+
resolveReadOnly: () => import_core7.resolveReadOnly,
|
|
46
|
+
useDynamicForm: () => useDynamicForm,
|
|
43
47
|
useFieldRegistry: () => useFieldRegistry,
|
|
44
|
-
validateField: () =>
|
|
45
|
-
validateFieldAsync: () =>
|
|
46
|
-
validateFields: () =>
|
|
47
|
-
validateFieldsAsync: () =>
|
|
48
|
-
validators: () =>
|
|
48
|
+
validateField: () => import_core7.validateField,
|
|
49
|
+
validateFieldAsync: () => import_core7.validateFieldAsync,
|
|
50
|
+
validateFields: () => import_core7.validateFields,
|
|
51
|
+
validateFieldsAsync: () => import_core7.validateFieldsAsync,
|
|
52
|
+
validators: () => import_core7.validators
|
|
49
53
|
});
|
|
50
54
|
module.exports = __toCommonJS(index_exports);
|
|
51
55
|
|
|
@@ -164,6 +168,307 @@ layoutRegistry.register("responsive", ({ children, config }) => {
|
|
|
164
168
|
// src/components/DynamicInput.tsx
|
|
165
169
|
var import_react3 = __toESM(require("react"));
|
|
166
170
|
|
|
171
|
+
// src/defaultRenderers.tsx
|
|
172
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
173
|
+
var DefaultTextRenderer = ({
|
|
174
|
+
value,
|
|
175
|
+
onValueChange,
|
|
176
|
+
onBlur,
|
|
177
|
+
disabled,
|
|
178
|
+
readOnly,
|
|
179
|
+
required,
|
|
180
|
+
placeholder,
|
|
181
|
+
id,
|
|
182
|
+
className,
|
|
183
|
+
ariaInvalid,
|
|
184
|
+
ariaDescribedBy,
|
|
185
|
+
ariaRequired,
|
|
186
|
+
inputType = "text"
|
|
187
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
188
|
+
"input",
|
|
189
|
+
{
|
|
190
|
+
type: inputType,
|
|
191
|
+
id,
|
|
192
|
+
className,
|
|
193
|
+
value: value ?? "",
|
|
194
|
+
onChange: (e) => onValueChange?.(e.target.value),
|
|
195
|
+
onBlur,
|
|
196
|
+
disabled,
|
|
197
|
+
readOnly,
|
|
198
|
+
required,
|
|
199
|
+
placeholder,
|
|
200
|
+
"aria-invalid": ariaInvalid,
|
|
201
|
+
"aria-describedby": ariaDescribedBy,
|
|
202
|
+
"aria-required": ariaRequired
|
|
203
|
+
}
|
|
204
|
+
);
|
|
205
|
+
var DefaultNumberRenderer = ({
|
|
206
|
+
value,
|
|
207
|
+
onValueChange,
|
|
208
|
+
onBlur,
|
|
209
|
+
disabled,
|
|
210
|
+
readOnly,
|
|
211
|
+
required,
|
|
212
|
+
placeholder,
|
|
213
|
+
id,
|
|
214
|
+
className,
|
|
215
|
+
ariaInvalid,
|
|
216
|
+
ariaDescribedBy,
|
|
217
|
+
ariaRequired
|
|
218
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
219
|
+
"input",
|
|
220
|
+
{
|
|
221
|
+
type: "number",
|
|
222
|
+
id,
|
|
223
|
+
className,
|
|
224
|
+
value: value ?? "",
|
|
225
|
+
onChange: (e) => onValueChange?.(
|
|
226
|
+
e.target.value === "" ? void 0 : Number(e.target.value)
|
|
227
|
+
),
|
|
228
|
+
onBlur,
|
|
229
|
+
disabled,
|
|
230
|
+
readOnly,
|
|
231
|
+
required,
|
|
232
|
+
placeholder,
|
|
233
|
+
"aria-invalid": ariaInvalid,
|
|
234
|
+
"aria-describedby": ariaDescribedBy,
|
|
235
|
+
"aria-required": ariaRequired
|
|
236
|
+
}
|
|
237
|
+
);
|
|
238
|
+
var DefaultPasswordRenderer = (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(DefaultTextRenderer, { ...props, inputType: "password" });
|
|
239
|
+
var DefaultEmailRenderer = (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(DefaultTextRenderer, { ...props, inputType: "email" });
|
|
240
|
+
var DefaultTextareaRenderer = ({
|
|
241
|
+
value,
|
|
242
|
+
onValueChange,
|
|
243
|
+
onBlur,
|
|
244
|
+
disabled,
|
|
245
|
+
readOnly,
|
|
246
|
+
required,
|
|
247
|
+
placeholder,
|
|
248
|
+
id,
|
|
249
|
+
className,
|
|
250
|
+
ariaInvalid,
|
|
251
|
+
ariaDescribedBy,
|
|
252
|
+
ariaRequired
|
|
253
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
254
|
+
"textarea",
|
|
255
|
+
{
|
|
256
|
+
id,
|
|
257
|
+
className,
|
|
258
|
+
value: value ?? "",
|
|
259
|
+
onChange: (e) => onValueChange?.(e.target.value),
|
|
260
|
+
onBlur,
|
|
261
|
+
disabled,
|
|
262
|
+
readOnly,
|
|
263
|
+
required,
|
|
264
|
+
placeholder,
|
|
265
|
+
"aria-invalid": ariaInvalid,
|
|
266
|
+
"aria-describedby": ariaDescribedBy,
|
|
267
|
+
"aria-required": ariaRequired
|
|
268
|
+
}
|
|
269
|
+
);
|
|
270
|
+
var DefaultCheckboxRenderer = ({
|
|
271
|
+
value,
|
|
272
|
+
onValueChange,
|
|
273
|
+
onBlur,
|
|
274
|
+
disabled,
|
|
275
|
+
readOnly,
|
|
276
|
+
required,
|
|
277
|
+
id,
|
|
278
|
+
className,
|
|
279
|
+
ariaInvalid,
|
|
280
|
+
ariaDescribedBy,
|
|
281
|
+
ariaRequired
|
|
282
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
283
|
+
"input",
|
|
284
|
+
{
|
|
285
|
+
type: "checkbox",
|
|
286
|
+
id,
|
|
287
|
+
className,
|
|
288
|
+
checked: Boolean(value),
|
|
289
|
+
onChange: (e) => onValueChange?.(e.target.checked),
|
|
290
|
+
onBlur,
|
|
291
|
+
disabled: disabled || readOnly,
|
|
292
|
+
required,
|
|
293
|
+
"aria-invalid": ariaInvalid,
|
|
294
|
+
"aria-describedby": ariaDescribedBy,
|
|
295
|
+
"aria-required": ariaRequired
|
|
296
|
+
}
|
|
297
|
+
);
|
|
298
|
+
var DefaultSelectRenderer = ({
|
|
299
|
+
value,
|
|
300
|
+
onValueChange,
|
|
301
|
+
onBlur,
|
|
302
|
+
disabled,
|
|
303
|
+
readOnly,
|
|
304
|
+
required,
|
|
305
|
+
options = [],
|
|
306
|
+
id,
|
|
307
|
+
className,
|
|
308
|
+
ariaInvalid,
|
|
309
|
+
ariaDescribedBy,
|
|
310
|
+
ariaRequired
|
|
311
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
312
|
+
"select",
|
|
313
|
+
{
|
|
314
|
+
id,
|
|
315
|
+
className,
|
|
316
|
+
value: value ?? "",
|
|
317
|
+
onChange: (e) => onValueChange?.(e.target.value),
|
|
318
|
+
onBlur,
|
|
319
|
+
disabled: disabled || readOnly,
|
|
320
|
+
required,
|
|
321
|
+
"aria-invalid": ariaInvalid,
|
|
322
|
+
"aria-describedby": ariaDescribedBy,
|
|
323
|
+
"aria-required": ariaRequired,
|
|
324
|
+
children: [
|
|
325
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "", disabled: true, children: "-- Select --" }),
|
|
326
|
+
options.map((opt, i) => {
|
|
327
|
+
const optVal = opt.value ?? opt.id ?? opt;
|
|
328
|
+
const optLabel = opt.label ?? opt.name ?? String(optVal);
|
|
329
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: String(optVal), children: String(optLabel) }, String(optVal) + i);
|
|
330
|
+
})
|
|
331
|
+
]
|
|
332
|
+
}
|
|
333
|
+
);
|
|
334
|
+
var DefaultRadioRenderer = ({
|
|
335
|
+
value,
|
|
336
|
+
onValueChange,
|
|
337
|
+
onBlur,
|
|
338
|
+
disabled,
|
|
339
|
+
readOnly,
|
|
340
|
+
required,
|
|
341
|
+
options = [],
|
|
342
|
+
id,
|
|
343
|
+
className,
|
|
344
|
+
ariaInvalid,
|
|
345
|
+
ariaDescribedBy
|
|
346
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: `dfk-radio-group ${className || ""}`, id, onBlur, children: options.map((opt, i) => {
|
|
347
|
+
const optVal = opt.value ?? opt.id ?? opt;
|
|
348
|
+
const optLabel = opt.label ?? opt.name ?? String(optVal);
|
|
349
|
+
const isChecked = String(value) === String(optVal);
|
|
350
|
+
const radioId = `${id || "radio"}-${i}`;
|
|
351
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
352
|
+
"label",
|
|
353
|
+
{
|
|
354
|
+
htmlFor: radioId,
|
|
355
|
+
style: {
|
|
356
|
+
marginRight: "12px",
|
|
357
|
+
display: "inline-flex",
|
|
358
|
+
alignItems: "center"
|
|
359
|
+
},
|
|
360
|
+
children: [
|
|
361
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
362
|
+
"input",
|
|
363
|
+
{
|
|
364
|
+
type: "radio",
|
|
365
|
+
id: radioId,
|
|
366
|
+
name: id,
|
|
367
|
+
value: String(optVal),
|
|
368
|
+
checked: isChecked,
|
|
369
|
+
onChange: () => onValueChange?.(optVal),
|
|
370
|
+
disabled: disabled || readOnly,
|
|
371
|
+
required,
|
|
372
|
+
"aria-invalid": ariaInvalid,
|
|
373
|
+
"aria-describedby": ariaDescribedBy
|
|
374
|
+
}
|
|
375
|
+
),
|
|
376
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { marginLeft: "4px" }, children: String(optLabel) })
|
|
377
|
+
]
|
|
378
|
+
},
|
|
379
|
+
String(optVal) + i
|
|
380
|
+
);
|
|
381
|
+
}) });
|
|
382
|
+
var DefaultRangeRenderer = ({
|
|
383
|
+
value,
|
|
384
|
+
onValueChange,
|
|
385
|
+
onBlur,
|
|
386
|
+
disabled,
|
|
387
|
+
readOnly,
|
|
388
|
+
required,
|
|
389
|
+
min,
|
|
390
|
+
max,
|
|
391
|
+
step,
|
|
392
|
+
id,
|
|
393
|
+
className,
|
|
394
|
+
ariaInvalid,
|
|
395
|
+
ariaDescribedBy
|
|
396
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
397
|
+
"input",
|
|
398
|
+
{
|
|
399
|
+
type: "range",
|
|
400
|
+
id,
|
|
401
|
+
className,
|
|
402
|
+
value: value ?? min ?? 0,
|
|
403
|
+
min,
|
|
404
|
+
max,
|
|
405
|
+
step,
|
|
406
|
+
onChange: (e) => onValueChange?.(Number(e.target.value)),
|
|
407
|
+
onBlur,
|
|
408
|
+
disabled: disabled || readOnly,
|
|
409
|
+
required,
|
|
410
|
+
"aria-invalid": ariaInvalid,
|
|
411
|
+
"aria-describedby": ariaDescribedBy
|
|
412
|
+
}
|
|
413
|
+
);
|
|
414
|
+
var DefaultFileRenderer = ({
|
|
415
|
+
onValueChange,
|
|
416
|
+
onBlur,
|
|
417
|
+
disabled,
|
|
418
|
+
readOnly,
|
|
419
|
+
required,
|
|
420
|
+
accept,
|
|
421
|
+
multiple,
|
|
422
|
+
id,
|
|
423
|
+
className,
|
|
424
|
+
ariaInvalid,
|
|
425
|
+
ariaDescribedBy
|
|
426
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
427
|
+
"input",
|
|
428
|
+
{
|
|
429
|
+
type: "file",
|
|
430
|
+
id,
|
|
431
|
+
className,
|
|
432
|
+
accept,
|
|
433
|
+
multiple,
|
|
434
|
+
onChange: (e) => {
|
|
435
|
+
const files = e.target.files;
|
|
436
|
+
if (!files) {
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
onValueChange?.(multiple ? Array.from(files) : files[0] || null);
|
|
440
|
+
},
|
|
441
|
+
onBlur,
|
|
442
|
+
disabled: disabled || readOnly,
|
|
443
|
+
required,
|
|
444
|
+
"aria-invalid": ariaInvalid,
|
|
445
|
+
"aria-describedby": ariaDescribedBy
|
|
446
|
+
}
|
|
447
|
+
);
|
|
448
|
+
var DefaultDateRenderer = (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(DefaultTextRenderer, { ...props, inputType: "date" });
|
|
449
|
+
var DefaultTimeRenderer = (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(DefaultTextRenderer, { ...props, inputType: "time" });
|
|
450
|
+
var DefaultDateTimeLocalRenderer = (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(DefaultTextRenderer, { ...props, inputType: "datetime-local" });
|
|
451
|
+
var DefaultSwitchRenderer = (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(DefaultCheckboxRenderer, { ...props });
|
|
452
|
+
var defaultRenderersMap = {
|
|
453
|
+
text: DefaultTextRenderer,
|
|
454
|
+
number: DefaultNumberRenderer,
|
|
455
|
+
password: DefaultPasswordRenderer,
|
|
456
|
+
email: DefaultEmailRenderer,
|
|
457
|
+
textarea: DefaultTextareaRenderer,
|
|
458
|
+
checkbox: DefaultCheckboxRenderer,
|
|
459
|
+
select: DefaultSelectRenderer,
|
|
460
|
+
radio: DefaultRadioRenderer,
|
|
461
|
+
range: DefaultRangeRenderer,
|
|
462
|
+
file: DefaultFileRenderer,
|
|
463
|
+
date: DefaultDateRenderer,
|
|
464
|
+
time: DefaultTimeRenderer,
|
|
465
|
+
"datetime-local": DefaultDateTimeLocalRenderer,
|
|
466
|
+
switch: DefaultSwitchRenderer
|
|
467
|
+
};
|
|
468
|
+
function getDefaultRenderer(type) {
|
|
469
|
+
return defaultRenderersMap[type];
|
|
470
|
+
}
|
|
471
|
+
|
|
167
472
|
// src/FieldRegistryContext.tsx
|
|
168
473
|
var import_react2 = require("react");
|
|
169
474
|
|
|
@@ -172,18 +477,18 @@ var import_core = require("@dynamic-field-kit/core");
|
|
|
172
477
|
var fieldRegistry = import_core.fieldRegistry;
|
|
173
478
|
|
|
174
479
|
// src/FieldRegistryContext.tsx
|
|
175
|
-
var
|
|
480
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
176
481
|
var FieldRegistryContext = (0, import_react2.createContext)(fieldRegistry);
|
|
177
482
|
var FieldRegistryProvider = ({
|
|
178
483
|
registry,
|
|
179
484
|
children
|
|
180
|
-
}) => /* @__PURE__ */ (0,
|
|
485
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(FieldRegistryContext.Provider, { value: registry, children });
|
|
181
486
|
function useFieldRegistry() {
|
|
182
487
|
return (0, import_react2.useContext)(FieldRegistryContext);
|
|
183
488
|
}
|
|
184
489
|
|
|
185
490
|
// src/components/DynamicInput.tsx
|
|
186
|
-
var
|
|
491
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
187
492
|
var DynamicInputInner = ({
|
|
188
493
|
type,
|
|
189
494
|
value,
|
|
@@ -207,11 +512,11 @@ var DynamicInputInner = ({
|
|
|
207
512
|
}) => {
|
|
208
513
|
const registry = useFieldRegistry();
|
|
209
514
|
const Renderer = (0, import_react3.useMemo)(
|
|
210
|
-
() => registry.get(type),
|
|
515
|
+
() => registry.get(type) || getDefaultRenderer(type),
|
|
211
516
|
[registry, type]
|
|
212
517
|
);
|
|
213
518
|
if (!Renderer) {
|
|
214
|
-
return /* @__PURE__ */ (0,
|
|
519
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
215
520
|
"Unknown field type: ",
|
|
216
521
|
type
|
|
217
522
|
] });
|
|
@@ -237,7 +542,7 @@ var DynamicInputInner = ({
|
|
|
237
542
|
ariaRequired
|
|
238
543
|
});
|
|
239
544
|
};
|
|
240
|
-
var DynamicInput = import_react3.default.memo(
|
|
545
|
+
var DynamicInput = /* @__PURE__ */ import_react3.default.memo(
|
|
241
546
|
DynamicInputInner
|
|
242
547
|
);
|
|
243
548
|
var DynamicInput_default = DynamicInput;
|
|
@@ -253,7 +558,7 @@ var import_react5 = require("react");
|
|
|
253
558
|
// src/components/MultiFieldInput.tsx
|
|
254
559
|
var import_core2 = require("@dynamic-field-kit/core");
|
|
255
560
|
var import_react4 = require("react");
|
|
256
|
-
var
|
|
561
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
257
562
|
function resolveLayout(layout) {
|
|
258
563
|
if (!layout) {
|
|
259
564
|
return { type: "column", config: {} };
|
|
@@ -269,7 +574,8 @@ var MultiFieldInput = ({
|
|
|
269
574
|
onChange,
|
|
270
575
|
layout,
|
|
271
576
|
rootData,
|
|
272
|
-
onValidityChange
|
|
577
|
+
onValidityChange,
|
|
578
|
+
onBlurField
|
|
273
579
|
}) => {
|
|
274
580
|
const [data, setData] = (0, import_react4.useState)({});
|
|
275
581
|
const [touchedFields, setTouchedFields] = (0, import_react4.useState)(
|
|
@@ -298,6 +604,8 @@ var MultiFieldInput = ({
|
|
|
298
604
|
rootDataRef.current = rootData;
|
|
299
605
|
const onValidityChangeRef = (0, import_react4.useRef)(onValidityChange);
|
|
300
606
|
onValidityChangeRef.current = onValidityChange;
|
|
607
|
+
const onBlurFieldRef = (0, import_react4.useRef)(onBlurField);
|
|
608
|
+
onBlurFieldRef.current = onBlurField;
|
|
301
609
|
(0, import_react4.useEffect)(() => {
|
|
302
610
|
onValidityChangeRef.current?.(
|
|
303
611
|
(0, import_core2.validateFields)(fieldDescriptions, data, rootData)
|
|
@@ -316,13 +624,14 @@ var MultiFieldInput = ({
|
|
|
316
624
|
}, []);
|
|
317
625
|
const handleBlurField = (0, import_react4.useCallback)((key) => {
|
|
318
626
|
setTouchedFields((prev) => prev[key] ? prev : { ...prev, [key]: true });
|
|
627
|
+
onBlurFieldRef.current?.(key);
|
|
319
628
|
}, []);
|
|
320
629
|
const { type, config } = resolveLayout(layout);
|
|
321
630
|
const Layout = layoutRegistry.get(type);
|
|
322
631
|
if (!Layout) {
|
|
323
632
|
throw new Error(`Unknown layout: ${type}`);
|
|
324
633
|
}
|
|
325
|
-
return /* @__PURE__ */ (0,
|
|
634
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Layout, { config, children: visibleFields.map((f) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
326
635
|
FieldInput_default,
|
|
327
636
|
{
|
|
328
637
|
fieldDescription: f,
|
|
@@ -339,7 +648,7 @@ var MultiFieldInput = ({
|
|
|
339
648
|
var MultiFieldInput_default = MultiFieldInput;
|
|
340
649
|
|
|
341
650
|
// src/components/FieldGroupInput.tsx
|
|
342
|
-
var
|
|
651
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
343
652
|
var FieldGroupInput = ({
|
|
344
653
|
fieldDescription,
|
|
345
654
|
items,
|
|
@@ -380,14 +689,14 @@ var FieldGroupInput = ({
|
|
|
380
689
|
},
|
|
381
690
|
[fieldDescription, items, onChange]
|
|
382
691
|
);
|
|
383
|
-
return /* @__PURE__ */ (0,
|
|
384
|
-
label && /* @__PURE__ */ (0,
|
|
385
|
-
items.map((item, index) => /* @__PURE__ */ (0,
|
|
692
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: fieldDescription.className, children: [
|
|
693
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { children: label }),
|
|
694
|
+
items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
386
695
|
"div",
|
|
387
696
|
{
|
|
388
697
|
style: { display: "flex", alignItems: "flex-start", gap: 8 },
|
|
389
698
|
children: [
|
|
390
|
-
/* @__PURE__ */ (0,
|
|
699
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { flex: 1 }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
391
700
|
MultiFieldInput_default,
|
|
392
701
|
{
|
|
393
702
|
fieldDescriptions: fields,
|
|
@@ -396,7 +705,7 @@ var FieldGroupInput = ({
|
|
|
396
705
|
onChange: (next) => handleItemChange(index, next)
|
|
397
706
|
}
|
|
398
707
|
) }),
|
|
399
|
-
/* @__PURE__ */ (0,
|
|
708
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
400
709
|
"button",
|
|
401
710
|
{
|
|
402
711
|
type: "button",
|
|
@@ -410,7 +719,7 @@ var FieldGroupInput = ({
|
|
|
410
719
|
},
|
|
411
720
|
itemKey(item, index)
|
|
412
721
|
)),
|
|
413
|
-
/* @__PURE__ */ (0,
|
|
722
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
414
723
|
"button",
|
|
415
724
|
{
|
|
416
725
|
type: "button",
|
|
@@ -425,7 +734,7 @@ var FieldGroupInput = ({
|
|
|
425
734
|
var FieldGroupInput_default = FieldGroupInput;
|
|
426
735
|
|
|
427
736
|
// src/components/FieldInput.tsx
|
|
428
|
-
var
|
|
737
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
429
738
|
var FieldInputInner = ({
|
|
430
739
|
fieldDescription,
|
|
431
740
|
renderInfos,
|
|
@@ -446,7 +755,7 @@ var FieldInputInner = ({
|
|
|
446
755
|
);
|
|
447
756
|
if (fields) {
|
|
448
757
|
const items = Array.isArray(renderInfos[name]) ? renderInfos[name] : [];
|
|
449
|
-
return /* @__PURE__ */ (0,
|
|
758
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
450
759
|
FieldGroupInput_default,
|
|
451
760
|
{
|
|
452
761
|
fieldDescription,
|
|
@@ -470,7 +779,7 @@ var FieldInputInner = ({
|
|
|
470
779
|
const errors = effectiveDisabled ? [] : (0, import_core4.validateField)(fieldDescription, renderInfos[name], renderInfos, rootData);
|
|
471
780
|
const error = errors.length > 0 ? errors : void 0;
|
|
472
781
|
const fieldId = `dfk-field-${name}`;
|
|
473
|
-
return /* @__PURE__ */ (0,
|
|
782
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
474
783
|
DynamicInput_default,
|
|
475
784
|
{
|
|
476
785
|
id: fieldId,
|
|
@@ -494,27 +803,338 @@ var FieldInputInner = ({
|
|
|
494
803
|
}
|
|
495
804
|
);
|
|
496
805
|
};
|
|
497
|
-
var FieldInput = import_react6.default.memo(FieldInputInner, (prev, next) => {
|
|
806
|
+
var FieldInput = /* @__PURE__ */ import_react6.default.memo(FieldInputInner, (prev, next) => {
|
|
498
807
|
const name = prev.fieldDescription.name;
|
|
499
808
|
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];
|
|
500
809
|
});
|
|
501
810
|
var FieldInput_default = FieldInput;
|
|
502
811
|
|
|
503
|
-
// src/
|
|
812
|
+
// src/components/DynamicFormDevTools.tsx
|
|
813
|
+
var import_react7 = require("react");
|
|
814
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
815
|
+
var DynamicFormDevTools = ({
|
|
816
|
+
data,
|
|
817
|
+
errors = {},
|
|
818
|
+
touched = {},
|
|
819
|
+
isDirty = false,
|
|
820
|
+
fields = [],
|
|
821
|
+
position = "bottom-right"
|
|
822
|
+
}) => {
|
|
823
|
+
const [isOpen, setIsOpen] = (0, import_react7.useState)(false);
|
|
824
|
+
const [activeTab, setActiveTab] = (0, import_react7.useState)("data");
|
|
825
|
+
const errorCount = Object.keys(errors).length;
|
|
826
|
+
const posStyle = position === "bottom-left" ? { left: "16px", bottom: "16px" } : { right: "16px", bottom: "16px" };
|
|
827
|
+
if (!isOpen) {
|
|
828
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
829
|
+
"button",
|
|
830
|
+
{
|
|
831
|
+
type: "button",
|
|
832
|
+
onClick: () => setIsOpen(true),
|
|
833
|
+
style: {
|
|
834
|
+
position: "fixed",
|
|
835
|
+
...posStyle,
|
|
836
|
+
zIndex: 99999,
|
|
837
|
+
background: "#1e293b",
|
|
838
|
+
color: "#f8fafc",
|
|
839
|
+
border: "1px solid #334155",
|
|
840
|
+
borderRadius: "20px",
|
|
841
|
+
padding: "8px 14px",
|
|
842
|
+
fontSize: "12px",
|
|
843
|
+
fontWeight: 600,
|
|
844
|
+
cursor: "pointer",
|
|
845
|
+
boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
|
|
846
|
+
display: "flex",
|
|
847
|
+
alignItems: "center",
|
|
848
|
+
gap: "6px"
|
|
849
|
+
},
|
|
850
|
+
children: [
|
|
851
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { children: "\u{1F50D} DevTools" }),
|
|
852
|
+
errorCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
853
|
+
"span",
|
|
854
|
+
{
|
|
855
|
+
style: {
|
|
856
|
+
background: "#ef4444",
|
|
857
|
+
color: "#fff",
|
|
858
|
+
borderRadius: "10px",
|
|
859
|
+
padding: "2px 6px",
|
|
860
|
+
fontSize: "10px"
|
|
861
|
+
},
|
|
862
|
+
children: errorCount
|
|
863
|
+
}
|
|
864
|
+
)
|
|
865
|
+
]
|
|
866
|
+
}
|
|
867
|
+
);
|
|
868
|
+
}
|
|
869
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
870
|
+
"div",
|
|
871
|
+
{
|
|
872
|
+
style: {
|
|
873
|
+
position: "fixed",
|
|
874
|
+
...posStyle,
|
|
875
|
+
zIndex: 99999,
|
|
876
|
+
width: "360px",
|
|
877
|
+
maxHeight: "420px",
|
|
878
|
+
background: "#0f172a",
|
|
879
|
+
color: "#f8fafc",
|
|
880
|
+
border: "1px solid #334155",
|
|
881
|
+
borderRadius: "12px",
|
|
882
|
+
boxShadow: "0 10px 25px rgba(0,0,0,0.3)",
|
|
883
|
+
display: "flex",
|
|
884
|
+
flexDirection: "column",
|
|
885
|
+
fontFamily: "monospace, sans-serif",
|
|
886
|
+
fontSize: "12px",
|
|
887
|
+
overflow: "hidden"
|
|
888
|
+
},
|
|
889
|
+
children: [
|
|
890
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
891
|
+
"div",
|
|
892
|
+
{
|
|
893
|
+
style: {
|
|
894
|
+
padding: "10px 14px",
|
|
895
|
+
background: "#1e293b",
|
|
896
|
+
display: "flex",
|
|
897
|
+
justifyContent: "space-between",
|
|
898
|
+
alignItems: "center",
|
|
899
|
+
borderBottom: "1px solid #334155"
|
|
900
|
+
},
|
|
901
|
+
children: [
|
|
902
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: { fontWeight: "bold", color: "#38bdf8" }, children: "\u{1F6E0}\uFE0F Form DevTools" }),
|
|
903
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
904
|
+
"button",
|
|
905
|
+
{
|
|
906
|
+
type: "button",
|
|
907
|
+
onClick: () => setIsOpen(false),
|
|
908
|
+
style: {
|
|
909
|
+
background: "transparent",
|
|
910
|
+
border: "none",
|
|
911
|
+
color: "#94a3b8",
|
|
912
|
+
fontSize: "14px",
|
|
913
|
+
cursor: "pointer"
|
|
914
|
+
},
|
|
915
|
+
children: "\u2715"
|
|
916
|
+
}
|
|
917
|
+
)
|
|
918
|
+
]
|
|
919
|
+
}
|
|
920
|
+
),
|
|
921
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
922
|
+
"div",
|
|
923
|
+
{
|
|
924
|
+
style: {
|
|
925
|
+
display: "flex",
|
|
926
|
+
background: "#1e293b",
|
|
927
|
+
borderBottom: "1px solid #334155"
|
|
928
|
+
},
|
|
929
|
+
children: ["data", "errors", "meta", "fields"].map((tab) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
930
|
+
"button",
|
|
931
|
+
{
|
|
932
|
+
type: "button",
|
|
933
|
+
onClick: () => setActiveTab(tab),
|
|
934
|
+
style: {
|
|
935
|
+
flex: 1,
|
|
936
|
+
padding: "6px 0",
|
|
937
|
+
background: activeTab === tab ? "#0f172a" : "transparent",
|
|
938
|
+
color: activeTab === tab ? "#38bdf8" : "#94a3b8",
|
|
939
|
+
border: "none",
|
|
940
|
+
cursor: "pointer",
|
|
941
|
+
textTransform: "capitalize",
|
|
942
|
+
fontSize: "11px",
|
|
943
|
+
fontWeight: activeTab === tab ? "bold" : "normal"
|
|
944
|
+
},
|
|
945
|
+
children: [
|
|
946
|
+
tab,
|
|
947
|
+
" ",
|
|
948
|
+
tab === "errors" && errorCount > 0 ? `(${errorCount})` : ""
|
|
949
|
+
]
|
|
950
|
+
},
|
|
951
|
+
tab
|
|
952
|
+
))
|
|
953
|
+
}
|
|
954
|
+
),
|
|
955
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { padding: "12px", overflowY: "auto", flex: 1 }, children: [
|
|
956
|
+
activeTab === "data" && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
957
|
+
"pre",
|
|
958
|
+
{
|
|
959
|
+
style: {
|
|
960
|
+
margin: 0,
|
|
961
|
+
whiteSpace: "pre-wrap",
|
|
962
|
+
wordBreak: "break-all",
|
|
963
|
+
color: "#a7f3d0"
|
|
964
|
+
},
|
|
965
|
+
children: JSON.stringify(data, null, 2)
|
|
966
|
+
}
|
|
967
|
+
),
|
|
968
|
+
activeTab === "errors" && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { children: Object.keys(errors).length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: { color: "#4ade80" }, children: "\u2713 No validation errors" }) : Object.entries(errors).map(([field, msgs]) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { marginBottom: "8px" }, children: [
|
|
969
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { style: { color: "#f87171", fontWeight: "bold" }, children: [
|
|
970
|
+
field,
|
|
971
|
+
":"
|
|
972
|
+
] }),
|
|
973
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("ul", { style: { margin: "4px 0 0 16px", padding: 0 }, children: msgs.map((m, i) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("li", { style: { color: "#fca5a5" }, children: m }, i)) })
|
|
974
|
+
] }, field)) }),
|
|
975
|
+
activeTab === "meta" && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { children: [
|
|
976
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { marginBottom: "6px" }, children: [
|
|
977
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: { color: "#94a3b8" }, children: "isDirty: " }),
|
|
978
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: { color: isDirty ? "#facc15" : "#4ade80" }, children: String(isDirty) })
|
|
979
|
+
] }),
|
|
980
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { children: [
|
|
981
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: { color: "#94a3b8" }, children: "Touched Fields:" }),
|
|
982
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("pre", { style: { margin: "4px 0 0 0", color: "#cbd5e1" }, children: JSON.stringify(touched, null, 2) })
|
|
983
|
+
] })
|
|
984
|
+
] }),
|
|
985
|
+
activeTab === "fields" && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { children: fields.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: { color: "#94a3b8" }, children: "No field descriptions passed" }) : fields.map((f) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
986
|
+
"div",
|
|
987
|
+
{
|
|
988
|
+
style: {
|
|
989
|
+
padding: "6px",
|
|
990
|
+
marginBottom: "6px",
|
|
991
|
+
background: "#1e293b",
|
|
992
|
+
borderRadius: "4px"
|
|
993
|
+
},
|
|
994
|
+
children: [
|
|
995
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { color: "#38bdf8", fontWeight: "bold" }, children: f.name }),
|
|
996
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { color: "#94a3b8", fontSize: "10px" }, children: [
|
|
997
|
+
"type: ",
|
|
998
|
+
f.type,
|
|
999
|
+
" | required: ",
|
|
1000
|
+
String(Boolean(f.required))
|
|
1001
|
+
] })
|
|
1002
|
+
]
|
|
1003
|
+
},
|
|
1004
|
+
f.name
|
|
1005
|
+
)) })
|
|
1006
|
+
] })
|
|
1007
|
+
]
|
|
1008
|
+
}
|
|
1009
|
+
);
|
|
1010
|
+
};
|
|
1011
|
+
|
|
1012
|
+
// src/useDynamicForm.ts
|
|
504
1013
|
var import_core5 = require("@dynamic-field-kit/core");
|
|
1014
|
+
var import_react8 = require("react");
|
|
1015
|
+
function useDynamicForm({
|
|
1016
|
+
fields,
|
|
1017
|
+
initialValues = {},
|
|
1018
|
+
validateOnBlur = true,
|
|
1019
|
+
validateOnChange = false
|
|
1020
|
+
}) {
|
|
1021
|
+
const [data, setData] = (0, import_react8.useState)(
|
|
1022
|
+
() => (0, import_core5.applyComputedValues)(fields, initialValues)
|
|
1023
|
+
);
|
|
1024
|
+
const [errors, setErrors] = (0, import_react8.useState)({});
|
|
1025
|
+
const [isDirty, setIsDirty] = (0, import_react8.useState)(false);
|
|
1026
|
+
const [touched, setTouched] = (0, import_react8.useState)({});
|
|
1027
|
+
const [isSubmitting, setIsSubmitting] = (0, import_react8.useState)(false);
|
|
1028
|
+
const [isSubmitted, setIsSubmitted] = (0, import_react8.useState)(false);
|
|
1029
|
+
const validate = (0, import_react8.useCallback)(() => {
|
|
1030
|
+
const res = (0, import_core5.validateFields)(fields, data);
|
|
1031
|
+
setErrors(res.errors);
|
|
1032
|
+
return res.valid;
|
|
1033
|
+
}, [fields, data]);
|
|
1034
|
+
const handleChange = (0, import_react8.useCallback)(
|
|
1035
|
+
(newData) => {
|
|
1036
|
+
const next = (0, import_core5.applyComputedValues)(fields, newData);
|
|
1037
|
+
setData(next);
|
|
1038
|
+
setIsDirty(true);
|
|
1039
|
+
if (validateOnChange) {
|
|
1040
|
+
const res = (0, import_core5.validateFields)(fields, next);
|
|
1041
|
+
setErrors(res.errors);
|
|
1042
|
+
}
|
|
1043
|
+
},
|
|
1044
|
+
[fields, validateOnChange]
|
|
1045
|
+
);
|
|
1046
|
+
const setFieldValue = (0, import_react8.useCallback)(
|
|
1047
|
+
(name, value) => {
|
|
1048
|
+
handleChange({ ...data, [name]: value });
|
|
1049
|
+
},
|
|
1050
|
+
[data, handleChange]
|
|
1051
|
+
);
|
|
1052
|
+
const setFieldTouched = (0, import_react8.useCallback)((name, isTouched = true) => {
|
|
1053
|
+
setTouched((prev) => ({ ...prev, [name]: isTouched }));
|
|
1054
|
+
}, []);
|
|
1055
|
+
const handleBlur = (0, import_react8.useCallback)(
|
|
1056
|
+
(fieldName) => {
|
|
1057
|
+
setFieldTouched(fieldName, true);
|
|
1058
|
+
if (validateOnBlur) {
|
|
1059
|
+
const res = (0, import_core5.validateFields)(fields, data);
|
|
1060
|
+
setErrors(res.errors);
|
|
1061
|
+
}
|
|
1062
|
+
},
|
|
1063
|
+
[fields, data, validateOnBlur, setFieldTouched]
|
|
1064
|
+
);
|
|
1065
|
+
const reset = (0, import_react8.useCallback)(
|
|
1066
|
+
(newValues) => {
|
|
1067
|
+
const seed = newValues ?? initialValues;
|
|
1068
|
+
const next = (0, import_core5.applyComputedValues)(fields, seed);
|
|
1069
|
+
setData(next);
|
|
1070
|
+
setErrors({});
|
|
1071
|
+
setIsDirty(false);
|
|
1072
|
+
setTouched({});
|
|
1073
|
+
setIsSubmitting(false);
|
|
1074
|
+
setIsSubmitted(false);
|
|
1075
|
+
},
|
|
1076
|
+
[fields, initialValues]
|
|
1077
|
+
);
|
|
1078
|
+
const handleSubmit = (0, import_react8.useCallback)(
|
|
1079
|
+
(onValid, onInvalid) => async (e) => {
|
|
1080
|
+
if (e && typeof e.preventDefault === "function") {
|
|
1081
|
+
e.preventDefault();
|
|
1082
|
+
}
|
|
1083
|
+
setIsSubmitting(true);
|
|
1084
|
+
try {
|
|
1085
|
+
const res = (0, import_core5.validateFields)(fields, data);
|
|
1086
|
+
setErrors(res.errors);
|
|
1087
|
+
setIsSubmitted(true);
|
|
1088
|
+
if (res.valid) {
|
|
1089
|
+
await onValid(data);
|
|
1090
|
+
} else if (onInvalid) {
|
|
1091
|
+
onInvalid(res.errors);
|
|
1092
|
+
}
|
|
1093
|
+
} finally {
|
|
1094
|
+
setIsSubmitting(false);
|
|
1095
|
+
}
|
|
1096
|
+
},
|
|
1097
|
+
[fields, data]
|
|
1098
|
+
);
|
|
1099
|
+
const isValid = Object.keys(errors).length === 0;
|
|
1100
|
+
return {
|
|
1101
|
+
data,
|
|
1102
|
+
errors,
|
|
1103
|
+
isValid,
|
|
1104
|
+
isDirty,
|
|
1105
|
+
isSubmitting,
|
|
1106
|
+
isSubmitted,
|
|
1107
|
+
touched,
|
|
1108
|
+
setData,
|
|
1109
|
+
setFieldValue,
|
|
1110
|
+
setFieldTouched,
|
|
1111
|
+
handleChange,
|
|
1112
|
+
handleBlur,
|
|
1113
|
+
reset,
|
|
1114
|
+
validate,
|
|
1115
|
+
handleSubmit
|
|
1116
|
+
};
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
// src/index.ts
|
|
505
1120
|
var import_core6 = require("@dynamic-field-kit/core");
|
|
1121
|
+
var import_core7 = require("@dynamic-field-kit/core");
|
|
506
1122
|
// Annotate the CommonJS export names for ESM import in node:
|
|
507
1123
|
0 && (module.exports = {
|
|
1124
|
+
DynamicFormDevTools,
|
|
508
1125
|
DynamicInput,
|
|
509
1126
|
FieldInput,
|
|
510
1127
|
FieldRegistry,
|
|
511
1128
|
FieldRegistryProvider,
|
|
512
1129
|
MultiFieldInput,
|
|
1130
|
+
defaultRenderersMap,
|
|
513
1131
|
fieldRegistry,
|
|
1132
|
+
getDefaultRenderer,
|
|
514
1133
|
layoutRegistry,
|
|
515
1134
|
resolveDisabled,
|
|
516
1135
|
resolveOptions,
|
|
517
1136
|
resolveReadOnly,
|
|
1137
|
+
useDynamicForm,
|
|
518
1138
|
useFieldRegistry,
|
|
519
1139
|
validateField,
|
|
520
1140
|
validateFieldAsync,
|
|
@@ -522,4 +1142,3 @@ var import_core6 = require("@dynamic-field-kit/core");
|
|
|
522
1142
|
validateFieldsAsync,
|
|
523
1143
|
validators
|
|
524
1144
|
});
|
|
525
|
-
//# sourceMappingURL=index.js.map
|