@deepseek-ai/dsh-client-ui-primitives 0.1.7-alpha.2 → 0.1.7-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.i18n.yaml +60 -5
- package/README.md +27 -10
- package/README.zh.md +27 -10
- package/lib/Button.module.css +6 -8
- package/lib/Checkbox.module.css +1 -1
- package/lib/CodeCard.module.css +3 -3
- package/lib/ConnectionIndicator.module.css +6 -2
- package/lib/HoverCard.module.css +17 -8
- package/lib/ImageLightbox.module.css +46 -0
- package/lib/ImagePreview.module.css +24 -0
- package/lib/Input.module.css +2 -2
- package/lib/JsonTree.module.css +3 -3
- package/lib/Menu.module.css +22 -18
- package/lib/MenuSurface.module.css +49 -0
- package/lib/Modal.module.css +27 -6
- package/lib/Pill.module.css +2 -1
- package/lib/RiskConfirmation.module.css +1 -1
- package/lib/SearchBlock.module.css +1 -1
- package/lib/SegmentedControl.module.css +9 -9
- package/lib/SegmentedTabs.module.css +3 -3
- package/lib/ShortcutKeys.module.css +33 -0
- package/lib/Switch.module.css +3 -8
- package/lib/TerminalBlock.module.css +3 -3
- package/lib/Toast.module.css +2 -2
- package/lib/Tooltip.module.css +9 -1
- package/lib/WebBlock.module.css +1 -1
- package/lib/index.js +1592 -825
- package/lib/markdown/CodeBlock.module.css +1 -1
- package/lib/markdown/JsonBlock.module.css +2 -2
- package/lib/markdown/MarkdownText.module.css +28 -5
- package/lib/settings-form/SettingsForm.module.css +2 -2
- package/lib/settings-form/fields.module.css +4 -4
- package/lib/types/Button.d.ts +6 -5
- package/lib/types/HoverCard.d.ts +5 -2
- package/lib/types/ImageLightbox.d.ts +27 -0
- package/lib/types/ImagePreview.d.ts +12 -0
- package/lib/types/Menu.d.ts +9 -1
- package/lib/types/MenuSurface.d.ts +16 -0
- package/lib/types/Modal.d.ts +12 -4
- package/lib/types/ShortcutKeys.d.ts +11 -0
- package/lib/types/Tooltip.d.ts +15 -4
- package/lib/types/code-highlighting.d.ts +1 -8
- package/lib/types/focus.d.ts +9 -0
- package/lib/types/guide-artwork.d.ts +15 -0
- package/lib/types/icons/index.d.ts +8 -4
- package/lib/types/icons/shared-artwork.d.ts +8 -1
- package/lib/types/index.d.ts +9 -1
- package/lib/types/input-modality.d.ts +19 -0
- package/lib/types/keyboard-composition.d.ts +11 -0
- package/lib/types/markdown/MarkdownDelegate.d.ts +11 -1
- package/lib/types/markdown/highlight.d.ts +16 -10
- package/lib/types/markdown/local-image-syntax.d.ts +10 -0
- package/lib/types/plugin-artwork.d.ts +1 -1
- package/lib/types/settings-form/fields.d.ts +1 -0
- package/lib/types/useModalLayer.d.ts +27 -0
- package/package.json +4 -3
- package/lib/OnboardingSurface.module.css +0 -28
- package/lib/types/OnboardingSurface.d.ts +0 -11
package/lib/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import clsx from "clsx";
|
|
3
3
|
import css from "./StateDot.module.css";
|
|
4
|
-
import { Fragment as Fragment$1, cloneElement, createContext, createElement, memo, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
4
|
+
import { Fragment as Fragment$1, cloneElement, createContext, createElement, forwardRef, memo, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
5
5
|
import css$1 from "./TextShimmer.module.css";
|
|
6
6
|
import css$2 from "./DisclosureRow.module.css";
|
|
7
7
|
import css$3 from "./Button.module.css";
|
|
@@ -15,34 +15,36 @@ import css$9 from "./SegmentedControl.module.css";
|
|
|
15
15
|
import css$10 from "./Checkbox.module.css";
|
|
16
16
|
import css$11 from "./Input.module.css";
|
|
17
17
|
import { createPortal } from "react-dom";
|
|
18
|
-
import css$12 from "./
|
|
19
|
-
import css$13 from "./
|
|
20
|
-
import css$14 from "./
|
|
21
|
-
import css$15 from "./
|
|
22
|
-
import css$16 from "./
|
|
23
|
-
import css$17 from "./
|
|
24
|
-
import css$18 from "./
|
|
18
|
+
import css$12 from "./ShortcutKeys.module.css";
|
|
19
|
+
import css$13 from "./MenuSurface.module.css";
|
|
20
|
+
import css$14 from "./Menu.module.css";
|
|
21
|
+
import css$15 from "./Tooltip.module.css";
|
|
22
|
+
import css$16 from "./HoverCard.module.css";
|
|
23
|
+
import css$17 from "./Modal.module.css";
|
|
24
|
+
import css$18 from "./RiskConfirmation.module.css";
|
|
25
|
+
import css$19 from "./ConnectionIndicator.module.css";
|
|
26
|
+
import css$20 from "./FileTypeIcon.module.css";
|
|
25
27
|
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";
|
|
26
|
-
import css$
|
|
28
|
+
import css$21 from "./user-text.module.css";
|
|
27
29
|
import markdownCss from "./markdown/MarkdownText.module.css";
|
|
28
|
-
import css$
|
|
29
|
-
import css$
|
|
30
|
-
import css$
|
|
31
|
-
import css$23 from "./settings-form/fields.module.css";
|
|
30
|
+
import css$22 from "./Toast.module.css";
|
|
31
|
+
import css$23 from "./settings-form/SettingsForm.module.css";
|
|
32
|
+
import css$24 from "./settings-form/fields.module.css";
|
|
32
33
|
import { createSnapshotStore } from "@deepseek-ai/dsh-client-store";
|
|
33
34
|
import { createCssVariablesTheme, createHighlighterCoreSync } from "shiki/core";
|
|
34
35
|
import { createJavaScriptRegexEngine, defaultJavaScriptRegexConstructor } from "shiki/engine/javascript";
|
|
35
36
|
import langTs from "@shikijs/langs/typescript";
|
|
36
37
|
import langBash from "@shikijs/langs/shellscript";
|
|
37
38
|
import langJson from "@shikijs/langs/json";
|
|
38
|
-
import
|
|
39
|
+
import { CODE_HIGHLIGHT_EXTENSIONS, languageForPath } from "@deepseek-ai/dsh-util-code-language";
|
|
40
|
+
import css$25 from "./JsonTree.module.css";
|
|
39
41
|
import Anser from "anser";
|
|
40
|
-
import css$
|
|
42
|
+
import css$26 from "./TerminalBlock.module.css";
|
|
41
43
|
import cardCss from "./CodeCard.module.css";
|
|
42
|
-
import css$
|
|
44
|
+
import css$27 from "./ReadBlock.module.css";
|
|
43
45
|
import { structuredPatch } from "diff";
|
|
44
|
-
import css$
|
|
45
|
-
import css$
|
|
46
|
+
import css$28 from "./DiffBlock.module.css";
|
|
47
|
+
import css$29 from "./SearchBlock.module.css";
|
|
46
48
|
import { fromMarkdown } from "mdast-util-from-markdown";
|
|
47
49
|
import { gfmFromMarkdown } from "mdast-util-gfm";
|
|
48
50
|
import { mathFromMarkdown } from "mdast-util-math";
|
|
@@ -54,14 +56,16 @@ import { classifyCharacter } from "micromark-util-classify-character";
|
|
|
54
56
|
import { codes, constants, types } from "micromark-util-symbol";
|
|
55
57
|
import { factorySpace } from "micromark-factory-space";
|
|
56
58
|
import { normalizeUri } from "micromark-util-sanitize-uri";
|
|
57
|
-
import css$
|
|
59
|
+
import css$30 from "./markdown/CodeBlock.module.css";
|
|
58
60
|
import katex from "katex";
|
|
61
|
+
import css$31 from "./ImageLightbox.module.css";
|
|
62
|
+
import css$32 from "./ImagePreview.module.css";
|
|
59
63
|
import "katex/dist/katex.min.css";
|
|
60
|
-
import css$
|
|
61
|
-
import css$
|
|
64
|
+
import css$33 from "./WebBlock.module.css";
|
|
65
|
+
import css$34 from "./markdown/JsonBlock.module.css";
|
|
62
66
|
//#region lib/types/icons/shared-artwork.js
|
|
63
67
|
/**
|
|
64
|
-
* Render
|
|
68
|
+
* Render new-conversation geometry — the bubble around a plus — for product icons.
|
|
65
69
|
* @param props - Size, optional CSS class, and inherited stroke width.
|
|
66
70
|
* @returns The decorative SVG artwork.
|
|
67
71
|
*/
|
|
@@ -90,6 +94,36 @@ const NewChatOutlineArtwork = ({ size = 16, className, strokeWidth }) => jsxs("s
|
|
|
90
94
|
]
|
|
91
95
|
});
|
|
92
96
|
/**
|
|
97
|
+
* Render shared conversation geometry — the chat bubble around two text
|
|
98
|
+
* lines — for the queue product icon and session reference icons.
|
|
99
|
+
* @param props - Size, optional CSS class, and inherited stroke width.
|
|
100
|
+
* @returns The decorative SVG artwork.
|
|
101
|
+
*/
|
|
102
|
+
const ChatLinesOutlineArtwork = ({ size = 16, className, strokeWidth }) => jsxs("svg", {
|
|
103
|
+
width: size,
|
|
104
|
+
height: size,
|
|
105
|
+
className,
|
|
106
|
+
viewBox: "0 0 16 16",
|
|
107
|
+
fill: "none",
|
|
108
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
109
|
+
"aria-hidden": "true",
|
|
110
|
+
strokeWidth,
|
|
111
|
+
children: [
|
|
112
|
+
jsx("path", {
|
|
113
|
+
d: "M5 6.75H11",
|
|
114
|
+
stroke: "currentColor"
|
|
115
|
+
}),
|
|
116
|
+
jsx("path", {
|
|
117
|
+
d: "M5 9H8",
|
|
118
|
+
stroke: "currentColor"
|
|
119
|
+
}),
|
|
120
|
+
jsx("path", {
|
|
121
|
+
d: "M2.37067 11.2497C1.5872 9.89252 1.32042 8.29798 1.61945 6.7597C1.91847 5.22141 2.76317 3.84293 3.99801 2.87809C5.23285 1.91325 6.7747 1.427 8.33964 1.50888C9.90458 1.59076 11.3873 2.23526 12.5147 3.32369C13.6422 4.41232 14.3384 5.8717 14.4751 7.43304C14.6118 8.99438 14.1797 10.5525 13.2585 11.8205C12.3372 13.0885 10.9889 13.9809 9.4617 14.3334C8.18666 14.6277 6.8587 14.529 5.64964 14.0601C5.17095 13.8745 4.76937 13.4929 4.26509 13.3963C3.67389 13.2832 2.95232 13.5595 2.0377 14.3334",
|
|
122
|
+
stroke: "currentColor"
|
|
123
|
+
})
|
|
124
|
+
]
|
|
125
|
+
});
|
|
126
|
+
/**
|
|
93
127
|
* Render shared globe geometry for product and link icons.
|
|
94
128
|
* @param props - Size, optional CSS class, and inherited stroke width.
|
|
95
129
|
* @returns The decorative SVG artwork.
|
|
@@ -205,6 +239,10 @@ const FolderCloseArtwork = ({ size = 16, className, strokeWidth }) => jsxs("svg"
|
|
|
205
239
|
});
|
|
206
240
|
//#endregion
|
|
207
241
|
//#region lib/types/icons/index.js
|
|
242
|
+
/**
|
|
243
|
+
* Shared current-color product icons. Names identify the glyph and weight;
|
|
244
|
+
* rendered size remains a prop instead of part of the component name.
|
|
245
|
+
*/
|
|
208
246
|
/** Shared shield contour used by composite icons outside this module. */
|
|
209
247
|
const SHIELD_OUTLINE_PATH = "M6.80132 2.14853C7.70663 1.80917 8.70422 1.80919 9.60952 2.14859L14.1296 3.84317V7.11961C14.1296 11.6089 10.7615 13.5975 8.20543 14.5779C5.64931 13.5975 2.28052 11.6089 2.28052 7.11961V3.84317L6.80132 2.14853Z";
|
|
210
248
|
/** Regular stroke width used by the product icon set. */
|
|
@@ -1243,10 +1281,10 @@ const IconUserOutlineArtwork = ({ size = 16, className, strokeWidth }) => jsxs("
|
|
|
1243
1281
|
"aria-hidden": "true",
|
|
1244
1282
|
strokeWidth,
|
|
1245
1283
|
children: [jsx("path", {
|
|
1246
|
-
d: "M8 8.
|
|
1284
|
+
d: "M8 8.25C9.51878 8.25 10.75 7.01878 10.75 5.5C10.75 3.98122 9.51878 2.75 8 2.75C6.48122 2.75 5.25 3.98122 5.25 5.5C5.25 7.01878 6.48122 8.25 8 8.25Z",
|
|
1247
1285
|
stroke: "currentColor"
|
|
1248
1286
|
}), jsx("path", {
|
|
1249
|
-
d: "
|
|
1287
|
+
d: "M2.5 14.5C2.5 11.5 5.25 10.25 8 10.25C10.75 10.25 13.5 11.5 13.5 14.5",
|
|
1250
1288
|
stroke: "currentColor"
|
|
1251
1289
|
})]
|
|
1252
1290
|
});
|
|
@@ -1260,6 +1298,44 @@ const IconUserOutlineMedium = (props) => jsx(IconUserOutlineArtwork, {
|
|
|
1260
1298
|
...props,
|
|
1261
1299
|
strokeWidth: ICON_MEDIUM_STROKE
|
|
1262
1300
|
});
|
|
1301
|
+
const IconUsersOutlineArtwork = ({ size = 16, className, strokeWidth }) => jsxs("svg", {
|
|
1302
|
+
width: size,
|
|
1303
|
+
height: size,
|
|
1304
|
+
className,
|
|
1305
|
+
viewBox: "0 0 16 16",
|
|
1306
|
+
fill: "none",
|
|
1307
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1308
|
+
"aria-hidden": "true",
|
|
1309
|
+
strokeWidth,
|
|
1310
|
+
children: [
|
|
1311
|
+
jsx("path", {
|
|
1312
|
+
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",
|
|
1313
|
+
stroke: "currentColor"
|
|
1314
|
+
}),
|
|
1315
|
+
jsx("path", {
|
|
1316
|
+
d: "M1 14.5C1 11.5 3.5 10.25 6 10.25C8.5 10.25 11 11.5 11 14.5",
|
|
1317
|
+
stroke: "currentColor"
|
|
1318
|
+
}),
|
|
1319
|
+
jsx("path", {
|
|
1320
|
+
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",
|
|
1321
|
+
stroke: "currentColor"
|
|
1322
|
+
}),
|
|
1323
|
+
jsx("path", {
|
|
1324
|
+
d: "M12.4 10.6C13.9 11.3 15 12.6 15 14.5",
|
|
1325
|
+
stroke: "currentColor"
|
|
1326
|
+
})
|
|
1327
|
+
]
|
|
1328
|
+
});
|
|
1329
|
+
/** Regular one-pixel IconUsersOutline artwork: a front person with a second person behind. */
|
|
1330
|
+
const IconUsersOutlineRegular = (props) => jsx(IconUsersOutlineArtwork, {
|
|
1331
|
+
...props,
|
|
1332
|
+
strokeWidth: 1
|
|
1333
|
+
});
|
|
1334
|
+
/** Medium IconUsersOutline artwork with a 1.3px stroke. */
|
|
1335
|
+
const IconUsersOutlineMedium = (props) => jsx(IconUsersOutlineArtwork, {
|
|
1336
|
+
...props,
|
|
1337
|
+
strokeWidth: ICON_MEDIUM_STROKE
|
|
1338
|
+
});
|
|
1263
1339
|
const IconPaperPlaneOutlineArtwork = ({ size = 14, className, strokeWidth }) => jsxs("svg", {
|
|
1264
1340
|
width: size,
|
|
1265
1341
|
height: size,
|
|
@@ -1953,10 +2029,10 @@ const IconClockOutlineArtwork = ({ size = 16, className, strokeWidth }) => jsxs(
|
|
|
1953
2029
|
"aria-hidden": "true",
|
|
1954
2030
|
strokeWidth,
|
|
1955
2031
|
children: [jsx("path", {
|
|
1956
|
-
d: "M8
|
|
2032
|
+
d: "M8 14C11.3137 14 14 11.3137 14 8C14 4.68629 11.3137 2 8 2C4.68629 2 2 4.68629 2 8C2 11.3137 4.68629 14 8 14Z",
|
|
1957
2033
|
stroke: "currentColor"
|
|
1958
2034
|
}), jsx("path", {
|
|
1959
|
-
d: "M8
|
|
2035
|
+
d: "M8 4.31V8.46L11 10.08",
|
|
1960
2036
|
stroke: "currentColor"
|
|
1961
2037
|
})]
|
|
1962
2038
|
});
|
|
@@ -2031,29 +2107,9 @@ const IconSendOutlineMedium = (props) => jsx(IconSendOutlineArtwork, {
|
|
|
2031
2107
|
...props,
|
|
2032
2108
|
strokeWidth: ICON_MEDIUM_STROKE
|
|
2033
2109
|
});
|
|
2034
|
-
const IconQueueOutlineArtwork = ({ size = 14,
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
className,
|
|
2038
|
-
viewBox: "0 0 16 16",
|
|
2039
|
-
fill: "none",
|
|
2040
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
2041
|
-
"aria-hidden": "true",
|
|
2042
|
-
strokeWidth,
|
|
2043
|
-
children: [
|
|
2044
|
-
jsx("path", {
|
|
2045
|
-
d: "M5 6.75H11",
|
|
2046
|
-
stroke: "currentColor"
|
|
2047
|
-
}),
|
|
2048
|
-
jsx("path", {
|
|
2049
|
-
d: "M5 9H8",
|
|
2050
|
-
stroke: "currentColor"
|
|
2051
|
-
}),
|
|
2052
|
-
jsx("path", {
|
|
2053
|
-
d: "M2.37067 11.2497C1.5872 9.89252 1.32042 8.29798 1.61945 6.7597C1.91847 5.22141 2.76317 3.84293 3.99801 2.87809C5.23285 1.91325 6.7747 1.427 8.33964 1.50888C9.90458 1.59076 11.3873 2.23526 12.5147 3.32369C13.6422 4.41232 14.3384 5.8717 14.4751 7.43304C14.6118 8.99438 14.1797 10.5525 13.2585 11.8205C12.3372 13.0885 10.9889 13.9809 9.4617 14.3334C8.18666 14.6277 6.8587 14.529 5.64964 14.0601C5.17095 13.8745 4.76937 13.4929 4.26509 13.3963C3.67389 13.2832 2.95232 13.5595 2.0377 14.3334",
|
|
2054
|
-
stroke: "currentColor"
|
|
2055
|
-
})
|
|
2056
|
-
]
|
|
2110
|
+
const IconQueueOutlineArtwork = ({ size = 14, ...rest }) => jsx(ChatLinesOutlineArtwork, {
|
|
2111
|
+
size,
|
|
2112
|
+
...rest
|
|
2057
2113
|
});
|
|
2058
2114
|
/** Regular one-pixel IconQueueOutline artwork. */
|
|
2059
2115
|
const IconQueueOutlineRegular = (props) => jsx(IconQueueOutlineArtwork, {
|
|
@@ -2826,6 +2882,64 @@ const IconChevronsUpDownOutlineMedium = (props) => jsx(IconChevronsUpDownOutline
|
|
|
2826
2882
|
...props,
|
|
2827
2883
|
strokeWidth: ICON_MEDIUM_STROKE
|
|
2828
2884
|
});
|
|
2885
|
+
const IconArchiveOffOutlineArtwork = ({ size = 16, className, strokeWidth }) => {
|
|
2886
|
+
const maskId = `dsh-archive-off-${useId().replaceAll(":", "")}`;
|
|
2887
|
+
return jsxs("svg", {
|
|
2888
|
+
width: size,
|
|
2889
|
+
height: size,
|
|
2890
|
+
className,
|
|
2891
|
+
viewBox: "0 0 16 16",
|
|
2892
|
+
fill: "none",
|
|
2893
|
+
stroke: "currentColor",
|
|
2894
|
+
strokeLinecap: "round",
|
|
2895
|
+
strokeLinejoin: "round",
|
|
2896
|
+
"aria-hidden": "true",
|
|
2897
|
+
strokeWidth,
|
|
2898
|
+
children: [
|
|
2899
|
+
jsxs("mask", {
|
|
2900
|
+
id: maskId,
|
|
2901
|
+
maskUnits: "userSpaceOnUse",
|
|
2902
|
+
x: "0",
|
|
2903
|
+
y: "0",
|
|
2904
|
+
width: "16",
|
|
2905
|
+
height: "16",
|
|
2906
|
+
children: [jsx("rect", {
|
|
2907
|
+
x: "0",
|
|
2908
|
+
y: "0",
|
|
2909
|
+
width: "16",
|
|
2910
|
+
height: "16",
|
|
2911
|
+
fill: "white",
|
|
2912
|
+
stroke: "none"
|
|
2913
|
+
}), jsx("path", {
|
|
2914
|
+
d: "m2.2 1.3 11.6 12.8",
|
|
2915
|
+
stroke: "black",
|
|
2916
|
+
strokeWidth: strokeWidth + 3
|
|
2917
|
+
})]
|
|
2918
|
+
}),
|
|
2919
|
+
jsxs("g", {
|
|
2920
|
+
mask: `url(#${maskId})`,
|
|
2921
|
+
children: [jsx("rect", {
|
|
2922
|
+
x: "1.9",
|
|
2923
|
+
y: "2.1",
|
|
2924
|
+
width: "12.2",
|
|
2925
|
+
height: "3.4",
|
|
2926
|
+
rx: "1.1"
|
|
2927
|
+
}), jsx("path", { d: "M2.95 5.7v4.8a2.9 2.9 0 0 0 2.9 2.9h4.3a2.9 2.9 0 0 0 2.9-2.9V5.7" })]
|
|
2928
|
+
}),
|
|
2929
|
+
jsx("path", { d: "m2.2 1.3 11.6 12.8" })
|
|
2930
|
+
]
|
|
2931
|
+
});
|
|
2932
|
+
};
|
|
2933
|
+
/** Regular one-pixel IconArchiveOffOutline artwork. */
|
|
2934
|
+
const IconArchiveOffOutlineRegular = (props) => jsx(IconArchiveOffOutlineArtwork, {
|
|
2935
|
+
...props,
|
|
2936
|
+
strokeWidth: 1
|
|
2937
|
+
});
|
|
2938
|
+
/** Medium IconArchiveOffOutline artwork with a 1.3px stroke. */
|
|
2939
|
+
const IconArchiveOffOutlineMedium = (props) => jsx(IconArchiveOffOutlineArtwork, {
|
|
2940
|
+
...props,
|
|
2941
|
+
strokeWidth: ICON_MEDIUM_STROKE
|
|
2942
|
+
});
|
|
2829
2943
|
const IconArchiveCheckOutlineArtwork = ({ size = 16, className, strokeWidth }) => jsxs("svg", {
|
|
2830
2944
|
width: size,
|
|
2831
2945
|
height: size,
|
|
@@ -3057,12 +3171,14 @@ const DisclosureRow = memo(function DisclosureRow({ icon, title, open, expandabl
|
|
|
3057
3171
|
/**
|
|
3058
3172
|
* Render a button.
|
|
3059
3173
|
* @param props.variant - visual family (default 'ghost').
|
|
3060
|
-
* @param props.size - 'md' 36px
|
|
3174
|
+
* @param props.size - 'md' 36px control with 12px corners or 'sm' 28px control with 8px corners.
|
|
3061
3175
|
* @param props.icon - optional leading 16px icon node.
|
|
3176
|
+
* @param ref - native button for focus management and overlay anchors.
|
|
3062
3177
|
* @returns the button element; native button attributes pass through.
|
|
3063
3178
|
*/
|
|
3064
|
-
function Button({ variant = "ghost", size = "md", icon, className, children, ...rest }) {
|
|
3179
|
+
const Button = forwardRef(function Button({ variant = "ghost", size = "md", icon, className, children, ...rest }, ref) {
|
|
3065
3180
|
return jsxs("button", {
|
|
3181
|
+
ref,
|
|
3066
3182
|
type: "button",
|
|
3067
3183
|
className: clsx(css$3.button, css$3[variant], css$3[size], className),
|
|
3068
3184
|
...rest,
|
|
@@ -3071,7 +3187,7 @@ function Button({ variant = "ghost", size = "md", icon, className, children, ...
|
|
|
3071
3187
|
children: icon
|
|
3072
3188
|
}), children]
|
|
3073
3189
|
});
|
|
3074
|
-
}
|
|
3190
|
+
});
|
|
3075
3191
|
//#endregion
|
|
3076
3192
|
//#region lib/types/Pill.js
|
|
3077
3193
|
/**
|
|
@@ -3432,6 +3548,234 @@ function usePointerGrace(close) {
|
|
|
3432
3548
|
};
|
|
3433
3549
|
}
|
|
3434
3550
|
//#endregion
|
|
3551
|
+
//#region lib/types/keyboard-composition.js
|
|
3552
|
+
/** Composition lifetime for local keyboard handlers, including a late closing keydown. */
|
|
3553
|
+
/**
|
|
3554
|
+
* Observe composition until its closing key is released or consumed.
|
|
3555
|
+
* @param document - document whose input events belong to the caller.
|
|
3556
|
+
* @returns an event guard and a disposer for all listeners.
|
|
3557
|
+
*/
|
|
3558
|
+
function observeComposition(document) {
|
|
3559
|
+
let composing = false;
|
|
3560
|
+
let ended = false;
|
|
3561
|
+
const start = () => {
|
|
3562
|
+
composing = true;
|
|
3563
|
+
};
|
|
3564
|
+
const end = () => {
|
|
3565
|
+
composing = false;
|
|
3566
|
+
ended = true;
|
|
3567
|
+
};
|
|
3568
|
+
const release = () => {
|
|
3569
|
+
ended = false;
|
|
3570
|
+
};
|
|
3571
|
+
const blur = () => {
|
|
3572
|
+
composing = false;
|
|
3573
|
+
ended = false;
|
|
3574
|
+
};
|
|
3575
|
+
document.addEventListener("compositionstart", start, true);
|
|
3576
|
+
document.addEventListener("compositionend", end, true);
|
|
3577
|
+
document.addEventListener("keyup", release, true);
|
|
3578
|
+
document.defaultView?.addEventListener("blur", blur);
|
|
3579
|
+
return {
|
|
3580
|
+
guards: (event) => {
|
|
3581
|
+
const guarded = composing || ended || event.isComposing || event.keyCode === 229;
|
|
3582
|
+
ended = false;
|
|
3583
|
+
return guarded;
|
|
3584
|
+
},
|
|
3585
|
+
dispose: () => {
|
|
3586
|
+
document.removeEventListener("compositionstart", start, true);
|
|
3587
|
+
document.removeEventListener("compositionend", end, true);
|
|
3588
|
+
document.removeEventListener("keyup", release, true);
|
|
3589
|
+
document.defaultView?.removeEventListener("blur", blur);
|
|
3590
|
+
}
|
|
3591
|
+
};
|
|
3592
|
+
}
|
|
3593
|
+
//#endregion
|
|
3594
|
+
//#region lib/types/focus.js
|
|
3595
|
+
/** Focus presentation for automatic entry and restoration. */
|
|
3596
|
+
const releases = /* @__PURE__ */ new WeakMap();
|
|
3597
|
+
const navigationKeys = new Set([
|
|
3598
|
+
"Tab",
|
|
3599
|
+
"ArrowUp",
|
|
3600
|
+
"ArrowDown",
|
|
3601
|
+
"ArrowLeft",
|
|
3602
|
+
"ArrowRight",
|
|
3603
|
+
"Home",
|
|
3604
|
+
"End"
|
|
3605
|
+
]);
|
|
3606
|
+
/**
|
|
3607
|
+
* Focus an automatic destination without a focus outline until keyboard navigation or blur.
|
|
3608
|
+
* The theme suppresses outlines while data-dsh-automatic-focus is present; borders and shadows remain intact.
|
|
3609
|
+
* Tab and directional navigation restore normal focus styling.
|
|
3610
|
+
* @param element - control or container receiving automatic focus.
|
|
3611
|
+
* @param options - browser focus options, including scroll preservation.
|
|
3612
|
+
*/
|
|
3613
|
+
function focusWithoutRing(element, options) {
|
|
3614
|
+
releases.get(element)?.();
|
|
3615
|
+
const release = () => {
|
|
3616
|
+
element.removeAttribute("data-dsh-automatic-focus");
|
|
3617
|
+
element.removeEventListener("blur", release);
|
|
3618
|
+
element.removeEventListener("keydown", navigate, true);
|
|
3619
|
+
releases.delete(element);
|
|
3620
|
+
};
|
|
3621
|
+
const navigate = (event) => {
|
|
3622
|
+
if (!event.isComposing && !event.ctrlKey && !event.altKey && !event.metaKey && navigationKeys.has(event.key)) release();
|
|
3623
|
+
};
|
|
3624
|
+
releases.set(element, release);
|
|
3625
|
+
element.setAttribute("data-dsh-automatic-focus", "");
|
|
3626
|
+
element.addEventListener("blur", release);
|
|
3627
|
+
element.addEventListener("keydown", navigate, true);
|
|
3628
|
+
element.focus(options);
|
|
3629
|
+
if (!element.matches(":focus")) release();
|
|
3630
|
+
}
|
|
3631
|
+
//#endregion
|
|
3632
|
+
//#region lib/types/useModalLayer.js
|
|
3633
|
+
/** Shared modal keyboard ownership and focus lifetime. */
|
|
3634
|
+
/** Dialog and menu elements whose document order determines foreground shortcut ownership. */
|
|
3635
|
+
const modalSelector = "[role=\"dialog\"][aria-modal=\"true\"], [role=\"menu\"]";
|
|
3636
|
+
const layers = /* @__PURE__ */ new WeakMap();
|
|
3637
|
+
/**
|
|
3638
|
+
* Request closure of the foreground registered modal using its current onClose callback.
|
|
3639
|
+
* A newer menu or unregistered dialog blocks dismissal of the modal behind it.
|
|
3640
|
+
* @param document - product document whose modal owns the close command.
|
|
3641
|
+
*/
|
|
3642
|
+
function closeTopModal(document) {
|
|
3643
|
+
const top = layers.get(document)?.at(-1);
|
|
3644
|
+
if (top === void 0) return;
|
|
3645
|
+
if ([...document.querySelectorAll("[role=\"dialog\"][aria-modal=\"true\"], [role=\"menu\"]")].at(-1) === top.element) top.close();
|
|
3646
|
+
}
|
|
3647
|
+
/**
|
|
3648
|
+
* Whether an anchor belongs behind the current modal and must yield keyboard input.
|
|
3649
|
+
* @param anchor - local control owning the input handler.
|
|
3650
|
+
* @returns true when another modal owns the foreground.
|
|
3651
|
+
*/
|
|
3652
|
+
function isBehindModal(anchor) {
|
|
3653
|
+
if (anchor === null) return false;
|
|
3654
|
+
const top = layers.get(anchor.ownerDocument)?.at(-1);
|
|
3655
|
+
return top !== void 0 && !top.element.contains(anchor);
|
|
3656
|
+
}
|
|
3657
|
+
const focusable = "button:not(:disabled), input:not(:disabled), textarea:not(:disabled), select:not(:disabled), a[href], [tabindex=\"0\"]";
|
|
3658
|
+
/**
|
|
3659
|
+
* Give only the top modal Escape and Tab ownership, then restore its previous focus.
|
|
3660
|
+
* Automatic entry and return focus omit outlines; keyboard traversal retains its indicators.
|
|
3661
|
+
* Controls mounted with the dialog use data-modal-autofocus for initial focus;
|
|
3662
|
+
* React autoFocus runs before this layer can capture the invoking control.
|
|
3663
|
+
* Local menus handle their Escape during capture before this bubble listener.
|
|
3664
|
+
* @param dialog - mounted dialog element.
|
|
3665
|
+
* @param open - whether this layer is active.
|
|
3666
|
+
* @param onClose - top-layer Escape or application close action.
|
|
3667
|
+
*/
|
|
3668
|
+
function useModalLayer(dialog, open, onClose) {
|
|
3669
|
+
const close = useRef(onClose);
|
|
3670
|
+
close.current = onClose;
|
|
3671
|
+
useLayoutEffect(() => {
|
|
3672
|
+
const element = dialog.current;
|
|
3673
|
+
if (!open || element === null) return;
|
|
3674
|
+
const document = element.ownerDocument;
|
|
3675
|
+
const composition = observeComposition(document);
|
|
3676
|
+
const previous = document.activeElement;
|
|
3677
|
+
const stack = layers.get(document) ?? [];
|
|
3678
|
+
layers.set(document, stack);
|
|
3679
|
+
const layer = {
|
|
3680
|
+
element,
|
|
3681
|
+
close: () => {
|
|
3682
|
+
close.current();
|
|
3683
|
+
}
|
|
3684
|
+
};
|
|
3685
|
+
stack.push(layer);
|
|
3686
|
+
const initial = element.querySelector("[data-modal-autofocus]") ?? element.querySelector(focusable) ?? element;
|
|
3687
|
+
if (!element.contains(document.activeElement)) focusWithoutRing(initial);
|
|
3688
|
+
const keydown = (event) => {
|
|
3689
|
+
const composing = composition.guards(event);
|
|
3690
|
+
if (stack.at(-1) !== layer || event.defaultPrevented || composing || event.ctrlKey || event.altKey || event.metaKey) return;
|
|
3691
|
+
if (event.key === "Escape" && !event.shiftKey) {
|
|
3692
|
+
event.preventDefault();
|
|
3693
|
+
if (!event.repeat) close.current();
|
|
3694
|
+
}
|
|
3695
|
+
if (event.key !== "Tab") return;
|
|
3696
|
+
if (document.activeElement?.closest("[role=\"menu\"]")) return;
|
|
3697
|
+
const items = [...element.querySelectorAll(focusable)].filter((item) => !item.closest("[inert], [hidden]"));
|
|
3698
|
+
const first = items[0] ?? element;
|
|
3699
|
+
const last = items.at(-1) ?? element;
|
|
3700
|
+
const atEdge = event.shiftKey ? document.activeElement === first : document.activeElement === last;
|
|
3701
|
+
if (document.activeElement === element || !element.contains(document.activeElement) || atEdge) {
|
|
3702
|
+
event.preventDefault();
|
|
3703
|
+
(event.shiftKey ? last : first).focus();
|
|
3704
|
+
}
|
|
3705
|
+
};
|
|
3706
|
+
document.addEventListener("keydown", keydown);
|
|
3707
|
+
return () => {
|
|
3708
|
+
composition.dispose();
|
|
3709
|
+
const wasTop = stack.at(-1) === layer;
|
|
3710
|
+
stack.splice(stack.indexOf(layer), 1);
|
|
3711
|
+
document.removeEventListener("keydown", keydown);
|
|
3712
|
+
if (stack.length === 0) layers.delete(document);
|
|
3713
|
+
if (wasTop) {
|
|
3714
|
+
const target = previous instanceof HTMLElement && previous.isConnected ? previous : stack.at(-1)?.element;
|
|
3715
|
+
if (target !== void 0) focusWithoutRing(target);
|
|
3716
|
+
}
|
|
3717
|
+
};
|
|
3718
|
+
}, [dialog, open]);
|
|
3719
|
+
}
|
|
3720
|
+
//#endregion
|
|
3721
|
+
//#region lib/types/ShortcutKeys.js
|
|
3722
|
+
/** Shared shortcut keycaps; callers supply the effective platform presentation. */
|
|
3723
|
+
/**
|
|
3724
|
+
* Render one command's keycaps without owning binding defaults or localized copy.
|
|
3725
|
+
* @param props - effective key labels, presentation variant and optional interaction styling.
|
|
3726
|
+
* @returns unboxed keys by default, or tooltip keycaps with plus-separated combinations grouped together.
|
|
3727
|
+
*/
|
|
3728
|
+
function ShortcutKeys({ keys, variant = "plain", className }) {
|
|
3729
|
+
return jsx("span", {
|
|
3730
|
+
className: clsx(css$12.keys, variant === "tooltip" && css$12.tooltip, variant === "tooltip" && keys.includes("+") && css$12.joined, className),
|
|
3731
|
+
children: keys.map((key, index) => jsx("kbd", {
|
|
3732
|
+
className: key === "+" ? css$12.separator : css$12.key,
|
|
3733
|
+
children: key
|
|
3734
|
+
}, index))
|
|
3735
|
+
});
|
|
3736
|
+
}
|
|
3737
|
+
//#endregion
|
|
3738
|
+
//#region lib/types/MenuSurface.js
|
|
3739
|
+
/** Shared menu material and the macOS backing that lets Chromium blur transparent windows. */
|
|
3740
|
+
/**
|
|
3741
|
+
* Paint a menu and, on macOS, an opaque backing behind the page content within its bounds.
|
|
3742
|
+
* CSS anchors keep each backing aligned during placement, resizing, and nested-menu movement.
|
|
3743
|
+
* @param props - Div content and placement, and compact geometry.
|
|
3744
|
+
* @param ref - The visible menu div, excluding the non-interactive backing.
|
|
3745
|
+
* @returns Menu content plus a backing portal removed with the menu.
|
|
3746
|
+
*/
|
|
3747
|
+
const MenuSurface = forwardRef(function MenuSurface({ compact = false, className, style, children, ...props }, ref) {
|
|
3748
|
+
const id = useId();
|
|
3749
|
+
const backingRef = useRef(null);
|
|
3750
|
+
useLayoutEffect(() => {
|
|
3751
|
+
document.body.appendChild(backingRef.current);
|
|
3752
|
+
}, []);
|
|
3753
|
+
const anchorStyle = { "--dsh-menu-anchor": `--dsh-menu-${id.replaceAll(":", "")}` };
|
|
3754
|
+
return jsxs(Fragment, { children: [jsxs("div", {
|
|
3755
|
+
...props,
|
|
3756
|
+
ref,
|
|
3757
|
+
"data-menu-material": "translucent",
|
|
3758
|
+
className: clsx(css$13.surface, compact && css$13.compact, className),
|
|
3759
|
+
style: {
|
|
3760
|
+
...style,
|
|
3761
|
+
...anchorStyle
|
|
3762
|
+
},
|
|
3763
|
+
children: [jsx("div", {
|
|
3764
|
+
"aria-hidden": "true",
|
|
3765
|
+
className: css$13.material
|
|
3766
|
+
}), children]
|
|
3767
|
+
}), createPortal(jsx("div", {
|
|
3768
|
+
ref: backingRef,
|
|
3769
|
+
"aria-hidden": "true",
|
|
3770
|
+
"data-menu-backing": "",
|
|
3771
|
+
className: clsx(css$13.backing, compact && css$13.compact),
|
|
3772
|
+
style: {
|
|
3773
|
+
...anchorStyle,
|
|
3774
|
+
visibility: style?.visibility
|
|
3775
|
+
}
|
|
3776
|
+
}), document.body)] });
|
|
3777
|
+
});
|
|
3778
|
+
//#endregion
|
|
3435
3779
|
//#region lib/types/Menu.js
|
|
3436
3780
|
/**
|
|
3437
3781
|
* Render one `role="menuitem"` row for a {@link Menu} whose rows are
|
|
@@ -3440,6 +3784,7 @@ function usePointerGrace(close) {
|
|
|
3440
3784
|
* without any shared state. Closing the menu stays the owner's decision, as
|
|
3441
3785
|
* it is for data rows.
|
|
3442
3786
|
* @param props.children - visible row label.
|
|
3787
|
+
* @param props.shortcut - effective key labels and accessible combination.
|
|
3443
3788
|
* @param props.icon - optional leading icon.
|
|
3444
3789
|
* @param props.disabled - whether the row cannot be activated.
|
|
3445
3790
|
* @param props.danger - whether to use the destructive row colors.
|
|
@@ -3447,25 +3792,37 @@ function usePointerGrace(close) {
|
|
|
3447
3792
|
* @param props.onSelect - row activation callback.
|
|
3448
3793
|
* @returns one menu-item row.
|
|
3449
3794
|
*/
|
|
3450
|
-
function MenuItemButton({ children, icon, disabled = false, danger = false, separatorBefore = false, onSelect }) {
|
|
3795
|
+
function MenuItemButton({ children, shortcut, icon, disabled = false, danger = false, separatorBefore = false, onSelect }) {
|
|
3451
3796
|
return jsxs("div", {
|
|
3452
|
-
className: css$
|
|
3797
|
+
className: css$14.itemWrap,
|
|
3453
3798
|
children: [separatorBefore && jsx("div", {
|
|
3454
|
-
className: css$
|
|
3799
|
+
className: css$14.separator,
|
|
3455
3800
|
role: "separator"
|
|
3456
3801
|
}), jsxs("button", {
|
|
3457
3802
|
type: "button",
|
|
3458
3803
|
role: "menuitem",
|
|
3459
|
-
className: clsx(css$
|
|
3804
|
+
className: clsx(css$14.item, danger && css$14.danger),
|
|
3460
3805
|
disabled,
|
|
3806
|
+
"aria-keyshortcuts": shortcut?.aria,
|
|
3461
3807
|
onClick: onSelect,
|
|
3462
|
-
children: [
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3808
|
+
children: [
|
|
3809
|
+
icon !== void 0 && jsx("span", {
|
|
3810
|
+
className: css$14.itemIcon,
|
|
3811
|
+
children: icon
|
|
3812
|
+
}),
|
|
3813
|
+
jsx("span", {
|
|
3814
|
+
className: css$14.itemLabel,
|
|
3815
|
+
children
|
|
3816
|
+
}),
|
|
3817
|
+
shortcut !== void 0 && jsx("span", {
|
|
3818
|
+
"aria-hidden": "true",
|
|
3819
|
+
className: css$14.shortcut,
|
|
3820
|
+
children: jsx(ShortcutKeys, {
|
|
3821
|
+
keys: shortcut.keys,
|
|
3822
|
+
className: css$14.shortcutKeys
|
|
3823
|
+
})
|
|
3824
|
+
})
|
|
3825
|
+
]
|
|
3469
3826
|
})]
|
|
3470
3827
|
});
|
|
3471
3828
|
}
|
|
@@ -3543,19 +3900,20 @@ function Menu({ open, anchor, items = [], children, selectedId, selectedIds, onS
|
|
|
3543
3900
|
* able to name by position.
|
|
3544
3901
|
*/
|
|
3545
3902
|
const triggerRef = useRef(null);
|
|
3903
|
+
const selectingWithTab = useRef(false);
|
|
3546
3904
|
/**
|
|
3547
3905
|
* Hand the keyboard back to the trigger that opened the menu — or, when the
|
|
3548
3906
|
* anchor never held it, to the anchor's first button. Focus left on a removed
|
|
3549
3907
|
* row otherwise falls to the page body, where the next Tab restarts from the
|
|
3550
3908
|
* top of the page.
|
|
3909
|
+
* @param navigation - whether explicit keyboard traversal should retain its focus indicator.
|
|
3551
3910
|
*/
|
|
3552
|
-
const refocusAnchor = () => {
|
|
3911
|
+
const refocusAnchor = (navigation = false) => {
|
|
3553
3912
|
const trigger = triggerRef.current;
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
rootRef.current?.querySelector("button:not(:disabled)")?.focus();
|
|
3913
|
+
const target = trigger !== null && document.contains(trigger) && !trigger.disabled ? trigger : rootRef.current?.querySelector("button:not(:disabled)");
|
|
3914
|
+
if (target == null) return;
|
|
3915
|
+
if (navigation) target.focus();
|
|
3916
|
+
else focusWithoutRing(target);
|
|
3559
3917
|
};
|
|
3560
3918
|
/**
|
|
3561
3919
|
* Post-selection focus, for the paths where the rows unmount with the list.
|
|
@@ -3565,10 +3923,11 @@ function Menu({ open, anchor, items = [], children, selectedId, selectedIds, onS
|
|
|
3565
3923
|
* its removal produced) comes back to the trigger.
|
|
3566
3924
|
*/
|
|
3567
3925
|
const refocusAfterSelection = () => {
|
|
3926
|
+
const navigation = selectingWithTab.current;
|
|
3568
3927
|
queueMicrotask(() => {
|
|
3569
3928
|
if (openRef.current) return;
|
|
3570
3929
|
const active = document.activeElement;
|
|
3571
|
-
if (active === null || active === document.body || listRef.current?.contains(active) === true) refocusAnchor();
|
|
3930
|
+
if (active === null || active === document.body || listRef.current?.contains(active) === true) refocusAnchor(navigation);
|
|
3572
3931
|
});
|
|
3573
3932
|
};
|
|
3574
3933
|
const openRef = useRef(open);
|
|
@@ -3645,7 +4004,7 @@ function Menu({ open, anchor, items = [], children, selectedId, selectedIds, onS
|
|
|
3645
4004
|
if (!open || !autoFocus) return;
|
|
3646
4005
|
const first = listRef.current?.querySelector("button:not(:disabled)");
|
|
3647
4006
|
walkIndex.current = first === void 0 || first === null ? null : 0;
|
|
3648
|
-
first
|
|
4007
|
+
if (first != null) focusWithoutRing(first);
|
|
3649
4008
|
}, [open, autoFocus]);
|
|
3650
4009
|
useEffect(() => {
|
|
3651
4010
|
if (!open) {
|
|
@@ -3653,6 +4012,7 @@ function Menu({ open, anchor, items = [], children, selectedId, selectedIds, onS
|
|
|
3653
4012
|
walkIndex.current = null;
|
|
3654
4013
|
return;
|
|
3655
4014
|
}
|
|
4015
|
+
const composition = observeComposition(document);
|
|
3656
4016
|
const onPointerDown = (e) => {
|
|
3657
4017
|
if (!(e.target instanceof Node)) return;
|
|
3658
4018
|
if (rootRef.current?.contains(e.target) === true) return;
|
|
@@ -3660,10 +4020,13 @@ function Menu({ open, anchor, items = [], children, selectedId, selectedIds, onS
|
|
|
3660
4020
|
onClose();
|
|
3661
4021
|
};
|
|
3662
4022
|
const onKeyDown = (e) => {
|
|
4023
|
+
if (composition.guards(e) || isBehindModal(rootRef.current) || e.defaultPrevented || e.ctrlKey || e.altKey || e.metaKey) return;
|
|
3663
4024
|
const focused = document.activeElement;
|
|
3664
4025
|
const insideList = listRef.current?.contains(focused) === true;
|
|
3665
4026
|
const anchored = rootRef.current?.contains(focused) === true || insideList;
|
|
3666
|
-
if (e.key === "Escape") {
|
|
4027
|
+
if (e.key === "Escape" && !e.shiftKey) {
|
|
4028
|
+
e.preventDefault();
|
|
4029
|
+
if (e.repeat) return;
|
|
3667
4030
|
onClose();
|
|
3668
4031
|
if (anchored || autoFocus) refocusAnchor();
|
|
3669
4032
|
}
|
|
@@ -3673,13 +4036,18 @@ function Menu({ open, anchor, items = [], children, selectedId, selectedIds, onS
|
|
|
3673
4036
|
if (e.shiftKey) {
|
|
3674
4037
|
e.preventDefault();
|
|
3675
4038
|
onClose();
|
|
3676
|
-
refocusAnchor();
|
|
4039
|
+
refocusAnchor(true);
|
|
3677
4040
|
return;
|
|
3678
4041
|
}
|
|
3679
4042
|
if (insideList) {
|
|
3680
4043
|
if (focused instanceof Element && focused.getAttribute("role") === "menuitem") {
|
|
3681
4044
|
e.preventDefault();
|
|
3682
|
-
|
|
4045
|
+
selectingWithTab.current = true;
|
|
4046
|
+
try {
|
|
4047
|
+
focused.click();
|
|
4048
|
+
} finally {
|
|
4049
|
+
selectingWithTab.current = false;
|
|
4050
|
+
}
|
|
3683
4051
|
}
|
|
3684
4052
|
return;
|
|
3685
4053
|
}
|
|
@@ -3711,11 +4079,20 @@ function Menu({ open, anchor, items = [], children, selectedId, selectedIds, onS
|
|
|
3711
4079
|
if (document.activeElement instanceof HTMLIFrameElement) onClose();
|
|
3712
4080
|
};
|
|
3713
4081
|
document.addEventListener("pointerdown", onPointerDown);
|
|
3714
|
-
|
|
4082
|
+
const onEscape = (event) => {
|
|
4083
|
+
if (event.key === "Escape") onKeyDown(event);
|
|
4084
|
+
};
|
|
4085
|
+
const onOtherKey = (event) => {
|
|
4086
|
+
if (event.key !== "Escape") onKeyDown(event);
|
|
4087
|
+
};
|
|
4088
|
+
document.addEventListener("keydown", onOtherKey);
|
|
4089
|
+
document.addEventListener("keydown", onEscape, true);
|
|
3715
4090
|
window.addEventListener("blur", onWindowBlur);
|
|
3716
4091
|
return () => {
|
|
4092
|
+
composition.dispose();
|
|
3717
4093
|
document.removeEventListener("pointerdown", onPointerDown);
|
|
3718
|
-
document.removeEventListener("keydown",
|
|
4094
|
+
document.removeEventListener("keydown", onOtherKey);
|
|
4095
|
+
document.removeEventListener("keydown", onEscape, true);
|
|
3719
4096
|
window.removeEventListener("blur", onWindowBlur);
|
|
3720
4097
|
};
|
|
3721
4098
|
}, [
|
|
@@ -3729,11 +4106,11 @@ function Menu({ open, anchor, items = [], children, selectedId, selectedIds, onS
|
|
|
3729
4106
|
const scrollable = !items.some((entry) => !isSeparator(entry) && !isLabel(entry) && entry.submenu !== void 0 && entry.submenu.length > 0);
|
|
3730
4107
|
const renderEntry = (entry) => {
|
|
3731
4108
|
if (isSeparator(entry)) return jsx("div", {
|
|
3732
|
-
className: css$
|
|
4109
|
+
className: css$14.separator,
|
|
3733
4110
|
role: "separator"
|
|
3734
4111
|
}, entry.id);
|
|
3735
4112
|
if (isLabel(entry)) return jsx("div", {
|
|
3736
|
-
className: css$
|
|
4113
|
+
className: css$14.label,
|
|
3737
4114
|
role: "presentation",
|
|
3738
4115
|
children: entry.text
|
|
3739
4116
|
}, entry.id);
|
|
@@ -3741,7 +4118,7 @@ function Menu({ open, anchor, items = [], children, selectedId, selectedIds, onS
|
|
|
3741
4118
|
const subOpen = hasSub && openSubmenuId === entry.id;
|
|
3742
4119
|
const selected = entry.id === selectedId || selectedIds?.includes(entry.id) === true;
|
|
3743
4120
|
return jsxs("div", {
|
|
3744
|
-
className: css$
|
|
4121
|
+
className: css$14.itemWrap,
|
|
3745
4122
|
onMouseEnter: hasSub ? () => {
|
|
3746
4123
|
setOpenSubmenuId(entry.id);
|
|
3747
4124
|
} : void 0,
|
|
@@ -3751,8 +4128,9 @@ function Menu({ open, anchor, items = [], children, selectedId, selectedIds, onS
|
|
|
3751
4128
|
children: [jsxs("button", {
|
|
3752
4129
|
type: "button",
|
|
3753
4130
|
role: "menuitem",
|
|
3754
|
-
className: clsx(css$
|
|
4131
|
+
className: clsx(css$14.item, selected && (selection === "fill" ? css$14.selectedFill : css$14.selected), entry.danger === true && css$14.danger),
|
|
3755
4132
|
disabled: entry.disabled,
|
|
4133
|
+
"aria-keyshortcuts": entry.shortcut?.aria,
|
|
3756
4134
|
"aria-haspopup": hasSub ? "menu" : void 0,
|
|
3757
4135
|
"aria-expanded": hasSub ? subOpen : void 0,
|
|
3758
4136
|
onFocus: hasSub ? () => {
|
|
@@ -3767,33 +4145,55 @@ function Menu({ open, anchor, items = [], children, selectedId, selectedIds, onS
|
|
|
3767
4145
|
},
|
|
3768
4146
|
children: [
|
|
3769
4147
|
entry.icon !== void 0 && jsx("span", {
|
|
3770
|
-
className: css$
|
|
4148
|
+
className: css$14.itemIcon,
|
|
3771
4149
|
children: entry.icon
|
|
3772
4150
|
}),
|
|
3773
4151
|
jsx("span", {
|
|
3774
|
-
className: css$
|
|
4152
|
+
className: css$14.itemLabel,
|
|
3775
4153
|
children: entry.label
|
|
3776
4154
|
}),
|
|
3777
|
-
|
|
4155
|
+
entry.shortcut !== void 0 && jsx("span", {
|
|
4156
|
+
"aria-hidden": "true",
|
|
4157
|
+
className: css$14.shortcut,
|
|
4158
|
+
children: jsx(ShortcutKeys, {
|
|
4159
|
+
keys: entry.shortcut.keys,
|
|
4160
|
+
className: css$14.shortcutKeys
|
|
4161
|
+
})
|
|
4162
|
+
}),
|
|
4163
|
+
selected && selection === "check" && jsx(IconCheckOutlineRegular, { className: css$14.check })
|
|
3778
4164
|
]
|
|
3779
|
-
}), subOpen && entry.submenu !== void 0 && jsx(
|
|
3780
|
-
|
|
4165
|
+
}), subOpen && entry.submenu !== void 0 && jsx(MenuSurface, {
|
|
4166
|
+
compact,
|
|
4167
|
+
className: clsx(css$14.submenu, compact && css$14.compactList),
|
|
3781
4168
|
role: "menu",
|
|
3782
4169
|
children: entry.submenu.map((sub) => jsxs("button", {
|
|
3783
4170
|
type: "button",
|
|
3784
4171
|
role: "menuitem",
|
|
3785
|
-
className: css$
|
|
4172
|
+
className: css$14.item,
|
|
3786
4173
|
disabled: sub.disabled,
|
|
4174
|
+
"aria-keyshortcuts": sub.shortcut?.aria,
|
|
3787
4175
|
onClick: () => {
|
|
3788
4176
|
onSelect?.(sub.id);
|
|
4177
|
+
refocusAfterSelection();
|
|
3789
4178
|
},
|
|
3790
|
-
children: [
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
4179
|
+
children: [
|
|
4180
|
+
sub.icon !== void 0 && jsx("span", {
|
|
4181
|
+
className: css$14.itemIcon,
|
|
4182
|
+
children: sub.icon
|
|
4183
|
+
}),
|
|
4184
|
+
jsx("span", {
|
|
4185
|
+
className: css$14.itemLabel,
|
|
4186
|
+
children: sub.label
|
|
4187
|
+
}),
|
|
4188
|
+
sub.shortcut !== void 0 && jsx("span", {
|
|
4189
|
+
"aria-hidden": "true",
|
|
4190
|
+
className: css$14.shortcut,
|
|
4191
|
+
children: jsx(ShortcutKeys, {
|
|
4192
|
+
keys: sub.shortcut.keys,
|
|
4193
|
+
className: css$14.shortcutKeys
|
|
4194
|
+
})
|
|
4195
|
+
})
|
|
4196
|
+
]
|
|
3797
4197
|
}, sub.id))
|
|
3798
4198
|
})]
|
|
3799
4199
|
}, entry.id);
|
|
@@ -3804,9 +4204,10 @@ function Menu({ open, anchor, items = [], children, selectedId, selectedIds, onS
|
|
|
3804
4204
|
if (row.closest("[role=\"menu\"]") !== e.currentTarget) return;
|
|
3805
4205
|
setOpenSubmenuId(null);
|
|
3806
4206
|
};
|
|
3807
|
-
const list = open && jsxs(
|
|
4207
|
+
const list = open && jsxs(MenuSurface, {
|
|
4208
|
+
compact,
|
|
3808
4209
|
ref: listRef,
|
|
3809
|
-
className: clsx(css$
|
|
4210
|
+
className: clsx(css$14.list, listClassName, dense && css$14.denseList, compact && css$14.compactList, scrollable && css$14.scrollable, portal && css$14.portal, side === "top" && !portal && css$14.sideTop, align === "end" && !portal && css$14.alignEnd),
|
|
3810
4211
|
style: portal ? fixedPos ?? MEASURE_STYLE : void 0,
|
|
3811
4212
|
role: "menu",
|
|
3812
4213
|
onClick: (e) => {
|
|
@@ -3817,18 +4218,18 @@ function Menu({ open, anchor, items = [], children, selectedId, selectedIds, onS
|
|
|
3817
4218
|
onMouseOver: collapseSubmenuFrom,
|
|
3818
4219
|
onFocus: collapseSubmenuFrom,
|
|
3819
4220
|
children: [jsxs("div", {
|
|
3820
|
-
className: css$
|
|
4221
|
+
className: css$14.viewport,
|
|
3821
4222
|
role: "presentation",
|
|
3822
4223
|
children: [items.map(renderEntry), children]
|
|
3823
4224
|
}), footer !== void 0 && footer.length > 0 && jsx("div", {
|
|
3824
|
-
className: css$
|
|
4225
|
+
className: css$14.footer,
|
|
3825
4226
|
role: "presentation",
|
|
3826
4227
|
children: footer.map(renderEntry)
|
|
3827
4228
|
})]
|
|
3828
4229
|
});
|
|
3829
4230
|
return jsxs("span", {
|
|
3830
4231
|
ref: rootRef,
|
|
3831
|
-
className: clsx(css$
|
|
4232
|
+
className: clsx(css$14.root, className),
|
|
3832
4233
|
onPointerEnter: closeOnPointerLeave ? cancelClose : void 0,
|
|
3833
4234
|
onPointerLeave: closeOnPointerLeave ? () => {
|
|
3834
4235
|
if (open) armClose();
|
|
@@ -4018,77 +4419,349 @@ async function writeClipboard(text) {
|
|
|
4018
4419
|
}
|
|
4019
4420
|
}
|
|
4020
4421
|
//#endregion
|
|
4021
|
-
//#region lib/types/
|
|
4022
|
-
/** Preview opacity transition and retained lifetime during dismissal. */
|
|
4023
|
-
const PREVIEW_FADE_MS = 100;
|
|
4024
|
-
const PREVIEW_MAX_HEIGHT = 420;
|
|
4025
|
-
const PREVIEW_INSET = 24;
|
|
4026
|
-
const ANCHOR_GAP = 8;
|
|
4027
|
-
const VIEWPORT_MARGIN = 8;
|
|
4422
|
+
//#region lib/types/input-modality.js
|
|
4028
4423
|
/**
|
|
4029
|
-
*
|
|
4030
|
-
*
|
|
4031
|
-
*
|
|
4032
|
-
*
|
|
4033
|
-
* @param props.openDelayMs - hover dwell before the card shows (default 500).
|
|
4034
|
-
* @param props.variant - compact card beside the anchor, or a preview above/below it
|
|
4035
|
-
* with 24px side insets, a 420px height cap, frame-top clearance, and 100ms opacity transitions.
|
|
4036
|
-
* @param props.widthAnchorRef - optional element whose width and horizontal position size the preview.
|
|
4037
|
-
* @param props.disabled - suppress opening; turning true dismisses an open card.
|
|
4038
|
-
* @param props.copyText - optional primary value copied by activation and
|
|
4039
|
-
* included in the card's accessible name.
|
|
4040
|
-
* @param props.copyLabel - localized accessible activation-label prefix.
|
|
4041
|
-
* @param props.copiedLabel - localized visible success label.
|
|
4042
|
-
* @returns anchor wrapper with the conditional portaled card.
|
|
4424
|
+
* Document-wide input tracking shared by tooltips and focus-ring styles.
|
|
4425
|
+
* Tooltips follow the last input; rings follow navigation or a key followed by
|
|
4426
|
+
* focus on a different control. Modifiers and refocusing alone keep rings silent.
|
|
4427
|
+
* Module-level listeners live for the document lifetime; Node imports are inert.
|
|
4043
4428
|
*/
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4429
|
+
/** Modality values published on the document element. */
|
|
4430
|
+
const INPUT_MODALITY = {
|
|
4431
|
+
pointer: "pointer",
|
|
4432
|
+
keyboard: "keyboard"
|
|
4433
|
+
};
|
|
4434
|
+
/** Attribute carrying whether focus navigation last owned focus. */
|
|
4435
|
+
const INPUT_MODALITY_ATTRIBUTE = "data-input-modality";
|
|
4436
|
+
const FOCUS_NAVIGATION = new Set([
|
|
4437
|
+
"Tab",
|
|
4438
|
+
"Home",
|
|
4439
|
+
"End",
|
|
4440
|
+
"PageUp",
|
|
4441
|
+
"PageDown"
|
|
4442
|
+
]);
|
|
4443
|
+
let pointer = false;
|
|
4444
|
+
let pointerOwnsFocus = false;
|
|
4445
|
+
let keyFocusOrigin;
|
|
4446
|
+
function publish() {
|
|
4447
|
+
document.documentElement.setAttribute(INPUT_MODALITY_ATTRIBUTE, pointerOwnsFocus ? INPUT_MODALITY.pointer : INPUT_MODALITY.keyboard);
|
|
4448
|
+
}
|
|
4449
|
+
/**
|
|
4450
|
+
* Whether the last input came from a pointer, independently of ring visibility.
|
|
4451
|
+
* @returns True after pointer input; false after any key.
|
|
4452
|
+
*/
|
|
4453
|
+
function pointerModality() {
|
|
4454
|
+
return pointer;
|
|
4455
|
+
}
|
|
4456
|
+
if (typeof window !== "undefined") {
|
|
4457
|
+
window.addEventListener("pointerdown", () => {
|
|
4458
|
+
pointer = true;
|
|
4459
|
+
pointerOwnsFocus = true;
|
|
4460
|
+
keyFocusOrigin = void 0;
|
|
4461
|
+
publish();
|
|
4462
|
+
}, true);
|
|
4463
|
+
window.addEventListener("keydown", (event) => {
|
|
4464
|
+
pointer = false;
|
|
4465
|
+
if (event.isComposing) {
|
|
4466
|
+
keyFocusOrigin = void 0;
|
|
4467
|
+
return;
|
|
4077
4468
|
}
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4469
|
+
keyFocusOrigin = event.composedPath()[0];
|
|
4470
|
+
if (!FOCUS_NAVIGATION.has(event.key) && !event.key.startsWith("Arrow")) return;
|
|
4471
|
+
pointerOwnsFocus = false;
|
|
4472
|
+
publish();
|
|
4473
|
+
}, true);
|
|
4474
|
+
window.addEventListener("focusin", (event) => {
|
|
4475
|
+
if (keyFocusOrigin === void 0 || event.composedPath()[0] === keyFocusOrigin) return;
|
|
4476
|
+
keyFocusOrigin = void 0;
|
|
4477
|
+
if (!pointerOwnsFocus) return;
|
|
4478
|
+
pointerOwnsFocus = false;
|
|
4479
|
+
publish();
|
|
4480
|
+
}, true);
|
|
4481
|
+
window.addEventListener("blur", () => {
|
|
4482
|
+
keyFocusOrigin = void 0;
|
|
4483
|
+
});
|
|
4484
|
+
}
|
|
4485
|
+
//#endregion
|
|
4486
|
+
//#region lib/types/Tooltip.js
|
|
4487
|
+
/** Anchor-preserving tooltips; an optional body portal escapes clipping containers and stacking contexts that cap the bubble's z-index. */
|
|
4488
|
+
/**
|
|
4489
|
+
* Suppression channel for enclosing tooltip and hover-card anchors: a visible
|
|
4490
|
+
* tooltip within an anchor withdraws the enclosing preview while its bubble is shown.
|
|
4491
|
+
*/
|
|
4492
|
+
const TooltipSuppression = createContext(null);
|
|
4493
|
+
/**
|
|
4494
|
+
* Attach a hover/focus tooltip to an anchor element.
|
|
4495
|
+
* @param props.label - bubble text, or a resolver evaluated only while visible; an empty string shows only shortcut keys.
|
|
4496
|
+
* @param props.shortcutKeys - effective key labels rendered as platform-formatted keycaps after optional text.
|
|
4497
|
+
* @param props.side - placement relative to the anchor (default 'right').
|
|
4498
|
+
* @param props.align - horizontal anchor-edge alignment for 'bottom'/'top' bubbles: 'end' pins
|
|
4499
|
+
* the bubble's right edge to the anchor's (for anchors beside other hover surfaces the centered
|
|
4500
|
+
* bubble would overlap); default 'center'. Ignored for side 'right'.
|
|
4501
|
+
* @param props.portal - render the bubble under document.body, so an ancestor's clipping or its
|
|
4502
|
+
* stacking context (which confines the bubble's z-index to that context) cannot hide it.
|
|
4503
|
+
* @param props.delayMs - hover delay in milliseconds; keyboard focus remains immediate.
|
|
4504
|
+
* @param props.gap - anchor-to-bubble distance in pixels for 'bottom'/'top' bubbles (default 8);
|
|
4505
|
+
* ignored for side 'right'.
|
|
4506
|
+
* @param props.disabled - suppress the bubble while true; the anchor renders identically so
|
|
4507
|
+
* toggling never remounts it (which would cut its CSS transitions).
|
|
4508
|
+
* @param props.maxWidth - bubble width cap in pixels, for labels long enough that the default
|
|
4509
|
+
* half-viewport cap would render a slab wider than the surface the anchor sits on.
|
|
4510
|
+
* @param props.children - a single anchor element; its own ref (callback or object) is forwarded alongside the tooltip's.
|
|
4511
|
+
* @returns the cloned anchor plus a fixed-position bubble, optionally portaled to the body.
|
|
4512
|
+
* The bubble stays hidden until ResizeObserver supplies its size for viewport fitting; clicking the
|
|
4513
|
+
* anchor dismisses the bubble until the next trigger, and focus arriving after a pointer
|
|
4514
|
+
* interaction (a closing menu refocusing its trigger) never raises it.
|
|
4515
|
+
*/
|
|
4516
|
+
function Tooltip({ label, shortcutKeys, side = "right", align = "center", delayMs = 0, gap = 8, disabled = false, portal = false, maxWidth, children }) {
|
|
4517
|
+
const anchor = useRef(null);
|
|
4518
|
+
const childRef = children.ref;
|
|
4519
|
+
const mergedRef = useCallback((el) => {
|
|
4520
|
+
anchor.current = el;
|
|
4521
|
+
if (typeof childRef === "function") childRef(el);
|
|
4522
|
+
else if (childRef != null) childRef.current = el;
|
|
4523
|
+
}, [childRef]);
|
|
4524
|
+
const [pos, setPos] = useState(null);
|
|
4525
|
+
const bubble = useRef(null);
|
|
4526
|
+
const resolvedLabel = pos === null ? null : typeof label === "function" ? label() : label;
|
|
4527
|
+
const y = pos === null ? 0 : side === "right" ? pos.top + (pos.bottom - pos.top) / 2 : side === "top" ? pos.top - gap : pos.bottom + gap;
|
|
4528
|
+
const showTimer = useRef(null);
|
|
4529
|
+
const triggers = useRef({
|
|
4530
|
+
hover: false,
|
|
4531
|
+
focus: false
|
|
4532
|
+
});
|
|
4533
|
+
const suppressAncestors = useContext(TooltipSuppression);
|
|
4534
|
+
const [suppressed, setSuppressed] = useState(false);
|
|
4535
|
+
const announce = useCallback((active) => {
|
|
4536
|
+
suppressAncestors?.(active);
|
|
4537
|
+
}, [suppressAncestors]);
|
|
4538
|
+
const visible = pos !== null && !disabled;
|
|
4539
|
+
useEffect(() => {
|
|
4540
|
+
const el = bubble.current;
|
|
4541
|
+
if (pos === null || !visible || suppressed || el === null) return;
|
|
4542
|
+
const edgeMargin = 12;
|
|
4543
|
+
let size;
|
|
4544
|
+
let placement = side;
|
|
4545
|
+
const fit = () => {
|
|
4546
|
+
if (size === void 0) return;
|
|
4547
|
+
const { inlineSize: width, blockSize: height } = size;
|
|
4548
|
+
const offset = side === "right" ? 0 : align === "end" ? width : width / 2;
|
|
4549
|
+
const left = Math.max(edgeMargin, Math.min(pos.x - offset, window.innerWidth - edgeMargin - width));
|
|
4550
|
+
const fitsBelow = pos.bottom + gap + height <= window.innerHeight - edgeMargin;
|
|
4551
|
+
const fitsAbove = pos.top - gap - height >= edgeMargin;
|
|
4552
|
+
if (placement === "bottom" && !fitsBelow && fitsAbove) placement = "top";
|
|
4553
|
+
else if (placement === "top" && !fitsAbove && fitsBelow) placement = "bottom";
|
|
4554
|
+
el.style.left = `${left + offset}px`;
|
|
4555
|
+
el.style.top = `${placement === "right" ? (pos.top + pos.bottom) / 2 : placement === "top" ? pos.top - gap : pos.bottom + gap}px`;
|
|
4556
|
+
el.dataset.side = placement;
|
|
4557
|
+
el.style.visibility = "visible";
|
|
4558
|
+
};
|
|
4559
|
+
const observer = new ResizeObserver((entries) => {
|
|
4560
|
+
size = entries[0]?.borderBoxSize[0];
|
|
4561
|
+
fit();
|
|
4562
|
+
});
|
|
4563
|
+
observer.observe(el, { box: "border-box" });
|
|
4564
|
+
window.addEventListener("resize", fit);
|
|
4565
|
+
return () => {
|
|
4566
|
+
observer.disconnect();
|
|
4567
|
+
window.removeEventListener("resize", fit);
|
|
4568
|
+
};
|
|
4569
|
+
}, [
|
|
4570
|
+
align,
|
|
4571
|
+
gap,
|
|
4572
|
+
pos,
|
|
4573
|
+
side,
|
|
4574
|
+
suppressed,
|
|
4575
|
+
visible
|
|
4576
|
+
]);
|
|
4577
|
+
useEffect(() => {
|
|
4578
|
+
announce(visible);
|
|
4579
|
+
return () => {
|
|
4580
|
+
announce(false);
|
|
4581
|
+
};
|
|
4582
|
+
}, [announce, visible]);
|
|
4583
|
+
const cancelShow = useCallback(() => {
|
|
4584
|
+
if (showTimer.current === null) return;
|
|
4585
|
+
clearTimeout(showTimer.current);
|
|
4586
|
+
showTimer.current = null;
|
|
4587
|
+
}, []);
|
|
4588
|
+
useEffect(() => {
|
|
4589
|
+
if (disabled) {
|
|
4590
|
+
cancelShow();
|
|
4591
|
+
triggers.current = {
|
|
4592
|
+
hover: false,
|
|
4593
|
+
focus: false
|
|
4594
|
+
};
|
|
4595
|
+
setPos(null);
|
|
4596
|
+
}
|
|
4597
|
+
return cancelShow;
|
|
4598
|
+
}, [cancelShow, disabled]);
|
|
4599
|
+
const show = () => {
|
|
4600
|
+
if (disabled) return;
|
|
4601
|
+
const el = anchor.current;
|
|
4602
|
+
/* v8 ignore next -- the ref is attached by event time: events fire on the cloned anchor. */
|
|
4603
|
+
if (el === null) return;
|
|
4604
|
+
const r = el.getBoundingClientRect();
|
|
4605
|
+
setPos({
|
|
4606
|
+
x: side === "right" ? r.right + 10 : align === "end" ? r.right : r.left + r.width / 2,
|
|
4607
|
+
top: r.top,
|
|
4608
|
+
bottom: r.bottom
|
|
4609
|
+
});
|
|
4610
|
+
announce(true);
|
|
4611
|
+
};
|
|
4612
|
+
const showAfterHoverDelay = () => {
|
|
4613
|
+
cancelShow();
|
|
4614
|
+
if (delayMs <= 0) {
|
|
4615
|
+
show();
|
|
4616
|
+
return;
|
|
4617
|
+
}
|
|
4618
|
+
showTimer.current = setTimeout(() => {
|
|
4619
|
+
showTimer.current = null;
|
|
4620
|
+
show();
|
|
4621
|
+
}, delayMs);
|
|
4622
|
+
};
|
|
4623
|
+
const withdraw = () => {
|
|
4624
|
+
setPos(null);
|
|
4625
|
+
announce(false);
|
|
4626
|
+
};
|
|
4627
|
+
const hide = () => {
|
|
4628
|
+
cancelShow();
|
|
4629
|
+
if (!triggers.current.hover && !triggers.current.focus) withdraw();
|
|
4630
|
+
};
|
|
4631
|
+
const content = visible && !suppressed && jsxs("span", {
|
|
4632
|
+
ref: bubble,
|
|
4633
|
+
className: css$15.bubble,
|
|
4634
|
+
"data-side": side,
|
|
4635
|
+
"data-portal": portal || void 0,
|
|
4636
|
+
"data-align": align,
|
|
4637
|
+
"data-has-shortcut": shortcutKeys?.length ? true : void 0,
|
|
4638
|
+
style: {
|
|
4639
|
+
left: pos.x,
|
|
4640
|
+
top: y,
|
|
4641
|
+
visibility: "hidden",
|
|
4642
|
+
...maxWidth === void 0 ? {} : { maxWidth }
|
|
4643
|
+
},
|
|
4644
|
+
role: "tooltip",
|
|
4645
|
+
"aria-label": shortcutKeys?.length ? [resolvedLabel, shortcutKeys.join(" ")].filter(Boolean).join(" ") : void 0,
|
|
4646
|
+
children: [resolvedLabel && jsx("span", {
|
|
4647
|
+
className: css$15.label,
|
|
4648
|
+
children: resolvedLabel
|
|
4649
|
+
}), shortcutKeys !== void 0 && shortcutKeys.length > 0 && jsx(ShortcutKeys, {
|
|
4650
|
+
keys: shortcutKeys,
|
|
4651
|
+
variant: "tooltip"
|
|
4652
|
+
})]
|
|
4653
|
+
});
|
|
4654
|
+
return jsxs(TooltipSuppression.Provider, {
|
|
4655
|
+
value: setSuppressed,
|
|
4656
|
+
children: [cloneElement(children, {
|
|
4657
|
+
ref: mergedRef,
|
|
4658
|
+
onMouseEnter: (e) => {
|
|
4659
|
+
children.props.onMouseEnter?.(e);
|
|
4660
|
+
triggers.current.hover = true;
|
|
4661
|
+
showAfterHoverDelay();
|
|
4662
|
+
},
|
|
4663
|
+
onMouseLeave: (e) => {
|
|
4664
|
+
children.props.onMouseLeave?.(e);
|
|
4665
|
+
triggers.current.hover = false;
|
|
4666
|
+
cancelShow();
|
|
4667
|
+
withdraw();
|
|
4668
|
+
},
|
|
4669
|
+
onClick: (e) => {
|
|
4670
|
+
children.props.onClick?.(e);
|
|
4671
|
+
triggers.current.focus = false;
|
|
4672
|
+
cancelShow();
|
|
4673
|
+
withdraw();
|
|
4674
|
+
},
|
|
4675
|
+
onFocus: (e) => {
|
|
4676
|
+
children.props.onFocus?.(e);
|
|
4677
|
+
if (pointerModality()) return;
|
|
4678
|
+
triggers.current.focus = true;
|
|
4679
|
+
cancelShow();
|
|
4680
|
+
show();
|
|
4681
|
+
},
|
|
4682
|
+
onBlur: (e) => {
|
|
4683
|
+
children.props.onBlur?.(e);
|
|
4684
|
+
triggers.current.focus = false;
|
|
4685
|
+
hide();
|
|
4686
|
+
}
|
|
4687
|
+
}), portal ? content !== false && createPortal(content, document.body) : content]
|
|
4688
|
+
});
|
|
4689
|
+
}
|
|
4690
|
+
//#endregion
|
|
4691
|
+
//#region lib/types/HoverCard.js
|
|
4692
|
+
/** Preview opacity transition and retained lifetime during dismissal. */
|
|
4693
|
+
const PREVIEW_FADE_MS = 100;
|
|
4694
|
+
const PREVIEW_MAX_HEIGHT = 420;
|
|
4695
|
+
const PREVIEW_INSET = 24;
|
|
4696
|
+
const INLINE_PREVIEW_WIDTH = 300;
|
|
4697
|
+
const ANCHOR_GAP = 8;
|
|
4698
|
+
const VIEWPORT_MARGIN = 8;
|
|
4699
|
+
/**
|
|
4700
|
+
* Render an anchor with a hover-triggered preview card, hidden while a tooltip within the anchor is visible.
|
|
4701
|
+
* @param props.anchor - the hover target (rendered in place inside a wrapper span).
|
|
4702
|
+
* @param props.content - card content; the pointer may rest on it, so it is
|
|
4703
|
+
* readable and selectable, but it carries no dismissal affordance of its own.
|
|
4704
|
+
* @param props.openDelayMs - hover dwell before the card shows (default 500).
|
|
4705
|
+
* @param props.variant - compact card beside the anchor, or a preview above/below it
|
|
4706
|
+
* with 24px side insets, a 420px height cap, frame-top clearance, and 100ms opacity transitions.
|
|
4707
|
+
* @param props.widthAnchorRef - optional element whose width and horizontal position size the preview.
|
|
4708
|
+
* @param props.inline - keep the anchor in prose; show a contained preview on hover or keyboard focus.
|
|
4709
|
+
* @param props.disabled - suppress opening; turning true dismisses an open card.
|
|
4710
|
+
* @param props.copyText - optional primary value copied by activation and
|
|
4711
|
+
* included in the card's accessible name.
|
|
4712
|
+
* @param props.copyLabel - localized accessible activation-label prefix.
|
|
4713
|
+
* @param props.copiedLabel - localized visible success label.
|
|
4714
|
+
* @returns anchor wrapper with the conditional portaled card.
|
|
4715
|
+
*/
|
|
4716
|
+
function HoverCard({ anchor, content, openDelayMs = 500, disabled = false, copyText, copyLabel, copiedLabel, variant = "compact", widthAnchorRef, inline = false }) {
|
|
4717
|
+
const rootRef = useRef(null);
|
|
4718
|
+
const cardRef = useRef(null);
|
|
4719
|
+
const timerRef = useRef(null);
|
|
4720
|
+
const copyTimerRef = useRef(null);
|
|
4721
|
+
const copyHeightRef = useRef(null);
|
|
4722
|
+
const copyEpochRef = useRef(0);
|
|
4723
|
+
const copyingRef = useRef(false);
|
|
4724
|
+
const mountedRef = useRef(true);
|
|
4725
|
+
const [phase, setPhase] = useState("closed");
|
|
4726
|
+
const open = phase !== "closed";
|
|
4727
|
+
const closing = phase === "closing";
|
|
4728
|
+
const [pos, setPos] = useState(null);
|
|
4729
|
+
const positioned = pos !== null;
|
|
4730
|
+
const [copied, setCopied] = useState(false);
|
|
4731
|
+
const [suppressed, setSuppressed] = useState(false);
|
|
4732
|
+
const clearCopied = useCallback(() => {
|
|
4733
|
+
if (copyTimerRef.current !== null) {
|
|
4734
|
+
clearTimeout(copyTimerRef.current);
|
|
4735
|
+
copyTimerRef.current = null;
|
|
4736
|
+
}
|
|
4737
|
+
copyHeightRef.current = null;
|
|
4738
|
+
setCopied(false);
|
|
4739
|
+
}, []);
|
|
4740
|
+
const close = useCallback(() => {
|
|
4741
|
+
copyEpochRef.current += 1;
|
|
4742
|
+
clearCopied();
|
|
4743
|
+
setPhase((current) => variant === "preview" && current !== "closed" ? "closing" : "closed");
|
|
4744
|
+
}, [clearCopied, variant]);
|
|
4745
|
+
const { arm: armClose, cancel: cancelClose } = usePointerGrace(close);
|
|
4746
|
+
const clearTimer = () => {
|
|
4747
|
+
if (timerRef.current !== null) {
|
|
4748
|
+
clearTimeout(timerRef.current);
|
|
4749
|
+
timerRef.current = null;
|
|
4750
|
+
}
|
|
4751
|
+
};
|
|
4752
|
+
useEffect(() => {
|
|
4753
|
+
if (!closing) return;
|
|
4754
|
+
const timer = setTimeout(() => {
|
|
4755
|
+
setPhase("closed");
|
|
4756
|
+
}, PREVIEW_FADE_MS);
|
|
4757
|
+
return () => {
|
|
4758
|
+
clearTimeout(timer);
|
|
4759
|
+
};
|
|
4760
|
+
}, [closing]);
|
|
4761
|
+
useEffect(() => {
|
|
4762
|
+
if (!disabled) return;
|
|
4763
|
+
clearTimer();
|
|
4764
|
+
cancelClose();
|
|
4092
4765
|
close();
|
|
4093
4766
|
}, [
|
|
4094
4767
|
disabled,
|
|
@@ -4108,19 +4781,22 @@ function HoverCard({ anchor, content, openDelayMs = 500, disabled = false, copyT
|
|
|
4108
4781
|
};
|
|
4109
4782
|
}, []);
|
|
4110
4783
|
useEffect(() => {
|
|
4111
|
-
if (!open || variant !== "preview") return;
|
|
4784
|
+
if (!open || variant !== "preview" && !inline) return;
|
|
4112
4785
|
const dismiss = (event) => {
|
|
4113
4786
|
if (event.key !== "Escape") return;
|
|
4787
|
+
if (inline) event.stopPropagation();
|
|
4788
|
+
clearTimer();
|
|
4114
4789
|
cancelClose();
|
|
4115
4790
|
close();
|
|
4116
4791
|
};
|
|
4117
|
-
window.addEventListener("keydown", dismiss);
|
|
4792
|
+
window.addEventListener("keydown", dismiss, inline);
|
|
4118
4793
|
return () => {
|
|
4119
|
-
window.removeEventListener("keydown", dismiss);
|
|
4794
|
+
window.removeEventListener("keydown", dismiss, inline);
|
|
4120
4795
|
};
|
|
4121
4796
|
}, [
|
|
4122
4797
|
open,
|
|
4123
4798
|
variant,
|
|
4799
|
+
inline,
|
|
4124
4800
|
cancelClose,
|
|
4125
4801
|
close
|
|
4126
4802
|
]);
|
|
@@ -4152,6 +4828,23 @@ function HoverCard({ anchor, content, openDelayMs = 500, disabled = false, copyT
|
|
|
4152
4828
|
});
|
|
4153
4829
|
return;
|
|
4154
4830
|
}
|
|
4831
|
+
if (inline) {
|
|
4832
|
+
const height = Math.max(h, cardRef.current?.scrollHeight ?? 0);
|
|
4833
|
+
const width = Math.max(0, Math.min(INLINE_PREVIEW_WIDTH, window.innerWidth - VIEWPORT_MARGIN * 2));
|
|
4834
|
+
const topMargin = overlayTopMargin(VIEWPORT_MARGIN);
|
|
4835
|
+
const belowTop = Math.max(topMargin, r.bottom + ANCHOR_GAP);
|
|
4836
|
+
const above = Math.max(0, r.top - ANCHOR_GAP - topMargin);
|
|
4837
|
+
const below = Math.max(0, window.innerHeight - belowTop - VIEWPORT_MARGIN);
|
|
4838
|
+
const onTop = height > below && above > below;
|
|
4839
|
+
const maxHeight = onTop ? above : below;
|
|
4840
|
+
setPos({
|
|
4841
|
+
left: Math.max(VIEWPORT_MARGIN, Math.min(r.left, window.innerWidth - width - VIEWPORT_MARGIN)),
|
|
4842
|
+
top: onTop ? r.top - ANCHOR_GAP - Math.min(height, maxHeight) : belowTop,
|
|
4843
|
+
width,
|
|
4844
|
+
maxHeight
|
|
4845
|
+
});
|
|
4846
|
+
return;
|
|
4847
|
+
}
|
|
4155
4848
|
const top = r.top + h > window.innerHeight - VIEWPORT_MARGIN ? window.innerHeight - h - VIEWPORT_MARGIN : r.top;
|
|
4156
4849
|
setPos({
|
|
4157
4850
|
left: r.right + ANCHOR_GAP,
|
|
@@ -4159,7 +4852,7 @@ function HoverCard({ anchor, content, openDelayMs = 500, disabled = false, copyT
|
|
|
4159
4852
|
});
|
|
4160
4853
|
};
|
|
4161
4854
|
place();
|
|
4162
|
-
const observer = variant === "preview" && typeof ResizeObserver !== "undefined" ? new ResizeObserver(place) : null;
|
|
4855
|
+
const observer = (variant === "preview" || inline) && typeof ResizeObserver !== "undefined" ? new ResizeObserver(place) : null;
|
|
4163
4856
|
for (const element of [
|
|
4164
4857
|
cardRef.current,
|
|
4165
4858
|
rootRef.current,
|
|
@@ -4176,10 +4869,11 @@ function HoverCard({ anchor, content, openDelayMs = 500, disabled = false, copyT
|
|
|
4176
4869
|
open,
|
|
4177
4870
|
variant,
|
|
4178
4871
|
widthAnchorRef,
|
|
4179
|
-
positioned
|
|
4872
|
+
positioned,
|
|
4873
|
+
inline
|
|
4180
4874
|
]);
|
|
4181
4875
|
useLayoutEffect(() => {
|
|
4182
|
-
if (!open || pos === null || variant === "preview") return;
|
|
4876
|
+
if (!open || pos === null || variant === "preview" || inline || suppressed) return;
|
|
4183
4877
|
/* v8 ignore next -- the card is mounted whenever pos is set, so the ref is attached here. */
|
|
4184
4878
|
const h = cardRef.current?.offsetHeight ?? 0;
|
|
4185
4879
|
if (pos.top + h > window.innerHeight - VIEWPORT_MARGIN) setPos({
|
|
@@ -4189,7 +4883,9 @@ function HoverCard({ anchor, content, openDelayMs = 500, disabled = false, copyT
|
|
|
4189
4883
|
}, [
|
|
4190
4884
|
open,
|
|
4191
4885
|
pos,
|
|
4192
|
-
variant
|
|
4886
|
+
variant,
|
|
4887
|
+
inline,
|
|
4888
|
+
suppressed
|
|
4193
4889
|
]);
|
|
4194
4890
|
const copy = async (text) => {
|
|
4195
4891
|
if (copied || copyingRef.current) return;
|
|
@@ -4211,9 +4907,9 @@ function HoverCard({ anchor, content, openDelayMs = 500, disabled = false, copyT
|
|
|
4211
4907
|
cancelClose();
|
|
4212
4908
|
close();
|
|
4213
4909
|
};
|
|
4214
|
-
const card = open && pos !== null && jsx("div", {
|
|
4910
|
+
const card = open && pos !== null && !suppressed && jsx("div", {
|
|
4215
4911
|
ref: cardRef,
|
|
4216
|
-
className: clsx(css$
|
|
4912
|
+
className: clsx(css$16.card, variant === "preview" && css$16.preview, inline && css$16.media, copyable && css$16.copyable, copied && css$16.feedback),
|
|
4217
4913
|
"data-closing": closing || void 0,
|
|
4218
4914
|
style: {
|
|
4219
4915
|
...pos,
|
|
@@ -4236,16 +4932,29 @@ function HoverCard({ anchor, content, openDelayMs = 500, disabled = false, copyT
|
|
|
4236
4932
|
copy(copyText);
|
|
4237
4933
|
} : void 0,
|
|
4238
4934
|
children: copied ? jsx("span", {
|
|
4239
|
-
className: css$
|
|
4935
|
+
className: css$16.copied,
|
|
4240
4936
|
"aria-hidden": "true",
|
|
4241
4937
|
children: copiedLabel
|
|
4242
4938
|
}) : content
|
|
4243
4939
|
});
|
|
4244
4940
|
return jsxs("span", {
|
|
4245
4941
|
ref: rootRef,
|
|
4246
|
-
className: css$
|
|
4247
|
-
|
|
4248
|
-
if (disabled)
|
|
4942
|
+
className: clsx(css$16.root, inline && css$16.inline),
|
|
4943
|
+
onFocus: inline ? (event) => {
|
|
4944
|
+
if (!disabled && event.target.matches(":focus-visible")) {
|
|
4945
|
+
cancelClose();
|
|
4946
|
+
setPhase("open");
|
|
4947
|
+
}
|
|
4948
|
+
} : void 0,
|
|
4949
|
+
onBlur: inline ? (event) => {
|
|
4950
|
+
if (!event.currentTarget.contains(event.relatedTarget)) {
|
|
4951
|
+
clearTimer();
|
|
4952
|
+
cancelClose();
|
|
4953
|
+
close();
|
|
4954
|
+
}
|
|
4955
|
+
} : void 0,
|
|
4956
|
+
onPointerEnter: (event) => {
|
|
4957
|
+
if (disabled || inline && event.pointerType === "touch") return;
|
|
4249
4958
|
cancelClose();
|
|
4250
4959
|
if (open) {
|
|
4251
4960
|
setPhase("open");
|
|
@@ -4263,9 +4972,12 @@ function HoverCard({ anchor, content, openDelayMs = 500, disabled = false, copyT
|
|
|
4263
4972
|
onPointerDownCapture: dismissFromAnchor,
|
|
4264
4973
|
onClickCapture: dismissFromAnchor,
|
|
4265
4974
|
children: [
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
|
|
4975
|
+
jsx(TooltipSuppression.Provider, {
|
|
4976
|
+
value: setSuppressed,
|
|
4977
|
+
children: anchor
|
|
4978
|
+
}),
|
|
4979
|
+
open && !suppressed && copyable && jsx("span", {
|
|
4980
|
+
className: css$16.status,
|
|
4269
4981
|
role: "status",
|
|
4270
4982
|
children: copied ? copiedLabel : ""
|
|
4271
4983
|
}),
|
|
@@ -4278,104 +4990,77 @@ function HoverCard({ anchor, content, openDelayMs = 500, disabled = false, copyT
|
|
|
4278
4990
|
/**
|
|
4279
4991
|
* Render a centered, body-portaled modal over a blurred page mask.
|
|
4280
4992
|
* @param props.open - whether the dialog is showing.
|
|
4281
|
-
* @param props.onClose - Escape or mask click; while a menu is open inside the
|
|
4993
|
+
* @param props.onClose - application close command, Escape, or mask click; while a menu is open inside the
|
|
4282
4994
|
* dialog, Escape belongs to that menu first.
|
|
4283
4995
|
* @param props.title - dialog heading (aria-label in every mode).
|
|
4284
4996
|
* @param props.closeLabel - localized accessible close-button label.
|
|
4285
4997
|
* @param props.description - optional supporting sentence under the title.
|
|
4286
|
-
* @param props.children - body
|
|
4998
|
+
* @param props.children - dialog body; mark its initial-focus control with
|
|
4999
|
+
* data-modal-autofocus instead of React autoFocus to preserve return focus.
|
|
4287
5000
|
* @param props.footer - action row (Cancel / Create).
|
|
4288
5001
|
* @param props.contentClassName - optional class for a scrollable content region.
|
|
5002
|
+
* @param props.backdropBlur - disable when the caller already blurs the page; defaults to true.
|
|
5003
|
+
* @param props.shortcutModal - command scope allowed by shortcut owners; unnamed
|
|
5004
|
+
* dialogs block application commands unless their owner allows the "other" scope.
|
|
4289
5005
|
* @param props.headless - render children directly in the card (no default
|
|
4290
5006
|
* header/close/body chrome); mask, card, Escape, and aria-label remain.
|
|
5007
|
+
* @param props.onKeyDownCapture - handle a nested dialog's keys before the document Escape listeners.
|
|
4291
5008
|
* @returns null when closed; otherwise the overlay tree.
|
|
4292
5009
|
*/
|
|
4293
|
-
function Modal({ open, onClose, title, closeLabel, description, children, footer, className, contentClassName, headless = false }) {
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
const onKeyDown = (e) => {
|
|
4297
|
-
if (e.key === "Escape") onClose();
|
|
4298
|
-
};
|
|
4299
|
-
document.addEventListener("keydown", onKeyDown);
|
|
4300
|
-
return () => {
|
|
4301
|
-
document.removeEventListener("keydown", onKeyDown);
|
|
4302
|
-
};
|
|
4303
|
-
}, [open, onClose]);
|
|
5010
|
+
function Modal({ open, onClose, title, closeLabel, description, children, footer, className, contentClassName, onKeyDownCapture, headless = false, backdropBlur = true, shortcutModal }) {
|
|
5011
|
+
const dialog = useRef(null);
|
|
5012
|
+
useModalLayer(dialog, open, onClose);
|
|
4304
5013
|
if (!open) return null;
|
|
4305
5014
|
return createPortal(jsxs("div", {
|
|
4306
|
-
className: css$
|
|
5015
|
+
className: css$17.root,
|
|
4307
5016
|
role: "presentation",
|
|
5017
|
+
onKeyDownCapture,
|
|
4308
5018
|
children: [jsx("div", {
|
|
4309
|
-
className: css$
|
|
5019
|
+
className: css$17.mask,
|
|
5020
|
+
style: backdropBlur ? void 0 : { backdropFilter: "none" },
|
|
4310
5021
|
"aria-hidden": "true",
|
|
4311
5022
|
onClick: onClose
|
|
4312
5023
|
}), jsx("div", {
|
|
4313
|
-
|
|
5024
|
+
ref: dialog,
|
|
5025
|
+
tabIndex: -1,
|
|
5026
|
+
"data-shortcut-modal": shortcutModal,
|
|
5027
|
+
className: clsx(css$17.dialog, className),
|
|
4314
5028
|
role: "dialog",
|
|
4315
5029
|
"aria-modal": "true",
|
|
4316
5030
|
"aria-label": title,
|
|
4317
5031
|
children: headless ? children : jsxs(Fragment, { children: [jsxs("div", {
|
|
4318
|
-
className: clsx(css$
|
|
5032
|
+
className: clsx(css$17.content, contentClassName),
|
|
4319
5033
|
children: [
|
|
4320
5034
|
jsxs("div", {
|
|
4321
|
-
className: css$
|
|
5035
|
+
className: css$17.header,
|
|
4322
5036
|
children: [jsx("h2", {
|
|
4323
|
-
className: css$
|
|
5037
|
+
className: css$17.title,
|
|
4324
5038
|
children: title
|
|
4325
5039
|
}), jsx("button", {
|
|
4326
5040
|
type: "button",
|
|
4327
|
-
className: css$
|
|
5041
|
+
className: css$17.close,
|
|
4328
5042
|
"aria-label": closeLabel,
|
|
4329
5043
|
onClick: onClose,
|
|
4330
5044
|
children: jsx(IconCloseOutlineRegular, { size: 14 })
|
|
4331
5045
|
})]
|
|
4332
5046
|
}),
|
|
4333
5047
|
description !== void 0 && description !== "" && jsx("p", {
|
|
4334
|
-
className: css$
|
|
5048
|
+
className: css$17.description,
|
|
4335
5049
|
children: description
|
|
4336
5050
|
}),
|
|
4337
5051
|
children !== void 0 && jsx("div", {
|
|
4338
|
-
className: css$
|
|
5052
|
+
className: css$17.body,
|
|
4339
5053
|
children
|
|
4340
5054
|
})
|
|
4341
5055
|
]
|
|
4342
5056
|
}), footer !== void 0 && jsx("div", {
|
|
4343
|
-
className: css$
|
|
5057
|
+
className: css$17.footer,
|
|
4344
5058
|
children: footer
|
|
4345
5059
|
})] })
|
|
4346
5060
|
})]
|
|
4347
5061
|
}), document.body);
|
|
4348
5062
|
}
|
|
4349
5063
|
//#endregion
|
|
4350
|
-
//#region lib/types/OnboardingSurface.js
|
|
4351
|
-
/**
|
|
4352
|
-
* Render a body-portaled onboarding stage and keep the application root inert
|
|
4353
|
-
* while mounted.
|
|
4354
|
-
* @param props.children - the step's page content, centered on the stage.
|
|
4355
|
-
* @returns the body-portaled overlay tree.
|
|
4356
|
-
*/
|
|
4357
|
-
function OnboardingSurface({ children }) {
|
|
4358
|
-
useEffect(() => {
|
|
4359
|
-
const appRoot = document.getElementById("root");
|
|
4360
|
-
if (appRoot === null) return;
|
|
4361
|
-
appRoot.inert = true;
|
|
4362
|
-
return () => {
|
|
4363
|
-
appRoot.inert = false;
|
|
4364
|
-
};
|
|
4365
|
-
}, []);
|
|
4366
|
-
return createPortal(jsxs("div", {
|
|
4367
|
-
className: css$15.onboardingOverlay,
|
|
4368
|
-
role: "presentation",
|
|
4369
|
-
children: [jsx("div", {
|
|
4370
|
-
className: css$15.onboardingMask,
|
|
4371
|
-
"aria-hidden": "true"
|
|
4372
|
-
}), jsx("div", {
|
|
4373
|
-
className: css$15.onboardingStage,
|
|
4374
|
-
children
|
|
4375
|
-
})]
|
|
4376
|
-
}), document.body);
|
|
4377
|
-
}
|
|
4378
|
-
//#endregion
|
|
4379
5064
|
//#region lib/types/RiskConfirmation.js
|
|
4380
5065
|
/**
|
|
4381
5066
|
* Controlled risk acknowledgement dialog shared by product surfaces that
|
|
@@ -4391,33 +5076,33 @@ function RiskConfirmation({ open, title, description, acknowledgeLabel, cancelLa
|
|
|
4391
5076
|
onClose: onCancel,
|
|
4392
5077
|
title,
|
|
4393
5078
|
closeLabel,
|
|
4394
|
-
className: css$
|
|
4395
|
-
contentClassName: css$
|
|
5079
|
+
className: css$18.confirmation ?? "",
|
|
5080
|
+
contentClassName: css$18.confirmationContent ?? "",
|
|
4396
5081
|
footer: jsxs(Fragment, { children: [jsx(Button, {
|
|
4397
5082
|
variant: "outline",
|
|
4398
|
-
className: css$
|
|
5083
|
+
className: css$18.modalAction,
|
|
4399
5084
|
onClick: onCancel,
|
|
4400
5085
|
children: cancelLabel
|
|
4401
5086
|
}), jsx(Button, {
|
|
4402
5087
|
variant: "primary",
|
|
4403
|
-
className: css$
|
|
5088
|
+
className: css$18.confirmAction,
|
|
4404
5089
|
disabled: disabled || !acknowledged,
|
|
4405
5090
|
onClick: onConfirm,
|
|
4406
5091
|
children: confirmLabel
|
|
4407
5092
|
})] }),
|
|
4408
5093
|
children: [jsxs("div", {
|
|
4409
|
-
className: css$
|
|
5094
|
+
className: css$18.warning,
|
|
4410
5095
|
children: [jsx(IconWarningOutlineRegular, {
|
|
4411
5096
|
size: 18,
|
|
4412
|
-
className: css$
|
|
5097
|
+
className: css$18.warningIcon
|
|
4413
5098
|
}), jsx("p", { children: description })]
|
|
4414
5099
|
}), jsxs("label", {
|
|
4415
|
-
className: css$
|
|
5100
|
+
className: css$18.acknowledgement,
|
|
4416
5101
|
children: [jsx("input", {
|
|
4417
5102
|
type: "checkbox",
|
|
4418
5103
|
checked: acknowledged,
|
|
4419
5104
|
disabled,
|
|
4420
|
-
|
|
5105
|
+
"data-modal-autofocus": true,
|
|
4421
5106
|
onChange: (event) => {
|
|
4422
5107
|
onAcknowledgedChange(event.currentTarget.checked);
|
|
4423
5108
|
}
|
|
@@ -4460,44 +5145,44 @@ function ConnectionIndicator({ state, disconnectedLabel, connectingLabel, recove
|
|
|
4460
5145
|
};
|
|
4461
5146
|
}, [state, rendered]);
|
|
4462
5147
|
if (rendered === void 0) return null;
|
|
4463
|
-
const leavingClass = leaving ? ` ${css$
|
|
5148
|
+
const leavingClass = leaving ? ` ${css$19.leaving}` : "";
|
|
4464
5149
|
if (rendered === "recovered") return jsxs("div", {
|
|
4465
|
-
className: `${css$
|
|
5150
|
+
className: `${css$19.indicator} ${css$19.success}${leavingClass}`,
|
|
4466
5151
|
role: "status",
|
|
4467
5152
|
"aria-label": recoveredLabel,
|
|
4468
5153
|
children: [jsx("span", {
|
|
4469
|
-
className: css$
|
|
5154
|
+
className: css$19.icon,
|
|
4470
5155
|
"aria-hidden": "true",
|
|
4471
5156
|
children: jsx(IconCheckOutlineRegular, { size: 14 })
|
|
4472
5157
|
}), jsx("span", {
|
|
4473
|
-
className: css$
|
|
5158
|
+
className: css$19.label,
|
|
4474
5159
|
children: recoveredLabel
|
|
4475
5160
|
})]
|
|
4476
5161
|
});
|
|
4477
5162
|
const connecting = rendered === "connecting";
|
|
4478
5163
|
return jsxs("button", {
|
|
4479
5164
|
type: "button",
|
|
4480
|
-
className: `${css$
|
|
5165
|
+
className: `${css$19.indicator} ${css$19.warning}${leavingClass}`,
|
|
4481
5166
|
"data-phase": rendered,
|
|
4482
5167
|
"aria-label": connecting ? restartActionLabel : reconnectActionLabel,
|
|
4483
5168
|
onClick: onReconnect,
|
|
4484
5169
|
children: [jsx("span", {
|
|
4485
|
-
className: css$
|
|
5170
|
+
className: css$19.icon,
|
|
4486
5171
|
"aria-hidden": "true",
|
|
4487
5172
|
children: connecting ? jsx(StateDot, { state: "ongoing" }) : jsx(IconRefreshOutlineRegular, { size: 14 })
|
|
4488
5173
|
}), jsx("span", {
|
|
4489
|
-
className: css$
|
|
5174
|
+
className: css$19.label,
|
|
4490
5175
|
children: connecting ? jsxs(Fragment, { children: [connectingLabel, jsxs("span", {
|
|
4491
|
-
className: css$
|
|
5176
|
+
className: css$19.dots,
|
|
4492
5177
|
"aria-hidden": "true",
|
|
4493
5178
|
children: [
|
|
4494
5179
|
jsx("span", { children: "." }),
|
|
4495
5180
|
jsx("span", {
|
|
4496
|
-
className: css$
|
|
5181
|
+
className: css$19.secondDot,
|
|
4497
5182
|
children: "."
|
|
4498
5183
|
}),
|
|
4499
5184
|
jsx("span", {
|
|
4500
|
-
className: css$
|
|
5185
|
+
className: css$19.thirdDot,
|
|
4501
5186
|
children: "."
|
|
4502
5187
|
})
|
|
4503
5188
|
]
|
|
@@ -4814,7 +5499,7 @@ function PermissionIconFullAccessMedium(props) {
|
|
|
4814
5499
|
*/
|
|
4815
5500
|
function ReferenceIconArtwork({ kind, size = 16, className, strokeWidth }) {
|
|
4816
5501
|
switch (kind) {
|
|
4817
|
-
case "session": return jsx(
|
|
5502
|
+
case "session": return jsx(ChatLinesOutlineArtwork, {
|
|
4818
5503
|
size,
|
|
4819
5504
|
className,
|
|
4820
5505
|
strokeWidth
|
|
@@ -5400,14 +6085,23 @@ function glyph(type, size, className) {
|
|
|
5400
6085
|
case "code": return jsxs(FileGlyph, {
|
|
5401
6086
|
size,
|
|
5402
6087
|
className,
|
|
5403
|
-
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
|
|
5410
|
-
|
|
6088
|
+
children: [
|
|
6089
|
+
jsx("path", {
|
|
6090
|
+
d: "M10.0053 13.126L7.0236 16.3788C6.96052 16.4476 6.96052 16.5532 7.0236 16.622L10.0053 19.8748",
|
|
6091
|
+
stroke: "currentColor",
|
|
6092
|
+
strokeWidth: "1.35"
|
|
6093
|
+
}),
|
|
6094
|
+
jsx("path", {
|
|
6095
|
+
d: "M17.9941 13.126L20.9759 16.3788C21.039 16.4476 21.039 16.5532 20.9759 16.622L17.9941 19.8748",
|
|
6096
|
+
stroke: "currentColor",
|
|
6097
|
+
strokeWidth: "1.35"
|
|
6098
|
+
}),
|
|
6099
|
+
jsx("path", {
|
|
6100
|
+
d: "M15.2652 12.957L12.7344 20.0433",
|
|
6101
|
+
stroke: "currentColor",
|
|
6102
|
+
strokeWidth: "1.35"
|
|
6103
|
+
})
|
|
6104
|
+
]
|
|
5411
6105
|
});
|
|
5412
6106
|
case "excel": return jsx(SpreadsheetGlyph, {
|
|
5413
6107
|
size,
|
|
@@ -5519,7 +6213,7 @@ function FileTypeIcon(props) {
|
|
|
5519
6213
|
type: resolvedType,
|
|
5520
6214
|
size,
|
|
5521
6215
|
className
|
|
5522
|
-
}) : glyph(resolvedType, size, clsx(css$
|
|
6216
|
+
}) : glyph(resolvedType, size, clsx(css$20.icon, css$20[resolvedType], className));
|
|
5523
6217
|
}
|
|
5524
6218
|
//#endregion
|
|
5525
6219
|
//#region lib/types/SiteGlyph.js
|
|
@@ -5817,284 +6511,82 @@ function projectUserText(text, sessionLabels, slashNames = [], slashKind = "skil
|
|
|
5817
6511
|
for (const rawLabel of [...new Set(sessionLabels)].sort((a, b) => b.length - a.length)) {
|
|
5818
6512
|
const label = `@${rawLabel}`;
|
|
5819
6513
|
let start = text.indexOf(label);
|
|
5820
|
-
while (start >= 0) {
|
|
5821
|
-
ranges.push({
|
|
5822
|
-
start,
|
|
5823
|
-
end: start + label.length,
|
|
5824
|
-
label,
|
|
5825
|
-
kind: "session"
|
|
5826
|
-
});
|
|
5827
|
-
start = text.indexOf(label, start + label.length);
|
|
5828
|
-
}
|
|
5829
|
-
}
|
|
5830
|
-
const re = /(^|\s)(\/[\w-]+(?=\s|$)|@"[^"\n]+"|@[^\s]+)/gu;
|
|
5831
|
-
let m;
|
|
5832
|
-
while ((m = re.exec(text)) !== null) {
|
|
5833
|
-
const tokenStart = m.index + m[1].length;
|
|
5834
|
-
const rawLabel = m[2];
|
|
5835
|
-
const label = rawLabel.startsWith("@\"") ? rawLabel : rawLabel.replace(TRAILING_PUNCTUATION_RE, "");
|
|
5836
|
-
if (label.length <= 1) continue;
|
|
5837
|
-
if (label.startsWith("/") && !slashNames.includes(label.slice(1))) continue;
|
|
5838
|
-
ranges.push({
|
|
5839
|
-
start: tokenStart,
|
|
5840
|
-
end: tokenStart + label.length,
|
|
5841
|
-
label,
|
|
5842
|
-
kind: "plain"
|
|
5843
|
-
});
|
|
5844
|
-
}
|
|
5845
|
-
const rankOf = (range) => range.kind === "session" ? 0 : 1;
|
|
5846
|
-
ranges.sort((a, b) => a.start - b.start || rankOf(a) - rankOf(b) || b.end - a.end);
|
|
5847
|
-
const parts = [];
|
|
5848
|
-
let cursor = 0;
|
|
5849
|
-
const pushPlain = (from, to) => {
|
|
5850
|
-
parts.push(jsx("span", {
|
|
5851
|
-
className: css$19.plainRun,
|
|
5852
|
-
children: text.slice(from, to)
|
|
5853
|
-
}, `t${from}`));
|
|
5854
|
-
};
|
|
5855
|
-
for (const range of ranges) {
|
|
5856
|
-
if (range.start < cursor) continue;
|
|
5857
|
-
const { start: tokenStart, end, label, kind } = range;
|
|
5858
|
-
if (tokenStart > cursor) pushPlain(cursor, tokenStart);
|
|
5859
|
-
const referenceKind = kind === "session" ? "session" : label.startsWith("@") ? label.replace(/^@"|"$/gu, "").endsWith("/") ? "folder" : "file" : void 0;
|
|
5860
|
-
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));
|
|
5861
|
-
const contents = jsxs(Fragment, { children: [referenceKind !== void 0 && jsx(ReferenceIconRegular, {
|
|
5862
|
-
kind: referenceKind,
|
|
5863
|
-
size: 16,
|
|
5864
|
-
className: css$19.refIcon
|
|
5865
|
-
}), displayLabel] });
|
|
5866
|
-
const open = references === void 0 ? void 0 : referenceKind === "file" ? () => {
|
|
5867
|
-
references.openFile(label.slice(1).replace(/^"|"$/gu, ""));
|
|
5868
|
-
} : referenceKind === void 0 && slashKind === "skill" ? () => {
|
|
5869
|
-
references.openSkill(label.slice(1));
|
|
5870
|
-
} : void 0;
|
|
5871
|
-
const className = clsx(css$19.refChip, referenceKind === void 0 && css$19.slashChip);
|
|
5872
|
-
parts.push(open === void 0 ? jsx("span", {
|
|
5873
|
-
className,
|
|
5874
|
-
"data-ref-chip": referenceKind ?? slashKind,
|
|
5875
|
-
title: label,
|
|
5876
|
-
children: contents
|
|
5877
|
-
}, tokenStart) : jsx("button", {
|
|
5878
|
-
type: "button",
|
|
5879
|
-
className: clsx(className, markdownCss.fileMention),
|
|
5880
|
-
"data-ref-chip": referenceKind ?? slashKind,
|
|
5881
|
-
title: label,
|
|
5882
|
-
onClick: (event) => {
|
|
5883
|
-
if (event.detail > 1 || event.detail !== 0 && event.currentTarget.ownerDocument.getSelection()?.isCollapsed === false) return;
|
|
5884
|
-
open();
|
|
5885
|
-
},
|
|
5886
|
-
children: contents
|
|
5887
|
-
}, tokenStart));
|
|
5888
|
-
cursor = end;
|
|
5889
|
-
}
|
|
5890
|
-
if (parts.length === 0) return jsx("span", {
|
|
5891
|
-
className: css$19.plainRun,
|
|
5892
|
-
children: text
|
|
5893
|
-
});
|
|
5894
|
-
if (cursor < text.length) pushPlain(cursor, text.length);
|
|
5895
|
-
return jsx(Fragment, { children: parts });
|
|
5896
|
-
}
|
|
5897
|
-
//#endregion
|
|
5898
|
-
//#region lib/types/Tooltip.js
|
|
5899
|
-
/** Anchor-preserving tooltips with optional body portals for clipping containers. */
|
|
5900
|
-
/**
|
|
5901
|
-
* Suppression channel from a tooltip to the tooltips above it: a tooltip hands
|
|
5902
|
-
* this setter to its own descendants, and a visible descendant bubble calls it
|
|
5903
|
-
* so the ancestor withdraws its bubble for as long as the descendant shows one.
|
|
5904
|
-
*/
|
|
5905
|
-
const TooltipSuppression = createContext(null);
|
|
5906
|
-
let pointerModality = false;
|
|
5907
|
-
if (typeof window !== "undefined") {
|
|
5908
|
-
window.addEventListener("pointerdown", () => {
|
|
5909
|
-
pointerModality = true;
|
|
5910
|
-
}, true);
|
|
5911
|
-
window.addEventListener("keydown", () => {
|
|
5912
|
-
pointerModality = false;
|
|
5913
|
-
}, true);
|
|
5914
|
-
}
|
|
5915
|
-
/**
|
|
5916
|
-
* Attach a hover/focus tooltip to an anchor element.
|
|
5917
|
-
* @param props.label - bubble text, or a resolver evaluated only while the bubble is visible.
|
|
5918
|
-
* @param props.side - placement relative to the anchor (default 'right').
|
|
5919
|
-
* @param props.align - horizontal anchor-edge alignment for 'bottom'/'top' bubbles: 'end' pins
|
|
5920
|
-
* the bubble's right edge to the anchor's (for anchors beside other hover surfaces the centered
|
|
5921
|
-
* bubble would overlap); default 'center'. Ignored for side 'right'.
|
|
5922
|
-
* @param props.portal - render the bubble under document.body to escape containing blocks and clipping ancestors.
|
|
5923
|
-
* @param props.delayMs - hover delay in milliseconds; keyboard focus remains immediate.
|
|
5924
|
-
* @param props.disabled - suppress the bubble while true; the anchor renders identically so
|
|
5925
|
-
* toggling never remounts it (which would cut its CSS transitions).
|
|
5926
|
-
* @param props.maxWidth - bubble width cap in pixels, for labels long enough that the default
|
|
5927
|
-
* half-viewport cap would render a slab wider than the surface the anchor sits on.
|
|
5928
|
-
* @param props.children - a single anchor element; its own ref (callback or object) is forwarded alongside the tooltip's.
|
|
5929
|
-
* @returns the cloned anchor plus a fixed-position bubble, optionally portaled to the body.
|
|
5930
|
-
* The bubble stays hidden until ResizeObserver supplies its size for viewport fitting; clicking the
|
|
5931
|
-
* anchor dismisses the bubble until the next trigger, and focus arriving after a pointer
|
|
5932
|
-
* interaction (a closing menu refocusing its trigger) never raises it.
|
|
5933
|
-
*/
|
|
5934
|
-
function Tooltip({ label, side = "right", align = "center", delayMs = 0, disabled = false, portal = false, maxWidth, children }) {
|
|
5935
|
-
const anchor = useRef(null);
|
|
5936
|
-
const childRef = children.ref;
|
|
5937
|
-
const mergedRef = useCallback((el) => {
|
|
5938
|
-
anchor.current = el;
|
|
5939
|
-
if (typeof childRef === "function") childRef(el);
|
|
5940
|
-
else if (childRef != null) childRef.current = el;
|
|
5941
|
-
}, [childRef]);
|
|
5942
|
-
const [pos, setPos] = useState(null);
|
|
5943
|
-
const bubble = useRef(null);
|
|
5944
|
-
const resolvedLabel = pos === null ? null : typeof label === "function" ? label() : label;
|
|
5945
|
-
const y = pos === null ? 0 : side === "right" ? pos.top + (pos.bottom - pos.top) / 2 : side === "top" ? pos.top - 8 : pos.bottom + 8;
|
|
5946
|
-
const showTimer = useRef(null);
|
|
5947
|
-
const triggers = useRef({
|
|
5948
|
-
hover: false,
|
|
5949
|
-
focus: false
|
|
5950
|
-
});
|
|
5951
|
-
const suppressAncestors = useContext(TooltipSuppression);
|
|
5952
|
-
const [suppressed, setSuppressed] = useState(false);
|
|
5953
|
-
const announce = useCallback((active) => {
|
|
5954
|
-
suppressAncestors?.(active);
|
|
5955
|
-
}, [suppressAncestors]);
|
|
5956
|
-
const visible = pos !== null && !disabled;
|
|
5957
|
-
useEffect(() => {
|
|
5958
|
-
const el = bubble.current;
|
|
5959
|
-
if (pos === null || !visible || suppressed || el === null) return;
|
|
5960
|
-
const edgeMargin = 12;
|
|
5961
|
-
let size;
|
|
5962
|
-
let placement = side;
|
|
5963
|
-
const fit = () => {
|
|
5964
|
-
if (size === void 0) return;
|
|
5965
|
-
const { inlineSize: width, blockSize: height } = size;
|
|
5966
|
-
const offset = side === "right" ? 0 : align === "end" ? width : width / 2;
|
|
5967
|
-
const left = Math.max(edgeMargin, Math.min(pos.x - offset, window.innerWidth - edgeMargin - width));
|
|
5968
|
-
const fitsBelow = pos.bottom + 8 + height <= window.innerHeight - edgeMargin;
|
|
5969
|
-
const fitsAbove = pos.top - 8 - height >= edgeMargin;
|
|
5970
|
-
if (placement === "bottom" && !fitsBelow && fitsAbove) placement = "top";
|
|
5971
|
-
else if (placement === "top" && !fitsAbove && fitsBelow) placement = "bottom";
|
|
5972
|
-
el.style.left = `${left + offset}px`;
|
|
5973
|
-
el.style.top = `${placement === "right" ? (pos.top + pos.bottom) / 2 : placement === "top" ? pos.top - 8 : pos.bottom + 8}px`;
|
|
5974
|
-
el.dataset.side = placement;
|
|
5975
|
-
el.style.visibility = "visible";
|
|
5976
|
-
};
|
|
5977
|
-
const observer = new ResizeObserver((entries) => {
|
|
5978
|
-
size = entries[0]?.borderBoxSize[0];
|
|
5979
|
-
fit();
|
|
5980
|
-
});
|
|
5981
|
-
observer.observe(el, { box: "border-box" });
|
|
5982
|
-
window.addEventListener("resize", fit);
|
|
5983
|
-
return () => {
|
|
5984
|
-
observer.disconnect();
|
|
5985
|
-
window.removeEventListener("resize", fit);
|
|
5986
|
-
};
|
|
5987
|
-
}, [
|
|
5988
|
-
align,
|
|
5989
|
-
pos,
|
|
5990
|
-
side,
|
|
5991
|
-
suppressed,
|
|
5992
|
-
visible
|
|
5993
|
-
]);
|
|
5994
|
-
useEffect(() => {
|
|
5995
|
-
announce(visible);
|
|
5996
|
-
return () => {
|
|
5997
|
-
announce(false);
|
|
5998
|
-
};
|
|
5999
|
-
}, [announce, visible]);
|
|
6000
|
-
const cancelShow = useCallback(() => {
|
|
6001
|
-
if (showTimer.current === null) return;
|
|
6002
|
-
clearTimeout(showTimer.current);
|
|
6003
|
-
showTimer.current = null;
|
|
6004
|
-
}, []);
|
|
6005
|
-
useEffect(() => {
|
|
6006
|
-
if (disabled) {
|
|
6007
|
-
cancelShow();
|
|
6008
|
-
triggers.current = {
|
|
6009
|
-
hover: false,
|
|
6010
|
-
focus: false
|
|
6011
|
-
};
|
|
6012
|
-
setPos(null);
|
|
6514
|
+
while (start >= 0) {
|
|
6515
|
+
ranges.push({
|
|
6516
|
+
start,
|
|
6517
|
+
end: start + label.length,
|
|
6518
|
+
label,
|
|
6519
|
+
kind: "session"
|
|
6520
|
+
});
|
|
6521
|
+
start = text.indexOf(label, start + label.length);
|
|
6013
6522
|
}
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
|
|
6017
|
-
|
|
6018
|
-
const
|
|
6019
|
-
|
|
6020
|
-
|
|
6021
|
-
|
|
6022
|
-
|
|
6023
|
-
|
|
6024
|
-
|
|
6025
|
-
|
|
6523
|
+
}
|
|
6524
|
+
const re = /(^|\s)(\/[\w-]+(?=\s|$)|@"[^"\n]+"|@[^\s]+)/gu;
|
|
6525
|
+
let m;
|
|
6526
|
+
while ((m = re.exec(text)) !== null) {
|
|
6527
|
+
const tokenStart = m.index + m[1].length;
|
|
6528
|
+
const rawLabel = m[2];
|
|
6529
|
+
const label = rawLabel.startsWith("@\"") ? rawLabel : rawLabel.replace(TRAILING_PUNCTUATION_RE, "");
|
|
6530
|
+
if (label.length <= 1) continue;
|
|
6531
|
+
if (label.startsWith("/") && !slashNames.includes(label.slice(1))) continue;
|
|
6532
|
+
ranges.push({
|
|
6533
|
+
start: tokenStart,
|
|
6534
|
+
end: tokenStart + label.length,
|
|
6535
|
+
label,
|
|
6536
|
+
kind: "plain"
|
|
6026
6537
|
});
|
|
6027
|
-
|
|
6028
|
-
|
|
6029
|
-
|
|
6030
|
-
|
|
6031
|
-
|
|
6032
|
-
|
|
6033
|
-
|
|
6034
|
-
|
|
6035
|
-
|
|
6036
|
-
|
|
6037
|
-
show();
|
|
6038
|
-
}, delayMs);
|
|
6039
|
-
};
|
|
6040
|
-
const withdraw = () => {
|
|
6041
|
-
setPos(null);
|
|
6042
|
-
announce(false);
|
|
6043
|
-
};
|
|
6044
|
-
const hide = () => {
|
|
6045
|
-
cancelShow();
|
|
6046
|
-
if (!triggers.current.hover && !triggers.current.focus) withdraw();
|
|
6538
|
+
}
|
|
6539
|
+
const rankOf = (range) => range.kind === "session" ? 0 : 1;
|
|
6540
|
+
ranges.sort((a, b) => a.start - b.start || rankOf(a) - rankOf(b) || b.end - a.end);
|
|
6541
|
+
const parts = [];
|
|
6542
|
+
let cursor = 0;
|
|
6543
|
+
const pushPlain = (from, to) => {
|
|
6544
|
+
parts.push(jsx("span", {
|
|
6545
|
+
className: css$21.plainRun,
|
|
6546
|
+
children: text.slice(from, to)
|
|
6547
|
+
}, `t${from}`));
|
|
6047
6548
|
};
|
|
6048
|
-
const
|
|
6049
|
-
|
|
6050
|
-
|
|
6051
|
-
|
|
6052
|
-
"
|
|
6053
|
-
"
|
|
6054
|
-
|
|
6055
|
-
|
|
6056
|
-
|
|
6057
|
-
|
|
6058
|
-
|
|
6059
|
-
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
|
|
6063
|
-
|
|
6064
|
-
|
|
6065
|
-
|
|
6066
|
-
|
|
6067
|
-
|
|
6068
|
-
|
|
6069
|
-
|
|
6070
|
-
|
|
6071
|
-
|
|
6072
|
-
|
|
6073
|
-
|
|
6074
|
-
|
|
6075
|
-
|
|
6076
|
-
|
|
6077
|
-
|
|
6078
|
-
onClick: (e) => {
|
|
6079
|
-
children.props.onClick?.(e);
|
|
6080
|
-
triggers.current.focus = false;
|
|
6081
|
-
cancelShow();
|
|
6082
|
-
withdraw();
|
|
6083
|
-
},
|
|
6084
|
-
onFocus: (e) => {
|
|
6085
|
-
children.props.onFocus?.(e);
|
|
6086
|
-
if (pointerModality) return;
|
|
6087
|
-
triggers.current.focus = true;
|
|
6088
|
-
cancelShow();
|
|
6089
|
-
show();
|
|
6549
|
+
for (const range of ranges) {
|
|
6550
|
+
if (range.start < cursor) continue;
|
|
6551
|
+
const { start: tokenStart, end, label, kind } = range;
|
|
6552
|
+
if (tokenStart > cursor) pushPlain(cursor, tokenStart);
|
|
6553
|
+
const referenceKind = kind === "session" ? "session" : label.startsWith("@") ? label.replace(/^@"|"$/gu, "").endsWith("/") ? "folder" : "file" : void 0;
|
|
6554
|
+
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));
|
|
6555
|
+
const contents = jsxs(Fragment, { children: [referenceKind !== void 0 && jsx(ReferenceIconRegular, {
|
|
6556
|
+
kind: referenceKind,
|
|
6557
|
+
size: 16,
|
|
6558
|
+
className: css$21.refIcon
|
|
6559
|
+
}), displayLabel] });
|
|
6560
|
+
const open = references === void 0 ? void 0 : referenceKind === "file" ? () => {
|
|
6561
|
+
references.openFile(label.slice(1).replace(/^"|"$/gu, ""));
|
|
6562
|
+
} : referenceKind === void 0 && slashKind === "skill" ? () => {
|
|
6563
|
+
references.openSkill(label.slice(1));
|
|
6564
|
+
} : void 0;
|
|
6565
|
+
const className = clsx(css$21.refChip, referenceKind === void 0 && css$21.slashChip);
|
|
6566
|
+
parts.push(open === void 0 ? jsx("span", {
|
|
6567
|
+
className,
|
|
6568
|
+
"data-ref-chip": referenceKind ?? slashKind,
|
|
6569
|
+
title: label,
|
|
6570
|
+
children: contents
|
|
6571
|
+
}, tokenStart) : jsx("button", {
|
|
6572
|
+
type: "button",
|
|
6573
|
+
className: clsx(className, markdownCss.fileMention),
|
|
6574
|
+
"data-ref-chip": referenceKind ?? slashKind,
|
|
6575
|
+
title: label,
|
|
6576
|
+
onClick: (event) => {
|
|
6577
|
+
if (event.detail > 1 || event.detail !== 0 && event.currentTarget.ownerDocument.getSelection()?.isCollapsed === false) return;
|
|
6578
|
+
open();
|
|
6090
6579
|
},
|
|
6091
|
-
|
|
6092
|
-
|
|
6093
|
-
|
|
6094
|
-
|
|
6095
|
-
|
|
6096
|
-
|
|
6580
|
+
children: contents
|
|
6581
|
+
}, tokenStart));
|
|
6582
|
+
cursor = end;
|
|
6583
|
+
}
|
|
6584
|
+
if (parts.length === 0) return jsx("span", {
|
|
6585
|
+
className: css$21.plainRun,
|
|
6586
|
+
children: text
|
|
6097
6587
|
});
|
|
6588
|
+
if (cursor < text.length) pushPlain(cursor, text.length);
|
|
6589
|
+
return jsx(Fragment, { children: parts });
|
|
6098
6590
|
}
|
|
6099
6591
|
//#endregion
|
|
6100
6592
|
//#region lib/types/Toast.js
|
|
@@ -6163,25 +6655,25 @@ function Toast({ text, icon, tone, anchor, holdMs = HOLD_MS, actions, onDone })
|
|
|
6163
6655
|
};
|
|
6164
6656
|
}, [anchor]);
|
|
6165
6657
|
return createPortal(jsxs("div", {
|
|
6166
|
-
className: css$
|
|
6658
|
+
className: css$22.toast,
|
|
6167
6659
|
role: "alert",
|
|
6168
6660
|
style: {
|
|
6169
6661
|
...left === null ? {} : { left },
|
|
6170
6662
|
"--dsh-toast-hold": `${String(holdMs)}ms`
|
|
6171
6663
|
},
|
|
6172
6664
|
children: [tone === "success" ? jsx("span", {
|
|
6173
|
-
className: `${css$
|
|
6665
|
+
className: `${css$22.icon} ${css$22.success}`,
|
|
6174
6666
|
"aria-hidden": true,
|
|
6175
6667
|
children: jsx(IconCheckCircleOutlineRegular, {})
|
|
6176
6668
|
}) : icon !== void 0 && jsx("span", {
|
|
6177
|
-
className: css$
|
|
6669
|
+
className: css$22.icon,
|
|
6178
6670
|
"aria-hidden": true,
|
|
6179
6671
|
children: icon
|
|
6180
6672
|
}), jsxs("span", {
|
|
6181
|
-
className: css$
|
|
6673
|
+
className: css$22.text,
|
|
6182
6674
|
children: [text, actions?.map((action) => jsxs(Fragment$1, { children: [action.prefix, jsx("button", {
|
|
6183
6675
|
type: "button",
|
|
6184
|
-
className: css$
|
|
6676
|
+
className: css$22.action,
|
|
6185
6677
|
onClick: action.onClick,
|
|
6186
6678
|
children: action.label
|
|
6187
6679
|
})] }, action.label))]
|
|
@@ -6231,29 +6723,29 @@ function SettingsForm(props) {
|
|
|
6231
6723
|
discard.current();
|
|
6232
6724
|
}, []);
|
|
6233
6725
|
if (!state.available) return jsx("p", {
|
|
6234
|
-
className: css$
|
|
6726
|
+
className: css$23.unavailable,
|
|
6235
6727
|
role: "status",
|
|
6236
6728
|
children: labels.unavailable
|
|
6237
6729
|
});
|
|
6238
6730
|
const blocked = !state.dirty || state.invalid || state.saving;
|
|
6239
6731
|
return jsxs("div", {
|
|
6240
|
-
className: css$
|
|
6732
|
+
className: css$23.form,
|
|
6241
6733
|
children: [
|
|
6242
6734
|
!state.writable ? jsx("p", {
|
|
6243
|
-
className: css$
|
|
6735
|
+
className: css$23.readOnly,
|
|
6244
6736
|
role: "status",
|
|
6245
6737
|
children: labels.readOnly
|
|
6246
6738
|
}) : null,
|
|
6247
6739
|
props.children,
|
|
6248
6740
|
jsxs("div", {
|
|
6249
|
-
className: css$
|
|
6741
|
+
className: css$23.footer,
|
|
6250
6742
|
children: [state.failed ? jsx("p", {
|
|
6251
|
-
className: css$
|
|
6743
|
+
className: css$23.failed,
|
|
6252
6744
|
role: "status",
|
|
6253
6745
|
children: labels.saveFailed
|
|
6254
6746
|
}) : null, jsx("button", {
|
|
6255
6747
|
type: "button",
|
|
6256
|
-
className: css$
|
|
6748
|
+
className: css$23.save,
|
|
6257
6749
|
disabled: blocked,
|
|
6258
6750
|
onClick: props.onSave,
|
|
6259
6751
|
children: state.saving ? labels.saving : labels.save
|
|
@@ -6285,19 +6777,19 @@ function SettingsValueField(props) {
|
|
|
6285
6777
|
const hasMessage = props.invalid || Boolean(props.hint);
|
|
6286
6778
|
const description = [hasMessage ? messageId : "", helpOpen ? helpId : ""].filter(Boolean).join(" ");
|
|
6287
6779
|
return jsxs("div", {
|
|
6288
|
-
className: css$
|
|
6780
|
+
className: css$24.field,
|
|
6289
6781
|
children: [
|
|
6290
6782
|
jsxs("div", {
|
|
6291
|
-
className: css$
|
|
6783
|
+
className: css$24.head,
|
|
6292
6784
|
children: [jsxs("div", {
|
|
6293
|
-
className: css$
|
|
6785
|
+
className: css$24.labelGroup,
|
|
6294
6786
|
children: [jsx("label", {
|
|
6295
|
-
className: css$
|
|
6787
|
+
className: css$24.label,
|
|
6296
6788
|
htmlFor: props.id,
|
|
6297
6789
|
children: props.label
|
|
6298
6790
|
}), props.help !== void 0 ? jsx("button", {
|
|
6299
6791
|
type: "button",
|
|
6300
|
-
className: css$
|
|
6792
|
+
className: css$24.helpButton,
|
|
6301
6793
|
"aria-label": props.help.label,
|
|
6302
6794
|
"aria-expanded": helpOpen,
|
|
6303
6795
|
"aria-controls": helpId,
|
|
@@ -6307,13 +6799,13 @@ function SettingsValueField(props) {
|
|
|
6307
6799
|
children: jsx(IconInfoOutlineRegular, { size: 12 })
|
|
6308
6800
|
}) : null]
|
|
6309
6801
|
}), props.overridden ? jsxs("span", {
|
|
6310
|
-
className: css$
|
|
6802
|
+
className: css$24.badges,
|
|
6311
6803
|
children: [jsx(Tag, {
|
|
6312
6804
|
tone: "neutral",
|
|
6313
6805
|
children: props.overriddenLabel
|
|
6314
6806
|
}), jsx("button", {
|
|
6315
6807
|
type: "button",
|
|
6316
|
-
className: css$
|
|
6808
|
+
className: css$24.reset,
|
|
6317
6809
|
disabled: props.disabled,
|
|
6318
6810
|
onClick: props.onReset,
|
|
6319
6811
|
children: props.resetLabel
|
|
@@ -6322,7 +6814,7 @@ function SettingsValueField(props) {
|
|
|
6322
6814
|
}),
|
|
6323
6815
|
jsx("input", {
|
|
6324
6816
|
id: props.id,
|
|
6325
|
-
className: css$
|
|
6817
|
+
className: css$24.input,
|
|
6326
6818
|
type: "text",
|
|
6327
6819
|
...props.numeric === true ? { inputMode: "numeric" } : {},
|
|
6328
6820
|
...props.invalid ? { "aria-invalid": true } : {},
|
|
@@ -6336,12 +6828,12 @@ function SettingsValueField(props) {
|
|
|
6336
6828
|
}),
|
|
6337
6829
|
hasMessage ? jsx("p", {
|
|
6338
6830
|
id: messageId,
|
|
6339
|
-
className: props.invalid ? css$
|
|
6831
|
+
className: props.invalid ? css$24.invalid : css$24.hint,
|
|
6340
6832
|
children: props.invalid ? props.invalidLabel : props.hint
|
|
6341
6833
|
}) : null,
|
|
6342
6834
|
props.help !== void 0 && helpOpen ? jsx("div", {
|
|
6343
6835
|
id: helpId,
|
|
6344
|
-
className: css$
|
|
6836
|
+
className: css$24.help,
|
|
6345
6837
|
role: "region",
|
|
6346
6838
|
"aria-label": props.help.label,
|
|
6347
6839
|
children: props.help.content
|
|
@@ -6353,21 +6845,22 @@ function SettingsValueField(props) {
|
|
|
6353
6845
|
* A write-only credential control. The value never rides a response, so the
|
|
6354
6846
|
* control reports only whether one is configured and starts blank; a blank
|
|
6355
6847
|
* draft writes nothing, which keeps the stored key rather than clearing it.
|
|
6848
|
+
* The control asks browsers not to autofill saved login passwords.
|
|
6356
6849
|
* @param props - the field's copy, its staged text, and the configured state.
|
|
6357
6850
|
* @returns the labelled control.
|
|
6358
6851
|
*/
|
|
6359
6852
|
function SettingsSecretField(props) {
|
|
6360
6853
|
return jsxs("div", {
|
|
6361
|
-
className: css$
|
|
6854
|
+
className: css$24.field,
|
|
6362
6855
|
children: [
|
|
6363
6856
|
jsxs("div", {
|
|
6364
|
-
className: css$
|
|
6857
|
+
className: css$24.head,
|
|
6365
6858
|
children: [jsx("label", {
|
|
6366
|
-
className: css$
|
|
6859
|
+
className: css$24.label,
|
|
6367
6860
|
htmlFor: props.id,
|
|
6368
6861
|
children: props.label
|
|
6369
6862
|
}), jsx("span", {
|
|
6370
|
-
className: css$
|
|
6863
|
+
className: css$24.badges,
|
|
6371
6864
|
children: jsx(Tag, {
|
|
6372
6865
|
tone: props.configured ? "neutral" : "quiet",
|
|
6373
6866
|
children: props.stateLabel
|
|
@@ -6376,9 +6869,9 @@ function SettingsSecretField(props) {
|
|
|
6376
6869
|
}),
|
|
6377
6870
|
jsx("input", {
|
|
6378
6871
|
id: props.id,
|
|
6379
|
-
className: css$
|
|
6872
|
+
className: css$24.input,
|
|
6380
6873
|
type: "password",
|
|
6381
|
-
autoComplete: "
|
|
6874
|
+
autoComplete: "new-password",
|
|
6382
6875
|
value: props.text,
|
|
6383
6876
|
disabled: props.disabled,
|
|
6384
6877
|
onChange: (event) => {
|
|
@@ -6386,7 +6879,7 @@ function SettingsSecretField(props) {
|
|
|
6386
6879
|
}
|
|
6387
6880
|
}),
|
|
6388
6881
|
jsx("p", {
|
|
6389
|
-
className: css$
|
|
6882
|
+
className: css$24.hint,
|
|
6390
6883
|
children: props.hint
|
|
6391
6884
|
})
|
|
6392
6885
|
]
|
|
@@ -6692,16 +7185,16 @@ var SettingsFormModel = class {
|
|
|
6692
7185
|
* dark blocks), never here — the repo's tokens-only styling rule.
|
|
6693
7186
|
*
|
|
6694
7187
|
* Only the three markdown-fence and `run_code` grammars (TypeScript, shell,
|
|
6695
|
-
* JSON) load into the singleton at boot — the set every session renders.
|
|
6696
|
-
*
|
|
6697
|
-
*
|
|
6698
|
-
*
|
|
6699
|
-
*
|
|
6700
|
-
*
|
|
6701
|
-
*
|
|
6702
|
-
*
|
|
6703
|
-
*
|
|
6704
|
-
*
|
|
7188
|
+
* JSON) load into the singleton at boot — the set every session renders. Every
|
|
7189
|
+
* other language in the shared extension table
|
|
7190
|
+
* (`@deepseek-ai/dsh-util-code-language`: python, rust, yaml, markup, …) is
|
|
7191
|
+
* imported lazily and registered the first time such a language is requested,
|
|
7192
|
+
* so a session that never opens a code surface in one of those languages pays
|
|
7193
|
+
* neither the grammar modules nor their synchronous init. The first render of a
|
|
7194
|
+
* lazy language falls back to plain text while its grammar loads, then
|
|
7195
|
+
* {@link onGrammarLoaded} notifies subscribers to re-render with highlighting.
|
|
7196
|
+
* An unknown or absent language falls back to plain text (no highlighting, still
|
|
7197
|
+
* monospace) — never an error.
|
|
6705
7198
|
*/
|
|
6706
7199
|
/**
|
|
6707
7200
|
* Grammars the singleton loads at boot; each entry's own `name` is the id
|
|
@@ -6709,8 +7202,8 @@ var SettingsFormModel = class {
|
|
|
6709
7202
|
* resolve to the TypeScript grammar rather than a separate one: it tokenizes
|
|
6710
7203
|
* plain TS/JS exactly, and JSX/TSX approximately (shiki's TS grammar is not the
|
|
6711
7204
|
* dedicated TSX grammar, so JSX elements tokenize imperfectly) — an accepted
|
|
6712
|
-
* trade to keep the boot set to one JS-family grammar.
|
|
6713
|
-
*
|
|
7205
|
+
* trade to keep the boot set to one JS-family grammar. Every other language in
|
|
7206
|
+
* the shared extension table loads lazily through {@link LAZY_GRAMMARS}.
|
|
6714
7207
|
*/
|
|
6715
7208
|
const LANGS = [
|
|
6716
7209
|
langTs,
|
|
@@ -6718,8 +7211,8 @@ const LANGS = [
|
|
|
6718
7211
|
langJson
|
|
6719
7212
|
];
|
|
6720
7213
|
/**
|
|
6721
|
-
* The
|
|
6722
|
-
*
|
|
7214
|
+
* The non-boot extension grammars, each behind a dynamic import so its module
|
|
7215
|
+
* stays out of the boot chunk until a code surface renders that language.
|
|
6723
7216
|
* Keyed by the grammar id (`LanguageRegistration.name`) the aliases resolve to.
|
|
6724
7217
|
* `@shikijs/langs`' default export is a `LanguageRegistration[]`; the loader
|
|
6725
7218
|
* hands the whole array to `loadLanguageSync`, which registers each entry
|
|
@@ -6749,16 +7242,51 @@ const LAZY_GRAMMARS = new Map([
|
|
|
6749
7242
|
["less", () => import("@shikijs/langs/less")],
|
|
6750
7243
|
["sql", () => import("@shikijs/langs/sql")],
|
|
6751
7244
|
["xml", () => import("@shikijs/langs/xml")],
|
|
6752
|
-
["lua", () => import("@shikijs/langs/lua")]
|
|
7245
|
+
["lua", () => import("@shikijs/langs/lua")],
|
|
7246
|
+
["bat", () => import("@shikijs/langs/bat")],
|
|
7247
|
+
["powershell", () => import("@shikijs/langs/powershell")],
|
|
7248
|
+
["fish", () => import("@shikijs/langs/fish")],
|
|
7249
|
+
["dotenv", () => import("@shikijs/langs/dotenv")],
|
|
7250
|
+
["log", () => import("@shikijs/langs/log")],
|
|
7251
|
+
["csv", () => import("@shikijs/langs/csv")],
|
|
7252
|
+
["diff", () => import("@shikijs/langs/diff")],
|
|
7253
|
+
["http", () => import("@shikijs/langs/http")],
|
|
7254
|
+
["rst", () => import("@shikijs/langs/rst")],
|
|
7255
|
+
["latex", () => import("@shikijs/langs/latex")],
|
|
7256
|
+
["bibtex", () => import("@shikijs/langs/bibtex")],
|
|
7257
|
+
["asciidoc", () => import("@shikijs/langs/asciidoc")],
|
|
7258
|
+
["r", () => import("@shikijs/langs/r")],
|
|
7259
|
+
["julia", () => import("@shikijs/langs/julia")],
|
|
7260
|
+
["dart", () => import("@shikijs/langs/dart")],
|
|
7261
|
+
["scala", () => import("@shikijs/langs/scala")],
|
|
7262
|
+
["clojure", () => import("@shikijs/langs/clojure")],
|
|
7263
|
+
["erlang", () => import("@shikijs/langs/erlang")],
|
|
7264
|
+
["elixir", () => import("@shikijs/langs/elixir")],
|
|
7265
|
+
["haskell", () => import("@shikijs/langs/haskell")],
|
|
7266
|
+
["fsharp", () => import("@shikijs/langs/fsharp")],
|
|
7267
|
+
["vb", () => import("@shikijs/langs/vb")],
|
|
7268
|
+
["perl", () => import("@shikijs/langs/perl")],
|
|
7269
|
+
["verilog", () => import("@shikijs/langs/verilog")],
|
|
7270
|
+
["system-verilog", () => import("@shikijs/langs/system-verilog")],
|
|
7271
|
+
["graphql", () => import("@shikijs/langs/graphql")],
|
|
7272
|
+
["proto", () => import("@shikijs/langs/proto")],
|
|
7273
|
+
["hcl", () => import("@shikijs/langs/hcl")],
|
|
7274
|
+
["nix", () => import("@shikijs/langs/nix")],
|
|
7275
|
+
["vue", () => import("@shikijs/langs/vue")],
|
|
7276
|
+
["svelte", () => import("@shikijs/langs/svelte")],
|
|
7277
|
+
["make", () => import("@shikijs/langs/make")],
|
|
7278
|
+
["cmake", () => import("@shikijs/langs/cmake")],
|
|
7279
|
+
["groovy", () => import("@shikijs/langs/groovy")]
|
|
6753
7280
|
]);
|
|
6754
7281
|
/**
|
|
6755
7282
|
* Language ids (and aliases) the highlighter accepts; everything else renders
|
|
6756
7283
|
* plain. A Map, not an object: fence info strings are assistant-authored, so
|
|
6757
7284
|
* a label like `constructor` or `__proto__` must miss instead of resolving an
|
|
6758
7285
|
* inherited property and crashing the renderer inside shiki. Keys cover both
|
|
6759
|
-
* the markdown-fence aliases `CodeBlock` uses
|
|
6760
|
-
*
|
|
6761
|
-
*
|
|
7286
|
+
* the markdown-fence aliases `CodeBlock` uses, the file-extension language ids
|
|
7287
|
+
* `@deepseek-ai/dsh-util-code-language` resolves, and the short ids
|
|
7288
|
+
* `readLangHintForPath` persists, so every caller resolves the same grammars.
|
|
7289
|
+
* A new short name in the shared table must be aliased here too. The JS family maps to the TypeScript grammar (see {@link LANGS} for
|
|
6762
7290
|
* the JSX/TSX approximation). A value not in {@link LANGS} names a
|
|
6763
7291
|
* {@link LAZY_GRAMMARS} entry loaded on first use.
|
|
6764
7292
|
*/
|
|
@@ -6804,15 +7332,89 @@ const LANG_ALIASES = new Map([
|
|
|
6804
7332
|
["less", "less"],
|
|
6805
7333
|
["sql", "sql"],
|
|
6806
7334
|
["xml", "xml"],
|
|
6807
|
-
["lua", "lua"]
|
|
7335
|
+
["lua", "lua"],
|
|
7336
|
+
["bat", "bat"],
|
|
7337
|
+
["batch", "bat"],
|
|
7338
|
+
["powershell", "powershell"],
|
|
7339
|
+
["ps1", "powershell"],
|
|
7340
|
+
["ps", "powershell"],
|
|
7341
|
+
["fish", "fish"],
|
|
7342
|
+
["properties", "ini"],
|
|
7343
|
+
["dotenv", "dotenv"],
|
|
7344
|
+
["env", "dotenv"],
|
|
7345
|
+
["log", "log"],
|
|
7346
|
+
["csv", "csv"],
|
|
7347
|
+
["diff", "diff"],
|
|
7348
|
+
["patch", "diff"],
|
|
7349
|
+
["http", "http"],
|
|
7350
|
+
["rst", "rst"],
|
|
7351
|
+
["latex", "latex"],
|
|
7352
|
+
["tex", "latex"],
|
|
7353
|
+
["bibtex", "bibtex"],
|
|
7354
|
+
["bib", "bibtex"],
|
|
7355
|
+
["asciidoc", "asciidoc"],
|
|
7356
|
+
["adoc", "asciidoc"],
|
|
7357
|
+
["r", "r"],
|
|
7358
|
+
["julia", "julia"],
|
|
7359
|
+
["jl", "julia"],
|
|
7360
|
+
["dart", "dart"],
|
|
7361
|
+
["scala", "scala"],
|
|
7362
|
+
["clojure", "clojure"],
|
|
7363
|
+
["clj", "clojure"],
|
|
7364
|
+
["erlang", "erlang"],
|
|
7365
|
+
["erl", "erlang"],
|
|
7366
|
+
["elixir", "elixir"],
|
|
7367
|
+
["ex", "elixir"],
|
|
7368
|
+
["exs", "elixir"],
|
|
7369
|
+
["haskell", "haskell"],
|
|
7370
|
+
["hs", "haskell"],
|
|
7371
|
+
["fsharp", "fsharp"],
|
|
7372
|
+
["fs", "fsharp"],
|
|
7373
|
+
["fsi", "fsharp"],
|
|
7374
|
+
["fsx", "fsharp"],
|
|
7375
|
+
["vb", "vb"],
|
|
7376
|
+
["vbnet", "vb"],
|
|
7377
|
+
["perl", "perl"],
|
|
7378
|
+
["pl", "perl"],
|
|
7379
|
+
["pm", "perl"],
|
|
7380
|
+
["verilog", "verilog"],
|
|
7381
|
+
["v", "verilog"],
|
|
7382
|
+
["system-verilog", "system-verilog"],
|
|
7383
|
+
["systemverilog", "system-verilog"],
|
|
7384
|
+
["sv", "system-verilog"],
|
|
7385
|
+
["svh", "system-verilog"],
|
|
7386
|
+
["graphql", "graphql"],
|
|
7387
|
+
["gql", "graphql"],
|
|
7388
|
+
["proto", "proto"],
|
|
7389
|
+
["protobuf", "proto"],
|
|
7390
|
+
["hcl", "hcl"],
|
|
7391
|
+
["tf", "hcl"],
|
|
7392
|
+
["tfvars", "hcl"],
|
|
7393
|
+
["nix", "nix"],
|
|
7394
|
+
["vue", "vue"],
|
|
7395
|
+
["svelte", "svelte"],
|
|
7396
|
+
["make", "make"],
|
|
7397
|
+
["makefile", "make"],
|
|
7398
|
+
["mk", "make"],
|
|
7399
|
+
["cmake", "cmake"],
|
|
7400
|
+
["groovy", "groovy"],
|
|
7401
|
+
["gradle", "groovy"]
|
|
6808
7402
|
]);
|
|
6809
7403
|
/**
|
|
7404
|
+
* Resolve a language hint to the grammar id {@link LANG_ALIASES} selects.
|
|
7405
|
+
* @param lang - Language hint from a code surface: a canonical grammar id or the read card's persisted short id.
|
|
7406
|
+
* @returns The resolved grammar id, or `undefined` when the table aliases no grammar.
|
|
7407
|
+
*/
|
|
7408
|
+
function grammarForHint(lang) {
|
|
7409
|
+
return lang === void 0 ? void 0 : LANG_ALIASES.get(lang.toLowerCase());
|
|
7410
|
+
}
|
|
7411
|
+
/**
|
|
6810
7412
|
* Whether a language hint can use the shared syntax highlighter.
|
|
6811
7413
|
* @param lang - Language hint from a code surface.
|
|
6812
7414
|
* @returns Whether the hint resolves to a supported grammar.
|
|
6813
7415
|
*/
|
|
6814
7416
|
function supportsHighlighting(lang) {
|
|
6815
|
-
return lang !== void 0
|
|
7417
|
+
return grammarForHint(lang) !== void 0;
|
|
6816
7418
|
}
|
|
6817
7419
|
/** All token colors resolve through `--shiki-*` custom properties (theme package sheets). */
|
|
6818
7420
|
const cssVariablesTheme = createCssVariablesTheme({
|
|
@@ -6933,7 +7535,7 @@ setTimeout(() => {
|
|
|
6933
7535
|
* @returns the highlighted HTML, or `undefined` for unknown or not-yet-loaded languages.
|
|
6934
7536
|
*/
|
|
6935
7537
|
function highlightToHtml(code, lang) {
|
|
6936
|
-
const resolved =
|
|
7538
|
+
const resolved = grammarForHint(lang);
|
|
6937
7539
|
if (resolved === void 0) return void 0;
|
|
6938
7540
|
if (!ensureGrammar(resolved)) return void 0;
|
|
6939
7541
|
return highlighter().codeToHtml(code, {
|
|
@@ -7045,7 +7647,7 @@ var StreamingHighlightSession = class {
|
|
|
7045
7647
|
this.lastCode = code;
|
|
7046
7648
|
this.lastLang = lang;
|
|
7047
7649
|
this.lastResult = void 0;
|
|
7048
|
-
const resolved =
|
|
7650
|
+
const resolved = grammarForHint(lang);
|
|
7049
7651
|
if (resolved === void 0 || !ensureGrammar(resolved)) {
|
|
7050
7652
|
this.reset(void 0);
|
|
7051
7653
|
return;
|
|
@@ -7105,7 +7707,7 @@ var StreamingHighlightSession = class {
|
|
|
7105
7707
|
* @returns one entry per source line (each an array of runs), or `undefined` for unknown or not-yet-loaded languages.
|
|
7106
7708
|
*/
|
|
7107
7709
|
function highlightLines(code, lang) {
|
|
7108
|
-
const resolved =
|
|
7710
|
+
const resolved = grammarForHint(lang);
|
|
7109
7711
|
if (resolved === void 0) return void 0;
|
|
7110
7712
|
if (!ensureGrammar(resolved)) return void 0;
|
|
7111
7713
|
const { tokens } = highlighter().codeToTokens(code, {
|
|
@@ -7121,89 +7723,6 @@ function highlightLines(code, lang) {
|
|
|
7121
7723
|
//#endregion
|
|
7122
7724
|
//#region lib/types/code-highlighting.js
|
|
7123
7725
|
/** Shared filename-to-grammar selection and lazy line highlighter for source views. */
|
|
7124
|
-
const LANGUAGES = new Map(Object.entries({
|
|
7125
|
-
typescript: [
|
|
7126
|
-
"ts",
|
|
7127
|
-
"tsx",
|
|
7128
|
-
"mts",
|
|
7129
|
-
"cts"
|
|
7130
|
-
],
|
|
7131
|
-
javascript: [
|
|
7132
|
-
"js",
|
|
7133
|
-
"jsx",
|
|
7134
|
-
"mjs",
|
|
7135
|
-
"cjs"
|
|
7136
|
-
],
|
|
7137
|
-
shellscript: [
|
|
7138
|
-
"sh",
|
|
7139
|
-
"bash",
|
|
7140
|
-
"zsh"
|
|
7141
|
-
],
|
|
7142
|
-
json: [
|
|
7143
|
-
"json",
|
|
7144
|
-
"jsonc",
|
|
7145
|
-
"jsonl",
|
|
7146
|
-
"ndjson"
|
|
7147
|
-
],
|
|
7148
|
-
python: [
|
|
7149
|
-
"py",
|
|
7150
|
-
"pyw",
|
|
7151
|
-
"pyi"
|
|
7152
|
-
],
|
|
7153
|
-
ruby: [
|
|
7154
|
-
"rb",
|
|
7155
|
-
"rake",
|
|
7156
|
-
"gemspec"
|
|
7157
|
-
],
|
|
7158
|
-
go: ["go"],
|
|
7159
|
-
rust: ["rs"],
|
|
7160
|
-
java: ["java"],
|
|
7161
|
-
c: ["c", "h"],
|
|
7162
|
-
cpp: [
|
|
7163
|
-
"cc",
|
|
7164
|
-
"cpp",
|
|
7165
|
-
"cxx",
|
|
7166
|
-
"hh",
|
|
7167
|
-
"hpp",
|
|
7168
|
-
"hxx"
|
|
7169
|
-
],
|
|
7170
|
-
csharp: ["cs"],
|
|
7171
|
-
kotlin: ["kt", "kts"],
|
|
7172
|
-
swift: ["swift"],
|
|
7173
|
-
php: ["php"],
|
|
7174
|
-
yaml: ["yaml", "yml"],
|
|
7175
|
-
toml: ["toml"],
|
|
7176
|
-
ini: ["ini"],
|
|
7177
|
-
markdown: ["md", "markdown"],
|
|
7178
|
-
mdx: ["mdx"],
|
|
7179
|
-
html: [
|
|
7180
|
-
"html",
|
|
7181
|
-
"htm",
|
|
7182
|
-
"xhtml"
|
|
7183
|
-
],
|
|
7184
|
-
css: ["css"],
|
|
7185
|
-
scss: ["scss"],
|
|
7186
|
-
less: ["less"],
|
|
7187
|
-
sql: ["sql"],
|
|
7188
|
-
xml: [
|
|
7189
|
-
"xml",
|
|
7190
|
-
"xsd",
|
|
7191
|
-
"xsl",
|
|
7192
|
-
"xslt"
|
|
7193
|
-
],
|
|
7194
|
-
lua: ["lua"]
|
|
7195
|
-
}).flatMap(([language, extensions]) => extensions.map((extension) => [extension, language])));
|
|
7196
|
-
/** Recognized filename suffixes whose source can use the shared syntax highlighter. */
|
|
7197
|
-
const CODE_HIGHLIGHT_EXTENSIONS = [...LANGUAGES.keys()];
|
|
7198
|
-
/**
|
|
7199
|
-
* Select the shared syntax highlighter's grammar from a filename.
|
|
7200
|
-
* @param path - decoded source filename or path.
|
|
7201
|
-
* @returns a supported grammar hint, or `undefined` for other suffixes.
|
|
7202
|
-
*/
|
|
7203
|
-
function languageForPath(path) {
|
|
7204
|
-
const extension = /\.([^./]+)$/u.exec(path.replaceAll("\\", "/"))?.[1]?.toLowerCase();
|
|
7205
|
-
return extension === void 0 ? void 0 : LANGUAGES.get(extension);
|
|
7206
|
-
}
|
|
7207
7726
|
/**
|
|
7208
7727
|
* Bind the shared lazy highlighter to one language and refresh after its grammar loads.
|
|
7209
7728
|
* @param language - grammar hint selected from the source filename.
|
|
@@ -7426,7 +7945,7 @@ function JsonCopyAction({ store, target, persistent, labels, onCopy, onClose })
|
|
|
7426
7945
|
const object = typeof target.value === "object" && target.value !== null;
|
|
7427
7946
|
const copyTitle = state === "copied" ? labels.copied : state === "failed" ? labels.copyFailed : object ? labels.copyPrettyJson : labels.copyValue;
|
|
7428
7947
|
return jsx("span", {
|
|
7429
|
-
className: css$
|
|
7948
|
+
className: css$25.copySlot,
|
|
7430
7949
|
children: (persistent || snapshot !== void 0) && jsx(Menu, {
|
|
7431
7950
|
open: snapshot?.menuOpen === true,
|
|
7432
7951
|
compact: true,
|
|
@@ -7435,7 +7954,7 @@ function JsonCopyAction({ store, target, persistent, labels, onCopy, onClose })
|
|
|
7435
7954
|
anchor: jsx("button", {
|
|
7436
7955
|
ref: buttonRef,
|
|
7437
7956
|
type: "button",
|
|
7438
|
-
className: css$
|
|
7957
|
+
className: css$25.actionButton,
|
|
7439
7958
|
"data-json-copy-button": true,
|
|
7440
7959
|
"data-state": state,
|
|
7441
7960
|
"aria-label": copyTitle,
|
|
@@ -7474,35 +7993,35 @@ function bracketOf(value) {
|
|
|
7474
7993
|
}
|
|
7475
7994
|
function previewPrimitive(value) {
|
|
7476
7995
|
if (value === null) return jsx("span", {
|
|
7477
|
-
className: css$
|
|
7996
|
+
className: css$25.keywordValue,
|
|
7478
7997
|
children: "null"
|
|
7479
7998
|
});
|
|
7480
7999
|
if (typeof value === "string") return jsx("span", {
|
|
7481
|
-
className: css$
|
|
8000
|
+
className: css$25.stringValue,
|
|
7482
8001
|
children: JSON.stringify(value)
|
|
7483
8002
|
});
|
|
7484
8003
|
if (typeof value === "number") return jsx("span", {
|
|
7485
|
-
className: css$
|
|
8004
|
+
className: css$25.numberValue,
|
|
7486
8005
|
children: String(value)
|
|
7487
8006
|
});
|
|
7488
8007
|
if (typeof value === "boolean") return jsx("span", {
|
|
7489
|
-
className: css$
|
|
8008
|
+
className: css$25.keywordValue,
|
|
7490
8009
|
children: String(value)
|
|
7491
8010
|
});
|
|
7492
8011
|
if (typeof value === "bigint") return jsx("span", {
|
|
7493
|
-
className: css$
|
|
8012
|
+
className: css$25.otherValue,
|
|
7494
8013
|
children: value.toString()
|
|
7495
8014
|
});
|
|
7496
8015
|
if (typeof value === "undefined") return jsx("span", {
|
|
7497
|
-
className: css$
|
|
8016
|
+
className: css$25.otherValue,
|
|
7498
8017
|
children: "undefined"
|
|
7499
8018
|
});
|
|
7500
8019
|
if (typeof value === "symbol") return jsx("span", {
|
|
7501
|
-
className: css$
|
|
8020
|
+
className: css$25.otherValue,
|
|
7502
8021
|
children: value.description ?? "Symbol"
|
|
7503
8022
|
});
|
|
7504
8023
|
if (typeof value === "function") return jsx("span", {
|
|
7505
|
-
className: css$
|
|
8024
|
+
className: css$25.otherValue,
|
|
7506
8025
|
children: value.name || "Function"
|
|
7507
8026
|
});
|
|
7508
8027
|
return null;
|
|
@@ -7516,71 +8035,71 @@ function previewValue(value, depth) {
|
|
|
7516
8035
|
const [open, close] = bracketOf(value);
|
|
7517
8036
|
return jsxs(Fragment, { children: [
|
|
7518
8037
|
jsx("span", {
|
|
7519
|
-
className: css$
|
|
8038
|
+
className: css$25.punctuation,
|
|
7520
8039
|
children: open
|
|
7521
8040
|
}),
|
|
7522
8041
|
depth >= PREVIEW_DEPTH_LIMIT ? jsx("span", {
|
|
7523
|
-
className: css$
|
|
8042
|
+
className: css$25.previewEllipsis,
|
|
7524
8043
|
children: "…"
|
|
7525
8044
|
}) : visible.map(([key, item], index) => jsxs("span", { children: [
|
|
7526
8045
|
index > 0 && jsx("span", {
|
|
7527
|
-
className: css$
|
|
8046
|
+
className: css$25.punctuation,
|
|
7528
8047
|
children: ", "
|
|
7529
8048
|
}),
|
|
7530
8049
|
!array && jsxs(Fragment, { children: [jsx("span", {
|
|
7531
|
-
className: css$
|
|
8050
|
+
className: css$25.previewProperty,
|
|
7532
8051
|
children: key
|
|
7533
8052
|
}), jsx("span", {
|
|
7534
|
-
className: css$
|
|
8053
|
+
className: css$25.punctuation,
|
|
7535
8054
|
children: ": "
|
|
7536
8055
|
})] }),
|
|
7537
8056
|
previewValue(item, depth + 1)
|
|
7538
8057
|
] }, key)),
|
|
7539
8058
|
depth < PREVIEW_DEPTH_LIMIT && entries.length > limit && jsx("span", {
|
|
7540
|
-
className: css$
|
|
8059
|
+
className: css$25.previewEllipsis,
|
|
7541
8060
|
children: ", …"
|
|
7542
8061
|
}),
|
|
7543
8062
|
jsx("span", {
|
|
7544
|
-
className: css$
|
|
8063
|
+
className: css$25.punctuation,
|
|
7545
8064
|
children: close
|
|
7546
8065
|
})
|
|
7547
8066
|
] });
|
|
7548
8067
|
}
|
|
7549
8068
|
function primitiveValue(value) {
|
|
7550
8069
|
if (value === null) return jsx("span", {
|
|
7551
|
-
className: css$
|
|
8070
|
+
className: css$25.keywordValue,
|
|
7552
8071
|
children: "null"
|
|
7553
8072
|
});
|
|
7554
8073
|
if (typeof value === "string") return jsx("span", {
|
|
7555
|
-
className: css$
|
|
8074
|
+
className: css$25.stringValue,
|
|
7556
8075
|
children: JSON.stringify(value)
|
|
7557
8076
|
});
|
|
7558
8077
|
if (typeof value === "boolean") return jsx("span", {
|
|
7559
|
-
className: css$
|
|
8078
|
+
className: css$25.keywordValue,
|
|
7560
8079
|
children: String(value)
|
|
7561
8080
|
});
|
|
7562
8081
|
if (typeof value === "number") return jsx("span", {
|
|
7563
|
-
className: css$
|
|
8082
|
+
className: css$25.numberValue,
|
|
7564
8083
|
children: String(value)
|
|
7565
8084
|
});
|
|
7566
8085
|
if (typeof value === "bigint") return jsx("span", {
|
|
7567
|
-
className: css$
|
|
8086
|
+
className: css$25.numberValue,
|
|
7568
8087
|
children: `${value.toString()}n`
|
|
7569
8088
|
});
|
|
7570
8089
|
if (value instanceof Date) return jsx("span", {
|
|
7571
|
-
className: css$
|
|
8090
|
+
className: css$25.otherValue,
|
|
7572
8091
|
children: value.toISOString()
|
|
7573
8092
|
});
|
|
7574
8093
|
if (typeof value === "function") return jsxs("span", {
|
|
7575
|
-
className: css$
|
|
8094
|
+
className: css$25.otherValue,
|
|
7576
8095
|
children: ["function() ", "{ }"]
|
|
7577
8096
|
});
|
|
7578
8097
|
if (typeof value === "undefined") return jsx("span", {
|
|
7579
|
-
className: css$
|
|
8098
|
+
className: css$25.otherValue,
|
|
7580
8099
|
children: "undefined"
|
|
7581
8100
|
});
|
|
7582
8101
|
return jsx("span", {
|
|
7583
|
-
className: css$
|
|
8102
|
+
className: css$25.otherValue,
|
|
7584
8103
|
children: value.toString()
|
|
7585
8104
|
});
|
|
7586
8105
|
}
|
|
@@ -7608,7 +8127,7 @@ function moveFocus(button, direction) {
|
|
|
7608
8127
|
function NodeField({ field, expandable, onToggle }) {
|
|
7609
8128
|
if (field === void 0) return null;
|
|
7610
8129
|
return jsxs("span", {
|
|
7611
|
-
className: clsx(css$
|
|
8130
|
+
className: clsx(css$25.label, expandable && css$25.clickableLabel),
|
|
7612
8131
|
onClick: expandable ? onToggle : void 0,
|
|
7613
8132
|
children: [fieldText(field), ":"]
|
|
7614
8133
|
});
|
|
@@ -7645,7 +8164,7 @@ function JsonString({ collapsedStringLines, stringWrapping, field, labels, lastE
|
|
|
7645
8164
|
if (!expanded) return;
|
|
7646
8165
|
const raw = rawRef.current;
|
|
7647
8166
|
const clips = [];
|
|
7648
|
-
const tree = raw.closest(`.${css$
|
|
8167
|
+
const tree = raw.closest(`.${css$25.root}`);
|
|
7649
8168
|
for (let parent = tree.parentElement; parent !== null; parent = parent.parentElement) if (/auto|scroll|hidden|clip/.test(getComputedStyle(parent).overflowY)) clips.push(parent);
|
|
7650
8169
|
const measure = () => {
|
|
7651
8170
|
let top = 0;
|
|
@@ -7674,33 +8193,33 @@ function JsonString({ collapsedStringLines, stringWrapping, field, labels, lastE
|
|
|
7674
8193
|
if (expanded) {
|
|
7675
8194
|
const fieldId = `${contentsId}-field`;
|
|
7676
8195
|
return jsxs("div", {
|
|
7677
|
-
className: css$
|
|
8196
|
+
className: css$25.stringField,
|
|
7678
8197
|
"data-expanded": true,
|
|
7679
8198
|
children: [
|
|
7680
8199
|
field !== void 0 && jsxs("span", {
|
|
7681
8200
|
id: fieldId,
|
|
7682
|
-
className: css$
|
|
8201
|
+
className: css$25.label,
|
|
7683
8202
|
children: [fieldText(field), ":"]
|
|
7684
8203
|
}),
|
|
7685
8204
|
jsx("pre", {
|
|
7686
8205
|
ref: rawRef,
|
|
7687
8206
|
id: contentsId,
|
|
7688
|
-
className: css$
|
|
8207
|
+
className: css$25.stringRaw,
|
|
7689
8208
|
"data-wrap": wrapped,
|
|
7690
8209
|
tabIndex: 0,
|
|
7691
8210
|
"aria-labelledby": field === void 0 ? void 0 : fieldId,
|
|
7692
8211
|
children: value
|
|
7693
8212
|
}),
|
|
7694
8213
|
!lastElement && jsx("span", {
|
|
7695
|
-
className: css$
|
|
8214
|
+
className: css$25.punctuation,
|
|
7696
8215
|
children: ","
|
|
7697
8216
|
}),
|
|
7698
8217
|
jsxs("div", {
|
|
7699
|
-
className: css$
|
|
8218
|
+
className: css$25.stringActions,
|
|
7700
8219
|
children: [
|
|
7701
8220
|
stringWrapping !== void 0 && jsx("button", {
|
|
7702
8221
|
type: "button",
|
|
7703
|
-
className: css$
|
|
8222
|
+
className: css$25.actionButton,
|
|
7704
8223
|
"aria-label": stringWrapping.label,
|
|
7705
8224
|
title: stringWrapping.label,
|
|
7706
8225
|
"aria-pressed": wrapped,
|
|
@@ -7714,7 +8233,7 @@ function JsonString({ collapsedStringLines, stringWrapping, field, labels, lastE
|
|
|
7714
8233
|
}),
|
|
7715
8234
|
jsx("button", {
|
|
7716
8235
|
type: "button",
|
|
7717
|
-
className: css$
|
|
8236
|
+
className: css$25.actionButton,
|
|
7718
8237
|
"aria-label": labels.collapseNode,
|
|
7719
8238
|
title: labels.collapseNode,
|
|
7720
8239
|
"aria-expanded": true,
|
|
@@ -7739,18 +8258,18 @@ function JsonString({ collapsedStringLines, stringWrapping, field, labels, lastE
|
|
|
7739
8258
|
});
|
|
7740
8259
|
}
|
|
7741
8260
|
return jsxs(Fragment, { children: [renderCopy?.(), jsx("span", {
|
|
7742
|
-
className: css$
|
|
8261
|
+
className: css$25.stringField,
|
|
7743
8262
|
"data-expanded": expanded,
|
|
7744
8263
|
children: jsxs("span", {
|
|
7745
8264
|
ref: contentRef,
|
|
7746
8265
|
id: contentsId,
|
|
7747
|
-
className: css$
|
|
8266
|
+
className: css$25.stringText,
|
|
7748
8267
|
children: [
|
|
7749
8268
|
truncated && jsx("span", {
|
|
7750
|
-
className: css$
|
|
8269
|
+
className: css$25.stringToggleSlot,
|
|
7751
8270
|
children: jsxs("button", {
|
|
7752
8271
|
type: "button",
|
|
7753
|
-
className: css$
|
|
8272
|
+
className: css$25.stringToggle,
|
|
7754
8273
|
"aria-label": labels.expandNode,
|
|
7755
8274
|
"aria-expanded": false,
|
|
7756
8275
|
"aria-controls": contentsId,
|
|
@@ -7765,12 +8284,12 @@ function JsonString({ collapsedStringLines, stringWrapping, field, labels, lastE
|
|
|
7765
8284
|
})
|
|
7766
8285
|
}),
|
|
7767
8286
|
field !== void 0 && jsxs("span", {
|
|
7768
|
-
className: css$
|
|
8287
|
+
className: css$25.label,
|
|
7769
8288
|
children: [fieldText(field), ":"]
|
|
7770
8289
|
}),
|
|
7771
8290
|
primitiveValue(value),
|
|
7772
8291
|
!lastElement && jsx("span", {
|
|
7773
|
-
className: css$
|
|
8292
|
+
className: css$25.punctuation,
|
|
7774
8293
|
children: ","
|
|
7775
8294
|
})
|
|
7776
8295
|
]
|
|
@@ -7801,7 +8320,7 @@ function JsonTreeNode({ collapsedStringLines, stringWrapping, field, initialExpa
|
|
|
7801
8320
|
}
|
|
7802
8321
|
};
|
|
7803
8322
|
const row = (children, ariaExpanded) => jsxs("div", {
|
|
7804
|
-
className: css$
|
|
8323
|
+
className: css$25.row,
|
|
7805
8324
|
role: "treeitem",
|
|
7806
8325
|
"aria-expanded": ariaExpanded,
|
|
7807
8326
|
onMouseOver: (event) => {
|
|
@@ -7836,7 +8355,7 @@ function JsonTreeNode({ collapsedStringLines, stringWrapping, field, initialExpa
|
|
|
7836
8355
|
}),
|
|
7837
8356
|
primitiveValue(value),
|
|
7838
8357
|
!lastElement && jsx("span", {
|
|
7839
|
-
className: css$
|
|
8358
|
+
className: css$25.punctuation,
|
|
7840
8359
|
children: ","
|
|
7841
8360
|
})
|
|
7842
8361
|
] }));
|
|
@@ -7848,22 +8367,22 @@ function JsonTreeNode({ collapsedStringLines, stringWrapping, field, initialExpa
|
|
|
7848
8367
|
onToggle: toggle
|
|
7849
8368
|
}),
|
|
7850
8369
|
jsx("span", {
|
|
7851
|
-
className: css$
|
|
8370
|
+
className: css$25.punctuation,
|
|
7852
8371
|
children: open
|
|
7853
8372
|
}),
|
|
7854
8373
|
jsx("span", {
|
|
7855
|
-
className: css$
|
|
8374
|
+
className: css$25.punctuation,
|
|
7856
8375
|
children: close
|
|
7857
8376
|
}),
|
|
7858
8377
|
!lastElement && jsx("span", {
|
|
7859
|
-
className: css$
|
|
8378
|
+
className: css$25.punctuation,
|
|
7860
8379
|
children: ","
|
|
7861
8380
|
})
|
|
7862
8381
|
] }));
|
|
7863
8382
|
return row(jsxs(Fragment, { children: [
|
|
7864
8383
|
jsx("span", {
|
|
7865
8384
|
ref: expanderRef,
|
|
7866
|
-
className: clsx(css$
|
|
8385
|
+
className: clsx(css$25.expander, expanded ? css$25.collapseIcon : css$25.expandIcon),
|
|
7867
8386
|
"data-json-expander": true,
|
|
7868
8387
|
role: "button",
|
|
7869
8388
|
"aria-label": expanded ? labels.collapseNode : labels.expandNode,
|
|
@@ -7877,7 +8396,7 @@ function JsonTreeNode({ collapsedStringLines, stringWrapping, field, initialExpa
|
|
|
7877
8396
|
onKeyDown: onExpanderKeyDown
|
|
7878
8397
|
}),
|
|
7879
8398
|
jsxs("span", {
|
|
7880
|
-
className: css$
|
|
8399
|
+
className: css$25.summary,
|
|
7881
8400
|
children: [
|
|
7882
8401
|
jsx(NodeField, {
|
|
7883
8402
|
field,
|
|
@@ -7885,11 +8404,11 @@ function JsonTreeNode({ collapsedStringLines, stringWrapping, field, initialExpa
|
|
|
7885
8404
|
onToggle: toggle
|
|
7886
8405
|
}),
|
|
7887
8406
|
jsx("span", {
|
|
7888
|
-
className: css$
|
|
8407
|
+
className: css$25.preview,
|
|
7889
8408
|
children: previewValue(value, 0)
|
|
7890
8409
|
}),
|
|
7891
8410
|
!lastElement && jsx("span", {
|
|
7892
|
-
className: css$
|
|
8411
|
+
className: css$25.punctuation,
|
|
7893
8412
|
children: ","
|
|
7894
8413
|
})
|
|
7895
8414
|
]
|
|
@@ -7897,7 +8416,7 @@ function JsonTreeNode({ collapsedStringLines, stringWrapping, field, initialExpa
|
|
|
7897
8416
|
expanded && jsx("ul", {
|
|
7898
8417
|
id: contentsId,
|
|
7899
8418
|
role: "group",
|
|
7900
|
-
className: css$
|
|
8419
|
+
className: css$25.children,
|
|
7901
8420
|
children: entries.map(([key, item], index) => jsx(JsonTreeNode, {
|
|
7902
8421
|
collapsedStringLines,
|
|
7903
8422
|
stringWrapping,
|
|
@@ -8029,17 +8548,17 @@ function JsonTree({ data, label, className, collapsedStringLines = 3, stringWrap
|
|
|
8029
8548
|
onClose: clearCopyTarget
|
|
8030
8549
|
}) : void 0;
|
|
8031
8550
|
return jsx("div", {
|
|
8032
|
-
className: clsx(css$
|
|
8551
|
+
className: clsx(css$25.root, className),
|
|
8033
8552
|
style: { "--json-tree-collapsed-lines": collapsedStringLines },
|
|
8034
8553
|
onMouseOver: handleRootMouseOver,
|
|
8035
8554
|
onMouseLeave: () => {
|
|
8036
8555
|
if (!copyStore.get()?.menuOpen) clearCopyTarget();
|
|
8037
8556
|
},
|
|
8038
8557
|
children: expandTopLevel ? jsxs("div", {
|
|
8039
|
-
className: css$
|
|
8558
|
+
className: css$25.expandedTopLevel,
|
|
8040
8559
|
children: [
|
|
8041
8560
|
jsxs("div", {
|
|
8042
|
-
className: clsx(css$
|
|
8561
|
+
className: clsx(css$25.row, css$25.topLevelBracket),
|
|
8043
8562
|
"data-json-root-row": true,
|
|
8044
8563
|
onMouseOver: (event) => {
|
|
8045
8564
|
event.stopPropagation();
|
|
@@ -8052,13 +8571,13 @@ function JsonTree({ data, label, className, collapsedStringLines = 3, stringWrap
|
|
|
8052
8571
|
path: [],
|
|
8053
8572
|
value: data
|
|
8054
8573
|
}), jsx("span", {
|
|
8055
|
-
className: css$
|
|
8574
|
+
className: css$25.punctuation,
|
|
8056
8575
|
children: rootOpen
|
|
8057
8576
|
})]
|
|
8058
8577
|
}),
|
|
8059
8578
|
jsx("div", {
|
|
8060
8579
|
"aria-label": label,
|
|
8061
|
-
className: clsx(css$
|
|
8580
|
+
className: clsx(css$25.container, css$25.expandedTopLevelContainer),
|
|
8062
8581
|
role: "tree",
|
|
8063
8582
|
children: rootEntries.map(([key, value], index) => jsx(JsonTreeNode, {
|
|
8064
8583
|
collapsedStringLines,
|
|
@@ -8076,16 +8595,16 @@ function JsonTree({ data, label, className, collapsedStringLines = 3, stringWrap
|
|
|
8076
8595
|
}, key))
|
|
8077
8596
|
}),
|
|
8078
8597
|
jsx("div", {
|
|
8079
|
-
className: clsx(css$
|
|
8598
|
+
className: clsx(css$25.row, css$25.topLevelBracket),
|
|
8080
8599
|
children: jsx("span", {
|
|
8081
|
-
className: css$
|
|
8600
|
+
className: css$25.punctuation,
|
|
8082
8601
|
children: rootClose
|
|
8083
8602
|
})
|
|
8084
8603
|
})
|
|
8085
8604
|
]
|
|
8086
8605
|
}) : jsx("div", {
|
|
8087
8606
|
"aria-label": label,
|
|
8088
|
-
className: css$
|
|
8607
|
+
className: css$25.container,
|
|
8089
8608
|
role: "tree",
|
|
8090
8609
|
children: jsx(JsonTreeNode, {
|
|
8091
8610
|
collapsedStringLines,
|
|
@@ -8648,67 +9167,67 @@ function TerminalBlock({ command, cwd, home, output, exitCode, signal, running =
|
|
|
8648
9167
|
const { hidden, capped, headLines, tailLines } = headTailCap(lines.length, maxLines, expanded);
|
|
8649
9168
|
const body = !running || !empty;
|
|
8650
9169
|
return jsxs("div", {
|
|
8651
|
-
className: clsx(css$
|
|
9170
|
+
className: clsx(css$26.block, className),
|
|
8652
9171
|
"data-terminal": "",
|
|
8653
9172
|
"data-running": running ? "" : void 0,
|
|
8654
9173
|
"data-body": body ? "" : void 0,
|
|
8655
9174
|
children: [jsxs("div", {
|
|
8656
|
-
className: css$
|
|
9175
|
+
className: css$26.header,
|
|
8657
9176
|
children: [
|
|
8658
9177
|
jsxs("div", {
|
|
8659
|
-
className: css$
|
|
9178
|
+
className: css$26.prompt,
|
|
8660
9179
|
children: [runStateDot && jsx("span", {
|
|
8661
|
-
className: css$
|
|
9180
|
+
className: css$26.runStateLabel,
|
|
8662
9181
|
children: state.label
|
|
8663
9182
|
}), commandLines.map((line, index) => jsxs("div", {
|
|
8664
|
-
className: css$
|
|
9183
|
+
className: css$26.promptLine,
|
|
8665
9184
|
children: [
|
|
8666
9185
|
index === 0 && runStateDot && jsx(StateDot, {
|
|
8667
9186
|
state: state.state,
|
|
8668
|
-
className: css$
|
|
9187
|
+
className: css$26.runState
|
|
8669
9188
|
}),
|
|
8670
9189
|
jsx("span", {
|
|
8671
|
-
className: css$
|
|
9190
|
+
className: css$26.cwd,
|
|
8672
9191
|
children: index > 0 || cwd === void 0 ? "$" : promptLabel(cwd, home)
|
|
8673
9192
|
}),
|
|
8674
9193
|
jsx("span", {
|
|
8675
|
-
className: css$
|
|
9194
|
+
className: css$26.command,
|
|
8676
9195
|
children: line
|
|
8677
9196
|
})
|
|
8678
9197
|
]
|
|
8679
9198
|
}, index))]
|
|
8680
9199
|
}),
|
|
8681
9200
|
status !== void 0 && jsx(Pill, {
|
|
8682
|
-
className: css$
|
|
9201
|
+
className: css$26.status,
|
|
8683
9202
|
children: status
|
|
8684
9203
|
}),
|
|
8685
9204
|
(copyText !== void 0 || !running && !empty) && jsx("button", {
|
|
8686
9205
|
type: "button",
|
|
8687
|
-
className: css$
|
|
9206
|
+
className: css$26.copyButton,
|
|
8688
9207
|
onClick: onCopy,
|
|
8689
9208
|
children: copied ? copy.copied : copy.copy
|
|
8690
9209
|
})
|
|
8691
9210
|
]
|
|
8692
9211
|
}), body && (empty ? jsx("div", {
|
|
8693
|
-
className: css$
|
|
9212
|
+
className: css$26.empty,
|
|
8694
9213
|
children: copy.noOutput
|
|
8695
9214
|
}) : jsxs("div", {
|
|
8696
|
-
className: css$
|
|
9215
|
+
className: css$26.output,
|
|
8697
9216
|
children: [
|
|
8698
9217
|
(capped ? lines.slice(0, headLines) : lines).map((line, index) => jsx("div", {
|
|
8699
|
-
className: css$
|
|
9218
|
+
className: css$26.line,
|
|
8700
9219
|
children: renderLine$1(line)
|
|
8701
9220
|
}, index)),
|
|
8702
9221
|
hidden > 0 && jsx("button", {
|
|
8703
9222
|
type: "button",
|
|
8704
|
-
className: css$
|
|
9223
|
+
className: css$26.expand,
|
|
8705
9224
|
"aria-expanded": expanded,
|
|
8706
9225
|
"aria-label": expanded ? copy.collapseAria : copy.expandAria(hidden),
|
|
8707
9226
|
onClick: onToggle,
|
|
8708
9227
|
children: expanded ? copy.collapse : copy.expand(hidden)
|
|
8709
9228
|
}),
|
|
8710
9229
|
capped && lines.slice(lines.length - tailLines).map((line, index) => jsx("div", {
|
|
8711
|
-
className: css$
|
|
9230
|
+
className: css$26.line,
|
|
8712
9231
|
children: renderLine$1(line)
|
|
8713
9232
|
}, index))
|
|
8714
9233
|
]
|
|
@@ -8911,13 +9430,13 @@ function ReadBlock({ label, labels, lines, totalLines, lang, maxLines = 16, clas
|
|
|
8911
9430
|
const tailLines = maxLines - headLines;
|
|
8912
9431
|
const windowed = lines.length < totalLines;
|
|
8913
9432
|
const rows = (slice) => slice.map(([line, spans]) => jsxs("div", {
|
|
8914
|
-
className: css$
|
|
9433
|
+
className: css$27.line,
|
|
8915
9434
|
children: [jsx("span", {
|
|
8916
|
-
className: css$
|
|
9435
|
+
className: css$27.gutter,
|
|
8917
9436
|
"aria-hidden": true,
|
|
8918
9437
|
children: line.number
|
|
8919
9438
|
}), jsx("span", {
|
|
8920
|
-
className: css$
|
|
9439
|
+
className: css$27.content,
|
|
8921
9440
|
children: spans === void 0 ? line.text : renderSpans(spans)
|
|
8922
9441
|
})]
|
|
8923
9442
|
}, line.number));
|
|
@@ -8925,7 +9444,7 @@ function ReadBlock({ label, labels, lines, totalLines, lang, maxLines = 16, clas
|
|
|
8925
9444
|
const paired = lines.map((line, index) => [line, highlighted?.[index]]);
|
|
8926
9445
|
return jsxs("div", {
|
|
8927
9446
|
ref: rootRef,
|
|
8928
|
-
className: clsx(cardCss.card, css$
|
|
9447
|
+
className: clsx(cardCss.card, css$27.block, className),
|
|
8929
9448
|
"data-read": "",
|
|
8930
9449
|
"data-code-wrap": wrapped,
|
|
8931
9450
|
style: gutterStyle,
|
|
@@ -8947,7 +9466,7 @@ function ReadBlock({ label, labels, lines, totalLines, lang, maxLines = 16, clas
|
|
|
8947
9466
|
children: [
|
|
8948
9467
|
rows(capped ? paired.slice(0, headLines) : paired),
|
|
8949
9468
|
hidden > 0 && jsx(FoldToggle, {
|
|
8950
|
-
className: css$
|
|
9469
|
+
className: css$27.expand,
|
|
8951
9470
|
expanded,
|
|
8952
9471
|
hidden,
|
|
8953
9472
|
labels,
|
|
@@ -8969,11 +9488,11 @@ function assertNever(value) {
|
|
|
8969
9488
|
}
|
|
8970
9489
|
/** The dim class per row kind (path/gap chrome vs the diff's own +/- colors). */
|
|
8971
9490
|
const ROW_CLASS = {
|
|
8972
|
-
path: css$
|
|
8973
|
-
del: css$
|
|
8974
|
-
add: css$
|
|
8975
|
-
context: css$
|
|
8976
|
-
gap: css$
|
|
9491
|
+
path: css$28.path,
|
|
9492
|
+
del: css$28.del,
|
|
9493
|
+
add: css$28.add,
|
|
9494
|
+
context: css$28.context,
|
|
9495
|
+
gap: css$28.gap
|
|
8977
9496
|
};
|
|
8978
9497
|
/** Bound synchronous edit-graph search; one replacement consumes two edits. */
|
|
8979
9498
|
const MAX_DIFF_EDIT_LENGTH = 256;
|
|
@@ -9107,7 +9626,7 @@ function DiffBlock({ diffs, labels, maxLines = 16, className }) {
|
|
|
9107
9626
|
const head = capped ? rows.slice(0, headLines) : rows;
|
|
9108
9627
|
const tail = capped ? rows.slice(rows.length - tailLines) : [];
|
|
9109
9628
|
return jsxs("div", {
|
|
9110
|
-
className: clsx(cardCss.card, css$
|
|
9629
|
+
className: clsx(cardCss.card, css$28.block, className),
|
|
9111
9630
|
"data-diff": "",
|
|
9112
9631
|
"data-code-wrap": wrapped,
|
|
9113
9632
|
children: [jsx(CodeToolbar, {
|
|
@@ -9122,21 +9641,21 @@ function DiffBlock({ diffs, labels, maxLines = 16, className }) {
|
|
|
9122
9641
|
setWrapped((value) => !value);
|
|
9123
9642
|
}
|
|
9124
9643
|
}), jsxs("div", {
|
|
9125
|
-
className: css$
|
|
9644
|
+
className: css$28.body,
|
|
9126
9645
|
children: [
|
|
9127
9646
|
head.map((row, index) => jsx("div", {
|
|
9128
|
-
className: clsx(css$
|
|
9647
|
+
className: clsx(css$28.line, ROW_CLASS[row.kind]),
|
|
9129
9648
|
children: row.text
|
|
9130
9649
|
}, index)),
|
|
9131
9650
|
hidden > 0 && jsx(FoldToggle, {
|
|
9132
|
-
className: css$
|
|
9651
|
+
className: css$28.expand,
|
|
9133
9652
|
expanded,
|
|
9134
9653
|
hidden,
|
|
9135
9654
|
labels,
|
|
9136
9655
|
onToggle
|
|
9137
9656
|
}),
|
|
9138
9657
|
tail.map((row, index) => jsx("div", {
|
|
9139
|
-
className: clsx(css$
|
|
9658
|
+
className: clsx(css$28.line, ROW_CLASS[row.kind]),
|
|
9140
9659
|
children: row.text
|
|
9141
9660
|
}, index))
|
|
9142
9661
|
]
|
|
@@ -9266,56 +9785,56 @@ function SearchBlock(props) {
|
|
|
9266
9785
|
const tail = tailHeader === void 0 ? naturalTail : naturalTail.slice(1);
|
|
9267
9786
|
const renderRow = (row) => {
|
|
9268
9787
|
if (row.type === "path") return jsx("div", {
|
|
9269
|
-
className: css$
|
|
9788
|
+
className: css$29.line,
|
|
9270
9789
|
children: row.path
|
|
9271
9790
|
});
|
|
9272
9791
|
if (row.type === "match") return jsxs("div", {
|
|
9273
|
-
className: css$
|
|
9792
|
+
className: css$29.line,
|
|
9274
9793
|
children: [jsxs("span", {
|
|
9275
|
-
className: css$
|
|
9794
|
+
className: css$29.lineNumber,
|
|
9276
9795
|
children: [row.lineNumber, ": "]
|
|
9277
9796
|
}), row.line]
|
|
9278
9797
|
});
|
|
9279
9798
|
return jsxs("button", {
|
|
9280
9799
|
type: "button",
|
|
9281
|
-
className: css$
|
|
9800
|
+
className: css$29.fileHeader,
|
|
9282
9801
|
"aria-expanded": !row.collapsed,
|
|
9283
9802
|
onClick: () => {
|
|
9284
9803
|
toggleFile(row.index);
|
|
9285
9804
|
},
|
|
9286
9805
|
children: [jsx("span", {
|
|
9287
|
-
className: css$
|
|
9806
|
+
className: css$29.filePath,
|
|
9288
9807
|
children: row.path
|
|
9289
9808
|
}), jsx("span", {
|
|
9290
|
-
className: css$
|
|
9809
|
+
className: css$29.fileCount,
|
|
9291
9810
|
children: row.count
|
|
9292
9811
|
})]
|
|
9293
9812
|
});
|
|
9294
9813
|
};
|
|
9295
9814
|
return jsxs("div", {
|
|
9296
|
-
className: clsx(css$
|
|
9815
|
+
className: clsx(css$29.block, className),
|
|
9297
9816
|
"data-search": props.kind,
|
|
9298
9817
|
children: [jsxs("div", {
|
|
9299
|
-
className: css$
|
|
9818
|
+
className: css$29.header,
|
|
9300
9819
|
children: [jsx("span", {
|
|
9301
|
-
className: css$
|
|
9820
|
+
className: css$29.summary,
|
|
9302
9821
|
children: summaryText(props, shown, truncated, total)
|
|
9303
9822
|
}), !empty && jsx("button", {
|
|
9304
9823
|
type: "button",
|
|
9305
|
-
className: css$
|
|
9824
|
+
className: css$29.copyButton,
|
|
9306
9825
|
onClick: onCopy,
|
|
9307
9826
|
children: copied ? props.labels.copied : props.labels.copy
|
|
9308
9827
|
})]
|
|
9309
9828
|
}), empty ? jsx("div", {
|
|
9310
|
-
className: css$
|
|
9829
|
+
className: css$29.empty,
|
|
9311
9830
|
children: props.labels.noResults
|
|
9312
9831
|
}) : jsxs("div", {
|
|
9313
|
-
className: css$
|
|
9832
|
+
className: css$29.body,
|
|
9314
9833
|
children: [
|
|
9315
9834
|
head.map((row) => jsx("div", { children: renderRow(row) }, rowKey(row))),
|
|
9316
9835
|
hidden > 0 && jsx("button", {
|
|
9317
9836
|
type: "button",
|
|
9318
|
-
className: css$
|
|
9837
|
+
className: css$29.expand,
|
|
9319
9838
|
"aria-expanded": expanded,
|
|
9320
9839
|
"aria-label": expanded ? props.labels.collapseAria : props.labels.expandAria(hidden),
|
|
9321
9840
|
onClick: onToggle,
|
|
@@ -9626,6 +10145,32 @@ var IncrementalMarkdownParser = class {
|
|
|
9626
10145
|
}
|
|
9627
10146
|
};
|
|
9628
10147
|
//#endregion
|
|
10148
|
+
//#region lib/types/markdown/local-image-syntax.js
|
|
10149
|
+
/**
|
|
10150
|
+
* Recover only unambiguous, unescaped image-only paragraphs containing a local path with spaces.
|
|
10151
|
+
* @param root - Parsed Markdown tree, modified in place.
|
|
10152
|
+
* @param source - Original source used to distinguish authored syntax from escaped examples.
|
|
10153
|
+
* @returns The same root with recovered image nodes.
|
|
10154
|
+
*/
|
|
10155
|
+
function recoverLocalImages(root, source) {
|
|
10156
|
+
const visit = (node) => {
|
|
10157
|
+
if (node.type === "paragraph" && node.children.length === 1) {
|
|
10158
|
+
const [child] = node.children;
|
|
10159
|
+
if (child.type === "text" && child.position !== void 0 && source.slice(child.position.start.offset, child.position.end.offset) === child.value) {
|
|
10160
|
+
const match = /^!\[([^\]\n]*)\]\(((?:\/(?!\/)|\.{1,2}\/|[a-z]:[\\/])[^\n<>()[\]"']+\.[a-z\d]+)\)$/iu.exec(child.value);
|
|
10161
|
+
if (match !== null && match[2].includes(" ") && classifyFileType(match[2]) === "image") node.children = [{
|
|
10162
|
+
type: "image",
|
|
10163
|
+
alt: match[1],
|
|
10164
|
+
url: match[2],
|
|
10165
|
+
position: child.position
|
|
10166
|
+
}];
|
|
10167
|
+
}
|
|
10168
|
+
} else if ("children" in node) for (const child of node.children) visit(child);
|
|
10169
|
+
};
|
|
10170
|
+
visit(root);
|
|
10171
|
+
return root;
|
|
10172
|
+
}
|
|
10173
|
+
//#endregion
|
|
9629
10174
|
//#region lib/types/markdown/cjkFriendlyStrong.js
|
|
9630
10175
|
/** Let asterisk strong emphasis close after punctuation when CJK prose continues without whitespace. */
|
|
9631
10176
|
const cjkCharacter = new RegExp([
|
|
@@ -9972,10 +10517,10 @@ function mathCompatibility() {
|
|
|
9972
10517
|
* @returns The mdast root.
|
|
9973
10518
|
*/
|
|
9974
10519
|
function parseGfm(text) {
|
|
9975
|
-
return fromMarkdown(text, {
|
|
10520
|
+
return recoverLocalImages(fromMarkdown(text, {
|
|
9976
10521
|
extensions: [gfm(), cjkFriendlyStrong()],
|
|
9977
10522
|
mdastExtensions: [gfmFromMarkdown()]
|
|
9978
|
-
});
|
|
10523
|
+
}), text);
|
|
9979
10524
|
}
|
|
9980
10525
|
/**
|
|
9981
10526
|
* Parse GFM markdown plus TeX math with the compatibility delimiters
|
|
@@ -9984,7 +10529,7 @@ function parseGfm(text) {
|
|
|
9984
10529
|
* @returns The mdast root.
|
|
9985
10530
|
*/
|
|
9986
10531
|
function parseGfmWithMath(text) {
|
|
9987
|
-
return fromMarkdown(text, {
|
|
10532
|
+
return recoverLocalImages(fromMarkdown(text, {
|
|
9988
10533
|
extensions: [
|
|
9989
10534
|
gfm(),
|
|
9990
10535
|
cjkFriendlyStrong(),
|
|
@@ -9992,7 +10537,7 @@ function parseGfmWithMath(text) {
|
|
|
9992
10537
|
math()
|
|
9993
10538
|
],
|
|
9994
10539
|
mdastExtensions: [gfmFromMarkdown(), mathFromMarkdown()]
|
|
9995
|
-
});
|
|
10540
|
+
}), text);
|
|
9996
10541
|
}
|
|
9997
10542
|
//#endregion
|
|
9998
10543
|
//#region lib/types/markdown/CodeBlock.js
|
|
@@ -10119,7 +10664,7 @@ function CodeBlock({ code, lang, streaming, className, contentRef, lineNumbers =
|
|
|
10119
10664
|
});
|
|
10120
10665
|
}, [copied, trimmed]);
|
|
10121
10666
|
const body = streamedBody !== void 0 ? streamedBody : html === void 0 ? jsx("pre", {
|
|
10122
|
-
className: css$
|
|
10667
|
+
className: css$30.plain,
|
|
10123
10668
|
children: jsx("code", { children: sourceLines === void 0 ? trimmed : sourceLines.map((line, index) => jsxs(Fragment$1, { children: [index > 0 && "\n", jsx("span", {
|
|
10124
10669
|
className: "line",
|
|
10125
10670
|
children: line
|
|
@@ -10127,12 +10672,12 @@ function CodeBlock({ code, lang, streaming, className, contentRef, lineNumbers =
|
|
|
10127
10672
|
}) : jsx("div", { dangerouslySetInnerHTML: { __html: html } });
|
|
10128
10673
|
return jsxs("div", {
|
|
10129
10674
|
ref: rootRef,
|
|
10130
|
-
className: clsx(css$
|
|
10675
|
+
className: clsx(css$30.block, "md-code-block", lineNumbers && css$30.numbered, toolbarLabels !== void 0 && css$30.card, className),
|
|
10131
10676
|
"data-line-numbers": lineNumbers || void 0,
|
|
10132
10677
|
"data-code-wrap": toolbarLabels === void 0 ? void 0 : wrapped,
|
|
10133
10678
|
style: sourceLines === void 0 ? void 0 : { "--dsl-code-block-line-number-width": `${Math.max(2, String(sourceLines.length).length)}ch` },
|
|
10134
10679
|
children: [showHeader && jsx("div", {
|
|
10135
|
-
className: css$
|
|
10680
|
+
className: css$30.bannerWrap,
|
|
10136
10681
|
children: toolbarLabels !== void 0 ? jsx(CodeToolbar, {
|
|
10137
10682
|
lang,
|
|
10138
10683
|
labels: toolbarLabels,
|
|
@@ -10145,16 +10690,16 @@ function CodeBlock({ code, lang, streaming, className, contentRef, lineNumbers =
|
|
|
10145
10690
|
setWrapped((value) => !value);
|
|
10146
10691
|
} : void 0
|
|
10147
10692
|
}) : jsxs("div", {
|
|
10148
|
-
className: css$
|
|
10693
|
+
className: css$30.banner,
|
|
10149
10694
|
"data-code-block-banner": true,
|
|
10150
10695
|
children: [jsx("div", {
|
|
10151
|
-
className: css$
|
|
10696
|
+
className: css$30.infostring,
|
|
10152
10697
|
children: lang ?? ""
|
|
10153
10698
|
}), jsx("div", {
|
|
10154
|
-
className: css$
|
|
10699
|
+
className: css$30.action,
|
|
10155
10700
|
children: jsx("button", {
|
|
10156
10701
|
type: "button",
|
|
10157
|
-
className: css$
|
|
10702
|
+
className: css$30.copyButton,
|
|
10158
10703
|
onClick: onCopy,
|
|
10159
10704
|
children: copied ? copiedLabel : copyLabel
|
|
10160
10705
|
})
|
|
@@ -10162,7 +10707,7 @@ function CodeBlock({ code, lang, streaming, className, contentRef, lineNumbers =
|
|
|
10162
10707
|
})
|
|
10163
10708
|
}), jsx("div", {
|
|
10164
10709
|
ref: contentRef,
|
|
10165
|
-
className: css$
|
|
10710
|
+
className: css$30.content,
|
|
10166
10711
|
"data-code-block-content": true,
|
|
10167
10712
|
children: body
|
|
10168
10713
|
})]
|
|
@@ -10292,11 +10837,16 @@ const MarkdownDelegateContext = createContext({});
|
|
|
10292
10837
|
* @param props - Child tree and its file and HTTP(S) link handlers.
|
|
10293
10838
|
* @returns the scoped child tree.
|
|
10294
10839
|
*/
|
|
10295
|
-
function MarkdownDelegateProvider({ children, openExternalLink, openFile }) {
|
|
10840
|
+
function MarkdownDelegateProvider({ children, openExternalLink, openFile, fileImages }) {
|
|
10296
10841
|
const delegate = useMemo(() => ({
|
|
10297
10842
|
openExternalLink,
|
|
10298
|
-
openFile
|
|
10299
|
-
|
|
10843
|
+
openFile,
|
|
10844
|
+
fileImages
|
|
10845
|
+
}), [
|
|
10846
|
+
openExternalLink,
|
|
10847
|
+
openFile,
|
|
10848
|
+
fileImages
|
|
10849
|
+
]);
|
|
10300
10850
|
return jsx(MarkdownDelegateContext.Provider, {
|
|
10301
10851
|
value: delegate,
|
|
10302
10852
|
children
|
|
@@ -10310,6 +10860,111 @@ function useMarkdownDelegate() {
|
|
|
10310
10860
|
return useContext(MarkdownDelegateContext);
|
|
10311
10861
|
}
|
|
10312
10862
|
//#endregion
|
|
10863
|
+
//#region lib/types/ImageLightbox.js
|
|
10864
|
+
/**
|
|
10865
|
+
* Document-level original-image preview opened by clicking a thumbnail.
|
|
10866
|
+
* Closes on Escape, backdrop press, or the close control, and restores focus
|
|
10867
|
+
* to the opener on unmount. Rendered through a body portal: an opener inside
|
|
10868
|
+
* a transformed or filtered ancestor would otherwise trap the fixed backdrop
|
|
10869
|
+
* in that ancestor's box instead of covering the viewport.
|
|
10870
|
+
*
|
|
10871
|
+
* @param props.src - the original image URL.
|
|
10872
|
+
* @param props.alt - the image's alt text.
|
|
10873
|
+
* @param props.labels - dialog and close-control strings.
|
|
10874
|
+
* @param props.onClose - dismiss callback owned by the opener.
|
|
10875
|
+
* @returns the modal preview dialog.
|
|
10876
|
+
*/
|
|
10877
|
+
function ImageLightbox({ src, alt, labels, onClose }) {
|
|
10878
|
+
const closeRef = useRef(null);
|
|
10879
|
+
const restoreRef = useRef(null);
|
|
10880
|
+
useEffect(() => {
|
|
10881
|
+
restoreRef.current = document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
10882
|
+
closeRef.current?.focus();
|
|
10883
|
+
const onKeyDown = (event) => {
|
|
10884
|
+
if (event.key === "Escape") {
|
|
10885
|
+
event.stopPropagation();
|
|
10886
|
+
onClose();
|
|
10887
|
+
}
|
|
10888
|
+
if (event.key === "Tab") {
|
|
10889
|
+
event.preventDefault();
|
|
10890
|
+
closeRef.current?.focus();
|
|
10891
|
+
}
|
|
10892
|
+
};
|
|
10893
|
+
window.addEventListener("keydown", onKeyDown, true);
|
|
10894
|
+
return () => {
|
|
10895
|
+
window.removeEventListener("keydown", onKeyDown, true);
|
|
10896
|
+
restoreRef.current?.focus();
|
|
10897
|
+
};
|
|
10898
|
+
}, [onClose]);
|
|
10899
|
+
return createPortal(jsxs("div", {
|
|
10900
|
+
className: css$31.backdrop,
|
|
10901
|
+
role: "dialog",
|
|
10902
|
+
"aria-modal": "true",
|
|
10903
|
+
"aria-label": labels.dialog,
|
|
10904
|
+
children: [
|
|
10905
|
+
jsx("div", {
|
|
10906
|
+
className: css$31.mask,
|
|
10907
|
+
"aria-hidden": "true",
|
|
10908
|
+
onMouseDown: onClose
|
|
10909
|
+
}),
|
|
10910
|
+
jsx("img", {
|
|
10911
|
+
className: css$31.image,
|
|
10912
|
+
src,
|
|
10913
|
+
alt
|
|
10914
|
+
}),
|
|
10915
|
+
jsx("button", {
|
|
10916
|
+
ref: closeRef,
|
|
10917
|
+
type: "button",
|
|
10918
|
+
className: css$31.close,
|
|
10919
|
+
"aria-label": labels.close,
|
|
10920
|
+
onClick: onClose,
|
|
10921
|
+
children: jsx(IconCloseOutlineRegular, { size: 16 })
|
|
10922
|
+
})
|
|
10923
|
+
]
|
|
10924
|
+
}), document.body);
|
|
10925
|
+
}
|
|
10926
|
+
//#endregion
|
|
10927
|
+
//#region lib/types/ImagePreview.js
|
|
10928
|
+
/** Passive, contained image preview for Markdown image links. */
|
|
10929
|
+
/**
|
|
10930
|
+
* Render an image without introducing a second activation target.
|
|
10931
|
+
* @param props - Source, accessible description, localized status.
|
|
10932
|
+
* @returns A contained preview with loading or failure status.
|
|
10933
|
+
*/
|
|
10934
|
+
function ImagePreview({ src, alt, loadingLabel, failedLabel }) {
|
|
10935
|
+
return jsx(Preview, {
|
|
10936
|
+
src,
|
|
10937
|
+
alt,
|
|
10938
|
+
loadingLabel,
|
|
10939
|
+
failedLabel
|
|
10940
|
+
}, src);
|
|
10941
|
+
}
|
|
10942
|
+
function Preview({ src, alt, loadingLabel, failedLabel }) {
|
|
10943
|
+
const [state, setState] = useState("loading");
|
|
10944
|
+
return jsxs("span", {
|
|
10945
|
+
className: css$32.frame,
|
|
10946
|
+
children: [state !== "failed" && jsx("img", {
|
|
10947
|
+
src,
|
|
10948
|
+
alt,
|
|
10949
|
+
loading: "lazy",
|
|
10950
|
+
decoding: "async",
|
|
10951
|
+
referrerPolicy: "no-referrer",
|
|
10952
|
+
className: css$32.image,
|
|
10953
|
+
"data-ready": state === "ready" || void 0,
|
|
10954
|
+
onLoad: () => {
|
|
10955
|
+
setState("ready");
|
|
10956
|
+
},
|
|
10957
|
+
onError: () => {
|
|
10958
|
+
setState("failed");
|
|
10959
|
+
}
|
|
10960
|
+
}), state !== "ready" && jsxs("span", {
|
|
10961
|
+
className: css$32.status,
|
|
10962
|
+
role: "status",
|
|
10963
|
+
children: [state === "loading" && jsx(IconLoadingOutlineRegular, { size: 16 }), jsx("span", { children: state === "loading" ? loadingLabel : failedLabel })]
|
|
10964
|
+
})]
|
|
10965
|
+
});
|
|
10966
|
+
}
|
|
10967
|
+
//#endregion
|
|
10313
10968
|
//#region lib/types/markdown/render.js
|
|
10314
10969
|
/**
|
|
10315
10970
|
* Direct mdast→React markdown renderer. Replaces the react-markdown /
|
|
@@ -10348,11 +11003,11 @@ function remoteImageUrl(url) {
|
|
|
10348
11003
|
return;
|
|
10349
11004
|
}
|
|
10350
11005
|
}
|
|
10351
|
-
/**
|
|
11006
|
+
/** Rewritten images may use Web media protocols or the Desktop application's file route. */
|
|
10352
11007
|
function vocabularyImageUrl(url) {
|
|
10353
11008
|
try {
|
|
10354
11009
|
const protocol = new URL(url).protocol;
|
|
10355
|
-
return protocol === "http:" || protocol === "https:" || protocol === "blob:" || protocol === "data:" ? url : void 0;
|
|
11010
|
+
return protocol === "http:" || protocol === "https:" || protocol === "blob:" || protocol === "data:" || url.startsWith("dsh-app://app/api/file?") ? url : void 0;
|
|
10356
11011
|
} catch {
|
|
10357
11012
|
return;
|
|
10358
11013
|
}
|
|
@@ -10631,12 +11286,14 @@ function renderAnchor(url, children, key, glyph = true, streaming = false) {
|
|
|
10631
11286
|
return renderSafeLink(normalizeUri(url), children, key, glyph);
|
|
10632
11287
|
}
|
|
10633
11288
|
function MarkdownFileLink({ file, glyph, children }) {
|
|
10634
|
-
const { openFile } = useMarkdownDelegate();
|
|
11289
|
+
const { openFile, fileImages } = useMarkdownDelegate();
|
|
10635
11290
|
if (openFile === void 0) return jsx(Fragment, { children });
|
|
10636
|
-
|
|
11291
|
+
const preview = glyph && classifyLinkPath(file.path) === "image" ? fileImages : void 0;
|
|
11292
|
+
const src = preview?.resolve(file.path);
|
|
11293
|
+
const anchor = jsxs("button", {
|
|
10637
11294
|
type: "button",
|
|
10638
11295
|
className: clsx(markdownCss.fileMention, markdownCss.fileLink),
|
|
10639
|
-
title: file.path,
|
|
11296
|
+
title: src === void 0 ? file.path : void 0,
|
|
10640
11297
|
onClick: () => {
|
|
10641
11298
|
openFile(file.path, file.line === void 0 ? void 0 : { line: file.line });
|
|
10642
11299
|
},
|
|
@@ -10645,6 +11302,20 @@ function MarkdownFileLink({ file, glyph, children }) {
|
|
|
10645
11302
|
className: markdownCss.linkIcon
|
|
10646
11303
|
}), children]
|
|
10647
11304
|
});
|
|
11305
|
+
if (src === void 0 || preview === void 0) return anchor;
|
|
11306
|
+
return jsx(HoverCard, {
|
|
11307
|
+
inline: true,
|
|
11308
|
+
anchor,
|
|
11309
|
+
content: jsxs(Fragment, { children: [jsx(ImagePreview, {
|
|
11310
|
+
src,
|
|
11311
|
+
alt: file.path,
|
|
11312
|
+
loadingLabel: preview.labels.loading,
|
|
11313
|
+
failedLabel: preview.labels.failed
|
|
11314
|
+
}), jsx("span", {
|
|
11315
|
+
className: markdownCss.previewName,
|
|
11316
|
+
children: file.path.split(/[\\/]/u).pop()
|
|
11317
|
+
})] })
|
|
11318
|
+
});
|
|
10648
11319
|
}
|
|
10649
11320
|
/**
|
|
10650
11321
|
* The complete inline-code value when it is exactly an absolute HTTP(S) URL
|
|
@@ -10660,25 +11331,40 @@ function inlineCodeHttpUrl(value) {
|
|
|
10660
11331
|
}
|
|
10661
11332
|
}
|
|
10662
11333
|
function renderImage(url, alt, key, context) {
|
|
10663
|
-
|
|
10664
|
-
|
|
11334
|
+
return jsx(MarkdownImage, {
|
|
11335
|
+
destination: url,
|
|
11336
|
+
alt,
|
|
11337
|
+
pathImages: context.pathImages,
|
|
11338
|
+
streaming: context.streaming,
|
|
11339
|
+
inLink: context.inLink === true
|
|
11340
|
+
}, `${key}:${url}`);
|
|
11341
|
+
}
|
|
11342
|
+
function MarkdownImage({ destination, alt, pathImages, streaming, inLink }) {
|
|
11343
|
+
const { fileImages } = useMarkdownDelegate();
|
|
11344
|
+
const file = streaming ? void 0 : parseFileLink(destination);
|
|
11345
|
+
const src = (file === void 0 ? void 0 : fileImages?.resolve(file.path)) ?? imageSource(destination, pathImages);
|
|
11346
|
+
if (src === void 0) return jsx("span", {
|
|
10665
11347
|
className: markdownCss.imageAlt,
|
|
10666
11348
|
children: alt
|
|
10667
|
-
}
|
|
10668
|
-
return jsx(
|
|
10669
|
-
src
|
|
11349
|
+
});
|
|
11350
|
+
return jsx(LoadedMarkdownImage, {
|
|
11351
|
+
src,
|
|
10670
11352
|
alt,
|
|
10671
|
-
destination
|
|
10672
|
-
|
|
11353
|
+
destination,
|
|
11354
|
+
preview: inLink ? void 0 : fileImages
|
|
11355
|
+
}, src);
|
|
10673
11356
|
}
|
|
10674
|
-
|
|
10675
|
-
function MarkdownImage({ src, alt, destination }) {
|
|
11357
|
+
function LoadedMarkdownImage({ src, alt, destination, preview }) {
|
|
10676
11358
|
const [failed, setFailed] = useState(false);
|
|
10677
|
-
|
|
11359
|
+
const [open, setOpen] = useState(false);
|
|
11360
|
+
const close = useCallback(() => {
|
|
11361
|
+
setOpen(false);
|
|
11362
|
+
}, []);
|
|
11363
|
+
if (failed) return jsxs("span", {
|
|
10678
11364
|
className: markdownCss.imageAlt,
|
|
10679
|
-
children: alt || destination
|
|
11365
|
+
children: [preview === void 0 ? "" : `${preview.labels.failed} · `, alt || destination]
|
|
10680
11366
|
});
|
|
10681
|
-
|
|
11367
|
+
const img = jsx("img", {
|
|
10682
11368
|
className: markdownCss.image,
|
|
10683
11369
|
src,
|
|
10684
11370
|
alt,
|
|
@@ -10689,6 +11375,22 @@ function MarkdownImage({ src, alt, destination }) {
|
|
|
10689
11375
|
decoding: "async",
|
|
10690
11376
|
referrerPolicy: "no-referrer"
|
|
10691
11377
|
});
|
|
11378
|
+
if (preview === void 0) return img;
|
|
11379
|
+
return jsxs(Fragment, { children: [jsx("button", {
|
|
11380
|
+
type: "button",
|
|
11381
|
+
className: markdownCss.imageButton,
|
|
11382
|
+
title: preview.labels.open,
|
|
11383
|
+
"aria-label": alt ? `${preview.labels.open}: ${alt}` : preview.labels.open,
|
|
11384
|
+
onClick: () => {
|
|
11385
|
+
setOpen(true);
|
|
11386
|
+
},
|
|
11387
|
+
children: img
|
|
11388
|
+
}), open && jsx(ImageLightbox, {
|
|
11389
|
+
src,
|
|
11390
|
+
alt,
|
|
11391
|
+
labels: preview.labels,
|
|
11392
|
+
onClose: close
|
|
11393
|
+
})] });
|
|
10692
11394
|
}
|
|
10693
11395
|
/** The bracketed source text a reference reverts to when its definition is missing. */
|
|
10694
11396
|
function referenceSuffix(node) {
|
|
@@ -10995,7 +11697,7 @@ function SafeLink({ url, label, className }) {
|
|
|
10995
11697
|
children: [jsx(LinkIconMedium, {
|
|
10996
11698
|
kind: "url",
|
|
10997
11699
|
href,
|
|
10998
|
-
className: css$
|
|
11700
|
+
className: css$33.linkIcon
|
|
10999
11701
|
}), label]
|
|
11000
11702
|
});
|
|
11001
11703
|
}
|
|
@@ -11010,20 +11712,20 @@ function SafeLink({ url, label, className }) {
|
|
|
11010
11712
|
*/
|
|
11011
11713
|
function SourceItem({ source, ordinal }) {
|
|
11012
11714
|
return jsxs("li", {
|
|
11013
|
-
className: css$
|
|
11715
|
+
className: css$33.source,
|
|
11014
11716
|
value: ordinal,
|
|
11015
11717
|
children: [
|
|
11016
11718
|
jsx(SafeLink, {
|
|
11017
11719
|
url: source.url,
|
|
11018
11720
|
label: linkLabel(source.url, source.title),
|
|
11019
|
-
className: css$
|
|
11721
|
+
className: css$33.sourceLink
|
|
11020
11722
|
}),
|
|
11021
11723
|
source.snippet !== void 0 && source.snippet !== "" && jsx("div", {
|
|
11022
|
-
className: css$
|
|
11724
|
+
className: css$33.snippet,
|
|
11023
11725
|
children: source.snippet
|
|
11024
11726
|
}),
|
|
11025
11727
|
source.publishedAt !== void 0 && source.publishedAt !== "" && jsx("div", {
|
|
11026
|
-
className: css$
|
|
11728
|
+
className: css$33.published,
|
|
11027
11729
|
children: source.publishedAt
|
|
11028
11730
|
})
|
|
11029
11731
|
]
|
|
@@ -11038,28 +11740,28 @@ function SourceItem({ source, ordinal }) {
|
|
|
11038
11740
|
function WebSearchBlock({ answer, sources, truncated, labels, className }) {
|
|
11039
11741
|
const empty = (answer === void 0 || answer === "") && sources.length === 0;
|
|
11040
11742
|
return jsxs("div", {
|
|
11041
|
-
className: clsx(css$
|
|
11743
|
+
className: clsx(css$33.block, className),
|
|
11042
11744
|
"data-web": "search",
|
|
11043
11745
|
children: [
|
|
11044
11746
|
answer !== void 0 && answer !== "" && jsx("div", {
|
|
11045
|
-
className: css$
|
|
11747
|
+
className: css$33.answer,
|
|
11046
11748
|
children: jsx(MarkdownText, {
|
|
11047
11749
|
text: answer,
|
|
11048
11750
|
labels: labels.markdown
|
|
11049
11751
|
})
|
|
11050
11752
|
}),
|
|
11051
11753
|
empty ? jsx("div", {
|
|
11052
|
-
className: css$
|
|
11754
|
+
className: css$33.empty,
|
|
11053
11755
|
children: labels.noResults
|
|
11054
11756
|
}) : jsx("ol", {
|
|
11055
|
-
className: css$
|
|
11757
|
+
className: css$33.sources,
|
|
11056
11758
|
children: sources.map((source, index) => jsx(SourceItem, {
|
|
11057
11759
|
source,
|
|
11058
11760
|
ordinal: index + 1
|
|
11059
11761
|
}, index))
|
|
11060
11762
|
}),
|
|
11061
11763
|
truncated && jsx("div", {
|
|
11062
|
-
className: css$
|
|
11764
|
+
className: css$33.truncated,
|
|
11063
11765
|
children: labels.sourcesTruncated
|
|
11064
11766
|
})
|
|
11065
11767
|
]
|
|
@@ -11072,23 +11774,23 @@ function WebSearchBlock({ answer, sources, truncated, labels, className }) {
|
|
|
11072
11774
|
*/
|
|
11073
11775
|
function WebFetchBlock({ url, statusCode, truncated, labels, className }) {
|
|
11074
11776
|
return jsxs("div", {
|
|
11075
|
-
className: clsx(css$
|
|
11777
|
+
className: clsx(css$33.block, css$33.fetch, className),
|
|
11076
11778
|
"data-web": "fetch",
|
|
11077
11779
|
children: [jsx(SafeLink, {
|
|
11078
11780
|
url,
|
|
11079
11781
|
label: url,
|
|
11080
|
-
className: css$
|
|
11782
|
+
className: css$33.fetchUrl
|
|
11081
11783
|
}), jsxs("div", {
|
|
11082
|
-
className: css$
|
|
11784
|
+
className: css$33.fetchMeta,
|
|
11083
11785
|
children: [jsxs("span", {
|
|
11084
|
-
className: css$
|
|
11786
|
+
className: css$33.status,
|
|
11085
11787
|
children: [
|
|
11086
11788
|
labels.http,
|
|
11087
11789
|
" ",
|
|
11088
11790
|
statusCode
|
|
11089
11791
|
]
|
|
11090
11792
|
}), truncated && jsx("span", {
|
|
11091
|
-
className: css$
|
|
11793
|
+
className: css$33.truncated,
|
|
11092
11794
|
children: labels.contentTruncated
|
|
11093
11795
|
})]
|
|
11094
11796
|
})]
|
|
@@ -11122,10 +11824,10 @@ function JsonBlock({ label, payload, defaultOpen = false, truncatedLabel }) {
|
|
|
11122
11824
|
truncatedLabel
|
|
11123
11825
|
]);
|
|
11124
11826
|
return jsxs("div", {
|
|
11125
|
-
className: css$
|
|
11827
|
+
className: css$34.root,
|
|
11126
11828
|
children: [jsxs("button", {
|
|
11127
11829
|
type: "button",
|
|
11128
|
-
className: css$
|
|
11830
|
+
className: css$34.toggle,
|
|
11129
11831
|
onClick: () => {
|
|
11130
11832
|
setOpen((v) => !v);
|
|
11131
11833
|
},
|
|
@@ -11135,7 +11837,7 @@ function JsonBlock({ label, payload, defaultOpen = false, truncatedLabel }) {
|
|
|
11135
11837
|
label
|
|
11136
11838
|
]
|
|
11137
11839
|
}), open && jsx("pre", {
|
|
11138
|
-
className: css$
|
|
11840
|
+
className: css$34.body,
|
|
11139
11841
|
children: body
|
|
11140
11842
|
})]
|
|
11141
11843
|
});
|
|
@@ -11223,7 +11925,7 @@ function extractMarkdownPlainText(markdown, options = {}) {
|
|
|
11223
11925
|
* and duplicate document ids would make every `url(#…)` resolve to the first instance.
|
|
11224
11926
|
*/
|
|
11225
11927
|
const useArtworkId = () => `dsh_plugin_art_${useId().replaceAll(":", "")}`;
|
|
11226
|
-
/**
|
|
11928
|
+
/** Light-blue terminal artwork shared by plugin cards and sidebar guide entries. */
|
|
11227
11929
|
const PluginArtworkTerminal = ({ size = 36, className }) => jsxs("svg", {
|
|
11228
11930
|
width: size,
|
|
11229
11931
|
height: size,
|
|
@@ -11233,11 +11935,11 @@ const PluginArtworkTerminal = ({ size = 36, className }) => jsxs("svg", {
|
|
|
11233
11935
|
xmlns: "http://www.w3.org/2000/svg",
|
|
11234
11936
|
children: [jsx("path", {
|
|
11235
11937
|
d: "M10 11L16.606 17.606C16.6841 17.6841 16.6841 17.8107 16.606 17.8888L10 24.4948",
|
|
11236
|
-
stroke: "#
|
|
11938
|
+
stroke: "#679EFE",
|
|
11237
11939
|
strokeWidth: "3.5"
|
|
11238
11940
|
}), jsx("path", {
|
|
11239
11941
|
d: "M20.1211 24.4946H26.8685",
|
|
11240
|
-
stroke: "#
|
|
11942
|
+
stroke: "#679EFE",
|
|
11241
11943
|
strokeWidth: "3.5"
|
|
11242
11944
|
})]
|
|
11243
11945
|
});
|
|
@@ -11411,6 +12113,71 @@ const PluginArtworkDefault = ({ size = 36, className }) => {
|
|
|
11411
12113
|
});
|
|
11412
12114
|
};
|
|
11413
12115
|
//#endregion
|
|
11414
|
-
|
|
12116
|
+
//#region lib/types/guide-artwork.js
|
|
12117
|
+
/**
|
|
12118
|
+
* Render fixed-palette artwork for a sidebar guide entry.
|
|
12119
|
+
* @param props - canvas size and layout class supplied by the guide.
|
|
12120
|
+
* @returns an ornamental SVG hidden from assistive technology.
|
|
12121
|
+
*/
|
|
12122
|
+
function GuideArtworkBrowser({ size = 36, className }) {
|
|
12123
|
+
return jsxs("svg", {
|
|
12124
|
+
width: size,
|
|
12125
|
+
height: size,
|
|
12126
|
+
className,
|
|
12127
|
+
"aria-hidden": "true",
|
|
12128
|
+
viewBox: "0 0 36 36",
|
|
12129
|
+
fill: "none",
|
|
12130
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
12131
|
+
children: [
|
|
12132
|
+
jsx("path", {
|
|
12133
|
+
d: "M17.9995 28.1465C23.6034 28.1465 28.1461 23.6038 28.1461 18C28.1461 12.3963 23.6034 7.85352 17.9995 7.85352C12.3958 7.85352 7.85303 12.3963 7.85303 18C7.85303 23.6038 12.3958 28.1465 17.9995 28.1465Z",
|
|
12134
|
+
stroke: "#539CFA",
|
|
12135
|
+
strokeWidth: "2"
|
|
12136
|
+
}),
|
|
12137
|
+
jsx("path", {
|
|
12138
|
+
d: "M8.57764 18H27.4211",
|
|
12139
|
+
stroke: "#539CFA",
|
|
12140
|
+
strokeWidth: "2",
|
|
12141
|
+
strokeLinecap: "square"
|
|
12142
|
+
}),
|
|
12143
|
+
jsx("path", {
|
|
12144
|
+
d: "M17.999 28.1467C20.0576 28.1467 21.6228 23.6039 21.6228 18C21.6228 12.3963 20.0576 7.85352 17.999 7.85352",
|
|
12145
|
+
stroke: "#539CFA",
|
|
12146
|
+
strokeWidth: "2"
|
|
12147
|
+
}),
|
|
12148
|
+
jsx("path", {
|
|
12149
|
+
d: "M17.9992 28.1467C15.9407 28.1467 14.3755 23.6039 14.3755 18C14.3755 12.3963 15.9407 7.85352 17.9992 7.85352",
|
|
12150
|
+
stroke: "#539CFA",
|
|
12151
|
+
strokeWidth: "2"
|
|
12152
|
+
})
|
|
12153
|
+
]
|
|
12154
|
+
});
|
|
12155
|
+
}
|
|
12156
|
+
/**
|
|
12157
|
+
* Render fixed-palette artwork for a sidebar guide entry.
|
|
12158
|
+
* @param props - canvas size and layout class supplied by the guide.
|
|
12159
|
+
* @returns an ornamental SVG hidden from assistive technology.
|
|
12160
|
+
*/
|
|
12161
|
+
function GuideArtworkFiles({ size = 36, className }) {
|
|
12162
|
+
return jsxs("svg", {
|
|
12163
|
+
width: size,
|
|
12164
|
+
height: size,
|
|
12165
|
+
className,
|
|
12166
|
+
"aria-hidden": "true",
|
|
12167
|
+
viewBox: "0 0 36 36",
|
|
12168
|
+
fill: "none",
|
|
12169
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
12170
|
+
children: [jsx("path", {
|
|
12171
|
+
d: "M10.7603 27.922H24.6817C26.3441 27.922 27.1753 27.922 27.8102 27.5984C28.3687 27.3139 28.8228 26.8598 29.1074 26.3012C29.4309 25.6663 29.4309 24.8351 29.4309 23.1727V15.4936",
|
|
12172
|
+
stroke: "#FFCD78",
|
|
12173
|
+
strokeWidth: "1.97886"
|
|
12174
|
+
}), jsx("path", {
|
|
12175
|
+
d: "M13.1597 8.07812C13.4182 8.07818 13.6727 8.14336 13.8989 8.26855L16.7554 9.84961C16.9817 9.97485 17.2369 10.041 17.4956 10.041H26.106C26.9492 10.0412 27.6323 10.7251 27.6323 11.5684V24.5371C27.6323 25.3805 26.9483 26.0645 26.105 26.0645H8.09619C7.25281 26.0645 6.56884 25.3805 6.56885 24.5371V9.60449C6.56909 8.76133 7.25297 8.07812 8.09619 8.07812H13.1597ZM9.81592 14.5508V16.5293H24.3999V14.5508H9.81592Z",
|
|
12176
|
+
fill: "#FFBC4D"
|
|
12177
|
+
})]
|
|
12178
|
+
});
|
|
12179
|
+
}
|
|
12180
|
+
//#endregion
|
|
12181
|
+
export { BrandWordmark, Button, CODE_HIGHLIGHT_EXTENSIONS, Checkbox, CodeBlock, ConnectionIndicator, DEFAULT_DIFF_MAX_LINES, DEFAULT_READ_MAX_LINES, DEFAULT_SEARCH_MAX_LINES, DEFAULT_TERMINAL_MAX_LINES, DiffBlock, DisclosureRow, FISH_LOGO_PATH, FISH_LOGO_VIEWBOX, FileTypeIcon, FishLogo, GuideArtworkBrowser, GuideArtworkFiles, HoverCard, ICON_MEDIUM_STROKE, ICON_REGULAR_STROKE, IconAgentPresetOutlineMedium, IconAgentPresetOutlineRegular, IconAlarmClockOutlineMedium, IconAlarmClockOutlineRegular, IconApiOutlineMedium, IconApiOutlineRegular, IconArchiveCheckOutlineMedium, IconArchiveCheckOutlineRegular, IconArchiveOffOutlineMedium, IconArchiveOffOutlineRegular, IconArchiveOutlineMedium, IconArchiveOutlineRegular, IconBranchOutlineMedium, IconBranchOutlineRegular, IconBrowseOutlineMedium, IconBrowseOutlineRegular, IconCheckCircleFillMedium, IconCheckCircleFillRegular, IconCheckCircleOutlineMedium, IconCheckCircleOutlineRegular, IconCheckOutlineMedium, IconCheckOutlineRegular, IconChecklistOutlineMedium, IconChecklistOutlineRegular, IconChevronDownOutlineMedium, IconChevronDownOutlineRegular, IconChevronLeftOutlineMedium, IconChevronLeftOutlineRegular, IconChevronRightOutlineMedium, IconChevronRightOutlineRegular, IconChevronUpOutlineMedium, IconChevronUpOutlineRegular, IconChevronsUpDownOutlineMedium, IconChevronsUpDownOutlineRegular, IconClockOutlineMedium, IconClockOutlineRegular, IconCloseCircleFillMedium, IconCloseCircleFillRegular, IconCloseFillMedium, IconCloseFillRegular, IconCloseOutlineMedium, IconCloseOutlineRegular, IconCodeOutlineMedium, IconCodeOutlineRegular, IconCompactOutlineMedium, IconCompactOutlineRegular, IconCompareSplitOutlineMedium, IconCompareSplitOutlineRegular, IconContextInjectionOutlineMedium, IconContextInjectionOutlineRegular, IconCopyOutlineMedium, IconCopyOutlineRegular, IconCordisPluginOutlineMedium, IconCordisPluginOutlineRegular, IconDarkOutlineMedium, IconDarkOutlineRegular, IconDataOutlineMedium, IconDataOutlineRegular, IconDatabaseOutlineMedium, IconDatabaseOutlineRegular, IconDeliverDocMedium, IconDeliverDocRegular, IconDislikeFillMedium, IconDislikeFillRegular, IconDislikeOutlineMedium, IconDislikeOutlineRegular, IconDownloadOutlineMedium, IconDownloadOutlineRegular, IconEditOutlineMedium, IconEditOutlineRegular, IconEllipsisOutlineMedium, IconEllipsisOutlineRegular, IconEnhanceOutlineMedium, IconEnhanceOutlineRegular, IconFlatListOutlineMedium, IconFlatListOutlineRegular, IconFolderCloseMedium, IconFolderCloseRegular, IconFolderOpenMedium, IconFolderOpenOutlineMedium, IconFolderOpenOutlineRegular, IconFolderOpenRegular, IconFollowsystemOutlineMedium, IconFollowsystemOutlineRegular, IconFullscreenOutlineMedium, IconFullscreenOutlineRegular, IconGaugeOutlineMedium, IconGaugeOutlineRegular, IconGlobeOutlineMedium, IconGlobeOutlineRegular, IconGoalOutlineMedium, IconGoalOutlineRegular, IconInfoOutlineMedium, IconInfoOutlineRegular, IconInspectOutlineMedium, IconInspectOutlineRegular, IconLightOutlineMedium, IconLightOutlineRegular, IconLikeFillMedium, IconLikeFillRegular, IconLikeOutlineMedium, IconLikeOutlineRegular, IconLinkOutlineMedium, IconLinkOutlineRegular, IconListPenOutlineMedium, IconListPenOutlineRegular, IconLoadingOutlineMedium, IconLoadingOutlineRegular, IconMicrophoneOutlineMedium, IconMicrophoneOutlineRegular, IconNewChatOutlineMedium, IconNewChatOutlineRegular, IconNowrapFillMedium, IconNowrapFillRegular, IconPanelLeftOutlineMedium, IconPanelLeftOutlineRegular, IconPaperPlaneOutlineMedium, IconPaperPlaneOutlineRegular, IconPaperclipOutlineMedium, IconPaperclipOutlineRegular, IconPauseOutlineMedium, IconPauseOutlineRegular, IconPersonalizationOutlineMedium, IconPersonalizationOutlineRegular, IconPinFillMedium, IconPinFillRegular, IconPinOutlineMedium, IconPinOutlineRegular, IconPlanOutlineMedium, IconPlanOutlineRegular, IconPlayOutlineMedium, IconPlayOutlineRegular, IconPluginPinwheelOutlineMedium, IconPluginPinwheelOutlineRegular, IconPlusOutlineMedium, IconPlusOutlineRegular, IconProjectAddOutlineMedium, IconProjectAddOutlineRegular, IconQuestionOutlineMedium, IconQuestionOutlineRegular, IconQueueOutlineMedium, IconQueueOutlineRegular, IconRefreshOutlineMedium, IconRefreshOutlineRegular, IconRightUpOutlineMedium, IconRightUpOutlineRegular, IconSearchOutlineMedium, IconSearchOutlineRegular, IconSendOutlineMedium, IconSendOutlineRegular, IconSettingsOutlineMedium, IconSettingsOutlineRegular, IconShareOutlineMedium, IconShareOutlineRegular, IconShieldOutlineMedium, IconShieldOutlineRegular, IconSkillOutlineMedium, IconSkillOutlineRegular, IconSlidersTwoOutlineMedium, IconSlidersTwoOutlineRegular, IconSparkleMedium, IconSparkleRegular, IconStopFillMedium, IconStopFillRegular, IconThinkOutlineMedium, IconThinkOutlineRegular, IconTrashOutlineMedium, IconTrashOutlineRegular, IconTreeCornerMedium, IconTreeCornerRegular, IconTriangleRightFillMedium, IconTriangleRightFillRegular, IconUnarchiveOutlineMedium, IconUnarchiveOutlineRegular, IconUserOutlineMedium, IconUserOutlineRegular, IconUsersOutlineMedium, IconUsersOutlineRegular, IconWarningOutlineMedium, IconWarningOutlineRegular, IconWarningTriangleOutlineMedium, IconWarningTriangleOutlineRegular, IconWorkspaceTreeOutlineMedium, IconWorkspaceTreeOutlineRegular, IconWrapFillMedium, IconWrapFillRegular, IconWrapLinesOutlineMedium, IconWrapLinesOutlineRegular, ImageLightbox, Input, JsonBlock, JsonTree, LinkIconMedium, LinkIconRegular, MarkdownDelegateProvider, MarkdownText, Menu, MenuItemButton, MenuSurface, Modal, PathLabel, PermissionIconFullAccessMedium, PermissionIconFullAccessRegular, PermissionIconReadOnlyMedium, PermissionIconReadOnlyRegular, PermissionIconWorkspaceWriteMedium, PermissionIconWorkspaceWriteRegular, Pill, PluginArtworkDefault, PluginArtworkLoop, PluginArtworkSearch, PluginArtworkSubagent, PluginArtworkTerminal, ReadBlock, ReferenceIconMedium, ReferenceIconRegular, RiskConfirmation, SHIELD_OUTLINE_PATH, SearchBlock, SegmentedControl, SegmentedTabs, SettingsForm, SettingsFormModel, SettingsSecretField, SettingsValueField, ShortcutKeys, StateDot, Switch, Tag, TerminalBlock, TextShimmer, Toast, Tooltip, WebBlock, classifyFileType, classifyLinkPath, closeTopModal, diffTotals, extractMarkdownPlainText, fileExtension, fileSizeText, focusWithoutRing, isBehindModal, isDarwinDesktop, languageForPath, modalSelector, observeComposition, projectUserText, rankByName, relativeTime, settingsNumberField, settingsTextField, useAnchoredMaxHeight, useAnchoredPosition, useCodeHighlighter, useDismissOnOutsidePointer, useModalLayer, writeClipboard };
|
|
11415
12182
|
|
|
11416
12183
|
//# sourceMappingURL=index.js.map
|