feat: add defaultShowPicker for katex

pull/29/head
fantasticit 2022-04-25 10:54:38 +08:00
parent c9d4fd5127
commit f89c1051db
5 changed files with 60 additions and 13 deletions

View File

@ -2,10 +2,15 @@ import { Node, mergeAttributes, nodeInputRule } from '@tiptap/core';
import { ReactNodeViewRenderer } from '@tiptap/react'; import { ReactNodeViewRenderer } from '@tiptap/react';
import { KatexWrapper } from '../wrappers/katex'; import { KatexWrapper } from '../wrappers/katex';
type IKatexAttrs = {
text?: string;
defaultShowPicker?: boolean;
};
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands<ReturnType> { interface Commands<ReturnType> {
katex: { katex: {
setKatex: () => ReturnType; setKatex: (arg?: IKatexAttrs) => ReturnType;
}; };
} }
} }
@ -35,6 +40,9 @@ export const Katex = Node.create({
return element.getAttribute('data-text'); return element.getAttribute('data-text');
}, },
}, },
defaultShowPicker: {
default: false,
},
}; };
}, },

View File

@ -79,7 +79,7 @@ export const Insert: React.FC<{ editor: Editor }> = ({ editor }) => {
<IconMind /> <IconMind />
</Dropdown.Item> </Dropdown.Item>
<Dropdown.Item onClick={() => editor.chain().focus().setKatex().run()}> <Dropdown.Item onClick={() => editor.chain().focus().setKatex({ defaultShowPicker: true }).run()}>
<IconMath /> <IconMath />
</Dropdown.Item> </Dropdown.Item>

View File

@ -208,7 +208,14 @@ export const QUICK_INSERT_ITEMS = [
</Space> </Space>
), ),
command: (editor: Editor) => editor.chain().focus().setKatex().run(), command: (editor: Editor) =>
editor
.chain()
.focus()
.setKatex({
defaultShowPicker: true,
})
.run(),
}, },
{ {

View File

@ -1,6 +1,12 @@
.wrap { .wrap {
display: inline-flex; display: inline-flex;
justify-content: center; justify-content: center;
padding: 0 8px; transform: translateY(1px);
transform: translateY(8px);
font-size: 12px;
line-height: 16px;
height: 20px;
padding: 2px 8px;
cursor: pointer;
} }

View File

@ -1,16 +1,19 @@
import { NodeViewWrapper, NodeViewContent } from '@tiptap/react'; import { NodeViewWrapper, NodeViewContent } from '@tiptap/react';
import { useMemo } from 'react'; import { useMemo, useCallback, useEffect, useRef } from 'react';
import cls from 'classnames'; import cls from 'classnames';
import { Popover, TextArea, Typography, Space } from '@douyinfe/semi-ui'; import { Popover, TextArea, Typography, Space } from '@douyinfe/semi-ui';
import { IconHelpCircle } from '@douyinfe/semi-icons'; import { IconHelpCircle } from '@douyinfe/semi-icons';
import katex from 'katex'; import katex from 'katex';
import { useToggle } from 'hooks/use-toggle';
import styles from './index.module.scss'; import styles from './index.module.scss';
const { Text } = Typography; const { Text } = Typography;
export const KatexWrapper = ({ editor, node, updateAttributes }) => { export const KatexWrapper = ({ editor, node, updateAttributes }) => {
const isEditable = editor.isEditable; const isEditable = editor.isEditable;
const { text } = node.attrs; const { text, defaultShowPicker } = node.attrs;
const ref = useRef<HTMLTextAreaElement>();
const [visible, toggleVisible] = useToggle(false);
const formatText = useMemo(() => { const formatText = useMemo(() => {
try { try {
@ -20,22 +23,46 @@ export const KatexWrapper = ({ editor, node, updateAttributes }) => {
} }
}, [text]); }, [text]);
const content = text.trim() ? ( const content = useMemo(
<span contentEditable={false} dangerouslySetInnerHTML={{ __html: formatText }}></span> () =>
) : ( text.trim() ? (
<span contentEditable={false}></span> <span contentEditable={false} dangerouslySetInnerHTML={{ __html: formatText }}></span>
) : (
<span contentEditable={false}></span>
),
[text]
); );
const onVisibleChange = useCallback(
(value) => {
toggleVisible(value);
if (defaultShowPicker) {
updateAttributes({ defaultShowPicker: false });
}
},
[defaultShowPicker, updateAttributes]
);
useEffect(() => {
if (defaultShowPicker) {
toggleVisible(true);
setTimeout(() => ref.current?.focus(), 100);
}
}, [defaultShowPicker]);
return ( return (
<NodeViewWrapper as="span" className={cls(styles.wrap, 'render-wrapper')} contentEditable={false}> <NodeViewWrapper as="span" className={cls(styles.wrap, 'render-wrapper')} contentEditable={false}>
<NodeViewContent />
{isEditable ? ( {isEditable ? (
<Popover <Popover
showArrow showArrow
position="bottomLeft" position="bottomLeft"
spacing={12}
visible={visible}
onVisibleChange={onVisibleChange}
content={ content={
<div style={{ width: 320 }}> <div style={{ width: 320 }}>
<TextArea <TextArea
ref={ref}
autofocus autofocus
placeholder="输入公式" placeholder="输入公式"
autosize autosize
@ -59,7 +86,6 @@ export const KatexWrapper = ({ editor, node, updateAttributes }) => {
) : ( ) : (
content content
)} )}
<NodeViewContent />
</NodeViewWrapper> </NodeViewWrapper>
); );
}; };