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 / feature-split / index.js

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

252 lines 18.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /* ====================================================
2 Feature Split Block — editor (index.js)
3 Block: blockenberg/feature-split
4 ==================================================== */
5 ( function () {
6 var el = wp.element.createElement;
7 var Fragment = wp.element.Fragment;
8 var useState = wp.element.useState;
9 var RichText = wp.blockEditor.RichText;
10 var MediaUpload = wp.blockEditor.MediaUpload;
11 var MediaUploadCheck = wp.blockEditor.MediaUploadCheck;
12 var registerBlockType = wp.blocks.registerBlockType;
13 var InspectorControls = wp.blockEditor.InspectorControls;
14 var useBlockProps = wp.blockEditor.useBlockProps;
15 var PanelBody = wp.components.PanelBody;
16 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
17 var RangeControl = wp.components.RangeControl;
18 var SelectControl = wp.components.SelectControl;
19 var ToggleControl = wp.components.ToggleControl;
20 var TextControl = wp.components.TextControl;
21 var Button = wp.components.Button;
22 var __ = wp.i18n.__;
23 var _fspTC, _fspTV;
24 function _tc() { return (_fspTC = _fspTC || window.bkbgTypographyControl); }
25 function _tv() { return (_fspTV = _fspTV || window.bkbgTypoCssVars); }
26 var IP = function () { return window.bkbgIconPicker; };
27
28 function uid() { return 'f' + Math.random().toString(36).slice(2,7); }
29 function move(arr, from, to) { var a=arr.slice(); a.splice(to,0,a.splice(from,1)[0]); return a; }
30
31 function buildWrapStyle(a) {
32 return Object.assign({
33 '--bkbg-fsp-gap': a.gap + 'px',
34 '--bkbg-fsp-img-w': a.imageWidth + '%',
35 '--bkbg-fsp-img-radius': a.imageRadius + 'px',
36 '--bkbg-fsp-btn-radius': a.btnRadius + 'px',
37 '--bkbg-fsp-pt': a.paddingTop + 'px',
38 '--bkbg-fsp-pb': a.paddingBottom + 'px',
39 '--bkbg-fsp-content-max':a.contentMaxWidth + 'px',
40 '--bkbg-fsp-eyebrow-bg': a.eyebrowBg,
41 '--bkbg-fsp-eyebrow-clr':a.eyebrowColor,
42 '--bkbg-fsp-h-color': a.headlineColor,
43 '--bkbg-fsp-body-color': a.bodyColor,
44 '--bkbg-fsp-feat-color': a.featureColor,
45 '--bkbg-fsp-prim-bg': a.primaryBtnBg,
46 '--bkbg-fsp-prim-color': a.primaryBtnColor,
47 '--bkbg-fsp-sec-color': a.secBtnColor,
48 '--bkbg-fsp-accent': a.accentColor,
49 background: a.sectionBg || undefined,
50 },
51 _tv()(a.typoEyebrow, '--bkbg-fsp-eb-'),
52 _tv()(a.typoHeadline, '--bkbg-fsp-hl-'),
53 _tv()(a.typoBody, '--bkbg-fsp-bd-'),
54 _tv()(a.typoFeature, '--bkbg-fsp-ft-')
55 );
56 }
57
58 /* ── REGISTER ── */
59 registerBlockType('blockenberg/feature-split', {
60 edit: function (props) {
61 var a = props.attributes;
62 var setAttr = props.setAttributes;
63 var features= a.features;
64
65 var wrapCls = 'bkbg-fsp-wrap bkbg-fsp-style--' + a.style
66 + (a.imagePosition === 'left' ? ' bkbg-fsp-img-left' : ' bkbg-fsp-img-right');
67 var blockProps = useBlockProps({ className: wrapCls, style: buildWrapStyle(a) });
68
69 function updateFeature(id, text) {
70 setAttr({ features: features.map(function(f){ return f.id===id ? Object.assign({},f,{text:text}) : f; }) });
71 }
72 function updateFeatureIcon(id, icon) {
73 setAttr({ features: features.map(function(f){ return f.id===id ? Object.assign({},f,{icon:icon}) : f; }) });
74 }
75
76 var inspector = el(InspectorControls, null,
77 /* Style */
78 el(PanelBody, { title:__('Style & Layout','blockenberg'), initialOpen:true },
79 el(SelectControl, { label:__('Visual style','blockenberg'), value:a.style, options:[
80 {label:__('Clean (white)','blockenberg'), value:'clean'},
81 {label:__('Dark','blockenberg'), value:'dark'},
82 {label:__('Soft gradient','blockenberg'), value:'gradient'},
83 {label:__('Accent bg','blockenberg'), value:'accent'},
84 ], onChange:function(v){ setAttr({style:v}); } }),
85 el(SelectControl, { label:__('Image position','blockenberg'), value:a.imagePosition, options:[
86 {label:__('Right','blockenberg'), value:'right'},
87 {label:__('Left','blockenberg'), value:'left'},
88 ], onChange:function(v){ setAttr({imagePosition:v}); } }),
89 el(SelectControl, { label:__('Vertical alignment','blockenberg'), value:a.verticalAlign, options:[
90 {label:'Center', value:'center'},{label:'Top', value:'flex-start'},{label:'Bottom', value:'flex-end'}
91 ], onChange:function(v){ setAttr({verticalAlign:v}); } }),
92 el(RangeControl, { label:__('Column gap (px)','blockenberg'), value:a.gap, min:0, max:120, onChange:function(v){ setAttr({gap:v}); } }),
93 el(RangeControl, { label:__('Image width %','blockenberg'), value:a.imageWidth, min:30, max:70, onChange:function(v){ setAttr({imageWidth:v}); } }),
94 el(RangeControl, { label:__('Image border radius (px)','blockenberg'), value:a.imageRadius, min:0, max:40, onChange:function(v){ setAttr({imageRadius:v}); } }),
95 el(ToggleControl, { label:__('Image shadow','blockenberg'), checked:a.imageShadow, onChange:function(v){ setAttr({imageShadow:v}); } })
96 ),
97
98 /* Content */
99 el(PanelBody, { title:__('Content','blockenberg'), initialOpen:false },
100 el(ToggleControl, { label:__('Show eyebrow badge','blockenberg'), checked:a.showEyebrow, onChange:function(v){ setAttr({showEyebrow:v}); } }),
101 el(ToggleControl, { label:__('Show body text','blockenberg'), checked:a.showBody, onChange:function(v){ setAttr({showBody:v}); } }),
102 el(ToggleControl, { label:__('Show feature list','blockenberg'), checked:a.showFeatures,onChange:function(v){ setAttr({showFeatures:v}); } }),
103 el(ToggleControl, { label:__('Show primary button','blockenberg'), checked:a.showPrimaryBtn, onChange:function(v){ setAttr({showPrimaryBtn:v}); } }),
104 el(ToggleControl, { label:__('Show secondary button','blockenberg'), checked:a.showSecondaryBtn, onChange:function(v){ setAttr({showSecondaryBtn:v}); } }),
105 a.showEyebrow ? el(TextControl, { label:__('Eyebrow text','blockenberg'), value:a.eyebrow, onChange:function(v){ setAttr({eyebrow:v}); } }) : null,
106 a.showPrimaryBtn ? el(Fragment, null,
107 el(TextControl, { label:__('Primary button label','blockenberg'), value:a.primaryBtnLabel, onChange:function(v){ setAttr({primaryBtnLabel:v}); } }),
108 el(TextControl, { label:__('Primary button URL','blockenberg'), value:a.primaryBtnUrl, onChange:function(v){ setAttr({primaryBtnUrl:v}); } }),
109 el(ToggleControl, { label:__('Open in new tab','blockenberg'), checked:a.primaryBtnTarget, onChange:function(v){ setAttr({primaryBtnTarget:v}); } })
110 ) : null,
111 a.showSecondaryBtn ? el(Fragment, null,
112 el(TextControl, { label:__('Secondary button label','blockenberg'), value:a.secondaryBtnLabel, onChange:function(v){ setAttr({secondaryBtnLabel:v}); } }),
113 el(TextControl, { label:__('Secondary button URL','blockenberg'), value:a.secondaryBtnUrl, onChange:function(v){ setAttr({secondaryBtnUrl:v}); } })
114 ) : null,
115 el(RangeControl, { label:__('Content max width (px)','blockenberg'), value:a.contentMaxWidth, min:300, max:800, onChange:function(v){ setAttr({contentMaxWidth:v}); } })
116 ),
117
118 /* Feature list */
119 a.showFeatures ? el(PanelBody, { title:__('Feature items','blockenberg'), initialOpen:false },
120 features.map(function(f, idx) {
121 return el('div', { key:f.id, style:{ display:'flex', gap:'4px', marginBottom:'6px', alignItems:'center' } },
122 el('div', { style:{ flexShrink:0 } },
123 el(IP().IconPickerControl, {
124 iconType: f.iconType, customChar: f.icon, dashicon: f.iconDashicon, imageUrl: f.iconImageUrl,
125 onChangeType: function(v){ setAttr({features:features.map(function(x){ return x.id===f.id ? Object.assign({},x,{iconType:v}) : x; })}); },
126 onChangeChar: function(v){ updateFeatureIcon(f.id,v); },
127 onChangeDashicon: function(v){ setAttr({features:features.map(function(x){ return x.id===f.id ? Object.assign({},x,{iconDashicon:v}) : x; })}); },
128 onChangeImageUrl: function(v){ setAttr({features:features.map(function(x){ return x.id===f.id ? Object.assign({},x,{iconImageUrl:v}) : x; })}); }
129 })
130 ),
131 el(TextControl, { label: idx===0 ? __('Text','blockenberg') : undefined, value:f.text, onChange:function(v){ updateFeature(f.id,v); }, style:{ flex:1 } }),
132 el(Button, { icon:'arrow-up', isSmall:true, disabled:idx===0, onClick:function(){ setAttr({features:move(features,idx,idx-1)}); } }),
133 el(Button, { icon:'no-alt', isSmall:true, isDestructive:true, onClick:function(){ setAttr({features:features.filter(function(_,i){ return i!==idx; })}); } })
134 );
135 }),
136 el(Button, { variant:'secondary', isSmall:true, style:{width:'100%',marginTop:'4px'},
137 onClick:function(){ setAttr({ features: features.concat([{id:uid(),icon:'�
138 ',text:'New feature',iconType:'custom-char',iconDashicon:'',iconImageUrl:''}]) }); }
139 }, __('+ Add feature','blockenberg'))
140 ) : null,
141
142 /* Spacing */
143 el(PanelBody, { title:__('Spacing','blockenberg'), initialOpen:false },
144 el(RangeControl, { label:__('Padding top (px)','blockenberg'), value:a.paddingTop, min:0, max:160, onChange:function(v){ setAttr({paddingTop:v}); } }),
145 el(RangeControl, { label:__('Padding bottom (px)','blockenberg'), value:a.paddingBottom, min:0, max:160, onChange:function(v){ setAttr({paddingBottom:v}); } }),
146 el(RangeControl, { label:__('Button radius (px)','blockenberg'), value:a.btnRadius, min:0, max:50, onChange:function(v){ setAttr({btnRadius:v}); } })
147 ),
148
149 /* Typography */
150 el(PanelBody, { title:__('Typography','blockenberg'), initialOpen:false },
151 _tc() && el(_tc(), { label: __('Headline', 'blockenberg'), value: a.typoHeadline, onChange: function (v) { setAttr({ typoHeadline: v }); } }),
152 _tc() && el(_tc(), { label: __('Body', 'blockenberg'), value: a.typoBody, onChange: function (v) { setAttr({ typoBody: v }); } }),
153 _tc() && el(_tc(), { label: __('Feature', 'blockenberg'), value: a.typoFeature, onChange: function (v) { setAttr({ typoFeature: v }); } }),
154 _tc() && el(_tc(), { label: __('Eyebrow', 'blockenberg'), value: a.typoEyebrow, onChange: function (v) { setAttr({ typoEyebrow: v }); } })
155 ),
156
157 /* Colors */
158 el(PanelColorSettings, { title:__('Colors','blockenberg'), initialOpen:false, colorSettings:[
159 {label:__('Section background','blockenberg'), value:a.sectionBg, onChange:function(v){ setAttr({sectionBg:v||''}); }},
160 {label:__('Eyebrow bg','blockenberg'), value:a.eyebrowBg, onChange:function(v){ setAttr({eyebrowBg:v||''}); }},
161 {label:__('Eyebrow color','blockenberg'), value:a.eyebrowColor, onChange:function(v){ setAttr({eyebrowColor:v||''}); }},
162 {label:__('Headline color','blockenberg'), value:a.headlineColor, onChange:function(v){ setAttr({headlineColor:v||''}); }},
163 {label:__('Body text color','blockenberg'), value:a.bodyColor, onChange:function(v){ setAttr({bodyColor:v||''}); }},
164 {label:__('Feature text color','blockenberg'), value:a.featureColor, onChange:function(v){ setAttr({featureColor:v||''}); }},
165 {label:__('Primary btn bg','blockenberg'), value:a.primaryBtnBg, onChange:function(v){ setAttr({primaryBtnBg:v||''}); }},
166 {label:__('Primary btn text','blockenberg'), value:a.primaryBtnColor, onChange:function(v){ setAttr({primaryBtnColor:v||''}); }},
167 {label:__('Secondary btn color','blockenberg'),value:a.secBtnColor, onChange:function(v){ setAttr({secBtnColor:v||''}); }},
168 {label:__('Accent color','blockenberg'), value:a.accentColor, onChange:function(v){ setAttr({accentColor:v||''}); }},
169 ] })
170 );
171
172 /* Content column */
173 var contentEl = el('div', {
174 className: 'bkbg-fsp-content',
175 style: { background: a.contentBg || undefined, alignSelf: a.verticalAlign }
176 },
177 a.showEyebrow ? el('span', { className:'bkbg-fsp-eyebrow' }, a.eyebrow) : null,
178 el(RichText, { tagName:'h2', className:'bkbg-fsp-headline', value:a.headline, onChange:function(v){ setAttr({headline:v}); }, placeholder:__('Compelling headline…','blockenberg') }),
179 a.showBody ? el(RichText, { tagName:'p', className:'bkbg-fsp-body', value:a.body, onChange:function(v){ setAttr({body:v}); }, placeholder:__('Body text…','blockenberg') }) : null,
180 a.showFeatures ? el('ul', { className:'bkbg-fsp-features' },
181 features.map(function(f){
182 return el('li', { key:f.id, className:'bkbg-fsp-feature' },
183 el('span', { className:'bkbg-fsp-feature-icon' }, (f.iconType || 'custom-char') !== 'custom-char' ? IP().buildEditorIcon(f.iconType, f.icon, f.iconDashicon, f.iconImageUrl, f.iconDashiconColor) : f.icon),
184 el('span', { className:'bkbg-fsp-feature-text' }, f.text)
185 );
186 })
187 ) : null,
188 (a.showPrimaryBtn || a.showSecondaryBtn) ? el('div', { className:'bkbg-fsp-btns' },
189 a.showPrimaryBtn ? el('a', { className:'bkbg-fsp-btn bkbg-fsp-btn--primary', href:a.primaryBtnUrl, onClick:function(e){ e.preventDefault(); } }, a.primaryBtnLabel) : null,
190 a.showSecondaryBtn ? el('a', { className:'bkbg-fsp-btn bkbg-fsp-btn--secondary', href:a.secondaryBtnUrl, onClick:function(e){ e.preventDefault(); } }, a.secondaryBtnLabel) : null
191 ) : null
192 );
193
194 /* Image column */
195 var imageEl = el('div', { className:'bkbg-fsp-image-wrap' + (a.imageShadow ? ' bkbg-fsp-shadow' : '') },
196 a.imageUrl
197 ? el('img', { src:a.imageUrl, alt:a.imageAlt, className:'bkbg-fsp-img' })
198 : el(MediaUploadCheck, null,
199 el(MediaUpload, {
200 onSelect:function(m){ setAttr({ imageUrl:m.url, imageId:m.id, imageAlt:m.alt||'' }); },
201 allowedTypes:['image'], value:a.imageId,
202 render:function(o){ return el(Button, { onClick:o.open, className:'bkbg-fsp-img-placeholder', variant:'secondary' }, __('+ Choose image','blockenberg')); }
203 })
204 ),
205 a.imageUrl ? el('div', { className:'bkbg-fsp-img-actions' },
206 el(Button, { isSmall:true, variant:'secondary', onClick:function(){ setAttr({ imageUrl:'', imageId:0 }); } }, __('Remove','blockenberg'))
207 ) : null
208 );
209
210 return el(Fragment, null,
211 inspector,
212 el('div', blockProps,
213 a.imagePosition === 'right' ? el(Fragment, null, contentEl, imageEl) : el(Fragment, null, imageEl, contentEl)
214 )
215 );
216 },
217
218 save: function (props) {
219 var a = props.attributes;
220 var wrapCls = 'bkbg-fsp-wrap bkbg-fsp-style--' + a.style
221 + (a.imagePosition === 'left' ? ' bkbg-fsp-img-left' : ' bkbg-fsp-img-right');
222 var blockProps = wp.blockEditor.useBlockProps.save({ className: wrapCls, style: buildWrapStyle(a) });
223
224 var contentEl = el('div', { className:'bkbg-fsp-content', style:{ alignSelf:a.verticalAlign } },
225 a.showEyebrow ? el('span', { className:'bkbg-fsp-eyebrow' }, a.eyebrow) : null,
226 el(RichText.Content, { tagName:'h2', className:'bkbg-fsp-headline', value:a.headline }),
227 a.showBody ? el(RichText.Content, { tagName:'p', className:'bkbg-fsp-body', value:a.body }) : null,
228 a.showFeatures ? el('ul', { className:'bkbg-fsp-features' },
229 a.features.map(function(f){
230 return el('li', { key:f.id, className:'bkbg-fsp-feature' },
231 el('span', { className:'bkbg-fsp-feature-icon' }, (f.iconType || 'custom-char') !== 'custom-char' ? IP().buildSaveIcon(f.iconType, f.icon, f.iconDashicon, f.iconImageUrl, f.iconDashiconColor) : f.icon),
232 el('span', { className:'bkbg-fsp-feature-text' }, f.text)
233 );
234 })
235 ) : null,
236 (a.showPrimaryBtn || a.showSecondaryBtn) ? el('div', { className:'bkbg-fsp-btns' },
237 a.showPrimaryBtn ? el('a', { className:'bkbg-fsp-btn bkbg-fsp-btn--primary', href:a.primaryBtnUrl, target: a.primaryBtnTarget ? '_blank' : undefined }, a.primaryBtnLabel) : null,
238 a.showSecondaryBtn ? el('a', { className:'bkbg-fsp-btn bkbg-fsp-btn--secondary', href:a.secondaryBtnUrl }, a.secondaryBtnLabel) : null
239 ) : null
240 );
241
242 var imageEl = el('div', { className:'bkbg-fsp-image-wrap' + (a.imageShadow ? ' bkbg-fsp-shadow' : '') },
243 a.imageUrl ? el('img', { src:a.imageUrl, alt:a.imageAlt, className:'bkbg-fsp-img', loading:'lazy' }) : null
244 );
245
246 return el('div', blockProps,
247 a.imagePosition === 'right' ? el(Fragment, null, contentEl, imageEl) : el(Fragment, null, imageEl, contentEl)
248 );
249 }
250 });
251 }() );
252