feat: improve tiptap

This commit is contained in:
fantasticit 2022-03-22 12:43:03 +08:00
parent e211f07794
commit 0e54e4af65
6 changed files with 119 additions and 27 deletions

View File

@ -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,

View File

@ -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>
);
};

View File

@ -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': ` 继续输入进行过滤`,
})
);

View File

@ -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);
},
},
}),
];
},
});

View File

@ -12,7 +12,6 @@ declare module '@tiptap/core' {
export const Status = Node.create({
name: 'status',
content: 'text*',
group: 'inline',
inline: true,
atom: true,

View File

@ -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 {