mirror of https://github.com/fantasticit/think.git
tiptap: improve banner
This commit is contained in:
parent
367800c24f
commit
4147f3821a
|
@ -0,0 +1,276 @@
|
||||||
|
export const EXPRESSIONES = [
|
||||||
|
'😀',
|
||||||
|
'😃',
|
||||||
|
'😄',
|
||||||
|
'😁',
|
||||||
|
'😆',
|
||||||
|
'😅',
|
||||||
|
'😂',
|
||||||
|
'🤣',
|
||||||
|
'🥲',
|
||||||
|
'😊',
|
||||||
|
'😇',
|
||||||
|
'🙂',
|
||||||
|
'🙃',
|
||||||
|
'😉',
|
||||||
|
'😌',
|
||||||
|
'😍',
|
||||||
|
'🥰',
|
||||||
|
'😘',
|
||||||
|
'😗',
|
||||||
|
'😙',
|
||||||
|
'😚',
|
||||||
|
'😋',
|
||||||
|
'😛',
|
||||||
|
'😝',
|
||||||
|
'😜',
|
||||||
|
'🤪',
|
||||||
|
'🤨',
|
||||||
|
'🧐',
|
||||||
|
'🤓',
|
||||||
|
'😎',
|
||||||
|
'🥸',
|
||||||
|
'🤩',
|
||||||
|
'🥳',
|
||||||
|
'😏',
|
||||||
|
'😒',
|
||||||
|
'😞',
|
||||||
|
'😔',
|
||||||
|
'😟',
|
||||||
|
'😕',
|
||||||
|
'🙁',
|
||||||
|
'😣',
|
||||||
|
'😖',
|
||||||
|
'😫',
|
||||||
|
'😩',
|
||||||
|
'🥺',
|
||||||
|
'😢',
|
||||||
|
'😭',
|
||||||
|
'😤',
|
||||||
|
'😠',
|
||||||
|
'😡',
|
||||||
|
'🤬',
|
||||||
|
'🤯',
|
||||||
|
'😳',
|
||||||
|
'🥵',
|
||||||
|
'🥶',
|
||||||
|
'😱',
|
||||||
|
'😨',
|
||||||
|
'😰',
|
||||||
|
'😥',
|
||||||
|
'😓',
|
||||||
|
'🤗',
|
||||||
|
'🤔',
|
||||||
|
'🤭',
|
||||||
|
'🤫',
|
||||||
|
'🤥',
|
||||||
|
'😶',
|
||||||
|
'😐',
|
||||||
|
'😑',
|
||||||
|
'😬',
|
||||||
|
'🙄',
|
||||||
|
'😯',
|
||||||
|
'😦',
|
||||||
|
'😧',
|
||||||
|
'😮',
|
||||||
|
'😲',
|
||||||
|
'🥱',
|
||||||
|
'😴',
|
||||||
|
'🤤',
|
||||||
|
'😪',
|
||||||
|
'😵',
|
||||||
|
'🤐',
|
||||||
|
'🥴',
|
||||||
|
'🤢',
|
||||||
|
'🤮',
|
||||||
|
'🤧',
|
||||||
|
'😷',
|
||||||
|
'🤒',
|
||||||
|
'🤕',
|
||||||
|
'🤑',
|
||||||
|
'🤠',
|
||||||
|
'😈',
|
||||||
|
'👿',
|
||||||
|
'👹',
|
||||||
|
'👺',
|
||||||
|
'🤡',
|
||||||
|
'💩',
|
||||||
|
'👻',
|
||||||
|
'💀',
|
||||||
|
'☠️',
|
||||||
|
'👽',
|
||||||
|
'👾',
|
||||||
|
'🤖',
|
||||||
|
'🎃',
|
||||||
|
'😺',
|
||||||
|
'😸',
|
||||||
|
'😹',
|
||||||
|
'😻',
|
||||||
|
'😼',
|
||||||
|
'😽',
|
||||||
|
'🙀',
|
||||||
|
'😿',
|
||||||
|
'😾',
|
||||||
|
];
|
||||||
|
|
||||||
|
export const GESTURES = [
|
||||||
|
'👋',
|
||||||
|
'🤚',
|
||||||
|
'🖐',
|
||||||
|
'✋',
|
||||||
|
'🖖',
|
||||||
|
'👌',
|
||||||
|
'🤌',
|
||||||
|
'🤏',
|
||||||
|
'✌️',
|
||||||
|
'🤞',
|
||||||
|
'🤟',
|
||||||
|
'🤘',
|
||||||
|
'🤙',
|
||||||
|
'👈',
|
||||||
|
'👉',
|
||||||
|
'👆',
|
||||||
|
'🖕',
|
||||||
|
'👇',
|
||||||
|
'☝️',
|
||||||
|
'👍',
|
||||||
|
'👎',
|
||||||
|
'✊',
|
||||||
|
'👊',
|
||||||
|
'🤛',
|
||||||
|
'🤜',
|
||||||
|
'👏',
|
||||||
|
'🙌',
|
||||||
|
'👐',
|
||||||
|
'🤲',
|
||||||
|
'🤝',
|
||||||
|
'🙏',
|
||||||
|
'✍️',
|
||||||
|
'💅',
|
||||||
|
'🤳',
|
||||||
|
'💪',
|
||||||
|
'🦾',
|
||||||
|
'🦵',
|
||||||
|
'🦿',
|
||||||
|
'🦶',
|
||||||
|
'👣',
|
||||||
|
'👂',
|
||||||
|
'🦻',
|
||||||
|
'👃',
|
||||||
|
'🫀',
|
||||||
|
'🫁',
|
||||||
|
'🧠',
|
||||||
|
'🦷',
|
||||||
|
'🦴',
|
||||||
|
'👀',
|
||||||
|
'👁',
|
||||||
|
'👅',
|
||||||
|
'👄',
|
||||||
|
'💋',
|
||||||
|
'🩸',
|
||||||
|
];
|
||||||
|
|
||||||
|
export const SYMBOLS = [
|
||||||
|
'⭕',
|
||||||
|
'✅',
|
||||||
|
'❎',
|
||||||
|
'✳️',
|
||||||
|
'✴️',
|
||||||
|
'❇️',
|
||||||
|
'#️⃣',
|
||||||
|
'*️⃣',
|
||||||
|
'0️⃣',
|
||||||
|
'1️⃣',
|
||||||
|
'2️⃣',
|
||||||
|
'3️⃣',
|
||||||
|
'4️⃣',
|
||||||
|
'5️⃣',
|
||||||
|
'6️⃣',
|
||||||
|
'7️⃣',
|
||||||
|
'8️⃣',
|
||||||
|
'9️⃣',
|
||||||
|
'🔟',
|
||||||
|
'⛔',
|
||||||
|
'🚫',
|
||||||
|
'🚳',
|
||||||
|
'🚭',
|
||||||
|
'🚯',
|
||||||
|
'🚱',
|
||||||
|
'🚷',
|
||||||
|
'📵',
|
||||||
|
'🔞',
|
||||||
|
'☢️',
|
||||||
|
'☣️',
|
||||||
|
'↩️',
|
||||||
|
'↪️',
|
||||||
|
'⤴️',
|
||||||
|
'⤵️',
|
||||||
|
'🔃',
|
||||||
|
'🔄',
|
||||||
|
'♈',
|
||||||
|
'♉',
|
||||||
|
'♊',
|
||||||
|
'♋',
|
||||||
|
'♌',
|
||||||
|
'♍',
|
||||||
|
'♎',
|
||||||
|
'♏',
|
||||||
|
'♐',
|
||||||
|
'♑',
|
||||||
|
'♒',
|
||||||
|
'♓',
|
||||||
|
'⛎',
|
||||||
|
'🛐',
|
||||||
|
'⚛️',
|
||||||
|
'🕉️',
|
||||||
|
'🕉',
|
||||||
|
'✡️',
|
||||||
|
'☸️',
|
||||||
|
'☯️',
|
||||||
|
'✝️',
|
||||||
|
'☦️',
|
||||||
|
'☪️',
|
||||||
|
'☮️',
|
||||||
|
'🕎',
|
||||||
|
'🔯',
|
||||||
|
'🔀',
|
||||||
|
'🔁',
|
||||||
|
'🔂',
|
||||||
|
'⏩',
|
||||||
|
'⏭️',
|
||||||
|
'⏭',
|
||||||
|
'⏯️',
|
||||||
|
'⏯',
|
||||||
|
'⏪',
|
||||||
|
'⏮️',
|
||||||
|
'⏮',
|
||||||
|
'🔼',
|
||||||
|
'⏫',
|
||||||
|
'🔽',
|
||||||
|
'⏬',
|
||||||
|
'⏸️',
|
||||||
|
'⏸',
|
||||||
|
'⏹️',
|
||||||
|
'⏹',
|
||||||
|
'⏺️',
|
||||||
|
'⏺',
|
||||||
|
'⏏️',
|
||||||
|
'🎦',
|
||||||
|
'📶',
|
||||||
|
'📳',
|
||||||
|
'📴',
|
||||||
|
'🏧',
|
||||||
|
'🚮',
|
||||||
|
'🚰',
|
||||||
|
'♿',
|
||||||
|
'🚹',
|
||||||
|
'🚺',
|
||||||
|
'🚻',
|
||||||
|
'🚼',
|
||||||
|
'🚾',
|
||||||
|
'🛂',
|
||||||
|
'🛃',
|
||||||
|
'🛄',
|
||||||
|
'🛅',
|
||||||
|
'🚸',
|
||||||
|
];
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,24 @@
|
||||||
|
.wrap {
|
||||||
|
height: 300px;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.listWrap {
|
||||||
|
display: flex;
|
||||||
|
width: 320px;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
list-style: none;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
> li {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
padding: 4px;
|
||||||
|
font-size: 24px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Popover, Typography } from '@douyinfe/semi-ui';
|
||||||
|
import { EXPRESSIONES, GESTURES, SYMBOLS } from './constants';
|
||||||
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
|
const { Title } = Typography;
|
||||||
|
|
||||||
|
const LIST = [
|
||||||
|
{
|
||||||
|
title: '符号',
|
||||||
|
data: SYMBOLS,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '表情',
|
||||||
|
data: EXPRESSIONES,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '手势',
|
||||||
|
data: GESTURES,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
onSelectEmoji: (arg: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const EmojiPicker: React.FC<IProps> = ({ onSelectEmoji, children }) => {
|
||||||
|
return (
|
||||||
|
<Popover
|
||||||
|
showArrow
|
||||||
|
zIndex={10000}
|
||||||
|
trigger="click"
|
||||||
|
position="bottomLeft"
|
||||||
|
content={
|
||||||
|
<div className={styles.wrap}>
|
||||||
|
{LIST.map((item, index) => {
|
||||||
|
return (
|
||||||
|
<div key={item.title} className={styles.sectionWrap}>
|
||||||
|
<Title heading={6} style={{ margin: `${index === 0 ? 0 : 16}px 0 6px` }}>
|
||||||
|
{item.title}
|
||||||
|
</Title>
|
||||||
|
<ul className={styles.listWrap}>
|
||||||
|
{(item.data || []).map((ex) => (
|
||||||
|
<li key={ex} onClick={() => onSelectEmoji(ex)}>
|
||||||
|
{ex}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<span>{children}</span>
|
||||||
|
</Popover>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,32 @@
|
||||||
|
import { Icon } from '@douyinfe/semi-ui';
|
||||||
|
|
||||||
|
export const IconDrawBoard: React.FC<{ style?: React.CSSProperties }> = ({ style = {} }) => {
|
||||||
|
return (
|
||||||
|
<Icon
|
||||||
|
style={style}
|
||||||
|
svg={
|
||||||
|
<svg
|
||||||
|
width="1em"
|
||||||
|
height="1em"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
data-icon="StyleSetOutlined"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M21.957 2.13a1 1 0 0 0-1.406.147l-9.11 11.25a6.632 6.632 0 0 0-1.367 2.969.221.221 0 0 0 .302.244 6.632 6.632 0 0 0 2.62-1.955l9.109-11.25a1 1 0 0 0-.148-1.406Z"
|
||||||
|
fill="currentColor"
|
||||||
|
></path>
|
||||||
|
<path
|
||||||
|
d="M17.008 3.665a13.454 13.454 0 0 0-5.06-.984l-.024.004-.538.011-.51.03c-1.191.091-2.37.343-3.51.75a12.305 12.305 0 0 0-3.754 2.142c-1.096.922-1.96 1.99-2.568 3.176a8.435 8.435 0 0 0-.96 3.885c0 1.335.324 2.63.962 3.848.608 1.157 1.474 2.195 2.573 3.083a12.303 12.303 0 0 0 3.755 2.049c1.444.494 2.981.745 4.563.745l.545-.01.525-.029a14.43 14.43 0 0 0 1.57-.203l.722-.148.196-.06c.514-.186.96-.566 1.253-1.083a2.87 2.87 0 0 0 .26-2.178l-.09-.349-.03-.218a2.301 2.301 0 0 1 .357-1.454c.357-.544.93-.868 1.538-.871h1.768l.204-.007c1.614-.113 2.91-1.56 3.007-3.365l.006-.22-.006-.24-.05-.432-.067-.404a8.844 8.844 0 0 0-1.236-3.08 10.13 10.13 0 0 0-.802-1.096l-1.199 1.48c.154.2.298.406.43.617.483.76.81 1.563.974 2.393l.06.358.032.276.003.086-.007.22-.021.169c-.12.724-.604 1.301-1.19 1.38l-.138.01h-1.77l-.247.008c-1.14.079-2.192.702-2.847 1.7a4.145 4.145 0 0 0-.574 3.156l.068.273.037.13.028.154a.993.993 0 0 1-.118.588.58.58 0 0 1-.248.247l-.07.021-.67.134-.549.085a12.6 12.6 0 0 1-1.657.11 12.18 12.18 0 0 1-3.961-.647 10.426 10.426 0 0 1-3.19-1.734c-.9-.729-1.606-1.57-2.096-2.5a6.38 6.38 0 0 1-.75-2.984c0-1.037.254-2.06.755-3.034.495-.963 1.206-1.839 2.11-2.6A10.494 10.494 0 0 1 7.99 5.235a11.42 11.42 0 0 1 3.41-.677l.538-.01.496.01c1.153.048 2.281.264 3.338.633l1.236-1.526Z"
|
||||||
|
fill="currentColor"
|
||||||
|
></path>
|
||||||
|
<path
|
||||||
|
d="M6.875 14.466a1.377 1.377 0 0 0-1.374-1.374 1.375 1.375 0 0 0 0 2.747c.758 0 1.374-.616 1.374-1.373ZM8.124 9.47a1.375 1.375 0 0 0-2.748 0 1.374 1.374 0 1 0 2.748 0Zm5.246-1.874a1.374 1.374 0 1 0-2.747-.001 1.374 1.374 0 0 0 2.747 0Z"
|
||||||
|
fill="currentColor"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
|
@ -49,3 +49,4 @@ export * from './IconSub';
|
||||||
export * from './IconSup';
|
export * from './IconSup';
|
||||||
export * from './IconGlobe';
|
export * from './IconGlobe';
|
||||||
export * from './IconCountdown';
|
export * from './IconCountdown';
|
||||||
|
export * from './IconDrawBoard';
|
||||||
|
|
|
@ -31,6 +31,18 @@ export const Banner = Node.create({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
emoji: {
|
||||||
|
default: '✅',
|
||||||
|
},
|
||||||
|
textColor: {
|
||||||
|
default: '#d83931',
|
||||||
|
},
|
||||||
|
borderColor: {
|
||||||
|
default: '#fbbfbc',
|
||||||
|
},
|
||||||
|
backgroundColor: {
|
||||||
|
default: '#fef1f1',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
.colorWrap {
|
||||||
|
margin-top: 16px;
|
||||||
|
|
||||||
|
> div {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
margin-top: 8px;
|
||||||
|
|
||||||
|
.color {
|
||||||
|
display: flex;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px solid var(--semi-color-border);
|
||||||
|
border-radius: 4px;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&:not(:first-of-type) {
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,13 +1,37 @@
|
||||||
import { Editor } from '@tiptap/core';
|
import { Editor } from '@tiptap/core';
|
||||||
import { Space, Button } from '@douyinfe/semi-ui';
|
import { Space, Button, Popover, Typography } from '@douyinfe/semi-ui';
|
||||||
import { IconDelete, IconTickCircle, IconAlertTriangle, IconClear, IconInfoCircle } from '@douyinfe/semi-icons';
|
import { IconDelete } from '@douyinfe/semi-icons';
|
||||||
import { Tooltip } from 'components/tooltip';
|
import { Tooltip } from 'components/tooltip';
|
||||||
|
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 { Banner } from '../../extensions/banner';
|
||||||
import { deleteNode } from '../../utils/delete-node';
|
import { deleteNode } from '../../utils/delete-node';
|
||||||
|
import styles from './bubble.module.scss';
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
|
||||||
|
const { Text } = Typography;
|
||||||
|
|
||||||
|
const TEXT_COLORS = ['#d83931', '#de7802', '#dc9b04', '#2ea121', '#245bdb', '#6425d0', '#646a73'];
|
||||||
|
const BORDER_COLORS = ['#fbbfbc', '#fed4a4', '#fff67a', '#b7edb1', '#bacefd', '#cdb2fa', '#dee0e3'];
|
||||||
|
const BACKGROUND_COLORS = ['#fef1f1', '#feead2', '#ffc', '#d9f5d6', '#e1eaff', '#ece2fe', '#f2f3f5'];
|
||||||
|
|
||||||
export const BannerBubbleMenu: React.FC<{ editor: Editor }> = ({ editor }) => {
|
export const BannerBubbleMenu: React.FC<{ editor: Editor }> = ({ editor }) => {
|
||||||
|
const setColor = useCallback(
|
||||||
|
(key, color) => {
|
||||||
|
return () => {
|
||||||
|
editor
|
||||||
|
.chain()
|
||||||
|
.updateAttributes(Banner.name, {
|
||||||
|
[key]: color,
|
||||||
|
})
|
||||||
|
.focus()
|
||||||
|
.run();
|
||||||
|
};
|
||||||
|
},
|
||||||
|
[editor]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BubbleMenu
|
<BubbleMenu
|
||||||
className={'bubble-menu'}
|
className={'bubble-menu'}
|
||||||
|
@ -17,80 +41,53 @@ export const BannerBubbleMenu: React.FC<{ editor: Editor }> = ({ editor }) => {
|
||||||
matchRenderContainer={(node) => node && node.id === 'js-bannber-container'}
|
matchRenderContainer={(node) => node && node.id === 'js-bannber-container'}
|
||||||
>
|
>
|
||||||
<Space>
|
<Space>
|
||||||
<Tooltip content="信息">
|
<Popover
|
||||||
<Button
|
spacing={10}
|
||||||
size="small"
|
visible
|
||||||
type="tertiary"
|
style={{ padding: '0 12px 12px', overflow: 'hidden' }}
|
||||||
theme="borderless"
|
content={
|
||||||
icon={<IconInfoCircle style={{ color: 'var(--semi-color-info)' }} />}
|
<>
|
||||||
onClick={() => {
|
<section className={styles.colorWrap}>
|
||||||
editor
|
<Text type="tertiary">字体颜色</Text>
|
||||||
.chain()
|
<div>
|
||||||
.updateAttributes(Banner.name, {
|
{TEXT_COLORS.map((color) => (
|
||||||
type: 'info',
|
<div className={styles.color} style={{ color: color }} onClick={setColor('textColor', color)}>
|
||||||
})
|
A
|
||||||
.focus()
|
</div>
|
||||||
.run();
|
))}
|
||||||
}}
|
</div>
|
||||||
/>
|
</section>
|
||||||
</Tooltip>
|
<section className={styles.colorWrap}>
|
||||||
|
<Text type="tertiary">边框颜色</Text>
|
||||||
<Tooltip content="警告">
|
|
||||||
<Button
|
|
||||||
onClick={() => {
|
|
||||||
editor
|
|
||||||
.chain()
|
|
||||||
.updateAttributes(Banner.name, {
|
|
||||||
type: 'warning',
|
|
||||||
})
|
|
||||||
.focus()
|
|
||||||
.run();
|
|
||||||
}}
|
|
||||||
icon={<IconAlertTriangle style={{ color: 'var(--semi-color-warning)' }} />}
|
|
||||||
type="tertiary"
|
|
||||||
theme="borderless"
|
|
||||||
size="small"
|
|
||||||
/>
|
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
<Tooltip content="危险">
|
|
||||||
<Button
|
|
||||||
onClick={() => {
|
|
||||||
editor
|
|
||||||
.chain()
|
|
||||||
.updateAttributes(Banner.name, {
|
|
||||||
type: 'danger',
|
|
||||||
})
|
|
||||||
.focus()
|
|
||||||
.run();
|
|
||||||
}}
|
|
||||||
icon={<IconClear style={{ color: 'var(--semi-color-danger)' }} />}
|
|
||||||
type="tertiary"
|
|
||||||
theme="borderless"
|
|
||||||
size="small"
|
|
||||||
/>
|
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
<Tooltip content="成功">
|
|
||||||
<Button
|
|
||||||
onClick={() => {
|
|
||||||
editor
|
|
||||||
.chain()
|
|
||||||
.updateAttributes(Banner.name, {
|
|
||||||
type: 'success',
|
|
||||||
})
|
|
||||||
.focus()
|
|
||||||
.run();
|
|
||||||
}}
|
|
||||||
icon={<IconTickCircle style={{ color: 'var(--semi-color-success)' }} />}
|
|
||||||
type="tertiary"
|
|
||||||
theme="borderless"
|
|
||||||
size="small"
|
|
||||||
/>
|
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{BORDER_COLORS.map((color) => (
|
||||||
|
<div
|
||||||
|
className={styles.color}
|
||||||
|
style={{ backgroundColor: color }}
|
||||||
|
onClick={setColor('borderColor', color)}
|
||||||
|
></div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section className={styles.colorWrap}>
|
||||||
|
<Text type="tertiary">背景颜色</Text>
|
||||||
|
<div>
|
||||||
|
{BACKGROUND_COLORS.map((color) => (
|
||||||
|
<div
|
||||||
|
className={styles.color}
|
||||||
|
style={{ backgroundColor: color }}
|
||||||
|
onClick={setColor('backgroundColor', color)}
|
||||||
|
></div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Button icon={<IconDrawBoard />} type="tertiary" theme="borderless" size="small" />
|
||||||
|
</Popover>
|
||||||
<Divider />
|
<Divider />
|
||||||
|
|
||||||
<Tooltip content="删除" hideOnClick>
|
<Tooltip content="删除" hideOnClick>
|
||||||
<Button
|
<Button
|
||||||
size="small"
|
size="small"
|
||||||
|
|
|
@ -1,10 +1,34 @@
|
||||||
.wrap {
|
.wrap {
|
||||||
line-height: 0;
|
line-height: 0;
|
||||||
border: 1px solid var(--node-border-color);
|
|
||||||
|
.innerWrap {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
padding: 16px;
|
||||||
|
border-width: 1px;
|
||||||
|
border-style: solid;
|
||||||
border-radius: var(--border-radius);
|
border-radius: var(--border-radius);
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
line-height: 24px;
|
||||||
|
font-size: 20px;
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0;
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
> div {
|
||||||
|
flex: 1;
|
||||||
|
padding-left: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin-top: .25em;
|
margin-top: 0.25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
p:first-child {
|
p:first-child {
|
||||||
|
|
|
@ -1,12 +1,36 @@
|
||||||
import { NodeViewWrapper, NodeViewContent } from '@tiptap/react';
|
import { NodeViewWrapper, NodeViewContent } from '@tiptap/react';
|
||||||
import { Banner as SemiBanner } from '@douyinfe/semi-ui';
|
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 styles from './index.module.scss';
|
import styles from './index.module.scss';
|
||||||
|
import { useCallback, useEffect, useMemo } from 'react';
|
||||||
|
|
||||||
|
export const BannerWrapper = ({ node, updateAttributes }) => {
|
||||||
|
const { emoji, textColor, borderColor, backgroundColor } = node.attrs;
|
||||||
|
|
||||||
|
const onSelectEmoji = useCallback((emoji) => {
|
||||||
|
updateAttributes({ emoji });
|
||||||
|
}, []);
|
||||||
|
|
||||||
export const BannerWrapper = ({ node }) => {
|
|
||||||
return (
|
return (
|
||||||
<NodeViewWrapper id="js-bannber-container" className={cls(styles.wrap, 'render-wrapper')}>
|
<NodeViewWrapper id="js-bannber-container" className={cls(styles.wrap)}>
|
||||||
<SemiBanner type={node.attrs.type} description={<NodeViewContent />} closeIcon={null} fullMode={false} />
|
<div
|
||||||
|
className={cls(styles.innerWrap, 'render-wrapper')}
|
||||||
|
style={{
|
||||||
|
borderColor,
|
||||||
|
backgroundColor,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<EmojiPicker onSelectEmoji={onSelectEmoji}>
|
||||||
|
<span className={styles.icon}>{emoji || 'Icon'}</span>
|
||||||
|
</EmojiPicker>
|
||||||
|
<NodeViewContent
|
||||||
|
style={{
|
||||||
|
color: textColor,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</NodeViewWrapper>
|
</NodeViewWrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue