| 1 |
( function () { |
| 2 |
var el = wp.element.createElement; |
| 3 |
var Fragment = wp.element.Fragment; |
| 4 |
var useState = wp.element.useState; |
| 5 |
var __ = wp.i18n.__; |
| 6 |
var registerBlockType = wp.blocks.registerBlockType; |
| 7 |
var InspectorControls = wp.blockEditor.InspectorControls; |
| 8 |
var RichText = wp.blockEditor.RichText; |
| 9 |
var useBlockProps = wp.blockEditor.useBlockProps; |
| 10 |
var PanelBody = wp.components.PanelBody; |
| 11 |
var Button = wp.components.Button; |
| 12 |
var ToggleControl = wp.components.ToggleControl; |
| 13 |
var RangeControl = wp.components.RangeControl; |
| 14 |
var SelectControl = wp.components.SelectControl; |
| 15 |
var TextControl = wp.components.TextControl; |
| 16 |
var ColorPicker = wp.components.ColorPicker; |
| 17 |
var Popover = wp.components.Popover; |
| 18 |
|
| 19 |
var _tc; function getTypoControl() { return _tc || (_tc = window.bkbgTypographyControl); } |
| 20 |
var _tv; function getTypoCssVars() { return _tv || (_tv = window.bkbgTypoCssVars); } |
| 21 |
|
| 22 |
var LAYOUT_OPTIONS = [ |
| 23 |
{ label: __('Equal halves', 'blockenberg'), value: 'equal' }, |
| 24 |
{ label: __('60 / 40', 'blockenberg'), value: '60-40' }, |
| 25 |
{ label: __('40 / 60', 'blockenberg'), value: '40-60' }, |
| 26 |
]; |
| 27 |
var DIVIDER_STYLE_OPTIONS = [ |
| 28 |
{ label: __('None', 'blockenberg'), value: 'none' }, |
| 29 |
{ label: __('Line', 'blockenberg'), value: 'line' }, |
| 30 |
{ label: __('Arrow', 'blockenberg'), value: 'arrow' }, |
| 31 |
]; |
| 32 |
var TEXT_ALIGN_OPTIONS = [ |
| 33 |
{ label: __('Left', 'blockenberg'), value: 'left' }, |
| 34 |
{ label: __('Center', 'blockenberg'), value: 'center' }, |
| 35 |
{ label: __('Right', 'blockenberg'), value: 'right' }, |
| 36 |
]; |
| 37 |
|
| 38 |
function makeId() { return 'sc' + Math.random().toString(36).substr(2, 5); } |
| 39 |
|
| 40 |
function buildWrapStyle(a) { |
| 41 |
var s = { |
| 42 |
'--bkbg-sct-wrap-r': a.wrapRadius + 'px', |
| 43 |
'--bkbg-sct-btn-r': a.btnRadius + 'px', |
| 44 |
'--bkbg-sct-badge-r': a.badgeRadius + 'px', |
| 45 |
'--bkbg-sct-headline-sz': a.headlineSize + 'px', |
| 46 |
'--bkbg-sct-desc-sz': a.descSize + 'px', |
| 47 |
'--bkbg-sct-badge-sz': a.badgeSize + 'px', |
| 48 |
'--bkbg-sct-btn-sz': a.btnSize + 'px', |
| 49 |
'--bkbg-sct-min-h': a.minHeight + 'px', |
| 50 |
'--bkbg-sct-pad': a.panelPadding + 'px', |
| 51 |
'--bkbg-sct-div-color': a.dividerColor, |
| 52 |
'--bkbg-sct-hl-w': a.headlineFontWeight || 700, |
| 53 |
paddingTop: a.paddingTop + 'px', |
| 54 |
paddingBottom: a.paddingBottom + 'px', |
| 55 |
}; |
| 56 |
var tv = getTypoCssVars(); |
| 57 |
if (tv) { |
| 58 |
Object.assign(s, tv(a.headlineTypo, '--bksct-hl-')); |
| 59 |
Object.assign(s, tv(a.descTypo, '--bksct-ds-')); |
| 60 |
Object.assign(s, tv(a.badgeTypo, '--bksct-bd-')); |
| 61 |
Object.assign(s, tv(a.btnTypo, '--bksct-bt-')); |
| 62 |
} |
| 63 |
return s; |
| 64 |
} |
| 65 |
|
| 66 |
function renderColorControl(key, label, value, onChange, openKey, setOpenKey) { |
| 67 |
var isOpen = openKey === key; |
| 68 |
return el('div', { key: key, style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '4px 0', gap: '8px' } }, |
| 69 |
el('span', { style: { fontSize: '12px', color: '#1e1e1e', flex: 1, lineHeight: 1.4 } }, label), |
| 70 |
el('div', { style: { position: 'relative', flexShrink: 0 } }, |
| 71 |
el('button', { type: 'button', title: value || 'default', onClick: function () { setOpenKey(isOpen ? null : key); }, |
| 72 |
style: { width: '28px', height: '28px', borderRadius: '4px', border: isOpen ? '2px solid #007cba' : '2px solid #ddd', cursor: 'pointer', padding: 0, background: value || '#cccccc' } |
| 73 |
}), |
| 74 |
isOpen && el(Popover, { position: 'bottom left', onClose: function () { setOpenKey(null); } }, |
| 75 |
el('div', { style: { padding: '8px' } }, |
| 76 |
el(ColorPicker, { color: value, enableAlpha: true, onChange: onChange }) |
| 77 |
) |
| 78 |
) |
| 79 |
) |
| 80 |
); |
| 81 |
} |
| 82 |
|
| 83 |
/* ── Single CTA panel ───────────────────────────────────────────── */ |
| 84 |
function CtaPanel(props) { |
| 85 |
var panel = props.panel; |
| 86 |
var a = props.a; |
| 87 |
var sa = props.setAttributes; |
| 88 |
var isEditor = props.isEditor; |
| 89 |
|
| 90 |
function update(key, val) { |
| 91 |
if (!sa) return; |
| 92 |
sa({ panels: a.panels.map(function (p) { if (p.id !== panel.id) return p; var u = Object.assign({}, p); u[key] = val; return u; }) }); |
| 93 |
} |
| 94 |
|
| 95 |
var panelStyle = { |
| 96 |
flex: 1, display: 'flex', flexDirection: 'column', alignItems: a.textAlign === 'center' ? 'center' : (a.textAlign === 'right' ? 'flex-end' : 'flex-start'), |
| 97 |
justifyContent: 'center', textAlign: a.textAlign, padding: a.panelPadding + 'px', minHeight: a.minHeight + 'px', |
| 98 |
backgroundColor: panel.bgColor || '#f5f3ff', color: panel.textColor || '#1e1e1e', |
| 99 |
}; |
| 100 |
var btnStyle = { display: 'inline-block', padding: '13px 32px', borderRadius: a.btnRadius + 'px', backgroundColor: panel.btnBg || '#6c3fb5', color: panel.btnColor || '#fff', cursor: 'pointer', border: 'none', marginTop: '18px' }; |
| 101 |
var badgeStyle = { display: 'inline-block', padding: '4px 14px', borderRadius: a.badgeRadius + 'px', backgroundColor: panel.btnBg + '22', color: panel.btnBg, marginBottom: '14px' }; |
| 102 |
|
| 103 |
if (isEditor) { |
| 104 |
return el('div', { className: 'bkbg-sct-panel', style: panelStyle }, |
| 105 |
panel.showBadge && el('span', { className: 'bkbg-sct-badge', style: badgeStyle }, panel.badge || __('Free', 'blockenberg')), |
| 106 |
el(RichText, { tagName: 'h2', className: 'bkbg-sct-headline', value: panel.headline, onChange: function (v) { update('headline', v); }, placeholder: __('Headline…', 'blockenberg'), style: { color: panel.textColor, margin: '0 0 12px', textAlign: a.textAlign } }), |
| 107 |
el(RichText, { tagName: 'p', className: 'bkbg-sct-desc', value: panel.description, onChange: function (v) { update('description', v); }, placeholder: __('Short description…', 'blockenberg'), style: { color: panel.textColor, margin: '0', textAlign: a.textAlign } }), |
| 108 |
el('span', { className: 'bkbg-sct-btn', style: btnStyle }, panel.btnLabel || __('Get Started', 'blockenberg')) |
| 109 |
); |
| 110 |
} |
| 111 |
|
| 112 |
return el('div', { className: 'bkbg-sct-panel', style: panelStyle }, |
| 113 |
panel.showBadge && el('span', { className: 'bkbg-sct-badge', style: badgeStyle }, panel.badge || ''), |
| 114 |
el(RichText.Content, { tagName: 'h2', className: 'bkbg-sct-headline', value: panel.headline, style: { color: panel.textColor } }), |
| 115 |
el(RichText.Content, { tagName: 'p', className: 'bkbg-sct-desc', value: panel.description, style: { color: panel.textColor } }), |
| 116 |
el('a', { href: panel.btnUrl || '#', className: 'bkbg-sct-btn', target: panel.btnNewTab ? '_blank' : undefined, rel: panel.btnNewTab ? 'noopener noreferrer' : undefined, style: btnStyle }, panel.btnLabel || '') |
| 117 |
); |
| 118 |
} |
| 119 |
|
| 120 |
/* ── Divider ────────────────────────────────────────────────────── */ |
| 121 |
function Divider(props) { |
| 122 |
var a = props.a; |
| 123 |
if (!a.showDivider || a.dividerStyle === 'none') return null; |
| 124 |
if (a.dividerStyle === 'arrow') { |
| 125 |
return el('div', { className: 'bkbg-sct-divider bkbg-sct-div--arrow', style: { position: 'relative', width: '48px', flexShrink: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '28px', color: a.dividerColor || '#6c3fb5' } }, '→'); |
| 126 |
} |
| 127 |
return el('div', { className: 'bkbg-sct-divider bkbg-sct-div--line', style: { width: '1px', flexShrink: 0, alignSelf: 'stretch', backgroundColor: a.dividerColor || '#ddd', margin: '24px 0' } }); |
| 128 |
} |
| 129 |
|
| 130 |
registerBlockType('blockenberg/split-cta', { |
| 131 |
title: __('Split CTA', 'blockenberg'), |
| 132 |
icon: 'columns', |
| 133 |
category: 'bkbg-marketing', |
| 134 |
|
| 135 |
edit: function (props) { |
| 136 |
var a = props.attributes; |
| 137 |
var setAttributes = props.setAttributes; |
| 138 |
|
| 139 |
var openColorKeyState = useState(null); |
| 140 |
var openColorKey = openColorKeyState[0]; |
| 141 |
var setOpenColorKey = openColorKeyState[1]; |
| 142 |
|
| 143 |
var blockProps = useBlockProps({ style: buildWrapStyle(a) }); |
| 144 |
|
| 145 |
function panelColorControl(panelId, key, label, value) { |
| 146 |
var ckKey = panelId + '_' + key; |
| 147 |
return renderColorControl(ckKey, label, value, function (val) { |
| 148 |
setAttributes({ panels: a.panels.map(function (p) { if (p.id !== panelId) return p; var u = Object.assign({}, p); u[key] = val; return u; }) }); |
| 149 |
}, openColorKey, setOpenColorKey); |
| 150 |
} |
| 151 |
|
| 152 |
var wrapFlex = { display: 'flex', flexDirection: 'row', borderRadius: a.wrapRadius + 'px', overflow: 'hidden' }; |
| 153 |
|
| 154 |
return el(Fragment, null, |
| 155 |
el(InspectorControls, null, |
| 156 |
el(PanelBody, { title: __('Layout', 'blockenberg'), initialOpen: true }, |
| 157 |
el(SelectControl, { label: __('Panel sizes', 'blockenberg'), value: a.layout, options: LAYOUT_OPTIONS, onChange: function (v) { setAttributes({ layout: v }); } }), |
| 158 |
el(SelectControl, { label: __('Text align', 'blockenberg'), value: a.textAlign, options: TEXT_ALIGN_OPTIONS, onChange: function (v) { setAttributes({ textAlign: v }); } }), |
| 159 |
el(SelectControl, { label: __('Divider style', 'blockenberg'), value: a.dividerStyle, options: DIVIDER_STYLE_OPTIONS, onChange: function (v) { setAttributes({ dividerStyle: v }); } }), |
| 160 |
a.dividerStyle !== 'none' && renderColorControl('dividerColor', __('Divider color', 'blockenberg'), a.dividerColor, function (v) { setAttributes({ dividerColor: v }); }, openColorKey, setOpenColorKey), |
| 161 |
el(RangeControl, { label: __('Min height (px)', 'blockenberg'), value: a.minHeight, min: 160, max: 700, onChange: function (v) { setAttributes({ minHeight: v }); } }), |
| 162 |
el(RangeControl, { label: __('Panel padding (px)', 'blockenberg'), value: a.panelPadding, min: 20, max: 120, onChange: function (v) { setAttributes({ panelPadding: v }); } }), |
| 163 |
el(RangeControl, { label: __('Outer radius (px)', 'blockenberg'), value: a.wrapRadius, min: 0, max: 32, onChange: function (v) { setAttributes({ wrapRadius: v }); } }), |
| 164 |
el(RangeControl, { label: __('Button radius (px)', 'blockenberg'), value: a.btnRadius, min: 0, max: 99, onChange: function (v) { setAttributes({ btnRadius: v }); } }), |
| 165 |
el(RangeControl, { label: __('Badge radius (px)', 'blockenberg'), value: a.badgeRadius, min: 0, max: 99, onChange: function (v) { setAttributes({ badgeRadius: v }); } }), |
| 166 |
el(ToggleControl, { label: __('Stack on mobile', 'blockenberg'), checked: a.stackOnMobile, onChange: function (v) { setAttributes({ stackOnMobile: v }); }, __nextHasNoMarginBottom: true }) |
| 167 |
), |
| 168 |
el(PanelBody, { title: __('Typography', 'blockenberg'), initialOpen: false }, |
| 169 |
getTypoControl() ? el(getTypoControl(), { label: __('Headline Typography', 'blockenberg'), value: a.headlineTypo || {}, onChange: function (v) { setAttributes({ headlineTypo: v }); } }) : null, |
| 170 |
getTypoControl() ? el(getTypoControl(), { label: __('Description Typography', 'blockenberg'), value: a.descTypo || {}, onChange: function (v) { setAttributes({ descTypo: v }); } }) : null, |
| 171 |
getTypoControl() ? el(getTypoControl(), { label: __('Badge Typography', 'blockenberg'), value: a.badgeTypo || {}, onChange: function (v) { setAttributes({ badgeTypo: v }); } }) : null, |
| 172 |
getTypoControl() ? el(getTypoControl(), { label: __('Button Typography', 'blockenberg'), value: a.btnTypo || {}, onChange: function (v) { setAttributes({ btnTypo: v }); } }) : null |
| 173 |
), |
| 174 |
el(PanelBody, { title: __('Spacing', 'blockenberg'), initialOpen: false }, |
| 175 |
el(RangeControl, { label: __('Padding top (px)', 'blockenberg'), value: a.paddingTop, min: 0, max: 200, onChange: function (v) { setAttributes({ paddingTop: v }); } }), |
| 176 |
el(RangeControl, { label: __('Padding bottom (px)', 'blockenberg'), value: a.paddingBottom, min: 0, max: 200, onChange: function (v) { setAttributes({ paddingBottom: v }); } }) |
| 177 |
), |
| 178 |
a.panels.map(function (panel, pi) { |
| 179 |
return el(PanelBody, { key: panel.id, title: __('Panel', 'blockenberg') + ' ' + (pi + 1) + ': ' + (panel.headline ? panel.headline.replace(/<[^>]+>/g,'').substring(0,24) : '…'), initialOpen: pi === 0 }, |
| 180 |
el(ToggleControl, { label: __('Show badge', 'blockenberg'), checked: panel.showBadge, onChange: function (v) { setAttributes({ panels: a.panels.map(function (p) { if (p.id !== panel.id) return p; return Object.assign({}, p, { showBadge: v }); }) }); }, __nextHasNoMarginBottom: true }), |
| 181 |
panel.showBadge && el(TextControl, { label: __('Badge text', 'blockenberg'), value: panel.badge, onChange: function (v) { setAttributes({ panels: a.panels.map(function (p) { if (p.id !== panel.id) return p; return Object.assign({}, p, { badge: v }); }) }); } }), |
| 182 |
el(TextControl, { label: __('Button label', 'blockenberg'), value: panel.btnLabel, onChange: function (v) { setAttributes({ panels: a.panels.map(function (p) { if (p.id !== panel.id) return p; return Object.assign({}, p, { btnLabel: v }); }) }); } }), |
| 183 |
el(TextControl, { label: __('Button URL', 'blockenberg'), value: panel.btnUrl, onChange: function (v) { setAttributes({ panels: a.panels.map(function (p) { if (p.id !== panel.id) return p; return Object.assign({}, p, { btnUrl: v }); }) }); } }), |
| 184 |
el(ToggleControl, { label: __('Open link in new tab', 'blockenberg'), checked: panel.btnNewTab, onChange: function (v) { setAttributes({ panels: a.panels.map(function (p) { if (p.id !== panel.id) return p; return Object.assign({}, p, { btnNewTab: v }); }) }); }, __nextHasNoMarginBottom: true }), |
| 185 |
panelColorControl(panel.id, 'bgColor', __('Panel background', 'blockenberg'), panel.bgColor), |
| 186 |
panelColorControl(panel.id, 'textColor', __('Panel text', 'blockenberg'), panel.textColor), |
| 187 |
panelColorControl(panel.id, 'btnBg', __('Button background','blockenberg'), panel.btnBg), |
| 188 |
panelColorControl(panel.id, 'btnColor', __('Button text', 'blockenberg'), panel.btnColor) |
| 189 |
); |
| 190 |
}) |
| 191 |
), |
| 192 |
|
| 193 |
el('div', blockProps, |
| 194 |
el('div', { className: 'bkbg-sct-wrapper bkbg-sct--' + a.layout, style: wrapFlex }, |
| 195 |
el(CtaPanel, { panel: a.panels[0], a: a, setAttributes: setAttributes, isEditor: true }), |
| 196 |
el(Divider, { a: a }), |
| 197 |
el(CtaPanel, { panel: a.panels[1], a: a, setAttributes: setAttributes, isEditor: true }) |
| 198 |
) |
| 199 |
) |
| 200 |
); |
| 201 |
}, |
| 202 |
|
| 203 |
save: function (props) { |
| 204 |
var a = props.attributes; |
| 205 |
var wrapFlex = { display: 'flex', flexDirection: 'row', borderRadius: a.wrapRadius + 'px', overflow: 'hidden' }; |
| 206 |
return el('div', wp.blockEditor.useBlockProps.save({ className: 'bkbg-sct-section bkbg-sct--stack-' + (a.stackOnMobile ? 'yes' : 'no'), style: buildWrapStyle(a) }), |
| 207 |
el('div', { className: 'bkbg-sct-wrapper bkbg-sct--' + a.layout, style: wrapFlex }, |
| 208 |
el(CtaPanel, { panel: a.panels[0], a: a, isEditor: false }), |
| 209 |
el(Divider, { a: a }), |
| 210 |
el(CtaPanel, { panel: a.panels[1], a: a, isEditor: false }) |
| 211 |
) |
| 212 |
); |
| 213 |
} |
| 214 |
}); |
| 215 |
}() ); |
| 216 |
|