@blocklet/pages-kit 0.4.116 → 0.4.117
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/lib/cjs/builtin/async/rehype-mermaid.js +26 -0
- package/lib/cjs/builtin/markdown/action-button.js +41 -0
- package/lib/cjs/builtin/markdown/index.js +13 -0
- package/lib/cjs/builtin/markdown/loading-button.js +19 -0
- package/lib/cjs/builtin/markdown/markdown-context.js +17 -0
- package/lib/cjs/builtin/markdown/markdown-renderer.js +156 -0
- package/lib/cjs/tsconfig.tsbuildinfo +1 -1
- package/lib/esm/builtin/async/rehype-mermaid.js +1 -0
- package/lib/esm/builtin/markdown/action-button.js +35 -0
- package/lib/esm/builtin/markdown/index.js +4 -0
- package/lib/esm/builtin/markdown/loading-button.js +17 -0
- package/lib/esm/builtin/markdown/markdown-context.js +12 -0
- package/lib/esm/builtin/markdown/markdown-renderer.js +128 -0
- package/lib/esm/tsconfig.tsbuildinfo +1 -1
- package/lib/types/builtin/async/rehype-mermaid.d.ts +2 -0
- package/lib/types/builtin/markdown/action-button.d.ts +13 -0
- package/lib/types/builtin/markdown/index.d.ts +5 -0
- package/lib/types/builtin/markdown/loading-button.d.ts +3 -0
- package/lib/types/builtin/markdown/markdown-context.d.ts +16 -0
- package/lib/types/builtin/markdown/markdown-renderer.d.ts +12 -0
- package/lib/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +9 -8
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default () => import('rehype-mermaid');
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Icon } from '@iconify/react';
|
|
3
|
+
import { Box, Tooltip } from '@mui/material';
|
|
4
|
+
import { useRef, useState } from 'react';
|
|
5
|
+
import LoadingButton from './loading-button';
|
|
6
|
+
export default function ActionButton({ tip, tipSucceed, title, titleSucceed, icon, iconSucceed, autoReset, placement = 'top', ...props }) {
|
|
7
|
+
const [active, setActive] = useState(false);
|
|
8
|
+
const [error, setError] = useState();
|
|
9
|
+
const timer = useRef();
|
|
10
|
+
const onClose = () => {
|
|
11
|
+
setError(undefined);
|
|
12
|
+
if (autoReset) {
|
|
13
|
+
timer.current = window.setTimeout(() => {
|
|
14
|
+
setActive(false);
|
|
15
|
+
}, 3000);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
const onOpen = () => {
|
|
19
|
+
clearTimeout(timer.current);
|
|
20
|
+
};
|
|
21
|
+
const realIcon = active ? iconSucceed : icon;
|
|
22
|
+
const toolTipTitleText = error ? _jsx(Box, { color: "error", children: error.message }) : (active && tipSucceed) || tip;
|
|
23
|
+
const buttonText = active ? titleSucceed : title;
|
|
24
|
+
return (_jsx(Tooltip, { title: toolTipTitleText, disableInteractive: true, placement: placement, onClose: onClose, onOpen: onOpen, children: _jsx("span", { children: _jsx(LoadingButton, { startIcon: realIcon && (typeof realIcon === 'string' ? _jsx(Icon, { icon: realIcon }) : realIcon), loadingPosition: realIcon ? 'start' : undefined, ...props, onClick: async (e) => {
|
|
25
|
+
if (!props.onClick)
|
|
26
|
+
return;
|
|
27
|
+
try {
|
|
28
|
+
await props.onClick(e);
|
|
29
|
+
setActive(true);
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
setError(error);
|
|
33
|
+
}
|
|
34
|
+
}, children: buttonText }) }) }));
|
|
35
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { LoadingButton as MuiLoadingButton } from '@mui/lab';
|
|
3
|
+
import { forwardRef, useCallback, useState } from 'react';
|
|
4
|
+
const LoadingButton = forwardRef(({ onClick, ...props }, ref) => {
|
|
5
|
+
const [loading, setLoading] = useState(false);
|
|
6
|
+
const handleClick = useCallback(async (e) => {
|
|
7
|
+
try {
|
|
8
|
+
setLoading(true);
|
|
9
|
+
await onClick?.(e);
|
|
10
|
+
}
|
|
11
|
+
finally {
|
|
12
|
+
setLoading(false);
|
|
13
|
+
}
|
|
14
|
+
}, [onClick]);
|
|
15
|
+
return _jsx(MuiLoadingButton, { ref: ref, ...props, loading: props.loading || loading, onClick: handleClick });
|
|
16
|
+
});
|
|
17
|
+
export default LoadingButton;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext } from 'react';
|
|
3
|
+
const defaultOptions = {
|
|
4
|
+
codeOptions: {
|
|
5
|
+
showActionButton: true,
|
|
6
|
+
},
|
|
7
|
+
};
|
|
8
|
+
export const MarkdownContext = createContext(defaultOptions);
|
|
9
|
+
export const useMarkdownOptions = () => useContext(MarkdownContext);
|
|
10
|
+
export function MarkdownProvider({ children, options = defaultOptions }) {
|
|
11
|
+
return _jsx(MarkdownContext.Provider, { value: options, children: children });
|
|
12
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Icon } from '@iconify/react';
|
|
3
|
+
import { Box, Stack, styled } from '@mui/material';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import { MarkdownHooks } from 'react-markdown';
|
|
6
|
+
import rehypeMermaid from 'rehype-mermaid';
|
|
7
|
+
import remarkGfm from 'remark-gfm';
|
|
8
|
+
import ActionButton from './action-button';
|
|
9
|
+
import { MarkdownProvider, useMarkdownOptions } from './markdown-context';
|
|
10
|
+
const ReactSyntaxHighlighter = React.lazy(() => import('react-syntax-highlighter').then((m) => ({ default: m.Prism })));
|
|
11
|
+
const matchLanguage = (className) => {
|
|
12
|
+
const match = /language-(\w+)/.exec(className || '');
|
|
13
|
+
return match?.[1];
|
|
14
|
+
};
|
|
15
|
+
function MarkdownCode({ node, inline, className, children, ...props }) {
|
|
16
|
+
const { codeOptions } = useMarkdownOptions();
|
|
17
|
+
if (!children)
|
|
18
|
+
return null;
|
|
19
|
+
const language = matchLanguage(className);
|
|
20
|
+
return !inline ? (_jsx(Box, { component: ReactSyntaxHighlighter, language: language, style: codeOptions?.theme, showLineNumbers: true, ...props, sx: { borderRadius: 1 }, children: String(children).replace(/\n$/, '') })) : (_jsx(Box, { component: "code", className: className, ...props, children: children }));
|
|
21
|
+
}
|
|
22
|
+
function MarkdownTable({ className, children }) {
|
|
23
|
+
return (_jsx(Box, { sx: { overflow: 'auto', my: 1 }, children: _jsx("table", { className: className, children: children }) }));
|
|
24
|
+
}
|
|
25
|
+
function MarkdownPre({ children }) {
|
|
26
|
+
const { codeOptions } = useMarkdownOptions();
|
|
27
|
+
const childrenProps = children?.props;
|
|
28
|
+
if (!childrenProps?.children)
|
|
29
|
+
return null;
|
|
30
|
+
const language = matchLanguage(childrenProps.className);
|
|
31
|
+
const showActionButton = codeOptions?.showActionButton !== false;
|
|
32
|
+
if (!showActionButton) {
|
|
33
|
+
return children;
|
|
34
|
+
}
|
|
35
|
+
return (_jsxs(Box, { component: "div", sx: {
|
|
36
|
+
fontSize: 14,
|
|
37
|
+
borderRadius: 1,
|
|
38
|
+
bgcolor: 'rgb(245, 242, 240)',
|
|
39
|
+
'> pre': { mt: '0 !important' },
|
|
40
|
+
}, children: [_jsxs(Stack, { direction: "row", alignItems: "center", p: 0.5, pl: 1.5, borderBottom: 1, borderColor: "grey.200", children: [_jsx(Box, { children: language }), _jsx(Box, { flex: 1 }), _jsx(ActionButton, { autoReset: true, title: _jsx(Icon, { icon: "tabler:copy" }), titleSucceed: _jsx(Icon, { icon: "tabler:copy-check" }), sx: { minWidth: 32, minHeight: 32, p: 0, fontSize: 18 }, onClick: () => {
|
|
41
|
+
window.navigator.clipboard.writeText(childrenProps.children);
|
|
42
|
+
} })] }), children] }));
|
|
43
|
+
}
|
|
44
|
+
function MarkdownRenderer(props) {
|
|
45
|
+
const { codeOptions = { showActionButton: true }, ...rest } = props;
|
|
46
|
+
const options = {
|
|
47
|
+
codeOptions,
|
|
48
|
+
};
|
|
49
|
+
return (_jsx(StyledBox, { children: _jsx(MarkdownProvider, { options: options, children: _jsx(MarkdownHooks, { ...rest, remarkPlugins: [remarkGfm], rehypePlugins: [rehypeMermaid], components: {
|
|
50
|
+
pre: MarkdownPre,
|
|
51
|
+
code: MarkdownCode,
|
|
52
|
+
table: MarkdownTable,
|
|
53
|
+
} }) }) }));
|
|
54
|
+
}
|
|
55
|
+
const StyledBox = styled(Box) `
|
|
56
|
+
width: 100%;
|
|
57
|
+
overflow: hidden;
|
|
58
|
+
word-break: break-word;
|
|
59
|
+
|
|
60
|
+
> * {
|
|
61
|
+
&:first-child /* emotion-disable-server-rendering-unsafe-selector-warning-please-do-not-use-this-the-warning-exists-for-a-reason */ {
|
|
62
|
+
margin-top: 0;
|
|
63
|
+
}
|
|
64
|
+
&:last-child /* emotion-disable-server-rendering-unsafe-selector-warning-please-do-not-use-this-the-warning-exists-for-a-reason */ {
|
|
65
|
+
margin-bottom: 0;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
pre {
|
|
70
|
+
overflow: auto;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
li {
|
|
74
|
+
margin: 0;
|
|
75
|
+
padding: 0;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
li p {
|
|
79
|
+
display: inline-block;
|
|
80
|
+
vertical-align: top;
|
|
81
|
+
margin: 0;
|
|
82
|
+
padding: 0;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
table {
|
|
86
|
+
border-collapse: collapse;
|
|
87
|
+
white-space: nowrap;
|
|
88
|
+
|
|
89
|
+
th,
|
|
90
|
+
td {
|
|
91
|
+
border: 1px solid grey;
|
|
92
|
+
padding: 4px 8px;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
a {
|
|
97
|
+
color: ${({ theme }) => theme.palette.primary.main};
|
|
98
|
+
|
|
99
|
+
:hover {
|
|
100
|
+
text-decoration: underline;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
&.writing > *:last-child {
|
|
105
|
+
&:after {
|
|
106
|
+
content: '';
|
|
107
|
+
display: inline-block;
|
|
108
|
+
vertical-align: middle;
|
|
109
|
+
height: 1.2em;
|
|
110
|
+
margin-top: -0.2em;
|
|
111
|
+
margin-left: 0.1em;
|
|
112
|
+
border-right: 0.2em solid orange;
|
|
113
|
+
border-radius: 10px;
|
|
114
|
+
animation: blink-caret 0.75s step-end infinite;
|
|
115
|
+
|
|
116
|
+
@keyframes blink-caret {
|
|
117
|
+
from,
|
|
118
|
+
to {
|
|
119
|
+
border-color: transparent;
|
|
120
|
+
}
|
|
121
|
+
50% {
|
|
122
|
+
border-color: ${({ theme }) => theme.palette.secondary.main};
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
`;
|
|
128
|
+
export default MarkdownRenderer;
|