@themarioga/grid-editor 8.7.1 → 8.8.1

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.
@@ -36,7 +36,11 @@ The tools in a drawer, and the buttons in the toolbar above the canvas.
36
36
  | `tool.delete_column` | Remove col | Column drawer |
37
37
  | `tool.delete_element` | Remove element | Element drawer |
38
38
  | `tool.delete_container` | Remove container | Container drawer |
39
- | `tool.delete_pane` | Remove pane | Drawer of a tab or an accordion item |
39
+ | `tool.delete_pane` | Remove pane | Drawer of a tab, an accordion item or a carousel slide |
40
+ | `tool.carousel_show_previous` | Previous slide | Carousel drawer, shows the previous slide |
41
+ | `tool.carousel_show_next` | Next slide | Carousel drawer, shows the next slide |
42
+ | `tool.carousel_move_back` | Move back | Slide drawer, moves the slide a place back |
43
+ | `tool.carousel_move_forward` | Move forward | Slide drawer, moves the slide a place on |
40
44
  | `tool.rename` | Double click to rename | Tooltip of a pane's label, which is edited in place |
41
45
  | `tool.toggle_popup` | Fold this popup away while editing | Popup drawer. Editing shows a popup unfolded, and this folds it away |
42
46
  | `tool.element_info` | Element: {name} | Tooltip of the element drawer's info tool. `{name}` is the element's `data-ge-label`, its `data-ge-element` type, or both |
@@ -90,12 +94,13 @@ title. `{kind}` is one of the `panel.kind_*` keys, or a container's own label.
90
94
  | `panel.kind_section` | Section | For a section |
91
95
  | `panel.kind_tab` | Tab | For a tab |
92
96
  | `panel.kind_accordion_item` | Accordion item | For an accordion item |
97
+ | `panel.kind_carousel_item` | Slide | For a carousel slide |
93
98
 
94
99
 
95
100
  container.*
96
101
  -----------
97
102
 
98
- The containers: tabs, accordions and popups, and the panes inside them.
103
+ The containers: tabs, accordions, popups, carousels and cards, and the panes inside them.
99
104
 
100
105
  | Key | English | Where |
101
106
  | --- | --- | --- |
@@ -122,6 +127,27 @@ The containers: tabs, accordions and popups, and the panes inside them.
122
127
  | `container.add_accordion` | Accordion | Toolbar button that adds an accordion |
123
128
  | `container.add_accordion_item` | Add item | Container drawer, adds an item |
124
129
  | `container.accordion_label` | Item {number} | Label of a new accordion item |
130
+ | `container.add_carousel` | Carousel | Toolbar button that adds a carousel |
131
+ | `container.add_carousel_item` | Add slide | Container drawer, adds a slide |
132
+ | `container.carousel_previous` | Previous | The text, hidden, of a carousel's previous arrow in the page |
133
+ | `container.carousel_next` | Next | The same for the next arrow |
134
+ | `container.carousel_slide_label` | Slide {number} | `aria-label` of a carousel's indicator. `{number}` is the slide's position |
135
+ | `container.carousel_counter` | {current} / {total} | The container's drawer says which slide is shown, and how many there are |
136
+ | `container.carousel_section` | Carousel | Heading of the carousel's section of its settings panel |
137
+ | `container.carousel_controls` | Arrows | Its checkbox for the previous and next arrows |
138
+ | `container.carousel_indicators` | Indicators | Its checkbox for the indicators |
139
+ | `container.carousel_fade` | Fade | Its checkbox for `carousel-fade` |
140
+ | `container.carousel_dark` | Dark theme | Its checkbox for `data-bs-theme="dark"` |
141
+ | `container.carousel_ride` | Autoplay | Its autoplay select, `data-bs-ride` |
142
+ | `container.carousel_ride_no` | No | Its choice for no autoplay |
143
+ | `container.carousel_ride_load` | On load | Its choice for `data-bs-ride="carousel"` |
144
+ | `container.carousel_ride_interaction` | After first interaction | Its choice for `data-bs-ride="true"` |
145
+ | `container.carousel_interval` | Interval (s) | The interval field, in seconds, of the carousel's section and of a slide's. `data-bs-interval` |
146
+ | `container.carousel_pause` | Pause on hover | Its checkbox for `data-bs-pause` |
147
+ | `container.carousel_wrap` | Wrap around | Its checkbox for `data-bs-wrap` |
148
+ | `container.carousel_keyboard` | Keyboard | Its checkbox for `data-bs-keyboard` |
149
+ | `container.carousel_touch` | Touch swipe | Its checkbox for `data-bs-touch` |
150
+ | `container.carousel_item_section` | Slide | Heading of a slide's section of its settings panel |
125
151
  | `container.add_popup` | Popup | Toolbar button that adds a popup |
126
152
  | `container.popup_title` | Title | Title of a new popup, in its modal header |
127
153
  | `container.popup_trigger` | Open | Label of the button a popup makes to open itself |
@@ -234,6 +260,7 @@ browser's own confirm instead.
234
260
  | `confirm.delete_container` | Delete this container and everything in it? | Before a container is removed |
235
261
  | `confirm.delete_tab` | Delete this tab and everything in it? | Before a tab and its pane are removed |
236
262
  | `confirm.delete_accordion_item` | Delete this item and everything in it? | Before an accordion item is removed |
263
+ | `confirm.delete_carousel_item` | Delete this slide and everything in it? | Before a carousel slide is removed |
237
264
 
238
265
 
239
266
  view.*
package/docs/plugins.md CHANGED
@@ -1,7 +1,7 @@
1
1
  Writing a plugin
2
2
  ================
3
3
 
4
- Tabs, accordions, popups, cards and the element level controls are not built
4
+ Tabs, accordions, popups, carousels, cards and the element level controls are not built
5
5
  into grid-editor: each is a file you load beside it, and loading the file is
6
6
  what turns the feature on. `grideditor.card.js` is the shortest of them, and
7
7
  the one to read first if you are about to write your own.
@@ -51,23 +51,26 @@ called once per editor, with the handle below, and returns the definition:
51
51
 
52
52
  ```javascript
53
53
  Object.assign(GridEditor.locales.en, {
54
- 'container.add_carousel': 'Carousel',
55
- 'container.carousel_label': 'Slide {number}',
54
+ 'container.add_gallery': 'Gallery',
55
+ 'container.gallery_label': 'Picture {number}',
56
56
  });
57
57
 
58
- GridEditor.containers.carousel = function(ge) {
58
+ GridEditor.containers.gallery = function(ge) {
59
59
 
60
- function addSlideTo(container, options) { … }
60
+ function addPictureTo(container, options) { … }
61
61
 
62
62
  return {
63
- labelKey: 'container.add_carousel', // the toolbar button's label
63
+ labelKey: 'container.add_gallery', // the toolbar button's label
64
64
  iconClass: 'bi bi-images', // optional: the button shows it in place of the label
65
65
  group: 'media', // optional: its toolbar tab, with toolbar_groups
66
- addPaneKey: 'container.add_slide', // the drawer's add pane tool
67
- paneKind: 'slide', // the kind its panes report
66
+ addPaneKey: 'container.add_picture', // the drawer's add pane tool
67
+ paneKind: 'picture', // the kind its panes report
68
+ paneClass: 'ge-picture', // optional: the class mark gives its panes, which is how
69
+ // the editor knows one is a picture
70
+ paneLabelKey: 'panel.kind_picture', // optional: what a pane's settings panel calls it
68
71
 
69
72
  create: function(options) { … }, // returns the container
70
- addPane: addSlideTo, // returns the new pane
73
+ addPane: addPictureTo, // returns the new pane
71
74
  mark: function(container) { … }, // editing furniture on
72
75
  unmark: function(container) { … }, // and off again
73
76
  cleanMarkup: function(root, liveOf) { … }, // the same, on a copy: see "Reading on a copy"
@@ -86,11 +89,11 @@ it is imported, which is how the shipped plugins' modules work:
86
89
  ```javascript
87
90
  import { GridEditor } from '@themarioga/grid-editor';
88
91
 
89
- GridEditor.containers.carousel = function(ge) { … };
92
+ GridEditor.containers.gallery = function(ge) { … };
90
93
  ```
91
94
 
92
95
  A page or an app imports it for that side effect, after the editor:
93
- `import './carousel.js'`. Either way there is one registry per page, and the
96
+ `import './gallery.js'`. Either way there is one registry per page, and the
94
97
  editors made after a plugin registered have it.
95
98
 
96
99
  Everything the editor hands a plugin, and everything a plugin hands back, is
@@ -141,11 +144,11 @@ element, and where there may be several, an array.
141
144
  | `ge.detailsOf(node)` | A node's settings panel, wherever it is: in its drawer, or open in the offcanvas, popover or modal `settings_panel` names, outside the canvas. Find a panel's fields through it, never through the drawer. Null for a node with none |
142
145
  | `ge.deleteNode(kind, node, confirmText, animate)` | Remove a node: ask, animate, announce |
143
146
  | `ge.place(node, kind, options)` | Put a created node where `appendTo` and friends say, through the add events. `options.source` is the payload's `source`, `api` by default |
144
- | `ge.createPaneControls(pane, kind, hostTools, confirmText, remove)` | The drawer a pane gets: move, the host's tools, delete |
147
+ | `ge.createPaneControls(pane, kind, hostTools, confirmText, remove)` | The drawer a pane gets: move, the host's tools, delete. Returns the drawer, for a plugin that wants other tools in it |
145
148
  | `ge.makeLabelEditable(label)` | Rename in place, with the Bootstrap toggle suspended while typing |
146
149
  | `ge.labelIn(button)` | The label span inside a button, wrapped if it is not already |
147
150
  | `ge.unwrapLabels(scope)` | Take those wrappers off again, for `unmark` |
148
- | `ge.suspendToggles(scope)` / `ge.resumeToggles(scope)` | Move `data-bs-toggle` aside while editing, and back on the way out |
151
+ | `ge.suspendToggles(scope)` / `ge.resumeToggles(scope)` | Move the attributes Bootstrap's data api acts on - `data-bs-toggle`, `data-bs-dismiss`, `data-bs-slide`, `data-bs-slide-to` and `data-bs-ride` - aside while editing, and back on the way out. They take `scope` and everything under it: a plugin whose container holds others passes the elements that are its own |
149
152
  | `ge.emit(name, payload)` | Fire an event and its callbacks; false means a handler canceled |
150
153
  | `ge.payloadFor(kind, node, extra)` | Build a payload the documented way |
151
154
  | `ge.operate(body)` | Run `body` as one operation, so a handler calling back in is queued |
@@ -297,7 +300,7 @@ is, called for each container of the type under `root`:
297
300
  ```javascript
298
301
  cleanMarkup: function(root) {
299
302
  var definition = this;
300
- root.querySelectorAll('[data-ge-container="carousel"]').forEach(function(container) {
303
+ root.querySelectorAll('[data-ge-container="gallery"]').forEach(function(container) {
301
304
  definition.unmark(container);
302
305
  });
303
306
  },
@@ -23,6 +23,7 @@
23
23
  <script src="../dist/plugins/grideditor.accordion.min.js"></script>
24
24
  <script src="../dist/plugins/grideditor.popup.min.js"></script>
25
25
  <script src="../dist/plugins/grideditor.card.min.js"></script>
26
+ <script src="../dist/plugins/grideditor.carousel.min.js"></script>
26
27
 
27
28
  <script>
28
29
  document.addEventListener('DOMContentLoaded', function() {
@@ -87,9 +88,9 @@
87
88
  <p class="form-text">
88
89
  A container holds regions, and every region is an ordinary
89
90
  one: rows, columns, content areas and elements nest inside
90
- it exactly as they do at the top level. The four buttons in
91
- the toolbar add a tabs container, an accordion, a popup and
92
- a card &mdash; the first three hold a pane each, a card
91
+ it exactly as they do at the top level. The five buttons in
92
+ the toolbar add a tabs container, an accordion, a popup, a
93
+ carousel and a card &mdash; the first four hold a pane each, a card
93
94
  holds one region and an editable header.
94
95
  </p>
95
96
  <p class="form-text">
@@ -104,7 +105,11 @@
104
105
  an accordion item. A tabs container's gear has a Tabs
105
106
  section for its variant - tabs, pills or underline, full
106
107
  width, alignment, and vertical from a breakpoint up - and
107
- the last row has two of them.
108
+ the row after has two of them. The last row is a carousel:
109
+ one slide shows at a time, the arrows in its drawer move
110
+ between them, and the gear has a Carousel section for
111
+ fade, autoplay and the rest of Bootstrap's options, and a
112
+ slide&rsquo;s own gear has its interval.
108
113
  </p>
109
114
  <button class="btn btn-sm btn-secondary" id="output" type="button">Show the html this produces</button>
110
115
  <button class="btn btn-sm btn-primary" id="authored" type="button">Open that html as a real page</button>
@@ -118,10 +123,10 @@
118
123
  <div class="col-lg-6">
119
124
  <div data-ge-container="tabs">
120
125
  <ul class="nav nav-tabs" role="tablist">
121
- <li class="nav-item ge-tab" role="presentation">
126
+ <li class="nav-item" role="presentation">
122
127
  <button class="nav-link active" type="button" role="tab" data-bs-toggle="tab" data-bs-target="#example-tab-one" aria-controls="example-tab-one" aria-selected="true">Overview</button>
123
128
  </li>
124
- <li class="nav-item ge-tab" role="presentation">
129
+ <li class="nav-item" role="presentation">
125
130
  <button class="nav-link" type="button" role="tab" data-bs-toggle="tab" data-bs-target="#example-tab-two" aria-controls="example-tab-two">Details</button>
126
131
  </li>
127
132
  </ul>
@@ -214,10 +219,10 @@
214
219
  <div class="accordion-body">
215
220
  <div data-ge-container="tabs">
216
221
  <ul class="nav nav-tabs" role="tablist">
217
- <li class="nav-item ge-tab" role="presentation">
222
+ <li class="nav-item" role="presentation">
218
223
  <button class="nav-link active" type="button" role="tab" data-bs-toggle="tab" data-bs-target="#nested-tab-one" aria-controls="nested-tab-one" aria-selected="true">Nested</button>
219
224
  </li>
220
- <li class="nav-item ge-tab" role="presentation">
225
+ <li class="nav-item" role="presentation">
221
226
  <button class="nav-link" type="button" role="tab" data-bs-toggle="tab" data-bs-target="#nested-tab-two" aria-controls="nested-tab-two">Two levels</button>
222
227
  </li>
223
228
  </ul>
@@ -301,6 +306,41 @@
301
306
  </div>
302
307
  </div>
303
308
 
309
+ <div class="row">
310
+ <div class="col-lg-12">
311
+ <div data-ge-container="carousel">
312
+ <div class="carousel slide carousel-fade" id="example-carousel" data-bs-ride="carousel" data-bs-interval="5000">
313
+ <div class="carousel-indicators">
314
+ <button type="button" data-bs-target="#example-carousel" data-bs-slide-to="0" class="active" aria-current="true" aria-label="Slide 1"></button>
315
+ <button type="button" data-bs-target="#example-carousel" data-bs-slide-to="1" aria-label="Slide 2"></button>
316
+ </div>
317
+ <div class="carousel-inner">
318
+ <div class="carousel-item active">
319
+ <div class="row"><div class="col-lg-12">
320
+ <div class="ge-content" data-ge-content-type="tinymce"><p>A carousel that fades and starts by itself on the page. In the editor it stays on one slide until you move it with the arrows in its drawer.</p></div>
321
+ </div></div>
322
+ </div>
323
+ <div class="carousel-item" data-bs-interval="2000">
324
+ <div class="row"><div class="col-lg-6">
325
+ <div class="ge-content" data-ge-content-type="tinymce"><p>A slide is a region like any other, and this one stays for two seconds only.</p></div>
326
+ </div><div class="col-lg-6">
327
+ <div class="ge-content" data-ge-content-type="tinymce"><p>So it takes rows and columns of its own.</p></div>
328
+ </div></div>
329
+ </div>
330
+ </div>
331
+ <button class="carousel-control-prev" type="button" data-bs-target="#example-carousel" data-bs-slide="prev">
332
+ <span class="carousel-control-prev-icon" aria-hidden="true"></span>
333
+ <span class="visually-hidden">Previous</span>
334
+ </button>
335
+ <button class="carousel-control-next" type="button" data-bs-target="#example-carousel" data-bs-slide="next">
336
+ <span class="carousel-control-next-icon" aria-hidden="true"></span>
337
+ <span class="visually-hidden">Next</span>
338
+ </button>
339
+ </div>
340
+ </div>
341
+ </div>
342
+ </div>
343
+
304
344
  </div> <!-- /#myGrid -->
305
345
  </div> <!-- /.container -->
306
346
 
package/package.json CHANGED
@@ -32,7 +32,7 @@
32
32
  "publishConfig": {
33
33
  "access": "public"
34
34
  },
35
- "version": "8.7.1",
35
+ "version": "8.8.1",
36
36
  "main": "dist/grideditor.js",
37
37
  "module": "dist/grideditor.esm.js",
38
38
  "types": "dist/grideditor.d.ts",
@@ -32,6 +32,7 @@ var METHODS = {
32
32
  createContainer: { value: true },
33
33
  addTab: { value: true },
34
34
  addAccordionItem: { value: true },
35
+ addPane: { value: true },
35
36
  setLocale: {},
36
37
  getUtility: { value: true },
37
38
  setUtility: { value: true },
@@ -985,6 +986,17 @@ function build(instance, baseElem, optionsOrMethod) {
985
986
  if (fromPlugin) { return fromPlugin; }
986
987
 
987
988
  if (node.getAttribute('data-ge-container')) { return node.getAttribute('data-ge-container'); }
989
+
990
+ // A container plugin's pane, by the class it marks its panes with
991
+ var paneKind = null;
992
+ Object.keys(CONTAINERS).forEach(function(type) {
993
+ var definition = CONTAINERS[type];
994
+ if (!paneKind && definition.paneClass && dom.hasClass(node, definition.paneClass)) {
995
+ paneKind = definition.paneKind;
996
+ }
997
+ });
998
+ if (paneKind) { return paneKind; }
999
+
988
1000
  if (dom.hasClass(node, 'ge-tab')) { return 'tab'; }
989
1001
  if (dom.hasClass(node, 'ge-accordion-item')) { return 'accordion-item'; }
990
1002
  if (dom.hasClass(node, 'row')) { return 'row'; }
@@ -3150,7 +3162,7 @@ function build(instance, baseElem, optionsOrMethod) {
3150
3162
  }
3151
3163
 
3152
3164
  /* --------------------------------------------------------------
3153
- * Containers: tabs, accordions and popups.
3165
+ * Containers: tabs, accordions, popups, carousels and cards.
3154
3166
  *
3155
3167
  * A container holds panes, and a pane is an ordinary canvas region -
3156
3168
  * rows, columns, content areas and elements nest inside one exactly
@@ -3260,6 +3272,7 @@ function build(instance, baseElem, optionsOrMethod) {
3260
3272
  if (definition.addPane) {
3261
3273
  createTool(drawer, t(definition.addPaneKey), 'ge-add-pane', 'bi bi-plus-circle', function() {
3262
3274
  var pane = definition.addPane(container, {});
3275
+ if (!pane) { return; }
3263
3276
 
3264
3277
  addNode(definition.paneKind, pane, function() {}, {
3265
3278
  parent: container,
@@ -3300,33 +3313,41 @@ function build(instance, baseElem, optionsOrMethod) {
3300
3313
  * for its selector to match, so the attribute is moved aside while
3301
3314
  * the editor needs the control not to react, and moved back on the
3302
3315
  * way out.
3316
+ *
3317
+ * The attributes are the ones Bootstrap's data api acts on: the tabs',
3318
+ * accordions' and popups' toggles and dismisses, and a carousel's
3319
+ * slide controls and autoplay.
3303
3320
  */
3321
+ var TOGGLE_ATTRIBUTES = ['toggle', 'dismiss', 'slide', 'slide-to', 'ride'];
3322
+
3304
3323
  function suspendToggles(scope) {
3305
3324
  if (!scope) { return; }
3306
3325
 
3307
- dom.selfAndAll(scope, '[data-bs-toggle], [data-bs-dismiss]').forEach(function(node) {
3308
- ['toggle', 'dismiss'].forEach(function(name) {
3309
- var value = node.getAttribute('data-bs-' + name);
3310
- if (value === null) { return; }
3326
+ dom.selfAndAll(scope, TOGGLE_ATTRIBUTES.map(function(name) { return '[data-bs-' + name + ']'; }).join(', '))
3327
+ .forEach(function(node) {
3328
+ TOGGLE_ATTRIBUTES.forEach(function(name) {
3329
+ var value = node.getAttribute('data-bs-' + name);
3330
+ if (value === null) { return; }
3311
3331
 
3312
- node.setAttribute('data-ge-bs-' + name, value);
3313
- node.removeAttribute('data-bs-' + name);
3332
+ node.setAttribute('data-ge-bs-' + name, value);
3333
+ node.removeAttribute('data-bs-' + name);
3334
+ });
3314
3335
  });
3315
- });
3316
3336
  }
3317
3337
 
3318
3338
  function resumeToggles(scope) {
3319
3339
  if (!scope) { return; }
3320
3340
 
3321
- dom.selfAndAll(scope, '[data-ge-bs-toggle], [data-ge-bs-dismiss]').forEach(function(node) {
3322
- ['toggle', 'dismiss'].forEach(function(name) {
3323
- var value = node.getAttribute('data-ge-bs-' + name);
3324
- if (value === null) { return; }
3341
+ dom.selfAndAll(scope, TOGGLE_ATTRIBUTES.map(function(name) { return '[data-ge-bs-' + name + ']'; }).join(', '))
3342
+ .forEach(function(node) {
3343
+ TOGGLE_ATTRIBUTES.forEach(function(name) {
3344
+ var value = node.getAttribute('data-ge-bs-' + name);
3345
+ if (value === null) { return; }
3325
3346
 
3326
- node.setAttribute('data-bs-' + name, value);
3327
- node.removeAttribute('data-ge-bs-' + name);
3347
+ node.setAttribute('data-bs-' + name, value);
3348
+ node.removeAttribute('data-ge-bs-' + name);
3349
+ });
3328
3350
  });
3329
- });
3330
3351
  }
3331
3352
 
3332
3353
  /**
@@ -4480,6 +4501,11 @@ function build(instance, baseElem, optionsOrMethod) {
4480
4501
 
4481
4502
  if (CONTAINERS[kind] && CONTAINERS[kind].labelKey) { return t(CONTAINERS[kind].labelKey); }
4482
4503
 
4504
+ var paneLabel = Object.keys(CONTAINERS).filter(function(type) {
4505
+ return CONTAINERS[type].paneKind === kind && CONTAINERS[type].paneLabelKey;
4506
+ })[0];
4507
+ if (paneLabel) { return t(CONTAINERS[paneLabel].paneLabelKey); }
4508
+
4483
4509
  switch (kind) {
4484
4510
  case 'row': return t('panel.kind_row');
4485
4511
  case 'column': return t('panel.kind_column');
@@ -5437,6 +5463,7 @@ function build(instance, baseElem, optionsOrMethod) {
5437
5463
  }
5438
5464
 
5439
5465
  var pane = definition.addPane(container, options);
5466
+ if (!pane) { return null; }
5440
5467
 
5441
5468
  return addNode(definition.paneKind, pane, function() {}, {
5442
5469
  parent: container,
@@ -5445,6 +5472,19 @@ function build(instance, baseElem, optionsOrMethod) {
5445
5472
  });
5446
5473
  }
5447
5474
 
5475
+ /** A pane appended to a container of any type that has panes. */
5476
+ function apiAddPane(container, options) {
5477
+ container = nodeFrom(container);
5478
+
5479
+ var type = containerTypeOf(container);
5480
+ if (!CONTAINERS[type] || !CONTAINERS[type].addPane) {
5481
+ warn('addPane: this is not a container with panes');
5482
+ return null;
5483
+ }
5484
+
5485
+ return addPaneTo(container, type, options);
5486
+ }
5487
+
5448
5488
  /**
5449
5489
  * A shallow frozen copy of the settings for the instance, so a host
5450
5490
  * can read what the editor is running with without changing it
@@ -5868,6 +5908,7 @@ function build(instance, baseElem, optionsOrMethod) {
5868
5908
  addAccordionItem: function(container, options) {
5869
5909
  return addPaneTo(container, 'accordion', options);
5870
5910
  },
5911
+ addPane: apiAddPane,
5871
5912
  setLocale: setLocale,
5872
5913
  getUtility: getUtility,
5873
5914
  setUtility: setUtility,
@@ -5930,13 +5971,13 @@ function build(instance, baseElem, optionsOrMethod) {
5930
5971
  GridEditor._created = [];
5931
5972
 
5932
5973
  /**
5933
- * Container plugins: tabs, accordions, popups, and whatever a host writes.
5974
+ * Container plugins: tabs, accordions, popups, carousels, cards, and whatever a host writes.
5934
5975
  *
5935
5976
  * A plugin is a factory registered under the type it builds, called once per
5936
5977
  * editor with the handle described in docs/plugins.md. Loading its file is
5937
5978
  * what makes the type available; the `plugins` setting narrows that list.
5938
5979
  *
5939
- * GridEditor.containers.carousel = function(ge) {
5980
+ * GridEditor.containers.gallery = function(ge) {
5940
5981
  * return { labelKey: ..., create: ..., mark: ..., unmark: ... };
5941
5982
  * };
5942
5983
  */
@@ -97,6 +97,33 @@ GridEditor.locales.es = {
97
97
  'container.tabs_layout_horizontal': 'Horizontal',
98
98
  'container.tabs_layout_vertical': 'Vertical',
99
99
  'container.tabs_layout_vertical_from': 'Vertical desde {breakpoint}',
100
+ 'container.add_carousel': 'Carrusel',
101
+ 'container.add_carousel_item': 'Añadir diapositiva',
102
+ 'confirm.delete_carousel_item': '¿Borrar esta diapositiva y todo lo que contiene?',
103
+ 'panel.kind_carousel_item': 'Diapositiva',
104
+ 'container.carousel_previous': 'Anterior',
105
+ 'container.carousel_next': 'Siguiente',
106
+ 'container.carousel_slide_label': 'Diapositiva {number}',
107
+ 'container.carousel_counter': '{current} / {total}',
108
+ 'tool.carousel_show_previous': 'Diapositiva anterior',
109
+ 'tool.carousel_show_next': 'Diapositiva siguiente',
110
+ 'tool.carousel_move_back': 'Mover atrás',
111
+ 'tool.carousel_move_forward': 'Mover adelante',
112
+ 'container.carousel_section': 'Carrusel',
113
+ 'container.carousel_controls': 'Flechas',
114
+ 'container.carousel_indicators': 'Indicadores',
115
+ 'container.carousel_fade': 'Fundido',
116
+ 'container.carousel_dark': 'Tema oscuro',
117
+ 'container.carousel_ride': 'Autoplay',
118
+ 'container.carousel_ride_no': 'No',
119
+ 'container.carousel_ride_load': 'Al cargar',
120
+ 'container.carousel_ride_interaction': 'Tras la primera interacción',
121
+ 'container.carousel_interval': 'Intervalo (s)',
122
+ 'container.carousel_pause': 'Pausa al pasar el ratón',
123
+ 'container.carousel_wrap': 'Volver al principio',
124
+ 'container.carousel_keyboard': 'Teclado',
125
+ 'container.carousel_touch': 'Táctil',
126
+ 'container.carousel_item_section': 'Diapositiva',
100
127
  'container.add_accordion': 'Acordeón',
101
128
  'container.add_accordion_item': 'Añadir apartado',
102
129
  'container.accordion_label': 'Apartado {number}',