@nkzw/codiff-core 1.9.0 → 1.10.0

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/dist/react.mjs CHANGED
@@ -7,15 +7,19 @@ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
7
7
  import { MarkdownEditor } from "@nkzw/mdx-editor";
8
8
  import { frontmatterPlugin, imagePlugin } from "@nkzw/mdx-editor/core";
9
9
  import { DownloadSimpleIcon } from "@phosphor-icons/react/DownloadSimple";
10
- import { Copy, ExternalLink, Trash2, X } from "lucide-react";
10
+ import { Copy, Trash2, X } from "lucide-react";
11
+ import { ArrowSquareOutIcon } from "@phosphor-icons/react/ArrowSquareOut";
12
+ import { ChatCircleIcon } from "@phosphor-icons/react/ChatCircle";
13
+ import { PathIcon } from "@phosphor-icons/react/Path";
14
+ import { TreeStructureIcon } from "@phosphor-icons/react/TreeStructure";
11
15
  import { FileTree, useFileTree } from "@pierre/trees/react";
12
16
  import { hydratePartialDiff, parseDiffFromFile, parsePatchFiles, registerCustomTheme, setCustomExtension } from "@pierre/diffs";
13
17
  import useRelativeTime from "@nkzw/use-relative-time";
14
- import { ChatCircleIcon } from "@phosphor-icons/react/ChatCircle";
15
18
  import { CaretDownIcon } from "@phosphor-icons/react/CaretDown";
16
19
  import "@phosphor-icons/react/CaretUp";
17
20
  import { CheckIcon } from "@phosphor-icons/react/Check";
18
21
  import { CheckCircleIcon } from "@phosphor-icons/react/CheckCircle";
22
+ import "@phosphor-icons/react/CircleNotch";
19
23
  import { PowerIcon } from "@phosphor-icons/react/Power";
20
24
  import { SealQuestionIcon } from "@phosphor-icons/react/SealQuestion";
21
25
  import { WarningOctagonIcon } from "@phosphor-icons/react/WarningOctagon";
@@ -26,13 +30,13 @@ import { SquareSplitVerticalIcon } from "@phosphor-icons/react/SquareSplitVertic
26
30
  import { CodeView, WorkerPoolContextProvider } from "@pierre/diffs/react";
27
31
  import { PersistentMarkdownEditor } from "@nkzw/mdx-editor/persistence";
28
32
  import { GitBranchIcon } from "@phosphor-icons/react/GitBranch";
29
- import { PathIcon } from "@phosphor-icons/react/Path";
30
33
  import { ShareNetworkIcon } from "@phosphor-icons/react/ShareNetwork";
31
34
  import { BugIcon } from "@phosphor-icons/react/Bug";
32
35
  import { FlaskIcon } from "@phosphor-icons/react/Flask";
33
36
  import { GearIcon } from "@phosphor-icons/react/Gear";
34
37
  import { ReadCvLogoIcon } from "@phosphor-icons/react/ReadCvLogo";
35
38
  import { WrenchIcon } from "@phosphor-icons/react/Wrench";
39
+ import { SidebarSimpleIcon } from "@phosphor-icons/react/SidebarSimple";
36
40
  import { ArrowLeftIcon } from "@phosphor-icons/react/ArrowLeft";
37
41
  import { ArrowRightIcon } from "@phosphor-icons/react/ArrowRight";
38
42
  import { CaretLeftIcon } from "@phosphor-icons/react/CaretLeft";
@@ -1067,7 +1071,7 @@ function PlanReviewSurface({ commenting, onDeleteShare, signInLabel = "Sign in t
1067
1071
  className: "plan-shell shared-plan-shell",
1068
1072
  "data-theme": snapshot.preferences.theme === "system" ? void 0 : snapshot.preferences.theme,
1069
1073
  children: [/* @__PURE__ */ jsx("header", {
1070
- className: "plan-header",
1074
+ className: "plan-header workspace-top-bar",
1071
1075
  children: /* @__PURE__ */ jsx("div", {
1072
1076
  className: "plan-title",
1073
1077
  title: snapshot.document.title,
@@ -1422,16 +1426,7 @@ const statusForTree = {
1422
1426
  untracked: "untracked"
1423
1427
  };
1424
1428
  const fileTreeSort = (left, right) => compareTreePaths(left.path, right.path);
1425
- const compactPath = (path) => {
1426
- const homePath = path.replace(/^\/Users\/[^/]+(?=\/|$)/, "~").replace(/^\/home\/[^/]+(?=\/|$)/, "~");
1427
- const parts = homePath.split("/").filter(Boolean);
1428
- if (parts.length <= 2) return homePath;
1429
- const prefix = homePath.startsWith("/") ? "/" : "";
1430
- const [first, ...rest] = parts;
1431
- const last = rest.pop();
1432
- const middle = rest.map((part) => part[0]).join("/");
1433
- return `${prefix}${first}/${middle ? `${middle}/` : ""}${last}`;
1434
- };
1429
+ const abbreviateHomePath = (path) => path.replace(/^\/Users\/[^/]+(?=\/|$)/, "~").replace(/^\/home\/[^/]+(?=\/|$)/, "~").replace(/^[A-Za-z]:[/\\]Users[/\\][^/\\]+(?=[/\\]|$)/, "~");
1435
1430
  function compareTreePaths(leftPath, rightPath) {
1436
1431
  const leftParts = leftPath.split("/");
1437
1432
  const rightParts = rightPath.split("/");
@@ -1630,26 +1625,108 @@ const syncTreeShadowStyle = (treeHost, styleAttribute, css) => {
1630
1625
  if (!existingStyle) shadowRoot.append(style);
1631
1626
  return true;
1632
1627
  };
1628
+ [...[..."abcdefghijklmnopqrstuvwxyz"].map((letter) => `Key${letter.toUpperCase()}`), ..."1234567890".split("").map((digit) => `Digit${digit}`)];
1629
+ const codeForCharacter = (character, shiftKey) => null;
1630
+ const shiftedCharacterForCode = (code) => null;
1631
+ const hasKeyboardLayout = () => false;
1633
1632
  //#endregion
1634
1633
  //#region config/keymap.ts
1635
1634
  const isMac = () => navigator.platform.toLowerCase().includes("mac");
1635
+ const unshiftedPunctuationCodes = {
1636
+ "-": "Minus",
1637
+ ",": "Comma",
1638
+ ";": "Semicolon",
1639
+ ".": "Period",
1640
+ "'": "Quote",
1641
+ "[": "BracketLeft",
1642
+ "]": "BracketRight",
1643
+ "/": "Slash",
1644
+ "\\": "Backslash",
1645
+ "`": "Backquote",
1646
+ "=": "Equal"
1647
+ };
1648
+ const shiftedPunctuationCodes = {
1649
+ _: "Minus",
1650
+ ":": "Semicolon",
1651
+ "!": "Digit1",
1652
+ "?": "Slash",
1653
+ "\"": "Quote",
1654
+ "(": "Digit9",
1655
+ ")": "Digit0",
1656
+ "{": "BracketLeft",
1657
+ "}": "BracketRight",
1658
+ "@": "Digit2",
1659
+ "*": "Digit8",
1660
+ "&": "Digit7",
1661
+ "#": "Digit3",
1662
+ "%": "Digit5",
1663
+ "^": "Digit6",
1664
+ "+": "Equal",
1665
+ "<": "Comma",
1666
+ ">": "Period",
1667
+ "|": "Backslash",
1668
+ "~": "Backquote",
1669
+ $: "Digit4"
1670
+ };
1671
+ const physicalCode = (key, shiftKey) => {
1672
+ const layoutCode = codeForCharacter(key, shiftKey);
1673
+ if (layoutCode !== null) return layoutCode;
1674
+ if (hasKeyboardLayout()) return null;
1675
+ if (/^[a-z]$/.test(key)) return `Key${key.toUpperCase()}`;
1676
+ if (/^[0-9]$/.test(key)) return shiftKey ? null : `Digit${key}`;
1677
+ return (shiftKey ? shiftedPunctuationCodes : unshiftedPunctuationCodes)[key] ?? null;
1678
+ };
1679
+ const resolveComboKey = (spelled, shiftKey) => {
1680
+ if (!shiftKey || spelled.length !== 1 || !hasKeyboardLayout()) return {
1681
+ code: physicalCode(spelled, shiftKey),
1682
+ key: spelled,
1683
+ requiresCode: false
1684
+ };
1685
+ const shiftedCode = codeForCharacter(spelled, true);
1686
+ if (shiftedCode !== null) return {
1687
+ code: shiftedCode,
1688
+ key: spelled,
1689
+ requiresCode: false
1690
+ };
1691
+ const unshiftedCode = codeForCharacter(spelled, false);
1692
+ const shiftedCharacter = unshiftedCode === null ? null : shiftedCharacterForCode(unshiftedCode);
1693
+ if (unshiftedCode !== null && shiftedCharacter !== null) return {
1694
+ code: unshiftedCode,
1695
+ key: shiftedCharacter,
1696
+ requiresCode: true
1697
+ };
1698
+ return {
1699
+ code: null,
1700
+ key: spelled,
1701
+ requiresCode: false
1702
+ };
1703
+ };
1636
1704
  const parseKeyCombo = (combo) => {
1637
1705
  const parts = combo.split("+").map((part) => part.trim().toLowerCase());
1638
1706
  const mac = isMac();
1707
+ const shiftKey = parts.includes("shift");
1708
+ const { code, key, requiresCode } = resolveComboKey(parts.find((part) => part !== "mod" && part !== "ctrl" && part !== "alt" && part !== "shift" && part !== "meta") ?? "", shiftKey);
1639
1709
  return {
1640
1710
  altKey: parts.includes("alt"),
1711
+ code,
1641
1712
  ctrlKey: mac ? parts.includes("ctrl") : parts.includes("mod") || parts.includes("ctrl"),
1642
- key: parts.find((part) => part !== "mod" && part !== "ctrl" && part !== "alt" && part !== "shift" && part !== "meta") ?? "",
1713
+ key,
1643
1714
  metaKey: mac ? parts.includes("mod") || parts.includes("meta") : parts.includes("meta"),
1644
- shiftKey: parts.includes("shift")
1715
+ requiresCode,
1716
+ shiftKey
1645
1717
  };
1646
1718
  };
1647
1719
  const getBindingCombos = (binding) => Array.isArray(binding) ? binding : [binding];
1648
- const matchesKeyCombo = (event, combo) => {
1720
+ const isDeadOrCharacterKey = (key) => key === "Dead" || key.length === 1;
1721
+ const matchesTypedKey = (event, parsed) => event.key.toLowerCase() === parsed.key && (!parsed.requiresCode || parsed.code !== null && event.code === parsed.code);
1722
+ const matchesPhysicalKey = (event, parsed) => parsed.altKey && parsed.code !== null && event.code === parsed.code;
1723
+ const matchesCombo = (event, combo, matchesKey) => {
1649
1724
  const parsed = parseKeyCombo(combo);
1650
- return event.key.toLowerCase() === parsed.key && event.altKey === parsed.altKey && event.ctrlKey === parsed.ctrlKey && event.metaKey === parsed.metaKey && event.shiftKey === parsed.shiftKey;
1725
+ return matchesKey(event, parsed) && event.altKey === parsed.altKey && event.ctrlKey === parsed.ctrlKey && event.metaKey === parsed.metaKey && event.shiftKey === parsed.shiftKey;
1651
1726
  };
1652
- const matchesShortcut = (event, keymap, action) => getBindingCombos(keymap[action]).some((combo) => matchesKeyCombo(event, combo));
1727
+ const matchesBinding = (event, binding, matchesKey) => getBindingCombos(binding).some((combo) => matchesCombo(event, combo, matchesKey));
1728
+ const canFallBackToPhysicalKey = (event, keymap) => event.altKey && isMac() && isDeadOrCharacterKey(event.key) && !Object.values(keymap).some((binding) => matchesBinding(event, binding, matchesTypedKey));
1729
+ const matchesShortcut = (event, keymap, action) => matchesBinding(event, keymap[action], matchesTypedKey) || canFallBackToPhysicalKey(event, keymap) && matchesBinding(event, keymap[action], matchesPhysicalKey);
1653
1730
  //#endregion
1654
1731
  //#region app/components/merge-request/GeneralComments.tsx
1655
1732
  const getAuthorDisplayName = (author) => author.name || author.login;
@@ -6999,6 +7076,70 @@ function ReviewCodeView({ activeSearchMatch, agentId, agentLabel, allowViewedTog
6999
7076
  });
7000
7077
  }
7001
7078
  //#endregion
7079
+ //#region app/components/ReviewTopBar.tsx
7080
+ function ReviewTopBar({ actions, context, leading, mode, modes, onModeChange, onToggleSidebar, repository, repositoryTooltip, sidebarCollapsed, sourceMenu, toggleTitle }) {
7081
+ return /* @__PURE__ */ jsxs("header", {
7082
+ className: "review-top-bar workspace-top-bar",
7083
+ children: [
7084
+ /* @__PURE__ */ jsxs("div", {
7085
+ className: "review-top-bar-left",
7086
+ children: [
7087
+ leading,
7088
+ /* @__PURE__ */ jsx("button", {
7089
+ "aria-label": sidebarCollapsed ? "Expand sidebar" : "Collapse sidebar",
7090
+ className: "review-top-bar-icon-button sidebar-toggle-button",
7091
+ onClick: onToggleSidebar,
7092
+ title: toggleTitle,
7093
+ type: "button",
7094
+ children: /* @__PURE__ */ jsx(SidebarSimpleIcon, {
7095
+ "aria-hidden": true,
7096
+ size: 18,
7097
+ weight: "bold"
7098
+ })
7099
+ }),
7100
+ sourceMenu,
7101
+ /* @__PURE__ */ jsx("div", {
7102
+ className: "review-top-bar-repository-slot",
7103
+ title: repositoryTooltip,
7104
+ children: repository
7105
+ })
7106
+ ]
7107
+ }),
7108
+ /* @__PURE__ */ jsx("div", {
7109
+ "aria-label": "Review mode",
7110
+ className: "review-mode-control",
7111
+ role: "tablist",
7112
+ children: modes.map((item) => /* @__PURE__ */ jsxs("button", {
7113
+ "aria-label": item.ariaLabel,
7114
+ "aria-selected": mode === item.value,
7115
+ onClick: () => onModeChange(item.value),
7116
+ role: "tab",
7117
+ title: item.title,
7118
+ type: "button",
7119
+ children: [
7120
+ item.icon,
7121
+ /* @__PURE__ */ jsx("span", {
7122
+ className: "review-mode-label",
7123
+ children: item.label
7124
+ }),
7125
+ item.indicator
7126
+ ]
7127
+ }, item.value))
7128
+ }),
7129
+ /* @__PURE__ */ jsxs("div", {
7130
+ className: "review-top-bar-right",
7131
+ children: [context ? /* @__PURE__ */ jsx("div", {
7132
+ className: "review-top-bar-context",
7133
+ children: context
7134
+ }) : null, actions ? /* @__PURE__ */ jsx("div", {
7135
+ className: "review-top-bar-actions",
7136
+ children: actions
7137
+ }) : null]
7138
+ })
7139
+ ]
7140
+ });
7141
+ }
7142
+ //#endregion
7002
7143
  //#region app/components/walkthrough/CommitView.tsx
7003
7144
  const TERMINAL_COLS = 80;
7004
7145
  const TERMINAL_ROWS = 12;
@@ -8586,6 +8727,7 @@ function useReviewFileState({ initialSelectedPath = null, onViewedChange } = {})
8586
8727
  const defaultConfigTemplate = {
8587
8728
  settings: {
8588
8729
  "agentBackend": "codex",
8730
+ "checkForUpdates": true,
8589
8731
  "claudeModel": "claude-sonnet-4-6",
8590
8732
  "codeFontFamily": "",
8591
8733
  "codeFontSize": 13,
@@ -8686,7 +8828,7 @@ const disabledCommitMessage = async () => ({
8686
8828
  reason: "Shared walkthroughs are read-only.",
8687
8829
  status: "unavailable"
8688
8830
  });
8689
- function ReviewSurface({ commenting, externalUrl, gitIdentity = null, initialMode, interactive, onDeleteShare, onModeChange, providerLabel = "provider", settingsBar, signInLabel = "Sign in to comment", snapshot, sourceDescriptionFooterAside, title }) {
8831
+ function ReviewSurface({ commenting, externalUrl, gitIdentity = null, initialMode, interactive, onDeleteShare, onModeChange, providerLabel = "provider", repositoryUrl, settingsBar, signInLabel = "Sign in to comment", snapshot, sourceDescriptionFooterAside, title }) {
8690
8832
  const canComment = commenting?.canComment ?? Boolean(interactive);
8691
8833
  const deleteShare = useCallback(async () => {
8692
8834
  if (!onDeleteShare || !window.confirm("Delete this shared walkthrough? This cannot be undone.")) return;
@@ -8709,10 +8851,22 @@ function ReviewSurface({ commenting, externalUrl, gitIdentity = null, initialMod
8709
8851
  const keymap = useMemo(() => createDefaultConfig().keymap, []);
8710
8852
  const [fileSearchQuery, setFileSearchQuery] = useState("");
8711
8853
  const [uncontrolledSidebarMode, setUncontrolledSidebarMode] = useState(() => initialMode ?? (interactive ? "tree" : "walkthrough"));
8712
- const sidebarMode = Boolean(initialMode && onModeChange) ? initialMode : uncontrolledSidebarMode;
8854
+ const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
8855
+ useEffect(() => {
8856
+ const handleKeyDown = (event) => {
8857
+ if (event.repeat || !matchesShortcut(event, keymap, "toggleSidebar")) return;
8858
+ event.preventDefault();
8859
+ setSidebarCollapsed((current) => !current);
8860
+ };
8861
+ window.addEventListener("keydown", handleKeyDown);
8862
+ return () => window.removeEventListener("keydown", handleKeyDown);
8863
+ }, [keymap]);
8864
+ const sidebarMode = Boolean(initialMode && onModeChange) && initialMode ? initialMode : uncontrolledSidebarMode;
8713
8865
  const [treeScrollTarget, setTreeScrollTarget] = useState(null);
8714
8866
  const { bumpItemVersion, collapsed, expandedGenerated, itemVersionByKey, selectedPath, setSelectedPath, toggleCollapsed, toggleViewed, viewed } = useReviewFileState({ initialSelectedPath: snapshot.files[0]?.path ?? null });
8715
8867
  const { resizeSidebar, sidebarWidth } = useResizableSidebar({
8868
+ collapseThreshold: 80,
8869
+ onCollapse: () => setSidebarCollapsed(true),
8716
8870
  onWidthCommit: writeSharedSidebarWidth,
8717
8871
  readWidth: readSharedSidebarWidth
8718
8872
  });
@@ -9102,8 +9256,10 @@ function ReviewSurface({ commenting, externalUrl, gitIdentity = null, initialMod
9102
9256
  sourceDescriptionFooter
9103
9257
  });
9104
9258
  };
9105
- const sourceLabel = snapshot.repository.source.type === "working-tree" ? "" : ` · ${getSourceLabel(snapshot.repository.source)}`;
9106
- const rootLabel = `${compactPath(snapshot.repository.root)}${snapshot.branch ? ` (${snapshot.branch})` : ""}`;
9259
+ const sourceLabel = snapshot.repository.source.type === "working-tree" ? null : getSourceLabel(snapshot.repository.source);
9260
+ const rootLabel = repositoryUrl ? snapshot.repository.root : abbreviateHomePath(snapshot.repository.root);
9261
+ const sourceExternalUrl = snapshot.repository.source.type === "pull-request" ? externalUrl ?? snapshot.repository.source.url : null;
9262
+ const repositoryLinkUrl = repositoryUrl ?? sourceExternalUrl;
9107
9263
  const walkthroughStatus = walkthroughRequestPending && interactive?.walkthroughStatus !== "ready" ? "generating" : interactive?.walkthroughStatus;
9108
9264
  const [walkthroughProgressRevision, setWalkthroughProgressRevision] = useState(0);
9109
9265
  const previousWalkthroughStatusRef = useRef(walkthroughStatus);
@@ -9119,57 +9275,120 @@ function ReviewSurface({ commenting, externalUrl, gitIdentity = null, initialMod
9119
9275
  const requestWalkthrough = () => {
9120
9276
  startWalkthroughGeneration();
9121
9277
  };
9278
+ const reviewModes = [
9279
+ {
9280
+ icon: /* @__PURE__ */ jsx(PathIcon, {
9281
+ "aria-hidden": true,
9282
+ size: 14,
9283
+ weight: "bold"
9284
+ }),
9285
+ label: "Walkthrough",
9286
+ value: "walkthrough"
9287
+ },
9288
+ {
9289
+ icon: /* @__PURE__ */ jsx(TreeStructureIcon, {
9290
+ "aria-hidden": true,
9291
+ size: 14,
9292
+ weight: "bold"
9293
+ }),
9294
+ label: "Tree",
9295
+ value: "tree"
9296
+ },
9297
+ ...showCommentsTab ? [{
9298
+ ariaLabel: generalCommentCount > 0 ? `Comments (${generalCommentCount})` : "Comments",
9299
+ icon: /* @__PURE__ */ jsx(ChatCircleIcon, {
9300
+ "aria-hidden": true,
9301
+ size: 14,
9302
+ weight: "bold"
9303
+ }),
9304
+ indicator: generalCommentCount > 0 ? /* @__PURE__ */ jsx("span", {
9305
+ "aria-hidden": true,
9306
+ className: "review-mode-count",
9307
+ children: generalCommentCount
9308
+ }) : void 0,
9309
+ label: "Comments",
9310
+ title: generalCommentCount > 0 ? `${generalCommentCount} ${generalCommentCount === 1 ? "comment" : "comments"}` : "Comments",
9311
+ value: "comments"
9312
+ }] : []
9313
+ ];
9314
+ const topBarActions = onDeleteShare || settingsBar ? /* @__PURE__ */ jsxs(Fragment$1, { children: [onDeleteShare ? /* @__PURE__ */ jsx(Button, {
9315
+ action: deleteShare,
9316
+ "aria-label": "Delete shared walkthrough",
9317
+ pendingPlaceholder: "…",
9318
+ size: "icon",
9319
+ title: "Delete shared walkthrough",
9320
+ type: "button",
9321
+ variant: "destructive",
9322
+ children: /* @__PURE__ */ jsx(Trash2, {
9323
+ "aria-hidden": true,
9324
+ size: 16
9325
+ })
9326
+ }) : null, settingsBar ? /* @__PURE__ */ jsx("div", {
9327
+ className: "review-top-bar-settings",
9328
+ children: settingsBar
9329
+ }) : null] }) : void 0;
9122
9330
  return /* @__PURE__ */ jsxs("div", {
9123
- className: `app-shell share-shell${interactive ? " merge-request-shell" : ""}`,
9331
+ className: `app-shell share-shell${interactive ? " merge-request-shell" : ""}${sidebarCollapsed ? " sidebar-collapsed" : ""}`,
9124
9332
  "data-theme": shellTheme,
9125
- style: { gridTemplateColumns: `${sidebarWidth}px 0 minmax(0, 1fr)` },
9333
+ style: sidebarCollapsed ? void 0 : { gridTemplateColumns: `${sidebarWidth}px 0 minmax(0, 1fr)` },
9126
9334
  children: [
9335
+ /* @__PURE__ */ jsx(ReviewTopBar, {
9336
+ actions: topBarActions,
9337
+ context: /* @__PURE__ */ jsxs(Fragment$1, { children: [snapshot.branch ? /* @__PURE__ */ jsx("span", {
9338
+ className: "review-top-bar-branch",
9339
+ title: snapshot.branch,
9340
+ children: snapshot.branch
9341
+ }) : null, sourceLabel ? sourceExternalUrl ? /* @__PURE__ */ jsxs("a", {
9342
+ "aria-label": `Open ${sourceLabel} in ${providerLabel}`,
9343
+ className: "review-top-bar-source",
9344
+ href: sourceExternalUrl,
9345
+ rel: "noreferrer",
9346
+ target: "_blank",
9347
+ title: `Open ${sourceLabel} in ${providerLabel}`,
9348
+ children: [/* @__PURE__ */ jsx("span", { children: sourceLabel }), /* @__PURE__ */ jsx(ArrowSquareOutIcon, {
9349
+ "aria-hidden": true,
9350
+ size: 14,
9351
+ weight: "bold"
9352
+ })]
9353
+ }) : /* @__PURE__ */ jsx("span", {
9354
+ className: "review-top-bar-source",
9355
+ children: sourceLabel
9356
+ }) : null] }),
9357
+ leading: interactive ? /* @__PURE__ */ jsx("button", {
9358
+ "aria-label": "Back to Codiff",
9359
+ className: "merge-request-nav-button merge-request-home-button",
9360
+ onClick: interactive.onHome,
9361
+ title: "Back to Codiff",
9362
+ type: "button",
9363
+ children: /* @__PURE__ */ jsx("img", {
9364
+ alt: "",
9365
+ "aria-hidden": true,
9366
+ className: "merge-request-nav-icon",
9367
+ draggable: false,
9368
+ src: "/icon.png"
9369
+ })
9370
+ }) : void 0,
9371
+ mode: sidebarMode,
9372
+ modes: reviewModes,
9373
+ onModeChange: changeSidebarMode,
9374
+ onToggleSidebar: () => setSidebarCollapsed((current) => !current),
9375
+ repository: repositoryLinkUrl ? /* @__PURE__ */ jsx("a", {
9376
+ className: "review-top-bar-repository",
9377
+ href: repositoryLinkUrl,
9378
+ rel: "noreferrer",
9379
+ target: repositoryUrl ? void 0 : "_blank",
9380
+ children: rootLabel
9381
+ }) : /* @__PURE__ */ jsx("span", {
9382
+ className: "review-top-bar-repository",
9383
+ children: rootLabel
9384
+ }),
9385
+ repositoryTooltip: snapshot.repository.root,
9386
+ sidebarCollapsed,
9387
+ toggleTitle: `${sidebarCollapsed ? "Expand" : "Collapse"} sidebar`
9388
+ }),
9127
9389
  /* @__PURE__ */ jsxs("aside", {
9128
9390
  className: "squircle sidebar",
9129
9391
  children: [
9130
- /* @__PURE__ */ jsx("div", {
9131
- className: "sidebar-header",
9132
- children: /* @__PURE__ */ jsxs("div", {
9133
- className: "sidebar-path-row",
9134
- children: [
9135
- interactive ? /* @__PURE__ */ jsx("button", {
9136
- "aria-label": "Back to Codiff",
9137
- className: "merge-request-nav-button merge-request-home-button",
9138
- onClick: interactive.onHome,
9139
- title: "Back to Codiff",
9140
- type: "button",
9141
- children: /* @__PURE__ */ jsx("img", {
9142
- alt: "",
9143
- "aria-hidden": true,
9144
- className: "merge-request-nav-icon",
9145
- draggable: false,
9146
- src: "/icon.png"
9147
- })
9148
- }) : null,
9149
- /* @__PURE__ */ jsxs("div", {
9150
- className: "sidebar-path",
9151
- title: title ?? snapshot.repository.root,
9152
- children: [
9153
- title ? `${title} · ` : null,
9154
- rootLabel,
9155
- sourceLabel
9156
- ]
9157
- }),
9158
- externalUrl ? /* @__PURE__ */ jsx("a", {
9159
- "aria-label": `Open merge request in ${providerLabel}`,
9160
- className: "merge-request-nav-button",
9161
- href: externalUrl,
9162
- rel: "noreferrer",
9163
- target: "_blank",
9164
- title: `Open merge request in ${providerLabel}`,
9165
- children: /* @__PURE__ */ jsx(ExternalLink, {
9166
- "aria-hidden": true,
9167
- size: 16
9168
- })
9169
- }) : null
9170
- ]
9171
- })
9172
- }),
9173
9392
  /* @__PURE__ */ jsx("div", {
9174
9393
  className: "sidebar-search-row",
9175
9394
  children: /* @__PURE__ */ jsx("input", {
@@ -9182,40 +9401,6 @@ function ReviewSurface({ commenting, externalUrl, gitIdentity = null, initialMod
9182
9401
  value: fileSearchQuery
9183
9402
  })
9184
9403
  }),
9185
- /* @__PURE__ */ jsxs("div", {
9186
- "aria-label": "Review order",
9187
- className: `sidebar-mode-toggle${showCommentsTab ? " sidebar-mode-toggle-with-comments" : ""}`,
9188
- role: "tablist",
9189
- children: [
9190
- /* @__PURE__ */ jsx("button", {
9191
- "aria-selected": sidebarMode === "tree",
9192
- onClick: () => changeSidebarMode("tree"),
9193
- role: "tab",
9194
- type: "button",
9195
- children: "Tree"
9196
- }),
9197
- /* @__PURE__ */ jsx("button", {
9198
- "aria-selected": sidebarMode === "walkthrough",
9199
- onClick: () => changeSidebarMode("walkthrough"),
9200
- role: "tab",
9201
- type: "button",
9202
- children: "Walkthrough"
9203
- }),
9204
- showCommentsTab ? /* @__PURE__ */ jsxs("button", {
9205
- "aria-label": generalCommentCount > 0 ? `Comments (${generalCommentCount})` : "Comments",
9206
- "aria-selected": sidebarMode === "comments",
9207
- onClick: () => changeSidebarMode("comments"),
9208
- role: "tab",
9209
- title: generalCommentCount > 0 ? `${generalCommentCount} ${generalCommentCount === 1 ? "comment" : "comments"}` : "Comments",
9210
- type: "button",
9211
- children: [/* @__PURE__ */ jsx("span", { children: "Comments" }), generalCommentCount > 0 ? /* @__PURE__ */ jsx("span", {
9212
- "aria-hidden": true,
9213
- className: "sidebar-tab-count",
9214
- children: generalCommentCount
9215
- }) : null]
9216
- }) : null
9217
- ]
9218
- }),
9219
9404
  sidebarMode === "tree" ? /* @__PURE__ */ jsx(ReviewFileTree, {
9220
9405
  files: visibleFiles,
9221
9406
  onActivatePath: activateTreePath,
@@ -9243,29 +9428,13 @@ function ReviewSurface({ commenting, externalUrl, gitIdentity = null, initialMod
9243
9428
  }), walkthroughStatusDescription ? /* @__PURE__ */ jsx("span", { children: walkthroughStatusDescription }) : null]
9244
9429
  })
9245
9430
  }),
9246
- onDeleteShare || settingsBar || showTotalLineCount ? /* @__PURE__ */ jsxs("div", {
9431
+ showTotalLineCount ? /* @__PURE__ */ jsx("div", {
9247
9432
  className: "sidebar-settings-bar",
9248
- children: [
9249
- onDeleteShare ? /* @__PURE__ */ jsx(Button, {
9250
- action: deleteShare,
9251
- "aria-label": "Delete shared walkthrough",
9252
- pendingPlaceholder: "…",
9253
- size: "icon",
9254
- title: "Delete shared walkthrough",
9255
- type: "button",
9256
- variant: "destructive",
9257
- children: /* @__PURE__ */ jsx(Trash2, {
9258
- "aria-hidden": true,
9259
- size: 16
9260
- })
9261
- }) : null,
9262
- settingsBar,
9263
- showTotalLineCount ? /* @__PURE__ */ jsx(DiffLineCountBadge, {
9264
- ariaLabelPrefix: "Total change",
9265
- className: "sidebar-total-line-count sidebar-settings-line-count",
9266
- lineCount: totalLineCount
9267
- }) : null
9268
- ]
9433
+ children: /* @__PURE__ */ jsx(DiffLineCountBadge, {
9434
+ ariaLabelPrefix: "Total change",
9435
+ className: "sidebar-total-line-count sidebar-settings-line-count",
9436
+ lineCount: totalLineCount
9437
+ })
9269
9438
  }) : null
9270
9439
  ]
9271
9440
  }),