mirror of https://github.com/fantasticit/think.git
refactor: rename banner to callout
parent
1786e21fc8
commit
20db8fcf57
|
@ -0,0 +1,14 @@
|
||||||
|
import { Icon } from '@douyinfe/semi-ui';
|
||||||
|
|
||||||
|
export const IconCallout: React.FC<{ style?: React.CSSProperties }> = ({ style = {} }) => {
|
||||||
|
return (
|
||||||
|
<Icon
|
||||||
|
style={style}
|
||||||
|
svg={
|
||||||
|
<svg viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16">
|
||||||
|
<path d="M4 2a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2H4Zm16 2v6H4V4h16ZM3 16a1 1 0 0 1 1-1h16a1 1 0 1 1 0 2H4a1 1 0 0 1-1-1Zm1 4a1 1 0 1 0 0 2h8a1 1 0 1 0 0-2H4Z"></path>
|
||||||
|
</svg>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
|
@ -50,3 +50,4 @@ export * from './IconSup';
|
||||||
export * from './IconGlobe';
|
export * from './IconGlobe';
|
||||||
export * from './IconCountdown';
|
export * from './IconCountdown';
|
||||||
export * from './IconDrawBoard';
|
export * from './IconDrawBoard';
|
||||||
|
export * from './IconCallout';
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
import { Node, mergeAttributes, wrappingInputRule } from '@tiptap/core';
|
import { Node, mergeAttributes, wrappingInputRule } from '@tiptap/core';
|
||||||
import { ReactNodeViewRenderer } from '@tiptap/react';
|
import { ReactNodeViewRenderer } from '@tiptap/react';
|
||||||
import { BannerWrapper } from '../wrappers/banner';
|
import { CalloutWrapper } from '../wrappers/callout';
|
||||||
import { getDatasetAttribute } from '../utils/dataset';
|
import { getDatasetAttribute } from '../utils/dataset';
|
||||||
|
|
||||||
declare module '@tiptap/core' {
|
declare module '@tiptap/core' {
|
||||||
interface Commands<ReturnType> {
|
interface Commands<ReturnType> {
|
||||||
banner: {
|
banner: {
|
||||||
setBanner: (attrs) => ReturnType;
|
setCallout: () => ReturnType;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Banner = Node.create({
|
export const Callout = Node.create({
|
||||||
name: 'banner',
|
name: 'callout',
|
||||||
content: 'paragraph+',
|
content: 'paragraph+',
|
||||||
group: 'block',
|
group: 'block',
|
||||||
defining: true,
|
defining: true,
|
||||||
|
@ -20,17 +20,6 @@ export const Banner = Node.create({
|
||||||
|
|
||||||
addAttributes() {
|
addAttributes() {
|
||||||
return {
|
return {
|
||||||
type: {
|
|
||||||
default: 'info',
|
|
||||||
rendered: false,
|
|
||||||
parseHTML: getDatasetAttribute('type'),
|
|
||||||
renderHTML: (attributes) => {
|
|
||||||
return {
|
|
||||||
'data-type': attributes.type,
|
|
||||||
'class': `banner banner-${attributes.type}`,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
},
|
|
||||||
emoji: {
|
emoji: {
|
||||||
default: '✅',
|
default: '✅',
|
||||||
},
|
},
|
||||||
|
@ -49,7 +38,7 @@ export const Banner = Node.create({
|
||||||
addOptions() {
|
addOptions() {
|
||||||
return {
|
return {
|
||||||
HTMLAttributes: {
|
HTMLAttributes: {
|
||||||
class: 'banner',
|
class: 'callout',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -68,14 +57,14 @@ export const Banner = Node.create({
|
||||||
|
|
||||||
addCommands() {
|
addCommands() {
|
||||||
return {
|
return {
|
||||||
setBanner:
|
setCallout:
|
||||||
(attributes) =>
|
() =>
|
||||||
({ commands, editor }) => {
|
({ commands, editor }) => {
|
||||||
const { type = null } = editor.getAttributes(this.name);
|
const { type = null } = editor.getAttributes(this.name);
|
||||||
if (type) {
|
if (type) {
|
||||||
commands.lift(this.name);
|
commands.lift(this.name);
|
||||||
} else {
|
} else {
|
||||||
return commands.toggleWrap(this.name, attributes);
|
return commands.toggleWrap(this.name);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -94,6 +83,6 @@ export const Banner = Node.create({
|
||||||
},
|
},
|
||||||
|
|
||||||
addNodeView() {
|
addNodeView() {
|
||||||
return ReactNodeViewRenderer(BannerWrapper);
|
return ReactNodeViewRenderer(CalloutWrapper);
|
||||||
},
|
},
|
||||||
});
|
});
|
|
@ -115,19 +115,19 @@ export const Paste = Extension.create({
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
// clipboardTextSerializer: (slice) => {
|
clipboardTextSerializer: (slice) => {
|
||||||
// const doc = slice.content;
|
const doc = slice.content;
|
||||||
|
|
||||||
// if (!doc) {
|
if (!doc) {
|
||||||
// return '';
|
return '';
|
||||||
// }
|
}
|
||||||
|
|
||||||
// const content = prosemirrorToMarkdown({
|
const content = prosemirrorToMarkdown({
|
||||||
// content: doc,
|
content: doc,
|
||||||
// });
|
});
|
||||||
|
|
||||||
// return content;
|
return content;
|
||||||
// },
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { Node } from './node';
|
import { Node } from './node';
|
||||||
|
|
||||||
export class Banner extends Node {
|
export class Callout extends Node {
|
||||||
type = 'banner';
|
type = 'callout';
|
||||||
|
|
||||||
matching() {
|
matching() {
|
||||||
return this.DOMNode.nodeName === 'DIV' && this.DOMNode.classList.contains('banner');
|
return this.DOMNode.nodeName === 'DIV' && this.DOMNode.classList.contains('callout');
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
// 自定义节点
|
// 自定义节点
|
||||||
import { Iframe } from './nodes/iframe';
|
import { Iframe } from './nodes/iframe';
|
||||||
import { Attachment } from './nodes/attachment';
|
import { Attachment } from './nodes/attachment';
|
||||||
import { Banner } from './nodes/banner';
|
import { Callout } from './nodes/callout';
|
||||||
import { Status } from './nodes/status';
|
import { Status } from './nodes/status';
|
||||||
import { DocumentReference } from './nodes/document-reference';
|
import { DocumentReference } from './nodes/document-reference';
|
||||||
import { DocumentChildren } from './nodes/document-children';
|
import { DocumentChildren } from './nodes/document-children';
|
||||||
|
@ -55,7 +55,7 @@ export class Renderer {
|
||||||
this.nodes = [
|
this.nodes = [
|
||||||
Attachment,
|
Attachment,
|
||||||
Countdown,
|
Countdown,
|
||||||
Banner,
|
Callout,
|
||||||
Iframe,
|
Iframe,
|
||||||
Status,
|
Status,
|
||||||
Mention,
|
Mention,
|
||||||
|
|
|
@ -8,7 +8,7 @@ import katex from './markdownKatex';
|
||||||
import tasklist from './markdownTaskList';
|
import tasklist from './markdownTaskList';
|
||||||
import splitMixedLists from './markedownSplitMixedList';
|
import splitMixedLists from './markedownSplitMixedList';
|
||||||
import markdownUnderline from './markdownUnderline';
|
import markdownUnderline from './markdownUnderline';
|
||||||
import markdownBanner from './markdownBanner';
|
import markdownCallout from './markdownCallout';
|
||||||
import { markdownItTable } from './markdownTable';
|
import { markdownItTable } from './markdownTable';
|
||||||
import { createMarkdownContainer } from './markdownItContainer';
|
import { createMarkdownContainer } from './markdownItContainer';
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ const markdown = markdownit('commonmark')
|
||||||
.use(emoji)
|
.use(emoji)
|
||||||
.use(katex)
|
.use(katex)
|
||||||
// 以下为自定义节点
|
// 以下为自定义节点
|
||||||
.use(markdownBanner)
|
.use(markdownCallout)
|
||||||
.use(markdownAttachment)
|
.use(markdownAttachment)
|
||||||
.use(markdownCountdown)
|
.use(markdownCountdown)
|
||||||
.use(markdownIframe)
|
.use(markdownIframe)
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
import container from 'markdown-it-container';
|
import container from 'markdown-it-container';
|
||||||
|
|
||||||
export const typesAvailable = ['info', 'warning', 'danger', 'success'];
|
const typesAvailable = ['callout'];
|
||||||
|
|
||||||
const buildRender = (type) => (tokens, idx, options, env, slf) => {
|
const buildRender = (type) => (tokens, idx, options, env, slf) => {
|
||||||
const tag = tokens[idx];
|
const tag = tokens[idx];
|
||||||
|
|
||||||
if (tag.nesting === 1) {
|
if (tag.nesting === 1) {
|
||||||
tag.attrSet('data-type', type);
|
tag.attrJoin('class', `callout`);
|
||||||
tag.attrJoin('class', `banner banner-${type}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return slf.renderToken(tokens, idx, options, env, slf);
|
return slf.renderToken(tokens, idx, options, env, slf);
|
||||||
|
@ -16,7 +15,7 @@ const buildRender = (type) => (tokens, idx, options, env, slf) => {
|
||||||
/**
|
/**
|
||||||
* @param {object} md Markdown object
|
* @param {object} md Markdown object
|
||||||
*/
|
*/
|
||||||
export default function markdownBanner(md) {
|
export default function markdownCallout(md) {
|
||||||
// create a custom container to each callout type
|
// create a custom container to each callout type
|
||||||
typesAvailable.forEach((type) => {
|
typesAvailable.forEach((type) => {
|
||||||
md.use(container, type, {
|
md.use(container, type, {
|
|
@ -1,8 +1,8 @@
|
||||||
import { MarkdownSerializer as ProseMirrorMarkdownSerializer, defaultMarkdownSerializer } from 'prosemirror-markdown';
|
import { MarkdownSerializer as ProseMirrorMarkdownSerializer, defaultMarkdownSerializer } from 'prosemirror-markdown';
|
||||||
import { Attachment } from '../../extensions/attachment';
|
import { Attachment } from '../../extensions/attachment';
|
||||||
import { Banner } from '../../extensions/banner';
|
|
||||||
import { Bold } from '../../extensions/bold';
|
import { Bold } from '../../extensions/bold';
|
||||||
import { BulletList } from '../../extensions/bullet-list';
|
import { BulletList } from '../../extensions/bullet-list';
|
||||||
|
import { Callout } from '../../extensions/callout';
|
||||||
import { Code } from '../../extensions/code';
|
import { Code } from '../../extensions/code';
|
||||||
import { CodeBlock } from '../../extensions/code-block';
|
import { CodeBlock } from '../../extensions/code-block';
|
||||||
import { Countdown } from '../../extensions/countdown';
|
import { Countdown } from '../../extensions/countdown';
|
||||||
|
@ -92,14 +92,6 @@ const SerializerConfig = {
|
||||||
|
|
||||||
nodes: {
|
nodes: {
|
||||||
[Attachment.name]: renderCustomContainer('attachment'),
|
[Attachment.name]: renderCustomContainer('attachment'),
|
||||||
[Banner.name]: (state, node) => {
|
|
||||||
state.write(`:::${node.attrs.type || 'info'}\n`);
|
|
||||||
state.ensureNewLine();
|
|
||||||
state.renderContent(node);
|
|
||||||
state.ensureNewLine();
|
|
||||||
state.write(':::');
|
|
||||||
state.closeBlock(node);
|
|
||||||
},
|
|
||||||
blockquote: (state, node) => {
|
blockquote: (state, node) => {
|
||||||
if (node.attrs.multiline) {
|
if (node.attrs.multiline) {
|
||||||
state.write('>>>');
|
state.write('>>>');
|
||||||
|
@ -113,6 +105,14 @@ const SerializerConfig = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[BulletList.name]: defaultMarkdownSerializer.nodes.bullet_list,
|
[BulletList.name]: defaultMarkdownSerializer.nodes.bullet_list,
|
||||||
|
[Callout.name]: (state, node) => {
|
||||||
|
state.write(`:::callout\n`);
|
||||||
|
state.ensureNewLine();
|
||||||
|
state.renderContent(node);
|
||||||
|
state.ensureNewLine();
|
||||||
|
state.write(':::');
|
||||||
|
state.closeBlock(node);
|
||||||
|
},
|
||||||
[CodeBlock.name]: (state, node) => {
|
[CodeBlock.name]: (state, node) => {
|
||||||
state.write(`\`\`\`${node.attrs.language || ''}\n`);
|
state.write(`\`\`\`${node.attrs.language || ''}\n`);
|
||||||
state.text(node.textContent, false);
|
state.text(node.textContent, false);
|
||||||
|
|
|
@ -32,7 +32,7 @@ import { Blockquote } from './menus/blockquote';
|
||||||
import { HorizontalRule } from './menus/horizontal-rule';
|
import { HorizontalRule } from './menus/horizontal-rule';
|
||||||
import { Search } from './menus/search';
|
import { Search } from './menus/search';
|
||||||
|
|
||||||
import { Banner } from './menus/banner';
|
import { Callout } from './menus/callout';
|
||||||
import { Countdonw } from './menus/countdown';
|
import { Countdonw } from './menus/countdown';
|
||||||
import { DocumentReference } from './menus/document-reference';
|
import { DocumentReference } from './menus/document-reference';
|
||||||
import { Image } from './menus/image';
|
import { Image } from './menus/image';
|
||||||
|
@ -88,7 +88,7 @@ export const MenuBar: React.FC<{ editor: any }> = ({ editor }) => {
|
||||||
<HorizontalRule editor={editor} />
|
<HorizontalRule editor={editor} />
|
||||||
<Search editor={editor} />
|
<Search editor={editor} />
|
||||||
|
|
||||||
<Banner editor={editor} />
|
<Callout editor={editor} />
|
||||||
<Countdonw editor={editor} />
|
<Countdonw editor={editor} />
|
||||||
<DocumentReference editor={editor} />
|
<DocumentReference editor={editor} />
|
||||||
<Image editor={editor} />
|
<Image editor={editor} />
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { Editor } from '@tiptap/core';
|
|
||||||
import { BannerBubbleMenu } from './bubble';
|
|
||||||
|
|
||||||
export const Banner: React.FC<{ editor: Editor }> = ({ editor }) => {
|
|
||||||
if (!editor) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<BannerBubbleMenu editor={editor} />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
|
@ -5,7 +5,7 @@ import { Tooltip } from 'components/tooltip';
|
||||||
import { IconDrawBoard } from 'components/icons';
|
import { IconDrawBoard } from 'components/icons';
|
||||||
import { BubbleMenu } from '../../views/bubble-menu';
|
import { BubbleMenu } from '../../views/bubble-menu';
|
||||||
import { Divider } from '../../divider';
|
import { Divider } from '../../divider';
|
||||||
import { Banner } from '../../extensions/banner';
|
import { Callout } from '../../extensions/callout';
|
||||||
import { deleteNode } from '../../utils/delete-node';
|
import { deleteNode } from '../../utils/delete-node';
|
||||||
import styles from './bubble.module.scss';
|
import styles from './bubble.module.scss';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
|
@ -16,13 +16,13 @@ const TEXT_COLORS = ['#d83931', '#de7802', '#dc9b04', '#2ea121', '#245bdb', '#64
|
||||||
const BORDER_COLORS = ['#fbbfbc', '#fed4a4', '#fff67a', '#b7edb1', '#bacefd', '#cdb2fa', '#dee0e3'];
|
const BORDER_COLORS = ['#fbbfbc', '#fed4a4', '#fff67a', '#b7edb1', '#bacefd', '#cdb2fa', '#dee0e3'];
|
||||||
const BACKGROUND_COLORS = ['#fef1f1', '#feead2', '#ffc', '#d9f5d6', '#e1eaff', '#ece2fe', '#f2f3f5'];
|
const BACKGROUND_COLORS = ['#fef1f1', '#feead2', '#ffc', '#d9f5d6', '#e1eaff', '#ece2fe', '#f2f3f5'];
|
||||||
|
|
||||||
export const BannerBubbleMenu: React.FC<{ editor: Editor }> = ({ editor }) => {
|
export const CalloutBubbleMenu: React.FC<{ editor: Editor }> = ({ editor }) => {
|
||||||
const setColor = useCallback(
|
const setColor = useCallback(
|
||||||
(key, color) => {
|
(key, color) => {
|
||||||
return () => {
|
return () => {
|
||||||
editor
|
editor
|
||||||
.chain()
|
.chain()
|
||||||
.updateAttributes(Banner.name, {
|
.updateAttributes(Callout.name, {
|
||||||
[key]: color,
|
[key]: color,
|
||||||
})
|
})
|
||||||
.focus()
|
.focus()
|
||||||
|
@ -37,18 +37,17 @@ export const BannerBubbleMenu: React.FC<{ editor: Editor }> = ({ editor }) => {
|
||||||
className={'bubble-menu'}
|
className={'bubble-menu'}
|
||||||
editor={editor}
|
editor={editor}
|
||||||
pluginKey="banner-bubble-menu"
|
pluginKey="banner-bubble-menu"
|
||||||
shouldShow={() => editor.isActive(Banner.name)}
|
shouldShow={() => editor.isActive(Callout.name)}
|
||||||
matchRenderContainer={(node) => node && node.id === 'js-bannber-container'}
|
matchRenderContainer={(node) => node && node.id === 'js-bannber-container'}
|
||||||
>
|
>
|
||||||
<Space>
|
<Space>
|
||||||
<Popover
|
<Popover
|
||||||
spacing={10}
|
spacing={10}
|
||||||
visible
|
|
||||||
style={{ padding: '0 12px 12px', overflow: 'hidden' }}
|
style={{ padding: '0 12px 12px', overflow: 'hidden' }}
|
||||||
content={
|
content={
|
||||||
<>
|
<>
|
||||||
<section className={styles.colorWrap}>
|
<section className={styles.colorWrap}>
|
||||||
<Text type="tertiary">字体颜色</Text>
|
<Text type="secondary">字体颜色</Text>
|
||||||
<div>
|
<div>
|
||||||
{TEXT_COLORS.map((color) => (
|
{TEXT_COLORS.map((color) => (
|
||||||
<div className={styles.color} style={{ color: color }} onClick={setColor('textColor', color)}>
|
<div className={styles.color} style={{ color: color }} onClick={setColor('textColor', color)}>
|
||||||
|
@ -58,7 +57,7 @@ export const BannerBubbleMenu: React.FC<{ editor: Editor }> = ({ editor }) => {
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section className={styles.colorWrap}>
|
<section className={styles.colorWrap}>
|
||||||
<Text type="tertiary">边框颜色</Text>
|
<Text type="secondary">边框颜色</Text>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
{BORDER_COLORS.map((color) => (
|
{BORDER_COLORS.map((color) => (
|
||||||
|
@ -71,7 +70,7 @@ export const BannerBubbleMenu: React.FC<{ editor: Editor }> = ({ editor }) => {
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section className={styles.colorWrap}>
|
<section className={styles.colorWrap}>
|
||||||
<Text type="tertiary">背景颜色</Text>
|
<Text type="secondary">背景颜色</Text>
|
||||||
<div>
|
<div>
|
||||||
{BACKGROUND_COLORS.map((color) => (
|
{BACKGROUND_COLORS.map((color) => (
|
||||||
<div
|
<div
|
|
@ -0,0 +1,15 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Editor } from '@tiptap/core';
|
||||||
|
import { CalloutBubbleMenu } from './bubble';
|
||||||
|
|
||||||
|
export const Callout: React.FC<{ editor: Editor }> = ({ editor }) => {
|
||||||
|
if (!editor) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<CalloutBubbleMenu editor={editor} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
|
@ -15,6 +15,7 @@ import {
|
||||||
IconAttachment,
|
IconAttachment,
|
||||||
IconMath,
|
IconMath,
|
||||||
IconCountdown,
|
IconCountdown,
|
||||||
|
IconCallout,
|
||||||
} from 'components/icons';
|
} from 'components/icons';
|
||||||
import { GridSelect } from 'components/grid-select';
|
import { GridSelect } from 'components/grid-select';
|
||||||
import { isTitleActive } from '../../utils/is-active';
|
import { isTitleActive } from '../../utils/is-active';
|
||||||
|
@ -90,8 +91,8 @@ export const Insert: React.FC<{ editor: Editor }> = ({ editor }) => {
|
||||||
<IconStatus /> 状态
|
<IconStatus /> 状态
|
||||||
</Dropdown.Item>
|
</Dropdown.Item>
|
||||||
|
|
||||||
<Dropdown.Item onClick={() => editor.chain().focus().setBanner({ type: 'info' }).run()}>
|
<Dropdown.Item onClick={() => editor.chain().focus().setCallout().run()}>
|
||||||
<IconInfo /> 信息框
|
<IconCallout /> 高亮块
|
||||||
</Dropdown.Item>
|
</Dropdown.Item>
|
||||||
|
|
||||||
<Dropdown.Divider />
|
<Dropdown.Divider />
|
||||||
|
|
|
@ -19,6 +19,7 @@ import {
|
||||||
IconAttachment,
|
IconAttachment,
|
||||||
IconMath,
|
IconMath,
|
||||||
IconCountdown,
|
IconCountdown,
|
||||||
|
IconCallout,
|
||||||
} from 'components/icons';
|
} from 'components/icons';
|
||||||
import { createCountdown } from './countdown/service';
|
import { createCountdown } from './countdown/service';
|
||||||
import { createOrToggleLink } from './link/service';
|
import { createOrToggleLink } from './link/service';
|
||||||
|
@ -237,14 +238,14 @@ export const QUICK_INSERT_ITEMS = [
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
key: '信息框',
|
key: '高亮块',
|
||||||
label: (
|
label: (
|
||||||
<Space>
|
<Space>
|
||||||
<IconInfo />
|
<IconCallout />
|
||||||
信息框
|
高亮块
|
||||||
</Space>
|
</Space>
|
||||||
),
|
),
|
||||||
command: (editor: Editor) => editor.chain().focus().setBanner({ type: 'info' }).run(),
|
command: (editor: Editor) => editor.chain().focus().setCallout().run(),
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { Attachment } from './extensions/attachment';
|
import { Attachment } from './extensions/attachment';
|
||||||
import { BackgroundColor } from './extensions/background-color';
|
import { BackgroundColor } from './extensions/background-color';
|
||||||
import { Banner } from './extensions/banner';
|
|
||||||
import { Blockquote } from './extensions/blockquote';
|
import { Blockquote } from './extensions/blockquote';
|
||||||
import { Bold } from './extensions/bold';
|
import { Bold } from './extensions/bold';
|
||||||
import { BulletList } from './extensions/bullet-list';
|
import { BulletList } from './extensions/bullet-list';
|
||||||
|
import { Callout } from './extensions/callout';
|
||||||
import { Code } from './extensions/code';
|
import { Code } from './extensions/code';
|
||||||
import { CodeBlock } from './extensions/code-block';
|
import { CodeBlock } from './extensions/code-block';
|
||||||
import { Color } from './extensions/color';
|
import { Color } from './extensions/color';
|
||||||
|
@ -57,10 +57,10 @@ import { Paste } from './extensions/paste';
|
||||||
export const BaseKit = [
|
export const BaseKit = [
|
||||||
Attachment,
|
Attachment,
|
||||||
BackgroundColor,
|
BackgroundColor,
|
||||||
Banner,
|
|
||||||
Blockquote,
|
Blockquote,
|
||||||
Bold,
|
Bold,
|
||||||
BulletList,
|
BulletList,
|
||||||
|
Callout,
|
||||||
Code,
|
Code,
|
||||||
CodeBlock,
|
CodeBlock,
|
||||||
Color,
|
Color,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
.wrap {
|
.wrap {
|
||||||
line-height: 0;
|
line-height: 0;
|
||||||
|
margin-top: 0.75em;
|
||||||
|
|
||||||
.innerWrap {
|
.innerWrap {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -28,7 +29,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin-top: .25em;
|
margin-top: 0.25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
p:first-child {
|
p:first-child {
|
|
@ -1,12 +1,10 @@
|
||||||
|
import { useCallback } from 'react';
|
||||||
import { NodeViewWrapper, NodeViewContent } from '@tiptap/react';
|
import { NodeViewWrapper, NodeViewContent } from '@tiptap/react';
|
||||||
import { Popover } from '@douyinfe/semi-ui';
|
|
||||||
import cls from 'classnames';
|
import cls from 'classnames';
|
||||||
import { useToggle } from 'hooks/use-toggle';
|
|
||||||
import { EmojiPicker } from 'components/emoji-picker';
|
import { EmojiPicker } from 'components/emoji-picker';
|
||||||
import styles from './index.module.scss';
|
import styles from './index.module.scss';
|
||||||
import { useCallback, useEffect, useMemo } from 'react';
|
|
||||||
|
|
||||||
export const BannerWrapper = ({ node, updateAttributes }) => {
|
export const CalloutWrapper = ({ node, updateAttributes }) => {
|
||||||
const { emoji, textColor, borderColor, backgroundColor } = node.attrs;
|
const { emoji, textColor, borderColor, backgroundColor } = node.attrs;
|
||||||
|
|
||||||
const onSelectEmoji = useCallback((emoji) => {
|
const onSelectEmoji = useCallback((emoji) => {
|
Loading…
Reference in New Issue