attaform 0.18.2 → 0.20.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/README.md +3 -0
- package/dist/chunks/devtools.cjs +1 -1
- package/dist/chunks/devtools.mjs +1 -1
- package/dist/chunks/indexeddb.cjs +1 -1
- package/dist/chunks/indexeddb.mjs +1 -1
- package/dist/chunks/local-storage.cjs +1 -1
- package/dist/chunks/local-storage.mjs +1 -1
- package/dist/chunks/session-storage.cjs +1 -1
- package/dist/chunks/session-storage.mjs +1 -1
- package/dist/index.cjs +4 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +77 -110
- package/dist/index.d.mts +77 -110
- package/dist/index.d.ts +77 -110
- package/dist/index.mjs +5 -5
- package/dist/nuxt.d.cts +1 -1
- package/dist/nuxt.d.mts +1 -1
- package/dist/nuxt.d.ts +1 -1
- package/dist/runtime/components/AttaformDevtoolsPanel.vue +2 -2
- package/dist/runtime/components/DevtoolsValueTree.d.vue.ts +1 -3
- package/dist/runtime/components/DevtoolsValueTree.vue.d.ts +1 -3
- package/dist/runtime/plugins/attaform.cjs +2 -2
- package/dist/runtime/plugins/attaform.mjs +2 -2
- package/dist/shared/{attaform.CDmaxrt2.mjs → attaform.BKozEdTr.mjs} +305 -178
- package/dist/shared/attaform.BKozEdTr.mjs.map +1 -0
- package/dist/shared/{attaform.Bubm_slq.cjs → attaform.BM6YD9kZ.cjs} +212 -269
- package/dist/shared/attaform.BM6YD9kZ.cjs.map +1 -0
- package/dist/shared/{attaform.5UhpSVFI.cjs → attaform.BPxsYtTe.cjs} +2 -26
- package/dist/shared/attaform.BPxsYtTe.cjs.map +1 -0
- package/dist/shared/{attaform.BqK_L4gK.cjs → attaform.BPy-4qRx.cjs} +305 -180
- package/dist/shared/attaform.BPy-4qRx.cjs.map +1 -0
- package/dist/shared/attaform.BWgAFnsj.mjs +770 -0
- package/dist/shared/attaform.BWgAFnsj.mjs.map +1 -0
- package/dist/shared/{attaform.CGX1CNpz.d.ts → attaform.Bh3ACtts.d.ts} +152 -111
- package/dist/shared/{attaform.CXpzmj38.mjs → attaform.BupwXkj_.mjs} +213 -270
- package/dist/shared/attaform.BupwXkj_.mjs.map +1 -0
- package/dist/shared/{attaform.Dlk1jMuv.cjs → attaform.CIn4bMsD.cjs} +263 -799
- package/dist/shared/attaform.CIn4bMsD.cjs.map +1 -0
- package/dist/shared/{attaform.CZ-XtZt_.mjs → attaform.CKFbKFb6.mjs} +2265 -1509
- package/dist/shared/attaform.CKFbKFb6.mjs.map +1 -0
- package/dist/shared/{attaform.CuN7ZhBy.d.cts → attaform.D5-1XGQU.d.cts} +152 -111
- package/dist/shared/{attaform.-1GQTX2T.mjs → attaform.DEBvCjeH.mjs} +257 -793
- package/dist/shared/attaform.DEBvCjeH.mjs.map +1 -0
- package/dist/shared/{attaform.II89Pcf4.cjs → attaform.DL4CQ-oW.cjs} +2270 -1514
- package/dist/shared/attaform.DL4CQ-oW.cjs.map +1 -0
- package/dist/shared/{attaform.FnEwjhvX.d.ts → attaform.DSD85fHb.d.cts} +1 -19
- package/dist/shared/{attaform.CRmmNAYp.d.cts → attaform.DSD85fHb.d.mts} +1 -19
- package/dist/shared/{attaform.D9wuTGu9.d.mts → attaform.DSD85fHb.d.ts} +1 -19
- package/dist/shared/{attaform.B7rzpK1U.d.cts → attaform.DkA5J8NW.d.cts} +1 -17
- package/dist/shared/{attaform.B7rzpK1U.d.mts → attaform.DkA5J8NW.d.mts} +1 -17
- package/dist/shared/{attaform.B7rzpK1U.d.ts → attaform.DkA5J8NW.d.ts} +1 -17
- package/dist/shared/{attaform.B957T6NU.d.ts → attaform.Dl5kDY-A.d.ts} +1 -1
- package/dist/shared/attaform.Dmb6itxC.cjs +781 -0
- package/dist/shared/attaform.Dmb6itxC.cjs.map +1 -0
- package/dist/shared/{attaform.M-RanbyV.d.mts → attaform.DoKXru-a.d.mts} +1 -1
- package/dist/shared/attaform.DvA-CJJW.mjs +1876 -0
- package/dist/shared/attaform.DvA-CJJW.mjs.map +1 -0
- package/dist/shared/{attaform.D1gzu2GL.d.mts → attaform.EMzJcQci.d.mts} +152 -111
- package/dist/shared/attaform.EZG6fOFb.mjs +35 -0
- package/dist/shared/attaform.EZG6fOFb.mjs.map +1 -0
- package/dist/shared/{attaform.XDjA7sRz.d.cts → attaform.GbDo_lJi.d.cts} +1 -1
- package/dist/shared/{attaform.Ca5_6Ky-.d.mts → attaform.SfhU0OEY.d.cts} +499 -116
- package/dist/shared/{attaform.Ca5_6Ky-.d.cts → attaform.SfhU0OEY.d.mts} +499 -116
- package/dist/shared/{attaform.Ca5_6Ky-.d.ts → attaform.SfhU0OEY.d.ts} +499 -116
- package/dist/shared/attaform.jgzuNZVC.cjs +1882 -0
- package/dist/shared/attaform.jgzuNZVC.cjs.map +1 -0
- package/dist/transforms.cjs +2 -2
- package/dist/transforms.d.cts +22 -13
- package/dist/transforms.d.mts +22 -13
- package/dist/transforms.d.ts +22 -13
- package/dist/transforms.mjs +1 -1
- package/dist/vite.cjs +8 -7
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.mjs +8 -7
- package/dist/vite.mjs.map +1 -1
- package/dist/zod-v3.cjs +3 -3
- package/dist/zod-v3.d.cts +32 -6
- package/dist/zod-v3.d.mts +32 -6
- package/dist/zod-v3.d.ts +32 -6
- package/dist/zod-v3.mjs +3 -3
- package/dist/zod-v4.cjs +3 -3
- package/dist/zod-v4.d.cts +12 -8
- package/dist/zod-v4.d.mts +12 -8
- package/dist/zod-v4.d.ts +12 -8
- package/dist/zod-v4.mjs +3 -3
- package/dist/zod.cjs +8 -8
- package/dist/zod.cjs.map +1 -1
- package/dist/zod.d.cts +6 -6
- package/dist/zod.d.mts +6 -6
- package/dist/zod.d.ts +6 -6
- package/dist/zod.mjs +6 -6
- package/package.json +2 -2
- package/dist/shared/attaform.-1GQTX2T.mjs.map +0 -1
- package/dist/shared/attaform.5UhpSVFI.cjs.map +0 -1
- package/dist/shared/attaform.BqK_L4gK.cjs.map +0 -1
- package/dist/shared/attaform.Bubm_slq.cjs.map +0 -1
- package/dist/shared/attaform.C8CyvYa_.cjs +0 -36
- package/dist/shared/attaform.C8CyvYa_.cjs.map +0 -1
- package/dist/shared/attaform.CDmaxrt2.mjs.map +0 -1
- package/dist/shared/attaform.CXpzmj38.mjs.map +0 -1
- package/dist/shared/attaform.CZ-XtZt_.mjs.map +0 -1
- package/dist/shared/attaform.D13GMFgK.mjs +0 -32
- package/dist/shared/attaform.D13GMFgK.mjs.map +0 -1
- package/dist/shared/attaform.DUHru0OF.cjs +0 -1600
- package/dist/shared/attaform.DUHru0OF.cjs.map +0 -1
- package/dist/shared/attaform.Df0tU0Ut.mjs +0 -1594
- package/dist/shared/attaform.Df0tU0Ut.mjs.map +0 -1
- package/dist/shared/attaform.Dl161U6E.mjs +0 -57
- package/dist/shared/attaform.Dl161U6E.mjs.map +0 -1
- package/dist/shared/attaform.Dlk1jMuv.cjs.map +0 -1
- package/dist/shared/attaform.II89Pcf4.cjs.map +0 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Plugin, App } from 'vue';
|
|
2
|
-
import { S as SSRDetectOptions,
|
|
3
|
-
export { A as
|
|
4
|
-
import { f as AttaformDefaults,
|
|
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, E as ErrorsProxyShape, F as FieldMetaPayload,
|
|
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
|
|
2
|
+
import { S as SSRDetectOptions, c as SerializedFormData, b as AttaformRegistry } from './shared/attaform.EMzJcQci.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.EMzJcQci.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.SfhU0OEY.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.SfhU0OEY.mjs';
|
|
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
|
/**
|
|
9
9
|
* Options for `createAttaform()`.
|
|
@@ -217,39 +217,13 @@ declare const vRegister: RegisterModelDynamicCustomDirective;
|
|
|
217
217
|
* the Nuxt DevTools (overlay) panel wired up via `../../nuxt.ts` +
|
|
218
218
|
* `../pages/_attaform_devtools.vue`.
|
|
219
219
|
*
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
*
|
|
220
|
+
* Houses the window-bridge contract both surfaces consume so a new
|
|
221
|
+
* bridge field lands in one file. Both surfaces render RAW form values
|
|
222
|
+
* by design — DevTools is a dev-only surface, and redaction across every
|
|
223
|
+
* place a value surfaces is impractical security theater rather than a
|
|
224
|
+
* real safeguard.
|
|
223
225
|
*/
|
|
224
226
|
|
|
225
|
-
declare const REDACTED = "[redacted]";
|
|
226
|
-
/**
|
|
227
|
-
* Walk `value` and replace any leaf whose enclosing path matches the
|
|
228
|
-
* sensitive-name heuristic with the string `'[redacted]'`. Returns a
|
|
229
|
-
* new tree (no mutation of the input). Object keys + array indices are
|
|
230
|
-
* preserved; only the leaf payloads change.
|
|
231
|
-
*
|
|
232
|
-
* Applied to BOTH devtools surfaces' Form-value rendering AND every
|
|
233
|
-
* timeline event payload — leaks via either surface are treatable as
|
|
234
|
-
* "any developer with the panel open during user testing can read a
|
|
235
|
-
* customer's password," which is exactly the failure mode the
|
|
236
|
-
* sensitive-name guard exists to prevent on the storage side.
|
|
237
|
-
*
|
|
238
|
-
* Leaves whose path doesn't match a pattern pass through untouched.
|
|
239
|
-
* `acknowledgeSensitive: true` on persistence does NOT bypass this — if
|
|
240
|
-
* the consumer opted into persisting the value, they still shouldn't
|
|
241
|
-
* see it in DevTools timelines that grow unbounded.
|
|
242
|
-
*
|
|
243
|
-
* Implementation note: tracks an `inSensitiveSubtree` flag through the
|
|
244
|
-
* recursion instead of allocating a fresh path array per node + calling
|
|
245
|
-
* `isSensitivePath` per leaf. Once any ancestor segment matches the
|
|
246
|
-
* heuristic, the flag stays set for every descendant — the leaf simply
|
|
247
|
-
* returns `REDACTED` without re-scanning the path. For a 100-leaf form:
|
|
248
|
-
* ~100 path allocations + ~100 full-path regex sweeps → 0 path
|
|
249
|
-
* allocations + ~100 single-segment regex sweeps, with whole-subtree
|
|
250
|
-
* short-circuit when sensitive ancestors are found early.
|
|
251
|
-
*/
|
|
252
|
-
declare function redactSensitiveLeaves(value: unknown, matchSensitive: (segment: Segment) => boolean): unknown;
|
|
253
227
|
/**
|
|
254
228
|
* Property key on `window` that the Nuxt-side dev plugin attaches the
|
|
255
229
|
* bridge object to. The iframe-mounted overlay panel reads
|
|
@@ -287,86 +261,79 @@ declare global {
|
|
|
287
261
|
}
|
|
288
262
|
|
|
289
263
|
/**
|
|
290
|
-
* Library-default heuristic
|
|
291
|
-
* `field.
|
|
292
|
-
* has not configured an override at
|
|
293
|
-
* level.
|
|
294
|
-
*
|
|
295
|
-
*
|
|
296
|
-
*
|
|
297
|
-
* the
|
|
298
|
-
*
|
|
299
|
-
*
|
|
300
|
-
*
|
|
301
|
-
*
|
|
302
|
-
*
|
|
303
|
-
*
|
|
304
|
-
*
|
|
305
|
-
*
|
|
306
|
-
*
|
|
307
|
-
*
|
|
308
|
-
*
|
|
309
|
-
*
|
|
310
|
-
*
|
|
311
|
-
*
|
|
312
|
-
*
|
|
313
|
-
*
|
|
314
|
-
*
|
|
315
|
-
*
|
|
316
|
-
*
|
|
317
|
-
*
|
|
318
|
-
*
|
|
319
|
-
*
|
|
320
|
-
*
|
|
321
|
-
*
|
|
322
|
-
*
|
|
323
|
-
*
|
|
324
|
-
*
|
|
325
|
-
*
|
|
326
|
-
*
|
|
327
|
-
*
|
|
328
|
-
*
|
|
329
|
-
*
|
|
330
|
-
*
|
|
331
|
-
*
|
|
332
|
-
*
|
|
333
|
-
*
|
|
334
|
-
*
|
|
335
|
-
*
|
|
336
|
-
*
|
|
337
|
-
*
|
|
338
|
-
*
|
|
339
|
-
*
|
|
340
|
-
*
|
|
341
|
-
*
|
|
342
|
-
*
|
|
343
|
-
*
|
|
344
|
-
* the field; they reappear when the user blurs (or focuses a
|
|
345
|
-
* sibling). This deliberately includes blur-without-typing on a
|
|
346
|
-
* required field (touched flips on blur regardless of `dirty`), so
|
|
347
|
-
* a user who visits an empty required field and moves on sees the
|
|
348
|
-
* error.
|
|
349
|
-
*
|
|
350
|
-
* The framework already gates on `errors.length > 0` before invoking
|
|
351
|
-
* the predicate, so the body only decides *when* to surface existing
|
|
352
|
-
* errors, not whether errors exist.
|
|
264
|
+
* Library-default `getDisplayState` heuristic. Resolves every path's
|
|
265
|
+
* `field.displayState` — and thus `field.show*` and the `form.meta`
|
|
266
|
+
* 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'`.
|
|
353
318
|
*
|
|
354
319
|
* Public re-export so adopters can compose with this without
|
|
355
|
-
* copy-pasting the rule body
|
|
356
|
-
*
|
|
357
|
-
*
|
|
320
|
+
* copy-pasting the rule body — a layered predicate that special-cases a
|
|
321
|
+
* subtree but otherwise defers picks up future refinements
|
|
322
|
+
* automatically:
|
|
358
323
|
*
|
|
359
324
|
* ```ts
|
|
360
|
-
* import {
|
|
325
|
+
* import { defaultDisplayState } from 'attaform'
|
|
361
326
|
*
|
|
362
327
|
* useForm({
|
|
363
328
|
* schema,
|
|
364
|
-
*
|
|
365
|
-
*
|
|
329
|
+
* getDisplayState: (field, formMeta) => {
|
|
330
|
+
* const state = defaultDisplayState(field, formMeta)
|
|
331
|
+
* return field.path[0] === 'username' && state === 'success' ? 'idle' : state
|
|
332
|
+
* },
|
|
366
333
|
* })
|
|
367
334
|
* ```
|
|
368
335
|
*/
|
|
369
|
-
declare const
|
|
336
|
+
declare const defaultDisplayState: GetDisplayState;
|
|
370
337
|
|
|
371
338
|
/**
|
|
372
339
|
* The library's built-in conservative set of identifier name stems that
|
|
@@ -391,9 +358,9 @@ declare const defaultShouldShowErrors: ShouldShowErrors;
|
|
|
391
358
|
* })
|
|
392
359
|
* ```
|
|
393
360
|
*
|
|
394
|
-
* The same resolved predicate gates persistence writes
|
|
395
|
-
* broadcasts
|
|
396
|
-
*
|
|
361
|
+
* The same resolved predicate gates persistence writes and multi-tab
|
|
362
|
+
* sync broadcasts — one source of truth for "what counts as sensitive"
|
|
363
|
+
* across those surfaces. (DevTools renders raw values by design.)
|
|
397
364
|
*
|
|
398
365
|
* **Non-goals.** This is not a soundness guarantee. Adversarial paths
|
|
399
366
|
* (`'sensitive_data'`, `'CCV'` instead of `'CVV'`) can slip through.
|
|
@@ -529,5 +496,5 @@ declare const PARSE_API_ERRORS_DEFAULTS: {
|
|
|
529
496
|
*/
|
|
530
497
|
declare function parseApiErrors(payload: ApiErrorEnvelope | ApiErrorDetails | null | undefined | unknown, options: ParseApiErrorsOptions): ParseApiErrorsResult;
|
|
531
498
|
|
|
532
|
-
export { AbstractSchema, ApiErrorDetails, ApiErrorEnvelope, AttaformDefaults, AttaformRegistry, DEFAULT_SENSITIVE_NAMES, DEVTOOLS_WINDOW_KEY, DefaultValuesInput, FormKey, GenericForm,
|
|
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 };
|
|
533
500
|
export type { AttaformDevtoolsBridge, AttaformPluginOptions, ParseApiErrorsOptions, ParseApiErrorsResult, SerializedAttaformState };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Plugin, App } from 'vue';
|
|
2
|
-
import { S as SSRDetectOptions,
|
|
3
|
-
export { A as
|
|
4
|
-
import { f as AttaformDefaults,
|
|
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, E as ErrorsProxyShape, F as FieldMetaPayload,
|
|
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
|
|
2
|
+
import { S as SSRDetectOptions, c as SerializedFormData, b as AttaformRegistry } from './shared/attaform.Bh3ACtts.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.Bh3ACtts.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.SfhU0OEY.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.SfhU0OEY.js';
|
|
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
|
/**
|
|
9
9
|
* Options for `createAttaform()`.
|
|
@@ -217,39 +217,13 @@ declare const vRegister: RegisterModelDynamicCustomDirective;
|
|
|
217
217
|
* the Nuxt DevTools (overlay) panel wired up via `../../nuxt.ts` +
|
|
218
218
|
* `../pages/_attaform_devtools.vue`.
|
|
219
219
|
*
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
*
|
|
220
|
+
* Houses the window-bridge contract both surfaces consume so a new
|
|
221
|
+
* bridge field lands in one file. Both surfaces render RAW form values
|
|
222
|
+
* by design — DevTools is a dev-only surface, and redaction across every
|
|
223
|
+
* place a value surfaces is impractical security theater rather than a
|
|
224
|
+
* real safeguard.
|
|
223
225
|
*/
|
|
224
226
|
|
|
225
|
-
declare const REDACTED = "[redacted]";
|
|
226
|
-
/**
|
|
227
|
-
* Walk `value` and replace any leaf whose enclosing path matches the
|
|
228
|
-
* sensitive-name heuristic with the string `'[redacted]'`. Returns a
|
|
229
|
-
* new tree (no mutation of the input). Object keys + array indices are
|
|
230
|
-
* preserved; only the leaf payloads change.
|
|
231
|
-
*
|
|
232
|
-
* Applied to BOTH devtools surfaces' Form-value rendering AND every
|
|
233
|
-
* timeline event payload — leaks via either surface are treatable as
|
|
234
|
-
* "any developer with the panel open during user testing can read a
|
|
235
|
-
* customer's password," which is exactly the failure mode the
|
|
236
|
-
* sensitive-name guard exists to prevent on the storage side.
|
|
237
|
-
*
|
|
238
|
-
* Leaves whose path doesn't match a pattern pass through untouched.
|
|
239
|
-
* `acknowledgeSensitive: true` on persistence does NOT bypass this — if
|
|
240
|
-
* the consumer opted into persisting the value, they still shouldn't
|
|
241
|
-
* see it in DevTools timelines that grow unbounded.
|
|
242
|
-
*
|
|
243
|
-
* Implementation note: tracks an `inSensitiveSubtree` flag through the
|
|
244
|
-
* recursion instead of allocating a fresh path array per node + calling
|
|
245
|
-
* `isSensitivePath` per leaf. Once any ancestor segment matches the
|
|
246
|
-
* heuristic, the flag stays set for every descendant — the leaf simply
|
|
247
|
-
* returns `REDACTED` without re-scanning the path. For a 100-leaf form:
|
|
248
|
-
* ~100 path allocations + ~100 full-path regex sweeps → 0 path
|
|
249
|
-
* allocations + ~100 single-segment regex sweeps, with whole-subtree
|
|
250
|
-
* short-circuit when sensitive ancestors are found early.
|
|
251
|
-
*/
|
|
252
|
-
declare function redactSensitiveLeaves(value: unknown, matchSensitive: (segment: Segment) => boolean): unknown;
|
|
253
227
|
/**
|
|
254
228
|
* Property key on `window` that the Nuxt-side dev plugin attaches the
|
|
255
229
|
* bridge object to. The iframe-mounted overlay panel reads
|
|
@@ -287,86 +261,79 @@ declare global {
|
|
|
287
261
|
}
|
|
288
262
|
|
|
289
263
|
/**
|
|
290
|
-
* Library-default heuristic
|
|
291
|
-
* `field.
|
|
292
|
-
* has not configured an override at
|
|
293
|
-
* level.
|
|
294
|
-
*
|
|
295
|
-
*
|
|
296
|
-
*
|
|
297
|
-
* the
|
|
298
|
-
*
|
|
299
|
-
*
|
|
300
|
-
*
|
|
301
|
-
*
|
|
302
|
-
*
|
|
303
|
-
*
|
|
304
|
-
*
|
|
305
|
-
*
|
|
306
|
-
*
|
|
307
|
-
*
|
|
308
|
-
*
|
|
309
|
-
*
|
|
310
|
-
*
|
|
311
|
-
*
|
|
312
|
-
*
|
|
313
|
-
*
|
|
314
|
-
*
|
|
315
|
-
*
|
|
316
|
-
*
|
|
317
|
-
*
|
|
318
|
-
*
|
|
319
|
-
*
|
|
320
|
-
*
|
|
321
|
-
*
|
|
322
|
-
*
|
|
323
|
-
*
|
|
324
|
-
*
|
|
325
|
-
*
|
|
326
|
-
*
|
|
327
|
-
*
|
|
328
|
-
*
|
|
329
|
-
*
|
|
330
|
-
*
|
|
331
|
-
*
|
|
332
|
-
*
|
|
333
|
-
*
|
|
334
|
-
*
|
|
335
|
-
*
|
|
336
|
-
*
|
|
337
|
-
*
|
|
338
|
-
*
|
|
339
|
-
*
|
|
340
|
-
*
|
|
341
|
-
*
|
|
342
|
-
*
|
|
343
|
-
*
|
|
344
|
-
* the field; they reappear when the user blurs (or focuses a
|
|
345
|
-
* sibling). This deliberately includes blur-without-typing on a
|
|
346
|
-
* required field (touched flips on blur regardless of `dirty`), so
|
|
347
|
-
* a user who visits an empty required field and moves on sees the
|
|
348
|
-
* error.
|
|
349
|
-
*
|
|
350
|
-
* The framework already gates on `errors.length > 0` before invoking
|
|
351
|
-
* the predicate, so the body only decides *when* to surface existing
|
|
352
|
-
* errors, not whether errors exist.
|
|
264
|
+
* Library-default `getDisplayState` heuristic. Resolves every path's
|
|
265
|
+
* `field.displayState` — and thus `field.show*` and the `form.meta`
|
|
266
|
+
* 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'`.
|
|
353
318
|
*
|
|
354
319
|
* Public re-export so adopters can compose with this without
|
|
355
|
-
* copy-pasting the rule body
|
|
356
|
-
*
|
|
357
|
-
*
|
|
320
|
+
* copy-pasting the rule body — a layered predicate that special-cases a
|
|
321
|
+
* subtree but otherwise defers picks up future refinements
|
|
322
|
+
* automatically:
|
|
358
323
|
*
|
|
359
324
|
* ```ts
|
|
360
|
-
* import {
|
|
325
|
+
* import { defaultDisplayState } from 'attaform'
|
|
361
326
|
*
|
|
362
327
|
* useForm({
|
|
363
328
|
* schema,
|
|
364
|
-
*
|
|
365
|
-
*
|
|
329
|
+
* getDisplayState: (field, formMeta) => {
|
|
330
|
+
* const state = defaultDisplayState(field, formMeta)
|
|
331
|
+
* return field.path[0] === 'username' && state === 'success' ? 'idle' : state
|
|
332
|
+
* },
|
|
366
333
|
* })
|
|
367
334
|
* ```
|
|
368
335
|
*/
|
|
369
|
-
declare const
|
|
336
|
+
declare const defaultDisplayState: GetDisplayState;
|
|
370
337
|
|
|
371
338
|
/**
|
|
372
339
|
* The library's built-in conservative set of identifier name stems that
|
|
@@ -391,9 +358,9 @@ declare const defaultShouldShowErrors: ShouldShowErrors;
|
|
|
391
358
|
* })
|
|
392
359
|
* ```
|
|
393
360
|
*
|
|
394
|
-
* The same resolved predicate gates persistence writes
|
|
395
|
-
* broadcasts
|
|
396
|
-
*
|
|
361
|
+
* The same resolved predicate gates persistence writes and multi-tab
|
|
362
|
+
* sync broadcasts — one source of truth for "what counts as sensitive"
|
|
363
|
+
* across those surfaces. (DevTools renders raw values by design.)
|
|
397
364
|
*
|
|
398
365
|
* **Non-goals.** This is not a soundness guarantee. Adversarial paths
|
|
399
366
|
* (`'sensitive_data'`, `'CCV'` instead of `'CVV'`) can slip through.
|
|
@@ -529,5 +496,5 @@ declare const PARSE_API_ERRORS_DEFAULTS: {
|
|
|
529
496
|
*/
|
|
530
497
|
declare function parseApiErrors(payload: ApiErrorEnvelope | ApiErrorDetails | null | undefined | unknown, options: ParseApiErrorsOptions): ParseApiErrorsResult;
|
|
531
498
|
|
|
532
|
-
export { AbstractSchema, ApiErrorDetails, ApiErrorEnvelope, AttaformDefaults, AttaformRegistry, DEFAULT_SENSITIVE_NAMES, DEVTOOLS_WINDOW_KEY, DefaultValuesInput, FormKey, GenericForm,
|
|
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 };
|
|
533
500
|
export type { AttaformDevtoolsBridge, AttaformPluginOptions, ParseApiErrorsOptions, ParseApiErrorsResult, SerializedAttaformState };
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { A as AnonPersistError, a as AttaformError, D as DEFAULT_SENSITIVE_NAMES,
|
|
3
|
-
export { D as DEVTOOLS_WINDOW_KEY,
|
|
4
|
-
import { n as normalizeNumericOption } from './shared/attaform.
|
|
5
|
-
export { A as AttaformErrorCode, d as defaultCoercionRules, a as
|
|
1
|
+
import { j as canonicalizePath, c as InvalidPathError } from './shared/attaform.BKozEdTr.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, r as getRegistryFromApp, s as isPathPrefix, t as isRegisterValue, w as kAttaformRegistry, B as parseDottedPath, G as useRegister, H as useRegistry, J as vRegister } from './shared/attaform.BKozEdTr.mjs';
|
|
3
|
+
export { D as DEVTOOLS_WINDOW_KEY, h as hydrateAttaformState, r as renderAttaformState } from './shared/attaform.EZG6fOFb.mjs';
|
|
4
|
+
import { n as normalizeNumericOption } from './shared/attaform.CKFbKFb6.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, k as useForm, m as useWizard } from './shared/attaform.CKFbKFb6.mjs';
|
|
6
6
|
|
|
7
7
|
function escapeForInlineScript(json) {
|
|
8
8
|
return json.replace(/[<>&\u2028\u2029]/g, (char) => {
|
package/dist/nuxt.d.cts
CHANGED
package/dist/nuxt.d.mts
CHANGED
package/dist/nuxt.d.ts
CHANGED
|
@@ -58,7 +58,7 @@ function humanizePathKey(key) {
|
|
|
58
58
|
try {
|
|
59
59
|
const parsed = JSON.parse(key);
|
|
60
60
|
if (Array.isArray(parsed)) {
|
|
61
|
-
return parsed.map((seg) =>
|
|
61
|
+
return parsed.map((seg) => String(seg)).join(".");
|
|
62
62
|
}
|
|
63
63
|
} catch {
|
|
64
64
|
}
|
|
@@ -449,5 +449,5 @@ onUnmounted(() => {
|
|
|
449
449
|
</template>
|
|
450
450
|
|
|
451
451
|
<style scoped>
|
|
452
|
-
.atf-panel{--atf-bg:#0f172a;--atf-bg-elev:#111c33;--atf-fg:#e2e8f0;--atf-fg-muted:#94a3b8;--atf-border:rgba(148,163,184,.12);--atf-border-strong:rgba(148,163,184,.2);--atf-accent:#5b8def;--atf-key:#93c5fd;--atf-string:#86efac;--atf-number:#fbbf24;--atf-boolean:#f472b6;--atf-
|
|
452
|
+
.atf-panel{--atf-bg:#0f172a;--atf-bg-elev:#111c33;--atf-fg:#e2e8f0;--atf-fg-muted:#94a3b8;--atf-border:rgba(148,163,184,.12);--atf-border-strong:rgba(148,163,184,.2);--atf-accent:#5b8def;--atf-key:#93c5fd;--atf-string:#86efac;--atf-number:#fbbf24;--atf-boolean:#f472b6;--atf-danger:#f87171;--atf-muted:#64748b;--atf-row-hover:hsla(0,0%,100%,.04);--atf-error-bg:rgba(248,113,113,.1);--atf-warn-bg:rgba(251,191,36,.1);background:var(--atf-bg);color:var(--atf-fg);display:flex;flex-direction:column;font-family:system-ui,-apple-system,Segoe UI,sans-serif;font-size:13px;height:100vh;line-height:1.5}@media (prefers-color-scheme:light){.atf-panel{--atf-bg:#fff;--atf-bg-elev:#f8fafc;--atf-fg:#0f172a;--atf-fg-muted:#64748b;--atf-border:rgba(15,23,42,.08);--atf-border-strong:rgba(15,23,42,.16);--atf-key:#2563eb;--atf-string:#16a34a;--atf-number:#d97706;--atf-boolean:#db2777;--atf-danger:#dc2626;--atf-muted:#94a3b8;--atf-row-hover:rgba(15,23,42,.04);--atf-error-bg:rgba(220,38,38,.08);--atf-warn-bg:rgba(217,119,6,.08)}}.atf-header{background:var(--atf-bg-elev);border-bottom:1px solid var(--atf-border);flex:0 0 auto;padding:.75rem 1rem}.atf-brand{align-items:center;display:flex;gap:.5rem}.atf-logo{display:block;height:22px;width:22px}.atf-title{font-size:14px;font-weight:600}.atf-version{color:var(--atf-fg-muted);font-family:ui-monospace,monospace;font-size:11px}.atf-body{display:grid;flex:1 1 auto;grid-template-columns:200px 1fr;min-height:0}.atf-sidebar{border-right:1px solid var(--atf-border);overflow-y:auto;padding:.75rem 0}.atf-sidebar-title{align-items:center;color:var(--atf-fg-muted);display:flex;font-size:11px;gap:.4em;letter-spacing:.05em;padding:0 1rem .5rem;text-transform:uppercase}.atf-count{background:var(--atf-border-strong);border-radius:999px;color:var(--atf-fg);font-size:10px;padding:0 .4em}.atf-empty{color:var(--atf-fg-muted);list-style:none;margin:0;padding:0 1rem}.atf-empty small{display:block;font-size:11px;margin-top:.4rem}.atf-empty code{background:var(--atf-border);border-radius:3px;font-size:11px;padding:.05em .35em}.atf-form-list{list-style:none;margin:0;padding:0}.atf-form-item{cursor:pointer;font-family:ui-monospace,monospace;font-size:12px;padding:.4rem 1rem;-webkit-user-select:none;-moz-user-select:none;user-select:none}.atf-form-item:hover{background:var(--atf-row-hover)}.atf-form-item.active{background:rgba(91,141,239,.12);border-left:2px solid var(--atf-accent);color:var(--atf-key);padding-left:calc(1rem - 2px)}.atf-detail{overflow-y:auto;padding:1rem 1.25rem}.atf-empty-detail{color:var(--atf-fg-muted);padding:3rem 0;text-align:center}.atf-section{margin-bottom:1.25rem}.atf-section-title{align-items:center;color:var(--atf-fg-muted);display:flex;font-size:11px;font-weight:600;gap:.5em;letter-spacing:.06em;margin:0 0 .5rem;text-transform:uppercase}.atf-section-body{background:var(--atf-bg-elev);border:1px solid var(--atf-border);border-radius:6px;padding:.6rem .8rem}.atf-badge{border-radius:999px;font-size:10px;font-weight:600;letter-spacing:.04em;padding:0 .45em}.atf-badge-error{background:var(--atf-error-bg);color:var(--atf-danger)}.atf-badge-warn{background:var(--atf-warn-bg);color:var(--atf-number)}.atf-empty-list{color:var(--atf-fg-muted);font-size:12px;margin:0}.atf-error-list{list-style:none;margin:0;padding:0}.atf-error-list>li+li{border-top:1px solid var(--atf-border);margin-top:.6rem;padding-top:.6rem}.atf-path{color:var(--atf-key);display:block;font-family:ui-monospace,monospace;font-size:12px;margin-bottom:.25rem}.atf-error-messages{color:var(--atf-danger);font-size:12px;list-style:none;margin:0;padding:0}.atf-error-messages>li+li{margin-top:.2rem}.atf-aggregates{display:grid;font-family:ui-monospace,monospace;font-size:12px;gap:.35rem .75rem;grid-template-columns:max-content 1fr;margin:0}.atf-aggregates dt{color:var(--atf-key)}.atf-aggregates dd{color:var(--atf-fg);margin:0}.atf-badge-neutral{background:var(--atf-border-strong);color:var(--atf-fg)}.atf-clear-btn{background:transparent;border:1px solid var(--atf-border);border-radius:4px;cursor:pointer;font:inherit;font-size:11px;padding:.1rem .5rem}.atf-clear-btn,.atf-section-hint{color:var(--atf-fg-muted);margin-left:auto}.atf-section-hint{font-size:10px;font-weight:400;letter-spacing:0;text-transform:none}.atf-fg-muted{color:var(--atf-fg-muted)}.atf-clear-btn:hover{border-color:var(--atf-border-strong);color:var(--atf-fg)}.atf-timeline{list-style:none;margin:0;max-height:18rem;overflow-y:auto;padding:0}.atf-timeline-entry{border-top:1px solid var(--atf-border)}.atf-timeline-entry:first-child{border-top:0}.atf-timeline-row{align-items:baseline;cursor:pointer;display:grid;font-family:ui-monospace,monospace;font-size:11px;gap:.6rem;grid-template-columns:7.5rem 8rem 1fr auto;padding:.4rem 0}.atf-timeline-row:hover{background:var(--atf-row-hover)}.atf-timeline-time{color:var(--atf-fg-muted)}.atf-timeline-type{color:var(--atf-key);font-weight:600}.atf-timeline-form{color:var(--atf-fg);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.atf-timeline-caret{color:var(--atf-fg-muted);text-align:center;width:1em}.atf-timeline-entry.atf-timeline-submit .atf-timeline-type{color:var(--atf-string)}.atf-timeline-entry.atf-timeline-reset .atf-timeline-type{color:var(--atf-danger)}.atf-timeline-detail{border-top:1px dashed var(--atf-border);margin-top:-1px;padding:.4rem 0 .6rem 7.5rem}
|
|
453
453
|
</style>
|
|
@@ -11,9 +11,7 @@ type __VLS_Props = {
|
|
|
11
11
|
path?: ReadonlyArray<string | number>;
|
|
12
12
|
/**
|
|
13
13
|
* Edit-mode toggle. When `true` and `onEdit` is wired, leaf cells
|
|
14
|
-
* become click-to-edit.
|
|
15
|
-
* regardless — overwriting with the literal `[redacted]` string
|
|
16
|
-
* would destroy the real value.
|
|
14
|
+
* become click-to-edit. Values render raw (DevTools does not redact).
|
|
17
15
|
*/
|
|
18
16
|
editable?: boolean | undefined;
|
|
19
17
|
onEdit?: ((path: ReadonlyArray<string | number>, next: unknown) => void) | undefined;
|
|
@@ -11,9 +11,7 @@ type __VLS_Props = {
|
|
|
11
11
|
path?: ReadonlyArray<string | number>;
|
|
12
12
|
/**
|
|
13
13
|
* Edit-mode toggle. When `true` and `onEdit` is wired, leaf cells
|
|
14
|
-
* become click-to-edit.
|
|
15
|
-
* regardless — overwriting with the literal `[redacted]` string
|
|
16
|
-
* would destroy the real value.
|
|
14
|
+
* become click-to-edit. Values render raw (DevTools does not redact).
|
|
17
15
|
*/
|
|
18
16
|
editable?: boolean | undefined;
|
|
19
17
|
onEdit?: ((path: ReadonlyArray<string | number>, next: unknown) => void) | undefined;
|