attaform 0.24.3 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/devtools.cjs +1 -1
- package/dist/chunks/devtools.mjs +1 -1
- package/dist/chunks/fingerprint2.cjs +1 -1
- package/dist/chunks/fingerprint2.mjs +1 -1
- package/dist/index.cjs +4 -4
- package/dist/index.d.cts +4 -4
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.mjs +4 -4
- package/dist/nuxt.d.cts +1 -1
- package/dist/nuxt.d.mts +1 -1
- package/dist/nuxt.d.ts +1 -1
- package/dist/runtime/plugins/attaform.cjs +2 -2
- package/dist/runtime/plugins/attaform.mjs +2 -2
- package/dist/shared/{attaform.DQcdvxKZ.cjs → attaform.3heDHayA.cjs} +146 -3
- package/dist/shared/attaform.3heDHayA.cjs.map +1 -0
- package/dist/shared/{attaform.yqcYwt0d.d.ts → attaform.8vmdOURQ.d.mts} +124 -56
- package/dist/shared/{attaform.BjiHiYAZ.d.ts → attaform.B3cgZE3c.d.ts} +1 -1
- package/dist/shared/{attaform.DHjRN5JP.d.cts → attaform.B5GFS3Su.d.cts} +124 -56
- package/dist/shared/{attaform.BVjueUPu.cjs → attaform.B5YcWrKi.cjs} +3 -3
- package/dist/shared/{attaform.BVjueUPu.cjs.map → attaform.B5YcWrKi.cjs.map} +1 -1
- package/dist/shared/{attaform.Bx6pgrIy.d.cts → attaform.BJt4ZCkM.d.mts} +1 -1
- package/dist/shared/{attaform.DK6_Ctv7.cjs → attaform.BRzKBj2g.cjs} +182 -7
- package/dist/shared/attaform.BRzKBj2g.cjs.map +1 -0
- package/dist/shared/{attaform.CB1kYKUB.cjs → attaform.BkUzunyB.cjs} +180 -38
- package/dist/shared/attaform.BkUzunyB.cjs.map +1 -0
- package/dist/shared/{attaform.Dbzwtn4g.mjs → attaform.CN4ZEGo6.mjs} +4 -4
- package/dist/shared/{attaform.Dbzwtn4g.mjs.map → attaform.CN4ZEGo6.mjs.map} +1 -1
- package/dist/shared/{attaform.C5qkSN6t.mjs → attaform.CqwcTExO.mjs} +146 -3
- package/dist/shared/attaform.CqwcTExO.mjs.map +1 -0
- package/dist/shared/{attaform.D4ebpNbS.mjs → attaform.CwXXbZIQ.mjs} +3 -3
- package/dist/shared/{attaform.D4ebpNbS.mjs.map → attaform.CwXXbZIQ.mjs.map} +1 -1
- package/dist/shared/{attaform.B_F61Rx1.mjs → attaform.DK3xUBkj.mjs} +181 -39
- package/dist/shared/attaform.DK3xUBkj.mjs.map +1 -0
- package/dist/shared/{attaform.ByIB7i15.mjs → attaform.DMNnfQq_.mjs} +4 -4
- package/dist/shared/{attaform.ByIB7i15.mjs.map → attaform.DMNnfQq_.mjs.map} +1 -1
- package/dist/shared/{attaform.0zueP54D.d.mts → attaform.DS_zBcdr.d.ts} +124 -56
- package/dist/shared/{attaform.DvqdxvNU.d.mts → attaform.DmKLa4tL.d.cts} +1 -1
- package/dist/shared/{attaform.DgbHNLf_.mjs → attaform.OLtKd9gM.mjs} +2 -2
- package/dist/shared/{attaform.DgbHNLf_.mjs.map → attaform.OLtKd9gM.mjs.map} +1 -1
- package/dist/shared/{attaform.WvcckZMD.mjs → attaform.Vp2-CWZB.mjs} +3 -2
- package/dist/shared/attaform.Vp2-CWZB.mjs.map +1 -0
- package/dist/shared/{attaform.CqlLImc1.cjs → attaform.Xe8dATED.cjs} +4 -4
- package/dist/shared/{attaform.CqlLImc1.cjs.map → attaform.Xe8dATED.cjs.map} +1 -1
- package/dist/shared/{attaform.CjdepGnw.cjs → attaform.ZXZ6dH72.cjs} +3 -1
- package/dist/shared/attaform.ZXZ6dH72.cjs.map +1 -0
- package/dist/shared/{attaform.DUc6cetN.d.cts → attaform.i_LA3X9o.d.cts} +54 -2
- package/dist/shared/{attaform.DUc6cetN.d.ts → attaform.i_LA3X9o.d.mts} +54 -2
- package/dist/shared/{attaform.DUc6cetN.d.mts → attaform.i_LA3X9o.d.ts} +54 -2
- package/dist/shared/{attaform.DwCtxauq.mjs → attaform.k9V0py0s.mjs} +182 -8
- package/dist/shared/attaform.k9V0py0s.mjs.map +1 -0
- package/dist/shared/{attaform.DfnwaGW2.cjs → attaform.sks1MFVO.cjs} +4 -4
- package/dist/shared/{attaform.DfnwaGW2.cjs.map → attaform.sks1MFVO.cjs.map} +1 -1
- package/dist/shared/{attaform.DRWrVSkH.cjs → attaform.xBDo0Ko0.cjs} +2 -2
- package/dist/shared/{attaform.DRWrVSkH.cjs.map → attaform.xBDo0Ko0.cjs.map} +1 -1
- package/dist/transforms.cjs +2 -1
- package/dist/transforms.cjs.map +1 -1
- package/dist/transforms.d.cts +13 -1
- package/dist/transforms.d.mts +13 -1
- package/dist/transforms.d.ts +13 -1
- package/dist/transforms.mjs +1 -1
- package/dist/vite.cjs +2 -1
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.mjs +2 -1
- package/dist/vite.mjs.map +1 -1
- package/dist/zod-v3.cjs +2 -2
- package/dist/zod-v3.d.cts +3 -3
- package/dist/zod-v3.d.mts +3 -3
- package/dist/zod-v3.d.ts +3 -3
- package/dist/zod-v3.mjs +2 -2
- package/dist/zod-v4.cjs +2 -2
- package/dist/zod-v4.d.cts +5 -5
- package/dist/zod-v4.d.mts +5 -5
- package/dist/zod-v4.d.ts +5 -5
- package/dist/zod-v4.mjs +2 -2
- package/dist/zod.cjs +5 -5
- package/dist/zod.d.cts +5 -5
- package/dist/zod.d.mts +5 -5
- package/dist/zod.d.ts +5 -5
- package/dist/zod.mjs +5 -5
- package/package.json +6 -2
- package/dist/shared/attaform.B_F61Rx1.mjs.map +0 -1
- package/dist/shared/attaform.C5qkSN6t.mjs.map +0 -1
- package/dist/shared/attaform.CB1kYKUB.cjs.map +0 -1
- package/dist/shared/attaform.CjdepGnw.cjs.map +0 -1
- package/dist/shared/attaform.DK6_Ctv7.cjs.map +0 -1
- package/dist/shared/attaform.DQcdvxKZ.cjs.map +0 -1
- package/dist/shared/attaform.DwCtxauq.mjs.map +0 -1
- package/dist/shared/attaform.WvcckZMD.mjs.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { F as FormKey, W as PathKey, m as DisplayCtx, d as GetDisplayState, n as DisplayMachine, V as Path, aa as SlimPrimitiveKind, C as CoercionEntry, g as CoercionRegistry,
|
|
1
|
+
import { F as FormKey, b as UseFormReturnType, G as GenericForm, W as PathKey, m as DisplayCtx, d as GetDisplayState, n as DisplayMachine, V as Path, aa as SlimPrimitiveKind, C as CoercionEntry, g as CoercionRegistry, ag as ValidationError, a as AbstractSchema, ak as WriteMeta, j as DeepPartial, al as WriteShape, at as TransformAbortHolder, ae as ValidateOn, A as AttaformDefaults, c as RegisterValue } from './attaform.i_LA3X9o.js';
|
|
2
2
|
import { Ref, ComputedRef, App, InjectionKey } from 'vue';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -137,23 +137,27 @@ declare const _lazyBrand: unique symbol;
|
|
|
137
137
|
*/
|
|
138
138
|
type LazyMarker<Ctx = WizardCtx> = {
|
|
139
139
|
readonly [_lazyBrand]: true;
|
|
140
|
-
readonly resolve: (ctx: Ctx) => AnyForm | string | undefined;
|
|
140
|
+
readonly resolve: (ctx: Ctx) => AnyForm | string | null | undefined;
|
|
141
141
|
};
|
|
142
142
|
/**
|
|
143
143
|
* One position in the source `useWizard({ steps })` array. Each slot
|
|
144
|
-
* resolves to a compiled `{ key, form }` step:
|
|
144
|
+
* resolves to a compiled `{ key, form }` step, or drops out:
|
|
145
145
|
*
|
|
146
146
|
* - `AnyForm` — a form declared via `useForm`. Surfaced as-is.
|
|
147
147
|
* - `string` — bare key. The wizard generates a noop form
|
|
148
148
|
* under the hood so the external surface stays
|
|
149
149
|
* uniform across affordance positions (intro,
|
|
150
150
|
* terms, congratulations, review surfaces).
|
|
151
|
+
* - `null` / `undefined` — a literal absence, dropped from the compiled
|
|
152
|
+
* list. Lets a conditional step read inline as
|
|
153
|
+
* `cond ? form : null` without pre-filtering the
|
|
154
|
+
* array.
|
|
151
155
|
* - function — eager slot, re-evaluates reactively. Returns
|
|
152
|
-
* one of the above, or `undefined` to
|
|
153
|
-
* slot from the compiled list.
|
|
156
|
+
* one of the above, or `null` / `undefined` to
|
|
157
|
+
* drop the slot from the compiled list.
|
|
154
158
|
* - `LazyMarker` — memoized function slot (see `lazy`).
|
|
155
159
|
*/
|
|
156
|
-
type StepSlot<Ctx = WizardCtx> = AnyForm | string | ((ctx: Ctx) => AnyForm | string | undefined) | LazyMarker<Ctx>;
|
|
160
|
+
type StepSlot<Ctx = WizardCtx> = AnyForm | string | null | undefined | ((ctx: Ctx) => AnyForm | string | null | undefined) | LazyMarker<Ctx>;
|
|
157
161
|
/**
|
|
158
162
|
* Shape returned by the `restore` callback. Carries the active step's
|
|
159
163
|
* key; intentionally open-ended (object form) so future additions land
|
|
@@ -178,8 +182,9 @@ type WizardRestoreFn = () => WizardRestoreState | undefined;
|
|
|
178
182
|
type WizardPersistFn = (state: WizardRestoreState) => void;
|
|
179
183
|
/**
|
|
180
184
|
* Submit context passed to the `onSubmit` callback registered via
|
|
181
|
-
* `wizard.handleSubmit(onSubmit, onError?)`.
|
|
182
|
-
* `
|
|
185
|
+
* `wizard.handleSubmit(onSubmit, onError?)`. `handleSubmit` always
|
|
186
|
+
* processes the whole step list, so `values` carries every form's
|
|
187
|
+
* parsed output regardless of which step fired the submit.
|
|
183
188
|
*
|
|
184
189
|
* - `values` — namespaced aggregate keyed by form key, mirroring
|
|
185
190
|
* `wizard.allValues`. Reflects parsed output for every
|
|
@@ -190,9 +195,11 @@ type WizardPersistFn = (state: WizardRestoreState) => void;
|
|
|
190
195
|
* because the form ref carries its schema info.
|
|
191
196
|
* - `currentKey` — key of the step that fired this submission.
|
|
192
197
|
* - `isFinal` — `true` when `currentKey` is the last position in
|
|
193
|
-
* `wizard.steps`.
|
|
194
|
-
*
|
|
195
|
-
* and
|
|
198
|
+
* `wizard.steps`. Positional only: it reports where the
|
|
199
|
+
* submit fired, never what got validated. A user who steps
|
|
200
|
+
* back, edits, and submits from the middle sees
|
|
201
|
+
* `isFinal === false`, yet the whole list is still
|
|
202
|
+
* processed and `done` still latches on success.
|
|
196
203
|
*/
|
|
197
204
|
type WizardSubmitContext = {
|
|
198
205
|
readonly values: Readonly<Record<FormKey, unknown>>;
|
|
@@ -209,9 +216,11 @@ type WizardSubmitContext = {
|
|
|
209
216
|
type WizardOnSubmit = (ctx: WizardSubmitContext) => void | Promise<void>;
|
|
210
217
|
/**
|
|
211
218
|
* Optional `onError` callback registered via `wizard.handleSubmit`.
|
|
212
|
-
* Receives the aggregate error list
|
|
213
|
-
*
|
|
214
|
-
*
|
|
219
|
+
* Receives the aggregate error list spanning EVERY step (handleSubmit
|
|
220
|
+
* validates the whole wizard), so a failed submit surfaces every form's
|
|
221
|
+
* errors at once, not just the active step's. Entries originate from
|
|
222
|
+
* per-form validation, activation failures (`atta:activation-failed`),
|
|
223
|
+
* and a submit callback that left errors on a processed step (the
|
|
215
224
|
* `setErrors(...); return` server-rejection path). Sync or async; the
|
|
216
225
|
* returned promise gates `wizard.submitting`.
|
|
217
226
|
*/
|
|
@@ -296,24 +305,55 @@ type WizardOptions = {
|
|
|
296
305
|
*/
|
|
297
306
|
readonly persist?: WizardPersistFn | false;
|
|
298
307
|
};
|
|
308
|
+
/**
|
|
309
|
+
* True when a single slot is guaranteed to contribute exactly one
|
|
310
|
+
* compiled step: a bare form or affordance string that is neither
|
|
311
|
+
* nullish nor a (maybe-absent) function / `lazy()` slot. One of these
|
|
312
|
+
* anywhere in the tuple proves the compiled list is non-empty.
|
|
313
|
+
*/
|
|
314
|
+
type IsGuaranteedStep<T> = [null] extends [T] ? false : [undefined] extends [T] ? false : T extends LazyMarker | ((...args: unknown[]) => unknown) ? false : T extends string ? true : T extends {
|
|
315
|
+
readonly key: string;
|
|
316
|
+
} ? true : false;
|
|
299
317
|
/**
|
|
300
318
|
* Predicate: is the steps tuple statically guaranteed to compile to a
|
|
301
|
-
* non-empty list?
|
|
302
|
-
*
|
|
303
|
-
*
|
|
304
|
-
*
|
|
305
|
-
*
|
|
306
|
-
*
|
|
319
|
+
* non-empty list? True when at least one element is a guaranteed step
|
|
320
|
+
* (see `IsGuaranteedStep`). Function / `lazy()` slots may resolve to
|
|
321
|
+
* nothing, and `null` / `undefined` (a literal absence or a
|
|
322
|
+
* `cond ? form : null` union) is an explicit drop, so none of those
|
|
323
|
+
* prove non-emptiness; a tuple of only maybe-absent slots stays
|
|
324
|
+
* honestly `| undefined`.
|
|
307
325
|
*
|
|
308
326
|
* Used to narrow `currentStep` / `activeForm` to their non-`undefined`
|
|
309
327
|
* shapes in the common-case wizard, while keeping the honest union
|
|
310
328
|
* everywhere a runtime drop is reachable.
|
|
311
329
|
*/
|
|
312
|
-
type StaticallyNonEmpty<S> = S extends readonly [
|
|
330
|
+
type StaticallyNonEmpty<S> = S extends readonly [infer First, ...infer Rest] ? IsGuaranteedStep<First> extends true ? true : StaticallyNonEmpty<Rest> : false;
|
|
313
331
|
/** Active step's key, narrowed to `string` when `S` is statically safe. */
|
|
314
332
|
type CurrentStepOf<S> = StaticallyNonEmpty<S> extends true ? FormKey : FormKey | undefined;
|
|
315
|
-
/**
|
|
316
|
-
|
|
333
|
+
/**
|
|
334
|
+
* Active step's form handle, schema-erased to `UseFormReturnType<GenericForm>`
|
|
335
|
+
* and narrowed to non-`undefined` when `S` is statically safe. The runtime
|
|
336
|
+
* value is a live facade over the active step, so reads (`.values`, `.meta`,
|
|
337
|
+
* `.history`) and `.handleSubmit` always target the current step. Values are
|
|
338
|
+
* loose here because the active step's schema is not statically known; reach
|
|
339
|
+
* for the original form ref or `ctx.get(ref)` when you need typed per-step
|
|
340
|
+
* values.
|
|
341
|
+
*/
|
|
342
|
+
type ActiveFormOf<S> = StaticallyNonEmpty<S> extends true ? UseFormReturnType<GenericForm> : UseFormReturnType<GenericForm> | undefined;
|
|
343
|
+
/**
|
|
344
|
+
* Per-slot contribution to {@link FormsRecordOf}. Strips a `null` /
|
|
345
|
+
* `undefined` (a literal absence or a `cond ? form : null` union) off the
|
|
346
|
+
* slot first, so a conditionally-present form still maps to its key and
|
|
347
|
+
* stays concretely typed on `wizard.forms`; a purely nullish slot
|
|
348
|
+
* contributes nothing.
|
|
349
|
+
*/
|
|
350
|
+
type SlotRecord<First, F = Exclude<First, null | undefined>> = [F] extends [never] ? unknown : F extends string ? {
|
|
351
|
+
readonly [P in F]: AnyForm;
|
|
352
|
+
} : F extends {
|
|
353
|
+
readonly key: infer K extends string;
|
|
354
|
+
} ? {
|
|
355
|
+
readonly [P in K]: F;
|
|
356
|
+
} : unknown;
|
|
317
357
|
/**
|
|
318
358
|
* Recursive tuple walk that builds the static portion of
|
|
319
359
|
* `wizard.forms`. Each step slot contributes to the record:
|
|
@@ -325,7 +365,9 @@ type ActiveFormOf<S> = StaticallyNonEmpty<S> extends true ? AnyForm : AnyForm |
|
|
|
325
365
|
* the form's own `key` becomes the record key, and the value is
|
|
326
366
|
* the concrete form handle type — so drilling
|
|
327
367
|
* `wizard.forms.shipping.values.address` carries the schema-derived
|
|
328
|
-
* field types through.
|
|
368
|
+
* field types through. A form kept behind a `cond ? form : null`
|
|
369
|
+
* conditional still maps to its key.
|
|
370
|
+
* - **`null` / `undefined` slot**: contributes nothing.
|
|
329
371
|
* - **Function / `lazy()` slot**: contributes nothing to the static
|
|
330
372
|
* map. Runtime-resolved forms are still reachable via the
|
|
331
373
|
* catch-all index signature on `WizardForms` (typed as `AnyForm`).
|
|
@@ -336,13 +378,7 @@ type ActiveFormOf<S> = StaticallyNonEmpty<S> extends true ? AnyForm : AnyForm |
|
|
|
336
378
|
type FormsRecordOf<S> = S extends readonly [
|
|
337
379
|
infer First,
|
|
338
380
|
...infer Rest extends ReadonlyArray<StepSlot>
|
|
339
|
-
] ?
|
|
340
|
-
readonly [P in First]: AnyForm;
|
|
341
|
-
} : First extends {
|
|
342
|
-
readonly key: infer K extends string;
|
|
343
|
-
} ? {
|
|
344
|
-
readonly [P in K]: First;
|
|
345
|
-
} : unknown) & FormsRecordOf<Rest> : unknown;
|
|
381
|
+
] ? SlotRecord<First> & FormsRecordOf<Rest> : unknown;
|
|
346
382
|
/**
|
|
347
383
|
* `wizard.forms` typed view. Combines the static per-step type map
|
|
348
384
|
* with a catch-all `Record<FormKey, AnyForm>` fallback so:
|
|
@@ -376,9 +412,15 @@ type WizardForms<S> = FormsRecordOf<S> & Readonly<Record<FormKey, AnyForm>>;
|
|
|
376
412
|
* slots). Otherwise reads as `string | undefined`
|
|
377
413
|
* so the degenerate case (empty list at runtime)
|
|
378
414
|
* surfaces honestly.
|
|
379
|
-
* - `activeForm` — the active step's form
|
|
380
|
-
*
|
|
381
|
-
*
|
|
415
|
+
* - `activeForm` — a LIVE view of the active step's form. Operating
|
|
416
|
+
* through it always targets the current step, so a
|
|
417
|
+
* handler captured once at setup
|
|
418
|
+
* (`wizard.activeForm.handleSubmit(() =>
|
|
419
|
+
* wizard.next())`) retargets as the wizard advances.
|
|
420
|
+
* No longer `===` the raw per-step handle; reach for
|
|
421
|
+
* `wizard.forms[key]` when you need raw identity.
|
|
422
|
+
* Same `undefined` narrowing as `currentStep`. Noop
|
|
423
|
+
* forms cover string slots in the normal path.
|
|
382
424
|
* - `activeIndex` — 0-based position of the active step.
|
|
383
425
|
* - `isFinalStep` — `true` when `currentStep === steps[count - 1].key`.
|
|
384
426
|
* - `steps` — ordered list of compiled `{ key, form }` slots.
|
|
@@ -404,13 +446,13 @@ type WizardForms<S> = FormsRecordOf<S> & Readonly<Record<FormKey, AnyForm>>;
|
|
|
404
446
|
* Forward-looking; reactive to current form
|
|
405
447
|
* validity. Gates "Finish button enable" style UI.
|
|
406
448
|
* - `done` — monotonic latch: flips `true` the first time a
|
|
407
|
-
*
|
|
408
|
-
*
|
|
409
|
-
*
|
|
410
|
-
*
|
|
411
|
-
*
|
|
412
|
-
*
|
|
413
|
-
*
|
|
449
|
+
* `handleSubmit` resolves without throwing AND leaves
|
|
450
|
+
* no errors set on any step, and stays `true` through
|
|
451
|
+
* subsequent edits or invalidations. A callback that
|
|
452
|
+
* calls `setErrors` and returns (the documented
|
|
453
|
+
* server-rejection path) is a failed submit, so it
|
|
454
|
+
* does not flip `done`. Only `reset()` flips it back.
|
|
455
|
+
* Gates "show success card" style UI that should
|
|
414
456
|
* reflect submission history rather than current
|
|
415
457
|
* validity.
|
|
416
458
|
* - `submitting` — `true` while a `wizard.handleSubmit` call is in
|
|
@@ -434,11 +476,23 @@ type WizardForms<S> = FormsRecordOf<S> & Readonly<Record<FormKey, AnyForm>>;
|
|
|
434
476
|
* `back()` does not pop; the trail is the audit
|
|
435
477
|
* log, not the back-stack.
|
|
436
478
|
* - `next/back/goTo` — pure navigation. Refuses while `submitting`.
|
|
437
|
-
* - `
|
|
438
|
-
*
|
|
439
|
-
*
|
|
440
|
-
*
|
|
441
|
-
*
|
|
479
|
+
* - `tryNext()` — validate the active step, then advance iff it
|
|
480
|
+
* passed; invalid input keeps the pin put under the
|
|
481
|
+
* form's standard error reveal (first error focused,
|
|
482
|
+
* display state advanced). The inline-bindable
|
|
483
|
+
* shorthand for `activeForm.handleSubmit(() =>
|
|
484
|
+
* next())`. Resolves to whether the pin moved. No-ops
|
|
485
|
+
* to `false` on a degenerate or final-step wizard
|
|
486
|
+
* (finish via `handleSubmit`).
|
|
487
|
+
* - `handleSubmit(onSubmit, onError?)` — always validates the entire
|
|
488
|
+
* step list, from any step, and never advances the
|
|
489
|
+
* pin: on success it latches `done`; on any error it
|
|
490
|
+
* focuses the first failing step and fires `onError`
|
|
491
|
+
* with errors spanning every step. To gate advancing
|
|
492
|
+
* a step on its own validity, compose with the active
|
|
493
|
+
* form's submit: `activeForm.handleSubmit(() =>
|
|
494
|
+
* wizard.next())`. Returns an event handler suitable
|
|
495
|
+
* for `<form @submit>` or imperative use.
|
|
442
496
|
* - `reset()` — zeros wizard lifecycle (`submissionAttempts`,
|
|
443
497
|
* `visited`), resets every form, returns
|
|
444
498
|
* `currentStep` to `steps[0].key`, and invokes
|
|
@@ -468,6 +522,7 @@ type UseWizardReturnType<S extends ReadonlyArray<StepSlot> = ReadonlyArray<StepS
|
|
|
468
522
|
readonly next: () => Promise<void>;
|
|
469
523
|
readonly back: () => void;
|
|
470
524
|
readonly goTo: (key: string) => void;
|
|
525
|
+
readonly tryNext: () => Promise<boolean>;
|
|
471
526
|
readonly handleSubmit: (onSubmit: WizardOnSubmit, onError?: WizardOnError) => (event?: Event) => Promise<void>;
|
|
472
527
|
readonly reset: () => void;
|
|
473
528
|
};
|
|
@@ -1073,6 +1128,14 @@ type FormStore<F extends GenericForm, G extends GenericForm = F> = {
|
|
|
1073
1128
|
* source there).
|
|
1074
1129
|
*/
|
|
1075
1130
|
markConnectedOptimistically(path: Path): void;
|
|
1131
|
+
/**
|
|
1132
|
+
* Client-side connected mark for a `v-register` component host that binds
|
|
1133
|
+
* value via the v-model channel but has no single inner control to latch
|
|
1134
|
+
* (a composite widget, or none found). The directive calls it on mount
|
|
1135
|
+
* (`true`) and unmount (`false`). Distinct from the SSR-only
|
|
1136
|
+
* `markConnectedOptimistically`; idempotent on the leading edge.
|
|
1137
|
+
*/
|
|
1138
|
+
markHostConnected(path: Path, connected: boolean): void;
|
|
1076
1139
|
/**
|
|
1077
1140
|
* Leaf-only pristine check. `originals` is populated via
|
|
1078
1141
|
* `diffAndApply`'s `added` patches, which fire only on primitive
|
|
@@ -1538,8 +1601,10 @@ type InjectFormInput = {
|
|
|
1538
1601
|
* independent of component-tree position.
|
|
1539
1602
|
*
|
|
1540
1603
|
* Returns `null` when no matching form exists (no ambient ancestor, or
|
|
1541
|
-
* the named key isn't registered). A dev-mode warning points at the
|
|
1542
|
-
* call site
|
|
1604
|
+
* the named key isn't registered yet). A dev-mode warning points at the
|
|
1605
|
+
* call site, lists the registered keys, and flags the mount-timing case
|
|
1606
|
+
* (a form created by a child or sibling isn't registered until its own
|
|
1607
|
+
* setup runs). Always narrow before using:
|
|
1543
1608
|
*
|
|
1544
1609
|
* ```ts
|
|
1545
1610
|
* const form = injectForm<Shape>('signup')
|
|
@@ -1642,9 +1707,10 @@ declare function useRegister<V = unknown>(): UseRegisterReturn<V> | undefined;
|
|
|
1642
1707
|
*
|
|
1643
1708
|
* The wizard's surface is read-only from the consumer's side:
|
|
1644
1709
|
* navigation (`next` / `back` / `goTo`) walks positional indices,
|
|
1645
|
-
* `handleSubmit` validates the
|
|
1646
|
-
*
|
|
1647
|
-
* `
|
|
1710
|
+
* `handleSubmit` validates the whole step list from any step and never
|
|
1711
|
+
* advances (gate advance with `activeForm.handleSubmit(() =>
|
|
1712
|
+
* wizard.next())`), and URL synchronization rides on `restore` /
|
|
1713
|
+
* `persist` callbacks that default to `?step=<key>`.
|
|
1648
1714
|
*/
|
|
1649
1715
|
declare function useWizard<const S extends ReadonlyArray<StepSlot>>(options: WizardOptions & {
|
|
1650
1716
|
readonly steps: S;
|
|
@@ -1688,8 +1754,10 @@ type InjectWizardInput = {
|
|
|
1688
1754
|
* constructed with `useWizard({ steps, key })` to be reachable.
|
|
1689
1755
|
*
|
|
1690
1756
|
* Returns `null` when no matching wizard exists (no ambient ancestor,
|
|
1691
|
-
* or the named key isn't registered). A dev-mode warning points at
|
|
1692
|
-
* call site
|
|
1757
|
+
* or the named key isn't registered yet). A dev-mode warning points at
|
|
1758
|
+
* the call site, lists the registered keys, and flags the mount-timing
|
|
1759
|
+
* case (a wizard created by a child or sibling isn't registered until
|
|
1760
|
+
* its own setup runs). Always narrow before using:
|
|
1693
1761
|
*
|
|
1694
1762
|
* ```ts
|
|
1695
1763
|
* const wizard = injectWizard('signup')
|
|
@@ -1739,13 +1807,13 @@ declare function injectWizard(input?: string | InjectWizardInput): UseWizardRetu
|
|
|
1739
1807
|
* this one.
|
|
1740
1808
|
* - `wizard.reset()` clears every lazy slot's cache so a reboot truly
|
|
1741
1809
|
* resolves from scratch.
|
|
1742
|
-
* - Resolving to `undefined` drops the slot from the compiled
|
|
1743
|
-
* until the resolver next re-fires.
|
|
1810
|
+
* - Resolving to `null` or `undefined` drops the slot from the compiled
|
|
1811
|
+
* list until the resolver next re-fires.
|
|
1744
1812
|
*
|
|
1745
1813
|
* The runtime brand returned by `lazy()` is opaque. Use
|
|
1746
1814
|
* {@link isLazyMarker} to detect it.
|
|
1747
1815
|
*/
|
|
1748
|
-
declare function lazy<Ctx = WizardCtx>(resolve: (ctx: Ctx) => AnyForm | string | undefined): LazyMarker<Ctx>;
|
|
1816
|
+
declare function lazy<Ctx = WizardCtx>(resolve: (ctx: Ctx) => AnyForm | string | null | undefined): LazyMarker<Ctx>;
|
|
1749
1817
|
|
|
1750
1818
|
/**
|
|
1751
1819
|
* Stable identifiers for library-emitted `ValidationError` codes.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { G as GenericForm, u as FlatPath, O as NestedType, F as FormKey, U as UseFormConfiguration, a as AbstractSchema, ar as AcceptableDefaults, af as ValidateOnConfig, b as UseFormReturnType } from './attaform.
|
|
2
|
+
import { G as GenericForm, u as FlatPath, O as NestedType, F as FormKey, U as UseFormConfiguration, a as AbstractSchema, ar as AcceptableDefaults, af as ValidateOnConfig, b as UseFormReturnType } from './attaform.i_LA3X9o.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* The shape `form.values.<key>` returns at runtime.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as getRegistryFromApp, m as pathKeyToDotted } from './attaform.
|
|
1
|
+
import { i as getRegistryFromApp, m as pathKeyToDotted } from './attaform.CqwcTExO.mjs';
|
|
2
2
|
|
|
3
3
|
function renderAttaformState(app) {
|
|
4
4
|
const registry = getRegistryFromApp(app);
|
|
@@ -32,4 +32,4 @@ function hydrateAttaformState(app, payload) {
|
|
|
32
32
|
const DEVTOOLS_WINDOW_KEY = "__attaform_devtools__";
|
|
33
33
|
|
|
34
34
|
export { DEVTOOLS_WINDOW_KEY as D, hydrateAttaformState as h, renderAttaformState as r };
|
|
35
|
-
//# sourceMappingURL=attaform.
|
|
35
|
+
//# sourceMappingURL=attaform.OLtKd9gM.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attaform.
|
|
1
|
+
{"version":3,"file":"attaform.OLtKd9gM.mjs","sources":["../../src/runtime/core/serialize.ts","../../src/runtime/core/devtools-shared.ts"],"sourcesContent":["import type { App } from 'vue'\nimport type { FormKey } from '../types/types-api'\nimport { pathKeyToDotted, type PathKey } from './paths'\nimport { getRegistryFromApp, type SerializedFormData } from './registry'\n\n/**\n * Serialised snapshot of every form in a Vue app, produced by\n * `renderAttaformState` and consumed by `hydrateAttaformState`.\n *\n * JSON-safe — pass to `JSON.stringify`, `devalue`, or any other\n * serialiser before embedding in your SSR payload.\n */\nexport type SerializedAttaformState = {\n /** Tuples of `[formKey, snapshot]` for every form in the app. */\n readonly forms: ReadonlyArray<readonly [FormKey, SerializedFormData]>\n}\n\n/**\n * Snapshot every form on a Vue app for SSR. Call from your server\n * entry after rendering the app:\n *\n * ```ts\n * import { renderToString } from '@vue/server-renderer'\n * import { renderAttaformState, escapeForInlineScript } from 'attaform'\n *\n * const html = await renderToString(app)\n * const state = renderAttaformState(app)\n * const payload = escapeForInlineScript(JSON.stringify(state))\n *\n * return `\n * ${html}\n * <script>window.__ATTAFORM_STATE__ = ${payload}</script>\n * `\n * ```\n *\n * Pair with `hydrateAttaformState` on the client to restore the\n * forms in their server-rendered state. Nuxt users don't need this —\n * `attaform/nuxt` wires SSR automatically.\n */\nexport function renderAttaformState(app: App): SerializedAttaformState {\n const registry = getRegistryFromApp(app)\n const forms: Array<readonly [FormKey, SerializedFormData]> = []\n for (const [key, state] of registry.forms) {\n // Skip the blank field when the set is empty so the\n // wire payload stays minimal for forms that don't use it. The\n // optional shape on the consuming side handles the absence\n // cleanly (defaults to \"no blank paths\"). PathKey → dotted at\n // the boundary so the wire shape matches the rest of the\n // public path notation.\n const transientList: string[] = []\n for (const pk of state.blankPaths) {\n const d = pathKeyToDotted(pk as PathKey)\n if (d !== null) transientList.push(d)\n }\n forms.push([\n key,\n {\n form: state.form.value,\n schemaErrors: Array.from(state.schemaErrors.entries()),\n userErrors: Array.from(state.userErrors.entries()),\n fields: Array.from(state.fields.entries()),\n ...(transientList.length > 0 ? { blankPaths: transientList } : {}),\n },\n ])\n }\n return { forms }\n}\n\n/**\n * Restore forms from a server-rendered snapshot on the client. Call\n * from your client entry before mounting:\n *\n * ```ts\n * import { createApp } from 'vue'\n * import { createAttaform, hydrateAttaformState } from 'attaform'\n *\n * const app = createApp(App).use(createAttaform())\n * hydrateAttaformState(app, window.__ATTAFORM_STATE__)\n * app.mount('#app')\n * ```\n *\n * The next `useForm({ key })` call for each serialised form picks up\n * the snapshot transparently — no further action is required.\n */\nexport function hydrateAttaformState(app: App, payload: SerializedAttaformState): void {\n const registry = getRegistryFromApp(app)\n for (const [key, data] of payload.forms) {\n registry.pendingHydration.set(key, data)\n }\n}\n","/**\n * Shared building blocks for Attaform's two devtools surfaces — the Vue\n * DevTools (Chrome-extension) inspector wired up in `./devtools.ts`, and\n * the Nuxt DevTools (overlay) panel wired up via `../../nuxt.ts` +\n * `../pages/_attaform_devtools.vue`.\n *\n * Houses the window-bridge contract both surfaces consume so a new\n * bridge field lands in one file. Both surfaces render RAW form values\n * by design — DevTools is a dev-only surface, and redaction across every\n * place a value surfaces is impractical security theater rather than a\n * real safeguard.\n */\nimport type { AttaformRegistry } from './registry'\n\n/**\n * Property key on `window` that the Nuxt-side dev plugin attaches the\n * bridge object to. The iframe-mounted overlay panel reads\n * `window.parent[DEVTOOLS_WINDOW_KEY]` to reach the host app's registry.\n *\n * Underscored + namespaced to make accidental collision with consumer\n * globals vanishingly unlikely. Stable across versions — bumping it\n * would silently disconnect older library builds from newer overlay\n * panels in the same browser tab during a library upgrade.\n */\nexport const DEVTOOLS_WINDOW_KEY = '__attaform_devtools__'\n\n/**\n * Shape of the object the host plugin attaches to `window` in dev mode.\n * The iframe overlay panel reads this to discover the live registry and\n * render its forms.\n *\n * Single-registry assumption: the latest `createAttaform()` install\n * wins. Multi-app pages (rare; typically only seen in micro-frontend\n * setups) will only see one app's forms in the panel. Documented but\n * not actively supported — the alternative (a Set of registries with\n * union-rendering) is a future call if a real consumer hits it.\n */\nexport interface AttaformDevtoolsBridge {\n registry: AttaformRegistry\n /**\n * The library version, surfaced in the panel's footer for support /\n * bug-report context. Read from `package.json` at host-plugin init.\n */\n version: string\n}\n\ndeclare global {\n interface Window {\n [DEVTOOLS_WINDOW_KEY]?: AttaformDevtoolsBridge\n }\n}\n"],"names":[],"mappings":";;AAuCO,SAAS,oBAAoB,GAAA,EAAmC;AACrE,EAAA,MAAM,QAAA,GAAW,mBAAmB,GAAG,CAAA;AACvC,EAAA,MAAM,QAAuD,EAAC;AAC9D,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,CAAA,IAAK,SAAS,KAAA,EAAO;AAOzC,IAAA,MAAM,gBAA0B,EAAC;AACjC,IAAA,KAAA,MAAW,EAAA,IAAM,MAAM,UAAA,EAAY;AACjC,MAAA,MAAM,CAAA,GAAI,gBAAgB,EAAa,CAAA;AACvC,MAAA,IAAI,CAAA,KAAM,IAAA,EAAM,aAAA,CAAc,IAAA,CAAK,CAAC,CAAA;AAAA,IACtC;AACA,IAAA,KAAA,CAAM,IAAA,CAAK;AAAA,MACT,GAAA;AAAA,MACA;AAAA,QACE,IAAA,EAAM,MAAM,IAAA,CAAK,KAAA;AAAA,QACjB,cAAc,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,YAAA,CAAa,SAAS,CAAA;AAAA,QACrD,YAAY,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,UAAA,CAAW,SAAS,CAAA;AAAA,QACjD,QAAQ,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,SAAS,CAAA;AAAA,QACzC,GAAI,cAAc,MAAA,GAAS,CAAA,GAAI,EAAE,UAAA,EAAY,aAAA,KAAkB;AAAC;AAClE,KACD,CAAA;AAAA,EACH;AACA,EAAA,OAAO,EAAE,KAAA,EAAM;AACjB;AAkBO,SAAS,oBAAA,CAAqB,KAAU,OAAA,EAAwC;AACrF,EAAA,MAAM,QAAA,GAAW,mBAAmB,GAAG,CAAA;AACvC,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,IAAI,CAAA,IAAK,QAAQ,KAAA,EAAO;AACvC,IAAA,QAAA,CAAS,gBAAA,CAAiB,GAAA,CAAI,GAAA,EAAK,IAAI,CAAA;AAAA,EACzC;AACF;;ACjEO,MAAM,mBAAA,GAAsB;;;;"}
|
|
@@ -3,6 +3,7 @@ import { isRef } from 'vue';
|
|
|
3
3
|
const V_REGISTER_MARKER = Symbol.for("attaform:v-register-directive");
|
|
4
4
|
const REGISTER_OWNER_MARKER = Symbol.for("attaform:register-owner-marker");
|
|
5
5
|
const SSR_COMPONENT_HOST_MODIFIER = "attaformComponentHost";
|
|
6
|
+
const V_REGISTER_COMPILED_MODIFIER = "attaformCompiled";
|
|
6
7
|
function isRegisterValue(val) {
|
|
7
8
|
if (typeof val !== "object" || val === null) return false;
|
|
8
9
|
if (!("innerRef" in val)) return false;
|
|
@@ -17,5 +18,5 @@ function isTransforming(value) {
|
|
|
17
18
|
return isRegisterValue(value) && value.transforming;
|
|
18
19
|
}
|
|
19
20
|
|
|
20
|
-
export { REGISTER_OWNER_MARKER as R, SSR_COMPONENT_HOST_MODIFIER as S,
|
|
21
|
-
//# sourceMappingURL=attaform.
|
|
21
|
+
export { REGISTER_OWNER_MARKER as R, SSR_COMPONENT_HOST_MODIFIER as S, V_REGISTER_COMPILED_MODIFIER as V, isTransforming as a, V_REGISTER_MARKER as b, isRegisterValue as i };
|
|
22
|
+
//# sourceMappingURL=attaform.Vp2-CWZB.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attaform.Vp2-CWZB.mjs","sources":["../../src/runtime/core/register-protocol.ts"],"sourcesContent":["import { isRef } from 'vue'\nimport type { InternalRegisterValue, RegisterValue } from '../types/types-api'\n\n// Shared register-protocol primitives: the markers and value guards that\n// the v-register directive, its file / lifecycle satellites, and\n// useRegister all build on. They live in this leaf (depending only on vue\n// and the types module) so those modules don't import directive.ts back,\n// which would form an import cycle.\n\n/**\n * Marker installed on the v-register directive object so consumers\n * (notably `useRegister`) can identify it in a child vnode's\n * directive list even when the consumer's bundler hasn't installed\n * attaform's compile-time transforms. `Symbol.for(...)` round-trips\n * across duplicate bundle copies: `attaform` and `attaform/zod` can\n * land on different `vRegister` references in the playground or\n * under pnpm-hoist edge cases, but both carry the same marker.\n */\nexport const V_REGISTER_MARKER: unique symbol = Symbol.for('attaform:v-register-directive')\n\n/**\n * Marker on the rendered root DOM element. Set by `useRegister`'s\n * `onMounted` hook; read by the directive's deferred warn check to\n * skip the \"is a no-op\" warn for components that handle binding via\n * an inner v-register.\n *\n * `Symbol.for(...)` so the marker round-trips across duplicate copies\n * of attaform — see `assignKey` in core/directive.ts for the same\n * reasoning. `useRegister` and the directive are typically loaded\n * from the same module copy, but a consumer importing from\n * `attaform/zod` (Vite-optimized bundle) and the Nuxt\n * plugin's relative-path import (live ESM) can land on different\n * copies; a global symbol means the marker check still works.\n */\nexport const REGISTER_OWNER_MARKER: unique symbol = Symbol.for('attaform:register-owner-marker')\n\n/**\n * Directive modifier the `componentBridgeTransform` stamps onto a\n * `v-register` that lands on a component host (or kebab custom element).\n * It is the compile-time -> runtime signal the directive's `getSSRProps`\n * reads under compiled SSR, where Vue passes a `null` vnode and the host\n * is otherwise indistinguishable from a native control. autoAria then\n * suppresses its attrs on the host root (the inner control the component\n * re-binds via useRegister carries them). Namespaced to avoid collision\n * with any author-written modifier. (#404)\n */\nexport const SSR_COMPONENT_HOST_MODIFIER = 'attaformComponentHost'\n\n/**\n * Directive modifier the `redundantBindingWarnTransform` stamps onto\n * every `v-register` it processes. It is the compile-time -> runtime\n * signal that Attaform's template transforms are active, and it lets the\n * runtime redundant-binding diagnostic (in the directive's `created`\n * hook) stand down.\n *\n * The hand-off matters because `inputTextAreaNodeTransform` strips the\n * author's `value` / `checked` and injects its own. Once that has run,\n * `vnode.props` no longer reflects what the author wrote, so a runtime\n * check would flag every field. With this marker present the compile\n * layer owns detection (it reads the authored props BEFORE injection);\n * with it absent (no bundler plugin) the runtime layer reads the\n * untouched `vnode.props` directly. Exactly one layer fires per\n * consumer, never both.\n *\n * Namespaced to avoid collision with any author-written modifier, like\n * `SSR_COMPONENT_HOST_MODIFIER` above.\n */\nexport const V_REGISTER_COMPILED_MODIFIER = 'attaformCompiled'\n\n/**\n * Type guard for a `RegisterValue`. Returns `true` when `val` looks\n * like the object returned from `form.register(path)`.\n *\n * ```ts\n * if (isRegisterValue(slotValue)) {\n * // slotValue.innerRef is now a Ref<unknown>\n * }\n * ```\n *\n * Useful when building wrapper components that accept either a\n * `RegisterValue` or a plain ref via the same prop.\n */\nexport function isRegisterValue<Value = unknown>(val: unknown): val is RegisterValue<Value> {\n if (typeof val !== 'object' || val === null) return false\n if (!('innerRef' in val)) return false\n if (!isRef(val.innerRef)) return false\n if (!('registerElement' in val)) return false\n if (typeof val.registerElement !== 'function') return false\n if (!('setValueWithInternalPath' in val)) return false\n if (typeof val.setValueWithInternalPath !== 'function') return false\n return true\n}\n\n/**\n * `true` while a deferred async transform is in flight at this path.\n * `beginTransform` flips it synchronously inside the assigner, so a\n * listener's post-write force-sync block reads it (right after the\n * assigner returns) to skip snapping the DOM back to stale storage —\n * the resolved value is painted in by the orchestrator's `syncDom`\n * once the run lands.\n */\nexport function isTransforming(value: unknown): boolean {\n return isRegisterValue(value) && (value as InternalRegisterValue).transforming\n}\n"],"names":[],"mappings":";;AAkBO,MAAM,iBAAA,GAAmC,MAAA,CAAO,GAAA,CAAI,+BAA+B;AAgBnF,MAAM,qBAAA,GAAuC,MAAA,CAAO,GAAA,CAAI,gCAAgC;AAYxF,MAAM,2BAAA,GAA8B;AAqBpC,MAAM,4BAAA,GAA+B;AAerC,SAAS,gBAAiC,GAAA,EAA2C;AAC1F,EAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,IAAY,GAAA,KAAQ,MAAM,OAAO,KAAA;AACpD,EAAA,IAAI,EAAE,UAAA,IAAc,GAAA,CAAA,EAAM,OAAO,KAAA;AACjC,EAAA,IAAI,CAAC,KAAA,CAAM,GAAA,CAAI,QAAQ,GAAG,OAAO,KAAA;AACjC,EAAA,IAAI,EAAE,iBAAA,IAAqB,GAAA,CAAA,EAAM,OAAO,KAAA;AACxC,EAAA,IAAI,OAAO,GAAA,CAAI,eAAA,KAAoB,UAAA,EAAY,OAAO,KAAA;AACtD,EAAA,IAAI,EAAE,0BAAA,IAA8B,GAAA,CAAA,EAAM,OAAO,KAAA;AACjD,EAAA,IAAI,OAAO,GAAA,CAAI,wBAAA,KAA6B,UAAA,EAAY,OAAO,KAAA;AAC/D,EAAA,OAAO,IAAA;AACT;AAUO,SAAS,eAAe,KAAA,EAAyB;AACtD,EAAA,OAAO,eAAA,CAAgB,KAAK,CAAA,IAAM,KAAA,CAAgC,YAAA;AACpE;;;;"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const injectWizard = require('./attaform.
|
|
4
|
-
const paths = require('./attaform.
|
|
5
|
-
const walkFieldMeta = require('./attaform.
|
|
3
|
+
const injectWizard = require('./attaform.BkUzunyB.cjs');
|
|
4
|
+
const paths = require('./attaform.3heDHayA.cjs');
|
|
5
|
+
const walkFieldMeta = require('./attaform.B5YcWrKi.cjs');
|
|
6
6
|
const zod = require('zod');
|
|
7
7
|
|
|
8
8
|
const fieldMeta = walkFieldMeta.fieldMetaStore;
|
|
@@ -1299,4 +1299,4 @@ exports.unwrapPipe = unwrapPipe;
|
|
|
1299
1299
|
exports.useForm = useForm;
|
|
1300
1300
|
exports.withMeta = withMeta;
|
|
1301
1301
|
exports.zodV4Adapter = zodV4Adapter;
|
|
1302
|
-
//# sourceMappingURL=attaform.
|
|
1302
|
+
//# sourceMappingURL=attaform.Xe8dATED.cjs.map
|