@choice-ui/react 1.6.7 → 1.6.9
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/dist/components/code-block/dist/index.d.ts +11 -14
- package/dist/components/code-block/dist/index.js +120 -93
- package/dist/components/code-block/src/code-block.d.ts +1 -2
- package/dist/components/code-block/src/code-block.js +11 -21
- package/dist/components/code-block/src/components/code-block-code.js +25 -13
- package/dist/components/code-block/src/components/code-block-content.d.ts +1 -1
- package/dist/components/code-block/src/components/code-block-content.js +14 -11
- package/dist/components/code-block/src/components/code-block-footer.js +4 -3
- package/dist/components/code-block/src/components/code-block-header.js +5 -6
- package/dist/components/code-block/src/hooks/index.d.ts +0 -1
- package/dist/components/code-block/src/hooks/use-code-block.js +26 -5
- package/dist/components/code-block/src/hooks/use-scroll-detection.d.ts +1 -2
- package/dist/components/code-block/src/hooks/use-scroll-detection.js +18 -12
- package/dist/components/code-block/src/types.d.ts +3 -5
- package/dist/components/code-block/src/utils/extract-code.js +23 -0
- package/dist/components/command/src/components/command-list.js +15 -3
- package/dist/components/description/dist/index.d.ts +8 -0
- package/dist/components/description/dist/index.js +29 -0
- package/dist/components/description/src/description.d.ts +6 -0
- package/dist/components/description/src/description.js +18 -0
- package/dist/components/description/src/index.d.ts +2 -0
- package/dist/components/description/src/tv.d.ts +13 -0
- package/dist/components/description/src/tv.js +15 -0
- package/dist/components/description/tsup.config.d.ts +2 -0
- package/dist/components/emoji-picker/dist/index.d.ts +1 -0
- package/dist/components/emoji-picker/dist/index.js +4 -2
- package/dist/components/emoji-picker/src/emoji-picker.d.ts +1 -0
- package/dist/components/emoji-picker/src/emoji-picker.js +4 -2
- package/dist/components/error-message/dist/index.d.ts +8 -0
- package/dist/components/error-message/dist/index.js +30 -0
- package/dist/components/error-message/src/error-message.d.ts +6 -0
- package/dist/components/error-message/src/error-message.js +19 -0
- package/dist/components/error-message/src/index.d.ts +2 -0
- package/dist/components/error-message/src/tv.d.ts +13 -0
- package/dist/components/error-message/src/tv.js +15 -0
- package/dist/components/error-message/tsup.config.d.ts +2 -0
- package/dist/components/form/src/adapters/base-adapter.js +4 -2
- package/dist/components/form/src/tv.d.ts +0 -12
- package/dist/components/form/src/tv.js +1 -13
- package/dist/components/index.d.ts +3 -0
- package/dist/components/md-render/dist/index.d.ts +2 -1
- package/dist/components/md-render/dist/index.js +5 -9
- package/dist/components/md-render/src/components/markdown-components.js +1 -7
- package/dist/components/md-render/src/md-render.js +4 -2
- package/dist/components/md-render/src/types.d.ts +2 -1
- package/dist/components/notifications/dist/index.d.ts +1 -5
- package/dist/components/notifications/src/notifications.d.ts +0 -1
- package/dist/components/notifications/src/notifications.js +0 -1
- package/dist/components/numeric-input/dist/index.d.ts +23 -9
- package/dist/components/numeric-input/dist/index.js +26 -3
- package/dist/components/numeric-input/src/components/numeric-input-menu-trigger.js +4 -1
- package/dist/components/numeric-input/src/hooks/index.d.ts +1 -0
- package/dist/components/numeric-input/src/hooks/use-numeric-long-press.d.ts +13 -0
- package/dist/components/numeric-input/src/hooks/use-numeric-long-press.js +27 -0
- package/dist/components/numeric-input/src/index.d.ts +1 -0
- package/dist/components/numeric-input/src/tv.js +22 -2
- package/dist/components/picture-preview/dist/index.d.ts +5 -0
- package/dist/components/picture-preview/dist/index.js +287 -140
- package/dist/components/picture-preview/src/hooks/useWheelHandler.d.ts +6 -1
- package/dist/components/picture-preview/src/hooks/useWheelHandler.js +25 -7
- package/dist/components/picture-preview/src/picture-preview.d.ts +5 -0
- package/dist/components/picture-preview/src/picture-preview.js +214 -123
- package/dist/components/picture-preview/src/tv.d.ts +93 -3
- package/dist/components/picture-preview/src/tv.js +48 -10
- package/dist/components/separator/dist/index.d.ts +1 -8
- package/dist/components/separator/src/separator.d.ts +1 -8
- package/dist/components/separator/src/separator.js +33 -5
- package/dist/components/separator/src/tv.d.ts +39 -18
- package/dist/components/separator/src/tv.js +37 -7
- package/dist/components/text-field/dist/index.d.ts +2 -3
- package/dist/components/text-field/dist/index.js +4 -19
- package/dist/components/text-field/src/components/index.d.ts +0 -1
- package/dist/components/text-field/src/text-field.d.ts +3 -2
- package/dist/components/text-field/src/text-field.js +2 -2
- package/dist/components/text-field/src/tv.d.ts +3 -3
- package/dist/components/text-field/src/tv.js +1 -6
- package/dist/components/toast/dist/index.d.ts +248 -0
- package/dist/components/toast/src/components/index.d.ts +3 -0
- package/dist/components/toast/src/components/toast-progress-bar.d.ts +7 -0
- package/dist/components/toast/src/components/toast-progress-bar.js +53 -0
- package/dist/components/toast/src/components/toaster-item.d.ts +26 -0
- package/dist/components/toast/src/components/toaster-item.js +416 -0
- package/dist/components/toast/src/components/toaster-slots.d.ts +87 -0
- package/dist/components/toast/src/components/toaster-slots.js +38 -0
- package/dist/components/toast/src/index.d.ts +5 -0
- package/dist/components/toast/src/store.d.ts +101 -0
- package/dist/components/toast/src/store.js +205 -0
- package/dist/components/toast/src/toaster.d.ts +87 -0
- package/dist/components/toast/src/toaster.js +271 -0
- package/dist/components/toast/src/tv.d.ts +365 -0
- package/dist/components/toast/src/tv.js +412 -0
- package/dist/components/toast/src/types.d.ts +79 -0
- package/dist/components/toast/tsup.config.d.ts +2 -0
- package/dist/index.js +11 -2
- package/dist/styles/components.css +2 -0
- package/package.json +1 -1
- package/dist/components/code-block/src/hooks/use-line-count.d.ts +0 -2
- package/dist/components/code-block/src/hooks/use-line-count.js +0 -27
- package/dist/components/text-field/src/components/field-description.d.ts +0 -2
- package/dist/components/text-field/src/components/field-description.js +0 -16
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { default as React__default, ReactNode, HTMLProps, RefObject } from 'react';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
3
|
|
|
5
4
|
interface CodeBlockContextValue {
|
|
6
5
|
codeExpanded: boolean;
|
|
@@ -14,7 +13,7 @@ interface CodeBlockContextValue {
|
|
|
14
13
|
isExpanded: boolean;
|
|
15
14
|
language: string;
|
|
16
15
|
lineCount: number;
|
|
17
|
-
lineThreshold
|
|
16
|
+
lineThreshold?: number;
|
|
18
17
|
needsScroll: boolean;
|
|
19
18
|
scrollRef?: RefObject<HTMLDivElement>;
|
|
20
19
|
variant?: "default" | "light" | "dark";
|
|
@@ -51,35 +50,33 @@ interface CodeBlockFooterProps extends CodeBlockInjectedProps {
|
|
|
51
50
|
}
|
|
52
51
|
interface CodeBlockContentProps extends CodeBlockInjectedProps {
|
|
53
52
|
className?: string;
|
|
54
|
-
code: string;
|
|
55
53
|
language?: string;
|
|
56
54
|
withScrollArea?: boolean;
|
|
55
|
+
children?: string;
|
|
57
56
|
}
|
|
58
57
|
interface CodeBlockCodeProps extends HTMLProps<HTMLDivElement> {
|
|
59
58
|
className?: string;
|
|
60
|
-
|
|
61
|
-
/** 从 CodeBlock 传递的 context */
|
|
59
|
+
children?: string;
|
|
62
60
|
codeBlock?: CodeBlockContextValue;
|
|
63
61
|
codeBlockId?: string;
|
|
64
62
|
language?: string;
|
|
65
|
-
/** 手动指定主题,覆盖自动检测 */
|
|
66
63
|
variant?: "light" | "dark";
|
|
67
64
|
}
|
|
68
65
|
|
|
66
|
+
declare const CodeBlock: React__default.NamedExoticComponent<CodeBlockProps> & {
|
|
67
|
+
Code: React__default.NamedExoticComponent<CodeBlockCodeProps>;
|
|
68
|
+
Content: React__default.NamedExoticComponent<CodeBlockContentProps>;
|
|
69
|
+
Footer: React__default.NamedExoticComponent<CodeBlockFooterProps>;
|
|
70
|
+
Header: React__default.NamedExoticComponent<CodeBlockHeaderProps>;
|
|
71
|
+
};
|
|
72
|
+
|
|
69
73
|
declare const CodeBlockCode: React.NamedExoticComponent<CodeBlockCodeProps>;
|
|
70
74
|
|
|
71
75
|
declare const CodeBlockHeader: React__default.NamedExoticComponent<CodeBlockHeaderProps>;
|
|
72
76
|
|
|
73
77
|
declare const CodeBlockFooter: React.NamedExoticComponent<CodeBlockFooterProps>;
|
|
74
78
|
|
|
75
|
-
declare
|
|
76
|
-
|
|
77
|
-
declare const CodeBlock: React__default.NamedExoticComponent<CodeBlockProps> & {
|
|
78
|
-
Code: React__default.NamedExoticComponent<CodeBlockCodeProps>;
|
|
79
|
-
Content: typeof CodeBlockContent;
|
|
80
|
-
Footer: React__default.NamedExoticComponent<CodeBlockFooterProps>;
|
|
81
|
-
Header: React__default.NamedExoticComponent<CodeBlockHeaderProps>;
|
|
82
|
-
};
|
|
79
|
+
declare const CodeBlockContent: React.NamedExoticComponent<CodeBlockContentProps>;
|
|
83
80
|
|
|
84
81
|
declare function getDefaultFilenameForLanguage(language: string): string;
|
|
85
82
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React__default, { memo, useState, useEffect } from "react";
|
|
1
|
+
import React__default, { memo, useState, useEffect, useRef, useCallback } from "react";
|
|
2
2
|
import { useStickToBottom } from "use-stick-to-bottom";
|
|
3
3
|
import { codeToHtml } from "shiki";
|
|
4
4
|
import { useEventCallback } from "usehooks-ts";
|
|
@@ -34,13 +34,34 @@ function useCodeBlock({
|
|
|
34
34
|
if (!code || typeof code !== "string") {
|
|
35
35
|
return;
|
|
36
36
|
}
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
const onSuccess = () => {
|
|
38
|
+
setCopied(true);
|
|
39
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
40
|
+
};
|
|
41
|
+
if (typeof navigator !== "undefined" && navigator.clipboard) {
|
|
42
|
+
try {
|
|
39
43
|
await navigator.clipboard.writeText(code);
|
|
40
|
-
|
|
41
|
-
|
|
44
|
+
onSuccess();
|
|
45
|
+
return;
|
|
46
|
+
} catch {
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
const textArea = document.createElement("textarea");
|
|
50
|
+
try {
|
|
51
|
+
textArea.value = code;
|
|
52
|
+
textArea.style.cssText = "position:fixed;top:0;left:0;width:2em;height:2em;padding:0;border:none;outline:none;box-shadow:none;background:transparent;";
|
|
53
|
+
document.body.appendChild(textArea);
|
|
54
|
+
textArea.focus();
|
|
55
|
+
textArea.select();
|
|
56
|
+
const successful = document.execCommand("copy");
|
|
57
|
+
if (successful) {
|
|
58
|
+
onSuccess();
|
|
59
|
+
}
|
|
60
|
+
} catch {
|
|
61
|
+
} finally {
|
|
62
|
+
if (textArea.parentNode) {
|
|
63
|
+
textArea.parentNode.removeChild(textArea);
|
|
42
64
|
}
|
|
43
|
-
} catch (error) {
|
|
44
65
|
}
|
|
45
66
|
});
|
|
46
67
|
return {
|
|
@@ -56,12 +77,15 @@ function useScrollDetection({
|
|
|
56
77
|
scrollRef,
|
|
57
78
|
contentRef,
|
|
58
79
|
isExpanded,
|
|
59
|
-
codeExpanded
|
|
60
|
-
children
|
|
80
|
+
codeExpanded
|
|
61
81
|
}) {
|
|
62
82
|
const [needsScroll, setNeedsScroll] = useState(false);
|
|
63
|
-
|
|
64
|
-
|
|
83
|
+
const debounceRef = useRef(null);
|
|
84
|
+
const checkScrollNeeded = useCallback(() => {
|
|
85
|
+
if (debounceRef.current) {
|
|
86
|
+
clearTimeout(debounceRef.current);
|
|
87
|
+
}
|
|
88
|
+
debounceRef.current = setTimeout(() => {
|
|
65
89
|
if (!scrollRef.current || !contentRef.current) {
|
|
66
90
|
setNeedsScroll(false);
|
|
67
91
|
return;
|
|
@@ -71,50 +95,30 @@ function useScrollDetection({
|
|
|
71
95
|
const content = contentRef.current;
|
|
72
96
|
const hasScroll = content.scrollHeight > viewport.clientHeight;
|
|
73
97
|
setNeedsScroll(hasScroll);
|
|
74
|
-
} catch
|
|
98
|
+
} catch {
|
|
75
99
|
setNeedsScroll(false);
|
|
76
100
|
}
|
|
77
|
-
};
|
|
101
|
+
}, 50);
|
|
102
|
+
}, [scrollRef, contentRef]);
|
|
103
|
+
useEffect(() => {
|
|
78
104
|
const timeoutId = setTimeout(checkScrollNeeded, 100);
|
|
79
105
|
window.addEventListener("resize", checkScrollNeeded);
|
|
80
106
|
let resizeObserver = null;
|
|
81
|
-
if (typeof ResizeObserver !== "undefined") {
|
|
107
|
+
if (typeof ResizeObserver !== "undefined" && contentRef.current) {
|
|
82
108
|
resizeObserver = new ResizeObserver(checkScrollNeeded);
|
|
83
|
-
|
|
84
|
-
resizeObserver.observe(contentRef.current);
|
|
85
|
-
}
|
|
109
|
+
resizeObserver.observe(contentRef.current);
|
|
86
110
|
}
|
|
87
111
|
return () => {
|
|
88
112
|
clearTimeout(timeoutId);
|
|
113
|
+
if (debounceRef.current) {
|
|
114
|
+
clearTimeout(debounceRef.current);
|
|
115
|
+
}
|
|
89
116
|
window.removeEventListener("resize", checkScrollNeeded);
|
|
90
117
|
resizeObserver == null ? void 0 : resizeObserver.disconnect();
|
|
91
118
|
};
|
|
92
|
-
}, [
|
|
119
|
+
}, [checkScrollNeeded, isExpanded, codeExpanded]);
|
|
93
120
|
return needsScroll;
|
|
94
121
|
}
|
|
95
|
-
function useLineCount(children) {
|
|
96
|
-
const [lineCount, setLineCount] = useState(0);
|
|
97
|
-
useEffect(() => {
|
|
98
|
-
try {
|
|
99
|
-
const codeContent = React__default.Children.toArray(children).map((child) => {
|
|
100
|
-
var _a;
|
|
101
|
-
if (React__default.isValidElement(child) && ((_a = child.props) == null ? void 0 : _a.code) && typeof child.props.code === "string") {
|
|
102
|
-
return child.props.code;
|
|
103
|
-
}
|
|
104
|
-
return "";
|
|
105
|
-
}).join("");
|
|
106
|
-
if (codeContent) {
|
|
107
|
-
const lines = codeContent.split("\n").length;
|
|
108
|
-
setLineCount(lines);
|
|
109
|
-
} else {
|
|
110
|
-
setLineCount(0);
|
|
111
|
-
}
|
|
112
|
-
} catch (error) {
|
|
113
|
-
setLineCount(0);
|
|
114
|
-
}
|
|
115
|
-
}, [children]);
|
|
116
|
-
return lineCount;
|
|
117
|
-
}
|
|
118
122
|
function useTheme() {
|
|
119
123
|
const [theme, setTheme] = useState(() => {
|
|
120
124
|
if (typeof window === "undefined") return "light";
|
|
@@ -176,34 +180,46 @@ var codeBlockCodeTv = tcv({
|
|
|
176
180
|
base: "text-message-code w-fit min-w-full bg-transparent font-mono [&>pre]:!bg-transparent [&>pre]:px-4 [&>pre]:py-4"
|
|
177
181
|
});
|
|
178
182
|
var CodeBlockCode = memo(function CodeBlockCode2(props) {
|
|
179
|
-
const {
|
|
183
|
+
const { children, language = "tsx", className, variant: variantProp, codeBlock, ...rest } = props;
|
|
180
184
|
const systemTheme = useTheme();
|
|
181
185
|
const resolvedVariant = variantProp ?? ((codeBlock == null ? void 0 : codeBlock.variant) === "default" ? void 0 : codeBlock == null ? void 0 : codeBlock.variant);
|
|
182
186
|
const theme = resolvedVariant ?? systemTheme;
|
|
183
187
|
const [highlightedHtml, setHighlightedHtml] = useState(null);
|
|
184
188
|
useEffect(() => {
|
|
189
|
+
let isMounted = true;
|
|
185
190
|
async function highlight() {
|
|
186
|
-
if (!
|
|
187
|
-
setHighlightedHtml("<pre><code></code></pre>");
|
|
191
|
+
if (!children) {
|
|
192
|
+
if (isMounted) setHighlightedHtml("<pre><code></code></pre>");
|
|
188
193
|
return;
|
|
189
194
|
}
|
|
190
195
|
const resolvedLang = resolveLanguage(language);
|
|
196
|
+
const themeConfig = theme === "light" ? "github-light" : "github-dark";
|
|
191
197
|
try {
|
|
192
|
-
const html = await codeToHtml(
|
|
198
|
+
const html = await codeToHtml(children, {
|
|
193
199
|
lang: resolvedLang,
|
|
194
|
-
theme:
|
|
200
|
+
theme: themeConfig
|
|
195
201
|
});
|
|
196
|
-
setHighlightedHtml(html);
|
|
202
|
+
if (isMounted) setHighlightedHtml(html);
|
|
197
203
|
} catch {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
204
|
+
try {
|
|
205
|
+
const html = await codeToHtml(children, {
|
|
206
|
+
lang: "text",
|
|
207
|
+
theme: themeConfig
|
|
208
|
+
});
|
|
209
|
+
if (isMounted) setHighlightedHtml(html);
|
|
210
|
+
} catch {
|
|
211
|
+
if (isMounted) {
|
|
212
|
+
const escaped = children.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
213
|
+
setHighlightedHtml(`<pre><code>${escaped}</code></pre>`);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
203
216
|
}
|
|
204
217
|
}
|
|
205
218
|
highlight();
|
|
206
|
-
|
|
219
|
+
return () => {
|
|
220
|
+
isMounted = false;
|
|
221
|
+
};
|
|
222
|
+
}, [children, language, theme]);
|
|
207
223
|
const classNames = codeBlockCodeTv({ className });
|
|
208
224
|
return highlightedHtml ? /* @__PURE__ */ jsx(
|
|
209
225
|
"div",
|
|
@@ -217,10 +233,29 @@ var CodeBlockCode = memo(function CodeBlockCode2(props) {
|
|
|
217
233
|
{
|
|
218
234
|
className: tcx("min-w-0", classNames),
|
|
219
235
|
...rest,
|
|
220
|
-
children: /* @__PURE__ */ jsx("pre", { children: /* @__PURE__ */ jsx("code", { children
|
|
236
|
+
children: /* @__PURE__ */ jsx("pre", { children: /* @__PURE__ */ jsx("code", { children }) })
|
|
221
237
|
}
|
|
222
238
|
);
|
|
223
239
|
});
|
|
240
|
+
function extractCodeFromChildren(children) {
|
|
241
|
+
if (!children) return "";
|
|
242
|
+
try {
|
|
243
|
+
return React__default.Children.toArray(children).map((child) => {
|
|
244
|
+
var _a, _b;
|
|
245
|
+
if (React__default.isValidElement(child)) {
|
|
246
|
+
if (((_a = child.props) == null ? void 0 : _a.code) && typeof child.props.code === "string") {
|
|
247
|
+
return child.props.code;
|
|
248
|
+
}
|
|
249
|
+
if (((_b = child.props) == null ? void 0 : _b.children) && typeof child.props.children === "string") {
|
|
250
|
+
return child.props.children;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return "";
|
|
254
|
+
}).filter(Boolean).join("");
|
|
255
|
+
} catch {
|
|
256
|
+
return "";
|
|
257
|
+
}
|
|
258
|
+
}
|
|
224
259
|
var icons = {
|
|
225
260
|
js: /* @__PURE__ */ jsxs(
|
|
226
261
|
"svg",
|
|
@@ -908,9 +943,8 @@ var CodeBlockHeader = memo(function CodeBlockHeader2(props) {
|
|
|
908
943
|
handleCopy,
|
|
909
944
|
variant
|
|
910
945
|
} = codeBlock;
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
}
|
|
946
|
+
const canExpand = Boolean(handleExpand);
|
|
947
|
+
const canCopy = Boolean(handleCopy);
|
|
914
948
|
const tv = codeBlockHeaderTv({ isExpanded, variant });
|
|
915
949
|
let icon = null;
|
|
916
950
|
try {
|
|
@@ -934,17 +968,17 @@ var CodeBlockHeader = memo(function CodeBlockHeader2(props) {
|
|
|
934
968
|
children
|
|
935
969
|
] }),
|
|
936
970
|
/* @__PURE__ */ jsxs("div", { className: tv.actions(), children: [
|
|
937
|
-
isExpanded && /* @__PURE__ */ jsx(
|
|
971
|
+
isExpanded && canCopy && /* @__PURE__ */ jsx(
|
|
938
972
|
IconButton,
|
|
939
973
|
{
|
|
940
974
|
className: tv.button(),
|
|
941
975
|
variant: variant === "dark" ? "dark" : "ghost",
|
|
942
|
-
onClick: () => handleCopy(),
|
|
976
|
+
onClick: () => handleCopy == null ? void 0 : handleCopy(),
|
|
943
977
|
tooltip: { content: copyTooltipContent },
|
|
944
978
|
children: copied ? /* @__PURE__ */ jsx(Check, { className: "text-success-foreground" }) : /* @__PURE__ */ jsx(ClipboardSmall, {})
|
|
945
979
|
}
|
|
946
980
|
),
|
|
947
|
-
expandable && /* @__PURE__ */ jsx(
|
|
981
|
+
expandable && canExpand && /* @__PURE__ */ jsx(
|
|
948
982
|
IconButton,
|
|
949
983
|
{
|
|
950
984
|
className: tv.button(),
|
|
@@ -972,9 +1006,10 @@ var codeBlockFooterTv = tcv({
|
|
|
972
1006
|
},
|
|
973
1007
|
false: {
|
|
974
1008
|
footer: [
|
|
975
|
-
"bg-secondary-background/
|
|
1009
|
+
"bg-secondary-background/80 absolute inset-x-0 bottom-0 z-3",
|
|
976
1010
|
"opacity-0 group-hover:opacity-100",
|
|
977
|
-
"hover:bg-tertiary-background"
|
|
1011
|
+
"hover:bg-tertiary-background",
|
|
1012
|
+
"backdrop-blur-xs"
|
|
978
1013
|
]
|
|
979
1014
|
}
|
|
980
1015
|
}
|
|
@@ -988,7 +1023,7 @@ var CodeBlockFooter = memo(function CodeBlockFooter2(props) {
|
|
|
988
1023
|
if (!codeBlock) return null;
|
|
989
1024
|
const { isExpanded, codeExpanded, handleCodeExpand, lineCount, lineThreshold, needsScroll } = codeBlock;
|
|
990
1025
|
const tv = codeBlockFooterTv({ codeExpanded });
|
|
991
|
-
if (!(lineCount > lineThreshold || needsScroll || codeExpanded) || !isExpanded) {
|
|
1026
|
+
if (lineThreshold && !(lineCount > lineThreshold || needsScroll || codeExpanded) || !isExpanded) {
|
|
992
1027
|
return null;
|
|
993
1028
|
}
|
|
994
1029
|
return /* @__PURE__ */ jsx(
|
|
@@ -1000,24 +1035,26 @@ var CodeBlockFooter = memo(function CodeBlockFooter2(props) {
|
|
|
1000
1035
|
}
|
|
1001
1036
|
);
|
|
1002
1037
|
});
|
|
1038
|
+
var LINE_HEIGHT_PX = 16;
|
|
1039
|
+
var HEIGHT_PADDING_PX = 32 + 40;
|
|
1003
1040
|
var codeBlockTv = tcv({
|
|
1004
1041
|
slots: {
|
|
1005
|
-
code: "overflow-hidden",
|
|
1042
|
+
code: "overflow-hidden min-h-0 flex-1",
|
|
1006
1043
|
content: "flex w-fit flex-col overflow-clip p-[inherit]"
|
|
1007
1044
|
}
|
|
1008
1045
|
});
|
|
1009
|
-
|
|
1010
|
-
const {
|
|
1046
|
+
var CodeBlockContent = memo(function CodeBlockContent2(props) {
|
|
1047
|
+
const { className, codeBlock, withScrollArea = true, children } = props;
|
|
1011
1048
|
if (!codeBlock) return null;
|
|
1012
1049
|
const { language, isExpanded, codeExpanded, scrollRef, contentRef, lineCount, lineThreshold } = codeBlock;
|
|
1013
1050
|
if (!isExpanded) {
|
|
1014
1051
|
return null;
|
|
1015
1052
|
}
|
|
1016
|
-
if (typeof
|
|
1053
|
+
if (typeof children !== "string") {
|
|
1017
1054
|
return null;
|
|
1018
1055
|
}
|
|
1019
1056
|
const tv = codeBlockTv();
|
|
1020
|
-
const shouldLimitHeight = lineCount > lineThreshold && !codeExpanded;
|
|
1057
|
+
const shouldLimitHeight = lineThreshold && lineCount > lineThreshold && !codeExpanded;
|
|
1021
1058
|
return /* @__PURE__ */ jsx(Fragment, { children: withScrollArea ? /* @__PURE__ */ jsx(
|
|
1022
1059
|
ScrollArea,
|
|
1023
1060
|
{
|
|
@@ -1030,7 +1067,7 @@ function CodeBlockContent(props) {
|
|
|
1030
1067
|
{
|
|
1031
1068
|
ref: scrollRef,
|
|
1032
1069
|
style: {
|
|
1033
|
-
maxHeight: shouldLimitHeight ? `${lineThreshold *
|
|
1070
|
+
maxHeight: shouldLimitHeight ? `${lineThreshold * LINE_HEIGHT_PX + HEIGHT_PADDING_PX}px` : "none"
|
|
1034
1071
|
},
|
|
1035
1072
|
children: /* @__PURE__ */ jsx(
|
|
1036
1073
|
ScrollArea.Content,
|
|
@@ -1040,9 +1077,9 @@ function CodeBlockContent(props) {
|
|
|
1040
1077
|
children: /* @__PURE__ */ jsx(
|
|
1041
1078
|
CodeBlockCode,
|
|
1042
1079
|
{
|
|
1043
|
-
code,
|
|
1044
1080
|
language,
|
|
1045
|
-
codeBlock
|
|
1081
|
+
codeBlock,
|
|
1082
|
+
children
|
|
1046
1083
|
}
|
|
1047
1084
|
)
|
|
1048
1085
|
}
|
|
@@ -1053,19 +1090,19 @@ function CodeBlockContent(props) {
|
|
|
1053
1090
|
) : /* @__PURE__ */ jsx("div", { className: tcx(tv.content(), className), children: /* @__PURE__ */ jsx(
|
|
1054
1091
|
CodeBlockCode,
|
|
1055
1092
|
{
|
|
1056
|
-
code,
|
|
1057
1093
|
language,
|
|
1058
|
-
codeBlock
|
|
1094
|
+
codeBlock,
|
|
1095
|
+
children
|
|
1059
1096
|
}
|
|
1060
1097
|
) }) });
|
|
1061
|
-
}
|
|
1098
|
+
});
|
|
1062
1099
|
var CodeBlockRoot = memo(function CodeBlock(props) {
|
|
1063
1100
|
const {
|
|
1064
1101
|
children,
|
|
1065
1102
|
className,
|
|
1066
1103
|
filename,
|
|
1067
1104
|
language = "code",
|
|
1068
|
-
lineThreshold
|
|
1105
|
+
lineThreshold,
|
|
1069
1106
|
expandable = true,
|
|
1070
1107
|
defaultExpanded = true,
|
|
1071
1108
|
defaultCodeExpanded = false,
|
|
@@ -1077,7 +1114,6 @@ var CodeBlockRoot = memo(function CodeBlock(props) {
|
|
|
1077
1114
|
resize: "smooth",
|
|
1078
1115
|
initial: "smooth"
|
|
1079
1116
|
});
|
|
1080
|
-
const codeContentRef = React__default.useRef("");
|
|
1081
1117
|
const {
|
|
1082
1118
|
isExpanded,
|
|
1083
1119
|
codeExpanded,
|
|
@@ -1092,34 +1128,25 @@ var CodeBlockRoot = memo(function CodeBlock(props) {
|
|
|
1092
1128
|
onCodeExpandChange,
|
|
1093
1129
|
scrollToBottom
|
|
1094
1130
|
});
|
|
1131
|
+
const codeContent = React__default.useMemo(() => extractCodeFromChildren(children), [children]);
|
|
1132
|
+
const lineCount = React__default.useMemo(
|
|
1133
|
+
() => codeContent ? codeContent.split("\n").length : 0,
|
|
1134
|
+
[codeContent]
|
|
1135
|
+
);
|
|
1095
1136
|
const handleCopy = React__default.useCallback(
|
|
1096
1137
|
(code) => {
|
|
1097
|
-
const codeToUse = code ||
|
|
1138
|
+
const codeToUse = code || codeContent;
|
|
1098
1139
|
if (codeToUse) {
|
|
1099
1140
|
originalHandleCopy(codeToUse);
|
|
1100
1141
|
}
|
|
1101
1142
|
},
|
|
1102
|
-
[originalHandleCopy]
|
|
1143
|
+
[originalHandleCopy, codeContent]
|
|
1103
1144
|
);
|
|
1104
|
-
React__default.useEffect(() => {
|
|
1105
|
-
try {
|
|
1106
|
-
React__default.Children.forEach(children, (child) => {
|
|
1107
|
-
if (React__default.isValidElement(child) && child.props) {
|
|
1108
|
-
if (child.props.code && typeof child.props.code === "string") {
|
|
1109
|
-
codeContentRef.current = child.props.code;
|
|
1110
|
-
}
|
|
1111
|
-
}
|
|
1112
|
-
});
|
|
1113
|
-
} catch {
|
|
1114
|
-
}
|
|
1115
|
-
}, [children]);
|
|
1116
|
-
const lineCount = useLineCount(children);
|
|
1117
1145
|
const needsScroll = useScrollDetection({
|
|
1118
1146
|
scrollRef,
|
|
1119
1147
|
contentRef,
|
|
1120
1148
|
isExpanded,
|
|
1121
|
-
codeExpanded
|
|
1122
|
-
children
|
|
1149
|
+
codeExpanded
|
|
1123
1150
|
});
|
|
1124
1151
|
const contextValue = React__default.useMemo(
|
|
1125
1152
|
() => ({
|
|
@@ -1178,7 +1205,7 @@ var CodeBlockRoot = memo(function CodeBlock(props) {
|
|
|
1178
1205
|
"div",
|
|
1179
1206
|
{
|
|
1180
1207
|
className: tcx(
|
|
1181
|
-
"group/code-block relative overflow-hidden rounded-lg",
|
|
1208
|
+
"group/code-block relative flex flex-col overflow-hidden rounded-lg",
|
|
1182
1209
|
variant === "default" && "bg-secondary-background",
|
|
1183
1210
|
variant === "light" && "bg-gray-100",
|
|
1184
1211
|
variant === "dark" && "bg-gray-700",
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
|
-
import { CodeBlockContent } from './components';
|
|
3
2
|
import { CodeBlockProps } from './types';
|
|
4
3
|
export declare const CodeBlockRoot: React.NamedExoticComponent<CodeBlockProps>;
|
|
5
4
|
export declare const CodeBlock: React.NamedExoticComponent<CodeBlockProps> & {
|
|
6
5
|
Code: React.NamedExoticComponent<import('../..').CodeBlockCodeProps>;
|
|
7
|
-
Content:
|
|
6
|
+
Content: React.NamedExoticComponent<import('../..').CodeBlockContentProps>;
|
|
8
7
|
Footer: React.NamedExoticComponent<import('../..').CodeBlockFooterProps>;
|
|
9
8
|
Header: React.NamedExoticComponent<import('../..').CodeBlockHeaderProps>;
|
|
10
9
|
};
|
|
@@ -6,7 +6,7 @@ import { CodeBlockFooter } from "./components/code-block-footer.js";
|
|
|
6
6
|
import { CodeBlockContent } from "./components/code-block-content.js";
|
|
7
7
|
import { CodeBlockCode } from "./components/code-block-code.js";
|
|
8
8
|
import { useCodeBlock } from "./hooks/use-code-block.js";
|
|
9
|
-
import {
|
|
9
|
+
import { extractCodeFromChildren } from "./utils/extract-code.js";
|
|
10
10
|
import { useScrollDetection } from "./hooks/use-scroll-detection.js";
|
|
11
11
|
import { tcx } from "../../../shared/utils/tcx/tcx.js";
|
|
12
12
|
const CodeBlockRoot = memo(function CodeBlock2(props) {
|
|
@@ -15,7 +15,7 @@ const CodeBlockRoot = memo(function CodeBlock2(props) {
|
|
|
15
15
|
className,
|
|
16
16
|
filename,
|
|
17
17
|
language = "code",
|
|
18
|
-
lineThreshold
|
|
18
|
+
lineThreshold,
|
|
19
19
|
expandable = true,
|
|
20
20
|
defaultExpanded = true,
|
|
21
21
|
defaultCodeExpanded = false,
|
|
@@ -27,7 +27,6 @@ const CodeBlockRoot = memo(function CodeBlock2(props) {
|
|
|
27
27
|
resize: "smooth",
|
|
28
28
|
initial: "smooth"
|
|
29
29
|
});
|
|
30
|
-
const codeContentRef = React__default.useRef("");
|
|
31
30
|
const {
|
|
32
31
|
isExpanded,
|
|
33
32
|
codeExpanded,
|
|
@@ -42,34 +41,25 @@ const CodeBlockRoot = memo(function CodeBlock2(props) {
|
|
|
42
41
|
onCodeExpandChange,
|
|
43
42
|
scrollToBottom
|
|
44
43
|
});
|
|
44
|
+
const codeContent = React__default.useMemo(() => extractCodeFromChildren(children), [children]);
|
|
45
|
+
const lineCount = React__default.useMemo(
|
|
46
|
+
() => codeContent ? codeContent.split("\n").length : 0,
|
|
47
|
+
[codeContent]
|
|
48
|
+
);
|
|
45
49
|
const handleCopy = React__default.useCallback(
|
|
46
50
|
(code) => {
|
|
47
|
-
const codeToUse = code ||
|
|
51
|
+
const codeToUse = code || codeContent;
|
|
48
52
|
if (codeToUse) {
|
|
49
53
|
originalHandleCopy(codeToUse);
|
|
50
54
|
}
|
|
51
55
|
},
|
|
52
|
-
[originalHandleCopy]
|
|
56
|
+
[originalHandleCopy, codeContent]
|
|
53
57
|
);
|
|
54
|
-
React__default.useEffect(() => {
|
|
55
|
-
try {
|
|
56
|
-
React__default.Children.forEach(children, (child) => {
|
|
57
|
-
if (React__default.isValidElement(child) && child.props) {
|
|
58
|
-
if (child.props.code && typeof child.props.code === "string") {
|
|
59
|
-
codeContentRef.current = child.props.code;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
} catch {
|
|
64
|
-
}
|
|
65
|
-
}, [children]);
|
|
66
|
-
const lineCount = useLineCount(children);
|
|
67
58
|
const needsScroll = useScrollDetection({
|
|
68
59
|
scrollRef,
|
|
69
60
|
contentRef,
|
|
70
61
|
isExpanded,
|
|
71
|
-
codeExpanded
|
|
72
|
-
children
|
|
62
|
+
codeExpanded
|
|
73
63
|
});
|
|
74
64
|
const contextValue = React__default.useMemo(
|
|
75
65
|
() => ({
|
|
@@ -128,7 +118,7 @@ const CodeBlockRoot = memo(function CodeBlock2(props) {
|
|
|
128
118
|
"div",
|
|
129
119
|
{
|
|
130
120
|
className: tcx(
|
|
131
|
-
"group/code-block relative overflow-hidden rounded-lg",
|
|
121
|
+
"group/code-block relative flex flex-col overflow-hidden rounded-lg",
|
|
132
122
|
variant === "default" && "bg-secondary-background",
|
|
133
123
|
variant === "light" && "bg-gray-100",
|
|
134
124
|
variant === "dark" && "bg-gray-700",
|
|
@@ -24,34 +24,46 @@ const codeBlockCodeTv = tcv({
|
|
|
24
24
|
base: "text-message-code w-fit min-w-full bg-transparent font-mono [&>pre]:!bg-transparent [&>pre]:px-4 [&>pre]:py-4"
|
|
25
25
|
});
|
|
26
26
|
const CodeBlockCode = memo(function CodeBlockCode2(props) {
|
|
27
|
-
const {
|
|
27
|
+
const { children, language = "tsx", className, variant: variantProp, codeBlock, ...rest } = props;
|
|
28
28
|
const systemTheme = useTheme();
|
|
29
29
|
const resolvedVariant = variantProp ?? ((codeBlock == null ? void 0 : codeBlock.variant) === "default" ? void 0 : codeBlock == null ? void 0 : codeBlock.variant);
|
|
30
30
|
const theme = resolvedVariant ?? systemTheme;
|
|
31
31
|
const [highlightedHtml, setHighlightedHtml] = useState(null);
|
|
32
32
|
useEffect(() => {
|
|
33
|
+
let isMounted = true;
|
|
33
34
|
async function highlight() {
|
|
34
|
-
if (!
|
|
35
|
-
setHighlightedHtml("<pre><code></code></pre>");
|
|
35
|
+
if (!children) {
|
|
36
|
+
if (isMounted) setHighlightedHtml("<pre><code></code></pre>");
|
|
36
37
|
return;
|
|
37
38
|
}
|
|
38
39
|
const resolvedLang = resolveLanguage(language);
|
|
40
|
+
const themeConfig = theme === "light" ? "github-light" : "github-dark";
|
|
39
41
|
try {
|
|
40
|
-
const html = await codeToHtml(
|
|
42
|
+
const html = await codeToHtml(children, {
|
|
41
43
|
lang: resolvedLang,
|
|
42
|
-
theme:
|
|
44
|
+
theme: themeConfig
|
|
43
45
|
});
|
|
44
|
-
setHighlightedHtml(html);
|
|
46
|
+
if (isMounted) setHighlightedHtml(html);
|
|
45
47
|
} catch {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
try {
|
|
49
|
+
const html = await codeToHtml(children, {
|
|
50
|
+
lang: "text",
|
|
51
|
+
theme: themeConfig
|
|
52
|
+
});
|
|
53
|
+
if (isMounted) setHighlightedHtml(html);
|
|
54
|
+
} catch {
|
|
55
|
+
if (isMounted) {
|
|
56
|
+
const escaped = children.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
57
|
+
setHighlightedHtml(`<pre><code>${escaped}</code></pre>`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
51
60
|
}
|
|
52
61
|
}
|
|
53
62
|
highlight();
|
|
54
|
-
|
|
63
|
+
return () => {
|
|
64
|
+
isMounted = false;
|
|
65
|
+
};
|
|
66
|
+
}, [children, language, theme]);
|
|
55
67
|
const classNames = codeBlockCodeTv({ className });
|
|
56
68
|
return highlightedHtml ? /* @__PURE__ */ jsx(
|
|
57
69
|
"div",
|
|
@@ -65,7 +77,7 @@ const CodeBlockCode = memo(function CodeBlockCode2(props) {
|
|
|
65
77
|
{
|
|
66
78
|
className: tcx("min-w-0", classNames),
|
|
67
79
|
...rest,
|
|
68
|
-
children: /* @__PURE__ */ jsx("pre", { children: /* @__PURE__ */ jsx("code", { children
|
|
80
|
+
children: /* @__PURE__ */ jsx("pre", { children: /* @__PURE__ */ jsx("code", { children }) })
|
|
69
81
|
}
|
|
70
82
|
);
|
|
71
83
|
});
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { CodeBlockContentProps } from '../types';
|
|
2
|
-
export declare
|
|
2
|
+
export declare const CodeBlockContent: import('react').NamedExoticComponent<CodeBlockContentProps>;
|