I have a plugin that registers four different Gutenberg blocks. I build them using the build script from the wp-scripts package. As you all surely know, this script automatically generates an index.asset.php file with an array with all the script dependencies for each block. For example:
<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-element', 'wp-i18n', 'wp-primitives'), 'version' => 'a955a4059265b7ad1ce6');
I need to add the masonry script (included in WP) to this dependency array in just ONE (not ALL) of the blocks, like this:
<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-element', 'wp-i18n', 'wp-primitives', 'masonry'), 'version' => 'a955a4059265b7ad1ce6');
I know that I can add this dependency manually after I build the blocks, but I'm wondering if there's a way to do this automatically via the block block.json file, a custom webpack.config.js file or anything else.
The contents of the block.json file is:
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "my/masonry-block",
"title": "My Masonry Block",
"description": "Display a Masonry gallery.",
"textdomain": "my-domain",
"category": "media",
"attributes": {
"items": {
"type": "array",
"default": []
},
"columns": {
"type": "number",
"minimum": 1,
"maximum": 8,
"default": 3
},
"gap": {
"type": "string",
"default": "10px"
},
"captions": {
"type": "boolean",
"default": false
}
},
"supports": {
"spacing": {
"margin": true,
"padding": true
},
"align": [ "center" ]
},
"editorScript": [
"file:./index.js",
"imagesloaded",
"masonry"
],
"viewScript": [
"file:./view.js",
"imagesloaded",
"masonry"
],
"style": [
"file:./style-index.css",
"file:./view.css"
],
"editorStyle": "file:./index.css"
}
I'm registering the block with:
register_block_type(
__DIR__ . '/build/blocks/masonry',
array(
'render_callback' => array( $this, 'render_block_masonry' ),
)
);
This is the block edit function (some code omitted for brevity):
const displayItems = (items) => {
return (
items.map((item, index) => {
return (
<div className="gallery-item" key={index}>
<figure>
<a data-rel="collection" href={item.url} data-sub-html={item.caption}>
<img className={`wp-image-${item.id}`} src={item.url} alt={item.alt} key={item.id} />
</a>
{captions && item.caption &&
<figcaption className="wp-element-caption">
{item.caption}
</figcaption>
}
</figure>
</div>
)
})
)
};
const containerMasonryRef = useRefEffect((element) => {
var msnry;
const { ownerDocument } = element;
const { defaultView } = ownerDocument;
if (!defaultView.imagesLoaded || !defaultView.Masonry) {
console.log('scripts not loaded');
return;
}
imagesLoaded(element, function () {
console.log('images loaded');
msnry = new defaultView.Masonry(element, {
itemSelector: '.gallery-item',
columnWidth: '.grid-sizer',
percentPosition: true,
gutter: parseInt(gap),
});
});
return () => {
msnry?.destroy();
}
}, [items, columns, gap, captions]);
const containerLightboxRef = useRefEffect((element) => {
lightGallery(element, {
selector: 'a[data-rel^=collection]',
mode: 'lg-fade',
preload: 4,
counter: false,
download: false,
youtubePlayerParams: {
autoplay: 0
},
vimeoPlayerParams: {
autoplay: 0
}
});
return () => {
window?.lgData[element?.getAttribute('lg-uid')]?.destroy(true);
}
}, []);
const mergedRefs = useMergeRefs([
containerMasonryRef,
containerLightboxRef,
]);
return (
<>
<InspectorControls>
<PanelBody
title={__('Settings')}
>
<RangeControl
label={__('Columns')}
value={columns}
onChange={setColumns}
min={1}
max={8}
/>
<UnitControl
label={__('Gap between items')}
min="0"
onChange={setGap}
value={gap}
units={units}
/>
</PanelBody>
</InspectorControls>
<BlockControls group="block">
<ToolbarButton
onClick={toggleCaptions}
icon={captionIcon}
isPressed={captions}
label={
captions
? __('Hide captions')
: __('Show captions')
}
/>
</BlockControls>
<BlockControls group="other">
{items.length > 0 && (
<ToolbarGroup>
<MediaUploadCheck>
<MediaUpload
allowedTypes={['image']}
multiple={true}
gallery={true}
value={items.map((item) => item.id)}
onSelect={setItems}
render={({ open }) => (
<ToolbarButton onClick={open}>
{__('Edit items')}
</ToolbarButton>)}
/>
</MediaUploadCheck>
</ToolbarGroup>
)}
</BlockControls>
<MediaUploadCheck>
{items.length > 0 ?
<div {...blockProps}>
<div className="gallery-items" style={{ '--gap': gap }} ref={mergedRefs}>
<div className="grid-sizer"></div>
{displayItems(items)}
</div>
</div>
:
<MediaPlaceholder
accept="image/*"
allowedTypes={['image']}
onSelect={setItems}
multiple={true}
gallery={true}
addToGallery={true}
handleUpload={true}
labels={
{ title: __('My Masonry Block') }
}
/>
}
</MediaUploadCheck>
</>
);