studiokit-scaffolding-js 4.5.2 → 4.5.3
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/lib/components/Quill/Formats/Image.d.ts +46 -0
- package/lib/components/Quill/Formats/Image.js +86 -0
- package/lib/components/Quill/Formats/List.d.ts +15 -0
- package/lib/components/Quill/Formats/List.js +79 -0
- package/lib/components/Quill/Formats/Video.d.ts +11 -0
- package/lib/components/Quill/Formats/Video.js +50 -0
- package/lib/components/{Blots → Quill/Specs}/CustomImageSpec.d.ts +2 -1
- package/lib/components/{Blots → Quill/Specs}/CustomImageSpec.js +10 -1
- package/lib/components/{Blots → Quill/Specs}/CustomVideoSpec.d.ts +0 -0
- package/lib/components/{Blots → Quill/Specs}/CustomVideoSpec.js +0 -0
- package/lib/components/Quill/TableModule/Blots/BaseTableBlot.d.ts +29 -0
- package/lib/components/Quill/TableModule/Blots/BaseTableBlot.js +126 -0
- package/lib/components/Quill/TableModule/Blots/TableBlot.d.ts +20 -0
- package/lib/components/Quill/TableModule/Blots/TableBlot.js +69 -0
- package/lib/components/Quill/TableModule/Blots/TableBodyBlot.d.ts +18 -0
- package/lib/components/Quill/TableModule/Blots/TableBodyBlot.js +71 -0
- package/lib/components/Quill/TableModule/Blots/TableCellBlot.d.ts +34 -0
- package/lib/components/Quill/TableModule/Blots/TableCellBlot.js +236 -0
- package/lib/components/Quill/TableModule/Blots/TableContainer.d.ts +16 -0
- package/lib/components/Quill/TableModule/Blots/TableContainer.js +103 -0
- package/lib/components/Quill/TableModule/Blots/TableRowBlot.d.ts +22 -0
- package/lib/components/Quill/TableModule/Blots/TableRowBlot.js +91 -0
- package/lib/components/Quill/TableModule/constants.d.ts +34 -0
- package/lib/components/Quill/TableModule/constants.js +42 -0
- package/lib/components/Quill/TableModule/index.css +171 -0
- package/lib/components/Quill/TableModule/index.d.ts +23 -0
- package/lib/components/Quill/TableModule/index.js +312 -0
- package/lib/components/Quill/TableModule/utils.d.ts +9 -0
- package/lib/components/Quill/TableModule/utils.js +54 -0
- package/lib/components/Quill/accessibilityFix.d.ts +19 -0
- package/lib/components/Quill/accessibilityFix.js +267 -0
- package/lib/components/Quill/index.d.ts +1 -0
- package/lib/components/Quill/index.js +27 -0
- package/lib/utils/dom.d.ts +25 -0
- package/lib/utils/dom.js +201 -0
- package/lib/utils/sort.js +1 -1
- package/package.json +4 -1
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
.ql-snow .ql-editor .table-container {
|
|
2
|
+
margin-bottom: 1rem;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.ql-snow .ql-editor table {
|
|
6
|
+
border-collapse: collapse;
|
|
7
|
+
width: fit-content;
|
|
8
|
+
|
|
9
|
+
& td {
|
|
10
|
+
border: 1px solid black;
|
|
11
|
+
padding: 5px;
|
|
12
|
+
vertical-align: top;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
& img {
|
|
16
|
+
max-width: fit-content;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.ql-table.dn {
|
|
21
|
+
display: none !important;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.ql-picker.ql-table {
|
|
25
|
+
font-size: 11px;
|
|
26
|
+
font-weight: normal;
|
|
27
|
+
|
|
28
|
+
& .ql-picker-label {
|
|
29
|
+
display: block;
|
|
30
|
+
width: 28px;
|
|
31
|
+
height: 24px;
|
|
32
|
+
padding: 1px 4px;
|
|
33
|
+
|
|
34
|
+
& svg {
|
|
35
|
+
position: static !important;
|
|
36
|
+
margin: 0 !important;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
& .ql-picker-options {
|
|
41
|
+
width: 178px;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
& .ql-picker-item {
|
|
45
|
+
display: block;
|
|
46
|
+
float: left;
|
|
47
|
+
width: 30px;
|
|
48
|
+
height: 30px;
|
|
49
|
+
line-height: 30px;
|
|
50
|
+
text-align: center;
|
|
51
|
+
padding: 0;
|
|
52
|
+
margin: 1px;
|
|
53
|
+
border: 1px solid #444;
|
|
54
|
+
color: #444;
|
|
55
|
+
|
|
56
|
+
&:nth-child(5)::after {
|
|
57
|
+
clear: both;
|
|
58
|
+
display: block;
|
|
59
|
+
content: "";
|
|
60
|
+
width: 100%;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
&:hover {
|
|
64
|
+
background-color: var(--color-purple);
|
|
65
|
+
|
|
66
|
+
&::before {
|
|
67
|
+
color: var(--color-white);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.ql-picker-item[data-value=newtable_1_1]::before {
|
|
74
|
+
content: "1x1";
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.ql-picker-item[data-value=newtable_1_2]::before {
|
|
78
|
+
content: "1x2";
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.ql-picker-item[data-value=newtable_1_3]::before {
|
|
82
|
+
content: "1x3";
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.ql-picker-item[data-value=newtable_1_4]::before {
|
|
86
|
+
content: "1x4";
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.ql-picker-item[data-value=newtable_1_5]::before {
|
|
90
|
+
content: "1x5";
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.ql-picker-item[data-value=newtable_2_1]::before {
|
|
94
|
+
content: "2x1";
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.ql-picker-item[data-value=newtable_2_2]::before {
|
|
98
|
+
content: "2x2";
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.ql-picker-item[data-value=newtable_2_3]::before {
|
|
102
|
+
content: "2x3";
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.ql-picker-item[data-value=newtable_2_4]::before {
|
|
106
|
+
content: "2x4";
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.ql-picker-item[data-value=newtable_2_5]::before {
|
|
110
|
+
content: "2x5";
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.ql-picker-item[data-value=newtable_3_1]::before {
|
|
114
|
+
content: "3x1";
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.ql-picker-item[data-value=newtable_3_2]::before {
|
|
118
|
+
content: "3x2";
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.ql-picker-item[data-value=newtable_3_3]::before {
|
|
122
|
+
content: "3x3";
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.ql-picker-item[data-value=newtable_3_4]::before {
|
|
126
|
+
content: "3x4";
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.ql-picker-item[data-value=newtable_3_5]::before {
|
|
130
|
+
content: "3x5";
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.ql-picker-item[data-value=newtable_4_1]::before {
|
|
134
|
+
content: "4x1";
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.ql-picker-item[data-value=newtable_4_2]::before {
|
|
138
|
+
content: "4x2";
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.ql-picker-item[data-value=newtable_4_3]::before {
|
|
142
|
+
content: "4x3";
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.ql-picker-item[data-value=newtable_4_4]::before {
|
|
146
|
+
content: "4x4";
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.ql-picker-item[data-value=newtable_4_5]::before {
|
|
150
|
+
content: "4x5";
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.ql-picker-item[data-value=newtable_5_1]::before {
|
|
154
|
+
content: "5x1";
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.ql-picker-item[data-value=newtable_5_2]::before {
|
|
158
|
+
content: "5x2";
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.ql-picker-item[data-value=newtable_5_3]::before {
|
|
162
|
+
content: "5x3";
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.ql-picker-item[data-value=newtable_5_4]::before {
|
|
166
|
+
content: "5x4";
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.ql-picker-item[data-value=newtable_5_5]::before {
|
|
170
|
+
content: "5x5";
|
|
171
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { RangeStatic } from 'quill';
|
|
2
|
+
import { Quill } from 'react-quill';
|
|
3
|
+
import { TableBlot } from './Blots/TableBlot';
|
|
4
|
+
import { TableCellBlot } from './Blots/TableCellBlot';
|
|
5
|
+
export declare class TableModule {
|
|
6
|
+
static register(): void;
|
|
7
|
+
quill: Quill;
|
|
8
|
+
options: any;
|
|
9
|
+
tableToolbarControls: HTMLElement[];
|
|
10
|
+
constructor(quill: Quill, options: any);
|
|
11
|
+
showOrHideToolbarControls: () => void;
|
|
12
|
+
handleBackspace: (range: RangeStatic, context: any) => boolean;
|
|
13
|
+
handleDelete: (range: RangeStatic, context: any) => boolean;
|
|
14
|
+
handleDeleteRange: (range: RangeStatic) => boolean;
|
|
15
|
+
getSelectedCell(): TableCellBlot | null;
|
|
16
|
+
getSelectedTable(): TableBlot | undefined;
|
|
17
|
+
tableHandler(action: string): void;
|
|
18
|
+
addNewTable(action: string, range: RangeStatic): void;
|
|
19
|
+
insertCol(selectedCell: TableCellBlot, range: RangeStatic): void;
|
|
20
|
+
insertRow(selectedCell: TableCellBlot, range: RangeStatic): void;
|
|
21
|
+
deleteCol(selectedCell: TableCellBlot): void;
|
|
22
|
+
deleteRow(selectedCell: TableCellBlot): void;
|
|
23
|
+
}
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TableModule = void 0;
|
|
4
|
+
var lodash_1 = require("lodash");
|
|
5
|
+
var react_quill_1 = require("react-quill");
|
|
6
|
+
var logger_1 = require("../../../utils/logger");
|
|
7
|
+
var BaseTableBlot_1 = require("./Blots/BaseTableBlot");
|
|
8
|
+
var TableBlot_1 = require("./Blots/TableBlot");
|
|
9
|
+
var TableBodyBlot_1 = require("./Blots/TableBodyBlot");
|
|
10
|
+
var TableCellBlot_1 = require("./Blots/TableCellBlot");
|
|
11
|
+
var TableContainer_1 = require("./Blots/TableContainer");
|
|
12
|
+
var TableRowBlot_1 = require("./Blots/TableRowBlot");
|
|
13
|
+
var constants_1 = require("./constants");
|
|
14
|
+
var utils_1 = require("./utils");
|
|
15
|
+
var Delta = react_quill_1.Quill.import('delta');
|
|
16
|
+
var Scroll = react_quill_1.Quill.import('blots/scroll');
|
|
17
|
+
var TableModule = /** @class */ (function () {
|
|
18
|
+
function TableModule(quill, options) {
|
|
19
|
+
var _this = this;
|
|
20
|
+
this.tableToolbarControls = [];
|
|
21
|
+
//#region Helpers
|
|
22
|
+
this.showOrHideToolbarControls = function () {
|
|
23
|
+
var selectedCell = _this.getSelectedCell();
|
|
24
|
+
if (selectedCell) {
|
|
25
|
+
_this.tableToolbarControls.forEach(function (domNode) {
|
|
26
|
+
domNode.classList.remove('dn');
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
_this.tableToolbarControls.forEach(function (domNode) {
|
|
31
|
+
domNode.classList.add('dn');
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
this.handleBackspace = function (range, context) {
|
|
36
|
+
if (range.index === 0 || _this.quill.getLength() <= 1)
|
|
37
|
+
return true;
|
|
38
|
+
var line = _this.quill.getLine(range.index)[0];
|
|
39
|
+
if (context.offset === 0 && utils_1.isLineAfterTable(line)) {
|
|
40
|
+
logger_1.getLogger().debug('prevent backspace after table', { range: range, context: context, line: line });
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
// if inside a TableCellBlot and at the start of the cell
|
|
44
|
+
// prevent "backspace" from removing previous cell
|
|
45
|
+
// or items before the table if in the first cell
|
|
46
|
+
if (
|
|
47
|
+
// in a cell
|
|
48
|
+
utils_1.isLineInTableCell(line) &&
|
|
49
|
+
// at the start of the cell
|
|
50
|
+
context.offset === 0 &&
|
|
51
|
+
!line.prev &&
|
|
52
|
+
// there is a cell before this one in the row
|
|
53
|
+
((line.parent.prev && line.parent.prev instanceof TableCellBlot_1.TableCellBlot) ||
|
|
54
|
+
// or the cell is at the start of a row
|
|
55
|
+
!line.parent.prev)) {
|
|
56
|
+
logger_1.getLogger().debug('prevent cell backspace', { range: range, context: context, line: line });
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
return true;
|
|
60
|
+
};
|
|
61
|
+
this.handleDelete = function (range, context) {
|
|
62
|
+
var length = /^[\uD800-\uDBFF][\uDC00-\uDFFF]/.test(context.suffix) ? 2 : 1;
|
|
63
|
+
if (range.index >= _this.quill.getLength() - length)
|
|
64
|
+
return true;
|
|
65
|
+
var line = _this.quill.getLine(range.index)[0];
|
|
66
|
+
if (context.offset === line.length() - 1 && utils_1.isLineBeforeTable(line)) {
|
|
67
|
+
logger_1.getLogger().debug('prevent delete before table', { range: range, context: context, line: line });
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
// if inside a TableCellBlot and at the end of the cell
|
|
71
|
+
// prevent "delete" from removing the next cell
|
|
72
|
+
// or items after the table if in the last cell
|
|
73
|
+
if (
|
|
74
|
+
// in a cell
|
|
75
|
+
utils_1.isLineInTableCell(line) &&
|
|
76
|
+
// at the end of the cell
|
|
77
|
+
!line.next &&
|
|
78
|
+
context.offset === line.length() - 1 &&
|
|
79
|
+
// there is a cell after this one in the row
|
|
80
|
+
((line.parent.next && line.parent.next instanceof TableCellBlot_1.TableCellBlot) ||
|
|
81
|
+
// or the cell is at the start of a row
|
|
82
|
+
!line.parent.next)) {
|
|
83
|
+
logger_1.getLogger().debug('prevent cell delete', { range: range, context: context, line: line });
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
return true;
|
|
87
|
+
};
|
|
88
|
+
this.handleDeleteRange = function (range) {
|
|
89
|
+
var lines = _this.quill.getLines(range);
|
|
90
|
+
logger_1.getLogger().debug('handleDeleteRange', { range: range, lines: lines });
|
|
91
|
+
var willDeleteCellWithoutRow = utils_1.rangeRemovalWillDeleteCellWithoutRow(_this.quill, range);
|
|
92
|
+
if (willDeleteCellWithoutRow) {
|
|
93
|
+
logger_1.getLogger().debug('prevent delete cell out of row');
|
|
94
|
+
}
|
|
95
|
+
return !willDeleteCellWithoutRow;
|
|
96
|
+
};
|
|
97
|
+
this.quill = quill;
|
|
98
|
+
this.options = options;
|
|
99
|
+
// Define Toolbar Handler
|
|
100
|
+
var toolbar = quill.getModule('toolbar');
|
|
101
|
+
if (toolbar) {
|
|
102
|
+
toolbar.addHandler('table', function (action) {
|
|
103
|
+
return _this.tableHandler(action);
|
|
104
|
+
});
|
|
105
|
+
// by default, hide all table controls
|
|
106
|
+
toolbar.controls.forEach(function (control) {
|
|
107
|
+
var name = control[0], domNode = control[1];
|
|
108
|
+
if (name === 'table' && domNode.tagName === 'BUTTON') {
|
|
109
|
+
_this.tableToolbarControls.push(domNode);
|
|
110
|
+
domNode.classList.add('dn');
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
this.quill.on('editor-change', this.showOrHideToolbarControls);
|
|
115
|
+
this.quill.on('selection-change', this.showOrHideToolbarControls);
|
|
116
|
+
// Define Clipboard Matchers
|
|
117
|
+
// When HTML is loaded or pasted into Quill, the matchers
|
|
118
|
+
// will find the given HTML Tag and allow the delta for the element's
|
|
119
|
+
// content to be modified.
|
|
120
|
+
var clipboard = quill.getModule('clipboard');
|
|
121
|
+
if (clipboard) {
|
|
122
|
+
clipboard.addMatcher(constants_1.TAG_NAME.TD, function (node, delta) {
|
|
123
|
+
logger_1.getLogger().debug(constants_1.TAG_NAME.TD + " matched", { node: node, delta: delta });
|
|
124
|
+
// load the table cell attribute to use as the delta operation attributes
|
|
125
|
+
var dataValue = node.getAttribute(constants_1.ATTRIBUTE.DATA_VALUE);
|
|
126
|
+
var defaultAttributes = {
|
|
127
|
+
td: dataValue
|
|
128
|
+
};
|
|
129
|
+
// handle empty cells, insert a single block / paragraph
|
|
130
|
+
if (delta.length() === 0) {
|
|
131
|
+
var updatedDelta_1 = new Delta().insert('\n', defaultAttributes);
|
|
132
|
+
logger_1.getLogger().debug(constants_1.TAG_NAME.TD + " matched - final delta (empty cell)", updatedDelta_1);
|
|
133
|
+
return updatedDelta_1;
|
|
134
|
+
}
|
|
135
|
+
// for each operation inside the cell's delta, add the table cell attributes
|
|
136
|
+
var updatedDelta = delta.reduce(function (newDelta, op) {
|
|
137
|
+
newDelta.insert(op.insert, lodash_1.merge({}, op.attributes, defaultAttributes));
|
|
138
|
+
return newDelta;
|
|
139
|
+
}, new Delta());
|
|
140
|
+
logger_1.getLogger().debug(constants_1.TAG_NAME.TD + " matched - final delta", updatedDelta);
|
|
141
|
+
return updatedDelta;
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
// Override "backspace" and "delete" actions that would delete or combine a table cell
|
|
145
|
+
var keyboard = quill.getModule('keyboard');
|
|
146
|
+
if (keyboard) {
|
|
147
|
+
keyboard.addBinding({ key: constants_1.KEY.BACKSPACE }, { collapsed: false }, this.handleDeleteRange);
|
|
148
|
+
// move binding to first position
|
|
149
|
+
var backspaceRangeBinding = keyboard.bindings[constants_1.KEY.BACKSPACE].pop();
|
|
150
|
+
keyboard.bindings[constants_1.KEY.BACKSPACE].splice(0, 0, backspaceRangeBinding);
|
|
151
|
+
keyboard.addBinding({ key: constants_1.KEY.BACKSPACE }, { collapsed: true }, this.handleBackspace);
|
|
152
|
+
// move binding to first position
|
|
153
|
+
var backspaceBinding = keyboard.bindings[constants_1.KEY.BACKSPACE].pop();
|
|
154
|
+
keyboard.bindings[constants_1.KEY.BACKSPACE].splice(0, 0, backspaceBinding);
|
|
155
|
+
keyboard.addBinding({ key: constants_1.KEY.DELETE }, { collapsed: false }, this.handleDeleteRange);
|
|
156
|
+
// move binding to first position
|
|
157
|
+
var deleteRangeBinding = keyboard.bindings[constants_1.KEY.DELETE].pop();
|
|
158
|
+
keyboard.bindings[constants_1.KEY.DELETE].splice(0, 0, deleteRangeBinding);
|
|
159
|
+
keyboard.addBinding({ key: constants_1.KEY.DELETE }, { collapsed: true }, this.handleDelete);
|
|
160
|
+
// move binding to first position
|
|
161
|
+
var deleteBinding = keyboard.bindings[constants_1.KEY.DELETE].pop();
|
|
162
|
+
keyboard.bindings[constants_1.KEY.DELETE].splice(0, 0, deleteBinding);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
TableModule.register = function () {
|
|
166
|
+
react_quill_1.Quill.register(BaseTableBlot_1.BaseTableBlot);
|
|
167
|
+
react_quill_1.Quill.register(TableCellBlot_1.TableCellBlot);
|
|
168
|
+
react_quill_1.Quill.register(TableRowBlot_1.TableRowBlot);
|
|
169
|
+
react_quill_1.Quill.register(TableBodyBlot_1.TableBodyBlot);
|
|
170
|
+
react_quill_1.Quill.register(TableBlot_1.TableBlot);
|
|
171
|
+
react_quill_1.Quill.register(TableContainer_1.TableContainerBlot);
|
|
172
|
+
};
|
|
173
|
+
TableModule.prototype.getSelectedCell = function () {
|
|
174
|
+
var selection = this.quill.getSelection();
|
|
175
|
+
if (!selection) {
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
var leaf = this.quill.getLeaf(selection.index);
|
|
179
|
+
var blot = leaf[0];
|
|
180
|
+
while (blot && !(blot instanceof TableCellBlot_1.TableCellBlot) && blot.parent) {
|
|
181
|
+
blot = blot.parent;
|
|
182
|
+
}
|
|
183
|
+
if (blot instanceof TableCellBlot_1.TableCellBlot) {
|
|
184
|
+
return blot;
|
|
185
|
+
}
|
|
186
|
+
return null;
|
|
187
|
+
};
|
|
188
|
+
TableModule.prototype.getSelectedTable = function () {
|
|
189
|
+
var _a;
|
|
190
|
+
return (_a = this.getSelectedCell()) === null || _a === void 0 ? void 0 : _a.table();
|
|
191
|
+
};
|
|
192
|
+
//#endregion Helpers
|
|
193
|
+
//#region Table Handler
|
|
194
|
+
TableModule.prototype.tableHandler = function (action) {
|
|
195
|
+
logger_1.getLogger().debug('tableHandler', action);
|
|
196
|
+
// require a selection range
|
|
197
|
+
var range = this.quill.getSelection();
|
|
198
|
+
if (!range)
|
|
199
|
+
return;
|
|
200
|
+
if (action.includes(constants_1.TABLE_ACTION.NEW_TABLE)) {
|
|
201
|
+
this.addNewTable(action, range);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
// require a selected cell
|
|
205
|
+
var selectedCell = this.getSelectedCell();
|
|
206
|
+
if (!selectedCell)
|
|
207
|
+
return;
|
|
208
|
+
switch (action) {
|
|
209
|
+
case constants_1.TABLE_ACTION.INSERT_COL:
|
|
210
|
+
this.insertCol(selectedCell, range);
|
|
211
|
+
break;
|
|
212
|
+
case constants_1.TABLE_ACTION.INSERT_ROW:
|
|
213
|
+
this.insertRow(selectedCell, range);
|
|
214
|
+
break;
|
|
215
|
+
case constants_1.TABLE_ACTION.DELETE_COL:
|
|
216
|
+
this.deleteCol(selectedCell);
|
|
217
|
+
break;
|
|
218
|
+
case constants_1.TABLE_ACTION.DELETE_ROW:
|
|
219
|
+
this.deleteRow(selectedCell);
|
|
220
|
+
break;
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
TableModule.prototype.addNewTable = function (action, range) {
|
|
224
|
+
var index = range.index;
|
|
225
|
+
// e.g. "new-table-2-2"
|
|
226
|
+
var sizes = action.replace(constants_1.TABLE_ACTION.NEW_TABLE, '').split('_');
|
|
227
|
+
var rows = parseInt(sizes[0]);
|
|
228
|
+
var cols = parseInt(sizes[1]);
|
|
229
|
+
var tableContainer = TableContainer_1.TableContainerBlot.createWithChildren(rows, cols);
|
|
230
|
+
// insert the table into the top level scroll element
|
|
231
|
+
// before the current leaf's top level branch
|
|
232
|
+
// PREVENT NESTED TABLES
|
|
233
|
+
var topBranch = null;
|
|
234
|
+
var leaf = this.quill.getLeaf(index);
|
|
235
|
+
var blot = leaf[0];
|
|
236
|
+
while (blot && blot.parent && !(blot instanceof Scroll)) {
|
|
237
|
+
topBranch = blot;
|
|
238
|
+
blot = blot.parent;
|
|
239
|
+
}
|
|
240
|
+
if (!blot || !(blot instanceof Scroll))
|
|
241
|
+
return;
|
|
242
|
+
blot.insertBefore(tableContainer, topBranch || undefined);
|
|
243
|
+
this.quill.setSelection(tableContainer.offset(this.quill.scroll), 0, 'user');
|
|
244
|
+
};
|
|
245
|
+
TableModule.prototype.insertCol = function (selectedCell, range) {
|
|
246
|
+
var _a;
|
|
247
|
+
var selectedCellColumn = selectedCell.column();
|
|
248
|
+
var tableId = selectedCell.tableId();
|
|
249
|
+
var tableBody = (_a = selectedCell.row()) === null || _a === void 0 ? void 0 : _a.tableBody();
|
|
250
|
+
if (!tableBody)
|
|
251
|
+
return;
|
|
252
|
+
tableBody.children.forEach(function (child) {
|
|
253
|
+
var tableRow = child;
|
|
254
|
+
var rowId = tableRow.id();
|
|
255
|
+
var tableCell = TableCellBlot_1.TableCellBlot.createWithChildren(tableId, rowId);
|
|
256
|
+
var cells = tableRow.children.map(function (c) { return c; });
|
|
257
|
+
var nextColumnCell = cells.length > selectedCellColumn - 1 ? cells[selectedCellColumn] : undefined;
|
|
258
|
+
if (nextColumnCell) {
|
|
259
|
+
tableRow.insertBefore(tableCell, nextColumnCell);
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
tableRow.appendChild(tableCell);
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
};
|
|
266
|
+
TableModule.prototype.insertRow = function (selectedCell, range) {
|
|
267
|
+
var currentRow = selectedCell.row();
|
|
268
|
+
if (!currentRow)
|
|
269
|
+
return;
|
|
270
|
+
var nextRow = currentRow.next;
|
|
271
|
+
var tableBody = currentRow.tableBody();
|
|
272
|
+
if (!tableBody)
|
|
273
|
+
return;
|
|
274
|
+
var newRow = TableRowBlot_1.TableRowBlot.createFromReference(currentRow);
|
|
275
|
+
if (nextRow) {
|
|
276
|
+
tableBody.insertBefore(newRow, nextRow);
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
tableBody.appendChild(newRow);
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
TableModule.prototype.deleteCol = function (selectedCell) {
|
|
283
|
+
var _a;
|
|
284
|
+
var selectedCellColumn = selectedCell.column();
|
|
285
|
+
var tableBody = (_a = selectedCell.row()) === null || _a === void 0 ? void 0 : _a.tableBody();
|
|
286
|
+
if (!tableBody)
|
|
287
|
+
return;
|
|
288
|
+
tableBody.children.forEach(function (c) {
|
|
289
|
+
var tableRow = c;
|
|
290
|
+
var cells = tableRow.children.map(function (c) { return c; });
|
|
291
|
+
var cell = cells[selectedCellColumn - 1];
|
|
292
|
+
cell === null || cell === void 0 ? void 0 : cell.remove();
|
|
293
|
+
});
|
|
294
|
+
};
|
|
295
|
+
TableModule.prototype.deleteRow = function (selectedCell) {
|
|
296
|
+
var selectedRow = selectedCell.row();
|
|
297
|
+
if (!selectedRow)
|
|
298
|
+
return;
|
|
299
|
+
var cellOffset = selectedCell.offset(); // offset inside row
|
|
300
|
+
var tableBody = selectedRow.tableBody();
|
|
301
|
+
var rowToSelectAfter = selectedRow.next || selectedRow.prev;
|
|
302
|
+
// delete the row
|
|
303
|
+
selectedRow.remove();
|
|
304
|
+
// focus the next row or prev row if possible
|
|
305
|
+
if (tableBody && tableBody.children.length > 0 && rowToSelectAfter) {
|
|
306
|
+
var index = rowToSelectAfter.offset(this.quill.scroll);
|
|
307
|
+
this.quill.setSelection(index + cellOffset, 0);
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
return TableModule;
|
|
311
|
+
}());
|
|
312
|
+
exports.TableModule = TableModule;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Blot } from 'parchment/dist/src/blot/abstract/blot';
|
|
2
|
+
import { RangeStatic } from 'quill';
|
|
3
|
+
import { Quill } from 'react-quill';
|
|
4
|
+
export declare const isInstanceOfBlot: (blot: Blot, blotName: string) => boolean;
|
|
5
|
+
export declare const isLineInTableCell: (line: Blot) => boolean;
|
|
6
|
+
export declare const isLineBeforeTable: (line: Blot) => boolean;
|
|
7
|
+
export declare const isLineAfterTable: (line: Blot) => boolean;
|
|
8
|
+
export declare const rangeRemovalWillDeleteCellWithoutRow: (quill: Quill, range: RangeStatic) => boolean;
|
|
9
|
+
export declare function newId(prefix: string): string;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.newId = exports.rangeRemovalWillDeleteCellWithoutRow = exports.isLineAfterTable = exports.isLineBeforeTable = exports.isLineInTableCell = exports.isInstanceOfBlot = void 0;
|
|
4
|
+
var logger_1 = require("../../../utils/logger");
|
|
5
|
+
var constants_1 = require("./constants");
|
|
6
|
+
var isInstanceOfBlot = function (blot, blotName) { return blot.statics.blotName === blotName; };
|
|
7
|
+
exports.isInstanceOfBlot = isInstanceOfBlot;
|
|
8
|
+
var isLineInTableCell = function (line) { return line.parent && exports.isInstanceOfBlot(line.parent, constants_1.TABLE_BLOT_NAME.TD); };
|
|
9
|
+
exports.isLineInTableCell = isLineInTableCell;
|
|
10
|
+
var isLineBeforeTable = function (line) {
|
|
11
|
+
return line.next && exports.isInstanceOfBlot(line.next, constants_1.TABLE_BLOT_NAME.TABLE_CONTAINER);
|
|
12
|
+
};
|
|
13
|
+
exports.isLineBeforeTable = isLineBeforeTable;
|
|
14
|
+
var isLineAfterTable = function (line) {
|
|
15
|
+
return line.prev && exports.isInstanceOfBlot(line.parent, constants_1.TABLE_BLOT_NAME.TABLE_CONTAINER);
|
|
16
|
+
};
|
|
17
|
+
exports.isLineAfterTable = isLineAfterTable;
|
|
18
|
+
var rangeRemovalWillDeleteCellWithoutRow = function (quill, range) {
|
|
19
|
+
var lines = quill.getLines(range);
|
|
20
|
+
var willDeleteCellWithoutRow = lines.some(function (line) {
|
|
21
|
+
if (exports.isLineInTableCell(line)) {
|
|
22
|
+
var cell = line.parent;
|
|
23
|
+
var cellOffset = cell.offset(quill.scroll);
|
|
24
|
+
var cellLength = cell.length();
|
|
25
|
+
var willDeleteCell =
|
|
26
|
+
// starts in cell and goes out of cell, or is exactly the cell
|
|
27
|
+
(range.index >= cellOffset && range.index + range.length >= cellOffset + cellLength) ||
|
|
28
|
+
// starts before cell and stops in cell
|
|
29
|
+
(range.index < cellOffset && range.index + range.length < cellOffset + cellLength);
|
|
30
|
+
var row = cell.row();
|
|
31
|
+
if (!row)
|
|
32
|
+
return false;
|
|
33
|
+
var rowOffset = row.offset(quill.scroll);
|
|
34
|
+
var rowLength = row.length();
|
|
35
|
+
var willDeleteRow = range.index <= rowOffset && range.index + range.length >= rowOffset + rowLength;
|
|
36
|
+
logger_1.getLogger().debug('rangeRemovalWillDeleteCellWithoutRow line', {
|
|
37
|
+
range: range,
|
|
38
|
+
line: line,
|
|
39
|
+
cellOffset: cellOffset,
|
|
40
|
+
cellLength: cellLength,
|
|
41
|
+
willDeleteCell: willDeleteCell,
|
|
42
|
+
willDeleteRow: willDeleteRow
|
|
43
|
+
});
|
|
44
|
+
return willDeleteCell && !willDeleteRow;
|
|
45
|
+
}
|
|
46
|
+
return false;
|
|
47
|
+
}, {});
|
|
48
|
+
return willDeleteCellWithoutRow;
|
|
49
|
+
};
|
|
50
|
+
exports.rangeRemovalWillDeleteCellWithoutRow = rangeRemovalWillDeleteCellWithoutRow;
|
|
51
|
+
function newId(prefix) {
|
|
52
|
+
return prefix + "-" + Math.random().toString(36).slice(2, 6);
|
|
53
|
+
}
|
|
54
|
+
exports.newId = newId;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { Quill } from 'react-quill';
|
|
3
|
+
/**
|
|
4
|
+
* Apply aria-labels to the icons from the quill text editor
|
|
5
|
+
* Imports the icons from Quill, recursively go through each icon and get the <svg /> html.
|
|
6
|
+
* Then it sets a <label /> between the <svg />
|
|
7
|
+
* Using css, it hides the label content.
|
|
8
|
+
*
|
|
9
|
+
* @param {*} icons The object that includes all the icons from Quill
|
|
10
|
+
*/
|
|
11
|
+
export declare function applyAccessibilityToIcons(icons: any): void;
|
|
12
|
+
/**
|
|
13
|
+
* Grabs the DOM from the toolbar reference and loop through each button, picker, and dropdowns adding accessibility values
|
|
14
|
+
* Help from: https://github.com/quilljs/quill/issues/1173
|
|
15
|
+
*
|
|
16
|
+
* @param toolbarRef: reference to the div containing our custom Quill toolbar
|
|
17
|
+
* @param editor: reference to the Quill editor
|
|
18
|
+
*/
|
|
19
|
+
export declare function applyAccessibilityHacks(toolbarRef: React.RefObject<HTMLDivElement>, editor: Quill): void;
|