@michengai/dsh-automation 0.1.1 → 0.1.2
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/docs/00-/344/272/244/346/216/245/345/205/245/345/217/243/02-/345/275/223/345/211/215/347/212/266/346/200/201.md +3 -3
- package/docs/01-/345/275/223/345/211/215/345/267/245/344/275/234/I001-/344/273/273/345/212/241/350/207/252/345/212/250/345/214/226/346/217/222/344/273/266/00-/350/277/255/344/273/243/346/200/273/350/247/210.md +3 -2
- package/lib/client.js +95 -32
- package/lib/client.js.map +4 -4
- package/lib/types/client/native-session-list.d.ts +1 -1
- package/lib/types/client/native-session-menu.d.ts +13 -0
- package/package.json +2 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# 当前状态
|
|
2
2
|
|
|
3
|
-
更新时间:2026-08-
|
|
3
|
+
更新时间:2026-08-18 08:40(Asia/Shanghai)
|
|
4
4
|
|
|
5
|
-
- 阶段:I001
|
|
5
|
+
- 阶段:I001 任务自动化插件首版已发布 0.1.1,本地待发布 0.1.2 菜单互斥修复。
|
|
6
6
|
- 活动迭代:[I001-任务自动化插件](..\01-当前工作\I001-任务自动化插件\00-迭代总览.md)
|
|
7
7
|
- 有效风险:
|
|
8
8
|
- Host 未运行时不会补跑历史 backlog。
|
|
9
|
-
- 无人值守工具 allowlist 无法覆盖全部第三方 DSH tool。
|
|
9
|
+
- 无人值守工具 allowlist 无法覆盖全部第三方 DSH tool。
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
- 状态:进行中
|
|
4
4
|
- 负责人:维护者
|
|
5
5
|
- 优先级:高
|
|
6
|
-
- 更新时间:2026-08-
|
|
6
|
+
- 更新时间:2026-08-18 08:40(Asia/Shanghai)
|
|
7
7
|
|
|
8
8
|
## 目标与业务边界
|
|
9
9
|
|
|
@@ -40,9 +40,10 @@
|
|
|
40
40
|
|
|
41
41
|
## 关联提交
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
本地菜单互斥修复待随 0.1.2 发布。
|
|
44
44
|
|
|
45
45
|
## 阅读顺序
|
|
46
46
|
|
|
47
47
|
1. [项目概览](..\..\00-交接入口\01-项目概览.md)
|
|
48
48
|
2. [调度与执行模型](..\..\03-技术架构\01-调度与执行模型.md)
|
|
49
|
+
|
package/lib/client.js
CHANGED
|
@@ -1873,6 +1873,49 @@ function isForeignSidebarHost(component) {
|
|
|
1873
1873
|
|
|
1874
1874
|
// src/client/native-session-list.tsx
|
|
1875
1875
|
var import_react4 = require("react");
|
|
1876
|
+
var import_react_dom2 = require("react-dom");
|
|
1877
|
+
|
|
1878
|
+
// src/client/native-session-menu.ts
|
|
1879
|
+
function resolveEventElement(target) {
|
|
1880
|
+
if (target == null || typeof target !== "object") return null;
|
|
1881
|
+
const node = target;
|
|
1882
|
+
if (node.nodeType === 3 || node.nodeType === 8) {
|
|
1883
|
+
return node.parentElement ?? null;
|
|
1884
|
+
}
|
|
1885
|
+
return node;
|
|
1886
|
+
}
|
|
1887
|
+
function shouldCloseNativeSessionMenu(target, keepInside) {
|
|
1888
|
+
const el = resolveEventElement(target);
|
|
1889
|
+
if (el == null) return true;
|
|
1890
|
+
return !keepInside.some((root) => {
|
|
1891
|
+
if (root == null || typeof root !== "object") return false;
|
|
1892
|
+
if (root === el) return true;
|
|
1893
|
+
const box = root;
|
|
1894
|
+
return typeof box.contains === "function" && box.contains(el);
|
|
1895
|
+
});
|
|
1896
|
+
}
|
|
1897
|
+
function nextOpenSessionMenuId(current, clicked) {
|
|
1898
|
+
return current === clicked ? null : clicked;
|
|
1899
|
+
}
|
|
1900
|
+
function nativeSessionMenuStyle(box, viewportWidth) {
|
|
1901
|
+
return {
|
|
1902
|
+
position: "fixed",
|
|
1903
|
+
zIndex: 1200,
|
|
1904
|
+
top: `${Math.round(box.bottom + 4)}px`,
|
|
1905
|
+
right: `${Math.max(8, Math.round(viewportWidth - box.right))}px`
|
|
1906
|
+
};
|
|
1907
|
+
}
|
|
1908
|
+
function relativeTime(value) {
|
|
1909
|
+
const ts = Date.parse(value || "");
|
|
1910
|
+
if (!Number.isFinite(ts)) return "";
|
|
1911
|
+
const delta = Math.max(0, Date.now() - ts);
|
|
1912
|
+
const min = Math.floor(delta / 6e4);
|
|
1913
|
+
if (min < 1) return "\u521A\u521A";
|
|
1914
|
+
if (min < 60) return String(min) + "\u5206\u949F";
|
|
1915
|
+
const hour = Math.floor(min / 60);
|
|
1916
|
+
if (hour < 24) return String(hour) + "\u5C0F\u65F6";
|
|
1917
|
+
return String(Math.floor(hour / 24)) + "\u5929";
|
|
1918
|
+
}
|
|
1876
1919
|
|
|
1877
1920
|
// src/run-title.ts
|
|
1878
1921
|
function formatRunStamp(iso) {
|
|
@@ -2050,17 +2093,6 @@ function pickWrappableWorkspacesEntry(entries) {
|
|
|
2050
2093
|
// src/client/native-session-list.tsx
|
|
2051
2094
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
2052
2095
|
var EMPTY_SESSION_BY_ID = {};
|
|
2053
|
-
function relativeTime(value) {
|
|
2054
|
-
const ts = Date.parse(value || "");
|
|
2055
|
-
if (!Number.isFinite(ts)) return "";
|
|
2056
|
-
const delta = Math.max(0, Date.now() - ts);
|
|
2057
|
-
const min = Math.floor(delta / 6e4);
|
|
2058
|
-
if (min < 1) return "\u521A\u521A";
|
|
2059
|
-
if (min < 60) return String(min) + "\u5206\u949F";
|
|
2060
|
-
const hour = Math.floor(min / 60);
|
|
2061
|
-
if (hour < 24) return String(hour) + "\u5C0F\u65F6";
|
|
2062
|
-
return String(Math.floor(hour / 24)) + "\u5929";
|
|
2063
|
-
}
|
|
2064
2096
|
function NativeScheduleSessionList(props) {
|
|
2065
2097
|
const { t, runtime, openSession, useSessions, useWorkspaces, renameSession, archiveSession, deleteSession, forkSession } = props;
|
|
2066
2098
|
const state = (0, import_react4.useSyncExternalStore)(runtime.source.subscribe, runtime.source.getSnapshot, runtime.source.getSnapshot);
|
|
@@ -2068,6 +2100,7 @@ function NativeScheduleSessionList(props) {
|
|
|
2068
2100
|
const sessionById = useSessions ? useSessions((snap) => snap?.byId ?? EMPTY_SESSION_BY_ID) : EMPTY_SESSION_BY_ID;
|
|
2069
2101
|
const archivedIds = useWorkspaces ? useWorkspaces((snap) => snap?.archivedSessionIds ?? []) : [];
|
|
2070
2102
|
const [folded, setFolded] = (0, import_react4.useState)({});
|
|
2103
|
+
const [openMenuId, setOpenMenuId] = (0, import_react4.useState)(null);
|
|
2071
2104
|
(0, import_react4.useEffect)(() => {
|
|
2072
2105
|
void runtime.refresh().catch(() => void 0);
|
|
2073
2106
|
const timer = window.setInterval(() => {
|
|
@@ -2112,6 +2145,7 @@ function NativeScheduleSessionList(props) {
|
|
|
2112
2145
|
"aria-label": t("session.deleteFolder"),
|
|
2113
2146
|
onClick: (event) => {
|
|
2114
2147
|
event.stopPropagation();
|
|
2148
|
+
setOpenMenuId(null);
|
|
2115
2149
|
void (async () => {
|
|
2116
2150
|
for (const session of group.sessions) {
|
|
2117
2151
|
try {
|
|
@@ -2135,7 +2169,11 @@ function NativeScheduleSessionList(props) {
|
|
|
2135
2169
|
updatedAt: session.updatedAt,
|
|
2136
2170
|
running: session.running,
|
|
2137
2171
|
selected: selectedId === session.id,
|
|
2172
|
+
menuOpen: openMenuId === session.id,
|
|
2173
|
+
onToggleMenu: () => setOpenMenuId((current) => nextOpenSessionMenuId(current, session.id)),
|
|
2174
|
+
onCloseMenu: () => setOpenMenuId((current) => current === session.id ? null : current),
|
|
2138
2175
|
onOpen: () => {
|
|
2176
|
+
setOpenMenuId(null);
|
|
2139
2177
|
openSession?.(session.id);
|
|
2140
2178
|
void runtime.adoptSession?.(session.id).catch(() => void 0);
|
|
2141
2179
|
},
|
|
@@ -2157,31 +2195,52 @@ function NativeScheduleSessionList(props) {
|
|
|
2157
2195
|
] }) });
|
|
2158
2196
|
}
|
|
2159
2197
|
function NativeSessionRow(props) {
|
|
2160
|
-
const { t, id, title, updatedAt, running, selected, onOpen, onDelete, renameSession, archiveSession, forkSession } = props;
|
|
2161
|
-
const
|
|
2198
|
+
const { t, id, title, updatedAt, running, selected, menuOpen, onToggleMenu, onCloseMenu, onOpen, onDelete, renameSession, archiveSession, forkSession } = props;
|
|
2199
|
+
const rowRef = (0, import_react4.useRef)(null);
|
|
2200
|
+
const menuRef = (0, import_react4.useRef)(null);
|
|
2162
2201
|
const [renaming, setRenaming] = (0, import_react4.useState)(false);
|
|
2163
2202
|
const [draft, setDraft] = (0, import_react4.useState)(title);
|
|
2203
|
+
const [menuStyle, setMenuStyle] = (0, import_react4.useState)({});
|
|
2164
2204
|
(0, import_react4.useEffect)(() => {
|
|
2165
2205
|
setDraft(title);
|
|
2166
2206
|
}, [title]);
|
|
2167
2207
|
(0, import_react4.useEffect)(() => {
|
|
2168
|
-
if (!
|
|
2208
|
+
if (!menuOpen) return;
|
|
2169
2209
|
const close = (event) => {
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2210
|
+
if (!shouldCloseNativeSessionMenu(event.target, [rowRef.current, menuRef.current])) return;
|
|
2211
|
+
onCloseMenu();
|
|
2212
|
+
};
|
|
2213
|
+
const onKey = (event) => {
|
|
2214
|
+
if (event.key === "Escape") onCloseMenu();
|
|
2173
2215
|
};
|
|
2174
2216
|
document.addEventListener("mousedown", close);
|
|
2217
|
+
document.addEventListener("keydown", onKey);
|
|
2175
2218
|
return () => {
|
|
2176
2219
|
document.removeEventListener("mousedown", close);
|
|
2220
|
+
document.removeEventListener("keydown", onKey);
|
|
2177
2221
|
};
|
|
2178
|
-
}, [
|
|
2222
|
+
}, [menuOpen, onCloseMenu]);
|
|
2223
|
+
(0, import_react4.useLayoutEffect)(() => {
|
|
2224
|
+
if (!menuOpen) return;
|
|
2225
|
+
const update = () => {
|
|
2226
|
+
const box = rowRef.current?.getBoundingClientRect();
|
|
2227
|
+
if (box === void 0) return;
|
|
2228
|
+
setMenuStyle(nativeSessionMenuStyle(box, window.innerWidth));
|
|
2229
|
+
};
|
|
2230
|
+
update();
|
|
2231
|
+
window.addEventListener("resize", update);
|
|
2232
|
+
document.addEventListener("scroll", update, true);
|
|
2233
|
+
return () => {
|
|
2234
|
+
window.removeEventListener("resize", update);
|
|
2235
|
+
document.removeEventListener("scroll", update, true);
|
|
2236
|
+
};
|
|
2237
|
+
}, [menuOpen]);
|
|
2179
2238
|
const run = (action) => {
|
|
2180
2239
|
void Promise.resolve(action()).catch(() => void 0);
|
|
2181
2240
|
};
|
|
2182
|
-
const rowClass = "dsh-st-n-sess" + (selected ? " is-on" : "") + (
|
|
2241
|
+
const rowClass = "dsh-st-n-sess" + (selected ? " is-on" : "") + (menuOpen ? " is-menu" : "");
|
|
2183
2242
|
if (renaming) {
|
|
2184
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: rowClass, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { className: "dsh-st-n-rename", value: draft, autoFocus: true, "aria-label": t("session.rename"), onChange: (event) => setDraft(event.target.value), onClick: (event) => event.stopPropagation(), onKeyDown: (event) => {
|
|
2243
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: rowClass, ref: rowRef, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { className: "dsh-st-n-rename", value: draft, autoFocus: true, "aria-label": t("session.rename"), onChange: (event) => setDraft(event.target.value), onClick: (event) => event.stopPropagation(), onKeyDown: (event) => {
|
|
2185
2244
|
if (event.key === "Enter") {
|
|
2186
2245
|
event.preventDefault();
|
|
2187
2246
|
setRenaming(false);
|
|
@@ -2205,7 +2264,17 @@ function NativeSessionRow(props) {
|
|
|
2205
2264
|
{ id: "archive", label: t("session.archive"), icon: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ArchiveIcon, { width: 16, height: 16 }), go: () => run(() => archiveSession?.(id)) },
|
|
2206
2265
|
{ id: "delete", label: t("session.delete"), icon: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TrashIcon, { width: 16, height: 16 }), danger: true, go: () => run(() => onDelete()) }
|
|
2207
2266
|
];
|
|
2208
|
-
|
|
2267
|
+
const menu = menuOpen && typeof document !== "undefined" ? (0, import_react_dom2.createPortal)(
|
|
2268
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { ref: menuRef, className: "dsh-st-n-menu is-float", "data-n-menu": id, style: menuStyle, onMouseDown: (event) => event.stopPropagation(), onClick: (event) => event.stopPropagation(), children: menuItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("button", { type: "button", className: item.danger === true ? "danger" : void 0, onClick: () => {
|
|
2269
|
+
onCloseMenu();
|
|
2270
|
+
item.go();
|
|
2271
|
+
}, children: [
|
|
2272
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "dsh-st-n-mi", children: item.icon }),
|
|
2273
|
+
item.label
|
|
2274
|
+
] }, item.id)) }),
|
|
2275
|
+
document.body
|
|
2276
|
+
) : null;
|
|
2277
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: rowClass, ref: rowRef, role: "treeitem", tabIndex: 0, "aria-selected": selected, "data-n-menu-root": id, onClick: onOpen, onKeyDown: (event) => {
|
|
2209
2278
|
if (event.key === "Enter" || event.key === " ") {
|
|
2210
2279
|
event.preventDefault();
|
|
2211
2280
|
onOpen();
|
|
@@ -2213,22 +2282,16 @@ function NativeSessionRow(props) {
|
|
|
2213
2282
|
}, onContextMenu: (event) => {
|
|
2214
2283
|
event.preventDefault();
|
|
2215
2284
|
event.stopPropagation();
|
|
2216
|
-
|
|
2285
|
+
onToggleMenu();
|
|
2217
2286
|
}, children: [
|
|
2218
2287
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "dsh-st-n-slot", children: running ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RunningStateDot, {}) : null }),
|
|
2219
2288
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "dsh-st-n-title", children: title }),
|
|
2220
2289
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "dsh-st-n-time", children: relativeTime(updatedAt) }),
|
|
2221
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "dsh-st-n-acts", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "dsh-st-n-ico", "aria-label": title + " \u66F4\u591A", onClick: (event) => {
|
|
2290
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "dsh-st-n-acts", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "dsh-st-n-ico", "aria-label": title + " \u66F4\u591A", onMouseDown: (event) => event.stopPropagation(), onClick: (event) => {
|
|
2222
2291
|
event.stopPropagation();
|
|
2223
|
-
|
|
2292
|
+
onToggleMenu();
|
|
2224
2293
|
}, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(EllipsisIcon, { width: 16, height: 16 }) }) }),
|
|
2225
|
-
menu
|
|
2226
|
-
setMenu(false);
|
|
2227
|
-
item.go();
|
|
2228
|
-
}, children: [
|
|
2229
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "dsh-st-n-mi", children: item.icon }),
|
|
2230
|
-
item.label
|
|
2231
|
-
] }, item.id)) })
|
|
2294
|
+
menu
|
|
2232
2295
|
] });
|
|
2233
2296
|
}
|
|
2234
2297
|
|
|
@@ -2556,7 +2619,7 @@ var CSS_TEXT = `
|
|
|
2556
2619
|
.dsh-st-shell-body>*{min-width:0;flex:1}.dsh-st-official-tree{display:flex;min-height:0;flex:1;overflow:hidden}.dsh-st-official-tree>*{min-width:0;flex:1}
|
|
2557
2620
|
.dsh-st-rail-head.is-static{cursor:default;font-weight:600}
|
|
2558
2621
|
.dsh-st-rail-session.is-on{background:var(--dsw-alias-interactive-bg-hover,rgba(255,255,255,.06))}
|
|
2559
|
-
.dsh-st-n,.dsh-st-n *{box-sizing:border-box}.dsh-st-n{box-sizing:border-box;display:flex;flex:1;min-width:0;max-width:100%;min-height:0;flex-direction:column;padding:0;padding-right:var(--dsh-sidebar-inline-padding,12px);color:var(--dsw-alias-label-primary,inherit);font:14px/20px inherit;overflow:hidden}.dsh-st-n-head{flex:none;display:flex;align-items:center;height:36px;padding-left:4px;margin:2px 0 4px;color:var(--dsw-alias-label-tertiary,#81858C)}.dsh-st-n-head-label{font-size:14px;line-height:20px}.dsh-st-n-tree{flex:1;min-width:0;max-width:100%;min-height:0;overflow-x:hidden;overflow-y:auto;padding:0 0 16px 4px;user-select:none}.dsh-st-n-empty{padding:14px 8px;color:var(--dsw-alias-label-tertiary,#8b8f98);font-size:12px}.dsh-st-n-group{min-width:0;max-width:100%}.dsh-st-n-row,.dsh-st-n-sess{display:flex;align-items:center;max-width:100%;border-radius:8px;padding:0 8px;cursor:pointer;border:0;background:transparent;color:var(--dsw-alias-label-primary,inherit);text-align:left;font:14px/20px inherit}.dsh-st-n-row{height:34px;gap:6px}.dsh-st-n-sess{height:32px;gap:0;position:relative;width:100%;appearance:none}.dsh-st-n-row:hover,.dsh-st-n-sess:hover,.dsh-st-n-sess.is-on,.dsh-st-n-sess.is-menu{background:var(--dsw-alias-interactive-bg-hover,rgba(255,255,255,.06))}.dsh-st-n-slot{flex:none;width:16px;height:20px;display:inline-flex;align-items:center;justify-content:center}.dsh-st-n-row .dsh-st-n-chevron{display:none;color:var(--dsw-alias-label-caption,#ADB2B8)}.dsh-st-n-row:hover .dsh-st-n-chevron{display:inline-flex}.dsh-st-n-row:hover .dsh-st-n-folder{display:none}.dsh-st-n-arrow{transition:transform .15s ease}.dsh-st-n-arrow.is-open{transform:rotate(90deg)}.dsh-st-n-title{min-width:0;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:14px;line-height:20px}.dsh-st-n-sess .dsh-st-n-title{margin:0 6px 0 4px}.dsh-st-n-time{flex:none;font-size:12px;line-height:20px;color:var(--dsw-alias-label-tertiary,#81858C);white-space:nowrap}.dsh-st-n-acts{flex:none;display:none;align-items:center;gap:12px}.dsh-st-n-row:hover .dsh-st-n-acts,.dsh-st-n-sess:hover .dsh-st-n-acts,.dsh-st-n-row.is-menu .dsh-st-n-acts,.dsh-st-n-sess.is-menu .dsh-st-n-acts{display:inline-flex}.dsh-st-n-sess:hover .dsh-st-n-time,.dsh-st-n-sess.is-menu .dsh-st-n-time{display:none}.dsh-st-n-ico{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;border:0;border-radius:4px;background:transparent;color:var(--dsw-alias-label-tertiary,#81858C);padding:0;cursor:pointer}.dsh-st-n-ico:hover{color:var(--dsw-alias-label-primary,inherit)}.dsh-st-n-menu{position:absolute;right:8px;top:calc(100% + 4px);z-index:1100;min-width:218px;max-width:360px;box-sizing:border-box;padding:4px;display:flex;flex-direction:column;border:1px solid var(--dsw-alias-border-inverted,rgba(255,255,255,.12));border-radius:12px;background:var(--dsw-specific-menu,#1c2128);box-shadow:var(--dsw-shadow-lv3,0 8px 24px rgba(0,0,0,.36))}.dsh-st-n-menu button{display:flex;align-items:center;gap:8px;width:100%;min-height:40px;padding:8px 10px;border:0;border-radius:10px;background:transparent;cursor:pointer;font-size:14px;line-height:22px;color:var(--dsw-alias-label-primary,inherit);text-align:left}.dsh-st-n-menu button:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(255,255,255,.06))}.dsh-st-n-mi{display:inline-flex;flex:none;width:16px;height:16px;align-items:center;justify-content:center;color:var(--dsw-alias-label-tertiary,#81858C)}.dsh-st-n-menu button.danger{color:var(--dsw-alias-state-error-primary,#f85149)}.dsh-st-n-menu button.danger .dsh-st-n-mi{color:inherit}.dsh-st-n-menu button.danger:hover{background:var(--dsw-alias-interactive-bg-hover-danger,rgba(248,81,73,.12))}.dsh-st-n-rename{flex:1;min-width:0;margin:0 6px 0 4px;border:1px solid var(--dsw-alias-border-l2);border-radius:4px;background:var(--dsw-alias-button-elevated-fill,rgba(255,255,255,.04));color:inherit;font:inherit;padding:0 2px}
|
|
2622
|
+
.dsh-st-n,.dsh-st-n *{box-sizing:border-box}.dsh-st-n{box-sizing:border-box;display:flex;flex:1;min-width:0;max-width:100%;min-height:0;flex-direction:column;padding:0;padding-right:var(--dsh-sidebar-inline-padding,12px);color:var(--dsw-alias-label-primary,inherit);font:14px/20px inherit;overflow:hidden}.dsh-st-n-head{flex:none;display:flex;align-items:center;height:36px;padding-left:4px;margin:2px 0 4px;color:var(--dsw-alias-label-tertiary,#81858C)}.dsh-st-n-head-label{font-size:14px;line-height:20px}.dsh-st-n-tree{flex:1;min-width:0;max-width:100%;min-height:0;overflow-x:hidden;overflow-y:auto;padding:0 0 16px 4px;user-select:none}.dsh-st-n-empty{padding:14px 8px;color:var(--dsw-alias-label-tertiary,#8b8f98);font-size:12px}.dsh-st-n-group{min-width:0;max-width:100%}.dsh-st-n-row,.dsh-st-n-sess{display:flex;align-items:center;max-width:100%;border-radius:8px;padding:0 8px;cursor:pointer;border:0;background:transparent;color:var(--dsw-alias-label-primary,inherit);text-align:left;font:14px/20px inherit}.dsh-st-n-row{height:34px;gap:6px}.dsh-st-n-sess{height:32px;gap:0;position:relative;width:100%;appearance:none}.dsh-st-n-row:hover,.dsh-st-n-sess:hover,.dsh-st-n-sess.is-on,.dsh-st-n-sess.is-menu{background:var(--dsw-alias-interactive-bg-hover,rgba(255,255,255,.06))}.dsh-st-n-slot{flex:none;width:16px;height:20px;display:inline-flex;align-items:center;justify-content:center}.dsh-st-n-row .dsh-st-n-chevron{display:none;color:var(--dsw-alias-label-caption,#ADB2B8)}.dsh-st-n-row:hover .dsh-st-n-chevron{display:inline-flex}.dsh-st-n-row:hover .dsh-st-n-folder{display:none}.dsh-st-n-arrow{transition:transform .15s ease}.dsh-st-n-arrow.is-open{transform:rotate(90deg)}.dsh-st-n-title{min-width:0;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:14px;line-height:20px}.dsh-st-n-sess .dsh-st-n-title{margin:0 6px 0 4px}.dsh-st-n-time{flex:none;font-size:12px;line-height:20px;color:var(--dsw-alias-label-tertiary,#81858C);white-space:nowrap}.dsh-st-n-acts{flex:none;display:none;align-items:center;gap:12px}.dsh-st-n-row:hover .dsh-st-n-acts,.dsh-st-n-sess:hover .dsh-st-n-acts,.dsh-st-n-row.is-menu .dsh-st-n-acts,.dsh-st-n-sess.is-menu .dsh-st-n-acts{display:inline-flex}.dsh-st-n-sess:hover .dsh-st-n-time,.dsh-st-n-sess.is-menu .dsh-st-n-time{display:none}.dsh-st-n-ico{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;border:0;border-radius:4px;background:transparent;color:var(--dsw-alias-label-tertiary,#81858C);padding:0;cursor:pointer}.dsh-st-n-ico:hover{color:var(--dsw-alias-label-primary,inherit)}.dsh-st-n-menu.is-float{position:fixed;z-index:1200}.dsh-st-n-menu{position:absolute;right:8px;top:calc(100% + 4px);z-index:1100;min-width:218px;max-width:360px;box-sizing:border-box;padding:4px;display:flex;flex-direction:column;border:1px solid var(--dsw-alias-border-inverted,rgba(255,255,255,.12));border-radius:12px;background:var(--dsw-specific-menu,#1c2128);box-shadow:var(--dsw-shadow-lv3,0 8px 24px rgba(0,0,0,.36))}.dsh-st-n-menu button{display:flex;align-items:center;gap:8px;width:100%;min-height:40px;padding:8px 10px;border:0;border-radius:10px;background:transparent;cursor:pointer;font-size:14px;line-height:22px;color:var(--dsw-alias-label-primary,inherit);text-align:left}.dsh-st-n-menu button:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(255,255,255,.06))}.dsh-st-n-mi{display:inline-flex;flex:none;width:16px;height:16px;align-items:center;justify-content:center;color:var(--dsw-alias-label-tertiary,#81858C)}.dsh-st-n-menu button.danger{color:var(--dsw-alias-state-error-primary,#f85149)}.dsh-st-n-menu button.danger .dsh-st-n-mi{color:inherit}.dsh-st-n-menu button.danger:hover{background:var(--dsw-alias-interactive-bg-hover-danger,rgba(248,81,73,.12))}.dsh-st-n-rename{flex:1;min-width:0;margin:0 6px 0 4px;border:1px solid var(--dsw-alias-border-l2);border-radius:4px;background:var(--dsw-alias-button-elevated-fill,rgba(255,255,255,.04));color:inherit;font:inherit;padding:0 2px}
|
|
2560
2623
|
`;
|
|
2561
2624
|
function installStyles() {
|
|
2562
2625
|
const existing = document.getElementById(STYLE_ID);
|