159 lines
3.5 KiB
TypeScript
159 lines
3.5 KiB
TypeScript
import { Card, Heading, SystemStyleObject } from '@chakra-ui/react';
|
|
import EditorJS, { EditorConfig } from '@editorjs/editorjs';
|
|
import Header from '@editorjs/header';
|
|
import List from '@editorjs/list';
|
|
import Quote from '@editorjs/quote';
|
|
import { useEffect, useRef } from 'react';
|
|
|
|
// @ts-ignore
|
|
import Link from '@coolbytes/editorjs-link';
|
|
|
|
export function Editor({ initialData }: { initialData?: EditorConfig['data'] }) {
|
|
const ejInstance = useRef<EditorJS | undefined | null>();
|
|
|
|
const initEditor = () => {
|
|
const editor = new EditorJS({
|
|
holder: 'editorjs',
|
|
onReady: () => {
|
|
ejInstance.current = editor;
|
|
},
|
|
autofocus: true,
|
|
data: initialData,
|
|
// onChange: async () => {
|
|
// const content = await editor.saver.save();
|
|
// },
|
|
tools: {
|
|
header: Header,
|
|
list: List,
|
|
link: Link,
|
|
quote: Quote
|
|
}
|
|
});
|
|
};
|
|
|
|
useEffect(() => {
|
|
if (ejInstance.current === null) {
|
|
initEditor();
|
|
}
|
|
|
|
return () => {
|
|
ejInstance?.current?.destroy();
|
|
ejInstance.current = null;
|
|
};
|
|
}, []);
|
|
|
|
return (
|
|
<>
|
|
<Card.Root
|
|
variant={'subtle'}
|
|
width="100%"
|
|
maxWidth="840px"
|
|
minHeight="sm"
|
|
justifyContent="center"
|
|
alignItems="center"
|
|
>
|
|
<Card.Header>
|
|
<Heading textAlign="center">Editor</Heading>
|
|
</Card.Header>
|
|
<Card.Body
|
|
width="90%"
|
|
css={{
|
|
'& *': {
|
|
fontSize: 'revert',
|
|
fontWeight: 'revert'
|
|
},
|
|
...editorJsStyles
|
|
}}
|
|
>
|
|
<div className="editorjs" id="editorjs"></div>
|
|
</Card.Body>
|
|
</Card.Root>
|
|
</>
|
|
);
|
|
}
|
|
|
|
const editorJsStyles:
|
|
| SystemStyleObject
|
|
| Omit<Array<SystemStyleObject | undefined>, keyof any[]>
|
|
| undefined = {
|
|
'& .ce-block--selected .ce-block__content, \
|
|
& .ce-inline-toolbar, \
|
|
& .codex-editor--narrow .ce-toolbox, \
|
|
& .ce-conversion-toolbar, \
|
|
& .ce-settings, \
|
|
& .ce-settings__button, \
|
|
& .ce-toolbar__settings-btn, \
|
|
& .cdx-button, \
|
|
& .ce-popover': {
|
|
background: 'colorPalette.500',
|
|
border: 'none'
|
|
},
|
|
|
|
'& .ce-inline-tool, \
|
|
& .ce-conversion-toolbar__label, \
|
|
& .ce-toolbox__button, \
|
|
& .cdx-settings-button, \
|
|
& .ce-toolbar__plus': {
|
|
color: 'colorPalette.500'
|
|
},
|
|
|
|
'& ::selection': {
|
|
background: 'colorPalette.500'
|
|
},
|
|
|
|
'& .cdx-settings-button:hover, \
|
|
& .ce-settings__button:hover, \
|
|
& .ce-toolbox__button--active, \
|
|
& .ce-toolbox__button:hover, \
|
|
& .cdx-button:hover, \
|
|
& .ce-inline-toolbar__dropdown:hover, \
|
|
& .ce-inline-tool:hover, \
|
|
& .ce-popover__item:hover, \
|
|
& .ce-toolbar__settings-btn:hover': {
|
|
background: 'colorPalette.500',
|
|
color: 'fg'
|
|
},
|
|
|
|
'& .cdx-notify--error': {
|
|
background: 'red !important'
|
|
},
|
|
|
|
'& .cdx-notify__cross::after, & .cdx-notify__cross::before': {
|
|
background: 'white'
|
|
},
|
|
|
|
'& .ce-toolbar__plus:hover, \
|
|
& .ce-popover__container': {
|
|
backgroundColor: 'bg.emphasized',
|
|
color: 'colorPalette.500',
|
|
border: 'none'
|
|
},
|
|
|
|
'& .ce-popover-item:hover:not(.ce-popover-item--no-hover)': {
|
|
backgroundColor: 'colorPalette.500',
|
|
color: 'fg'
|
|
},
|
|
|
|
'& .cdx-search-field': {
|
|
background: 'bg.muted',
|
|
color: 'fg',
|
|
border: 'none'
|
|
},
|
|
|
|
'& .ce-popover-item__title, \
|
|
& .ce-popover-item__icon': {
|
|
color: 'fg'
|
|
},
|
|
|
|
'& .ce-popover-item-separator': {
|
|
color: 'bg.muted'
|
|
},
|
|
|
|
'& .ce-toolbar__settings-btn': {
|
|
color: 'white'
|
|
},
|
|
|
|
'& .ce-toolbar__settings-btn:hover': {
|
|
color: 'black'
|
|
}
|
|
};
|