@qilin-agent/client-ui-primitives 3.1.5 → 3.1.6

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
@@ -12,37 +12,41 @@ import css$6 from "./DisclosureRow.module.css";
12
12
  import css$7 from "./Button.module.css";
13
13
  import css$8 from "./Pill.module.css";
14
14
  import css$9 from "./SegmentedControl.module.css";
15
- import css$10 from "./Switch.module.css";
16
- import css$11 from "./Checkbox.module.css";
17
- import css$12 from "./Input.module.css";
15
+ import css$10 from "./SegmentedTabs.module.css";
16
+ import css$11 from "./Switch.module.css";
17
+ import css$12 from "./Checkbox.module.css";
18
+ import css$13 from "./Input.module.css";
19
+ import css$14 from "./InlineEditor.module.css";
18
20
  import { createPortal } from "react-dom";
19
- import css$13 from "./ShortcutKeys.module.css";
20
- import css$14 from "./Menu.module.css";
21
- import css$15 from "./Tooltip.module.css";
22
- import css$16 from "./HoverCard.module.css";
23
- import css$17 from "./Modal.module.css";
24
- import css$18 from "./OnboardingSurface.module.css";
25
- import css$19 from "./RiskConfirmation.module.css";
26
- import css$20 from "./ConnectionIndicator.module.css";
27
- import css$21 from "./FileTypeIcon.module.css";
21
+ import css$15 from "./ShortcutKeys.module.css";
22
+ import css$16 from "./MenuSurface.module.css";
23
+ import css$17 from "./Menu.module.css";
24
+ import css$18 from "./Tooltip.module.css";
25
+ import css$19 from "./HoverCard.module.css";
26
+ import css$20 from "./Modal.module.css";
27
+ import css$21 from "./OnboardingSurface.module.css";
28
+ import css$22 from "./RiskConfirmation.module.css";
29
+ import css$23 from "./ConnectionIndicator.module.css";
30
+ import css$24 from "./FileTypeIcon.module.css";
28
31
  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";
29
32
  import { pathPartsOf } from "@qilin-agent/util-workspace-path";
30
- import css$22 from "./PathLabel.module.css";
31
- import css$23 from "./user-text.module.css";
33
+ import css$25 from "./PathLabel.module.css";
34
+ import css$26 from "./SecretText.module.css";
35
+ import css$27 from "./user-text.module.css";
32
36
  import markdownCss from "./markdown/MarkdownText.module.css";
33
- import css$24 from "./Toast.module.css";
34
- import css$25 from "./JsonTree.module.css";
37
+ import css$28 from "./Toast.module.css";
38
+ import css$29 from "./JsonTree.module.css";
35
39
  import Anser from "anser";
36
- import css$26 from "./TerminalBlock.module.css";
40
+ import css$30 from "./TerminalBlock.module.css";
37
41
  import { createCssVariablesTheme, createHighlighterCoreSync } from "shiki/core";
38
42
  import { createJavaScriptRegexEngine, defaultJavaScriptRegexConstructor } from "shiki/engine/javascript";
39
43
  import langTs from "@shikijs/langs/typescript";
40
44
  import langBash from "@shikijs/langs/shellscript";
41
45
  import langJson from "@shikijs/langs/json";
42
- import css$27 from "./ReadBlock.module.css";
46
+ import css$31 from "./ReadBlock.module.css";
43
47
  import { structuredPatch } from "diff";
44
- import css$28 from "./DiffBlock.module.css";
45
- import css$29 from "./SearchBlock.module.css";
48
+ import css$32 from "./DiffBlock.module.css";
49
+ import css$33 from "./SearchBlock.module.css";
46
50
  import { fromMarkdown } from "mdast-util-from-markdown";
47
51
  import { gfmFromMarkdown } from "mdast-util-gfm";
48
52
  import { mathFromMarkdown } from "mdast-util-math";
@@ -54,16 +58,15 @@ import { classifyCharacter } from "micromark-util-classify-character";
54
58
  import { codes, constants, types } from "micromark-util-symbol";
55
59
  import { factorySpace } from "micromark-factory-space";
56
60
  import { normalizeUri } from "micromark-util-sanitize-uri";
57
- import css$30 from "./markdown/CodeBlock.module.css";
58
- import css$31 from "./markdown/mermaid.module.css";
61
+ import css$34 from "./markdown/CodeBlock.module.css";
62
+ import css$35 from "./markdown/mermaid.module.css";
59
63
  import katex from "katex";
60
- import css$32 from "./ImageLightbox.module.css";
61
- import css$33 from "./ImagePreview.module.css";
64
+ import css$36 from "./ImageLightbox.module.css";
65
+ import css$37 from "./ImagePreview.module.css";
62
66
  import "katex/dist/katex.min.css";
63
- import css$34 from "./WebBlock.module.css";
64
- import css$35 from "./markdown/JsonBlock.module.css";
65
- import css$36 from "./MenuGroup.module.css";
66
- import css$37 from "./MenuSurface.module.css";
67
+ import css$38 from "./WebBlock.module.css";
68
+ import css$39 from "./markdown/JsonBlock.module.css";
69
+ import css$40 from "./MenuGroup.module.css";
67
70
  //#region lib/types/settings-form/SettingsForm.js
68
71
  /**
69
72
  * One plugin's settings form as its page on the Plugins page shows it: the
@@ -1909,6 +1912,24 @@ const IconPinFillRegular = ({ size = 16, className }) => jsxs("svg", {
1909
1912
  * upstream artwork verbatim (dsh-context is the current consumer).
1910
1913
  */
1911
1914
  const ICON_REGULAR_STROKE = 1;
1915
+ const ICON_MEDIUM_STROKE = 1.3;
1916
+ /** Circle-and-tick glyph the plugin page marks shipped rows with; upstream artwork. */
1917
+ const IconCheckCircleFillRegular = ({ size = 16, className }) => jsxs("svg", {
1918
+ width: size,
1919
+ height: size,
1920
+ className,
1921
+ viewBox: "0 0 36 36",
1922
+ fill: "none",
1923
+ xmlns: "http://www.w3.org/2000/svg",
1924
+ "aria-hidden": "true",
1925
+ children: [jsx("path", {
1926
+ d: "M28.1936 14.6936L19.8066 23.0806C19.2373 23.65 18.7159 24.1742 18.24 24.5571C17.7389 24.9602 17.1365 25.3359 16.3657 25.458C15.9581 25.5225 15.5428 25.5225 15.1353 25.458C14.3645 25.3359 13.7621 24.9602 13.261 24.5571C12.7851 24.1742 12.2637 23.65 11.6943 23.0806L7.80737 19.1936L10.1936 16.8074L14.0806 20.6943C14.7033 21.317 15.0763 21.6873 15.377 21.9292C15.6523 22.1507 15.7109 22.1325 15.6626 22.1248C15.7208 22.1339 15.7802 22.1339 15.8384 22.1248C15.7901 22.1325 15.8486 22.1507 16.124 21.9292C16.4247 21.6873 16.7977 21.317 17.4204 20.6943L25.8074 12.3074L28.1936 14.6936Z",
1927
+ fill: "currentColor"
1928
+ }), jsx("path", {
1929
+ d: "M32.8496 18.0005C32.8496 9.79906 26.2019 3.15137 18.0005 3.15137C9.79906 3.15137 3.15137 9.79906 3.15137 18.0005C3.15137 26.2019 9.79906 32.8496 18.0005 32.8496C26.2019 32.8496 32.8496 26.2019 32.8496 18.0005ZM35.7764 18.0005C35.7764 27.8173 27.8173 35.7764 18.0005 35.7764C8.18363 35.7764 0.224609 27.8173 0.224609 18.0005C0.224609 8.18363 8.18363 0.224609 18.0005 0.224609C27.8173 0.224609 35.7764 8.18363 35.7764 18.0005Z",
1930
+ fill: "currentColor"
1931
+ })]
1932
+ });
1912
1933
  const IconUsersOutlineRegular = ({ size = 16, className }) => jsxs("svg", {
1913
1934
  width: size,
1914
1935
  height: size,
@@ -1951,6 +1972,58 @@ const IconWorkspaceTreeOutlineRegular = ({ size = 16, className }) => jsxs("svg"
1951
1972
  strokeWidth: ICON_REGULAR_STROKE,
1952
1973
  children: [jsx("path", { d: "M14 12.05c0 .8-.65 1.45-1.46 1.45H3.46C2.65 13.5 2 12.85 2 12.05v-8.1c0-.8.65-1.45 1.46-1.45h2.4c.49 0 .94.24 1.21.65l.5.73c.27.4.73.65 1.21.65h3.76c.8 0 1.46.65 1.46 1.45v6.02Z" }), jsx("path", { d: "M8.7 8.1v3M11.2 8.1v3" })]
1953
1974
  });
1975
+ /** Regular one-pixel IconSlidersTwoOutline artwork (Filters and Labels menu rows). */
1976
+ const IconSlidersTwoOutlineRegular = ({ size = 16, className }) => jsxs("svg", {
1977
+ "aria-hidden": "true",
1978
+ width: size,
1979
+ height: size,
1980
+ className,
1981
+ viewBox: "0 0 16 16",
1982
+ fill: "none",
1983
+ stroke: "currentColor",
1984
+ strokeLinecap: "round",
1985
+ strokeWidth: ICON_REGULAR_STROKE,
1986
+ children: [
1987
+ jsx("path", { d: "M2.3 5h5.85M12.05 5h1.65" }),
1988
+ jsx("circle", {
1989
+ cx: "9.95",
1990
+ cy: "5",
1991
+ r: "1.45"
1992
+ }),
1993
+ jsx("path", { d: "M2.3 11h1.65M7.85 11h5.85" }),
1994
+ jsx("circle", {
1995
+ cx: "5.75",
1996
+ cy: "11",
1997
+ r: "1.45"
1998
+ })
1999
+ ]
2000
+ });
2001
+ /** Medium IconSlidersTwoOutline artwork with a 1.3px stroke. */
2002
+ const IconSlidersTwoOutlineMedium = ({ size = 16, className }) => jsxs("svg", {
2003
+ "aria-hidden": "true",
2004
+ width: size,
2005
+ height: size,
2006
+ className,
2007
+ viewBox: "0 0 16 16",
2008
+ fill: "none",
2009
+ stroke: "currentColor",
2010
+ strokeLinecap: "round",
2011
+ strokeWidth: ICON_MEDIUM_STROKE,
2012
+ children: [
2013
+ jsx("path", { d: "M2.3 5h5.85M12.05 5h1.65" }),
2014
+ jsx("circle", {
2015
+ cx: "9.95",
2016
+ cy: "5",
2017
+ r: "1.45"
2018
+ }),
2019
+ jsx("path", { d: "M2.3 11h1.65M7.85 11h5.85" }),
2020
+ jsx("circle", {
2021
+ cx: "5.75",
2022
+ cy: "11",
2023
+ r: "1.45"
2024
+ })
2025
+ ]
2026
+ });
1954
2027
  //#endregion
1955
2028
  //#region lib/types/Tag.js
1956
2029
  /**
@@ -2428,6 +2501,29 @@ function CommandText({ text, label, className }) {
2428
2501
  }
2429
2502
  //#endregion
2430
2503
  //#region lib/types/StateDot.js
2504
+ /**
2505
+ * Pin the loader's CSS animations to document time zero. A CSS animation starts
2506
+ * when its element is inserted and restarts when the element is moved or shown
2507
+ * again, so loaders started at different moments animate out of phase; one shared
2508
+ * start time keeps every visible loader in step. Mount pins the first start; the
2509
+ * element's own `animationstart` listener pins each restart.
2510
+ * @param element - the mounted loader, or null on unmount.
2511
+ */
2512
+ function syncSpinner(element) {
2513
+ if (element === null) return;
2514
+ pinSpinner(element);
2515
+ element.addEventListener("animationstart", () => {
2516
+ pinSpinner(element);
2517
+ });
2518
+ }
2519
+ /**
2520
+ * Set every CSS animation in the loader's subtree to start at document time zero.
2521
+ * @param element - the mounted loader.
2522
+ */
2523
+ function pinSpinner(element) {
2524
+ const spinner = element;
2525
+ for (const animation of spinner.getAnimations?.({ subtree: true }) ?? []) animation.startTime = 0;
2526
+ }
2431
2527
  /** Outer 3x3 matrix cells (2px pixels on a 10px grid), clockwise from top-left. */
2432
2528
  const MATRIX_CELLS = [
2433
2529
  [0, 0],
@@ -2448,6 +2544,7 @@ const MATRIX_CELLS = [
2448
2544
  */
2449
2545
  function StateDot({ state, size = 10, className }) {
2450
2546
  if (state === "ongoing") return jsx("svg", {
2547
+ ref: syncSpinner,
2451
2548
  className: clsx(css$4.matrix, className),
2452
2549
  "data-state": "ongoing",
2453
2550
  width: size,
@@ -2710,6 +2807,274 @@ function SegmentedControl({ id, value, options, onChange, label, disabled = fals
2710
2807
  });
2711
2808
  }
2712
2809
  //#endregion
2810
+ //#region lib/types/SegmentedTabs.js
2811
+ /**
2812
+ * Render equal-width, controlled tabs with a sliding selection indicator.
2813
+ * @param props.items - non-empty ordered tabs with unique values and DOM ids.
2814
+ * @param props.value - selected value, which must belong to items.
2815
+ * @param props.onChange - selection requested by click, Left/Right, or Home/End.
2816
+ * Keyboard selection also moves focus; only the selected tab is a tab stop.
2817
+ * @param props.label - localized accessible name for the tab list.
2818
+ * @param props.className - layout placement; panels remain caller-owned.
2819
+ * @returns the tab list, without its panels.
2820
+ */
2821
+ function SegmentedTabs({ items, value, onChange, label, className }) {
2822
+ const selectedIndex = items.findIndex((item) => item.value === value);
2823
+ const onKeyDown = (event, index) => {
2824
+ let next;
2825
+ switch (event.key) {
2826
+ case "ArrowLeft":
2827
+ next = (index + items.length - 1) % items.length;
2828
+ break;
2829
+ case "ArrowRight":
2830
+ next = (index + 1) % items.length;
2831
+ break;
2832
+ case "Home":
2833
+ next = 0;
2834
+ break;
2835
+ case "End":
2836
+ next = items.length - 1;
2837
+ break;
2838
+ default: return;
2839
+ }
2840
+ event.preventDefault();
2841
+ event.stopPropagation();
2842
+ const tablist = event.currentTarget.parentElement;
2843
+ const nextItem = items[next];
2844
+ /* v8 ignore next -- the event comes from a mounted direct child and next is bounded by non-empty items. */
2845
+ if (tablist === null || nextItem === void 0) return;
2846
+ tablist.querySelectorAll("[role=\"tab\"]").item(next).focus();
2847
+ onChange(nextItem.value);
2848
+ };
2849
+ return jsxs("div", {
2850
+ role: "tablist",
2851
+ "aria-label": label,
2852
+ className: clsx(css$10.tabs, className),
2853
+ style: { gridTemplateColumns: `repeat(${items.length}, minmax(0, 1fr))` },
2854
+ children: [jsx("span", {
2855
+ className: css$10.indicator,
2856
+ "aria-hidden": "true",
2857
+ style: {
2858
+ width: `calc((100% - 8px) / ${items.length})`,
2859
+ transform: `translateX(${selectedIndex * 100}%)`
2860
+ }
2861
+ }), items.map((item, index) => jsx(Pill, {
2862
+ id: item.id,
2863
+ role: "tab",
2864
+ className: css$10.tab,
2865
+ "aria-selected": value === item.value,
2866
+ "aria-controls": item.panelId,
2867
+ tabIndex: value === item.value ? 0 : -1,
2868
+ onClick: () => {
2869
+ onChange(item.value);
2870
+ },
2871
+ onKeyDown: (event) => {
2872
+ onKeyDown(event, index);
2873
+ },
2874
+ children: item.label
2875
+ }, item.value))]
2876
+ });
2877
+ }
2878
+ //#endregion
2879
+ //#region lib/types/plugin-artwork.js
2880
+ /**
2881
+ * Fixed-palette plugin artwork for the plugin management surfaces. Unlike the
2882
+ * ic_ds_* set these glyphs carry their own brand colors and gradients instead
2883
+ * of riding currentColor; all draw on a 36×36 viewBox and take {size, className}.
2884
+ */
2885
+ /**
2886
+ * A per-instance SVG def id prefix: the artwork repeats across cards and rows,
2887
+ * and duplicate document ids would make every `url(#…)` resolve to the first instance.
2888
+ */
2889
+ const useArtworkId = () => `qilin_plugin_art_${useId().replaceAll(":", "")}`;
2890
+ /** Light-blue terminal artwork shared by plugin cards and sidebar guide entries. */
2891
+ const PluginArtworkTerminal = ({ size = 36, className }) => jsxs("svg", {
2892
+ width: size,
2893
+ height: size,
2894
+ className,
2895
+ viewBox: "0 0 36 36",
2896
+ fill: "none",
2897
+ xmlns: "http://www.w3.org/2000/svg",
2898
+ children: [jsx("path", {
2899
+ d: "M10 11L16.606 17.606C16.6841 17.6841 16.6841 17.8107 16.606 17.8888L10 24.4948",
2900
+ stroke: "#679EFE",
2901
+ strokeWidth: "3.5"
2902
+ }), jsx("path", {
2903
+ d: "M20.1211 24.4946H26.8685",
2904
+ stroke: "#679EFE",
2905
+ strokeWidth: "3.5"
2906
+ })]
2907
+ });
2908
+ /** Agent-loop plugin artwork (four leaves circling a center). */
2909
+ const PluginArtworkLoop = ({ size = 36, className }) => {
2910
+ const uid = useArtworkId();
2911
+ return jsxs("svg", {
2912
+ width: size,
2913
+ height: size,
2914
+ className,
2915
+ viewBox: "0 0 36 36",
2916
+ fill: "none",
2917
+ xmlns: "http://www.w3.org/2000/svg",
2918
+ children: [
2919
+ jsx("path", {
2920
+ d: "M18.0486 28.4901C12.0858 28.4901 7.25195 23.6562 7.25195 17.6934C13.2148 17.6934 18.0486 22.5272 18.0486 28.4901Z",
2921
+ fill: "#A797FC"
2922
+ }),
2923
+ jsx("path", {
2924
+ d: "M18.0486 6.89667C12.0858 6.89667 7.25195 11.7305 7.25195 17.6934C13.2148 17.6934 18.0486 12.8595 18.0486 6.89667Z",
2925
+ fill: `url(#${uid}a)`
2926
+ }),
2927
+ jsx("path", {
2928
+ d: "M18.0485 28.4901C24.0114 28.4901 28.8452 23.6562 28.8452 17.6934C22.8824 17.6934 18.0485 22.5272 18.0485 28.4901Z",
2929
+ fill: "#4561EE"
2930
+ }),
2931
+ jsx("path", {
2932
+ d: "M18.0485 6.89667C24.0114 6.89667 28.8452 11.7305 28.8452 17.6934C22.8824 17.6934 18.0485 12.8595 18.0485 6.89667Z",
2933
+ fill: "#658EFF"
2934
+ }),
2935
+ jsx("defs", { children: jsxs("linearGradient", {
2936
+ id: `${uid}a`,
2937
+ x1: "16.7911",
2938
+ y1: "16.1655",
2939
+ x2: "8.98192",
2940
+ y2: "8.74289",
2941
+ gradientUnits: "userSpaceOnUse",
2942
+ children: [jsx("stop", { stopColor: "#A23AE7" }), jsx("stop", {
2943
+ offset: "1",
2944
+ stopColor: "#E2E2E2"
2945
+ })]
2946
+ }) })
2947
+ ]
2948
+ });
2949
+ };
2950
+ /** Subagent plugin artwork (two stacked rounded squares); also marks every row inside a bundle. */
2951
+ const PluginArtworkSubagent = ({ size = 36, className }) => {
2952
+ const uid = useArtworkId();
2953
+ return jsxs("svg", {
2954
+ width: size,
2955
+ height: size,
2956
+ className,
2957
+ viewBox: "0 0 36 36",
2958
+ fill: "none",
2959
+ xmlns: "http://www.w3.org/2000/svg",
2960
+ children: [
2961
+ jsx("rect", {
2962
+ x: "14.9893",
2963
+ y: "15.1877",
2964
+ width: "12.2365",
2965
+ height: "12.2365",
2966
+ rx: "2",
2967
+ fill: `url(#${uid}a)`,
2968
+ fillOpacity: "0.8"
2969
+ }),
2970
+ jsx("rect", {
2971
+ x: "8.87109",
2972
+ y: "9.0697",
2973
+ width: "12.2365",
2974
+ height: "12.2365",
2975
+ rx: "2",
2976
+ fill: `url(#${uid}b)`,
2977
+ fillOpacity: "0.8"
2978
+ }),
2979
+ jsxs("defs", { children: [jsxs("linearGradient", {
2980
+ id: `${uid}a`,
2981
+ x1: "21.1075",
2982
+ y1: "15.1877",
2983
+ x2: "21.1075",
2984
+ y2: "27.4243",
2985
+ gradientUnits: "userSpaceOnUse",
2986
+ children: [jsx("stop", { stopColor: "#45E7A4" }), jsx("stop", {
2987
+ offset: "1",
2988
+ stopColor: "#05909D"
2989
+ })]
2990
+ }), jsxs("linearGradient", {
2991
+ id: `${uid}b`,
2992
+ x1: "14.9894",
2993
+ y1: "9.0697",
2994
+ x2: "14.9894",
2995
+ y2: "21.3063",
2996
+ gradientUnits: "userSpaceOnUse",
2997
+ children: [jsx("stop", { stopColor: "#69B9FF" }), jsx("stop", {
2998
+ offset: "1",
2999
+ stopColor: "#324DE2"
3000
+ })]
3001
+ })] })
3002
+ ]
3003
+ });
3004
+ };
3005
+ /**
3006
+ * Web-search plugin artwork (conic-gradient ring and handle). SVG has no
3007
+ * native conic gradient, so the ring clips an HTML div painted with CSS
3008
+ * `conic-gradient` — the same emulation Figma exports; it renders inline in
3009
+ * the browser UI but would stay empty in an `<img>` or mask context.
3010
+ */
3011
+ const PluginArtworkSearch = ({ size = 36, className }) => {
3012
+ const uid = useArtworkId();
3013
+ return jsxs("svg", {
3014
+ width: size,
3015
+ height: size,
3016
+ className,
3017
+ viewBox: "0 0 36 36",
3018
+ fill: "none",
3019
+ xmlns: "http://www.w3.org/2000/svg",
3020
+ children: [
3021
+ jsx("path", {
3022
+ d: "M26.5362 26.9865L22.3813 22.8317",
3023
+ stroke: "#658EFF",
3024
+ strokeWidth: "3"
3025
+ }),
3026
+ jsx("g", {
3027
+ clipPath: `url(#${uid}ring)`,
3028
+ children: jsx("g", {
3029
+ transform: "matrix(0.0119394 -0.00173904 0.00173904 0.0119394 15.7661 16.2159)",
3030
+ children: jsx("foreignObject", {
3031
+ x: "-958.94",
3032
+ y: "-958.94",
3033
+ width: "1917.88",
3034
+ height: "1917.88",
3035
+ children: jsx("div", { style: {
3036
+ background: "conic-gradient(from 90deg, rgb(65, 225, 172) 0deg, rgb(101, 142, 255) 62.0619deg, rgb(65, 225, 172) 360deg)",
3037
+ height: "100%",
3038
+ width: "100%"
3039
+ } })
3040
+ })
3041
+ })
3042
+ }),
3043
+ jsx("defs", { children: jsx("clipPath", {
3044
+ id: `${uid}ring`,
3045
+ children: jsx("path", { d: "M21.9717 16.2159H19.9717C19.9717 18.5386 18.0888 20.4215 15.7661 20.4215V22.4215V24.4215C20.2979 24.4215 23.9717 20.7478 23.9717 16.2159H21.9717ZM15.7661 22.4215V20.4215C13.4434 20.4215 11.5605 18.5386 11.5605 16.2159H9.56055H7.56055C7.56055 20.7478 11.2343 24.4215 15.7661 24.4215V22.4215ZM9.56055 16.2159H11.5605C11.5605 13.8933 13.4434 12.0104 15.7661 12.0104V10.0104V8.01038C11.2343 8.01038 7.56055 11.6841 7.56055 16.2159H9.56055ZM15.7661 10.0104V12.0104C18.0888 12.0104 19.9717 13.8933 19.9717 16.2159H21.9717H23.9717C23.9717 11.6841 20.2979 8.01038 15.7661 8.01038V10.0104Z" })
3046
+ }) })
3047
+ ]
3048
+ });
3049
+ };
3050
+ /** Default plugin artwork for plugins without one of their own (connector blocks and a node). */
3051
+ const PluginArtworkDefault = ({ size = 36, className }) => {
3052
+ const uid = useArtworkId();
3053
+ return jsxs("svg", {
3054
+ width: size,
3055
+ height: size,
3056
+ className,
3057
+ viewBox: "0 0 36 36",
3058
+ fill: "none",
3059
+ xmlns: "http://www.w3.org/2000/svg",
3060
+ children: [jsx("path", {
3061
+ d: "M24.6294 8.63696C26.2862 8.63705 27.6294 9.98016 27.6294 11.637V12.7825C27.6292 14.4391 26.2861 15.7824 24.6294 15.7825H23.4839C22.6519 15.7825 21.5454 16.3459 21.5454 17.1778V18.1573C21.5454 18.7757 22.216 19.1966 22.8345 19.1965H24.6294C26.2861 19.1965 27.6292 20.5398 27.6294 22.1965V23.9924C27.6292 25.6491 26.2861 26.9924 24.6294 26.9924H22.8345C21.1778 26.9924 19.8347 25.649 19.8345 23.9924V22.1965C19.8345 21.7148 19.4957 21.2327 19.014 21.2327H16.4792C15.7975 21.2327 15.3374 22.0061 15.3374 22.6877V23.8333C15.3373 25.49 13.9942 26.8333 12.3374 26.8333H11.1919C9.53509 26.8333 8.19198 25.49 8.19189 23.8333V22.6877C8.19189 21.0309 9.53504 19.6877 11.1919 19.6877H12.3374C13.1964 19.6877 14.3999 19.0959 14.3999 18.2369V16.0185C14.3999 14.9518 15.2646 14.0872 16.3312 14.0872H19.435C20.0596 14.0872 20.484 13.4071 20.4839 12.7825V11.637C20.4839 9.98011 21.827 8.63696 23.4839 8.63696H24.6294ZM13.4116 11.2468C13.4116 12.6882 12.2431 13.8567 10.8018 13.8567C9.36037 13.8567 8.19189 12.6882 8.19189 11.2468C8.19189 9.80544 9.36037 8.63696 10.8018 8.63696C12.2431 8.63696 13.4116 9.80544 13.4116 11.2468Z",
3062
+ fill: `url(#${uid}a)`
3063
+ }), jsx("defs", { children: jsxs("linearGradient", {
3064
+ id: `${uid}a`,
3065
+ x1: "15.1481",
3066
+ y1: "9.94188",
3067
+ x2: "15.1481",
3068
+ y2: "13.6375",
3069
+ gradientUnits: "userSpaceOnUse",
3070
+ children: [jsx("stop", { stopColor: "#54ECE7" }), jsx("stop", {
3071
+ offset: "1",
3072
+ stopColor: "#658EFF"
3073
+ })]
3074
+ }) })]
3075
+ });
3076
+ };
3077
+ //#endregion
2713
3078
  //#region lib/types/Switch.js
2714
3079
  /**
2715
3080
  * Render a toggle switch.
@@ -2730,11 +3095,11 @@ function Switch({ checked, onChange, label, disabled = false, title, className }
2730
3095
  "aria-label": label,
2731
3096
  title,
2732
3097
  disabled,
2733
- className: clsx(css$10.switch, className),
3098
+ className: clsx(css$11.switch, className),
2734
3099
  onClick: () => {
2735
3100
  onChange(!checked);
2736
3101
  },
2737
- children: jsx("span", { className: css$10.thumb })
3102
+ children: jsx("span", { className: css$11.thumb })
2738
3103
  });
2739
3104
  }
2740
3105
  //#endregion
@@ -2752,7 +3117,7 @@ function Switch({ checked, onChange, label, disabled = false, title, className }
2752
3117
  */
2753
3118
  function Checkbox({ checked, onChange, label, disabled = false, title, className }) {
2754
3119
  return jsxs("label", {
2755
- className: clsx(css$11.checkbox, className),
3120
+ className: clsx(css$12.checkbox, className),
2756
3121
  title,
2757
3122
  children: [jsx("input", {
2758
3123
  type: "checkbox",
@@ -2774,17 +3139,85 @@ function Checkbox({ checked, onChange, label, disabled = false, title, className
2774
3139
  */
2775
3140
  const Input = forwardRef(function Input({ icon, className, ...rest }, ref) {
2776
3141
  return jsxs("span", {
2777
- className: clsx(css$12.wrap, className),
3142
+ className: clsx(css$13.wrap, className),
2778
3143
  children: [icon != null && jsx("span", {
2779
- className: css$12.icon,
3144
+ className: css$13.icon,
2780
3145
  children: icon
2781
3146
  }), jsx("input", {
2782
3147
  ref,
2783
- className: css$12.input,
3148
+ className: css$13.input,
2784
3149
  ...rest
2785
3150
  })]
2786
3151
  });
2787
3152
  });
3153
+ //#endregion
3154
+ //#region lib/types/InlineEditor.js
3155
+ /** Multi-line inline editor for short saved-on-Enter drafts such as queued messages and goals. */
3156
+ /**
3157
+ * Render an autofocused textarea that grows with its text up to six lines, then scrolls.
3158
+ * A textarea rather than an input: HTML strips newlines from single-line input values.
3159
+ * Enter saves, Shift+Enter breaks the line, Enter during IME composition does nothing,
3160
+ * and Escape cancels.
3161
+ * @param props.value - current draft text.
3162
+ * @param props.label - localized accessible name.
3163
+ * @param props.onChange - receives the edited text.
3164
+ * @param props.onSave - called for a plain Enter.
3165
+ * @param props.onCancel - called for Escape.
3166
+ * @param props.className - extra class for the editor's placement.
3167
+ * @returns the textarea.
3168
+ */
3169
+ function InlineEditor({ value, label, onChange, onSave, onCancel, className }) {
3170
+ const ref = useRef(null);
3171
+ useLayoutEffect(() => {
3172
+ const node = ref.current;
3173
+ const fit = () => {
3174
+ node.style.height = "auto";
3175
+ node.style.height = `${node.scrollHeight + node.offsetHeight - node.clientHeight}px`;
3176
+ };
3177
+ fit();
3178
+ const observer = new ResizeObserver(fit);
3179
+ observer.observe(node);
3180
+ return () => {
3181
+ observer.disconnect();
3182
+ };
3183
+ }, [value]);
3184
+ const onKeyDown = (event) => {
3185
+ if (event.key === "Escape") {
3186
+ onCancel();
3187
+ return;
3188
+ }
3189
+ const composing = event.nativeEvent.isComposing || Reflect.get(event.nativeEvent, "keyCode") === 229;
3190
+ if (event.key !== "Enter" || event.shiftKey || composing) return;
3191
+ event.preventDefault();
3192
+ onSave();
3193
+ };
3194
+ return jsx("textarea", {
3195
+ ref,
3196
+ autoFocus: true,
3197
+ rows: 1,
3198
+ className: clsx(css$14.editor, className),
3199
+ "aria-label": label,
3200
+ value,
3201
+ onChange: (event) => {
3202
+ onChange(event.currentTarget.value);
3203
+ },
3204
+ onKeyDown
3205
+ });
3206
+ }
3207
+ //#endregion
3208
+ //#region lib/types/overlay-top-margin.js
3209
+ /** Shared viewport inset for overlays, derived from the desktop frame's reserved top strip. */
3210
+ /**
3211
+ * Resolve the top margin an overlay keeps from the viewport edge.
3212
+ * @param min - the overlay's own viewport margin in px, used as the floor.
3213
+ * @returns the larger of `min` and the frame clearance plus 20px; fullscreen keeps only the 20px gap.
3214
+ */
3215
+ function overlayTopMargin(min) {
3216
+ const root = document.documentElement;
3217
+ const clearance = Number.parseFloat(getComputedStyle(root).getPropertyValue("--dsh-frame-top-clearance"));
3218
+ if (Number.isNaN(clearance)) return min;
3219
+ return Math.max(min, (root.hasAttribute("data-fullscreen") ? 0 : clearance) + 20);
3220
+ }
2788
3221
  /**
2789
3222
  * Delay a pointer-dismissed popup's close so the pointer can cross the gap
2790
3223
  * between anchor and popup. A pending close is dropped on unmount.
@@ -2994,14 +3427,55 @@ function useModalLayer(dialog, open, onClose) {
2994
3427
  */
2995
3428
  function ShortcutKeys({ keys, variant = "plain", className }) {
2996
3429
  return jsx("span", {
2997
- className: clsx(css$13.keys, variant === "tooltip" && css$13.tooltip, variant === "tooltip" && keys.includes("+") && css$13.joined, className),
3430
+ className: clsx(css$15.keys, variant === "tooltip" && css$15.tooltip, variant === "tooltip" && keys.includes("+") && css$15.joined, className),
2998
3431
  children: keys.map((key, index) => jsx("kbd", {
2999
- className: key === "+" ? css$13.separator : css$13.key,
3432
+ className: key === "+" ? css$15.separator : css$15.key,
3000
3433
  children: key
3001
3434
  }, index))
3002
3435
  });
3003
3436
  }
3004
3437
  //#endregion
3438
+ //#region lib/types/MenuSurface.js
3439
+ /** Shared menu material and the macOS backing that lets Chromium blur transparent windows. */
3440
+ /**
3441
+ * Paint a menu and, on macOS, an opaque backing behind the page content within its bounds.
3442
+ * CSS anchors keep each backing aligned during placement, resizing, and nested-menu movement.
3443
+ * @param props - Div content and placement, and compact geometry.
3444
+ * @param ref - The visible menu div, excluding the non-interactive backing.
3445
+ * @returns Menu content plus a backing portal removed with the menu.
3446
+ */
3447
+ const MenuSurface = forwardRef(function MenuSurface({ compact = false, className, style, children, ...props }, ref) {
3448
+ const id = useId();
3449
+ const backingRef = useRef(null);
3450
+ useLayoutEffect(() => {
3451
+ document.body.appendChild(backingRef.current);
3452
+ }, []);
3453
+ const anchorStyle = { "--qilin-menu-anchor": `--qilin-menu-${id.replaceAll(":", "")}` };
3454
+ return jsxs(Fragment, { children: [jsxs("div", {
3455
+ ...props,
3456
+ ref,
3457
+ "data-menu-material": "translucent",
3458
+ className: clsx(css$16.surface, compact && css$16.compact, className),
3459
+ style: {
3460
+ ...style,
3461
+ ...anchorStyle
3462
+ },
3463
+ children: [jsx("div", {
3464
+ "aria-hidden": "true",
3465
+ className: css$16.material
3466
+ }), children]
3467
+ }), createPortal(jsx("div", {
3468
+ ref: backingRef,
3469
+ "aria-hidden": "true",
3470
+ "data-menu-backing": "",
3471
+ className: clsx(css$16.backing, compact && css$16.compact),
3472
+ style: {
3473
+ ...anchorStyle,
3474
+ visibility: style?.visibility
3475
+ }
3476
+ }), document.body)] });
3477
+ });
3478
+ //#endregion
3005
3479
  //#region lib/types/Menu.js
3006
3480
  /**
3007
3481
  * Render one `role="menuitem"` row for a {@link Menu} whose rows are
@@ -3020,32 +3494,32 @@ function ShortcutKeys({ keys, variant = "plain", className }) {
3020
3494
  */
3021
3495
  function MenuItemButton({ children, shortcut, icon, disabled = false, danger = false, separatorBefore = false, onSelect }) {
3022
3496
  return jsxs("div", {
3023
- className: css$14.itemWrap,
3497
+ className: css$17.itemWrap,
3024
3498
  children: [separatorBefore && jsx("div", {
3025
- className: css$14.separator,
3499
+ className: css$17.separator,
3026
3500
  role: "separator"
3027
3501
  }), jsxs("button", {
3028
3502
  type: "button",
3029
3503
  role: "menuitem",
3030
- className: clsx(css$14.item, danger && css$14.danger),
3504
+ className: clsx(css$17.item, danger && css$17.danger),
3031
3505
  disabled,
3032
3506
  "aria-keyshortcuts": shortcut?.aria,
3033
3507
  onClick: onSelect,
3034
3508
  children: [
3035
3509
  icon !== void 0 && jsx("span", {
3036
- className: css$14.itemIcon,
3510
+ className: css$17.itemIcon,
3037
3511
  children: icon
3038
3512
  }),
3039
3513
  jsx("span", {
3040
- className: css$14.itemLabel,
3514
+ className: css$17.itemLabel,
3041
3515
  children
3042
3516
  }),
3043
3517
  shortcut !== void 0 && jsx("span", {
3044
3518
  "aria-hidden": "true",
3045
- className: css$14.shortcut,
3519
+ className: css$17.shortcut,
3046
3520
  children: jsx(ShortcutKeys, {
3047
3521
  keys: shortcut.keys,
3048
- className: css$14.shortcutKeys
3522
+ className: css$17.shortcutKeys
3049
3523
  })
3050
3524
  })
3051
3525
  ]
@@ -3074,17 +3548,17 @@ const MEASURE_STYLE = {
3074
3548
  * @param props.autoFocus - focus the first item on open; the arrow keys walk the list either way.
3075
3549
  * @param props.open - whether the list is showing (owner-controlled).
3076
3550
  * @param props.anchor - the trigger element (rendered in place).
3077
- * @param props.items - selectable rows and optional separators.
3551
+ * @param props.items - selectable data rows and optional separators (default none; with no `children` either, the list is empty).
3078
3552
  * @param props.selectedId - row shown as selected.
3079
3553
  * @param props.selectedIds - rows shown as selected when a menu contains independent option groups.
3080
- * @param props.onSelect - row click callback (not called for disabled rows or submenu parents that only open children).
3554
+ * @param props.onSelect - data-row activation callback (not called for disabled rows or submenu parents that only open children).
3081
3555
  * @param props.onClose - invoked on outside click, Escape, or a window blur
3082
3556
  * that moved focus into an iframe (the only signal a pointerdown inside a
3083
3557
  * cross-origin iframe leaves).
3084
3558
  * @param props.align - list alignment against the anchor (default 'start').
3085
3559
  * @param props.side - open below (`bottom`, default) or above (`top`) the anchor.
3086
3560
  * @param props.portal - render the list into document.body, fixed-positioned
3087
- * from the anchor rect (repositions on scroll/resize while open). Use when an
3561
+ * from the anchor rect (follows movement and resizing while open). Use when an
3088
3562
  * ancestor's overflow clipping would crop the in-place list; default false
3089
3563
  * keeps the pure-CSS in-place behavior.
3090
3564
  * @param props.closeOnPointerLeave - close the list once the pointer has left
@@ -3097,17 +3571,25 @@ const MEASURE_STYLE = {
3097
3571
  * directly (e.g. from a host-owned trigger button) instead of measuring the
3098
3572
  * Menu's own wrapper span. Required when the wrapper isn't itself laid out at
3099
3573
  * the trigger (render-prop anchors, effect-positioned proxies — measuring the
3100
- * wrapper there races the host's layout effects). Called on open and on every
3101
- * scroll/resize; return null to skip placement for that frame.
3574
+ * wrapper there races the host's layout effects). Called on open, each animation
3575
+ * frame, and scroll/resize; return null to skip placement for that frame.
3102
3576
  * @param props.footer - rows pinned below the scrolling items area, separated
3103
3577
  * by a hairline; they stay visible while the items above scroll.
3578
+ * @param props.children - component rows rendered after `items` in the same
3579
+ * list, each a `role="menuitem"` button such as {@link MenuItemButton}; they
3580
+ * share the keyboard walk, the submenu exclusivity, and the post-selection
3581
+ * focus return.
3104
3582
  * @param props.selection - how a selected row is marked: a trailing check
3105
3583
  * (`'check'`, default — figma .Menu_cell) or the hover fill held on the row
3106
3584
  * with no check (`'fill'`, for icon-labelled rows where a trailing glyph
3107
3585
  * crowds the cell).
3586
+ * @param props.className - extra class on the anchor wrapper span.
3587
+ * @param props.listClassName - extra class on the dropdown card itself; the
3588
+ * only style hook that reaches a portaled list, which renders under
3589
+ * document.body outside the owner's DOM subtree.
3108
3590
  * @returns anchor wrapper with the conditional list.
3109
3591
  */
3110
- 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 }) {
3592
+ function Menu({ open, anchor, items = [], children, selectedId, selectedIds, onSelect, onClose, align = "start", side = "bottom", portal = false, closeOnPointerLeave = false, dense = false, compact = false, autoFocus = false, selection = "check", getAnchorRect, footer, className, listClassName }) {
3111
3593
  const rootRef = useRef(null);
3112
3594
  const listRef = useRef(null);
3113
3595
  /** Index the arrow walk last focused, the resume point when focus left the rows. */
@@ -3124,6 +3606,7 @@ function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, onClose,
3124
3606
  * anchor never held it, to the anchor's first button. Focus left on a removed
3125
3607
  * row otherwise falls to the page body, where the next Tab restarts from the
3126
3608
  * top of the page.
3609
+ * @param navigation - whether explicit keyboard traversal should retain its focus indicator.
3127
3610
  */
3128
3611
  const refocusAnchor = (navigation = false) => {
3129
3612
  const trigger = triggerRef.current;
@@ -3140,10 +3623,10 @@ function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, onClose,
3140
3623
  * its removal produced) comes back to the trigger.
3141
3624
  */
3142
3625
  const refocusAfterSelection = () => {
3626
+ const navigation = selectingWithTab.current;
3143
3627
  queueMicrotask(() => {
3144
3628
  if (openRef.current) return;
3145
3629
  const active = document.activeElement;
3146
- const navigation = selectingWithTab.current;
3147
3630
  if (active === null || active === document.body || listRef.current?.contains(active) === true) refocusAnchor(navigation);
3148
3631
  });
3149
3632
  };
@@ -3183,16 +3666,22 @@ function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, onClose,
3183
3666
  y = side === "bottom" ? r.bottom + 4 : r.top - lh - 4;
3184
3667
  }
3185
3668
  if (lw > 0) x = Math.min(Math.max(x, MARGIN), vw - lw - MARGIN);
3186
- if (lh > 0) y = Math.min(Math.max(y, MARGIN), vh - lh - MARGIN);
3187
- setFixedPos({
3669
+ if (lh > 0) y = Math.min(Math.max(y, overlayTopMargin(MARGIN)), vh - lh - MARGIN);
3670
+ setFixedPos((current) => current?.left === x && current.top === y ? current : {
3188
3671
  left: x,
3189
3672
  top: y
3190
3673
  });
3191
3674
  };
3192
3675
  place();
3676
+ const track = () => {
3677
+ place();
3678
+ frame = requestAnimationFrame(track);
3679
+ };
3680
+ let frame = requestAnimationFrame(track);
3193
3681
  window.addEventListener("scroll", place, true);
3194
3682
  window.addEventListener("resize", place);
3195
3683
  return () => {
3684
+ cancelAnimationFrame(frame);
3196
3685
  window.removeEventListener("scroll", place, true);
3197
3686
  window.removeEventListener("resize", place);
3198
3687
  };
@@ -3223,6 +3712,7 @@ function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, onClose,
3223
3712
  walkIndex.current = null;
3224
3713
  return;
3225
3714
  }
3715
+ const composition = observeComposition(document);
3226
3716
  const onPointerDown = (e) => {
3227
3717
  if (!(e.target instanceof Node)) return;
3228
3718
  if (rootRef.current?.contains(e.target) === true) return;
@@ -3230,15 +3720,15 @@ function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, onClose,
3230
3720
  onClose();
3231
3721
  };
3232
3722
  const onKeyDown = (e) => {
3723
+ if (composition.guards(e) || isBehindModal(rootRef.current) || e.defaultPrevented || e.ctrlKey || e.altKey || e.metaKey) return;
3233
3724
  const focused = document.activeElement;
3234
3725
  const insideList = listRef.current?.contains(focused) === true;
3235
3726
  const anchored = rootRef.current?.contains(focused) === true || insideList;
3236
- if (composition.guards(e) || isBehindModal(rootRef.current) || e.defaultPrevented || e.ctrlKey || e.altKey || e.metaKey) return;
3237
3727
  if (e.key === "Escape" && !e.shiftKey) {
3238
3728
  e.preventDefault();
3239
3729
  if (e.repeat) return;
3240
3730
  onClose();
3241
- if (anchored || autoFocus) refocusAnchor(true);
3731
+ if (anchored || autoFocus) refocusAnchor();
3242
3732
  }
3243
3733
  if (e.key === "Tab") {
3244
3734
  const list = listRef.current;
@@ -3246,7 +3736,7 @@ function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, onClose,
3246
3736
  if (e.shiftKey) {
3247
3737
  e.preventDefault();
3248
3738
  onClose();
3249
- refocusAnchor();
3739
+ refocusAnchor(true);
3250
3740
  return;
3251
3741
  }
3252
3742
  if (insideList) {
@@ -3288,14 +3778,13 @@ function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, onClose,
3288
3778
  const onWindowBlur = () => {
3289
3779
  if (document.activeElement instanceof HTMLIFrameElement) onClose();
3290
3780
  };
3781
+ document.addEventListener("pointerdown", onPointerDown);
3291
3782
  const onEscape = (event) => {
3292
3783
  if (event.key === "Escape") onKeyDown(event);
3293
3784
  };
3294
3785
  const onOtherKey = (event) => {
3295
3786
  if (event.key !== "Escape") onKeyDown(event);
3296
3787
  };
3297
- const composition = observeComposition(document);
3298
- document.addEventListener("pointerdown", onPointerDown);
3299
3788
  document.addEventListener("keydown", onOtherKey);
3300
3789
  document.addEventListener("keydown", onEscape, true);
3301
3790
  window.addEventListener("blur", onWindowBlur);
@@ -3317,11 +3806,11 @@ function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, onClose,
3317
3806
  const scrollable = !items.some((entry) => !isSeparator(entry) && !isLabel(entry) && entry.submenu !== void 0 && entry.submenu.length > 0);
3318
3807
  const renderEntry = (entry) => {
3319
3808
  if (isSeparator(entry)) return jsx("div", {
3320
- className: css$14.separator,
3809
+ className: css$17.separator,
3321
3810
  role: "separator"
3322
3811
  }, entry.id);
3323
3812
  if (isLabel(entry)) return jsx("div", {
3324
- className: css$14.label,
3813
+ className: css$17.label,
3325
3814
  role: "presentation",
3326
3815
  children: entry.text
3327
3816
  }, entry.id);
@@ -3329,79 +3818,79 @@ function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, onClose,
3329
3818
  const subOpen = hasSub && openSubmenuId === entry.id;
3330
3819
  const selected = entry.id === selectedId || selectedIds?.includes(entry.id) === true;
3331
3820
  return jsxs("div", {
3332
- className: css$14.itemWrap,
3333
- onMouseEnter: () => {
3334
- setOpenSubmenuId(hasSub ? entry.id : null);
3335
- },
3821
+ className: css$17.itemWrap,
3822
+ onMouseEnter: hasSub ? () => {
3823
+ setOpenSubmenuId(entry.id);
3824
+ } : void 0,
3336
3825
  onMouseLeave: () => {
3337
3826
  setOpenSubmenuId(null);
3338
3827
  },
3339
3828
  children: [jsxs("button", {
3340
3829
  type: "button",
3341
3830
  role: "menuitem",
3342
- className: clsx(css$14.item, selected && (selection === "fill" ? css$14.selectedFill : css$14.selected), entry.danger === true && css$14.danger),
3831
+ className: clsx(css$17.item, selected && (selection === "fill" ? css$17.selectedFill : css$17.selected), entry.danger === true && css$17.danger),
3343
3832
  disabled: entry.disabled,
3344
3833
  "aria-keyshortcuts": entry.shortcut?.aria,
3345
3834
  "aria-haspopup": hasSub ? "menu" : void 0,
3346
3835
  "aria-expanded": hasSub ? subOpen : void 0,
3347
- onFocus: () => {
3348
- setOpenSubmenuId(hasSub ? entry.id : null);
3349
- },
3836
+ onFocus: hasSub ? () => {
3837
+ setOpenSubmenuId(entry.id);
3838
+ } : void 0,
3350
3839
  onClick: () => {
3351
3840
  if (hasSub) {
3352
3841
  setOpenSubmenuId(entry.id);
3353
3842
  return;
3354
3843
  }
3355
- onSelect(entry.id);
3356
- refocusAfterSelection();
3844
+ onSelect?.(entry.id);
3357
3845
  },
3358
3846
  children: [
3359
3847
  entry.icon !== void 0 && jsx("span", {
3360
- className: css$14.itemIcon,
3848
+ className: css$17.itemIcon,
3361
3849
  children: entry.icon
3362
3850
  }),
3363
3851
  jsx("span", {
3364
- className: css$14.itemLabel,
3852
+ className: css$17.itemLabel,
3365
3853
  children: entry.label
3366
3854
  }),
3367
3855
  entry.shortcut !== void 0 && jsx("span", {
3368
3856
  "aria-hidden": "true",
3369
- className: css$14.shortcut,
3857
+ className: css$17.shortcut,
3370
3858
  children: jsx(ShortcutKeys, {
3371
3859
  keys: entry.shortcut.keys,
3372
- className: css$14.shortcutKeys
3860
+ className: css$17.shortcutKeys
3373
3861
  })
3374
3862
  }),
3375
- selected && selection === "check" && jsx(IconCheckOutline16, { className: css$14.check })
3863
+ selected && selection === "check" && jsx(IconCheckOutline16, { className: css$17.check })
3376
3864
  ]
3377
- }), subOpen && entry.submenu !== void 0 && jsx("div", {
3378
- className: clsx(css$14.submenu, compact && css$14.compactList),
3865
+ }), subOpen && entry.submenu !== void 0 && jsx(MenuSurface, {
3866
+ compact,
3867
+ className: clsx(css$17.submenu, compact && css$17.compactList),
3379
3868
  role: "menu",
3380
3869
  children: entry.submenu.map((sub) => jsxs("button", {
3381
3870
  type: "button",
3382
3871
  role: "menuitem",
3383
- className: css$14.item,
3872
+ className: css$17.item,
3384
3873
  disabled: sub.disabled,
3385
3874
  "aria-keyshortcuts": sub.shortcut?.aria,
3386
3875
  onClick: () => {
3387
- onSelect(sub.id);
3876
+ onSelect?.(sub.id);
3388
3877
  refocusAfterSelection();
3389
3878
  },
3390
3879
  children: [
3391
3880
  sub.icon !== void 0 && jsx("span", {
3392
- className: css$14.itemIcon,
3881
+ className: css$17.itemIcon,
3393
3882
  children: sub.icon
3394
3883
  }),
3395
3884
  jsx("span", {
3396
- className: css$14.itemLabel,
3885
+ className: css$17.itemLabel,
3397
3886
  children: sub.label
3398
3887
  }),
3399
3888
  sub.shortcut !== void 0 && jsx("span", {
3400
3889
  "aria-hidden": "true",
3401
- className: css$14.shortcut,
3890
+ className: css$17.shortcut,
3402
3891
  children: jsx(ShortcutKeys, {
3403
3892
  keys: sub.shortcut.keys,
3404
- className: css$14.shortcutKeys
3893
+ className: css$17.shortcutKeys
3405
3894
  })
3406
3895
  })
3407
3896
  ]
@@ -3409,27 +3898,38 @@ function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, onClose,
3409
3898
  })]
3410
3899
  }, entry.id);
3411
3900
  };
3412
- const list = open && jsxs("div", {
3901
+ const collapseSubmenuFrom = (e) => {
3902
+ const row = e.target instanceof Element ? e.target.closest("button[role=\"menuitem\"]") : null;
3903
+ if (row === null || row.getAttribute("aria-haspopup") === "menu") return;
3904
+ if (row.closest("[role=\"menu\"]") !== e.currentTarget) return;
3905
+ setOpenSubmenuId(null);
3906
+ };
3907
+ const list = open && jsxs(MenuSurface, {
3908
+ compact,
3413
3909
  ref: listRef,
3414
- className: clsx(css$14.list, dense && css$14.denseList, compact && css$14.compactList, scrollable && css$14.scrollable, portal && css$14.portal, side === "top" && !portal && css$14.sideTop, align === "end" && !portal && css$14.alignEnd),
3910
+ className: clsx(css$17.list, listClassName, dense && css$17.denseList, compact && css$17.compactList, scrollable && css$17.scrollable, portal && css$17.portal, side === "top" && !portal && css$17.sideTop, align === "end" && !portal && css$17.alignEnd),
3415
3911
  style: portal ? fixedPos ?? MEASURE_STYLE : void 0,
3416
3912
  role: "menu",
3417
3913
  onClick: (e) => {
3418
3914
  e.stopPropagation();
3915
+ const row = e.target instanceof Element ? e.target.closest("button[role=\"menuitem\"]") : null;
3916
+ if (row !== null && row.getAttribute("aria-haspopup") !== "menu") refocusAfterSelection();
3419
3917
  },
3420
- children: [jsx("div", {
3421
- className: css$14.viewport,
3918
+ onMouseOver: collapseSubmenuFrom,
3919
+ onFocus: collapseSubmenuFrom,
3920
+ children: [jsxs("div", {
3921
+ className: css$17.viewport,
3422
3922
  role: "presentation",
3423
- children: items.map(renderEntry)
3923
+ children: [items.map(renderEntry), children]
3424
3924
  }), footer !== void 0 && footer.length > 0 && jsx("div", {
3425
- className: css$14.footer,
3925
+ className: css$17.footer,
3426
3926
  role: "presentation",
3427
3927
  children: footer.map(renderEntry)
3428
3928
  })]
3429
3929
  });
3430
3930
  return jsxs("span", {
3431
3931
  ref: rootRef,
3432
- className: clsx(css$14.root, className),
3932
+ className: clsx(css$17.root, className),
3433
3933
  onPointerEnter: closeOnPointerLeave ? cancelClose : void 0,
3434
3934
  onPointerLeave: closeOnPointerLeave ? () => {
3435
3935
  if (open) armClose();
@@ -3478,20 +3978,6 @@ function useAnchoredMaxHeight(ref, cap, signal) {
3478
3978
  return maxHeight;
3479
3979
  }
3480
3980
  //#endregion
3481
- //#region lib/types/overlay-top-margin.js
3482
- /** Shared viewport inset for overlays, derived from the desktop frame's reserved top strip. */
3483
- /**
3484
- * Resolve the top margin an overlay keeps from the viewport edge.
3485
- * @param min - the overlay's own viewport margin in px, used as the floor.
3486
- * @returns the larger of `min` and the frame clearance plus 20px; fullscreen keeps only the 20px gap.
3487
- */
3488
- function overlayTopMargin(min) {
3489
- const root = document.documentElement;
3490
- const clearance = Number.parseFloat(getComputedStyle(root).getPropertyValue("--qilin-frame-top-clearance"));
3491
- if (Number.isNaN(clearance)) return min;
3492
- return Math.max(min, (root.hasAttribute("data-fullscreen") ? 0 : clearance) + 20);
3493
- }
3494
- //#endregion
3495
3981
  //#region lib/types/useAnchoredPosition.js
3496
3982
  /**
3497
3983
  * Keep a fixed-position floating element anchored to a trigger.
@@ -3506,11 +3992,11 @@ function overlayTopMargin(min) {
3506
3992
  */
3507
3993
  /**
3508
3994
  * Track an anchor and return the panel's fixed coordinates.
3509
- * @param options - the open state, the two refs, the placement side, and the gap/margin distances.
3995
+ * @param options - the open state, the two refs, the placement side and alignment, and the gap/margin distances.
3510
3996
  * @returns `left`/`top` for the panel, or `null` before the first measurement.
3511
3997
  */
3512
3998
  function useAnchoredPosition(options) {
3513
- const { open, anchorRef, panelRef, side = "bottom", gap, margin } = options;
3999
+ const { open, anchorRef, panelRef, side = "bottom", align = "start", gap, margin } = options;
3514
4000
  const [position, setPosition] = useState(null);
3515
4001
  useLayoutEffect(() => {
3516
4002
  if (!open) {
@@ -3526,7 +4012,7 @@ function useAnchoredPosition(options) {
3526
4012
  const panel = panelRef.current;
3527
4013
  const width = panel?.offsetWidth ?? 0;
3528
4014
  const height = panel?.offsetHeight ?? 0;
3529
- let left = rect.left;
4015
+ let left = align === "end" ? rect.right - width : rect.left;
3530
4016
  let top = side === "top" ? rect.top - gap - height : rect.bottom + gap;
3531
4017
  if (width > 0) left = Math.min(Math.max(left, margin), window.innerWidth - width - margin);
3532
4018
  if (height > 0) top = Math.min(Math.max(top, margin), window.innerHeight - height - margin);
@@ -3555,6 +4041,7 @@ function useAnchoredPosition(options) {
3555
4041
  anchorRef,
3556
4042
  panelRef,
3557
4043
  side,
4044
+ align,
3558
4045
  gap,
3559
4046
  margin
3560
4047
  ]);
@@ -3700,18 +4187,25 @@ const TooltipSuppression = createContext(null);
3700
4187
  * @param props.label - bubble text, or a resolver evaluated only while the bubble is visible.
3701
4188
  * @param props.shortcutKeys - effective key labels rendered as platform-formatted keycaps after optional text.
3702
4189
  * @param props.side - placement relative to the anchor (default 'right').
3703
- * @param props.delayMs - hover delay in milliseconds; keyboard focus remains immediate.
4190
+ * @param props.delayMs - hover delay in milliseconds (default 0).
4191
+ * @param props.focusDelayMs - keyboard focus delay in milliseconds (default 0); blur, mouse
4192
+ * leave, disabling, and unmount cancel a pending show.
3704
4193
  * @param props.disabled - suppress the bubble while true; the anchor renders identically so
3705
4194
  * toggling never remounts it (which would cut its CSS transitions).
3706
4195
  * @param props.portal - render the bubble under document.body, so an ancestor's clipping or its
3707
4196
  * stacking context can neither clip the bubble nor paint over it.
3708
4197
  * @param props.maxWidth - bubble width cap in pixels, for labels long enough that the default
3709
4198
  * half-viewport cap would render a slab wider than the surface the anchor sits on.
4199
+ * @param props.openOnClick - clicking also pins the bubble for reading; another click, Escape,
4200
+ * Tab, or an outside pointerdown dismisses it. Defaults to false, leaving an ordinary action
4201
+ * tooltip to hover and focus alone.
3710
4202
  * @param props.children - a single anchor element; its own ref (callback or object) is forwarded alongside the tooltip's.
3711
4203
  * An anchor that accepts no ref still positions the bubble: a raise records the element the event ran on.
3712
4204
  * @returns the cloned anchor plus a fixed-position bubble while hovered/focused.
3713
4205
  */
3714
- function Tooltip({ label, shortcutKeys, side = "right", delayMs = 0, disabled = false, portal = false, maxWidth, children }) {
4206
+ function Tooltip({ label, shortcutKeys, side = "right", delayMs = 0, focusDelayMs = 0, disabled = false, portal = false, maxWidth, openOnClick = false, children }) {
4207
+ const id = useId();
4208
+ const [pinned, setPinned] = useState(false);
3715
4209
  const anchor = useRef(null);
3716
4210
  const childRef = children.ref;
3717
4211
  const mergedRef = useCallback((el) => {
@@ -3781,6 +4275,7 @@ function Tooltip({ label, shortcutKeys, side = "right", delayMs = 0, disabled =
3781
4275
  showTimer.current = null;
3782
4276
  }, []);
3783
4277
  useEffect(() => {
4278
+ if (pinned && (disabled || !openOnClick)) setPinned(false);
3784
4279
  if (disabled) {
3785
4280
  cancelShow();
3786
4281
  triggers.current = {
@@ -3790,7 +4285,12 @@ function Tooltip({ label, shortcutKeys, side = "right", delayMs = 0, disabled =
3790
4285
  setPos(null);
3791
4286
  }
3792
4287
  return cancelShow;
3793
- }, [cancelShow, disabled]);
4288
+ }, [
4289
+ cancelShow,
4290
+ disabled,
4291
+ openOnClick,
4292
+ pinned
4293
+ ]);
3794
4294
  const show = () => {
3795
4295
  if (disabled) return;
3796
4296
  const el = anchor.current ?? eventAnchor.current;
@@ -3805,30 +4305,61 @@ function Tooltip({ label, shortcutKeys, side = "right", delayMs = 0, disabled =
3805
4305
  });
3806
4306
  announce(true);
3807
4307
  };
3808
- const showAfterHoverDelay = () => {
4308
+ const showAfterDelay = (delay) => {
3809
4309
  cancelShow();
3810
- if (delayMs <= 0) {
4310
+ if (delay <= 0) {
3811
4311
  show();
3812
4312
  return;
3813
4313
  }
3814
4314
  showTimer.current = setTimeout(() => {
3815
4315
  showTimer.current = null;
3816
4316
  show();
3817
- }, delayMs);
4317
+ }, delay);
3818
4318
  };
3819
- const withdraw = () => {
4319
+ const withdraw = useCallback(() => {
4320
+ setPinned(false);
3820
4321
  setPos(null);
3821
4322
  announce(false);
3822
- };
4323
+ }, [announce]);
3823
4324
  const hide = () => {
3824
4325
  cancelShow();
3825
- if (!triggers.current.hover && !triggers.current.focus) withdraw();
4326
+ if (!triggers.current.hover && !triggers.current.focus && !pinned) withdraw();
3826
4327
  };
4328
+ const dismiss = useCallback(() => {
4329
+ cancelShow();
4330
+ triggers.current = {
4331
+ hover: false,
4332
+ focus: false
4333
+ };
4334
+ withdraw();
4335
+ }, [cancelShow, withdraw]);
4336
+ useDismissOnOutsidePointer(anchor, openOnClick && visible, dismiss, bubble);
4337
+ useEffect(() => {
4338
+ if (!openOnClick || !visible) return;
4339
+ const onKeyDown = (event) => {
4340
+ if (event.key !== "Escape" && event.key !== "Tab") return;
4341
+ if (event.key === "Escape") {
4342
+ event.preventDefault();
4343
+ event.stopPropagation();
4344
+ }
4345
+ dismiss();
4346
+ };
4347
+ document.addEventListener("keydown", onKeyDown, true);
4348
+ return () => {
4349
+ document.removeEventListener("keydown", onKeyDown, true);
4350
+ };
4351
+ }, [
4352
+ dismiss,
4353
+ openOnClick,
4354
+ visible
4355
+ ]);
3827
4356
  const bubbleNode = visible && !suppressed && jsxs("span", {
3828
4357
  ref: bubble,
3829
- className: css$15.bubble,
4358
+ id: openOnClick ? id : void 0,
4359
+ className: css$18.bubble,
3830
4360
  "data-side": placement,
3831
4361
  "data-portal": portal || void 0,
4362
+ "data-pinned": pinned || void 0,
3832
4363
  "data-has-shortcut": shortcutKeys?.length ? true : void 0,
3833
4364
  style: {
3834
4365
  left: pos.x,
@@ -3838,7 +4369,7 @@ function Tooltip({ label, shortcutKeys, side = "right", delayMs = 0, disabled =
3838
4369
  role: "tooltip",
3839
4370
  "aria-label": shortcutKeys?.length ? [resolvedLabel, shortcutKeys.join(" ")].filter(Boolean).join(" ") : void 0,
3840
4371
  children: [resolvedLabel && jsx("span", {
3841
- className: css$15.label,
4372
+ className: css$18.label,
3842
4373
  children: resolvedLabel
3843
4374
  }), shortcutKeys !== void 0 && shortcutKeys.length > 0 && jsx(ShortcutKeys, {
3844
4375
  keys: shortcutKeys,
@@ -3849,25 +4380,35 @@ function Tooltip({ label, shortcutKeys, side = "right", delayMs = 0, disabled =
3849
4380
  value: setSuppressed,
3850
4381
  children: [cloneElement(children, {
3851
4382
  ref: mergedRef,
4383
+ "aria-describedby": openOnClick && visible ? [children.props["aria-describedby"], id].filter(Boolean).join(" ") : children.props["aria-describedby"],
3852
4384
  onMouseEnter: (e) => {
3853
4385
  children.props.onMouseEnter?.(e);
3854
4386
  trackAnchor(e);
3855
4387
  triggers.current.hover = true;
3856
- showAfterHoverDelay();
4388
+ showAfterDelay(delayMs);
3857
4389
  },
3858
4390
  onMouseLeave: (e) => {
3859
4391
  children.props.onMouseLeave?.(e);
3860
4392
  triggers.current.hover = false;
3861
4393
  cancelShow();
3862
- withdraw();
4394
+ if (!pinned) withdraw();
4395
+ },
4396
+ onClick: (e) => {
4397
+ children.props.onClick?.(e);
4398
+ if (!openOnClick) return;
4399
+ triggers.current.focus = false;
4400
+ cancelShow();
4401
+ if (!disabled && !pinned) {
4402
+ setPinned(true);
4403
+ show();
4404
+ } else withdraw();
3863
4405
  },
3864
4406
  onFocus: (e) => {
3865
4407
  children.props.onFocus?.(e);
3866
4408
  trackAnchor(e);
3867
4409
  if (pointerModality()) return;
3868
4410
  triggers.current.focus = true;
3869
- cancelShow();
3870
- show();
4411
+ showAfterDelay(focusDelayMs);
3871
4412
  },
3872
4413
  onBlur: (e) => {
3873
4414
  children.props.onBlur?.(e);
@@ -4044,7 +4585,7 @@ function HoverCard({ anchor, content, openDelayMs = 500, disabled = false, copyT
4044
4585
  const copyable = copyText !== void 0;
4045
4586
  const card = open && pos !== null && !suppressed && jsx("div", {
4046
4587
  ref: cardRef,
4047
- className: clsx(css$16.card, inline && css$16.media, copyable && css$16.copyable, copied && css$16.feedback),
4588
+ className: clsx(css$19.card, inline && css$19.media, copyable && css$19.copyable, copied && css$19.feedback),
4048
4589
  style: {
4049
4590
  ...pos,
4050
4591
  minHeight: copied && copyHeightRef.current !== null ? copyHeightRef.current : void 0
@@ -4065,14 +4606,14 @@ function HoverCard({ anchor, content, openDelayMs = 500, disabled = false, copyT
4065
4606
  copy(copyText);
4066
4607
  } : void 0,
4067
4608
  children: copied ? jsx("span", {
4068
- className: css$16.copied,
4609
+ className: css$19.copied,
4069
4610
  "aria-hidden": "true",
4070
4611
  children: copiedLabel
4071
4612
  }) : content
4072
4613
  });
4073
4614
  return jsxs("span", {
4074
4615
  ref: rootRef,
4075
- className: clsx(css$16.root, inline && css$16.inline),
4616
+ className: clsx(css$19.root, inline && css$19.inline),
4076
4617
  onFocus: inline ? (event) => {
4077
4618
  if (!disabled && event.target.matches(":focus-visible")) {
4078
4619
  cancelClose();
@@ -4111,7 +4652,7 @@ function HoverCard({ anchor, content, openDelayMs = 500, disabled = false, copyT
4111
4652
  children: anchor
4112
4653
  }),
4113
4654
  open && !suppressed && copyable && jsx("span", {
4114
- className: css$16.status,
4655
+ className: css$19.status,
4115
4656
  role: "status",
4116
4657
  children: copied ? copiedLabel : ""
4117
4658
  }),
@@ -4146,11 +4687,11 @@ function Modal({ open, onClose, title, closeLabel, description, children, footer
4146
4687
  useModalLayer(dialog, open, onClose);
4147
4688
  if (!open) return null;
4148
4689
  return createPortal(jsxs("div", {
4149
- className: css$17.root,
4690
+ className: css$20.root,
4150
4691
  role: "presentation",
4151
4692
  onKeyDownCapture,
4152
4693
  children: [jsx("div", {
4153
- className: css$17.mask,
4694
+ className: css$20.mask,
4154
4695
  style: backdropBlur ? void 0 : { backdropFilter: "none" },
4155
4696
  "aria-hidden": "true",
4156
4697
  onClick: onClose
@@ -4158,37 +4699,37 @@ function Modal({ open, onClose, title, closeLabel, description, children, footer
4158
4699
  ref: dialog,
4159
4700
  tabIndex: -1,
4160
4701
  "data-shortcut-modal": shortcutModal,
4161
- className: clsx(css$17.dialog, className),
4702
+ className: clsx(css$20.dialog, className),
4162
4703
  role: "dialog",
4163
4704
  "aria-modal": "true",
4164
4705
  "aria-label": title,
4165
4706
  children: headless ? children : jsxs(Fragment, { children: [jsxs("div", {
4166
- className: clsx(css$17.content, contentClassName),
4707
+ className: clsx(css$20.content, contentClassName),
4167
4708
  children: [
4168
4709
  jsxs("div", {
4169
- className: css$17.header,
4710
+ className: css$20.header,
4170
4711
  children: [jsx("h2", {
4171
- className: css$17.title,
4712
+ className: css$20.title,
4172
4713
  children: title
4173
4714
  }), jsx("button", {
4174
4715
  type: "button",
4175
- className: css$17.close,
4716
+ className: css$20.close,
4176
4717
  "aria-label": closeLabel,
4177
4718
  onClick: onClose,
4178
4719
  children: jsx(IconCloseOutline16, { size: 14 })
4179
4720
  })]
4180
4721
  }),
4181
4722
  description !== void 0 && description !== "" && jsx("p", {
4182
- className: css$17.description,
4723
+ className: css$20.description,
4183
4724
  children: description
4184
4725
  }),
4185
4726
  children !== void 0 && jsx("div", {
4186
- className: css$17.body,
4727
+ className: css$20.body,
4187
4728
  children
4188
4729
  })
4189
4730
  ]
4190
4731
  }), footer !== void 0 && jsx("div", {
4191
- className: css$17.footer,
4732
+ className: css$20.footer,
4192
4733
  children: footer
4193
4734
  })] })
4194
4735
  })]
@@ -4212,13 +4753,13 @@ function OnboardingSurface({ children }) {
4212
4753
  };
4213
4754
  }, []);
4214
4755
  return createPortal(jsxs("div", {
4215
- className: css$18.onboardingOverlay,
4756
+ className: css$21.onboardingOverlay,
4216
4757
  role: "presentation",
4217
4758
  children: [jsx("div", {
4218
- className: css$18.onboardingMask,
4759
+ className: css$21.onboardingMask,
4219
4760
  "aria-hidden": "true"
4220
4761
  }), jsx("div", {
4221
- className: css$18.onboardingStage,
4762
+ className: css$21.onboardingStage,
4222
4763
  children
4223
4764
  })]
4224
4765
  }), document.body);
@@ -4239,28 +4780,28 @@ function RiskConfirmation({ open, title, description, acknowledgeLabel, cancelLa
4239
4780
  onClose: onCancel,
4240
4781
  title,
4241
4782
  closeLabel,
4242
- className: css$19.confirmation ?? "",
4243
- contentClassName: css$19.confirmationContent ?? "",
4783
+ className: css$22.confirmation ?? "",
4784
+ contentClassName: css$22.confirmationContent ?? "",
4244
4785
  footer: jsxs(Fragment, { children: [jsx(Button, {
4245
4786
  variant: "outline",
4246
- className: css$19.modalAction,
4787
+ className: css$22.modalAction,
4247
4788
  onClick: onCancel,
4248
4789
  children: cancelLabel
4249
4790
  }), jsx(Button, {
4250
4791
  variant: "primary",
4251
- className: css$19.confirmAction,
4792
+ className: css$22.confirmAction,
4252
4793
  disabled: disabled || !acknowledged,
4253
4794
  onClick: onConfirm,
4254
4795
  children: confirmLabel
4255
4796
  })] }),
4256
4797
  children: [jsxs("div", {
4257
- className: css$19.warning,
4798
+ className: css$22.warning,
4258
4799
  children: [jsx(IconWarningOutline16, {
4259
4800
  size: 18,
4260
- className: css$19.warningIcon
4801
+ className: css$22.warningIcon
4261
4802
  }), jsx("p", { children: description })]
4262
4803
  }), jsxs("label", {
4263
- className: css$19.acknowledgement,
4804
+ className: css$22.acknowledgement,
4264
4805
  children: [jsx("input", {
4265
4806
  type: "checkbox",
4266
4807
  checked: acknowledged,
@@ -4308,47 +4849,47 @@ function ConnectionIndicator({ state, disconnectedLabel, connectingLabel, recove
4308
4849
  };
4309
4850
  }, [state, rendered]);
4310
4851
  if (rendered === void 0) return null;
4311
- const leavingClass = leaving ? ` ${css$20.leaving}` : "";
4852
+ const leavingClass = leaving ? ` ${css$23.leaving}` : "";
4312
4853
  if (rendered === "recovered") return jsxs("div", {
4313
- className: `${css$20.indicator} ${css$20.success}${leavingClass}`,
4854
+ className: `${css$23.indicator} ${css$23.success}${leavingClass}`,
4314
4855
  role: "status",
4315
4856
  "aria-label": recoveredLabel,
4316
4857
  children: [jsx("span", {
4317
- className: css$20.icon,
4858
+ className: css$23.icon,
4318
4859
  "aria-hidden": "true",
4319
4860
  children: jsx(IconCheckOutline16, { size: 14 })
4320
4861
  }), jsx("span", {
4321
- className: css$20.label,
4862
+ className: css$23.label,
4322
4863
  children: recoveredLabel
4323
4864
  })]
4324
4865
  });
4325
4866
  const connecting = rendered === "connecting";
4326
4867
  return jsxs("button", {
4327
4868
  type: "button",
4328
- className: `${css$20.indicator} ${css$20.warning}${leavingClass}`,
4869
+ className: `${css$23.indicator} ${css$23.warning}${leavingClass}`,
4329
4870
  "data-phase": rendered,
4330
4871
  "aria-label": connecting ? restartActionLabel : reconnectActionLabel,
4331
4872
  onClick: onReconnect,
4332
4873
  children: [jsx("span", {
4333
- className: css$20.icon,
4874
+ className: css$23.icon,
4334
4875
  "aria-hidden": "true",
4335
4876
  children: connecting ? jsx(IconLoadingOutline16, {
4336
4877
  size: 14,
4337
- className: css$20.spinner
4878
+ className: css$23.spinner
4338
4879
  }) : jsx(IconRefreshOutline14, { size: 14 })
4339
4880
  }), jsx("span", {
4340
- className: css$20.label,
4881
+ className: css$23.label,
4341
4882
  children: connecting ? jsxs(Fragment, { children: [connectingLabel, jsxs("span", {
4342
- className: css$20.dots,
4883
+ className: css$23.dots,
4343
4884
  "aria-hidden": "true",
4344
4885
  children: [
4345
4886
  jsx("span", { children: "." }),
4346
4887
  jsx("span", {
4347
- className: css$20.secondDot,
4888
+ className: css$23.secondDot,
4348
4889
  children: "."
4349
4890
  }),
4350
4891
  jsx("span", {
4351
- className: css$20.thirdDot,
4892
+ className: css$23.thirdDot,
4352
4893
  children: "."
4353
4894
  })
4354
4895
  ]
@@ -5173,7 +5714,7 @@ function FileTypeIcon(props) {
5173
5714
  type: resolvedType,
5174
5715
  size,
5175
5716
  className
5176
- }) : glyph(resolvedType, size, clsx(css$21.icon, css$21[resolvedType], className));
5717
+ }) : glyph(resolvedType, size, clsx(css$24.icon, css$24[resolvedType], className));
5177
5718
  }
5178
5719
  //#endregion
5179
5720
  //#region lib/types/SiteGlyph.js
@@ -5486,22 +6027,772 @@ function PathLabel({ path, className, ...attributes }) {
5486
6027
  return jsx("span", {
5487
6028
  ...attributes,
5488
6029
  ref: boxRef,
5489
- className: clsx(css$22.path, className),
6030
+ className: clsx(css$25.path, className),
5490
6031
  title: path,
5491
6032
  "data-path-label": true,
5492
6033
  children: jsxs("span", {
5493
6034
  ref: textRef,
5494
- className: css$22.text,
6035
+ className: css$25.text,
5495
6036
  children: [directory !== "" && jsx("span", {
5496
- className: css$22.directory,
6037
+ className: css$25.directory,
5497
6038
  children: directory
5498
6039
  }), jsx("span", {
5499
- className: css$22.name,
6040
+ className: css$25.name,
5500
6041
  children: name
5501
6042
  })]
5502
6043
  })
5503
6044
  });
5504
6045
  }
6046
+ const prefixed = (literal, check, run, min, max = 0) => ({
6047
+ literal,
6048
+ kind: 2,
6049
+ check,
6050
+ run,
6051
+ min,
6052
+ max
6053
+ });
6054
+ /**
6055
+ * Every prefixed format matches more than the eight characters a mask leaves
6056
+ * readable, so a near miss never exposes a whole value.
6057
+ */
6058
+ const CREDENTIAL_FORMATS = [
6059
+ {
6060
+ literal: "-----BEGIN ",
6061
+ kind: 0,
6062
+ check: 0,
6063
+ run: 0,
6064
+ min: 0,
6065
+ max: 0
6066
+ },
6067
+ {
6068
+ literal: "://",
6069
+ kind: 1,
6070
+ check: 0,
6071
+ run: 0,
6072
+ min: 0,
6073
+ max: 0
6074
+ },
6075
+ prefixed("sk-", 2, 1, 20),
6076
+ prefixed("AIza", 3, 1, 35),
6077
+ prefixed("ghp_", 0, 2, 36),
6078
+ prefixed("gho_", 0, 2, 36),
6079
+ prefixed("ghu_", 0, 2, 36),
6080
+ prefixed("ghs_", 0, 2, 36),
6081
+ prefixed("ghr_", 0, 2, 36),
6082
+ prefixed("github_pat_", 0, 4, 22),
6083
+ prefixed("glpat-", 0, 1, 20),
6084
+ prefixed("npm_", 0, 2, 36),
6085
+ prefixed("hf_", 0, 2, 30),
6086
+ prefixed("AKIA", 1, 16, 16, 16),
6087
+ prefixed("ASIA", 1, 16, 16, 16),
6088
+ prefixed("LTAI", 1, 2, 12, 20),
6089
+ prefixed("AKID", 1, 2, 28, 36),
6090
+ prefixed("xoxa-", 0, 8, 10),
6091
+ prefixed("xoxb-", 0, 8, 10),
6092
+ prefixed("xoxp-", 0, 8, 10),
6093
+ prefixed("xoxr-", 0, 8, 10),
6094
+ prefixed("xoxs-", 0, 8, 10),
6095
+ prefixed("sk_live_", 0, 2, 16),
6096
+ prefixed("sk_test_", 0, 2, 16),
6097
+ prefixed("rk_live_", 0, 2, 16),
6098
+ prefixed("rk_test_", 0, 2, 16),
6099
+ prefixed("whsec_", 0, 2, 24),
6100
+ prefixed("eyJ", 4, 1, 8, 2048)
6101
+ ];
6102
+ /** Leading characters of a prefixed key left readable: the provider prefix and little else. */
6103
+ const VISIBLE_PREFIX = 8;
6104
+ const SHARED_MARKS = 4096;
6105
+ /** Builds masks; owns the shared mark strings and its sticky run pattern. */
6106
+ var CredentialMasks = class {
6107
+ marksOnly = "*".repeat(SHARED_MARKS);
6108
+ marksLf = `${this.marksOnly}\n`;
6109
+ marksCr = `${this.marksOnly}\r`;
6110
+ /** Code units that `lines` counts without inspection: neither line breaks nor surrogates. Set `lastIndex` before each test. */
6111
+ ordinary = /[^\r\n\ud800-\udfff]*/y;
6112
+ /**
6113
+ * The display form of `text[start, end)`, whose earliest candidate has `kind`.
6114
+ * @param text - the queried text.
6115
+ * @param kind - the literal kind of the range's earliest candidate.
6116
+ * @param plain - the range holds only prefixed-format characters: ASCII without line breaks.
6117
+ * @param start - first offset of the range.
6118
+ * @param end - offset after the range.
6119
+ * @returns the mask; line breaks stay in place, one mark per code point.
6120
+ */
6121
+ masked(text, kind, plain, start, end) {
6122
+ if (kind === 1) return this.range(text, start, end);
6123
+ if (kind === 2) return text.slice(start, start + VISIBLE_PREFIX) + (plain ? this.marks(end - start - VISIBLE_PREFIX) : this.range(text, start + VISIBLE_PREFIX, end));
6124
+ return this.keyBlock(text, start, end);
6125
+ }
6126
+ /**
6127
+ * Marks for a run of hidden characters.
6128
+ * @param count - how many marks.
6129
+ * @returns `count` marks, one slice of the shared string where it reaches.
6130
+ */
6131
+ marks(count) {
6132
+ return count <= SHARED_MARKS ? this.marksOnly.slice(0, count) : "*".repeat(count);
6133
+ }
6134
+ /**
6135
+ * Marks, then one line break, in a single slice.
6136
+ * @param count - how many marks.
6137
+ * @param code - the line break's code unit, 10 or 13.
6138
+ * @returns `count` marks and that line break.
6139
+ */
6140
+ marksThen(count, code) {
6141
+ return count <= SHARED_MARKS ? (code === 10 ? this.marksLf : this.marksCr).slice(SHARED_MARKS - count) : "*".repeat(count) + (code === 10 ? "\n" : "\r");
6142
+ }
6143
+ /**
6144
+ * Keep the `BEGIN` line, the `END` line when present, and every line break; a block written on
6145
+ * one line is masked whole. Both searches stay inside the range, so they cost what the mask costs.
6146
+ * @param text - the queried text.
6147
+ * @param start - first offset of the range.
6148
+ * @param end - offset after the range.
6149
+ * @returns the masked block.
6150
+ */
6151
+ keyBlock(text, start, end) {
6152
+ let bodyStart = start;
6153
+ for (let index = start; index < end; index++) if (text.charCodeAt(index) === 10) {
6154
+ bodyStart = index + 1;
6155
+ break;
6156
+ }
6157
+ let bodyEnd = end;
6158
+ for (let index = end - 9; index >= bodyStart; index--) if (text.charCodeAt(index) === 10 && text.startsWith("-----END", index + 1)) {
6159
+ bodyEnd = index;
6160
+ break;
6161
+ }
6162
+ const body = bodyEnd === text.length || text.charCodeAt(bodyEnd) === 10 || text.charCodeAt(bodyEnd) === 13 ? this.lines(text, bodyStart, bodyEnd) : this.range(text, bodyStart, bodyEnd);
6163
+ return text.slice(start, bodyStart) + body + text.slice(bodyEnd, end);
6164
+ }
6165
+ /**
6166
+ * Replace every character except line breaks; a surrogate pair is one character,
6167
+ * as `[^\r\n]` with the `u` flag counts it. A character loop: a native run could read far past `end`.
6168
+ * @param text - the queried text.
6169
+ * @param start - first offset of the range.
6170
+ * @param end - offset after the range.
6171
+ * @returns the masked range.
6172
+ */
6173
+ range(text, start, end) {
6174
+ let masked = "";
6175
+ let count = 0;
6176
+ for (let index = start; index < end; index++) {
6177
+ const code = text.charCodeAt(index);
6178
+ if (code === 10 || code === 13) {
6179
+ masked += this.marksThen(count, code);
6180
+ count = 0;
6181
+ continue;
6182
+ }
6183
+ if (code >= 55296 && code <= 56319 && index + 1 < end) {
6184
+ const next = text.charCodeAt(index + 1);
6185
+ if (next >= 56320 && next <= 57343) index++;
6186
+ }
6187
+ count++;
6188
+ }
6189
+ return masked + this.marks(count);
6190
+ }
6191
+ /**
6192
+ * `range` for a body that ends at a line break or the end of the text, where native runs stop.
6193
+ * @param text - the queried text.
6194
+ * @param start - first offset of the range.
6195
+ * @param end - offset after the range.
6196
+ * @returns the masked body.
6197
+ */
6198
+ lines(text, start, end) {
6199
+ const ordinary = this.ordinary;
6200
+ let masked = "";
6201
+ let count = 0;
6202
+ let index = start;
6203
+ while (index < end) {
6204
+ ordinary.lastIndex = index;
6205
+ ordinary.test(text);
6206
+ const stop = Math.min(ordinary.lastIndex, end);
6207
+ count += stop - index;
6208
+ if (stop === end) break;
6209
+ const code = text.charCodeAt(stop);
6210
+ index = stop + 1;
6211
+ if (code === 10 || code === 13) {
6212
+ masked += this.marksThen(count, code);
6213
+ count = 0;
6214
+ continue;
6215
+ }
6216
+ if (code <= 56319 && index < end) {
6217
+ const next = text.charCodeAt(index);
6218
+ if (next >= 56320 && next <= 57343) index++;
6219
+ }
6220
+ count++;
6221
+ }
6222
+ return masked + this.marks(count);
6223
+ }
6224
+ };
6225
+ //#endregion
6226
+ //#region lib/types/SecretText.js
6227
+ /**
6228
+ * Masked credential presentation: the masked form by default, plus a control
6229
+ * that reveals this one value in interactive text.
6230
+ */
6231
+ const EYE_PATH = "M1.5 8C2.9 5.25 5.25 3.5 8 3.5C10.75 3.5 13.1 5.25 14.5 8C13.1 10.75 10.75 12.5 8 12.5C5.25 12.5 2.9 10.75 1.5 8ZM10 8C10 9.1 9.1 10 8 10C6.9 10 6 9.1 6 8C6 6.9 6.9 6 8 6C9.1 6 10 6.9 10 8Z";
6232
+ /** The struck-through glyph drops the pupil so it stays distinct at text size. */
6233
+ const EYE_OFF_PATH = "M1.5 8C2.9 5.25 5.25 3.5 8 3.5C10.75 3.5 13.1 5.25 14.5 8C13.1 10.75 10.75 12.5 8 12.5C5.25 12.5 2.9 10.75 1.5 8ZM2.5 2.5L13.5 13.5";
6234
+ const MASK_RUNS = /* @__PURE__ */ new RegExp("(\\*+)", "u");
6235
+ /**
6236
+ * One eye glyph, drawn in the current text color.
6237
+ * @param props - the outline to draw.
6238
+ * @returns the glyph.
6239
+ */
6240
+ function EyeGlyph({ path }) {
6241
+ return jsx("svg", {
6242
+ className: css$26.icon,
6243
+ viewBox: "0 0 16 16",
6244
+ fill: "none",
6245
+ stroke: "currentColor",
6246
+ strokeWidth: 1.3,
6247
+ strokeLinecap: "round",
6248
+ "aria-hidden": "true",
6249
+ children: jsx("path", { d: path })
6250
+ });
6251
+ }
6252
+ /**
6253
+ * Split a masked form into kept text and mask runs. A mask run keeps its
6254
+ * characters for copying and assistive technology but draws centered tiles,
6255
+ * because a font's own asterisk sits near the cap height.
6256
+ * @param props - the masked form.
6257
+ * @returns the inline parts covering it.
6258
+ */
6259
+ function MaskedText({ masked }) {
6260
+ let offset = 0;
6261
+ return masked.split(MASK_RUNS).map((part) => {
6262
+ const key = offset;
6263
+ offset += part.length;
6264
+ if (part === "") return null;
6265
+ return part.startsWith("*") ? jsx("span", {
6266
+ className: css$26.mask,
6267
+ children: part
6268
+ }, key) : jsx("span", { children: part }, key);
6269
+ });
6270
+ }
6271
+ /**
6272
+ * Draw one credential masked. Interactive text adds a control that reveals or
6273
+ * hides this value; every mount, and every different original value at the same
6274
+ * position, starts masked.
6275
+ * @param props - the masked form, the original spelling, and optional control copy.
6276
+ * @returns the masked run, with the reveal control when copy is supplied.
6277
+ */
6278
+ function SecretText({ masked, raw, labels }) {
6279
+ const [revealedRaw, setRevealedRaw] = useState();
6280
+ const revealed = labels !== void 0 && revealedRaw === raw;
6281
+ return jsxs("span", {
6282
+ className: css$26.secret,
6283
+ "data-secret": "",
6284
+ children: [jsx("span", { children: revealed ? raw : jsx(MaskedText, { masked }) }), labels !== void 0 && jsx("button", {
6285
+ type: "button",
6286
+ className: css$26.toggle,
6287
+ "aria-pressed": revealed,
6288
+ "aria-label": revealed ? labels.hide : labels.reveal,
6289
+ onClick: () => {
6290
+ setRevealedRaw(revealed ? void 0 : raw);
6291
+ },
6292
+ children: jsx(EyeGlyph, { path: revealed ? EYE_OFF_PATH : EYE_PATH })
6293
+ })]
6294
+ });
6295
+ }
6296
+ //#endregion
6297
+ //#region lib/types/format-tables.js
6298
+ /** Lookup tables derived from the credential formats, built once on first use. */
6299
+ let tables;
6300
+ /**
6301
+ * The tables for `CREDENTIAL_FORMATS`; the first call builds them.
6302
+ * @returns the shared, read-only tables.
6303
+ */
6304
+ function formatTables() {
6305
+ tables ??= buildTables();
6306
+ return tables;
6307
+ }
6308
+ /**
6309
+ * Build every lookup table once.
6310
+ * @returns the tables.
6311
+ */
6312
+ function buildTables() {
6313
+ const formats = CREDENTIAL_FORMATS;
6314
+ const literals = formats.map((f) => f.literal);
6315
+ const { ending, sharedEndings } = endingTables(literals);
6316
+ return {
6317
+ classes: charClasses(),
6318
+ literals,
6319
+ literalLength: Uint8Array.from(literals, (literal) => literal.length),
6320
+ literalKind: Uint8Array.from(formats, (f) => f.kind),
6321
+ literalCheck: Uint8Array.from(formats, (f) => f.check),
6322
+ literalRun: Uint16Array.from(formats, (f) => f.run),
6323
+ literalMin: Int32Array.from(formats, (f) => f.min),
6324
+ literalMax: Int32Array.from(formats, (f) => f.max),
6325
+ literalOverlap: Uint8Array.from(literals, (literal) => overlap(literal, literals)),
6326
+ prefixSource: alternation(literals),
6327
+ ending,
6328
+ sharedEndings
6329
+ };
6330
+ }
6331
+ /**
6332
+ * Class bits for every ASCII code unit; non-ASCII units carry none.
6333
+ * @returns the 128-entry table.
6334
+ */
6335
+ function charClasses() {
6336
+ const classes = new Uint16Array(128);
6337
+ for (let code = 0; code < 128; code++) {
6338
+ const upper = code >= 65 && code <= 90;
6339
+ const lower = code >= 97 && code <= 122;
6340
+ const digit = code >= 48 && code <= 57;
6341
+ const alnum = upper || lower || digit;
6342
+ const authority = !(code >= 9 && code <= 13 || code === 32 || code === 47 || code === 64 || code === 63 || code === 35);
6343
+ classes[code] = (alnum || code === 95 || code === 45 ? 1 : 0) | (alnum ? 2 : 0) | (alnum || code === 95 ? 4 : 0) | (alnum || code === 45 ? 8 : 0) | (upper || digit ? 16 : 0) | (upper || digit || code === 32 ? 32 : 0) | (lower || digit || code === 43 || code === 46 || code === 45 ? 64 : 0) | (lower ? 128 : 0) | (authority && code !== 58 ? 256 : 0) | (authority ? 512 : 0);
6344
+ }
6345
+ return classes;
6346
+ }
6347
+ /**
6348
+ * Length of the longest proper suffix of `literal` that begins another literal.
6349
+ * @param literal - the literal to measure.
6350
+ * @param literals - every literal.
6351
+ * @returns that suffix length, or 0.
6352
+ */
6353
+ function overlap(literal, literals) {
6354
+ for (let size = literal.length - 1; size > 0; size--) {
6355
+ const suffix = literal.slice(-size);
6356
+ if (literals.some((other) => other.startsWith(suffix))) return size;
6357
+ }
6358
+ return 0;
6359
+ }
6360
+ /**
6361
+ * Index the literals by their last two code units so the scan reads the matched
6362
+ * literal from the prefix alternation's end.
6363
+ * @param literals - every literal.
6364
+ * @returns the single-literal table and the table of endings several literals share.
6365
+ */
6366
+ function endingTables(literals) {
6367
+ const ending = new Int8Array(16384);
6368
+ const sharedEndings = [];
6369
+ literals.forEach((literal, index) => {
6370
+ const key = literal.charCodeAt(literal.length - 2) * 128 + literal.charCodeAt(literal.length - 1);
6371
+ const existing = ending[key];
6372
+ if (existing === 0) {
6373
+ ending[key] = index + 1;
6374
+ return;
6375
+ }
6376
+ if (existing > 0) {
6377
+ sharedEndings[key] = [existing - 1];
6378
+ ending[key] = -1;
6379
+ }
6380
+ sharedEndings[key].push(index);
6381
+ });
6382
+ return {
6383
+ ending,
6384
+ sharedEndings
6385
+ };
6386
+ }
6387
+ const escape = (literal) => literal.replace(/[.*+?^${}()|[\]\\/]/gu, "\\$&");
6388
+ /**
6389
+ * Literal alternatives grouped by shared leading characters; groups only factor literals and add no quantifier.
6390
+ * @param literals - every literal.
6391
+ * @returns the alternation source.
6392
+ */
6393
+ function alternation(literals) {
6394
+ const groups = /* @__PURE__ */ new Map();
6395
+ for (const literal of literals) groups.set(literal.charAt(0), [...groups.get(literal.charAt(0)) ?? [], literal.slice(1)]);
6396
+ return [...groups].map(([head, tails]) => tails.length === 1 ? escape(head + tails.join("")) : `${escape(head)}(?:${alternation(tails)})`).join("|");
6397
+ }
6398
+ //#endregion
6399
+ //#region lib/types/credential-scanner.js
6400
+ /**
6401
+ * Prefix-pruned, linear credential scanning that allocates nothing until it
6402
+ * returns a range. A literal-only alternation finds each place a format can
6403
+ * begin and resumes inside a literal that can overlap the next one. Format
6404
+ * checks are bounded character comparisons and sticky `[class]*` runs, which
6405
+ * end at the first character outside the class and leave nothing to backtrack
6406
+ * into. Run ends, the next digit, and the next key-block `END` line are
6407
+ * memoized per text across queries, so each is measured once per text.
6408
+ */
6409
+ const KEY_SLOTS = 0;
6410
+ const KEY_NEXT = 8;
6411
+ const ALNUM_SLOT = 9;
6412
+ const WORD_SLOT = 11;
6413
+ const ALNUM_DASH_SLOT = 13;
6414
+ const UPPER_ALNUM_SLOT = 15;
6415
+ const USER_SLOT = 17;
6416
+ const PASSWORD_SLOT = 19;
6417
+ const DIGIT_FROM = 21;
6418
+ const DIGIT_AT = 22;
6419
+ const BLOCK_FROM = 23;
6420
+ const BLOCK_END_START = 24;
6421
+ const BLOCK_END = 25;
6422
+ /** Start of the password that the last address check accepted. */
6423
+ const CANDIDATE_START = 26;
6424
+ const MEMO_SIZE = 27;
6425
+ /** `\s` above ASCII. */
6426
+ function isWideSpace(code) {
6427
+ return code === 160 || code === 5760 || code >= 8192 && code <= 8202 || code === 8232 || code === 8233 || code === 8239 || code === 8287 || code === 12288 || code === 65279;
6428
+ }
6429
+ /**
6430
+ * Offset after the run that sticky `pattern` matches at `start`.
6431
+ * @param pattern - sticky run pattern.
6432
+ * @param text - the text to measure.
6433
+ * @param start - offset the run starts at.
6434
+ * @returns offset after the run.
6435
+ */
6436
+ function runEnd(pattern, text, start) {
6437
+ pattern.lastIndex = start;
6438
+ pattern.test(text);
6439
+ return pattern.lastIndex;
6440
+ }
6441
+ /**
6442
+ * One scanner's state: the tables, its own patterns, and a memo of the last
6443
+ * queried text, which it keeps until a query for another text. Queries are
6444
+ * synchronous and never re-enter, so the patterns' cursors are never shared.
6445
+ */
6446
+ var CredentialScanner = class {
6447
+ classes;
6448
+ literals;
6449
+ literalLength;
6450
+ literalKind;
6451
+ literalCheck;
6452
+ literalMin;
6453
+ literalMax;
6454
+ literalOverlap;
6455
+ ending;
6456
+ sharedEndings;
6457
+ /** Memo slot of each prefixed format's run class; 0 for `[A-Za-z0-9_-]`, which has four. */
6458
+ literalSlot;
6459
+ literalPattern;
6460
+ prefixes;
6461
+ keyRun = /[A-Za-z0-9_-]*/y;
6462
+ userRun = /[^\s/:@?#]*/y;
6463
+ passwordRun = /[^\s/@?#]*/y;
6464
+ nonDigits = /\D*/y;
6465
+ masks = new CredentialMasks();
6466
+ memo = new Int32Array(MEMO_SIZE).fill(-1);
6467
+ text = "";
6468
+ /**
6469
+ * Build one scanner over shared tables.
6470
+ * @param tables - the tables every scanner shares.
6471
+ */
6472
+ constructor(tables) {
6473
+ this.classes = tables.classes;
6474
+ this.literals = tables.literals;
6475
+ this.literalLength = tables.literalLength;
6476
+ this.literalKind = tables.literalKind;
6477
+ this.literalCheck = tables.literalCheck;
6478
+ this.literalMin = tables.literalMin;
6479
+ this.literalMax = tables.literalMax;
6480
+ this.literalOverlap = tables.literalOverlap;
6481
+ this.ending = tables.ending;
6482
+ this.sharedEndings = tables.sharedEndings;
6483
+ this.prefixes = new RegExp(tables.prefixSource, "g");
6484
+ const patterns = new Map([
6485
+ [2, [ALNUM_SLOT, /[A-Za-z0-9]*/y]],
6486
+ [4, [WORD_SLOT, /\w*/y]],
6487
+ [8, [ALNUM_DASH_SLOT, /[A-Za-z0-9-]*/y]],
6488
+ [16, [UPPER_ALNUM_SLOT, /[A-Z0-9]*/y]]
6489
+ ]);
6490
+ this.literalSlot = Uint8Array.from(tables.literalRun, (run) => patterns.get(run)?.[0] ?? 0);
6491
+ this.literalPattern = Array.from(tables.literalRun, (run) => patterns.get(run)?.[1] ?? this.keyRun);
6492
+ }
6493
+ /**
6494
+ * The nearest credential at or after `from`. Overlapping candidates of any format join the earliest
6495
+ * one and take its mask, so no credential is drawn half masked. Candidates arrive in start order;
6496
+ * an address password waits until the scan passes its start, and no other `://` can occur before
6497
+ * then, because a user name and a password exclude `/`. A password that starts inside a range also
6498
+ * ends inside it: the range holds the `:` before the password, so it is a key block, whose `END`
6499
+ * line has spaces, or one that runs to the end of the text.
6500
+ * @param text - the complete original text.
6501
+ * @param from - the query offset.
6502
+ * @returns the nearest credential range, or undefined when none starts at or after `from`.
6503
+ */
6504
+ match(text, from) {
6505
+ if (text !== this.text) {
6506
+ this.memo.fill(-1);
6507
+ this.text = text;
6508
+ }
6509
+ const prefixes = this.prefixes;
6510
+ const length = text.length;
6511
+ let start = -1;
6512
+ let end = -1;
6513
+ let kind = 2;
6514
+ let plain = true;
6515
+ let deferredEnd = this.addressBefore(from);
6516
+ let deferredStart = deferredEnd < 0 ? -1 : this.slot(CANDIDATE_START);
6517
+ prefixes.lastIndex = from;
6518
+ while (prefixes.test(text)) {
6519
+ const literalEnd = prefixes.lastIndex;
6520
+ const literal = this.literalEndingAt(literalEnd);
6521
+ const at = literalEnd - this.literalLength[literal];
6522
+ prefixes.lastIndex = literalEnd - this.literalOverlap[literal];
6523
+ if (deferredStart >= 0 && deferredStart <= at) {
6524
+ if (start < 0) {
6525
+ start = deferredStart;
6526
+ end = deferredEnd;
6527
+ kind = 1;
6528
+ } else break;
6529
+ deferredStart = -1;
6530
+ }
6531
+ if (start >= 0 && (at >= end || end === length)) break;
6532
+ const literalKind = this.literalKind[literal];
6533
+ if (literalKind === 1) {
6534
+ deferredEnd = this.addressPassword(at);
6535
+ deferredStart = deferredEnd < 0 ? -1 : this.slot(CANDIDATE_START);
6536
+ continue;
6537
+ }
6538
+ const candidateEnd = literalKind === 0 ? this.keyBlockEnd(at) : this.prefixedEnd(literal, at);
6539
+ if (candidateEnd < 0) continue;
6540
+ if (start < 0) {
6541
+ start = at;
6542
+ end = candidateEnd;
6543
+ kind = literalKind;
6544
+ plain = literalKind === 2;
6545
+ } else if (candidateEnd > end) {
6546
+ end = candidateEnd;
6547
+ if (literalKind !== 2) plain = false;
6548
+ }
6549
+ }
6550
+ if (start < 0 && deferredStart >= 0) {
6551
+ start = deferredStart;
6552
+ end = deferredEnd;
6553
+ kind = 1;
6554
+ }
6555
+ if (start < 0) return void 0;
6556
+ return {
6557
+ start,
6558
+ end,
6559
+ masked: this.masks.masked(text, kind, plain, start, end)
6560
+ };
6561
+ }
6562
+ /**
6563
+ * Memo entry at `index`; the layout keeps every index inside the array.
6564
+ * @param index - the memo index.
6565
+ * @returns the stored offset.
6566
+ */
6567
+ slot(index) {
6568
+ return this.memo[index];
6569
+ }
6570
+ /**
6571
+ * `\w` at one offset; out of range is not a word character.
6572
+ * @param index - the offset to read.
6573
+ * @returns whether the code unit is a word character.
6574
+ */
6575
+ isWordAt(index) {
6576
+ const code = this.text.charCodeAt(index);
6577
+ return code < 128 && (this.classes[code] & 4) !== 0;
6578
+ }
6579
+ /**
6580
+ * `[^\s/:@?#]` for one UTF-16 code unit; NaN, read out of range, is not one.
6581
+ * @param code - the code unit.
6582
+ * @returns whether the code unit may appear in an address user name.
6583
+ */
6584
+ isUserCode(code) {
6585
+ return code < 128 ? (this.classes[code] & 256) !== 0 : code === code && !isWideSpace(code);
6586
+ }
6587
+ /**
6588
+ * Index of the literal the prefix scan matched ending at `end`; one literal sharing the ending matches, so the last needs no check.
6589
+ * @param end - the offset after the matched literal.
6590
+ * @returns the literal's index.
6591
+ */
6592
+ literalEndingAt(end) {
6593
+ const text = this.text;
6594
+ const key = text.charCodeAt(end - 2) * 128 + text.charCodeAt(end - 1);
6595
+ const literal = this.ending[key];
6596
+ if (literal > 0) return literal - 1;
6597
+ const shared = this.sharedEndings[key];
6598
+ let index = 0;
6599
+ for (; index < shared.length - 1; index++) {
6600
+ const candidate = shared[index];
6601
+ if (text.startsWith(this.literals[candidate], end - this.literalLength[candidate])) break;
6602
+ }
6603
+ return shared[index];
6604
+ }
6605
+ /**
6606
+ * End of the `[A-Za-z0-9_-]*` run at `start`, through four memo pairs replaced in turn.
6607
+ * @param start - the run's first offset.
6608
+ * @returns the offset after the run.
6609
+ */
6610
+ keyRunEnd(start) {
6611
+ for (let slot = KEY_SLOTS; slot < KEY_NEXT; slot += 2) if (this.slot(slot) <= start && start <= this.slot(slot + 1)) return this.slot(slot + 1);
6612
+ const end = runEnd(this.keyRun, this.text, start);
6613
+ const next = this.slot(KEY_NEXT) + 1 & 3;
6614
+ this.memo[KEY_NEXT] = next;
6615
+ this.memo[KEY_SLOTS + 2 * next] = start;
6616
+ this.memo[KEY_SLOTS + 2 * next + 1] = end;
6617
+ return end;
6618
+ }
6619
+ /**
6620
+ * End of the run `pattern` matches at `start`, through the memo pair at `slot`.
6621
+ * @param pattern - the sticky run pattern.
6622
+ * @param start - the run's first offset.
6623
+ * @param slot - the memo pair to fill.
6624
+ * @returns the offset after the run.
6625
+ */
6626
+ memoRunEnd(pattern, start, slot) {
6627
+ if (this.slot(slot) <= start && start <= this.slot(slot + 1)) return this.slot(slot + 1);
6628
+ const end = runEnd(pattern, this.text, start);
6629
+ this.memo[slot] = start;
6630
+ this.memo[slot + 1] = end;
6631
+ return end;
6632
+ }
6633
+ /**
6634
+ * Offset of the first digit at or after `start`, or the text length.
6635
+ * @param start - the offset to search from.
6636
+ * @returns the digit's offset.
6637
+ */
6638
+ nextDigit(start) {
6639
+ if (this.slot(DIGIT_FROM) <= start && start <= this.slot(DIGIT_AT)) return this.slot(DIGIT_AT);
6640
+ this.memo[DIGIT_FROM] = start;
6641
+ this.memo[DIGIT_AT] = runEnd(this.nonDigits, this.text, start);
6642
+ return this.slot(DIGIT_AT);
6643
+ }
6644
+ /**
6645
+ * Offset after `[A-Z0-9 ]{0,40}PRIVATE KEY-----` at `start`, or -1; reads at most 52 characters.
6646
+ * @param start - the offset the label starts at.
6647
+ * @returns the offset after the header label, or -1.
6648
+ */
6649
+ labelEnd(start) {
6650
+ const text = this.text;
6651
+ const limit = Math.min(text.length, start + 52);
6652
+ let index = start;
6653
+ while (index < limit) {
6654
+ const code = text.charCodeAt(index);
6655
+ if (code > 127 || (this.classes[code] & 32) === 0) break;
6656
+ index++;
6657
+ }
6658
+ const tail = index - 11;
6659
+ return index < start + 52 && tail >= start && text.startsWith("PRIVATE KEY-----", tail) ? tail + 16 : -1;
6660
+ }
6661
+ /**
6662
+ * End of the `-----BEGIN [A-Z0-9 ]{0,40}PRIVATE KEY-----` block at `at`: after its first complete
6663
+ * `END` line, or the end of the text; -1 for an invalid header.
6664
+ * @param at - the offset of the `-----BEGIN ` literal.
6665
+ * @returns the offset after the block, or -1.
6666
+ */
6667
+ keyBlockEnd(at) {
6668
+ const header = this.labelEnd(at + 11);
6669
+ if (header < 0) return -1;
6670
+ if (this.slot(BLOCK_FROM) <= header && header <= this.slot(BLOCK_END_START)) return this.slot(BLOCK_END);
6671
+ const text = this.text;
6672
+ this.memo[BLOCK_FROM] = header;
6673
+ this.memo[BLOCK_END_START] = text.length;
6674
+ this.memo[BLOCK_END] = text.length;
6675
+ for (let line = text.indexOf("-----END ", header); line >= 0; line = text.indexOf("-----END ", line + 1)) {
6676
+ const end = this.labelEnd(line + 9);
6677
+ if (end < 0) continue;
6678
+ this.memo[BLOCK_END_START] = line;
6679
+ this.memo[BLOCK_END] = end;
6680
+ break;
6681
+ }
6682
+ return this.slot(BLOCK_END);
6683
+ }
6684
+ /**
6685
+ * Whether `\b[a-z][a-z0-9+.-]{1,15}` ends at `at`; reads at most 17 characters back.
6686
+ * @param at - the offset after the scheme.
6687
+ * @returns whether a scheme ends there.
6688
+ */
6689
+ schemeBefore(at) {
6690
+ const text = this.text;
6691
+ for (let start = at - 1; start >= 0 && start >= at - 16; start--) {
6692
+ const code = text.charCodeAt(start);
6693
+ const bits = code < 128 ? this.classes[code] : 0;
6694
+ if ((bits & 64) === 0) return false;
6695
+ if ((bits & 128) !== 0 && at - start >= 2 && !this.isWordAt(start - 1)) return true;
6696
+ }
6697
+ return false;
6698
+ }
6699
+ /**
6700
+ * The password in `\b[a-z][a-z0-9+.-]{1,15}://[^\s/:@?#]{0,256}:[^\s/@?#]+@` for the `://` at
6701
+ * `at`; neither part crosses `?` or `#`, where the authority ends. Callers pass a `://` at or after
6702
+ * the query offset, or one whose user name reaches it, so the password never starts before it.
6703
+ * @param at - the offset of the `://` literal.
6704
+ * @returns the password end with its start in the memo, or -1.
6705
+ */
6706
+ addressPassword(at) {
6707
+ if (!this.schemeBefore(at)) return -1;
6708
+ const text = this.text;
6709
+ const userStart = at + 3;
6710
+ const userEnd = this.memoRunEnd(this.userRun, userStart, USER_SLOT);
6711
+ if (userEnd - userStart > 256 || text.charCodeAt(userEnd) !== 58) return -1;
6712
+ const start = userEnd + 1;
6713
+ const end = this.memoRunEnd(this.passwordRun, start, PASSWORD_SLOT);
6714
+ if (end === start || text.charCodeAt(end) !== 64) return -1;
6715
+ this.memo[CANDIDATE_START] = start;
6716
+ return end;
6717
+ }
6718
+ /**
6719
+ * The address password at or after `from` whose `://` starts before `from`, as `addressPassword`
6720
+ * returns it. The walk back over the user name runs only when a `:`, a password, and `@` follow.
6721
+ * @param from - the query offset.
6722
+ * @returns the password end with its start in the memo, or -1.
6723
+ */
6724
+ addressBefore(from) {
6725
+ const text = this.text;
6726
+ if (from < 3) return -1;
6727
+ if (text.startsWith("://", from - 1)) return this.addressPassword(from - 1);
6728
+ if (text.startsWith("://", from - 2)) return this.addressPassword(from - 2);
6729
+ let index = from - 1;
6730
+ const before = text.charCodeAt(index);
6731
+ let passwordStart;
6732
+ if (before === 58) {
6733
+ passwordStart = from;
6734
+ index--;
6735
+ } else if (this.isUserCode(before)) {
6736
+ const userEnd = this.memoRunEnd(this.userRun, from, USER_SLOT);
6737
+ if (text.charCodeAt(userEnd) !== 58) return -1;
6738
+ passwordStart = userEnd + 1;
6739
+ } else return text.startsWith("://", from - 3) ? this.addressPassword(from - 3) : -1;
6740
+ const passwordEnd = this.memoRunEnd(this.passwordRun, passwordStart, PASSWORD_SLOT);
6741
+ if (passwordEnd === passwordStart || text.charCodeAt(passwordEnd) !== 64) return -1;
6742
+ const lowest = Math.max(0, passwordStart - 258);
6743
+ while (index >= lowest && this.isUserCode(text.charCodeAt(index))) index--;
6744
+ return index >= 2 && text.startsWith("://", index - 2) ? this.addressPassword(index - 2) : -1;
6745
+ }
6746
+ /**
6747
+ * End of the prefixed credential whose literal starts at `at`, or -1.
6748
+ * @param literal - the literal's index.
6749
+ * @param at - the offset of the literal.
6750
+ * @returns the offset after the credential, or -1.
6751
+ */
6752
+ prefixedEnd(literal, at) {
6753
+ if (this.isWordAt(at - 1)) return -1;
6754
+ const text = this.text;
6755
+ const start = at + this.literalLength[literal];
6756
+ const check = this.literalCheck[literal];
6757
+ const min = this.literalMin[literal];
6758
+ if (check === 2) {
6759
+ const digit = this.nextDigit(start);
6760
+ if (digit - start > 255) return -1;
6761
+ const end = this.keyRunEnd(start);
6762
+ return end - start >= min && digit < end ? end : -1;
6763
+ }
6764
+ const slot = this.literalSlot[literal];
6765
+ const end = slot === 0 ? this.keyRunEnd(start) : this.memoRunEnd(this.literalPattern[literal], start, slot);
6766
+ const length = end - start;
6767
+ if (length < min) return -1;
6768
+ if (check === 0) return end;
6769
+ if (check === 3) return start + min;
6770
+ if (check === 1) return length <= this.literalMax[literal] && !this.isWordAt(end) ? end : -1;
6771
+ if (length > this.literalMax[literal] || !text.startsWith(".eyJ", end)) return -1;
6772
+ const payloadStart = end + 4;
6773
+ const payloadEnd = this.keyRunEnd(payloadStart);
6774
+ if (payloadEnd - payloadStart < min || text.charCodeAt(payloadEnd) !== 46) return -1;
6775
+ const signatureEnd = this.keyRunEnd(payloadEnd + 1);
6776
+ return signatureEnd - (payloadEnd + 1) >= min ? signatureEnd : -1;
6777
+ }
6778
+ };
6779
+ const scanner = new CredentialScanner(formatTables());
6780
+ /**
6781
+ * Every credential in `text`, in start order, each with the display form that
6782
+ * masks it.
6783
+ * @param text - the original user text.
6784
+ * @returns the masked ranges; empty when the text holds no recognized credential.
6785
+ */
6786
+ function scanSecrets(text) {
6787
+ const ranges = [];
6788
+ let from = 0;
6789
+ for (;;) {
6790
+ const match = scanner.match(text, from);
6791
+ if (match === void 0) return ranges;
6792
+ ranges.push(match);
6793
+ from = match.end;
6794
+ }
6795
+ }
5505
6796
  //#endregion
5506
6797
  //#region lib/types/user-text.js
5507
6798
  /** The wire form a session chip serializes to; label is the display text. */
@@ -5517,24 +6808,35 @@ const TRAILING_PUNCTUATION_RE = /[.,;:!?,。;:!?]+$/u;
5517
6808
  * (unsent queue rows pass none).
5518
6809
  * @param slashKind - the chip kind those tokens render as.
5519
6810
  * @param references - optional file and skill preview actions; session and command tokens stay labels.
6811
+ * @param secretLabels - reveal-control copy for credentials; absent in text that stays masked.
5520
6812
  * @returns inline nodes covering the whole text.
5521
6813
  */
5522
- function projectUserText(text, sessionLabels, slashNames = [], slashKind = "skill", references) {
5523
- const ranges = [];
6814
+ function projectUserText(text, sessionLabels, slashNames = [], slashKind = "skill", references, secretLabels) {
6815
+ const secrets = scanSecrets(text);
6816
+ const ranges = secrets.map((secret) => ({
6817
+ start: secret.start,
6818
+ end: secret.end,
6819
+ kind: "secret",
6820
+ masked: secret.masked
6821
+ }));
6822
+ const maskedOver = (start, end) => secrets.some((secret) => start < secret.end && secret.start < end);
5524
6823
  SESSION_WIRE_RE.lastIndex = 0;
5525
6824
  let wire;
5526
- while ((wire = SESSION_WIRE_RE.exec(text)) !== null) ranges.push({
5527
- start: wire.index,
5528
- end: wire.index + wire[0].length,
5529
- label: wire[0],
5530
- kind: "session",
5531
- display: wire[1]
5532
- });
6825
+ while ((wire = SESSION_WIRE_RE.exec(text)) !== null) {
6826
+ if (maskedOver(wire.index, wire.index + wire[0].length)) continue;
6827
+ ranges.push({
6828
+ start: wire.index,
6829
+ end: wire.index + wire[0].length,
6830
+ label: wire[0],
6831
+ kind: "session",
6832
+ display: wire[1]
6833
+ });
6834
+ }
5533
6835
  for (const rawLabel of [...new Set(sessionLabels)].sort((a, b) => b.length - a.length)) {
5534
6836
  const label = `@${rawLabel}`;
5535
6837
  let start = text.indexOf(label);
5536
6838
  while (start >= 0) {
5537
- ranges.push({
6839
+ if (!maskedOver(start, start + label.length)) ranges.push({
5538
6840
  start,
5539
6841
  end: start + label.length,
5540
6842
  label,
@@ -5551,6 +6853,7 @@ function projectUserText(text, sessionLabels, slashNames = [], slashKind = "skil
5551
6853
  const label = rawLabel.startsWith("@\"") ? rawLabel : rawLabel.replace(TRAILING_PUNCTUATION_RE, "");
5552
6854
  if (label.length <= 1) continue;
5553
6855
  if (label.startsWith("/") && !slashNames.includes(label.slice(1))) continue;
6856
+ if (maskedOver(tokenStart, tokenStart + label.length)) continue;
5554
6857
  ranges.push({
5555
6858
  start: tokenStart,
5556
6859
  end: tokenStart + label.length,
@@ -5564,27 +6867,37 @@ function projectUserText(text, sessionLabels, slashNames = [], slashKind = "skil
5564
6867
  let cursor = 0;
5565
6868
  const pushPlain = (from, to) => {
5566
6869
  parts.push(jsx("span", {
5567
- className: css$23.plainRun,
6870
+ className: css$27.plainRun,
5568
6871
  children: text.slice(from, to)
5569
6872
  }, `t${from}`));
5570
6873
  };
5571
6874
  for (const range of ranges) {
5572
6875
  if (range.start < cursor) continue;
5573
- const { start: tokenStart, end, label, kind } = range;
6876
+ const { start: tokenStart, end } = range;
5574
6877
  if (tokenStart > cursor) pushPlain(cursor, tokenStart);
6878
+ if (range.kind === "secret") {
6879
+ parts.push(jsx(SecretText, {
6880
+ masked: range.masked,
6881
+ raw: text.slice(tokenStart, end),
6882
+ labels: secretLabels
6883
+ }, `sec${tokenStart}`));
6884
+ cursor = end;
6885
+ continue;
6886
+ }
6887
+ const { label, kind } = range;
5575
6888
  const referenceKind = kind === "session" ? "session" : label.startsWith("@") ? label.replace(/^@"|"$/gu, "").endsWith("/") ? "folder" : "file" : void 0;
5576
6889
  const displayLabel = range.display ?? (referenceKind === void 0 ? label : referenceKind === "session" ? label.slice(1) : label.slice(1).replace(/^"|"$/gu, "").split(/[\\/]/u).filter(Boolean).at(-1) ?? label.slice(1));
5577
6890
  const contents = jsxs(Fragment, { children: [referenceKind !== void 0 && jsx(ReferenceIcon, {
5578
6891
  kind: referenceKind,
5579
6892
  size: 16,
5580
- className: css$23.refIcon
6893
+ className: css$27.refIcon
5581
6894
  }), displayLabel] });
5582
6895
  const open = references === void 0 ? void 0 : referenceKind === "file" ? () => {
5583
6896
  references.openFile(label.slice(1).replace(/^"|"$/gu, ""));
5584
6897
  } : referenceKind === void 0 && slashKind === "skill" ? () => {
5585
6898
  references.openSkill(label.slice(1));
5586
6899
  } : void 0;
5587
- const className = clsx(css$23.refChip, referenceKind === void 0 && css$23.slashChip);
6900
+ const className = clsx(css$27.refChip, referenceKind === void 0 && css$27.slashChip);
5588
6901
  parts.push(open === void 0 ? jsx("span", {
5589
6902
  className,
5590
6903
  "data-ref-chip": referenceKind ?? slashKind,
@@ -5604,7 +6917,7 @@ function projectUserText(text, sessionLabels, slashNames = [], slashKind = "skil
5604
6917
  cursor = end;
5605
6918
  }
5606
6919
  if (parts.length === 0) return jsx("span", {
5607
- className: css$23.plainRun,
6920
+ className: css$27.plainRun,
5608
6921
  children: text
5609
6922
  });
5610
6923
  if (cursor < text.length) pushPlain(cursor, text.length);
@@ -5663,22 +6976,22 @@ function Toast({ text, icon, tone, anchor, holdMs = HOLD_MS, onDone }) {
5663
6976
  };
5664
6977
  }, [anchor]);
5665
6978
  return createPortal(jsxs("div", {
5666
- className: css$24.toast,
6979
+ className: css$28.toast,
5667
6980
  role: "alert",
5668
6981
  style: {
5669
6982
  ...left === null ? {} : { left },
5670
6983
  "--qilin-toast-hold": `${String(holdMs)}ms`
5671
6984
  },
5672
6985
  children: [tone === "success" ? jsx("span", {
5673
- className: `${css$24.icon} ${css$24.success}`,
6986
+ className: `${css$28.icon} ${css$28.success}`,
5674
6987
  "aria-hidden": true,
5675
6988
  children: jsx(IconCheckOutline16, {})
5676
6989
  }) : icon !== void 0 && jsx("span", {
5677
- className: css$24.icon,
6990
+ className: css$28.icon,
5678
6991
  "aria-hidden": true,
5679
6992
  children: icon
5680
6993
  }), jsx("span", {
5681
- className: css$24.text,
6994
+ className: css$28.text,
5682
6995
  children: text
5683
6996
  })]
5684
6997
  }), document.body);
@@ -5972,7 +7285,7 @@ function JsonCopyAction({ store, target, persistent, labels, onCopy, onClose })
5972
7285
  const object = typeof target.value === "object" && target.value !== null;
5973
7286
  const copyTitle = state === "copied" ? labels.copied : state === "failed" ? labels.copyFailed : object ? labels.copyPrettyJson : labels.copyValue;
5974
7287
  return jsx("span", {
5975
- className: css$25.copySlot,
7288
+ className: css$29.copySlot,
5976
7289
  children: (persistent || snapshot !== void 0) && jsx(Menu, {
5977
7290
  open: snapshot?.menuOpen === true,
5978
7291
  compact: true,
@@ -5981,7 +7294,7 @@ function JsonCopyAction({ store, target, persistent, labels, onCopy, onClose })
5981
7294
  anchor: jsx("button", {
5982
7295
  ref: buttonRef,
5983
7296
  type: "button",
5984
- className: css$25.actionButton,
7297
+ className: css$29.actionButton,
5985
7298
  "data-json-copy-button": true,
5986
7299
  "data-state": state,
5987
7300
  "aria-label": copyTitle,
@@ -6020,35 +7333,35 @@ function bracketOf(value) {
6020
7333
  }
6021
7334
  function previewPrimitive(value) {
6022
7335
  if (value === null) return jsx("span", {
6023
- className: css$25.keywordValue,
7336
+ className: css$29.keywordValue,
6024
7337
  children: "null"
6025
7338
  });
6026
7339
  if (typeof value === "string") return jsx("span", {
6027
- className: css$25.stringValue,
7340
+ className: css$29.stringValue,
6028
7341
  children: JSON.stringify(value)
6029
7342
  });
6030
7343
  if (typeof value === "number") return jsx("span", {
6031
- className: css$25.numberValue,
7344
+ className: css$29.numberValue,
6032
7345
  children: String(value)
6033
7346
  });
6034
7347
  if (typeof value === "boolean") return jsx("span", {
6035
- className: css$25.keywordValue,
7348
+ className: css$29.keywordValue,
6036
7349
  children: String(value)
6037
7350
  });
6038
7351
  if (typeof value === "bigint") return jsx("span", {
6039
- className: css$25.otherValue,
7352
+ className: css$29.otherValue,
6040
7353
  children: value.toString()
6041
7354
  });
6042
7355
  if (typeof value === "undefined") return jsx("span", {
6043
- className: css$25.otherValue,
7356
+ className: css$29.otherValue,
6044
7357
  children: "undefined"
6045
7358
  });
6046
7359
  if (typeof value === "symbol") return jsx("span", {
6047
- className: css$25.otherValue,
7360
+ className: css$29.otherValue,
6048
7361
  children: value.description ?? "Symbol"
6049
7362
  });
6050
7363
  if (typeof value === "function") return jsx("span", {
6051
- className: css$25.otherValue,
7364
+ className: css$29.otherValue,
6052
7365
  children: value.name || "Function"
6053
7366
  });
6054
7367
  return null;
@@ -6062,71 +7375,71 @@ function previewValue(value, depth) {
6062
7375
  const [open, close] = bracketOf(value);
6063
7376
  return jsxs(Fragment, { children: [
6064
7377
  jsx("span", {
6065
- className: css$25.punctuation,
7378
+ className: css$29.punctuation,
6066
7379
  children: open
6067
7380
  }),
6068
7381
  depth >= PREVIEW_DEPTH_LIMIT ? jsx("span", {
6069
- className: css$25.previewEllipsis,
7382
+ className: css$29.previewEllipsis,
6070
7383
  children: "…"
6071
7384
  }) : visible.map(([key, item], index) => jsxs("span", { children: [
6072
7385
  index > 0 && jsx("span", {
6073
- className: css$25.punctuation,
7386
+ className: css$29.punctuation,
6074
7387
  children: ", "
6075
7388
  }),
6076
7389
  !array && jsxs(Fragment, { children: [jsx("span", {
6077
- className: css$25.previewProperty,
7390
+ className: css$29.previewProperty,
6078
7391
  children: key
6079
7392
  }), jsx("span", {
6080
- className: css$25.punctuation,
7393
+ className: css$29.punctuation,
6081
7394
  children: ": "
6082
7395
  })] }),
6083
7396
  previewValue(item, depth + 1)
6084
7397
  ] }, key)),
6085
7398
  depth < PREVIEW_DEPTH_LIMIT && entries.length > limit && jsx("span", {
6086
- className: css$25.previewEllipsis,
7399
+ className: css$29.previewEllipsis,
6087
7400
  children: ", …"
6088
7401
  }),
6089
7402
  jsx("span", {
6090
- className: css$25.punctuation,
7403
+ className: css$29.punctuation,
6091
7404
  children: close
6092
7405
  })
6093
7406
  ] });
6094
7407
  }
6095
7408
  function primitiveValue(value) {
6096
7409
  if (value === null) return jsx("span", {
6097
- className: css$25.keywordValue,
7410
+ className: css$29.keywordValue,
6098
7411
  children: "null"
6099
7412
  });
6100
7413
  if (typeof value === "string") return jsx("span", {
6101
- className: css$25.stringValue,
7414
+ className: css$29.stringValue,
6102
7415
  children: JSON.stringify(value)
6103
7416
  });
6104
7417
  if (typeof value === "boolean") return jsx("span", {
6105
- className: css$25.keywordValue,
7418
+ className: css$29.keywordValue,
6106
7419
  children: String(value)
6107
7420
  });
6108
7421
  if (typeof value === "number") return jsx("span", {
6109
- className: css$25.numberValue,
7422
+ className: css$29.numberValue,
6110
7423
  children: String(value)
6111
7424
  });
6112
7425
  if (typeof value === "bigint") return jsx("span", {
6113
- className: css$25.numberValue,
7426
+ className: css$29.numberValue,
6114
7427
  children: `${value.toString()}n`
6115
7428
  });
6116
7429
  if (value instanceof Date) return jsx("span", {
6117
- className: css$25.otherValue,
7430
+ className: css$29.otherValue,
6118
7431
  children: value.toISOString()
6119
7432
  });
6120
7433
  if (typeof value === "function") return jsxs("span", {
6121
- className: css$25.otherValue,
7434
+ className: css$29.otherValue,
6122
7435
  children: ["function() ", "{ }"]
6123
7436
  });
6124
7437
  if (typeof value === "undefined") return jsx("span", {
6125
- className: css$25.otherValue,
7438
+ className: css$29.otherValue,
6126
7439
  children: "undefined"
6127
7440
  });
6128
7441
  return jsx("span", {
6129
- className: css$25.otherValue,
7442
+ className: css$29.otherValue,
6130
7443
  children: value.toString()
6131
7444
  });
6132
7445
  }
@@ -6154,7 +7467,7 @@ function moveFocus(button, direction) {
6154
7467
  function NodeField({ field, expandable, onToggle }) {
6155
7468
  if (field === void 0) return null;
6156
7469
  return jsxs("span", {
6157
- className: clsx(css$25.label, expandable && css$25.clickableLabel),
7470
+ className: clsx(css$29.label, expandable && css$29.clickableLabel),
6158
7471
  onClick: expandable ? onToggle : void 0,
6159
7472
  children: [fieldText(field), ":"]
6160
7473
  });
@@ -6191,7 +7504,7 @@ function JsonString({ collapsedStringLines, stringWrapping, field, labels, lastE
6191
7504
  if (!expanded) return;
6192
7505
  const raw = rawRef.current;
6193
7506
  const clips = [];
6194
- const tree = raw.closest(`.${css$25.root}`);
7507
+ const tree = raw.closest(`.${css$29.root}`);
6195
7508
  for (let parent = tree.parentElement; parent !== null; parent = parent.parentElement) if (/auto|scroll|hidden|clip/.test(getComputedStyle(parent).overflowY)) clips.push(parent);
6196
7509
  const measure = () => {
6197
7510
  let top = 0;
@@ -6220,33 +7533,33 @@ function JsonString({ collapsedStringLines, stringWrapping, field, labels, lastE
6220
7533
  if (expanded) {
6221
7534
  const fieldId = `${contentsId}-field`;
6222
7535
  return jsxs("div", {
6223
- className: css$25.stringField,
7536
+ className: css$29.stringField,
6224
7537
  "data-expanded": true,
6225
7538
  children: [
6226
7539
  field !== void 0 && jsxs("span", {
6227
7540
  id: fieldId,
6228
- className: css$25.label,
7541
+ className: css$29.label,
6229
7542
  children: [fieldText(field), ":"]
6230
7543
  }),
6231
7544
  jsx("pre", {
6232
7545
  ref: rawRef,
6233
7546
  id: contentsId,
6234
- className: css$25.stringRaw,
7547
+ className: css$29.stringRaw,
6235
7548
  "data-wrap": wrapped,
6236
7549
  tabIndex: 0,
6237
7550
  "aria-labelledby": field === void 0 ? void 0 : fieldId,
6238
7551
  children: value
6239
7552
  }),
6240
7553
  !lastElement && jsx("span", {
6241
- className: css$25.punctuation,
7554
+ className: css$29.punctuation,
6242
7555
  children: ","
6243
7556
  }),
6244
7557
  jsxs("div", {
6245
- className: css$25.stringActions,
7558
+ className: css$29.stringActions,
6246
7559
  children: [
6247
7560
  stringWrapping !== void 0 && jsx("button", {
6248
7561
  type: "button",
6249
- className: css$25.actionButton,
7562
+ className: css$29.actionButton,
6250
7563
  "aria-label": stringWrapping.label,
6251
7564
  title: stringWrapping.label,
6252
7565
  "aria-pressed": wrapped,
@@ -6260,7 +7573,7 @@ function JsonString({ collapsedStringLines, stringWrapping, field, labels, lastE
6260
7573
  }),
6261
7574
  jsx("button", {
6262
7575
  type: "button",
6263
- className: css$25.actionButton,
7576
+ className: css$29.actionButton,
6264
7577
  "aria-label": labels.collapseNode,
6265
7578
  title: labels.collapseNode,
6266
7579
  "aria-expanded": true,
@@ -6286,18 +7599,18 @@ function JsonString({ collapsedStringLines, stringWrapping, field, labels, lastE
6286
7599
  });
6287
7600
  }
6288
7601
  return jsxs(Fragment, { children: [renderCopy?.(), jsx("span", {
6289
- className: css$25.stringField,
7602
+ className: css$29.stringField,
6290
7603
  "data-expanded": expanded,
6291
7604
  children: jsxs("span", {
6292
7605
  ref: contentRef,
6293
7606
  id: contentsId,
6294
- className: css$25.stringText,
7607
+ className: css$29.stringText,
6295
7608
  children: [
6296
7609
  truncated && jsx("span", {
6297
- className: css$25.stringToggleSlot,
7610
+ className: css$29.stringToggleSlot,
6298
7611
  children: jsxs("button", {
6299
7612
  type: "button",
6300
- className: css$25.stringToggle,
7613
+ className: css$29.stringToggle,
6301
7614
  "aria-label": labels.expandNode,
6302
7615
  "aria-expanded": false,
6303
7616
  "aria-controls": contentsId,
@@ -6312,12 +7625,12 @@ function JsonString({ collapsedStringLines, stringWrapping, field, labels, lastE
6312
7625
  })
6313
7626
  }),
6314
7627
  field !== void 0 && jsxs("span", {
6315
- className: css$25.label,
7628
+ className: css$29.label,
6316
7629
  children: [fieldText(field), ":"]
6317
7630
  }),
6318
7631
  primitiveValue(value),
6319
7632
  !lastElement && jsx("span", {
6320
- className: css$25.punctuation,
7633
+ className: css$29.punctuation,
6321
7634
  children: ","
6322
7635
  })
6323
7636
  ]
@@ -6348,7 +7661,7 @@ function JsonTreeNode({ collapsedStringLines, stringWrapping, field, initialExpa
6348
7661
  }
6349
7662
  };
6350
7663
  const row = (children, ariaExpanded) => jsxs("div", {
6351
- className: css$25.row,
7664
+ className: css$29.row,
6352
7665
  role: "treeitem",
6353
7666
  "aria-expanded": ariaExpanded,
6354
7667
  onMouseOver: (event) => {
@@ -6383,7 +7696,7 @@ function JsonTreeNode({ collapsedStringLines, stringWrapping, field, initialExpa
6383
7696
  }),
6384
7697
  primitiveValue(value),
6385
7698
  !lastElement && jsx("span", {
6386
- className: css$25.punctuation,
7699
+ className: css$29.punctuation,
6387
7700
  children: ","
6388
7701
  })
6389
7702
  ] }));
@@ -6395,22 +7708,22 @@ function JsonTreeNode({ collapsedStringLines, stringWrapping, field, initialExpa
6395
7708
  onToggle: toggle
6396
7709
  }),
6397
7710
  jsx("span", {
6398
- className: css$25.punctuation,
7711
+ className: css$29.punctuation,
6399
7712
  children: open
6400
7713
  }),
6401
7714
  jsx("span", {
6402
- className: css$25.punctuation,
7715
+ className: css$29.punctuation,
6403
7716
  children: close
6404
7717
  }),
6405
7718
  !lastElement && jsx("span", {
6406
- className: css$25.punctuation,
7719
+ className: css$29.punctuation,
6407
7720
  children: ","
6408
7721
  })
6409
7722
  ] }));
6410
7723
  return row(jsxs(Fragment, { children: [
6411
7724
  jsx("span", {
6412
7725
  ref: expanderRef,
6413
- className: clsx(css$25.expander, expanded ? css$25.collapseIcon : css$25.expandIcon),
7726
+ className: clsx(css$29.expander, expanded ? css$29.collapseIcon : css$29.expandIcon),
6414
7727
  "data-json-expander": true,
6415
7728
  role: "button",
6416
7729
  "aria-label": expanded ? labels.collapseNode : labels.expandNode,
@@ -6424,7 +7737,7 @@ function JsonTreeNode({ collapsedStringLines, stringWrapping, field, initialExpa
6424
7737
  onKeyDown: onExpanderKeyDown
6425
7738
  }),
6426
7739
  jsxs("span", {
6427
- className: css$25.summary,
7740
+ className: css$29.summary,
6428
7741
  children: [
6429
7742
  jsx(NodeField, {
6430
7743
  field,
@@ -6432,11 +7745,11 @@ function JsonTreeNode({ collapsedStringLines, stringWrapping, field, initialExpa
6432
7745
  onToggle: toggle
6433
7746
  }),
6434
7747
  jsx("span", {
6435
- className: css$25.preview,
7748
+ className: css$29.preview,
6436
7749
  children: previewValue(value, 0)
6437
7750
  }),
6438
7751
  !lastElement && jsx("span", {
6439
- className: css$25.punctuation,
7752
+ className: css$29.punctuation,
6440
7753
  children: ","
6441
7754
  })
6442
7755
  ]
@@ -6444,7 +7757,7 @@ function JsonTreeNode({ collapsedStringLines, stringWrapping, field, initialExpa
6444
7757
  expanded && jsx("ul", {
6445
7758
  id: contentsId,
6446
7759
  role: "group",
6447
- className: css$25.children,
7760
+ className: css$29.children,
6448
7761
  children: entries.map(([key, item], index) => jsx(JsonTreeNode, {
6449
7762
  collapsedStringLines,
6450
7763
  stringWrapping,
@@ -6576,17 +7889,17 @@ function JsonTree({ data, label, className, collapsedStringLines = 3, stringWrap
6576
7889
  onClose: clearCopyTarget
6577
7890
  }) : void 0;
6578
7891
  return jsx("div", {
6579
- className: clsx(css$25.root, className),
7892
+ className: clsx(css$29.root, className),
6580
7893
  style: { "--json-tree-collapsed-lines": collapsedStringLines },
6581
7894
  onMouseOver: handleRootMouseOver,
6582
7895
  onMouseLeave: () => {
6583
7896
  if (!copyStore.get()?.menuOpen) clearCopyTarget();
6584
7897
  },
6585
7898
  children: expandTopLevel ? jsxs("div", {
6586
- className: css$25.expandedTopLevel,
7899
+ className: css$29.expandedTopLevel,
6587
7900
  children: [
6588
7901
  jsxs("div", {
6589
- className: clsx(css$25.row, css$25.topLevelBracket),
7902
+ className: clsx(css$29.row, css$29.topLevelBracket),
6590
7903
  "data-json-root-row": true,
6591
7904
  onMouseOver: (event) => {
6592
7905
  event.stopPropagation();
@@ -6599,13 +7912,13 @@ function JsonTree({ data, label, className, collapsedStringLines = 3, stringWrap
6599
7912
  path: [],
6600
7913
  value: data
6601
7914
  }), jsx("span", {
6602
- className: css$25.punctuation,
7915
+ className: css$29.punctuation,
6603
7916
  children: rootOpen
6604
7917
  })]
6605
7918
  }),
6606
7919
  jsx("div", {
6607
7920
  "aria-label": label,
6608
- className: clsx(css$25.container, css$25.expandedTopLevelContainer),
7921
+ className: clsx(css$29.container, css$29.expandedTopLevelContainer),
6609
7922
  role: "tree",
6610
7923
  children: rootEntries.map(([key, value], index) => jsx(JsonTreeNode, {
6611
7924
  collapsedStringLines,
@@ -6623,16 +7936,16 @@ function JsonTree({ data, label, className, collapsedStringLines = 3, stringWrap
6623
7936
  }, key))
6624
7937
  }),
6625
7938
  jsx("div", {
6626
- className: clsx(css$25.row, css$25.topLevelBracket),
7939
+ className: clsx(css$29.row, css$29.topLevelBracket),
6627
7940
  children: jsx("span", {
6628
- className: css$25.punctuation,
7941
+ className: css$29.punctuation,
6629
7942
  children: rootClose
6630
7943
  })
6631
7944
  })
6632
7945
  ]
6633
7946
  }) : jsx("div", {
6634
7947
  "aria-label": label,
6635
- className: css$25.container,
7948
+ className: css$29.container,
6636
7949
  role: "tree",
6637
7950
  children: jsx(JsonTreeNode, {
6638
7951
  collapsedStringLines,
@@ -7148,7 +8461,7 @@ function renderLine$1(line) {
7148
8461
  * @param props - see {@link TerminalBlockProps}.
7149
8462
  * @returns the terminal block element.
7150
8463
  */
7151
- function TerminalBlock({ command, cwd, home, output, exitCode, signal, running = false, maxLines = 16, className, labels }) {
8464
+ function TerminalBlock({ command, cwd, home, output, exitCode, signal, running = false, background = false, maxLines = 16, className, labels }) {
7152
8465
  const copy = labels;
7153
8466
  const text = output ?? "";
7154
8467
  const lines = useMemo(() => {
@@ -7161,40 +8474,41 @@ function TerminalBlock({ command, cwd, home, output, exitCode, signal, running =
7161
8474
  const onToggle = useCallback(() => {
7162
8475
  setExpanded((value) => !value);
7163
8476
  }, []);
7164
- const status = statusText(exitCode, signal, copy);
8477
+ const status = background ? void 0 : statusText(exitCode, signal, copy);
7165
8478
  const state = runState(running, exitCode, signal, copy);
8479
+ const showState = !background || running;
7166
8480
  const commandLines = useMemo(() => {
7167
8481
  return (command.endsWith("\n") ? command.slice(0, -1) : command).split("\n");
7168
8482
  }, [command]);
7169
8483
  const empty = lines.every((line) => line.every((span) => span.text.trim() === ""));
7170
8484
  const { hidden, capped, headLines, tailLines } = headTailCap(lines.length, maxLines, expanded);
7171
- const body = !running || !empty;
8485
+ const body = !background && (!running || !empty);
7172
8486
  return jsxs("div", {
7173
- className: clsx(css$26.block, className),
8487
+ className: clsx(css$30.block, className),
7174
8488
  "data-terminal": "",
7175
8489
  "data-running": running ? "" : void 0,
7176
8490
  "data-body": body ? "" : void 0,
7177
8491
  children: [jsxs("div", {
7178
- className: css$26.header,
8492
+ className: css$30.header,
7179
8493
  children: [
7180
8494
  jsxs("div", {
7181
- className: css$26.prompt,
7182
- children: [jsx("span", {
7183
- className: css$26.runStateLabel,
8495
+ className: css$30.prompt,
8496
+ children: [showState && jsx("span", {
8497
+ className: css$30.runStateLabel,
7184
8498
  children: state.label
7185
8499
  }), commandLines.map((line, index) => jsxs("div", {
7186
- className: css$26.promptLine,
8500
+ className: css$30.promptLine,
7187
8501
  children: [
7188
- index === 0 && jsx(StateDot, {
8502
+ index === 0 && showState && jsx(StateDot, {
7189
8503
  state: state.state,
7190
- className: css$26.runState
8504
+ className: css$30.runState
7191
8505
  }),
7192
8506
  jsx("span", {
7193
- className: css$26.cwd,
8507
+ className: css$30.cwd,
7194
8508
  children: index > 0 || cwd === void 0 ? "$" : promptLabel(cwd, home)
7195
8509
  }),
7196
8510
  jsx(CommandText, {
7197
- className: css$26.command,
8511
+ className: css$30.command,
7198
8512
  text: line,
7199
8513
  label: copy.commandLine(index + 1)
7200
8514
  })
@@ -7202,36 +8516,36 @@ function TerminalBlock({ command, cwd, home, output, exitCode, signal, running =
7202
8516
  }, index))]
7203
8517
  }),
7204
8518
  status !== void 0 && jsx(Pill, {
7205
- className: css$26.status,
8519
+ className: css$30.status,
7206
8520
  children: status
7207
8521
  }),
7208
- !running && !empty && jsx("button", {
8522
+ !background && !running && !empty && jsx("button", {
7209
8523
  type: "button",
7210
- className: css$26.copyButton,
8524
+ className: css$30.copyButton,
7211
8525
  onClick: onCopy,
7212
8526
  children: copied ? copy.copied : copy.copy
7213
8527
  })
7214
8528
  ]
7215
8529
  }), body && (empty ? jsx("div", {
7216
- className: css$26.empty,
8530
+ className: css$30.empty,
7217
8531
  children: copy.noOutput
7218
8532
  }) : jsxs("div", {
7219
- className: css$26.output,
8533
+ className: css$30.output,
7220
8534
  children: [
7221
8535
  (capped ? lines.slice(0, headLines) : lines).map((line, index) => jsx("div", {
7222
- className: css$26.line,
8536
+ className: css$30.line,
7223
8537
  children: renderLine$1(line)
7224
8538
  }, index)),
7225
8539
  hidden > 0 && jsx("button", {
7226
8540
  type: "button",
7227
- className: css$26.expand,
8541
+ className: css$30.expand,
7228
8542
  "aria-expanded": expanded,
7229
8543
  "aria-label": expanded ? copy.collapseAria : copy.expandAria(hidden),
7230
8544
  onClick: onToggle,
7231
8545
  children: expanded ? copy.collapse : copy.expand(hidden)
7232
8546
  }),
7233
8547
  capped && lines.slice(lines.length - tailLines).map((line, index) => jsx("div", {
7234
- className: css$26.line,
8548
+ className: css$30.line,
7235
8549
  children: renderLine$1(line)
7236
8550
  }, index))
7237
8551
  ]
@@ -7819,51 +9133,51 @@ function ReadBlock({ label, labels, lines, totalLines, lang, maxLines = 16, clas
7819
9133
  const tailLines = maxLines - headLines;
7820
9134
  const windowed = lines.length < totalLines;
7821
9135
  const rows = (slice) => slice.map(([line, spans]) => jsxs("div", {
7822
- className: css$27.line,
9136
+ className: css$31.line,
7823
9137
  children: [jsx("span", {
7824
- className: css$27.gutter,
9138
+ className: css$31.gutter,
7825
9139
  "aria-hidden": true,
7826
9140
  children: line.number
7827
9141
  }), jsx("span", {
7828
- className: css$27.content,
9142
+ className: css$31.content,
7829
9143
  children: spans === void 0 ? line.text : renderSpans(spans)
7830
9144
  })]
7831
9145
  }, line.number));
7832
9146
  const paired = lines.map((line, index) => [line, highlighted?.[index]]);
7833
9147
  return jsxs("div", {
7834
9148
  ref: rootRef,
7835
- className: clsx(css$27.block, className),
9149
+ className: clsx(css$31.block, className),
7836
9150
  "data-read": "",
7837
9151
  children: [jsxs("div", {
7838
- className: css$27.banner,
9152
+ className: css$31.banner,
7839
9153
  children: [jsx("div", {
7840
- className: css$27.label,
9154
+ className: css$31.label,
7841
9155
  children: label ?? ""
7842
9156
  }), jsxs("div", {
7843
- className: css$27.action,
9157
+ className: css$31.action,
7844
9158
  children: [
7845
9159
  windowed && jsx("span", {
7846
- className: css$27.count,
9160
+ className: css$31.count,
7847
9161
  children: labels.window(lines.length, totalLines)
7848
9162
  }),
7849
9163
  jsx("span", {
7850
- className: css$27.lang,
9164
+ className: css$31.lang,
7851
9165
  children: lang ?? ""
7852
9166
  }),
7853
9167
  lines.length > 0 && jsx("button", {
7854
9168
  type: "button",
7855
- className: css$27.copyButton,
9169
+ className: css$31.copyButton,
7856
9170
  onClick: onCopy,
7857
9171
  children: copied ? labels.copied : labels.copy
7858
9172
  })
7859
9173
  ]
7860
9174
  })]
7861
9175
  }), jsxs("div", {
7862
- className: css$27.body,
9176
+ className: css$31.body,
7863
9177
  children: [
7864
9178
  rows(capped ? paired.slice(0, headLines) : paired),
7865
9179
  hidden > 0 && jsx(FoldToggle, {
7866
- className: css$27.expand,
9180
+ className: css$31.expand,
7867
9181
  expanded,
7868
9182
  hidden,
7869
9183
  labels,
@@ -7885,11 +9199,11 @@ function assertNever(value) {
7885
9199
  }
7886
9200
  /** The dim class per row kind (path/gap chrome vs the diff's own +/- colors). */
7887
9201
  const ROW_CLASS = {
7888
- path: css$28.path,
7889
- del: css$28.del,
7890
- add: css$28.add,
7891
- context: css$28.context,
7892
- gap: css$28.gap
9202
+ path: css$32.path,
9203
+ del: css$32.del,
9204
+ add: css$32.add,
9205
+ context: css$32.context,
9206
+ gap: css$32.gap
7893
9207
  };
7894
9208
  /** Bound synchronous edit-graph search; one replacement consumes two edits. */
7895
9209
  const MAX_DIFF_EDIT_LENGTH = 256;
@@ -8027,37 +9341,37 @@ function DiffBlock({ diffs, labels, maxLines = 16, className }) {
8027
9341
  const head = capped ? rows.slice(0, headLines) : rows;
8028
9342
  const tail = capped ? rows.slice(rows.length - tailLines) : [];
8029
9343
  return jsxs("div", {
8030
- className: clsx(css$28.block, className),
9344
+ className: clsx(css$32.block, className),
8031
9345
  "data-diff": "",
8032
9346
  children: [
8033
9347
  jsx("button", {
8034
9348
  type: "button",
8035
- className: css$28.copyButton,
9349
+ className: css$32.copyButton,
8036
9350
  onClick: onCopy,
8037
9351
  children: copied ? labels.copied : labels.copy
8038
9352
  }),
8039
9353
  jsxs("div", {
8040
- className: css$28.body,
9354
+ className: css$32.body,
8041
9355
  children: [
8042
9356
  head.map((row, index) => jsx("div", {
8043
- className: clsx(css$28.line, ROW_CLASS[row.kind]),
9357
+ className: clsx(css$32.line, ROW_CLASS[row.kind]),
8044
9358
  children: row.text
8045
9359
  }, index)),
8046
9360
  hidden > 0 && jsx(FoldToggle, {
8047
- className: css$28.expand,
9361
+ className: css$32.expand,
8048
9362
  expanded,
8049
9363
  hidden,
8050
9364
  labels,
8051
9365
  onToggle
8052
9366
  }),
8053
9367
  tail.map((row, index) => jsx("div", {
8054
- className: clsx(css$28.line, ROW_CLASS[row.kind]),
9368
+ className: clsx(css$32.line, ROW_CLASS[row.kind]),
8055
9369
  children: row.text
8056
9370
  }, index))
8057
9371
  ]
8058
9372
  }),
8059
9373
  jsxs("div", {
8060
- className: css$28.footer,
9374
+ className: css$32.footer,
8061
9375
  children: [
8062
9376
  "└ +",
8063
9377
  added,
@@ -8193,56 +9507,56 @@ function SearchBlock(props) {
8193
9507
  const tail = tailHeader === void 0 ? naturalTail : naturalTail.slice(1);
8194
9508
  const renderRow = (row) => {
8195
9509
  if (row.type === "path") return jsx("div", {
8196
- className: css$29.line,
9510
+ className: css$33.line,
8197
9511
  children: row.path
8198
9512
  });
8199
9513
  if (row.type === "match") return jsxs("div", {
8200
- className: css$29.line,
9514
+ className: css$33.line,
8201
9515
  children: [jsxs("span", {
8202
- className: css$29.lineNumber,
9516
+ className: css$33.lineNumber,
8203
9517
  children: [row.lineNumber, ": "]
8204
9518
  }), row.line]
8205
9519
  });
8206
9520
  return jsxs("button", {
8207
9521
  type: "button",
8208
- className: css$29.fileHeader,
9522
+ className: css$33.fileHeader,
8209
9523
  "aria-expanded": !row.collapsed,
8210
9524
  onClick: () => {
8211
9525
  toggleFile(row.index);
8212
9526
  },
8213
9527
  children: [jsx("span", {
8214
- className: css$29.filePath,
9528
+ className: css$33.filePath,
8215
9529
  children: row.path
8216
9530
  }), jsx("span", {
8217
- className: css$29.fileCount,
9531
+ className: css$33.fileCount,
8218
9532
  children: row.count
8219
9533
  })]
8220
9534
  });
8221
9535
  };
8222
9536
  return jsxs("div", {
8223
- className: clsx(css$29.block, className),
9537
+ className: clsx(css$33.block, className),
8224
9538
  "data-search": props.kind,
8225
9539
  children: [jsxs("div", {
8226
- className: css$29.header,
9540
+ className: css$33.header,
8227
9541
  children: [jsx("span", {
8228
- className: css$29.summary,
9542
+ className: css$33.summary,
8229
9543
  children: summaryText(props, shown, truncated, total)
8230
9544
  }), !empty && jsx("button", {
8231
9545
  type: "button",
8232
- className: css$29.copyButton,
9546
+ className: css$33.copyButton,
8233
9547
  onClick: onCopy,
8234
9548
  children: copied ? props.labels.copied : props.labels.copy
8235
9549
  })]
8236
9550
  }), empty ? jsx("div", {
8237
- className: css$29.empty,
9551
+ className: css$33.empty,
8238
9552
  children: props.labels.noResults
8239
9553
  }) : jsxs("div", {
8240
- className: css$29.body,
9554
+ className: css$33.body,
8241
9555
  children: [
8242
9556
  head.map((row) => jsx("div", { children: renderRow(row) }, rowKey(row))),
8243
9557
  hidden > 0 && jsx("button", {
8244
9558
  type: "button",
8245
- className: css$29.expand,
9559
+ className: css$33.expand,
8246
9560
  "aria-expanded": expanded,
8247
9561
  "aria-label": expanded ? props.labels.collapseAria : props.labels.expandAria(hidden),
8248
9562
  onClick: onToggle,
@@ -9070,7 +10384,7 @@ function CodeBlock({ code, lang, streaming, className, contentRef, lineNumbers =
9070
10384
  });
9071
10385
  }, [copied, trimmed]);
9072
10386
  const body = streamedBody !== void 0 ? streamedBody : html === void 0 ? jsx("pre", {
9073
- className: css$30.plain,
10387
+ className: css$34.plain,
9074
10388
  children: jsx("code", { children: sourceLines === void 0 ? trimmed : sourceLines.map((line, index) => jsxs(Fragment$1, { children: [index > 0 && "\n", jsx("span", {
9075
10389
  className: "line",
9076
10390
  children: line
@@ -9078,22 +10392,22 @@ function CodeBlock({ code, lang, streaming, className, contentRef, lineNumbers =
9078
10392
  }) : jsx("div", { dangerouslySetInnerHTML: { __html: html } });
9079
10393
  return jsxs("div", {
9080
10394
  ref: rootRef,
9081
- className: clsx(css$30.block, "md-code-block", lineNumbers && css$30.numbered, className),
10395
+ className: clsx(css$34.block, "md-code-block", lineNumbers && css$34.numbered, className),
9082
10396
  "data-line-numbers": lineNumbers || void 0,
9083
10397
  style: sourceLines === void 0 ? void 0 : { "--dsl-code-block-line-number-width": `${Math.max(2, String(sourceLines.length).length)}ch` },
9084
10398
  children: [showHeader && jsx("div", {
9085
- className: css$30.bannerWrap,
10399
+ className: css$34.bannerWrap,
9086
10400
  children: jsxs("div", {
9087
- className: css$30.banner,
10401
+ className: css$34.banner,
9088
10402
  "data-code-block-banner": true,
9089
10403
  children: [jsx("div", {
9090
- className: css$30.infostring,
10404
+ className: css$34.infostring,
9091
10405
  children: lang ?? ""
9092
10406
  }), jsx("div", {
9093
- className: css$30.action,
10407
+ className: css$34.action,
9094
10408
  children: jsx("button", {
9095
10409
  type: "button",
9096
- className: css$30.copyButton,
10410
+ className: css$34.copyButton,
9097
10411
  onClick: onCopy,
9098
10412
  children: copied ? copiedLabel : copyLabel
9099
10413
  })
@@ -9101,7 +10415,7 @@ function CodeBlock({ code, lang, streaming, className, contentRef, lineNumbers =
9101
10415
  })
9102
10416
  }), jsx("div", {
9103
10417
  ref: contentRef,
9104
- className: css$30.content,
10418
+ className: css$34.content,
9105
10419
  "data-code-block-content": true,
9106
10420
  children: body
9107
10421
  })]
@@ -9252,15 +10566,15 @@ function MermaidDiagram({ code, copyLabel, copiedLabel, diagramLabel, enlargedLa
9252
10566
  };
9253
10567
  }, [code, domId]);
9254
10568
  if (state.status === "loading") return jsx("div", {
9255
- className: css$31.stage,
10569
+ className: css$35.stage,
9256
10570
  "data-mermaid-loading": true,
9257
10571
  "aria-hidden": "true"
9258
10572
  });
9259
10573
  if (state.status === "error") return jsxs("div", {
9260
- className: css$31.error,
10574
+ className: css$35.error,
9261
10575
  role: "alert",
9262
10576
  children: [jsx("span", {
9263
- className: css$31.errorLine,
10577
+ className: css$35.errorLine,
9264
10578
  children: state.message
9265
10579
  }), jsx(CodeBlock, {
9266
10580
  code: `${code}\n`,
@@ -9269,7 +10583,7 @@ function MermaidDiagram({ code, copyLabel, copiedLabel, diagramLabel, enlargedLa
9269
10583
  })]
9270
10584
  });
9271
10585
  const stage = jsx("div", {
9272
- className: css$31.stage,
10586
+ className: css$35.stage,
9273
10587
  "data-mermaid-diagram": true,
9274
10588
  dangerouslySetInnerHTML: { __html: state.svg },
9275
10589
  onClick: () => {
@@ -9284,13 +10598,13 @@ function MermaidDiagram({ code, copyLabel, copiedLabel, diagramLabel, enlargedLa
9284
10598
  });
9285
10599
  if (zoom === null) return stage;
9286
10600
  return jsxs(Fragment, { children: [stage, createPortal(jsx("div", {
9287
- className: css$31.zoomOverlay,
10601
+ className: css$35.zoomOverlay,
9288
10602
  onClick: () => {
9289
10603
  setZoom(null);
9290
10604
  },
9291
10605
  role: "presentation",
9292
10606
  children: jsx("div", {
9293
- className: css$31.zoomStage,
10607
+ className: css$35.zoomStage,
9294
10608
  dangerouslySetInnerHTML: { __html: zoom },
9295
10609
  onClick: (event) => {
9296
10610
  event.stopPropagation();
@@ -9483,31 +10797,34 @@ function ImageLightbox({ src, alt, labels, onClose }) {
9483
10797
  restoreRef.current?.focus();
9484
10798
  };
9485
10799
  }, [onClose]);
9486
- return createPortal(jsxs("div", {
9487
- className: css$32.backdrop,
10800
+ return createPortal(jsx("div", {
10801
+ className: css$36.backdrop,
9488
10802
  role: "dialog",
9489
10803
  "aria-modal": "true",
9490
10804
  "aria-label": labels.dialog,
9491
- children: [
9492
- jsx("div", {
9493
- className: css$32.mask,
9494
- "aria-hidden": "true",
9495
- onMouseDown: onClose
9496
- }),
9497
- jsx("img", {
9498
- className: css$32.image,
9499
- src,
9500
- alt
9501
- }),
9502
- jsx("button", {
9503
- ref: closeRef,
9504
- type: "button",
9505
- className: css$32.close,
9506
- "aria-label": labels.close,
9507
- onClick: onClose,
9508
- children: jsx(IconCloseOutline16, { size: 16 })
9509
- })
9510
- ]
10805
+ children: jsxs("div", {
10806
+ className: css$36.stage,
10807
+ children: [
10808
+ jsx("div", {
10809
+ className: css$36.mask,
10810
+ "aria-hidden": "true",
10811
+ onMouseDown: onClose
10812
+ }),
10813
+ jsx("img", {
10814
+ className: css$36.image,
10815
+ src,
10816
+ alt
10817
+ }),
10818
+ jsx("button", {
10819
+ ref: closeRef,
10820
+ type: "button",
10821
+ className: css$36.close,
10822
+ "aria-label": labels.close,
10823
+ onClick: onClose,
10824
+ children: jsx(IconCloseOutline16, { size: 16 })
10825
+ })
10826
+ ]
10827
+ })
9511
10828
  }), document.body);
9512
10829
  }
9513
10830
  //#endregion
@@ -9529,14 +10846,14 @@ function ImagePreview({ src, alt, loadingLabel, failedLabel }) {
9529
10846
  function Preview({ src, alt, loadingLabel, failedLabel }) {
9530
10847
  const [state, setState] = useState("loading");
9531
10848
  return jsxs("span", {
9532
- className: css$33.frame,
10849
+ className: css$37.frame,
9533
10850
  children: [state !== "failed" && jsx("img", {
9534
10851
  src,
9535
10852
  alt,
9536
10853
  loading: "lazy",
9537
10854
  decoding: "async",
9538
10855
  referrerPolicy: "no-referrer",
9539
- className: css$33.image,
10856
+ className: css$37.image,
9540
10857
  "data-ready": state === "ready" || void 0,
9541
10858
  onLoad: () => {
9542
10859
  setState("ready");
@@ -9545,7 +10862,7 @@ function Preview({ src, alt, loadingLabel, failedLabel }) {
9545
10862
  setState("failed");
9546
10863
  }
9547
10864
  }), state !== "ready" && jsxs("span", {
9548
- className: css$33.status,
10865
+ className: css$37.status,
9549
10866
  role: "status",
9550
10867
  children: [state === "loading" && jsx(IconLoadingOutline16, { size: 16 }), jsx("span", { children: state === "loading" ? loadingLabel : failedLabel })]
9551
10868
  })]
@@ -10316,7 +11633,7 @@ function SafeLink({ url, label, className }) {
10316
11633
  children: [jsx(LinkIcon, {
10317
11634
  kind: "url",
10318
11635
  href,
10319
- className: css$34.linkIcon
11636
+ className: css$38.linkIcon
10320
11637
  }), label]
10321
11638
  });
10322
11639
  }
@@ -10331,20 +11648,20 @@ function SafeLink({ url, label, className }) {
10331
11648
  */
10332
11649
  function SourceItem({ source, ordinal }) {
10333
11650
  return jsxs("li", {
10334
- className: css$34.source,
11651
+ className: css$38.source,
10335
11652
  value: ordinal,
10336
11653
  children: [
10337
11654
  jsx(SafeLink, {
10338
11655
  url: source.url,
10339
11656
  label: linkLabel(source.url, source.title),
10340
- className: css$34.sourceLink
11657
+ className: css$38.sourceLink
10341
11658
  }),
10342
11659
  source.snippet !== void 0 && source.snippet !== "" && jsx("div", {
10343
- className: css$34.snippet,
11660
+ className: css$38.snippet,
10344
11661
  children: source.snippet
10345
11662
  }),
10346
11663
  source.publishedAt !== void 0 && source.publishedAt !== "" && jsx("div", {
10347
- className: css$34.published,
11664
+ className: css$38.published,
10348
11665
  children: source.publishedAt
10349
11666
  })
10350
11667
  ]
@@ -10359,28 +11676,28 @@ function SourceItem({ source, ordinal }) {
10359
11676
  function WebSearchBlock({ answer, sources, truncated, labels, className }) {
10360
11677
  const empty = (answer === void 0 || answer === "") && sources.length === 0;
10361
11678
  return jsxs("div", {
10362
- className: clsx(css$34.block, className),
11679
+ className: clsx(css$38.block, className),
10363
11680
  "data-web": "search",
10364
11681
  children: [
10365
11682
  answer !== void 0 && answer !== "" && jsx("div", {
10366
- className: css$34.answer,
11683
+ className: css$38.answer,
10367
11684
  children: jsx(MarkdownText, {
10368
11685
  text: answer,
10369
11686
  labels: labels.markdown
10370
11687
  })
10371
11688
  }),
10372
11689
  empty ? jsx("div", {
10373
- className: css$34.empty,
11690
+ className: css$38.empty,
10374
11691
  children: labels.noResults
10375
11692
  }) : jsx("ol", {
10376
- className: css$34.sources,
11693
+ className: css$38.sources,
10377
11694
  children: sources.map((source, index) => jsx(SourceItem, {
10378
11695
  source,
10379
11696
  ordinal: index + 1
10380
11697
  }, index))
10381
11698
  }),
10382
11699
  truncated && jsx("div", {
10383
- className: css$34.truncated,
11700
+ className: css$38.truncated,
10384
11701
  children: labels.sourcesTruncated
10385
11702
  })
10386
11703
  ]
@@ -10393,23 +11710,23 @@ function WebSearchBlock({ answer, sources, truncated, labels, className }) {
10393
11710
  */
10394
11711
  function WebFetchBlock({ url, statusCode, truncated, labels, className }) {
10395
11712
  return jsxs("div", {
10396
- className: clsx(css$34.block, css$34.fetch, className),
11713
+ className: clsx(css$38.block, css$38.fetch, className),
10397
11714
  "data-web": "fetch",
10398
11715
  children: [jsx(SafeLink, {
10399
11716
  url,
10400
11717
  label: url,
10401
- className: css$34.fetchUrl
11718
+ className: css$38.fetchUrl
10402
11719
  }), jsxs("div", {
10403
- className: css$34.fetchMeta,
11720
+ className: css$38.fetchMeta,
10404
11721
  children: [jsxs("span", {
10405
- className: css$34.status,
11722
+ className: css$38.status,
10406
11723
  children: [
10407
11724
  labels.http,
10408
11725
  " ",
10409
11726
  statusCode
10410
11727
  ]
10411
11728
  }), truncated && jsx("span", {
10412
- className: css$34.truncated,
11729
+ className: css$38.truncated,
10413
11730
  children: labels.contentTruncated
10414
11731
  })]
10415
11732
  })]
@@ -10443,10 +11760,10 @@ function JsonBlock({ label, payload, defaultOpen = false, truncatedLabel }) {
10443
11760
  truncatedLabel
10444
11761
  ]);
10445
11762
  return jsxs("div", {
10446
- className: css$35.root,
11763
+ className: css$39.root,
10447
11764
  children: [jsxs("button", {
10448
11765
  type: "button",
10449
- className: css$35.toggle,
11766
+ className: css$39.toggle,
10450
11767
  onClick: () => {
10451
11768
  setOpen((v) => !v);
10452
11769
  },
@@ -10456,7 +11773,7 @@ function JsonBlock({ label, payload, defaultOpen = false, truncatedLabel }) {
10456
11773
  label
10457
11774
  ]
10458
11775
  }), open && jsx("pre", {
10459
- className: css$35.body,
11776
+ className: css$39.body,
10460
11777
  children: body
10461
11778
  })]
10462
11779
  });
@@ -10546,17 +11863,17 @@ function MenuGroup({ label, children }) {
10546
11863
  role: "group",
10547
11864
  "aria-labelledby": headingId,
10548
11865
  "data-menu-group": "",
10549
- className: css$36.group,
11866
+ className: css$40.group,
10550
11867
  children: [
10551
11868
  jsx("span", {
10552
11869
  "aria-hidden": "true",
10553
11870
  "data-menu-group-start": "",
10554
- className: css$36.start
11871
+ className: css$40.start
10555
11872
  }),
10556
11873
  jsx("div", {
10557
11874
  id: headingId,
10558
11875
  "data-menu-group-heading": "",
10559
- className: css$36.heading,
11876
+ className: css$40.heading,
10560
11877
  children: label
10561
11878
  }),
10562
11879
  children
@@ -10652,47 +11969,6 @@ function observeStickyMenuGroups(viewport) {
10652
11969
  };
10653
11970
  }
10654
11971
  //#endregion
10655
- //#region lib/types/MenuSurface.js
10656
- /** Shared menu material and the macOS backing that lets Chromium blur transparent windows. */
10657
- /**
10658
- * Paint a menu and, on macOS, an opaque backing behind the page content within its bounds.
10659
- * CSS anchors keep each backing aligned during placement, resizing, and nested-menu movement.
10660
- * @param props - Div content and placement, and compact geometry.
10661
- * @param ref - The visible menu div, excluding the non-interactive backing.
10662
- * @returns Menu content plus a backing portal removed with the menu.
10663
- */
10664
- const MenuSurface = forwardRef(function MenuSurface({ compact = false, className, style, children, ...props }, ref) {
10665
- const id = useId();
10666
- const backingRef = useRef(null);
10667
- useLayoutEffect(() => {
10668
- document.body.appendChild(backingRef.current);
10669
- }, []);
10670
- const anchorStyle = { "--dsh-menu-anchor": `--dsh-menu-${id.replaceAll(":", "")}` };
10671
- return jsxs(Fragment, { children: [jsxs("div", {
10672
- ...props,
10673
- ref,
10674
- "data-menu-material": "translucent",
10675
- className: clsx(css$37.surface, compact && css$37.compact, className),
10676
- style: {
10677
- ...style,
10678
- ...anchorStyle
10679
- },
10680
- children: [jsx("div", {
10681
- "aria-hidden": "true",
10682
- className: css$37.material
10683
- }), children]
10684
- }), createPortal(jsx("div", {
10685
- ref: backingRef,
10686
- "aria-hidden": "true",
10687
- "data-menu-backing": "",
10688
- className: clsx(css$37.backing, compact && css$37.compact),
10689
- style: {
10690
- ...anchorStyle,
10691
- visibility: style?.visibility
10692
- }
10693
- }), document.body)] });
10694
- });
10695
- //#endregion
10696
- export { Button, Checkbox, CodeBlock, CommandText, ConnectionIndicator, DEFAULT_DIFF_MAX_LINES, DEFAULT_READ_MAX_LINES, DEFAULT_SEARCH_MAX_LINES, DEFAULT_TERMINAL_MAX_LINES, DiffBlock, DisclosureRow, FileTypeIcon, HoverCard, IconAgentPresetOutline16, IconAlarmClockOutline16, IconApiOutline14, IconArchiveOutline20, IconBranchOutline16, IconBranchOutline16 as IconBranchOutlineRegular, IconBrowseOutline16, IconCheckOutline14, IconCheckOutline16, IconCheckOutline16 as IconCheckOutlineRegular, IconChecklistOutline14, IconChecklistOutline14 as IconChecklistOutlineRegular, IconChevronDownOutline14, IconChevronDownOutline14 as IconChevronDownOutlineMedium, IconChevronLeftOutline14, IconChevronRightOutline14, IconChevronUpOutline14, IconChevronUpOutline14 as IconChevronUpOutlineMedium, IconClockOutline16, IconCloseFill14, IconCloseOutline16, IconCloseOutline16 as IconCloseOutlineRegular, IconCodeOutline16, IconCompactOutline16, IconContextInjectionOutline16, IconCopyOutline16, IconCopyOutline16 as IconCopyOutlineRegular, 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, IconLogoutOutline16, IconMicrophoneOutline16, IconNewChatOutline16, IconPanelLeftOutline16, IconPaperPlaneOutline14, IconPaperclipOutline16, IconPauseOutline16, IconPersonalizationOutline16, IconPinFillRegular, IconPinOutlineRegular, IconPlanOutline14, IconPlayOutline16, IconPluginPinwheelOutline16, IconPlusOutline16, IconPlusOutline16 as IconPlusOutlineRegular, IconProjectAddOutline16, IconQuestionOutline14, IconQueueOutline14, IconRefreshOutline14, IconRefreshOutline16, IconRightUpOutline14, IconRightUpOutline16, IconSearchOutline16, IconSearchOutline16 as IconSearchOutlineRegular, IconSendOutline14, IconSendOutline16, IconSendOutline16 as IconSendOutlineRegular, IconSettingsOutline14, IconSettingsOutline14 as IconSettingsOutlineMedium, IconSettingsOutline16, IconShareOutline16, IconShieldOutline16, IconSkillOutline16, IconSparkle16, IconStopFill16, IconTerminalOutline16, IconThinkOutline14, IconThinkOutline16, IconTrashOutline16, IconTreeCorner8x10, IconTriangleRightFill14, IconUserOutline16, IconUserOutline16 as IconUserOutlineRegular, IconUsersOutlineRegular, IconWarningOutline16, IconWorkspaceTreeOutlineRegular, IconWrapLinesOutline16, ImageLightbox, Input, JsonBlock, JsonTree, LinkIcon, MarkdownDelegateProvider, MarkdownText, Menu, MenuGroup, MenuItemButton, MenuSurface, Modal, OnboardingSurface, PathLabel, Pill, QilinSeal, ReadBlock, ReferenceIcon, RiskConfirmation, SHIELD_OUTLINE_PATH, SHIELD_OUTLINE_STROKE, SearchBlock, SegmentedControl, SettingsForm, SettingsFormModel, SettingsSecretField, SettingsValueField, ShortcutKeys, StateDot, Switch, Tag, TerminalBlock, TextShimmer, Toast, Tooltip, WebBlock, classifyFileType, classifyLinkPath, closeTopModal, diffTotals, extractMarkdownPlainText, fileExtension, fileSizeRoundedText, fileSizeText, focusWithoutRing, isBehindModal, isDarwinDesktop, modalSelector, observeComposition, observeStickyMenuGroups, overlayTopMargin, projectUserText, rankByName, relativeTime, settingsNumberField, settingsTextField, useAnchoredMaxHeight, useAnchoredPosition, useCopyFeedback, useDismissOnOutsidePointer, useModalLayer, watchDarwinDesktop, writeClipboard };
11972
+ export { Button, Checkbox, CodeBlock, CommandText, ConnectionIndicator, DEFAULT_DIFF_MAX_LINES, DEFAULT_READ_MAX_LINES, DEFAULT_SEARCH_MAX_LINES, DEFAULT_TERMINAL_MAX_LINES, DiffBlock, DisclosureRow, FileTypeIcon, HoverCard, IconAgentPresetOutline16, IconAlarmClockOutline16, IconApiOutline14, IconArchiveOutline20, IconBranchOutline16, IconBranchOutline16 as IconBranchOutlineRegular, IconBrowseOutline16, IconCheckCircleFillRegular, IconCheckOutline14, IconCheckOutline16, IconCheckOutline16 as IconCheckOutlineRegular, IconChecklistOutline14, IconChecklistOutline14 as IconChecklistOutlineRegular, IconChevronDownOutline14, IconChevronDownOutline14 as IconChevronDownOutlineMedium, IconChevronDownOutline14 as IconChevronDownOutlineRegular, IconChevronLeftOutline14, IconChevronLeftOutline14 as IconChevronLeftOutlineMedium, IconChevronRightOutline14, IconChevronRightOutline14 as IconChevronRightOutlineRegular, IconChevronUpOutline14, IconChevronUpOutline14 as IconChevronUpOutlineMedium, IconClockOutline16, IconCloseFill14, IconCloseOutline16, IconCloseOutline16 as IconCloseOutlineMedium, IconCloseOutline16 as IconCloseOutlineRegular, IconCodeOutline16, IconCompactOutline16, IconContextInjectionOutline16, IconCopyOutline16, IconCopyOutline16 as IconCopyOutlineRegular, IconCordisPluginOutline14, IconDarkOutline16, IconDataOutline16, IconDatabaseOutline16, IconDislikeFill16, IconDislikeOutline16, IconDownloadOutline16, IconDownloadOutline16 as IconDownloadOutlineRegular, IconEditOutline16, IconEllipsisOutline16, IconEnhanceOutline16, IconFolderClose16, IconFolderOpen16, IconFolderOpenOutline16, IconFollowsystemOutline16, IconFullscreenOutline16, IconGaugeOutline16, IconGlobeOutline14, IconGoalOutline16, IconInfoOutline14, IconInfoOutline14 as IconInfoOutlineRegular, IconInspectOutline12, IconLightOutline16, IconLikeFill16, IconLikeOutline16, IconLinkOutline14, IconLinkOutline16, IconListPenOutline16, IconLoadingOutline16, IconLogoutOutline16, IconMicrophoneOutline16, IconNewChatOutline16, IconPanelLeftOutline16, IconPaperPlaneOutline14, IconPaperclipOutline16, IconPauseOutline16, IconPersonalizationOutline16, IconPinFillRegular, IconPinOutlineRegular, IconPlanOutline14, IconPlayOutline16, IconPluginPinwheelOutline16, IconPluginPinwheelOutline16 as IconPluginPinwheelOutlineRegular, IconPlusOutline16, IconPlusOutline16 as IconPlusOutlineRegular, IconProjectAddOutline16, IconQuestionOutline14, IconQueueOutline14, IconRefreshOutline14, IconRefreshOutline14 as IconRefreshOutlineRegular, IconRefreshOutline16, IconRightUpOutline14, IconRightUpOutline16, IconSearchOutline16, IconSearchOutline16 as IconSearchOutlineRegular, IconSendOutline14, IconSendOutline16, IconSendOutline16 as IconSendOutlineRegular, IconSettingsOutline14, IconSettingsOutline14 as IconSettingsOutlineMedium, IconSettingsOutline16, IconShareOutline16, IconShieldOutline16, IconSkillOutline16, IconSlidersTwoOutlineMedium, IconSlidersTwoOutlineRegular, IconSparkle16, IconStopFill16, IconTerminalOutline16, IconThinkOutline14, IconThinkOutline16, IconTrashOutline16, IconTrashOutline16 as IconTrashOutlineRegular, IconTreeCorner8x10, IconTriangleRightFill14, IconUserOutline16, IconUserOutline16 as IconUserOutlineRegular, IconUsersOutlineRegular, IconWarningOutline16, IconWarningOutline16 as IconWarningOutlineRegular, IconWorkspaceTreeOutlineRegular, IconWrapLinesOutline16, ImageLightbox, InlineEditor, Input, JsonBlock, JsonTree, LinkIcon, MarkdownDelegateProvider, MarkdownText, Menu, MenuGroup, MenuItemButton, MenuSurface, Modal, OnboardingSurface, PathLabel, Pill, PluginArtworkDefault, PluginArtworkLoop, PluginArtworkSearch, PluginArtworkSubagent, PluginArtworkTerminal, QilinSeal, ReadBlock, ReferenceIcon, RiskConfirmation, SHIELD_OUTLINE_PATH, SHIELD_OUTLINE_STROKE, SearchBlock, SegmentedControl, SegmentedTabs, SettingsForm, SettingsFormModel, SettingsSecretField, SettingsValueField, ShortcutKeys, StateDot, Switch, Tag, TerminalBlock, TextShimmer, Toast, Tooltip, WebBlock, classifyFileType, classifyLinkPath, closeTopModal, diffTotals, extractMarkdownPlainText, fileExtension, fileSizeRoundedText, fileSizeText, focusWithoutRing, isBehindModal, isDarwinDesktop, modalSelector, observeComposition, observeStickyMenuGroups, overlayTopMargin, pointerModality, projectUserText, rankByName, relativeTime, settingsNumberField, settingsTextField, useAnchoredMaxHeight, useAnchoredPosition, useCopyFeedback, useDismissOnOutsidePointer, useModalLayer, watchDarwinDesktop, writeClipboard };
10697
11973
 
10698
11974
  //# sourceMappingURL=index.js.map