@industry-theme/file-city-panel 0.5.70 → 0.5.71

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.
@@ -257703,7 +257703,7 @@ const TrailLeaderLine = React.forwardRef(function TrailLeaderLine2({ containerRe
257703
257703
  const HEADER_BAND_OFFSET = 22;
257704
257704
  const bx = nodeRect.left - containerRect.left;
257705
257705
  const by = nodeRect.top - containerRect.top + HEADER_BAND_OFFSET;
257706
- const ELBOW_GAP = 60;
257706
+ const ELBOW_GAP = 30;
257707
257707
  const CORNER_RADIUS = 14;
257708
257708
  const elbowX = Math.max(
257709
257709
  canvasLeft + 8,
@@ -257806,6 +257806,7 @@ const TrailLeaderLine = React.forwardRef(function TrailLeaderLine2({ containerRe
257806
257806
  )
257807
257807
  ] });
257808
257808
  });
257809
+ const CALLOUT_FADE_IN_MS = 350;
257809
257810
  const fileBasename = (path2) => {
257810
257811
  const i = path2.lastIndexOf("/");
257811
257812
  return i >= 0 ? path2.slice(i + 1) : path2;
@@ -257817,8 +257818,10 @@ const fileDirname = (path2) => {
257817
257818
  const TrailFilePath = React.forwardRef(function TrailFilePath2({
257818
257819
  containerRef,
257819
257820
  buildings,
257821
+ markerTitles,
257820
257822
  cityCenter,
257821
257823
  animate: animate2 = true,
257824
+ currentStepIndex = null,
257822
257825
  stepMs = 1100,
257823
257826
  dwellMs = 1400,
257824
257827
  endHoldMs = 2200
@@ -257828,7 +257831,9 @@ const TrailFilePath = React.forwardRef(function TrailFilePath2({
257828
257831
  const fontFamily = theme2.fonts.body;
257829
257832
  const calloutFontSize = String(theme2.fontSizes[1] ?? 14);
257830
257833
  const calloutFontWeight = String(theme2.fontWeights.semibold ?? 600);
257831
- const calloutLineDy = String(Math.round((theme2.fontSizes[1] ?? 14) * 1.45));
257834
+ const calloutBodyFontWeight = String(theme2.fontWeights.body ?? 400);
257835
+ const calloutLineDyPx = Math.round((theme2.fontSizes[1] ?? 14) * 1.45);
257836
+ const calloutLineDy = String(calloutLineDyPx);
257832
257837
  const surfaceColor = theme2.colors.backgroundSecondary ?? "#0f1419";
257833
257838
  const filenameColor = theme2.colors.text ?? "#f8fafc";
257834
257839
  const dirColor = theme2.colors.textMuted ?? "#94a3b8";
@@ -257841,13 +257846,21 @@ const TrailFilePath = React.forwardRef(function TrailFilePath2({
257841
257846
  typeof performance !== "undefined" ? performance.now() : 0
257842
257847
  );
257843
257848
  const buildingsRef = React.useRef(buildings);
257849
+ const markerTitlesRef = React.useRef(markerTitles);
257844
257850
  const cityCenterRef = React.useRef(cityCenter);
257851
+ const currentStepIndexRef = React.useRef(currentStepIndex);
257845
257852
  React.useEffect(() => {
257846
257853
  buildingsRef.current = buildings;
257847
257854
  }, [buildings]);
257855
+ React.useEffect(() => {
257856
+ markerTitlesRef.current = markerTitles;
257857
+ }, [markerTitles]);
257848
257858
  React.useEffect(() => {
257849
257859
  cityCenterRef.current = cityCenter;
257850
257860
  }, [cityCenter]);
257861
+ React.useEffect(() => {
257862
+ currentStepIndexRef.current = currentStepIndex;
257863
+ }, [currentStepIndex]);
257851
257864
  const hideAll = React.useCallback(() => {
257852
257865
  const g2 = groupRef.current;
257853
257866
  if (!g2) return;
@@ -257861,6 +257874,7 @@ const TrailFilePath = React.forwardRef(function TrailFilePath2({
257861
257874
  }, [animate2, buildings, dwellMs, stepMs, endHoldMs]);
257862
257875
  const onCameraFrame = React.useCallback(
257863
257876
  (camera, size) => {
257877
+ var _a;
257864
257878
  const targets = buildingsRef.current;
257865
257879
  const center = cityCenterRef.current;
257866
257880
  const container = containerRef.current;
@@ -257892,11 +257906,16 @@ const TrailFilePath = React.forwardRef(function TrailFilePath2({
257892
257906
  const N = points.length;
257893
257907
  const slotMs = dwellMs + stepMs;
257894
257908
  const period = N >= 2 ? (N - 1) * slotMs + dwellMs + endHoldMs : 0;
257909
+ const rawFrozen = currentStepIndexRef.current;
257910
+ const frozenIndex = rawFrozen != null && rawFrozen >= 0 && rawFrozen < N ? rawFrozen : null;
257895
257911
  let revealedCount = animate2 ? 0 : N;
257896
257912
  let leadingTip = null;
257897
257913
  let traverseFrac = null;
257898
257914
  let dwellElapsed = 0;
257899
- if (animate2 && period > 0) {
257915
+ if (frozenIndex != null) {
257916
+ revealedCount = frozenIndex + 1;
257917
+ dwellElapsed = CALLOUT_FADE_IN_MS;
257918
+ } else if (animate2 && period > 0) {
257900
257919
  const elapsed = ((typeof performance !== "undefined" ? performance.now() : Date.now()) - animStartTsRef.current) % period;
257901
257920
  const traversalsEnd = (N - 1) * slotMs;
257902
257921
  if (elapsed >= traversalsEnd) {
@@ -258011,32 +258030,52 @@ const TrailFilePath = React.forwardRef(function TrailFilePath2({
258011
258030
  }
258012
258031
  }
258013
258032
  const SVG_NS = "http://www.w3.org/2000/svg";
258014
- const paintCallout = (textEl, bgEl, point2, path2, opacity) => {
258033
+ const paintCallout = (textEl, bgEl, point2, path2, title, opacity) => {
258015
258034
  if (!textEl || !bgEl) return;
258016
258035
  if (!point2 || !point2.visible || opacity <= 1e-3 || !path2) {
258017
258036
  textEl.setAttribute("opacity", "0");
258018
258037
  bgEl.setAttribute("opacity", "0");
258019
258038
  return;
258020
258039
  }
258021
- if (textEl.children.length < 2) {
258022
- while (textEl.firstChild) textEl.removeChild(textEl.firstChild);
258023
- textEl.appendChild(document.createElementNS(SVG_NS, "tspan"));
258040
+ while (textEl.children.length < 3) {
258024
258041
  textEl.appendChild(document.createElementNS(SVG_NS, "tspan"));
258025
258042
  }
258026
- const nameTspan = textEl.children[0];
258027
- const pathTspan = textEl.children[1];
258043
+ while (textEl.children.length > 3) {
258044
+ textEl.removeChild(textEl.lastChild);
258045
+ }
258046
+ const titleTspan = textEl.children[0];
258047
+ const nameTspan = textEl.children[1];
258048
+ const pathTspan = textEl.children[2];
258028
258049
  const name2 = fileBasename(path2);
258029
258050
  const dir = fileDirname(path2);
258030
- const nameLineY = point2.y - 44;
258051
+ const trimmedTitle = (title == null ? void 0 : title.trim()) ?? "";
258052
+ const lineCount = (trimmedTitle ? 1 : 0) + 1 + (dir ? 1 : 0);
258053
+ const BOTTOM_LINE_OFFSET = 24;
258054
+ const topLineY = point2.y - BOTTOM_LINE_OFFSET - (lineCount - 1) * calloutLineDyPx;
258031
258055
  textEl.setAttribute("text-anchor", "middle");
258032
258056
  textEl.setAttribute("font-family", fontFamily);
258033
258057
  textEl.setAttribute("opacity", String(opacity));
258058
+ titleTspan.textContent = trimmedTitle;
258059
+ titleTspan.setAttribute("x", String(point2.x));
258060
+ titleTspan.setAttribute("y", String(topLineY));
258061
+ titleTspan.setAttribute("fill", filenameColor);
258062
+ titleTspan.setAttribute("font-size", calloutFontSize);
258063
+ titleTspan.setAttribute("font-weight", calloutFontWeight);
258034
258064
  nameTspan.textContent = name2;
258035
258065
  nameTspan.setAttribute("x", String(point2.x));
258036
- nameTspan.setAttribute("y", String(nameLineY));
258037
- nameTspan.setAttribute("fill", filenameColor);
258066
+ nameTspan.setAttribute(
258067
+ "dy",
258068
+ trimmedTitle ? calloutLineDy : "0"
258069
+ );
258070
+ nameTspan.setAttribute(
258071
+ "fill",
258072
+ trimmedTitle ? dirColor : filenameColor
258073
+ );
258038
258074
  nameTspan.setAttribute("font-size", calloutFontSize);
258039
- nameTspan.setAttribute("font-weight", calloutFontWeight);
258075
+ nameTspan.setAttribute(
258076
+ "font-weight",
258077
+ trimmedTitle ? calloutBodyFontWeight : calloutFontWeight
258078
+ );
258040
258079
  pathTspan.textContent = dir;
258041
258080
  pathTspan.setAttribute("x", String(point2.x));
258042
258081
  pathTspan.setAttribute("dy", dir ? calloutLineDy : "0");
@@ -258056,14 +258095,15 @@ const TrailFilePath = React.forwardRef(function TrailFilePath2({
258056
258095
  bgEl.setAttribute("stroke-width", "1.5");
258057
258096
  bgEl.setAttribute("opacity", String(0.94 * opacity));
258058
258097
  };
258059
- const fadeInMs = 350;
258060
258098
  let calloutOpacity = 0;
258061
- if (animate2 && lastIndex >= 0 && lastIndex < targets.length) {
258099
+ if (frozenIndex != null && lastIndex >= 0) {
258100
+ calloutOpacity = 1;
258101
+ } else if (animate2 && lastIndex >= 0 && lastIndex < targets.length) {
258062
258102
  if (traverseFrac !== null) {
258063
258103
  const eased = traverseFrac * traverseFrac * (3 - 2 * traverseFrac);
258064
258104
  calloutOpacity = 1 - eased;
258065
258105
  } else {
258066
- const t = Math.min(1, dwellElapsed / fadeInMs);
258106
+ const t = Math.min(1, dwellElapsed / CALLOUT_FADE_IN_MS);
258067
258107
  calloutOpacity = t * t * (3 - 2 * t);
258068
258108
  }
258069
258109
  } else if (!animate2 && lastIndex >= 0) {
@@ -258074,6 +258114,7 @@ const TrailFilePath = React.forwardRef(function TrailFilePath2({
258074
258114
  calloutBgRef.current,
258075
258115
  lastIndex >= 0 ? points[lastIndex] : null,
258076
258116
  lastIndex >= 0 ? targets[lastIndex].path : null,
258117
+ lastIndex >= 0 ? ((_a = markerTitlesRef.current) == null ? void 0 : _a[lastIndex]) ?? null : null,
258077
258118
  calloutOpacity
258078
258119
  );
258079
258120
  g2.setAttribute("opacity", "1");
@@ -258089,7 +258130,9 @@ const TrailFilePath = React.forwardRef(function TrailFilePath2({
258089
258130
  fontFamily,
258090
258131
  calloutFontSize,
258091
258132
  calloutFontWeight,
258133
+ calloutBodyFontWeight,
258092
258134
  calloutLineDy,
258135
+ calloutLineDyPx,
258093
258136
  surfaceColor,
258094
258137
  filenameColor,
258095
258138
  dirColor
@@ -258126,6 +258169,7 @@ const RESIZE_HANDLE_WIDTH = 6;
258126
258169
  const TrailMarkdownOverlay = ({
258127
258170
  eyebrow,
258128
258171
  title,
258172
+ subtitle,
258129
258173
  markdown: markdown2,
258130
258174
  slideIdPrefix,
258131
258175
  bottomOffset,
@@ -258233,7 +258277,7 @@ const TrailMarkdownOverlay = ({
258233
258277
  to { transform: translateX(0); }
258234
258278
  }
258235
258279
  ` }),
258236
- eyebrow || title ? /* @__PURE__ */ jsxs(
258280
+ eyebrow || title || subtitle ? /* @__PURE__ */ jsxs(
258237
258281
  "div",
258238
258282
  {
258239
258283
  style: {
@@ -258272,6 +258316,22 @@ const TrailMarkdownOverlay = ({
258272
258316
  title,
258273
258317
  children: title
258274
258318
  }
258319
+ ) : null,
258320
+ subtitle ? /* @__PURE__ */ jsx(
258321
+ "span",
258322
+ {
258323
+ style: {
258324
+ fontSize: theme2.fontSizes[0],
258325
+ color: theme2.colors.textSecondary,
258326
+ fontFamily: theme2.fonts.monospace,
258327
+ overflow: "hidden",
258328
+ textOverflow: "ellipsis",
258329
+ whiteSpace: "nowrap",
258330
+ marginTop: 2
258331
+ },
258332
+ title: subtitle,
258333
+ children: subtitle
258334
+ }
258275
258335
  ) : null
258276
258336
  ]
258277
258337
  }
@@ -258675,32 +258735,15 @@ const TrailSnippetView = ({
258675
258735
  if (!fileObject || !slice) {
258676
258736
  return /* @__PURE__ */ jsx("div", { style: { padding: 16, color: theme2.colors.textSecondary }, children: "Loading…" });
258677
258737
  }
258678
- const rangeLabel = slice.sliceStart === slice.sliceEnd ? `Line ${slice.sliceStart}` : `Lines ${slice.sliceStart}–${slice.sliceEnd}`;
258679
- return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", minHeight: 0 }, children: [
258680
- /* @__PURE__ */ jsx(
258681
- "div",
258682
- {
258683
- style: {
258684
- padding: "4px 14px 6px",
258685
- fontFamily: theme2.fonts.monospace,
258686
- fontSize: theme2.fontSizes[0],
258687
- color: theme2.colors.textSecondary,
258688
- letterSpacing: 0.4,
258689
- textTransform: "uppercase"
258690
- },
258691
- children: rangeLabel
258692
- }
258693
- ),
258694
- /* @__PURE__ */ jsx(
258695
- File$2,
258696
- {
258697
- file: fileObject,
258698
- options,
258699
- selectedLines: slice.focusOffset != null ? { start: slice.focusOffset, end: slice.focusOffset } : void 0,
258700
- style: pierreStyle$1
258701
- }
258702
- )
258703
- ] });
258738
+ return /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", minHeight: 0 }, children: /* @__PURE__ */ jsx(
258739
+ File$2,
258740
+ {
258741
+ file: fileObject,
258742
+ options,
258743
+ selectedLines: slice.focusOffset != null ? { start: slice.focusOffset, end: slice.focusOffset } : void 0,
258744
+ style: pierreStyle$1
258745
+ }
258746
+ ) });
258704
258747
  };
258705
258748
  const buildBackgroundCSS = (color2) => `
258706
258749
  :host {
@@ -258825,40 +258868,23 @@ const TrailDiffSnippetView = ({
258825
258868
  if (!fileDiff) {
258826
258869
  return /* @__PURE__ */ jsx("div", { style: { padding: 16, color: theme2.colors.error }, children: "Failed to compute diff" });
258827
258870
  }
258828
- const rangeLabel = startLine != null && endLine != null ? startLine === endLine ? `Line ${startLine}` : `Lines ${startLine}–${endLine}` : null;
258829
- return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", minHeight: 0 }, children: [
258830
- rangeLabel && /* @__PURE__ */ jsx(
258831
- "div",
258832
- {
258833
- style: {
258834
- padding: "4px 14px 6px",
258835
- fontFamily: theme2.fonts.monospace,
258836
- fontSize: theme2.fontSizes[0],
258837
- color: theme2.colors.textSecondary,
258838
- letterSpacing: 0.4,
258839
- textTransform: "uppercase"
258840
- },
258841
- children: rangeLabel
258842
- }
258843
- ),
258844
- /* @__PURE__ */ jsx(
258845
- FileDiff$2,
258846
- {
258847
- fileDiff,
258848
- options: { ...pierreOptionsBase, diffStyle },
258849
- selectedLines: slice.focusOffset != null ? { start: slice.focusOffset, end: slice.focusOffset } : void 0,
258850
- style: background ? {
258851
- ...pierreStyle,
258852
- // Pierre derives addition/deletion/context surfaces by
258853
- // `color-mix`ing from --diffs-bg, which is keyed off
258854
- // --diffs-light-bg / --diffs-dark-bg. Overriding the
258855
- // source variables recolors the whole palette coherently.
258856
- ["--diffs-light-bg"]: background,
258857
- ["--diffs-dark-bg"]: background
258858
- } : pierreStyle
258859
- }
258860
- )
258861
- ] });
258871
+ return /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", minHeight: 0 }, children: /* @__PURE__ */ jsx(
258872
+ FileDiff$2,
258873
+ {
258874
+ fileDiff,
258875
+ options: { ...pierreOptionsBase, diffStyle },
258876
+ selectedLines: slice.focusOffset != null ? { start: slice.focusOffset, end: slice.focusOffset } : void 0,
258877
+ style: background ? {
258878
+ ...pierreStyle,
258879
+ // Pierre derives addition/deletion/context surfaces by
258880
+ // `color-mix`ing from --diffs-bg, which is keyed off
258881
+ // --diffs-light-bg / --diffs-dark-bg. Overriding the
258882
+ // source variables recolors the whole palette coherently.
258883
+ ["--diffs-light-bg"]: background,
258884
+ ["--diffs-dark-bg"]: background
258885
+ } : pierreStyle
258886
+ }
258887
+ ) });
258862
258888
  };
258863
258889
  const pierreOptionsBase = {
258864
258890
  disableFileHeader: true
@@ -258867,10 +258893,11 @@ const pierreStyle = {
258867
258893
  display: "block"
258868
258894
  };
258869
258895
  const SEQUENCE_DRAWER_HEIGHT_PCT = 45;
258870
- const SNIPPET_PANE_WIDTH_PX = 460;
258896
+ const SNIPPET_PANE_RIGHT_GUTTER_PX = 16;
258897
+ const SNIPPET_PANE_LEADER_BUFFER_PX = 60;
258871
258898
  const PANEL_TRANSITION_MS = 280;
258872
258899
  const THREE_D_TOGGLE_DISABLED = true;
258873
- const FileCityTrailExplorerPanel = ({ context, actions }) => {
258900
+ const FileCityTrailExplorerPanel = ({ context, actions, defaultViewMode, defaultShowSequenceDrawer }) => {
258874
258901
  var _a;
258875
258902
  const tree = context.fileTree.data;
258876
258903
  const lineCounts = ((_a = context.lineCounts.data) == null ? void 0 : _a.lineCounts) ?? null;
@@ -258926,7 +258953,9 @@ const FileCityTrailExplorerPanel = ({ context, actions }) => {
258926
258953
  onSelectMarker: setSelectedMarkerId,
258927
258954
  cityData,
258928
258955
  hasLineCounts: lineCounts != null && Object.keys(lineCounts).length > 0,
258929
- readFile: actions.readFile
258956
+ readFile: actions.readFile,
258957
+ defaultViewMode,
258958
+ defaultShowSequenceDrawer
258930
258959
  }
258931
258960
  );
258932
258961
  };
@@ -258938,7 +258967,9 @@ const FileCityTrailSequenceLayout = ({
258938
258967
  onSelectMarker,
258939
258968
  cityData,
258940
258969
  hasLineCounts,
258941
- readFile
258970
+ readFile,
258971
+ defaultViewMode = "city",
258972
+ defaultShowSequenceDrawer = true
258942
258973
  }) => {
258943
258974
  var _a, _b;
258944
258975
  const { theme: theme2 } = useTheme();
@@ -258949,8 +258980,12 @@ const FileCityTrailSequenceLayout = ({
258949
258980
  return;
258950
258981
  }, [hasLineCounts]);
258951
258982
  const effectiveShow3D = false;
258952
- const [viewMode, setViewMode] = React.useState("city");
258953
- const [showSequenceDrawer, setShowSequenceDrawer] = React.useState(true);
258983
+ const [viewMode, setViewMode] = React.useState(
258984
+ defaultViewMode
258985
+ );
258986
+ const [showSequenceDrawer, setShowSequenceDrawer] = React.useState(
258987
+ defaultShowSequenceDrawer
258988
+ );
258954
258989
  const [drawerHeightOverridePct, setDrawerHeightOverridePct] = React.useState(null);
258955
258990
  const [isResizingDrawer, setIsResizingDrawer] = React.useState(false);
258956
258991
  const drawerHeightPct = !showSequenceDrawer ? 0 : drawerHeightOverridePct ?? SEQUENCE_DRAWER_HEIGHT_PCT;
@@ -259117,17 +259152,43 @@ const FileCityTrailSequenceLayout = ({
259117
259152
  z: (cityData.bounds.minZ + cityData.bounds.maxZ) / 2
259118
259153
  };
259119
259154
  }, [cityData]);
259120
- const trailPathBuildings = React.useMemo(() => {
259121
- if (!cityData || markersForThisRepo.length === 0) return [];
259122
- const buildingByPath = new Map(cityData.buildings.map((b) => [b.path, b]));
259123
- const out = [];
259155
+ const { trailPathBuildings, trailPathTitles, trailPathMarkerIds } = React.useMemo(() => {
259156
+ var _a2;
259157
+ if (!cityData || markersForThisRepo.length === 0) {
259158
+ return {
259159
+ trailPathBuildings: [],
259160
+ trailPathTitles: [],
259161
+ trailPathMarkerIds: []
259162
+ };
259163
+ }
259164
+ const buildingByPath = new Map(
259165
+ cityData.buildings.map((b) => [b.path, b])
259166
+ );
259167
+ const buildings = [];
259168
+ const titles = [];
259169
+ const markerIds = [];
259124
259170
  for (const m of markersForThisRepo) {
259125
259171
  if (!m.sourcePath) continue;
259126
- const b = buildingByPath.get(m.sourcePath) ?? cityData.buildings.find((cb) => cb.path.endsWith(`/${m.sourcePath}`));
259127
- if (b) out.push(b);
259172
+ const b = buildingByPath.get(m.sourcePath) ?? cityData.buildings.find(
259173
+ (cb) => cb.path.endsWith(`/${m.sourcePath}`)
259174
+ );
259175
+ if (b) {
259176
+ buildings.push(b);
259177
+ titles.push(((_a2 = m.label) == null ? void 0 : _a2.trim()) || null);
259178
+ markerIds.push(m.id);
259179
+ }
259128
259180
  }
259129
- return out;
259181
+ return {
259182
+ trailPathBuildings: buildings,
259183
+ trailPathTitles: titles,
259184
+ trailPathMarkerIds: markerIds
259185
+ };
259130
259186
  }, [cityData, markersForThisRepo]);
259187
+ const trailPathCurrentStepIndex = React.useMemo(() => {
259188
+ if (!selectedMarkerId) return null;
259189
+ const idx = trailPathMarkerIds.indexOf(selectedMarkerId);
259190
+ return idx >= 0 ? idx : null;
259191
+ }, [selectedMarkerId, trailPathMarkerIds]);
259131
259192
  const onCameraFrame = React.useCallback(
259132
259193
  (camera, size) => {
259133
259194
  var _a2, _b2;
@@ -259172,13 +259233,18 @@ const FileCityTrailSequenceLayout = ({
259172
259233
  return () => observer.disconnect();
259173
259234
  }, [snippetPaneEl]);
259174
259235
  const overlayMarkdown = ((_a = selectedMarker == null ? void 0 : selectedMarker.description) == null ? void 0 : _a.trim()) ? {
259175
- eyebrow: "Marker",
259236
+ eyebrow: null,
259176
259237
  title: selectedMarker.label ?? selectedMarker.id,
259238
+ // File path under the title — the panel header already names
259239
+ // the trail, so swapping the "Marker" eyebrow for the marker's
259240
+ // sourcePath gives the user the more useful piece of context.
259241
+ subtitle: selectedMarker.sourcePath ?? null,
259177
259242
  markdown: selectedMarker.description,
259178
259243
  slideIdPrefix: `trail-${trail2.id}-marker-${selectedMarker.id}`
259179
259244
  } : ((_b = trail2.summary) == null ? void 0 : _b.trim()) ? {
259180
259245
  eyebrow: null,
259181
259246
  title: null,
259247
+ subtitle: null,
259182
259248
  markdown: trail2.summary,
259183
259249
  slideIdPrefix: `trail-${trail2.id}-summary`
259184
259250
  } : null;
@@ -259262,6 +259328,7 @@ const FileCityTrailSequenceLayout = ({
259262
259328
  {
259263
259329
  trail: trail2,
259264
259330
  markerCount: markersForThisRepo.length,
259331
+ activeMarkerIndex: stepperIndex,
259265
259332
  show3D: effectiveShow3D,
259266
259333
  onToggle3D: () => setShow3D((v) => !v),
259267
259334
  hideToggle: THREE_D_TOGGLE_DISABLED,
@@ -259274,13 +259341,16 @@ const FileCityTrailSequenceLayout = ({
259274
259341
  // Drawer-open is the default start state, so it no longer
259275
259342
  // counts as "non-idle". Exit is offered only when the user
259276
259343
  // has drilled into something the start view doesn't show.
259277
- selectedMarkerId != null || snippetExpanded || viewMode !== "city"
259344
+ // The "idle" view-mode is the host-supplied default — when
259345
+ // the host opens the panel in 'doc', staying in 'doc' is
259346
+ // idle and switching to 'city' is the non-idle drill-in.
259347
+ selectedMarkerId != null || snippetExpanded || viewMode !== defaultViewMode
259278
259348
  ),
259279
259349
  onExitTrail: () => {
259280
259350
  onSelectMarker(null);
259281
259351
  setDrawerHeightOverridePct(null);
259282
259352
  setSnippetExpanded(false);
259283
- setViewMode("city");
259353
+ setViewMode(defaultViewMode);
259284
259354
  },
259285
259355
  viewMode,
259286
259356
  onSetViewMode: setViewMode
@@ -259329,6 +259399,8 @@ const FileCityTrailSequenceLayout = ({
259329
259399
  ref: filePathRef,
259330
259400
  containerRef,
259331
259401
  buildings: trailPathBuildings,
259402
+ markerTitles: trailPathTitles,
259403
+ currentStepIndex: trailPathCurrentStepIndex,
259332
259404
  cityCenter
259333
259405
  }
259334
259406
  ),
@@ -259347,6 +259419,7 @@ const FileCityTrailSequenceLayout = ({
259347
259419
  {
259348
259420
  eyebrow: overlayMarkdown.eyebrow,
259349
259421
  title: overlayMarkdown.title,
259422
+ subtitle: overlayMarkdown.subtitle,
259350
259423
  markdown: overlayMarkdown.markdown,
259351
259424
  slideIdPrefix: overlayMarkdown.slideIdPrefix,
259352
259425
  bottomOffset: `${drawerHeightPct}%`,
@@ -259388,7 +259461,8 @@ const FileCityTrailSequenceLayout = ({
259388
259461
  drawerHeightPct,
259389
259462
  disableBottomTransition: isResizingDrawer,
259390
259463
  expanded: snippetExpanded,
259391
- onToggleExpanded: () => setSnippetExpanded((v) => !v)
259464
+ onToggleExpanded: () => setSnippetExpanded((v) => !v),
259465
+ markdownOverlayWidth
259392
259466
  }
259393
259467
  ) : null
259394
259468
  ]
@@ -259555,7 +259629,8 @@ const SnippetSidePane = React.forwardRef(function SnippetSidePane2({
259555
259629
  drawerHeightPct,
259556
259630
  disableBottomTransition,
259557
259631
  expanded,
259558
- onToggleExpanded
259632
+ onToggleExpanded,
259633
+ markdownOverlayWidth
259559
259634
  }, ref) {
259560
259635
  const { theme: theme2 } = useTheme();
259561
259636
  if (!marker.sourcePath) {
@@ -259569,6 +259644,7 @@ const SnippetSidePane = React.forwardRef(function SnippetSidePane2({
259569
259644
  disableBottomTransition,
259570
259645
  expanded,
259571
259646
  onToggleExpanded,
259647
+ markdownOverlayWidth,
259572
259648
  children: /* @__PURE__ */ jsx(
259573
259649
  "div",
259574
259650
  {
@@ -259594,6 +259670,7 @@ const SnippetSidePane = React.forwardRef(function SnippetSidePane2({
259594
259670
  disableBottomTransition,
259595
259671
  expanded,
259596
259672
  onToggleExpanded,
259673
+ markdownOverlayWidth,
259597
259674
  children: snippet2.kind === "slice" ? /* @__PURE__ */ jsx(
259598
259675
  TrailSnippetView,
259599
259676
  {
@@ -259635,10 +259712,12 @@ const SidePaneFrame = React.forwardRef(
259635
259712
  drawerHeightPct,
259636
259713
  disableBottomTransition,
259637
259714
  expanded,
259638
- onToggleExpanded
259715
+ onToggleExpanded,
259716
+ markdownOverlayWidth
259639
259717
  }, ref) {
259640
259718
  const { theme: theme2 } = useTheme();
259641
259719
  const [widthPx, setWidthPx] = React.useState(null);
259720
+ const defaultLeftInset = (markdownOverlayWidth ?? 0) + SNIPPET_PANE_LEADER_BUFFER_PX;
259642
259721
  const [isResizing, setIsResizing] = React.useState(false);
259643
259722
  const innerRef = React.useRef(null);
259644
259723
  const setInnerRef = React.useCallback(
@@ -259677,7 +259756,7 @@ const SidePaneFrame = React.forwardRef(
259677
259756
  const parentWidth = (parent == null ? void 0 : parent.clientWidth) ?? window.innerWidth;
259678
259757
  const maxWidth = Math.max(
259679
259758
  SNIPPET_PANE_MIN_WIDTH_PX,
259680
- parentWidth - 32
259759
+ parentWidth - defaultLeftInset - SNIPPET_PANE_RIGHT_GUTTER_PX
259681
259760
  );
259682
259761
  const dx = e.clientX - drag2.startX;
259683
259762
  const next2 = Math.min(
@@ -259686,7 +259765,7 @@ const SidePaneFrame = React.forwardRef(
259686
259765
  );
259687
259766
  setWidthPx(next2);
259688
259767
  },
259689
- []
259768
+ [defaultLeftInset]
259690
259769
  );
259691
259770
  const handleResizePointerUp = React.useCallback(
259692
259771
  (e) => {
@@ -259706,9 +259785,15 @@ const SidePaneFrame = React.forwardRef(
259706
259785
  style: {
259707
259786
  position: "absolute",
259708
259787
  top: 16,
259709
- right: 16,
259788
+ right: SNIPPET_PANE_RIGHT_GUTTER_PX,
259710
259789
  bottom: expanded ? `calc(${drawerHeightPct}% + 16px)` : "50%",
259711
- width: widthPx ?? SNIPPET_PANE_WIDTH_PX,
259790
+ // Auto-fill the right column when the user hasn't dragged an
259791
+ // explicit width: anchor to the markdown overlay's right edge
259792
+ // (plus a leader-line buffer) and the city container's right
259793
+ // gutter. Once `widthPx` is set, switch to an explicit width
259794
+ // and let `right` keep the right anchor.
259795
+ left: widthPx == null ? defaultLeftInset : void 0,
259796
+ width: widthPx ?? void 0,
259712
259797
  minWidth: SNIPPET_PANE_MIN_WIDTH_PX,
259713
259798
  backgroundColor: theme2.colors.background,
259714
259799
  border: `1px solid ${theme2.colors.border}`,
@@ -259771,33 +259856,77 @@ const SidePaneFrame = React.forwardRef(
259771
259856
  flexShrink: 0
259772
259857
  },
259773
259858
  children: [
259774
- /* @__PURE__ */ jsxs("div", { style: { minWidth: 0 }, children: [
259775
- /* @__PURE__ */ jsx(
259776
- "div",
259777
- {
259778
- style: {
259779
- fontFamily: theme2.fonts.heading,
259780
- fontSize: theme2.fontSizes[0],
259781
- fontWeight: theme2.fontWeights.semibold,
259782
- color: theme2.colors.text
259783
- },
259784
- children: marker.label ?? marker.id
259785
- }
259786
- ),
259787
- marker.sourcePath ? /* @__PURE__ */ jsx(
259788
- "div",
259789
- {
259790
- style: {
259791
- fontSize: theme2.fontSizes[0],
259792
- color: theme2.colors.textSecondary,
259793
- fontFamily: theme2.fonts.monospace,
259794
- marginTop: 2,
259795
- wordBreak: "break-all"
259796
- },
259797
- children: marker.sourcePath
259798
- }
259799
- ) : null
259800
- ] }),
259859
+ /* @__PURE__ */ jsx("div", { style: { minWidth: 0, flex: 1 }, children: (() => {
259860
+ const path2 = marker.sourcePath ?? "";
259861
+ const slashIdx = path2.lastIndexOf("/");
259862
+ const filename = slashIdx >= 0 ? path2.slice(slashIdx + 1) : path2;
259863
+ const directory = slashIdx >= 0 ? path2.slice(0, slashIdx + 1) : null;
259864
+ const snippet2 = marker.snippet;
259865
+ const rangeLabel = snippet2 ? snippet2.startLine === snippet2.endLine ? `${snippet2.startLine}` : `${snippet2.startLine}–${snippet2.endLine}` : null;
259866
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
259867
+ /* @__PURE__ */ jsxs(
259868
+ "div",
259869
+ {
259870
+ style: {
259871
+ display: "flex",
259872
+ alignItems: "baseline",
259873
+ gap: 8,
259874
+ minWidth: 0
259875
+ },
259876
+ children: [
259877
+ /* @__PURE__ */ jsx(
259878
+ "div",
259879
+ {
259880
+ style: {
259881
+ fontFamily: theme2.fonts.monospace,
259882
+ fontSize: theme2.fontSizes[1],
259883
+ fontWeight: theme2.fontWeights.semibold,
259884
+ color: theme2.colors.text,
259885
+ overflow: "hidden",
259886
+ textOverflow: "ellipsis",
259887
+ whiteSpace: "nowrap",
259888
+ minWidth: 0,
259889
+ flexShrink: 1
259890
+ },
259891
+ title: path2 || void 0,
259892
+ children: filename || marker.id
259893
+ }
259894
+ ),
259895
+ rangeLabel ? /* @__PURE__ */ jsx(
259896
+ "div",
259897
+ {
259898
+ style: {
259899
+ fontFamily: theme2.fonts.monospace,
259900
+ fontSize: theme2.fontSizes[0],
259901
+ color: theme2.colors.textSecondary,
259902
+ letterSpacing: 0.4,
259903
+ textTransform: "uppercase",
259904
+ flexShrink: 0
259905
+ },
259906
+ children: rangeLabel
259907
+ }
259908
+ ) : null
259909
+ ]
259910
+ }
259911
+ ),
259912
+ directory ? /* @__PURE__ */ jsx(
259913
+ "div",
259914
+ {
259915
+ style: {
259916
+ fontSize: theme2.fontSizes[0],
259917
+ color: theme2.colors.textSecondary,
259918
+ fontFamily: theme2.fonts.monospace,
259919
+ marginTop: 2,
259920
+ overflow: "hidden",
259921
+ textOverflow: "ellipsis",
259922
+ whiteSpace: "nowrap"
259923
+ },
259924
+ title: directory,
259925
+ children: directory
259926
+ }
259927
+ ) : null
259928
+ ] });
259929
+ })() }),
259801
259930
  /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 6, flexShrink: 0 }, children: [
259802
259931
  /* @__PURE__ */ jsx(
259803
259932
  "button",
@@ -260094,6 +260223,7 @@ const TrailDocumentCard = ({
260094
260223
  const TrailHeader = ({
260095
260224
  trail: trail2,
260096
260225
  markerCount,
260226
+ activeMarkerIndex,
260097
260227
  show3D,
260098
260228
  onToggle3D,
260099
260229
  hideToggle = false,
@@ -260173,20 +260303,34 @@ const TrailHeader = ({
260173
260303
  children: trail2.title
260174
260304
  }
260175
260305
  ),
260176
- /* @__PURE__ */ jsxs(
260306
+ /* @__PURE__ */ jsx(
260177
260307
  "div",
260178
260308
  {
260309
+ "aria-label": `${markerCount} marker${markerCount === 1 ? "" : "s"} in this repo`,
260179
260310
  style: {
260180
- fontFamily: theme2.fonts.body,
260181
- fontSize: theme2.fontSizes[0],
260182
- color: theme2.colors.textSecondary
260311
+ display: "flex",
260312
+ alignItems: "center",
260313
+ height: theme2.fontSizes[0]
260183
260314
  },
260184
- children: [
260185
- markerCount,
260186
- " marker",
260187
- markerCount === 1 ? "" : "s",
260188
- " in this repo"
260189
- ]
260315
+ children: Array.from({ length: markerCount }).map((_, i) => {
260316
+ const isActive = i === activeMarkerIndex;
260317
+ return /* @__PURE__ */ jsx(
260318
+ "span",
260319
+ {
260320
+ style: {
260321
+ width: 6,
260322
+ height: 6,
260323
+ borderRadius: "50%",
260324
+ background: isActive ? theme2.colors.accent : theme2.colors.textSecondary,
260325
+ // Group dots in fives for at-a-glance countability — a
260326
+ // wider gap before every 5th index (after the first)
260327
+ // creates visual columns of 5 like tally marks.
260328
+ marginLeft: i === 0 ? 0 : i % 5 === 0 ? 11 : 5
260329
+ }
260330
+ },
260331
+ i
260332
+ );
260333
+ })
260190
260334
  }
260191
260335
  )
260192
260336
  ]