@wix/headless-forms 0.0.0

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 (49) hide show
  1. package/README.md +46 -0
  2. package/cjs/dist/react/Form.d.ts +802 -0
  3. package/cjs/dist/react/Form.js +776 -0
  4. package/cjs/dist/react/Phone.d.ts +47 -0
  5. package/cjs/dist/react/Phone.js +56 -0
  6. package/cjs/dist/react/constants/calling-country-codes.d.ts +242 -0
  7. package/cjs/dist/react/constants/calling-country-codes.js +242 -0
  8. package/cjs/dist/react/context/FieldContext.d.ts +12 -0
  9. package/cjs/dist/react/context/FieldContext.js +16 -0
  10. package/cjs/dist/react/context/FieldLayoutContext.d.ts +12 -0
  11. package/cjs/dist/react/context/FieldLayoutContext.js +21 -0
  12. package/cjs/dist/react/core/Form.d.ts +342 -0
  13. package/cjs/dist/react/core/Form.js +278 -0
  14. package/cjs/dist/react/index.d.ts +3 -0
  15. package/cjs/dist/react/index.js +42 -0
  16. package/cjs/dist/react/types.d.ts +3 -0
  17. package/cjs/dist/react/types.js +2 -0
  18. package/cjs/dist/react/utils.d.ts +13 -0
  19. package/cjs/dist/react/utils.js +20 -0
  20. package/cjs/dist/services/form-service.d.ts +114 -0
  21. package/cjs/dist/services/form-service.js +152 -0
  22. package/cjs/dist/services/index.d.ts +1 -0
  23. package/cjs/dist/services/index.js +17 -0
  24. package/cjs/package.json +3 -0
  25. package/dist/react/Form.d.ts +802 -0
  26. package/dist/react/Form.js +740 -0
  27. package/dist/react/Phone.d.ts +47 -0
  28. package/dist/react/Phone.js +50 -0
  29. package/dist/react/constants/calling-country-codes.d.ts +242 -0
  30. package/dist/react/constants/calling-country-codes.js +241 -0
  31. package/dist/react/context/FieldContext.d.ts +12 -0
  32. package/dist/react/context/FieldContext.js +9 -0
  33. package/dist/react/context/FieldLayoutContext.d.ts +12 -0
  34. package/dist/react/context/FieldLayoutContext.js +13 -0
  35. package/dist/react/core/Form.d.ts +342 -0
  36. package/dist/react/core/Form.js +269 -0
  37. package/dist/react/index.d.ts +3 -0
  38. package/dist/react/index.js +3 -0
  39. package/dist/react/types.d.ts +3 -0
  40. package/dist/react/types.js +1 -0
  41. package/dist/react/utils.d.ts +13 -0
  42. package/dist/react/utils.js +17 -0
  43. package/dist/services/form-service.d.ts +114 -0
  44. package/dist/services/form-service.js +148 -0
  45. package/dist/services/index.d.ts +1 -0
  46. package/dist/services/index.js +1 -0
  47. package/package.json +62 -0
  48. package/react/package.json +4 -0
  49. package/services/package.json +4 -0
@@ -0,0 +1,114 @@
1
+ import { forms } from '@wix/forms';
2
+ import { type ReadOnlySignal } from '@wix/services-definitions/core-services/signals';
3
+ import { FormValues } from '../react/types.js';
4
+ /**
5
+ * Response type for form submission operations.
6
+ * Represents the different states a form submission can be in.
7
+ */
8
+ export type SubmitResponse = {
9
+ type: 'success';
10
+ message?: string;
11
+ } | {
12
+ type: 'error';
13
+ message: string;
14
+ } | {
15
+ type: 'idle';
16
+ } | {
17
+ type: 'loading';
18
+ };
19
+ /**
20
+ * API interface for the Form service, providing reactive form data management.
21
+ * This service handles loading and managing form data, loading state, errors, and submissions.
22
+ * It supports both pre-loaded form data and lazy loading with form IDs.
23
+ *
24
+ * @interface FormServiceAPI
25
+ */
26
+ export interface FormServiceAPI {
27
+ /** Reactive signal containing the current form data */
28
+ formSignal: ReadOnlySignal<forms.Form | null>;
29
+ /** Reactive signal indicating if a form is currently being loaded */
30
+ isLoadingSignal: ReadOnlySignal<boolean>;
31
+ /** Reactive signal containing any error message, or null if no error */
32
+ errorSignal: ReadOnlySignal<string | null>;
33
+ /** Reactive signal containing submission response state */
34
+ submitResponseSignal: ReadOnlySignal<SubmitResponse>;
35
+ /** Function to submit form with current values */
36
+ submitForm: (formValues: FormValues) => Promise<void>;
37
+ }
38
+ /**
39
+ * Service definition for the Form service.
40
+ * This defines the contract that the FormService must implement.
41
+ *
42
+ * @constant
43
+ */
44
+ export declare const FormServiceDefinition: string & {
45
+ __api: FormServiceAPI;
46
+ __config: {};
47
+ isServiceDefinition?: boolean;
48
+ } & FormServiceAPI;
49
+ type OnSubmit = (formId: string, formValues: FormValues) => Promise<SubmitResponse>;
50
+ /**
51
+ * Configuration type for the Form service.
52
+ * Supports two distinct patterns for providing form data:
53
+ * - Pre-loaded form data (SSR/SSG scenarios)
54
+ * - Lazy loading with form ID (client-side routing)
55
+ *
56
+ * Optionally accepts a custom submission handler to override default behavior.
57
+ *
58
+ * @type {FormServiceConfig}
59
+ */
60
+ export type FormServiceConfig = {
61
+ formId: string;
62
+ onSubmit?: OnSubmit;
63
+ } | {
64
+ form: forms.Form;
65
+ onSubmit?: OnSubmit;
66
+ };
67
+ /**
68
+ * Implementation of the Form service that manages reactive form data and submissions.
69
+ * This service provides signals for form data, loading state, error handling, and submission state.
70
+ * It supports both pre-loaded form data and lazy loading with form IDs.
71
+ * Consumers can provide a custom submission handler via config.
72
+ *
73
+ * @example
74
+ * ```tsx
75
+ * // Pre-loaded form data (SSR/SSG)
76
+ * const formService = FormService.withConfig({ form: formData });
77
+ *
78
+ * // Lazy loading with form ID (client-side)
79
+ * const formService = FormService.withConfig({ formId: 'form-123' });
80
+ *
81
+ * // With custom submission handler
82
+ * const formService = FormService.withConfig({
83
+ * formId: 'form-123',
84
+ * onSubmit: async (formId, formValues) => {
85
+ * // Custom submission logic
86
+ * await fetch('/api/submit', { method: 'POST', body: JSON.stringify({ formId, ...formValues }) });
87
+ * return { type: 'success', message: 'Form submitted!' };
88
+ * }
89
+ * });
90
+ * ```
91
+ */
92
+ export declare const FormService: import("@wix/services-definitions").ServiceFactory<string & {
93
+ __api: FormServiceAPI;
94
+ __config: {};
95
+ isServiceDefinition?: boolean;
96
+ } & FormServiceAPI, FormServiceConfig>;
97
+ /**
98
+ * Loads form service configuration from the Wix Forms API for SSR initialization.
99
+ * This function is designed to be used during Server-Side Rendering (SSR) to preload
100
+ * a specific form by ID that will be used to configure the FormService.
101
+ *
102
+ * @param {string} formId - The unique identifier of the form to load
103
+ * @returns {Promise<FormServiceConfig>} Configuration object with pre-loaded form data
104
+ * @throws {Error} When the form cannot be loaded
105
+ *
106
+ * @example
107
+ * ```tsx
108
+ * // In your SSR/SSG setup
109
+ * const formConfig = await loadFormServiceConfig('form-123');
110
+ * const formService = FormService.withConfig(formConfig);
111
+ * ```
112
+ */
113
+ export declare function loadFormServiceConfig(formId: string): Promise<FormServiceConfig>;
114
+ export {};
@@ -0,0 +1,148 @@
1
+ import { forms, submissions } from '@wix/forms';
2
+ import { defineService, implementService } from '@wix/services-definitions';
3
+ import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
4
+ /**
5
+ * Service definition for the Form service.
6
+ * This defines the contract that the FormService must implement.
7
+ *
8
+ * @constant
9
+ */
10
+ export const FormServiceDefinition = defineService('formService');
11
+ /**
12
+ * Implementation of the Form service that manages reactive form data and submissions.
13
+ * This service provides signals for form data, loading state, error handling, and submission state.
14
+ * It supports both pre-loaded form data and lazy loading with form IDs.
15
+ * Consumers can provide a custom submission handler via config.
16
+ *
17
+ * @example
18
+ * ```tsx
19
+ * // Pre-loaded form data (SSR/SSG)
20
+ * const formService = FormService.withConfig({ form: formData });
21
+ *
22
+ * // Lazy loading with form ID (client-side)
23
+ * const formService = FormService.withConfig({ formId: 'form-123' });
24
+ *
25
+ * // With custom submission handler
26
+ * const formService = FormService.withConfig({
27
+ * formId: 'form-123',
28
+ * onSubmit: async (formId, formValues) => {
29
+ * // Custom submission logic
30
+ * await fetch('/api/submit', { method: 'POST', body: JSON.stringify({ formId, ...formValues }) });
31
+ * return { type: 'success', message: 'Form submitted!' };
32
+ * }
33
+ * });
34
+ * ```
35
+ */
36
+ export const FormService = implementService.withConfig()(FormServiceDefinition, ({ getService, config }) => {
37
+ const signalsService = getService(SignalsServiceDefinition);
38
+ const isLoadingSignal = signalsService.signal(false);
39
+ const errorSignal = signalsService.signal(null);
40
+ const submitResponseSignal = signalsService.signal({
41
+ type: 'idle',
42
+ });
43
+ const hasSchema = 'form' in config;
44
+ const formSignal = signalsService.signal(hasSchema ? config.form : null);
45
+ if (!hasSchema) {
46
+ loadForm(config.formId);
47
+ }
48
+ async function loadForm(id) {
49
+ isLoadingSignal.set(true);
50
+ errorSignal.set(null);
51
+ try {
52
+ const result = await fetchForm(id);
53
+ if (result) {
54
+ formSignal.set(result);
55
+ }
56
+ else {
57
+ errorSignal.set('Form not found');
58
+ }
59
+ }
60
+ catch (err) {
61
+ errorSignal.set('Failed to load form');
62
+ throw err;
63
+ }
64
+ finally {
65
+ isLoadingSignal.set(false);
66
+ }
67
+ }
68
+ async function defaultSubmitHandler(formId, formValues) {
69
+ try {
70
+ await submissions.createSubmission({
71
+ formId,
72
+ submissions: formValues,
73
+ });
74
+ // TODO: add message
75
+ return { type: 'success' };
76
+ }
77
+ catch (error) {
78
+ console.error('Form submission failed:', error);
79
+ return { type: 'error', message: 'Failed to submit form' };
80
+ }
81
+ }
82
+ /**
83
+ * Submits the form with the provided values.
84
+ * Uses custom handler if provided in config, otherwise uses default submission.
85
+ */
86
+ async function submitForm(formValues) {
87
+ const form = formSignal.get();
88
+ if (!form) {
89
+ console.error('Cannot submit: form not loaded');
90
+ return;
91
+ }
92
+ // @ts-expect-error
93
+ const formId = form._id ? form._id : form.id;
94
+ submitResponseSignal.set({ type: 'loading' });
95
+ try {
96
+ const handler = config.onSubmit || defaultSubmitHandler;
97
+ const response = await handler(formId, formValues);
98
+ submitResponseSignal.set(response);
99
+ }
100
+ catch (error) {
101
+ console.error('Unexpected error during submission:', error);
102
+ submitResponseSignal.set({
103
+ type: 'error',
104
+ message: 'Unexpected error during submission',
105
+ });
106
+ }
107
+ }
108
+ return {
109
+ formSignal: formSignal,
110
+ isLoadingSignal: isLoadingSignal,
111
+ errorSignal: errorSignal,
112
+ submitResponseSignal: submitResponseSignal,
113
+ submitForm: submitForm,
114
+ };
115
+ });
116
+ async function fetchForm(id) {
117
+ try {
118
+ const result = await forms.getForm(id);
119
+ if (!result) {
120
+ throw new Error(`Form ${id} not found`);
121
+ }
122
+ return result;
123
+ }
124
+ catch (err) {
125
+ console.error('Failed to load form:', id, err);
126
+ throw err;
127
+ }
128
+ }
129
+ /**
130
+ * Loads form service configuration from the Wix Forms API for SSR initialization.
131
+ * This function is designed to be used during Server-Side Rendering (SSR) to preload
132
+ * a specific form by ID that will be used to configure the FormService.
133
+ *
134
+ * @param {string} formId - The unique identifier of the form to load
135
+ * @returns {Promise<FormServiceConfig>} Configuration object with pre-loaded form data
136
+ * @throws {Error} When the form cannot be loaded
137
+ *
138
+ * @example
139
+ * ```tsx
140
+ * // In your SSR/SSG setup
141
+ * const formConfig = await loadFormServiceConfig('form-123');
142
+ * const formService = FormService.withConfig(formConfig);
143
+ * ```
144
+ */
145
+ export async function loadFormServiceConfig(formId) {
146
+ const form = await fetchForm(formId);
147
+ return { form };
148
+ }
@@ -0,0 +1 @@
1
+ export * from './form-service.js';
@@ -0,0 +1 @@
1
+ export * from './form-service.js';
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@wix/headless-forms",
3
+ "version": "0.0.0",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "scripts": {
7
+ "build": "npm run build:esm && npm run build:cjs",
8
+ "build:esm": "tsc -p tsconfig.json",
9
+ "build:cjs": "tsc -p tsconfig.cjs.json",
10
+ "build:watch": "tsc -p tsconfig.json --watch",
11
+ "test": "vitest",
12
+ "lint:fix": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json,md}\"",
13
+ "lint:check": "prettier --check \"src/**/*.{ts,tsx,js,jsx,json,md}\""
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "cjs",
18
+ "react",
19
+ "services"
20
+ ],
21
+ "exports": {
22
+ "./react": {
23
+ "types": "./dist/react/index.d.ts",
24
+ "import": "./dist/react/index.js",
25
+ "require": "./cjs/dist/react/index.js"
26
+ },
27
+ "./services": {
28
+ "types": "./dist/services/index.d.ts",
29
+ "import": "./dist/services/index.js",
30
+ "require": "./cjs/dist/services/index.js"
31
+ }
32
+ },
33
+ "devDependencies": {
34
+ "@testing-library/dom": "^10.4.0",
35
+ "@testing-library/jest-dom": "^6.6.3",
36
+ "@testing-library/react": "^16.3.0",
37
+ "@types/node": "^20.9.0",
38
+ "@vitest/ui": "^3.1.4",
39
+ "jsdom": "^26.1.0",
40
+ "prettier": "^3.4.2",
41
+ "typescript": "^5.8.3",
42
+ "vitest": "^3.1.4"
43
+ },
44
+ "dependencies": {
45
+ "@wix/form-public": "^0.55.0",
46
+ "@wix/forms": "^1.0.331",
47
+ "@wix/headless-utils": "0.0.0",
48
+ "@wix/services-definitions": "^0.1.4",
49
+ "@wix/services-manager-react": "^0.1.26"
50
+ },
51
+ "publishConfig": {
52
+ "registry": "https://registry.npmjs.org/",
53
+ "access": "public"
54
+ },
55
+ "wix": {
56
+ "artifact": {
57
+ "artifactId": "headless-forms",
58
+ "groupId": "com.wixpress.headless-components"
59
+ }
60
+ },
61
+ "falconPackageHash": "dcd3156d41c136d87ea0aa02ff35682cef2a377130471163d8530f6d"
62
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "main": "../cjs/dist/react/index.js",
3
+ "types": "../dist/react/index.d.ts"
4
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "main": "../cjs/dist/services/index.js",
3
+ "types": "../dist/services/index.d.ts"
4
+ }