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 { KatexWrapper } from '../wrappers/katex';
type IKatexAttrs = {
text?: string;
defaultShowPicker?: boolean;
};
declare module '@tiptap/core' {
interface Commands<ReturnType> {
katex: {
setKatex: () => ReturnType;
setKatex: (arg?: IKatexAttrs) => ReturnType;
};
}
}
@ -35,6 +40,9 @@ export const Katex = Node.create({
return element.getAttribute('data-text');
},
},
defaultShowPicker: {
default: false,
},
};
},

View File

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

View File

@ -208,7 +208,14 @@ export const QUICK_INSERT_ITEMS = [
</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 {
display: inline-flex;
justify-content: center;
padding: 0 8px;
transform: translateY(8px);
transform: translateY(1px);
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 { useMemo } from 'react';
import { useMemo, useCallback, useEffect, useRef } from 'react';
import cls from 'classnames';
import { Popover, TextArea, Typography, Space } from '@douyinfe/semi-ui';
import { IconHelpCircle } from '@douyinfe/semi-icons';
import katex from 'katex';
import { useToggle } from 'hooks/use-toggle';
import styles from './index.module.scss';
const { Text } = Typography;
export const KatexWrapper = ({ editor, node, updateAttributes }) => {
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(() => {
try {
@ -20,22 +23,46 @@ export const KatexWrapper = ({ editor, node, updateAttributes }) => {
}
}, [text]);
const content = text.trim() ? (
<span contentEditable={false} dangerouslySetInnerHTML={{ __html: formatText }}></span>
) : (
<span contentEditable={false}></span>
const content = useMemo(
() =>
text.trim() ? (
<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 (
<NodeViewWrapper as="span" className={cls(styles.wrap, 'render-wrapper')} contentEditable={false}>
<NodeViewContent />
{isEditable ? (
<Popover
showArrow
position="bottomLeft"
spacing={12}
visible={visible}
onVisibleChange={onVisibleChange}
content={
<div style={{ width: 320 }}>
<TextArea
ref={ref}
autofocus
placeholder="输入公式"
autosize
@ -59,7 +86,6 @@ export const KatexWrapper = ({ editor, node, updateAttributes }) => {
) : (
content
)}
<NodeViewContent />
</NodeViewWrapper>
);
};