From d975803fb2d4edd6808af683c4c43fb3f7c18c1b Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 20 Aug 2026 01:26:36 +0000 Subject: [PATCH] docs(guide,api): one disposition per fabricated export, applied at every site (#5343) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The getting-started guides under `content/docs/guide/**` and `content/docs/api/schema-reference.md` documented 14 symbols the packages do not export. A reader copying one of those imports got a compile error, not a degraded render — the same class as #5160, one directory over. Every name set was taken from each package's built `dist/index.d.ts`, never from a grep of `src/`. Each symbol got ONE disposition, applied at every site: - renamed: `PageSchema` -> `PageNodeSchema`, `DashboardSchema` -> `DashboardComponentSchema`, `AppSchema` / `ThemeSchema` / `ReportSchema` -> `AppComponentSchema` / `ThemeComponentSchema` / `ReportComponentSchema` (type AND zod entries), `componentSchema` -> `ComponentSchema`, `registerDefaultRenderers` / `registerAllComponents` -> `initializeComponents()` plus the side-effect `@object-ui/fields` import, `getComponentRegistry()` -> the `ComponentRegistry` singleton; - wrong package: `BaseSchema`, `PageSchema` and `FormSchema` were claimed from `@object-ui/core` while they live in `@object-ui/types`; - removed with nothing replacing it: `InputRenderer`, the `ObjectSchema` / `Field` builder pair and `getExpressionEvaluator` — those examples are gone and the pages teach the real surface instead. The seven `UNGATED_DOCS` entries are rewritten to the mix each page now measures. Every bucket is equal or lower; no new diagnostic class appears. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01RV6yuVCxymHYE16PL9vQkE --- .changeset/guide-fabricated-exports-5343.md | 24 ++++ content/docs/api/schema-reference.md | 18 +-- content/docs/guide/building-crud-app.md | 79 +++++++---- content/docs/guide/component-registry.md | 138 +++++++++----------- content/docs/guide/expressions.md | 50 +++---- content/docs/guide/schema-overview.md | 70 +++++----- content/docs/guide/schema-rendering.md | 31 ++--- content/docs/guide/troubleshooting.md | 5 +- scripts/check-doc-snippet-types.mjs | 93 ++++++++----- 9 files changed, 290 insertions(+), 218 deletions(-) create mode 100644 .changeset/guide-fabricated-exports-5343.md diff --git a/.changeset/guide-fabricated-exports-5343.md b/.changeset/guide-fabricated-exports-5343.md new file mode 100644 index 0000000000..32e9251645 --- /dev/null +++ b/.changeset/guide-fabricated-exports-5343.md @@ -0,0 +1,24 @@ +--- +--- + +Docs + gate-ledger only (objectui#5343). The getting-started guides under +`content/docs/guide/**` and `content/docs/api/schema-reference.md` documented 14 symbols +the packages do not export; a reader who copied one of those imports got a compile error, +not a degraded render. Each symbol got ONE disposition, taken from the packages' built +`dist/index.d.ts` and applied at every site: + +- renamed — `PageSchema` → `PageNodeSchema`, `DashboardSchema` → `DashboardComponentSchema`, + `AppSchema` / `ThemeSchema` / `ReportSchema` → `AppComponentSchema` / + `ThemeComponentSchema` / `ReportComponentSchema` (type and zod entries both), + `componentSchema` → `ComponentSchema`, `registerDefaultRenderers` / + `registerAllComponents` → `initializeComponents()` plus the side-effect + `@object-ui/fields` import, `getComponentRegistry()` → the `ComponentRegistry` singleton; +- wrong package — `BaseSchema`, `PageSchema` and `FormSchema` were claimed from + `@object-ui/core` while they live in `@object-ui/types`; +- removed with nothing replacing it — `InputRenderer`, the `ObjectSchema` / `Field` + builder pair and `getExpressionEvaluator`: those examples are gone and the pages teach + the real surface instead. + +No published behaviour changes: no package's runtime source was touched. The +`UNGATED_DOCS` entries in `scripts/check-doc-snippet-types.mjs` are rewritten to the +diagnostic mix each page now measures — every bucket equal or lower, nothing added. diff --git a/content/docs/api/schema-reference.md b/content/docs/api/schema-reference.md index 862ca3c553..f9aa192bcc 100644 --- a/content/docs/api/schema-reference.md +++ b/content/docs/api/schema-reference.md @@ -10,7 +10,7 @@ This reference documents every ObjectUI schema type with annotated JSON examples > **Import:** All types are available from `@object-ui/types`. > > ```typescript -> import type { PageSchema, FormSchema, TableSchema, /* ... */ } from '@object-ui/types'; +> import type { PageNodeSchema, FormSchema, TableSchema, /* ... */ } from '@object-ui/types'; > ``` --- @@ -68,7 +68,7 @@ All schema types extend `BaseSchema`. These shared properties are available on e ## Layout Schemas -### PageSchema +### PageNodeSchema Top-level page container. Defines a full page with optional regions (header, sidebar, footer). @@ -196,7 +196,7 @@ A responsive grid layout. Columns can be a fixed number or responsive breakpoint | `gap` | `number` | Gap between grid items (Tailwind spacing scale). | | `children` | `SchemaNode \| SchemaNode[]` | Grid items. | -**Related:** [DivSchema](#divschema), [CardSchema](#cardschema), [DashboardSchema](#dashboardschema) +**Related:** [DivSchema](#divschema), [CardSchema](#cardschema), [DashboardComponentSchema](#dashboardcomponentschema) --- @@ -233,7 +233,7 @@ A tabbed interface for organizing content into switchable panels. | `orientation` | `"horizontal" \| "vertical"` | Tab bar orientation. | | `items` | `TabItem[]` | Tab definitions, each with `value`, `label`, `icon`, `content`, and optional `disabled`. | -**Related:** [CardSchema](#cardschema), [PageSchema](#pageschema) +**Related:** [CardSchema](#cardschema), [PageNodeSchema](#pagenodeschema) --- @@ -469,7 +469,7 @@ A chart visualization supporting multiple chart types. | `animate` | `boolean` | Enable entry animations. | | `config` | `Record` | Additional chart library configuration. | -**Related:** [DashboardSchema](#dashboardschema), [CardSchema](#cardschema) +**Related:** [DashboardComponentSchema](#dashboardcomponentschema), [CardSchema](#cardschema) --- @@ -971,7 +971,7 @@ A drag-and-drop Kanban board with columns and cards. --- -### DashboardSchema +### DashboardComponentSchema A widget-based dashboard with configurable grid layout and auto-refresh. @@ -1076,7 +1076,7 @@ A multi-view calendar for displaying and managing events. | `onEventUpdate` | `function` | Callback when an event is modified. | | `onDateChange` | `function` | Callback when the visible date range changes. | -**Related:** [ObjectViewSchema](#objectviewschema), [DashboardSchema](#dashboardschema) +**Related:** [ObjectViewSchema](#objectviewschema), [DashboardComponentSchema](#dashboardcomponentschema) --- @@ -1281,7 +1281,7 @@ Import only the types you need: ```typescript // Layout -import type { PageSchema, DivSchema, CardSchema, GridSchema, TabsSchema } from '@object-ui/types'; +import type { PageNodeSchema, DivSchema, CardSchema, GridSchema, TabsSchema } from '@object-ui/types'; // Forms import type { FormSchema, InputSchema, SelectSchema, ButtonSchema } from '@object-ui/types'; @@ -1296,7 +1296,7 @@ import type { CRUDSchema, ActionSchema, DetailSchema } from '@object-ui/types'; import type { ObjectGridSchema, ObjectFormSchema, ObjectViewSchema } from '@object-ui/types'; // Complex -import type { KanbanSchema, DashboardSchema, CalendarViewSchema } from '@object-ui/types'; +import type { KanbanSchema, DashboardComponentSchema, CalendarViewSchema } from '@object-ui/types'; // Views import type { DetailViewSchema, ViewSwitcherSchema } from '@object-ui/types'; diff --git a/content/docs/guide/building-crud-app.md b/content/docs/guide/building-crud-app.md index efab7d160a..3c7e6951ba 100644 --- a/content/docs/guide/building-crud-app.md +++ b/content/docs/guide/building-crud-app.md @@ -57,14 +57,18 @@ Add to your `src/index.css`: Create `src/setup.ts` to register the built-in component and field renderers: ```ts -import { Registry } from '@object-ui/core'; -import { registerAllComponents } from '@object-ui/components'; -import { registerAllFields } from '@object-ui/fields'; +import { initializeComponents } from '@object-ui/components'; +// Side-effect import: loading the package runs its own field registration. +import '@object-ui/fields'; -registerAllComponents(Registry); -registerAllFields(Registry); +initializeComponents(); ``` +Loading each package registers what it owns — the components and the field +widgets go into the one `ComponentRegistry` that `@object-ui/core` exports. +`initializeComponents()` takes no arguments; it exists so a bundler cannot +tree-shake the side-effect import away. + Import this file once at the top of your app entry point (`src/main.tsx` or `src/App.tsx`). ## Step 3: Define the Object Schema @@ -72,31 +76,46 @@ Import this file once at the top of your app entry point (`src/main.tsx` or `src Create `src/schemas/task.ts`. This is the metadata that drives the entire UI — grid columns, form fields, validation, and views are all derived from this schema: ```ts -import { ObjectSchema, Field } from '@object-ui/types'; +import type { FieldMetadata } from '@object-ui/types'; + +const fields: Record = { + title: { name: 'title', type: 'text', label: 'Title', required: true }, + status: { + name: 'status', + type: 'select', + label: 'Status', + defaultValue: 'Todo', + options: [ + { label: 'Backlog', value: 'Backlog' }, + { label: 'Todo', value: 'Todo' }, + { label: 'In Progress', value: 'In Progress' }, + { label: 'Review', value: 'Review' }, + { label: 'Done', value: 'Done' }, + ], + }, + priority: { + name: 'priority', + type: 'select', + label: 'Priority', + defaultValue: 'Medium', + options: [ + { label: 'Critical', value: 'Critical' }, + { label: 'High', value: 'High' }, + { label: 'Medium', value: 'Medium' }, + { label: 'Low', value: 'Low' }, + ], + }, + assignee: { name: 'assignee', type: 'text', label: 'Assignee' }, + due_date: { name: 'due_date', type: 'date', label: 'Due Date' }, + description: { name: 'description', type: 'textarea', label: 'Description' }, +}; -export const TaskSchema = ObjectSchema.create({ +export const TaskSchema = { name: 'task', label: 'Task', icon: 'check-circle-2', titleFormat: '{title}', - fields: { - title: Field.text({ - label: 'Title', - required: true, - searchable: true, - }), - status: Field.select( - ['Backlog', 'Todo', 'In Progress', 'Review', 'Done'], - { label: 'Status', defaultValue: 'Todo' } - ), - priority: Field.select( - ['Critical', 'High', 'Medium', 'Low'], - { label: 'Priority', defaultValue: 'Medium' } - ), - assignee: Field.text({ label: 'Assignee' }), - due_date: Field.date({ label: 'Due Date' }), - description: Field.textarea({ label: 'Description' }), - }, + fields, list_views: { all: { label: 'All Tasks', @@ -109,10 +128,16 @@ export const TaskSchema = ObjectSchema.create({ sort: [['priority', 'asc']], }, }, -}); +}; ``` -Each `Field.*()` call produces a `FieldMetadata` entry that ObjectUI uses to choose the correct renderer, apply validation, and generate form controls automatically. +An object's metadata is a plain document — the same shape a backend serves from +`DataSource.getObjectSchema()` — so it is written as a literal rather than built +by a helper. `FieldMetadata` is the union every field entry belongs to (`text`, +`select`, `date`, `textarea`, …), and typing the `fields` record against it is +what makes a wrong `type` or a misspelled key fail at compile time. ObjectUI +reads those entries to choose the renderer, apply validation, and generate form +controls automatically. ## Step 4: Create a Data Source diff --git a/content/docs/guide/component-registry.md b/content/docs/guide/component-registry.md index df2fe6c7ff..601109512e 100644 --- a/content/docs/guide/component-registry.md +++ b/content/docs/guide/component-registry.md @@ -14,10 +14,11 @@ Schema Type → Component Registry → React Component ## Getting the Registry -```tsx -import { getComponentRegistry } from '@object-ui/react' +`ComponentRegistry` is a process-level singleton exported by `@object-ui/core`. +Import it directly — there is no accessor function and nothing to construct: -const registry = getComponentRegistry() +```tsx +import { ComponentRegistry } from '@object-ui/core' ``` ## Registering Components @@ -27,38 +28,33 @@ const registry = getComponentRegistry() The easiest way to get started is to register all default components: ```tsx -import { registerDefaultRenderers } from '@object-ui/components' +import { initializeComponents } from '@object-ui/components' +// Side-effect import: loading the package runs its own field registration. +import '@object-ui/fields' // Call once at app initialization -registerDefaultRenderers() +initializeComponents() ``` +Loading each package registers what it owns — the components and the field +widgets both land in the one `ComponentRegistry`; `initializeComponents()` exists +so a bundler cannot tree-shake the side-effect import away. The individual +renderers are not exported for hand-registration: registration is what loading +the package does. + This registers all built-in components like: - Forms: `input`, `textarea`, `select`, `checkbox`, etc. - Data: `table`, `list`, `card`, `tree`, etc. - Layout: `page`, `grid`, `flex`, `container`, etc. - Feedback: `alert`, `dialog`, `toast`, etc. -### Registering Individual Components - -Register specific components one at a time: - -```tsx -import { getComponentRegistry } from '@object-ui/react' -import { InputRenderer } from '@object-ui/components' - -const registry = getComponentRegistry() - -registry.register('input', InputRenderer) -``` - ### Registering Custom Components Create and register your own components: ```tsx -import { getComponentRegistry } from '@object-ui/react' -import type { BaseSchema } from '@object-ui/core' +import { ComponentRegistry } from '@object-ui/core' +import type { BaseSchema } from '@object-ui/types' interface MyComponentSchema extends BaseSchema { type: 'my-component' @@ -75,8 +71,7 @@ function MyComponent(props: MyComponentSchema) { ) } -const registry = getComponentRegistry() -registry.register('my-component', MyComponent) +ComponentRegistry.register('my-component', MyComponent) ``` Now you can use it in schemas: @@ -125,18 +120,14 @@ function MyRenderer(props: ComponentProps) { Register components with additional metadata: ```tsx -registry.register('my-component', MyComponent, { - displayName: 'My Custom Component', +ComponentRegistry.register('my-component', MyComponent, { + label: 'My Custom Component', category: 'Custom', icon: 'component-icon', - description: 'A custom component for special use cases', - schema: { - type: 'object', - properties: { - title: { type: 'string' }, - content: { type: 'string' } - } - } + inputs: [ + { name: 'title', type: 'string', label: 'Title' }, + { name: 'content', type: 'string', label: 'Content' } + ] }) ``` @@ -147,13 +138,8 @@ This metadata is used by the Visual Designer to provide better editing experienc Register components that load on demand: ```tsx -import { lazy } from 'react' - -const HeavyComponent = lazy(() => import('./HeavyComponent')) - -registry.register('heavy-component', HeavyComponent, { - lazy: true -}) +// The loader runs the first time a schema asks for `heavy-component`. +ComponentRegistry.registerLazy('heavy-component', () => import('./HeavyComponent')) ``` ### Overriding Built-in Components @@ -161,13 +147,15 @@ registry.register('heavy-component', HeavyComponent, { Override default components with your own: ```tsx -import { registerDefaultRenderers } from '@object-ui/components' +import { ComponentRegistry } from '@object-ui/core' +import { initializeComponents } from '@object-ui/components' +import '@object-ui/fields' // Register defaults first -registerDefaultRenderers() +initializeComponents() // Override specific component -registry.register('button', MyCustomButton) +ComponentRegistry.register('button', MyCustomButton) ``` ## Component Categories @@ -250,14 +238,14 @@ Default components are organized by category: ### Get All Registered Types ```tsx -const types = registry.getRegisteredTypes() +const types = ComponentRegistry.getAllTypes() console.log(types) // ['input', 'button', 'form', ...] ``` ### Check if Type is Registered ```tsx -if (registry.has('my-component')) { +if (ComponentRegistry.has('my-component')) { console.log('Component is registered') } ``` @@ -265,10 +253,10 @@ if (registry.has('my-component')) { ### Get Component Metadata ```tsx -const metadata = registry.getMetadata('input') +const metadata = ComponentRegistry.getMeta('input') console.log(metadata) // { -// displayName: 'Input', +// label: 'Input', // category: 'Form', // icon: 'input-icon', // ... @@ -281,9 +269,10 @@ console.log(metadata) ```tsx // main.tsx or App.tsx -import { registerDefaultRenderers } from '@object-ui/components' +import { initializeComponents } from '@object-ui/components' +import '@object-ui/fields' -registerDefaultRenderers() +initializeComponents() function App() { // Your app code @@ -293,7 +282,7 @@ function App() { ### 2. Use TypeScript for Custom Components ```tsx -import type { BaseSchema } from '@object-ui/core' +import type { BaseSchema } from '@object-ui/types' interface CustomSchema extends BaseSchema { type: 'custom' @@ -314,12 +303,11 @@ Use kebab-case for component types: ### 4. Provide Meaningful Metadata ```tsx -registry.register('rating', RatingComponent, { - displayName: 'Star Rating', +ComponentRegistry.register('rating', RatingComponent, { + label: 'Star Rating', category: 'Form', icon: 'star', - description: 'A 5-star rating input component', - tags: ['form', 'input', 'rating'] + labelling: 'group' }) ``` @@ -346,27 +334,26 @@ Group related components into plugin packages: ```tsx // @my-org/objectui-plugin-charts -import { getComponentRegistry } from '@object-ui/react' +import { ComponentRegistry } from '@object-ui/core' import { BarChart } from './BarChart' import { LineChart } from './LineChart' import { PieChart } from './PieChart' export function registerChartComponents() { - const registry = getComponentRegistry() - - registry.register('bar-chart', BarChart) - registry.register('line-chart', LineChart) - registry.register('pie-chart', PieChart) + ComponentRegistry.register('bar-chart', BarChart) + ComponentRegistry.register('line-chart', LineChart) + ComponentRegistry.register('pie-chart', PieChart) } ``` Usage: ```tsx -import { registerDefaultRenderers } from '@object-ui/components' +import { initializeComponents } from '@object-ui/components' +import '@object-ui/fields' import { registerChartComponents } from '@my-org/objectui-plugin-charts' -registerDefaultRenderers() +initializeComponents() registerChartComponents() ``` @@ -376,8 +363,8 @@ Here's a complete example of a custom form component: ```tsx import { forwardRef } from 'react' -import { getComponentRegistry } from '@object-ui/react' -import type { BaseSchema } from '@object-ui/core' +import { ComponentRegistry } from '@object-ui/core' +import type { BaseSchema } from '@object-ui/types' import { cn } from '@/lib/utils' interface RatingSchema extends BaseSchema { @@ -434,22 +421,17 @@ const RatingComponent = forwardRef( RatingComponent.displayName = 'Rating' // Register the component -const registry = getComponentRegistry() -registry.register('rating', RatingComponent, { - displayName: 'Star Rating', +ComponentRegistry.register('rating', RatingComponent, { + label: 'Star Rating', category: 'Form', - description: 'A star rating input component', - schema: { - type: 'object', - properties: { - name: { type: 'string' }, - label: { type: 'string' }, - maxStars: { type: 'number', default: 5 }, - required: { type: 'boolean' }, - disabled: { type: 'boolean' } - }, - required: ['name'] - } + labelling: 'group', + inputs: [ + { name: 'name', type: 'string', label: 'Name', required: true }, + { name: 'label', type: 'string', label: 'Label' }, + { name: 'maxStars', type: 'number', label: 'Max stars', defaultValue: 5 }, + { name: 'required', type: 'boolean', label: 'Required' }, + { name: 'disabled', type: 'boolean', label: 'Disabled' } + ] }) export { RatingComponent } diff --git a/content/docs/guide/expressions.md b/content/docs/guide/expressions.md index 303bbf37a9..170ac294fd 100644 --- a/content/docs/guide/expressions.md +++ b/content/docs/guide/expressions.md @@ -530,44 +530,48 @@ This logs all expression evaluations to the console. ### Custom Functions -Extend the expression context with custom functions: +There is no global evaluator to extend: `SchemaRenderer` builds a fresh +`ExpressionEvaluator` for each evaluation, so a function has to reach it through +the evaluation context. Anything callable you put in the context is callable in +an expression, under exactly the name you gave it: ```tsx -import { getExpressionEvaluator } from '@object-ui/core' +import { evaluateExpression } from '@object-ui/core' -const evaluator = getExpressionEvaluator() +const formatCurrency = (value: number) => + new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(value) -evaluator.registerFunction('formatCurrency', (value: number) => { - return new Intl.NumberFormat('en-US', { - style: 'currency', - currency: 'USD' - }).format(value) -}) +// => '$1,234.50' +evaluateExpression('${formatCurrency(price)}', { formatCurrency, price: 1234.5 }) ``` -Use in schemas: +That is the direct-evaluation path. A component expression rendered by +`SchemaRenderer` resolves against the scope the renderer itself builds — the +provider's data source (as `data`), the host scope (`user` / `current_user`) and +page variables — so a function you registered elsewhere is not reachable from a +schema expression. Compute the value before it reaches the schema, and bind the +result. -```json -{ - "type": "text", - "value": "${formatCurrency(price)}" -} -``` +Hold an evaluator when you want one context reused — construct it, then call +`evaluate`: -### Custom Operators +```tsx +import { ExpressionEvaluator } from '@object-ui/core' -Register custom operators for domain-specific logic: +const evaluator = new ExpressionEvaluator({ user: { role: 'admin' } }) -```tsx -evaluator.registerOperator('contains', (array, item) => { - return array.includes(item) -}) +evaluator.evaluate('${user.role === "admin"}') ``` +### Custom Operators + +Expressions are JavaScript, evaluated against the context — operators are the +language's own. A membership test is written with the array method: + ```json { "type": "button", - "visibleOn": "${user.permissions contains 'admin'}" + "visibleOn": "${user.permissions.includes('admin')}" } ``` diff --git a/content/docs/guide/schema-overview.md b/content/docs/guide/schema-overview.md index 4a3ada94ee..1c5583ce4c 100644 --- a/content/docs/guide/schema-overview.md +++ b/content/docs/guide/schema-overview.md @@ -25,7 +25,7 @@ ObjectUI includes enterprise-grade capabilities to build production-ready applic Define your entire application structure with navigation, branding, and global settings. ```typescript -const app: AppSchema = { +const app: AppComponentSchema = { type: 'app', title: 'My Application', layout: 'sidebar', @@ -48,13 +48,14 @@ const app: AppSchema = { Dynamic theming with light/dark modes, color palettes, and typography. ```typescript -const theme: ThemeSchema = { +const theme: ThemeComponentSchema = { type: 'theme', mode: 'dark', themes: [{ - name: 'professional', - light: { primary: '#3b82f6', ... }, - dark: { primary: '#60a5fa', ... } + name: 'professional-dark', + label: 'Professional (Dark)', + mode: 'dark', + colors: { primary: '#60a5fa', background: '#0f172a', ... } }] }; ``` @@ -105,7 +106,7 @@ const action: ActionSchema = { Enterprise reports with aggregation, export, and scheduling. ```typescript -const report: ReportSchema = { +const report: ReportComponentSchema = { type: 'report', title: 'Sales Report', fields: [ @@ -160,10 +161,10 @@ const block: BlockSchema = { | Schema | Purpose | Best For | |--------|---------|----------| -| **AppSchema** | Application structure | Multi-page apps, dashboards | -| **ThemeSchema** | Visual theming | Brand consistency, white-labeling | +| **AppComponentSchema** | Application structure | Multi-page apps, dashboards | +| **ThemeComponentSchema** | Visual theming | Brand consistency, white-labeling | | **Enhanced Actions** | Complex workflows | API integration, multi-step processes | -| **ReportSchema** | Data reporting | Analytics, business intelligence | +| **ReportComponentSchema** | Data reporting | Analytics, business intelligence | | **BlockSchema** | Reusable components | Marketing pages, component libraries | ## View Components @@ -202,10 +203,10 @@ Import the type definitions you need: ```typescript import type { - AppSchema, - ThemeSchema, + AppComponentSchema, + ThemeComponentSchema, ActionSchema, - ReportSchema, + ReportComponentSchema, BlockSchema } from '@object-ui/types'; ``` @@ -216,14 +217,14 @@ For runtime validation, use the included Zod schemas: ```typescript import { - AppSchema, - ThemeSchema, + AppComponentSchema, + ThemeComponentSchema, ActionSchema, - ReportSchema, + ReportComponentSchema, BlockSchema } from '@object-ui/types/zod'; -const result = AppSchema.safeParse(myConfig); +const result = AppComponentSchema.safeParse(myConfig); if (result.success) { // Valid configuration const app = result.data; @@ -238,10 +239,10 @@ if (result.success) { Here's a complete example showing how to build a simple CRM application using ObjectUI schemas: ```typescript -import type { AppSchema, ThemeSchema } from '@object-ui/types'; +import type { AppComponentSchema, ThemeComponentSchema } from '@object-ui/types'; // Define your application structure -const app: AppSchema = { +const app: AppComponentSchema = { type: 'app', name: 'enterprise-crm', title: 'Enterprise CRM', @@ -277,14 +278,23 @@ const app: AppSchema = { }; // Configure your theme -const theme: ThemeSchema = { +const theme: ThemeComponentSchema = { type: 'theme', - mode: 'system', - themes: [{ - name: 'professional', - light: { primary: '#3b82f6', background: '#fff' }, - dark: { primary: '#60a5fa', background: '#0f172a' } - }], + mode: 'auto', + themes: [ + { + name: 'professional-light', + label: 'Professional (Light)', + mode: 'light', + colors: { primary: '#3b82f6', background: '#ffffff' } + }, + { + name: 'professional-dark', + label: 'Professional (Dark)', + mode: 'dark', + colors: { primary: '#60a5fa', background: '#0f172a' } + } + ], allowSwitching: true, persistPreference: true }; @@ -304,9 +314,9 @@ ObjectUI provides advanced schemas and capabilities for enterprise applications: ObjectUI includes these top-level schemas: -- **`AppSchema`** - Define your entire application structure -- **`ThemeSchema`** - Configure themes and color palettes -- **`ReportSchema`** - Create data reports with aggregation +- **`AppComponentSchema`** - Define your entire application structure +- **`ThemeComponentSchema`** - Configure themes and color palettes +- **`ReportComponentSchema`** - Create data reports with aggregation - **`BlockSchema`** - Build reusable component blocks ### Enhanced ActionSchema @@ -338,9 +348,9 @@ ObjectUI includes enhanced view components: npm install @object-ui/types@latest ``` -2. **Configure application** - Define your app structure with AppSchema (optional) +2. **Configure application** - Define your app structure with AppComponentSchema (optional) -3. **Set up theming** - Add a ThemeSchema for consistent styling (optional) +3. **Set up theming** - Add a ThemeComponentSchema for consistent styling (optional) 4. **Implement actions** - Use advanced action features like `confirm` and callbacks diff --git a/content/docs/guide/schema-rendering.md b/content/docs/guide/schema-rendering.md index d0eaca1b29..4f7ca6f4e7 100644 --- a/content/docs/guide/schema-rendering.md +++ b/content/docs/guide/schema-rendering.md @@ -20,10 +20,12 @@ The `SchemaRenderer` is the primary component that interprets your JSON schemas: ```tsx import { SchemaRenderer } from '@object-ui/react' -import { registerDefaultRenderers } from '@object-ui/components' +import { initializeComponents } from '@object-ui/components' +// Side-effect import: loading the package runs its own field registration. +import '@object-ui/fields' // Register components once at app initialization -registerDefaultRenderers() +initializeComponents() function App() { const schema = { @@ -97,12 +99,11 @@ Use expression syntax `${}` to reference data: The schema renderer uses a component registry to map schema types to React components: ```tsx -import { getComponentRegistry } from '@object-ui/react' - -const registry = getComponentRegistry() +import { ComponentRegistry } from '@object-ui/core' +// `ComponentRegistry` is a process-level singleton — import it, do not construct one. // Register a custom component -registry.register('my-component', MyComponent) +ComponentRegistry.register('my-component', MyComponent) // Now you can use it in schemas const schema = { @@ -289,18 +290,18 @@ The renderer includes built-in error boundaries: Full type safety for your schemas: ```tsx -import type { PageSchema, FormSchema } from '@object-ui/core' +import type { PageNodeSchema, FormSchema } from '@object-ui/types' + +const form: FormSchema = { + type: "form", + // TypeScript will validate this entire structure + fields: [] +} -const schema: PageSchema = { +const schema: PageNodeSchema = { type: "page", title: "Typed Page", - body: { - type: "form", - // TypeScript will validate this entire structure - body: [ - // ... - ] - } + body: [form] } ``` diff --git a/content/docs/guide/troubleshooting.md b/content/docs/guide/troubleshooting.md index b3a4cb1edc..1def2c9ce9 100644 --- a/content/docs/guide/troubleshooting.md +++ b/content/docs/guide/troubleshooting.md @@ -154,8 +154,9 @@ import type { FormSchema } from '@object-ui/types/form'; import type { LayoutSchema } from '@object-ui/types/layout'; import type { DataDisplaySchema } from '@object-ui/types/data-display'; -// Zod validation schemas -import { componentSchema } from '@object-ui/types/zod'; +// Zod validation schemas — same PascalCase names as the types, so alias one of +// the two when a module imports both. +import { ComponentSchema as ComponentSchemaValidator } from '@object-ui/types/zod'; ``` The `@object-ui/types` package exports multiple entry points (`base`, `layout`, `form`, `data-display`, `feedback`, `overlay`, `navigation`, `complex`, `data`, `zod`). Check `packages/types/package.json` for the full list. diff --git a/scripts/check-doc-snippet-types.mjs b/scripts/check-doc-snippet-types.mjs index 14f9e44560..9592f53e32 100644 --- a/scripts/check-doc-snippet-types.mjs +++ b/scripts/check-doc-snippet-types.mjs @@ -231,9 +231,17 @@ const TS_FENCE_LANGUAGES = new Set(['ts', 'tsx', 'typescript']); * made visible: the collector now reads `.md`, and an entry with a measured reason * is what a page that cannot pass yet is owed. They are DISCLOSED debt, not new * debt — every one of them was equally unverified before, just unnamed. Their - * reasons carry the same measured diagnostic mix as the rest, and several name - * the missing export by hand, because a documented symbol a package does not - * export is the reader-visible half (objectui#5160). + * reasons carry the same measured diagnostic mix as the rest, and a symbol a + * package does not export is called out by name, because that is the + * reader-visible half (objectui#5160). + * + * objectui#5343 then read that list back and cleared it for the getting-started + * pages: no entry for `content/docs/guide/**` or for + * `content/docs/api/schema-reference.md` names a missing export any more. Every + * symbol those pages documented now exists on the built `dist/index.d.ts`, so + * their reasons record what each fabricated name BECAME instead. Exactly one + * entry still names a missing export — `content/docs/utilities/index.md` + * (`ObjectStackProvider`), a different directory and a different card. * * The reasons are deliberately concrete about WHAT would have to change, because * "does not compile" is three different jobs: a page whose snippets reference @@ -248,9 +256,10 @@ const TS_FENCE_LANGUAGES = new Set(['ts', 'tsx', 'typescript']); const UNGATED_DOCS = { 'content/docs/api/schema-reference.md': '1 undefined-name diagnostic(s) — blocks continue an earlier block, or use ambient names the ' + - 'page never defines; plus TS2305x1 TS2724x1 — candidate real defects, un-triaged. The ' + - 'missing-export diagnostics name `DashboardSchema` (@object-ui/types), `PageSchema` ' + - '(@object-ui/types) — the reader-visible half of this entry', + 'page never defines. This entry read TS2305x1 TS2724x1 until objectui#5343: both were ' + + 'fabricated exports of @object-ui/types, re-spelled to the names the built `dist/index.d.ts` ' + + 'declares — `PageSchema` → `PageNodeSchema` (renamed by objectui#3074, which split the ' + + 'renderer NODE off the spec document type) and `DashboardSchema` → `DashboardComponentSchema`', 'content/docs/guide/architecture-overview.md': '1 parse diagnostic(s) — blocks fenced `ts` that are bare object literals or elided bodies; 5 ' + 'undefined-name diagnostic(s) — blocks continue an earlier block, or use ambient names the ' + @@ -264,28 +273,38 @@ const UNGATED_DOCS = { 'content/docs/guide/building-crud-app.md': '1 parse diagnostic(s) — blocks fenced `ts` that are bare object literals or elided bodies; ' + '20 undefined-name diagnostic(s) — blocks continue an earlier block, or use ambient names the ' + - 'page never defines; 4 unresolved-module diagnostic(s); plus TS2305x2 TS2339x1 TS2345x1 ' + - 'TS2554x1 TS2724x1 TS2882x1 — candidate real defects, un-triaged. The missing-export ' + - 'diagnostics name `Field` (@object-ui/types), `ObjectSchema` (@object-ui/types), ' + - '`registerAllComponents` (@object-ui/components) — the reader-visible half of this entry', + 'page never defines; 4 unresolved-module diagnostic(s); plus TS2339x1 TS2345x1 TS2882x1 — ' + + 'candidate real defects, un-triaged. This entry read TS2305x2 TS2554x1 TS2724x1 until ' + + 'objectui#5343: `registerAllComponents` (@object-ui/components) and the `ObjectSchema` / ' + + '`Field` builder pair (@object-ui/types) were fabricated. Registration is now what LOADING ' + + 'the packages does (`initializeComponents()` plus the side-effect `@object-ui/fields` ' + + 'import), which also retired the `registerAllFields(Registry)` arity error, and the object ' + + 'metadata is the plain document a data source serves, with its `fields` record typed ' + + '`Record`', 'content/docs/guide/component-registry.md': '3 parse diagnostic(s) — blocks fenced `ts` that are bare object literals or elided bodies; ' + - '51 undefined-name diagnostic(s) — blocks continue an earlier block, or use ambient names the ' + - 'page never defines; 6 unresolved-module diagnostic(s); plus TS2305x13 TS2339x1 — candidate ' + - 'real defects, un-triaged. The missing-export diagnostics name `getComponentRegistry` ' + - '(@object-ui/react) x5, `registerDefaultRenderers` (@object-ui/components) x4, `BaseSchema` ' + - '(@object-ui/core) x3, `InputRenderer` (@object-ui/components) — the reader-visible half of ' + - 'this entry', + '50 undefined-name diagnostic(s) — blocks continue an earlier block, or use ambient names the ' + + 'page never defines; 6 unresolved-module diagnostic(s). This entry read TS2305x13 TS2339x1 ' + + 'until objectui#5343, which cleared the page of fabricated exports: `getComponentRegistry` ' + + '(@object-ui/react) x5 → the `ComponentRegistry` singleton @object-ui/core exports, ' + + '`registerDefaultRenderers` (@object-ui/components) x4 → `initializeComponents()` plus the ' + + 'side-effect `@object-ui/fields` import, `BaseSchema` (@object-ui/core) x3 → @object-ui/types ' + + '(which is also what retired the TS2339, since the real `BaseSchema` declares `className`), ' + + 'and `InputRenderer` (@object-ui/components), which nothing replaces — the built-in renderers ' + + 'are registered by loading their package, never handed out one by one', 'content/docs/guide/deployment.md': '6 undefined-name diagnostic(s) — blocks continue an earlier block, or use ambient names the ' + 'page never defines; 1 unresolved-module diagnostic(s); plus TS2322x1 — candidate real ' + 'defects, un-triaged', 'content/docs/guide/expressions.md': - '8 parse diagnostic(s) — blocks fenced `ts` that are bare object literals or elided bodies; 6 ' + + '8 parse diagnostic(s) — blocks fenced `ts` that are bare object literals or elided bodies; 5 ' + 'undefined-name diagnostic(s) — blocks continue an earlier block, or use ambient names the ' + - 'page never defines; plus TS2724x1 TS7006x3 — candidate real defects, un-triaged. The ' + - 'missing-export diagnostics name `getExpressionEvaluator` (@object-ui/core) — the ' + - 'reader-visible half of this entry', + 'page never defines; plus TS7006x1 — a candidate real defect, un-triaged. This entry read ' + + 'TS2724x1 TS7006x3 until objectui#5343: `getExpressionEvaluator` (@object-ui/core) was ' + + 'fabricated and nothing replaces it — there is no process-level evaluator, `SchemaRenderer` ' + + 'constructs a fresh `ExpressionEvaluator` per evaluation, so the section now teaches the real ' + + 'surface (`evaluateExpression(expr, context)` / `new ExpressionEvaluator(context)`) and the ' + + 'two implicit-any parameters went with the `registerOperator` example it rooted', 'content/docs/guide/layout.md': '21 parse diagnostic(s) — blocks fenced `ts` that are bare object literals or elided bodies; ' + '20 undefined-name diagnostic(s) — blocks continue an earlier block, or use ambient names the ' + @@ -317,21 +336,25 @@ const UNGATED_DOCS = { 'undefined-name diagnostic(s) — blocks continue an earlier block, or use ambient names the ' + 'page never defines; 1 unresolved-module diagnostic(s)', 'content/docs/guide/schema-overview.md': - '9 parse diagnostic(s) — blocks fenced `ts` that are bare object literals or elided bodies; 2 ' + + '8 parse diagnostic(s) — blocks fenced `ts` that are bare object literals or elided bodies; 2 ' + 'undefined-name diagnostic(s) — blocks continue an earlier block, or use ambient names the ' + - 'page never defines; plus TS2305x2 TS2724x6 — candidate real defects, un-triaged. The ' + - 'missing-export diagnostics name `AppSchema` (@object-ui/types) x2, `ThemeSchema` ' + - '(@object-ui/types) x2, `AppSchema` (@object-ui/types/zod), `ReportSchema` ' + - '(@object-ui/types), `ReportSchema` (@object-ui/types/zod), `ThemeSchema` ' + - '(@object-ui/types/zod) — the reader-visible half of this entry', + 'page never defines. This entry read TS2305x2 TS2724x6 until objectui#5343: `AppSchema`, ' + + '`ThemeSchema` and `ReportSchema` were fabricated in BOTH the type and the ' + + '`@object-ui/types/zod` entry, and are re-spelled `AppComponentSchema`, ' + + '`ThemeComponentSchema`, `ReportComponentSchema` at every site including the prose. The ' + + 'annotations that renaming made real then rejected two more falsehoods in the theme example ' + + '(`mode: \'system\'`, and per-theme `light`/`dark` palettes where the spec `Theme` carries one ' + + '`colors` map), fixed in the same pass so the page could not get worse', 'content/docs/guide/schema-rendering.md': '8 parse diagnostic(s) — blocks fenced `ts` that are bare object literals or elided bodies; ' + '10 undefined-name diagnostic(s) — blocks continue an earlier block, or use ambient names the ' + - 'page never defines; 1 unresolved-module diagnostic(s); plus TS2305x4 TS2322x1 TS2451x2 ' + - 'TS7006x5 — candidate real defects, un-triaged. The missing-export diagnostics name ' + - '`FormSchema` (@object-ui/core), `getComponentRegistry` (@object-ui/react), `PageSchema` ' + - '(@object-ui/core), `registerDefaultRenderers` (@object-ui/components) — the reader-visible ' + - 'half of this entry', + 'page never defines; 1 unresolved-module diagnostic(s); plus TS2322x1 TS2451x2 TS7006x5 — ' + + 'candidate real defects, un-triaged. This entry read TS2305x4 until objectui#5343: ' + + '`registerDefaultRenderers` (@object-ui/components) → `initializeComponents()` plus the ' + + 'side-effect `@object-ui/fields` import, `getComponentRegistry` (@object-ui/react) → the ' + + '`ComponentRegistry` singleton @object-ui/core exports, and `PageSchema` / `FormSchema` were ' + + 'claimed from @object-ui/core while they live in @object-ui/types (`PageNodeSchema` there, ' + + 'whose `body` is `SchemaNode[]` — the typed example is written as an array now)', 'content/docs/guide/theming.md': '3 parse diagnostic(s) — blocks fenced `ts` that are bare object literals or elided bodies; ' + '23 undefined-name diagnostic(s) — blocks continue an earlier block, or use ambient names the ' + @@ -339,9 +362,11 @@ const UNGATED_DOCS = { 'real defects, un-triaged', 'content/docs/guide/troubleshooting.md': '8 undefined-name diagnostic(s) — blocks continue an earlier block, or use ambient names the ' + - 'page never defines; 1 unresolved-module diagnostic(s); plus TS2322x1 TS2339x2 TS2559x1 ' + - 'TS2724x1 — candidate real defects, un-triaged. The missing-export diagnostics name ' + - '`componentSchema` (@object-ui/types/zod) — the reader-visible half of this entry', + 'page never defines; 1 unresolved-module diagnostic(s); plus TS2322x1 TS2339x2 TS2559x1 — ' + + 'candidate real defects, un-triaged. This entry read TS2724x1 until objectui#5343: the zod ' + + 'entry exports `ComponentSchema`, not `componentSchema` — and because the same block imports ' + + 'the TYPE of that name from @object-ui/types, the validator is imported under an alias rather ' + + 'than colliding with it', 'content/docs/guide/user-state-persistence.md': '10 parse diagnostic(s) — blocks fenced `ts` that are bare object literals or elided bodies; ' + '1 undefined-name diagnostic(s) — blocks continue an earlier block, or use ambient names the ' +