@springmicro/rte 0.1.3 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -5
- package/dist/index.js +7361 -7279
- package/package.json +7 -3
- package/.eslintrc.cjs +0 -18
- package/dist/index.d.ts +0 -10
- package/dist/index.umd.cjs +0 -469
- package/index.html +0 -13
- package/src/App.css +0 -42
- package/src/App.tsx +0 -10
- package/src/contexts/color-context.tsx +0 -53
- package/src/hooks/useSimpleFormik.tsx +0 -74
- package/src/index.css +0 -68
- package/src/index.tsx +0 -3
- package/src/main.tsx +0 -10
- package/src/slate/base-editor.stories.tsx +0 -16
- package/src/slate/base-editor.tsx +0 -116
- package/src/slate/blog-rte.stories.tsx +0 -16
- package/src/slate/blog-rte.tsx +0 -126
- package/src/slate/common/button.tsx +0 -35
- package/src/slate/common/element.tsx +0 -13
- package/src/slate/common/icon.jsx +0 -97
- package/src/slate/components/code-to-text/CodeToTextButton.jsx +0 -19
- package/src/slate/components/code-to-text/HtmlCode.jsx +0 -64
- package/src/slate/components/code-to-text/HtmlContextMenu.jsx +0 -39
- package/src/slate/components/code-to-text/index.jsx +0 -111
- package/src/slate/components/color-picker/color-cursor.stories.tsx +0 -16
- package/src/slate/components/color-picker/color-cursor.tsx +0 -34
- package/src/slate/components/color-picker/color-formats-view.stories.tsx +0 -25
- package/src/slate/components/color-picker/color-formats-view.tsx +0 -115
- package/src/slate/components/color-picker/color-gradient.stories.tsx +0 -48
- package/src/slate/components/color-picker/color-gradient.tsx +0 -128
- package/src/slate/components/color-picker/color-hue.stories.tsx +0 -41
- package/src/slate/components/color-picker/color-hue.tsx +0 -110
- package/src/slate/components/color-picker/color-picker.stories.tsx +0 -25
- package/src/slate/components/color-picker/color-picker.tsx +0 -41
- package/src/slate/components/color-picker/color-popover.stories.tsx +0 -26
- package/src/slate/components/color-picker/color-popover.tsx +0 -58
- package/src/slate/components/color-picker/color-swatch.stories.tsx +0 -16
- package/src/slate/components/color-picker/color-swatch.tsx +0 -76
- package/src/slate/components/color-picker/default-colors.ts +0 -38
- package/src/slate/components/color-picker/slate-color-button.tsx +0 -128
- package/src/slate/components/embed/Embed.jsx +0 -96
- package/src/slate/components/embed/Image.jsx +0 -45
- package/src/slate/components/embed/Video.jsx +0 -65
- package/src/slate/components/equation/Equation.jsx +0 -19
- package/src/slate/components/equation/EquationButton.jsx +0 -68
- package/src/slate/components/id/Id.jsx +0 -57
- package/src/slate/components/image/image.stories.tsx +0 -17
- package/src/slate/components/image/image.tsx +0 -62
- package/src/slate/components/image/insert-image-button.stories.tsx +0 -83
- package/src/slate/components/image/insert-image-button.tsx +0 -132
- package/src/slate/components/image/types.ts +0 -9
- package/src/slate/components/link/Link.jsx +0 -56
- package/src/slate/components/link/LinkButton.tsx +0 -106
- package/src/slate/components/table/Table.jsx +0 -11
- package/src/slate/components/table/TableSelector.jsx +0 -97
- package/src/slate/components/table-context-menu/TableContextMenu.tsx +0 -106
- package/src/slate/custom-types.d.ts +0 -152
- package/src/slate/editor.module.css +0 -226
- package/src/slate/paper-rte.stories.tsx +0 -16
- package/src/slate/paper-rte.tsx +0 -47
- package/src/slate/plugins/withEmbeds.js +0 -33
- package/src/slate/plugins/withEquation.js +0 -8
- package/src/slate/plugins/withImages.ts +0 -69
- package/src/slate/plugins/withLinks.js +0 -9
- package/src/slate/plugins/withTable.js +0 -74
- package/src/slate/serializers/generic.ts +0 -44
- package/src/slate/serializers/types.ts +0 -20
- package/src/slate/toolbar/index.tsx +0 -186
- package/src/slate/toolbar/paper-toolbar.tsx +0 -494
- package/src/slate/toolbar/shortcuts.tsx +0 -77
- package/src/slate/toolbar/toolbar-groups.ts +0 -213
- package/src/slate/types/index.ts +0 -0
- package/src/slate/utils/customHooks/useContextMenu.js +0 -42
- package/src/slate/utils/customHooks/useFormat.js +0 -26
- package/src/slate/utils/customHooks/usePopup.jsx +0 -26
- package/src/slate/utils/customHooks/useResize.js +0 -27
- package/src/slate/utils/embed.js +0 -18
- package/src/slate/utils/equation.js +0 -22
- package/src/slate/utils/index.jsx +0 -267
- package/src/slate/utils/link.js +0 -44
- package/src/slate/utils/p.js +0 -4
- package/src/slate/utils/table.js +0 -131
- package/src/vite-env.d.ts +0 -1
- package/tsconfig.json +0 -32
- package/tsconfig.node.json +0 -10
- package/vite.config.ts +0 -41
package/index.html
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
-
<title>Vite + React + TS</title>
|
|
8
|
-
</head>
|
|
9
|
-
<body>
|
|
10
|
-
<div id="root"></div>
|
|
11
|
-
<script type="module" src="/src/main.tsx"></script>
|
|
12
|
-
</body>
|
|
13
|
-
</html>
|
package/src/App.css
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
#root {
|
|
2
|
-
max-width: 1280px;
|
|
3
|
-
margin: 0 auto;
|
|
4
|
-
padding: 2rem;
|
|
5
|
-
text-align: center;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
.logo {
|
|
9
|
-
height: 6em;
|
|
10
|
-
padding: 1.5em;
|
|
11
|
-
will-change: filter;
|
|
12
|
-
transition: filter 300ms;
|
|
13
|
-
}
|
|
14
|
-
.logo:hover {
|
|
15
|
-
filter: drop-shadow(0 0 2em #646cffaa);
|
|
16
|
-
}
|
|
17
|
-
.logo.react:hover {
|
|
18
|
-
filter: drop-shadow(0 0 2em #61dafbaa);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
@keyframes logo-spin {
|
|
22
|
-
from {
|
|
23
|
-
transform: rotate(0deg);
|
|
24
|
-
}
|
|
25
|
-
to {
|
|
26
|
-
transform: rotate(360deg);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
@media (prefers-reduced-motion: no-preference) {
|
|
31
|
-
a:nth-of-type(2) .logo {
|
|
32
|
-
animation: logo-spin infinite 20s linear;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
.card {
|
|
37
|
-
padding: 2em;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
.read-the-docs {
|
|
41
|
-
color: #888;
|
|
42
|
-
}
|
package/src/App.tsx
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
// FontMetadata,
|
|
5
|
-
// PagesType,
|
|
6
|
-
// LayoutsType,
|
|
7
|
-
ColorFormats,
|
|
8
|
-
} from "@springmicro/utils/types";
|
|
9
|
-
import {
|
|
10
|
-
colorStringToColorFormats,
|
|
11
|
-
// defaultSelectedColors,
|
|
12
|
-
// defaultSelectedFonts,
|
|
13
|
-
} from "@springmicro/utils/editor";
|
|
14
|
-
|
|
15
|
-
export const ColorContext = React.createContext({
|
|
16
|
-
colorFormats: colorStringToColorFormats("#ffffff") as ColorFormats,
|
|
17
|
-
setColorFormats: ((colorFormats: ColorFormats) => {}) as React.Dispatch<
|
|
18
|
-
React.SetStateAction<ColorFormats>
|
|
19
|
-
>,
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
export function ColorProvider({
|
|
23
|
-
initialColor,
|
|
24
|
-
colorChangeCallback,
|
|
25
|
-
children,
|
|
26
|
-
}: React.PropsWithChildren<{
|
|
27
|
-
initialColor: string;
|
|
28
|
-
colorChangeCallback?: (color: string) => void;
|
|
29
|
-
}>) {
|
|
30
|
-
const [colorFormats, setColorFormats] = React.useState(
|
|
31
|
-
colorStringToColorFormats(initialColor)
|
|
32
|
-
);
|
|
33
|
-
|
|
34
|
-
React.useEffect(() => {
|
|
35
|
-
setColorFormats(colorStringToColorFormats(initialColor));
|
|
36
|
-
}, [initialColor]);
|
|
37
|
-
|
|
38
|
-
React.useEffect(() => {
|
|
39
|
-
// the callback updates the selectedColors for the site
|
|
40
|
-
if (colorChangeCallback && initialColor !== "#" + colorFormats.hex) {
|
|
41
|
-
colorChangeCallback("#" + colorFormats.hex);
|
|
42
|
-
}
|
|
43
|
-
}, [colorFormats]);
|
|
44
|
-
|
|
45
|
-
const value = {
|
|
46
|
-
colorFormats,
|
|
47
|
-
setColorFormats,
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
return (
|
|
51
|
-
<ColorContext.Provider value={value}>{children}</ColorContext.Provider>
|
|
52
|
-
);
|
|
53
|
-
}
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
// drop-in replacement for formik and Yup
|
|
2
|
-
// in the minimum way we use it in color-formats-view.tsx
|
|
3
|
-
import { useState, useCallback, ChangeEvent, FocusEvent } from "react";
|
|
4
|
-
|
|
5
|
-
interface FormikValues {
|
|
6
|
-
[key: string]: any;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
interface FormikValidators {
|
|
10
|
-
[key: string]: {
|
|
11
|
-
fn: (value: any) => boolean;
|
|
12
|
-
msg: string;
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
interface UseSimpleFormik<T> {
|
|
17
|
-
errors: Record<string, undefined | string>;
|
|
18
|
-
values: T;
|
|
19
|
-
setValues: React.Dispatch<React.SetStateAction<T>>;
|
|
20
|
-
handleChange: (
|
|
21
|
-
event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
|
|
22
|
-
) => void;
|
|
23
|
-
handleBlur: (
|
|
24
|
-
event: FocusEvent<HTMLInputElement | HTMLTextAreaElement>
|
|
25
|
-
) => void;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const useSimpleFormik = <T extends FormikValues>(
|
|
29
|
-
initialValues: T,
|
|
30
|
-
validators: FormikValidators
|
|
31
|
-
): UseSimpleFormik<T> => {
|
|
32
|
-
const [values, setValues] = useState<T>(initialValues);
|
|
33
|
-
const [errors, setErrors] = useState(
|
|
34
|
-
Object.fromEntries(
|
|
35
|
-
Object.entries(initialValues).map(([k, _]) => [k, undefined])
|
|
36
|
-
)
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
const handleChange = useCallback(
|
|
40
|
-
(event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
|
41
|
-
const { name, value } = event.target;
|
|
42
|
-
if (validators[name]?.fn(value) === false) {
|
|
43
|
-
setErrors((prevValues) => ({
|
|
44
|
-
...prevValues,
|
|
45
|
-
[name]: validators[name].msg,
|
|
46
|
-
}));
|
|
47
|
-
}
|
|
48
|
-
setValues((prevValues) => ({
|
|
49
|
-
...prevValues,
|
|
50
|
-
[name]: value,
|
|
51
|
-
}));
|
|
52
|
-
},
|
|
53
|
-
[]
|
|
54
|
-
);
|
|
55
|
-
|
|
56
|
-
const handleBlur = useCallback(
|
|
57
|
-
(event: FocusEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
|
58
|
-
const { name } = event.target;
|
|
59
|
-
// Here you can handle the blur event, e.g., setting touched fields if needed
|
|
60
|
-
console.log(`${name} field blurred`);
|
|
61
|
-
},
|
|
62
|
-
[]
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
return {
|
|
66
|
-
errors,
|
|
67
|
-
values,
|
|
68
|
-
setValues,
|
|
69
|
-
handleChange,
|
|
70
|
-
handleBlur,
|
|
71
|
-
};
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
export default useSimpleFormik;
|
package/src/index.css
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
:root {
|
|
2
|
-
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
|
3
|
-
line-height: 1.5;
|
|
4
|
-
font-weight: 400;
|
|
5
|
-
|
|
6
|
-
color-scheme: light dark;
|
|
7
|
-
color: rgba(255, 255, 255, 0.87);
|
|
8
|
-
background-color: #242424;
|
|
9
|
-
|
|
10
|
-
font-synthesis: none;
|
|
11
|
-
text-rendering: optimizeLegibility;
|
|
12
|
-
-webkit-font-smoothing: antialiased;
|
|
13
|
-
-moz-osx-font-smoothing: grayscale;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
a {
|
|
17
|
-
font-weight: 500;
|
|
18
|
-
color: #646cff;
|
|
19
|
-
text-decoration: inherit;
|
|
20
|
-
}
|
|
21
|
-
a:hover {
|
|
22
|
-
color: #535bf2;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
body {
|
|
26
|
-
margin: 0;
|
|
27
|
-
display: flex;
|
|
28
|
-
place-items: center;
|
|
29
|
-
min-width: 320px;
|
|
30
|
-
min-height: 100vh;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
h1 {
|
|
34
|
-
font-size: 3.2em;
|
|
35
|
-
line-height: 1.1;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
button {
|
|
39
|
-
border-radius: 8px;
|
|
40
|
-
border: 1px solid transparent;
|
|
41
|
-
padding: 0.6em 1.2em;
|
|
42
|
-
font-size: 1em;
|
|
43
|
-
font-weight: 500;
|
|
44
|
-
font-family: inherit;
|
|
45
|
-
background-color: #1a1a1a;
|
|
46
|
-
cursor: pointer;
|
|
47
|
-
transition: border-color 0.25s;
|
|
48
|
-
}
|
|
49
|
-
button:hover {
|
|
50
|
-
border-color: #646cff;
|
|
51
|
-
}
|
|
52
|
-
button:focus,
|
|
53
|
-
button:focus-visible {
|
|
54
|
-
outline: 4px auto -webkit-focus-ring-color;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
@media (prefers-color-scheme: light) {
|
|
58
|
-
:root {
|
|
59
|
-
color: #213547;
|
|
60
|
-
background-color: #ffffff;
|
|
61
|
-
}
|
|
62
|
-
a:hover {
|
|
63
|
-
color: #747bff;
|
|
64
|
-
}
|
|
65
|
-
button {
|
|
66
|
-
background-color: #f9f9f9;
|
|
67
|
-
}
|
|
68
|
-
}
|
package/src/index.tsx
DELETED
package/src/main.tsx
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { SlateEditor, SlateEditorProps } from "./base-editor";
|
|
2
|
-
import React from "react";
|
|
3
|
-
import { StoryFn, Meta } from "@storybook/react";
|
|
4
|
-
|
|
5
|
-
export default {
|
|
6
|
-
/* 👇 The title prop is optional.
|
|
7
|
-
* See https://storybook.js.org/docs/react/configure/overview#configure-story-loading
|
|
8
|
-
* to learn how to generate automatic titles
|
|
9
|
-
*/
|
|
10
|
-
title: "Slate/Slate Editor Base",
|
|
11
|
-
component: SlateEditor,
|
|
12
|
-
} as Meta<typeof SlateEditor>;
|
|
13
|
-
|
|
14
|
-
export const Primary = {
|
|
15
|
-
args: { readOnly: false } as SlateEditorProps,
|
|
16
|
-
};
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import { Descendant, createEditor } from "slate";
|
|
3
|
-
import { withHistory } from "slate-history";
|
|
4
|
-
import {
|
|
5
|
-
Slate,
|
|
6
|
-
Editable,
|
|
7
|
-
withReact,
|
|
8
|
-
RenderLeafProps,
|
|
9
|
-
RenderElementProps,
|
|
10
|
-
} from "slate-react";
|
|
11
|
-
import Toolbar from "./toolbar";
|
|
12
|
-
import { getMarked, getBlock } from "./utils";
|
|
13
|
-
import withLinks from "./plugins/withLinks.js";
|
|
14
|
-
import withTables from "./plugins/withTable.js";
|
|
15
|
-
import withEmbeds from "./plugins/withEmbeds.js";
|
|
16
|
-
import withEquation from "./plugins/withEquation.js";
|
|
17
|
-
import styles from "./editor.module.css";
|
|
18
|
-
import CodeToText from "./components/code-to-text";
|
|
19
|
-
import { issuesToolbarGroups } from "./toolbar/toolbar-groups";
|
|
20
|
-
import { Element } from "./common/element";
|
|
21
|
-
import { ScopedCssBaseline } from "@mui/material";
|
|
22
|
-
// import { serialize } from "./utils/serializer"
|
|
23
|
-
|
|
24
|
-
export type SlateEditorProps = {
|
|
25
|
-
value?: Descendant[];
|
|
26
|
-
setValue?: React.Dispatch<React.SetStateAction<Descendant[]>>;
|
|
27
|
-
readOnly: boolean;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
const Leaf = ({ attributes, children, leaf }: RenderLeafProps) => {
|
|
31
|
-
children = getMarked(leaf, children);
|
|
32
|
-
return <span {...attributes}>{children}</span>;
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
export function SlateEditor(props: SlateEditorProps) {
|
|
36
|
-
const { readOnly } = props;
|
|
37
|
-
const initialValue = props.value || [
|
|
38
|
-
{
|
|
39
|
-
type: "p",
|
|
40
|
-
children: [{ text: "" }],
|
|
41
|
-
},
|
|
42
|
-
];
|
|
43
|
-
|
|
44
|
-
const [value, setValue] = React.useState(initialValue);
|
|
45
|
-
const [htmlAction, setHtmlAction] = React.useState({
|
|
46
|
-
showInput: false,
|
|
47
|
-
html: "",
|
|
48
|
-
action: "",
|
|
49
|
-
location: "",
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
const editor = React.useMemo(
|
|
53
|
-
() =>
|
|
54
|
-
withEquation(
|
|
55
|
-
withHistory(
|
|
56
|
-
withEmbeds(withTables(withLinks(withReact(createEditor()))))
|
|
57
|
-
)
|
|
58
|
-
),
|
|
59
|
-
[]
|
|
60
|
-
);
|
|
61
|
-
|
|
62
|
-
const renderElement = React.useCallback(
|
|
63
|
-
(props: RenderElementProps) => <Element {...props} />,
|
|
64
|
-
[]
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
-
const renderLeaf = React.useCallback((props: RenderLeafProps) => {
|
|
68
|
-
return <Leaf {...props} />;
|
|
69
|
-
}, []);
|
|
70
|
-
|
|
71
|
-
const handleEditorChange = (newValue: Descendant[]) => {
|
|
72
|
-
if (props.setValue) {
|
|
73
|
-
props.setValue(newValue);
|
|
74
|
-
} else {
|
|
75
|
-
setValue(newValue);
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
const handleCodeToText = (partialState: any) => {
|
|
80
|
-
setHtmlAction((prev) => ({
|
|
81
|
-
...prev,
|
|
82
|
-
...partialState,
|
|
83
|
-
}));
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
return (
|
|
87
|
-
<div className={styles.slate}>
|
|
88
|
-
<ScopedCssBaseline>
|
|
89
|
-
<Slate
|
|
90
|
-
editor={editor}
|
|
91
|
-
initialValue={props.value !== undefined ? props.value : value}
|
|
92
|
-
onChange={handleEditorChange}
|
|
93
|
-
>
|
|
94
|
-
{!readOnly && (
|
|
95
|
-
<Toolbar
|
|
96
|
-
handleCodeToText={handleCodeToText}
|
|
97
|
-
toolbarGroups={issuesToolbarGroups}
|
|
98
|
-
/>
|
|
99
|
-
)}
|
|
100
|
-
<div className={readOnly ? "" : styles.editorWrapper}>
|
|
101
|
-
<Editable
|
|
102
|
-
placeholder="Write something"
|
|
103
|
-
renderElement={renderElement}
|
|
104
|
-
renderLeaf={renderLeaf}
|
|
105
|
-
readOnly={props.readOnly}
|
|
106
|
-
spellCheck={true}
|
|
107
|
-
/>
|
|
108
|
-
</div>
|
|
109
|
-
{htmlAction.showInput && (
|
|
110
|
-
<CodeToText {...htmlAction} handleCodeToText={handleCodeToText} />
|
|
111
|
-
)}
|
|
112
|
-
</Slate>
|
|
113
|
-
</ScopedCssBaseline>
|
|
114
|
-
</div>
|
|
115
|
-
);
|
|
116
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { BlogEditor, BlogEditorProps } from "./blog-rte"
|
|
2
|
-
import React from "react"
|
|
3
|
-
import { StoryFn, Meta } from "@storybook/react"
|
|
4
|
-
|
|
5
|
-
export default {
|
|
6
|
-
/* 👇 The title prop is optional.
|
|
7
|
-
* See https://storybook.js.org/docs/react/configure/overview#configure-story-loading
|
|
8
|
-
* to learn how to generate automatic titles
|
|
9
|
-
*/
|
|
10
|
-
title: "Slate/Blog Editor",
|
|
11
|
-
component: BlogEditor,
|
|
12
|
-
} as Meta<typeof BlogEditor>
|
|
13
|
-
|
|
14
|
-
export const Primary = {
|
|
15
|
-
args: { readOnly: false } as BlogEditorProps,
|
|
16
|
-
}
|
package/src/slate/blog-rte.tsx
DELETED
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import { Box, ScopedCssBaseline } from "@mui/material";
|
|
3
|
-
import { BaseEditor, Descendant, createEditor } from "slate";
|
|
4
|
-
import { withHistory } from "slate-history";
|
|
5
|
-
import {
|
|
6
|
-
Slate,
|
|
7
|
-
Editable,
|
|
8
|
-
withReact,
|
|
9
|
-
RenderLeafProps,
|
|
10
|
-
RenderElementProps,
|
|
11
|
-
ReactEditor,
|
|
12
|
-
} from "slate-react";
|
|
13
|
-
import Toolbar from "./toolbar";
|
|
14
|
-
import { getMarked, getBlock } from "./utils";
|
|
15
|
-
import withLinks from "./plugins/withLinks.js";
|
|
16
|
-
import withTables from "./plugins/withTable.js";
|
|
17
|
-
import withEmbeds from "./plugins/withEmbeds.js";
|
|
18
|
-
import withEquation from "./plugins/withEquation.js";
|
|
19
|
-
import withImages from "./plugins/withImages";
|
|
20
|
-
import styles from "./editor.module.css";
|
|
21
|
-
import CodeToText from "./components/code-to-text";
|
|
22
|
-
import { blogToolbarGroups } from "./toolbar/toolbar-groups";
|
|
23
|
-
import { Element } from "./common/element";
|
|
24
|
-
|
|
25
|
-
export type BlogEditorProps = {
|
|
26
|
-
value?: Descendant[];
|
|
27
|
-
setValue?: React.Dispatch<React.SetStateAction<Descendant[]>>;
|
|
28
|
-
readOnly: boolean;
|
|
29
|
-
editor?: BaseEditor & ReactEditor;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
const Leaf = ({ attributes, children, leaf }: RenderLeafProps) => {
|
|
33
|
-
children = getMarked(leaf, children);
|
|
34
|
-
return <span {...attributes}>{children}</span>;
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export function BlogEditor(props: BlogEditorProps) {
|
|
38
|
-
const { readOnly } = props;
|
|
39
|
-
const initialValue = props.value || [
|
|
40
|
-
{
|
|
41
|
-
type: "p",
|
|
42
|
-
children: [{ text: "" }],
|
|
43
|
-
},
|
|
44
|
-
];
|
|
45
|
-
|
|
46
|
-
const [value, setValue] = React.useState(initialValue);
|
|
47
|
-
const [htmlAction, setHtmlAction] = React.useState({
|
|
48
|
-
showInput: false,
|
|
49
|
-
html: "",
|
|
50
|
-
action: "",
|
|
51
|
-
location: "",
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
const editor =
|
|
55
|
-
props.editor ||
|
|
56
|
-
React.useMemo(
|
|
57
|
-
() =>
|
|
58
|
-
withImages(
|
|
59
|
-
withEquation(
|
|
60
|
-
withHistory(
|
|
61
|
-
withEmbeds(withTables(withLinks(withReact(createEditor()))))
|
|
62
|
-
)
|
|
63
|
-
)
|
|
64
|
-
),
|
|
65
|
-
[]
|
|
66
|
-
);
|
|
67
|
-
|
|
68
|
-
const renderElement = React.useCallback(
|
|
69
|
-
(props: RenderElementProps) => <Element {...props} />,
|
|
70
|
-
[]
|
|
71
|
-
);
|
|
72
|
-
|
|
73
|
-
const renderLeaf = React.useCallback((props: RenderLeafProps) => {
|
|
74
|
-
return <Leaf {...props} />;
|
|
75
|
-
}, []);
|
|
76
|
-
|
|
77
|
-
const handleEditorChange = (newValue: Descendant[]) => {
|
|
78
|
-
// console.log(newValue)
|
|
79
|
-
if (props.setValue) {
|
|
80
|
-
props.setValue(newValue);
|
|
81
|
-
} else {
|
|
82
|
-
setValue(newValue);
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
const handleCodeToText = (partialState: any) => {
|
|
87
|
-
setHtmlAction((prev) => ({
|
|
88
|
-
...prev,
|
|
89
|
-
...partialState,
|
|
90
|
-
}));
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
return (
|
|
94
|
-
<div className={styles.slate}>
|
|
95
|
-
<ScopedCssBaseline>
|
|
96
|
-
<Slate
|
|
97
|
-
editor={editor}
|
|
98
|
-
initialValue={props.value ? props.value : value}
|
|
99
|
-
onChange={handleEditorChange}
|
|
100
|
-
>
|
|
101
|
-
{!readOnly && (
|
|
102
|
-
<Toolbar
|
|
103
|
-
handleCodeToText={handleCodeToText}
|
|
104
|
-
toolbarGroups={blogToolbarGroups}
|
|
105
|
-
/>
|
|
106
|
-
)}
|
|
107
|
-
<Box
|
|
108
|
-
className={readOnly ? "" : styles.editorWrapper}
|
|
109
|
-
sx={{ minHeight: 400 }}
|
|
110
|
-
>
|
|
111
|
-
<Editable
|
|
112
|
-
placeholder="Write something"
|
|
113
|
-
renderElement={renderElement}
|
|
114
|
-
renderLeaf={renderLeaf}
|
|
115
|
-
readOnly={props.readOnly}
|
|
116
|
-
spellCheck={true}
|
|
117
|
-
/>
|
|
118
|
-
</Box>
|
|
119
|
-
{htmlAction.showInput && (
|
|
120
|
-
<CodeToText {...htmlAction} handleCodeToText={handleCodeToText} />
|
|
121
|
-
)}
|
|
122
|
-
</Slate>
|
|
123
|
-
</ScopedCssBaseline>
|
|
124
|
-
</div>
|
|
125
|
-
);
|
|
126
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import { Box, useTheme } from "@mui/material";
|
|
3
|
-
import { snakeToTitle } from "@springmicro/utils/string";
|
|
4
|
-
import { getShortcutKey } from "../toolbar/shortcuts";
|
|
5
|
-
|
|
6
|
-
const Button = (props: React.PropsWithChildren<any>) => {
|
|
7
|
-
const theme = useTheme();
|
|
8
|
-
const { children, format, active, ...rest } = props;
|
|
9
|
-
const [key, combo] = getShortcutKey(format, true);
|
|
10
|
-
const title =
|
|
11
|
-
key && combo
|
|
12
|
-
? `${snakeToTitle(format)} (${combo}+${key.toUpperCase()})`
|
|
13
|
-
: snakeToTitle(format);
|
|
14
|
-
return (
|
|
15
|
-
<Box
|
|
16
|
-
component="button"
|
|
17
|
-
title={title}
|
|
18
|
-
{...rest}
|
|
19
|
-
sx={{
|
|
20
|
-
width: "30px",
|
|
21
|
-
height: "20px",
|
|
22
|
-
margin: "0 2px",
|
|
23
|
-
paddingBottom: "24px",
|
|
24
|
-
borderBottom: active
|
|
25
|
-
? `2px solid ${theme.palette.primary.main} !important`
|
|
26
|
-
: "",
|
|
27
|
-
...rest.sx,
|
|
28
|
-
}}
|
|
29
|
-
>
|
|
30
|
-
{children}
|
|
31
|
-
</Box>
|
|
32
|
-
);
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
export default Button;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import Image from "../components/image/image";
|
|
2
|
-
import { getBlock } from "../utils";
|
|
3
|
-
|
|
4
|
-
export const Element = (props: any) => {
|
|
5
|
-
const { attributes, children, element } = props;
|
|
6
|
-
|
|
7
|
-
switch (element.type) {
|
|
8
|
-
case "image":
|
|
9
|
-
return <Image {...props} />;
|
|
10
|
-
default:
|
|
11
|
-
return getBlock(props);
|
|
12
|
-
}
|
|
13
|
-
};
|