@themarioga/grid-editor 8.8.2 → 8.10.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.
@@ -329,9 +329,23 @@
329
329
  getUtility: { value: true },
330
330
  setUtility: { value: true },
331
331
  getActiveTarget: { value: true },
332
- setActiveTarget: {}
332
+ setActiveTarget: {},
333
+ getSelected: { value: true },
334
+ setSelected: {}
333
335
  };
334
336
  var PLACEMENTS = ["appendTo", "prependTo", "insertAfter", "insertBefore"];
337
+ var REFERENCES = [
338
+ "data-bs-target",
339
+ "data-bs-parent",
340
+ "href",
341
+ "aria-controls",
342
+ "aria-labelledby",
343
+ "aria-describedby",
344
+ "for",
345
+ "data-ge-popup-id",
346
+ "data-ge-popup-target"
347
+ ];
348
+ var GENERATED_ID = /^ge-([a-z][a-z-]*?)-\d+-[a-z0-9]+$/;
335
349
  var BREAKPOINTS = [
336
350
  { key: "xs", infix: "", colPrefix: "col-", offsetPrefix: "offset-", min: 0, preview: 400, labelKey: "view.xs" },
337
351
  { key: "sm", infix: "sm", colPrefix: "col-sm-", offsetPrefix: "offset-sm-", min: 576, preview: 576, labelKey: "view.sm" },
@@ -413,6 +427,10 @@
413
427
  tools: true
414
428
  // The indent tools in the column's drawer
415
429
  },
430
+ sidebar: {
431
+ empty: null
432
+ // function(ge) -> { title, body } shown while nothing is selected, or null for the message
433
+ },
416
434
  drag: {
417
435
  delay: 0,
418
436
  // Milliseconds to hold before a drag starts
@@ -429,6 +447,8 @@
429
447
  var warned = {};
430
448
  var editorCounter = 0;
431
449
  var instances = /* @__PURE__ */ new WeakMap();
450
+ var sidebarHolder = null;
451
+ var EDITOR_CONTROLS = ".ge-mainControls, .ge-settings-panel, .ge-sidebar-toggle, .ge-dialog, .ge-confirm, .ge-size-picker, .modal, .modal-backdrop";
432
452
  function translate(settings, key, params) {
433
453
  var locales = GridEditor.locales;
434
454
  var locale = locales[settings.locale] || {};
@@ -634,7 +654,9 @@
634
654
  "confirm_delete": true,
635
655
  // Ask before deleting a row or a column
636
656
  "settings_panel": "offcanvas",
637
- // Where a node's settings open: 'offcanvas', 'popover', 'modal' or 'inline'
657
+ // Where a node's settings open: 'offcanvas', 'popover', 'modal', 'inline' or 'sidebar'
658
+ "sidebar": NESTED_SETTINGS.sidebar,
659
+ // The 'sidebar' panel: what it shows while nothing is selected
638
660
  "drag": NESTED_SETTINGS.drag
639
661
  // How a drag behaves, whatever drives it
640
662
  }, optionsOrMethod);
@@ -660,6 +682,17 @@
660
682
  var sortables = [];
661
683
  var instanceId = ++editorCounter;
662
684
  var destroyed = false;
685
+ var selected = null;
686
+ var sidebarCollapsed = null;
687
+ var pluginHandle = null;
688
+ if (settings.settings_panel === "sidebar") {
689
+ if (sidebarHolder) {
690
+ warnOnceHere("sidebar", 'settings_panel "sidebar" is in use by another editor on the page, which has one sidebar: using offcanvas');
691
+ settings.settings_panel = "offcanvas";
692
+ } else {
693
+ sidebarHolder = instance;
694
+ }
695
+ }
663
696
  var detailsFor = /* @__PURE__ */ new WeakMap();
664
697
  var moves = /* @__PURE__ */ new WeakMap();
665
698
  var resizes = /* @__PURE__ */ new WeakMap();
@@ -1097,7 +1130,8 @@
1097
1130
  e.preventDefault();
1098
1131
  }
1099
1132
  }, signal);
1100
- if (settings.active_target) {
1133
+ var sidebarMode = panelMode() === "sidebar";
1134
+ if (settings.active_target || sidebarMode) {
1101
1135
  var pressed = null;
1102
1136
  canvas.addEventListener("pointerdown", function(e) {
1103
1137
  pressed = { x: e.clientX, y: e.clientY };
@@ -1111,23 +1145,60 @@
1111
1145
  if (from && Math.abs(e.clientX - from.x) + Math.abs(e.clientY - from.y) > settings.drag.threshold) {
1112
1146
  return;
1113
1147
  }
1114
- var region = closest(e.target, targetSelector());
1115
- if (region && region === activeTarget && (e.target === region || e.target === child(region, ".ge-tools-drawer"))) {
1116
- changeTarget(null);
1117
- return;
1148
+ if (settings.active_target) {
1149
+ clickTarget(e);
1150
+ }
1151
+ if (sidebarMode && canvas.contains(e.target)) {
1152
+ changeSelection(settingsNodeAt(e.target));
1118
1153
  }
1119
- changeTarget(region && region !== canvas && canvas.contains(region) ? region : null);
1120
1154
  }, signal);
1121
1155
  document.addEventListener("keydown", function(e) {
1122
- if (e.key !== "Escape" || !activeTarget || openSettingsState || dialogState) {
1156
+ if (e.key !== "Escape" || openSettingsState || dialogState) {
1157
+ return;
1158
+ }
1159
+ if (confirmDialog && hasClass(confirmDialog, "show")) {
1123
1160
  return;
1124
1161
  }
1125
1162
  var focus = document.activeElement;
1126
1163
  if (focus && (is(focus, "input, textarea, select") || focus.isContentEditable)) {
1127
1164
  return;
1128
1165
  }
1129
- changeTarget(null);
1166
+ if (selected && isEditing()) {
1167
+ changeSelection(null);
1168
+ } else if (activeTarget) {
1169
+ changeTarget(null);
1170
+ }
1171
+ }, signal);
1172
+ }
1173
+ if (sidebarMode) {
1174
+ canvas.addEventListener("focusin", function(e) {
1175
+ var node = isEditing() ? settingsNodeAt(e.target) : null;
1176
+ if (node) {
1177
+ changeSelection(node);
1178
+ }
1179
+ }, signal);
1180
+ document.addEventListener("click", function(e) {
1181
+ var target = e.target;
1182
+ if (!selected || !isEditing() || !target || target.nodeType !== 1) {
1183
+ return;
1184
+ }
1185
+ if (!attached(target) || canvas.contains(target)) {
1186
+ return;
1187
+ }
1188
+ if (closest(target, EDITOR_CONTROLS) || canvas.querySelector(".ge-rte-active")) {
1189
+ return;
1190
+ }
1191
+ changeSelection(null);
1130
1192
  }, signal);
1193
+ window.addEventListener("resize", reserveSidebarRoom, signal);
1194
+ }
1195
+ function clickTarget(e) {
1196
+ var region = closest(e.target, targetSelector());
1197
+ if (region && region === activeTarget && (e.target === region || e.target === child(region, ".ge-tools-drawer"))) {
1198
+ changeTarget(null);
1199
+ return;
1200
+ }
1201
+ changeTarget(region && region !== canvas && canvas.contains(region) ? region : null);
1131
1202
  }
1132
1203
  }
1133
1204
  function textReady(block) {
@@ -1899,6 +1970,7 @@
1899
1970
  function openSource() {
1900
1971
  deinit();
1901
1972
  changeTarget(null);
1973
+ changeSelection(null);
1902
1974
  htmlTextArea.style.height = 0.8 * document.documentElement.clientHeight + "px";
1903
1975
  htmlTextArea.value = canvas.innerHTML;
1904
1976
  show(htmlTextArea);
@@ -1944,6 +2016,9 @@
1944
2016
  if (openSettingsState && !attached(openSettingsState.node)) {
1945
2017
  closeSettings();
1946
2018
  }
2019
+ if (selected && !canvas.contains(selected)) {
2020
+ changeSelection(null);
2021
+ }
1947
2022
  if (dialogState && dialogState.home && !attached(dialogState.home)) {
1948
2023
  closeDialog();
1949
2024
  }
@@ -1968,9 +2043,11 @@
1968
2043
  } else if (activeTarget) {
1969
2044
  addClass(activeTarget, "ge-active-target");
1970
2045
  }
2046
+ showSidebar();
1971
2047
  }
1972
2048
  function deinit() {
1973
2049
  closeSettings();
2050
+ hideSidebar();
1974
2051
  removeClass(canvas, "ge-editing ge-drag-drawer ge-dropping");
1975
2052
  if (activeTarget) {
1976
2053
  removeClass(activeTarget, "ge-active-target");
@@ -2131,6 +2208,10 @@
2131
2208
  }
2132
2209
  deinit();
2133
2210
  activeTarget = null;
2211
+ selected = null;
2212
+ if (sidebarHolder === instance) {
2213
+ sidebarHolder = null;
2214
+ }
2134
2215
  removeConfirmModal();
2135
2216
  removeSettingsPanels();
2136
2217
  removeDialog();
@@ -2141,7 +2222,7 @@
2141
2222
  destroyed = true;
2142
2223
  }
2143
2224
  function loadPlugins() {
2144
- var api = pluginApi();
2225
+ var api = pluginHandle = pluginApi();
2145
2226
  registerFamily("grid", {}, widthFamily());
2146
2227
  if (settings.row_cols !== false) {
2147
2228
  registerFamily("grid", {}, rowColsFamily());
@@ -2201,6 +2282,7 @@
2201
2282
  t,
2202
2283
  warn,
2203
2284
  containerId,
2285
+ freshNode,
2204
2286
  defaultRegion,
2205
2287
  createTool,
2206
2288
  createMoveTool,
@@ -2738,6 +2820,63 @@
2738
2820
  containerCounter++;
2739
2821
  return "ge-" + type + "-" + containerCounter + "-" + Math.random().toString(36).slice(2, 6);
2740
2822
  }
2823
+ function freshNode(html) {
2824
+ var node = create(html);
2825
+ var renamed = {};
2826
+ var taken = function(id) {
2827
+ return !!document.getElementById(id) || Object.keys(renamed).some(function(old) {
2828
+ return renamed[old] === id;
2829
+ });
2830
+ };
2831
+ selfAndAll(node, "[id]").forEach(function(element2) {
2832
+ var id = element2.id;
2833
+ if (!document.getElementById(id)) {
2834
+ return;
2835
+ }
2836
+ var generated = GENERATED_ID.exec(id);
2837
+ var next;
2838
+ if (generated) {
2839
+ do {
2840
+ next = containerId(generated[1]);
2841
+ } while (taken(next));
2842
+ } else {
2843
+ var n = 2;
2844
+ while (taken(id + "-" + n)) {
2845
+ n++;
2846
+ }
2847
+ next = id + "-" + n;
2848
+ }
2849
+ renamed[id] = next;
2850
+ element2.id = next;
2851
+ });
2852
+ if (!Object.keys(renamed).length) {
2853
+ return node;
2854
+ }
2855
+ selfAndAll(node, "*").forEach(function(element2) {
2856
+ REFERENCES.forEach(function(name) {
2857
+ var value = element2.getAttribute(name);
2858
+ if (value === null) {
2859
+ return;
2860
+ }
2861
+ if (name === "href" && value.charAt(0) !== "#") {
2862
+ return;
2863
+ }
2864
+ var rewritten = value.split(/(\s+)/).map(function(token) {
2865
+ if (renamed[token]) {
2866
+ return renamed[token];
2867
+ }
2868
+ if (token.charAt(0) === "#" && renamed[token.slice(1)]) {
2869
+ return "#" + renamed[token.slice(1)];
2870
+ }
2871
+ return token;
2872
+ }).join("");
2873
+ if (rewritten !== value) {
2874
+ element2.setAttribute(name, rewritten);
2875
+ }
2876
+ });
2877
+ });
2878
+ return node;
2879
+ }
2741
2880
  function defaultRegion() {
2742
2881
  var row = createRow();
2743
2882
  row.appendChild(createColumn(MAX_COL_SIZE));
@@ -3262,9 +3401,11 @@
3262
3401
  function addSettingsTool(drawer, node, presets) {
3263
3402
  var details = createDetails(node, presets || []);
3264
3403
  detailsFor.set(node, details);
3265
- createTool(drawer, t("tool.settings"), "ge-settings", "bi bi-gear-fill", function() {
3266
- toggleSettings(node, details, this);
3267
- });
3404
+ if (panelMode() !== "sidebar") {
3405
+ createTool(drawer, t("tool.settings"), "ge-settings", "bi bi-gear-fill", function() {
3406
+ toggleSettings(node, details, this);
3407
+ });
3408
+ }
3268
3409
  var kind = kindOf(node);
3269
3410
  Object.keys(UTILITIES).forEach(function(name) {
3270
3411
  if (UTILITIES[name].drawerTools) {
@@ -3355,7 +3496,7 @@
3355
3496
  return;
3356
3497
  }
3357
3498
  var holder = element("div", { "class": "ge-panel-section", "data-ge-plugin": name });
3358
- if (mode === "offcanvas" || mode === "modal") {
3499
+ if (mode === "offcanvas" || mode === "modal" || mode === "sidebar") {
3359
3500
  holder.appendChild(sectionTitle(t(section.labelKey)));
3360
3501
  holder.appendChild(section.body);
3361
3502
  } else {
@@ -3379,7 +3520,7 @@
3379
3520
  });
3380
3521
  return sections;
3381
3522
  }
3382
- var PANEL_MODES = ["offcanvas", "popover", "modal", "inline"];
3523
+ var PANEL_MODES = ["offcanvas", "popover", "modal", "inline", "sidebar"];
3383
3524
  var settingsPanels = {};
3384
3525
  var openSettingsState = null;
3385
3526
  var modalState = /* @__PURE__ */ new WeakMap();
@@ -3394,7 +3535,14 @@
3394
3535
  return node && detailsFor.get(node) || null;
3395
3536
  }
3396
3537
  function settingsScope() {
3397
- return openSettingsState && openSettingsState.mode !== "inline" ? [canvas, openSettingsState.details] : [canvas];
3538
+ var scope = [canvas];
3539
+ if (openSettingsState && openSettingsState.mode !== "inline") {
3540
+ scope.push(openSettingsState.details);
3541
+ }
3542
+ if (sidebarShown) {
3543
+ scope.push(sidebarShown.details);
3544
+ }
3545
+ return scope;
3398
3546
  }
3399
3547
  function toggleSettings(node, details, gear) {
3400
3548
  var mode = panelMode();
@@ -3484,6 +3632,9 @@
3484
3632
  } else {
3485
3633
  hideModal(panel);
3486
3634
  }
3635
+ returnPanel(open);
3636
+ }
3637
+ function returnPanel(open) {
3487
3638
  removeClass(open.node, "ge-settings-target");
3488
3639
  open.details.style.removeProperty("display");
3489
3640
  dropEmptyStyle(open.details);
@@ -3516,6 +3667,11 @@
3516
3667
  panel = create('<div class="popover bs-popover-bottom ge-settings-panel ge-settings-popover" role="dialog"><div class="popover-arrow"></div><div class="popover-header"><span class="ge-settings-title"></span></div><div class="popover-body ge-settings-body"></div></div>');
3517
3668
  one(panel, ".popover-header").appendChild(closeButton());
3518
3669
  hide(panel);
3670
+ } else if (mode === "sidebar") {
3671
+ panel = create('<div class="offcanvas offcanvas-end ge-settings-panel ge-settings-sidebar" tabindex="-1" role="complementary"><div class="offcanvas-header"><h5 class="offcanvas-title ge-settings-title"></h5></div><div class="offcanvas-body ge-settings-body"></div></div>');
3672
+ panel.id = "ge-settings-sidebar-" + instanceId;
3673
+ one(panel, ".offcanvas-header").appendChild(closeButton());
3674
+ settingsPanels["sidebar-toggle"] = document.body.appendChild(sidebarToggle(panel));
3519
3675
  } else {
3520
3676
  panel = create('<div class="modal fade ge-settings-panel ge-settings-modal" tabindex="-1" role="dialog" aria-hidden="true"><div class="modal-dialog modal-dialog-centered modal-dialog-scrollable"><div class="modal-content"><div class="modal-header"><h5 class="modal-title ge-settings-title"></h5></div><div class="modal-body ge-settings-body"></div><div class="modal-footer"></div></div></div></div>');
3521
3677
  one(panel, ".modal-header").appendChild(closeButton());
@@ -3526,13 +3682,19 @@
3526
3682
  }
3527
3683
  delegate(panel, "click", ".ge-settings-close", function(e) {
3528
3684
  e.preventDefault();
3529
- closeSettings();
3685
+ if (mode === "sidebar") {
3686
+ changeSelection(null);
3687
+ } else {
3688
+ closeSettings();
3689
+ }
3530
3690
  });
3531
3691
  settingsPanels[mode] = document.body.appendChild(panel);
3532
3692
  return panel;
3533
3693
  }
3534
3694
  function removeSettingsPanels() {
3535
3695
  closeSettings();
3696
+ unshowSidebar();
3697
+ removeClass(document.documentElement, "ge-sidebar-open");
3536
3698
  Object.keys(settingsPanels).forEach(function(mode) {
3537
3699
  if (mode === "modal") {
3538
3700
  retireModal(settingsPanels[mode]);
@@ -3545,6 +3707,180 @@
3545
3707
  });
3546
3708
  settingsPanels = {};
3547
3709
  }
3710
+ var SIDEBAR_MIN_WIDTH = 576;
3711
+ var sidebarShown = null;
3712
+ var sidebarEmpty = null;
3713
+ function isEditing() {
3714
+ return hasClass(canvas, "ge-editing");
3715
+ }
3716
+ function sidebarToggle(panel) {
3717
+ var button = element("button", { type: "button", "class": "ge-sidebar-toggle", "aria-controls": panel.id });
3718
+ button.appendChild(element("i"));
3719
+ button.addEventListener("click", function() {
3720
+ foldSidebar(!sidebarCollapsed);
3721
+ });
3722
+ return button;
3723
+ }
3724
+ function foldSidebar(collapsed) {
3725
+ sidebarCollapsed = collapsed;
3726
+ applySidebar();
3727
+ }
3728
+ function applySidebar() {
3729
+ var panel = settingsPanels.sidebar;
3730
+ var toggle2 = settingsPanels["sidebar-toggle"];
3731
+ if (!panel) {
3732
+ return;
3733
+ }
3734
+ var open = !sidebarCollapsed;
3735
+ if (open && !hasClass(panel, "show")) {
3736
+ removeClass(panel, "hiding");
3737
+ panel.getBoundingClientRect();
3738
+ addClass(panel, "show");
3739
+ } else if (!open && hasClass(panel, "show")) {
3740
+ removeClass(panel, "show");
3741
+ addClass(panel, "hiding");
3742
+ window.setTimeout(function() {
3743
+ removeClass(panel, "hiding");
3744
+ }, 300);
3745
+ }
3746
+ var label = open ? t("panel.collapse") : t("panel.expand");
3747
+ toggle2.setAttribute("aria-expanded", open ? "true" : "false");
3748
+ toggle2.setAttribute("aria-label", label);
3749
+ toggle2.setAttribute("title", label);
3750
+ one(toggle2, "i").className = "bi " + (open ? "bi-chevron-right" : "bi-chevron-left");
3751
+ reserveSidebarRoom();
3752
+ }
3753
+ function reserveSidebarRoom() {
3754
+ toggleClass(
3755
+ document.documentElement,
3756
+ "ge-sidebar-open",
3757
+ !!settingsPanels.sidebar && isEditing() && !sidebarCollapsed && window.innerWidth >= SIDEBAR_MIN_WIDTH
3758
+ );
3759
+ }
3760
+ function showSidebar() {
3761
+ if (panelMode() !== "sidebar") {
3762
+ return;
3763
+ }
3764
+ var panel = settingsPanel("sidebar");
3765
+ if (sidebarCollapsed === null) {
3766
+ sidebarCollapsed = window.innerWidth < SIDEBAR_MIN_WIDTH;
3767
+ }
3768
+ panel.style.removeProperty("display");
3769
+ settingsPanels["sidebar-toggle"].style.removeProperty("display");
3770
+ renderSidebar();
3771
+ applySidebar();
3772
+ }
3773
+ function hideSidebar() {
3774
+ unshowDetails();
3775
+ var panel = settingsPanels.sidebar;
3776
+ if (!panel) {
3777
+ return;
3778
+ }
3779
+ panel.style.display = "none";
3780
+ settingsPanels["sidebar-toggle"].style.display = "none";
3781
+ removeClass(document.documentElement, "ge-sidebar-open");
3782
+ }
3783
+ function setSidebarTitle(text) {
3784
+ var panel = settingsPanels.sidebar;
3785
+ one(panel, ".ge-settings-title").textContent = text;
3786
+ panel.setAttribute("aria-label", text);
3787
+ }
3788
+ function unshowDetails() {
3789
+ var shown = sidebarShown;
3790
+ sidebarShown = null;
3791
+ if (shown) {
3792
+ returnPanel(shown);
3793
+ }
3794
+ }
3795
+ function unshowSidebar() {
3796
+ unshowDetails();
3797
+ if (sidebarEmpty) {
3798
+ sidebarEmpty.body.remove();
3799
+ sidebarEmpty = null;
3800
+ }
3801
+ }
3802
+ function renderSidebar() {
3803
+ var panel = settingsPanels.sidebar;
3804
+ if (!panel || !isEditing()) {
3805
+ return;
3806
+ }
3807
+ var details = selected ? detailsOf(selected) : null;
3808
+ if (details ? sidebarShown && sidebarShown.details === details : !sidebarShown && sidebarEmpty) {
3809
+ return;
3810
+ }
3811
+ unshowSidebar();
3812
+ var holder = one(panel, ".ge-settings-body");
3813
+ if (!details) {
3814
+ var content = emptyContent();
3815
+ var body = content ? content.body : element("p", { "class": "ge-sidebar-empty" }, t("panel.sidebar_empty"));
3816
+ setSidebarTitle(content ? content.title : t("panel.sidebar_title"));
3817
+ holder.appendChild(body);
3818
+ sidebarEmpty = { body };
3819
+ return;
3820
+ }
3821
+ sidebarShown = { node: selected, details, home: details.parentElement, next: details.nextElementSibling };
3822
+ setSidebarTitle(t("panel.title", { kind: kindLabel(selected) }));
3823
+ holder.appendChild(details);
3824
+ show(details);
3825
+ addClass(selected, "ge-settings-target");
3826
+ }
3827
+ function emptyContent() {
3828
+ var fromHost = settings.sidebar.empty;
3829
+ var found = null;
3830
+ if (typeof fromHost === "function") {
3831
+ found = emptyContentOf(fromHost(instance), function(result) {
3832
+ return result.title;
3833
+ });
3834
+ } else if (fromHost !== null && fromHost !== void 0) {
3835
+ warnOnceHere("sidebar.empty", "sidebar.empty is a function(ge) returning { title, body }, not " + typeof fromHost + ": ignored");
3836
+ }
3837
+ [CONTAINERS, FEATURES, UTILITIES].forEach(function(registry) {
3838
+ Object.keys(registry).forEach(function(name) {
3839
+ var plugin = registry[name];
3840
+ if (found || !plugin.sidebarEmpty) {
3841
+ return;
3842
+ }
3843
+ found = emptyContentOf(plugin.sidebarEmpty(pluginHandle), function(result) {
3844
+ return typeof result.titleKey === "string" && result.titleKey !== "" ? t(result.titleKey) : "";
3845
+ });
3846
+ });
3847
+ });
3848
+ return found;
3849
+ }
3850
+ function emptyContentOf(result, titleOf) {
3851
+ if (!result || !result.body || result.body.nodeType !== 1) {
3852
+ return null;
3853
+ }
3854
+ var title = titleOf(result);
3855
+ return { title: typeof title === "string" && title !== "" ? title : t("panel.sidebar_title"), body: result.body };
3856
+ }
3857
+ function settingsNodeAt(target) {
3858
+ var drawer = closest(target, ".ge-tools-drawer", canvas);
3859
+ if (drawer) {
3860
+ var home = drawer.parentElement;
3861
+ var owner = detailsFor.has(home) ? home : children(home).filter(function(each) {
3862
+ return detailsFor.has(each);
3863
+ })[0];
3864
+ if (owner) {
3865
+ return owner;
3866
+ }
3867
+ }
3868
+ for (var node = target; node && node !== canvas; node = node.parentElement) {
3869
+ if (detailsFor.has(node)) {
3870
+ return node;
3871
+ }
3872
+ }
3873
+ return null;
3874
+ }
3875
+ function changeSelection(node) {
3876
+ if (node === selected) {
3877
+ return;
3878
+ }
3879
+ var from = selected;
3880
+ selected = node;
3881
+ renderSidebar();
3882
+ emit("selection-change", { canvas, node, from });
3883
+ }
3548
3884
  function placePopover(panel, gear) {
3549
3885
  if (!attached(gear)) {
3550
3886
  return;
@@ -4659,6 +4995,23 @@
4659
4995
  }
4660
4996
  changeTarget(node);
4661
4997
  }
4998
+ function apiSetSelected(value) {
4999
+ if (panelMode() !== "sidebar") {
5000
+ warnOnceHere("sidebar-api", 'setSelected needs settings_panel "sidebar": without it, it does nothing');
5001
+ return;
5002
+ }
5003
+ if (value === null || value === void 0) {
5004
+ changeSelection(null);
5005
+ return;
5006
+ }
5007
+ var node = nodeFrom(value);
5008
+ if (!node || node === canvas || !canvas.contains(node) || !detailsFor.has(node)) {
5009
+ var named = typeof value === "string" ? value : node ? "<" + node.tagName.toLowerCase() + ">" : String(value);
5010
+ warn("setSelected: " + named + " is not a node of the canvas with settings");
5011
+ return;
5012
+ }
5013
+ changeSelection(node);
5014
+ }
4662
5015
  var own = {
4663
5016
  getHtml,
4664
5017
  getPlainHtml,
@@ -4697,7 +5050,11 @@
4697
5050
  getActiveTarget: function() {
4698
5051
  return settings.active_target ? activeTarget : null;
4699
5052
  },
4700
- setActiveTarget: apiSetActiveTarget
5053
+ setActiveTarget: apiSetActiveTarget,
5054
+ getSelected: function() {
5055
+ return panelMode() === "sidebar" ? selected : null;
5056
+ },
5057
+ setSelected: apiSetSelected
4701
5058
  };
4702
5059
  Object.keys(own).forEach(function(name) {
4703
5060
  var value = !!(METHODS[name] && METHODS[name].value);
@@ -4748,7 +5105,7 @@
4748
5105
  GridEditor._plainHtml = plainHtml;
4749
5106
  GridEditor.Sortable = null;
4750
5107
  GridEditor.bootstrap = null;
4751
- GridEditor.version = false ? "dev" : "8.8.2";
5108
+ GridEditor.version = false ? "dev" : "8.10.0";
4752
5109
  GridEditor.locales = {
4753
5110
  en: {
4754
5111
  "tool.move": "Move",
@@ -4781,6 +5138,10 @@
4781
5138
  "panel.title": "{kind} settings",
4782
5139
  "panel.close": "Close",
4783
5140
  "panel.done": "Done",
5141
+ "panel.sidebar_title": "Settings",
5142
+ "panel.sidebar_empty": "Click an element to see its settings",
5143
+ "panel.collapse": "Hide settings",
5144
+ "panel.expand": "Show settings",
4784
5145
  "panel.id": "Id",
4785
5146
  "panel.classes": "Classes",
4786
5147
  "panel.section_general": "Id and classes",