| 1 |
/* ==================================================== |
| 2 |
Split Price CTA — editor (index.js) |
| 3 |
Block: blockenberg/split-price-cta |
| 4 |
==================================================== */ |
| 5 |
( function () { |
| 6 |
var el = wp.element.createElement; |
| 7 |
var useState = wp.element.useState; |
| 8 |
var Fragment = wp.element.Fragment; |
| 9 |
var RichText = wp.blockEditor.RichText; |
| 10 |
var registerBlockType = wp.blocks.registerBlockType; |
| 11 |
var InspectorControls = wp.blockEditor.InspectorControls; |
| 12 |
var useBlockProps = wp.blockEditor.useBlockProps; |
| 13 |
var PanelColorSettings = wp.blockEditor.PanelColorSettings; |
| 14 |
var PanelBody = wp.components.PanelBody; |
| 15 |
var RangeControl = wp.components.RangeControl; |
| 16 |
var SelectControl = wp.components.SelectControl; |
| 17 |
var ToggleControl = wp.components.ToggleControl; |
| 18 |
var TextControl = wp.components.TextControl; |
| 19 |
var Button = wp.components.Button; |
| 20 |
var GradientPicker = wp.components.__experimentalGradientPicker; |
| 21 |
var __ = wp.i18n.__; |
| 22 |
|
| 23 |
function uid() { return Math.random().toString(36).slice(2,9); } |
| 24 |
|
| 25 |
var _tc; function getTypoControl() { return _tc || (_tc = window.bkbgTypographyControl); } |
| 26 |
var _tv; function getTypoCssVars() { return _tv || (_tv = window.bkbgTypoCssVars); } |
| 27 |
|
| 28 |
function getLeftBg(a) { |
| 29 |
return a.leftStyle === 'gradient' ? a.leftGradient : a.leftBg; |
| 30 |
} |
| 31 |
|
| 32 |
function wrapStyle(a) { |
| 33 |
var s = { |
| 34 |
'--bkbg-spc-pt': a.paddingTop + 'px', |
| 35 |
'--bkbg-spc-pb': a.paddingBottom + 'px', |
| 36 |
'--bkbg-spc-r': a.blockRadius + 'px', |
| 37 |
'--bkbg-spc-btn-r': a.btnRadius + 'px', |
| 38 |
'--bkbg-spc-chk-c': a.checkColor, |
| 39 |
'--bkbg-spc-price-lbl-c': a.priceLabelColor, |
| 40 |
'--bkbg-spc-price-val-c': a.priceValueColor, |
| 41 |
'--bkbg-spc-price-note-c':a.priceNoteColor, |
| 42 |
'--bkbg-spc-feat-c': a.featureColor, |
| 43 |
'--bkbg-spc-right-bg': a.rightBg, |
| 44 |
'--bkbg-spc-ttl-c': a.ctaHeadingColor, |
| 45 |
'--bkbg-spc-sub-c': a.ctaSubtitleColor, |
| 46 |
'--bkbg-spc-primary-bg': a.primaryBg, |
| 47 |
'--bkbg-spc-primary-c': a.primaryColor, |
| 48 |
'--bkbg-spc-proof-c': a.proofColor, |
| 49 |
'--bkbg-spc-bd': a.borderColor, |
| 50 |
'--bkbg-spc-price-sz': a.priceSize + 'px', |
| 51 |
'--bkbg-spc-pv-w': a.priceFontWeight, |
| 52 |
'--bkbg-spc-ttl-sz': a.ctaHeadingSize + 'px', |
| 53 |
'--bkbg-spc-hd-w': a.ctaHeadingFontWeight, |
| 54 |
}; |
| 55 |
var fn = getTypoCssVars(); |
| 56 |
if (fn) { |
| 57 |
Object.assign(s, fn(a.priceTypo, '--bkspc-pv')); |
| 58 |
Object.assign(s, fn(a.headingTypo, '--bkspc-hd')); |
| 59 |
Object.assign(s, fn(a.subtitleTypo, '--bkspc-st')); |
| 60 |
Object.assign(s, fn(a.badgeTypo, '--bkspc-bd')); |
| 61 |
Object.assign(s, fn(a.featureTypo, '--bkspc-ft')); |
| 62 |
Object.assign(s, fn(a.btnTypo, '--bkspc-bt')); |
| 63 |
} |
| 64 |
return s; |
| 65 |
} |
| 66 |
|
| 67 |
registerBlockType('blockenberg/split-price-cta', { |
| 68 |
edit: function (props) { |
| 69 |
var a = props.attributes; |
| 70 |
var setAttr = props.setAttributes; |
| 71 |
|
| 72 |
function updateFeature(idx, text) { |
| 73 |
var arr = a.features.map(function(f,i){ return i===idx ? Object.assign({},f,{text:text}) : f; }); |
| 74 |
setAttr({ features: arr }); |
| 75 |
} |
| 76 |
function deleteFeature(idx) { setAttr({ features: a.features.filter(function(_,i){ return i!==idx; }) }); } |
| 77 |
function addFeature() { setAttr({ features: a.features.concat([{id:uid(), text:'New feature'}]) }); } |
| 78 |
function moveFeature(from, to) { |
| 79 |
var arr = a.features.slice(); arr.splice(to, 0, arr.splice(from, 1)[0]); setAttr({ features: arr }); |
| 80 |
} |
| 81 |
|
| 82 |
var blockProps = useBlockProps({ className:'bkbg-spc-outer', style:wrapStyle(a) }); |
| 83 |
|
| 84 |
var inspector = el(InspectorControls, null, |
| 85 |
el(PanelBody, { title:__('Price (left panel)','blockenberg'), initialOpen:true }, |
| 86 |
el(TextControl, { label:__('Price label','blockenberg'), value:a.priceLabel, onChange:function(v){ setAttr({priceLabel:v}); } }), |
| 87 |
el(TextControl, { label:__('Price value','blockenberg'), value:a.priceValue, onChange:function(v){ setAttr({priceValue:v}); } }), |
| 88 |
el(TextControl, { label:__('Price period','blockenberg'), value:a.pricePeriod, onChange:function(v){ setAttr({pricePeriod:v}); } }), |
| 89 |
el(TextControl, { label:__('Price note','blockenberg'), value:a.priceNote, onChange:function(v){ setAttr({priceNote:v}); } }), |
| 90 |
el(ToggleControl, { label:__('Show old/crossed price','blockenberg'), checked:a.showOldPrice, onChange:function(v){ setAttr({showOldPrice:v}); } }), |
| 91 |
a.showOldPrice ? el(TextControl, { label:__('Old price','blockenberg'), value:a.oldPrice, onChange:function(v){ setAttr({oldPrice:v}); } }) : null, |
| 92 |
el(ToggleControl, { label:__('Show offer badge','blockenberg'), checked:a.showBadge, onChange:function(v){ setAttr({showBadge:v}); } }), |
| 93 |
a.showBadge ? el(TextControl, { label:__('Badge text','blockenberg'), value:a.badge, onChange:function(v){ setAttr({badge:v}); } }) : null, |
| 94 |
el('p', { style:{ fontWeight:600, fontSize:11, margin:'10px 0 4px' } }, __('Included features','blockenberg')), |
| 95 |
a.features.map(function(f, i) { |
| 96 |
return el('div', { key:f.id, style:{ display:'flex', gap:4, marginBottom:4, alignItems:'center' } }, |
| 97 |
el(TextControl, { value:f.text, onChange:function(v){ updateFeature(i,v); }, placeholder:'Feature…' }), |
| 98 |
el(Button, { isSmall:true, variant:'tertiary', disabled:i===0, onClick:function(){ moveFeature(i,i-1); } }, '↑'), |
| 99 |
el(Button, { isSmall:true, isDestructive:true, onClick:function(){ deleteFeature(i); } }, '✕') |
| 100 |
); |
| 101 |
}), |
| 102 |
el(Button, { isSmall:true, variant:'tertiary', onClick:addFeature, style:{marginTop:4} }, __('+ Feature','blockenberg')) |
| 103 |
), |
| 104 |
el(PanelBody, { title:__('CTA (right panel)','blockenberg'), initialOpen:false }, |
| 105 |
el(TextControl, { label:__('Heading','blockenberg'), value:a.ctaHeading, onChange:function(v){ setAttr({ctaHeading:v}); } }), |
| 106 |
el(TextControl, { label:__('Subtitle','blockenberg'), value:a.ctaSubtitle, onChange:function(v){ setAttr({ctaSubtitle:v}); } }), |
| 107 |
el(TextControl, { label:__('Primary button','blockenberg'), value:a.primaryLabel, onChange:function(v){ setAttr({primaryLabel:v}); } }), |
| 108 |
el(TextControl, { label:__('Primary URL','blockenberg'), value:a.primaryUrl, onChange:function(v){ setAttr({primaryUrl:v}); } }), |
| 109 |
el(ToggleControl, { label:__('Show secondary link','blockenberg'), checked:a.showSecondary, onChange:function(v){ setAttr({showSecondary:v}); } }), |
| 110 |
a.showSecondary ? el(TextControl, { label:__('Secondary label','blockenberg'), value:a.secondaryLabel, onChange:function(v){ setAttr({secondaryLabel:v}); } }) : null, |
| 111 |
a.showSecondary ? el(TextControl, { label:__('Secondary URL','blockenberg'), value:a.secondaryUrl, onChange:function(v){ setAttr({secondaryUrl:v}); } }) : null, |
| 112 |
el(ToggleControl, { label:__('Show social proof quote','blockenberg'), checked:a.showSocialProof, onChange:function(v){ setAttr({showSocialProof:v}); } }), |
| 113 |
a.showSocialProof ? el(TextControl, { label:__('Quote text','blockenberg'), value:a.socialProofText, onChange:function(v){ setAttr({socialProofText:v}); } }) : null, |
| 114 |
a.showSocialProof ? el(TextControl, { label:__('Quote author','blockenberg'), value:a.socialProofAuthor, onChange:function(v){ setAttr({socialProofAuthor:v}); } }) : null |
| 115 |
), |
| 116 |
el(PanelBody, { title:__('Style','blockenberg'), initialOpen:false }, |
| 117 |
el(SelectControl, { label:__('Left panel style','blockenberg'), value:a.leftStyle, options:[{label:'Gradient',value:'gradient'},{label:'Solid color',value:'solid'}], onChange:function(v){ setAttr({leftStyle:v}); } }), |
| 118 |
a.leftStyle === 'gradient' ? el('div', { style:{ marginBottom:'12px' } }, |
| 119 |
el('p', { style:{ fontSize:'11px', fontWeight:600, margin:'0 0 6px', textTransform:'uppercase', color:'#757575' } }, __('Gradient','blockenberg')), |
| 120 |
el(GradientPicker, { value: a.leftGradient, onChange:function(v){ setAttr({leftGradient:v}); } }) |
| 121 |
) : null, |
| 122 |
el(RangeControl, { label:__('Block radius (px)','blockenberg'), value:a.blockRadius, min:0, max:32, onChange:function(v){ setAttr({blockRadius:v}); } }), |
| 123 |
el(RangeControl, { label:__('Button radius (px)','blockenberg'), value:a.btnRadius, min:0, max:50, onChange:function(v){ setAttr({btnRadius:v}); } }), |
| 124 |
), |
| 125 |
el(PanelBody, { title:__('Spacing','blockenberg'), initialOpen:false }, |
| 126 |
el(RangeControl, { label:__('Padding top (px)','blockenberg'), value:a.paddingTop, min:0, max:160, onChange:function(v){ setAttr({paddingTop:v}); } }), |
| 127 |
el(RangeControl, { label:__('Padding bottom (px)','blockenberg'), value:a.paddingBottom, min:0, max:160, onChange:function(v){ setAttr({paddingBottom:v}); } }) |
| 128 |
), |
| 129 |
|
| 130 |
el( PanelBody, { title: __( 'Typography', 'blockenberg' ), initialOpen: false }, |
| 131 |
getTypoControl() ? el(getTypoControl(), { label:__('Price','blockenberg'), value:a.priceTypo, onChange:function(v){ setAttr({priceTypo:v}); } }) : null, |
| 132 |
getTypoControl() ? el(getTypoControl(), { label:__('CTA heading','blockenberg'), value:a.headingTypo, onChange:function(v){ setAttr({headingTypo:v}); } }) : null, |
| 133 |
getTypoControl() ? el(getTypoControl(), { label:__('CTA subtitle','blockenberg'), value:a.subtitleTypo, onChange:function(v){ setAttr({subtitleTypo:v}); } }) : null, |
| 134 |
getTypoControl() ? el(getTypoControl(), { label:__('Badge','blockenberg'), value:a.badgeTypo, onChange:function(v){ setAttr({badgeTypo:v}); } }) : null, |
| 135 |
getTypoControl() ? el(getTypoControl(), { label:__('Feature','blockenberg'), value:a.featureTypo, onChange:function(v){ setAttr({featureTypo:v}); } }) : null, |
| 136 |
getTypoControl() ? el(getTypoControl(), { label:__('Primary button','blockenberg'), value:a.btnTypo, onChange:function(v){ setAttr({btnTypo:v}); } }) : null |
| 137 |
), |
| 138 |
el(PanelColorSettings, { title:__('Colors','blockenberg'), initialOpen:false, colorSettings:[ |
| 139 |
{label:__('Check icon','blockenberg'), value:a.checkColor, onChange:function(v){ setAttr({checkColor:v||''}); }}, |
| 140 |
{label:__('Price label','blockenberg'), value:a.priceLabelColor, onChange:function(v){ setAttr({priceLabelColor:v||''}); }}, |
| 141 |
{label:__('Price value','blockenberg'), value:a.priceValueColor, onChange:function(v){ setAttr({priceValueColor:v||''}); }}, |
| 142 |
{label:__('Price note','blockenberg'), value:a.priceNoteColor, onChange:function(v){ setAttr({priceNoteColor:v||''}); }}, |
| 143 |
{label:__('Feature text','blockenberg'), value:a.featureColor, onChange:function(v){ setAttr({featureColor:v||''}); }}, |
| 144 |
{label:__('Right panel bg','blockenberg'), value:a.rightBg, onChange:function(v){ setAttr({rightBg:v||''}); }}, |
| 145 |
{label:__('CTA heading','blockenberg'), value:a.ctaHeadingColor, onChange:function(v){ setAttr({ctaHeadingColor:v||''}); }}, |
| 146 |
{label:__('CTA subtitle','blockenberg'), value:a.ctaSubtitleColor,onChange:function(v){ setAttr({ctaSubtitleColor:v||''}); }}, |
| 147 |
{label:__('Primary button bg','blockenberg'), value:a.primaryBg, onChange:function(v){ setAttr({primaryBg:v||''}); }}, |
| 148 |
{label:__('Primary button text','blockenberg'),value:a.primaryColor, onChange:function(v){ setAttr({primaryColor:v||''}); }}, |
| 149 |
{label:__('Quote text','blockenberg'), value:a.proofColor, onChange:function(v){ setAttr({proofColor:v||''}); }}, |
| 150 |
{label:__('Block border','blockenberg'), value:a.borderColor, onChange:function(v){ setAttr({borderColor:v||''}); }}, |
| 151 |
] }) |
| 152 |
); |
| 153 |
|
| 154 |
return el(Fragment, null, |
| 155 |
inspector, |
| 156 |
el('div', blockProps, |
| 157 |
el('div', { className:'bkbg-spc-wrap' }, |
| 158 |
/* Left — price panel */ |
| 159 |
el('div', { className:'bkbg-spc-left', style:{ background: getLeftBg(a) } }, |
| 160 |
a.showBadge ? el('span', { className:'bkbg-spc-badge' }, a.badge) : null, |
| 161 |
el('div', { className:'bkbg-spc-price-label' }, a.priceLabel), |
| 162 |
el('div', { className:'bkbg-spc-price-row' }, |
| 163 |
a.showOldPrice ? el('span', { className:'bkbg-spc-old-price' }, a.oldPrice) : null, |
| 164 |
el('span', { className:'bkbg-spc-price' }, a.priceValue), |
| 165 |
el('span', { className:'bkbg-spc-period' }, ' / ' + a.pricePeriod) |
| 166 |
), |
| 167 |
el('div', { className:'bkbg-spc-price-note' }, a.priceNote), |
| 168 |
el('ul', { className:'bkbg-spc-features' }, |
| 169 |
a.features.map(function(f) { |
| 170 |
return el('li', { key:f.id }, |
| 171 |
el('span', { className:'bkbg-spc-check' }, '✓'), |
| 172 |
f.text |
| 173 |
); |
| 174 |
}) |
| 175 |
) |
| 176 |
), |
| 177 |
/* Right — CTA panel */ |
| 178 |
el('div', { className:'bkbg-spc-right' }, |
| 179 |
el(RichText, { tagName:'h3', className:'bkbg-spc-heading', value:a.ctaHeading, onChange:function(v){ setAttr({ctaHeading:v}); }, placeholder:__('CTA heading…','blockenberg') }), |
| 180 |
el(RichText, { tagName:'p', className:'bkbg-spc-subtitle', value:a.ctaSubtitle, onChange:function(v){ setAttr({ctaSubtitle:v}); }, placeholder:__('Subtitle…','blockenberg') }), |
| 181 |
el('div', { className:'bkbg-spc-actions' }, |
| 182 |
el('a', { href:'#', className:'bkbg-spc-btn-primary', onClick:function(e){ e.preventDefault(); } }, a.primaryLabel), |
| 183 |
a.showSecondary ? el('a', { href:'#', className:'bkbg-spc-btn-secondary', onClick:function(e){ e.preventDefault(); } }, a.secondaryLabel) : null |
| 184 |
), |
| 185 |
a.showSocialProof ? el('div', { className:'bkbg-spc-proof' }, |
| 186 |
el('p', { className:'bkbg-spc-proof-text' }, a.socialProofText), |
| 187 |
el('p', { className:'bkbg-spc-proof-author' }, a.socialProofAuthor) |
| 188 |
) : null |
| 189 |
) |
| 190 |
) |
| 191 |
) |
| 192 |
); |
| 193 |
}, |
| 194 |
|
| 195 |
save: function (props) { |
| 196 |
var a = props.attributes; |
| 197 |
var blockProps = wp.blockEditor.useBlockProps.save({ className:'bkbg-spc-outer', style:wrapStyle(a) }); |
| 198 |
return el('div', blockProps, |
| 199 |
el('div', { className:'bkbg-spc-wrap' }, |
| 200 |
el('div', { className:'bkbg-spc-left', style:{ background: getLeftBg(a) } }, |
| 201 |
a.showBadge ? el('span', { className:'bkbg-spc-badge' }, a.badge) : null, |
| 202 |
el('div', { className:'bkbg-spc-price-label' }, a.priceLabel), |
| 203 |
el('div', { className:'bkbg-spc-price-row' }, |
| 204 |
a.showOldPrice ? el('span', { className:'bkbg-spc-old-price' }, a.oldPrice) : null, |
| 205 |
el('span', { className:'bkbg-spc-price' }, a.priceValue), |
| 206 |
el('span', { className:'bkbg-spc-period' }, ' / ' + a.pricePeriod) |
| 207 |
), |
| 208 |
el('div', { className:'bkbg-spc-price-note' }, a.priceNote), |
| 209 |
el('ul', { className:'bkbg-spc-features' }, |
| 210 |
a.features.map(function(f) { |
| 211 |
return el('li', { key:f.id }, el('span', { className:'bkbg-spc-check' }, '✓'), f.text); |
| 212 |
}) |
| 213 |
) |
| 214 |
), |
| 215 |
el('div', { className:'bkbg-spc-right' }, |
| 216 |
el(RichText.Content, { tagName:'h3', className:'bkbg-spc-heading', value:a.ctaHeading }), |
| 217 |
el(RichText.Content, { tagName:'p', className:'bkbg-spc-subtitle', value:a.ctaSubtitle }), |
| 218 |
el('div', { className:'bkbg-spc-actions' }, |
| 219 |
el('a', { href:a.primaryUrl, className:'bkbg-spc-btn-primary', target:a.primaryTarget, rel:a.primaryTarget==='_blank'?'noopener noreferrer':undefined }, a.primaryLabel), |
| 220 |
a.showSecondary ? el('a', { href:a.secondaryUrl, className:'bkbg-spc-btn-secondary', target:a.secondaryTarget, rel:a.secondaryTarget==='_blank'?'noopener noreferrer':undefined }, a.secondaryLabel) : null |
| 221 |
), |
| 222 |
a.showSocialProof ? el('div', { className:'bkbg-spc-proof' }, |
| 223 |
el('p', { className:'bkbg-spc-proof-text' }, a.socialProofText), |
| 224 |
el('p', { className:'bkbg-spc-proof-author' }, a.socialProofAuthor) |
| 225 |
) : null |
| 226 |
) |
| 227 |
) |
| 228 |
); |
| 229 |
} |
| 230 |
}); |
| 231 |
}() ); |
| 232 |
|