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 / post-slider / index.js

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

229 lines 13.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 ( function () {
2 const el = window.wp.element.createElement;
3 const { registerBlockType } = window.wp.blocks;
4 const { InspectorControls, MediaUpload, MediaUploadCheck, PanelColorSettings } = window.wp.blockEditor;
5 const { PanelBody, RangeControl, SelectControl, TextControl, TextareaControl, ToggleControl, Button } = window.wp.components;
6 const { __ } = window.wp.i18n;
7 const useState = window.wp.element.useState;
8 const Fragment = window.wp.element.Fragment;
9 let _tc; const getTypoControl = () => _tc || (_tc = window.bkbgTypographyControl);
10 let _tv; const getTypoCssVars = () => _tv || (_tv = window.bkbgTypoCssVars);
11
12 function SlideEditor( { slide, index, onChange, onRemove } ) {
13 function upd(k,v){ onChange(index, Object.assign({}, slide, {[k]:v})); }
14 return el('div', { style:{border:'1px solid #ddd',borderRadius:'8px',padding:'12px',marginBottom:'8px',background:'#fafafa'} },
15 el('strong', { style:{display:'block',marginBottom:'8px'} }, __('Slide ') + (index+1)),
16 el('label', {style:{fontSize:'11px',fontWeight:600,display:'block',marginBottom:'4px'}} , __('Background Image')),
17 slide.imageUrl
18 ? el('div', {style:{marginBottom:'8px'}},
19 el('img', {src:slide.imageUrl, style:{width:'100%',height:'80px',objectFit:'cover',borderRadius:'6px',display:'block',marginBottom:'4px'}}),
20 el(Button, {isDestructive:true, isSmall:true, onClick:()=>{upd('imageUrl','');upd('imageId',0);}}, __('Remove'))
21 )
22 : el(MediaUploadCheck, null,
23 el(MediaUpload, {
24 onSelect: m=>{upd('imageUrl',m.url);upd('imageId',m.id);},
25 allowedTypes:['image'], value:slide.imageId,
26 render:({open})=>el(Button,{onClick:open,isSmall:true,variant:'secondary'}, __('Upload Image'))
27 })
28 ),
29 el(TextControl, {label:__('Title'), value:slide.title, onChange:v=>upd('title',v)}),
30 el(TextareaControl, {label:__('Excerpt'), value:slide.excerpt, onChange:v=>upd('excerpt',v), rows:2}),
31 el(TextControl, {label:__('Button Label'), value:slide.btnLabel, onChange:v=>upd('btnLabel',v)}),
32 el(TextControl, {label:__('Button URL'), value:slide.btnUrl, onChange:v=>upd('btnUrl',v)}),
33 el(Button, {isDestructive:true, isSmall:true, onClick:()=>onRemove(index)}, __('Remove Slide'))
34 );
35 }
36
37 registerBlockType('blockenberg/post-slider', {
38 edit: function(props) {
39 const { attributes: attr, setAttributes } = props;
40 const [activeIdx, setActiveIdx] = useState(0);
41
42 function updateSlide(idx, next){ const s=attr.slides.slice(); s[idx]=next; setAttributes({slides:s}); }
43 function removeSlide(idx){ const s=attr.slides.filter((_,i)=>i!==idx); setAttributes({slides:s}); setActiveIdx(Math.min(activeIdx, s.length-1)); }
44 function addSlide(){ setAttributes({slides:[...attr.slides,{imageUrl:'',imageId:0,title:'New Slide',excerpt:'Caption here.',btnLabel:'Read More',btnUrl:'#'}]}); }
45
46 const current = attr.slides[activeIdx] || attr.slides[0] || {};
47 const heightVal = attr.height + attr.heightUnit;
48
49 const _tvFn = getTypoCssVars();
50 const wrapStyle = Object.assign({
51 '--bkps-height': heightVal,
52 '--bkps-overlay': attr.overlayBg,
53 '--bkps-text': attr.textColor,
54 '--bkps-accent': attr.accentColor,
55 '--bkps-radius': attr.borderRadius + 'px',
56 borderRadius: attr.borderRadius + 'px',
57 overflow: 'hidden',
58 position: 'relative',
59 }, _tvFn(attr.titleTypo, '--bkps-tt-'), _tvFn(attr.excerptTypo, '--bkps-ex-'));
60
61 const slideStyle = {
62 backgroundImage: current.imageUrl ? `url(${current.imageUrl})` : 'none',
63 backgroundColor: current.imageUrl ? 'transparent' : '#1e0a3c',
64 backgroundSize: 'cover',
65 backgroundPosition: 'center',
66 height: heightVal,
67 };
68
69 const boxAlign = attr.captionAlign === 'center' ? 'center' : attr.captionAlign === 'right' ? 'flex-end' : 'flex-start';
70
71 return el('div', { className:'bkps-wrap', style: wrapStyle },
72
73 el(InspectorControls, null,
74 el(PanelBody, {title:__('Slides'), initialOpen:true},
75 attr.slides.map((slide,i)=>el(SlideEditor,{key:i,slide,index:i,onChange:updateSlide,onRemove:removeSlide})),
76 el(Button,{variant:'secondary',onClick:addSlide,style:{width:'100%',justifyContent:'center',marginTop:'8px'}}, __('+ Add Slide'))
77 ),
78 el(PanelBody, {title:__('Slider Settings'), initialOpen:false},
79 el(RangeControl, {label:__('Height (px)'), value:attr.height, min:200, max:900, onChange:v=>setAttributes({height:v})}),
80 el(SelectControl, {label:__('Transition'), value:attr.transition, options:[{label:'Fade',value:'fade'},{label:'Slide',value:'slide'}], onChange:v=>setAttributes({transition:v})}),
81 el(ToggleControl, {label:__('Autoplay'), checked:attr.autoplay, onChange:v=>setAttributes({autoplay:v}), __nextHasNoMarginBottom:true}),
82 attr.autoplay && el(RangeControl, {label:__('Speed (ms)'), value:attr.speed, min:1500, max:9000, step:500, onChange:v=>setAttributes({speed:v})}),
83 el(ToggleControl, {label:__('Show Arrows'), checked:attr.showArrows, onChange:v=>setAttributes({showArrows:v}), __nextHasNoMarginBottom:true}),
84 el(ToggleControl, {label:__('Show Dots'), checked:attr.showDots, onChange:v=>setAttributes({showDots:v}), __nextHasNoMarginBottom:true}),
85 el(SelectControl, {label:__('Caption Alignment'), value:attr.captionAlign, options:[{label:'Left',value:'left'},{label:'Center',value:'center'},{label:'Right',value:'right'}], onChange:v=>setAttributes({captionAlign:v})})
86 ),
87 el(PanelBody, {title:__('Typography'), initialOpen:false},
88 (() => {
89 const TC = getTypoControl();
90 if (!TC) return el('p', null, 'Loading…');
91 return el(Fragment, null,
92 el(TC, { label: 'Title Typography', value: attr.titleTypo, onChange: v => setAttributes({ titleTypo: v }) }),
93 el(TC, { label: 'Excerpt Typography', value: attr.excerptTypo, onChange: v => setAttributes({ excerptTypo: v }) })
94 );
95 })(),
96 el(RangeControl, {label:__('Border Radius (px)'), value:attr.borderRadius, min:0, max:32, onChange:v=>setAttributes({borderRadius:v})})
97 ),
98 el(PanelColorSettings, {
99 title:__('Colors'), initialOpen:false,
100 colorSettings:[
101 {label:__('Overlay Color'), value:attr.overlayBg, onChange:v=>setAttributes({overlayBg:v||'rgba(0,0,0,0.45)'})},
102 {label:__('Text Color'), value:attr.textColor, onChange:v=>setAttributes({textColor:v||'#ffffff'})},
103 {label:__('Accent / Button'), value:attr.accentColor, onChange:v=>setAttributes({accentColor:v||'#6c3fb5'})},
104 ]
105 })
106 ),
107
108 /* Editor preview */
109 el('div', {className:'bkps-slide bkps-active', style: slideStyle},
110 el('div', {className:'bkps-overlay'}),
111 el('div', {className:'bkps-caption', style:{alignItems: boxAlign, textAlign: attr.captionAlign}},
112 el('h2', {className:'bkps-title'}, current.title),
113 el('p', {className:'bkps-excerpt'}, current.excerpt),
114 current.btnLabel && el('span', {className:'bkps-btn'}, current.btnLabel)
115 )
116 ),
117
118 attr.showArrows && el('div', {className:'bkps-arrows'},
119 el('button', {className:'bkps-arrow bkps-prev', onClick:()=>setActiveIdx((activeIdx-1+attr.slides.length)%attr.slides.length)}, ''),
120 el('button', {className:'bkps-arrow bkps-next', onClick:()=>setActiveIdx((activeIdx+1)%attr.slides.length)}, '')
121 ),
122 attr.showDots && el('div', {className:'bkps-dots'},
123 attr.slides.map((_,i)=>el('button',{key:i, className:'bkps-dot'+(i===activeIdx?' bkps-dot-active':''), onClick:()=>setActiveIdx(i)}))
124 )
125 );
126 },
127
128 deprecated: [{
129 attributes: {
130 slides: { type: 'array', default: [{imageUrl:'',imageId:0,title:'Slide One Headline',excerpt:'A short caption describing this featured post or section.',btnLabel:'Read More',btnUrl:'#'},{imageUrl:'',imageId:0,title:'Slide Two Headline',excerpt:'A short caption describing this featured post or section.',btnLabel:'Read More',btnUrl:'#'}] },
131 height: { type: 'number', default: 500 },
132 heightUnit: { type: 'string', default: 'px' },
133 transition: { type: 'string', default: 'fade' },
134 autoplay: { type: 'boolean', default: true },
135 speed: { type: 'number', default: 4000 },
136 overlayBg: { type: 'string', default: 'rgba(0,0,0,0.45)' },
137 captionAlign: { type: 'string', default: 'left' },
138 textColor: { type: 'string', default: '#ffffff' },
139 accentColor: { type: 'string', default: '#6c3fb5' },
140 showArrows: { type: 'boolean', default: true },
141 showDots: { type: 'boolean', default: true },
142 titleSz: { type: 'number', default: 42 },
143 excerptSz: { type: 'number', default: 16 },
144 borderRadius: { type: 'number', default: 0 },
145 titleFontWeight: { type: 'string', default: '700' },
146 excerptFontWeight:{ type: 'string', default: '400' }
147 },
148 save: function({ attributes: attr }) {
149 const wrapStyle = {
150 '--bkps-height': attr.height + attr.heightUnit,
151 '--bkps-overlay': attr.overlayBg,
152 '--bkps-text': attr.textColor,
153 '--bkps-accent': attr.accentColor,
154 '--bkps-title-sz': attr.titleSz + 'px',
155 '--bkps-excerpt-sz': attr.excerptSz + 'px',
156 '--bkps-radius': attr.borderRadius + 'px',
157 };
158 return el('div', {
159 className: 'bkps-wrap bkps-transition-' + attr.transition,
160 style: wrapStyle,
161 'data-autoplay': attr.autoplay ? '1' : '0',
162 'data-speed': attr.speed,
163 'data-arrows': attr.showArrows ? '1' : '0',
164 'data-dots': attr.showDots ? '1' : '0',
165 },
166 el('div', {className:'bkps-track'},
167 attr.slides.map((slide, i)=>
168 el('div', {key:i, className:'bkps-slide'+(i===0?' bkps-active':''),
169 style:{backgroundImage: slide.imageUrl ? `url(${slide.imageUrl})` : 'none', backgroundColor: slide.imageUrl ? 'transparent':'#1e0a3c'}
170 },
171 el('div', {className:'bkps-overlay'}),
172 el('div', {className:'bkps-caption', style:{textAlign:attr.captionAlign, alignItems:attr.captionAlign==='center'?'center':attr.captionAlign==='right'?'flex-end':'flex-start'}},
173 el('h2', {className:'bkps-title'}, slide.title),
174 el('p', {className:'bkps-excerpt'}, slide.excerpt),
175 slide.btnLabel && el('a', {href:slide.btnUrl, className:'bkps-btn'}, slide.btnLabel)
176 )
177 )
178 )
179 ),
180 attr.showArrows && el('div', {className:'bkps-arrows'},
181 el('button', {className:'bkps-arrow bkps-prev','aria-label':'Previous'}, '\u2039'),
182 el('button', {className:'bkps-arrow bkps-next','aria-label':'Next'}, '\u203A')
183 ),
184 attr.showDots && el('div', {className:'bkps-dots'})
185 );
186 }
187 }],
188
189 save: function({ attributes: attr }) {
190 const _tvFn = getTypoCssVars();
191 const wrapStyle = Object.assign({
192 '--bkps-height': attr.height + attr.heightUnit,
193 '--bkps-overlay': attr.overlayBg,
194 '--bkps-text': attr.textColor,
195 '--bkps-accent': attr.accentColor,
196 '--bkps-radius': attr.borderRadius + 'px',
197 }, _tvFn(attr.titleTypo, '--bkps-tt-'), _tvFn(attr.excerptTypo, '--bkps-ex-'));
198 return el('div', {
199 className: 'bkps-wrap bkps-transition-' + attr.transition,
200 style: wrapStyle,
201 'data-autoplay': attr.autoplay ? '1' : '0',
202 'data-speed': attr.speed,
203 'data-arrows': attr.showArrows ? '1' : '0',
204 'data-dots': attr.showDots ? '1' : '0',
205 },
206 el('div', {className:'bkps-track'},
207 attr.slides.map((slide, i)=>
208 el('div', {key:i, className:'bkps-slide'+(i===0?' bkps-active':''),
209 style:{backgroundImage: slide.imageUrl ? `url(${slide.imageUrl})` : 'none', backgroundColor: slide.imageUrl ? 'transparent':'#1e0a3c'}
210 },
211 el('div', {className:'bkps-overlay'}),
212 el('div', {className:'bkps-caption', style:{textAlign:attr.captionAlign, alignItems:attr.captionAlign==='center'?'center':attr.captionAlign==='right'?'flex-end':'flex-start'}},
213 el('h2', {className:'bkps-title'}, slide.title),
214 el('p', {className:'bkps-excerpt'}, slide.excerpt),
215 slide.btnLabel && el('a', {href:slide.btnUrl, className:'bkps-btn'}, slide.btnLabel)
216 )
217 )
218 )
219 ),
220 attr.showArrows && el('div', {className:'bkps-arrows'},
221 el('button', {className:'bkps-arrow bkps-prev','aria-label':'Previous'}, ''),
222 el('button', {className:'bkps-arrow bkps-next','aria-label':'Next'}, '')
223 ),
224 attr.showDots && el('div', {className:'bkps-dots'})
225 );
226 }
227 });
228 }() );
229