@wix/headless-forms 0.0.1 → 0.0.3

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/README.md ADDED
@@ -0,0 +1,46 @@
1
+ # @wix/headless-forms
2
+
3
+ Headless React components for rendering and managing forms. It follows the compound component pattern and integrates with Wix Forms services.
4
+
5
+ `@wix/headless-forms/react` and `@wix/headless-forms/services` are exported through forms public SDK `@wix/forms`.
6
+
7
+ ## Development Guide
8
+
9
+ 1. **Install Dependencies**
10
+ ```bash
11
+ yarn install
12
+ ```
13
+
14
+ 2. **Start Development**
15
+ ```bash
16
+ # Build in watch mode
17
+ yarn build:watch
18
+ ```
19
+
20
+ 3. **Test Changes Locally**
21
+ Run `examples/astro-forms-demo` to test changes locally.
22
+
23
+ ## Documentation
24
+
25
+ All changes should be documented using `jsdoc` and updating `docs/api/FORM_INTERFACE.md`.
26
+
27
+ ## Publishing
28
+
29
+ 1. **Update Version**
30
+ - Update version in `package.json`
31
+ - Create PR and merge to main branch
32
+
33
+ 2. **Publish to NPM**
34
+ - Go to GitHub Actions
35
+ - Run "Publish Package" workflow
36
+ - Enter package name: `forms`
37
+ - Monitor the workflow for successful completion
38
+
39
+ 3. **Update SDK Exports**
40
+ - Go to Form app in Wix Dev Center
41
+ - Update SDK exports extensions:
42
+ - "Forms SDK Exports Components"
43
+ - "Forms SDK Exports Services"
44
+ - Release new app version
45
+ - Check if update has been commited to `auto-sdk-packages` repo
46
+
@@ -22,6 +22,7 @@ export interface RootProps {
22
22
  * @param {RootProps} props - The component props
23
23
  * @param {React.ReactNode} props.children - Child components that will have access to form context
24
24
  * @param {FormServiceConfig} props.formServiceConfig - Form service configuration object
25
+ * @param {boolean} [props.asChild] - Whether to render as a child component
25
26
  * @param {string} [props.className] - CSS classes to apply to the root element
26
27
  * @example
27
28
  * ```tsx
@@ -368,7 +369,7 @@ export declare const Submitted: React.ForwardRefExoticComponent<SubmittedProps &
368
369
  * };
369
370
  * ```
370
371
  */
371
- interface FieldMap {
372
+ export interface FieldMap {
372
373
  TEXT_INPUT: React.ComponentType<TextInputProps>;
373
374
  TEXT_AREA: React.ComponentType<TextAreaProps>;
374
375
  PHONE_INPUT: React.ComponentType<PhoneInputProps>;
@@ -416,7 +417,7 @@ interface FieldMap {
416
417
  * <Form.Fields fieldMap={FIELD_MAP} />
417
418
  * ```
418
419
  */
419
- export interface FieldsProps {
420
+ interface FieldsProps {
420
421
  fieldMap: FieldMap;
421
422
  }
422
423
  /**
@@ -563,70 +564,5 @@ export interface FieldsProps {
563
564
  * };
564
565
  * ```
565
566
  */
566
- export declare const Fields: React.ForwardRefExoticComponent<FieldsProps & React.RefAttributes<HTMLElement>>;
567
- /**
568
- * Main Form namespace containing all form components following the compound component pattern.
569
- * Provides a headless, flexible way to render and manage forms with custom field components.
570
- *
571
- * @namespace Form
572
- * @property {typeof Root} Root - Form root component that provides service context to all child components
573
- * @property {typeof Loading} Loading - Form loading state component that displays content during form loading
574
- * @property {typeof LoadingError} LoadingError - Form loading error state component for handling form loading errors
575
- * @property {typeof Error} Error - Form submit error state component for handling form submission errors
576
- * @property {typeof Submitted} Submitted - Form submitted state component for displaying success messages
577
- * @property {typeof Fields} Fields - Form fields component for rendering form fields with custom field renderers
578
- * @example
579
- * ```tsx
580
- * import { Form } from '@wix/headless-forms/react';
581
- * import { loadFormServiceConfig } from '@wix/headless-forms/services';
582
- * import { TextInput, TextArea, Checkbox } from './field-components';
583
- *
584
- * const FIELD_MAP = {
585
- * TEXT_INPUT: TextInput,
586
- * TEXT_AREA: TextArea,
587
- * CHECKBOX: Checkbox,
588
- * // ... other field components
589
- * };
590
- *
591
- * // Pattern 1: Pre-loaded form data (SSR/SSG)
592
- * function MyForm({ formServiceConfig }) {
593
- * return (
594
- * <Form.Root formServiceConfig={formServiceConfig}>
595
- * <Form.Loading className="flex justify-center p-4" />
596
- * <Form.LoadingError className="text-destructive px-4 py-3 rounded mb-4" />
597
- * <Form.Fields fieldMap={FIELD_MAP} />
598
- * <Form.Error className="text-destructive p-4 rounded-lg mb-4" />
599
- * <Form.Submitted className="text-green-500 p-4 rounded-lg mb-4" />
600
- * </Form.Root>
601
- * );
602
- * }
603
- *
604
- * // Pattern 2: Lazy loading with formId (Client-side)
605
- * function DynamicForm({ formId }) {
606
- * return (
607
- * <Form.Root formServiceConfig={{ formId }}>
608
- * <Form.Loading className="flex justify-center p-4" />
609
- * <Form.LoadingError className="text-destructive px-4 py-3 rounded mb-4" />
610
- * <Form.Fields fieldMap={FIELD_MAP} />
611
- * <Form.Error className="text-destructive p-4 rounded-lg mb-4" />
612
- * <Form.Submitted className="text-green-500 p-4 rounded-lg mb-4" />
613
- * </Form.Root>
614
- * );
615
- * }
616
- * ```
617
- */
618
- export declare const Form: {
619
- /** Form root component that provides service context */
620
- readonly Root: React.ForwardRefExoticComponent<RootProps & React.RefAttributes<HTMLDivElement>>;
621
- /** Form loading state component */
622
- readonly Loading: React.ForwardRefExoticComponent<LoadingProps & React.RefAttributes<HTMLElement>>;
623
- /** Form loading error state component */
624
- readonly LoadingError: React.ForwardRefExoticComponent<LoadingErrorProps & React.RefAttributes<HTMLElement>>;
625
- /** Form error state component */
626
- readonly Error: React.ForwardRefExoticComponent<ErrorProps & React.RefAttributes<HTMLElement>>;
627
- /** Form submitted state component */
628
- readonly Submitted: React.ForwardRefExoticComponent<SubmittedProps & React.RefAttributes<HTMLElement>>;
629
- /** Form fields component for rendering form fields */
630
- readonly Fields: React.ForwardRefExoticComponent<FieldsProps & React.RefAttributes<HTMLElement>>;
631
- };
567
+ export declare const Fields: React.ForwardRefExoticComponent<FieldsProps & React.RefAttributes<HTMLDivElement>>;
632
568
  export {};
@@ -32,18 +32,18 @@ var __importStar = (this && this.__importStar) || (function () {
32
32
  return result;
33
33
  };
34
34
  })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
35
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.Form = exports.Fields = exports.Submitted = exports.Error = exports.LoadingError = exports.Loading = exports.Root = void 0;
36
+ exports.Fields = exports.Submitted = exports.Error = exports.LoadingError = exports.Loading = exports.Root = void 0;
40
37
  const jsx_runtime_1 = require("react/jsx-runtime");
41
- const react_1 = __importDefault(require("react"));
38
+ const react_1 = __importStar(require("react"));
42
39
  const react_2 = require("@wix/headless-utils/react");
43
- const CoreForm = __importStar(require("./core/Form.js"));
40
+ const form_public_1 = require("@wix/form-public");
41
+ const Form_1 = require("./core/Form");
44
42
  var TestIds;
45
43
  (function (TestIds) {
46
44
  TestIds["formRoot"] = "form-root";
45
+ TestIds["form"] = "form";
46
+ TestIds["formLoading"] = "form-loading";
47
47
  TestIds["formLoadingError"] = "form-loading-error";
48
48
  TestIds["formError"] = "form-error";
49
49
  TestIds["formSubmitted"] = "form-submitted";
@@ -57,6 +57,7 @@ var TestIds;
57
57
  * @param {RootProps} props - The component props
58
58
  * @param {React.ReactNode} props.children - Child components that will have access to form context
59
59
  * @param {FormServiceConfig} props.formServiceConfig - Form service configuration object
60
+ * @param {boolean} [props.asChild] - Whether to render as a child component
60
61
  * @param {string} [props.className] - CSS classes to apply to the root element
61
62
  * @example
62
63
  * ```tsx
@@ -99,7 +100,7 @@ var TestIds;
99
100
  */
100
101
  exports.Root = react_1.default.forwardRef((props, ref) => {
101
102
  const { children, formServiceConfig, asChild, ...otherProps } = props;
102
- return ((0, jsx_runtime_1.jsx)(CoreForm.Root, { formServiceConfig: formServiceConfig, children: (0, jsx_runtime_1.jsx)(RootContent, { asChild: asChild, ref: ref, ...otherProps, children: children }) }));
103
+ return ((0, jsx_runtime_1.jsx)(Form_1.Root, { formServiceConfig: formServiceConfig, children: (0, jsx_runtime_1.jsx)(RootContent, { asChild: asChild, ref: ref, ...otherProps, children: children }) }));
103
104
  });
104
105
  /**
105
106
  * Internal component to handle the Root content with service access.
@@ -114,7 +115,7 @@ exports.Root = react_1.default.forwardRef((props, ref) => {
114
115
  */
115
116
  const RootContent = react_1.default.forwardRef((props, ref) => {
116
117
  const { asChild, children, className, ...otherProps } = props;
117
- return ((0, jsx_runtime_1.jsx)(react_2.AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.formRoot, customElement: children, customElementProps: {}, ...otherProps, children: (0, jsx_runtime_1.jsx)("div", { children: react_1.default.isValidElement(children) ? children : null }) }));
118
+ return ((0, jsx_runtime_1.jsx)(react_2.AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": TestIds.formRoot, customElement: children, customElementProps: {}, ...otherProps, children: (0, jsx_runtime_1.jsx)("div", { children: children }) }));
118
119
  });
119
120
  /**
120
121
  * Component that renders content during loading state.
@@ -163,10 +164,10 @@ const RootContent = react_1.default.forwardRef((props, ref) => {
163
164
  */
164
165
  exports.Loading = react_1.default.forwardRef((props, ref) => {
165
166
  const { asChild, children, className, ...otherProps } = props;
166
- return ((0, jsx_runtime_1.jsx)(CoreForm.Loading, { children: ({ isLoading }) => {
167
+ return ((0, jsx_runtime_1.jsx)(Form_1.Loading, { children: ({ isLoading }) => {
167
168
  if (!isLoading)
168
169
  return null;
169
- return ((0, jsx_runtime_1.jsx)(react_2.AsChildSlot, { ref: ref, asChild: asChild, className: className, "data-testid": "form-loading", customElement: children, content: "Loading form...", ...otherProps, children: (0, jsx_runtime_1.jsx)("div", { children: "Loading form..." }) }));
170
+ return ((0, jsx_runtime_1.jsx)(react_2.AsChildSlot, { "data-testid": TestIds.formLoading, ref: ref, asChild: asChild, className: className, customElement: children, content: "Loading form...", ...otherProps, children: (0, jsx_runtime_1.jsx)("div", { children: "Loading form..." }) }));
170
171
  } }));
171
172
  });
172
173
  /**
@@ -220,7 +221,7 @@ exports.Loading = react_1.default.forwardRef((props, ref) => {
220
221
  */
221
222
  exports.LoadingError = react_1.default.forwardRef((props, ref) => {
222
223
  const { asChild, children, className, ...otherProps } = props;
223
- return ((0, jsx_runtime_1.jsx)(CoreForm.LoadingError, { children: ({ error, hasError }) => {
224
+ return ((0, jsx_runtime_1.jsx)(Form_1.LoadingError, { children: ({ error, hasError }) => {
224
225
  if (!hasError)
225
226
  return null;
226
227
  const errorData = { error, hasError };
@@ -276,7 +277,7 @@ exports.LoadingError = react_1.default.forwardRef((props, ref) => {
276
277
  */
277
278
  exports.Error = react_1.default.forwardRef((props, ref) => {
278
279
  const { asChild, children, className, ...otherProps } = props;
279
- return ((0, jsx_runtime_1.jsx)(CoreForm.Error, { children: ({ error, hasError }) => {
280
+ return ((0, jsx_runtime_1.jsx)(Form_1.Error, { children: ({ error, hasError }) => {
280
281
  if (!hasError)
281
282
  return null;
282
283
  const errorData = { error, hasError };
@@ -332,7 +333,7 @@ exports.Error = react_1.default.forwardRef((props, ref) => {
332
333
  */
333
334
  exports.Submitted = react_1.default.forwardRef((props, ref) => {
334
335
  const { asChild, children, className, ...otherProps } = props;
335
- return ((0, jsx_runtime_1.jsx)(CoreForm.Submitted, { children: ({ isSubmitted, message }) => {
336
+ return ((0, jsx_runtime_1.jsx)(Form_1.Submitted, { children: ({ isSubmitted, message }) => {
336
337
  if (!isSubmitted)
337
338
  return null;
338
339
  const submittedData = { isSubmitted, message };
@@ -483,170 +484,26 @@ exports.Submitted = react_1.default.forwardRef((props, ref) => {
483
484
  * };
484
485
  * ```
485
486
  */
486
- exports.Fields = react_1.default.forwardRef(({ fieldMap }) => {
487
- // TODO: render real viewer
488
- return (0, jsx_runtime_1.jsx)(MockViewer, { fieldMap: fieldMap });
487
+ exports.Fields = react_1.default.forwardRef((props, ref) => {
488
+ const [formValues, setFormValues] = (0, react_1.useState)({});
489
+ const [formErrors, setFormErrors] = (0, react_1.useState)([]);
490
+ const handleFormChange = (0, react_1.useCallback)((values) => {
491
+ setFormValues(values);
492
+ }, []);
493
+ const handleFormValidate = (0, react_1.useCallback)((errors) => {
494
+ setFormErrors(errors);
495
+ }, []);
496
+ return ((0, jsx_runtime_1.jsx)(Form_1.Fields, { children: ({ form }) => {
497
+ console.log('Fields form', form);
498
+ if (!form)
499
+ return null;
500
+ return ((0, jsx_runtime_1.jsx)("div", { ref: ref, children: (0, jsx_runtime_1.jsx)(form_public_1.Form, { form: {
501
+ ...form,
502
+ id: form?._id,
503
+ fields: form?.formFields?.map((field) => ({
504
+ ...field,
505
+ id: field._id,
506
+ })),
507
+ }, values: formValues, onChange: handleFormChange, errors: formErrors, onValidate: handleFormValidate, fields: props.fieldMap }) }));
508
+ } }));
489
509
  });
490
- const MockViewer = ({ fieldMap }) => {
491
- // This is how fieldMap is expected to be used in the viewer
492
- const schemaFields = {
493
- // CONTACTS_FIELD_TYPES
494
- CONTACTS_COMPANY: fieldMap.TEXT_INPUT,
495
- CONTACTS_POSITION: fieldMap.TEXT_INPUT,
496
- CONTACTS_TAX_ID: fieldMap.TEXT_INPUT,
497
- CONTACTS_FIRST_NAME: fieldMap.TEXT_INPUT,
498
- CONTACTS_LAST_NAME: fieldMap.TEXT_INPUT,
499
- CONTACTS_EMAIL: fieldMap.TEXT_INPUT,
500
- CONTACTS_BIRTHDATE: fieldMap.DATE_INPUT,
501
- CONTACTS_PHONE: fieldMap.PHONE_INPUT,
502
- CONTACTS_ADDRESS: fieldMap.TEXT_INPUT,
503
- CONTACTS_SUBSCRIBE: fieldMap.CHECKBOX,
504
- // QUIZ_FIELD_TYPES
505
- QUIZ_MULTI_CHOICE: fieldMap.CHECKBOX_GROUP,
506
- QUIZ_SINGLE_CHOICE: fieldMap.RADIO_GROUP,
507
- QUIZ_SHORT_TEXT: fieldMap.TEXT_INPUT,
508
- QUIZ_LONG_TEXT: fieldMap.TEXT_AREA,
509
- QUIZ_NUMBER: fieldMap.NUMBER_INPUT,
510
- QUIZ_FILE_UPLOAD: fieldMap.FILE_UPLOAD,
511
- QUIZ_IMAGE_CHOICE: fieldMap.IMAGE_CHOICE, // TODO: add
512
- // DEXT_FIELD_TYPES
513
- DEXT_TEXT_INPUT: fieldMap.TEXT_INPUT,
514
- DEXT_TEXT_AREA: fieldMap.TEXT_AREA,
515
- DEXT_DROPDOWN: fieldMap.DROPDOWN,
516
- DEXT_URL_INPUT: fieldMap.TEXT_INPUT,
517
- DEXT_RADIO_GROUP: fieldMap.RADIO_GROUP,
518
- DEXT_NUMBER_INPUT: fieldMap.NUMBER_INPUT,
519
- DEXT_CHECKBOX: fieldMap.CHECKBOX,
520
- DEXT_CHECKBOX_GROUP: fieldMap.CHECKBOX_GROUP,
521
- DEXT_EMAIL: fieldMap.TEXT_INPUT,
522
- DEXT_PHONE: fieldMap.PHONE_INPUT,
523
- DEXT_RATING_INPUT: fieldMap.RATING_INPUT,
524
- DEXT_DATE_PICKER: fieldMap.DATE_PICKER,
525
- DEXT_TAGS: fieldMap.TAGS,
526
- // SCHEDULING_FIELD_TYPES
527
- APPOINTMENT: fieldMap.APPOINTMENT,
528
- SERVICES_DROPDOWN: fieldMap.DROPDOWN,
529
- // ECOM_FIELD_TYPES
530
- ECOM_ADDITIONAL_INFO: fieldMap.TEXT_AREA,
531
- ECOM_ADDRESS: fieldMap.TEXT_INPUT,
532
- ECOM_FULL_NAME: fieldMap.TEXT_INPUT,
533
- ECOM_PHONE: fieldMap.PHONE_INPUT,
534
- ECOM_COMPANY_NAME: fieldMap.TEXT_INPUT,
535
- ECOM_EMAIL: fieldMap.TEXT_INPUT,
536
- ECOM_SUBSCRIPTION: fieldMap.CHECKBOX,
537
- // BOOKINGS_FIELD_TYPES
538
- BOOKINGS_FIRST_NAME: fieldMap.TEXT_INPUT,
539
- BOOKINGS_LAST_NAME: fieldMap.TEXT_INPUT,
540
- BOOKINGS_EMAIL: fieldMap.TEXT_INPUT,
541
- BOOKINGS_PHONE: fieldMap.PHONE_INPUT,
542
- BOOKINGS_ADDRESS: fieldMap.TEXT_INPUT,
543
- // PAYMENTS_FIELD_TYPES
544
- PRODUCT_LIST: fieldMap.PRODUCT_LIST,
545
- DONATION: fieldMap.DONATION,
546
- PAYMENT_INPUT: fieldMap.PAYMENT_INPUT, // could be TEXT_INPUT?
547
- FIXED_PAYMENT: fieldMap.FIXED_PAYMENT, // could be TAGS?
548
- // COMMON_FIELD_TYPES
549
- TEXT_INPUT: fieldMap.TEXT_INPUT,
550
- NUMBER_INPUT: fieldMap.NUMBER_INPUT,
551
- URL_INPUT: fieldMap.TEXT_INPUT,
552
- TEXT_AREA: fieldMap.TEXT_AREA,
553
- DATE_INPUT: fieldMap.DATE_INPUT,
554
- DATE_TIME_INPUT: fieldMap.DATE_TIME_INPUT,
555
- TIME_INPUT: fieldMap.TIME_INPUT,
556
- RADIO_GROUP: fieldMap.RADIO_GROUP,
557
- CHECKBOX_GROUP: fieldMap.CHECKBOX_GROUP,
558
- FILE_UPLOAD: fieldMap.FILE_UPLOAD,
559
- CHECKBOX: fieldMap.CHECKBOX,
560
- DROPDOWN: fieldMap.DROPDOWN,
561
- // NESTED_FORM: 'NESTED_FORM',
562
- MULTILINE_ADDRESS: fieldMap.MULTILINE_ADDRESS,
563
- // are these relevant for headless?
564
- MLA_COUNTRY: fieldMap.DROPDOWN,
565
- MLA_CITY: fieldMap.TEXT_INPUT,
566
- MLA_ADDRESS_LINE: fieldMap.TEXT_INPUT, // dropdown if autocomplete disabled?
567
- MLA_ADDRESS_LINE_2: fieldMap.TEXT_INPUT,
568
- MLA_POSTAL_CODE: fieldMap.TEXT_INPUT,
569
- MLA_SUBDIVISION: fieldMap.DROPDOWN,
570
- MLA_STREET_NAME: fieldMap.TEXT_INPUT,
571
- MLA_STREET_NUMBER: fieldMap.TEXT_INPUT,
572
- MLA_APARTMENT: fieldMap.TEXT_INPUT,
573
- FULL_NAME_FIRST_NAME: fieldMap.TEXT_INPUT,
574
- FULL_NAME_LAST_NAME: fieldMap.TEXT_INPUT,
575
- FULL_NAME: fieldMap.TEXT_INPUT,
576
- VAT_ID: fieldMap.TEXT_INPUT,
577
- SIGNATURE: fieldMap.SIGNATURE,
578
- RATING_INPUT: fieldMap.RATING_INPUT,
579
- TAGS: fieldMap.TAGS,
580
- DATE_PICKER: fieldMap.DATE_PICKER,
581
- // READONLY_FIELD_TYPES
582
- HEADER: fieldMap.TEXT,
583
- RICH_TEXT: fieldMap.TEXT,
584
- SUBMIT_BUTTON: fieldMap.SUBMIT_BUTTON,
585
- };
586
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { children: "Form Fields" }), (0, jsx_runtime_1.jsx)("div", { children: JSON.stringify(schemaFields) })] }));
587
- };
588
- /**
589
- * Main Form namespace containing all form components following the compound component pattern.
590
- * Provides a headless, flexible way to render and manage forms with custom field components.
591
- *
592
- * @namespace Form
593
- * @property {typeof Root} Root - Form root component that provides service context to all child components
594
- * @property {typeof Loading} Loading - Form loading state component that displays content during form loading
595
- * @property {typeof LoadingError} LoadingError - Form loading error state component for handling form loading errors
596
- * @property {typeof Error} Error - Form submit error state component for handling form submission errors
597
- * @property {typeof Submitted} Submitted - Form submitted state component for displaying success messages
598
- * @property {typeof Fields} Fields - Form fields component for rendering form fields with custom field renderers
599
- * @example
600
- * ```tsx
601
- * import { Form } from '@wix/headless-forms/react';
602
- * import { loadFormServiceConfig } from '@wix/headless-forms/services';
603
- * import { TextInput, TextArea, Checkbox } from './field-components';
604
- *
605
- * const FIELD_MAP = {
606
- * TEXT_INPUT: TextInput,
607
- * TEXT_AREA: TextArea,
608
- * CHECKBOX: Checkbox,
609
- * // ... other field components
610
- * };
611
- *
612
- * // Pattern 1: Pre-loaded form data (SSR/SSG)
613
- * function MyForm({ formServiceConfig }) {
614
- * return (
615
- * <Form.Root formServiceConfig={formServiceConfig}>
616
- * <Form.Loading className="flex justify-center p-4" />
617
- * <Form.LoadingError className="text-destructive px-4 py-3 rounded mb-4" />
618
- * <Form.Fields fieldMap={FIELD_MAP} />
619
- * <Form.Error className="text-destructive p-4 rounded-lg mb-4" />
620
- * <Form.Submitted className="text-green-500 p-4 rounded-lg mb-4" />
621
- * </Form.Root>
622
- * );
623
- * }
624
- *
625
- * // Pattern 2: Lazy loading with formId (Client-side)
626
- * function DynamicForm({ formId }) {
627
- * return (
628
- * <Form.Root formServiceConfig={{ formId }}>
629
- * <Form.Loading className="flex justify-center p-4" />
630
- * <Form.LoadingError className="text-destructive px-4 py-3 rounded mb-4" />
631
- * <Form.Fields fieldMap={FIELD_MAP} />
632
- * <Form.Error className="text-destructive p-4 rounded-lg mb-4" />
633
- * <Form.Submitted className="text-green-500 p-4 rounded-lg mb-4" />
634
- * </Form.Root>
635
- * );
636
- * }
637
- * ```
638
- */
639
- exports.Form = {
640
- /** Form root component that provides service context */
641
- Root: exports.Root,
642
- /** Form loading state component */
643
- Loading: exports.Loading,
644
- /** Form loading error state component */
645
- LoadingError: exports.LoadingError,
646
- /** Form error state component */
647
- Error: exports.Error,
648
- /** Form submitted state component */
649
- Submitted: exports.Submitted,
650
- /** Form fields component for rendering form fields */
651
- Fields: exports.Fields,
652
- };
@@ -1,4 +1,8 @@
1
+ import { forms } from '@wix/forms';
1
2
  import { FormServiceConfig } from '../../services/form-service.js';
3
+ /**
4
+ * Props for Root headless component
5
+ */
2
6
  export interface RootProps {
3
7
  children: React.ReactNode;
4
8
  formServiceConfig: FormServiceConfig;
@@ -9,8 +13,9 @@ export interface RootProps {
9
13
  *
10
14
  * @order 1
11
15
  * @component
12
- * @param {React.ReactNode} children - Child components that will have access to form context
13
- * @param {FormServiceConfig} formServiceConfig - Configuration object containing form data
16
+ * @param {RootProps} props - Component props
17
+ * @param {React.ReactNode} props.children - Child components that will have access to form context
18
+ * @param {FormServiceConfig} props.formServiceConfig - Configuration object containing form data
14
19
  * @example
15
20
  * ```tsx
16
21
  * import { Form } from '@wix/headless-forms/react';
@@ -47,7 +52,7 @@ export interface RootProps {
47
52
  * }
48
53
  * ```
49
54
  */
50
- export declare function Root(props: RootProps): React.ReactNode;
55
+ export declare function Root({ formServiceConfig, children, }: RootProps): React.ReactNode;
51
56
  /**
52
57
  * Props for FormLoading headless component
53
58
  */
@@ -213,3 +218,44 @@ export interface FormSubmittedRenderProps {
213
218
  * ```
214
219
  */
215
220
  export declare function Submitted(props: FormSubmittedProps): import("react").ReactNode;
221
+ /**
222
+ * Render props for Fields component
223
+ */
224
+ interface FieldsRenderProps {
225
+ form: forms.Form | null;
226
+ }
227
+ /**
228
+ * Props for Fields headless component
229
+ */
230
+ interface FieldsProps {
231
+ children: (props: FieldsRenderProps) => React.ReactNode;
232
+ }
233
+ /**
234
+ * Fields component that provides form data to its children.
235
+ * This component accesses the form data from the service and passes it to children via render props.
236
+ *
237
+ * @component
238
+ * @param {FieldsProps} props - Component props
239
+ * @param {FieldsProps['children']} props.children - Render prop function that receives form data
240
+ * @example
241
+ * ```tsx
242
+ * import { Form } from '@wix/headless-forms/react';
243
+ *
244
+ * function FormFields() {
245
+ * return (
246
+ * <Form.Fields>
247
+ * {({ form }) => (
248
+ * form ? (
249
+ * <div>
250
+ * <h2>{form.name}</h2>
251
+ * <p>{form.description}</p>
252
+ * </div>
253
+ * ) : null
254
+ * )}
255
+ * </Form.Fields>
256
+ * );
257
+ * }
258
+ * ```
259
+ */
260
+ export declare function Fields(props: FieldsProps): import("react").ReactNode;
261
+ export {};
@@ -5,10 +5,11 @@ exports.Loading = Loading;
5
5
  exports.LoadingError = LoadingError;
6
6
  exports.Error = Error;
7
7
  exports.Submitted = Submitted;
8
+ exports.Fields = Fields;
8
9
  const jsx_runtime_1 = require("react/jsx-runtime");
9
10
  const services_manager_react_1 = require("@wix/services-manager-react");
10
- const form_service_js_1 = require("../../services/form-service.js");
11
11
  const services_manager_1 = require("@wix/services-manager");
12
+ const form_service_js_1 = require("../../services/form-service.js");
12
13
  const DEFAULT_SUCCESS_MESSAGE = 'Your form has been submitted successfully.';
13
14
  /**
14
15
  * Root component that provides the Form service context to its children.
@@ -16,8 +17,9 @@ const DEFAULT_SUCCESS_MESSAGE = 'Your form has been submitted successfully.';
16
17
  *
17
18
  * @order 1
18
19
  * @component
19
- * @param {React.ReactNode} children - Child components that will have access to form context
20
- * @param {FormServiceConfig} formServiceConfig - Configuration object containing form data
20
+ * @param {RootProps} props - Component props
21
+ * @param {React.ReactNode} props.children - Child components that will have access to form context
22
+ * @param {FormServiceConfig} props.formServiceConfig - Configuration object containing form data
21
23
  * @example
22
24
  * ```tsx
23
25
  * import { Form } from '@wix/headless-forms/react';
@@ -54,8 +56,8 @@ const DEFAULT_SUCCESS_MESSAGE = 'Your form has been submitted successfully.';
54
56
  * }
55
57
  * ```
56
58
  */
57
- function Root(props) {
58
- return ((0, jsx_runtime_1.jsx)(services_manager_react_1.WixServices, { servicesMap: (0, services_manager_1.createServicesMap)().addService(form_service_js_1.FormServiceDefinition, form_service_js_1.FormService, props.formServiceConfig), children: props.children }));
59
+ function Root({ formServiceConfig, children, }) {
60
+ return ((0, jsx_runtime_1.jsx)(services_manager_react_1.WixServices, { servicesMap: (0, services_manager_1.createServicesMap)().addService(form_service_js_1.FormServiceDefinition, form_service_js_1.FormService, formServiceConfig), children: children }));
59
61
  }
60
62
  /**
61
63
  * Headless component for form loading state access
@@ -81,8 +83,8 @@ function Root(props) {
81
83
  * ```
82
84
  */
83
85
  function Loading(props) {
84
- const service = (0, services_manager_react_1.useService)(form_service_js_1.FormServiceDefinition);
85
- const isLoading = service.isLoading?.get() || false;
86
+ const { isLoadingSignal } = (0, services_manager_react_1.useService)(form_service_js_1.FormServiceDefinition);
87
+ const isLoading = isLoadingSignal.get();
86
88
  return props.children({
87
89
  isLoading,
88
90
  });
@@ -113,8 +115,8 @@ function Loading(props) {
113
115
  * ```
114
116
  */
115
117
  function LoadingError(props) {
116
- const service = (0, services_manager_react_1.useService)(form_service_js_1.FormServiceDefinition);
117
- const error = service.error?.get() || null;
118
+ const { errorSignal } = (0, services_manager_react_1.useService)(form_service_js_1.FormServiceDefinition);
119
+ const error = errorSignal.get();
118
120
  const hasError = !!error;
119
121
  return props.children({
120
122
  error,
@@ -147,10 +149,9 @@ function LoadingError(props) {
147
149
  * ```
148
150
  */
149
151
  function Error(props) {
150
- const service = (0, services_manager_react_1.useService)(form_service_js_1.FormServiceDefinition);
151
- const submitResponse = service.submitResponse?.get() || { type: 'idle' };
152
- const error = submitResponse.type === 'error' ? submitResponse.message : null;
153
- const hasError = submitResponse.type === 'error';
152
+ // TODO: Implement submit response handling when submitResponseSignal is added to service
153
+ const error = null;
154
+ const hasError = false;
154
155
  return props.children({
155
156
  error,
156
157
  hasError,
@@ -183,14 +184,45 @@ function Error(props) {
183
184
  * ```
184
185
  */
185
186
  function Submitted(props) {
186
- const service = (0, services_manager_react_1.useService)(form_service_js_1.FormServiceDefinition);
187
- const submitResponse = service.submitResponse?.get() || { type: 'idle' };
188
- const isSubmitted = submitResponse.type === 'success';
189
- const message = submitResponse.type === 'success'
190
- ? submitResponse.message || DEFAULT_SUCCESS_MESSAGE
191
- : DEFAULT_SUCCESS_MESSAGE;
187
+ // TODO: Implement submit response handling when submitResponseSignal is added to service
188
+ const isSubmitted = false;
189
+ const message = DEFAULT_SUCCESS_MESSAGE;
192
190
  return props.children({
193
191
  isSubmitted,
194
192
  message,
195
193
  });
196
194
  }
195
+ /**
196
+ * Fields component that provides form data to its children.
197
+ * This component accesses the form data from the service and passes it to children via render props.
198
+ *
199
+ * @component
200
+ * @param {FieldsProps} props - Component props
201
+ * @param {FieldsProps['children']} props.children - Render prop function that receives form data
202
+ * @example
203
+ * ```tsx
204
+ * import { Form } from '@wix/headless-forms/react';
205
+ *
206
+ * function FormFields() {
207
+ * return (
208
+ * <Form.Fields>
209
+ * {({ form }) => (
210
+ * form ? (
211
+ * <div>
212
+ * <h2>{form.name}</h2>
213
+ * <p>{form.description}</p>
214
+ * </div>
215
+ * ) : null
216
+ * )}
217
+ * </Form.Fields>
218
+ * );
219
+ * }
220
+ * ```
221
+ */
222
+ function Fields(props) {
223
+ const { formSignal } = (0, services_manager_react_1.useService)(form_service_js_1.FormServiceDefinition);
224
+ const form = formSignal.get();
225
+ return props.children({
226
+ form,
227
+ });
228
+ }
@@ -786,7 +786,7 @@ export interface DateInputProps extends BaseFieldProps {
786
786
  label: string;
787
787
  showLabel: boolean;
788
788
  showPlaceholder: boolean;
789
- firstDayOfWeek: 'SUNDAY' | 'MONDAY';
789
+ showDateLabels: boolean;
790
790
  acceptedDates: 'all' | 'past' | 'future';
791
791
  description?: forms.RichContent;
792
792
  }