itmar-block-packages
Version:
We have put together a package of common React components used for WordPress custom blocks.
905 lines (873 loc) • 31.9 kB
JavaScript
import { __ } from "@wordpress/i18n";
import { useState, useEffect } from "@wordpress/element";
import {
Button,
PanelBody,
PanelRow,
__experimentalUnitControl as UnitControl,
ComboboxControl,
Icon,
ToolbarGroup,
ToolbarItem,
RangeControl,
TextControl,
RadioControl,
ToggleControl,
Modal,
} from "@wordpress/components";
import {
group,
stack,
layout,
justifyCenter,
justifyLeft,
justifyRight,
justifySpaceBetween,
justifyStretch,
stretchWide,
positionCenter,
} from "@wordpress/icons";
import GridControls from "./GridControls";
//横並びのアイコン
const flex = <Icon icon={stack} className="rotate-icon" />;
//上よせアイコン
const upper = <Icon icon={justifyLeft} className="rotate-icon" />;
//中央よせのアイコン
const middle = <Icon icon={justifyCenter} className="rotate-icon" />;
//下よせのアイコン
const lower = <Icon icon={justifyRight} className="rotate-icon" />;
//上下一杯に伸ばすアイコン
const vert_between = <Icon icon={justifyStretch} className="rotate-icon" />;
//上下均等に伸ばすアイコン
const vert_around = <Icon icon={justifySpaceBetween} className="rotate-icon" />;
export default function BlockPlace(props) {
const { attributes, clientId, blockRef, isMobile, isSubmenu, isParallax } =
props;
const { positionType, isPosCenter, default_val, mobile_val } = attributes;
//モバイルかデスクトップか
const sel_pos = isMobile ? mobile_val : default_val;
//配置アイコンの選択
const start_icon = sel_pos.direction === "vertical" ? upper : justifyLeft;
const center_icon = sel_pos.direction === "vertical" ? middle : justifyCenter;
const end_icon = sel_pos.direction === "vertical" ? lower : justifyRight;
const start_cross = sel_pos.direction === "vertical" ? justifyLeft : upper;
const center_cross =
sel_pos.direction === "vertical" ? justifyCenter : middle;
const end_cross = sel_pos.direction === "vertical" ? justifyRight : lower;
const stretch =
sel_pos.direction === "vertical" ? justifyStretch : vert_between;
const between_icon =
sel_pos.direction === "vertical" ? vert_between : justifyStretch;
const around_icon =
sel_pos.direction === "vertical" ? vert_around : justifySpaceBetween;
//ツールチップの選択
const start_tip =
sel_pos.direction === "vertical"
? __("upper alignment", "block-collections")
: __("left alignment", "block-collections");
const end_tip =
sel_pos.direction === "vertical"
? __("lower alignment", "block-collections")
: __("right alignment", "block-collections");
const cross_start_tip =
sel_pos.direction === "vertical"
? __("left alignment", "block-collections")
: __("upper alignment", "block-collections");
const cross_end_tip =
sel_pos.direction === "vertical"
? __("right alignment", "block-collections")
: __("lower alignment", "block-collections");
const [isContainer, setIsContainer] = useState(false);
const [isFlexItem, setIsFlexItem] = useState(false);
const [direction, setDirection] = useState("row");
useEffect(() => {
if (blockRef.current) {
const element = blockRef.current;
const parentElement = element.parentElement;
const grandparentElement = parentElement?.parentElement;
const computedStyle = getComputedStyle(grandparentElement);
//親要素がFlex又はGridコンテナか
if (
computedStyle.display === "flex" ||
computedStyle.display === "inline-flex" ||
computedStyle.display === "grid" ||
computedStyle.display === "inline-grid"
) {
setIsContainer(true);
}
//flexの時その方向
if (
computedStyle.display === "flex" ||
computedStyle.display === "inline-flex"
) {
setIsFlexItem(true);
if (
computedStyle.flexDirection === "row" ||
computedStyle.flexDirection === "row-reverse"
) {
setDirection("row");
} else {
setDirection("column");
}
}
}
}, []);
//GridModalを開く
const [isGridModalOpen, setIsGridModalOpen] = useState(false);
const openGridModal = () => setIsGridModalOpen(true);
const closeGridModal = () => setIsGridModalOpen(false);
// 翻訳が必要な文字列を直接指定
const blockMaxWidthMobile = __(
"Block Max Width(Mobile)",
"block-collections"
);
const blockWidthMobile = __("Block Width(Mobile)", "block-collections");
const blockMaxWidthDesktop = __(
"Block Max Width(DeskTop)",
"block-collections"
);
const blockWidthDesktop = __("Block Width(DeskTop)", "block-collections");
// 条件に応じて選択
const blockWidthLabel = isMobile
? isSubmenu
? blockWidthMobile
: blockMaxWidthMobile
: isSubmenu
? blockWidthDesktop
: blockMaxWidthDesktop;
return (
<>
<PanelBody
title={__("Block placement", "block-collections")}
initialOpen={false}
className="itmar_group_direction"
>
{isMobile ? (
<p>{__("InnerBlock direction(Mobile)", "block-collections")}</p>
) : (
<p>{__("InnerBlock direction(DeskTop)", "block-collections")}</p>
)}
<ToolbarGroup>
<ToolbarItem>
{(itemProps) => (
<Button
{...itemProps}
isPressed={sel_pos.direction === "block"}
onClick={() => props.onDirectionChange("block")}
icon={group}
label={__("block", "block-collections")}
/>
)}
</ToolbarItem>
<ToolbarItem>
{(itemProps) => (
<Button
{...itemProps}
isPressed={sel_pos.direction === "vertical"}
onClick={() => props.onDirectionChange("vertical")}
icon={stack}
label={__("virtical", "block-collections")}
/>
)}
</ToolbarItem>
<ToolbarItem>
{(itemProps) => (
<Button
{...itemProps}
isPressed={sel_pos.direction === "horizen"}
onClick={() => props.onDirectionChange("horizen")}
icon={flex}
label={__("horizen", "block-collections")}
/>
)}
</ToolbarItem>
<ToolbarItem>
{(itemProps) => (
<Button
{...itemProps}
isPressed={sel_pos.direction === "grid"}
onClick={() => props.onDirectionChange("grid")}
icon={layout}
label={__("grid", "block-collections")}
/>
)}
</ToolbarItem>
{(sel_pos.direction === "horizen" ||
sel_pos.direction === "vertical") && (
<PanelRow className="position_row">
<ToggleControl
label={__("reverse", "block-collections")}
checked={sel_pos.reverse}
onChange={(checked) => props.onReverseChange(checked)}
/>
<ToggleControl
label={__("wrap", "block-collections")}
checked={sel_pos.wrap}
onChange={(checked) => props.onWrapChange(checked)}
/>
</PanelRow>
)}
</ToolbarGroup>
{sel_pos.direction !== "block" && sel_pos.direction !== "grid" && (
<>
{isMobile ? (
<p>{__("InnerBlock Main Axis(Mobile)", "block-collections")}</p>
) : (
<p>{__("InnerBlock Main Axis(DeskTop)", "block-collections")}</p>
)}
<ToolbarGroup>
<ToolbarItem>
{(itemProps) => (
<Button
{...itemProps}
isPressed={sel_pos.inner_align === "flex-start"}
onClick={() =>
props.onFlexChange("flex-start", "inner_align")
} //親コンポーネントに通知
icon={start_icon}
label={start_tip}
/>
)}
</ToolbarItem>
<ToolbarItem>
{(itemProps) => (
<Button
{...itemProps}
isPressed={sel_pos.inner_align === "center"}
onClick={() => props.onFlexChange("center", "inner_align")} //親コンポーネントに通知
icon={center_icon}
label={__("center alignment", "block-collections")}
/>
)}
</ToolbarItem>
<ToolbarItem>
{(itemProps) => (
<Button
{...itemProps}
isPressed={sel_pos.inner_align === "flex-end"}
onClick={() =>
props.onFlexChange("flex-end", "inner_align")
} //親コンポーネントに通知
icon={end_icon}
label={end_tip}
/>
)}
</ToolbarItem>
<ToolbarItem>
{(itemProps) => (
<Button
{...itemProps}
isPressed={sel_pos.inner_align === "space-between"}
onClick={() =>
props.onFlexChange("space-between", "inner_align")
} //親コンポーネントに通知
icon={between_icon}
label={__("stretch", "block-collections")}
/>
)}
</ToolbarItem>
<ToolbarItem>
{(itemProps) => (
<Button
{...itemProps}
isPressed={sel_pos.inner_align === "space-around"}
onClick={() =>
props.onFlexChange("space-around", "inner_align")
} //親コンポーネントに通知
icon={around_icon}
label={__("around stretch", "block-collections")}
/>
)}
</ToolbarItem>
</ToolbarGroup>
</>
)}
{!isSubmenu &&
(isMobile ? (
<p>{__("InnerBlock Cross Axis(Mobile)", "block-collections")}</p>
) : (
<p>{__("InnerBlock Cross Axis(DeskTop)", "block-collections")}</p>
))}
{!isSubmenu && (
<ToolbarGroup>
<ToolbarItem>
{(itemProps) => (
<Button
{...itemProps}
isPressed={sel_pos.inner_items === "flex-start"}
onClick={() =>
props.onFlexChange("flex-start", "inner_items")
} //親コンポーネントに通知
icon={start_cross}
label={cross_start_tip}
/>
)}
</ToolbarItem>
<ToolbarItem>
{(itemProps) => (
<Button
{...itemProps}
isPressed={sel_pos.inner_items === "center"}
onClick={() => props.onFlexChange("center", "inner_items")} //親コンポーネントに通知
icon={center_cross}
label={__("center alignment", "block-collections")}
/>
)}
</ToolbarItem>
<ToolbarItem>
{(itemProps) => (
<Button
{...itemProps}
isPressed={sel_pos.inner_items === "flex-end"}
onClick={() => props.onFlexChange("flex-end", "inner_items")} //親コンポーネントに通知
icon={end_cross}
label={cross_end_tip}
/>
)}
</ToolbarItem>
<ToolbarItem>
{(itemProps) => (
<Button
{...itemProps}
isPressed={sel_pos.inner_items === "stretch"}
onClick={() => props.onFlexChange("stretch", "inner_items")} //親コンポーネントに通知
icon={stretch}
label={__("beteen stretch", "block-collections")}
/>
)}
</ToolbarItem>
</ToolbarGroup>
)}
{isContainer && (
<>
{isMobile ? (
<p>{__("Alignment in container(Mobile)", "block-collections")}</p>
) : (
<p>
{__("Alignment in container(DeskTop)", "block-collections")}
</p>
)}
<ToolbarGroup>
<ToolbarItem>
{(itemProps) => (
<Button
{...itemProps}
isPressed={
direction === "row"
? sel_pos.outer_vertical === "self-start"
: sel_pos.outer_align === "left"
}
onClick={
direction === "row"
? () => props.onVerticalChange("self-start")
: () => props.onAlignChange("left")
}
icon={direction === "row" ? upper : justifyLeft}
label={
direction === "row"
? __("upper alignment", "block-collections")
: __("left alignment", "block-collections")
}
/>
)}
</ToolbarItem>
<ToolbarItem>
{(itemProps) => (
<Button
{...itemProps}
isPressed={
direction === "row"
? sel_pos.outer_vertical === "center"
: sel_pos.outer_align === "center"
}
onClick={
direction === "row"
? () => props.onVerticalChange("center")
: () => props.onAlignChange("center")
}
icon={direction === "row" ? middle : justifyCenter}
label={__("center alignment", "block-collections")}
/>
)}
</ToolbarItem>
<ToolbarItem>
{(itemProps) => (
<Button
{...itemProps}
isPressed={
direction === "row"
? sel_pos.outer_vertical === "self-end"
: sel_pos.outer_align === "right"
}
onClick={
direction === "row"
? () => props.onVerticalChange("self-end")
: () => props.onAlignChange("right")
}
icon={direction === "row" ? lower : justifyRight}
label={
direction === "row"
? __("lower alignment", "block-collections")
: __("right alignment", "block-collections")
}
/>
)}
</ToolbarItem>
<ToolbarItem>
{(itemProps) => (
<Button
{...itemProps}
isPressed={sel_pos.outer_vertical === "stretch"}
onClick={
direction === "row"
? () => props.onVerticalChange("stretch")
: () => props.onAlignChange("stretch")
}
icon={direction === "row" ? vert_between : justifyStretch}
label={__("stretch", "block-collections")}
/>
)}
</ToolbarItem>
</ToolbarGroup>
</>
)}
<BlockWidth
attributes={attributes}
isMobile={isMobile}
isSubmenu={isSubmenu}
onWidthChange={(key, widthVal) => props.onWidthChange(key, widthVal)}
onFreeWidthChange={(key, freeVal) =>
props.onFreeWidthChange(key, freeVal)
}
/>
{isFlexItem && (
<PanelRow className="position_row">
<TextControl
label={__("grow", "block-collections")}
labelPosition="left"
value={sel_pos.flex?.grow}
onChange={(newValue) => {
const flexObj = {
grow: newValue,
shrink: sel_pos.flex?.shrink,
basis: sel_pos.flex?.basis,
};
props.onFlexItemChange(flexObj);
}}
/>
<TextControl
label={__("shrink", "block-collections")}
labelPosition="left"
value={sel_pos.flex?.shrink}
onChange={(newValue) => {
const flexObj = {
grow: sel_pos.flex?.grow,
shrink: newValue,
basis: sel_pos.flex?.basis,
};
props.onFlexItemChange(flexObj);
}}
/>
<TextControl
label={__("basis", "block-collections")}
labelPosition="left"
value={sel_pos.flex?.basis}
onChange={(newValue) => {
const flexObj = {
grow: sel_pos.flex?.grow,
shrink: sel_pos.flex?.shrink,
basis: newValue,
};
props.onFlexItemChange(flexObj);
}}
/>
</PanelRow>
)}
<BlockHeight
attributes={attributes}
isMobile={isMobile}
onHeightChange={(heightVal) => props.onHeightChange(heightVal)}
onFreeHeightChange={(freeVal) => props.onFreeHeightChange(freeVal)}
/>
{sel_pos.direction === "grid" && (
<>
{isMobile ? (
<p>{__("Grid Info settings(Mobile)", "block-collections")}</p>
) : (
<p>{__("Grid Info settings(DeskTop)", "block-collections")}</p>
)}
<Button variant="primary" onClick={openGridModal}>
{__("Open Setting Modal", "block-collections")}
</Button>
{isGridModalOpen && (
<Modal title="Grid Info settings" onRequestClose={closeGridModal}>
<GridControls
attributes={sel_pos.grid_info}
clientId={clientId}
onChange={(newValue) => {
props.onGridChange(newValue);
}}
/>
</Modal>
)}
</>
)}
<div className="itmar_title_type">
<RadioControl
label={__("Position Type", "block-collections")}
selected={positionType}
options={[
{ label: __("Static", "block-collections"), value: "staic" },
{
label: __("Relative", "block-collections"),
value: "relative",
},
{
label: __("Absolute", "block-collections"),
value: "absolute",
},
{ label: __("Fix", "block-collections"), value: "fixed" },
{ label: __("Sticky", "block-collections"), value: "sticky" },
]}
onChange={(newVal) => {
props.onPositionChange(newVal);
}}
/>
</div>
{positionType === "absolute" && !isParallax && (
<ToggleControl
label={__(
"Center Vertically and Horizontally",
"block-collections"
)}
checked={isPosCenter}
onChange={(newVal) => {
props.onIsPosCenterChange(newVal);
}}
/>
)}
{((positionType === "absolute" && !isPosCenter) ||
positionType === "fixed" ||
positionType === "sticky") && (
<>
{isMobile ? (
<p>{__("Block Position(Mobile)", "block-collections")}</p>
) : (
<p>{__("Block Position(DeskTop)", "block-collections")}</p>
)}
<PanelBody
title={__("Vertical", "block-collections")}
initialOpen={true}
>
{!sel_pos.posValue?.isVertCenter && (
<PanelRow className="position_row">
<ComboboxControl
options={[
{ value: "top", label: "Top" },
{ value: "bottom", label: "Bottom" },
]}
value={sel_pos.posValue?.vertBase || "top"}
onChange={(newValue) => {
const newValObj = {
...(sel_pos.posValue || {}),
vertBase: newValue,
};
props.onPosValueChange(newValObj);
}}
/>
<UnitControl
dragDirection="e"
onChange={(newValue) => {
const newValObj = {
...(sel_pos.posValue || {}),
vertValue: newValue,
};
props.onPosValueChange(newValObj);
}}
value={sel_pos.posValue?.vertValue || "3em"}
/>
</PanelRow>
)}
{!isParallax && (
<ToggleControl
label={__("Is Center", "block-collections")}
checked={sel_pos.posValue?.isVertCenter}
onChange={(newValue) => {
const newValObj = {
...(sel_pos.posValue || {}),
isVertCenter: newValue,
};
props.onPosValueChange(newValObj);
}}
/>
)}
</PanelBody>
<PanelBody
title={__("Horizon", "block-collections")}
initialOpen={true}
>
{!sel_pos.posValue?.isHorCenter && (
<PanelRow className="position_row">
<ComboboxControl
options={[
{ value: "left", label: "Left" },
{ value: "right", label: "Right" },
]}
value={sel_pos.posValue?.horBase || "left"}
onChange={(newValue) => {
const newValObj = {
...(sel_pos.posValue || {}),
horBase: newValue,
};
props.onPosValueChange(newValObj);
}}
/>
<UnitControl
dragDirection="e"
onChange={(newValue) => {
const newValObj = {
...(sel_pos.posValue || {}),
horValue: newValue,
};
props.onPosValueChange(newValObj);
}}
value={sel_pos.posValue?.horValue || "3em"}
/>
</PanelRow>
)}
{!isParallax && (
<ToggleControl
label={__("Is Center", "block-collections")}
checked={sel_pos.posValue?.isHorCenter}
onChange={(newValue) => {
const newValObj = {
...(sel_pos.posValue || {}),
isHorCenter: newValue,
};
props.onPosValueChange(newValObj);
}}
/>
)}
</PanelBody>
</>
)}
</PanelBody>
</>
);
}
export function BlockWidth(props) {
const { attributes, isMobile, flexDirection, isSubmenu } = props;
const { default_val, mobile_val } = attributes;
//モバイルかデスクトップか
const sel_pos = isMobile ? mobile_val : default_val;
// 翻訳が必要な文字列を直接指定
const blockMaxWidthMobile = __(
"Block Max Width(Mobile)",
"block-collections"
);
const blockWidthMobile = __("Block Width(Mobile)", "block-collections");
const blockMaxWidthDesktop = __(
"Block Max Width(DeskTop)",
"block-collections"
);
const blockWidthDesktop = __("Block Width(DeskTop)", "block-collections");
// ラベル
const widthLabel = isMobile ? blockWidthMobile : blockWidthDesktop;
const maxWidthLabel = isMobile ? blockMaxWidthMobile : blockMaxWidthDesktop;
return (
<>
<p>{widthLabel}</p>
<ToolbarGroup>
<ToolbarItem>
{(itemProps) => (
<Button
{...itemProps}
isPressed={sel_pos.width_val === "full"}
onClick={() => props.onWidthChange("width_val", "full")}
text="full"
/>
)}
</ToolbarItem>
<ToolbarItem>
{(itemProps) => (
<Button
{...itemProps}
isPressed={sel_pos.width_val === "fit"}
onClick={() => props.onWidthChange("width_val", "fit")}
text="fit"
/>
)}
</ToolbarItem>
<ToolbarItem>
{(itemProps) => (
<Button
{...itemProps}
isPressed={sel_pos.width_val === "wideSize"}
onClick={() => props.onWidthChange("width_val", "wideSize")}
icon={stretchWide}
label={__("Wide Size", "block-collections")}
/>
)}
</ToolbarItem>
<ToolbarItem>
{(itemProps) => (
<Button
{...itemProps}
isPressed={sel_pos.width_val === "contentSize"}
onClick={() => props.onWidthChange("width_val", "contentSize")}
icon={positionCenter}
label={__("Content Size", "block-collections")}
/>
)}
</ToolbarItem>
<ToolbarItem>
{(itemProps) => (
<Button
{...itemProps}
isPressed={sel_pos.width_val === "free"}
onClick={() => props.onWidthChange("width_val", "free")}
text="free"
/>
)}
</ToolbarItem>
</ToolbarGroup>
{sel_pos.width_val === "free" && (
<UnitControl
dragDirection="e"
onChange={(newValue) =>
props.onFreeWidthChange("free_width", newValue)
}
value={sel_pos.free_width}
/>
)}
<p>{maxWidthLabel}</p>
<ToolbarGroup>
<ToolbarItem>
{(itemProps) => (
<Button
{...itemProps}
isPressed={sel_pos.max_width === "full"}
onClick={() => props.onWidthChange("max_width", "full")}
text="full"
/>
)}
</ToolbarItem>
<ToolbarItem>
{(itemProps) => (
<Button
{...itemProps}
isPressed={sel_pos.max_width === "fit"}
onClick={() => props.onWidthChange("max_width", "fit")}
text="fit"
/>
)}
</ToolbarItem>
<ToolbarItem>
{(itemProps) => (
<Button
{...itemProps}
isPressed={sel_pos.max_width === "wideSize"}
onClick={() => props.onWidthChange("max_width", "wideSize")}
icon={stretchWide}
label={__("Wide Size", "block-collections")}
/>
)}
</ToolbarItem>
<ToolbarItem>
{(itemProps) => (
<Button
{...itemProps}
isPressed={sel_pos.max_width === "contentSize"}
onClick={() => props.onWidthChange("max_width", "contentSize")}
icon={positionCenter}
label={__("Content Size", "block-collections")}
/>
)}
</ToolbarItem>
<ToolbarItem>
{(itemProps) => (
<Button
{...itemProps}
isPressed={sel_pos.max_width === "free"}
onClick={() => props.onWidthChange("max_width", "free")}
text="free"
/>
)}
</ToolbarItem>
</ToolbarGroup>
{sel_pos.max_width === "free" && (
<UnitControl
dragDirection="e"
onChange={(newValue) =>
props.onFreeWidthChange("max_free_width", newValue)
}
value={sel_pos.max_free_width}
/>
)}
</>
);
}
export function BlockHeight(props) {
const { attributes, isMobile } = props;
const { default_val, mobile_val } = attributes;
//モバイルかデスクトップか
const sel_pos = isMobile ? mobile_val : default_val;
return (
<>
{isMobile ? (
<p>{__("Block Height(Mobile)", "block-collections")}</p>
) : (
<p>{__("Block Height(DeskTop)", "block-collections")}</p>
)}
<ToolbarGroup>
<ToolbarItem>
{(itemProps) => (
<Button
{...itemProps}
isPressed={sel_pos.height_val === "full"}
onClick={() => props.onHeightChange("full")}
text="full"
/>
)}
</ToolbarItem>
<ToolbarItem>
{(itemProps) => (
<Button
{...itemProps}
isPressed={sel_pos.height_val === "fit"}
onClick={() => props.onHeightChange("fit")}
text="fit"
/>
)}
</ToolbarItem>
<ToolbarItem>
{(itemProps) => (
<Button
{...itemProps}
isPressed={sel_pos.height_val === "free"}
onClick={() => props.onHeightChange("free")}
text="free"
/>
)}
</ToolbarItem>
<ToolbarItem>
{(itemProps) => (
<Button
{...itemProps}
isPressed={sel_pos.height_val === "auto"}
onClick={() => props.onHeightChange("auto")}
text="auto"
/>
)}
</ToolbarItem>
</ToolbarGroup>
{sel_pos.height_val === "free" && (
<UnitControl
dragDirection="e"
onChange={(newValue) => props.onFreeHeightChange(newValue)}
value={sel_pos.free_height}
/>
)}
</>
);
}