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

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

252 lines 18.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /* ====================================================
2 Use Case Section — editor (index.js)
3 Block: blockenberg/use-case-section
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 ColorPicker = wp.components.ColorPicker;
21 var Popover = wp.components.Popover;
22 var __ = wp.i18n.__;
23
24 var _tc, _tvf;
25 Object.defineProperty(window, '_tc', { get: function () { return _tc || (_tc = window.bkbgTypographyControl); } });
26 Object.defineProperty(window, '_tvf', { get: function () { return _tvf || (_tvf = window.bkbgTypoCssVars); } });
27 function getTypoControl(label, key, attrs, setA) { return _tc(label, key, attrs, setA); }
28 function getTypoCssVars(attrs) {
29 var v = {};
30 _tvf(v, 'titleTypo', attrs, '--bkusec-tt-');
31 _tvf(v, 'descTypo', attrs, '--bkusec-ds-');
32 return v;
33 }
34 var IP = function () { return window.bkbgIconPicker; };
35
36 function uid() { return Math.random().toString(36).slice(2,9); }
37
38 function wrapStyle(a) {
39 var s = {
40 '--bkbg-usec-pt': a.paddingTop + 'px',
41 '--bkbg-usec-pb': a.paddingBottom + 'px',
42 '--bkbg-usec-sec-bg': a.sectionBg,
43 '--bkbg-usec-card-bg':a.cardBg,
44 '--bkbg-usec-card-bd':a.cardBorder,
45 '--bkbg-usec-title-c':a.titleColor,
46 '--bkbg-usec-desc-c': a.descColor,
47 '--bkbg-usec-feat-c': a.featureColor,
48 '--bkbg-usec-chk-c': a.checkColor,
49 '--bkbg-usec-ey-bg': a.eyebrowBg,
50 '--bkbg-usec-ey-c': a.eyebrowColor,
51 '--bkbg-usec-sec-ttl':a.sectionTitleColor,
52 '--bkbg-usec-sec-sub':a.sectionSubColor,
53 '--bkbg-usec-icon-sz':a.iconSize + 'px',
54 '--bkbg-usec-r': a.cardRadius + 'px',
55 '--bkbg-usec-p': a.cardPadding + 'px',
56 '--bkbg-usec-gap': a.gap + 'px',
57 '--bkbg-usec-cols': a.columns,
58 '--bkbg-usec-header-gap': a.headerGap + 'px',
59 };
60 var _tv = getTypoCssVars(a);
61 Object.assign(s, _tv);
62 return s;
63 }
64
65 /* ----- Inspector: one expandable case row ----- */
66 function CaseRow(props) {
67 var c = props.caseItem;
68 var idx = props.index;
69 var total = props.total;
70 var onUpdate = props.onUpdate;
71 var onDelete = props.onDelete;
72 var onMove = props.onMove;
73 var open = useState(idx === 0);
74 var isOpen = open[0]; var setOpen = open[1];
75
76 return el('div', { className:'bkbg-inspector-row', style:{ borderBottom:'1px solid #e2e8f0', marginBottom:4 } },
77 el('div', { style:{ display:'flex', alignItems:'center', cursor:'pointer', padding:'6px 0' }, onClick:function(){ setOpen(!isOpen); } },
78 el('span', { style:{ flex:1, fontWeight:600, fontSize:12 } }, '#'+(idx+1)+' '+((c.iconType || 'custom-char') === 'custom-char' ? c.icon : '')+' '+(c.title||'Case')),
79 el('span', null, isOpen ? '' : '')
80 ),
81 !isOpen ? null : el('div', { style:{ paddingBottom:8 } },
82 el(IP().IconPickerControl, IP().iconPickerProps(c, function(patch) { onUpdate(idx, patch); }, { label:__('Icon (emoji or symbol)','blockenberg'), charAttr:'icon', typeAttr:'iconType', dashiconAttr:'iconDashicon', imageUrlAttr:'iconImageUrl' })),
83 el(TextControl, { label:__('Title','blockenberg'), value:c.title, onChange:function(v){ onUpdate(idx,{title:v}); } }),
84 el(TextControl, { label:__('Description','blockenberg'), value:c.description, onChange:function(v){ onUpdate(idx,{description:v}); }, __nextHasNoMarginBottom:false }),
85 el(BkbgColorSwatch, { label:__('Accent color','blockenberg'), value:c.accentColor, onChange:function(v){ onUpdate(idx,{accentColor:v}); } }),
86 el('p', { style:{ fontWeight:600, fontSize:11, margin:'8px 0 4px' } }, __('Features','blockenberg')),
87 c.features.map(function(f, fi) {
88 return el('div', { key:f.id, style:{ display:'flex', gap:4, marginBottom:4 } },
89 el(TextControl, { value:f.text, onChange:function(v){ var feats=[].concat(c.features); feats[fi]=Object.assign({},f,{text:v}); onUpdate(idx,{features:feats}); }, placeholder:'Feature…' }),
90 el(Button, { isSmall:true, isDestructive:true, onClick:function(){ var feats=c.features.filter(function(_,i){ return i!==fi; }); onUpdate(idx,{features:feats}); } }, '')
91 );
92 }),
93 el(Button, { isSmall:true, variant:'tertiary', onClick:function(){ onUpdate(idx,{features:c.features.concat([{id:uid(),text:''}])}); } }, __('+ Feature','blockenberg')),
94 el(TextControl, { label:__('CTA label','blockenberg'), value:c.ctaLabel, onChange:function(v){ onUpdate(idx,{ctaLabel:v}); } }),
95 el(TextControl, { label:__('CTA URL','blockenberg'), value:c.ctaUrl, onChange:function(v){ onUpdate(idx,{ctaUrl:v}); } }),
96 el('div', { style:{ display:'flex', gap:4, marginTop:8 } },
97 el(Button, { isSmall:true, variant:'secondary', disabled:idx===0, onClick:function(){ onMove(idx,idx-1); } }, ''),
98 el(Button, { isSmall:true, variant:'secondary', disabled:idx===total-1, onClick:function(){ onMove(idx,idx+1); } }, ''),
99 el(Button, { isSmall:true, isDestructive:true, onClick:function(){ onDelete(idx); } }, __('Delete','blockenberg'))
100 )
101 )
102 );
103 }
104
105 var BkbgColorSwatch = function (props) {
106 var _st = useState(false); var isOpen = _st[0]; var setOpen = _st[1];
107 return el(Fragment, {},
108 el('div', { style: { display: 'flex', alignItems: 'center', gap: '8px', marginBottom: '8px' } },
109 el('span', { style: { fontSize: '11px', fontWeight: 500, textTransform: 'uppercase', color: '#1e1e1e' } }, props.label),
110 el('button', {
111 type: 'button',
112 onClick: function () { setOpen(!isOpen); },
113 style: { width: '28px', height: '28px', borderRadius: '4px', border: '1px solid #ccc', background: props.value || '#ffffff', cursor: 'pointer', padding: 0 }
114 })
115 ),
116 isOpen && el(Popover, { onClose: function () { setOpen(false); } },
117 el('div', { style: { padding: '8px' } },
118 el(ColorPicker, { color: props.value, onChangeComplete: function (c) { props.onChange(c.hex); }, enableAlpha: true })
119 )
120 )
121 );
122 };
123
124 registerBlockType('blockenberg/use-case-section', {
125 edit: function (props) {
126 var a = props.attributes;
127 var setAttr = props.setAttributes;
128
129 function updateCase(idx, patch) {
130 var arr = a.cases.map(function(c,i){ return i===idx ? Object.assign({},c,patch) : c; });
131 setAttr({ cases: arr });
132 }
133 function deleteCase(idx) { setAttr({ cases: a.cases.filter(function(_,i){ return i!==idx; }) }); }
134 function moveCase(from, to) {
135 var arr = a.cases.slice();
136 arr.splice(to, 0, arr.splice(from, 1)[0]);
137 setAttr({ cases: arr });
138 }
139 function addCase() {
140 setAttr({ cases: a.cases.concat([{ id:uid(), icon:'', iconType:'custom-char', iconDashicon:'', iconImageUrl:'', title:'New Use Case', description:'Describe who benefits from this.', features:[{id:uid(),text:'Key feature'}], ctaLabel:'Learn more', ctaUrl:'#', accentColor:'#6c3fb5' }]) });
141 }
142
143 var blockProps = useBlockProps({ className:'bkbg-usec-wrap', style:wrapStyle(a) });
144
145 var inspector = el(InspectorControls, null,
146 el(PanelBody, { title:__('Cases','blockenberg'), initialOpen:true },
147 a.cases.map(function(c,i){ return el(CaseRow, { key:c.id, caseItem:c, index:i, total:a.cases.length, onUpdate:updateCase, onDelete:deleteCase, onMove:moveCase }); }),
148 el(Button, { variant:'primary', onClick:addCase, style:{marginTop:8} }, __('+ Add case','blockenberg'))
149 ),
150 el(PanelBody, { title:__('Display','blockenberg'), initialOpen:false },
151 el(SelectControl, { label:__('Display style','blockenberg'), value:a.displayStyle, options:[{label:'Cards',value:'cards'},{label:'Tabs',value:'tabs'}], onChange:function(v){ setAttr({displayStyle:v}); } }),
152 el(RangeControl, { label:__('Columns','blockenberg'), value:a.columns, min:1, max:4, onChange:function(v){ setAttr({columns:v}); } }),
153 el(RangeControl, { label:__('Gap (px)','blockenberg'), value:a.gap, min:0, max:64, onChange:function(v){ setAttr({gap:v}); } }),
154 el(RangeControl, { label:__('Card radius (px)','blockenberg'), value:a.cardRadius, min:0, max:32, onChange:function(v){ setAttr({cardRadius:v}); } }),
155 el(RangeControl, { label:__('Card padding (px)','blockenberg'), value:a.cardPadding, min:0, max:64, onChange:function(v){ setAttr({cardPadding:v}); } }),
156 el(RangeControl, { label:__('Icon size (px)','blockenberg'), value:a.iconSize, min:16, max:72, onChange:function(v){ setAttr({iconSize:v}); } }),
157 el(ToggleControl, { label:__('Show features','blockenberg'), checked:a.showFeatures, onChange:function(v){ setAttr({showFeatures:v}); } }),
158 el(ToggleControl, { label:__('Show CTA links','blockenberg'), checked:a.showCta, onChange:function(v){ setAttr({showCta:v}); } })
159 ),
160 el(PanelBody, { title:__('Section header','blockenberg'), initialOpen:false },
161 el(ToggleControl, { label:__('Show header','blockenberg'), checked:a.showHeader, onChange:function(v){ setAttr({showHeader:v}); } }),
162 el(ToggleControl, { label:__('Show eyebrow','blockenberg'), checked:a.showEyebrow, onChange:function(v){ setAttr({showEyebrow:v}); } }),
163 el(TextControl, { label:__('Eyebrow text','blockenberg'), value:a.eyebrow, onChange:function(v){ setAttr({eyebrow:v}); } }),
164 el(SelectControl, { label:__('Header align','blockenberg'), value:a.headerAlign, options:[{label:'Center',value:'center'},{label:'Left',value:'left'}], onChange:function(v){ setAttr({headerAlign:v}); } }),
165 el(RangeControl, { label:__('Header gap (px)','blockenberg'), value:a.headerGap, min:8, max:96, onChange:function(v){ setAttr({headerGap:v}); } })
166 ),
167 el(PanelBody, { title:__('Typography','blockenberg'), initialOpen:false },
168 getTypoControl(__('Card Title', 'blockenberg'), 'titleTypo', a, setAttr),
169 getTypoControl(__('Card Description', 'blockenberg'), 'descTypo', a, setAttr)
170 ),
171 el(PanelBody, { title:__('Spacing','blockenberg'), initialOpen:false },
172 el(RangeControl, { label:__('Padding top (px)','blockenberg'), value:a.paddingTop, min:0, max:200, onChange:function(v){ setAttr({paddingTop:v}); } }),
173 el(RangeControl, { label:__('Padding bottom (px)','blockenberg'), value:a.paddingBottom, min:0, max:200, onChange:function(v){ setAttr({paddingBottom:v}); } })
174 ),
175 el(PanelColorSettings, { title:__('Colors','blockenberg'), initialOpen:false, colorSettings:[
176 {label:__('Section bg','blockenberg'), value:a.sectionBg, onChange:function(v){ setAttr({sectionBg:v||''}); }},
177 {label:__('Card bg','blockenberg'), value:a.cardBg, onChange:function(v){ setAttr({cardBg:v||''}); }},
178 {label:__('Card border','blockenberg'), value:a.cardBorder, onChange:function(v){ setAttr({cardBorder:v||''}); }},
179 {label:__('Title','blockenberg'), value:a.titleColor, onChange:function(v){ setAttr({titleColor:v||''}); }},
180 {label:__('Description','blockenberg'), value:a.descColor, onChange:function(v){ setAttr({descColor:v||''}); }},
181 {label:__('Feature text','blockenberg'), value:a.featureColor, onChange:function(v){ setAttr({featureColor:v||''}); }},
182 {label:__('Check icon','blockenberg'), value:a.checkColor, onChange:function(v){ setAttr({checkColor:v||''}); }},
183 {label:__('Eyebrow bg','blockenberg'), value:a.eyebrowBg, onChange:function(v){ setAttr({eyebrowBg:v||''}); }},
184 {label:__('Eyebrow text','blockenberg'), value:a.eyebrowColor, onChange:function(v){ setAttr({eyebrowColor:v||''}); }},
185 {label:__('Section title','blockenberg'), value:a.sectionTitleColor,onChange:function(v){ setAttr({sectionTitleColor:v||''}); }},
186 {label:__('Section subtitle','blockenberg'), value:a.sectionSubColor, onChange:function(v){ setAttr({sectionSubColor:v||''}); }},
187 ] })
188 );
189
190 /* render a single card in the editor canvas */
191 function renderCard(c) {
192 var _iType = c.iconType || 'custom-char';
193 var _iconContent = (_iType !== 'custom-char' && IP()) ? IP().buildEditorIcon(_iType, c.icon, c.iconDashicon, c.iconImageUrl, c.iconDashiconColor) : c.icon;
194 return el('div', { key:c.id, className:'bkbg-usec-card', style:{'--bkbg-usec-accent': c.accentColor} },
195 el('div', { className:'bkbg-usec-icon-wrap' }, el('span', { className:'bkbg-usec-icon' }, _iconContent)),
196 el('div', { className:'bkbg-usec-title' }, c.title),
197 el('div', { className:'bkbg-usec-desc' }, c.description),
198 a.showFeatures && c.features.length ? el('ul', { className:'bkbg-usec-features' },
199 c.features.map(function(f){ return el('li', { key:f.id }, el('span', { className:'bkbg-usec-check' }, ''), f.text); })
200 ) : null,
201 a.showCta ? el('span', { className:'bkbg-usec-cta' }, c.ctaLabel, el('span', { className:'bkbg-usec-cta-arrow' }, '')) : null
202 );
203 }
204
205 return el(Fragment, null,
206 inspector,
207 el('div', blockProps,
208 a.showHeader ? el('div', { className:'bkbg-usec-header bkbg-usec-header--' + a.headerAlign },
209 a.showEyebrow ? el('span', { className:'bkbg-usec-eyebrow' }, a.eyebrow) : null,
210 el(RichText, { tagName:'h2', className:'bkbg-usec-section-title', value:a.sectionTitle, onChange:function(v){ setAttr({sectionTitle:v}); }, placeholder:__('Section title…','blockenberg') }),
211 el(RichText, { tagName:'p', className:'bkbg-usec-section-sub', value:a.sectionSubtitle, onChange:function(v){ setAttr({sectionSubtitle:v}); }, placeholder:__('Section subtitle…','blockenberg') })
212 ) : null,
213 el('div', { className:'bkbg-usec-grid' },
214 a.cases.map(renderCard)
215 )
216 )
217 );
218 },
219
220 save: function (props) {
221 var a = props.attributes;
222 var blockProps = wp.blockEditor.useBlockProps.save({
223 className: 'bkbg-usec-wrap',
224 style: wrapStyle(a),
225 'data-display-style': a.displayStyle
226 });
227 return el('div', blockProps,
228 a.showHeader ? el('div', { className:'bkbg-usec-header bkbg-usec-header--' + a.headerAlign },
229 a.showEyebrow ? el('span', { className:'bkbg-usec-eyebrow' }, a.eyebrow) : null,
230 el(RichText.Content, { tagName:'h2', className:'bkbg-usec-section-title', value:a.sectionTitle }),
231 el(RichText.Content, { tagName:'p', className:'bkbg-usec-section-sub', value:a.sectionSubtitle })
232 ) : null,
233 el('div', { className:'bkbg-usec-grid' + (a.displayStyle === 'tabs' ? ' bkbg-usec-grid--tabs' : '') },
234 a.cases.map(function(c) {
235 var _iType = c.iconType || 'custom-char';
236 var _iconContent = (_iType !== 'custom-char' && IP()) ? IP().buildSaveIcon(_iType, c.icon, c.iconDashicon, c.iconImageUrl, c.iconDashiconColor) : c.icon;
237 return el('div', { key:c.id, className:'bkbg-usec-card', style:{'--bkbg-usec-accent': c.accentColor}, 'data-tab-label': c.title },
238 el('div', { className:'bkbg-usec-icon-wrap' }, el('span', { className:'bkbg-usec-icon' }, _iconContent)),
239 el('div', { className:'bkbg-usec-title' }, c.title),
240 el('div', { className:'bkbg-usec-desc' }, c.description),
241 a.showFeatures && c.features.length ? el('ul', { className:'bkbg-usec-features' },
242 c.features.map(function(f){ return el('li', { key:f.id }, el('span', { className:'bkbg-usec-check' }, ''), f.text); })
243 ) : null,
244 a.showCta ? el('a', { href:c.ctaUrl, className:'bkbg-usec-cta' }, c.ctaLabel, el('span', { className:'bkbg-usec-cta-arrow' }, '')) : null
245 );
246 })
247 )
248 );
249 }
250 });
251 }() );
252