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

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

254 lines 13.8 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 __ = wp.i18n.__;
4 var registerBlockType = wp.blocks.registerBlockType;
5 var InspectorControls = wp.blockEditor.InspectorControls;
6 var MediaUpload = wp.blockEditor.MediaUpload;
7 var MediaUploadCheck = wp.blockEditor.MediaUploadCheck;
8 var useBlockProps = wp.blockEditor.useBlockProps;
9 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
10 var PanelBody = wp.components.PanelBody;
11 var ToggleControl = wp.components.ToggleControl;
12 var RangeControl = wp.components.RangeControl;
13 var SelectControl = wp.components.SelectControl;
14 var TextControl = wp.components.TextControl;
15 var Button = wp.components.Button;
16
17 var _TypographyControl, _typoCssVars;
18 function getTypographyControl() { return _TypographyControl || (_TypographyControl = window.bkbgTypographyControl); }
19 function getTypoCssVars() { return _typoCssVars || (_typoCssVars = window.bkbgTypoCssVars); }
20
21 var ALIGN_OPTIONS = [
22 { label: 'Left', value: 'left' }, { label: 'Center', value: 'center' }, { label: 'Right', value: 'right' }
23 ];
24 var LENS_SHAPE_OPTIONS = [
25 { label: 'Circle', value: 'circle' }, { label: 'Square', value: 'square' }
26 ];
27 var EFFECT_OPTIONS = [
28 { label: 'Floating Lens', value: 'lens' },
29 { label: 'Side Preview Box', value: 'preview' },
30 ];
31
32 function EditorPlaceholder(a, openFn) {
33 if (!a.imageUrl) {
34 return el('div', {
35 onClick: openFn,
36 style: {
37 border: '2px dashed #c084fc', borderRadius: a.imageRadius + 'px',
38 height: '200px', display: 'flex', alignItems: 'center', justifyContent: 'center',
39 cursor: 'pointer', background: '#faf5ff', flexDirection: 'column', gap: '8px',
40 }
41 },
42 el('span', { className: 'dashicons dashicons-search', style: { fontSize: '40px', width: '40px', height: '40px', color: '#c084fc', lineHeight: 1 } }),
43 el('span', { style: { color: '#a855f7', fontWeight: 600 } }, __('Click to select image', 'blockenberg')),
44 el('span', { style: { color: '#c4b5fd', fontSize: '13px' } }, __('Opens with zoom lens on hover', 'blockenberg')),
45 );
46 }
47 return el('div', { style: { position: 'relative', textAlign: a.align } },
48 el('div', { style: { display: 'inline-block', position: 'relative', maxWidth: '100%' } },
49 el('img', {
50 src: a.imageUrl, alt: a.alt,
51 style: { maxWidth: '100%', width: a.width + 'px', display: 'block', borderRadius: a.imageRadius + 'px' }
52 }),
53 /* lens demo in editor */
54 el('div', {
55 style: {
56 position: 'absolute', width: a.lensSize + 'px', height: a.lensSize + 'px',
57 borderRadius: a.lensShape === 'circle' ? '50%' : a.imageRadius + 'px',
58 border: a.lensBorderWidth + 'px solid ' + a.lensBorderColor,
59 boxShadow: a.lensShadow ? '0 4px 20px rgba(0,0,0,0.25)' : 'none',
60 top: '50%', left: '50%',
61 transform: 'translate(-50%,-50%)',
62 pointerEvents: 'none', zIndex: 2,
63 backgroundImage: 'url(' + a.imageUrl + ')',
64 backgroundSize: (a.zoomFactor) + '% ' + (a.zoomFactor) + '%',
65 backgroundPosition: '50% 50%',
66 backgroundRepeat: 'no-repeat',
67 overflow: 'hidden',
68 opacity: 0.85,
69 }
70 }),
71 el('div', {
72 style: {
73 position: 'absolute', bottom: '8px', right: '8px', zIndex: 3,
74 background: 'rgba(0,0,0,0.5)', color: '#fff', fontSize: '11px', padding: '3px 8px', borderRadius: '4px',
75 }
76 }, '🔍 Editor preview'),
77 ),
78 a.showCaption && a.caption && el('p', {
79 className: 'bkmag-caption',
80 style: { color: a.captionColor, marginTop: '8px', textAlign: 'center' }
81 }, a.caption),
82 );
83 }
84
85 registerBlockType('blockenberg/image-magnifier', {
86 edit: function (props) {
87 var a = props.attributes;
88 var set = props.setAttributes;
89 var blockProps = useBlockProps({ style: (function () {
90 var s = { textAlign: a.align };
91 var fn = getTypoCssVars();
92 if (fn) { Object.assign(s, fn(a.captionTypo, '--bkmag-cp-')); }
93 return s;
94 })() });
95
96 return el('div', blockProps,
97 el(InspectorControls, null,
98 el(PanelBody, { title: __('Image', 'blockenberg'), initialOpen: true },
99 el(MediaUploadCheck, null,
100 el(MediaUpload, {
101 onSelect: function (m) { set({ imageUrl: m.url, imageId: m.id, alt: m.alt || '' }); },
102 allowedTypes: ['image'], value: a.imageId,
103 render: function (ref) {
104 return el(Button, {
105 onClick: ref.open, variant: 'secondary',
106 style: { width: '100%', justifyContent: 'center', marginBottom: '6px' }
107 }, a.imageUrl ? __('Change Image') : __('Select Image'));
108 }
109 })
110 ),
111 a.imageUrl && el(Button, {
112 isDestructive: true, isSmall: true,
113 onClick: function () { set({ imageUrl: '', imageId: 0 }); }
114 }, __('Remove Image')),
115 el(TextControl, {
116 label: __('Alt Text'), value: a.alt,
117 onChange: function (v) { set({ alt: v }); }
118 }),
119 el(RangeControl, {
120 label: __('Max Width (px)'), value: a.width, min: 200, max: 1200,
121 onChange: function (v) { set({ width: v }); }
122 }),
123 el(RangeControl, {
124 label: __('Border Radius (px)'), value: a.imageRadius, min: 0, max: 32,
125 onChange: function (v) { set({ imageRadius: v }); }
126 }),
127 el(SelectControl, {
128 label: __('Alignment'), value: a.align, options: ALIGN_OPTIONS,
129 onChange: function (v) { set({ align: v }); }
130 }),
131 ),
132 el(PanelBody, { title: __('Zoom Effect', 'blockenberg'), initialOpen: false },
133 el(SelectControl, {
134 label: __('Effect Type'), value: a.effectType, options: EFFECT_OPTIONS,
135 onChange: function (v) { set({ effectType: v }); }
136 }),
137 el(RangeControl, {
138 label: __('Zoom Factor %'), value: a.zoomFactor, min: 110, max: 500,
139 onChange: function (v) { set({ zoomFactor: v }); }
140 }),
141 a.effectType === 'lens' && el(RangeControl, {
142 label: __('Lens Size (px)'), value: a.lensSize, min: 60, max: 400,
143 onChange: function (v) { set({ lensSize: v }); }
144 }),
145 a.effectType === 'lens' && el(SelectControl, {
146 label: __('Lens Shape'), value: a.lensShape, options: LENS_SHAPE_OPTIONS,
147 onChange: function (v) { set({ lensShape: v }); }
148 }),
149 a.effectType === 'lens' && el(RangeControl, {
150 label: __('Lens Border Width (px)'), value: a.lensBorderWidth, min: 0, max: 6,
151 onChange: function (v) { set({ lensBorderWidth: v }); }
152 }),
153 a.effectType === 'lens' && el(ToggleControl, {
154 label: __('Lens Shadow'), checked: a.lensShadow,
155 onChange: function (v) { set({ lensShadow: v }); }, __nextHasNoMarginBottom: true
156 }),
157 a.effectType === 'preview' && el(RangeControl, {
158 label: __('Preview Width (px)'), value: a.previewWidth, min: 150, max: 600,
159 onChange: function (v) { set({ previewWidth: v }); }
160 }),
161 a.effectType === 'preview' && el(RangeControl, {
162 label: __('Preview Height (px)'), value: a.previewHeight, min: 150, max: 600,
163 onChange: function (v) { set({ previewHeight: v }); }
164 }),
165 ),
166 el(PanelBody, { title: __('Caption & Hint', 'blockenberg'), initialOpen: false },
167 el(ToggleControl, {
168 label: __('Show Caption'), checked: a.showCaption,
169 onChange: function (v) { set({ showCaption: v }); }, __nextHasNoMarginBottom: true
170 }),
171 a.showCaption && el(TextControl, {
172 label: __('Caption'), value: a.caption,
173 onChange: function (v) { set({ caption: v }); }
174 }),
175 el(ToggleControl, {
176 label: __('Show Hover Hint'), checked: a.showHint,
177 onChange: function (v) { set({ showHint: v }); }, __nextHasNoMarginBottom: true
178 }),
179 a.showHint && el(TextControl, {
180 label: __('Hint Text'), value: a.hint,
181 onChange: function (v) { set({ hint: v }); }
182 }),
183 ),
184 el(PanelColorSettings, {
185 title: __('Colors', 'blockenberg'), initialOpen: false,
186 colorSettings: [
187 { label: __('Lens Border'), value: a.lensBorderColor, onChange: function (v) { set({ lensBorderColor: v || '#6c3fb5' }); } },
188 { label: __('Preview Border'), value: a.previewBorder, onChange: function (v) { set({ previewBorder: v || '#e5e7eb' }); } },
189 { label: __('Caption Color'), value: a.captionColor, onChange: function (v) { set({ captionColor: v || '#6b7280' }); } },
190 { label: __('Hint Color'), value: a.hintColor, onChange: function (v) { set({ hintColor: v || '#9ca3af' }); } },
191 ]
192 }),
193 el(PanelBody, { title: 'Typography', initialOpen: false },
194 getTypographyControl() && el(getTypographyControl(), { label: __('Caption', 'blockenberg'), value: a.captionTypo, onChange: function (v) { set({ captionTypo: v }); } })
195 ),
196
197 ),
198 el(MediaUploadCheck, null,
199 el(MediaUpload, {
200 onSelect: function (m) { set({ imageUrl: m.url, imageId: m.id, alt: m.alt || '' }); },
201 allowedTypes: ['image'], value: a.imageId,
202 render: function (ref) { return EditorPlaceholder(a, ref.open); }
203 })
204 ),
205 );
206 },
207
208 save: function (props) {
209 var a = props.attributes;
210 if (!a.imageUrl) return el('div', { className: 'bkmag-wrap' });
211
212 return el('div', {
213 className: 'bkmag-wrap',
214 style: (function () {
215 var s = { textAlign: a.align };
216 var fn = getTypoCssVars();
217 if (fn) { Object.assign(s, fn(a.captionTypo, '--bkmag-cp-')); }
218 return s;
219 })()
220 },
221 el('div', {
222 className: 'bkmag-container',
223 'data-zoom': a.zoomFactor,
224 'data-lens-size': a.lensSize,
225 'data-lens-shape': a.lensShape,
226 'data-lens-border': a.lensBorderColor,
227 'data-lens-border-w': a.lensBorderWidth,
228 'data-lens-shadow': a.lensShadow ? '1' : '0',
229 'data-effect': a.effectType,
230 'data-preview-w': a.previewWidth,
231 'data-preview-h': a.previewHeight,
232 'data-preview-border': a.previewBorder,
233 'data-preview-radius': a.previewRadius,
234 style: { display: 'inline-block', position: 'relative', maxWidth: '100%', cursor: 'crosshair' }
235 },
236 el('img', {
237 className: 'bkmag-img',
238 src: a.imageUrl, alt: a.alt,
239 style: { width: a.width + 'px', maxWidth: '100%', display: 'block', borderRadius: a.imageRadius + 'px', userSelect: 'none', WebkitUserDrag: 'none' }
240 }),
241 a.showHint && el('div', {
242 className: 'bkmag-hint',
243 style: { textAlign: 'center', color: a.hintColor, fontSize: '12px', marginTop: '6px', position: 'absolute', bottom: '-24px', left: 0, right: 0 }
244 }, a.hint),
245 ),
246 a.showCaption && a.caption && el('p', {
247 className: 'bkmag-caption',
248 style: { color: a.captionColor, marginTop: '32px', textAlign: 'center' }
249 }, a.caption),
250 );
251 }
252 });
253 }() );
254