quill-table-up 2.4.2 → 3.0.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/README.md +96 -40
- package/dist/index.css +1 -1
- package/dist/index.d.ts +172 -110
- package/dist/index.js +29 -28
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +29 -28
- package/dist/index.umd.js.map +1 -1
- package/dist/table-creator.css +1 -1
- package/package.json +1 -1
- package/src/__tests__/e2e/table-align.test.ts +1 -2
- package/src/__tests__/e2e/table-blots.test.ts +45 -35
- package/src/__tests__/e2e/table-clipboard.test.ts +20 -0
- package/src/__tests__/e2e/table-hack.test.ts +5 -5
- package/src/__tests__/e2e/table-keyboard-handler.test.ts +6 -6
- package/src/__tests__/e2e/table-menu.test.ts +23 -0
- package/src/__tests__/e2e/table-selection.test.ts +3 -3
- package/src/__tests__/unit/table-blots.test.ts +26 -26
- package/src/__tests__/unit/table-caption.test.ts +33 -36
- package/src/__tests__/unit/table-cell-merge.test.ts +114 -114
- package/src/__tests__/unit/table-clipboard.test.ts +383 -19
- package/src/__tests__/unit/table-hack.test.ts +202 -144
- package/src/__tests__/unit/table-insert.test.ts +79 -79
- package/src/__tests__/unit/table-redo-undo.test.ts +495 -64
- package/src/__tests__/unit/table-remove.test.ts +8 -11
- package/src/__tests__/unit/utils.test.ts +4 -4
- package/src/__tests__/unit/utils.ts +4 -3
- package/src/formats/container-format.ts +25 -2
- package/src/formats/index.ts +54 -8
- package/src/formats/overrides/block.ts +35 -30
- package/src/formats/table-body-format.ts +18 -58
- package/src/formats/table-cell-format.ts +296 -286
- package/src/formats/table-cell-inner-format.ts +384 -358
- package/src/formats/table-foot-format.ts +7 -0
- package/src/formats/table-head-format.ts +7 -0
- package/src/formats/table-main-format.ts +84 -5
- package/src/formats/table-row-format.ts +44 -14
- package/src/modules/index.ts +1 -0
- package/src/modules/table-align.ts +59 -53
- package/src/modules/table-clipboard.ts +60 -39
- package/src/modules/table-dom-selector.ts +33 -0
- package/src/modules/table-menu/constants.ts +21 -31
- package/src/modules/table-menu/table-menu-common.ts +72 -51
- package/src/modules/table-menu/table-menu-contextmenu.ts +22 -6
- package/src/modules/table-menu/table-menu-select.ts +75 -12
- package/src/modules/table-resize/table-resize-box.ts +148 -128
- package/src/modules/table-resize/table-resize-common.ts +37 -32
- package/src/modules/table-resize/table-resize-line.ts +53 -36
- package/src/modules/table-resize/table-resize-scale.ts +32 -27
- package/src/modules/table-scrollbar.ts +58 -32
- package/src/modules/table-selection.ts +102 -79
- package/src/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
- package/src/style/index.less +0 -1
- package/src/style/select-box.less +1 -0
- package/src/style/table-menu.less +4 -4
- package/src/style/table-resize.less +1 -0
- package/src/style/table-scrollbar.less +2 -2
- package/src/table-up.ts +161 -194
- package/src/utils/components/table/creator.ts +4 -1
- package/src/utils/components/tooltip.ts +6 -1
- package/src/utils/constants.ts +8 -2
- package/src/utils/index.ts +2 -1
- package/src/utils/scroll.ts +47 -0
- package/src/utils/style-helper.ts +47 -0
- package/src/utils/transformer.ts +0 -25
- package/src/utils/types.ts +15 -15
- package/src/utils/scroll-event-helper.ts +0 -22
|
@@ -28,7 +28,7 @@ export const tableMenuTools: Record<string, Tool> = {
|
|
|
28
28
|
name: 'CopyCell',
|
|
29
29
|
tip: 'Copy cell',
|
|
30
30
|
icon: Copy,
|
|
31
|
-
handle
|
|
31
|
+
handle(tableModule, selectedTds) {
|
|
32
32
|
const text = tableModule.getTextByCell(selectedTds);
|
|
33
33
|
const html = tableModule.getHTMLByCell(selectedTds);
|
|
34
34
|
|
|
@@ -37,14 +37,13 @@ export const tableMenuTools: Record<string, Tool> = {
|
|
|
37
37
|
'text/html': new Blob([html], { type: 'text/html' }),
|
|
38
38
|
});
|
|
39
39
|
navigator.clipboard.write([clipboardItem]);
|
|
40
|
-
tableModule.hideTableTools();
|
|
41
40
|
},
|
|
42
41
|
},
|
|
43
42
|
CutCell: {
|
|
44
43
|
name: 'CutCell',
|
|
45
44
|
tip: 'Cut cell',
|
|
46
45
|
icon: Cut,
|
|
47
|
-
handle
|
|
46
|
+
handle(tableModule, selectedTds) {
|
|
48
47
|
const text = tableModule.getTextByCell(selectedTds);
|
|
49
48
|
const html = tableModule.getHTMLByCell(selectedTds, true);
|
|
50
49
|
|
|
@@ -53,86 +52,77 @@ export const tableMenuTools: Record<string, Tool> = {
|
|
|
53
52
|
'text/html': new Blob([html], { type: 'text/html' }),
|
|
54
53
|
});
|
|
55
54
|
navigator.clipboard.write([clipboardItem]);
|
|
56
|
-
tableModule.hideTableTools();
|
|
57
55
|
},
|
|
58
56
|
},
|
|
59
57
|
InsertTop: {
|
|
60
58
|
name: 'InsertTop',
|
|
61
59
|
icon: InsertTop,
|
|
62
60
|
tip: 'Insert row above',
|
|
63
|
-
handle
|
|
61
|
+
handle(tableModule, selectedTds) {
|
|
64
62
|
tableModule.appendRow(selectedTds, false);
|
|
65
|
-
tableModule.hideTableTools();
|
|
66
63
|
},
|
|
67
64
|
},
|
|
68
65
|
InsertRight: {
|
|
69
66
|
name: 'InsertRight',
|
|
70
67
|
icon: InsertRight,
|
|
71
68
|
tip: 'Insert column right',
|
|
72
|
-
handle
|
|
69
|
+
handle(tableModule, selectedTds) {
|
|
73
70
|
tableModule.appendCol(selectedTds, true);
|
|
74
|
-
tableModule.hideTableTools();
|
|
75
71
|
},
|
|
76
72
|
},
|
|
77
73
|
InsertBottom: {
|
|
78
74
|
name: 'InsertBottom',
|
|
79
75
|
icon: InsertBottom,
|
|
80
76
|
tip: 'Insert row below',
|
|
81
|
-
handle
|
|
77
|
+
handle(tableModule, selectedTds) {
|
|
82
78
|
tableModule.appendRow(selectedTds, true);
|
|
83
|
-
tableModule.hideTableTools();
|
|
84
79
|
},
|
|
85
80
|
},
|
|
86
81
|
InsertLeft: {
|
|
87
82
|
name: 'InsertLeft',
|
|
88
83
|
icon: InsertLeft,
|
|
89
84
|
tip: 'Insert column Left',
|
|
90
|
-
handle
|
|
85
|
+
handle(tableModule, selectedTds) {
|
|
91
86
|
tableModule.appendCol(selectedTds, false);
|
|
92
|
-
tableModule.hideTableTools();
|
|
93
87
|
},
|
|
94
88
|
},
|
|
95
89
|
MergeCell: {
|
|
96
90
|
name: 'MergeCell',
|
|
97
91
|
icon: MergeCell,
|
|
98
92
|
tip: 'Merge Cell',
|
|
99
|
-
handle
|
|
93
|
+
handle(tableModule, selectedTds) {
|
|
100
94
|
tableModule.mergeCells(selectedTds);
|
|
101
|
-
tableModule.hideTableTools();
|
|
102
95
|
},
|
|
103
96
|
},
|
|
104
97
|
SplitCell: {
|
|
105
98
|
name: 'SplitCell',
|
|
106
99
|
icon: SplitCell,
|
|
107
100
|
tip: 'Split Cell',
|
|
108
|
-
handle
|
|
101
|
+
handle(tableModule, selectedTds) {
|
|
109
102
|
tableModule.splitCell(selectedTds);
|
|
110
|
-
tableModule.hideTableTools();
|
|
111
103
|
},
|
|
112
104
|
},
|
|
113
105
|
DeleteRow: {
|
|
114
106
|
name: 'DeleteRow',
|
|
115
107
|
icon: RemoveRow,
|
|
116
108
|
tip: 'Delete Row',
|
|
117
|
-
handle
|
|
109
|
+
handle(tableModule, selectedTds) {
|
|
118
110
|
tableModule.removeRow(selectedTds);
|
|
119
|
-
tableModule.hideTableTools();
|
|
120
111
|
},
|
|
121
112
|
},
|
|
122
113
|
DeleteColumn: {
|
|
123
114
|
name: 'DeleteColumn',
|
|
124
115
|
icon: RemoveColumn,
|
|
125
116
|
tip: 'Delete Column',
|
|
126
|
-
handle
|
|
117
|
+
handle(tableModule, selectedTds) {
|
|
127
118
|
tableModule.removeCol(selectedTds);
|
|
128
|
-
tableModule.hideTableTools();
|
|
129
119
|
},
|
|
130
120
|
},
|
|
131
121
|
DeleteTable: {
|
|
132
122
|
name: 'DeleteTable',
|
|
133
123
|
icon: RemoveTable,
|
|
134
124
|
tip: 'Delete table',
|
|
135
|
-
handle
|
|
125
|
+
handle(tableModule, selectedTds) {
|
|
136
126
|
tableModule.deleteTable(selectedTds);
|
|
137
127
|
},
|
|
138
128
|
},
|
|
@@ -142,7 +132,7 @@ export const tableMenuTools: Record<string, Tool> = {
|
|
|
142
132
|
isColorChoose: true,
|
|
143
133
|
tip: 'Set background color',
|
|
144
134
|
key: 'background-color',
|
|
145
|
-
handle
|
|
135
|
+
handle(tableModule, selectedTds, color) {
|
|
146
136
|
tableModule.setCellAttrs(selectedTds, 'background-color', color, true);
|
|
147
137
|
},
|
|
148
138
|
},
|
|
@@ -152,7 +142,7 @@ export const tableMenuTools: Record<string, Tool> = {
|
|
|
152
142
|
isColorChoose: true,
|
|
153
143
|
tip: 'Set border color',
|
|
154
144
|
key: 'border-color',
|
|
155
|
-
handle
|
|
145
|
+
handle(tableModule, selectedTds, color) {
|
|
156
146
|
tableModule.setCellAttrs(selectedTds, 'border-color', color, true);
|
|
157
147
|
},
|
|
158
148
|
},
|
|
@@ -160,9 +150,9 @@ export const tableMenuTools: Record<string, Tool> = {
|
|
|
160
150
|
name: 'SwitchWidth',
|
|
161
151
|
icon: AutoFull,
|
|
162
152
|
tip: 'Switch table width',
|
|
163
|
-
handle
|
|
164
|
-
if (!
|
|
165
|
-
const tableMainBlot = Quill.find(
|
|
153
|
+
handle() {
|
|
154
|
+
if (!this.table) return;
|
|
155
|
+
const tableMainBlot = Quill.find(this.table) as TableMainFormat;
|
|
166
156
|
if (!tableMainBlot) return;
|
|
167
157
|
|
|
168
158
|
if (tableMainBlot.full) {
|
|
@@ -177,12 +167,12 @@ export const tableMenuTools: Record<string, Tool> = {
|
|
|
177
167
|
name: 'InsertCaption',
|
|
178
168
|
icon: TableHead,
|
|
179
169
|
tip: 'Insert table caption',
|
|
180
|
-
handle
|
|
181
|
-
if (!
|
|
182
|
-
const tableMainBlot = Quill.find(
|
|
170
|
+
handle() {
|
|
171
|
+
if (!this.table) return;
|
|
172
|
+
const tableMainBlot = Quill.find(this.table) as TableMainFormat;
|
|
183
173
|
if (!tableMainBlot) return;
|
|
184
174
|
|
|
185
|
-
const tableCaption =
|
|
175
|
+
const tableCaption = this.quill.scroll.create('text', 'Table Caption').wrap(blotName.tableCaption, {
|
|
186
176
|
tableId: tableMainBlot.tableId,
|
|
187
177
|
});
|
|
188
178
|
tableMainBlot.insertBefore(tableCaption, tableMainBlot.children.head);
|
|
@@ -192,7 +182,7 @@ export const tableMenuTools: Record<string, Tool> = {
|
|
|
192
182
|
name: 'ToggleTdBetweenTh',
|
|
193
183
|
icon: ConvertCell,
|
|
194
184
|
tip: 'Toggle td between th',
|
|
195
|
-
handle
|
|
185
|
+
handle(tableModule, selectedTds) {
|
|
196
186
|
for (const td of selectedTds) {
|
|
197
187
|
td.convertTableCell();
|
|
198
188
|
}
|
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
import type { TableUp } from '../../table-up';
|
|
2
2
|
import type { TableMenuOptions, ToolOption, TooltipInstance, ToolTipOptions } from '../../utils';
|
|
3
|
+
import type { TableSelection } from '../table-selection';
|
|
3
4
|
import Quill from 'quill';
|
|
4
|
-
import { createBEM, createColorPicker, createTooltip, debounce, defaultColorMap, isArray, isFunction, randomId } from '../../utils';
|
|
5
|
+
import { createBEM, createColorPicker, createTooltip, debounce, defaultColorMap, isArray, isFunction, randomId, tableUpEvent } from '../../utils';
|
|
6
|
+
import { TableDomSelector } from '../table-dom-selector';
|
|
5
7
|
import { colorClassName, maxSaveColorCount, menuColorSelectClassName, tableMenuTools } from './constants';
|
|
6
8
|
|
|
7
9
|
export type TableMenuOptionsInput = Partial<Omit<TableMenuOptions, 'texts'>>;
|
|
8
10
|
export interface MenuTooltipInstance extends TooltipInstance {
|
|
9
11
|
isColorPick?: boolean;
|
|
10
12
|
}
|
|
11
|
-
export class TableMenuCommon {
|
|
13
|
+
export class TableMenuCommon extends TableDomSelector {
|
|
14
|
+
static moduleName = 'table-menu';
|
|
15
|
+
|
|
12
16
|
usedColors = new Set<string>();
|
|
13
17
|
options: TableMenuOptions;
|
|
14
18
|
menu: HTMLElement | null = null;
|
|
15
19
|
isMenuDisplay: boolean = false;
|
|
16
20
|
isColorPicking: boolean = false;
|
|
17
|
-
updateUsedColor: (this: any, color?: string) => void;
|
|
18
21
|
tooltipItem: MenuTooltipInstance[] = [];
|
|
19
22
|
activeTooltip: MenuTooltipInstance | null = null;
|
|
20
23
|
bem = createBEM('menu');
|
|
@@ -24,8 +27,9 @@ export class TableMenuCommon {
|
|
|
24
27
|
};
|
|
25
28
|
|
|
26
29
|
constructor(public tableModule: TableUp, public quill: Quill, options: TableMenuOptionsInput) {
|
|
27
|
-
|
|
30
|
+
super(tableModule, quill);
|
|
28
31
|
|
|
32
|
+
this.options = this.resolveOptions(options);
|
|
29
33
|
try {
|
|
30
34
|
const storageValue = localStorage.getItem(this.options.localstorageKey) || '[]';
|
|
31
35
|
let colorValue = JSON.parse(storageValue);
|
|
@@ -36,38 +40,44 @@ export class TableMenuCommon {
|
|
|
36
40
|
}
|
|
37
41
|
catch {}
|
|
38
42
|
|
|
39
|
-
this.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (this.usedColors.size > maxSaveColorCount) {
|
|
43
|
-
const saveColors = Array.from(this.usedColors).slice(-1 * maxSaveColorCount);
|
|
44
|
-
this.usedColors.clear();
|
|
45
|
-
saveColors.map(v => this.usedColors.add(v));
|
|
46
|
-
}
|
|
43
|
+
this.quill.on(Quill.events.EDITOR_CHANGE, this.updateWhenTextChange);
|
|
44
|
+
this.quill.on(tableUpEvent.TABLE_SELECTION_DRAG_START, this.hideWhenSelectionDragStart);
|
|
45
|
+
}
|
|
47
46
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if (sameColorItem.length <= 0) {
|
|
57
|
-
usedColorWrapper.appendChild(newColorItem);
|
|
58
|
-
}
|
|
47
|
+
updateUsedColor = debounce((color?: string) => {
|
|
48
|
+
if (!color) return;
|
|
49
|
+
this.usedColors.add(color);
|
|
50
|
+
if (this.usedColors.size > maxSaveColorCount) {
|
|
51
|
+
const saveColors = Array.from(this.usedColors).slice(-1 * maxSaveColorCount);
|
|
52
|
+
this.usedColors.clear();
|
|
53
|
+
saveColors.map(v => this.usedColors.add(v));
|
|
54
|
+
}
|
|
59
55
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
56
|
+
localStorage.setItem(this.options.localstorageKey, JSON.stringify(Array.from(this.usedColors)));
|
|
57
|
+
const usedColorWrappers = Array.from(document.querySelectorAll(`.${this.colorItemClass}.${colorClassName.used}`));
|
|
58
|
+
for (const usedColorWrapper of usedColorWrappers) {
|
|
59
|
+
const newColorItem = document.createElement('div');
|
|
60
|
+
newColorItem.classList.add(colorClassName.item);
|
|
61
|
+
newColorItem.style.backgroundColor = String(color);
|
|
62
|
+
// if already have same color item. doesn't need insert
|
|
63
|
+
const sameColorItem = Array.from(usedColorWrapper.querySelectorAll(`.${colorClassName.item}[style*="background-color: ${newColorItem.style.backgroundColor}"]`));
|
|
64
|
+
if (sameColorItem.length <= 0) {
|
|
65
|
+
usedColorWrapper.appendChild(newColorItem);
|
|
64
66
|
}
|
|
65
|
-
}, 1000);
|
|
66
|
-
this.quill.on(Quill.events.TEXT_CHANGE, this.updateWhenTextChange);
|
|
67
|
-
}
|
|
68
67
|
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
const colorItem = Array.from(usedColorWrapper.querySelectorAll(`.${colorClassName.item}`)).slice(0, -1 * maxSaveColorCount);
|
|
69
|
+
for (const item of colorItem) {
|
|
70
|
+
item.remove();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}, 1000);
|
|
74
|
+
|
|
75
|
+
hideWhenSelectionDragStart = () => {
|
|
76
|
+
this.hide();
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
updateWhenTextChange = (eventName: string) => {
|
|
80
|
+
if (eventName === Quill.events.TEXT_CHANGE && this.isMenuDisplay) {
|
|
71
81
|
this.update();
|
|
72
82
|
}
|
|
73
83
|
};
|
|
@@ -128,7 +138,7 @@ export class TableMenuCommon {
|
|
|
128
138
|
else {
|
|
129
139
|
isFunction(handle) && item.addEventListener('click', (e) => {
|
|
130
140
|
this.quill.focus();
|
|
131
|
-
handle(this.tableModule, this.getSelectedTds(), e);
|
|
141
|
+
handle.call(this, this.tableModule, this.getSelectedTds(), e);
|
|
132
142
|
}, false);
|
|
133
143
|
}
|
|
134
144
|
|
|
@@ -173,20 +183,20 @@ export class TableMenuCommon {
|
|
|
173
183
|
transparentColor.classList.add(colorClassName.btn, 'transparent');
|
|
174
184
|
transparentColor.textContent = this.tableModule.options.texts.transparent;
|
|
175
185
|
transparentColor.addEventListener('click', () => {
|
|
176
|
-
handle(this.tableModule, this.getSelectedTds(), 'transparent');
|
|
186
|
+
handle.call(this, this.tableModule, this.getSelectedTds(), 'transparent');
|
|
177
187
|
});
|
|
178
188
|
const clearColor = document.createElement('div');
|
|
179
189
|
clearColor.classList.add(colorClassName.btn, 'clear');
|
|
180
190
|
clearColor.textContent = this.tableModule.options.texts.clear;
|
|
181
191
|
clearColor.addEventListener('click', () => {
|
|
182
|
-
handle(this.tableModule, this.getSelectedTds(), null);
|
|
192
|
+
handle.call(this, this.tableModule, this.getSelectedTds(), null);
|
|
183
193
|
});
|
|
184
194
|
const customColor = document.createElement('div');
|
|
185
195
|
customColor.classList.add(colorClassName.btn, 'custom');
|
|
186
196
|
customColor.textContent = this.tableModule.options.texts.custom;
|
|
187
197
|
const colorPicker = createColorPicker({
|
|
188
198
|
onChange: (color) => {
|
|
189
|
-
handle(this.tableModule, this.getSelectedTds(), color);
|
|
199
|
+
handle.call(this, this.tableModule, this.getSelectedTds(), color);
|
|
190
200
|
this.updateUsedColor(color);
|
|
191
201
|
},
|
|
192
202
|
});
|
|
@@ -230,16 +240,18 @@ export class TableMenuCommon {
|
|
|
230
240
|
type: 'click',
|
|
231
241
|
content: colorSelectWrapper,
|
|
232
242
|
onOpen: () => {
|
|
233
|
-
|
|
234
|
-
|
|
243
|
+
const tableSelection = this.tableModule.getModule<TableSelection>('table-selection');
|
|
244
|
+
if (this.isMenuDisplay && tableSelection) {
|
|
245
|
+
tableSelection.hideDisplay();
|
|
235
246
|
}
|
|
236
247
|
this.setActiveTooltip(tooltip);
|
|
237
248
|
return false;
|
|
238
249
|
},
|
|
239
250
|
onClose: () => {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
251
|
+
const tableSelection = this.tableModule.getModule<TableSelection>('table-selection');
|
|
252
|
+
if (this.isMenuDisplay && tableSelection) {
|
|
253
|
+
tableSelection.updateWithSelectedTds();
|
|
254
|
+
tableSelection.showDisplay();
|
|
243
255
|
}
|
|
244
256
|
const isChild = colorSelectWrapper.contains(colorPicker);
|
|
245
257
|
if (isChild) {
|
|
@@ -270,7 +282,8 @@ export class TableMenuCommon {
|
|
|
270
282
|
}
|
|
271
283
|
|
|
272
284
|
getSelectedTds() {
|
|
273
|
-
|
|
285
|
+
const tableSelection = this.tableModule.getModule<TableSelection>('table-selection');
|
|
286
|
+
return tableSelection?.selectedTds || [];
|
|
274
287
|
}
|
|
275
288
|
|
|
276
289
|
createTipText(item: HTMLElement, text: string) {
|
|
@@ -279,17 +292,24 @@ export class TableMenuCommon {
|
|
|
279
292
|
}
|
|
280
293
|
|
|
281
294
|
show() {
|
|
282
|
-
if (!this.
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
295
|
+
if (!this.table) return;
|
|
296
|
+
if (this.menu) {
|
|
297
|
+
this.hide();
|
|
298
|
+
}
|
|
299
|
+
this.menu = this.buildTools();
|
|
286
300
|
}
|
|
287
301
|
|
|
288
302
|
update() {
|
|
303
|
+
if (this.table && !this.quill.root.contains(this.table)) {
|
|
304
|
+
this.setSelectionTable(undefined);
|
|
305
|
+
}
|
|
289
306
|
}
|
|
290
307
|
|
|
291
308
|
hide() {
|
|
292
|
-
|
|
309
|
+
if (this.menu) {
|
|
310
|
+
this.menu.remove();
|
|
311
|
+
this.menu = null;
|
|
312
|
+
}
|
|
293
313
|
for (const tooltip of this.tooltipItem) {
|
|
294
314
|
tooltip.hide(true);
|
|
295
315
|
}
|
|
@@ -298,11 +318,12 @@ export class TableMenuCommon {
|
|
|
298
318
|
|
|
299
319
|
destroy() {
|
|
300
320
|
this.quill.off(Quill.events.TEXT_CHANGE, this.updateWhenTextChange);
|
|
321
|
+
this.quill.off(tableUpEvent.TABLE_SELECTION_DRAG_START, this.hideWhenSelectionDragStart);
|
|
301
322
|
this.activeTooltip = null;
|
|
302
|
-
for (const tooltip of this.tooltipItem)
|
|
303
|
-
|
|
323
|
+
for (const tooltip of this.tooltipItem) {
|
|
324
|
+
tooltip.destroy();
|
|
325
|
+
}
|
|
326
|
+
this.tooltipItem = [];
|
|
304
327
|
this.hide();
|
|
305
|
-
this.menu.remove();
|
|
306
|
-
this.menu = null;
|
|
307
328
|
}
|
|
308
329
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type Quill from 'quill';
|
|
2
2
|
import type { TableUp } from '../../table-up';
|
|
3
|
-
import type { TableMenuOptions, ToolTipOptions } from '../../utils';
|
|
4
|
-
import {
|
|
3
|
+
import type { InternalTableSelectionModule, TableMenuOptions, ToolTipOptions } from '../../utils';
|
|
4
|
+
import type { TableSelection } from '../table-selection';
|
|
5
|
+
import { limitDomInViewPort, tableUpEvent } from '../../utils';
|
|
5
6
|
import { menuColorSelectClassName } from './constants';
|
|
6
7
|
import { TableMenuCommon } from './table-menu-common';
|
|
7
8
|
|
|
@@ -15,8 +16,16 @@ export class TableMenuContextmenu extends TableMenuCommon {
|
|
|
15
16
|
super(tableModule, quill, options);
|
|
16
17
|
|
|
17
18
|
this.quill.root.addEventListener('contextmenu', this.listenContextmenu);
|
|
19
|
+
this.quill.on(tableUpEvent.TABLE_SELECTION_CHANGE, this.tableSelectioChange);
|
|
20
|
+
this.quill.on(tableUpEvent.TABLE_SELECTION_DISPLAY_CHANGE, this.tableSelectioChange);
|
|
18
21
|
}
|
|
19
22
|
|
|
23
|
+
tableSelectioChange = (tableSelection: InternalTableSelectionModule) => {
|
|
24
|
+
if (tableSelection.selectedTds.length <= 0) {
|
|
25
|
+
this.hide();
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
20
29
|
listenContextmenu = (e: MouseEvent) => {
|
|
21
30
|
e.preventDefault();
|
|
22
31
|
|
|
@@ -25,7 +34,8 @@ export class TableMenuContextmenu extends TableMenuCommon {
|
|
|
25
34
|
|
|
26
35
|
const tableNode = path.find(node => node.tagName && node.tagName.toUpperCase() === 'TABLE' && node.classList.contains('ql-table'));
|
|
27
36
|
|
|
28
|
-
|
|
37
|
+
const tableSelection = this.tableModule.getModule<TableSelection>('table-selection');
|
|
38
|
+
if (tableNode && tableSelection?.selectedTds?.length) {
|
|
29
39
|
if (!this.menu) {
|
|
30
40
|
this.menu = this.buildTools();
|
|
31
41
|
}
|
|
@@ -64,12 +74,16 @@ export class TableMenuContextmenu extends TableMenuCommon {
|
|
|
64
74
|
show() {}
|
|
65
75
|
|
|
66
76
|
update(position?: { x: number; y: number }) {
|
|
67
|
-
|
|
68
|
-
|
|
77
|
+
super.update();
|
|
78
|
+
const tableSelection = this.tableModule.getModule<TableSelection>('table-selection');
|
|
79
|
+
if (!this.table || !this.isMenuDisplay || !this.menu) {
|
|
80
|
+
this.hide();
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (!position || !tableSelection?.isDisplaySelection) {
|
|
69
84
|
return;
|
|
70
85
|
}
|
|
71
86
|
|
|
72
|
-
super.update();
|
|
73
87
|
const style: Record<string, any> = {
|
|
74
88
|
display: 'flex',
|
|
75
89
|
left: 0,
|
|
@@ -98,5 +112,7 @@ export class TableMenuContextmenu extends TableMenuCommon {
|
|
|
98
112
|
destroy() {
|
|
99
113
|
this.quill.root.removeEventListener('contextmenu', this.listenContextmenu);
|
|
100
114
|
super.destroy();
|
|
115
|
+
this.quill.off(tableUpEvent.TABLE_SELECTION_CHANGE, this.tableSelectioChange);
|
|
116
|
+
this.quill.off(tableUpEvent.TABLE_SELECTION_DISPLAY_CHANGE, this.tableSelectioChange);
|
|
101
117
|
}
|
|
102
118
|
}
|
|
@@ -1,31 +1,94 @@
|
|
|
1
1
|
import type Quill from 'quill';
|
|
2
|
+
import type { TableCellInnerFormat } from '../../formats';
|
|
2
3
|
import type { TableUp } from '../../table-up';
|
|
4
|
+
import type { InternalTableSelectionModule } from '../../utils';
|
|
5
|
+
import type { TableSelection } from '../table-selection';
|
|
3
6
|
import type { TableMenuOptionsInput } from './table-menu-common';
|
|
4
7
|
import { computePosition, flip, limitShift, offset, shift } from '@floating-ui/dom';
|
|
8
|
+
import { tableUpEvent } from '../../utils';
|
|
5
9
|
import { TableMenuCommon } from './table-menu-common';
|
|
6
10
|
|
|
7
11
|
export class TableMenuSelect extends TableMenuCommon {
|
|
8
12
|
constructor(public tableModule: TableUp, public quill: Quill, options: TableMenuOptionsInput) {
|
|
9
13
|
super(tableModule, quill, options);
|
|
10
14
|
|
|
11
|
-
this.
|
|
12
|
-
this.
|
|
13
|
-
this.
|
|
15
|
+
this.quill.on(tableUpEvent.TABLE_SELECTION_DRAG_START, this.tableSelectionDragStart);
|
|
16
|
+
this.quill.on(tableUpEvent.TABLE_SELECTION_DRAG_END, this.tableSelectionDragEnd);
|
|
17
|
+
this.quill.on(tableUpEvent.TABLE_SELECTION_CHANGE, this.tableSelectioChange);
|
|
18
|
+
this.quill.on(tableUpEvent.TABLE_SELECTION_DISPLAY_CHANGE, this.tableSelectionDisplayChange);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
tableSelectionDragStart = () => {
|
|
22
|
+
this.hide();
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
tableSelectionDragEnd = (tableSelection: InternalTableSelectionModule) => {
|
|
26
|
+
if (tableSelection.selectedTds.length > 0) {
|
|
27
|
+
this.show();
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
tableSelectioChange = (tableSelection: InternalTableSelectionModule, selectedTds: TableCellInnerFormat[]) => {
|
|
32
|
+
if (selectedTds.length <= 0) {
|
|
33
|
+
this.hide();
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
tableSelectionDisplayChange = (tableSelection: InternalTableSelectionModule) => {
|
|
38
|
+
if (!tableSelection.dragging) {
|
|
39
|
+
this.update();
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
buildTools(): HTMLElement {
|
|
44
|
+
const menu = super.buildTools();
|
|
45
|
+
this.tableModule.addContainer(menu);
|
|
46
|
+
return menu;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
show() {
|
|
50
|
+
super.show();
|
|
14
51
|
this.update();
|
|
15
52
|
}
|
|
16
53
|
|
|
17
54
|
update() {
|
|
18
|
-
if (!this.isMenuDisplay || !this.menu || !this.tableModule.tableSelection || !this.tableModule.tableSelection.isDisplaySelection) return;
|
|
19
55
|
super.update();
|
|
56
|
+
if (!this.menu && this.table) {
|
|
57
|
+
this.show();
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const selectedTds = this.getSelectedTds();
|
|
61
|
+
if (!this.menu || !this.table || selectedTds.length === 0) {
|
|
62
|
+
if (this.menu || !this.table) {
|
|
63
|
+
this.isMenuDisplay = false;
|
|
64
|
+
this.menu && this.menu.classList.add(this.bem.is('hidden'));
|
|
65
|
+
this.hide();
|
|
66
|
+
}
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
this.isMenuDisplay = true;
|
|
70
|
+
this.menu.classList.remove(this.bem.is('hidden'));
|
|
20
71
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
72
|
+
const tableSelection = this.tableModule.getModule<TableSelection>('table-selection');
|
|
73
|
+
if (tableSelection?.isDisplaySelection) {
|
|
74
|
+
computePosition(tableSelection.cellSelect, this.menu, {
|
|
75
|
+
placement: 'bottom',
|
|
76
|
+
middleware: [flip(), shift({ limiter: limitShift() }), offset(20)],
|
|
77
|
+
}).then(({ x, y }) => {
|
|
78
|
+
if (this.menu) {
|
|
79
|
+
Object.assign(this.menu.style, {
|
|
80
|
+
left: `${x}px`,
|
|
81
|
+
top: `${y}px`,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
28
84
|
});
|
|
29
|
-
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
destroy(): void {
|
|
89
|
+
super.destroy();
|
|
90
|
+
|
|
91
|
+
this.quill.off(tableUpEvent.TABLE_SELECTION_DRAG_START, this.tableSelectionDragStart);
|
|
92
|
+
this.quill.off(tableUpEvent.TABLE_SELECTION_DRAG_END, this.tableSelectionDragEnd);
|
|
30
93
|
}
|
|
31
94
|
}
|