@wix/headless-forms 0.0.1

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.
@@ -0,0 +1,613 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React from 'react';
3
+ import { AsChildSlot } from '@wix/headless-utils/react';
4
+ import * as CoreForm from './core/Form.js';
5
+ var TestIds;
6
+ (function (TestIds) {
7
+ TestIds["formRoot"] = "form-root";
8
+ TestIds["formLoadingError"] = "form-loading-error";
9
+ TestIds["formError"] = "form-error";
10
+ TestIds["formSubmitted"] = "form-submitted";
11
+ })(TestIds || (TestIds = {}));
12
+ /**
13
+ * Root component that provides all necessary service contexts for a complete form experience.
14
+ * This component sets up the Form service and provides context to child components.
15
+ * Must be used as the top-level component for all form functionality.
16
+ *
17
+ * @component
18
+ * @param {RootProps} props - The component props
19
+ * @param {React.ReactNode} props.children - Child components that will have access to form context
20
+ * @param {FormServiceConfig} props.formServiceConfig - Form service configuration object
21
+ * @param {string} [props.className] - CSS classes to apply to the root element
22
+ * @example
23
+ * ```tsx
24
+ * import { Form } from '@wix/headless-forms/react';
25
+ * import { loadFormServiceConfig } from '@wix/headless-forms/services';
26
+ *
27
+ * const FIELD_MAP = {
28
+ * TEXT_INPUT: TextInput,
29
+ * TEXT_AREA: TextArea,
30
+ * CHECKBOX: Checkbox,
31
+ * // ... other field components
32
+ * };
33
+ *
34
+ * // Pattern 1: Pre-loaded form data (SSR/SSG)
35
+ * function FormPage({ formServiceConfig }) {
36
+ * return (
37
+ * <Form.Root formServiceConfig={formServiceConfig}>
38
+ * <Form.Loading className="flex justify-center p-4" />
39
+ * <Form.LoadingError className="text-destructive px-4 py-3 rounded mb-4" />
40
+ * <Form.Fields fieldMap={FIELD_MAP} />
41
+ * <Form.Error className="text-destructive p-4 rounded-lg mb-4" />
42
+ * <Form.Submitted className="text-green-500 p-4 rounded-lg mb-4" />
43
+ * </Form.Root>
44
+ * );
45
+ * }
46
+ *
47
+ * // Pattern 2: Lazy loading with formId (Client-side)
48
+ * function DynamicFormPage({ formId }) {
49
+ * return (
50
+ * <Form.Root formServiceConfig={{ formId }}>
51
+ * <Form.Loading className="flex justify-center p-4" />
52
+ * <Form.LoadingError className="text-destructive px-4 py-3 rounded mb-4" />
53
+ * <Form.Fields fieldMap={FIELD_MAP} />
54
+ * <Form.Error className="text-destructive p-4 rounded-lg mb-4" />
55
+ * <Form.Submitted className="text-green-500 p-4 rounded-lg mb-4" />
56
+ * </Form.Root>
57
+ * );
58
+ * }
59
+ * ```
60
+ */
61
+ export const Root = React.forwardRef((props, ref) => {
62
+ const { children, formServiceConfig, asChild, ...otherProps } = props;
63
+ return (_jsx(CoreForm.Root, { formServiceConfig: formServiceConfig, children: _jsx(RootContent, { asChild: asChild, ref: ref, ...otherProps, children: children }) }));
64
+ });
65
+ /**
66
+ * Internal component to handle the Root content with service access.
67
+ * This component wraps the children with the necessary div container and applies styling.
68
+ *
69
+ * @internal
70
+ * @param {RootContentProps} props - Component props
71
+ * @param {React.ReactNode} props.children - Child components to render
72
+ * @param {string} [props.className] - CSS classes to apply to the container
73
+ * @param {boolean} [props.asChild] - Whether to render as a child component
74
+ * @returns {JSX.Element} The wrapped content
75
+ */
76
+ const RootContent = React.forwardRef((props, ref) => {
77
+ const { asChild, children, className, ...otherProps } = props;
78
+ return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.formRoot, customElement: children, customElementProps: {}, ...otherProps, children: _jsx("div", { children: React.isValidElement(children) ? children : null }) }));
79
+ });
80
+ /**
81
+ * Component that renders content during loading state.
82
+ * Only displays its children when the form is currently loading.
83
+ *
84
+ * @component
85
+ * @param {LoadingProps} props - The component props
86
+ * @param {boolean} [props.asChild] - Whether to render as a child component
87
+ * @param {React.ReactNode} [props.children] - Content to display during loading state
88
+ * @param {string} [props.className] - CSS classes to apply to the default element
89
+ * @example
90
+ * ```tsx
91
+ * import { Form } from '@wix/headless-forms/react';
92
+ *
93
+ * // Default usage with className
94
+ * function FormLoading() {
95
+ * return (
96
+ * <Form.Loading className="flex justify-center p-4" />
97
+ * );
98
+ * }
99
+ *
100
+ * // Custom content
101
+ * function CustomFormLoading() {
102
+ * return (
103
+ * <Form.Loading>
104
+ * <div className="flex justify-center items-center p-4">
105
+ * <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary"></div>
106
+ * <span className="ml-2 text-foreground font-paragraph">Loading form...</span>
107
+ * </div>
108
+ * </Form.Loading>
109
+ * );
110
+ * }
111
+ *
112
+ * // With asChild for custom components
113
+ * function CustomFormLoadingAsChild() {
114
+ * return (
115
+ * <Form.Loading asChild>
116
+ * <div className="custom-loading-container">
117
+ * <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary"></div>
118
+ * <span className="ml-2 text-foreground font-paragraph">Loading form...</span>
119
+ * </div>
120
+ * </Form.Loading>
121
+ * );
122
+ * }
123
+ * ```
124
+ */
125
+ export const Loading = React.forwardRef((props, ref) => {
126
+ const { asChild, children, className, ...otherProps } = props;
127
+ return (_jsx(CoreForm.Loading, { children: ({ isLoading }) => {
128
+ if (!isLoading)
129
+ return null;
130
+ return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": "form-loading", customElement: children, content: "Loading form...", ...otherProps, children: _jsx("div", { children: "Loading form..." }) }));
131
+ } }));
132
+ });
133
+ /**
134
+ * Component that renders content when there's an error loading the form.
135
+ * Only displays its children when an error has occurred.
136
+ *
137
+ * @component
138
+ * @param {LoadingErrorProps} props - The component props
139
+ * @param {boolean} [props.asChild] - Whether to render as a child component
140
+ * @param {React.ReactNode} [props.children] - Content to display during error state
141
+ * @param {string} [props.className] - CSS classes to apply to the default element
142
+ * @example
143
+ * ```tsx
144
+ * import { Form } from '@wix/headless-forms/react';
145
+ *
146
+ * // Default usage with className
147
+ * function FormLoadingError() {
148
+ * return (
149
+ * <Form.LoadingError className="text-destructive px-4 py-3 rounded mb-4" />
150
+ * );
151
+ * }
152
+ *
153
+ * // Custom content
154
+ * function CustomLoadingError() {
155
+ * return (
156
+ * <Form.LoadingError>
157
+ * <div className="bg-destructive/10 border border-destructive text-destructive px-4 py-3 rounded mb-4">
158
+ * <h3 className="font-heading text-lg">Error loading form</h3>
159
+ * <p className="font-paragraph">Something went wrong. Please try again.</p>
160
+ * </div>
161
+ * </Form.LoadingError>
162
+ * );
163
+ * }
164
+ *
165
+ * // With asChild for custom components
166
+ * function CustomLoadingErrorAsChild() {
167
+ * return (
168
+ * <Form.LoadingError asChild>
169
+ * {React.forwardRef<HTMLDivElement, { error: string | null; hasError: boolean }>(
170
+ * ({ error }, ref) => (
171
+ * <div ref={ref} className="custom-error-container">
172
+ * <h3 className="font-heading">Error Loading Form</h3>
173
+ * <p className="font-paragraph">{error}</p>
174
+ * </div>
175
+ * )
176
+ * )}
177
+ * </Form.LoadingError>
178
+ * );
179
+ * }
180
+ * ```
181
+ */
182
+ export const LoadingError = React.forwardRef((props, ref) => {
183
+ const { asChild, children, className, ...otherProps } = props;
184
+ return (_jsx(CoreForm.LoadingError, { children: ({ error, hasError }) => {
185
+ if (!hasError)
186
+ return null;
187
+ const errorData = { error, hasError };
188
+ return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.formLoadingError, customElement: children, customElementProps: errorData, content: error, ...otherProps, children: _jsx("div", { children: error }) }));
189
+ } }));
190
+ });
191
+ /**
192
+ * Component that renders content when there's an error during form submission.
193
+ * Only displays its children when a submission error has occurred.
194
+ *
195
+ * @component
196
+ * @param {ErrorProps} props - The component props
197
+ * @param {boolean} [props.asChild] - Whether to render as a child component
198
+ * @param {React.ReactNode} [props.children] - Content to display during submit error state
199
+ * @param {string} [props.className] - CSS classes to apply to the default element
200
+ * @example
201
+ * ```tsx
202
+ * import { Form } from '@wix/headless-forms/react';
203
+ *
204
+ * // Default usage with className
205
+ * function FormError() {
206
+ * return <Form.Error className="text-destructive p-4 rounded-lg mb-4" />;
207
+ * }
208
+ *
209
+ * // Custom content
210
+ * function CustomFormError() {
211
+ * return (
212
+ * <Form.Error>
213
+ * <div className="bg-destructive/10 border border-destructive text-destructive p-4 rounded-lg mb-4">
214
+ * <h3 className="font-heading text-lg">Submission Failed</h3>
215
+ * <p className="font-paragraph">Please check your input and try again.</p>
216
+ * </div>
217
+ * </Form.Error>
218
+ * );
219
+ * }
220
+ *
221
+ * // With asChild for custom components
222
+ * function CustomFormErrorAsChild() {
223
+ * return (
224
+ * <Form.Error asChild>
225
+ * {React.forwardRef<HTMLDivElement, { error: string | null; hasError: boolean }>(
226
+ * ({ error }, ref) => (
227
+ * <div ref={ref} className="custom-error-container">
228
+ * <h3 className="font-heading">Submission Failed</h3>
229
+ * <p className="font-paragraph">{error}</p>
230
+ * </div>
231
+ * )
232
+ * )}
233
+ * </Form.Error>
234
+ * );
235
+ * }
236
+ * ```
237
+ */
238
+ export const Error = React.forwardRef((props, ref) => {
239
+ const { asChild, children, className, ...otherProps } = props;
240
+ return (_jsx(CoreForm.Error, { children: ({ error, hasError }) => {
241
+ if (!hasError)
242
+ return null;
243
+ const errorData = { error, hasError };
244
+ return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.formError, customElement: children, customElementProps: errorData, content: error, ...otherProps, children: _jsx("div", { className: "text-destructive text-sm sm:text-base", children: error }) }));
245
+ } }));
246
+ });
247
+ /**
248
+ * Component that renders content after successful form submission.
249
+ * Only displays its children when the form has been successfully submitted.
250
+ *
251
+ * @component
252
+ * @param {SubmittedProps} props - The component props
253
+ * @param {boolean} [props.asChild] - Whether to render as a child component
254
+ * @param {React.ReactNode} [props.children] - Content to display after successful submission
255
+ * @param {string} [props.className] - CSS classes to apply to the default element
256
+ * @example
257
+ * ```tsx
258
+ * import { Form } from '@wix/headless-forms/react';
259
+ *
260
+ * // Default usage with className
261
+ * function FormSubmitted() {
262
+ * return <Form.Submitted className="text-green-500 p-4 rounded-lg mb-4" />;
263
+ * }
264
+ *
265
+ * // Custom content
266
+ * function CustomFormSubmitted() {
267
+ * return (
268
+ * <Form.Submitted>
269
+ * <div className="bg-green-50 border border-green-200 text-green-800 p-6 rounded-lg mb-4">
270
+ * <h2 className="font-heading text-xl mb-2">Thank You!</h2>
271
+ * <p className="font-paragraph">Your form has been submitted successfully.</p>
272
+ * </div>
273
+ * </Form.Submitted>
274
+ * );
275
+ * }
276
+ *
277
+ * // With asChild for custom components
278
+ * function CustomFormSubmittedAsChild() {
279
+ * return (
280
+ * <Form.Submitted asChild>
281
+ * {React.forwardRef<HTMLDivElement, { isSubmitted: boolean; message: string }>(
282
+ * ({ message }, ref) => (
283
+ * <div ref={ref} className="custom-success-container">
284
+ * <h2 className="font-heading">Thank You!</h2>
285
+ * <p className="font-paragraph">{message}</p>
286
+ * </div>
287
+ * )
288
+ * )}
289
+ * </Form.Submitted>
290
+ * );
291
+ * }
292
+ * ```
293
+ */
294
+ export const Submitted = React.forwardRef((props, ref) => {
295
+ const { asChild, children, className, ...otherProps } = props;
296
+ return (_jsx(CoreForm.Submitted, { children: ({ isSubmitted, message }) => {
297
+ if (!isSubmitted)
298
+ return null;
299
+ const submittedData = { isSubmitted, message };
300
+ return (_jsx(AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.formSubmitted, customElement: children, customElementProps: submittedData, content: message, ...otherProps, children: _jsx("div", { className: "text-green-500 text-sm sm:text-base", children: message }) }));
301
+ } }));
302
+ });
303
+ /**
304
+ * Fields component for rendering a form with custom field renderers.
305
+ * This component handles the rendering of form fields based on the provided fieldMap.
306
+ * Must be used within Form.Root to access form context.
307
+ *
308
+ * @component
309
+ * @param {FieldsProps} props - Component props
310
+ * @param {FieldMap} props.fieldMap - A mapping of field types to their corresponding React components
311
+ * @example
312
+ * ```tsx
313
+ * import { Form } from '@wix/headless-forms/react';
314
+ * import { TextInput, TextArea, Checkbox } from './field-components';
315
+ *
316
+ * const FIELD_MAP = {
317
+ * TEXT_INPUT: TextInput,
318
+ * TEXT_AREA: TextArea,
319
+ * CHECKBOX: Checkbox,
320
+ * NUMBER_INPUT: NumberInput,
321
+ * // ... remaining field components
322
+ * };
323
+ *
324
+ * function ContactForm({ formServiceConfig }) {
325
+ * return (
326
+ * <Form.Root formServiceConfig={formServiceConfig}>
327
+ * <Form.Loading className="flex justify-center p-4" />
328
+ * <Form.LoadingError className="text-destructive px-4 py-3 rounded mb-4" />
329
+ * <Form.Fields fieldMap={FIELD_MAP} />
330
+ * </Form.Root>
331
+ * );
332
+ * }
333
+ * ```
334
+ */
335
+ /**
336
+ * Fields component for rendering a form with custom field renderers.
337
+ * It maps each field type from the form configuration to its corresponding React component
338
+ * and renders them in the order and layout defined by the form structure.
339
+ *
340
+ * The component automatically handles:
341
+ * - Field validation and error display
342
+ * - Form state management
343
+ * - Field value updates
344
+ *
345
+ * Must be used within Form.Root to access form context.
346
+ *
347
+ * @component
348
+ * @param {FieldsProps} props - The component props
349
+ * @param {FieldMap} props.fieldMap - A mapping of field types to their corresponding React components. Each key represents a field type (e.g., 'TEXT_INPUT', 'CHECKBOX') and the value is the React component that should render that field type.
350
+ *
351
+ * @example
352
+ * ```tsx
353
+ * import { Form } from '@wix/headless-forms/react';
354
+ * import { loadFormServiceConfig } from '@wix/headless-forms/services';
355
+ * import {
356
+ * TextInput,
357
+ * TextArea,
358
+ * PhoneInput,
359
+ * MultilineAddress,
360
+ * DateInput,
361
+ * DatePicker,
362
+ * DateTimeInput,
363
+ * FileUpload,
364
+ * NumberInput,
365
+ * Checkbox,
366
+ * Signature,
367
+ * RatingInput,
368
+ * RadioGroup,
369
+ * CheckboxGroup,
370
+ * Dropdown,
371
+ * Tags,
372
+ * TimeInput,
373
+ * RichText,
374
+ * SubmitButton,
375
+ * ProductList,
376
+ * FixedPayment,
377
+ * PaymentInput,
378
+ * Donation,
379
+ * Appointment,
380
+ * ImageChoice
381
+ * } from './components';
382
+ *
383
+ * // Define your field mapping - this tells the Fields component which React component to use for each field type
384
+ * const FIELD_MAP = {
385
+ * TEXT_INPUT: TextInput,
386
+ * TEXT_AREA: TextArea,
387
+ * PHONE_INPUT: PhoneInput,
388
+ * MULTILINE_ADDRESS: MultilineAddress,
389
+ * DATE_INPUT: DateInput,
390
+ * DATE_PICKER: DatePicker,
391
+ * DATE_TIME_INPUT: DateTimeInput,
392
+ * FILE_UPLOAD: FileUpload,
393
+ * NUMBER_INPUT: NumberInput,
394
+ * CHECKBOX: Checkbox,
395
+ * SIGNATURE: Signature,
396
+ * RATING_INPUT: RatingInput,
397
+ * RADIO_GROUP: RadioGroup,
398
+ * CHECKBOX_GROUP: CheckboxGroup,
399
+ * DROPDOWN: Dropdown,
400
+ * TAGS: Tags,
401
+ * TIME_INPUT: TimeInput,
402
+ * TEXT: RichText,
403
+ * SUBMIT_BUTTON: SubmitButton,
404
+ * PRODUCT_LIST: ProductList,
405
+ * FIXED_PAYMENT: FixedPayment,
406
+ * PAYMENT_INPUT: PaymentInput,
407
+ * DONATION: Donation,
408
+ * APPOINTMENT: Appointment,
409
+ * IMAGE_CHOICE: ImageChoice,
410
+ * };
411
+ *
412
+ * function ContactForm({ formServiceConfig }) {
413
+ * return (
414
+ * <Form.Root formServiceConfig={formServiceConfig}>
415
+ * <Form.Loading className="flex justify-center p-4" />
416
+ * <Form.LoadingError className="text-destructive px-4 py-3 rounded mb-4" />
417
+ * <Form.Fields fieldMap={FIELD_MAP} />
418
+ * <Form.Error className="text-destructive p-4 rounded-lg mb-4" />
419
+ * <Form.Submitted className="text-green-500 p-4 rounded-lg mb-4" />
420
+ * </Form.Root>
421
+ * );
422
+ * }
423
+ * ```
424
+ *
425
+ * @example
426
+ * ```tsx
427
+ * // Advanced usage with custom field components
428
+ * const CustomTextField = ({ value, onChange, label, error, ...props }) => (
429
+ * <div className="form-field">
430
+ * <label className="text-foreground font-paragraph">{label}</label>
431
+ * <input
432
+ * value={value || ''}
433
+ * onChange={(e) => onChange(e.target.value)}
434
+ * className="bg-background border-foreground text-foreground"
435
+ * {...props}
436
+ * />
437
+ * {error && <span className="text-destructive">{error}</span>}
438
+ * </div>
439
+ * );
440
+ *
441
+ * const FIELD_MAP = {
442
+ * TEXT_INPUT: CustomTextField,
443
+ * // ... other field components
444
+ * };
445
+ * ```
446
+ */
447
+ export const Fields = React.forwardRef(({ fieldMap }) => {
448
+ // TODO: render real viewer
449
+ return _jsx(MockViewer, { fieldMap: fieldMap });
450
+ });
451
+ const MockViewer = ({ fieldMap }) => {
452
+ // This is how fieldMap is expected to be used in the viewer
453
+ const schemaFields = {
454
+ // CONTACTS_FIELD_TYPES
455
+ CONTACTS_COMPANY: fieldMap.TEXT_INPUT,
456
+ CONTACTS_POSITION: fieldMap.TEXT_INPUT,
457
+ CONTACTS_TAX_ID: fieldMap.TEXT_INPUT,
458
+ CONTACTS_FIRST_NAME: fieldMap.TEXT_INPUT,
459
+ CONTACTS_LAST_NAME: fieldMap.TEXT_INPUT,
460
+ CONTACTS_EMAIL: fieldMap.TEXT_INPUT,
461
+ CONTACTS_BIRTHDATE: fieldMap.DATE_INPUT,
462
+ CONTACTS_PHONE: fieldMap.PHONE_INPUT,
463
+ CONTACTS_ADDRESS: fieldMap.TEXT_INPUT,
464
+ CONTACTS_SUBSCRIBE: fieldMap.CHECKBOX,
465
+ // QUIZ_FIELD_TYPES
466
+ QUIZ_MULTI_CHOICE: fieldMap.CHECKBOX_GROUP,
467
+ QUIZ_SINGLE_CHOICE: fieldMap.RADIO_GROUP,
468
+ QUIZ_SHORT_TEXT: fieldMap.TEXT_INPUT,
469
+ QUIZ_LONG_TEXT: fieldMap.TEXT_AREA,
470
+ QUIZ_NUMBER: fieldMap.NUMBER_INPUT,
471
+ QUIZ_FILE_UPLOAD: fieldMap.FILE_UPLOAD,
472
+ QUIZ_IMAGE_CHOICE: fieldMap.IMAGE_CHOICE, // TODO: add
473
+ // DEXT_FIELD_TYPES
474
+ DEXT_TEXT_INPUT: fieldMap.TEXT_INPUT,
475
+ DEXT_TEXT_AREA: fieldMap.TEXT_AREA,
476
+ DEXT_DROPDOWN: fieldMap.DROPDOWN,
477
+ DEXT_URL_INPUT: fieldMap.TEXT_INPUT,
478
+ DEXT_RADIO_GROUP: fieldMap.RADIO_GROUP,
479
+ DEXT_NUMBER_INPUT: fieldMap.NUMBER_INPUT,
480
+ DEXT_CHECKBOX: fieldMap.CHECKBOX,
481
+ DEXT_CHECKBOX_GROUP: fieldMap.CHECKBOX_GROUP,
482
+ DEXT_EMAIL: fieldMap.TEXT_INPUT,
483
+ DEXT_PHONE: fieldMap.PHONE_INPUT,
484
+ DEXT_RATING_INPUT: fieldMap.RATING_INPUT,
485
+ DEXT_DATE_PICKER: fieldMap.DATE_PICKER,
486
+ DEXT_TAGS: fieldMap.TAGS,
487
+ // SCHEDULING_FIELD_TYPES
488
+ APPOINTMENT: fieldMap.APPOINTMENT,
489
+ SERVICES_DROPDOWN: fieldMap.DROPDOWN,
490
+ // ECOM_FIELD_TYPES
491
+ ECOM_ADDITIONAL_INFO: fieldMap.TEXT_AREA,
492
+ ECOM_ADDRESS: fieldMap.TEXT_INPUT,
493
+ ECOM_FULL_NAME: fieldMap.TEXT_INPUT,
494
+ ECOM_PHONE: fieldMap.PHONE_INPUT,
495
+ ECOM_COMPANY_NAME: fieldMap.TEXT_INPUT,
496
+ ECOM_EMAIL: fieldMap.TEXT_INPUT,
497
+ ECOM_SUBSCRIPTION: fieldMap.CHECKBOX,
498
+ // BOOKINGS_FIELD_TYPES
499
+ BOOKINGS_FIRST_NAME: fieldMap.TEXT_INPUT,
500
+ BOOKINGS_LAST_NAME: fieldMap.TEXT_INPUT,
501
+ BOOKINGS_EMAIL: fieldMap.TEXT_INPUT,
502
+ BOOKINGS_PHONE: fieldMap.PHONE_INPUT,
503
+ BOOKINGS_ADDRESS: fieldMap.TEXT_INPUT,
504
+ // PAYMENTS_FIELD_TYPES
505
+ PRODUCT_LIST: fieldMap.PRODUCT_LIST,
506
+ DONATION: fieldMap.DONATION,
507
+ PAYMENT_INPUT: fieldMap.PAYMENT_INPUT, // could be TEXT_INPUT?
508
+ FIXED_PAYMENT: fieldMap.FIXED_PAYMENT, // could be TAGS?
509
+ // COMMON_FIELD_TYPES
510
+ TEXT_INPUT: fieldMap.TEXT_INPUT,
511
+ NUMBER_INPUT: fieldMap.NUMBER_INPUT,
512
+ URL_INPUT: fieldMap.TEXT_INPUT,
513
+ TEXT_AREA: fieldMap.TEXT_AREA,
514
+ DATE_INPUT: fieldMap.DATE_INPUT,
515
+ DATE_TIME_INPUT: fieldMap.DATE_TIME_INPUT,
516
+ TIME_INPUT: fieldMap.TIME_INPUT,
517
+ RADIO_GROUP: fieldMap.RADIO_GROUP,
518
+ CHECKBOX_GROUP: fieldMap.CHECKBOX_GROUP,
519
+ FILE_UPLOAD: fieldMap.FILE_UPLOAD,
520
+ CHECKBOX: fieldMap.CHECKBOX,
521
+ DROPDOWN: fieldMap.DROPDOWN,
522
+ // NESTED_FORM: 'NESTED_FORM',
523
+ MULTILINE_ADDRESS: fieldMap.MULTILINE_ADDRESS,
524
+ // are these relevant for headless?
525
+ MLA_COUNTRY: fieldMap.DROPDOWN,
526
+ MLA_CITY: fieldMap.TEXT_INPUT,
527
+ MLA_ADDRESS_LINE: fieldMap.TEXT_INPUT, // dropdown if autocomplete disabled?
528
+ MLA_ADDRESS_LINE_2: fieldMap.TEXT_INPUT,
529
+ MLA_POSTAL_CODE: fieldMap.TEXT_INPUT,
530
+ MLA_SUBDIVISION: fieldMap.DROPDOWN,
531
+ MLA_STREET_NAME: fieldMap.TEXT_INPUT,
532
+ MLA_STREET_NUMBER: fieldMap.TEXT_INPUT,
533
+ MLA_APARTMENT: fieldMap.TEXT_INPUT,
534
+ FULL_NAME_FIRST_NAME: fieldMap.TEXT_INPUT,
535
+ FULL_NAME_LAST_NAME: fieldMap.TEXT_INPUT,
536
+ FULL_NAME: fieldMap.TEXT_INPUT,
537
+ VAT_ID: fieldMap.TEXT_INPUT,
538
+ SIGNATURE: fieldMap.SIGNATURE,
539
+ RATING_INPUT: fieldMap.RATING_INPUT,
540
+ TAGS: fieldMap.TAGS,
541
+ DATE_PICKER: fieldMap.DATE_PICKER,
542
+ // READONLY_FIELD_TYPES
543
+ HEADER: fieldMap.TEXT,
544
+ RICH_TEXT: fieldMap.TEXT,
545
+ SUBMIT_BUTTON: fieldMap.SUBMIT_BUTTON,
546
+ };
547
+ return (_jsxs(_Fragment, { children: [_jsx("div", { children: "Form Fields" }), _jsx("div", { children: JSON.stringify(schemaFields) })] }));
548
+ };
549
+ /**
550
+ * Main Form namespace containing all form components following the compound component pattern.
551
+ * Provides a headless, flexible way to render and manage forms with custom field components.
552
+ *
553
+ * @namespace Form
554
+ * @property {typeof Root} Root - Form root component that provides service context to all child components
555
+ * @property {typeof Loading} Loading - Form loading state component that displays content during form loading
556
+ * @property {typeof LoadingError} LoadingError - Form loading error state component for handling form loading errors
557
+ * @property {typeof Error} Error - Form submit error state component for handling form submission errors
558
+ * @property {typeof Submitted} Submitted - Form submitted state component for displaying success messages
559
+ * @property {typeof Fields} Fields - Form fields component for rendering form fields with custom field renderers
560
+ * @example
561
+ * ```tsx
562
+ * import { Form } from '@wix/headless-forms/react';
563
+ * import { loadFormServiceConfig } from '@wix/headless-forms/services';
564
+ * import { TextInput, TextArea, Checkbox } from './field-components';
565
+ *
566
+ * const FIELD_MAP = {
567
+ * TEXT_INPUT: TextInput,
568
+ * TEXT_AREA: TextArea,
569
+ * CHECKBOX: Checkbox,
570
+ * // ... other field components
571
+ * };
572
+ *
573
+ * // Pattern 1: Pre-loaded form data (SSR/SSG)
574
+ * function MyForm({ formServiceConfig }) {
575
+ * return (
576
+ * <Form.Root formServiceConfig={formServiceConfig}>
577
+ * <Form.Loading className="flex justify-center p-4" />
578
+ * <Form.LoadingError className="text-destructive px-4 py-3 rounded mb-4" />
579
+ * <Form.Fields fieldMap={FIELD_MAP} />
580
+ * <Form.Error className="text-destructive p-4 rounded-lg mb-4" />
581
+ * <Form.Submitted className="text-green-500 p-4 rounded-lg mb-4" />
582
+ * </Form.Root>
583
+ * );
584
+ * }
585
+ *
586
+ * // Pattern 2: Lazy loading with formId (Client-side)
587
+ * function DynamicForm({ formId }) {
588
+ * return (
589
+ * <Form.Root formServiceConfig={{ formId }}>
590
+ * <Form.Loading className="flex justify-center p-4" />
591
+ * <Form.LoadingError className="text-destructive px-4 py-3 rounded mb-4" />
592
+ * <Form.Fields fieldMap={FIELD_MAP} />
593
+ * <Form.Error className="text-destructive p-4 rounded-lg mb-4" />
594
+ * <Form.Submitted className="text-green-500 p-4 rounded-lg mb-4" />
595
+ * </Form.Root>
596
+ * );
597
+ * }
598
+ * ```
599
+ */
600
+ export const Form = {
601
+ /** Form root component that provides service context */
602
+ Root,
603
+ /** Form loading state component */
604
+ Loading,
605
+ /** Form loading error state component */
606
+ LoadingError,
607
+ /** Form error state component */
608
+ Error,
609
+ /** Form submitted state component */
610
+ Submitted,
611
+ /** Form fields component for rendering form fields */
612
+ Fields,
613
+ };