dsh-vscode-workbench 0.2.1 → 0.2.4

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/lib/client.js CHANGED
@@ -46,6 +46,7 @@ window.__ModuleLoader__.load({
46
46
  //#endregion
47
47
  let react = require("react");
48
48
  let react_jsx_runtime = require("react/jsx-runtime");
49
+ let react_dom = require("react-dom");
49
50
  //#region src/client/service.ts
50
51
  const SNAPSHOT_KEY = "dvw:workbench:snapshot:v1";
51
52
  const DEFAULT_SNAPSHOT = {
@@ -14243,6 +14244,36 @@ Please report this to https://github.com/markedjs/marked.`, e) {
14243
14244
  "scrollbarSlider.hoverBackground": "#646464b3",
14244
14245
  "scrollbarSlider.activeBackground": "#bfbfbf66"
14245
14246
  };
14247
+ /** Eye-care palette: the editor shares the workbench's warm yellow surface. */
14248
+ const EYE_THEME = "dvw-eyecare";
14249
+ const EYE_COLORS = {
14250
+ "editor.background": "#f7ebc8",
14251
+ "editor.foreground": "#3b3324",
14252
+ "editorLineNumber.foreground": "#92856a",
14253
+ "editorLineNumber.activeForeground": "#5c4a2a",
14254
+ "editor.selectionBackground": "#e6d294",
14255
+ "editor.inactiveSelectionBackground": "#ecdcae",
14256
+ "editor.lineHighlightBackground": "#efe1b4",
14257
+ "editorCursor.foreground": "#6b5320",
14258
+ "editorWidget.background": "#f7ebc8",
14259
+ "editorWidget.border": "#e0cf9f",
14260
+ "editorSuggestWidget.background": "#f7ebc8",
14261
+ "editorSuggestWidget.border": "#e0cf9f",
14262
+ "editorSuggestWidget.selectedBackground": "#f0e0ae",
14263
+ "editorHoverWidget.background": "#f7ebc8",
14264
+ "editorHoverWidget.border": "#e0cf9f",
14265
+ "editorGutter.background": "#f7ebc8",
14266
+ "diffEditor.insertedTextBackground": "#b7d7a8aa",
14267
+ "diffEditor.removedTextBackground": "#e8b4ad88",
14268
+ "diffEditor.border": "#e0cf9f",
14269
+ "diffEditor.diagonalFill": "#eadcb6",
14270
+ "scrollbarSlider.background": "#92856a55",
14271
+ "scrollbarSlider.hoverBackground": "#92856a88",
14272
+ "scrollbarSlider.activeBackground": "#5c4a2a66"
14273
+ };
14274
+ function monacoThemeFor(theme) {
14275
+ return theme === "dark" ? DARK_THEME : theme === "eyecare" ? EYE_THEME : "vs";
14276
+ }
14246
14277
  function defineWorkbenchThemes(monaco) {
14247
14278
  monaco.editor.defineTheme(DARK_THEME, {
14248
14279
  base: "vs-dark",
@@ -14250,6 +14281,12 @@ Please report this to https://github.com/markedjs/marked.`, e) {
14250
14281
  rules: DARK_RULES,
14251
14282
  colors: DARK_COLORS
14252
14283
  });
14284
+ monaco.editor.defineTheme(EYE_THEME, {
14285
+ base: "vs",
14286
+ inherit: true,
14287
+ rules: [],
14288
+ colors: EYE_COLORS
14289
+ });
14253
14290
  }
14254
14291
  /**
14255
14292
  * Bootstrap source for Monaco's AMD web workers. Workers resolve module paths against their own
@@ -14309,7 +14346,8 @@ Please report this to https://github.com/markedjs/marked.`, e) {
14309
14346
  automaticLayout: true,
14310
14347
  readOnly: true,
14311
14348
  renderSideBySide: props.mode === "split",
14312
- theme: props.theme === "dark" ? DARK_THEME : "vs",
14349
+ useInlineViewWhenSpaceIsLimited: false,
14350
+ theme: monacoThemeFor(props.theme),
14313
14351
  fontSize: props.fontSize ?? 14,
14314
14352
  ...WORKBENCH_EDITOR_CHROME,
14315
14353
  originalEditable: false,
@@ -14337,13 +14375,17 @@ Please report this to https://github.com/markedjs/marked.`, e) {
14337
14375
  if (value.modified.getValue() !== props.modified) value.modified.setValue(props.modified);
14338
14376
  }, [props.original, props.modified]);
14339
14377
  (0, react.useEffect)(() => {
14340
- editor.current?.updateOptions({ renderSideBySide: props.mode === "split" });
14378
+ const value = editor.current;
14379
+ if (value === void 0) return;
14380
+ value.updateOptions({ renderSideBySide: props.mode === "split" });
14381
+ const frame = requestAnimationFrame(() => value.layout());
14382
+ return () => cancelAnimationFrame(frame);
14341
14383
  }, [props.mode]);
14342
14384
  (0, react.useEffect)(() => {
14343
14385
  editor.current?.updateOptions({ fontSize: props.fontSize ?? 14 });
14344
14386
  }, [props.fontSize]);
14345
14387
  (0, react.useEffect)(() => {
14346
- if (window.monaco !== void 0) window.monaco.editor.setTheme(props.theme === "dark" ? DARK_THEME : "vs");
14388
+ if (window.monaco !== void 0) window.monaco.editor.setTheme(monacoThemeFor(props.theme));
14347
14389
  }, [props.theme]);
14348
14390
  return error === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
14349
14391
  className: "dvw-diff dvw-monaco-diff",
@@ -14454,7 +14496,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
14454
14496
  const instance = monaco.editor.create(root.current, {
14455
14497
  model: null,
14456
14498
  automaticLayout: true,
14457
- theme: props.theme === "dark" ? DARK_THEME : "vs",
14499
+ theme: monacoThemeFor(props.theme),
14458
14500
  fontSize: props.fontSize ?? 14,
14459
14501
  ...WORKBENCH_EDITOR_CHROME,
14460
14502
  wordWrap: "off"
@@ -14523,7 +14565,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
14523
14565
  if (model !== null && model !== void 0 && model.getValue() !== props.value) model.setValue(props.value);
14524
14566
  }, [props.value]);
14525
14567
  (0, react.useEffect)(() => {
14526
- if (window.monaco !== void 0) window.monaco.editor.setTheme(props.theme === "dark" ? DARK_THEME : "vs");
14568
+ if (window.monaco !== void 0) window.monaco.editor.setTheme(monacoThemeFor(props.theme));
14527
14569
  }, [props.theme]);
14528
14570
  (0, react.useEffect)(() => {
14529
14571
  editor.current?.updateOptions({ fontSize: props.fontSize ?? 14 });
@@ -14658,16 +14700,26 @@ Please report this to https://github.com/markedjs/marked.`, e) {
14658
14700
  function toggleActivityHidden(hidden, id) {
14659
14701
  return hidden.includes(id) ? hidden.filter((value) => value !== id) : [...hidden, id];
14660
14702
  }
14661
- /** VS Code-style activity bar: pointer drag with a floating ghost and live reordering, right-click hide. */
14703
+ /**
14704
+ * VS Code-style activity bar: every view can be dragged into a new slot while `fixed` actions stay pinned on
14705
+ * top and `bottom` actions stay pinned at the foot. Reordering is computed from pointer position so it keeps
14706
+ * working when the DOM shifts under a fast drag.
14707
+ */
14662
14708
  function ActivityBar({ views, fixed, bottom = [], order, hidden, onOrderChange, onHiddenChange }) {
14663
14709
  const [menu, setMenu] = (0, react.useState)();
14664
14710
  const drag = (0, react.useRef)();
14711
+ const draggingRef = (0, react.useRef)(false);
14665
14712
  const nodes = (0, react.useRef)(/* @__PURE__ */ new Map());
14666
14713
  const flip = (0, react.useRef)();
14667
- const suppressClick = (0, react.useRef)(false);
14714
+ const didDrag = (0, react.useRef)(false);
14668
14715
  const [draggingId, setDraggingId] = (0, react.useState)();
14669
14716
  const [ghost, setGhost] = (0, react.useState)();
14670
14717
  const [preview, setPreview] = (0, react.useState)();
14718
+ const previewRef = (0, react.useRef)();
14719
+ const orderRef = (0, react.useRef)(order);
14720
+ const visibleRef = (0, react.useRef)([]);
14721
+ previewRef.current = preview;
14722
+ orderRef.current = order;
14671
14723
  (0, react.useEffect)(() => {
14672
14724
  if (menu === void 0) return;
14673
14725
  const close = () => setMenu(void 0);
@@ -14685,6 +14737,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
14685
14737
  const before = flip.current;
14686
14738
  flip.current = void 0;
14687
14739
  if (before === void 0) return;
14740
+ if (draggingRef.current) return;
14688
14741
  for (const [id, element] of nodes.current) {
14689
14742
  const previous = before.get(id);
14690
14743
  if (previous === void 0) continue;
@@ -14697,69 +14750,97 @@ Please report this to https://github.com/markedjs/marked.`, e) {
14697
14750
  }
14698
14751
  });
14699
14752
  const visible = views.filter((view) => !hidden.includes(view.id));
14700
- const currentOrder = preview ?? order;
14701
- const ordered = currentOrder.flatMap((id) => visible.filter((view) => view.id === id));
14753
+ visibleRef.current = visible;
14754
+ const ordered = (preview ?? order).flatMap((id) => visible.filter((view) => view.id === id));
14702
14755
  const toggled = (id) => onHiddenChange(toggleActivityHidden(hidden, id));
14703
14756
  const target = menu?.target === void 0 ? void 0 : views.find((view) => view.id === menu.target);
14704
14757
  const capturePositions = () => {
14705
14758
  flip.current = new Map([...nodes.current].map(([id, element]) => [id, element.getBoundingClientRect().top]));
14706
14759
  };
14707
- const beginDrag = (event, id) => {
14708
- if (event.button !== 0) return;
14709
- drag.current = {
14710
- id,
14711
- x: event.clientX,
14712
- y: event.clientY,
14713
- active: false
14714
- };
14715
- event.currentTarget.setPointerCapture?.(event.pointerId);
14716
- };
14717
- const moveDrag = (event, id) => {
14760
+ const moveDrag = (clientX, clientY) => {
14718
14761
  const state = drag.current;
14719
- if (state === void 0 || state.id !== id) return;
14762
+ if (state === void 0) return;
14720
14763
  if (!state.active) {
14721
- if (Math.abs(event.clientX - state.x) + Math.abs(event.clientY - state.y) < 5) return;
14764
+ if (Math.abs(clientX - state.x) + Math.abs(clientY - state.y) < 5) return;
14722
14765
  state.active = true;
14723
- setDraggingId(id);
14766
+ draggingRef.current = true;
14767
+ setDraggingId(state.id);
14724
14768
  }
14725
14769
  setGhost({
14726
- x: event.clientX,
14727
- y: event.clientY
14770
+ x: clientX,
14771
+ y: clientY
14728
14772
  });
14729
- const element = document.elementFromPoint(event.clientX, event.clientY)?.closest("[data-act-id]");
14730
- if (element === null || element === void 0) return;
14731
- const targetId = element.dataset.actId;
14732
- if (targetId === void 0 || targetId === id || !visible.some((view) => view.id === targetId)) return;
14733
- const rect = element.getBoundingClientRect();
14734
- const ids = currentOrder.filter((value) => visible.some((view) => view.id === value));
14735
- const index = ids.indexOf(targetId);
14736
- if (index < 0) return;
14737
- const next = moveActivity(currentOrder, id, event.clientY > rect.top + rect.height / 2 ? ids[index + 1] : targetId);
14738
- if (next.join("|") === currentOrder.join("|")) return;
14773
+ const base = previewRef.current ?? orderRef.current;
14774
+ const visibleIds = new Set(visibleRef.current.map((view) => view.id));
14775
+ const slots = base.filter((id) => visibleIds.has(id) && id !== state.id);
14776
+ let index = 0;
14777
+ for (const id of slots) {
14778
+ const element = nodes.current.get(id);
14779
+ if (element === void 0) continue;
14780
+ const rect = element.getBoundingClientRect();
14781
+ if (clientY > rect.top + rect.height / 2) index += 1;
14782
+ }
14783
+ const next = moveActivity(base, state.id, slots[index]);
14784
+ if (next.join("|") === base.join("|")) return;
14739
14785
  capturePositions();
14786
+ previewRef.current = next;
14740
14787
  setPreview(next);
14741
14788
  };
14742
- const endDrag = (event) => {
14789
+ const endDrag = () => {
14743
14790
  const state = drag.current;
14744
14791
  drag.current = void 0;
14745
14792
  if (state?.active) {
14746
- suppressClick.current = true;
14747
- window.setTimeout(() => {
14748
- suppressClick.current = false;
14749
- }, 0);
14750
- if (preview !== void 0) onOrderChange(preview);
14793
+ didDrag.current = true;
14794
+ const next = previewRef.current;
14795
+ if (next !== void 0) onOrderChange(next);
14751
14796
  }
14752
- event.currentTarget.releasePointerCapture?.(event.pointerId);
14797
+ draggingRef.current = false;
14798
+ previewRef.current = void 0;
14753
14799
  setDraggingId(void 0);
14754
14800
  setGhost(void 0);
14755
14801
  setPreview(void 0);
14756
14802
  };
14757
14803
  const cancelDrag = () => {
14758
14804
  drag.current = void 0;
14805
+ draggingRef.current = false;
14806
+ previewRef.current = void 0;
14759
14807
  setDraggingId(void 0);
14760
14808
  setGhost(void 0);
14761
14809
  setPreview(void 0);
14762
14810
  };
14811
+ const handlers = (0, react.useRef)({
14812
+ moveDrag,
14813
+ endDrag,
14814
+ cancelDrag
14815
+ });
14816
+ handlers.current = {
14817
+ moveDrag,
14818
+ endDrag,
14819
+ cancelDrag
14820
+ };
14821
+ (0, react.useEffect)(() => {
14822
+ const move = (event) => handlers.current.moveDrag(event.clientX, event.clientY);
14823
+ const up = () => handlers.current.endDrag();
14824
+ const cancel = () => handlers.current.cancelDrag();
14825
+ window.addEventListener("pointermove", move);
14826
+ window.addEventListener("pointerup", up);
14827
+ window.addEventListener("pointercancel", cancel);
14828
+ return () => {
14829
+ window.removeEventListener("pointermove", move);
14830
+ window.removeEventListener("pointerup", up);
14831
+ window.removeEventListener("pointercancel", cancel);
14832
+ };
14833
+ }, []);
14834
+ const beginDrag = (event, id) => {
14835
+ if (event.button !== 0) return;
14836
+ didDrag.current = false;
14837
+ drag.current = {
14838
+ id,
14839
+ x: event.clientX,
14840
+ y: event.clientY,
14841
+ active: false
14842
+ };
14843
+ };
14763
14844
  const renderView = (view) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
14764
14845
  ref: (element) => {
14765
14846
  if (element === null) nodes.current.delete(view.id);
@@ -14772,11 +14853,12 @@ Please report this to https://github.com/markedjs/marked.`, e) {
14772
14853
  disabled: view.disabled,
14773
14854
  title: view.label,
14774
14855
  onPointerDown: (event) => beginDrag(event, view.id),
14775
- onPointerMove: (event) => moveDrag(event, view.id),
14776
- onPointerUp: (event) => endDrag(event),
14777
- onPointerCancel: cancelDrag,
14778
14856
  onClick: () => {
14779
- if (!suppressClick.current) view.onActivate();
14857
+ if (didDrag.current) {
14858
+ didDrag.current = false;
14859
+ return;
14860
+ }
14861
+ view.onActivate();
14780
14862
  },
14781
14863
  onContextMenu: (event) => {
14782
14864
  event.preventDefault();
@@ -14800,10 +14882,6 @@ Please report this to https://github.com/markedjs/marked.`, e) {
14800
14882
  });
14801
14883
  },
14802
14884
  children: [
14803
- ordered.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
14804
- className: "dvw-activity-empty",
14805
- "aria-hidden": "true"
14806
- }) : ordered.map(renderView),
14807
14885
  fixed.map((view) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
14808
14886
  className: "dvw-act",
14809
14887
  "data-act-id": view.id,
@@ -14813,6 +14891,10 @@ Please report this to https://github.com/markedjs/marked.`, e) {
14813
14891
  onClick: view.onActivate,
14814
14892
  children: view.icon
14815
14893
  }, view.id)),
14894
+ ordered.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
14895
+ className: "dvw-activity-empty",
14896
+ "aria-hidden": "true"
14897
+ }) : ordered.map(renderView),
14816
14898
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
14817
14899
  className: "dvw-activity-bottom",
14818
14900
  children: bottom.map((view) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
@@ -14887,7 +14969,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
14887
14969
  //#endregion
14888
14970
  //#region src/client/WorkspaceSwitcher.tsx
14889
14971
  /** Centered switcher: existing workspaces, their sessions, and a new-workspace action. */
14890
- function WorkspaceSwitcher({ choices, activeSessionId, unavailable, busy, error, onCreate, onSwitch, onOpenWorkspace, onClose }) {
14972
+ function WorkspaceSwitcher({ choices, activeSessionId, unavailable, busy, error, theme, onCreate, onSwitch, onOpenWorkspace, onClose }) {
14891
14973
  const current = choices.find((workspace) => workspace.sessions.some((session) => session.id === activeSessionId))?.id;
14892
14974
  const [expanded, setExpanded] = (0, react.useState)(current ?? choices[0]?.id);
14893
14975
  (0, react.useEffect)(() => {
@@ -14897,98 +14979,102 @@ Please report this to https://github.com/markedjs/marked.`, e) {
14897
14979
  window.addEventListener("keydown", escape);
14898
14980
  return () => window.removeEventListener("keydown", escape);
14899
14981
  }, [onClose]);
14900
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
14901
- className: "dvw-confirm-backdrop",
14902
- role: "presentation",
14903
- onMouseDown: onClose,
14904
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
14905
- className: "dvw-workspace-switcher",
14906
- role: "dialog",
14907
- "aria-modal": "true",
14908
- "aria-label": "打开工作区",
14909
- onMouseDown: (event) => event.stopPropagation(),
14910
- children: [
14911
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", { children: "打开工作区" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
14912
- className: "dvw-icon",
14913
- title: "关闭",
14914
- onClick: onClose,
14915
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { name: "close" })
14916
- })] }),
14917
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
14918
- className: "dvw-workspace-list",
14919
- children: unavailable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
14920
- className: "dvw-workspace-empty",
14921
- children: "无法读取 DSH 的工作区列表,请重启 DSH 后再试。"
14922
- }) : choices.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
14923
- className: "dvw-workspace-empty",
14924
- children: "还没有工作区,先新建一个。"
14925
- }) : choices.map((workspace) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
14926
- className: "dvw-workspace-group",
14927
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
14928
- className: "dvw-workspace-row",
14929
- "data-expanded": expanded === workspace.id,
14930
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
14931
- className: "dvw-workspace-toggle",
14932
- "aria-expanded": expanded === workspace.id,
14933
- onClick: () => setExpanded((value) => value === workspace.id ? void 0 : workspace.id),
14934
- children: [
14935
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { name: "folder-opened" }),
14936
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
14937
- className: "dvw-workspace-title",
14938
- children: workspace.title
14939
- }),
14940
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
14941
- className: "dvw-workspace-path",
14942
- children: workspace.path
14943
- }),
14944
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { name: expanded === workspace.id ? "chevron-down" : "chevron-right" })
14945
- ]
14946
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
14947
- className: "dvw-icon dvw-workspace-enter",
14948
- title: "进入此工作区",
14949
- onClick: () => onOpenWorkspace(workspace.id),
14950
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { name: "arrow-right" })
14982
+ return (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
14983
+ className: "dvw-overlay dvw-workspace-layer",
14984
+ "data-dvw-theme": theme,
14985
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
14986
+ className: "dvw-workspace-backdrop",
14987
+ role: "presentation",
14988
+ onMouseDown: onClose,
14989
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
14990
+ className: "dvw-workspace-switcher",
14991
+ role: "dialog",
14992
+ "aria-modal": "true",
14993
+ "aria-label": "打开工作区",
14994
+ onMouseDown: (event) => event.stopPropagation(),
14995
+ children: [
14996
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", { children: "打开工作区" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
14997
+ className: "dvw-icon",
14998
+ title: "关闭",
14999
+ onClick: onClose,
15000
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { name: "close" })
15001
+ })] }),
15002
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
15003
+ className: "dvw-workspace-list",
15004
+ children: unavailable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
15005
+ className: "dvw-workspace-empty",
15006
+ children: "无法读取 DSH 的工作区列表,请重启 DSH 后再试。"
15007
+ }) : choices.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
15008
+ className: "dvw-workspace-empty",
15009
+ children: "还没有工作区,先新建一个。"
15010
+ }) : choices.map((workspace) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
15011
+ className: "dvw-workspace-group",
15012
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
15013
+ className: "dvw-workspace-row",
15014
+ "data-expanded": expanded === workspace.id,
15015
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
15016
+ className: "dvw-workspace-toggle",
15017
+ "aria-expanded": expanded === workspace.id,
15018
+ onClick: () => setExpanded((value) => value === workspace.id ? void 0 : workspace.id),
15019
+ children: [
15020
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { name: "folder-opened" }),
15021
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
15022
+ className: "dvw-workspace-title",
15023
+ children: workspace.title
15024
+ }),
15025
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
15026
+ className: "dvw-workspace-path",
15027
+ children: workspace.path
15028
+ }),
15029
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { name: expanded === workspace.id ? "chevron-down" : "chevron-right" })
15030
+ ]
15031
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
15032
+ className: "dvw-icon dvw-workspace-enter",
15033
+ title: "进入此工作区",
15034
+ onClick: () => onOpenWorkspace(workspace.id),
15035
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { name: "arrow-right" })
15036
+ })]
15037
+ }), expanded === workspace.id && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
15038
+ className: "dvw-workspace-sessions",
15039
+ children: workspace.sessions.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
15040
+ className: "dvw-workspace-empty",
15041
+ children: "此工作区还没有会话"
15042
+ }) : workspace.sessions.map((session) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
15043
+ className: "dvw-workspace-session",
15044
+ "data-active": session.id === activeSessionId,
15045
+ onClick: () => onSwitch(session.id),
15046
+ children: [
15047
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { name: "comment-discussion" }),
15048
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
15049
+ className: "dvw-workspace-session-title",
15050
+ children: session.title
15051
+ }),
15052
+ session.id === activeSessionId && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
15053
+ className: "dvw-workspace-current",
15054
+ children: "当前"
15055
+ })
15056
+ ]
15057
+ }, session.id))
14951
15058
  })]
14952
- }), expanded === workspace.id && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
14953
- className: "dvw-workspace-sessions",
14954
- children: workspace.sessions.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
14955
- className: "dvw-workspace-empty",
14956
- children: "此工作区还没有会话"
14957
- }) : workspace.sessions.map((session) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
14958
- className: "dvw-workspace-session",
14959
- "data-active": session.id === activeSessionId,
14960
- onClick: () => onSwitch(session.id),
14961
- children: [
14962
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { name: "comment-discussion" }),
14963
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
14964
- className: "dvw-workspace-session-title",
14965
- children: session.title
14966
- }),
14967
- session.id === activeSessionId && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
14968
- className: "dvw-workspace-current",
14969
- children: "当前"
14970
- })
14971
- ]
14972
- }, session.id))
14973
- })]
14974
- }, workspace.id))
14975
- }),
14976
- error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
14977
- className: "dvw-workspace-error",
14978
- children: error
14979
- }),
14980
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("footer", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
14981
- className: "dvw-primary-button",
14982
- disabled: busy,
14983
- onClick: onCreate,
14984
- children: busy ? "正在打开…" : "新建工作区…"
14985
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
14986
- onClick: onClose,
14987
- children: "取消"
14988
- })] })
14989
- ]
15059
+ }, workspace.id))
15060
+ }),
15061
+ error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
15062
+ className: "dvw-workspace-error",
15063
+ children: error
15064
+ }),
15065
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("footer", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
15066
+ className: "dvw-primary-button",
15067
+ disabled: busy,
15068
+ onClick: onCreate,
15069
+ children: busy ? "正在打开…" : "新建工作区…"
15070
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
15071
+ onClick: onClose,
15072
+ children: "取消"
15073
+ })] })
15074
+ ]
15075
+ })
14990
15076
  })
14991
- });
15077
+ }), document.body);
14992
15078
  }
14993
15079
  //#endregion
14994
15080
  //#region src/client/lsp.ts
@@ -49680,6 +49766,9 @@ section.${c}>footer { z-index: 1; }
49680
49766
  return epoch === this.epoch;
49681
49767
  }
49682
49768
  };
49769
+ //#endregion
49770
+ //#region src/client/Workbench.tsx
49771
+ const MARKDOWN_DEFAULT_VIEW_KEY = "dvw:markdown-default-view";
49683
49772
  /** Keep persisted or dragged widths inside the range the DSH composer can lay out cleanly. */
49684
49773
  function clampChatWidth(width) {
49685
49774
  if (!Number.isFinite(width)) return 440;
@@ -49757,6 +49846,14 @@ section.${c}>footer { z-index: 1; }
49757
49846
  }
49758
49847
  });
49759
49848
  }
49849
+ /** Read the saved Markdown default without depending on browser storage during unit tests. */
49850
+ function markdownDefaultView() {
49851
+ try {
49852
+ return localStorage.getItem("dvw:markdown-default-view") === "source" ? "source" : "preview";
49853
+ } catch {
49854
+ return "preview";
49855
+ }
49856
+ }
49760
49857
  function unloadedTab(path) {
49761
49858
  return {
49762
49859
  instance: Symbol(path),
@@ -49769,7 +49866,7 @@ section.${c}>footer { z-index: 1; }
49769
49866
  tooLarge: false,
49770
49867
  dirty: false,
49771
49868
  loaded: false,
49772
- preview: /\.md$/i.test(path)
49869
+ preview: /\.md$/i.test(path) ? markdownDefaultView() === "preview" : void 0
49773
49870
  };
49774
49871
  }
49775
49872
  function WorkbenchTitlebar({ name }) {
@@ -50938,6 +51035,8 @@ section.${c}>footer { z-index: 1; }
50938
51035
  const [branches, setBranches] = (0, react.useState)([]);
50939
51036
  const [newBranch, setNewBranch] = (0, react.useState)("");
50940
51037
  const [branchError, setBranchError] = (0, react.useState)();
51038
+ const [generating, setGenerating] = (0, react.useState)(false);
51039
+ const [commitMenu, setCommitMenu] = (0, react.useState)(false);
50941
51040
  const refresh = (0, react.useCallback)(() => {
50942
51041
  Promise.all([api("git.status", { sessionId: props.sessionId }), api("git.action", {
50943
51042
  sessionId: props.sessionId,
@@ -50994,6 +51093,19 @@ section.${c}>footer { z-index: 1; }
50994
51093
  window.removeEventListener("keydown", escape);
50995
51094
  };
50996
51095
  }, [branchMenu]);
51096
+ (0, react.useEffect)(() => {
51097
+ if (!commitMenu) return;
51098
+ const close = () => setCommitMenu(false);
51099
+ const escape = (event) => {
51100
+ if (event.key === "Escape") close();
51101
+ };
51102
+ window.addEventListener("pointerdown", close);
51103
+ window.addEventListener("keydown", escape);
51104
+ return () => {
51105
+ window.removeEventListener("pointerdown", close);
51106
+ window.removeEventListener("keydown", escape);
51107
+ };
51108
+ }, [commitMenu]);
50997
51109
  const openBranchMenu = async () => {
50998
51110
  if (branchMenu) {
50999
51111
  setBranchMenu(false);
@@ -51090,6 +51202,23 @@ section.${c}>footer { z-index: 1; }
51090
51202
  setBusy(false);
51091
51203
  }
51092
51204
  };
51205
+ const generateMessage = async () => {
51206
+ if (generating) return;
51207
+ setGenerating(true);
51208
+ setError(void 0);
51209
+ try {
51210
+ const result = await api("git.commitMessage", {
51211
+ sessionId: props.sessionId,
51212
+ detail: props.preferences.detail,
51213
+ language: props.preferences.language
51214
+ });
51215
+ setMessage(result.message);
51216
+ } catch (error) {
51217
+ setError(error instanceof ApiError ? error.message : String(error));
51218
+ } finally {
51219
+ setGenerating(false);
51220
+ }
51221
+ };
51093
51222
  const staged = status?.changes.filter((change) => change.index !== "." && change.index !== "?") ?? [];
51094
51223
  const changed = status?.changes.filter((change) => change.worktree !== "." || change.untracked) ?? [];
51095
51224
  const renderChange = (change, group) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -51223,19 +51352,89 @@ section.${c}>footer { z-index: 1; }
51223
51352
  }),
51224
51353
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
51225
51354
  className: "dvw-commit",
51226
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
51227
- className: "dvw-input",
51228
- value: message,
51229
- onChange: (event) => setMessage(event.target.value),
51230
- onKeyDown: (event) => {
51231
- if (event.ctrlKey && event.key === "Enter" && message.trim()) action("commit", void 0, message).then(() => setMessage(""));
51232
- },
51233
- placeholder: `消息 (Ctrl+Enter 在“${status.branch}”提交)`
51234
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
51235
- className: "dvw-commit-button",
51236
- disabled: busy || !message.trim(),
51237
- onClick: () => void action("commit", void 0, message).then(() => setMessage("")),
51238
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { name: "check" }), " 提交"]
51355
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
51356
+ className: "dvw-commit-box",
51357
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
51358
+ className: "dvw-textarea dvw-commit-input",
51359
+ rows: 1,
51360
+ value: message,
51361
+ onChange: (event) => setMessage(event.target.value),
51362
+ onKeyDown: (event) => {
51363
+ if ((event.ctrlKey || event.metaKey) && event.key === "Enter" && message.trim()) action("commit", void 0, message).then(() => setMessage(""));
51364
+ },
51365
+ placeholder: `消息 (${isMacPlatform() ? "⌘" : "Ctrl+"}Enter 在“${status.branch}”提交)`
51366
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
51367
+ className: "dvw-commit-ai",
51368
+ disabled: busy || generating || status.changes.length === 0,
51369
+ title: generating ? "正在生成提交信息" : "根据当前更改生成提交信息",
51370
+ "aria-label": "生成提交信息",
51371
+ onClick: () => void generateMessage(),
51372
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { name: "sparkle" })
51373
+ })]
51374
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
51375
+ className: "dvw-commit-actions",
51376
+ children: [
51377
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
51378
+ className: "dvw-commit-button",
51379
+ disabled: busy || !message.trim() || status.changes.length === 0,
51380
+ title: "提交暂存的更改",
51381
+ onClick: () => void action("commit", void 0, message).then(() => setMessage("")),
51382
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { name: "check" }), " 提交"]
51383
+ }),
51384
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
51385
+ className: "dvw-commit-more",
51386
+ disabled: busy || !message.trim() || status.changes.length === 0,
51387
+ "aria-haspopup": "menu",
51388
+ "aria-expanded": commitMenu,
51389
+ title: "更多提交操作",
51390
+ "aria-label": "更多提交操作",
51391
+ onClick: () => setCommitMenu((value) => !value),
51392
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { name: "chevron-down" })
51393
+ }),
51394
+ commitMenu && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
51395
+ className: "dvw-commit-menu",
51396
+ role: "menu",
51397
+ onPointerDown: (event) => event.stopPropagation(),
51398
+ children: [
51399
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
51400
+ role: "menuitem",
51401
+ onClick: () => {
51402
+ setCommitMenu(false);
51403
+ action("commit", void 0, message).then(() => setMessage(""));
51404
+ },
51405
+ children: "提交"
51406
+ }),
51407
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
51408
+ role: "menuitem",
51409
+ onClick: () => {
51410
+ setCommitMenu(false);
51411
+ action("commit.amend", void 0, message).then(() => setMessage(""));
51412
+ },
51413
+ children: "提交(修改)"
51414
+ }),
51415
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
51416
+ className: "dvw-commit-menu-sep",
51417
+ role: "separator"
51418
+ }),
51419
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
51420
+ role: "menuitem",
51421
+ onClick: () => {
51422
+ setCommitMenu(false);
51423
+ action("commit", void 0, message).then(() => action("push")).then(() => setMessage(""));
51424
+ },
51425
+ children: "提交和推送"
51426
+ }),
51427
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
51428
+ role: "menuitem",
51429
+ onClick: () => {
51430
+ setCommitMenu(false);
51431
+ action("commit", void 0, message).then(() => action("sync")).then(() => setMessage(""));
51432
+ },
51433
+ children: "提交和同步"
51434
+ })
51435
+ ]
51436
+ })
51437
+ ]
51239
51438
  })]
51240
51439
  }),
51241
51440
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -51398,6 +51597,7 @@ section.${c}>footer { z-index: 1; }
51398
51597
  const [tabMenu, setTabMenu] = (0, react.useState)();
51399
51598
  const tabsRef = (0, react.useRef)(tabs);
51400
51599
  tabsRef.current = tabs;
51600
+ const [settingsSection, setSettingsSection] = (0, react.useState)("appearance");
51401
51601
  const tabListRef = (0, react.useRef)(null);
51402
51602
  const workspaceRequests = (0, react.useRef)(new WorkspaceRequestScope());
51403
51603
  const loadedWorkspaceCwd = (0, react.useRef)();
@@ -51405,10 +51605,26 @@ section.${c}>footer { z-index: 1; }
51405
51605
  const dshDark = useDshDarkTheme();
51406
51606
  const [theme, setTheme] = (0, react.useState)(() => {
51407
51607
  const saved = localStorage.getItem("dvw:theme");
51408
- return saved === "dark" || saved === "light" ? saved : "dsh";
51608
+ return saved === "dark" || saved === "light" || saved === "white" || saved === "eyecare" ? saved : "dsh";
51609
+ });
51610
+ const [markdownView, setMarkdownView] = (0, react.useState)(() => markdownDefaultView());
51611
+ const [commitDetail, setCommitDetail] = (0, react.useState)(() => {
51612
+ const saved = localStorage.getItem("dvw:commit-detail");
51613
+ return saved === "concise" || saved === "detailed" ? saved : "standard";
51614
+ });
51615
+ const [commitLanguage, setCommitLanguage] = (0, react.useState)(() => {
51616
+ const saved = localStorage.getItem("dvw:commit-language");
51617
+ return saved === "zh" || saved === "en" ? saved : "auto";
51409
51618
  });
51410
51619
  const colorScheme = theme === "dsh" ? dshDark ? "dark" : "light" : theme;
51620
+ const commitPreferences = (0, react.useMemo)(() => ({
51621
+ detail: commitDetail,
51622
+ language: commitLanguage
51623
+ }), [commitDetail, commitLanguage]);
51411
51624
  (0, react.useEffect)(() => localStorage.setItem("dvw:theme", theme), [theme]);
51625
+ (0, react.useEffect)(() => localStorage.setItem(MARKDOWN_DEFAULT_VIEW_KEY, markdownView), [markdownView]);
51626
+ (0, react.useEffect)(() => localStorage.setItem("dvw:commit-detail", commitDetail), [commitDetail]);
51627
+ (0, react.useEffect)(() => localStorage.setItem("dvw:commit-language", commitLanguage), [commitLanguage]);
51412
51628
  (0, react.useEffect)(() => {
51413
51629
  if (!snapshot.visible || theme === "dsh") return;
51414
51630
  const body = document.body;
@@ -51416,7 +51632,7 @@ section.${c}>footer { z-index: 1; }
51416
51632
  const wasDark = body.hasAttribute("data-ds-dark-theme");
51417
51633
  const previousColorScheme = root.style.colorScheme;
51418
51634
  body.toggleAttribute("data-ds-dark-theme", theme === "dark");
51419
- root.style.colorScheme = theme;
51635
+ root.style.colorScheme = theme === "dark" ? "dark" : "light";
51420
51636
  return () => {
51421
51637
  body.toggleAttribute("data-ds-dark-theme", wasDark);
51422
51638
  if (previousColorScheme === "") root.style.removeProperty("color-scheme");
@@ -51486,7 +51702,7 @@ section.${c}>footer { z-index: 1; }
51486
51702
  line,
51487
51703
  column,
51488
51704
  highlight,
51489
- preview: line !== void 0 ? false : void 0
51705
+ ...line !== void 0 ? { preview: false } : {}
51490
51706
  }]);
51491
51707
  setActive(path);
51492
51708
  };
@@ -51804,6 +52020,13 @@ section.${c}>footer { z-index: 1; }
51804
52020
  workspace,
51805
52021
  refreshLsp
51806
52022
  ]);
52023
+ (0, react.useEffect)(() => {
52024
+ if (settingsOpen && settingsSection === "language") refreshLsp();
52025
+ }, [
52026
+ settingsOpen,
52027
+ settingsSection,
52028
+ refreshLsp
52029
+ ]);
51807
52030
  (0, react.useEffect)(() => () => {
51808
52031
  lspManager.current?.dispose();
51809
52032
  }, []);
@@ -52020,6 +52243,7 @@ section.${c}>footer { z-index: 1; }
52020
52243
  if (sessionId === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
52021
52244
  className: "dvw-overlay",
52022
52245
  "data-dvw-theme": colorScheme,
52246
+ "data-dvw-theme-name": theme,
52023
52247
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorkbenchTitlebar, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
52024
52248
  className: "dvw-empty",
52025
52249
  style: { gridColumn: "1/4" },
@@ -52040,6 +52264,7 @@ section.${c}>footer { z-index: 1; }
52040
52264
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
52041
52265
  className: "dvw-overlay",
52042
52266
  "data-dvw-theme": colorScheme,
52267
+ "data-dvw-theme-name": theme,
52043
52268
  "data-dvw-chat": chatVisible || void 0,
52044
52269
  "data-dvw-primary-side": primarySideVisible || void 0,
52045
52270
  "data-dvw-status": statusVisible || void 0,
@@ -52098,6 +52323,7 @@ section.${c}>footer { z-index: 1; }
52098
52323
  unavailable: navigation?.available === false,
52099
52324
  busy: switcherBusy,
52100
52325
  error: switcherError,
52326
+ theme: colorScheme,
52101
52327
  onCreate: () => void createWorkspace(),
52102
52328
  onSwitch: switchSession,
52103
52329
  onOpenWorkspace: enterWorkspace,
@@ -52120,7 +52346,38 @@ section.${c}>footer { z-index: 1; }
52120
52346
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { name: "close" })
52121
52347
  })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
52122
52348
  className: "dvw-settings-body",
52349
+ "data-section": settingsSection,
52123
52350
  children: [
52351
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("nav", {
52352
+ className: "dvw-settings-nav",
52353
+ "aria-label": "设置分类",
52354
+ children: [
52355
+ [
52356
+ "appearance",
52357
+ "外观",
52358
+ "color-mode"
52359
+ ],
52360
+ [
52361
+ "layout",
52362
+ "布局",
52363
+ "layout-sidebar-right"
52364
+ ],
52365
+ [
52366
+ "commit",
52367
+ "提交信息",
52368
+ "sparkle"
52369
+ ],
52370
+ [
52371
+ "language",
52372
+ "语言智能",
52373
+ "code"
52374
+ ]
52375
+ ].map(([value, label, icon]) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
52376
+ "data-active": settingsSection === value,
52377
+ onClick: () => setSettingsSection(value),
52378
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { name: icon }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: label })]
52379
+ }, value))
52380
+ }),
52124
52381
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", { children: [
52125
52382
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: "外观" }),
52126
52383
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", { children: "颜色主题" }),
@@ -52129,7 +52386,9 @@ section.${c}>footer { z-index: 1; }
52129
52386
  children: [
52130
52387
  ["dsh", "跟随 DSH"],
52131
52388
  ["dark", "深色"],
52132
- ["light", "浅色"]
52389
+ ["light", "浅色"],
52390
+ ["white", "纯白"],
52391
+ ["eyecare", "护眼"]
52133
52392
  ].map(([value, label]) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
52134
52393
  "data-active": theme === value,
52135
52394
  onClick: () => setTheme(value),
@@ -52200,6 +52459,54 @@ section.${c}>footer { z-index: 1; }
52200
52459
  }),
52201
52460
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("output", { children: [chatWidth, "px"] })
52202
52461
  ]
52462
+ }),
52463
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
52464
+ className: "dvw-setting-choice",
52465
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Markdown 默认视图" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
52466
+ className: "dvw-setting-segment",
52467
+ children: [["preview", "预览"], ["source", "源码"]].map(([value, label]) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
52468
+ "data-active": markdownView === value,
52469
+ onClick: () => setMarkdownView(value),
52470
+ children: label
52471
+ }, value))
52472
+ })]
52473
+ })
52474
+ ] }),
52475
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", { children: [
52476
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: "提交信息" }),
52477
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
52478
+ className: "dvw-setting-choice",
52479
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "详细程度" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
52480
+ className: "dvw-setting-segment",
52481
+ children: [
52482
+ ["concise", "简洁"],
52483
+ ["standard", "标准"],
52484
+ ["detailed", "详细"]
52485
+ ].map(([value, label]) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
52486
+ "data-active": commitDetail === value,
52487
+ onClick: () => setCommitDetail(value),
52488
+ children: label
52489
+ }, value))
52490
+ })]
52491
+ }),
52492
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
52493
+ className: "dvw-setting-choice",
52494
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "语言" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
52495
+ className: "dvw-setting-segment",
52496
+ children: [
52497
+ ["auto", "跟随最近提交"],
52498
+ ["zh", "中文"],
52499
+ ["en", "English"]
52500
+ ].map(([value, label]) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
52501
+ "data-active": commitLanguage === value,
52502
+ onClick: () => setCommitLanguage(value),
52503
+ children: label
52504
+ }, value))
52505
+ })]
52506
+ }),
52507
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
52508
+ className: "dvw-setting-hint",
52509
+ children: "详细模式会生成标题和 2–4 条说明;简洁模式限制标题长度,标准模式保持单行约定式提交。"
52203
52510
  })
52204
52511
  ] }),
52205
52512
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", { children: [
@@ -52214,19 +52521,39 @@ section.${c}>footer { z-index: 1; }
52214
52521
  }),
52215
52522
  lspServers.map((server) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
52216
52523
  className: "dvw-setting-extension",
52217
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: server.name }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [server.installed ? "已安装" : server.installable ? "点击安装" : "需要手动安装", !server.installed && server.hint ? ` · ${server.hint}` : ""] })] }), server.installable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
52524
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: server.name }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
52525
+ className: "dvw-lsp-status",
52526
+ children: [
52527
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
52528
+ className: "dvw-lsp-chip",
52529
+ "data-installed": server.language === void 0 || server.language.installed,
52530
+ "data-action": server.language !== void 0 && !server.language.installed,
52531
+ children: server.language === void 0 ? "语言:无需安装" : server.language.installed ? "语言:已安装" : "安装语言"
52532
+ }),
52533
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
52534
+ className: "dvw-lsp-chip",
52535
+ "data-installed": server.installed,
52536
+ children: server.installed ? "LSP:已安装" : "LSP:未安装"
52537
+ }),
52538
+ !server.installed && server.hint !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
52539
+ className: "dvw-lsp-hint",
52540
+ children: server.hint
52541
+ })
52542
+ ]
52543
+ })] }), server.language !== void 0 && !server.language.installed ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
52544
+ disabled: true,
52545
+ title: "先安装语言工具链,再安装 LSP",
52546
+ children: "等待"
52547
+ }) : server.installable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
52218
52548
  disabled: lspBusy === server.id,
52219
52549
  className: server.installed ? void 0 : "dvw-primary-button",
52220
52550
  onClick: () => void changeLsp(server.id, server.installed ? "uninstall" : "install"),
52221
- children: lspBusy === server.id ? "处理中…" : server.installed ? "卸载" : "安装"
52222
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
52223
- onClick: () => void refreshLsp(),
52224
- children: "重新检测"
52551
+ children: lspBusy === server.id ? "处理中…" : server.installed ? "卸载 LSP" : "安装 LSP"
52225
52552
  })]
52226
52553
  }, server.id)),
52227
52554
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
52228
52555
  className: "dvw-setting-hint",
52229
- children: "每种语言使用该生态里最活跃的语言服务器,安装只写入本插件的私有目录。安装后在编辑器中 F12 转到定义、Shift+F12 查找引用、Alt+F12 速览、Ctrl+Space 补全,并显示诊断。"
52556
+ children: "每种语言使用该生态里最活跃的语言服务器;能自动安装的会装进本插件的私有目录,需要手动安装的会分别检查语言工具链和服务器本身。"
52230
52557
  }),
52231
52558
  lspError && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
52232
52559
  className: "dvw-setting-hint",
@@ -52320,6 +52647,7 @@ section.${c}>footer { z-index: 1; }
52320
52647
  " ",
52321
52648
  snapshot.view === "git" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(GitView, {
52322
52649
  sessionId,
52650
+ preferences: commitPreferences,
52323
52651
  onDiff: openDiff
52324
52652
  })
52325
52653
  ]
@@ -52712,7 +53040,7 @@ body[data-ds-dark-theme] .dvw-overlay,.dvw-overlay[data-dvw-theme=dark]{color-sc
52712
53040
  .dvw-main{grid-column:3;grid-row:1;position:relative;display:flex;min-width:0;min-height:0;flex-direction:column;background:var(--dvw-surface-1);border-left:1px solid var(--dvw-border);border-top:1px solid var(--dvw-border);border-right:1px solid var(--dvw-border);border-bottom:1px solid var(--dvw-border);border-radius:8px;margin-left:4px;overflow:hidden}.dvw-tabs{height:35px;background:linear-gradient(to top,var(--dvw-border) 0 1px,var(--dvw-base) 1px 100%);display:flex;overflow:hidden}.dvw-tabs[data-empty]{display:none}.dvw-tab{position:relative;height:35px;margin:0;min-width:110px;max-width:260px;border:0;border-right:1px solid var(--dvw-border-soft);border-radius:8px 8px 0 0;background:transparent;color:var(--dvw-text-2);padding:0 8px 0 12px;display:flex;align-items:center;gap:6px;cursor:pointer;flex:none;white-space:nowrap}.dvw-tab:hover{background:var(--dvw-hover)}.dvw-tab[data-active=true]{background:var(--dvw-surface-1);color:var(--dvw-text);border-top:1px solid var(--dvw-border);border-right:1px solid var(--dvw-border)}.dvw-tab-icon{width:16px;height:16px;flex:none;object-fit:contain}.dvw-tab-close{width:16px;height:16px;flex:none;display:grid;place-items:center;border-radius:3px;opacity:0}.dvw-tab-close:hover{background:var(--dvw-hover);color:var(--dvw-text)}.dvw-tab[data-active=true] .dvw-tab-close,.dvw-tab:hover .dvw-tab-close{opacity:1}.dvw-tab-name{overflow:hidden;text-overflow:ellipsis;flex:1;min-width:0;text-align:left;white-space:nowrap}.dvw-editor{position:relative;flex:1;min-height:0}.dvw-editor-toolbar{position:absolute;z-index:3;top:0;right:0;left:0;height:35px;display:flex;align-items:center;justify-content:flex-end;gap:4px;padding:0 10px;border-bottom:1px solid var(--dvw-border-soft);background:var(--dvw-surface-1)}.dvw-editor-body{position:absolute;inset:0;min-height:0}.dvw-editor-body[data-toolbar=true]{top:35px}.dvw-mode-button{height:27px;padding:0 10px;display:flex;align-items:center;gap:6px;border:1px solid transparent;border-radius:5px;background:transparent;color:var(--dvw-text-2);cursor:pointer}.dvw-mode-button:hover{background:var(--dvw-hover)}.dvw-mode-button[data-active=true]{border-color:var(--dvw-border);background:var(--dvw-active);color:var(--dvw-text)}.dvw-empty{height:100%;display:grid;place-items:center;color:var(--dvw-text-3);text-align:center}.dvw-empty strong{font-size:24px;color:var(--dvw-text-2)}.dvw-message{padding:12px;color:var(--dvw-warn)}.dvw-message button{margin-left:10px;padding:2px 10px;border:1px solid var(--dvw-border);border-radius:4px;background:var(--dvw-surface-2);color:var(--dvw-text);font:inherit;cursor:pointer}.dvw-message button:hover{background:var(--dvw-hover)}
52713
53041
  .dvw-bottom-resizer{height:4px;cursor:ns-resize}.dvw-bottom-resizer:hover{background:var(--dvw-accent)}.dvw-bottom-reveal{position:absolute;left:0;right:0;bottom:0;height:6px;z-index:4;cursor:ns-resize}.dvw-bottom-reveal::after{content:"";position:absolute;left:0;right:0;bottom:0;height:2px;background:transparent}.dvw-bottom-reveal:hover::after{background:var(--dvw-accent)}.dvw-bottom{grid-column:3;grid-row:2;height:260px;min-height:120px;border-top:1px solid var(--dvw-border);border-left:1px solid var(--dvw-border);border-right:1px solid var(--dvw-border);border-bottom:1px solid var(--dvw-border);border-radius:8px;margin-top:4px;margin-left:4px;background:var(--dvw-base);display:flex;flex-direction:column}.dvw-bottom-head{height:35px;display:flex;align-items:center;gap:14px;padding:0 12px}.dvw-bottom-title{border:0;border-bottom:1px solid var(--dvw-text);background:transparent;color:var(--dvw-text);height:35px}.dvw-bottom-body{flex:1;min-height:0}.dvw-status{grid-column:1/4;grid-row:3;background:var(--dvw-base);color:var(--dvw-text);display:flex;align-items:center;padding:6px 8px 0;gap:18px;font-size:12px}.dvw-theme-control{position:relative;margin-left:auto}.dvw-theme-trigger{height:22px;min-width:112px;display:flex;align-items:center;gap:7px;padding:0 8px;border:0;border-radius:5px;background:color-mix(in srgb,#000 17%,transparent);color:#fff;cursor:pointer}.dvw-theme-trigger:hover{background:color-mix(in srgb,#000 27%,transparent)}.dvw-theme-orb{width:13px;height:13px;border:2px solid #fff;border-radius:50%;background:linear-gradient(90deg,#191a1b 50%,#fff 50%)}.dvw-theme-orb.dark{background:#191a1b}.dvw-theme-orb.light{background:#fff}.dvw-theme-menu{position:absolute;right:0;bottom:29px;width:224px;padding:6px;border:1px solid var(--dvw-border);border-radius:10px;background:var(--dvw-surface-3);box-shadow:0 10px 35px rgba(0,0,0,.28);color:var(--dvw-text)}.dvw-theme-menu button{width:100%;min-height:48px;border:0;border-radius:7px;background:transparent;color:inherit;display:grid;grid-template-columns:30px 1fr 20px;align-items:center;text-align:left;padding:6px;cursor:pointer}.dvw-theme-menu button:hover,.dvw-theme-menu button[aria-checked=true]{background:var(--dvw-hover)}.dvw-theme-menu strong,.dvw-theme-menu small{display:block}.dvw-theme-menu small{color:var(--dvw-text-3);margin-top:2px}.dvw-theme-swatch{width:22px;height:22px;border-radius:6px;border:1px solid var(--dvw-border);background:linear-gradient(135deg,#191a1b 0 50%,#fff 50%)}.dvw-theme-swatch.dark{background:#191a1b}.dvw-theme-swatch.light{background:#fff}
52714
53042
  .dvw-search-form{padding:8px;display:grid;gap:6px}.dvw-input,.dvw-textarea,.dvw-select{width:100%;border:1px solid var(--dvw-border);border-radius:2px;background:var(--dvw-surface-2);color:var(--dvw-text);padding:3px 7px;outline:none}.dvw-input:focus,.dvw-textarea:focus,.dvw-select:focus{border-color:var(--dvw-accent)}.dvw-options{display:flex;align-items:center;gap:8px;font-size:11px}.dvw-result-file{height:22px;display:flex;align-items:center;gap:4px;padding:0 8px;font-weight:600}.dvw-result{height:22px;align-items:center;padding:0 8px 0 20px;cursor:pointer;display:flex;gap:8px}.dvw-result:hover{background:var(--dvw-hover)}.dvw-line{color:var(--dvw-text-3);min-width:30px;text-align:right}.dvw-preview{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dvw-search-hit{background:color-mix(in srgb,var(--dvw-accent) 28%,transparent);border-radius:2px}
52715
- .dvw-git-head{padding:7px 10px;border-bottom:1px solid var(--dvw-border);display:flex;align-items:center;gap:8px;position:relative}.dvw-branch{min-width:0;border:0;background:transparent;color:var(--dvw-text);font:inherit;font-weight:600;display:flex;align-items:center;gap:5px;cursor:pointer}.dvw-branch-caret{margin-left:2px;font-size:14px;color:var(--dvw-text-3)}.dvw-branch-menu{position:absolute;z-index:12;top:calc(100% + 2px);left:6px;right:6px;padding:4px;border:1px solid var(--dvw-border);border-radius:8px;background:var(--dvw-surface-2);box-shadow:0 10px 28px rgba(0,0,0,.28);color:var(--dvw-text)}.dvw-branch-current{padding:4px 8px;color:var(--dvw-text-3);font-size:11px}.dvw-branch-list{max-height:min(300px,45vh);overflow:auto}.dvw-branch-list button{width:100%;height:26px;display:flex;align-items:center;gap:6px;border:0;border-radius:4px;background:transparent;color:var(--dvw-text);padding:0 8px;text-align:left;font:inherit;cursor:pointer}.dvw-branch-list button:hover{background:var(--dvw-hover)}.dvw-branch-list button[data-active=true]{background:var(--dvw-active)}.dvw-branch-list button span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dvw-branch-worktree{margin-left:auto;flex:none;padding:1px 5px;border-radius:8px;background:var(--dvw-surface-3);color:var(--dvw-text-3);font-size:10px;line-height:14px}.dvw-branch-create{display:flex;gap:4px;align-items:center;margin-top:4px;padding-top:6px;border-top:1px solid var(--dvw-border-soft)}.dvw-branch-create .dvw-input{flex:1;min-width:0}.dvw-branch-create-button{flex:none;width:24px;min-width:24px;height:24px;border:1px solid var(--dvw-border);border-radius:4px}.dvw-commit{display:grid;grid-template-columns:1fr auto;gap:6px;padding:9px}.dvw-commit .dvw-input{grid-column:1/3}.dvw-commit-button{grid-column:1/3;height:31px;border:0;border-radius:6px;background:color-mix(in srgb,var(--dvw-accent) 24%,var(--dvw-surface-2));color:var(--dvw-text);display:flex;align-items:center;justify-content:center;gap:7px;cursor:pointer}.dvw-commit-button:hover{background:color-mix(in srgb,var(--dvw-accent) 34%,var(--dvw-surface-2))}.dvw-commit-button:disabled{opacity:.45;cursor:default}.dvw-group-head{height:30px;display:flex;align-items:center;gap:5px;padding:0 6px 0 9px;font-weight:600;position:sticky;top:0;background:var(--dvw-side);z-index:1}.dvw-group-head:hover{background:var(--dvw-hover)}.dvw-group-head .dvw-count{margin-left:auto;min-width:20px;height:20px;border-radius:10px;display:grid;place-items:center;background:var(--dvw-surface-3);color:var(--dvw-text-2);font-size:11px}.dvw-change{display:flex;align-items:center;height:22px;padding:0 5px 0 19px;gap:5px;cursor:pointer}.dvw-change:hover{background:var(--dvw-hover)}.dvw-change .dvw-icon{opacity:0}.dvw-change:hover .dvw-icon,.dvw-change:focus-within .dvw-icon{opacity:1}.dvw-change-path{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1}.dvw-badge{font-size:11px;color:var(--dvw-warn)}.dvw-graph{border-top:1px solid var(--dvw-border-soft);margin-top:8px;padding-top:3px}.dvw-graph-list{padding-bottom:8px}.dvw-graph-row{width:100%;height:38px;border:0;background:transparent;color:var(--dvw-text);display:flex;align-items:center;padding:0 7px;text-align:left;cursor:pointer;overflow:hidden}.dvw-graph-row:hover{background:var(--dvw-hover)}.dvw-graph-svg{flex:none;align-self:stretch}.dvw-graph-line{fill:none;stroke-width:1px;stroke-linecap:round;vector-effect:non-scaling-stroke}.dvw-graph-node{stroke:var(--dvw-side);stroke-width:2px;fill:var(--dvw-side)}.dvw-graph-copy{display:flex;min-width:0;flex:1;flex-direction:column;justify-content:center}.dvw-graph-subject{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dvw-graph-meta{font-size:11px;color:var(--dvw-text-3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dvw-ref{max-width:82px;margin-left:4px;padding:1px 5px;border:1px solid color-mix(in srgb,var(--dvw-accent) 50%,transparent);border-radius:9px;color:var(--dvw-accent);font-size:10px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dvw-error{padding:8px;color:var(--dvw-error);white-space:pre-wrap}.dvw-diff{margin:0;height:100%;overflow:auto;padding:8px 0;background:var(--dvw-surface-1);font:12px/1.5 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;white-space:pre}.dvw-diff-line{display:block;min-height:18px;padding:0 14px}.dvw-diff-line.add{background:color-mix(in srgb,var(--dvw-success) 15%,transparent);color:var(--dvw-success)}.dvw-diff-line.remove{background:color-mix(in srgb,var(--dvw-error) 13%,transparent);color:var(--dvw-error)}.dvw-diff-line.hunk{background:color-mix(in srgb,var(--dvw-accent) 12%,transparent);color:var(--dvw-accent)}.dvw-diff-line.meta{color:var(--dvw-text-3)}.dvw-diff-empty{padding:24px;color:var(--dvw-text-3)}
53043
+ .dvw-git-head{padding:7px 10px;border-bottom:1px solid var(--dvw-border);display:flex;align-items:center;gap:8px;position:relative}.dvw-branch{min-width:0;border:0;background:transparent;color:var(--dvw-text);font:inherit;font-weight:600;display:flex;align-items:center;gap:5px;cursor:pointer}.dvw-branch-caret{margin-left:2px;font-size:14px;color:var(--dvw-text-3)}.dvw-branch-menu{position:absolute;z-index:12;top:calc(100% + 2px);left:6px;right:6px;padding:4px;border:1px solid var(--dvw-border);border-radius:8px;background:var(--dvw-surface-2);box-shadow:0 10px 28px rgba(0,0,0,.28);color:var(--dvw-text)}.dvw-branch-current{padding:4px 8px;color:var(--dvw-text-3);font-size:11px}.dvw-branch-list{max-height:min(300px,45vh);overflow:auto}.dvw-branch-list button{width:100%;height:26px;display:flex;align-items:center;gap:6px;border:0;border-radius:4px;background:transparent;color:var(--dvw-text);padding:0 8px;text-align:left;font:inherit;cursor:pointer}.dvw-branch-list button:hover{background:var(--dvw-hover)}.dvw-branch-list button[data-active=true]{background:var(--dvw-active)}.dvw-branch-list button span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dvw-branch-worktree{margin-left:auto;flex:none;padding:1px 5px;border-radius:8px;background:var(--dvw-surface-3);color:var(--dvw-text-3);font-size:10px;line-height:14px}.dvw-branch-create{display:flex;gap:4px;align-items:center;margin-top:4px;padding-top:6px;border-top:1px solid var(--dvw-border-soft)}.dvw-branch-create .dvw-input{flex:1;min-width:0}.dvw-branch-create-button{flex:none;width:24px;min-width:24px;height:24px;border:1px solid var(--dvw-border);border-radius:4px}.dvw-commit{display:flex;flex-direction:column;gap:6px;padding:9px}.dvw-commit-actions{display:grid;grid-template-columns:1fr auto;gap:6px}.dvw-commit-button{height:31px;border:0;border-radius:6px;background:color-mix(in srgb,var(--dvw-accent) 24%,var(--dvw-surface-2));color:var(--dvw-text);display:flex;align-items:center;justify-content:center;gap:7px;cursor:pointer}.dvw-commit-button:hover{background:color-mix(in srgb,var(--dvw-accent) 34%,var(--dvw-surface-2))}.dvw-commit-button:disabled{opacity:.45;cursor:default}.dvw-commit-ai{height:31px;border:1px solid var(--dvw-border);border-radius:6px;background:var(--dvw-surface-2);color:var(--dvw-text-2);display:flex;align-items:center;justify-content:center;gap:6px;font:inherit;cursor:pointer}.dvw-commit-ai:hover:not(:disabled){background:var(--dvw-hover);color:var(--dvw-text)}.dvw-commit-ai:disabled{opacity:.45;cursor:default}.dvw-group-head{height:30px;display:flex;align-items:center;gap:5px;padding:0 6px 0 9px;font-weight:600;position:sticky;top:0;background:var(--dvw-side);z-index:1}.dvw-group-head:hover{background:var(--dvw-hover)}.dvw-group-head .dvw-count{margin-left:auto;min-width:20px;height:20px;border-radius:10px;display:grid;place-items:center;background:var(--dvw-surface-3);color:var(--dvw-text-2);font-size:11px}.dvw-change{display:flex;align-items:center;height:22px;padding:0 5px 0 19px;gap:5px;cursor:pointer}.dvw-change:hover{background:var(--dvw-hover)}.dvw-change .dvw-icon{opacity:0}.dvw-change:hover .dvw-icon,.dvw-change:focus-within .dvw-icon{opacity:1}.dvw-change-path{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1}.dvw-badge{font-size:11px;color:var(--dvw-warn)}.dvw-graph{border-top:1px solid var(--dvw-border-soft);margin-top:8px;padding-top:3px}.dvw-graph-list{padding-bottom:8px}.dvw-graph-row{width:100%;height:38px;border:0;background:transparent;color:var(--dvw-text);display:flex;align-items:center;padding:0 7px;text-align:left;cursor:pointer;overflow:hidden}.dvw-graph-row:hover{background:var(--dvw-hover)}.dvw-graph-svg{flex:none;align-self:stretch}.dvw-graph-line{fill:none;stroke-width:1px;stroke-linecap:round;vector-effect:non-scaling-stroke}.dvw-graph-node{stroke:var(--dvw-side);stroke-width:2px;fill:var(--dvw-side)}.dvw-graph-copy{display:flex;min-width:0;flex:1;flex-direction:column;justify-content:center}.dvw-graph-subject{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dvw-graph-meta{font-size:11px;color:var(--dvw-text-3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dvw-ref{max-width:82px;margin-left:4px;padding:1px 5px;border:1px solid color-mix(in srgb,var(--dvw-accent) 50%,transparent);border-radius:9px;color:var(--dvw-accent);font-size:10px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dvw-error{padding:8px;color:var(--dvw-error);white-space:pre-wrap}.dvw-diff{margin:0;height:100%;overflow:auto;padding:8px 0;background:var(--dvw-surface-1);font:12px/1.5 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;white-space:pre}.dvw-diff-line{display:block;min-height:18px;padding:0 14px}.dvw-diff-line.add{background:color-mix(in srgb,var(--dvw-success) 15%,transparent);color:var(--dvw-success)}.dvw-diff-line.remove{background:color-mix(in srgb,var(--dvw-error) 13%,transparent);color:var(--dvw-error)}.dvw-diff-line.hunk{background:color-mix(in srgb,var(--dvw-accent) 12%,transparent);color:var(--dvw-accent)}.dvw-diff-line.meta{color:var(--dvw-text-3)}.dvw-diff-empty{padding:24px;color:var(--dvw-text-3)}
52716
53044
  .dvw-tab-list{display:flex;min-width:0;flex:1;overflow-x:auto;overflow-y:hidden;overscroll-behavior-x:contain;scrollbar-width:none}.dvw-tab-list::-webkit-scrollbar{display:none}.dvw-monaco-diff{position:absolute;inset:0}.dvw-diff-toolbar{justify-content:flex-end}.dvw-group-head{gap:2px;padding-left:2px}.dvw-group-toggle{min-width:0;height:30px;flex:1;border:0;border-radius:5px;background:transparent;color:var(--dvw-text);font:inherit;font-weight:600;display:flex;align-items:center;gap:5px;padding:0 7px;cursor:pointer;text-align:left}.dvw-group-toggle:hover{background:var(--dvw-hover)}.dvw-graph-entry[data-expanded=true]{background:color-mix(in srgb,var(--dvw-accent) 5%,transparent)}.dvw-commit-files{padding:1px 0 5px 26px}.dvw-commit-file{width:100%;height:22px;border:0;background:transparent;color:var(--dvw-text);display:flex;align-items:center;gap:6px;padding:0 7px;text-align:left;cursor:pointer}.dvw-commit-file:hover{background:var(--dvw-hover)}.dvw-commit-file-name{white-space:nowrap}.dvw-commit-file-dir{min-width:0;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dvw-text-3);font-size:11px}
52717
53045
  .dvw-outline{flex:none;max-height:38%;display:flex;flex-direction:column;border-bottom:1px solid var(--dvw-border)}.dvw-outline-head{height:30px;display:flex;align-items:center;justify-content:space-between;padding:0 5px 0 10px;font-weight:600}.dvw-outline-head>span{display:flex;align-items:center;gap:6px}.dvw-outline-list{overflow:auto;padding-bottom:5px}.dvw-outline-item{display:block;width:100%;height:22px;border:0;background:transparent;color:var(--dvw-text-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left;cursor:pointer}.dvw-outline-item:hover{background:var(--dvw-hover);color:var(--dvw-text)}.dvw-image-preview{position:absolute;inset:0;overflow:auto;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:14px;padding:24px;background:repeating-conic-gradient(var(--dvw-surface-2) 0 25%,var(--dvw-surface-1) 0 50%) 0/20px 20px}.dvw-image-preview img{max-width:100%;max-height:calc(100% - 32px);object-fit:contain;box-shadow:0 4px 24px rgba(0,0,0,.22)}.dvw-image-preview span{max-width:100%;padding:3px 8px;border-radius:5px;background:var(--dvw-surface-1);color:var(--dvw-text-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
52718
53046
  .dvw-pdf-preview{position:absolute;inset:0;display:flex;min-height:0;flex-direction:column;background:var(--dvw-base);color:var(--dvw-text)}.dvw-pdf-toolbar{height:30px;flex:none;display:flex;align-items:center;justify-content:center;gap:2px;padding:0 8px;border-bottom:1px solid var(--dvw-border);background:var(--dvw-surface-1);font-variant-numeric:tabular-nums}.dvw-pdf-toolbar .dvw-icon{font-size:18px}.dvw-pdf-zoom{min-width:52px;height:24px;border:0;border-radius:4px;background:var(--dvw-active);color:var(--dvw-text);font:inherit;cursor:pointer}.dvw-pdf-zoom:hover{background:var(--dvw-hover)}.dvw-pdf-separator{width:1px;height:18px;margin:0 4px;background:var(--dvw-border)}.dvw-pdf-page{min-height:0;flex:1;overflow:auto;display:flex;justify-content:center;padding:8px;background:var(--dvw-base)}.dvw-pdf-page canvas{flex:none;background:#fff;box-shadow:0 2px 12px rgba(0,0,0,.28)}.dvw-sheet-preview{position:absolute;inset:0;display:flex;min-height:0;flex-direction:column;background:var(--dvw-base);color:var(--dvw-text)}.dvw-sheet-tabs{flex:none;display:flex;gap:2px;padding:6px 8px;overflow:auto;border-bottom:1px solid var(--dvw-border)}.dvw-sheet-tabs button{height:24px;padding:0 10px;border:0;border-radius:3px;background:transparent;color:var(--dvw-text-2);font:inherit;cursor:pointer;white-space:nowrap}.dvw-sheet-tabs button:hover{background:var(--dvw-hover)}.dvw-sheet-tabs button[data-active=true]{background:var(--dvw-active);color:var(--dvw-text)}.dvw-sheet-scroll{flex:1;min-height:0;overflow:auto;padding:10px}.dvw-sheet-table{border-collapse:collapse;font-size:12px}.dvw-sheet-table td{max-width:360px;padding:2px 8px;border:1px solid var(--dvw-border);white-space:pre;overflow:hidden;text-overflow:ellipsis}.dvw-sheet-table tr:first-child td{background:var(--dvw-hover);font-weight:600}.dvw-slides-preview{position:absolute;inset:0;overflow:auto;padding:16px;background:var(--dvw-base)}.dvw-docx-preview{position:absolute;inset:0;overflow:auto;padding:28px;background:var(--dvw-base);color:#222}.dvw-docx-preview .docx-wrapper{margin:auto;background:#fff;box-shadow:0 2px 12px rgba(0,0,0,.2)}.dvw-document-error,.dvw-document-download{height:100%;display:grid;place-content:center;justify-items:center;gap:12px;padding:24px;color:var(--dvw-text-2);text-align:center}.dvw-document-download a{color:var(--dvw-accent);text-decoration:none}.dvw-document-download a:hover{text-decoration:underline}
@@ -52760,12 +53088,15 @@ body[data-dvw-workbench-active] [data-sidebar-toggle]{display:none!important}
52760
53088
  .dvw-settings-body{overflow:auto;padding:8px 20px 20px}.dvw-settings-body section+section{margin-top:20px;padding-top:12px;border-top:1px solid var(--dvw-border-soft)}.dvw-settings-body h3{margin:8px 0 12px;font-size:13px}.dvw-settings-body>section>label:not(.dvw-setting-check):not(.dvw-setting-range){display:block;margin-bottom:7px;color:var(--dvw-text-2);font-size:12px}
52761
53089
  .dvw-settings-themes{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}.dvw-settings-themes button{height:56px;display:grid;grid-template-columns:28px 1fr 18px;align-items:center;gap:7px;padding:0 9px;border:1px solid var(--dvw-border);border-radius:7px;background:var(--dvw-base);color:var(--dvw-text);text-align:left;cursor:pointer}.dvw-settings-themes button:hover{background:var(--dvw-hover)}.dvw-settings-themes button[data-active=true]{border-color:var(--dvw-accent);background:color-mix(in srgb,var(--dvw-accent) 10%,var(--dvw-base))}
52762
53090
  .dvw-setting-check{height:36px;display:flex;align-items:center;gap:9px;border-bottom:1px solid var(--dvw-border-soft);cursor:pointer}.dvw-setting-check input{accent-color:var(--dvw-accent)}.dvw-setting-range{display:grid;grid-template-columns:145px 1fr 52px;align-items:center;gap:10px;min-height:42px}.dvw-setting-range input{accent-color:var(--dvw-accent)}.dvw-setting-range output{text-align:right;color:var(--dvw-text-3);font-variant-numeric:tabular-nums}
53091
+ .dvw-setting-choice{display:grid;grid-template-columns:145px 1fr;align-items:center;gap:10px;min-height:42px}.dvw-setting-choice>span{color:var(--dvw-text-2);font-size:12px}.dvw-setting-segment{display:inline-flex;justify-self:start;padding:2px;border:1px solid var(--dvw-border);border-radius:6px;background:var(--dvw-base)}.dvw-setting-segment button{min-width:64px;height:26px;border:0;border-radius:4px;background:transparent;color:var(--dvw-text-2);font:inherit;font-size:12px;cursor:pointer}.dvw-setting-segment button:hover{background:var(--dvw-hover);color:var(--dvw-text)}.dvw-setting-segment button[data-active=true]{background:var(--dvw-active);color:var(--dvw-text)}
52763
53092
  @media(max-width:900px){.dvw-overlay[data-dvw-chat=true]{--dvw-chat-effective:max(440px,min(var(--dvw-chat-width),calc(100vw - 254px)));grid-template-columns:44px min(210px,var(--dvw-side-width),max(0px,calc(100vw - 164px - var(--dvw-chat-effective)))) minmax(0,1fr) var(--dvw-chat-effective)}.dvw-overlay[data-dvw-chat=true] .dvw-status{padding-right:calc(var(--dvw-chat-effective) + 8px)}.dvw-chat-resizer{right:calc(var(--dvw-chat-effective) - 5px)}[data-dvw-conversation-panel]{width:calc(max(440px,min(var(--dvw-chat-width),calc(100vw - 254px))) - 8px)!important}}
52764
53093
  .dvw-setting-textarea{width:100%;min-height:84px;resize:vertical;padding:8px 10px;border:1px solid var(--dvw-border);border-radius:6px;background:var(--dvw-base);color:var(--dvw-text);font:12px/1.5 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
52765
53094
  .dvw-setting-textarea:focus{outline:none;border-color:var(--dvw-accent)}
52766
53095
  .dvw-setting-extension{display:flex;align-items:center;gap:12px;padding:10px 12px;border:1px solid var(--dvw-border);border-radius:7px;background:var(--dvw-base)}.dvw-setting-extension>div{min-width:0;flex:1;display:flex;flex-direction:column;gap:2px}.dvw-setting-extension span{color:var(--dvw-text-3);font-size:12px}.dvw-setting-extension button{height:26px;padding:0 14px;border:1px solid var(--dvw-border);border-radius:4px;background:transparent;color:var(--dvw-text);font:inherit;cursor:pointer}.dvw-setting-extension button:hover{background:var(--dvw-hover)}.dvw-setting-extension button.dvw-primary-button{border-color:var(--dvw-accent);background:var(--dvw-accent);color:#fff}.dvw-setting-hint{margin:8px 0 0;color:var(--dvw-text-3);font-size:11px;line-height:1.5}
52767
53096
  /* Slightly larger explorer rows for comfortable reading without shrinking the file list. */
52768
53097
  .dvw-tree-row{height:24px;font-size:13px}
53098
+ /* Keep a single focus surface: hovering another row clears the selected row's fill. */
53099
+ .dvw-tree:has(.dvw-tree-row:hover) .dvw-tree-row[data-selected=true]:not(:hover){background:transparent}
52769
53100
  .dvw-chevron{width:18px}
52770
53101
  .dvw-file-icon{width:18px;height:18px}
52771
53102
  .dvw-tree-rename,.dvw-tree-create-input{height:22px}
@@ -52786,6 +53117,97 @@ body[data-dvw-workbench-active] [data-sidebar-toggle]{display:none!important}
52786
53117
  .dvw-tab[data-active=true]::before,.dvw-tab[data-active=true]::after{content:"";position:absolute;bottom:0;width:10px;height:10px;background:var(--dvw-surface-1);pointer-events:none}
52787
53118
  .dvw-tab[data-active=true]::before{left:-10px;-webkit-mask:radial-gradient(circle 10px at 0 0,transparent 9px,#000 9.6px);mask:radial-gradient(circle 10px at 0 0,transparent 9px,#000 9.6px)}
52788
53119
  .dvw-tab[data-active=true]::after{right:-10px;-webkit-mask:radial-gradient(circle 10px at 100% 0,transparent 9px,#000 9.6px);mask:radial-gradient(circle 10px at 100% 0,transparent 9px,#000 9.6px)}
53120
+ .dvw-commit-box{position:relative;display:flex;align-items:stretch}
53121
+ .dvw-commit-input{width:100%;min-height:30px;max-height:96px;field-sizing:content;resize:none;padding:5px 32px 5px 8px;line-height:18px}
53122
+ .dvw-commit-ai{position:absolute;right:4px;top:50%;transform:translateY(-50%);width:24px;min-width:24px;height:24px;border:0;background:transparent;color:var(--dvw-text-3)}
53123
+ .dvw-commit-ai:hover:not(:disabled){background:var(--dvw-hover);color:var(--dvw-text)}
53124
+ /* VS Code-style split commit button: primary action plus a narrow dropdown for commit variants. */
53125
+ .dvw-commit .dvw-commit-actions{display:flex;gap:0;position:relative}
53126
+ .dvw-commit .dvw-commit-button{flex:1;min-width:0;height:30px;border:0;border-radius:6px 0 0 6px;background:var(--dvw-accent);color:#fff;display:flex;align-items:center;justify-content:center;gap:7px;font:inherit;cursor:pointer}
53127
+ .dvw-commit .dvw-commit-button:hover:not(:disabled){background:color-mix(in srgb,var(--dvw-accent) 88%,#fff)}
53128
+ .dvw-commit .dvw-commit-button:disabled{opacity:.45;cursor:default}
53129
+ .dvw-commit .dvw-commit-more{flex:none;width:30px;height:30px;border:0;border-left:1px solid rgba(255,255,255,.3);border-radius:0 6px 6px 0;background:var(--dvw-accent);color:#fff;display:grid;place-items:center;cursor:pointer}
53130
+ .dvw-commit .dvw-commit-more:hover:not(:disabled){background:color-mix(in srgb,var(--dvw-accent) 88%,#fff)}
53131
+ .dvw-commit .dvw-commit-more:disabled{opacity:.45;cursor:default}
53132
+ .dvw-commit .dvw-commit-menu{position:absolute;z-index:12;top:calc(100% + 4px);right:0;min-width:180px;padding:4px;border:1px solid var(--dvw-border);border-radius:8px;background:var(--dvw-surface-2);box-shadow:0 10px 28px rgba(0,0,0,.28)}
53133
+ .dvw-commit .dvw-commit-menu button{width:100%;height:26px;border:0;border-radius:4px;background:transparent;color:var(--dvw-text);padding:0 8px;text-align:left;font:inherit;cursor:pointer}
53134
+ .dvw-commit .dvw-commit-menu button:hover{background:var(--dvw-hover)}
53135
+ /* Pure-white theme: every chrome surface uses the editor's white background. */
53136
+ .dvw-overlay[data-dvw-theme=white]{--dvw-base:#fff;--dvw-surface-1:#fff;--dvw-surface-2:#fff;--dvw-surface-3:#fff;--dvw-side:#fff;--dvw-tab-active:#fff;--dvw-gutter:#fff;--dvw-graph-ref:#0063d3;--dvw-text:#171717;--dvw-text-2:#5c5c5c;--dvw-text-3:#8c8c8c;--dvw-border:#e2e2e2;--dvw-border-soft:#efefef;--dvw-hover:#0000000c;--dvw-active:#00000014;--dvw-accent:#0066cc;--dvw-error:#d13438;--dvw-success:#2e7d32;--dvw-warn:#8a6100;color-scheme:light}
53137
+ .dvw-overlay[data-dvw-theme=white] .dvw-tabs{background:#fff}
53138
+ .dvw-overlay[data-dvw-theme=white] .dvw-act[data-active=true]::before{background:#00000010}
53139
+ /* Eye-care theme: a warm paper-yellow surface shared by every panel and the editor. */
53140
+ .dvw-overlay[data-dvw-theme=eyecare]{--dvw-base:#f7ebc8;--dvw-surface-1:#f7ebc8;--dvw-surface-2:#f7ebc8;--dvw-surface-3:#f7ebc8;--dvw-side:#f7ebc8;--dvw-tab-active:#ecdcae;--dvw-gutter:#f7ebc8;--dvw-graph-ref:#9c6b1e;--dvw-text:#3b3324;--dvw-text-2:#6b604a;--dvw-text-3:#92856a;--dvw-border:#e0cf9f;--dvw-border-soft:#eadcb6;--dvw-hover:#0000000c;--dvw-active:#00000014;--dvw-accent:#9c6b1e;--dvw-error:#b03a2e;--dvw-success:#4c7a34;--dvw-warn:#8a5a00;color-scheme:light}
53141
+ .dvw-overlay[data-dvw-theme=eyecare] .dvw-tabs{background:#f7ebc8}
53142
+ .dvw-overlay[data-dvw-theme=eyecare] .dvw-act[data-active=true]::before{background:#00000016}
53143
+ .dvw-theme-swatch.white{background:#fff}
53144
+ .dvw-theme-swatch.eyecare{background:#f7ebc8}
53145
+ .dvw-settings-themes{grid-template-columns:repeat(auto-fit,minmax(108px,1fr))}
53146
+ body[data-dvw-palette=white] [data-dvw-conversation-panel]{--dsw-alias-bg-base:#fff;--dsw-specific-sidebar-fill:#fff;--dsw-alias-bg-layer-1:#fff;--dsw-alias-bg-layer-2:#fff;--dsw-alias-bg-layer-3:#fff;--dsw-alias-border-l2:#e2e2e2;--dsw-alias-border-l3:#efefef;background:#fff!important}
53147
+ body[data-dvw-palette=eyecare] [data-dvw-conversation-panel]{--dsw-alias-bg-base:#f7ebc8;--dsw-specific-sidebar-fill:#f7ebc8;--dsw-alias-bg-layer-1:#f7ebc8;--dsw-alias-bg-layer-2:#f1e2b8;--dsw-alias-bg-layer-3:#ecdcae;--dsw-alias-bg-layer-4:#ecdcae;--dsw-specific-input-major:#f7ebc8;--dsw-specific-login-input:#f1e2b8;--dsw-menu-surface-fill:#f7ebc8;--dsw-alias-label-primary:#3b3324;--dsw-alias-label-secondary:#6b604a;--dsw-alias-label-tertiary:#92856a;--dsw-alias-border-l2:#e0cf9f;--dsw-alias-border-l3:#eadcb6;--dsw-alias-interactive-bg-hover:#0000000c;--dsw-alias-interactive-bg-active:#00000014;background:#f7ebc8!important}
53148
+ /* Settings dialog: left navigation rail with aligned label/control rows, mirroring DSH settings. */
53149
+ .dvw-settings{width:min(880px,calc(100vw - 40px));height:min(680px,calc(100vh - 40px));max-height:none;border-radius:18px}
53150
+ .dvw-settings>header{height:52px;padding:0 14px 0 20px;font-size:15px}
53151
+ .dvw-settings-body{flex:1;min-height:0;display:grid;grid-template-columns:190px minmax(0,1fr);gap:0;padding:0;overflow:hidden}
53152
+ .dvw-settings-nav{grid-column:1;display:flex;flex-direction:column;gap:4px;padding:12px 10px;border-right:1px solid var(--dvw-border-soft);background:var(--dvw-surface-1);overflow:auto}
53153
+ .dvw-settings-nav button{height:36px;border:0;border-radius:11px;background:transparent;color:var(--dvw-text-2);display:flex;align-items:center;gap:10px;padding:0 12px;font:inherit;text-align:left;cursor:pointer}
53154
+ .dvw-settings-nav button .codicon{font-size:16px}
53155
+ .dvw-settings-nav button:hover{background:var(--dvw-hover);color:var(--dvw-text)}
53156
+ .dvw-settings-nav button[data-active=true]{background:var(--dvw-active);color:var(--dvw-text);font-weight:600}
53157
+ .dvw-settings-body>section{grid-column:2;min-height:0;overflow:auto;padding:20px 26px 30px;border-left:0}
53158
+ .dvw-settings-body>section+section{margin-top:0;padding-top:20px;border-top:0}
53159
+ .dvw-settings-body[data-section=appearance]>section:not(:nth-of-type(1)){display:none}
53160
+ .dvw-settings-body[data-section=layout]>section:not(:nth-of-type(2)){display:none}
53161
+ .dvw-settings-body[data-section=commit]>section:not(:nth-of-type(3)){display:none}
53162
+ .dvw-settings-body[data-section=language]>section:not(:nth-of-type(4)){display:none}
53163
+ .dvw-settings-body h3{margin:0 0 4px;font-size:16px;font-weight:600}
53164
+ .dvw-settings-body>section>label:not(.dvw-setting-check):not(.dvw-setting-range){display:block;margin:14px 0 9px;color:var(--dvw-text-2);font-size:12px}
53165
+ .dvw-setting-range{display:grid;grid-template-columns:minmax(0,1fr) minmax(140px,240px) 48px;align-items:center;gap:16px;min-height:52px;border-bottom:1px solid var(--dvw-border-soft)}
53166
+ .dvw-setting-range>span{color:var(--dvw-text);font-size:13px;font-weight:500}
53167
+ .dvw-setting-range output{text-align:right;color:var(--dvw-text-3);font-variant-numeric:tabular-nums}
53168
+ .dvw-setting-choice{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:16px;min-height:52px;border-bottom:1px solid var(--dvw-border-soft)}
53169
+ .dvw-setting-choice>span{color:var(--dvw-text);font-size:13px;font-weight:500}
53170
+ .dvw-setting-check{height:auto;min-height:52px;display:flex;flex-direction:row-reverse;align-items:center;justify-content:space-between;gap:16px;border-bottom:1px solid var(--dvw-border-soft);cursor:pointer;font-size:13px;font-weight:500}
53171
+ .dvw-setting-check input{appearance:none;flex:none;width:38px;height:22px;margin:0;border-radius:11px;background:color-mix(in srgb,var(--dvw-text) 22%,transparent);position:relative;cursor:pointer;transition:background .15s}
53172
+ .dvw-setting-check input::after{content:"";position:absolute;top:3px;left:3px;width:16px;height:16px;border-radius:50%;background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.25);transition:transform .15s}
53173
+ .dvw-setting-check input:checked{background:var(--dvw-accent)}
53174
+ .dvw-setting-check input:checked::after{transform:translateX(16px)}
53175
+ .dvw-settings-themes{grid-template-columns:repeat(5,minmax(0,1fr));gap:8px;margin:12px 0 10px}
53176
+ .dvw-settings-themes button{position:relative;height:86px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:9px;padding:10px;text-align:center;border-radius:14px;background:var(--dvw-base)}
53177
+ .dvw-settings-themes button[data-active=true]{border-color:var(--dvw-accent);box-shadow:inset 0 0 0 1px var(--dvw-accent);background:color-mix(in srgb,var(--dvw-accent) 8%,var(--dvw-base))}
53178
+ .dvw-settings-themes .dvw-theme-swatch{width:26px;height:26px;border-radius:8px;flex:none}
53179
+ .dvw-settings-themes button>.codicon{position:absolute;top:8px;right:8px;font-size:13px;color:var(--dvw-accent)}
53180
+ .dvw-settings-body .dvw-setting-extension{border:0;border-bottom:1px solid var(--dvw-border-soft);border-radius:0;background:transparent;padding:14px 0}
53181
+ .dvw-settings-body .dvw-setting-extension strong{font-size:13px}
53182
+ .dvw-settings-body .dvw-setting-extension button{height:28px;border-radius:9px;padding:0 16px;background:var(--dvw-surface-3)}
53183
+ .dvw-settings-body .dvw-setting-extension button.dvw-primary-button{border-color:var(--dvw-accent);background:var(--dvw-accent);color:#fff}
53184
+ .dvw-setting-extension .dvw-lsp-status{display:flex;flex-wrap:wrap;align-items:center;gap:6px 8px;margin-top:2px}
53185
+ .dvw-setting-extension .dvw-lsp-chip{padding:1px 8px;border:1px solid var(--dvw-border);border-radius:999px;font-size:11px;line-height:18px;color:var(--dvw-text-3)}
53186
+ .dvw-setting-extension .dvw-lsp-chip[data-installed=true]{border-color:color-mix(in srgb,var(--dvw-success) 42%,transparent);color:var(--dvw-success)}
53187
+ .dvw-setting-extension .dvw-lsp-chip[data-action=true]{border-color:color-mix(in srgb,var(--dvw-accent) 45%,transparent);color:var(--dvw-accent)}
53188
+ .dvw-setting-extension .dvw-lsp-hint{flex-basis:100%;font-size:11px;line-height:1.45;color:var(--dvw-text-3)}
53189
+ .dvw-setting-extension button:disabled{opacity:.55;cursor:default}
53190
+ .dvw-settings .dvw-setting-segment{border-radius:10px;padding:3px}
53191
+ .dvw-settings .dvw-setting-segment button{border-radius:7px}
53192
+ .dvw-settings .dvw-icon{border-radius:9px}
53193
+ /* Monaco owns diff scrolling; an outer scroller changes the width as scrollbars appear and makes split mode oscillate. */
53194
+ .dvw-editor{min-width:0;overflow:hidden}
53195
+ .dvw-editor-body{min-width:0;overflow:hidden}
53196
+ .dvw-monaco-diff{height:auto;min-width:0;min-height:0;margin:0;padding:0;overflow:hidden;white-space:normal}
53197
+ /* Keep the workspace switcher in the same elevated surface family as workbench settings. */
53198
+ .dvw-workspace-layer{position:fixed!important;inset:0!important;z-index:1000!important;display:block!important;padding:0!important;background:transparent!important;overflow:hidden!important}
53199
+ .dvw-workspace-backdrop{position:absolute;inset:0;z-index:50;display:grid;place-items:center;padding:24px;background:rgba(0,0,0,.34);backdrop-filter:blur(3px)}
53200
+ .dvw-workspace-switcher{width:min(640px,calc(100vw - 48px));height:min(680px,calc(100vh - 48px));max-height:none;border-radius:18px;overflow:hidden;box-shadow:0 16px 50px rgba(0,0,0,.32)}
53201
+ .dvw-workspace-switcher>header{height:52px;padding:0 12px 0 20px;font-size:15px}
53202
+ .dvw-workspace-list{padding:10px}
53203
+ .dvw-workspace-row{border-radius:11px}
53204
+ .dvw-workspace-toggle{height:40px;padding:0 12px}
53205
+ .dvw-workspace-sessions{gap:3px;padding:4px 0 8px 32px}
53206
+ .dvw-workspace-session{height:34px;padding:0 12px;border-radius:11px}
53207
+ .dvw-workspace-switcher>footer{padding:12px 16px}
53208
+ .dvw-workspace-switcher>footer button{height:32px;border-radius:9px;padding:0 16px}
53209
+ .dvw-workspace-switcher .dvw-icon{border-radius:9px}
53210
+ @media(max-width:760px){.dvw-settings-body{grid-template-columns:1fr;grid-template-rows:auto minmax(0,1fr)}.dvw-settings-nav{grid-column:1;grid-row:1;flex-direction:row;border-right:0;border-bottom:1px solid var(--dvw-border-soft);padding:8px}.dvw-settings-nav button{flex:none}.dvw-settings-body>section{grid-column:1;grid-row:2;padding:16px 18px 24px}}
52789
53211
  `;
52790
53212
  function installStyles() {
52791
53213
  const id = "dsh-vscode-workbench/styles";