From 190c3cea2c7e50f60cf6716b7d7a20d95546b5c8 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 6 Sep 2026 07:26:44 +0000 Subject: [PATCH] docs(plugin-detail): compile every README snippet and leave UNGATED_DOCS Part of #5174 (batch 17). Removes the 'packages/plugin-detail/README.md' entry from UNGATED_DOCS in scripts/check-doc-snippet-types.mjs -- the only change to that file, +0/-2, inside the object literal -- and repairs the document so all 7 ts/tsx blocks compile against the built types. The 21 measured diagnostics split into fragment shape and real API drift: - 6 parse diagnostics: two blocks were not statements at all. The data-source block held two sibling top-level JSX expressions, and the custom-Page block was a bare object literal fenced `ts`. Both now bind their value to a name, with no re-indentation of the content. - 15 undefined-name diagnostics: blocks used ambient names (DetailView, accountData, activityData, navigate, deleteAccount) or continued an earlier block. They now carry real imports plus `declare const` placeholders typed to the shipped surface. Three of them were doc lies rather than fragment shape: - `related[].columns` was documented as a string array. The shipped DetailViewSchema declares TableColumn[], so the example moves to { accessorKey, header } entries. - The "## Schema" block re-declared DetailViewSchema by hand and had drifted from the package: it named `RelatedList` (a component, not a type) for `related`, and omitted primaryField, summaryFields, layout, columns, onNavigate and history. It now imports the real type from @object-ui/types and annotates an example with it, so the compiler keeps it honest. - The Reference Rail's "per-object opt-out" documented `ObjectSchema.create({ detail: { hideReferenceRail } })`. That factory is not importable from @objectstack/spec, and the objectDef `detail.*` block was retired -- this package's own CHANGELOG records it as an ADR-0085 removed dead read that is "no longer consulted". The surviving opt-out is BuildPageOptions, passed to buildDefaultPageSchema, which is what the block and the matrix bullet naming it now say. No packages/** source touched, no public type widened, no gate loosened, and no new FRAGMENT_MARKER: declared fragments stay at 158, so all 7 blocks earn coverage by compiling. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01MM7kaS4dPpYHV5BsMyu4tQ --- packages/plugin-detail/README.md | 124 ++++++++++++++++++---------- scripts/check-doc-snippet-types.mjs | 2 - 2 files changed, 80 insertions(+), 46 deletions(-) diff --git a/packages/plugin-detail/README.md b/packages/plugin-detail/README.md index cea492a8c4..a363c7609b 100644 --- a/packages/plugin-detail/README.md +++ b/packages/plugin-detail/README.md @@ -30,16 +30,20 @@ present: ```tsx import { SchemaRenderer, SchemaRendererProvider } from '@object-ui/react'; +import { DetailView } from '@object-ui/plugin-detail'; +import type { DataSource } from '@object-ui/types'; + +declare const dataSource: DataSource; // 1. Injected by an ancestor — the pattern the rest of the family uses, and the // one to reach for when a page renders several data-bound blocks. - +const viaProvider = - +; // 2. Handed to one placement — what `` has always // taken, and what the examples below use. - +const viaProp = ; ``` Route 1 is new as of objectui#5378: this block used to read the adapter from its @@ -87,7 +91,11 @@ function ContactDetail() { ### With Sections ```tsx -; + +const accountDetail = +/>; ``` ### With Tabs and Related Lists ```tsx -[]; +declare const navigate: (url: string) => void; +declare const deleteAccount: (id: string) => void; + +const accountDetail = navigate('/accounts/12345/edit')} onDelete={() => deleteAccount('12345')} onBack={() => navigate('/accounts')} -/> +/>; ``` ## Schema -The DetailView component accepts a `DetailViewSchema`: +The DetailView component accepts a `DetailViewSchema`, declared in +`@object-ui/types`. Import it rather than re-typing it — every key below is +checked against that declaration, so this example cannot drift from the package: ```typescript -interface DetailViewSchema { - type: 'detail-view'; - title?: string; - objectName?: string; - resourceId?: string | number; - api?: string; - data?: any; - sections?: DetailViewSection[]; - fields?: DetailViewField[]; - tabs?: DetailViewTab[]; - related?: RelatedList[]; - actions?: ActionSchema[]; - showBack?: boolean; - showEdit?: boolean; - showDelete?: boolean; - backUrl?: string; - editUrl?: string; - deleteConfirmation?: string; - loading?: boolean; - header?: SchemaNode; - footer?: SchemaNode; -} +import type { DetailViewSchema } from '@object-ui/types'; + +const schema: DetailViewSchema = { + type: 'detail-view', + title: 'Account Details', + objectName: 'accounts', + resourceId: '12345', + api: '/api/accounts/12345', + data: undefined, + // Field name whose value becomes the header title; `title` is the fallback. + primaryField: 'name', + // Field values rendered as badges beside the header title. + summaryFields: ['industry', 'website'], + layout: 'vertical', + columns: 2, + // See the examples above for the shapes these four carry. + sections: [], + fields: [], + tabs: [], + related: [], + actions: [], + showBack: true, + backUrl: '/accounts', + showEdit: true, + editUrl: '/accounts/12345/edit', + showDelete: true, + deleteConfirmation: 'Delete this account?', + loading: false, + header: { type: 'text', label: 'Custom header' }, + footer: { type: 'text', label: 'Custom footer' }, +}; ``` ## Components @@ -349,23 +384,24 @@ emits automatically when: inbound fields). 3. The viewport is **≥ xl (1280 px)** — below that the rail collapses and the **Related** tab keeps full coverage. -4. The objectDef does **not** opt out via `detail.hideReferenceRail`. +4. The synth call does **not** opt out via `hideReferenceRail`. When the rail emits, the synth automatically suppresses the **Related** tab so the same information isn't shown twice. -### Per-object opt-out +### Opting out -Add a `detail` block to the objectDef: +The opt-out is a `buildDefaultPageSchema` **option**, not an objectDef key: ```ts -ObjectSchema.create({ - name: 'product', - // … - detail: { - hideReferenceRail: true, // hide the rail; restore the Related tab - hideRelatedTab: true, // (optional) force-hide the Related tab too - }, +import { buildDefaultPageSchema } from '@object-ui/plugin-detail'; +import type { ObjectDefLike } from '@object-ui/plugin-detail'; + +declare const productDef: ObjectDefLike; + +const page = buildDefaultPageSchema(productDef, { + hideReferenceRail: true, // hide the rail; restore the Related tab + hideRelatedTab: true, // (optional) force-hide the Related tab too }); ``` @@ -386,7 +422,7 @@ For explicit (non-synth) Pages, add an `aside` region after the `main` region: ```ts -{ +const asideRegion = { name: 'aside', width: 'small', className: 'hidden xl:flex flex-col gap-4', @@ -403,7 +439,7 @@ region: }, }, ], -}, +}; ``` The renderer reads `entries` from both `schema.entries` and diff --git a/scripts/check-doc-snippet-types.mjs b/scripts/check-doc-snippet-types.mjs index 9f7afb122f..304bbe5706 100644 --- a/scripts/check-doc-snippet-types.mjs +++ b/scripts/check-doc-snippet-types.mjs @@ -731,8 +731,6 @@ const UNGATED_DOCS = { '6 parse diagnostic(s) — blocks fenced `ts` that are bare object literals or elided bodies', 'packages/plugin-chatbot/README.md': '5 undefined-name diagnostic(s) — blocks continue an earlier block, or use ambient names the page never defines; 1 unresolved-module diagnostic(s); plus TS17000x1 TS2322x1 — candidate real defects, un-triaged', - 'packages/plugin-detail/README.md': - '5 parse diagnostic(s) — blocks fenced `ts` that are bare object literals or elided bodies; 15 undefined-name diagnostic(s) — blocks continue an earlier block, or use ambient names the page never defines', 'packages/plugin-editor/README.md': '6 parse diagnostic(s) — blocks fenced `ts` that are bare object literals or elided bodies', 'packages/plugin-gantt/README.md':