Migrasi Slide & Slideshow Blocks
Gambaran Umum
Slide dan slideshow block mengikuti pola yang sama dengan banner block. Slide = hampir identik dengan banner (background image + InnerBlocks). Slideshow = wrapper sederhana yang menampung beberapa slide.
Slide Block
Langkah 1: functions.php
php
// Hapus/comment out:
// new JSXBlock("slide", true, [...]);
// Tambahkan di ourNewBlocks():
register_block_type_from_metadata(__DIR__ . "/build/slide");Langkah 2: Duplikasi folder banner
Duplikasi src/banner/ → rename jadi src/slide/ (karena sangat mirip).
Langkah 3: block.json
json
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "ourblocktheme/slide",
"title": "Slide",
"supports": {
"align": ["full"]
},
"attributes": {
"align": {
"type": "string",
"default": "full"
},
"themeimage": {
"type": "string"
},
"imgID": {
"type": "number"
},
"imgURL": {
"type": "string"
}
},
"editorScript": "file:./index.js",
"render": "file:./render.php"
}Perbedaan dari banner:
- Tambah attribute
themeimage(type: string) — untuk default image dari template HTML - Ini diperlukan agar WordPress mengenali attribute
themeimageyang datang dari template file
Langkah 4: render.php
Copy dari our-blocks/slide.php:
php
<div class="hero-slider__slide"
style="background-image: url(<?php echo esc_url($attributes['imgURL']); ?>)">
<div class="hero-slider__interior container">
<div class="hero-slider__overlay">
<?php echo $content; ?>
</div>
</div>
</div>Langkah 5: edit.js
Hampir identik dengan banner, tapi punya logika themeimage untuk fallback:
js
import { InspectorControls, MediaUpload, MediaUploadCheck, InnerBlocks, useBlockProps } from "@wordpress/block-editor";
import { PanelBody, PanelRow } from "@wordpress/components";
import { useEffect } from "@wordpress/element";
import apiFetch from "@wordpress/api-fetch";
export default function Edit(props) {
const blockProps = useBlockProps();
// useEffect 1: Set imgURL dari themeimage (default dari template)
useEffect(() => {
if (props.attributes.themeimage) {
props.setAttributes({
imgURL: `${ourThemeData.themePath}/images/${props.attributes.themeimage}`
});
}
}, [props.attributes.themeimage]);
// useEffect 2: Fallback jika TIDAK ada themeimage DAN belum ada imgURL
useEffect(() => {
if (!props.attributes.themeimage && !props.attributes.imgURL) {
props.setAttributes({
imgURL: `${ourThemeData.themePath}/images/library-hero.jpg`
});
}
}, []);
// useEffect 3: Fetch image URL dari media ID (saat user upload gambar)
useEffect(() => {
if (props.attributes.imgID) {
async function go() {
const response = await apiFetch({
path: `/wp/v2/media/${props.attributes.imgID}`,
method: "GET",
});
props.setAttributes({
imgURL: response.media_details.sizes.pageBanner?.source_url
?? response.media_details.sizes.full.source_url,
});
}
go();
}
}, [props.attributes.imgID]);
function onFileSelect(x) {
props.setAttributes({ imgID: x.id });
}
return (
<div {...blockProps}>
<InspectorControls>
<PanelBody title="Background" initialOpen={true}>
<PanelRow>
<MediaUploadCheck>
<MediaUpload
onSelect={onFileSelect}
value={props.attributes.imgID}
render={({ open }) => (
<button className="button button-large" onClick={open}>
Choose Background Image
</button>
)}
/>
</MediaUploadCheck>
</PanelRow>
</PanelBody>
</InspectorControls>
<div className="hero-slider__slide"
style={{ backgroundImage: `url('${props.attributes.imgURL}')` }}>
<div className="hero-slider__interior container">
<div className="hero-slider__overlay">
<InnerBlocks allowedBlocks={[
"ourblocktheme/genericheading",
"ourblocktheme/genericbutton"
]} />
</div>
</div>
</div>
</div>
);
}Logika themeimage Explained
Template file (front-page.html) bisa menyediakan default image per slide:
html
<!-- wp:ourblocktheme/slide {"themeimage":"bus.jpg"} -->
<!-- inner blocks -->
<!-- /wp:ourblocktheme/slide -->- Slide 1:
themeimage: "bus.jpg"→ourThemeData.themePath + "/images/bus.jpg" - Slide 2:
themeimage: "apples.jpg"→ourThemeData.themePath + "/images/apples.jpg" - Slide baru (tanpa themeimage): → fallback ke
library-hero.jpg
Langkah 6: index.js (sama dengan banner)
js
import { registerBlockType } from "@wordpress/blocks";
import { InnerBlocks } from "@wordpress/block-editor";
import metadata from "./block.json";
import Edit from "./edit";
registerBlockType(metadata.name, {
edit: Edit,
save: () => {
return <InnerBlocks.Content />;
},
});Slideshow Block
Langkah 1: functions.php
php
// Hapus/comment out:
// new JSXBlock("slideshow", false);
// Tambahkan di ourNewBlocks():
register_block_type_from_metadata(__DIR__ . "/build/slideshow");Langkah 2: Duplikasi folder slide → rename slideshow
Langkah 3: block.json (Lebih Sederhana)
json
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "ourblocktheme/slideshow",
"title": "Slideshow",
"supports": {
"align": ["full"]
},
"attributes": {
"align": {
"type": "string",
"default": "full"
}
},
"editorScript": "file:./index.js",
"render": "file:./render.php"
}Slideshow TIDAK butuh themeimage, imgID, atau imgURL — itu urusan setiap slide individual.
Langkah 4: render.php
Copy dari our-blocks/slideshow.php (Glide.js wrapper):
php
<div class="hero-slider">
<div data-glide-el="track" class="glide__track">
<div class="glide__slides">
<?php echo $content; ?>
</div>
</div>
<div data-glide-el="controls">
<button data-glide-dir="<">Prev</button>
<button data-glide-dir=">">Next</button>
</div>
</div>Langkah 5: edit.js (Sangat Sederhana)
js
import { InnerBlocks, useBlockProps } from "@wordpress/block-editor";
export default function Edit() {
const blockProps = useBlockProps();
return (
<div {...blockProps}>
<div className="hero-slider">
<InnerBlocks allowedBlocks={["ourblocktheme/slide"]} />
</div>
</div>
);
}Catatan:
- Tidak perlu
propsparameter (tidak ada dynamic attributes) - Tidak perlu
useEffectatauapiFetch - Hanya
InnerBlocksyang mengizinkan blockslidesaja - Tetap butuh
useBlockPropswrapper
Langkah 6: index.js (sama)
js
import { registerBlockType } from "@wordpress/blocks";
import { InnerBlocks } from "@wordpress/block-editor";
import metadata from "./block.json";
import Edit from "./edit";
registerBlockType(metadata.name, {
edit: Edit,
save: () => {
return <InnerBlocks.Content />;
},
});Setelah Selesai: Hapus File Lama
Hapus dari our-blocks/:
✗ slide.js
✗ slide.php
✗ slideshow.js
✗ slideshow.php
✗ banner.js
✗ banner.phpRingkasan Perbedaan Slide vs Slideshow vs Banner
| Fitur | Banner | Slide | Slideshow |
|---|---|---|---|
| Background Image | ✅ | ✅ | ❌ |
| themeimage attr | ❌ | ✅ | ❌ |
| InnerBlocks | heading + button | heading + button | slide |
| InspectorControls | ✅ (MediaUpload) | ✅ (MediaUpload) | ❌ |
| useEffect | 2x (fallback + fetch) | 3x (theme + fallback + fetch) | ❌ |
| Kompleksitas edit.js | Tinggi | Tinggi | Rendah |