attaform 0.20.2 → 0.21.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/dist/chunks/dev-key-collision-warnings.cjs +58 -0
  2. package/dist/chunks/dev-key-collision-warnings.cjs.map +1 -0
  3. package/dist/chunks/dev-key-collision-warnings.mjs +55 -0
  4. package/dist/chunks/dev-key-collision-warnings.mjs.map +1 -0
  5. package/dist/chunks/devtools.cjs +1 -1
  6. package/dist/chunks/devtools.mjs +1 -1
  7. package/dist/chunks/fingerprint.cjs +186 -0
  8. package/dist/chunks/fingerprint.cjs.map +1 -0
  9. package/dist/chunks/fingerprint.mjs +184 -0
  10. package/dist/chunks/fingerprint.mjs.map +1 -0
  11. package/dist/chunks/fingerprint2.cjs +162 -0
  12. package/dist/chunks/fingerprint2.cjs.map +1 -0
  13. package/dist/chunks/fingerprint2.mjs +160 -0
  14. package/dist/chunks/fingerprint2.mjs.map +1 -0
  15. package/dist/chunks/indexeddb.cjs +1 -1
  16. package/dist/chunks/indexeddb.mjs +1 -1
  17. package/dist/chunks/local-storage.cjs +1 -1
  18. package/dist/chunks/local-storage.mjs +1 -1
  19. package/dist/chunks/multi-tab-sync.cjs +367 -0
  20. package/dist/chunks/multi-tab-sync.cjs.map +1 -0
  21. package/dist/chunks/multi-tab-sync.mjs +364 -0
  22. package/dist/chunks/multi-tab-sync.mjs.map +1 -0
  23. package/dist/chunks/session-storage.cjs +1 -1
  24. package/dist/chunks/session-storage.mjs +1 -1
  25. package/dist/chunks/wire-persistence.cjs +396 -0
  26. package/dist/chunks/wire-persistence.cjs.map +1 -0
  27. package/dist/chunks/wire-persistence.mjs +394 -0
  28. package/dist/chunks/wire-persistence.mjs.map +1 -0
  29. package/dist/esbuild.cjs +28 -0
  30. package/dist/esbuild.cjs.map +1 -0
  31. package/dist/esbuild.d.cts +56 -0
  32. package/dist/esbuild.d.mts +56 -0
  33. package/dist/esbuild.d.ts +56 -0
  34. package/dist/esbuild.mjs +26 -0
  35. package/dist/esbuild.mjs.map +1 -0
  36. package/dist/index.cjs +5 -3
  37. package/dist/index.cjs.map +1 -1
  38. package/dist/index.d.cts +66 -70
  39. package/dist/index.d.mts +66 -70
  40. package/dist/index.d.ts +66 -70
  41. package/dist/index.mjs +5 -5
  42. package/dist/nuxt.d.cts +1 -1
  43. package/dist/nuxt.d.mts +1 -1
  44. package/dist/nuxt.d.ts +1 -1
  45. package/dist/rollup.cjs +24 -0
  46. package/dist/rollup.cjs.map +1 -0
  47. package/dist/rollup.d.cts +35 -0
  48. package/dist/rollup.d.mts +35 -0
  49. package/dist/rollup.d.ts +35 -0
  50. package/dist/rollup.mjs +22 -0
  51. package/dist/rollup.mjs.map +1 -0
  52. package/dist/rspack.cjs +10 -0
  53. package/dist/rspack.cjs.map +1 -0
  54. package/dist/rspack.d.cts +40 -0
  55. package/dist/rspack.d.mts +40 -0
  56. package/dist/rspack.d.ts +40 -0
  57. package/dist/rspack.mjs +8 -0
  58. package/dist/rspack.mjs.map +1 -0
  59. package/dist/runtime/plugins/attaform.cjs +2 -2
  60. package/dist/runtime/plugins/attaform.mjs +2 -2
  61. package/dist/shared/attaform.BJGA_UOS.mjs +37 -0
  62. package/dist/shared/attaform.BJGA_UOS.mjs.map +1 -0
  63. package/dist/shared/attaform.BRGIpZo4.cjs +26 -0
  64. package/dist/shared/attaform.BRGIpZo4.cjs.map +1 -0
  65. package/dist/shared/{attaform.DAKrGhxc.cjs → attaform.BSkvn43g.cjs} +101 -417
  66. package/dist/shared/attaform.BSkvn43g.cjs.map +1 -0
  67. package/dist/shared/{attaform.sWm8B15V.d.mts → attaform.BWfliRIK.d.cts} +172 -2
  68. package/dist/shared/{attaform.BGk8cfw2.mjs → attaform.Be8NZG9M.mjs} +178 -21
  69. package/dist/shared/attaform.Be8NZG9M.mjs.map +1 -0
  70. package/dist/shared/{attaform.D2SCCd4O.cjs → attaform.Bq5sX7TF.cjs} +2 -2
  71. package/dist/shared/{attaform.D2SCCd4O.cjs.map → attaform.Bq5sX7TF.cjs.map} +1 -1
  72. package/dist/shared/{attaform.ceGEAEMk.d.ts → attaform.Bv7dRDWK.d.ts} +172 -2
  73. package/dist/shared/attaform.C3Doa9Pt.mjs +24 -0
  74. package/dist/shared/attaform.C3Doa9Pt.mjs.map +1 -0
  75. package/dist/shared/{attaform.B_hph5AE.cjs → attaform.CICFZ1iS.cjs} +178 -20
  76. package/dist/shared/attaform.CICFZ1iS.cjs.map +1 -0
  77. package/dist/shared/attaform.CQN9R62B.cjs +39 -0
  78. package/dist/shared/attaform.CQN9R62B.cjs.map +1 -0
  79. package/dist/shared/{attaform.CwLjUqmQ.cjs → attaform.ClXwitZj.cjs} +735 -960
  80. package/dist/shared/attaform.ClXwitZj.cjs.map +1 -0
  81. package/dist/shared/{attaform.99cfHcIt.d.cts → attaform.D0dWZsJt.d.cts} +349 -77
  82. package/dist/shared/{attaform.99cfHcIt.d.mts → attaform.D0dWZsJt.d.mts} +349 -77
  83. package/dist/shared/{attaform.99cfHcIt.d.ts → attaform.D0dWZsJt.d.ts} +349 -77
  84. package/dist/shared/{attaform.z5j3LwJz.cjs → attaform.D32WwKk6.cjs} +216 -35
  85. package/dist/shared/attaform.D32WwKk6.cjs.map +1 -0
  86. package/dist/shared/{attaform.C5aYC_T8.mjs → attaform.DMEP_ENr.mjs} +39 -392
  87. package/dist/shared/attaform.DMEP_ENr.mjs.map +1 -0
  88. package/dist/shared/{attaform.tiWEVznj.mjs → attaform.DR6RmxWZ.mjs} +725 -962
  89. package/dist/shared/attaform.DR6RmxWZ.mjs.map +1 -0
  90. package/dist/shared/{attaform.Dt7dEcHk.mjs → attaform.DozgVlCE.mjs} +89 -405
  91. package/dist/shared/attaform.DozgVlCE.mjs.map +1 -0
  92. package/dist/shared/{attaform.DN5CvZrg.d.ts → attaform.Duecg2NO.d.mts} +2 -2
  93. package/dist/shared/attaform.DuzQYscR.d.cts +41 -0
  94. package/dist/shared/attaform.DuzQYscR.d.mts +41 -0
  95. package/dist/shared/attaform.DuzQYscR.d.ts +41 -0
  96. package/dist/shared/{attaform.BXinSW2T.d.mts → attaform.FudOcHaa.d.cts} +2 -2
  97. package/dist/shared/attaform.LEWUFqUw.cjs +54 -0
  98. package/dist/shared/attaform.LEWUFqUw.cjs.map +1 -0
  99. package/dist/shared/{attaform.CywE4y8x.d.cts → attaform.MtrpT6Ki.d.ts} +2 -2
  100. package/dist/shared/{attaform.DbRgDFa7.d.cts → attaform.NQ8mybyW.d.mts} +172 -2
  101. package/dist/shared/{attaform.Cd4AOfwu.cjs → attaform.S-pYLSo4.cjs} +68 -402
  102. package/dist/shared/attaform.S-pYLSo4.cjs.map +1 -0
  103. package/dist/shared/{attaform.CnrxbkB6.mjs → attaform.Y1ZGhM4k.mjs} +2 -2
  104. package/dist/shared/{attaform.CnrxbkB6.mjs.map → attaform.Y1ZGhM4k.mjs.map} +1 -1
  105. package/dist/shared/{attaform.QG5TG8lB.mjs → attaform.pmtahXKy.mjs} +216 -36
  106. package/dist/shared/attaform.pmtahXKy.mjs.map +1 -0
  107. package/dist/shared/attaform.sHkHv_98.mjs +51 -0
  108. package/dist/shared/attaform.sHkHv_98.mjs.map +1 -0
  109. package/dist/vite.cjs +9 -45
  110. package/dist/vite.cjs.map +1 -1
  111. package/dist/vite.d.cts +36 -0
  112. package/dist/vite.d.mts +36 -0
  113. package/dist/vite.d.ts +36 -0
  114. package/dist/vite.mjs +8 -44
  115. package/dist/vite.mjs.map +1 -1
  116. package/dist/webpack.cjs +10 -0
  117. package/dist/webpack.cjs.map +1 -0
  118. package/dist/webpack.d.cts +37 -0
  119. package/dist/webpack.d.mts +37 -0
  120. package/dist/webpack.d.ts +37 -0
  121. package/dist/webpack.mjs +8 -0
  122. package/dist/webpack.mjs.map +1 -0
  123. package/dist/zod-v3.cjs +3 -3
  124. package/dist/zod-v3.d.cts +3 -3
  125. package/dist/zod-v3.d.mts +3 -3
  126. package/dist/zod-v3.d.ts +3 -3
  127. package/dist/zod-v3.mjs +3 -3
  128. package/dist/zod-v4.cjs +3 -3
  129. package/dist/zod-v4.d.cts +4 -4
  130. package/dist/zod-v4.d.mts +4 -4
  131. package/dist/zod-v4.d.ts +4 -4
  132. package/dist/zod-v4.mjs +3 -3
  133. package/dist/zod.cjs +8 -8
  134. package/dist/zod.cjs.map +1 -1
  135. package/dist/zod.d.cts +52 -10
  136. package/dist/zod.d.mts +52 -10
  137. package/dist/zod.d.ts +52 -10
  138. package/dist/zod.mjs +6 -6
  139. package/dist/zod.mjs.map +1 -1
  140. package/package.json +19 -5
  141. package/dist/shared/attaform.BGk8cfw2.mjs.map +0 -1
  142. package/dist/shared/attaform.B_hph5AE.cjs.map +0 -1
  143. package/dist/shared/attaform.C5aYC_T8.mjs.map +0 -1
  144. package/dist/shared/attaform.Cd4AOfwu.cjs.map +0 -1
  145. package/dist/shared/attaform.CwLjUqmQ.cjs.map +0 -1
  146. package/dist/shared/attaform.DAKrGhxc.cjs.map +0 -1
  147. package/dist/shared/attaform.Dt7dEcHk.mjs.map +0 -1
  148. package/dist/shared/attaform.QG5TG8lB.mjs.map +0 -1
  149. package/dist/shared/attaform.tiWEVznj.mjs.map +0 -1
  150. package/dist/shared/attaform.z5j3LwJz.cjs.map +0 -1
package/dist/index.d.mts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { Plugin, App } from 'vue';
2
- import { S as SSRDetectOptions, c as SerializedFormData, b as AttaformRegistry } from './shared/attaform.sWm8B15V.mjs';
3
- export { A as AnyForm, a as AttaformErrorCode, C as CompiledStep, F as FormStatus, I as InjectWizardInput, L as LazyMarker, d as StepSlot, U as UseRegisterReturn, e as UseWizardReturnType, W as WizardAggregateError, f as WizardCtx, g as WizardCtxForm, h as WizardOnError, i as WizardOnSubmit, j as WizardOptions, k as WizardPersistFn, l as WizardRestoreFn, m as WizardRestoreState, n as WizardStatusesProxy, o as WizardSubmitContext, p as createRegistry, q as defaultCoercionRules, r as defineCoercion, s as getRegistryFromApp, t as injectForm, u as injectWizard, v as kAttaformRegistry, w as lazy, x as useRegister, y as useRegistry, z as useWizard } from './shared/attaform.sWm8B15V.mjs';
4
- import { f as AttaformDefaults, t as FormKey, G as GenericForm, ai as UseFormConfiguration, A as AbstractSchema, j as DefaultValuesInput, aj as UseFormReturnType, a8 as RegisterValue, a3 as RegisterModelDynamicCustomDirective, x as GetDisplayState, am as ValidationError, c as ApiErrorEnvelope, a as ApiErrorDetails } from './shared/attaform.99cfHcIt.mjs';
5
- export { b as ApiErrorEntry, d as ArrayItem, e as ArrayPath, C as CoercionEntry, g as CoercionRegistry, h as CoercionResult, i as CustomDirectiveRegisterAssignerFn, D as DeepPartial, k as DefaultValuesResponse, l as DefaultValuesShape, m as DisplayState, E as ErrorsProxyShape, F as FieldMetaPayload, n as FieldState, o as FieldStateMap, p as FieldStateMapEntry, q as FlatPath, r as FormErrorRecord, s as FormErrorsSurface, u as FormMeta, v as FormStorage, w as FormStorageKind, H as HandleSubmit, y as HistoryConfig, I as IsTuple, z as IsUnion, J as JoinSegments, K as KeyofUnion, L as LiftedValueShape, M as MetaTrackerValue, N as NestedReadType, B as NestedType, O as OnError, P as OnInvalidSubmitPolicy, Q as OnSubmit, R as PartialFlatPath, S as Path, T as PathKey, U as PendingValidationStatus, V as PersistConfig, W as PersistConfigOptions, X as PersistIncludeMode, Z as Primitive, _ as ROOT_PATH, $ as ROOT_PATH_KEY, a0 as ReactiveValidationStatus, a1 as RegisterDirective, a2 as RegisterFlatPath, a4 as RegisterOptions, a5 as RegisterSelectModifier, a6 as RegisterTextModifier, a7 as RegisterTransform, aa as Segment, ab as SetValueCallback, ac as SetValuePayload, ad as SettledValidationStatus, ae as SlimPrimitiveKind, af as SlimRuntimeOf, ag as SubmitHandler, ah as Unset, ak as ValidateOn, al as ValidateOnConfig, an as ValidationResponse, ao as ValidationResponseWithoutValue, ap as ValueOfUnion, aq as WriteMeta, ar as WriteShape, as as canonicalizePath, at as isPathPrefix, au as isUnset, av as parseDottedPath, aw as unset } from './shared/attaform.99cfHcIt.mjs';
2
+ import { S as SSRDetectOptions, c as SerializedFormData, b as AttaformRegistry } from './shared/attaform.NQ8mybyW.mjs';
3
+ export { A as AnyForm, a as AttaformErrorCode, C as CompiledStep, F as FormStatus, I as InjectWizardInput, L as LazyMarker, d as StepSlot, U as UseRegisterReturn, e as UseWizardReturnType, W as WizardAggregateError, f as WizardCtx, g as WizardCtxForm, h as WizardOnError, i as WizardOnSubmit, j as WizardOptions, k as WizardPersistFn, l as WizardRestoreFn, m as WizardRestoreState, n as WizardStatusesProxy, o as WizardSubmitContext, p as createRegistry, q as defaultCoercionRules, r as defineCoercion, s as getRegistryFromApp, t as injectForm, u as injectWizard, v as kAttaformRegistry, w as lazy, x as useRegister, y as useRegistry, z as useWizard } from './shared/attaform.NQ8mybyW.mjs';
4
+ import { f as AttaformDefaults, v as FormKey, G as GenericForm, al as UseFormConfiguration, A as AbstractSchema, j as DefaultValuesInput, am as UseFormReturnType, aa as RegisterValue, a5 as RegisterModelDynamicCustomDirective, z as GetDisplayState, ap as ValidationError, c as ApiErrorEnvelope, a as ApiErrorDetails } from './shared/attaform.D0dWZsJt.mjs';
5
+ export { b as ApiErrorEntry, d as ArrayItem, e as ArrayPath, C as CoercionEntry, g as CoercionRegistry, h as CoercionResult, i as CustomDirectiveRegisterAssignerFn, D as DeepPartial, k as DefaultValuesResponse, l as DefaultValuesShape, m as DisplayCtx, n as DisplayMachine, o as DisplayState, E as ErrorsProxyShape, F as FieldMetaPayload, p as FieldState, q as FieldStateMap, r as FieldStateMapEntry, s as FlatPath, t as FormErrorRecord, u as FormErrorsSurface, w as FormMeta, x as FormStorage, y as FormStorageKind, H as HandleSubmit, B as HistoryConfig, I as IsTuple, J as IsUnion, K as JoinSegments, L as KeyofUnion, M as LiftedValueShape, N as MetaTrackerValue, O as NestedReadType, P as NestedType, Q as OnError, R as OnInvalidSubmitPolicy, S as OnSubmit, T as PartialFlatPath, U as Path, V as PathKey, W as PendingValidationStatus, X as PersistConfig, Y as PersistConfigOptions, Z as PersistIncludeMode, $ as Primitive, a0 as ROOT_PATH, a1 as ROOT_PATH_KEY, a2 as ReactiveValidationStatus, a3 as RegisterDirective, a4 as RegisterFlatPath, a6 as RegisterOptions, a7 as RegisterSelectModifier, a8 as RegisterTextModifier, a9 as RegisterTransform, ac as Segment, ad as SetValueCallback, ae as SetValuePayload, af as SettledValidationStatus, ag as SlimPrimitiveKind, ah as SlimRuntimeOf, ai as SubmitHandler, ak as Unset, an as ValidateOn, ao as ValidateOnConfig, aq as ValidationResponse, ar as ValidationResponseWithoutValue, as as ValueOfUnion, at as WriteMeta, au as WriteShape, av as canonicalizePath, aw as isPathPrefix, ax as isUnset, ay as parseDottedPath, az as unset } from './shared/attaform.D0dWZsJt.mjs';
6
6
  export { A as AnonPersistError, a as AttaformError, I as InvalidPathError, b as InvalidUseFormConfigError, O as OutsideSetupError, R as RegistryNotInstalledError, c as ReservedFormKeyError, S as SubmitErrorHandlerError } from './shared/attaform.DkA5J8NW.mjs';
7
7
 
8
8
  /**
@@ -11,10 +11,11 @@ export { A as AnonPersistError, a as AttaformError, I as InvalidPathError, b as
11
11
  type AttaformPluginOptions = SSRDetectOptions & {
12
12
  /**
13
13
  * Whether to install the Vue DevTools integration. Default `true`.
14
- * The DevTools peer dependency is loaded lazily in production
15
- * builds where it's absent, the import fails silently and no
16
- * extra bundle is shipped. Pass `false` to skip even attempting
17
- * the import.
14
+ * The integration is dev-only: the `import('./devtools')` sits behind
15
+ * the `__DEV__` flag, so a consumer's production build folds it out
16
+ * entirely (no devtools chunk shipped, no fetch attempted). In
17
+ * development the DevTools peer is loaded lazily and a missing peer
18
+ * fails silently. Pass `false` to skip the integration even in dev.
18
19
  */
19
20
  devtools?: boolean;
20
21
  /**
@@ -261,74 +262,69 @@ declare global {
261
262
  }
262
263
 
263
264
  /**
264
- * Library-default `getDisplayState` heuristic. Resolves every path's
265
+ * Anti-flash timing for the library-default display reducer.
266
+ *
267
+ * - `showDelay` — how long in-flight work (a validation run or an async
268
+ * register transform) may run before its spinner is allowed to show. Work
269
+ * that settles inside this window never reveals `'pending'` at all, so a
270
+ * fast (often synchronous) check does not flash a spinner on every keystroke.
271
+ * - `minVisible` — once shown, the minimum time the spinner stays up. Work
272
+ * that lands just past `showDelay` is held here so the spinner does not
273
+ * itself flash on and immediately off.
274
+ *
275
+ * Both are milliseconds.
276
+ */
277
+ type DisplayTimings = {
278
+ readonly showDelay: number;
279
+ readonly minVisible: number;
280
+ };
281
+ /**
282
+ * Library-default anti-flash timings. `showDelay: 120` cleanly swallows
283
+ * synchronous, microtask-resolved, and tiny-async work (validation runs and
284
+ * async register transforms alike) so none of them flash a spinner;
285
+ * `minVisible: 120` keeps a shown spinner snappy once one does land.
286
+ * Retune via {@link makeDefaultDisplayState} without touching the engine.
287
+ */
288
+ declare const DEFAULT_TIMINGS: DisplayTimings;
289
+ /**
290
+ * Build a default `getDisplayState` reducer with custom anti-flash timing.
291
+ * Power users who want a tighter or looser spinner than {@link DEFAULT_TIMINGS}
292
+ * pass their own `{ showDelay, minVisible }`:
293
+ *
294
+ * ```ts
295
+ * import { makeDefaultDisplayState } from 'attaform'
296
+ *
297
+ * useForm({
298
+ * schema,
299
+ * getDisplayState: makeDefaultDisplayState({ showDelay: 50, minVisible: 200 }),
300
+ * })
301
+ * ```
302
+ *
303
+ * The returned reducer is pure: the engine injects `now` and threads the
304
+ * previous machine, so the same `(prev, ctx)` always yields the same next
305
+ * machine. It shapes only the display projection — `errors`, `valid`,
306
+ * `validating`, and the underlying validation run exactly as before.
307
+ */
308
+ declare function makeDefaultDisplayState({ showDelay, minVisible, }: DisplayTimings): GetDisplayState;
309
+ /**
310
+ * Library-default `getDisplayState` reducer. Resolves every path's
265
311
  * `field.displayState` — and thus `field.show*` and the `form.meta`
266
312
  * rollups — whenever the consumer has not configured an override at the
267
- * per-form or plugin level.
268
- *
269
- * One timing gate, then precedence:
270
- *
271
- * 1. **Timing gate.** `gateOpen` once the form has been submitted
272
- * (`submissionAttempts > 0`) OR the field has been edited and then
273
- * left (`blurredAfterInteraction === true`). Before the gate opens
274
- * the verdict is `'idle'` regardless of errors. This is the "reward
275
- * early, punish late" rule:
276
- * - A clean tab-through never engages. `blurredAfterInteraction`
277
- * only flips on a blur that follows an edit, so visiting a field
278
- * and moving on without editing it stays quiet until a submit
279
- * forces the issue, even if the field was tabbed through before.
280
- * - The first pass stays quiet. Editing alone (`interacted`) does
281
- * not open the gate; the error reveals only once the user
282
- * finishes that pass and leaves the field, never mid-entry.
283
- * - Recovery is live. The bit is sticky and carries no not-focused
284
- * term, so once a field has been revealed it stays open through a
285
- * re-focus: a shown error clears (or greens) the instant the
286
- * value becomes valid, without forcing another blur.
287
- *
288
- * The submit arm covers `form.handleSubmit` directly and
289
- * `wizard.handleSubmit` (which bumps `submissionAttempts` on the
290
- * active form at intermediate steps and on every form at the final
291
- * step, lighting up the whole flow at once).
292
- *
293
- * 2. **Pending.** With the gate open, a per-field run in flight
294
- * (`validating === true`) wins: the verdict in `errors` is stale by
295
- * definition, so surface `'pending'` (a spinner) rather than a
296
- * possibly-wrong error or success. Containers roll `validating` up as
297
- * a disjunction, so any descendant under revalidation reads
298
- * `'pending'` at the container too.
299
- *
300
- * 3. **Error.** An own-path error (one whose path equals the field's own
301
- * path) resolves to `'error'`. The own-path filter means a container
302
- * never duplicates an error a more-specific descendant already
303
- * renders; aggregate banners bind to `form.meta.errorCount` instead.
304
- *
305
- * 4. **Success.** No error, `valid === true`, and the green check is
306
- * earned: the field is non-blank and `dirty` (its value diverges from
307
- * the hydration original). Gating success on `dirty && !blank` keeps
308
- * the check meaningful — an empty field that happens to pass, a
309
- * pre-filled field merely tabbed through, and the post-submit flood of
310
- * every valid field all stay `'idle'` rather than greening for free.
311
- * `valid` already gates async schemas on the form-wide first
312
- * validation pass, so success never fires before the first verdict
313
- * lands.
314
- *
315
- * 5. **Idle.** Anything else — gate open but not validating, no own-path
316
- * error, and either not yet `valid` or valid-but-unearned (blank or
317
- * unchanged) — stays `'idle'`.
318
- *
319
- * Public re-export so adopters can compose with this without
320
- * copy-pasting the rule body — a layered predicate that special-cases a
321
- * subtree but otherwise defers picks up future refinements
322
- * automatically:
313
+ * per-form or plugin level. Built from {@link DEFAULT_TIMINGS}; publicly
314
+ * re-exported so an override can compose with it (a layered reducer that
315
+ * special-cases a subtree but otherwise defers picks up future
316
+ * refinements for free):
323
317
  *
324
318
  * ```ts
325
319
  * import { defaultDisplayState } from 'attaform'
326
320
  *
327
321
  * useForm({
328
322
  * schema,
329
- * getDisplayState: (field, formMeta) => {
330
- * const state = defaultDisplayState(field, formMeta)
331
- * return field.path[0] === 'username' && state === 'success' ? 'idle' : state
323
+ * getDisplayState: (prev, ctx) => {
324
+ * const next = defaultDisplayState(prev, ctx)
325
+ * return next.display === 'success' && ctx.field.path[0] === 'username'
326
+ * ? { display: 'idle' }
327
+ * : next
332
328
  * },
333
329
  * })
334
330
  * ```
@@ -496,5 +492,5 @@ declare const PARSE_API_ERRORS_DEFAULTS: {
496
492
  */
497
493
  declare function parseApiErrors(payload: ApiErrorEnvelope | ApiErrorDetails | null | undefined | unknown, options: ParseApiErrorsOptions): ParseApiErrorsResult;
498
494
 
499
- export { AbstractSchema, ApiErrorDetails, ApiErrorEnvelope, AttaformDefaults, AttaformRegistry, DEFAULT_SENSITIVE_NAMES, DEVTOOLS_WINDOW_KEY, DefaultValuesInput, FormKey, GenericForm, GetDisplayState, PARSE_API_ERRORS_DEFAULTS, RegisterValue, SerializedFormData, UseFormConfiguration, UseFormReturnType, ValidationError, assignKey, createAttaform, defaultDisplayState, escapeForInlineScript, hydrateAttaformState, isRegisterValue, parseApiErrors, renderAttaformState, useAbstractForm as useForm, vRegister };
500
- export type { AttaformDevtoolsBridge, AttaformPluginOptions, ParseApiErrorsOptions, ParseApiErrorsResult, SerializedAttaformState };
495
+ export { AbstractSchema, ApiErrorDetails, ApiErrorEnvelope, AttaformDefaults, AttaformRegistry, DEFAULT_SENSITIVE_NAMES, DEFAULT_TIMINGS, DEVTOOLS_WINDOW_KEY, DefaultValuesInput, FormKey, GenericForm, GetDisplayState, PARSE_API_ERRORS_DEFAULTS, RegisterValue, SerializedFormData, UseFormConfiguration, UseFormReturnType, ValidationError, assignKey, createAttaform, defaultDisplayState, escapeForInlineScript, hydrateAttaformState, isRegisterValue, makeDefaultDisplayState, parseApiErrors, renderAttaformState, useAbstractForm as useForm, vRegister };
496
+ export type { AttaformDevtoolsBridge, AttaformPluginOptions, DisplayTimings, ParseApiErrorsOptions, ParseApiErrorsResult, SerializedAttaformState };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { Plugin, App } from 'vue';
2
- import { S as SSRDetectOptions, c as SerializedFormData, b as AttaformRegistry } from './shared/attaform.ceGEAEMk.js';
3
- export { A as AnyForm, a as AttaformErrorCode, C as CompiledStep, F as FormStatus, I as InjectWizardInput, L as LazyMarker, d as StepSlot, U as UseRegisterReturn, e as UseWizardReturnType, W as WizardAggregateError, f as WizardCtx, g as WizardCtxForm, h as WizardOnError, i as WizardOnSubmit, j as WizardOptions, k as WizardPersistFn, l as WizardRestoreFn, m as WizardRestoreState, n as WizardStatusesProxy, o as WizardSubmitContext, p as createRegistry, q as defaultCoercionRules, r as defineCoercion, s as getRegistryFromApp, t as injectForm, u as injectWizard, v as kAttaformRegistry, w as lazy, x as useRegister, y as useRegistry, z as useWizard } from './shared/attaform.ceGEAEMk.js';
4
- import { f as AttaformDefaults, t as FormKey, G as GenericForm, ai as UseFormConfiguration, A as AbstractSchema, j as DefaultValuesInput, aj as UseFormReturnType, a8 as RegisterValue, a3 as RegisterModelDynamicCustomDirective, x as GetDisplayState, am as ValidationError, c as ApiErrorEnvelope, a as ApiErrorDetails } from './shared/attaform.99cfHcIt.js';
5
- export { b as ApiErrorEntry, d as ArrayItem, e as ArrayPath, C as CoercionEntry, g as CoercionRegistry, h as CoercionResult, i as CustomDirectiveRegisterAssignerFn, D as DeepPartial, k as DefaultValuesResponse, l as DefaultValuesShape, m as DisplayState, E as ErrorsProxyShape, F as FieldMetaPayload, n as FieldState, o as FieldStateMap, p as FieldStateMapEntry, q as FlatPath, r as FormErrorRecord, s as FormErrorsSurface, u as FormMeta, v as FormStorage, w as FormStorageKind, H as HandleSubmit, y as HistoryConfig, I as IsTuple, z as IsUnion, J as JoinSegments, K as KeyofUnion, L as LiftedValueShape, M as MetaTrackerValue, N as NestedReadType, B as NestedType, O as OnError, P as OnInvalidSubmitPolicy, Q as OnSubmit, R as PartialFlatPath, S as Path, T as PathKey, U as PendingValidationStatus, V as PersistConfig, W as PersistConfigOptions, X as PersistIncludeMode, Z as Primitive, _ as ROOT_PATH, $ as ROOT_PATH_KEY, a0 as ReactiveValidationStatus, a1 as RegisterDirective, a2 as RegisterFlatPath, a4 as RegisterOptions, a5 as RegisterSelectModifier, a6 as RegisterTextModifier, a7 as RegisterTransform, aa as Segment, ab as SetValueCallback, ac as SetValuePayload, ad as SettledValidationStatus, ae as SlimPrimitiveKind, af as SlimRuntimeOf, ag as SubmitHandler, ah as Unset, ak as ValidateOn, al as ValidateOnConfig, an as ValidationResponse, ao as ValidationResponseWithoutValue, ap as ValueOfUnion, aq as WriteMeta, ar as WriteShape, as as canonicalizePath, at as isPathPrefix, au as isUnset, av as parseDottedPath, aw as unset } from './shared/attaform.99cfHcIt.js';
2
+ import { S as SSRDetectOptions, c as SerializedFormData, b as AttaformRegistry } from './shared/attaform.Bv7dRDWK.js';
3
+ export { A as AnyForm, a as AttaformErrorCode, C as CompiledStep, F as FormStatus, I as InjectWizardInput, L as LazyMarker, d as StepSlot, U as UseRegisterReturn, e as UseWizardReturnType, W as WizardAggregateError, f as WizardCtx, g as WizardCtxForm, h as WizardOnError, i as WizardOnSubmit, j as WizardOptions, k as WizardPersistFn, l as WizardRestoreFn, m as WizardRestoreState, n as WizardStatusesProxy, o as WizardSubmitContext, p as createRegistry, q as defaultCoercionRules, r as defineCoercion, s as getRegistryFromApp, t as injectForm, u as injectWizard, v as kAttaformRegistry, w as lazy, x as useRegister, y as useRegistry, z as useWizard } from './shared/attaform.Bv7dRDWK.js';
4
+ import { f as AttaformDefaults, v as FormKey, G as GenericForm, al as UseFormConfiguration, A as AbstractSchema, j as DefaultValuesInput, am as UseFormReturnType, aa as RegisterValue, a5 as RegisterModelDynamicCustomDirective, z as GetDisplayState, ap as ValidationError, c as ApiErrorEnvelope, a as ApiErrorDetails } from './shared/attaform.D0dWZsJt.js';
5
+ export { b as ApiErrorEntry, d as ArrayItem, e as ArrayPath, C as CoercionEntry, g as CoercionRegistry, h as CoercionResult, i as CustomDirectiveRegisterAssignerFn, D as DeepPartial, k as DefaultValuesResponse, l as DefaultValuesShape, m as DisplayCtx, n as DisplayMachine, o as DisplayState, E as ErrorsProxyShape, F as FieldMetaPayload, p as FieldState, q as FieldStateMap, r as FieldStateMapEntry, s as FlatPath, t as FormErrorRecord, u as FormErrorsSurface, w as FormMeta, x as FormStorage, y as FormStorageKind, H as HandleSubmit, B as HistoryConfig, I as IsTuple, J as IsUnion, K as JoinSegments, L as KeyofUnion, M as LiftedValueShape, N as MetaTrackerValue, O as NestedReadType, P as NestedType, Q as OnError, R as OnInvalidSubmitPolicy, S as OnSubmit, T as PartialFlatPath, U as Path, V as PathKey, W as PendingValidationStatus, X as PersistConfig, Y as PersistConfigOptions, Z as PersistIncludeMode, $ as Primitive, a0 as ROOT_PATH, a1 as ROOT_PATH_KEY, a2 as ReactiveValidationStatus, a3 as RegisterDirective, a4 as RegisterFlatPath, a6 as RegisterOptions, a7 as RegisterSelectModifier, a8 as RegisterTextModifier, a9 as RegisterTransform, ac as Segment, ad as SetValueCallback, ae as SetValuePayload, af as SettledValidationStatus, ag as SlimPrimitiveKind, ah as SlimRuntimeOf, ai as SubmitHandler, ak as Unset, an as ValidateOn, ao as ValidateOnConfig, aq as ValidationResponse, ar as ValidationResponseWithoutValue, as as ValueOfUnion, at as WriteMeta, au as WriteShape, av as canonicalizePath, aw as isPathPrefix, ax as isUnset, ay as parseDottedPath, az as unset } from './shared/attaform.D0dWZsJt.js';
6
6
  export { A as AnonPersistError, a as AttaformError, I as InvalidPathError, b as InvalidUseFormConfigError, O as OutsideSetupError, R as RegistryNotInstalledError, c as ReservedFormKeyError, S as SubmitErrorHandlerError } from './shared/attaform.DkA5J8NW.js';
7
7
 
8
8
  /**
@@ -11,10 +11,11 @@ export { A as AnonPersistError, a as AttaformError, I as InvalidPathError, b as
11
11
  type AttaformPluginOptions = SSRDetectOptions & {
12
12
  /**
13
13
  * Whether to install the Vue DevTools integration. Default `true`.
14
- * The DevTools peer dependency is loaded lazily in production
15
- * builds where it's absent, the import fails silently and no
16
- * extra bundle is shipped. Pass `false` to skip even attempting
17
- * the import.
14
+ * The integration is dev-only: the `import('./devtools')` sits behind
15
+ * the `__DEV__` flag, so a consumer's production build folds it out
16
+ * entirely (no devtools chunk shipped, no fetch attempted). In
17
+ * development the DevTools peer is loaded lazily and a missing peer
18
+ * fails silently. Pass `false` to skip the integration even in dev.
18
19
  */
19
20
  devtools?: boolean;
20
21
  /**
@@ -261,74 +262,69 @@ declare global {
261
262
  }
262
263
 
263
264
  /**
264
- * Library-default `getDisplayState` heuristic. Resolves every path's
265
+ * Anti-flash timing for the library-default display reducer.
266
+ *
267
+ * - `showDelay` — how long in-flight work (a validation run or an async
268
+ * register transform) may run before its spinner is allowed to show. Work
269
+ * that settles inside this window never reveals `'pending'` at all, so a
270
+ * fast (often synchronous) check does not flash a spinner on every keystroke.
271
+ * - `minVisible` — once shown, the minimum time the spinner stays up. Work
272
+ * that lands just past `showDelay` is held here so the spinner does not
273
+ * itself flash on and immediately off.
274
+ *
275
+ * Both are milliseconds.
276
+ */
277
+ type DisplayTimings = {
278
+ readonly showDelay: number;
279
+ readonly minVisible: number;
280
+ };
281
+ /**
282
+ * Library-default anti-flash timings. `showDelay: 120` cleanly swallows
283
+ * synchronous, microtask-resolved, and tiny-async work (validation runs and
284
+ * async register transforms alike) so none of them flash a spinner;
285
+ * `minVisible: 120` keeps a shown spinner snappy once one does land.
286
+ * Retune via {@link makeDefaultDisplayState} without touching the engine.
287
+ */
288
+ declare const DEFAULT_TIMINGS: DisplayTimings;
289
+ /**
290
+ * Build a default `getDisplayState` reducer with custom anti-flash timing.
291
+ * Power users who want a tighter or looser spinner than {@link DEFAULT_TIMINGS}
292
+ * pass their own `{ showDelay, minVisible }`:
293
+ *
294
+ * ```ts
295
+ * import { makeDefaultDisplayState } from 'attaform'
296
+ *
297
+ * useForm({
298
+ * schema,
299
+ * getDisplayState: makeDefaultDisplayState({ showDelay: 50, minVisible: 200 }),
300
+ * })
301
+ * ```
302
+ *
303
+ * The returned reducer is pure: the engine injects `now` and threads the
304
+ * previous machine, so the same `(prev, ctx)` always yields the same next
305
+ * machine. It shapes only the display projection — `errors`, `valid`,
306
+ * `validating`, and the underlying validation run exactly as before.
307
+ */
308
+ declare function makeDefaultDisplayState({ showDelay, minVisible, }: DisplayTimings): GetDisplayState;
309
+ /**
310
+ * Library-default `getDisplayState` reducer. Resolves every path's
265
311
  * `field.displayState` — and thus `field.show*` and the `form.meta`
266
312
  * rollups — whenever the consumer has not configured an override at the
267
- * per-form or plugin level.
268
- *
269
- * One timing gate, then precedence:
270
- *
271
- * 1. **Timing gate.** `gateOpen` once the form has been submitted
272
- * (`submissionAttempts > 0`) OR the field has been edited and then
273
- * left (`blurredAfterInteraction === true`). Before the gate opens
274
- * the verdict is `'idle'` regardless of errors. This is the "reward
275
- * early, punish late" rule:
276
- * - A clean tab-through never engages. `blurredAfterInteraction`
277
- * only flips on a blur that follows an edit, so visiting a field
278
- * and moving on without editing it stays quiet until a submit
279
- * forces the issue, even if the field was tabbed through before.
280
- * - The first pass stays quiet. Editing alone (`interacted`) does
281
- * not open the gate; the error reveals only once the user
282
- * finishes that pass and leaves the field, never mid-entry.
283
- * - Recovery is live. The bit is sticky and carries no not-focused
284
- * term, so once a field has been revealed it stays open through a
285
- * re-focus: a shown error clears (or greens) the instant the
286
- * value becomes valid, without forcing another blur.
287
- *
288
- * The submit arm covers `form.handleSubmit` directly and
289
- * `wizard.handleSubmit` (which bumps `submissionAttempts` on the
290
- * active form at intermediate steps and on every form at the final
291
- * step, lighting up the whole flow at once).
292
- *
293
- * 2. **Pending.** With the gate open, a per-field run in flight
294
- * (`validating === true`) wins: the verdict in `errors` is stale by
295
- * definition, so surface `'pending'` (a spinner) rather than a
296
- * possibly-wrong error or success. Containers roll `validating` up as
297
- * a disjunction, so any descendant under revalidation reads
298
- * `'pending'` at the container too.
299
- *
300
- * 3. **Error.** An own-path error (one whose path equals the field's own
301
- * path) resolves to `'error'`. The own-path filter means a container
302
- * never duplicates an error a more-specific descendant already
303
- * renders; aggregate banners bind to `form.meta.errorCount` instead.
304
- *
305
- * 4. **Success.** No error, `valid === true`, and the green check is
306
- * earned: the field is non-blank and `dirty` (its value diverges from
307
- * the hydration original). Gating success on `dirty && !blank` keeps
308
- * the check meaningful — an empty field that happens to pass, a
309
- * pre-filled field merely tabbed through, and the post-submit flood of
310
- * every valid field all stay `'idle'` rather than greening for free.
311
- * `valid` already gates async schemas on the form-wide first
312
- * validation pass, so success never fires before the first verdict
313
- * lands.
314
- *
315
- * 5. **Idle.** Anything else — gate open but not validating, no own-path
316
- * error, and either not yet `valid` or valid-but-unearned (blank or
317
- * unchanged) — stays `'idle'`.
318
- *
319
- * Public re-export so adopters can compose with this without
320
- * copy-pasting the rule body — a layered predicate that special-cases a
321
- * subtree but otherwise defers picks up future refinements
322
- * automatically:
313
+ * per-form or plugin level. Built from {@link DEFAULT_TIMINGS}; publicly
314
+ * re-exported so an override can compose with it (a layered reducer that
315
+ * special-cases a subtree but otherwise defers picks up future
316
+ * refinements for free):
323
317
  *
324
318
  * ```ts
325
319
  * import { defaultDisplayState } from 'attaform'
326
320
  *
327
321
  * useForm({
328
322
  * schema,
329
- * getDisplayState: (field, formMeta) => {
330
- * const state = defaultDisplayState(field, formMeta)
331
- * return field.path[0] === 'username' && state === 'success' ? 'idle' : state
323
+ * getDisplayState: (prev, ctx) => {
324
+ * const next = defaultDisplayState(prev, ctx)
325
+ * return next.display === 'success' && ctx.field.path[0] === 'username'
326
+ * ? { display: 'idle' }
327
+ * : next
332
328
  * },
333
329
  * })
334
330
  * ```
@@ -496,5 +492,5 @@ declare const PARSE_API_ERRORS_DEFAULTS: {
496
492
  */
497
493
  declare function parseApiErrors(payload: ApiErrorEnvelope | ApiErrorDetails | null | undefined | unknown, options: ParseApiErrorsOptions): ParseApiErrorsResult;
498
494
 
499
- export { AbstractSchema, ApiErrorDetails, ApiErrorEnvelope, AttaformDefaults, AttaformRegistry, DEFAULT_SENSITIVE_NAMES, DEVTOOLS_WINDOW_KEY, DefaultValuesInput, FormKey, GenericForm, GetDisplayState, PARSE_API_ERRORS_DEFAULTS, RegisterValue, SerializedFormData, UseFormConfiguration, UseFormReturnType, ValidationError, assignKey, createAttaform, defaultDisplayState, escapeForInlineScript, hydrateAttaformState, isRegisterValue, parseApiErrors, renderAttaformState, useAbstractForm as useForm, vRegister };
500
- export type { AttaformDevtoolsBridge, AttaformPluginOptions, ParseApiErrorsOptions, ParseApiErrorsResult, SerializedAttaformState };
495
+ export { AbstractSchema, ApiErrorDetails, ApiErrorEnvelope, AttaformDefaults, AttaformRegistry, DEFAULT_SENSITIVE_NAMES, DEFAULT_TIMINGS, DEVTOOLS_WINDOW_KEY, DefaultValuesInput, FormKey, GenericForm, GetDisplayState, PARSE_API_ERRORS_DEFAULTS, RegisterValue, SerializedFormData, UseFormConfiguration, UseFormReturnType, ValidationError, assignKey, createAttaform, defaultDisplayState, escapeForInlineScript, hydrateAttaformState, isRegisterValue, makeDefaultDisplayState, parseApiErrors, renderAttaformState, useAbstractForm as useForm, vRegister };
496
+ export type { AttaformDevtoolsBridge, AttaformPluginOptions, DisplayTimings, ParseApiErrorsOptions, ParseApiErrorsResult, SerializedAttaformState };
package/dist/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
- import { j as canonicalizePath, c as InvalidPathError } from './shared/attaform.QG5TG8lB.mjs';
2
- export { A as AnonPersistError, a as AttaformError, D as DEFAULT_SENSITIVE_NAMES, d as InvalidUseFormConfigError, O as OutsideSetupError, R as ROOT_PATH, e as ROOT_PATH_KEY, f as RegistryNotInstalledError, g as ReservedFormKeyError, S as SubmitErrorHandlerError, i as assignKey, m as createAttaform, p as createRegistry, s as getRegistryFromApp, t as isPathPrefix, u as isRegisterValue, x as kAttaformRegistry, C as parseDottedPath, H as useRegister, J as useRegistry, K as vRegister } from './shared/attaform.QG5TG8lB.mjs';
3
- export { D as DEVTOOLS_WINDOW_KEY, h as hydrateAttaformState, r as renderAttaformState } from './shared/attaform.CnrxbkB6.mjs';
4
- import { n as normalizeNumericOption } from './shared/attaform.tiWEVznj.mjs';
5
- export { A as AttaformErrorCode, d as defaultCoercionRules, a as defaultDisplayState, b as defineCoercion, i as injectForm, c as injectWizard, f as isUnset, l as lazy, u as unset, o as useForm, p as useWizard } from './shared/attaform.tiWEVznj.mjs';
1
+ import { j as canonicalizePath, c as InvalidPathError } from './shared/attaform.pmtahXKy.mjs';
2
+ export { A as AnonPersistError, a as AttaformError, D as DEFAULT_SENSITIVE_NAMES, d as InvalidUseFormConfigError, O as OutsideSetupError, R as ROOT_PATH, e as ROOT_PATH_KEY, f as RegistryNotInstalledError, g as ReservedFormKeyError, S as SubmitErrorHandlerError, i as assignKey, m as createAttaform, p as createRegistry, s as getRegistryFromApp, t as isPathPrefix, u as isRegisterValue, x as kAttaformRegistry, C as parseDottedPath, J as useRegister, K as useRegistry, L as vRegister } from './shared/attaform.pmtahXKy.mjs';
3
+ export { D as DEVTOOLS_WINDOW_KEY, h as hydrateAttaformState, r as renderAttaformState } from './shared/attaform.Y1ZGhM4k.mjs';
4
+ import { r as normalizeNumericOption } from './shared/attaform.DR6RmxWZ.mjs';
5
+ export { A as AttaformErrorCode, a as DEFAULT_TIMINGS, d as defaultCoercionRules, e as defaultDisplayState, f as defineCoercion, k as injectForm, l as injectWizard, n as isUnset, o as lazy, p as makeDefaultDisplayState, z as unset, B as useForm, C as useWizard } from './shared/attaform.DR6RmxWZ.mjs';
6
6
 
7
7
  function escapeForInlineScript(json) {
8
8
  return json.replace(/[<>&\u2028\u2029]/g, (char) => {
package/dist/nuxt.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _nuxt_schema from '@nuxt/schema';
2
- import { f as AttaformDefaults } from './shared/attaform.99cfHcIt.cjs';
2
+ import { f as AttaformDefaults } from './shared/attaform.D0dWZsJt.cjs';
3
3
  import 'vue';
4
4
 
5
5
  /**
package/dist/nuxt.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _nuxt_schema from '@nuxt/schema';
2
- import { f as AttaformDefaults } from './shared/attaform.99cfHcIt.mjs';
2
+ import { f as AttaformDefaults } from './shared/attaform.D0dWZsJt.mjs';
3
3
  import 'vue';
4
4
 
5
5
  /**
package/dist/nuxt.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _nuxt_schema from '@nuxt/schema';
2
- import { f as AttaformDefaults } from './shared/attaform.99cfHcIt.js';
2
+ import { f as AttaformDefaults } from './shared/attaform.D0dWZsJt.js';
3
3
  import 'vue';
4
4
 
5
5
  /**
@@ -0,0 +1,24 @@
1
+ 'use strict';
2
+
3
+ const detectZodMajor = require('./shared/attaform.LEWUFqUw.cjs');
4
+
5
+ function attaform(options = {}) {
6
+ const resolveZodAlias = options.resolveZodAlias !== false;
7
+ const root = options.root ?? process.cwd();
8
+ const warnState = { warned: false };
9
+ let aliasTarget = null;
10
+ return {
11
+ name: "attaform",
12
+ buildStart() {
13
+ aliasTarget = detectZodMajor.resolveZodAliasTarget(root, "attaform/rollup", resolveZodAlias, warnState);
14
+ },
15
+ resolveId(source, importer) {
16
+ if (aliasTarget === null) return null;
17
+ if (source !== detectZodMajor.ZOD_UNIFIED_SPECIFIER) return null;
18
+ return this.resolve(aliasTarget, importer, { skipSelf: true });
19
+ }
20
+ };
21
+ }
22
+
23
+ exports.attaform = attaform;
24
+ //# sourceMappingURL=rollup.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rollup.cjs","sources":["../src/rollup.ts"],"sourcesContent":["/**\n * `attaform/rollup` — Rollup plugin that rewrites `attaform/zod` imports\n * to the single matching adapter subpath (`attaform/zod-v3` or\n * `attaform/zod-v4`) at build time, based on the consumer's installed Zod\n * major. Without it, Rollup ships both adapters because the unified\n * `attaform/zod` entry imports both for runtime dispatch.\n *\n * Usage:\n *\n * // rollup.config.js\n * import { attaform } from 'attaform/rollup'\n *\n * export default {\n * plugins: [attaform()],\n * }\n *\n * This plugin only does the adapter rewrite. The Vue SFC `v-register`\n * transforms that `attaform/vite` wires (load-bearing for SSR initial\n * render) are `@vitejs/plugin-vue`-specific and do not transfer; a\n * non-Vite consumer that needs them wires `attaform/transforms` into\n * their Vue compiler separately.\n *\n * Zero-dep: the plugin imports nothing from `rollup` (the bundler injects\n * its plugin context at the consumer's build); the structural types below\n * are all it needs to compile.\n */\nimport { resolveZodAliasTarget, ZOD_UNIFIED_SPECIFIER } from './core/detect-zod-major'\n\n/** Options for the Rollup `attaform()` plugin. */\nexport interface AttaformRollupPluginOptions {\n /**\n * Rewrite `attaform/zod` imports at build time to the matching adapter\n * subpath. Default `true`. Set to `false` to keep the runtime-dispatch\n * unified entry (ships both adapters).\n */\n resolveZodAlias?: boolean\n /**\n * Project root to resolve the installed Zod from. Defaults to\n * `process.cwd()`. Set this when the build runs from a directory other\n * than the project that owns the Zod dependency.\n */\n root?: string\n}\n\ninterface RollupResolveContext {\n resolve(\n source: string,\n importer: string | undefined,\n options: { skipSelf: boolean }\n ): Promise<{ id: string; external: boolean | 'absolute' | 'relative' } | null>\n}\n\n/** The structural shape Rollup requires of the plugin. */\nexport interface AttaformRollupPlugin {\n name: string\n buildStart(): void\n resolveId(\n this: RollupResolveContext,\n source: string,\n importer: string | undefined\n ): Promise<{ id: string } | null> | null\n}\n\nexport function attaform(options: AttaformRollupPluginOptions = {}): AttaformRollupPlugin {\n const resolveZodAlias = options.resolveZodAlias !== false\n const root = options.root ?? process.cwd()\n const warnState = { warned: false }\n let aliasTarget: string | null = null\n\n return {\n name: 'attaform',\n buildStart() {\n // Detect once at build start (fail fast on missing zod). `buildStart`\n // is guaranteed to run before any `resolveId`, so the target is set\n // before the rewrite hook fires.\n aliasTarget = resolveZodAliasTarget(root, 'attaform/rollup', resolveZodAlias, warnState)\n },\n resolveId(source, importer) {\n if (aliasTarget === null) return null\n if (source !== ZOD_UNIFIED_SPECIFIER) return null\n // Re-run the rewritten specifier through the resolver chain so the\n // matching subpath export lands as a real module. `skipSelf` keeps\n // the hook reentrant (our source check rejects the rewritten target\n // anyway, since it is no longer the bare unified specifier).\n return this.resolve(aliasTarget, importer, { skipSelf: true })\n },\n }\n}\n"],"names":["resolveZodAliasTarget","ZOD_UNIFIED_SPECIFIER"],"mappings":";;;;AA+DO,SAAS,QAAA,CAAS,OAAA,GAAuC,EAAC,EAAyB;AACxF,EAAA,MAAM,eAAA,GAAkB,QAAQ,eAAA,KAAoB,KAAA;AACpD,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,IAAA,IAAQ,OAAA,CAAQ,GAAA,EAAI;AACzC,EAAA,MAAM,SAAA,GAAY,EAAE,MAAA,EAAQ,KAAA,EAAM;AAClC,EAAA,IAAI,WAAA,GAA6B,IAAA;AAEjC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,UAAA;AAAA,IACN,UAAA,GAAa;AAIX,MAAA,WAAA,GAAcA,oCAAA,CAAsB,IAAA,EAAM,iBAAA,EAAmB,eAAA,EAAiB,SAAS,CAAA;AAAA,IACzF,CAAA;AAAA,IACA,SAAA,CAAU,QAAQ,QAAA,EAAU;AAC1B,MAAA,IAAI,WAAA,KAAgB,MAAM,OAAO,IAAA;AACjC,MAAA,IAAI,MAAA,KAAWC,sCAAuB,OAAO,IAAA;AAK7C,MAAA,OAAO,KAAK,OAAA,CAAQ,WAAA,EAAa,UAAU,EAAE,QAAA,EAAU,MAAM,CAAA;AAAA,IAC/D;AAAA,GACF;AACF;;;;"}
@@ -0,0 +1,35 @@
1
+ /** Options for the Rollup `attaform()` plugin. */
2
+ interface AttaformRollupPluginOptions {
3
+ /**
4
+ * Rewrite `attaform/zod` imports at build time to the matching adapter
5
+ * subpath. Default `true`. Set to `false` to keep the runtime-dispatch
6
+ * unified entry (ships both adapters).
7
+ */
8
+ resolveZodAlias?: boolean;
9
+ /**
10
+ * Project root to resolve the installed Zod from. Defaults to
11
+ * `process.cwd()`. Set this when the build runs from a directory other
12
+ * than the project that owns the Zod dependency.
13
+ */
14
+ root?: string;
15
+ }
16
+ interface RollupResolveContext {
17
+ resolve(source: string, importer: string | undefined, options: {
18
+ skipSelf: boolean;
19
+ }): Promise<{
20
+ id: string;
21
+ external: boolean | 'absolute' | 'relative';
22
+ } | null>;
23
+ }
24
+ /** The structural shape Rollup requires of the plugin. */
25
+ interface AttaformRollupPlugin {
26
+ name: string;
27
+ buildStart(): void;
28
+ resolveId(this: RollupResolveContext, source: string, importer: string | undefined): Promise<{
29
+ id: string;
30
+ } | null> | null;
31
+ }
32
+ declare function attaform(options?: AttaformRollupPluginOptions): AttaformRollupPlugin;
33
+
34
+ export { attaform };
35
+ export type { AttaformRollupPlugin, AttaformRollupPluginOptions };
@@ -0,0 +1,35 @@
1
+ /** Options for the Rollup `attaform()` plugin. */
2
+ interface AttaformRollupPluginOptions {
3
+ /**
4
+ * Rewrite `attaform/zod` imports at build time to the matching adapter
5
+ * subpath. Default `true`. Set to `false` to keep the runtime-dispatch
6
+ * unified entry (ships both adapters).
7
+ */
8
+ resolveZodAlias?: boolean;
9
+ /**
10
+ * Project root to resolve the installed Zod from. Defaults to
11
+ * `process.cwd()`. Set this when the build runs from a directory other
12
+ * than the project that owns the Zod dependency.
13
+ */
14
+ root?: string;
15
+ }
16
+ interface RollupResolveContext {
17
+ resolve(source: string, importer: string | undefined, options: {
18
+ skipSelf: boolean;
19
+ }): Promise<{
20
+ id: string;
21
+ external: boolean | 'absolute' | 'relative';
22
+ } | null>;
23
+ }
24
+ /** The structural shape Rollup requires of the plugin. */
25
+ interface AttaformRollupPlugin {
26
+ name: string;
27
+ buildStart(): void;
28
+ resolveId(this: RollupResolveContext, source: string, importer: string | undefined): Promise<{
29
+ id: string;
30
+ } | null> | null;
31
+ }
32
+ declare function attaform(options?: AttaformRollupPluginOptions): AttaformRollupPlugin;
33
+
34
+ export { attaform };
35
+ export type { AttaformRollupPlugin, AttaformRollupPluginOptions };
@@ -0,0 +1,35 @@
1
+ /** Options for the Rollup `attaform()` plugin. */
2
+ interface AttaformRollupPluginOptions {
3
+ /**
4
+ * Rewrite `attaform/zod` imports at build time to the matching adapter
5
+ * subpath. Default `true`. Set to `false` to keep the runtime-dispatch
6
+ * unified entry (ships both adapters).
7
+ */
8
+ resolveZodAlias?: boolean;
9
+ /**
10
+ * Project root to resolve the installed Zod from. Defaults to
11
+ * `process.cwd()`. Set this when the build runs from a directory other
12
+ * than the project that owns the Zod dependency.
13
+ */
14
+ root?: string;
15
+ }
16
+ interface RollupResolveContext {
17
+ resolve(source: string, importer: string | undefined, options: {
18
+ skipSelf: boolean;
19
+ }): Promise<{
20
+ id: string;
21
+ external: boolean | 'absolute' | 'relative';
22
+ } | null>;
23
+ }
24
+ /** The structural shape Rollup requires of the plugin. */
25
+ interface AttaformRollupPlugin {
26
+ name: string;
27
+ buildStart(): void;
28
+ resolveId(this: RollupResolveContext, source: string, importer: string | undefined): Promise<{
29
+ id: string;
30
+ } | null> | null;
31
+ }
32
+ declare function attaform(options?: AttaformRollupPluginOptions): AttaformRollupPlugin;
33
+
34
+ export { attaform };
35
+ export type { AttaformRollupPlugin, AttaformRollupPluginOptions };
@@ -0,0 +1,22 @@
1
+ import { r as resolveZodAliasTarget, Z as ZOD_UNIFIED_SPECIFIER } from './shared/attaform.sHkHv_98.mjs';
2
+
3
+ function attaform(options = {}) {
4
+ const resolveZodAlias = options.resolveZodAlias !== false;
5
+ const root = options.root ?? process.cwd();
6
+ const warnState = { warned: false };
7
+ let aliasTarget = null;
8
+ return {
9
+ name: "attaform",
10
+ buildStart() {
11
+ aliasTarget = resolveZodAliasTarget(root, "attaform/rollup", resolveZodAlias, warnState);
12
+ },
13
+ resolveId(source, importer) {
14
+ if (aliasTarget === null) return null;
15
+ if (source !== ZOD_UNIFIED_SPECIFIER) return null;
16
+ return this.resolve(aliasTarget, importer, { skipSelf: true });
17
+ }
18
+ };
19
+ }
20
+
21
+ export { attaform };
22
+ //# sourceMappingURL=rollup.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rollup.mjs","sources":["../src/rollup.ts"],"sourcesContent":["/**\n * `attaform/rollup` — Rollup plugin that rewrites `attaform/zod` imports\n * to the single matching adapter subpath (`attaform/zod-v3` or\n * `attaform/zod-v4`) at build time, based on the consumer's installed Zod\n * major. Without it, Rollup ships both adapters because the unified\n * `attaform/zod` entry imports both for runtime dispatch.\n *\n * Usage:\n *\n * // rollup.config.js\n * import { attaform } from 'attaform/rollup'\n *\n * export default {\n * plugins: [attaform()],\n * }\n *\n * This plugin only does the adapter rewrite. The Vue SFC `v-register`\n * transforms that `attaform/vite` wires (load-bearing for SSR initial\n * render) are `@vitejs/plugin-vue`-specific and do not transfer; a\n * non-Vite consumer that needs them wires `attaform/transforms` into\n * their Vue compiler separately.\n *\n * Zero-dep: the plugin imports nothing from `rollup` (the bundler injects\n * its plugin context at the consumer's build); the structural types below\n * are all it needs to compile.\n */\nimport { resolveZodAliasTarget, ZOD_UNIFIED_SPECIFIER } from './core/detect-zod-major'\n\n/** Options for the Rollup `attaform()` plugin. */\nexport interface AttaformRollupPluginOptions {\n /**\n * Rewrite `attaform/zod` imports at build time to the matching adapter\n * subpath. Default `true`. Set to `false` to keep the runtime-dispatch\n * unified entry (ships both adapters).\n */\n resolveZodAlias?: boolean\n /**\n * Project root to resolve the installed Zod from. Defaults to\n * `process.cwd()`. Set this when the build runs from a directory other\n * than the project that owns the Zod dependency.\n */\n root?: string\n}\n\ninterface RollupResolveContext {\n resolve(\n source: string,\n importer: string | undefined,\n options: { skipSelf: boolean }\n ): Promise<{ id: string; external: boolean | 'absolute' | 'relative' } | null>\n}\n\n/** The structural shape Rollup requires of the plugin. */\nexport interface AttaformRollupPlugin {\n name: string\n buildStart(): void\n resolveId(\n this: RollupResolveContext,\n source: string,\n importer: string | undefined\n ): Promise<{ id: string } | null> | null\n}\n\nexport function attaform(options: AttaformRollupPluginOptions = {}): AttaformRollupPlugin {\n const resolveZodAlias = options.resolveZodAlias !== false\n const root = options.root ?? process.cwd()\n const warnState = { warned: false }\n let aliasTarget: string | null = null\n\n return {\n name: 'attaform',\n buildStart() {\n // Detect once at build start (fail fast on missing zod). `buildStart`\n // is guaranteed to run before any `resolveId`, so the target is set\n // before the rewrite hook fires.\n aliasTarget = resolveZodAliasTarget(root, 'attaform/rollup', resolveZodAlias, warnState)\n },\n resolveId(source, importer) {\n if (aliasTarget === null) return null\n if (source !== ZOD_UNIFIED_SPECIFIER) return null\n // Re-run the rewritten specifier through the resolver chain so the\n // matching subpath export lands as a real module. `skipSelf` keeps\n // the hook reentrant (our source check rejects the rewritten target\n // anyway, since it is no longer the bare unified specifier).\n return this.resolve(aliasTarget, importer, { skipSelf: true })\n },\n }\n}\n"],"names":[],"mappings":";;AA+DO,SAAS,QAAA,CAAS,OAAA,GAAuC,EAAC,EAAyB;AACxF,EAAA,MAAM,eAAA,GAAkB,QAAQ,eAAA,KAAoB,KAAA;AACpD,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,IAAA,IAAQ,OAAA,CAAQ,GAAA,EAAI;AACzC,EAAA,MAAM,SAAA,GAAY,EAAE,MAAA,EAAQ,KAAA,EAAM;AAClC,EAAA,IAAI,WAAA,GAA6B,IAAA;AAEjC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,UAAA;AAAA,IACN,UAAA,GAAa;AAIX,MAAA,WAAA,GAAc,qBAAA,CAAsB,IAAA,EAAM,iBAAA,EAAmB,eAAA,EAAiB,SAAS,CAAA;AAAA,IACzF,CAAA;AAAA,IACA,SAAA,CAAU,QAAQ,QAAA,EAAU;AAC1B,MAAA,IAAI,WAAA,KAAgB,MAAM,OAAO,IAAA;AACjC,MAAA,IAAI,MAAA,KAAW,uBAAuB,OAAO,IAAA;AAK7C,MAAA,OAAO,KAAK,OAAA,CAAQ,WAAA,EAAa,UAAU,EAAE,QAAA,EAAU,MAAM,CAAA;AAAA,IAC/D;AAAA,GACF;AACF;;;;"}
@@ -0,0 +1,10 @@
1
+ 'use strict';
2
+
3
+ const webpackFamilyPlugin = require('./shared/attaform.BRGIpZo4.cjs');
4
+
5
+ function attaform(options = {}) {
6
+ return webpackFamilyPlugin.createWebpackFamilyPlugin("attaform/rspack", options);
7
+ }
8
+
9
+ exports.attaform = attaform;
10
+ //# sourceMappingURL=rspack.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rspack.cjs","sources":["../src/rspack.ts"],"sourcesContent":["/**\n * `attaform/rspack` — Rspack plugin that rewrites `attaform/zod` imports\n * to the single matching adapter subpath (`attaform/zod-v3` or\n * `attaform/zod-v4`) at build time, based on the consumer's installed Zod\n * major. Without it, Rspack ships both adapters because the unified\n * `attaform/zod` entry imports both for runtime dispatch.\n *\n * Usage:\n *\n * // rspack.config.mjs\n * import { attaform } from 'attaform/rspack'\n *\n * export default {\n * plugins: [attaform()],\n * }\n *\n * Rspack mirrors webpack's plugin API for the resolve hook attaform taps,\n * so this shares its body with `attaform/webpack` via\n * `createWebpackFamilyPlugin`; only the diagnostic tag differs.\n *\n * This plugin only does the adapter rewrite. The Vue SFC `v-register`\n * transforms that `attaform/vite` wires (load-bearing for SSR initial\n * render) are `@vitejs/plugin-vue`-specific and do not transfer; a\n * non-Vite consumer that needs them wires `attaform/transforms` into\n * their Vue compiler separately.\n *\n * Zero-dep: the plugin imports nothing from `@rspack/core` (it taps the\n * resolve hook the compiler injects at the consumer's build).\n */\nimport {\n createWebpackFamilyPlugin,\n type WebpackFamilyPlugin,\n type WebpackFamilyPluginOptions,\n} from './core/webpack-family-plugin'\n\n/** Options for the Rspack `attaform()` plugin. */\nexport type AttaformRspackPluginOptions = WebpackFamilyPluginOptions\n/** The structural shape Rspack requires of the plugin. */\nexport type AttaformRspackPlugin = WebpackFamilyPlugin\n\nexport function attaform(options: AttaformRspackPluginOptions = {}): AttaformRspackPlugin {\n return createWebpackFamilyPlugin('attaform/rspack', options)\n}\n"],"names":["createWebpackFamilyPlugin"],"mappings":";;;;AAwCO,SAAS,QAAA,CAAS,OAAA,GAAuC,EAAC,EAAyB;AACxF,EAAA,OAAOA,6CAAA,CAA0B,mBAAmB,OAAO,CAAA;AAC7D;;;;"}