@rachelallyson/hero-hook-form 2.7.0 → 2.7.2
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 +18 -0
- package/dist/cypress/index.d.ts +62 -71
- package/dist/cypress/index.js +583 -70
- package/dist/index.d.ts +504 -78
- package/dist/index.js +1390 -671
- package/package.json +15 -12
- package/dist/react/index.d.ts +0 -3777
- package/dist/react/index.js +0 -4235
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
6
6
|
});
|
|
7
7
|
|
|
8
8
|
// src/components/Form.tsx
|
|
9
|
-
import
|
|
9
|
+
import React20 from "react";
|
|
10
10
|
import { Button as Button3 } from "@heroui/react";
|
|
11
11
|
|
|
12
12
|
// src/hooks/useFormHelper.ts
|
|
@@ -24,7 +24,9 @@ function useFormHelper({
|
|
|
24
24
|
isSubmitting: false,
|
|
25
25
|
isSuccess: false
|
|
26
26
|
});
|
|
27
|
-
const form = methods ?? useForm({
|
|
27
|
+
const form = methods ?? useForm({
|
|
28
|
+
...defaultValues && { defaultValues }
|
|
29
|
+
});
|
|
28
30
|
const handleSubmit = async () => {
|
|
29
31
|
setSubmissionState((prev) => ({
|
|
30
32
|
...prev,
|
|
@@ -64,6 +66,7 @@ function useFormHelper({
|
|
|
64
66
|
};
|
|
65
67
|
return {
|
|
66
68
|
error: submissionState.error,
|
|
69
|
+
// useForm returns UseFormReturn<T, any, T> which is structurally compatible with UseFormReturn<T>
|
|
67
70
|
form,
|
|
68
71
|
handleSubmit,
|
|
69
72
|
isSubmitted: submissionState.isSubmitted,
|
|
@@ -74,8 +77,14 @@ function useFormHelper({
|
|
|
74
77
|
};
|
|
75
78
|
}
|
|
76
79
|
|
|
80
|
+
// src/types.ts
|
|
81
|
+
function pathToString(path) {
|
|
82
|
+
if (path === void 0) return "";
|
|
83
|
+
return path;
|
|
84
|
+
}
|
|
85
|
+
|
|
77
86
|
// src/components/FormField.tsx
|
|
78
|
-
import
|
|
87
|
+
import React19 from "react";
|
|
79
88
|
import { get, useWatch as useWatch3 } from "react-hook-form";
|
|
80
89
|
|
|
81
90
|
// src/fields/AutocompleteField.tsx
|
|
@@ -129,6 +138,7 @@ function AutocompleteField(props) {
|
|
|
129
138
|
isDisabled,
|
|
130
139
|
isInvalid: Boolean(fieldState.error),
|
|
131
140
|
label,
|
|
141
|
+
name,
|
|
132
142
|
placeholder,
|
|
133
143
|
selectedKey: allowsCustomValue ? void 0 : hasSelectedValue ? String(selectedKey) : void 0,
|
|
134
144
|
inputValue: shouldShowInputValue ? field2.value ?? "" : void 0,
|
|
@@ -171,81 +181,93 @@ function HeroHookFormProvider(props) {
|
|
|
171
181
|
const value = useMemo(() => props.defaults ?? {}, [props.defaults]);
|
|
172
182
|
return /* @__PURE__ */ React2.createElement(DefaultsContext.Provider, { value }, props.children);
|
|
173
183
|
}
|
|
184
|
+
function extractInputCommon(common) {
|
|
185
|
+
const result = {};
|
|
186
|
+
if (common.color !== void 0) {
|
|
187
|
+
const color = common.color;
|
|
188
|
+
result.color = color;
|
|
189
|
+
}
|
|
190
|
+
if (common.size !== void 0) {
|
|
191
|
+
const size = common.size;
|
|
192
|
+
result.size = size;
|
|
193
|
+
}
|
|
194
|
+
if (common.variant !== void 0) {
|
|
195
|
+
const variant = common.variant;
|
|
196
|
+
result.variant = variant;
|
|
197
|
+
}
|
|
198
|
+
if (common.radius !== void 0) {
|
|
199
|
+
const radius = common.radius;
|
|
200
|
+
result.radius = radius;
|
|
201
|
+
}
|
|
202
|
+
if (common.labelPlacement !== void 0) {
|
|
203
|
+
const labelPlacement = common.labelPlacement;
|
|
204
|
+
result.labelPlacement = labelPlacement;
|
|
205
|
+
}
|
|
206
|
+
return result;
|
|
207
|
+
}
|
|
208
|
+
function extractTextareaCommon(common) {
|
|
209
|
+
const result = {};
|
|
210
|
+
if (common.color !== void 0) {
|
|
211
|
+
const color = common.color;
|
|
212
|
+
result.color = color;
|
|
213
|
+
}
|
|
214
|
+
if (common.size !== void 0) {
|
|
215
|
+
const size = common.size;
|
|
216
|
+
result.size = size;
|
|
217
|
+
}
|
|
218
|
+
if (common.variant !== void 0) {
|
|
219
|
+
const variant = common.variant;
|
|
220
|
+
result.variant = variant;
|
|
221
|
+
}
|
|
222
|
+
if (common.radius !== void 0) {
|
|
223
|
+
const radius = common.radius;
|
|
224
|
+
result.radius = radius;
|
|
225
|
+
}
|
|
226
|
+
if (common.labelPlacement !== void 0) {
|
|
227
|
+
const labelPlacement = common.labelPlacement;
|
|
228
|
+
result.labelPlacement = labelPlacement;
|
|
229
|
+
}
|
|
230
|
+
return result;
|
|
231
|
+
}
|
|
232
|
+
function extractSelectCommon(common) {
|
|
233
|
+
const result = {};
|
|
234
|
+
if (common.color !== void 0) {
|
|
235
|
+
const color = common.color;
|
|
236
|
+
result.color = color;
|
|
237
|
+
}
|
|
238
|
+
if (common.size !== void 0) {
|
|
239
|
+
const size = common.size;
|
|
240
|
+
result.size = size;
|
|
241
|
+
}
|
|
242
|
+
if (common.variant !== void 0) {
|
|
243
|
+
const variant = common.variant;
|
|
244
|
+
result.variant = variant;
|
|
245
|
+
}
|
|
246
|
+
if (common.radius !== void 0) {
|
|
247
|
+
const radius = common.radius;
|
|
248
|
+
result.radius = radius;
|
|
249
|
+
}
|
|
250
|
+
if (common.labelPlacement !== void 0) {
|
|
251
|
+
const labelPlacement = common.labelPlacement;
|
|
252
|
+
result.labelPlacement = labelPlacement;
|
|
253
|
+
}
|
|
254
|
+
return result;
|
|
255
|
+
}
|
|
174
256
|
function useHeroHookFormDefaults() {
|
|
175
257
|
const cfg = useContext(DefaultsContext) ?? {};
|
|
176
258
|
const common = cfg.common ?? {};
|
|
177
|
-
const commonInput =
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
...common.variant !== void 0 ? { variant: common.variant } : {},
|
|
181
|
-
...common.radius !== void 0 ? { radius: common.radius } : {},
|
|
182
|
-
...common.labelPlacement !== void 0 ? {
|
|
183
|
-
labelPlacement: common.labelPlacement
|
|
184
|
-
} : {}
|
|
185
|
-
};
|
|
186
|
-
const commonTextarea = {
|
|
187
|
-
...common.color !== void 0 ? { color: common.color } : {},
|
|
188
|
-
...common.size !== void 0 ? { size: common.size } : {},
|
|
189
|
-
...common.variant !== void 0 ? { variant: common.variant } : {},
|
|
190
|
-
...common.radius !== void 0 ? { radius: common.radius } : {},
|
|
191
|
-
...common.labelPlacement !== void 0 ? {
|
|
192
|
-
labelPlacement: common.labelPlacement
|
|
193
|
-
} : {}
|
|
194
|
-
};
|
|
195
|
-
const commonSelect = {
|
|
196
|
-
...common.color !== void 0 ? { color: common.color } : {},
|
|
197
|
-
...common.size !== void 0 ? { size: common.size } : {},
|
|
198
|
-
...common.variant !== void 0 ? { variant: common.variant } : {},
|
|
199
|
-
...common.radius !== void 0 ? { radius: common.radius } : {},
|
|
200
|
-
...common.labelPlacement !== void 0 ? {
|
|
201
|
-
labelPlacement: common.labelPlacement
|
|
202
|
-
} : {}
|
|
203
|
-
};
|
|
204
|
-
const commonCheckbox = {
|
|
205
|
-
...common.color !== void 0 ? {
|
|
206
|
-
color: common.color
|
|
207
|
-
} : {},
|
|
208
|
-
...common.size !== void 0 ? { size: common.size } : {}
|
|
209
|
-
};
|
|
210
|
-
const commonRadioGroup = {
|
|
211
|
-
...common.color !== void 0 ? {
|
|
212
|
-
color: common.color
|
|
213
|
-
} : {},
|
|
214
|
-
...common.size !== void 0 ? { size: common.size } : {}
|
|
215
|
-
};
|
|
216
|
-
const commonDateInput = {
|
|
217
|
-
...common.color !== void 0 ? {
|
|
218
|
-
color: common.color
|
|
219
|
-
} : {},
|
|
220
|
-
...common.size !== void 0 ? { size: common.size } : {},
|
|
221
|
-
...common.variant !== void 0 ? {
|
|
222
|
-
variant: common.variant
|
|
223
|
-
} : {},
|
|
224
|
-
...common.radius !== void 0 ? {
|
|
225
|
-
radius: common.radius
|
|
226
|
-
} : {}
|
|
227
|
-
};
|
|
228
|
-
const commonSlider = {
|
|
229
|
-
...common.color !== void 0 ? { color: common.color } : {},
|
|
230
|
-
...common.size !== void 0 ? { size: common.size } : {}
|
|
231
|
-
};
|
|
232
|
-
const commonSwitch = {
|
|
233
|
-
...common.color !== void 0 ? { color: common.color } : {},
|
|
234
|
-
...common.size !== void 0 ? { size: common.size } : {}
|
|
235
|
-
};
|
|
236
|
-
const commonButton = {
|
|
237
|
-
...common.color !== void 0 ? { color: common.color } : {},
|
|
238
|
-
...common.size !== void 0 ? { size: common.size } : {}
|
|
239
|
-
};
|
|
259
|
+
const commonInput = extractInputCommon(common);
|
|
260
|
+
const commonTextarea = extractTextareaCommon(common);
|
|
261
|
+
const commonSelect = extractSelectCommon(common);
|
|
240
262
|
return {
|
|
241
|
-
checkbox:
|
|
242
|
-
dateInput:
|
|
263
|
+
checkbox: cfg.checkbox ?? {},
|
|
264
|
+
dateInput: cfg.dateInput ?? {},
|
|
243
265
|
input: { ...commonInput, ...cfg.input ?? {} },
|
|
244
|
-
radioGroup:
|
|
266
|
+
radioGroup: cfg.radioGroup ?? {},
|
|
245
267
|
select: { ...commonSelect, ...cfg.select ?? {} },
|
|
246
|
-
slider:
|
|
247
|
-
submitButton:
|
|
248
|
-
switch:
|
|
268
|
+
slider: cfg.slider ?? {},
|
|
269
|
+
submitButton: cfg.submitButton ?? {},
|
|
270
|
+
switch: cfg.switch ?? {},
|
|
249
271
|
textarea: { ...commonTextarea, ...cfg.textarea ?? {} }
|
|
250
272
|
};
|
|
251
273
|
}
|
|
@@ -263,31 +285,111 @@ function CheckboxField(props) {
|
|
|
263
285
|
rules
|
|
264
286
|
} = props;
|
|
265
287
|
const defaults = useHeroHookFormDefaults();
|
|
288
|
+
const checkboxValue = checkboxProps?.value ?? "on";
|
|
266
289
|
return /* @__PURE__ */ React3.createElement(
|
|
267
290
|
Controller2,
|
|
268
291
|
{
|
|
269
292
|
control,
|
|
270
293
|
name,
|
|
271
|
-
render: ({ field: field2, fieldState }) =>
|
|
272
|
-
|
|
273
|
-
{
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
294
|
+
render: ({ field: field2, fieldState }) => {
|
|
295
|
+
const containerRef = React3.useRef(null);
|
|
296
|
+
React3.useLayoutEffect(() => {
|
|
297
|
+
const setValue = () => {
|
|
298
|
+
if (containerRef.current) {
|
|
299
|
+
const input = containerRef.current.querySelector(
|
|
300
|
+
`input[type="checkbox"][name="${name}"]`
|
|
301
|
+
);
|
|
302
|
+
if (input instanceof HTMLInputElement) {
|
|
303
|
+
input.setAttribute("value", checkboxValue);
|
|
304
|
+
input.value = checkboxValue;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
setValue();
|
|
309
|
+
const timeoutId = setTimeout(setValue, 0);
|
|
310
|
+
return () => clearTimeout(timeoutId);
|
|
311
|
+
}, [name, checkboxValue, field2.value]);
|
|
312
|
+
return /* @__PURE__ */ React3.createElement("div", { ref: containerRef, className }, /* @__PURE__ */ React3.createElement(
|
|
313
|
+
Checkbox,
|
|
314
|
+
{
|
|
315
|
+
...defaults.checkbox,
|
|
316
|
+
...checkboxProps,
|
|
317
|
+
isDisabled,
|
|
318
|
+
isInvalid: Boolean(fieldState.error),
|
|
319
|
+
isSelected: Boolean(field2.value),
|
|
320
|
+
name,
|
|
321
|
+
value: checkboxValue,
|
|
322
|
+
onBlur: field2.onBlur,
|
|
323
|
+
onValueChange: (val) => field2.onChange(val)
|
|
324
|
+
},
|
|
325
|
+
label
|
|
326
|
+
), description ? /* @__PURE__ */ React3.createElement("p", { className: "text-small text-default-400" }, description) : null, fieldState.error?.message ? /* @__PURE__ */ React3.createElement("p", { className: "text-tiny text-danger mt-1" }, fieldState.error.message) : null);
|
|
327
|
+
},
|
|
284
328
|
rules
|
|
285
329
|
}
|
|
286
330
|
);
|
|
287
331
|
}
|
|
288
332
|
|
|
289
|
-
// src/fields/
|
|
333
|
+
// src/fields/CheckboxGroupField.tsx
|
|
290
334
|
import React4 from "react";
|
|
335
|
+
import { Controller as Controller3 } from "react-hook-form";
|
|
336
|
+
function CheckboxGroupField(props) {
|
|
337
|
+
const {
|
|
338
|
+
checkboxProps,
|
|
339
|
+
className,
|
|
340
|
+
control,
|
|
341
|
+
description,
|
|
342
|
+
isDisabled,
|
|
343
|
+
label,
|
|
344
|
+
name,
|
|
345
|
+
options,
|
|
346
|
+
orientation = "vertical",
|
|
347
|
+
rules
|
|
348
|
+
} = props;
|
|
349
|
+
const defaults = useHeroHookFormDefaults();
|
|
350
|
+
return /* @__PURE__ */ React4.createElement(
|
|
351
|
+
Controller3,
|
|
352
|
+
{
|
|
353
|
+
control,
|
|
354
|
+
name,
|
|
355
|
+
render: ({ field: field2, fieldState }) => {
|
|
356
|
+
const currentValues = field2.value || [];
|
|
357
|
+
const handleCheckboxChange = (optionValue, checked) => {
|
|
358
|
+
if (checked) {
|
|
359
|
+
if (!currentValues.includes(optionValue)) {
|
|
360
|
+
field2.onChange([...currentValues, optionValue]);
|
|
361
|
+
}
|
|
362
|
+
} else {
|
|
363
|
+
field2.onChange(currentValues.filter((val) => val !== optionValue));
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
const containerClass = orientation === "horizontal" ? "flex flex-row gap-4 flex-wrap" : "flex flex-col gap-2";
|
|
367
|
+
return /* @__PURE__ */ React4.createElement("div", { className }, label && /* @__PURE__ */ React4.createElement("label", { className: "text-sm font-medium text-foreground block mb-2" }, label), description && /* @__PURE__ */ React4.createElement("p", { className: "text-sm text-default-500 mb-2" }, description), /* @__PURE__ */ React4.createElement("div", { className: containerClass }, options.map((option) => {
|
|
368
|
+
const isSelected = currentValues.includes(option.value);
|
|
369
|
+
return /* @__PURE__ */ React4.createElement(
|
|
370
|
+
Checkbox,
|
|
371
|
+
{
|
|
372
|
+
key: String(option.value),
|
|
373
|
+
...defaults.checkbox,
|
|
374
|
+
...checkboxProps,
|
|
375
|
+
isDisabled: isDisabled || option.disabled,
|
|
376
|
+
isInvalid: Boolean(fieldState.error),
|
|
377
|
+
isSelected,
|
|
378
|
+
name,
|
|
379
|
+
onBlur: field2.onBlur,
|
|
380
|
+
onValueChange: (checked) => handleCheckboxChange(option.value, checked)
|
|
381
|
+
},
|
|
382
|
+
option.label
|
|
383
|
+
);
|
|
384
|
+
})), fieldState.error?.message ? /* @__PURE__ */ React4.createElement("p", { className: "text-tiny text-danger mt-1" }, fieldState.error.message) : null);
|
|
385
|
+
},
|
|
386
|
+
rules
|
|
387
|
+
}
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// src/fields/ConditionalField.tsx
|
|
392
|
+
import React5 from "react";
|
|
291
393
|
import { useWatch, useFormContext } from "react-hook-form";
|
|
292
394
|
function ConditionalField({
|
|
293
395
|
className,
|
|
@@ -301,7 +403,7 @@ function ConditionalField({
|
|
|
301
403
|
if (!shouldShow) {
|
|
302
404
|
return null;
|
|
303
405
|
}
|
|
304
|
-
return /* @__PURE__ */
|
|
406
|
+
return /* @__PURE__ */ React5.createElement("div", { className }, /* @__PURE__ */ React5.createElement(
|
|
305
407
|
FormField,
|
|
306
408
|
{
|
|
307
409
|
config: field2,
|
|
@@ -317,29 +419,29 @@ function ConditionalField({
|
|
|
317
419
|
}
|
|
318
420
|
|
|
319
421
|
// src/fields/ContentField.tsx
|
|
320
|
-
import
|
|
422
|
+
import React6 from "react";
|
|
321
423
|
function ContentField({
|
|
322
424
|
config,
|
|
323
425
|
form,
|
|
324
426
|
submissionState
|
|
325
427
|
}) {
|
|
326
428
|
if (config.render) {
|
|
327
|
-
return /* @__PURE__ */
|
|
429
|
+
return /* @__PURE__ */ React6.createElement("div", { className: config.className }, config.render({
|
|
328
430
|
errors: form.formState.errors,
|
|
329
431
|
form,
|
|
330
432
|
isSubmitting: submissionState.isSubmitting
|
|
331
433
|
}));
|
|
332
434
|
}
|
|
333
|
-
return /* @__PURE__ */
|
|
435
|
+
return /* @__PURE__ */ React6.createElement("div", { className: config.className }, config.title && /* @__PURE__ */ React6.createElement("h3", { className: "text-lg font-semibold text-foreground mb-2" }, config.title), config.description && /* @__PURE__ */ React6.createElement("p", { className: "text-sm text-muted-foreground" }, config.description));
|
|
334
436
|
}
|
|
335
437
|
|
|
336
438
|
// src/fields/DateField.tsx
|
|
337
|
-
import
|
|
338
|
-
import { Controller as
|
|
439
|
+
import React7 from "react";
|
|
440
|
+
import { Controller as Controller4 } from "react-hook-form";
|
|
339
441
|
function CoercedDateInput(props) {
|
|
340
442
|
const { dateProps, description, disabled, errorMessage, field: field2, label } = props;
|
|
341
443
|
const defaults = useHeroHookFormDefaults();
|
|
342
|
-
return /* @__PURE__ */
|
|
444
|
+
return /* @__PURE__ */ React7.createElement(
|
|
343
445
|
DateInput,
|
|
344
446
|
{
|
|
345
447
|
...defaults.dateInput,
|
|
@@ -349,6 +451,7 @@ function CoercedDateInput(props) {
|
|
|
349
451
|
isDisabled: disabled,
|
|
350
452
|
isInvalid: Boolean(errorMessage),
|
|
351
453
|
label,
|
|
454
|
+
name: field2.name,
|
|
352
455
|
value: field2.value ?? null,
|
|
353
456
|
onBlur: field2.onBlur,
|
|
354
457
|
onChange: field2.onChange
|
|
@@ -367,12 +470,12 @@ function DateField(props) {
|
|
|
367
470
|
rules,
|
|
368
471
|
transform
|
|
369
472
|
} = props;
|
|
370
|
-
return /* @__PURE__ */
|
|
371
|
-
|
|
473
|
+
return /* @__PURE__ */ React7.createElement(
|
|
474
|
+
Controller4,
|
|
372
475
|
{
|
|
373
476
|
control,
|
|
374
477
|
name,
|
|
375
|
-
render: ({ field: field2, fieldState }) => /* @__PURE__ */
|
|
478
|
+
render: ({ field: field2, fieldState }) => /* @__PURE__ */ React7.createElement("div", { className }, /* @__PURE__ */ React7.createElement(
|
|
376
479
|
CoercedDateInput,
|
|
377
480
|
{
|
|
378
481
|
dateProps,
|
|
@@ -392,7 +495,7 @@ function DateField(props) {
|
|
|
392
495
|
}
|
|
393
496
|
|
|
394
497
|
// src/fields/DynamicSectionField.tsx
|
|
395
|
-
import
|
|
498
|
+
import React8 from "react";
|
|
396
499
|
import { useWatch as useWatch2, useFormContext as useFormContext2 } from "react-hook-form";
|
|
397
500
|
function DynamicSectionField({
|
|
398
501
|
className,
|
|
@@ -406,7 +509,7 @@ function DynamicSectionField({
|
|
|
406
509
|
if (!shouldShow) {
|
|
407
510
|
return null;
|
|
408
511
|
}
|
|
409
|
-
return /* @__PURE__ */
|
|
512
|
+
return /* @__PURE__ */ React8.createElement("div", { className }, (title || description) && /* @__PURE__ */ React8.createElement("div", { className: "mb-6" }, title && /* @__PURE__ */ React8.createElement("h3", { className: "text-lg font-semibold text-gray-900 mb-2" }, title), description && /* @__PURE__ */ React8.createElement("p", { className: "text-sm text-gray-600" }, description)), /* @__PURE__ */ React8.createElement("div", { className: "space-y-4" }, fields.map((fieldConfig, index) => /* @__PURE__ */ React8.createElement(
|
|
410
513
|
FormField,
|
|
411
514
|
{
|
|
412
515
|
key: `${fieldConfig.name}-${index}`,
|
|
@@ -423,7 +526,7 @@ function DynamicSectionField({
|
|
|
423
526
|
}
|
|
424
527
|
|
|
425
528
|
// src/fields/FieldArrayField.tsx
|
|
426
|
-
import
|
|
529
|
+
import React9 from "react";
|
|
427
530
|
import { useFieldArray, useFormContext as useFormContext3 } from "react-hook-form";
|
|
428
531
|
import { Button as Button2 } from "@heroui/react";
|
|
429
532
|
function FieldArrayField({
|
|
@@ -451,27 +554,60 @@ function FieldArrayField({
|
|
|
451
554
|
const { append, fields, move, remove } = useFieldArray({
|
|
452
555
|
control,
|
|
453
556
|
name
|
|
454
|
-
// FieldArray name
|
|
455
557
|
});
|
|
456
558
|
const canAdd = fields.length < max;
|
|
457
559
|
const canRemove = fields.length > min;
|
|
560
|
+
const getFieldPath = (fieldName, itemIndex) => {
|
|
561
|
+
return `${String(name)}.${itemIndex}.${fieldName}`;
|
|
562
|
+
};
|
|
563
|
+
const processFieldConfig = (fieldConfig, itemIndex) => {
|
|
564
|
+
const fieldName = String(fieldConfig.name);
|
|
565
|
+
const fullPath = getFieldPath(fieldName, itemIndex);
|
|
566
|
+
if ("dependsOn" in fieldConfig && fieldConfig.dependsOn && typeof fieldConfig.dependsOn === "string") {
|
|
567
|
+
const dependsOnPath = fieldConfig.dependsOn;
|
|
568
|
+
const arrayNamePrefix = `${String(name)}.`;
|
|
569
|
+
if (!dependsOnPath.startsWith(arrayNamePrefix)) {
|
|
570
|
+
const nestedDependsOn = getFieldPath(dependsOnPath, itemIndex);
|
|
571
|
+
return {
|
|
572
|
+
...fieldConfig,
|
|
573
|
+
dependsOn: nestedDependsOn,
|
|
574
|
+
name: fullPath,
|
|
575
|
+
..."dependsOnValue" in fieldConfig && {
|
|
576
|
+
dependsOnValue: fieldConfig.dependsOnValue
|
|
577
|
+
}
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
return {
|
|
582
|
+
...fieldConfig,
|
|
583
|
+
name: fullPath
|
|
584
|
+
};
|
|
585
|
+
};
|
|
586
|
+
const renderField = (fieldConfig, itemIndex) => {
|
|
587
|
+
const processedConfig = processFieldConfig(fieldConfig, itemIndex);
|
|
588
|
+
return /* @__PURE__ */ React9.createElement(
|
|
589
|
+
FormField,
|
|
590
|
+
{
|
|
591
|
+
key: `${fieldConfig.name}-${itemIndex}`,
|
|
592
|
+
config: processedConfig,
|
|
593
|
+
form,
|
|
594
|
+
submissionState: {
|
|
595
|
+
error: void 0,
|
|
596
|
+
isSubmitted: false,
|
|
597
|
+
isSubmitting: false,
|
|
598
|
+
isSuccess: false
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
);
|
|
602
|
+
};
|
|
458
603
|
const handleAdd = () => {
|
|
459
604
|
if (canAdd) {
|
|
460
605
|
if (defaultItem) {
|
|
461
606
|
append(defaultItem());
|
|
462
607
|
} else {
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
acc[fieldName] = false;
|
|
467
|
-
} else if (fieldConfig.type === "slider") {
|
|
468
|
-
acc[fieldName] = 0;
|
|
469
|
-
} else {
|
|
470
|
-
acc[fieldName] = "";
|
|
471
|
-
}
|
|
472
|
-
return acc;
|
|
473
|
-
}, {});
|
|
474
|
-
append(defaultValues);
|
|
608
|
+
console.warn(
|
|
609
|
+
`FieldArrayField: defaultItem is required for field array "${String(name)}". Please provide a defaultItem function that returns the default item structure.`
|
|
610
|
+
);
|
|
475
611
|
}
|
|
476
612
|
}
|
|
477
613
|
};
|
|
@@ -495,44 +631,15 @@ function FieldArrayField({
|
|
|
495
631
|
const canMoveUp = enableReordering && index > 0;
|
|
496
632
|
const canMoveDown = enableReordering && index < fields.length - 1;
|
|
497
633
|
const itemCanRemove = canRemove;
|
|
498
|
-
const fieldElements = fieldConfigs.map(
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
let processedConfig = { ...fieldConfig, name: fullPath };
|
|
502
|
-
if ("dependsOn" in fieldConfig && fieldConfig.dependsOn && typeof fieldConfig.dependsOn === "string") {
|
|
503
|
-
const dependsOnPath = fieldConfig.dependsOn;
|
|
504
|
-
if (!dependsOnPath.startsWith(`${name}.`)) {
|
|
505
|
-
processedConfig = {
|
|
506
|
-
...processedConfig,
|
|
507
|
-
dependsOn: `${name}.${index}.${dependsOnPath}`,
|
|
508
|
-
// Preserve dependsOnValue if it exists
|
|
509
|
-
..."dependsOnValue" in fieldConfig && {
|
|
510
|
-
dependsOnValue: fieldConfig.dependsOnValue
|
|
511
|
-
}
|
|
512
|
-
};
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
return /* @__PURE__ */ React8.createElement(
|
|
516
|
-
FormField,
|
|
517
|
-
{
|
|
518
|
-
key: `${fieldConfig.name}-${index}`,
|
|
519
|
-
config: processedConfig,
|
|
520
|
-
form,
|
|
521
|
-
submissionState: {
|
|
522
|
-
error: void 0,
|
|
523
|
-
isSubmitted: false,
|
|
524
|
-
isSubmitting: false,
|
|
525
|
-
isSuccess: false
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
);
|
|
529
|
-
});
|
|
634
|
+
const fieldElements = fieldConfigs.map(
|
|
635
|
+
(fieldConfig) => renderField(fieldConfig, index)
|
|
636
|
+
);
|
|
530
637
|
if (renderItem) {
|
|
531
|
-
return /* @__PURE__ */
|
|
638
|
+
return /* @__PURE__ */ React9.createElement(React9.Fragment, { key: field2.id }, renderItem({
|
|
532
639
|
canMoveDown,
|
|
533
640
|
canMoveUp,
|
|
534
641
|
canRemove: itemCanRemove,
|
|
535
|
-
children: /* @__PURE__ */
|
|
642
|
+
children: /* @__PURE__ */ React9.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, fieldElements),
|
|
536
643
|
field: field2,
|
|
537
644
|
fields,
|
|
538
645
|
index,
|
|
@@ -541,13 +648,13 @@ function FieldArrayField({
|
|
|
541
648
|
onRemove: () => handleRemove(index)
|
|
542
649
|
}));
|
|
543
650
|
}
|
|
544
|
-
return /* @__PURE__ */
|
|
651
|
+
return /* @__PURE__ */ React9.createElement(
|
|
545
652
|
"div",
|
|
546
653
|
{
|
|
547
654
|
key: field2.id,
|
|
548
655
|
className: "border border-gray-200 rounded-lg p-4 space-y-4"
|
|
549
656
|
},
|
|
550
|
-
/* @__PURE__ */
|
|
657
|
+
/* @__PURE__ */ React9.createElement("div", { className: "flex justify-between items-center" }, /* @__PURE__ */ React9.createElement("h4", { className: "text-sm font-medium text-gray-700" }, config.label, " #", index + 1), /* @__PURE__ */ React9.createElement("div", { className: "flex gap-2" }, enableReordering && /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement(
|
|
551
658
|
Button2,
|
|
552
659
|
{
|
|
553
660
|
size: "sm",
|
|
@@ -557,7 +664,7 @@ function FieldArrayField({
|
|
|
557
664
|
"aria-label": `Move ${config.label} ${index + 1} up`
|
|
558
665
|
},
|
|
559
666
|
reorderButtonText.up
|
|
560
|
-
), /* @__PURE__ */
|
|
667
|
+
), /* @__PURE__ */ React9.createElement(
|
|
561
668
|
Button2,
|
|
562
669
|
{
|
|
563
670
|
size: "sm",
|
|
@@ -567,7 +674,7 @@ function FieldArrayField({
|
|
|
567
674
|
"aria-label": `Move ${config.label} ${index + 1} down`
|
|
568
675
|
},
|
|
569
676
|
reorderButtonText.down
|
|
570
|
-
)), itemCanRemove && /* @__PURE__ */
|
|
677
|
+
)), itemCanRemove && /* @__PURE__ */ React9.createElement(
|
|
571
678
|
Button2,
|
|
572
679
|
{
|
|
573
680
|
size: "sm",
|
|
@@ -579,7 +686,7 @@ function FieldArrayField({
|
|
|
579
686
|
},
|
|
580
687
|
removeButtonText
|
|
581
688
|
))),
|
|
582
|
-
/* @__PURE__ */
|
|
689
|
+
/* @__PURE__ */ React9.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, fieldElements)
|
|
583
690
|
);
|
|
584
691
|
});
|
|
585
692
|
};
|
|
@@ -593,7 +700,7 @@ function FieldArrayField({
|
|
|
593
700
|
if (!canAdd) {
|
|
594
701
|
return null;
|
|
595
702
|
}
|
|
596
|
-
return /* @__PURE__ */
|
|
703
|
+
return /* @__PURE__ */ React9.createElement(
|
|
597
704
|
Button2,
|
|
598
705
|
{
|
|
599
706
|
variant: "bordered",
|
|
@@ -604,12 +711,12 @@ function FieldArrayField({
|
|
|
604
711
|
addButtonText
|
|
605
712
|
);
|
|
606
713
|
};
|
|
607
|
-
return /* @__PURE__ */
|
|
714
|
+
return /* @__PURE__ */ React9.createElement("div", { className }, /* @__PURE__ */ React9.createElement("div", { className: "space-y-4" }, fields.length > 0 ? renderFieldArrayItems() : /* @__PURE__ */ React9.createElement("div", { className: "text-center py-8 text-gray-500" }, /* @__PURE__ */ React9.createElement("p", null, "No ", config.label?.toLowerCase(), " added yet."), renderAddButtonElement()), fields.length > 0 && renderAddButtonElement()));
|
|
608
715
|
}
|
|
609
716
|
|
|
610
717
|
// src/fields/FileField.tsx
|
|
611
|
-
import
|
|
612
|
-
import { Controller as
|
|
718
|
+
import React10 from "react";
|
|
719
|
+
import { Controller as Controller5 } from "react-hook-form";
|
|
613
720
|
function CoercedFileInput(props) {
|
|
614
721
|
const {
|
|
615
722
|
accept,
|
|
@@ -622,7 +729,7 @@ function CoercedFileInput(props) {
|
|
|
622
729
|
multiple
|
|
623
730
|
} = props;
|
|
624
731
|
const defaults = useHeroHookFormDefaults();
|
|
625
|
-
return /* @__PURE__ */
|
|
732
|
+
return /* @__PURE__ */ React10.createElement(
|
|
626
733
|
Input,
|
|
627
734
|
{
|
|
628
735
|
...defaults.input,
|
|
@@ -634,10 +741,14 @@ function CoercedFileInput(props) {
|
|
|
634
741
|
isInvalid: Boolean(errorMessage),
|
|
635
742
|
label,
|
|
636
743
|
multiple,
|
|
744
|
+
name: field2.name,
|
|
637
745
|
type: "file",
|
|
638
746
|
value: field2.value ? "" : "",
|
|
639
747
|
onBlur: field2.onBlur,
|
|
640
748
|
onChange: (e) => {
|
|
749
|
+
if (!(e.target instanceof HTMLInputElement)) {
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
641
752
|
const target = e.target;
|
|
642
753
|
field2.onChange(target.files);
|
|
643
754
|
}
|
|
@@ -658,12 +769,12 @@ function FileField(props) {
|
|
|
658
769
|
rules,
|
|
659
770
|
transform
|
|
660
771
|
} = props;
|
|
661
|
-
return /* @__PURE__ */
|
|
662
|
-
|
|
772
|
+
return /* @__PURE__ */ React10.createElement(
|
|
773
|
+
Controller5,
|
|
663
774
|
{
|
|
664
775
|
control,
|
|
665
776
|
name,
|
|
666
|
-
render: ({ field: field2, fieldState }) => /* @__PURE__ */
|
|
777
|
+
render: ({ field: field2, fieldState }) => /* @__PURE__ */ React10.createElement("div", { className }, /* @__PURE__ */ React10.createElement(
|
|
667
778
|
CoercedFileInput,
|
|
668
779
|
{
|
|
669
780
|
accept,
|
|
@@ -685,8 +796,8 @@ function FileField(props) {
|
|
|
685
796
|
}
|
|
686
797
|
|
|
687
798
|
// src/fields/FontPickerField.tsx
|
|
688
|
-
import
|
|
689
|
-
import { Controller as
|
|
799
|
+
import React11 from "react";
|
|
800
|
+
import { Controller as Controller6 } from "react-hook-form";
|
|
690
801
|
var FontPickerComponent = null;
|
|
691
802
|
var fontPickerLoaded = false;
|
|
692
803
|
var fontPickerLoading = false;
|
|
@@ -702,12 +813,12 @@ function FontPickerField(props) {
|
|
|
702
813
|
name,
|
|
703
814
|
rules
|
|
704
815
|
} = props;
|
|
705
|
-
const [fontPickerState, setFontPickerState] =
|
|
816
|
+
const [fontPickerState, setFontPickerState] = React11.useState({
|
|
706
817
|
component: FontPickerComponent,
|
|
707
818
|
error: null,
|
|
708
819
|
loading: false
|
|
709
820
|
});
|
|
710
|
-
|
|
821
|
+
React11.useEffect(() => {
|
|
711
822
|
if (fontPickerLoaded && FontPickerComponent) {
|
|
712
823
|
setFontPickerState({
|
|
713
824
|
component: FontPickerComponent,
|
|
@@ -765,17 +876,17 @@ function FontPickerField(props) {
|
|
|
765
876
|
void loadFontPicker();
|
|
766
877
|
}, []);
|
|
767
878
|
if (fontPickerState.loading) {
|
|
768
|
-
return /* @__PURE__ */
|
|
879
|
+
return /* @__PURE__ */ React11.createElement("div", { className }, /* @__PURE__ */ React11.createElement("div", { className: "space-y-2" }, label && /* @__PURE__ */ React11.createElement("label", { className: "block text-sm font-medium text-foreground" }, label), description && /* @__PURE__ */ React11.createElement("p", { className: "text-sm text-muted-foreground" }, description), /* @__PURE__ */ React11.createElement("div", { className: "p-4 border border-default-200 bg-default-50 rounded-medium" }, /* @__PURE__ */ React11.createElement("p", { className: "text-default-600 text-sm" }, "Loading font picker..."))));
|
|
769
880
|
}
|
|
770
881
|
if (!fontPickerState.component) {
|
|
771
|
-
return /* @__PURE__ */
|
|
882
|
+
return /* @__PURE__ */ React11.createElement("div", { className }, /* @__PURE__ */ React11.createElement("div", { className: "space-y-2" }, label && /* @__PURE__ */ React11.createElement("label", { className: "block text-sm font-medium text-foreground" }, label), description && /* @__PURE__ */ React11.createElement("p", { className: "text-sm text-muted-foreground" }, description), /* @__PURE__ */ React11.createElement("div", { className: "p-4 border border-warning-200 bg-warning-50 rounded-medium" }, /* @__PURE__ */ React11.createElement("p", { className: "text-warning-800 text-sm" }, "Font picker requires the @rachelallyson/heroui-font-picker package. Please install it as a peer dependency for advanced font selection features."))));
|
|
772
883
|
}
|
|
773
|
-
return /* @__PURE__ */
|
|
774
|
-
|
|
884
|
+
return /* @__PURE__ */ React11.createElement(
|
|
885
|
+
Controller6,
|
|
775
886
|
{
|
|
776
887
|
control,
|
|
777
888
|
name,
|
|
778
|
-
render: ({ field: field2, fieldState }) => /* @__PURE__ */
|
|
889
|
+
render: ({ field: field2, fieldState }) => /* @__PURE__ */ React11.createElement(
|
|
779
890
|
fontPickerState.component,
|
|
780
891
|
{
|
|
781
892
|
label,
|
|
@@ -794,12 +905,12 @@ function FontPickerField(props) {
|
|
|
794
905
|
}
|
|
795
906
|
|
|
796
907
|
// src/fields/InputField.tsx
|
|
797
|
-
import
|
|
798
|
-
import { Controller as
|
|
908
|
+
import React12 from "react";
|
|
909
|
+
import { Controller as Controller7 } from "react-hook-form";
|
|
799
910
|
function CoercedInput(props) {
|
|
800
911
|
const { description, disabled, errorMessage, field: field2, inputProps, label } = props;
|
|
801
912
|
const defaults = useHeroHookFormDefaults();
|
|
802
|
-
return /* @__PURE__ */
|
|
913
|
+
return /* @__PURE__ */ React12.createElement(
|
|
803
914
|
Input,
|
|
804
915
|
{
|
|
805
916
|
...defaults.input,
|
|
@@ -809,13 +920,14 @@ function CoercedInput(props) {
|
|
|
809
920
|
isDisabled: disabled,
|
|
810
921
|
isInvalid: Boolean(errorMessage),
|
|
811
922
|
label,
|
|
923
|
+
name: field2.name,
|
|
812
924
|
value: field2.value ?? "",
|
|
813
925
|
onBlur: field2.onBlur,
|
|
814
926
|
onValueChange: field2.onChange
|
|
815
927
|
}
|
|
816
928
|
);
|
|
817
929
|
}
|
|
818
|
-
var InputField =
|
|
930
|
+
var InputField = React12.memo(
|
|
819
931
|
(props) => {
|
|
820
932
|
const {
|
|
821
933
|
className,
|
|
@@ -828,12 +940,12 @@ var InputField = React11.memo(
|
|
|
828
940
|
rules,
|
|
829
941
|
transform
|
|
830
942
|
} = props;
|
|
831
|
-
return /* @__PURE__ */
|
|
832
|
-
|
|
943
|
+
return /* @__PURE__ */ React12.createElement(
|
|
944
|
+
Controller7,
|
|
833
945
|
{
|
|
834
946
|
control,
|
|
835
947
|
name,
|
|
836
|
-
render: ({ field: field2, fieldState }) => /* @__PURE__ */
|
|
948
|
+
render: ({ field: field2, fieldState }) => /* @__PURE__ */ React12.createElement("div", { className }, /* @__PURE__ */ React12.createElement(
|
|
837
949
|
CoercedInput,
|
|
838
950
|
{
|
|
839
951
|
description,
|
|
@@ -863,8 +975,8 @@ var InputField = React11.memo(
|
|
|
863
975
|
);
|
|
864
976
|
|
|
865
977
|
// src/fields/RadioGroupField.tsx
|
|
866
|
-
import
|
|
867
|
-
import { Controller as
|
|
978
|
+
import React13 from "react";
|
|
979
|
+
import { Controller as Controller8 } from "react-hook-form";
|
|
868
980
|
function RadioGroupField(props) {
|
|
869
981
|
const {
|
|
870
982
|
className,
|
|
@@ -878,12 +990,12 @@ function RadioGroupField(props) {
|
|
|
878
990
|
rules
|
|
879
991
|
} = props;
|
|
880
992
|
const defaults = useHeroHookFormDefaults();
|
|
881
|
-
return /* @__PURE__ */
|
|
882
|
-
|
|
993
|
+
return /* @__PURE__ */ React13.createElement(
|
|
994
|
+
Controller8,
|
|
883
995
|
{
|
|
884
996
|
control,
|
|
885
997
|
name,
|
|
886
|
-
render: ({ field: field2, fieldState }) => /* @__PURE__ */
|
|
998
|
+
render: ({ field: field2, fieldState }) => /* @__PURE__ */ React13.createElement("div", { className }, /* @__PURE__ */ React13.createElement(
|
|
887
999
|
RadioGroup,
|
|
888
1000
|
{
|
|
889
1001
|
...defaults.radioGroup,
|
|
@@ -892,11 +1004,12 @@ function RadioGroupField(props) {
|
|
|
892
1004
|
isDisabled,
|
|
893
1005
|
isInvalid: Boolean(fieldState.error),
|
|
894
1006
|
label,
|
|
1007
|
+
name,
|
|
895
1008
|
value: String(field2.value ?? ""),
|
|
896
1009
|
onBlur: field2.onBlur,
|
|
897
1010
|
onValueChange: (val) => field2.onChange(val)
|
|
898
1011
|
},
|
|
899
|
-
options.map((opt) => /* @__PURE__ */
|
|
1012
|
+
options.map((opt) => /* @__PURE__ */ React13.createElement(
|
|
900
1013
|
Radio,
|
|
901
1014
|
{
|
|
902
1015
|
key: String(opt.value),
|
|
@@ -905,15 +1018,15 @@ function RadioGroupField(props) {
|
|
|
905
1018
|
},
|
|
906
1019
|
opt.label
|
|
907
1020
|
))
|
|
908
|
-
), fieldState.error?.message ? /* @__PURE__ */
|
|
1021
|
+
), fieldState.error?.message ? /* @__PURE__ */ React13.createElement("p", { className: "text-tiny text-danger mt-1" }, fieldState.error.message) : null),
|
|
909
1022
|
rules
|
|
910
1023
|
}
|
|
911
1024
|
);
|
|
912
1025
|
}
|
|
913
1026
|
|
|
914
1027
|
// src/fields/SelectField.tsx
|
|
915
|
-
import
|
|
916
|
-
import { Controller as
|
|
1028
|
+
import React14 from "react";
|
|
1029
|
+
import { Controller as Controller9 } from "react-hook-form";
|
|
917
1030
|
function SelectField(props) {
|
|
918
1031
|
const {
|
|
919
1032
|
className,
|
|
@@ -928,14 +1041,14 @@ function SelectField(props) {
|
|
|
928
1041
|
selectProps
|
|
929
1042
|
} = props;
|
|
930
1043
|
const defaults = useHeroHookFormDefaults();
|
|
931
|
-
return /* @__PURE__ */
|
|
932
|
-
|
|
1044
|
+
return /* @__PURE__ */ React14.createElement(
|
|
1045
|
+
Controller9,
|
|
933
1046
|
{
|
|
934
1047
|
control,
|
|
935
1048
|
name,
|
|
936
1049
|
render: ({ field: field2, fieldState }) => {
|
|
937
1050
|
const selectedKey = field2.value;
|
|
938
|
-
return /* @__PURE__ */
|
|
1051
|
+
return /* @__PURE__ */ React14.createElement("div", { className }, /* @__PURE__ */ React14.createElement(
|
|
939
1052
|
Select,
|
|
940
1053
|
{
|
|
941
1054
|
...defaults.select,
|
|
@@ -945,6 +1058,7 @@ function SelectField(props) {
|
|
|
945
1058
|
isDisabled,
|
|
946
1059
|
isInvalid: Boolean(fieldState.error),
|
|
947
1060
|
label,
|
|
1061
|
+
name,
|
|
948
1062
|
placeholder,
|
|
949
1063
|
selectedKeys: selectedKey != null ? /* @__PURE__ */ new Set([String(selectedKey)]) : /* @__PURE__ */ new Set(),
|
|
950
1064
|
onSelectionChange: (keys) => {
|
|
@@ -953,7 +1067,7 @@ function SelectField(props) {
|
|
|
953
1067
|
field2.onChange(next);
|
|
954
1068
|
}
|
|
955
1069
|
},
|
|
956
|
-
options.map((opt) => /* @__PURE__ */
|
|
1070
|
+
options.map((opt) => /* @__PURE__ */ React14.createElement(
|
|
957
1071
|
SelectItem,
|
|
958
1072
|
{
|
|
959
1073
|
key: String(opt.value),
|
|
@@ -970,12 +1084,12 @@ function SelectField(props) {
|
|
|
970
1084
|
}
|
|
971
1085
|
|
|
972
1086
|
// src/fields/SliderField.tsx
|
|
973
|
-
import
|
|
974
|
-
import { Controller as
|
|
1087
|
+
import React15 from "react";
|
|
1088
|
+
import { Controller as Controller10 } from "react-hook-form";
|
|
975
1089
|
function CoercedSlider(props) {
|
|
976
1090
|
const { description, disabled, errorMessage, field: field2, label, sliderProps } = props;
|
|
977
1091
|
const defaults = useHeroHookFormDefaults();
|
|
978
|
-
return /* @__PURE__ */
|
|
1092
|
+
return /* @__PURE__ */ React15.createElement(
|
|
979
1093
|
Slider,
|
|
980
1094
|
{
|
|
981
1095
|
...defaults.slider,
|
|
@@ -985,6 +1099,7 @@ function CoercedSlider(props) {
|
|
|
985
1099
|
isDisabled: disabled,
|
|
986
1100
|
isInvalid: Boolean(errorMessage),
|
|
987
1101
|
label,
|
|
1102
|
+
name: field2.name,
|
|
988
1103
|
value: field2.value ?? 0,
|
|
989
1104
|
onBlur: field2.onBlur,
|
|
990
1105
|
onValueChange: field2.onChange
|
|
@@ -1003,12 +1118,12 @@ function SliderField(props) {
|
|
|
1003
1118
|
sliderProps,
|
|
1004
1119
|
transform
|
|
1005
1120
|
} = props;
|
|
1006
|
-
return /* @__PURE__ */
|
|
1007
|
-
|
|
1121
|
+
return /* @__PURE__ */ React15.createElement(
|
|
1122
|
+
Controller10,
|
|
1008
1123
|
{
|
|
1009
1124
|
control,
|
|
1010
1125
|
name,
|
|
1011
|
-
render: ({ field: field2, fieldState }) => /* @__PURE__ */
|
|
1126
|
+
render: ({ field: field2, fieldState }) => /* @__PURE__ */ React15.createElement("div", { className }, /* @__PURE__ */ React15.createElement(
|
|
1012
1127
|
CoercedSlider,
|
|
1013
1128
|
{
|
|
1014
1129
|
description,
|
|
@@ -1027,9 +1142,123 @@ function SliderField(props) {
|
|
|
1027
1142
|
);
|
|
1028
1143
|
}
|
|
1029
1144
|
|
|
1145
|
+
// src/fields/StringArrayField.tsx
|
|
1146
|
+
import React16, { useState as useState2 } from "react";
|
|
1147
|
+
import { Controller as Controller11 } from "react-hook-form";
|
|
1148
|
+
function StringArrayInput(props) {
|
|
1149
|
+
const {
|
|
1150
|
+
description,
|
|
1151
|
+
disabled,
|
|
1152
|
+
errorMessage,
|
|
1153
|
+
field: field2,
|
|
1154
|
+
label,
|
|
1155
|
+
stringArrayProps
|
|
1156
|
+
} = props;
|
|
1157
|
+
const [inputValue, setInputValue] = useState2("");
|
|
1158
|
+
const items = field2.value || [];
|
|
1159
|
+
const {
|
|
1160
|
+
addButtonText = "Add",
|
|
1161
|
+
allowDuplicates = false,
|
|
1162
|
+
maxItems,
|
|
1163
|
+
minItems,
|
|
1164
|
+
placeholder = "Add item...",
|
|
1165
|
+
showAddButton = true,
|
|
1166
|
+
transformItem = (item) => item.trim(),
|
|
1167
|
+
validateItem = () => true
|
|
1168
|
+
} = stringArrayProps || {};
|
|
1169
|
+
const canAddMore = !maxItems || items.length < maxItems;
|
|
1170
|
+
const handleAddItem = () => {
|
|
1171
|
+
const trimmedValue = inputValue.trim();
|
|
1172
|
+
if (!trimmedValue) return;
|
|
1173
|
+
const transformedValue = transformItem(trimmedValue);
|
|
1174
|
+
const validation = validateItem(transformedValue);
|
|
1175
|
+
if (validation !== true) return;
|
|
1176
|
+
if (!allowDuplicates && items.includes(transformedValue)) return;
|
|
1177
|
+
const newItems = [...items, transformedValue];
|
|
1178
|
+
field2.onChange(newItems);
|
|
1179
|
+
setInputValue("");
|
|
1180
|
+
};
|
|
1181
|
+
const handleRemoveItem = (indexToRemove) => {
|
|
1182
|
+
const newItems = items.filter((_, index) => index !== indexToRemove);
|
|
1183
|
+
field2.onChange(newItems);
|
|
1184
|
+
};
|
|
1185
|
+
const handleKeyPress = (e) => {
|
|
1186
|
+
if (e.key === "Enter") {
|
|
1187
|
+
e.preventDefault();
|
|
1188
|
+
if (!showAddButton) {
|
|
1189
|
+
handleAddItem();
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
};
|
|
1193
|
+
return /* @__PURE__ */ React16.createElement("div", { className: "space-y-2" }, label && /* @__PURE__ */ React16.createElement("label", { className: "block text-sm font-medium text-foreground" }, label, minItems !== void 0 && /* @__PURE__ */ React16.createElement("span", { className: "text-xs text-muted-foreground ml-1" }, "(min ", minItems, ")"), maxItems !== void 0 && /* @__PURE__ */ React16.createElement("span", { className: "text-xs text-muted-foreground ml-1" }, "(max ", maxItems, ")")), description && /* @__PURE__ */ React16.createElement("p", { className: "text-sm text-muted-foreground" }, description), canAddMore && /* @__PURE__ */ React16.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ React16.createElement(
|
|
1194
|
+
Input,
|
|
1195
|
+
{
|
|
1196
|
+
className: "flex-1",
|
|
1197
|
+
disabled,
|
|
1198
|
+
placeholder,
|
|
1199
|
+
value: inputValue,
|
|
1200
|
+
onChange: (e) => setInputValue(e.target.value),
|
|
1201
|
+
onKeyPress: handleKeyPress,
|
|
1202
|
+
isInvalid: !!errorMessage,
|
|
1203
|
+
errorMessage
|
|
1204
|
+
}
|
|
1205
|
+
), showAddButton && /* @__PURE__ */ React16.createElement(
|
|
1206
|
+
Button,
|
|
1207
|
+
{
|
|
1208
|
+
type: "button",
|
|
1209
|
+
variant: "flat",
|
|
1210
|
+
onClick: handleAddItem,
|
|
1211
|
+
disabled: disabled || !inputValue.trim(),
|
|
1212
|
+
size: "sm"
|
|
1213
|
+
},
|
|
1214
|
+
addButtonText
|
|
1215
|
+
)), items.length > 0 && /* @__PURE__ */ React16.createElement("div", { className: "space-y-1" }, items.map((item, index) => /* @__PURE__ */ React16.createElement(
|
|
1216
|
+
"div",
|
|
1217
|
+
{
|
|
1218
|
+
key: index,
|
|
1219
|
+
className: "flex items-center gap-2 p-2 bg-content2 rounded-md"
|
|
1220
|
+
},
|
|
1221
|
+
/* @__PURE__ */ React16.createElement("span", { className: "flex-1 text-sm" }, item),
|
|
1222
|
+
/* @__PURE__ */ React16.createElement(
|
|
1223
|
+
Button,
|
|
1224
|
+
{
|
|
1225
|
+
type: "button",
|
|
1226
|
+
variant: "light",
|
|
1227
|
+
size: "sm",
|
|
1228
|
+
onClick: () => handleRemoveItem(index),
|
|
1229
|
+
disabled,
|
|
1230
|
+
className: "min-w-[60px]"
|
|
1231
|
+
},
|
|
1232
|
+
"Remove"
|
|
1233
|
+
)
|
|
1234
|
+
))), minItems !== void 0 && items.length < minItems && /* @__PURE__ */ React16.createElement("p", { className: "text-xs text-danger" }, "At least ", minItems, " item", minItems === 1 ? "" : "s", " required"), maxItems !== void 0 && items.length >= maxItems && /* @__PURE__ */ React16.createElement("p", { className: "text-xs text-muted-foreground" }, "Maximum ", maxItems, " item", maxItems === 1 ? "" : "s", " allowed"));
|
|
1235
|
+
}
|
|
1236
|
+
function StringArrayField(props) {
|
|
1237
|
+
const { control, label, name, rules, ...fieldProps } = props;
|
|
1238
|
+
return /* @__PURE__ */ React16.createElement(
|
|
1239
|
+
Controller11,
|
|
1240
|
+
{
|
|
1241
|
+
control,
|
|
1242
|
+
name,
|
|
1243
|
+
rules,
|
|
1244
|
+
render: ({ field: field2, fieldState }) => /* @__PURE__ */ React16.createElement(
|
|
1245
|
+
StringArrayInput,
|
|
1246
|
+
{
|
|
1247
|
+
field: field2,
|
|
1248
|
+
label,
|
|
1249
|
+
description: fieldProps.description,
|
|
1250
|
+
disabled: fieldProps.isDisabled,
|
|
1251
|
+
errorMessage: fieldState.error?.message,
|
|
1252
|
+
stringArrayProps: fieldProps.stringArrayProps
|
|
1253
|
+
}
|
|
1254
|
+
)
|
|
1255
|
+
}
|
|
1256
|
+
);
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1030
1259
|
// src/fields/SwitchField.tsx
|
|
1031
|
-
import
|
|
1032
|
-
import { Controller as
|
|
1260
|
+
import React17 from "react";
|
|
1261
|
+
import { Controller as Controller12 } from "react-hook-form";
|
|
1033
1262
|
function SwitchField(props) {
|
|
1034
1263
|
const {
|
|
1035
1264
|
className,
|
|
@@ -1042,31 +1271,32 @@ function SwitchField(props) {
|
|
|
1042
1271
|
switchProps
|
|
1043
1272
|
} = props;
|
|
1044
1273
|
const defaults = useHeroHookFormDefaults();
|
|
1045
|
-
return /* @__PURE__ */
|
|
1046
|
-
|
|
1274
|
+
return /* @__PURE__ */ React17.createElement(
|
|
1275
|
+
Controller12,
|
|
1047
1276
|
{
|
|
1048
1277
|
control,
|
|
1049
1278
|
name,
|
|
1050
|
-
render: ({ field: field2, fieldState }) => /* @__PURE__ */
|
|
1279
|
+
render: ({ field: field2, fieldState }) => /* @__PURE__ */ React17.createElement("div", { className }, /* @__PURE__ */ React17.createElement(
|
|
1051
1280
|
Switch,
|
|
1052
1281
|
{
|
|
1053
1282
|
...defaults.switch,
|
|
1054
1283
|
...switchProps,
|
|
1055
1284
|
isDisabled,
|
|
1056
1285
|
isSelected: Boolean(field2.value),
|
|
1286
|
+
name,
|
|
1057
1287
|
onBlur: field2.onBlur,
|
|
1058
1288
|
onValueChange: (val) => field2.onChange(val)
|
|
1059
1289
|
},
|
|
1060
1290
|
label
|
|
1061
|
-
), description ? /* @__PURE__ */
|
|
1291
|
+
), description ? /* @__PURE__ */ React17.createElement("p", { className: "text-small text-default-400" }, description) : null, fieldState.error?.message ? /* @__PURE__ */ React17.createElement("p", { className: "text-tiny text-danger mt-1" }, fieldState.error.message) : null),
|
|
1062
1292
|
rules
|
|
1063
1293
|
}
|
|
1064
1294
|
);
|
|
1065
1295
|
}
|
|
1066
1296
|
|
|
1067
1297
|
// src/fields/TextareaField.tsx
|
|
1068
|
-
import
|
|
1069
|
-
import { Controller as
|
|
1298
|
+
import React18 from "react";
|
|
1299
|
+
import { Controller as Controller13 } from "react-hook-form";
|
|
1070
1300
|
function TextareaField(props) {
|
|
1071
1301
|
const {
|
|
1072
1302
|
className,
|
|
@@ -1079,12 +1309,12 @@ function TextareaField(props) {
|
|
|
1079
1309
|
textareaProps
|
|
1080
1310
|
} = props;
|
|
1081
1311
|
const defaults = useHeroHookFormDefaults();
|
|
1082
|
-
return /* @__PURE__ */
|
|
1083
|
-
|
|
1312
|
+
return /* @__PURE__ */ React18.createElement(
|
|
1313
|
+
Controller13,
|
|
1084
1314
|
{
|
|
1085
1315
|
control,
|
|
1086
1316
|
name,
|
|
1087
|
-
render: ({ field: field2, fieldState }) => /* @__PURE__ */
|
|
1317
|
+
render: ({ field: field2, fieldState }) => /* @__PURE__ */ React18.createElement("div", { className }, /* @__PURE__ */ React18.createElement(
|
|
1088
1318
|
Textarea,
|
|
1089
1319
|
{
|
|
1090
1320
|
...defaults.textarea,
|
|
@@ -1094,6 +1324,7 @@ function TextareaField(props) {
|
|
|
1094
1324
|
isDisabled,
|
|
1095
1325
|
isInvalid: Boolean(fieldState.error),
|
|
1096
1326
|
label,
|
|
1327
|
+
name: field2.name,
|
|
1097
1328
|
value: field2.value ?? "",
|
|
1098
1329
|
onBlur: field2.onBlur,
|
|
1099
1330
|
onValueChange: field2.onChange
|
|
@@ -1105,213 +1336,319 @@ function TextareaField(props) {
|
|
|
1105
1336
|
}
|
|
1106
1337
|
|
|
1107
1338
|
// src/components/FormField.tsx
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1339
|
+
function FormFieldComponent({
|
|
1340
|
+
config,
|
|
1341
|
+
form,
|
|
1342
|
+
submissionState
|
|
1343
|
+
}) {
|
|
1344
|
+
if (!form || !form.control) {
|
|
1345
|
+
return null;
|
|
1346
|
+
}
|
|
1347
|
+
const { control } = form;
|
|
1348
|
+
const watchedValues = useWatch3({ control });
|
|
1349
|
+
const fieldConfig = config;
|
|
1350
|
+
if ("type" in fieldConfig && fieldConfig.type === "content") {
|
|
1351
|
+
if ("render" in fieldConfig || "content" in fieldConfig) {
|
|
1352
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1121
1353
|
ContentField,
|
|
1122
1354
|
{
|
|
1123
|
-
config,
|
|
1355
|
+
config: fieldConfig,
|
|
1124
1356
|
form,
|
|
1125
1357
|
submissionState
|
|
1126
1358
|
}
|
|
1127
1359
|
);
|
|
1128
1360
|
}
|
|
1129
|
-
|
|
1361
|
+
}
|
|
1362
|
+
if ("condition" in fieldConfig && fieldConfig.condition && !fieldConfig.condition(watchedValues)) {
|
|
1363
|
+
return null;
|
|
1364
|
+
}
|
|
1365
|
+
if ("dependsOn" in fieldConfig && fieldConfig.dependsOn) {
|
|
1366
|
+
const dependentValue = get(watchedValues, fieldConfig.dependsOn);
|
|
1367
|
+
if ("dependsOnValue" in fieldConfig && fieldConfig.dependsOnValue !== void 0 && dependentValue !== fieldConfig.dependsOnValue) {
|
|
1130
1368
|
return null;
|
|
1131
1369
|
}
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1370
|
+
}
|
|
1371
|
+
const baseProps = {
|
|
1372
|
+
ariaDescribedBy: "ariaDescribedBy" in fieldConfig ? fieldConfig.ariaDescribedBy : void 0,
|
|
1373
|
+
ariaLabel: "ariaLabel" in fieldConfig ? fieldConfig.ariaLabel : void 0,
|
|
1374
|
+
className: "className" in fieldConfig ? fieldConfig.className : void 0,
|
|
1375
|
+
description: "description" in fieldConfig ? fieldConfig.description : void 0,
|
|
1376
|
+
isDisabled: ("isDisabled" in fieldConfig ? fieldConfig.isDisabled : void 0) ?? submissionState.isSubmitting,
|
|
1377
|
+
label: "label" in fieldConfig ? fieldConfig.label : void 0,
|
|
1378
|
+
// name is Path<TFieldValues> | string, but FieldBaseProps expects Path<TFieldValues>
|
|
1379
|
+
// We pass it directly to each component instead of through baseProps
|
|
1380
|
+
rules: "rules" in fieldConfig ? fieldConfig.rules : void 0
|
|
1381
|
+
};
|
|
1382
|
+
switch (fieldConfig.type) {
|
|
1383
|
+
case "input": {
|
|
1384
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1385
|
+
InputField,
|
|
1386
|
+
{
|
|
1387
|
+
...baseProps,
|
|
1388
|
+
name: fieldConfig.name,
|
|
1389
|
+
control,
|
|
1390
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0,
|
|
1391
|
+
inputProps: "inputProps" in fieldConfig ? fieldConfig.inputProps : void 0
|
|
1392
|
+
}
|
|
1393
|
+
);
|
|
1394
|
+
}
|
|
1395
|
+
case "textarea": {
|
|
1396
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1397
|
+
TextareaField,
|
|
1398
|
+
{
|
|
1399
|
+
...baseProps,
|
|
1400
|
+
name: fieldConfig.name,
|
|
1401
|
+
control,
|
|
1402
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0,
|
|
1403
|
+
textareaProps: "textareaProps" in fieldConfig ? fieldConfig.textareaProps : void 0
|
|
1404
|
+
}
|
|
1405
|
+
);
|
|
1406
|
+
}
|
|
1407
|
+
case "select": {
|
|
1408
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1409
|
+
SelectField,
|
|
1410
|
+
{
|
|
1411
|
+
...baseProps,
|
|
1412
|
+
name: fieldConfig.name,
|
|
1413
|
+
control,
|
|
1414
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0,
|
|
1415
|
+
options: "options" in fieldConfig && fieldConfig.options ? fieldConfig.options.map((opt) => ({
|
|
1416
|
+
label: opt.label,
|
|
1417
|
+
value: String(opt.value)
|
|
1418
|
+
})) : [],
|
|
1419
|
+
selectProps: "selectProps" in fieldConfig ? fieldConfig.selectProps : void 0
|
|
1420
|
+
}
|
|
1421
|
+
);
|
|
1422
|
+
}
|
|
1423
|
+
case "autocomplete": {
|
|
1424
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1425
|
+
AutocompleteField,
|
|
1426
|
+
{
|
|
1427
|
+
...baseProps,
|
|
1428
|
+
name: fieldConfig.name,
|
|
1429
|
+
control,
|
|
1430
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0,
|
|
1431
|
+
items: ("options" in fieldConfig && fieldConfig.options ? fieldConfig.options : []).map((opt) => ({
|
|
1432
|
+
label: opt.label,
|
|
1433
|
+
value: String(opt.value)
|
|
1434
|
+
})),
|
|
1435
|
+
autocompleteProps: "autocompleteProps" in fieldConfig ? fieldConfig.autocompleteProps : void 0
|
|
1436
|
+
}
|
|
1437
|
+
);
|
|
1438
|
+
}
|
|
1439
|
+
case "checkbox": {
|
|
1440
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1441
|
+
CheckboxField,
|
|
1442
|
+
{
|
|
1443
|
+
...baseProps,
|
|
1444
|
+
name: fieldConfig.name,
|
|
1445
|
+
checkboxProps: "checkboxProps" in fieldConfig ? fieldConfig.checkboxProps : void 0,
|
|
1446
|
+
control,
|
|
1447
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0
|
|
1448
|
+
}
|
|
1449
|
+
);
|
|
1450
|
+
}
|
|
1451
|
+
case "checkboxGroup": {
|
|
1452
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1453
|
+
CheckboxGroupField,
|
|
1454
|
+
{
|
|
1455
|
+
...baseProps,
|
|
1456
|
+
name: fieldConfig.name,
|
|
1457
|
+
checkboxProps: "checkboxProps" in fieldConfig ? fieldConfig.checkboxProps : void 0,
|
|
1458
|
+
control,
|
|
1459
|
+
defaultValue: "defaultValue" in fieldConfig && fieldConfig.defaultValue && Array.isArray(fieldConfig.defaultValue) ? fieldConfig.defaultValue.map((v) => String(v)) : void 0,
|
|
1460
|
+
options: ("checkboxGroupOptions" in fieldConfig && fieldConfig.checkboxGroupOptions ? fieldConfig.checkboxGroupOptions : []).map((opt) => ({
|
|
1461
|
+
label: opt.label,
|
|
1462
|
+
value: String(opt.value)
|
|
1463
|
+
})),
|
|
1464
|
+
orientation: "orientation" in fieldConfig ? fieldConfig.orientation : void 0
|
|
1465
|
+
}
|
|
1466
|
+
);
|
|
1467
|
+
}
|
|
1468
|
+
case "radio": {
|
|
1469
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1470
|
+
RadioGroupField,
|
|
1471
|
+
{
|
|
1472
|
+
...baseProps,
|
|
1473
|
+
name: fieldConfig.name,
|
|
1474
|
+
control,
|
|
1475
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0,
|
|
1476
|
+
options: ("radioOptions" in fieldConfig && fieldConfig.radioOptions ? fieldConfig.radioOptions : []).map((opt) => ({
|
|
1477
|
+
label: opt.label,
|
|
1478
|
+
value: String(opt.value)
|
|
1479
|
+
})),
|
|
1480
|
+
radioGroupProps: "radioProps" in fieldConfig ? fieldConfig.radioProps : void 0
|
|
1481
|
+
}
|
|
1482
|
+
);
|
|
1483
|
+
}
|
|
1484
|
+
case "switch": {
|
|
1485
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1486
|
+
SwitchField,
|
|
1487
|
+
{
|
|
1488
|
+
...baseProps,
|
|
1489
|
+
name: fieldConfig.name,
|
|
1490
|
+
control,
|
|
1491
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0,
|
|
1492
|
+
switchProps: "switchProps" in fieldConfig ? fieldConfig.switchProps : void 0
|
|
1493
|
+
}
|
|
1494
|
+
);
|
|
1495
|
+
}
|
|
1496
|
+
case "slider": {
|
|
1497
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1498
|
+
SliderField,
|
|
1499
|
+
{
|
|
1500
|
+
...baseProps,
|
|
1501
|
+
name: fieldConfig.name,
|
|
1502
|
+
control,
|
|
1503
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0,
|
|
1504
|
+
sliderProps: "sliderProps" in fieldConfig ? fieldConfig.sliderProps : void 0
|
|
1505
|
+
}
|
|
1506
|
+
);
|
|
1507
|
+
}
|
|
1508
|
+
case "stringArray": {
|
|
1509
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1510
|
+
StringArrayField,
|
|
1511
|
+
{
|
|
1512
|
+
...baseProps,
|
|
1513
|
+
name: fieldConfig.name,
|
|
1514
|
+
control,
|
|
1515
|
+
stringArrayProps: "stringArrayProps" in fieldConfig ? fieldConfig.stringArrayProps : void 0,
|
|
1516
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0
|
|
1517
|
+
}
|
|
1518
|
+
);
|
|
1519
|
+
}
|
|
1520
|
+
case "date": {
|
|
1521
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1522
|
+
DateField,
|
|
1523
|
+
{
|
|
1524
|
+
...baseProps,
|
|
1525
|
+
name: fieldConfig.name,
|
|
1526
|
+
control,
|
|
1527
|
+
dateProps: "dateProps" in fieldConfig ? fieldConfig.dateProps : void 0,
|
|
1528
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0
|
|
1529
|
+
}
|
|
1530
|
+
);
|
|
1531
|
+
}
|
|
1532
|
+
case "file": {
|
|
1533
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1534
|
+
FileField,
|
|
1535
|
+
{
|
|
1536
|
+
...baseProps,
|
|
1537
|
+
name: fieldConfig.name,
|
|
1538
|
+
accept: "accept" in fieldConfig ? fieldConfig.accept : void 0,
|
|
1539
|
+
control,
|
|
1540
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0,
|
|
1541
|
+
fileProps: "fileProps" in fieldConfig ? fieldConfig.fileProps : void 0,
|
|
1542
|
+
multiple: "multiple" in fieldConfig ? fieldConfig.multiple : void 0
|
|
1543
|
+
}
|
|
1544
|
+
);
|
|
1545
|
+
}
|
|
1546
|
+
case "fontPicker": {
|
|
1547
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1548
|
+
FontPickerField,
|
|
1549
|
+
{
|
|
1550
|
+
...baseProps,
|
|
1551
|
+
name: fieldConfig.name,
|
|
1552
|
+
control,
|
|
1553
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0,
|
|
1554
|
+
fontPickerProps: "fontPickerProps" in fieldConfig ? fieldConfig.fontPickerProps : void 0
|
|
1555
|
+
}
|
|
1556
|
+
);
|
|
1557
|
+
}
|
|
1558
|
+
case "custom": {
|
|
1559
|
+
if (!("render" in fieldConfig)) {
|
|
1135
1560
|
return null;
|
|
1136
1561
|
}
|
|
1562
|
+
return fieldConfig.render({
|
|
1563
|
+
control,
|
|
1564
|
+
errors: form.formState.errors,
|
|
1565
|
+
form,
|
|
1566
|
+
isSubmitting: submissionState.isSubmitting,
|
|
1567
|
+
name: fieldConfig.name
|
|
1568
|
+
});
|
|
1137
1569
|
}
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
defaultValue: config.defaultValue,
|
|
1156
|
-
inputProps: config.inputProps
|
|
1157
|
-
}
|
|
1158
|
-
);
|
|
1159
|
-
case "textarea":
|
|
1160
|
-
return /* @__PURE__ */ React17.createElement(
|
|
1161
|
-
TextareaField,
|
|
1162
|
-
{
|
|
1163
|
-
...baseProps,
|
|
1164
|
-
control,
|
|
1165
|
-
defaultValue: config.defaultValue,
|
|
1166
|
-
textareaProps: config.textareaProps
|
|
1167
|
-
}
|
|
1168
|
-
);
|
|
1169
|
-
case "select":
|
|
1170
|
-
return /* @__PURE__ */ React17.createElement(
|
|
1171
|
-
SelectField,
|
|
1172
|
-
{
|
|
1173
|
-
...baseProps,
|
|
1174
|
-
control,
|
|
1175
|
-
defaultValue: config.defaultValue,
|
|
1176
|
-
options: (config.options ?? []).map((opt) => ({
|
|
1177
|
-
label: opt.label,
|
|
1178
|
-
value: String(opt.value)
|
|
1179
|
-
})),
|
|
1180
|
-
selectProps: config.selectProps
|
|
1181
|
-
}
|
|
1182
|
-
);
|
|
1183
|
-
case "autocomplete":
|
|
1184
|
-
return /* @__PURE__ */ React17.createElement(
|
|
1185
|
-
AutocompleteField,
|
|
1186
|
-
{
|
|
1187
|
-
...baseProps,
|
|
1188
|
-
control,
|
|
1189
|
-
defaultValue: config.defaultValue,
|
|
1190
|
-
items: (config.options ?? []).map((opt) => ({
|
|
1191
|
-
label: opt.label,
|
|
1192
|
-
value: String(opt.value)
|
|
1193
|
-
})),
|
|
1194
|
-
autocompleteProps: config.autocompleteProps
|
|
1195
|
-
}
|
|
1196
|
-
);
|
|
1197
|
-
case "checkbox":
|
|
1198
|
-
return /* @__PURE__ */ React17.createElement(
|
|
1199
|
-
CheckboxField,
|
|
1200
|
-
{
|
|
1201
|
-
...baseProps,
|
|
1202
|
-
checkboxProps: config.checkboxProps,
|
|
1203
|
-
control,
|
|
1204
|
-
defaultValue: config.defaultValue
|
|
1205
|
-
}
|
|
1206
|
-
);
|
|
1207
|
-
case "radio":
|
|
1208
|
-
return /* @__PURE__ */ React17.createElement(
|
|
1209
|
-
RadioGroupField,
|
|
1210
|
-
{
|
|
1211
|
-
...baseProps,
|
|
1212
|
-
control,
|
|
1213
|
-
defaultValue: config.defaultValue,
|
|
1214
|
-
options: (config.radioOptions ?? []).map((opt) => ({
|
|
1215
|
-
label: opt.label,
|
|
1216
|
-
value: String(opt.value)
|
|
1217
|
-
})),
|
|
1218
|
-
radioGroupProps: config.radioProps
|
|
1219
|
-
}
|
|
1220
|
-
);
|
|
1221
|
-
case "switch":
|
|
1222
|
-
return /* @__PURE__ */ React17.createElement(
|
|
1223
|
-
SwitchField,
|
|
1224
|
-
{
|
|
1225
|
-
...baseProps,
|
|
1226
|
-
control,
|
|
1227
|
-
defaultValue: config.defaultValue,
|
|
1228
|
-
switchProps: config.switchProps
|
|
1229
|
-
}
|
|
1230
|
-
);
|
|
1231
|
-
case "slider":
|
|
1232
|
-
return /* @__PURE__ */ React17.createElement(
|
|
1233
|
-
SliderField,
|
|
1234
|
-
{
|
|
1235
|
-
...baseProps,
|
|
1236
|
-
control,
|
|
1237
|
-
defaultValue: config.defaultValue,
|
|
1238
|
-
sliderProps: config.sliderProps
|
|
1239
|
-
}
|
|
1240
|
-
);
|
|
1241
|
-
case "date":
|
|
1242
|
-
return /* @__PURE__ */ React17.createElement(
|
|
1243
|
-
DateField,
|
|
1244
|
-
{
|
|
1245
|
-
...baseProps,
|
|
1246
|
-
control,
|
|
1247
|
-
dateProps: config.dateProps,
|
|
1248
|
-
defaultValue: config.defaultValue
|
|
1249
|
-
}
|
|
1250
|
-
);
|
|
1251
|
-
case "file":
|
|
1252
|
-
return /* @__PURE__ */ React17.createElement(
|
|
1253
|
-
FileField,
|
|
1254
|
-
{
|
|
1255
|
-
...baseProps,
|
|
1256
|
-
accept: config.accept,
|
|
1257
|
-
control,
|
|
1258
|
-
defaultValue: config.defaultValue,
|
|
1259
|
-
fileProps: config.fileProps,
|
|
1260
|
-
multiple: config.multiple
|
|
1261
|
-
}
|
|
1262
|
-
);
|
|
1263
|
-
case "fontPicker":
|
|
1264
|
-
return /* @__PURE__ */ React17.createElement(
|
|
1265
|
-
FontPickerField,
|
|
1266
|
-
{
|
|
1267
|
-
...baseProps,
|
|
1268
|
-
control,
|
|
1269
|
-
defaultValue: config.defaultValue,
|
|
1270
|
-
fontPickerProps: config.fontPickerProps
|
|
1271
|
-
}
|
|
1272
|
-
);
|
|
1273
|
-
case "custom":
|
|
1274
|
-
return config.render({
|
|
1570
|
+
case "conditional": {
|
|
1571
|
+
if (!("condition" in fieldConfig) || !("field" in fieldConfig)) {
|
|
1572
|
+
return null;
|
|
1573
|
+
}
|
|
1574
|
+
const conditionalConfig = {
|
|
1575
|
+
className: "className" in fieldConfig ? fieldConfig.className : void 0,
|
|
1576
|
+
condition: fieldConfig.condition,
|
|
1577
|
+
description: "description" in fieldConfig ? fieldConfig.description : void 0,
|
|
1578
|
+
field: fieldConfig.field,
|
|
1579
|
+
label: "label" in fieldConfig ? fieldConfig.label : void 0,
|
|
1580
|
+
name: fieldConfig.name,
|
|
1581
|
+
type: "conditional"
|
|
1582
|
+
};
|
|
1583
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1584
|
+
ConditionalField,
|
|
1585
|
+
{
|
|
1586
|
+
config: conditionalConfig,
|
|
1275
1587
|
control,
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
return
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1588
|
+
className: conditionalConfig.className
|
|
1589
|
+
}
|
|
1590
|
+
);
|
|
1591
|
+
}
|
|
1592
|
+
case "fieldArray": {
|
|
1593
|
+
if (!("fields" in fieldConfig) || !fieldConfig.fields) {
|
|
1594
|
+
return null;
|
|
1595
|
+
}
|
|
1596
|
+
const fieldArrayConfig = {
|
|
1597
|
+
addButtonText: "addButtonText" in fieldConfig ? fieldConfig.addButtonText : void 0,
|
|
1598
|
+
className: "className" in fieldConfig ? fieldConfig.className : void 0,
|
|
1599
|
+
defaultItem: "defaultItem" in fieldConfig ? fieldConfig.defaultItem : void 0,
|
|
1600
|
+
description: "description" in fieldConfig ? fieldConfig.description : void 0,
|
|
1601
|
+
enableReordering: "enableReordering" in fieldConfig ? fieldConfig.enableReordering : void 0,
|
|
1602
|
+
fields: fieldConfig.fields,
|
|
1603
|
+
label: "label" in fieldConfig ? fieldConfig.label : void 0,
|
|
1604
|
+
max: "max" in fieldConfig ? fieldConfig.max : void 0,
|
|
1605
|
+
min: "min" in fieldConfig ? fieldConfig.min : void 0,
|
|
1606
|
+
name: fieldConfig.name,
|
|
1607
|
+
removeButtonText: "removeButtonText" in fieldConfig ? fieldConfig.removeButtonText : void 0,
|
|
1608
|
+
renderAddButton: "renderAddButton" in fieldConfig ? fieldConfig.renderAddButton : void 0,
|
|
1609
|
+
renderItem: "renderItem" in fieldConfig ? fieldConfig.renderItem : void 0,
|
|
1610
|
+
reorderButtonText: "reorderButtonText" in fieldConfig ? fieldConfig.reorderButtonText : void 0,
|
|
1611
|
+
type: "fieldArray"
|
|
1612
|
+
};
|
|
1613
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1614
|
+
FieldArrayField,
|
|
1615
|
+
{
|
|
1616
|
+
config: fieldArrayConfig,
|
|
1617
|
+
className: fieldArrayConfig.className
|
|
1618
|
+
}
|
|
1619
|
+
);
|
|
1620
|
+
}
|
|
1621
|
+
case "dynamicSection": {
|
|
1622
|
+
if (!("sections" in fieldConfig) || !("condition" in fieldConfig) || !("fields" in fieldConfig)) {
|
|
1310
1623
|
return null;
|
|
1311
1624
|
}
|
|
1625
|
+
const dynamicSectionConfig = {
|
|
1626
|
+
className: "className" in fieldConfig ? fieldConfig.className : void 0,
|
|
1627
|
+
condition: fieldConfig.condition,
|
|
1628
|
+
description: "description" in fieldConfig ? fieldConfig.description : void 0,
|
|
1629
|
+
fields: fieldConfig.fields,
|
|
1630
|
+
label: "label" in fieldConfig ? fieldConfig.label : void 0,
|
|
1631
|
+
name: fieldConfig.name,
|
|
1632
|
+
title: "title" in fieldConfig ? fieldConfig.title : void 0,
|
|
1633
|
+
type: "dynamicSection"
|
|
1634
|
+
};
|
|
1635
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1636
|
+
DynamicSectionField,
|
|
1637
|
+
{
|
|
1638
|
+
config: dynamicSectionConfig,
|
|
1639
|
+
control,
|
|
1640
|
+
className: dynamicSectionConfig.className
|
|
1641
|
+
}
|
|
1642
|
+
);
|
|
1643
|
+
}
|
|
1644
|
+
default: {
|
|
1645
|
+
const fieldType = "type" in config ? config.type : "unknown";
|
|
1646
|
+
console.warn(`Unknown field type: ${fieldType}`);
|
|
1647
|
+
return null;
|
|
1312
1648
|
}
|
|
1313
1649
|
}
|
|
1314
|
-
|
|
1650
|
+
}
|
|
1651
|
+
var FormField = FormFieldComponent;
|
|
1315
1652
|
|
|
1316
1653
|
// src/components/Form.tsx
|
|
1317
1654
|
function ConfigurableForm({
|
|
@@ -1348,12 +1685,12 @@ function ConfigurableForm({
|
|
|
1348
1685
|
});
|
|
1349
1686
|
const renderFields = () => {
|
|
1350
1687
|
if (layout === "grid") {
|
|
1351
|
-
return /* @__PURE__ */
|
|
1688
|
+
return /* @__PURE__ */ React20.createElement(
|
|
1352
1689
|
"div",
|
|
1353
1690
|
{
|
|
1354
1691
|
className: `grid gap-${spacing} ${columns === 1 ? "grid-cols-1" : columns === 2 ? "grid-cols-1 md:grid-cols-2" : "grid-cols-1 md:grid-cols-2 lg:grid-cols-3"}`
|
|
1355
1692
|
},
|
|
1356
|
-
fields.map((field2) => /* @__PURE__ */
|
|
1693
|
+
fields.map((field2) => /* @__PURE__ */ React20.createElement(
|
|
1357
1694
|
FormField,
|
|
1358
1695
|
{
|
|
1359
1696
|
key: field2.name,
|
|
@@ -1365,7 +1702,7 @@ function ConfigurableForm({
|
|
|
1365
1702
|
);
|
|
1366
1703
|
}
|
|
1367
1704
|
if (layout === "horizontal") {
|
|
1368
|
-
return /* @__PURE__ */
|
|
1705
|
+
return /* @__PURE__ */ React20.createElement("div", { className: `grid gap-${spacing} grid-cols-1 md:grid-cols-2` }, fields.map((field2) => /* @__PURE__ */ React20.createElement(
|
|
1369
1706
|
FormField,
|
|
1370
1707
|
{
|
|
1371
1708
|
key: field2.name,
|
|
@@ -1375,10 +1712,10 @@ function ConfigurableForm({
|
|
|
1375
1712
|
}
|
|
1376
1713
|
)));
|
|
1377
1714
|
}
|
|
1378
|
-
return /* @__PURE__ */
|
|
1715
|
+
return /* @__PURE__ */ React20.createElement("div", { className: `space-y-${spacing}` }, fields.map((field2) => /* @__PURE__ */ React20.createElement(
|
|
1379
1716
|
FormField,
|
|
1380
1717
|
{
|
|
1381
|
-
key: field2.name
|
|
1718
|
+
key: field2.name ? pathToString(field2.name) : `field-${Math.random()}`,
|
|
1382
1719
|
config: field2,
|
|
1383
1720
|
form,
|
|
1384
1721
|
submissionState
|
|
@@ -1389,23 +1726,23 @@ function ConfigurableForm({
|
|
|
1389
1726
|
e.preventDefault();
|
|
1390
1727
|
void handleSubmit();
|
|
1391
1728
|
};
|
|
1392
|
-
return /* @__PURE__ */
|
|
1729
|
+
return /* @__PURE__ */ React20.createElement("form", { className, role: "form", onSubmit: handleFormSubmit }, title && /* @__PURE__ */ React20.createElement("div", { className: "mb-6" }, /* @__PURE__ */ React20.createElement("h2", { className: "text-xl font-semibold text-foreground mb-2" }, title), subtitle && /* @__PURE__ */ React20.createElement("p", { className: "text-sm text-muted-foreground" }, subtitle)), isSubmitted && isSuccess && /* @__PURE__ */ React20.createElement(
|
|
1393
1730
|
"div",
|
|
1394
1731
|
{
|
|
1395
1732
|
className: "mb-6 p-4 bg-success-50 border border-success-200 rounded-lg",
|
|
1396
1733
|
"data-testid": "success-message"
|
|
1397
1734
|
},
|
|
1398
|
-
/* @__PURE__ */
|
|
1399
|
-
/* @__PURE__ */
|
|
1400
|
-
), error && /* @__PURE__ */
|
|
1735
|
+
/* @__PURE__ */ React20.createElement("p", { className: "text-success-800 font-medium" }, "Success!"),
|
|
1736
|
+
/* @__PURE__ */ React20.createElement("p", { className: "text-success-700 text-sm mt-1" }, "Your request has been processed successfully.")
|
|
1737
|
+
), error && /* @__PURE__ */ React20.createElement(
|
|
1401
1738
|
"div",
|
|
1402
1739
|
{
|
|
1403
1740
|
className: "mb-6 p-4 bg-danger-50 border border-danger-200 rounded-lg",
|
|
1404
1741
|
"data-testid": "error-message"
|
|
1405
1742
|
},
|
|
1406
|
-
/* @__PURE__ */
|
|
1407
|
-
/* @__PURE__ */
|
|
1408
|
-
), renderFields(), /* @__PURE__ */
|
|
1743
|
+
/* @__PURE__ */ React20.createElement("p", { className: "text-danger-800 font-medium" }, "Error"),
|
|
1744
|
+
/* @__PURE__ */ React20.createElement("p", { className: "text-danger-700 text-sm mt-1" }, error)
|
|
1745
|
+
), renderFields(), /* @__PURE__ */ React20.createElement("div", { className: "mt-6 flex gap-3 justify-end" }, /* @__PURE__ */ React20.createElement(
|
|
1409
1746
|
Button3,
|
|
1410
1747
|
{
|
|
1411
1748
|
color: "primary",
|
|
@@ -1415,7 +1752,7 @@ function ConfigurableForm({
|
|
|
1415
1752
|
...submitButtonProps
|
|
1416
1753
|
},
|
|
1417
1754
|
submitButtonText
|
|
1418
|
-
), showResetButton && /* @__PURE__ */
|
|
1755
|
+
), showResetButton && /* @__PURE__ */ React20.createElement(
|
|
1419
1756
|
Button3,
|
|
1420
1757
|
{
|
|
1421
1758
|
isDisabled: isSubmitting,
|
|
@@ -1428,7 +1765,7 @@ function ConfigurableForm({
|
|
|
1428
1765
|
}
|
|
1429
1766
|
|
|
1430
1767
|
// src/components/ServerActionForm.tsx
|
|
1431
|
-
import
|
|
1768
|
+
import React21 from "react";
|
|
1432
1769
|
import { useActionState } from "react";
|
|
1433
1770
|
function ServerActionForm({
|
|
1434
1771
|
action,
|
|
@@ -1453,10 +1790,10 @@ function ServerActionForm({
|
|
|
1453
1790
|
action,
|
|
1454
1791
|
initialState ?? { errors: void 0, message: void 0, success: false }
|
|
1455
1792
|
);
|
|
1456
|
-
const formRef =
|
|
1457
|
-
const [clientErrors, setClientErrors] =
|
|
1458
|
-
const lastSubmittedFormData =
|
|
1459
|
-
|
|
1793
|
+
const formRef = React21.useRef(null);
|
|
1794
|
+
const [clientErrors, setClientErrors] = React21.useState({});
|
|
1795
|
+
const lastSubmittedFormData = React21.useRef(null);
|
|
1796
|
+
React21.useEffect(() => {
|
|
1460
1797
|
if (state && (state.errors || state.message && !state.success)) {
|
|
1461
1798
|
onError?.({
|
|
1462
1799
|
errors: state.errors,
|
|
@@ -1464,7 +1801,7 @@ function ServerActionForm({
|
|
|
1464
1801
|
});
|
|
1465
1802
|
}
|
|
1466
1803
|
}, [state, onError]);
|
|
1467
|
-
|
|
1804
|
+
React21.useEffect(() => {
|
|
1468
1805
|
if (state?.success && lastSubmittedFormData.current) {
|
|
1469
1806
|
onSuccess?.(lastSubmittedFormData.current);
|
|
1470
1807
|
}
|
|
@@ -1477,14 +1814,14 @@ function ServerActionForm({
|
|
|
1477
1814
|
e.preventDefault();
|
|
1478
1815
|
if (clientValidationSchema) {
|
|
1479
1816
|
const formData2 = new FormData(e.currentTarget);
|
|
1817
|
+
const form = e.currentTarget;
|
|
1480
1818
|
const values = {};
|
|
1481
1819
|
formData2.forEach((val, key) => {
|
|
1482
|
-
|
|
1820
|
+
const formElement = form.querySelector(
|
|
1821
|
+
`input[type="checkbox"][name="${key}"], input[role="switch"][name="${key}"]`
|
|
1822
|
+
);
|
|
1823
|
+
if (formElement instanceof HTMLInputElement && (formElement.type === "checkbox" || formElement.getAttribute("role") === "switch")) {
|
|
1483
1824
|
values[key] = true;
|
|
1484
|
-
} else if (val === "") {
|
|
1485
|
-
if (!values[key]) {
|
|
1486
|
-
values[key] = false;
|
|
1487
|
-
}
|
|
1488
1825
|
} else {
|
|
1489
1826
|
values[key] = val;
|
|
1490
1827
|
}
|
|
@@ -1507,12 +1844,12 @@ function ServerActionForm({
|
|
|
1507
1844
|
};
|
|
1508
1845
|
const renderFields = () => {
|
|
1509
1846
|
if (layout === "grid") {
|
|
1510
|
-
return /* @__PURE__ */
|
|
1847
|
+
return /* @__PURE__ */ React21.createElement(
|
|
1511
1848
|
"div",
|
|
1512
1849
|
{
|
|
1513
1850
|
className: `grid gap-${spacing} ${columns === 1 ? "grid-cols-1" : columns === 2 ? "grid-cols-1 md:grid-cols-2" : "grid-cols-1 md:grid-cols-2 lg:grid-cols-3"}`
|
|
1514
1851
|
},
|
|
1515
|
-
fields.map((field2) => /* @__PURE__ */
|
|
1852
|
+
fields.map((field2) => /* @__PURE__ */ React21.createElement(
|
|
1516
1853
|
ServerActionField,
|
|
1517
1854
|
{
|
|
1518
1855
|
key: field2.name,
|
|
@@ -1525,7 +1862,7 @@ function ServerActionForm({
|
|
|
1525
1862
|
);
|
|
1526
1863
|
}
|
|
1527
1864
|
if (layout === "horizontal") {
|
|
1528
|
-
return /* @__PURE__ */
|
|
1865
|
+
return /* @__PURE__ */ React21.createElement("div", { className: `grid gap-${spacing} grid-cols-1 md:grid-cols-2` }, fields.map((field2) => /* @__PURE__ */ React21.createElement(
|
|
1529
1866
|
ServerActionField,
|
|
1530
1867
|
{
|
|
1531
1868
|
key: field2.name,
|
|
@@ -1536,10 +1873,10 @@ function ServerActionForm({
|
|
|
1536
1873
|
}
|
|
1537
1874
|
)));
|
|
1538
1875
|
}
|
|
1539
|
-
return /* @__PURE__ */
|
|
1876
|
+
return /* @__PURE__ */ React21.createElement("div", { className: `space-y-${spacing}` }, fields.map((field2) => /* @__PURE__ */ React21.createElement(
|
|
1540
1877
|
ServerActionField,
|
|
1541
1878
|
{
|
|
1542
|
-
key: field2.name,
|
|
1879
|
+
key: pathToString(field2.name),
|
|
1543
1880
|
clientErrors,
|
|
1544
1881
|
defaultValues,
|
|
1545
1882
|
errors: state?.errors,
|
|
@@ -1547,7 +1884,7 @@ function ServerActionForm({
|
|
|
1547
1884
|
}
|
|
1548
1885
|
)));
|
|
1549
1886
|
};
|
|
1550
|
-
return /* @__PURE__ */
|
|
1887
|
+
return /* @__PURE__ */ React21.createElement(
|
|
1551
1888
|
"form",
|
|
1552
1889
|
{
|
|
1553
1890
|
ref: formRef,
|
|
@@ -1555,27 +1892,27 @@ function ServerActionForm({
|
|
|
1555
1892
|
role: "form",
|
|
1556
1893
|
onSubmit: handleSubmit
|
|
1557
1894
|
},
|
|
1558
|
-
title && /* @__PURE__ */
|
|
1559
|
-
state?.success && !pending && /* @__PURE__ */
|
|
1895
|
+
title && /* @__PURE__ */ React21.createElement("div", { className: "mb-6" }, /* @__PURE__ */ React21.createElement("h2", { className: "text-xl font-semibold text-foreground mb-2" }, title), subtitle && /* @__PURE__ */ React21.createElement("p", { className: "text-sm text-muted-foreground" }, subtitle)),
|
|
1896
|
+
state?.success && !pending && /* @__PURE__ */ React21.createElement(
|
|
1560
1897
|
"div",
|
|
1561
1898
|
{
|
|
1562
1899
|
className: "mb-6 p-4 bg-success-50 border border-success-200 rounded-lg",
|
|
1563
1900
|
"data-testid": "success-message"
|
|
1564
1901
|
},
|
|
1565
|
-
/* @__PURE__ */
|
|
1566
|
-
state.message && /* @__PURE__ */
|
|
1902
|
+
/* @__PURE__ */ React21.createElement("p", { className: "text-success-800 font-medium" }, "Success!"),
|
|
1903
|
+
state.message && /* @__PURE__ */ React21.createElement("p", { className: "text-success-700 text-sm mt-1" }, state.message)
|
|
1567
1904
|
),
|
|
1568
|
-
state?.message && !state.success && /* @__PURE__ */
|
|
1905
|
+
state?.message && !state.success && /* @__PURE__ */ React21.createElement(
|
|
1569
1906
|
"div",
|
|
1570
1907
|
{
|
|
1571
1908
|
className: "mb-6 p-4 bg-danger-50 border border-danger-200 rounded-lg",
|
|
1572
1909
|
"data-testid": "error-message"
|
|
1573
1910
|
},
|
|
1574
|
-
/* @__PURE__ */
|
|
1575
|
-
/* @__PURE__ */
|
|
1911
|
+
/* @__PURE__ */ React21.createElement("p", { className: "text-danger-800 font-medium" }, "Error"),
|
|
1912
|
+
/* @__PURE__ */ React21.createElement("p", { className: "text-danger-700 text-sm mt-1" }, state.message)
|
|
1576
1913
|
),
|
|
1577
1914
|
renderFields(),
|
|
1578
|
-
/* @__PURE__ */
|
|
1915
|
+
/* @__PURE__ */ React21.createElement("div", { className: "mt-6 flex gap-3 justify-end" }, /* @__PURE__ */ React21.createElement(
|
|
1579
1916
|
Button,
|
|
1580
1917
|
{
|
|
1581
1918
|
color: "primary",
|
|
@@ -1585,7 +1922,7 @@ function ServerActionForm({
|
|
|
1585
1922
|
...submitButtonProps
|
|
1586
1923
|
},
|
|
1587
1924
|
submitButtonText
|
|
1588
|
-
), showResetButton && /* @__PURE__ */
|
|
1925
|
+
), showResetButton && /* @__PURE__ */ React21.createElement(
|
|
1589
1926
|
Button,
|
|
1590
1927
|
{
|
|
1591
1928
|
isDisabled: pending,
|
|
@@ -1603,24 +1940,44 @@ function ServerActionField({
|
|
|
1603
1940
|
errors,
|
|
1604
1941
|
field: field2
|
|
1605
1942
|
}) {
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1943
|
+
const fieldConfig = field2;
|
|
1944
|
+
const getBaseProps = () => {
|
|
1945
|
+
const baseProps2 = {};
|
|
1946
|
+
if ("label" in fieldConfig) {
|
|
1947
|
+
baseProps2.label = fieldConfig.label;
|
|
1948
|
+
}
|
|
1949
|
+
if ("description" in fieldConfig) {
|
|
1950
|
+
baseProps2.description = fieldConfig.description;
|
|
1951
|
+
}
|
|
1952
|
+
if ("isDisabled" in fieldConfig) {
|
|
1953
|
+
baseProps2.isDisabled = fieldConfig.isDisabled;
|
|
1954
|
+
}
|
|
1955
|
+
return baseProps2;
|
|
1956
|
+
};
|
|
1957
|
+
const baseProps = getBaseProps();
|
|
1958
|
+
if (fieldConfig.type === "content") {
|
|
1959
|
+
const contentField = fieldConfig;
|
|
1960
|
+
if (contentField.render) {
|
|
1961
|
+
const mockForm = {
|
|
1962
|
+
formState: { errors: {} },
|
|
1963
|
+
watch: () => ({})
|
|
1964
|
+
};
|
|
1965
|
+
const renderFn = contentField.render;
|
|
1966
|
+
return /* @__PURE__ */ React21.createElement("div", { className: contentField.className }, renderFn({
|
|
1610
1967
|
errors: {},
|
|
1611
|
-
form:
|
|
1968
|
+
form: mockForm,
|
|
1612
1969
|
isSubmitting: false
|
|
1613
1970
|
}));
|
|
1614
1971
|
}
|
|
1615
|
-
return /* @__PURE__ */
|
|
1972
|
+
return /* @__PURE__ */ React21.createElement("div", { className: contentField.className }, contentField.title && /* @__PURE__ */ React21.createElement("h3", { className: "text-lg font-semibold text-foreground mb-2" }, contentField.title), contentField.description && /* @__PURE__ */ React21.createElement("p", { className: "text-sm text-muted-foreground" }, contentField.description));
|
|
1616
1973
|
}
|
|
1617
|
-
const fieldName =
|
|
1974
|
+
const fieldName = pathToString(fieldConfig.name);
|
|
1618
1975
|
const fieldErrors = errors?.[fieldName];
|
|
1619
1976
|
const clientError = clientErrors?.[fieldName];
|
|
1620
1977
|
const errorMessage = clientError || (fieldErrors && fieldErrors.length > 0 ? fieldErrors[0] : void 0);
|
|
1621
1978
|
const getDefaultValue = () => {
|
|
1622
1979
|
const fromProps = defaultValues?.[fieldName];
|
|
1623
|
-
const fromField =
|
|
1980
|
+
const fromField = "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0;
|
|
1624
1981
|
if (fromProps !== void 0 && fromProps !== null) {
|
|
1625
1982
|
return typeof fromProps === "string" ? fromProps : String(fromProps);
|
|
1626
1983
|
}
|
|
@@ -1631,7 +1988,7 @@ function ServerActionField({
|
|
|
1631
1988
|
};
|
|
1632
1989
|
const getDefaultChecked = () => {
|
|
1633
1990
|
const fromProps = defaultValues?.[fieldName];
|
|
1634
|
-
const fromField =
|
|
1991
|
+
const fromField = "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0;
|
|
1635
1992
|
if (fromProps !== void 0 && fromProps !== null) {
|
|
1636
1993
|
return typeof fromProps === "boolean" ? fromProps : false;
|
|
1637
1994
|
}
|
|
@@ -1640,94 +1997,182 @@ function ServerActionField({
|
|
|
1640
1997
|
}
|
|
1641
1998
|
return false;
|
|
1642
1999
|
};
|
|
1643
|
-
const [value, setValue] =
|
|
1644
|
-
const [checked, setChecked] =
|
|
1645
|
-
|
|
2000
|
+
const [value, setValue] = React21.useState(getDefaultValue);
|
|
2001
|
+
const [checked, setChecked] = React21.useState(getDefaultChecked);
|
|
2002
|
+
React21.useEffect(() => {
|
|
1646
2003
|
const newDefaultValue = defaultValues?.[fieldName];
|
|
1647
2004
|
if (newDefaultValue !== void 0 && newDefaultValue !== null) {
|
|
1648
|
-
if (
|
|
2005
|
+
if (fieldConfig.type === "checkbox") {
|
|
1649
2006
|
setChecked(
|
|
1650
2007
|
typeof newDefaultValue === "boolean" ? newDefaultValue : false
|
|
1651
2008
|
);
|
|
2009
|
+
} else if (fieldConfig.type === "checkboxGroup") {
|
|
2010
|
+
const arrayValue = Array.isArray(newDefaultValue) ? newDefaultValue.map(String).join(",") : "";
|
|
2011
|
+
setValue(arrayValue);
|
|
1652
2012
|
} else {
|
|
1653
2013
|
setValue(
|
|
1654
2014
|
typeof newDefaultValue === "string" ? newDefaultValue : String(newDefaultValue)
|
|
1655
2015
|
);
|
|
1656
2016
|
}
|
|
1657
2017
|
}
|
|
1658
|
-
}, [defaultValues, fieldName,
|
|
1659
|
-
|
|
2018
|
+
}, [defaultValues, fieldName, fieldConfig.type]);
|
|
2019
|
+
React21.useEffect(() => {
|
|
2020
|
+
if (fieldConfig.type !== "date") {
|
|
2021
|
+
return;
|
|
2022
|
+
}
|
|
1660
2023
|
const hiddenInput = document.querySelector(
|
|
1661
2024
|
`input[type="hidden"][name="${fieldName}"]`
|
|
1662
2025
|
);
|
|
2026
|
+
if (!(hiddenInput instanceof HTMLInputElement)) {
|
|
2027
|
+
throw new Error(`Expected HTMLInputElement for field ${fieldName}`);
|
|
2028
|
+
}
|
|
1663
2029
|
if (hiddenInput) {
|
|
1664
|
-
|
|
1665
|
-
hiddenInput.value = checked ? "on" : "";
|
|
1666
|
-
} else {
|
|
1667
|
-
hiddenInput.value = value;
|
|
1668
|
-
}
|
|
2030
|
+
hiddenInput.value = value || "";
|
|
1669
2031
|
}
|
|
1670
|
-
}, [value,
|
|
1671
|
-
switch (
|
|
2032
|
+
}, [value, fieldName, fieldConfig.type]);
|
|
2033
|
+
switch (fieldConfig.type) {
|
|
1672
2034
|
case "input": {
|
|
1673
|
-
const
|
|
1674
|
-
|
|
2035
|
+
const stringConfig = fieldConfig;
|
|
2036
|
+
const inputType = stringConfig.inputProps?.type || "text";
|
|
2037
|
+
return /* @__PURE__ */ React21.createElement(
|
|
1675
2038
|
Input,
|
|
1676
2039
|
{
|
|
1677
|
-
...
|
|
2040
|
+
...stringConfig.inputProps,
|
|
2041
|
+
name: fieldName,
|
|
1678
2042
|
"data-field-name": fieldName,
|
|
1679
2043
|
type: inputType,
|
|
1680
|
-
label:
|
|
1681
|
-
description:
|
|
1682
|
-
isDisabled:
|
|
2044
|
+
label: baseProps.label,
|
|
2045
|
+
description: baseProps.description,
|
|
2046
|
+
isDisabled: baseProps.isDisabled,
|
|
1683
2047
|
isInvalid: Boolean(errorMessage),
|
|
1684
2048
|
errorMessage,
|
|
1685
2049
|
value,
|
|
1686
2050
|
onValueChange: setValue
|
|
1687
2051
|
}
|
|
1688
|
-
)
|
|
2052
|
+
);
|
|
1689
2053
|
}
|
|
1690
2054
|
case "textarea": {
|
|
1691
|
-
|
|
2055
|
+
const stringConfig = fieldConfig;
|
|
2056
|
+
return /* @__PURE__ */ React21.createElement(
|
|
1692
2057
|
Textarea,
|
|
1693
2058
|
{
|
|
1694
|
-
...
|
|
2059
|
+
...stringConfig.textareaProps,
|
|
2060
|
+
name: fieldName,
|
|
1695
2061
|
"data-field-name": fieldName,
|
|
1696
|
-
label:
|
|
1697
|
-
description:
|
|
1698
|
-
isDisabled:
|
|
2062
|
+
label: baseProps.label,
|
|
2063
|
+
description: baseProps.description,
|
|
2064
|
+
isDisabled: baseProps.isDisabled,
|
|
1699
2065
|
isInvalid: Boolean(errorMessage),
|
|
1700
2066
|
errorMessage,
|
|
1701
2067
|
value,
|
|
1702
2068
|
onValueChange: setValue
|
|
1703
2069
|
}
|
|
1704
|
-
)
|
|
2070
|
+
);
|
|
1705
2071
|
}
|
|
1706
2072
|
case "checkbox": {
|
|
1707
|
-
|
|
2073
|
+
const booleanConfig = fieldConfig;
|
|
2074
|
+
const checkboxValue = booleanConfig.checkboxProps?.value ?? "on";
|
|
2075
|
+
const containerRef = React21.useRef(null);
|
|
2076
|
+
React21.useLayoutEffect(() => {
|
|
2077
|
+
const setValue2 = () => {
|
|
2078
|
+
if (containerRef.current) {
|
|
2079
|
+
const input = containerRef.current.querySelector(
|
|
2080
|
+
`input[type="checkbox"][name="${fieldName}"]`
|
|
2081
|
+
);
|
|
2082
|
+
if (input instanceof HTMLInputElement) {
|
|
2083
|
+
input.setAttribute("value", checkboxValue);
|
|
2084
|
+
input.value = checkboxValue;
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2087
|
+
};
|
|
2088
|
+
setValue2();
|
|
2089
|
+
const timeoutId = setTimeout(setValue2, 0);
|
|
2090
|
+
return () => clearTimeout(timeoutId);
|
|
2091
|
+
}, [fieldName, checkboxValue, checked]);
|
|
2092
|
+
return /* @__PURE__ */ React21.createElement("div", { ref: containerRef }, /* @__PURE__ */ React21.createElement(
|
|
1708
2093
|
Checkbox,
|
|
1709
2094
|
{
|
|
1710
|
-
...
|
|
2095
|
+
...booleanConfig.checkboxProps,
|
|
2096
|
+
name: fieldName,
|
|
1711
2097
|
"data-field-name": fieldName,
|
|
1712
|
-
|
|
2098
|
+
value: checkboxValue,
|
|
2099
|
+
isDisabled: baseProps.isDisabled,
|
|
1713
2100
|
isSelected: checked,
|
|
1714
2101
|
onValueChange: setChecked,
|
|
1715
2102
|
isInvalid: Boolean(errorMessage),
|
|
1716
2103
|
errorMessage
|
|
1717
2104
|
},
|
|
1718
|
-
|
|
2105
|
+
baseProps.label
|
|
1719
2106
|
));
|
|
1720
2107
|
}
|
|
2108
|
+
case "checkboxGroup": {
|
|
2109
|
+
const checkboxGroupConfig = fieldConfig;
|
|
2110
|
+
const options = checkboxGroupConfig.checkboxGroupOptions || [];
|
|
2111
|
+
const currentValues = value ? String(value).split(",").filter(Boolean) : [];
|
|
2112
|
+
return /* @__PURE__ */ React21.createElement("div", null, baseProps.label && /* @__PURE__ */ React21.createElement("label", { className: "text-sm font-medium text-foreground block mb-2" }, baseProps.label), baseProps.description && /* @__PURE__ */ React21.createElement("p", { className: "text-sm text-default-500 mb-2" }, baseProps.description), /* @__PURE__ */ React21.createElement(
|
|
2113
|
+
"div",
|
|
2114
|
+
{
|
|
2115
|
+
className: checkboxGroupConfig.orientation === "horizontal" ? "flex flex-row gap-4 flex-wrap" : "flex flex-col gap-2"
|
|
2116
|
+
},
|
|
2117
|
+
options.map(
|
|
2118
|
+
(option) => {
|
|
2119
|
+
const optionValue = String(option.value);
|
|
2120
|
+
const isSelected = currentValues.includes(optionValue);
|
|
2121
|
+
return /* @__PURE__ */ React21.createElement(
|
|
2122
|
+
Checkbox,
|
|
2123
|
+
{
|
|
2124
|
+
key: optionValue,
|
|
2125
|
+
...checkboxGroupConfig.checkboxProps,
|
|
2126
|
+
name: fieldName,
|
|
2127
|
+
"data-field-name": fieldName,
|
|
2128
|
+
"data-checkbox-value": optionValue,
|
|
2129
|
+
isDisabled: baseProps.isDisabled,
|
|
2130
|
+
isSelected,
|
|
2131
|
+
onValueChange: (checked2) => {
|
|
2132
|
+
const newValues = checked2 ? [
|
|
2133
|
+
...currentValues.filter((v) => v !== optionValue),
|
|
2134
|
+
optionValue
|
|
2135
|
+
] : currentValues.filter((v) => v !== optionValue);
|
|
2136
|
+
setValue(newValues.join(","));
|
|
2137
|
+
},
|
|
2138
|
+
isInvalid: Boolean(errorMessage),
|
|
2139
|
+
errorMessage
|
|
2140
|
+
},
|
|
2141
|
+
option.label
|
|
2142
|
+
);
|
|
2143
|
+
}
|
|
2144
|
+
)
|
|
2145
|
+
), errorMessage && /* @__PURE__ */ React21.createElement("p", { className: "text-tiny text-danger mt-1" }, errorMessage));
|
|
2146
|
+
}
|
|
2147
|
+
case "switch": {
|
|
2148
|
+
const booleanConfig = fieldConfig;
|
|
2149
|
+
return /* @__PURE__ */ React21.createElement(
|
|
2150
|
+
Switch,
|
|
2151
|
+
{
|
|
2152
|
+
...booleanConfig.switchProps,
|
|
2153
|
+
name: fieldName,
|
|
2154
|
+
"data-field-name": fieldName,
|
|
2155
|
+
isDisabled: baseProps.isDisabled,
|
|
2156
|
+
isSelected: checked,
|
|
2157
|
+
onValueChange: setChecked,
|
|
2158
|
+
isInvalid: Boolean(errorMessage),
|
|
2159
|
+
errorMessage
|
|
2160
|
+
},
|
|
2161
|
+
baseProps.label
|
|
2162
|
+
);
|
|
2163
|
+
}
|
|
1721
2164
|
case "select": {
|
|
1722
|
-
const
|
|
1723
|
-
|
|
2165
|
+
const stringConfig = fieldConfig;
|
|
2166
|
+
const options = stringConfig.options || [];
|
|
2167
|
+
return /* @__PURE__ */ React21.createElement(
|
|
1724
2168
|
Select,
|
|
1725
2169
|
{
|
|
1726
|
-
...
|
|
2170
|
+
...stringConfig.selectProps,
|
|
2171
|
+
name: fieldName,
|
|
1727
2172
|
"data-field-name": fieldName,
|
|
1728
|
-
label:
|
|
1729
|
-
description:
|
|
1730
|
-
isDisabled:
|
|
2173
|
+
label: baseProps.label,
|
|
2174
|
+
description: baseProps.description,
|
|
2175
|
+
isDisabled: baseProps.isDisabled,
|
|
1731
2176
|
isInvalid: Boolean(errorMessage),
|
|
1732
2177
|
errorMessage,
|
|
1733
2178
|
selectedKeys: value ? [value] : [],
|
|
@@ -1736,25 +2181,142 @@ function ServerActionField({
|
|
|
1736
2181
|
setValue(selectedValue || "");
|
|
1737
2182
|
}
|
|
1738
2183
|
},
|
|
1739
|
-
options.map(
|
|
1740
|
-
|
|
1741
|
-
|
|
2184
|
+
options.map((option) => /* @__PURE__ */ React21.createElement(SelectItem, { key: String(option.value) }, option.label))
|
|
2185
|
+
);
|
|
2186
|
+
}
|
|
2187
|
+
case "radio": {
|
|
2188
|
+
const radioConfig = fieldConfig;
|
|
2189
|
+
const options = radioConfig.radioOptions || [];
|
|
2190
|
+
return /* @__PURE__ */ React21.createElement(
|
|
2191
|
+
RadioGroup,
|
|
2192
|
+
{
|
|
2193
|
+
...radioConfig.radioProps,
|
|
2194
|
+
name: fieldName,
|
|
2195
|
+
"data-field-name": fieldName,
|
|
2196
|
+
label: baseProps.label,
|
|
2197
|
+
description: baseProps.description,
|
|
2198
|
+
isDisabled: baseProps.isDisabled,
|
|
2199
|
+
isInvalid: Boolean(errorMessage),
|
|
2200
|
+
errorMessage,
|
|
2201
|
+
value: value || "",
|
|
2202
|
+
onValueChange: setValue
|
|
2203
|
+
},
|
|
2204
|
+
options.map((option) => /* @__PURE__ */ React21.createElement(Radio, { key: String(option.value), value: String(option.value) }, option.label))
|
|
2205
|
+
);
|
|
2206
|
+
}
|
|
2207
|
+
case "autocomplete": {
|
|
2208
|
+
const stringConfig = fieldConfig;
|
|
2209
|
+
const items = stringConfig.options?.map((opt) => ({
|
|
2210
|
+
label: opt.label,
|
|
2211
|
+
value: String(opt.value)
|
|
2212
|
+
})) || [];
|
|
2213
|
+
return /* @__PURE__ */ React21.createElement(
|
|
2214
|
+
Autocomplete,
|
|
2215
|
+
{
|
|
2216
|
+
...stringConfig.autocompleteProps,
|
|
2217
|
+
name: fieldName,
|
|
2218
|
+
"data-field-name": fieldName,
|
|
2219
|
+
label: baseProps.label,
|
|
2220
|
+
description: baseProps.description,
|
|
2221
|
+
isDisabled: baseProps.isDisabled,
|
|
2222
|
+
isInvalid: Boolean(errorMessage),
|
|
2223
|
+
errorMessage,
|
|
2224
|
+
selectedKey: value || null,
|
|
2225
|
+
inputValue: value || "",
|
|
2226
|
+
onSelectionChange: (key) => {
|
|
2227
|
+
setValue(key ? String(key) : "");
|
|
2228
|
+
},
|
|
2229
|
+
onInputChange: setValue,
|
|
2230
|
+
items
|
|
2231
|
+
},
|
|
2232
|
+
items.map((item) => /* @__PURE__ */ React21.createElement(AutocompleteItem, { key: String(item.value) }, item.label))
|
|
2233
|
+
);
|
|
2234
|
+
}
|
|
2235
|
+
case "slider": {
|
|
2236
|
+
const sliderConfig = fieldConfig;
|
|
2237
|
+
const numValue = value ? Number(value) : 0;
|
|
2238
|
+
return /* @__PURE__ */ React21.createElement(
|
|
2239
|
+
Slider,
|
|
2240
|
+
{
|
|
2241
|
+
...sliderConfig.sliderProps,
|
|
2242
|
+
name: fieldName,
|
|
2243
|
+
"data-field-name": fieldName,
|
|
2244
|
+
label: baseProps.label,
|
|
2245
|
+
description: baseProps.description,
|
|
2246
|
+
isDisabled: baseProps.isDisabled,
|
|
2247
|
+
value: numValue,
|
|
2248
|
+
onChange: (val) => {
|
|
2249
|
+
const newValue = Array.isArray(val) ? val[0] : val;
|
|
2250
|
+
setValue(String(newValue));
|
|
2251
|
+
}
|
|
2252
|
+
}
|
|
2253
|
+
);
|
|
2254
|
+
}
|
|
2255
|
+
case "date": {
|
|
2256
|
+
const dateConfig = fieldConfig;
|
|
2257
|
+
return /* @__PURE__ */ React21.createElement(React21.Fragment, null, /* @__PURE__ */ React21.createElement("input", { type: "hidden", name: fieldName, value: value || "" }), /* @__PURE__ */ React21.createElement(
|
|
2258
|
+
DateInput,
|
|
2259
|
+
{
|
|
2260
|
+
...dateConfig.dateProps,
|
|
2261
|
+
"data-field-name": fieldName,
|
|
2262
|
+
label: baseProps.label,
|
|
2263
|
+
description: baseProps.description,
|
|
2264
|
+
isDisabled: baseProps.isDisabled,
|
|
2265
|
+
isInvalid: Boolean(errorMessage),
|
|
2266
|
+
errorMessage,
|
|
2267
|
+
value: value ? value : null,
|
|
2268
|
+
onChange: (date) => {
|
|
2269
|
+
const dateString = date ? `${date.year}-${String(date.month).padStart(2, "0")}-${String(date.day).padStart(2, "0")}` : "";
|
|
2270
|
+
setValue(dateString);
|
|
2271
|
+
}
|
|
2272
|
+
}
|
|
2273
|
+
));
|
|
2274
|
+
}
|
|
2275
|
+
case "file": {
|
|
2276
|
+
const fileConfig = fieldConfig;
|
|
2277
|
+
const multiple = fileConfig.multiple || false;
|
|
2278
|
+
const accept = fileConfig.accept;
|
|
2279
|
+
return /* @__PURE__ */ React21.createElement(React21.Fragment, null, /* @__PURE__ */ React21.createElement(
|
|
2280
|
+
Input,
|
|
2281
|
+
{
|
|
2282
|
+
...fileConfig.fileProps,
|
|
2283
|
+
name: fieldName,
|
|
2284
|
+
"data-field-name": fieldName,
|
|
2285
|
+
type: "file",
|
|
2286
|
+
label: baseProps.label,
|
|
2287
|
+
description: baseProps.description,
|
|
2288
|
+
isDisabled: baseProps.isDisabled,
|
|
2289
|
+
isInvalid: Boolean(errorMessage),
|
|
2290
|
+
errorMessage,
|
|
2291
|
+
multiple,
|
|
2292
|
+
accept,
|
|
2293
|
+
onChange: (e) => {
|
|
2294
|
+
if (!(e.target instanceof HTMLInputElement)) {
|
|
2295
|
+
return;
|
|
2296
|
+
}
|
|
2297
|
+
const target = e.target;
|
|
2298
|
+
if (target.files) {
|
|
2299
|
+
setValue(String(target.files.length));
|
|
2300
|
+
}
|
|
2301
|
+
}
|
|
2302
|
+
}
|
|
1742
2303
|
));
|
|
1743
2304
|
}
|
|
1744
2305
|
default:
|
|
1745
|
-
return /* @__PURE__ */
|
|
2306
|
+
return /* @__PURE__ */ React21.createElement(
|
|
1746
2307
|
Input,
|
|
1747
2308
|
{
|
|
2309
|
+
name: fieldName,
|
|
1748
2310
|
"data-field-name": fieldName,
|
|
1749
|
-
label:
|
|
1750
|
-
description:
|
|
1751
|
-
isDisabled:
|
|
2311
|
+
label: baseProps.label,
|
|
2312
|
+
description: baseProps.description,
|
|
2313
|
+
isDisabled: baseProps.isDisabled,
|
|
1752
2314
|
isInvalid: Boolean(errorMessage),
|
|
1753
2315
|
errorMessage,
|
|
1754
2316
|
value,
|
|
1755
2317
|
onValueChange: setValue
|
|
1756
2318
|
}
|
|
1757
|
-
)
|
|
2319
|
+
);
|
|
1758
2320
|
}
|
|
1759
2321
|
}
|
|
1760
2322
|
|
|
@@ -1772,10 +2334,10 @@ function useHeroForm() {
|
|
|
1772
2334
|
}
|
|
1773
2335
|
|
|
1774
2336
|
// src/providers/FormProvider.tsx
|
|
1775
|
-
import
|
|
2337
|
+
import React22 from "react";
|
|
1776
2338
|
import { FormProvider as RHFProvider } from "react-hook-form";
|
|
1777
2339
|
function FormProvider(props) {
|
|
1778
|
-
return /* @__PURE__ */
|
|
2340
|
+
return /* @__PURE__ */ React22.createElement(RHFProvider, { ...props.methods }, /* @__PURE__ */ React22.createElement(
|
|
1779
2341
|
"form",
|
|
1780
2342
|
{
|
|
1781
2343
|
className: props.className,
|
|
@@ -1788,7 +2350,7 @@ function FormProvider(props) {
|
|
|
1788
2350
|
}
|
|
1789
2351
|
|
|
1790
2352
|
// src/submit/SubmitButton.tsx
|
|
1791
|
-
import
|
|
2353
|
+
import React23 from "react";
|
|
1792
2354
|
function SubmitButton(props) {
|
|
1793
2355
|
const ctx = useFormContext5();
|
|
1794
2356
|
const loading = props.isLoading ?? ctx.formState.isSubmitting;
|
|
@@ -1798,10 +2360,10 @@ function SubmitButton(props) {
|
|
|
1798
2360
|
const defaults = useHeroHookFormDefaults();
|
|
1799
2361
|
const getButtonContent = () => {
|
|
1800
2362
|
if (enhancedState?.isSuccess) {
|
|
1801
|
-
return /* @__PURE__ */
|
|
2363
|
+
return /* @__PURE__ */ React23.createElement("span", { className: "inline-flex items-center gap-2" }, "\u2705", props.successText || "Success!");
|
|
1802
2364
|
}
|
|
1803
2365
|
if (loading) {
|
|
1804
|
-
return /* @__PURE__ */
|
|
2366
|
+
return /* @__PURE__ */ React23.createElement("span", { className: "inline-flex items-center gap-2" }, "\u23F3", props.loadingText || "Submitting...");
|
|
1805
2367
|
}
|
|
1806
2368
|
return props.children;
|
|
1807
2369
|
};
|
|
@@ -1814,7 +2376,7 @@ function SubmitButton(props) {
|
|
|
1814
2376
|
}
|
|
1815
2377
|
return props.buttonProps?.color || defaults.submitButton.color;
|
|
1816
2378
|
};
|
|
1817
|
-
return /* @__PURE__ */
|
|
2379
|
+
return /* @__PURE__ */ React23.createElement(
|
|
1818
2380
|
Button,
|
|
1819
2381
|
{
|
|
1820
2382
|
type: "submit",
|
|
@@ -2055,7 +2617,7 @@ var commonValidations = {
|
|
|
2055
2617
|
import { useFormContext as useFormContext5 } from "react-hook-form";
|
|
2056
2618
|
|
|
2057
2619
|
// src/components/ZodForm.tsx
|
|
2058
|
-
import
|
|
2620
|
+
import React25 from "react";
|
|
2059
2621
|
import { Button as Button5 } from "@heroui/react";
|
|
2060
2622
|
import {
|
|
2061
2623
|
FormProvider as FormProvider2
|
|
@@ -2079,8 +2641,15 @@ function createZodResolver(schema) {
|
|
|
2079
2641
|
const path = err.path.join(".");
|
|
2080
2642
|
errors[path] = { message: err.message };
|
|
2081
2643
|
});
|
|
2644
|
+
const fieldErrors = {};
|
|
2645
|
+
Object.entries(errors).forEach(([path, error2]) => {
|
|
2646
|
+
fieldErrors[path] = error2;
|
|
2647
|
+
});
|
|
2082
2648
|
return {
|
|
2083
|
-
|
|
2649
|
+
// TypeScript can't prove all paths are valid field paths, but at runtime they will be
|
|
2650
|
+
// because Zod validates against the schema which matches T
|
|
2651
|
+
// This is a necessary type assertion due to TypeScript's limitations with dynamic paths
|
|
2652
|
+
errors: fieldErrors,
|
|
2084
2653
|
values: {}
|
|
2085
2654
|
};
|
|
2086
2655
|
}
|
|
@@ -2098,14 +2667,12 @@ function createZodFormConfig(schema, fields, defaultValues) {
|
|
|
2098
2667
|
return {
|
|
2099
2668
|
fields,
|
|
2100
2669
|
schema,
|
|
2101
|
-
...defaultValues && {
|
|
2102
|
-
defaultValues
|
|
2103
|
-
}
|
|
2670
|
+
...defaultValues && { defaultValues }
|
|
2104
2671
|
};
|
|
2105
2672
|
}
|
|
2106
2673
|
|
|
2107
2674
|
// src/hooks/useEnhancedFormState.ts
|
|
2108
|
-
import { useCallback, useEffect, useState as
|
|
2675
|
+
import { useCallback, useEffect, useState as useState3 } from "react";
|
|
2109
2676
|
function useEnhancedFormState(form, options = {}) {
|
|
2110
2677
|
const {
|
|
2111
2678
|
autoReset = true,
|
|
@@ -2117,9 +2684,9 @@ function useEnhancedFormState(form, options = {}) {
|
|
|
2117
2684
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2118
2685
|
successMessage: _successMessage = "Form submitted successfully!"
|
|
2119
2686
|
} = options;
|
|
2120
|
-
const [status, setStatus] =
|
|
2121
|
-
const [error, setError] =
|
|
2122
|
-
const [submittedData, setSubmittedData] =
|
|
2687
|
+
const [status, setStatus] = useState3("idle");
|
|
2688
|
+
const [error, setError] = useState3(void 0);
|
|
2689
|
+
const [submittedData, setSubmittedData] = useState3(void 0);
|
|
2123
2690
|
const { formState, getValues: _getValues } = form;
|
|
2124
2691
|
const { dirtyFields, errors, isSubmitting, touchedFields } = formState;
|
|
2125
2692
|
useEffect(() => {
|
|
@@ -2178,7 +2745,7 @@ function useEnhancedFormState(form, options = {}) {
|
|
|
2178
2745
|
}
|
|
2179
2746
|
|
|
2180
2747
|
// src/components/FormStatus.tsx
|
|
2181
|
-
import
|
|
2748
|
+
import React24 from "react";
|
|
2182
2749
|
import { Button as Button4 } from "@heroui/react";
|
|
2183
2750
|
function FormStatus({
|
|
2184
2751
|
className = "",
|
|
@@ -2191,25 +2758,25 @@ function FormStatus({
|
|
|
2191
2758
|
return null;
|
|
2192
2759
|
}
|
|
2193
2760
|
if (isSubmitting) {
|
|
2194
|
-
return /* @__PURE__ */
|
|
2761
|
+
return /* @__PURE__ */ React24.createElement(
|
|
2195
2762
|
"div",
|
|
2196
2763
|
{
|
|
2197
2764
|
className: `flex items-center gap-3 p-4 bg-blue-50 border border-blue-200 rounded-lg ${className}`
|
|
2198
2765
|
},
|
|
2199
|
-
/* @__PURE__ */
|
|
2200
|
-
/* @__PURE__ */
|
|
2766
|
+
/* @__PURE__ */ React24.createElement("span", { className: "text-blue-600" }, "\u23F3"),
|
|
2767
|
+
/* @__PURE__ */ React24.createElement("div", null, /* @__PURE__ */ React24.createElement("p", { className: "text-sm font-medium text-blue-900" }, "Submitting form..."), showDetails && /* @__PURE__ */ React24.createElement("p", { className: "text-xs text-blue-700" }, "Please wait while we process your request."))
|
|
2201
2768
|
);
|
|
2202
2769
|
}
|
|
2203
2770
|
if (isSuccess) {
|
|
2204
|
-
return /* @__PURE__ */
|
|
2771
|
+
return /* @__PURE__ */ React24.createElement(
|
|
2205
2772
|
"div",
|
|
2206
2773
|
{
|
|
2207
2774
|
className: `flex items-center gap-3 p-4 bg-green-50 border border-green-200 rounded-lg ${className}`,
|
|
2208
2775
|
"data-testid": "success-message"
|
|
2209
2776
|
},
|
|
2210
|
-
/* @__PURE__ */
|
|
2211
|
-
/* @__PURE__ */
|
|
2212
|
-
onDismiss && /* @__PURE__ */
|
|
2777
|
+
/* @__PURE__ */ React24.createElement("span", { className: "text-green-600" }, "\u2705"),
|
|
2778
|
+
/* @__PURE__ */ React24.createElement("div", { className: "flex-1" }, /* @__PURE__ */ React24.createElement("p", { className: "text-sm font-medium text-green-900" }, "Form submitted successfully!"), showDetails && submittedData && /* @__PURE__ */ React24.createElement("p", { className: "text-xs text-green-700" }, "Your data has been saved. Thank you for your submission.")),
|
|
2779
|
+
onDismiss && /* @__PURE__ */ React24.createElement(
|
|
2213
2780
|
Button4,
|
|
2214
2781
|
{
|
|
2215
2782
|
size: "sm",
|
|
@@ -2223,15 +2790,15 @@ function FormStatus({
|
|
|
2223
2790
|
);
|
|
2224
2791
|
}
|
|
2225
2792
|
if (isError && error) {
|
|
2226
|
-
return /* @__PURE__ */
|
|
2793
|
+
return /* @__PURE__ */ React24.createElement(
|
|
2227
2794
|
"div",
|
|
2228
2795
|
{
|
|
2229
2796
|
className: `flex items-center gap-3 p-4 bg-red-50 border border-red-200 rounded-lg ${className}`,
|
|
2230
2797
|
"data-testid": "error-message"
|
|
2231
2798
|
},
|
|
2232
|
-
/* @__PURE__ */
|
|
2233
|
-
/* @__PURE__ */
|
|
2234
|
-
onDismiss && /* @__PURE__ */
|
|
2799
|
+
/* @__PURE__ */ React24.createElement("span", { className: "text-red-600" }, "\u26A0\uFE0F"),
|
|
2800
|
+
/* @__PURE__ */ React24.createElement("div", { className: "flex-1" }, /* @__PURE__ */ React24.createElement("p", { className: "text-sm font-medium text-red-900" }, "Error submitting form"), /* @__PURE__ */ React24.createElement("p", { className: "text-xs text-red-700" }, error)),
|
|
2801
|
+
onDismiss && /* @__PURE__ */ React24.createElement(
|
|
2235
2802
|
Button4,
|
|
2236
2803
|
{
|
|
2237
2804
|
size: "sm",
|
|
@@ -2252,8 +2819,8 @@ function FormToast({
|
|
|
2252
2819
|
position = "top-right",
|
|
2253
2820
|
state
|
|
2254
2821
|
}) {
|
|
2255
|
-
const [isVisible, setIsVisible] =
|
|
2256
|
-
|
|
2822
|
+
const [isVisible, setIsVisible] = React24.useState(false);
|
|
2823
|
+
React24.useEffect(() => {
|
|
2257
2824
|
if (state.isSuccess || state.isError) {
|
|
2258
2825
|
setIsVisible(true);
|
|
2259
2826
|
if (duration > 0) {
|
|
@@ -2274,7 +2841,7 @@ function FormToast({
|
|
|
2274
2841
|
"top-left": "top-4 left-4",
|
|
2275
2842
|
"top-right": "top-4 right-4"
|
|
2276
2843
|
};
|
|
2277
|
-
return /* @__PURE__ */
|
|
2844
|
+
return /* @__PURE__ */ React24.createElement("div", { className: `fixed z-50 ${positionClasses[position]}` }, /* @__PURE__ */ React24.createElement(FormStatus, { state, onDismiss }));
|
|
2278
2845
|
}
|
|
2279
2846
|
|
|
2280
2847
|
// src/components/ZodForm.tsx
|
|
@@ -2294,7 +2861,10 @@ function ZodForm({
|
|
|
2294
2861
|
subtitle,
|
|
2295
2862
|
title
|
|
2296
2863
|
}) {
|
|
2297
|
-
const
|
|
2864
|
+
const formConfig = {
|
|
2865
|
+
...config
|
|
2866
|
+
};
|
|
2867
|
+
const form = useZodForm(formConfig);
|
|
2298
2868
|
const enhancedState = useEnhancedFormState(form, {
|
|
2299
2869
|
autoReset: true,
|
|
2300
2870
|
onError: (error) => onError?.({ field: "form", message: error }),
|
|
@@ -2324,12 +2894,12 @@ function ZodForm({
|
|
|
2324
2894
|
};
|
|
2325
2895
|
const renderFields = () => {
|
|
2326
2896
|
if (layout === "grid") {
|
|
2327
|
-
return /* @__PURE__ */
|
|
2897
|
+
return /* @__PURE__ */ React25.createElement(
|
|
2328
2898
|
"div",
|
|
2329
2899
|
{
|
|
2330
2900
|
className: `grid gap-${spacing} ${columns === 1 ? "grid-cols-1" : columns === 2 ? "grid-cols-1 md:grid-cols-2" : "grid-cols-1 md:grid-cols-2 lg:grid-cols-3"}`
|
|
2331
2901
|
},
|
|
2332
|
-
config.fields.map((field2) => /* @__PURE__ */
|
|
2902
|
+
config.fields.map((field2) => /* @__PURE__ */ React25.createElement(
|
|
2333
2903
|
FormField,
|
|
2334
2904
|
{
|
|
2335
2905
|
key: field2.name,
|
|
@@ -2346,7 +2916,7 @@ function ZodForm({
|
|
|
2346
2916
|
);
|
|
2347
2917
|
}
|
|
2348
2918
|
if (layout === "horizontal") {
|
|
2349
|
-
return /* @__PURE__ */
|
|
2919
|
+
return /* @__PURE__ */ React25.createElement("div", { className: `grid gap-${spacing} grid-cols-1 md:grid-cols-2` }, config.fields.map((field2) => /* @__PURE__ */ React25.createElement(
|
|
2350
2920
|
FormField,
|
|
2351
2921
|
{
|
|
2352
2922
|
key: field2.name,
|
|
@@ -2361,10 +2931,10 @@ function ZodForm({
|
|
|
2361
2931
|
}
|
|
2362
2932
|
)));
|
|
2363
2933
|
}
|
|
2364
|
-
return /* @__PURE__ */
|
|
2934
|
+
return /* @__PURE__ */ React25.createElement("div", { className: `space-y-${spacing}` }, config.fields.map((field2) => /* @__PURE__ */ React25.createElement(
|
|
2365
2935
|
FormField,
|
|
2366
2936
|
{
|
|
2367
|
-
key: field2.name,
|
|
2937
|
+
key: pathToString(field2.name),
|
|
2368
2938
|
config: field2,
|
|
2369
2939
|
form,
|
|
2370
2940
|
submissionState: {
|
|
@@ -2380,19 +2950,19 @@ function ZodForm({
|
|
|
2380
2950
|
e.preventDefault();
|
|
2381
2951
|
void handleSubmit();
|
|
2382
2952
|
};
|
|
2383
|
-
|
|
2953
|
+
React25.useEffect(() => {
|
|
2384
2954
|
if (config.onError && Object.keys(form.formState.errors).length > 0) {
|
|
2385
2955
|
config.onError(form.formState.errors);
|
|
2386
2956
|
}
|
|
2387
2957
|
}, [form.formState.errors, config.onError]);
|
|
2388
|
-
return /* @__PURE__ */
|
|
2958
|
+
return /* @__PURE__ */ React25.createElement(FormProvider2, { ...form }, /* @__PURE__ */ React25.createElement("form", { className, role: "form", onSubmit: handleFormSubmit }, title && /* @__PURE__ */ React25.createElement("div", { className: "mb-6" }, /* @__PURE__ */ React25.createElement("h2", { className: "text-xl font-semibold text-foreground mb-2" }, title), subtitle && /* @__PURE__ */ React25.createElement("p", { className: "text-sm text-muted-foreground" }, subtitle)), /* @__PURE__ */ React25.createElement(
|
|
2389
2959
|
FormStatus,
|
|
2390
2960
|
{
|
|
2391
2961
|
state: enhancedState,
|
|
2392
2962
|
onDismiss: () => enhancedState.reset(),
|
|
2393
2963
|
showDetails: true
|
|
2394
2964
|
}
|
|
2395
|
-
), renderFields(), /* @__PURE__ */
|
|
2965
|
+
), renderFields(), /* @__PURE__ */ React25.createElement("div", { className: "mt-6 flex gap-3 justify-end" }, /* @__PURE__ */ React25.createElement(
|
|
2396
2966
|
Button5,
|
|
2397
2967
|
{
|
|
2398
2968
|
color: "primary",
|
|
@@ -2402,7 +2972,7 @@ function ZodForm({
|
|
|
2402
2972
|
...submitButtonProps
|
|
2403
2973
|
},
|
|
2404
2974
|
enhancedState.isSuccess ? "Success!" : submitButtonText
|
|
2405
|
-
), showResetButton && /* @__PURE__ */
|
|
2975
|
+
), showResetButton && /* @__PURE__ */ React25.createElement(
|
|
2406
2976
|
Button5,
|
|
2407
2977
|
{
|
|
2408
2978
|
isDisabled: enhancedState.isSubmitting,
|
|
@@ -2415,7 +2985,7 @@ function ZodForm({
|
|
|
2415
2985
|
}
|
|
2416
2986
|
|
|
2417
2987
|
// src/components/SimpleForm.tsx
|
|
2418
|
-
import
|
|
2988
|
+
import React26 from "react";
|
|
2419
2989
|
function SimpleForm({
|
|
2420
2990
|
className,
|
|
2421
2991
|
defaultValues,
|
|
@@ -2429,7 +2999,7 @@ function SimpleForm({
|
|
|
2429
2999
|
subtitle,
|
|
2430
3000
|
title
|
|
2431
3001
|
}) {
|
|
2432
|
-
return /* @__PURE__ */
|
|
3002
|
+
return /* @__PURE__ */ React26.createElement(
|
|
2433
3003
|
ZodForm,
|
|
2434
3004
|
{
|
|
2435
3005
|
className,
|
|
@@ -2553,6 +3123,29 @@ var BasicFormBuilder = class {
|
|
|
2553
3123
|
function createBasicFormBuilder() {
|
|
2554
3124
|
return new BasicFormBuilder();
|
|
2555
3125
|
}
|
|
3126
|
+
function inputHelper(name, label, typeOrProps, inputProps) {
|
|
3127
|
+
if (typeOrProps && typeof typeOrProps === "object" && !("type" in typeOrProps && typeof typeOrProps.type === "string" && ["text", "email", "tel", "password"].includes(typeOrProps.type))) {
|
|
3128
|
+
return {
|
|
3129
|
+
inputProps: {
|
|
3130
|
+
type: "text",
|
|
3131
|
+
...typeOrProps
|
|
3132
|
+
},
|
|
3133
|
+
label,
|
|
3134
|
+
name,
|
|
3135
|
+
type: "input"
|
|
3136
|
+
};
|
|
3137
|
+
}
|
|
3138
|
+
const type = typeof typeOrProps === "string" ? typeOrProps : void 0;
|
|
3139
|
+
return {
|
|
3140
|
+
inputProps: {
|
|
3141
|
+
type: type || "text",
|
|
3142
|
+
...inputProps
|
|
3143
|
+
},
|
|
3144
|
+
label,
|
|
3145
|
+
name,
|
|
3146
|
+
type: "input"
|
|
3147
|
+
};
|
|
3148
|
+
}
|
|
2556
3149
|
var FormFieldHelpers = {
|
|
2557
3150
|
/**
|
|
2558
3151
|
* Create an autocomplete field
|
|
@@ -2603,6 +3196,34 @@ var FormFieldHelpers = {
|
|
|
2603
3196
|
name,
|
|
2604
3197
|
type: "checkbox"
|
|
2605
3198
|
}),
|
|
3199
|
+
/**
|
|
3200
|
+
* Create a checkbox group field (multiple checkboxes saving to an array)
|
|
3201
|
+
*
|
|
3202
|
+
* @example
|
|
3203
|
+
* ```tsx
|
|
3204
|
+
* // Simple checkbox group
|
|
3205
|
+
* FormFieldHelpers.checkboxGroup("interests", "Interests", [
|
|
3206
|
+
* { label: "Reading", value: "reading" },
|
|
3207
|
+
* { label: "Sports", value: "sports" },
|
|
3208
|
+
* { label: "Music", value: "music" },
|
|
3209
|
+
* ])
|
|
3210
|
+
*
|
|
3211
|
+
* // With horizontal layout and custom styling
|
|
3212
|
+
* FormFieldHelpers.checkboxGroup("interests", "Interests", options, {
|
|
3213
|
+
* orientation: "horizontal",
|
|
3214
|
+
* checkboxProps: { color: "primary", size: "lg" }
|
|
3215
|
+
* })
|
|
3216
|
+
* ```
|
|
3217
|
+
*/
|
|
3218
|
+
checkboxGroup: (name, label, options, config) => ({
|
|
3219
|
+
checkboxGroupOptions: options,
|
|
3220
|
+
checkboxProps: config?.checkboxProps,
|
|
3221
|
+
description: config?.description,
|
|
3222
|
+
label,
|
|
3223
|
+
name,
|
|
3224
|
+
orientation: config?.orientation || "vertical",
|
|
3225
|
+
type: "checkboxGroup"
|
|
3226
|
+
}),
|
|
2606
3227
|
/**
|
|
2607
3228
|
* Create a conditional field that shows/hides based on form data
|
|
2608
3229
|
*
|
|
@@ -2627,12 +3248,13 @@ var FormFieldHelpers = {
|
|
|
2627
3248
|
* ```
|
|
2628
3249
|
*/
|
|
2629
3250
|
conditional: (name, condition, field2) => {
|
|
2630
|
-
|
|
3251
|
+
const config = {
|
|
2631
3252
|
condition,
|
|
2632
3253
|
field: field2,
|
|
2633
3254
|
name,
|
|
2634
3255
|
type: "conditional"
|
|
2635
3256
|
};
|
|
3257
|
+
return config;
|
|
2636
3258
|
},
|
|
2637
3259
|
/**
|
|
2638
3260
|
* Create a content field for headers, questions, or custom content between fields
|
|
@@ -2649,7 +3271,7 @@ var FormFieldHelpers = {
|
|
|
2649
3271
|
* ```
|
|
2650
3272
|
*/
|
|
2651
3273
|
content: (title, description, options) => {
|
|
2652
|
-
|
|
3274
|
+
const config = {
|
|
2653
3275
|
className: options?.className,
|
|
2654
3276
|
description: description || void 0,
|
|
2655
3277
|
name: options?.name,
|
|
@@ -2657,7 +3279,31 @@ var FormFieldHelpers = {
|
|
|
2657
3279
|
title: title || void 0,
|
|
2658
3280
|
type: "content"
|
|
2659
3281
|
};
|
|
3282
|
+
return config;
|
|
2660
3283
|
},
|
|
3284
|
+
/**
|
|
3285
|
+
* Create a custom field with full control over rendering
|
|
3286
|
+
*
|
|
3287
|
+
* @example
|
|
3288
|
+
* ```tsx
|
|
3289
|
+
* // Custom field with render function
|
|
3290
|
+
* FormFieldHelpers.custom<FormData>(
|
|
3291
|
+
* "skills",
|
|
3292
|
+
* "Skills",
|
|
3293
|
+
* ({ form, control }) => {
|
|
3294
|
+
* // Custom rendering logic
|
|
3295
|
+
* return <div>...</div>;
|
|
3296
|
+
* }
|
|
3297
|
+
* )
|
|
3298
|
+
* ```
|
|
3299
|
+
*/
|
|
3300
|
+
custom: (name, label, render, options) => ({
|
|
3301
|
+
label,
|
|
3302
|
+
name,
|
|
3303
|
+
render,
|
|
3304
|
+
type: "custom",
|
|
3305
|
+
...options
|
|
3306
|
+
}),
|
|
2661
3307
|
/**
|
|
2662
3308
|
* Create a date field
|
|
2663
3309
|
*
|
|
@@ -2743,7 +3389,10 @@ var FormFieldHelpers = {
|
|
|
2743
3389
|
* // With type
|
|
2744
3390
|
* FormFieldHelpers.input("email", "Email", "email")
|
|
2745
3391
|
*
|
|
2746
|
-
* // With
|
|
3392
|
+
* // With props only (no type)
|
|
3393
|
+
* FormFieldHelpers.input("name", "Name", { placeholder: "Enter name" })
|
|
3394
|
+
*
|
|
3395
|
+
* // With type and props
|
|
2747
3396
|
* FormFieldHelpers.input("email", "Email", "email", {
|
|
2748
3397
|
* placeholder: "Enter your email",
|
|
2749
3398
|
* classNames: { input: "custom-input" },
|
|
@@ -2752,15 +3401,25 @@ var FormFieldHelpers = {
|
|
|
2752
3401
|
* })
|
|
2753
3402
|
* ```
|
|
2754
3403
|
*/
|
|
2755
|
-
input:
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
3404
|
+
input: inputHelper,
|
|
3405
|
+
/**
|
|
3406
|
+
* Create a radio group field
|
|
3407
|
+
*
|
|
3408
|
+
* @example
|
|
3409
|
+
* ```tsx
|
|
3410
|
+
* // Simple radio group
|
|
3411
|
+
* FormFieldHelpers.radio("gender", "Gender", [
|
|
3412
|
+
* { label: "Male", value: "male" },
|
|
3413
|
+
* { label: "Female", value: "female" }
|
|
3414
|
+
* ])
|
|
3415
|
+
*
|
|
3416
|
+
* // With full customization
|
|
3417
|
+
* FormFieldHelpers.radio("gender", "Gender", options, {
|
|
3418
|
+
* orientation: "horizontal",
|
|
3419
|
+
* classNames: { base: "custom-radio" }
|
|
3420
|
+
* })
|
|
3421
|
+
* ```
|
|
3422
|
+
*/
|
|
2764
3423
|
/**
|
|
2765
3424
|
* Create a radio group field
|
|
2766
3425
|
*
|
|
@@ -2893,6 +3552,8 @@ var CommonFields = {
|
|
|
2893
3552
|
* Address fields
|
|
2894
3553
|
*/
|
|
2895
3554
|
address: () => [
|
|
3555
|
+
// Type assertions are necessary: TypeScript can't prove these strings are valid Path<T>
|
|
3556
|
+
// for an arbitrary T, but they will be valid when used with a matching schema
|
|
2896
3557
|
FormFieldHelpers.input("street", "Street Address"),
|
|
2897
3558
|
FormFieldHelpers.input("city", "City"),
|
|
2898
3559
|
FormFieldHelpers.input("state", "State/Province"),
|
|
@@ -2911,6 +3572,7 @@ var CommonFields = {
|
|
|
2911
3572
|
* Personal information fields
|
|
2912
3573
|
*/
|
|
2913
3574
|
personal: () => [
|
|
3575
|
+
// Type assertions are necessary - see CommonFields documentation above
|
|
2914
3576
|
FormFieldHelpers.input("firstName", "First Name"),
|
|
2915
3577
|
FormFieldHelpers.input("lastName", "Last Name"),
|
|
2916
3578
|
FormFieldHelpers.input("email", "Email", "email"),
|
|
@@ -2920,6 +3582,7 @@ var CommonFields = {
|
|
|
2920
3582
|
* Terms and conditions fields
|
|
2921
3583
|
*/
|
|
2922
3584
|
terms: () => [
|
|
3585
|
+
// Type assertions are necessary - see CommonFields documentation above
|
|
2923
3586
|
FormFieldHelpers.checkbox(
|
|
2924
3587
|
"terms",
|
|
2925
3588
|
"I agree to the terms and conditions"
|
|
@@ -2936,7 +3599,7 @@ var CommonFields = {
|
|
|
2936
3599
|
};
|
|
2937
3600
|
|
|
2938
3601
|
// src/builders/AdvancedFormBuilder.ts
|
|
2939
|
-
function
|
|
3602
|
+
function createInputField(name, label, props) {
|
|
2940
3603
|
return {
|
|
2941
3604
|
label,
|
|
2942
3605
|
name,
|
|
@@ -2952,7 +3615,7 @@ function inputField(name, label, props) {
|
|
|
2952
3615
|
}
|
|
2953
3616
|
};
|
|
2954
3617
|
}
|
|
2955
|
-
function
|
|
3618
|
+
function createTextareaField(name, label, props) {
|
|
2956
3619
|
return {
|
|
2957
3620
|
label,
|
|
2958
3621
|
name,
|
|
@@ -2968,7 +3631,7 @@ function textareaField(name, label, props) {
|
|
|
2968
3631
|
}
|
|
2969
3632
|
};
|
|
2970
3633
|
}
|
|
2971
|
-
function
|
|
3634
|
+
function createSelectField(name, label, options) {
|
|
2972
3635
|
return {
|
|
2973
3636
|
label,
|
|
2974
3637
|
name,
|
|
@@ -2976,7 +3639,7 @@ function selectField(name, label, options) {
|
|
|
2976
3639
|
type: "select"
|
|
2977
3640
|
};
|
|
2978
3641
|
}
|
|
2979
|
-
function
|
|
3642
|
+
function createCheckboxField(name, label, props) {
|
|
2980
3643
|
return {
|
|
2981
3644
|
label,
|
|
2982
3645
|
name,
|
|
@@ -2989,7 +3652,7 @@ function checkboxField(name, label, props) {
|
|
|
2989
3652
|
}
|
|
2990
3653
|
};
|
|
2991
3654
|
}
|
|
2992
|
-
function
|
|
3655
|
+
function createSwitchField(name, label, props) {
|
|
2993
3656
|
return {
|
|
2994
3657
|
description: props?.description,
|
|
2995
3658
|
isDisabled: props?.isDisabled,
|
|
@@ -3003,7 +3666,7 @@ function switchField(name, label, props) {
|
|
|
3003
3666
|
}
|
|
3004
3667
|
};
|
|
3005
3668
|
}
|
|
3006
|
-
function
|
|
3669
|
+
function createRadioField(name, label, options, props) {
|
|
3007
3670
|
return {
|
|
3008
3671
|
label,
|
|
3009
3672
|
name,
|
|
@@ -3018,7 +3681,7 @@ function radioField(name, label, options, props) {
|
|
|
3018
3681
|
}
|
|
3019
3682
|
};
|
|
3020
3683
|
}
|
|
3021
|
-
function
|
|
3684
|
+
function createSliderField(name, label, props) {
|
|
3022
3685
|
return {
|
|
3023
3686
|
label,
|
|
3024
3687
|
name,
|
|
@@ -3033,20 +3696,19 @@ function sliderField(name, label, props) {
|
|
|
3033
3696
|
}
|
|
3034
3697
|
};
|
|
3035
3698
|
}
|
|
3036
|
-
function
|
|
3699
|
+
function createDateField(name, label, props) {
|
|
3700
|
+
const dateProps = {};
|
|
3701
|
+
if (props?.className !== void 0) {
|
|
3702
|
+
dateProps.className = props.className;
|
|
3703
|
+
}
|
|
3037
3704
|
return {
|
|
3038
3705
|
label,
|
|
3039
3706
|
name,
|
|
3040
3707
|
type: "date",
|
|
3041
|
-
...
|
|
3042
|
-
dateProps: {
|
|
3043
|
-
className: props.className,
|
|
3044
|
-
placeholder: props.placeholder
|
|
3045
|
-
}
|
|
3046
|
-
}
|
|
3708
|
+
...Object.keys(dateProps).length > 0 && { dateProps }
|
|
3047
3709
|
};
|
|
3048
3710
|
}
|
|
3049
|
-
function
|
|
3711
|
+
function createFileField(name, label, props) {
|
|
3050
3712
|
return {
|
|
3051
3713
|
label,
|
|
3052
3714
|
name,
|
|
@@ -3061,7 +3723,7 @@ function fileField(name, label, props) {
|
|
|
3061
3723
|
}
|
|
3062
3724
|
};
|
|
3063
3725
|
}
|
|
3064
|
-
function
|
|
3726
|
+
function createFontPickerField(name, label, props) {
|
|
3065
3727
|
return {
|
|
3066
3728
|
className: props?.className,
|
|
3067
3729
|
description: props?.description,
|
|
@@ -3071,83 +3733,119 @@ function fontPickerField(name, label, props) {
|
|
|
3071
3733
|
type: "fontPicker"
|
|
3072
3734
|
};
|
|
3073
3735
|
}
|
|
3074
|
-
function
|
|
3736
|
+
function createStringArrayField(name, label, props) {
|
|
3737
|
+
return {
|
|
3738
|
+
className: props?.className,
|
|
3739
|
+
description: props?.description,
|
|
3740
|
+
isDisabled: props?.isDisabled,
|
|
3741
|
+
label,
|
|
3742
|
+
name,
|
|
3743
|
+
stringArrayProps: {
|
|
3744
|
+
addButtonText: props?.addButtonText,
|
|
3745
|
+
allowDuplicates: props?.allowDuplicates,
|
|
3746
|
+
maxItems: props?.maxItems,
|
|
3747
|
+
minItems: props?.minItems,
|
|
3748
|
+
placeholder: props?.placeholder,
|
|
3749
|
+
showAddButton: props?.showAddButton,
|
|
3750
|
+
transformItem: props?.transformItem,
|
|
3751
|
+
validateItem: props?.validateItem
|
|
3752
|
+
},
|
|
3753
|
+
type: "stringArray"
|
|
3754
|
+
};
|
|
3755
|
+
}
|
|
3756
|
+
function createContentField(config) {
|
|
3075
3757
|
return {
|
|
3076
|
-
className:
|
|
3077
|
-
description: description || void 0,
|
|
3078
|
-
name:
|
|
3079
|
-
render:
|
|
3080
|
-
title: title || void 0,
|
|
3758
|
+
className: config.className,
|
|
3759
|
+
description: config.description || void 0,
|
|
3760
|
+
name: config.name,
|
|
3761
|
+
render: config.render,
|
|
3762
|
+
title: config.title || void 0,
|
|
3081
3763
|
type: "content"
|
|
3082
3764
|
};
|
|
3083
3765
|
}
|
|
3084
|
-
function
|
|
3085
|
-
switch (type) {
|
|
3766
|
+
function createFieldFromParams(params) {
|
|
3767
|
+
switch (params.type) {
|
|
3086
3768
|
case "input":
|
|
3087
|
-
return
|
|
3769
|
+
return createInputField(params.name, params.label, params.props);
|
|
3088
3770
|
case "textarea":
|
|
3089
|
-
return
|
|
3771
|
+
return createTextareaField(params.name, params.label, params.props);
|
|
3090
3772
|
case "select":
|
|
3091
|
-
return
|
|
3773
|
+
return createSelectField(params.name, params.label, params.options);
|
|
3092
3774
|
case "checkbox":
|
|
3093
|
-
return
|
|
3775
|
+
return createCheckboxField(params.name, params.label, params.props);
|
|
3094
3776
|
case "switch":
|
|
3095
|
-
return
|
|
3777
|
+
return createSwitchField(params.name, params.label, params.props);
|
|
3096
3778
|
case "radio":
|
|
3097
|
-
return
|
|
3779
|
+
return createRadioField(
|
|
3780
|
+
params.name,
|
|
3781
|
+
params.label,
|
|
3782
|
+
params.options,
|
|
3783
|
+
params.props
|
|
3784
|
+
);
|
|
3098
3785
|
case "slider":
|
|
3099
|
-
return
|
|
3786
|
+
return createSliderField(params.name, params.label, params.props);
|
|
3100
3787
|
case "date":
|
|
3101
|
-
return
|
|
3788
|
+
return createDateField(params.name, params.label, params.props);
|
|
3102
3789
|
case "file":
|
|
3103
|
-
return
|
|
3790
|
+
return createFileField(params.name, params.label, params.props);
|
|
3104
3791
|
case "fontPicker":
|
|
3105
|
-
return
|
|
3792
|
+
return createFontPickerField(params.name, params.label, params.props);
|
|
3793
|
+
case "stringArray":
|
|
3794
|
+
return createStringArrayField(params.name, params.label, params.props);
|
|
3795
|
+
case "autocomplete":
|
|
3796
|
+
return {
|
|
3797
|
+
autocompleteProps: params.props,
|
|
3798
|
+
label: params.label,
|
|
3799
|
+
name: params.name,
|
|
3800
|
+
options: params.options,
|
|
3801
|
+
type: "autocomplete"
|
|
3802
|
+
};
|
|
3106
3803
|
case "content":
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
}
|
|
3117
|
-
|
|
3118
|
-
name,
|
|
3119
|
-
label,
|
|
3120
|
-
optionsOrProps
|
|
3121
|
-
);
|
|
3122
|
-
default:
|
|
3123
|
-
throw new Error(`Unknown field type: ${type}`);
|
|
3804
|
+
return createContentField({
|
|
3805
|
+
className: params.className,
|
|
3806
|
+
description: params.description,
|
|
3807
|
+
name: params.name,
|
|
3808
|
+
render: params.render,
|
|
3809
|
+
title: params.title
|
|
3810
|
+
});
|
|
3811
|
+
default: {
|
|
3812
|
+
const _exhaustive = params;
|
|
3813
|
+
throw new Error(`Unknown field type: ${_exhaustive.type}`);
|
|
3814
|
+
}
|
|
3124
3815
|
}
|
|
3125
3816
|
}
|
|
3817
|
+
function createField(params) {
|
|
3818
|
+
return createFieldFromParams(params);
|
|
3819
|
+
}
|
|
3126
3820
|
var AdvancedFieldBuilder = class {
|
|
3127
3821
|
constructor() {
|
|
3128
3822
|
this.fields = [];
|
|
3129
3823
|
}
|
|
3130
|
-
|
|
3131
|
-
|
|
3824
|
+
/**
|
|
3825
|
+
* Add any field type using the unified API
|
|
3826
|
+
*/
|
|
3827
|
+
field(params) {
|
|
3828
|
+
this.fields.push(createField(params));
|
|
3132
3829
|
return this;
|
|
3133
3830
|
}
|
|
3134
3831
|
/**
|
|
3135
3832
|
* Add a conditional field that shows/hides based on form data
|
|
3136
3833
|
*/
|
|
3137
3834
|
conditionalField(name, condition, field2) {
|
|
3138
|
-
|
|
3835
|
+
const config = {
|
|
3139
3836
|
condition,
|
|
3140
3837
|
field: field2,
|
|
3141
3838
|
name,
|
|
3142
3839
|
type: "conditional"
|
|
3143
|
-
}
|
|
3840
|
+
};
|
|
3841
|
+
this.fields.push(config);
|
|
3144
3842
|
return this;
|
|
3145
3843
|
}
|
|
3146
3844
|
/**
|
|
3147
3845
|
* Add a field array for dynamic repeating field groups
|
|
3148
3846
|
*/
|
|
3149
3847
|
fieldArray(name, label, fields, options) {
|
|
3150
|
-
|
|
3848
|
+
const config = {
|
|
3151
3849
|
addButtonText: options?.addButtonText,
|
|
3152
3850
|
fields,
|
|
3153
3851
|
label,
|
|
@@ -3156,21 +3854,23 @@ var AdvancedFieldBuilder = class {
|
|
|
3156
3854
|
name,
|
|
3157
3855
|
removeButtonText: options?.removeButtonText,
|
|
3158
3856
|
type: "fieldArray"
|
|
3159
|
-
}
|
|
3857
|
+
};
|
|
3858
|
+
this.fields.push(config);
|
|
3160
3859
|
return this;
|
|
3161
3860
|
}
|
|
3162
3861
|
/**
|
|
3163
3862
|
* Add a dynamic section that shows/hides based on form data
|
|
3164
3863
|
*/
|
|
3165
3864
|
dynamicSection(name, condition, fields, options) {
|
|
3166
|
-
|
|
3865
|
+
const config = {
|
|
3167
3866
|
condition,
|
|
3168
3867
|
description: options?.description,
|
|
3169
3868
|
fields,
|
|
3170
3869
|
name,
|
|
3171
3870
|
title: options?.title,
|
|
3172
3871
|
type: "dynamicSection"
|
|
3173
|
-
}
|
|
3872
|
+
};
|
|
3873
|
+
this.fields.push(config);
|
|
3174
3874
|
return this;
|
|
3175
3875
|
}
|
|
3176
3876
|
/**
|
|
@@ -3184,8 +3884,11 @@ var FieldArrayItemBuilder = class {
|
|
|
3184
3884
|
constructor() {
|
|
3185
3885
|
this.fields = [];
|
|
3186
3886
|
}
|
|
3187
|
-
|
|
3188
|
-
|
|
3887
|
+
/**
|
|
3888
|
+
* Add any field type using the unified API for array items
|
|
3889
|
+
*/
|
|
3890
|
+
field(params) {
|
|
3891
|
+
this.fields.push(createField(params));
|
|
3189
3892
|
return this;
|
|
3190
3893
|
}
|
|
3191
3894
|
/**
|
|
@@ -3203,15 +3906,12 @@ var FieldArrayBuilder = class {
|
|
|
3203
3906
|
this.arrayName = arrayName;
|
|
3204
3907
|
this.fields = [];
|
|
3205
3908
|
}
|
|
3206
|
-
field(
|
|
3207
|
-
const fullPath = `${this.arrayName}.${name}`;
|
|
3208
|
-
const fieldConfig = createField(
|
|
3209
|
-
|
|
3210
|
-
fullPath
|
|
3211
|
-
|
|
3212
|
-
optionsOrProps,
|
|
3213
|
-
props
|
|
3214
|
-
);
|
|
3909
|
+
field(params) {
|
|
3910
|
+
const fullPath = `${this.arrayName}.${params.name}`;
|
|
3911
|
+
const fieldConfig = createField({
|
|
3912
|
+
...params,
|
|
3913
|
+
name: fullPath
|
|
3914
|
+
});
|
|
3215
3915
|
this.fields.push(fieldConfig);
|
|
3216
3916
|
return this;
|
|
3217
3917
|
}
|
|
@@ -3254,7 +3954,7 @@ var TypeInferredBuilder = class {
|
|
|
3254
3954
|
new RegExp(pattern),
|
|
3255
3955
|
`${label} format is invalid`
|
|
3256
3956
|
);
|
|
3257
|
-
this.schemaFields[name] = zodType;
|
|
3957
|
+
this.schemaFields[pathToString(name)] = zodType;
|
|
3258
3958
|
this.formFields.push({
|
|
3259
3959
|
inputProps: { type: "text", ...fieldOptions },
|
|
3260
3960
|
label,
|
|
@@ -3267,7 +3967,7 @@ var TypeInferredBuilder = class {
|
|
|
3267
3967
|
* Add an email field
|
|
3268
3968
|
*/
|
|
3269
3969
|
email(name, label, options) {
|
|
3270
|
-
this.schemaFields[name] = z3.string().email(`Please enter a valid email address`);
|
|
3970
|
+
this.schemaFields[pathToString(name)] = z3.string().email(`Please enter a valid email address`);
|
|
3271
3971
|
this.formFields.push({
|
|
3272
3972
|
inputProps: { type: "email", ...options },
|
|
3273
3973
|
label,
|
|
@@ -3286,7 +3986,7 @@ var TypeInferredBuilder = class {
|
|
|
3286
3986
|
zodType = zodType.min(min, `${label} must be at least ${min}`);
|
|
3287
3987
|
if (max !== void 0)
|
|
3288
3988
|
zodType = zodType.max(max, `${label} must be no more than ${max}`);
|
|
3289
|
-
this.schemaFields[name] = zodType;
|
|
3989
|
+
this.schemaFields[pathToString(name)] = zodType;
|
|
3290
3990
|
this.formFields.push({
|
|
3291
3991
|
inputProps: { max, min, step, type: "number", ...fieldOptions },
|
|
3292
3992
|
label,
|
|
@@ -3306,7 +4006,7 @@ var TypeInferredBuilder = class {
|
|
|
3306
4006
|
minLength,
|
|
3307
4007
|
`${label} must be at least ${minLength} characters`
|
|
3308
4008
|
);
|
|
3309
|
-
this.schemaFields[name] = zodType;
|
|
4009
|
+
this.schemaFields[pathToString(name)] = zodType;
|
|
3310
4010
|
this.formFields.push({
|
|
3311
4011
|
label,
|
|
3312
4012
|
name,
|
|
@@ -3319,7 +4019,7 @@ var TypeInferredBuilder = class {
|
|
|
3319
4019
|
* Add a select field
|
|
3320
4020
|
*/
|
|
3321
4021
|
select(name, label, options) {
|
|
3322
|
-
this.schemaFields[name] = z3.string().min(1, `Please select a ${label.toLowerCase()}`);
|
|
4022
|
+
this.schemaFields[pathToString(name)] = z3.string().min(1, `Please select a ${label.toLowerCase()}`);
|
|
3323
4023
|
this.formFields.push({
|
|
3324
4024
|
label,
|
|
3325
4025
|
name,
|
|
@@ -3340,7 +4040,7 @@ var TypeInferredBuilder = class {
|
|
|
3340
4040
|
`You must agree to ${label.toLowerCase()}`
|
|
3341
4041
|
);
|
|
3342
4042
|
}
|
|
3343
|
-
this.schemaFields[name] = zodType;
|
|
4043
|
+
this.schemaFields[pathToString(name)] = zodType;
|
|
3344
4044
|
this.formFields.push({
|
|
3345
4045
|
checkboxProps: fieldOptions,
|
|
3346
4046
|
label,
|
|
@@ -3353,7 +4053,7 @@ var TypeInferredBuilder = class {
|
|
|
3353
4053
|
* Add a switch field
|
|
3354
4054
|
*/
|
|
3355
4055
|
switch(name, label, options) {
|
|
3356
|
-
this.schemaFields[name] = z3.boolean().optional();
|
|
4056
|
+
this.schemaFields[pathToString(name)] = z3.boolean().optional();
|
|
3357
4057
|
this.formFields.push({
|
|
3358
4058
|
label,
|
|
3359
4059
|
name,
|
|
@@ -3366,7 +4066,7 @@ var TypeInferredBuilder = class {
|
|
|
3366
4066
|
* Add a radio field
|
|
3367
4067
|
*/
|
|
3368
4068
|
radio(name, label, options, fieldOptions) {
|
|
3369
|
-
this.schemaFields[name] = z3.string().min(1, `Please select a ${label.toLowerCase()}`);
|
|
4069
|
+
this.schemaFields[pathToString(name)] = z3.string().min(1, `Please select a ${label.toLowerCase()}`);
|
|
3370
4070
|
this.formFields.push({
|
|
3371
4071
|
label,
|
|
3372
4072
|
name,
|
|
@@ -3386,15 +4086,19 @@ var TypeInferredBuilder = class {
|
|
|
3386
4086
|
zodType = zodType.min(min, `${label} must be at least ${min}`);
|
|
3387
4087
|
if (max !== void 0)
|
|
3388
4088
|
zodType = zodType.max(max, `${label} must be no more than ${max}`);
|
|
3389
|
-
this.schemaFields[name] = zodType;
|
|
4089
|
+
this.schemaFields[pathToString(name)] = zodType;
|
|
4090
|
+
const { className, description, isDisabled, ...validSliderProps } = fieldOptions || {};
|
|
3390
4091
|
this.formFields.push({
|
|
4092
|
+
className,
|
|
4093
|
+
description,
|
|
4094
|
+
isDisabled,
|
|
3391
4095
|
label,
|
|
3392
4096
|
name,
|
|
3393
4097
|
sliderProps: {
|
|
3394
4098
|
maxValue: max,
|
|
3395
4099
|
minValue: min,
|
|
3396
4100
|
step,
|
|
3397
|
-
...
|
|
4101
|
+
...validSliderProps
|
|
3398
4102
|
},
|
|
3399
4103
|
type: "slider"
|
|
3400
4104
|
});
|
|
@@ -3404,7 +4108,7 @@ var TypeInferredBuilder = class {
|
|
|
3404
4108
|
* Add a date field
|
|
3405
4109
|
*/
|
|
3406
4110
|
date(name, label, options) {
|
|
3407
|
-
this.schemaFields[name] = z3.string().min(1, `${label} is required`);
|
|
4111
|
+
this.schemaFields[pathToString(name)] = z3.string().min(1, `${label} is required`);
|
|
3408
4112
|
this.formFields.push({
|
|
3409
4113
|
dateProps: options,
|
|
3410
4114
|
label,
|
|
@@ -3417,7 +4121,7 @@ var TypeInferredBuilder = class {
|
|
|
3417
4121
|
* Add a file field
|
|
3418
4122
|
*/
|
|
3419
4123
|
file(name, label, options) {
|
|
3420
|
-
this.schemaFields[name] = z3.any().optional();
|
|
4124
|
+
this.schemaFields[pathToString(name)] = z3.any().optional();
|
|
3421
4125
|
this.formFields.push({
|
|
3422
4126
|
fileProps: options,
|
|
3423
4127
|
label,
|
|
@@ -3494,11 +4198,18 @@ var field = {
|
|
|
3494
4198
|
// src/builders/NestedPathBuilder.ts
|
|
3495
4199
|
var NestedPathBuilder = class {
|
|
3496
4200
|
constructor() {
|
|
4201
|
+
// fields is accessed by nested builder classes, so it needs to be accessible
|
|
4202
|
+
// Making it public allows nested builders to add fields while maintaining encapsulation
|
|
3497
4203
|
this.fields = [];
|
|
3498
4204
|
}
|
|
3499
4205
|
/**
|
|
3500
4206
|
* Create a nested object path builder
|
|
3501
4207
|
* Usage: builder.nest("address").field("street", "Street Address")
|
|
4208
|
+
*
|
|
4209
|
+
* @param path - A path in the form data structure. When called from root level,
|
|
4210
|
+
* accepts Path<T>. When called after .end() from a nested context,
|
|
4211
|
+
* accepts any string for nested paths under sections.
|
|
4212
|
+
* @returns A builder for nested paths under the specified path
|
|
3502
4213
|
*/
|
|
3503
4214
|
nest(path) {
|
|
3504
4215
|
return new NestedObjectBuilder(this, path);
|
|
@@ -3512,29 +4223,18 @@ var NestedPathBuilder = class {
|
|
|
3512
4223
|
}
|
|
3513
4224
|
/**
|
|
3514
4225
|
* Add a field with single path
|
|
3515
|
-
* Usage: builder.field("firstName", "First Name")
|
|
4226
|
+
* Usage: builder.field({ type: "input", name: "firstName", label: "First Name" })
|
|
3516
4227
|
*/
|
|
3517
|
-
field(
|
|
3518
|
-
this.fields.push(
|
|
3519
|
-
label,
|
|
3520
|
-
name,
|
|
3521
|
-
type,
|
|
3522
|
-
...props
|
|
3523
|
-
});
|
|
4228
|
+
field(params) {
|
|
4229
|
+
this.fields.push(createField(params));
|
|
3524
4230
|
return this;
|
|
3525
4231
|
}
|
|
3526
4232
|
/**
|
|
3527
4233
|
* Add a field with path segments
|
|
3528
|
-
* Usage: builder.fieldPath(
|
|
4234
|
+
* Usage: builder.fieldPath({ type: "input", name: path.join("."), label: "Full Name" })
|
|
3529
4235
|
*/
|
|
3530
|
-
fieldPath(
|
|
3531
|
-
|
|
3532
|
-
this.fields.push({
|
|
3533
|
-
label,
|
|
3534
|
-
name,
|
|
3535
|
-
type,
|
|
3536
|
-
...props
|
|
3537
|
-
});
|
|
4236
|
+
fieldPath(params) {
|
|
4237
|
+
this.fields.push(createField(params));
|
|
3538
4238
|
return this;
|
|
3539
4239
|
}
|
|
3540
4240
|
/**
|
|
@@ -3563,23 +4263,28 @@ var NestedObjectBuilder = class _NestedObjectBuilder {
|
|
|
3563
4263
|
/**
|
|
3564
4264
|
* Add a field to the current nested path
|
|
3565
4265
|
*/
|
|
3566
|
-
field(
|
|
3567
|
-
const fullPath = `${this.path}.${
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
name: fullPath
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
});
|
|
4266
|
+
field(params) {
|
|
4267
|
+
const fullPath = typeof params.name === "string" ? `${this.path}.${params.name}` : params.name;
|
|
4268
|
+
const fieldParams = {
|
|
4269
|
+
...params,
|
|
4270
|
+
name: fullPath
|
|
4271
|
+
};
|
|
4272
|
+
this.parent.fields.push(createField(fieldParams));
|
|
3574
4273
|
return this;
|
|
3575
4274
|
}
|
|
3576
4275
|
/**
|
|
3577
4276
|
* Nest deeper into the object
|
|
4277
|
+
*
|
|
4278
|
+
* @param subPath - A string representing a nested path under the current path.
|
|
4279
|
+
* The parameter accepts any string; TypeScript validates the constructed
|
|
4280
|
+
* path (basePath.subPath) in the return type.
|
|
4281
|
+
* @returns A builder for the nested path
|
|
3578
4282
|
*/
|
|
3579
4283
|
nest(subPath) {
|
|
4284
|
+
const fullPath = `${this.path}.${subPath}`;
|
|
3580
4285
|
return new _NestedObjectBuilder(
|
|
3581
4286
|
this.parent,
|
|
3582
|
-
|
|
4287
|
+
fullPath
|
|
3583
4288
|
);
|
|
3584
4289
|
}
|
|
3585
4290
|
/**
|
|
@@ -3597,14 +4302,13 @@ var SectionBuilder = class {
|
|
|
3597
4302
|
/**
|
|
3598
4303
|
* Add a field to the current section
|
|
3599
4304
|
*/
|
|
3600
|
-
field(
|
|
3601
|
-
const fullPath = `${this.path}.${
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
name: fullPath
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
});
|
|
4305
|
+
field(params) {
|
|
4306
|
+
const fullPath = typeof params.name === "string" ? `${this.path}.${params.name}` : params.name;
|
|
4307
|
+
const fieldParams = {
|
|
4308
|
+
...params,
|
|
4309
|
+
name: fullPath
|
|
4310
|
+
};
|
|
4311
|
+
this.parent.fields.push(createField(fieldParams));
|
|
3608
4312
|
return this;
|
|
3609
4313
|
}
|
|
3610
4314
|
/**
|
|
@@ -3612,17 +4316,29 @@ var SectionBuilder = class {
|
|
|
3612
4316
|
*/
|
|
3613
4317
|
fields(fieldDefinitions) {
|
|
3614
4318
|
fieldDefinitions.forEach((field2) => {
|
|
3615
|
-
this.
|
|
4319
|
+
const fullPath = `${this.path}.${field2.name}`;
|
|
4320
|
+
this.parent.fields.push({
|
|
4321
|
+
label: field2.label,
|
|
4322
|
+
name: fullPath,
|
|
4323
|
+
type: field2.type || "input",
|
|
4324
|
+
...field2.props
|
|
4325
|
+
});
|
|
3616
4326
|
});
|
|
3617
4327
|
return this;
|
|
3618
4328
|
}
|
|
3619
4329
|
/**
|
|
3620
4330
|
* Nest deeper into the section
|
|
4331
|
+
*
|
|
4332
|
+
* @param subPath - A string representing a nested path under the current section path.
|
|
4333
|
+
* The parameter accepts any string; TypeScript validates the constructed
|
|
4334
|
+
* path (basePath.subPath) in the return type.
|
|
4335
|
+
* @returns A builder for the nested path
|
|
3621
4336
|
*/
|
|
3622
4337
|
nest(subPath) {
|
|
4338
|
+
const fullPath = `${this.path}.${subPath}`;
|
|
3623
4339
|
return new NestedObjectBuilder(
|
|
3624
4340
|
this.parent,
|
|
3625
|
-
|
|
4341
|
+
fullPath
|
|
3626
4342
|
);
|
|
3627
4343
|
}
|
|
3628
4344
|
/**
|
|
@@ -3640,13 +4356,12 @@ var FieldTemplateBuilder = class {
|
|
|
3640
4356
|
/**
|
|
3641
4357
|
* Complete the field definition
|
|
3642
4358
|
*/
|
|
3643
|
-
complete(
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
name: this.path
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
});
|
|
4359
|
+
complete(params) {
|
|
4360
|
+
const fieldParams = {
|
|
4361
|
+
...params,
|
|
4362
|
+
name: params.name ? `${this.path}.${params.name}` : this.path
|
|
4363
|
+
};
|
|
4364
|
+
this.parent.fields.push(createField(fieldParams));
|
|
3650
4365
|
return this.parent;
|
|
3651
4366
|
}
|
|
3652
4367
|
};
|
|
@@ -3904,7 +4619,7 @@ function syncArrays(options) {
|
|
|
3904
4619
|
}
|
|
3905
4620
|
|
|
3906
4621
|
// src/utils/createFieldArrayCustomConfig.tsx
|
|
3907
|
-
import
|
|
4622
|
+
import React27 from "react";
|
|
3908
4623
|
import { useFieldArray as useFieldArray2 } from "react-hook-form";
|
|
3909
4624
|
import { Button as Button6 } from "@heroui/react";
|
|
3910
4625
|
function createFieldArrayCustomConfig(options) {
|
|
@@ -3923,11 +4638,12 @@ function createFieldArrayCustomConfig(options) {
|
|
|
3923
4638
|
className,
|
|
3924
4639
|
label,
|
|
3925
4640
|
name,
|
|
3926
|
-
// ArrayPath is
|
|
4641
|
+
// ArrayPath is now accepted by CustomFieldConfig
|
|
3927
4642
|
render: ({ control, errors, form }) => {
|
|
3928
4643
|
const { append, fields, move, remove } = useFieldArray2({
|
|
3929
4644
|
control,
|
|
3930
4645
|
name
|
|
4646
|
+
// ArrayPath is the correct type for useFieldArray
|
|
3931
4647
|
});
|
|
3932
4648
|
const canAdd = fields.length < max;
|
|
3933
4649
|
const canRemove = fields.length > min;
|
|
@@ -3955,14 +4671,15 @@ function createFieldArrayCustomConfig(options) {
|
|
|
3955
4671
|
move(index, index + 1);
|
|
3956
4672
|
}
|
|
3957
4673
|
};
|
|
3958
|
-
return /* @__PURE__ */
|
|
4674
|
+
return /* @__PURE__ */ React27.createElement("div", { className }, /* @__PURE__ */ React27.createElement("div", { className: "space-y-4" }, fields.map((field2, index) => {
|
|
3959
4675
|
const canMoveUp = enableReordering && index > 0;
|
|
3960
4676
|
const canMoveDown = enableReordering && index < fields.length - 1;
|
|
3961
|
-
return /* @__PURE__ */
|
|
4677
|
+
return /* @__PURE__ */ React27.createElement(React27.Fragment, { key: field2.id }, renderItem({
|
|
3962
4678
|
canMoveDown,
|
|
3963
4679
|
canMoveUp,
|
|
3964
4680
|
control,
|
|
3965
4681
|
errors,
|
|
4682
|
+
// fields from useFieldArray are already typed correctly
|
|
3966
4683
|
field: field2,
|
|
3967
4684
|
fields,
|
|
3968
4685
|
form,
|
|
@@ -3971,7 +4688,7 @@ function createFieldArrayCustomConfig(options) {
|
|
|
3971
4688
|
onMoveUp: () => handleMoveUp(index),
|
|
3972
4689
|
onRemove: () => handleRemove(index)
|
|
3973
4690
|
}));
|
|
3974
|
-
}), fields.length === 0 && renderAddButton ? /* @__PURE__ */
|
|
4691
|
+
}), fields.length === 0 && renderAddButton ? /* @__PURE__ */ React27.createElement("div", { className: "text-center py-8 text-gray-500" }, /* @__PURE__ */ React27.createElement("p", null, "No ", label?.toLowerCase() || "items", " added yet."), renderAddButton({ canAdd, onAdd: handleAdd })) : null, fields.length > 0 && renderAddButton ? renderAddButton({ canAdd, onAdd: handleAdd }) : canAdd && /* @__PURE__ */ React27.createElement(
|
|
3975
4692
|
Button6,
|
|
3976
4693
|
{
|
|
3977
4694
|
variant: "bordered",
|
|
@@ -4137,6 +4854,7 @@ export {
|
|
|
4137
4854
|
AutocompleteField,
|
|
4138
4855
|
BasicFormBuilder,
|
|
4139
4856
|
CheckboxField,
|
|
4857
|
+
CheckboxGroupField,
|
|
4140
4858
|
CommonFields,
|
|
4141
4859
|
ConditionalField,
|
|
4142
4860
|
ConfigurableForm,
|
|
@@ -4204,6 +4922,7 @@ export {
|
|
|
4204
4922
|
getFormErrors,
|
|
4205
4923
|
hasFieldError,
|
|
4206
4924
|
hasFormErrors,
|
|
4925
|
+
pathToString,
|
|
4207
4926
|
serverValidation,
|
|
4208
4927
|
shallowEqual,
|
|
4209
4928
|
simulateFieldInput,
|