@page-speed/forms 0.6.3 → 0.6.4

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.
Files changed (45) hide show
  1. package/dist/{FormContext-Db0L3Kwv.d.ts → FormContext-C6kWSQuv.d.ts} +1 -1
  2. package/dist/{FormContext-kKZxeb7G.d.cts → FormContext-DLG3GzgL.d.cts} +1 -1
  3. package/dist/chunk-A7MVZ757.js +701 -0
  4. package/dist/chunk-A7MVZ757.js.map +1 -0
  5. package/dist/chunk-DCGSRMZT.cjs +728 -0
  6. package/dist/chunk-DCGSRMZT.cjs.map +1 -0
  7. package/dist/chunk-UBDA7CS5.js +3 -0
  8. package/dist/chunk-UBDA7CS5.js.map +1 -0
  9. package/dist/chunk-V7JSGFCI.cjs +4 -0
  10. package/dist/chunk-V7JSGFCI.cjs.map +1 -0
  11. package/dist/core.cjs +13 -13
  12. package/dist/core.d.cts +10 -8
  13. package/dist/core.d.ts +10 -8
  14. package/dist/core.js +2 -2
  15. package/dist/index.cjs +12 -12
  16. package/dist/index.d.cts +2 -2
  17. package/dist/index.d.ts +2 -2
  18. package/dist/index.js +2 -2
  19. package/dist/inputs.d.cts +1 -1
  20. package/dist/inputs.d.ts +1 -1
  21. package/dist/integration.cjs +101 -3
  22. package/dist/integration.cjs.map +1 -1
  23. package/dist/integration.d.cts +103 -18
  24. package/dist/integration.d.ts +103 -18
  25. package/dist/integration.js +100 -3
  26. package/dist/integration.js.map +1 -1
  27. package/dist/{types-BPxsUGm_.d.ts → types-BhcLAcZe.d.cts} +31 -22
  28. package/dist/{types-BPxsUGm_.d.cts → types-BhcLAcZe.d.ts} +31 -22
  29. package/dist/validation-rules.d.cts +1 -1
  30. package/dist/validation-rules.d.ts +1 -1
  31. package/dist/validation-utils.d.cts +1 -1
  32. package/dist/validation-utils.d.ts +1 -1
  33. package/dist/validation-valibot.d.cts +1 -1
  34. package/dist/validation-valibot.d.ts +1 -1
  35. package/dist/validation.d.cts +1 -1
  36. package/dist/validation.d.ts +1 -1
  37. package/package.json +1 -1
  38. package/dist/chunk-3ED2FKXF.cjs +0 -350
  39. package/dist/chunk-3ED2FKXF.cjs.map +0 -1
  40. package/dist/chunk-H3YJRLVO.js +0 -326
  41. package/dist/chunk-H3YJRLVO.js.map +0 -1
  42. package/dist/chunk-SNSK3TMG.js +0 -373
  43. package/dist/chunk-SNSK3TMG.js.map +0 -1
  44. package/dist/chunk-V545YJFP.cjs +0 -397
  45. package/dist/chunk-V545YJFP.cjs.map +0 -1
@@ -0,0 +1,728 @@
1
+ 'use strict';
2
+
3
+ var chunkQMWZLGON_cjs = require('./chunk-QMWZLGON.cjs');
4
+ var React5 = require('react');
5
+ var react = require('@legendapp/state/react');
6
+ var useMap = require('@opensite/hooks/useMap');
7
+ var classVarianceAuthority = require('class-variance-authority');
8
+ require('radix-ui');
9
+ var icon = require('@page-speed/icon');
10
+
11
+ function _interopNamespace(e) {
12
+ if (e && e.__esModule) return e;
13
+ var n = Object.create(null);
14
+ if (e) {
15
+ Object.keys(e).forEach(function (k) {
16
+ if (k !== 'default') {
17
+ var d = Object.getOwnPropertyDescriptor(e, k);
18
+ Object.defineProperty(n, k, d.get ? d : {
19
+ enumerable: true,
20
+ get: function () { return e[k]; }
21
+ });
22
+ }
23
+ });
24
+ }
25
+ n.default = e;
26
+ return Object.freeze(n);
27
+ }
28
+
29
+ var React5__namespace = /*#__PURE__*/_interopNamespace(React5);
30
+
31
+ function useForm(options) {
32
+ const {
33
+ initialValues,
34
+ validationSchema,
35
+ validateOn = "onBlur",
36
+ revalidateOn = "onChange",
37
+ onSubmit,
38
+ onError,
39
+ debug = false
40
+ } = options;
41
+ const state$ = react.useObservable({
42
+ values: initialValues,
43
+ errors: {},
44
+ touched: {},
45
+ isSubmitting: false,
46
+ status: "idle",
47
+ initialValues: { ...initialValues },
48
+ // Create a copy to prevent reference sharing
49
+ hasValidated: {}
50
+ });
51
+ const validationInProgress = React5.useRef(/* @__PURE__ */ new Set());
52
+ const [, fieldMetadataActions] = useMap.useMap();
53
+ const validateField = React5.useCallback(
54
+ async (field) => {
55
+ const validators = validationSchema?.[field];
56
+ if (!validators) return void 0;
57
+ const fieldKey = String(field);
58
+ validationInProgress.current.add(fieldKey);
59
+ const currentMeta = fieldMetadataActions.get(fieldKey) || {
60
+ validationCount: 0
61
+ };
62
+ fieldMetadataActions.set(fieldKey, {
63
+ lastValidated: Date.now(),
64
+ validationCount: currentMeta.validationCount + 1
65
+ });
66
+ try {
67
+ const value = state$.values[field].get();
68
+ const allValues = state$.values.get();
69
+ const validatorArray = Array.isArray(validators) ? validators : [validators];
70
+ for (const validator of validatorArray) {
71
+ const error = await validator(value, allValues);
72
+ if (error) {
73
+ state$.errors[field].set(error);
74
+ validationInProgress.current.delete(fieldKey);
75
+ return error;
76
+ }
77
+ }
78
+ state$.errors[field].set(void 0);
79
+ validationInProgress.current.delete(fieldKey);
80
+ return void 0;
81
+ } catch (error) {
82
+ validationInProgress.current.delete(fieldKey);
83
+ const errorMessage = error instanceof Error ? error.message : "Validation error";
84
+ state$.errors[field].set(errorMessage);
85
+ return errorMessage;
86
+ }
87
+ },
88
+ [validationSchema, state$, fieldMetadataActions]
89
+ );
90
+ const validateForm = React5.useCallback(async () => {
91
+ if (!validationSchema) return {};
92
+ const fields = Object.keys(validationSchema);
93
+ const errors2 = {};
94
+ await Promise.all(
95
+ fields.map(async (field) => {
96
+ const error = await validateField(field);
97
+ if (error) {
98
+ errors2[field] = error;
99
+ }
100
+ })
101
+ );
102
+ state$.errors.set(errors2);
103
+ return errors2;
104
+ }, [validationSchema, validateField, state$]);
105
+ const setFieldValue = React5.useCallback(
106
+ (field, value) => {
107
+ state$.values[field].set(value);
108
+ const shouldRevalidate = revalidateOn === "onChange" && state$.hasValidated[String(field)].get();
109
+ if (shouldRevalidate && validationSchema?.[field]) {
110
+ validateField(field);
111
+ }
112
+ if (debug) {
113
+ console.log("[useForm] setFieldValue:", { field, value });
114
+ }
115
+ },
116
+ [state$, revalidateOn, validationSchema, validateField, debug]
117
+ );
118
+ const setFieldTouched = React5.useCallback(
119
+ (field, touched2) => {
120
+ state$.touched[field].set(touched2);
121
+ if (touched2 && validateOn === "onBlur" && validationSchema?.[field]) {
122
+ state$.hasValidated[String(field)].set(true);
123
+ validateField(field);
124
+ }
125
+ if (debug) {
126
+ console.log("[useForm] setFieldTouched:", { field, touched: touched2 });
127
+ }
128
+ },
129
+ [state$, validateOn, validationSchema, validateField, debug]
130
+ );
131
+ const resetForm = React5.useCallback(() => {
132
+ state$.values.set(state$.initialValues.get());
133
+ state$.errors.set({});
134
+ state$.touched.set({});
135
+ state$.isSubmitting.set(false);
136
+ state$.status.set("idle");
137
+ state$.hasValidated.set({});
138
+ fieldMetadataActions.clear();
139
+ if (debug) {
140
+ console.log("[useForm] Form reset");
141
+ }
142
+ }, [state$, fieldMetadataActions, debug]);
143
+ const handleSubmit = React5.useCallback(
144
+ async (e) => {
145
+ e?.preventDefault();
146
+ if (debug) {
147
+ console.log("[useForm] handleSubmit started");
148
+ }
149
+ state$.isSubmitting.set(true);
150
+ state$.status.set("submitting");
151
+ try {
152
+ const errors2 = await validateForm();
153
+ const hasErrors = Object.keys(errors2).length > 0;
154
+ if (hasErrors) {
155
+ state$.status.set("error");
156
+ onError?.(errors2);
157
+ if (debug) {
158
+ console.log("[useForm] Validation errors:", errors2);
159
+ }
160
+ return;
161
+ }
162
+ const helpers = {
163
+ setValues: (values2) => {
164
+ if (typeof values2 === "function") {
165
+ state$.values.set(values2(state$.values.get()));
166
+ } else {
167
+ state$.values.set(values2);
168
+ }
169
+ },
170
+ setFieldValue,
171
+ setErrors: (errors3) => state$.errors.set(errors3),
172
+ setFieldError: (field, error) => state$.errors[field].set(error),
173
+ setTouched: (touched2) => state$.touched.set(touched2),
174
+ setFieldTouched,
175
+ setSubmitting: (submitting) => state$.isSubmitting.set(submitting),
176
+ resetForm
177
+ };
178
+ await onSubmit(state$.values.get(), helpers);
179
+ state$.status.set("success");
180
+ if (debug) {
181
+ console.log("[useForm] Submit successful");
182
+ }
183
+ } catch (error) {
184
+ state$.status.set("error");
185
+ if (debug) {
186
+ console.error("[useForm] Submit error:", error);
187
+ }
188
+ throw error;
189
+ } finally {
190
+ state$.isSubmitting.set(false);
191
+ }
192
+ },
193
+ [
194
+ state$,
195
+ validateForm,
196
+ onSubmit,
197
+ onError,
198
+ setFieldValue,
199
+ setFieldTouched,
200
+ resetForm,
201
+ debug
202
+ ]
203
+ );
204
+ const getFieldProps = React5.useCallback(
205
+ (field) => {
206
+ return {
207
+ name: String(field),
208
+ value: state$.values[field].get(),
209
+ onChange: (value) => setFieldValue(field, value),
210
+ onBlur: () => setFieldTouched(field, true)
211
+ };
212
+ },
213
+ [state$, setFieldValue, setFieldTouched]
214
+ );
215
+ const getFieldMeta = React5.useCallback(
216
+ (field) => {
217
+ const fieldKey = String(field);
218
+ const metadata = fieldMetadataActions.get(fieldKey);
219
+ return {
220
+ error: state$.errors[field].get(),
221
+ touched: state$.touched[field].get() ?? false,
222
+ isDirty: state$.values[field].get() !== state$.initialValues[field].get(),
223
+ isValidating: validationInProgress.current.has(fieldKey),
224
+ // Additional metadata from @opensite/hooks
225
+ validationCount: metadata?.validationCount,
226
+ lastValidated: metadata?.lastValidated
227
+ };
228
+ },
229
+ [state$, fieldMetadataActions]
230
+ );
231
+ const values = react.useSelector(() => state$.values.get());
232
+ const errors = react.useSelector(() => state$.errors.get());
233
+ const touched = react.useSelector(() => state$.touched.get());
234
+ const isSubmitting = react.useSelector(() => state$.isSubmitting.get());
235
+ const status = react.useSelector(() => state$.status.get());
236
+ const isValid = react.useSelector(() => Object.keys(state$.errors.get()).length === 0);
237
+ const isDirty = react.useSelector(() => {
238
+ const currentValues = state$.values.get();
239
+ const initialValues2 = state$.initialValues.get();
240
+ return Object.keys(currentValues).some(
241
+ (key) => currentValues[key] !== initialValues2[key]
242
+ );
243
+ });
244
+ return {
245
+ // State
246
+ values,
247
+ errors,
248
+ touched,
249
+ isSubmitting,
250
+ isValid,
251
+ isDirty,
252
+ status,
253
+ // Actions
254
+ handleSubmit,
255
+ setValues: (values2) => {
256
+ if (typeof values2 === "function") {
257
+ state$.values.set(values2(state$.values.get()));
258
+ } else {
259
+ state$.values.set(values2);
260
+ }
261
+ },
262
+ setFieldValue,
263
+ setErrors: (errors2) => state$.errors.set(errors2),
264
+ setFieldError: (field, error) => state$.errors[field].set(error),
265
+ setTouched: (touched2) => state$.touched.set(touched2),
266
+ setFieldTouched,
267
+ validateForm,
268
+ validateField,
269
+ resetForm,
270
+ getFieldProps,
271
+ getFieldMeta
272
+ };
273
+ }
274
+ var FormContext = React5__namespace.createContext(null);
275
+ FormContext.displayName = "FormContext";
276
+ function useField(options) {
277
+ const { name, validate, transform } = options;
278
+ const form = React5.useContext(FormContext);
279
+ if (!form) {
280
+ throw new Error(
281
+ "useField must be used within a FormContext. Wrap your component with <Form> or use useForm's getFieldProps instead."
282
+ );
283
+ }
284
+ const baseFieldProps = form.getFieldProps(name);
285
+ const field = {
286
+ ...baseFieldProps,
287
+ value: baseFieldProps.value,
288
+ onChange: (value) => {
289
+ const transformedValue = transform ? transform(value) : value;
290
+ baseFieldProps.onChange(transformedValue);
291
+ if (validate) {
292
+ const result = validate(transformedValue, form.values);
293
+ if (result instanceof Promise) {
294
+ result.then((error) => {
295
+ if (error !== void 0) {
296
+ form.setFieldError(name, error);
297
+ }
298
+ });
299
+ } else if (result !== void 0) {
300
+ form.setFieldError(name, result);
301
+ }
302
+ }
303
+ }
304
+ };
305
+ const meta = form.getFieldMeta(name);
306
+ const helpers = {
307
+ setValue: React5.useCallback(
308
+ (value) => {
309
+ const transformedValue = transform ? transform(value) : value;
310
+ form.setFieldValue(name, transformedValue);
311
+ },
312
+ [name, transform, form]
313
+ ),
314
+ setTouched: React5.useCallback(
315
+ (touched) => {
316
+ form.setFieldTouched(name, touched);
317
+ },
318
+ [name, form]
319
+ ),
320
+ setError: React5.useCallback(
321
+ (error) => {
322
+ form.setFieldError(name, error);
323
+ },
324
+ [name, form]
325
+ )
326
+ };
327
+ return {
328
+ field,
329
+ meta,
330
+ helpers
331
+ };
332
+ }
333
+ function renderMessage(message, fallbackClassName, className) {
334
+ if (typeof message === "string") {
335
+ return /* @__PURE__ */ React5__namespace.createElement(
336
+ "p",
337
+ {
338
+ className: chunkQMWZLGON_cjs.cn(
339
+ "text-sm font-medium text-center text-balance",
340
+ className
341
+ )
342
+ },
343
+ message
344
+ );
345
+ }
346
+ return /* @__PURE__ */ React5__namespace.createElement("div", { className: chunkQMWZLGON_cjs.cn(fallbackClassName, className) }, message);
347
+ }
348
+ function FormFeedback({
349
+ successMessage,
350
+ submissionError,
351
+ successMessageClassName,
352
+ errorMessageClassName
353
+ }) {
354
+ if (!successMessage && !submissionError) {
355
+ return null;
356
+ }
357
+ return /* @__PURE__ */ React5__namespace.createElement(React5__namespace.Fragment, null, successMessage ? /* @__PURE__ */ React5__namespace.createElement(
358
+ "div",
359
+ {
360
+ className: chunkQMWZLGON_cjs.cn(
361
+ "rounded-md border border-primary bg-primary px-4 py-3 shadow-sm",
362
+ successMessageClassName
363
+ ),
364
+ role: "status",
365
+ "aria-live": "polite"
366
+ },
367
+ renderMessage(
368
+ successMessage,
369
+ "text-primary-foreground",
370
+ "text-primary-foreground"
371
+ )
372
+ ) : null, submissionError ? /* @__PURE__ */ React5__namespace.createElement(
373
+ "div",
374
+ {
375
+ className: chunkQMWZLGON_cjs.cn(
376
+ "rounded-md border border-destructive bg-destructive px-4 py-3 shadow-sm",
377
+ errorMessageClassName
378
+ ),
379
+ role: "alert",
380
+ "aria-live": "assertive"
381
+ },
382
+ renderMessage(
383
+ submissionError,
384
+ "text-destructive-foreground",
385
+ "text-destructive-foreground"
386
+ )
387
+ ) : null);
388
+ }
389
+ FormFeedback.displayName = "FormFeedback";
390
+ var buttonGroupVariants = classVarianceAuthority.cva(
391
+ "flex w-fit items-stretch [&>*]:focus-visible:z-10 [&>*]:focus-visible:relative [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md has-[>[data-slot=button-group]]:gap-2",
392
+ {
393
+ variants: {
394
+ orientation: {
395
+ horizontal: "[&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none",
396
+ vertical: "flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none"
397
+ }
398
+ },
399
+ defaultVariants: {
400
+ orientation: "horizontal"
401
+ }
402
+ }
403
+ );
404
+ function ButtonGroup({
405
+ className,
406
+ orientation,
407
+ ...props
408
+ }) {
409
+ return /* @__PURE__ */ React5__namespace.createElement(
410
+ "div",
411
+ {
412
+ role: "group",
413
+ "data-slot": "button-group",
414
+ "data-orientation": orientation,
415
+ className: chunkQMWZLGON_cjs.cn(buttonGroupVariants({ orientation }), className),
416
+ ...props
417
+ }
418
+ );
419
+ }
420
+ var FieldFeedback = ({
421
+ errorId,
422
+ errorClassName,
423
+ error,
424
+ shouldRenderError
425
+ }) => {
426
+ const errorText = Array.isArray(error) ? error.join(", ") : error;
427
+ if (!errorText || !shouldRenderError) return null;
428
+ return /* @__PURE__ */ React5__namespace.createElement(chunkQMWZLGON_cjs.FieldError, { id: errorId, className: errorClassName }, errorText);
429
+ };
430
+ var DEFAULT_ICON_API_KEY = "au382bi7fsh96w9h9xlrnat2jglx";
431
+ var INPUT_SIZE_CLASSES = {
432
+ xs: "h-6 text-xs px-3",
433
+ // button: h-6 → match
434
+ sm: "text-sm px-3",
435
+ // button: h-8 overridden to h-9 below → match
436
+ default: "text-base px-4",
437
+ // button: h-9 (no override needed)
438
+ lg: "h-10 text-md px-6"
439
+ // button: h-10 → match
440
+ };
441
+ function ButtonGroupForm({
442
+ name,
443
+ label,
444
+ description,
445
+ inputProps,
446
+ submitLabel = "Submit",
447
+ submitVariant = "default",
448
+ size = "default",
449
+ isSubmitting = false,
450
+ submitIconName,
451
+ submitIconComponent,
452
+ errorText,
453
+ className,
454
+ labelClassName
455
+ }) {
456
+ const inputId = React5__namespace.useMemo(() => {
457
+ return `button-group-input-${name}`;
458
+ }, [name]);
459
+ const errorId = `${inputId}-error`;
460
+ const hasValue = React5__namespace.useMemo(() => {
461
+ return String(inputProps.value ?? "").trim().length > 0;
462
+ }, [inputProps.value]);
463
+ const hasError = React5__namespace.useMemo(() => {
464
+ return !!inputProps.error;
465
+ }, [inputProps.error]);
466
+ const buttonSize = React5__namespace.useMemo(() => {
467
+ if (submitIconName || submitIconComponent) {
468
+ return size === "default" || size === "sm" ? "icon" : `icon-${size}`;
469
+ }
470
+ return size;
471
+ }, [submitIconName, size, submitIconComponent]);
472
+ const labelElement = React5__namespace.useMemo(() => {
473
+ if (submitIconName) {
474
+ return /* @__PURE__ */ React5__namespace.createElement(icon.Icon, { name: submitIconName, apiKey: DEFAULT_ICON_API_KEY });
475
+ } else if (submitIconComponent) {
476
+ return submitIconComponent;
477
+ } else if (submitLabel) {
478
+ return submitLabel;
479
+ } else {
480
+ return "Submit";
481
+ }
482
+ }, [submitIconComponent, submitIconName, submitLabel]);
483
+ return /* @__PURE__ */ React5__namespace.createElement("div", { className: chunkQMWZLGON_cjs.cn("space-y-2", className) }, label && /* @__PURE__ */ React5__namespace.createElement(chunkQMWZLGON_cjs.FieldLabel, { htmlFor: inputId, className: labelClassName }, label), /* @__PURE__ */ React5__namespace.createElement(
484
+ ButtonGroup,
485
+ {
486
+ className: chunkQMWZLGON_cjs.cn(
487
+ "rounded-md",
488
+ !hasError && hasValue && "ring-2 ring-ring",
489
+ hasError && "ring-1 ring-destructive"
490
+ )
491
+ },
492
+ /* @__PURE__ */ React5__namespace.createElement(
493
+ chunkQMWZLGON_cjs.TextInput,
494
+ {
495
+ ...inputProps,
496
+ id: inputId,
497
+ suppressValueRing: true,
498
+ "aria-describedby": hasError ? errorId : void 0,
499
+ className: chunkQMWZLGON_cjs.cn(
500
+ INPUT_SIZE_CLASSES[size],
501
+ "border-r-0 rounded-r-none focus-visible:z-10",
502
+ inputProps.className
503
+ )
504
+ }
505
+ ),
506
+ /* @__PURE__ */ React5__namespace.createElement(
507
+ chunkQMWZLGON_cjs.Button,
508
+ {
509
+ size: buttonSize,
510
+ type: "submit",
511
+ variant: submitVariant,
512
+ disabled: isSubmitting,
513
+ className: chunkQMWZLGON_cjs.cn(
514
+ "relative rounded-l-none ring-0",
515
+ // 'sm' button variant is h-8; override to h-9 to align with input
516
+ size === "sm" && "h-9"
517
+ )
518
+ },
519
+ isSubmitting ? /* @__PURE__ */ React5__namespace.createElement("span", { className: "absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2" }, /* @__PURE__ */ React5__namespace.createElement(
520
+ icon.Icon,
521
+ {
522
+ name: "line-md/loading-twotone-loop",
523
+ apiKey: DEFAULT_ICON_API_KEY
524
+ }
525
+ )) : null,
526
+ /* @__PURE__ */ React5__namespace.createElement(
527
+ "span",
528
+ {
529
+ className: chunkQMWZLGON_cjs.cn(
530
+ "transition-opacity duration-200",
531
+ isSubmitting ? "opacity-0" : "opacity-100"
532
+ )
533
+ },
534
+ labelElement
535
+ )
536
+ )
537
+ ), description && /* @__PURE__ */ React5__namespace.createElement(chunkQMWZLGON_cjs.FieldDescription, null, description), /* @__PURE__ */ React5__namespace.createElement(
538
+ FieldFeedback,
539
+ {
540
+ error: errorText,
541
+ shouldRenderError: hasError,
542
+ errorId
543
+ }
544
+ ));
545
+ }
546
+ ButtonGroupForm.displayName = "ButtonGroupForm";
547
+ function Form({
548
+ form,
549
+ children,
550
+ fields,
551
+ className,
552
+ action,
553
+ method,
554
+ noValidate = true,
555
+ submissionConfig,
556
+ successMessage,
557
+ submissionError,
558
+ successMessageClassName,
559
+ errorMessageClassName,
560
+ onNewSubmission,
561
+ notificationConfig,
562
+ styleConfig,
563
+ formConfig,
564
+ ...props
565
+ }) {
566
+ const handleFormSubmit = React5__namespace.useCallback(
567
+ async (e) => {
568
+ try {
569
+ await form.handleSubmit(e);
570
+ } catch {
571
+ }
572
+ },
573
+ [form]
574
+ );
575
+ const resolvedClassName = className ?? styleConfig?.formClassName;
576
+ const resolvedAction = action ?? formConfig?.endpoint;
577
+ const resolvedMethod = method ?? formConfig?.method ?? "post";
578
+ const resolvedSubmissionConfig = submissionConfig ?? formConfig?.submissionConfig;
579
+ const resolvedSuccessMessage = successMessage ?? notificationConfig?.successMessage;
580
+ const resolvedSubmissionError = submissionError ?? notificationConfig?.submissionError;
581
+ const resolvedSuccessMessageClassName = successMessageClassName ?? styleConfig?.successMessageClassName;
582
+ const resolvedErrorMessageClassName = errorMessageClassName ?? styleConfig?.errorMessageClassName;
583
+ const behavior = resolvedSubmissionConfig?.behavior || "showConfirmation";
584
+ const shouldManageSubmissionUi = resolvedSubmissionConfig !== void 0 || resolvedSuccessMessage !== void 0 || resolvedSuccessMessageClassName !== void 0 || resolvedErrorMessageClassName !== void 0 || resolvedSubmissionError != null || onNewSubmission !== void 0;
585
+ const hasSubmissionError = Boolean(resolvedSubmissionError);
586
+ const isSubmissionSuccessful = shouldManageSubmissionUi && form.status === "success" && !hasSubmissionError;
587
+ const defaultSuccessMessage = behavior === "redirect" ? "Form submitted successfully. Redirecting..." : "Thank you. Your form has been submitted successfully.";
588
+ const finalSuccessMessage = resolvedSuccessMessage ?? defaultSuccessMessage;
589
+ const shouldRenderCustomComponent = isSubmissionSuccessful && behavior === "renderCustomComponent" && Boolean(resolvedSubmissionConfig?.customComponent);
590
+ const newSubmissionAction = resolvedSubmissionConfig?.newFormSubmissionAction;
591
+ const showNewSubmissionAction = isSubmissionSuccessful && (typeof newSubmissionAction?.enable === "boolean" ? newSubmissionAction.enable : Boolean(newSubmissionAction?.label));
592
+ const newSubmissionLabel = newSubmissionAction?.label ?? "Submit another response";
593
+ const handleNewSubmission = React5__namespace.useCallback(() => {
594
+ form.resetForm();
595
+ onNewSubmission?.();
596
+ }, [form, onNewSubmission]);
597
+ const formLayout = formConfig?.formLayout ?? "standard";
598
+ const isButtonGroupLayout = formLayout === "button-group";
599
+ const hasTextField = fields && fields.length === 1 && fields[0] && ["text", "email", "password", "url", "tel", "search"].includes(
600
+ fields[0].type
601
+ );
602
+ const shouldUseButtonGroup = isButtonGroupLayout && hasTextField;
603
+ const buttonGroupContent = React5__namespace.useMemo(() => {
604
+ if (!shouldUseButtonGroup || !fields || fields.length === 0) return null;
605
+ const field = fields[0];
606
+ const fieldProps = form.getFieldProps(field.name);
607
+ const fieldMeta = form.getFieldMeta(field.name);
608
+ return /* @__PURE__ */ React5__namespace.createElement(
609
+ ButtonGroupForm,
610
+ {
611
+ name: field.name,
612
+ label: field.label,
613
+ description: field.description,
614
+ className: field.className,
615
+ inputProps: {
616
+ name: fieldProps.name,
617
+ value: fieldProps.value,
618
+ onChange: fieldProps.onChange,
619
+ onBlur: fieldProps.onBlur,
620
+ type: field.type,
621
+ placeholder: field.placeholder,
622
+ required: field.required,
623
+ disabled: field.disabled,
624
+ error: fieldMeta.touched && !!fieldMeta.error
625
+ },
626
+ errorText: fieldMeta.touched ? fieldMeta.error : void 0,
627
+ submitLabel: formConfig?.submitLabel,
628
+ submitVariant: formConfig?.submitVariant,
629
+ submitIconName: formConfig?.submitIconName,
630
+ submitIconComponent: formConfig?.submitIconComponent,
631
+ size: formConfig?.buttonGroupSize,
632
+ isSubmitting: form.isSubmitting
633
+ }
634
+ );
635
+ }, [shouldUseButtonGroup, fields, form, formConfig]);
636
+ return /* @__PURE__ */ React5__namespace.createElement(FormContext.Provider, { value: form }, /* @__PURE__ */ React5__namespace.createElement(
637
+ "form",
638
+ {
639
+ onSubmit: handleFormSubmit,
640
+ action: resolvedAction,
641
+ method: resolvedMethod,
642
+ noValidate,
643
+ className: resolvedClassName,
644
+ ...props
645
+ },
646
+ isSubmissionSuccessful ? /* @__PURE__ */ React5__namespace.createElement("div", { className: "space-y-4" }, shouldRenderCustomComponent ? resolvedSubmissionConfig?.customComponent : /* @__PURE__ */ React5__namespace.createElement(
647
+ FormFeedback,
648
+ {
649
+ successMessage: finalSuccessMessage,
650
+ successMessageClassName: resolvedSuccessMessageClassName
651
+ }
652
+ ), showNewSubmissionAction ? /* @__PURE__ */ React5__namespace.createElement(
653
+ chunkQMWZLGON_cjs.Button,
654
+ {
655
+ type: "button",
656
+ variant: "outline",
657
+ onClick: handleNewSubmission
658
+ },
659
+ newSubmissionLabel
660
+ ) : null) : /* @__PURE__ */ React5__namespace.createElement(React5__namespace.Fragment, null, shouldUseButtonGroup ? buttonGroupContent : children, resolvedSubmissionError ? /* @__PURE__ */ React5__namespace.createElement("div", { className: "mt-4" }, /* @__PURE__ */ React5__namespace.createElement(
661
+ FormFeedback,
662
+ {
663
+ submissionError: resolvedSubmissionError,
664
+ errorMessageClassName: resolvedErrorMessageClassName
665
+ }
666
+ )) : null)
667
+ ));
668
+ }
669
+ Form.displayName = "Form";
670
+ function Field2({
671
+ name,
672
+ label,
673
+ description,
674
+ children,
675
+ showError = true,
676
+ className,
677
+ errorClassName,
678
+ required = false,
679
+ validate
680
+ }) {
681
+ const fieldState = useField({ name, validate });
682
+ const { meta } = fieldState;
683
+ const hasError = React5__namespace.useMemo(() => {
684
+ return showError && meta.touched && meta.error ? true : false;
685
+ }, [meta?.touched, meta?.error, showError]);
686
+ const errorId = `${name}-error`;
687
+ const descriptionId = `${name}-description`;
688
+ return /* @__PURE__ */ React5__namespace.createElement(
689
+ chunkQMWZLGON_cjs.Field,
690
+ {
691
+ className,
692
+ "data-field": name,
693
+ invalid: hasError
694
+ },
695
+ /* @__PURE__ */ React5__namespace.createElement(
696
+ chunkQMWZLGON_cjs.LabelGroup,
697
+ {
698
+ labelHtmlFor: name,
699
+ required,
700
+ variant: "label",
701
+ secondaryId: descriptionId,
702
+ secondary: description,
703
+ primary: label
704
+ }
705
+ ),
706
+ /* @__PURE__ */ React5__namespace.createElement("div", { "data-slot": "field-control" }, typeof children === "function" ? children(fieldState) : children),
707
+ /* @__PURE__ */ React5__namespace.createElement(
708
+ FieldFeedback,
709
+ {
710
+ errorId,
711
+ errorClassName,
712
+ shouldRenderError: hasError,
713
+ error: meta.error
714
+ }
715
+ )
716
+ );
717
+ }
718
+ Field2.displayName = "Field";
719
+
720
+ exports.ButtonGroupForm = ButtonGroupForm;
721
+ exports.Field = Field2;
722
+ exports.Form = Form;
723
+ exports.FormContext = FormContext;
724
+ exports.FormFeedback = FormFeedback;
725
+ exports.useField = useField;
726
+ exports.useForm = useForm;
727
+ //# sourceMappingURL=chunk-DCGSRMZT.cjs.map
728
+ //# sourceMappingURL=chunk-DCGSRMZT.cjs.map