@deepseek-ai/dsh-client-ui-primitives 0.1.6-alpha.1 → 0.1.6-alpha.2

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/index.js CHANGED
@@ -6,32 +6,34 @@ import css$2 from "./Button.module.css";
6
6
  import css$3 from "./Pill.module.css";
7
7
  import css$4 from "./Tag.module.css";
8
8
  import css$5 from "./Switch.module.css";
9
- import css$6 from "./Input.module.css";
10
- import { Fragment as Fragment$1, cloneElement, createElement, memo, useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
9
+ import css$6 from "./Checkbox.module.css";
10
+ import css$7 from "./Input.module.css";
11
+ import { Fragment as Fragment$1, cloneElement, createContext, createElement, memo, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
11
12
  import { createPortal } from "react-dom";
12
- import css$7 from "./Menu.module.css";
13
- import css$8 from "./HoverCard.module.css";
14
- import css$9 from "./Modal.module.css";
15
- import css$10 from "./OnboardingSurface.module.css";
16
- import css$11 from "./RiskConfirmation.module.css";
17
- import css$12 from "./ConnectionIndicator.module.css";
18
- import css$13 from "./FileTypeIcon.module.css";
19
- import css$14 from "./user-text.module.css";
13
+ import css$8 from "./Menu.module.css";
14
+ import css$9 from "./HoverCard.module.css";
15
+ import css$10 from "./Modal.module.css";
16
+ import css$11 from "./OnboardingSurface.module.css";
17
+ import css$12 from "./RiskConfirmation.module.css";
18
+ import css$13 from "./ConnectionIndicator.module.css";
19
+ import css$14 from "./FileTypeIcon.module.css";
20
+ import { siAliexpress, siApple, siBaidu, siBilibili, siCsdn, siDuckduckgo, siEbay, siFacebook, siGithub, siGitlab, siGoogle, siInstagram, siJuejin, siMdnwebdocs, siNetflix, siNpm, siPypi, siQq, siQuora, siReddit, siSinaweibo, siSpotify, siStackoverflow, siTaobao, siTelegram, siTiktok, siV2ex, siWechat, siWhatsapp, siWikipedia, siX, siYcombinator, siYoutube, siZhihu } from "simple-icons";
21
+ import css$15 from "./user-text.module.css";
20
22
  import markdownCss from "./markdown/MarkdownText.module.css";
21
- import css$15 from "./Tooltip.module.css";
22
- import css$16 from "./Toast.module.css";
23
- import css$17 from "./JsonTree.module.css";
23
+ import css$16 from "./Tooltip.module.css";
24
+ import css$17 from "./Toast.module.css";
25
+ import css$18 from "./JsonTree.module.css";
24
26
  import Anser from "anser";
25
- import css$18 from "./TerminalBlock.module.css";
27
+ import css$19 from "./TerminalBlock.module.css";
26
28
  import { createCssVariablesTheme, createHighlighterCoreSync } from "shiki/core";
27
29
  import { createJavaScriptRegexEngine, defaultJavaScriptRegexConstructor } from "shiki/engine/javascript";
28
30
  import langTs from "@shikijs/langs/typescript";
29
31
  import langBash from "@shikijs/langs/shellscript";
30
32
  import langJson from "@shikijs/langs/json";
31
- import css$19 from "./ReadBlock.module.css";
33
+ import css$20 from "./ReadBlock.module.css";
32
34
  import { structuredPatch } from "diff";
33
- import css$20 from "./DiffBlock.module.css";
34
- import css$21 from "./SearchBlock.module.css";
35
+ import css$21 from "./DiffBlock.module.css";
36
+ import css$22 from "./SearchBlock.module.css";
35
37
  import { fromMarkdown } from "mdast-util-from-markdown";
36
38
  import { gfmFromMarkdown } from "mdast-util-gfm";
37
39
  import { mathFromMarkdown } from "mdast-util-math";
@@ -43,11 +45,11 @@ import { classifyCharacter } from "micromark-util-classify-character";
43
45
  import { codes, constants, types } from "micromark-util-symbol";
44
46
  import { factorySpace } from "micromark-factory-space";
45
47
  import { normalizeUri } from "micromark-util-sanitize-uri";
46
- import css$22 from "./markdown/CodeBlock.module.css";
48
+ import css$23 from "./markdown/CodeBlock.module.css";
47
49
  import katex from "katex";
48
50
  import "katex/dist/katex.min.css";
49
- import css$23 from "./WebBlock.module.css";
50
- import css$24 from "./markdown/JsonBlock.module.css";
51
+ import css$24 from "./WebBlock.module.css";
52
+ import css$25 from "./markdown/JsonBlock.module.css";
51
53
  //#region lib/types/StateDot.js
52
54
  /** Outer 3x3 matrix cells (2px pixels on a 10px grid), clockwise from top-left. */
53
55
  const MATRIX_CELLS = [
@@ -1429,6 +1431,29 @@ const IconQuestionOutline14 = ({ size = 14, className }) => jsxs("svg", {
1429
1431
  })
1430
1432
  ]
1431
1433
  });
1434
+ /** Info companion to the question outline: the same ring with an "i" glyph. */
1435
+ const IconInfoOutline14 = ({ size = 14, className }) => jsxs("svg", {
1436
+ width: size,
1437
+ height: size,
1438
+ className,
1439
+ viewBox: "0 0 14 14",
1440
+ fill: "none",
1441
+ xmlns: "http://www.w3.org/2000/svg",
1442
+ children: [
1443
+ jsx("path", {
1444
+ d: "M12.5757 7.00012C12.5757 3.92085 10.0794 1.42463 7.00012 1.42456C3.9208 1.42456 1.42456 3.9208 1.42456 7.00012C1.42463 10.0794 3.92085 12.5757 7.00012 12.5757C10.0793 12.5756 12.5756 10.0793 12.5757 7.00012ZM13.8002 7.00012C13.8001 10.7559 10.7559 13.8001 7.00012 13.8002C3.2443 13.8002 0.199291 10.7559 0.199219 7.00012C0.199219 3.24426 3.24426 0.199219 7.00012 0.199219C10.7559 0.199291 13.8002 3.2443 13.8002 7.00012Z",
1445
+ fill: "currentColor"
1446
+ }),
1447
+ jsx("path", {
1448
+ d: "M7.6127 3.18921V4.55986H6.38735V3.18921H7.6127Z",
1449
+ fill: "currentColor"
1450
+ }),
1451
+ jsx("path", {
1452
+ d: "M7.6127 5.68921V10.8109H6.38735V5.68921H7.6127Z",
1453
+ fill: "currentColor"
1454
+ })
1455
+ ]
1456
+ });
1432
1457
  /** Alarm clock outline for active scheduled-task indicators. */
1433
1458
  const IconAlarmClockOutline16 = ({ size = 16, className }) => jsxs("svg", {
1434
1459
  "aria-hidden": "true",
@@ -1602,6 +1627,37 @@ const IconShieldOutline16 = ({ size = 16, className }) => jsx("svg", {
1602
1627
  strokeLinejoin: "round"
1603
1628
  })
1604
1629
  });
1630
+ /** Plugin pinwheel (design handoff for the plugin manager): four interleaved arcs on the 16 grid. */
1631
+ const IconPluginPinwheelOutline16 = ({ size = 16, className }) => jsxs("svg", {
1632
+ width: size,
1633
+ height: size,
1634
+ className,
1635
+ viewBox: "0 0 16 16",
1636
+ fill: "none",
1637
+ xmlns: "http://www.w3.org/2000/svg",
1638
+ children: [
1639
+ jsx("path", {
1640
+ d: "M7.84457 5.06199C11.6605 4.93876 14.7962 6.14848 14.8484 7.76397C14.8875 8.97461 13.1838 10.0696 10.7215 10.5942",
1641
+ stroke: "currentColor",
1642
+ strokeWidth: "1.2"
1643
+ }),
1644
+ jsx("path", {
1645
+ d: "M5.12742 8.07731C5.00419 4.26138 6.21391 1.12568 7.8294 1.07351C9.04004 1.03441 10.135 2.73808 10.6596 5.20037",
1646
+ stroke: "currentColor",
1647
+ strokeWidth: "1.2"
1648
+ }),
1649
+ jsx("path", {
1650
+ d: "M8.02457 10.6802C4.20865 10.8034 1.07294 9.5937 1.02077 7.97821C0.981678 6.76758 2.68535 5.67262 5.14763 5.14798",
1651
+ stroke: "currentColor",
1652
+ strokeWidth: "1.2"
1653
+ }),
1654
+ jsx("path", {
1655
+ d: "M10.7476 7.89535C10.8708 11.7113 9.66109 14.847 8.0456 14.8991C6.83496 14.9382 5.74 13.2346 5.21536 10.7723",
1656
+ stroke: "currentColor",
1657
+ strokeWidth: "1.2"
1658
+ })
1659
+ ]
1660
+ });
1605
1661
  //#endregion
1606
1662
  //#region lib/types/DisclosureRow.js
1607
1663
  /**
@@ -1743,6 +1799,33 @@ function Switch({ checked, onChange, label, disabled = false, title, className }
1743
1799
  });
1744
1800
  }
1745
1801
  //#endregion
1802
+ //#region lib/types/Checkbox.js
1803
+ /** Controlled native checkbox with a caller-owned visible and accessible label. */
1804
+ /**
1805
+ * Render a labeled checkbox with native keyboard and form semantics.
1806
+ * @param props.checked - current checked state.
1807
+ * @param props.onChange - receives the requested checked state.
1808
+ * @param props.label - localized visible and accessible label.
1809
+ * @param props.disabled - whether the control refuses changes.
1810
+ * @param props.title - optional localized hover text.
1811
+ * @param props.className - extra class for the label's placement.
1812
+ * @returns the label containing its checkbox.
1813
+ */
1814
+ function Checkbox({ checked, onChange, label, disabled = false, title, className }) {
1815
+ return jsxs("label", {
1816
+ className: clsx(css$6.checkbox, className),
1817
+ title,
1818
+ children: [jsx("input", {
1819
+ type: "checkbox",
1820
+ checked,
1821
+ disabled,
1822
+ onChange: (event) => {
1823
+ onChange(event.target.checked);
1824
+ }
1825
+ }), jsx("span", { children: label })]
1826
+ });
1827
+ }
1828
+ //#endregion
1746
1829
  //#region lib/types/Input.js
1747
1830
  /**
1748
1831
  * Render a text input with an optional leading icon.
@@ -1751,12 +1834,12 @@ function Switch({ checked, onChange, label, disabled = false, title, className }
1751
1834
  */
1752
1835
  function Input({ icon, className, ...rest }) {
1753
1836
  return jsxs("span", {
1754
- className: clsx(css$6.wrap, className),
1837
+ className: clsx(css$7.wrap, className),
1755
1838
  children: [icon != null && jsx("span", {
1756
- className: css$6.icon,
1839
+ className: css$7.icon,
1757
1840
  children: icon
1758
1841
  }), jsx("input", {
1759
- className: css$6.input,
1842
+ className: css$7.input,
1760
1843
  ...rest
1761
1844
  })]
1762
1845
  });
@@ -1805,8 +1888,13 @@ const MEASURE_STYLE = {
1805
1888
  top: 0
1806
1889
  };
1807
1890
  /**
1808
- * Render an anchored dropdown menu.
1809
- * @param props.autoFocus - focus the first item on open and enable arrow-key navigation; Escape focuses the anchor's first button.
1891
+ * Render an anchored dropdown menu. While the list is open its keys mirror the
1892
+ * composer's: Tab settles the focused row — from the trigger, Tab enters the
1893
+ * list instead — and Escape or Shift+Tab close it and return focus to the
1894
+ * anchor's first button, and selecting a row does the same — the rows unmount
1895
+ * with the list. Only a keyboard on the trigger or inside the list is
1896
+ * intercepted; Tab presses elsewhere on the page stay the browser's.
1897
+ * @param props.autoFocus - focus the first item on open; the arrow keys walk the list either way.
1810
1898
  * @param props.open - whether the list is showing (owner-controlled).
1811
1899
  * @param props.anchor - the trigger element (rendered in place).
1812
1900
  * @param props.items - selectable rows and optional separators.
@@ -1845,6 +1933,44 @@ const MEASURE_STYLE = {
1845
1933
  function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, onClose, align = "start", side = "bottom", portal = false, closeOnPointerLeave = false, dense = false, compact = false, autoFocus = false, selection = "check", getAnchorRect, footer, className }) {
1846
1934
  const rootRef = useRef(null);
1847
1935
  const listRef = useRef(null);
1936
+ /** Index the arrow walk last focused, the resume point when focus left the rows. */
1937
+ const walkIndex = useRef(null);
1938
+ /**
1939
+ * The control that had the keyboard when this menu opened — its own trigger,
1940
+ * which an anchor that wraps several controls (a split button) would not be
1941
+ * able to name by position.
1942
+ */
1943
+ const triggerRef = useRef(null);
1944
+ /**
1945
+ * Hand the keyboard back to the trigger that opened the menu — or, when the
1946
+ * anchor never held it, to the anchor's first button. Focus left on a removed
1947
+ * row otherwise falls to the page body, where the next Tab restarts from the
1948
+ * top of the page.
1949
+ */
1950
+ const refocusAnchor = () => {
1951
+ const trigger = triggerRef.current;
1952
+ if (trigger !== null && document.contains(trigger) && !trigger.disabled) {
1953
+ trigger.focus();
1954
+ return;
1955
+ }
1956
+ rootRef.current?.querySelector("button:not(:disabled)")?.focus();
1957
+ };
1958
+ /**
1959
+ * Post-selection focus, for the paths where the rows unmount with the list.
1960
+ * A selection whose owner keeps the menu open is left alone, and so is an
1961
+ * owner that moved focus itself (a presented file card hands it to its
1962
+ * preview button): only a keyboard left on the closing list (or on the body
1963
+ * its removal produced) comes back to the trigger.
1964
+ */
1965
+ const refocusAfterSelection = () => {
1966
+ queueMicrotask(() => {
1967
+ if (openRef.current) return;
1968
+ const active = document.activeElement;
1969
+ if (active === null || active === document.body || listRef.current?.contains(active) === true) refocusAnchor();
1970
+ });
1971
+ };
1972
+ const openRef = useRef(open);
1973
+ openRef.current = open;
1848
1974
  const [openSubmenuId, setOpenSubmenuId] = useState(null);
1849
1975
  const [fixedPos, setFixedPos] = useState(null);
1850
1976
  const { arm: armClose, cancel: cancelClose } = usePointerGrace(onClose);
@@ -1900,11 +2026,23 @@ function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, onClose,
1900
2026
  getAnchorRect
1901
2027
  ]);
1902
2028
  useEffect(() => {
1903
- if (open && autoFocus) listRef.current?.querySelector("button:not(:disabled)")?.focus();
2029
+ if (!open) {
2030
+ triggerRef.current = null;
2031
+ return;
2032
+ }
2033
+ const active = document.activeElement;
2034
+ triggerRef.current = active instanceof HTMLElement && rootRef.current?.contains(active) === true ? active : null;
2035
+ }, [open]);
2036
+ useEffect(() => {
2037
+ if (!open || !autoFocus) return;
2038
+ const first = listRef.current?.querySelector("button:not(:disabled)");
2039
+ walkIndex.current = first === void 0 || first === null ? null : 0;
2040
+ first?.focus();
1904
2041
  }, [open, autoFocus]);
1905
2042
  useEffect(() => {
1906
2043
  if (!open) {
1907
2044
  setOpenSubmenuId(null);
2045
+ walkIndex.current = null;
1908
2046
  return;
1909
2047
  }
1910
2048
  const onPointerDown = (e) => {
@@ -1914,21 +2052,52 @@ function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, onClose,
1914
2052
  onClose();
1915
2053
  };
1916
2054
  const onKeyDown = (e) => {
2055
+ const focused = document.activeElement;
2056
+ const insideList = listRef.current?.contains(focused) === true;
2057
+ const anchored = rootRef.current?.contains(focused) === true || insideList;
1917
2058
  if (e.key === "Escape") {
1918
2059
  onClose();
1919
- if (autoFocus) rootRef.current?.querySelector("button")?.focus();
2060
+ if (anchored || autoFocus) refocusAnchor();
2061
+ }
2062
+ if (e.key === "Tab") {
2063
+ const list = listRef.current;
2064
+ if (list === null || !anchored) return;
2065
+ if (e.shiftKey) {
2066
+ e.preventDefault();
2067
+ onClose();
2068
+ refocusAnchor();
2069
+ return;
2070
+ }
2071
+ if (insideList) {
2072
+ if (focused instanceof Element && focused.getAttribute("role") === "menuitem") {
2073
+ e.preventDefault();
2074
+ focused.click();
2075
+ }
2076
+ return;
2077
+ }
2078
+ const row = list.querySelector("button:not(:disabled)");
2079
+ if (row === null) return;
2080
+ e.preventDefault();
2081
+ row.focus();
2082
+ walkIndex.current = 0;
2083
+ return;
1920
2084
  }
1921
- if (!autoFocus || ![
2085
+ if (![
1922
2086
  "ArrowDown",
1923
2087
  "ArrowUp",
1924
2088
  "Home",
1925
2089
  "End"
1926
2090
  ].includes(e.key)) return;
1927
- const buttons = Array.from(listRef.current?.querySelectorAll("button:not(:disabled)") ?? []);
1928
- const index = buttons.indexOf(document.activeElement);
1929
- if (index < 0) return;
2091
+ const list = listRef.current;
2092
+ if (list === null || !anchored) return;
2093
+ const buttons = Array.from(list.querySelectorAll("button:not(:disabled)"));
2094
+ if (buttons.length === 0) return;
2095
+ const index = buttons.indexOf(focused);
2096
+ const from = index >= 0 ? index : walkIndex.current;
2097
+ const next = e.key === "Home" ? 0 : e.key === "End" ? buttons.length - 1 : from === null ? e.key === "ArrowDown" ? 0 : buttons.length - 1 : (from + (e.key === "ArrowDown" ? 1 : -1) + buttons.length) % buttons.length;
1930
2098
  e.preventDefault();
1931
- buttons[e.key === "Home" ? 0 : e.key === "End" ? buttons.length - 1 : (index + (e.key === "ArrowDown" ? 1 : -1) + buttons.length) % buttons.length]?.focus();
2099
+ walkIndex.current = next;
2100
+ buttons[next]?.focus();
1932
2101
  };
1933
2102
  const onWindowBlur = () => {
1934
2103
  if (document.activeElement instanceof HTMLIFrameElement) onClose();
@@ -1952,11 +2121,11 @@ function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, onClose,
1952
2121
  const scrollable = !items.some((entry) => !isSeparator(entry) && !isLabel(entry) && entry.submenu !== void 0 && entry.submenu.length > 0);
1953
2122
  const renderEntry = (entry) => {
1954
2123
  if (isSeparator(entry)) return jsx("div", {
1955
- className: css$7.separator,
2124
+ className: css$8.separator,
1956
2125
  role: "separator"
1957
2126
  }, entry.id);
1958
2127
  if (isLabel(entry)) return jsx("div", {
1959
- className: css$7.label,
2128
+ className: css$8.label,
1960
2129
  role: "presentation",
1961
2130
  children: entry.text
1962
2131
  }, entry.id);
@@ -1964,7 +2133,7 @@ function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, onClose,
1964
2133
  const subOpen = hasSub && openSubmenuId === entry.id;
1965
2134
  const selected = entry.id === selectedId || selectedIds?.includes(entry.id) === true;
1966
2135
  return jsxs("div", {
1967
- className: css$7.itemWrap,
2136
+ className: css$8.itemWrap,
1968
2137
  onMouseEnter: () => {
1969
2138
  setOpenSubmenuId(hasSub ? entry.id : null);
1970
2139
  },
@@ -1974,7 +2143,7 @@ function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, onClose,
1974
2143
  children: [jsxs("button", {
1975
2144
  type: "button",
1976
2145
  role: "menuitem",
1977
- className: clsx(css$7.item, selected && (selection === "fill" ? css$7.selectedFill : css$7.selected), entry.danger === true && css$7.danger),
2146
+ className: clsx(css$8.item, selected && (selection === "fill" ? css$8.selectedFill : css$8.selected), entry.danger === true && css$8.danger),
1978
2147
  disabled: entry.disabled,
1979
2148
  "aria-haspopup": hasSub ? "menu" : void 0,
1980
2149
  "aria-expanded": hasSub ? subOpen : void 0,
@@ -1987,34 +2156,36 @@ function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, onClose,
1987
2156
  return;
1988
2157
  }
1989
2158
  onSelect(entry.id);
2159
+ refocusAfterSelection();
1990
2160
  },
1991
2161
  children: [
1992
2162
  entry.icon !== void 0 && jsx("span", {
1993
- className: css$7.itemIcon,
2163
+ className: css$8.itemIcon,
1994
2164
  children: entry.icon
1995
2165
  }),
1996
2166
  jsx("span", {
1997
- className: css$7.itemLabel,
2167
+ className: css$8.itemLabel,
1998
2168
  children: entry.label
1999
2169
  }),
2000
- selected && selection === "check" && jsx(IconCheckOutline16, { className: css$7.check })
2170
+ selected && selection === "check" && jsx(IconCheckOutline16, { className: css$8.check })
2001
2171
  ]
2002
2172
  }), subOpen && entry.submenu !== void 0 && jsx("div", {
2003
- className: clsx(css$7.submenu, compact && css$7.compactList),
2173
+ className: clsx(css$8.submenu, compact && css$8.compactList),
2004
2174
  role: "menu",
2005
2175
  children: entry.submenu.map((sub) => jsxs("button", {
2006
2176
  type: "button",
2007
2177
  role: "menuitem",
2008
- className: css$7.item,
2178
+ className: css$8.item,
2009
2179
  disabled: sub.disabled,
2010
2180
  onClick: () => {
2011
2181
  onSelect(sub.id);
2182
+ refocusAfterSelection();
2012
2183
  },
2013
2184
  children: [sub.icon !== void 0 && jsx("span", {
2014
- className: css$7.itemIcon,
2185
+ className: css$8.itemIcon,
2015
2186
  children: sub.icon
2016
2187
  }), jsx("span", {
2017
- className: css$7.itemLabel,
2188
+ className: css$8.itemLabel,
2018
2189
  children: sub.label
2019
2190
  })]
2020
2191
  }, sub.id))
@@ -2023,25 +2194,25 @@ function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, onClose,
2023
2194
  };
2024
2195
  const list = open && jsxs("div", {
2025
2196
  ref: listRef,
2026
- className: clsx(css$7.list, dense && css$7.denseList, compact && css$7.compactList, scrollable && css$7.scrollable, portal && css$7.portal, side === "top" && !portal && css$7.sideTop, align === "end" && !portal && css$7.alignEnd),
2197
+ className: clsx(css$8.list, dense && css$8.denseList, compact && css$8.compactList, scrollable && css$8.scrollable, portal && css$8.portal, side === "top" && !portal && css$8.sideTop, align === "end" && !portal && css$8.alignEnd),
2027
2198
  style: portal ? fixedPos ?? MEASURE_STYLE : void 0,
2028
2199
  role: "menu",
2029
2200
  onClick: (e) => {
2030
2201
  e.stopPropagation();
2031
2202
  },
2032
2203
  children: [jsx("div", {
2033
- className: css$7.viewport,
2204
+ className: css$8.viewport,
2034
2205
  role: "presentation",
2035
2206
  children: items.map(renderEntry)
2036
2207
  }), footer !== void 0 && footer.length > 0 && jsx("div", {
2037
- className: css$7.footer,
2208
+ className: css$8.footer,
2038
2209
  role: "presentation",
2039
2210
  children: footer.map(renderEntry)
2040
2211
  })]
2041
2212
  });
2042
2213
  return jsxs("span", {
2043
2214
  ref: rootRef,
2044
- className: clsx(css$7.root, className),
2215
+ className: clsx(css$8.root, className),
2045
2216
  onPointerEnter: closeOnPointerLeave ? cancelClose : void 0,
2046
2217
  onPointerLeave: closeOnPointerLeave ? () => {
2047
2218
  if (open) armClose();
@@ -2341,7 +2512,7 @@ function HoverCard({ anchor, content, openDelayMs = 500, disabled = false, copyT
2341
2512
  const copyable = copyText !== void 0;
2342
2513
  const card = open && pos !== null && jsx("div", {
2343
2514
  ref: cardRef,
2344
- className: `${css$8.card}${copyable ? ` ${css$8.copyable}` : ""}${copied ? ` ${css$8.feedback}` : ""}`,
2515
+ className: `${css$9.card}${copyable ? ` ${css$9.copyable}` : ""}${copied ? ` ${css$9.feedback}` : ""}`,
2345
2516
  style: {
2346
2517
  ...pos,
2347
2518
  minHeight: copied && copyHeightRef.current !== null ? copyHeightRef.current : void 0
@@ -2362,14 +2533,14 @@ function HoverCard({ anchor, content, openDelayMs = 500, disabled = false, copyT
2362
2533
  copy(copyText);
2363
2534
  } : void 0,
2364
2535
  children: copied ? jsx("span", {
2365
- className: css$8.copied,
2536
+ className: css$9.copied,
2366
2537
  "aria-hidden": "true",
2367
2538
  children: copiedLabel
2368
2539
  }) : content
2369
2540
  });
2370
2541
  return jsxs("span", {
2371
2542
  ref: rootRef,
2372
- className: css$8.root,
2543
+ className: css$9.root,
2373
2544
  onPointerEnter: () => {
2374
2545
  if (disabled) return;
2375
2546
  cancelClose();
@@ -2392,7 +2563,7 @@ function HoverCard({ anchor, content, openDelayMs = 500, disabled = false, copyT
2392
2563
  children: [
2393
2564
  anchor,
2394
2565
  open && copyable && jsx("span", {
2395
- className: css$8.status,
2566
+ className: css$9.status,
2396
2567
  role: "status",
2397
2568
  children: copied ? copiedLabel : ""
2398
2569
  }),
@@ -2405,7 +2576,8 @@ function HoverCard({ anchor, content, openDelayMs = 500, disabled = false, copyT
2405
2576
  /**
2406
2577
  * Render a centered, body-portaled modal over a blurred page mask.
2407
2578
  * @param props.open - whether the dialog is showing.
2408
- * @param props.onClose - Escape or mask click.
2579
+ * @param props.onClose - Escape or mask click; while a menu is open inside the
2580
+ * dialog, Escape belongs to that menu first.
2409
2581
  * @param props.title - dialog heading (aria-label in every mode).
2410
2582
  * @param props.closeLabel - localized accessible close-button label.
2411
2583
  * @param props.description - optional supporting sentence under the title.
@@ -2429,44 +2601,44 @@ function Modal({ open, onClose, title, closeLabel, description, children, footer
2429
2601
  }, [open, onClose]);
2430
2602
  if (!open) return null;
2431
2603
  return createPortal(jsxs("div", {
2432
- className: css$9.root,
2604
+ className: css$10.root,
2433
2605
  role: "presentation",
2434
2606
  children: [jsx("div", {
2435
- className: css$9.mask,
2607
+ className: css$10.mask,
2436
2608
  "aria-hidden": "true",
2437
2609
  onClick: onClose
2438
2610
  }), jsx("div", {
2439
- className: clsx(css$9.dialog, className),
2611
+ className: clsx(css$10.dialog, className),
2440
2612
  role: "dialog",
2441
2613
  "aria-modal": "true",
2442
2614
  "aria-label": title,
2443
2615
  children: headless ? children : jsxs(Fragment, { children: [jsxs("div", {
2444
- className: clsx(css$9.content, contentClassName),
2616
+ className: clsx(css$10.content, contentClassName),
2445
2617
  children: [
2446
2618
  jsxs("div", {
2447
- className: css$9.header,
2619
+ className: css$10.header,
2448
2620
  children: [jsx("h2", {
2449
- className: css$9.title,
2621
+ className: css$10.title,
2450
2622
  children: title
2451
2623
  }), jsx("button", {
2452
2624
  type: "button",
2453
- className: css$9.close,
2625
+ className: css$10.close,
2454
2626
  "aria-label": closeLabel,
2455
2627
  onClick: onClose,
2456
2628
  children: jsx(IconCloseOutline16, { size: 14 })
2457
2629
  })]
2458
2630
  }),
2459
2631
  description !== void 0 && description !== "" && jsx("p", {
2460
- className: css$9.description,
2632
+ className: css$10.description,
2461
2633
  children: description
2462
2634
  }),
2463
2635
  children !== void 0 && jsx("div", {
2464
- className: css$9.body,
2636
+ className: css$10.body,
2465
2637
  children
2466
2638
  })
2467
2639
  ]
2468
2640
  }), footer !== void 0 && jsx("div", {
2469
- className: css$9.footer,
2641
+ className: css$10.footer,
2470
2642
  children: footer
2471
2643
  })] })
2472
2644
  })]
@@ -2490,13 +2662,13 @@ function OnboardingSurface({ children }) {
2490
2662
  };
2491
2663
  }, []);
2492
2664
  return createPortal(jsxs("div", {
2493
- className: css$10.onboardingOverlay,
2665
+ className: css$11.onboardingOverlay,
2494
2666
  role: "presentation",
2495
2667
  children: [jsx("div", {
2496
- className: css$10.onboardingMask,
2668
+ className: css$11.onboardingMask,
2497
2669
  "aria-hidden": "true"
2498
2670
  }), jsx("div", {
2499
- className: css$10.onboardingStage,
2671
+ className: css$11.onboardingStage,
2500
2672
  children
2501
2673
  })]
2502
2674
  }), document.body);
@@ -2517,28 +2689,28 @@ function RiskConfirmation({ open, title, description, acknowledgeLabel, cancelLa
2517
2689
  onClose: onCancel,
2518
2690
  title,
2519
2691
  closeLabel,
2520
- className: css$11.confirmation ?? "",
2521
- contentClassName: css$11.confirmationContent ?? "",
2692
+ className: css$12.confirmation ?? "",
2693
+ contentClassName: css$12.confirmationContent ?? "",
2522
2694
  footer: jsxs(Fragment, { children: [jsx(Button, {
2523
2695
  variant: "outline",
2524
- className: css$11.modalAction,
2696
+ className: css$12.modalAction,
2525
2697
  onClick: onCancel,
2526
2698
  children: cancelLabel
2527
2699
  }), jsx(Button, {
2528
2700
  variant: "primary",
2529
- className: css$11.confirmAction,
2701
+ className: css$12.confirmAction,
2530
2702
  disabled: disabled || !acknowledged,
2531
2703
  onClick: onConfirm,
2532
2704
  children: confirmLabel
2533
2705
  })] }),
2534
2706
  children: [jsxs("div", {
2535
- className: css$11.warning,
2707
+ className: css$12.warning,
2536
2708
  children: [jsx(IconWarningOutline16, {
2537
2709
  size: 18,
2538
- className: css$11.warningIcon
2710
+ className: css$12.warningIcon
2539
2711
  }), jsx("p", { children: description })]
2540
2712
  }), jsxs("label", {
2541
- className: css$11.acknowledgement,
2713
+ className: css$12.acknowledgement,
2542
2714
  children: [jsx("input", {
2543
2715
  type: "checkbox",
2544
2716
  checked: acknowledged,
@@ -2586,47 +2758,47 @@ function ConnectionIndicator({ state, disconnectedLabel, connectingLabel, recove
2586
2758
  };
2587
2759
  }, [state, rendered]);
2588
2760
  if (rendered === void 0) return null;
2589
- const leavingClass = leaving ? ` ${css$12.leaving}` : "";
2761
+ const leavingClass = leaving ? ` ${css$13.leaving}` : "";
2590
2762
  if (rendered === "recovered") return jsxs("div", {
2591
- className: `${css$12.indicator} ${css$12.success}${leavingClass}`,
2763
+ className: `${css$13.indicator} ${css$13.success}${leavingClass}`,
2592
2764
  role: "status",
2593
2765
  "aria-label": recoveredLabel,
2594
2766
  children: [jsx("span", {
2595
- className: css$12.icon,
2767
+ className: css$13.icon,
2596
2768
  "aria-hidden": "true",
2597
2769
  children: jsx(IconCheckOutline16, { size: 14 })
2598
2770
  }), jsx("span", {
2599
- className: css$12.label,
2771
+ className: css$13.label,
2600
2772
  children: recoveredLabel
2601
2773
  })]
2602
2774
  });
2603
2775
  const connecting = rendered === "connecting";
2604
2776
  return jsxs("button", {
2605
2777
  type: "button",
2606
- className: `${css$12.indicator} ${css$12.warning}${leavingClass}`,
2778
+ className: `${css$13.indicator} ${css$13.warning}${leavingClass}`,
2607
2779
  "data-phase": rendered,
2608
2780
  "aria-label": connecting ? restartActionLabel : reconnectActionLabel,
2609
2781
  onClick: onReconnect,
2610
2782
  children: [jsx("span", {
2611
- className: css$12.icon,
2783
+ className: css$13.icon,
2612
2784
  "aria-hidden": "true",
2613
2785
  children: connecting ? jsx(IconLoadingOutline16, {
2614
2786
  size: 14,
2615
- className: css$12.spinner
2787
+ className: css$13.spinner
2616
2788
  }) : jsx(IconRefreshOutline14, { size: 14 })
2617
2789
  }), jsx("span", {
2618
- className: css$12.label,
2790
+ className: css$13.label,
2619
2791
  children: connecting ? jsxs(Fragment, { children: [connectingLabel, jsxs("span", {
2620
- className: css$12.dots,
2792
+ className: css$13.dots,
2621
2793
  "aria-hidden": "true",
2622
2794
  children: [
2623
2795
  jsx("span", { children: "." }),
2624
2796
  jsx("span", {
2625
- className: css$12.secondDot,
2797
+ className: css$13.secondDot,
2626
2798
  children: "."
2627
2799
  }),
2628
2800
  jsx("span", {
2629
- className: css$12.thirdDot,
2801
+ className: css$13.thirdDot,
2630
2802
  children: "."
2631
2803
  })
2632
2804
  ]
@@ -3467,7 +3639,103 @@ function FileTypeIcon(props) {
3467
3639
  type: resolvedType,
3468
3640
  size,
3469
3641
  className
3470
- }) : glyph(resolvedType, size, clsx(css$13.icon, css$13[resolvedType], className));
3642
+ }) : glyph(resolvedType, size, clsx(css$14.icon, css$14[resolvedType], className));
3643
+ }
3644
+ //#endregion
3645
+ //#region lib/types/SiteGlyph.js
3646
+ /**
3647
+ * Host suffix to site mark, covering the developer sites the transcript
3648
+ * usually cites plus the mainstream search, video, social, shopping, and
3649
+ * reference sites a general audience links. A host matches a suffix when it
3650
+ * equals it or is a subdomain of it, and the longest matching suffix wins, so
3651
+ * `weixin.qq.com` keeps WeChat while `qq.com` keeps QQ and `gist.github.com`
3652
+ * needs no entry of its own.
3653
+ */
3654
+ const SITE_HOSTS = {
3655
+ "github.com": siGithub,
3656
+ "github.io": siGithub,
3657
+ "raw.githubusercontent.com": siGithub,
3658
+ "gitlab.com": siGitlab,
3659
+ "npmjs.com": siNpm,
3660
+ "pypi.org": siPypi,
3661
+ "stackoverflow.com": siStackoverflow,
3662
+ "developer.mozilla.org": siMdnwebdocs,
3663
+ "wikipedia.org": siWikipedia,
3664
+ "news.ycombinator.com": siYcombinator,
3665
+ "youtube.com": siYoutube,
3666
+ "youtu.be": siYoutube,
3667
+ "x.com": siX,
3668
+ "twitter.com": siX,
3669
+ "bilibili.com": siBilibili,
3670
+ "zhihu.com": siZhihu,
3671
+ "juejin.cn": siJuejin,
3672
+ "csdn.net": siCsdn,
3673
+ "google.com": siGoogle,
3674
+ "baidu.com": siBaidu,
3675
+ "duckduckgo.com": siDuckduckgo,
3676
+ "tiktok.com": siTiktok,
3677
+ "netflix.com": siNetflix,
3678
+ "spotify.com": siSpotify,
3679
+ "facebook.com": siFacebook,
3680
+ "instagram.com": siInstagram,
3681
+ "reddit.com": siReddit,
3682
+ "telegram.org": siTelegram,
3683
+ "t.me": siTelegram,
3684
+ "weixin.qq.com": siWechat,
3685
+ "qq.com": siQq,
3686
+ "whatsapp.com": siWhatsapp,
3687
+ "wa.me": siWhatsapp,
3688
+ "weibo.com": siSinaweibo,
3689
+ "taobao.com": siTaobao,
3690
+ "aliexpress.com": siAliexpress,
3691
+ "ebay.com": siEbay,
3692
+ "quora.com": siQuora,
3693
+ "v2ex.com": siV2ex,
3694
+ "apple.com": siApple
3695
+ };
3696
+ /**
3697
+ * Resolve the mark named by an external destination.
3698
+ * @param href - The link destination; only an absolute http(s) URL can name a host.
3699
+ * @returns The matched site mark, or undefined when the host is unknown or not http(s).
3700
+ */
3701
+ function siteIcon(href) {
3702
+ let host;
3703
+ try {
3704
+ const url = new URL(href);
3705
+ if (url.protocol !== "http:" && url.protocol !== "https:") return void 0;
3706
+ host = url.hostname.toLowerCase();
3707
+ } catch {
3708
+ return;
3709
+ }
3710
+ let match;
3711
+ let matched = 0;
3712
+ for (const [suffix, icon] of Object.entries(SITE_HOSTS)) if ((host === suffix || host.endsWith(`.${suffix}`)) && suffix.length > matched) {
3713
+ match = icon;
3714
+ matched = suffix.length;
3715
+ }
3716
+ return match;
3717
+ }
3718
+ /**
3719
+ * Render the site mark for a known external destination.
3720
+ * @param props - The destination and the icon sizing seat.
3721
+ * @returns The site's mark riding currentColor, or undefined for an unknown site.
3722
+ */
3723
+ function siteGlyph({ href, size, className }) {
3724
+ const icon = href === void 0 ? void 0 : siteIcon(href);
3725
+ if (icon === void 0) return void 0;
3726
+ return jsx("svg", {
3727
+ width: size,
3728
+ height: size,
3729
+ className,
3730
+ viewBox: "-2 -2 28 28",
3731
+ fill: "none",
3732
+ xmlns: "http://www.w3.org/2000/svg",
3733
+ "aria-hidden": true,
3734
+ children: jsx("path", {
3735
+ d: icon.path,
3736
+ fill: "currentColor"
3737
+ })
3738
+ });
3471
3739
  }
3472
3740
  //#endregion
3473
3741
  //#region lib/types/LinkIcon.js
@@ -3614,13 +3882,18 @@ function assertNever$1(value) {
3614
3882
  }
3615
3883
  /**
3616
3884
  * Render the leading glyph for one clickable artifact link.
3617
- * @param props - The link category, optional size (default 14px — the inline
3618
- * link text size these glyphs sit beside), and optional CSS class.
3885
+ * @param props - The link category, the optional destination that can select a
3886
+ * site mark, optional size (default 14px — the inline link text size these
3887
+ * glyphs sit beside), and optional CSS class.
3619
3888
  * @returns The category's SVG glyph, riding currentColor.
3620
3889
  */
3621
- function LinkIcon({ kind, size = 14, className }) {
3890
+ function LinkIcon({ kind, href, size = 14, className }) {
3622
3891
  switch (kind) {
3623
- case "url": return jsx(GlobeGlyph, {
3892
+ case "url": return siteGlyph({
3893
+ href,
3894
+ size,
3895
+ className
3896
+ }) ?? jsx(GlobeGlyph, {
3624
3897
  size,
3625
3898
  className
3626
3899
  });
@@ -3710,7 +3983,7 @@ function projectUserText(text, sessionLabels, slashNames = [], slashKind = "skil
3710
3983
  let cursor = 0;
3711
3984
  const pushPlain = (from, to) => {
3712
3985
  parts.push(jsx("span", {
3713
- className: css$14.plainRun,
3986
+ className: css$15.plainRun,
3714
3987
  children: text.slice(from, to)
3715
3988
  }, `t${from}`));
3716
3989
  };
@@ -3723,14 +3996,14 @@ function projectUserText(text, sessionLabels, slashNames = [], slashKind = "skil
3723
3996
  const contents = jsxs(Fragment, { children: [referenceKind !== void 0 && jsx(ReferenceIcon, {
3724
3997
  kind: referenceKind,
3725
3998
  size: 16,
3726
- className: css$14.refIcon
3999
+ className: css$15.refIcon
3727
4000
  }), displayLabel] });
3728
4001
  const open = references === void 0 ? void 0 : referenceKind === "file" ? () => {
3729
4002
  references.openFile(label.slice(1).replace(/^"|"$/gu, ""));
3730
4003
  } : referenceKind === void 0 && slashKind === "skill" ? () => {
3731
4004
  references.openSkill(label.slice(1));
3732
4005
  } : void 0;
3733
- const className = clsx(css$14.refChip, referenceKind === void 0 && css$14.slashChip);
4006
+ const className = clsx(css$15.refChip, referenceKind === void 0 && css$15.slashChip);
3734
4007
  parts.push(open === void 0 ? jsx("span", {
3735
4008
  className,
3736
4009
  "data-ref-chip": referenceKind ?? slashKind,
@@ -3750,7 +4023,7 @@ function projectUserText(text, sessionLabels, slashNames = [], slashKind = "skil
3750
4023
  cursor = end;
3751
4024
  }
3752
4025
  if (parts.length === 0) return jsx("span", {
3753
- className: css$14.plainRun,
4026
+ className: css$15.plainRun,
3754
4027
  children: text
3755
4028
  });
3756
4029
  if (cursor < text.length) pushPlain(cursor, text.length);
@@ -3759,6 +4032,12 @@ function projectUserText(text, sessionLabels, slashNames = [], slashKind = "skil
3759
4032
  //#endregion
3760
4033
  //#region lib/types/Tooltip.js
3761
4034
  /**
4035
+ * Suppression channel from a tooltip to the tooltips above it: a tooltip hands
4036
+ * this setter to its own descendants, and a visible descendant bubble calls it
4037
+ * so the ancestor withdraws its bubble for as long as the descendant shows one.
4038
+ */
4039
+ const TooltipSuppression = createContext(null);
4040
+ /**
3762
4041
  * Attach a hover/focus tooltip to an anchor element.
3763
4042
  * @param props.label - bubble text, or a resolver evaluated only while the bubble is visible.
3764
4043
  * @param props.side - placement relative to the anchor (default 'right').
@@ -3818,6 +4097,18 @@ function Tooltip({ label, side = "right", delayMs = 0, disabled = false, maxWidt
3818
4097
  hover: false,
3819
4098
  focus: false
3820
4099
  });
4100
+ const suppressAncestors = useContext(TooltipSuppression);
4101
+ const [suppressed, setSuppressed] = useState(false);
4102
+ const announce = useCallback((active) => {
4103
+ suppressAncestors?.(active);
4104
+ }, [suppressAncestors]);
4105
+ const visible = pos !== null && !disabled;
4106
+ useEffect(() => {
4107
+ announce(visible);
4108
+ return () => {
4109
+ announce(false);
4110
+ };
4111
+ }, [announce, visible]);
3821
4112
  const cancelShow = useCallback(() => {
3822
4113
  if (showTimer.current === null) return;
3823
4114
  clearTimeout(showTimer.current);
@@ -3846,6 +4137,7 @@ function Tooltip({ label, side = "right", delayMs = 0, disabled = false, maxWidt
3846
4137
  top: r.top,
3847
4138
  bottom: r.bottom
3848
4139
  });
4140
+ announce(true);
3849
4141
  };
3850
4142
  const showAfterHoverDelay = () => {
3851
4143
  cancelShow();
@@ -3858,46 +4150,53 @@ function Tooltip({ label, side = "right", delayMs = 0, disabled = false, maxWidt
3858
4150
  show();
3859
4151
  }, delayMs);
3860
4152
  };
4153
+ const withdraw = () => {
4154
+ setPos(null);
4155
+ announce(false);
4156
+ };
3861
4157
  const hide = () => {
3862
4158
  cancelShow();
3863
- if (!triggers.current.hover && !triggers.current.focus) setPos(null);
4159
+ if (!triggers.current.hover && !triggers.current.focus) withdraw();
3864
4160
  };
3865
- return jsxs(Fragment, { children: [cloneElement(children, {
3866
- ref: mergedRef,
3867
- onMouseEnter: (e) => {
3868
- children.props.onMouseEnter?.(e);
3869
- triggers.current.hover = true;
3870
- showAfterHoverDelay();
3871
- },
3872
- onMouseLeave: (e) => {
3873
- children.props.onMouseLeave?.(e);
3874
- triggers.current.hover = false;
3875
- cancelShow();
3876
- setPos(null);
3877
- },
3878
- onFocus: (e) => {
3879
- children.props.onFocus?.(e);
3880
- triggers.current.focus = true;
3881
- cancelShow();
3882
- show();
3883
- },
3884
- onBlur: (e) => {
3885
- children.props.onBlur?.(e);
3886
- triggers.current.focus = false;
3887
- hide();
3888
- }
3889
- }), pos !== null && jsx("span", {
3890
- ref: bubble,
3891
- className: css$15.bubble,
3892
- "data-side": placement,
3893
- style: {
3894
- left: pos.x,
3895
- top: y,
3896
- ...maxWidth === void 0 ? {} : { maxWidth }
3897
- },
3898
- role: "tooltip",
3899
- children: resolvedLabel
3900
- })] });
4161
+ return jsxs(TooltipSuppression.Provider, {
4162
+ value: setSuppressed,
4163
+ children: [cloneElement(children, {
4164
+ ref: mergedRef,
4165
+ onMouseEnter: (e) => {
4166
+ children.props.onMouseEnter?.(e);
4167
+ triggers.current.hover = true;
4168
+ showAfterHoverDelay();
4169
+ },
4170
+ onMouseLeave: (e) => {
4171
+ children.props.onMouseLeave?.(e);
4172
+ triggers.current.hover = false;
4173
+ cancelShow();
4174
+ withdraw();
4175
+ },
4176
+ onFocus: (e) => {
4177
+ children.props.onFocus?.(e);
4178
+ triggers.current.focus = true;
4179
+ cancelShow();
4180
+ show();
4181
+ },
4182
+ onBlur: (e) => {
4183
+ children.props.onBlur?.(e);
4184
+ triggers.current.focus = false;
4185
+ hide();
4186
+ }
4187
+ }), visible && !suppressed && jsx("span", {
4188
+ ref: bubble,
4189
+ className: css$16.bubble,
4190
+ "data-side": placement,
4191
+ style: {
4192
+ left: pos.x,
4193
+ top: y,
4194
+ ...maxWidth === void 0 ? {} : { maxWidth }
4195
+ },
4196
+ role: "tooltip",
4197
+ children: resolvedLabel
4198
+ })]
4199
+ });
3901
4200
  }
3902
4201
  //#endregion
3903
4202
  //#region lib/types/Toast.js
@@ -3949,18 +4248,18 @@ function Toast({ text, icon, anchor, holdMs = HOLD_MS, onDone }) {
3949
4248
  };
3950
4249
  }, [anchor]);
3951
4250
  return createPortal(jsxs("div", {
3952
- className: css$16.toast,
4251
+ className: css$17.toast,
3953
4252
  role: "alert",
3954
4253
  style: {
3955
4254
  ...left === null ? {} : { left },
3956
4255
  "--dsh-toast-hold": `${String(holdMs)}ms`
3957
4256
  },
3958
4257
  children: [icon !== void 0 && jsx("span", {
3959
- className: css$16.icon,
4258
+ className: css$17.icon,
3960
4259
  "aria-hidden": true,
3961
4260
  children: icon
3962
4261
  }), jsx("span", {
3963
- className: css$16.text,
4262
+ className: css$17.text,
3964
4263
  children: text
3965
4264
  })]
3966
4265
  }), document.body);
@@ -4110,6 +4409,18 @@ function rankByName(items, rawQuery) {
4110
4409
  return ranked.map((match) => match.item);
4111
4410
  }
4112
4411
  //#endregion
4412
+ //#region lib/types/darwin-desktop.js
4413
+ /** macOS desktop detection for hiddenInset-titlebar layout variants. */
4414
+ /**
4415
+ * Whether the client runs in the macOS desktop shell: the Electron preload
4416
+ * marks `<html>` with `data-platform="darwin"`; plain web never sets it.
4417
+ * Read at render time — the mark may arrive as late as DOMContentLoaded.
4418
+ * @returns true only inside the macOS Electron shell.
4419
+ */
4420
+ function isDarwinDesktop() {
4421
+ return document.documentElement.dataset.platform === "darwin";
4422
+ }
4423
+ //#endregion
4113
4424
  //#region lib/types/JsonTree.js
4114
4425
  const OBJECT_PREVIEW_LIMIT = 4;
4115
4426
  const ARRAY_PREVIEW_LIMIT = 5;
@@ -4184,7 +4495,7 @@ function JsonCopyAction({ store, target, persistent, labels, onCopy, onClose })
4184
4495
  const object = typeof target.value === "object" && target.value !== null;
4185
4496
  const copyTitle = state === "copied" ? labels.copied : state === "failed" ? labels.copyFailed : object ? labels.copyPrettyJson : labels.copyValue;
4186
4497
  return jsx("span", {
4187
- className: css$17.copySlot,
4498
+ className: css$18.copySlot,
4188
4499
  children: (persistent || snapshot !== void 0) && jsx(Menu, {
4189
4500
  open: snapshot?.menuOpen === true,
4190
4501
  compact: true,
@@ -4193,7 +4504,7 @@ function JsonCopyAction({ store, target, persistent, labels, onCopy, onClose })
4193
4504
  anchor: jsx("button", {
4194
4505
  ref: buttonRef,
4195
4506
  type: "button",
4196
- className: css$17.actionButton,
4507
+ className: css$18.actionButton,
4197
4508
  "data-json-copy-button": true,
4198
4509
  "data-state": state,
4199
4510
  "aria-label": copyTitle,
@@ -4232,35 +4543,35 @@ function bracketOf(value) {
4232
4543
  }
4233
4544
  function previewPrimitive(value) {
4234
4545
  if (value === null) return jsx("span", {
4235
- className: css$17.keywordValue,
4546
+ className: css$18.keywordValue,
4236
4547
  children: "null"
4237
4548
  });
4238
4549
  if (typeof value === "string") return jsx("span", {
4239
- className: css$17.stringValue,
4550
+ className: css$18.stringValue,
4240
4551
  children: JSON.stringify(value)
4241
4552
  });
4242
4553
  if (typeof value === "number") return jsx("span", {
4243
- className: css$17.numberValue,
4554
+ className: css$18.numberValue,
4244
4555
  children: String(value)
4245
4556
  });
4246
4557
  if (typeof value === "boolean") return jsx("span", {
4247
- className: css$17.keywordValue,
4558
+ className: css$18.keywordValue,
4248
4559
  children: String(value)
4249
4560
  });
4250
4561
  if (typeof value === "bigint") return jsx("span", {
4251
- className: css$17.otherValue,
4562
+ className: css$18.otherValue,
4252
4563
  children: value.toString()
4253
4564
  });
4254
4565
  if (typeof value === "undefined") return jsx("span", {
4255
- className: css$17.otherValue,
4566
+ className: css$18.otherValue,
4256
4567
  children: "undefined"
4257
4568
  });
4258
4569
  if (typeof value === "symbol") return jsx("span", {
4259
- className: css$17.otherValue,
4570
+ className: css$18.otherValue,
4260
4571
  children: value.description ?? "Symbol"
4261
4572
  });
4262
4573
  if (typeof value === "function") return jsx("span", {
4263
- className: css$17.otherValue,
4574
+ className: css$18.otherValue,
4264
4575
  children: value.name || "Function"
4265
4576
  });
4266
4577
  return null;
@@ -4274,71 +4585,71 @@ function previewValue(value, depth) {
4274
4585
  const [open, close] = bracketOf(value);
4275
4586
  return jsxs(Fragment, { children: [
4276
4587
  jsx("span", {
4277
- className: css$17.punctuation,
4588
+ className: css$18.punctuation,
4278
4589
  children: open
4279
4590
  }),
4280
4591
  depth >= PREVIEW_DEPTH_LIMIT ? jsx("span", {
4281
- className: css$17.previewEllipsis,
4592
+ className: css$18.previewEllipsis,
4282
4593
  children: "…"
4283
4594
  }) : visible.map(([key, item], index) => jsxs("span", { children: [
4284
4595
  index > 0 && jsx("span", {
4285
- className: css$17.punctuation,
4596
+ className: css$18.punctuation,
4286
4597
  children: ", "
4287
4598
  }),
4288
4599
  !array && jsxs(Fragment, { children: [jsx("span", {
4289
- className: css$17.previewProperty,
4600
+ className: css$18.previewProperty,
4290
4601
  children: key
4291
4602
  }), jsx("span", {
4292
- className: css$17.punctuation,
4603
+ className: css$18.punctuation,
4293
4604
  children: ": "
4294
4605
  })] }),
4295
4606
  previewValue(item, depth + 1)
4296
4607
  ] }, key)),
4297
4608
  depth < PREVIEW_DEPTH_LIMIT && entries.length > limit && jsx("span", {
4298
- className: css$17.previewEllipsis,
4609
+ className: css$18.previewEllipsis,
4299
4610
  children: ", …"
4300
4611
  }),
4301
4612
  jsx("span", {
4302
- className: css$17.punctuation,
4613
+ className: css$18.punctuation,
4303
4614
  children: close
4304
4615
  })
4305
4616
  ] });
4306
4617
  }
4307
4618
  function primitiveValue(value) {
4308
4619
  if (value === null) return jsx("span", {
4309
- className: css$17.keywordValue,
4620
+ className: css$18.keywordValue,
4310
4621
  children: "null"
4311
4622
  });
4312
4623
  if (typeof value === "string") return jsx("span", {
4313
- className: css$17.stringValue,
4624
+ className: css$18.stringValue,
4314
4625
  children: JSON.stringify(value)
4315
4626
  });
4316
4627
  if (typeof value === "boolean") return jsx("span", {
4317
- className: css$17.keywordValue,
4628
+ className: css$18.keywordValue,
4318
4629
  children: String(value)
4319
4630
  });
4320
4631
  if (typeof value === "number") return jsx("span", {
4321
- className: css$17.numberValue,
4632
+ className: css$18.numberValue,
4322
4633
  children: String(value)
4323
4634
  });
4324
4635
  if (typeof value === "bigint") return jsx("span", {
4325
- className: css$17.numberValue,
4636
+ className: css$18.numberValue,
4326
4637
  children: `${value.toString()}n`
4327
4638
  });
4328
4639
  if (value instanceof Date) return jsx("span", {
4329
- className: css$17.otherValue,
4640
+ className: css$18.otherValue,
4330
4641
  children: value.toISOString()
4331
4642
  });
4332
4643
  if (typeof value === "function") return jsxs("span", {
4333
- className: css$17.otherValue,
4644
+ className: css$18.otherValue,
4334
4645
  children: ["function() ", "{ }"]
4335
4646
  });
4336
4647
  if (typeof value === "undefined") return jsx("span", {
4337
- className: css$17.otherValue,
4648
+ className: css$18.otherValue,
4338
4649
  children: "undefined"
4339
4650
  });
4340
4651
  return jsx("span", {
4341
- className: css$17.otherValue,
4652
+ className: css$18.otherValue,
4342
4653
  children: value.toString()
4343
4654
  });
4344
4655
  }
@@ -4366,7 +4677,7 @@ function moveFocus(button, direction) {
4366
4677
  function NodeField({ field, expandable, onToggle }) {
4367
4678
  if (field === void 0) return null;
4368
4679
  return jsxs("span", {
4369
- className: clsx(css$17.label, expandable && css$17.clickableLabel),
4680
+ className: clsx(css$18.label, expandable && css$18.clickableLabel),
4370
4681
  onClick: expandable ? onToggle : void 0,
4371
4682
  children: [fieldText(field), ":"]
4372
4683
  });
@@ -4403,7 +4714,7 @@ function JsonString({ collapsedStringLines, stringWrapping, field, labels, lastE
4403
4714
  if (!expanded) return;
4404
4715
  const raw = rawRef.current;
4405
4716
  const clips = [];
4406
- const tree = raw.closest(`.${css$17.root}`);
4717
+ const tree = raw.closest(`.${css$18.root}`);
4407
4718
  for (let parent = tree.parentElement; parent !== null; parent = parent.parentElement) if (/auto|scroll|hidden|clip/.test(getComputedStyle(parent).overflowY)) clips.push(parent);
4408
4719
  const measure = () => {
4409
4720
  let top = 0;
@@ -4432,33 +4743,33 @@ function JsonString({ collapsedStringLines, stringWrapping, field, labels, lastE
4432
4743
  if (expanded) {
4433
4744
  const fieldId = `${contentsId}-field`;
4434
4745
  return jsxs("div", {
4435
- className: css$17.stringField,
4746
+ className: css$18.stringField,
4436
4747
  "data-expanded": true,
4437
4748
  children: [
4438
4749
  field !== void 0 && jsxs("span", {
4439
4750
  id: fieldId,
4440
- className: css$17.label,
4751
+ className: css$18.label,
4441
4752
  children: [fieldText(field), ":"]
4442
4753
  }),
4443
4754
  jsx("pre", {
4444
4755
  ref: rawRef,
4445
4756
  id: contentsId,
4446
- className: css$17.stringRaw,
4757
+ className: css$18.stringRaw,
4447
4758
  "data-wrap": wrapped,
4448
4759
  tabIndex: 0,
4449
4760
  "aria-labelledby": field === void 0 ? void 0 : fieldId,
4450
4761
  children: value
4451
4762
  }),
4452
4763
  !lastElement && jsx("span", {
4453
- className: css$17.punctuation,
4764
+ className: css$18.punctuation,
4454
4765
  children: ","
4455
4766
  }),
4456
4767
  jsxs("div", {
4457
- className: css$17.stringActions,
4768
+ className: css$18.stringActions,
4458
4769
  children: [
4459
4770
  stringWrapping !== void 0 && jsx("button", {
4460
4771
  type: "button",
4461
- className: css$17.actionButton,
4772
+ className: css$18.actionButton,
4462
4773
  "aria-label": stringWrapping.label,
4463
4774
  title: stringWrapping.label,
4464
4775
  "aria-pressed": wrapped,
@@ -4472,7 +4783,7 @@ function JsonString({ collapsedStringLines, stringWrapping, field, labels, lastE
4472
4783
  }),
4473
4784
  jsx("button", {
4474
4785
  type: "button",
4475
- className: css$17.actionButton,
4786
+ className: css$18.actionButton,
4476
4787
  "aria-label": labels.collapseNode,
4477
4788
  title: labels.collapseNode,
4478
4789
  "aria-expanded": true,
@@ -4498,18 +4809,18 @@ function JsonString({ collapsedStringLines, stringWrapping, field, labels, lastE
4498
4809
  });
4499
4810
  }
4500
4811
  return jsxs(Fragment, { children: [renderCopy?.(), jsx("span", {
4501
- className: css$17.stringField,
4812
+ className: css$18.stringField,
4502
4813
  "data-expanded": expanded,
4503
4814
  children: jsxs("span", {
4504
4815
  ref: contentRef,
4505
4816
  id: contentsId,
4506
- className: css$17.stringText,
4817
+ className: css$18.stringText,
4507
4818
  children: [
4508
4819
  truncated && jsx("span", {
4509
- className: css$17.stringToggleSlot,
4820
+ className: css$18.stringToggleSlot,
4510
4821
  children: jsxs("button", {
4511
4822
  type: "button",
4512
- className: css$17.stringToggle,
4823
+ className: css$18.stringToggle,
4513
4824
  "aria-label": labels.expandNode,
4514
4825
  "aria-expanded": false,
4515
4826
  "aria-controls": contentsId,
@@ -4524,12 +4835,12 @@ function JsonString({ collapsedStringLines, stringWrapping, field, labels, lastE
4524
4835
  })
4525
4836
  }),
4526
4837
  field !== void 0 && jsxs("span", {
4527
- className: css$17.label,
4838
+ className: css$18.label,
4528
4839
  children: [fieldText(field), ":"]
4529
4840
  }),
4530
4841
  primitiveValue(value),
4531
4842
  !lastElement && jsx("span", {
4532
- className: css$17.punctuation,
4843
+ className: css$18.punctuation,
4533
4844
  children: ","
4534
4845
  })
4535
4846
  ]
@@ -4560,7 +4871,7 @@ function JsonTreeNode({ collapsedStringLines, stringWrapping, field, initialExpa
4560
4871
  }
4561
4872
  };
4562
4873
  const row = (children, ariaExpanded) => jsxs("div", {
4563
- className: css$17.row,
4874
+ className: css$18.row,
4564
4875
  role: "treeitem",
4565
4876
  "aria-expanded": ariaExpanded,
4566
4877
  onMouseOver: (event) => {
@@ -4595,7 +4906,7 @@ function JsonTreeNode({ collapsedStringLines, stringWrapping, field, initialExpa
4595
4906
  }),
4596
4907
  primitiveValue(value),
4597
4908
  !lastElement && jsx("span", {
4598
- className: css$17.punctuation,
4909
+ className: css$18.punctuation,
4599
4910
  children: ","
4600
4911
  })
4601
4912
  ] }));
@@ -4607,22 +4918,22 @@ function JsonTreeNode({ collapsedStringLines, stringWrapping, field, initialExpa
4607
4918
  onToggle: toggle
4608
4919
  }),
4609
4920
  jsx("span", {
4610
- className: css$17.punctuation,
4921
+ className: css$18.punctuation,
4611
4922
  children: open
4612
4923
  }),
4613
4924
  jsx("span", {
4614
- className: css$17.punctuation,
4925
+ className: css$18.punctuation,
4615
4926
  children: close
4616
4927
  }),
4617
4928
  !lastElement && jsx("span", {
4618
- className: css$17.punctuation,
4929
+ className: css$18.punctuation,
4619
4930
  children: ","
4620
4931
  })
4621
4932
  ] }));
4622
4933
  return row(jsxs(Fragment, { children: [
4623
4934
  jsx("span", {
4624
4935
  ref: expanderRef,
4625
- className: clsx(css$17.expander, expanded ? css$17.collapseIcon : css$17.expandIcon),
4936
+ className: clsx(css$18.expander, expanded ? css$18.collapseIcon : css$18.expandIcon),
4626
4937
  "data-json-expander": true,
4627
4938
  role: "button",
4628
4939
  "aria-label": expanded ? labels.collapseNode : labels.expandNode,
@@ -4636,7 +4947,7 @@ function JsonTreeNode({ collapsedStringLines, stringWrapping, field, initialExpa
4636
4947
  onKeyDown: onExpanderKeyDown
4637
4948
  }),
4638
4949
  jsxs("span", {
4639
- className: css$17.summary,
4950
+ className: css$18.summary,
4640
4951
  children: [
4641
4952
  jsx(NodeField, {
4642
4953
  field,
@@ -4644,11 +4955,11 @@ function JsonTreeNode({ collapsedStringLines, stringWrapping, field, initialExpa
4644
4955
  onToggle: toggle
4645
4956
  }),
4646
4957
  jsx("span", {
4647
- className: css$17.preview,
4958
+ className: css$18.preview,
4648
4959
  children: previewValue(value, 0)
4649
4960
  }),
4650
4961
  !lastElement && jsx("span", {
4651
- className: css$17.punctuation,
4962
+ className: css$18.punctuation,
4652
4963
  children: ","
4653
4964
  })
4654
4965
  ]
@@ -4656,7 +4967,7 @@ function JsonTreeNode({ collapsedStringLines, stringWrapping, field, initialExpa
4656
4967
  expanded && jsx("ul", {
4657
4968
  id: contentsId,
4658
4969
  role: "group",
4659
- className: css$17.children,
4970
+ className: css$18.children,
4660
4971
  children: entries.map(([key, item], index) => jsx(JsonTreeNode, {
4661
4972
  collapsedStringLines,
4662
4973
  stringWrapping,
@@ -4788,17 +5099,17 @@ function JsonTree({ data, label, className, collapsedStringLines = 3, stringWrap
4788
5099
  onClose: clearCopyTarget
4789
5100
  }) : void 0;
4790
5101
  return jsx("div", {
4791
- className: clsx(css$17.root, className),
5102
+ className: clsx(css$18.root, className),
4792
5103
  style: { "--json-tree-collapsed-lines": collapsedStringLines },
4793
5104
  onMouseOver: handleRootMouseOver,
4794
5105
  onMouseLeave: () => {
4795
5106
  if (!copyStore.get()?.menuOpen) clearCopyTarget();
4796
5107
  },
4797
5108
  children: expandTopLevel ? jsxs("div", {
4798
- className: css$17.expandedTopLevel,
5109
+ className: css$18.expandedTopLevel,
4799
5110
  children: [
4800
5111
  jsxs("div", {
4801
- className: clsx(css$17.row, css$17.topLevelBracket),
5112
+ className: clsx(css$18.row, css$18.topLevelBracket),
4802
5113
  "data-json-root-row": true,
4803
5114
  onMouseOver: (event) => {
4804
5115
  event.stopPropagation();
@@ -4811,13 +5122,13 @@ function JsonTree({ data, label, className, collapsedStringLines = 3, stringWrap
4811
5122
  path: [],
4812
5123
  value: data
4813
5124
  }), jsx("span", {
4814
- className: css$17.punctuation,
5125
+ className: css$18.punctuation,
4815
5126
  children: rootOpen
4816
5127
  })]
4817
5128
  }),
4818
5129
  jsx("div", {
4819
5130
  "aria-label": label,
4820
- className: clsx(css$17.container, css$17.expandedTopLevelContainer),
5131
+ className: clsx(css$18.container, css$18.expandedTopLevelContainer),
4821
5132
  role: "tree",
4822
5133
  children: rootEntries.map(([key, value], index) => jsx(JsonTreeNode, {
4823
5134
  collapsedStringLines,
@@ -4835,16 +5146,16 @@ function JsonTree({ data, label, className, collapsedStringLines = 3, stringWrap
4835
5146
  }, key))
4836
5147
  }),
4837
5148
  jsx("div", {
4838
- className: clsx(css$17.row, css$17.topLevelBracket),
5149
+ className: clsx(css$18.row, css$18.topLevelBracket),
4839
5150
  children: jsx("span", {
4840
- className: css$17.punctuation,
5151
+ className: css$18.punctuation,
4841
5152
  children: rootClose
4842
5153
  })
4843
5154
  })
4844
5155
  ]
4845
5156
  }) : jsx("div", {
4846
5157
  "aria-label": label,
4847
- className: css$17.container,
5158
+ className: css$18.container,
4848
5159
  role: "tree",
4849
5160
  children: jsx(JsonTreeNode, {
4850
5161
  collapsedStringLines,
@@ -4870,8 +5181,10 @@ function JsonTree({ data, label, className, collapsedStringLines = 3, stringWrap
4870
5181
  * semantic. Black and white both resolve to the primary label color so text
4871
5182
  * stays legible under either theme instead of matching the surface it sits
4872
5183
  * on; bright black takes the tertiary label color (the muted-gray role).
4873
- * Magenta and cyan have no token equivalent in this design system and fall
4874
- * through to anser's literal rgb, as do all 256-palette and truecolor values.
5184
+ * Cyan and bright cyan take two static blues: the design system has no cyan,
5185
+ * and anser's literal bright cyan is unreadable on the light theme's code
5186
+ * surface. Magenta has no token equivalent and falls through to anser's
5187
+ * literal rgb, as do all 256-palette and truecolor values.
4875
5188
  */
4876
5189
  const TOKEN_BY_BASIC_RGB = {
4877
5190
  "0,0,0": "var(--dsw-alias-label-primary)",
@@ -4884,7 +5197,9 @@ const TOKEN_BY_BASIC_RGB = {
4884
5197
  "187,187,0": "var(--dsw-alias-state-warn-primary)",
4885
5198
  "255,255,85": "var(--dsw-alias-state-warn-secondary)",
4886
5199
  "0,0,187": "var(--dsw-alias-state-business-primary)",
4887
- "85,85,255": "var(--dsw-static-blue-400)"
5200
+ "85,85,255": "var(--dsw-static-blue-400)",
5201
+ "0,187,187": "var(--dsw-static-blue-600)",
5202
+ "85,255,255": "var(--dsw-static-blue-500)"
4888
5203
  };
4889
5204
  /**
4890
5205
  * CSS for each SGR attribute anser reports. `blink` is deliberately absent —
@@ -5324,13 +5639,14 @@ function promptLabel(cwd, home) {
5324
5639
  * Status pill text for a settled command, or undefined when the command
5325
5640
  * settled cleanly (exit 0, no signal) and needs no pill — the same
5326
5641
  * distinction the bash tool's own exit-status markers draw.
5327
- * @param exitCode - settled exit code, when known.
5642
+ * @param exitCode - settled exit code, when known; null when the command settled without one.
5328
5643
  * @param signal - settled terminating signal name, when known.
5329
5644
  * @param labels - display copy for the pill text.
5330
5645
  * @returns the pill text, or undefined for a clean exit.
5331
5646
  */
5332
5647
  function statusText(exitCode, signal, labels) {
5333
5648
  if (signal !== void 0) return labels.signal(signal);
5649
+ if (exitCode === null) return labels.noExitCode;
5334
5650
  if (exitCode !== void 0 && exitCode !== 0) return labels.exitCode(exitCode);
5335
5651
  }
5336
5652
  /**
@@ -5344,7 +5660,7 @@ function statusText(exitCode, signal, labels) {
5344
5660
  * settled command whose exit status never reached the view counts as a clean
5345
5661
  * settle: the view says it finished and says nothing went wrong.
5346
5662
  * @param running - the command has not settled.
5347
- * @param exitCode - settled exit code, when known.
5663
+ * @param exitCode - settled exit code, when known; null when the command settled without one.
5348
5664
  * @param signal - settled terminating signal name, when known.
5349
5665
  * @param labels - display copy for the text label.
5350
5666
  * @returns the dot's state and its text label, since the dot is aria-hidden.
@@ -5400,67 +5716,69 @@ function TerminalBlock({ command, cwd, home, output, exitCode, signal, running =
5400
5716
  }, [command]);
5401
5717
  const empty = lines.every((line) => line.every((span) => span.text.trim() === ""));
5402
5718
  const { hidden, capped, headLines, tailLines } = headTailCap(lines.length, maxLines, expanded);
5719
+ const body = !running || !empty;
5403
5720
  return jsxs("div", {
5404
- className: clsx(css$18.block, className),
5721
+ className: clsx(css$19.block, className),
5405
5722
  "data-terminal": "",
5406
5723
  "data-running": running ? "" : void 0,
5724
+ "data-body": body ? "" : void 0,
5407
5725
  children: [jsxs("div", {
5408
- className: css$18.header,
5726
+ className: css$19.header,
5409
5727
  children: [
5410
5728
  jsxs("div", {
5411
- className: css$18.prompt,
5729
+ className: css$19.prompt,
5412
5730
  children: [jsx("span", {
5413
- className: css$18.runStateLabel,
5731
+ className: css$19.runStateLabel,
5414
5732
  children: state.label
5415
5733
  }), commandLines.map((line, index) => jsxs("div", {
5416
- className: css$18.promptLine,
5734
+ className: css$19.promptLine,
5417
5735
  children: [
5418
5736
  index === 0 && jsx(StateDot, {
5419
5737
  state: state.state,
5420
- className: css$18.runState
5738
+ className: css$19.runState
5421
5739
  }),
5422
5740
  jsx("span", {
5423
- className: css$18.cwd,
5741
+ className: css$19.cwd,
5424
5742
  children: index > 0 || cwd === void 0 ? "$" : promptLabel(cwd, home)
5425
5743
  }),
5426
5744
  jsx("span", {
5427
- className: css$18.command,
5745
+ className: css$19.command,
5428
5746
  children: line
5429
5747
  })
5430
5748
  ]
5431
5749
  }, index))]
5432
5750
  }),
5433
5751
  status !== void 0 && jsx(Pill, {
5434
- className: css$18.status,
5752
+ className: css$19.status,
5435
5753
  children: status
5436
5754
  }),
5437
5755
  !running && !empty && jsx("button", {
5438
5756
  type: "button",
5439
- className: css$18.copyButton,
5757
+ className: css$19.copyButton,
5440
5758
  onClick: onCopy,
5441
5759
  children: copied ? copy.copied : copy.copy
5442
5760
  })
5443
5761
  ]
5444
- }), !running && (empty ? jsx("div", {
5445
- className: css$18.empty,
5762
+ }), body && (empty ? jsx("div", {
5763
+ className: css$19.empty,
5446
5764
  children: copy.noOutput
5447
5765
  }) : jsxs("div", {
5448
- className: css$18.output,
5766
+ className: css$19.output,
5449
5767
  children: [
5450
5768
  (capped ? lines.slice(0, headLines) : lines).map((line, index) => jsx("div", {
5451
- className: css$18.line,
5769
+ className: css$19.line,
5452
5770
  children: renderLine$1(line)
5453
5771
  }, index)),
5454
5772
  hidden > 0 && jsx("button", {
5455
5773
  type: "button",
5456
- className: css$18.expand,
5774
+ className: css$19.expand,
5457
5775
  "aria-expanded": expanded,
5458
5776
  "aria-label": expanded ? copy.collapseAria : copy.expandAria(hidden),
5459
5777
  onClick: onToggle,
5460
5778
  children: expanded ? copy.collapse : copy.expand(hidden)
5461
5779
  }),
5462
5780
  capped && lines.slice(lines.length - tailLines).map((line, index) => jsx("div", {
5463
- className: css$18.line,
5781
+ className: css$19.line,
5464
5782
  children: renderLine$1(line)
5465
5783
  }, index))
5466
5784
  ]
@@ -6038,51 +6356,51 @@ function ReadBlock({ label, labels, lines, totalLines, lang, maxLines = 16, clas
6038
6356
  const tailLines = maxLines - headLines;
6039
6357
  const windowed = lines.length < totalLines;
6040
6358
  const rows = (slice) => slice.map(([line, spans]) => jsxs("div", {
6041
- className: css$19.line,
6359
+ className: css$20.line,
6042
6360
  children: [jsx("span", {
6043
- className: css$19.gutter,
6361
+ className: css$20.gutter,
6044
6362
  "aria-hidden": true,
6045
6363
  children: line.number
6046
6364
  }), jsx("span", {
6047
- className: css$19.content,
6365
+ className: css$20.content,
6048
6366
  children: spans === void 0 ? line.text : renderSpans(spans)
6049
6367
  })]
6050
6368
  }, line.number));
6051
6369
  const paired = lines.map((line, index) => [line, highlighted?.[index]]);
6052
6370
  return jsxs("div", {
6053
6371
  ref: rootRef,
6054
- className: clsx(css$19.block, className),
6372
+ className: clsx(css$20.block, className),
6055
6373
  "data-read": "",
6056
6374
  children: [jsxs("div", {
6057
- className: css$19.banner,
6375
+ className: css$20.banner,
6058
6376
  children: [jsx("div", {
6059
- className: css$19.label,
6377
+ className: css$20.label,
6060
6378
  children: label ?? ""
6061
6379
  }), jsxs("div", {
6062
- className: css$19.action,
6380
+ className: css$20.action,
6063
6381
  children: [
6064
6382
  windowed && jsx("span", {
6065
- className: css$19.count,
6383
+ className: css$20.count,
6066
6384
  children: labels.window(lines.length, totalLines)
6067
6385
  }),
6068
6386
  jsx("span", {
6069
- className: css$19.lang,
6387
+ className: css$20.lang,
6070
6388
  children: lang ?? ""
6071
6389
  }),
6072
6390
  lines.length > 0 && jsx("button", {
6073
6391
  type: "button",
6074
- className: css$19.copyButton,
6392
+ className: css$20.copyButton,
6075
6393
  onClick: onCopy,
6076
6394
  children: copied ? labels.copied : labels.copy
6077
6395
  })
6078
6396
  ]
6079
6397
  })]
6080
6398
  }), jsxs("div", {
6081
- className: css$19.body,
6399
+ className: css$20.body,
6082
6400
  children: [
6083
6401
  rows(capped ? paired.slice(0, headLines) : paired),
6084
6402
  hidden > 0 && jsx(FoldToggle, {
6085
- className: css$19.expand,
6403
+ className: css$20.expand,
6086
6404
  expanded,
6087
6405
  hidden,
6088
6406
  labels,
@@ -6104,11 +6422,11 @@ function assertNever(value) {
6104
6422
  }
6105
6423
  /** The dim class per row kind (path/gap chrome vs the diff's own +/- colors). */
6106
6424
  const ROW_CLASS = {
6107
- path: css$20.path,
6108
- del: css$20.del,
6109
- add: css$20.add,
6110
- context: css$20.context,
6111
- gap: css$20.gap
6425
+ path: css$21.path,
6426
+ del: css$21.del,
6427
+ add: css$21.add,
6428
+ context: css$21.context,
6429
+ gap: css$21.gap
6112
6430
  };
6113
6431
  /** Bound synchronous edit-graph search; one replacement consumes two edits. */
6114
6432
  const MAX_DIFF_EDIT_LENGTH = 256;
@@ -6246,37 +6564,37 @@ function DiffBlock({ diffs, labels, maxLines = 16, className }) {
6246
6564
  const head = capped ? rows.slice(0, headLines) : rows;
6247
6565
  const tail = capped ? rows.slice(rows.length - tailLines) : [];
6248
6566
  return jsxs("div", {
6249
- className: clsx(css$20.block, className),
6567
+ className: clsx(css$21.block, className),
6250
6568
  "data-diff": "",
6251
6569
  children: [
6252
6570
  jsx("button", {
6253
6571
  type: "button",
6254
- className: css$20.copyButton,
6572
+ className: css$21.copyButton,
6255
6573
  onClick: onCopy,
6256
6574
  children: copied ? labels.copied : labels.copy
6257
6575
  }),
6258
6576
  jsxs("div", {
6259
- className: css$20.body,
6577
+ className: css$21.body,
6260
6578
  children: [
6261
6579
  head.map((row, index) => jsx("div", {
6262
- className: clsx(css$20.line, ROW_CLASS[row.kind]),
6580
+ className: clsx(css$21.line, ROW_CLASS[row.kind]),
6263
6581
  children: row.text
6264
6582
  }, index)),
6265
6583
  hidden > 0 && jsx(FoldToggle, {
6266
- className: css$20.expand,
6584
+ className: css$21.expand,
6267
6585
  expanded,
6268
6586
  hidden,
6269
6587
  labels,
6270
6588
  onToggle
6271
6589
  }),
6272
6590
  tail.map((row, index) => jsx("div", {
6273
- className: clsx(css$20.line, ROW_CLASS[row.kind]),
6591
+ className: clsx(css$21.line, ROW_CLASS[row.kind]),
6274
6592
  children: row.text
6275
6593
  }, index))
6276
6594
  ]
6277
6595
  }),
6278
6596
  jsxs("div", {
6279
- className: css$20.footer,
6597
+ className: css$21.footer,
6280
6598
  children: [
6281
6599
  "└ +",
6282
6600
  added,
@@ -6412,56 +6730,56 @@ function SearchBlock(props) {
6412
6730
  const tail = tailHeader === void 0 ? naturalTail : naturalTail.slice(1);
6413
6731
  const renderRow = (row) => {
6414
6732
  if (row.type === "path") return jsx("div", {
6415
- className: css$21.line,
6733
+ className: css$22.line,
6416
6734
  children: row.path
6417
6735
  });
6418
6736
  if (row.type === "match") return jsxs("div", {
6419
- className: css$21.line,
6737
+ className: css$22.line,
6420
6738
  children: [jsxs("span", {
6421
- className: css$21.lineNumber,
6739
+ className: css$22.lineNumber,
6422
6740
  children: [row.lineNumber, ": "]
6423
6741
  }), row.line]
6424
6742
  });
6425
6743
  return jsxs("button", {
6426
6744
  type: "button",
6427
- className: css$21.fileHeader,
6745
+ className: css$22.fileHeader,
6428
6746
  "aria-expanded": !row.collapsed,
6429
6747
  onClick: () => {
6430
6748
  toggleFile(row.index);
6431
6749
  },
6432
6750
  children: [jsx("span", {
6433
- className: css$21.filePath,
6751
+ className: css$22.filePath,
6434
6752
  children: row.path
6435
6753
  }), jsx("span", {
6436
- className: css$21.fileCount,
6754
+ className: css$22.fileCount,
6437
6755
  children: row.count
6438
6756
  })]
6439
6757
  });
6440
6758
  };
6441
6759
  return jsxs("div", {
6442
- className: clsx(css$21.block, className),
6760
+ className: clsx(css$22.block, className),
6443
6761
  "data-search": props.kind,
6444
6762
  children: [jsxs("div", {
6445
- className: css$21.header,
6763
+ className: css$22.header,
6446
6764
  children: [jsx("span", {
6447
- className: css$21.summary,
6765
+ className: css$22.summary,
6448
6766
  children: summaryText(props, shown, truncated, total)
6449
6767
  }), !empty && jsx("button", {
6450
6768
  type: "button",
6451
- className: css$21.copyButton,
6769
+ className: css$22.copyButton,
6452
6770
  onClick: onCopy,
6453
6771
  children: copied ? props.labels.copied : props.labels.copy
6454
6772
  })]
6455
6773
  }), empty ? jsx("div", {
6456
- className: css$21.empty,
6774
+ className: css$22.empty,
6457
6775
  children: props.labels.noResults
6458
6776
  }) : jsxs("div", {
6459
- className: css$21.body,
6777
+ className: css$22.body,
6460
6778
  children: [
6461
6779
  head.map((row) => jsx("div", { children: renderRow(row) }, rowKey(row))),
6462
6780
  hidden > 0 && jsx("button", {
6463
6781
  type: "button",
6464
- className: css$21.expand,
6782
+ className: css$22.expand,
6465
6783
  "aria-expanded": expanded,
6466
6784
  "aria-label": expanded ? props.labels.collapseAria : props.labels.expandAria(hidden),
6467
6785
  onClick: onToggle,
@@ -7263,7 +7581,7 @@ function CodeBlock({ code, lang, streaming, className, contentRef, lineNumbers =
7263
7581
  });
7264
7582
  }, [copied, trimmed]);
7265
7583
  const body = streamedBody !== void 0 ? streamedBody : html === void 0 ? jsx("pre", {
7266
- className: css$22.plain,
7584
+ className: css$23.plain,
7267
7585
  children: jsx("code", { children: sourceLines === void 0 ? trimmed : sourceLines.map((line, index) => jsxs(Fragment$1, { children: [index > 0 && "\n", jsx("span", {
7268
7586
  className: "line",
7269
7587
  children: line
@@ -7271,22 +7589,22 @@ function CodeBlock({ code, lang, streaming, className, contentRef, lineNumbers =
7271
7589
  }) : jsx("div", { dangerouslySetInnerHTML: { __html: html } });
7272
7590
  return jsxs("div", {
7273
7591
  ref: rootRef,
7274
- className: clsx(css$22.block, "md-code-block", lineNumbers && css$22.numbered, className),
7592
+ className: clsx(css$23.block, "md-code-block", lineNumbers && css$23.numbered, className),
7275
7593
  "data-line-numbers": lineNumbers || void 0,
7276
7594
  style: sourceLines === void 0 ? void 0 : { "--dsl-code-block-line-number-width": `${Math.max(2, String(sourceLines.length).length)}ch` },
7277
7595
  children: [showHeader && jsx("div", {
7278
- className: css$22.bannerWrap,
7596
+ className: css$23.bannerWrap,
7279
7597
  children: jsxs("div", {
7280
- className: css$22.banner,
7598
+ className: css$23.banner,
7281
7599
  "data-code-block-banner": true,
7282
7600
  children: [jsx("div", {
7283
- className: css$22.infostring,
7601
+ className: css$23.infostring,
7284
7602
  children: lang ?? ""
7285
7603
  }), jsx("div", {
7286
- className: css$22.action,
7604
+ className: css$23.action,
7287
7605
  children: jsx("button", {
7288
7606
  type: "button",
7289
- className: css$22.copyButton,
7607
+ className: css$23.copyButton,
7290
7608
  onClick: onCopy,
7291
7609
  children: copied ? copiedLabel : copyLabel
7292
7610
  })
@@ -7294,13 +7612,46 @@ function CodeBlock({ code, lang, streaming, className, contentRef, lineNumbers =
7294
7612
  })
7295
7613
  }), jsx("div", {
7296
7614
  ref: contentRef,
7297
- className: css$22.content,
7615
+ className: css$23.content,
7298
7616
  "data-code-block-content": true,
7299
7617
  children: body
7300
7618
  })]
7301
7619
  });
7302
7620
  }
7303
7621
  //#endregion
7622
+ //#region lib/types/markdown/file-link.js
7623
+ /** Local Markdown destinations accepted by the file-preview callback. */
7624
+ /**
7625
+ * Decode a file destination and its optional GitHub-style line fragment.
7626
+ * Literal `?` and `#` in filenames must be percent-encoded.
7627
+ * @param value - Parsed Markdown link destination.
7628
+ * @returns A local path and optional first line, or undefined for URLs,
7629
+ * fragment-only links, queries, malformed escapes, or invalid line ranges.
7630
+ */
7631
+ function parseFileLink(value) {
7632
+ const hash = value.indexOf("#");
7633
+ const destination = hash < 0 ? value : value.slice(0, hash);
7634
+ if (destination.includes("?")) return void 0;
7635
+ let path;
7636
+ try {
7637
+ path = decodeURIComponent(destination);
7638
+ } catch (_error) {
7639
+ return;
7640
+ }
7641
+ if (path.length === 0 || /[\u0000-\u001f\u007f]/.test(path) || /^[\\/]{2}/.test(path) || /^[a-z][a-z\d+.-]*:/i.test(path) && !/^[a-z]:[\\/]/i.test(path)) return void 0;
7642
+ if (hash < 0) return { path };
7643
+ const fragment = value.slice(hash + 1);
7644
+ const match = /^L([1-9]\d*)(?:-L([1-9]\d*))?$/.exec(fragment);
7645
+ if (match === null) return void 0;
7646
+ const line = Number(match[1]);
7647
+ const end = match[2] === void 0 ? line : Number(match[2]);
7648
+ if (!Number.isSafeInteger(line) || !Number.isSafeInteger(end) || end < line) return void 0;
7649
+ return {
7650
+ path,
7651
+ line
7652
+ };
7653
+ }
7654
+ //#endregion
7304
7655
  //#region lib/types/markdown/katex.js
7305
7656
  /**
7306
7657
  * TeX-to-React via KaTeX, replicating the rehype-katex pipeline this renderer
@@ -7382,6 +7733,33 @@ function renderTexToReact(value, displayMode) {
7382
7733
  return [...new DOMParser().parseFromString(html, "text/html").body.childNodes].map(domToReact);
7383
7734
  }
7384
7735
  //#endregion
7736
+ //#region lib/types/markdown/MarkdownDelegate.js
7737
+ /** Consumer-owned navigation for Markdown links. */
7738
+ const MarkdownDelegateContext = createContext({});
7739
+ /**
7740
+ * Scope Markdown navigation without threading callbacks through renderers.
7741
+ * Nested providers replace the enclosing capabilities. Handler changes reach cached links.
7742
+ * @param props - Child tree and its file and HTTP(S) link handlers.
7743
+ * @returns the scoped child tree.
7744
+ */
7745
+ function MarkdownDelegateProvider({ children, openExternalLink, openFile }) {
7746
+ const delegate = useMemo(() => ({
7747
+ openExternalLink,
7748
+ openFile
7749
+ }), [openExternalLink, openFile]);
7750
+ return jsx(MarkdownDelegateContext.Provider, {
7751
+ value: delegate,
7752
+ children
7753
+ });
7754
+ }
7755
+ /**
7756
+ * Read the nearest Markdown navigation capabilities.
7757
+ * @returns Owner callbacks, or an empty delegate outside a provider.
7758
+ */
7759
+ function useMarkdownDelegate() {
7760
+ return useContext(MarkdownDelegateContext);
7761
+ }
7762
+ //#endregion
7385
7763
  //#region lib/types/markdown/render.js
7386
7764
  /**
7387
7765
  * Direct mdast→React markdown renderer. Replaces the react-markdown /
@@ -7389,8 +7767,8 @@ function renderTexToReact(value, displayMode) {
7389
7767
  * cache frozen blocks as React elements; the rendered DOM is pinned
7390
7768
  * byte-for-byte by `tests/fixtures/markdown-dom` and must not drift.
7391
7769
  *
7392
- * Untrusted-output policy (unchanged from the replaced pipeline): link and
7393
- * image destinations pass a protocol allowlist, images additionally require
7770
+ * External link and image destinations pass a protocol allowlist; settled
7771
+ * local file links use an explicit owner callback. Images additionally require
7394
7772
  * absolute HTTP(S), raw HTML renders as literal text (no HTML enters the
7395
7773
  * DOM), and KaTeX runs without trusted commands. Fragment-anchor URLs fail
7396
7774
  * the allowlist, so footnote references and back-references render as plain
@@ -7556,7 +7934,7 @@ function renderNode(node, key, context) {
7556
7934
  case "link": return renderAnchor(node.url, renderChildren(node.children, {
7557
7935
  ...context,
7558
7936
  inLink: true
7559
- }), key, !anchorWrapsOnlyImages(node.children));
7937
+ }), key, !anchorWrapsOnlyImages(node.children), context.streaming);
7560
7938
  case "linkReference": return renderLinkReference(node, key, context);
7561
7939
  case "image": return renderImage(node.url, node.alt ?? "", key, context);
7562
7940
  case "imageReference": return renderImageReference(node, key, context);
@@ -7659,26 +8037,64 @@ function renderTableRow(row, cellTag, align, key, context) {
7659
8037
  function anchorWrapsOnlyImages(children) {
7660
8038
  return children.length > 0 && children.every((child) => child.type === "image" || child.type === "imageReference");
7661
8039
  }
7662
- /** Anchor over an already-authored href: allowlisted or unwrapped, external links get the safe attributes. */
8040
+ /** Anchor over an already-authored href: allowlisted or unwrapped, with optional owner navigation for HTTP(S). */
7663
8041
  function renderSafeLink(href, children, key, glyph = true) {
7664
8042
  const safeHref = sanitizeUrl(href);
7665
8043
  if (safeHref === "") return jsx(Fragment$1, { children }, key);
7666
- return jsxs("a", {
8044
+ return jsx(MarkdownAnchor, {
7667
8045
  href: safeHref,
7668
- ...["http:", "https:"].includes(new URL(safeHref).protocol) ? {
8046
+ glyph,
8047
+ children
8048
+ }, key);
8049
+ }
8050
+ function MarkdownAnchor({ href, glyph, children }) {
8051
+ const { openExternalLink } = useMarkdownDelegate();
8052
+ const external = ["http:", "https:"].includes(new URL(href).protocol);
8053
+ const open = external ? openExternalLink : void 0;
8054
+ return jsxs("a", {
8055
+ href,
8056
+ ...external ? {
7669
8057
  target: "_blank",
7670
8058
  rel: "noopener noreferrer"
7671
8059
  } : {},
8060
+ onClick: open === void 0 ? void 0 : (event) => {
8061
+ if (event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
8062
+ event.preventDefault();
8063
+ open(href);
8064
+ },
7672
8065
  children: [glyph && jsx(LinkIcon, {
7673
8066
  kind: "url",
8067
+ href,
7674
8068
  className: markdownCss.linkIcon
7675
8069
  }), children]
7676
- }, key);
8070
+ });
7677
8071
  }
7678
- /** Anchor over a parsed markdown destination, which hast normalized before the allowlist saw it. */
7679
- function renderAnchor(url, children, key, glyph = true) {
8072
+ /** Local destinations use the scoped file delegate after settlement. */
8073
+ function renderAnchor(url, children, key, glyph = true, streaming = false) {
8074
+ const file = streaming ? void 0 : parseFileLink(url);
8075
+ if (file !== void 0) return jsx(MarkdownFileLink, {
8076
+ file,
8077
+ glyph,
8078
+ children
8079
+ }, key);
7680
8080
  return renderSafeLink(normalizeUri(url), children, key, glyph);
7681
8081
  }
8082
+ function MarkdownFileLink({ file, glyph, children }) {
8083
+ const { openFile } = useMarkdownDelegate();
8084
+ if (openFile === void 0) return jsx(Fragment, { children });
8085
+ return jsxs("button", {
8086
+ type: "button",
8087
+ className: clsx(markdownCss.fileMention, markdownCss.fileLink),
8088
+ title: file.path,
8089
+ onClick: () => {
8090
+ openFile(file.path, file.line === void 0 ? void 0 : { line: file.line });
8091
+ },
8092
+ children: [glyph && jsx(LinkIcon, {
8093
+ kind: classifyLinkPath(file.path),
8094
+ className: markdownCss.linkIcon
8095
+ }), children]
8096
+ });
8097
+ }
7682
8098
  /**
7683
8099
  * The complete inline-code value when it is exactly an absolute HTTP(S) URL
7684
8100
  * (no surrounding whitespace); anything else stays inert code.
@@ -7740,7 +8156,7 @@ function renderLinkReference(node, key, context) {
7740
8156
  ...context,
7741
8157
  inLink: true
7742
8158
  });
7743
- return renderAnchor(definition.url, rendered, key, !anchorWrapsOnlyImages(node.children));
8159
+ return renderAnchor(definition.url, rendered, key, !anchorWrapsOnlyImages(node.children), context.streaming);
7744
8160
  }
7745
8161
  function renderImageReference(node, key, context) {
7746
8162
  const definition = context.targets.definitions.get(node.identifier.toUpperCase());
@@ -7928,15 +8344,21 @@ var StreamingRenderer = class {
7928
8344
  * identity discards the streaming render cache mid-message. `fileMentions`
7929
8345
  * links inline-code tokens its resolver recognizes as real files, and
7930
8346
  * `pathImages` rewrites image destinations that are local file paths into
7931
- * displayable URLs its resolver vouches for; both vocabularies are the
8347
+ * displayable URLs its resolver vouches for. Those two vocabularies are the
7932
8348
  * single streaming gate — they apply to settled renders only, because a
7933
8349
  * streaming message's vocabulary is not final and frozen cached elements
7934
- * must not bake in handlers that could go stale.
7935
- * @returns A GFM document with TeX math rendered through KaTeX; raw HTML,
7936
- * relative links, and unsafe protocols are disabled, while absolute HTTP(S)
7937
- * images render directly.
7938
- */
7939
- const MarkdownText = memo(function MarkdownText({ text, streaming = false, labels, fileMentions, pathImages }) {
8350
+ * must not bake in handlers that could go stale. A surrounding
8351
+ * `MarkdownDelegateProvider` can delegate ordinary HTTP(S) activation while
8352
+ * modified clicks retain native behavior. `variant="compact"` uses secondary
8353
+ * text sizing, uniform bold headings, and tight block spacing; the default
8354
+ * `body` variant uses the full document typography.
8355
+ * The provider's `openFile` enables local Markdown links in settled messages,
8356
+ * including `#L24` and `#L24-L30` destinations (ranges open at their first line).
8357
+ * @returns A GFM document with TeX math rendered through KaTeX; raw HTML and
8358
+ * unsafe protocols are disabled. Local links without an opener remain text;
8359
+ * absolute HTTP(S) images render directly.
8360
+ */
8361
+ const MarkdownText = memo(function MarkdownText({ text, streaming = false, labels, fileMentions, pathImages, variant = "body" }) {
7940
8362
  const streamRef = useRef(null);
7941
8363
  const streamLabelsRef = useRef(labels);
7942
8364
  const children = useMemo(() => {
@@ -7957,7 +8379,8 @@ const MarkdownText = memo(function MarkdownText({ text, streaming = false, label
7957
8379
  pathImages
7958
8380
  ]);
7959
8381
  return jsx("div", {
7960
- className: markdownCss.markdown,
8382
+ className: clsx(markdownCss.markdown, variant === "compact" && markdownCss.compact),
8383
+ "data-markdown-variant": variant === "compact" ? variant : void 0,
7961
8384
  children
7962
8385
  });
7963
8386
  });
@@ -8020,7 +8443,8 @@ function SafeLink({ url, label, className }) {
8020
8443
  rel: "noopener noreferrer",
8021
8444
  children: [jsx(LinkIcon, {
8022
8445
  kind: "url",
8023
- className: css$23.linkIcon
8446
+ href,
8447
+ className: css$24.linkIcon
8024
8448
  }), label]
8025
8449
  });
8026
8450
  }
@@ -8035,20 +8459,20 @@ function SafeLink({ url, label, className }) {
8035
8459
  */
8036
8460
  function SourceItem({ source, ordinal }) {
8037
8461
  return jsxs("li", {
8038
- className: css$23.source,
8462
+ className: css$24.source,
8039
8463
  value: ordinal,
8040
8464
  children: [
8041
8465
  jsx(SafeLink, {
8042
8466
  url: source.url,
8043
8467
  label: linkLabel(source.url, source.title),
8044
- className: css$23.sourceLink
8468
+ className: css$24.sourceLink
8045
8469
  }),
8046
8470
  source.snippet !== void 0 && source.snippet !== "" && jsx("div", {
8047
- className: css$23.snippet,
8471
+ className: css$24.snippet,
8048
8472
  children: source.snippet
8049
8473
  }),
8050
8474
  source.publishedAt !== void 0 && source.publishedAt !== "" && jsx("div", {
8051
- className: css$23.published,
8475
+ className: css$24.published,
8052
8476
  children: source.publishedAt
8053
8477
  })
8054
8478
  ]
@@ -8063,28 +8487,28 @@ function SourceItem({ source, ordinal }) {
8063
8487
  function WebSearchBlock({ answer, sources, truncated, labels, className }) {
8064
8488
  const empty = (answer === void 0 || answer === "") && sources.length === 0;
8065
8489
  return jsxs("div", {
8066
- className: clsx(css$23.block, className),
8490
+ className: clsx(css$24.block, className),
8067
8491
  "data-web": "search",
8068
8492
  children: [
8069
8493
  answer !== void 0 && answer !== "" && jsx("div", {
8070
- className: css$23.answer,
8494
+ className: css$24.answer,
8071
8495
  children: jsx(MarkdownText, {
8072
8496
  text: answer,
8073
8497
  labels: labels.markdown
8074
8498
  })
8075
8499
  }),
8076
8500
  empty ? jsx("div", {
8077
- className: css$23.empty,
8501
+ className: css$24.empty,
8078
8502
  children: labels.noResults
8079
8503
  }) : jsx("ol", {
8080
- className: css$23.sources,
8504
+ className: css$24.sources,
8081
8505
  children: sources.map((source, index) => jsx(SourceItem, {
8082
8506
  source,
8083
8507
  ordinal: index + 1
8084
8508
  }, index))
8085
8509
  }),
8086
8510
  truncated && jsx("div", {
8087
- className: css$23.truncated,
8511
+ className: css$24.truncated,
8088
8512
  children: labels.sourcesTruncated
8089
8513
  })
8090
8514
  ]
@@ -8097,23 +8521,23 @@ function WebSearchBlock({ answer, sources, truncated, labels, className }) {
8097
8521
  */
8098
8522
  function WebFetchBlock({ url, statusCode, truncated, labels, className }) {
8099
8523
  return jsxs("div", {
8100
- className: clsx(css$23.block, css$23.fetch, className),
8524
+ className: clsx(css$24.block, css$24.fetch, className),
8101
8525
  "data-web": "fetch",
8102
8526
  children: [jsx(SafeLink, {
8103
8527
  url,
8104
8528
  label: url,
8105
- className: css$23.fetchUrl
8529
+ className: css$24.fetchUrl
8106
8530
  }), jsxs("div", {
8107
- className: css$23.fetchMeta,
8531
+ className: css$24.fetchMeta,
8108
8532
  children: [jsxs("span", {
8109
- className: css$23.status,
8533
+ className: css$24.status,
8110
8534
  children: [
8111
8535
  labels.http,
8112
8536
  " ",
8113
8537
  statusCode
8114
8538
  ]
8115
8539
  }), truncated && jsx("span", {
8116
- className: css$23.truncated,
8540
+ className: css$24.truncated,
8117
8541
  children: labels.contentTruncated
8118
8542
  })]
8119
8543
  })]
@@ -8147,10 +8571,10 @@ function JsonBlock({ label, payload, defaultOpen = false, truncatedLabel }) {
8147
8571
  truncatedLabel
8148
8572
  ]);
8149
8573
  return jsxs("div", {
8150
- className: css$24.root,
8574
+ className: css$25.root,
8151
8575
  children: [jsxs("button", {
8152
8576
  type: "button",
8153
- className: css$24.toggle,
8577
+ className: css$25.toggle,
8154
8578
  onClick: () => {
8155
8579
  setOpen((v) => !v);
8156
8580
  },
@@ -8160,7 +8584,7 @@ function JsonBlock({ label, payload, defaultOpen = false, truncatedLabel }) {
8160
8584
  label
8161
8585
  ]
8162
8586
  }), open && jsx("pre", {
8163
- className: css$24.body,
8587
+ className: css$25.body,
8164
8588
  children: body
8165
8589
  })]
8166
8590
  });
@@ -8237,6 +8661,6 @@ function extractMarkdownPlainText(markdown, options = {}) {
8237
8661
  }
8238
8662
  }
8239
8663
  //#endregion
8240
- export { BrandWordmark, Button, CodeBlock, ConnectionIndicator, DEFAULT_DIFF_MAX_LINES, DEFAULT_READ_MAX_LINES, DEFAULT_SEARCH_MAX_LINES, DEFAULT_TERMINAL_MAX_LINES, DiffBlock, DisclosureRow, FISH_LOGO_PATH, FISH_LOGO_VIEWBOX, FileTypeIcon, FishLogo, HoverCard, IconAgentPresetOutline16, IconAlarmClockOutline16, IconApiOutline14, IconArchiveOutline20, IconBranchOutline16, IconBrowseOutline16, IconCheckOutline14, IconCheckOutline16, IconChecklistOutline14, IconChevronDownOutline14, IconChevronLeftOutline14, IconChevronRightOutline14, IconChevronUpOutline14, IconClockOutline16, IconCloseFill14, IconCloseOutline16, IconCodeOutline16, IconCompactOutline16, IconContextInjectionOutline16, IconCopyOutline16, IconCordisPluginOutline14, IconDarkOutline16, IconDataOutline16, IconDatabaseOutline16, IconDislikeFill16, IconDislikeOutline16, IconDownloadOutline16, IconEditOutline16, IconEllipsisOutline16, IconEnhanceOutline16, IconFolderClose16, IconFolderOpen16, IconFolderOpenOutline16, IconFollowsystemOutline16, IconFullscreenOutline16, IconGaugeOutline16, IconGlobeOutline14, IconGoalOutline16, IconInspectOutline12, IconLightOutline16, IconLikeFill16, IconLikeOutline16, IconLinkOutline14, IconLinkOutline16, IconListPenOutline16, IconLoadingOutline16, IconNewChatOutline16, IconPanelLeftOutline16, IconPaperPlaneOutline14, IconPaperclipOutline16, IconPauseOutline16, IconPersonalizationOutline16, IconPlanOutline14, IconPlayOutline16, IconPlusOutline16, IconProjectAddOutline16, IconQuestionOutline14, IconQueueOutline14, IconRefreshOutline14, IconRefreshOutline16, IconRightUpOutline14, IconRightUpOutline16, IconSearchOutline16, IconSendOutline14, IconSettingsOutline14, IconSettingsOutline16, IconShareOutline16, IconShieldOutline16, IconSkillOutline16, IconSparkle16, IconStopFill16, IconThinkOutline14, IconThinkOutline16, IconTrashOutline16, IconTreeCorner8x10, IconTriangleRightFill14, IconUserOutline16, IconWarningOutline16, IconWrapLinesOutline16, Input, JsonBlock, JsonTree, LinkIcon, MarkdownText, Menu, Modal, OnboardingSurface, Pill, ReadBlock, ReferenceIcon, RiskConfirmation, SHIELD_OUTLINE_PATH, SHIELD_OUTLINE_STROKE, SearchBlock, StateDot, Switch, Tag, TerminalBlock, Toast, Tooltip, WebBlock, classifyFileType, classifyLinkPath, diffTotals, extractMarkdownPlainText, fileExtension, fileSizeText, projectUserText, rankByName, relativeTime, useAnchoredMaxHeight, useAnchoredPosition, useDismissOnOutsidePointer, writeClipboard };
8664
+ export { BrandWordmark, Button, Checkbox, CodeBlock, ConnectionIndicator, DEFAULT_DIFF_MAX_LINES, DEFAULT_READ_MAX_LINES, DEFAULT_SEARCH_MAX_LINES, DEFAULT_TERMINAL_MAX_LINES, DiffBlock, DisclosureRow, FISH_LOGO_PATH, FISH_LOGO_VIEWBOX, FileTypeIcon, FishLogo, HoverCard, IconAgentPresetOutline16, IconAlarmClockOutline16, IconApiOutline14, IconArchiveOutline20, IconBranchOutline16, IconBrowseOutline16, IconCheckOutline14, IconCheckOutline16, IconChecklistOutline14, IconChevronDownOutline14, IconChevronLeftOutline14, IconChevronRightOutline14, IconChevronUpOutline14, IconClockOutline16, IconCloseFill14, IconCloseOutline16, IconCodeOutline16, IconCompactOutline16, IconContextInjectionOutline16, IconCopyOutline16, IconCordisPluginOutline14, IconDarkOutline16, IconDataOutline16, IconDatabaseOutline16, IconDislikeFill16, IconDislikeOutline16, IconDownloadOutline16, IconEditOutline16, IconEllipsisOutline16, IconEnhanceOutline16, IconFolderClose16, IconFolderOpen16, IconFolderOpenOutline16, IconFollowsystemOutline16, IconFullscreenOutline16, IconGaugeOutline16, IconGlobeOutline14, IconGoalOutline16, IconInfoOutline14, IconInspectOutline12, IconLightOutline16, IconLikeFill16, IconLikeOutline16, IconLinkOutline14, IconLinkOutline16, IconListPenOutline16, IconLoadingOutline16, IconNewChatOutline16, IconPanelLeftOutline16, IconPaperPlaneOutline14, IconPaperclipOutline16, IconPauseOutline16, IconPersonalizationOutline16, IconPlanOutline14, IconPlayOutline16, IconPluginPinwheelOutline16, IconPlusOutline16, IconProjectAddOutline16, IconQuestionOutline14, IconQueueOutline14, IconRefreshOutline14, IconRefreshOutline16, IconRightUpOutline14, IconRightUpOutline16, IconSearchOutline16, IconSendOutline14, IconSettingsOutline14, IconSettingsOutline16, IconShareOutline16, IconShieldOutline16, IconSkillOutline16, IconSparkle16, IconStopFill16, IconThinkOutline14, IconThinkOutline16, IconTrashOutline16, IconTreeCorner8x10, IconTriangleRightFill14, IconUserOutline16, IconWarningOutline16, IconWrapLinesOutline16, Input, JsonBlock, JsonTree, LinkIcon, MarkdownDelegateProvider, MarkdownText, Menu, Modal, OnboardingSurface, Pill, ReadBlock, ReferenceIcon, RiskConfirmation, SHIELD_OUTLINE_PATH, SHIELD_OUTLINE_STROKE, SearchBlock, StateDot, Switch, Tag, TerminalBlock, Toast, Tooltip, WebBlock, classifyFileType, classifyLinkPath, diffTotals, extractMarkdownPlainText, fileExtension, fileSizeText, isDarwinDesktop, projectUserText, rankByName, relativeTime, useAnchoredMaxHeight, useAnchoredPosition, useDismissOnOutsidePointer, writeClipboard };
8241
8665
 
8242
8666
  //# sourceMappingURL=index.js.map