@wix/headless-forms 0.0.2 → 0.0.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.
@@ -1,137 +1,92 @@
1
1
  import { forms } from '@wix/forms';
2
2
  import { defineService, implementService } from '@wix/services-definitions';
3
3
  import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
4
- export const FormServiceDefinition = defineService('formService');
5
4
  /**
6
- * Form service implementation that supports both pre-loaded form data and lazy loading.
7
- *
8
- * This service provides reactive state management for form data, loading states, errors, and submission responses.
9
- * It automatically handles form loading when only a formId is provided, making it suitable for both SSR and client-side scenarios.
10
- *
11
- * ## Service Behavior
12
- *
13
- * **Configuration Resolution:**
14
- * - If `form` is provided: Uses pre-loaded form data immediately (SSR/SSG pattern)
15
- * - If only `formId` is provided: Loads form data asynchronously from Wix Forms API
16
- * - If both are provided: Uses pre-loaded `form` data and ignores `formId`
17
- * - If neither is provided: Throws an error during service initialization
5
+ * Service definition for the Form service.
6
+ * This defines the contract that the FormService must implement.
18
7
  *
19
- * **Loading States:**
20
- * - `isLoading`: `true` when loading form data via `formId`, `false` otherwise
21
- * - `form`: `null` initially when using `formId`, populated after successful load
22
- * - `error`: `null` initially, populated if form loading fails
23
- * - `submitResponse`: `{ type: 'idle' }` initially, updated during form submission
24
- *
25
- * **Error Handling:**
26
- * - Network errors during form loading are caught and stored in the `error` signal
27
- * - "Form not found" errors are handled when the formId doesn't exist
28
- * - All errors are logged to console for debugging
8
+ * @constant
9
+ */
10
+ export const FormServiceDefinition = defineService('formService');
11
+ /**
12
+ * Implementation of the Form service that manages reactive form data.
13
+ * This service provides signals for form data, loading state, and error handling.
14
+ * It supports both pre-loaded form data and lazy loading with form IDs.
29
15
  *
30
16
  * @example
31
17
  * ```tsx
32
- * // Service automatically handles loading states
33
- * const service = useService(FormServiceDefinition);
18
+ * // Pre-loaded form data (SSR/SSG)
19
+ * const formService = FormService.withConfig({ form: formData });
34
20
  *
35
- * // Check loading state
36
- * const isLoading = service.isLoading.get();
37
- *
38
- * // Access form data (null during loading)
39
- * const form = service.form.get();
40
- *
41
- * // Check for errors
42
- * const error = service.error.get();
21
+ * // Lazy loading with form ID (client-side)
22
+ * const formService = FormService.withConfig({ formId: 'form-123' });
43
23
  * ```
44
- *
45
24
  */
46
25
  export const FormService = implementService.withConfig()(FormServiceDefinition, ({ getService, config }) => {
47
26
  const signalsService = getService(SignalsServiceDefinition);
48
- const { form: initialForm, formId } = config;
49
- // Validation: ensure either form or formId is provided
50
- if (!initialForm && !formId) {
51
- throw new Error('FormServiceConfig must provide either "form" or "formId"');
27
+ const isLoadingSignal = signalsService.signal(false);
28
+ const errorSignal = signalsService.signal(null);
29
+ const hasSchema = 'form' in config;
30
+ const formSignal = signalsService.signal(hasSchema ? config.form : null);
31
+ if (!hasSchema) {
32
+ loadForm(config.formId);
52
33
  }
53
- const form = signalsService.signal(initialForm || null);
54
- const isLoading = signalsService.signal(!!formId && !initialForm);
55
- const error = signalsService.signal(null);
56
- const submitResponse = signalsService.signal({ type: 'idle' });
57
- // Client-side form loading for formId case
58
- if (formId && !initialForm) {
59
- // Load form asynchronously
60
- forms
61
- .getForm(formId)
62
- .then((loadedForm) => {
63
- if (loadedForm) {
64
- form.set(loadedForm);
65
- isLoading.set(false);
34
+ async function loadForm(id) {
35
+ isLoadingSignal.set(true);
36
+ errorSignal.set(null);
37
+ try {
38
+ const result = await fetchForm(id);
39
+ if (result) {
40
+ formSignal.set(result);
66
41
  }
67
42
  else {
68
- error.set('Form not found');
69
- isLoading.set(false);
43
+ errorSignal.set('Form not found');
70
44
  }
71
- })
72
- .catch((err) => {
73
- console.error('Failed to load form:', err);
74
- error.set('Failed to load form');
75
- isLoading.set(false);
76
- });
45
+ }
46
+ catch (err) {
47
+ errorSignal.set('Failed to load form');
48
+ throw err;
49
+ }
50
+ finally {
51
+ isLoadingSignal.set(false);
52
+ }
77
53
  }
78
- return { form, isLoading, error, submitResponse };
54
+ return {
55
+ formSignal: formSignal,
56
+ isLoadingSignal: isLoadingSignal,
57
+ errorSignal: errorSignal,
58
+ };
79
59
  });
60
+ async function fetchForm(id) {
61
+ try {
62
+ const result = await forms.getForm(id);
63
+ if (!result) {
64
+ throw new Error(`Form ${id} not found`);
65
+ }
66
+ return result;
67
+ }
68
+ catch (err) {
69
+ console.error('Failed to load form:', id, err);
70
+ throw err;
71
+ }
72
+ }
80
73
  /**
81
- * Loads form service configuration by form ID.
82
- *
83
- * This function fetches form data from the Wix Forms API and returns a configuration
84
- * object that can be used to initialize the Form service. This is the recommended approach
85
- * for server-side rendering (SSR) and static site generation (SSG) scenarios.
86
- *
87
- * @param {string} id - The unique identifier of the form to load
88
- * @returns {Promise<FormServiceConfigResult>} A promise that resolves to either:
89
- * - `{ type: 'success', config: FormServiceConfig }` if the form is found and loaded successfully
90
- * - `{ type: 'notFound' }` if the form doesn't exist or an error occurs during loading
91
- *
92
- * @example
93
- * ```tsx
94
- * import { loadFormServiceConfig } from '@wix/headless-forms/services';
74
+ * Loads form service configuration from the Wix Forms API for SSR initialization.
75
+ * This function is designed to be used during Server-Side Rendering (SSR) to preload
76
+ * a specific form by ID that will be used to configure the FormService.
95
77
  *
96
- * // Server-side loading (Astro/SSR) - pre-loads form data
97
- * const formServiceConfigResult = await loadFormServiceConfig('form-id');
98
- *
99
- * if (formServiceConfigResult.type === 'notFound') {
100
- * return Astro.redirect('/404');
101
- * }
102
- *
103
- * // Use pre-loaded form data
104
- * const formServiceConfig = formServiceConfigResult.config;
105
- * <Form.Root formServiceConfig={formServiceConfig} />
106
- * ```
78
+ * @param {string} formId - The unique identifier of the form to load
79
+ * @returns {Promise<FormServiceConfig>} Configuration object with pre-loaded form data
80
+ * @throws {Error} When the form cannot be loaded
107
81
  *
108
82
  * @example
109
83
  * ```tsx
110
- * // Alternative: Client-side loading with formId
111
- * // No need to pre-load, service handles loading automatically
112
- * <Form.Root formServiceConfig={{ formId: 'form-id' }}>
113
- * <Form.Loading>
114
- * {({ isLoading }) => isLoading ? <div>Loading...</div> : null}
115
- * </Form.Loading>
116
- * <Form.Fields fieldMap={FIELD_MAP} />
117
- * </Form.Root>
84
+ * // In your SSR/SSG setup
85
+ * const formConfig = await loadFormServiceConfig('form-123');
86
+ * const formService = FormService.withConfig(formConfig);
118
87
  * ```
119
- *
120
- * @throws {Error} Logs errors to console but returns 'notFound' result instead of throwing
121
88
  */
122
- export async function loadFormServiceConfig(id) {
123
- try {
124
- const form = await forms.getForm(id);
125
- if (!form) {
126
- return { type: 'notFound' };
127
- }
128
- return {
129
- type: 'success',
130
- config: { form },
131
- };
132
- }
133
- catch (error) {
134
- console.error('Failed to load form:', error);
135
- }
136
- return { type: 'notFound' };
89
+ export async function loadFormServiceConfig(formId) {
90
+ const form = await fetchForm(formId);
91
+ return { form };
137
92
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/headless-forms",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "build": "npm run build:esm && npm run build:cjs",