Skip to content

Commit e9ff53c

Browse files
committed
chore(spec): re-derive the merged dropped-refinements ledger and component reference
The merge took main's ledger side whole (228 schemas / 731 sites, #23098's 18 emptyState.link.url sites among them). build-schemas on the merged tree then printed this branch's 21 sites as undeclared or moved: 4 new entries and 17 sites in 13 existing entries. They are applied exactly as printed, and the header totals now match the body: 232 schemas / 752 sites. gen:docs regenerates ui/component.mdx from the merged tree. Claude-Session: https://claude.ai/code/session_019G5ZnRrTMiwcHG6iZM19zf Co-authored-by: Claude <noreply@anthropic.com>
1 parent e6d8238 commit e9ff53c

2 files changed

Lines changed: 42 additions & 4 deletions

File tree

‎content/docs/references/ui/component.mdx‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -793,7 +793,7 @@ Sort field and direction pair
793793
| **label** | `string \| Record<string, string>` | optional | Grid label — used as the table caption and export file title |
794794
| **title** | `string \| Record<string, string>` | optional | Fallback for `label` (the renderer reads `label \|\| title`) |
795795
| **description** | `string \| Record<string, string>` | optional | One line of help text drawn above the grid's rows — a string, or an inline locale map resolved against the display locale |
796-
| **emptyState** | `{ title?: string \| Record<string, string>; message?: string \| Record<string, string>; icon?: string }` | optional | What the grid draws instead of an empty table: `{ title, message, icon }` — the list view's own empty-state shape |
796+
| **emptyState** | `{ title?: string \| Record<string, string>; message?: string \| Record<string, string>; icon?: string; link?: object }` | optional | What the grid draws instead of an empty table: `{ title, message, icon }` — the list view's own empty-state shape |
797797
| **columns** | `string[] \| { field: string; label?: string \| Record<string, string>; width?: number; align?: Enum<'left' \| 'center' \| 'right'>; … }[]` | optional | Columns — all field-name strings, or all column entries `{ field, label?, width?, align?, hidden?, sortable?, … }`, the same union a list view's `columns` declares. One spelling per list: an array mixing strings and column objects is refused |
798798
| **fields** | `string[]` | optional | Field-name fallback the grid reads when `columns` is absent — bare field names (`['name', 'amount']`); write column decoration such as `label` or `width` on `columns` |
799799
| **filter** | `{ field: string; operator: Enum<'equals' \| 'not_equals' \| 'contains' \| 'not_contains' \| 'icontains' \| …>; value?: string \| number \| boolean \| null \| (string \| number)[] }[]` | optional | Base query filter — the ViewFilterRule array form `[{ field, operator, value }, ...]`, the one filter orthography every `filter` door in this map shares; lowered to the wire `$filter`. THE key, singular — not the plural misspelling. The MongoDB-style record form is refused — see migration `element-data-source-and-object-block-filter-rule-array` |
@@ -837,6 +837,7 @@ Sort field and direction pair
837837
| **title** | `string \| Record<string, string>` | optional | Heading of the empty state |
838838
| **message** | `string \| Record<string, string>` | optional | Line of text below the heading |
839839
| **icon** | `string` | optional | Icon name drawn above the heading; a name that resolves to no icon draws the default empty-state glyph |
840+
| **link** | `{ label: string \| Record<string, string>; url: string }` | optional | [PLANNED — not yet rendered] The one next step an empty list names: a link the user follows, `{ label, url }` — for example to the how-to page that explains what belongs here when nobody can add a row. It opens a page or an address and runs no action. The console's empty-state renderers are its planned readers; until they ship, the link parses and is not drawn. |
840841

841842
### Nested Shape: `ObjectGridProps.columns[number]`
842843

@@ -1522,7 +1523,7 @@ View filter rule
15221523
| **subtitle** | `string \| Record<string, string>` | optional | Page subtitle |
15231524
| **icon** | `never` | optional | [REMOVED] `page:header` property `icon` was removed in @objectstack/spec 17.0.0 (ADR-0087 D2) — no renderer ever read it: objectui resolves `icon` only per header action (`action.icon`), never off the header's own props bag, and the component registry never published it as an input, so an authored value was accepted and dropped. Delete the key. The header's own identity is drawn by the record chrome (`recordChrome`, on by default) and each action carries its own `icon`. Run `os migrate meta --from 16` to list the mechanical edits for existing sources; `--write` applies the ones it can prove, and you apply the rest by hand. |
15241525
| **breadcrumb** | `never` | optional | [REMOVED] `page:header` property `breadcrumb` was removed in @objectstack/spec 17 (ADR-0087 D2) — no renderer ever drew a trail for it: objectui drew an empty slot and nothing filled it, and the navigation trail is drawn once, by the app shell's header. Delete the key, whether it was `true` or `false`; the shell's trail is unchanged. Run `os migrate meta --from 17` to list the mechanical edits for existing sources; `--write` applies the ones it can prove, and you apply the rest by hand. |
1525-
| **actions** | `string[]` | optional | Action IDs to show in header |
1526+
| **actions** | `string[]` | optional | Action IDs the header draws, resolved against the actions declared on the page's object. An authored list is the whole set: an action that declares `record_header` (or `record_more`) in its `locations` but is not named here is not drawn, and omitting the key draws none of the object's actions. A named action that declares neither location renders nowhere. The host's own Edit / Share / Delete chrome is separate from this list. |
15261527
| **recordChrome** | `boolean` | optional (default: `true`) | Render the record chrome — the title as a record chip with its follow star and copy-id button. Set false on a non-record page (dashboard, landing) to fall back to the bare heading layout. |
15271528
| **showStar** | `boolean` | optional (default: `true`) | Show the follow (favourite) star beside the record title. Part of the record chrome — no effect when `recordChrome` is false. |
15281529
| **showCopyId** | `boolean` | optional (default: `true`) | Show the copy-record-id button beside the record title. Part of the record chrome — no effect when `recordChrome` is false. |

‎packages/spec/dropped-refinements.baseline.json‎

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
"description": "Shrink-only ledger of every PUBLISHED JSON Schema that is STILL WIDER than the Zod type it was generated from, because a rule written as `.refine()` reaches the runtime and not the file (#18670). `z.toJSONSchema()` has no arm for a `custom` check: a plain record, the same record with a `.refine()`, and the same record with an ABORTING `.refine()` all project byte-identically (measured on zod 4.4.3, the version packages/spec resolves). So a document one of these files ACCEPTS can still be refused at parse time, and an author -- or an AI -- validating against packages/spec/json-schema/** finds out a release later. Each `sites` path is a position under that schema at which a refinement is dropped; the same paths are written onto the artifact itself as `x-dropped-refinements`. Item 2 closed the first patterns: a refinement DECLARED through the closed list in src/shared/refinement-projection.ts is emitted into the published file, reads `projected` rather than `dropped`, and its row LEAVES this ledger in the same PR -- which is why the ledger shrinks and never grows on a repair. Every refinement outside that closed list stays here, and adding an arm to the list is a public-contract decision, not a refactor. Hand-edited on purpose and with no `gen:` script: a generator would let a new gap be admitted by running a command instead of by a decision, which is the silence this ledger exists to end. Adding, removing or moving a site fails packages/spec/scripts/build-schemas.ts until the line moves with it, and the failure prints the corrected entry in full. ⛔ Do not delete or weaken a refinement to shorten this file -- the runtime rule is correct; it is the projection that is silent, and the remedy is to teach the closed list a NAMED pattern, never to drop the rule.",
33
"measured": {
44
"zod": "4.4.3",
5-
"publishedSchemasWithDroppedRefinements": 228,
6-
"droppedRefinementSites": 731,
5+
"publishedSchemasWithDroppedRefinements": 232,
6+
"droppedRefinementSites": 752,
77
"refinementSitesThatDidProject": 369,
88
"refinementSitesWithNoJsonFormToCompare": 0
99
},
@@ -63,12 +63,14 @@
6363
"sites": [
6464
"manifest.actions.element.in",
6565
"manifest.actions.element.in.ai.outputSchema",
66+
"manifest.actions.element.in.onSuccess",
6667
"manifest.actions.element.in.params.element.in",
6768
"manifest.agents.element.memory",
6869
"manifest.agents.element.structuredOutput.schema",
6970
"manifest.analyticsCubes.element.measures.valueType",
7071
"manifest.connectors.element.out",
7172
"manifest.dashboards.element.globalFilters.element",
73+
"manifest.dashboards.element.header.actions.element",
7274
"manifest.dashboards.element.widgets.element",
7375
"manifest.dashboards.element.widgets.element.filter",
7476
"manifest.datasets.element",
@@ -177,12 +179,14 @@
177179
"data.options[0].manifest.navigationContributions.element.items.element.lazy.options[0]",
178180
"data.options[1].manifest.actions.element.in",
179181
"data.options[1].manifest.actions.element.in.ai.outputSchema",
182+
"data.options[1].manifest.actions.element.in.onSuccess",
180183
"data.options[1].manifest.actions.element.in.params.element.in",
181184
"data.options[1].manifest.agents.element.memory",
182185
"data.options[1].manifest.agents.element.structuredOutput.schema",
183186
"data.options[1].manifest.analyticsCubes.element.measures.valueType",
184187
"data.options[1].manifest.connectors.element.out",
185188
"data.options[1].manifest.dashboards.element.globalFilters.element",
189+
"data.options[1].manifest.dashboards.element.header.actions.element",
186190
"data.options[1].manifest.dashboards.element.widgets.element",
187191
"data.options[1].manifest.dashboards.element.widgets.element.filter",
188192
"data.options[1].manifest.datasets.element",
@@ -281,12 +285,14 @@
281285
"options[0].manifest.navigationContributions.element.items.element.lazy.options[0]",
282286
"options[1].manifest.actions.element.in",
283287
"options[1].manifest.actions.element.in.ai.outputSchema",
288+
"options[1].manifest.actions.element.in.onSuccess",
284289
"options[1].manifest.actions.element.in.params.element.in",
285290
"options[1].manifest.agents.element.memory",
286291
"options[1].manifest.agents.element.structuredOutput.schema",
287292
"options[1].manifest.analyticsCubes.element.measures.valueType",
288293
"options[1].manifest.connectors.element.out",
289294
"options[1].manifest.dashboards.element.globalFilters.element",
295+
"options[1].manifest.dashboards.element.header.actions.element",
290296
"options[1].manifest.dashboards.element.widgets.element",
291297
"options[1].manifest.dashboards.element.widgets.element.filter",
292298
"options[1].manifest.datasets.element",
@@ -340,12 +346,14 @@
340346
"data.packages.element.options[0].manifest.navigationContributions.element.items.element.lazy.options[0]",
341347
"data.packages.element.options[1].manifest.actions.element.in",
342348
"data.packages.element.options[1].manifest.actions.element.in.ai.outputSchema",
349+
"data.packages.element.options[1].manifest.actions.element.in.onSuccess",
343350
"data.packages.element.options[1].manifest.actions.element.in.params.element.in",
344351
"data.packages.element.options[1].manifest.agents.element.memory",
345352
"data.packages.element.options[1].manifest.agents.element.structuredOutput.schema",
346353
"data.packages.element.options[1].manifest.analyticsCubes.element.measures.valueType",
347354
"data.packages.element.options[1].manifest.connectors.element.out",
348355
"data.packages.element.options[1].manifest.dashboards.element.globalFilters.element",
356+
"data.packages.element.options[1].manifest.dashboards.element.header.actions.element",
349357
"data.packages.element.options[1].manifest.dashboards.element.widgets.element",
350358
"data.packages.element.options[1].manifest.dashboards.element.widgets.element.filter",
351359
"data.packages.element.options[1].manifest.datasets.element",
@@ -397,6 +405,7 @@
397405
"sites": [
398406
"data.actions.element.in",
399407
"data.actions.element.in.ai.outputSchema",
408+
"data.actions.element.in.onSuccess",
400409
"data.actions.element.in.params.element.in"
401410
]
402411
},
@@ -405,6 +414,7 @@
405414
"data",
406415
"data.actions.element.in",
407416
"data.actions.element.in.ai.outputSchema",
417+
"data.actions.element.in.onSuccess",
408418
"data.actions.element.in.params.element.in",
409419
"data.fieldGroups",
410420
"data.fields.out.valueType",
@@ -841,6 +851,7 @@
841851
"",
842852
"actions.element.in",
843853
"actions.element.in.ai.outputSchema",
854+
"actions.element.in.onSuccess",
844855
"actions.element.in.params.element.in",
845856
"fieldGroups",
846857
"fields.out.valueType",
@@ -1021,6 +1032,7 @@
10211032
"",
10221033
"actions.element.in",
10231034
"actions.element.in.ai.outputSchema",
1035+
"actions.element.in.onSuccess",
10241036
"actions.element.in.params.element.in"
10251037
]
10261038
},
@@ -1120,6 +1132,7 @@
11201132
"operations.element.options[3].object",
11211133
"operations.element.options[3].object.actions.element.in",
11221134
"operations.element.options[3].object.actions.element.in.ai.outputSchema",
1135+
"operations.element.options[3].object.actions.element.in.onSuccess",
11231136
"operations.element.options[3].object.actions.element.in.params.element.in",
11241137
"operations.element.options[3].object.fieldGroups",
11251138
"operations.element.options[3].object.fields.out.valueType",
@@ -1139,6 +1152,7 @@
11391152
"object",
11401153
"object.actions.element.in",
11411154
"object.actions.element.in.ai.outputSchema",
1155+
"object.actions.element.in.onSuccess",
11421156
"object.actions.element.in.params.element.in",
11431157
"object.fieldGroups",
11441158
"object.fields.out.valueType",
@@ -1184,6 +1198,7 @@
11841198
"options[3].object",
11851199
"options[3].object.actions.element.in",
11861200
"options[3].object.actions.element.in.ai.outputSchema",
1201+
"options[3].object.actions.element.in.onSuccess",
11871202
"options[3].object.actions.element.in.params.element.in",
11881203
"options[3].object.fieldGroups",
11891204
"options[3].object.fields.out.valueType",
@@ -1282,6 +1297,7 @@
12821297
"sites": [
12831298
"in",
12841299
"in.ai.outputSchema",
1300+
"in.onSuccess",
12851301
"in.params.element.in"
12861302
]
12871303
},
@@ -1290,11 +1306,21 @@
12901306
"outputSchema"
12911307
]
12921308
},
1309+
"ui/ActionButtonProps": {
1310+
"sites": [
1311+
""
1312+
]
1313+
},
12931314
"ui/ActionGroupProps": {
12941315
"sites": [
12951316
"actions.element"
12961317
]
12971318
},
1319+
"ui/ActionIconProps": {
1320+
"sites": [
1321+
""
1322+
]
1323+
},
12981324
"ui/ActionMenuProps": {
12991325
"sites": [
13001326
"actions.element"
@@ -1323,11 +1349,22 @@
13231349
"ui/Dashboard": {
13241350
"sites": [
13251351
"globalFilters.element",
1352+
"header.actions.element",
13261353
"widgets.element",
13271354
"widgets.element.filter",
13281355
"widgets.element.filter.lazy"
13291356
]
13301357
},
1358+
"ui/DashboardHeader": {
1359+
"sites": [
1360+
"actions.element"
1361+
]
1362+
},
1363+
"ui/DashboardHeaderAction": {
1364+
"sites": [
1365+
""
1366+
]
1367+
},
13311368
"ui/DashboardWidget": {
13321369
"sites": [
13331370
"",

0 commit comments

Comments
 (0)