@innovastudio/contentbuilder 1.5.48 → 1.5.49

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@innovastudio/contentbuilder",
3
3
  "type": "module",
4
- "version": "1.5.48",
4
+ "version": "1.5.49",
5
5
  "description": "",
6
6
  "main": "public/contentbuilder/contentbuilder.esm.js",
7
7
  "types": "index.d.ts",
@@ -3711,6 +3711,24 @@ class Dom {
3711
3711
  constructor(builder) {
3712
3712
  this.builder = builder;
3713
3713
  }
3714
+ detectMobileOrTablet() {
3715
+ const userAgent = navigator.userAgent.toLowerCase();
3716
+ const isIOS = /ipad|iphone|ipod/.test(userAgent) && !window.MSStream;
3717
+ const isAndroid = /android/.test(userAgent);
3718
+ const isTouchDevice = 'ontouchstart' in window || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0;
3719
+ const screenWidth = window.innerWidth <= 1600;
3720
+ if (isIOS || isAndroid) {
3721
+ return true; // Definitely a mobile or tablet
3722
+ }
3723
+
3724
+ // Additional check for other touch devices with screen width under 1600px
3725
+ if (isTouchDevice && screenWidth) {
3726
+ return true; // Likely a mobile or tablet
3727
+ }
3728
+
3729
+ return false; // Likely not a mobile or tablet
3730
+ }
3731
+
3714
3732
  getScale(container) {
3715
3733
  let matrix = window.getComputedStyle(container).transform;
3716
3734
  if (matrix === 'none') return 1;
@@ -17223,7 +17241,19 @@ const renderSnippetPanel = (builder, snippetOpen) => {
17223
17241
 
17224
17242
  let activeBuilderArea;
17225
17243
  let itemHeight;
17226
- new Sortable(snippetlist, {
17244
+ const isMobile = dom.detectMobileOrTablet();
17245
+ let useClick = false;
17246
+ if (isMobile && builder.isContentBox) {
17247
+ const items = snippetlist.querySelectorAll('.snippet-item');
17248
+ items.forEach(item => {
17249
+ item.addEventListener('click', () => {
17250
+ const snippetid = item.getAttribute('data-id');
17251
+ builder.dropSnippet(snippetid);
17252
+ });
17253
+ });
17254
+ useClick = true;
17255
+ }
17256
+ if (!useClick) new Sortable(snippetlist, {
17227
17257
  // forceFallback: safariAgent,
17228
17258
  group: {
17229
17259
  name: 'shared',
@@ -66679,6 +66709,7 @@ class Rte {
66679
66709
  btnFront.forEach(btn => {
66680
66710
  btn.addEventListener('click', () => {
66681
66711
  let activeBlock = this.builder.doc.querySelector('.is-block.cloned');
66712
+ if (!activeBlock) activeBlock = this.builder.doc.querySelector('.is-block.active');
66682
66713
  if (!activeBlock) return;
66683
66714
  this.builder.forward(activeBlock);
66684
66715
  });
@@ -66687,6 +66718,7 @@ class Rte {
66687
66718
  btnBackward.forEach(btn => {
66688
66719
  btn.addEventListener('click', () => {
66689
66720
  let activeBlock = this.builder.doc.querySelector('.is-block.cloned');
66721
+ if (!activeBlock) activeBlock = this.builder.doc.querySelector('.is-block.active');
66690
66722
  if (!activeBlock) return;
66691
66723
  if (activeBlock.style.zIndex === '0') {
66692
66724
  this.builder.moveUp(activeBlock);
@@ -66714,6 +66746,7 @@ class Rte {
66714
66746
  btnDuplicate.forEach(btn => {
66715
66747
  btn.addEventListener('click', () => {
66716
66748
  let activeBlock = this.builder.doc.querySelector('.is-block.cloned');
66749
+ if (!activeBlock) activeBlock = this.builder.doc.querySelector('.is-block.active');
66717
66750
  if (!activeBlock) return;
66718
66751
  this.builder.duplicate(activeBlock);
66719
66752
  });
@@ -83995,7 +84028,8 @@ class EditableBlocks {
83995
84028
  }
83996
84029
  if (block.classList.contains('is-group')) return; // do not clone if block is shape
83997
84030
 
83998
- if (!block.classList.contains('clone')) {
84031
+ const isMobileOrTablet = this.detectMobileOrTablet();
84032
+ if (!block.classList.contains('clone') & !isMobileOrTablet) {
83999
84033
  let clonedDiv = block.cloneNode(true);
84000
84034
  clonedDiv.classList.add('clone');
84001
84035
  block.parentNode.appendChild(clonedDiv);
@@ -84003,6 +84037,24 @@ class EditableBlocks {
84003
84037
  this.refresh();
84004
84038
  }
84005
84039
  }
84040
+ detectMobileOrTablet() {
84041
+ const userAgent = navigator.userAgent.toLowerCase();
84042
+ const isIOS = /ipad|iphone|ipod/.test(userAgent) && !window.MSStream;
84043
+ const isAndroid = /android/.test(userAgent);
84044
+ const isTouchDevice = 'ontouchstart' in window || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0;
84045
+ const screenWidth = window.innerWidth <= 1600;
84046
+ if (isIOS || isAndroid) {
84047
+ return true; // Definitely a mobile or tablet
84048
+ }
84049
+
84050
+ // Additional check for other touch devices with screen width under 1600px
84051
+ if (isTouchDevice && screenWidth) {
84052
+ return true; // Likely a mobile or tablet
84053
+ }
84054
+
84055
+ return false; // Likely not a mobile or tablet
84056
+ }
84057
+
84006
84058
  selectClear() {
84007
84059
  this.doc.querySelectorAll('.clone').forEach(elm => elm.parentNode.removeChild(elm));
84008
84060
  this.doc.querySelectorAll('.cloned').forEach(elm => elm.classList.remove('cloned'));
@@ -92316,6 +92368,203 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
92316
92368
  // return currentScript.replace(currentScriptFile, '');
92317
92369
  }
92318
92370
 
92371
+ dropSnippet(snippetid) {
92372
+ // snippetJSON is snippet's JSON (from assets/minimalist-blocks/content.js) that store all snippets' html
92373
+ const result = this.opts.snippetJSON.snippets.filter(item => {
92374
+ if (item.id + '' === snippetid) return item;else return false;
92375
+ });
92376
+ let html = result[0].html;
92377
+ let noedit = result[0].noedit;
92378
+ let bSnippet;
92379
+ if (html.indexOf('"row') === -1) {
92380
+ bSnippet = true; // Just snippet (without row/column grid)
92381
+ } else {
92382
+ bSnippet = false; // Snippet is wrapped in row/colum
92383
+ }
92384
+
92385
+ if (this.opts.emailMode) bSnippet = false;
92386
+
92387
+ // check if is block
92388
+ let isBlock = false;
92389
+ if (html.includes('"is-block')) {
92390
+ isBlock = true;
92391
+ bSnippet = false;
92392
+ }
92393
+
92394
+ // Convert snippet into your defined 12 columns grid
92395
+ let rowClass = this.opts.row; //row
92396
+ let colClass = this.opts.cols; //['col s1', 'col s2', 'col s3', 'col s4', 'col s5', 'col s6', 'col s7', 'col s8', 'col s9', 'col s10', 'col s11', 'col s12']
92397
+ if (rowClass !== '' && colClass.length === 12) {
92398
+ // html = html.replace(new RegExp('row clearfix', 'g'), rowClass);
92399
+ html = html.replace(new RegExp('row clearfix', 'g'), 'row'); // backward
92400
+ html = html.replace(new RegExp('"row', 'g'), '"' + rowClass);
92401
+ html = html.replace(new RegExp('column full', 'g'), colClass[11]);
92402
+ html = html.replace(new RegExp('column half', 'g'), colClass[5]);
92403
+ html = html.replace(new RegExp('column third', 'g'), colClass[3]);
92404
+ html = html.replace(new RegExp('column fourth', 'g'), colClass[2]);
92405
+ html = html.replace(new RegExp('column fifth', 'g'), colClass[1]);
92406
+ html = html.replace(new RegExp('column sixth', 'g'), colClass[1]);
92407
+ html = html.replace(new RegExp('column two-third', 'g'), colClass[7]);
92408
+ html = html.replace(new RegExp('column two-fourth', 'g'), colClass[8]);
92409
+ html = html.replace(new RegExp('column two-fifth', 'g'), colClass[9]);
92410
+ html = html.replace(new RegExp('column two-sixth', 'g'), colClass[9]);
92411
+ }
92412
+ html = html.replace(/{id}/g, this.util.makeId());
92413
+ if (this.opts.onAdd) {
92414
+ html = this.opts.onAdd(html);
92415
+ }
92416
+ if (this.opts.snippetPathReplace.length > 0) {
92417
+ // try {
92418
+ if (this.opts.snippetPathReplace[0] !== '') {
92419
+ let regex = new RegExp(this.opts.snippetPathReplace[0], 'g');
92420
+ html = html.replace(regex, this.opts.snippetPathReplace[1]);
92421
+ let string1 = this.opts.snippetPathReplace[0].replace(/\//g, '%2F');
92422
+ let string2 = this.opts.snippetPathReplace[1].replace(/\//g, '%2F');
92423
+ let regex2 = new RegExp(string1, 'g');
92424
+ html = html.replace(regex2, string2);
92425
+ }
92426
+ // } catch (e) { 1; }
92427
+ }
92428
+
92429
+ // this.addSnippet(html, bSnippet, noedit);
92430
+
92431
+ if (bSnippet) {
92432
+ // Just snippet (without row/column grid), ex. buttons, line, social, video, map.
92433
+ // Can be inserted after current row, column (cell), element, or last row.
92434
+
92435
+ html = `<div class="${this.opts.row}"><div class="${this.opts.cols[this.opts.cols.length - 1]}"${noedit ? ' data-noedit' : ''}>${html}</div></div>`;
92436
+ } else if (isBlock) ; else {
92437
+ // Snippet is wrapped in row/colum (may contain custom code or has [data-html] attribute)
92438
+ // Can only be inserted after current row or last row (not on column or element).
92439
+
92440
+ let snippet = this.dom.createElement('div');
92441
+ snippet.innerHTML = html;
92442
+ let blocks = snippet.querySelectorAll('[data-html]');
92443
+ Array.prototype.forEach.call(blocks, block => {
92444
+ // Render custom code block
92445
+ html = decodeURIComponent(block.getAttribute('data-html'));
92446
+ html = html.replace(/{id}/g, this.util.makeId());
92447
+ html = html.replace(/<script>/g, `${this.nonce ? `<script nonce="${this.nonce}">` : '<script>'}`);
92448
+ for (var i = 1; i <= 20; i++) {
92449
+ html = html.replace('[%HTML' + i + '%]', block.getAttribute('data-html-' + i) === undefined ? '' : decodeURIComponent(block.getAttribute('data-html-' + i))); //render editable area
92450
+ }
92451
+
92452
+ block.innerHTML = html;
92453
+ });
92454
+ html = snippet.innerHTML;
92455
+ }
92456
+ const activeBox = this.doc.querySelector('.box-select');
92457
+ const activeRow = this.doc.querySelector('.row-active');
92458
+ if (activeRow) {
92459
+ this.addRow(html, activeBox);
92460
+ } else {
92461
+ if (activeBox) {
92462
+ if (activeBox.classList.contains('box-canvas')) {
92463
+ // Canvas Mode
92464
+
92465
+ let snippet = this.dom.createElement('div');
92466
+ snippet.innerHTML = html;
92467
+ let blocks = snippet.querySelectorAll('[data-html]');
92468
+ Array.prototype.forEach.call(blocks, block => {
92469
+ // Render custom code block
92470
+ html = decodeURIComponent(block.getAttribute('data-html'));
92471
+ html = html.replace(/{id}/g, this.util.makeId());
92472
+ html = html.replace(/<script>/g, `${this.nonce ? `<script nonce="${this.nonce}">` : '<script>'}`);
92473
+ for (var i = 1; i <= 20; i++) {
92474
+ html = html.replace('[%HTML' + i + '%]', block.getAttribute('data-html-' + i) === undefined ? '' : decodeURIComponent(block.getAttribute('data-html-' + i))); //render editable area
92475
+ }
92476
+
92477
+ block.innerHTML = html;
92478
+ });
92479
+ html = snippet.innerHTML;
92480
+ const blockTemplate = `
92481
+ <div class="is-block block-steady height-auto" data-new-dummy="1" style="top: 20%; left: 20%; width: 760px;">
92482
+ <div class="is-container container-new size-18 leading-14">
92483
+ [%CONTENT%]
92484
+ </div>
92485
+ </div>
92486
+ `; // data-new-dummy will be used by onSort to apply top/left position (snippetpanel.js)
92487
+ // html = blockTemplate.replace('[%CONTENT%]', html);
92488
+
92489
+ this.uo.saveForUndo();
92490
+ this.eb.addBlock(blockTemplate, activeBox);
92491
+ const builders = activeBox.querySelectorAll('.is-container.container-new');
92492
+ builders.forEach(builder => {
92493
+ // After snippet has been added, re-apply behavior on builder areas
92494
+
92495
+ var range = document.createRange();
92496
+ range.setStart(builder, 0);
92497
+ builder.appendChild(range.createContextualFragment(html));
92498
+ this.applyBehaviorOn(builder);
92499
+ builder.classList.remove('container-new');
92500
+ });
92501
+ this.opts.onChange();
92502
+ this.opts.onRender();
92503
+ if (this.opts.onBlockCanvasAdd) this.opts.onBlockCanvasAdd();
92504
+ } else {
92505
+ let container = activeBox.querySelector('.builder-active');
92506
+ if (container) {
92507
+ this.addRow(html, activeBox);
92508
+ } else {
92509
+ container = activeBox.querySelector('.is-container');
92510
+ if (container) {
92511
+ this.addRow(html, activeBox);
92512
+ }
92513
+ }
92514
+ }
92515
+ }
92516
+ }
92517
+ this.activeCol = null;
92518
+ }
92519
+ addRow(html, box) {
92520
+ this.uo.saveForUndo();
92521
+ let rowElement;
92522
+ let bAddLast = false;
92523
+
92524
+ // Add after selected row
92525
+ let cell = this.activeCol;
92526
+ let row;
92527
+ if (cell) {
92528
+ row = cell.parentNode; // in email mode, cell active is also under row active (incorrect, but cell active is not needed in email mode. So this line works!)
92529
+ } else {
92530
+ // If no active cell, check if it is from .row-add-initial (empty info)
92531
+ row = this.doc.querySelector('.row-active');
92532
+ if (!row) {
92533
+ bAddLast = true;
92534
+ }
92535
+ }
92536
+ // Add after last row
92537
+ if (bAddLast) {
92538
+ const container = box.querySelector('.is-builder');
92539
+ const rows = this.dom.elementChildren(container);
92540
+ const lastrow = rows[rows.length - 1];
92541
+ row = lastrow;
92542
+ }
92543
+
92544
+ // Use createContextualFragment() to make embedded script executable
92545
+ let range = document.createRange();
92546
+ row.parentNode.insertBefore(range.createContextualFragment(html), row.nextSibling);
92547
+ // rowElement = snippet.childNodes[0];
92548
+
92549
+ rowElement = row.nextElementSibling; // a must. Must be before applyBehavior to prevent element delete during fixLayout
92550
+
92551
+ // checkEmpty & onRender called here
92552
+ let builderActive = box.querySelector('.builder-active');
92553
+ if (builderActive) this.applyBehaviorOn(builderActive);else {
92554
+ builderActive = box.querySelector('.is-builder');
92555
+ this.applyBehaviorOn(builderActive);
92556
+ }
92557
+ let cellElement = rowElement.querySelector('div');
92558
+ if (cellElement) cellElement.click(); //change active block to the newly created
92559
+
92560
+ // Change to row selection
92561
+ rowElement.className = rowElement.className.replace('row-outline', '');
92562
+
92563
+ //Hide Column tool (new!)
92564
+ this.util.hideColumnTool();
92565
+ this.opts.onChange();
92566
+ this.opts.onRender();
92567
+ }
92319
92568
  sectionDropSetup() {
92320
92569
  if (this.blockContainer) {
92321
92570
  this.sortableOnCanvas = [];