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

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

237 lines 10.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 function defaultLogo() {
18 return { imageUrl: '', imageId: 0, imageAlt: '', linkUrl: '' };
19 }
20
21 registerBlockType('blockenberg/logo-ticker', {
22 edit: function (props) {
23 var attr = props.attributes;
24 var setAttr = props.setAttributes;
25 var logos = attr.logos || [];
26
27 var blockProps = useBlockProps({ className: 'bkbg-lt-editor' });
28
29 function updateLogo(i, key, value) {
30 var updated = logos.map(function (l, idx) {
31 if (idx !== i) return l;
32 var copy = Object.assign({}, l);
33 copy[key] = value;
34 return copy;
35 });
36 setAttr({ logos: updated });
37 }
38
39 function removeLogo(i) {
40 setAttr({ logos: logos.filter(function (_, idx) { return idx !== i; }) });
41 }
42
43 function addLogo() {
44 setAttr({ logos: logos.concat(defaultLogo()) });
45 }
46
47 var logoControls = logos.map(function (logo, i) {
48 return el('div', {
49 key: i,
50 style: {
51 borderLeft: '3px solid #7c3aed',
52 paddingLeft: '12px',
53 marginBottom: '16px'
54 }
55 },
56 el('div', { style: { display: 'flex', alignItems: 'center', gap: '8px', marginBottom: '8px' } },
57 el('strong', {}, 'Logo ' + (i + 1)),
58 el(Button, {
59 isSmall: true,
60 isDestructive: true,
61 onClick: function () { removeLogo(i); }
62 }, '')
63 ),
64 el(MediaUploadCheck, {},
65 el(MediaUpload, {
66 onSelect: function (media) {
67 updateLogo(i, 'imageUrl', media.url);
68 updateLogo(i, 'imageId', media.id);
69 updateLogo(i, 'imageAlt', media.alt || '');
70 },
71 allowedTypes: ['image'],
72 value: logo.imageId,
73 render: function (ref) {
74 return el('div', {},
75 logo.imageUrl
76 ? el('img', {
77 src: logo.imageUrl,
78 alt: logo.imageAlt,
79 style: { height: '40px', objectFit: 'contain', display: 'block', marginBottom: '6px', cursor: 'pointer' },
80 onClick: ref.open
81 })
82 : el(Button, { isSecondary: true, isSmall: true, onClick: ref.open }, 'Select Logo Image')
83 );
84 }
85 })
86 ),
87 el(TextControl, {
88 label: __('Link URL', 'blockenberg'),
89 value: logo.linkUrl,
90 onChange: function (v) { updateLogo(i, 'linkUrl', v); },
91 __nextHasNoMarginBottom: true
92 })
93 );
94 });
95
96 // Editor preview
97 var previewLogos = logos.filter(function (l) { return l.imageUrl; });
98 var previewContent = previewLogos.length === 0
99 ? el('div', { style: { textAlign: 'center', color: '#9ca3af', padding: '24px' } }, '← Add logos in the sidebar →')
100 : el('div', { style: { display: 'flex', gap: '32px', alignItems: 'center', flexWrap: 'wrap', justifyContent: 'center' } },
101 previewLogos.map(function (l, i) {
102 return el('img', {
103 key: i,
104 src: l.imageUrl,
105 alt: l.imageAlt,
106 style: { height: attr.height + 'px', objectFit: 'contain', opacity: 0.8 }
107 });
108 })
109 );
110
111 var wrapStyle = {
112 background: attr.bgColor || 'transparent',
113 paddingTop: attr.paddingTop + 'px',
114 paddingBottom: attr.paddingBottom + 'px',
115 borderTop: attr.borderTop ? '1px solid ' + attr.borderColor : 'none',
116 borderBottom: attr.borderBottom ? '1px solid ' + attr.borderColor : 'none',
117 overflow: 'hidden'
118 };
119
120 var controls = el(InspectorControls, {},
121 el(PanelBody, { title: __('Logos', 'blockenberg'), initialOpen: true },
122 logoControls,
123 el(Button, {
124 isPrimary: true,
125 isSmall: true,
126 onClick: addLogo,
127 style: { marginTop: '8px' }
128 }, '+ Add Logo')
129 ),
130 el(PanelBody, { title: __('Ticker Settings', 'blockenberg'), initialOpen: false },
131 el(RangeControl, {
132 label: __('Speed (seconds per loop)', 'blockenberg'),
133 value: attr.speed,
134 min: 5, max: 120,
135 onChange: function (v) { setAttr({ speed: v }); },
136 __nextHasNoMarginBottom: true
137 }),
138 el(SelectControl, {
139 label: __('Direction', 'blockenberg'),
140 value: attr.direction,
141 options: [
142 { label: 'Left (→)', value: 'left' },
143 { label: 'Right (←)', value: 'right' }
144 ],
145 onChange: function (v) { setAttr({ direction: v }); },
146 __nextHasNoMarginBottom: true
147 }),
148 el(ToggleControl, {
149 label: __('Pause on Hover', 'blockenberg'),
150 checked: attr.pauseOnHover,
151 onChange: function (v) { setAttr({ pauseOnHover: v }); },
152 __nextHasNoMarginBottom: true
153 }),
154 el(SelectControl, {
155 label: __('Logo Filter', 'blockenberg'),
156 value: attr.logoFilter,
157 options: [
158 { label: 'None (full color)', value: 'none' },
159 { label: 'Grayscale always', value: 'grayscale' },
160 { label: 'Grayscale → color on hover', value: 'grayscale-hover' }
161 ],
162 onChange: function (v) { setAttr({ logoFilter: v }); },
163 __nextHasNoMarginBottom: true
164 }),
165 el(RangeControl, {
166 label: __('Logo Height (px)', 'blockenberg'),
167 value: attr.height,
168 min: 20, max: 120,
169 onChange: function (v) { setAttr({ height: v }); },
170 __nextHasNoMarginBottom: true
171 }),
172 el(RangeControl, {
173 label: __('Gap Between Logos (px)', 'blockenberg'),
174 value: attr.gap,
175 min: 8, max: 120,
176 onChange: function (v) { setAttr({ gap: v }); },
177 __nextHasNoMarginBottom: true
178 })
179 ),
180 el(PanelColorSettings, {
181 title: __('Colors', 'blockenberg'),
182 initialOpen: false,
183 colorSettings: [
184 { label: __('Background', 'blockenberg'), value: attr.bgColor, onChange: function (v) { setAttr({ bgColor: v || '' }); } },
185 { label: __('Border Color', 'blockenberg'), value: attr.borderColor, onChange: function (v) { setAttr({ borderColor: v || '#e5e7eb' }); } }
186 ]
187 }),
188 el(PanelBody, { title: __('Borders & Spacing', 'blockenberg'), initialOpen: false },
189 el(ToggleControl, {
190 label: __('Border Top', 'blockenberg'),
191 checked: attr.borderTop,
192 onChange: function (v) { setAttr({ borderTop: v }); },
193 __nextHasNoMarginBottom: true
194 }),
195 el(ToggleControl, {
196 label: __('Border Bottom', 'blockenberg'),
197 checked: attr.borderBottom,
198 onChange: function (v) { setAttr({ borderBottom: v }); },
199 __nextHasNoMarginBottom: true
200 }),
201 el(RangeControl, {
202 label: __('Padding Top (px)', 'blockenberg'),
203 value: attr.paddingTop,
204 min: 0, max: 120,
205 onChange: function (v) { setAttr({ paddingTop: v }); },
206 __nextHasNoMarginBottom: true
207 }),
208 el(RangeControl, {
209 label: __('Padding Bottom (px)', 'blockenberg'),
210 value: attr.paddingBottom,
211 min: 0, max: 120,
212 onChange: function (v) { setAttr({ paddingBottom: v }); },
213 __nextHasNoMarginBottom: true
214 })
215 )
216
217 );
218
219 return el('div', blockProps,
220 controls,
221 el('div', { style: wrapStyle }, previewContent)
222 );
223 },
224
225 save: function (props) {
226 var attr = props.attributes;
227 var blockProps = wp.blockEditor.useBlockProps.save();
228 return el('div', blockProps,
229 el('div', {
230 className: 'bkbg-lt-app',
231 'data-opts': JSON.stringify(attr)
232 })
233 );
234 }
235 });
236 }() );
237