diff --git a/packages/client/src/tiptap/core/extensions/table-cell.tsx b/packages/client/src/tiptap/core/extensions/table-cell.tsx index 51966045..beb4d1b7 100644 --- a/packages/client/src/tiptap/core/extensions/table-cell.tsx +++ b/packages/client/src/tiptap/core/extensions/table-cell.tsx @@ -28,10 +28,16 @@ export const TableCell = BuiltInTableCell.extend({ }, addProseMirrorPlugins() { + const { isEditable } = this.editor; + return [ new Plugin({ props: { decorations: (state) => { + if (!isEditable) { + return DecorationSet.empty; + } + const { doc, selection } = state; const decorations: Decoration[] = []; const cells = getCellsInColumn(0)(selection); diff --git a/packages/client/src/tiptap/core/extensions/table-header.tsx b/packages/client/src/tiptap/core/extensions/table-header.tsx index 4d6f52a5..02e9cf99 100644 --- a/packages/client/src/tiptap/core/extensions/table-header.tsx +++ b/packages/client/src/tiptap/core/extensions/table-header.tsx @@ -28,10 +28,16 @@ export const TableHeader = BuiltInTableHeader.extend({ }, addProseMirrorPlugins() { + const { isEditable } = this.editor; + return [ new Plugin({ props: { decorations: (state) => { + if (!isEditable) { + return DecorationSet.empty; + } + const { doc, selection } = state; const decorations: Decoration[] = []; const cells = getCellsInRow(0)(selection); diff --git a/packages/client/src/tiptap/core/extensions/table.ts b/packages/client/src/tiptap/core/extensions/table.ts index 2952326d..5fef9ccb 100644 --- a/packages/client/src/tiptap/core/extensions/table.ts +++ b/packages/client/src/tiptap/core/extensions/table.ts @@ -7,12 +7,14 @@ export const Table = BuiltInTable.extend({ renderHTML() { return [ 'div', - { class: 'scrollable-wrapper' }, - ['div', { class: 'scrollable' }, ['table', { class: 'rme-table' }, ['tbody', 0]]], + { class: 'node-table' }, + ['div', { class: `scrollable` }, ['table', { class: `think-table render-wrapper` }, ['tbody', 0]]], ]; }, addProseMirrorPlugins() { + const { isEditable } = this.editor; + return [ tableEditing(), new Plugin({ @@ -25,10 +27,15 @@ export const Table = BuiltInTable.extend({ doc.descendants((node, pos) => { if (node.type.name !== this.name) return; - const elements = document.getElementsByClassName('rme-table'); + const elements = document.getElementsByClassName('think-table'); const table = elements[index]; + if (!table) return; + if (!isEditable) { + table.classList.add('is-readonly'); + } + const element = table.parentElement; const shadowRight = !!(element && element.scrollWidth > element.clientWidth); @@ -36,7 +43,7 @@ export const Table = BuiltInTable.extend({ decorations.push( Decoration.widget(pos + 1, () => { const shadow = document.createElement('div'); - shadow.className = 'scrollable-shadow right'; + shadow.className = `scrollable-shadow right ${isEditable ? 'is-editable' : ''}`; return shadow; }) ); diff --git a/packages/client/src/tiptap/core/styles/selection.scss b/packages/client/src/tiptap/core/styles/selection.scss index fae93afa..277a578c 100644 --- a/packages/client/src/tiptap/core/styles/selection.scss +++ b/packages/client/src/tiptap/core/styles/selection.scss @@ -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; + } + } + } + } } diff --git a/packages/client/src/tiptap/core/styles/table.scss b/packages/client/src/tiptap/core/styles/table.scss index ccaa5d8a..65cf255d 100644 --- a/packages/client/src/tiptap/core/styles/table.scss +++ b/packages/client/src/tiptap/core/styles/table.scss @@ -1,7 +1,7 @@ .ProseMirror { - .scrollable-wrapper { + .node-table { position: relative; - margin: 0.5em 0; + margin-top: 0.75em; scrollbar-width: thin; scrollbar-color: transparent transparent; } @@ -30,13 +30,24 @@ &.left { box-shadow: 16px 0 16px -16px inset rgb(0 0 0 / 25%); - border-left: 1em solid red; } &.right { right: 0; left: auto; 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; border-color: var(--semi-color-fill-2); + &.is-readonly { + margin-top: 0; + } + td, th { position: relative; diff --git a/packages/client/src/tiptap/editor/menus/table/col-bubble.tsx b/packages/client/src/tiptap/editor/menus/table/col-bubble.tsx index c11fbe9d..908b474c 100644 --- a/packages/client/src/tiptap/editor/menus/table/col-bubble.tsx +++ b/packages/client/src/tiptap/editor/menus/table/col-bubble.tsx @@ -3,7 +3,7 @@ import { Space, Button } from '@douyinfe/semi-ui'; import { IconAddColumnBefore, IconAddColumnAfter, IconDeleteColumn } from 'components/icons'; import { Tooltip } from 'components/tooltip'; 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'; export const TableColBubbleMenu = ({ editor }) => { @@ -20,9 +20,9 @@ export const TableColBubbleMenu = ({ editor }) => { offset: [0, 20], }} 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'); - return editor.isActive(TableRow.name) && !!gripColumn; + return !!gripColumn; }} getRenderContainer={(node) => { return node; diff --git a/packages/client/src/tiptap/editor/menus/table/row-bubble.tsx b/packages/client/src/tiptap/editor/menus/table/row-bubble.tsx index 6a310014..d221c0d4 100644 --- a/packages/client/src/tiptap/editor/menus/table/row-bubble.tsx +++ b/packages/client/src/tiptap/editor/menus/table/row-bubble.tsx @@ -3,7 +3,7 @@ import { Space, Button } from '@douyinfe/semi-ui'; import { IconAddRowBefore, IconAddRowAfter, IconDeleteRow } from 'components/icons'; import { Tooltip } from 'components/tooltip'; 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'; export const TableRowBubbleMenu = ({ editor }) => { @@ -21,9 +21,9 @@ export const TableRowBubbleMenu = ({ editor }) => { offset: [0, 20], }} 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'); - return editor.isActive(TableRow.name) && !!gripRow; + return !!gripRow; }} getRenderContainer={(node) => { return node;