PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.13
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.13
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 / case-study / index.js

index.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.13, at blocks/case-study/index.js

356 lines 27.7 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 MediaUpload = wp.blockEditor.MediaUpload;
11 var MediaUploadCheck = wp.blockEditor.MediaUploadCheck;
12 var PanelBody = wp.components.PanelBody;
13 var Button = wp.components.Button;
14 var ToggleControl = wp.components.ToggleControl;
15 var RangeControl = wp.components.RangeControl;
16 var SelectControl = wp.components.SelectControl;
17 var TextControl = wp.components.TextControl;
18 var TextareaControl = wp.components.TextareaControl;
19 var ColorPicker = wp.components.ColorPicker;
20 var Popover = wp.components.Popover;
21
22 function getTypographyControl() { return (window.bkbgTypographyControl || function () { return null; }); }
23 function getTypoCssVars() { return (window.bkbgTypoCssVars || function () { return {}; }); }
24 function _tv(typo, prefix) { var fn = getTypoCssVars(); return fn(typo || {}, prefix); }
25
26 function makeId() { return 'cs' + Math.random().toString(36).substr(2,8); }
27
28 var DEFAULT_METRICS = [
29 { id: makeId(), value: '94%', prefix: '', suffix: '%', label: 'Reporting time reduced', description: 'From weekly to daily reports', color: '#6c3fb5' },
30 { id: makeId(), value: '3.2×', prefix: '', suffix: '×', label: 'Productivity increase', description: 'Across all departments', color: '#059669' },
31 { id: makeId(), value: '$1.4M',prefix: '$', suffix: 'M', label: 'Annual savings', description: 'In operational overhead', color: '#0ea5e9' },
32 ];
33
34 /* ── Build wrapper CSS ──────────────────────────────────────────── */
35 function buildWrapStyle(a) {
36 return Object.assign({
37 '--bkbg-cs-accent': a.accentColor,
38 '--bkbg-cs-title': a.titleColor,
39 '--bkbg-cs-subtitle': a.subtitleColor,
40 '--bkbg-cs-label': a.labelColor,
41 '--bkbg-cs-body': a.bodyColor,
42 '--bkbg-cs-sec-lbl-bg': a.sectionLabelBg,
43 '--bkbg-cs-sec-lbl-col': a.sectionLabelColor,
44 '--bkbg-cs-card-bg': a.cardBg,
45 '--bkbg-cs-card-border': a.cardBorder,
46 '--bkbg-cs-metric-bg': a.metricBg,
47 '--bkbg-cs-quote-bg': a.quoteBg,
48 '--bkbg-cs-quote-border': a.quoteBorder,
49 '--bkbg-cs-quote-color': a.quoteColor,
50 '--bkbg-cs-cta-bg': a.ctaBg,
51 '--bkbg-cs-cta-color': a.ctaColor,
52 '--bkbg-cs-radius': a.cardRadius + 'px',
53 paddingTop: a.paddingTop + 'px',
54 paddingBottom: a.paddingBottom + 'px',
55 backgroundColor: a.bgColor || undefined,
56 },
57 _tv(a.typoTitle, '--bkbg-cs-tt-'),
58 _tv(a.typoSubtitle, '--bkbg-cs-ts-'),
59 _tv(a.typoBody, '--bkbg-cs-bd-'),
60 _tv(a.typoQuote, '--bkbg-cs-qt-'),
61 _tv(a.typoCta, '--bkbg-cs-ct-')
62 );
63 }
64
65 /* ── Colour swatch helper ───────────────────────────────────────── */
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', onClick: function(){ setOpenKey(isOpen ? null : key); }, style: { width:'28px', height:'28px', borderRadius:'4px', border: isOpen ? '2px solid #007cba' : '2px solid #ddd', cursor:'pointer', padding:0, background: value||'#ccc' } }),
72 isOpen && el(Popover, { position:'bottom left', onClose: function(){ setOpenKey(null); } },
73 el('div', { style:{ padding:'8px' } },
74 el(ColorPicker, { color:value, enableAlpha:true, onChange:onChange })
75 )
76 )
77 )
78 );
79 }
80
81 /* ── Section label pill ──────────────────────────────────────────── */
82 function SectionLabel(props) {
83 return el('span', { style: {
84 display:'inline-block', padding:'3px 12px', borderRadius:'999px',
85 background: props.bg || '#ede9fe', color: props.color || '#5b21b6',
86 fontSize:'11px', fontWeight:700, letterSpacing:'0.06em', textTransform:'uppercase', marginBottom:'10px',
87 } }, props.children);
88 }
89
90 /* ── Metric row ──────────────────────────────────────────────────── */
91 function MetricCard(props) {
92 var m = props.metric;
93 var a = props.a;
94 return el('div', { style: { background: a.metricBg||'#f5f3ff', borderRadius: a.cardRadius+'px', padding:'20px 18px', flex:'1 1 150px', minWidth:'130px', borderTop:'3px solid '+(m.color||a.accentColor||'#6c3fb5') } },
95 el('div', { style: { fontSize: a.metricValueSize+'px', fontWeight:900, color: m.color||a.accentColor||'#6c3fb5', lineHeight:1.1, marginBottom:'6px' } }, m.value),
96 el('div', { style: { fontSize: a.metricLabelSize+'px', fontWeight:700, color: a.labelColor||'#374151', marginBottom:'4px' } }, m.label),
97 m.description && el('div', { style: { fontSize:'12px', color: a.bodyColor||'#6b7280' } }, m.description)
98 );
99 }
100
101 /* ── Metric Inspector row ─────────────────────────────────────────── */
102 function MetricEditor(props) {
103 var m = props.metric;
104 var onChange = props.onChange;
105 var onRemove = props.onRemove;
106 var openKey = props.openKey;
107 var setOpenKey = props.setOpenKey;
108
109 function upd(key, val) { var c=Object.assign({},m); c[key]=val; onChange(c); }
110
111 return el('div', { style:{ background:'#f9f9f9', border:'1px solid #e0e0e0', borderRadius:'8px', padding:'10px 12px', marginBottom:'10px' } },
112 el(TextControl, { label:__('Display value (e.g. 94%)','blockenberg'), value:m.value, onChange:function(v){upd('value',v);} }),
113 el(TextControl, { label:__('Label','blockenberg'), value:m.label, onChange:function(v){upd('label',v);} }),
114 el(TextControl, { label:__('Description','blockenberg'), value:m.description||'', onChange:function(v){upd('description',v);} }),
115 el('div', { style:{ display:'flex', alignItems:'center', justifyContent:'space-between', marginTop:'4px' } },
116 renderColorControl('mc-'+m.id, __('Accent colour','blockenberg'), m.color, function(v){upd('color',v);}, openKey, setOpenKey),
117 el(Button, { variant:'tertiary', size:'compact', isDestructive:true, onClick:onRemove, style:{marginLeft:'8px'} }, '')
118 )
119 );
120 }
121
122 /* ── Register ────────────────────────────────────────────────────── */
123 registerBlockType('blockenberg/case-study', {
124 title: __('Case Study','blockenberg'),
125 icon: 'analytics',
126 category: 'bkbg-business',
127
128 edit: function(props) {
129 var a = props.attributes;
130 var setAttributes = props.setAttributes;
131
132 var openColorState = useState(null);
133 var openColorKey = openColorState[0];
134 var setOpenColorKey = openColorState[1];
135
136 var blockProps = useBlockProps({ style: buildWrapStyle(a) });
137
138 function cc(key, label, value, attrKey){
139 return renderColorControl(key, label, value, function(v){ var u={}; u[attrKey]=v; setAttributes(u); }, openColorKey, setOpenColorKey);
140 }
141
142 function updateMetric(id, upd) { setAttributes({ metrics: a.metrics.map(function(m){ return m.id===id ? upd : m; }) }); }
143 function removeMetric(id) { setAttributes({ metrics: a.metrics.filter(function(m){ return m.id!==id; }) }); }
144 function addMetric() { setAttributes({ metrics: a.metrics.concat([{ id:makeId(), value:'0', prefix:'', suffix:'', label:__('New metric','blockenberg'), description:'', color:'' }]) }); }
145
146 var twoCol = a.layout === 'two-col';
147
148 return el(Fragment, null,
149 el(InspectorControls, null,
150 el(PanelBody, { title:__('Client Info','blockenberg'), initialOpen:true },
151 el(TextControl, { label:__('Client name','blockenberg'), value:a.clientName, onChange:function(v){setAttributes({clientName:v});} }),
152 el(TextControl, { label:__('Industry / Category','blockenberg'), value:a.clientIndustry, onChange:function(v){setAttributes({clientIndustry:v});} }),
153 el(TextControl, { label:__('Website URL','blockenberg'), value:a.clientUrl||'', onChange:function(v){setAttributes({clientUrl:v});} }),
154 el(TextControl, { label:__('Tagline','blockenberg'), value:a.clientTagline||'', onChange:function(v){setAttributes({clientTagline:v});} }),
155 el('p', { style:{margin:'4px 0 8px',fontSize:'12px',color:'#555'} }, __('Client logo:','blockenberg')),
156 el(MediaUploadCheck, null,
157 el(MediaUpload, { onSelect:function(m){setAttributes({clientLogoUrl:m.url,clientLogoId:m.id});}, allowedTypes:['image'], value:a.clientLogoId,
158 render:function(mp){
159 return el(Fragment, null,
160 a.clientLogoUrl && el('img', { src:a.clientLogoUrl, style:{maxHeight:'48px', objectFit:'contain', display:'block', marginBottom:'6px' } }),
161 el(Button, { variant:'secondary', size:'compact', onClick:mp.open }, a.clientLogoUrl ? __('Change logo','blockenberg') : __('Upload logo','blockenberg')),
162 a.clientLogoUrl && el(Button, { variant:'tertiary', size:'compact', isDestructive:true, onClick:function(){setAttributes({clientLogoUrl:'',clientLogoId:0});}, style:{marginLeft:'6px'} }, __('Remove','blockenberg'))
163 );
164 }
165 })
166 )
167 ),
168 el(PanelBody, { title:__('Header','blockenberg'), initialOpen:false },
169 el(ToggleControl, { label:__('Show title','blockenberg'), checked:a.showTitle, onChange:function(v){setAttributes({showTitle:v});}, __nextHasNoMarginBottom:true }),
170 a.showTitle && el(TextControl, { label:__('Title','blockenberg'), value:a.title, onChange:function(v){setAttributes({title:v});} }),
171 el(ToggleControl, { label:__('Show subtitle','blockenberg'), checked:a.showSubtitle, onChange:function(v){setAttributes({showSubtitle:v});}, __nextHasNoMarginBottom:true }),
172 a.showSubtitle && el(TextControl, { label:__('Subtitle','blockenberg'), value:a.subtitle||'', onChange:function(v){setAttributes({subtitle:v});} })
173 ),
174 el(PanelBody, { title:__('Challenge & Solution labels','blockenberg'), initialOpen:false },
175 el(TextControl, { label:__('Challenge label','blockenberg'), value:a.challengeLabel||__('The Challenge','blockenberg'), onChange:function(v){setAttributes({challengeLabel:v});} }),
176 el(TextControl, { label:__('Solution label','blockenberg'), value:a.solutionLabel||__('The Solution','blockenberg'), onChange:function(v){setAttributes({solutionLabel:v});} })
177 ),
178 el(PanelBody, { title:__('Metrics','blockenberg'), initialOpen:false },
179 (a.metrics||[]).map(function(m){
180 return el(MetricEditor, { key:m.id, metric:m, onChange:function(upd){updateMetric(m.id,upd);}, onRemove:function(){removeMetric(m.id);}, openKey:openColorKey, setOpenKey:setOpenColorKey });
181 }),
182 el(Button, { variant:'primary', onClick:addMetric }, '+ ' + __('Add metric','blockenberg'))
183 ),
184 el(PanelBody, { title:__('Quote','blockenberg'), initialOpen:false },
185 el(ToggleControl, { label:__('Show quote','blockenberg'), checked:a.showQuote, onChange:function(v){setAttributes({showQuote:v});}, __nextHasNoMarginBottom:true }),
186 el(TextareaControl, { label:__('Quote text','blockenberg'), value:a.quote||'', onChange:function(v){setAttributes({quote:v});} }),
187 el(TextControl, { label:__('Author name','blockenberg'), value:a.quoteAuthor||'', onChange:function(v){setAttributes({quoteAuthor:v});} }),
188 el(TextControl, { label:__('Author role','blockenberg'), value:a.quoteAuthorRole||'', onChange:function(v){setAttributes({quoteAuthorRole:v});} }),
189 el('p', { style:{margin:'4px 0 8px',fontSize:'12px',color:'#555'} }, __('Avatar:','blockenberg')),
190 el(MediaUploadCheck, null,
191 el(MediaUpload, { onSelect:function(m){setAttributes({quoteAvatarUrl:m.url,quoteAvatarId:m.id});}, allowedTypes:['image'], value:a.quoteAvatarId,
192 render:function(mp){
193 return el(Fragment, null,
194 a.quoteAvatarUrl && el('img', { src:a.quoteAvatarUrl, style:{width:'48px',height:'48px',objectFit:'cover',borderRadius:'50%',display:'block',marginBottom:'6px'} }),
195 el(Button, { variant:'secondary', size:'compact', onClick:mp.open }, a.quoteAvatarUrl ? __('Change avatar','blockenberg') : __('Upload avatar','blockenberg')),
196 a.quoteAvatarUrl && el(Button, { variant:'tertiary', size:'compact', isDestructive:true, onClick:function(){setAttributes({quoteAvatarUrl:'',quoteAvatarId:0});}, style:{marginLeft:'6px'} }, __('Remove','blockenberg'))
197 );
198 }
199 })
200 )
201 ),
202 el(PanelBody, { title:__('Call to Action','blockenberg'), initialOpen:false },
203 el(ToggleControl, { label:__('Show CTA button','blockenberg'), checked:a.showCta, onChange:function(v){setAttributes({showCta:v});}, __nextHasNoMarginBottom:true }),
204 el(TextControl, { label:__('Button label','blockenberg'), value:a.ctaLabel||'', onChange:function(v){setAttributes({ctaLabel:v});} }),
205 el(TextControl, { label:__('Button URL','blockenberg'), value:a.ctaUrl||'', onChange:function(v){setAttributes({ctaUrl:v});} }),
206 el(ToggleControl, { label:__('Open in new tab','blockenberg'), checked:a.ctaNewTab, onChange:function(v){setAttributes({ctaNewTab:v});}, __nextHasNoMarginBottom:true })
207 ),
208 el(PanelBody, { title:__('Layout','blockenberg'), initialOpen:false },
209 el(SelectControl, { label:__('Layout','blockenberg'), value:a.layout, options:[{ label:__('Two columns (challenge / solution)','blockenberg'), value:'two-col' },{ label:__('Stacked','blockenberg'), value:'stack' }], onChange:function(v){setAttributes({layout:v});} })
210 ),
211 el(PanelBody, { title:__('Colours','blockenberg'), initialOpen:false },
212 cc('accentColor', __('Accent','blockenberg'), a.accentColor, 'accentColor'),
213 cc('titleColor', __('Title','blockenberg'), a.titleColor, 'titleColor'),
214 cc('subtitleColor', __('Subtitle','blockenberg'), a.subtitleColor, 'subtitleColor'),
215 cc('labelColor', __('Label / metric label','blockenberg'), a.labelColor, 'labelColor'),
216 cc('bodyColor', __('Body text','blockenberg'), a.bodyColor, 'bodyColor'),
217 cc('sectionLabelBg', __('Section label background','blockenberg'), a.sectionLabelBg, 'sectionLabelBg'),
218 cc('sectionLabelColor', __('Section label text','blockenberg'), a.sectionLabelColor, 'sectionLabelColor'),
219 cc('cardBg', __('Card background','blockenberg'), a.cardBg, 'cardBg'),
220 cc('metricBg', __('Metric card background','blockenberg'), a.metricBg, 'metricBg'),
221 cc('quoteBg', __('Quote background','blockenberg'), a.quoteBg, 'quoteBg'),
222 cc('quoteBorder', __('Quote border','blockenberg'), a.quoteBorder, 'quoteBorder'),
223 cc('quoteColor', __('Quote text','blockenberg'), a.quoteColor, 'quoteColor'),
224 cc('ctaBg', __('CTA background','blockenberg'), a.ctaBg, 'ctaBg'),
225 cc('ctaColor', __('CTA text','blockenberg'), a.ctaColor, 'ctaColor'),
226 cc('bgColor', __('Section background','blockenberg'), a.bgColor, 'bgColor')
227 ),
228 el(PanelBody, { title:__('Appearance','blockenberg'), initialOpen:false },
229 el(RangeControl, { label:__('Card radius (px)','blockenberg'), value:a.cardRadius, min:0, max:40, onChange:function(v){setAttributes({cardRadius:v});} }),
230 el(RangeControl, { label:__('CTA radius (px)','blockenberg'), value:a.ctaRadius, min:0, max:40, onChange:function(v){setAttributes({ctaRadius:v});} })
231 ),
232 el(PanelBody, { title:__('Spacing','blockenberg'), initialOpen:false },
233 el(RangeControl, { label:__('Padding top (px)','blockenberg'), value:a.paddingTop, min:0, max:200, onChange:function(v){setAttributes({paddingTop:v});} }),
234 el(RangeControl, { label:__('Padding bottom (px)','blockenberg'), value:a.paddingBottom, min:0, max:200, onChange:function(v){setAttributes({paddingBottom:v});} })
235 ),
236 el(PanelBody, { title: __('Typography', 'blockenberg'), initialOpen: false },
237 el(getTypographyControl(), { label: __('Title', 'blockenberg'), value: a.typoTitle, onChange: function (v) { setAttributes({ typoTitle: v }); } }),
238 el(getTypographyControl(), { label: __('Subtitle', 'blockenberg'), value: a.typoSubtitle, onChange: function (v) { setAttributes({ typoSubtitle: v }); } }),
239 el(getTypographyControl(), { label: __('Body Text', 'blockenberg'), value: a.typoBody, onChange: function (v) { setAttributes({ typoBody: v }); } }),
240 el(getTypographyControl(), { label: __('Quote Text', 'blockenberg'), value: a.typoQuote, onChange: function (v) { setAttributes({ typoQuote: v }); } }),
241 el(getTypographyControl(), { label: __('CTA Button', 'blockenberg'), value: a.typoCta, onChange: function (v) { setAttributes({ typoCta: v }); } }),
242 el(RangeControl, { label:__('Metric value size (px)','blockenberg'), value:a.metricValueSize, min:24, max:72, onChange:function(v){setAttributes({metricValueSize:v});} }),
243 el(RangeControl, { label:__('Metric label size (px)','blockenberg'), value:a.metricLabelSize, min:10, max:20, onChange:function(v){setAttributes({metricLabelSize:v});} })
244 )
245 ),
246
247 el('div', blockProps,
248 /* Header */
249 (a.showTitle || a.showSubtitle) && el('div', { style:{ textAlign:'center', marginBottom:'32px' } },
250 a.showTitle && el('h2', { className: 'bkbg-cs-title', style:{ margin:'0 0 8px' } }, a.title),
251 a.showSubtitle && el('p', { className: 'bkbg-cs-subtitle', style:{ margin:0 } }, a.subtitle)
252 ),
253
254 /* Client info */
255 el('div', { style:{ display:'flex', alignItems:'center', gap:'18px', background: a.cardBg||'#fff', borderRadius: a.cardRadius+'px', padding:'20px 24px', marginBottom:'28px', boxShadow:'0 1px 8px rgba(0,0,0,0.06)' } },
256 a.clientLogoUrl && el('img', { src:a.clientLogoUrl, style:{ maxHeight:'60px', objectFit:'contain', flexShrink:0 } }),
257 el('div', null,
258 el('div', { style:{ fontWeight:800, fontSize:'20px', color: a.titleColor||'#1e1b4b' } }, a.clientName),
259 el('div', { style:{ fontSize:'13px', color: a.accentColor||'#6c3fb5', fontWeight:600 } }, a.clientIndustry),
260 a.clientTagline && el('div', { style:{ fontSize:'13px', color: a.bodyColor||'#6b7280', marginTop:'2px' } }, a.clientTagline)
261 )
262 ),
263
264 /* Challenge / Solution */
265 el('div', { style:{ display:'grid', gridTemplateColumns: twoCol ? '1fr 1fr' : '1fr', gap:'24px', marginBottom:'28px' } },
266 el('div', { style:{ background: a.cardBg||'#faf9ff', borderRadius: a.cardRadius+'px', padding:'24px' } },
267 el(SectionLabel, { bg: a.sectionLabelBg, color: a.sectionLabelColor }, a.challengeLabel || __('The Challenge','blockenberg')),
268 el(RichText, { tagName:'div', className:'bkbg-cs-rt', value:a.challenge, onChange:function(v){setAttributes({challenge:v});}, placeholder:__('Describe the problem this client faced…','blockenberg') })
269 ),
270 el('div', { style:{ background: a.cardBg||'#faf9ff', borderRadius: a.cardRadius+'px', padding:'24px' } },
271 el(SectionLabel, { bg: a.sectionLabelBg, color: a.sectionLabelColor }, a.solutionLabel || __('The Solution','blockenberg')),
272 el(RichText, { tagName:'div', className:'bkbg-cs-rt', value:a.solution, onChange:function(v){setAttributes({solution:v});}, placeholder:__('Describe how you solved it…','blockenberg') })
273 )
274 ),
275
276 /* Metrics */
277 (a.metrics||[]).length > 0 && el('div', { style:{ display:'flex', flexWrap:'wrap', gap:'16px', marginBottom:'28px' } },
278 (a.metrics||[]).map(function(m){ return el(MetricCard, { key:m.id, metric:m, a:a }); })
279 ),
280
281 /* Quote */
282 a.showQuote && a.quote && el('blockquote', { style:{ margin:'0 0 28px', padding:'24px 28px', background: a.quoteBg||'#f5f3ff', borderLeft:'4px solid '+(a.quoteBorder||'#6c3fb5'), borderRadius: a.cardRadius+'px', color: a.quoteColor||'#1e1b4b' } },
283 el('p', { style:{ fontSize:'18px', fontStyle:'italic', lineHeight:1.6, margin:'0 0 14px' } }, '\u201C' + a.quote + '\u201D'),
284 el('div', { style:{ display:'flex', alignItems:'center', gap:'12px' } },
285 a.quoteAvatarUrl && el('img', { src:a.quoteAvatarUrl, style:{ width:'40px', height:'40px', borderRadius:'50%', objectFit:'cover' } }),
286 el('div', null,
287 el('div', { style:{ fontWeight:700, fontSize:'14px' } }, a.quoteAuthor),
288 el('div', { style:{ fontSize:'12px', opacity:0.7 } }, a.quoteAuthorRole)
289 )
290 )
291 ),
292
293 /* CTA */
294 a.showCta && a.ctaLabel && el('div', { style:{ textAlign:'center' } },
295 el('a', { href: a.ctaUrl||'#', style:{ display:'inline-block', padding:'14px 32px', background: a.ctaBg||'#6c3fb5', color: a.ctaColor||'#fff', borderRadius: a.ctaRadius+'px', fontWeight:700, fontSize:'16px', textDecoration:'none' } }, a.ctaLabel)
296 )
297 )
298 );
299 },
300
301 save: function(props) {
302 var a = props.attributes;
303 var twoCol = a.layout === 'two-col';
304 return el('div', wp.blockEditor.useBlockProps.save({
305 className: 'bkbg-cs-wrapper bkbg-cs-layout-' + a.layout,
306 style: buildWrapStyle(a),
307 }),
308 (a.showTitle || a.showSubtitle) && el('div', { className:'bkbg-cs-header' },
309 a.showTitle && el('h2', { className:'bkbg-cs-title' }, a.title),
310 a.showSubtitle && el('p', { className:'bkbg-cs-subtitle' }, a.subtitle)
311 ),
312 el('div', { className:'bkbg-cs-client-bar' },
313 a.clientLogoUrl && el('img', { className:'bkbg-cs-logo', src:a.clientLogoUrl, alt:a.clientName, loading:'lazy' }),
314 el('div', { className:'bkbg-cs-client-info' },
315 el('div', { className:'bkbg-cs-client-name' }, a.clientName),
316 el('div', { className:'bkbg-cs-client-industry' }, a.clientIndustry),
317 a.clientTagline && el('div', { className:'bkbg-cs-client-tagline' }, a.clientTagline)
318 )
319 ),
320 el('div', { className: 'bkbg-cs-content-grid' + (twoCol ? ' bkbg-cs-two-col' : '') },
321 el('div', { className:'bkbg-cs-card bkbg-cs-challenge' },
322 el('span', { className:'bkbg-cs-section-label' }, a.challengeLabel || 'The Challenge'),
323 el(RichText.Content, { tagName:'div', className:'bkbg-cs-rt', value:a.challenge })
324 ),
325 el('div', { className:'bkbg-cs-card bkbg-cs-solution' },
326 el('span', { className:'bkbg-cs-section-label' }, a.solutionLabel || 'The Solution'),
327 el(RichText.Content, { tagName:'div', className:'bkbg-cs-rt', value:a.solution })
328 )
329 ),
330 (a.metrics||[]).length > 0 && el('div', { className:'bkbg-cs-metrics' },
331 (a.metrics||[]).map(function(m){
332 return el('div', { key:m.id, className:'bkbg-cs-metric', style:{ borderTopColor: m.color||a.accentColor||'' } },
333 el('div', { className:'bkbg-cs-metric-value' }, m.value),
334 el('div', { className:'bkbg-cs-metric-label' }, m.label),
335 m.description && el('div', { className:'bkbg-cs-metric-desc' }, m.description)
336 );
337 })
338 ),
339 a.showQuote && a.quote && el('blockquote', { className:'bkbg-cs-quote' },
340 el('p', { className:'bkbg-cs-quote-text' }, '\u201C' + a.quote + '\u201D'),
341 el('div', { className:'bkbg-cs-quote-author' },
342 a.quoteAvatarUrl && el('img', { className:'bkbg-cs-avatar', src:a.quoteAvatarUrl, alt:a.quoteAuthor, loading:'lazy' }),
343 el('div', null,
344 el('div', { className:'bkbg-cs-author-name' }, a.quoteAuthor),
345 el('div', { className:'bkbg-cs-author-role' }, a.quoteAuthorRole)
346 )
347 )
348 ),
349 a.showCta && a.ctaLabel && el('div', { className:'bkbg-cs-cta-row' },
350 el('a', { className:'bkbg-cs-cta', href:a.ctaUrl||'#', target: a.ctaNewTab ? '_blank' : undefined, rel: a.ctaNewTab ? 'noopener noreferrer' : undefined }, a.ctaLabel)
351 )
352 );
353 }
354 });
355 }() );
356