mirror of https://github.com/fantasticit/think.git
feat: improve status
This commit is contained in:
parent
1756161ead
commit
5db270dcf6
|
@ -3,10 +3,16 @@ import { ReactNodeViewRenderer } from '@tiptap/react';
|
|||
import { StatusWrapper } from '../wrappers/status';
|
||||
import { getDatasetAttribute } from '../utils/dataset';
|
||||
|
||||
type IStatusAttrs = {
|
||||
color?: string;
|
||||
text?: string;
|
||||
defaultShowPicker?: boolean;
|
||||
};
|
||||
|
||||
declare module '@tiptap/core' {
|
||||
interface Commands<ReturnType> {
|
||||
status: {
|
||||
setStatus: () => ReturnType;
|
||||
setStatus: (arg: IStatusAttrs) => ReturnType;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -21,13 +27,16 @@ export const Status = Node.create({
|
|||
addAttributes() {
|
||||
return {
|
||||
color: {
|
||||
default: 'grey',
|
||||
default: '#FFA39E',
|
||||
parseHTML: getDatasetAttribute('color'),
|
||||
},
|
||||
text: {
|
||||
default: '',
|
||||
default: '请设置状态内容',
|
||||
parseHTML: getDatasetAttribute('text'),
|
||||
},
|
||||
defaultShowPicker: {
|
||||
default: false,
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ export const Insert: React.FC<{ editor: Editor }> = ({ editor }) => {
|
|||
<Dropdown.Divider />
|
||||
<Dropdown.Title>卡片</Dropdown.Title>
|
||||
|
||||
<Dropdown.Item onClick={() => editor.chain().focus().setStatus().run()}>
|
||||
<Dropdown.Item onClick={() => editor.chain().focus().setStatus({ defaultShowPicker: true }).run()}>
|
||||
<IconStatus /> 状态
|
||||
</Dropdown.Item>
|
||||
|
||||
|
|
|
@ -219,7 +219,14 @@ export const QUICK_INSERT_ITEMS = [
|
|||
状态
|
||||
</Space>
|
||||
),
|
||||
command: (editor: Editor) => editor.chain().focus().setStatus().run(),
|
||||
command: (editor: Editor) =>
|
||||
editor
|
||||
.chain()
|
||||
.focus()
|
||||
.setStatus({
|
||||
defaultShowPicker: true,
|
||||
})
|
||||
.run(),
|
||||
},
|
||||
|
||||
{
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
.tableWrapper {
|
||||
::selection {
|
||||
background-color: transparent;
|
||||
//background-color: transparent;
|
||||
}
|
||||
|
||||
&.selected-node {
|
||||
|
@ -18,7 +18,6 @@
|
|||
|
||||
.node-status {
|
||||
.semi-tag-default {
|
||||
height: 27px;
|
||||
border: 1px solid var(--node-border-color);
|
||||
}
|
||||
|
||||
|
@ -95,7 +94,7 @@
|
|||
&::after {
|
||||
position: absolute;
|
||||
content: '';
|
||||
inset: 0px;
|
||||
inset: 0;
|
||||
pointer-events: none;
|
||||
background-color: rgba(179, 212, 255, 0.3);
|
||||
}
|
||||
|
@ -111,7 +110,7 @@
|
|||
&::after {
|
||||
position: absolute;
|
||||
content: '';
|
||||
inset: 0px;
|
||||
inset: 0;
|
||||
pointer-events: none;
|
||||
background-color: transparent;
|
||||
border: 1px solid var(--node-hover-border-color) !important;
|
||||
|
@ -133,7 +132,7 @@
|
|||
&::after {
|
||||
position: absolute;
|
||||
content: '';
|
||||
inset: 0px;
|
||||
inset: 0;
|
||||
pointer-events: none;
|
||||
background-color: rgba(179, 212, 255, 0.3);
|
||||
border: 1px solid var(--node-selected-border-color) !important;
|
||||
|
|
|
@ -1,42 +1,123 @@
|
|||
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 { useToggle } from 'hooks/use-toggle';
|
||||
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 }) => {
|
||||
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 = (
|
||||
<Tag className="render-wrapper" color={color}>
|
||||
<Tag className="render-wrapper" style={{ backgroundColor: color }}>
|
||||
{text || '点击设置状态'}
|
||||
</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 (
|
||||
<NodeViewWrapper as="span" className={cls(styles.wrap, 'status')}>
|
||||
<NodeViewContent />
|
||||
{isEditable ? (
|
||||
<Popover
|
||||
showArrow
|
||||
visible={visible}
|
||||
onVisibleChange={onVisibleChange}
|
||||
content={
|
||||
<>
|
||||
<div style={{ width: 216 }}>
|
||||
<div style={{ marginBottom: 8 }}>
|
||||
<Input autofocus placeholder="输入状态" onChange={(v) => updateAttributes({ text: v })} />
|
||||
<Input ref={ref} placeholder="输入状态" onChange={(v) => updateAttributes({ text: v })} />
|
||||
</div>
|
||||
<Space>
|
||||
{['grey', 'red', 'green', 'orange', 'purple', 'teal'].map((color) => {
|
||||
return (
|
||||
<Tag
|
||||
key={color}
|
||||
style={{ width: 24, height: 24, cursor: 'pointer' }}
|
||||
type="solid"
|
||||
color={color as unknown as any}
|
||||
onClick={() => updateAttributes({ color })}
|
||||
></Tag>
|
||||
);
|
||||
})}
|
||||
</Space>
|
||||
</>
|
||||
<Collapsible isOpen={isOpen} collapseHeight={28}>
|
||||
<Space wrap={true}>
|
||||
{colors.map((color) => {
|
||||
return (
|
||||
<Tag
|
||||
key={color}
|
||||
style={{ width: 24, height: 24, cursor: 'pointer', background: color }}
|
||||
type="solid"
|
||||
onClick={() => updateAttributes({ color })}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</Space>
|
||||
</Collapsible>
|
||||
<div style={{ textAlign: 'right', marginTop: 8 }}>
|
||||
<Button size={'small'} onClick={toggleOpen}>
|
||||
{isOpen ? '收起' : '更多'}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
trigger="click"
|
||||
>
|
||||
|
|
Loading…
Reference in New Issue