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

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

298 lines 18.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 useState = wp.element.useState;
6 var registerBlockType = wp.blocks.registerBlockType;
7 var InspectorControls = wp.blockEditor.InspectorControls;
8 var useBlockProps = wp.blockEditor.useBlockProps;
9 var RichText = wp.blockEditor.RichText;
10 var MediaUpload = wp.blockEditor.MediaUpload;
11 var MediaUploadCheck = wp.blockEditor.MediaUploadCheck;
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 _tc, _tv;
21 function getTypoControl() { return _tc || (_tc = window.bkbgTypographyControl); }
22 function getTypoCssVars() { return _tv || (_tv = window.bkbgTypoCssVars); }
23
24 /* ── Placeholder logo SVG ─────────────────────────────────────────────── */
25 var PLACEHOLDER_SVG = 'data:image/svg+xml;utf8,' + encodeURIComponent(
26 '<svg xmlns="http://www.w3.org/2000/svg" width="120" height="60" viewBox="0 0 120 60">' +
27 '<rect width="120" height="60" fill="#f3f4f6" rx="4"/>' +
28 '<text x="60" y="36" text-anchor="middle" fill="#9ca3af" font-size="11" font-family="sans-serif">Logo</text>' +
29 '</svg>'
30 );
31
32 /* ── Card builder (shared edit/save) ──────────────────────────────────── */
33 function buildCardStyle(a) {
34 return {
35 background: a.cardBg,
36 borderRadius: a.cardRadius + 'px',
37 padding: a.cardPadding + 'px',
38 border: a.showBorder ? '1px solid ' + a.borderColor : 'none',
39 boxShadow: a.showShadow ? '0 2px 12px rgba(0,0,0,0.06)' : 'none',
40 display: 'flex',
41 flexDirection: 'column',
42 alignItems: a.itemAlign === 'left' ? 'flex-start' : 'center',
43 justifyContent: 'center',
44 textDecoration: 'none',
45 cursor: 'default',
46 };
47 }
48
49 function buildImgStyle(a, logo) {
50 return {
51 height: a.logoHeight + 'px',
52 width: 'auto',
53 maxWidth: '100%',
54 objectFit: 'contain',
55 display: 'block',
56 filter: a.grayscale ? 'grayscale(100%)' : 'none',
57 opacity: a.logoOpacity / 100,
58 transition: 'filter 0.3s ease, opacity 0.3s ease, transform 0.25s ease',
59 };
60 }
61
62 /* ── Logo item editor row ─────────────────────────────────────────────── */
63 function LogoEditor(props) {
64 var a = props.attr, logo = props.logo, idx = props.idx;
65 var onUpdate = props.onUpdate, onRemove = props.onRemove;
66 var expandState = useState(false);
67 var expanded = expandState[0], setExpanded = expandState[1];
68
69 return el('div', { style: { border: '1px solid #e5e7eb', borderRadius: '8px', marginBottom: '8px', overflow: 'hidden' } },
70 el('div', {
71 style: { display: 'flex', alignItems: 'center', gap: '8px', padding: '8px', background: '#f9fafb', cursor: 'pointer' },
72 onClick: function () { setExpanded(!expanded); }
73 },
74 logo.url
75 ? el('img', { src: logo.url, alt: logo.alt, style: { height: '28px', width: 'auto', objectFit: 'contain', borderRadius: '3px' } })
76 : el('div', { style: { width: '40px', height: '28px', background: '#e5e7eb', borderRadius: '3px', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '10px', color: '#9ca3af' } }, 'img'),
77 el('span', { style: { flex: 1, fontSize: '13px', fontWeight: 600, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }, logo.name || ('Logo ' + (idx + 1))),
78 el('span', { style: { fontSize: '12px', color: '#9ca3af' } }, expanded ? '' : ''),
79 el(Button, {
80 isSmall: true, variant: 'tertiary', isDestructive: true,
81 onClick: function (e) { e.stopPropagation(); onRemove(idx); }
82 }, '×')
83 ),
84 expanded && el('div', { style: { padding: '12px', display: 'flex', flexDirection: 'column', gap: '8px' } },
85 el(MediaUploadCheck, null,
86 el(MediaUpload, {
87 onSelect: function (m) { onUpdate(idx, 'url', m.url); onUpdate(idx, 'id', m.id); onUpdate(idx, 'alt', m.alt || ''); },
88 allowedTypes: ['image'],
89 value: logo.id,
90 render: function (ref) {
91 return el(Button, { variant: logo.url ? 'secondary' : 'primary', onClick: ref.open, isSmall: true },
92 logo.url ? __('Replace Image', 'blockenberg') : __('Choose Image', 'blockenberg')
93 );
94 }
95 })
96 ),
97 el(TextControl, { label: __('Name', 'blockenberg'), value: logo.name, onChange: function (v) { onUpdate(idx, 'name', v); } }),
98 el(TextControl, { label: __('Link URL', 'blockenberg'), value: logo.link, onChange: function (v) { onUpdate(idx, 'link', v); } }),
99 el(ToggleControl, { label: __('Open in new tab', 'blockenberg'), checked: logo.newTab, onChange: function (v) { onUpdate(idx, 'newTab', v); }, __nextHasNoMarginBottom: true })
100 )
101 );
102 }
103
104 registerBlockType('blockenberg/logo-wall', {
105 title: __('Logo Wall', 'blockenberg'),
106 icon: 'grid-view',
107 category: 'bkbg-marketing',
108 description: __('Static grid of client/partner logos with hover effects.', 'blockenberg'),
109
110 edit: function (props) {
111 var attributes = props.attributes;
112 var setAttributes = props.setAttributes;
113 var a = attributes;
114
115 function updateLogo(idx, key, val) {
116 var arr = a.logos.slice();
117 arr[idx] = Object.assign({}, arr[idx]);
118 arr[idx][key] = val;
119 setAttributes({ logos: arr });
120 }
121 function addLogo() {
122 var n = a.logos.length + 1;
123 setAttributes({ logos: a.logos.concat([{ url: '', id: 0, alt: 'Logo ' + n, name: 'Client ' + n, link: '', newTab: false }]) });
124 }
125 function removeLogo(idx) {
126 setAttributes({ logos: a.logos.filter(function (_, i) { return i !== idx; }) });
127 }
128
129 var hoverOptions = [
130 { label: __('Lift (move up)', 'blockenberg'), value: 'lift' },
131 { label: __('Scale (zoom in)', 'blockenberg'), value: 'scale' },
132 { label: __('Glow', 'blockenberg'), value: 'glow' },
133 { label: __('None', 'blockenberg'), value: 'none' },
134 ];
135 var alignOptions = [
136 { label: __('Center', 'blockenberg'), value: 'center' },
137 { label: __('Left', 'blockenberg'), value: 'left' },
138 ];
139
140 var blockProps = useBlockProps((function () {
141 var _tvFn = getTypoCssVars();
142 var s = {};
143 if (_tvFn) {
144 Object.assign(s, _tvFn(a.titleTypo, '--bklw-tt-'));
145 Object.assign(s, _tvFn(a.nameTypo, '--bklw-n-'));
146 }
147 return { className: 'bklw-wrap', style: s };
148 })());
149
150 return el(Fragment, null,
151 el(InspectorControls, null,
152
153 /* — Logos — */
154 el(PanelBody, { title: __('Logos', 'blockenberg'), initialOpen: true },
155 a.logos.map(function (logo, idx) {
156 return el(LogoEditor, { key: idx, attr: a, logo: logo, idx: idx, onUpdate: updateLogo, onRemove: removeLogo });
157 }),
158 el(Button, { variant: 'primary', onClick: addLogo, style: { width: '100%', marginTop: '8px' } },
159 __('+ Add Logo', 'blockenberg'))
160 ),
161
162 /* — Layout — */
163 el(PanelBody, { title: __('Grid Layout', 'blockenberg'), initialOpen: false },
164 el(RangeControl, { label: __('Columns', 'blockenberg'), value: a.columns, min: 2, max: 8, onChange: function (v) { setAttributes({ columns: v }); } }),
165 el(RangeControl, { label: __('Logo Height (px)', 'blockenberg'), value: a.logoHeight, min: 20, max: 200, onChange: function (v) { setAttributes({ logoHeight: v }); } }),
166 el(RangeControl, { label: __('Gap (px)', 'blockenberg'), value: a.gap, min: 4, max: 80, onChange: function (v) { setAttributes({ gap: v }); } }),
167 el(SelectControl, { label: __('Item Alignment', 'blockenberg'), value: a.itemAlign, options: alignOptions, onChange: function (v) { setAttributes({ itemAlign: v }); } })
168 ),
169
170 /* — Title — */
171 el(PanelBody, { title: __('Section Title', 'blockenberg'), initialOpen: false },
172 el(ToggleControl, { label: __('Show Title', 'blockenberg'), checked: a.showTitle, onChange: function (v) { setAttributes({ showTitle: v }); }, __nextHasNoMarginBottom: true }),
173 a.showTitle && el(TextControl, { label: __('Title Text', 'blockenberg'), value: a.title, onChange: function (v) { setAttributes({ title: v }); } }),
174 a.showTitle && el(SelectControl, { label: __('Title Align', 'blockenberg'), value: a.titleAlign, options: [{ label: 'Center', value: 'center' }, { label: 'Left', value: 'left' }, { label: 'Right', value: 'right' }], onChange: function (v) { setAttributes({ titleAlign: v }); } })
175 ),
176
177 /* — Logo Effects — */
178 el(PanelBody, { title: __('Logo Effects', 'blockenberg'), initialOpen: false },
179 el(ToggleControl, { label: __('Grayscale', 'blockenberg'), checked: a.grayscale, onChange: function (v) { setAttributes({ grayscale: v }); }, __nextHasNoMarginBottom: true }),
180 el(ToggleControl, { label: __('Color on Hover', 'blockenberg'), checked: a.colorOnHover, onChange: function (v) { setAttributes({ colorOnHover: v }); }, __nextHasNoMarginBottom: true }),
181 el(RangeControl, { label: __('Default Opacity (%)', 'blockenberg'), value: a.logoOpacity, min: 10, max: 100, onChange: function (v) { setAttributes({ logoOpacity: v }); } }),
182 el(SelectControl, { label: __('Hover Effect', 'blockenberg'), value: a.hoverEffect, options: hoverOptions, onChange: function (v) { setAttributes({ hoverEffect: v }); } }),
183 el(ToggleControl, { label: __('Show Name', 'blockenberg'), checked: a.showName, onChange: function (v) { setAttributes({ showName: v }); }, __nextHasNoMarginBottom: true }),
184 ),
185
186 /* — Card Style — */
187 el(PanelBody, { title: __('Card Style', 'blockenberg'), initialOpen: false },
188 el(RangeControl, { label: __('Card Radius (px)', 'blockenberg'), value: a.cardRadius, min: 0, max: 40, onChange: function (v) { setAttributes({ cardRadius: v }); } }),
189 el(RangeControl, { label: __('Card Padding (px)', 'blockenberg'), value: a.cardPadding, min: 0, max: 60, onChange: function (v) { setAttributes({ cardPadding: v }); } }),
190 el(ToggleControl, { label: __('Show Border', 'blockenberg'), checked: a.showBorder, onChange: function (v) { setAttributes({ showBorder: v }); }, __nextHasNoMarginBottom: true }),
191 el(ToggleControl, { label: __('Show Shadow', 'blockenberg'), checked: a.showShadow, onChange: function (v) { setAttributes({ showShadow: v }); }, __nextHasNoMarginBottom: true }),
192 el(ToggleControl, { label: __('Show Divider', 'blockenberg'), checked: a.showDivider, onChange: function (v) { setAttributes({ showDivider: v }); }, __nextHasNoMarginBottom: true })
193 ),
194
195 /* — Colors — */
196
197 el( PanelBody, { title: __( 'Typography', 'blockenberg' ), initialOpen: false },
198 el(getTypoControl(), { label: __('Title', 'blockenberg'), value: a.titleTypo, onChange: function (v) { setAttributes({ titleTypo: v }); } }),
199 el(getTypoControl(), { label: __('Name', 'blockenberg'), value: a.nameTypo, onChange: function (v) { setAttributes({ nameTypo: v }); } })
200 ),
201 el(PanelColorSettings, {
202 title: __('Colors', 'blockenberg'),
203 initialOpen: false,
204 colorSettings: [
205 { label: __('Card Background', 'blockenberg'), value: a.cardBg, onChange: function (v) { setAttributes({ cardBg: v || 'transparent' }); } },
206 { label: __('Card Background Hover', 'blockenberg'), value: a.cardBgHover, onChange: function (v) { setAttributes({ cardBgHover: v || '#f9fafb' }); } },
207 { label: __('Border Color', 'blockenberg'), value: a.borderColor, onChange: function (v) { setAttributes({ borderColor: v || '#e5e7eb' }); } },
208 { label: __('Divider Color', 'blockenberg'), value: a.dividerColor, onChange: function (v) { setAttributes({ dividerColor: v || '#e5e7eb' }); } },
209 { label: __('Name Color', 'blockenberg'), value: a.nameColor, onChange: function (v) { setAttributes({ nameColor: v || '#374151' }); } },
210 { label: __('Title Color', 'blockenberg'), value: a.titleColor, onChange: function (v) { setAttributes({ titleColor: v || '#6b7280' }); } },
211 ]
212 })
213 ),
214
215 /* ── Canvas ─────────────────────────────────────────────────── */
216 el('div', blockProps,
217 a.showTitle && el('p', {
218 className: 'bklw-title',
219 style: { textAlign: a.titleAlign, color: a.titleColor, margin: '0 0 24px' }
220 }, a.title),
221 a.showDivider && el('hr', { style: { borderColor: a.dividerColor, margin: '0 0 24px' } }),
222 el('div', {
223 className: 'bklw-grid',
224 style: { display: 'grid', gridTemplateColumns: 'repeat(' + a.columns + ', 1fr)', gap: a.gap + 'px' }
225 },
226 a.logos.map(function (logo, idx) {
227 return el('div', { key: idx, className: 'bklw-card', style: buildCardStyle(a) },
228 el('img', {
229 src: logo.url || PLACEHOLDER_SVG,
230 alt: logo.alt || logo.name,
231 style: buildImgStyle(a, logo),
232 className: 'bklw-img'
233 }),
234 a.showName && el('p', {
235 className: 'bklw-name',
236 style: { margin: '8px 0 0', color: a.nameColor, textAlign: a.itemAlign }
237 }, logo.name)
238 );
239 })
240 )
241 )
242 );
243 },
244
245 save: function (props) {
246 var a = props.attributes;
247 var _tvFn = window.bkbgTypoCssVars;
248 var s = {};
249 if (_tvFn) {
250 Object.assign(s, _tvFn(a.titleTypo, '--bklw-tt-'));
251 Object.assign(s, _tvFn(a.nameTypo, '--bklw-n-'));
252 }
253 var blockProps = wp.blockEditor.useBlockProps.save({ className: 'bklw-wrap', style: s });
254 return el('div', blockProps,
255 a.showTitle && el('p', {
256 className: 'bklw-title',
257 style: { textAlign: a.titleAlign, color: a.titleColor, margin: '0 0 24px' }
258 }, a.title),
259 a.showDivider && el('hr', { className: 'bklw-divider', style: { borderColor: a.dividerColor, margin: '0 0 24px' } }),
260 el('div', {
261 className: 'bklw-grid',
262 'data-grayscale': a.grayscale ? '1' : '0',
263 'data-color-hover': a.colorOnHover ? '1' : '0',
264 'data-opacity': a.logoOpacity,
265 'data-hover-fx': a.hoverEffect,
266 'data-card-bg': a.cardBg,
267 'data-card-hover': a.cardBgHover,
268 style: { display: 'grid', gridTemplateColumns: 'repeat(' + a.columns + ', 1fr)', gap: a.gap + 'px' }
269 },
270 a.logos.map(function (logo, idx) {
271 var inner = [
272 el('img', {
273 key: 'img', src: logo.url, alt: logo.alt || logo.name, className: 'bklw-img',
274 style: buildImgStyle(a, logo)
275 }),
276 a.showName && el('p', {
277 key: 'name', className: 'bklw-name',
278 style: { margin: '8px 0 0', color: a.nameColor, textAlign: a.itemAlign }
279 }, logo.name)
280 ].filter(Boolean);
281
282 var cardStyle = buildCardStyle(a);
283 if (logo.link) {
284 return el('a', {
285 key: idx, href: logo.link, className: 'bklw-card',
286 target: logo.newTab ? '_blank' : undefined,
287 rel: logo.newTab ? 'noopener noreferrer' : undefined,
288 style: Object.assign({}, cardStyle, { cursor: 'pointer' })
289 }, inner);
290 }
291 return el('div', { key: idx, className: 'bklw-card', style: cardStyle }, inner);
292 })
293 )
294 );
295 }
296 });
297 }() );
298