@object-ui/plugin-form 17.6.0 → 18.0.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 (72) hide show
  1. package/CHANGELOG.md +4991 -0
  2. package/README.md +522 -80
  3. package/dist/DrawerForm.d.ts +42 -3
  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 +79 -38
  10. package/dist/MasterDetailForm.d.ts.map +1 -1
  11. package/dist/ModalForm.d.ts +60 -5
  12. package/dist/ModalForm.d.ts.map +1 -1
  13. package/dist/ObjectForm.d.ts.map +1 -1
  14. package/dist/SplitForm.d.ts +49 -3
  15. package/dist/SplitForm.d.ts.map +1 -1
  16. package/dist/TabbedForm.d.ts +75 -5
  17. package/dist/TabbedForm.d.ts.map +1 -1
  18. package/dist/WizardForm.d.ts +145 -38
  19. package/dist/WizardForm.d.ts.map +1 -1
  20. package/dist/autoLayout.d.ts +113 -8
  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 +82 -29
  27. package/dist/deriveMasterDetail.d.ts.map +1 -1
  28. package/dist/fieldGroups.d.ts +189 -0
  29. package/dist/fieldGroups.d.ts.map +1 -1
  30. package/dist/fieldWriteGate.d.ts +136 -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 +149 -26
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +3984 -2332
  39. package/dist/index.umd.cjs +1 -1
  40. package/dist/initialFieldFocus.d.ts +23 -0
  41. package/dist/initialFieldFocus.d.ts.map +1 -0
  42. package/dist/initialRecord.d.ts +72 -0
  43. package/dist/initialRecord.d.ts.map +1 -0
  44. package/dist/loadFailure.d.ts +28 -0
  45. package/dist/loadFailure.d.ts.map +1 -0
  46. package/dist/masterDetailTx.d.ts.map +1 -1
  47. package/dist/occSave.d.ts +6 -1
  48. package/dist/occSave.d.ts.map +1 -1
  49. package/dist/recordInvalidation.d.ts +33 -0
  50. package/dist/recordInvalidation.d.ts.map +1 -0
  51. package/dist/recordReadGate.d.ts +34 -0
  52. package/dist/recordReadGate.d.ts.map +1 -0
  53. package/dist/sanitize.d.ts +272 -5
  54. package/dist/sanitize.d.ts.map +1 -1
  55. package/dist/schemaDefaults.d.ts +104 -9
  56. package/dist/schemaDefaults.d.ts.map +1 -1
  57. package/dist/sectionFields.d.ts +67 -2
  58. package/dist/sectionFields.d.ts.map +1 -1
  59. package/dist/sectionGroups.d.ts +62 -0
  60. package/dist/sectionGroups.d.ts.map +1 -0
  61. package/dist/sectionPredicateDiagnostic.d.ts +38 -0
  62. package/dist/sectionPredicateDiagnostic.d.ts.map +1 -0
  63. package/dist/submitTarget.d.ts +136 -0
  64. package/dist/submitTarget.d.ts.map +1 -0
  65. package/dist/successBehavior.d.ts +44 -25
  66. package/dist/successBehavior.d.ts.map +1 -1
  67. package/dist/thankYouRedirectCountdown.d.ts +1 -1
  68. package/dist/uploadGate.d.ts +35 -0
  69. package/dist/uploadGate.d.ts.map +1 -0
  70. package/dist/writePayload.d.ts +87 -0
  71. package/dist/writePayload.d.ts.map +1 -0
  72. package/package.json +13 -12
@@ -1,40 +1,114 @@
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, ObjectFormSection } 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
+ * The same three entry shapes as `ObjectFormSection.fields`, by reference:
94
+ * a field name, the form view's `{ field, … }` entry, or an inline
95
+ * `FormField` (objectui#11615).
96
+ */
97
+ fields: NonNullable<ObjectFormSection['fields']>;
98
+ /**
99
+ * Custom CSS class for this step's container.
100
+ *
101
+ * Honoured, unlike its tabbed counterpart: a wizard mounts ONE step at a
102
+ * time inside its own `FormSectionContainer`, so the step has a container to
103
+ * carry it.
104
+ */
105
+ className?: string;
106
+ /**
107
+ * Custom CSS class for this step's field grid (overrides the column classes).
108
+ */
109
+ gridClassName?: string;
110
+ }
111
+ export { NAVIGATE_ON_SUCCESS_REFUSED_NOTE } from './formChrome.js';
38
112
  export interface WizardFormSchema {
39
113
  type: 'object-form';
40
114
  formType: 'wizard';
@@ -47,13 +121,23 @@ export interface WizardFormSchema {
47
121
  */
48
122
  mode: 'create' | 'edit' | 'view';
49
123
  /**
50
- * Record ID (for edit/view modes)
124
+ * Record ID (for edit/view modes). A string, per the one record-id rule on
125
+ * `DataSource` (objectui#9511) — `ObjectForm` builds this schema from the
126
+ * authorable `ObjectFormSchema.recordId`, which is a string, and `findOne`
127
+ * takes a string.
51
128
  */
52
- recordId?: string | number;
129
+ recordId?: string;
53
130
  /**
54
131
  * Wizard step sections
55
132
  */
56
- sections: FormSectionConfig[];
133
+ sections: WizardStepConfig[];
134
+ /**
135
+ * Inline field definitions (`object-form.customFields`). A member naming a
136
+ * field a section lists is that field's definition, as on every other
137
+ * `formType` (objectui#10254); `ObjectForm` hands the key over in its
138
+ * `{...schema}` spread.
139
+ */
140
+ customFields?: FormField[];
57
141
  /**
58
142
  * Allow navigation to any step (not just sequential).
59
143
  *
@@ -77,22 +161,26 @@ export interface WizardFormSchema {
77
161
  */
78
162
  showStepIndicator?: boolean;
79
163
  /**
80
- * Text for Next button
164
+ * Text for Next button. Rendered as authored when set; otherwise the
165
+ * session locale's `common.next`.
81
166
  * @default 'Next'
82
167
  */
83
168
  nextText?: string;
84
169
  /**
85
- * Text for Previous button
170
+ * Text for Previous button. Rendered as authored when set; otherwise the
171
+ * session locale's `wizard.back`.
86
172
  * @default 'Back'
87
173
  */
88
174
  prevText?: string;
89
175
  /**
90
- * Submit button text (shown on last step)
176
+ * Submit button text (shown on last step). Rendered as authored when set;
177
+ * otherwise the session locale's `form.create` / `form.update`.
91
178
  */
92
179
  submitText?: string;
93
180
  /**
94
181
  * Declarative success toast text shown when no `onSuccess` handler is given
95
- * (metadata pages cannot pass a function). Falls back to 'Created'/'Saved'.
182
+ * (metadata pages cannot pass a function). Falls back to the session
183
+ * locale's `form.created` / `form.saved` ('Created' / 'Saved' in English).
96
184
  * Ignored when `submitBehavior` is set.
97
185
  */
98
186
  successMessage?: string;
@@ -117,7 +205,8 @@ export interface WizardFormSchema {
117
205
  */
118
206
  showCancel?: boolean;
119
207
  /**
120
- * Cancel button text
208
+ * Cancel button text. Rendered as authored when set; otherwise the session
209
+ * locale's `common.cancel`.
121
210
  */
122
211
  cancelText?: string;
123
212
  /**
@@ -132,6 +221,24 @@ export interface WizardFormSchema {
132
221
  * Read-only mode
133
222
  */
134
223
  readOnly?: boolean;
224
+ /**
225
+ * Override persistence — the seam a host uses to own the write. Declared as
226
+ * `ObjectFormSchema['submitHandler']` rather than restated, so this variant
227
+ * and the canonical key `ObjectForm` forwards can never drift apart.
228
+ * When supplied, the form validates and hands the collected values
229
+ * to this handler INSTEAD of calling `dataSource.create` /
230
+ * `dataSource.update`; the returned record is passed on to `onSuccess`.
231
+ * In `edit` mode, for a record this form read itself, it hands over what it
232
+ * would have written: the fields that differ from that read, or the full
233
+ * sanitized payload when nothing changed (objectui#10156, objectui#10563;
234
+ * the whole rule is on `ObjectFormSchema['submitHandler']`).
235
+ *
236
+ * `MasterDetailForm` supplies it to route the parent AND its child
237
+ * collections through one atomic `batchTransaction` (#2679 / ADR-0034
238
+ * item 4). A renderer that does not read it writes the parent on its own and
239
+ * escapes that transaction — objectui#6176.
240
+ */
241
+ submitHandler?: ObjectFormSchema['submitHandler'];
135
242
  /**
136
243
  * Callbacks
137
244
  */
@@ -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
  *
@@ -94,6 +103,96 @@ export declare function filterAutoGeneratedFields(fields: FormField[], objectSch
94
103
  export declare const CONTAINER_GRID_COLS: Record<number, string | undefined>;
95
104
  /** Clamp an arbitrary column count into the 1–4 keys of {@link CONTAINER_GRID_COLS}. */
96
105
  export declare function containerGridColsFor(columns: number | undefined): string | undefined;
106
+ /**
107
+ * The field grid of a sectioned form whose sections do not all fit one grid
108
+ * (objectui#12548): one column below `@md`, twelve tracks from `@md` up.
109
+ *
110
+ * Twelve is the least count every authored section density divides
111
+ * (`@objectstack/spec` `FormSectionSchema.columns` is `1 | 2 | 3 | 4`), so in
112
+ * this grid a field's colSpan is in TWELFTHS of the row: 12 / 6 / 4 / 3 for a
113
+ * 1 / 2 / 3 / 4-column section. The form renderer draws a twelfths colSpan as
114
+ * one class per tier, keeping each density's step ladder from
115
+ * {@link CONTAINER_GRID_COLS} (at most two per row at `@md`, three at `@2xl`,
116
+ * four at `@4xl`); its table is `TWELVE_TRACK_SPAN_CLASS` in
117
+ * `@object-ui/components`' form renderer.
118
+ *
119
+ * ⛔ A literal, never assembled: Tailwind's scanner reads source text.
120
+ */
121
+ export declare const TWELVE_TRACK_GRID_COLS = "grid gap-4 grid-cols-1 @md:grid-cols-12";
122
+ /**
123
+ * How many fields per row a section draws where neither it nor its form
124
+ * declares `columns` (objectui#12592): two from the container's `@md` tier up,
125
+ * one below it, so a phone keeps its single column.
126
+ *
127
+ * An undeclared density is the renderer's choice by available width, and a
128
+ * declared one — `1` included — is drawn as written (the section-`columns`
129
+ * fork on objectui#12521, ruled 6204264665; `@objectstack/spec` dropped
130
+ * `FormSectionSchema.columns`' `default(1)` in objectstack-ai/objectstack#23740,
131
+ * so an undeclared section reaches every host). The container query makes
132
+ * "available width" literal: the same section draws one per row in a narrow
133
+ * drawer or on a phone, and two in a dialog or a page.
134
+ */
135
+ export declare const UNDECLARED_SECTION_COLUMNS = 2;
136
+ /**
137
+ * One section's fields per row: its declared `columns` as written, else the
138
+ * form's declared `columns` (what an undeclared section always filled), else
139
+ * {@link UNDECLARED_SECTION_COLUMNS}.
140
+ */
141
+ export declare function sectionColumnsFor(sectionColumns: unknown, formColumns: unknown): number;
142
+ /**
143
+ * The ONE grid width of a sectioned form: the form's declared `columns`, else
144
+ * the widest section's {@link sectionColumnsFor}.
145
+ *
146
+ * @param formColumns The form's DECLARED `columns` (`undefined` when none).
147
+ * @param sectionColumns The DECLARED `columns` of every section the form draws.
148
+ */
149
+ export declare function sectionedFormColumns(formColumns: unknown, sectionColumns: ReadonlyArray<unknown>): 1 | 2 | 3 | 4;
150
+ /** The field grid a sectioned host draws, and how it lays out one section's fields on it. */
151
+ export interface SectionedGridLayout {
152
+ /** The form's grid width in the 1–4 vocabulary (`FormSchema.columns`). */
153
+ columns: 1 | 2 | 3 | 4;
154
+ /** The field container's grid classes; `undefined` for a one-column form. */
155
+ fieldContainerClass: string | undefined;
156
+ /** Lay one section's fields out at that section's DECLARED `columns` (`undefined` when none). */
157
+ layOut: (fields: FormField[], sectionColumns?: unknown) => FormField[];
158
+ }
159
+ /**
160
+ * The ONE layout rule of a sectioned form — `ModalForm`, `ObjectForm`,
161
+ * `SplitForm`, `TabbedForm` and `WizardForm` all call it (objectui#12548).
162
+ *
163
+ * Every section shares the form's single field grid (one form, one
164
+ * react-hook-form instance — #2153/#2959), and every authored section must
165
+ * still draw its OWN `columns` count per row: `FormSectionSchema.columns` is a
166
+ * per-section count, whatever the other sections declare.
167
+ *
168
+ * - When every section's count is 1 or the grid's own width, the grid is
169
+ * {@link CONTAINER_GRID_COLS}' and the spans are {@link applyAutoColSpan}'s,
170
+ * byte for byte what a single-density form always drew: on that grid a
171
+ * one-column section's fields take the row and a full-width section's take
172
+ * one cell each, which is exactly their count.
173
+ * - Otherwise a section's count does not fit that grid at some tier — a
174
+ * `columns: 2` section on a 3-wide grid spanned 2 of 3 cells, ONE field per
175
+ * row, and a `columns: 3` section on a 4-wide grid spanned 1 cell, FOUR per
176
+ * row (`Math.round(grid / sectionColumns)`). The grid becomes
177
+ * {@link TWELVE_TRACK_GRID_COLS} and each field spans twelfths of the row:
178
+ * 1. `span: 'full'`, or a wide widget type → 12, the whole row;
179
+ * 2. an authored `colSpan` → that many of its SECTION's columns, clamped
180
+ * to them (it keeps winning over the density);
181
+ * 3. otherwise → 12 / the section's columns.
182
+ *
183
+ * A section's count is clamped to the grid width, as it always was: the form
184
+ * view's own `columns` outranks how a section fills it.
185
+ *
186
+ * Every host hands it what the AUTHOR wrote, never a count it resolved itself
187
+ * (objectui#12592): an undeclared section and an undeclared form resolve here,
188
+ * through {@link sectionColumnsFor} and {@link sectionedFormColumns}, so a
189
+ * section that declares nothing draws {@link UNDECLARED_SECTION_COLUMNS} per
190
+ * row in the dialog and on every page host alike.
191
+ *
192
+ * @param formColumns The form's DECLARED `columns` (`undefined` when none).
193
+ * @param sectionColumns The DECLARED `columns` of every section the form draws.
194
+ */
195
+ export declare function sectionedGridLayout(formColumns: unknown, sectionColumns: ReadonlyArray<unknown>): SectionedGridLayout;
97
196
  /**
98
197
  * Build the layout-related props for a *section's* inner form (`SchemaRenderer`).
99
198
  *
@@ -114,13 +213,19 @@ export declare function sectionFormLayout(fields: FormField[], columns: number |
114
213
  fieldContainerClass?: string;
115
214
  };
116
215
  /**
117
- * Infer an appropriate modal size based on the number of layout columns.
118
- * Used to auto-upgrade the modal width when auto-layout detects multi-column forms.
216
+ * Infer the modal size for a dialog whose author declared none, from the
217
+ * number of layout columns it will show.
119
218
  *
120
219
  * Mapping:
121
- * - 1 column → 'default' (max-w-lg)
122
- * - 2 columns → 'xl' (max-w-5xl)
123
- * - 3+ columns → 'full' (max-w-[95vw])
220
+ * - 0–1 column → 'lg' (max-w-2xl)
221
+ * - 2+ columns → 'xl' (max-w-5xl)
222
+ *
223
+ * ⛔ Never 'full' (objectui#12521): a derived dialog is bounded, and its width
224
+ * follows its content (the objectui#12080 ruling). 'full' (95vw) stays
225
+ * available to an author who declares `modalSize: 'full'`. The bound changes
226
+ * no grid class an authored layout carries: the field grid's tiers are
227
+ * container queries, so an authored section draws as many of its columns as
228
+ * the bounded dialog's width admits.
124
229
  */
125
230
  export declare function inferModalSize(columns: number): 'sm' | 'default' | 'lg' | 'xl' | 'full';
126
231
  /**
@@ -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;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,sBAAsB,4CAA4C,CAAC;AAEhF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAO5C;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,cAAc,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,GAAG,MAAM,CAEvF;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,OAAO,EACpB,cAAc,EAAE,aAAa,CAAC,OAAO,CAAC,GACrC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAKf;AAED,6FAA6F;AAC7F,MAAM,WAAW,mBAAmB;IAClC,0EAA0E;IAC1E,OAAO,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACvB,6EAA6E;IAC7E,mBAAmB,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,iGAAiG;IACjG,MAAM,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,cAAc,CAAC,EAAE,OAAO,KAAK,SAAS,EAAE,CAAC;CACxE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,OAAO,EACpB,cAAc,EAAE,aAAa,CAAC,OAAO,CAAC,GACrC,mBAAmB,CA6BrB;AAcD;;;;;;;;;;;;;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;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAGvF;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
- import { GridColumn } from '@object-ui/fields';
2
- /** Minimal shape of an object schema as returned by `DataSource.getObjectSchema`. */
3
- export interface ObjectSchemaLike {
1
+ import { BooleanValueLabel, GridColumn } from '@object-ui/fields';
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,25 +30,31 @@ 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
- * Default-visible column budget for an auto-derived inline grid. An inline
17
- * line-item grid lives in a constrained width (modal / detail card), so we show
18
- * a focused set by default and mark the rest `defaultHidden` — they are NOT
19
- * dropped: the grid's column chooser reveals them on demand (the mainstream
20
- * "personalize columns" pattern; cf. Odoo `optional` / Salesforce column
21
- * personalization). Required columns are always visible. Authors can override
22
- * with explicit `columns` / `inlineColumns` (no curation), or `maxColumns: 0`.
35
+ * Derive editable grid columns from a child object's fields — the grid an
36
+ * inline master-detail collection draws when its author listed no columns.
37
+ *
38
+ * WHICH columns, in what order, and which are `defaultHidden`, is
39
+ * `@objectstack/spec`'s rule, `deriveInlineGridColumns` (objectui#11345): it
40
+ * skips system / audit fields, sort-position fields, fields flagged `system`,
41
+ * `readonly` or `hidden`, non-editable types, the back-reference FK to the
42
+ * parent and any `exclude`d name, and keeps every other field. Past the
43
+ * visible budget ({@link DEFAULT_MAX_INLINE_GRID_COLUMNS}, the spec's) the
44
+ * overflow is flagged `defaultHidden` — collapsed into the grid's column
45
+ * chooser, never dropped; required columns always stay visible. Pass
46
+ * `maxColumns: 0` to flag none. The rule lives in the spec so that an
47
+ * author-time tool (objectstack's `field-no-consumers` lint) credits exactly
48
+ * the columns this grid draws, and the two cannot disagree.
49
+ *
50
+ * What each column carries — label, cell type, options, lookup target,
51
+ * conditional rules, computed expression — is built here, from the child
52
+ * field, by {@link deriveColumn}. `booleanLabel` is required: it draws the
53
+ * option labels of a `boolean` / `toggle` child field in the session language
54
+ * (see `optionsFor`, objectui#12924).
23
55
  */
24
- export declare const DEFAULT_MAX_INLINE_COLUMNS = 6;
25
- /**
26
- * Derive editable grid columns from a child object's fields, skipping system /
27
- * audit fields, non-editable types, and the back-reference FK to the parent.
28
- * Every editable column is returned; those beyond {@link DEFAULT_MAX_INLINE_COLUMNS}
29
- * are flagged `defaultHidden` (collapsed into the grid's column chooser, not
30
- * dropped). Pass `maxColumns: 0` to flag none.
31
- */
32
- export declare function deriveColumns(childSchema: ObjectSchemaLike | undefined, opts?: {
56
+ export declare function deriveColumns(childSchema: ChildObjectSchemaLike | undefined, opts: {
57
+ booleanLabel: BooleanValueLabel;
33
58
  relationshipField?: string;
34
59
  exclude?: string[];
35
60
  maxColumns?: number;
@@ -44,15 +69,40 @@ export declare function deriveColumns(childSchema: ObjectSchemaLike | undefined,
44
69
  * schema, exactly as {@link deriveColumns} would, while preserving the author's
45
70
  * column set, order and labels. A column that already declares a `type` is left
46
71
  * untouched — the author's explicit choice always wins.
72
+ *
73
+ * A column that renders as `currency` and carries an authored `scale`, whether
74
+ * its type is declared or hydrated, is reported by
75
+ * {@link reportCurrencyColumnScale} (objectui#10783): the grid does not read
76
+ * that key.
77
+ *
78
+ * `booleanLabel` is required for the same reason as on {@link deriveColumns}:
79
+ * an untyped column over a `boolean` / `toggle` child field hydrates into a
80
+ * select whose two option labels it draws (objectui#12924).
47
81
  */
48
- export declare function hydrateColumns(columns: GridColumn[] | undefined, childSchema: ObjectSchemaLike | undefined): GridColumn[];
82
+ export declare function hydrateColumns(columns: GridColumn[] | undefined, childSchema: ChildObjectSchemaLike | undefined, opts: {
83
+ booleanLabel: BooleanValueLabel;
84
+ }): GridColumn[];
49
85
  /**
50
- * Field names for a child's full "row form" (the per-row expand editor) — every
51
- * editable business field, skipping system/audit fields, the back-reference FK,
52
- * and computed types. Broader than {@link deriveColumns} (which only returns
53
- * grid-friendly types): the form has room for textarea/richtext/file/etc.
86
+ * Field names for a child's full "row form" (the per-row expand editor) — the
87
+ * form an inline master-detail collection opens when its author listed no
88
+ * `formFields`.
89
+ *
90
+ * WHICH fields, in what order, is `@objectstack/spec`'s rule,
91
+ * `deriveInlineRowFormFields` (objectui#11428), the row-form twin of the
92
+ * `deriveInlineGridColumns` rule {@link deriveColumns} reads: it skips system /
93
+ * audit fields, sort-position fields, fields flagged `system` or `hidden`, the
94
+ * computed types, the back-reference FK to the parent and any `exclude`d name,
95
+ * and keeps every other field in the child's field order. So it is broader than
96
+ * the grid: `readonly` fields and the rich types a grid cell omits (textarea,
97
+ * richtext, json, file, …) stay, since the form has room for them. The rule
98
+ * lives in the spec so that an author-time tool (objectstack's
99
+ * `field-no-consumers` lint) credits exactly the fields this form draws.
100
+ *
101
+ * WHETHER a row offers the form at all is the spec's `isInlineRowFormOffered`,
102
+ * which `MasterDetailForm` asks. How each named field renders is the form's own
103
+ * per-field builder, over these names.
54
104
  */
55
- export declare function deriveFormFields(childSchema: ObjectSchemaLike | undefined, opts?: {
105
+ export declare function deriveFormFields(childSchema: ChildObjectSchemaLike | undefined, opts?: {
56
106
  relationshipField?: string;
57
107
  exclude?: string[];
58
108
  }): string[];
@@ -72,7 +122,7 @@ export declare const RICH_FIELD_FORM_THRESHOLD = 2;
72
122
  * ({@link RICH_FIELD_FORM_THRESHOLD}), or more than
73
123
  * {@link SMART_FORM_FIELD_THRESHOLD} editable business fields; else a `grid`.
74
124
  */
75
- export declare function resolveInlineMode(childSchema: ObjectSchemaLike | undefined, inlineEdit: boolean | InlineMode | undefined, opts?: {
125
+ export declare function resolveInlineMode(childSchema: ChildObjectSchemaLike | undefined, inlineEdit: boolean | InlineMode | undefined, opts?: {
76
126
  relationshipField?: string;
77
127
  }): InlineMode;
78
128
  export interface DerivedDetail {
@@ -93,9 +143,12 @@ export interface DerivedDetail {
93
143
  * Resolve a child collection's full config (FK + columns) from its object
94
144
  * schema. Throws when no relationship to the parent can be found. The caller
95
145
  * supplies any explicit overrides (relationshipField / columns / amountField),
96
- * which win over the derived values.
146
+ * which win over the derived values, and the required `booleanLabel`, which
147
+ * is not an override: it draws a `boolean` / `toggle` column's two option
148
+ * labels in the session language (objectui#12924, see {@link deriveColumns}).
97
149
  */
98
- export declare function deriveDetail(childObject: string, childSchema: ObjectSchemaLike | undefined, parentObjectName: string, override?: {
150
+ export declare function deriveDetail(childObject: string, childSchema: ChildObjectSchemaLike | undefined, parentObjectName: string, override: {
151
+ booleanLabel: BooleanValueLabel;
99
152
  relationshipField?: string;
100
153
  columns?: GridColumn[];
101
154
  amountField?: string;