@themarioga/grid-editor 6.0.0 → 7.1.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/AUTO_SAVE.md +2 -2
- package/BUILDING.md +45 -29
- package/CHANGELOG.md +59 -0
- package/README.md +163 -87
- package/UPGRADING.md +119 -0
- package/dist/grideditor.bundle.min.js +14 -0
- package/dist/grideditor.d.ts +335 -0
- package/dist/grideditor.esm.js +3977 -0
- package/dist/grideditor.jquery.js +253 -0
- package/dist/grideditor.jquery.min.js +1 -0
- package/dist/grideditor.jquery.min.js.map +7 -0
- package/dist/grideditor.js +3983 -0
- package/dist/grideditor.min.js +6 -0
- package/dist/grideditor.min.js.map +7 -0
- package/dist/locales/grideditor.es.esm.js +158 -0
- package/dist/locales/grideditor.es.js +164 -168
- package/dist/locales/grideditor.es.min.js +6 -2
- package/dist/locales/grideditor.es.min.js.map +7 -1
- package/dist/plugins/grideditor.accordion.esm.js +294 -0
- package/dist/plugins/grideditor.accordion.js +286 -180
- package/dist/plugins/grideditor.accordion.min.js +1 -2
- package/dist/plugins/grideditor.accordion.min.js.map +7 -1
- package/dist/plugins/grideditor.alignment.esm.js +55 -0
- package/dist/plugins/grideditor.alignment.js +58 -77
- package/dist/plugins/grideditor.alignment.min.js +1 -2
- package/dist/plugins/grideditor.alignment.min.js.map +7 -1
- package/dist/plugins/grideditor.card.esm.js +73 -0
- package/dist/plugins/grideditor.card.js +74 -64
- package/dist/plugins/grideditor.card.min.js +1 -2
- package/dist/plugins/grideditor.card.min.js.map +7 -1
- package/dist/plugins/grideditor.ckeditor.esm.js +500 -0
- package/dist/plugins/grideditor.ckeditor.js +484 -449
- package/dist/plugins/grideditor.ckeditor.min.js +1 -2
- package/dist/plugins/grideditor.ckeditor.min.js.map +7 -1
- package/dist/plugins/grideditor.clipboard.esm.js +326 -0
- package/dist/plugins/grideditor.clipboard.js +298 -235
- package/dist/plugins/grideditor.clipboard.min.js +1 -2
- package/dist/plugins/grideditor.clipboard.min.js.map +7 -1
- package/dist/plugins/grideditor.codemirror-inline.esm.js +205 -0
- package/dist/plugins/grideditor.codemirror-inline.js +188 -168
- package/dist/plugins/grideditor.codemirror-inline.min.js +1 -2
- package/dist/plugins/grideditor.codemirror-inline.min.js.map +7 -1
- package/dist/plugins/grideditor.codemirror.esm.js +63 -0
- package/dist/plugins/grideditor.codemirror.js +60 -71
- package/dist/plugins/grideditor.codemirror.min.js +1 -2
- package/dist/plugins/grideditor.codemirror.min.js.map +7 -1
- package/dist/plugins/grideditor.elements.esm.js +271 -0
- package/dist/plugins/grideditor.elements.js +256 -149
- package/dist/plugins/grideditor.elements.min.js +1 -2
- package/dist/plugins/grideditor.elements.min.js.map +7 -1
- package/dist/plugins/grideditor.float.esm.js +34 -0
- package/dist/plugins/grideditor.float.js +37 -52
- package/dist/plugins/grideditor.float.min.js +1 -2
- package/dist/plugins/grideditor.float.min.js.map +7 -1
- package/dist/plugins/grideditor.gutters.esm.js +143 -0
- package/dist/plugins/grideditor.gutters.js +134 -131
- package/dist/plugins/grideditor.gutters.min.js +1 -2
- package/dist/plugins/grideditor.gutters.min.js.map +7 -1
- package/dist/plugins/grideditor.order.esm.js +189 -0
- package/dist/plugins/grideditor.order.js +170 -182
- package/dist/plugins/grideditor.order.min.js +1 -2
- package/dist/plugins/grideditor.order.min.js.map +7 -1
- package/dist/plugins/grideditor.popup.esm.js +187 -0
- package/dist/plugins/grideditor.popup.js +183 -134
- package/dist/plugins/grideditor.popup.min.js +1 -2
- package/dist/plugins/grideditor.popup.min.js.map +7 -1
- package/dist/plugins/grideditor.sections.esm.js +271 -0
- package/dist/plugins/grideditor.sections.js +250 -173
- package/dist/plugins/grideditor.sections.min.js +1 -2
- package/dist/plugins/grideditor.sections.min.js.map +7 -1
- package/dist/plugins/grideditor.spacing.esm.js +318 -0
- package/dist/plugins/grideditor.spacing.js +296 -272
- package/dist/plugins/grideditor.spacing.min.js +1 -2
- package/dist/plugins/grideditor.spacing.min.js.map +7 -1
- package/dist/plugins/grideditor.summernote.esm.js +509 -0
- package/dist/plugins/grideditor.summernote.js +493 -427
- package/dist/plugins/grideditor.summernote.min.js +1 -2
- package/dist/plugins/grideditor.summernote.min.js.map +7 -1
- package/dist/plugins/grideditor.tabs.esm.js +237 -0
- package/dist/plugins/grideditor.tabs.js +233 -139
- package/dist/plugins/grideditor.tabs.min.js +1 -2
- package/dist/plugins/grideditor.tabs.min.js.map +7 -1
- package/dist/plugins/grideditor.textalign.esm.js +40 -0
- package/dist/plugins/grideditor.textalign.js +43 -56
- package/dist/plugins/grideditor.textalign.min.js +1 -2
- package/dist/plugins/grideditor.textalign.min.js.map +7 -1
- package/dist/plugins/grideditor.tinymce.esm.js +519 -0
- package/dist/plugins/grideditor.tinymce.js +502 -490
- package/dist/plugins/grideditor.tinymce.min.js +1 -2
- package/dist/plugins/grideditor.tinymce.min.js.map +7 -1
- package/dist/plugins/grideditor.visibility.esm.js +158 -0
- package/dist/plugins/grideditor.visibility.js +140 -149
- package/dist/plugins/grideditor.visibility.min.js +1 -2
- package/dist/plugins/grideditor.visibility.min.js.map +7 -1
- package/docs/events.md +47 -21
- package/docs/locale-keys.md +6 -0
- package/docs/plugins.md +47 -25
- package/example/adapter.html +112 -0
- package/example/attributes.html +89 -62
- package/example/autocols.html +9 -9
- package/example/autosave.html +18 -16
- package/example/basic.html +8 -6
- package/example/breakpoints.html +5 -6
- package/example/ckeditor.html +4 -5
- package/example/clipboard.html +15 -11
- package/example/codemirror.html +13 -8
- package/example/containers.html +11 -9
- package/example/custom_editor.html +53 -34
- package/example/elements.html +14 -12
- package/example/index.html +16 -2
- package/example/locale.html +6 -7
- package/example/plugins.html +44 -29
- package/example/summernote.html +6 -5
- package/example/utilities.html +17 -13
- package/example/wrap_content.html +13 -10
- package/package.json +44 -12
- package/src/js/dom.js +401 -0
- package/src/js/grideditor.classic.js +16 -0
- package/src/js/grideditor.jquery.js +325 -0
- package/src/js/{jquery.grideditor.js → grideditor.js} +1284 -1124
- package/src/js/locales/grideditor.es.js +163 -156
- package/src/js/plugins/grideditor.accordion.js +97 -77
- package/src/js/plugins/grideditor.alignment.js +5 -7
- package/src/js/plugins/grideditor.card.js +23 -23
- package/src/js/plugins/grideditor.ckeditor.js +107 -106
- package/src/js/plugins/grideditor.clipboard.js +49 -37
- package/src/js/plugins/grideditor.codemirror-inline.js +50 -37
- package/src/js/plugins/grideditor.codemirror.js +9 -10
- package/src/js/plugins/grideditor.elements.js +57 -33
- package/src/js/plugins/grideditor.float.js +4 -6
- package/src/js/plugins/grideditor.gutters.js +20 -15
- package/src/js/plugins/grideditor.order.js +28 -25
- package/src/js/plugins/grideditor.popup.js +63 -51
- package/src/js/plugins/grideditor.sections.js +39 -32
- package/src/js/plugins/grideditor.spacing.js +42 -45
- package/src/js/plugins/grideditor.summernote.js +112 -76
- package/src/js/plugins/grideditor.tabs.js +65 -57
- package/src/js/plugins/grideditor.textalign.js +4 -6
- package/src/js/plugins/grideditor.tinymce.js +148 -140
- package/src/js/plugins/grideditor.visibility.js +24 -25
- package/src/js/register.js +18 -0
- package/src/js/text/grideditor.text.js +77 -56
- package/types/grideditor.d.ts +335 -0
- package/dist/jquery.grideditor.bundle.min.js +0 -10
- package/dist/jquery.grideditor.js +0 -4927
- package/dist/jquery.grideditor.min.js +0 -2
- package/dist/jquery.grideditor.min.js.map +0 -1
|
@@ -13,23 +13,31 @@
|
|
|
13
13
|
* back, and making the host's plain content a text through the core's
|
|
14
14
|
* `textTypes` hook.
|
|
15
15
|
*
|
|
16
|
-
* Each editor registers under
|
|
16
|
+
* Each editor registers under GridEditor.texts, which is this file's own
|
|
17
17
|
* registry and not a contract: an editor of a host's own is a feature plugin
|
|
18
18
|
* of its own, as example/custom_editor.html shows.
|
|
19
19
|
*/
|
|
20
|
-
|
|
20
|
+
import { GridEditor } from '../grideditor.js';
|
|
21
|
+
import * as dom from '../dom.js';
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
// However many editors a page loads, each with a copy of this file in its
|
|
24
|
+
// classic script: the first one installs it
|
|
25
|
+
if (!GridEditor.features.text) {
|
|
23
26
|
|
|
24
|
-
|
|
27
|
+
Object.assign(GridEditor.locales.en, {
|
|
25
28
|
'text.add': 'Text',
|
|
26
29
|
'text.add_type': 'Text ({editor})',
|
|
27
30
|
'panel.editor': 'Editor',
|
|
28
31
|
'panel.kind_text': 'Text',
|
|
29
32
|
});
|
|
30
33
|
|
|
31
|
-
/**
|
|
32
|
-
|
|
34
|
+
/**
|
|
35
|
+
* What a content area's attributes were before its editor opened, and
|
|
36
|
+
* once it had: the two readings closeText plays the host's changes
|
|
37
|
+
* back from. Shared by every editor on the page, like the nodes.
|
|
38
|
+
*/
|
|
39
|
+
var readBefore = new WeakMap();
|
|
40
|
+
var readReady = new WeakMap();
|
|
33
41
|
|
|
34
42
|
/** What a text editor puts on a content area while it is open, whenever it likes. */
|
|
35
43
|
var EDITOR_CLASS = /^(mce-|cke|note-)|^(active|ge-rte-active)$/;
|
|
@@ -37,7 +45,7 @@
|
|
|
37
45
|
|
|
38
46
|
function attributesOf(element) {
|
|
39
47
|
var found = {};
|
|
40
|
-
|
|
48
|
+
Array.prototype.slice.call(element.attributes).forEach(function(attribute) {
|
|
41
49
|
found[attribute.name] = attribute.value;
|
|
42
50
|
});
|
|
43
51
|
return found;
|
|
@@ -51,9 +59,9 @@
|
|
|
51
59
|
|
|
52
60
|
/** The host's markup, with what changed from `ready` to `open` played back onto it. */
|
|
53
61
|
function restoreAttributes(block, before, ready, open) {
|
|
54
|
-
var result =
|
|
62
|
+
var result = Object.assign({}, before);
|
|
55
63
|
|
|
56
|
-
|
|
64
|
+
Object.keys(Object.assign({}, ready, open)).forEach(function(name) {
|
|
57
65
|
if (name === 'class' || EDITOR_ATTRIBUTE.test(name) || ready[name] === open[name]) { return; }
|
|
58
66
|
|
|
59
67
|
if (open[name] === undefined) {
|
|
@@ -76,8 +84,8 @@
|
|
|
76
84
|
// shuffle a node's attributes because it was edited
|
|
77
85
|
if (classes.length) { result['class'] = classes.join(' '); } else { delete result['class']; }
|
|
78
86
|
|
|
79
|
-
|
|
80
|
-
|
|
87
|
+
Object.keys(attributesOf(block)).forEach(function(name) { block.removeAttribute(name); });
|
|
88
|
+
Object.keys(result).forEach(function(name) { block.setAttribute(name, result[name]); });
|
|
81
89
|
}
|
|
82
90
|
|
|
83
91
|
function textFeature(ge) {
|
|
@@ -86,8 +94,8 @@
|
|
|
86
94
|
var TEXTS = {};
|
|
87
95
|
var warned = {};
|
|
88
96
|
|
|
89
|
-
|
|
90
|
-
TEXTS[type] =
|
|
97
|
+
Object.keys(GridEditor.texts).forEach(function(type) {
|
|
98
|
+
TEXTS[type] = GridEditor.texts[type](ge);
|
|
91
99
|
});
|
|
92
100
|
|
|
93
101
|
// Every editor loaded, in the order the page loaded them, unless the
|
|
@@ -110,11 +118,17 @@
|
|
|
110
118
|
/** A detached content area of `type`, holding `content` or the editor's initial content. */
|
|
111
119
|
function makeText(type, content) {
|
|
112
120
|
var text = TEXTS[type];
|
|
121
|
+
var block = dom.element('div', {
|
|
122
|
+
'class': 'ge-content ge-content-type-' + type,
|
|
123
|
+
'data-ge-content-type': type,
|
|
124
|
+
});
|
|
113
125
|
|
|
114
|
-
|
|
115
|
-
.
|
|
116
|
-
|
|
117
|
-
.
|
|
126
|
+
if (content && content.nodeType) {
|
|
127
|
+
block.appendChild(content);
|
|
128
|
+
} else {
|
|
129
|
+
dom.setHtml(block, content !== undefined ? content : (text && text.initialContent) || '');
|
|
130
|
+
}
|
|
131
|
+
return block;
|
|
118
132
|
}
|
|
119
133
|
|
|
120
134
|
/**
|
|
@@ -144,21 +158,20 @@
|
|
|
144
158
|
|
|
145
159
|
/** Whether a content area is a text of one of the editors loaded here. */
|
|
146
160
|
function isOurs(block) {
|
|
147
|
-
return !!TEXTS[block.
|
|
161
|
+
return !!TEXTS[block.getAttribute('data-ge-content-type')];
|
|
148
162
|
}
|
|
149
163
|
|
|
150
164
|
/** Open the editor on a text, once: until it is closed again. */
|
|
151
165
|
function startText(block) {
|
|
152
|
-
if (
|
|
166
|
+
if (dom.hasClass(block, 'ge-rte-active')) { return; }
|
|
153
167
|
|
|
154
168
|
// A content area nobody can see - a tab that is not the open one,
|
|
155
169
|
// a closed accordion item - has no geometry for an editor to lay
|
|
156
170
|
// its toolbar out against, and nothing anyone can type into
|
|
157
|
-
if (!
|
|
171
|
+
if (!dom.visible(block)) { return; }
|
|
158
172
|
|
|
159
|
-
// The attribute
|
|
160
|
-
|
|
161
|
-
var text = TEXTS[block.attr('data-ge-content-type')];
|
|
173
|
+
// The attribute: it is markup, and the drawer reads it the same way
|
|
174
|
+
var text = TEXTS[block.getAttribute('data-ge-content-type')];
|
|
162
175
|
if (!text) { return; }
|
|
163
176
|
|
|
164
177
|
// Not marked active, so the next click tries again: the library
|
|
@@ -168,13 +181,14 @@
|
|
|
168
181
|
return;
|
|
169
182
|
}
|
|
170
183
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
184
|
+
readBefore.set(block, attributesOf(block));
|
|
185
|
+
readReady.delete(block);
|
|
186
|
+
dom.addClass(block, 'ge-rte-active');
|
|
187
|
+
text.start([block]);
|
|
174
188
|
}
|
|
175
189
|
|
|
176
190
|
function onClick() {
|
|
177
|
-
startText(
|
|
191
|
+
startText(this);
|
|
178
192
|
}
|
|
179
193
|
|
|
180
194
|
/**
|
|
@@ -192,28 +206,30 @@
|
|
|
192
206
|
* is left out either way.
|
|
193
207
|
*/
|
|
194
208
|
function closeText(block) {
|
|
195
|
-
var text = TEXTS[block.
|
|
196
|
-
var before =
|
|
197
|
-
var open = before ? attributesOf(block
|
|
209
|
+
var text = TEXTS[block.getAttribute('data-ge-content-type')];
|
|
210
|
+
var before = readBefore.get(block);
|
|
211
|
+
var open = before ? attributesOf(block) : null;
|
|
198
212
|
|
|
199
213
|
// Every content area is told, as in 5.x: one whose editor never
|
|
200
214
|
// started is the plugin's to ignore
|
|
201
|
-
if (text) { text.stop(block); }
|
|
215
|
+
if (text) { text.stop([block]); }
|
|
202
216
|
|
|
203
217
|
// After stop, not before: an editor that restores the class
|
|
204
218
|
// attribute it snapshotted would put ge-rte-active back
|
|
205
|
-
|
|
219
|
+
dom.removeClass(block, 'ge-rte-active');
|
|
206
220
|
|
|
207
221
|
if (before) {
|
|
208
|
-
restoreAttributes(block, before,
|
|
209
|
-
|
|
222
|
+
restoreAttributes(block, before, readReady.get(block) || before, open);
|
|
223
|
+
readBefore.delete(block);
|
|
224
|
+
readReady.delete(block);
|
|
210
225
|
}
|
|
211
226
|
}
|
|
212
227
|
|
|
213
228
|
function createTextControls(textBlock) {
|
|
214
|
-
var block =
|
|
215
|
-
var type = block.
|
|
216
|
-
var drawer =
|
|
229
|
+
var block = dom.child(textBlock, '.ge-content');
|
|
230
|
+
var type = block.getAttribute('data-ge-content-type');
|
|
231
|
+
var drawer = dom.element('div', { 'class': 'ge-tools-drawer ge-text-drawer' });
|
|
232
|
+
textBlock.insertBefore(drawer, textBlock.firstChild);
|
|
217
233
|
|
|
218
234
|
ge.createMoveTool(drawer);
|
|
219
235
|
|
|
@@ -221,10 +237,11 @@
|
|
|
221
237
|
|
|
222
238
|
// Which editor edits it, first in its settings: something to
|
|
223
239
|
// know about it, not something to do with it
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
240
|
+
var general = dom.child(details, '.ge-details-general');
|
|
241
|
+
var editor = dom.element('div', { 'class': 'ge-field ge-text-editor' });
|
|
242
|
+
editor.appendChild(dom.element('span', { 'class': 'ge-field-label' }, ge.t('panel.editor')));
|
|
243
|
+
editor.appendChild(dom.element('span', { 'class': 'ge-field-value' }, textLabel(type)));
|
|
244
|
+
general.insertBefore(editor, general.firstChild);
|
|
228
245
|
|
|
229
246
|
settings.text_tools.forEach(function(hostTool) {
|
|
230
247
|
ge.createTool(drawer, hostTool.title || '', hostTool.className || '',
|
|
@@ -236,7 +253,7 @@
|
|
|
236
253
|
// Its editor lets go first: removed while open, it would
|
|
237
254
|
// be left behind, attached to nothing
|
|
238
255
|
closeText(block);
|
|
239
|
-
|
|
256
|
+
dom.slideUp(textBlock, function() {
|
|
240
257
|
textBlock.remove();
|
|
241
258
|
removed();
|
|
242
259
|
});
|
|
@@ -246,16 +263,18 @@
|
|
|
246
263
|
|
|
247
264
|
/** A drawer for each text of ours in a text block that has none yet. */
|
|
248
265
|
function markTexts() {
|
|
249
|
-
ge.canvas
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
266
|
+
dom.all(ge.canvas, '.ge-text-block').forEach(function(textBlock) {
|
|
267
|
+
if (dom.child(textBlock, '.ge-tools-drawer')) { return; }
|
|
268
|
+
|
|
269
|
+
var block = dom.child(textBlock, '.ge-content');
|
|
270
|
+
if (!block || !isOurs(block)) { return; }
|
|
253
271
|
|
|
254
272
|
createTextControls(textBlock);
|
|
255
273
|
});
|
|
256
274
|
}
|
|
257
275
|
|
|
258
276
|
var texts = offeredTexts();
|
|
277
|
+
var clicks = null; // The delegated click listener, while editing
|
|
259
278
|
|
|
260
279
|
return {
|
|
261
280
|
methods: {
|
|
@@ -281,8 +300,8 @@
|
|
|
281
300
|
available: text.available ? function() { return text.available(); } : null,
|
|
282
301
|
missingKey: text.missingKey,
|
|
283
302
|
edit: function(block) {
|
|
284
|
-
var textBlock = block.
|
|
285
|
-
if (textBlock
|
|
303
|
+
var textBlock = block.parentElement;
|
|
304
|
+
if (dom.hasClass(textBlock, 'ge-text-block') && !dom.child(textBlock, '.ge-tools-drawer')) {
|
|
286
305
|
createTextControls(textBlock);
|
|
287
306
|
}
|
|
288
307
|
|
|
@@ -310,26 +329,28 @@
|
|
|
310
329
|
onInit: function() {
|
|
311
330
|
markTexts();
|
|
312
331
|
|
|
313
|
-
ge.canvas.
|
|
332
|
+
if (clicks) { ge.canvas.removeEventListener('click', clicks); }
|
|
333
|
+
clicks = dom.delegate(ge.canvas, 'click', '.ge-content', onClick);
|
|
314
334
|
},
|
|
315
335
|
|
|
316
336
|
// While the drawers and the text blocks are still there, as the
|
|
317
337
|
// editors left them
|
|
318
338
|
onBeforeDeinit: function() {
|
|
319
|
-
ge.canvas
|
|
320
|
-
if (isOurs(
|
|
339
|
+
dom.all(ge.canvas, '.ge-content').forEach(function(block) {
|
|
340
|
+
if (isOurs(block)) { closeText(block); }
|
|
321
341
|
});
|
|
322
342
|
},
|
|
323
343
|
|
|
324
344
|
onDeinit: function() {
|
|
325
|
-
ge.canvas.
|
|
345
|
+
if (clicks) { ge.canvas.removeEventListener('click', clicks); }
|
|
346
|
+
clicks = null;
|
|
326
347
|
},
|
|
327
348
|
|
|
328
349
|
// The first time only: an undo says ready again, and by then the
|
|
329
350
|
// host may have changed the content area itself
|
|
330
351
|
onContentReady: function(area) {
|
|
331
|
-
if (
|
|
332
|
-
|
|
352
|
+
if (readBefore.has(area) && !readReady.has(area)) {
|
|
353
|
+
readReady.set(area, attributesOf(area));
|
|
333
354
|
}
|
|
334
355
|
},
|
|
335
356
|
};
|
|
@@ -338,6 +359,6 @@
|
|
|
338
359
|
// Whatever the plugins setting says: content_types chooses the editors
|
|
339
360
|
textFeature.always = true;
|
|
340
361
|
|
|
341
|
-
|
|
362
|
+
GridEditor.features.text = textFeature;
|
|
342
363
|
|
|
343
|
-
}
|
|
364
|
+
}
|
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for grid-editor's public API: the GridEditor class, its methods, its
|
|
3
|
+
* settings, and its events and their payloads.
|
|
4
|
+
*
|
|
5
|
+
* The plugin contract - the handle a plugin's factory gets - is not typed
|
|
6
|
+
* here; docs/plugins.md describes it. A plugin's factory is typed loosely as
|
|
7
|
+
* a function of that handle.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** A breakpoint key. */
|
|
11
|
+
export type Breakpoint = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl';
|
|
12
|
+
|
|
13
|
+
/** A view: a breakpoint, or every one at once. */
|
|
14
|
+
export type View = Breakpoint | 'all';
|
|
15
|
+
|
|
16
|
+
/** A column's size: units, Bootstrap's `col` (`'equal'`) or `col-auto` (`'auto'`). */
|
|
17
|
+
export type ColumnSize = number | 'equal' | 'auto';
|
|
18
|
+
|
|
19
|
+
/** A row's columns-per-row layout: row-cols per breakpoint, and how many columns. */
|
|
20
|
+
export interface RowColsLayout {
|
|
21
|
+
row_cols: Partial<Record<Breakpoint, number | 'auto'>>;
|
|
22
|
+
columns?: number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** What a row is made of: sizes, or a columns-per-row layout. */
|
|
26
|
+
export type RowLayout = ColumnSize[] | RowColsLayout;
|
|
27
|
+
|
|
28
|
+
/** An element, or a selector for the first element it matches. */
|
|
29
|
+
export type Target = Element | string;
|
|
30
|
+
|
|
31
|
+
/** Where a created node goes. The first one given wins; none leaves it detached. */
|
|
32
|
+
export interface Placement {
|
|
33
|
+
appendTo?: Target;
|
|
34
|
+
prependTo?: Target;
|
|
35
|
+
insertAfter?: Target;
|
|
36
|
+
insertBefore?: Target;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** A host tool in a drawer: row_tools, col_tools and the rest. */
|
|
40
|
+
export interface HostTool {
|
|
41
|
+
title?: string;
|
|
42
|
+
className?: string;
|
|
43
|
+
iconClass?: string;
|
|
44
|
+
/** A click handler, or handlers by event name. `this` is the tool. */
|
|
45
|
+
on?: ((this: HTMLElement, event: Event) => void) | Record<string, (this: HTMLElement, event: Event) => void>;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** A preset class toggle on a settings panel. */
|
|
49
|
+
export interface PresetClass {
|
|
50
|
+
label: string;
|
|
51
|
+
cssClass: string;
|
|
52
|
+
title?: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** A content filter: run on init and deinit with the canvas. A string names a function on window. */
|
|
56
|
+
export type CustomFilter = ((canvas: HTMLElement, isInit: boolean) => void) | string;
|
|
57
|
+
|
|
58
|
+
/** The settings. Every one is optional. */
|
|
59
|
+
export interface GridEditorOptions {
|
|
60
|
+
new_row_layouts?: RowLayout[];
|
|
61
|
+
row_classes?: PresetClass[];
|
|
62
|
+
col_classes?: PresetClass[];
|
|
63
|
+
element_classes?: PresetClass[];
|
|
64
|
+
container_classes?: PresetClass[];
|
|
65
|
+
pane_classes?: PresetClass[];
|
|
66
|
+
text_classes?: PresetClass[];
|
|
67
|
+
row_tools?: HostTool[];
|
|
68
|
+
col_tools?: HostTool[];
|
|
69
|
+
element_tools?: HostTool[];
|
|
70
|
+
container_tools?: HostTool[];
|
|
71
|
+
tab_tools?: HostTool[];
|
|
72
|
+
accordion_tools?: HostTool[];
|
|
73
|
+
text_tools?: HostTool[];
|
|
74
|
+
drag_handle?: 'tool' | 'drawer';
|
|
75
|
+
toolbar_drag?: 'auto' | boolean;
|
|
76
|
+
/** The plugins to use, of any kind; null is every one loaded. */
|
|
77
|
+
plugins?: string[] | null;
|
|
78
|
+
/** The text editors offered, in order. */
|
|
79
|
+
content_types?: string[];
|
|
80
|
+
row_cols?: boolean;
|
|
81
|
+
utilities?: Record<string, unknown>;
|
|
82
|
+
elements?: { enabled?: boolean | 'auto'; selector?: string; auto?: boolean };
|
|
83
|
+
custom_filter?: CustomFilter | CustomFilter[] | '';
|
|
84
|
+
valid_col_sizes?: ColumnSize[];
|
|
85
|
+
valid_col_offsets?: number[];
|
|
86
|
+
add_column?: { size?: ColumnSize | null; picker?: boolean; delay?: number };
|
|
87
|
+
layout_modes?: View[];
|
|
88
|
+
default_view?: View;
|
|
89
|
+
resize?: { enabled?: boolean; handles?: string; balance?: 'next' | false };
|
|
90
|
+
/** A textarea whose html the canvas starts with. */
|
|
91
|
+
source_textarea?: Target | '';
|
|
92
|
+
edit_source?: boolean;
|
|
93
|
+
locale?: string;
|
|
94
|
+
locale_strings?: Record<string, string>;
|
|
95
|
+
callbacks?: Partial<GridEditorCallbacks>;
|
|
96
|
+
confirm_delete?: boolean;
|
|
97
|
+
settings_panel?: 'offcanvas' | 'popover' | 'modal' | 'inline';
|
|
98
|
+
drag?: { delay?: number; touch_delay?: number; threshold?: number; animation?: number; scroll?: boolean };
|
|
99
|
+
tinymce?: { config?: Record<string, unknown> };
|
|
100
|
+
ckeditor?: { config?: Record<string, unknown> };
|
|
101
|
+
summernote?: { config?: Record<string, unknown> };
|
|
102
|
+
[plugin: string]: unknown;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** Where a node was, or went: its parent and its index among the blocks there. */
|
|
106
|
+
export interface Position {
|
|
107
|
+
parent: HTMLElement;
|
|
108
|
+
index: number;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** What a breakpoint said before the all view's write took it off. */
|
|
112
|
+
export interface Cleared {
|
|
113
|
+
breakpoint: Breakpoint;
|
|
114
|
+
value: string | number;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** What every notification carries. */
|
|
118
|
+
export interface Payload {
|
|
119
|
+
/** What the node is: row, column, text, plain, element, tab, accordion-item, a container's type… */
|
|
120
|
+
kind: string;
|
|
121
|
+
node: HTMLElement;
|
|
122
|
+
/** Where the node is going, or coming from on a delete; null while it is detached. */
|
|
123
|
+
parent: HTMLElement | null;
|
|
124
|
+
canvas: HTMLElement;
|
|
125
|
+
breakpoint: View;
|
|
126
|
+
source: 'api' | 'tool' | 'dragdrop' | 'paste' | 'panel' | string;
|
|
127
|
+
/** A pane inside a container. */
|
|
128
|
+
container?: HTMLElement;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export interface MovePayload extends Payload {
|
|
132
|
+
from: Position;
|
|
133
|
+
to?: Position;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export interface ResizePayload extends Payload {
|
|
137
|
+
from: ColumnSize | null;
|
|
138
|
+
to: ColumnSize | null;
|
|
139
|
+
cleared?: Cleared[];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export interface IndentPayload extends Payload {
|
|
143
|
+
from: number;
|
|
144
|
+
to: number;
|
|
145
|
+
cleared?: Cleared[];
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export interface UtilityPayload extends Payload {
|
|
149
|
+
family: string;
|
|
150
|
+
from: string | null;
|
|
151
|
+
to: string | null;
|
|
152
|
+
tiers: Breakpoint[];
|
|
153
|
+
cleared: Cleared[];
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export interface ConvertPayload extends Payload {
|
|
157
|
+
from: 'plain';
|
|
158
|
+
to: string;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export interface EditHtmlPayload extends Omit<Payload, 'node'> {
|
|
162
|
+
node: HTMLElement | null;
|
|
163
|
+
/** Every element written, which may be several. */
|
|
164
|
+
nodes?: HTMLElement[];
|
|
165
|
+
from: string;
|
|
166
|
+
to: string;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export interface PopupOrphanPayload extends Payload {
|
|
170
|
+
missing: string;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export interface ViewChangePayload {
|
|
174
|
+
canvas: HTMLElement;
|
|
175
|
+
breakpoint: View;
|
|
176
|
+
from: View;
|
|
177
|
+
to: View;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/** The events, by name, with their payloads. Adding fires a specific name and the generic one. */
|
|
181
|
+
export interface GridEditorEventMap {
|
|
182
|
+
'grideditor:before-add': Payload;
|
|
183
|
+
'grideditor:after-add': Payload;
|
|
184
|
+
'grideditor:before-add-row': Payload;
|
|
185
|
+
'grideditor:after-add-row': Payload;
|
|
186
|
+
'grideditor:before-add-column': Payload;
|
|
187
|
+
'grideditor:after-add-column': Payload;
|
|
188
|
+
'grideditor:before-add-text': Payload;
|
|
189
|
+
'grideditor:after-add-text': Payload;
|
|
190
|
+
'grideditor:before-add-element': Payload;
|
|
191
|
+
'grideditor:after-add-element': Payload;
|
|
192
|
+
'grideditor:before-add-container': Payload;
|
|
193
|
+
'grideditor:after-add-container': Payload;
|
|
194
|
+
'grideditor:before-add-tab': Payload;
|
|
195
|
+
'grideditor:after-add-tab': Payload;
|
|
196
|
+
'grideditor:before-add-accordion-item': Payload;
|
|
197
|
+
'grideditor:after-add-accordion-item': Payload;
|
|
198
|
+
'grideditor:before-add-section': Payload;
|
|
199
|
+
'grideditor:after-add-section': Payload;
|
|
200
|
+
'grideditor:before-delete': Payload;
|
|
201
|
+
'grideditor:after-delete': Payload;
|
|
202
|
+
'grideditor:before-move': MovePayload;
|
|
203
|
+
'grideditor:after-move': MovePayload;
|
|
204
|
+
'grideditor:before-resize': ResizePayload;
|
|
205
|
+
'grideditor:after-resize': ResizePayload;
|
|
206
|
+
'grideditor:before-indent': IndentPayload;
|
|
207
|
+
'grideditor:after-indent': IndentPayload;
|
|
208
|
+
'grideditor:before-utility': UtilityPayload;
|
|
209
|
+
'grideditor:after-utility': UtilityPayload;
|
|
210
|
+
'grideditor:before-convert': ConvertPayload;
|
|
211
|
+
'grideditor:after-convert': ConvertPayload;
|
|
212
|
+
'grideditor:before-edit-html': EditHtmlPayload;
|
|
213
|
+
'grideditor:after-edit-html': EditHtmlPayload;
|
|
214
|
+
'grideditor:after-copy': Payload;
|
|
215
|
+
'grideditor:popup-orphan': PopupOrphanPayload;
|
|
216
|
+
'grideditor:view-change': ViewChangePayload;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/** An event the editor dispatches on its canvas: a CustomEvent whose detail is the payload. */
|
|
220
|
+
export type GridEditorEvent<K extends keyof GridEditorEventMap> = CustomEvent<GridEditorEventMap[K]>;
|
|
221
|
+
|
|
222
|
+
/** 'grideditor:before-add-row' is the callback before_add_row. */
|
|
223
|
+
type CallbackName<K> = K extends `grideditor:${infer Name}` ? Snake<Name> : never;
|
|
224
|
+
type Snake<S extends string> = S extends `${infer Head}-${infer Tail}` ? `${Head}_${Snake<Tail>}` : S;
|
|
225
|
+
|
|
226
|
+
/** The callbacks setting: the events by another route. Returning false cancels a before-*. */
|
|
227
|
+
export type GridEditorCallbacks = {
|
|
228
|
+
[K in keyof GridEditorEventMap as CallbackName<K>]: (payload: GridEditorEventMap[K]) => boolean | void;
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
/** A plugin's factory: called once per editor with the handle in docs/plugins.md. */
|
|
232
|
+
export type PluginFactory = ((ge: any) => Record<string, unknown>) & { always?: boolean };
|
|
233
|
+
|
|
234
|
+
export interface CreateColumnOptions extends Placement {
|
|
235
|
+
offset?: number;
|
|
236
|
+
/** Html, or a node: a text of the first editor offered, or plain content with none. */
|
|
237
|
+
content?: string | Node;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
export interface CreateTextOptions extends Placement {
|
|
241
|
+
content?: string | Node;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export interface CreateElementOptions extends Placement {
|
|
245
|
+
type?: string;
|
|
246
|
+
label?: string;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export interface CreateSectionOptions extends Placement {
|
|
250
|
+
width?: 'fixed' | 'fluid' | Breakpoint;
|
|
251
|
+
rows?: RowLayout[];
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export interface PaneOptions {
|
|
255
|
+
label?: string;
|
|
256
|
+
[option: string]: unknown;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/** An editor on a canvas element. */
|
|
260
|
+
export declare class GridEditor {
|
|
261
|
+
/**
|
|
262
|
+
* An editor on `target`. An element carries one at most: asked for a
|
|
263
|
+
* second, this gives back the first, with its options, and warns once.
|
|
264
|
+
* Throws a TypeError when `target` is neither an element nor a selector
|
|
265
|
+
* that matches one.
|
|
266
|
+
*/
|
|
267
|
+
constructor(target: Target, options?: GridEditorOptions);
|
|
268
|
+
|
|
269
|
+
/** The same as `new GridEditor(target, options)`. */
|
|
270
|
+
static create(target: Target, options?: GridEditorOptions): GridEditor;
|
|
271
|
+
/** The editor on `target`, or null. */
|
|
272
|
+
static get(target: Target | null | undefined): GridEditor | null;
|
|
273
|
+
|
|
274
|
+
static containers: Record<string, PluginFactory>;
|
|
275
|
+
static features: Record<string, PluginFactory>;
|
|
276
|
+
static utilities: Record<string, PluginFactory>;
|
|
277
|
+
static texts: Record<string, PluginFactory>;
|
|
278
|
+
static locales: Record<string, Record<string, string>>;
|
|
279
|
+
/** A string from the locale `settings.locale` names, English when it has none. */
|
|
280
|
+
static t(settings: { locale?: string; locale_strings?: Record<string, string> }, key: string, params?: Record<string, string | number>): string;
|
|
281
|
+
/** SortableJS, for a page that imports it rather than loading it as window.Sortable. */
|
|
282
|
+
static Sortable: unknown;
|
|
283
|
+
/** Bootstrap's javascript (only its Modal is used), for a page with no window.bootstrap. */
|
|
284
|
+
static bootstrap: { Modal?: unknown } | null;
|
|
285
|
+
static version: string;
|
|
286
|
+
|
|
287
|
+
/** The canvas element. */
|
|
288
|
+
readonly canvas: HTMLElement;
|
|
289
|
+
/** A read-only copy of the settings the editor runs with. */
|
|
290
|
+
readonly settings: Readonly<GridEditorOptions>;
|
|
291
|
+
|
|
292
|
+
/** The html to save: no drawers, no editor classes, no inline styles. */
|
|
293
|
+
getHtml(): string;
|
|
294
|
+
/** getHtml without grid-editor's marking, for publishing. It cannot be edited again as it was. */
|
|
295
|
+
getPlainHtml(): string;
|
|
296
|
+
/** Run the editing pass over the canvas again, after markup was put in. */
|
|
297
|
+
init(): this;
|
|
298
|
+
/** Take the editing furniture off, leaving the markup. */
|
|
299
|
+
deinit(): this;
|
|
300
|
+
/** deinit(), then init(). */
|
|
301
|
+
reset(): this;
|
|
302
|
+
/** Take the editor off: the markup stays, everything else goes. */
|
|
303
|
+
destroy(): this;
|
|
304
|
+
changeView(view: View): this;
|
|
305
|
+
getView(): View;
|
|
306
|
+
setLocale(code: string): this;
|
|
307
|
+
createRow(layout?: RowLayout, options?: Placement): HTMLElement | null;
|
|
308
|
+
createColumn(size?: ColumnSize | null, options?: CreateColumnOptions): HTMLElement | null;
|
|
309
|
+
createText(type?: string, options?: CreateTextOptions): HTMLElement | null;
|
|
310
|
+
createText(options: CreateTextOptions): HTMLElement | null;
|
|
311
|
+
createElement(content: string | Node | ArrayLike<Node>, options?: CreateElementOptions): HTMLElement | null;
|
|
312
|
+
createSection(options?: CreateSectionOptions): HTMLElement | null;
|
|
313
|
+
createContainer(type: string, options?: Placement & Record<string, unknown>): HTMLElement | null;
|
|
314
|
+
addTab(container: Target, options?: PaneOptions): HTMLElement | null;
|
|
315
|
+
addAccordionItem(container: Target, options?: PaneOptions): HTMLElement | null;
|
|
316
|
+
/** A utility's value on a node in a view (the current one by default), or null. */
|
|
317
|
+
getUtility(node: Target, family: string, view?: View): string | null;
|
|
318
|
+
/** Write one through the events; null is inherit. False when canceled or nothing changed. */
|
|
319
|
+
setUtility(node: Target, family: string, value: string | number | null, view?: View): boolean;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
export default GridEditor;
|
|
323
|
+
|
|
324
|
+
declare global {
|
|
325
|
+
interface Window {
|
|
326
|
+
GridEditor: typeof GridEditor;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
interface HTMLElementEventMap extends GridEditorEventMap_ {}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/** The events on any element, so canvas.addEventListener('grideditor:...') is typed. */
|
|
333
|
+
type GridEditorEventMap_ = {
|
|
334
|
+
[K in keyof GridEditorEventMap]: CustomEvent<GridEditorEventMap[K]>;
|
|
335
|
+
};
|