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 { 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,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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(),
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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}>
|
||||||
|
{colors.map((color) => {
|
||||||
return (
|
return (
|
||||||
<Tag
|
<Tag
|
||||||
key={color}
|
key={color}
|
||||||
style={{ width: 24, height: 24, cursor: 'pointer' }}
|
style={{ width: 24, height: 24, cursor: 'pointer', background: color }}
|
||||||
type="solid"
|
type="solid"
|
||||||
color={color as unknown as any}
|
|
||||||
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"
|
||||||
>
|
>
|
||||||
|
|
Loading…
Reference in New Issue