Merge remote-tracking branch 'origin/master' into xtr/sidebar-workspace-controls
This commit is contained in:
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/client/ui-layout/README.md
|
||||
README.md: fa60520a20ac8a7f25d494879c68efb06a28998f
|
||||
README.md: c58b9a26ac794131aaa197722d14bd04de9f0cae
|
||||
README.zh.md: 2ce3d1972d39013d84216596dc57d48ab2d245d9
|
||||
|
||||
@@ -6,7 +6,7 @@ Shell plugin: three-column AppFrame (drag handles and concession chain) plus the
|
||||
|
||||
AppFrame always mounts the conversation and details columns; a connected Session renders through `SessionProvider`. The transient layout store starts the sidebar at its default width and details closed, and it never reads or writes `localStorage`. Hero and other unselected states also derive a zero rendered details width without changing that stored preference. AppFrame retains the last non-blank Session id across those states: the first Session remains closed, an explicit details action opens the contract default width, returning to the same Session restores its unchanged width, and selecting a different Session closes details before paint. The conversation owner share is empty, while the sidebar owner share contains only `collapsed` and `width`; registrants obtain business data from standard hooks and actions from their own inject faces.
|
||||
|
||||
The `/client` export surface is the plugin body (`apply`/`inject`), `LayoutService`, and the four owner-share interfaces. AppFrame, the panel store, and the concession solver remain package-internal.
|
||||
The `/client` exports are the plugin body (`apply`/`inject`), `LayoutService`, and the four owner-share interfaces. AppFrame, the panel store, and the concession solver remain package-internal.
|
||||
|
||||
## Model Experience
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import { createLayoutStore } from './stores.ts'
|
||||
import { LayoutService } from './service.ts'
|
||||
import { ThemePresenter } from './theme-presenter.ts'
|
||||
|
||||
// Contract surface only (export-convergence rule: cross-package consumers
|
||||
// Contract exports only (export-convergence rule: cross-package consumers
|
||||
// keep a symbol exported; test-only/package-internal symbols live off /src).
|
||||
// ILayout: the ctx.layout face consumers and test fakes type against.
|
||||
// OwnerShare contracts below are the render-side halves registrants compose
|
||||
@@ -64,7 +64,7 @@ export interface ConvOwnerProps {}
|
||||
/** Details owner share: empty — sessionId arrives as a framework-standard prop. */
|
||||
export interface DetailsOwnerProps {}
|
||||
|
||||
/** Required services (cordis fiber inject — the loader passes the whole export surface as an object plugin). */
|
||||
/** Required services (cordis fiber inject — the loader passes all module exports as an object plugin). */
|
||||
export const inject = ['slots', 'theme']
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// ONE register() call declares the three child slots + seats the store factory
|
||||
// + wires the panel actions through the inject hook; teardown cascades
|
||||
// (service unprovided + declarations gone + registration cleared). Node half
|
||||
// and the invariant companion ride along — one-line surfaces the aggregate
|
||||
// and the invariant companion ride along — one line exposes the aggregate
|
||||
// coverage gate still requires exercised.
|
||||
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
@@ -111,7 +111,7 @@ describe('node half + invariant companion', () => {
|
||||
const register = vi.fn().mockReturnValue(() => {})
|
||||
const ctx = { invariants: { register } } as never
|
||||
// The /invariant subpath types live in lib/types (build product); assert
|
||||
// the surface so the call stays typed where lint runs without a build.
|
||||
// the API so the call stays typed where lint runs without a build.
|
||||
const dispose = await (invariant as { apply: (ctx: never) => Promise<() => void> }).apply(ctx)
|
||||
expect(register).toHaveBeenCalledWith('@deepseek-ai/dsh-client-ui-layout', expect.any(Function))
|
||||
// The installer is the declared no-op — calling it must not throw.
|
||||
|
||||
Reference in New Issue
Block a user