feat: improve status

This commit is contained in:
fantasticit 2022-04-10 11:34:25 +08:00
parent 1756161ead
commit 5db270dcf6
5 changed files with 125 additions and 29 deletions

View File

@ -3,10 +3,16 @@ import { ReactNodeViewRenderer } from '@tiptap/react';
import { StatusWrapper } from '../wrappers/status'; import { StatusWrapper } from '../wrappers/status';
import { getDatasetAttribute } from '../utils/dataset'; import { getDatasetAttribute } from '../utils/dataset';
type IStatusAttrs = {
color?: string;
text?: string;
defaultShowPicker?: boolean;
};
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands<ReturnType> { interface Commands<ReturnType> {
status: { status: {
setStatus: () => ReturnType; setStatus: (arg: IStatusAttrs) => ReturnType;
}; };
} }
} }
@ -21,13 +27,16 @@ export const Status = Node.create({
addAttributes() { addAttributes() {
return { return {
color: { color: {
default: 'grey', default: '#FFA39E',
parseHTML: getDatasetAttribute('color'), parseHTML: getDatasetAttribute('color'),
}, },
text: { text: {
default: '', default: '请设置状态内容',
parseHTML: getDatasetAttribute('text'), parseHTML: getDatasetAttribute('text'),
}, },
defaultShowPicker: {
default: false,
},
}; };
}, },

View File

@ -86,7 +86,7 @@ export const Insert: React.FC<{ editor: Editor }> = ({ editor }) => {
<Dropdown.Divider /> <Dropdown.Divider />
<Dropdown.Title></Dropdown.Title> <Dropdown.Title></Dropdown.Title>
<Dropdown.Item onClick={() => editor.chain().focus().setStatus().run()}> <Dropdown.Item onClick={() => editor.chain().focus().setStatus({ defaultShowPicker: true }).run()}>
<IconStatus /> <IconStatus />
</Dropdown.Item> </Dropdown.Item>

View File

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

View File

@ -5,7 +5,7 @@
.tableWrapper { .tableWrapper {
::selection { ::selection {
background-color: transparent; //background-color: transparent;
} }
&.selected-node { &.selected-node {
@ -18,7 +18,6 @@
.node-status { .node-status {
.semi-tag-default { .semi-tag-default {
height: 27px;
border: 1px solid var(--node-border-color); border: 1px solid var(--node-border-color);
} }
@ -95,7 +94,7 @@
&::after { &::after {
position: absolute; position: absolute;
content: ''; content: '';
inset: 0px; inset: 0;
pointer-events: none; pointer-events: none;
background-color: rgba(179, 212, 255, 0.3); background-color: rgba(179, 212, 255, 0.3);
} }
@ -111,7 +110,7 @@
&::after { &::after {
position: absolute; position: absolute;
content: ''; content: '';
inset: 0px; inset: 0;
pointer-events: none; pointer-events: none;
background-color: transparent; background-color: transparent;
border: 1px solid var(--node-hover-border-color) !important; border: 1px solid var(--node-hover-border-color) !important;
@ -133,7 +132,7 @@
&::after { &::after {
position: absolute; position: absolute;
content: ''; content: '';
inset: 0px; inset: 0;
pointer-events: none; pointer-events: none;
background-color: rgba(179, 212, 255, 0.3); background-color: rgba(179, 212, 255, 0.3);
border: 1px solid var(--node-selected-border-color) !important; border: 1px solid var(--node-selected-border-color) !important;

View File

@ -1,42 +1,123 @@
import { NodeViewWrapper, NodeViewContent } from '@tiptap/react'; import { NodeViewWrapper, NodeViewContent } from '@tiptap/react';
import { Space, Popover, Tag, Input } from '@douyinfe/semi-ui'; import { Button, Collapsible, Space, Popover, Tag, Input } from '@douyinfe/semi-ui';
import cls from 'classnames'; import cls from 'classnames';
import { useToggle } from 'hooks/use-toggle';
import styles from './index.module.scss'; import styles from './index.module.scss';
import { useCallback, useEffect, useRef } from 'react';
const colors = [
'#F5222D',
'#FA541C',
'#FA8C16',
'#FADB14',
'#52C41A',
'#13C2C2',
'#1890FF',
'#2F54EB',
'#722ED1',
'#EB2F96',
'#FFE8E6',
'#FFECE0',
'#FFEFD1',
'#DEE8FC',
'#EFE1FA',
'#FAE1EB',
'#FFA39E',
'#FFBB96',
'#FFD591',
'#FFFB8F',
'#B7EB8F',
'#87E8DE',
'#91D5FF',
'#ADC6FF',
'#D3ADF7',
'#FFADD2',
'#FF4D4F',
'#FF7A45',
'#FFA940',
'#FFEC3D',
'#73D13D',
'#36CFC9',
'#40A9FF',
'#597EF7',
'#9254DE',
'#F759AB',
'#CF1322',
'#D4380D',
'#D46B08',
'#D4B106',
'#389E0D',
'#08979C',
];
export const StatusWrapper = ({ editor, node, updateAttributes }) => { export const StatusWrapper = ({ editor, node, updateAttributes }) => {
const isEditable = editor.isEditable; const isEditable = editor.isEditable;
const { color, text } = node.attrs; const { color, text, defaultShowPicker } = node.attrs;
const ref = useRef<HTMLInputElement>();
const [visible, toggleVisible] = useToggle(false);
const [isOpen, toggleOpen] = useToggle(false);
const content = ( const content = (
<Tag className="render-wrapper" color={color}> <Tag className="render-wrapper" style={{ backgroundColor: color }}>
{text || '点击设置状态'} {text || '点击设置状态'}
</Tag> </Tag>
); );
const onVisibleChange = useCallback(
(value) => {
toggleVisible(value);
if (defaultShowPicker) {
updateAttributes({ defaultShowPicker: false });
}
},
[defaultShowPicker, updateAttributes]
);
useEffect(() => {
if (defaultShowPicker) {
toggleVisible(true);
}
}, [defaultShowPicker]);
useEffect(() => {
if (visible) {
ref.current?.focus();
}
}, [visible]);
return ( return (
<NodeViewWrapper as="span" className={cls(styles.wrap, 'status')}> <NodeViewWrapper as="span" className={cls(styles.wrap, 'status')}>
<NodeViewContent /> <NodeViewContent />
{isEditable ? ( {isEditable ? (
<Popover <Popover
showArrow showArrow
visible={visible}
onVisibleChange={onVisibleChange}
content={ content={
<> <div style={{ width: 216 }}>
<div style={{ marginBottom: 8 }}> <div style={{ marginBottom: 8 }}>
<Input autofocus placeholder="输入状态" onChange={(v) => updateAttributes({ text: v })} /> <Input ref={ref} placeholder="输入状态" onChange={(v) => updateAttributes({ text: v })} />
</div> </div>
<Space> <Collapsible isOpen={isOpen} collapseHeight={28}>
{['grey', 'red', 'green', 'orange', 'purple', 'teal'].map((color) => { <Space wrap={true}>
return ( {colors.map((color) => {
<Tag return (
key={color} <Tag
style={{ width: 24, height: 24, cursor: 'pointer' }} key={color}
type="solid" style={{ width: 24, height: 24, cursor: 'pointer', background: color }}
color={color as unknown as any} type="solid"
onClick={() => updateAttributes({ color })} onClick={() => updateAttributes({ color })}
></Tag> />
); );
})} })}
</Space> </Space>
</> </Collapsible>
<div style={{ textAlign: 'right', marginTop: 8 }}>
<Button size={'small'} onClick={toggleOpen}>
{isOpen ? '收起' : '更多'}
</Button>
</div>
</div>
} }
trigger="click" trigger="click"
> >