tiptap: fix menu

This commit is contained in:
fantasticit 2022-05-09 16:04:55 +08:00
parent 7e0d145ce9
commit d5b3ea24de
7 changed files with 70 additions and 13 deletions

View File

@ -28,10 +28,16 @@ export const TableCell = BuiltInTableCell.extend({
}, },
addProseMirrorPlugins() { addProseMirrorPlugins() {
const { isEditable } = this.editor;
return [ return [
new Plugin({ new Plugin({
props: { props: {
decorations: (state) => { decorations: (state) => {
if (!isEditable) {
return DecorationSet.empty;
}
const { doc, selection } = state; const { doc, selection } = state;
const decorations: Decoration[] = []; const decorations: Decoration[] = [];
const cells = getCellsInColumn(0)(selection); const cells = getCellsInColumn(0)(selection);

View File

@ -28,10 +28,16 @@ export const TableHeader = BuiltInTableHeader.extend({
}, },
addProseMirrorPlugins() { addProseMirrorPlugins() {
const { isEditable } = this.editor;
return [ return [
new Plugin({ new Plugin({
props: { props: {
decorations: (state) => { decorations: (state) => {
if (!isEditable) {
return DecorationSet.empty;
}
const { doc, selection } = state; const { doc, selection } = state;
const decorations: Decoration[] = []; const decorations: Decoration[] = [];
const cells = getCellsInRow(0)(selection); const cells = getCellsInRow(0)(selection);

View File

@ -7,12 +7,14 @@ export const Table = BuiltInTable.extend({
renderHTML() { renderHTML() {
return [ return [
'div', 'div',
{ class: 'scrollable-wrapper' }, { class: 'node-table' },
['div', { class: 'scrollable' }, ['table', { class: 'rme-table' }, ['tbody', 0]]], ['div', { class: `scrollable` }, ['table', { class: `think-table render-wrapper` }, ['tbody', 0]]],
]; ];
}, },
addProseMirrorPlugins() { addProseMirrorPlugins() {
const { isEditable } = this.editor;
return [ return [
tableEditing(), tableEditing(),
new Plugin({ new Plugin({
@ -25,10 +27,15 @@ export const Table = BuiltInTable.extend({
doc.descendants((node, pos) => { doc.descendants((node, pos) => {
if (node.type.name !== this.name) return; if (node.type.name !== this.name) return;
const elements = document.getElementsByClassName('rme-table'); const elements = document.getElementsByClassName('think-table');
const table = elements[index]; const table = elements[index];
if (!table) return; if (!table) return;
if (!isEditable) {
table.classList.add('is-readonly');
}
const element = table.parentElement; const element = table.parentElement;
const shadowRight = !!(element && element.scrollWidth > element.clientWidth); const shadowRight = !!(element && element.scrollWidth > element.clientWidth);
@ -36,7 +43,7 @@ export const Table = BuiltInTable.extend({
decorations.push( decorations.push(
Decoration.widget(pos + 1, () => { Decoration.widget(pos + 1, () => {
const shadow = document.createElement('div'); const shadow = document.createElement('div');
shadow.className = 'scrollable-shadow right'; shadow.className = `scrollable-shadow right ${isEditable ? 'is-editable' : ''}`;
return shadow; return shadow;
}) })
); );

View File

@ -80,4 +80,27 @@
} }
} }
} }
.node-table {
&.selected-node {
&:not(.has-focus) {
::selection {
background-color: transparent;
}
}
.render-wrapper {
position: relative;
&::after {
position: absolute;
pointer-events: none;
border: 1px solid var(--node-selected-border-color) !important;
background-color: rgb(179 212 255 / 30%);
content: '';
inset: 0;
}
}
}
}
} }

View File

@ -1,7 +1,7 @@
.ProseMirror { .ProseMirror {
.scrollable-wrapper { .node-table {
position: relative; position: relative;
margin: 0.5em 0; margin-top: 0.75em;
scrollbar-width: thin; scrollbar-width: thin;
scrollbar-color: transparent transparent; scrollbar-color: transparent transparent;
} }
@ -30,13 +30,24 @@
&.left { &.left {
box-shadow: 16px 0 16px -16px inset rgb(0 0 0 / 25%); box-shadow: 16px 0 16px -16px inset rgb(0 0 0 / 25%);
border-left: 1em solid red;
} }
&.right { &.right {
right: 0; right: 0;
left: auto; left: auto;
box-shadow: rgb(0 0 0 / 25%) -16px 0 16px -16px inset; box-shadow: rgb(0 0 0 / 25%) -16px 0 16px -16px inset;
&.is-editable {
&::after {
position: absolute;
top: 0;
right: 0;
width: 1em;
height: 1em;
background-color: var(--semi-color-nav-bg);
content: '';
}
}
} }
} }
@ -48,6 +59,10 @@
box-sizing: border-box; box-sizing: border-box;
border-color: var(--semi-color-fill-2); border-color: var(--semi-color-fill-2);
&.is-readonly {
margin-top: 0;
}
td, td,
th { th {
position: relative; position: relative;

View File

@ -3,7 +3,7 @@ import { Space, Button } from '@douyinfe/semi-ui';
import { IconAddColumnBefore, IconAddColumnAfter, IconDeleteColumn } from 'components/icons'; import { IconAddColumnBefore, IconAddColumnAfter, IconDeleteColumn } from 'components/icons';
import { Tooltip } from 'components/tooltip'; import { Tooltip } from 'components/tooltip';
import { BubbleMenu } from 'tiptap/editor/views/bubble-menu'; import { BubbleMenu } from 'tiptap/editor/views/bubble-menu';
import { TableRow } from 'tiptap/core/extensions/table-row'; import { Table } from 'tiptap/core/extensions/table';
import { isTableSelected } from 'tiptap/prose-utils'; import { isTableSelected } from 'tiptap/prose-utils';
export const TableColBubbleMenu = ({ editor }) => { export const TableColBubbleMenu = ({ editor }) => {
@ -20,9 +20,9 @@ export const TableColBubbleMenu = ({ editor }) => {
offset: [0, 20], offset: [0, 20],
}} }}
shouldShow={({ node, state }) => { shouldShow={({ node, state }) => {
if (!node || isTableSelected(state.selection)) return false; if (!editor.isActive(Table.name) || !node || isTableSelected(state.selection)) return false;
const gripColumn = node.querySelector('a.grip-column.selected'); const gripColumn = node.querySelector('a.grip-column.selected');
return editor.isActive(TableRow.name) && !!gripColumn; return !!gripColumn;
}} }}
getRenderContainer={(node) => { getRenderContainer={(node) => {
return node; return node;

View File

@ -3,7 +3,7 @@ import { Space, Button } from '@douyinfe/semi-ui';
import { IconAddRowBefore, IconAddRowAfter, IconDeleteRow } from 'components/icons'; import { IconAddRowBefore, IconAddRowAfter, IconDeleteRow } from 'components/icons';
import { Tooltip } from 'components/tooltip'; import { Tooltip } from 'components/tooltip';
import { BubbleMenu } from 'tiptap/editor/views/bubble-menu'; import { BubbleMenu } from 'tiptap/editor/views/bubble-menu';
import { TableRow } from 'tiptap/core/extensions/table-row'; import { Table } from 'tiptap/core/extensions/table';
import { isTableSelected } from 'tiptap/prose-utils'; import { isTableSelected } from 'tiptap/prose-utils';
export const TableRowBubbleMenu = ({ editor }) => { export const TableRowBubbleMenu = ({ editor }) => {
@ -21,9 +21,9 @@ export const TableRowBubbleMenu = ({ editor }) => {
offset: [0, 20], offset: [0, 20],
}} }}
shouldShow={({ node, state }) => { shouldShow={({ node, state }) => {
if (!node || isTableSelected(state.selection)) return false; if (!editor.isActive(Table.name) || !node || isTableSelected(state.selection)) return false;
const gripRow = node.querySelector('a.grip-row.selected'); const gripRow = node.querySelector('a.grip-row.selected');
return editor.isActive(TableRow.name) && !!gripRow; return !!gripRow;
}} }}
getRenderContainer={(node) => { getRenderContainer={(node) => {
return node; return node;