@qilin-agent/client-ui-primitives 3.1.4 → 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 +12 -12
- package/README.md +9 -6
- package/README.zh.md +9 -6
- 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 +1726 -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 +9 -0
- 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
|
|
@@ -1900,6 +1903,127 @@ const IconPinFillRegular = ({ size = 16, className }) => jsxs("svg", {
|
|
|
1900
1903
|
fill: "currentColor"
|
|
1901
1904
|
})]
|
|
1902
1905
|
});
|
|
1906
|
+
/**
|
|
1907
|
+
* Upstream-named icon surface. Community plugins written against
|
|
1908
|
+
* `@deepseek-ai/dsh-client-ui-primitives` import weight-suffixed names
|
|
1909
|
+
* (`OutlineRegular`/`OutlineMedium`) that this set spells with size
|
|
1910
|
+
* suffixes; each alias binds the same-name glyph in the nearest size. The
|
|
1911
|
+
* two names with no drawn QiLin glyph (Users, WorkspaceTree) port the
|
|
1912
|
+
* upstream artwork verbatim (dsh-context is the current consumer).
|
|
1913
|
+
*/
|
|
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
|
+
});
|
|
1933
|
+
const IconUsersOutlineRegular = ({ size = 16, className }) => jsxs("svg", {
|
|
1934
|
+
width: size,
|
|
1935
|
+
height: size,
|
|
1936
|
+
className,
|
|
1937
|
+
viewBox: "0 0 16 16",
|
|
1938
|
+
fill: "none",
|
|
1939
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1940
|
+
"aria-hidden": "true",
|
|
1941
|
+
strokeWidth: ICON_REGULAR_STROKE,
|
|
1942
|
+
children: [
|
|
1943
|
+
jsx("path", {
|
|
1944
|
+
d: "M6 8.25C7.51878 8.25 8.75 7.01878 8.75 5.5C8.75 3.98122 7.51878 2.75 6 2.75C4.48122 2.75 3.25 3.98122 3.25 5.5C3.25 7.01878 4.48122 8.25 6 8.25Z",
|
|
1945
|
+
stroke: "currentColor"
|
|
1946
|
+
}),
|
|
1947
|
+
jsx("path", {
|
|
1948
|
+
d: "M1 14.5C1 11.5 3.5 10.25 6 10.25C8.5 10.25 11 11.5 11 14.5",
|
|
1949
|
+
stroke: "currentColor"
|
|
1950
|
+
}),
|
|
1951
|
+
jsx("path", {
|
|
1952
|
+
d: "M10.5 2.9C11.65 3.35 12.45 4.35 12.45 5.5C12.45 6.65 11.65 7.65 10.5 8.1",
|
|
1953
|
+
stroke: "currentColor"
|
|
1954
|
+
}),
|
|
1955
|
+
jsx("path", {
|
|
1956
|
+
d: "M12.4 10.6C13.9 11.3 15 12.6 15 14.5",
|
|
1957
|
+
stroke: "currentColor"
|
|
1958
|
+
})
|
|
1959
|
+
]
|
|
1960
|
+
});
|
|
1961
|
+
const IconWorkspaceTreeOutlineRegular = ({ size = 16, className }) => jsxs("svg", {
|
|
1962
|
+
width: size,
|
|
1963
|
+
height: size,
|
|
1964
|
+
className,
|
|
1965
|
+
viewBox: "0 0 16 16",
|
|
1966
|
+
fill: "none",
|
|
1967
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1968
|
+
"aria-hidden": "true",
|
|
1969
|
+
stroke: "currentColor",
|
|
1970
|
+
strokeLinecap: "round",
|
|
1971
|
+
strokeLinejoin: "round",
|
|
1972
|
+
strokeWidth: ICON_REGULAR_STROKE,
|
|
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" })]
|
|
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
|
+
});
|
|
1903
2027
|
//#endregion
|
|
1904
2028
|
//#region lib/types/Tag.js
|
|
1905
2029
|
/**
|
|
@@ -2377,6 +2501,29 @@ function CommandText({ text, label, className }) {
|
|
|
2377
2501
|
}
|
|
2378
2502
|
//#endregion
|
|
2379
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
|
+
}
|
|
2380
2527
|
/** Outer 3x3 matrix cells (2px pixels on a 10px grid), clockwise from top-left. */
|
|
2381
2528
|
const MATRIX_CELLS = [
|
|
2382
2529
|
[0, 0],
|
|
@@ -2397,6 +2544,7 @@ const MATRIX_CELLS = [
|
|
|
2397
2544
|
*/
|
|
2398
2545
|
function StateDot({ state, size = 10, className }) {
|
|
2399
2546
|
if (state === "ongoing") return jsx("svg", {
|
|
2547
|
+
ref: syncSpinner,
|
|
2400
2548
|
className: clsx(css$4.matrix, className),
|
|
2401
2549
|
"data-state": "ongoing",
|
|
2402
2550
|
width: size,
|
|
@@ -2659,6 +2807,274 @@ function SegmentedControl({ id, value, options, onChange, label, disabled = fals
|
|
|
2659
2807
|
});
|
|
2660
2808
|
}
|
|
2661
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
|
|
2662
3078
|
//#region lib/types/Switch.js
|
|
2663
3079
|
/**
|
|
2664
3080
|
* Render a toggle switch.
|
|
@@ -2679,11 +3095,11 @@ function Switch({ checked, onChange, label, disabled = false, title, className }
|
|
|
2679
3095
|
"aria-label": label,
|
|
2680
3096
|
title,
|
|
2681
3097
|
disabled,
|
|
2682
|
-
className: clsx(css$
|
|
3098
|
+
className: clsx(css$11.switch, className),
|
|
2683
3099
|
onClick: () => {
|
|
2684
3100
|
onChange(!checked);
|
|
2685
3101
|
},
|
|
2686
|
-
children: jsx("span", { className: css$
|
|
3102
|
+
children: jsx("span", { className: css$11.thumb })
|
|
2687
3103
|
});
|
|
2688
3104
|
}
|
|
2689
3105
|
//#endregion
|
|
@@ -2701,7 +3117,7 @@ function Switch({ checked, onChange, label, disabled = false, title, className }
|
|
|
2701
3117
|
*/
|
|
2702
3118
|
function Checkbox({ checked, onChange, label, disabled = false, title, className }) {
|
|
2703
3119
|
return jsxs("label", {
|
|
2704
|
-
className: clsx(css$
|
|
3120
|
+
className: clsx(css$12.checkbox, className),
|
|
2705
3121
|
title,
|
|
2706
3122
|
children: [jsx("input", {
|
|
2707
3123
|
type: "checkbox",
|
|
@@ -2723,17 +3139,85 @@ function Checkbox({ checked, onChange, label, disabled = false, title, className
|
|
|
2723
3139
|
*/
|
|
2724
3140
|
const Input = forwardRef(function Input({ icon, className, ...rest }, ref) {
|
|
2725
3141
|
return jsxs("span", {
|
|
2726
|
-
className: clsx(css$
|
|
3142
|
+
className: clsx(css$13.wrap, className),
|
|
2727
3143
|
children: [icon != null && jsx("span", {
|
|
2728
|
-
className: css$
|
|
3144
|
+
className: css$13.icon,
|
|
2729
3145
|
children: icon
|
|
2730
3146
|
}), jsx("input", {
|
|
2731
3147
|
ref,
|
|
2732
|
-
className: css$
|
|
3148
|
+
className: css$13.input,
|
|
2733
3149
|
...rest
|
|
2734
3150
|
})]
|
|
2735
3151
|
});
|
|
2736
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
|
+
}
|
|
2737
3221
|
/**
|
|
2738
3222
|
* Delay a pointer-dismissed popup's close so the pointer can cross the gap
|
|
2739
3223
|
* between anchor and popup. A pending close is dropped on unmount.
|
|
@@ -2943,14 +3427,55 @@ function useModalLayer(dialog, open, onClose) {
|
|
|
2943
3427
|
*/
|
|
2944
3428
|
function ShortcutKeys({ keys, variant = "plain", className }) {
|
|
2945
3429
|
return jsx("span", {
|
|
2946
|
-
className: clsx(css$
|
|
3430
|
+
className: clsx(css$15.keys, variant === "tooltip" && css$15.tooltip, variant === "tooltip" && keys.includes("+") && css$15.joined, className),
|
|
2947
3431
|
children: keys.map((key, index) => jsx("kbd", {
|
|
2948
|
-
className: key === "+" ? css$
|
|
3432
|
+
className: key === "+" ? css$15.separator : css$15.key,
|
|
2949
3433
|
children: key
|
|
2950
3434
|
}, index))
|
|
2951
3435
|
});
|
|
2952
3436
|
}
|
|
2953
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
|
|
2954
3479
|
//#region lib/types/Menu.js
|
|
2955
3480
|
/**
|
|
2956
3481
|
* Render one `role="menuitem"` row for a {@link Menu} whose rows are
|
|
@@ -2969,32 +3494,32 @@ function ShortcutKeys({ keys, variant = "plain", className }) {
|
|
|
2969
3494
|
*/
|
|
2970
3495
|
function MenuItemButton({ children, shortcut, icon, disabled = false, danger = false, separatorBefore = false, onSelect }) {
|
|
2971
3496
|
return jsxs("div", {
|
|
2972
|
-
className: css$
|
|
3497
|
+
className: css$17.itemWrap,
|
|
2973
3498
|
children: [separatorBefore && jsx("div", {
|
|
2974
|
-
className: css$
|
|
3499
|
+
className: css$17.separator,
|
|
2975
3500
|
role: "separator"
|
|
2976
3501
|
}), jsxs("button", {
|
|
2977
3502
|
type: "button",
|
|
2978
3503
|
role: "menuitem",
|
|
2979
|
-
className: clsx(css$
|
|
3504
|
+
className: clsx(css$17.item, danger && css$17.danger),
|
|
2980
3505
|
disabled,
|
|
2981
3506
|
"aria-keyshortcuts": shortcut?.aria,
|
|
2982
3507
|
onClick: onSelect,
|
|
2983
3508
|
children: [
|
|
2984
3509
|
icon !== void 0 && jsx("span", {
|
|
2985
|
-
className: css$
|
|
3510
|
+
className: css$17.itemIcon,
|
|
2986
3511
|
children: icon
|
|
2987
3512
|
}),
|
|
2988
3513
|
jsx("span", {
|
|
2989
|
-
className: css$
|
|
3514
|
+
className: css$17.itemLabel,
|
|
2990
3515
|
children
|
|
2991
3516
|
}),
|
|
2992
3517
|
shortcut !== void 0 && jsx("span", {
|
|
2993
3518
|
"aria-hidden": "true",
|
|
2994
|
-
className: css$
|
|
3519
|
+
className: css$17.shortcut,
|
|
2995
3520
|
children: jsx(ShortcutKeys, {
|
|
2996
3521
|
keys: shortcut.keys,
|
|
2997
|
-
className: css$
|
|
3522
|
+
className: css$17.shortcutKeys
|
|
2998
3523
|
})
|
|
2999
3524
|
})
|
|
3000
3525
|
]
|
|
@@ -3023,17 +3548,17 @@ const MEASURE_STYLE = {
|
|
|
3023
3548
|
* @param props.autoFocus - focus the first item on open; the arrow keys walk the list either way.
|
|
3024
3549
|
* @param props.open - whether the list is showing (owner-controlled).
|
|
3025
3550
|
* @param props.anchor - the trigger element (rendered in place).
|
|
3026
|
-
* @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).
|
|
3027
3552
|
* @param props.selectedId - row shown as selected.
|
|
3028
3553
|
* @param props.selectedIds - rows shown as selected when a menu contains independent option groups.
|
|
3029
|
-
* @param props.onSelect - row
|
|
3554
|
+
* @param props.onSelect - data-row activation callback (not called for disabled rows or submenu parents that only open children).
|
|
3030
3555
|
* @param props.onClose - invoked on outside click, Escape, or a window blur
|
|
3031
3556
|
* that moved focus into an iframe (the only signal a pointerdown inside a
|
|
3032
3557
|
* cross-origin iframe leaves).
|
|
3033
3558
|
* @param props.align - list alignment against the anchor (default 'start').
|
|
3034
3559
|
* @param props.side - open below (`bottom`, default) or above (`top`) the anchor.
|
|
3035
3560
|
* @param props.portal - render the list into document.body, fixed-positioned
|
|
3036
|
-
* from the anchor rect (
|
|
3561
|
+
* from the anchor rect (follows movement and resizing while open). Use when an
|
|
3037
3562
|
* ancestor's overflow clipping would crop the in-place list; default false
|
|
3038
3563
|
* keeps the pure-CSS in-place behavior.
|
|
3039
3564
|
* @param props.closeOnPointerLeave - close the list once the pointer has left
|
|
@@ -3046,17 +3571,25 @@ const MEASURE_STYLE = {
|
|
|
3046
3571
|
* directly (e.g. from a host-owned trigger button) instead of measuring the
|
|
3047
3572
|
* Menu's own wrapper span. Required when the wrapper isn't itself laid out at
|
|
3048
3573
|
* the trigger (render-prop anchors, effect-positioned proxies — measuring the
|
|
3049
|
-
* wrapper there races the host's layout effects). Called on open
|
|
3050
|
-
* 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.
|
|
3051
3576
|
* @param props.footer - rows pinned below the scrolling items area, separated
|
|
3052
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.
|
|
3053
3582
|
* @param props.selection - how a selected row is marked: a trailing check
|
|
3054
3583
|
* (`'check'`, default — figma .Menu_cell) or the hover fill held on the row
|
|
3055
3584
|
* with no check (`'fill'`, for icon-labelled rows where a trailing glyph
|
|
3056
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.
|
|
3057
3590
|
* @returns anchor wrapper with the conditional list.
|
|
3058
3591
|
*/
|
|
3059
|
-
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 }) {
|
|
3060
3593
|
const rootRef = useRef(null);
|
|
3061
3594
|
const listRef = useRef(null);
|
|
3062
3595
|
/** Index the arrow walk last focused, the resume point when focus left the rows. */
|
|
@@ -3073,6 +3606,7 @@ function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, onClose,
|
|
|
3073
3606
|
* anchor never held it, to the anchor's first button. Focus left on a removed
|
|
3074
3607
|
* row otherwise falls to the page body, where the next Tab restarts from the
|
|
3075
3608
|
* top of the page.
|
|
3609
|
+
* @param navigation - whether explicit keyboard traversal should retain its focus indicator.
|
|
3076
3610
|
*/
|
|
3077
3611
|
const refocusAnchor = (navigation = false) => {
|
|
3078
3612
|
const trigger = triggerRef.current;
|
|
@@ -3089,10 +3623,10 @@ function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, onClose,
|
|
|
3089
3623
|
* its removal produced) comes back to the trigger.
|
|
3090
3624
|
*/
|
|
3091
3625
|
const refocusAfterSelection = () => {
|
|
3626
|
+
const navigation = selectingWithTab.current;
|
|
3092
3627
|
queueMicrotask(() => {
|
|
3093
3628
|
if (openRef.current) return;
|
|
3094
3629
|
const active = document.activeElement;
|
|
3095
|
-
const navigation = selectingWithTab.current;
|
|
3096
3630
|
if (active === null || active === document.body || listRef.current?.contains(active) === true) refocusAnchor(navigation);
|
|
3097
3631
|
});
|
|
3098
3632
|
};
|
|
@@ -3132,16 +3666,22 @@ function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, onClose,
|
|
|
3132
3666
|
y = side === "bottom" ? r.bottom + 4 : r.top - lh - 4;
|
|
3133
3667
|
}
|
|
3134
3668
|
if (lw > 0) x = Math.min(Math.max(x, MARGIN), vw - lw - MARGIN);
|
|
3135
|
-
if (lh > 0) y = Math.min(Math.max(y, MARGIN), vh - lh - MARGIN);
|
|
3136
|
-
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 : {
|
|
3137
3671
|
left: x,
|
|
3138
3672
|
top: y
|
|
3139
3673
|
});
|
|
3140
3674
|
};
|
|
3141
3675
|
place();
|
|
3676
|
+
const track = () => {
|
|
3677
|
+
place();
|
|
3678
|
+
frame = requestAnimationFrame(track);
|
|
3679
|
+
};
|
|
3680
|
+
let frame = requestAnimationFrame(track);
|
|
3142
3681
|
window.addEventListener("scroll", place, true);
|
|
3143
3682
|
window.addEventListener("resize", place);
|
|
3144
3683
|
return () => {
|
|
3684
|
+
cancelAnimationFrame(frame);
|
|
3145
3685
|
window.removeEventListener("scroll", place, true);
|
|
3146
3686
|
window.removeEventListener("resize", place);
|
|
3147
3687
|
};
|
|
@@ -3172,6 +3712,7 @@ function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, onClose,
|
|
|
3172
3712
|
walkIndex.current = null;
|
|
3173
3713
|
return;
|
|
3174
3714
|
}
|
|
3715
|
+
const composition = observeComposition(document);
|
|
3175
3716
|
const onPointerDown = (e) => {
|
|
3176
3717
|
if (!(e.target instanceof Node)) return;
|
|
3177
3718
|
if (rootRef.current?.contains(e.target) === true) return;
|
|
@@ -3179,15 +3720,15 @@ function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, onClose,
|
|
|
3179
3720
|
onClose();
|
|
3180
3721
|
};
|
|
3181
3722
|
const onKeyDown = (e) => {
|
|
3723
|
+
if (composition.guards(e) || isBehindModal(rootRef.current) || e.defaultPrevented || e.ctrlKey || e.altKey || e.metaKey) return;
|
|
3182
3724
|
const focused = document.activeElement;
|
|
3183
3725
|
const insideList = listRef.current?.contains(focused) === true;
|
|
3184
3726
|
const anchored = rootRef.current?.contains(focused) === true || insideList;
|
|
3185
|
-
if (composition.guards(e) || isBehindModal(rootRef.current) || e.defaultPrevented || e.ctrlKey || e.altKey || e.metaKey) return;
|
|
3186
3727
|
if (e.key === "Escape" && !e.shiftKey) {
|
|
3187
3728
|
e.preventDefault();
|
|
3188
3729
|
if (e.repeat) return;
|
|
3189
3730
|
onClose();
|
|
3190
|
-
if (anchored || autoFocus) refocusAnchor(
|
|
3731
|
+
if (anchored || autoFocus) refocusAnchor();
|
|
3191
3732
|
}
|
|
3192
3733
|
if (e.key === "Tab") {
|
|
3193
3734
|
const list = listRef.current;
|
|
@@ -3195,7 +3736,7 @@ function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, onClose,
|
|
|
3195
3736
|
if (e.shiftKey) {
|
|
3196
3737
|
e.preventDefault();
|
|
3197
3738
|
onClose();
|
|
3198
|
-
refocusAnchor();
|
|
3739
|
+
refocusAnchor(true);
|
|
3199
3740
|
return;
|
|
3200
3741
|
}
|
|
3201
3742
|
if (insideList) {
|
|
@@ -3237,14 +3778,13 @@ function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, onClose,
|
|
|
3237
3778
|
const onWindowBlur = () => {
|
|
3238
3779
|
if (document.activeElement instanceof HTMLIFrameElement) onClose();
|
|
3239
3780
|
};
|
|
3781
|
+
document.addEventListener("pointerdown", onPointerDown);
|
|
3240
3782
|
const onEscape = (event) => {
|
|
3241
3783
|
if (event.key === "Escape") onKeyDown(event);
|
|
3242
3784
|
};
|
|
3243
3785
|
const onOtherKey = (event) => {
|
|
3244
3786
|
if (event.key !== "Escape") onKeyDown(event);
|
|
3245
3787
|
};
|
|
3246
|
-
const composition = observeComposition(document);
|
|
3247
|
-
document.addEventListener("pointerdown", onPointerDown);
|
|
3248
3788
|
document.addEventListener("keydown", onOtherKey);
|
|
3249
3789
|
document.addEventListener("keydown", onEscape, true);
|
|
3250
3790
|
window.addEventListener("blur", onWindowBlur);
|
|
@@ -3266,11 +3806,11 @@ function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, onClose,
|
|
|
3266
3806
|
const scrollable = !items.some((entry) => !isSeparator(entry) && !isLabel(entry) && entry.submenu !== void 0 && entry.submenu.length > 0);
|
|
3267
3807
|
const renderEntry = (entry) => {
|
|
3268
3808
|
if (isSeparator(entry)) return jsx("div", {
|
|
3269
|
-
className: css$
|
|
3809
|
+
className: css$17.separator,
|
|
3270
3810
|
role: "separator"
|
|
3271
3811
|
}, entry.id);
|
|
3272
3812
|
if (isLabel(entry)) return jsx("div", {
|
|
3273
|
-
className: css$
|
|
3813
|
+
className: css$17.label,
|
|
3274
3814
|
role: "presentation",
|
|
3275
3815
|
children: entry.text
|
|
3276
3816
|
}, entry.id);
|
|
@@ -3278,79 +3818,79 @@ function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, onClose,
|
|
|
3278
3818
|
const subOpen = hasSub && openSubmenuId === entry.id;
|
|
3279
3819
|
const selected = entry.id === selectedId || selectedIds?.includes(entry.id) === true;
|
|
3280
3820
|
return jsxs("div", {
|
|
3281
|
-
className: css$
|
|
3282
|
-
onMouseEnter: () => {
|
|
3283
|
-
setOpenSubmenuId(
|
|
3284
|
-
},
|
|
3821
|
+
className: css$17.itemWrap,
|
|
3822
|
+
onMouseEnter: hasSub ? () => {
|
|
3823
|
+
setOpenSubmenuId(entry.id);
|
|
3824
|
+
} : void 0,
|
|
3285
3825
|
onMouseLeave: () => {
|
|
3286
3826
|
setOpenSubmenuId(null);
|
|
3287
3827
|
},
|
|
3288
3828
|
children: [jsxs("button", {
|
|
3289
3829
|
type: "button",
|
|
3290
3830
|
role: "menuitem",
|
|
3291
|
-
className: clsx(css$
|
|
3831
|
+
className: clsx(css$17.item, selected && (selection === "fill" ? css$17.selectedFill : css$17.selected), entry.danger === true && css$17.danger),
|
|
3292
3832
|
disabled: entry.disabled,
|
|
3293
3833
|
"aria-keyshortcuts": entry.shortcut?.aria,
|
|
3294
3834
|
"aria-haspopup": hasSub ? "menu" : void 0,
|
|
3295
3835
|
"aria-expanded": hasSub ? subOpen : void 0,
|
|
3296
|
-
onFocus: () => {
|
|
3297
|
-
setOpenSubmenuId(
|
|
3298
|
-
},
|
|
3836
|
+
onFocus: hasSub ? () => {
|
|
3837
|
+
setOpenSubmenuId(entry.id);
|
|
3838
|
+
} : void 0,
|
|
3299
3839
|
onClick: () => {
|
|
3300
3840
|
if (hasSub) {
|
|
3301
3841
|
setOpenSubmenuId(entry.id);
|
|
3302
3842
|
return;
|
|
3303
3843
|
}
|
|
3304
|
-
onSelect(entry.id);
|
|
3305
|
-
refocusAfterSelection();
|
|
3844
|
+
onSelect?.(entry.id);
|
|
3306
3845
|
},
|
|
3307
3846
|
children: [
|
|
3308
3847
|
entry.icon !== void 0 && jsx("span", {
|
|
3309
|
-
className: css$
|
|
3848
|
+
className: css$17.itemIcon,
|
|
3310
3849
|
children: entry.icon
|
|
3311
3850
|
}),
|
|
3312
3851
|
jsx("span", {
|
|
3313
|
-
className: css$
|
|
3852
|
+
className: css$17.itemLabel,
|
|
3314
3853
|
children: entry.label
|
|
3315
3854
|
}),
|
|
3316
3855
|
entry.shortcut !== void 0 && jsx("span", {
|
|
3317
3856
|
"aria-hidden": "true",
|
|
3318
|
-
className: css$
|
|
3857
|
+
className: css$17.shortcut,
|
|
3319
3858
|
children: jsx(ShortcutKeys, {
|
|
3320
3859
|
keys: entry.shortcut.keys,
|
|
3321
|
-
className: css$
|
|
3860
|
+
className: css$17.shortcutKeys
|
|
3322
3861
|
})
|
|
3323
3862
|
}),
|
|
3324
|
-
selected && selection === "check" && jsx(IconCheckOutline16, { className: css$
|
|
3863
|
+
selected && selection === "check" && jsx(IconCheckOutline16, { className: css$17.check })
|
|
3325
3864
|
]
|
|
3326
|
-
}), subOpen && entry.submenu !== void 0 && jsx(
|
|
3327
|
-
|
|
3865
|
+
}), subOpen && entry.submenu !== void 0 && jsx(MenuSurface, {
|
|
3866
|
+
compact,
|
|
3867
|
+
className: clsx(css$17.submenu, compact && css$17.compactList),
|
|
3328
3868
|
role: "menu",
|
|
3329
3869
|
children: entry.submenu.map((sub) => jsxs("button", {
|
|
3330
3870
|
type: "button",
|
|
3331
3871
|
role: "menuitem",
|
|
3332
|
-
className: css$
|
|
3872
|
+
className: css$17.item,
|
|
3333
3873
|
disabled: sub.disabled,
|
|
3334
3874
|
"aria-keyshortcuts": sub.shortcut?.aria,
|
|
3335
3875
|
onClick: () => {
|
|
3336
|
-
onSelect(sub.id);
|
|
3876
|
+
onSelect?.(sub.id);
|
|
3337
3877
|
refocusAfterSelection();
|
|
3338
3878
|
},
|
|
3339
3879
|
children: [
|
|
3340
3880
|
sub.icon !== void 0 && jsx("span", {
|
|
3341
|
-
className: css$
|
|
3881
|
+
className: css$17.itemIcon,
|
|
3342
3882
|
children: sub.icon
|
|
3343
3883
|
}),
|
|
3344
3884
|
jsx("span", {
|
|
3345
|
-
className: css$
|
|
3885
|
+
className: css$17.itemLabel,
|
|
3346
3886
|
children: sub.label
|
|
3347
3887
|
}),
|
|
3348
3888
|
sub.shortcut !== void 0 && jsx("span", {
|
|
3349
3889
|
"aria-hidden": "true",
|
|
3350
|
-
className: css$
|
|
3890
|
+
className: css$17.shortcut,
|
|
3351
3891
|
children: jsx(ShortcutKeys, {
|
|
3352
3892
|
keys: sub.shortcut.keys,
|
|
3353
|
-
className: css$
|
|
3893
|
+
className: css$17.shortcutKeys
|
|
3354
3894
|
})
|
|
3355
3895
|
})
|
|
3356
3896
|
]
|
|
@@ -3358,27 +3898,38 @@ function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, onClose,
|
|
|
3358
3898
|
})]
|
|
3359
3899
|
}, entry.id);
|
|
3360
3900
|
};
|
|
3361
|
-
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,
|
|
3362
3909
|
ref: listRef,
|
|
3363
|
-
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),
|
|
3364
3911
|
style: portal ? fixedPos ?? MEASURE_STYLE : void 0,
|
|
3365
3912
|
role: "menu",
|
|
3366
3913
|
onClick: (e) => {
|
|
3367
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();
|
|
3368
3917
|
},
|
|
3369
|
-
|
|
3370
|
-
|
|
3918
|
+
onMouseOver: collapseSubmenuFrom,
|
|
3919
|
+
onFocus: collapseSubmenuFrom,
|
|
3920
|
+
children: [jsxs("div", {
|
|
3921
|
+
className: css$17.viewport,
|
|
3371
3922
|
role: "presentation",
|
|
3372
|
-
children: items.map(renderEntry)
|
|
3923
|
+
children: [items.map(renderEntry), children]
|
|
3373
3924
|
}), footer !== void 0 && footer.length > 0 && jsx("div", {
|
|
3374
|
-
className: css$
|
|
3925
|
+
className: css$17.footer,
|
|
3375
3926
|
role: "presentation",
|
|
3376
3927
|
children: footer.map(renderEntry)
|
|
3377
3928
|
})]
|
|
3378
3929
|
});
|
|
3379
3930
|
return jsxs("span", {
|
|
3380
3931
|
ref: rootRef,
|
|
3381
|
-
className: clsx(css$
|
|
3932
|
+
className: clsx(css$17.root, className),
|
|
3382
3933
|
onPointerEnter: closeOnPointerLeave ? cancelClose : void 0,
|
|
3383
3934
|
onPointerLeave: closeOnPointerLeave ? () => {
|
|
3384
3935
|
if (open) armClose();
|
|
@@ -3427,20 +3978,6 @@ function useAnchoredMaxHeight(ref, cap, signal) {
|
|
|
3427
3978
|
return maxHeight;
|
|
3428
3979
|
}
|
|
3429
3980
|
//#endregion
|
|
3430
|
-
//#region lib/types/overlay-top-margin.js
|
|
3431
|
-
/** Shared viewport inset for overlays, derived from the desktop frame's reserved top strip. */
|
|
3432
|
-
/**
|
|
3433
|
-
* Resolve the top margin an overlay keeps from the viewport edge.
|
|
3434
|
-
* @param min - the overlay's own viewport margin in px, used as the floor.
|
|
3435
|
-
* @returns the larger of `min` and the frame clearance plus 20px; fullscreen keeps only the 20px gap.
|
|
3436
|
-
*/
|
|
3437
|
-
function overlayTopMargin(min) {
|
|
3438
|
-
const root = document.documentElement;
|
|
3439
|
-
const clearance = Number.parseFloat(getComputedStyle(root).getPropertyValue("--qilin-frame-top-clearance"));
|
|
3440
|
-
if (Number.isNaN(clearance)) return min;
|
|
3441
|
-
return Math.max(min, (root.hasAttribute("data-fullscreen") ? 0 : clearance) + 20);
|
|
3442
|
-
}
|
|
3443
|
-
//#endregion
|
|
3444
3981
|
//#region lib/types/useAnchoredPosition.js
|
|
3445
3982
|
/**
|
|
3446
3983
|
* Keep a fixed-position floating element anchored to a trigger.
|
|
@@ -3455,11 +3992,11 @@ function overlayTopMargin(min) {
|
|
|
3455
3992
|
*/
|
|
3456
3993
|
/**
|
|
3457
3994
|
* Track an anchor and return the panel's fixed coordinates.
|
|
3458
|
-
* @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.
|
|
3459
3996
|
* @returns `left`/`top` for the panel, or `null` before the first measurement.
|
|
3460
3997
|
*/
|
|
3461
3998
|
function useAnchoredPosition(options) {
|
|
3462
|
-
const { open, anchorRef, panelRef, side = "bottom", gap, margin } = options;
|
|
3999
|
+
const { open, anchorRef, panelRef, side = "bottom", align = "start", gap, margin } = options;
|
|
3463
4000
|
const [position, setPosition] = useState(null);
|
|
3464
4001
|
useLayoutEffect(() => {
|
|
3465
4002
|
if (!open) {
|
|
@@ -3475,7 +4012,7 @@ function useAnchoredPosition(options) {
|
|
|
3475
4012
|
const panel = panelRef.current;
|
|
3476
4013
|
const width = panel?.offsetWidth ?? 0;
|
|
3477
4014
|
const height = panel?.offsetHeight ?? 0;
|
|
3478
|
-
let left = rect.left;
|
|
4015
|
+
let left = align === "end" ? rect.right - width : rect.left;
|
|
3479
4016
|
let top = side === "top" ? rect.top - gap - height : rect.bottom + gap;
|
|
3480
4017
|
if (width > 0) left = Math.min(Math.max(left, margin), window.innerWidth - width - margin);
|
|
3481
4018
|
if (height > 0) top = Math.min(Math.max(top, margin), window.innerHeight - height - margin);
|
|
@@ -3504,6 +4041,7 @@ function useAnchoredPosition(options) {
|
|
|
3504
4041
|
anchorRef,
|
|
3505
4042
|
panelRef,
|
|
3506
4043
|
side,
|
|
4044
|
+
align,
|
|
3507
4045
|
gap,
|
|
3508
4046
|
margin
|
|
3509
4047
|
]);
|
|
@@ -3649,18 +4187,25 @@ const TooltipSuppression = createContext(null);
|
|
|
3649
4187
|
* @param props.label - bubble text, or a resolver evaluated only while the bubble is visible.
|
|
3650
4188
|
* @param props.shortcutKeys - effective key labels rendered as platform-formatted keycaps after optional text.
|
|
3651
4189
|
* @param props.side - placement relative to the anchor (default 'right').
|
|
3652
|
-
* @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.
|
|
3653
4193
|
* @param props.disabled - suppress the bubble while true; the anchor renders identically so
|
|
3654
4194
|
* toggling never remounts it (which would cut its CSS transitions).
|
|
3655
4195
|
* @param props.portal - render the bubble under document.body, so an ancestor's clipping or its
|
|
3656
4196
|
* stacking context can neither clip the bubble nor paint over it.
|
|
3657
4197
|
* @param props.maxWidth - bubble width cap in pixels, for labels long enough that the default
|
|
3658
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.
|
|
3659
4202
|
* @param props.children - a single anchor element; its own ref (callback or object) is forwarded alongside the tooltip's.
|
|
3660
4203
|
* An anchor that accepts no ref still positions the bubble: a raise records the element the event ran on.
|
|
3661
4204
|
* @returns the cloned anchor plus a fixed-position bubble while hovered/focused.
|
|
3662
4205
|
*/
|
|
3663
|
-
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);
|
|
3664
4209
|
const anchor = useRef(null);
|
|
3665
4210
|
const childRef = children.ref;
|
|
3666
4211
|
const mergedRef = useCallback((el) => {
|
|
@@ -3730,6 +4275,7 @@ function Tooltip({ label, shortcutKeys, side = "right", delayMs = 0, disabled =
|
|
|
3730
4275
|
showTimer.current = null;
|
|
3731
4276
|
}, []);
|
|
3732
4277
|
useEffect(() => {
|
|
4278
|
+
if (pinned && (disabled || !openOnClick)) setPinned(false);
|
|
3733
4279
|
if (disabled) {
|
|
3734
4280
|
cancelShow();
|
|
3735
4281
|
triggers.current = {
|
|
@@ -3739,7 +4285,12 @@ function Tooltip({ label, shortcutKeys, side = "right", delayMs = 0, disabled =
|
|
|
3739
4285
|
setPos(null);
|
|
3740
4286
|
}
|
|
3741
4287
|
return cancelShow;
|
|
3742
|
-
}, [
|
|
4288
|
+
}, [
|
|
4289
|
+
cancelShow,
|
|
4290
|
+
disabled,
|
|
4291
|
+
openOnClick,
|
|
4292
|
+
pinned
|
|
4293
|
+
]);
|
|
3743
4294
|
const show = () => {
|
|
3744
4295
|
if (disabled) return;
|
|
3745
4296
|
const el = anchor.current ?? eventAnchor.current;
|
|
@@ -3754,30 +4305,61 @@ function Tooltip({ label, shortcutKeys, side = "right", delayMs = 0, disabled =
|
|
|
3754
4305
|
});
|
|
3755
4306
|
announce(true);
|
|
3756
4307
|
};
|
|
3757
|
-
const
|
|
4308
|
+
const showAfterDelay = (delay) => {
|
|
3758
4309
|
cancelShow();
|
|
3759
|
-
if (
|
|
4310
|
+
if (delay <= 0) {
|
|
3760
4311
|
show();
|
|
3761
4312
|
return;
|
|
3762
4313
|
}
|
|
3763
4314
|
showTimer.current = setTimeout(() => {
|
|
3764
4315
|
showTimer.current = null;
|
|
3765
4316
|
show();
|
|
3766
|
-
},
|
|
4317
|
+
}, delay);
|
|
3767
4318
|
};
|
|
3768
|
-
const withdraw = () => {
|
|
4319
|
+
const withdraw = useCallback(() => {
|
|
4320
|
+
setPinned(false);
|
|
3769
4321
|
setPos(null);
|
|
3770
4322
|
announce(false);
|
|
3771
|
-
};
|
|
4323
|
+
}, [announce]);
|
|
3772
4324
|
const hide = () => {
|
|
3773
4325
|
cancelShow();
|
|
3774
|
-
if (!triggers.current.hover && !triggers.current.focus) withdraw();
|
|
4326
|
+
if (!triggers.current.hover && !triggers.current.focus && !pinned) withdraw();
|
|
3775
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
|
+
]);
|
|
3776
4356
|
const bubbleNode = visible && !suppressed && jsxs("span", {
|
|
3777
4357
|
ref: bubble,
|
|
3778
|
-
|
|
4358
|
+
id: openOnClick ? id : void 0,
|
|
4359
|
+
className: css$18.bubble,
|
|
3779
4360
|
"data-side": placement,
|
|
3780
4361
|
"data-portal": portal || void 0,
|
|
4362
|
+
"data-pinned": pinned || void 0,
|
|
3781
4363
|
"data-has-shortcut": shortcutKeys?.length ? true : void 0,
|
|
3782
4364
|
style: {
|
|
3783
4365
|
left: pos.x,
|
|
@@ -3787,7 +4369,7 @@ function Tooltip({ label, shortcutKeys, side = "right", delayMs = 0, disabled =
|
|
|
3787
4369
|
role: "tooltip",
|
|
3788
4370
|
"aria-label": shortcutKeys?.length ? [resolvedLabel, shortcutKeys.join(" ")].filter(Boolean).join(" ") : void 0,
|
|
3789
4371
|
children: [resolvedLabel && jsx("span", {
|
|
3790
|
-
className: css$
|
|
4372
|
+
className: css$18.label,
|
|
3791
4373
|
children: resolvedLabel
|
|
3792
4374
|
}), shortcutKeys !== void 0 && shortcutKeys.length > 0 && jsx(ShortcutKeys, {
|
|
3793
4375
|
keys: shortcutKeys,
|
|
@@ -3798,25 +4380,35 @@ function Tooltip({ label, shortcutKeys, side = "right", delayMs = 0, disabled =
|
|
|
3798
4380
|
value: setSuppressed,
|
|
3799
4381
|
children: [cloneElement(children, {
|
|
3800
4382
|
ref: mergedRef,
|
|
4383
|
+
"aria-describedby": openOnClick && visible ? [children.props["aria-describedby"], id].filter(Boolean).join(" ") : children.props["aria-describedby"],
|
|
3801
4384
|
onMouseEnter: (e) => {
|
|
3802
4385
|
children.props.onMouseEnter?.(e);
|
|
3803
4386
|
trackAnchor(e);
|
|
3804
4387
|
triggers.current.hover = true;
|
|
3805
|
-
|
|
4388
|
+
showAfterDelay(delayMs);
|
|
3806
4389
|
},
|
|
3807
4390
|
onMouseLeave: (e) => {
|
|
3808
4391
|
children.props.onMouseLeave?.(e);
|
|
3809
4392
|
triggers.current.hover = false;
|
|
3810
4393
|
cancelShow();
|
|
3811
|
-
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();
|
|
3812
4405
|
},
|
|
3813
4406
|
onFocus: (e) => {
|
|
3814
4407
|
children.props.onFocus?.(e);
|
|
3815
4408
|
trackAnchor(e);
|
|
3816
4409
|
if (pointerModality()) return;
|
|
3817
4410
|
triggers.current.focus = true;
|
|
3818
|
-
|
|
3819
|
-
show();
|
|
4411
|
+
showAfterDelay(focusDelayMs);
|
|
3820
4412
|
},
|
|
3821
4413
|
onBlur: (e) => {
|
|
3822
4414
|
children.props.onBlur?.(e);
|
|
@@ -3993,7 +4585,7 @@ function HoverCard({ anchor, content, openDelayMs = 500, disabled = false, copyT
|
|
|
3993
4585
|
const copyable = copyText !== void 0;
|
|
3994
4586
|
const card = open && pos !== null && !suppressed && jsx("div", {
|
|
3995
4587
|
ref: cardRef,
|
|
3996
|
-
className: clsx(css$
|
|
4588
|
+
className: clsx(css$19.card, inline && css$19.media, copyable && css$19.copyable, copied && css$19.feedback),
|
|
3997
4589
|
style: {
|
|
3998
4590
|
...pos,
|
|
3999
4591
|
minHeight: copied && copyHeightRef.current !== null ? copyHeightRef.current : void 0
|
|
@@ -4014,14 +4606,14 @@ function HoverCard({ anchor, content, openDelayMs = 500, disabled = false, copyT
|
|
|
4014
4606
|
copy(copyText);
|
|
4015
4607
|
} : void 0,
|
|
4016
4608
|
children: copied ? jsx("span", {
|
|
4017
|
-
className: css$
|
|
4609
|
+
className: css$19.copied,
|
|
4018
4610
|
"aria-hidden": "true",
|
|
4019
4611
|
children: copiedLabel
|
|
4020
4612
|
}) : content
|
|
4021
4613
|
});
|
|
4022
4614
|
return jsxs("span", {
|
|
4023
4615
|
ref: rootRef,
|
|
4024
|
-
className: clsx(css$
|
|
4616
|
+
className: clsx(css$19.root, inline && css$19.inline),
|
|
4025
4617
|
onFocus: inline ? (event) => {
|
|
4026
4618
|
if (!disabled && event.target.matches(":focus-visible")) {
|
|
4027
4619
|
cancelClose();
|
|
@@ -4060,7 +4652,7 @@ function HoverCard({ anchor, content, openDelayMs = 500, disabled = false, copyT
|
|
|
4060
4652
|
children: anchor
|
|
4061
4653
|
}),
|
|
4062
4654
|
open && !suppressed && copyable && jsx("span", {
|
|
4063
|
-
className: css$
|
|
4655
|
+
className: css$19.status,
|
|
4064
4656
|
role: "status",
|
|
4065
4657
|
children: copied ? copiedLabel : ""
|
|
4066
4658
|
}),
|
|
@@ -4095,11 +4687,11 @@ function Modal({ open, onClose, title, closeLabel, description, children, footer
|
|
|
4095
4687
|
useModalLayer(dialog, open, onClose);
|
|
4096
4688
|
if (!open) return null;
|
|
4097
4689
|
return createPortal(jsxs("div", {
|
|
4098
|
-
className: css$
|
|
4690
|
+
className: css$20.root,
|
|
4099
4691
|
role: "presentation",
|
|
4100
4692
|
onKeyDownCapture,
|
|
4101
4693
|
children: [jsx("div", {
|
|
4102
|
-
className: css$
|
|
4694
|
+
className: css$20.mask,
|
|
4103
4695
|
style: backdropBlur ? void 0 : { backdropFilter: "none" },
|
|
4104
4696
|
"aria-hidden": "true",
|
|
4105
4697
|
onClick: onClose
|
|
@@ -4107,37 +4699,37 @@ function Modal({ open, onClose, title, closeLabel, description, children, footer
|
|
|
4107
4699
|
ref: dialog,
|
|
4108
4700
|
tabIndex: -1,
|
|
4109
4701
|
"data-shortcut-modal": shortcutModal,
|
|
4110
|
-
className: clsx(css$
|
|
4702
|
+
className: clsx(css$20.dialog, className),
|
|
4111
4703
|
role: "dialog",
|
|
4112
4704
|
"aria-modal": "true",
|
|
4113
4705
|
"aria-label": title,
|
|
4114
4706
|
children: headless ? children : jsxs(Fragment, { children: [jsxs("div", {
|
|
4115
|
-
className: clsx(css$
|
|
4707
|
+
className: clsx(css$20.content, contentClassName),
|
|
4116
4708
|
children: [
|
|
4117
4709
|
jsxs("div", {
|
|
4118
|
-
className: css$
|
|
4710
|
+
className: css$20.header,
|
|
4119
4711
|
children: [jsx("h2", {
|
|
4120
|
-
className: css$
|
|
4712
|
+
className: css$20.title,
|
|
4121
4713
|
children: title
|
|
4122
4714
|
}), jsx("button", {
|
|
4123
4715
|
type: "button",
|
|
4124
|
-
className: css$
|
|
4716
|
+
className: css$20.close,
|
|
4125
4717
|
"aria-label": closeLabel,
|
|
4126
4718
|
onClick: onClose,
|
|
4127
4719
|
children: jsx(IconCloseOutline16, { size: 14 })
|
|
4128
4720
|
})]
|
|
4129
4721
|
}),
|
|
4130
4722
|
description !== void 0 && description !== "" && jsx("p", {
|
|
4131
|
-
className: css$
|
|
4723
|
+
className: css$20.description,
|
|
4132
4724
|
children: description
|
|
4133
4725
|
}),
|
|
4134
4726
|
children !== void 0 && jsx("div", {
|
|
4135
|
-
className: css$
|
|
4727
|
+
className: css$20.body,
|
|
4136
4728
|
children
|
|
4137
4729
|
})
|
|
4138
4730
|
]
|
|
4139
4731
|
}), footer !== void 0 && jsx("div", {
|
|
4140
|
-
className: css$
|
|
4732
|
+
className: css$20.footer,
|
|
4141
4733
|
children: footer
|
|
4142
4734
|
})] })
|
|
4143
4735
|
})]
|
|
@@ -4161,13 +4753,13 @@ function OnboardingSurface({ children }) {
|
|
|
4161
4753
|
};
|
|
4162
4754
|
}, []);
|
|
4163
4755
|
return createPortal(jsxs("div", {
|
|
4164
|
-
className: css$
|
|
4756
|
+
className: css$21.onboardingOverlay,
|
|
4165
4757
|
role: "presentation",
|
|
4166
4758
|
children: [jsx("div", {
|
|
4167
|
-
className: css$
|
|
4759
|
+
className: css$21.onboardingMask,
|
|
4168
4760
|
"aria-hidden": "true"
|
|
4169
4761
|
}), jsx("div", {
|
|
4170
|
-
className: css$
|
|
4762
|
+
className: css$21.onboardingStage,
|
|
4171
4763
|
children
|
|
4172
4764
|
})]
|
|
4173
4765
|
}), document.body);
|
|
@@ -4188,28 +4780,28 @@ function RiskConfirmation({ open, title, description, acknowledgeLabel, cancelLa
|
|
|
4188
4780
|
onClose: onCancel,
|
|
4189
4781
|
title,
|
|
4190
4782
|
closeLabel,
|
|
4191
|
-
className: css$
|
|
4192
|
-
contentClassName: css$
|
|
4783
|
+
className: css$22.confirmation ?? "",
|
|
4784
|
+
contentClassName: css$22.confirmationContent ?? "",
|
|
4193
4785
|
footer: jsxs(Fragment, { children: [jsx(Button, {
|
|
4194
4786
|
variant: "outline",
|
|
4195
|
-
className: css$
|
|
4787
|
+
className: css$22.modalAction,
|
|
4196
4788
|
onClick: onCancel,
|
|
4197
4789
|
children: cancelLabel
|
|
4198
4790
|
}), jsx(Button, {
|
|
4199
4791
|
variant: "primary",
|
|
4200
|
-
className: css$
|
|
4792
|
+
className: css$22.confirmAction,
|
|
4201
4793
|
disabled: disabled || !acknowledged,
|
|
4202
4794
|
onClick: onConfirm,
|
|
4203
4795
|
children: confirmLabel
|
|
4204
4796
|
})] }),
|
|
4205
4797
|
children: [jsxs("div", {
|
|
4206
|
-
className: css$
|
|
4798
|
+
className: css$22.warning,
|
|
4207
4799
|
children: [jsx(IconWarningOutline16, {
|
|
4208
4800
|
size: 18,
|
|
4209
|
-
className: css$
|
|
4801
|
+
className: css$22.warningIcon
|
|
4210
4802
|
}), jsx("p", { children: description })]
|
|
4211
4803
|
}), jsxs("label", {
|
|
4212
|
-
className: css$
|
|
4804
|
+
className: css$22.acknowledgement,
|
|
4213
4805
|
children: [jsx("input", {
|
|
4214
4806
|
type: "checkbox",
|
|
4215
4807
|
checked: acknowledged,
|
|
@@ -4257,47 +4849,47 @@ function ConnectionIndicator({ state, disconnectedLabel, connectingLabel, recove
|
|
|
4257
4849
|
};
|
|
4258
4850
|
}, [state, rendered]);
|
|
4259
4851
|
if (rendered === void 0) return null;
|
|
4260
|
-
const leavingClass = leaving ? ` ${css$
|
|
4852
|
+
const leavingClass = leaving ? ` ${css$23.leaving}` : "";
|
|
4261
4853
|
if (rendered === "recovered") return jsxs("div", {
|
|
4262
|
-
className: `${css$
|
|
4854
|
+
className: `${css$23.indicator} ${css$23.success}${leavingClass}`,
|
|
4263
4855
|
role: "status",
|
|
4264
4856
|
"aria-label": recoveredLabel,
|
|
4265
4857
|
children: [jsx("span", {
|
|
4266
|
-
className: css$
|
|
4858
|
+
className: css$23.icon,
|
|
4267
4859
|
"aria-hidden": "true",
|
|
4268
4860
|
children: jsx(IconCheckOutline16, { size: 14 })
|
|
4269
4861
|
}), jsx("span", {
|
|
4270
|
-
className: css$
|
|
4862
|
+
className: css$23.label,
|
|
4271
4863
|
children: recoveredLabel
|
|
4272
4864
|
})]
|
|
4273
4865
|
});
|
|
4274
4866
|
const connecting = rendered === "connecting";
|
|
4275
4867
|
return jsxs("button", {
|
|
4276
4868
|
type: "button",
|
|
4277
|
-
className: `${css$
|
|
4869
|
+
className: `${css$23.indicator} ${css$23.warning}${leavingClass}`,
|
|
4278
4870
|
"data-phase": rendered,
|
|
4279
4871
|
"aria-label": connecting ? restartActionLabel : reconnectActionLabel,
|
|
4280
4872
|
onClick: onReconnect,
|
|
4281
4873
|
children: [jsx("span", {
|
|
4282
|
-
className: css$
|
|
4874
|
+
className: css$23.icon,
|
|
4283
4875
|
"aria-hidden": "true",
|
|
4284
4876
|
children: connecting ? jsx(IconLoadingOutline16, {
|
|
4285
4877
|
size: 14,
|
|
4286
|
-
className: css$
|
|
4878
|
+
className: css$23.spinner
|
|
4287
4879
|
}) : jsx(IconRefreshOutline14, { size: 14 })
|
|
4288
4880
|
}), jsx("span", {
|
|
4289
|
-
className: css$
|
|
4881
|
+
className: css$23.label,
|
|
4290
4882
|
children: connecting ? jsxs(Fragment, { children: [connectingLabel, jsxs("span", {
|
|
4291
|
-
className: css$
|
|
4883
|
+
className: css$23.dots,
|
|
4292
4884
|
"aria-hidden": "true",
|
|
4293
4885
|
children: [
|
|
4294
4886
|
jsx("span", { children: "." }),
|
|
4295
4887
|
jsx("span", {
|
|
4296
|
-
className: css$
|
|
4888
|
+
className: css$23.secondDot,
|
|
4297
4889
|
children: "."
|
|
4298
4890
|
}),
|
|
4299
4891
|
jsx("span", {
|
|
4300
|
-
className: css$
|
|
4892
|
+
className: css$23.thirdDot,
|
|
4301
4893
|
children: "."
|
|
4302
4894
|
})
|
|
4303
4895
|
]
|
|
@@ -5122,7 +5714,7 @@ function FileTypeIcon(props) {
|
|
|
5122
5714
|
type: resolvedType,
|
|
5123
5715
|
size,
|
|
5124
5716
|
className
|
|
5125
|
-
}) : glyph(resolvedType, size, clsx(css$
|
|
5717
|
+
}) : glyph(resolvedType, size, clsx(css$24.icon, css$24[resolvedType], className));
|
|
5126
5718
|
}
|
|
5127
5719
|
//#endregion
|
|
5128
5720
|
//#region lib/types/SiteGlyph.js
|
|
@@ -5435,22 +6027,772 @@ function PathLabel({ path, className, ...attributes }) {
|
|
|
5435
6027
|
return jsx("span", {
|
|
5436
6028
|
...attributes,
|
|
5437
6029
|
ref: boxRef,
|
|
5438
|
-
className: clsx(css$
|
|
6030
|
+
className: clsx(css$25.path, className),
|
|
5439
6031
|
title: path,
|
|
5440
6032
|
"data-path-label": true,
|
|
5441
6033
|
children: jsxs("span", {
|
|
5442
6034
|
ref: textRef,
|
|
5443
|
-
className: css$
|
|
6035
|
+
className: css$25.text,
|
|
5444
6036
|
children: [directory !== "" && jsx("span", {
|
|
5445
|
-
className: css$
|
|
6037
|
+
className: css$25.directory,
|
|
5446
6038
|
children: directory
|
|
5447
6039
|
}), jsx("span", {
|
|
5448
|
-
className: css$
|
|
6040
|
+
className: css$25.name,
|
|
5449
6041
|
children: name
|
|
5450
6042
|
})]
|
|
5451
6043
|
})
|
|
5452
6044
|
});
|
|
5453
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
|
+
}
|
|
5454
6796
|
//#endregion
|
|
5455
6797
|
//#region lib/types/user-text.js
|
|
5456
6798
|
/** The wire form a session chip serializes to; label is the display text. */
|
|
@@ -5466,24 +6808,35 @@ const TRAILING_PUNCTUATION_RE = /[.,;:!?,。;:!?]+$/u;
|
|
|
5466
6808
|
* (unsent queue rows pass none).
|
|
5467
6809
|
* @param slashKind - the chip kind those tokens render as.
|
|
5468
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.
|
|
5469
6812
|
* @returns inline nodes covering the whole text.
|
|
5470
6813
|
*/
|
|
5471
|
-
function projectUserText(text, sessionLabels, slashNames = [], slashKind = "skill", references) {
|
|
5472
|
-
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);
|
|
5473
6823
|
SESSION_WIRE_RE.lastIndex = 0;
|
|
5474
6824
|
let wire;
|
|
5475
|
-
while ((wire = SESSION_WIRE_RE.exec(text)) !== null)
|
|
5476
|
-
|
|
5477
|
-
|
|
5478
|
-
|
|
5479
|
-
|
|
5480
|
-
|
|
5481
|
-
|
|
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
|
+
}
|
|
5482
6835
|
for (const rawLabel of [...new Set(sessionLabels)].sort((a, b) => b.length - a.length)) {
|
|
5483
6836
|
const label = `@${rawLabel}`;
|
|
5484
6837
|
let start = text.indexOf(label);
|
|
5485
6838
|
while (start >= 0) {
|
|
5486
|
-
ranges.push({
|
|
6839
|
+
if (!maskedOver(start, start + label.length)) ranges.push({
|
|
5487
6840
|
start,
|
|
5488
6841
|
end: start + label.length,
|
|
5489
6842
|
label,
|
|
@@ -5500,6 +6853,7 @@ function projectUserText(text, sessionLabels, slashNames = [], slashKind = "skil
|
|
|
5500
6853
|
const label = rawLabel.startsWith("@\"") ? rawLabel : rawLabel.replace(TRAILING_PUNCTUATION_RE, "");
|
|
5501
6854
|
if (label.length <= 1) continue;
|
|
5502
6855
|
if (label.startsWith("/") && !slashNames.includes(label.slice(1))) continue;
|
|
6856
|
+
if (maskedOver(tokenStart, tokenStart + label.length)) continue;
|
|
5503
6857
|
ranges.push({
|
|
5504
6858
|
start: tokenStart,
|
|
5505
6859
|
end: tokenStart + label.length,
|
|
@@ -5513,27 +6867,37 @@ function projectUserText(text, sessionLabels, slashNames = [], slashKind = "skil
|
|
|
5513
6867
|
let cursor = 0;
|
|
5514
6868
|
const pushPlain = (from, to) => {
|
|
5515
6869
|
parts.push(jsx("span", {
|
|
5516
|
-
className: css$
|
|
6870
|
+
className: css$27.plainRun,
|
|
5517
6871
|
children: text.slice(from, to)
|
|
5518
6872
|
}, `t${from}`));
|
|
5519
6873
|
};
|
|
5520
6874
|
for (const range of ranges) {
|
|
5521
6875
|
if (range.start < cursor) continue;
|
|
5522
|
-
const { start: tokenStart, end
|
|
6876
|
+
const { start: tokenStart, end } = range;
|
|
5523
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;
|
|
5524
6888
|
const referenceKind = kind === "session" ? "session" : label.startsWith("@") ? label.replace(/^@"|"$/gu, "").endsWith("/") ? "folder" : "file" : void 0;
|
|
5525
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));
|
|
5526
6890
|
const contents = jsxs(Fragment, { children: [referenceKind !== void 0 && jsx(ReferenceIcon, {
|
|
5527
6891
|
kind: referenceKind,
|
|
5528
6892
|
size: 16,
|
|
5529
|
-
className: css$
|
|
6893
|
+
className: css$27.refIcon
|
|
5530
6894
|
}), displayLabel] });
|
|
5531
6895
|
const open = references === void 0 ? void 0 : referenceKind === "file" ? () => {
|
|
5532
6896
|
references.openFile(label.slice(1).replace(/^"|"$/gu, ""));
|
|
5533
6897
|
} : referenceKind === void 0 && slashKind === "skill" ? () => {
|
|
5534
6898
|
references.openSkill(label.slice(1));
|
|
5535
6899
|
} : void 0;
|
|
5536
|
-
const className = clsx(css$
|
|
6900
|
+
const className = clsx(css$27.refChip, referenceKind === void 0 && css$27.slashChip);
|
|
5537
6901
|
parts.push(open === void 0 ? jsx("span", {
|
|
5538
6902
|
className,
|
|
5539
6903
|
"data-ref-chip": referenceKind ?? slashKind,
|
|
@@ -5553,7 +6917,7 @@ function projectUserText(text, sessionLabels, slashNames = [], slashKind = "skil
|
|
|
5553
6917
|
cursor = end;
|
|
5554
6918
|
}
|
|
5555
6919
|
if (parts.length === 0) return jsx("span", {
|
|
5556
|
-
className: css$
|
|
6920
|
+
className: css$27.plainRun,
|
|
5557
6921
|
children: text
|
|
5558
6922
|
});
|
|
5559
6923
|
if (cursor < text.length) pushPlain(cursor, text.length);
|
|
@@ -5612,22 +6976,22 @@ function Toast({ text, icon, tone, anchor, holdMs = HOLD_MS, onDone }) {
|
|
|
5612
6976
|
};
|
|
5613
6977
|
}, [anchor]);
|
|
5614
6978
|
return createPortal(jsxs("div", {
|
|
5615
|
-
className: css$
|
|
6979
|
+
className: css$28.toast,
|
|
5616
6980
|
role: "alert",
|
|
5617
6981
|
style: {
|
|
5618
6982
|
...left === null ? {} : { left },
|
|
5619
6983
|
"--qilin-toast-hold": `${String(holdMs)}ms`
|
|
5620
6984
|
},
|
|
5621
6985
|
children: [tone === "success" ? jsx("span", {
|
|
5622
|
-
className: `${css$
|
|
6986
|
+
className: `${css$28.icon} ${css$28.success}`,
|
|
5623
6987
|
"aria-hidden": true,
|
|
5624
6988
|
children: jsx(IconCheckOutline16, {})
|
|
5625
6989
|
}) : icon !== void 0 && jsx("span", {
|
|
5626
|
-
className: css$
|
|
6990
|
+
className: css$28.icon,
|
|
5627
6991
|
"aria-hidden": true,
|
|
5628
6992
|
children: icon
|
|
5629
6993
|
}), jsx("span", {
|
|
5630
|
-
className: css$
|
|
6994
|
+
className: css$28.text,
|
|
5631
6995
|
children: text
|
|
5632
6996
|
})]
|
|
5633
6997
|
}), document.body);
|
|
@@ -5921,7 +7285,7 @@ function JsonCopyAction({ store, target, persistent, labels, onCopy, onClose })
|
|
|
5921
7285
|
const object = typeof target.value === "object" && target.value !== null;
|
|
5922
7286
|
const copyTitle = state === "copied" ? labels.copied : state === "failed" ? labels.copyFailed : object ? labels.copyPrettyJson : labels.copyValue;
|
|
5923
7287
|
return jsx("span", {
|
|
5924
|
-
className: css$
|
|
7288
|
+
className: css$29.copySlot,
|
|
5925
7289
|
children: (persistent || snapshot !== void 0) && jsx(Menu, {
|
|
5926
7290
|
open: snapshot?.menuOpen === true,
|
|
5927
7291
|
compact: true,
|
|
@@ -5930,7 +7294,7 @@ function JsonCopyAction({ store, target, persistent, labels, onCopy, onClose })
|
|
|
5930
7294
|
anchor: jsx("button", {
|
|
5931
7295
|
ref: buttonRef,
|
|
5932
7296
|
type: "button",
|
|
5933
|
-
className: css$
|
|
7297
|
+
className: css$29.actionButton,
|
|
5934
7298
|
"data-json-copy-button": true,
|
|
5935
7299
|
"data-state": state,
|
|
5936
7300
|
"aria-label": copyTitle,
|
|
@@ -5969,35 +7333,35 @@ function bracketOf(value) {
|
|
|
5969
7333
|
}
|
|
5970
7334
|
function previewPrimitive(value) {
|
|
5971
7335
|
if (value === null) return jsx("span", {
|
|
5972
|
-
className: css$
|
|
7336
|
+
className: css$29.keywordValue,
|
|
5973
7337
|
children: "null"
|
|
5974
7338
|
});
|
|
5975
7339
|
if (typeof value === "string") return jsx("span", {
|
|
5976
|
-
className: css$
|
|
7340
|
+
className: css$29.stringValue,
|
|
5977
7341
|
children: JSON.stringify(value)
|
|
5978
7342
|
});
|
|
5979
7343
|
if (typeof value === "number") return jsx("span", {
|
|
5980
|
-
className: css$
|
|
7344
|
+
className: css$29.numberValue,
|
|
5981
7345
|
children: String(value)
|
|
5982
7346
|
});
|
|
5983
7347
|
if (typeof value === "boolean") return jsx("span", {
|
|
5984
|
-
className: css$
|
|
7348
|
+
className: css$29.keywordValue,
|
|
5985
7349
|
children: String(value)
|
|
5986
7350
|
});
|
|
5987
7351
|
if (typeof value === "bigint") return jsx("span", {
|
|
5988
|
-
className: css$
|
|
7352
|
+
className: css$29.otherValue,
|
|
5989
7353
|
children: value.toString()
|
|
5990
7354
|
});
|
|
5991
7355
|
if (typeof value === "undefined") return jsx("span", {
|
|
5992
|
-
className: css$
|
|
7356
|
+
className: css$29.otherValue,
|
|
5993
7357
|
children: "undefined"
|
|
5994
7358
|
});
|
|
5995
7359
|
if (typeof value === "symbol") return jsx("span", {
|
|
5996
|
-
className: css$
|
|
7360
|
+
className: css$29.otherValue,
|
|
5997
7361
|
children: value.description ?? "Symbol"
|
|
5998
7362
|
});
|
|
5999
7363
|
if (typeof value === "function") return jsx("span", {
|
|
6000
|
-
className: css$
|
|
7364
|
+
className: css$29.otherValue,
|
|
6001
7365
|
children: value.name || "Function"
|
|
6002
7366
|
});
|
|
6003
7367
|
return null;
|
|
@@ -6011,71 +7375,71 @@ function previewValue(value, depth) {
|
|
|
6011
7375
|
const [open, close] = bracketOf(value);
|
|
6012
7376
|
return jsxs(Fragment, { children: [
|
|
6013
7377
|
jsx("span", {
|
|
6014
|
-
className: css$
|
|
7378
|
+
className: css$29.punctuation,
|
|
6015
7379
|
children: open
|
|
6016
7380
|
}),
|
|
6017
7381
|
depth >= PREVIEW_DEPTH_LIMIT ? jsx("span", {
|
|
6018
|
-
className: css$
|
|
7382
|
+
className: css$29.previewEllipsis,
|
|
6019
7383
|
children: "…"
|
|
6020
7384
|
}) : visible.map(([key, item], index) => jsxs("span", { children: [
|
|
6021
7385
|
index > 0 && jsx("span", {
|
|
6022
|
-
className: css$
|
|
7386
|
+
className: css$29.punctuation,
|
|
6023
7387
|
children: ", "
|
|
6024
7388
|
}),
|
|
6025
7389
|
!array && jsxs(Fragment, { children: [jsx("span", {
|
|
6026
|
-
className: css$
|
|
7390
|
+
className: css$29.previewProperty,
|
|
6027
7391
|
children: key
|
|
6028
7392
|
}), jsx("span", {
|
|
6029
|
-
className: css$
|
|
7393
|
+
className: css$29.punctuation,
|
|
6030
7394
|
children: ": "
|
|
6031
7395
|
})] }),
|
|
6032
7396
|
previewValue(item, depth + 1)
|
|
6033
7397
|
] }, key)),
|
|
6034
7398
|
depth < PREVIEW_DEPTH_LIMIT && entries.length > limit && jsx("span", {
|
|
6035
|
-
className: css$
|
|
7399
|
+
className: css$29.previewEllipsis,
|
|
6036
7400
|
children: ", …"
|
|
6037
7401
|
}),
|
|
6038
7402
|
jsx("span", {
|
|
6039
|
-
className: css$
|
|
7403
|
+
className: css$29.punctuation,
|
|
6040
7404
|
children: close
|
|
6041
7405
|
})
|
|
6042
7406
|
] });
|
|
6043
7407
|
}
|
|
6044
7408
|
function primitiveValue(value) {
|
|
6045
7409
|
if (value === null) return jsx("span", {
|
|
6046
|
-
className: css$
|
|
7410
|
+
className: css$29.keywordValue,
|
|
6047
7411
|
children: "null"
|
|
6048
7412
|
});
|
|
6049
7413
|
if (typeof value === "string") return jsx("span", {
|
|
6050
|
-
className: css$
|
|
7414
|
+
className: css$29.stringValue,
|
|
6051
7415
|
children: JSON.stringify(value)
|
|
6052
7416
|
});
|
|
6053
7417
|
if (typeof value === "boolean") return jsx("span", {
|
|
6054
|
-
className: css$
|
|
7418
|
+
className: css$29.keywordValue,
|
|
6055
7419
|
children: String(value)
|
|
6056
7420
|
});
|
|
6057
7421
|
if (typeof value === "number") return jsx("span", {
|
|
6058
|
-
className: css$
|
|
7422
|
+
className: css$29.numberValue,
|
|
6059
7423
|
children: String(value)
|
|
6060
7424
|
});
|
|
6061
7425
|
if (typeof value === "bigint") return jsx("span", {
|
|
6062
|
-
className: css$
|
|
7426
|
+
className: css$29.numberValue,
|
|
6063
7427
|
children: `${value.toString()}n`
|
|
6064
7428
|
});
|
|
6065
7429
|
if (value instanceof Date) return jsx("span", {
|
|
6066
|
-
className: css$
|
|
7430
|
+
className: css$29.otherValue,
|
|
6067
7431
|
children: value.toISOString()
|
|
6068
7432
|
});
|
|
6069
7433
|
if (typeof value === "function") return jsxs("span", {
|
|
6070
|
-
className: css$
|
|
7434
|
+
className: css$29.otherValue,
|
|
6071
7435
|
children: ["function() ", "{ }"]
|
|
6072
7436
|
});
|
|
6073
7437
|
if (typeof value === "undefined") return jsx("span", {
|
|
6074
|
-
className: css$
|
|
7438
|
+
className: css$29.otherValue,
|
|
6075
7439
|
children: "undefined"
|
|
6076
7440
|
});
|
|
6077
7441
|
return jsx("span", {
|
|
6078
|
-
className: css$
|
|
7442
|
+
className: css$29.otherValue,
|
|
6079
7443
|
children: value.toString()
|
|
6080
7444
|
});
|
|
6081
7445
|
}
|
|
@@ -6103,7 +7467,7 @@ function moveFocus(button, direction) {
|
|
|
6103
7467
|
function NodeField({ field, expandable, onToggle }) {
|
|
6104
7468
|
if (field === void 0) return null;
|
|
6105
7469
|
return jsxs("span", {
|
|
6106
|
-
className: clsx(css$
|
|
7470
|
+
className: clsx(css$29.label, expandable && css$29.clickableLabel),
|
|
6107
7471
|
onClick: expandable ? onToggle : void 0,
|
|
6108
7472
|
children: [fieldText(field), ":"]
|
|
6109
7473
|
});
|
|
@@ -6140,7 +7504,7 @@ function JsonString({ collapsedStringLines, stringWrapping, field, labels, lastE
|
|
|
6140
7504
|
if (!expanded) return;
|
|
6141
7505
|
const raw = rawRef.current;
|
|
6142
7506
|
const clips = [];
|
|
6143
|
-
const tree = raw.closest(`.${css$
|
|
7507
|
+
const tree = raw.closest(`.${css$29.root}`);
|
|
6144
7508
|
for (let parent = tree.parentElement; parent !== null; parent = parent.parentElement) if (/auto|scroll|hidden|clip/.test(getComputedStyle(parent).overflowY)) clips.push(parent);
|
|
6145
7509
|
const measure = () => {
|
|
6146
7510
|
let top = 0;
|
|
@@ -6169,33 +7533,33 @@ function JsonString({ collapsedStringLines, stringWrapping, field, labels, lastE
|
|
|
6169
7533
|
if (expanded) {
|
|
6170
7534
|
const fieldId = `${contentsId}-field`;
|
|
6171
7535
|
return jsxs("div", {
|
|
6172
|
-
className: css$
|
|
7536
|
+
className: css$29.stringField,
|
|
6173
7537
|
"data-expanded": true,
|
|
6174
7538
|
children: [
|
|
6175
7539
|
field !== void 0 && jsxs("span", {
|
|
6176
7540
|
id: fieldId,
|
|
6177
|
-
className: css$
|
|
7541
|
+
className: css$29.label,
|
|
6178
7542
|
children: [fieldText(field), ":"]
|
|
6179
7543
|
}),
|
|
6180
7544
|
jsx("pre", {
|
|
6181
7545
|
ref: rawRef,
|
|
6182
7546
|
id: contentsId,
|
|
6183
|
-
className: css$
|
|
7547
|
+
className: css$29.stringRaw,
|
|
6184
7548
|
"data-wrap": wrapped,
|
|
6185
7549
|
tabIndex: 0,
|
|
6186
7550
|
"aria-labelledby": field === void 0 ? void 0 : fieldId,
|
|
6187
7551
|
children: value
|
|
6188
7552
|
}),
|
|
6189
7553
|
!lastElement && jsx("span", {
|
|
6190
|
-
className: css$
|
|
7554
|
+
className: css$29.punctuation,
|
|
6191
7555
|
children: ","
|
|
6192
7556
|
}),
|
|
6193
7557
|
jsxs("div", {
|
|
6194
|
-
className: css$
|
|
7558
|
+
className: css$29.stringActions,
|
|
6195
7559
|
children: [
|
|
6196
7560
|
stringWrapping !== void 0 && jsx("button", {
|
|
6197
7561
|
type: "button",
|
|
6198
|
-
className: css$
|
|
7562
|
+
className: css$29.actionButton,
|
|
6199
7563
|
"aria-label": stringWrapping.label,
|
|
6200
7564
|
title: stringWrapping.label,
|
|
6201
7565
|
"aria-pressed": wrapped,
|
|
@@ -6209,7 +7573,7 @@ function JsonString({ collapsedStringLines, stringWrapping, field, labels, lastE
|
|
|
6209
7573
|
}),
|
|
6210
7574
|
jsx("button", {
|
|
6211
7575
|
type: "button",
|
|
6212
|
-
className: css$
|
|
7576
|
+
className: css$29.actionButton,
|
|
6213
7577
|
"aria-label": labels.collapseNode,
|
|
6214
7578
|
title: labels.collapseNode,
|
|
6215
7579
|
"aria-expanded": true,
|
|
@@ -6235,18 +7599,18 @@ function JsonString({ collapsedStringLines, stringWrapping, field, labels, lastE
|
|
|
6235
7599
|
});
|
|
6236
7600
|
}
|
|
6237
7601
|
return jsxs(Fragment, { children: [renderCopy?.(), jsx("span", {
|
|
6238
|
-
className: css$
|
|
7602
|
+
className: css$29.stringField,
|
|
6239
7603
|
"data-expanded": expanded,
|
|
6240
7604
|
children: jsxs("span", {
|
|
6241
7605
|
ref: contentRef,
|
|
6242
7606
|
id: contentsId,
|
|
6243
|
-
className: css$
|
|
7607
|
+
className: css$29.stringText,
|
|
6244
7608
|
children: [
|
|
6245
7609
|
truncated && jsx("span", {
|
|
6246
|
-
className: css$
|
|
7610
|
+
className: css$29.stringToggleSlot,
|
|
6247
7611
|
children: jsxs("button", {
|
|
6248
7612
|
type: "button",
|
|
6249
|
-
className: css$
|
|
7613
|
+
className: css$29.stringToggle,
|
|
6250
7614
|
"aria-label": labels.expandNode,
|
|
6251
7615
|
"aria-expanded": false,
|
|
6252
7616
|
"aria-controls": contentsId,
|
|
@@ -6261,12 +7625,12 @@ function JsonString({ collapsedStringLines, stringWrapping, field, labels, lastE
|
|
|
6261
7625
|
})
|
|
6262
7626
|
}),
|
|
6263
7627
|
field !== void 0 && jsxs("span", {
|
|
6264
|
-
className: css$
|
|
7628
|
+
className: css$29.label,
|
|
6265
7629
|
children: [fieldText(field), ":"]
|
|
6266
7630
|
}),
|
|
6267
7631
|
primitiveValue(value),
|
|
6268
7632
|
!lastElement && jsx("span", {
|
|
6269
|
-
className: css$
|
|
7633
|
+
className: css$29.punctuation,
|
|
6270
7634
|
children: ","
|
|
6271
7635
|
})
|
|
6272
7636
|
]
|
|
@@ -6297,7 +7661,7 @@ function JsonTreeNode({ collapsedStringLines, stringWrapping, field, initialExpa
|
|
|
6297
7661
|
}
|
|
6298
7662
|
};
|
|
6299
7663
|
const row = (children, ariaExpanded) => jsxs("div", {
|
|
6300
|
-
className: css$
|
|
7664
|
+
className: css$29.row,
|
|
6301
7665
|
role: "treeitem",
|
|
6302
7666
|
"aria-expanded": ariaExpanded,
|
|
6303
7667
|
onMouseOver: (event) => {
|
|
@@ -6332,7 +7696,7 @@ function JsonTreeNode({ collapsedStringLines, stringWrapping, field, initialExpa
|
|
|
6332
7696
|
}),
|
|
6333
7697
|
primitiveValue(value),
|
|
6334
7698
|
!lastElement && jsx("span", {
|
|
6335
|
-
className: css$
|
|
7699
|
+
className: css$29.punctuation,
|
|
6336
7700
|
children: ","
|
|
6337
7701
|
})
|
|
6338
7702
|
] }));
|
|
@@ -6344,22 +7708,22 @@ function JsonTreeNode({ collapsedStringLines, stringWrapping, field, initialExpa
|
|
|
6344
7708
|
onToggle: toggle
|
|
6345
7709
|
}),
|
|
6346
7710
|
jsx("span", {
|
|
6347
|
-
className: css$
|
|
7711
|
+
className: css$29.punctuation,
|
|
6348
7712
|
children: open
|
|
6349
7713
|
}),
|
|
6350
7714
|
jsx("span", {
|
|
6351
|
-
className: css$
|
|
7715
|
+
className: css$29.punctuation,
|
|
6352
7716
|
children: close
|
|
6353
7717
|
}),
|
|
6354
7718
|
!lastElement && jsx("span", {
|
|
6355
|
-
className: css$
|
|
7719
|
+
className: css$29.punctuation,
|
|
6356
7720
|
children: ","
|
|
6357
7721
|
})
|
|
6358
7722
|
] }));
|
|
6359
7723
|
return row(jsxs(Fragment, { children: [
|
|
6360
7724
|
jsx("span", {
|
|
6361
7725
|
ref: expanderRef,
|
|
6362
|
-
className: clsx(css$
|
|
7726
|
+
className: clsx(css$29.expander, expanded ? css$29.collapseIcon : css$29.expandIcon),
|
|
6363
7727
|
"data-json-expander": true,
|
|
6364
7728
|
role: "button",
|
|
6365
7729
|
"aria-label": expanded ? labels.collapseNode : labels.expandNode,
|
|
@@ -6373,7 +7737,7 @@ function JsonTreeNode({ collapsedStringLines, stringWrapping, field, initialExpa
|
|
|
6373
7737
|
onKeyDown: onExpanderKeyDown
|
|
6374
7738
|
}),
|
|
6375
7739
|
jsxs("span", {
|
|
6376
|
-
className: css$
|
|
7740
|
+
className: css$29.summary,
|
|
6377
7741
|
children: [
|
|
6378
7742
|
jsx(NodeField, {
|
|
6379
7743
|
field,
|
|
@@ -6381,11 +7745,11 @@ function JsonTreeNode({ collapsedStringLines, stringWrapping, field, initialExpa
|
|
|
6381
7745
|
onToggle: toggle
|
|
6382
7746
|
}),
|
|
6383
7747
|
jsx("span", {
|
|
6384
|
-
className: css$
|
|
7748
|
+
className: css$29.preview,
|
|
6385
7749
|
children: previewValue(value, 0)
|
|
6386
7750
|
}),
|
|
6387
7751
|
!lastElement && jsx("span", {
|
|
6388
|
-
className: css$
|
|
7752
|
+
className: css$29.punctuation,
|
|
6389
7753
|
children: ","
|
|
6390
7754
|
})
|
|
6391
7755
|
]
|
|
@@ -6393,7 +7757,7 @@ function JsonTreeNode({ collapsedStringLines, stringWrapping, field, initialExpa
|
|
|
6393
7757
|
expanded && jsx("ul", {
|
|
6394
7758
|
id: contentsId,
|
|
6395
7759
|
role: "group",
|
|
6396
|
-
className: css$
|
|
7760
|
+
className: css$29.children,
|
|
6397
7761
|
children: entries.map(([key, item], index) => jsx(JsonTreeNode, {
|
|
6398
7762
|
collapsedStringLines,
|
|
6399
7763
|
stringWrapping,
|
|
@@ -6525,17 +7889,17 @@ function JsonTree({ data, label, className, collapsedStringLines = 3, stringWrap
|
|
|
6525
7889
|
onClose: clearCopyTarget
|
|
6526
7890
|
}) : void 0;
|
|
6527
7891
|
return jsx("div", {
|
|
6528
|
-
className: clsx(css$
|
|
7892
|
+
className: clsx(css$29.root, className),
|
|
6529
7893
|
style: { "--json-tree-collapsed-lines": collapsedStringLines },
|
|
6530
7894
|
onMouseOver: handleRootMouseOver,
|
|
6531
7895
|
onMouseLeave: () => {
|
|
6532
7896
|
if (!copyStore.get()?.menuOpen) clearCopyTarget();
|
|
6533
7897
|
},
|
|
6534
7898
|
children: expandTopLevel ? jsxs("div", {
|
|
6535
|
-
className: css$
|
|
7899
|
+
className: css$29.expandedTopLevel,
|
|
6536
7900
|
children: [
|
|
6537
7901
|
jsxs("div", {
|
|
6538
|
-
className: clsx(css$
|
|
7902
|
+
className: clsx(css$29.row, css$29.topLevelBracket),
|
|
6539
7903
|
"data-json-root-row": true,
|
|
6540
7904
|
onMouseOver: (event) => {
|
|
6541
7905
|
event.stopPropagation();
|
|
@@ -6548,13 +7912,13 @@ function JsonTree({ data, label, className, collapsedStringLines = 3, stringWrap
|
|
|
6548
7912
|
path: [],
|
|
6549
7913
|
value: data
|
|
6550
7914
|
}), jsx("span", {
|
|
6551
|
-
className: css$
|
|
7915
|
+
className: css$29.punctuation,
|
|
6552
7916
|
children: rootOpen
|
|
6553
7917
|
})]
|
|
6554
7918
|
}),
|
|
6555
7919
|
jsx("div", {
|
|
6556
7920
|
"aria-label": label,
|
|
6557
|
-
className: clsx(css$
|
|
7921
|
+
className: clsx(css$29.container, css$29.expandedTopLevelContainer),
|
|
6558
7922
|
role: "tree",
|
|
6559
7923
|
children: rootEntries.map(([key, value], index) => jsx(JsonTreeNode, {
|
|
6560
7924
|
collapsedStringLines,
|
|
@@ -6572,16 +7936,16 @@ function JsonTree({ data, label, className, collapsedStringLines = 3, stringWrap
|
|
|
6572
7936
|
}, key))
|
|
6573
7937
|
}),
|
|
6574
7938
|
jsx("div", {
|
|
6575
|
-
className: clsx(css$
|
|
7939
|
+
className: clsx(css$29.row, css$29.topLevelBracket),
|
|
6576
7940
|
children: jsx("span", {
|
|
6577
|
-
className: css$
|
|
7941
|
+
className: css$29.punctuation,
|
|
6578
7942
|
children: rootClose
|
|
6579
7943
|
})
|
|
6580
7944
|
})
|
|
6581
7945
|
]
|
|
6582
7946
|
}) : jsx("div", {
|
|
6583
7947
|
"aria-label": label,
|
|
6584
|
-
className: css$
|
|
7948
|
+
className: css$29.container,
|
|
6585
7949
|
role: "tree",
|
|
6586
7950
|
children: jsx(JsonTreeNode, {
|
|
6587
7951
|
collapsedStringLines,
|
|
@@ -7097,7 +8461,7 @@ function renderLine$1(line) {
|
|
|
7097
8461
|
* @param props - see {@link TerminalBlockProps}.
|
|
7098
8462
|
* @returns the terminal block element.
|
|
7099
8463
|
*/
|
|
7100
|
-
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 }) {
|
|
7101
8465
|
const copy = labels;
|
|
7102
8466
|
const text = output ?? "";
|
|
7103
8467
|
const lines = useMemo(() => {
|
|
@@ -7110,40 +8474,41 @@ function TerminalBlock({ command, cwd, home, output, exitCode, signal, running =
|
|
|
7110
8474
|
const onToggle = useCallback(() => {
|
|
7111
8475
|
setExpanded((value) => !value);
|
|
7112
8476
|
}, []);
|
|
7113
|
-
const status = statusText(exitCode, signal, copy);
|
|
8477
|
+
const status = background ? void 0 : statusText(exitCode, signal, copy);
|
|
7114
8478
|
const state = runState(running, exitCode, signal, copy);
|
|
8479
|
+
const showState = !background || running;
|
|
7115
8480
|
const commandLines = useMemo(() => {
|
|
7116
8481
|
return (command.endsWith("\n") ? command.slice(0, -1) : command).split("\n");
|
|
7117
8482
|
}, [command]);
|
|
7118
8483
|
const empty = lines.every((line) => line.every((span) => span.text.trim() === ""));
|
|
7119
8484
|
const { hidden, capped, headLines, tailLines } = headTailCap(lines.length, maxLines, expanded);
|
|
7120
|
-
const body = !running || !empty;
|
|
8485
|
+
const body = !background && (!running || !empty);
|
|
7121
8486
|
return jsxs("div", {
|
|
7122
|
-
className: clsx(css$
|
|
8487
|
+
className: clsx(css$30.block, className),
|
|
7123
8488
|
"data-terminal": "",
|
|
7124
8489
|
"data-running": running ? "" : void 0,
|
|
7125
8490
|
"data-body": body ? "" : void 0,
|
|
7126
8491
|
children: [jsxs("div", {
|
|
7127
|
-
className: css$
|
|
8492
|
+
className: css$30.header,
|
|
7128
8493
|
children: [
|
|
7129
8494
|
jsxs("div", {
|
|
7130
|
-
className: css$
|
|
7131
|
-
children: [jsx("span", {
|
|
7132
|
-
className: css$
|
|
8495
|
+
className: css$30.prompt,
|
|
8496
|
+
children: [showState && jsx("span", {
|
|
8497
|
+
className: css$30.runStateLabel,
|
|
7133
8498
|
children: state.label
|
|
7134
8499
|
}), commandLines.map((line, index) => jsxs("div", {
|
|
7135
|
-
className: css$
|
|
8500
|
+
className: css$30.promptLine,
|
|
7136
8501
|
children: [
|
|
7137
|
-
index === 0 && jsx(StateDot, {
|
|
8502
|
+
index === 0 && showState && jsx(StateDot, {
|
|
7138
8503
|
state: state.state,
|
|
7139
|
-
className: css$
|
|
8504
|
+
className: css$30.runState
|
|
7140
8505
|
}),
|
|
7141
8506
|
jsx("span", {
|
|
7142
|
-
className: css$
|
|
8507
|
+
className: css$30.cwd,
|
|
7143
8508
|
children: index > 0 || cwd === void 0 ? "$" : promptLabel(cwd, home)
|
|
7144
8509
|
}),
|
|
7145
8510
|
jsx(CommandText, {
|
|
7146
|
-
className: css$
|
|
8511
|
+
className: css$30.command,
|
|
7147
8512
|
text: line,
|
|
7148
8513
|
label: copy.commandLine(index + 1)
|
|
7149
8514
|
})
|
|
@@ -7151,36 +8516,36 @@ function TerminalBlock({ command, cwd, home, output, exitCode, signal, running =
|
|
|
7151
8516
|
}, index))]
|
|
7152
8517
|
}),
|
|
7153
8518
|
status !== void 0 && jsx(Pill, {
|
|
7154
|
-
className: css$
|
|
8519
|
+
className: css$30.status,
|
|
7155
8520
|
children: status
|
|
7156
8521
|
}),
|
|
7157
|
-
!running && !empty && jsx("button", {
|
|
8522
|
+
!background && !running && !empty && jsx("button", {
|
|
7158
8523
|
type: "button",
|
|
7159
|
-
className: css$
|
|
8524
|
+
className: css$30.copyButton,
|
|
7160
8525
|
onClick: onCopy,
|
|
7161
8526
|
children: copied ? copy.copied : copy.copy
|
|
7162
8527
|
})
|
|
7163
8528
|
]
|
|
7164
8529
|
}), body && (empty ? jsx("div", {
|
|
7165
|
-
className: css$
|
|
8530
|
+
className: css$30.empty,
|
|
7166
8531
|
children: copy.noOutput
|
|
7167
8532
|
}) : jsxs("div", {
|
|
7168
|
-
className: css$
|
|
8533
|
+
className: css$30.output,
|
|
7169
8534
|
children: [
|
|
7170
8535
|
(capped ? lines.slice(0, headLines) : lines).map((line, index) => jsx("div", {
|
|
7171
|
-
className: css$
|
|
8536
|
+
className: css$30.line,
|
|
7172
8537
|
children: renderLine$1(line)
|
|
7173
8538
|
}, index)),
|
|
7174
8539
|
hidden > 0 && jsx("button", {
|
|
7175
8540
|
type: "button",
|
|
7176
|
-
className: css$
|
|
8541
|
+
className: css$30.expand,
|
|
7177
8542
|
"aria-expanded": expanded,
|
|
7178
8543
|
"aria-label": expanded ? copy.collapseAria : copy.expandAria(hidden),
|
|
7179
8544
|
onClick: onToggle,
|
|
7180
8545
|
children: expanded ? copy.collapse : copy.expand(hidden)
|
|
7181
8546
|
}),
|
|
7182
8547
|
capped && lines.slice(lines.length - tailLines).map((line, index) => jsx("div", {
|
|
7183
|
-
className: css$
|
|
8548
|
+
className: css$30.line,
|
|
7184
8549
|
children: renderLine$1(line)
|
|
7185
8550
|
}, index))
|
|
7186
8551
|
]
|
|
@@ -7768,51 +9133,51 @@ function ReadBlock({ label, labels, lines, totalLines, lang, maxLines = 16, clas
|
|
|
7768
9133
|
const tailLines = maxLines - headLines;
|
|
7769
9134
|
const windowed = lines.length < totalLines;
|
|
7770
9135
|
const rows = (slice) => slice.map(([line, spans]) => jsxs("div", {
|
|
7771
|
-
className: css$
|
|
9136
|
+
className: css$31.line,
|
|
7772
9137
|
children: [jsx("span", {
|
|
7773
|
-
className: css$
|
|
9138
|
+
className: css$31.gutter,
|
|
7774
9139
|
"aria-hidden": true,
|
|
7775
9140
|
children: line.number
|
|
7776
9141
|
}), jsx("span", {
|
|
7777
|
-
className: css$
|
|
9142
|
+
className: css$31.content,
|
|
7778
9143
|
children: spans === void 0 ? line.text : renderSpans(spans)
|
|
7779
9144
|
})]
|
|
7780
9145
|
}, line.number));
|
|
7781
9146
|
const paired = lines.map((line, index) => [line, highlighted?.[index]]);
|
|
7782
9147
|
return jsxs("div", {
|
|
7783
9148
|
ref: rootRef,
|
|
7784
|
-
className: clsx(css$
|
|
9149
|
+
className: clsx(css$31.block, className),
|
|
7785
9150
|
"data-read": "",
|
|
7786
9151
|
children: [jsxs("div", {
|
|
7787
|
-
className: css$
|
|
9152
|
+
className: css$31.banner,
|
|
7788
9153
|
children: [jsx("div", {
|
|
7789
|
-
className: css$
|
|
9154
|
+
className: css$31.label,
|
|
7790
9155
|
children: label ?? ""
|
|
7791
9156
|
}), jsxs("div", {
|
|
7792
|
-
className: css$
|
|
9157
|
+
className: css$31.action,
|
|
7793
9158
|
children: [
|
|
7794
9159
|
windowed && jsx("span", {
|
|
7795
|
-
className: css$
|
|
9160
|
+
className: css$31.count,
|
|
7796
9161
|
children: labels.window(lines.length, totalLines)
|
|
7797
9162
|
}),
|
|
7798
9163
|
jsx("span", {
|
|
7799
|
-
className: css$
|
|
9164
|
+
className: css$31.lang,
|
|
7800
9165
|
children: lang ?? ""
|
|
7801
9166
|
}),
|
|
7802
9167
|
lines.length > 0 && jsx("button", {
|
|
7803
9168
|
type: "button",
|
|
7804
|
-
className: css$
|
|
9169
|
+
className: css$31.copyButton,
|
|
7805
9170
|
onClick: onCopy,
|
|
7806
9171
|
children: copied ? labels.copied : labels.copy
|
|
7807
9172
|
})
|
|
7808
9173
|
]
|
|
7809
9174
|
})]
|
|
7810
9175
|
}), jsxs("div", {
|
|
7811
|
-
className: css$
|
|
9176
|
+
className: css$31.body,
|
|
7812
9177
|
children: [
|
|
7813
9178
|
rows(capped ? paired.slice(0, headLines) : paired),
|
|
7814
9179
|
hidden > 0 && jsx(FoldToggle, {
|
|
7815
|
-
className: css$
|
|
9180
|
+
className: css$31.expand,
|
|
7816
9181
|
expanded,
|
|
7817
9182
|
hidden,
|
|
7818
9183
|
labels,
|
|
@@ -7834,11 +9199,11 @@ function assertNever(value) {
|
|
|
7834
9199
|
}
|
|
7835
9200
|
/** The dim class per row kind (path/gap chrome vs the diff's own +/- colors). */
|
|
7836
9201
|
const ROW_CLASS = {
|
|
7837
|
-
path: css$
|
|
7838
|
-
del: css$
|
|
7839
|
-
add: css$
|
|
7840
|
-
context: css$
|
|
7841
|
-
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
|
|
7842
9207
|
};
|
|
7843
9208
|
/** Bound synchronous edit-graph search; one replacement consumes two edits. */
|
|
7844
9209
|
const MAX_DIFF_EDIT_LENGTH = 256;
|
|
@@ -7976,37 +9341,37 @@ function DiffBlock({ diffs, labels, maxLines = 16, className }) {
|
|
|
7976
9341
|
const head = capped ? rows.slice(0, headLines) : rows;
|
|
7977
9342
|
const tail = capped ? rows.slice(rows.length - tailLines) : [];
|
|
7978
9343
|
return jsxs("div", {
|
|
7979
|
-
className: clsx(css$
|
|
9344
|
+
className: clsx(css$32.block, className),
|
|
7980
9345
|
"data-diff": "",
|
|
7981
9346
|
children: [
|
|
7982
9347
|
jsx("button", {
|
|
7983
9348
|
type: "button",
|
|
7984
|
-
className: css$
|
|
9349
|
+
className: css$32.copyButton,
|
|
7985
9350
|
onClick: onCopy,
|
|
7986
9351
|
children: copied ? labels.copied : labels.copy
|
|
7987
9352
|
}),
|
|
7988
9353
|
jsxs("div", {
|
|
7989
|
-
className: css$
|
|
9354
|
+
className: css$32.body,
|
|
7990
9355
|
children: [
|
|
7991
9356
|
head.map((row, index) => jsx("div", {
|
|
7992
|
-
className: clsx(css$
|
|
9357
|
+
className: clsx(css$32.line, ROW_CLASS[row.kind]),
|
|
7993
9358
|
children: row.text
|
|
7994
9359
|
}, index)),
|
|
7995
9360
|
hidden > 0 && jsx(FoldToggle, {
|
|
7996
|
-
className: css$
|
|
9361
|
+
className: css$32.expand,
|
|
7997
9362
|
expanded,
|
|
7998
9363
|
hidden,
|
|
7999
9364
|
labels,
|
|
8000
9365
|
onToggle
|
|
8001
9366
|
}),
|
|
8002
9367
|
tail.map((row, index) => jsx("div", {
|
|
8003
|
-
className: clsx(css$
|
|
9368
|
+
className: clsx(css$32.line, ROW_CLASS[row.kind]),
|
|
8004
9369
|
children: row.text
|
|
8005
9370
|
}, index))
|
|
8006
9371
|
]
|
|
8007
9372
|
}),
|
|
8008
9373
|
jsxs("div", {
|
|
8009
|
-
className: css$
|
|
9374
|
+
className: css$32.footer,
|
|
8010
9375
|
children: [
|
|
8011
9376
|
"└ +",
|
|
8012
9377
|
added,
|
|
@@ -8142,56 +9507,56 @@ function SearchBlock(props) {
|
|
|
8142
9507
|
const tail = tailHeader === void 0 ? naturalTail : naturalTail.slice(1);
|
|
8143
9508
|
const renderRow = (row) => {
|
|
8144
9509
|
if (row.type === "path") return jsx("div", {
|
|
8145
|
-
className: css$
|
|
9510
|
+
className: css$33.line,
|
|
8146
9511
|
children: row.path
|
|
8147
9512
|
});
|
|
8148
9513
|
if (row.type === "match") return jsxs("div", {
|
|
8149
|
-
className: css$
|
|
9514
|
+
className: css$33.line,
|
|
8150
9515
|
children: [jsxs("span", {
|
|
8151
|
-
className: css$
|
|
9516
|
+
className: css$33.lineNumber,
|
|
8152
9517
|
children: [row.lineNumber, ": "]
|
|
8153
9518
|
}), row.line]
|
|
8154
9519
|
});
|
|
8155
9520
|
return jsxs("button", {
|
|
8156
9521
|
type: "button",
|
|
8157
|
-
className: css$
|
|
9522
|
+
className: css$33.fileHeader,
|
|
8158
9523
|
"aria-expanded": !row.collapsed,
|
|
8159
9524
|
onClick: () => {
|
|
8160
9525
|
toggleFile(row.index);
|
|
8161
9526
|
},
|
|
8162
9527
|
children: [jsx("span", {
|
|
8163
|
-
className: css$
|
|
9528
|
+
className: css$33.filePath,
|
|
8164
9529
|
children: row.path
|
|
8165
9530
|
}), jsx("span", {
|
|
8166
|
-
className: css$
|
|
9531
|
+
className: css$33.fileCount,
|
|
8167
9532
|
children: row.count
|
|
8168
9533
|
})]
|
|
8169
9534
|
});
|
|
8170
9535
|
};
|
|
8171
9536
|
return jsxs("div", {
|
|
8172
|
-
className: clsx(css$
|
|
9537
|
+
className: clsx(css$33.block, className),
|
|
8173
9538
|
"data-search": props.kind,
|
|
8174
9539
|
children: [jsxs("div", {
|
|
8175
|
-
className: css$
|
|
9540
|
+
className: css$33.header,
|
|
8176
9541
|
children: [jsx("span", {
|
|
8177
|
-
className: css$
|
|
9542
|
+
className: css$33.summary,
|
|
8178
9543
|
children: summaryText(props, shown, truncated, total)
|
|
8179
9544
|
}), !empty && jsx("button", {
|
|
8180
9545
|
type: "button",
|
|
8181
|
-
className: css$
|
|
9546
|
+
className: css$33.copyButton,
|
|
8182
9547
|
onClick: onCopy,
|
|
8183
9548
|
children: copied ? props.labels.copied : props.labels.copy
|
|
8184
9549
|
})]
|
|
8185
9550
|
}), empty ? jsx("div", {
|
|
8186
|
-
className: css$
|
|
9551
|
+
className: css$33.empty,
|
|
8187
9552
|
children: props.labels.noResults
|
|
8188
9553
|
}) : jsxs("div", {
|
|
8189
|
-
className: css$
|
|
9554
|
+
className: css$33.body,
|
|
8190
9555
|
children: [
|
|
8191
9556
|
head.map((row) => jsx("div", { children: renderRow(row) }, rowKey(row))),
|
|
8192
9557
|
hidden > 0 && jsx("button", {
|
|
8193
9558
|
type: "button",
|
|
8194
|
-
className: css$
|
|
9559
|
+
className: css$33.expand,
|
|
8195
9560
|
"aria-expanded": expanded,
|
|
8196
9561
|
"aria-label": expanded ? props.labels.collapseAria : props.labels.expandAria(hidden),
|
|
8197
9562
|
onClick: onToggle,
|
|
@@ -9019,7 +10384,7 @@ function CodeBlock({ code, lang, streaming, className, contentRef, lineNumbers =
|
|
|
9019
10384
|
});
|
|
9020
10385
|
}, [copied, trimmed]);
|
|
9021
10386
|
const body = streamedBody !== void 0 ? streamedBody : html === void 0 ? jsx("pre", {
|
|
9022
|
-
className: css$
|
|
10387
|
+
className: css$34.plain,
|
|
9023
10388
|
children: jsx("code", { children: sourceLines === void 0 ? trimmed : sourceLines.map((line, index) => jsxs(Fragment$1, { children: [index > 0 && "\n", jsx("span", {
|
|
9024
10389
|
className: "line",
|
|
9025
10390
|
children: line
|
|
@@ -9027,22 +10392,22 @@ function CodeBlock({ code, lang, streaming, className, contentRef, lineNumbers =
|
|
|
9027
10392
|
}) : jsx("div", { dangerouslySetInnerHTML: { __html: html } });
|
|
9028
10393
|
return jsxs("div", {
|
|
9029
10394
|
ref: rootRef,
|
|
9030
|
-
className: clsx(css$
|
|
10395
|
+
className: clsx(css$34.block, "md-code-block", lineNumbers && css$34.numbered, className),
|
|
9031
10396
|
"data-line-numbers": lineNumbers || void 0,
|
|
9032
10397
|
style: sourceLines === void 0 ? void 0 : { "--dsl-code-block-line-number-width": `${Math.max(2, String(sourceLines.length).length)}ch` },
|
|
9033
10398
|
children: [showHeader && jsx("div", {
|
|
9034
|
-
className: css$
|
|
10399
|
+
className: css$34.bannerWrap,
|
|
9035
10400
|
children: jsxs("div", {
|
|
9036
|
-
className: css$
|
|
10401
|
+
className: css$34.banner,
|
|
9037
10402
|
"data-code-block-banner": true,
|
|
9038
10403
|
children: [jsx("div", {
|
|
9039
|
-
className: css$
|
|
10404
|
+
className: css$34.infostring,
|
|
9040
10405
|
children: lang ?? ""
|
|
9041
10406
|
}), jsx("div", {
|
|
9042
|
-
className: css$
|
|
10407
|
+
className: css$34.action,
|
|
9043
10408
|
children: jsx("button", {
|
|
9044
10409
|
type: "button",
|
|
9045
|
-
className: css$
|
|
10410
|
+
className: css$34.copyButton,
|
|
9046
10411
|
onClick: onCopy,
|
|
9047
10412
|
children: copied ? copiedLabel : copyLabel
|
|
9048
10413
|
})
|
|
@@ -9050,7 +10415,7 @@ function CodeBlock({ code, lang, streaming, className, contentRef, lineNumbers =
|
|
|
9050
10415
|
})
|
|
9051
10416
|
}), jsx("div", {
|
|
9052
10417
|
ref: contentRef,
|
|
9053
|
-
className: css$
|
|
10418
|
+
className: css$34.content,
|
|
9054
10419
|
"data-code-block-content": true,
|
|
9055
10420
|
children: body
|
|
9056
10421
|
})]
|
|
@@ -9201,15 +10566,15 @@ function MermaidDiagram({ code, copyLabel, copiedLabel, diagramLabel, enlargedLa
|
|
|
9201
10566
|
};
|
|
9202
10567
|
}, [code, domId]);
|
|
9203
10568
|
if (state.status === "loading") return jsx("div", {
|
|
9204
|
-
className: css$
|
|
10569
|
+
className: css$35.stage,
|
|
9205
10570
|
"data-mermaid-loading": true,
|
|
9206
10571
|
"aria-hidden": "true"
|
|
9207
10572
|
});
|
|
9208
10573
|
if (state.status === "error") return jsxs("div", {
|
|
9209
|
-
className: css$
|
|
10574
|
+
className: css$35.error,
|
|
9210
10575
|
role: "alert",
|
|
9211
10576
|
children: [jsx("span", {
|
|
9212
|
-
className: css$
|
|
10577
|
+
className: css$35.errorLine,
|
|
9213
10578
|
children: state.message
|
|
9214
10579
|
}), jsx(CodeBlock, {
|
|
9215
10580
|
code: `${code}\n`,
|
|
@@ -9218,7 +10583,7 @@ function MermaidDiagram({ code, copyLabel, copiedLabel, diagramLabel, enlargedLa
|
|
|
9218
10583
|
})]
|
|
9219
10584
|
});
|
|
9220
10585
|
const stage = jsx("div", {
|
|
9221
|
-
className: css$
|
|
10586
|
+
className: css$35.stage,
|
|
9222
10587
|
"data-mermaid-diagram": true,
|
|
9223
10588
|
dangerouslySetInnerHTML: { __html: state.svg },
|
|
9224
10589
|
onClick: () => {
|
|
@@ -9233,13 +10598,13 @@ function MermaidDiagram({ code, copyLabel, copiedLabel, diagramLabel, enlargedLa
|
|
|
9233
10598
|
});
|
|
9234
10599
|
if (zoom === null) return stage;
|
|
9235
10600
|
return jsxs(Fragment, { children: [stage, createPortal(jsx("div", {
|
|
9236
|
-
className: css$
|
|
10601
|
+
className: css$35.zoomOverlay,
|
|
9237
10602
|
onClick: () => {
|
|
9238
10603
|
setZoom(null);
|
|
9239
10604
|
},
|
|
9240
10605
|
role: "presentation",
|
|
9241
10606
|
children: jsx("div", {
|
|
9242
|
-
className: css$
|
|
10607
|
+
className: css$35.zoomStage,
|
|
9243
10608
|
dangerouslySetInnerHTML: { __html: zoom },
|
|
9244
10609
|
onClick: (event) => {
|
|
9245
10610
|
event.stopPropagation();
|
|
@@ -9432,31 +10797,34 @@ function ImageLightbox({ src, alt, labels, onClose }) {
|
|
|
9432
10797
|
restoreRef.current?.focus();
|
|
9433
10798
|
};
|
|
9434
10799
|
}, [onClose]);
|
|
9435
|
-
return createPortal(
|
|
9436
|
-
className: css$
|
|
10800
|
+
return createPortal(jsx("div", {
|
|
10801
|
+
className: css$36.backdrop,
|
|
9437
10802
|
role: "dialog",
|
|
9438
10803
|
"aria-modal": "true",
|
|
9439
10804
|
"aria-label": labels.dialog,
|
|
9440
|
-
children:
|
|
9441
|
-
|
|
9442
|
-
|
|
9443
|
-
"
|
|
9444
|
-
|
|
9445
|
-
|
|
9446
|
-
|
|
9447
|
-
|
|
9448
|
-
|
|
9449
|
-
|
|
9450
|
-
|
|
9451
|
-
|
|
9452
|
-
|
|
9453
|
-
|
|
9454
|
-
|
|
9455
|
-
|
|
9456
|
-
|
|
9457
|
-
|
|
9458
|
-
|
|
9459
|
-
|
|
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
|
+
})
|
|
9460
10828
|
}), document.body);
|
|
9461
10829
|
}
|
|
9462
10830
|
//#endregion
|
|
@@ -9478,14 +10846,14 @@ function ImagePreview({ src, alt, loadingLabel, failedLabel }) {
|
|
|
9478
10846
|
function Preview({ src, alt, loadingLabel, failedLabel }) {
|
|
9479
10847
|
const [state, setState] = useState("loading");
|
|
9480
10848
|
return jsxs("span", {
|
|
9481
|
-
className: css$
|
|
10849
|
+
className: css$37.frame,
|
|
9482
10850
|
children: [state !== "failed" && jsx("img", {
|
|
9483
10851
|
src,
|
|
9484
10852
|
alt,
|
|
9485
10853
|
loading: "lazy",
|
|
9486
10854
|
decoding: "async",
|
|
9487
10855
|
referrerPolicy: "no-referrer",
|
|
9488
|
-
className: css$
|
|
10856
|
+
className: css$37.image,
|
|
9489
10857
|
"data-ready": state === "ready" || void 0,
|
|
9490
10858
|
onLoad: () => {
|
|
9491
10859
|
setState("ready");
|
|
@@ -9494,7 +10862,7 @@ function Preview({ src, alt, loadingLabel, failedLabel }) {
|
|
|
9494
10862
|
setState("failed");
|
|
9495
10863
|
}
|
|
9496
10864
|
}), state !== "ready" && jsxs("span", {
|
|
9497
|
-
className: css$
|
|
10865
|
+
className: css$37.status,
|
|
9498
10866
|
role: "status",
|
|
9499
10867
|
children: [state === "loading" && jsx(IconLoadingOutline16, { size: 16 }), jsx("span", { children: state === "loading" ? loadingLabel : failedLabel })]
|
|
9500
10868
|
})]
|
|
@@ -10265,7 +11633,7 @@ function SafeLink({ url, label, className }) {
|
|
|
10265
11633
|
children: [jsx(LinkIcon, {
|
|
10266
11634
|
kind: "url",
|
|
10267
11635
|
href,
|
|
10268
|
-
className: css$
|
|
11636
|
+
className: css$38.linkIcon
|
|
10269
11637
|
}), label]
|
|
10270
11638
|
});
|
|
10271
11639
|
}
|
|
@@ -10280,20 +11648,20 @@ function SafeLink({ url, label, className }) {
|
|
|
10280
11648
|
*/
|
|
10281
11649
|
function SourceItem({ source, ordinal }) {
|
|
10282
11650
|
return jsxs("li", {
|
|
10283
|
-
className: css$
|
|
11651
|
+
className: css$38.source,
|
|
10284
11652
|
value: ordinal,
|
|
10285
11653
|
children: [
|
|
10286
11654
|
jsx(SafeLink, {
|
|
10287
11655
|
url: source.url,
|
|
10288
11656
|
label: linkLabel(source.url, source.title),
|
|
10289
|
-
className: css$
|
|
11657
|
+
className: css$38.sourceLink
|
|
10290
11658
|
}),
|
|
10291
11659
|
source.snippet !== void 0 && source.snippet !== "" && jsx("div", {
|
|
10292
|
-
className: css$
|
|
11660
|
+
className: css$38.snippet,
|
|
10293
11661
|
children: source.snippet
|
|
10294
11662
|
}),
|
|
10295
11663
|
source.publishedAt !== void 0 && source.publishedAt !== "" && jsx("div", {
|
|
10296
|
-
className: css$
|
|
11664
|
+
className: css$38.published,
|
|
10297
11665
|
children: source.publishedAt
|
|
10298
11666
|
})
|
|
10299
11667
|
]
|
|
@@ -10308,28 +11676,28 @@ function SourceItem({ source, ordinal }) {
|
|
|
10308
11676
|
function WebSearchBlock({ answer, sources, truncated, labels, className }) {
|
|
10309
11677
|
const empty = (answer === void 0 || answer === "") && sources.length === 0;
|
|
10310
11678
|
return jsxs("div", {
|
|
10311
|
-
className: clsx(css$
|
|
11679
|
+
className: clsx(css$38.block, className),
|
|
10312
11680
|
"data-web": "search",
|
|
10313
11681
|
children: [
|
|
10314
11682
|
answer !== void 0 && answer !== "" && jsx("div", {
|
|
10315
|
-
className: css$
|
|
11683
|
+
className: css$38.answer,
|
|
10316
11684
|
children: jsx(MarkdownText, {
|
|
10317
11685
|
text: answer,
|
|
10318
11686
|
labels: labels.markdown
|
|
10319
11687
|
})
|
|
10320
11688
|
}),
|
|
10321
11689
|
empty ? jsx("div", {
|
|
10322
|
-
className: css$
|
|
11690
|
+
className: css$38.empty,
|
|
10323
11691
|
children: labels.noResults
|
|
10324
11692
|
}) : jsx("ol", {
|
|
10325
|
-
className: css$
|
|
11693
|
+
className: css$38.sources,
|
|
10326
11694
|
children: sources.map((source, index) => jsx(SourceItem, {
|
|
10327
11695
|
source,
|
|
10328
11696
|
ordinal: index + 1
|
|
10329
11697
|
}, index))
|
|
10330
11698
|
}),
|
|
10331
11699
|
truncated && jsx("div", {
|
|
10332
|
-
className: css$
|
|
11700
|
+
className: css$38.truncated,
|
|
10333
11701
|
children: labels.sourcesTruncated
|
|
10334
11702
|
})
|
|
10335
11703
|
]
|
|
@@ -10342,23 +11710,23 @@ function WebSearchBlock({ answer, sources, truncated, labels, className }) {
|
|
|
10342
11710
|
*/
|
|
10343
11711
|
function WebFetchBlock({ url, statusCode, truncated, labels, className }) {
|
|
10344
11712
|
return jsxs("div", {
|
|
10345
|
-
className: clsx(css$
|
|
11713
|
+
className: clsx(css$38.block, css$38.fetch, className),
|
|
10346
11714
|
"data-web": "fetch",
|
|
10347
11715
|
children: [jsx(SafeLink, {
|
|
10348
11716
|
url,
|
|
10349
11717
|
label: url,
|
|
10350
|
-
className: css$
|
|
11718
|
+
className: css$38.fetchUrl
|
|
10351
11719
|
}), jsxs("div", {
|
|
10352
|
-
className: css$
|
|
11720
|
+
className: css$38.fetchMeta,
|
|
10353
11721
|
children: [jsxs("span", {
|
|
10354
|
-
className: css$
|
|
11722
|
+
className: css$38.status,
|
|
10355
11723
|
children: [
|
|
10356
11724
|
labels.http,
|
|
10357
11725
|
" ",
|
|
10358
11726
|
statusCode
|
|
10359
11727
|
]
|
|
10360
11728
|
}), truncated && jsx("span", {
|
|
10361
|
-
className: css$
|
|
11729
|
+
className: css$38.truncated,
|
|
10362
11730
|
children: labels.contentTruncated
|
|
10363
11731
|
})]
|
|
10364
11732
|
})]
|
|
@@ -10392,10 +11760,10 @@ function JsonBlock({ label, payload, defaultOpen = false, truncatedLabel }) {
|
|
|
10392
11760
|
truncatedLabel
|
|
10393
11761
|
]);
|
|
10394
11762
|
return jsxs("div", {
|
|
10395
|
-
className: css$
|
|
11763
|
+
className: css$39.root,
|
|
10396
11764
|
children: [jsxs("button", {
|
|
10397
11765
|
type: "button",
|
|
10398
|
-
className: css$
|
|
11766
|
+
className: css$39.toggle,
|
|
10399
11767
|
onClick: () => {
|
|
10400
11768
|
setOpen((v) => !v);
|
|
10401
11769
|
},
|
|
@@ -10405,7 +11773,7 @@ function JsonBlock({ label, payload, defaultOpen = false, truncatedLabel }) {
|
|
|
10405
11773
|
label
|
|
10406
11774
|
]
|
|
10407
11775
|
}), open && jsx("pre", {
|
|
10408
|
-
className: css$
|
|
11776
|
+
className: css$39.body,
|
|
10409
11777
|
children: body
|
|
10410
11778
|
})]
|
|
10411
11779
|
});
|
|
@@ -10495,17 +11863,17 @@ function MenuGroup({ label, children }) {
|
|
|
10495
11863
|
role: "group",
|
|
10496
11864
|
"aria-labelledby": headingId,
|
|
10497
11865
|
"data-menu-group": "",
|
|
10498
|
-
className: css$
|
|
11866
|
+
className: css$40.group,
|
|
10499
11867
|
children: [
|
|
10500
11868
|
jsx("span", {
|
|
10501
11869
|
"aria-hidden": "true",
|
|
10502
11870
|
"data-menu-group-start": "",
|
|
10503
|
-
className: css$
|
|
11871
|
+
className: css$40.start
|
|
10504
11872
|
}),
|
|
10505
11873
|
jsx("div", {
|
|
10506
11874
|
id: headingId,
|
|
10507
11875
|
"data-menu-group-heading": "",
|
|
10508
|
-
className: css$
|
|
11876
|
+
className: css$40.heading,
|
|
10509
11877
|
children: label
|
|
10510
11878
|
}),
|
|
10511
11879
|
children
|
|
@@ -10601,47 +11969,6 @@ function observeStickyMenuGroups(viewport) {
|
|
|
10601
11969
|
};
|
|
10602
11970
|
}
|
|
10603
11971
|
//#endregion
|
|
10604
|
-
|
|
10605
|
-
/** Shared menu material and the macOS backing that lets Chromium blur transparent windows. */
|
|
10606
|
-
/**
|
|
10607
|
-
* Paint a menu and, on macOS, an opaque backing behind the page content within its bounds.
|
|
10608
|
-
* CSS anchors keep each backing aligned during placement, resizing, and nested-menu movement.
|
|
10609
|
-
* @param props - Div content and placement, and compact geometry.
|
|
10610
|
-
* @param ref - The visible menu div, excluding the non-interactive backing.
|
|
10611
|
-
* @returns Menu content plus a backing portal removed with the menu.
|
|
10612
|
-
*/
|
|
10613
|
-
const MenuSurface = forwardRef(function MenuSurface({ compact = false, className, style, children, ...props }, ref) {
|
|
10614
|
-
const id = useId();
|
|
10615
|
-
const backingRef = useRef(null);
|
|
10616
|
-
useLayoutEffect(() => {
|
|
10617
|
-
document.body.appendChild(backingRef.current);
|
|
10618
|
-
}, []);
|
|
10619
|
-
const anchorStyle = { "--dsh-menu-anchor": `--dsh-menu-${id.replaceAll(":", "")}` };
|
|
10620
|
-
return jsxs(Fragment, { children: [jsxs("div", {
|
|
10621
|
-
...props,
|
|
10622
|
-
ref,
|
|
10623
|
-
"data-menu-material": "translucent",
|
|
10624
|
-
className: clsx(css$37.surface, compact && css$37.compact, className),
|
|
10625
|
-
style: {
|
|
10626
|
-
...style,
|
|
10627
|
-
...anchorStyle
|
|
10628
|
-
},
|
|
10629
|
-
children: [jsx("div", {
|
|
10630
|
-
"aria-hidden": "true",
|
|
10631
|
-
className: css$37.material
|
|
10632
|
-
}), children]
|
|
10633
|
-
}), createPortal(jsx("div", {
|
|
10634
|
-
ref: backingRef,
|
|
10635
|
-
"aria-hidden": "true",
|
|
10636
|
-
"data-menu-backing": "",
|
|
10637
|
-
className: clsx(css$37.backing, compact && css$37.compact),
|
|
10638
|
-
style: {
|
|
10639
|
-
...anchorStyle,
|
|
10640
|
-
visibility: style?.visibility
|
|
10641
|
-
}
|
|
10642
|
-
}), document.body)] });
|
|
10643
|
-
});
|
|
10644
|
-
//#endregion
|
|
10645
|
-
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, IconBrowseOutline16, IconCheckOutline14, IconCheckOutline16, IconChecklistOutline14, IconChevronDownOutline14, IconChevronLeftOutline14, IconChevronRightOutline14, IconChevronUpOutline14, IconClockOutline16, IconCloseFill14, IconCloseOutline16, IconCodeOutline16, IconCompactOutline16, IconContextInjectionOutline16, IconCopyOutline16, IconCordisPluginOutline14, IconDarkOutline16, IconDataOutline16, IconDatabaseOutline16, IconDislikeFill16, IconDislikeOutline16, IconDownloadOutline16, IconEditOutline16, IconEllipsisOutline16, IconEnhanceOutline16, IconFolderClose16, IconFolderOpen16, IconFolderOpenOutline16, IconFollowsystemOutline16, IconFullscreenOutline16, IconGaugeOutline16, IconGlobeOutline14, IconGoalOutline16, IconInfoOutline14, IconInspectOutline12, IconLightOutline16, IconLikeFill16, IconLikeOutline16, IconLinkOutline14, IconLinkOutline16, IconListPenOutline16, IconLoadingOutline16, IconLogoutOutline16, IconMicrophoneOutline16, IconNewChatOutline16, IconPanelLeftOutline16, IconPaperPlaneOutline14, IconPaperclipOutline16, IconPauseOutline16, IconPersonalizationOutline16, IconPinFillRegular, IconPinOutlineRegular, IconPlanOutline14, IconPlayOutline16, IconPluginPinwheelOutline16, IconPlusOutline16, IconProjectAddOutline16, IconQuestionOutline14, IconQueueOutline14, IconRefreshOutline14, IconRefreshOutline16, IconRightUpOutline14, IconRightUpOutline16, IconSearchOutline16, IconSendOutline14, IconSendOutline16, IconSettingsOutline14, IconSettingsOutline16, IconShareOutline16, IconShieldOutline16, IconSkillOutline16, IconSparkle16, IconStopFill16, IconTerminalOutline16, IconThinkOutline14, IconThinkOutline16, IconTrashOutline16, IconTreeCorner8x10, IconTriangleRightFill14, IconUserOutline16, IconWarningOutline16, 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 };
|
|
10646
11973
|
|
|
10647
11974
|
//# sourceMappingURL=index.js.map
|