@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/README.i18n.yaml +10 -10
- package/README.md +8 -5
- package/README.zh.md +8 -5
- package/lib/ImageLightbox.module.css +14 -5
- package/lib/InlineEditor.module.css +23 -0
- package/lib/MenuSurface.module.css +2 -2
- package/lib/SecretText.module.css +52 -0
- package/lib/SegmentedTabs.module.css +55 -0
- package/lib/index.js +1675 -399
- package/lib/types/InlineEditor.d.ts +23 -0
- package/lib/types/Menu.d.ts +18 -8
- package/lib/types/SecretText.d.ts +25 -0
- package/lib/types/SegmentedTabs.d.ts +26 -0
- package/lib/types/TerminalBlock.d.ts +7 -1
- package/lib/types/Tooltip.d.ts +11 -2
- package/lib/types/credential-formats.d.ts +63 -0
- package/lib/types/credential-masks.d.ts +60 -0
- package/lib/types/credential-scanner.d.ts +146 -0
- package/lib/types/format-tables.d.ts +29 -0
- package/lib/types/icons/index.d.ts +7 -1
- package/lib/types/index.d.ts +6 -1
- package/lib/types/plugin-artwork.d.ts +17 -0
- package/lib/types/useAnchoredPosition.d.ts +3 -1
- package/lib/types/user-text.d.ts +13 -2
- package/package.json +5 -5
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 "./
|
|
16
|
-
import css$11 from "./
|
|
17
|
-
import css$12 from "./
|
|
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$
|
|
20
|
-
import css$
|
|
21
|
-
import css$
|
|
22
|
-
import css$
|
|
23
|
-
import css$
|
|
24
|
-
import css$
|
|
25
|
-
import css$
|
|
26
|
-
import css$
|
|
27
|
-
import 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$
|
|
31
|
-
import 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$
|
|
34
|
-
import 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$
|
|
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$
|
|
46
|
+
import css$31 from "./ReadBlock.module.css";
|
|
43
47
|
import { structuredPatch } from "diff";
|
|
44
|
-
import css$
|
|
45
|
-
import 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$
|
|
58
|
-
import 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$
|
|
61
|
-
import 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$
|
|
64
|
-
import css$
|
|
65
|
-
import 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$
|
|
3098
|
+
className: clsx(css$11.switch, className),
|
|
2734
3099
|
onClick: () => {
|
|
2735
3100
|
onChange(!checked);
|
|
2736
3101
|
},
|
|
2737
|
-
children: jsx("span", { className: css$
|
|
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$
|
|
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$
|
|
3142
|
+
className: clsx(css$13.wrap, className),
|
|
2778
3143
|
children: [icon != null && jsx("span", {
|
|
2779
|
-
className: css$
|
|
3144
|
+
className: css$13.icon,
|
|
2780
3145
|
children: icon
|
|
2781
3146
|
}), jsx("input", {
|
|
2782
3147
|
ref,
|
|
2783
|
-
className: css$
|
|
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$
|
|
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$
|
|
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$
|
|
3497
|
+
className: css$17.itemWrap,
|
|
3024
3498
|
children: [separatorBefore && jsx("div", {
|
|
3025
|
-
className: css$
|
|
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$
|
|
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$
|
|
3510
|
+
className: css$17.itemIcon,
|
|
3037
3511
|
children: icon
|
|
3038
3512
|
}),
|
|
3039
3513
|
jsx("span", {
|
|
3040
|
-
className: css$
|
|
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$
|
|
3519
|
+
className: css$17.shortcut,
|
|
3046
3520
|
children: jsx(ShortcutKeys, {
|
|
3047
3521
|
keys: shortcut.keys,
|
|
3048
|
-
className: css$
|
|
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
|
|
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 (
|
|
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
|
|
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(
|
|
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$
|
|
3809
|
+
className: css$17.separator,
|
|
3321
3810
|
role: "separator"
|
|
3322
3811
|
}, entry.id);
|
|
3323
3812
|
if (isLabel(entry)) return jsx("div", {
|
|
3324
|
-
className: css$
|
|
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$
|
|
3333
|
-
onMouseEnter: () => {
|
|
3334
|
-
setOpenSubmenuId(
|
|
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$
|
|
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(
|
|
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$
|
|
3848
|
+
className: css$17.itemIcon,
|
|
3361
3849
|
children: entry.icon
|
|
3362
3850
|
}),
|
|
3363
3851
|
jsx("span", {
|
|
3364
|
-
className: css$
|
|
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$
|
|
3857
|
+
className: css$17.shortcut,
|
|
3370
3858
|
children: jsx(ShortcutKeys, {
|
|
3371
3859
|
keys: entry.shortcut.keys,
|
|
3372
|
-
className: css$
|
|
3860
|
+
className: css$17.shortcutKeys
|
|
3373
3861
|
})
|
|
3374
3862
|
}),
|
|
3375
|
-
selected && selection === "check" && jsx(IconCheckOutline16, { className: css$
|
|
3863
|
+
selected && selection === "check" && jsx(IconCheckOutline16, { className: css$17.check })
|
|
3376
3864
|
]
|
|
3377
|
-
}), subOpen && entry.submenu !== void 0 && jsx(
|
|
3378
|
-
|
|
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$
|
|
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$
|
|
3881
|
+
className: css$17.itemIcon,
|
|
3393
3882
|
children: sub.icon
|
|
3394
3883
|
}),
|
|
3395
3884
|
jsx("span", {
|
|
3396
|
-
className: css$
|
|
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$
|
|
3890
|
+
className: css$17.shortcut,
|
|
3402
3891
|
children: jsx(ShortcutKeys, {
|
|
3403
3892
|
keys: sub.shortcut.keys,
|
|
3404
|
-
className: css$
|
|
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
|
|
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$
|
|
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
|
-
|
|
3421
|
-
|
|
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$
|
|
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$
|
|
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
|
|
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
|
-
}, [
|
|
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
|
|
4308
|
+
const showAfterDelay = (delay) => {
|
|
3809
4309
|
cancelShow();
|
|
3810
|
-
if (
|
|
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
|
-
},
|
|
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
|
-
|
|
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$
|
|
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
|
-
|
|
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
|
-
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
4690
|
+
className: css$20.root,
|
|
4150
4691
|
role: "presentation",
|
|
4151
4692
|
onKeyDownCapture,
|
|
4152
4693
|
children: [jsx("div", {
|
|
4153
|
-
className: css$
|
|
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$
|
|
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$
|
|
4707
|
+
className: clsx(css$20.content, contentClassName),
|
|
4167
4708
|
children: [
|
|
4168
4709
|
jsxs("div", {
|
|
4169
|
-
className: css$
|
|
4710
|
+
className: css$20.header,
|
|
4170
4711
|
children: [jsx("h2", {
|
|
4171
|
-
className: css$
|
|
4712
|
+
className: css$20.title,
|
|
4172
4713
|
children: title
|
|
4173
4714
|
}), jsx("button", {
|
|
4174
4715
|
type: "button",
|
|
4175
|
-
className: css$
|
|
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$
|
|
4723
|
+
className: css$20.description,
|
|
4183
4724
|
children: description
|
|
4184
4725
|
}),
|
|
4185
4726
|
children !== void 0 && jsx("div", {
|
|
4186
|
-
className: css$
|
|
4727
|
+
className: css$20.body,
|
|
4187
4728
|
children
|
|
4188
4729
|
})
|
|
4189
4730
|
]
|
|
4190
4731
|
}), footer !== void 0 && jsx("div", {
|
|
4191
|
-
className: css$
|
|
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$
|
|
4756
|
+
className: css$21.onboardingOverlay,
|
|
4216
4757
|
role: "presentation",
|
|
4217
4758
|
children: [jsx("div", {
|
|
4218
|
-
className: css$
|
|
4759
|
+
className: css$21.onboardingMask,
|
|
4219
4760
|
"aria-hidden": "true"
|
|
4220
4761
|
}), jsx("div", {
|
|
4221
|
-
className: css$
|
|
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$
|
|
4243
|
-
contentClassName: css$
|
|
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$
|
|
4787
|
+
className: css$22.modalAction,
|
|
4247
4788
|
onClick: onCancel,
|
|
4248
4789
|
children: cancelLabel
|
|
4249
4790
|
}), jsx(Button, {
|
|
4250
4791
|
variant: "primary",
|
|
4251
|
-
className: css$
|
|
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$
|
|
4798
|
+
className: css$22.warning,
|
|
4258
4799
|
children: [jsx(IconWarningOutline16, {
|
|
4259
4800
|
size: 18,
|
|
4260
|
-
className: css$
|
|
4801
|
+
className: css$22.warningIcon
|
|
4261
4802
|
}), jsx("p", { children: description })]
|
|
4262
4803
|
}), jsxs("label", {
|
|
4263
|
-
className: css$
|
|
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$
|
|
4852
|
+
const leavingClass = leaving ? ` ${css$23.leaving}` : "";
|
|
4312
4853
|
if (rendered === "recovered") return jsxs("div", {
|
|
4313
|
-
className: `${css$
|
|
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$
|
|
4858
|
+
className: css$23.icon,
|
|
4318
4859
|
"aria-hidden": "true",
|
|
4319
4860
|
children: jsx(IconCheckOutline16, { size: 14 })
|
|
4320
4861
|
}), jsx("span", {
|
|
4321
|
-
className: css$
|
|
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$
|
|
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$
|
|
4874
|
+
className: css$23.icon,
|
|
4334
4875
|
"aria-hidden": "true",
|
|
4335
4876
|
children: connecting ? jsx(IconLoadingOutline16, {
|
|
4336
4877
|
size: 14,
|
|
4337
|
-
className: css$
|
|
4878
|
+
className: css$23.spinner
|
|
4338
4879
|
}) : jsx(IconRefreshOutline14, { size: 14 })
|
|
4339
4880
|
}), jsx("span", {
|
|
4340
|
-
className: css$
|
|
4881
|
+
className: css$23.label,
|
|
4341
4882
|
children: connecting ? jsxs(Fragment, { children: [connectingLabel, jsxs("span", {
|
|
4342
|
-
className: css$
|
|
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$
|
|
4888
|
+
className: css$23.secondDot,
|
|
4348
4889
|
children: "."
|
|
4349
4890
|
}),
|
|
4350
4891
|
jsx("span", {
|
|
4351
|
-
className: css$
|
|
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$
|
|
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$
|
|
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$
|
|
6035
|
+
className: css$25.text,
|
|
5495
6036
|
children: [directory !== "" && jsx("span", {
|
|
5496
|
-
className: css$
|
|
6037
|
+
className: css$25.directory,
|
|
5497
6038
|
children: directory
|
|
5498
6039
|
}), jsx("span", {
|
|
5499
|
-
className: css$
|
|
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
|
|
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)
|
|
5527
|
-
|
|
5528
|
-
|
|
5529
|
-
|
|
5530
|
-
|
|
5531
|
-
|
|
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$
|
|
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
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
6990
|
+
className: css$28.icon,
|
|
5678
6991
|
"aria-hidden": true,
|
|
5679
6992
|
children: icon
|
|
5680
6993
|
}), jsx("span", {
|
|
5681
|
-
className: css$
|
|
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$
|
|
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$
|
|
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$
|
|
7336
|
+
className: css$29.keywordValue,
|
|
6024
7337
|
children: "null"
|
|
6025
7338
|
});
|
|
6026
7339
|
if (typeof value === "string") return jsx("span", {
|
|
6027
|
-
className: css$
|
|
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$
|
|
7344
|
+
className: css$29.numberValue,
|
|
6032
7345
|
children: String(value)
|
|
6033
7346
|
});
|
|
6034
7347
|
if (typeof value === "boolean") return jsx("span", {
|
|
6035
|
-
className: css$
|
|
7348
|
+
className: css$29.keywordValue,
|
|
6036
7349
|
children: String(value)
|
|
6037
7350
|
});
|
|
6038
7351
|
if (typeof value === "bigint") return jsx("span", {
|
|
6039
|
-
className: css$
|
|
7352
|
+
className: css$29.otherValue,
|
|
6040
7353
|
children: value.toString()
|
|
6041
7354
|
});
|
|
6042
7355
|
if (typeof value === "undefined") return jsx("span", {
|
|
6043
|
-
className: css$
|
|
7356
|
+
className: css$29.otherValue,
|
|
6044
7357
|
children: "undefined"
|
|
6045
7358
|
});
|
|
6046
7359
|
if (typeof value === "symbol") return jsx("span", {
|
|
6047
|
-
className: css$
|
|
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$
|
|
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$
|
|
7378
|
+
className: css$29.punctuation,
|
|
6066
7379
|
children: open
|
|
6067
7380
|
}),
|
|
6068
7381
|
depth >= PREVIEW_DEPTH_LIMIT ? jsx("span", {
|
|
6069
|
-
className: css$
|
|
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$
|
|
7386
|
+
className: css$29.punctuation,
|
|
6074
7387
|
children: ", "
|
|
6075
7388
|
}),
|
|
6076
7389
|
!array && jsxs(Fragment, { children: [jsx("span", {
|
|
6077
|
-
className: css$
|
|
7390
|
+
className: css$29.previewProperty,
|
|
6078
7391
|
children: key
|
|
6079
7392
|
}), jsx("span", {
|
|
6080
|
-
className: css$
|
|
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$
|
|
7399
|
+
className: css$29.previewEllipsis,
|
|
6087
7400
|
children: ", …"
|
|
6088
7401
|
}),
|
|
6089
7402
|
jsx("span", {
|
|
6090
|
-
className: css$
|
|
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$
|
|
7410
|
+
className: css$29.keywordValue,
|
|
6098
7411
|
children: "null"
|
|
6099
7412
|
});
|
|
6100
7413
|
if (typeof value === "string") return jsx("span", {
|
|
6101
|
-
className: css$
|
|
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$
|
|
7418
|
+
className: css$29.keywordValue,
|
|
6106
7419
|
children: String(value)
|
|
6107
7420
|
});
|
|
6108
7421
|
if (typeof value === "number") return jsx("span", {
|
|
6109
|
-
className: css$
|
|
7422
|
+
className: css$29.numberValue,
|
|
6110
7423
|
children: String(value)
|
|
6111
7424
|
});
|
|
6112
7425
|
if (typeof value === "bigint") return jsx("span", {
|
|
6113
|
-
className: css$
|
|
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$
|
|
7430
|
+
className: css$29.otherValue,
|
|
6118
7431
|
children: value.toISOString()
|
|
6119
7432
|
});
|
|
6120
7433
|
if (typeof value === "function") return jsxs("span", {
|
|
6121
|
-
className: css$
|
|
7434
|
+
className: css$29.otherValue,
|
|
6122
7435
|
children: ["function() ", "{ }"]
|
|
6123
7436
|
});
|
|
6124
7437
|
if (typeof value === "undefined") return jsx("span", {
|
|
6125
|
-
className: css$
|
|
7438
|
+
className: css$29.otherValue,
|
|
6126
7439
|
children: "undefined"
|
|
6127
7440
|
});
|
|
6128
7441
|
return jsx("span", {
|
|
6129
|
-
className: css$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
7554
|
+
className: css$29.punctuation,
|
|
6242
7555
|
children: ","
|
|
6243
7556
|
}),
|
|
6244
7557
|
jsxs("div", {
|
|
6245
|
-
className: css$
|
|
7558
|
+
className: css$29.stringActions,
|
|
6246
7559
|
children: [
|
|
6247
7560
|
stringWrapping !== void 0 && jsx("button", {
|
|
6248
7561
|
type: "button",
|
|
6249
|
-
className: css$
|
|
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$
|
|
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$
|
|
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$
|
|
7607
|
+
className: css$29.stringText,
|
|
6295
7608
|
children: [
|
|
6296
7609
|
truncated && jsx("span", {
|
|
6297
|
-
className: css$
|
|
7610
|
+
className: css$29.stringToggleSlot,
|
|
6298
7611
|
children: jsxs("button", {
|
|
6299
7612
|
type: "button",
|
|
6300
|
-
className: css$
|
|
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$
|
|
7628
|
+
className: css$29.label,
|
|
6316
7629
|
children: [fieldText(field), ":"]
|
|
6317
7630
|
}),
|
|
6318
7631
|
primitiveValue(value),
|
|
6319
7632
|
!lastElement && jsx("span", {
|
|
6320
|
-
className: css$
|
|
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$
|
|
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$
|
|
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$
|
|
7711
|
+
className: css$29.punctuation,
|
|
6399
7712
|
children: open
|
|
6400
7713
|
}),
|
|
6401
7714
|
jsx("span", {
|
|
6402
|
-
className: css$
|
|
7715
|
+
className: css$29.punctuation,
|
|
6403
7716
|
children: close
|
|
6404
7717
|
}),
|
|
6405
7718
|
!lastElement && jsx("span", {
|
|
6406
|
-
className: css$
|
|
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$
|
|
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$
|
|
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$
|
|
7748
|
+
className: css$29.preview,
|
|
6436
7749
|
children: previewValue(value, 0)
|
|
6437
7750
|
}),
|
|
6438
7751
|
!lastElement && jsx("span", {
|
|
6439
|
-
className: css$
|
|
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$
|
|
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$
|
|
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$
|
|
7899
|
+
className: css$29.expandedTopLevel,
|
|
6587
7900
|
children: [
|
|
6588
7901
|
jsxs("div", {
|
|
6589
|
-
className: clsx(css$
|
|
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$
|
|
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$
|
|
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$
|
|
7939
|
+
className: clsx(css$29.row, css$29.topLevelBracket),
|
|
6627
7940
|
children: jsx("span", {
|
|
6628
|
-
className: css$
|
|
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$
|
|
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$
|
|
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$
|
|
8492
|
+
className: css$30.header,
|
|
7179
8493
|
children: [
|
|
7180
8494
|
jsxs("div", {
|
|
7181
|
-
className: css$
|
|
7182
|
-
children: [jsx("span", {
|
|
7183
|
-
className: css$
|
|
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$
|
|
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$
|
|
8504
|
+
className: css$30.runState
|
|
7191
8505
|
}),
|
|
7192
8506
|
jsx("span", {
|
|
7193
|
-
className: css$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
8530
|
+
className: css$30.empty,
|
|
7217
8531
|
children: copy.noOutput
|
|
7218
8532
|
}) : jsxs("div", {
|
|
7219
|
-
className: css$
|
|
8533
|
+
className: css$30.output,
|
|
7220
8534
|
children: [
|
|
7221
8535
|
(capped ? lines.slice(0, headLines) : lines).map((line, index) => jsx("div", {
|
|
7222
|
-
className: css$
|
|
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$
|
|
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$
|
|
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$
|
|
9136
|
+
className: css$31.line,
|
|
7823
9137
|
children: [jsx("span", {
|
|
7824
|
-
className: css$
|
|
9138
|
+
className: css$31.gutter,
|
|
7825
9139
|
"aria-hidden": true,
|
|
7826
9140
|
children: line.number
|
|
7827
9141
|
}), jsx("span", {
|
|
7828
|
-
className: css$
|
|
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$
|
|
9149
|
+
className: clsx(css$31.block, className),
|
|
7836
9150
|
"data-read": "",
|
|
7837
9151
|
children: [jsxs("div", {
|
|
7838
|
-
className: css$
|
|
9152
|
+
className: css$31.banner,
|
|
7839
9153
|
children: [jsx("div", {
|
|
7840
|
-
className: css$
|
|
9154
|
+
className: css$31.label,
|
|
7841
9155
|
children: label ?? ""
|
|
7842
9156
|
}), jsxs("div", {
|
|
7843
|
-
className: css$
|
|
9157
|
+
className: css$31.action,
|
|
7844
9158
|
children: [
|
|
7845
9159
|
windowed && jsx("span", {
|
|
7846
|
-
className: css$
|
|
9160
|
+
className: css$31.count,
|
|
7847
9161
|
children: labels.window(lines.length, totalLines)
|
|
7848
9162
|
}),
|
|
7849
9163
|
jsx("span", {
|
|
7850
|
-
className: css$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
7889
|
-
del: css$
|
|
7890
|
-
add: css$
|
|
7891
|
-
context: css$
|
|
7892
|
-
gap: css$
|
|
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$
|
|
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$
|
|
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$
|
|
9354
|
+
className: css$32.body,
|
|
8041
9355
|
children: [
|
|
8042
9356
|
head.map((row, index) => jsx("div", {
|
|
8043
|
-
className: clsx(css$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
9510
|
+
className: css$33.line,
|
|
8197
9511
|
children: row.path
|
|
8198
9512
|
});
|
|
8199
9513
|
if (row.type === "match") return jsxs("div", {
|
|
8200
|
-
className: css$
|
|
9514
|
+
className: css$33.line,
|
|
8201
9515
|
children: [jsxs("span", {
|
|
8202
|
-
className: css$
|
|
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$
|
|
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$
|
|
9528
|
+
className: css$33.filePath,
|
|
8215
9529
|
children: row.path
|
|
8216
9530
|
}), jsx("span", {
|
|
8217
|
-
className: css$
|
|
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$
|
|
9537
|
+
className: clsx(css$33.block, className),
|
|
8224
9538
|
"data-search": props.kind,
|
|
8225
9539
|
children: [jsxs("div", {
|
|
8226
|
-
className: css$
|
|
9540
|
+
className: css$33.header,
|
|
8227
9541
|
children: [jsx("span", {
|
|
8228
|
-
className: css$
|
|
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$
|
|
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$
|
|
9551
|
+
className: css$33.empty,
|
|
8238
9552
|
children: props.labels.noResults
|
|
8239
9553
|
}) : jsxs("div", {
|
|
8240
|
-
className: css$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
10399
|
+
className: css$34.bannerWrap,
|
|
9086
10400
|
children: jsxs("div", {
|
|
9087
|
-
className: css$
|
|
10401
|
+
className: css$34.banner,
|
|
9088
10402
|
"data-code-block-banner": true,
|
|
9089
10403
|
children: [jsx("div", {
|
|
9090
|
-
className: css$
|
|
10404
|
+
className: css$34.infostring,
|
|
9091
10405
|
children: lang ?? ""
|
|
9092
10406
|
}), jsx("div", {
|
|
9093
|
-
className: css$
|
|
10407
|
+
className: css$34.action,
|
|
9094
10408
|
children: jsx("button", {
|
|
9095
10409
|
type: "button",
|
|
9096
|
-
className: css$
|
|
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$
|
|
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$
|
|
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$
|
|
10574
|
+
className: css$35.error,
|
|
9261
10575
|
role: "alert",
|
|
9262
10576
|
children: [jsx("span", {
|
|
9263
|
-
className: css$
|
|
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$
|
|
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$
|
|
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$
|
|
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(
|
|
9487
|
-
className: css$
|
|
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
|
-
|
|
9493
|
-
|
|
9494
|
-
"
|
|
9495
|
-
|
|
9496
|
-
|
|
9497
|
-
|
|
9498
|
-
|
|
9499
|
-
|
|
9500
|
-
|
|
9501
|
-
|
|
9502
|
-
|
|
9503
|
-
|
|
9504
|
-
|
|
9505
|
-
|
|
9506
|
-
|
|
9507
|
-
|
|
9508
|
-
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
11657
|
+
className: css$38.sourceLink
|
|
10341
11658
|
}),
|
|
10342
11659
|
source.snippet !== void 0 && source.snippet !== "" && jsx("div", {
|
|
10343
|
-
className: css$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
11690
|
+
className: css$38.empty,
|
|
10374
11691
|
children: labels.noResults
|
|
10375
11692
|
}) : jsx("ol", {
|
|
10376
|
-
className: css$
|
|
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$
|
|
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$
|
|
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$
|
|
11718
|
+
className: css$38.fetchUrl
|
|
10402
11719
|
}), jsxs("div", {
|
|
10403
|
-
className: css$
|
|
11720
|
+
className: css$38.fetchMeta,
|
|
10404
11721
|
children: [jsxs("span", {
|
|
10405
|
-
className: css$
|
|
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$
|
|
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$
|
|
11763
|
+
className: css$39.root,
|
|
10447
11764
|
children: [jsxs("button", {
|
|
10448
11765
|
type: "button",
|
|
10449
|
-
className: css$
|
|
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$
|
|
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$
|
|
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$
|
|
11871
|
+
className: css$40.start
|
|
10555
11872
|
}),
|
|
10556
11873
|
jsx("div", {
|
|
10557
11874
|
id: headingId,
|
|
10558
11875
|
"data-menu-group-heading": "",
|
|
10559
|
-
className: css$
|
|
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
|
-
|
|
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
|