@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.mjs
CHANGED
|
@@ -113,6 +113,307 @@ layoutRegistry.register("responsive", ({ children, config }) => {
|
|
|
113
113
|
// src/components/DynamicInput.tsx
|
|
114
114
|
import React3, { useMemo } from "react";
|
|
115
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
|
+
|
|
116
417
|
// src/FieldRegistryContext.tsx
|
|
117
418
|
import { createContext, useContext } from "react";
|
|
118
419
|
|
|
@@ -123,18 +424,18 @@ import {
|
|
|
123
424
|
var fieldRegistry = coreFieldRegistry;
|
|
124
425
|
|
|
125
426
|
// src/FieldRegistryContext.tsx
|
|
126
|
-
import { jsx as
|
|
427
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
127
428
|
var FieldRegistryContext = createContext(fieldRegistry);
|
|
128
429
|
var FieldRegistryProvider = ({
|
|
129
430
|
registry,
|
|
130
431
|
children
|
|
131
|
-
}) => /* @__PURE__ */
|
|
432
|
+
}) => /* @__PURE__ */ jsx4(FieldRegistryContext.Provider, { value: registry, children });
|
|
132
433
|
function useFieldRegistry() {
|
|
133
434
|
return useContext(FieldRegistryContext);
|
|
134
435
|
}
|
|
135
436
|
|
|
136
437
|
// src/components/DynamicInput.tsx
|
|
137
|
-
import { jsxs as
|
|
438
|
+
import { jsxs as jsxs3 } from "react/jsx-runtime";
|
|
138
439
|
var DynamicInputInner = ({
|
|
139
440
|
type,
|
|
140
441
|
value,
|
|
@@ -158,11 +459,11 @@ var DynamicInputInner = ({
|
|
|
158
459
|
}) => {
|
|
159
460
|
const registry = useFieldRegistry();
|
|
160
461
|
const Renderer = useMemo(
|
|
161
|
-
() => registry.get(type),
|
|
462
|
+
() => registry.get(type) || getDefaultRenderer(type),
|
|
162
463
|
[registry, type]
|
|
163
464
|
);
|
|
164
465
|
if (!Renderer) {
|
|
165
|
-
return /* @__PURE__ */
|
|
466
|
+
return /* @__PURE__ */ jsxs3("div", { children: [
|
|
166
467
|
"Unknown field type: ",
|
|
167
468
|
type
|
|
168
469
|
] });
|
|
@@ -188,7 +489,7 @@ var DynamicInputInner = ({
|
|
|
188
489
|
ariaRequired
|
|
189
490
|
});
|
|
190
491
|
};
|
|
191
|
-
var DynamicInput = React3.memo(
|
|
492
|
+
var DynamicInput = /* @__PURE__ */ React3.memo(
|
|
192
493
|
DynamicInputInner
|
|
193
494
|
);
|
|
194
495
|
var DynamicInput_default = DynamicInput;
|
|
@@ -222,7 +523,7 @@ import {
|
|
|
222
523
|
useRef,
|
|
223
524
|
useState as useState2
|
|
224
525
|
} from "react";
|
|
225
|
-
import { jsx as
|
|
526
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
226
527
|
function resolveLayout(layout) {
|
|
227
528
|
if (!layout) {
|
|
228
529
|
return { type: "column", config: {} };
|
|
@@ -238,7 +539,8 @@ var MultiFieldInput = ({
|
|
|
238
539
|
onChange,
|
|
239
540
|
layout,
|
|
240
541
|
rootData,
|
|
241
|
-
onValidityChange
|
|
542
|
+
onValidityChange,
|
|
543
|
+
onBlurField
|
|
242
544
|
}) => {
|
|
243
545
|
const [data, setData] = useState2({});
|
|
244
546
|
const [touchedFields, setTouchedFields] = useState2(
|
|
@@ -267,6 +569,8 @@ var MultiFieldInput = ({
|
|
|
267
569
|
rootDataRef.current = rootData;
|
|
268
570
|
const onValidityChangeRef = useRef(onValidityChange);
|
|
269
571
|
onValidityChangeRef.current = onValidityChange;
|
|
572
|
+
const onBlurFieldRef = useRef(onBlurField);
|
|
573
|
+
onBlurFieldRef.current = onBlurField;
|
|
270
574
|
useEffect2(() => {
|
|
271
575
|
onValidityChangeRef.current?.(
|
|
272
576
|
validateFields(fieldDescriptions, data, rootData)
|
|
@@ -285,13 +589,14 @@ var MultiFieldInput = ({
|
|
|
285
589
|
}, []);
|
|
286
590
|
const handleBlurField = useCallback((key) => {
|
|
287
591
|
setTouchedFields((prev) => prev[key] ? prev : { ...prev, [key]: true });
|
|
592
|
+
onBlurFieldRef.current?.(key);
|
|
288
593
|
}, []);
|
|
289
594
|
const { type, config } = resolveLayout(layout);
|
|
290
595
|
const Layout = layoutRegistry.get(type);
|
|
291
596
|
if (!Layout) {
|
|
292
597
|
throw new Error(`Unknown layout: ${type}`);
|
|
293
598
|
}
|
|
294
|
-
return /* @__PURE__ */
|
|
599
|
+
return /* @__PURE__ */ jsx5(Layout, { config, children: visibleFields.map((f) => /* @__PURE__ */ jsx5(
|
|
295
600
|
FieldInput_default,
|
|
296
601
|
{
|
|
297
602
|
fieldDescription: f,
|
|
@@ -308,7 +613,7 @@ var MultiFieldInput = ({
|
|
|
308
613
|
var MultiFieldInput_default = MultiFieldInput;
|
|
309
614
|
|
|
310
615
|
// src/components/FieldGroupInput.tsx
|
|
311
|
-
import { jsx as
|
|
616
|
+
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
312
617
|
var FieldGroupInput = ({
|
|
313
618
|
fieldDescription,
|
|
314
619
|
items,
|
|
@@ -349,14 +654,14 @@ var FieldGroupInput = ({
|
|
|
349
654
|
},
|
|
350
655
|
[fieldDescription, items, onChange]
|
|
351
656
|
);
|
|
352
|
-
return /* @__PURE__ */
|
|
353
|
-
label && /* @__PURE__ */
|
|
354
|
-
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(
|
|
355
660
|
"div",
|
|
356
661
|
{
|
|
357
662
|
style: { display: "flex", alignItems: "flex-start", gap: 8 },
|
|
358
663
|
children: [
|
|
359
|
-
/* @__PURE__ */
|
|
664
|
+
/* @__PURE__ */ jsx6("div", { style: { flex: 1 }, children: /* @__PURE__ */ jsx6(
|
|
360
665
|
MultiFieldInput_default,
|
|
361
666
|
{
|
|
362
667
|
fieldDescriptions: fields,
|
|
@@ -365,7 +670,7 @@ var FieldGroupInput = ({
|
|
|
365
670
|
onChange: (next) => handleItemChange(index, next)
|
|
366
671
|
}
|
|
367
672
|
) }),
|
|
368
|
-
/* @__PURE__ */
|
|
673
|
+
/* @__PURE__ */ jsx6(
|
|
369
674
|
"button",
|
|
370
675
|
{
|
|
371
676
|
type: "button",
|
|
@@ -379,7 +684,7 @@ var FieldGroupInput = ({
|
|
|
379
684
|
},
|
|
380
685
|
itemKey(item, index)
|
|
381
686
|
)),
|
|
382
|
-
/* @__PURE__ */
|
|
687
|
+
/* @__PURE__ */ jsx6(
|
|
383
688
|
"button",
|
|
384
689
|
{
|
|
385
690
|
type: "button",
|
|
@@ -394,7 +699,7 @@ var FieldGroupInput = ({
|
|
|
394
699
|
var FieldGroupInput_default = FieldGroupInput;
|
|
395
700
|
|
|
396
701
|
// src/components/FieldInput.tsx
|
|
397
|
-
import { jsx as
|
|
702
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
398
703
|
var FieldInputInner = ({
|
|
399
704
|
fieldDescription,
|
|
400
705
|
renderInfos,
|
|
@@ -415,7 +720,7 @@ var FieldInputInner = ({
|
|
|
415
720
|
);
|
|
416
721
|
if (fields) {
|
|
417
722
|
const items = Array.isArray(renderInfos[name]) ? renderInfos[name] : [];
|
|
418
|
-
return /* @__PURE__ */
|
|
723
|
+
return /* @__PURE__ */ jsx7(
|
|
419
724
|
FieldGroupInput_default,
|
|
420
725
|
{
|
|
421
726
|
fieldDescription,
|
|
@@ -439,7 +744,7 @@ var FieldInputInner = ({
|
|
|
439
744
|
const errors = effectiveDisabled ? [] : validateField(fieldDescription, renderInfos[name], renderInfos, rootData);
|
|
440
745
|
const error = errors.length > 0 ? errors : void 0;
|
|
441
746
|
const fieldId = `dfk-field-${name}`;
|
|
442
|
-
return /* @__PURE__ */
|
|
747
|
+
return /* @__PURE__ */ jsx7(
|
|
443
748
|
DynamicInput_default,
|
|
444
749
|
{
|
|
445
750
|
id: fieldId,
|
|
@@ -463,18 +768,328 @@ var FieldInputInner = ({
|
|
|
463
768
|
}
|
|
464
769
|
);
|
|
465
770
|
};
|
|
466
|
-
var FieldInput = React6.memo(FieldInputInner, (prev, next) => {
|
|
771
|
+
var FieldInput = /* @__PURE__ */ React6.memo(FieldInputInner, (prev, next) => {
|
|
467
772
|
const name = prev.fieldDescription.name;
|
|
468
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];
|
|
469
774
|
});
|
|
470
775
|
var FieldInput_default = FieldInput;
|
|
471
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
|
+
|
|
472
1087
|
// src/index.ts
|
|
473
1088
|
import { FieldRegistry } from "@dynamic-field-kit/core";
|
|
474
1089
|
import {
|
|
475
1090
|
validateField as validateField2,
|
|
476
1091
|
validateFieldAsync,
|
|
477
|
-
validateFields as
|
|
1092
|
+
validateFields as validateFields3,
|
|
478
1093
|
validateFieldsAsync,
|
|
479
1094
|
resolveDisabled as resolveDisabled2,
|
|
480
1095
|
resolveReadOnly as resolveReadOnly2,
|
|
@@ -482,21 +1097,24 @@ import {
|
|
|
482
1097
|
validators
|
|
483
1098
|
} from "@dynamic-field-kit/core";
|
|
484
1099
|
export {
|
|
1100
|
+
DynamicFormDevTools,
|
|
485
1101
|
DynamicInput_default as DynamicInput,
|
|
486
1102
|
FieldInput_default as FieldInput,
|
|
487
1103
|
FieldRegistry,
|
|
488
1104
|
FieldRegistryProvider,
|
|
489
1105
|
MultiFieldInput_default as MultiFieldInput,
|
|
1106
|
+
defaultRenderersMap,
|
|
490
1107
|
fieldRegistry,
|
|
1108
|
+
getDefaultRenderer,
|
|
491
1109
|
layoutRegistry,
|
|
492
1110
|
resolveDisabled2 as resolveDisabled,
|
|
493
1111
|
resolveOptions2 as resolveOptions,
|
|
494
1112
|
resolveReadOnly2 as resolveReadOnly,
|
|
1113
|
+
useDynamicForm,
|
|
495
1114
|
useFieldRegistry,
|
|
496
1115
|
validateField2 as validateField,
|
|
497
1116
|
validateFieldAsync,
|
|
498
|
-
|
|
1117
|
+
validateFields3 as validateFields,
|
|
499
1118
|
validateFieldsAsync,
|
|
500
1119
|
validators
|
|
501
1120
|
};
|
|
502
|
-
//# sourceMappingURL=index.mjs.map
|