@embeddables/forms 0.0.4 → 0.0.5
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/dist/{form-CbU5ezg7.d.ts → index-qfBhdk5L.d.ts} +75 -2
- package/dist/index-qfBhdk5L.d.ts.map +1 -0
- package/dist/index.d.ts +2 -76
- package/dist/react.cjs +4 -0
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.ts +5 -2
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +4 -1
- package/dist/react.js.map +1 -1
- package/package.json +3 -3
- package/dist/form-CbU5ezg7.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
|
@@ -1,4 +1,27 @@
|
|
|
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
|
|
2
25
|
//#region ../shared-types/dist/json.types.d.ts
|
|
3
26
|
/**
|
|
4
27
|
* Recursive JSON value, compatible with JSONB column values and public
|
|
@@ -61,6 +84,15 @@ type ProtocolFieldId<TSchema extends FormSchema> = [TSchema] extends [FormSchema
|
|
|
61
84
|
protocolFieldId: string;
|
|
62
85
|
}>['protocolFieldId'];
|
|
63
86
|
//#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
|
|
64
96
|
//#region ../shared-types/dist/analytics-instance.types.d.ts
|
|
65
97
|
/**
|
|
66
98
|
* Hono-free analytics client surface other SDKs accept without depending on
|
|
@@ -95,6 +127,47 @@ interface AnalyticsInstance<TEvent = AnalyticsTrackEvent> {
|
|
|
95
127
|
getProjectId(): string;
|
|
96
128
|
}
|
|
97
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
|
|
98
171
|
//#region src/core/form.d.ts
|
|
99
172
|
/** Per-key validation errors. An empty object means the operation succeeded. */
|
|
100
173
|
type FieldErrors<TSchema extends FormSchema> = Readonly<Partial<Record<FormFieldKey<TSchema>, readonly string[]>>>;
|
|
@@ -192,5 +265,5 @@ interface FormsClient<TSchemas extends FormSchemaMap = FormSchemaMap> {
|
|
|
192
265
|
*/
|
|
193
266
|
declare function initForms<const TSchemas extends FormSchemaMap>(options: InitFormsOptions<TSchemas>): FormsClient<TSchemas>;
|
|
194
267
|
//#endregion
|
|
195
|
-
export {
|
|
196
|
-
//# sourceMappingURL=
|
|
268
|
+
export { FormsError as A, FieldValidations as C, FormValues as D, FormSchema as E, ValidatorError as M, ProtocolFieldId as O, FieldType as S, FormFieldKey as T, AnalyticsTrackEvent as _, FormsClient as a, FormsStorage as b, SubmitResult as c, FormsAnalyticsEvent as d, DataUpdatedEvent as f, AnalyticsInstance as g, FormSubmittedEvent as h, FormSchemaMap as i, SchemaError as j, JsonValue as k, ValidateResult as l, FieldUpdatedType as m, FieldErrors as n, InitFormsOptions as o, FieldUpdatedEvent as p, FormInstance as r, SetResult as s, CustomValidationsFor as t, initForms as u, AnalyticsTrackResult as v, FieldValidator as w, FieldConfig as x, FORM_DATA_KEY as y };
|
|
269
|
+
//# sourceMappingURL=index-qfBhdk5L.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-qfBhdk5L.d.ts","names":[],"sources":["../src/errors.ts","../../shared-types/dist/json.types.d.ts","../src/core/config.ts","../src/storage/storage.ts","../../shared-types/dist/analytics-instance.types.d.ts","../../shared-types/dist/analytics-ingest.types.d.ts","../src/core/analytics.ts","../src/core/form.ts"],"mappings":";;;;;;;;;;;;cAWa,mBAAmB;EAClB,YAAA,iBAAiB,UAAU;;;cAO5B,oBAAoB;EACnB,YAAA,iBAAiB,UAAU;;;cAO5B,uBAAuB;EACtB,YAAA,iBAAiB,UAAU;;;;;;;;KCxB7B,+CAA+C;GACtD,cAAc;;;;KCHP;;UAMF;EACR;EACA;EACA;EACA;EACA;EACA;EACA,MAAM;;KAGI,eAAe,eAAe,YAAY,cAAc;EAClE,OAAO;EACP,QAAQ,SAAS,eAAe;;UAUxB,oBAAoB,cAAc;WACjC;WACA;WACA;WACA;WACA;;WAEA;;WAEA;WACA,iBAAiB;;WAEjB,SAAS,eAAe,iBAAiB;;UAG1C,eAAe,cAAc;WAC5B;WACA;WACA,MAAM;WACN,cAAc,oBAAoB;WAGlC;WACA;;KAUC,iBAAiB,KAAK,YAAY,eAAe,MAAK;KAEtD,sBAAsB,KAAK,YAAY,oBAAoB,MAAK;UAE3D;WACN;WACA;WACA,iBAAiB;;KAGvB,SAAS,gBAAgB,cAAc;KAEhC,aAAa,gBAAgB,cAAc,SAAS;KAEpD,WAAW,gBAAgB,iBACpC,KAAK,SAAS,YAAY,WAAW,iBAAiB;;KAI7C,gBAAgB,gBAAgB,eAAe,kBAAkB,uBAEzE,QAAQ,SAAS;EAAY;;;;;cC/EpB;UAEI;EACf,QAAQ;EACR,QAAQ,aAAa;EACrB,WAAW;;;;;;;;;;;;;;;UCCI;EACb;GACC;;;UAGY;EACb;EACA;EACA;;;;;;;UAOa,kBAAkB,SAAS;EACxC,WAAW,OAAO,kBAAkB,WAAW,QAAQ;;EAEvD;EACA;;;;KCxBQ;;;;;;;;KAQA,oBAAoB;KACpB;EACR;EACA;;KAsBQ,oBAAoB;EAC5B;;EAEA;EACA,YAAY;EACZ,cAAc;;EAEd;;EAEA;;KAEQ;EACR;EACA;;KAEQ,mBAAmB;EAC3B;EACA,MAAM,eAAe;;KAMb,qBAAqB;EAC7B;EACA;;;;KCpCQ,sBAAsB,mBAAmB,oBAAoB;;;;KCE7D,YAAY,gBAAgB,cAAc,SACpD,QAAQ,OAAO,aAAa;UAGb,UAAU,gBAAgB;EACzC;EACA,QAAQ,YAAY;;EAEpB;;UAGe,aAAa,gBAAgB;EAC5C;EACA,QAAQ,YAAY;EACpB,QAAQ,QAAQ,WAAW;EAC3B;;UAGe,eAAe,gBAAgB;EAC9C;EACA,QAAQ,YAAY;EACpB,QAAQ,QAAQ,WAAW;;UAGZ,aAAa,gBAAgB;WACnC,KAAK;;;;;;;EAOd,IAAI,OAAO,QAAQ,WAAW,YAAY,QAAQ,UAAU;;EAE5D,IAAI,UAAU,aAAa,UAAU,KAAK,IAAI,WAAW,SAAS;;;;;;EAMlE,0BAA0B,UAAU,gBAAgB,UAClD,iBAAiB,IAEf,WAAW,SAAS,QAAQ;IAA6B,iBAAiB;;EAE9E,UAAU,QAAQ,WAAW;;;;;;;;;EAS7B,UAAU,QAAQ,aAAa;;;;;;;;;;EAU/B,SAAS,QAAQ,QAAQ,WAAW,YAAY,QAAQ,eAAe;EACvE,UAAU,YAAY;EACtB;;EAEA,UAAU;;;KA6CA,gBAAgB,SAAS,eAAe;KAExC,qBAAqB,gBAAgB,0BACrC,KAAK,aAAa,YAAY;UAOzB,iBAAiB,iBAAiB,gBAAgB;EACjE,MAAM;;EAEN,SAAS;EACT,oBAAoB;;UAGL,YAAY,iBAAiB,gBAAgB;;;;;;;;;;;;;EAa5D,QAAQ,gBAAgB,mBAAmB;IACzC,QAAQ;IACR,oBAAoB,qBAAqB,SAAS;MAChD,aAAa,SAAS;;;;;;iBAOZ,gBAAgB,iBAAiB,eAC/C,SAAS,iBAAiB,YACzB,YAAY"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,76 +1,2 @@
|
|
|
1
|
-
import { S as
|
|
2
|
-
|
|
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 src/storage/storage.d.ts
|
|
26
|
-
/** Every form on the origin shares this one entry, indexed by form ID. */
|
|
27
|
-
declare const FORM_DATA_KEY = "EMBEDDABLES-FORM-DATA";
|
|
28
|
-
interface FormsStorage {
|
|
29
|
-
getItem(key: string): string | null;
|
|
30
|
-
setItem(key: string, value: string): void;
|
|
31
|
-
removeItem(key: string): void;
|
|
32
|
-
}
|
|
33
|
-
//#endregion
|
|
34
|
-
//#region ../shared-types/dist/analytics-ingest.types.d.ts
|
|
35
|
-
type FieldUpdatedType = 'text' | 'email' | 'number' | 'boolean' | 'select' | 'multiselect' | 'json';
|
|
36
|
-
/**
|
|
37
|
-
* Raw `field_value` accepted by ingest. Every forms-sdk `ValueOfFieldType` is a
|
|
38
|
-
* JSON value — scalar (`text`/`email`/`select` → string, `number` → number,
|
|
39
|
-
* `boolean` → boolean), `multiselect` → `string[]`, `json` → arbitrary JSON —
|
|
40
|
-
* so the contract collapses to `JsonValue`; the runtime ingest schema is what
|
|
41
|
-
* bounds each shape.
|
|
42
|
-
*/
|
|
43
|
-
type FieldUpdatedValue = JsonValue;
|
|
44
|
-
type FunnelStepFields = {
|
|
45
|
-
is_funnel_step?: boolean;
|
|
46
|
-
funnel_step_label?: string;
|
|
47
|
-
};
|
|
48
|
-
type FieldUpdatedEvent = FunnelStepFields & {
|
|
49
|
-
event_name: 'field:updated';
|
|
50
|
-
/** Schema key of the updated field. */
|
|
51
|
-
field_key: string;
|
|
52
|
-
field_type: FieldUpdatedType;
|
|
53
|
-
field_value?: FieldUpdatedValue;
|
|
54
|
-
/** Field Registry identifier when the field is registry-backed. */
|
|
55
|
-
registry_field_id?: string;
|
|
56
|
-
/** Protocol question identifier when the field is protocol-backed. */
|
|
57
|
-
protocol_field_id?: string;
|
|
58
|
-
};
|
|
59
|
-
type DataUpdatedEntry = {
|
|
60
|
-
value: string;
|
|
61
|
-
label: string;
|
|
62
|
-
};
|
|
63
|
-
type DataUpdatedEvent = FunnelStepFields & {
|
|
64
|
-
event_name: 'data:updated';
|
|
65
|
-
data: Record<string, DataUpdatedEntry>;
|
|
66
|
-
};
|
|
67
|
-
type FormSubmittedEvent = FunnelStepFields & {
|
|
68
|
-
event_name: 'form:submitted';
|
|
69
|
-
form_key: string;
|
|
70
|
-
};
|
|
71
|
-
//#endregion
|
|
72
|
-
//#region src/core/analytics.d.ts
|
|
73
|
-
type FormsAnalyticsEvent = DataUpdatedEvent | FieldUpdatedEvent | FormSubmittedEvent;
|
|
74
|
-
//#endregion
|
|
75
|
-
export { type AnalyticsInstance, type AnalyticsTrackEvent, type AnalyticsTrackResult, type CustomValidationsFor, type DataUpdatedEvent, FORM_DATA_KEY, type FieldConfig, type FieldErrors, type FieldType, type FieldUpdatedEvent, type FieldUpdatedType, type FieldValidations, type FieldValidator, type FormFieldKey, type FormInstance, type FormSchema, type FormSchemaMap, type FormSubmittedEvent, type FormValues, type FormsAnalyticsEvent, type FormsClient, FormsError, type FormsStorage, type InitFormsOptions, type JsonValue, type ProtocolFieldId, SchemaError, type SetResult, type SubmitResult, type ValidateResult, ValidatorError, initForms };
|
|
76
|
-
//# sourceMappingURL=index.d.ts.map
|
|
1
|
+
import { A as FormsError, C as FieldValidations, D as FormValues, E as FormSchema, M as ValidatorError, O as ProtocolFieldId, S as FieldType, T as FormFieldKey, _ as AnalyticsTrackEvent, a as FormsClient, b as FormsStorage, c as SubmitResult, d as FormsAnalyticsEvent, f as DataUpdatedEvent, g as AnalyticsInstance, h as FormSubmittedEvent, i as FormSchemaMap, j as SchemaError, k as JsonValue, l as ValidateResult, m as FieldUpdatedType, n as FieldErrors, o as InitFormsOptions, p as FieldUpdatedEvent, r as FormInstance, s as SetResult, t as CustomValidationsFor, u as initForms, v as AnalyticsTrackResult, w as FieldValidator, x as FieldConfig, y as FORM_DATA_KEY } from "./index-qfBhdk5L.js";
|
|
2
|
+
export { type AnalyticsInstance, type AnalyticsTrackEvent, type AnalyticsTrackResult, type CustomValidationsFor, type DataUpdatedEvent, FORM_DATA_KEY, type FieldConfig, type FieldErrors, type FieldType, type FieldUpdatedEvent, type FieldUpdatedType, type FieldValidations, type FieldValidator, type FormFieldKey, type FormInstance, type FormSchema, type FormSchemaMap, type FormSubmittedEvent, type FormValues, type FormsAnalyticsEvent, type FormsClient, FormsError, type FormsStorage, type InitFormsOptions, type JsonValue, type ProtocolFieldId, SchemaError, type SetResult, type SubmitResult, type ValidateResult, ValidatorError, initForms };
|
package/dist/react.cjs
CHANGED
|
@@ -47,6 +47,9 @@ const FORMS_MODULE_KEY = "forms";
|
|
|
47
47
|
* from provider context, not from here.
|
|
48
48
|
*/
|
|
49
49
|
const formsByCore = /* @__PURE__ */ new WeakMap();
|
|
50
|
+
function getRegisteredFormsClient(core) {
|
|
51
|
+
return formsByCore.get(core);
|
|
52
|
+
}
|
|
50
53
|
//#endregion
|
|
51
54
|
//#region src/react/use-forms.ts
|
|
52
55
|
/** @internal Product hooks read the module client from provider context. */
|
|
@@ -163,6 +166,7 @@ function forms(options) {
|
|
|
163
166
|
}
|
|
164
167
|
//#endregion
|
|
165
168
|
exports.forms = forms;
|
|
169
|
+
exports.getRegisteredFormsClient = getRegisteredFormsClient;
|
|
166
170
|
exports.registerFormsClient = registerFormsClient;
|
|
167
171
|
exports.useForm = useForm;
|
|
168
172
|
exports.useFormErrors = useFormErrors;
|
package/dist/react.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.cjs","names":["useRef","useCallback","useSyncExternalStore","useEmbeddablesModule","useRef","useState","useCallback","initForms"],"sources":["../src/react/use-form-store.ts","../src/react/forms-registry.ts","../src/react/use-forms.ts","../src/react/use-form.ts","../src/react/use-form-errors.ts","../src/react/use-form-field.ts","../src/react/resolve-core-analytics.ts","../src/react/register-forms-client.ts","../src/react/forms-module.ts"],"sourcesContent":["import { useCallback, useRef, useSyncExternalStore } from 'react'\n\nimport type { FormSchema, FormValues } from '../core/config.js'\nimport type { FieldErrors, FormInstance } from '../core/form.js'\n\nexport type FormSnapshot<TSchema extends FormSchema> = Readonly<{\n values: Partial<FormValues<TSchema>>\n errors: FieldErrors<TSchema>\n}>\n\nconst EMPTY_SNAPSHOT: FormSnapshot<FormSchema> = Object.freeze({\n values: {},\n errors: {},\n})\n\nfunction createSnapshot<TSchema extends FormSchema>(\n form: FormInstance<TSchema>,\n): FormSnapshot<TSchema> {\n return Object.freeze({\n values: form.getAll(),\n errors: form.errors(),\n })\n}\n\ninterface CachedSnapshot<TSchema extends FormSchema> {\n readonly form: FormInstance<TSchema>\n readonly snapshot: FormSnapshot<TSchema>\n}\n\nexport function useFormSnapshot<TSchema extends FormSchema>(\n form: FormInstance<TSchema> | null,\n): FormSnapshot<TSchema> {\n const cachedRef = useRef<CachedSnapshot<TSchema> | null>(null)\n const emptyRef = useRef<FormSnapshot<TSchema>>(EMPTY_SNAPSHOT as FormSnapshot<TSchema>)\n\n const subscribe = useCallback(\n (listener: () => void) => {\n if (form === null) return () => undefined\n return form.subscribe(() => {\n cachedRef.current = { form, snapshot: createSnapshot(form) }\n listener()\n })\n },\n [form],\n )\n\n const getSnapshot = useCallback((): FormSnapshot<TSchema> => {\n if (form === null) {\n // * Otherwise a later A -> null -> mutate A -> A sequence would resurrect\n // * a snapshot cached before the detach, missing the mutation in between.\n cachedRef.current = null\n return emptyRef.current\n }\n // * A cached snapshot from a previous form instance must not survive a\n // * form change — recompute so switching forms without a mutation still\n // * returns the new form's values and errors.\n if (cachedRef.current === null || cachedRef.current.form !== form) {\n cachedRef.current = { form, snapshot: createSnapshot(form) }\n }\n return cachedRef.current.snapshot\n }, [form])\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot)\n}\n","import type { FormSchemaMap, FormsClient } from '../core/form.js'\n\nexport const FORMS_MODULE_KEY = 'forms'\n\n/**\n * Idempotence guard for `registerFormsClient` only — React reads the client\n * from provider context, not from here.\n */\nexport const formsByCore = new WeakMap<object, FormsClient<FormSchemaMap>>()\n","import { useEmbeddablesModule } from '@embeddables/core/react'\n\nimport { FORMS_MODULE_KEY } from './forms-registry.js'\n\nimport type { FormSchemaMap, FormsClient, InitFormsOptions } from '../core/form.js'\n\nexport type FormsReactOptions<TSchemas extends FormSchemaMap = FormSchemaMap> = Omit<\n InitFormsOptions<TSchemas>,\n 'core'\n>\n\n/** @internal Product hooks read the module client from provider context. */\nexport function useRegisteredFormsClient<\n TSchemas extends FormSchemaMap = FormSchemaMap,\n>(): FormsClient<TSchemas> | null {\n return useEmbeddablesModule<FormsClient<TSchemas>>({ key: FORMS_MODULE_KEY })\n}\n","import { useRef } from 'react'\n\nimport { useFormSnapshot } from './use-form-store.js'\nimport { useRegisteredFormsClient } from './use-forms.js'\n\nimport type { CustomValidationsFor, FormInstance, FormSchemaMap } from '../core/form.js'\nimport type { RegisteredSchemas } from './schema-registry.js'\n\n/**\n * Reactive binding for one declared form.\n *\n * Takes no type arguments: `TFormId` is inferred from `formId`, and the schema\n * map comes from the registry `em build` augments. Pass both explicitly\n * (`useForm<'signup', OtherSchemas>`) only to work against a map other than the\n * registered one.\n */\nexport function useForm<\n TFormId extends keyof TSchemas & string,\n TSchemas extends FormSchemaMap = RegisteredSchemas,\n>({\n formId,\n customValidations,\n}: {\n formId: TFormId\n customValidations?: CustomValidationsFor<TSchemas[TFormId]>\n}): {\n form: FormInstance<TSchemas[TFormId]> | null\n values: ReturnType<typeof useFormSnapshot<TSchemas[TFormId]>>['values']\n errors: ReturnType<typeof useFormSnapshot<TSchemas[TFormId]>>['errors']\n} {\n const client = useRegisteredFormsClient<TSchemas>()\n // * Held in a ref because only the first call for a form id builds the\n // * instance; a later render passing new validators must not look like a change.\n const customValidationsRef = useRef(customValidations)\n customValidationsRef.current = customValidations\n\n // * Safe to call on every render: the client returns one instance per form id.\n const form =\n client === null\n ? null\n : client.getForm({ formId, customValidations: customValidationsRef.current })\n const { values, errors } = useFormSnapshot(form)\n\n return { form, values, errors }\n}\n\n// prueba de la colisión\n","import { useFormSnapshot } from './use-form-store.js'\n\nimport type { FormSchema } from '../core/config.js'\nimport type { FieldErrors, FormInstance } from '../core/form.js'\n\nexport function useFormErrors<TSchema extends FormSchema>(\n form: FormInstance<TSchema> | null,\n): FieldErrors<TSchema> {\n const { errors } = useFormSnapshot(form)\n return errors\n}\n","import { useCallback, useEffect, useState } from 'react'\n\nimport { useFormSnapshot } from './use-form-store.js'\n\nimport type { FormFieldKey, FormSchema, FormValues } from '../core/config.js'\nimport type { FieldErrors, FormInstance, SetResult } from '../core/form.js'\n\nconst noopSetValue = async (): Promise<SetResult<FormSchema>> => ({\n ok: false,\n errors: {},\n})\n\nexport function useFormField<const TSchema extends FormSchema, K extends FormFieldKey<TSchema>>({\n form,\n key,\n}: {\n form: FormInstance<TSchema> | null\n key: K\n}): {\n value: FormValues<TSchema>[K] | undefined\n error: readonly string[] | undefined\n setValue: (value: FormValues<TSchema>[K]) => void\n onBlur: () => Promise<SetResult<TSchema>>\n} {\n const { values, errors } = useFormSnapshot(form)\n const committed = values[key]\n const [draft, setDraft] = useState<FormValues<TSchema>[K] | undefined>(committed)\n\n useEffect(() => {\n setDraft(committed)\n }, [form, key, committed])\n\n const setValue = useCallback((value: FormValues<TSchema>[K]) => {\n setDraft(value)\n }, [])\n\n const onBlur = useCallback(async (): Promise<SetResult<TSchema>> => {\n if (form === null) return noopSetValue()\n if (draft === committed) {\n return { ok: true, errors: {} as FieldErrors<TSchema> }\n }\n return form.set({ [key]: draft } as Partial<FormValues<TSchema>>)\n }, [committed, draft, form, key])\n\n if (form === null) {\n return {\n value: undefined,\n error: undefined,\n setValue: () => undefined,\n onBlur: async () => noopSetValue(),\n }\n }\n\n return {\n value: draft,\n error: errors[key],\n setValue,\n onBlur,\n }\n}\n","import type { AnalyticsInstance } from '@embeddables/core'\nimport type { EmbeddablesInstance } from '@embeddables/core'\n\nexport function resolveCoreAnalyticsInstance(\n core: EmbeddablesInstance,\n): AnalyticsInstance | undefined {\n if (typeof core.getAnalyticsInstance !== 'function') return undefined\n return core.getAnalyticsInstance() ?? undefined\n}\n","import { initForms } from '../core/form.js'\nimport { formsByCore } from './forms-registry.js'\nimport { resolveCoreAnalyticsInstance } from './resolve-core-analytics.js'\n\nimport type { FormSchemaMap, FormsClient, InitFormsOptions } from '../core/form.js'\n\nexport function registerFormsClient<const TSchemas extends FormSchemaMap>({\n core,\n ...options\n}: InitFormsOptions<TSchemas>): FormsClient<TSchemas> {\n const existing = formsByCore.get(core) as FormsClient<TSchemas> | undefined\n if (existing !== undefined) return existing\n\n const analyticsInstance = options.analyticsInstance ?? resolveCoreAnalyticsInstance(core)\n\n const client = initForms({ ...options, core, analyticsInstance })\n formsByCore.set(core, client as FormsClient<FormSchemaMap>)\n return client\n}\n","import type { EmbeddablesReactModule } from '@embeddables/core/react'\n\nimport { FORMS_MODULE_KEY } from './forms-registry.js'\nimport { registerFormsClient } from './register-forms-client.js'\n\nimport type { FormSchemaMap, FormsClient } from '../core/form.js'\nimport type { FormsReactOptions } from './use-forms.js'\n\nexport type { FormsReactOptions } from './use-forms.js'\n\nexport function forms<const TSchemas extends FormSchemaMap>(\n options: FormsReactOptions<TSchemas>,\n): EmbeddablesReactModule<FormsClient<TSchemas>> {\n return {\n key: FORMS_MODULE_KEY,\n init: (core) => registerFormsClient({ core, ...options }),\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"react.cjs","names":["useRef","useCallback","useSyncExternalStore","useEmbeddablesModule","useRef","useState","useCallback","initForms"],"sources":["../src/react/use-form-store.ts","../src/react/forms-registry.ts","../src/react/use-forms.ts","../src/react/use-form.ts","../src/react/use-form-errors.ts","../src/react/use-form-field.ts","../src/react/resolve-core-analytics.ts","../src/react/register-forms-client.ts","../src/react/forms-module.ts"],"sourcesContent":["import { useCallback, useRef, useSyncExternalStore } from 'react'\n\nimport type { FormSchema, FormValues } from '../core/config.js'\nimport type { FieldErrors, FormInstance } from '../core/form.js'\n\nexport type FormSnapshot<TSchema extends FormSchema> = Readonly<{\n values: Partial<FormValues<TSchema>>\n errors: FieldErrors<TSchema>\n}>\n\nconst EMPTY_SNAPSHOT: FormSnapshot<FormSchema> = Object.freeze({\n values: {},\n errors: {},\n})\n\nfunction createSnapshot<TSchema extends FormSchema>(\n form: FormInstance<TSchema>,\n): FormSnapshot<TSchema> {\n return Object.freeze({\n values: form.getAll(),\n errors: form.errors(),\n })\n}\n\ninterface CachedSnapshot<TSchema extends FormSchema> {\n readonly form: FormInstance<TSchema>\n readonly snapshot: FormSnapshot<TSchema>\n}\n\nexport function useFormSnapshot<TSchema extends FormSchema>(\n form: FormInstance<TSchema> | null,\n): FormSnapshot<TSchema> {\n const cachedRef = useRef<CachedSnapshot<TSchema> | null>(null)\n const emptyRef = useRef<FormSnapshot<TSchema>>(EMPTY_SNAPSHOT as FormSnapshot<TSchema>)\n\n const subscribe = useCallback(\n (listener: () => void) => {\n if (form === null) return () => undefined\n return form.subscribe(() => {\n cachedRef.current = { form, snapshot: createSnapshot(form) }\n listener()\n })\n },\n [form],\n )\n\n const getSnapshot = useCallback((): FormSnapshot<TSchema> => {\n if (form === null) {\n // * Otherwise a later A -> null -> mutate A -> A sequence would resurrect\n // * a snapshot cached before the detach, missing the mutation in between.\n cachedRef.current = null\n return emptyRef.current\n }\n // * A cached snapshot from a previous form instance must not survive a\n // * form change — recompute so switching forms without a mutation still\n // * returns the new form's values and errors.\n if (cachedRef.current === null || cachedRef.current.form !== form) {\n cachedRef.current = { form, snapshot: createSnapshot(form) }\n }\n return cachedRef.current.snapshot\n }, [form])\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot)\n}\n","import type { FormSchemaMap, FormsClient } from '../core/form.js'\n\nexport const FORMS_MODULE_KEY = 'forms'\n\n/**\n * Idempotence guard for `registerFormsClient` only — React reads the client\n * from provider context, not from here.\n */\nexport const formsByCore = new WeakMap<object, FormsClient<FormSchemaMap>>()\n\nexport function getRegisteredFormsClient(core: object): FormsClient<FormSchemaMap> | undefined {\n return formsByCore.get(core)\n}\n","import { useEmbeddablesModule } from '@embeddables/core/react'\n\nimport { FORMS_MODULE_KEY } from './forms-registry.js'\n\nimport type { FormSchemaMap, FormsClient, InitFormsOptions } from '../core/form.js'\n\nexport type FormsReactOptions<TSchemas extends FormSchemaMap = FormSchemaMap> = Omit<\n InitFormsOptions<TSchemas>,\n 'core'\n>\n\n/** @internal Product hooks read the module client from provider context. */\nexport function useRegisteredFormsClient<\n TSchemas extends FormSchemaMap = FormSchemaMap,\n>(): FormsClient<TSchemas> | null {\n return useEmbeddablesModule<FormsClient<TSchemas>>({ key: FORMS_MODULE_KEY })\n}\n","import { useRef } from 'react'\n\nimport { useFormSnapshot } from './use-form-store.js'\nimport { useRegisteredFormsClient } from './use-forms.js'\n\nimport type { CustomValidationsFor, FormInstance, FormSchemaMap } from '../core/form.js'\nimport type { RegisteredSchemas } from './schema-registry.js'\n\n/**\n * Reactive binding for one declared form.\n *\n * Takes no type arguments: `TFormId` is inferred from `formId`, and the schema\n * map comes from the registry `em build` augments. Pass both explicitly\n * (`useForm<'signup', OtherSchemas>`) only to work against a map other than the\n * registered one.\n */\nexport function useForm<\n TFormId extends keyof TSchemas & string,\n TSchemas extends FormSchemaMap = RegisteredSchemas,\n>({\n formId,\n customValidations,\n}: {\n formId: TFormId\n customValidations?: CustomValidationsFor<TSchemas[TFormId]>\n}): {\n form: FormInstance<TSchemas[TFormId]> | null\n values: ReturnType<typeof useFormSnapshot<TSchemas[TFormId]>>['values']\n errors: ReturnType<typeof useFormSnapshot<TSchemas[TFormId]>>['errors']\n} {\n const client = useRegisteredFormsClient<TSchemas>()\n // * Held in a ref because only the first call for a form id builds the\n // * instance; a later render passing new validators must not look like a change.\n const customValidationsRef = useRef(customValidations)\n customValidationsRef.current = customValidations\n\n // * Safe to call on every render: the client returns one instance per form id.\n const form =\n client === null\n ? null\n : client.getForm({ formId, customValidations: customValidationsRef.current })\n const { values, errors } = useFormSnapshot(form)\n\n return { form, values, errors }\n}\n","import { useFormSnapshot } from './use-form-store.js'\n\nimport type { FormSchema } from '../core/config.js'\nimport type { FieldErrors, FormInstance } from '../core/form.js'\n\nexport function useFormErrors<TSchema extends FormSchema>(\n form: FormInstance<TSchema> | null,\n): FieldErrors<TSchema> {\n const { errors } = useFormSnapshot(form)\n return errors\n}\n","import { useCallback, useEffect, useState } from 'react'\n\nimport { useFormSnapshot } from './use-form-store.js'\n\nimport type { FormFieldKey, FormSchema, FormValues } from '../core/config.js'\nimport type { FieldErrors, FormInstance, SetResult } from '../core/form.js'\n\nconst noopSetValue = async (): Promise<SetResult<FormSchema>> => ({\n ok: false,\n errors: {},\n})\n\nexport function useFormField<const TSchema extends FormSchema, K extends FormFieldKey<TSchema>>({\n form,\n key,\n}: {\n form: FormInstance<TSchema> | null\n key: K\n}): {\n value: FormValues<TSchema>[K] | undefined\n error: readonly string[] | undefined\n setValue: (value: FormValues<TSchema>[K]) => void\n onBlur: () => Promise<SetResult<TSchema>>\n} {\n const { values, errors } = useFormSnapshot(form)\n const committed = values[key]\n const [draft, setDraft] = useState<FormValues<TSchema>[K] | undefined>(committed)\n\n useEffect(() => {\n setDraft(committed)\n }, [form, key, committed])\n\n const setValue = useCallback((value: FormValues<TSchema>[K]) => {\n setDraft(value)\n }, [])\n\n const onBlur = useCallback(async (): Promise<SetResult<TSchema>> => {\n if (form === null) return noopSetValue()\n if (draft === committed) {\n return { ok: true, errors: {} as FieldErrors<TSchema> }\n }\n return form.set({ [key]: draft } as Partial<FormValues<TSchema>>)\n }, [committed, draft, form, key])\n\n if (form === null) {\n return {\n value: undefined,\n error: undefined,\n setValue: () => undefined,\n onBlur: async () => noopSetValue(),\n }\n }\n\n return {\n value: draft,\n error: errors[key],\n setValue,\n onBlur,\n }\n}\n","import type { AnalyticsInstance } from '@embeddables/core'\nimport type { EmbeddablesInstance } from '@embeddables/core'\n\nexport function resolveCoreAnalyticsInstance(\n core: EmbeddablesInstance,\n): AnalyticsInstance | undefined {\n if (typeof core.getAnalyticsInstance !== 'function') return undefined\n return core.getAnalyticsInstance() ?? undefined\n}\n","import { initForms } from '../core/form.js'\nimport { formsByCore } from './forms-registry.js'\nimport { resolveCoreAnalyticsInstance } from './resolve-core-analytics.js'\n\nimport type { FormSchemaMap, FormsClient, InitFormsOptions } from '../core/form.js'\n\nexport function registerFormsClient<const TSchemas extends FormSchemaMap>({\n core,\n ...options\n}: InitFormsOptions<TSchemas>): FormsClient<TSchemas> {\n const existing = formsByCore.get(core) as FormsClient<TSchemas> | undefined\n if (existing !== undefined) return existing\n\n const analyticsInstance = options.analyticsInstance ?? resolveCoreAnalyticsInstance(core)\n\n const client = initForms({ ...options, core, analyticsInstance })\n formsByCore.set(core, client as FormsClient<FormSchemaMap>)\n return client\n}\n","import type { EmbeddablesReactModule } from '@embeddables/core/react'\n\nimport { FORMS_MODULE_KEY } from './forms-registry.js'\nimport { registerFormsClient } from './register-forms-client.js'\n\nimport type { FormSchemaMap, FormsClient } from '../core/form.js'\nimport type { FormsReactOptions } from './use-forms.js'\n\nexport type { FormsReactOptions } from './use-forms.js'\n\nexport function forms<const TSchemas extends FormSchemaMap>(\n options: FormsReactOptions<TSchemas>,\n): EmbeddablesReactModule<FormsClient<TSchemas>> {\n return {\n key: FORMS_MODULE_KEY,\n init: (core) => registerFormsClient({ core, ...options }),\n }\n}\n"],"mappings":"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"}
|
package/dist/react.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { D as FormValues, E as FormSchema, T as FormFieldKey, a as FormsClient, i as FormSchemaMap, n as FieldErrors, o as InitFormsOptions, r as FormInstance, s as SetResult, t as CustomValidationsFor } from "./index-qfBhdk5L.js";
|
|
2
2
|
import { EmbeddablesReactModule } from "@embeddables/core/react";
|
|
3
3
|
//#region src/react/use-form-store.d.ts
|
|
4
4
|
type FormSnapshot<TSchema extends FormSchema> = Readonly<{
|
|
@@ -76,5 +76,8 @@ declare function forms<const TSchemas extends FormSchemaMap>(options: FormsReact
|
|
|
76
76
|
//#region src/react/register-forms-client.d.ts
|
|
77
77
|
declare function registerFormsClient<const TSchemas extends FormSchemaMap>({ core, ...options }: InitFormsOptions<TSchemas>): FormsClient<TSchemas>;
|
|
78
78
|
//#endregion
|
|
79
|
-
|
|
79
|
+
//#region src/react/forms-registry.d.ts
|
|
80
|
+
declare function getRegisteredFormsClient(core: object): FormsClient<FormSchemaMap> | undefined;
|
|
81
|
+
//#endregion
|
|
82
|
+
export { type EmbeddablesSchemaRegistry, type FormsReactOptions, type RegisteredSchemas, forms, getRegisteredFormsClient, registerFormsClient, useForm, useFormErrors, useFormField };
|
|
80
83
|
//# sourceMappingURL=react.d.ts.map
|
package/dist/react.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.d.ts","names":[],"sources":["../src/react/use-form-store.ts","../src/react/schema-registry.ts","../src/react/use-form.ts","../src/react/use-form-errors.ts","../src/react/use-form-field.ts","../src/react/use-forms.ts","../src/react/forms-module.ts","../src/react/register-forms-client.ts"],"mappings":";;;KAKY,aAAa,gBAAgB,cAAc;EACrD,QAAQ,QAAQ,WAAW;EAC3B,QAAQ,YAAY;;iBAsBN,gBAAgB,gBAAgB,YAC9C,MAAM,aAAa,kBAClB,aAAa;;;;;;;;;;;;;;;;;;;;UCXC;;;;;;KAOL,oBAAoB;EAC9B,aAAa,iBAAiB;IAE5B,WACA;;;;;;;;;;;iBCfY,QACd,sBAAsB,mBACtB,iBAAiB,gBAAgB,qBAEjC,QACA;EAEA,QAAQ;EACR,oBAAoB,qBAAqB,SAAS;;EAElD,MAAM,aAAa,SAAS;EAC5B,QAAQ,kBAAkB,gBAAgB,SAAS;EACnD,QAAQ,kBAAkB,gBAAgB,SAAS;;;;iBCvBrC,cAAc,gBAAgB,YAC5C,MAAM,aAAa,kBAClB,YAAY;;;iBCKC,mBAAmB,gBAAgB,YAAY,UAAU,aAAa,YACpF,MACA;EAEA,MAAM,aAAa;EACnB,KAAK;;EAEL,OAAO,WAAW,SAAS;EAC3B;EACA,WAAW,OAAO,WAAW,SAAS;EACtC,cAAc,QAAQ,UAAU;;;;KChBtB,kBAAkB,iBAAiB,gBAAgB,iBAAiB,KAC9E,iBAAiB;;;iBCGH,YAAY,iBAAiB,eAC3C,SAAS,kBAAkB,YAC1B,uBAAuB,YAAY;;;iBCNtB,0BAA0B,iBAAiB,iBACzD,SACG,WACF,iBAAiB,YAAY,YAAY"}
|
|
1
|
+
{"version":3,"file":"react.d.ts","names":[],"sources":["../src/react/use-form-store.ts","../src/react/schema-registry.ts","../src/react/use-form.ts","../src/react/use-form-errors.ts","../src/react/use-form-field.ts","../src/react/use-forms.ts","../src/react/forms-module.ts","../src/react/register-forms-client.ts","../src/react/forms-registry.ts"],"mappings":";;;KAKY,aAAa,gBAAgB,cAAc;EACrD,QAAQ,QAAQ,WAAW;EAC3B,QAAQ,YAAY;;iBAsBN,gBAAgB,gBAAgB,YAC9C,MAAM,aAAa,kBAClB,aAAa;;;;;;;;;;;;;;;;;;;;UCXC;;;;;;KAOL,oBAAoB;EAC9B,aAAa,iBAAiB;IAE5B,WACA;;;;;;;;;;;iBCfY,QACd,sBAAsB,mBACtB,iBAAiB,gBAAgB,qBAEjC,QACA;EAEA,QAAQ;EACR,oBAAoB,qBAAqB,SAAS;;EAElD,MAAM,aAAa,SAAS;EAC5B,QAAQ,kBAAkB,gBAAgB,SAAS;EACnD,QAAQ,kBAAkB,gBAAgB,SAAS;;;;iBCvBrC,cAAc,gBAAgB,YAC5C,MAAM,aAAa,kBAClB,YAAY;;;iBCKC,mBAAmB,gBAAgB,YAAY,UAAU,aAAa,YACpF,MACA;EAEA,MAAM,aAAa;EACnB,KAAK;;EAEL,OAAO,WAAW,SAAS;EAC3B;EACA,WAAW,OAAO,WAAW,SAAS;EACtC,cAAc,QAAQ,UAAU;;;;KChBtB,kBAAkB,iBAAiB,gBAAgB,iBAAiB,KAC9E,iBAAiB;;;iBCGH,YAAY,iBAAiB,eAC3C,SAAS,kBAAkB,YAC1B,uBAAuB,YAAY;;;iBCNtB,0BAA0B,iBAAiB,iBACzD,SACG,WACF,iBAAiB,YAAY,YAAY;;;iBCC5B,yBAAyB,eAAe,YAAY"}
|
package/dist/react.js
CHANGED
|
@@ -46,6 +46,9 @@ const FORMS_MODULE_KEY = "forms";
|
|
|
46
46
|
* from provider context, not from here.
|
|
47
47
|
*/
|
|
48
48
|
const formsByCore = /* @__PURE__ */ new WeakMap();
|
|
49
|
+
function getRegisteredFormsClient(core) {
|
|
50
|
+
return formsByCore.get(core);
|
|
51
|
+
}
|
|
49
52
|
//#endregion
|
|
50
53
|
//#region src/react/use-forms.ts
|
|
51
54
|
/** @internal Product hooks read the module client from provider context. */
|
|
@@ -161,6 +164,6 @@ function forms(options) {
|
|
|
161
164
|
};
|
|
162
165
|
}
|
|
163
166
|
//#endregion
|
|
164
|
-
export { forms, registerFormsClient, useForm, useFormErrors, useFormField };
|
|
167
|
+
export { forms, getRegisteredFormsClient, registerFormsClient, useForm, useFormErrors, useFormField };
|
|
165
168
|
|
|
166
169
|
//# sourceMappingURL=react.js.map
|
package/dist/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.js","names":[],"sources":["../src/react/use-form-store.ts","../src/react/forms-registry.ts","../src/react/use-forms.ts","../src/react/use-form.ts","../src/react/use-form-errors.ts","../src/react/use-form-field.ts","../src/react/resolve-core-analytics.ts","../src/react/register-forms-client.ts","../src/react/forms-module.ts"],"sourcesContent":["import { useCallback, useRef, useSyncExternalStore } from 'react'\n\nimport type { FormSchema, FormValues } from '../core/config.js'\nimport type { FieldErrors, FormInstance } from '../core/form.js'\n\nexport type FormSnapshot<TSchema extends FormSchema> = Readonly<{\n values: Partial<FormValues<TSchema>>\n errors: FieldErrors<TSchema>\n}>\n\nconst EMPTY_SNAPSHOT: FormSnapshot<FormSchema> = Object.freeze({\n values: {},\n errors: {},\n})\n\nfunction createSnapshot<TSchema extends FormSchema>(\n form: FormInstance<TSchema>,\n): FormSnapshot<TSchema> {\n return Object.freeze({\n values: form.getAll(),\n errors: form.errors(),\n })\n}\n\ninterface CachedSnapshot<TSchema extends FormSchema> {\n readonly form: FormInstance<TSchema>\n readonly snapshot: FormSnapshot<TSchema>\n}\n\nexport function useFormSnapshot<TSchema extends FormSchema>(\n form: FormInstance<TSchema> | null,\n): FormSnapshot<TSchema> {\n const cachedRef = useRef<CachedSnapshot<TSchema> | null>(null)\n const emptyRef = useRef<FormSnapshot<TSchema>>(EMPTY_SNAPSHOT as FormSnapshot<TSchema>)\n\n const subscribe = useCallback(\n (listener: () => void) => {\n if (form === null) return () => undefined\n return form.subscribe(() => {\n cachedRef.current = { form, snapshot: createSnapshot(form) }\n listener()\n })\n },\n [form],\n )\n\n const getSnapshot = useCallback((): FormSnapshot<TSchema> => {\n if (form === null) {\n // * Otherwise a later A -> null -> mutate A -> A sequence would resurrect\n // * a snapshot cached before the detach, missing the mutation in between.\n cachedRef.current = null\n return emptyRef.current\n }\n // * A cached snapshot from a previous form instance must not survive a\n // * form change — recompute so switching forms without a mutation still\n // * returns the new form's values and errors.\n if (cachedRef.current === null || cachedRef.current.form !== form) {\n cachedRef.current = { form, snapshot: createSnapshot(form) }\n }\n return cachedRef.current.snapshot\n }, [form])\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot)\n}\n","import type { FormSchemaMap, FormsClient } from '../core/form.js'\n\nexport const FORMS_MODULE_KEY = 'forms'\n\n/**\n * Idempotence guard for `registerFormsClient` only — React reads the client\n * from provider context, not from here.\n */\nexport const formsByCore = new WeakMap<object, FormsClient<FormSchemaMap>>()\n","import { useEmbeddablesModule } from '@embeddables/core/react'\n\nimport { FORMS_MODULE_KEY } from './forms-registry.js'\n\nimport type { FormSchemaMap, FormsClient, InitFormsOptions } from '../core/form.js'\n\nexport type FormsReactOptions<TSchemas extends FormSchemaMap = FormSchemaMap> = Omit<\n InitFormsOptions<TSchemas>,\n 'core'\n>\n\n/** @internal Product hooks read the module client from provider context. */\nexport function useRegisteredFormsClient<\n TSchemas extends FormSchemaMap = FormSchemaMap,\n>(): FormsClient<TSchemas> | null {\n return useEmbeddablesModule<FormsClient<TSchemas>>({ key: FORMS_MODULE_KEY })\n}\n","import { useRef } from 'react'\n\nimport { useFormSnapshot } from './use-form-store.js'\nimport { useRegisteredFormsClient } from './use-forms.js'\n\nimport type { CustomValidationsFor, FormInstance, FormSchemaMap } from '../core/form.js'\nimport type { RegisteredSchemas } from './schema-registry.js'\n\n/**\n * Reactive binding for one declared form.\n *\n * Takes no type arguments: `TFormId` is inferred from `formId`, and the schema\n * map comes from the registry `em build` augments. Pass both explicitly\n * (`useForm<'signup', OtherSchemas>`) only to work against a map other than the\n * registered one.\n */\nexport function useForm<\n TFormId extends keyof TSchemas & string,\n TSchemas extends FormSchemaMap = RegisteredSchemas,\n>({\n formId,\n customValidations,\n}: {\n formId: TFormId\n customValidations?: CustomValidationsFor<TSchemas[TFormId]>\n}): {\n form: FormInstance<TSchemas[TFormId]> | null\n values: ReturnType<typeof useFormSnapshot<TSchemas[TFormId]>>['values']\n errors: ReturnType<typeof useFormSnapshot<TSchemas[TFormId]>>['errors']\n} {\n const client = useRegisteredFormsClient<TSchemas>()\n // * Held in a ref because only the first call for a form id builds the\n // * instance; a later render passing new validators must not look like a change.\n const customValidationsRef = useRef(customValidations)\n customValidationsRef.current = customValidations\n\n // * Safe to call on every render: the client returns one instance per form id.\n const form =\n client === null\n ? null\n : client.getForm({ formId, customValidations: customValidationsRef.current })\n const { values, errors } = useFormSnapshot(form)\n\n return { form, values, errors }\n}\n\n// prueba de la colisión\n","import { useFormSnapshot } from './use-form-store.js'\n\nimport type { FormSchema } from '../core/config.js'\nimport type { FieldErrors, FormInstance } from '../core/form.js'\n\nexport function useFormErrors<TSchema extends FormSchema>(\n form: FormInstance<TSchema> | null,\n): FieldErrors<TSchema> {\n const { errors } = useFormSnapshot(form)\n return errors\n}\n","import { useCallback, useEffect, useState } from 'react'\n\nimport { useFormSnapshot } from './use-form-store.js'\n\nimport type { FormFieldKey, FormSchema, FormValues } from '../core/config.js'\nimport type { FieldErrors, FormInstance, SetResult } from '../core/form.js'\n\nconst noopSetValue = async (): Promise<SetResult<FormSchema>> => ({\n ok: false,\n errors: {},\n})\n\nexport function useFormField<const TSchema extends FormSchema, K extends FormFieldKey<TSchema>>({\n form,\n key,\n}: {\n form: FormInstance<TSchema> | null\n key: K\n}): {\n value: FormValues<TSchema>[K] | undefined\n error: readonly string[] | undefined\n setValue: (value: FormValues<TSchema>[K]) => void\n onBlur: () => Promise<SetResult<TSchema>>\n} {\n const { values, errors } = useFormSnapshot(form)\n const committed = values[key]\n const [draft, setDraft] = useState<FormValues<TSchema>[K] | undefined>(committed)\n\n useEffect(() => {\n setDraft(committed)\n }, [form, key, committed])\n\n const setValue = useCallback((value: FormValues<TSchema>[K]) => {\n setDraft(value)\n }, [])\n\n const onBlur = useCallback(async (): Promise<SetResult<TSchema>> => {\n if (form === null) return noopSetValue()\n if (draft === committed) {\n return { ok: true, errors: {} as FieldErrors<TSchema> }\n }\n return form.set({ [key]: draft } as Partial<FormValues<TSchema>>)\n }, [committed, draft, form, key])\n\n if (form === null) {\n return {\n value: undefined,\n error: undefined,\n setValue: () => undefined,\n onBlur: async () => noopSetValue(),\n }\n }\n\n return {\n value: draft,\n error: errors[key],\n setValue,\n onBlur,\n }\n}\n","import type { AnalyticsInstance } from '@embeddables/core'\nimport type { EmbeddablesInstance } from '@embeddables/core'\n\nexport function resolveCoreAnalyticsInstance(\n core: EmbeddablesInstance,\n): AnalyticsInstance | undefined {\n if (typeof core.getAnalyticsInstance !== 'function') return undefined\n return core.getAnalyticsInstance() ?? undefined\n}\n","import { initForms } from '../core/form.js'\nimport { formsByCore } from './forms-registry.js'\nimport { resolveCoreAnalyticsInstance } from './resolve-core-analytics.js'\n\nimport type { FormSchemaMap, FormsClient, InitFormsOptions } from '../core/form.js'\n\nexport function registerFormsClient<const TSchemas extends FormSchemaMap>({\n core,\n ...options\n}: InitFormsOptions<TSchemas>): FormsClient<TSchemas> {\n const existing = formsByCore.get(core) as FormsClient<TSchemas> | undefined\n if (existing !== undefined) return existing\n\n const analyticsInstance = options.analyticsInstance ?? resolveCoreAnalyticsInstance(core)\n\n const client = initForms({ ...options, core, analyticsInstance })\n formsByCore.set(core, client as FormsClient<FormSchemaMap>)\n return client\n}\n","import type { EmbeddablesReactModule } from '@embeddables/core/react'\n\nimport { FORMS_MODULE_KEY } from './forms-registry.js'\nimport { registerFormsClient } from './register-forms-client.js'\n\nimport type { FormSchemaMap, FormsClient } from '../core/form.js'\nimport type { FormsReactOptions } from './use-forms.js'\n\nexport type { FormsReactOptions } from './use-forms.js'\n\nexport function forms<const TSchemas extends FormSchemaMap>(\n options: FormsReactOptions<TSchemas>,\n): EmbeddablesReactModule<FormsClient<TSchemas>> {\n return {\n key: FORMS_MODULE_KEY,\n init: (core) => registerFormsClient({ core, ...options }),\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"react.js","names":[],"sources":["../src/react/use-form-store.ts","../src/react/forms-registry.ts","../src/react/use-forms.ts","../src/react/use-form.ts","../src/react/use-form-errors.ts","../src/react/use-form-field.ts","../src/react/resolve-core-analytics.ts","../src/react/register-forms-client.ts","../src/react/forms-module.ts"],"sourcesContent":["import { useCallback, useRef, useSyncExternalStore } from 'react'\n\nimport type { FormSchema, FormValues } from '../core/config.js'\nimport type { FieldErrors, FormInstance } from '../core/form.js'\n\nexport type FormSnapshot<TSchema extends FormSchema> = Readonly<{\n values: Partial<FormValues<TSchema>>\n errors: FieldErrors<TSchema>\n}>\n\nconst EMPTY_SNAPSHOT: FormSnapshot<FormSchema> = Object.freeze({\n values: {},\n errors: {},\n})\n\nfunction createSnapshot<TSchema extends FormSchema>(\n form: FormInstance<TSchema>,\n): FormSnapshot<TSchema> {\n return Object.freeze({\n values: form.getAll(),\n errors: form.errors(),\n })\n}\n\ninterface CachedSnapshot<TSchema extends FormSchema> {\n readonly form: FormInstance<TSchema>\n readonly snapshot: FormSnapshot<TSchema>\n}\n\nexport function useFormSnapshot<TSchema extends FormSchema>(\n form: FormInstance<TSchema> | null,\n): FormSnapshot<TSchema> {\n const cachedRef = useRef<CachedSnapshot<TSchema> | null>(null)\n const emptyRef = useRef<FormSnapshot<TSchema>>(EMPTY_SNAPSHOT as FormSnapshot<TSchema>)\n\n const subscribe = useCallback(\n (listener: () => void) => {\n if (form === null) return () => undefined\n return form.subscribe(() => {\n cachedRef.current = { form, snapshot: createSnapshot(form) }\n listener()\n })\n },\n [form],\n )\n\n const getSnapshot = useCallback((): FormSnapshot<TSchema> => {\n if (form === null) {\n // * Otherwise a later A -> null -> mutate A -> A sequence would resurrect\n // * a snapshot cached before the detach, missing the mutation in between.\n cachedRef.current = null\n return emptyRef.current\n }\n // * A cached snapshot from a previous form instance must not survive a\n // * form change — recompute so switching forms without a mutation still\n // * returns the new form's values and errors.\n if (cachedRef.current === null || cachedRef.current.form !== form) {\n cachedRef.current = { form, snapshot: createSnapshot(form) }\n }\n return cachedRef.current.snapshot\n }, [form])\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot)\n}\n","import type { FormSchemaMap, FormsClient } from '../core/form.js'\n\nexport const FORMS_MODULE_KEY = 'forms'\n\n/**\n * Idempotence guard for `registerFormsClient` only — React reads the client\n * from provider context, not from here.\n */\nexport const formsByCore = new WeakMap<object, FormsClient<FormSchemaMap>>()\n\nexport function getRegisteredFormsClient(core: object): FormsClient<FormSchemaMap> | undefined {\n return formsByCore.get(core)\n}\n","import { useEmbeddablesModule } from '@embeddables/core/react'\n\nimport { FORMS_MODULE_KEY } from './forms-registry.js'\n\nimport type { FormSchemaMap, FormsClient, InitFormsOptions } from '../core/form.js'\n\nexport type FormsReactOptions<TSchemas extends FormSchemaMap = FormSchemaMap> = Omit<\n InitFormsOptions<TSchemas>,\n 'core'\n>\n\n/** @internal Product hooks read the module client from provider context. */\nexport function useRegisteredFormsClient<\n TSchemas extends FormSchemaMap = FormSchemaMap,\n>(): FormsClient<TSchemas> | null {\n return useEmbeddablesModule<FormsClient<TSchemas>>({ key: FORMS_MODULE_KEY })\n}\n","import { useRef } from 'react'\n\nimport { useFormSnapshot } from './use-form-store.js'\nimport { useRegisteredFormsClient } from './use-forms.js'\n\nimport type { CustomValidationsFor, FormInstance, FormSchemaMap } from '../core/form.js'\nimport type { RegisteredSchemas } from './schema-registry.js'\n\n/**\n * Reactive binding for one declared form.\n *\n * Takes no type arguments: `TFormId` is inferred from `formId`, and the schema\n * map comes from the registry `em build` augments. Pass both explicitly\n * (`useForm<'signup', OtherSchemas>`) only to work against a map other than the\n * registered one.\n */\nexport function useForm<\n TFormId extends keyof TSchemas & string,\n TSchemas extends FormSchemaMap = RegisteredSchemas,\n>({\n formId,\n customValidations,\n}: {\n formId: TFormId\n customValidations?: CustomValidationsFor<TSchemas[TFormId]>\n}): {\n form: FormInstance<TSchemas[TFormId]> | null\n values: ReturnType<typeof useFormSnapshot<TSchemas[TFormId]>>['values']\n errors: ReturnType<typeof useFormSnapshot<TSchemas[TFormId]>>['errors']\n} {\n const client = useRegisteredFormsClient<TSchemas>()\n // * Held in a ref because only the first call for a form id builds the\n // * instance; a later render passing new validators must not look like a change.\n const customValidationsRef = useRef(customValidations)\n customValidationsRef.current = customValidations\n\n // * Safe to call on every render: the client returns one instance per form id.\n const form =\n client === null\n ? null\n : client.getForm({ formId, customValidations: customValidationsRef.current })\n const { values, errors } = useFormSnapshot(form)\n\n return { form, values, errors }\n}\n","import { useFormSnapshot } from './use-form-store.js'\n\nimport type { FormSchema } from '../core/config.js'\nimport type { FieldErrors, FormInstance } from '../core/form.js'\n\nexport function useFormErrors<TSchema extends FormSchema>(\n form: FormInstance<TSchema> | null,\n): FieldErrors<TSchema> {\n const { errors } = useFormSnapshot(form)\n return errors\n}\n","import { useCallback, useEffect, useState } from 'react'\n\nimport { useFormSnapshot } from './use-form-store.js'\n\nimport type { FormFieldKey, FormSchema, FormValues } from '../core/config.js'\nimport type { FieldErrors, FormInstance, SetResult } from '../core/form.js'\n\nconst noopSetValue = async (): Promise<SetResult<FormSchema>> => ({\n ok: false,\n errors: {},\n})\n\nexport function useFormField<const TSchema extends FormSchema, K extends FormFieldKey<TSchema>>({\n form,\n key,\n}: {\n form: FormInstance<TSchema> | null\n key: K\n}): {\n value: FormValues<TSchema>[K] | undefined\n error: readonly string[] | undefined\n setValue: (value: FormValues<TSchema>[K]) => void\n onBlur: () => Promise<SetResult<TSchema>>\n} {\n const { values, errors } = useFormSnapshot(form)\n const committed = values[key]\n const [draft, setDraft] = useState<FormValues<TSchema>[K] | undefined>(committed)\n\n useEffect(() => {\n setDraft(committed)\n }, [form, key, committed])\n\n const setValue = useCallback((value: FormValues<TSchema>[K]) => {\n setDraft(value)\n }, [])\n\n const onBlur = useCallback(async (): Promise<SetResult<TSchema>> => {\n if (form === null) return noopSetValue()\n if (draft === committed) {\n return { ok: true, errors: {} as FieldErrors<TSchema> }\n }\n return form.set({ [key]: draft } as Partial<FormValues<TSchema>>)\n }, [committed, draft, form, key])\n\n if (form === null) {\n return {\n value: undefined,\n error: undefined,\n setValue: () => undefined,\n onBlur: async () => noopSetValue(),\n }\n }\n\n return {\n value: draft,\n error: errors[key],\n setValue,\n onBlur,\n }\n}\n","import type { AnalyticsInstance } from '@embeddables/core'\nimport type { EmbeddablesInstance } from '@embeddables/core'\n\nexport function resolveCoreAnalyticsInstance(\n core: EmbeddablesInstance,\n): AnalyticsInstance | undefined {\n if (typeof core.getAnalyticsInstance !== 'function') return undefined\n return core.getAnalyticsInstance() ?? undefined\n}\n","import { initForms } from '../core/form.js'\nimport { formsByCore } from './forms-registry.js'\nimport { resolveCoreAnalyticsInstance } from './resolve-core-analytics.js'\n\nimport type { FormSchemaMap, FormsClient, InitFormsOptions } from '../core/form.js'\n\nexport function registerFormsClient<const TSchemas extends FormSchemaMap>({\n core,\n ...options\n}: InitFormsOptions<TSchemas>): FormsClient<TSchemas> {\n const existing = formsByCore.get(core) as FormsClient<TSchemas> | undefined\n if (existing !== undefined) return existing\n\n const analyticsInstance = options.analyticsInstance ?? resolveCoreAnalyticsInstance(core)\n\n const client = initForms({ ...options, core, analyticsInstance })\n formsByCore.set(core, client as FormsClient<FormSchemaMap>)\n return client\n}\n","import type { EmbeddablesReactModule } from '@embeddables/core/react'\n\nimport { FORMS_MODULE_KEY } from './forms-registry.js'\nimport { registerFormsClient } from './register-forms-client.js'\n\nimport type { FormSchemaMap, FormsClient } from '../core/form.js'\nimport type { FormsReactOptions } from './use-forms.js'\n\nexport type { FormsReactOptions } from './use-forms.js'\n\nexport function forms<const TSchemas extends FormSchemaMap>(\n options: FormsReactOptions<TSchemas>,\n): EmbeddablesReactModule<FormsClient<TSchemas>> {\n return {\n key: FORMS_MODULE_KEY,\n init: (core) => registerFormsClient({ core, ...options }),\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@embeddables/forms",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "Schema-driven form state, local persistence, and analytics events for Embeddables funnels.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -53,8 +53,8 @@
|
|
|
53
53
|
"typescript": "~6.0.2",
|
|
54
54
|
"vitest": "^4.1.9",
|
|
55
55
|
"@embeddables/core": "0.0.4",
|
|
56
|
-
"
|
|
57
|
-
"
|
|
56
|
+
"@embeddables/shared-types": "1.0.0",
|
|
57
|
+
"backend-worker": "1.0.0"
|
|
58
58
|
},
|
|
59
59
|
"scripts": {
|
|
60
60
|
"build": "tsdown",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"form-CbU5ezg7.d.ts","names":[],"sources":["../../shared-types/dist/json.types.d.ts","../src/core/config.ts","../../shared-types/dist/analytics-instance.types.d.ts","../src/core/form.ts"],"mappings":";;;;;;KAIY,+CAA+C;GACtD,cAAc;;;;KCHP;;UAMF;EACR;EACA;EACA;EACA;EACA;EACA;EACA,MAAM;;KAGI,eAAe,eAAe,YAAY,cAAc;EAClE,OAAO;EACP,QAAQ,SAAS,eAAe;;UAUxB,oBAAoB,cAAc;WACjC;WACA;WACA;WACA;WACA;;WAEA;;WAEA;WACA,iBAAiB;;WAEjB,SAAS,eAAe,iBAAiB;;UAG1C,eAAe,cAAc;WAC5B;WACA;WACA,MAAM;WACN,cAAc,oBAAoB;WAGlC;WACA;;KAUC,iBAAiB,KAAK,YAAY,eAAe,MAAK;KAEtD,sBAAsB,KAAK,YAAY,oBAAoB,MAAK;UAE3D;WACN;WACA;WACA,iBAAiB;;KAGvB,SAAS,gBAAgB,cAAc;KAEhC,aAAa,gBAAgB,cAAc,SAAS;KAEpD,WAAW,gBAAgB,iBACpC,KAAK,SAAS,YAAY,WAAW,iBAAiB;;KAI7C,gBAAgB,gBAAgB,eAAe,kBAAkB,uBAEzE,QAAQ,SAAS;EAAY;;;;;;;;;;;;;;;UCzEhB;EACb;GACC;;;UAGY;EACb;EACA;EACA;;;;;;;UAOa,kBAAkB,SAAS;EACxC,WAAW,OAAO,kBAAkB,WAAW,QAAQ;;EAEvD;EACA;;;;;KCAQ,YAAY,gBAAgB,cAAc,SACpD,QAAQ,OAAO,aAAa;UAGb,UAAU,gBAAgB;EACzC;EACA,QAAQ,YAAY;;EAEpB;;UAGe,aAAa,gBAAgB;EAC5C;EACA,QAAQ,YAAY;EACpB,QAAQ,QAAQ,WAAW;EAC3B;;UAGe,eAAe,gBAAgB;EAC9C;EACA,QAAQ,YAAY;EACpB,QAAQ,QAAQ,WAAW;;UAGZ,aAAa,gBAAgB;WACnC,KAAK;;;;;;;EAOd,IAAI,OAAO,QAAQ,WAAW,YAAY,QAAQ,UAAU;;EAE5D,IAAI,UAAU,aAAa,UAAU,KAAK,IAAI,WAAW,SAAS;;;;;;EAMlE,0BAA0B,UAAU,gBAAgB,UAClD,iBAAiB,IAEf,WAAW,SAAS,QAAQ;IAA6B,iBAAiB;;EAE9E,UAAU,QAAQ,WAAW;;;;;;;;;EAS7B,UAAU,QAAQ,aAAa;;;;;;;;;;EAU/B,SAAS,QAAQ,QAAQ,WAAW,YAAY,QAAQ,eAAe;EACvE,UAAU,YAAY;EACtB;;EAEA,UAAU;;;KA6CA,gBAAgB,SAAS,eAAe;KAExC,qBAAqB,gBAAgB,0BACrC,KAAK,aAAa,YAAY;UAOzB,iBAAiB,iBAAiB,gBAAgB;EACjE,MAAM;;EAEN,SAAS;EACT,oBAAoB;;UAGL,YAAY,iBAAiB,gBAAgB;;;;;;;;;;;;;EAa5D,QAAQ,gBAAgB,mBAAmB;IACzC,QAAQ;IACR,oBAAoB,qBAAqB,SAAS;MAChD,aAAa,SAAS;;;;;;iBAOZ,gBAAgB,iBAAiB,eAC/C,SAAS,iBAAiB,YACzB,YAAY"}
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/errors.ts","../src/storage/storage.ts","../../shared-types/dist/analytics-ingest.types.d.ts","../src/core/analytics.ts"],"mappings":";;;;;;;;;;;;cAWa,mBAAmB;EAClB,YAAA,iBAAiB,UAAU;;;cAO5B,oBAAoB;EACnB,YAAA,iBAAiB,UAAU;;;cAO5B,uBAAuB;EACtB,YAAA,iBAAiB,UAAU;;;;;cCvB5B;UAEI;EACf,QAAQ;EACR,QAAQ,aAAa;EACrB,WAAW;;;;KCJD;;;;;;;;KAQA,oBAAoB;KACpB;EACR;EACA;;KAsBQ,oBAAoB;EAC5B;;EAEA;EACA,YAAY;EACZ,cAAc;;EAEd;;EAEA;;KAEQ;EACR;EACA;;KAEQ,mBAAmB;EAC3B;EACA,MAAM,eAAe;;KAMb,qBAAqB;EAC7B;EACA;;;;KCpCQ,sBAAsB,mBAAmB,oBAAoB"}
|