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 / image-collage / index.js

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

311 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 Fragment = wp.element.Fragment;
4 var __ = wp.i18n.__;
5 var registerBlockType = wp.blocks.registerBlockType;
6 var InspectorControls = wp.blockEditor.InspectorControls;
7 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
8 var MediaUpload = wp.blockEditor.MediaUpload;
9 var MediaUploadCheck = wp.blockEditor.MediaUploadCheck;
10 var useBlockProps = wp.blockEditor.useBlockProps;
11 var PanelBody = wp.components.PanelBody;
12 var RangeControl = wp.components.RangeControl;
13 var ToggleControl = wp.components.ToggleControl;
14 var TextControl = wp.components.TextControl;
15 var SelectControl = wp.components.SelectControl;
16 var Button = wp.components.Button;
17
18 var _TypographyControl, _typoCssVars;
19 function getTypographyControl() { return _TypographyControl || (_TypographyControl = window.bkbgTypographyControl); }
20 function getTypoCssVars() { return _typoCssVars || (_typoCssVars = window.bkbgTypoCssVars); }
21
22 var PRESET_OPTIONS = [
23 { label: __('Scattered', 'blockenberg'), value: 'scattered' },
24 { label: __('Stack', 'blockenberg'), value: 'stack' },
25 { label: __('Grid', 'blockenberg'), value: 'grid' },
26 ];
27 var FRAME_OPTIONS = [
28 { label: __('None', 'blockenberg'), value: 'none' },
29 { label: __('Shadow', 'blockenberg'), value: 'shadow' },
30 { label: __('Polaroid', 'blockenberg'), value: 'polaroid' },
31 ];
32 var ALIGN_OPTIONS = [
33 { label: __('Left', 'blockenberg'), value: 'left' },
34 { label: __('Center', 'blockenberg'), value: 'center' },
35 { label: __('Right', 'blockenberg'), value: 'right' },
36 ];
37 var OVERLAY_POS_OPTIONS = [
38 { label: __('Bottom right', 'blockenberg'), value: 'bottom-right' },
39 { label: __('Bottom left', 'blockenberg'), value: 'bottom-left' },
40 { label: __('Top right', 'blockenberg'), value: 'top-right' },
41 { label: __('Top left', 'blockenberg'), value: 'top-left' },
42 { label: __('Center', 'blockenberg'), value: 'center' },
43 ];
44
45 /* Preset position/rotation tables */
46 var PRESETS = {
47 scattered: [
48 { rotation: -6, offsetX: 0, offsetY: 0, scale: 1.0, zIndex: 1 },
49 { rotation: 4, offsetX: 30, offsetY: 15, scale: 0.9, zIndex: 2 },
50 { rotation: -2, offsetX: 55, offsetY: 5, scale: 0.85, zIndex: 3 },
51 { rotation: 7, offsetX: 15, offsetY: 40, scale: 0.8, zIndex: 2 },
52 { rotation: -4, offsetX: 45, offsetY: 35, scale: 0.75, zIndex: 1 },
53 ],
54 stack: [
55 { rotation: -8, offsetX: 0, offsetY: 0, scale: 1.0, zIndex: 1 },
56 { rotation: 4, offsetX: 5, offsetY: 5, scale: 1.0, zIndex: 2 },
57 { rotation: -2, offsetX: 2, offsetY: 2, scale: 1.0, zIndex: 3 },
58 { rotation: 6, offsetX: 4, offsetY: 4, scale: 1.0, zIndex: 2 },
59 { rotation: -5, offsetX: 1, offsetY: 1, scale: 1.0, zIndex: 1 },
60 ],
61 grid: [
62 { rotation: 0, offsetX: 0, offsetY: 0, scale: 1.0, zIndex: 1 },
63 { rotation: 0, offsetX: 52, offsetY: 0, scale: 1.0, zIndex: 1 },
64 { rotation: 0, offsetX: 0, offsetY: 52, scale: 1.0, zIndex: 1 },
65 { rotation: 0, offsetX: 52, offsetY: 52, scale: 1.0, zIndex: 1 },
66 { rotation: 0, offsetX: 26, offsetY: 26, scale: 1.0, zIndex: 2 },
67 ],
68 };
69
70 function makeId() { return 'ic' + Math.random().toString(36).substr(2, 6); }
71
72 function imgStyle(img, a) {
73 var w = img.w || 240;
74 var h = img.h || 180;
75 var fp = img.frame === 'polaroid' ? a.framePadding : (img.frame === 'shadow' ? 0 : 0);
76 var style = {
77 position: 'absolute',
78 left: img.offsetX + '%',
79 top: img.offsetY + '%',
80 width: w + 'px',
81 height: h + 'px',
82 transform: 'rotate(' + img.rotation + 'deg) scale(' + img.scale + ')',
83 zIndex: img.zIndex,
84 transition: a.hoverLift ? 'transform 0.3s ease, box-shadow 0.3s ease' : undefined,
85 overflow: 'hidden',
86 background: '#e5e7eb',
87 };
88 var frame = img.frame !== 'inherit' ? img.frame : 'none';
89 if (frame === 'polaroid') {
90 Object.assign(style, {
91 padding: a.framePadding + 'px',
92 paddingBottom: (a.framePadding * 3) + 'px',
93 background: a.frameColor,
94 boxShadow: '0 ' + (a.shadowIntensity / 5) + 'px ' + a.shadowIntensity + 'px rgba(0,0,0,0.18)',
95 overflow: 'visible',
96 });
97 } else if (frame === 'shadow') {
98 Object.assign(style, {
99 boxShadow: '0 ' + (a.shadowIntensity / 5) + 'px ' + a.shadowIntensity + 'px rgba(0,0,0,0.18)',
100 });
101 }
102 return style;
103 }
104
105 function overlayPosStyle(pos) {
106 var map = {
107 'bottom-right': { bottom: '20px', right: '20px' },
108 'bottom-left': { bottom: '20px', left: '20px' },
109 'top-right': { top: '20px', right: '20px' },
110 'top-left': { top: '20px', left: '20px' },
111 'center': { top: '50%', left: '50%', transform: 'translate(-50%,-50%)' },
112 };
113 return map[pos] || map['bottom-right'];
114 }
115
116 registerBlockType('blockenberg/image-collage', {
117 edit: function (props) {
118 var a = props.attributes;
119 var setAttributes = props.setAttributes;
120 var blockProps = useBlockProps({ style: (function () {
121 var s = { paddingTop: a.paddingTop + 'px', paddingBottom: a.paddingBottom + 'px', backgroundColor: a.bgColor || undefined };
122 var fn = getTypoCssVars();
123 if (fn) { Object.assign(s, fn(a.headlineTypo, '--bkbg-ic-ht-'), fn(a.subtextTypo, '--bkbg-ic-st-')); }
124 return s;
125 })() });
126
127 function setImg(id, patch) {
128 setAttributes({ images: a.images.map(function (img) { return img.id === id ? Object.assign({}, img, patch) : img; }) });
129 }
130 function addImg() {
131 if (a.images.length >= 5) return;
132 var idx = a.images.length;
133 var pre = PRESETS.scattered[idx] || PRESETS.scattered[0];
134 setAttributes({ images: a.images.concat([Object.assign({ id: makeId(), url: '', mediaId: 0, frame: 'inherit', w: 240, h: 180 }, pre)]) });
135 }
136 function removeImg(id) {
137 if (a.images.length <= 1) return;
138 setAttributes({ images: a.images.filter(function (img) { return img.id !== id; }) });
139 }
140 function applyPreset(preset) {
141 var pre = PRESETS[preset] || PRESETS.scattered;
142 setAttributes({
143 preset: preset,
144 images: a.images.map(function (img, i) {
145 return Object.assign({}, img, pre[i] || pre[0]);
146 })
147 });
148 }
149
150 var canvasStyle = {
151 position: 'relative',
152 height: a.canvasHeight + 'px',
153 maxWidth: a.canvasMaxWidth + 'px',
154 margin: a.align === 'center' ? '0 auto' : (a.align === 'right' ? '0 0 0 auto' : '0'),
155 overflow: 'visible',
156 };
157
158 return el(Fragment, null,
159 el(InspectorControls, null,
160 el(PanelBody, { title: __('Preset', 'blockenberg'), initialOpen: true },
161 el(SelectControl, { label: __('Layout preset', 'blockenberg'), value: a.preset, options: PRESET_OPTIONS, onChange: applyPreset }),
162 el(SelectControl, { label: __('Align canvas', 'blockenberg'), value: a.align, options: ALIGN_OPTIONS, onChange: function (v) { setAttributes({ align: v }); } })
163 ),
164 el(PanelBody, { title: __('Canvas', 'blockenberg'), initialOpen: false },
165 el(RangeControl, { label: __('Canvas height (px)', 'blockenberg'), value: a.canvasHeight, min: 200, max: 900, onChange: function (v) { setAttributes({ canvasHeight: v }); } }),
166 el(RangeControl, { label: __('Max width (px)', 'blockenberg'), value: a.canvasMaxWidth, min: 300, max: 1400, onChange: function (v) { setAttributes({ canvasMaxWidth: v }); } })
167 ),
168 el(PanelBody, { title: __('Frame & Effects', 'blockenberg'), initialOpen: false },
169 el(RangeControl, { label: __('Shadow intensity', 'blockenberg'), value: a.shadowIntensity, min: 0, max: 60, onChange: function (v) { setAttributes({ shadowIntensity: v }); } }),
170 el(TextControl, { label: __('Frame padding (px)', 'blockenberg'), type: 'number', value: a.framePadding, onChange: function (v) { setAttributes({ framePadding: parseInt(v, 10) || 0 }); } }),
171 el(ToggleControl, { label: __('Hover lift effect', 'blockenberg'), checked: a.hoverLift, onChange: function (v) { setAttributes({ hoverLift: v }); }, __nextHasNoMarginBottom: true }),
172 el(ToggleControl, { label: __('Animate in on scroll', 'blockenberg'), checked: a.animateIn, onChange: function (v) { setAttributes({ animateIn: v }); }, __nextHasNoMarginBottom: true })
173 ),
174 el(PanelBody, { title: __('Overlay Card', 'blockenberg'), initialOpen: false },
175 el(ToggleControl, { label: __('Show overlay card', 'blockenberg'), checked: a.showOverlayCard, onChange: function (v) { setAttributes({ showOverlayCard: v }); }, __nextHasNoMarginBottom: true }),
176 a.showOverlayCard && el(Fragment, null,
177 el(TextControl, { label: __('Headline', 'blockenberg'), value: a.overlayCardText, onChange: function (v) { setAttributes({ overlayCardText: v }); } }),
178 el(TextControl, { label: __('Subtext', 'blockenberg'), value: a.overlayCardSubtext, onChange: function (v) { setAttributes({ overlayCardSubtext: v }); } }),
179 el(SelectControl, { label: __('Position', 'blockenberg'), value: a.overlayCardPos, options: OVERLAY_POS_OPTIONS, onChange: function (v) { setAttributes({ overlayCardPos: v }); } })
180 )
181 ),
182 a.showOverlayCard && el(PanelColorSettings, {
183 title: __('Overlay Card Colors', 'blockenberg'), initialOpen: false,
184 colorSettings: [
185 { value: a.overlayCardBg, onChange: function (v) { setAttributes({ overlayCardBg: v || '' }); }, label: __('Card background', 'blockenberg') },
186 { value: a.overlayCardColor, onChange: function (v) { setAttributes({ overlayCardColor: v || '' }); }, label: __('Text color', 'blockenberg') },
187 { value: a.overlayCardAccent, onChange: function (v) { setAttributes({ overlayCardAccent: v || '' }); }, label: __('Accent line', 'blockenberg') },
188 ]
189 }),
190 el(PanelBody, { title: __('Typography', 'blockenberg'), initialOpen: false },
191 getTypographyControl() && el(getTypographyControl(), { label: __('Headline', 'blockenberg'), value: a.headlineTypo, onChange: function (v) { setAttributes({ headlineTypo: v }); } }),
192 getTypographyControl() && el(getTypographyControl(), { label: __('Subtext', 'blockenberg'), value: a.subtextTypo, onChange: function (v) { setAttributes({ subtextTypo: v }); } })
193 ),
194 el(PanelColorSettings, {
195 title: __('Colors', 'blockenberg'), initialOpen: false,
196 colorSettings: [
197 { value: a.frameColor, onChange: function (v) { setAttributes({ frameColor: v || '' }); }, label: __('Frame / polaroid bg', 'blockenberg') },
198 { value: a.bgColor, onChange: function (v) { setAttributes({ bgColor: v || '' }); }, label: __('Section background', 'blockenberg') },
199 ]
200 }),
201 el(PanelBody, { title: __('Spacing', 'blockenberg'), initialOpen: false },
202 el(RangeControl, { label: __('Padding top (px)', 'blockenberg'), value: a.paddingTop, min: 0, max: 200, onChange: function (v) { setAttributes({ paddingTop: v }); } }),
203 el(RangeControl, { label: __('Padding bottom (px)', 'blockenberg'), value: a.paddingBottom, min: 0, max: 200, onChange: function (v) { setAttributes({ paddingBottom: v }); } })
204 ),
205 el(PanelBody, { title: __('Images', 'blockenberg'), initialOpen: true },
206 a.images.map(function (img, idx) {
207 return el(PanelBody, { key: img.id, title: (img.url ? __('Image', 'blockenberg') + ' ' + (idx + 1) : __('Empty slot', 'blockenberg') + ' ' + (idx + 1)), initialOpen: false },
208 el(MediaUploadCheck, null,
209 el(MediaUpload, {
210 onSelect: function (media) { setImg(img.id, { url: media.url, mediaId: media.id, w: media.width || 240, h: media.height || 180 }); },
211 allowedTypes: ['image'],
212 value: img.mediaId,
213 render: function (p) {
214 return el('div', { style: { marginBottom: '12px' } },
215 img.url && el('img', { src: img.url, style: { width: '100%', height: '80px', objectFit: 'cover', borderRadius: '6px', marginBottom: '6px' } }),
216 el(Button, { onClick: p.open, variant: img.url ? 'secondary' : 'primary', size: 'compact' }, img.url ? __('Replace image', 'blockenberg') : __('Select image', 'blockenberg'))
217 );
218 }
219 })
220 ),
221 el(SelectControl, { label: __('Frame', 'blockenberg'), value: img.frame, options: [{ label: __('Use global', 'blockenberg'), value: 'inherit' }].concat(FRAME_OPTIONS), onChange: function (v) { setImg(img.id, { frame: v }); } }),
222 el(RangeControl, { label: __('Rotation (°)', 'blockenberg'), value: img.rotation, min: -20, max: 20, onChange: function (v) { setImg(img.id, { rotation: v }); } }),
223 el(RangeControl, { label: __('Offset X (%)', 'blockenberg'), value: img.offsetX, min: 0, max: 80, onChange: function (v) { setImg(img.id, { offsetX: v }); } }),
224 el(RangeControl, { label: __('Offset Y (%)', 'blockenberg'), value: img.offsetY, min: 0, max: 80, onChange: function (v) { setImg(img.id, { offsetY: v }); } }),
225 el(RangeControl, { label: __('Scale (%)', 'blockenberg'), value: Math.round(img.scale * 100), min: 50, max: 150, onChange: function (v) { setImg(img.id, { scale: v / 100 }); } }),
226 el(RangeControl, { label: __('Z-index', 'blockenberg'), value: img.zIndex, min: 1, max: 10, onChange: function (v) { setImg(img.id, { zIndex: v }); } }),
227 el(RangeControl, { label: __('Width (px)', 'blockenberg'), value: img.w, min: 80, max: 600, onChange: function (v) { setImg(img.id, { w: v }); } }),
228 el(RangeControl, { label: __('Height (px)', 'blockenberg'), value: img.h, min: 60, max: 500, onChange: function (v) { setImg(img.id, { h: v }); } }),
229 a.images.length > 1 && el(Button, { onClick: function () { removeImg(img.id); }, variant: 'tertiary', isDestructive: true, size: 'compact' }, __('Remove', 'blockenberg'))
230 );
231 }),
232 a.images.length < 5 && el(Button, { onClick: addImg, variant: 'primary', style: { marginTop: '8px' } }, __('+ Add Image', 'blockenberg'))
233 )
234 ),
235
236 el('div', blockProps,
237 el('div', { style: canvasStyle },
238 a.images.map(function (img) {
239 return el('div', { key: img.id, style: imgStyle(img, a) },
240 img.url
241 ? el('img', { src: img.url, alt: '', style: { width: '100%', height: '100%', objectFit: 'cover', display: 'block' } })
242 : el('div', { style: { width: '100%', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#9ca3af', fontSize: '12px' } }, __('No image', 'blockenberg'))
243 );
244 }),
245 a.showOverlayCard && el('div', {
246 style: Object.assign({ position: 'absolute', zIndex: 20, background: a.overlayCardBg || '#fff', color: a.overlayCardColor || '#1e293b', padding: '16px 22px', borderRadius: '12px', boxShadow: '0 8px 32px rgba(0,0,0,0.12)', maxWidth: '260px', borderTop: '4px solid ' + (a.overlayCardAccent || '#6c3fb5') }, overlayPosStyle(a.overlayCardPos))
247 },
248 a.overlayCardText && el('p', { className: 'bkbg-ic-headline', style: { margin: '0 0 4px' } }, a.overlayCardText),
249 a.overlayCardSubtext && el('p', { className: 'bkbg-ic-subtext', style: { margin: 0, opacity: 0.75 } }, a.overlayCardSubtext)
250 )
251 )
252 )
253 );
254 },
255
256 save: function (props) {
257 var a = props.attributes;
258 var blockProps = wp.blockEditor.useBlockProps.save({ className: 'bkbg-image-collage-wrap' });
259
260 var canvasStyle = {
261 position: 'relative',
262 height: a.canvasHeight + 'px',
263 maxWidth: a.canvasMaxWidth + 'px',
264 margin: a.align === 'center' ? '0 auto' : (a.align === 'right' ? '0 0 0 auto' : '0'),
265 overflow: 'visible',
266 };
267
268 return el('div', Object.assign({}, blockProps, { style: (function () {
269 var s = { paddingTop: a.paddingTop + 'px', paddingBottom: a.paddingBottom + 'px', backgroundColor: a.bgColor || undefined };
270 var fn = getTypoCssVars();
271 if (fn) { Object.assign(s, fn(a.headlineTypo, '--bkbg-ic-ht-'), fn(a.subtextTypo, '--bkbg-ic-st-')); }
272 return s;
273 })() }),
274 el('div', { className: 'bkbg-image-collage bkbg-image-collage--' + a.preset, 'data-hover-lift': a.hoverLift ? '1' : '0', 'data-animate-in': a.animateIn ? '1' : '0', style: canvasStyle },
275 a.images.map(function (img) {
276 var w = img.w || 240;
277 var h = img.h || 180;
278 var frame = img.frame !== 'inherit' ? img.frame : 'none';
279 var style = {
280 position: 'absolute',
281 left: img.offsetX + '%',
282 top: img.offsetY + '%',
283 width: w + 'px',
284 height: h + 'px',
285 transform: 'rotate(' + img.rotation + 'deg) scale(' + img.scale + ')',
286 zIndex: img.zIndex,
287 overflow: frame === 'polaroid' ? 'visible' : 'hidden',
288 background: '#e5e7eb',
289 };
290 if (frame === 'polaroid') {
291 Object.assign(style, { padding: a.framePadding + 'px', paddingBottom: (a.framePadding * 3) + 'px', background: a.frameColor, boxShadow: '0 ' + (a.shadowIntensity / 5) + 'px ' + a.shadowIntensity + 'px rgba(0,0,0,0.18)' });
292 } else if (frame === 'shadow') {
293 style.boxShadow = '0 ' + (a.shadowIntensity / 5) + 'px ' + a.shadowIntensity + 'px rgba(0,0,0,0.18)';
294 }
295 return el('div', { key: img.id, className: 'bkbg-ic-img', style: style },
296 img.url && el('img', { src: img.url, alt: '', style: { width: '100%', height: '100%', objectFit: 'cover', display: 'block' } })
297 );
298 }),
299 a.showOverlayCard && el('div', {
300 className: 'bkbg-ic-overlay-card',
301 style: Object.assign({ position: 'absolute', zIndex: 20, background: a.overlayCardBg || '#fff', color: a.overlayCardColor || '#1e293b', padding: '16px 22px', borderRadius: '12px', boxShadow: '0 8px 32px rgba(0,0,0,0.12)', maxWidth: '260px', borderTop: '4px solid ' + (a.overlayCardAccent || '#6c3fb5') }, (function(pos) { var map = { 'bottom-right': { bottom: '20px', right: '20px' }, 'bottom-left': { bottom: '20px', left: '20px' }, 'top-right': { top: '20px', right: '20px' }, 'top-left': { top: '20px', left: '20px' }, 'center': { top: '50%', left: '50%', transform: 'translate(-50%,-50%)' } }; return map[pos] || map['bottom-right']; })(a.overlayCardPos))
302 },
303 a.overlayCardText && el('p', { className: 'bkbg-ic-headline', style: { margin: '0 0 4px' } }, a.overlayCardText),
304 a.overlayCardSubtext && el('p', { className: 'bkbg-ic-subtext', style: { margin: 0, opacity: 0.75 } }, a.overlayCardSubtext)
305 )
306 )
307 );
308 }
309 });
310 }() );
311