UNPKG

itmar-block-packages

Version:

We have put together a package of common React components used for WordPress custom blocks.

179 lines (163 loc) 5.32 kB
import { MediaUpload, MediaUploadCheck } from "@wordpress/block-editor"; import { __ } from "@wordpress/i18n"; import { Button, PanelBody } from "@wordpress/components"; export function SingleImageSelect(props) { const { attributes } = props; const { mediaID, media } = attributes; //URL の配列から画像を生成 const getImage = (image) => { //メディアオブジェクトの配列をループ処理 return ( <figure> <img src={image.url} className="image" alt="アップロード画像" /> </figure> ); }; //メディアライブラリを開くボタンをレンダリングする関数 const getImageButton = (open) => { if (media) { return ( <div onClick={open} className="block-container"> {getImage(media)} </div> ); } else { return ( <div className="button-container"> <Button onClick={open} className="button button-large"> {__("Sel", "itmar_mv_blocks")} </Button> </div> ); } }; return ( <MediaUploadCheck> <MediaUpload onSelect={(media) => props.onSelectChange(media)} allowedTypes={["image"]} value={mediaID} render={({ open }) => getImageButton(open)} /> </MediaUploadCheck> ); } export function MultiImageSelect(props) { const { attributes, label } = props; const { mediaID, media } = attributes; //URL の配列から画像を生成 const getImages = (media) => { //メディアオブジェクトの配列をループ処理 let imagesArray = media.map((image, index) => { return ( <figure key={index}> <img src={image.url} className="image" alt="アップロード画像" /> <figcaption className="block-image-caption"> {image.caption ? image.caption : ""} </figcaption> </figure> ); }); return imagesArray; }; //メディアライブラリを開くボタンをレンダリングする関数 const getImageButton = (open) => { if (media.length > 0) { return ( <div key="media-container" onClick={open} className="block-container"> {getImages(media)} </div> ); } else { return ( <div key="media-container" className="button-container"> <Button onClick={open} className="button button-large"> {__("Image Upload", "slide-blocks")} </Button> </div> ); } }; return ( <PanelBody title={label} initialOpen={true} className="itmar_image_display"> <MediaUploadCheck> <MediaUpload multiple={true} gallery={true} //追加 onSelect={(media) => props.onSelectChange(media)} allowedTypes={["image"]} value={mediaID} render={({ open }) => getImageButton(open)} /> </MediaUploadCheck> {media.length != 0 && ( //メディアオブジェクト(配列の長さ)で判定 <MediaUploadCheck> <Button onClick={() => props.onAllDelete()} variant="secondary" isDestructive className="removeImage" > {__("Delete All", "slide-blocks")} </Button> </MediaUploadCheck> )} </PanelBody> ); } //静止画か動画かを判定する関数 export function getMediaType(url) { const imageExtensions = [ ".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp", ".svg", ]; const videoExtensions = [".mp4", ".webm", ".ogg", ".mov", ".m4v"]; // クエリストリング(?以降)を除去 const cleanUrl = url.split("?")[0].toLowerCase(); const isImage = imageExtensions.some((ext) => cleanUrl.endsWith(ext)); const isVideo = videoExtensions.some((ext) => cleanUrl.endsWith(ext)); if (isImage) { return "image"; } else if (isVideo) { return "video"; } else { // 拡張子で判別できない → HEADリクエストでContent-Type判定 or fallback return undefined; } } //静止画のアスペクト比を返す関数 export function getImageAspectRatio(url) { return new Promise((resolve, reject) => { const img = new Image(); img.onload = function () { const aspectRatio = img.naturalWidth / img.naturalHeight; resolve(aspectRatio); }; img.onerror = function () { reject(new Error("画像の読み込みに失敗しました: " + url)); }; img.src = url; }); } //動画のアスペクト比を返す関数 export function getVideoAspectRatio(url) { return new Promise((resolve, reject) => { const video = document.createElement("video"); video.preload = "metadata"; video.src = url; video.muted = true; // 一部のブラウザで安全に動作させるため video.playsInline = true; video.onloadedmetadata = function () { const aspectRatio = video.videoWidth / video.videoHeight; resolve(aspectRatio); }; video.onerror = function () { reject(new Error("動画の読み込みに失敗しました: " + url)); }; }); }