@formwright/core 0.1.0 → 0.2.2
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 +96 -0
- package/dist/chunk-OWEG6VGP.js +3 -0
- package/dist/chunk-OWEG6VGP.js.map +1 -0
- package/dist/index.cjs +376 -232
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +105 -17
- package/dist/index.d.ts +105 -17
- package/dist/index.js +330 -51
- package/dist/index.js.map +1 -1
- package/dist/reactive.cjs +27 -164
- package/dist/reactive.cjs.map +1 -1
- package/dist/reactive.d.cts +1 -45
- package/dist/reactive.d.ts +1 -45
- package/dist/reactive.js +1 -1
- package/package.json +3 -2
- package/dist/chunk-EZUHEI5F.js +0 -162
- package/dist/chunk-EZUHEI5F.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { ReadSignal, WriteSignal, Dispose } from '
|
|
2
|
-
export { batch, computed, effect, isTracking, signal, untrack } from '
|
|
1
|
+
import { ReadSignal, WriteSignal, Dispose } from '@formwright/reactive';
|
|
2
|
+
export { Dispose, ReadSignal, WriteSignal, batch, computed, effect, isTracking, signal, untrack } from '@formwright/reactive';
|
|
3
3
|
import { FieldValue, Condition, ValidationSchema, ProviderRef, FieldOption, Resolvable, FieldSchema, FormSchema } from '@formwright/schema';
|
|
4
|
-
export { Condition, FieldOption, FieldSchema, FieldValue, FormSchema } from '@formwright/schema';
|
|
4
|
+
export { Condition, FieldOption, FieldSchema, FieldType, FieldValue, FormSchema } from '@formwright/schema';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Condition engine — evaluates the sandboxed JSONLogic-style {@link Condition}
|
|
@@ -86,17 +86,28 @@ declare class FieldState {
|
|
|
86
86
|
/** Discriminant for the {@link FieldNode} union (leaf vs group/collection). */
|
|
87
87
|
readonly kind: "field";
|
|
88
88
|
readonly id: string;
|
|
89
|
-
|
|
89
|
+
/** A globally-unique DOM id for the control (collection rows reuse `id`, so this must be unique). */
|
|
90
|
+
readonly domId: string;
|
|
91
|
+
/** The field's schema — mutable at runtime via {@link patchSchema}. */
|
|
92
|
+
schema: FieldSchema;
|
|
90
93
|
readonly value: WriteSignal<FieldValue>;
|
|
91
94
|
readonly error: WriteSignal<string | null>;
|
|
92
95
|
readonly touched: WriteSignal<boolean>;
|
|
93
96
|
readonly visible: ReadSignal<boolean>;
|
|
94
97
|
readonly enabled: ReadSignal<boolean>;
|
|
95
98
|
readonly required: ReadSignal<boolean>;
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
99
|
+
/** Bumps whenever the schema is patched — renderers re-render the field on change. */
|
|
100
|
+
readonly revision: ReadSignal<number>;
|
|
101
|
+
private validator;
|
|
102
|
+
private readonly rev;
|
|
103
|
+
private readonly stepActive;
|
|
104
|
+
constructor(schema: FieldSchema, initial: FieldValue, getValue: ValueGetter, stepActive?: ReadSignal<boolean>);
|
|
105
|
+
/** Merge a partial schema in at runtime (change type, label, options, validation, …). */
|
|
106
|
+
patchSchema(partial: Partial<FieldSchema>): void;
|
|
107
|
+
/** Run validation, store and return the error (or null). Hidden / inactive-step fields never error. */
|
|
108
|
+
validate(options?: {
|
|
109
|
+
allSteps?: boolean;
|
|
110
|
+
}): string | null;
|
|
100
111
|
reset(value: FieldValue): void;
|
|
101
112
|
}
|
|
102
113
|
|
|
@@ -112,11 +123,13 @@ declare class FieldState {
|
|
|
112
123
|
* are skipped by validation.
|
|
113
124
|
*/
|
|
114
125
|
|
|
115
|
-
/** A node in the field tree: a leaf field, a nested object,
|
|
116
|
-
type FieldNode = FieldState | GroupNode | CollectionNode;
|
|
126
|
+
/** A node in the field tree: a leaf field, a nested object, a repeatable list, or a wizard. */
|
|
127
|
+
type FieldNode = FieldState | GroupNode | CollectionNode | StepsNode | StepNode;
|
|
117
128
|
/** Resolves a referenced field name to its current value, walking enclosing scopes. */
|
|
118
129
|
type Scope = ValueGetter;
|
|
119
130
|
type Dict = Record<string, unknown>;
|
|
131
|
+
/** True for fields that render content but contribute nothing to the payload. */
|
|
132
|
+
declare function isPresentational(type: string): boolean;
|
|
120
133
|
/** A nested object field: produces `{ ...visible child values }`. */
|
|
121
134
|
declare class GroupNode {
|
|
122
135
|
readonly kind: "group";
|
|
@@ -129,7 +142,7 @@ declare class GroupNode {
|
|
|
129
142
|
readonly enabled: ReadSignal<boolean>;
|
|
130
143
|
/** The scope a child uses: resolve a name among siblings, else delegate upward. */
|
|
131
144
|
readonly scope: Scope;
|
|
132
|
-
constructor(schema: FieldSchema, parentScope: Scope, initial: Dict);
|
|
145
|
+
constructor(schema: FieldSchema, parentScope: Scope, initial: Dict, stepActive?: ReadSignal<boolean>);
|
|
133
146
|
reset(initial: Dict): void;
|
|
134
147
|
}
|
|
135
148
|
/** One row of a {@link CollectionNode}: a group with a stable identity key. */
|
|
@@ -160,13 +173,52 @@ declare class CollectionNode {
|
|
|
160
173
|
removeAt(index: number): void;
|
|
161
174
|
reset(initial: Dict[]): void;
|
|
162
175
|
}
|
|
176
|
+
/** One step of a {@link StepsNode}: a titled section of nested fields. */
|
|
177
|
+
declare class StepNode {
|
|
178
|
+
readonly kind: "step";
|
|
179
|
+
readonly id: string;
|
|
180
|
+
readonly schema: FieldSchema;
|
|
181
|
+
readonly children: readonly FieldNode[];
|
|
182
|
+
readonly byName: ReadonlyMap<string, FieldNode>;
|
|
183
|
+
readonly value: ReadSignal<Dict>;
|
|
184
|
+
readonly visible: ReadSignal<boolean>;
|
|
185
|
+
readonly enabled: ReadSignal<boolean>;
|
|
186
|
+
readonly scope: Scope;
|
|
187
|
+
/** True when this step is the active step in its parent wizard. */
|
|
188
|
+
readonly active: ReadSignal<boolean>;
|
|
189
|
+
constructor(schema: FieldSchema, parentScope: Scope, initial: Dict, active: ReadSignal<boolean>);
|
|
190
|
+
reset(initial: Dict): void;
|
|
191
|
+
}
|
|
192
|
+
/** A multi-step wizard: shows one {@link StepNode} at a time with next/back navigation. */
|
|
193
|
+
declare class StepsNode {
|
|
194
|
+
readonly kind: "steps";
|
|
195
|
+
readonly id: string;
|
|
196
|
+
readonly schema: FieldSchema;
|
|
197
|
+
readonly steps: readonly StepNode[];
|
|
198
|
+
readonly byName: Map<string, StepNode>;
|
|
199
|
+
readonly value: ReadSignal<Dict>;
|
|
200
|
+
readonly visible: ReadSignal<boolean>;
|
|
201
|
+
readonly enabled: ReadSignal<boolean>;
|
|
202
|
+
readonly currentStep: WriteSignal<number>;
|
|
203
|
+
readonly scope: Scope;
|
|
204
|
+
constructor(schema: FieldSchema, parentScope: Scope, initial: Dict);
|
|
205
|
+
/** Validate every leaf in the step at `index` (defaults to the current step). */
|
|
206
|
+
validateStep(index?: number): boolean;
|
|
207
|
+
/** Advance to the next step after optionally validating the current one. Returns false if blocked. */
|
|
208
|
+
next(): boolean;
|
|
209
|
+
/** Go back one step (no validation). */
|
|
210
|
+
prev(): void;
|
|
211
|
+
/** Jump to a step by index (does not validate). */
|
|
212
|
+
goTo(index: number): void;
|
|
213
|
+
reset(initial: Dict): void;
|
|
214
|
+
}
|
|
163
215
|
/** Build the top-level field tree for a form, rooted at `rootScope`. */
|
|
164
216
|
declare function buildTree(schemas: readonly FieldSchema[], initial: Dict): {
|
|
165
217
|
nodes: FieldNode[];
|
|
166
218
|
byName: Map<string, FieldNode>;
|
|
167
219
|
scope: Scope;
|
|
168
220
|
};
|
|
169
|
-
/** Visit every leaf {@link FieldState} in a node list (descends groups/collections). */
|
|
221
|
+
/** Visit every leaf {@link FieldState} in a node list (descends groups/collections/steps). */
|
|
170
222
|
declare function eachLeaf(nodes: readonly FieldNode[], visit: (leaf: FieldState) => void): void;
|
|
171
223
|
|
|
172
224
|
/**
|
|
@@ -185,6 +237,15 @@ declare function eachLeaf(nodes: readonly FieldNode[], visit: (leaf: FieldState)
|
|
|
185
237
|
/** Form values — nested for `group` (object) and `collection` (array) fields. */
|
|
186
238
|
type FormValues = Record<string, unknown>;
|
|
187
239
|
type FormErrors = Record<string, string | null>;
|
|
240
|
+
/** The outcome of {@link Form.submit} — resolved for both success and failure. */
|
|
241
|
+
type SubmitResult = {
|
|
242
|
+
readonly ok: true;
|
|
243
|
+
readonly data: unknown;
|
|
244
|
+
} | {
|
|
245
|
+
readonly ok: false;
|
|
246
|
+
readonly error: unknown;
|
|
247
|
+
readonly errors?: FormErrors;
|
|
248
|
+
};
|
|
188
249
|
/** A transform applied to values before submission. */
|
|
189
250
|
type Transform = (values: FormValues, form: Form) => unknown;
|
|
190
251
|
/** Handlers referenced by name from the schema's `submit` block. */
|
|
@@ -196,12 +257,18 @@ interface FormOptions {
|
|
|
196
257
|
readonly handlers?: Record<string, SuccessHandler | ErrorHandler>;
|
|
197
258
|
/** Override the network send (defaults to `fetch` against `submit.endpoint`). */
|
|
198
259
|
readonly send?: (payload: unknown, form: Form) => Promise<unknown>;
|
|
260
|
+
/**
|
|
261
|
+
* Persist entered values under this `localStorage` key and restore them on the
|
|
262
|
+
* next load — so a refresh before submitting keeps the form filled. Cleared on
|
|
263
|
+
* a successful submit.
|
|
264
|
+
*/
|
|
265
|
+
readonly persistKey?: string;
|
|
199
266
|
}
|
|
200
267
|
/** Renders a {@link Form} into a host node; returns a disposer. Provided by a renderer package. */
|
|
201
268
|
interface FormRenderer {
|
|
202
269
|
mount(form: Form, host: Element): Dispose;
|
|
203
270
|
}
|
|
204
|
-
type EventName = "submit" | "success" | "error" | "change";
|
|
271
|
+
type EventName = "submit" | "success" | "error" | "change" | "action";
|
|
205
272
|
type Listener = (payload: unknown) => void;
|
|
206
273
|
/** Register the renderer used by {@link Form.mount} when none is passed explicitly. */
|
|
207
274
|
declare function setDefaultRenderer(renderer: FormRenderer): void;
|
|
@@ -223,6 +290,7 @@ declare class Form {
|
|
|
223
290
|
private readonly rootByName;
|
|
224
291
|
private readonly listeners;
|
|
225
292
|
private disposeRenderer;
|
|
293
|
+
private disposePersist;
|
|
226
294
|
constructor(schema: FormSchema | unknown, initialValues?: FormValues, options?: FormOptions);
|
|
227
295
|
/** All leaf fields keyed by dotted path (e.g. `items.name`, `contacts.0.email`). */
|
|
228
296
|
get fields(): ReadonlyMap<string, FieldState>;
|
|
@@ -233,16 +301,36 @@ declare class Form {
|
|
|
233
301
|
/** Apply a value to a specific leaf node (used by the renderer). */
|
|
234
302
|
setFieldValue(field: FieldState, value: FieldValue): void;
|
|
235
303
|
setError(id: string, error: string | null): void;
|
|
304
|
+
/** Patch one field's schema at runtime (change type, label, options, validation, …). */
|
|
305
|
+
setFieldSchema(path: string, partial: Partial<FieldSchema>): void;
|
|
306
|
+
/** Patch many fields' schemas at once: `form.patch({ state: { type: "text" }, … })`. */
|
|
307
|
+
patch(updates: Record<string, Partial<FieldSchema>>): void;
|
|
236
308
|
setErrors(errors: FormErrors): void;
|
|
237
309
|
get isSubmitting(): ReadSignal<boolean>;
|
|
238
310
|
/** Validate every (visible) leaf field; returns true when the whole form is valid. */
|
|
239
|
-
validate(
|
|
240
|
-
|
|
241
|
-
|
|
311
|
+
validate(options?: {
|
|
312
|
+
allSteps?: boolean;
|
|
313
|
+
}): boolean;
|
|
314
|
+
/** Find the first `steps` container in the field tree (if any). */
|
|
315
|
+
findSteps(): StepsNode | undefined;
|
|
316
|
+
/**
|
|
317
|
+
* Run the submission pipeline: validate → transform → send → onSuccess/onError.
|
|
318
|
+
* Pass an inline `transform` to shape the final payload, e.g.
|
|
319
|
+
* `form.submit((values) => ({ ...values, source: "web" }))`.
|
|
320
|
+
*
|
|
321
|
+
* Always **resolves** with a {@link SubmitResult} — never throws — so you can
|
|
322
|
+
* handle both outcomes from the API in one place:
|
|
323
|
+
* `const res = await form.submit(); res.ok ? res.data : res.error`.
|
|
324
|
+
*/
|
|
325
|
+
submit(transform?: (values: FormValues, form: Form) => unknown): Promise<SubmitResult>;
|
|
242
326
|
reset(values?: FormValues): void;
|
|
327
|
+
/** Trigger a named form action: runs its handler (from options) and emits "action". */
|
|
328
|
+
action(name: string): void;
|
|
243
329
|
/** Mount into a host element using the given renderer (or the registered default). */
|
|
244
330
|
mount(host: Element, renderer?: FormRenderer | null): Dispose;
|
|
245
331
|
destroy(): void;
|
|
332
|
+
/** Remove the cached draft from `localStorage` (called on a successful submit). */
|
|
333
|
+
private clearPersisted;
|
|
246
334
|
on(event: EventName, listener: Listener): Dispose;
|
|
247
335
|
private emit;
|
|
248
336
|
private collectErrors;
|
|
@@ -256,4 +344,4 @@ declare class FormValidationError extends Error {
|
|
|
256
344
|
constructor(errors: FormErrors);
|
|
257
345
|
}
|
|
258
346
|
|
|
259
|
-
export { type CollectionItem, CollectionNode,
|
|
347
|
+
export { type CollectionItem, CollectionNode, type ErrorHandler, type FieldNode, FieldState, type FieldValidator, Form, type FormErrors, type FormOptions, type FormRenderer, FormValidationError, type FormValues, GroupNode, type I18nProvider, type Providers, type QueryProvider, type QueryResult, type Scope, StepNode, StepsNode, type SubmitResult, type SuccessHandler, type ThemeProvider, type Transform, type ValueGetter, buildTree, compileValidator, defaultValueFor, eachLeaf, evaluateCondition, isPresentational, isProviderRef, referencedFields, resolve, resolveQuery, setDefaultRenderer };
|