PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.7
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.7
2.0.13 2.0.12 2.0.11 2.0.10 2.0.9 trunk 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8
blockenberg / blocks / split-cta / index.js

index.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.7, at blocks/split-cta/index.js

216 lines 16.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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