Files
michaelschiemer/resources/js/modules/admin/block-editor-asset-picker.js
2025-11-24 21:28:25 +01:00

133 lines
4.5 KiB
JavaScript

/**
* Block Editor Asset Picker Integration
*
* Handles asset selection from AssetPickerComponent and updates block fields
*/
export class BlockEditorAssetPicker {
constructor(blockEditorElement, blockEditorComponentId) {
this.blockEditorElement = blockEditorElement;
this.blockEditorComponentId = blockEditorComponentId;
this.init();
}
init() {
// Listen for asset selection events from AssetPickerComponent
document.addEventListener('livecomponent:event', (e) => {
const eventData = e.detail;
if (eventData && eventData.event_name === 'asset:selected') {
// Find the asset picker component that triggered this
const assetPickerElement = e.target.closest('[data-live-component^="admin-asset-picker:"]');
if (assetPickerElement) {
this.handleAssetSelected(eventData, assetPickerElement);
}
}
});
// Also listen for direct asset selection from AssetPickerComponent
this.blockEditorElement.addEventListener('click', (e) => {
const pickerItem = e.target.closest('[data-live-action="selectAsset"]');
if (pickerItem) {
const assetId = pickerItem.dataset.assetId;
if (assetId) {
// Find which block field this picker is for
const fieldWrapper = pickerItem.closest('.admin-asset-picker-wrapper');
if (fieldWrapper) {
const fieldInput = fieldWrapper.querySelector('input[data-param-field-path]');
if (fieldInput) {
const blockId = fieldInput.dataset.paramBlockId;
const fieldPath = fieldInput.dataset.paramFieldPath;
if (blockId && fieldPath) {
this.selectAssetForBlock(blockId, fieldPath, assetId);
}
}
}
}
}
});
}
/**
* Handle asset selected event
*/
handleAssetSelected(eventData, assetPickerElement) {
// Find the block field this picker is associated with
const fieldWrapper = assetPickerElement.closest('.admin-asset-picker-wrapper');
if (!fieldWrapper) {
return;
}
const fieldInput = fieldWrapper.querySelector('input[data-param-field-path]');
if (!fieldInput) {
return;
}
const blockId = fieldInput.dataset.paramBlockId;
const fieldPath = fieldInput.dataset.paramFieldPath;
const assetId = eventData.asset_id || eventData.selected_asset_id;
if (blockId && fieldPath && assetId) {
this.selectAssetForBlock(blockId, fieldPath, assetId);
}
}
/**
* Select asset for a block field
*/
async selectAssetForBlock(blockId, fieldPath, assetId) {
const liveComponent = window.LiveComponents?.getComponent?.(this.blockEditorComponentId);
if (!liveComponent) {
console.warn('BlockEditorAssetPicker: LiveComponent instance not found');
return;
}
try {
await liveComponent.action('selectAssetForBlock', {
blockId,
fieldPath,
assetId
});
} catch (error) {
console.error('BlockEditorAssetPicker: Failed to select asset', error);
}
}
/**
* Initialize all asset pickers in block editor
*/
static initializeAll() {
const instances = [];
// Find all BlockEditorComponents
const blockEditorElements = document.querySelectorAll(
'[data-live-component^="admin-block-editor:"]'
);
blockEditorElements.forEach(blockEditorElement => {
const componentId = blockEditorElement.dataset.liveComponent;
if (componentId) {
instances.push(new BlockEditorAssetPicker(blockEditorElement, componentId));
}
});
return instances;
}
}
// Auto-initialize when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => {
BlockEditorAssetPicker.initializeAll();
});
} else {
BlockEditorAssetPicker.initializeAll();
}
// Re-initialize when LiveComponents are loaded dynamically
document.addEventListener('livecomponent:loaded', () => {
BlockEditorAssetPicker.initializeAll();
});