From ce711b6ff6e52cbebee8ffeca2e4f1e535a8a1fd Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 19 Aug 2026 06:54:49 +0000 Subject: [PATCH] docs(plugin-view): re-teach the canonical table keys now that #5102 landed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #5271 objectui#5102 (PR #5274, merged) made ObjectView forward the canonical `table.pagination` / `.selection` / `.filter` / `.sort` on every rendering path, keeping `pageSize` / `selectable` / `defaultFilters` / `defaultSort` as working aliases. The two docs pages PR #5101 (README) and PR #5109 (docs-site mirror) wrote against the pre-#5102 reality — legacy-only — and now teach a stale caveat. Re-teach the canonical spellings as the recommended form without implying the legacy ones stopped working, and state the precedence read directly off the landed `ObjectView.tsx` / `ObjectGrid.tsx`: canonical wins when both are written; an active named view's own filter/sort still outranks anything on `table`; `table.columns` stays out of scope (#5269, still open, grid-path only). Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01RV6yuVCxymHYE16PL9vQkE --- content/docs/plugins/plugin-view.mdx | 95 +++++++++++++++++++++------- packages/plugin-view/README.md | 70 +++++++++++++++----- 2 files changed, 128 insertions(+), 37 deletions(-) diff --git a/content/docs/plugins/plugin-view.mdx b/content/docs/plugins/plugin-view.mdx index eb0fdd07a..7e91aac52 100644 --- a/content/docs/plugins/plugin-view.mdx +++ b/content/docs/plugins/plugin-view.mdx @@ -119,24 +119,75 @@ object through. Anything else you put in them is ignored: | Sub-config | Keys `ObjectView` forwards | | --- | --- | -| `table` | `columns`, `fields`, `title`, `description`, `defaultFilters`, `defaultSort`, `pageSize`, `selectable`, `operations`, `className` | +| `table` | `columns`, `fields`, `title`, `description`, `filter`, `defaultFilters`, `sort`, `defaultSort`, `pagination`, `pageSize`, `selection`, `selectable`, `operations`, `className` | | `form` | `fields`, `customFields`, `sections`, `groups`, `layout`, `columns`, `title`, `description`, `subforms`, `buttons`, `defaults`, `initialValues`, `readOnly`, `showSubmit`, `submitText`, `showCancel`, `cancelText`, `showReset`, `className` | -The forwarding is literal, key by key (`ObjectView.tsx:833-848` for `table`, -`:857-890` for `form`), which is why the list is worth reading: page size is -`table.pageSize` and **not** `table.pagination` — the latter is a declared -`ObjectGridSchema` key, but it is not one of the keys `ObjectView` forwards, so -on an `object-view` node it has no effect. - -That is one instance of a general point: several of the forwarded `table` keys -are the ones `ObjectGridSchema` marks legacy — `fields`, `pageSize`, -`selectable`, `defaultFilters` and `defaultSort` each have a newer counterpart -there (`columns`, `pagination`, `selection`, `filter`, `sort`). `ObjectView` -forwards the legacy spellings, so on an `object-view` node those are the ones -that take effect. `columns` is the exception — it is forwarded alongside -`fields` and preferred over it. Shapes follow `ObjectGridSchema`: -`defaultSort` is a single `{ field, order }` object and `defaultFilters` is a -plain record of field to value. +The forwarding is literal, key by key, spread across three sites in +`ObjectView.tsx` — the non-grid data fetch (around `:604-611`), the grid +schema (around `:1041-1078`), and the schema handed to a host-supplied list +renderer (around `:1201-1209`) — so the four keys below behave the same on +every rendering path. + +#### Canonical keys now take effect (objectui#5102) + +Four of the forwarded `table` keys are pairs — a canonical `ObjectGridSchema` +key and the `@deprecated` legacy spelling it replaced. Both now work; write +the canonical one: + +| write this (canonical) | not this (legacy alias — still works) | +| --- | --- | +| `pagination: { pageSize, pageSizeOptions? }` | `pageSize: number` | +| `selection: { type: 'single' \| 'multiple' \| 'none' }` | `selectable: boolean \| 'single' \| 'multiple'` | +| `filter: [{ field, operator, value }, …]` (same shape as a named view's `filter`) | `defaultFilters: Record` (equality-only) | +| `sort: 'field direction'` or `SortConfig[]` | `defaultSort: { field, order }` (**no string form** — that arity only exists on `sort`) | + +Before objectui#5102, `pagination` / `selection` / `filter` / `sort` had **no +read point at all** in this file: an author who wrote the canonical shape +`ObjectGridSchema`'s own JSDoc recommends got a view that compiled, read +correctly, and silently did nothing. That is fixed — the legacy spellings on +the right are not going away, they are simply no longer the ones to reach for. + +**When a key is written both ways, the canonical spelling wins** — that is +`ObjectGrid`'s own existing resolution (`schema.pagination?.pageSize || +schema.pageSize`; `if (schema.selection?.type) … else if (schema.selectable +!== undefined)`; `schemaFilter !== undefined ? … : schema.defaultFilters`; +`schemaSort ?? (schema.defaultSort ? [schema.defaultSort] : undefined)`), and +`ObjectView` defers to it by forwarding both slots rather than re-resolving +the pair itself: + +```typescript +import type { ObjectViewSchema } from '@object-ui/types'; + +const bothSpellingsWritten: ObjectViewSchema = { + type: 'object-view', + objectName: 'products', + table: { + pagination: { pageSize: 10 }, // wins + pageSize: 50, // ignored while `pagination` is present + }, +}; +``` + +⚠️ **`filter` / `sort` have one more tier ahead of `table` entirely**, and it +predates this change: an **active named view's own** `filter` / `sort` +(`listViews..filter` / `.sort`) always outranks anything written on +`table` — `table.filter` does **not** universally win over the legacy +`table.defaultFilters`, it wins only when no active named view supplies its +own filter. In order, highest first: the active named view's `filter`/`sort`, +then `table.filter`/`table.sort`, then +`table.defaultFilters`/`table.defaultSort`. If you never write `listViews`, +that first tier never applies. + +`pagination` and `selection` have no such tier, and no effect outside the +grid: `defaultViewType: 'kanban' | 'gallery' | 'calendar' | 'timeline' | +'gantt' | 'map'` don't page or multi-select, so `ObjectView` never forwards +either spelling to those renderers. + +`columns` is the one forwarded `table` key that is **not** part of this +canonical/legacy story, and its gap is still open: it is forwarded on the grid +path only (the row above, and the section below), so on a non-grid +`defaultViewType` the field list still comes from `table.fields` +(objectui#5269). ## Usage @@ -209,7 +260,7 @@ const userDirectory: ObjectViewSchema = { defaultViewType: 'grid', table: { columns: ['name', 'email', 'role', 'created_at'], - defaultSort: { field: 'created_at', order: 'desc' }, + sort: 'created_at desc', // or [{ field: 'created_at', order: 'desc' }] }, }; ``` @@ -301,8 +352,8 @@ opening a drawer, so the host route owns the form. ### Read/List -Search, filter and sort are toolbar toggles; the column set, default filter, -default sort and page size live in `table`: +Search, filter and sort are toolbar toggles; the column set, filter, sort and +page size live in `table`: ```typescript import type { ObjectViewSchema } from '@object-ui/types'; @@ -316,8 +367,8 @@ const productList: ObjectViewSchema = { showSort: true, table: { columns: ['name', 'price', 'category'], - defaultFilters: { category: 'electronics' }, - pageSize: 25, + filter: [{ field: 'category', operator: 'equals', value: 'electronics' }], + pagination: { pageSize: 25 }, }, }; ``` @@ -492,7 +543,7 @@ const contactView: ObjectViewSchema = { showSort: true, table: { columns: ['first_name', 'last_name', 'email', 'company'], - pageSize: 25, + pagination: { pageSize: 25 }, }, }; diff --git a/packages/plugin-view/README.md b/packages/plugin-view/README.md index e9bcf7c51..df295d32c 100644 --- a/packages/plugin-view/README.md +++ b/packages/plugin-view/README.md @@ -202,17 +202,57 @@ object through. Anything else you put in them is ignored: | Sub-config | Keys `ObjectView` forwards | | --- | --- | -| `table` | `columns`, `fields`, `title`, `description`, `defaultFilters`, `defaultSort`, `pageSize`, `selectable`, `operations`, `className` | +| `table` | `columns`, `fields`, `title`, `description`, `filter`, `defaultFilters`, `sort`, `defaultSort`, `pagination`, `pageSize`, `selection`, `selectable`, `operations`, `className` | | `form` | `fields`, `customFields`, `sections`, `groups`, `layout`, `columns`, `title`, `description`, `subforms`, `buttons`, `defaults`, `initialValues`, `readOnly`, `showSubmit`, `submitText`, `showCancel`, `cancelText`, `showReset`, `className` | -Note that several of the forwarded `table` keys are the ones `ObjectGridSchema` -marks legacy — `fields`, `pageSize`, `selectable`, `defaultFilters` and -`defaultSort` each have a newer counterpart there (`columns`, `pagination`, -`selection`, `filter`, `sort`). `ObjectView` forwards the legacy spellings, so -on an `object-view` node those are the ones that take effect; `columns` is the -exception, forwarded alongside `fields` and preferred here. Shapes follow -`ObjectGridSchema`: `defaultSort` is a single `{ field, order }` object and -`defaultFilters` is a plain `Record` of field to value. +Four of the forwarded `table` keys are pairs — a canonical `ObjectGridSchema` +key and the `@deprecated` legacy spelling it replaced. As of objectui#5102 the +canonical spelling **takes effect** on every rendering path (the grid, and the +non-grid `kanban` / `gallery` / `calendar` / `timeline` / `gantt` / `map` +renderers); the legacy spelling on the right keeps working as an alias, it is +just no longer the one to reach for: + +| write this (canonical) | not this (legacy alias — still works) | +| --- | --- | +| `pagination: { pageSize, pageSizeOptions? }` | `pageSize: number` | +| `selection: { type: 'single' \| 'multiple' \| 'none' }` | `selectable: boolean \| 'single' \| 'multiple'` | +| `filter: [{ field, operator, value }, …]` (same shape as a named view's `filter`) | `defaultFilters: Record` (equality-only) | +| `sort: 'field direction'` or `SortConfig[]` | `defaultSort: { field, order }` (**no string form** — that arity only exists on `sort`) | + +**Precedence when a key is written both ways** — `table: { pagination: { +pageSize: 10 }, pageSize: 50 }`, say — the canonical spelling wins. That is +`ObjectGrid`'s own existing resolution (`schema.pagination?.pageSize || +schema.pageSize`; `if (schema.selection?.type) … else if (schema.selectable +!== undefined)`; `schemaFilter !== undefined ? … : schema.defaultFilters`; +`schemaSort ?? (schema.defaultSort ? [schema.defaultSort] : undefined)`), and +`ObjectView` defers to it by forwarding both slots rather than re-resolving +the pair itself: + +```typescript +const schema: ObjectViewSchema = { + type: 'object-view', + objectName: 'products', + table: { + pagination: { pageSize: 10 }, // wins + pageSize: 50, // ignored while `pagination` is present + }, +}; +``` + +`filter` / `sort` have one more tier ahead of `table` entirely, and it +predates this change: an **active named view's own** `filter` / `sort` +(`listViews..filter` / `.sort`) always outranks anything written on +`table`. In order, highest first: the active named view's `filter`/`sort`, +then `table.filter`/`table.sort`, then `table.defaultFilters`/ +`table.defaultSort`. (If you never write `listViews`, that first tier never +applies.) `pagination` and `selection` have no such tier, and no effect +outside the grid — the non-grid renderers don't page or multi-select, so +`ObjectView` never forwards either spelling to them. + +`columns` is the one forwarded `table` key that is **not** part of this +canonical/legacy story, and it has an unrelated gap: it is forwarded on the +grid path only, so on a non-grid `defaultViewType` the field list still comes +from `table.fields` (objectui#5269, open). ### ViewSwitcher @@ -285,7 +325,7 @@ const schema: ObjectViewSchema = { defaultViewType: 'grid', table: { columns: ['name', 'email', 'role', 'created_at'], - defaultSort: { field: 'created_at', order: 'desc' }, + sort: 'created_at desc', // or [{ field: 'created_at', order: 'desc' }] }, }; ``` @@ -367,8 +407,8 @@ opening a drawer, so the host route owns the form. ### Read/List -Search, filter and sort are toolbar toggles; column set, default filter, -default sort and page size live in `table`: +Search, filter and sort are toolbar toggles; column set, filter, sort and page +size live in `table`: ```typescript const schema: ObjectViewSchema = { @@ -380,8 +420,8 @@ const schema: ObjectViewSchema = { showSort: true, table: { columns: ['name', 'price', 'category'], - defaultFilters: { category: 'electronics' }, - pageSize: 25, + filter: [{ field: 'category', operator: 'equals', value: 'electronics' }], + pagination: { pageSize: 25 }, }, }; ``` @@ -459,7 +499,7 @@ const schema: ObjectViewSchema = { showSort: true, table: { columns: ['first_name', 'last_name', 'email', 'company'], - pageSize: 25, + pagination: { pageSize: 25 }, }, };