@innovastudio/contentbox 1.6.156 → 1.6.158
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/index.d.ts
CHANGED
@@ -374,6 +374,11 @@ interface ContentBoxOptions {
|
|
374
374
|
exampleAudioUrl?: string;
|
375
375
|
saveResults?: boolean;
|
376
376
|
//---
|
377
|
+
|
378
|
+
autoSaveDelay?: number;
|
379
|
+
maxAutoSaveInterval?: number;
|
380
|
+
minAutoSaveInterval?: number;
|
381
|
+
autoSave?: () => void | Promise<void>;
|
377
382
|
}
|
378
383
|
|
379
384
|
interface OpenModalOptions {
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@innovastudio/contentbox",
|
3
3
|
"type": "module",
|
4
|
-
"version": "1.6.
|
4
|
+
"version": "1.6.158",
|
5
5
|
"description": "",
|
6
6
|
"main": "public/contentbox/contentbox.esm.js",
|
7
7
|
"types": "index.d.ts",
|
@@ -59,7 +59,7 @@
|
|
59
59
|
"ws": "^8.13.0"
|
60
60
|
},
|
61
61
|
"dependencies": {
|
62
|
-
"@innovastudio/contentbuilder": "^1.5.
|
62
|
+
"@innovastudio/contentbuilder": "^1.5.153",
|
63
63
|
"js-beautify": "^1.14.0",
|
64
64
|
"sortablejs": "^1.15.2"
|
65
65
|
}
|
@@ -1391,10 +1391,14 @@ class SideBar {
|
|
1391
1391
|
dom$l.removeClass(elm, 'active');
|
1392
1392
|
});
|
1393
1393
|
builderStuff.querySelectorAll('.is-sidebar-content.active').forEach(elm => {
|
1394
|
-
dom$l.removeClass(elm, 'active');
|
1395
|
-
|
1394
|
+
dom$l.removeClass(elm, 'active'); // elm.setAttribute('aria-hidden', true);
|
1395
|
+
|
1396
1396
|
setTimeout(() => {
|
1397
1397
|
elm.style.display = ''; //hide
|
1398
|
+
|
1399
|
+
setTimeout(() => {
|
1400
|
+
elm.setAttribute('aria-hidden', true);
|
1401
|
+
}, 50);
|
1398
1402
|
}, 300);
|
1399
1403
|
}); // this.builder.animateScroll.close();
|
1400
1404
|
}
|
@@ -25779,16 +25783,30 @@ class ControlPanel {
|
|
25779
25783
|
this.builder.iframePanel.setScreenMode('desktop');
|
25780
25784
|
}
|
25781
25785
|
} else if (this.builder.iframeSrc && this.builder.controlPanel) {
|
25782
|
-
const controlPanel = this.controlPanel;
|
25783
|
-
const btnToggleDevice = controlPanel.querySelector('.btn-toggledevice');
|
25786
|
+
// const controlPanel = this.controlPanel;
|
25787
|
+
// const btnToggleDevice = controlPanel.querySelector('.btn-toggledevice');
|
25788
|
+
// const screenMode = this.builder.screenMode;
|
25789
|
+
// if(screenMode!=='fullview') {
|
25790
|
+
// this.builder.iframePanel.setScreenMode('fullview');
|
25791
|
+
// btnToggleDevice.classList.remove('on');
|
25792
|
+
// } else {
|
25793
|
+
// this.builder.iframePanel.setScreenMode('desktop');
|
25794
|
+
// btnToggleDevice.classList.add('on');
|
25795
|
+
// }
|
25784
25796
|
const screenMode = this.builder.screenMode;
|
25785
25797
|
|
25786
|
-
if (screenMode
|
25787
|
-
this.builder.iframePanel.setScreenMode('fullview');
|
25788
|
-
btnToggleDevice.classList.remove('on');
|
25789
|
-
} else {
|
25798
|
+
if (screenMode === 'desktop-lg') {
|
25790
25799
|
this.builder.iframePanel.setScreenMode('desktop');
|
25791
|
-
|
25800
|
+
} else if (screenMode === 'desktop') {
|
25801
|
+
this.builder.iframePanel.setScreenMode('tablet-landscape');
|
25802
|
+
} else if (screenMode === 'tablet-landscape') {
|
25803
|
+
this.builder.iframePanel.setScreenMode('tablet');
|
25804
|
+
} else if (screenMode === 'tablet') {
|
25805
|
+
this.builder.iframePanel.setScreenMode('mobile');
|
25806
|
+
} else if (screenMode === 'mobile') {
|
25807
|
+
this.builder.iframePanel.setScreenMode('fullview');
|
25808
|
+
} else if (screenMode === 'fullview') {
|
25809
|
+
this.builder.iframePanel.setScreenMode('desktop-lg');
|
25792
25810
|
}
|
25793
25811
|
}
|
25794
25812
|
}
|
@@ -126116,6 +126134,11 @@ Please obtain a license at: https://innovastudio.com/contentbox`);
|
|
126116
126134
|
this.elmTool.hide();
|
126117
126135
|
}
|
126118
126136
|
typing() {
|
126137
|
+
// Lightweight: Just mark content changed for auto-save
|
126138
|
+
if (this.opts.onType) {
|
126139
|
+
this.opts.onType();
|
126140
|
+
}
|
126141
|
+
|
126119
126142
|
// console.log('typing');
|
126120
126143
|
if (this.timeoutId) clearTimeout(this.timeoutId);
|
126121
126144
|
this.timeoutId = setTimeout(() => {
|
@@ -154490,18 +154513,16 @@ class IframePanel {
|
|
154490
154513
|
tool.querySelectorAll('button').forEach(btn => btn.classList.remove('active'));
|
154491
154514
|
const btn = tool.querySelector(`[data-command="${screenMode}"]`);
|
154492
154515
|
if (btn) btn.classList.add('active'); // set on/off toggle device button
|
154493
|
-
|
154494
|
-
|
154495
|
-
|
154496
|
-
|
154497
|
-
|
154498
|
-
|
154499
|
-
|
154500
|
-
|
154501
|
-
|
154502
|
-
|
154503
|
-
}
|
154504
|
-
}
|
154516
|
+
// if(this.builder.controlpanel) {
|
154517
|
+
// const btnToggleDevice = this.builder.controlpanel.controlPanel.querySelector('.btn-toggledevice');
|
154518
|
+
// if(btnToggleDevice) {
|
154519
|
+
// if(screenMode!=='fullview') {
|
154520
|
+
// btnToggleDevice.classList.add('on');
|
154521
|
+
// } else {
|
154522
|
+
// btnToggleDevice.classList.remove('on');
|
154523
|
+
// }
|
154524
|
+
// }
|
154525
|
+
// }
|
154505
154526
|
|
154506
154527
|
this.loadIframe();
|
154507
154528
|
let btns = tool.querySelectorAll('button');
|
@@ -154676,19 +154697,17 @@ class IframePanel {
|
|
154676
154697
|
}
|
154677
154698
|
|
154678
154699
|
if (screenMode !== 'fullview') tool.querySelector(`button[data-command="${screenMode}"]`).classList.add('active'); // set on/off toggle device button
|
154679
|
-
|
154680
|
-
|
154681
|
-
|
154682
|
-
|
154683
|
-
|
154684
|
-
|
154685
|
-
|
154686
|
-
|
154687
|
-
|
154688
|
-
|
154689
|
-
|
154690
|
-
} // Refresh Part 2
|
154691
|
-
|
154700
|
+
// if(this.builder.controlpanel) {
|
154701
|
+
// const btnToggleDevice = this.builder.controlpanel.controlPanel.querySelector('.btn-toggledevice');
|
154702
|
+
// if(btnToggleDevice) {
|
154703
|
+
// if(screenMode!=='fullview') {
|
154704
|
+
// btnToggleDevice.classList.add('on');
|
154705
|
+
// } else {
|
154706
|
+
// btnToggleDevice.classList.remove('on');
|
154707
|
+
// }
|
154708
|
+
// }
|
154709
|
+
// }
|
154710
|
+
// Refresh Part 2
|
154692
154711
|
|
154693
154712
|
if (hasPin) {
|
154694
154713
|
setTimeout(() => {
|
@@ -161170,8 +161189,13 @@ Add an image for each feature.`, 'Create a new block showcasing a photo gallery
|
|
161170
161189
|
|
161171
161190
|
let old2 = this.settings.onChange;
|
161172
161191
|
|
161173
|
-
this.settings.onChange = () => {
|
161174
|
-
|
161192
|
+
this.settings.onChange = (...args) => {
|
161193
|
+
// Accept all arguments
|
161194
|
+
// Call original onChange with all arguments
|
161195
|
+
if (old2) old2.apply(this, args); // Use apply to pass arguments
|
161196
|
+
// Trigger auto-save
|
161197
|
+
|
161198
|
+
this.markContentChanged();
|
161175
161199
|
setTimeout(() => {
|
161176
161200
|
// this.quickPosTool();
|
161177
161201
|
this.editor.livePreview.previewRefresh();
|
@@ -161401,16 +161425,184 @@ Add an image for each feature.`, 'Create a new block showcasing a photo gallery
|
|
161401
161425
|
}, this);
|
161402
161426
|
} else {
|
161403
161427
|
initialStart();
|
161428
|
+
} // ---- AUTO-SAVE ----
|
161429
|
+
// Auto-save timing configuration
|
161430
|
+
|
161431
|
+
|
161432
|
+
this.autoSaveDelay = settings.autoSaveDelay || 3000; // Wait 3s after pause before saving
|
161433
|
+
|
161434
|
+
this.maxAutoSaveInterval = settings.maxAutoSaveInterval || 30000; // Force save every 30s during continuous editing
|
161435
|
+
|
161436
|
+
this.minAutoSaveInterval = settings.minAutoSaveInterval || 5000; // Minimum 5s between saves (rate limit)
|
161437
|
+
// Auto-save callback function
|
161438
|
+
|
161439
|
+
this.autoSave = settings.autoSave; // Auto-save state
|
161440
|
+
|
161441
|
+
this.autoSaveTimeoutId = null; // Debounce timer
|
161442
|
+
|
161443
|
+
this.maxIntervalCheckerId = null; // Background checker for max interval
|
161444
|
+
|
161445
|
+
this.previousHash = null; // Last saved content hash
|
161446
|
+
|
161447
|
+
this.lastSaveTime = 0; // Timestamp of last save
|
161448
|
+
|
161449
|
+
this.pendingChanges = false; // Flag for unsaved changes
|
161450
|
+
|
161451
|
+
this.isSaving = false; // Prevent concurrent saves
|
161452
|
+
// Start auto-save if configured
|
161453
|
+
|
161454
|
+
if (this.autoSave && typeof this.autoSave === 'function') {
|
161455
|
+
this.initAutoSave();
|
161404
161456
|
}
|
161405
161457
|
} // constructor
|
161458
|
+
// ---- AUTO-SAVE ----
|
161459
|
+
// Initialize auto-save system
|
161460
|
+
|
161461
|
+
|
161462
|
+
initAutoSave() {
|
161463
|
+
this.startMaxIntervalChecker();
|
161464
|
+
} // Start background checker to enforce max interval
|
161465
|
+
|
161466
|
+
|
161467
|
+
startMaxIntervalChecker() {
|
161468
|
+
this.maxIntervalCheckerId = setInterval(() => {
|
161469
|
+
// Only check if there are pending changes and not currently saving
|
161470
|
+
if (this.pendingChanges && !this.isSaving) {
|
161471
|
+
const now = Date.now();
|
161472
|
+
const timeSinceLastSave = now - this.lastSaveTime; // Force save if max interval exceeded
|
161473
|
+
|
161474
|
+
if (timeSinceLastSave >= this.maxAutoSaveInterval) {
|
161475
|
+
// console.log('Max interval reached - forcing save');
|
161476
|
+
this.performAutoSave();
|
161477
|
+
}
|
161478
|
+
}
|
161479
|
+
}, 1000); // Check every second
|
161480
|
+
} // Mark content as changed and schedule auto-save
|
161481
|
+
|
161482
|
+
|
161483
|
+
markContentChanged() {
|
161484
|
+
// Skip if auto-save not configured
|
161485
|
+
if (!this.autoSave) return; // Mark that changes exist
|
161486
|
+
|
161487
|
+
this.pendingChanges = true; // Initialize lastSaveTime on first change
|
161488
|
+
|
161489
|
+
if (this.lastSaveTime === 0) {
|
161490
|
+
this.lastSaveTime = Date.now();
|
161491
|
+
}
|
161492
|
+
|
161493
|
+
const now = Date.now();
|
161494
|
+
const timeSinceLastSave = now - this.lastSaveTime; // Clear any pending scheduled save
|
161495
|
+
|
161496
|
+
if (this.autoSaveTimeoutId) {
|
161497
|
+
clearTimeout(this.autoSaveTimeoutId);
|
161498
|
+
} // Scenario 1: Max interval reached - save immediately
|
161499
|
+
|
161500
|
+
|
161501
|
+
if (timeSinceLastSave >= this.maxAutoSaveInterval && !this.isSaving) {
|
161502
|
+
this.performAutoSave();
|
161503
|
+
} // Scenario 2: Min interval passed - schedule debounced save
|
161504
|
+
else if (timeSinceLastSave >= this.minAutoSaveInterval) {
|
161505
|
+
this.autoSaveTimeoutId = setTimeout(() => {
|
161506
|
+
this.performAutoSave();
|
161507
|
+
}, this.autoSaveDelay);
|
161508
|
+
} // Scenario 3: Too soon - schedule for later
|
161509
|
+
else {
|
161510
|
+
const delayUntilNextSave = this.minAutoSaveInterval - timeSinceLastSave;
|
161511
|
+
this.autoSaveTimeoutId = setTimeout(() => {
|
161512
|
+
if (this.pendingChanges) {
|
161513
|
+
this.performAutoSave();
|
161514
|
+
}
|
161515
|
+
}, delayUntilNextSave + this.autoSaveDelay);
|
161516
|
+
}
|
161517
|
+
} // Execute auto-save with change detection
|
161518
|
+
|
161519
|
+
|
161520
|
+
async performAutoSave() {
|
161521
|
+
// Prevent concurrent saves
|
161522
|
+
if (this.isSaving) return; // Get current content hash (lightweight check)
|
161523
|
+
|
161524
|
+
const htmlLight = this.htmlCheck();
|
161525
|
+
const currentHash = this.simpleHash(htmlLight); // Only save if content actually changed
|
161526
|
+
|
161527
|
+
if (this.previousHash !== currentHash) {
|
161528
|
+
this.isSaving = true;
|
161529
|
+
|
161530
|
+
try {
|
161531
|
+
// Call the save function
|
161532
|
+
await this.autoSave(); // console.log('Content auto-saved successfully.');
|
161533
|
+
// Update tracking state
|
161534
|
+
|
161535
|
+
this.previousHash = currentHash;
|
161536
|
+
this.lastSaveTime = Date.now();
|
161537
|
+
this.pendingChanges = false;
|
161538
|
+
} catch (error) {// console.error('Auto-save failed:', error);
|
161539
|
+
// Keep pendingChanges = true to retry later
|
161540
|
+
} finally {
|
161541
|
+
this.isSaving = false;
|
161542
|
+
}
|
161543
|
+
} else {
|
161544
|
+
// No actual changes detected
|
161545
|
+
this.pendingChanges = false;
|
161546
|
+
}
|
161547
|
+
} // Generate hash for efficient change detection
|
161548
|
+
|
161549
|
+
|
161550
|
+
simpleHash(str) {
|
161551
|
+
let hash = 0;
|
161552
|
+
|
161553
|
+
for (let i = 0; i < str.length; i++) {
|
161554
|
+
const char = str.charCodeAt(i);
|
161555
|
+
hash = (hash << 5) - hash + char; // hash * 31 + char
|
161556
|
+
|
161557
|
+
hash = hash & hash; // Convert to 32-bit integer
|
161558
|
+
}
|
161559
|
+
|
161560
|
+
return hash;
|
161561
|
+
} // Manually trigger save (useful for "Save" button)
|
161562
|
+
|
161563
|
+
|
161564
|
+
async saveNow() {
|
161565
|
+
if (this.pendingChanges && !this.isSaving) {
|
161566
|
+
await this.performAutoSave();
|
161567
|
+
}
|
161568
|
+
} //----
|
161406
161569
|
|
161407
161570
|
|
161408
161571
|
isNewV2() {
|
161409
161572
|
return this.wrapperEl.classList.contains('box-v2');
|
161410
161573
|
}
|
161411
161574
|
|
161575
|
+
loadFonts() {
|
161576
|
+
let contentStylePath = this.settings.contentStylePath;
|
161577
|
+
const wrapper = this.wrapperEl;
|
161578
|
+
const sections = wrapper.querySelectorAll('.is-section');
|
161579
|
+
sections.forEach(section => {
|
161580
|
+
section.classList.forEach(item => {
|
161581
|
+
if (item.indexOf('type-') !== -1) {
|
161582
|
+
const contentClass = item;
|
161583
|
+
const contentCss = item + '.css'; //Add css
|
161584
|
+
|
161585
|
+
let exist = false;
|
161586
|
+
let links = this.doc.getElementsByTagName('link');
|
161587
|
+
|
161588
|
+
for (let i = 0; i < links.length; i++) {
|
161589
|
+
let src = links[i].href.toLowerCase();
|
161590
|
+
if (src.indexOf(contentCss.toLowerCase()) !== -1) exist = true;
|
161591
|
+
}
|
161592
|
+
|
161593
|
+
if (!exist) {
|
161594
|
+
this.wrapperEl.insertAdjacentHTML('beforeend', '<link data-name="contentstyle" data-class="' + contentClass + '" href="' + contentStylePath + contentCss + '" rel="stylesheet">');
|
161595
|
+
}
|
161596
|
+
}
|
161597
|
+
});
|
161598
|
+
});
|
161599
|
+
}
|
161600
|
+
|
161412
161601
|
editorSetup() {
|
161413
161602
|
this.editor = new ContentBuilder({
|
161603
|
+
onType: () => {
|
161604
|
+
this.markContentChanged();
|
161605
|
+
},
|
161414
161606
|
quickAddButtons: this.settings.quickAddButtons,
|
161415
161607
|
assetManagerBasePath: this.settings.assetManagerBasePath || '',
|
161416
161608
|
assetAbsoluteBasePath: this.settings.assetAbsoluteBasePath || '',
|
@@ -161535,6 +161727,7 @@ Add an image for each feature.`, 'Create a new block showcasing a photo gallery
|
|
161535
161727
|
sectionTemplate: this.settings.sectionTemplate,
|
161536
161728
|
formTemplate: this.settings.formTemplate,
|
161537
161729
|
onBlockSectionAdd: () => {
|
161730
|
+
this.loadFonts();
|
161538
161731
|
this.pageSetup();
|
161539
161732
|
},
|
161540
161733
|
onBlockCanvasAdd: () => {
|
@@ -165304,7 +165497,23 @@ Add an image for each feature.`, 'Create a new block showcasing a photo gallery
|
|
165304
165497
|
}
|
165305
165498
|
|
165306
165499
|
destroy() {
|
165307
|
-
//
|
165500
|
+
// Save any pending changes before destroying
|
165501
|
+
if (this.pendingChanges && !this.isSaving) {
|
165502
|
+
this.performAutoSave();
|
165503
|
+
} // Clear debounce timer
|
165504
|
+
|
165505
|
+
|
165506
|
+
if (this.autoSaveTimeoutId) {
|
165507
|
+
clearTimeout(this.autoSaveTimeoutId);
|
165508
|
+
this.autoSaveTimeoutId = null;
|
165509
|
+
} // Clear background checker
|
165510
|
+
|
165511
|
+
|
165512
|
+
if (this.maxIntervalCheckerId) {
|
165513
|
+
clearInterval(this.maxIntervalCheckerId);
|
165514
|
+
this.maxIntervalCheckerId = null;
|
165515
|
+
}
|
165516
|
+
|
165308
165517
|
if (this.resizeObserver) this.resizeObserver.disconnect();
|
165309
165518
|
const elmStyleEditPanel = document.querySelector('#_style_editpanel');
|
165310
165519
|
if (elmStyleEditPanel) elmStyleEditPanel.remove(elmStyleEditPanel);
|