components-svelte 0.1.0
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/LICENSE +21 -0
- package/README.md +103 -0
- package/dist/components/Search.svelte +320 -0
- package/dist/components/Search.svelte.d.ts +31 -0
- package/dist/components/SearchButton.svelte +82 -0
- package/dist/components/SearchButton.svelte.d.ts +13 -0
- package/dist/components/SearchProvider.svelte +87 -0
- package/dist/components/SearchProvider.svelte.d.ts +17 -0
- package/dist/components/accordion/Accordion.svelte +150 -0
- package/dist/components/accordion/Accordion.svelte.d.ts +25 -0
- package/dist/components/accordion/AccordionCover.svelte +68 -0
- package/dist/components/accordion/AccordionCover.svelte.d.ts +13 -0
- package/dist/components/accordion/AccordionGroup.svelte +23 -0
- package/dist/components/accordion/AccordionGroup.svelte.d.ts +8 -0
- package/dist/components/accordion/accordion-url-utils.d.ts +4 -0
- package/dist/components/accordion/accordion-url-utils.js +48 -0
- package/dist/components/accordion/index.d.ts +29 -0
- package/dist/components/accordion/index.js +6 -0
- package/dist/components/badge/Badge.svelte +152 -0
- package/dist/components/badge/Badge.svelte.d.ts +23 -0
- package/dist/components/badge/index.d.ts +1 -0
- package/dist/components/badge/index.js +2 -0
- package/dist/components/callout/Callout.svelte +317 -0
- package/dist/components/callout/Callout.svelte.d.ts +17 -0
- package/dist/components/callout/Check.svelte +9 -0
- package/dist/components/callout/Check.svelte.d.ts +4 -0
- package/dist/components/callout/Danger.svelte +9 -0
- package/dist/components/callout/Danger.svelte.d.ts +4 -0
- package/dist/components/callout/Info.svelte +9 -0
- package/dist/components/callout/Info.svelte.d.ts +4 -0
- package/dist/components/callout/Note.svelte +9 -0
- package/dist/components/callout/Note.svelte.d.ts +4 -0
- package/dist/components/callout/Tip.svelte +9 -0
- package/dist/components/callout/Tip.svelte.d.ts +4 -0
- package/dist/components/callout/Warning.svelte +9 -0
- package/dist/components/callout/Warning.svelte.d.ts +4 -0
- package/dist/components/callout/index.d.ts +8 -0
- package/dist/components/callout/index.js +8 -0
- package/dist/components/card/Card.svelte +172 -0
- package/dist/components/card/Card.svelte.d.ts +21 -0
- package/dist/components/card/index.d.ts +3 -0
- package/dist/components/card/index.js +2 -0
- package/dist/components/code-block/BaseCodeBlock.svelte +249 -0
- package/dist/components/code-block/BaseCodeBlock.svelte.d.ts +10 -0
- package/dist/components/code-block/CodeBlock.svelte +185 -0
- package/dist/components/code-block/CodeBlock.svelte.d.ts +5 -0
- package/dist/components/code-block/CodeFooter.svelte +34 -0
- package/dist/components/code-block/CodeFooter.svelte.d.ts +8 -0
- package/dist/components/code-block/CodeHeader.svelte +52 -0
- package/dist/components/code-block/CodeHeader.svelte.d.ts +11 -0
- package/dist/components/code-block/CopyToClipboardButton.svelte +124 -0
- package/dist/components/code-block/CopyToClipboardButton.svelte.d.ts +4 -0
- package/dist/components/code-block/index.d.ts +10 -0
- package/dist/components/code-block/index.js +5 -0
- package/dist/components/code-block/types.d.ts +85 -0
- package/dist/components/code-block/types.js +1 -0
- package/dist/components/code-group/CodeGroup.svelte +327 -0
- package/dist/components/code-group/CodeGroup.svelte.d.ts +24 -0
- package/dist/components/code-group/CodeGroupSelect.svelte +170 -0
- package/dist/components/code-group/CodeGroupSelect.svelte.d.ts +25 -0
- package/dist/components/code-group/CodeSelectDropdown.svelte +74 -0
- package/dist/components/code-group/CodeSelectDropdown.svelte.d.ts +9 -0
- package/dist/components/code-group/LanguageDropdown.svelte +134 -0
- package/dist/components/code-group/LanguageDropdown.svelte.d.ts +11 -0
- package/dist/components/code-group/LanguageIcon.svelte +24 -0
- package/dist/components/code-group/LanguageIcon.svelte.d.ts +8 -0
- package/dist/components/code-group/context.d.ts +14 -0
- package/dist/components/code-group/context.js +2 -0
- package/dist/components/code-group/index.d.ts +8 -0
- package/dist/components/code-group/index.js +4 -0
- package/dist/components/color/Color.svelte +34 -0
- package/dist/components/color/Color.svelte.d.ts +10 -0
- package/dist/components/color/ColorItem.svelte +140 -0
- package/dist/components/color/ColorItem.svelte.d.ts +10 -0
- package/dist/components/color/ColorRow.svelte +27 -0
- package/dist/components/color/ColorRow.svelte.d.ts +8 -0
- package/dist/components/color/index.d.ts +1 -0
- package/dist/components/color/index.js +8 -0
- package/dist/components/columns/Box.svelte +15 -0
- package/dist/components/columns/Box.svelte.d.ts +7 -0
- package/dist/components/columns/Columns.svelte +31 -0
- package/dist/components/columns/Columns.svelte.d.ts +10 -0
- package/dist/components/columns/constants.d.ts +5 -0
- package/dist/components/columns/constants.js +3 -0
- package/dist/components/columns/index.d.ts +5 -0
- package/dist/components/columns/index.js +3 -0
- package/dist/components/expandable/Expandable.svelte +182 -0
- package/dist/components/expandable/Expandable.svelte.d.ts +22 -0
- package/dist/components/expandable/index.d.ts +3 -0
- package/dist/components/expandable/index.js +2 -0
- package/dist/components/frame/Frame.svelte +118 -0
- package/dist/components/frame/Frame.svelte.d.ts +15 -0
- package/dist/components/frame/index.d.ts +3 -0
- package/dist/components/frame/index.js +2 -0
- package/dist/components/icon/Icon.svelte +129 -0
- package/dist/components/icon/Icon.svelte.d.ts +18 -0
- package/dist/components/icon/index.d.ts +2 -0
- package/dist/components/icon/index.js +1 -0
- package/dist/components/index.d.ts +22 -0
- package/dist/components/index.js +22 -0
- package/dist/components/mermaid/Mermaid.svelte +181 -0
- package/dist/components/mermaid/Mermaid.svelte.d.ts +11 -0
- package/dist/components/mermaid/ZoomControls.svelte +74 -0
- package/dist/components/mermaid/ZoomControls.svelte.d.ts +12 -0
- package/dist/components/mermaid/index.d.ts +7 -0
- package/dist/components/mermaid/index.js +4 -0
- package/dist/components/mermaid/use-pan-zoom.svelte.d.ts +11 -0
- package/dist/components/mermaid/use-pan-zoom.svelte.js +41 -0
- package/dist/components/panel/Panel.svelte +27 -0
- package/dist/components/panel/Panel.svelte.d.ts +9 -0
- package/dist/components/panel/index.d.ts +3 -0
- package/dist/components/panel/index.js +2 -0
- package/dist/components/property/DeprecatedPill.svelte +16 -0
- package/dist/components/property/DeprecatedPill.svelte.d.ts +6 -0
- package/dist/components/property/InfoPill.svelte +32 -0
- package/dist/components/property/InfoPill.svelte.d.ts +10 -0
- package/dist/components/property/ParamHead.svelte +188 -0
- package/dist/components/property/ParamHead.svelte.d.ts +22 -0
- package/dist/components/property/Property.svelte +123 -0
- package/dist/components/property/Property.svelte.d.ts +24 -0
- package/dist/components/property/RequiredPill.svelte +16 -0
- package/dist/components/property/RequiredPill.svelte.d.ts +6 -0
- package/dist/components/property/index.d.ts +11 -0
- package/dist/components/property/index.js +6 -0
- package/dist/components/search/index.d.ts +7 -0
- package/dist/components/search/index.js +4 -0
- package/dist/components/search/use-search.d.ts +9 -0
- package/dist/components/search/use-search.js +6 -0
- package/dist/components/steps/Step.svelte +314 -0
- package/dist/components/steps/Step.svelte.d.ts +26 -0
- package/dist/components/steps/Steps.svelte +51 -0
- package/dist/components/steps/Steps.svelte.d.ts +11 -0
- package/dist/components/steps/constants.d.ts +4 -0
- package/dist/components/steps/constants.js +2 -0
- package/dist/components/steps/context.d.ts +10 -0
- package/dist/components/steps/context.js +2 -0
- package/dist/components/steps/index.d.ts +32 -0
- package/dist/components/steps/index.js +6 -0
- package/dist/components/tabs/Tabs.svelte +254 -0
- package/dist/components/tabs/Tabs.svelte.d.ts +16 -0
- package/dist/components/tabs/TabsItem.svelte +56 -0
- package/dist/components/tabs/TabsItem.svelte.d.ts +15 -0
- package/dist/components/tabs/context.d.ts +20 -0
- package/dist/components/tabs/context.js +2 -0
- package/dist/components/tabs/index.d.ts +27 -0
- package/dist/components/tabs/index.js +5 -0
- package/dist/components/tile/Tile.svelte +124 -0
- package/dist/components/tile/Tile.svelte.d.ts +12 -0
- package/dist/components/tile/index.d.ts +2 -0
- package/dist/components/tile/index.js +1 -0
- package/dist/components/tooltip/Tooltip.svelte +170 -0
- package/dist/components/tooltip/Tooltip.svelte.d.ts +23 -0
- package/dist/components/tooltip/index.d.ts +2 -0
- package/dist/components/tooltip/index.js +1 -0
- package/dist/components/tree/Tree.svelte +226 -0
- package/dist/components/tree/Tree.svelte.d.ts +9 -0
- package/dist/components/tree/TreeFile.svelte +44 -0
- package/dist/components/tree/TreeFile.svelte.d.ts +6 -0
- package/dist/components/tree/TreeFolder.svelte +107 -0
- package/dist/components/tree/TreeFolder.svelte.d.ts +10 -0
- package/dist/components/tree/context.d.ts +3 -0
- package/dist/components/tree/context.js +7 -0
- package/dist/components/tree/index.d.ts +10 -0
- package/dist/components/tree/index.js +9 -0
- package/dist/components/tree/tree-level-context.d.ts +8 -0
- package/dist/components/tree/tree-level-context.js +7 -0
- package/dist/components/tree/use-tree-level.d.ts +3 -0
- package/dist/components/tree/use-tree-level.js +5 -0
- package/dist/components/tree/utils.d.ts +9 -0
- package/dist/components/tree/utils.js +86 -0
- package/dist/components/update/Update.svelte +210 -0
- package/dist/components/update/Update.svelte.d.ts +34 -0
- package/dist/components/update/index.d.ts +4 -0
- package/dist/components/update/index.js +3 -0
- package/dist/components/view/View.svelte +52 -0
- package/dist/components/view/View.svelte.d.ts +14 -0
- package/dist/components/view/index.d.ts +3 -0
- package/dist/components/view/index.js +2 -0
- package/dist/constants/brands.d.ts +2 -0
- package/dist/constants/brands.js +4 -0
- package/dist/constants/index.d.ts +6 -0
- package/dist/constants/index.js +6 -0
- package/dist/constants/selectors.d.ts +125 -0
- package/dist/constants/selectors.js +125 -0
- package/dist/hooks/index.d.ts +8 -0
- package/dist/hooks/index.js +6 -0
- package/dist/hooks/use-expandable-memory.svelte.d.ts +6 -0
- package/dist/hooks/use-expandable-memory.svelte.js +89 -0
- package/dist/hooks/use-expandable.svelte.d.ts +15 -0
- package/dist/hooks/use-expandable.svelte.js +53 -0
- package/dist/hooks/use-get-shiki-highlighted-html.svelte.d.ts +8 -0
- package/dist/hooks/use-get-shiki-highlighted-html.svelte.js +36 -0
- package/dist/hooks/use-has-hover.d.ts +2 -0
- package/dist/hooks/use-has-hover.js +10 -0
- package/dist/hooks/use-is-dark-theme.svelte.d.ts +3 -0
- package/dist/hooks/use-is-dark-theme.svelte.js +25 -0
- package/dist/hooks/use-isomorphic-layout-effect.d.ts +3 -0
- package/dist/hooks/use-isomorphic-layout-effect.js +6 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/styles.css +2 -0
- package/dist/utils/cn.d.ts +3 -0
- package/dist/utils/cn.js +7 -0
- package/dist/utils/copy-to-clipboard.d.ts +4 -0
- package/dist/utils/copy-to-clipboard.js +50 -0
- package/dist/utils/dedent.d.ts +1 -0
- package/dist/utils/dedent.js +125 -0
- package/dist/utils/enhance-video-props.d.ts +4 -0
- package/dist/utils/enhance-video-props.js +25 -0
- package/dist/utils/get-node-text.d.ts +2 -0
- package/dist/utils/get-node-text.js +26 -0
- package/dist/utils/icon-utils.d.ts +18 -0
- package/dist/utils/icon-utils.js +30 -0
- package/dist/utils/is-absolute-url.d.ts +4 -0
- package/dist/utils/is-absolute-url.js +11 -0
- package/dist/utils/is-remote-url.d.ts +2 -0
- package/dist/utils/is-remote-url.js +12 -0
- package/dist/utils/make-marker-ids-unique.d.ts +2 -0
- package/dist/utils/make-marker-ids-unique.js +36 -0
- package/dist/utils/shiki/code-styling.d.ts +13 -0
- package/dist/utils/shiki/code-styling.js +1 -0
- package/dist/utils/shiki/constants.d.ts +21 -0
- package/dist/utils/shiki/constants.js +116 -0
- package/dist/utils/shiki/get-code-styling.d.ts +9 -0
- package/dist/utils/shiki/get-code-styling.js +38 -0
- package/dist/utils/shiki/get-shiki-background-colors.d.ts +20 -0
- package/dist/utils/shiki/get-shiki-background-colors.js +56 -0
- package/dist/utils/shiki/index.d.ts +30 -0
- package/dist/utils/shiki/index.js +209 -0
- package/dist/utils/shiki/lib.d.ts +4 -0
- package/dist/utils/shiki/lib.js +49 -0
- package/dist/utils/shiki/shiki-themes.d.ts +2 -0
- package/dist/utils/shiki/shiki-themes.js +64 -0
- package/dist/utils/shiki/snippet-presets.d.ts +27 -0
- package/dist/utils/shiki/snippet-presets.js +44 -0
- package/dist/utils/shiki/worker-client.d.ts +9 -0
- package/dist/utils/shiki/worker-client.js +22 -0
- package/dist/utils/shiki/worker.d.ts +1 -0
- package/dist/utils/shiki/worker.js +134 -0
- package/dist/utils/slugify.d.ts +2 -0
- package/dist/utils/slugify.js +9 -0
- package/package.json +100 -0
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import CodeFooter from "./CodeFooter.svelte";
|
|
3
|
+
import type { CodeBlockProps } from "./types";
|
|
4
|
+
import { cn } from "../../utils/cn";
|
|
5
|
+
import {
|
|
6
|
+
getShikiHighlightedHtml,
|
|
7
|
+
type ShikiHighlightedHtmlArgs,
|
|
8
|
+
} from "../../utils/shiki";
|
|
9
|
+
import { useCalculateCodeLines } from "../../utils/shiki/lib";
|
|
10
|
+
import { getShikiBackgroundColors } from "../../utils/shiki/get-shiki-background-colors";
|
|
11
|
+
|
|
12
|
+
export type BaseCodeBlockProps = CodeBlockProps & {
|
|
13
|
+
isParentCodeGroup?: boolean;
|
|
14
|
+
shouldHighlight?: boolean;
|
|
15
|
+
forceExtract?: boolean;
|
|
16
|
+
codeString?: string;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const SMALL_EXPANDABLE_NUMBER_OF_LINES = 7;
|
|
20
|
+
const SMALL_EXPANDABLE_HEIGHT_OFFSET = 30;
|
|
21
|
+
const EXPANDED_HEIGHT_OFFSET = 40;
|
|
22
|
+
const SMALL_EXPANDABLE_CODE_BLOCK_HEIGHT = 45;
|
|
23
|
+
const DEFAULT_EXPANDABLE_CODE_BLOCK_HEIGHT = 190;
|
|
24
|
+
|
|
25
|
+
let {
|
|
26
|
+
expandable = false,
|
|
27
|
+
shouldHighlight = true,
|
|
28
|
+
children,
|
|
29
|
+
filename,
|
|
30
|
+
isParentCodeGroup,
|
|
31
|
+
isSmallText,
|
|
32
|
+
numberOfLines,
|
|
33
|
+
codeBlockTheme = "system",
|
|
34
|
+
codeBlockThemeObject = "system",
|
|
35
|
+
codeString = "",
|
|
36
|
+
class: className,
|
|
37
|
+
focus,
|
|
38
|
+
highlight,
|
|
39
|
+
language,
|
|
40
|
+
lang,
|
|
41
|
+
wrap,
|
|
42
|
+
lines,
|
|
43
|
+
}: BaseCodeBlockProps = $props();
|
|
44
|
+
|
|
45
|
+
function parseLineNumbers(value: string | undefined): number[] {
|
|
46
|
+
if (!value) {
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
const parsed = JSON.parse(value);
|
|
52
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
53
|
+
} catch {
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
let focusLines = $derived(parseLineNumbers(focus));
|
|
59
|
+
let highlightLines = $derived(parseLineNumbers(highlight));
|
|
60
|
+
let opts = $derived.by(() => {
|
|
61
|
+
const options: {
|
|
62
|
+
highlightedLines?: number[];
|
|
63
|
+
focusedLines?: number[];
|
|
64
|
+
} = {};
|
|
65
|
+
|
|
66
|
+
if (highlightLines.length > 0) {
|
|
67
|
+
options.highlightedLines = highlightLines;
|
|
68
|
+
}
|
|
69
|
+
if (focusLines.length > 0) {
|
|
70
|
+
options.focusedLines = focusLines;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return options;
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
let selectedLang = $derived(lang || language);
|
|
77
|
+
let html = $state<string | undefined>();
|
|
78
|
+
// Keep the request counter non-reactive. It guards stale async results but
|
|
79
|
+
// must not become a dependency of the highlighting effect that increments it.
|
|
80
|
+
let highlightRequest = 0;
|
|
81
|
+
|
|
82
|
+
$effect(() => {
|
|
83
|
+
const request: string | undefined | Promise<string | undefined> =
|
|
84
|
+
selectedLang
|
|
85
|
+
? getShikiHighlightedHtml({
|
|
86
|
+
codeString,
|
|
87
|
+
codeBlockTheme: codeBlockThemeObject,
|
|
88
|
+
language: shouldHighlight ? selectedLang : "text",
|
|
89
|
+
opts,
|
|
90
|
+
} satisfies ShikiHighlightedHtmlArgs)
|
|
91
|
+
: getShikiHighlightedHtml({
|
|
92
|
+
codeString,
|
|
93
|
+
codeBlockTheme: codeBlockThemeObject,
|
|
94
|
+
className: shouldHighlight ? className : "lang-text",
|
|
95
|
+
opts,
|
|
96
|
+
} satisfies ShikiHighlightedHtmlArgs);
|
|
97
|
+
|
|
98
|
+
const requestId = highlightRequest + 1;
|
|
99
|
+
highlightRequest = requestId;
|
|
100
|
+
|
|
101
|
+
if (request instanceof Promise) {
|
|
102
|
+
html = undefined;
|
|
103
|
+
void request.then((result) => {
|
|
104
|
+
if (requestId === highlightRequest) {
|
|
105
|
+
html = result;
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
} else {
|
|
109
|
+
html = request;
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
let resolvedNumberOfLines = $derived(
|
|
114
|
+
useCalculateCodeLines(html, numberOfLines)
|
|
115
|
+
);
|
|
116
|
+
let isExpanded = $state(false);
|
|
117
|
+
let calculatedHeight = $state(0);
|
|
118
|
+
let contentRef = $state<HTMLDivElement>();
|
|
119
|
+
|
|
120
|
+
$effect(() => {
|
|
121
|
+
const currentContentRef = contentRef;
|
|
122
|
+
if (!currentContentRef || !expandable) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const rafId = requestAnimationFrame(() => {
|
|
127
|
+
if (contentRef === currentContentRef) {
|
|
128
|
+
calculatedHeight =
|
|
129
|
+
currentContentRef.scrollHeight +
|
|
130
|
+
(resolvedNumberOfLines &&
|
|
131
|
+
resolvedNumberOfLines < SMALL_EXPANDABLE_NUMBER_OF_LINES
|
|
132
|
+
? SMALL_EXPANDABLE_HEIGHT_OFFSET
|
|
133
|
+
: EXPANDED_HEIGHT_OFFSET);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
return () => cancelAnimationFrame(rafId);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
function toggleExpanded() {
|
|
141
|
+
isExpanded = !isExpanded;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
let height = $derived.by(() => {
|
|
145
|
+
if (expandable) {
|
|
146
|
+
if (isExpanded) {
|
|
147
|
+
return calculatedHeight + "px";
|
|
148
|
+
}
|
|
149
|
+
if (
|
|
150
|
+
resolvedNumberOfLines &&
|
|
151
|
+
resolvedNumberOfLines < SMALL_EXPANDABLE_NUMBER_OF_LINES
|
|
152
|
+
) {
|
|
153
|
+
return SMALL_EXPANDABLE_CODE_BLOCK_HEIGHT + "px";
|
|
154
|
+
}
|
|
155
|
+
return DEFAULT_EXPANDABLE_CODE_BLOCK_HEIGHT + "px";
|
|
156
|
+
}
|
|
157
|
+
if (isParentCodeGroup) {
|
|
158
|
+
return "100%";
|
|
159
|
+
}
|
|
160
|
+
return "auto";
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
let isFocusEnabled = $derived(focusLines.length > 0);
|
|
164
|
+
let isHighlightEnabled = $derived(highlightLines.length > 0);
|
|
165
|
+
let shikiBackgroundColors = $derived(
|
|
166
|
+
getShikiBackgroundColors(codeBlockTheme, html, codeString)
|
|
167
|
+
);
|
|
168
|
+
let showFadeOverlay = $derived(
|
|
169
|
+
!(wrap || isHighlightEnabled || expandable) && focusLines.length === 0
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
function styleToString(
|
|
173
|
+
styles: Record<string, string | number | undefined>
|
|
174
|
+
): string {
|
|
175
|
+
return Object.entries(styles)
|
|
176
|
+
.filter(([, value]) => value !== undefined)
|
|
177
|
+
.map(([key, value]) => key + ":" + value)
|
|
178
|
+
.join(";");
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
let rootStyle = $derived(
|
|
182
|
+
styleToString({
|
|
183
|
+
"font-variant-ligatures": "none",
|
|
184
|
+
height,
|
|
185
|
+
"background-color": shikiBackgroundColors?.light,
|
|
186
|
+
"--shiki-dark-bg": shikiBackgroundColors?.dark,
|
|
187
|
+
})
|
|
188
|
+
);
|
|
189
|
+
let fadeStyle = $derived(
|
|
190
|
+
styleToString({
|
|
191
|
+
"--fade-color-light": shikiBackgroundColors?.light,
|
|
192
|
+
"--fade-color-dark": shikiBackgroundColors?.dark,
|
|
193
|
+
})
|
|
194
|
+
);
|
|
195
|
+
</script>
|
|
196
|
+
|
|
197
|
+
<!-- svelte-ignore a11y_no_noninteractive_tabindex: scrollable code blocks must be keyboard-focusable -->
|
|
198
|
+
<div
|
|
199
|
+
class={cn(
|
|
200
|
+
"children:!my-0 children:!shadow-none children:!bg-transparent relative h-full w-0 min-w-full max-w-full rounded-[14px] px-4 py-3.5 text-sm leading-6 dark:bg-codeblock",
|
|
201
|
+
"code-block-background overflow-x-auto transition-[height] duration-300 ease-in-out",
|
|
202
|
+
"**:outline-0 **:ring-0 **:focus:outline-0 **:focus:ring-0",
|
|
203
|
+
filename ? "rounded-[14px]" : "rounded-2xl",
|
|
204
|
+
codeBlockTheme === "system" ? "bg-white" : "bg-codeblock",
|
|
205
|
+
(expandable || isParentCodeGroup) && "overflow-auto",
|
|
206
|
+
expandable && (isExpanded ? "overflow-y-auto" : "overflow-y-hidden"),
|
|
207
|
+
wrap
|
|
208
|
+
? "code-block-wrap overflow-x-hidden whitespace-pre-wrap"
|
|
209
|
+
: "overflow-x-auto",
|
|
210
|
+
lines && "has-line-numbers",
|
|
211
|
+
isFocusEnabled && "has-focused",
|
|
212
|
+
isHighlightEnabled && "has-highlighted",
|
|
213
|
+
codeBlockTheme === "system"
|
|
214
|
+
? "scrollbar-code-system"
|
|
215
|
+
: "scrollbar-code-dark"
|
|
216
|
+
)}
|
|
217
|
+
data-component-part="code-block-root"
|
|
218
|
+
style={rootStyle}
|
|
219
|
+
tabindex={0}
|
|
220
|
+
>
|
|
221
|
+
<div
|
|
222
|
+
class={cn(
|
|
223
|
+
"font-mono",
|
|
224
|
+
wrap ? "whitespace-pre-wrap" : "whitespace-pre",
|
|
225
|
+
isParentCodeGroup && "h-full flex-none text-sm",
|
|
226
|
+
isSmallText ? "text-xs leading-[1.35rem]" : "leading-6"
|
|
227
|
+
)}
|
|
228
|
+
bind:this={contentRef}
|
|
229
|
+
data-component-part={isParentCodeGroup ? "code-group-tab-content" : undefined}
|
|
230
|
+
>
|
|
231
|
+
{#if html}
|
|
232
|
+
{@html html}
|
|
233
|
+
{:else if children}
|
|
234
|
+
{@render children()}
|
|
235
|
+
{/if}
|
|
236
|
+
</div>
|
|
237
|
+
</div>
|
|
238
|
+
|
|
239
|
+
{#if showFadeOverlay}
|
|
240
|
+
<div aria-hidden="true" data-fade-overlay style={fadeStyle}></div>
|
|
241
|
+
{/if}
|
|
242
|
+
|
|
243
|
+
{#if expandable}
|
|
244
|
+
<CodeFooter
|
|
245
|
+
isExpanded={isExpanded}
|
|
246
|
+
numberOfLines={resolvedNumberOfLines}
|
|
247
|
+
toggleExpanded={toggleExpanded}
|
|
248
|
+
/>
|
|
249
|
+
{/if}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { CodeBlockProps } from "./types";
|
|
2
|
+
export type BaseCodeBlockProps = CodeBlockProps & {
|
|
3
|
+
isParentCodeGroup?: boolean;
|
|
4
|
+
shouldHighlight?: boolean;
|
|
5
|
+
forceExtract?: boolean;
|
|
6
|
+
codeString?: string;
|
|
7
|
+
};
|
|
8
|
+
declare const BaseCodeBlock: import("svelte").Component<BaseCodeBlockProps, {}, "">;
|
|
9
|
+
type BaseCodeBlock = ReturnType<typeof BaseCodeBlock>;
|
|
10
|
+
export default BaseCodeBlock;
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Classes } from "../../constants/selectors";
|
|
3
|
+
import { cn } from "../../utils/cn";
|
|
4
|
+
import { CODE_GROUP_CONTEXT, type CodeGroupContext } from "../code-group/context";
|
|
5
|
+
import { getContext, untrack } from "svelte";
|
|
6
|
+
import { getCodeString } from "../../utils/shiki/lib";
|
|
7
|
+
import BaseCodeBlock from "./BaseCodeBlock.svelte";
|
|
8
|
+
import CodeHeader from "./CodeHeader.svelte";
|
|
9
|
+
import CopyToClipboardButton from "./CopyToClipboardButton.svelte";
|
|
10
|
+
import type {
|
|
11
|
+
CodeBlockProps as CodeBlockPropsFromTypes,
|
|
12
|
+
CopyToClipboardButtonProps,
|
|
13
|
+
} from "./types";
|
|
14
|
+
|
|
15
|
+
export type CodeBlockProps = CodeBlockPropsFromTypes;
|
|
16
|
+
|
|
17
|
+
let {
|
|
18
|
+
filename,
|
|
19
|
+
children,
|
|
20
|
+
class: className,
|
|
21
|
+
icon,
|
|
22
|
+
lang,
|
|
23
|
+
language,
|
|
24
|
+
wrap,
|
|
25
|
+
lines,
|
|
26
|
+
expandable,
|
|
27
|
+
highlight,
|
|
28
|
+
focus,
|
|
29
|
+
numberOfLines,
|
|
30
|
+
hideAskAiButton,
|
|
31
|
+
isSmallText,
|
|
32
|
+
feedbackModalOpen,
|
|
33
|
+
anchorRef,
|
|
34
|
+
codeBlockTheme = "system",
|
|
35
|
+
codeBlockThemeObject = "system",
|
|
36
|
+
askAiButton,
|
|
37
|
+
feedbackButton,
|
|
38
|
+
copyButtonProps,
|
|
39
|
+
}: CodeBlockProps = $props();
|
|
40
|
+
|
|
41
|
+
let codeSourceRef = $state<HTMLDivElement>();
|
|
42
|
+
let extractedCode = $state("");
|
|
43
|
+
let rootRef = $state<HTMLDivElement>();
|
|
44
|
+
const codeGroupContext = getContext<CodeGroupContext | undefined>(CODE_GROUP_CONTEXT);
|
|
45
|
+
const codeGroupChildId = Symbol("code-group-child");
|
|
46
|
+
|
|
47
|
+
$effect(() => {
|
|
48
|
+
if (!codeSourceRef) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const nextCode = codeSourceRef.textContent ?? "";
|
|
53
|
+
if (nextCode !== extractedCode) {
|
|
54
|
+
extractedCode = nextCode;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
let codeString = $derived(getCodeString(extractedCode, className, true));
|
|
59
|
+
let hasGrayBackgroundContainer = $derived(!!filename || !!icon);
|
|
60
|
+
|
|
61
|
+
// Register the CodeBlock with a parent CodeGroup — replaces React child inspection.
|
|
62
|
+
$effect(() => {
|
|
63
|
+
if (!codeGroupContext) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const child = {
|
|
68
|
+
id: codeGroupChildId,
|
|
69
|
+
filename,
|
|
70
|
+
icon,
|
|
71
|
+
lang,
|
|
72
|
+
class: className,
|
|
73
|
+
language,
|
|
74
|
+
wrap,
|
|
75
|
+
lines,
|
|
76
|
+
expandable,
|
|
77
|
+
highlight,
|
|
78
|
+
focus,
|
|
79
|
+
numberOfLines,
|
|
80
|
+
isSmallText,
|
|
81
|
+
feedbackModalOpen,
|
|
82
|
+
anchorRef,
|
|
83
|
+
codeBlockTheme,
|
|
84
|
+
codeBlockThemeObject,
|
|
85
|
+
askAiButton,
|
|
86
|
+
feedbackButton,
|
|
87
|
+
copyButtonProps,
|
|
88
|
+
children,
|
|
89
|
+
codeString,
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// Keep the child subscribed to its own props without subscribing it to the
|
|
93
|
+
// parent's reactive child array while registration mutates that array.
|
|
94
|
+
untrack(() => codeGroupContext.register(child));
|
|
95
|
+
|
|
96
|
+
return () => untrack(() => codeGroupContext.unregister(codeGroupChildId));
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
$effect(() => {
|
|
100
|
+
if (anchorRef && rootRef) {
|
|
101
|
+
anchorRef.current = rootRef;
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
</script>
|
|
105
|
+
|
|
106
|
+
<div
|
|
107
|
+
aria-hidden="true"
|
|
108
|
+
class="hidden"
|
|
109
|
+
bind:this={codeSourceRef}
|
|
110
|
+
>
|
|
111
|
+
{#if children}{@render children()}{/if}
|
|
112
|
+
</div>
|
|
113
|
+
|
|
114
|
+
{#if !codeGroupContext}
|
|
115
|
+
<div
|
|
116
|
+
bind:this={rootRef}
|
|
117
|
+
class={cn(
|
|
118
|
+
Classes.CodeBlock,
|
|
119
|
+
"not-prose group relative mt-5 mb-8 rounded-2xl",
|
|
120
|
+
codeBlockTheme === "system" &&
|
|
121
|
+
"codeblock-light dark:twoslash-dark border border-stone-950/10 bg-stone-50 text-stone-950 dark:border-white/10 dark:bg-white/5 dark:text-stone-50",
|
|
122
|
+
codeBlockTheme === "dark" &&
|
|
123
|
+
"codeblock-dark twoslash-dark dark:twoslash-dark bg-codeblock text-stone-50 ring-1 ring-transparent dark:bg-white/5 dark:ring-white/[0.14]",
|
|
124
|
+
hasGrayBackgroundContainer
|
|
125
|
+
? "p-0.5"
|
|
126
|
+
: "bg-transparent dark:bg-transparent",
|
|
127
|
+
feedbackModalOpen && "border border-primary dark:border-primary-light",
|
|
128
|
+
className
|
|
129
|
+
)}
|
|
130
|
+
{...(hasGrayBackgroundContainer
|
|
131
|
+
? { "data-has-header": "" }
|
|
132
|
+
: { "data-has-floating-buttons": "" })}
|
|
133
|
+
>
|
|
134
|
+
{#if hasGrayBackgroundContainer}
|
|
135
|
+
<CodeHeader
|
|
136
|
+
codeBlockTheme={codeBlockTheme}
|
|
137
|
+
filename={filename}
|
|
138
|
+
icon={icon}
|
|
139
|
+
>
|
|
140
|
+
{#snippet children()}
|
|
141
|
+
{#if feedbackButton}{@render feedbackButton()}{/if}
|
|
142
|
+
<CopyToClipboardButton
|
|
143
|
+
codeBlockTheme={codeBlockTheme}
|
|
144
|
+
textToCopy={codeString}
|
|
145
|
+
{...(copyButtonProps as Omit<CopyToClipboardButtonProps, "textToCopy">)}
|
|
146
|
+
/>
|
|
147
|
+
{#if askAiButton}{@render askAiButton()}{/if}
|
|
148
|
+
{/snippet}
|
|
149
|
+
</CodeHeader>
|
|
150
|
+
{:else}
|
|
151
|
+
<div
|
|
152
|
+
class="absolute top-3 right-4 flex items-center gap-1.5"
|
|
153
|
+
data-floating-buttons
|
|
154
|
+
>
|
|
155
|
+
{#if feedbackButton}{@render feedbackButton()}{/if}
|
|
156
|
+
<CopyToClipboardButton
|
|
157
|
+
codeBlockTheme={codeBlockTheme}
|
|
158
|
+
textToCopy={codeString}
|
|
159
|
+
{...(copyButtonProps as Omit<CopyToClipboardButtonProps, "textToCopy">)}
|
|
160
|
+
/>
|
|
161
|
+
{#if askAiButton}{@render askAiButton()}{/if}
|
|
162
|
+
</div>
|
|
163
|
+
{/if}
|
|
164
|
+
|
|
165
|
+
<BaseCodeBlock
|
|
166
|
+
class={className}
|
|
167
|
+
codeBlockTheme={codeBlockTheme}
|
|
168
|
+
codeBlockThemeObject={codeBlockThemeObject}
|
|
169
|
+
codeString={codeString}
|
|
170
|
+
expandable={expandable}
|
|
171
|
+
filename={filename}
|
|
172
|
+
focus={focus}
|
|
173
|
+
forceExtract
|
|
174
|
+
highlight={highlight}
|
|
175
|
+
isSmallText={isSmallText}
|
|
176
|
+
lang={lang}
|
|
177
|
+
language={language}
|
|
178
|
+
lines={lines}
|
|
179
|
+
numberOfLines={numberOfLines}
|
|
180
|
+
wrap={wrap}
|
|
181
|
+
>
|
|
182
|
+
{#if children}{@render children()}{/if}
|
|
183
|
+
</BaseCodeBlock>
|
|
184
|
+
</div>
|
|
185
|
+
{/if}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { CodeBlockProps as CodeBlockPropsFromTypes } from "./types";
|
|
2
|
+
export type CodeBlockProps = CodeBlockPropsFromTypes;
|
|
3
|
+
declare const CodeBlock: import("svelte").Component<CodeBlockPropsFromTypes, {}, "">;
|
|
4
|
+
type CodeBlock = ReturnType<typeof CodeBlock>;
|
|
5
|
+
export default CodeBlock;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Ellipsis } from "@lucide/svelte";
|
|
3
|
+
|
|
4
|
+
export type CodeFooterProps = {
|
|
5
|
+
numberOfLines: number | undefined;
|
|
6
|
+
isExpanded: boolean;
|
|
7
|
+
toggleExpanded: () => void;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
let {
|
|
11
|
+
numberOfLines,
|
|
12
|
+
isExpanded,
|
|
13
|
+
toggleExpanded,
|
|
14
|
+
}: CodeFooterProps = $props();
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
{#if numberOfLines}
|
|
18
|
+
<div
|
|
19
|
+
class="flex items-center px-3 py-1 font-medium text-stone-500 text-xs hover:text-stone-600 dark:text-stone-400 dark:hover:text-stone-300"
|
|
20
|
+
data-component-part="code-block-footer"
|
|
21
|
+
>
|
|
22
|
+
<button
|
|
23
|
+
class="flex flex-1 items-center gap-1.5 py-1.5"
|
|
24
|
+
data-component-part="code-block-footer-button"
|
|
25
|
+
onclick={toggleExpanded}
|
|
26
|
+
type="button"
|
|
27
|
+
>
|
|
28
|
+
<Ellipsis class="size-3.5 shrink-0 text-stone-500 dark:text-stone-400" />
|
|
29
|
+
{isExpanded
|
|
30
|
+
? "Collapse"
|
|
31
|
+
: "See all " + numberOfLines + " line" + (numberOfLines === 1 ? "" : "s")}
|
|
32
|
+
</button>
|
|
33
|
+
</div>
|
|
34
|
+
{/if}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type CodeFooterProps = {
|
|
2
|
+
numberOfLines: number | undefined;
|
|
3
|
+
isExpanded: boolean;
|
|
4
|
+
toggleExpanded: () => void;
|
|
5
|
+
};
|
|
6
|
+
declare const CodeFooter: import("svelte").Component<CodeFooterProps, {}, "">;
|
|
7
|
+
type CodeFooter = ReturnType<typeof CodeFooter>;
|
|
8
|
+
export default CodeFooter;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
import Icon from "../icon/Icon.svelte";
|
|
4
|
+
import { Classes } from "../../constants/selectors";
|
|
5
|
+
import { cn } from "../../utils/cn";
|
|
6
|
+
import type { CodeBlockTheme } from "../../utils/shiki/code-styling";
|
|
7
|
+
|
|
8
|
+
export type CodeHeaderProps = {
|
|
9
|
+
filename?: string;
|
|
10
|
+
icon?: string;
|
|
11
|
+
codeBlockTheme?: CodeBlockTheme;
|
|
12
|
+
children?: Snippet;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
let {
|
|
16
|
+
filename,
|
|
17
|
+
icon,
|
|
18
|
+
codeBlockTheme = "system",
|
|
19
|
+
children,
|
|
20
|
+
}: CodeHeaderProps = $props();
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<div
|
|
24
|
+
class="flex rounded-t-[14px] py-1 pr-2.5 pl-4 font-medium text-stone-400 text-xs leading-6"
|
|
25
|
+
data-component-part="code-block-header"
|
|
26
|
+
>
|
|
27
|
+
<div
|
|
28
|
+
class={cn(
|
|
29
|
+
"flex min-w-0 grow-0 items-center gap-1.5 text-stone-700 dark:text-stone-300",
|
|
30
|
+
codeBlockTheme === "dark" && "text-stone-300"
|
|
31
|
+
)}
|
|
32
|
+
data-component-part="code-block-header-filename"
|
|
33
|
+
>
|
|
34
|
+
{#if icon}
|
|
35
|
+
<Icon
|
|
36
|
+
class={cn(
|
|
37
|
+
"size-3.5 shrink-0 bg-stone-500 dark:bg-stone-400",
|
|
38
|
+
Classes.CodeBlockIcon
|
|
39
|
+
)}
|
|
40
|
+
icon={icon}
|
|
41
|
+
iconType="regular"
|
|
42
|
+
overrideColor
|
|
43
|
+
/>
|
|
44
|
+
{/if}
|
|
45
|
+
{#if filename}
|
|
46
|
+
<span class="mr-2 min-w-0 truncate">{filename}</span>
|
|
47
|
+
{/if}
|
|
48
|
+
</div>
|
|
49
|
+
<div class="flex flex-1 items-center justify-end gap-1.5">
|
|
50
|
+
{#if children}{@render children()}{/if}
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
import type { CodeBlockTheme } from "../../utils/shiki/code-styling";
|
|
3
|
+
export type CodeHeaderProps = {
|
|
4
|
+
filename?: string;
|
|
5
|
+
icon?: string;
|
|
6
|
+
codeBlockTheme?: CodeBlockTheme;
|
|
7
|
+
children?: Snippet;
|
|
8
|
+
};
|
|
9
|
+
declare const CodeHeader: import("svelte").Component<CodeHeaderProps, {}, "">;
|
|
10
|
+
type CodeHeader = ReturnType<typeof CodeHeader>;
|
|
11
|
+
export default CodeHeader;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { copyToClipboard } from "../../utils/copy-to-clipboard";
|
|
3
|
+
import type { CopyToClipboardButtonProps } from "./types";
|
|
4
|
+
import { cn } from "../../utils/cn";
|
|
5
|
+
|
|
6
|
+
const DEFAULT_COPY_BUTTON_ARIA_LABEL = "Copy the contents from the code block";
|
|
7
|
+
const DEFAULT_TOOLTIP_COPY_TEXT = "Copy";
|
|
8
|
+
const DEFAULT_TOOLTIP_COPIED_TEXT = "Copied!";
|
|
9
|
+
|
|
10
|
+
let {
|
|
11
|
+
textToCopy,
|
|
12
|
+
onCopied,
|
|
13
|
+
class: className,
|
|
14
|
+
showTooltip = true,
|
|
15
|
+
codeBlockTheme,
|
|
16
|
+
copyButtonAriaLabel = DEFAULT_COPY_BUTTON_ARIA_LABEL,
|
|
17
|
+
tooltipCopyText = DEFAULT_TOOLTIP_COPY_TEXT,
|
|
18
|
+
tooltipCopiedText = DEFAULT_TOOLTIP_COPIED_TEXT,
|
|
19
|
+
...buttonProps
|
|
20
|
+
}: CopyToClipboardButtonProps = $props();
|
|
21
|
+
|
|
22
|
+
let isCopiedActive = $state(false);
|
|
23
|
+
let isDisabled = $state(false);
|
|
24
|
+
let trimmedTextToCopy = $derived(textToCopy.trim());
|
|
25
|
+
|
|
26
|
+
$effect(() => {
|
|
27
|
+
// Hide copy button if the browser does not support it
|
|
28
|
+
const canCopy =
|
|
29
|
+
typeof window === "undefined" ||
|
|
30
|
+
!!navigator.clipboard?.writeText ||
|
|
31
|
+
typeof document.execCommand === "function";
|
|
32
|
+
|
|
33
|
+
if (!canCopy) {
|
|
34
|
+
console.warn(
|
|
35
|
+
"The browser's Clipboard API and copy fallback are unavailable."
|
|
36
|
+
);
|
|
37
|
+
isDisabled = true;
|
|
38
|
+
} else {
|
|
39
|
+
isDisabled = false;
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
async function onCopy() {
|
|
44
|
+
const result = await copyToClipboard(trimmedTextToCopy);
|
|
45
|
+
if (onCopied) {
|
|
46
|
+
onCopied(result, trimmedTextToCopy);
|
|
47
|
+
}
|
|
48
|
+
if (result === "success") {
|
|
49
|
+
isCopiedActive = true;
|
|
50
|
+
setTimeout(() => {
|
|
51
|
+
isCopiedActive = false;
|
|
52
|
+
}, 2000);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
</script>
|
|
56
|
+
|
|
57
|
+
{#if trimmedTextToCopy && !isDisabled}
|
|
58
|
+
<div class={cn("relative z-10 select-none", className)}>
|
|
59
|
+
<button
|
|
60
|
+
{...buttonProps}
|
|
61
|
+
aria-label={copyButtonAriaLabel}
|
|
62
|
+
class="peer group/copy-button flex size-[26px] items-center justify-center rounded-md backdrop-blur"
|
|
63
|
+
data-testid="copy-code-button"
|
|
64
|
+
onclick={onCopy}
|
|
65
|
+
type="button"
|
|
66
|
+
>
|
|
67
|
+
{#if isCopiedActive}
|
|
68
|
+
<svg
|
|
69
|
+
class={cn(
|
|
70
|
+
"size-4",
|
|
71
|
+
codeBlockTheme === "system" && "fill-primary dark:fill-primary-light",
|
|
72
|
+
codeBlockTheme === "dark" && "fill-primary-light"
|
|
73
|
+
)}
|
|
74
|
+
fill="none"
|
|
75
|
+
height="11"
|
|
76
|
+
role="img"
|
|
77
|
+
viewBox="0 0 16 11"
|
|
78
|
+
width="16"
|
|
79
|
+
>
|
|
80
|
+
<title>Copied</title>
|
|
81
|
+
<path d="M14.7813 1.21873C15.0751 1.51248 15.0751 1.98748 14.7813 2.2781L6.53135 10.5312C6.2376 10.825 5.7626 10.825 5.47197 10.5312L1.21885 6.28123C0.925098 5.98748 0.925098 5.51248 1.21885 5.22185C1.5126 4.93123 1.9876 4.9281 2.27822 5.22185L5.99697 8.9406L13.7188 1.21873C14.0126 0.924976 14.4876 0.924976 14.7782 1.21873H14.7813Z" />
|
|
82
|
+
</svg>
|
|
83
|
+
{:else}
|
|
84
|
+
<svg
|
|
85
|
+
class={cn(
|
|
86
|
+
"size-4",
|
|
87
|
+
codeBlockTheme === "system" &&
|
|
88
|
+
"text-stone-400 group-hover/copy-button:text-stone-500 dark:text-white/40 dark:group-hover/copy-button:text-white/60",
|
|
89
|
+
codeBlockTheme === "dark" &&
|
|
90
|
+
"text-white/40 group-hover/copy-button:text-white/60"
|
|
91
|
+
)}
|
|
92
|
+
fill="none"
|
|
93
|
+
height="18"
|
|
94
|
+
viewBox="0 0 18 18"
|
|
95
|
+
width="18"
|
|
96
|
+
>
|
|
97
|
+
<title>Copy</title>
|
|
98
|
+
<path
|
|
99
|
+
d="M14.25 5.25H7.25C6.14543 5.25 5.25 6.14543 5.25 7.25V14.25C5.25 15.3546 6.14543 16.25 7.25 16.25H14.25C15.3546 16.25 16.25 15.3546 16.25 14.25V7.25C16.25 6.14543 15.3546 5.25 14.25 5.25Z"
|
|
100
|
+
stroke="currentColor"
|
|
101
|
+
stroke-linecap="round"
|
|
102
|
+
stroke-linejoin="round"
|
|
103
|
+
stroke-width="1.5"
|
|
104
|
+
/>
|
|
105
|
+
<path
|
|
106
|
+
d="M2.80103 11.998L1.77203 5.07397C1.61003 3.98097 2.36403 2.96397 3.45603 2.80197L10.38 1.77297C11.313 1.63397 12.19 2.16297 12.528 3.00097"
|
|
107
|
+
stroke="currentColor"
|
|
108
|
+
stroke-linecap="round"
|
|
109
|
+
stroke-linejoin="round"
|
|
110
|
+
stroke-width="1.5"
|
|
111
|
+
/>
|
|
112
|
+
</svg>
|
|
113
|
+
{/if}
|
|
114
|
+
</button>
|
|
115
|
+
{#if showTooltip}
|
|
116
|
+
<div
|
|
117
|
+
aria-hidden="true"
|
|
118
|
+
class="absolute top-11 left-1/2 -translate-x-1/2 -translate-y-1/2 transform whitespace-nowrap rounded-lg bg-primary-dark px-1.5 py-0.5 text-tooltip-foreground text-xs opacity-0 peer-hover:opacity-100"
|
|
119
|
+
>
|
|
120
|
+
{isCopiedActive ? tooltipCopiedText : tooltipCopyText}
|
|
121
|
+
</div>
|
|
122
|
+
{/if}
|
|
123
|
+
</div>
|
|
124
|
+
{/if}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { CopyToClipboardButtonProps } from "./types";
|
|
2
|
+
declare const CopyToClipboardButton: import("svelte").Component<CopyToClipboardButtonProps, {}, "">;
|
|
3
|
+
type CopyToClipboardButton = ReturnType<typeof CopyToClipboardButton>;
|
|
4
|
+
export default CopyToClipboardButton;
|