ブロックフック メディアクエリで表示切替

block-customize.php

require plugin_dir_path(__FILE__). 'includes/media-query.php';

src/media-query/style.scss

@media screen and (min-width: 768px) {
	.pc-hidden {
		display: none;
	}
}

@media screen and (max-width: 768px) {
	.sp-hidden {
		display: none;
	}
}

src/media-query/index.js

import { addFilter } from "@wordpress/hooks";
import {
	PanelBody,
	ToggleControl,
	ToolbarDropdownMenu,
} from "@wordpress/components";
import { createHigherOrderComponent } from "@wordpress/compose";
import { InspectorControls, BlockControls } from "@wordpress/block-editor";
import { hasBlockSupport } from "@wordpress/blocks";
import "./style.scss";

// settingsは各ブロックに設定可能なスタイル情報
export function addAttribute(settings) {
	const hasSupportCustomClassName = hasBlockSupport(
		settings.name,
		"customClassName",
		true,
	);
	if (!hasSupportCustomClassName) {
		return settings;
	}

	settings.attributes = {
		...settings.attributes,
		gttPcHidden: {
			type: "boolean",
		},
		gttSpHidden: {
			type: "boolean",
		},
	};
	return settings;
}

export const withInspectorControls = createHigherOrderComponent(
	(BlockEdit) => (props) => {
		// attributesはpropsの中身
		const {
			name,
			attributes: { gttPcHidden, gttSpHidden },
			setAttributes,
		} = props;

		// 追加CSSをサポートしていないブロック選択時には無効化
		const hasSupportCustomClassName = hasBlockSupport(
			name,
			"customClassName",
			true,
		);
		if (!hasSupportCustomClassName) {
			return <BlockEdit {...props} />;
		}

		const hiddenControls = [
			{
				title: "PC非表示",
				icon: <span class="dashicons dashicons-desktop"></span>,
				onClick: () => {
					setAttributes({ gttPcHidden: !gttPcHidden });
				},
			},
			{
				title: "スマホ非表示",
				icon: <span class="dashicons dashicons-smartphone"></span>,
				onClick: () => {
					setAttributes({ gttSpHidden: !gttSpHidden });
				},
			},
		];

		const getButtonIcon = () => {
			if (gttPcHidden && gttSpHidden) {
				return <span className="dashicons dashicons-hidden"></span>;
			} else if (gttSpHidden) {
				return <span className="dashicons dashicons-smartphone"></span>;
			} else if (gttPcHidden) {
				return <span className="dashicons dashicons-desktop"></span>;
			}
			return <span className="dashicons dashicons-visibility"></span>;
		};

		return (
			<>
				<BlockEdit {...props} />
				<BlockControls>
					<ToolbarDropdownMenu
						icon={getButtonIcon}
						label="メディアクエリ非表示設定"
						controls={hiddenControls}
					/>
				</BlockControls>
				<InspectorControls>
					<PanelBody title="メディアクエリ非表示設定">
						<ToggleControl
							label="PC非表示"
							// チェック状態を識別するデータの名称をgttIsLoginとする
							checked={gttPcHidden}
							onChange={(checked) => setAttributes({ gttPcHidden: checked })}
						/>
						<ToggleControl
							label="スマホ非表示"
							// チェック状態を識別するデータの名称をgttIsLoginとする
							checked={gttSpHidden}
							onChange={(checked) => setAttributes({ gttSpHidden: checked })}
						/>
					</PanelBody>
				</InspectorControls>
			</>
		);
	},
);

addFilter(
	"blocks.registerBlockType",
	"gtt/media-query/add-attributes",
	addAttribute,
);

addFilter(
	"editor.BlockEdit",
	"gtt/editor/media-query/with-inspector-controls",
	withInspectorControls,
);

includes/media-query.php

<?php

function gtt_add_attributes_media_query($settings, $metadata){
	// ブロックタイプを取得
	$block_type = WP_Block_Type_Registry::get_instance()->get_registered($metadata['name']);
	// カスタムCSSをサポートしていない場合は何もせずリターン
	if(! block_has_support( $block_type, array('customClassName'), true )){
		return $settings;
	}

	$attributes = array();
	if(!empty($settings['attributes'])){
		$attributes = $settings['attributes'];
	}

	$add_attributes = array(
		'gttPcHidden'=> array(
			'type' => 'boolean',
			'default'=> false
		),
		'gttSpHidden'=> array(
			'type' => 'boolean',
			'default'=> false
		),
	);

	$settings['attributes'] = array_merge(
		$attributes,
		$add_attributes
	);

	return $settings;
}

add_filter('block_type_metadata_settings','gtt_add_attributes_media_query',10,2);


function gtt_render_block_media_query($block_content, $block){
	$block_type = WP_Block_Type_Registry::get_instance()->get_registered($block['blockName']);
	if(! block_has_support( $block_type, array('customClassName'), true )){
		return $block_content;
	}

	// cssを読み込む
	if(!empty($block['attrs']['gttPcHidden']) || !empty($block['attrs']['gttSpHidden'])){
		wp_register_style(
			'gtt/media-query',
			plugin_dir_url(__DIR__) . 'build/style-index.css'
		);
		wp_enqueue_style('gtt/media-query');
	}
	// pc-hiddenとsp-hiddenのクラスを追加する
	if(!empty($block['attrs']['gttPcHidden']) && !empty($block['attrs']['gttSpHidden'])){
		// $block_content:ブロックのhtmlを所持
		$block_content = new WP_HTML_Tag_Processor($block_content);
		if($block_content->next_tag()){
			$block_content->add_class('pc-hidden sp-hidden');
			return $block_content->get_updated_html();
		}
	}

	// pc-hiddenのクラスを追加する
	if(!empty($block['attrs']['gttPcHidden'])){
		// $block_content:ブロックのhtmlを所持
		$block_content = new WP_HTML_Tag_Processor($block_content);
		if($block_content->next_tag()){
			$block_content->add_class('pc-hidden');
			return $block_content->get_updated_html();
		}
	}

	// sp-hiddenのクラスを追加する
	if(!empty($block['attrs']['gttSpHidden'])){
		// $block_content:ブロックのhtmlを所持
		$block_content = new WP_HTML_Tag_Processor($block_content);
		if($block_content->next_tag()){
			$block_content->add_class('sp-hidden');
			return $block_content->get_updated_html();
		}
	}

	return $block_content;
};

add_filter('render_block', 'gtt_render_block_media_query',10, 2);