@themarioga/grid-editor 8.4.0 → 8.5.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/CHANGELOG.md +18 -0
- package/README.md +27 -1
- package/dist/grideditor.bundle.min.js +3 -3
- package/dist/grideditor.d.ts +17 -1
- package/dist/grideditor.esm.js +13 -3
- package/dist/grideditor.js +13 -3
- package/dist/grideditor.min.js +2 -2
- package/dist/grideditor.min.js.map +2 -2
- package/dist/locales/grideditor.es.esm.js +1 -0
- package/dist/locales/grideditor.es.js +1 -0
- package/dist/locales/grideditor.es.min.js +1 -1
- package/dist/locales/grideditor.es.min.js.map +2 -2
- package/dist/plugins/grideditor.ckeditor.esm.js +1 -1
- package/dist/plugins/grideditor.ckeditor.js +1 -1
- package/dist/plugins/grideditor.ckeditor.min.js +1 -1
- package/dist/plugins/grideditor.ckeditor.min.js.map +2 -2
- package/dist/plugins/grideditor.elements.esm.js +72 -1
- package/dist/plugins/grideditor.elements.js +72 -1
- package/dist/plugins/grideditor.elements.min.js +1 -1
- package/dist/plugins/grideditor.elements.min.js.map +3 -3
- package/dist/plugins/grideditor.summernote.esm.js +1 -1
- package/dist/plugins/grideditor.summernote.js +1 -1
- package/dist/plugins/grideditor.summernote.min.js +1 -1
- package/dist/plugins/grideditor.summernote.min.js.map +2 -2
- package/dist/plugins/grideditor.tinymce.esm.js +1 -1
- package/dist/plugins/grideditor.tinymce.js +1 -1
- package/dist/plugins/grideditor.tinymce.min.js +1 -1
- package/dist/plugins/grideditor.tinymce.min.js.map +2 -2
- package/docs/locale-keys.md +2 -1
- package/docs/plugins.md +6 -5
- package/package.json +1 -1
- package/src/js/grideditor.js +6 -0
- package/src/js/locales/grideditor.es.js +1 -0
- package/src/js/plugins/grideditor.elements.js +94 -1
- package/src/js/text/grideditor.text.js +1 -1
- package/types/grideditor.d.ts +17 -1
package/package.json
CHANGED
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"comment": "A scoped package publishes restricted unless it is told otherwise.",
|
|
34
34
|
"access": "public"
|
|
35
35
|
},
|
|
36
|
-
"version": "8.
|
|
36
|
+
"version": "8.5.0",
|
|
37
37
|
"main": "dist/grideditor.js",
|
|
38
38
|
"module": "dist/grideditor.esm.js",
|
|
39
39
|
"types": "dist/grideditor.d.ts",
|
package/src/js/grideditor.js
CHANGED
|
@@ -142,6 +142,7 @@ var NESTED_SETTINGS = {
|
|
|
142
142
|
enabled: 'auto', // 'auto' turns them on when the page has any
|
|
143
143
|
selector: '[data-ge-element]', // What the host marks an element with
|
|
144
144
|
auto: false, // Treat every child of a content area as an element
|
|
145
|
+
types: [], // The elements the toolbar offers: { type, html, label | labelKey, iconClass, group }
|
|
145
146
|
},
|
|
146
147
|
resize: {
|
|
147
148
|
enabled: true, // The handle on the column's edge
|
|
@@ -1239,6 +1240,7 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
1239
1240
|
var CORE_GROUPS = [
|
|
1240
1241
|
{ name: 'rows', labelKey: 'group.rows' },
|
|
1241
1242
|
{ name: 'content', labelKey: 'group.content' },
|
|
1243
|
+
{ name: 'elements', labelKey: 'group.elements' },
|
|
1242
1244
|
];
|
|
1243
1245
|
|
|
1244
1246
|
/** A plugin's category, when it names one. */
|
|
@@ -1452,6 +1454,8 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
1452
1454
|
if (activeTarget) { addToTarget(button, item.source || 'tool'); return; }
|
|
1453
1455
|
|
|
1454
1456
|
var made = item.create();
|
|
1457
|
+
// A plugin that could not make one says so with null
|
|
1458
|
+
if (!made) { return; }
|
|
1455
1459
|
|
|
1456
1460
|
// One that belongs in a column brings a row and a column
|
|
1457
1461
|
// of its own, the way a container does
|
|
@@ -1611,6 +1615,7 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
1611
1615
|
function insertFeatureFromToolbar(button, where, source) {
|
|
1612
1616
|
var item = FEATURES[button.getAttribute('data-ge-feature')].toolbar[parseInt(button.getAttribute('data-ge-item'), 10)];
|
|
1613
1617
|
var made = item.create();
|
|
1618
|
+
if (!made) { return null; }
|
|
1614
1619
|
var placed = made;
|
|
1615
1620
|
|
|
1616
1621
|
if (item.inColumn) {
|
|
@@ -5770,6 +5775,7 @@ GridEditor.locales = {
|
|
|
5770
5775
|
'tool.more': 'More',
|
|
5771
5776
|
'group.rows': 'Rows',
|
|
5772
5777
|
'group.content': 'Content',
|
|
5778
|
+
'group.elements': 'Elements',
|
|
5773
5779
|
'group.select': 'Add',
|
|
5774
5780
|
'panel.title': '{kind} settings',
|
|
5775
5781
|
'panel.close': 'Close',
|
|
@@ -28,11 +28,95 @@ var NOT_ELEMENTS = '.row, .ge-content, .ge-text-block, [data-ge-container], .ge-
|
|
|
28
28
|
GridEditor.features.elements = function(ge) {
|
|
29
29
|
|
|
30
30
|
var warnedIntoText = false;
|
|
31
|
+
var types = validTypes();
|
|
31
32
|
|
|
32
33
|
function elementsEnabled() {
|
|
33
34
|
if (ge.settings.elements.enabled !== 'auto') { return !!ge.settings.elements.enabled; }
|
|
34
35
|
|
|
35
|
-
|
|
36
|
+
// A host that offers elements on the toolbar uses them, even on a
|
|
37
|
+
// page that has none yet
|
|
38
|
+
return ge.settings.elements.auto || types.length > 0 ||
|
|
39
|
+
!!ge.canvas.querySelector(ge.settings.elements.selector);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** The elements.types the toolbar can offer. One that can't be made is left out, with a word to the host. */
|
|
43
|
+
function validTypes() {
|
|
44
|
+
return (ge.settings.elements.types || []).filter(function(type, index) {
|
|
45
|
+
var named = type && typeof type.type === 'string' && type.type.trim() !== '';
|
|
46
|
+
var html = type && (typeof type.html === 'function' || (typeof type.html === 'string' && type.html.trim() !== ''));
|
|
47
|
+
|
|
48
|
+
if (!named || !html) {
|
|
49
|
+
ge.warn('elements.types[' + index + ']: a type needs a type name and its html, as a string or a ' +
|
|
50
|
+
'function; it is left off the toolbar.');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return named && html;
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** A type's toolbar button. */
|
|
58
|
+
function typeItem(type) {
|
|
59
|
+
var mismatched = false;
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
// Asked again whenever the toolbar is built, so setLocale
|
|
63
|
+
// translates a labelKey
|
|
64
|
+
label: function() { return labelOf(type); },
|
|
65
|
+
iconClass: type.iconClass,
|
|
66
|
+
group: type.group || 'elements',
|
|
67
|
+
kind: 'element',
|
|
68
|
+
inColumn: true,
|
|
69
|
+
create: function() {
|
|
70
|
+
var element = makeElement(type);
|
|
71
|
+
|
|
72
|
+
if (element && !mismatched && !ge.settings.elements.auto && !element.matches(ge.settings.elements.selector)) {
|
|
73
|
+
mismatched = true;
|
|
74
|
+
ge.warn('elements.types "' + type.type + '": what it makes does not match elements.selector "' +
|
|
75
|
+
ge.settings.elements.selector + '", so it will not be an element once the editor looks again.');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return element;
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function labelOf(type) {
|
|
84
|
+
if (type.labelKey) { return ge.t(type.labelKey); }
|
|
85
|
+
|
|
86
|
+
return type.label || type.type;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* What a type's button makes: the root of its html, marked as the host
|
|
91
|
+
* marks its own, or a div around it when it has no single root. Null,
|
|
92
|
+
* with a word to the host, when there is nothing to make.
|
|
93
|
+
*/
|
|
94
|
+
function makeElement(type) {
|
|
95
|
+
var made;
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
made = typeof type.html === 'function' ? type.html() : type.html;
|
|
99
|
+
} catch (error) {
|
|
100
|
+
ge.warn('elements.types "' + type.type + '": its html function threw (' + error.message + '); nothing was added.');
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
var nodes = typeof made === 'string' ? dom.parse(made) : (made && made.nodeType ? [made] : []);
|
|
105
|
+
// Whitespace between tags is not content
|
|
106
|
+
nodes = nodes.filter(function(node) { return node.nodeType !== 3 || node.textContent.trim() !== ''; });
|
|
107
|
+
|
|
108
|
+
if (!nodes.length) {
|
|
109
|
+
ge.warn('elements.types "' + type.type + '": its html came out empty; nothing was added.');
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
var element = nodes.length === 1 && nodes[0].nodeType === 1 ? nodes[0] : dom.element('div');
|
|
114
|
+
if (element !== nodes[0] || nodes.length > 1) { fill(element, nodes); }
|
|
115
|
+
|
|
116
|
+
element.setAttribute('data-ge-element', type.type);
|
|
117
|
+
if (!element.hasAttribute('data-ge-label')) { element.setAttribute('data-ge-label', labelOf(type)); }
|
|
118
|
+
|
|
119
|
+
return element;
|
|
36
120
|
}
|
|
37
121
|
|
|
38
122
|
/** Whether a child of a column is an element. */
|
|
@@ -121,6 +205,11 @@ GridEditor.features.elements = function(ge) {
|
|
|
121
205
|
return placed;
|
|
122
206
|
}
|
|
123
207
|
|
|
208
|
+
/** enabled: false takes the toolbar's element buttons away too. */
|
|
209
|
+
function elementsOff() {
|
|
210
|
+
return ge.settings.elements.enabled === false;
|
|
211
|
+
}
|
|
212
|
+
|
|
124
213
|
/** A place a caller named: an element, or the first one a selector matches. */
|
|
125
214
|
function nodeFrom(node) {
|
|
126
215
|
if (typeof node === 'string') { return document.querySelector(node); }
|
|
@@ -163,6 +252,10 @@ GridEditor.features.elements = function(ge) {
|
|
|
163
252
|
createElement: apiCreateElement,
|
|
164
253
|
},
|
|
165
254
|
|
|
255
|
+
// A button for each type the host offers, in the elements category
|
|
256
|
+
// unless the type names another
|
|
257
|
+
toolbar: elementsOff() ? [] : types.map(typeItem),
|
|
258
|
+
|
|
166
259
|
/** A node this plugin marked is an element, whatever else it is. */
|
|
167
260
|
kindOf: function(node) {
|
|
168
261
|
return dom.hasClass(node, 'ge-element') ? 'element' : null;
|
package/types/grideditor.d.ts
CHANGED
|
@@ -125,7 +125,7 @@ export interface GridEditorOptions {
|
|
|
125
125
|
inline_style?: InlineStyleOptions;
|
|
126
126
|
/** The tabs plugin: the variant of the tabs containers made new. */
|
|
127
127
|
tabs?: TabsOptions;
|
|
128
|
-
elements?: { enabled?: boolean | 'auto'; selector?: string; auto?: boolean };
|
|
128
|
+
elements?: { enabled?: boolean | 'auto'; selector?: string; auto?: boolean; types?: ElementType[] };
|
|
129
129
|
custom_filter?: CustomFilter | CustomFilter[] | '';
|
|
130
130
|
valid_col_sizes?: ColumnSize[];
|
|
131
131
|
valid_col_offsets?: number[];
|
|
@@ -286,6 +286,22 @@ export type GridEditorCallbacks = {
|
|
|
286
286
|
};
|
|
287
287
|
|
|
288
288
|
/** A plugin's factory: called once per editor with the handle in docs/plugins.md. */
|
|
289
|
+
/** An element the toolbar offers, from elements.types. */
|
|
290
|
+
export interface ElementType {
|
|
291
|
+
/** What it is: its data-ge-element. */
|
|
292
|
+
type: string;
|
|
293
|
+
/** Its markup: html, or a function called for each one made that returns html or a node. */
|
|
294
|
+
html: string | (() => string | Node);
|
|
295
|
+
/** Its button's label, as it is. */
|
|
296
|
+
label?: string;
|
|
297
|
+
/** Its button's label, a locale key: wins over label, and follows setLocale. */
|
|
298
|
+
labelKey?: string;
|
|
299
|
+
/** The button shows this icon alone, with the label as its title. */
|
|
300
|
+
iconClass?: string;
|
|
301
|
+
/** Its toolbar_groups category. Default 'elements'. */
|
|
302
|
+
group?: string;
|
|
303
|
+
}
|
|
304
|
+
|
|
289
305
|
export type PluginFactory = ((ge: any) => Record<string, unknown>) & { always?: boolean };
|
|
290
306
|
|
|
291
307
|
export interface CreateColumnOptions extends Placement {
|