@fishawack/lab-velocity 1.6.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/_basic.scss +1 -1
- package/components/_wysiwyg2.scss +19 -0
- package/form/Wysiwyg/CustomTableView.ts +124 -0
- package/form/Wysiwyg/Table.js +30 -0
- package/form/Wysiwyg2.vue +16 -6
- package/package.json +1 -1
package/components/_basic.scss
CHANGED
|
@@ -115,3 +115,22 @@
|
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
.lab-table, .lab-table-cell, .lab-table-header {
|
|
121
|
+
border: solid .5px $color1;
|
|
122
|
+
}
|
|
123
|
+
.lab-table-header {
|
|
124
|
+
background-color: $color5;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.lab-table {
|
|
128
|
+
a {
|
|
129
|
+
text-decoration: underline;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
.lab-table-cell {
|
|
133
|
+
&:active, &:focus-within, &.selectedCell {
|
|
134
|
+
background-color: transparentize($color: $color5, $amount: .8);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { Node as ProseMirrorNode } from '@tiptap/pm/model'
|
|
2
|
+
import { NodeView, ViewMutationRecord } from '@tiptap/pm/view'
|
|
3
|
+
|
|
4
|
+
export function getColStyleDeclaration(minWidth: number, width: number | undefined): [string, string] {
|
|
5
|
+
if (width) {
|
|
6
|
+
// apply the stored width unless it is below the configured minimum cell width
|
|
7
|
+
return ['width', `${Math.max(width, minWidth)}px`]
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// set the minimum with on the column if it has no stored width
|
|
11
|
+
return ['min-width', `${minWidth}px`]
|
|
12
|
+
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function updateColumns(
|
|
16
|
+
node: ProseMirrorNode,
|
|
17
|
+
colgroup: HTMLTableColElement, // <colgroup> has the same prototype as <col>
|
|
18
|
+
table: HTMLTableElement,
|
|
19
|
+
cellMinWidth: number,
|
|
20
|
+
overrideCol?: number,
|
|
21
|
+
overrideValue?: number,
|
|
22
|
+
) {
|
|
23
|
+
let totalWidth = 0
|
|
24
|
+
let fixedWidth = false
|
|
25
|
+
let nextDOM = colgroup.firstChild
|
|
26
|
+
const row = node.firstChild
|
|
27
|
+
|
|
28
|
+
if (row !== null) {
|
|
29
|
+
for (let i = 0, col = 0; i < row.childCount; i += 1) {
|
|
30
|
+
const { colspan, colwidth } = row.child(i).attrs
|
|
31
|
+
|
|
32
|
+
for (let j = 0; j < colspan; j += 1, col += 1) {
|
|
33
|
+
const hasWidth = overrideCol === col ? overrideValue : (colwidth && colwidth[j]) as number | undefined
|
|
34
|
+
const cssWidth = hasWidth ? `${hasWidth}px` : ''
|
|
35
|
+
|
|
36
|
+
totalWidth += hasWidth || cellMinWidth
|
|
37
|
+
|
|
38
|
+
if (!hasWidth) {
|
|
39
|
+
fixedWidth = false
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (!nextDOM) {
|
|
43
|
+
const colElement = document.createElement('col')
|
|
44
|
+
|
|
45
|
+
const [propertyKey, propertyValue] = getColStyleDeclaration(cellMinWidth, hasWidth)
|
|
46
|
+
|
|
47
|
+
colElement.style.setProperty(propertyKey, propertyValue)
|
|
48
|
+
|
|
49
|
+
colgroup.appendChild(colElement)
|
|
50
|
+
} else {
|
|
51
|
+
if ((nextDOM as HTMLTableColElement).style.width !== cssWidth) {
|
|
52
|
+
const [propertyKey, propertyValue] = getColStyleDeclaration(cellMinWidth, hasWidth);
|
|
53
|
+
|
|
54
|
+
(nextDOM as HTMLTableColElement).style.setProperty(propertyKey, propertyValue)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
nextDOM = nextDOM.nextSibling
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
while (nextDOM) {
|
|
64
|
+
const after = nextDOM.nextSibling
|
|
65
|
+
|
|
66
|
+
nextDOM.parentNode?.removeChild(nextDOM)
|
|
67
|
+
nextDOM = after
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (fixedWidth) {
|
|
71
|
+
table.style.width = `${totalWidth}px`
|
|
72
|
+
table.style.minWidth = ''
|
|
73
|
+
} else {
|
|
74
|
+
table.style.width = ''
|
|
75
|
+
table.style.minWidth = `${totalWidth}px`
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export class CustomTableView implements NodeView {
|
|
80
|
+
node: ProseMirrorNode
|
|
81
|
+
|
|
82
|
+
cellMinWidth: number
|
|
83
|
+
|
|
84
|
+
dom: HTMLDivElement
|
|
85
|
+
|
|
86
|
+
table: HTMLTableElement
|
|
87
|
+
|
|
88
|
+
colgroup: HTMLTableColElement
|
|
89
|
+
|
|
90
|
+
contentDOM: HTMLTableSectionElement
|
|
91
|
+
|
|
92
|
+
constructor(node: ProseMirrorNode, cellMinWidth: number) {
|
|
93
|
+
this.node = node
|
|
94
|
+
this.cellMinWidth = cellMinWidth
|
|
95
|
+
this.dom = document.createElement('div')
|
|
96
|
+
this.dom.className = 'tableWrapper'
|
|
97
|
+
this.table = this.dom.appendChild(document.createElement('table'))
|
|
98
|
+
this.colgroup = this.table.appendChild(document.createElement('colgroup'))
|
|
99
|
+
updateColumns(node, this.colgroup, this.table, cellMinWidth)
|
|
100
|
+
this.contentDOM = this.table.appendChild(document.createElement('tbody'))
|
|
101
|
+
|
|
102
|
+
if (node.attrs.class) {
|
|
103
|
+
this.table.className = node.attrs.class
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
update(node: ProseMirrorNode) {
|
|
108
|
+
if (node.type !== this.node.type) {
|
|
109
|
+
return false
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
this.node = node
|
|
113
|
+
updateColumns(node, this.colgroup, this.table, this.cellMinWidth)
|
|
114
|
+
|
|
115
|
+
return true
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
ignoreMutation(mutation: ViewMutationRecord) {
|
|
119
|
+
return (
|
|
120
|
+
mutation.type === 'attributes'
|
|
121
|
+
&& (mutation.target === this.table || this.colgroup.contains(mutation.target))
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import Table from '@tiptap/extension-table'
|
|
2
|
+
import {CustomTableView} from './CustomTableView.ts'
|
|
3
|
+
|
|
4
|
+
export default Table.extend({
|
|
5
|
+
|
|
6
|
+
// @ts-ignore
|
|
7
|
+
addOptions() {
|
|
8
|
+
return {
|
|
9
|
+
HTMLAttributes: {},
|
|
10
|
+
resizable: true,
|
|
11
|
+
handleWidth: 5,
|
|
12
|
+
cellMinWidth: 25,
|
|
13
|
+
// TODO: fix
|
|
14
|
+
View: CustomTableView, /* REPLACED BY CUSTOM_TABLE_VIEW */
|
|
15
|
+
lastColumnResizable: true,
|
|
16
|
+
allowTableNodeSelection: false,
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
addAttributes() {
|
|
21
|
+
return {
|
|
22
|
+
...this.parent?.(),
|
|
23
|
+
class: {
|
|
24
|
+
default: 'lab-table',
|
|
25
|
+
parseHTML: element => element.getAttribute('class'),
|
|
26
|
+
renderHTML: attributes => attributes.class ? {class: attributes.class} : {},
|
|
27
|
+
},
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
})
|
package/form/Wysiwyg2.vue
CHANGED
|
@@ -150,7 +150,7 @@ import { ElDropdown, ElDropdownItem, ElDropdownMenu, ElDialog, ElButton, ElInput
|
|
|
150
150
|
import { Editor, EditorContent } from '@tiptap/vue-3'
|
|
151
151
|
import StarterKit from '@tiptap/starter-kit';
|
|
152
152
|
import Underline from '@tiptap/extension-underline'
|
|
153
|
-
import Table from
|
|
153
|
+
import Table from "./Wysiwyg/Table.js"
|
|
154
154
|
import TableCell from '@tiptap/extension-table-cell'
|
|
155
155
|
import TableHeader from '@tiptap/extension-table-header'
|
|
156
156
|
import TableRow from '@tiptap/extension-table-row'
|
|
@@ -253,12 +253,22 @@ export default {
|
|
|
253
253
|
];
|
|
254
254
|
if(this.$props.table) {
|
|
255
255
|
extensions.push(
|
|
256
|
-
Table
|
|
257
|
-
|
|
256
|
+
Table,
|
|
257
|
+
TableRow.configure({
|
|
258
|
+
HTMLAttributes: {
|
|
259
|
+
class: 'lab-table-row'
|
|
260
|
+
}
|
|
261
|
+
}),
|
|
262
|
+
TableHeader.configure({
|
|
263
|
+
HTMLAttributes: {
|
|
264
|
+
class: 'lab-table-header'
|
|
265
|
+
}
|
|
258
266
|
}),
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
267
|
+
TableCell.configure({
|
|
268
|
+
HTMLAttributes: {
|
|
269
|
+
class: 'lab-table-cell'
|
|
270
|
+
}
|
|
271
|
+
}));
|
|
262
272
|
}
|
|
263
273
|
|
|
264
274
|
this.editor = new Editor({
|