mirror of https://github.com/fantasticit/think.git
close #211
parent
ab6affa3cc
commit
8c58090a41
|
@ -46,7 +46,7 @@ export const TableCell = Node.create<TableCellOptions>({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
colwidth: {
|
colwidth: {
|
||||||
default: null,
|
default: [150],
|
||||||
parseHTML: (element) => {
|
parseHTML: (element) => {
|
||||||
const colwidth = element.getAttribute('colwidth');
|
const colwidth = element.getAttribute('colwidth');
|
||||||
const value = colwidth ? [parseInt(colwidth, 10)] : null;
|
const value = colwidth ? [parseInt(colwidth, 10)] : null;
|
||||||
|
|
|
@ -13,7 +13,7 @@ export const TableHeader = BuiltInTableHeader.extend({
|
||||||
default: 1,
|
default: 1,
|
||||||
},
|
},
|
||||||
colwidth: {
|
colwidth: {
|
||||||
default: null,
|
default: [150],
|
||||||
parseHTML: (element) => {
|
parseHTML: (element) => {
|
||||||
const colwidth = element.getAttribute('colwidth');
|
const colwidth = element.getAttribute('colwidth');
|
||||||
const value = colwidth ? colwidth.split(',').map((item) => parseInt(item, 10)) : null;
|
const value = colwidth ? colwidth.split(',').map((item) => parseInt(item, 10)) : null;
|
||||||
|
|
|
@ -1,60 +1,121 @@
|
||||||
import BuiltInTable from '@tiptap/extension-table';
|
import BuiltInTable from '@tiptap/extension-table';
|
||||||
import { Plugin } from 'prosemirror-state';
|
import { Node as ProseMirrorNode } from 'prosemirror-model';
|
||||||
import { tableEditing } from 'prosemirror-tables';
|
import { NodeView } from 'prosemirror-view';
|
||||||
import { Decoration, DecorationSet } from 'prosemirror-view';
|
|
||||||
|
|
||||||
export const Table = BuiltInTable.extend({
|
function updateColumns(
|
||||||
renderHTML() {
|
node: ProseMirrorNode,
|
||||||
return [
|
colgroup: Element,
|
||||||
'div',
|
table: HTMLElement,
|
||||||
{ class: 'node-table' },
|
cellMinWidth: number,
|
||||||
['div', { class: `scrollable` }, ['table', { class: `think-table render-wrapper` }, ['tbody', 0]]],
|
overrideCol?: number,
|
||||||
];
|
overrideValue?: any
|
||||||
},
|
) {
|
||||||
|
let totalWidth = 0;
|
||||||
|
let fixedWidth = true;
|
||||||
|
let nextDOM = colgroup.firstChild as HTMLElement;
|
||||||
|
const row = node.firstChild;
|
||||||
|
|
||||||
addProseMirrorPlugins() {
|
for (let i = 0, col = 0; i < row.childCount; i += 1) {
|
||||||
const { isEditable } = this.editor;
|
const { colspan, colwidth } = row.child(i).attrs;
|
||||||
|
|
||||||
return [
|
for (let j = 0; j < colspan; j += 1, col += 1) {
|
||||||
tableEditing(),
|
const hasWidth = overrideCol === col ? overrideValue : colwidth && colwidth[j];
|
||||||
new Plugin({
|
const cssWidth = hasWidth ? `${hasWidth}px` : '';
|
||||||
props: {
|
|
||||||
decorations: (state) => {
|
|
||||||
const { doc } = state;
|
|
||||||
const decorations: Decoration[] = [];
|
|
||||||
let index = 0;
|
|
||||||
|
|
||||||
doc.descendants((node, pos) => {
|
totalWidth += hasWidth || cellMinWidth;
|
||||||
if (node.type.name !== this.name) return;
|
|
||||||
|
|
||||||
const elements = document.getElementsByClassName('think-table');
|
if (!hasWidth) {
|
||||||
const table = elements[index];
|
fixedWidth = false;
|
||||||
|
|
||||||
if (!table) return;
|
|
||||||
|
|
||||||
if (!isEditable) {
|
|
||||||
table.classList.add('is-readonly');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const element = table.parentElement;
|
if (!nextDOM) {
|
||||||
const shadowRight = !!(element && element.scrollWidth > element.clientWidth);
|
colgroup.appendChild(document.createElement('col')).style.width = cssWidth;
|
||||||
|
} else {
|
||||||
|
if (nextDOM.style.width !== cssWidth) {
|
||||||
|
nextDOM.style.width = cssWidth;
|
||||||
|
}
|
||||||
|
|
||||||
if (shadowRight) {
|
nextDOM = nextDOM.nextSibling as HTMLElement;
|
||||||
decorations.push(
|
}
|
||||||
Decoration.widget(pos + 1, () => {
|
}
|
||||||
const shadow = document.createElement('div');
|
}
|
||||||
shadow.className = `scrollable-shadow right ${isEditable ? 'is-editable' : ''}`;
|
|
||||||
return shadow;
|
while (nextDOM) {
|
||||||
})
|
const after = nextDOM.nextSibling as HTMLElement;
|
||||||
|
|
||||||
|
nextDOM.parentNode.removeChild(nextDOM);
|
||||||
|
nextDOM = after;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fixedWidth) {
|
||||||
|
table.style.width = `${totalWidth}px`;
|
||||||
|
table.style.minWidth = '';
|
||||||
|
} else {
|
||||||
|
table.style.width = '';
|
||||||
|
table.style.minWidth = `${totalWidth}px`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TableView implements NodeView {
|
||||||
|
node: ProseMirrorNode;
|
||||||
|
|
||||||
|
cellMinWidth: number;
|
||||||
|
|
||||||
|
dom: HTMLElement;
|
||||||
|
|
||||||
|
scrollDom: HTMLElement;
|
||||||
|
|
||||||
|
table: HTMLElement;
|
||||||
|
|
||||||
|
colgroup: HTMLElement;
|
||||||
|
|
||||||
|
contentDOM: HTMLElement;
|
||||||
|
|
||||||
|
constructor(node: ProseMirrorNode, cellMinWidth: number) {
|
||||||
|
this.node = node;
|
||||||
|
this.cellMinWidth = cellMinWidth;
|
||||||
|
this.dom = document.createElement('div');
|
||||||
|
this.dom.className = 'tableWrapper';
|
||||||
|
|
||||||
|
this.scrollDom = document.createElement('div');
|
||||||
|
this.scrollDom.className = 'scrollWrapper';
|
||||||
|
this.dom.appendChild(this.scrollDom);
|
||||||
|
|
||||||
|
this.table = this.scrollDom.appendChild(document.createElement('table'));
|
||||||
|
this.colgroup = this.table.appendChild(document.createElement('colgroup'));
|
||||||
|
updateColumns(node, this.colgroup, this.table, cellMinWidth);
|
||||||
|
this.contentDOM = this.table.appendChild(document.createElement('tbody'));
|
||||||
|
}
|
||||||
|
|
||||||
|
update(node: ProseMirrorNode) {
|
||||||
|
if (node.type !== this.node.type) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.node = node;
|
||||||
|
updateColumns(node, this.colgroup, this.table, this.cellMinWidth);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ignoreMutation(mutation: MutationRecord | { type: 'selection'; target: Element }) {
|
||||||
|
return (
|
||||||
|
mutation.type === 'attributes' && (mutation.target === this.table || this.colgroup.contains(mutation.target))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
index++;
|
}
|
||||||
});
|
|
||||||
|
|
||||||
return DecorationSet.create(doc, decorations);
|
export const Table = BuiltInTable.extend({
|
||||||
},
|
// @ts-ignore
|
||||||
},
|
addOptions() {
|
||||||
}),
|
return {
|
||||||
];
|
HTMLAttributes: {},
|
||||||
|
resizable: true,
|
||||||
|
handleWidth: 5,
|
||||||
|
cellMinWidth: 25,
|
||||||
|
View: TableView,
|
||||||
|
lastColumnResizable: true,
|
||||||
|
allowTableNodeSelection: false,
|
||||||
|
};
|
||||||
},
|
},
|
||||||
}).configure({ resizable: true });
|
}).configure({ resizable: true });
|
||||||
|
|
|
@ -34,7 +34,7 @@ export const TableBubbleMenu = ({ editor }) => {
|
||||||
while (container && container.tagName !== 'TABLE') {
|
while (container && container.tagName !== 'TABLE') {
|
||||||
container = container.parentElement;
|
container = container.parentElement;
|
||||||
}
|
}
|
||||||
return container.parentElement;
|
return container;
|
||||||
}, []);
|
}, []);
|
||||||
const copyMe = useCallback(() => copyNode(Table.name, editor), [editor]);
|
const copyMe = useCallback(() => copyNode(Table.name, editor), [editor]);
|
||||||
const deleteMe = useCallback(() => {
|
const deleteMe = useCallback(() => {
|
||||||
|
|
Loading…
Reference in New Issue