Some checks failed
Deploy Application / deploy (push) Has been cancelled
139 lines
4.3 KiB
JavaScript
139 lines
4.3 KiB
JavaScript
/**
|
|
* Block Editor Auto-Sync
|
|
*
|
|
* Automatically syncs blocks from BlockEditorComponent to ContentFormComponent
|
|
* when blocks are added, removed, updated, or reordered.
|
|
*/
|
|
|
|
export class BlockEditorSync {
|
|
constructor(blockEditorElement, contentFormComponentId) {
|
|
this.blockEditorElement = blockEditorElement;
|
|
this.contentFormComponentId = contentFormComponentId;
|
|
this.syncDebounceTimer = null;
|
|
this.SYNC_DEBOUNCE_MS = 500; // Debounce sync calls by 500ms
|
|
|
|
this.init();
|
|
}
|
|
|
|
init() {
|
|
// Listen for LiveComponent update events
|
|
this.blockEditorElement.addEventListener('livecomponent:updated', (e) => {
|
|
this.handleBlockEditorUpdate(e);
|
|
});
|
|
|
|
// Also listen for custom block events
|
|
document.addEventListener('livecomponent:event', (e) => {
|
|
const eventData = e.detail;
|
|
if (eventData && eventData.component_id) {
|
|
const blockEditorId = this.blockEditorElement.dataset.liveComponent;
|
|
if (eventData.component_id === blockEditorId) {
|
|
// Check if it's a block-related event
|
|
if (eventData.event_name && (
|
|
eventData.event_name.includes('block:') ||
|
|
eventData.event_name.includes('blocks:')
|
|
)) {
|
|
this.scheduleSync();
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Handle BlockEditorComponent update
|
|
*/
|
|
handleBlockEditorUpdate(e) {
|
|
// Debounce sync to avoid too many requests
|
|
this.scheduleSync();
|
|
}
|
|
|
|
/**
|
|
* Schedule sync with debouncing
|
|
*/
|
|
scheduleSync() {
|
|
if (this.syncDebounceTimer) {
|
|
clearTimeout(this.syncDebounceTimer);
|
|
}
|
|
|
|
this.syncDebounceTimer = setTimeout(() => {
|
|
this.syncBlocks();
|
|
}, this.SYNC_DEBOUNCE_MS);
|
|
}
|
|
|
|
/**
|
|
* Sync blocks from BlockEditorComponent to ContentFormComponent
|
|
*/
|
|
async syncBlocks() {
|
|
if (!this.contentFormComponentId) {
|
|
console.warn('BlockEditorSync: No content form component ID');
|
|
return;
|
|
}
|
|
|
|
// Find ContentFormComponent element
|
|
const contentFormElement = document.querySelector(
|
|
`[data-live-component="${this.contentFormComponentId}"]`
|
|
);
|
|
|
|
if (!contentFormElement) {
|
|
console.warn('BlockEditorSync: ContentFormComponent not found');
|
|
return;
|
|
}
|
|
|
|
// Get LiveComponent instance
|
|
const liveComponent = window.LiveComponents?.getComponent?.(this.contentFormComponentId);
|
|
|
|
if (!liveComponent) {
|
|
console.warn('BlockEditorSync: LiveComponent instance not found');
|
|
return;
|
|
}
|
|
|
|
// Call syncBlocksFromBlockEditor action on ContentFormComponent
|
|
try {
|
|
await liveComponent.action('syncBlocksFromBlockEditor');
|
|
} catch (error) {
|
|
console.error('BlockEditorSync: Failed to sync blocks', error);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initialize all block editor syncs on the page
|
|
*/
|
|
static initializeAll() {
|
|
const instances = [];
|
|
|
|
// Find all BlockEditorComponents
|
|
const blockEditorElements = document.querySelectorAll(
|
|
'[data-live-component^="admin-block-editor:"]'
|
|
);
|
|
|
|
blockEditorElements.forEach(blockEditorElement => {
|
|
// Find parent ContentFormComponent
|
|
const contentFormElement = blockEditorElement.closest(
|
|
'[data-live-component^="admin-content-form:"]'
|
|
);
|
|
|
|
if (contentFormElement) {
|
|
const contentFormComponentId = contentFormElement.dataset.liveComponent;
|
|
instances.push(new BlockEditorSync(blockEditorElement, contentFormComponentId));
|
|
}
|
|
});
|
|
|
|
return instances;
|
|
}
|
|
}
|
|
|
|
// Auto-initialize when DOM is ready
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
BlockEditorSync.initializeAll();
|
|
});
|
|
} else {
|
|
BlockEditorSync.initializeAll();
|
|
}
|
|
|
|
// Re-initialize when LiveComponents are loaded dynamically
|
|
document.addEventListener('livecomponent:loaded', () => {
|
|
BlockEditorSync.initializeAll();
|
|
});
|
|
|