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 / embed-preview / index.js

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

294 lines 16.9 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 Fragment = wp.element.Fragment;
4 var useState = wp.element.useState;
5 var __ = wp.i18n.__;
6 var registerBlockType = wp.blocks.registerBlockType;
7 var InspectorControls = wp.blockEditor.InspectorControls;
8 var MediaUpload = wp.blockEditor.MediaUpload;
9 var MediaUploadCheck = wp.blockEditor.MediaUploadCheck;
10 var useBlockProps = wp.blockEditor.useBlockProps;
11 var RichText = wp.blockEditor.RichText;
12 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
13 var PanelBody = wp.components.PanelBody;
14 var ToggleControl = wp.components.ToggleControl;
15 var RangeControl = wp.components.RangeControl;
16 var SelectControl = wp.components.SelectControl;
17 var TextControl = wp.components.TextControl;
18 var Button = wp.components.Button;
19
20 var _epTC, _epTV;
21 function _tc() { return _epTC || (_epTC = window.bkbgTypographyControl); }
22 function _tv(t, p) { return (_epTV || (_epTV = window.bkbgTypoCssVars)) ? _epTV(t, p) : {}; }
23
24 var PROVIDER_OPTIONS = [
25 { label: 'Custom / Other', value: 'custom' },
26 { label: 'Figma', value: 'figma' },
27 { label: 'Loom', value: 'loom' },
28 { label: 'YouTube', value: 'youtube' },
29 { label: 'Typeform', value: 'typeform' },
30 { label: 'Calendly', value: 'calendly' },
31 { label: 'Miro', value: 'miro' },
32 { label: 'Notion', value: 'notion' },
33 { label: 'Airtable', value: 'airtable' },
34 ];
35
36 var ASPECT_OPTIONS = [
37 { label: '16:9 (widescreen)', value: '16-9' },
38 { label: '4:3 (classic)', value: '4-3' },
39 { label: '1:1 (square)', value: '1-1' },
40 { label: '3:2', value: '3-2' },
41 { label: '21:9 (ultra-wide)', value: '21-9' },
42 { label: 'Custom height', value: 'custom' },
43 ];
44
45 var CTA_STYLE_OPTIONS = [
46 { label: 'Filled', value: 'filled' },
47 { label: 'Outline', value: 'outline' },
48 { label: 'Ghost', value: 'ghost' },
49 ];
50
51 var PROVIDER_ICONS = {
52 figma: '🎨',
53 loom: '🎥',
54 youtube: '',
55 typeform: '📋',
56 calendly: '�
57 ',
58 miro: '🗂',
59 notion: '📄',
60 airtable: '🗃',
61 custom: '🔗',
62 };
63
64 var ASPECT_RATIOS = {
65 '16-9': 56.25,
66 '4-3': 75,
67 '1-1': 100,
68 '3-2': 66.67,
69 '21-9': 42.86,
70 };
71
72 function hexToRgba(hex, opacity) {
73 var r = parseInt((hex || '#000000').substr(1, 2), 16);
74 var g = parseInt((hex || '#000000').substr(3, 2), 16);
75 var b = parseInt((hex || '#000000').substr(5, 2), 16);
76 return 'rgba(' + r + ',' + g + ',' + b + ',' + (opacity / 100) + ')';
77 }
78
79 registerBlockType('blockenberg/embed-preview', {
80 title: __('Embed Preview', 'blockenberg'),
81 icon: 'embed-generic',
82 category: 'bkbg-media',
83 description: __('Click-to-load embed with custom thumbnail and CTA overlay.', 'blockenberg'),
84
85 edit: function (props) {
86 var a = props.attributes;
87 var set = props.setAttributes;
88 var blockProps = useBlockProps({ style: Object.assign({}, _tv(a.typoTitle || {}, '--bkbg-ep-ttl-'), _tv(a.typoDesc || {}, '--bkbg-ep-dsc-'), _tv(a.typoCta || {}, '--bkbg-ep-cta-')) });
89
90 var paddingPct = a.aspectRatio !== 'custom' ? ASPECT_RATIOS[a.aspectRatio] || 56.25 : null;
91
92 var containerStyle = {
93 maxWidth: a.maxWidth + 'px',
94 margin: '0 auto',
95 borderRadius: a.borderRadius + 'px',
96 overflow: 'hidden',
97 border: '1px solid ' + a.borderColor,
98 position: 'relative',
99 };
100
101 if (!a.thumbnailUrl) {
102 containerStyle.background = '#1e293b';
103 }
104
105 var heightStyle = paddingPct
106 ? { paddingBottom: paddingPct + '%', height: 0, position: 'relative' }
107 : { height: a.customHeight + 'px', position: 'relative' };
108
109 var overlayBgColor = hexToRgba(a.overlayBg, a.overlayOpacity);
110
111 return el(Fragment, null,
112 el(InspectorControls, null,
113
114 // Content
115 el(PanelBody, { title: 'Embed Content', initialOpen: true },
116 el(SelectControl, { label: 'Provider', value: a.embedProvider, options: PROVIDER_OPTIONS, onChange: function (v) { set({ embedProvider: v }); }, __nextHasNoMarginBottom: true }),
117 el('div', { style: { height: 10 } }),
118 el(TextControl, { label: 'Embed URL', value: a.embedUrl, placeholder: 'https://...', onChange: function (v) { set({ embedUrl: v }); }, __nextHasNoMarginBottom: true }),
119 el('div', { style: { height: 10 } }),
120 el(ToggleControl, { label: 'Show title', checked: a.showTitle, onChange: function (v) { set({ showTitle: v }); }, __nextHasNoMarginBottom: true }),
121 a.showTitle && el(Fragment, null,
122 el('div', { style: { height: 6 } }),
123 el(TextControl, { label: 'Title', value: a.embedTitle, onChange: function (v) { set({ embedTitle: v }); }, __nextHasNoMarginBottom: true })
124 ),
125 el('div', { style: { height: 8 } }),
126 el(ToggleControl, { label: 'Show description', checked: a.showDescription, onChange: function (v) { set({ showDescription: v }); }, __nextHasNoMarginBottom: true }),
127 a.showDescription && el(Fragment, null,
128 el('div', { style: { height: 6 } }),
129 el(TextControl, { label: 'Description', value: a.description, onChange: function (v) { set({ description: v }); }, __nextHasNoMarginBottom: true })
130 ),
131 el('div', { style: { height: 8 } }),
132 el(TextControl, { label: 'CTA Button Label', value: a.ctaLabel, onChange: function (v) { set({ ctaLabel: v }); }, __nextHasNoMarginBottom: true }),
133 el('div', { style: { height: 10 } }),
134 el(SelectControl, { label: 'CTA Style', value: a.ctaStyle, options: CTA_STYLE_OPTIONS, onChange: function (v) { set({ ctaStyle: v }); }, __nextHasNoMarginBottom: true }),
135 el('div', { style: { height: 8 } }),
136 el(ToggleControl, { label: 'Show provider badge', checked: a.showBrand, onChange: function (v) { set({ showBrand: v }); }, __nextHasNoMarginBottom: true }),
137 el('div', { style: { height: 8 } }),
138 el(ToggleControl, { label: 'Show loading bar', checked: a.showLoadingBar, onChange: function (v) { set({ showLoadingBar: v }); }, __nextHasNoMarginBottom: true }),
139 el('div', { style: { height: 8 } }),
140 el(ToggleControl, { label: 'Show privacy note', checked: a.showPrivacyNote, onChange: function (v) { set({ showPrivacyNote: v }); }, __nextHasNoMarginBottom: true }),
141 a.showPrivacyNote && el(Fragment, null,
142 el('div', { style: { height: 6 } }),
143 el(TextControl, { label: 'Privacy note text', value: a.privacyNote, onChange: function (v) { set({ privacyNote: v }); }, __nextHasNoMarginBottom: true })
144 )
145 ),
146
147 // Thumbnail
148 el(PanelBody, { title: 'Thumbnail', initialOpen: false },
149 el(MediaUploadCheck, null,
150 el(MediaUpload, {
151 onSelect: function (media) { set({ thumbnailUrl: media.url, thumbnailId: media.id }); },
152 allowedTypes: ['image'],
153 value: a.thumbnailId,
154 render: function (ref) {
155 return el(Button, {
156 onClick: ref.open,
157 variant: a.thumbnailUrl ? 'secondary' : 'primary',
158 __nextHasNoMarginBottom: true,
159 }, a.thumbnailUrl ? 'Change Thumbnail' : 'Set Thumbnail');
160 }
161 })
162 ),
163 a.thumbnailUrl && el(Fragment, null,
164 el('img', { src: a.thumbnailUrl, alt: '', style: { width: '100%', borderRadius: 6, marginTop: 8 } }),
165 el(Button, { onClick: function () { set({ thumbnailUrl: '', thumbnailId: 0 }); }, isDestructive: true, variant: 'link', __nextHasNoMarginBottom: true, style: { marginTop: 4 } }, 'Remove Thumbnail')
166 )
167 ),
168
169 // Layout
170 el(PanelBody, { title: 'Layout', initialOpen: false },
171 el(SelectControl, { label: 'Aspect ratio', value: a.aspectRatio, options: ASPECT_OPTIONS, onChange: function (v) { set({ aspectRatio: v }); }, __nextHasNoMarginBottom: true }),
172 a.aspectRatio === 'custom' && el(Fragment, null,
173 el('div', { style: { height: 10 } }),
174 el(RangeControl, { label: 'Custom height (px)', value: a.customHeight, min: 200, max: 1200, onChange: function (v) { set({ customHeight: v }); }, __nextHasNoMarginBottom: true })
175 ),
176 el('div', { style: { height: 10 } }),
177 el(RangeControl, { label: 'Max width (px)', value: a.maxWidth, min: 400, max: 1400, onChange: function (v) { set({ maxWidth: v }); }, __nextHasNoMarginBottom: true }),
178 el('div', { style: { height: 10 } }),
179 el(RangeControl, { label: 'Border radius (px)', value: a.borderRadius, min: 0, max: 32, onChange: function (v) { set({ borderRadius: v }); }, __nextHasNoMarginBottom: true }),
180 el('div', { style: { height: 10 } }),
181 el(RangeControl, { label: 'Overlay opacity (%)', value: a.overlayOpacity, min: 0, max: 95, onChange: function (v) { set({ overlayOpacity: v }); }, __nextHasNoMarginBottom: true }),
182 el('div', { style: { height: 10 } }),
183 el(TextControl, { label: 'iframe sandbox (advanced)', value: a.iframeSandbox, onChange: function (v) { set({ iframeSandbox: v }); }, __nextHasNoMarginBottom: true })
184 ),
185
186 // Colors
187 el( PanelBody, { title: __( 'Typography', 'blockenberg' ), initialOpen: false },
188 _tc() && el(_tc(), { label: __('Title'), typo: a.typoTitle || {}, onChange: function (v) { set({ typoTitle: v }); }, defaultSize: a.titleSize || 18 }),
189 _tc() && el(_tc(), { label: __('Description'), typo: a.typoDesc || {}, onChange: function (v) { set({ typoDesc: v }); }, defaultSize: a.descSize || 14 }),
190 _tc() && el(_tc(), { label: __('CTA Button'), typo: a.typoCta || {}, onChange: function (v) { set({ typoCta: v }); }, defaultSize: a.ctaLabelSize || 14 })
191 ),
192 el(PanelColorSettings, {
193 title: 'Colors',
194 initialOpen: false,
195 colorSettings: [
196 { label: 'Overlay Color', value: a.overlayBg, onChange: function (v) { set({ overlayBg: v || '#0f172a' }); } },
197 { label: 'CTA Background', value: a.ctaBg, onChange: function (v) { set({ ctaBg: v || '#6366f1' }); } },
198 { label: 'CTA Text', value: a.ctaColor, onChange: function (v) { set({ ctaColor: v || '#ffffff' }); } },
199 { label: 'Title Color', value: a.titleColor, onChange: function (v) { set({ titleColor: v || '#f8fafc' }); } },
200 { label: 'Description Color',value: a.descColor, onChange: function (v) { set({ descColor: v || '#cbd5e1' }); } },
201 { label: 'Privacy Note Color',value: a.privacyColor,onChange: function (v) { set({ privacyColor: v || '#94a3b8' }); } },
202 { label: 'Border Color', value: a.borderColor, onChange: function (v) { set({ borderColor: v || '#e5e7eb' }); } },
203 ]
204 })
205 ),
206
207 // ── Editor Preview ──
208 el('div', blockProps,
209 el('div', { style: containerStyle },
210 el('div', { style: Object.assign({ position: 'relative' }, heightStyle) },
211 // Thumbnail
212 a.thumbnailUrl && el('img', {
213 src: a.thumbnailUrl,
214 alt: '',
215 style: {
216 position: 'absolute', inset: 0,
217 width: '100%', height: '100%',
218 objectFit: 'cover',
219 }
220 }),
221 // Dark overlay
222 el('div', {
223 style: {
224 position: 'absolute', inset: 0,
225 background: overlayBgColor,
226 display: 'flex',
227 flexDirection: 'column',
228 alignItems: 'center',
229 justifyContent: 'center',
230 gap: 14,
231 padding: 24,
232 textAlign: 'center',
233 }
234 },
235 // Provider badge
236 a.showBrand && el('div', {
237 style: {
238 position: 'absolute', top: 14, left: 14,
239 background: 'rgba(255,255,255,0.12)',
240 borderRadius: 8,
241 padding: '4px 10px',
242 fontSize: 13,
243 color: '#fff',
244 }
245 }, (PROVIDER_ICONS[a.embedProvider] || '🔗') + ' ' + (a.embedProvider.charAt(0).toUpperCase() + a.embedProvider.slice(1))),
246 // Title
247 a.showTitle && el('p', {
248 className: 'bkbg-ep-title',
249 style: {
250 margin: 0,
251 color: a.titleColor,
252 }
253 }, a.embedTitle),
254 // Description
255 a.showDescription && a.description && el('p', {
256 className: 'bkbg-ep-description',
257 style: { margin: 0, color: a.descColor }
258 }, a.description),
259 // CTA
260 el('button', {
261 className: 'bkbg-ep-cta',
262 style: {
263 background: a.ctaStyle === 'filled' ? a.ctaBg : 'transparent',
264 color: a.ctaStyle === 'filled' ? a.ctaColor : a.ctaBg,
265 border: a.ctaStyle === 'ghost' ? 'none' : '2px solid ' + a.ctaBg,
266 cursor: 'pointer',
267 pointerEvents: 'none',
268 }
269 }, a.ctaLabel),
270 // Privacy note
271 a.showPrivacyNote && a.privacyNote && el('p', {
272 style: {
273 margin: 0, fontSize: 11, color: a.privacyColor,
274 position: 'absolute', bottom: 10,
275 }
276 }, '🔒 ' + a.privacyNote)
277 )
278 )
279 ),
280 !a.embedUrl && el('p', {
281 style: { textAlign: 'center', fontSize: 12, color: '#9ca3af', marginTop: 8 }
282 }, '⚙ Add an embed URL in the inspector panel.')
283 )
284 );
285 },
286
287 save: function (props) {
288 return el('div', useBlockProps.save(),
289 el('div', { className: 'bkbg-ep-app', 'data-opts': JSON.stringify(props.attributes) })
290 );
291 }
292 });
293 }() );
294