@themarioga/grid-editor 8.2.0 → 8.4.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 (40) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +25 -1
  3. package/dist/grideditor.bundle.min.js +3 -3
  4. package/dist/grideditor.css +116 -0
  5. package/dist/grideditor.d.ts +6 -0
  6. package/dist/grideditor.esm.js +301 -5
  7. package/dist/grideditor.js +301 -5
  8. package/dist/grideditor.min.css +1 -1
  9. package/dist/grideditor.min.css.map +1 -1
  10. package/dist/grideditor.min.js +2 -2
  11. package/dist/grideditor.min.js.map +3 -3
  12. package/dist/locales/grideditor.es.esm.js +4 -0
  13. package/dist/locales/grideditor.es.js +4 -0
  14. package/dist/locales/grideditor.es.min.js +1 -1
  15. package/dist/locales/grideditor.es.min.js.map +2 -2
  16. package/dist/plugins/grideditor.ckeditor.esm.js +1 -0
  17. package/dist/plugins/grideditor.ckeditor.js +1 -0
  18. package/dist/plugins/grideditor.ckeditor.min.js +1 -1
  19. package/dist/plugins/grideditor.ckeditor.min.js.map +2 -2
  20. package/dist/plugins/grideditor.sections.esm.js +1 -0
  21. package/dist/plugins/grideditor.sections.js +1 -0
  22. package/dist/plugins/grideditor.sections.min.js +1 -1
  23. package/dist/plugins/grideditor.sections.min.js.map +2 -2
  24. package/dist/plugins/grideditor.summernote.esm.js +1 -0
  25. package/dist/plugins/grideditor.summernote.js +1 -0
  26. package/dist/plugins/grideditor.summernote.min.js +1 -1
  27. package/dist/plugins/grideditor.summernote.min.js.map +2 -2
  28. package/dist/plugins/grideditor.tinymce.esm.js +1 -0
  29. package/dist/plugins/grideditor.tinymce.js +1 -0
  30. package/dist/plugins/grideditor.tinymce.min.js +1 -1
  31. package/dist/plugins/grideditor.tinymce.min.js.map +2 -2
  32. package/docs/locale-keys.md +4 -0
  33. package/docs/plugins.md +22 -0
  34. package/package.json +1 -1
  35. package/src/js/grideditor.js +359 -4
  36. package/src/js/locales/grideditor.es.js +4 -0
  37. package/src/js/plugins/grideditor.sections.js +1 -0
  38. package/src/js/text/grideditor.text.js +1 -0
  39. package/src/less/grideditor.less +134 -0
  40. package/types/grideditor.d.ts +6 -0
@@ -445,6 +445,10 @@
445
445
  return params && params[name] !== void 0 ? params[name] : placeholder;
446
446
  });
447
447
  }
448
+ function hasString(settings, key) {
449
+ var locales = GridEditor.locales;
450
+ return (settings.locale_strings || {})[key] !== void 0 || (locales[settings.locale] || {})[key] !== void 0 || locales.en[key] !== void 0;
451
+ }
448
452
  function warn(message) {
449
453
  if (window.console && window.console.warn) {
450
454
  window.console.warn("grid-editor: " + message);
@@ -571,6 +575,12 @@
571
575
  // 'tool' for the move tool, 'drawer' for the whole drawer
572
576
  "toolbar_drag": "auto",
573
577
  // Drag the toolbar's buttons onto the canvas. 'auto' follows drag_handle
578
+ "toolbar_overflow": "menu",
579
+ // What doesn't fit on one line: 'menu' behind a button, 'wrap' onto another line
580
+ "drawer_overflow": "menu",
581
+ // The same for the drawers' tools: 'menu' behind a button, 'wrap' onto another line
582
+ "toolbar_groups": false,
583
+ // The add buttons in categories, one shown at a time, picked with tabs
574
584
  "active_target": false,
575
585
  // A click in a column makes it where the toolbar's buttons add
576
586
  "element_tools": [],
@@ -635,6 +645,13 @@
635
645
  var sourceOpen = false;
636
646
  var dropMarker = null;
637
647
  var activeTarget = null;
648
+ var toolbarLifetime = null;
649
+ var closeOverflowMenu = function() {
650
+ };
651
+ var refitToolbar = function() {
652
+ };
653
+ var addButtons = [];
654
+ var toolbarGroup = null;
638
655
  var warnedHere = {};
639
656
  var sortables = [];
640
657
  var instanceId = ++editorCounter;
@@ -662,7 +679,7 @@
662
679
  removeConfirmModal();
663
680
  removeSettingsPanels();
664
681
  removeDialog();
665
- mainControls.remove();
682
+ removeMainControls();
666
683
  createMainControls();
667
684
  reset();
668
685
  }
@@ -1031,6 +1048,7 @@
1031
1048
  htmlTextArea = element("textarea", { "class": "ge-html-output" });
1032
1049
  canvas.parentNode.insertBefore(htmlTextArea, canvas);
1033
1050
  createMainControls();
1051
+ watchDrawers();
1034
1052
  var signal = { signal: lifetime.signal };
1035
1053
  window.addEventListener("scroll", onScroll, signal);
1036
1054
  delegate(canvas, "click", ".ge-content", onContentClick, signal);
@@ -1054,6 +1072,10 @@
1054
1072
  return;
1055
1073
  }
1056
1074
  var region = closest(e.target, targetSelector());
1075
+ if (region && region === activeTarget && (e.target === region || e.target === child(region, ".ge-tools-drawer"))) {
1076
+ changeTarget(null);
1077
+ return;
1078
+ }
1057
1079
  changeTarget(region && region !== canvas && canvas.contains(region) ? region : null);
1058
1080
  }, signal);
1059
1081
  document.addEventListener("keydown", function(e) {
@@ -1079,7 +1101,14 @@
1079
1101
  mainControls = element("div", { "class": "ge-mainControls" });
1080
1102
  htmlTextArea.parentNode.insertBefore(mainControls, htmlTextArea);
1081
1103
  wrapper = mainControls.appendChild(element("div", { "class": "ge-wrapper ge-top" }));
1082
- addRowGroup = wrapper.appendChild(element("div", { "class": "ge-addRowGroup btn-group" }));
1104
+ var overflowMenu = settings.toolbar_overflow !== "wrap";
1105
+ var start = wrapper;
1106
+ if (overflowMenu) {
1107
+ addClass(wrapper, "ge-toolbar-menu");
1108
+ start = wrapper.appendChild(element("div", { "class": "ge-toolbar-start" }));
1109
+ }
1110
+ addButtons = [];
1111
+ addRowGroup = start.appendChild(element("div", { "class": "ge-addRowGroup btn-group" }));
1083
1112
  addContainerGroup = element("div", { "class": "ge-addContainerGroup btn-group ms-1" });
1084
1113
  settings.new_row_layouts.forEach(function(layout) {
1085
1114
  var grouped = !Array.isArray(layout);
@@ -1105,6 +1134,7 @@
1105
1134
  }
1106
1135
  });
1107
1136
  addRowGroup.appendChild(btn);
1137
+ addButtons.push({ button: btn, home: addRowGroup, group: "rows" });
1108
1138
  btn.appendChild(create('<i class="bi bi-plus"></i>'));
1109
1139
  var sizes = grouped ? rowColsIcon(layout) : layout;
1110
1140
  var icon = '<div class="row ge-row-icon">';
@@ -1114,7 +1144,7 @@
1114
1144
  icon += "</div>";
1115
1145
  btn.appendChild(create(icon));
1116
1146
  });
1117
- wrapper.appendChild(addContainerGroup);
1147
+ start.appendChild(addContainerGroup);
1118
1148
  Object.keys(CONTAINERS).forEach(function(type) {
1119
1149
  var definition = CONTAINERS[type];
1120
1150
  var button = labelButton(
@@ -1136,6 +1166,7 @@
1136
1166
  }, { parent: canvas, source: "tool" });
1137
1167
  });
1138
1168
  addContainerGroup.appendChild(button);
1169
+ addButtons.push({ button, home: addContainerGroup, group: toolbarGroupOf(definition.group) || "content" });
1139
1170
  });
1140
1171
  var endItems = [];
1141
1172
  Object.keys(FEATURES).forEach(function(name) {
@@ -1145,6 +1176,7 @@
1145
1176
  endItems.push(button);
1146
1177
  } else {
1147
1178
  addContainerGroup.appendChild(button);
1179
+ addButtons.push({ button, home: addContainerGroup, group: toolbarGroupOf(item.group) || name });
1148
1180
  }
1149
1181
  });
1150
1182
  });
@@ -1198,8 +1230,171 @@
1198
1230
  end.appendChild(button);
1199
1231
  });
1200
1232
  }
1233
+ if (settings.toolbar_groups) {
1234
+ createGroupTabs(start);
1235
+ }
1236
+ if (overflowMenu) {
1237
+ createOverflowMenu(start);
1238
+ }
1201
1239
  makeToolbarDraggable();
1202
1240
  }
1241
+ var CORE_GROUPS = [
1242
+ { name: "rows", labelKey: "group.rows" },
1243
+ { name: "content", labelKey: "group.content" }
1244
+ ];
1245
+ function toolbarGroupOf(value) {
1246
+ return typeof value === "string" && value.trim() !== "" ? value : null;
1247
+ }
1248
+ function createGroupTabs(start) {
1249
+ var names = CORE_GROUPS.map(function(group) {
1250
+ return group.name;
1251
+ });
1252
+ addButtons.forEach(function(entry) {
1253
+ if (names.indexOf(entry.group) < 0) {
1254
+ names.push(entry.group);
1255
+ }
1256
+ });
1257
+ names = names.filter(function(name) {
1258
+ return addButtons.some(function(entry) {
1259
+ return entry.group === name;
1260
+ });
1261
+ });
1262
+ if (names.length < 2) {
1263
+ return;
1264
+ }
1265
+ var tabs = element("div", { "class": "ge-toolbar-groups btn-group", role: "tablist", "aria-label": t("group.select") });
1266
+ start.insertBefore(tabs, start.firstChild);
1267
+ var stash = mainControls.appendChild(element("div", { "class": "ge-toolbar-stash", hidden: "hidden" }));
1268
+ names.forEach(function(name) {
1269
+ var tab = tabs.appendChild(element("button", {
1270
+ type: "button",
1271
+ "class": "btn btn-sm btn-outline-primary",
1272
+ role: "tab",
1273
+ "data-ge-group": name
1274
+ }, groupLabel(name)));
1275
+ tab.addEventListener("click", function() {
1276
+ showGroup(name);
1277
+ });
1278
+ });
1279
+ showGroup(names.indexOf(toolbarGroup) >= 0 ? toolbarGroup : names[0]);
1280
+ function showGroup(name) {
1281
+ toolbarGroup = name;
1282
+ addButtons.forEach(function(entry) {
1283
+ (entry.group === name ? entry.home : stash).appendChild(entry.button);
1284
+ });
1285
+ children(tabs).forEach(function(tab) {
1286
+ var chosen = tab.getAttribute("data-ge-group") === name;
1287
+ toggleClass(tab, "active", chosen);
1288
+ tab.setAttribute("aria-selected", chosen ? "true" : "false");
1289
+ });
1290
+ refitToolbar();
1291
+ }
1292
+ }
1293
+ function groupLabel(name) {
1294
+ var key = "group." + name;
1295
+ if (hasString(settings, key)) {
1296
+ return t(key);
1297
+ }
1298
+ var first = addButtons.filter(function(entry) {
1299
+ return entry.group === name;
1300
+ })[0];
1301
+ return first.button.getAttribute("title") || name;
1302
+ }
1303
+ function shownAddButtons() {
1304
+ return addButtons.filter(function(entry) {
1305
+ return !closest(entry.button, ".ge-toolbar-stash");
1306
+ });
1307
+ }
1308
+ function removeMainControls() {
1309
+ if (toolbarLifetime) {
1310
+ toolbarLifetime.abort();
1311
+ }
1312
+ toolbarLifetime = null;
1313
+ closeOverflowMenu = function() {
1314
+ };
1315
+ refitToolbar = function() {
1316
+ };
1317
+ mainControls.remove();
1318
+ }
1319
+ function createOverflowMenu(start) {
1320
+ var more = create('<div class="ge-toolbar-more"><button type="button" class="btn btn-sm btn-primary"><i class="bi bi-three-dots"></i></button><div class="ge-toolbar-overflow"><div class="ge-addRowGroup btn-group"></div><div class="ge-addContainerGroup btn-group"></div></div></div>');
1321
+ start.parentNode.insertBefore(more, start.nextSibling);
1322
+ var toggle2 = one(more, "button");
1323
+ var panel = one(more, ".ge-toolbar-overflow");
1324
+ var spares = all(panel, ".btn-group");
1325
+ function spareOf(home) {
1326
+ return home === addRowGroup ? spares[0] : spares[1];
1327
+ }
1328
+ toggle2.setAttribute("title", t("tool.more"));
1329
+ toggle2.setAttribute("aria-haspopup", "true");
1330
+ toggle2.setAttribute("aria-expanded", "false");
1331
+ var menuLifetime = toolbarLifetime = new AbortController();
1332
+ var signal = { signal: menuLifetime.signal };
1333
+ toggle2.addEventListener("click", function() {
1334
+ openOverflow(!hasClass(more, "ge-open"));
1335
+ });
1336
+ panel.addEventListener("click", function(e) {
1337
+ if (closest(e.target, "[data-ge-toolbar]")) {
1338
+ openOverflow(false);
1339
+ }
1340
+ });
1341
+ document.addEventListener("pointerdown", function(e) {
1342
+ if (!more.contains(e.target)) {
1343
+ openOverflow(false);
1344
+ }
1345
+ }, signal);
1346
+ document.addEventListener("keydown", function(e) {
1347
+ if (e.key === "Escape") {
1348
+ openOverflow(false);
1349
+ }
1350
+ }, signal);
1351
+ closeOverflowMenu = function() {
1352
+ openOverflow(false);
1353
+ };
1354
+ refitToolbar = fit;
1355
+ fit();
1356
+ if (window.ResizeObserver) {
1357
+ var pending = false;
1358
+ var observer = new window.ResizeObserver(function() {
1359
+ if (pending) {
1360
+ return;
1361
+ }
1362
+ pending = true;
1363
+ window.requestAnimationFrame(function() {
1364
+ pending = false;
1365
+ if (!menuLifetime.signal.aborted) {
1366
+ fit();
1367
+ }
1368
+ });
1369
+ });
1370
+ observer.observe(wrapper);
1371
+ observer.observe(start);
1372
+ menuLifetime.signal.addEventListener("abort", function() {
1373
+ observer.disconnect();
1374
+ });
1375
+ }
1376
+ function openOverflow(open) {
1377
+ open = open && hasClass(more, "ge-needed");
1378
+ toggleClass(more, "ge-open", open);
1379
+ toggle2.setAttribute("aria-expanded", open ? "true" : "false");
1380
+ }
1381
+ function fit() {
1382
+ var homes = shownAddButtons();
1383
+ homes.forEach(function(entry) {
1384
+ entry.home.appendChild(entry.button);
1385
+ });
1386
+ removeClass(more, "ge-needed");
1387
+ if (start.scrollWidth <= start.clientWidth) {
1388
+ openOverflow(false);
1389
+ return;
1390
+ }
1391
+ addClass(more, "ge-needed");
1392
+ for (var i = homes.length - 1; i >= 0 && start.scrollWidth > start.clientWidth; i--) {
1393
+ var into = spareOf(homes[i].home);
1394
+ into.insertBefore(homes[i].button, into.firstChild);
1395
+ }
1396
+ }
1397
+ }
1203
1398
  function labelButton(button, label, iconClass) {
1204
1399
  button.setAttribute("title", label);
1205
1400
  if (iconClass) {
@@ -1274,6 +1469,7 @@
1274
1469
  }
1275
1470
  helper = addClass(button.cloneNode(true), "ge-toolbar-helper");
1276
1471
  document.body.appendChild(helper);
1472
+ closeOverflowMenu();
1277
1473
  addClass(canvas, "ge-dropping");
1278
1474
  }
1279
1475
  css(helper, { left: move.pageX - 14, top: move.pageY - 14 });
@@ -1755,7 +1951,7 @@
1755
1951
  removeConfirmModal();
1756
1952
  removeSettingsPanels();
1757
1953
  removeDialog();
1758
- mainControls.remove();
1954
+ removeMainControls();
1759
1955
  htmlTextArea.remove();
1760
1956
  lifetime.abort();
1761
1957
  instances.delete(canvas);
@@ -2722,6 +2918,102 @@
2722
2918
  }
2723
2919
  return createTool(drawer, t("tool.move"), "ge-move", "bi bi-arrows-move");
2724
2920
  }
2921
+ var FITTED_DRAWERS = ".ge-tools-drawer:not(.ge-text-drawer):not(.ge-pane-drawer):not(.ge-code-inline)";
2922
+ function watchDrawers() {
2923
+ if (settings.drawer_overflow === "wrap" || !window.ResizeObserver || !window.MutationObserver) {
2924
+ return;
2925
+ }
2926
+ var due = /* @__PURE__ */ new Set();
2927
+ var frame = null;
2928
+ function schedule(drawer) {
2929
+ due.add(drawer);
2930
+ if (frame === null) {
2931
+ frame = window.requestAnimationFrame(flush);
2932
+ }
2933
+ }
2934
+ function flush() {
2935
+ frame = null;
2936
+ var drawers = Array.from(due);
2937
+ due.clear();
2938
+ drawers.forEach(function(drawer) {
2939
+ if (!drawer.isConnected) {
2940
+ drawerResizes.unobserve(drawer);
2941
+ return;
2942
+ }
2943
+ fitDrawer(drawer);
2944
+ });
2945
+ }
2946
+ var drawerResizes = new window.ResizeObserver(function(entries) {
2947
+ entries.forEach(function(entry) {
2948
+ schedule(entry.target);
2949
+ });
2950
+ });
2951
+ var mutations = new window.MutationObserver(function(records) {
2952
+ records.forEach(function(record) {
2953
+ var target = record.target;
2954
+ if (record.type === "attributes") {
2955
+ var parent = target.parentNode;
2956
+ if (parent && parent.nodeType === 1 && parent.matches(FITTED_DRAWERS)) {
2957
+ schedule(parent);
2958
+ }
2959
+ return;
2960
+ }
2961
+ if (target.nodeType === 1 && target.matches(FITTED_DRAWERS)) {
2962
+ schedule(target);
2963
+ return;
2964
+ }
2965
+ record.addedNodes.forEach(function(node) {
2966
+ if (node.nodeType !== 1) {
2967
+ return;
2968
+ }
2969
+ selfAndAll(node, FITTED_DRAWERS).forEach(function(drawer) {
2970
+ addClass(drawer, "ge-drawer-fit");
2971
+ drawerResizes.observe(drawer);
2972
+ schedule(drawer);
2973
+ });
2974
+ });
2975
+ });
2976
+ });
2977
+ mutations.observe(canvas, { childList: true, subtree: true, attributes: true, attributeFilter: ["style"] });
2978
+ lifetime.signal.addEventListener("abort", function() {
2979
+ mutations.disconnect();
2980
+ drawerResizes.disconnect();
2981
+ if (frame !== null) {
2982
+ window.cancelAnimationFrame(frame);
2983
+ }
2984
+ });
2985
+ }
2986
+ function fitDrawer(drawer) {
2987
+ var tools = children(drawer, "a").filter(function(tool) {
2988
+ return !hasClass(tool, "ge-drawer-more");
2989
+ });
2990
+ var expanded = hasClass(drawer, "ge-drawer-expanded");
2991
+ removeClass(drawer, "ge-drawer-overflow ge-drawer-expanded");
2992
+ tools.forEach(function(tool) {
2993
+ removeClass(tool, "ge-tool-overflow");
2994
+ });
2995
+ if (!drawerOverflows(drawer, tools)) {
2996
+ return;
2997
+ }
2998
+ addClass(drawer, "ge-drawer-overflow");
2999
+ if (!child(drawer, ".ge-drawer-more")) {
3000
+ createTool(drawer, t("tool.more"), "ge-drawer-more", "bi bi-three-dots", function() {
3001
+ toggleClass(drawer, "ge-drawer-expanded");
3002
+ });
3003
+ }
3004
+ for (var i = tools.length - 1; i >= 0 && drawerOverflows(drawer, tools); i--) {
3005
+ addClass(tools[i], "ge-tool-overflow");
3006
+ }
3007
+ toggleClass(drawer, "ge-drawer-expanded", expanded);
3008
+ }
3009
+ function drawerOverflows(drawer, tools) {
3010
+ var style = window.getComputedStyle(drawer);
3011
+ var limit = drawer.getBoundingClientRect().right - parseFloat(style.borderRightWidth) - parseFloat(style.paddingRight);
3012
+ return tools.some(function(tool) {
3013
+ var rects = tool.getClientRects();
3014
+ return rects.length > 0 && rects[0].right > limit + 0.5;
3015
+ });
3016
+ }
2725
3017
  function createTool(drawer, title, className, iconClass, eventHandlers) {
2726
3018
  var tool = element("a", { title, "class": className });
2727
3019
  tool.appendChild(element("i", { "class": iconClass }));
@@ -4221,7 +4513,7 @@
4221
4513
  GridEditor._plainHtml = plainHtml;
4222
4514
  GridEditor.Sortable = null;
4223
4515
  GridEditor.bootstrap = null;
4224
- GridEditor.version = false ? "dev" : "8.2.0";
4516
+ GridEditor.version = false ? "dev" : "8.4.0";
4225
4517
  GridEditor.locales = {
4226
4518
  en: {
4227
4519
  "tool.move": "Move",
@@ -4246,6 +4538,10 @@
4246
4538
  "tool.indent_increase": "Increase indent\n(hold shift for max)",
4247
4539
  "tool.edit_source": "Edit Source Code",
4248
4540
  "tool.preview": "Preview",
4541
+ "tool.more": "More",
4542
+ "group.rows": "Rows",
4543
+ "group.content": "Content",
4544
+ "group.select": "Add",
4249
4545
  "panel.title": "{kind} settings",
4250
4546
  "panel.close": "Close",
4251
4547
  "panel.done": "Done",