| 1 |
import { InnerBlocks, useBlockProps, store as blockEditorStore, BlockControls } from "@wordpress/block-editor"; |
| 2 |
import { useEffect, useMemo, useState } from "@wordpress/element"; |
| 3 |
import { useSelect, select, dispatch } from "@wordpress/data"; |
| 4 |
import LayoutPreset from "./layoutPreset"; |
| 5 |
import { InspectorControl } from "../../components"; |
| 6 |
import { panelBodyRightIcon } from "../../icons/icons"; |
| 7 |
import Inspector from "./Inspector"; |
| 8 |
import { useDeviceType } from "../../controls/controls"; |
| 9 |
import dynamicCss from "./dynamicCss"; |
| 10 |
import { containerTemplatesConstant, layoutsColumnsWidth, shapeDividerIconConstant } from "./containerConstant"; |
| 11 |
import "./ContainerSelector.css"; |
| 12 |
import { compose } from "@wordpress/compose"; |
| 13 |
import addInitialAttr from "../shared/addInitialAttr"; |
| 14 |
import { ToolbarDropdownMenu } from "@wordpress/components"; |
| 15 |
import { AlignNoneIcon } from "./icons"; |
| 16 |
|
| 17 |
const ContainerEdit = ({ attributes, setAttributes, clientId, isSelected }) => { |
| 18 |
const [showPresetLayer, setShowPresetLayer] = useState(null); |
| 19 |
const page = "editor"; |
| 20 |
const { |
| 21 |
blockName, |
| 22 |
uniqueId, |
| 23 |
containerLayer, |
| 24 |
customCss, |
| 25 |
columns, |
| 26 |
containerFlexDirection, |
| 27 |
layout, |
| 28 |
htmlTag, |
| 29 |
containerTopDividerType, |
| 30 |
containerBottomDividerType, |
| 31 |
shapeDividerFlipTop, |
| 32 |
shapeDividerFlipBottom, |
| 33 |
advancedAdditionalID, |
| 34 |
advancedAdditionalClass, |
| 35 |
advanceWrapperLink, |
| 36 |
advanceWrapperLinkUrl, |
| 37 |
advanceWrapperLinkNewTab, |
| 38 |
containerFlexWrap, |
| 39 |
containerBGVideo, |
| 40 |
containerBG, |
| 41 |
columnsGap, |
| 42 |
columnsTablet, |
| 43 |
columnsMobile, |
| 44 |
align, |
| 45 |
containerWidth, |
| 46 |
} = attributes; |
| 47 |
const deviceType = useDeviceType(); |
| 48 |
const blockProps = useBlockProps({ |
| 49 |
className: `${uniqueId}-boxed`, |
| 50 |
}); |
| 51 |
const [template, setTemplate] = useState(""); |
| 52 |
const ContainerTag = htmlTag; |
| 53 |
const containerFlexDir = containerFlexDirection?.device?.[ deviceType ]; |
| 54 |
|
| 55 |
const numberOfColumns = columns; |
| 56 |
|
| 57 |
useEffect(() => { |
| 58 |
setAttributes({ blockClientId: clientId }); |
| 59 |
}, [clientId]); |
| 60 |
|
| 61 |
const { getBlock } = select("core/block-editor"); |
| 62 |
const { updateBlockAttributes } = dispatch("core/block-editor"); |
| 63 |
// For updating the template dynamically. |
| 64 |
const innerBlocks = useSelect((select) => select(blockEditorStore).getBlocks(clientId), [clientId, columns]); |
| 65 |
|
| 66 |
// const getGlobalBreakpoint = select("smartpost/global-settings").getCategory("breakpoint"); |
| 67 |
// useEffect( () => { |
| 68 |
// if (typeof getGlobalBreakpoint === "object") { |
| 69 |
// setAttributes({ globalBreakPointData: getGlobalBreakpoint }) |
| 70 |
// } |
| 71 |
// }, [ getGlobalBreakpoint ]) |
| 72 |
|
| 73 |
useEffect(() => { |
| 74 |
if (innerBlocks.length < 1 && !containerLayer) { |
| 75 |
setShowPresetLayer("show"); |
| 76 |
} else { |
| 77 |
setShowPresetLayer("hide"); |
| 78 |
} |
| 79 |
}, [columns, layout]); |
| 80 |
|
| 81 |
useEffect(() => { |
| 82 |
//reduceColWidth, |
| 83 |
const childBlocks = getBlock(clientId)?.innerBlocks; |
| 84 |
|
| 85 |
const responsiveColumns = { |
| 86 |
Desktop: columns, |
| 87 |
Tablet: columnsTablet, |
| 88 |
Mobile: columnsMobile, |
| 89 |
} |
| 90 |
|
| 91 |
const multiRowCols = ("container-column-multi-row-layout-one" !== layout ) ? 2 : 3; |
| 92 |
|
| 93 |
let reduceGap = 0; |
| 94 |
|
| 95 |
if([ |
| 96 |
"container-column-multi-row-layout-one", |
| 97 |
"container-column-multi-row-layout-two", |
| 98 |
"container-column-multi-row-layout-three", "container-column-multi-row-layout-four", "container-column-multi-row-layout-five"].includes(layout)) { |
| 99 |
reduceGap = |
| 100 |
childBlocks?.length > 1 |
| 101 |
? (( columnsGap?.device?.[deviceType] || columnsGap?.device?.Desktop ) * (multiRowCols - 1) / multiRowCols ).toFixed(2) |
| 102 |
: 0; |
| 103 |
}else { |
| 104 |
reduceGap = childBlocks?.length > 1 |
| 105 |
? (( (columnsGap?.device?.[deviceType] || columnsGap?.device?.Desktop ) * (((responsiveColumns[deviceType] || columns) - 1) / responsiveColumns[deviceType] || columns))).toFixed(2) |
| 106 |
: 0; |
| 107 |
} |
| 108 |
|
| 109 |
childBlocks?.forEach((child) => { |
| 110 |
|
| 111 |
const reduceColumnWidth = child?.attributes?.reduceColWidth || {}; |
| 112 |
|
| 113 |
updateBlockAttributes(child?.clientId, { |
| 114 |
reduceColWidth: { |
| 115 |
...reduceColumnWidth, |
| 116 |
device: { |
| 117 |
...reduceColumnWidth.device, |
| 118 |
[deviceType]: reduceGap, |
| 119 |
}, |
| 120 |
}, |
| 121 |
parentColumnGap: columnsGap, |
| 122 |
}); |
| 123 |
}); |
| 124 |
}, [columnsGap, columns, innerBlocks.length, columnsTablet, columnsMobile]); |
| 125 |
|
| 126 |
useEffect( () => { |
| 127 |
if ( !template && containerLayer ) { |
| 128 |
setTemplate( containerTemplatesConstant[ containerLayer ] ) |
| 129 |
} |
| 130 |
}, [ containerLayer ]); |
| 131 |
|
| 132 |
const customAppenderHandler = () => ( |
| 133 |
<div> |
| 134 |
<InnerBlocks.ButtonBlockAppender /> |
| 135 |
</div> |
| 136 |
); |
| 137 |
const layoutClassName = ( numberOfColumns < 7 || numberOfColumns === "multi-row" ) ? layout : `${blockName}-column-${numberOfColumns}-layout`; |
| 138 |
|
| 139 |
const blockStyling = useMemo(() => dynamicCss(attributes, page, deviceType), [attributes, deviceType]); |
| 140 |
const multiRowLayout = { |
| 141 |
"container-column-multi-row-layout-one": 3, |
| 142 |
}; |
| 143 |
const gapMultiplier = !["multi-row", ""].includes( columns ) ? columns : multiRowLayout[layout] || 2; |
| 144 |
|
| 145 |
|
| 146 |
const columnsWidthStyle = layout ? { |
| 147 |
"--columnOne": layoutsColumnsWidth[layout][0] ? `${layoutsColumnsWidth[layout][0]}%` : "auto", |
| 148 |
"--columnTwo": layoutsColumnsWidth[layout][1] ? `${layoutsColumnsWidth[layout][1]}%` : "auto", |
| 149 |
"--columnThree": layoutsColumnsWidth[layout][2] ? `${layoutsColumnsWidth[layout][2]}%` : "auto", |
| 150 |
"--columnFour": layoutsColumnsWidth[layout][3] ? `${layoutsColumnsWidth[layout][3]}%` : "auto", |
| 151 |
"--columnFive": layoutsColumnsWidth[layout][4] ? `${layoutsColumnsWidth[layout][4]}%` : "auto", |
| 152 |
"--columnSix": layoutsColumnsWidth[layout][5] ? `${layoutsColumnsWidth[layout][5]}%` : "auto", |
| 153 |
"--gap": `${(columnsGap?.device?.[ deviceType ] || columnsGap?.device?.Desktop) * ( gapMultiplier - 1 )}px`, |
| 154 |
"--gapMultiplier": layout ? gapMultiplier : 0, |
| 155 |
} : {}; |
| 156 |
|
| 157 |
useEffect( () => { |
| 158 |
setAttributes({ |
| 159 |
containerColumnRoot: columnsWidthStyle, |
| 160 |
}) |
| 161 |
}, [layout, columnsGap]); |
| 162 |
|
| 163 |
const alignClasses = containerWidth === "boxed" ? `${align ? "align"+align : ""}` : "alignfull"; |
| 164 |
const activeAlignIcon = { |
| 165 |
none: <AlignNoneIcon />, |
| 166 |
wide: "align-wide", |
| 167 |
full: "align-full-width", |
| 168 |
}; |
| 169 |
|
| 170 |
return ( |
| 171 |
<> |
| 172 |
{showPresetLayer && showPresetLayer === "show" && ( |
| 173 |
<div {...blockProps}> |
| 174 |
<LayoutPreset |
| 175 |
attributes={{ |
| 176 |
containerLayer, |
| 177 |
containerFlexDirection, |
| 178 |
columns, |
| 179 |
containerFlexWrap, |
| 180 |
}} |
| 181 |
setAttributes={setAttributes} |
| 182 |
deviceType={deviceType} |
| 183 |
/> |
| 184 |
</div> |
| 185 |
)} |
| 186 |
<style> |
| 187 |
{blockStyling} |
| 188 |
{customCss} |
| 189 |
</style> |
| 190 |
{showPresetLayer && showPresetLayer === "hide" && ( |
| 191 |
<div className={alignClasses}> |
| 192 |
<div {...blockProps} > |
| 193 |
<ContainerTag |
| 194 |
key={layout} |
| 195 |
{...(advancedAdditionalID ? { id: advancedAdditionalID } : {})} |
| 196 |
className={`sp-smart-post-container-editor-page sp-smart-post-show-pro ${uniqueId} ${advancedAdditionalClass}`} |
| 197 |
> |
| 198 |
{/* Container Shape Divider Start */} |
| 199 |
{"none" !== containerTopDividerType && ( |
| 200 |
<div |
| 201 |
className={`sp-smart-post-container-shape sp-smart-post-container-shape-top${ |
| 202 |
shapeDividerFlipTop ? " sp-smart-post-shape-flip" : "" |
| 203 |
}`} |
| 204 |
> |
| 205 |
{shapeDividerIconConstant[containerTopDividerType]} |
| 206 |
</div> |
| 207 |
)} |
| 208 |
{"none" !== containerBottomDividerType && ( |
| 209 |
<div |
| 210 |
className={`sp-smart-post-container-shape sp-smart-post-container-shape-bottom${ |
| 211 |
shapeDividerFlipBottom ? " sp-smart-post-shape-flip" : "" |
| 212 |
}`} |
| 213 |
> |
| 214 |
{shapeDividerIconConstant[containerBottomDividerType]} |
| 215 |
</div> |
| 216 |
)} |
| 217 |
{"video" === containerBG?.color?.style && ( |
| 218 |
<div className="sp-smart-post-container__video-wrap"> |
| 219 |
{containerBGVideo && ( |
| 220 |
<video autoPlay loop muted> |
| 221 |
<source src={containerBGVideo.url} type="video/mp4" /> |
| 222 |
</video> |
| 223 |
)} |
| 224 |
</div> |
| 225 |
)} |
| 226 |
{/* Container Shape Divider Ends */} |
| 227 |
{/* <div {...blockProps}> */} |
| 228 |
{containerWidth === "boxed" && ( |
| 229 |
<BlockControls> |
| 230 |
<ToolbarDropdownMenu |
| 231 |
icon={ activeAlignIcon[ align ] } |
| 232 |
label="Select a direction" |
| 233 |
controls={ [ |
| 234 |
{ |
| 235 |
title: "None", |
| 236 |
icon: AlignNoneIcon, |
| 237 |
onClick: () => setAttributes({ align: "none", containerWidth: "boxed" }), |
| 238 |
}, |
| 239 |
{ |
| 240 |
title: "Wide", |
| 241 |
icon: "align-wide", |
| 242 |
onClick: () => setAttributes({ align: "wide", containerWidth: "boxed" }), |
| 243 |
}, |
| 244 |
// { |
| 245 |
// title: "Full", |
| 246 |
// icon: "align-full-width", |
| 247 |
// onClick: () => setAttributes({ align: "full", containerWidth: "full-width" }), |
| 248 |
// }, |
| 249 |
] } |
| 250 |
/> |
| 251 |
</BlockControls> |
| 252 |
)} |
| 253 |
|
| 254 |
<div |
| 255 |
className={`sp-smart-post-container-parent-block sp-smart-post-container sp-smart-post-container-column-${ columns ? columns : "multi-row"} ${layoutClassName} sp-smart-post-flex-${containerFlexDir}`} |
| 256 |
style={ columnsWidthStyle } |
| 257 |
> |
| 258 |
<InspectorControl |
| 259 |
RightIcon={panelBodyRightIcon} |
| 260 |
attributes={attributes} |
| 261 |
setAttributes={setAttributes} |
| 262 |
Inspector={Inspector} |
| 263 |
templateLibrary={"google.com"} |
| 264 |
isSelected={isSelected} |
| 265 |
/> |
| 266 |
{/* { containerFlexWrap?.device?.[ deviceType ] !== "wrap" && ( |
| 267 |
<ResizableComponents |
| 268 |
attributes={attributes} |
| 269 |
setAttributes={setAttributes} |
| 270 |
clientId={ clientId } |
| 271 |
/> |
| 272 |
)} */} |
| 273 |
<InnerBlocks |
| 274 |
// __experimentalCaptureToolbars={ true } |
| 275 |
allowedBlocks={["sp-smart-post-show/column"]} |
| 276 |
renderAppender={customAppenderHandler} |
| 277 |
orientation="horizontal" |
| 278 |
template={ template } |
| 279 |
/> |
| 280 |
</div> |
| 281 |
{advanceWrapperLink && ( |
| 282 |
<a |
| 283 |
className={"sp-smart-post-container-parent-block-wrapper-link"} |
| 284 |
rel="noopener noreferrer" |
| 285 |
href={advanceWrapperLinkUrl} |
| 286 |
target={advanceWrapperLinkNewTab ? "_blank" : "_self"} |
| 287 |
> |
| 288 |
{" "} |
| 289 |
</a> |
| 290 |
)} |
| 291 |
{/* </div> */} |
| 292 |
</ContainerTag> |
| 293 |
</div> |
| 294 |
</div> |
| 295 |
)} |
| 296 |
</> |
| 297 |
); |
| 298 |
}; |
| 299 |
|
| 300 |
export default compose(addInitialAttr)(ContainerEdit); |
| 301 |
|