dsh-vscode-mode 0.1.62 → 0.1.63

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.
@@ -1,9 +1,11 @@
1
1
  // @ts-nocheck
2
2
  /**
3
3
  * dsh-vscode-mode client — 侧边栏面板定义(文件管理 + 搜索 + 规则)。
4
- * 作者 ddj 2026-08-26 / 2026-09-03
4
+ * 活动栏图标用官方 UI 原语(跟随 DSH 主题与皮肤);原语缺失时由 SidebarView 回落文本渲染。
5
+ * 作者 ddj 2026-08-26 / 2026-09-03 / 2026-09-10
5
6
  */
6
7
  import React from 'react'
8
+ import { IconFolderOpenOutline16, IconListPenOutline16, IconSearchOutline16 } from '@deepseek-ai/dsh-client-ui-primitives'
7
9
  import { FileExplorer } from './FileExplorer.js'
8
10
  import { SearchPanel } from './SearchPanel.js'
9
11
  import { RulesPanel } from './RulesPanel.js'
@@ -11,14 +13,14 @@ import type { SidebarPanelDef, SidebarCtx } from '../types.js'
11
13
 
12
14
  /**
13
15
  * 构造文件管理面板定义。
14
- * @author ddj 2026年08月26号
15
- * @returns 面板定义(含活动栏徽标 = 差异文件总数)
16
+ * @author ddj 2026年08月26号 / 2026年09月10号
17
+ * @returns 面板定义(含活动栏徽标 = 差异文件总数;图标 = 官方 IconFolderOpenOutline16)
16
18
  */
17
19
  export function createFilePanel(): SidebarPanelDef {
18
20
  return {
19
21
  id: 'explorer',
20
22
  title: '文件管理',
21
- icon: '📁',
23
+ icon: IconFolderOpenOutline16,
22
24
  order: 10,
23
25
  badge: (ctx: SidebarCtx) => (ctx.sum && ctx.sum.totalFiles > 0 ? ctx.sum.totalFiles : null),
24
26
  render: (ctx: SidebarCtx) => React.createElement(FileExplorer, { ctx }),
@@ -27,14 +29,14 @@ export function createFilePanel(): SidebarPanelDef {
27
29
 
28
30
  /**
29
31
  * 构造搜索面板定义。
30
- * @author ddj 2026年08月30号
31
- * @returns 面板定义(无徽标;活动栏图标 🔍)
32
+ * @author ddj 2026年08月30号 / 2026年09月10号
33
+ * @returns 面板定义(无徽标;图标 = 官方 IconSearchOutline16)
32
34
  */
33
35
  export function createSearchPanel(): SidebarPanelDef {
34
36
  return {
35
37
  id: 'search',
36
38
  title: '搜索',
37
- icon: '🔍',
39
+ icon: IconSearchOutline16,
38
40
  order: 15,
39
41
  render: (ctx: SidebarCtx) => React.createElement(SearchPanel, { ctx }),
40
42
  }
@@ -42,14 +44,14 @@ export function createSearchPanel(): SidebarPanelDef {
42
44
 
43
45
  /**
44
46
  * 构造规则管理面板定义(Codebuddy 规则形态:用户规则/项目规则双 Tab + 开关)。
45
- * @author ddj 2026年09月03号
46
- * @returns 面板定义(无徽标;活动栏图标 📏,与大纲 📜 区分)
47
+ * @author ddj 2026年09月03号 / 2026年09月10号
48
+ * @returns 面板定义(无徽标;图标 = 官方 IconListPenOutline16)
47
49
  */
48
50
  export function createRulesPanel(): SidebarPanelDef {
49
51
  return {
50
52
  id: 'rules',
51
53
  title: '规则',
52
- icon: '📏',
54
+ icon: IconListPenOutline16,
53
55
  order: 20,
54
56
  render: (ctx: SidebarCtx) => React.createElement(RulesPanel, { ctx }),
55
57
  }
@@ -40,8 +40,8 @@ export interface SidebarCtx {
40
40
  export interface SidebarPanelDef {
41
41
  id: string
42
42
  title: string
43
- /** 活动栏图标(文本/SVG 均可,横向居中显示)。 */
44
- icon: string
43
+ /** 活动栏图标:官方图标组件(跟随官方主题)或文本/emoji(回落),横向居中显示。 */
44
+ icon: string | ((props: { size?: number }) => unknown)
45
45
  order?: number
46
46
  /** 活动栏徽标:返回数字/null;缺省不显示。 */
47
47
  badge?: (ctx: SidebarCtx) => number | null
@@ -1,7 +1,9 @@
1
1
  /* dsh-vscode-mode 编辑区样式(原 ensureEdrvStyles 字符串,落盘为真 .css,由 tsdown CSS-inline 注入) */
2
- /* 浅色主题(对齐参考图:#f8f8f8 近白底 + 薄荷绿药丸 + 青绿文字 + 三文鱼 undo + 浅灰边框):
3
- 在 [data-edrv-view] 作用域内重定义 --dsw-alias-*,级联命中组件内联样式与 CSS。 */
4
- [data-edrv-view] { box-sizing: border-box; --edrv-tab-h: 34px; --dsw-alias-bg-base: #f8f8f8; --dsw-alias-bg-layer-1: #ffffff; --dsw-alias-bg-layer-2: #f0f4f4; --dsw-alias-bg-overlay: #ffffff; --dsw-alias-label-primary: #1f2933; --dsw-alias-label-secondary: #52606d; --dsw-alias-label-tertiary: #9aa5b1; --dsw-alias-border-l1: #e0e6e8; --dsw-alias-border-l2: #cbd2d9; --dsw-alias-brand-primary: #0f9d58; --dsw-alias-state-success-primary: #0f9d58; --dsw-alias-state-error-primary: #d9534f; --dsw-alias-state-warn-primary: #d97706; --dsw-alias-interactive-bg-hover: rgba(15,157,88,.08); }
2
+ /* 主题:跟随官方 --dsw-alias-* 令牌(DSH 明暗与第三方皮肤生效)。
3
+ 本作用域不再重定义官方令牌(旧实现曾在此硬覆盖浅色盘,导致插件不跟随 DSH 主题);
4
+ 旧环境/缺令牌场景由每条声明的 var(--dsw-alias-*, 回落值) 兜底。
5
+ @author ddj 2026-09-10 */
6
+ [data-edrv-view] { box-sizing: border-box; --edrv-tab-h: 34px; }
5
7
 
6
8
  [data-edrv-view] .edrv-tabs { display: flex; align-items: center; gap: 2px; padding: 2px 8px 0; background: var(--dsw-alias-bg-layer-1, transparent); overflow-x: auto; scrollbar-width: thin; flex-shrink: 0; }
7
9
  [data-edrv-view] .edrv-tab { display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 8px 0 12px; border: none; border-radius: 6px 6px 0 0; background: transparent; color: var(--dsw-alias-label-secondary, #aaa); font-size: 12px; cursor: pointer; white-space: nowrap; flex-shrink: 0; }
@@ -9,7 +11,7 @@
9
11
  [data-edrv-view] .edrv-tab.edrv-tab-active { background: var(--dsw-alias-bg-base, #111); color: var(--dsw-alias-label-primary, #eee); box-shadow: inset 0 -2px 0 var(--dsw-alias-brand-primary, #4f8cff); }
10
12
  [data-edrv-view] .edrv-tab .edrv-tab-star { color: var(--dsw-alias-brand-primary, #4f8cff); font-size: 13px; font-weight: 700; line-height: 1; flex-shrink: 0; } /* 未保存修改星号 @author ddj 2026年09月09号 */
11
13
  [data-edrv-view] .edrv-tab .edrv-tab-x { display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; border-radius: 4px; color: var(--dsw-alias-label-tertiary, #888); font-size: 11px; }
12
- [data-edrv-view] .edrv-tab .edrv-tab-x:hover { background: rgba(255,255,255,.12); color: var(--dsw-alias-label-primary, #eee); }
14
+ [data-edrv-view] .edrv-tab .edrv-tab-x:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.12)); color: var(--dsw-alias-label-primary, #eee); }
13
15
  [data-edrv-view] .edrv-tab-add { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; margin-left: 2px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-secondary, #aaa); font-size: 14px; cursor: pointer; flex-shrink: 0; }
14
16
  [data-edrv-view] .edrv-tab-add:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.06)); }
15
17
  [data-edrv-view] .edrv-pathbar { display: flex; align-items: center; gap: 8px; height: 26px; padding: 0 10px; background: var(--dsw-alias-bg-layer-1, #ffffff); border-bottom: 1px solid var(--dsw-alias-border-l1, #e0e6e8); font-size: 12px; flex-shrink: 0; overflow: hidden; }
@@ -27,7 +29,7 @@
27
29
  [data-edrv-view] .edrv-search-item .n { color: var(--dsw-alias-label-primary, #eee); font-size: 12px; word-break: break-all; }
28
30
  [data-edrv-view] .edrv-search-item .d { color: var(--dsw-alias-label-tertiary, #888); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
29
31
  [data-edrv-view] .edrv-search-empty { padding: 8px; font-size: 12px; color: var(--dsw-alias-label-tertiary, #888); }
30
- [data-edrv-view] .edrv-btn-mini { font-size: 11px; padding: 2px 9px; border: none; border-radius: 999px; cursor: pointer; color: #fff; font-weight: 600; white-space: nowrap; }
32
+ [data-edrv-view] .edrv-btn-mini { font-size: 11px; padding: 2px 9px; border: none; border-radius: 999px; cursor: pointer; color: var(--dsw-alias-label-primary-inverted, #fff); font-weight: 600; white-space: nowrap; }
31
33
  [data-edrv-view] .edrv-btn-keep { background: var(--dsw-alias-state-success-primary, #2e9e44); }
32
34
  [data-edrv-view] .edrv-btn-undo { background: var(--dsw-alias-state-warn-primary, #d97706); }
33
35
  [data-edrv-view] .edrv-btn-mini:disabled { opacity: .45; cursor: default; }
@@ -47,15 +49,15 @@
47
49
  [data-edrv-view] .edrv-chip-btn:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.06)); }
48
50
  [data-edrv-view] .edrv-chip-btn:disabled { opacity: .35; cursor: default; }
49
51
  [data-edrv-view] .edrv-chip-btn:disabled:hover { background: transparent; }
50
- [data-edrv-view] .edrv-mn-add-line { background: rgba(15,157,88,.10); }
51
- [data-edrv-view] .edrv-mn-gutter-add { color: #0f9d58 !important; font-weight: 700; display: flex !important; align-items: center; justify-content: center; }
52
+ [data-edrv-view] .edrv-mn-add-line { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.10)); }
53
+ [data-edrv-view] .edrv-mn-gutter-add { color: var(--dsw-alias-state-success-primary, #0f9d58) !important; font-weight: 700; display: flex !important; align-items: center; justify-content: center; }
52
54
  [data-edrv-view] .edrv-mn-gutter-add::before { content: "+"; }
53
- [data-edrv-view] .edrv-del-zone { background: #fdeaea; border-top: 1px solid rgba(217,83,79,.35); border-bottom: 1px solid rgba(217,83,79,.35); box-shadow: inset 0 0 0 1px rgba(217,83,79,.12); }
54
- [data-edrv-view] .edrv-del-row { white-space: pre; font-family: var(--ds-font-family-code, ui-monospace, monospace); font-size: 12.5px; line-height: 20px; color: #c0392b; }
55
+ [data-edrv-view] .edrv-del-zone { background: var(--dsw-alias-interactive-bg-hover-danger, rgba(217,83,79,.14)); border-top: 1px solid var(--dsw-alias-state-error-primary, rgba(217,83,79,.35)); border-bottom: 1px solid var(--dsw-alias-state-error-primary, rgba(217,83,79,.35)); box-shadow: inset 0 0 0 1px var(--dsw-alias-interactive-bg-hover-danger, rgba(217,83,79,.12)); }
56
+ [data-edrv-view] .edrv-del-row { white-space: pre; font-family: var(--ds-font-family-code, ui-monospace, monospace); font-size: 12.5px; line-height: 20px; color: var(--dsw-alias-state-error-primary, #c0392b); }
55
57
  [data-edrv-view] .edrv-del-text { display: inline-block; white-space: pre; }
56
58
  [data-edrv-view] .edrv-minus-overlay { position: absolute; left: 0; top: 0; width: 100%; height: 100%; max-width: 100%; overflow: visible; pointer-events: none; z-index: 6; }
57
59
  [data-edrv-view] .edrv-minus-item { position: absolute; box-sizing: border-box; max-width: 100%; overflow: hidden; }
58
- [data-edrv-view] .edrv-minus-item::before { content: ''; position: absolute; left: 4px; top: 50%; width: 8px; height: 2px; transform: translateY(-50%); border-radius: 2px; background: #d9534f; }
60
+ [data-edrv-view] .edrv-minus-item::before { content: ''; position: absolute; left: 4px; top: 50%; width: 8px; height: 2px; transform: translateY(-50%); border-radius: 2px; background: var(--dsw-alias-state-error-primary, #d9534f); }
59
61
  [data-edrv-view] .edrv-monaco-host { flex: 1 1 auto; min-width: 0; min-height: 0; position: relative; overflow: hidden; }
60
62
  [data-edrv-view] .edrv-monaco-host > div { position: absolute; inset: 0; min-width: 0; min-height: 0; }
61
63
  [data-edrv-view] .edrv-imgview { flex: 1 1 auto; min-width: 0; min-height: 0; display: flex; flex-direction: column; overflow: hidden; }
@@ -83,9 +85,9 @@
83
85
  [data-edrv-view] .edrv-diffbar-count.edrv-count-file { min-width: 64px; cursor: default; }
84
86
  [data-edrv-view] .edrv-diffbar-file { flex: 1; min-width: 0; font-size: 11px; color: var(--dsw-alias-label-tertiary, #9aa5b1); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
85
87
  [data-edrv-view] .edrv-pill { font-size: 11px; padding: 3px 10px; border: none; border-radius: 999px; cursor: pointer; white-space: nowrap; font-weight: 600; }
86
- [data-edrv-view] .edrv-pill-keep { background: #e8f8e8; color: #0f7a45; border: 1px solid rgba(15,157,88,.4); }
87
- [data-edrv-view] .edrv-pill-undo { background: #fdeaea; color: #c0392b; border: 1px solid rgba(217,83,79,.4); }
88
- [data-edrv-view] .edrv-pill-ghost { background: #ffffff; color: var(--dsw-alias-label-secondary, #52606d); border: 1px solid var(--dsw-alias-border-l1, #e0e6e8); }
88
+ [data-edrv-view] .edrv-pill-keep { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.14)); color: var(--dsw-alias-state-success-primary, #0f7a45); border: 1px solid var(--dsw-alias-state-success-primary, rgba(15,157,88,.4)); }
89
+ [data-edrv-view] .edrv-pill-undo { background: var(--dsw-alias-interactive-bg-hover-danger, rgba(217,83,79,.14)); color: var(--dsw-alias-state-error-primary, #c0392b); border: 1px solid var(--dsw-alias-state-error-primary, rgba(217,83,79,.4)); }
90
+ [data-edrv-view] .edrv-pill-ghost { background: var(--dsw-alias-bg-layer-1, #ffffff); color: var(--dsw-alias-label-secondary, #52606d); border: 1px solid var(--dsw-alias-border-l1, #e0e6e8); }
89
91
  [data-edrv-view] .edrv-pill:disabled { opacity: .45; cursor: default; }
90
92
  [data-edrv-view] .edrv-diffbar-menu { position: absolute; right: 8px; bottom: calc(100% + 6px); z-index: 45; min-width: 160px; border-radius: 10px; background: var(--dsw-alias-bg-overlay, #ffffff); border: 1px solid var(--dsw-alias-border-l2, #cbd2d9); box-shadow: 0 6px 20px rgba(31,41,51,.16); padding: 4px; display: flex; flex-direction: column; gap: 2px; }
91
93
  [data-edrv-view] .edrv-diffmenu-item { display: flex; align-items: center; gap: 8px; font-size: 12px; padding: 6px 10px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-primary, #1f2933); cursor: pointer; text-align: left; }
@@ -107,7 +109,7 @@
107
109
  [data-edrv-view] .edrv-diffrow-o { font-size: 11px; color: var(--dsw-alias-state-error-primary, #d9534f); font-family: var(--ds-font-family-code, ui-monospace, monospace); }
108
110
  [data-edrv-view] .edrv-diffrow-n { font-size: 11px; color: var(--dsw-alias-state-success-primary, #0f9d58); font-family: var(--ds-font-family-code, ui-monospace, monospace); }
109
111
  [data-edrv-view] .edrv-diffrow-tag { font-size: 11px; color: var(--dsw-alias-label-tertiary, #9aa5b1); }
110
- [data-edrv-view] .edrv-diffrow-stale { border-color: rgba(217,119,6,.5); cursor: default; }
112
+ [data-edrv-view] .edrv-diffrow-stale { border-color: var(--dsw-alias-state-warn-primary, rgba(217,119,6,.5)); cursor: default; }
111
113
  [data-edrv-view] .edrv-diffbox-others { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; padding: 4px 2px 0; border-top: 1px solid var(--dsw-alias-border-l1, #e0e6e8); margin-top: 2px; }
112
114
  [data-edrv-view] .edrv-diffrow-file { font-size: 11px; padding: 2px 10px; border: 1px solid var(--dsw-alias-border-l1, #e0e6e8); border-radius: 999px; background: var(--dsw-alias-bg-layer-2, #f0f4f4); color: var(--dsw-alias-label-secondary, #52606d); cursor: pointer; white-space: nowrap; max-width: 200px; overflow: hidden; text-overflow: ellipsis; }
113
115
  [data-edrv-view] .edrv-diffrow-file:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); color: var(--dsw-alias-label-primary, #1f2933); }
@@ -228,8 +230,11 @@
228
230
  [data-edrv-view] .edrv-rail-btn { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; border: none; border-radius: 8px; background: transparent; color: var(--dsw-alias-label-secondary, #52606d); cursor: pointer; flex-shrink: 0; }
229
231
  [data-edrv-view] .edrv-rail-btn:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }
230
232
  [data-edrv-view] .edrv-rail-btn.edrv-rail-on { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.12)); color: var(--dsw-alias-label-primary, #1f2933); box-shadow: inset 2px 0 0 var(--dsw-alias-brand-primary, #0f9d58); }
231
- [data-edrv-view] .edrv-rail-icon { font-size: 15px; line-height: 1; }
232
- [data-edrv-view] .edrv-rail-badge { position: absolute; top: 2px; right: 2px; min-width: 14px; height: 14px; padding: 0 3px; border-radius: 999px; background: var(--dsw-alias-brand-primary, #0f9d58); color: #fff; font-size: 9px; font-weight: 600; line-height: 14px; text-align: center; box-sizing: border-box; }
233
+ [data-edrv-view] .edrv-rail-icon { font-size: 15px; line-height: 1; display: inline-flex; align-items: center; justify-content: center; }
234
+ /* 树行图标:官方原语(文件夹/文件类型),尺寸与行高对齐 @author ddj 2026-09-10 */
235
+ [data-edrv-view] .edrv-tree-icon { flex-shrink: 0; display: inline-flex; align-items: center; color: var(--dsw-alias-label-tertiary, #9aa5b1); }
236
+ [data-edrv-view] .edrv-tree-row.edrv-tree-active .edrv-tree-icon { color: var(--dsw-alias-label-secondary, #52606d); }
237
+ [data-edrv-view] .edrv-rail-badge { position: absolute; top: 2px; right: 2px; min-width: 14px; height: 14px; padding: 0 3px; border-radius: 999px; background: var(--dsw-alias-brand-primary, #0f9d58); color: var(--dsw-alias-label-primary-inverted, #fff); font-size: 9px; font-weight: 600; line-height: 14px; text-align: center; box-sizing: border-box; }
233
238
  [data-edrv-view] .edrv-side-body { flex: 1; min-width: 0; min-height: 0; display: flex; overflow: hidden; }
234
239
  [data-edrv-view] .edrv-side-panel { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column; position: relative; }
235
240
  [data-edrv-view] .edrv-side-head { display: flex; align-items: center; gap: 8px; height: 34px; padding: 0 10px 0 12px; border-bottom: 1px solid var(--dsw-alias-border-l1, #e0e6e8); flex-shrink: 0; }
@@ -245,9 +250,9 @@
245
250
  [data-edrv-view] .edrv-tree-chev { width: 12px; flex-shrink: 0; color: var(--dsw-alias-label-tertiary, #9aa5b1); font-size: 10px; text-align: center; }
246
251
  [data-edrv-view] .edrv-tree-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
247
252
  [data-edrv-view] .edrv-tree-name.edrv-tree-dim { color: var(--dsw-alias-label-tertiary, #9aa5b1); }
248
- [data-edrv-view] .edrv-tree-badge { min-width: 14px; height: 14px; padding: 0 4px; border-radius: 999px; background: var(--dsw-alias-state-warn-primary, #d97706); color: #fff; font-size: 9px; font-weight: 600; line-height: 14px; text-align: center; box-sizing: border-box; flex-shrink: 0; }
253
+ [data-edrv-view] .edrv-tree-badge { min-width: 14px; height: 14px; padding: 0 4px; border-radius: 999px; background: var(--dsw-alias-state-warn-primary, #d97706); color: var(--dsw-alias-label-primary-inverted, #fff); font-size: 9px; font-weight: 600; line-height: 14px; text-align: center; box-sizing: border-box; flex-shrink: 0; }
249
254
  [data-edrv-view] .edrv-tree-loading { height: 22px; line-height: 22px; color: var(--dsw-alias-label-tertiary, #9aa5b1); font-size: 11px; }
250
- [data-edrv-view] .edrv-tree-error { display: flex; align-items: center; gap: 8px; margin: 4px 2px 6px; padding: 6px 8px; border: 1px solid rgba(217,83,79,.4); border-radius: 6px; background: #fdeaea; color: var(--dsw-alias-state-error-primary, #d9534f); font-size: 11px; }
255
+ [data-edrv-view] .edrv-tree-error { display: flex; align-items: center; gap: 8px; margin: 4px 2px 6px; padding: 6px 8px; border: 1px solid var(--dsw-alias-state-error-primary, rgba(217,83,79,.4)); border-radius: 6px; background: var(--dsw-alias-interactive-bg-hover-danger, rgba(217,83,79,.12)); color: var(--dsw-alias-state-error-primary, #d9534f); font-size: 11px; }
251
256
  /* 大纲面板:kind 字形 / detail / 行号 */
252
257
  [data-edrv-view] .edrv-outline-kind { display: inline-flex; align-items: center; justify-content: center; width: 14px; flex-shrink: 0; font-size: 12px; font-weight: 600; text-align: center; }
253
258
  [data-edrv-view] .edrv-outline-kind.edrv-ol-func { color: var(--dsw-alias-brand-primary, #0f9d58); }
@@ -295,10 +300,10 @@
295
300
  [data-edrv-view] .edrv-search-line:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }
296
301
  [data-edrv-view] .edrv-search-ln { flex-shrink: 0; color: var(--dsw-alias-label-tertiary, #9aa5b1); font-size: 11px; min-width: 26px; text-align: right; user-select: none; }
297
302
  [data-edrv-view] .edrv-search-text { overflow: hidden; text-overflow: ellipsis; white-space: pre; font-family: var(--ds-font-family-code, ui-monospace, monospace); font-size: 11px; }
298
- [data-edrv-view] .edrv-search-hit { background: var(--dsw-alias-state-warn-primary, #e5b93f); color: #1f2933; border-radius: 2px; padding: 0 1px; }
303
+ [data-edrv-view] .edrv-search-hit { background: var(--dsw-alias-state-warn-primary, #e5b93f); color: var(--dsw-alias-label-primary-inverted, #1f2933); border-radius: 2px; padding: 0 1px; }
299
304
  [data-edrv-view] .edrv-search-empty { padding: 8px 4px; font-size: 12px; color: var(--dsw-alias-label-tertiary, #9aa5b1); }
300
- [data-edrv-view] .edrv-search-error { padding: 6px 8px; border: 1px solid rgba(217,83,79,.4); border-radius: 6px; background: #fdeaea; color: var(--dsw-alias-state-error-primary, #d9534f); font-size: 11px; }
301
- [data-edrv-view] .edrv-search-warn { padding: 6px 8px; border: 1px solid rgba(240,173,78,.45); border-radius: 6px; background: #fdf6e3; color: #b8860b; font-size: 11px; word-break: break-all; }
305
+ [data-edrv-view] .edrv-search-error { padding: 6px 8px; border: 1px solid var(--dsw-alias-state-error-primary, rgba(217,83,79,.4)); border-radius: 6px; background: var(--dsw-alias-interactive-bg-hover-danger, rgba(217,83,79,.12)); color: var(--dsw-alias-state-error-primary, #d9534f); font-size: 11px; }
306
+ [data-edrv-view] .edrv-search-warn { padding: 6px 8px; border: 1px solid var(--dsw-alias-state-warn-primary, rgba(240,173,78,.45)); border-radius: 6px; background: var(--dsw-alias-interactive-bg-hover, rgba(240,173,78,.12)); color: var(--dsw-alias-state-warn-primary, #b8860b); font-size: 11px; word-break: break-all; }
302
307
 
303
308
  /* include/exclude filter rows (collapsible) */
304
309
  [data-edrv-view] .edrv-search-rows { display: flex; flex-direction: column; gap: 4px; padding: 2px 0 4px; }
@@ -333,20 +338,20 @@
333
338
  [data-edrv-view] .edrv-rules-file { font-weight: 600; font-size: 12px; color: var(--dsw-alias-label-primary, #1f2933); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
334
339
  [data-edrv-view] .edrv-rules-path { font-size: 10px; color: var(--dsw-alias-label-tertiary, #9aa5b1); flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
335
340
  [data-edrv-view] .edrv-rules-type { flex-shrink: 0; height: 15px; padding: 0 5px; border-radius: 999px; font-size: 10px; line-height: 15px; }
336
- [data-edrv-view] .edrv-rules-type-always { background: rgba(15,157,88,.15); color: #0b7c46; }
337
- [data-edrv-view] .edrv-rules-type-auto { background: rgba(79,140,255,.16); color: #3367c9; }
341
+ [data-edrv-view] .edrv-rules-type-always { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.15)); color: var(--dsw-alias-state-success-primary, #0b7c46); }
342
+ [data-edrv-view] .edrv-rules-type-auto { background: var(--dsw-alias-interactive-bg-hover-accent, rgba(79,140,255,.16)); color: var(--dsw-alias-link, #3367c9); }
338
343
  [data-edrv-view] .edrv-rules-type-manual { background: var(--dsw-alias-bg-layer-2, #f0f4f4); color: var(--dsw-alias-label-secondary, #52606d); }
339
344
  [data-edrv-view] .edrv-rules-offtag { font-size: 10px; color: var(--dsw-alias-label-tertiary, #9aa5b1); flex-shrink: 0; }
340
345
  [data-edrv-view] .edrv-rules-desc { font-size: 11px; color: var(--dsw-alias-label-secondary, #52606d); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; flex: 0 1 auto; }
341
346
  [data-edrv-view] .edrv-rules-actions { display: flex; align-items: center; gap: 2px; flex-shrink: 0; margin-left: auto; }
342
347
  [data-edrv-view] .edrv-rules-act { min-width: 22px; height: 22px; padding: 0 4px; border: none; border-radius: 5px; background: transparent; font-size: 12px; line-height: 1; cursor: pointer; color: var(--dsw-alias-label-secondary, #52606d); display: inline-flex; align-items: center; justify-content: center; }
343
348
  [data-edrv-view] .edrv-rules-act:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }
344
- [data-edrv-view] .edrv-rules-switch { position: relative; width: 30px; height: 16px; border-radius: 999px; border: none; background: #b9c4cc; cursor: pointer; transition: background .15s; flex-shrink: 0; padding: 0; }
345
- [data-edrv-view] .edrv-rules-switch.on { background: #7c5cff; }
346
- [data-edrv-view] .edrv-rules-knob { position: absolute; top: 2px; left: 2px; width: 12px; height: 12px; border-radius: 50%; background: #fff; transition: left .15s; }
349
+ [data-edrv-view] .edrv-rules-switch { position: relative; width: 30px; height: 16px; border-radius: 999px; border: none; background: var(--dsw-alias-border-l2, #b9c4cc); cursor: pointer; transition: background .15s; flex-shrink: 0; padding: 0; }
350
+ [data-edrv-view] .edrv-rules-switch.on { background: var(--dsw-alias-brand-primary, #7c5cff); }
351
+ [data-edrv-view] .edrv-rules-knob { position: absolute; top: 2px; left: 2px; width: 12px; height: 12px; border-radius: 50%; background: var(--dsw-alias-bg-layer-1, #fff); transition: left .15s; }
347
352
  [data-edrv-view] .edrv-rules-switch.on .edrv-rules-knob { left: 16px; }
348
353
  [data-edrv-view] .edrv-rules-empty { padding: 10px 4px; font-size: 12px; color: var(--dsw-alias-label-tertiary, #9aa5b1); line-height: 1.6; }
349
- [data-edrv-view] .edrv-rules-err { padding: 6px 8px; border: 1px solid rgba(217,83,79,.4); border-radius: 6px; background: #fdeaea; color: var(--dsw-alias-state-error-primary, #d9534f); font-size: 11px; word-break: break-all; }
354
+ [data-edrv-view] .edrv-rules-err { padding: 6px 8px; border: 1px solid var(--dsw-alias-state-error-primary, rgba(217,83,79,.4)); border-radius: 6px; background: var(--dsw-alias-interactive-bg-hover-danger, rgba(217,83,79,.12)); color: var(--dsw-alias-state-error-primary, #d9534f); font-size: 11px; word-break: break-all; }
350
355
  [data-edrv-view] .edrv-rules-editor { display: flex; flex-direction: column; min-height: 0; flex: 1; gap: 6px; }
351
356
  [data-edrv-view] .edrv-rules-editor-head { display: flex; align-items: center; justify-content: space-between; gap: 6px; font-size: 12px; font-weight: 600; color: var(--dsw-alias-label-primary, #1f2933); flex: 0 0 auto; }
352
357
  [data-edrv-view] .edrv-rules-crumb { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@@ -361,7 +366,7 @@
361
366
  [data-edrv-view] .edrv-rules-body:focus { border-color: var(--dsw-alias-brand-primary, #4f8cff); }
362
367
  [data-edrv-view] .edrv-rules-editor-hint { font-size: 10px; color: var(--dsw-alias-label-tertiary, #9aa5b1); line-height: 1.5; flex: 0 0 auto; }
363
368
  [data-edrv-view] .edrv-rules-editor-foot { display: flex; justify-content: flex-end; flex: 0 0 auto; }
364
- [data-edrv-view] .edrv-rules-save { height: 24px; padding: 0 14px; border: none; border-radius: 6px; background: var(--dsw-alias-brand-primary, #0f9d58); color: #fff; font-size: 12px; cursor: pointer; }
369
+ [data-edrv-view] .edrv-rules-save { height: 24px; padding: 0 14px; border: none; border-radius: 6px; background: var(--dsw-alias-brand-primary, #0f9d58); color: var(--dsw-alias-label-primary-inverted, #fff); font-size: 12px; cursor: pointer; }
365
370
  [data-edrv-view] .edrv-rules-save:disabled { opacity: .5; cursor: default; }
366
371
 
367
372
 
@@ -0,0 +1,96 @@
1
+ // @ts-nocheck
2
+ /**
3
+ * dsh-vscode-mode client — ClaimRouter:官方 file 认领页签的中转正文。
4
+ * 官方为每个 `dsh-resource://file/**` 地址开一个认领页签;本组件只做转发:
5
+ * 解析地址 → 送进单一编辑器页签(文件分页由编辑器自带页签栏接管)→ 关闭本中转页签。
6
+ * 转发失败(seat 未就绪等瞬时态)按 3 次 ×150ms 重试;仍失败则就地渲染兜底正文
7
+ * (旧行为:每文件一套编辑器),保证退化路径不白屏。本组件自身不创建 Monaco 实例。
8
+ * 作者 ddj 2026年09月10号
9
+ */
10
+ import React from 'react'
11
+ import { forwardToEditor, parseOfficialFileAddress, resolveNavLine } from '../officialSidebar.js'
12
+ import { log } from '../log.js'
13
+
14
+ /** 转发尝试次数(含首次)与重试间隔。 */
15
+ const FORWARD_ATTEMPTS = 3
16
+ const FORWARD_DELAY_MS = 150
17
+
18
+ /**
19
+ * 读 slot 框架注入的 tab 记录(hook 缺失或抛错时返回 undefined)。
20
+ * @author ddj 2026年09月10号
21
+ * @param props slot 框架注入的组件 props
22
+ * @returns tab 记录(含 navigation 与 actions),或 undefined
23
+ */
24
+ function readTab(props) {
25
+ const useTabInfo = props?.useTabInfo
26
+ if (typeof useTabInfo !== 'function') return undefined
27
+ try {
28
+ return useTabInfo()?.tab
29
+ } catch {
30
+ return undefined
31
+ }
32
+ }
33
+
34
+ /**
35
+ * 关闭本中转页签(失败仅告警:目标文件已在编辑器打开,残留页签不阻塞功能)。
36
+ * @author ddj 2026年09月10号
37
+ * @param tab slot 框架注入的 tab 记录
38
+ */
39
+ function closeTab(tab) {
40
+ try {
41
+ tab?.actions?.close?.()
42
+ } catch (error) {
43
+ log.warn('中转页签关闭失败(' + String(error) + ')')
44
+ }
45
+ }
46
+
47
+ /**
48
+ * 组装 file 认领转发正文。
49
+ * @author ddj 2026年09月10号
50
+ * @param spec 装配依赖(service 官方导航服务 / schedule 延时调度 / fallback 兜底正文)
51
+ * @returns 正文组件(注册进 keyed slot sidebar.right.pane.tab)
52
+ */
53
+ export function createClaimRouter(spec) {
54
+ const service = spec?.service
55
+ const schedule = spec?.schedule
56
+ const fallback = spec?.fallback
57
+
58
+ /**
59
+ * 中转正文:转发成功即关闭自身;重试耗尽后渲染兜底正文。
60
+ * @param props slot 框架注入(useTabInfo)+ 装配依赖
61
+ * @returns 兜底正文元素,或 null(转发中 / 已转发)
62
+ */
63
+ function ClaimRouter(props) {
64
+ const tab = readTab(props)
65
+ const navigation = tab?.navigation
66
+ const revision = typeof navigation?.revision === 'number' ? navigation.revision : -1
67
+ const [failed, setFailed] = React.useState(false)
68
+ const doneRef = React.useRef(-1)
69
+
70
+ React.useEffect(() => {
71
+ if (revision === doneRef.current) return
72
+ doneRef.current = revision
73
+ const parsed = parseOfficialFileAddress(navigation?.address)
74
+ if (!parsed) {
75
+ setFailed(true)
76
+ return
77
+ }
78
+ const line = resolveNavLine(navigation?.params)
79
+ let left = FORWARD_ATTEMPTS
80
+ const attempt = () => {
81
+ if (forwardToEditor(service, parsed.path, line)) {
82
+ closeTab(tab)
83
+ return
84
+ }
85
+ left -= 1
86
+ if (left > 0 && typeof schedule === 'function') schedule(attempt, FORWARD_DELAY_MS)
87
+ else setFailed(true)
88
+ }
89
+ attempt()
90
+ }, [revision])
91
+
92
+ if (!failed || typeof fallback !== 'function') return null
93
+ return React.createElement(fallback, props)
94
+ }
95
+ return ClaimRouter
96
+ }
@@ -14,7 +14,7 @@ import { langOf, loadMonaco } from '../monaco/loader.js'
14
14
  import { dataUrlOf, isImagePath, isSvgPath } from '../imagePreview.js'
15
15
  import { base64ToBytes, isPdfPath } from '../pdfPreview.js'
16
16
  import { createPdfPanel } from '../pdf/pdfPanel.js'
17
- import { applyTheme, registerThemes, themeNameOf } from '../monaco/theme.js'
17
+ import { applyOfficial, registerThemes, themeNameOf } from '../monaco/theme.js'
18
18
  import { createDiffRenderer } from '../monaco/diffRender.js'
19
19
  import { ST, callIdAttr, noopHunk, summarize } from '../state/records.js'
20
20
  import { diffRegions } from '../state/regions.js'
@@ -130,6 +130,8 @@ export function EditorView(props) {
130
130
  const navCursorTimerRef = React.useRef(null) // 光标位置防抖记录计时器
131
131
  const navBackRef = React.useRef(null) // 后退动作最新闭包(窗口级键盘监听读取)
132
132
  const navForwardRef = React.useRef(null) // 前进动作最新闭包(窗口级键盘监听读取)
133
+ const cycleTabRef = React.useRef(null) // 页签循环动作最新闭包(Ctrl+Alt+←/→、Ctrl+PgUp/PgDn)
134
+ const tabsHostRef = React.useRef(null) // 页签栏容器(切换后把当前页签滚入可见区)
133
135
  const [navTick, setNavTick] = React.useState(0) // 历史可用性版本(按钮 disabled 重渲染)
134
136
  const hoverRegionsRef = React.useRef([]) // 当前 pending 区域镜像(稳定回调读取)
135
137
  const lineRegionMapRef = React.useRef(new Map()) // 行 → 区域 映射(hover 命中)
@@ -324,6 +326,23 @@ export function EditorView(props) {
324
326
  })
325
327
  }
326
328
 
329
+ /**
330
+ * 在已打开页签间循环切换(文件分页归编辑器自带页签栏)。
331
+ * @author ddj 2026年09月10号
332
+ * @param step 步进(+1 下一个 / -1 上一个)
333
+ */
334
+ const cycleTab = (step) => {
335
+ if (tabs.length < 2) return
336
+ const idx = tabs.findIndex((t) => t.path === active)
337
+ const next = tabs[(idx + step + tabs.length) % tabs.length]
338
+ if (!next || next.path === active) return
339
+ flushSave()
340
+ saveViewState(active)
341
+ recordNav()
342
+ setActive(next.path)
343
+ }
344
+ cycleTabRef.current = cycleTab
345
+
327
346
  /**
328
347
  * 轮询去重:前后记录内容一致时返回原引用,React 跳过重渲染,
329
348
  * 阻断 5s 轮询 → memo 链 → diff 重渲染/日志 的空转。
@@ -766,6 +785,33 @@ export function EditorView(props) {
766
785
  return () => window.removeEventListener('keydown', onKey, true)
767
786
  }, [])
768
787
 
788
+ // 页签循环切换:Ctrl+Alt+←/→(主候选,浏览器不占用)或 Ctrl+PgUp/PgDn(部分宿主可用)
789
+ React.useEffect(() => {
790
+ const onKey = (e) => {
791
+ const step = matchEvent(e, bindingsOf('edrv.nextTab')) ? 1
792
+ : matchEvent(e, bindingsOf('edrv.prevTab')) ? -1
793
+ : 0
794
+ if (step === 0) return
795
+ e.preventDefault(); e.stopPropagation()
796
+ if (cycleTabRef.current) cycleTabRef.current(step)
797
+ }
798
+ window.addEventListener('keydown', onKey, true)
799
+ return () => window.removeEventListener('keydown', onKey, true)
800
+ }, [])
801
+
802
+ // 活动页签滚动可见(页签栏溢出时键盘切换/打开文件后把当前页签带回视野):
803
+ // 只调整页签栏自身 scrollLeft,不触发页面滚动。
804
+ React.useEffect(() => {
805
+ const host = tabsHostRef.current
806
+ if (!host) return
807
+ const el = host.querySelector?.('.edrv-tab-active')
808
+ if (!el) return
809
+ const left = el.offsetLeft
810
+ const right = left + el.offsetWidth
811
+ if (left < host.scrollLeft) host.scrollLeft = left
812
+ else if (right > host.scrollLeft + host.clientWidth) host.scrollLeft = right - host.clientWidth
813
+ }, [active, tabs.length])
814
+
769
815
  // 鼠标侧键后退/前进:Logitech 官方默认「后退/前进」= XButton 鼠标事件(button 3/4),不产生键盘事件。
770
816
  // pointerdown 触发导航(preventDefault 后兼容 mousedown 可能不再触发,避免双触发);
771
817
  // mousedown 兜底仅取消浏览器历史导航默认动作(MDN:preventDefault mousedown/pointerdown 可抑制)。
@@ -840,20 +886,25 @@ export function EditorView(props) {
840
886
  return () => { alive = false }
841
887
  }, [monaco, monacoErr])
842
888
 
843
- // 分色主题:Monaco 就绪后注册(幂等)+ 应用;DSH 明暗切换时跟随重刷。
889
+ // 主题:Monaco 就绪后注册现役双套(幂等)+ 应用跟随官方的令牌主题;
890
+ // 官方主题事件(edrv:theme-change,经 ctx.theme/属性观察广播)与系统明暗切换时跟随重刷。
844
891
  React.useEffect(() => {
845
892
  if (!monaco) return
846
893
  registerThemes(monaco)
847
- applyTheme(monaco)
848
- if (typeof window.matchMedia !== 'function') return
849
- const query = window.matchMedia('(prefers-color-scheme: dark)')
850
- const onChange = () => applyTheme(monaco)
851
- if (typeof query.addEventListener === 'function') {
852
- query.addEventListener('change', onChange)
853
- return () => query.removeEventListener('change', onChange)
894
+ const apply = () => applyOfficial(monaco)
895
+ apply()
896
+ window.addEventListener('edrv:theme-change', apply)
897
+ const query = typeof window.matchMedia === 'function' ? window.matchMedia('(prefers-color-scheme: dark)') : null
898
+ if (query) {
899
+ if (typeof query.addEventListener === 'function') query.addEventListener('change', apply)
900
+ else query.addListener(apply)
901
+ }
902
+ return () => {
903
+ window.removeEventListener('edrv:theme-change', apply)
904
+ if (!query) return
905
+ if (typeof query.removeEventListener === 'function') query.removeEventListener('change', apply)
906
+ else query.removeListener(apply)
854
907
  }
855
- query.addListener(onChange)
856
- return () => query.removeListener(onChange)
857
908
  }, [monaco])
858
909
 
859
910
  monacoRef.current = monaco
@@ -1470,7 +1521,7 @@ export function EditorView(props) {
1470
1521
  }).catch((e) => { setStatus('打开失败'); setError('打开异常:' + String(e)) })
1471
1522
  }
1472
1523
 
1473
- const tabsEl = React.createElement('div', { className: 'edrv-tabs', style: { flex: '1 1 auto', minWidth: 0 } },
1524
+ const tabsEl = React.createElement('div', { className: 'edrv-tabs', ref: tabsHostRef, style: { flex: '1 1 auto', minWidth: 0 } },
1474
1525
  tabs.map((t) => React.createElement('div', {
1475
1526
  key: t.path,
1476
1527
  className: 'edrv-tab' + (t.path === active ? ' edrv-tab-active' : ''),
@@ -1,17 +1,16 @@
1
1
  // @ts-nocheck
2
2
  /**
3
- * dsh-vscode-mode client — OfficialSideTab:DSH 官方右侧 Sidebar「文件编辑」Tab 正文包装。
4
- * 双用途:页类型 Tab(edrvEditor)经 navigation.params(openPath/focusDiff)打开;
5
- * file 资源类型 Tab(edrvEditorFile,认领 dsh-resource://file/**)经 navigation.address
6
- * 解码出真实路径并透传 params.line 行号定位。派发既有 edrv:open-editor 事件复用
7
- * EditorView 打开流;按会话 key 保证切会话干净重建。
3
+ * dsh-vscode-mode client — OfficialSideTab:DSH 官方右侧 Sidebar「文件编辑」页签正文包装。
4
+ * 用途:页类型 Tab(edrvEditor)经 navigation.params(openPath/focusDiff/line)打开;
5
+ * 兼作 file 认领转发(ClaimRouter)失败时的兜底正文(就地挂编辑器,旧行为)。
6
+ * 派发既有 edrv:open-editor 事件复用 EditorView 打开流;按会话 key 保证切会话干净重建。
8
7
  * Tab 正文切换后重挂载时按最新导航恢复打开(对齐 better-sidebar 形态的种子行为)。
9
- * 作者 ddj 2026年09月09号
8
+ * 作者 ddj 2026年09月09号 / 2026年09月10号
10
9
  */
11
10
  import React from 'react'
12
11
  import { EditorView } from './EditorView.js'
13
12
  import { setSideEditorMounted } from '../sidebarBridge.js'
14
- import { editorMountEpoch, markEditorMounted, parseOfficialFileAddress, resolveNavOpen } from '../officialSidebar.js'
13
+ import { editorMountEpoch, markEditorMounted, parseOfficialFileAddress, resolveNavLine, resolveNavOpen } from '../officialSidebar.js'
15
14
 
16
15
  /**
17
16
  * 官方侧边栏 Tab 正文组件(keyed slot sidebar.right.pane.tab 装配)。
@@ -71,10 +70,10 @@ export function OfficialSideTab(props) {
71
70
  }))
72
71
  return
73
72
  }
74
- // 页类型 Tab:params 携带打开请求
73
+ // 页类型 Tab:params 携带打开请求(line = 行引用/工具行跳转的行号定位)
75
74
  const request = resolveNavOpen(navigation?.params)
76
75
  window.dispatchEvent(new CustomEvent('edrv:open-editor', {
77
- detail: { path: request.path, focusDiff: request.focusDiff },
76
+ detail: { path: request.path, focusDiff: request.focusDiff, line: resolveNavLine(navigation?.params) },
78
77
  }))
79
78
  })
80
79
 
@@ -0,0 +1,37 @@
1
+ /**
2
+ * 官方 UI 原语虚拟模块的最小类型垫片(@deepseek-ai/dsh-client-ui-primitives)。
3
+ *
4
+ * 该模块由 DSH web 前端的 loader 在运行时提供(磁盘上没有对应包目录,官方 40+ 个
5
+ * 客户端包同样以 require 方式消费),本垫片只声明本插件用到的成员,供 tsc 类型检查;
6
+ * 运行时取值为 loader 注入实例。完整成员清单见官方前端产物导出表。
7
+ * 作者 ddj 2026-09-10
8
+ */
9
+ declare module '@deepseek-ai/dsh-client-ui-primitives' {
10
+ /** 图标组件通用 props(官方 Icon* 组件与 FileTypeIcon 共用形状)。 */
11
+ export interface EdrvIconProps {
12
+ /** 图标边长(px);省略时用图标自带尺寸。 */
13
+ size?: number
14
+ className?: string
15
+ }
16
+
17
+ /** 按文件名(或扩展名)分类的官方文件类型判别符(未知类型返回 'other')。 */
18
+ export function classifyFileType(name: string): string
19
+
20
+ /** 官方文件类型图标:按 classifyFileType 的 kind 渲染(跟随官方主题配色)。 */
21
+ export const FileTypeIcon: (props: EdrvIconProps & { kind: string }) => unknown
22
+
23
+ /** 目录闭合图标(官方文件树同款)。 */
24
+ export const IconFolderClose16: (props: EdrvIconProps) => unknown
25
+ /** 目录展开图标(官方文件树同款)。 */
26
+ export const IconFolderOpen16: (props: EdrvIconProps) => unknown
27
+ /** 目录轮廓图标(活动栏「文件管理」)。 */
28
+ export const IconFolderOpenOutline16: (props: EdrvIconProps) => unknown
29
+ /** 刷新图标(面板工具条)。 */
30
+ export const IconRefreshOutline16: (props: EdrvIconProps) => unknown
31
+ /** 搜索图标(活动栏「搜索」)。 */
32
+ export const IconSearchOutline16: (props: EdrvIconProps) => unknown
33
+ /** 列表+笔图标(活动栏「规则」)。 */
34
+ export const IconListPenOutline16: (props: EdrvIconProps) => unknown
35
+ /** 代码图标(活动栏「大纲」)。 */
36
+ export const IconCodeOutline16: (props: EdrvIconProps) => unknown
37
+ }
@@ -14,6 +14,9 @@ export const KEYBINDING_DEFAULTS: Record<string, string> = {
14
14
  'edrv.searchInFiles': 'Ctrl+Shift+F',
15
15
  'edrv.navigateBack': 'Alt+ArrowLeft|Ctrl+Alt+-',
16
16
  'edrv.navigateForward': 'Alt+ArrowRight|Ctrl+Shift+-',
17
+ // 页签循环:主候选避开浏览器保留键(Ctrl+Tab / Ctrl+PgUp/PgDn 会被浏览器截获)
18
+ 'edrv.nextTab': 'Ctrl+Alt+ArrowRight|Ctrl+PageDown',
19
+ 'edrv.prevTab': 'Ctrl+Alt+ArrowLeft|Ctrl+PageUp',
17
20
  }
18
21
 
19
22
  /**