jsonisch 0.1.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.
@@ -0,0 +1,724 @@
1
+ import { C as flattenSourceRow, D as derivation, F as AmountOrPercentEnvelope, G as CalcParseResult, H as EstimateMeta, K as DerivationMode, L as EntryMeta, M as ValidateFormInputConfig, N as ValidationResult, R as EntryMode, S as computeBag, V as EstimateEnvelope, W as CalcEngine, _ as bagger, b as ComputeBagOptions, c as CheckDefinition, d as ChecksConfig, f as Finding, h as SeverityConfig, i as formulaCheck, j as envelopes, l as CheckInstanceConfig, m as Severity, n as replaceCheckInstances, p as FormulaOptions, q as DerivedState, r as UNEVALUABLE_MESSAGE_ID, s as CheckContext, t as checks, u as CheckScope, w as visibility, x as collectionKeys, y as BaggerOptions, z as Envelope } from "./plugin-BCsAE8RK.js";
2
+ import { A as VisibleWhen, C as FieldErrors, G as JsonSchema, K as Path, M as ControlKind, N as inferControl, _ as WireContract, a as InternalFormStore, g as PluginsInput, i as FormValidator, j as VisibleWhenOp, o as ValidationIssue, q as PathSegment, r as FormConfig, s as ValidationMode, t as FormRef, w as FieldKind, x as ContainerInput } from "./form-ref-D_xHSaqL.js";
3
+ import { n as handleSubmit, t as SubmitHandler } from "./handle-submit-Dk7QW3_q.js";
4
+
5
+ //#region src/core/form/create-form-store.d.ts
6
+ /**
7
+ * The default empty input of a form. Required string fields start as an
8
+ * empty string, while every other type starts as `undefined`.
9
+ */
10
+ declare const DEFAULT_EMPTY_INPUT: Record<string, unknown>;
11
+ /**
12
+ * The default root-record alias (`FormConfig.rootRecordAlias`). The
13
+ * store's resolved value is the one home at runtime; this default
14
+ * exists so store-less readers (`computeBag`) resolve identically.
15
+ */
16
+ declare const DEFAULT_ROOT_RECORD_ALIAS = "record";
17
+ /**
18
+ * Creates a new internal form store from the provided configuration: walks
19
+ * the JSON-Schema once and builds the field-store tree (`kind:
20
+ * array|object|value`), with the schema as the allow-list — `initialInput`
21
+ * keys not declared in the schema never enter form state.
22
+ *
23
+ * Plugins are resolved and their state containers created BEFORE the walk,
24
+ * so the walk can dispatch `buildScope` for every array-item object it
25
+ * creates (a row wired by the walk behaves exactly like one built later by
26
+ * an insert). The ROOT scope is dispatched after the walk, in plugin array
27
+ * order — for the standard trio that means envelopes (the estimate pin's
28
+ * mode signal) before derivation before visibility.
29
+ *
30
+ * @param config The form configuration.
31
+ *
32
+ * @returns The internal form store.
33
+ */
34
+ declare function createFormStore(config: FormConfig): InternalFormStore;
35
+ //#endregion
36
+ //#region src/methods/apply-baseline.d.ts
37
+ /**
38
+ * Configuration for `applyBaseline`.
39
+ */
40
+ interface ApplyBaselineConfig {
41
+ /**
42
+ * Fresh off-form values (canonical rows, the read-only eval scope) to
43
+ * adopt in the same batch as the baseline, so formula fields recompute
44
+ * once against a consistent snapshot. Omit to keep the current values.
45
+ */
46
+ readonly offFormValues?: Record<string, unknown> | undefined;
47
+ }
48
+ /**
49
+ * Rebases a live form on a fresh server-loaded record — after a save or a
50
+ * revalidate, the store adopts the record as its new baseline instead of
51
+ * being torn down and rebuilt: the record decodes through the `x-column`
52
+ * codec (envelope fields keep their kind-discriminated shape for
53
+ * the plugin rebase), clean fields
54
+ * take the new server value, dirty fields keep the user's in-flight edit
55
+ * re-diffed against the new baseline (an edit equal to the fresh server
56
+ * value becomes clean), and a later `reset()` returns to the NEW baseline.
57
+ * Array membership follows the same rule: unchanged membership adopts the
58
+ * server rows — by `id` when the item schema has usable ids, otherwise
59
+ * positionally — and surviving rows keep their identity. Unmatched clean
60
+ * locals drop; unmatched dirty locals append after the server prefix
61
+ * (field-level dirty still enables Save). Locally changed membership wins,
62
+ * with rows still rebasing content by server `id` where ids exist.
63
+ *
64
+ * It is NOT conflict resolution — two people editing the same field stays
65
+ * last-write-wins. A nullish record is a no-op (nothing to rebase on).
66
+ *
67
+ * For flat-JSONB surfaces without column routing, pass the bag as
68
+ * `{ data: bag }` (the `decodeRecord` convention).
69
+ *
70
+ * @param form The form store to rebase.
71
+ * @param record The fresh server record (`{ …columns, data? }`).
72
+ * @param config Rebase options (e.g. fresh off-form values).
73
+ */
74
+ declare function applyBaseline(form: FormRef, record: Record<string, unknown> | null | undefined, config?: ApplyBaselineConfig): void;
75
+ //#endregion
76
+ //#region src/methods/array-ops.d.ts
77
+ /**
78
+ * Configuration for inserting an array item.
79
+ */
80
+ interface InsertConfig {
81
+ /**
82
+ * The index to insert the new item at. Appends to the end when omitted.
83
+ */
84
+ readonly at?: number | undefined;
85
+ /**
86
+ * The initial input value for the new item.
87
+ */
88
+ readonly initialInput?: unknown;
89
+ }
90
+ /**
91
+ * Inserts a new item into the array field at the given path. All items at
92
+ * or after the insertion point shift up by one index, and their full state
93
+ * (values, errors, touched/dirty flags, elements) shifts with them.
94
+ *
95
+ * @param form The form store containing the array field.
96
+ * @param path The path to the array field.
97
+ * @param config The insert configuration.
98
+ */
99
+ declare function insert(form: FormRef, path: Path, config?: InsertConfig): void;
100
+ /**
101
+ * Removes the item at the given index from the array field at the given
102
+ * path. All items after it shift down by one index with their full state.
103
+ *
104
+ * @param form The form store containing the array field.
105
+ * @param path The path to the array field.
106
+ * @param at The index of the item to remove.
107
+ */
108
+ declare function remove(form: FormRef, path: Path, at: number): void;
109
+ /**
110
+ * Moves the item at one index to another within the array field at the
111
+ * given path. All items between the two indices shift accordingly with
112
+ * their full state.
113
+ *
114
+ * @param form The form store containing the array field.
115
+ * @param path The path to the array field.
116
+ * @param from The index of the item to move.
117
+ * @param to The index to move the item to.
118
+ */
119
+ declare function move(form: FormRef, path: Path, from: number, to: number): void;
120
+ /**
121
+ * Swaps two items in the array field at the given path by exchanging their
122
+ * positions and their full state.
123
+ *
124
+ * @param form The form store containing the array field.
125
+ * @param path The path to the array field.
126
+ * @param at The index of the first item.
127
+ * @param and The index of the second item.
128
+ */
129
+ declare function swap(form: FormRef, path: Path, at: number, and: number): void;
130
+ //#endregion
131
+ //#region src/methods/errors.d.ts
132
+ /**
133
+ * Sets or clears the error messages of the field at the given path, or the
134
+ * form-level (root) errors when no path is given. Useful for custom errors
135
+ * that do not come from schema validation (e.g. a failed server action).
136
+ *
137
+ * @param form The form store to set errors on.
138
+ * @param errors The error messages, or `null` to clear.
139
+ * @param path The path to the field (omit for form-level errors).
140
+ */
141
+ declare function setErrors(form: FormRef, errors: FieldErrors, path?: Path): void;
142
+ /**
143
+ * Retrieves the error messages of the field at the given path, or the
144
+ * form-level (root) errors when no path is given. Does NOT include
145
+ * descendants — use `getDeepErrors` for a subtree.
146
+ *
147
+ * @param form The form store to read errors from.
148
+ * @param path The path to the field (omit for form-level errors).
149
+ *
150
+ * @returns The error messages, or `null`.
151
+ */
152
+ declare function getErrors(form: FormRef, path?: Path): FieldErrors;
153
+ /**
154
+ * Retrieves every error message of the field at the given path and all its
155
+ * descendants (the entire form when no path is given), in depth-first
156
+ * order. Form-level errors are included. This is what a checks panel sits
157
+ * on — it surfaces errors of fields that are not currently rendered.
158
+ *
159
+ * @param form The form store to read errors from.
160
+ * @param path The path to scope to (omit for the whole form).
161
+ *
162
+ * @returns The error messages, or `null` if none exist.
163
+ */
164
+ declare function getDeepErrors(form: FormRef, path?: Path): FieldErrors;
165
+ /**
166
+ * One deep-error entry: the erroring field's path and its messages.
167
+ */
168
+ interface DeepErrorEntry {
169
+ /**
170
+ * The path to the erroring field (`[]` for form-level errors).
171
+ */
172
+ readonly path: Path;
173
+ /**
174
+ * The error messages of the field.
175
+ */
176
+ readonly errors: [string, ...string[]];
177
+ }
178
+ /**
179
+ * Retrieves every erroring field of the subtree at the given path (the
180
+ * entire form when no path is given) as `{ path, errors }` entries in
181
+ * depth-first order.
182
+ *
183
+ * @param form The form store to read errors from.
184
+ * @param path The path to scope to (omit for the whole form).
185
+ *
186
+ * @returns The deep error entries (empty when none exist).
187
+ */
188
+ declare function getDeepErrorEntries(form: FormRef, path?: Path): DeepErrorEntry[];
189
+ //#endregion
190
+ //#region src/methods/focus.d.ts
191
+ /**
192
+ * Focuses the first focusable element of the field at the given path.
193
+ * Detached, disabled or hidden elements are skipped.
194
+ *
195
+ * @param form The form store containing the field.
196
+ * @param path The path to the field to focus.
197
+ */
198
+ declare function focus(form: FormRef, path: Path): void;
199
+ //#endregion
200
+ //#region src/methods/get-dirty-input.d.ts
201
+ /**
202
+ * Retrieves only the dirty input values of the field at the given path, or
203
+ * the entire form when no path is given. Arrays are treated as atomic and
204
+ * returned in full if any item is dirty, while object keys without a dirty
205
+ * descendant are omitted. Returns `undefined` if nothing in the inspected
206
+ * subtree is dirty.
207
+ *
208
+ * @param form The form store to retrieve dirty input from.
209
+ * @param path The path to the field (omit for the whole form).
210
+ *
211
+ * @returns The dirty input, or `undefined`.
212
+ */
213
+ declare function getDirtyInput(form: FormRef, path?: Path): unknown;
214
+ //#endregion
215
+ //#region src/methods/get-dirty-paths.d.ts
216
+ /**
217
+ * Returns the paths to the dirty fields of the form (or of the subtree at
218
+ * the given path). Arrays are treated as atomic and contribute only their
219
+ * own path if any item is dirty; object branches are recursed into, and a
220
+ * container that flipped dirty itself (e.g. nullish → present) emits its
221
+ * own path only when no descendant already covers it.
222
+ *
223
+ * @param form The form store to inspect.
224
+ * @param path The path to scope to (omit for the whole form).
225
+ *
226
+ * @returns The list of paths to the dirty fields.
227
+ */
228
+ declare function getDirtyPaths(form: FormRef, path?: Path): Path[];
229
+ //#endregion
230
+ //#region src/methods/get-input.d.ts
231
+ /**
232
+ * Retrieves the current input value of the field at the given path, or the
233
+ * entire form when no path is given. The tree is the allow-list, so the
234
+ * result only ever contains declared fields.
235
+ *
236
+ * @param form The form store to retrieve input from.
237
+ * @param path The path to the field (omit for the whole form).
238
+ *
239
+ * @returns The input value.
240
+ */
241
+ declare function getInput(form: FormRef, path?: Path): unknown;
242
+ //#endregion
243
+ //#region src/methods/pick-dirty.d.ts
244
+ /**
245
+ * Picks only the dirty parts of the given value, using the form's dirty
246
+ * fields as a structural mask while reading from the SUPPLIED value (e.g. a
247
+ * validated output), not the form's own input. Arrays are treated as atomic
248
+ * and object keys without a dirty descendant are omitted. Returns
249
+ * `undefined` if no field is dirty or no dirty key is present in the value.
250
+ *
251
+ * Envelope leaves (estimate/amount-or-percent) emit their COMPLETE
252
+ * kind envelope — the plugin wraps the supplied
253
+ * value with its meta half, and a leaf whose only change is plugin state
254
+ * (a mode flip) still emits.
255
+ *
256
+ * @param form The form store providing the dirty mask.
257
+ * @param from The value to filter down to its dirty parts.
258
+ *
259
+ * @returns The dirty parts of the value, or `undefined`.
260
+ */
261
+ declare function pickDirty(form: FormRef, from: Record<string, unknown>): Record<string, unknown> | undefined;
262
+ //#endregion
263
+ //#region src/methods/reset.d.ts
264
+ /**
265
+ * Configuration for resetting a form or field.
266
+ */
267
+ interface ResetConfig {
268
+ /**
269
+ * The path to the field to reset. Leave undefined to reset the entire
270
+ * form.
271
+ */
272
+ readonly path?: Path | undefined;
273
+ /**
274
+ * The new initial input to reset to. An EXPLICIT `undefined` resets the
275
+ * baseline to the empty input; an OMITTED key keeps the existing
276
+ * baseline — the two are distinguished by key presence.
277
+ */
278
+ readonly initialInput?: unknown;
279
+ /**
280
+ * Whether to keep the current input values. Defaults to `false`.
281
+ */
282
+ readonly keepInput?: boolean | undefined;
283
+ /**
284
+ * Whether to keep the touched state. Defaults to `false`.
285
+ */
286
+ readonly keepTouched?: boolean | undefined;
287
+ /**
288
+ * Whether to keep the edited state. Defaults to `false`.
289
+ */
290
+ readonly keepEdited?: boolean | undefined;
291
+ /**
292
+ * Whether to keep the error messages. Defaults to `false`.
293
+ */
294
+ readonly keepErrors?: boolean | undefined;
295
+ /**
296
+ * Whether to keep the submitted state (form reset only). Defaults to
297
+ * `false`.
298
+ */
299
+ readonly keepSubmitted?: boolean | undefined;
300
+ }
301
+ /**
302
+ * Resets a specific field or the entire form to its initial state, with
303
+ * fine-grained control over which state to preserve via the `keep*` flags.
304
+ * When `initialInput` is provided it replaces the reset baseline first.
305
+ *
306
+ * @param form The form store to reset.
307
+ * @param config The reset configuration.
308
+ */
309
+ declare function reset(form: FormRef, config?: ResetConfig): void;
310
+ //#endregion
311
+ //#region src/methods/set-entry.d.ts
312
+ /**
313
+ * Sets the entry mode of an amount-or-percent field (enter a dollar
314
+ * amount, or a percent of the percent basis). Dirties the meta half; the
315
+ * field's own value — always the resolved dollar amount — is the widget's
316
+ * to convert and write.
317
+ *
318
+ * @param form The form store containing the field.
319
+ * @param path The path to the amount-or-percent field.
320
+ * @param mode The entry mode.
321
+ */
322
+ declare function setEntryMode(form: FormRef, path: Path, mode: EntryMode): void;
323
+ /**
324
+ * Sets the percent basis of an amount-or-percent field (the root-level field key
325
+ * the percent is taken of). Dirties the meta half; keeping the resolved
326
+ * dollar amount constant against the new basis is the widget's job.
327
+ *
328
+ * @param form The form store containing the field.
329
+ * @param path The path to the amount-or-percent field.
330
+ * @param percentBasis The basis field key.
331
+ */
332
+ declare function setPercentBasis(form: FormRef, path: Path, percentBasis: string): void;
333
+ //#endregion
334
+ //#region src/methods/set-input.d.ts
335
+ /**
336
+ * Sets the input value of the field at the given path (or the entire form
337
+ * for an empty path), updating touched, edited and dirty state, and
338
+ * triggers validation when the form's validation mode requires it. Throws
339
+ * on a path not declared in the schema.
340
+ *
341
+ * @param form The form store to set input on.
342
+ * @param path The path to the field (`[]` for the whole form).
343
+ * @param input The new input value.
344
+ */
345
+ declare function setInput(form: FormRef, path: Path, input: unknown): void;
346
+ //#endregion
347
+ //#region src/methods/set-mode.d.ts
348
+ /**
349
+ * Options for `setMode`.
350
+ */
351
+ interface SetModeOptions {
352
+ /**
353
+ * The flip timestamp (ISO-8601) stamped into the meta half's
354
+ * `lastFlippedAt`. Defaults to the current time; inject for
355
+ * deterministic tests.
356
+ */
357
+ readonly now?: string | undefined;
358
+ }
359
+ /**
360
+ * Flips an estimate field between its two modes — the ONLY supported mode
361
+ * writer (a raw `mode` signal write skips value seeding and the flip
362
+ * timestamp):
363
+ *
364
+ * - `estimate` → `formula`: the current input is preserved as the meta
365
+ * half's `manualValue` and the field computes again. The derived value
366
+ * is NOT written into the input — derived values are outputs; the
367
+ * server recompute pass is their author.
368
+ * - `formula` → `estimate`: the manual value is seeded from the last
369
+ * formula result (estimate-first chronology: when you stop trusting the
370
+ * formula you start from its current value and adjust), which marks the
371
+ * value dirty like any user edit.
372
+ *
373
+ * Either flip dirties the meta half (`lastFlippedAt` stamped), so a flip
374
+ * with no other edit still produces a payload.
375
+ *
376
+ * Works at any depth: an estimate field inside an array row has its own
377
+ * envelope slot, built from the row's envelope. The throw is reserved
378
+ * for a field that genuinely has none — a non-estimate control, or a form
379
+ * without the envelopes plugin.
380
+ *
381
+ * @param form The form store containing the field.
382
+ * @param path The path to the estimate field.
383
+ * @param mode The target mode (a no-op when already current).
384
+ * @param options Flip options (e.g. an injected timestamp).
385
+ */
386
+ declare function setMode(form: FormRef, path: Path, mode: DerivationMode, options?: SetModeOptions): void;
387
+ //#endregion
388
+ //#region src/methods/set-off-form-values.d.ts
389
+ /**
390
+ * Replaces the form's off-form values (the read-only eval scope formula
391
+ * resolution falls back to). One signal write: every formula field reading
392
+ * off-form values re-resolves once — the LOS-470 `BpsBaseSync` behavior as
393
+ * a store property. `applyBaseline` performs the same
394
+ * write on reconcile, batched with the value rebase.
395
+ *
396
+ * @param form The form store.
397
+ * @param values The new off-form values.
398
+ */
399
+ declare function setOffFormValues(form: FormRef, values: Record<string, unknown>): void;
400
+ //#endregion
401
+ //#region src/methods/validate.d.ts
402
+ /**
403
+ * Validates the entire form input with the injected validator, routing each
404
+ * issue to its field's `errors` signal. Optionally focuses the first field
405
+ * with an error.
406
+ *
407
+ * @param form The form store to validate.
408
+ * @param config The validation configuration.
409
+ *
410
+ * @returns The validation result.
411
+ */
412
+ declare function validate(form: FormRef, config?: ValidateFormInputConfig): ValidationResult;
413
+ //#endregion
414
+ //#region src/core/codec/decode-record.d.ts
415
+ /**
416
+ * Options for `decodeRecord`.
417
+ */
418
+ interface DecodeRecordOptions {
419
+ /**
420
+ * Envelope wire contracts keyed by control kind — the form store's
421
+ * `pluginDriver.envelopes`, or `envelopeContracts([envelopesWire])` on
422
+ * the server. An envelope-control field reads its WHOLE envelope from
423
+ * the `data` bag (falling back to the bare column value for a field
424
+ * whose meta was never persisted); core unwraps the value half at the
425
+ * leaf, and the owning plugin re-reads the meta half from the same raw.
426
+ */
427
+ envelopes?: ReadonlyMap<string, WireContract>;
428
+ }
429
+ /**
430
+ * Decodes a nested server record into the form's `initialInput` shape,
431
+ * routing each declared root property by its `x-column` geometry:
432
+ * `x-column: true` fields read from a real record column (a top-level
433
+ * record key), everything else reads from the record's `data` JSONB bag.
434
+ *
435
+ * The schema is the allow-list — only declared property keys are read, so
436
+ * undeclared record keys (including prototype-pollution keys) never enter
437
+ * the result. Nested values pass through as-is; the store walk applies the
438
+ * allow-list recursively when the result becomes `initialInput`, and
439
+ * unwraps envelope leaves (`{ kind, value?, mode, … }`) through the
440
+ * registered wire contracts.
441
+ *
442
+ * For flat-JSONB surfaces without column routing (e.g. workflow form
443
+ * tasks), pass the bag as `{ data: bag }`.
444
+ *
445
+ * @param schema The form's JSON-Schema (object schema with properties).
446
+ * @param record The server record (`{ …columns, data? }`).
447
+ * @param options Decode options (envelope wire contracts).
448
+ *
449
+ * @returns The decoded initial input, or `undefined` for a nullish record.
450
+ */
451
+ declare function decodeRecord(schema: JsonSchema, record: Record<string, unknown> | null | undefined, options?: DecodeRecordOptions): Record<string, unknown> | undefined;
452
+ //#endregion
453
+ //#region src/core/codec/encode-dirty.d.ts
454
+ /**
455
+ * The save payload partitioned by record geometry: real table columns and
456
+ * `data` JSONB bag entries. Envelope fields (kind-discriminated union)
457
+ * always land WHOLE in `data`; an `x-column: true` envelope field also
458
+ * mirrors its value half into `columns` (a write-through scalar for SQL
459
+ * and list pages — the bag stays the source of truth).
460
+ */
461
+ interface EncodedDirty {
462
+ columns: Record<string, unknown>;
463
+ data: Record<string, unknown>;
464
+ }
465
+ /**
466
+ * Options for `encodeDirty`.
467
+ */
468
+ interface EncodeDirtyOptions {
469
+ /**
470
+ * The real table columns that exist (server-side drizzle column keys).
471
+ * When provided, an `x-column: true` key with no matching real column is
472
+ * DROPPED instead of routed to `columns` — a schema declaring a column
473
+ * that does not exist is an undeclared write path, and one bad key must
474
+ * not fail the whole save (mirrors `partitionAssetRow`).
475
+ */
476
+ knownColumns?: ReadonlySet<string>;
477
+ /**
478
+ * The plugins' static wire contracts (`[envelopesWire, derivationWire]`
479
+ * for the standard trio). This function is isomorphic — the server
480
+ * assembles the same list from the same exported descriptors, with no
481
+ * form store anywhere (D7). Without contracts every declared value
482
+ * passes through bare.
483
+ */
484
+ wire?: readonly WireContract[];
485
+ }
486
+ /**
487
+ * Builds the envelope-control lookup from a wire list.
488
+ */
489
+ declare function envelopeContracts(wire: readonly WireContract[] | undefined): ReadonlyMap<string, WireContract>;
490
+ /**
491
+ * Encodes a dirty-values object (the `pickDirty`/`getDirtyInput` result)
492
+ * into the save payload, partitioning each root key by its `x-column`
493
+ * geometry: `x-column: true` fields become column updates, everything else
494
+ * lands in the `data` bag. Undeclared keys — including prototype-pollution
495
+ * keys — are dropped: the schema is the allow-list at the write boundary
496
+ * too.
497
+ *
498
+ * Wire contracts carry each plugin's persistence policy (behavior
499
+ * relocated verbatim from LOS-461, not redesigned): `skipValue` drops a
500
+ * formula value (the server recompute is its only author), and an
501
+ * envelope contract's `encode` normalizes the outgoing envelope (an
502
+ * estimate value persists exactly when its meta pins `mode: "estimate"`).
503
+ *
504
+ * @param schema The form's JSON-Schema (object schema with properties).
505
+ * @param dirty The dirty values, or `undefined` when nothing is dirty.
506
+ * @param options Encoding options (column set, wire contracts).
507
+ *
508
+ * @returns The partitioned payload, or `undefined` when nothing survives.
509
+ */
510
+ declare function encodeDirty(schema: JsonSchema, dirty: Record<string, unknown> | null | undefined, options?: EncodeDirtyOptions): EncodedDirty | undefined;
511
+ //#endregion
512
+ //#region src/core/derivation/merge-collection-rows.d.ts
513
+ /**
514
+ * Merge a collection's canonical rows (the read model — full server rows
515
+ * with calc fields pre-evaluated, delivered via `offFormValues`) with the
516
+ * live form rows (the write model the user edits) for formula evaluation.
517
+ *
518
+ * Membership comes from the LIVE rows, so rows added or removed during the
519
+ * form session are respected. Each live row is enriched from the canonical
520
+ * row with the same `id`: live keys win (an explicit `null` means the user
521
+ * cleared the field), canonical fills everything the live row doesn't
522
+ * carry — core columns the write model never holds.
523
+ *
524
+ * One home for collection overlay (app re-exports this). The merged result
525
+ * is for evaluation only; it is never written back into form state.
526
+ */
527
+ declare function mergeCollectionRows(canonicalRows: ReadonlyArray<Record<string, unknown>>, liveRows: unknown): Array<Record<string, unknown>>;
528
+ //#endregion
529
+ //#region src/core/relation/relation-config.d.ts
530
+ /**
531
+ * The relation config a select/multiselect control may carry. Read
532
+ * straight off the schema node at render time; jsonisch's `inferControl`
533
+ * already classified the node select/multiselect, so this only decides
534
+ * WHICH picker renders and with what search filters.
535
+ *
536
+ * Core home — bagger() classifies collections with this; host widgets
537
+ * import it from the package root.
538
+ */
539
+ interface RelationConfig {
540
+ /**
541
+ * The related domain: `entity` | `contact` | `participant` | `party` |
542
+ * `asset` (from the `schema://<target>` ref or the `x-relation` target).
543
+ */
544
+ target: string;
545
+ /**
546
+ * Whether the field holds many rows. Explicit `multiple` wins over the
547
+ * node's type — legacy data has array-typed nodes that render a single
548
+ * picker (e.g. loan.assignee).
549
+ */
550
+ many: boolean;
551
+ /**
552
+ * The participant role the picker searches for (drives placeholder,
553
+ * trait filter fallback, and the add-button label).
554
+ */
555
+ role?: string | undefined;
556
+ /**
557
+ * The trait slugs filtering the search.
558
+ */
559
+ traits?: string[] | undefined;
560
+ /**
561
+ * Restricts search to entities that are members of the entity picked in
562
+ * this sibling field (e.g. closingContact within lendingBranch).
563
+ */
564
+ parent?: string | undefined;
565
+ /**
566
+ * Mock search data (docs/demo surfaces only).
567
+ */
568
+ useMockData?: boolean | undefined;
569
+ /**
570
+ * The per-row nested sub-schema (stage-configured "fields on this
571
+ * record"; the stage loader injects it into `items`).
572
+ */
573
+ items?: JsonSchema | undefined;
574
+ }
575
+ /**
576
+ * Reads a node's relation config, or `undefined` for a plain enum
577
+ * select/multiselect. Two schema forms:
578
+ * 1. Canonical — `$ref: schema://<target>` (one) or array of that ref
579
+ * (many); widget extras ride as sibling keys.
580
+ * 2. Vendor — `x-relation` namespace or flat `x-relation-target`;
581
+ * cardinality follows the node's `type` unless `multiple` overrides.
582
+ */
583
+ declare function readRelationConfig(schema: JsonSchema): RelationConfig | undefined;
584
+ /**
585
+ * Maps a relation target to the party autocomplete's kind hint. The widget
586
+ * only knows `entity` / `contact` / undefined (= search both); join-table
587
+ * targets (`participant`, `party`) stay open.
588
+ */
589
+ declare function targetToKind(target: string): "entity" | "contact" | undefined;
590
+ /**
591
+ * The sibling field a contact picker is scoped to (`memberOfEntityId`).
592
+ *
593
+ * Explicit `x-relation-parent` always wins. When it is missing — the live
594
+ * artifact schema never carried the key — a contact relation whose traits
595
+ * include exactly one sibling entity relation's role is scoped to that
596
+ * sibling (LOS-860: titleOfficer traits `["title-company"]` → titleCompany).
597
+ * Two matches is ambiguous, so no parent is invented.
598
+ */
599
+ declare function relationParentFieldName(schema: JsonSchema, path: readonly (string | number)[], relation: RelationConfig): string | undefined;
600
+ /**
601
+ * The row-identity contract for a relation target. A relation whose item
602
+ * schema declares NO properties never reaches `withRelationRowIdentity` —
603
+ * its rows are a value leaf holding the whole object, with no allow-list to
604
+ * thin them — so a host feeding such a relation from a canonical record
605
+ * must project the rows against this same set itself.
606
+ */
607
+ declare function relationRowIdentityProps(target: string): Record<string, JsonSchema>;
608
+ /**
609
+ * Returns a schema whose multi-row relation item schemas additionally
610
+ * declare the row-identity keys (stage-configured keys win on collision).
611
+ * Apply to the STORE schema only — rendering iterates the configured keys
612
+ * and skips hidden controls.
613
+ */
614
+ declare function withRelationRowIdentity(schema: JsonSchema): JsonSchema;
615
+ //#endregion
616
+ //#region src/core/dirty.d.ts
617
+ /**
618
+ * Returns whether a value is semantically empty: `undefined`, `null`, the
619
+ * empty string, or `NaN` (what a cleared number input parses to). These are
620
+ * all "no value entered" and must never make a field dirty against each
621
+ * other — the core semantic-dirty promise.
622
+ */
623
+ declare function isEmptyish(value: unknown): boolean;
624
+ /**
625
+ * Semantic, empty-aware equality between two leaf inputs: equal when both
626
+ * are semantically empty (`null` ≡ `undefined` ≡ `""` ≡ `NaN`) or deeply
627
+ * structurally equal.
628
+ */
629
+ declare function isSemanticEqual(a: unknown, b: unknown): boolean;
630
+ /**
631
+ * Semantic equality between two container presence sentinels: `true` only
632
+ * equals `true`; `null` and `undefined` (absent container) are equivalent.
633
+ */
634
+ declare function isPresenceEqual(a: ContainerInput, b: ContainerInput): boolean;
635
+ //#endregion
636
+ //#region src/plugins/derivation/resolve-scope-value.d.ts
637
+ /**
638
+ * Resolves a single scalar key through the canonical scope precedence —
639
+ * the same order the derivation plugin evaluates formula dependencies in:
640
+ * the form value wins (a formula field resolves through its derived
641
+ * signal, so the read is always fresh; an erroring formula resolves
642
+ * `undefined`, never a stale number), `offFormValues` fills what the form
643
+ * does not hold (an off-stage field still resolves from the canonical record).
644
+ *
645
+ * For widget-side scalar reads (e.g. an amount-or-percent field resolving
646
+ * its percent basis). Collection overlay semantics stay inside the
647
+ * derivation plugin — this helper is for scalars.
648
+ *
649
+ * @param internalFormStore The form store.
650
+ * @param key The root-level field key to resolve.
651
+ *
652
+ * @returns The resolved value, or `undefined`.
653
+ */
654
+ declare function resolveScopeValue(internalFormStore: InternalFormStore, key: string): unknown;
655
+ /**
656
+ * Resolves a single scalar key in the scope of the field at `path` — the
657
+ * path-aware sibling of `resolveScopeValue`, and the read a widget owned by
658
+ * a field should use:
659
+ *
660
+ * - inside an array row, the ROW's scope (live siblings in the same row →
661
+ * the canonical row from `offFormValues` matched by `id` → the parent
662
+ * root record under the form's `rootRecordAlias`), so a per-row formula's inputs are ITS
663
+ * row's values;
664
+ * - anywhere else, the document scope (`resolveScopeValue`).
665
+ *
666
+ * The same precedence the derivation graph evaluates the field's own
667
+ * formula in, so a widget can never display an input the value was not
668
+ * computed from.
669
+ *
670
+ * @param internalFormStore The form store.
671
+ * @param path The path of the field whose scope to resolve in.
672
+ * @param key The identifier to resolve.
673
+ *
674
+ * @returns The resolved value, or `undefined`.
675
+ */
676
+ declare function resolveScopeValueAt(internalFormStore: InternalFormStore, path: Path, key: string): unknown;
677
+ //#endregion
678
+ //#region src/plugins/envelopes/wire.d.ts
679
+ /** Discriminator of a persisted estimate / amount-or-percent envelope. */
680
+ type EnvelopeKind = "estimate" | "amount-or-percent";
681
+ /**
682
+ * Returns whether a raw persisted entry is an envelope: an object whose
683
+ * `kind` is `estimate` or `amount-or-percent`. Anything else — including
684
+ * the bare scalars every non-envelope field persists — is a bare value.
685
+ */
686
+ declare function isEnvelope(raw: unknown): raw is Record<string, unknown>;
687
+ /**
688
+ * Wraps an estimate field's halves into its envelope. The value key is
689
+ * OMITTED when `value` is `undefined` (formula mode ships
690
+ * `{ kind: "estimate", mode: "formula" }` and lets the server recompute
691
+ * author the value half).
692
+ */
693
+ declare function wrapEstimate(value: unknown, meta: EstimateMeta): unknown;
694
+ /**
695
+ * Wraps an amount-or-percent field's halves into its envelope. Always
696
+ * complete — an envelope is one bag key, so a partial write would clobber
697
+ * the persisted other half.
698
+ */
699
+ declare function wrapAmountOrPercent(value: unknown, meta: EntryMeta): unknown;
700
+ /**
701
+ * The envelopes plugin's STATIC wire contract — isomorphic by
702
+ * construction: the server imports this same object for save routing
703
+ * (`encodeDirty`), the recompute pass, and engine-less readers
704
+ * (changelog, list pages), with no form store anywhere (D7).
705
+ *
706
+ * Envelope shape: estimate fields persist
707
+ * `{ kind: "estimate", value?, mode, manualValue?, lastFlippedAt? }`,
708
+ * amount-or-percent fields
709
+ * `{ kind: "amount-or-percent", value, mode, basis? }`.
710
+ * Wire `mode` uses settled names (`estimate`/`formula`, `amount`/`percent`).
711
+ * Only these two controls grow the envelope; scalars stay bare.
712
+ */
713
+ declare const envelopesWire: WireContract;
714
+ //#endregion
715
+ //#region src/plugins/derivation/wire.d.ts
716
+ /**
717
+ * The derivation plugin's STATIC wire contract: a `formula` value is
718
+ * ALWAYS server-recomputed — a client payload only carries a stale echo of
719
+ * the last-rendered result, so `encodeDirty` drops it. (The estimate-pin
720
+ * policy lives on `envelopesWire.encode` — the envelope owns it.)
721
+ */
722
+ declare const derivationWire: WireContract;
723
+ //#endregion
724
+ export { type AmountOrPercentEnvelope, type ApplyBaselineConfig, type BaggerOptions, type CalcEngine, type CalcParseResult, type CheckContext, type CheckDefinition, type CheckInstanceConfig, type CheckScope, type ChecksConfig, type ComputeBagOptions, type ControlKind, DEFAULT_EMPTY_INPUT, DEFAULT_ROOT_RECORD_ALIAS, type DecodeRecordOptions, type DeepErrorEntry, type DerivationMode, type DerivedState, type EncodeDirtyOptions, type EncodedDirty, type EntryMeta, type EntryMode, type Envelope, type EnvelopeKind, type EstimateEnvelope, type EstimateMeta, type FieldErrors, type FieldKind, type Finding, type FormConfig, type FormRef, type FormValidator, type FormulaOptions, type InsertConfig, type JsonSchema, type Path, type PathSegment, type PluginsInput, type RelationConfig, type ResetConfig, type SetModeOptions, type Severity, type SeverityConfig, type SubmitHandler, UNEVALUABLE_MESSAGE_ID, type ValidateFormInputConfig, type ValidationIssue, type ValidationMode, type ValidationResult, type VisibleWhen, type VisibleWhenOp, applyBaseline, bagger, checks, collectionKeys, computeBag, createFormStore, decodeRecord, derivation, derivationWire, encodeDirty, envelopeContracts, envelopes, envelopesWire, flattenSourceRow, focus, formulaCheck, getDeepErrorEntries, getDeepErrors, getDirtyInput, getDirtyPaths, getErrors, getInput, handleSubmit, inferControl, insert, isEmptyish, isEnvelope, isPresenceEqual, isSemanticEqual, mergeCollectionRows, move, pickDirty, readRelationConfig, relationParentFieldName, relationRowIdentityProps, remove, replaceCheckInstances, reset, resolveScopeValue, resolveScopeValueAt, setEntryMode, setErrors, setInput, setMode, setOffFormValues, setPercentBasis, swap, targetToKind, validate, visibility, withRelationRowIdentity, wrapAmountOrPercent, wrapEstimate };