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

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

263 lines 13.3 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 useBlockProps = wp.blockEditor.useBlockProps;
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 PanelBody = wp.components.PanelBody;
11 var RangeControl = wp.components.RangeControl;
12 var ToggleControl = wp.components.ToggleControl;
13 var SelectControl = wp.components.SelectControl;
14 var TextControl = wp.components.TextControl;
15 var Button = wp.components.Button;
16 var ColorPicker = wp.components.ColorPicker;
17 var Popover = wp.components.Popover;
18 var useState = wp.element.useState;
19 var Fragment = wp.element.Fragment;
20
21 var _tc, _tv;
22 function getTypoControl() { return _tc || (_tc = window.bkbgTypographyControl); }
23 function getTypoCssVars() { return _tv || (_tv = window.bkbgTypoCssVars); }
24
25 function TilePreview(tile, a, flipped) {
26 var face = flipped ? 'back' : 'front';
27 var bg = flipped ? tile.backBg : tile.frontBg;
28 var url = flipped ? tile.backUrl : tile.frontUrl;
29
30 return el('div', {
31 style: {
32 width: a.tileWidth + 'px',
33 height: a.tileHeight + 'px',
34 borderRadius: a.tileRadius + 'px',
35 background: url ? 'url(' + url + ') center/cover no-repeat, ' + bg : bg,
36 position: 'relative',
37 overflow: 'hidden',
38 flexShrink: 0
39 }
40 },
41 a.showLabel && tile.label && el('div', {
42 className: 'bkbg-rit-label',
43 style: {
44 position: 'absolute', bottom: 0, left: 0, right: 0,
45 padding: '8px 12px',
46 background: a.labelBg || 'rgba(0,0,0,0.5)',
47 color: a.labelColor || '#ffffff',
48 textAlign: 'center'
49 }
50 }, tile.label)
51 );
52 }
53
54 var BkbgColorSwatch = function (props) {
55 var _st = useState(false); var isOpen = _st[0]; var setOpen = _st[1];
56 return el(Fragment, {},
57 el('div', { style: { display: 'flex', alignItems: 'center', gap: '8px', marginBottom: '8px' } },
58 el('span', { style: { fontSize: '11px', fontWeight: 500, textTransform: 'uppercase', color: '#1e1e1e' } }, props.label),
59 el('button', {
60 type: 'button',
61 onClick: function () { setOpen(!isOpen); },
62 style: { width: '28px', height: '28px', borderRadius: '4px', border: '1px solid #ccc', background: props.value || '#ffffff', cursor: 'pointer', padding: 0 }
63 })
64 ),
65 isOpen && el(Popover, { onClose: function () { setOpen(false); } },
66 el('div', { style: { padding: '8px' } },
67 el(ColorPicker, { color: props.value, onChangeComplete: function (c) { props.onChange(c.hex); }, enableAlpha: true })
68 )
69 )
70 );
71 };
72
73 registerBlockType('blockenberg/rotating-image-tiles', {
74 title: __('Rotating Image Tiles'),
75 icon: 'images-alt2',
76 category: 'bkbg-effects',
77
78 edit: function (props) {
79 var attr = props.attributes;
80 var setAttr = props.setAttributes;
81 var bp = useBlockProps((function () {
82 var _tv = getTypoCssVars();
83 var s = {};
84 if (_tv) {
85 Object.assign(s, _tv(attr.labelTypo, '--bkrit-lt-'));
86 }
87 return { className: 'bkbg-rit-wrap', style: s };
88 })());
89
90 function updateTile(idx, field, val) {
91 var tiles = attr.tiles.map(function (t, i) {
92 return i === idx ? Object.assign({}, t, { [field]: val }) : t;
93 });
94 setAttr({ tiles: tiles });
95 }
96 function addTile() {
97 setAttr({ tiles: attr.tiles.concat([{
98 frontUrl: '', frontAlt: 'Front', backUrl: '', backAlt: 'Back',
99 frontBg: '#6366f1', backBg: '#a5b4fc', label: ''
100 }]) });
101 }
102 function removeTile(idx) {
103 if (attr.tiles.length <= 2) return;
104 setAttr({ tiles: attr.tiles.filter(function (_, i) { return i !== idx; }) });
105 }
106
107 var inspector = el(InspectorControls, {},
108 /* Tiles */
109 el(PanelBody, { title: __('Tiles'), initialOpen: true },
110 attr.tiles.map(function (tile, idx) {
111 return el(PanelBody, { key: idx, title: 'Tile ' + (idx + 1), initialOpen: false },
112 /* Front image */
113 el('p', { style: { margin: '0 0 6px', fontWeight: 600 } }, __('Front Face')),
114 el(MediaUploadCheck, {},
115 el(MediaUpload, {
116 onSelect: function (m) { updateTile(idx, 'frontUrl', m.url); },
117 allowedTypes: ['image'], value: tile.frontUrl,
118 render: function (ref) {
119 return el(Button, { variant: tile.frontUrl ? 'secondary' : 'primary', onClick: ref.open },
120 tile.frontUrl ? __('Change Front Image') : __('Choose Front Image'));
121 }
122 })
123 ),
124 el(BkbgColorSwatch, { label: __('Front BG Color (fallback)'), value: tile.frontBg || '',
125 onChange: function (v) { updateTile(idx, 'frontBg', v); } }),
126 /* Back image */
127 el('p', { style: { margin: '8px 0 6px', fontWeight: 600 } }, __('Back Face')),
128 el(MediaUploadCheck, {},
129 el(MediaUpload, {
130 onSelect: function (m) { updateTile(idx, 'backUrl', m.url); },
131 allowedTypes: ['image'], value: tile.backUrl,
132 render: function (ref) {
133 return el(Button, { variant: tile.backUrl ? 'secondary' : 'primary', onClick: ref.open },
134 tile.backUrl ? __('Change Back Image') : __('Choose Back Image'));
135 }
136 })
137 ),
138 el(BkbgColorSwatch, { label: __('Back BG Color (fallback)'), value: tile.backBg || '',
139 onChange: function (v) { updateTile(idx, 'backBg', v); } }),
140 el(TextControl, { label: __('Label'), value: tile.label || '',
141 onChange: function (v) { updateTile(idx, 'label', v); },
142 __nextHasNoMarginBottom: true }),
143 attr.tiles.length > 2 && el(Button, {
144 isDestructive: true, variant: 'secondary',
145 onClick: function () { removeTile(idx); },
146 style: { marginTop: '8px' }
147 }, __('Remove Tile'))
148 );
149 }),
150 el(Button, { variant: 'primary', onClick: addTile,
151 style: { marginTop: '8px', width: '100%' }
152 }, __('+ Add Tile'))
153 ),
154
155 /* Layout */
156 el(PanelBody, { title: __('Layout'), initialOpen: false },
157 el(SelectControl, {
158 label: __('Columns'),
159 value: String(attr.columns),
160 options: ['2','3','4'].map(function (v) { return { label: v, value: v }; }),
161 onChange: function (v) { setAttr({ columns: Number(v) }); },
162 __nextHasNoMarginBottom: true
163 }),
164 el(RangeControl, { label: __('Tile Width (px)'), value: attr.tileWidth,
165 min: 120, max: 600,
166 onChange: function (v) { setAttr({ tileWidth: v }); },
167 __nextHasNoMarginBottom: true }),
168 el(RangeControl, { label: __('Tile Height (px)'), value: attr.tileHeight,
169 min: 80, max: 500,
170 onChange: function (v) { setAttr({ tileHeight: v }); },
171 __nextHasNoMarginBottom: true }),
172 el(RangeControl, { label: __('Tile Radius (px)'), value: attr.tileRadius,
173 min: 0, max: 40,
174 onChange: function (v) { setAttr({ tileRadius: v }); },
175 __nextHasNoMarginBottom: true }),
176 el(RangeControl, { label: __('Gap (px)'), value: attr.gap,
177 min: 0, max: 40,
178 onChange: function (v) { setAttr({ gap: v }); },
179 __nextHasNoMarginBottom: true })
180 ),
181
182 /* Animation */
183 el(PanelBody, { title: __('Animation'), initialOpen: false },
184 el(SelectControl, {
185 label: __('Flip Axis'),
186 value: attr.flipAxis,
187 options: [
188 { label: __('Horizontal (Y)'), value: 'Y' },
189 { label: __('Vertical (X)'), value: 'X' }
190 ],
191 onChange: function (v) { setAttr({ flipAxis: v }); },
192 __nextHasNoMarginBottom: true
193 }),
194 el(ToggleControl, { label: __('Auto Flip'), checked: attr.autoFlip,
195 onChange: function (v) { setAttr({ autoFlip: v }); },
196 __nextHasNoMarginBottom: true }),
197 el(ToggleControl, { label: __('Flip on Hover'), checked: attr.flipOnHover,
198 onChange: function (v) { setAttr({ flipOnHover: v }); },
199 __nextHasNoMarginBottom: true }),
200 el(RangeControl, { label: __('Flip Duration (ms)'), value: attr.flipDuration,
201 min: 200, max: 2000, step: 100,
202 onChange: function (v) { setAttr({ flipDuration: v }); },
203 __nextHasNoMarginBottom: true }),
204 el(RangeControl, { label: __('Stagger Delay (ms)'), value: attr.staggerDelay,
205 min: 0, max: 1000, step: 50,
206 onChange: function (v) { setAttr({ staggerDelay: v }); },
207 __nextHasNoMarginBottom: true }),
208 attr.autoFlip && el(RangeControl, { label: __('Auto Interval (ms)'), value: attr.autoInterval,
209 min: 1000, max: 10000, step: 500,
210 onChange: function (v) { setAttr({ autoInterval: v }); },
211 __nextHasNoMarginBottom: true }),
212 el(ToggleControl, { label: __('Show Label'), checked: attr.showLabel,
213 onChange: function (v) { setAttr({ showLabel: v }); },
214 __nextHasNoMarginBottom: true }),
215 ),
216
217 /* Colors */
218
219 el(PanelBody, { title: __('Typography', 'blockenberg'), initialOpen: false },
220 getTypoControl() && el(getTypoControl(), {
221 label: __('Label Typography', 'blockenberg'),
222 value: attr.labelTypo || {},
223 onChange: function (v) { setAttr({ labelTypo: v }); }
224 })
225 ),
226 el(PanelColorSettings, {
227 title: __('Colors'), initialOpen: false,
228 colorSettings: [
229 { label: __('Label Text'), value: attr.labelColor,
230 onChange: function (v) { setAttr({ labelColor: v || '#ffffff' }); } },
231 { label: __('Label BG'), value: attr.labelBg,
232 onChange: function (v) { setAttr({ labelBg: v || 'rgba(0,0,0,0.5)' }); } }
233 ]
234 })
235 );
236
237 return el(wp.element.Fragment, {}, inspector,
238 el('div', bp,
239 el('div', {
240 style: {
241 display: 'grid',
242 gridTemplateColumns: 'repeat(' + attr.columns + ', 1fr)',
243 gap: attr.gap + 'px'
244 }
245 },
246 attr.tiles.map(function (tile, i) {
247 return el('div', { key: i }, TilePreview(tile, attr, false));
248 })
249 )
250 )
251 );
252 },
253
254 save: function (props) {
255 var attr = props.attributes;
256 var bp = useBlockProps.save();
257 return el('div', bp,
258 el('div', { className: 'bkbg-rit-app', 'data-opts': JSON.stringify(attr) })
259 );
260 }
261 });
262 }() );
263