dsh-sidebar-row-menu 1.9.2 → 1.9.3
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/CHANGELOG.md +22 -0
- package/lib/client.js +138 -78
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.9.3 — 2026-11-06
|
|
4
|
+
|
|
5
|
+
### 中文摘要
|
|
6
|
+
|
|
7
|
+
- **二级菜单贴着屏幕右边缘时不再飞出去。** 之前子菜单按估算宽度(220)算位置,
|
|
8
|
+
贴右边缘向左翻转时会和菜单之间空出一大截、还竖直跑到触发行上方。现在子菜单
|
|
9
|
+
先测真实尺寸再定位:翻转后横向留 6px 间距、纵向和触发行齐平,箭头方向跟着翻转;
|
|
10
|
+
底边 / 顶边超出屏幕时会被夹回视口内。主菜单定位也改成量真实宽高(原来是按入场
|
|
11
|
+
动画中途的偏小尺寸夹取,贴右边缘会溢出几个像素),窗口 resize 或菜单行数变化会
|
|
12
|
+
重新定位。
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- **Submenus no longer fly off when opened against the right screen edge.** The
|
|
17
|
+
previous code estimated the submenu width (220px), so a left-flip near the edge left
|
|
18
|
+
a large gap from the menu and landed above the trigger row. The submenu is now
|
|
19
|
+
measured and then positioned: 6px horizontal gap when flipped, vertically aligned
|
|
20
|
+
with the trigger row, and its chevron mirrors to match. Panels are clamped back into
|
|
21
|
+
the viewport at the top and bottom edges. Menu surfaces also measure their real size
|
|
22
|
+
(the old code measured mid-animation, which let them overflow by a few pixels at the
|
|
23
|
+
right edge), and reposition on window resize or row-count changes.
|
|
24
|
+
|
|
3
25
|
## 1.9.2 — 2026-11-06
|
|
4
26
|
|
|
5
27
|
### 中文摘要
|
package/lib/client.js
CHANGED
|
@@ -1296,18 +1296,135 @@ window.__ModuleLoader__.load({
|
|
|
1296
1296
|
|
|
1297
1297
|
/* ---------------------------------------------------------- 打开方式子菜单 */
|
|
1298
1298
|
|
|
1299
|
-
/**
|
|
1300
|
-
function
|
|
1299
|
+
/** 视口可用尺寸:滚动条会占掉 innerWidth/innerHeight 的一部分,贴边要贴着可视区算。 */
|
|
1300
|
+
function viewportBounds() {
|
|
1301
|
+
const root = typeof document === 'undefined' ? null : document.documentElement;
|
|
1302
|
+
const width = root !== null && root !== undefined && root.clientWidth > 0 ? root.clientWidth : window.innerWidth;
|
|
1303
|
+
const height = root !== null && root !== undefined && root.clientHeight > 0 ? root.clientHeight : window.innerHeight;
|
|
1304
|
+
return { width: Number(width) || 0, height: Number(height) || 0 };
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
/**
|
|
1308
|
+
* 元素真实占位尺寸。必须用 offsetWidth/offsetHeight:面板入场动画带 transform 缩放,
|
|
1309
|
+
* 动画期间 getBoundingClientRect 量出来偏小(实测 181 vs 198),按它夹取会溢出视口。
|
|
1310
|
+
*/
|
|
1311
|
+
function layoutSize(node) {
|
|
1312
|
+
if (node === null || node === undefined) return null;
|
|
1313
|
+
const width = Number(node.offsetWidth) || 0;
|
|
1314
|
+
const height = Number(node.offsetHeight) || 0;
|
|
1315
|
+
if (width > 0 && height > 0) return { width, height };
|
|
1316
|
+
if (typeof node.getBoundingClientRect !== 'function') return null;
|
|
1317
|
+
const rect = node.getBoundingClientRect();
|
|
1318
|
+
if (!(rect.width > 0) || !(rect.height > 0)) return null;
|
|
1319
|
+
return { width: rect.width, height: rect.height };
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
/** 菜单面板定位:按布局尺寸夹进视口;尺寸后续变化(异步条目、字体)时再夹一次。 */
|
|
1323
|
+
function useMenuPos(hostRef, x, y, deps) {
|
|
1324
|
+
const [pos, setPos] = useState(null);
|
|
1325
|
+
const place = () => {
|
|
1326
|
+
const host = hostRef.current;
|
|
1327
|
+
if (host === null || host === undefined) return;
|
|
1328
|
+
const size = layoutSize(host);
|
|
1329
|
+
if (size === null) return;
|
|
1330
|
+
const view = viewportBounds();
|
|
1331
|
+
const margin = 8;
|
|
1332
|
+
const left = Math.max(margin, Math.min(x, view.width - size.width - margin));
|
|
1333
|
+
const top = Math.max(margin, Math.min(y, view.height - size.height - margin));
|
|
1334
|
+
setPos((prev) => (prev !== null && prev.left === left && prev.top === top ? prev : { left, top }));
|
|
1335
|
+
};
|
|
1336
|
+
useLayoutEffect(place, [x, y, ...deps]);
|
|
1337
|
+
useEffect(() => {
|
|
1338
|
+
if (typeof ResizeObserver !== 'function') return undefined;
|
|
1339
|
+
const host = hostRef.current;
|
|
1340
|
+
if (host === null || host === undefined) return undefined;
|
|
1341
|
+
const observer = new ResizeObserver(place);
|
|
1342
|
+
observer.observe(host);
|
|
1343
|
+
return () => observer.disconnect();
|
|
1344
|
+
}, [x, y]);
|
|
1345
|
+
return pos;
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
/**
|
|
1349
|
+
* 二级菜单位置:横向贴住菜单面板外沿,纵向和触发它的那一行对齐;
|
|
1350
|
+
* 右侧放不下就翻到左边,仍然紧贴面板,再整体夹进视口。
|
|
1351
|
+
*/
|
|
1352
|
+
function submenuGeometry(anchor, size, row = anchor) {
|
|
1301
1353
|
const margin = 12;
|
|
1302
1354
|
const gap = 6;
|
|
1355
|
+
const view = viewportBounds();
|
|
1303
1356
|
const width = Math.max(160, size?.width ?? 180);
|
|
1304
1357
|
const height = Math.max(0, size?.height ?? 0);
|
|
1358
|
+
const rightRoom = view.width - margin - (anchor.right + gap);
|
|
1359
|
+
const leftRoom = anchor.left - gap - margin;
|
|
1360
|
+
let side = 'right';
|
|
1305
1361
|
let left = anchor.right + gap;
|
|
1306
|
-
if (
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1362
|
+
if (rightRoom < width && leftRoom > rightRoom) {
|
|
1363
|
+
side = 'left';
|
|
1364
|
+
left = anchor.left - width - gap;
|
|
1365
|
+
}
|
|
1366
|
+
left = Math.max(margin, Math.min(left, view.width - width - margin));
|
|
1367
|
+
let top = row.top;
|
|
1368
|
+
top = Math.max(margin, Math.min(top, view.height - height - margin));
|
|
1369
|
+
return { left, top, side };
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
/**
|
|
1373
|
+
* 二级菜单定位:面板先以隐藏状态挂载,量到真实尺寸后再贴边,
|
|
1374
|
+
* 因此顶到屏幕右侧时会精确翻到另一侧并紧贴菜单,不再按估算宽度留出空隙。
|
|
1375
|
+
*/
|
|
1376
|
+
function useSubmenuPos(open, hostRef, deps) {
|
|
1377
|
+
const [box, setBox] = useState(null);
|
|
1378
|
+
const place = () => {
|
|
1379
|
+
const host = hostRef.current;
|
|
1380
|
+
if (host === null || host === undefined) return;
|
|
1381
|
+
const panel = typeof host.querySelector === 'function' ? host.querySelector('.dsrm-submenu') : null;
|
|
1382
|
+
const size = layoutSize(panel);
|
|
1383
|
+
if (size === null) return;
|
|
1384
|
+
const row = host.getBoundingClientRect();
|
|
1385
|
+
// 横向以菜单面板外沿为锚:自绘菜单是 .dsrm-menu,会话 / 工作区行注入到宿主菜单里,
|
|
1386
|
+
// 那时要找宿主的 [role="menu"] 面板(行本身比面板内缩 4px,贴它会偏进面板里)。
|
|
1387
|
+
const menu = typeof host.closest === 'function'
|
|
1388
|
+
? (host.closest('.dsrm-menu') ?? host.closest('[role="menu"]'))
|
|
1389
|
+
: null;
|
|
1390
|
+
const anchor = menu !== null && menu !== undefined && menu !== host ? menu.getBoundingClientRect() : row;
|
|
1391
|
+
const next = submenuGeometry(anchor, size, row);
|
|
1392
|
+
setBox((prev) => (prev !== null
|
|
1393
|
+
&& prev.left === next.left
|
|
1394
|
+
&& prev.top === next.top
|
|
1395
|
+
&& prev.side === next.side ? prev : next));
|
|
1396
|
+
};
|
|
1397
|
+
useLayoutEffect(() => {
|
|
1398
|
+
if (!open) {
|
|
1399
|
+
setBox(null);
|
|
1400
|
+
return;
|
|
1401
|
+
}
|
|
1402
|
+
place();
|
|
1403
|
+
}, [open, ...deps]);
|
|
1404
|
+
useEffect(() => {
|
|
1405
|
+
if (!open) return undefined;
|
|
1406
|
+
window.addEventListener('resize', place);
|
|
1407
|
+
const host = hostRef.current;
|
|
1408
|
+
const panel = host !== null && host !== undefined && typeof host.querySelector === 'function'
|
|
1409
|
+
? host.querySelector('.dsrm-submenu')
|
|
1410
|
+
: null;
|
|
1411
|
+
const observer = typeof ResizeObserver === 'function' && panel !== null && panel !== undefined
|
|
1412
|
+
? new ResizeObserver(place)
|
|
1413
|
+
: null;
|
|
1414
|
+
if (observer !== null) observer.observe(panel);
|
|
1415
|
+
return () => {
|
|
1416
|
+
window.removeEventListener('resize', place);
|
|
1417
|
+
if (observer !== null) observer.disconnect();
|
|
1418
|
+
};
|
|
1419
|
+
}, [open, ...deps]);
|
|
1420
|
+
return box;
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1423
|
+
/** 面板翻到左侧时箭头跟着翻转,指向菜单所在方向。 */
|
|
1424
|
+
function chevronClass(box) {
|
|
1425
|
+
return box?.side === 'left'
|
|
1426
|
+
? 'dsrm-submenu-chevron dsrm-submenu-chevron-flipped'
|
|
1427
|
+
: 'dsrm-submenu-chevron';
|
|
1311
1428
|
}
|
|
1312
1429
|
|
|
1313
1430
|
/** slot 注入的 useMenuOpenState 在不同版本里可能不是数组,宽松取关闭函数。 */
|
|
@@ -1326,7 +1443,6 @@ window.__ModuleLoader__.load({
|
|
|
1326
1443
|
const apps = useApps();
|
|
1327
1444
|
usePinned();
|
|
1328
1445
|
const [open, setOpen] = useState(false);
|
|
1329
|
-
const [box, setBox] = useState(null);
|
|
1330
1446
|
const hostRef = useRef(null);
|
|
1331
1447
|
const closeTimer = useRef(0);
|
|
1332
1448
|
|
|
@@ -1352,17 +1468,8 @@ window.__ModuleLoader__.load({
|
|
|
1352
1468
|
};
|
|
1353
1469
|
}, [open]);
|
|
1354
1470
|
|
|
1355
|
-
//
|
|
1356
|
-
|
|
1357
|
-
useEffect(() => {
|
|
1358
|
-
if (!open) return;
|
|
1359
|
-
const host = hostRef.current;
|
|
1360
|
-
if (host === null) return;
|
|
1361
|
-
const pinnedIds = new Set(effectivePinned(apps.ids));
|
|
1362
|
-
const count = apps.ids.filter((id) => childOn(id) && !pinnedIds.has(id)).length;
|
|
1363
|
-
const height = Math.min(380, Math.max(40, count * 34 + 8));
|
|
1364
|
-
setBox(submenuGeometry(host.getBoundingClientRect(), { width: 220, height }));
|
|
1365
|
-
}, [open, apps.status, apps.ids]);
|
|
1471
|
+
// 面板先隐藏挂载再量真实尺寸,所以这里不再按条目数估算宽高。
|
|
1472
|
+
const box = useSubmenuPos(open, hostRef, [apps.status, apps.ids]);
|
|
1366
1473
|
|
|
1367
1474
|
// 会话行菜单的 pointerover/out 在 document 捕获阶段被「移出关闭」守卫截断,
|
|
1368
1475
|
// React 的 onPointerEnter 收不到。把悬浮展开挂到 window 捕获阶段,抢在守卫前。
|
|
@@ -1388,12 +1495,6 @@ window.__ModuleLoader__.load({
|
|
|
1388
1495
|
|
|
1389
1496
|
const openNow = () => {
|
|
1390
1497
|
window.clearTimeout(closeTimer.current);
|
|
1391
|
-
if (!open && hostRef.current !== null) {
|
|
1392
|
-
const pinnedIds = new Set(effectivePinned(apps.ids));
|
|
1393
|
-
const count = apps.ids.filter((id) => childOn(id) && !pinnedIds.has(id)).length;
|
|
1394
|
-
const height = Math.min(380, Math.max(40, count * 34 + 8));
|
|
1395
|
-
setBox(submenuGeometry(hostRef.current.getBoundingClientRect(), { width: 220, height }));
|
|
1396
|
-
}
|
|
1397
1498
|
setOpen(true);
|
|
1398
1499
|
ensureApps();
|
|
1399
1500
|
};
|
|
@@ -1459,7 +1560,7 @@ window.__ModuleLoader__.load({
|
|
|
1459
1560
|
},
|
|
1460
1561
|
jsx(IconRightUpOutlineRegular, { size: 14 }),
|
|
1461
1562
|
h('span', { className: 'dsrm-submenu-label' }, t('openWith')),
|
|
1462
|
-
jsx(IconChevronRightOutlineRegular, { size: 12, className:
|
|
1563
|
+
jsx(IconChevronRightOutlineRegular, { size: 12, className: chevronClass(box) }),
|
|
1463
1564
|
),
|
|
1464
1565
|
open ? h(MenuSurface, {
|
|
1465
1566
|
role: 'group',
|
|
@@ -1808,7 +1909,7 @@ window.__ModuleLoader__.load({
|
|
|
1808
1909
|
usePinned();
|
|
1809
1910
|
useChildren();
|
|
1810
1911
|
const hostRef = useRef(null);
|
|
1811
|
-
const
|
|
1912
|
+
const pos = useMenuPos(hostRef, x, y, [apps.status]);
|
|
1812
1913
|
|
|
1813
1914
|
const ellipsisMode = mode === 'ellipsis';
|
|
1814
1915
|
/** 右键菜单永远显示;「…」菜单只在对应开关打开时显示(内置项除外)。 */
|
|
@@ -1836,16 +1937,7 @@ window.__ModuleLoader__.load({
|
|
|
1836
1937
|
};
|
|
1837
1938
|
}, [onClose]);
|
|
1838
1939
|
|
|
1839
|
-
//
|
|
1840
|
-
useLayoutEffect(() => {
|
|
1841
|
-
const host = hostRef.current;
|
|
1842
|
-
if (host === null) return;
|
|
1843
|
-
const rect = host.getBoundingClientRect();
|
|
1844
|
-
const margin = 8;
|
|
1845
|
-
const left = Math.max(margin, Math.min(x, window.innerWidth - rect.width - margin));
|
|
1846
|
-
const top = Math.max(margin, Math.min(y, window.innerHeight - rect.height - margin));
|
|
1847
|
-
setPos((prev) => (prev !== null && prev.left === left && prev.top === top ? prev : { left, top }));
|
|
1848
|
-
}, [x, y, apps.status]);
|
|
1940
|
+
// 置顶应用是异步取到的,行数会变;尺寸变化由 useMenuPos 里的 ResizeObserver 兜住。
|
|
1849
1941
|
|
|
1850
1942
|
const group = props.group ?? {};
|
|
1851
1943
|
const workspaceId = typeof group.workspaceId === 'string' ? group.workspaceId : '';
|
|
@@ -2357,7 +2449,6 @@ window.__ModuleLoader__.load({
|
|
|
2357
2449
|
useChildren();
|
|
2358
2450
|
usePinned();
|
|
2359
2451
|
const [open, setOpen] = useState(false);
|
|
2360
|
-
const [box, setBox] = useState(null);
|
|
2361
2452
|
const hostRef = useRef(null);
|
|
2362
2453
|
const closeTimer = useRef(0);
|
|
2363
2454
|
|
|
@@ -2379,27 +2470,13 @@ window.__ModuleLoader__.load({
|
|
|
2379
2470
|
};
|
|
2380
2471
|
}, [open]);
|
|
2381
2472
|
|
|
2382
|
-
//
|
|
2383
|
-
|
|
2384
|
-
if (!open) return;
|
|
2385
|
-
const host = hostRef.current;
|
|
2386
|
-
if (host === null) return;
|
|
2387
|
-
const pinnedIds = new Set(effectivePinned(apps.ids).filter((id) => childOn(id)));
|
|
2388
|
-
const count = apps.ids.filter((id) => childOn(id) && !pinnedIds.has(id)).length;
|
|
2389
|
-
const height = Math.min(380, Math.max(40, count * 34 + 8));
|
|
2390
|
-
setBox(submenuGeometry(host.getBoundingClientRect(), { width: 220, height }));
|
|
2391
|
-
}, [open, apps.status, apps.ids]);
|
|
2473
|
+
// 面板先隐藏挂载再量真实尺寸,位置按真实宽高算。
|
|
2474
|
+
const box = useSubmenuPos(open, hostRef, [apps.status, apps.ids]);
|
|
2392
2475
|
|
|
2393
2476
|
useEffect(() => () => window.clearTimeout(closeTimer.current), []);
|
|
2394
2477
|
|
|
2395
2478
|
const openNow = () => {
|
|
2396
2479
|
window.clearTimeout(closeTimer.current);
|
|
2397
|
-
if (!open && hostRef.current !== null) {
|
|
2398
|
-
const pinnedIds = new Set(effectivePinned(apps.ids).filter((id) => childOn(id)));
|
|
2399
|
-
const count = apps.ids.filter((id) => childOn(id) && !pinnedIds.has(id)).length;
|
|
2400
|
-
const height = Math.min(380, Math.max(40, count * 34 + 8));
|
|
2401
|
-
setBox(submenuGeometry(hostRef.current.getBoundingClientRect(), { width: 220, height }));
|
|
2402
|
-
}
|
|
2403
2480
|
setOpen(true);
|
|
2404
2481
|
ensureApps();
|
|
2405
2482
|
};
|
|
@@ -2458,7 +2535,7 @@ window.__ModuleLoader__.load({
|
|
|
2458
2535
|
icon: jsx(IconRightUpOutlineRegular, { size: 14 }),
|
|
2459
2536
|
children: h('span', { className: 'dsrm-host-label' },
|
|
2460
2537
|
h('span', { className: 'dsrm-host-label-text' }, t('openWith')),
|
|
2461
|
-
jsx(IconChevronRightOutlineRegular, { size: 12, className:
|
|
2538
|
+
jsx(IconChevronRightOutlineRegular, { size: 12, className: chevronClass(box) }),
|
|
2462
2539
|
),
|
|
2463
2540
|
}),
|
|
2464
2541
|
open ? h(MenuSurface, {
|
|
@@ -2506,7 +2583,6 @@ window.__ModuleLoader__.load({
|
|
|
2506
2583
|
*/
|
|
2507
2584
|
function BlankMoreRows({ label, icon, controller, separatorBefore, onClose, children }) {
|
|
2508
2585
|
const [open, setOpen] = useState(false);
|
|
2509
|
-
const [box, setBox] = useState(null);
|
|
2510
2586
|
const hostRef = useRef(null);
|
|
2511
2587
|
const closeTimer = useRef(0);
|
|
2512
2588
|
const entries = orderMoreItems(controller.items);
|
|
@@ -2529,22 +2605,13 @@ window.__ModuleLoader__.load({
|
|
|
2529
2605
|
};
|
|
2530
2606
|
}, [open]);
|
|
2531
2607
|
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
const host = hostRef.current;
|
|
2535
|
-
if (host === null) return;
|
|
2536
|
-
const height = Math.min(320, Math.max(40, entries.length * 34 + 8));
|
|
2537
|
-
setBox(submenuGeometry(host.getBoundingClientRect(), { width: 220, height }));
|
|
2538
|
-
}, [open, controller, entries.length]);
|
|
2608
|
+
// 面板先隐藏挂载再量真实尺寸,位置按真实宽高算。
|
|
2609
|
+
const box = useSubmenuPos(open, hostRef, [entries.length]);
|
|
2539
2610
|
|
|
2540
2611
|
useEffect(() => () => window.clearTimeout(closeTimer.current), []);
|
|
2541
2612
|
|
|
2542
2613
|
const openNow = () => {
|
|
2543
2614
|
window.clearTimeout(closeTimer.current);
|
|
2544
|
-
if (!open && hostRef.current !== null) {
|
|
2545
|
-
const height = Math.min(320, Math.max(40, entries.length * 34 + 8));
|
|
2546
|
-
setBox(submenuGeometry(hostRef.current.getBoundingClientRect(), { width: 220, height }));
|
|
2547
|
-
}
|
|
2548
2615
|
setOpen(true);
|
|
2549
2616
|
};
|
|
2550
2617
|
const closeSoon = () => {
|
|
@@ -2578,7 +2645,7 @@ window.__ModuleLoader__.load({
|
|
|
2578
2645
|
icon: headerIconNode(icon),
|
|
2579
2646
|
children: h('span', { className: 'dsrm-host-label' },
|
|
2580
2647
|
h('span', { className: 'dsrm-host-label-text' }, children ?? label),
|
|
2581
|
-
jsx(IconChevronRightOutlineRegular, { size: 12, className:
|
|
2648
|
+
jsx(IconChevronRightOutlineRegular, { size: 12, className: chevronClass(box) }),
|
|
2582
2649
|
),
|
|
2583
2650
|
}),
|
|
2584
2651
|
open ? h(MenuSurface, {
|
|
@@ -2610,7 +2677,7 @@ window.__ModuleLoader__.load({
|
|
|
2610
2677
|
*/
|
|
2611
2678
|
function HeaderToolbarMenu({ x, y, items, t, sessionId, onClose }) {
|
|
2612
2679
|
const hostRef = useRef(null);
|
|
2613
|
-
const
|
|
2680
|
+
const pos = useMenuPos(hostRef, x, y, []);
|
|
2614
2681
|
const itemsConfig = useItems();
|
|
2615
2682
|
const blankMenu = useBlankMenu();
|
|
2616
2683
|
const apps = useApps();
|
|
@@ -2634,15 +2701,7 @@ window.__ModuleLoader__.load({
|
|
|
2634
2701
|
};
|
|
2635
2702
|
}, [onClose]);
|
|
2636
2703
|
|
|
2637
|
-
|
|
2638
|
-
const host = hostRef.current;
|
|
2639
|
-
if (host === null) return;
|
|
2640
|
-
const rect = host.getBoundingClientRect();
|
|
2641
|
-
const margin = 8;
|
|
2642
|
-
const left = Math.max(margin, Math.min(x, window.innerWidth - rect.width - margin));
|
|
2643
|
-
const top = Math.max(margin, Math.min(y, window.innerHeight - rect.height - margin));
|
|
2644
|
-
setPos((prev) => (prev !== null && prev.left === left && prev.top === top ? prev : { left, top }));
|
|
2645
|
-
}, [x, y, items]);
|
|
2704
|
+
// 位置由 useMenuPos 统一夹取:菜单行数随工具条内容变化,尺寸变了再夹一次。
|
|
2646
2705
|
|
|
2647
2706
|
const cwd = typeof sessionId === 'string' && sessionId !== '' ? sessionCwd(rootCtx, sessionId) : '';
|
|
2648
2707
|
const enabledApps = apps.ids.filter((id) => childOn(id));
|
|
@@ -3695,6 +3754,7 @@ window.__ModuleLoader__.load({
|
|
|
3695
3754
|
.dsrm-submenu-trigger:hover:not(:disabled),.dsrm-submenu-trigger:focus-visible{background:var(--dsw-alias-interactive-bg-hover);outline:none}
|
|
3696
3755
|
.dsrm-submenu-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
3697
3756
|
.dsrm-submenu-chevron{color:var(--dsw-alias-label-caption)}
|
|
3757
|
+
.dsrm-submenu-chevron-flipped{transform:scaleX(-1)}
|
|
3698
3758
|
.dsrm-host-label{display:flex;align-items:center;gap:6px;width:100%}
|
|
3699
3759
|
.dsrm-host-label-text{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis}
|
|
3700
3760
|
.dsrm-submenu{position:fixed;z-index:1101;min-width:180px;max-width:300px;max-height:min(380px,64vh);overflow:auto;padding:4px}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-sidebar-row-menu",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Adds open-with and cleanup entries to the DSH sidebar context menus (interleaved on 0.2.2+, self-drawn workspace menu on 0.2.1), plus a conversation-body right-click menu that mirrors the session header toolbar with in-menu open-with and more-actions submenus.",
|
|
6
6
|
"keywords": [
|