Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .changeset/6349-batch7-plugin-list.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@

The view switcher's views are typed as `@object-ui/core`'s `ListViewVisualization`, and this package no longer re-exports that union as `ViewType` (objectui#6349, batch 7). `@object-ui/types` publishes a different `ViewType`: the whole view-type vocabulary, which adds the `list` and `detail` categories to the nine visualizations the switcher draws. One exported name stood for two unions across the two packages.

**Type change, breaking for some consumers.** `ViewType` is no longer exported from `@object-ui/plugin-list` (TS2305 on import). Import `ListViewVisualization` from `@object-ui/core` instead; it is the same nine-member union. `ViewSwitcherProps` keeps its members, and `ViewSwitcherProps['currentView']` names the same union.
**Type change, breaking for some consumers.** `ViewType` is no longer exported from `@object-ui/plugin-list` (TS2305 on import). Import `ListViewVisualization` from `@object-ui/core` instead; it is the same nine-member union. The switcher's props keep their members, and `ListViewSwitcherProps['currentView']` names the same union (the props were renamed from `ViewSwitcherProps` in objectui#6349, batch 8).

No runtime behaviour changes.
7 changes: 7 additions & 0 deletions .changeset/6349-batch8-app-shell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@object-ui/app-shell': patch
---

The props of the console's page header are declared as `ConsolePageHeaderProps` instead of `PageHeaderComponentProps` (objectui#6349, batch 8). `@object-ui/layout` publishes `PageHeaderComponentProps` for the props of its own `PageHeader`, which is a different component: it takes string `title` and `subtitle` with record tokens and action definitions, where the console's header takes rendered nodes. This package's entry does not export the console header, so no import changes and the props are the same.

No runtime behaviour changes.
7 changes: 7 additions & 0 deletions .changeset/6349-batch8-layout.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@object-ui/layout': patch
---

Doc comment only. The `PageHeaderComponentProps` comment no longer says `@object-ui/app-shell` shares the name: the console's header props are now `ConsolePageHeaderProps`, so this package is the one authority for `PageHeaderComponentProps` (objectui#6349, batch 8). The type and its members are unchanged.

No runtime behaviour changes.
7 changes: 7 additions & 0 deletions .changeset/6349-batch8-plugin-dashboard.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@object-ui/plugin-dashboard': patch
---

The props of the dashboard's read-only record drill drawer are declared as `DashboardRecordDetailDrawerProps` instead of `RecordDetailDrawerProps` (objectui#6349, batch 8). `@object-ui/plugin-detail` publishes `RecordDetailDrawerProps` for its own record drawer, which is a different, editable component. This package's entry does not export the dashboard drawer, so no import changes and the props are the same.

No runtime behaviour changes.
9 changes: 9 additions & 0 deletions .changeset/6349-batch8-plugin-list.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@object-ui/plugin-list': minor
---

The props of this package's view switcher are declared and exported as `ListViewSwitcherProps` instead of `ViewSwitcherProps` (objectui#6349, batch 8). `@object-ui/plugin-view` publishes a different `ViewSwitcherProps`: the props of its `view-switcher` renderer, which takes a `ViewSwitcherSchema` and host callbacks and is keyed on the whole `ViewType`. This package's switcher takes `currentView` and `availableViews`, keyed on `@object-ui/core`'s `ListViewVisualization`. One exported name stood for two props types across the two packages.

**Type change, breaking for some consumers.** `ViewSwitcherProps` is no longer exported from `@object-ui/plugin-list`. Replace `import type { ViewSwitcherProps } from '@object-ui/plugin-list'` with `ListViewSwitcherProps`; the members (`currentView`, `availableViews`, `onViewChange`, `className`, `animated`) are unchanged. The compiler names the replacement (TS2724, "Did you mean 'ListViewSwitcherProps'?"). The `ViewSwitcher` and `ViewSwitcherDropdown` components keep their names.

No runtime behaviour changes.
4 changes: 3 additions & 1 deletion packages/app-shell/src/__tests__/spec-symbol-parity.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,9 @@ const RENAMES: Array<[local: string, formerly: string, specMeaning: string]> = [
['ScreenFieldInput', 'FieldInput', "the authoring shape of an object FIELD (Omit<Partial<Field>, 'type'>)"],
['ConversationListItem', 'ConversationSummary', 'the AI context-COMPACTION record (keyPoints, tokensSaved, …)'],
['AppShellRuntimeConfig', 'RuntimeConfig', 'the ENGINE runtime config (engine, engineConfig, resourceLimits)'],
['PageHeaderComponentProps', 'PageHeaderProps', 'the AUTHORED SDUI page-header node schema (strings, action ids)'],
// Renamed again in objectui#6349 (batch 8): `@object-ui/layout` publishes
// `PageHeaderComponentProps` for its own, different header component.
['ConsolePageHeaderProps', 'PageHeaderProps', 'the AUTHORED SDUI page-header node schema (strings, action ids)'],
['FlowDesignerNode', 'FlowNode', 'a COMPLETE authored flow node (label required)'],
['FlowDesignerEdge', 'FlowEdge', 'a COMPLETE authored flow edge (id required, condition needs `dialect`)'],
['PackageManifestRow', 'PackageManifest', 'the full authored package manifest (~40 keys)'],
Expand Down
19 changes: 14 additions & 5 deletions packages/app-shell/src/layout/PageHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { cn } from '@object-ui/components';
/**
* Props of the app-shell `<PageHeader>` React component.
*
* Named `PageHeaderComponentProps`, not `PageHeaderProps`:
* Named `ConsolePageHeaderProps`, not `PageHeaderProps`:
* `@objectstack/spec/ui` exports a `PageHeaderProps` **zod schema** describing
* the AUTHORED SDUI page-header node — `title: string`, `subtitle`, `icon`
* (an icon NAME), `breadcrumb`, `actions: string[]` (action ids), `aria`. This
Expand All @@ -37,10 +37,19 @@ import { cn } from '@object-ui/components';
* objectstack#4115 defect. `__tests__/spec-symbol-parity.test.ts` pins that the spec
* does not own this name.
*
* `@object-ui/layout` carries the same collision (objectui#3161, batch 7) and
* adopted this same name, so the two packages do not invent two dialects.
* Not `PageHeaderComponentProps` either. This interface carried that name
* until objectui#6349 (batch 8). `@object-ui/layout` publishes it for the
* props of its own `<PageHeader>`, which is a different React component.
* Its `title` and `subtitle` are strings with record tokens, its
* `actions` are action definitions handed to `record:quick_actions`, and it
* adds `showBack` and `schema` on top of every DOM attribute. (It is not the
* `page:header` renderer either: `@object-ui/components` registers that node
* type.) This console title row takes rendered nodes, and its
* `actions` is one rendered node. The two shapes do not fit each other, so
* this name cannot be re-pointed at layout's, and the console's header has the
* specific name.
*/
export interface PageHeaderComponentProps {
export interface ConsolePageHeaderProps {
/** Page title (required, becomes <h1>). */
title: React.ReactNode;
/**
Expand Down Expand Up @@ -114,7 +123,7 @@ export function PageHeader({
sticky = false,
className,
'data-testid': testId,
}: PageHeaderComponentProps) {
}: ConsolePageHeaderProps) {
// Resolve accent → CSS var. Falls back to the Shadcn primary token so the
// header follows whatever brand the active app has injected.
const accent = accentColor || 'hsl(var(--primary))';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ import { describe, it, expect } from 'vitest';
import { render, screen } from '@testing-library/react';

import { PageHeader } from '../PageHeader';
import type { PageHeaderComponentProps } from '../PageHeader';
import type { ConsolePageHeaderProps } from '../PageHeader';
// The sibling component this card exists to agree with. A type-only import:
// nothing from `@object-ui/layout` is rendered here.
import type { PageHeaderComponentProps as LayoutPageHeaderProps } from '@object-ui/layout';
Expand Down Expand Up @@ -114,7 +114,7 @@ type HasKey<T, K extends string> = K extends keyof T ? true : false;

describe('both `PageHeader`s spell the secondary line the same way', () => {
it('is pinned at compile time', () => {
type _ConsoleHasSubtitle = Assert<HasKey<PageHeaderComponentProps, 'subtitle'>>;
type _ConsoleHasSubtitle = Assert<HasKey<ConsolePageHeaderProps, 'subtitle'>>;
type _LayoutHasSubtitle = Assert<HasKey<LayoutPageHeaderProps, 'subtitle'>>;

// Only this side can be pinned negatively. `@object-ui/layout`'s props
Expand All @@ -125,7 +125,7 @@ describe('both `PageHeader`s spell the secondary line the same way', () => {
// half of the retirement is pinned where it belongs, on rendered output, in
// `packages/layout/src/__tests__/page-header-authorable-keys.test.tsx`.
type _ConsoleHasNoDescription = Assert<
HasKey<PageHeaderComponentProps, 'description'> extends true ? false : true
HasKey<ConsolePageHeaderProps, 'description'> extends true ? false : true
>;

expect(true).toBe(true);
Expand Down
2 changes: 1 addition & 1 deletion packages/app-shell/src/layout/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ export { PreviewBadge } from './PreviewBadge.js';
export type { PreviewBadgeProps } from './PreviewBadge.js';
export { AuthPageLayout } from './AuthPageLayout.js';
export { PageHeader } from './PageHeader.js';
export type { PageHeaderComponentProps } from './PageHeader.js';
export type { ConsolePageHeaderProps } from './PageHeader.js';
11 changes: 6 additions & 5 deletions packages/layout/src/PageHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import { useRecordContext, SchemaRenderer } from '@object-ui/react';
* Props of this package's `<PageHeader>` React component.
*
* Named `PageHeaderComponentProps`, not `PageHeaderProps` (objectui#3161,
* objectstack#4115 ledger batch 7) — the same name `@object-ui/app-shell`
* settled on for its own header props in objectui#3169, deliberately reused
* rather than re-invented, so one concept does not end up with two dialect
* names one package apart.
* objectstack#4115 ledger batch 7). `@object-ui/app-shell` once used this
* name for its own console header (objectui#3169). That header is a different
* component, with rendered-node `title`, `subtitle` and `actions`, so since
* objectui#6349 (batch 8) it is `ConsolePageHeaderProps`, and this package is
* the one authority for this name.
*
* `@objectstack/spec/ui` owns `PageHeaderProps` for the AUTHORED `page:header`
* node: a zod object of `title: string`, `subtitle`, an icon NAME, `breadcrumb`
Expand All @@ -21,7 +22,7 @@ import { useRecordContext, SchemaRenderer } from '@object-ui/react';
* prop rides along. Authored layer vs rendered layer, which is exactly the
* one-name-two-layers failure objectstack#4115 exists to end.
*
* Pinned by `__tests__/spec-symbol-batch7.test.tsx`, which fails if the spec
* Pinned by `__tests__/spec-symbol-batch7.test.ts`, which fails if the spec
* stops owning `PageHeaderProps` (then this can take the plain name back) or
* starts owning `PageHeaderComponentProps`.
*/
Expand Down
11 changes: 6 additions & 5 deletions packages/layout/src/__tests__/spec-symbol-batch7.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@
* point:
*
* - `PageHeaderProps` → `PageHeaderComponentProps`, the name
* `@object-ui/app-shell` already settled on for its own header props
* (objectui#3169). Reused deliberately: one concept, one name, even across
* two packages that each draw their own header. Still exported by this
* package, still guarded below — that is the whole of what this file now
* covers.
* `@object-ui/app-shell` had already given its own header props
* (objectui#3169). The two headers turned out to be different components,
* so app-shell's took the specific name `ConsolePageHeaderProps` in
* objectui#6349 (batch 8), and this package is the one authority for this
* name. Still exported by this package, still guarded below — that is the
* whole of what this file now covers.
* - `Page` → `PageNodeRenderer` → **deleted** (objectui#3223, ADR-0049
* enforce-or-remove). The rename was correct and did not go far enough: the
* renderer was registered nowhere and called from nowhere — the `page` key
Expand Down
15 changes: 13 additions & 2 deletions packages/plugin-dashboard/src/RecordDetailDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,18 @@ import {
} from './recordFields';
import { humanizeFieldKey } from './utils';

export interface RecordDetailDrawerProps {
/**
* Props of the dashboard's read-only drill drawer.
*
* Named `DashboardRecordDetailDrawerProps`, not `RecordDetailDrawerProps`:
* `@object-ui/plugin-detail` publishes `RecordDetailDrawerProps` for its own
* record drawer, a different component. That drawer is editable, deletes, and
* resizes, and it takes an `open` flag, a `recordId` and a `dataSource`. This
* one only shows a record the table already fetched. Neither package depends
* on the other, so the two could not share one declaration, and the narrower
* drawer has the specific name (objectui#6349, batch 8).
*/
export interface DashboardRecordDetailDrawerProps {
/** The record to display, or `null` when nothing is selected. */
record: Record<string, any> | null;
/** Object the record belongs to (drives label translation + field meta). */
Expand Down Expand Up @@ -80,7 +91,7 @@ function resolveRecordTitle(record: Record<string, any>, explicit?: string): str
return id != null ? String(id) : 'Record';
}

export const RecordDetailDrawer: React.FC<RecordDetailDrawerProps> = ({
export const RecordDetailDrawer: React.FC<DashboardRecordDetailDrawerProps> = ({
record,
objectName,
objectSchema,
Expand Down
16 changes: 12 additions & 4 deletions packages/plugin-list/src/ViewSwitcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,16 @@ import {
* deliberately NOT a visualization: the spec models it as a list view that
* mounts a published page rather than one a user switches into, and
* `AppearanceConfig.allowedVisualizations` excludes it for the same reason.
*
* The props are named `ListViewSwitcherProps`, not `ViewSwitcherProps`, for the
* same reason. `@object-ui/plugin-view` publishes `ViewSwitcherProps` for a
* different switcher: the `view-switcher` renderer, which takes a
* `ViewSwitcherSchema` and the host callbacks and is keyed on the whole
* `ViewType`. Neither package depends on the other, so the two could not share
* one declaration. The general name stays with the schema-driven renderer, and
* this list view's switcher has the specific one (objectui#6349, batch 8).
*/
export interface ViewSwitcherProps {
export interface ListViewSwitcherProps {
currentView: ListViewVisualization;
availableViews?: ListViewVisualization[];
onViewChange: (view: ListViewVisualization) => void;
Expand All @@ -71,7 +79,7 @@ export interface ViewSwitcherProps {
// `gantt` is the one real glyph change of the three: `GanttChartSquare` and
// `ChartGantt` are DIFFERENT objects (the identity-preserving live spelling is
// `SquareChartGantt`). `ChartGantt` is chosen over it so the two switchers draw
// the same glyph for the same `ViewType` — #5586 landed `ChartGantt` for
// the same glyph for the same visualization — #5586 landed `ChartGantt` for
// `gantt` in `plugin-view`, and one view type showing two different icons
// depending on which switcher is on screen is the drift worth avoiding.
const VIEW_ICONS: Record<ListViewVisualization, React.ReactNode> = {
Expand Down Expand Up @@ -165,7 +173,7 @@ function useViewLabels(): Record<ListViewVisualization, string> {
* menu of the available visualizations. Replaces the full button row so
* the toolbar stays one line tall.
*/
export const ViewSwitcherDropdown: React.FC<ViewSwitcherProps> = ({
export const ViewSwitcherDropdown: React.FC<ListViewSwitcherProps> = ({
currentView,
availableViews = ['grid', 'kanban'],
onViewChange,
Expand Down Expand Up @@ -273,7 +281,7 @@ export const ViewSwitcherDropdown: React.FC<ViewSwitcherProps> = ({
);
};

export const ViewSwitcher: React.FC<ViewSwitcherProps> = ({
export const ViewSwitcher: React.FC<ListViewSwitcherProps> = ({
currentView,
availableViews = ['grid', 'kanban'],
onViewChange,
Expand Down
6 changes: 4 additions & 2 deletions packages/plugin-list/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ export type { ListViewProps, ListViewHandle } from './ListView';
export type { ObjectGalleryProps } from './ObjectGallery';
// The switcher's views are `@object-ui/core`'s `ListViewVisualization`. This
// barrel no longer re-exports them as `ViewType`, the name `@object-ui/types`
// gives the wider view-type vocabulary (objectui#6349, batch 7).
export type { ViewSwitcherProps } from './ViewSwitcher';
// gives the wider view-type vocabulary (objectui#6349, batch 7). Its props are
// `ListViewSwitcherProps`, because `@object-ui/plugin-view` publishes
// `ViewSwitcherProps` for a different switcher (objectui#6349, batch 8).
export type { ListViewSwitcherProps } from './ViewSwitcher';

/**
* Registry entry point for `<ListView>`. Both bridges it carries — the
Expand Down
34 changes: 31 additions & 3 deletions scripts/__tests__/one-authority-per-exported-name-6273.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -527,8 +527,27 @@ const KNOWN_COLLISIONS: ReadonlyMap<string, readonly string[]> = new Map([
// `OrgTranslate` sat here — two IDENTICAL declarations inside app-shell's
// organizations console. `orgErrorMessage.ts` is the one authority;
// `orgRoleLabel.ts` re-exports it (objectui#6349).
['PageHeaderComponentProps', ['packages/app-shell/src/layout/PageHeader.tsx', 'packages/layout/src/PageHeader.tsx']],
['RecordDetailDrawerProps', ['packages/plugin-dashboard/src/RecordDetailDrawer.tsx', 'packages/plugin-detail/src/RecordDetailDrawer.tsx']],
// `PageHeaderComponentProps` sat here, colliding between
// `packages/app-shell/src/layout/PageHeader.tsx` and
// `packages/layout/src/PageHeader.tsx`. Two components, not one drifted
// shape: layout's is its published `<PageHeader>` (string `title` /
// `subtitle` with record tokens, `actions` as action definitions, `showBack`,
// `schema`, every DOM attribute) and app-shell's is the console's own title
// row (rendered-node `title` / `subtitle` / `actions`, `accentColor`,
// `sticky`). Neither is the `page:header` renderer, which
// `@object-ui/components` registers. app-shell depends on layout, but
// re-pointing its name at layout's does not compile. RENAME branch: the
// console's declaration now spells `ConsolePageHeaderProps`, and layout is
// the one authority (objectui#6349, batch 8).
// `RecordDetailDrawerProps` sat here, colliding between
// `packages/plugin-dashboard/src/RecordDetailDrawer.tsx` and
// `packages/plugin-detail/src/RecordDetailDrawer.tsx`. Two drawers, not one:
// plugin-detail's is the published, editable record drawer (`open`,
// `recordId`, `dataSource`, save, delete, resize) and plugin-dashboard's is
// the read-only drill drawer of a table widget (`record` may be `null`,
// `target` is `'drawer' | 'dialog'`, `fields` whitelists). Neither package
// depends on the other. RENAME branch: the dashboard's declaration now spells
// `DashboardRecordDetailDrawerProps` (objectui#6349, batch 8).
['SchemaNode', ['packages/sdui-parser/src/types.ts', 'packages/types/src/base.ts']],
['ThemeProviderProps', ['packages/providers/src/types.ts', 'packages/react/src/context/ThemeContext.tsx']],
// `TranslateFn` sat here — i18next's `t` narrowed to `(key, options?) => string`,
Expand Down Expand Up @@ -564,7 +583,16 @@ const KNOWN_COLLISIONS: ReadonlyMap<string, readonly string[]> = new Map([
// `FieldValidationFunction`, the name `src/index.ts` always published it under
// (objectui#6349).
['VersionEntry', ['packages/collaboration/src/useConflictResolution.ts', 'packages/plugin-designer/src/components/VersionHistory.tsx']],
['ViewSwitcherProps', ['packages/plugin-list/src/ViewSwitcher.tsx', 'packages/plugin-view/src/ViewSwitcher.tsx']],
// `ViewSwitcherProps` sat here, colliding between
// `packages/plugin-list/src/ViewSwitcher.tsx` and
// `packages/plugin-view/src/ViewSwitcher.tsx`. Two switchers, not one:
// plugin-view's is the `view-switcher` renderer (a `ViewSwitcherSchema` plus
// host callbacks, keyed on the whole `ViewType`) and plugin-list's is the list
// view's visualization switcher (`currentView` / `availableViews`, keyed on
// `@object-ui/core`'s `ListViewVisualization`). Neither package depends on
// the other. RENAME branch: plugin-list's declaration now spells
// `ListViewSwitcherProps`, and the plugin-list root publishes that name
// instead (objectui#6349, batch 8).
// `ViewType` sat here, colliding between
// `packages/plugin-list/src/ViewSwitcher.tsx` and `packages/types/src/views.ts`.
// Two meanings, not drift: `@object-ui/types`' is the whole view-type
Expand Down
Loading