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 / verdict-box / index.js

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

372 lines 24.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 __ = wp.i18n.__;
5 var registerBlockType = wp.blocks.registerBlockType;
6 var InspectorControls = wp.blockEditor.InspectorControls;
7 var useBlockProps = wp.blockEditor.useBlockProps;
8 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
9 var PanelBody = wp.components.PanelBody;
10 var ToggleControl = wp.components.ToggleControl;
11 var RangeControl = wp.components.RangeControl;
12 var SelectControl = wp.components.SelectControl;
13 var TextControl = wp.components.TextControl;
14 var Button = wp.components.Button;
15
16 var _tc, _tvf;
17 Object.defineProperty(window, '_tc', { get: function () { return _tc || (_tc = window.bkbgTypographyControl); } });
18 Object.defineProperty(window, '_tvf', { get: function () { return _tvf || (_tvf = window.bkbgTypoCssVars); } });
19 function getTypoControl(label, key, attrs, setA) { return _tc(label, key, attrs, setA); }
20 function getTypoCssVars(attrs) {
21 var v = {};
22 _tvf(v, 'nameTypo', attrs, '--bkvb-nm-');
23 _tvf(v, 'bodyTypo', attrs, '--bkvb-bd-');
24 _tvf(v, 'taglineTypo', attrs, '--bkvb-tl-');
25 _tvf(v, 'scoreTypo', attrs, '--bkvb-sc-');
26 _tvf(v, 'prosConsLabelTypo', attrs, '--bkvb-pl-');
27 _tvf(v, 'ctaTypo', attrs, '--bkvb-ct-');
28 return v;
29 }
30
31 var BADGE_OPTIONS = [
32 { label: '⭐ Recommended', value: 'recommended' },
33 { label: '💰 Best Value', value: 'best-value' },
34 { label: '🏆 Top Pick', value: 'top-pick' },
35 { label: '�
36 Award Winner',value: 'award-winner' },
37 { label: '👎 Skip It', value: 'skip' },
38 { label: '(None)', value: 'none' }
39 ];
40
41 function badgeLabel(badge) {
42 if (badge === 'recommended') return '⭐ Recommended';
43 if (badge === 'best-value') return '💰 Best Value';
44 if (badge === 'top-pick') return '🏆 Top Pick';
45 if (badge === 'award-winner') return '�
46 Award Winner';
47 if (badge === 'skip') return '👎 Skip It';
48 return '';
49 }
50
51 function badgeColors(badge) {
52 if (badge === 'skip') return { bg: '#fee2e2', color: '#991b1b' };
53 if (badge === 'best-value') return { bg: '#dcfce7', color: '#14532d' };
54 if (badge === 'top-pick') return { bg: '#eff6ff', color: '#1e40af' };
55 if (badge === 'award-winner') return { bg: '#fef9c3', color: '#713f12' };
56 return { bg: '#fbbf24', color: '#451a03' }; /* recommended / default */
57 }
58
59 /* ── ES5 update helpers ──────────────────────────── */
60 function updateList(list, idx, val) {
61 return list.map(function (item, i) { return i === idx ? val : item; });
62 }
63 function removeItem(list, idx) { return list.filter(function (_, i) { return i !== idx; }); }
64 function addItem(list) { return list.concat(['New item']); }
65
66 /* score fill percentage for progress-bar style */
67 function scoreFill(score, max) { return Math.min(100, Math.max(0, (score / max) * 100)); }
68
69 registerBlockType('blockenberg/verdict-box', {
70 edit: function (props) {
71 var a = props.attributes;
72 var set = props.setAttributes;
73 var blockProps = useBlockProps((function () {
74 var s = getTypoCssVars(a);
75 return { className: 'bkbg-vb-editor', style: s };
76 })());
77
78 function renderScore() {
79 var pct = scoreFill(a.overallScore, a.scoreMax);
80 if (a.scoreDisplay === 'circle') {
81 return el('div', {
82 className: 'bkbg-vb-score-circle',
83 style: {
84 width: '80px', height: '80px', borderRadius: '50%',
85 background: a.scoreCircleBg, color: a.scoreCircleColor,
86 display: 'flex', flexDirection: 'column', alignItems: 'center',
87 justifyContent: 'center', flexShrink: 0
88 }
89 },
90 el('span', { style: { fontSize: '26px', fontWeight: 800, lineHeight: 1 } }, a.overallScore.toFixed(1)),
91 el('span', { style: { fontSize: '11px', opacity: '.8' } }, '/' + a.scoreMax)
92 );
93 }
94 if (a.scoreDisplay === 'bar') {
95 return el('div', { style: { minWidth: '120px', flexShrink: 0 } },
96 el('div', { style: { fontSize: '28px', fontWeight: 800, color: a.scoreCircleBg, lineHeight: 1 } }, a.overallScore.toFixed(1)),
97 el('div', { style: { fontSize: '11px', color: a.headerColor, opacity: '.7', marginBottom: '6px' } }, '/ ' + a.scoreMax),
98 el('div', { style: { height: '6px', borderRadius: '3px', background: 'rgba(255,255,255,.25)', overflow: 'hidden' } },
99 el('div', { style: { height: '100%', width: pct + '%', background: a.scoreCircleBg, borderRadius: '3px' } })
100 )
101 );
102 }
103 /* numeric only */
104 return el('div', { style: { flexShrink: 0 } },
105 el('span', { style: { fontSize: '36px', fontWeight: 900, color: a.scoreCircleBg, lineHeight: 1 } }, a.overallScore.toFixed(1)),
106 el('span', { style: { fontSize: '18px', color: a.headerColor, opacity: '.7' } }, '/' + a.scoreMax)
107 );
108 }
109
110 function renderPreview() {
111 var bCol = a.badge !== 'none' ? badgeColors(a.badge) : null;
112 return el('div', {
113 className: 'bkbg-vb-block',
114 style: {
115 background: a.bgColor,
116 border: '1px solid ' + a.borderColor,
117 borderRadius: a.borderRadius + 'px',
118 overflow: 'hidden', boxSizing: 'border-box'
119 }
120 },
121 /* Header */
122 el('div', {
123 className: 'bkbg-vb-header',
124 style: {
125 background: a.headerBg, color: a.headerColor,
126 padding: '20px 24px', display: 'flex',
127 alignItems: 'center', gap: '20px', flexWrap: 'wrap'
128 }
129 },
130 renderScore(),
131 el('div', { style: { flex: 1 } },
132 el('h3', { className: 'bkbg-vb-product-name', style: { color: a.headerColor } }, a.productName),
133 a.showTagline && a.productTagline && el('div', { style: { fontSize: '13px', opacity: '.75', marginBottom: '8px' } }, a.productTagline),
134 a.badge !== 'none' && bCol && el('span', {
135 style: {
136 display: 'inline-block', padding: '4px 12px', borderRadius: '100px',
137 fontSize: '12px', fontWeight: 700, background: bCol.bg, color: bCol.color
138 }
139 }, badgeLabel(a.badge))
140 ),
141 el('div', {
142 style: { textAlign: 'right', flexShrink: 0 }
143 },
144 el('div', { style: { fontSize: '11px', opacity: '.6', textTransform: 'uppercase', letterSpacing: '.08em' } }, a.scoreLabel)
145 )
146 ),
147 /* Pros & Cons */
148 el('div', {
149 className: 'bkbg-vb-proscons',
150 style: { display: 'flex', flexWrap: 'wrap', gap: a.layout === 'split' ? '0' : '0' }
151 },
152 /* Pros */
153 el('div', {
154 className: 'bkbg-vb-pros',
155 style: {
156 flex: 1, minWidth: '220px',
157 background: a.prosBg,
158 borderRight: '1px solid ' + a.borderColor,
159 padding: '18px 22px'
160 }
161 },
162 el('div', { style: { fontWeight: 700, fontSize: '14px', color: a.prosColor, marginBottom: '12px' } }, a.prosLabel),
163 el('ul', { style: { margin: 0, padding: 0, listStyle: 'none' } },
164 a.pros.map(function (pro, idx) {
165 return el('li', {
166 key: idx,
167 style: { display: 'flex', gap: '8px', marginBottom: '8px', color: a.prosColor, alignItems: 'flex-start' }
168 },
169 el('span', { style: { color: a.prosIconColor, flexShrink: 0, marginTop: '1px' } }, ''),
170 el('span', { style: { lineHeight: 1.5 } }, pro)
171 );
172 })
173 )
174 ),
175 /* Cons */
176 el('div', {
177 className: 'bkbg-vb-cons',
178 style: {
179 flex: 1, minWidth: '220px',
180 background: a.consBg,
181 padding: '18px 22px'
182 }
183 },
184 el('div', { style: { fontWeight: 700, fontSize: '14px', color: a.consColor, marginBottom: '12px' } }, a.consLabel),
185 el('ul', { style: { margin: 0, padding: 0, listStyle: 'none' } },
186 a.cons.map(function (con, idx) {
187 return el('li', {
188 key: idx,
189 style: { display: 'flex', gap: '8px', marginBottom: '8px', color: a.consColor, alignItems: 'flex-start' }
190 },
191 el('span', { style: { color: a.consIconColor, flexShrink: 0, marginTop: '1px' } }, ''),
192 el('span', { style: { lineHeight: 1.5 } }, con)
193 );
194 })
195 )
196 )
197 ),
198 /* Verdict */
199 a.showVerdict && a.verdictText && el('div', {
200 className: 'bkbg-vb-verdict',
201 style: {
202 background: a.verdictBg, borderTop: '1px solid ' + a.verdictBorderColor,
203 padding: '16px 24px', display: 'flex', gap: '12px', alignItems: 'flex-start'
204 }
205 },
206 el('span', { style: { fontSize: '18px', flexShrink: 0 } }, '💬'),
207 el('p', { style: { margin: 0, color: a.verdictColor, lineHeight: 1.65 } }, a.verdictText)
208 ),
209 /* CTAs */
210 (a.showCta || a.showSecondaryCta) && el('div', {
211 className: 'bkbg-vb-ctas',
212 style: { padding: '16px 24px', borderTop: '1px solid ' + a.borderColor, display: 'flex', gap: '12px', flexWrap: 'wrap' }
213 },
214 a.showCta && a.ctaText && el('a', {
215 href: a.ctaUrl || '#', target: '_blank',
216 className: 'bkbg-vb-cta-primary',
217 style: {
218 display: 'inline-block', padding: '12px 24px',
219 background: a.ctaBg, color: a.ctaColor,
220 borderRadius: (a.borderRadius - 4) + 'px',
221 fontWeight: 700, fontSize: '15px',
222 textDecoration: 'none'
223 }
224 }, a.ctaText),
225 a.showSecondaryCta && a.ctaSecondaryText && el('a', {
226 href: a.ctaSecondaryUrl || '#', target: '_blank',
227 className: 'bkbg-vb-cta-secondary',
228 style: {
229 display: 'inline-block', padding: '12px 24px',
230 border: '2px solid ' + a.ctaSecondaryColor,
231 color: a.ctaSecondaryColor,
232 borderRadius: (a.borderRadius - 4) + 'px',
233 fontWeight: 700, fontSize: '15px',
234 textDecoration: 'none', background: 'transparent'
235 }
236 }, a.ctaSecondaryText)
237 )
238 );
239 }
240
241 var inspector = el(InspectorControls, {},
242 /* Product Info */
243 el(PanelBody, { title: 'Product Info', initialOpen: true },
244 el(TextControl, { __nextHasNoMarginBottom: true, label: 'Product Name', value: a.productName, onChange: function (v) { set({ productName: v }); } }),
245 el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Show Tagline', checked: a.showTagline, onChange: function (v) { set({ showTagline: v }); } }),
246 a.showTagline && el(TextControl, { __nextHasNoMarginBottom: true, label: 'Tagline', value: a.productTagline, onChange: function (v) { set({ productTagline: v }); } }),
247 el('div', { style: { marginBottom: 8, fontWeight: 600, fontSize: 12 } }, 'Score'),
248 el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Overall Score', value: a.overallScore, min: 0, max: a.scoreMax, step: 0.1, onChange: function (v) { set({ overallScore: v }); } }),
249 el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Score Max', value: a.scoreMax, min: 5, max: 100, onChange: function (v) { set({ scoreMax: v }); } }),
250 el(TextControl, { __nextHasNoMarginBottom: true, label: 'Score Label', value: a.scoreLabel, onChange: function (v) { set({ scoreLabel: v }); } }),
251 el(SelectControl, { __nextHasNoMarginBottom: true, label: 'Score Display', value: a.scoreDisplay, options: [{ label: 'Circle', value: 'circle' }, { label: 'Progress Bar', value: 'bar' }, { label: 'Numeric Only', value: 'numeric' }], onChange: function (v) { set({ scoreDisplay: v }); } }),
252 el(SelectControl, { __nextHasNoMarginBottom: true, label: 'Verdict Badge', value: a.badge, options: BADGE_OPTIONS, onChange: function (v) { set({ badge: v }); } })
253 ),
254 /* Pros */
255 el(PanelBody, { title: 'Pros (' + a.pros.length + ')', initialOpen: true },
256 el(TextControl, { __nextHasNoMarginBottom: true, label: 'Pros Label', value: a.prosLabel, onChange: function (v) { set({ prosLabel: v }); } }),
257 a.pros.map(function (pro, idx) {
258 return el('div', {
259 key: idx,
260 style: { display: 'flex', gap: 6, marginBottom: 6, alignItems: 'center' }
261 },
262 el('input', {
263 type: 'text', value: pro,
264 style: { flex: 1, fontSize: 12, padding: '5px 7px', border: '1px solid #ddd', borderRadius: 4 },
265 onChange: function (e) { set({ pros: updateList(a.pros, idx, e.target.value) }); }
266 }),
267 el(Button, { isSmall: true, isDestructive: true, onClick: function () { set({ pros: removeItem(a.pros, idx) }); } }, '')
268 );
269 }),
270 el(Button, { variant: 'secondary', style: { width: '100%', justifyContent: 'center', marginTop: 4 }, onClick: function () { set({ pros: addItem(a.pros) }); } }, '+ Add Pro')
271 ),
272 /* Cons */
273 el(PanelBody, { title: 'Cons (' + a.cons.length + ')', initialOpen: true },
274 el(TextControl, { __nextHasNoMarginBottom: true, label: 'Cons Label', value: a.consLabel, onChange: function (v) { set({ consLabel: v }); } }),
275 a.cons.map(function (con, idx) {
276 return el('div', {
277 key: idx,
278 style: { display: 'flex', gap: 6, marginBottom: 6, alignItems: 'center' }
279 },
280 el('input', {
281 type: 'text', value: con,
282 style: { flex: 1, fontSize: 12, padding: '5px 7px', border: '1px solid #ddd', borderRadius: 4 },
283 onChange: function (e) { set({ cons: updateList(a.cons, idx, e.target.value) }); }
284 }),
285 el(Button, { isSmall: true, isDestructive: true, onClick: function () { set({ cons: removeItem(a.cons, idx) }); } }, '')
286 );
287 }),
288 el(Button, { variant: 'secondary', style: { width: '100%', justifyContent: 'center', marginTop: 4 }, onClick: function () { set({ cons: addItem(a.cons) }); } }, '+ Add Con')
289 ),
290 /* Verdict & CTAs */
291 el(PanelBody, { title: 'Verdict & CTAs', initialOpen: false },
292 el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Show Verdict Text', checked: a.showVerdict, onChange: function (v) { set({ showVerdict: v }); } }),
293 a.showVerdict && el('div', { style: { marginBottom: 8 } },
294 el('label', { style: { fontSize: 11, fontWeight: 600, display: 'block', marginBottom: 4 } }, 'Verdict Text'),
295 el('textarea', {
296 value: a.verdictText, rows: 4,
297 style: { width: '100%', fontSize: 12, padding: '5px 7px', border: '1px solid #ddd', borderRadius: 4, boxSizing: 'border-box', fontFamily: 'inherit' },
298 onChange: function (e) { set({ verdictText: e.target.value }); }
299 })
300 ),
301 el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Show Primary CTA', checked: a.showCta, onChange: function (v) { set({ showCta: v }); } }),
302 a.showCta && el(TextControl, { __nextHasNoMarginBottom: true, label: 'CTA Text', value: a.ctaText, onChange: function (v) { set({ ctaText: v }); } }),
303 a.showCta && el(TextControl, { __nextHasNoMarginBottom: true, label: 'CTA URL', value: a.ctaUrl, onChange: function (v) { set({ ctaUrl: v }); } }),
304 el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Show Secondary CTA', checked: a.showSecondaryCta, onChange: function (v) { set({ showSecondaryCta: v }); } }),
305 a.showSecondaryCta && el(TextControl, { __nextHasNoMarginBottom: true, label: 'Secondary CTA Text', value: a.ctaSecondaryText, onChange: function (v) { set({ ctaSecondaryText: v }); } }),
306 a.showSecondaryCta && el(TextControl, { __nextHasNoMarginBottom: true, label: 'Secondary CTA URL', value: a.ctaSecondaryUrl, onChange: function (v) { set({ ctaSecondaryUrl: v }); } })
307 ),
308 /* Display */
309 el(PanelBody, { title: 'Display', initialOpen: false },
310 el(SelectControl, { __nextHasNoMarginBottom: true, label: 'Layout', value: a.layout, options: [{ label: 'Split (side by side)', value: 'split' }, { label: 'Stacked', value: 'stacked' }], onChange: function (v) { set({ layout: v }); } }),
311 el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Border Radius', value: a.borderRadius, min: 0, max: 24, onChange: function (v) { set({ borderRadius: v }); } })
312 ),
313 /* Colors */
314
315 el( PanelBody, { title: __( 'Typography', 'blockenberg' ), initialOpen: false },
316 getTypoControl(__('Product Name', 'blockenberg'), 'nameTypo', a, set),
317 getTypoControl(__('Body Text', 'blockenberg'), 'bodyTypo', a, set),
318 getTypoControl(__('Tagline', 'blockenberg'), 'taglineTypo', a, set),
319 getTypoControl(__('Score', 'blockenberg'), 'scoreTypo', a, set),
320 getTypoControl(__('Pros/Cons Label', 'blockenberg'), 'prosConsLabelTypo', a, set),
321 getTypoControl(__('CTA Button', 'blockenberg'), 'ctaTypo', a, set)
322 ),
323 el(PanelColorSettings, {
324 title: 'Header & Score Colors', initialOpen: false,
325 colorSettings: [
326 { label: 'Header Background', value: a.headerBg, onChange: function (v) { set({ headerBg: v || '#0f172a' }); } },
327 { label: 'Header Text', value: a.headerColor, onChange: function (v) { set({ headerColor: v || '#ffffff' }); } },
328 { label: 'Score Circle Background', value: a.scoreCircleBg, onChange: function (v) { set({ scoreCircleBg: v || '#6366f1' }); } },
329 { label: 'Score Circle Text', value: a.scoreCircleColor, onChange: function (v) { set({ scoreCircleColor: v || '#ffffff' }); } },
330 { label: 'Block Background', value: a.bgColor, onChange: function (v) { set({ bgColor: v || '#ffffff' }); } },
331 { label: 'Border Color', value: a.borderColor, onChange: function (v) { set({ borderColor: v || '#e2e8f0' }); } }
332 ]
333 }),
334 el(PanelColorSettings, {
335 title: 'Pros & Cons Colors', initialOpen: false,
336 colorSettings: [
337 { label: 'Pros Background', value: a.prosBg, onChange: function (v) { set({ prosBg: v || '#f0fdf4' }); } },
338 { label: 'Pros Text Color', value: a.prosColor, onChange: function (v) { set({ prosColor: v || '#14532d' }); } },
339 { label: 'Pros Icon Color', value: a.prosIconColor, onChange: function (v) { set({ prosIconColor: v || '#22c55e' }); } },
340 { label: 'Cons Background', value: a.consBg, onChange: function (v) { set({ consBg: v || '#fef2f2' }); } },
341 { label: 'Cons Text Color', value: a.consColor, onChange: function (v) { set({ consColor: v || '#7f1d1d' }); } },
342 { label: 'Cons Icon Color', value: a.consIconColor, onChange: function (v) { set({ consIconColor: v || '#ef4444' }); } }
343 ]
344 }),
345 el(PanelColorSettings, {
346 title: 'Verdict & CTA Colors', initialOpen: false,
347 colorSettings: [
348 { label: 'Verdict Background', value: a.verdictBg, onChange: function (v) { set({ verdictBg: v || '#f8fafc' }); } },
349 { label: 'Verdict Text Color', value: a.verdictColor, onChange: function (v) { set({ verdictColor: v || '#374151' }); } },
350 { label: 'CTA Background', value: a.ctaBg, onChange: function (v) { set({ ctaBg: v || '#6366f1' }); } },
351 { label: 'CTA Text Color', value: a.ctaColor, onChange: function (v) { set({ ctaColor: v || '#ffffff' }); } },
352 { label: 'Secondary CTA Color', value: a.ctaSecondaryColor, onChange: function (v) { set({ ctaSecondaryColor: v || '#6366f1' }); } }
353 ]
354 })
355 );
356
357 return el(Fragment, {}, inspector, el('div', blockProps, renderPreview()));
358 },
359
360 save: function (props) {
361 var a = props.attributes;
362 var blockProps = wp.blockEditor.useBlockProps.save((function () { var _tv = getTypoCssVars(a); return { style: _tv }; })());
363 return el('div', blockProps,
364 el('div', {
365 className: 'bkbg-verdict-box-app',
366 'data-opts': JSON.stringify(props.attributes)
367 })
368 );
369 }
370 });
371 }() );
372