attaform 0.27.3 → 0.27.4
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/abstract.cjs +1 -1
- package/dist/abstract.d.cts +2 -2
- package/dist/abstract.d.mts +2 -2
- package/dist/abstract.d.ts +2 -2
- package/dist/abstract.mjs +1 -1
- package/dist/chunks/fingerprint2.cjs +1 -1
- package/dist/chunks/fingerprint2.mjs +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +2 -2
- package/dist/shared/{attaform.DeHCOlC8.cjs → attaform.B3spfqIA.cjs} +3 -3
- package/dist/shared/{attaform.DeHCOlC8.cjs.map → attaform.B3spfqIA.cjs.map} +1 -1
- package/dist/shared/{attaform.DuVCclwv.mjs → attaform.BrVzB14N.mjs} +3 -3
- package/dist/shared/{attaform.DuVCclwv.mjs.map → attaform.BrVzB14N.mjs.map} +1 -1
- package/dist/shared/{attaform.Mg4g-J0z.cjs → attaform.C9arOC5p.cjs} +4 -4
- package/dist/shared/{attaform.Mg4g-J0z.cjs.map → attaform.C9arOC5p.cjs.map} +1 -1
- package/dist/shared/{attaform.DHQjaGMP.mjs → attaform.CC4KCx_q.mjs} +4 -4
- package/dist/shared/{attaform.DHQjaGMP.mjs.map → attaform.CC4KCx_q.mjs.map} +1 -1
- package/dist/shared/{attaform.dX58Auwf.cjs → attaform.CX2NHAFs.cjs} +2 -2
- package/dist/shared/{attaform.dX58Auwf.cjs.map → attaform.CX2NHAFs.cjs.map} +1 -1
- package/dist/shared/{attaform.BjGedLx2.d.cts → attaform.Cjh6b6xU.d.cts} +50 -14
- package/dist/shared/{attaform.BqkFQ2B9.mjs → attaform.CuUx4jWI.mjs} +41 -25
- package/dist/shared/{attaform.ij2W7VTw.cjs.map → attaform.CuUx4jWI.mjs.map} +1 -1
- package/dist/shared/{attaform.gqOCvpSB.d.ts → attaform.DKtXMaJB.d.ts} +50 -14
- package/dist/shared/{attaform.BOIpRdeG.cjs → attaform.DXwJVUNS.cjs} +3 -3
- package/dist/shared/{attaform.BOIpRdeG.cjs.map → attaform.DXwJVUNS.cjs.map} +1 -1
- package/dist/shared/{attaform.ij2W7VTw.cjs → attaform.Ib2seKUE.cjs} +41 -25
- package/dist/shared/{attaform.BqkFQ2B9.mjs.map → attaform.Ib2seKUE.cjs.map} +1 -1
- package/dist/shared/{attaform.BKxpBJVF.mjs → attaform.a1GnhjVk.mjs} +2 -2
- package/dist/shared/{attaform.BKxpBJVF.mjs.map → attaform.a1GnhjVk.mjs.map} +1 -1
- package/dist/shared/{attaform.CEZP3i3I.d.mts → attaform.gj8dtOlx.d.mts} +50 -14
- package/dist/shared/{attaform.DDIn4fv-.mjs → attaform.shkNCMEz.mjs} +3 -3
- package/dist/shared/{attaform.DDIn4fv-.mjs.map → attaform.shkNCMEz.mjs.map} +1 -1
- package/dist/zod-v3.cjs +2 -2
- package/dist/zod-v3.d.cts +1 -1
- package/dist/zod-v3.d.mts +1 -1
- package/dist/zod-v3.d.ts +1 -1
- package/dist/zod-v3.mjs +2 -2
- package/dist/zod-v4.cjs +2 -2
- package/dist/zod-v4.d.cts +2 -2
- package/dist/zod-v4.d.mts +2 -2
- package/dist/zod-v4.d.ts +2 -2
- package/dist/zod-v4.mjs +2 -2
- package/dist/zod.cjs +2 -2
- package/dist/zod.d.cts +1 -1
- package/dist/zod.d.mts +1 -1
- package/dist/zod.d.ts +1 -1
- package/dist/zod.mjs +2 -2
- package/package.json +1 -1
|
@@ -1036,9 +1036,9 @@ type AnyForm = {
|
|
|
1036
1036
|
* - `gate`: this step's own role as a hard prerequisite. `null` when the
|
|
1037
1037
|
* step is not a `gate()`; `'uncleared'` while its member form is
|
|
1038
1038
|
* unconfirmed (so it seals every later step); `'cleared'` once
|
|
1039
|
-
* confirmed by a clean member submit or
|
|
1040
|
-
*
|
|
1041
|
-
* that a function slot drops resolves to `null`.
|
|
1039
|
+
* confirmed by a clean member submit or seeded cleared via
|
|
1040
|
+
* `defaultStatuses`. Reflects the live compiled shape, so a conditional
|
|
1041
|
+
* `gate()` that a function slot drops resolves to `null`.
|
|
1042
1042
|
*
|
|
1043
1043
|
* Noop forms generated for string slots surface as default-valid
|
|
1044
1044
|
* (`{ valid: true, dirty: false, submitted: false, errorCount: 0, locked: false, gate: null }`),
|
|
@@ -1054,12 +1054,27 @@ type FormStatus = {
|
|
|
1054
1054
|
readonly gate: 'cleared' | 'uncleared' | null;
|
|
1055
1055
|
};
|
|
1056
1056
|
/**
|
|
1057
|
-
* Seed shape accepted by `useWizard({ defaultStatuses })`.
|
|
1058
|
-
*
|
|
1059
|
-
*
|
|
1060
|
-
*
|
|
1061
|
-
|
|
1062
|
-
|
|
1057
|
+
* Seed shape accepted by `useWizard({ defaultStatuses })`. Every field is
|
|
1058
|
+
* optional; an omitted meta field falls back to the pending sentinel on
|
|
1059
|
+
* read.
|
|
1060
|
+
*
|
|
1061
|
+
* `locked` is never accepted: it is purely live-derived (sealed behind an
|
|
1062
|
+
* earlier uncleared gate) and overlaid on every status read, so a seeded
|
|
1063
|
+
* value would be ignored.
|
|
1064
|
+
*
|
|
1065
|
+
* `gate` is a WRITE-only seed, not a status field echoed back on read. A
|
|
1066
|
+
* seed of `'cleared'` latches the gate's cleared state once at construction
|
|
1067
|
+
* (an SSR restore of a confirmed prerequisite); the live `gate` overlay
|
|
1068
|
+
* then owns the read. `'uncleared'` is the default and seeds nothing. Only
|
|
1069
|
+
* a step that compiles to a `gate()` honors it — other keys ignore it.
|
|
1070
|
+
*/
|
|
1071
|
+
type FormStatusSeed = {
|
|
1072
|
+
readonly valid?: boolean;
|
|
1073
|
+
readonly dirty?: boolean;
|
|
1074
|
+
readonly submitted?: boolean;
|
|
1075
|
+
readonly errorCount?: number;
|
|
1076
|
+
readonly gate?: 'cleared' | 'uncleared';
|
|
1077
|
+
};
|
|
1063
1078
|
/**
|
|
1064
1079
|
* Flat error shape returned per form by `wizard.allErrors[key]`. Each
|
|
1065
1080
|
* entry carries the formKey + path tuple so consumers can route to the
|
|
@@ -1314,12 +1329,20 @@ type WizardOptions = {
|
|
|
1314
1329
|
* Status resolution priority per form:
|
|
1315
1330
|
* 1. `store.defaultsResolved === true` → derive from `form.meta`
|
|
1316
1331
|
* 2. else noop form → built-in always-valid status
|
|
1317
|
-
* 3. else seed value for this key →
|
|
1332
|
+
* 3. else seed value for this key → seed over the pending sentinel
|
|
1318
1333
|
* 4. else → pending sentinel
|
|
1319
1334
|
*
|
|
1320
|
-
*
|
|
1321
|
-
*
|
|
1322
|
-
*
|
|
1335
|
+
* `locked` is never seeded: it is computed live from the wizard's gates
|
|
1336
|
+
* and overlaid on every status read. `gate: 'cleared'` IS honored, but as
|
|
1337
|
+
* a one-shot seed of the gate's cleared latch at construction (an SSR
|
|
1338
|
+
* restore of a confirmed prerequisite), not as a status field echoed on
|
|
1339
|
+
* read — the live `gate` overlay owns the read. Only a step that compiles
|
|
1340
|
+
* to a `gate()` honors it. See `FormStatusSeed`.
|
|
1341
|
+
*
|
|
1342
|
+
* SSR note: the async factory resolves after hydration (client-only), so
|
|
1343
|
+
* a gate seeded through it clears post-hydration. For a gate that must
|
|
1344
|
+
* render open on the first server byte, use the plain or sync-factory
|
|
1345
|
+
* form (resolve server truth in the page's `setup` await).
|
|
1323
1346
|
*
|
|
1324
1347
|
* Unknown keys in the seed object dev-warn so a stale resume payload
|
|
1325
1348
|
* surfaces at construction.
|
|
@@ -1559,7 +1582,19 @@ type WizardForms<S> = FormsRecordOf<S> & Readonly<Record<FormKey, AnyForm>>;
|
|
|
1559
1582
|
* - `reset()` — zeros wizard lifecycle (`submissionAttempts`,
|
|
1560
1583
|
* `visited`), resets every form, returns
|
|
1561
1584
|
* `currentStep` to `steps[0].key`, and invokes
|
|
1562
|
-
* `persist` with the cleared state.
|
|
1585
|
+
* `persist` with the cleared state. Re-applies the
|
|
1586
|
+
* `defaultStatuses` gate seed, so a reboot returns to
|
|
1587
|
+
* the seeded initial clearance, not fully sealed.
|
|
1588
|
+
* - `relock(key, commit)` — re-seal a cleared gate, contingent on
|
|
1589
|
+
* `commit`. Awaits `commit` (a server-side revoke) and
|
|
1590
|
+
* re-seals only if it resolves clean, so the gate reflects
|
|
1591
|
+
* server-confirmed truth the same way a clearing submit
|
|
1592
|
+
* does; a thrown `commit` leaves it as-is. Seal-only (never
|
|
1593
|
+
* opens a gate), so it cannot become the leading-signal
|
|
1594
|
+
* foot-gun `gate()` exists to prevent. `commit` is required
|
|
1595
|
+
* (pass `() => {}` for a deliberate client-only re-seal).
|
|
1596
|
+
* Resolves whether the gate ended up sealed; never rejects.
|
|
1597
|
+
* Resolves `false` (dev-warn) on a non-gate key.
|
|
1563
1598
|
*/
|
|
1564
1599
|
type UseWizardReturnType<S extends ReadonlyArray<StepSlot> = ReadonlyArray<StepSlot>> = {
|
|
1565
1600
|
readonly key: string;
|
|
@@ -1588,6 +1623,7 @@ type UseWizardReturnType<S extends ReadonlyArray<StepSlot> = ReadonlyArray<StepS
|
|
|
1588
1623
|
readonly tryNext: () => Promise<boolean>;
|
|
1589
1624
|
readonly handleSubmit: (onSubmit: WizardOnSubmit, onError?: WizardOnError) => (event?: Event) => Promise<void>;
|
|
1590
1625
|
readonly reset: () => void;
|
|
1626
|
+
readonly relock: (key: FormKey, commit: () => void | Promise<void>) => Promise<boolean>;
|
|
1591
1627
|
};
|
|
1592
1628
|
|
|
1593
1629
|
/**
|
|
@@ -6687,24 +6687,6 @@ function useWizard(options) {
|
|
|
6687
6687
|
(slot) => isGateMarker(slot) || isLazyMarker(slot) || typeof slot === "function"
|
|
6688
6688
|
);
|
|
6689
6689
|
const clearedGates = reactive(/* @__PURE__ */ new Set());
|
|
6690
|
-
const seededSampled = /* @__PURE__ */ new Set();
|
|
6691
|
-
function isGateVerdictSettled(key) {
|
|
6692
|
-
const store = registry.forms.get(key);
|
|
6693
|
-
if (store === void 0) return false;
|
|
6694
|
-
return store.defaultsResolved.value === true && store.firstValidationDone.value === true && store.activeValidations.value === 0;
|
|
6695
|
-
}
|
|
6696
|
-
function isGateFormValid(key) {
|
|
6697
|
-
const form = formsRecord.value[key] ?? formsAccumulator.get(key);
|
|
6698
|
-
if (form === void 0) return false;
|
|
6699
|
-
return asStatusSource(form).meta?.valid ?? false;
|
|
6700
|
-
}
|
|
6701
|
-
function sampleSeededGate(key) {
|
|
6702
|
-
if (seededSampled.has(key)) return;
|
|
6703
|
-
if (noopForms.has(key)) return;
|
|
6704
|
-
if (!isGateVerdictSettled(key)) return;
|
|
6705
|
-
seededSampled.add(key);
|
|
6706
|
-
if (isGateFormValid(key)) clearedGates.add(key);
|
|
6707
|
-
}
|
|
6708
6690
|
const gateSubs = /* @__PURE__ */ new Map();
|
|
6709
6691
|
function reconcileGates() {
|
|
6710
6692
|
const gateKeys = /* @__PURE__ */ new Set();
|
|
@@ -6721,7 +6703,6 @@ function useWizard(options) {
|
|
|
6721
6703
|
);
|
|
6722
6704
|
}
|
|
6723
6705
|
}
|
|
6724
|
-
sampleSeededGate(key);
|
|
6725
6706
|
}
|
|
6726
6707
|
for (const [key, unsub] of gateSubs) {
|
|
6727
6708
|
if (!gateKeys.has(key)) {
|
|
@@ -6779,8 +6760,7 @@ function useWizard(options) {
|
|
|
6779
6760
|
for (const step of compiledSteps.value) {
|
|
6780
6761
|
if (!step.isGate) continue;
|
|
6781
6762
|
const store = registry.forms.get(step.key);
|
|
6782
|
-
|
|
6783
|
-
parts.push(`${step.key}:${store !== void 0 ? 1 : 0}:${settled ? 1 : 0}`);
|
|
6763
|
+
parts.push(`${step.key}:${store !== void 0 ? 1 : 0}`);
|
|
6784
6764
|
}
|
|
6785
6765
|
return parts.join("|");
|
|
6786
6766
|
},
|
|
@@ -6813,20 +6793,30 @@ function useWizard(options) {
|
|
|
6813
6793
|
});
|
|
6814
6794
|
}
|
|
6815
6795
|
}
|
|
6796
|
+
function applyGateSeed(map) {
|
|
6797
|
+
if (map === void 0 || !mightGate) return;
|
|
6798
|
+
const gates = gatePositions.value;
|
|
6799
|
+
for (const key of Object.keys(map)) {
|
|
6800
|
+
if (map[key]?.gate === "cleared" && gates.includes(key)) clearedGates.add(key);
|
|
6801
|
+
}
|
|
6802
|
+
}
|
|
6816
6803
|
const seedRef = ref(void 0);
|
|
6817
6804
|
const seedInput = options.defaultStatuses;
|
|
6818
6805
|
if (seedInput !== void 0) {
|
|
6819
6806
|
const resolved = resolveTrichotomy(seedInput);
|
|
6820
6807
|
if (resolved.kind === "sync") {
|
|
6821
6808
|
seedRef.value = resolved.value;
|
|
6809
|
+
applyGateSeed(resolved.value);
|
|
6822
6810
|
} else {
|
|
6823
6811
|
const eager = resolved.factory();
|
|
6824
6812
|
if (eager instanceof Promise) {
|
|
6825
6813
|
void eager.then((value) => {
|
|
6826
6814
|
seedRef.value = value;
|
|
6815
|
+
applyGateSeed(value);
|
|
6827
6816
|
});
|
|
6828
6817
|
} else {
|
|
6829
6818
|
seedRef.value = eager;
|
|
6819
|
+
applyGateSeed(eager);
|
|
6830
6820
|
}
|
|
6831
6821
|
}
|
|
6832
6822
|
}
|
|
@@ -6858,7 +6848,7 @@ function useWizard(options) {
|
|
|
6858
6848
|
return locked || gate !== null ? { ...NOOP_VALID_STATUS, locked, gate } : NOOP_VALID_STATUS;
|
|
6859
6849
|
}
|
|
6860
6850
|
const seed = seedRef.value?.[form.key];
|
|
6861
|
-
if (seed !== void 0) return { ...seed, locked, gate };
|
|
6851
|
+
if (seed !== void 0) return { ...PENDING_STATUS, ...seed, locked, gate };
|
|
6862
6852
|
return locked || gate !== null ? { ...PENDING_STATUS, locked, gate } : PENDING_STATUS;
|
|
6863
6853
|
});
|
|
6864
6854
|
statusCache.set(form.key, computedStatus);
|
|
@@ -7350,14 +7340,16 @@ function useWizard(options) {
|
|
|
7350
7340
|
submitError.value = null;
|
|
7351
7341
|
if (mightGate) {
|
|
7352
7342
|
clearedGates.clear();
|
|
7353
|
-
seededSampled.clear();
|
|
7354
7343
|
}
|
|
7355
7344
|
lazyEpoch.value += 1;
|
|
7356
7345
|
for (const step of compiledSteps.value) {
|
|
7357
7346
|
const full = asSubmissionSource(step.form);
|
|
7358
7347
|
if (typeof full.reset === "function") full.reset();
|
|
7359
7348
|
}
|
|
7360
|
-
if (mightGate)
|
|
7349
|
+
if (mightGate) {
|
|
7350
|
+
reconcileGates();
|
|
7351
|
+
applyGateSeed(seedRef.value);
|
|
7352
|
+
}
|
|
7361
7353
|
const firstStep = compiledSteps.value[0];
|
|
7362
7354
|
if (firstStep !== void 0) {
|
|
7363
7355
|
const landing = commitActiveKey(firstStep.key);
|
|
@@ -7368,6 +7360,29 @@ function useWizard(options) {
|
|
|
7368
7360
|
}
|
|
7369
7361
|
}
|
|
7370
7362
|
}
|
|
7363
|
+
async function relock(key, commit) {
|
|
7364
|
+
if (!mightGate || !gatePositions.value.includes(key)) {
|
|
7365
|
+
if (__DEV__) {
|
|
7366
|
+
console.warn(
|
|
7367
|
+
`[attaform] useWizard.relock(${JSON.stringify(key)}): no gate at that key; nothing to re-lock.`
|
|
7368
|
+
);
|
|
7369
|
+
}
|
|
7370
|
+
return false;
|
|
7371
|
+
}
|
|
7372
|
+
try {
|
|
7373
|
+
await commit();
|
|
7374
|
+
} catch (err) {
|
|
7375
|
+
if (__DEV__) {
|
|
7376
|
+
console.warn(
|
|
7377
|
+
`[attaform] useWizard.relock(${JSON.stringify(key)}): commit threw, so the gate was not re-sealed.`,
|
|
7378
|
+
err
|
|
7379
|
+
);
|
|
7380
|
+
}
|
|
7381
|
+
return false;
|
|
7382
|
+
}
|
|
7383
|
+
clearedGates.delete(key);
|
|
7384
|
+
return true;
|
|
7385
|
+
}
|
|
7371
7386
|
if (mightGate) {
|
|
7372
7387
|
watchEffect(() => {
|
|
7373
7388
|
const key = activeKey.value;
|
|
@@ -7393,6 +7408,7 @@ function useWizard(options) {
|
|
|
7393
7408
|
tryNext,
|
|
7394
7409
|
handleSubmit,
|
|
7395
7410
|
reset,
|
|
7411
|
+
relock,
|
|
7396
7412
|
get currentStep() {
|
|
7397
7413
|
return currentStep.value;
|
|
7398
7414
|
},
|
|
@@ -7573,4 +7589,4 @@ function escapeForInlineScript(json) {
|
|
|
7573
7589
|
}
|
|
7574
7590
|
|
|
7575
7591
|
export { AttaformErrorCode as A, DEFAULT_TIMINGS as D, defaultDisplayState as a, defineCoercion as b, injectWizard as c, defaultCoercionRules as d, escapeForInlineScript as e, isUnset as f, gate as g, useAbstractForm as h, injectForm as i, useRegister as j, useWizard as k, lazy as l, makeDefaultDisplayState as m, isPlainRecord as n, safeAssign as o, slimKindOf as p, humanize as q, getAtPath as r, safeOwnRead as s, setAtPath as t, unset as u };
|
|
7576
|
-
//# sourceMappingURL=attaform.
|
|
7592
|
+
//# sourceMappingURL=attaform.CuUx4jWI.mjs.map
|