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

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

229 lines 12.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 ( function () {
2 var el = window.wp.element.createElement;
3 var { useState } = window.wp.element;
4 var { registerBlockType } = window.wp.blocks;
5 var { InspectorControls, MediaUpload, MediaUploadCheck, PanelColorSettings } = window.wp.blockEditor;
6 var { PanelBody, PanelRow, TabPanel, RangeControl, SelectControl, TextControl, ToggleControl, Button, __experimentalGradientPicker: GradientPicker } = window.wp.components;
7 var { __ } = window.wp.i18n;
8
9 var RATIOS = [
10 {label:'50 / 50', value:'50-50'},
11 {label:'40 / 60', value:'40-60'},
12 {label:'60 / 40', value:'60-40'},
13 {label:'33 / 67', value:'33-67'},
14 {label:'67 / 33', value:'67-33'},
15 ];
16 var V_ALIGNS = [{label:'Top',value:'flex-start'},{label:'Center',value:'center'},{label:'Bottom',value:'flex-end'}];
17 var TAGS = ['h1','h2','h3','h4','p'].map(t=>({label:t.toUpperCase(),value:t}));
18 var BG_TYPES = [{label:'Color',value:'color'},{label:'Gradient',value:'gradient'},{label:'Image',value:'image'}];
19 var ALIGNS = [{label:'Left',value:'left'},{label:'Center',value:'center'},{label:'Right',value:'right'}];
20
21 var _tc; function getTypoControl() { return _tc || (_tc = window.bkbgTypographyControl); }
22 var _tv; function getTypoCssVars() { return _tv || (_tv = window.bkbgTypoCssVars); }
23
24 function ratioToPct(ratio, side) {
25 var parts = ratio.split('-');
26 return side === 'left' ? parts[0]+'%' : parts[1]+'%';
27 }
28
29 function buildWrapStyle(a) {
30 var leftW = ratioToPct(a.splitRatio,'left');
31 var s = {
32 '--bkss-left-w': leftW,
33 '--bkss-gap': a.gap + 'px',
34 '--bkss-min-h': a.minHeight + 'px',
35 '--bkss-lh-sz': a.leftHeadingSize + 'px',
36 '--bkss-lh-w': a.leftHeadingWeight,
37 '--bkss-rh-sz': a.rightHeadingSize + 'px',
38 '--bkss-rh-w': a.rightHeadingWeight,
39 };
40 var fn = getTypoCssVars();
41 if (fn) {
42 Object.assign(s, fn(a.leftHeadingTypo, '--bkss-lh'));
43 Object.assign(s, fn(a.leftTextTypo, '--bkss-lt'));
44 Object.assign(s, fn(a.leftBtnTypo, '--bkss-lb'));
45 Object.assign(s, fn(a.rightHeadingTypo, '--bkss-rh'));
46 Object.assign(s, fn(a.rightTextTypo, '--bkss-rt'));
47 Object.assign(s, fn(a.rightBtnTypo, '--bkss-rb'));
48 }
49 return s;
50 }
51
52 function panelBg(a, side) {
53 var bt = a[side+'BgType'];
54 if (bt === 'gradient') return a[side+'BgGradient'];
55 if (bt === 'image' && a[side+'BgImage']) return 'url('+a[side+'BgImage']+') '+a[side+'BgPosition']+'/cover no-repeat';
56 return a[side+'BgColor'];
57 }
58
59 function PanelEditor({ a, set, side, label }) {
60 var pfx = side;
61 var bg = panelBg(a, side);
62 var hasOverlay = a[pfx+'BgType'] === 'image' && a[pfx+'BgImage'];
63
64 return el('div', null,
65 el(PanelBody, { title: label + ' — Background', initialOpen: true },
66 el(SelectControl, { label: __('Background Type'), value: a[pfx+'BgType'],
67 options: BG_TYPES, onChange: v => set({[pfx+'BgType']:v}) }),
68 a[pfx+'BgType'] === 'color' && el('div', null,
69 el('label', {style:{fontSize:'11px',fontWeight:600,display:'block',marginBottom:'4px'}}, __('Color')),
70 el('input', { type:'color', value:a[pfx+'BgColor'],
71 onChange: e => set({[pfx+'BgColor']:e.target.value}),
72 style:{width:'100%',height:'34px',borderRadius:'4px',border:'1px solid #ccc',cursor:'pointer'} })
73 ),
74 a[pfx+'BgType'] === 'gradient' && el('div', { style:{ marginBottom:'8px' } },
75 el('p', { style:{ fontSize:'11px', fontWeight:600, margin:'0 0 6px', textTransform:'uppercase', color:'#757575' } }, __('Gradient')),
76 el(GradientPicker, { value: a[pfx+'BgGradient'], onChange: v=>set({[pfx+'BgGradient']:v}) })
77 ),
78 a[pfx+'BgType'] === 'image' && el(MediaUploadCheck, null,
79 el(MediaUpload, {
80 onSelect: m => set({[pfx+'BgImage']:m.url, [pfx+'BgImageId']:m.id}),
81 allowedTypes:['image'], value: a[pfx+'BgImageId'],
82 render: ({open}) => el(Button, {onClick:open, variant:'secondary', style:{width:'100%',justifyContent:'center',marginBottom:'8px'}},
83 a[pfx+'BgImage'] ? __('Change Image') : __('Select Image'))
84 }),
85 a[pfx+'BgImage'] && el(Button, {isDestructive:true,isSmall:true,onClick:()=>set({[pfx+'BgImage']:'', [pfx+'BgImageId']:0})}, __('Remove Image'))
86 ),
87 a[pfx+'BgType'] === 'image' && el(TextControl, { label:__('Image Position'), value:a[pfx+'BgPosition'], onChange:v=>set({[pfx+'BgPosition']:v}) }),
88 hasOverlay && el('div',null,
89 el('label',{style:{fontSize:'11px',fontWeight:600,display:'block',marginBottom:'4px'}},__('Overlay Color')),
90 el('input',{type:'color',value:a[pfx+'Overlay']||'#000000',onChange:e=>set({[pfx+'Overlay']:e.target.value}),
91 style:{width:'100%',height:'34px',borderRadius:'4px',border:'1px solid #ccc',cursor:'pointer'}}),
92 el(RangeControl,{label:__('Overlay Opacity %'),value:a[pfx+'OverlayOpacity'],min:0,max:90,onChange:v=>set({[pfx+'OverlayOpacity']:v})})
93 ),
94 el(RangeControl, { label:__('Padding X (px)'), value:a[pfx+'PaddingX'], min:0, max:120, onChange:v=>set({[pfx+'PaddingX']:v}) }),
95 el(RangeControl, { label:__('Padding Y (px)'), value:a[pfx+'PaddingY'], min:0, max:120, onChange:v=>set({[pfx+'PaddingY']:v}) }),
96 ),
97 el(PanelBody, { title: label + ' — Content', initialOpen: false },
98 el(SelectControl,{label:__('Heading Tag'),value:a[pfx+'Tag'],options:TAGS,onChange:v=>set({[pfx+'Tag']:v})}),
99 el(TextControl,{label:__('Heading'),value:a[pfx+'Heading'],onChange:v=>set({[pfx+'Heading']:v})}),
100 el(TextControl,{label:__('Body Text'),value:a[pfx+'Text'],onChange:v=>set({[pfx+'Text']:v})}),
101 el(SelectControl,{label:__('Text Align'),value:a[pfx+'TextAlign'],options:ALIGNS,onChange:v=>set({[pfx+'TextAlign']:v})}),
102 el(ToggleControl,{label:__('Show Button'),checked:a[pfx+'ShowBtn'],onChange:v=>set({[pfx+'ShowBtn']:v}),__nextHasNoMarginBottom:true}),
103 a[pfx+'ShowBtn'] && el(TextControl,{label:__('Button Label'),value:a[pfx+'BtnLabel'],onChange:v=>set({[pfx+'BtnLabel']:v})}),
104 a[pfx+'ShowBtn'] && el(TextControl,{label:__('Button URL'),value:a[pfx+'BtnUrl'],onChange:v=>set({[pfx+'BtnUrl']:v})}),
105 a[pfx+'ShowBtn'] && el(RangeControl,{label:__('Button Radius (px)'),value:a[pfx+'BtnRadius'],min:0,max:50,onChange:v=>set({[pfx+'BtnRadius']:v})}),
106 ),
107
108 el( PanelBody, { title: __( 'Typography', 'blockenberg' ), initialOpen: false },
109 getTypoControl() ? el(getTypoControl(), { label:__('Heading','blockenberg'), value:a[pfx+'HeadingTypo'], onChange:function(v){ set({[pfx+'HeadingTypo']:v}); } }) : null,
110 getTypoControl() ? el(getTypoControl(), { label:__('Text','blockenberg'), value:a[pfx+'TextTypo'], onChange:function(v){ set({[pfx+'TextTypo']:v}); } }) : null,
111 getTypoControl() ? el(getTypoControl(), { label:__('Button','blockenberg'), value:a[pfx+'BtnTypo'], onChange:function(v){ set({[pfx+'BtnTypo']:v}); } }) : null
112 ),
113 el(PanelColorSettings, { title: label+' — Colors', initialOpen:false, colorSettings:[
114 {label:__('Heading Color'),value:a[pfx+'HeadingColor'],onChange:v=>set({[pfx+'HeadingColor']:v||'#ffffff'})},
115 {label:__('Text Color'), value:a[pfx+'TextColor'], onChange:v=>set({[pfx+'TextColor']:v||'#ffffff'})},
116 {label:__('Button BG'), value:a[pfx+'BtnBg'], onChange:v=>set({[pfx+'BtnBg']:v||'#ffffff'})},
117 {label:__('Button Text'), value:a[pfx+'BtnColor'], onChange:v=>set({[pfx+'BtnColor']:v||'#333333'})},
118 ]}),
119 );
120 }
121
122 function PanelPreview({ a, side }) {
123 var bg = panelBg(a, side);
124 var pfx = side;
125 var hasOverlay = a[pfx+'BgType'] === 'image' && a[pfx+'BgImage'];
126
127 var panelStyle = {
128 background: bg,
129 padding: a[pfx+'PaddingY']+'px '+a[pfx+'PaddingX']+'px',
130 display:'flex', flexDirection:'column', justifyContent: a.verticalAlign || 'center',
131 position:'relative', overflow:'hidden', boxSizing:'border-box',
132 textAlign: a[pfx+'TextAlign'],
133 };
134 var contentStyle = { position:'relative', zIndex:1 };
135
136 return el('div', {style:panelStyle},
137 hasOverlay && el('div',{style:{
138 position:'absolute',inset:0,
139 background: a[pfx+'Overlay']||'#000',
140 opacity:(a[pfx+'OverlayOpacity']||40)/100,
141 }}),
142 el('div',{style:contentStyle},
143 el(a[pfx+'Tag']||'h2', {className:'bkss-heading',style:{color:a[pfx+'HeadingColor'],margin:'0 0 12px'}},
144 a[pfx+'Heading']),
145 a[pfx+'Text'] && el('p',{className:'bkss-text',style:{color:a[pfx+'TextColor'],margin:'0 0 20px'}},a[pfx+'Text']),
146 a[pfx+'ShowBtn'] && el('a',{href:'#',className:'bkss-btn',
147 style:{display:'inline-block',background:a[pfx+'BtnBg'],color:a[pfx+'BtnColor'],
148 padding:'10px 24px',borderRadius:a[pfx+'BtnRadius']+'px'}},
149 a[pfx+'BtnLabel']),
150 )
151 );
152 }
153
154 registerBlockType('blockenberg/split-screen', {
155 edit: function(props) {
156 var a = props.attributes;
157 var set = props.setAttributes;
158 var [activeTab, setActiveTab] = useState('left');
159
160 var leftW = ratioToPct(a.splitRatio,'left');
161 var rightW = ratioToPct(a.splitRatio,'right');
162
163 return el('div',{className:'bkss-wrap',style:buildWrapStyle(a)},
164 el(InspectorControls,null,
165 el(PanelBody,{title:__('Layout'),initialOpen:true},
166 el(SelectControl,{label:__('Split Ratio'),value:a.splitRatio,options:RATIOS,onChange:v=>set({splitRatio:v})}),
167 el(RangeControl,{label:__('Min Height (px)'),value:a.minHeight,min:200,max:1000,onChange:v=>set({minHeight:v})}),
168 el(SelectControl,{label:__('Vertical Align'),value:a.verticalAlign,options:V_ALIGNS,onChange:v=>set({verticalAlign:v})}),
169 el(RangeControl,{label:__('Gap Between Panels (px)'),value:a.gap,min:0,max:60,onChange:v=>set({gap:v})}),
170 el(ToggleControl,{label:__('Stack on Mobile'),checked:a.stackOnMobile,onChange:v=>set({stackOnMobile:v}),__nextHasNoMarginBottom:true}),
171 ),
172 el(TabPanel,{
173 activeClass:'is-active',
174 tabs:[{name:'left',title:__('Left Panel')},{name:'right',title:__('Right Panel')}],
175 }, tab => el(PanelEditor,{a,set,side:tab.name,label:tab.name==='left'?__('Left'):__('Right')})),
176 ),
177
178 el('div',{className:'bkss-layout',style:{display:'flex',gap:a.gap+'px',minHeight:a.minHeight+'px'}},
179 el('div',{className:'bkss-left',style:{width:leftW,flexShrink:0}},
180 el(PanelPreview,{a,side:'left'})),
181 el('div',{className:'bkss-right',style:{flex:1}},
182 el(PanelPreview,{a,side:'right'})),
183 )
184 );
185 },
186
187 save: function({attributes:a}) {
188 function panelHTML(side) {
189 var pfx = side;
190 var bg = panelBg(a, side);
191 var hasOverlay = a[pfx+'BgType']==='image' && a[pfx+'BgImage'];
192
193 return el('div',{
194 className:'bkss-panel bkss-'+side,
195 style:{
196 background:bg,
197 padding:a[pfx+'PaddingY']+'px '+a[pfx+'PaddingX']+'px',
198 textAlign:a[pfx+'TextAlign'], position:'relative', overflow:'hidden', boxSizing:'border-box',
199 }
200 },
201 hasOverlay && el('div',{className:'bkss-overlay',style:{
202 position:'absolute',inset:0,
203 background:a[pfx+'Overlay']||'#000',
204 opacity:(a[pfx+'OverlayOpacity']||40)/100,
205 }}),
206 el('div',{style:{position:'relative',zIndex:1}},
207 el(a[pfx+'Tag']||'h2',{className:'bkss-heading',style:{color:a[pfx+'HeadingColor'],margin:'0 0 12px'}},
208 a[pfx+'Heading']),
209 a[pfx+'Text'] && el('p',{className:'bkss-text',style:{color:a[pfx+'TextColor'],margin:'0 0 20px'}},a[pfx+'Text']),
210 a[pfx+'ShowBtn'] && el('a',{className:'bkss-btn',href:a[pfx+'BtnUrl'],
211 style:{display:'inline-block',background:a[pfx+'BtnBg'],color:a[pfx+'BtnColor'],
212 padding:'10px 24px',borderRadius:a[pfx+'BtnRadius']+'px'}},
213 a[pfx+'BtnLabel']),
214 )
215 );
216 }
217 return el('div',{
218 className:'bkss-wrap'+(a.stackOnMobile?' bkss-stack-mobile':''),
219 style:buildWrapStyle(a),
220 },
221 el('div',{className:'bkss-layout'},
222 panelHTML('left'),
223 panelHTML('right'),
224 )
225 );
226 }
227 });
228 }() );
229