@deepseek-ai/dsh-client-ui-sidebar-right 0.2.0-rc.1 → 0.2.1-alpha.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 +6 -6
- package/README.md +3 -5
- package/README.zh.md +3 -5
- package/lib/client.js +188 -160
- package/lib/types/client/index.d.ts +1 -1
- package/lib/types/client/service.d.ts +84 -70
- package/lib/types/client/shell/SidebarRight.d.ts +18 -23
- package/package.json +19 -19
package/README.i18n.yaml
CHANGED
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
en: 6d7f145ecb1fd140
|
|
22
22
|
zh: 666d142ef249f6cb
|
|
23
23
|
/deepseek-ai-dsh-client-ui-sidebar-right/the-expand-button:
|
|
24
|
-
en:
|
|
25
|
-
zh:
|
|
24
|
+
en: 2614d3f179290606
|
|
25
|
+
zh: 88c08ee260ba57b7
|
|
26
26
|
/deepseek-ai-dsh-client-ui-sidebar-right/state:
|
|
27
27
|
en: 2b15cdf5f1383291
|
|
28
28
|
zh: 57018036d77363ba
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
en: ef2af36136c4a919
|
|
31
31
|
zh: 48d992e2c923a130
|
|
32
32
|
/deepseek-ai-dsh-client-ui-sidebar-right/ctx-sidebarright:
|
|
33
|
-
en:
|
|
34
|
-
zh:
|
|
33
|
+
en: 4519c4633d160c2a
|
|
34
|
+
zh: e4019a62532f885a
|
|
35
35
|
/deepseek-ai-dsh-client-ui-sidebar-right/the-tab-domain:
|
|
36
36
|
en: 717b86e05b44ebdd
|
|
37
37
|
zh: 0f4f694d0ea1d7f8
|
|
@@ -51,5 +51,5 @@
|
|
|
51
51
|
en: 76a763b4dd71babd
|
|
52
52
|
zh: fdc966dd427a82fb
|
|
53
53
|
/deepseek-ai-dsh-client-ui-sidebar-right/known-limitations-and-deferred-work/dev-note:
|
|
54
|
-
en:
|
|
55
|
-
zh:
|
|
54
|
+
en: e67f633dc6fe7773
|
|
55
|
+
zh: e88aeb617ffb74ea
|
package/README.md
CHANGED
|
@@ -58,7 +58,7 @@ While the panel is hidden, one button in the conversation header's corner seat (
|
|
|
58
58
|
|
|
59
59
|
The panel takes the conversation's ground colour and content font sizes rather than a raised layer of its own: it is a column of the page, not a card over it.
|
|
60
60
|
|
|
61
|
-
The root-scoped `rightbar` entry renders the selected Session and background Sessions with initialized `keepMounted` bodies through separate `rightbar.session` subtrees. Each View owns its Session reference. Only the foreground
|
|
61
|
+
The root-scoped `rightbar` entry renders the selected Session and background Sessions with initialized `keepMounted` bodies through separate `rightbar.session` subtrees. Each View owns its Session reference. Only the foreground subtree reports a frame track; other subtrees stay hidden without deleting tab state.
|
|
62
62
|
|
|
63
63
|
<a id="state"></a>
|
|
64
64
|
## State
|
|
@@ -94,9 +94,9 @@ Two more seats extend what is already there: `sidebar.right.tab.guide` (chain) r
|
|
|
94
94
|
|
|
95
95
|
`preferNewPane: true` first asks the target docked pane to split under the normal two-pane and room rules, then falls back to that pane when no split is available. `replaceTab` takes precedence and disables this preference.
|
|
96
96
|
|
|
97
|
-
`close(tabId)` closes a tab; `active()` reads the active tab. `isExpanded()` and `toggleExpanded()` read and drive the column's expansion; `toggleFullscreen(target)` applies the panel control’s display-mode action to a captured dock pane. Layout operations, for callers that arrange the column programmatically, each recorded like the gesture it stands in for: `focus(tabId)` focuses a tab and its pane; `split(paneId?)` splits a docked pane (the active one by default) under the same pane budget and room rule as the strip's control and returns the new pane's id, or `undefined` — recording nothing — when it cannot; `float(tabId, rect?)` takes a docked tab out into a panel; `dock(paneId)` returns a floating panel to the active docked pane. A tab or pane that does not exist, or already is where the call would put it, is left alone. The face exposes operations only: no layout snapshot, no operation log, no lookup by address. `_undo()` / `_redo()` step the
|
|
97
|
+
`close(tabId)` closes a tab; `active()` reads the active tab. `isExpanded()` and `toggleExpanded()` read and drive the column's expansion; `toggleFullscreen(target)` applies the panel control’s display-mode action to a captured dock pane. Layout operations, for callers that arrange the column programmatically, each recorded like the gesture it stands in for: `focus(tabId)` focuses a tab and its pane; `split(paneId?)` splits a docked pane (the active one by default) under the same pane budget and room rule as the strip's control and returns the new pane's id, or `undefined` — recording nothing — when it cannot; `float(tabId, rect?)` takes a docked tab out into a panel; `dock(paneId)` returns a floating panel to the active docked pane. A tab or pane that does not exist, or already is where the call would put it, is left alone. The face exposes operations only: no layout snapshot, no operation log, no lookup by address. `_undo()` / `_redo()` step the on-screen surface's history; they are `@internal` — the sequence has no user-facing control, and these exist for tests. Commands act on the on-screen Session through its adopted store; with no Session on screen, or before the runtime mints its store, they throw rather than write into a surface nobody draws. `mounted` is the observable of the Session on screen: the selected Session while the Conversation fills the main column, `undefined` while a global panel replaces it or no Session is selected. The plugin derives it from the Session selection and `ctx.layout.panelInfo`, and it changes before React renders the change that causes it, so a component rendered in that commit reads the arriving Session and may act on it from its effects: the frame renders that Session's seat in the same pass, which mints its store. Seats never publish it; each reports only what it renders with: the room its docking kit measured, which `split` and `preferNewPane` apply to that Session's panes (unmeasured panes have room), and whether its frame width presents the panel fullscreen automatically, which the fullscreen command applies. The plan review's automatic open reads `mounted` through a bound hook.
|
|
98
98
|
|
|
99
|
-
`focusedTarget(element?)` resolves the current DOM pane and tab, including an embedding iframe; outside focus returns no page. `commandTarget(element?)` additionally allows an outside open to use the
|
|
99
|
+
`focusedTarget(element?)` resolves the current DOM pane and tab, including an embedding iframe; outside focus returns no page. `commandTarget(element?)` additionally allows an outside open to use the on-screen Session's active dock pane. Captures include the occurrence and navigation revision; `isTargetCurrent(target)` rejects changed Sessions, moved or reopened tabs, and intervening navigation. Focus and pointer activation remain separate from persisted layout selection.
|
|
100
100
|
|
|
101
101
|
<a id="the-tab-domain"></a>
|
|
102
102
|
## The Tab domain
|
|
@@ -155,5 +155,3 @@ None; this package neither assembles nor sends a provider request.
|
|
|
155
155
|
None.
|
|
156
156
|
|
|
157
157
|
</details>
|
|
158
|
-
|
|
159
|
-
**Runtime invariant:** No companion is published. The two services (`sidebarRight`, `sidebarRightTabs`) are provided through `ctx.reflect.provide` inside one effect and torn down with it; the seat's binding and the Tab domain's occurrence lifetimes are asserted directly by this package's specs, and no independent observation exists to diverge from them.
|
package/README.zh.md
CHANGED
|
@@ -58,7 +58,7 @@ kind: "package-reference"
|
|
|
58
58
|
|
|
59
59
|
面板取会话区的底色与正文字号,而不是自成一层浮起的表面:它是页面的一列,不是压在页面上的卡片。
|
|
60
60
|
|
|
61
|
-
root 作用域的 `rightbar` 入口通过独立的 `rightbar.session` 子树渲染选中的 Session,以及拥有已初始化 `keepMounted` 正文的后台 Session。每个 View 拥有自身的 Session reference
|
|
61
|
+
root 作用域的 `rightbar` 入口通过独立的 `rightbar.session` 子树渲染选中的 Session,以及拥有已初始化 `keepMounted` 正文的后台 Session。每个 View 拥有自身的 Session reference。只有前台子树上报框架列宽;其他子树保持隐藏,不删除 tab 状态。
|
|
62
62
|
|
|
63
63
|
<a id="state"></a>
|
|
64
64
|
## 状态
|
|
@@ -94,9 +94,9 @@ tab 类型分两阶段注册,随包发布的引导类型走的正是别的包
|
|
|
94
94
|
|
|
95
95
|
`preferNewPane: true` 会先按普通的两格上限与空间规则尝试分割目标停靠格,无法分栏时回退到该格。`replaceTab` 优先并会禁用这项偏好。
|
|
96
96
|
|
|
97
|
-
`close(tabId)` 关闭一个 tab;`active()` 读取活动 tab。`isExpanded()` 与 `toggleExpanded()` 读取并驱动该列的展开;`toggleFullscreen(target)` 对捕获的停靠分栏执行面板控件的显示模式操作。布局操作供以编程方式安排该列的调用方使用,每个都像它替代的手势一样被记录:`focus(tabId)` 聚焦一个 tab 及其格;`split(paneId?)` 在与 tab 条控件相同的格预算与空间规则下分栏一个停靠格(默认活跃格),返回新格的 id,做不到时返回 `undefined`——且不记录任何东西;`float(tabId, rect?)` 把停靠 tab 浮出为浮窗;`dock(paneId)` 把浮窗放回活跃停靠格。不存在的 tab 或格、或已处于调用目标状态的,都原样不动。该接口只暴露操作:没有布局快照、没有操作日志、没有按地址查找。`_undo()` / `_redo()`
|
|
97
|
+
`close(tabId)` 关闭一个 tab;`active()` 读取活动 tab。`isExpanded()` 与 `toggleExpanded()` 读取并驱动该列的展开;`toggleFullscreen(target)` 对捕获的停靠分栏执行面板控件的显示模式操作。布局操作供以编程方式安排该列的调用方使用,每个都像它替代的手势一样被记录:`focus(tabId)` 聚焦一个 tab 及其格;`split(paneId?)` 在与 tab 条控件相同的格预算与空间规则下分栏一个停靠格(默认活跃格),返回新格的 id,做不到时返回 `undefined`——且不记录任何东西;`float(tabId, rect?)` 把停靠 tab 浮出为浮窗;`dock(paneId)` 把浮窗放回活跃停靠格。不存在的 tab 或格、或已处于调用目标状态的,都原样不动。该接口只暴露操作:没有布局快照、没有操作日志、没有按地址查找。`_undo()` / `_redo()` 步进屏幕上停靠面的历史;它们是 `@internal`——序列没有面向用户的控件,这两个只为测试存在。命令通过屏幕上会话已采用的 store 作用于该会话;没有会话在屏幕上、或运行时尚未创建它的 store 时,命令 throw,而不是写进一个没人绘制的面里。`mounted` 是「屏幕上的会话」的可观察值:Conversation 占据主栏时为选中的会话,全局面板替代它或没有选中会话时为 `undefined`。插件从会话选择与 `ctx.layout.panelInfo` 推导它,它在 React 渲染引起变化的那次更新之前就已改变,因此同一次提交里渲染的组件读到的是到来的会话,并可以在自己的 effect 里对它行动:框架在同一轮渲染里渲染该会话的席位,席位随之创建它的 store。席位从不发布它;每个席位只上报它渲染时依据的事实:停靠套件测得的空间,`split` 与 `preferNewPane` 把它用于该会话的分栏(未测量的分栏视为有空间);以及框架宽度是否让面板自动全屏,全屏命令据此执行。计划审阅的自动打开通过绑定的 hook 读取 `mounted`。
|
|
98
98
|
|
|
99
|
-
`focusedTarget(element?)` 解析当前 DOM 分栏和标签页,也接受嵌入 iframe;焦点位于外部时不返回页面。`commandTarget(element?)`
|
|
99
|
+
`focusedTarget(element?)` 解析当前 DOM 分栏和标签页,也接受嵌入 iframe;焦点位于外部时不返回页面。`commandTarget(element?)` 另外允许外部打开动作使用屏幕上会话的活动停靠分栏。捕获值包含 occurrence 和导航版本;`isTargetCurrent(target)` 拒绝会话变更、已移动或重新打开的标签页,以及期间发生的导航。焦点和指针激活独立于持久化的布局选择。
|
|
100
100
|
|
|
101
101
|
<a id="the-tab-domain"></a>
|
|
102
102
|
## Tab 域
|
|
@@ -155,5 +155,3 @@ Tab 域按(Session,Tab id)保留品牌化 occurrence id、导航、中止
|
|
|
155
155
|
无。
|
|
156
156
|
|
|
157
157
|
</details>
|
|
158
|
-
|
|
159
|
-
**运行时不变量:** 不发布 companion。两个服务(`sidebarRight`、`sidebarRightTabs`)在同一个 effect 内经 `ctx.reflect.provide` 提供并随之拆除;席位绑定与 Tab 域 occurrence 的生命周期由本包的 spec 直接断言,不存在会与之分歧的独立观察。
|
package/lib/client.js
CHANGED
|
@@ -5426,38 +5426,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5426
5426
|
"unavailable": "P3OORG_unavailable"
|
|
5427
5427
|
};
|
|
5428
5428
|
//#endregion
|
|
5429
|
-
//#region lib/types/client/shell/close-focus.js
|
|
5430
|
-
/** Focus continuity after page operations replace docked or floating pane elements. */
|
|
5431
|
-
/**
|
|
5432
|
-
* Focus the page selected by an open or split after its DOM has committed.
|
|
5433
|
-
* @param document - product document owning the input focus.
|
|
5434
|
-
* @param sessionId - Session whose page is opening.
|
|
5435
|
-
* @param open - synchronous operation returning its selected pane, or undefined when unchanged.
|
|
5436
|
-
*/
|
|
5437
|
-
function openWithPaneFocus(document, sessionId, open) {
|
|
5438
|
-
let paneId;
|
|
5439
|
-
(0, react_dom.flushSync)(() => {
|
|
5440
|
-
paneId = open();
|
|
5441
|
-
});
|
|
5442
|
-
if (paneId !== void 0) visibleSidebarPane(document, sessionId, paneId)?.focus({ preventScroll: true });
|
|
5443
|
-
}
|
|
5444
|
-
/**
|
|
5445
|
-
* Commit a focused page's removal before focusing a surviving visible pane.
|
|
5446
|
-
* @param document - product document owning the input focus.
|
|
5447
|
-
* @param sessionId - Session whose page is closing.
|
|
5448
|
-
* @param paneId - pane whose page is closing; preferred if it survives.
|
|
5449
|
-
* @param close - synchronous cleanup and layout removal; errors preserve focus.
|
|
5450
|
-
*/
|
|
5451
|
-
function closeWithPaneFocus(document, sessionId, paneId, close) {
|
|
5452
|
-
const before = document.activeElement;
|
|
5453
|
-
const owner = before?.closest("[data-sidebar-right-session]");
|
|
5454
|
-
const source = before?.closest("[data-dockkit-pane], [data-dockkit-float]");
|
|
5455
|
-
const retain = owner?.dataset.sidebarRightSession === sessionId && (source?.dataset.dockkitPane ?? source?.dataset.dockkitFloat) === paneId;
|
|
5456
|
-
(0, react_dom.flushSync)(close);
|
|
5457
|
-
if (!retain || document.activeElement !== document.body && document.activeElement !== before) return;
|
|
5458
|
-
visibleSidebarPane(document, sessionId, paneId)?.focus({ preventScroll: true });
|
|
5459
|
-
}
|
|
5460
|
-
//#endregion
|
|
5461
5429
|
//#region lib/types/client/shell/SidebarRight.js
|
|
5462
5430
|
/**
|
|
5463
5431
|
* The Sidebar's seat in the frame, and the panel it draws.
|
|
@@ -5589,12 +5557,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5589
5557
|
"data-sidebar-right-tab": tab.id,
|
|
5590
5558
|
"data-sidebar-right-occurrence": id,
|
|
5591
5559
|
children: content
|
|
5592
|
-
}) : (0, react_jsx_runtime.jsx)("div", {
|
|
5560
|
+
}, id) : (0, react_jsx_runtime.jsx)("div", {
|
|
5593
5561
|
className: SidebarRight_module_css_default.tabBody,
|
|
5594
5562
|
"data-sidebar-right-tab": tab.id,
|
|
5595
5563
|
"data-sidebar-right-occurrence": id,
|
|
5596
5564
|
children: content
|
|
5597
|
-
});
|
|
5565
|
+
}, id);
|
|
5598
5566
|
}
|
|
5599
5567
|
/**
|
|
5600
5568
|
* Dispatch a tab's body to its registered type.
|
|
@@ -5712,7 +5680,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5712
5680
|
"data-sidebar-right-session": sessionId,
|
|
5713
5681
|
"data-sidebar-right-panel": fullscreen ? "fullscreen" : "push",
|
|
5714
5682
|
"data-sidebar-right-open": expanded || void 0,
|
|
5715
|
-
"aria-hidden": !expanded || void 0,
|
|
5683
|
+
"aria-hidden": !expanded && surface.layout.floats.length === 0 || void 0,
|
|
5716
5684
|
children: (0, react_jsx_runtime.jsx)("div", {
|
|
5717
5685
|
className: SidebarRight_module_css_default.panelBody,
|
|
5718
5686
|
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_dockkit.DockLayout, {
|
|
@@ -5747,22 +5715,21 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5747
5715
|
}
|
|
5748
5716
|
/**
|
|
5749
5717
|
* The right column's occupant: stable tab containers, docked or floating.
|
|
5750
|
-
* It is also where the
|
|
5751
|
-
*
|
|
5752
|
-
*
|
|
5718
|
+
* It is also where the frame learns the panel's presentation, because this is
|
|
5719
|
+
* the seat that knows it. `ctx.sidebarRight` names the on-screen Session
|
|
5720
|
+
* itself; this seat reports only what it renders with: the room its kit
|
|
5721
|
+
* measured and the automatic fullscreen rule of its frame width.
|
|
5753
5722
|
*/
|
|
5754
|
-
function RightbarSeat({ sessionId, width, viewportWidth, canShow, useStore, actions, t, renderSlot, syncPresentation,
|
|
5723
|
+
function RightbarSeat({ sessionId, width, viewportWidth, canShow, useStore, actions, t, renderSlot, syncPresentation, measureRoom, reportAutoFullscreen, openTab, closeTab, useTabTypes, useTabNavigation, occurrence, retainTab, active, useShortcuts, splitPane, toggleFullscreen }) {
|
|
5755
5724
|
const shortcuts = useShortcuts((entries) => entries);
|
|
5756
|
-
const
|
|
5757
|
-
const surface = surfaces[sessionId];
|
|
5725
|
+
const surface = useStore((state) => state.bySession[sessionId]);
|
|
5758
5726
|
const shown = active && surface !== void 0 && surface.layout.expanded;
|
|
5759
5727
|
const autoFullscreen = viewportWidth < 768;
|
|
5760
5728
|
const fullscreen = autoFullscreen || surface?.layout.mode === "fullscreen";
|
|
5761
5729
|
const panelRef = (0, react.useRef)(null);
|
|
5762
|
-
const room = (0, react.useRef)(/* @__PURE__ */ new Map());
|
|
5763
5730
|
const reportRoom = (0, react.useCallback)((fits) => {
|
|
5764
|
-
|
|
5765
|
-
}, []);
|
|
5731
|
+
measureRoom((paneId) => fits.get(paneId)?.row !== false);
|
|
5732
|
+
}, [measureRoom]);
|
|
5766
5733
|
const track = shown && !autoFullscreen;
|
|
5767
5734
|
(0, react.useEffect)(() => {
|
|
5768
5735
|
if (active && surface === void 0) actions.open(sessionId);
|
|
@@ -5781,6 +5748,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5781
5748
|
fullscreen,
|
|
5782
5749
|
canShow
|
|
5783
5750
|
]);
|
|
5751
|
+
(0, react.useLayoutEffect)(() => {
|
|
5752
|
+
reportAutoFullscreen(autoFullscreen);
|
|
5753
|
+
}, [reportAutoFullscreen, autoFullscreen]);
|
|
5784
5754
|
(0, react.useLayoutEffect)(() => {
|
|
5785
5755
|
if (!active) return;
|
|
5786
5756
|
let disposed = false;
|
|
@@ -5816,26 +5786,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5816
5786
|
fullscreen: false
|
|
5817
5787
|
});
|
|
5818
5788
|
} : void 0, [syncPresentation, active]);
|
|
5819
|
-
(0, react.useEffect)(() => active ? bindService({
|
|
5820
|
-
sessionId,
|
|
5821
|
-
actions,
|
|
5822
|
-
surfaces,
|
|
5823
|
-
autoFullscreen,
|
|
5824
|
-
closeWithFocus: (paneId, close) => {
|
|
5825
|
-
closeWithPaneFocus(document, sessionId, paneId, close);
|
|
5826
|
-
},
|
|
5827
|
-
openWithFocus: (open) => {
|
|
5828
|
-
openWithPaneFocus(document, sessionId, open);
|
|
5829
|
-
},
|
|
5830
|
-
canSplitPane: (paneId) => room.current.get(paneId)?.row !== false
|
|
5831
|
-
}) : void 0, [
|
|
5832
|
-
bindService,
|
|
5833
|
-
sessionId,
|
|
5834
|
-
actions,
|
|
5835
|
-
surfaces,
|
|
5836
|
-
autoFullscreen,
|
|
5837
|
-
active
|
|
5838
|
-
]);
|
|
5839
5789
|
if (surface === void 0) return null;
|
|
5840
5790
|
return (0, react_jsx_runtime.jsx)(SidebarPanel, {
|
|
5841
5791
|
sessionId,
|
|
@@ -5862,6 +5812,38 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5862
5812
|
});
|
|
5863
5813
|
}
|
|
5864
5814
|
//#endregion
|
|
5815
|
+
//#region lib/types/client/shell/close-focus.js
|
|
5816
|
+
/** Focus continuity after page operations replace docked or floating pane elements. */
|
|
5817
|
+
/**
|
|
5818
|
+
* Focus the page selected by an open or split after its DOM has committed.
|
|
5819
|
+
* @param document - product document owning the input focus.
|
|
5820
|
+
* @param sessionId - Session whose page is opening.
|
|
5821
|
+
* @param open - synchronous operation returning its selected pane, or undefined when unchanged.
|
|
5822
|
+
*/
|
|
5823
|
+
function openWithPaneFocus(document, sessionId, open) {
|
|
5824
|
+
let paneId;
|
|
5825
|
+
(0, react_dom.flushSync)(() => {
|
|
5826
|
+
paneId = open();
|
|
5827
|
+
});
|
|
5828
|
+
if (paneId !== void 0) visibleSidebarPane(document, sessionId, paneId)?.focus({ preventScroll: true });
|
|
5829
|
+
}
|
|
5830
|
+
/**
|
|
5831
|
+
* Commit a focused page's removal before focusing a surviving visible pane.
|
|
5832
|
+
* @param document - product document owning the input focus.
|
|
5833
|
+
* @param sessionId - Session whose page is closing.
|
|
5834
|
+
* @param paneId - pane whose page is closing; preferred if it survives.
|
|
5835
|
+
* @param close - synchronous cleanup and layout removal; errors preserve focus.
|
|
5836
|
+
*/
|
|
5837
|
+
function closeWithPaneFocus(document, sessionId, paneId, close) {
|
|
5838
|
+
const before = document.activeElement;
|
|
5839
|
+
const owner = before?.closest("[data-sidebar-right-session]");
|
|
5840
|
+
const source = before?.closest("[data-dockkit-pane], [data-dockkit-float]");
|
|
5841
|
+
const retain = owner?.dataset.sidebarRightSession === sessionId && (source?.dataset.dockkitPane ?? source?.dataset.dockkitFloat) === paneId;
|
|
5842
|
+
(0, react_dom.flushSync)(close);
|
|
5843
|
+
if (!retain || document.activeElement !== document.body && document.activeElement !== before) return;
|
|
5844
|
+
visibleSidebarPane(document, sessionId, paneId)?.focus({ preventScroll: true });
|
|
5845
|
+
}
|
|
5846
|
+
//#endregion
|
|
5865
5847
|
//#region lib/types/client/shell/RightbarRoot.js
|
|
5866
5848
|
/** Root-scoped controller for the right Sidebar's Session content. */
|
|
5867
5849
|
function SessionView({ view, visible, SessionProvider, renderSlot, mountView, width, viewportWidth, canShow }) {
|
|
@@ -6260,19 +6242,22 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6260
6242
|
*
|
|
6261
6243
|
* The surface is per session and its state lives in that session's store
|
|
6262
6244
|
* instance, which the slot runtime mints per session and a root service cannot
|
|
6263
|
-
* reach on its own.
|
|
6264
|
-
*
|
|
6265
|
-
*
|
|
6266
|
-
*
|
|
6267
|
-
*
|
|
6268
|
-
*
|
|
6269
|
-
*
|
|
6270
|
-
*
|
|
6271
|
-
*
|
|
6272
|
-
*
|
|
6245
|
+
* reach on its own. The plugin adopts each session's store instance as the
|
|
6246
|
+
* runtime mints it, so the controller reaches any session's store by id and
|
|
6247
|
+
* syncs the Tab domain from that store's commits, on screen or not.
|
|
6248
|
+
*
|
|
6249
|
+
* The plugin also names the Session on screen — the selected Session while the
|
|
6250
|
+
* Conversation fills the main column — from the selection and the main panel,
|
|
6251
|
+
* before React renders either change, and publishes it as `mounted`. Every
|
|
6252
|
+
* command on the public face acts on that Session through its adopted store; a
|
|
6253
|
+
* command with no Session on screen, or with one whose store the runtime has not
|
|
6254
|
+
* minted, has nothing to act on and fails loudly rather than writing into a
|
|
6255
|
+
* surface nobody is drawing. The seats never publish which Session they draw:
|
|
6256
|
+
* they report only what they render with, the room their docking kit measured
|
|
6257
|
+
* and the automatic fullscreen rule of their frame width.
|
|
6273
6258
|
*
|
|
6274
6259
|
* A tab's own actions (`tabActions`) aim at the session the tab is in, not at
|
|
6275
|
-
* the
|
|
6260
|
+
* the on-screen one: they run through that session's adopted store, so a callback
|
|
6276
6261
|
* fired after the user switched sessions still lands where its tab is, and they
|
|
6277
6262
|
* do nothing for a session whose store was never minted.
|
|
6278
6263
|
*
|
|
@@ -6284,24 +6269,39 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6284
6269
|
* hand the store one settled intent and record the navigation in the Tab
|
|
6285
6270
|
* domain. Placement is the caller's option, never a type's property.
|
|
6286
6271
|
*
|
|
6287
|
-
* The registration adopts Session stores
|
|
6288
|
-
* callers use the service's navigation methods.
|
|
6272
|
+
* The registration adopts Session stores, names the on-screen Session, and
|
|
6273
|
+
* forwards the seats' reports; callers use the service's navigation methods.
|
|
6289
6274
|
*/
|
|
6290
6275
|
/**
|
|
6291
|
-
* Create the public controller and the plugin-private
|
|
6276
|
+
* Create the public controller and the plugin-private Session callbacks.
|
|
6292
6277
|
* Adoption reconciles restored records before any seat renders, then follows commits.
|
|
6293
6278
|
* @param tabs - registered tab types.
|
|
6294
6279
|
* @param pin - resource retention for an occurrence's lifetime.
|
|
6295
|
-
* @
|
|
6280
|
+
* @param host - the viewport rule and focus continuity the commands use.
|
|
6281
|
+
* @returns the controller; store adoption and scope removal; naming the on-screen Session; and recording a seat's room rule.
|
|
6296
6282
|
*/
|
|
6297
|
-
function createSidebarRightController(tabs, pin) {
|
|
6283
|
+
function createSidebarRightController(tabs, pin, host) {
|
|
6298
6284
|
const adopted = /* @__PURE__ */ new Map();
|
|
6285
|
+
const rooms = /* @__PURE__ */ new Map();
|
|
6286
|
+
const onScreen = (0, _deepseek_ai_dsh_client_store.createSnapshotStore)(void 0);
|
|
6299
6287
|
const inventory = new SidebarTabInventory();
|
|
6300
|
-
const controller = new SidebarRightController(tabs, pin,
|
|
6288
|
+
const controller = new SidebarRightController(tabs, pin, host, {
|
|
6289
|
+
adopted,
|
|
6290
|
+
rooms,
|
|
6291
|
+
onScreen,
|
|
6292
|
+
openTabs: inventory.source
|
|
6293
|
+
});
|
|
6301
6294
|
return {
|
|
6302
6295
|
controller,
|
|
6303
6296
|
forget: (sessionId) => {
|
|
6304
6297
|
inventory.remove(sessionId);
|
|
6298
|
+
rooms.delete(sessionId);
|
|
6299
|
+
},
|
|
6300
|
+
show: (sessionId) => {
|
|
6301
|
+
if (onScreen.getSnapshot() !== sessionId) onScreen.set(sessionId);
|
|
6302
|
+
},
|
|
6303
|
+
measure: (sessionId, canSplitPane) => {
|
|
6304
|
+
rooms.set(sessionId, canSplitPane);
|
|
6305
6305
|
},
|
|
6306
6306
|
adopt(sessionId, store) {
|
|
6307
6307
|
adopted.get(sessionId)?.unsubscribe();
|
|
@@ -6328,13 +6328,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6328
6328
|
/** Cross-plugin right-Sidebar face (ctx.sidebarRight). */
|
|
6329
6329
|
var SidebarRightController = class {
|
|
6330
6330
|
tabs;
|
|
6331
|
-
|
|
6331
|
+
host;
|
|
6332
6332
|
/** Open tab metadata across saved and adopted Sessions, independent of visible seats. */
|
|
6333
6333
|
openTabs;
|
|
6334
|
-
|
|
6335
|
-
|
|
6336
|
-
|
|
6337
|
-
|
|
6334
|
+
/** The on-screen Session; see {@link ISidebarRight.mounted}. */
|
|
6335
|
+
mounted;
|
|
6336
|
+
adopted;
|
|
6337
|
+
rooms;
|
|
6338
6338
|
closeHandlers = /* @__PURE__ */ new Map();
|
|
6339
6339
|
/**
|
|
6340
6340
|
* Register resource cleanup before explicit removal. Failure preserves the tab.
|
|
@@ -6357,13 +6357,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6357
6357
|
/**
|
|
6358
6358
|
* @param tabs - the tab-type registry consulted to claim an address.
|
|
6359
6359
|
* @param pin - `ctx.resources.pin`, which the Tab domain holds addresses with.
|
|
6360
|
-
* @param
|
|
6361
|
-
* @param
|
|
6360
|
+
* @param host - the viewport rule and focus continuity the commands use.
|
|
6361
|
+
* @param sessions - plugin-owned adopted stores, room rules, on-screen Session, and open tab metadata.
|
|
6362
6362
|
*/
|
|
6363
|
-
constructor(tabs, pin,
|
|
6363
|
+
constructor(tabs, pin, host, sessions) {
|
|
6364
6364
|
this.tabs = tabs;
|
|
6365
|
-
this.
|
|
6366
|
-
this.
|
|
6365
|
+
this.host = host;
|
|
6366
|
+
this.adopted = sessions.adopted;
|
|
6367
|
+
this.rooms = sessions.rooms;
|
|
6368
|
+
this.mounted = sessions.onScreen;
|
|
6369
|
+
this.openTabs = sessions.openTabs;
|
|
6367
6370
|
this.tabDomain = new TabDomain(this, pin);
|
|
6368
6371
|
}
|
|
6369
6372
|
/**
|
|
@@ -6375,27 +6378,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6375
6378
|
return Object.values(this.adopted.get(sessionId)?.store.getSnapshot().bySession[sessionId]?.layout.tabs ?? {});
|
|
6376
6379
|
}
|
|
6377
6380
|
/**
|
|
6378
|
-
* Adopt the mounted seat's binding, replacing any previous one.
|
|
6379
|
-
*
|
|
6380
|
-
* Called from the seat while it is mounted, and released when it leaves.
|
|
6381
|
-
* @param binding - the mounted seat's session, actions, and the store's surfaces.
|
|
6382
|
-
* @returns a release callback that clears exactly this binding.
|
|
6383
|
-
*/
|
|
6384
|
-
bind(binding) {
|
|
6385
|
-
this.binding = binding;
|
|
6386
|
-
this.publishMounted();
|
|
6387
|
-
return () => {
|
|
6388
|
-
if (this.binding !== binding) return;
|
|
6389
|
-
this.binding = void 0;
|
|
6390
|
-
this.publishMounted();
|
|
6391
|
-
};
|
|
6392
|
-
}
|
|
6393
|
-
/** Publish the mounted session only when it changes; a republished binding for the same session is silent. */
|
|
6394
|
-
publishMounted() {
|
|
6395
|
-
const next = this.binding?.sessionId;
|
|
6396
|
-
if (this.mountedSession.getSnapshot() !== next) this.mountedSession.set(next);
|
|
6397
|
-
}
|
|
6398
|
-
/**
|
|
6399
6381
|
* Open a resource: claim it, place it, reveal the column, record the navigation.
|
|
6400
6382
|
* @param address - a `dsh-resource://<type>/…` address.
|
|
6401
6383
|
* @param options - placement, the opening type, and navigation parameters.
|
|
@@ -6476,10 +6458,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6476
6458
|
}
|
|
6477
6459
|
/** The steps both opens share: one store intent, and the navigation record for the tab it settles on. */
|
|
6478
6460
|
place(sessionId, actions, claim, address, placement, params) {
|
|
6479
|
-
const surface = this.adopted.get(sessionId)?.store.getSnapshot().bySession[sessionId]
|
|
6461
|
+
const surface = this.adopted.get(sessionId)?.store.getSnapshot().bySession[sessionId];
|
|
6480
6462
|
const targetPane = surface === void 0 ? void 0 : placement.paneId ?? (0, _deepseek_ai_dsh_client_ui_dockkit.activeDockPaneId)(surface.layout);
|
|
6481
6463
|
const target = targetPane === void 0 ? void 0 : surface?.layout.nodes[targetPane];
|
|
6482
|
-
const preferNewPane = placement.preferNewPane === true && placement.replaceTab === void 0 && surface !== void 0 && target?.kind === "pane" && target.host === "dock" && target.tabs.length > 0 && (0, _deepseek_ai_dsh_client_ui_dockkit.canSplit)(surface.layout) && (0, _deepseek_ai_dsh_client_ui_dockkit.dockPaneIds)(surface.layout).length < 2 && this.
|
|
6464
|
+
const preferNewPane = placement.preferNewPane === true && placement.replaceTab === void 0 && surface !== void 0 && target?.kind === "pane" && target.host === "dock" && target.tabs.length > 0 && (0, _deepseek_ai_dsh_client_ui_dockkit.canSplit)(surface.layout) && (0, _deepseek_ai_dsh_client_ui_dockkit.dockPaneIds)(surface.layout).length < 2 && this.mounted.getSnapshot() === sessionId && this.canSplitPane(sessionId, target.id);
|
|
6483
6465
|
const commit = () => {
|
|
6484
6466
|
actions.openContent(sessionId, {
|
|
6485
6467
|
kind: claim.kind,
|
|
@@ -6498,7 +6480,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6498
6480
|
};
|
|
6499
6481
|
const layout = surface?.layout;
|
|
6500
6482
|
const replaced = placement.replaceTab === void 0 ? void 0 : layout?.tabs[placement.replaceTab];
|
|
6501
|
-
const
|
|
6483
|
+
const replacementPane = replaced === void 0 || layout === void 0 ? void 0 : (0, _deepseek_ai_dsh_client_ui_dockkit.findTabPane)(layout, replaced.id);
|
|
6484
|
+
const revealed = layout === void 0 ? void 0 : claim.contentId === pageAddress(claim.kind) ? (0, _deepseek_ai_dsh_client_ui_dockkit.findPaneContentTab)(layout, replacementPane?.host === "dock" ? replacementPane.id : placement.paneId ?? (0, _deepseek_ai_dsh_client_ui_dockkit.activeDockPaneId)(layout), claim.contentId, claim.kind) : placement.revealIfOpened === false ? void 0 : (0, _deepseek_ai_dsh_client_ui_dockkit.findContentTab)(layout, claim.contentId, claim.kind);
|
|
6502
6485
|
if (replaced === void 0 || replaced.id === revealed) {
|
|
6503
6486
|
commit();
|
|
6504
6487
|
return;
|
|
@@ -6506,20 +6489,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6506
6489
|
this.removeAfterCleanup(sessionId, replaced, commit);
|
|
6507
6490
|
}
|
|
6508
6491
|
/**
|
|
6509
|
-
* Close one tab of the
|
|
6492
|
+
* Close one tab of the on-screen Session; the sole docked guide remains open.
|
|
6510
6493
|
* @param tabId - the tab to close.
|
|
6511
6494
|
*/
|
|
6512
6495
|
close(tabId) {
|
|
6513
|
-
|
|
6514
|
-
if (this.adopted.has(sessionId)) {
|
|
6515
|
-
this.closeIn(sessionId, tabId);
|
|
6516
|
-
return;
|
|
6517
|
-
}
|
|
6518
|
-
actions.closeTab(sessionId, tabId);
|
|
6496
|
+
this.closeIn(this.require().sessionId, tabId);
|
|
6519
6497
|
}
|
|
6520
6498
|
/**
|
|
6521
6499
|
* The active tab of the active pane.
|
|
6522
|
-
* @returns the record, or `undefined`
|
|
6500
|
+
* @returns the record, or `undefined` without an on-screen surface.
|
|
6523
6501
|
*/
|
|
6524
6502
|
active() {
|
|
6525
6503
|
const layout = this.mountedSurface()?.layout;
|
|
@@ -6529,15 +6507,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6529
6507
|
}
|
|
6530
6508
|
/**
|
|
6531
6509
|
* Whether the column is currently showing its panel.
|
|
6532
|
-
* @returns `true` while expanded; `false` while collapsed or
|
|
6510
|
+
* @returns `true` while expanded; `false` while collapsed or without an on-screen surface.
|
|
6533
6511
|
*/
|
|
6534
6512
|
isExpanded() {
|
|
6535
6513
|
return this.mountedSurface()?.layout.expanded ?? false;
|
|
6536
6514
|
}
|
|
6537
6515
|
/** Collapse the column, or expand it and focus its active dock pane after rendering. */
|
|
6538
6516
|
toggleExpanded() {
|
|
6539
|
-
const { sessionId, actions
|
|
6540
|
-
openWithFocus(() => {
|
|
6517
|
+
const { sessionId, actions } = this.require();
|
|
6518
|
+
this.host.openWithFocus(sessionId, () => {
|
|
6541
6519
|
actions.toggleExpanded(sessionId);
|
|
6542
6520
|
const layout = this.mountedSurface()?.layout;
|
|
6543
6521
|
return layout?.expanded ? (0, _deepseek_ai_dsh_client_ui_dockkit.activeDockPaneId)(layout) : void 0;
|
|
@@ -6558,26 +6536,25 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6558
6536
|
* @returns current focused page identity, or undefined outside a visible sidebar page.
|
|
6559
6537
|
*/
|
|
6560
6538
|
focusedTarget(element = document.activeElement) {
|
|
6561
|
-
const
|
|
6562
|
-
|
|
6563
|
-
return binding === void 0 || surface === void 0 ? void 0 : sidebarTargetFromElement(element, binding.sessionId, surface.layout, (tabId) => this.tabDomain.occurrence(binding.sessionId, { id: tabId }));
|
|
6539
|
+
const screen = this.screen();
|
|
6540
|
+
return screen === void 0 ? void 0 : sidebarTargetFromElement(element, screen.sessionId, screen.surface.layout, (tabId) => this.tabDomain.occurrence(screen.sessionId, { id: tabId }));
|
|
6564
6541
|
}
|
|
6565
6542
|
/**
|
|
6566
|
-
* Choose a focused sidebar pane, or the
|
|
6543
|
+
* Choose a focused sidebar pane, or the on-screen Session's active dock pane for an outside open.
|
|
6567
6544
|
* @param element - live command input target; stale sidebar markup never falls back to another pane.
|
|
6568
|
-
* @returns captured target, or undefined without
|
|
6545
|
+
* @returns captured target, or undefined without an on-screen surface.
|
|
6569
6546
|
*/
|
|
6570
6547
|
commandTarget(element = document.activeElement) {
|
|
6571
6548
|
const focused = this.focusedTarget(element);
|
|
6572
6549
|
if (focused !== void 0 || element?.closest("[data-sidebar-right-session]")) return focused;
|
|
6573
|
-
const
|
|
6574
|
-
|
|
6575
|
-
|
|
6550
|
+
const screen = this.screen();
|
|
6551
|
+
if (screen === void 0) return void 0;
|
|
6552
|
+
const { sessionId, surface: { layout } } = screen;
|
|
6576
6553
|
const pane = (0, _deepseek_ai_dsh_client_ui_dockkit.getPane)(layout, (0, _deepseek_ai_dsh_client_ui_dockkit.activeDockPaneId)(layout));
|
|
6577
6554
|
const tabId = pane.activeTabId;
|
|
6578
|
-
const held = tabId === void 0 ? void 0 : this.tabDomain.occurrence(
|
|
6555
|
+
const held = tabId === void 0 ? void 0 : this.tabDomain.occurrence(sessionId, { id: tabId });
|
|
6579
6556
|
return {
|
|
6580
|
-
sessionId
|
|
6557
|
+
sessionId,
|
|
6581
6558
|
paneId: pane.id,
|
|
6582
6559
|
host: pane.host,
|
|
6583
6560
|
tabId,
|
|
@@ -6592,10 +6569,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6592
6569
|
*/
|
|
6593
6570
|
openTabFromTarget(kind, target) {
|
|
6594
6571
|
if (!this.isTargetCurrent(target)) return;
|
|
6595
|
-
this.require()
|
|
6572
|
+
const { sessionId, actions } = this.require();
|
|
6573
|
+
this.host.openWithFocus(sessionId, () => {
|
|
6596
6574
|
const tab = target.tabId === void 0 ? void 0 : this.mountedSurface()?.layout.tabs[target.tabId];
|
|
6597
6575
|
if (target.host === "float" && tab?.kind === kind && this.tabs.get(kind)?.multiple !== true) {
|
|
6598
|
-
|
|
6576
|
+
actions.setExpanded(sessionId, true);
|
|
6599
6577
|
this.focus(tab.id);
|
|
6600
6578
|
} else this.openTab(kind, {
|
|
6601
6579
|
...target.host === "dock" ? { paneId: target.paneId } : {},
|
|
@@ -6623,20 +6601,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6623
6601
|
const surface = this.mountedSurface();
|
|
6624
6602
|
if (surface === void 0 || target.tabId === void 0) return "unavailable";
|
|
6625
6603
|
const tabId = target.tabId;
|
|
6626
|
-
const
|
|
6627
|
-
|
|
6604
|
+
const { sessionId, actions } = this.require();
|
|
6605
|
+
this.host.closeWithFocus(sessionId, target.paneId, () => {
|
|
6628
6606
|
if (canCloseTab(surface, tabId)) this.close(tabId);
|
|
6629
|
-
else
|
|
6607
|
+
else actions.setExpanded(sessionId, false);
|
|
6630
6608
|
});
|
|
6631
6609
|
return "closed";
|
|
6632
6610
|
}
|
|
6633
6611
|
/**
|
|
6634
6612
|
* Check a captured target before acting, including reopened records and intervening navigation.
|
|
6635
6613
|
* @param target - identity captured while resolving the input.
|
|
6636
|
-
* @returns whether the
|
|
6614
|
+
* @returns whether the on-screen Session, pane, tab lifetime and navigation still match.
|
|
6637
6615
|
*/
|
|
6638
6616
|
isTargetCurrent(target) {
|
|
6639
|
-
if (this.
|
|
6617
|
+
if (this.mounted.getSnapshot() !== target.sessionId) return false;
|
|
6640
6618
|
const layout = this.mountedSurface()?.layout;
|
|
6641
6619
|
const pane = layout?.nodes[target.paneId];
|
|
6642
6620
|
if (pane?.kind !== "pane" || pane.host !== target.host) return false;
|
|
@@ -6658,7 +6636,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6658
6636
|
if (!layout.expanded) return "collapsed";
|
|
6659
6637
|
if ((0, _deepseek_ai_dsh_client_ui_dockkit.getPane)(layout, target.paneId).tabs.length === 0) return "empty";
|
|
6660
6638
|
if (!(0, _deepseek_ai_dsh_client_ui_dockkit.canSplit)(layout) || (0, _deepseek_ai_dsh_client_ui_dockkit.dockPaneIds)(layout).length >= 2) return "budget";
|
|
6661
|
-
if (!this.
|
|
6639
|
+
if (!this.canSplitPane(target.sessionId, target.paneId)) return "width";
|
|
6662
6640
|
}
|
|
6663
6641
|
/**
|
|
6664
6642
|
* Toggle the right panel's display mode through the same action as its chrome button.
|
|
@@ -6666,9 +6644,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6666
6644
|
*/
|
|
6667
6645
|
toggleFullscreen(target) {
|
|
6668
6646
|
if (!this.isTargetCurrent(target) || target.host === "float" || !this.isExpanded()) return;
|
|
6669
|
-
const { sessionId, actions
|
|
6670
|
-
const
|
|
6671
|
-
|
|
6647
|
+
const { sessionId, actions } = this.require();
|
|
6648
|
+
const autoFullscreen = this.host.autoFullscreen();
|
|
6649
|
+
const fullscreen = autoFullscreen || this.mountedSurface()?.layout.mode === "fullscreen";
|
|
6650
|
+
if (fullscreen && autoFullscreen) actions.setExpanded(sessionId, false);
|
|
6672
6651
|
actions.setMode(sessionId, fullscreen ? "push" : "fullscreen");
|
|
6673
6652
|
}
|
|
6674
6653
|
/**
|
|
@@ -6677,15 +6656,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6677
6656
|
* @returns the new pane's id, or `undefined` when nothing was split.
|
|
6678
6657
|
*/
|
|
6679
6658
|
split(paneId) {
|
|
6680
|
-
const { sessionId, actions
|
|
6659
|
+
const { sessionId, actions } = this.require();
|
|
6681
6660
|
const layout = this.mountedSurface()?.layout;
|
|
6682
6661
|
if (layout === void 0) return void 0;
|
|
6683
6662
|
const target = paneId ?? (0, _deepseek_ai_dsh_client_ui_dockkit.activeDockPaneId)(layout);
|
|
6684
6663
|
const node = layout.nodes[target];
|
|
6685
6664
|
if (node === void 0 || node.kind !== "pane" || node.host !== "dock") return void 0;
|
|
6686
|
-
if (!(0, _deepseek_ai_dsh_client_ui_dockkit.canSplit)(layout) || (0, _deepseek_ai_dsh_client_ui_dockkit.dockPaneIds)(layout).length >= 2 || !canSplitPane(target)) return void 0;
|
|
6665
|
+
if (!(0, _deepseek_ai_dsh_client_ui_dockkit.canSplit)(layout) || (0, _deepseek_ai_dsh_client_ui_dockkit.dockPaneIds)(layout).length >= 2 || !this.canSplitPane(sessionId, target)) return void 0;
|
|
6687
6666
|
let created;
|
|
6688
|
-
this.
|
|
6667
|
+
this.host.openWithFocus(sessionId, () => {
|
|
6689
6668
|
actions.splitPane(sessionId, target, (id) => {
|
|
6690
6669
|
created = id;
|
|
6691
6670
|
});
|
|
@@ -6716,7 +6695,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6716
6695
|
actions.unfloatPane(sessionId, paneId);
|
|
6717
6696
|
}
|
|
6718
6697
|
/**
|
|
6719
|
-
* Step the
|
|
6698
|
+
* Step the on-screen Session's surface back one intent.
|
|
6720
6699
|
*
|
|
6721
6700
|
* @internal Not part of the product: the sequence is an architectural fact
|
|
6722
6701
|
* with no user-facing control yet. Kept reachable for tests.
|
|
@@ -6726,7 +6705,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6726
6705
|
actions.undo(sessionId);
|
|
6727
6706
|
}
|
|
6728
6707
|
/**
|
|
6729
|
-
* Step the
|
|
6708
|
+
* Step the on-screen Session's surface forward one intent.
|
|
6730
6709
|
*
|
|
6731
6710
|
* @internal See `_undo`.
|
|
6732
6711
|
*/
|
|
@@ -6734,10 +6713,26 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6734
6713
|
const { sessionId, actions } = this.require();
|
|
6735
6714
|
actions.redo(sessionId);
|
|
6736
6715
|
}
|
|
6737
|
-
/**
|
|
6716
|
+
/**
|
|
6717
|
+
* The on-screen Session and its committed surface; `undefined` with no Session
|
|
6718
|
+
* on screen, before the runtime mints its store, or before its first open.
|
|
6719
|
+
*/
|
|
6720
|
+
screen() {
|
|
6721
|
+
const sessionId = this.mounted.getSnapshot();
|
|
6722
|
+
if (sessionId === void 0) return void 0;
|
|
6723
|
+
const surface = this.adopted.get(sessionId)?.store.getSnapshot().bySession[sessionId];
|
|
6724
|
+
return surface === void 0 ? void 0 : {
|
|
6725
|
+
sessionId,
|
|
6726
|
+
surface
|
|
6727
|
+
};
|
|
6728
|
+
}
|
|
6729
|
+
/** The on-screen Session's surface; see {@link SidebarRightController.screen}. */
|
|
6738
6730
|
mountedSurface() {
|
|
6739
|
-
|
|
6740
|
-
|
|
6731
|
+
return this.screen()?.surface;
|
|
6732
|
+
}
|
|
6733
|
+
/** Whether a Session's docked pane has room for two working halves, as its seat last measured; unmeasured panes do. */
|
|
6734
|
+
canSplitPane(sessionId, paneId) {
|
|
6735
|
+
return this.rooms.get(sessionId)?.(paneId) ?? true;
|
|
6741
6736
|
}
|
|
6742
6737
|
/**
|
|
6743
6738
|
* The store actions a tab's own action on `sessionId` runs through: that
|
|
@@ -6748,8 +6743,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6748
6743
|
return this.adopted.get(sessionId)?.store.actions;
|
|
6749
6744
|
}
|
|
6750
6745
|
require() {
|
|
6751
|
-
|
|
6752
|
-
|
|
6746
|
+
const sessionId = this.mounted.getSnapshot();
|
|
6747
|
+
const actions = sessionId === void 0 ? void 0 : this.actionsFor(sessionId);
|
|
6748
|
+
if (sessionId === void 0 || actions === void 0) throw new Error("sidebarRight: no session surface is mounted");
|
|
6749
|
+
return {
|
|
6750
|
+
sessionId,
|
|
6751
|
+
actions
|
|
6752
|
+
};
|
|
6753
6753
|
}
|
|
6754
6754
|
};
|
|
6755
6755
|
//#endregion
|
|
@@ -9044,9 +9044,33 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9044
9044
|
views.dispose();
|
|
9045
9045
|
};
|
|
9046
9046
|
}, "ui-sidebar-right: retained Session views");
|
|
9047
|
-
const
|
|
9047
|
+
const layout = ctx.layout;
|
|
9048
|
+
let autoFullscreen = false;
|
|
9049
|
+
const { controller, adopt, forget, show, measure } = createSidebarRightController(tabs, (address, signal) => {
|
|
9048
9050
|
ctx.resources.pin(address, signal);
|
|
9051
|
+
}, {
|
|
9052
|
+
autoFullscreen: () => autoFullscreen,
|
|
9053
|
+
openWithFocus: (sessionId, open) => {
|
|
9054
|
+
openWithPaneFocus(document, sessionId, open);
|
|
9055
|
+
},
|
|
9056
|
+
closeWithFocus: (sessionId, paneId, close) => {
|
|
9057
|
+
closeWithPaneFocus(document, sessionId, paneId, close);
|
|
9058
|
+
}
|
|
9049
9059
|
});
|
|
9060
|
+
ctx.effect(() => {
|
|
9061
|
+
const sync = () => {
|
|
9062
|
+
const selected = views.source.getSnapshot().find((view) => view.selected);
|
|
9063
|
+
show(layout.panelInfo.getSnapshot().activePanelId === null ? selected?.sessionId : void 0);
|
|
9064
|
+
};
|
|
9065
|
+
const unsubscribeViews = views.source.subscribe(sync);
|
|
9066
|
+
const unsubscribePanel = layout.panelInfo.subscribe(sync);
|
|
9067
|
+
sync();
|
|
9068
|
+
return () => {
|
|
9069
|
+
unsubscribeViews();
|
|
9070
|
+
unsubscribePanel();
|
|
9071
|
+
show(void 0);
|
|
9072
|
+
};
|
|
9073
|
+
}, "ui-sidebar-right: on-screen Session");
|
|
9050
9074
|
const disposeRegistry = ctx.reflect.provide("sidebarRightTabs", tabs);
|
|
9051
9075
|
const disposeService = ctx.reflect.provide("sidebarRight", controller);
|
|
9052
9076
|
ctx.effect(() => () => {
|
|
@@ -9085,13 +9109,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9085
9109
|
};
|
|
9086
9110
|
}
|
|
9087
9111
|
};
|
|
9088
|
-
const layout = ctx.layout;
|
|
9089
9112
|
const injected = {
|
|
9090
9113
|
syncPresentation({ shown, track, fullscreen }) {
|
|
9091
9114
|
if (shown) layout.openRightbar(track, fullscreen);
|
|
9092
9115
|
else layout.closeRightbar();
|
|
9093
9116
|
},
|
|
9094
|
-
|
|
9117
|
+
reportAutoFullscreen: (value) => {
|
|
9118
|
+
autoFullscreen = value;
|
|
9119
|
+
},
|
|
9095
9120
|
splitPane: (paneId) => {
|
|
9096
9121
|
controller.split(paneId);
|
|
9097
9122
|
},
|
|
@@ -9145,6 +9170,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9145
9170
|
store,
|
|
9146
9171
|
inject: (sessionId) => ({
|
|
9147
9172
|
...injected,
|
|
9173
|
+
measureRoom: (canSplitPane) => {
|
|
9174
|
+
measure(sessionId, canSplitPane);
|
|
9175
|
+
},
|
|
9148
9176
|
closeTab: (tabId) => {
|
|
9149
9177
|
try {
|
|
9150
9178
|
controller.closeIn(sessionId, tabId);
|
|
@@ -6,7 +6,7 @@ export type { RightbarSeatProps, SidebarRightInjected, SidebarRightPresentation
|
|
|
6
6
|
export type { GuideBodyProps, GuideInjected } from './tabs/guide/GuideBody.tsx';
|
|
7
7
|
export type { ExpandButtonProps } from './shell/ExpandButton.tsx';
|
|
8
8
|
export type { SidebarRightState, SurfaceState } from './stores.ts';
|
|
9
|
-
export type { ISidebarRight,
|
|
9
|
+
export type { ISidebarRight, SidebarRightOpenResourceOptions, SidebarRightOpenTabOptions, SidebarRightPlacement, SidebarRightCloseHandler, SurfaceActions, } from './service.ts';
|
|
10
10
|
export type { SidebarRightGuideBox, SidebarRightGuideEntry, SidebarRightTabClaim, SidebarRightTabDefinition, SidebarRightTabPriority, } from './tab-registry.ts';
|
|
11
11
|
export type { SidebarRightTabInfo, SidebarRightTabInjected, UseSidebarRightTabInfo, SidebarRightTabActions, SidebarRightTabMenuOwnerProps, SidebarRightTabNavigation, SidebarRightTabPlacement, SidebarRightGuideEntryOwnerProps, } from './contract/slots.ts';
|
|
12
12
|
export type { SidebarRightNavigationParams, SidebarRightResourceParams, SidebarRightResourceParamsMap, SidebarRightTabParams, SidebarRightTabParamsFor, SidebarRightTabParamsMap, } from './contract/params.ts';
|
|
@@ -3,19 +3,22 @@
|
|
|
3
3
|
*
|
|
4
4
|
* The surface is per session and its state lives in that session's store
|
|
5
5
|
* instance, which the slot runtime mints per session and a root service cannot
|
|
6
|
-
* reach on its own.
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
6
|
+
* reach on its own. The plugin adopts each session's store instance as the
|
|
7
|
+
* runtime mints it, so the controller reaches any session's store by id and
|
|
8
|
+
* syncs the Tab domain from that store's commits, on screen or not.
|
|
9
|
+
*
|
|
10
|
+
* The plugin also names the Session on screen — the selected Session while the
|
|
11
|
+
* Conversation fills the main column — from the selection and the main panel,
|
|
12
|
+
* before React renders either change, and publishes it as `mounted`. Every
|
|
13
|
+
* command on the public face acts on that Session through its adopted store; a
|
|
14
|
+
* command with no Session on screen, or with one whose store the runtime has not
|
|
15
|
+
* minted, has nothing to act on and fails loudly rather than writing into a
|
|
16
|
+
* surface nobody is drawing. The seats never publish which Session they draw:
|
|
17
|
+
* they report only what they render with, the room their docking kit measured
|
|
18
|
+
* and the automatic fullscreen rule of their frame width.
|
|
16
19
|
*
|
|
17
20
|
* A tab's own actions (`tabActions`) aim at the session the tab is in, not at
|
|
18
|
-
* the
|
|
21
|
+
* the on-screen one: they run through that session's adopted store, so a callback
|
|
19
22
|
* fired after the user switched sessions still lands where its tab is, and they
|
|
20
23
|
* do nothing for a session whose store was never minted.
|
|
21
24
|
*
|
|
@@ -27,8 +30,8 @@
|
|
|
27
30
|
* hand the store one settled intent and record the navigation in the Tab
|
|
28
31
|
* domain. Placement is the caller's option, never a type's property.
|
|
29
32
|
*
|
|
30
|
-
* The registration adopts Session stores
|
|
31
|
-
* callers use the service's navigation methods.
|
|
33
|
+
* The registration adopts Session stores, names the on-screen Session, and
|
|
34
|
+
* forwards the seats' reports; callers use the service's navigation methods.
|
|
32
35
|
*/
|
|
33
36
|
import { type SidebarRightTarget } from './focus.ts';
|
|
34
37
|
import { type ObservableSnapshot } from '@deepseek-ai/dsh-client-store';
|
|
@@ -37,7 +40,7 @@ import type { BoundActions } from '@deepseek-ai/dsh-client-ui-slots';
|
|
|
37
40
|
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
38
41
|
import type { SidebarRightResourceParams, SidebarRightTabParamsFor } from './contract/params.ts';
|
|
39
42
|
import type { SidebarRightTabRegistry } from './tab-registry.ts';
|
|
40
|
-
import { type SidebarRightState
|
|
43
|
+
import { type SidebarRightState } from './stores.ts';
|
|
41
44
|
import type { createSidebarRightStore } from './stores.ts';
|
|
42
45
|
import { TabDomain, type PinResource } from './tab-domain.ts';
|
|
43
46
|
import { SidebarTabInventory } from './tab-inventory.ts';
|
|
@@ -54,41 +57,54 @@ interface Adoption {
|
|
|
54
57
|
readonly store: SidebarRightSurfaceStore;
|
|
55
58
|
readonly unsubscribe: () => void;
|
|
56
59
|
}
|
|
60
|
+
/** The room rule's verdict for a docked pane, as a seat's docking kit last measured it: whether two working halves would fit. */
|
|
61
|
+
type RoomRule = (paneId: PaneId) => boolean;
|
|
62
|
+
/** Plugin-owned Session state the controller reads; the plugin writes it through the factory's callbacks. */
|
|
63
|
+
interface SidebarRightSessions {
|
|
64
|
+
/** Each Session's latest adopted store. */
|
|
65
|
+
readonly adopted: ReadonlyMap<SessionId, Adoption>;
|
|
66
|
+
/** Each Session's room rule as its seat last reported it; a Session without one has room in every pane. */
|
|
67
|
+
readonly rooms: ReadonlyMap<SessionId, RoomRule>;
|
|
68
|
+
/** The Session the plugin names as on screen. */
|
|
69
|
+
readonly onScreen: ObservableSnapshot<SessionId | undefined>;
|
|
70
|
+
/** Open tab metadata across saved and adopted Sessions. */
|
|
71
|
+
readonly openTabs: SidebarTabInventory['source'];
|
|
72
|
+
}
|
|
57
73
|
/**
|
|
58
|
-
* Create the public controller and the plugin-private
|
|
74
|
+
* Create the public controller and the plugin-private Session callbacks.
|
|
59
75
|
* Adoption reconciles restored records before any seat renders, then follows commits.
|
|
60
76
|
* @param tabs - registered tab types.
|
|
61
77
|
* @param pin - resource retention for an occurrence's lifetime.
|
|
62
|
-
* @
|
|
78
|
+
* @param host - the viewport rule and focus continuity the commands use.
|
|
79
|
+
* @returns the controller; store adoption and scope removal; naming the on-screen Session; and recording a seat's room rule.
|
|
63
80
|
*/
|
|
64
|
-
export declare function createSidebarRightController(tabs: SidebarRightTabRegistry, pin: PinResource): {
|
|
81
|
+
export declare function createSidebarRightController(tabs: SidebarRightTabRegistry, pin: PinResource, host: SidebarRightHost): {
|
|
65
82
|
controller: SidebarRightController;
|
|
66
83
|
adopt: (sessionId: SessionId, store: SidebarRightSurfaceStore) => () => void;
|
|
67
84
|
forget: (sessionId: SessionId) => void;
|
|
85
|
+
show: (sessionId: SessionId | undefined) => void;
|
|
86
|
+
measure: (sessionId: SessionId, canSplitPane: RoomRule) => void;
|
|
68
87
|
};
|
|
69
|
-
/**
|
|
70
|
-
export interface
|
|
71
|
-
/** The session the mounted seat is drawing. */
|
|
72
|
-
readonly sessionId: SessionId;
|
|
73
|
-
/** The seat's store's bound actions; every action names the session it acts on. */
|
|
74
|
-
readonly actions: SurfaceActions;
|
|
88
|
+
/** What the controller needs from the page around it: the viewport rule and focus continuity. */
|
|
89
|
+
export interface SidebarRightHost {
|
|
75
90
|
/**
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
* open. The runtime mints one store per session, so this holds that session.
|
|
91
|
+
* Whether the viewport is narrow enough that an expanded panel is presented fullscreen.
|
|
92
|
+
* @returns the rule's verdict for the frame width the seats last rendered at.
|
|
79
93
|
*/
|
|
80
|
-
readonly
|
|
94
|
+
readonly autoFullscreen: () => boolean;
|
|
81
95
|
/**
|
|
82
|
-
*
|
|
83
|
-
*
|
|
96
|
+
* Commit a page operation and focus the pane it selects.
|
|
97
|
+
* @param sessionId - the Session whose page is opening.
|
|
98
|
+
* @param open - the synchronous operation; returns the selected pane, or `undefined` when unchanged.
|
|
84
99
|
*/
|
|
85
|
-
readonly
|
|
86
|
-
/**
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
100
|
+
readonly openWithFocus: (sessionId: SessionId, open: () => PaneId | undefined) => void;
|
|
101
|
+
/**
|
|
102
|
+
* Commit a keyboard/menu close and retain focus on a surviving visible pane.
|
|
103
|
+
* @param sessionId - the Session whose page is closing.
|
|
104
|
+
* @param paneId - the pane whose page is closing.
|
|
105
|
+
* @param close - the synchronous cleanup and removal.
|
|
106
|
+
*/
|
|
107
|
+
readonly closeWithFocus: (sessionId: SessionId, paneId: PaneId, close: () => void) => void;
|
|
92
108
|
}
|
|
93
109
|
/** Where an open lands; every field is optional and the defaults are the common case. */
|
|
94
110
|
export interface SidebarRightPlacement {
|
|
@@ -121,12 +137,13 @@ export type SidebarRightCloseHandler = (sessionId: SessionId, tab: TabRecord) =>
|
|
|
121
137
|
/** The outward right-Sidebar face (`ctx.sidebarRight`). */
|
|
122
138
|
export interface ISidebarRight {
|
|
123
139
|
/**
|
|
124
|
-
* The
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
140
|
+
* The Session on screen, or `undefined` while none is (a global panel fills
|
|
141
|
+
* the main column, or no Session is selected). It changes before React
|
|
142
|
+
* renders the selection or panel change that causes it, so every component
|
|
143
|
+
* rendered in that commit reads the arriving Session, and the commands act on
|
|
144
|
+
* it from that commit's effects: its seat mints its store in the same render.
|
|
145
|
+
* Moves only when the on-screen Session changes; the Session's own store
|
|
146
|
+
* commits are silent.
|
|
130
147
|
*/
|
|
131
148
|
readonly mounted: ObservableSnapshot<SessionId | undefined>;
|
|
132
149
|
/**
|
|
@@ -150,13 +167,13 @@ export interface ISidebarRight {
|
|
|
150
167
|
*/
|
|
151
168
|
openTab<K extends string>(kind: K, options?: SidebarRightOpenTabOptions<K>): void;
|
|
152
169
|
/**
|
|
153
|
-
* Close one tab of the
|
|
170
|
+
* Close one tab of the on-screen Session; the sole docked guide remains open.
|
|
154
171
|
* @param tabId - the tab to close.
|
|
155
172
|
*/
|
|
156
173
|
close(tabId: TabId): void;
|
|
157
174
|
/**
|
|
158
175
|
* The active tab of the active pane.
|
|
159
|
-
* @returns the record, or `undefined`
|
|
176
|
+
* @returns the record, or `undefined` with no Session on screen.
|
|
160
177
|
*/
|
|
161
178
|
active(): TabRecord | undefined;
|
|
162
179
|
/**
|
|
@@ -195,13 +212,13 @@ export interface ISidebarRight {
|
|
|
195
212
|
/** Cross-plugin right-Sidebar face (ctx.sidebarRight). */
|
|
196
213
|
export declare class SidebarRightController implements ISidebarRight {
|
|
197
214
|
private readonly tabs;
|
|
198
|
-
private readonly
|
|
215
|
+
private readonly host;
|
|
199
216
|
/** Open tab metadata across saved and adopted Sessions, independent of visible seats. */
|
|
200
217
|
readonly openTabs: SidebarTabInventory['source'];
|
|
201
|
-
|
|
202
|
-
/** The mounted seat's session; see {@link ISidebarRight.mounted}. */
|
|
218
|
+
/** The on-screen Session; see {@link ISidebarRight.mounted}. */
|
|
203
219
|
readonly mounted: ObservableSnapshot<SessionId | undefined>;
|
|
204
|
-
private
|
|
220
|
+
private readonly adopted;
|
|
221
|
+
private readonly rooms;
|
|
205
222
|
private readonly closeHandlers;
|
|
206
223
|
/**
|
|
207
224
|
* Register resource cleanup before explicit removal. Failure preserves the tab.
|
|
@@ -218,26 +235,16 @@ export declare class SidebarRightController implements ISidebarRight {
|
|
|
218
235
|
/**
|
|
219
236
|
* @param tabs - the tab-type registry consulted to claim an address.
|
|
220
237
|
* @param pin - `ctx.resources.pin`, which the Tab domain holds addresses with.
|
|
221
|
-
* @param
|
|
222
|
-
* @param
|
|
238
|
+
* @param host - the viewport rule and focus continuity the commands use.
|
|
239
|
+
* @param sessions - plugin-owned adopted stores, room rules, on-screen Session, and open tab metadata.
|
|
223
240
|
*/
|
|
224
|
-
constructor(tabs: SidebarRightTabRegistry, pin: PinResource,
|
|
241
|
+
constructor(tabs: SidebarRightTabRegistry, pin: PinResource, host: SidebarRightHost, sessions: SidebarRightSessions);
|
|
225
242
|
/**
|
|
226
243
|
* Read the committed tabs of a Session so providers can restore their content.
|
|
227
244
|
* @param sessionId - Session whose layout has been adopted.
|
|
228
245
|
* @returns its open records, or an empty list before adoption.
|
|
229
246
|
*/
|
|
230
247
|
tabsIn(sessionId: SessionId): readonly TabRecord[];
|
|
231
|
-
/**
|
|
232
|
-
* Adopt the mounted seat's binding, replacing any previous one.
|
|
233
|
-
*
|
|
234
|
-
* Called from the seat while it is mounted, and released when it leaves.
|
|
235
|
-
* @param binding - the mounted seat's session, actions, and the store's surfaces.
|
|
236
|
-
* @returns a release callback that clears exactly this binding.
|
|
237
|
-
*/
|
|
238
|
-
bind(binding: SidebarRightBinding): () => void;
|
|
239
|
-
/** Publish the mounted session only when it changes; a republished binding for the same session is silent. */
|
|
240
|
-
private publishMounted;
|
|
241
248
|
/**
|
|
242
249
|
* Open a resource: claim it, place it, reveal the column, record the navigation.
|
|
243
250
|
* @param address - a `dsh-resource://<type>/…` address.
|
|
@@ -284,18 +291,18 @@ export declare class SidebarRightController implements ISidebarRight {
|
|
|
284
291
|
/** The steps both opens share: one store intent, and the navigation record for the tab it settles on. */
|
|
285
292
|
private place;
|
|
286
293
|
/**
|
|
287
|
-
* Close one tab of the
|
|
294
|
+
* Close one tab of the on-screen Session; the sole docked guide remains open.
|
|
288
295
|
* @param tabId - the tab to close.
|
|
289
296
|
*/
|
|
290
297
|
close(tabId: TabId): void;
|
|
291
298
|
/**
|
|
292
299
|
* The active tab of the active pane.
|
|
293
|
-
* @returns the record, or `undefined`
|
|
300
|
+
* @returns the record, or `undefined` without an on-screen surface.
|
|
294
301
|
*/
|
|
295
302
|
active(): TabRecord | undefined;
|
|
296
303
|
/**
|
|
297
304
|
* Whether the column is currently showing its panel.
|
|
298
|
-
* @returns `true` while expanded; `false` while collapsed or
|
|
305
|
+
* @returns `true` while expanded; `false` while collapsed or without an on-screen surface.
|
|
299
306
|
*/
|
|
300
307
|
isExpanded(): boolean;
|
|
301
308
|
/** Collapse the column, or expand it and focus its active dock pane after rendering. */
|
|
@@ -312,9 +319,9 @@ export declare class SidebarRightController implements ISidebarRight {
|
|
|
312
319
|
*/
|
|
313
320
|
focusedTarget(element?: Element | null): SidebarRightTarget | undefined;
|
|
314
321
|
/**
|
|
315
|
-
* Choose a focused sidebar pane, or the
|
|
322
|
+
* Choose a focused sidebar pane, or the on-screen Session's active dock pane for an outside open.
|
|
316
323
|
* @param element - live command input target; stale sidebar markup never falls back to another pane.
|
|
317
|
-
* @returns captured target, or undefined without
|
|
324
|
+
* @returns captured target, or undefined without an on-screen surface.
|
|
318
325
|
*/
|
|
319
326
|
commandTarget(element?: Element | null): SidebarRightTarget | undefined;
|
|
320
327
|
/**
|
|
@@ -339,7 +346,7 @@ export declare class SidebarRightController implements ISidebarRight {
|
|
|
339
346
|
/**
|
|
340
347
|
* Check a captured target before acting, including reopened records and intervening navigation.
|
|
341
348
|
* @param target - identity captured while resolving the input.
|
|
342
|
-
* @returns whether the
|
|
349
|
+
* @returns whether the on-screen Session, pane, tab lifetime and navigation still match.
|
|
343
350
|
*/
|
|
344
351
|
isTargetCurrent(target: SidebarRightTarget): boolean;
|
|
345
352
|
/**
|
|
@@ -371,20 +378,27 @@ export declare class SidebarRightController implements ISidebarRight {
|
|
|
371
378
|
*/
|
|
372
379
|
dock(paneId: PaneId): void;
|
|
373
380
|
/**
|
|
374
|
-
* Step the
|
|
381
|
+
* Step the on-screen Session's surface back one intent.
|
|
375
382
|
*
|
|
376
383
|
* @internal Not part of the product: the sequence is an architectural fact
|
|
377
384
|
* with no user-facing control yet. Kept reachable for tests.
|
|
378
385
|
*/
|
|
379
386
|
_undo(): void;
|
|
380
387
|
/**
|
|
381
|
-
* Step the
|
|
388
|
+
* Step the on-screen Session's surface forward one intent.
|
|
382
389
|
*
|
|
383
390
|
* @internal See `_undo`.
|
|
384
391
|
*/
|
|
385
392
|
_redo(): void;
|
|
386
|
-
/**
|
|
393
|
+
/**
|
|
394
|
+
* The on-screen Session and its committed surface; `undefined` with no Session
|
|
395
|
+
* on screen, before the runtime mints its store, or before its first open.
|
|
396
|
+
*/
|
|
397
|
+
private screen;
|
|
398
|
+
/** The on-screen Session's surface; see {@link SidebarRightController.screen}. */
|
|
387
399
|
private mountedSurface;
|
|
400
|
+
/** Whether a Session's docked pane has room for two working halves, as its seat last measured; unmeasured panes do. */
|
|
401
|
+
private canSplitPane;
|
|
388
402
|
/**
|
|
389
403
|
* The store actions a tab's own action on `sessionId` runs through: that
|
|
390
404
|
* session's adopted store. `undefined` — nothing to act on — for a session
|
|
@@ -33,27 +33,21 @@ export interface SidebarRightInjected {
|
|
|
33
33
|
*/
|
|
34
34
|
readonly syncPresentation: (presentation: SidebarRightPresentation) => void;
|
|
35
35
|
/**
|
|
36
|
-
*
|
|
36
|
+
* Record this seat's room rule for `ctx.sidebarRight`'s splits, replacing its previous one.
|
|
37
37
|
*
|
|
38
|
-
* The
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* @param binding - what a command needs to act on this session, and what a tab's own action needs to act on its.
|
|
42
|
-
* @returns a release callback.
|
|
38
|
+
* The docking kit measures its panes after it renders; the seat forwards each
|
|
39
|
+
* reading, and the service applies it when it splits this seat's Session.
|
|
40
|
+
* @param canSplitPane - whether two working halves of a docked pane would fit; unmeasured panes fit.
|
|
43
41
|
*/
|
|
44
|
-
readonly
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
/** Commit a page operation and focus the pane it selects. */
|
|
54
|
-
openWithFocus: (open: () => PaneId | undefined) => void;
|
|
55
|
-
autoFullscreen?: boolean;
|
|
56
|
-
}) => () => void;
|
|
42
|
+
readonly measureRoom: (canSplitPane: (paneId: PaneId) => boolean) => void;
|
|
43
|
+
/**
|
|
44
|
+
* Record whether the frame width this seat renders at presents an expanded panel fullscreen automatically.
|
|
45
|
+
*
|
|
46
|
+
* The fullscreen command reads the latest report: while it holds, the command
|
|
47
|
+
* closes the panel instead of switching its recorded mode.
|
|
48
|
+
* @param autoFullscreen - whether the frame is narrower than the automatic fullscreen width.
|
|
49
|
+
*/
|
|
50
|
+
readonly reportAutoFullscreen: (autoFullscreen: boolean) => void;
|
|
57
51
|
/**
|
|
58
52
|
* The navigation face's `openTab`, for the strip's add control: a new tab is
|
|
59
53
|
* the guide opened by kind, through the same path as every other open.
|
|
@@ -110,10 +104,11 @@ interface PanelProps {
|
|
|
110
104
|
export declare function intentsFor(sessionId: SessionId, actions: Store['actions'], openTab: PanelProps['openTab'], closeTab?: PanelProps['closeTab'], splitPane?: PanelProps['splitPane']): DockIntents;
|
|
111
105
|
/**
|
|
112
106
|
* The right column's occupant: stable tab containers, docked or floating.
|
|
113
|
-
* It is also where the
|
|
114
|
-
*
|
|
115
|
-
*
|
|
107
|
+
* It is also where the frame learns the panel's presentation, because this is
|
|
108
|
+
* the seat that knows it. `ctx.sidebarRight` names the on-screen Session
|
|
109
|
+
* itself; this seat reports only what it renders with: the room its kit
|
|
110
|
+
* measured and the automatic fullscreen rule of its frame width.
|
|
116
111
|
*/
|
|
117
|
-
export declare function RightbarSeat({ sessionId, width, viewportWidth, canShow, useStore, actions, t, renderSlot, syncPresentation,
|
|
112
|
+
export declare function RightbarSeat({ sessionId, width, viewportWidth, canShow, useStore, actions, t, renderSlot, syncPresentation, measureRoom, reportAutoFullscreen, openTab, closeTab, useTabTypes, useTabNavigation, occurrence, retainTab, active, useShortcuts, splitPane, toggleFullscreen, }: RightbarSeatProps): ReactNode;
|
|
118
113
|
export {};
|
|
119
114
|
//# sourceMappingURL=SidebarRight.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-client-ui-sidebar-right",
|
|
3
3
|
"description": "Right Sidebar: the docking surface's session-bound state, its panel and header expand control, and the navigation service over it",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.1-alpha.1",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
},
|
|
41
41
|
"license": "MIT",
|
|
42
42
|
"peerDependencies": {
|
|
43
|
-
"@deepseek-ai/cordis": "~4.0.
|
|
43
|
+
"@deepseek-ai/cordis": "~4.0.5-alpha.1"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@testing-library/react": "^16.1.0",
|
|
@@ -52,23 +52,23 @@
|
|
|
52
52
|
"picomatch": "^4.0.4",
|
|
53
53
|
"clsx": "^2.0.0",
|
|
54
54
|
"zod": "^4.4.3",
|
|
55
|
-
"@deepseek-ai/cordis": "~4.0.
|
|
56
|
-
"@deepseek-ai/dsh-api-session-controller": "0.2.
|
|
57
|
-
"@deepseek-ai/dsh-client-
|
|
58
|
-
"@deepseek-ai/dsh-client-
|
|
59
|
-
"@deepseek-ai/dsh-client-
|
|
60
|
-
"@deepseek-ai/dsh-client-
|
|
61
|
-
"@deepseek-ai/dsh-client-ui-conversation": "0.2.
|
|
62
|
-
"@deepseek-ai/dsh-client-ui-dockkit": "0.2.
|
|
63
|
-
"@deepseek-ai/dsh-client-ui-layout": "0.2.
|
|
64
|
-
"@deepseek-ai/dsh-client-ui-
|
|
65
|
-
"@deepseek-ai/dsh-client-ui-
|
|
66
|
-
"@deepseek-ai/dsh-client-ui-
|
|
67
|
-
"@deepseek-ai/dsh-
|
|
68
|
-
"@deepseek-ai/dsh-
|
|
69
|
-
"@deepseek-ai/dsh-util-crypto": "0.2.
|
|
70
|
-
"@deepseek-ai/dsh-client-shortcuts": "0.2.
|
|
71
|
-
"@deepseek-ai/dsh-brand": "0.2.
|
|
55
|
+
"@deepseek-ai/cordis": "~4.0.5-alpha.1",
|
|
56
|
+
"@deepseek-ai/dsh-api-session-controller": "0.2.1-alpha.1",
|
|
57
|
+
"@deepseek-ai/dsh-client-locale": "0.2.1-alpha.1",
|
|
58
|
+
"@deepseek-ai/dsh-client-resources": "0.2.1-alpha.1",
|
|
59
|
+
"@deepseek-ai/dsh-client-test-runtime": "0.2.1-alpha.1",
|
|
60
|
+
"@deepseek-ai/dsh-client-store": "0.2.1-alpha.1",
|
|
61
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.2.1-alpha.1",
|
|
62
|
+
"@deepseek-ai/dsh-client-ui-dockkit": "0.2.1-alpha.1",
|
|
63
|
+
"@deepseek-ai/dsh-client-ui-layout": "0.2.1-alpha.1",
|
|
64
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.2.1-alpha.1",
|
|
65
|
+
"@deepseek-ai/dsh-client-ui-renderer": "0.2.1-alpha.1",
|
|
66
|
+
"@deepseek-ai/dsh-client-ui-session": "0.2.1-alpha.1",
|
|
67
|
+
"@deepseek-ai/dsh-session": "0.2.1-alpha.1",
|
|
68
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.2.1-alpha.1",
|
|
69
|
+
"@deepseek-ai/dsh-util-crypto": "0.2.1-alpha.1",
|
|
70
|
+
"@deepseek-ai/dsh-client-shortcuts": "0.2.1-alpha.1",
|
|
71
|
+
"@deepseek-ai/dsh-brand": "0.2.1-alpha.1"
|
|
72
72
|
},
|
|
73
73
|
"files": [
|
|
74
74
|
"lib/index.js",
|