@embeddables/forms 0.0.5 → 0.2.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.
- package/README.md +116 -33
- package/dist/{form-9Tp91g6a.js → form-7wmC3G_q.js} +652 -221
- package/dist/form-7wmC3G_q.js.map +1 -0
- package/dist/{form-DzfCc5X2.cjs → form-CdIfHqNc.cjs} +675 -220
- package/dist/form-CdIfHqNc.cjs.map +1 -0
- package/dist/{index-qfBhdk5L.d.ts → form-x4EJcR9A.d.ts} +114 -122
- package/dist/form-x4EJcR9A.d.ts.map +1 -0
- package/dist/index-CmcgIxTH.d.ts +78 -0
- package/dist/index-CmcgIxTH.d.ts.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +1 -1
- package/dist/react.cjs +136 -15
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.ts +49 -7
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +136 -16
- package/dist/react.js.map +1 -1
- package/dist/server.cjs +50 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.ts +13 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +49 -0
- package/dist/server.js.map +1 -0
- package/package.json +8 -3
- package/dist/form-9Tp91g6a.js.map +0 -1
- package/dist/form-DzfCc5X2.cjs.map +0 -1
- package/dist/index-qfBhdk5L.d.ts.map +0 -1
|
@@ -1,27 +1,4 @@
|
|
|
1
1
|
import { EmbeddablesInstance } from "@embeddables/core";
|
|
2
|
-
//#region src/errors.d.ts
|
|
3
|
-
/**
|
|
4
|
-
* Typed error hierarchy. Every failure this SDK raises on its own behalf is an
|
|
5
|
-
* instance of one of these, so consumers branch on the type
|
|
6
|
-
* (`if (e instanceof SchemaError) …`) instead of string-matching messages.
|
|
7
|
-
* Catch `FormsError` to handle them all.
|
|
8
|
-
*
|
|
9
|
-
* An error thrown by a consumer's own custom validator is never wrapped in one
|
|
10
|
-
* of these — it propagates with its original type and stack.
|
|
11
|
-
*/
|
|
12
|
-
/** Base class for every error the SDK throws. */
|
|
13
|
-
declare class FormsError extends Error {
|
|
14
|
-
constructor(message: string, options?: ErrorOptions);
|
|
15
|
-
}
|
|
16
|
-
/** The schema is malformed. */
|
|
17
|
-
declare class SchemaError extends FormsError {
|
|
18
|
-
constructor(message: string, options?: ErrorOptions);
|
|
19
|
-
}
|
|
20
|
-
/** A custom validator returned a thenable, or a shape that is not a message. */
|
|
21
|
-
declare class ValidatorError extends FormsError {
|
|
22
|
-
constructor(message: string, options?: ErrorOptions);
|
|
23
|
-
}
|
|
24
|
-
//#endregion
|
|
25
2
|
//#region ../shared-types/dist/json.types.d.ts
|
|
26
3
|
/**
|
|
27
4
|
* Recursive JSON value, compatible with JSONB column values and public
|
|
@@ -31,8 +8,54 @@ type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
|
31
8
|
[key: string]: JsonValue;
|
|
32
9
|
};
|
|
33
10
|
//#endregion
|
|
11
|
+
//#region ../shared-types/dist/analytics-instance.types.d.ts
|
|
12
|
+
/**
|
|
13
|
+
* Hono-free analytics client surface other SDKs accept without depending on
|
|
14
|
+
* `hono` or `@embeddables/analytics`. Precise ingest event types stay inferred
|
|
15
|
+
* from the Worker in analytics-sdk; this module is the structural instance, not
|
|
16
|
+
* the HTTP contract.
|
|
17
|
+
*
|
|
18
|
+
* `trackEvent` is a method (not a function property) so parameter checking
|
|
19
|
+
* stays bivariant: a precise analytics-sdk client remains assignable here, and
|
|
20
|
+
* callers without those types can still pass their payloads.
|
|
21
|
+
*/
|
|
22
|
+
/** Loose event payload other SDKs pass to `trackEvent`. */
|
|
23
|
+
interface AnalyticsTrackEvent {
|
|
24
|
+
event_name: string;
|
|
25
|
+
[key: string]: unknown;
|
|
26
|
+
}
|
|
27
|
+
/** Body `trackEvent` resolves with — identity plus ingest outcome. */
|
|
28
|
+
interface AnalyticsTrackResult {
|
|
29
|
+
app_user_id: string;
|
|
30
|
+
accepted: number;
|
|
31
|
+
forwarded: boolean;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Structural stand-in for `ReturnType<typeof initAnalytics>`. Other SDKs type
|
|
35
|
+
* injected clients against this; analytics-sdk's `AnalyticsClient` must remain
|
|
36
|
+
* assignable to it.
|
|
37
|
+
*/
|
|
38
|
+
interface AnalyticsInstance<TEvent = AnalyticsTrackEvent> {
|
|
39
|
+
trackEvent(input: TEvent | readonly TEvent[]): Promise<AnalyticsTrackResult>;
|
|
40
|
+
/** Live identity: the composed core instance's current user. */
|
|
41
|
+
getAppUserId(): string | null;
|
|
42
|
+
getProjectId(): string;
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region ../shared-types/dist/forms.types.d.ts
|
|
46
|
+
/** Stored field value for `type: file` — bytes live in R2; JSON carries metadata only. */
|
|
47
|
+
type FormFileRef = {
|
|
48
|
+
file_id: string;
|
|
49
|
+
name: string;
|
|
50
|
+
content_type: string;
|
|
51
|
+
size: number;
|
|
52
|
+
status: 'uploading' | 'done' | 'error';
|
|
53
|
+
uploaded_at?: string;
|
|
54
|
+
error?: string;
|
|
55
|
+
} & Record<string, JsonValue>;
|
|
56
|
+
//#endregion
|
|
34
57
|
//#region src/core/config.d.ts
|
|
35
|
-
type FieldType = 'text' | 'email' | 'number' | 'boolean' | 'select' | 'multiselect' | 'json';
|
|
58
|
+
type FieldType = 'text' | 'email' | 'number' | 'boolean' | 'select' | 'multiselect' | 'json' | 'file';
|
|
36
59
|
/** Runtime `type` literal → the TypeScript type of that field's value. */
|
|
37
60
|
interface ValueOfFieldType {
|
|
38
61
|
text: string;
|
|
@@ -42,22 +65,43 @@ interface ValueOfFieldType {
|
|
|
42
65
|
select: string;
|
|
43
66
|
multiselect: string[];
|
|
44
67
|
json: JsonValue;
|
|
68
|
+
file: FormFileRef | null;
|
|
45
69
|
}
|
|
46
70
|
type FieldValidator<TValue extends JsonValue = JsonValue> = (args: {
|
|
47
71
|
value: TValue;
|
|
48
72
|
values: Readonly<Record<string, JsonValue>>;
|
|
49
73
|
}) => string | readonly string[] | null;
|
|
74
|
+
/** One declarable choice on a `select` or `multiselect` field. */
|
|
75
|
+
interface FieldOption {
|
|
76
|
+
readonly value: string;
|
|
77
|
+
readonly label?: string;
|
|
78
|
+
/**
|
|
79
|
+
* `multiselect` only. A selected exclusive option cannot coexist with any
|
|
80
|
+
* other value: selecting it clears the rest, and selecting a regular
|
|
81
|
+
* option clears it.
|
|
82
|
+
*/
|
|
83
|
+
readonly exclusive?: boolean;
|
|
84
|
+
}
|
|
85
|
+
type SelectFieldOption = Omit<FieldOption, 'exclusive'> & {
|
|
86
|
+
readonly exclusive?: never;
|
|
87
|
+
};
|
|
50
88
|
interface FieldValidationsFor<TType extends FieldType> {
|
|
51
89
|
readonly required?: boolean;
|
|
52
90
|
readonly minLength?: number;
|
|
53
91
|
readonly maxLength?: number;
|
|
54
92
|
readonly min?: number;
|
|
55
93
|
readonly max?: number;
|
|
56
|
-
/**
|
|
94
|
+
/**
|
|
95
|
+
* ECMAScript source without delimiters. Flags go in an optional leading
|
|
96
|
+
* `(?flags)` prefix, e.g. `'(?u)^\\p{L}+$'`. Allowed: `dgimsuvy`; `g` and
|
|
97
|
+
* `y` are stripped before compilation.
|
|
98
|
+
*/
|
|
57
99
|
readonly pattern?: string;
|
|
58
|
-
/** Flags for `pattern`. `g` and `y` are stripped before compilation. */
|
|
59
|
-
readonly patternFlags?: string;
|
|
60
100
|
readonly oneOf?: readonly JsonValue[];
|
|
101
|
+
/** MIME types or `type/*` wildcards. */
|
|
102
|
+
readonly accept?: TType extends 'file' ? readonly string[] : never;
|
|
103
|
+
/** Max bytes. */
|
|
104
|
+
readonly maxSize?: TType extends 'file' ? number : never;
|
|
61
105
|
/** `value` is bound to this field's declared `type`. */
|
|
62
106
|
readonly custom?: FieldValidator<ValueOfFieldType[TType]>;
|
|
63
107
|
}
|
|
@@ -65,9 +109,16 @@ interface FieldConfigFor<TType extends FieldType> {
|
|
|
65
109
|
readonly key: string;
|
|
66
110
|
readonly label: string;
|
|
67
111
|
readonly type: TType;
|
|
112
|
+
/**
|
|
113
|
+
* Declarable choices. `select` accepts one of these values, `multiselect`
|
|
114
|
+
* accepts any number of them. Typed as `never` on every other field type.
|
|
115
|
+
*/
|
|
116
|
+
readonly options?: TType extends 'select' ? readonly SelectFieldOption[] : TType extends 'multiselect' ? readonly FieldOption[] : never;
|
|
68
117
|
readonly validations?: FieldValidationsFor<TType>;
|
|
69
118
|
readonly registryId?: string;
|
|
70
119
|
readonly protocolFieldId?: string;
|
|
120
|
+
/** When true, the field value is persisted to a per-form browser cookie on `set`. */
|
|
121
|
+
readonly includeInCookies?: boolean;
|
|
71
122
|
}
|
|
72
123
|
type FieldConfig = { [T in FieldType]: FieldConfigFor<T>; }[FieldType];
|
|
73
124
|
type FieldValidations = { [T in FieldType]: FieldValidationsFor<T>; }[FieldType];
|
|
@@ -84,90 +135,6 @@ type ProtocolFieldId<TSchema extends FormSchema> = [TSchema] extends [FormSchema
|
|
|
84
135
|
protocolFieldId: string;
|
|
85
136
|
}>['protocolFieldId'];
|
|
86
137
|
//#endregion
|
|
87
|
-
//#region src/storage/storage.d.ts
|
|
88
|
-
/** Every form on the origin shares this one entry, indexed by form ID. */
|
|
89
|
-
declare const FORM_DATA_KEY = "EMBEDDABLES-FORM-DATA";
|
|
90
|
-
interface FormsStorage {
|
|
91
|
-
getItem(key: string): string | null;
|
|
92
|
-
setItem(key: string, value: string): void;
|
|
93
|
-
removeItem(key: string): void;
|
|
94
|
-
}
|
|
95
|
-
//#endregion
|
|
96
|
-
//#region ../shared-types/dist/analytics-instance.types.d.ts
|
|
97
|
-
/**
|
|
98
|
-
* Hono-free analytics client surface other SDKs accept without depending on
|
|
99
|
-
* `hono` or `@embeddables/analytics`. Precise ingest event types stay inferred
|
|
100
|
-
* from the Worker in analytics-sdk; this module is the structural instance, not
|
|
101
|
-
* the HTTP contract.
|
|
102
|
-
*
|
|
103
|
-
* `trackEvent` is a method (not a function property) so parameter checking
|
|
104
|
-
* stays bivariant: a precise analytics-sdk client remains assignable here, and
|
|
105
|
-
* callers without those types can still pass their payloads.
|
|
106
|
-
*/
|
|
107
|
-
/** Loose event payload other SDKs pass to `trackEvent`. */
|
|
108
|
-
interface AnalyticsTrackEvent {
|
|
109
|
-
event_name: string;
|
|
110
|
-
[key: string]: unknown;
|
|
111
|
-
}
|
|
112
|
-
/** Body `trackEvent` resolves with — identity plus ingest outcome. */
|
|
113
|
-
interface AnalyticsTrackResult {
|
|
114
|
-
app_user_id: string;
|
|
115
|
-
accepted: number;
|
|
116
|
-
forwarded: boolean;
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* Structural stand-in for `ReturnType<typeof initAnalytics>`. Other SDKs type
|
|
120
|
-
* injected clients against this; analytics-sdk's `AnalyticsClient` must remain
|
|
121
|
-
* assignable to it.
|
|
122
|
-
*/
|
|
123
|
-
interface AnalyticsInstance<TEvent = AnalyticsTrackEvent> {
|
|
124
|
-
trackEvent(input: TEvent | readonly TEvent[]): Promise<AnalyticsTrackResult>;
|
|
125
|
-
/** Live identity: the composed core instance's current user. */
|
|
126
|
-
getAppUserId(): string | null;
|
|
127
|
-
getProjectId(): string;
|
|
128
|
-
}
|
|
129
|
-
//#endregion
|
|
130
|
-
//#region ../shared-types/dist/analytics-ingest.types.d.ts
|
|
131
|
-
type FieldUpdatedType = 'text' | 'email' | 'number' | 'boolean' | 'select' | 'multiselect' | 'json';
|
|
132
|
-
/**
|
|
133
|
-
* Raw `field_value` accepted by ingest. Every forms-sdk `ValueOfFieldType` is a
|
|
134
|
-
* JSON value — scalar (`text`/`email`/`select` → string, `number` → number,
|
|
135
|
-
* `boolean` → boolean), `multiselect` → `string[]`, `json` → arbitrary JSON —
|
|
136
|
-
* so the contract collapses to `JsonValue`; the runtime ingest schema is what
|
|
137
|
-
* bounds each shape.
|
|
138
|
-
*/
|
|
139
|
-
type FieldUpdatedValue = JsonValue;
|
|
140
|
-
type FunnelStepFields = {
|
|
141
|
-
is_funnel_step?: boolean;
|
|
142
|
-
funnel_step_label?: string;
|
|
143
|
-
};
|
|
144
|
-
type FieldUpdatedEvent = FunnelStepFields & {
|
|
145
|
-
event_name: 'field:updated';
|
|
146
|
-
/** Schema key of the updated field. */
|
|
147
|
-
field_key: string;
|
|
148
|
-
field_type: FieldUpdatedType;
|
|
149
|
-
field_value?: FieldUpdatedValue;
|
|
150
|
-
/** Field Registry identifier when the field is registry-backed. */
|
|
151
|
-
registry_field_id?: string;
|
|
152
|
-
/** Protocol question identifier when the field is protocol-backed. */
|
|
153
|
-
protocol_field_id?: string;
|
|
154
|
-
};
|
|
155
|
-
type DataUpdatedEntry = {
|
|
156
|
-
value: string;
|
|
157
|
-
label: string;
|
|
158
|
-
};
|
|
159
|
-
type DataUpdatedEvent = FunnelStepFields & {
|
|
160
|
-
event_name: 'data:updated';
|
|
161
|
-
data: Record<string, DataUpdatedEntry>;
|
|
162
|
-
};
|
|
163
|
-
type FormSubmittedEvent = FunnelStepFields & {
|
|
164
|
-
event_name: 'form:submitted';
|
|
165
|
-
form_key: string;
|
|
166
|
-
};
|
|
167
|
-
//#endregion
|
|
168
|
-
//#region src/core/analytics.d.ts
|
|
169
|
-
type FormsAnalyticsEvent = DataUpdatedEvent | FieldUpdatedEvent | FormSubmittedEvent;
|
|
170
|
-
//#endregion
|
|
171
138
|
//#region src/core/form.d.ts
|
|
172
139
|
/** Per-key validation errors. An empty object means the operation succeeded. */
|
|
173
140
|
type FieldErrors<TSchema extends FormSchema> = Readonly<Partial<Record<FormFieldKey<TSchema>, readonly string[]>>>;
|
|
@@ -229,16 +196,43 @@ interface FormInstance<TSchema extends FormSchema> {
|
|
|
229
196
|
validate(patch?: Partial<FormValues<TSchema>>): Promise<ValidateResult<TSchema>>;
|
|
230
197
|
errors(): FieldErrors<TSchema>;
|
|
231
198
|
clear(): void;
|
|
199
|
+
/**
|
|
200
|
+
* Uploads a file for a declared `type: file` field. Returns a `FormFileRef`
|
|
201
|
+
* with `status: 'done'`; the caller commits it with `.set()`.
|
|
202
|
+
*/
|
|
203
|
+
uploadFile(args: {
|
|
204
|
+
key: FormFieldKey<TSchema>;
|
|
205
|
+
file: Blob;
|
|
206
|
+
fileName?: string;
|
|
207
|
+
}): Promise<FormFileRef>;
|
|
232
208
|
/** Synchronous listener for value and error mutations. Returns an unsubscribe function. */
|
|
233
209
|
subscribe(listener: () => void): () => void;
|
|
234
210
|
}
|
|
235
211
|
/** Every form the app can open, keyed by form id — the shape `_dist` exports. */
|
|
236
212
|
type FormSchemaMap = Readonly<Record<string, FormSchema>>;
|
|
237
213
|
type CustomValidationsFor<TSchema extends FormSchema> = { readonly [K in FormFieldKey<TSchema>]?: FieldValidator; };
|
|
214
|
+
interface FormCustomValidationsEntry<TSchema extends FormSchema = FormSchema> {
|
|
215
|
+
formId: Extract<TSchema['id'], string>;
|
|
216
|
+
customValidations: CustomValidationsFor<TSchema>;
|
|
217
|
+
}
|
|
218
|
+
/** Per-form SSR/hydration seed passed from `initFormsServer().getServerFormData()`. */
|
|
219
|
+
interface FormServerDataEntry<TSchema extends FormSchema = FormSchema> {
|
|
220
|
+
formId: Extract<TSchema['id'], string>;
|
|
221
|
+
serverFormData: Partial<FormValues<TSchema>>;
|
|
222
|
+
}
|
|
223
|
+
type FormCustomValidationsEntriesFor<TSchemas extends FormSchemaMap> = ReadonlyArray<{ [K in keyof TSchemas & string]: FormCustomValidationsEntry<TSchemas[K]>; }[keyof TSchemas & string]>;
|
|
224
|
+
type FormServerDataEntriesFor<TSchemas extends FormSchemaMap> = ReadonlyArray<{ [K in keyof TSchemas & string]: FormServerDataEntry<TSchemas[K]>; }[keyof TSchemas & string]>;
|
|
225
|
+
interface FormsServerInitOptions<TSchemas extends FormSchemaMap = FormSchemaMap> {
|
|
226
|
+
server: EmbeddablesInstance;
|
|
227
|
+
customValidations?: FormCustomValidationsEntriesFor<TSchemas>;
|
|
228
|
+
analyticsInstance?: AnalyticsInstance;
|
|
229
|
+
}
|
|
230
|
+
type ServerFormInstance<TSchema extends FormSchema> = Pick<FormInstance<TSchema>, 'key' | 'set' | 'get' | 'getAll' | 'getValueByProtocolFieldId'>;
|
|
231
|
+
type ServerFormDataByFormId<TSchemas extends FormSchemaMap> = { [K in keyof TSchemas]?: Partial<FormValues<TSchemas[K]>>; };
|
|
238
232
|
interface InitFormsOptions<TSchemas extends FormSchemaMap = FormSchemaMap> {
|
|
239
233
|
core: EmbeddablesInstance;
|
|
240
|
-
|
|
241
|
-
|
|
234
|
+
customValidations?: FormCustomValidationsEntriesFor<TSchemas>;
|
|
235
|
+
serverFormData?: FormServerDataEntriesFor<TSchemas>;
|
|
242
236
|
analyticsInstance?: AnalyticsInstance;
|
|
243
237
|
}
|
|
244
238
|
interface FormsClient<TSchemas extends FormSchemaMap = FormSchemaMap> {
|
|
@@ -250,20 +244,18 @@ interface FormsClient<TSchemas extends FormSchemaMap = FormSchemaMap> {
|
|
|
250
244
|
* would not observe each other's writes and the later one's `.set()` would
|
|
251
245
|
* overwrite the earlier one's storage, so the client never hands out a second.
|
|
252
246
|
*
|
|
253
|
-
* ! `customValidations`
|
|
254
|
-
* !
|
|
255
|
-
* ! with the original ones.
|
|
247
|
+
* ! `customValidations` belong to the matching form id on Core. `getForm`
|
|
248
|
+
* ! only selects which memoized instance to return.
|
|
256
249
|
*/
|
|
257
250
|
getForm<K extends keyof TSchemas & string>(params: {
|
|
258
251
|
formId: K;
|
|
259
|
-
customValidations?: CustomValidationsFor<TSchemas[K]>;
|
|
260
252
|
}): FormInstance<TSchemas[K]>;
|
|
261
253
|
}
|
|
262
254
|
/**
|
|
263
|
-
* Validates the core instance and
|
|
264
|
-
* whose `getForm` builds each form by id.
|
|
255
|
+
* Validates the core instance and registered form schemas once, then returns a
|
|
256
|
+
* client whose `getForm` builds each form by id.
|
|
265
257
|
*/
|
|
266
|
-
declare function initForms<
|
|
258
|
+
declare function initForms<TSchemas extends FormSchemaMap = FormSchemaMap>(options: InitFormsOptions<TSchemas>): FormsClient<TSchemas>;
|
|
267
259
|
//#endregion
|
|
268
|
-
export {
|
|
269
|
-
//# sourceMappingURL=
|
|
260
|
+
export { JsonValue as A, FormValues as C, AnalyticsInstance as D, FormFileRef as E, AnalyticsTrackEvent as O, FormSchema as S, SelectFieldOption as T, FieldOption as _, FormSchemaMap as a, FieldValidator as b, FormsServerInitOptions as c, ServerFormInstance as d, SetResult as f, FieldConfig as g, initForms as h, FormInstance as i, AnalyticsTrackResult as k, InitFormsOptions as l, ValidateResult as m, FieldErrors as n, FormServerDataEntry as o, SubmitResult as p, FormCustomValidationsEntry as r, FormsClient as s, CustomValidationsFor as t, ServerFormDataByFormId as u, FieldType as v, ProtocolFieldId as w, FormFieldKey as x, FieldValidations as y };
|
|
261
|
+
//# sourceMappingURL=form-x4EJcR9A.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"form-x4EJcR9A.d.ts","names":[],"sources":["../../shared-types/dist/json.types.d.ts","../../shared-types/dist/analytics-instance.types.d.ts","../../shared-types/dist/forms.types.d.ts","../src/core/config.ts","../src/core/form.ts"],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { A as JsonValue } from "./form-x4EJcR9A.js";
|
|
2
|
+
//#region src/errors.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Typed error hierarchy. Every failure this SDK raises on its own behalf is an
|
|
5
|
+
* instance of one of these, so consumers branch on the type
|
|
6
|
+
* (`if (e instanceof SchemaError) …`) instead of string-matching messages.
|
|
7
|
+
* Catch `FormsError` to handle them all.
|
|
8
|
+
*
|
|
9
|
+
* An error thrown by a consumer's own custom validator is never wrapped in one
|
|
10
|
+
* of these — it propagates with its original type and stack.
|
|
11
|
+
*/
|
|
12
|
+
/** Base class for every error the SDK throws. */
|
|
13
|
+
declare class FormsError extends Error {
|
|
14
|
+
constructor(message: string, options?: ErrorOptions);
|
|
15
|
+
}
|
|
16
|
+
/** The schema is malformed. */
|
|
17
|
+
declare class SchemaError extends FormsError {
|
|
18
|
+
constructor(message: string, options?: ErrorOptions);
|
|
19
|
+
}
|
|
20
|
+
/** A custom validator returned a thenable, or a shape that is not a message. */
|
|
21
|
+
declare class ValidatorError extends FormsError {
|
|
22
|
+
constructor(message: string, options?: ErrorOptions);
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region ../shared-types/dist/analytics-ingest.types.d.ts
|
|
26
|
+
type FieldUpdatedType = 'text' | 'email' | 'number' | 'boolean' | 'select' | 'multiselect' | 'json' | 'file';
|
|
27
|
+
/**
|
|
28
|
+
* Raw `field_value` accepted by ingest. Every forms-sdk `ValueOfFieldType` is a
|
|
29
|
+
* JSON value — scalar (`text`/`email`/`select` → string, `number` → number,
|
|
30
|
+
* `boolean` → boolean), `multiselect` → `string[]`, `json` → arbitrary JSON —
|
|
31
|
+
* so the contract collapses to `JsonValue`; the runtime ingest schema is what
|
|
32
|
+
* bounds each shape.
|
|
33
|
+
*/
|
|
34
|
+
type FieldUpdatedValue = JsonValue;
|
|
35
|
+
type FunnelStepFields = {
|
|
36
|
+
is_funnel_step?: boolean;
|
|
37
|
+
funnel_step_label?: string;
|
|
38
|
+
};
|
|
39
|
+
type FieldUpdatedEvent = FunnelStepFields & {
|
|
40
|
+
event_name: 'field:updated';
|
|
41
|
+
/** Schema key of the updated field. */
|
|
42
|
+
field_key: string;
|
|
43
|
+
field_type: FieldUpdatedType;
|
|
44
|
+
field_value?: FieldUpdatedValue;
|
|
45
|
+
/** Field Registry identifier when the field is registry-backed. */
|
|
46
|
+
registry_field_id?: string;
|
|
47
|
+
/** Protocol question identifier when the field is protocol-backed. */
|
|
48
|
+
protocol_field_id?: string;
|
|
49
|
+
form_id: string;
|
|
50
|
+
};
|
|
51
|
+
type DataUpdatedEntry = {
|
|
52
|
+
value: string;
|
|
53
|
+
label: string;
|
|
54
|
+
};
|
|
55
|
+
type DataUpdatedEvent = FunnelStepFields & {
|
|
56
|
+
event_name: 'data:updated';
|
|
57
|
+
data: Record<string, DataUpdatedEntry>;
|
|
58
|
+
form_id: string;
|
|
59
|
+
};
|
|
60
|
+
type FormSubmittedEvent = FunnelStepFields & {
|
|
61
|
+
event_name: 'form:submitted';
|
|
62
|
+
form_key: string;
|
|
63
|
+
};
|
|
64
|
+
//#endregion
|
|
65
|
+
//#region src/storage/storage.d.ts
|
|
66
|
+
/** Every form on the origin shares this one entry, indexed by form ID. */
|
|
67
|
+
declare const FORM_DATA_KEY = "EMBEDDABLES-FORM-DATA";
|
|
68
|
+
interface FormsStorage {
|
|
69
|
+
getItem(key: string): string | null;
|
|
70
|
+
setItem(key: string, value: string): void;
|
|
71
|
+
removeItem(key: string): void;
|
|
72
|
+
}
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region src/core/analytics.d.ts
|
|
75
|
+
type FormsAnalyticsEvent = DataUpdatedEvent | FieldUpdatedEvent | FormSubmittedEvent;
|
|
76
|
+
//#endregion
|
|
77
|
+
export { FieldUpdatedEvent as a, FormsError as c, DataUpdatedEvent as i, SchemaError as l, FORM_DATA_KEY as n, FieldUpdatedType as o, FormsStorage as r, FormSubmittedEvent as s, FormsAnalyticsEvent as t, ValidatorError as u };
|
|
78
|
+
//# sourceMappingURL=index-CmcgIxTH.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-CmcgIxTH.d.ts","names":[],"sources":["../src/errors.ts","../../shared-types/dist/analytics-ingest.types.d.ts","../src/storage/storage.ts","../src/core/analytics.ts"],"mappings":";;;;;;;;;;;;cAWa,mBAAmB;EAClB,YAAA,iBAAiB,UAAU;;;cAO5B,oBAAoB;EACnB,YAAA,iBAAiB,UAAU;;;cAO5B,uBAAuB;EACtB,YAAA,iBAAiB,UAAU;;;;KCtB7B;;;;;;;;KAQA,oBAAoB;KACpB;EACR;EACA;;KA4CQ,oBAAoB;EAC5B;;EAEA;EACA,YAAY;EACZ,cAAc;;EAEd;;EAEA;EACA;;KAEQ;EACR;EACA;;KAEQ,mBAAmB;EAC3B;EACA,MAAM,eAAe;EACrB;;KAEQ,qBAAqB;EAC7B;EACA;;;;;cC/ES;UAEI;EACf,QAAQ;EACR,QAAQ,aAAa;EACrB,WAAW;;;;KCkBD,sBAAsB,mBAAmB,oBAAoB"}
|
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_form = require("./form-
|
|
2
|
+
const require_form = require("./form-CdIfHqNc.cjs");
|
|
3
3
|
exports.FORM_DATA_KEY = require_form.FORM_DATA_KEY;
|
|
4
4
|
exports.FormsError = require_form.FormsError;
|
|
5
5
|
exports.SchemaError = require_form.SchemaError;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { a as FieldUpdatedEvent, c as FormsError, i as DataUpdatedEvent, l as SchemaError, n as FORM_DATA_KEY, o as FieldUpdatedType, r as FormsStorage, s as FormSubmittedEvent, t as FormsAnalyticsEvent, u as ValidatorError } from "./index-CmcgIxTH.js";
|
|
2
|
+
import { A as JsonValue, C as FormValues, D as AnalyticsInstance, E as FormFileRef, O as AnalyticsTrackEvent, S as FormSchema, T as SelectFieldOption, _ as FieldOption, a as FormSchemaMap, b as FieldValidator, c as FormsServerInitOptions, f as SetResult, g as FieldConfig, h as initForms, i as FormInstance, k as AnalyticsTrackResult, l as InitFormsOptions, m as ValidateResult, n as FieldErrors, o as FormServerDataEntry, p as SubmitResult, r as FormCustomValidationsEntry, s as FormsClient, t as CustomValidationsFor, v as FieldType, w as ProtocolFieldId, x as FormFieldKey, y as FieldValidations } from "./form-x4EJcR9A.js";
|
|
3
|
+
export { type AnalyticsInstance, type AnalyticsTrackEvent, type AnalyticsTrackResult, type CustomValidationsFor, type DataUpdatedEvent, FORM_DATA_KEY, type FieldConfig, type FieldErrors, type FieldOption, type FieldType, type FieldUpdatedEvent, type FieldUpdatedType, type FieldValidations, type FieldValidator, type FormCustomValidationsEntry, type FormFieldKey, type FormFileRef, type FormInstance, type FormSchema, type FormSchemaMap, type FormServerDataEntry, type FormSubmittedEvent, type FormValues, type FormsAnalyticsEvent, type FormsClient, FormsError, type FormsServerInitOptions, type FormsStorage, type InitFormsOptions, type JsonValue, type ProtocolFieldId, SchemaError, type SelectFieldOption, type SetResult, type SubmitResult, type ValidateResult, ValidatorError, initForms };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as FORM_DATA_KEY, c as SchemaError, l as ValidatorError, n as initForms, s as FormsError } from "./form-7wmC3G_q.js";
|
|
2
2
|
export { FORM_DATA_KEY, FormsError, SchemaError, ValidatorError, initForms };
|
package/dist/react.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_form = require("./form-
|
|
2
|
+
const require_form = require("./form-CdIfHqNc.cjs");
|
|
3
3
|
let react = require("react");
|
|
4
4
|
let _embeddables_core_react = require("@embeddables/core/react");
|
|
5
5
|
//#region src/react/use-form-store.ts
|
|
@@ -66,14 +66,9 @@ function useRegisteredFormsClient() {
|
|
|
66
66
|
* (`useForm<'signup', OtherSchemas>`) only to work against a map other than the
|
|
67
67
|
* registered one.
|
|
68
68
|
*/
|
|
69
|
-
function useForm({ formId
|
|
69
|
+
function useForm({ formId }) {
|
|
70
70
|
const client = useRegisteredFormsClient();
|
|
71
|
-
const
|
|
72
|
-
customValidationsRef.current = customValidations;
|
|
73
|
-
const form = client === null ? null : client.getForm({
|
|
74
|
-
formId,
|
|
75
|
-
customValidations: customValidationsRef.current
|
|
76
|
-
});
|
|
71
|
+
const form = client === null ? null : client.getForm({ formId });
|
|
77
72
|
const { values, errors } = useFormSnapshot(form);
|
|
78
73
|
return {
|
|
79
74
|
form,
|
|
@@ -107,6 +102,11 @@ function useFormField({ form, key }) {
|
|
|
107
102
|
const setValue = (0, react.useCallback)((value) => {
|
|
108
103
|
setDraft(value);
|
|
109
104
|
}, []);
|
|
105
|
+
const commit = (0, react.useCallback)((value) => {
|
|
106
|
+
if (form === null) return noopSetValue();
|
|
107
|
+
setDraft(value);
|
|
108
|
+
return form.set({ [key]: value });
|
|
109
|
+
}, [form, key]);
|
|
110
110
|
const onBlur = (0, react.useCallback)(async () => {
|
|
111
111
|
if (form === null) return noopSetValue();
|
|
112
112
|
if (draft === committed) return {
|
|
@@ -124,16 +124,111 @@ function useFormField({ form, key }) {
|
|
|
124
124
|
value: void 0,
|
|
125
125
|
error: void 0,
|
|
126
126
|
setValue: () => void 0,
|
|
127
|
+
commit: async () => noopSetValue(),
|
|
127
128
|
onBlur: async () => noopSetValue()
|
|
128
129
|
};
|
|
129
130
|
return {
|
|
130
131
|
value: draft,
|
|
131
132
|
error: errors[key],
|
|
132
133
|
setValue,
|
|
134
|
+
commit,
|
|
133
135
|
onBlur
|
|
134
136
|
};
|
|
135
137
|
}
|
|
136
138
|
//#endregion
|
|
139
|
+
//#region src/react/use-form-file-upload.ts
|
|
140
|
+
const noopSetResult = async () => ({
|
|
141
|
+
ok: false,
|
|
142
|
+
errors: {}
|
|
143
|
+
});
|
|
144
|
+
/**
|
|
145
|
+
* Reactive binding for a `type: file` field: uploads through the public API,
|
|
146
|
+
* commits the returned `FormFileRef`, and exposes a native `<input type="file">`
|
|
147
|
+
* handler.
|
|
148
|
+
*/
|
|
149
|
+
function useFormFileUpload({ form, key }) {
|
|
150
|
+
const { values, errors } = useFormSnapshot(form);
|
|
151
|
+
const [isLoading, setIsLoading] = (0, react.useState)(false);
|
|
152
|
+
const [uploadError, setUploadError] = (0, react.useState)(void 0);
|
|
153
|
+
const uploadGenerationRef = (0, react.useRef)(0);
|
|
154
|
+
(0, react.useEffect)(() => {
|
|
155
|
+
return () => {
|
|
156
|
+
uploadGenerationRef.current += 1;
|
|
157
|
+
setIsLoading(false);
|
|
158
|
+
setUploadError(void 0);
|
|
159
|
+
};
|
|
160
|
+
}, [form, key]);
|
|
161
|
+
const upload = (0, react.useCallback)(async (file) => {
|
|
162
|
+
if (form === null) return noopSetResult();
|
|
163
|
+
const generation = ++uploadGenerationRef.current;
|
|
164
|
+
setIsLoading(true);
|
|
165
|
+
setUploadError(void 0);
|
|
166
|
+
try {
|
|
167
|
+
const ref = await form.uploadFile({
|
|
168
|
+
key,
|
|
169
|
+
file
|
|
170
|
+
});
|
|
171
|
+
if (generation !== uploadGenerationRef.current) return {
|
|
172
|
+
ok: false,
|
|
173
|
+
errors: {}
|
|
174
|
+
};
|
|
175
|
+
return await form.set({ [key]: ref });
|
|
176
|
+
} catch (error) {
|
|
177
|
+
if (generation !== uploadGenerationRef.current) return {
|
|
178
|
+
ok: false,
|
|
179
|
+
errors: {}
|
|
180
|
+
};
|
|
181
|
+
const message = error instanceof require_form.FormsError ? error.message : "File upload failed.";
|
|
182
|
+
setUploadError(message);
|
|
183
|
+
return {
|
|
184
|
+
ok: false,
|
|
185
|
+
errors: {}
|
|
186
|
+
};
|
|
187
|
+
} finally {
|
|
188
|
+
if (generation === uploadGenerationRef.current) setIsLoading(false);
|
|
189
|
+
}
|
|
190
|
+
}, [form, key]);
|
|
191
|
+
const clear = (0, react.useCallback)(async () => {
|
|
192
|
+
if (form === null) return noopSetResult();
|
|
193
|
+
uploadGenerationRef.current += 1;
|
|
194
|
+
setIsLoading(false);
|
|
195
|
+
setUploadError(void 0);
|
|
196
|
+
return form.set({ [key]: null });
|
|
197
|
+
}, [form, key]);
|
|
198
|
+
const onChange = (0, react.useCallback)((event) => {
|
|
199
|
+
const file = event.target.files?.[0];
|
|
200
|
+
if (file === void 0) return;
|
|
201
|
+
upload(file);
|
|
202
|
+
event.target.value = "";
|
|
203
|
+
}, [upload]);
|
|
204
|
+
if (form === null) return {
|
|
205
|
+
value: void 0,
|
|
206
|
+
error: void 0,
|
|
207
|
+
isLoading: false,
|
|
208
|
+
uploadError: void 0,
|
|
209
|
+
upload: async () => noopSetResult(),
|
|
210
|
+
clear: async () => noopSetResult(),
|
|
211
|
+
inputProps: {
|
|
212
|
+
type: "file",
|
|
213
|
+
disabled: true,
|
|
214
|
+
onChange: () => void 0
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
return {
|
|
218
|
+
value: values[key],
|
|
219
|
+
error: errors[key],
|
|
220
|
+
isLoading,
|
|
221
|
+
uploadError,
|
|
222
|
+
upload,
|
|
223
|
+
clear,
|
|
224
|
+
inputProps: {
|
|
225
|
+
type: "file",
|
|
226
|
+
disabled: isLoading,
|
|
227
|
+
onChange
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
//#endregion
|
|
137
232
|
//#region src/react/resolve-core-analytics.ts
|
|
138
233
|
function resolveCoreAnalyticsInstance(core) {
|
|
139
234
|
if (typeof core.getAnalyticsInstance !== "function") return void 0;
|
|
@@ -141,10 +236,11 @@ function resolveCoreAnalyticsInstance(core) {
|
|
|
141
236
|
}
|
|
142
237
|
//#endregion
|
|
143
238
|
//#region src/react/register-forms-client.ts
|
|
144
|
-
function
|
|
239
|
+
function register({ disableAnalyticsFallback, ...options }) {
|
|
240
|
+
const { core } = options;
|
|
145
241
|
const existing = formsByCore.get(core);
|
|
146
242
|
if (existing !== void 0) return existing;
|
|
147
|
-
const analyticsInstance = options.analyticsInstance ?? resolveCoreAnalyticsInstance(core);
|
|
243
|
+
const analyticsInstance = disableAnalyticsFallback ? void 0 : options.analyticsInstance ?? resolveCoreAnalyticsInstance(core);
|
|
148
244
|
const client = require_form.initForms({
|
|
149
245
|
...options,
|
|
150
246
|
core,
|
|
@@ -153,15 +249,39 @@ function registerFormsClient({ core, ...options }) {
|
|
|
153
249
|
formsByCore.set(core, client);
|
|
154
250
|
return client;
|
|
155
251
|
}
|
|
252
|
+
function registerFormsClient(options) {
|
|
253
|
+
return register(options);
|
|
254
|
+
}
|
|
255
|
+
function registerFormsModuleClient(options) {
|
|
256
|
+
return register(options);
|
|
257
|
+
}
|
|
156
258
|
//#endregion
|
|
157
259
|
//#region src/react/forms-module.ts
|
|
158
|
-
|
|
260
|
+
const ANALYTICS_MODULE_KEY = "analytics";
|
|
261
|
+
function resolveInjectedAnalytics(value) {
|
|
262
|
+
if (value === void 0) return void 0;
|
|
263
|
+
if (typeof value !== "object" || value === null) throw new require_form.FormsError("Forms received an invalid Analytics module dependency.");
|
|
264
|
+
const candidate = value;
|
|
265
|
+
if (typeof candidate.trackEvent !== "function" || typeof candidate.getAppUserId !== "function" || typeof candidate.getProjectId !== "function") throw new require_form.FormsError("Forms received an invalid Analytics module dependency.");
|
|
266
|
+
return candidate;
|
|
267
|
+
}
|
|
268
|
+
function forms(options = {}) {
|
|
159
269
|
return {
|
|
160
270
|
key: FORMS_MODULE_KEY,
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
}
|
|
271
|
+
dependencies: [{
|
|
272
|
+
key: ANALYTICS_MODULE_KEY,
|
|
273
|
+
optional: true
|
|
274
|
+
}],
|
|
275
|
+
init: (core, context) => {
|
|
276
|
+
const analyticsInstance = context?.analyticsExcluded ? void 0 : options.analyticsInstance ?? resolveInjectedAnalytics(context?.dependencies.get(ANALYTICS_MODULE_KEY));
|
|
277
|
+
return registerFormsModuleClient({
|
|
278
|
+
core,
|
|
279
|
+
customValidations: context?.parameters?.customValidations ?? options.customValidations,
|
|
280
|
+
serverFormData: context?.parameters?.serverFormData ?? options.serverFormData,
|
|
281
|
+
analyticsInstance,
|
|
282
|
+
disableAnalyticsFallback: context?.analyticsExcluded
|
|
283
|
+
});
|
|
284
|
+
}
|
|
165
285
|
};
|
|
166
286
|
}
|
|
167
287
|
//#endregion
|
|
@@ -171,5 +291,6 @@ exports.registerFormsClient = registerFormsClient;
|
|
|
171
291
|
exports.useForm = useForm;
|
|
172
292
|
exports.useFormErrors = useFormErrors;
|
|
173
293
|
exports.useFormField = useFormField;
|
|
294
|
+
exports.useFormFileUpload = useFormFileUpload;
|
|
174
295
|
|
|
175
296
|
//# sourceMappingURL=react.cjs.map
|