@object-ui/plugin-form 17.6.0 → 17.7.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.
Files changed (70) hide show
  1. package/CHANGELOG.md +4187 -0
  2. package/README.md +376 -44
  3. package/dist/DrawerForm.d.ts +30 -2
  4. package/dist/DrawerForm.d.ts.map +1 -1
  5. package/dist/EmbeddableForm.d.ts.map +1 -1
  6. package/dist/FormAnalytics.d.ts.map +1 -1
  7. package/dist/LineItemsPanel.d.ts +6 -3
  8. package/dist/LineItemsPanel.d.ts.map +1 -1
  9. package/dist/MasterDetailForm.d.ts +31 -10
  10. package/dist/MasterDetailForm.d.ts.map +1 -1
  11. package/dist/ModalForm.d.ts +48 -4
  12. package/dist/ModalForm.d.ts.map +1 -1
  13. package/dist/ObjectForm.d.ts.map +1 -1
  14. package/dist/SplitForm.d.ts +37 -2
  15. package/dist/SplitForm.d.ts.map +1 -1
  16. package/dist/TabbedForm.d.ts +65 -3
  17. package/dist/TabbedForm.d.ts.map +1 -1
  18. package/dist/WizardForm.d.ts +143 -38
  19. package/dist/WizardForm.d.ts.map +1 -1
  20. package/dist/autoLayout.d.ts +12 -3
  21. package/dist/autoLayout.d.ts.map +1 -1
  22. package/dist/closedAffordanceNotice.d.ts +14 -0
  23. package/dist/closedAffordanceNotice.d.ts.map +1 -0
  24. package/dist/customFieldsMerge.d.ts +29 -0
  25. package/dist/customFieldsMerge.d.ts.map +1 -0
  26. package/dist/deriveMasterDetail.d.ts +32 -8
  27. package/dist/deriveMasterDetail.d.ts.map +1 -1
  28. package/dist/fieldGroups.d.ts +176 -0
  29. package/dist/fieldGroups.d.ts.map +1 -1
  30. package/dist/fieldWriteGate.d.ts +116 -0
  31. package/dist/fieldWriteGate.d.ts.map +1 -0
  32. package/dist/flatFields.d.ts +11 -2
  33. package/dist/flatFields.d.ts.map +1 -1
  34. package/dist/formChrome.d.ts +55 -0
  35. package/dist/formChrome.d.ts.map +1 -0
  36. package/dist/index.d.ts +124 -26
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +3435 -2093
  39. package/dist/index.umd.cjs +1 -1
  40. package/dist/initialRecord.d.ts +72 -0
  41. package/dist/initialRecord.d.ts.map +1 -0
  42. package/dist/loadFailure.d.ts +28 -0
  43. package/dist/loadFailure.d.ts.map +1 -0
  44. package/dist/masterDetailTx.d.ts.map +1 -1
  45. package/dist/occSave.d.ts +6 -1
  46. package/dist/occSave.d.ts.map +1 -1
  47. package/dist/recordInvalidation.d.ts +33 -0
  48. package/dist/recordInvalidation.d.ts.map +1 -0
  49. package/dist/recordReadGate.d.ts +34 -0
  50. package/dist/recordReadGate.d.ts.map +1 -0
  51. package/dist/sanitize.d.ts +187 -5
  52. package/dist/sanitize.d.ts.map +1 -1
  53. package/dist/schemaDefaults.d.ts +27 -6
  54. package/dist/schemaDefaults.d.ts.map +1 -1
  55. package/dist/sectionFields.d.ts +56 -2
  56. package/dist/sectionFields.d.ts.map +1 -1
  57. package/dist/sectionGroups.d.ts +62 -0
  58. package/dist/sectionGroups.d.ts.map +1 -0
  59. package/dist/sectionPredicateDiagnostic.d.ts +38 -0
  60. package/dist/sectionPredicateDiagnostic.d.ts.map +1 -0
  61. package/dist/submitTarget.d.ts +119 -0
  62. package/dist/submitTarget.d.ts.map +1 -0
  63. package/dist/successBehavior.d.ts +44 -25
  64. package/dist/successBehavior.d.ts.map +1 -1
  65. package/dist/thankYouRedirectCountdown.d.ts +1 -1
  66. package/dist/uploadGate.d.ts +35 -0
  67. package/dist/uploadGate.d.ts.map +1 -0
  68. package/dist/writePayload.d.ts +68 -0
  69. package/dist/writePayload.d.ts.map +1 -0
  70. package/package.json +12 -11
@@ -1,40 +1,112 @@
1
1
  import { default as React } from 'react';
2
- import { DataSource } from '@object-ui/types';
3
- import { SubmitBehavior } from './successBehavior';
4
- import { FormSectionConfig } from './TabbedForm';
2
+ import { FormField, DataSource, ObjectFormSchema } from '@object-ui/types';
3
+ import { SubmitBehavior } from './successBehavior.js';
5
4
  /**
6
- * What the submitter is told when a DECLARED `navigateOnSuccess` produced no
7
- * destination — objectui#5034 point 2.
5
+ * A wizard STEP — the wizard's OWN authored group shape (objectui#6237).
8
6
  *
9
- * The write succeeded, so this rides on the success toast as a note rather than
10
- * becoming an error or a blocking panel: turning a successful write into an
11
- * error state would be a worse lie than the silence it replaces. What was
12
- * missing is one fact, and only one: the navigation the author declared did not
13
- * happen. Before this, the toast was byte-identical to the toast a form with no
14
- * `navigateOnSuccess` at all produces, so an author who mistyped the destination
15
- * — or whose record carried no usable id — saw a form that looked entirely
16
- * healthy and had silently stopped honouring a key they wrote.
7
+ * ## Why this is declared here rather than derived from the tabbed layout
17
8
  *
18
- * Maintainer ruling, 2026-08-17: "A refused declared navigation is surfaced: the
19
- * success toast carries a note that the declared navigation was not performed —
20
- * never indistinguishable from the no-key case."
9
+ * It used to be `Omit<FormSectionConfig, 'visibleWhen'>`, which subtracted the
10
+ * predicate slot from `TabbedForm`'s section type. That closed the hole for the
11
+ * ONE key it named and left the mechanism wide open: `FormSectionConfig` is the
12
+ * predicate-CARRYING type, so every key added to it lands here by default and
13
+ * the author has to remember to widen the `Omit`. The defect the 2026-08-30
14
+ * ruling closes is the SILENCE — "在共享 `FormSectionConfig` 上声明 `visibleWhen`
15
+ * 会**静默**给 WizardForm 的 step 也发一个谓词槽而那侧无实现" — and a subtractive
16
+ * derivation reproduces that silence for the next key in the same family
17
+ * (`readonlyWhen` / `requiredWhen`, both already this repo's field-level
18
+ * predicate vocabulary). Declaring the step shape independently flips the
19
+ * derivation from subtractive to additive: a key reaches a wizard step only
20
+ * because someone wrote it here, on the type whose renderer has to honour it.
21
21
  *
22
- * The note names no REASON on purpose. `resolveSuccessNavigate` answers null for
23
- * two different causes (no usable id on the written record; a destination the
24
- * same-origin guard refused) and returns no discriminant, so a reason in this
25
- * copy could only be re-derived by reimplementing that helper's internals at the
26
- * call site — where it would drift from the helper, and would additionally bake
27
- * today's acceptance rule into user-visible prose while objectui#5548 is still
28
- * open on exactly that rule. The diagnosable detail — the template the author
29
- * actually wrote — goes to `console.warn` at each call site instead.
22
+ * This is also simply the house pattern. `SplitFormSectionConfig`,
23
+ * `ModalFormSectionConfig` and `DrawerFormSectionConfig` each declare their own
24
+ * group shape, each documents `className` / `gridClassName` in ITS layout's
25
+ * terms, and each declares `visibleWhen` only because its layout honours it
26
+ * (`SplitFormSectionConfig` even carries a key — `pane` — that exists nowhere
27
+ * else). The wizard borrowing the tabbed layout's interface was the exception,
28
+ * and it cost real accuracy: a wizard author reading the shared type was told
29
+ * `name` is "used as tab value", `label` is "used as tab trigger text", and
30
+ * `className` is "Unused in the tabbed layout" — while this renderer uses all
31
+ * three, `className` at the step container (`FormSectionContainer` below).
30
32
  *
31
- * Lives here rather than in `successBehavior.ts` (the natural home, but read-only
32
- * for this card) and is imported BY `ObjectForm`, which is the dependency
33
- * direction that already exists — ObjectForm imports WizardForm, never the
34
- * reverse. Single-sourced so a wizard and a flat form cannot tell a submitter
35
- * two different things about one refusal; a test pins that they do not.
33
+ * ## ⛔ Why there is no predicate slot, and why that is not an oversight
34
+ *
35
+ * A step predicate is not a port of the tab predicate, it is a different
36
+ * contract. Steps are wizard component state keyed by section INDEX, only the
37
+ * current step is mounted (unmounted-ness is every other step's NORMAL state,
38
+ * which is why the final gate re-checks the whole declared field set), and the
39
+ * predicate would read `formData` — which merges only at step boundaries. So a
40
+ * step predicate is structurally STEP-BOUNDARY reactive where a tab's is ruled
41
+ * LIVE-RECORD reactive: one keyword, two different "when". It also needs
42
+ * machinery none of which is inherited — navigation policy for skipping hidden
43
+ * steps, the indicator, `isLastStep`, the "Step X of Y" denominator, index
44
+ * stability while hiding is live, re-selection when the CURRENT step hides, and
45
+ * a final-gate exclusion for a hidden step's required fields.
46
+ *
47
+ * Declaring the key on a type this renderer ignores would make it WRITABLE on a
48
+ * step — precisely the declared-but-unenforced shape this card family exists to
49
+ * close. Its absence means TypeScript rejects the key on a wizard step literal,
50
+ * which is where an author (or an agent authoring metadata) finds out.
51
+ * `ObjectForm` additionally reports the gap at runtime for a section predicate
52
+ * arriving on the wizard route, since untyped JSON reaches it too. Both halves
53
+ * are pinned in `__tests__/tabbedFormSectionPredicate-6237.test.tsx`, including
54
+ * a FAMILY-level pin that fails the build if any `*When` key ever appears here,
55
+ * not just the one this card was about.
56
+ *
57
+ * Since the objectstack#13622 ruling (2026-08-31), the boundary is also an
58
+ * AUTHOR-door refusal: `@objectstack/spec` refuses `visibleWhen` (and
59
+ * `collapsible`/`collapsed: true`) on a wizard step at parse, so authored
60
+ * form-view metadata carrying them never reaches this renderer at all. This
61
+ * type and the runtime report remain the guard for what the spec door cannot
62
+ * see — programmatic SDUI callers and metadata published before the
63
+ * tightening. The step-predicate FUTURE contract stays tracked in
64
+ * objectui#6237; the spec-side refusal is its single opening point.
65
+ *
66
+ * ⚠️ This changes nothing that used to work. The published surface is exactly
67
+ * the key set `WizardStepConfig` already had — the derivation changed, not the
68
+ * type — and `visibleWhen` was already a type error on a wizard step literal.
36
69
  */
37
- export declare const NAVIGATE_ON_SUCCESS_REFUSED_NOTE: string;
70
+ export interface WizardStepConfig {
71
+ /**
72
+ * Step identifier. Used as the step's test handle
73
+ * (`data-testid="wizard-step:<name>"`) and, with `label`, as what the
74
+ * indicator names; falls back to the step INDEX when absent.
75
+ */
76
+ name?: string;
77
+ /**
78
+ * Step label — the text the step indicator shows.
79
+ * Falls back to `Step <n>`, in the session locale (`wizard.stepFallback`).
80
+ */
81
+ label?: string;
82
+ /**
83
+ * Step description, rendered under the step heading.
84
+ */
85
+ description?: string;
86
+ /**
87
+ * How densely this step fills the grid (1–4). Outranked by the form view's
88
+ * own `columns` (spec `FormView.columns`), which sets the grid WIDTH.
89
+ * @default 1
90
+ */
91
+ columns?: 1 | 2 | 3 | 4;
92
+ /**
93
+ * Field names or configurations in this step.
94
+ */
95
+ fields: (string | FormField)[];
96
+ /**
97
+ * Custom CSS class for this step's container.
98
+ *
99
+ * Honoured, unlike its tabbed counterpart: a wizard mounts ONE step at a
100
+ * time inside its own `FormSectionContainer`, so the step has a container to
101
+ * carry it.
102
+ */
103
+ className?: string;
104
+ /**
105
+ * Custom CSS class for this step's field grid (overrides the column classes).
106
+ */
107
+ gridClassName?: string;
108
+ }
109
+ export { NAVIGATE_ON_SUCCESS_REFUSED_NOTE } from './formChrome.js';
38
110
  export interface WizardFormSchema {
39
111
  type: 'object-form';
40
112
  formType: 'wizard';
@@ -47,13 +119,23 @@ export interface WizardFormSchema {
47
119
  */
48
120
  mode: 'create' | 'edit' | 'view';
49
121
  /**
50
- * Record ID (for edit/view modes)
122
+ * Record ID (for edit/view modes). A string, per the one record-id rule on
123
+ * `DataSource` (objectui#9511) — `ObjectForm` builds this schema from the
124
+ * authorable `ObjectFormSchema.recordId`, which is a string, and `findOne`
125
+ * takes a string.
51
126
  */
52
- recordId?: string | number;
127
+ recordId?: string;
53
128
  /**
54
129
  * Wizard step sections
55
130
  */
56
- sections: FormSectionConfig[];
131
+ sections: WizardStepConfig[];
132
+ /**
133
+ * Inline field definitions (`object-form.customFields`). A member naming a
134
+ * field a section lists is that field's definition, as on every other
135
+ * `formType` (objectui#10254); `ObjectForm` hands the key over in its
136
+ * `{...schema}` spread.
137
+ */
138
+ customFields?: FormField[];
57
139
  /**
58
140
  * Allow navigation to any step (not just sequential).
59
141
  *
@@ -77,22 +159,26 @@ export interface WizardFormSchema {
77
159
  */
78
160
  showStepIndicator?: boolean;
79
161
  /**
80
- * Text for Next button
162
+ * Text for Next button. Rendered as authored when set; otherwise the
163
+ * session locale's `common.next`.
81
164
  * @default 'Next'
82
165
  */
83
166
  nextText?: string;
84
167
  /**
85
- * Text for Previous button
168
+ * Text for Previous button. Rendered as authored when set; otherwise the
169
+ * session locale's `wizard.back`.
86
170
  * @default 'Back'
87
171
  */
88
172
  prevText?: string;
89
173
  /**
90
- * Submit button text (shown on last step)
174
+ * Submit button text (shown on last step). Rendered as authored when set;
175
+ * otherwise the session locale's `form.create` / `form.update`.
91
176
  */
92
177
  submitText?: string;
93
178
  /**
94
179
  * Declarative success toast text shown when no `onSuccess` handler is given
95
- * (metadata pages cannot pass a function). Falls back to 'Created'/'Saved'.
180
+ * (metadata pages cannot pass a function). Falls back to the session
181
+ * locale's `form.created` / `form.saved` ('Created' / 'Saved' in English).
96
182
  * Ignored when `submitBehavior` is set.
97
183
  */
98
184
  successMessage?: string;
@@ -117,7 +203,8 @@ export interface WizardFormSchema {
117
203
  */
118
204
  showCancel?: boolean;
119
205
  /**
120
- * Cancel button text
206
+ * Cancel button text. Rendered as authored when set; otherwise the session
207
+ * locale's `common.cancel`.
121
208
  */
122
209
  cancelText?: string;
123
210
  /**
@@ -132,6 +219,24 @@ export interface WizardFormSchema {
132
219
  * Read-only mode
133
220
  */
134
221
  readOnly?: boolean;
222
+ /**
223
+ * Override persistence — the seam a host uses to own the write. Declared as
224
+ * `ObjectFormSchema['submitHandler']` rather than restated, so this variant
225
+ * and the canonical key `ObjectForm` forwards can never drift apart.
226
+ * When supplied, the form validates and hands the collected values
227
+ * to this handler INSTEAD of calling `dataSource.create` /
228
+ * `dataSource.update`; the returned record is passed on to `onSuccess`.
229
+ * In `edit` mode, for a record this form read itself, it hands over what it
230
+ * would have written: the fields that differ from that read, or the full
231
+ * sanitized payload when nothing changed (objectui#10156, objectui#10563;
232
+ * the whole rule is on `ObjectFormSchema['submitHandler']`).
233
+ *
234
+ * `MasterDetailForm` supplies it to route the parent AND its child
235
+ * collections through one atomic `batchTransaction` (#2679 / ADR-0034
236
+ * item 4). A renderer that does not read it writes the parent on its own and
237
+ * escapes that transaction — objectui#6176.
238
+ */
239
+ submitHandler?: ObjectFormSchema['submitHandler'];
135
240
  /**
136
241
  * Callbacks
137
242
  */
@@ -1 +1 @@
1
- {"version":3,"file":"WizardForm.d.ts","sourceRoot":"","sources":["../src/WizardForm.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;GAKG;AAEH,OAAO,KAAyC,MAAM,OAAO,CAAC;AAC9D,OAAO,KAAK,EAAa,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAW9D,OAAO,EAA0B,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAQhF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,gCAAgC,QAEN,CAAC;AAiBxC,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,aAAa,CAAC;IACpB,QAAQ,EAAE,QAAQ,CAAC;IAEnB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;IAEjC;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAE3B;;OAEG;IACH,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAE9B;;;;;;;;;OASG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAE5B;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;+CAG2C;IAC3C,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B;;iBAEa;IACb,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;;OAIG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;IAEhC;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAEpC;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAElC;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IAEtB;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAEtC;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,gBAAgB,CAAC;IACzB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAwsBhD,CAAC;AAEF,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"WizardForm.d.ts","sourceRoot":"","sources":["../src/WizardForm.tsx"],"names":[],"mappings":"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"}
@@ -8,7 +8,7 @@ export declare function isWideFieldType(type: string): boolean;
8
8
  */
9
9
  export declare function isAutoGeneratedFieldType(type: string): boolean;
10
10
  /**
11
- * Infer the MAX column count from the field count (#2578). This is an UPPER
11
+ * Infer the MAX column count from the field count (objectstack-ai/objectstack#2578). This is an UPPER
12
12
  * BOUND — the actual column count at render time is decided by the CSS
13
13
  * container queries in {@link CONTAINER_GRID_COLS} against the form's REAL
14
14
  * width, so a narrow drawer stays 1–2 columns while the SAME form on a wide
@@ -25,12 +25,21 @@ export declare function isAutoGeneratedFieldType(type: string): boolean;
25
25
  export declare function inferColumns(fieldCount: number): number;
26
26
  /**
27
27
  * Resolve the effective colSpan (grid cells) a field occupies, given the form's
28
- * grid width and the section's desired column count (#2578).
28
+ * grid width and the section's desired column count (objectstack-ai/objectstack#2578).
29
29
  *
30
30
  * The column count is derived per surface (mobile 1 / modal 2 / page 3-4), so
31
31
  * the robust field-width primitive is the relative `span`, NOT an absolute
32
32
  * colSpan. Precedence:
33
33
  * 1. `span: 'full'` → whole row (grid cells).
34
+ *
35
+ * ⚠️ «Whole row» is a claim about what RENDERS, and this function only returns
36
+ * a number. It is kept by the form renderer's `spanLadderFor`, which turns
37
+ * that number into one col-span class per container-query tier. Until
38
+ * `bd0995738` the renderer emitted a single class for the widest tier only,
39
+ * so this sentence was true of the return value and false on screen at every
40
+ * intermediate width. ⛔ A pin under this function cannot observe that — see
41
+ * `__tests__/spanFullTierLadder-9244.test.tsx` for the leg that can.
42
+ *
34
43
  * 2. legacy `colSpan` → honoured but CLAMPED to the grid (never overflows).
35
44
  * 3. wide widget type → whole row (textarea/markdown/… — the `span:'auto'` default).
36
45
  * 4. section density → grid / sectionColumns, so `sectionColumns` fields fill a row.
@@ -41,7 +50,7 @@ export declare function inferColumns(fieldCount: number): number;
41
50
  export declare function resolveColSpan(field: FormField, gridColumns: number, sectionColumns?: number): number;
42
51
  /**
43
52
  * Apply the resolved colSpan to each field so the form's CSS grid lays them out
44
- * at the intended density. Span-aware and clamping (#2578); wide fields still
53
+ * at the intended density. Span-aware and clamping (objectstack-ai/objectstack#2578); wide fields still
45
54
  * span the full row (the `span: 'auto'` default). `section-divider` rows are
46
55
  * left untouched (they carry their own full-row span).
47
56
  *
@@ -1 +1 @@
1
- {"version":3,"file":"autoLayout.d.ts","sourceRoot":"","sources":["../src/autoLayout.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAqElD;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAErD;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAKvD;AAOD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,SAAS,EAChB,WAAW,EAAE,MAAM,EACnB,cAAc,CAAC,EAAE,MAAM,GACtB,MAAM,CAmBR;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,SAAS,EAAE,EACnB,WAAW,EAAE,MAAM,EACnB,cAAc,CAAC,EAAE,MAAM,GACtB,SAAS,EAAE,CAab;AAmCD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,SAAS,EAAE,EACnB,YAAY,CAAC,EAAE,GAAG,GACjB,SAAS,EAAE,CAgBb;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,SAAS,EAAE,EACnB,YAAY,CAAC,EAAE,GAAG,GACjB,SAAS,EAAE,CAmBb;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,SAAS,EAAE,EACnB,YAAY,CAAC,EAAE,GAAG,GACjB,SAAS,EAAE,CAOb;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAKlE,CAAC;AAEF,wFAAwF;AACxF,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAGpF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,SAAS,EAAE,EACnB,OAAO,EAAE,MAAM,GAAG,SAAS,GAC1B;IAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAAE,CASxE;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAIvF;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,SAAS,EAAE,EACvB,YAAY,EAAE,GAAG,EACjB,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,IAAI,EAAE,MAAM,GAAG,SAAS,GACvB;IAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CA6BtD"}
1
+ {"version":3,"file":"autoLayout.d.ts","sourceRoot":"","sources":["../src/autoLayout.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAsElD;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAErD;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAKvD;AAOD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,SAAS,EAChB,WAAW,EAAE,MAAM,EACnB,cAAc,CAAC,EAAE,MAAM,GACtB,MAAM,CAmBR;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,SAAS,EAAE,EACnB,WAAW,EAAE,MAAM,EACnB,cAAc,CAAC,EAAE,MAAM,GACtB,SAAS,EAAE,CAab;AAiBD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,SAAS,EAAE,EACnB,YAAY,CAAC,EAAE,GAAG,GACjB,SAAS,EAAE,CAgBb;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,SAAS,EAAE,EACnB,YAAY,CAAC,EAAE,GAAG,GACjB,SAAS,EAAE,CAmBb;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,SAAS,EAAE,EACnB,YAAY,CAAC,EAAE,GAAG,GACjB,SAAS,EAAE,CAOb;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAKlE,CAAC;AAEF,wFAAwF;AACxF,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAGpF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,SAAS,EAAE,EACnB,OAAO,EAAE,MAAM,GAAG,SAAS,GAC1B;IAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAAE,CASxE;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAIvF;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,SAAS,EAAE,EACvB,YAAY,EAAE,GAAG,EACjB,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,IAAI,EAAE,MAAM,GAAG,SAAS,GACvB;IAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CA6BtD"}
@@ -0,0 +1,14 @@
1
+ import { default as React } from 'react';
2
+ import { ClosedFormAffordance } from './fieldWriteGate.js';
3
+ export interface ClosedAffordanceNoticeProps {
4
+ /** `closedFormAffordance`'s answer for the form; nothing renders when `undefined`. */
5
+ affordance: ClosedFormAffordance | undefined;
6
+ /** The form's object. Its label is resolved the way the console resolves it. */
7
+ objectName: string;
8
+ /** The object schema the form resolved; its `label` is the fallback label. */
9
+ objectSchema: {
10
+ label?: unknown;
11
+ } | null | undefined;
12
+ }
13
+ export declare function ClosedAffordanceNotice({ affordance, objectName, objectSchema, }: ClosedAffordanceNoticeProps): React.ReactElement | null;
14
+ //# sourceMappingURL=closedAffordanceNotice.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"closedAffordanceNotice.d.ts","sourceRoot":"","sources":["../src/closedAffordanceNotice.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAwC7D,MAAM,WAAW,2BAA2B;IAC1C,sFAAsF;IACtF,UAAU,EAAE,oBAAoB,GAAG,SAAS,CAAC;IAC7C,gFAAgF;IAChF,UAAU,EAAE,MAAM,CAAC;IACnB,8EAA8E;IAC9E,YAAY,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,GAAG,SAAS,CAAC;CACtD;AAED,wBAAgB,sBAAsB,CAAC,EACrC,UAAU,EACV,UAAU,EACV,YAAY,GACb,EAAE,2BAA2B,GAAG,KAAK,CAAC,YAAY,GAAG,IAAI,CA4BzD"}
@@ -0,0 +1,29 @@
1
+ import { FormField } from '@object-ui/types';
2
+ /**
3
+ * The member that supplies the definition of the field called `name`, or
4
+ * `undefined` when no member names it — the override direction's precedence,
5
+ * spelled once. The first member naming the field wins, and an EMPTY
6
+ * `customFields` supplies nothing.
7
+ *
8
+ * Shared by the two producers of a runtime field from a name: the flat list
9
+ * (`mergeCustomFields` below, the default arm's pool and the drawer / modal
10
+ * no-sections path) and a section body (`normalizeSectionField` in
11
+ * `sectionFields.ts`, where the member is a section entry's BASE definition).
12
+ * objectui#10254: the drawer and modal section bodies used to regenerate every
13
+ * named field from the object schema, so a member the default arm drew was
14
+ * dropped on those two arms.
15
+ */
16
+ export declare function findCustomFieldMember(customFields: readonly FormField[] | null | undefined, name: string): FormField | undefined;
17
+ /**
18
+ * Resolve the runtime field list for `names`, with `customFields` merged over
19
+ * the fields `generate` produces.
20
+ *
21
+ * @param names The field names the form draws, in render order.
22
+ * @param customFields The authored members (`schema.customFields`).
23
+ * @param generate Builds the generated field for `names[index]`, or
24
+ * returns `undefined` when the object declares no such
25
+ * field (the name is then skipped unless a member names it).
26
+ * @param normalize Applied to every member before it is drawn.
27
+ */
28
+ export declare function mergeCustomFields(names: readonly string[], customFields: readonly FormField[] | null | undefined, generate: (name: string, index: number) => FormField | undefined, normalize?: (member: FormField) => FormField): FormField[];
29
+ //# sourceMappingURL=customFieldsMerge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"customFieldsMerge.d.ts","sourceRoot":"","sources":["../src/customFieldsMerge.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,SAAS,SAAS,EAAE,GAAG,IAAI,GAAG,SAAS,EACrD,IAAI,EAAE,MAAM,GACX,SAAS,GAAG,SAAS,CAGvB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,YAAY,EAAE,SAAS,SAAS,EAAE,GAAG,IAAI,GAAG,SAAS,EACrD,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,SAAS,GAAG,SAAS,EAChE,SAAS,GAAE,CAAC,MAAM,EAAE,SAAS,KAAK,SAA8B,GAC/D,SAAS,EAAE,CAyBb"}
@@ -1,6 +1,25 @@
1
1
  import { GridColumn } from '@object-ui/fields';
2
- /** Minimal shape of an object schema as returned by `DataSource.getObjectSchema`. */
3
- export interface ObjectSchemaLike {
2
+ /**
3
+ * Minimal shape of a MASTER-DETAIL CHILD object's schema, as returned by
4
+ * `DataSource.getObjectSchema` — the `childSchema` parameter of every derive
5
+ * function below (objectui#7324).
6
+ *
7
+ * Named for the child because that is the only thing it is ever used for, and
8
+ * because `schemaDefaults.ts` holds a DIFFERENT shape under what used to be
9
+ * the same name (`FieldDefaultsSchemaLike` now). The two are not
10
+ * interchangeable: this one's field values are `any` — these functions read a
11
+ * field's `type`, `label`, `options`, `hidden`, `reference` and more — while
12
+ * the defaults one pins the four members that rule reads. Publishing both
13
+ * under one name would have put a name on the package surface that already
14
+ * meant something else two files over.
15
+ *
16
+ * NOT `@object-ui/types`' `ObjectSchemaMetadata`: that type requires `name`
17
+ * and requires a `type` on every field, so the partial schemas these
18
+ * functions are handed (and every fixture that exercises them) would stop
19
+ * compiling. This is a deliberately structural parameter type — pass the
20
+ * object document your data source serves.
21
+ */
22
+ export interface ChildObjectSchemaLike {
4
23
  name?: string;
5
24
  fields?: Record<string, any>;
6
25
  }
@@ -11,7 +30,7 @@ export declare function fieldTypeToColumnType(type: string | undefined): GridCol
11
30
  * master_detail/lookup field whose `reference` is the parent object. Prefer
12
31
  * `master_detail` over `lookup` when both exist.
13
32
  */
14
- export declare function findRelationshipField(childSchema: ObjectSchemaLike | undefined, parentObjectName: string): string | undefined;
33
+ export declare function findRelationshipField(childSchema: ChildObjectSchemaLike | undefined, parentObjectName: string): string | undefined;
15
34
  /**
16
35
  * Default-visible column budget for an auto-derived inline grid. An inline
17
36
  * line-item grid lives in a constrained width (modal / detail card), so we show
@@ -29,7 +48,7 @@ export declare const DEFAULT_MAX_INLINE_COLUMNS = 6;
29
48
  * are flagged `defaultHidden` (collapsed into the grid's column chooser, not
30
49
  * dropped). Pass `maxColumns: 0` to flag none.
31
50
  */
32
- export declare function deriveColumns(childSchema: ObjectSchemaLike | undefined, opts?: {
51
+ export declare function deriveColumns(childSchema: ChildObjectSchemaLike | undefined, opts?: {
33
52
  relationshipField?: string;
34
53
  exclude?: string[];
35
54
  maxColumns?: number;
@@ -44,15 +63,20 @@ export declare function deriveColumns(childSchema: ObjectSchemaLike | undefined,
44
63
  * schema, exactly as {@link deriveColumns} would, while preserving the author's
45
64
  * column set, order and labels. A column that already declares a `type` is left
46
65
  * untouched — the author's explicit choice always wins.
66
+ *
67
+ * A column that renders as `currency` and carries an authored `scale`, whether
68
+ * its type is declared or hydrated, is reported by
69
+ * {@link reportCurrencyColumnScale} (objectui#10783): the grid does not read
70
+ * that key.
47
71
  */
48
- export declare function hydrateColumns(columns: GridColumn[] | undefined, childSchema: ObjectSchemaLike | undefined): GridColumn[];
72
+ export declare function hydrateColumns(columns: GridColumn[] | undefined, childSchema: ChildObjectSchemaLike | undefined): GridColumn[];
49
73
  /**
50
74
  * Field names for a child's full "row form" (the per-row expand editor) — every
51
75
  * editable business field, skipping system/audit fields, the back-reference FK,
52
76
  * and computed types. Broader than {@link deriveColumns} (which only returns
53
77
  * grid-friendly types): the form has room for textarea/richtext/file/etc.
54
78
  */
55
- export declare function deriveFormFields(childSchema: ObjectSchemaLike | undefined, opts?: {
79
+ export declare function deriveFormFields(childSchema: ChildObjectSchemaLike | undefined, opts?: {
56
80
  relationshipField?: string;
57
81
  exclude?: string[];
58
82
  }): string[];
@@ -72,7 +96,7 @@ export declare const RICH_FIELD_FORM_THRESHOLD = 2;
72
96
  * ({@link RICH_FIELD_FORM_THRESHOLD}), or more than
73
97
  * {@link SMART_FORM_FIELD_THRESHOLD} editable business fields; else a `grid`.
74
98
  */
75
- export declare function resolveInlineMode(childSchema: ObjectSchemaLike | undefined, inlineEdit: boolean | InlineMode | undefined, opts?: {
99
+ export declare function resolveInlineMode(childSchema: ChildObjectSchemaLike | undefined, inlineEdit: boolean | InlineMode | undefined, opts?: {
76
100
  relationshipField?: string;
77
101
  }): InlineMode;
78
102
  export interface DerivedDetail {
@@ -95,7 +119,7 @@ export interface DerivedDetail {
95
119
  * supplies any explicit overrides (relationshipField / columns / amountField),
96
120
  * which win over the derived values.
97
121
  */
98
- export declare function deriveDetail(childObject: string, childSchema: ObjectSchemaLike | undefined, parentObjectName: string, override?: {
122
+ export declare function deriveDetail(childObject: string, childSchema: ChildObjectSchemaLike | undefined, parentObjectName: string, override?: {
99
123
  relationshipField?: string;
100
124
  columns?: GridColumn[];
101
125
  amountField?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"deriveMasterDetail.d.ts","sourceRoot":"","sources":["../src/deriveMasterDetail.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,qFAAqF;AACrF,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC9B;AAuBD,kEAAkE;AAClE,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,CAAC,MAAM,CAAC,CAqClF;AAgCD;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,gBAAgB,GAAG,SAAS,EACzC,gBAAgB,EAAE,MAAM,GACvB,MAAM,GAAG,SAAS,CAWpB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAuD5C;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,WAAW,EAAE,gBAAgB,GAAG,SAAS,EACzC,IAAI,GAAE;IAAE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO,GACjF,UAAU,EAAE,CA0Cd;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,UAAU,EAAE,GAAG,SAAS,EACjC,WAAW,EAAE,gBAAgB,GAAG,SAAS,GACxC,UAAU,EAAE,CAgCd;AAOD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,gBAAgB,GAAG,SAAS,EACzC,IAAI,GAAE;IAAE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CAAO,GAC5D,MAAM,EAAE,CAaV;AAED,+BAA+B;AAC/B,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;AAiBzC,gFAAgF;AAChF,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAE5C;;iFAEiF;AACjF,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAE3C;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,gBAAgB,GAAG,SAAS,EACzC,UAAU,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,EAC5C,IAAI,GAAE;IAAE,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAAO,GACxC,UAAU,CAaZ;AAwBD,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,wEAAwE;IACxE,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,mFAAmF;IACnF,IAAI,EAAE,UAAU,CAAC;IACjB,+EAA+E;IAC/E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;+EAC2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,gBAAgB,GAAG,SAAS,EACzC,gBAAgB,EAAE,MAAM,EACxB,QAAQ,GAAE;IAAE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,GAAG,UAAU,CAAA;CAAO,GAC7H,aAAa,CAmBf"}
1
+ {"version":3,"file":"deriveMasterDetail.d.ts","sourceRoot":"","sources":["../src/deriveMasterDetail.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,qBAAqB;IACpC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC9B;AAuBD,kEAAkE;AAClE,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,CAAC,MAAM,CAAC,CAqClF;AAgCD;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,qBAAqB,GAAG,SAAS,EAC9C,gBAAgB,EAAE,MAAM,GACvB,MAAM,GAAG,SAAS,CAWpB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAuD5C;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,WAAW,EAAE,qBAAqB,GAAG,SAAS,EAC9C,IAAI,GAAE;IAAE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO,GACjF,UAAU,EAAE,CAsDd;AAkDD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,UAAU,EAAE,GAAG,SAAS,EACjC,WAAW,EAAE,qBAAqB,GAAG,SAAS,GAC7C,UAAU,EAAE,CAqCd;AAOD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,qBAAqB,GAAG,SAAS,EAC9C,IAAI,GAAE;IAAE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CAAO,GAC5D,MAAM,EAAE,CAaV;AAED,+BAA+B;AAC/B,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;AAiBzC,gFAAgF;AAChF,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAE5C;;iFAEiF;AACjF,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAE3C;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,qBAAqB,GAAG,SAAS,EAC9C,UAAU,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,EAC5C,IAAI,GAAE;IAAE,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAAO,GACxC,UAAU,CAaZ;AAwBD,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,wEAAwE;IACxE,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,mFAAmF;IACnF,IAAI,EAAE,UAAU,CAAC;IACjB,+EAA+E;IAC/E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;+EAC2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,qBAAqB,GAAG,SAAS,EAC9C,gBAAgB,EAAE,MAAM,EACxB,QAAQ,GAAE;IAAE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,GAAG,UAAU,CAAA;CAAO,GAC7H,aAAa,CAmBf"}
@@ -19,4 +19,180 @@ import { FormField, ObjectFormSection } from '@object-ui/types';
19
19
  * into ObjectForm's existing section-render path.
20
20
  */
21
21
  export declare function deriveFieldGroupSections(fields: FormField[], fieldGroups: unknown): ObjectFormSection[] | null;
22
+ /**
23
+ * THE ONE ROW RULE (objectui#9849 step two — director ruling letter E,
24
+ * item 2): 「The divider row exists iff `title || description`; with
25
+ * `description` only it is the blurb-only row (objectui#9835's shape), on
26
+ * every arm — one rule」.
27
+ *
28
+ * Every arm asks this one function, both to decide whether a row is drawn and
29
+ * — because 「the collapse control lives on the row」 (item 3) — whether a
30
+ * collapse control has anywhere to live. It replaced a four-way gate union
31
+ * (one answer per arm) that the ruling deleted.
32
+ *
33
+ * ⚠️ The row is PRESENTATION only. Whether the group is gated by its ADR-0089
34
+ * `visibleWhen` predicate and objectui#6236 membership claim does NOT depend
35
+ * on it (item 1) — see `projectSectionDivider`.
36
+ */
37
+ export declare function sectionDrawsDividerRow(title?: string, description?: string): boolean;
38
+ /**
39
+ * The section configuration a divider row is projected FROM, already resolved
40
+ * by the arm that owns each resolution.
41
+ *
42
+ * ⚠️ `collapse` arrives RESOLVED — by `resolveSectionCollapse` below, the one
43
+ * `collapsed` / `collapsible` resolution every arm calls. It is resolved before
44
+ * this projection rather than inside it because the arm needs the same answer
45
+ * a second time: whether to take the section's fields out of the DOM.
46
+ */
47
+ export interface SectionDividerSource {
48
+ /** Section identity; spells the row's `name`. */
49
+ key: string | number;
50
+ /** The heading, already resolved through `sectionLabel` where the arm does that. */
51
+ title?: string;
52
+ /** The authored blurb (spec `FormSection.description`). */
53
+ description?: string;
54
+ /** ADR-0089 `FormSection.visibleWhen` (#6111), unevaluated. */
55
+ visibleWhen?: unknown;
56
+ /** The objectui#6236 membership claim: RESOLVED (post-FLS) member names. */
57
+ members: string[];
58
+ /** Read by one arm only — see `projectSectionDivider`. */
59
+ className?: string;
60
+ /** Resolved by `resolveSectionCollapse`, ⛔ never here. */
61
+ collapse?: {
62
+ collapsible?: boolean;
63
+ collapsed?: boolean;
64
+ onToggle?: () => void;
65
+ };
66
+ }
67
+ /**
68
+ * The loud diagnostic director ruling letter E, item 3 orders for a group that
69
+ * declares `collapsible` (or `collapsed`) but yields neither a heading nor a
70
+ * blurb: 「The collapse control lives on the row. A group that … yields neither
71
+ * title nor description has nowhere to host the control ⇒ a loud diagnostic at
72
+ * validation or render …, ⛔ never fields removed from the DOM with no control」.
73
+ *
74
+ * Emitted at RENDER, through the channel this package already uses for
75
+ * renderer-side author mistakes — a once-per-occurrence `console.warn`, the
76
+ * voice of `warnSectionMemberExcludedByFields` in `sectionFields.ts`. ⛔ It
77
+ * only warns: the resolution below keeps such a group OPEN, so its fields stay
78
+ * reachable whatever the warning's reader does.
79
+ *
80
+ * The first sentence is the ruling's own wording, verbatim; the pin that holds
81
+ * it reads it from this function, so the two cannot drift.
82
+ */
83
+ export declare function headinglessCollapseWarning(where: string): string;
84
+ /**
85
+ * Forget which sections were already reported — for pins only, so each row
86
+ * observes its own first report. The dedupe is per module instance, and this
87
+ * module is internal (the package barrel does not re-export it).
88
+ */
89
+ export declare function resetHeadinglessCollapseWarnings(): void;
90
+ /**
91
+ * Resolve a section's authored `collapsed` / `collapsible` pair into what the
92
+ * page draws: whether its row is a disclosure control, whether its fields are
93
+ * out of the DOM right now, and what toggles them.
94
+ *
95
+ * ⭐ THE ONE RESOLUTION (objectui#9849 — director ruling letter E, item 4:
96
+ * 「the three `collapsed` / `collapsible` resolutions converge to the
97
+ * declaration-based one objectui#9780 established」). Every arm calls it: the
98
+ * default arm, both `DrawerForm` pushes and — since step two, per item 1's
99
+ * 「on every arm」 — both stacked `ModalForm` pushes.
100
+ *
101
+ * The rules, each objectui#9780's (maintainer ruling 2026-09-18, letter A):
102
+ *
103
+ * - `collapsed` IMPLIES `collapsible`. "Collapsed by default" is an everyday
104
+ * intent and `collapsed: true` its most natural spelling, so that spelling
105
+ * installs the control.
106
+ * - `collapsible: false` WITH `collapsed: true` is the same contradiction and
107
+ * resolves the same way — collapsed wins, the control is present.
108
+ * - The control is read off the DECLARATION, ⛔ never off the live state:
109
+ * deriving it from the live state would delete the control the moment the
110
+ * user opened the section.
111
+ * - A section declaring neither member is untouched.
112
+ * - ⭐ A section is only ever collapsed when it is collapsible, and it is only
113
+ * collapsible when it has a divider row to carry the control — which, by
114
+ * the one row rule (`sectionDrawsDividerRow`), is exactly when it yields a
115
+ * heading or a blurb. So fields leave the DOM only while a control that
116
+ * brings them back is on the page.
117
+ * - ⭐ A section that declares the pair and yields NEITHER is rendered open
118
+ * and reported (`headinglessCollapseWarning`) — letter E item 3.
119
+ */
120
+ export declare function resolveSectionCollapse(declared: {
121
+ collapsible?: boolean;
122
+ collapsed?: boolean;
123
+ }, host: {
124
+ /** The live state the user has toggled this section to, if any. */
125
+ live: boolean | undefined;
126
+ /** The row the section yields — the one row rule decides from these two. */
127
+ title: string | undefined;
128
+ description: string | undefined;
129
+ /**
130
+ * Who is asking and about which section, for the diagnostic only — e.g.
131
+ * `ObjectForm section 2 of object 'invoice'`. Also its dedupe key.
132
+ */
133
+ where: string;
134
+ /** Record the next live state for this section. */
135
+ setCollapsed: (next: boolean) => void;
136
+ }): {
137
+ collapsible: boolean;
138
+ collapsed: boolean;
139
+ onToggle?: () => void;
140
+ };
141
+ /**
142
+ * Project one section configuration onto the `section-divider` row it draws.
143
+ *
144
+ * ⭐ THIS IS THE ONE PATH (objectui#9849, triage ruling 2026-09-18:
145
+ * 「让 section 配置到 divider 的投影只有一条路径」). Before it, six sites across
146
+ * `ObjectForm.tsx`, `ModalForm.tsx` and `DrawerForm.tsx` each rebuilt the row
147
+ * key by key, and a key one of them forgot was invisible to the author. A key
148
+ * added here is added for every arm at once, and a key dropped here is dropped
149
+ * for every arm at once, which is what makes the loss visible instead of
150
+ * silent.
151
+ *
152
+ * ⭐ AND ONE RULE FOR WHICH ROW (director ruling letter E, maintainer 「同意」).
153
+ * There is no per-arm gate any more — the enumerated four-way union this
154
+ * function used to take as a parameter was deleted by that ruling:
155
+ *
156
+ * 1. 「Group-level semantics are independent of the heading」 — the ADR-0089
157
+ * `visibleWhen` predicate and the objectui#6236 membership claim ride
158
+ * EVERY row this function returns, so a headingless group is never
159
+ * un-gated, and the claim names only the group's own resolved members, so
160
+ * its predicate never hides more than the group it names.
161
+ * 2. The VISIBLE row exists iff `title || description`
162
+ * (`sectionDrawsDividerRow`); with `description` only, it is the blurb-only
163
+ * row — no heading span, just the blurb (objectui#9835's shape).
164
+ * 3. A group with neither, that authored a predicate, still needs a carrier
165
+ * for item 1: it gets a CHROME-LESS gate row — no `label`, no
166
+ * `description`, so `SectionDivider` renders nothing — which exists only
167
+ * to carry the predicate and the claim. It is the same shape `TabbedForm`
168
+ * already emits for a degraded single-section form, spelled
169
+ * `__section_gate_` like that one. A group with neither and no predicate
170
+ * returns no row at all: nothing to draw, nothing to gate.
171
+ *
172
+ * The key set, and who owns each member:
173
+ *
174
+ * - `label` — the heading. The arm resolves i18n before handing it over.
175
+ * - `description` — the authored blurb (objectui#9779 / #9834 / #9849).
176
+ * - `visibleWhen` — ADR-0089's section predicate (#6111). The renderer
177
+ * evaluates it on this pseudo-field with the host predicate scope bound
178
+ * (#6010), so copying it here is what makes the authored predicate reach an
179
+ * evaluator at all.
180
+ * - `fields` — the objectui#6236 membership claim: RESOLVED member names, so
181
+ * the predicate gates the whole group and not just the heading.
182
+ * - `colSpan` — see `DIVIDER_COL_SPAN`.
183
+ * - `collapsible` / `collapsed` / `onToggle` — on the visible row only (the
184
+ * control lives on the row), and only when the arm hands over a resolved
185
+ * `collapse`; see `SectionDividerSource`.
186
+ * - `className` — emitted only when the arm hands one over. objectstack#13626
187
+ * ("retire the reads", maintainer ruling 2026-09-01) took this read off
188
+ * every arm but `ModalForm`'s explicit-sections push, whose residue is
189
+ * preserved here rather than retired in passing: retiring it is a second
190
+ * ruling's job, and `sectionStyleKeysRetired-13626` pins the arms that
191
+ * already dropped it.
192
+ *
193
+ * ⛔ Not read, on any arm: `gridClassName` — a per-section grid needs a
194
+ * per-section form, which the single-form structure these arms share does not
195
+ * have.
196
+ */
197
+ export declare function projectSectionDivider(source: SectionDividerSource): FormField[];
22
198
  //# sourceMappingURL=fieldGroups.d.ts.map