@assistant-ui/react-markdown 0.2.22 → 0.2.24
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/index.d.ts +6 -45
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -307
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +7 -293
- package/dist/index.mjs.map +1 -1
- package/dist/overrides/CodeBlock.d.ts +14 -0
- package/dist/overrides/CodeBlock.d.ts.map +1 -0
- package/dist/overrides/CodeBlock.js +50 -0
- package/dist/overrides/CodeBlock.js.map +1 -0
- package/dist/overrides/CodeBlock.mjs +26 -0
- package/dist/overrides/CodeBlock.mjs.map +1 -0
- package/dist/overrides/CodeOverride.d.ts +16 -0
- package/dist/overrides/CodeOverride.d.ts.map +1 -0
- package/dist/overrides/CodeOverride.js +85 -0
- package/dist/overrides/CodeOverride.js.map +1 -0
- package/dist/overrides/CodeOverride.mjs +61 -0
- package/dist/overrides/CodeOverride.mjs.map +1 -0
- package/dist/overrides/PreOverride.d.ts +6 -0
- package/dist/overrides/PreOverride.d.ts.map +1 -0
- package/dist/overrides/PreOverride.js +41 -0
- package/dist/overrides/PreOverride.js.map +1 -0
- package/dist/overrides/PreOverride.mjs +15 -0
- package/dist/overrides/PreOverride.mjs.map +1 -0
- package/dist/overrides/defaultComponents.d.ts +13 -0
- package/dist/overrides/defaultComponents.d.ts.map +1 -0
- package/dist/overrides/defaultComponents.js +39 -0
- package/dist/overrides/defaultComponents.js.map +1 -0
- package/dist/overrides/defaultComponents.mjs +12 -0
- package/dist/overrides/defaultComponents.mjs.map +1 -0
- package/dist/overrides/types.d.ts +16 -0
- package/dist/overrides/types.d.ts.map +1 -0
- package/dist/overrides/types.js +17 -0
- package/dist/overrides/types.js.map +1 -0
- package/dist/overrides/types.mjs +1 -0
- package/dist/overrides/types.mjs.map +1 -0
- package/dist/overrides/withDefaults.d.ts +4 -0
- package/dist/overrides/withDefaults.d.ts.map +1 -0
- package/dist/overrides/withDefaults.js +49 -0
- package/dist/overrides/withDefaults.js.map +1 -0
- package/dist/overrides/withDefaults.mjs +15 -0
- package/dist/overrides/withDefaults.mjs.map +1 -0
- package/dist/primitives/MarkdownText.d.ts +22 -0
- package/dist/primitives/MarkdownText.d.ts.map +1 -0
- package/dist/primitives/MarkdownText.js +96 -0
- package/dist/primitives/MarkdownText.js.map +1 -0
- package/dist/primitives/MarkdownText.mjs +69 -0
- package/dist/primitives/MarkdownText.mjs.map +1 -0
- package/dist/styles/markdown.css +1 -0
- package/dist/styles/markdown.css.map +1 -0
- package/dist/tailwindcss/index.d.ts +4 -6
- package/dist/tailwindcss/index.d.ts.map +1 -0
- package/dist/tailwindcss/index.js +3 -76
- package/dist/tailwindcss/index.js.map +1 -1
- package/dist/tailwindcss/index.mjs +3 -75
- package/dist/tailwindcss/index.mjs.map +1 -1
- package/dist/ui/code-header.d.ts +4 -0
- package/dist/ui/code-header.d.ts.map +1 -0
- package/dist/ui/code-header.js +52 -0
- package/dist/ui/code-header.js.map +1 -0
- package/dist/ui/code-header.mjs +28 -0
- package/dist/ui/code-header.mjs.map +1 -0
- package/dist/ui/markdown-text.d.ts +4 -0
- package/dist/ui/markdown-text.d.ts.map +1 -0
- package/dist/ui/markdown-text.js +112 -0
- package/dist/ui/markdown-text.js.map +1 -0
- package/dist/ui/markdown-text.mjs +80 -0
- package/dist/ui/markdown-text.mjs.map +1 -0
- package/dist/ui/useCopyToClipboard.d.ts +7 -0
- package/dist/ui/useCopyToClipboard.d.ts.map +1 -0
- package/dist/ui/useCopyToClipboard.js +42 -0
- package/dist/ui/useCopyToClipboard.js.map +1 -0
- package/dist/ui/useCopyToClipboard.mjs +18 -0
- package/dist/ui/useCopyToClipboard.mjs.map +1 -0
- package/package.json +15 -21
- package/src/index.ts +18 -0
- package/src/overrides/CodeBlock.tsx +41 -0
- package/src/overrides/CodeOverride.tsx +91 -0
- package/src/overrides/PreOverride.tsx +15 -0
- package/src/overrides/defaultComponents.tsx +21 -0
- package/src/overrides/types.ts +22 -0
- package/src/overrides/withDefaults.tsx +14 -0
- package/src/primitives/MarkdownText.tsx +110 -0
- package/src/styles/tailwindcss/markdown.css +106 -0
- package/src/tailwindcss/index.ts +8 -0
- package/src/ui/code-header.tsx +32 -0
- package/src/ui/markdown-text.tsx +114 -0
- package/src/ui/useCopyToClipboard.tsx +21 -0
- package/tailwindcss/README.md +1 -0
- package/tailwindcss/package.json +5 -0
- package/dist/index.d.mts +0 -45
- package/dist/tailwindcss/index.d.mts +0 -11
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/ui/useCopyToClipboard.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { UseActionBarCopyProps } from \"@assistant-ui/react\";\n\nexport type useCopyToClipboardProps = UseActionBarCopyProps;\n\nexport const useCopyToClipboard = ({\n copiedDuration = 3000,\n}: useCopyToClipboardProps = {}) => {\n const [isCopied, setIsCopied] = useState<boolean>(false);\n\n const copyToClipboard = (value: string) => {\n if (!value) return;\n\n navigator.clipboard.writeText(value).then(() => {\n setIsCopied(true);\n setTimeout(() => setIsCopied(false), copiedDuration);\n });\n };\n\n return { isCopied, copyToClipboard };\n};\n"],"mappings":"AAAA,SAAS,gBAAgB;AAKlB,MAAM,qBAAqB,CAAC;AAAA,EACjC,iBAAiB;AACnB,IAA6B,CAAC,MAAM;AAClC,QAAM,CAAC,UAAU,WAAW,IAAI,SAAkB,KAAK;AAEvD,QAAM,kBAAkB,CAAC,UAAkB;AACzC,QAAI,CAAC,MAAO;AAEZ,cAAU,UAAU,UAAU,KAAK,EAAE,KAAK,MAAM;AAC9C,kBAAY,IAAI;AAChB,iBAAW,MAAM,YAAY,KAAK,GAAG,cAAc;AAAA,IACrD,CAAC;AAAA,EACH;AAEA,SAAO,EAAE,UAAU,gBAAgB;AACrC;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,27 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@assistant-ui/react-markdown",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.24",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
7
|
-
"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
},
|
|
11
|
-
"require": {
|
|
12
|
-
"types": "./dist/index.d.ts",
|
|
13
|
-
"default": "./dist/index.js"
|
|
14
|
-
}
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"import": "./dist/index.mjs",
|
|
9
|
+
"require": "./dist/index.js"
|
|
15
10
|
},
|
|
16
11
|
"./tailwindcss": {
|
|
17
|
-
"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
},
|
|
21
|
-
"require": {
|
|
22
|
-
"types": "./dist/tailwindcss/index.d.ts",
|
|
23
|
-
"default": "./dist/tailwindcss/index.js"
|
|
24
|
-
}
|
|
12
|
+
"types": "./dist/tailwindcss/index.d.ts",
|
|
13
|
+
"import": "./dist/tailwindcss/index.mjs",
|
|
14
|
+
"require": "./dist/tailwindcss/index.js"
|
|
25
15
|
},
|
|
26
16
|
"./styles/*": {
|
|
27
17
|
"default": "./dist/styles/*"
|
|
@@ -33,6 +23,8 @@
|
|
|
33
23
|
"types": "./dist/index.d.ts",
|
|
34
24
|
"files": [
|
|
35
25
|
"dist",
|
|
26
|
+
"tailwindcss",
|
|
27
|
+
"src",
|
|
36
28
|
"README.md"
|
|
37
29
|
],
|
|
38
30
|
"sideEffects": false,
|
|
@@ -44,7 +36,7 @@
|
|
|
44
36
|
"react-markdown": "^9.0.1"
|
|
45
37
|
},
|
|
46
38
|
"peerDependencies": {
|
|
47
|
-
"@assistant-ui/react": "^0.5.
|
|
39
|
+
"@assistant-ui/react": "^0.5.93",
|
|
48
40
|
"@types/react": "*",
|
|
49
41
|
"react": "^18 || ^19",
|
|
50
42
|
"tailwindcss": "^3.4.4"
|
|
@@ -70,8 +62,9 @@
|
|
|
70
62
|
"tailwindcss-animate": "^1.0.7",
|
|
71
63
|
"tsup": "8.3.0",
|
|
72
64
|
"tsx": "^4.19.1",
|
|
73
|
-
"@assistant-ui/
|
|
74
|
-
"@assistant-ui/tsconfig": "0.0.0"
|
|
65
|
+
"@assistant-ui/react": "0.5.93",
|
|
66
|
+
"@assistant-ui/tsconfig": "0.0.0",
|
|
67
|
+
"@assistant-ui/tailwindcss-transformer": "0.1.0"
|
|
75
68
|
},
|
|
76
69
|
"publishConfig": {
|
|
77
70
|
"access": "public",
|
|
@@ -86,6 +79,7 @@
|
|
|
86
79
|
"url": "https://github.com/Yonom/assistant-ui/issues"
|
|
87
80
|
},
|
|
88
81
|
"scripts": {
|
|
89
|
-
"build": "tsx scripts/build.mts"
|
|
82
|
+
"build": "tsx scripts/build.mts && pnpm run build:declarations",
|
|
83
|
+
"build:declarations": "tsc -p tsconfig.declarations.json"
|
|
90
84
|
}
|
|
91
85
|
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export {
|
|
2
|
+
MarkdownTextPrimitive,
|
|
3
|
+
type MarkdownTextPrimitiveProps,
|
|
4
|
+
} from "./primitives/MarkdownText";
|
|
5
|
+
|
|
6
|
+
export type {
|
|
7
|
+
CodeHeaderProps,
|
|
8
|
+
SyntaxHighlighterProps,
|
|
9
|
+
} from "./overrides/types";
|
|
10
|
+
|
|
11
|
+
export { useIsMarkdownCodeBlock } from "./overrides/PreOverride";
|
|
12
|
+
|
|
13
|
+
export {
|
|
14
|
+
makeMarkdownText,
|
|
15
|
+
type MakeMarkdownTextProps,
|
|
16
|
+
} from "./ui/markdown-text";
|
|
17
|
+
|
|
18
|
+
export { CodeHeader } from "./ui/code-header";
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { ComponentType, FC, useMemo } from "react";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
CodeComponent,
|
|
5
|
+
CodeHeaderProps,
|
|
6
|
+
PreComponent,
|
|
7
|
+
SyntaxHighlighterProps,
|
|
8
|
+
} from "./types";
|
|
9
|
+
import { DefaultCodeBlockContent } from "./defaultComponents";
|
|
10
|
+
|
|
11
|
+
export type CodeBlockProps = {
|
|
12
|
+
language: string;
|
|
13
|
+
code: string;
|
|
14
|
+
components: {
|
|
15
|
+
Pre: PreComponent;
|
|
16
|
+
Code: CodeComponent;
|
|
17
|
+
CodeHeader: ComponentType<CodeHeaderProps>;
|
|
18
|
+
SyntaxHighlighter: ComponentType<SyntaxHighlighterProps>;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const DefaultCodeBlock: FC<CodeBlockProps> = ({
|
|
23
|
+
components: { Pre, Code, SyntaxHighlighter, CodeHeader },
|
|
24
|
+
language,
|
|
25
|
+
code,
|
|
26
|
+
}) => {
|
|
27
|
+
const components = useMemo(() => ({ Pre, Code }), [Pre, Code]);
|
|
28
|
+
|
|
29
|
+
const SH = !!language ? SyntaxHighlighter : DefaultCodeBlockContent;
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<>
|
|
33
|
+
<CodeHeader language={language} code={code} />
|
|
34
|
+
<SH
|
|
35
|
+
components={components}
|
|
36
|
+
language={language ?? "unknown"}
|
|
37
|
+
code={code}
|
|
38
|
+
/>
|
|
39
|
+
</>
|
|
40
|
+
);
|
|
41
|
+
};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { ComponentPropsWithoutRef, ComponentType, FC, useContext } from "react";
|
|
2
|
+
import { PreContext } from "./PreOverride";
|
|
3
|
+
import {
|
|
4
|
+
CodeComponent,
|
|
5
|
+
CodeHeaderProps,
|
|
6
|
+
PreComponent,
|
|
7
|
+
SyntaxHighlighterProps,
|
|
8
|
+
} from "./types";
|
|
9
|
+
import { DefaultCodeBlock } from "./CodeBlock";
|
|
10
|
+
import { useCallbackRef } from "@radix-ui/react-use-callback-ref";
|
|
11
|
+
import { withDefaultProps } from "./withDefaults";
|
|
12
|
+
import { DefaultCodeBlockContent } from "./defaultComponents";
|
|
13
|
+
|
|
14
|
+
const CodeBlockOverride: FC<CodeOverrideProps> = ({
|
|
15
|
+
components: {
|
|
16
|
+
Pre,
|
|
17
|
+
Code,
|
|
18
|
+
SyntaxHighlighter: FallbackSyntaxHighlighter,
|
|
19
|
+
CodeHeader: FallbackCodeHeader,
|
|
20
|
+
by_language = {},
|
|
21
|
+
},
|
|
22
|
+
children,
|
|
23
|
+
...codeProps
|
|
24
|
+
}) => {
|
|
25
|
+
const preProps = useContext(PreContext)!;
|
|
26
|
+
const getPreProps = withDefaultProps<any>(preProps);
|
|
27
|
+
const WrappedPre: PreComponent = useCallbackRef((props) => (
|
|
28
|
+
<Pre {...getPreProps(props)} />
|
|
29
|
+
));
|
|
30
|
+
|
|
31
|
+
const getCodeProps = withDefaultProps<any>(codeProps);
|
|
32
|
+
const WrappedCode: CodeComponent = useCallbackRef((props) => (
|
|
33
|
+
<Code {...getCodeProps(props)} />
|
|
34
|
+
));
|
|
35
|
+
|
|
36
|
+
const language = /language-(\w+)/.exec(codeProps.className || "")?.[1] ?? "";
|
|
37
|
+
|
|
38
|
+
// if the code content is not string (due to rehype plugins), return a default code block
|
|
39
|
+
if (typeof children !== "string") {
|
|
40
|
+
return (
|
|
41
|
+
<DefaultCodeBlockContent
|
|
42
|
+
components={{ Pre: WrappedPre, Code: WrappedCode }}
|
|
43
|
+
code={children}
|
|
44
|
+
/>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const SyntaxHighlighter: ComponentType<SyntaxHighlighterProps> =
|
|
49
|
+
by_language[language]?.SyntaxHighlighter ?? FallbackSyntaxHighlighter;
|
|
50
|
+
|
|
51
|
+
const CodeHeader: ComponentType<CodeHeaderProps> =
|
|
52
|
+
by_language[language]?.CodeHeader ?? FallbackCodeHeader;
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<DefaultCodeBlock
|
|
56
|
+
components={{
|
|
57
|
+
Pre: WrappedPre,
|
|
58
|
+
Code: WrappedCode,
|
|
59
|
+
SyntaxHighlighter,
|
|
60
|
+
CodeHeader,
|
|
61
|
+
}}
|
|
62
|
+
language={language || "unknown"}
|
|
63
|
+
code={children}
|
|
64
|
+
/>
|
|
65
|
+
);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export type CodeOverrideProps = ComponentPropsWithoutRef<CodeComponent> & {
|
|
69
|
+
components: {
|
|
70
|
+
Pre: PreComponent;
|
|
71
|
+
Code: CodeComponent;
|
|
72
|
+
CodeHeader: ComponentType<CodeHeaderProps>;
|
|
73
|
+
SyntaxHighlighter: ComponentType<SyntaxHighlighterProps>;
|
|
74
|
+
by_language?: Record<
|
|
75
|
+
string,
|
|
76
|
+
{
|
|
77
|
+
CodeHeader?: ComponentType<CodeHeaderProps>;
|
|
78
|
+
SyntaxHighlighter?: ComponentType<SyntaxHighlighterProps>;
|
|
79
|
+
}
|
|
80
|
+
>;
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export const CodeOverride: FC<CodeOverrideProps> = ({
|
|
85
|
+
components,
|
|
86
|
+
...props
|
|
87
|
+
}) => {
|
|
88
|
+
const preProps = useContext(PreContext);
|
|
89
|
+
if (!preProps) return <components.Code {...(props as any)} />;
|
|
90
|
+
return <CodeBlockOverride components={components} {...props} />;
|
|
91
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createContext, ComponentPropsWithoutRef, useContext } from "react";
|
|
2
|
+
import { PreComponent } from "./types";
|
|
3
|
+
|
|
4
|
+
export const PreContext = createContext<Omit<
|
|
5
|
+
ComponentPropsWithoutRef<PreComponent>,
|
|
6
|
+
"children"
|
|
7
|
+
> | null>(null);
|
|
8
|
+
|
|
9
|
+
export const useIsMarkdownCodeBlock = () => {
|
|
10
|
+
return useContext(PreContext) !== null;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const PreOverride: PreComponent = ({ children, ...rest }) => {
|
|
14
|
+
return <PreContext.Provider value={rest}>{children}</PreContext.Provider>;
|
|
15
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ComponentType, ReactNode } from "react";
|
|
2
|
+
import { PreComponent, CodeComponent, CodeHeaderProps } from "./types";
|
|
3
|
+
|
|
4
|
+
export const DefaultPre: PreComponent = ({ node, ...rest }) => (
|
|
5
|
+
<pre {...rest} />
|
|
6
|
+
);
|
|
7
|
+
|
|
8
|
+
export const DefaultCode: CodeComponent = ({ node, ...rest }) => (
|
|
9
|
+
<code {...rest} />
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
export const DefaultCodeBlockContent: ComponentType<{
|
|
13
|
+
components: { Pre: PreComponent; Code: CodeComponent };
|
|
14
|
+
code: string | ReactNode | undefined;
|
|
15
|
+
}> = ({ components: { Pre, Code }, code }) => (
|
|
16
|
+
<Pre>
|
|
17
|
+
<Code>{code}</Code>
|
|
18
|
+
</Pre>
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
export const DefaultCodeHeader: ComponentType<CodeHeaderProps> = () => null;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Options } from "react-markdown";
|
|
2
|
+
|
|
3
|
+
export type PreComponent = NonNullable<
|
|
4
|
+
NonNullable<Options["components"]>["pre"]
|
|
5
|
+
>;
|
|
6
|
+
export type CodeComponent = NonNullable<
|
|
7
|
+
NonNullable<Options["components"]>["code"]
|
|
8
|
+
>;
|
|
9
|
+
|
|
10
|
+
export type CodeHeaderProps = {
|
|
11
|
+
language: string | undefined;
|
|
12
|
+
code: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export type SyntaxHighlighterProps = {
|
|
16
|
+
components: {
|
|
17
|
+
Pre: PreComponent;
|
|
18
|
+
Code: CodeComponent;
|
|
19
|
+
};
|
|
20
|
+
language: string;
|
|
21
|
+
code: string;
|
|
22
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import classNames from "classnames";
|
|
2
|
+
|
|
3
|
+
export const withDefaultProps =
|
|
4
|
+
<TProps extends { className?: string | undefined }>({
|
|
5
|
+
className,
|
|
6
|
+
...defaultProps
|
|
7
|
+
}: Partial<TProps>) =>
|
|
8
|
+
({ className: classNameProp, ...props }: TProps) => {
|
|
9
|
+
return {
|
|
10
|
+
className: classNames(className, classNameProp),
|
|
11
|
+
...defaultProps,
|
|
12
|
+
...props,
|
|
13
|
+
} as TProps;
|
|
14
|
+
};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { INTERNAL, useContentPartText } from "@assistant-ui/react";
|
|
4
|
+
import {
|
|
5
|
+
ElementRef,
|
|
6
|
+
ElementType,
|
|
7
|
+
forwardRef,
|
|
8
|
+
ForwardRefExoticComponent,
|
|
9
|
+
RefAttributes,
|
|
10
|
+
type ComponentPropsWithoutRef,
|
|
11
|
+
type ComponentType,
|
|
12
|
+
} from "react";
|
|
13
|
+
import ReactMarkdown, { type Options } from "react-markdown";
|
|
14
|
+
import { SyntaxHighlighterProps, CodeHeaderProps } from "../overrides/types";
|
|
15
|
+
import { PreOverride } from "../overrides/PreOverride";
|
|
16
|
+
import {
|
|
17
|
+
DefaultPre,
|
|
18
|
+
DefaultCode,
|
|
19
|
+
DefaultCodeBlockContent,
|
|
20
|
+
DefaultCodeHeader,
|
|
21
|
+
} from "../overrides/defaultComponents";
|
|
22
|
+
import { useCallbackRef } from "@radix-ui/react-use-callback-ref";
|
|
23
|
+
import { CodeOverride } from "../overrides/CodeOverride";
|
|
24
|
+
import { Primitive } from "@radix-ui/react-primitive";
|
|
25
|
+
import classNames from "classnames";
|
|
26
|
+
|
|
27
|
+
const { useSmooth } = INTERNAL;
|
|
28
|
+
|
|
29
|
+
type MarkdownTextPrimitiveElement = ElementRef<typeof Primitive.div>;
|
|
30
|
+
type PrimitiveDivProps = ComponentPropsWithoutRef<typeof Primitive.div>;
|
|
31
|
+
|
|
32
|
+
export type MarkdownTextPrimitiveProps = Omit<
|
|
33
|
+
Options,
|
|
34
|
+
"components" | "children"
|
|
35
|
+
> & {
|
|
36
|
+
containerProps?: Omit<PrimitiveDivProps, "children" | "asChild">;
|
|
37
|
+
containerComponent?: ElementType;
|
|
38
|
+
components?: NonNullable<Options["components"]> & {
|
|
39
|
+
SyntaxHighlighter?: ComponentType<SyntaxHighlighterProps>;
|
|
40
|
+
CodeHeader?: ComponentType<CodeHeaderProps>;
|
|
41
|
+
by_language?: Record<
|
|
42
|
+
string,
|
|
43
|
+
{
|
|
44
|
+
CodeHeader?: ComponentType<CodeHeaderProps>;
|
|
45
|
+
SyntaxHighlighter?: ComponentType<SyntaxHighlighterProps>;
|
|
46
|
+
}
|
|
47
|
+
>;
|
|
48
|
+
};
|
|
49
|
+
smooth?: boolean;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const MarkdownTextPrimitive: ForwardRefExoticComponent<MarkdownTextPrimitiveProps> &
|
|
53
|
+
RefAttributes<MarkdownTextPrimitiveElement> = forwardRef<
|
|
54
|
+
MarkdownTextPrimitiveElement,
|
|
55
|
+
MarkdownTextPrimitiveProps
|
|
56
|
+
>(
|
|
57
|
+
(
|
|
58
|
+
{
|
|
59
|
+
components: userComponents,
|
|
60
|
+
className,
|
|
61
|
+
containerProps,
|
|
62
|
+
containerComponent: Container = "div",
|
|
63
|
+
...rest
|
|
64
|
+
},
|
|
65
|
+
forwardedRef,
|
|
66
|
+
smooth = true,
|
|
67
|
+
) => {
|
|
68
|
+
const { text, status } = useSmooth(useContentPartText(), smooth);
|
|
69
|
+
|
|
70
|
+
const {
|
|
71
|
+
pre = DefaultPre,
|
|
72
|
+
code = DefaultCode,
|
|
73
|
+
SyntaxHighlighter = DefaultCodeBlockContent,
|
|
74
|
+
CodeHeader = DefaultCodeHeader,
|
|
75
|
+
by_language,
|
|
76
|
+
...componentsRest
|
|
77
|
+
} = userComponents ?? {};
|
|
78
|
+
const components: typeof userComponents = {
|
|
79
|
+
...componentsRest,
|
|
80
|
+
pre: PreOverride,
|
|
81
|
+
code: useCallbackRef((props) => (
|
|
82
|
+
<CodeOverride
|
|
83
|
+
components={{
|
|
84
|
+
Pre: pre,
|
|
85
|
+
Code: code,
|
|
86
|
+
SyntaxHighlighter,
|
|
87
|
+
CodeHeader,
|
|
88
|
+
by_language,
|
|
89
|
+
}}
|
|
90
|
+
{...props}
|
|
91
|
+
/>
|
|
92
|
+
)),
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
return (
|
|
96
|
+
<Container
|
|
97
|
+
data-status={status.type}
|
|
98
|
+
{...containerProps}
|
|
99
|
+
className={classNames(className, containerProps?.className)}
|
|
100
|
+
ref={forwardedRef}
|
|
101
|
+
>
|
|
102
|
+
<ReactMarkdown components={components} {...rest}>
|
|
103
|
+
{text}
|
|
104
|
+
</ReactMarkdown>
|
|
105
|
+
</Container>
|
|
106
|
+
);
|
|
107
|
+
},
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
MarkdownTextPrimitive.displayName = "MarkdownTextPrimitive";
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/* running indicator */
|
|
2
|
+
:where(.aui-md-running):empty::after,
|
|
3
|
+
:where(.aui-md-running) > :where(:not(ol):not(ul):not(pre)):last-child::after,
|
|
4
|
+
:where(.aui-md-running) > pre:last-child code::after,
|
|
5
|
+
:where(.aui-md-running)
|
|
6
|
+
> :where(:is(ol, ul):last-child)
|
|
7
|
+
> :where(li:last-child:not(:has(* > li)))::after,
|
|
8
|
+
:where(.aui-md-running)
|
|
9
|
+
> :where(:is(ol, ul):last-child)
|
|
10
|
+
> :where(li:last-child)
|
|
11
|
+
> :where(:is(ol, ul):last-child)
|
|
12
|
+
> :where(li:last-child:not(:has(* > li)))::after,
|
|
13
|
+
:where(.aui-md-running)
|
|
14
|
+
> :where(:is(ol, ul):last-child)
|
|
15
|
+
> :where(li:last-child)
|
|
16
|
+
> :where(:is(ol, ul):last-child)
|
|
17
|
+
> :where(li:last-child)
|
|
18
|
+
> :where(:is(ol, ul):last-child)
|
|
19
|
+
> :where(li:last-child)::after {
|
|
20
|
+
@apply animate-pulse font-sans content-['\25CF'] ltr:ml-1 rtl:mr-1;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/* typography */
|
|
24
|
+
.aui-md-h1 {
|
|
25
|
+
@apply mb-8 scroll-m-20 text-4xl font-extrabold tracking-tight last:mb-0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.aui-md-h2 {
|
|
29
|
+
@apply mb-4 mt-8 scroll-m-20 text-3xl font-semibold tracking-tight first:mt-0 last:mb-0;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.aui-md-h3 {
|
|
33
|
+
@apply mb-4 mt-6 scroll-m-20 text-2xl font-semibold tracking-tight first:mt-0 last:mb-0;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.aui-md-h4 {
|
|
37
|
+
@apply mb-4 mt-6 scroll-m-20 text-xl font-semibold tracking-tight first:mt-0 last:mb-0;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.aui-md-h5 {
|
|
41
|
+
@apply my-4 text-lg font-semibold first:mt-0 last:mb-0;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.aui-md-h6 {
|
|
45
|
+
@apply my-4 font-semibold first:mt-0 last:mb-0;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.aui-md-p {
|
|
49
|
+
@apply mb-5 mt-5 leading-7 first:mt-0 last:mb-0;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.aui-md-a {
|
|
53
|
+
@apply text-aui-primary font-medium underline underline-offset-4;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.aui-md-blockquote {
|
|
57
|
+
@apply border-l-2 pl-6 italic;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.aui-md-ul {
|
|
61
|
+
@apply my-5 ml-6 list-disc [&>li]:mt-2;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.aui-md-ol {
|
|
65
|
+
@apply my-5 ml-6 list-decimal [&>li]:mt-2;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.aui-md-hr {
|
|
69
|
+
@apply my-5 border-b;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.aui-md-table {
|
|
73
|
+
@apply my-5 w-full border-separate border-spacing-0 overflow-y-auto;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.aui-md-th {
|
|
77
|
+
@apply bg-aui-muted px-4 py-2 text-left font-bold first:rounded-tl-lg last:rounded-tr-lg [&[align=center]]:text-center [&[align=right]]:text-right;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.aui-md-td {
|
|
81
|
+
@apply border-b border-l px-4 py-2 text-left last:border-r [&[align=center]]:text-center [&[align=right]]:text-right;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.aui-md-tr {
|
|
85
|
+
@apply m-0 border-b p-0 first:border-t [&:last-child>td:first-child]:rounded-bl-lg [&:last-child>td:last-child]:rounded-br-lg;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.aui-md-sup {
|
|
89
|
+
@apply [&>a]:text-xs [&>a]:no-underline;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.aui-md-pre {
|
|
93
|
+
@apply overflow-x-auto rounded-b-lg bg-black p-4 text-white;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.aui-md-inline-code {
|
|
97
|
+
@apply bg-aui-muted rounded border font-semibold;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.aui-code-header-root {
|
|
101
|
+
@apply flex items-center justify-between gap-4 rounded-t-lg bg-zinc-900 px-4 py-2 text-sm font-semibold text-white;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.aui-code-header-language {
|
|
105
|
+
@apply lowercase [&>span]:text-xs;
|
|
106
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { FC } from "react";
|
|
2
|
+
import { CheckIcon, CopyIcon } from "lucide-react";
|
|
3
|
+
import { INTERNAL, useThreadConfig } from "@assistant-ui/react";
|
|
4
|
+
|
|
5
|
+
import { CodeHeaderProps } from "../overrides/types";
|
|
6
|
+
import { useCopyToClipboard } from "./useCopyToClipboard";
|
|
7
|
+
|
|
8
|
+
const { TooltipIconButton } = INTERNAL;
|
|
9
|
+
|
|
10
|
+
export const CodeHeader: FC<CodeHeaderProps> = ({ language, code }) => {
|
|
11
|
+
const {
|
|
12
|
+
strings: {
|
|
13
|
+
code: { header: { copy: { tooltip = "Copy" } = {} } = {} } = {},
|
|
14
|
+
} = {},
|
|
15
|
+
} = useThreadConfig();
|
|
16
|
+
|
|
17
|
+
const { isCopied, copyToClipboard } = useCopyToClipboard();
|
|
18
|
+
const onCopy = () => {
|
|
19
|
+
if (!code || isCopied) return;
|
|
20
|
+
copyToClipboard(code);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<div className="aui-code-header-root">
|
|
25
|
+
<span className="aui-code-header-language">{language}</span>
|
|
26
|
+
<TooltipIconButton tooltip={tooltip} onClick={onCopy}>
|
|
27
|
+
{!isCopied && <CopyIcon />}
|
|
28
|
+
{isCopied && <CheckIcon />}
|
|
29
|
+
</TooltipIconButton>
|
|
30
|
+
</div>
|
|
31
|
+
);
|
|
32
|
+
};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { FC, memo } from "react";
|
|
2
|
+
import { CodeHeader } from "./code-header";
|
|
3
|
+
import classNames from "classnames";
|
|
4
|
+
import {
|
|
5
|
+
MarkdownTextPrimitive,
|
|
6
|
+
MarkdownTextPrimitiveProps,
|
|
7
|
+
} from "../primitives/MarkdownText";
|
|
8
|
+
import { INTERNAL } from "@assistant-ui/react";
|
|
9
|
+
import { useIsMarkdownCodeBlock } from "../overrides/PreOverride";
|
|
10
|
+
|
|
11
|
+
const { withSmoothContextProvider, useSmoothStatus } = INTERNAL;
|
|
12
|
+
|
|
13
|
+
export type MakeMarkdownTextProps = MarkdownTextPrimitiveProps;
|
|
14
|
+
|
|
15
|
+
const defaultComponents: MakeMarkdownTextProps["components"] = {
|
|
16
|
+
h1: ({ node, className, ...props }) => (
|
|
17
|
+
<h1 className={classNames("aui-md-h1", className)} {...props} />
|
|
18
|
+
),
|
|
19
|
+
h2: ({ node, className, ...props }) => (
|
|
20
|
+
<h2 className={classNames("aui-md-h2", className)} {...props} />
|
|
21
|
+
),
|
|
22
|
+
h3: ({ node, className, ...props }) => (
|
|
23
|
+
<h3 className={classNames("aui-md-h3", className)} {...props} />
|
|
24
|
+
),
|
|
25
|
+
h4: ({ node, className, ...props }) => (
|
|
26
|
+
<h4 className={classNames("aui-md-h4", className)} {...props} />
|
|
27
|
+
),
|
|
28
|
+
h5: ({ node, className, ...props }) => (
|
|
29
|
+
<h5 className={classNames("aui-md-h5", className)} {...props} />
|
|
30
|
+
),
|
|
31
|
+
h6: ({ node, className, ...props }) => (
|
|
32
|
+
<h6 className={classNames("aui-md-h6", className)} {...props} />
|
|
33
|
+
),
|
|
34
|
+
p: ({ node, className, ...props }) => (
|
|
35
|
+
<p className={classNames("aui-md-p", className)} {...props} />
|
|
36
|
+
),
|
|
37
|
+
a: ({ node, className, ...props }) => (
|
|
38
|
+
<a className={classNames("aui-md-a", className)} {...props} />
|
|
39
|
+
),
|
|
40
|
+
blockquote: ({ node, className, ...props }) => (
|
|
41
|
+
<blockquote
|
|
42
|
+
className={classNames("aui-md-blockquote", className)}
|
|
43
|
+
{...props}
|
|
44
|
+
/>
|
|
45
|
+
),
|
|
46
|
+
ul: ({ node, className, ...props }) => (
|
|
47
|
+
<ul className={classNames("aui-md-ul", className)} {...props} />
|
|
48
|
+
),
|
|
49
|
+
ol: ({ node, className, ...props }) => (
|
|
50
|
+
<ol className={classNames("aui-md-ol", className)} {...props} />
|
|
51
|
+
),
|
|
52
|
+
hr: ({ node, className, ...props }) => (
|
|
53
|
+
<hr className={classNames("aui-md-hr", className)} {...props} />
|
|
54
|
+
),
|
|
55
|
+
table: ({ node, className, ...props }) => (
|
|
56
|
+
<table className={classNames("aui-md-table", className)} {...props} />
|
|
57
|
+
),
|
|
58
|
+
th: ({ node, className, ...props }) => (
|
|
59
|
+
<th className={classNames("aui-md-th", className)} {...props} />
|
|
60
|
+
),
|
|
61
|
+
td: ({ node, className, ...props }) => (
|
|
62
|
+
<td className={classNames("aui-md-td", className)} {...props} />
|
|
63
|
+
),
|
|
64
|
+
tr: ({ node, className, ...props }) => (
|
|
65
|
+
<tr className={classNames("aui-md-tr", className)} {...props} />
|
|
66
|
+
),
|
|
67
|
+
sup: ({ node, className, ...props }) => (
|
|
68
|
+
<sup className={classNames("aui-md-sup", className)} {...props} />
|
|
69
|
+
),
|
|
70
|
+
pre: ({ node, className, ...props }) => (
|
|
71
|
+
<pre className={classNames("aui-md-pre", className)} {...props} />
|
|
72
|
+
),
|
|
73
|
+
code: ({ node, className, ...props }) => {
|
|
74
|
+
const isCodeBlock = useIsMarkdownCodeBlock();
|
|
75
|
+
return (
|
|
76
|
+
<code
|
|
77
|
+
className={classNames(!isCodeBlock && "aui-md-inline-code", className)}
|
|
78
|
+
{...props}
|
|
79
|
+
/>
|
|
80
|
+
);
|
|
81
|
+
},
|
|
82
|
+
CodeHeader,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export const makeMarkdownText = ({
|
|
86
|
+
className,
|
|
87
|
+
components: userComponents,
|
|
88
|
+
...rest
|
|
89
|
+
}: MakeMarkdownTextProps = {}) => {
|
|
90
|
+
const components = {
|
|
91
|
+
...defaultComponents,
|
|
92
|
+
...Object.fromEntries(
|
|
93
|
+
// ignore undefined values, so undefined values do not override default components
|
|
94
|
+
Object.entries(userComponents ?? {}).filter(([_, v]) => v !== undefined),
|
|
95
|
+
),
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const MarkdownTextImpl: FC = () => {
|
|
99
|
+
const status = useSmoothStatus();
|
|
100
|
+
return (
|
|
101
|
+
<MarkdownTextPrimitive
|
|
102
|
+
components={components}
|
|
103
|
+
{...rest}
|
|
104
|
+
className={classNames(
|
|
105
|
+
status.type === "running" && "aui-md-running",
|
|
106
|
+
className,
|
|
107
|
+
)}
|
|
108
|
+
/>
|
|
109
|
+
);
|
|
110
|
+
};
|
|
111
|
+
MarkdownTextImpl.displayName = "MarkdownText";
|
|
112
|
+
|
|
113
|
+
return memo(withSmoothContextProvider(MarkdownTextImpl), () => true);
|
|
114
|
+
};
|