| 1 |
/* ==================================================== |
| 2 |
Feature Split Block — editor (index.js) |
| 3 |
Block: blockenberg/feature-split |
| 4 |
==================================================== */ |
| 5 |
( function () { |
| 6 |
var el = wp.element.createElement; |
| 7 |
var Fragment = wp.element.Fragment; |
| 8 |
var useState = wp.element.useState; |
| 9 |
var RichText = wp.blockEditor.RichText; |
| 10 |
var MediaUpload = wp.blockEditor.MediaUpload; |
| 11 |
var MediaUploadCheck = wp.blockEditor.MediaUploadCheck; |
| 12 |
var registerBlockType = wp.blocks.registerBlockType; |
| 13 |
var InspectorControls = wp.blockEditor.InspectorControls; |
| 14 |
var useBlockProps = wp.blockEditor.useBlockProps; |
| 15 |
var PanelBody = wp.components.PanelBody; |
| 16 |
var PanelColorSettings = wp.blockEditor.PanelColorSettings; |
| 17 |
var RangeControl = wp.components.RangeControl; |
| 18 |
var SelectControl = wp.components.SelectControl; |
| 19 |
var ToggleControl = wp.components.ToggleControl; |
| 20 |
var TextControl = wp.components.TextControl; |
| 21 |
var Button = wp.components.Button; |
| 22 |
var __ = wp.i18n.__; |
| 23 |
var _fspTC, _fspTV; |
| 24 |
function _tc() { return (_fspTC = _fspTC || window.bkbgTypographyControl); } |
| 25 |
function _tv() { return (_fspTV = _fspTV || window.bkbgTypoCssVars); } |
| 26 |
var IP = function () { return window.bkbgIconPicker; }; |
| 27 |
|
| 28 |
function uid() { return 'f' + Math.random().toString(36).slice(2,7); } |
| 29 |
function move(arr, from, to) { var a=arr.slice(); a.splice(to,0,a.splice(from,1)[0]); return a; } |
| 30 |
|
| 31 |
function buildWrapStyle(a) { |
| 32 |
return Object.assign({ |
| 33 |
'--bkbg-fsp-gap': a.gap + 'px', |
| 34 |
'--bkbg-fsp-img-w': a.imageWidth + '%', |
| 35 |
'--bkbg-fsp-img-radius': a.imageRadius + 'px', |
| 36 |
'--bkbg-fsp-btn-radius': a.btnRadius + 'px', |
| 37 |
'--bkbg-fsp-pt': a.paddingTop + 'px', |
| 38 |
'--bkbg-fsp-pb': a.paddingBottom + 'px', |
| 39 |
'--bkbg-fsp-content-max':a.contentMaxWidth + 'px', |
| 40 |
'--bkbg-fsp-eyebrow-bg': a.eyebrowBg, |
| 41 |
'--bkbg-fsp-eyebrow-clr':a.eyebrowColor, |
| 42 |
'--bkbg-fsp-h-color': a.headlineColor, |
| 43 |
'--bkbg-fsp-body-color': a.bodyColor, |
| 44 |
'--bkbg-fsp-feat-color': a.featureColor, |
| 45 |
'--bkbg-fsp-prim-bg': a.primaryBtnBg, |
| 46 |
'--bkbg-fsp-prim-color': a.primaryBtnColor, |
| 47 |
'--bkbg-fsp-sec-color': a.secBtnColor, |
| 48 |
'--bkbg-fsp-accent': a.accentColor, |
| 49 |
background: a.sectionBg || undefined, |
| 50 |
}, |
| 51 |
_tv()(a.typoEyebrow, '--bkbg-fsp-eb-'), |
| 52 |
_tv()(a.typoHeadline, '--bkbg-fsp-hl-'), |
| 53 |
_tv()(a.typoBody, '--bkbg-fsp-bd-'), |
| 54 |
_tv()(a.typoFeature, '--bkbg-fsp-ft-') |
| 55 |
); |
| 56 |
} |
| 57 |
|
| 58 |
/* ── REGISTER ── */ |
| 59 |
registerBlockType('blockenberg/feature-split', { |
| 60 |
edit: function (props) { |
| 61 |
var a = props.attributes; |
| 62 |
var setAttr = props.setAttributes; |
| 63 |
var features= a.features; |
| 64 |
|
| 65 |
var wrapCls = 'bkbg-fsp-wrap bkbg-fsp-style--' + a.style |
| 66 |
+ (a.imagePosition === 'left' ? ' bkbg-fsp-img-left' : ' bkbg-fsp-img-right'); |
| 67 |
var blockProps = useBlockProps({ className: wrapCls, style: buildWrapStyle(a) }); |
| 68 |
|
| 69 |
function updateFeature(id, text) { |
| 70 |
setAttr({ features: features.map(function(f){ return f.id===id ? Object.assign({},f,{text:text}) : f; }) }); |
| 71 |
} |
| 72 |
function updateFeatureIcon(id, icon) { |
| 73 |
setAttr({ features: features.map(function(f){ return f.id===id ? Object.assign({},f,{icon:icon}) : f; }) }); |
| 74 |
} |
| 75 |
|
| 76 |
var inspector = el(InspectorControls, null, |
| 77 |
/* Style */ |
| 78 |
el(PanelBody, { title:__('Style & Layout','blockenberg'), initialOpen:true }, |
| 79 |
el(SelectControl, { label:__('Visual style','blockenberg'), value:a.style, options:[ |
| 80 |
{label:__('Clean (white)','blockenberg'), value:'clean'}, |
| 81 |
{label:__('Dark','blockenberg'), value:'dark'}, |
| 82 |
{label:__('Soft gradient','blockenberg'), value:'gradient'}, |
| 83 |
{label:__('Accent bg','blockenberg'), value:'accent'}, |
| 84 |
], onChange:function(v){ setAttr({style:v}); } }), |
| 85 |
el(SelectControl, { label:__('Image position','blockenberg'), value:a.imagePosition, options:[ |
| 86 |
{label:__('Right','blockenberg'), value:'right'}, |
| 87 |
{label:__('Left','blockenberg'), value:'left'}, |
| 88 |
], onChange:function(v){ setAttr({imagePosition:v}); } }), |
| 89 |
el(SelectControl, { label:__('Vertical alignment','blockenberg'), value:a.verticalAlign, options:[ |
| 90 |
{label:'Center', value:'center'},{label:'Top', value:'flex-start'},{label:'Bottom', value:'flex-end'} |
| 91 |
], onChange:function(v){ setAttr({verticalAlign:v}); } }), |
| 92 |
el(RangeControl, { label:__('Column gap (px)','blockenberg'), value:a.gap, min:0, max:120, onChange:function(v){ setAttr({gap:v}); } }), |
| 93 |
el(RangeControl, { label:__('Image width %','blockenberg'), value:a.imageWidth, min:30, max:70, onChange:function(v){ setAttr({imageWidth:v}); } }), |
| 94 |
el(RangeControl, { label:__('Image border radius (px)','blockenberg'), value:a.imageRadius, min:0, max:40, onChange:function(v){ setAttr({imageRadius:v}); } }), |
| 95 |
el(ToggleControl, { label:__('Image shadow','blockenberg'), checked:a.imageShadow, onChange:function(v){ setAttr({imageShadow:v}); } }) |
| 96 |
), |
| 97 |
|
| 98 |
/* Content */ |
| 99 |
el(PanelBody, { title:__('Content','blockenberg'), initialOpen:false }, |
| 100 |
el(ToggleControl, { label:__('Show eyebrow badge','blockenberg'), checked:a.showEyebrow, onChange:function(v){ setAttr({showEyebrow:v}); } }), |
| 101 |
el(ToggleControl, { label:__('Show body text','blockenberg'), checked:a.showBody, onChange:function(v){ setAttr({showBody:v}); } }), |
| 102 |
el(ToggleControl, { label:__('Show feature list','blockenberg'), checked:a.showFeatures,onChange:function(v){ setAttr({showFeatures:v}); } }), |
| 103 |
el(ToggleControl, { label:__('Show primary button','blockenberg'), checked:a.showPrimaryBtn, onChange:function(v){ setAttr({showPrimaryBtn:v}); } }), |
| 104 |
el(ToggleControl, { label:__('Show secondary button','blockenberg'), checked:a.showSecondaryBtn, onChange:function(v){ setAttr({showSecondaryBtn:v}); } }), |
| 105 |
a.showEyebrow ? el(TextControl, { label:__('Eyebrow text','blockenberg'), value:a.eyebrow, onChange:function(v){ setAttr({eyebrow:v}); } }) : null, |
| 106 |
a.showPrimaryBtn ? el(Fragment, null, |
| 107 |
el(TextControl, { label:__('Primary button label','blockenberg'), value:a.primaryBtnLabel, onChange:function(v){ setAttr({primaryBtnLabel:v}); } }), |
| 108 |
el(TextControl, { label:__('Primary button URL','blockenberg'), value:a.primaryBtnUrl, onChange:function(v){ setAttr({primaryBtnUrl:v}); } }), |
| 109 |
el(ToggleControl, { label:__('Open in new tab','blockenberg'), checked:a.primaryBtnTarget, onChange:function(v){ setAttr({primaryBtnTarget:v}); } }) |
| 110 |
) : null, |
| 111 |
a.showSecondaryBtn ? el(Fragment, null, |
| 112 |
el(TextControl, { label:__('Secondary button label','blockenberg'), value:a.secondaryBtnLabel, onChange:function(v){ setAttr({secondaryBtnLabel:v}); } }), |
| 113 |
el(TextControl, { label:__('Secondary button URL','blockenberg'), value:a.secondaryBtnUrl, onChange:function(v){ setAttr({secondaryBtnUrl:v}); } }) |
| 114 |
) : null, |
| 115 |
el(RangeControl, { label:__('Content max width (px)','blockenberg'), value:a.contentMaxWidth, min:300, max:800, onChange:function(v){ setAttr({contentMaxWidth:v}); } }) |
| 116 |
), |
| 117 |
|
| 118 |
/* Feature list */ |
| 119 |
a.showFeatures ? el(PanelBody, { title:__('Feature items','blockenberg'), initialOpen:false }, |
| 120 |
features.map(function(f, idx) { |
| 121 |
return el('div', { key:f.id, style:{ display:'flex', gap:'4px', marginBottom:'6px', alignItems:'center' } }, |
| 122 |
el('div', { style:{ flexShrink:0 } }, |
| 123 |
el(IP().IconPickerControl, { |
| 124 |
iconType: f.iconType, customChar: f.icon, dashicon: f.iconDashicon, imageUrl: f.iconImageUrl, |
| 125 |
onChangeType: function(v){ setAttr({features:features.map(function(x){ return x.id===f.id ? Object.assign({},x,{iconType:v}) : x; })}); }, |
| 126 |
onChangeChar: function(v){ updateFeatureIcon(f.id,v); }, |
| 127 |
onChangeDashicon: function(v){ setAttr({features:features.map(function(x){ return x.id===f.id ? Object.assign({},x,{iconDashicon:v}) : x; })}); }, |
| 128 |
onChangeImageUrl: function(v){ setAttr({features:features.map(function(x){ return x.id===f.id ? Object.assign({},x,{iconImageUrl:v}) : x; })}); } |
| 129 |
}) |
| 130 |
), |
| 131 |
el(TextControl, { label: idx===0 ? __('Text','blockenberg') : undefined, value:f.text, onChange:function(v){ updateFeature(f.id,v); }, style:{ flex:1 } }), |
| 132 |
el(Button, { icon:'arrow-up', isSmall:true, disabled:idx===0, onClick:function(){ setAttr({features:move(features,idx,idx-1)}); } }), |
| 133 |
el(Button, { icon:'no-alt', isSmall:true, isDestructive:true, onClick:function(){ setAttr({features:features.filter(function(_,i){ return i!==idx; })}); } }) |
| 134 |
); |
| 135 |
}), |
| 136 |
el(Button, { variant:'secondary', isSmall:true, style:{width:'100%',marginTop:'4px'}, |
| 137 |
onClick:function(){ setAttr({ features: features.concat([{id:uid(),icon:'� |
| 138 |
',text:'New feature',iconType:'custom-char',iconDashicon:'',iconImageUrl:''}]) }); } |
| 139 |
}, __('+ Add feature','blockenberg')) |
| 140 |
) : null, |
| 141 |
|
| 142 |
/* Spacing */ |
| 143 |
el(PanelBody, { title:__('Spacing','blockenberg'), initialOpen:false }, |
| 144 |
el(RangeControl, { label:__('Padding top (px)','blockenberg'), value:a.paddingTop, min:0, max:160, onChange:function(v){ setAttr({paddingTop:v}); } }), |
| 145 |
el(RangeControl, { label:__('Padding bottom (px)','blockenberg'), value:a.paddingBottom, min:0, max:160, onChange:function(v){ setAttr({paddingBottom:v}); } }), |
| 146 |
el(RangeControl, { label:__('Button radius (px)','blockenberg'), value:a.btnRadius, min:0, max:50, onChange:function(v){ setAttr({btnRadius:v}); } }) |
| 147 |
), |
| 148 |
|
| 149 |
/* Typography */ |
| 150 |
el(PanelBody, { title:__('Typography','blockenberg'), initialOpen:false }, |
| 151 |
_tc() && el(_tc(), { label: __('Headline', 'blockenberg'), value: a.typoHeadline, onChange: function (v) { setAttr({ typoHeadline: v }); } }), |
| 152 |
_tc() && el(_tc(), { label: __('Body', 'blockenberg'), value: a.typoBody, onChange: function (v) { setAttr({ typoBody: v }); } }), |
| 153 |
_tc() && el(_tc(), { label: __('Feature', 'blockenberg'), value: a.typoFeature, onChange: function (v) { setAttr({ typoFeature: v }); } }), |
| 154 |
_tc() && el(_tc(), { label: __('Eyebrow', 'blockenberg'), value: a.typoEyebrow, onChange: function (v) { setAttr({ typoEyebrow: v }); } }) |
| 155 |
), |
| 156 |
|
| 157 |
/* Colors */ |
| 158 |
el(PanelColorSettings, { title:__('Colors','blockenberg'), initialOpen:false, colorSettings:[ |
| 159 |
{label:__('Section background','blockenberg'), value:a.sectionBg, onChange:function(v){ setAttr({sectionBg:v||''}); }}, |
| 160 |
{label:__('Eyebrow bg','blockenberg'), value:a.eyebrowBg, onChange:function(v){ setAttr({eyebrowBg:v||''}); }}, |
| 161 |
{label:__('Eyebrow color','blockenberg'), value:a.eyebrowColor, onChange:function(v){ setAttr({eyebrowColor:v||''}); }}, |
| 162 |
{label:__('Headline color','blockenberg'), value:a.headlineColor, onChange:function(v){ setAttr({headlineColor:v||''}); }}, |
| 163 |
{label:__('Body text color','blockenberg'), value:a.bodyColor, onChange:function(v){ setAttr({bodyColor:v||''}); }}, |
| 164 |
{label:__('Feature text color','blockenberg'), value:a.featureColor, onChange:function(v){ setAttr({featureColor:v||''}); }}, |
| 165 |
{label:__('Primary btn bg','blockenberg'), value:a.primaryBtnBg, onChange:function(v){ setAttr({primaryBtnBg:v||''}); }}, |
| 166 |
{label:__('Primary btn text','blockenberg'), value:a.primaryBtnColor, onChange:function(v){ setAttr({primaryBtnColor:v||''}); }}, |
| 167 |
{label:__('Secondary btn color','blockenberg'),value:a.secBtnColor, onChange:function(v){ setAttr({secBtnColor:v||''}); }}, |
| 168 |
{label:__('Accent color','blockenberg'), value:a.accentColor, onChange:function(v){ setAttr({accentColor:v||''}); }}, |
| 169 |
] }) |
| 170 |
); |
| 171 |
|
| 172 |
/* Content column */ |
| 173 |
var contentEl = el('div', { |
| 174 |
className: 'bkbg-fsp-content', |
| 175 |
style: { background: a.contentBg || undefined, alignSelf: a.verticalAlign } |
| 176 |
}, |
| 177 |
a.showEyebrow ? el('span', { className:'bkbg-fsp-eyebrow' }, a.eyebrow) : null, |
| 178 |
el(RichText, { tagName:'h2', className:'bkbg-fsp-headline', value:a.headline, onChange:function(v){ setAttr({headline:v}); }, placeholder:__('Compelling headline…','blockenberg') }), |
| 179 |
a.showBody ? el(RichText, { tagName:'p', className:'bkbg-fsp-body', value:a.body, onChange:function(v){ setAttr({body:v}); }, placeholder:__('Body text…','blockenberg') }) : null, |
| 180 |
a.showFeatures ? el('ul', { className:'bkbg-fsp-features' }, |
| 181 |
features.map(function(f){ |
| 182 |
return el('li', { key:f.id, className:'bkbg-fsp-feature' }, |
| 183 |
el('span', { className:'bkbg-fsp-feature-icon' }, (f.iconType || 'custom-char') !== 'custom-char' ? IP().buildEditorIcon(f.iconType, f.icon, f.iconDashicon, f.iconImageUrl, f.iconDashiconColor) : f.icon), |
| 184 |
el('span', { className:'bkbg-fsp-feature-text' }, f.text) |
| 185 |
); |
| 186 |
}) |
| 187 |
) : null, |
| 188 |
(a.showPrimaryBtn || a.showSecondaryBtn) ? el('div', { className:'bkbg-fsp-btns' }, |
| 189 |
a.showPrimaryBtn ? el('a', { className:'bkbg-fsp-btn bkbg-fsp-btn--primary', href:a.primaryBtnUrl, onClick:function(e){ e.preventDefault(); } }, a.primaryBtnLabel) : null, |
| 190 |
a.showSecondaryBtn ? el('a', { className:'bkbg-fsp-btn bkbg-fsp-btn--secondary', href:a.secondaryBtnUrl, onClick:function(e){ e.preventDefault(); } }, a.secondaryBtnLabel) : null |
| 191 |
) : null |
| 192 |
); |
| 193 |
|
| 194 |
/* Image column */ |
| 195 |
var imageEl = el('div', { className:'bkbg-fsp-image-wrap' + (a.imageShadow ? ' bkbg-fsp-shadow' : '') }, |
| 196 |
a.imageUrl |
| 197 |
? el('img', { src:a.imageUrl, alt:a.imageAlt, className:'bkbg-fsp-img' }) |
| 198 |
: el(MediaUploadCheck, null, |
| 199 |
el(MediaUpload, { |
| 200 |
onSelect:function(m){ setAttr({ imageUrl:m.url, imageId:m.id, imageAlt:m.alt||'' }); }, |
| 201 |
allowedTypes:['image'], value:a.imageId, |
| 202 |
render:function(o){ return el(Button, { onClick:o.open, className:'bkbg-fsp-img-placeholder', variant:'secondary' }, __('+ Choose image','blockenberg')); } |
| 203 |
}) |
| 204 |
), |
| 205 |
a.imageUrl ? el('div', { className:'bkbg-fsp-img-actions' }, |
| 206 |
el(Button, { isSmall:true, variant:'secondary', onClick:function(){ setAttr({ imageUrl:'', imageId:0 }); } }, __('Remove','blockenberg')) |
| 207 |
) : null |
| 208 |
); |
| 209 |
|
| 210 |
return el(Fragment, null, |
| 211 |
inspector, |
| 212 |
el('div', blockProps, |
| 213 |
a.imagePosition === 'right' ? el(Fragment, null, contentEl, imageEl) : el(Fragment, null, imageEl, contentEl) |
| 214 |
) |
| 215 |
); |
| 216 |
}, |
| 217 |
|
| 218 |
save: function (props) { |
| 219 |
var a = props.attributes; |
| 220 |
var wrapCls = 'bkbg-fsp-wrap bkbg-fsp-style--' + a.style |
| 221 |
+ (a.imagePosition === 'left' ? ' bkbg-fsp-img-left' : ' bkbg-fsp-img-right'); |
| 222 |
var blockProps = wp.blockEditor.useBlockProps.save({ className: wrapCls, style: buildWrapStyle(a) }); |
| 223 |
|
| 224 |
var contentEl = el('div', { className:'bkbg-fsp-content', style:{ alignSelf:a.verticalAlign } }, |
| 225 |
a.showEyebrow ? el('span', { className:'bkbg-fsp-eyebrow' }, a.eyebrow) : null, |
| 226 |
el(RichText.Content, { tagName:'h2', className:'bkbg-fsp-headline', value:a.headline }), |
| 227 |
a.showBody ? el(RichText.Content, { tagName:'p', className:'bkbg-fsp-body', value:a.body }) : null, |
| 228 |
a.showFeatures ? el('ul', { className:'bkbg-fsp-features' }, |
| 229 |
a.features.map(function(f){ |
| 230 |
return el('li', { key:f.id, className:'bkbg-fsp-feature' }, |
| 231 |
el('span', { className:'bkbg-fsp-feature-icon' }, (f.iconType || 'custom-char') !== 'custom-char' ? IP().buildSaveIcon(f.iconType, f.icon, f.iconDashicon, f.iconImageUrl, f.iconDashiconColor) : f.icon), |
| 232 |
el('span', { className:'bkbg-fsp-feature-text' }, f.text) |
| 233 |
); |
| 234 |
}) |
| 235 |
) : null, |
| 236 |
(a.showPrimaryBtn || a.showSecondaryBtn) ? el('div', { className:'bkbg-fsp-btns' }, |
| 237 |
a.showPrimaryBtn ? el('a', { className:'bkbg-fsp-btn bkbg-fsp-btn--primary', href:a.primaryBtnUrl, target: a.primaryBtnTarget ? '_blank' : undefined }, a.primaryBtnLabel) : null, |
| 238 |
a.showSecondaryBtn ? el('a', { className:'bkbg-fsp-btn bkbg-fsp-btn--secondary', href:a.secondaryBtnUrl }, a.secondaryBtnLabel) : null |
| 239 |
) : null |
| 240 |
); |
| 241 |
|
| 242 |
var imageEl = el('div', { className:'bkbg-fsp-image-wrap' + (a.imageShadow ? ' bkbg-fsp-shadow' : '') }, |
| 243 |
a.imageUrl ? el('img', { src:a.imageUrl, alt:a.imageAlt, className:'bkbg-fsp-img', loading:'lazy' }) : null |
| 244 |
); |
| 245 |
|
| 246 |
return el('div', blockProps, |
| 247 |
a.imagePosition === 'right' ? el(Fragment, null, contentEl, imageEl) : el(Fragment, null, imageEl, contentEl) |
| 248 |
); |
| 249 |
} |
| 250 |
}); |
| 251 |
}() ); |
| 252 |
|