@crazx/dsh-client-ui-layout 0.1.6-alpha.1.zw.2 → 0.1.6-alpha.2.zw.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.i18n.yaml CHANGED
@@ -2,5 +2,5 @@
2
2
  # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/client/ui-layout/README.md
5
- README.md: 50c73069c0d9151b13c985f867d9ae7d4f213a8a
6
- README.zh.md: b643bc5ae9116a898050292ea0401575750fa32a
5
+ README.md: eccaa40d8920828eda2a5a3a700b731ad8320e51
6
+ README.zh.md: 1842cd1b710e3e738ef6d60f8cea7d3acacc3121
package/README.md CHANGED
@@ -29,6 +29,8 @@ The root slot composes the sidebar, main content, and right column. The sidebar
29
29
 
30
30
  Global panels occupy the root-scoped `main` keyed slot; `conversation` is the reserved key for the Conversation. `ctx.layout.selectPanel(id)` selects a registered panel, and `null` selects the Conversation without changing the current Session. No global panel is registered by the shipped composition.
31
31
 
32
+ Windows Electron's `data-windows-titlebar` marker reserves the caption height above all columns and removes the collapsed sidebar rail. Only the content area's top-left corner has a 16px radius; the other corners and the internal divider remain square. The frame publishes `--dsh-windows-content-radius` and `--dsh-windows-sidebar-width` for ui-sidebar-right's fullscreen corner and sidebar clearance. Ordinary Web documents do not receive the marker; macOS retains its separate layout.
33
+
32
34
  The optional-Session `shell.toolbar` slot occupies a frame-spanning toolbar row above the three columns — the desktop-bridge seat for a unified macOS toolbar. With no occupant the row is a zero-height track, so plain web layouts are unchanged. A mounted toolbar publishes its two portal hosts through `ctx.layout.setToolbarHosts` / `releaseToolbarHosts`; every component reads the registration through the standard `useToolbarHosts` hook (`null` while no toolbar is mounted).
33
35
 
34
36
  ### Theme presentation
package/README.zh.md CHANGED
@@ -29,6 +29,8 @@ kind: "package-reference"
29
29
 
30
30
  全局面板占据 root 作用域的 `main` keyed slot;`conversation` 是为会话界面保留的 key。`ctx.layout.selectPanel(id)` 选中已注册面板,`null` 则选中会话界面,但不改变当前会话。默认组合不注册任何全局面板。
31
31
 
32
+ Windows Electron 的 `data-windows-titlebar` 标记在所有列上方预留顶栏高度,并移除收起后的侧栏轨道。内容区仅左上角保留 16px 圆角,其余角和内部交界处保持直角。框架发布 `--dsh-windows-content-radius` 和 `--dsh-windows-sidebar-width`,供 ui-sidebar-right 的全屏圆角及侧栏避让使用。普通 Web 文档不会获得该标记;macOS 保留其独立布局。
33
+
32
34
  可选 Session 的 `shell.toolbar` slot 占据三栏上方横跨整框的 toolbar 行——桌面桥统一 macOS 工具栏的席位。没有占用方时该行是零高度轨道,纯 Web 布局保持不变。已挂载的工具栏通过 `ctx.layout.setToolbarHosts` / `releaseToolbarHosts` 发布两个 portal 宿主;所有组件通过标准 `useToolbarHosts` hook 读取该注册(未挂载工具栏时为 `null`)。
33
35
 
34
36
  ### 主题呈现
package/lib/client.js CHANGED
@@ -30,11 +30,13 @@ window.__ModuleLoader__.load({
30
30
  * @param viewport - available frame width in px.
31
31
  * @param sidebar - sidebar width preference in px (0 = closed).
32
32
  * @param rightbar - requested right panel width in px (0 = no track).
33
+ * @param collapsedWidth - track width of the closed sidebar; the default keeps
34
+ * the icon rail, 0 hides the column entirely (macOS desktop).
33
35
  * @returns actual widths after shrinking or removing the right track; only
34
36
  * without that track may the center fall below its minimum, down to zero.
35
37
  */
36
- function computeColumns(viewport, sidebar, rightbar) {
37
- const s = sidebar === 0 ? 56 : clampWidth(sidebar, 264, 420);
38
+ function computeColumns(viewport, sidebar, rightbar, collapsedWidth = 56) {
39
+ const s = sidebar === 0 ? collapsedWidth : clampWidth(sidebar, 264, 420);
38
40
  const available = viewport - s - 400;
39
41
  const r = rightbar === 0 || available < 300 ? 0 : Math.min(available, clampWidth(rightbar, 300, viewport * RIGHTBAR_MAX_RATIO));
40
42
  return {
@@ -55,7 +57,7 @@ window.__ModuleLoader__.load({
55
57
  function DocumentTitle({ useSessions, usePanelInfo, productTitle }) {
56
58
  const showSessionTitle = usePanelInfo((info) => info.activePanelId === null);
57
59
  const title = useSessions((state) => {
58
- const current = state.current;
60
+ const current = Object.values(state.byId).find((session) => (session.retainedBy.mainView ?? 0) > 0)?.id;
59
61
  return !showSessionTitle || current === void 0 ? void 0 : state.byId[current]?.title;
60
62
  });
61
63
  (0, react.useEffect)(() => {
@@ -68,7 +70,7 @@ window.__ModuleLoader__.load({
68
70
  }
69
71
  //#endregion
70
72
  //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-layout/src/client/AppFrame.module.css.mjs
71
- const css = ".pI_x6G_frame{background:var(--dsw-alias-bg-base);height:100%;transition:grid-template-columns var(--ds-transition-duration-slow) var(--ds-ease-in-out);grid-template-rows:auto minmax(0,1fr);display:grid;position:relative;overflow:hidden}.pI_x6G_frame[data-dragging]{transition:none}@media (prefers-reduced-motion:reduce){.pI_x6G_frame{transition:none}}.pI_x6G_toolbarRow{grid-area:1/1/auto/-1;min-width:0;min-height:0}.pI_x6G_sidebarCol{background:var(--dsw-specific-sidebar-fill);border-right:.5px solid var(--dsw-alias-border-l3);grid-row:2;min-width:0;overflow:hidden}.pI_x6G_centerCol{flex-direction:column;grid-row:2;min-width:0;display:flex;overflow:hidden}.pI_x6G_handle{cursor:col-resize;z-index:11;touch-action:none;width:8px;transition:left var(--ds-transition-duration-slow) var(--ds-ease-in-out);margin-left:-4px;position:absolute;top:0;bottom:0}.pI_x6G_frame[data-dragging] .pI_x6G_handle,.pI_x6G_frame[data-rightbar-fullscreen],.pI_x6G_frame[data-rightbar-fullscreen] .pI_x6G_handle,.pI_x6G_frame[data-rightbar-instant],.pI_x6G_frame[data-rightbar-instant] .pI_x6G_handle{transition:none}@media (prefers-reduced-motion:reduce){.pI_x6G_handle{transition:none}}.pI_x6G_rightbarCol{grid-row:2;min-width:0;position:relative;overflow:visible}.pI_x6G_overlayLayer{z-index:20;pointer-events:none;position:absolute;inset:0}.pI_x6G_overlayLayer>*{pointer-events:auto}";
73
+ const css = ".pI_x6G_frame{background:var(--dsw-alias-bg-base);height:100%;transition:grid-template-columns var(--ds-transition-duration-slow) var(--ds-ease-in-out);grid-template-rows:auto minmax(0,1fr);display:grid;position:relative;overflow:hidden}.pI_x6G_frame[data-dragging]{transition:none}[data-windows-titlebar] .pI_x6G_frame{--dsh-windows-content-radius:16px;box-sizing:border-box;padding-top:var(--dsh-windows-titlebar-height);background:var(--dsw-specific-sidebar-fill);grid-template-rows:minmax(0,1fr)}[data-windows-titlebar] .pI_x6G_centerCol{background:var(--dsw-alias-bg-base);border-radius:var(--dsh-windows-content-radius) 0 0 0;corner-shape:round}[data-windows-titlebar] .pI_x6G_frame:before{content:\"\";height:var(--dsh-windows-titlebar-height);background:var(--dsw-specific-sidebar-fill);-webkit-app-region:drag;position:absolute;inset:0 0 auto}[data-windows-titlebar] .pI_x6G_sidebarCol{border-right:none}[data-windows-titlebar] .pI_x6G_handle{top:var(--dsh-windows-titlebar-height)}@media (prefers-reduced-motion:reduce){.pI_x6G_frame{transition:none}}.pI_x6G_toolbarRow{grid-area:1/1/auto/-1;min-width:0;min-height:0}.pI_x6G_sidebarCol{background:var(--dsw-specific-sidebar-fill);border-right:.5px solid var(--dsw-alias-border-l3);grid-row:2;min-width:0;overflow:hidden}.pI_x6G_centerCol{flex-direction:column;grid-row:2;min-width:0;display:flex;overflow:hidden}[data-platform=darwin] .pI_x6G_frame{background:0 0}[data-platform=darwin] .pI_x6G_sidebarCol{background:color-mix(in srgb, var(--dsw-specific-sidebar-fill) 60%, transparent);border-right:none}[data-platform=darwin] .pI_x6G_centerCol{background:var(--dsw-alias-bg-base);border-left:.5px solid var(--dsw-alias-border-l3)}[data-platform=darwin] [data-sidebar-collapsed] .pI_x6G_centerCol{border-left:none}.pI_x6G_handle{cursor:col-resize;z-index:11;touch-action:none;width:8px;transition:left var(--ds-transition-duration-slow) var(--ds-ease-in-out);margin-left:-4px;position:absolute;top:0;bottom:0}.pI_x6G_frame[data-dragging] .pI_x6G_handle,.pI_x6G_frame[data-rightbar-fullscreen],.pI_x6G_frame[data-rightbar-fullscreen] .pI_x6G_handle,.pI_x6G_frame[data-rightbar-instant],.pI_x6G_frame[data-rightbar-instant] .pI_x6G_handle{transition:none}@media (prefers-reduced-motion:reduce){.pI_x6G_handle{transition:none}}.pI_x6G_rightbarCol{grid-row:2;min-width:0;position:relative;overflow:visible}.pI_x6G_overlayLayer{z-index:20;pointer-events:none;position:absolute;inset:0}.pI_x6G_overlayLayer>*{pointer-events:auto}";
72
74
  const tagId = "@deepseek-ai/dsh-client-ui-layout/AppFrame.module.css";
73
75
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
74
76
  const tag = document.createElement("style");
@@ -235,8 +237,9 @@ window.__ModuleLoader__.load({
235
237
  const sidebarCollapsed = narrow ? !layoutInfo.narrowExpanded : layoutInfo.sidebar === 0;
236
238
  const sidebarPreference = sidebarCollapsed ? 0 : layoutInfo.sidebar === 0 ? 280 : layoutInfo.sidebar;
237
239
  const rightbarPreference = layoutInfo.rightbar ?? viewport * .45;
238
- const normal = computeColumns(viewport, !layoutInfo.rightbarShown && narrow ? 0 : sidebarPreference, rightbarPreference);
239
- const cols = computeColumns(viewport, sidebarPreference, layoutInfo.rightbarTrack ? rightbarPreference : 0);
240
+ const collapsedWidth = document.documentElement.dataset.platform === "darwin" || document.documentElement.hasAttribute("data-windows-titlebar") ? 0 : 56;
241
+ const normal = computeColumns(viewport, !layoutInfo.rightbarShown && narrow ? 0 : sidebarPreference, rightbarPreference, collapsedWidth);
242
+ const cols = computeColumns(viewport, sidebarPreference, layoutInfo.rightbarTrack ? rightbarPreference : 0, collapsedWidth);
240
243
  const colsRef = (0, react.useRef)(cols);
241
244
  colsRef.current = cols;
242
245
  const rightbarWidth = (0, react.useRef)(normal.rightbar);
@@ -278,7 +281,10 @@ window.__ModuleLoader__.load({
278
281
  return (0, react_jsx_runtime.jsxs)("div", {
279
282
  ref: frameRef,
280
283
  className: AppFrame_module_css_default.frame,
281
- style: { gridTemplateColumns: `${cols.sidebar}px minmax(0, 1fr) ${cols.rightbar}px` },
284
+ style: {
285
+ ...document.documentElement.hasAttribute("data-windows-titlebar") ? { "--dsh-windows-sidebar-width": `${cols.sidebar}px` } : {},
286
+ gridTemplateColumns: `${cols.sidebar}px minmax(0, 1fr) ${cols.rightbar}px`
287
+ },
282
288
  "data-sidebar-collapsed": sidebarCollapsed || void 0,
283
289
  "data-rightbar-collapsed": cols.rightbar === 0 || void 0,
284
290
  "data-rightbar-fullscreen": layoutInfo.rightbarFullscreen || void 0,
@@ -472,6 +478,14 @@ window.__ModuleLoader__.load({
472
478
  //#region lib/types/client/theme-presenter.js
473
479
  /** Body attribute selecting the dark base palette in the token stylesheets. */
474
480
  const DARK_ATTRIBUTE = "data-ds-dark-theme";
481
+ /**
482
+ * Root attribute publishing the theme source (`light`, `dark`, or `system`)
483
+ * for host shells that mirror it into native window chrome (the Electron
484
+ * preload forwards it to `nativeTheme.themeSource` so macOS vibrancy follows
485
+ * the app theme). `system` only when the preference is `system`; a fixed
486
+ * preference (including registered theme ids) publishes its resolved scheme.
487
+ */
488
+ const THEME_SOURCE_ATTRIBUTE = "data-ds-theme-source";
475
489
  /** Body variable carrying the user's content font size in px. */
476
490
  const CONTENT_FONT_SIZE_VARIABLE = "--dsh-content-font-size";
477
491
  /** Applies theme snapshots to the document; one instance per plugin fiber. */
@@ -497,6 +511,7 @@ window.__ModuleLoader__.load({
497
511
  apply(snapshot) {
498
512
  const scheme = snapshot.active.colorScheme;
499
513
  document.documentElement.style.colorScheme = scheme;
514
+ document.documentElement.setAttribute(THEME_SOURCE_ATTRIBUTE, snapshot.preference === "system" ? "system" : scheme);
500
515
  const body = document.body;
501
516
  if (scheme === "dark") body.setAttribute(DARK_ATTRIBUTE, "");
502
517
  else body.removeAttribute(DARK_ATTRIBUTE);
@@ -510,9 +525,13 @@ window.__ModuleLoader__.load({
510
525
  this.themeColorMeta.content = getComputedStyle(body).backgroundColor;
511
526
  if (!this.themeColorMeta.isConnected) document.head.append(this.themeColorMeta);
512
527
  }
513
- /** Retract root color-scheme, the palette attribute, token variables, the font-size axis, and the owned metadata node. */
528
+ /**
529
+ * Retract root color-scheme, the theme-source attribute, the palette
530
+ * attribute, token variables, the font-size axis, and the owned metadata node.
531
+ */
514
532
  dispose() {
515
533
  document.documentElement.style.removeProperty("color-scheme");
534
+ document.documentElement.removeAttribute(THEME_SOURCE_ATTRIBUTE);
516
535
  const body = document.body;
517
536
  body.removeAttribute(DARK_ATTRIBUTE);
518
537
  body.style.removeProperty(CONTENT_FONT_SIZE_VARIABLE);
@@ -42,8 +42,10 @@ export declare function clampWidth(px: number, min: number, max: number): number
42
42
  * @param viewport - available frame width in px.
43
43
  * @param sidebar - sidebar width preference in px (0 = closed).
44
44
  * @param rightbar - requested right panel width in px (0 = no track).
45
+ * @param collapsedWidth - track width of the closed sidebar; the default keeps
46
+ * the icon rail, 0 hides the column entirely (macOS desktop).
45
47
  * @returns actual widths after shrinking or removing the right track; only
46
48
  * without that track may the center fall below its minimum, down to zero.
47
49
  */
48
- export declare function computeColumns(viewport: number, sidebar: number, rightbar: number): Columns;
50
+ export declare function computeColumns(viewport: number, sidebar: number, rightbar: number, collapsedWidth?: number): Columns;
49
51
  //# sourceMappingURL=columns.d.ts.map
@@ -3,7 +3,8 @@
3
3
  * document — `html { color-scheme }` for native UA chrome (scrollbars, form
4
4
  * controls), `body[data-ds-dark-theme]` for the token palette, the active
5
5
  * theme's alias-token overrides as inline CSS variables on body, the content
6
- * font-size axis (`--dsh-content-font-size`), and one presenter-owned
6
+ * font-size axis (`--dsh-content-font-size`), `html[data-ds-theme-source]`
7
+ * for native-chrome mirroring, and one presenter-owned
7
8
  * `meta[name="theme-color"]` for surrounding browser UI. Pure DOM writes, no
8
9
  * React involvement; the presenter only ever retracts what it wrote itself,
9
10
  * so foreign attributes, metadata, and inline styles survive.
@@ -11,6 +12,14 @@
11
12
  import type { ThemeSnapshot } from '@deepseek-ai/dsh-client-ui-theme/client';
12
13
  /** Body attribute selecting the dark base palette in the token stylesheets. */
13
14
  export declare const DARK_ATTRIBUTE = "data-ds-dark-theme";
15
+ /**
16
+ * Root attribute publishing the theme source (`light`, `dark`, or `system`)
17
+ * for host shells that mirror it into native window chrome (the Electron
18
+ * preload forwards it to `nativeTheme.themeSource` so macOS vibrancy follows
19
+ * the app theme). `system` only when the preference is `system`; a fixed
20
+ * preference (including registered theme ids) publishes its resolved scheme.
21
+ */
22
+ export declare const THEME_SOURCE_ATTRIBUTE = "data-ds-theme-source";
14
23
  /** Body variable carrying the user's content font size in px. */
15
24
  export declare const CONTENT_FONT_SIZE_VARIABLE = "--dsh-content-font-size";
16
25
  /** Applies theme snapshots to the document; one instance per plugin fiber. */
@@ -31,7 +40,10 @@ export declare class ThemePresenter {
31
40
  * @param snapshot - resolved theme snapshot from ctx.theme.
32
41
  */
33
42
  apply(snapshot: ThemeSnapshot): void;
34
- /** Retract root color-scheme, the palette attribute, token variables, the font-size axis, and the owned metadata node. */
43
+ /**
44
+ * Retract root color-scheme, the theme-source attribute, the palette
45
+ * attribute, token variables, the font-size axis, and the owned metadata node.
46
+ */
35
47
  dispose(): void;
36
48
  }
37
49
  //# sourceMappingURL=theme-presenter.d.ts.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@crazx/dsh-client-ui-layout",
3
3
  "description": "Shell plugin: three-column AppFrame with drag handles, ctx.layout viewing-state service (navigation + panels)",
4
- "version": "0.1.6-alpha.1.zw.2",
4
+ "version": "0.1.6-alpha.2.zw.1",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -41,13 +41,13 @@
41
41
  "@deepseek-ai/cordis": "^4.0.2"
42
42
  },
43
43
  "devDependencies": {
44
- "@deepseek-ai/dsh-brand": "^0.1.6-alpha.1",
45
- "@deepseek-ai/dsh-client-locale": "^0.1.6-alpha.1",
46
- "@deepseek-ai/dsh-client-store": "^0.1.6-alpha.1",
47
- "@deepseek-ai/dsh-client-ui-renderer": "^0.1.6-alpha.1",
48
- "@deepseek-ai/dsh-client-ui-session": "^0.1.6-alpha.1",
49
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.6-alpha.1",
50
- "@deepseek-ai/dsh-client-ui-theme": "^0.1.6-alpha.1",
44
+ "@deepseek-ai/dsh-brand": "^0.1.6-alpha.2",
45
+ "@deepseek-ai/dsh-client-locale": "^0.1.6-alpha.2",
46
+ "@deepseek-ai/dsh-client-store": "^0.1.6-alpha.2",
47
+ "@deepseek-ai/dsh-client-ui-renderer": "^0.1.6-alpha.2",
48
+ "@deepseek-ai/dsh-client-ui-session": "^0.1.6-alpha.2",
49
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.6-alpha.2",
50
+ "@deepseek-ai/dsh-client-ui-theme": "^0.1.6-alpha.2",
51
51
  "@types/react": "~18.3.1",
52
52
  "@deepseek-ai/cordis": "^4.0.2",
53
53
  "react": "^18.2.0"