mirror of https://github.com/fantasticit/think.git
feat: improve tiptap
This commit is contained in:
parent
e211f07794
commit
0e54e4af65
|
@ -13,6 +13,7 @@ import { DocumentReference } from './extensions/documentReference';
|
|||
import { Dropcursor } from './extensions/dropCursor';
|
||||
import { Emoji } from './extensions/emoji';
|
||||
import { EvokeMenu } from './extensions/evokeMenu';
|
||||
import { Focus } from './extensions/focus';
|
||||
import { FontSize } from './extensions/fontSize';
|
||||
import { FootnoteDefinition } from './extensions/footnoteDefinition';
|
||||
import { FootnoteReference } from './extensions/footnoteReference';
|
||||
|
@ -67,6 +68,7 @@ export const BaseKit = [
|
|||
Dropcursor,
|
||||
Emoji,
|
||||
EvokeMenu,
|
||||
Focus,
|
||||
FontSize,
|
||||
FootnoteDefinition,
|
||||
FootnoteReference,
|
||||
|
|
|
@ -15,11 +15,7 @@ export const StatusWrapper = ({ editor, node, updateAttributes }) => {
|
|||
content={
|
||||
<>
|
||||
<div style={{ marginBottom: 8 }}>
|
||||
<Input
|
||||
autofocus
|
||||
placeholder="输入状态"
|
||||
onChange={(v) => updateAttributes({ text: v })}
|
||||
/>
|
||||
<Input autofocus placeholder="输入状态" onChange={(v) => updateAttributes({ text: v })} />
|
||||
</div>
|
||||
<Space>
|
||||
{['grey', 'red', 'green', 'orange', 'purple', 'teal'].map((color) => {
|
||||
|
@ -44,7 +40,7 @@ export const StatusWrapper = ({ editor, node, updateAttributes }) => {
|
|||
) : (
|
||||
content
|
||||
)}
|
||||
<NodeViewContent></NodeViewContent>
|
||||
{/* <NodeViewContent></NodeViewContent> */}
|
||||
</NodeViewWrapper>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -54,21 +54,22 @@ export const EvokeMenu = Node.create({
|
|||
const isEmpty = parent && parent.node.content.size === 0;
|
||||
const isSlash = parent && parent.node.textContent === '/';
|
||||
const isTopLevel = state.selection.$from.depth === 1;
|
||||
const hasOtherChildren = parent && parent.node.content.childCount > 1;
|
||||
|
||||
if (isTopLevel) {
|
||||
if (isEmpty) {
|
||||
decorations.push(
|
||||
Decoration.node(parent.pos, parent.pos + parent.node.nodeSize, {
|
||||
'class': 'placeholder',
|
||||
'class': 'is-empty',
|
||||
'data-placeholder': '输入 / 唤起更多',
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
if (isSlash) {
|
||||
if (isSlash && !hasOtherChildren) {
|
||||
decorations.push(
|
||||
Decoration.node(parent.pos, parent.pos + parent.node.nodeSize, {
|
||||
'class': 'placeholder',
|
||||
'class': 'is-empty',
|
||||
'data-placeholder': ` 继续输入进行过滤`,
|
||||
})
|
||||
);
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
import { Extension } from '@tiptap/core';
|
||||
import { Plugin, PluginKey } from 'prosemirror-state';
|
||||
import { DecorationSet, Decoration } from 'prosemirror-view';
|
||||
|
||||
export interface FocusOptions {
|
||||
className: string;
|
||||
mode: 'all' | 'deepest' | 'shallowest';
|
||||
}
|
||||
|
||||
export const Focus = Extension.create<FocusOptions>({
|
||||
name: 'focus',
|
||||
|
||||
addOptions() {
|
||||
return {
|
||||
className: 'has-focus',
|
||||
mode: 'all',
|
||||
};
|
||||
},
|
||||
|
||||
addProseMirrorPlugins() {
|
||||
return [
|
||||
new Plugin({
|
||||
key: new PluginKey('focus'),
|
||||
props: {
|
||||
decorations: ({ doc, selection }) => {
|
||||
const { isEditable, isFocused } = this.editor;
|
||||
const { anchor } = selection;
|
||||
const decorations: Decoration[] = [];
|
||||
|
||||
if (!isEditable || !isFocused) {
|
||||
return DecorationSet.create(doc, []);
|
||||
}
|
||||
|
||||
// Maximum Levels
|
||||
let maxLevels = 0;
|
||||
|
||||
if (this.options.mode === 'deepest') {
|
||||
doc.descendants((node, pos) => {
|
||||
if (node.isText) {
|
||||
return;
|
||||
}
|
||||
|
||||
const isCurrent = anchor >= pos && anchor <= pos + node.nodeSize - 1;
|
||||
|
||||
if (!isCurrent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
maxLevels += 1;
|
||||
});
|
||||
}
|
||||
|
||||
// Loop through current
|
||||
let currentLevel = 0;
|
||||
|
||||
doc.descendants((node, pos) => {
|
||||
if (node.isText) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const isCurrent = anchor >= pos && anchor <= pos + node.nodeSize - 1;
|
||||
|
||||
if (!isCurrent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
currentLevel += 1;
|
||||
|
||||
const outOfScope =
|
||||
(this.options.mode === 'deepest' && maxLevels - currentLevel > 0) ||
|
||||
(this.options.mode === 'shallowest' && currentLevel > 1);
|
||||
|
||||
if (outOfScope) {
|
||||
return this.options.mode === 'deepest';
|
||||
}
|
||||
|
||||
decorations.push(
|
||||
Decoration.node(pos, pos + node.nodeSize, {
|
||||
class: this.options.className,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
return DecorationSet.create(doc, decorations);
|
||||
},
|
||||
},
|
||||
}),
|
||||
];
|
||||
},
|
||||
});
|
|
@ -12,7 +12,6 @@ declare module '@tiptap/core' {
|
|||
|
||||
export const Status = Node.create({
|
||||
name: 'status',
|
||||
content: 'text*',
|
||||
group: 'inline',
|
||||
inline: true,
|
||||
atom: true,
|
||||
|
|
|
@ -38,24 +38,20 @@
|
|||
outline: none;
|
||||
}
|
||||
|
||||
.is-empty::before {
|
||||
.is-empty {
|
||||
&.has-focus {
|
||||
&::before {
|
||||
content: attr(data-placeholder);
|
||||
float: left;
|
||||
color: #aaa;
|
||||
pointer-events: none;
|
||||
height: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.is-empty.node-codeBlock::before {
|
||||
&.node-codeBlock::before {
|
||||
transform: translate(10px, 10px);
|
||||
}
|
||||
|
||||
.placeholder::before {
|
||||
content: attr(data-placeholder);
|
||||
float: left;
|
||||
color: #aaa;
|
||||
pointer-events: none;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.hr-line {
|
||||
|
@ -108,6 +104,14 @@
|
|||
color: var(--semi-color-text-0);
|
||||
margin: 10px 0 22px;
|
||||
border-bottom: 1px solid var(--semi-color-border);
|
||||
|
||||
&.is-empty::before {
|
||||
content: attr(data-placeholder);
|
||||
float: left;
|
||||
color: #aaa;
|
||||
pointer-events: none;
|
||||
height: 0;
|
||||
}
|
||||
}
|
||||
|
||||
h1 {
|
||||
|
|
Loading…
Reference in New Issue