PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.14
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.14
2.0.14 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 / video-hero / index.js

index.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.14, at blocks/video-hero/index.js

374 lines 21.4 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 useState = wp.element.useState;
4 var __ = wp.i18n.__;
5 var registerBlockType = wp.blocks.registerBlockType;
6 var InspectorControls = wp.blockEditor.InspectorControls;
7 var RichText = wp.blockEditor.RichText;
8 var MediaUpload = wp.blockEditor.MediaUpload;
9 var useBlockProps = wp.blockEditor.useBlockProps;
10 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
11 var PanelBody = wp.components.PanelBody;
12 var RangeControl = wp.components.RangeControl;
13 var SelectControl = wp.components.SelectControl;
14 var ToggleControl = wp.components.ToggleControl;
15 var TextControl = wp.components.TextControl;
16 var Button = wp.components.Button;
17
18 // Resolve the shared components lazily without defining globals for each block.
19 function _tc(label, key, attrs, setA) {
20 var Control = window.bkbgTypographyControl;
21 return Control ? el(Control, {
22 label: label,
23 value: attrs[key] || {},
24 onChange: function (value) { var update = {}; update[key] = value; setA(update); }
25 }) : null;
26 }
27 function _tvf(vars, key, attrs, prefix) {
28 var cssVars = window.bkbgTypoCssVars;
29 if (cssVars) Object.assign(vars, cssVars(attrs[key] || {}, prefix));
30 return vars;
31 }
32 function getTypoControl(label, key, attrs, setA) { return _tc(label, key, attrs, setA); }
33 function getTypoCssVars(attrs) {
34 var v = {};
35 _tvf(v, 'headingTypo', attrs, '--bkvh-hd-');
36 _tvf(v, 'subTypo', attrs, '--bkvh-sb-');
37 _tvf(v, 'eyebrowTypo', attrs, '--bkvh-ey-');
38 _tvf(v, 'ctaTypo', attrs, '--bkvh-ct-');
39 return v;
40 }
41
42 function wrapStyle(a) {
43 var s = getTypoCssVars(a);
44 s['--bkbg-vh-bg'] = a.bgColor;
45 s['--bkbg-vh-heading-c'] = a.headingColor;
46 s['--bkbg-vh-sub-c'] = a.subColor;
47 s['--bkbg-vh-eyebrow-c'] = a.eyebrowColor;
48 s['--bkbg-vh-accent'] = a.accentColor;
49 s['--bkbg-vh-btn-bg'] = a.btnBg;
50 s['--bkbg-vh-btn-text'] = a.btnText;
51 s['--bkbg-vh-btn2-bg'] = a.btn2Bg;
52 s['--bkbg-vh-btn2-text'] = a.btn2Text;
53 s['--bkbg-vh-btn2-border'] = a.btn2Border;
54 s['--bkbg-vh-video-border'] = a.videoBorder;
55 s['--bkbg-vh-cta-r'] = a.ctaRadius + 'px';
56 s['--bkbg-vh-pt'] = a.paddingTop + 'px';
57 s['--bkbg-vh-pb'] = a.paddingBottom + 'px';
58 s['--bkbg-vh-max-w'] = a.maxWidth + 'px';
59 s['--bkbg-vh-video-r'] = a.videoRadius + 'px';
60 return s;
61 }
62
63 var ASPECT_MAP = { '16-9': '56.25%', '4-3': '75%', '21-9': '42.86%' };
64
65 registerBlockType('blockenberg/video-hero', {
66 title: __('Video Hero', 'blockenberg'),
67 icon: 'video-alt3',
68 category: 'bkbg-layout',
69
70 edit: function (props) {
71 var a = props.attributes;
72 var set = props.setAttributes;
73
74 var styleOptions = [
75 { label: __('Dark', 'blockenberg'), value: 'dark' },
76 { label: __('Light', 'blockenberg'), value: 'light' },
77 { label: __('Gradient', 'blockenberg'), value: 'gradient' },
78 ];
79 var layoutOptions = [
80 { label: __('Video below content', 'blockenberg'), value: 'below' },
81 { label: __('Video beside content', 'blockenberg'), value: 'side' },
82 ];
83 var aspectOptions = [
84 { label: __('16:9 (Widescreen)', 'blockenberg'), value: '16-9' },
85 { label: __('4:3', 'blockenberg'), value: '4-3' },
86 { label: __('21:9 (Cinematic)', 'blockenberg'), value: '21-9' },
87 ];
88 var alignOptions = [
89 { label: __('Center', 'blockenberg'), value: 'center' },
90 { label: __('Left', 'blockenberg'), value: 'left' },
91 ];
92
93 function isYoutube(url) { return url && (url.includes('youtube.com') || url.includes('youtu.be')); }
94 function isVimeo(url) { return url && url.includes('vimeo.com'); }
95
96 function renderVideoPreview() {
97 var padPct = ASPECT_MAP[a.aspectRatio] || '56.25%';
98 var shadowStyle = a.videoShadow ? { boxShadow: '0 24px 64px rgba(0,0,0,0.25)' } : {};
99 return el('div', {
100 className: 'bkbg-vh-video-wrap bkbg-vh-video--' + a.aspectRatio,
101 style: Object.assign({ borderRadius: a.videoRadius + 'px' }, shadowStyle, { border: '1px solid ' + a.videoBorder })
102 },
103 el('div', { className: 'bkbg-vh-video-inner', style: { paddingBottom: padPct, position: 'relative' } },
104 a.videoUrl && (isYoutube(a.videoUrl) || isVimeo(a.videoUrl))
105 ? el('div', { className: 'bkbg-vh-video-embed', style: { position: 'absolute', inset: 0 } },
106 el('div', { style: { background: '#000', width: '100%', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff', fontSize: '14px', borderRadius: a.videoRadius + 'px' } },
107 el('span', { style: { opacity: .6 } }, '▶ ' + (isYoutube(a.videoUrl) ? 'YouTube' : 'Vimeo') + ' video will play on frontend')
108 )
109 )
110 : el('div', { style: { position: 'absolute', inset: 0, background: 'rgba(255,255,255,.06)', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: '12px', borderRadius: a.videoRadius + 'px' } },
111 el('span', { className: 'dashicons dashicons-video-alt3', style: { fontSize: '48px', width: '48px', height: '48px', color: a.accentColor } }),
112 el('span', { style: { color: 'rgba(255,255,255,.5)', fontSize: '13px' } }, a.videoUrl ? a.videoUrl.substring(0, 40) + '…' : __('No video URL set', 'blockenberg'))
113 ),
114 a.showPlayButton && el('div', { className: 'bkbg-vh-play-btn', style: { position: 'absolute', top: '50%', left: '50%', transform: 'translate(-50%,-50%)', width: '64px', height: '64px', background: a.accentColor, borderRadius: '50%', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer' } },
115 el('span', { style: { color:'#fff', fontSize:'24px', marginLeft:'4px' } }, '▶')
116 )
117 )
118 );
119 }
120
121 var blockProps = useBlockProps({
122 className: 'bkbg-vh-wrap bkbg-vh-style--' + a.style + ' bkbg-vh-layout--' + a.videoLayout + ' bkbg-vh-align--' + a.contentAlign,
123 style: wrapStyle(a)
124 });
125
126 var inspector = el(InspectorControls, {},
127 el(PanelBody, { title: __('Content', 'blockenberg'), initialOpen: true },
128 el(ToggleControl, {
129 label: __('Show Eyebrow', 'blockenberg'),
130 checked: a.showEyebrow,
131 __nextHasNoMarginBottom: true,
132 onChange: function (v) { set({ showEyebrow: v }); }
133 }),
134 a.showEyebrow && el(TextControl, {
135 label: __('Eyebrow Text', 'blockenberg'),
136 value: a.eyebrow,
137 onChange: function (v) { set({ eyebrow: v }); }
138 }),
139 el(ToggleControl, {
140 label: __('Show Subheading', 'blockenberg'),
141 checked: a.showSubheading,
142 __nextHasNoMarginBottom: true,
143 onChange: function (v) { set({ showSubheading: v }); }
144 }),
145 el(ToggleControl, {
146 label: __('Show Primary CTA', 'blockenberg'),
147 checked: a.showCta,
148 __nextHasNoMarginBottom: true,
149 onChange: function (v) { set({ showCta: v }); }
150 }),
151 a.showCta && el(TextControl, {
152 label: __('CTA Text', 'blockenberg'),
153 value: a.ctaText,
154 onChange: function (v) { set({ ctaText: v }); }
155 }),
156 a.showCta && el(TextControl, {
157 label: __('CTA URL', 'blockenberg'),
158 value: a.ctaUrl,
159 onChange: function (v) { set({ ctaUrl: v }); }
160 }),
161 el(ToggleControl, {
162 label: __('Show Secondary CTA', 'blockenberg'),
163 checked: a.showSecondaryCta,
164 __nextHasNoMarginBottom: true,
165 onChange: function (v) { set({ showSecondaryCta: v }); }
166 }),
167 a.showSecondaryCta && el(TextControl, {
168 label: __('Secondary Text', 'blockenberg'),
169 value: a.ctaSecondaryText,
170 onChange: function (v) { set({ ctaSecondaryText: v }); }
171 }),
172 a.showSecondaryCta && el(TextControl, {
173 label: __('Secondary URL', 'blockenberg'),
174 value: a.ctaSecondaryUrl,
175 onChange: function (v) { set({ ctaSecondaryUrl: v }); }
176 })
177 ),
178 el(PanelBody, { title: __('Video', 'blockenberg'), initialOpen: false },
179 el(TextControl, {
180 label: __('Video URL / Embed URL', 'blockenberg'),
181 value: a.videoUrl,
182 onChange: function (v) { set({ videoUrl: v }); },
183 help: __('YouTube, Vimeo, or direct embed URL', 'blockenberg')
184 }),
185 el('div', { style: { marginBottom: '12px' } },
186 el('label', { style: { display:'block', fontSize:'11px', fontWeight:'500', marginBottom:'6px', textTransform:'uppercase', letterSpacing:'.05em' } }, __('Poster / Thumbnail Image', 'blockenberg')),
187 el(MediaUpload, {
188 onSelect: function (m) { set({ posterUrl: m.url, posterId: m.id }); },
189 allowedTypes: ['image'],
190 value: a.posterId,
191 render: function (p) {
192 return el('div', {},
193 a.posterUrl && el('img', { src: a.posterUrl, style: { width: '100%', height: '80px', objectFit: 'cover', borderRadius: '6px', marginBottom: '6px' } }),
194 el(Button, { onClick: p.open, variant: 'secondary', isSmall: true }, a.posterUrl ? __('Change Poster', 'blockenberg') : __('Set Poster Image', 'blockenberg'))
195 );
196 }
197 })
198 ),
199 el(SelectControl, {
200 label: __('Video Layout', 'blockenberg'),
201 value: a.videoLayout,
202 options: layoutOptions,
203 onChange: function (v) { set({ videoLayout: v }); }
204 }),
205 el(SelectControl, {
206 label: __('Aspect Ratio', 'blockenberg'),
207 value: a.aspectRatio,
208 options: aspectOptions,
209 onChange: function (v) { set({ aspectRatio: v }); }
210 }),
211 el(ToggleControl, {
212 label: __('Show Play Button Overlay', 'blockenberg'),
213 checked: a.showPlayButton,
214 __nextHasNoMarginBottom: true,
215 onChange: function (v) { set({ showPlayButton: v }); }
216 }),
217 el(ToggleControl, {
218 label: __('Video Shadow', 'blockenberg'),
219 checked: a.videoShadow,
220 __nextHasNoMarginBottom: true,
221 onChange: function (v) { set({ videoShadow: v }); }
222 }),
223 el(RangeControl, {
224 label: __('Video Border Radius (px)', 'blockenberg'),
225 value: a.videoRadius,
226 onChange: function (v) { set({ videoRadius: v }); },
227 min: 0,
228 max: 32
229 })
230 ),
231 el(PanelBody, { title: __('Style & Layout', 'blockenberg'), initialOpen: false },
232 el(SelectControl, {
233 label: __('Section Style', 'blockenberg'),
234 value: a.style,
235 options: styleOptions,
236 onChange: function (v) { set({ style: v }); }
237 }),
238 el(SelectControl, {
239 label: __('Content Alignment', 'blockenberg'),
240 value: a.contentAlign,
241 options: alignOptions,
242 onChange: function (v) { set({ contentAlign: v }); }
243 }),
244 el(RangeControl, {
245 label: __('Max Content Width (px)', 'blockenberg'),
246 value: a.maxWidth,
247 onChange: function (v) { set({ maxWidth: v }); },
248 min: 480,
249 max: 1200,
250 step: 20
251 }),
252 el(RangeControl, {
253 label: __('Padding Top (px)', 'blockenberg'),
254 value: a.paddingTop,
255 onChange: function (v) { set({ paddingTop: v }); },
256 min: 0, max: 200
257 }),
258 el(RangeControl, {
259 label: __('Padding Bottom (px)', 'blockenberg'),
260 value: a.paddingBottom,
261 onChange: function (v) { set({ paddingBottom: v }); },
262 min: 0, max: 200
263 })
264 ),
265 el(PanelBody, { title: __('Typography', 'blockenberg'), initialOpen: false },
266 getTypoControl(__('Heading', 'blockenberg'), 'headingTypo', a, set),
267 getTypoControl(__('Subheading', 'blockenberg'), 'subTypo', a, set),
268 getTypoControl(__('Eyebrow', 'blockenberg'), 'eyebrowTypo', a, set),
269 getTypoControl(__('CTA Button', 'blockenberg'), 'ctaTypo', a, set)
270 ),
271 el(PanelColorSettings, {
272 title: __('Colors', 'blockenberg'),
273 initialOpen: false,
274 colorSettings: [
275 { label: __('Background', 'blockenberg'), value: a.bgColor, onChange: function (v) { set({ bgColor: v || '#0f172a' }); } },
276 { label: __('Accent Color', 'blockenberg'), value: a.accentColor, onChange: function (v) { set({ accentColor: v || '#6c3fb5' }); } },
277 { label: __('Heading', 'blockenberg'), value: a.headingColor, onChange: function (v) { set({ headingColor: v || '#ffffff' }); } },
278 { label: __('Subheading', 'blockenberg'), value: a.subColor, onChange: function (v) { set({ subColor: v || 'rgba(255,255,255,0.65)' }); } },
279 { label: __('Eyebrow', 'blockenberg'), value: a.eyebrowColor, onChange: function (v) { set({ eyebrowColor: v || '#a78bfa' }); } },
280 { label: __('Primary Button', 'blockenberg'), value: a.btnBg, onChange: function (v) { set({ btnBg: v || '#6c3fb5' }); } },
281 { label: __('Primary Button Text', 'blockenberg'), value: a.btnText, onChange: function (v) { set({ btnText: v || '#ffffff' }); } },
282 { label: __('Secondary Button Text', 'blockenberg'), value: a.btn2Text, onChange: function (v) { set({ btn2Text: v || 'rgba(255,255,255,0.85)' }); } },
283 { label: __('Video Border', 'blockenberg'), value: a.videoBorder, onChange: function (v) { set({ videoBorder: v || 'rgba(255,255,255,0.1)' }); } },
284 ]
285 })
286 );
287
288 var canvas = el('div', blockProps,
289 el('div', { className: 'bkbg-vh-inner' },
290 el('div', { className: 'bkbg-vh-content' },
291 a.showEyebrow && a.eyebrow && el('span', { className: 'bkbg-vh-eyebrow' }, a.eyebrow),
292 el(RichText, {
293 tagName: 'h1',
294 className: 'bkbg-vh-heading',
295 value: a.heading,
296 onChange: function (v) { set({ heading: v }); },
297 placeholder: __('Enter headline…', 'blockenberg'),
298 allowedFormats: ['core/bold', 'core/italic']
299 }),
300 a.showSubheading && el(RichText, {
301 tagName: 'p',
302 className: 'bkbg-vh-sub',
303 value: a.subheading,
304 onChange: function (v) { set({ subheading: v }); },
305 placeholder: __('Enter subheading…', 'blockenberg'),
306 allowedFormats: ['core/bold', 'core/italic']
307 }),
308 (a.showCta || a.showSecondaryCta) && el('div', { className: 'bkbg-vh-ctas' },
309 a.showCta && el('a', { className: 'bkbg-vh-btn bkbg-vh-btn--primary', href: '#', onClick: function (e) { e.preventDefault(); } }, a.ctaText),
310 a.showSecondaryCta && el('a', { className: 'bkbg-vh-btn bkbg-vh-btn--secondary', href: '#', onClick: function (e) { e.preventDefault(); } }, a.ctaSecondaryText)
311 )
312 ),
313 el('div', { className: 'bkbg-vh-video-col' },
314 renderVideoPreview()
315 )
316 )
317 );
318
319 return el('div', {}, inspector, canvas);
320 },
321
322 save: function (props) {
323 var a = props.attributes;
324 var blockProps = useBlockProps.save({
325 className: 'bkbg-vh-wrap bkbg-vh-style--' + a.style + ' bkbg-vh-layout--' + a.videoLayout + ' bkbg-vh-align--' + a.contentAlign,
326 style: wrapStyle(a)
327 });
328 var padPct = ASPECT_MAP[a.aspectRatio] || '56.25%';
329 var shadowStyle = a.videoShadow ? { boxShadow: '0 24px 64px rgba(0,0,0,0.25)' } : {};
330
331 return el('div', blockProps,
332 el('div', { className: 'bkbg-vh-inner' },
333 el('div', { className: 'bkbg-vh-content' },
334 a.showEyebrow && a.eyebrow && el('span', { className: 'bkbg-vh-eyebrow' }, a.eyebrow),
335 el(RichText.Content, { tagName: 'h1', className: 'bkbg-vh-heading', value: a.heading }),
336 a.showSubheading && el(RichText.Content, { tagName: 'p', className: 'bkbg-vh-sub', value: a.subheading }),
337 (a.showCta || a.showSecondaryCta) && el('div', { className: 'bkbg-vh-ctas' },
338 a.showCta && el('a', { className: 'bkbg-vh-btn bkbg-vh-btn--primary', href: a.ctaUrl }, a.ctaText),
339 a.showSecondaryCta && el('a', { className: 'bkbg-vh-btn bkbg-vh-btn--secondary', href: a.ctaSecondaryUrl }, a.ctaSecondaryText)
340 )
341 ),
342 el('div', { className: 'bkbg-vh-video-col' },
343 el('div', {
344 className: 'bkbg-vh-video-wrap bkbg-vh-video--' + a.aspectRatio,
345 style: Object.assign({ borderRadius: a.videoRadius + 'px' }, shadowStyle, { border: '1px solid ' + a.videoBorder })
346 },
347 el('div', { className: 'bkbg-vh-video-inner', style: { paddingBottom: padPct, position: 'relative' } },
348 el('iframe', {
349 className: 'bkbg-vh-iframe',
350 src: a.videoUrl,
351 frameBorder: '0',
352 allow: 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture',
353 allowFullScreen: true,
354 style: { position: 'absolute', inset: 0, width: '100%', height: '100%', borderRadius: a.videoRadius + 'px' }
355 }),
356 a.showPlayButton && a.posterUrl && el('div', {
357 className: 'bkbg-vh-poster',
358 'data-video': a.videoUrl,
359 style: { position: 'absolute', inset: 0, cursor: 'pointer' }
360 },
361 el('img', { src: a.posterUrl, alt: '', style: { width: '100%', height: '100%', objectFit: 'cover', borderRadius: a.videoRadius + 'px' } }),
362 el('div', { className: 'bkbg-vh-play-btn' },
363 el('span', {}, '▶')
364 )
365 )
366 )
367 )
368 )
369 )
370 );
371 }
372 });
373 }() );
374