@innovastudio/contentbox 1.6.157 → 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
|
}
|
@@ -126130,6 +126134,11 @@ Please obtain a license at: https://innovastudio.com/contentbox`);
|
|
126130
126134
|
this.elmTool.hide();
|
126131
126135
|
}
|
126132
126136
|
typing() {
|
126137
|
+
// Lightweight: Just mark content changed for auto-save
|
126138
|
+
if (this.opts.onType) {
|
126139
|
+
this.opts.onType();
|
126140
|
+
}
|
126141
|
+
|
126133
126142
|
// console.log('typing');
|
126134
126143
|
if (this.timeoutId) clearTimeout(this.timeoutId);
|
126135
126144
|
this.timeoutId = setTimeout(() => {
|
@@ -161180,8 +161189,13 @@ Add an image for each feature.`, 'Create a new block showcasing a photo gallery
|
|
161180
161189
|
|
161181
161190
|
let old2 = this.settings.onChange;
|
161182
161191
|
|
161183
|
-
this.settings.onChange = () => {
|
161184
|
-
|
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();
|
161185
161199
|
setTimeout(() => {
|
161186
161200
|
// this.quickPosTool();
|
161187
161201
|
this.editor.livePreview.previewRefresh();
|
@@ -161411,16 +161425,184 @@ Add an image for each feature.`, 'Create a new block showcasing a photo gallery
|
|
161411
161425
|
}, this);
|
161412
161426
|
} else {
|
161413
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();
|
161414
161456
|
}
|
161415
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
|
+
} //----
|
161416
161569
|
|
161417
161570
|
|
161418
161571
|
isNewV2() {
|
161419
161572
|
return this.wrapperEl.classList.contains('box-v2');
|
161420
161573
|
}
|
161421
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
|
+
|
161422
161601
|
editorSetup() {
|
161423
161602
|
this.editor = new ContentBuilder({
|
161603
|
+
onType: () => {
|
161604
|
+
this.markContentChanged();
|
161605
|
+
},
|
161424
161606
|
quickAddButtons: this.settings.quickAddButtons,
|
161425
161607
|
assetManagerBasePath: this.settings.assetManagerBasePath || '',
|
161426
161608
|
assetAbsoluteBasePath: this.settings.assetAbsoluteBasePath || '',
|
@@ -161545,6 +161727,7 @@ Add an image for each feature.`, 'Create a new block showcasing a photo gallery
|
|
161545
161727
|
sectionTemplate: this.settings.sectionTemplate,
|
161546
161728
|
formTemplate: this.settings.formTemplate,
|
161547
161729
|
onBlockSectionAdd: () => {
|
161730
|
+
this.loadFonts();
|
161548
161731
|
this.pageSetup();
|
161549
161732
|
},
|
161550
161733
|
onBlockCanvasAdd: () => {
|
@@ -165314,7 +165497,23 @@ Add an image for each feature.`, 'Create a new block showcasing a photo gallery
|
|
165314
165497
|
}
|
165315
165498
|
|
165316
165499
|
destroy() {
|
165317
|
-
//
|
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
|
+
|
165318
165517
|
if (this.resizeObserver) this.resizeObserver.disconnect();
|
165319
165518
|
const elmStyleEditPanel = document.querySelector('#_style_editpanel');
|
165320
165519
|
if (elmStyleEditPanel) elmStyleEditPanel.remove(elmStyleEditPanel);
|