You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 2b80461
Browse filesBrowse the repository at this point in the historyBrowse files
fix(spec): the four ComponentPropsMap navigation doors list all seven NavigationModeSchema modes (#19675)
Part of #18459 (item N2)
> ⚠️ **Closing keyword corrected by the seat from `Fixes` to `Part
of`.** Card #18459 carries FOUR items. N1 is measured DEAD on main (PR
#18904 replaced the enumerating describe with a pointer at
`ListViewSchema.map`, whose schema declares every key `.optional()`),
and **N2 is what this PR lands**. ⛔ **N3 and N4 are NOT fixed** — both
were re-measured at the live pin and deliberately left on the card, N3
with fresh numbers that supersede the card's own stale proposals. A
`Fixes` would have closed the card on merge and destroyed both. The seat
releases the card back to the queue on landing with a `Release:` naming
what landed and what remains.
Clause-②: no
## Summary
The card carried **two shipped imprecisions**. Re-measured at the LIVE
objectui pin
`87af769e9a3ee28ace099fdd653d3ebd79fe82e2` before anything was changed,
**one is dead and
one survives** — and the surviving one is wider than the card scoped it.
This PR fixes the surviving one. The falsification of the other is
recorded below rather
than acted on.
## Zone 2 — what the re-measurement found
### N1 (lat/lng pair marked required) — FALSIFIED, already fixed. No
change here.
At PR #18403 the `object-map` `map` row read:
`'Map field config, the author face: { latitudeField, longitudeField,
locationField?, titleField?, descriptionField?, zoom?, center?, style?
}. Taken WHOLE when present ...'`
— the enumeration the card objected to. Commit `1aa5026e30` (PR #18904,
"declare `style` on
`ListMapConfigSchema` and point `object-map.map` back at it") **deleted
that enumeration**.
On `main` today the row reads `'Map field config, the author face — the
same block
ListViewSchema.map declares ...'`, and the generated reference renders
the TYPE from
`ListMapConfigSchema` itself:
`| **map** | { latitudeField?: string; longitudeField?: string;
locationField?: string; titleField?: string; … } | optional | ...`
Every key optional, no required pair claimed. The statement the card
called false no longer
exists in the source or in the shipped reference.
Reproduce: `git log -S "Map field config, the author face: {
latitudeField" -- packages/spec/src/ui/component.zod.ts`
returns exactly two commits, `a3d4c59d69` (added, PR #18403) and
`1aa5026e30` (removed, PR #18904).
### N2 (navigation list omits `new_window`) — CONFIRMED, and it is four
rows, not three.
At the live pin, `object-grid`, `object-map`, `object-gantt` and
`object-tree` each hand
`schema.navigation` straight into the shared `useNavigationOverlay` hook
(`ObjectGrid.tsx:2321`, `ObjectMap.tsx:1041`, `ObjectGantt.tsx:1680`,
`ObjectTree.tsx:891`).
That hook binds its own mode union to this package's
`NavigationModeSchema` — its docblock
says so in as many words, *"the seven modes this hook switches on are
exactly the seven the
exported union publishes"*, held by a parity test on that side — and its
click router carries
a `new_window` branch that delegates to `onNavigate` and otherwise falls
through to a
`window.open`. `object-gantt` implements that action itself as well.
The four `.describe()` strings listed six of the seven (no
`new_window`), except `object-grid`
— the row the other three were copied from — which listed five (no
`popover` either). All four
doors are `z.unknown()`, so that sentence is the entire published
account of the shape, and
the reference page renders the type beside it as `any`.
### N3 (two comment citations in `component.test.ts`) — NOT fixed here,
and the card's own correction is stale.
Both citations still exist (`component.test.ts:3649` `label (:1849)`,
`:3750`
`ObjectGantt.tsx:501`). But they are HISTORICAL citations anchored to
the retired pin
`53ded82b`, and the corrections the card proposes (`:1871`, `:500`) were
measured at that
same retired pin. At the live pin the true positions are **`:503`** for
the
`GanttConfigSchema.safeParse` and **`:2181`** for the label resolution —
so applying the
card's numbers would replace one unverifiable pair with another.
`component.test.ts` is also
outside this dispatch's declared file surface. Left for the card.
### N4 (historical pin-citation spelling) — unchanged, measured.
`check:objectui-pin-citations --list` on this head: **48 historical / 29
asserting / 7
assertion** entries. **30 historical citations still name the retired
`53ded82b`**, ten of
them in `component.zod.ts`, including the three headers this card is
about
(`component.zod.ts:3561` map, `:3715` gantt, `:3906` tree). The gate
permits the historical
form by design, so nothing is violated and nothing reds — those anchors
simply are not
re-checked on a pin bump, which is exactly what the card recorded. N3's
re-measurement above
shows the drift is real and not hypothetical. Converting them is a
re-measurement job, not a
spelling change, and is left for the card.
## The change
Four `.describe()` strings, plus the reference page regenerated from
them with
`pnpm --filter @objectstack/spec check:generated --fix` (never by hand):
- `ObjectGridPropsSchema.navigation`
- `ObjectMapPropsSchema.navigation`
- `ObjectGanttPropsSchema.navigation`
- `ObjectTreePropsSchema.navigation`
Each now lists `page | drawer | modal | split | popover | new_window |
none` and names
`NavigationModeSchema` as the source of that list, so the next member
added to the enum has a
named edge into these rows instead of four independently drifting lists.
**Why `object-grid` is in scope.** The card names it as the precedent
the other three copied
and says "fixing it means fixing the family, not just these three rows".
It is the same defect
class, in the same file, in the same gate family, adds no verification
surface, and understates
by two rather than one. Correcting three while leaving the source of the
pattern intact would
leave the family in the state that produced the defect.
No accept set moves: the doors stay `z.unknown()`.
## Changeset — measured, not pattern-matched
`patch` on `@objectstack/spec`. The changed bytes ARE published bytes:
- `packages/spec/package.json` `files[]` contains `src/**/*.zod.ts`, so
`src/ui/component.zod.ts` ships verbatim in the tarball.
- The compiled strings ship in `dist/ui/index.js` and
`dist/ui/index.mjs`.
- `npm pack --dry-run --json` in `packages/spec` lists all three of
those paths among its
2030 entries. `@objectstack/spec` is `private: false` at `17.4.0` — a
released package.
- Controls: a positive control (an untouched describe from the same
rows) is found in the same
dist files; a negative control (a string present nowhere) is found in
none.
So `skip-changeset` would have been wrong here, and no changeset would
have been wrong too.
## Verification
Head `55dd769453`. `origin/main` merged in at `f2101d0492` via
`scripts/pm/os-regen-merge.sh`
before the final measurements; all 15 spec generated artifacts
re-checked clean after it.
- `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack
--commands` derived
**102 families** from the actual changed paths. All 102 run, exit codes
captured to a file
BEFORE any pipe, reconciled with `--ran`: **102 run, 0 NOT MEASURED, 0
UNRUN**.
- The single non-zero is `pnpm --filter @objectstack/spec run
check:react-declaration-parity`
in its bare spelling, which exits 1 by design with no `MANIFEST`. Run as
CI runs it —
`MANIFEST="$PWD/sdui.manifest.json" ... --baseline
react-declaration-parity.baseline.json --strict`
— it exits **0**, with no new declaration divergence vs the accepted
baseline.
- `pnpm --filter @objectstack/spec test` — **512 files, 14953 passed, 1
todo**.
- `pnpm --filter @objectstack/spec typecheck` — exit 0 (`tsc --noEmit`,
`check:scripts-typecheck`,
`check:test-typecheck`).
- `pnpm lint` (`eslint . --no-inline-config`, the whole repo, not
narrowed) — exit 0.
- `pnpm --filter @objectstack/spec check:generated` — all 15 artifacts
up to date.
- Every heavy run went through `scripts/pm/os-verify-lock.sh`; verdicts
read from its
`VERDICT command-exit` line.
## Acceptance notes
Observed while measuring, deliberately NOT changed here and not filed:
1. **These four describes account for `mode` only.**
`useNavigationOverlay` also reads `size`,
`openNewTab` and `preventNavigation`, and the TYPED sibling rows
(`object-kanban`,
`object-calendar`, the list-view entry) name all four members. On a
`z.unknown()` door the
describe is the whole account, so naming one member of four understates
the block — a
separate imprecision from the one this card carries. Carrier: the next
PR touching these
rows, or a decision to point these four doors at
`NavigationConfigSchema` the way their
typed siblings already do.
2. **A stale comment in the sibling repo.**
`plugin-tree/src/ObjectTree.tsx` at the live pin
states "measured on the installed spec: `navigation` is declared on
exactly one
`ComponentPropsMap` entry, `object-grid`". It is now declared on
several. A comment in
another repository with no contract behind it. Carrier: objectui.
3. N3 and N4 above remain open on the card, with fresh measurements
recorded there.
---
_Generated by [Claude Code](https://claude.ai/code)_
---------
Co-authored-by: Claude <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: content/docs/references/ui/component.mdx
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -413,7 +413,7 @@ Sort field and direction pair
413
413
|**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 MongoDB-style record form is refused — see migration `element-data-source-and-object-block-filter-rule-array`|
414
414
|**sort**|`{ field: string; order: Enum<'asc' \| 'desc'> }[]`| optional | Task order for the fetched bars — the SortItem array form `[{ field, order }, ...]`, the one sort orthography every declared `sort` door on this platform shares; lowered to the wire `$orderby`. The legacy string clause (`name desc`) is refused — see migration `object-block-sort-item-array`|
415
415
|**gantt**|`{ startDateField: string; endDateField: string; titleField: string; progressField?: string; … }`| optional | Gantt-timeline configuration, the author face — the same block `ListViewSchema.gantt` declares, and the one the renderer validates this node against. Taken WHOLE when present: the flat top-level spelling beside it is ignored |
|**navigation**|`any`| optional | Task-click navigation config (`{ mode: page \| drawer \| modal \| split \| popover \| new_window \| none }`) — all seven `NavigationModeSchema` values, since the shared `useNavigationOverlay` hook types its own mode union as that schema; renderer default `drawer`|
417
417
|**label**|`string \| Record<string, string>`| optional | Gantt label — the second link of the exported PNG/PDF file-name chain, after `gantt.exportFileName` and before the bound object's own label |
418
418
|**skipWeekends**|`boolean`| optional | Measure duration and auto-schedule math in WORKING days, skipping Saturdays and Sundays |
419
419
|**holidays**|`string[]`| optional | Additional non-working dates for the working calendar, ISO `yyyy-mm-dd` strings; folded into a Set for the duration math |
@@ -542,7 +542,7 @@ Sort field and direction pair
542
542
|**bulkActions**|`any[]`| optional | Bulk action names shown on selection |
543
543
|**batchActions**|`any[]`| optional | Alternate spelling the renderer reads FIRST (`batchActions ?? bulkActions`) |
|**navigation**|`any`| optional | Row-click navigation config (`{ mode: page \| drawer \| modal \| split \| popover \| new_window \| none }`) — all seven `NavigationModeSchema` values, since the shared `useNavigationOverlay` hook types its own mode union as that schema|
|**singleClickEdit**|`boolean`| optional | Enter cell edit on single click (default true when editable) |
548
548
|**resizable**|`boolean`| optional | Allow column resize (read before `resizableColumns`) |
@@ -666,7 +666,7 @@ View filter rule
666
666
|**sort**|`{ field: string; order: Enum<'asc' \| 'desc'> }[]`| optional | Marker order for the fetched records — the SortItem array form `[{ field, order }, ...]`, the one sort orthography every declared `sort` door on this platform shares; lowered to the wire `$orderby`. The legacy string clause (`name desc`) is refused — see migration `object-block-sort-item-array`|
667
667
|**map**|`{ latitudeField?: string; longitudeField?: string; locationField?: string; titleField?: string; … }`| optional | Map field config, the author face — the same block `ListViewSchema.map` declares, and the one the renderer validates this node against. Taken WHOLE when present: the flat top-level spelling beside it is ignored |
668
668
|**mapStyle**|`string`| optional | MapLibre style URL or spec, overriding the public demo tiles. Read before `map.style`; NOT the base node `style`, which is an inline CSS record |
|**navigation**|`any`| optional | Marker-click navigation config (`{ mode: page \| drawer \| modal \| split \| popover \| new_window \| none }`) — all seven `NavigationModeSchema` values, since the shared `useNavigationOverlay` hook types its own mode union as that schema|
670
670
|**enableClustering**|`boolean`| optional | Group nearby markers into clusters. Absent, the renderer clusters only above 100 markers |
|**staticData**|`any[]`| optional | Inline records — read SECOND by `resolveRecordSourceConfig`, wrapped into a `{ provider: 'value' }` config |
875
875
|**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 MongoDB-style record form is refused — see migration `element-data-source-and-object-block-filter-rule-array`|
876
876
|**tree**|`{ parentField?: string; labelField?: string; fields?: string[]; defaultExpandedDepth?: integer }`| optional | Tree/hierarchy configuration, the author face — the same block `ListViewSchema.tree` declares: `{ parentField?, labelField?, fields?, defaultExpandedDepth? }`. `parentField` auto-detects from the object schema when omitted |
|**navigation**|`any`| optional | Row-click navigation config (`{ mode: page \| drawer \| modal \| split \| popover \| new_window \| none }`) — all seven `NavigationModeSchema` values, since the shared `useNavigationOverlay` hook types its own mode union as that schema|
navigation: z.unknown().optional().describe('Row-click navigation config ({ mode: page | drawer | modal | split | popover | new_window | none }) — all seven `NavigationModeSchema` values, since the shared `useNavigationOverlay` hook types its own mode union as that schema'),
.describe('MapLibre style URL or spec, overriding the public demo tiles. Read before `map.style`; NOT the base node `style`, which is an inline CSS record'),
.describe('Marker-click navigation config ({ mode: page | drawer | modal | split | popover | new_window | none }) — all seven `NavigationModeSchema` values, since the shared `useNavigationOverlay` hook types its own mode union as that schema'),
3654
3654
enableClustering: z.boolean().optional()
3655
3655
.describe('Group nearby markers into clusters. Absent, the renderer clusters only above 100 markers'),
.describe('Gantt-timeline configuration, the author face — the same block `ListViewSchema.gantt` declares, and the one the renderer validates this node against. Taken WHOLE when present: the flat top-level spelling beside it is ignored'),
.describe('Task-click navigation config ({ mode: page | drawer | modal | split | popover | new_window | none }) — all seven `NavigationModeSchema` values, since the shared `useNavigationOverlay` hook types its own mode union as that schema; renderer default `drawer`'),
3781
3781
label: I18nLabelSchema.optional()
3782
3782
.describe('Gantt label — the second link of the exported PNG/PDF file-name chain, after `gantt.exportFileName` and before the bound object\'s own label'),
.describe('Tree/hierarchy configuration, the author face — the same block `ListViewSchema.tree` declares: { parentField?, labelField?, fields?, defaultExpandedDepth? }. `parentField` auto-detects from the object schema when omitted'),
.describe('Row-click navigation config ({ mode: page | drawer | modal | split | popover | new_window | none }) — all seven `NavigationModeSchema` values, since the shared `useNavigationOverlay` hook types its own mode union as that schema'),
3940
3940
}));
3941
3941
/** Author state (ADR-0122: the bare name is the author state). */
0 commit comments