From 2f620769227b871c660c25809c7cbffc3dee7b99 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 24 Aug 2026 10:20:54 +0000 Subject: [PATCH] docs(guides,tooling): clear three .md pages off the doc-snippet ledger Walk `guide/plugin-development`, `guide/schema-rendering` and `guide/theming` off `UNGATED_DOCS`, clearing 81 diagnostics (25 / 27 / 29). The ledger goes 49 -> 46 entries and the covered set 173 -> 176; `guide/layout` and `guide/component-registry` are the two that remain. 38 blocks come under the gate: 26 declared fragments and 12 that compile, of which 7 already compiled untouched and 5 were edited to. Only the two honest routes were used. Four genuine documented-API defects were fixed rather than declared away: - `guide/theming`'s three `Theme` objects were annotated `Theme` while the annotation itself errored, so TypeScript never excess-checked the literals. With it resolving, the `brand` palette had ten of fourteen `colors` keys off `ColorPalette` -- `"primary-foreground"`, `foreground`, `muted`, `ring`, `destructive` and the other `*-foreground` pairs are Shadcn CSS VARIABLE names, not palette keys -- plus `radius` and `fonts`, neither a `Theme` key, and no `label`, which is required. `generateColorVars` iterates `COLOR_TO_CSS_MAP`, so every one of those was dropped in silence at runtime. Routed through the two doors that do work: real palette keys, each annotated with the variable it emits, and `customVars` for the rest. - `guide/plugin-development`'s Vitest example asserted `toBeInTheDocument()` with no `@testing-library/jest-dom` import. - `guide/schema-rendering`'s first example set `body: { /* ... */ }`, which is not a `SchemaNode`. - the same page's restated `BaseSchema` named `CSSProperties` from nowhere. Gate strictness is unmoved: everything from the `Fence scanning` banner to EOF is byte-identical to `main` (475 lines, same sha), as are `DOC_EXTENSIONS`, `TS_FENCE_LANGUAGES`, `FRAGMENT_MARKER`, `MIN_REASON_LENGTH` and `COMPILER_OPTIONS`. `--build-filter` is unchanged at 20 filters / 33 turbo build tasks, both sets identical package-by-package. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_019b5UBNMtTzKbVtZZGvFuxe --- content/docs/guide/plugin-development.md | 16 ++++++ content/docs/guide/schema-rendering.md | 11 +++- content/docs/guide/theming.md | 69 +++++++++++++++++------- scripts/check-doc-snippet-types.mjs | 54 +++++++++++-------- 4 files changed, 109 insertions(+), 41 deletions(-) diff --git a/content/docs/guide/plugin-development.md b/content/docs/guide/plugin-development.md index 4de811c8b5..4b29340e55 100644 --- a/content/docs/guide/plugin-development.md +++ b/content/docs/guide/plugin-development.md @@ -95,6 +95,7 @@ export interface BoardProps { ### 2. Build the Implementation + ```tsx // src/BoardImpl.tsx import React from 'react'; @@ -133,6 +134,7 @@ export default function BoardImpl({ schema, className }: BoardProps) { ### 3. Create the Entry Point + ```tsx // src/index.tsx import React, { Suspense } from 'react'; @@ -180,6 +182,8 @@ Field widgets follow the `FieldWidgetComponentProps` interface from `@object-ui/ ```typescript // FieldWidgetComponentProps shape (from packages/fields/src/widgets/types.ts) +import type { FieldMetadata } from '@object-ui/types'; + type FieldWidgetComponentProps = { value: T; onChange: (val: T) => void; @@ -209,6 +213,7 @@ grids, reports). That is precisely why a **field widget** needs an adapter when it is rendered from a schema node instead of from a form. Wrap it once, at registration, and the widget only ever implements one contract: + ```tsx import { ComponentRegistry } from '@object-ui/core'; import { withFieldCarrier } from '@object-ui/fields'; @@ -292,6 +297,7 @@ export function ColorPickerField({ Register it as a field widget: + ```tsx // src/index.tsx import { ComponentRegistry } from '@object-ui/core'; @@ -317,6 +323,7 @@ export { ColorPickerField }; Namespaces prevent type collisions between plugins: + ```tsx import { ComponentRegistry } from '@object-ui/core'; @@ -337,6 +344,8 @@ Use `skipFallback: true` in the metadata if you do **not** want the component to ### Querying Registered Components ```tsx +import { ComponentRegistry } from '@object-ui/core'; + ComponentRegistry.has('board'); // boolean ComponentRegistry.getAllTypes(); // string[] ComponentRegistry.getNamespaceComponents('plugin-board'); // ComponentConfig[] @@ -346,6 +355,7 @@ ComponentRegistry.getNamespaceComponents('plugin-board'); // ComponentConfig Define your schema interface in `types.ts` and extend `BaseSchema`: + ```typescript import type { BaseSchema } from '@object-ui/types'; @@ -358,6 +368,7 @@ export interface BoardSchema extends BaseSchema { Declare `ComponentInput` entries when registering so the visual designer can offer a property panel: + ```tsx ComponentRegistry.register('board', BoardRenderer, { inputs: [ @@ -378,10 +389,14 @@ ComponentRegistry.register('board', BoardRenderer, { ObjectUI uses **Vitest + React Testing Library**. Place tests next to the implementation. + ```tsx // src/BoardImpl.test.tsx import { describe, it, expect } from 'vitest'; import { render, screen } from '@testing-library/react'; +// `toBeInTheDocument` is a jest-dom matcher, not a Vitest one — without this +// import the assertions below do not type-check and do not run. +import '@testing-library/jest-dom'; import BoardImpl from './BoardImpl'; const schema = { @@ -458,6 +473,7 @@ npm publish --access public pnpm add @object-ui/plugin-board ``` + ```tsx // app/main.tsx — import once, auto-registers import '@object-ui/plugin-board'; diff --git a/content/docs/guide/schema-rendering.md b/content/docs/guide/schema-rendering.md index 33f4bacb07..c273d987ae 100644 --- a/content/docs/guide/schema-rendering.md +++ b/content/docs/guide/schema-rendering.md @@ -31,7 +31,7 @@ function App() { const schema = { type: "page", title: "My Dashboard", - body: { /* ... */ } + body: { type: "text", value: "Hello" } } return @@ -43,6 +43,8 @@ function App() { Every schema object must have at minimum a `type` field: ```typescript +import type { CSSProperties } from 'react' + interface BaseSchema { type: string // Component type identifier id?: string // Optional unique identifier @@ -74,6 +76,7 @@ interface BaseSchema { The `SchemaRenderer` accepts a `data` prop that provides context for expressions: + ```tsx const data = { user: { name: "John", role: "admin" }, @@ -98,6 +101,7 @@ Use expression syntax `${}` to reference data: The schema renderer uses a component registry to map schema types to React components: + ```tsx import { ComponentRegistry } from '@object-ui/core' @@ -212,6 +216,7 @@ Object UI includes a powerful expression system for dynamic behavior: Components can emit events that you handle in React: + ```tsx ```tsx import { lazy } from 'react' @@ -275,6 +281,7 @@ registry.register('heavy-chart', HeavyChart) The renderer includes built-in error boundaries: + ```tsx ```tsx // ✅ Good const data = { @@ -345,6 +353,7 @@ const data = { Move logic to expressions instead of creating conditional schemas: + ```tsx // ❌ Bad const schema = user.isAdmin ? adminSchema : userSchema diff --git a/content/docs/guide/theming.md b/content/docs/guide/theming.md index 2466055583..a3e026bca0 100644 --- a/content/docs/guide/theming.md +++ b/content/docs/guide/theming.md @@ -55,6 +55,7 @@ ObjectUI follows the Shadcn convention. Design tokens are defined as HSL channel Components reference these tokens through Tailwind: + ```tsx