@themarioga/grid-editor 7.1.0 → 7.3.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.
Files changed (76) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/README.md +117 -19
  3. package/UPGRADING.md +72 -0
  4. package/dist/grideditor.bundle.min.js +3 -3
  5. package/dist/grideditor.css +102 -0
  6. package/dist/grideditor.d.ts +18 -0
  7. package/dist/grideditor.esm.js +292 -32
  8. package/dist/grideditor.js +292 -32
  9. package/dist/grideditor.min.css +1 -1
  10. package/dist/grideditor.min.css.map +1 -1
  11. package/dist/grideditor.min.js +2 -2
  12. package/dist/grideditor.min.js.map +3 -3
  13. package/dist/locales/grideditor.es.esm.js +70 -1
  14. package/dist/locales/grideditor.es.js +70 -1
  15. package/dist/locales/grideditor.es.min.js +1 -1
  16. package/dist/locales/grideditor.es.min.js.map +2 -2
  17. package/dist/plugins/grideditor.ckeditor.esm.js +123 -48
  18. package/dist/plugins/grideditor.ckeditor.js +123 -48
  19. package/dist/plugins/grideditor.ckeditor.min.js +1 -1
  20. package/dist/plugins/grideditor.ckeditor.min.js.map +3 -3
  21. package/dist/plugins/grideditor.float.esm.js +10 -1
  22. package/dist/plugins/grideditor.float.js +8 -2
  23. package/dist/plugins/grideditor.float.min.js +1 -1
  24. package/dist/plugins/grideditor.float.min.js.map +4 -4
  25. package/dist/plugins/grideditor.spacing.esm.js +12 -3
  26. package/dist/plugins/grideditor.spacing.js +9 -3
  27. package/dist/plugins/grideditor.spacing.min.js +1 -1
  28. package/dist/plugins/grideditor.spacing.min.js.map +4 -4
  29. package/dist/plugins/grideditor.style.esm.js +1593 -0
  30. package/dist/plugins/grideditor.style.js +1592 -0
  31. package/dist/plugins/grideditor.style.min.js +2 -0
  32. package/dist/plugins/grideditor.style.min.js.map +7 -0
  33. package/dist/plugins/grideditor.summernote.esm.js +1 -1
  34. package/dist/plugins/grideditor.summernote.js +1 -1
  35. package/dist/plugins/grideditor.summernote.min.js +1 -1
  36. package/dist/plugins/grideditor.summernote.min.js.map +2 -2
  37. package/dist/plugins/grideditor.textalign.esm.js +10 -1
  38. package/dist/plugins/grideditor.textalign.js +8 -2
  39. package/dist/plugins/grideditor.textalign.min.js +1 -1
  40. package/dist/plugins/grideditor.textalign.min.js.map +4 -4
  41. package/dist/plugins/grideditor.tinymce.esm.js +1 -1
  42. package/dist/plugins/grideditor.tinymce.js +1 -1
  43. package/dist/plugins/grideditor.tinymce.min.js +1 -1
  44. package/dist/plugins/grideditor.tinymce.min.js.map +2 -2
  45. package/dist/plugins/grideditor.visibility.esm.js +12 -3
  46. package/dist/plugins/grideditor.visibility.js +9 -3
  47. package/dist/plugins/grideditor.visibility.min.js +1 -1
  48. package/dist/plugins/grideditor.visibility.min.js.map +4 -4
  49. package/docs/locale-keys.md +89 -8
  50. package/docs/plugins.md +49 -5
  51. package/example/ckeditor.html +9 -4
  52. package/example/index.html +15 -1
  53. package/example/style.html +151 -0
  54. package/example/utilities.html +15 -11
  55. package/package.json +1 -1
  56. package/src/js/grideditor.js +366 -28
  57. package/src/js/locales/grideditor.es.js +70 -1
  58. package/src/js/plugins/grideditor.ckeditor.js +129 -65
  59. package/src/js/plugins/grideditor.float.js +8 -33
  60. package/src/js/plugins/grideditor.spacing.js +8 -273
  61. package/src/js/plugins/grideditor.style.js +179 -0
  62. package/src/js/plugins/grideditor.textalign.js +8 -39
  63. package/src/js/plugins/grideditor.visibility.js +8 -147
  64. package/src/js/style/accordion.js +157 -0
  65. package/src/js/style/catalog.js +76 -0
  66. package/src/js/style/custom.js +84 -0
  67. package/src/js/style/fields.js +382 -0
  68. package/src/js/style/float.js +46 -0
  69. package/src/js/style/options.js +75 -0
  70. package/src/js/style/sections.js +271 -0
  71. package/src/js/style/spacing.js +286 -0
  72. package/src/js/style/textalign.js +52 -0
  73. package/src/js/style/visibility.js +160 -0
  74. package/src/js/text/grideditor.text.js +1 -1
  75. package/src/less/grideditor.less +111 -0
  76. package/types/grideditor.d.ts +18 -0
@@ -16,281 +16,16 @@
16
16
  * utilities.spacing.values narrows the values offered, and
17
17
  * utilities.spacing.scale is what 0 to 5 come to, for a page that changed
18
18
  * Bootstrap's $spacers.
19
+ *
20
+ * Deprecated since 7.3, and gone in 8.0: grideditor.style.js carries this
21
+ * plugin's families, and edits them in its own sections. This file is that
22
+ * part on its own, as it was, and says so once per editor. Loaded beside
23
+ * the style plugin, it stands down.
19
24
  */
20
25
  import { GridEditor } from '../grideditor.js';
21
- import * as dom from '../dom.js';
22
-
23
- Object.assign(GridEditor.locales.en, {
24
- 'utility.padding': 'Padding',
25
- 'utility.margin': 'Margin',
26
- 'utility.side_all': 'All sides',
27
- 'utility.side_x': 'Left and right',
28
- 'utility.side_y': 'Top and bottom',
29
- 'utility.side_t': 'Top',
30
- 'utility.side_b': 'Bottom',
31
- 'utility.side_s': 'Start',
32
- 'utility.side_e': 'End',
33
- 'utility.spacing_gutter': 'A column\'s side padding is its gutter: changing it changes the gutter',
34
- });
35
-
36
- var VALUES = ['0', '1', '2', '3', '4', '5'];
37
-
38
- /** Bootstrap's $spacers. */
39
- var SCALE = ['0', '.25rem', '.5rem', '1rem', '1.5rem', '3rem'];
40
-
41
- /**
42
- * The sides, in the order Bootstrap's css writes their rules: within one
43
- * breakpoint a later rule wins, so p-3 pt-1 has a top of .25rem.
44
- */
45
- var SIDES = ['', 'x', 'y', 't', 'e', 'b', 's'];
46
-
47
- /** What each side sets. Start and end are left and right: Bootstrap's css is left to right. */
48
- var SET = {
49
- '': ['top', 'right', 'bottom', 'left'],
50
- x: ['left', 'right'],
51
- y: ['top', 'bottom'],
52
- t: ['top'],
53
- e: ['right'],
54
- b: ['bottom'],
55
- s: ['left'],
56
- };
57
-
58
- var INFIXES = ['', 'sm', 'md', 'lg', 'xl', 'xxl'];
59
-
60
- var PROPERTIES = { p: 'padding', m: 'margin' };
61
-
62
- /** Every class of the plugin's, padding or margin. */
63
- function pattern(key) {
64
- return new RegExp('^' + key + '[xytbse]?-(?:(?:sm|md|lg|xl|xxl)-)?(?:[0-5]|auto)$');
65
- }
26
+ import { spacingPart } from '../style/spacing.js';
66
27
 
67
28
  GridEditor.utilities.spacing = function(ge) {
68
-
69
- var options = Object.assign({ values: VALUES, scale: SCALE }, ge.settings.utilities.spacing);
70
- var patterns = { p: pattern('p'), m: pattern('m') };
71
-
72
- function applies(node, kind) {
73
- return kind === 'row' || kind === 'column' || kind === 'element' ||
74
- dom.is(node, '[data-ge-container]');
75
- }
76
-
77
- function classes(node) {
78
- return (node.getAttribute('class') || '').split(/\s+/);
79
- }
80
-
81
- function carries(node, key) {
82
- return classes(node).some(function(name) { return patterns[key].test(name); });
83
- }
84
-
85
- /**
86
- * The class of one family that decides a side at a breakpoint: the
87
- * widest breakpoint up to it that has one, as { tier, value }.
88
- */
89
- function source(node, family, tier) {
90
- var names = classes(node);
91
- var values = family.charAt(0) === 'm' ? VALUES.concat(['auto']) : VALUES;
92
-
93
- for (var i = tier; i >= 0; i--) {
94
- for (var v = 0; v < values.length; v++) {
95
- var name = family + (INFIXES[i] ? '-' + INFIXES[i] : '') + '-' + values[v];
96
- if (names.indexOf(name) !== -1) { return { tier: i, value: values[v] }; }
97
- }
98
- }
99
-
100
- return null;
101
- }
102
-
103
- /**
104
- * What padding or margin is on each side with none of the plugin's
105
- * classes: the editor's frame for a row or a column, the host's css
106
- * for anything else. Read by taking the classes off for a moment,
107
- * since that is the only way to ask the browser.
108
- */
109
- function without(node, key) {
110
- var original = node.getAttribute('class');
111
- var style;
112
- var bare = {};
113
-
114
- node.setAttribute('class', classes(node).filter(function(name) { return !patterns[key].test(name); }).join(' '));
115
- style = getComputedStyle(node);
116
- ['top', 'right', 'bottom', 'left'].forEach(function(side) {
117
- bare[side] = style.getPropertyValue(PROPERTIES[key] + '-' + side);
118
- });
119
- if (original === null) { node.removeAttribute('class'); } else { node.setAttribute('class', original); }
120
-
121
- return bare;
122
- }
123
-
124
- /**
125
- * Each side the way Bootstrap's css settles it: the class from the
126
- * widest breakpoint wins, and within one breakpoint the side written
127
- * later in the css. A side no class reaches shows what it is without
128
- * any, over a wider breakpoint's class that is live in a wide window.
129
- */
130
- function sides(node, key, breakpoint) {
131
- var tier = ge.breakpoints.indexOf(breakpoint);
132
- var winners = {};
133
- var styles = {};
134
- var neutral = null;
135
-
136
- SIDES.forEach(function(side, order) {
137
- var found = source(node, key + side, tier);
138
- if (!found) { return; }
139
-
140
- SET[side].forEach(function(set) {
141
- var current = winners[set];
142
- if (!current || found.tier > current.tier || (found.tier === current.tier && order > current.order)) {
143
- winners[set] = { tier: found.tier, order: order, value: found.value };
144
- }
145
- });
146
- });
147
-
148
- ['top', 'right', 'bottom', 'left'].forEach(function(set) {
149
- var winner = winners[set];
150
-
151
- if (!winner) {
152
- neutral = neutral || without(node, key);
153
- styles[PROPERTIES[key] + '-' + set] = neutral[set];
154
- } else {
155
- styles[PROPERTIES[key] + '-' + set] = winner.value === 'auto' ? 'auto' : options.scale[winner.value];
156
- }
157
- });
158
-
159
- return styles;
160
- }
161
-
162
- /** The side a group's select starts on: the first that has a class, or all. */
163
- function startingSide(node, key) {
164
- var names = classes(node).filter(function(name) { return patterns[key].test(name); });
165
- var found = SIDES.filter(function(side) {
166
- return names.some(function(name) { return name.indexOf(key + side + '-') === 0; });
167
- });
168
-
169
- return found.length ? found[0] : '';
170
- }
171
-
172
- function sideLabel(side) {
173
- switch (side) {
174
- case 'x': return ge.t('utility.side_x');
175
- case 'y': return ge.t('utility.side_y');
176
- case 't': return ge.t('utility.side_t');
177
- case 'b': return ge.t('utility.side_b');
178
- case 's': return ge.t('utility.side_s');
179
- case 'e': return ge.t('utility.side_e');
180
- default: return ge.t('utility.side_all');
181
- }
182
- }
183
-
184
- /** A padding or margin group: its name, the side, and the field of that side's family. */
185
- function group(node, key, labelText) {
186
- var box = dom.element('div', { 'class': 'ge-spacing-group', 'data-ge-spacing': key });
187
- var side = dom.element('select', { 'class': 'ge-spacing-side form-select form-select-sm' });
188
-
189
- box.appendChild(dom.element('span', { 'class': 'ge-utility-label' }, labelText));
190
-
191
- SIDES.forEach(function(value) {
192
- side.appendChild(dom.element('option', { value: value }, sideLabel(value)));
193
- });
194
-
195
- var field = ge.utilityField(node, key + startingSide(node, key));
196
-
197
- side.value = field.getAttribute('data-ge-family').slice(1);
198
- side.addEventListener('change', function() {
199
- var next = ge.utilityField(node, key + this.value);
200
- field.replaceWith(next);
201
- field = next;
202
- });
203
- box.appendChild(side);
204
- box.appendChild(field);
205
-
206
- return box;
207
- }
208
-
209
- var NODES = '.row, .column, .ge-element, [data-ge-container]';
210
-
211
- /**
212
- * Keep each drawer on its node's edges. A drawer is pulled out over the
213
- * editor's frame by as much as the frame pads the node, and a padding
214
- * class replaces the frame, so a padded node's drawer is pulled out by
215
- * its real padding instead. And a column padded at the sides gets a word
216
- * about what that does to its gutter.
217
- */
218
- function mark(scope) {
219
- dom.selfAndAll(scope, NODES).forEach(function(node) {
220
- var drawer = dom.child(node, '.ge-tools-drawer');
221
-
222
- if (!drawer || !applies(node, ge.kindOf(node))) { return; }
223
-
224
- if (carries(node, 'p')) {
225
- var style = getComputedStyle(node);
226
-
227
- dom.css(drawer, {
228
- 'margin-top': '-' + style.paddingTop,
229
- 'margin-left': '-' + style.paddingLeft,
230
- 'margin-right': '-' + style.paddingRight,
231
- width: 'calc(100% + ' + style.paddingLeft + ' + ' + style.paddingRight + ')',
232
- });
233
- } else {
234
- dom.css(drawer, { 'margin-top': '', 'margin-left': '', 'margin-right': '', width: '' });
235
- }
236
-
237
- if (dom.hasClass(node, 'column')) {
238
- var padded = classes(node).some(function(name) {
239
- return /^p[xse]?-/.test(name) && patterns.p.test(name);
240
- });
241
- dom.all(drawer, '.ge-spacing-gutter').forEach(function(note) { dom.toggle(note, padded); });
242
- }
243
- });
244
- }
245
-
246
- function families(key, labelKey) {
247
- var values = key === 'm' ? VALUES.concat(['auto']) : VALUES;
248
- var offered = options.values.concat(key === 'm' ? ['auto'] : []);
249
-
250
- return SIDES.map(function(side) {
251
- return {
252
- name: key + side,
253
- prefix: key + side,
254
- values: values,
255
- appliesTo: ['row', 'column', 'text', 'element', 'container'],
256
- labelKey: labelKey,
257
- panel: false,
258
- choices: function() {
259
- return values.filter(function(value) { return offered.indexOf(value) !== -1; });
260
- },
261
- };
262
- });
263
- }
264
-
265
- return {
266
- families: families('p', 'utility.padding').concat(families('m', 'utility.margin')),
267
-
268
- panel: function(node, kind) {
269
- if (!applies(node, kind)) { return null; }
270
-
271
- var box = dom.element('div', { 'class': 'ge-spacing' });
272
- box.appendChild(group(node, 'p', ge.t('utility.padding')));
273
- box.appendChild(group(node, 'm', ge.t('utility.margin')));
274
-
275
- if (kind === 'column') {
276
- box.appendChild(dom.element('small', { 'class': 'ge-spacing-gutter' }, ge.t('utility.spacing_gutter')));
277
- }
278
-
279
- return box;
280
- },
281
-
282
- preview: function(node, kind, breakpoint) {
283
- if (!applies(node, kind)) { return {}; }
284
-
285
- var styles = {};
286
-
287
- ['p', 'm'].forEach(function(key) {
288
- if (carries(node, key)) { Object.assign(styles, sides(node, key, breakpoint)); }
289
- });
290
-
291
- return styles;
292
- },
293
-
294
- onRefresh: mark,
295
- };
29
+ ge.warn('the "spacing" plugin is deprecated and will be removed in 8.0: load grideditor.style.js');
30
+ return spacingPart(ge, ge.settings.utilities.spacing);
296
31
  };
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Style for grid-editor.
3
+ *
4
+ * A utility plugin: load this file after the editor and every row, column,
5
+ * container, pane, element and section gets a Style accordion in its
6
+ * settings panel - size, spacing, border, background, text, typography,
7
+ * display, position and free css - written to the node's own style
8
+ * attribute, with Bootstrap's classes for each section as chips that put
9
+ * them in the classes field. What it can ask the editor for is the handle
10
+ * its factory is called with, described in docs/plugins.md.
11
+ *
12
+ * <script src="dist/grideditor.min.js"></script>
13
+ * <script src="dist/plugins/grideditor.style.min.js"></script>
14
+ *
15
+ * It carries what the spacing, textalign, visibility and float plugins
16
+ * were up to 7.2: their per breakpoint fields are in its sections rather
17
+ * than in Responsive, and those four files are deprecated. Loaded beside
18
+ * it they stand down, and their names in the plugins setting ask for it.
19
+ *
20
+ * Where the settings panel has no room for it - a popover, inline in the
21
+ * drawer - the accordion opens in a dialog, from a Style button.
22
+ *
23
+ * style.sections chooses the sections, and in each the properties and
24
+ * whether it has a catalog; style.spacing and style.visibility are what
25
+ * utilities.spacing and utilities.visibility were.
26
+ */
27
+ import { GridEditor } from '../grideditor.js';
28
+ import { spacingPart } from '../style/spacing.js';
29
+ import { textalignPart } from '../style/textalign.js';
30
+ import { visibilityPart } from '../style/visibility.js';
31
+ import { floatPart } from '../style/float.js';
32
+ import { resolveOptions } from '../style/options.js';
33
+ import { createAccordion } from '../style/accordion.js';
34
+
35
+ Object.assign(GridEditor.locales.en, {
36
+ 'style.section_title': 'Style',
37
+ 'style.dialog_title': 'Style: {kind}',
38
+ 'style.section_size': 'Size',
39
+ 'style.section_spacing': 'Spacing',
40
+ 'style.section_border': 'Border',
41
+ 'style.section_background': 'Background',
42
+ 'style.section_text': 'Text',
43
+ 'style.section_typography': 'Typography',
44
+ 'style.section_display': 'Display',
45
+ 'style.section_position': 'Position',
46
+ 'style.section_custom': 'Custom css',
47
+ 'style.all_sizes': 'Applies to every size',
48
+ 'style.overridden': 'The class {class} takes priority over this value',
49
+ 'style.invalid': 'Not a value this property takes',
50
+ 'style.catalog': 'Bootstrap classes',
51
+ 'style.shadow_x': 'X',
52
+ 'style.shadow_y': 'Y',
53
+ 'style.shadow_blur': 'Blur',
54
+ 'style.shadow_spread': 'Spread',
55
+ 'style.shadow_color': 'Color',
56
+ 'style.shadow_inset': 'Inset',
57
+ 'style.shadow_text_mode': 'Edit as text',
58
+ 'style.prop_width': 'Width',
59
+ 'style.prop_height': 'Height',
60
+ 'style.prop_min_width': 'Min width',
61
+ 'style.prop_min_height': 'Min height',
62
+ 'style.prop_max_width': 'Max width',
63
+ 'style.prop_max_height': 'Max height',
64
+ 'style.prop_margin_top': 'Margin top',
65
+ 'style.prop_margin_right': 'Margin right',
66
+ 'style.prop_margin_bottom': 'Margin bottom',
67
+ 'style.prop_margin_left': 'Margin left',
68
+ 'style.prop_padding_top': 'Padding top',
69
+ 'style.prop_padding_right': 'Padding right',
70
+ 'style.prop_padding_bottom': 'Padding bottom',
71
+ 'style.prop_padding_left': 'Padding left',
72
+ 'style.prop_border_width': 'Border width',
73
+ 'style.prop_border_style': 'Border style',
74
+ 'style.prop_border_color': 'Border color',
75
+ 'style.prop_border_radius': 'Border radius',
76
+ 'style.prop_box_shadow': 'Shadow',
77
+ 'style.prop_background_color': 'Background color',
78
+ 'style.prop_background_image': 'Background image',
79
+ 'style.prop_background_size': 'Background size',
80
+ 'style.prop_background_position': 'Background position',
81
+ 'style.prop_background_repeat': 'Background repeat',
82
+ 'style.prop_color': 'Color',
83
+ 'style.prop_font_size': 'Font size',
84
+ 'style.prop_text_align': 'Text align',
85
+ 'style.prop_text_shadow': 'Text shadow',
86
+ 'style.prop_font_family': 'Font family',
87
+ 'style.prop_font_weight': 'Font weight',
88
+ 'style.prop_font_style': 'Font style',
89
+ 'style.prop_line_height': 'Line height',
90
+ 'style.prop_letter_spacing': 'Letter spacing',
91
+ 'style.prop_text_transform': 'Text transform',
92
+ 'style.prop_text_decoration': 'Text decoration',
93
+ 'style.prop_display': 'Display',
94
+ 'style.prop_opacity': 'Opacity',
95
+ 'style.prop_overflow': 'Overflow',
96
+ 'style.prop_visibility': 'Visibility',
97
+ 'style.prop_position': 'Position',
98
+ 'style.prop_top': 'Top',
99
+ 'style.prop_right': 'Right',
100
+ 'style.prop_bottom': 'Bottom',
101
+ 'style.prop_left': 'Left',
102
+ 'style.prop_z_index': 'Z-index',
103
+ });
104
+
105
+ var PARTS = ['spacing', 'textalign', 'visibility', 'float'];
106
+
107
+ GridEditor.utilities.style = function(ge) {
108
+
109
+ var options = resolveOptions(ge);
110
+ var parts = {
111
+ spacing: spacingPart(ge, options.spacing),
112
+ textalign: textalignPart(ge),
113
+ visibility: visibilityPart(ge, options.visibility),
114
+ float: floatPart(ge),
115
+ };
116
+ var accordions = []; // { node, accordion } for every panel built since the last init
117
+ var context = {
118
+ sections: options.sections,
119
+ parts: parts,
120
+ state: { open: null },
121
+ opened: function(key) {
122
+ accordions.forEach(function(entry) { entry.accordion.open(key); });
123
+ },
124
+ };
125
+
126
+ /** Every part's hook, called in turn. */
127
+ function each(hook) {
128
+ return function() {
129
+ var args = arguments;
130
+ PARTS.forEach(function(name) {
131
+ if (parts[name][hook]) { parts[name][hook].apply(null, args); }
132
+ });
133
+ };
134
+ }
135
+
136
+ var partsRefresh = each('onRefresh');
137
+
138
+ return {
139
+ // The parts' families, edited in the sections rather than in Responsive
140
+ families: PARTS.reduce(function(all, name) {
141
+ return all.concat(parts[name].families.map(function(family) {
142
+ return Object.assign({}, family, { panel: false });
143
+ }));
144
+ }, []),
145
+
146
+ panelSection: function(node, kind) {
147
+ var accordion = createAccordion(ge, node, kind, context);
148
+ if (!accordion) { return null; }
149
+
150
+ accordions.push({ node: node, accordion: accordion });
151
+
152
+ return { labelKey: 'style.section_title', titleKey: 'style.dialog_title', body: accordion.element };
153
+ },
154
+
155
+ preview: function(node, kind, breakpoint) {
156
+ return parts.spacing.preview(node, kind, breakpoint);
157
+ },
158
+
159
+ // After a write, a change of classes or of view: the accordions of
160
+ // the nodes it touched follow
161
+ onRefresh: function(scope) {
162
+ partsRefresh(scope);
163
+
164
+ accordions = accordions.filter(function(entry) { return entry.accordion.element.isConnected; });
165
+ accordions.forEach(function(entry) {
166
+ if (entry.node === scope || scope.contains(entry.node)) { entry.accordion.render(); }
167
+ });
168
+ },
169
+
170
+ drawerTools: each('drawerTools'),
171
+
172
+ onDeinit: function() {
173
+ each('onDeinit')();
174
+ accordions = [];
175
+ },
176
+ };
177
+ };
178
+
179
+ GridEditor.utilities.style.replaces = PARTS;
@@ -12,47 +12,16 @@
12
12
  *
13
13
  * The class aligns everything inside the node that does not align itself: a
14
14
  * paragraph the rich text editor gave its own text-align keeps it.
15
+ *
16
+ * Deprecated since 7.3, and gone in 8.0: grideditor.style.js carries this
17
+ * plugin's families, and edits them in its own sections. This file is that
18
+ * part on its own, as it was, and says so once per editor. Loaded beside
19
+ * the style plugin, it stands down.
15
20
  */
16
21
  import { GridEditor } from '../grideditor.js';
17
-
18
- Object.assign(GridEditor.locales.en, {
19
- 'utility.text_align': 'Text alignment',
20
- 'utility.text_start': 'Start',
21
- 'utility.text_center': 'Center',
22
- 'utility.text_end': 'End',
23
- });
24
-
25
- /** Start and end are left and right: Bootstrap's css is left to right. */
26
- var CSS = { start: 'left', center: 'center', end: 'right' };
22
+ import { textalignPart } from '../style/textalign.js';
27
23
 
28
24
  GridEditor.utilities.textalign = function(ge) {
29
-
30
- function label(value) {
31
- if (value === 'start') { return ge.t('utility.text_start'); }
32
- if (value === 'center') { return ge.t('utility.text_center'); }
33
-
34
- return ge.t('utility.text_end');
35
- }
36
-
37
- return {
38
- families: [{
39
- name: 'text-align',
40
- prefix: 'text',
41
- values: ['start', 'center', 'end'],
42
- appliesTo: ['row', 'column', 'text', 'element', 'container'],
43
- labelKey: 'utility.text_align',
44
- label: label,
45
-
46
- /**
47
- * With no class applying here, the node aligns as its parent
48
- * does - or as the host's css says - which only the browser can
49
- * tell, so it is asked with the classes out of the way. Parents
50
- * are previewed before their children, so the parent's answer is
51
- * already the view's.
52
- */
53
- preview: function(value, node) {
54
- return { 'text-align': value === null ? ge.bareStyle(node, 'text-align', 'text-align') : CSS[value] };
55
- },
56
- }],
57
- };
25
+ ge.warn('the "textalign" plugin is deprecated and will be removed in 8.0: load grideditor.style.js');
26
+ return textalignPart(ge);
58
27
  };
@@ -17,155 +17,16 @@
17
17
  *
18
18
  * utilities.visibility.drawer: false leaves the eye out of the drawers, and
19
19
  * the panel field is the only control.
20
+ *
21
+ * Deprecated since 7.3, and gone in 8.0: grideditor.style.js carries this
22
+ * plugin's families, and edits them in its own sections. This file is that
23
+ * part on its own, as it was, and says so once per editor. Loaded beside
24
+ * the style plugin, it stands down.
20
25
  */
21
26
  import { GridEditor } from '../grideditor.js';
22
- import * as dom from '../dom.js';
23
-
24
- Object.assign(GridEditor.locales.en, {
25
- 'utility.visibility': 'Visibility',
26
- 'utility.visibility_hidden': 'Hidden',
27
- 'utility.visibility_shown': 'Shown',
28
- 'tool.hide_in_view': 'Hide in this view',
29
- 'tool.show_in_view': 'Show in this view',
30
- 'badge.hidden_in': 'Hidden at {breakpoints}',
31
- });
32
-
33
- /** A node that carries any class of the family, at any breakpoint. */
34
- var CLASS_PATTERN = /(?:^|\s)d-(?:(?:sm|md|lg|xl|xxl)-)?(?:none|block|flex)(?:\s|$)/;
35
-
36
- var NODES = '.row, .column, .ge-content, .ge-element, [data-ge-container]';
27
+ import { visibilityPart } from '../style/visibility.js';
37
28
 
38
29
  GridEditor.utilities.visibility = function(ge) {
39
-
40
- var options = Object.assign({ drawer: true }, ge.settings.utilities.visibility);
41
-
42
- /** What "shown" is written as on this kind of node. */
43
- function shown(kind) {
44
- return kind === 'row' ? 'flex' : 'block';
45
- }
46
-
47
- function applies(node, kind) {
48
- return kind === 'row' || kind === 'column' || kind === 'element' || kind === 'text' || kind === 'plain' ||
49
- dom.is(node, '[data-ge-container]');
50
- }
51
-
52
- function hiddenAt(node, view) {
53
- return ge.getUtility(node, 'visibility', view) === 'none';
54
- }
55
-
56
- /** The breakpoints at which the node is hidden, smallest first. */
57
- function hiddenTiers(node) {
58
- return ge.breakpoints.filter(function(key) { return hiddenAt(node, key); });
59
- }
60
-
61
- /**
62
- * Whether the node is hidden in the view being edited. In the all view
63
- * that means hidden at every breakpoint, since "hidden at some" is what
64
- * the badge is for.
65
- */
66
- function hiddenHere(node) {
67
- return ge.view() === 'all'
68
- ? hiddenTiers(node).length === ge.breakpoints.length
69
- : hiddenAt(node, ge.view());
70
- }
71
-
72
- /** What the breakpoint below the view shows, which an inherit falls back to. */
73
- function hiddenBelow(node) {
74
- var index = ge.breakpoints.indexOf(ge.view());
75
-
76
- return index > 0 && hiddenAt(node, ge.breakpoints[index - 1]);
77
- }
78
-
79
- /**
80
- * Hide or show the node in the view being edited, with as few classes as
81
- * that takes. In a breakpoint view that is often none at all: showing a
82
- * node the breakpoint below shows removes this breakpoint's d-*-none
83
- * rather than writing a d-*-block on top of it. In the all view a node
84
- * is hidden everywhere or shown everywhere, and shown is no class.
85
- */
86
- function toggle(node, kind) {
87
- var hide = !hiddenHere(node);
88
- var value;
89
-
90
- if (ge.view() === 'all') {
91
- value = hide ? 'none' : null;
92
- } else if (hide) {
93
- value = hiddenBelow(node) ? null : 'none';
94
- } else {
95
- value = hiddenBelow(node) ? shown(kind) : null;
96
- }
97
-
98
- ge.setUtility(node, 'visibility', value, { source: 'tool' });
99
- }
100
-
101
- /**
102
- * The canvas shows each node as the view sees it. ge-visibility keeps a
103
- * node Bootstrap would hide on the canvas, ge-hidden-in-view fades it,
104
- * and data-ge-hidden-in carries the badge text for the all view.
105
- */
106
- function mark(scope) {
107
- dom.selfAndAll(scope, NODES).forEach(function(node) {
108
- var kind = ge.kindOf(node);
109
- var carries = applies(node, kind) && CLASS_PATTERN.test(node.getAttribute('class') || '');
110
- var tiers = carries ? hiddenTiers(node) : [];
111
- var here = carries && hiddenHere(node);
112
- var partly = carries && ge.view() === 'all' && tiers.length > 0 && !here;
113
-
114
- dom.toggleClass(node, 'ge-visibility', carries);
115
- dom.toggleClass(node, 'ge-hidden-in-view', here);
116
-
117
- if (partly) {
118
- node.setAttribute('data-ge-hidden-in', ge.t('badge.hidden_in', { breakpoints: tiers.join(', ') }));
119
- } else {
120
- node.removeAttribute('data-ge-hidden-in');
121
- }
122
-
123
- dom.children(node, '.ge-tools-drawer').forEach(function(drawer) {
124
- dom.children(drawer, '.ge-visibility-tool').forEach(function(tool) {
125
- tool.setAttribute('title', here ? ge.t('tool.show_in_view') : ge.t('tool.hide_in_view'));
126
- dom.all(tool, 'i').forEach(function(icon) {
127
- icon.setAttribute('class', here ? 'bi bi-eye-slash' : 'bi bi-eye');
128
- });
129
- });
130
- });
131
- });
132
- }
133
-
134
- function unmark() {
135
- dom.all(ge.canvas, '.ge-visibility, .ge-hidden-in-view, [data-ge-hidden-in]').forEach(function(node) {
136
- dom.removeClass(node, 'ge-visibility ge-hidden-in-view');
137
- node.removeAttribute('data-ge-hidden-in');
138
- dom.dropEmptyClass(node);
139
- });
140
- }
141
-
142
- return {
143
- families: [{
144
- name: 'visibility',
145
- prefix: 'd',
146
- values: ['none', 'block', 'flex'],
147
- appliesTo: ['row', 'column', 'text', 'element', 'container'],
148
- labelKey: 'utility.visibility',
149
-
150
- /** Hidden, or shown the way this kind of node is shown. */
151
- choices: function(node, kind) {
152
- return ['none', shown(kind)];
153
- },
154
-
155
- label: function(value) {
156
- return value === 'none' ? ge.t('utility.visibility_hidden') : ge.t('utility.visibility_shown');
157
- },
158
- }],
159
-
160
- drawerTools: function(drawer, node, kind) {
161
- if (!options.drawer || !applies(node, kind)) { return; }
162
-
163
- ge.createTool(drawer, ge.t('tool.hide_in_view'), 'ge-visibility-tool', 'bi bi-eye', function() {
164
- toggle(node, kind);
165
- });
166
- },
167
-
168
- onRefresh: mark,
169
- onDeinit: unmark,
170
- };
30
+ ge.warn('the "visibility" plugin is deprecated and will be removed in 8.0: load grideditor.style.js');
31
+ return visibilityPart(ge, ge.settings.utilities.visibility);
171
32
  };