@innovastudio/contentbox 1.6.204 → 1.6.205

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@innovastudio/contentbox",
4
- "version": "1.6.204",
4
+ "version": "1.6.205",
5
5
  "description": "",
6
6
  "main": "public/contentbox/contentbox.esm.js",
7
7
  "types": "index.d.ts",
@@ -73,7 +73,7 @@
73
73
  "ws": "^8.13.0"
74
74
  },
75
75
  "dependencies": {
76
- "@innovastudio/contentbuilder": "^1.5.222",
76
+ "@innovastudio/contentbuilder": "^1.5.223",
77
77
  "js-beautify": "^1.14.0",
78
78
  "marked": "^17.0.0",
79
79
  "sortablejs": "^1.15.2"
@@ -19517,7 +19517,7 @@ class PanelIcon {
19517
19517
  <button title="${out('Color')}" class="btn-color is-btn-color"></button>
19518
19518
  </div>
19519
19519
 
19520
- <div class="label">${out('Icon Size')}:</div>
19520
+ <div class="label label-iconsize">${out('Icon Size')}:</div>
19521
19521
 
19522
19522
  <div role="group" aria-label="${out('Font Size')}" class="group fontsizes">
19523
19523
  ${fontSizeHtml}
@@ -19580,20 +19580,17 @@ class PanelIcon {
19580
19580
  btnSizes.forEach(btn => {
19581
19581
  btn.addEventListener('click', () => {
19582
19582
  this.builder.editor.saveForUndo();
19583
- const num = btn.getAttribute('data-value');
19584
- let currentFontSize = 1;
19585
- let container = this.getElm();
19583
+ const num = btn.getAttribute('data-value'); // Size the icon itself, as ContentBuilder's own size buttons do for an icon.
19586
19584
 
19587
- if (container) {
19588
- currentFontSize = Number(window.getComputedStyle(container).getPropertyValue('font-size').match(/\d+/)[0]);
19585
+ const icon = this.builder.controlpanel.activeElement;
19586
+ const rte = this.builder.editor.rte;
19587
+
19588
+ if ((this.builder.editor.opts.fontSizeClassValues || []).length > 0) {
19589
+ rte.applyClassFontSize(icon, num);
19590
+ } else {
19591
+ rte.applyInlineFontSize(icon, num);
19589
19592
  }
19590
19593
 
19591
- this.builder.editor.dom.execCommand('font-size', currentFontSize + 1 + 'px', (ok, container) => {
19592
- if (ok) {
19593
- this.builder.editor.rte.applyClassFontSize(container, num);
19594
- container.style.fontSize = '';
19595
- }
19596
- });
19597
19594
  this.getState();
19598
19595
  this.builder.editor.onChange();
19599
19596
  });
@@ -19631,7 +19628,13 @@ class PanelIcon {
19631
19628
  getState() {
19632
19629
  const panel = this.panel;
19633
19630
  let icon = this.builder.controlpanel.activeElement;
19634
- const div = icon.parentNode;
19631
+ const div = icon.parentNode; // An icon in overlay text: its link and alignment belong to the line (the Text panel),
19632
+ // and its size follows the design, like the text's. Only Change icon and Color are shown.
19633
+
19634
+ const inOverlayText = !!this.builder.controlpanel.overlayIcon(icon);
19635
+ panel.querySelectorAll('.btn-link, .label-iconsize, .group.fontsizes, .alignicon').forEach(elm => {
19636
+ elm.style.display = inOverlayText ? 'none' : '';
19637
+ });
19635
19638
  const btnAligns = panel.querySelectorAll('[data-align]');
19636
19639
  btnAligns.forEach(btn => btn.classList.remove('on'));
19637
19640
  if (div.classList.contains('text-left')) panel.querySelector('[data-align="left"]').classList.add('on');
@@ -19682,14 +19685,6 @@ class PanelIcon {
19682
19685
  }
19683
19686
  }
19684
19687
 
19685
- getElm() {
19686
- const selection = this.builder.win.getSelection();
19687
- const anchorNode = selection.anchorNode;
19688
- if (!anchorNode) return false;
19689
- const container = anchorNode.nodeType !== Node.TEXT_NODE && anchorNode.nodeType !== Node.COMMENT_NODE ? anchorNode : anchorNode.parentElement;
19690
- return container;
19691
- }
19692
-
19693
19688
  }
19694
19689
 
19695
19690
  class PanelSvg {
@@ -33708,6 +33703,15 @@ class PanelSection {
33708
33703
  <div class="accordion-content" id="sectioncontent5" aria-hidden="true">
33709
33704
 
33710
33705
  <div class="subpanel">
33706
+ <div class="barstart-row">
33707
+ <div class="label mt-2">${out('Bar at the start')}:</div>
33708
+ <div role="group" aria-label="${out('Bar at the start')}" class="group sectionbar barstart">
33709
+ <button title="${out('Auto')}" data-barstart="">${out('Auto')}</button>
33710
+ <button title="${out('Light')}" data-barstart="light">${out('Light')}</button>
33711
+ <button title="${out('Dark')}" data-barstart="dark">${out('Dark')}</button>
33712
+ </div>
33713
+ </div>
33714
+
33711
33715
  <div class="label mt-2">${out('Bar over this section')}:</div>
33712
33716
  <div role="group" aria-label="${out('Bar over this section')}" class="group sectionbar">
33713
33717
  <button title="${out('Default')}" data-bar="">${out('Default')}</button>
@@ -33932,6 +33936,20 @@ class PanelSection {
33932
33936
  btn.classList.add('on');
33933
33937
  this.builder.onChange();
33934
33938
  });
33939
+ }); // Bar at the start: the bar's text while it rests over the top section, at the top of
33940
+ // the page (data-bar-start). Only the top section has it. Auto: no attribute.
33941
+
33942
+ const btnBarStarts = panel.querySelectorAll('[data-barstart]');
33943
+ btnBarStarts.forEach(btn => {
33944
+ btn.addEventListener('click', () => {
33945
+ this.builder.editor.saveForUndo();
33946
+ const section = this.builder.activeSection;
33947
+ const s = btn.getAttribute('data-barstart');
33948
+ if (s) section.setAttribute('data-bar-start', s);else section.removeAttribute('data-bar-start');
33949
+ btnBarStarts.forEach(btn => btn.classList.remove('on'));
33950
+ btn.classList.add('on');
33951
+ this.builder.onChange();
33952
+ });
33935
33953
  });
33936
33954
  const btnBarInk = panel.querySelector('.btn-barink');
33937
33955
  btnBarInk.addEventListener('click', () => {
@@ -34208,7 +34226,16 @@ class PanelSection {
34208
34226
  if (showBar) {
34209
34227
  const look = activeSection.getAttribute('data-bar') || '';
34210
34228
  panel.querySelectorAll('[data-bar]').forEach(btn => btn.classList.toggle('on', btn.getAttribute('data-bar') === look));
34211
- panel.querySelector('.btn-barink').style.backgroundColor = activeSection.getAttribute('data-bar-ink') || '';
34229
+ panel.querySelector('.btn-barink').style.backgroundColor = activeSection.getAttribute('data-bar-ink') || ''; // Bar at the start: the top section only (the first section under the bar)
34230
+
34231
+ const top = Array.from(this.builder.wrapperEl.querySelectorAll('.is-section')).find(s => !s.closest('.is-section-navbar'));
34232
+ const isTop = top === activeSection;
34233
+ panel.querySelector('.barstart-row').style.display = isTop ? '' : 'none';
34234
+
34235
+ if (isTop) {
34236
+ const start = activeSection.getAttribute('data-bar-start') || '';
34237
+ panel.querySelectorAll('[data-barstart]').forEach(btn => btn.classList.toggle('on', btn.getAttribute('data-barstart') === start));
34238
+ }
34212
34239
  }
34213
34240
 
34214
34241
  this.realtimeVisibility(activeSection, true);
@@ -43566,6 +43593,9 @@ class ControlPanel {
43566
43593
  // elmTool, whose duplicate/delete/move actions would let a user
43567
43594
  // restructure a generated layer.
43568
43595
  this.builder.editor.inspectedElement = overlayTarget.element;
43596
+ } else if (this.overlayIcon(e.target)) {
43597
+ // An icon in overlay text opens the Icon panel.
43598
+ this.builder.editor.inspectedElement = e.target;
43569
43599
  } else {
43570
43600
  // A plugin in the box overlay opens its own panel (Section > Box > the
43571
43601
  // plugin), like overlay text. Its editable parts and content areas are
@@ -44154,6 +44184,8 @@ class ControlPanel {
44154
44184
  if (el.closest('[data-html]')) return null; // code/module block — has its own editor
44155
44185
 
44156
44186
  if (el.closest('[data-cb-type]')) return null; // plugin — panel-plugin owns it
44187
+
44188
+ if (this.overlayIcon(el)) return null; // icon in a text — the Icon panel owns it
44157
44189
  // Text of an overlay layer. Resolve upward: a click can land on a
44158
44190
  // <b>/<span> inside the region, which is not itself a region.
44159
44191
 
@@ -44394,7 +44426,7 @@ class ControlPanel {
44394
44426
  activeElement = this.resolvedImage;
44395
44427
  }
44396
44428
 
44397
- if (activeElement && this.overlayTarget(activeElement)) {
44429
+ if (activeElement && (this.overlayTarget(activeElement) || this.overlayIcon(activeElement))) {
44398
44430
  this.activeElement = activeElement;
44399
44431
  this.activeColumn = null;
44400
44432
  this.activeRow = null;
@@ -44518,7 +44550,7 @@ class ControlPanel {
44518
44550
  } // Overlay content has no row/column to walk back up to.
44519
44551
 
44520
44552
 
44521
- if (selection === 'element' && (this.overlayTarget(this.activeElement) || this.activeElement.closest('[data-cb-type]') && this.activeElement.closest('.is-overlay-content'))) {
44553
+ if (selection === 'element' && (this.overlayTarget(this.activeElement) || this.overlayIcon(this.activeElement) || this.activeElement.closest('[data-cb-type]') && this.activeElement.closest('.is-overlay-content'))) {
44522
44554
  breadcrumbHtml = `<div>${section} ${sep} ${box} ${sep}</div>`;
44523
44555
  }
44524
44556
 
@@ -44771,6 +44803,25 @@ class ControlPanel {
44771
44803
  elm.removeAttribute('data-overlay-select');
44772
44804
  });
44773
44805
  if (el) el.setAttribute('data-overlay-select', '');
44806
+ } // A plugin placed in an overlay (eg. a header bar's Site Menu or Site Logo).
44807
+ // Like an overlay target it has no cell/row outline, so it gets the same mark.
44808
+
44809
+
44810
+ overlayPlugin(el) {
44811
+ if (!el || !el.closest) return null;
44812
+ const plugin = el.closest('[data-cb-type]');
44813
+ if (!plugin || !plugin.closest(this.builder.overlayEditableSelector)) return null;
44814
+ if (plugin.closest('.is-container')) return null;
44815
+ return plugin;
44816
+ } // An icon (<i class="bi ...">) in an overlay, eg. at the start of a chip's text. It opens the
44817
+ // Icon panel, so it can be changed, while a click on the words still opens the Text panel.
44818
+
44819
+
44820
+ overlayIcon(el) {
44821
+ if (!el || !el.matches || !el.matches('i.bi, i.icon') || el.innerHTML !== '') return null;
44822
+ if (!el.closest(this.builder.overlayEditableSelector)) return null;
44823
+ if (el.closest('.is-container, [data-html], [data-cb-type]')) return null;
44824
+ return el;
44774
44825
  } // Is `el` (or an ancestor of it) a button?
44775
44826
  //
44776
44827
  // A <button> always is. An <a> is a button when it lays itself out as a
@@ -44853,7 +44904,16 @@ class ControlPanel {
44853
44904
 
44854
44905
  if (what === 'element' && this.activeElement) {
44855
44906
  const overlayNow = this.overlayTarget(this.activeElement);
44856
- if (overlayNow) marked = overlayNow.element;else if (this.pictureOnlyElement(this.activeElement)) marked = this.activeElement;
44907
+ if (overlayNow) marked = overlayNow.element;else if (this.pictureOnlyElement(this.activeElement)) marked = this.activeElement;else marked = this.overlayPlugin(this.activeElement) || this.overlayIcon(this.activeElement);
44908
+ } // An overlay icon stays the editor's active icon only while it is selected; otherwise
44909
+ // a later icon insert would replace it.
44910
+
44911
+
44912
+ const activeIcon = this.builder.editor.activeIcon;
44913
+
44914
+ if (activeIcon && activeIcon !== marked && this.overlayIcon(activeIcon)) {
44915
+ activeIcon.classList.remove('icon-active');
44916
+ this.builder.editor.activeIcon = null;
44857
44917
  }
44858
44918
 
44859
44919
  this.markOverlaySelection(marked);
@@ -45004,6 +45064,9 @@ class ControlPanel {
45004
45064
  this.panelIframe.classList.add('active');
45005
45065
  this.objPanelIframe.getState();
45006
45066
  } else if (element.tagName.toLowerCase() === 'i' && (element.classList.contains('icon') || element.classList.contains('bi'))) {
45067
+ // In a container ContentBuilder's click makes it the active icon; an overlay
45068
+ // icon gets no such click, so name it here (Change icon replaces this one).
45069
+ if (this.overlayIcon(element)) this.builder.editor.activeIcon = element;
45007
45070
  let titleHtml = out('Icon');
45008
45071
  this.title.innerHTML = titleHtml;
45009
45072
  this.panelIcon.classList.add('active');
@@ -45136,8 +45199,10 @@ class ControlPanel {
45136
45199
  // should animate exposes that as its own setting.
45137
45200
 
45138
45201
 
45139
- const isPlugin = what === 'element' && !!pluginOf(this.activeElement);
45140
- const canMotion = !isPlugin && (what === 'element' || what === 'column' || what === 'row' || what === 'container' || what === 'block' || what === 'box' || what === 'section');
45202
+ const isPlugin = what === 'element' && !!pluginOf(this.activeElement); // An icon in overlay text moves with its line; only the line has Motion.
45203
+
45204
+ const isOverlayIcon = what === 'element' && !!this.overlayIcon(this.activeElement);
45205
+ const canMotion = !isPlugin && !isOverlayIcon && (what === 'element' || what === 'column' || what === 'row' || what === 'container' || what === 'block' || what === 'box' || what === 'section');
45141
45206
 
45142
45207
  if (canMotion) {
45143
45208
  if (this.tab === 'motion') {
@@ -176896,6 +176961,9 @@ Add an image for each feature.`, 'Create a new block showcasing a photo gallery
176896
176961
  }
176897
176962
 
176898
176963
  i.bi, i.icon { display: inline-flex; }
176964
+ /* As a flex box an icon ignores Bootstrap Icons' own vertical-align (on its ::before) and
176965
+ sits higher than the text beside it. Put the same offset on the icon itself. */
176966
+ i.bi { vertical-align: -.125em; }
176899
176967
 
176900
176968
  </style>`); // i.bi, i.icon { display: inline-flex; } => this makes icons more cursor friendly
176901
176969