PluginProbe ʕ •ᴥ•ʔ
FrontBlocks for Gutenberg/GeneratePress / trunk
FrontBlocks for Gutenberg/GeneratePress vtrunk
trunk 0.2.0 0.2.1 0.2.2 0.2.3 0.2.4 0.2.5 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.1.0 1.2.0 1.2.1 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 ci-artifacts
frontblocks / assets / carousel / frontblocks-advanced-option.js
frontblocks / assets / carousel Last commit date
frontblocks-advanced-option.js 2 weeks ago frontblocks-advanced-option.jsx 2 weeks ago frontblocks-carousel-editor.css 4 months ago frontblocks-carousel.css 2 weeks ago frontblocks-carousel.js 2 weeks ago glide.min.js 8 months ago
frontblocks-advanced-option.js
633 lines
1 "use strict";
2
3 function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
4 function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
5 function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
6 // Add custom controls to the Advanced panel of GenerateBlocks Grid block
7 var addFilter = wp.hooks.addFilter;
8 var _wp$element = wp.element,
9 Fragment = _wp$element.Fragment,
10 useEffect = _wp$element.useEffect,
11 useRef = _wp$element.useRef;
12 var _wp$blockEditor = wp.blockEditor,
13 InspectorControls = _wp$blockEditor.InspectorControls,
14 PanelColorSettings = _wp$blockEditor.PanelColorSettings,
15 MediaUpload = _wp$blockEditor.MediaUpload;
16 var _wp$components = wp.components,
17 SelectControl = _wp$components.SelectControl,
18 TextControl = _wp$components.TextControl,
19 PanelBody = _wp$components.PanelBody,
20 ToggleControl = _wp$components.ToggleControl,
21 Button = _wp$components.Button;
22 var __ = wp.i18n.__;
23
24 /**
25 * Returns the document that renders block content.
26 * WordPress 6.x uses an <iframe> for the editor canvas.
27 */
28 function getEditorDocument() {
29 var iframe = document.querySelector('iframe[name="editor-canvas"]');
30 return iframe && iframe.contentDocument && iframe.contentDocument.body ? iframe.contentDocument : document;
31 }
32 var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-/;
33
34 /**
35 * Walk an element's subtree to find the container whose DIRECT children
36 * are actual blocks (UUID data-block). Stops at depth 4.
37 */
38 function findSlidesParent(el, depth) {
39 if (depth === 0) return null;
40 if (Array.from(el.children).some(function (c) {
41 return UUID_RE.test(c.dataset.block || '');
42 })) {
43 return el;
44 }
45 var _iterator = _createForOfIteratorHelper(el.children),
46 _step;
47 try {
48 for (_iterator.s(); !(_step = _iterator.n()).done;) {
49 var child = _step.value;
50 var found = findSlidesParent(child, depth - 1);
51 if (found) return found;
52 }
53 } catch (err) {
54 _iterator.e(err);
55 } finally {
56 _iterator.f();
57 }
58 return null;
59 }
60
61 /**
62 * Find the grid DOM element for a given block.
63 *
64 * For generateblocks/element: [data-block][data-type] IS the gb-element.
65 * Do NOT search inside – that returns a child item.
66 * For generateblocks/grid: look for .gb-grid-wrapper inside.
67 * For core/group: walk the subtree to find the element whose children
68 * are the real blocks, because WP nests them differently across versions.
69 */
70 function findGridEl(blockEl, name) {
71 if (name === 'generateblocks/element') {
72 return blockEl;
73 }
74 if (name === 'generateblocks/grid') {
75 if (blockEl.classList.contains('gb-grid-wrapper')) return blockEl;
76 var grid = blockEl.querySelector('.gb-grid-wrapper');
77 return grid || null;
78 }
79 if (name === 'core/group') {
80 // Walk up to 4 levels deep to find where the child blocks live.
81 return findSlidesParent(blockEl, 4) || blockEl;
82 }
83 if (name === 'core/query') {
84 return blockEl.querySelector('.wp-block-post-template') || null;
85 }
86 return null;
87 }
88 function addCustomCarouselPanel(BlockEdit) {
89 return function (props) {
90 if (props.name !== 'generateblocks/grid' && props.name !== 'generateblocks/element' && props.name !== 'core/group' && props.name !== 'core/query') {
91 return /*#__PURE__*/React.createElement(BlockEdit, props);
92 }
93 if (props.name === 'generateblocks/element') {
94 var styles = props.attributes.styles || {};
95 if (styles.display !== 'grid') {
96 return /*#__PURE__*/React.createElement(BlockEdit, props);
97 }
98 }
99 if (props.name === 'core/group') {
100 var layout = props.attributes.layout || {};
101 if (layout.type !== 'grid') {
102 return /*#__PURE__*/React.createElement(BlockEdit, props);
103 }
104 }
105 var _props$attributes = props.attributes,
106 _props$attributes$frb = _props$attributes.frblGridOption,
107 frblGridOption = _props$attributes$frb === void 0 ? 'none' : _props$attributes$frb,
108 _props$attributes$frb2 = _props$attributes.frblItemsToView,
109 frblItemsToView = _props$attributes$frb2 === void 0 ? '4' : _props$attributes$frb2,
110 _props$attributes$frb3 = _props$attributes.frblLaptopToView,
111 frblLaptopToView = _props$attributes$frb3 === void 0 ? '3' : _props$attributes$frb3,
112 _props$attributes$frb4 = _props$attributes.frblTabletToView,
113 frblTabletToView = _props$attributes$frb4 === void 0 ? '2' : _props$attributes$frb4,
114 _props$attributes$frb5 = _props$attributes.frblResponsiveToView,
115 frblResponsiveToView = _props$attributes$frb5 === void 0 ? '1' : _props$attributes$frb5,
116 _props$attributes$frb6 = _props$attributes.frblAutoplay,
117 frblAutoplay = _props$attributes$frb6 === void 0 ? '' : _props$attributes$frb6,
118 _props$attributes$frb7 = _props$attributes.frblGap,
119 frblGap = _props$attributes$frb7 === void 0 ? '20' : _props$attributes$frb7,
120 _props$attributes$frb8 = _props$attributes.frblButtons,
121 frblButtons = _props$attributes$frb8 === void 0 ? 'arrows' : _props$attributes$frb8,
122 _props$attributes$frb9 = _props$attributes.frblRewind,
123 frblRewind = _props$attributes$frb9 === void 0 ? true : _props$attributes$frb9,
124 frblButtonColor = _props$attributes.frblButtonColor,
125 frblButtonBgColor = _props$attributes.frblButtonBgColor,
126 _props$attributes$frb0 = _props$attributes.frblButtonsPosition,
127 frblButtonsPosition = _props$attributes$frb0 === void 0 ? 'side' : _props$attributes$frb0,
128 _props$attributes$frb1 = _props$attributes.frblArrowLeftUrl,
129 frblArrowLeftUrl = _props$attributes$frb1 === void 0 ? '' : _props$attributes$frb1,
130 _props$attributes$frb10 = _props$attributes.frblArrowRightUrl,
131 frblArrowRightUrl = _props$attributes$frb10 === void 0 ? '' : _props$attributes$frb10,
132 _props$attributes$frb11 = _props$attributes.frblDisableOnDesktop,
133 frblDisableOnDesktop = _props$attributes$frb11 === void 0 ? false : _props$attributes$frb11;
134
135 // ── Editor carousel preview ──────────────────────────────────────────
136 var stateRef = useRef(null);
137 useEffect(function () {
138 var mounted = true;
139 var timer = null;
140 function cleanup() {
141 if (!stateRef.current) return;
142 var _stateRef$current = stateRef.current,
143 gridEl = _stateRef$current.gridEl,
144 slides = _stateRef$current.slides,
145 spacer = _stateRef$current.spacer,
146 prevBtn = _stateRef$current.prevBtn,
147 nextBtn = _stateRef$current.nextBtn,
148 resizeObs = _stateRef$current.resizeObs,
149 scrollFn = _stateRef$current.scrollFn;
150
151 // Disconnect observer and scroll listener.
152 if (resizeObs) resizeObs.disconnect();
153 var editorDoc = getEditorDocument();
154 var editorScrollEl = editorDoc.documentElement || editorDoc.body;
155 if (scrollFn) editorScrollEl.removeEventListener('scroll', scrollFn, true);
156
157 // Remove arrows from outer window body (completely outside React).
158 [prevBtn, nextBtn].forEach(function (btn) {
159 if (btn && btn.parentNode) btn.parentNode.removeChild(btn);
160 });
161
162 // Remove right spacer element.
163 if (spacer && spacer.parentNode) spacer.parentNode.removeChild(spacer);
164
165 // Restore gridEl styles.
166 try {
167 var preventScroll = stateRef.current.preventScroll;
168 if (preventScroll) {
169 gridEl.removeEventListener('wheel', preventScroll);
170 gridEl.removeEventListener('touchstart', preventScroll);
171 gridEl.removeEventListener('touchmove', preventScroll);
172 }
173 gridEl.classList.remove('frbl-carousel-noscrollbar');
174 ['display', 'flex-wrap', 'gap', 'overflow-x', 'scroll-behavior', 'padding-left', 'padding-right', 'max-width', 'grid-template-columns'].forEach(function (p) {
175 return gridEl.style.removeProperty(p);
176 });
177 slides.forEach(function (slide) {
178 ['flex-shrink', 'width', 'min-width', 'margin-left', 'margin-right', 'grid-column', 'grid-row'].forEach(function (p) {
179 return slide.style.removeProperty(p);
180 });
181 });
182 } catch (e) {}
183 stateRef.current = null;
184 }
185 function init() {
186 if (!mounted) return;
187 cleanup();
188 var editorDoc = getEditorDocument();
189
190 // GB 2.x wraps blocks in a root element that shares the same data-block UUID.
191 // Use data-type to select the correct inner element; fall back for native blocks.
192 var blockEl = editorDoc.querySelector("[data-block=\"".concat(props.clientId, "\"][data-type=\"").concat(props.name, "\"]"));
193 if (!blockEl) {
194 blockEl = editorDoc.querySelector("[data-block=\"".concat(props.clientId, "\"]"));
195 }
196 if (!blockEl) return;
197 var gridEl = findGridEl(blockEl, props.name);
198 if (!gridEl) return;
199
200 // For core/query, <li> items don't have data-block UUIDs (server-rendered).
201 // For other blocks, filter by UUID data-block attribute.
202 var isQueryLoop = props.name === 'core/query';
203 var slides = isQueryLoop ? Array.from(gridEl.children).filter(function (el) {
204 return el.tagName === 'LI';
205 }) : Array.from(gridEl.children).filter(function (el) {
206 return UUID_RE.test(el.dataset.block || '');
207 });
208 if (slides.length === 0) return;
209 var perView = Math.max(1, parseInt(frblItemsToView) || 4);
210 var gap = Math.max(0, parseInt(frblGap) || 20);
211 var btnColor = frblButtonColor || '#fff';
212 var btnBg = frblButtonBgColor || 'rgba(0,0,0,0.45)';
213
214 // For core/query, force flex via setProperty to beat WP's grid CSS.
215 if (isQueryLoop) {
216 gridEl.style.setProperty('display', 'flex', 'important');
217 gridEl.style.setProperty('flex-wrap', 'nowrap', 'important');
218 gridEl.style.setProperty('max-width', 'none', 'important');
219 gridEl.style.setProperty('grid-template-columns', 'none', 'important');
220 gridEl.style.setProperty('list-style', 'none', 'important');
221 gridEl.style.setProperty('padding-left', '0', 'important');
222 }
223
224 // Measure content-box width before any style changes.
225 var editorWin = editorDoc.defaultView || window;
226 var ARROW_W = 40; // px reserved on each side for arrow buttons.
227 var cs = editorWin.getComputedStyle(gridEl);
228 var innerW = gridEl.getBoundingClientRect().width - (parseFloat(cs.paddingLeft) || 0) - (parseFloat(cs.paddingRight) || 0);
229 var totalWidth = Math.round(innerW) || 600;
230 // Content area after reserving space for both arrow buttons.
231 var contentW = totalWidth - ARROW_W * 2;
232 var slideWidth = Math.round((contentW - gap * (perView - 1)) / perView);
233 var step = slideWidth + gap;
234
235 // ── Apply scroll-based layout directly to gridEl ─────────────
236 // No DOM restructuring → no React reconciliation conflicts.
237 gridEl.classList.add('frbl-carousel-noscrollbar');
238 if (!isQueryLoop) {
239 gridEl.style.display = 'flex';
240 gridEl.style.flexWrap = 'nowrap';
241 gridEl.style.paddingLeft = ARROW_W + 'px';
242 } else {
243 // paddingLeft already set via setProperty above; override with arrow offset.
244 gridEl.style.setProperty('padding-left', ARROW_W + 'px', 'important');
245 }
246 gridEl.style.gap = gap + 'px';
247 gridEl.style.overflowX = 'scroll';
248 gridEl.style.scrollBehavior = 'smooth';
249 gridEl.style.paddingRight = '0';
250 slides.forEach(function (slide) {
251 slide.style.flexShrink = '0';
252 slide.style.width = slideWidth + 'px';
253 slide.style.minWidth = slideWidth + 'px';
254 slide.style.marginLeft = '0';
255 slide.style.marginRight = '0';
256 slide.style.gridColumn = 'unset';
257 slide.style.gridRow = 'unset';
258 });
259
260 // Right-side spacer: Chrome does not include padding-right in horizontal
261 // scroll extent, so we use a real flex child to guarantee right space.
262 var appender = gridEl.querySelector('.block-list-appender');
263 var spacer = editorDoc.createElement('span');
264 spacer.setAttribute('data-frbl-spacer', '1');
265 spacer.style.cssText = "display:block;flex-shrink:0;width:".concat(ARROW_W, "px;min-width:").concat(ARROW_W, "px;");
266 gridEl.insertBefore(spacer, appender || null);
267
268 // Prevent manual scroll — only arrows drive navigation.
269 var preventScroll = function preventScroll(e) {
270 return e.preventDefault();
271 };
272 gridEl.addEventListener('wheel', preventScroll, {
273 passive: false
274 });
275 gridEl.addEventListener('touchstart', preventScroll, {
276 passive: false
277 });
278 gridEl.addEventListener('touchmove', preventScroll, {
279 passive: false
280 });
281
282 // ── Navigation (scrollLeft, item-by-item) ────────────────────
283 var idx = 0;
284 var lastIdx = Math.max(0, slides.length - perView);
285 function scrollTo(n) {
286 if (n > lastIdx) {
287 // Wrap forward to start.
288 gridEl.style.scrollBehavior = 'auto';
289 gridEl.scrollLeft = 0;
290 void gridEl.offsetWidth;
291 gridEl.style.scrollBehavior = 'smooth';
292 idx = 0;
293 return;
294 }
295 if (n < 0) {
296 // Wrap back to end.
297 gridEl.style.scrollBehavior = 'auto';
298 gridEl.scrollLeft = Math.round(lastIdx * step);
299 void gridEl.offsetWidth;
300 gridEl.style.scrollBehavior = 'smooth';
301 idx = lastIdx;
302 return;
303 }
304 idx = n;
305 gridEl.scrollLeft = Math.round(idx * step);
306 }
307
308 // ── Arrows in OUTER document body ────────────────────────────
309 // Placing them outside the iframe means React never touches them.
310 var iframe = document.querySelector('iframe[name="editor-canvas"]');
311 function updateArrowPos() {
312 if (!stateRef.current) return;
313 var ifrRect = iframe ? iframe.getBoundingClientRect() : {
314 top: 0,
315 left: 0
316 };
317 var rect = gridEl.getBoundingClientRect(); // coords in iframe viewport
318 var midY = Math.round(ifrRect.top + rect.top + rect.height / 2 - 16);
319 prevBtn.style.top = midY + 'px';
320 prevBtn.style.left = Math.round(ifrRect.left + rect.left + 8) + 'px';
321 nextBtn.style.top = midY + 'px';
322 nextBtn.style.right = Math.round(window.innerWidth - (ifrRect.left + rect.right) + 8) + 'px';
323 }
324 function makeArrow(dir) {
325 var btn = document.createElement('button');
326 btn.type = 'button';
327 btn.className = "frbl-editor-arrow frbl-editor-arrow-".concat(dir);
328 btn.setAttribute('aria-label', dir === 'prev' ? 'Previous slide' : 'Next slide');
329 btn.style.cssText = "position:fixed;z-index:99999;background-color:".concat(btnBg, ";");
330 var d = dir === 'prev' ? 'M6 1L1 6L6 11' : 'M1 11L6 6L1 1';
331 btn.innerHTML = "<svg width=\"7\" height=\"12\" viewBox=\"0 0 7 12\" fill=\"none\"><path d=\"".concat(d, "\" stroke=\"").concat(btnColor, "\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>");
332 btn.addEventListener('click', function (e) {
333 e.stopPropagation();
334 scrollTo(dir === 'prev' ? idx - 1 : idx + 1);
335 });
336 document.body.appendChild(btn);
337 return btn;
338 }
339 var prevBtn = makeArrow('prev');
340 var nextBtn = makeArrow('next');
341 updateArrowPos();
342
343 // Keep arrows positioned correctly when the editor scrolls or resizes.
344 var resizeObs = new ResizeObserver(updateArrowPos);
345 resizeObs.observe(gridEl);
346 var editorScrollEl = editorDoc.documentElement || editorDoc.body;
347 var scrollFn = updateArrowPos;
348 editorScrollEl.addEventListener('scroll', scrollFn, {
349 passive: true,
350 capture: true
351 });
352 stateRef.current = {
353 gridEl: gridEl,
354 slides: slides,
355 spacer: spacer,
356 prevBtn: prevBtn,
357 nextBtn: nextBtn,
358 resizeObs: resizeObs,
359 scrollFn: scrollFn,
360 preventScroll: preventScroll
361 };
362 }
363 if (frblGridOption !== 'none') {
364 timer = setTimeout(init, 300);
365 } else {
366 cleanup();
367 }
368 return function () {
369 mounted = false;
370 if (timer) clearTimeout(timer);
371 cleanup();
372 };
373 }, [frblGridOption, frblItemsToView, frblGap, frblButtonColor, frblButtonBgColor, props.clientId]);
374 // ── Inspector panel ──────────────────────────────────────────────────
375
376 return /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement(BlockEdit, props), /*#__PURE__*/React.createElement(InspectorControls, null, /*#__PURE__*/React.createElement(PanelBody, {
377 title: __('FrontBlocks - Carousel', 'frontblocks'),
378 initialOpen: true
379 }, /*#__PURE__*/React.createElement(SelectControl, {
380 label: __('FrontBlocks Grid Option', 'frontblocks'),
381 value: frblGridOption,
382 options: [{
383 label: __('None', 'frontblocks'),
384 value: 'none'
385 }, {
386 label: __('Carousel', 'frontblocks'),
387 value: 'carousel'
388 }, {
389 label: __('Slider', 'frontblocks'),
390 value: 'slider'
391 }],
392 onChange: function onChange(value) {
393 return props.setAttributes({
394 frblGridOption: value
395 });
396 },
397 help: __('This option gives the option to make carousel in your grid block.', 'frontblocks')
398 }), frblGridOption !== 'none' && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(TextControl, {
399 label: __('Items to view (Desktop)', 'frontblocks'),
400 value: frblItemsToView,
401 onChange: function onChange(value) {
402 return props.setAttributes({
403 frblItemsToView: value
404 });
405 },
406 help: __('Number of items to show on desktop (>1200px)', 'frontblocks')
407 }), /*#__PURE__*/React.createElement(TextControl, {
408 label: __('Items to view (Laptop)', 'frontblocks'),
409 value: frblLaptopToView,
410 onChange: function onChange(value) {
411 return props.setAttributes({
412 frblLaptopToView: value
413 });
414 },
415 help: __('Number of items to show on laptop (992px-1199px)', 'frontblocks')
416 }), /*#__PURE__*/React.createElement(TextControl, {
417 label: __('Items to view (Tablet)', 'frontblocks'),
418 value: frblTabletToView,
419 onChange: function onChange(value) {
420 return props.setAttributes({
421 frblTabletToView: value
422 });
423 },
424 help: __('Number of items to show on tablet (768px-991px)', 'frontblocks')
425 }), /*#__PURE__*/React.createElement(TextControl, {
426 label: __('Items to view (Mobile)', 'frontblocks'),
427 value: frblResponsiveToView,
428 onChange: function onChange(value) {
429 return props.setAttributes({
430 frblResponsiveToView: value
431 });
432 },
433 help: __('Number of items to show on mobile (<768px)', 'frontblocks')
434 }), /*#__PURE__*/React.createElement(TextControl, {
435 label: __('Autoplay (seconds)', 'frontblocks'),
436 value: frblAutoplay,
437 onChange: function onChange(value) {
438 return props.setAttributes({
439 frblAutoplay: value
440 });
441 }
442 }), /*#__PURE__*/React.createElement(TextControl, {
443 label: __('Gap (px)', 'frontblocks'),
444 value: frblGap,
445 onChange: function onChange(value) {
446 return props.setAttributes({
447 frblGap: value
448 });
449 },
450 help: __('Space between slides in pixels. Leave empty for 20.', 'frontblocks')
451 }), frblGridOption === 'slider' && /*#__PURE__*/React.createElement(ToggleControl, {
452 label: __('Rewind', 'frontblocks'),
453 checked: frblRewind,
454 onChange: function onChange(value) {
455 return props.setAttributes({
456 frblRewind: value
457 });
458 }
459 }), /*#__PURE__*/React.createElement(SelectControl, {
460 label: __('Buttons', 'frontblocks'),
461 value: frblButtons,
462 options: [{
463 label: __('None', 'frontblocks'),
464 value: 'none'
465 }, {
466 label: __('Bullets', 'frontblocks'),
467 value: 'bullets'
468 }, {
469 label: __('Arrows', 'frontblocks'),
470 value: 'arrows'
471 }],
472 onChange: function onChange(value) {
473 return props.setAttributes({
474 frblButtons: value
475 });
476 }
477 }), frblButtons === 'arrows' && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(SelectControl, {
478 label: __('Buttons Position', 'frontblocks'),
479 value: frblButtonsPosition,
480 options: [{
481 label: __('Side (left & right)', 'frontblocks'),
482 value: 'side'
483 }, {
484 label: __('Bottom left', 'frontblocks'),
485 value: 'bottom-left'
486 }, {
487 label: __('Bottom right', 'frontblocks'),
488 value: 'bottom-right'
489 }, {
490 label: __('Top left', 'frontblocks'),
491 value: 'top-left'
492 }, {
493 label: __('Top right', 'frontblocks'),
494 value: 'top-right'
495 }],
496 onChange: function onChange(value) {
497 return props.setAttributes({
498 frblButtonsPosition: value
499 });
500 }
501 }), /*#__PURE__*/React.createElement("div", {
502 style: {
503 marginBottom: '12px'
504 }
505 }, /*#__PURE__*/React.createElement("p", {
506 style: {
507 marginBottom: '4px',
508 fontWeight: 500
509 }
510 }, __('Left arrow icon', 'frontblocks')), frblArrowLeftUrl && /*#__PURE__*/React.createElement("img", {
511 src: frblArrowLeftUrl,
512 alt: "",
513 style: {
514 display: 'block',
515 width: '32px',
516 height: '32px',
517 marginBottom: '6px',
518 objectFit: 'contain'
519 }
520 }), /*#__PURE__*/React.createElement(MediaUpload, {
521 onSelect: function onSelect(media) {
522 return props.setAttributes({
523 frblArrowLeftUrl: media.url
524 });
525 },
526 allowedTypes: ['image'],
527 value: frblArrowLeftUrl,
528 render: function render(_ref) {
529 var open = _ref.open;
530 return /*#__PURE__*/React.createElement("div", {
531 style: {
532 display: 'flex',
533 gap: '6px',
534 flexWrap: 'wrap'
535 }
536 }, /*#__PURE__*/React.createElement(Button, {
537 onClick: open,
538 variant: "secondary",
539 size: "small"
540 }, frblArrowLeftUrl ? __('Change', 'frontblocks') : __('Select SVG', 'frontblocks')), frblArrowLeftUrl && /*#__PURE__*/React.createElement(Button, {
541 onClick: function onClick() {
542 return props.setAttributes({
543 frblArrowLeftUrl: ''
544 });
545 },
546 variant: "link",
547 isDestructive: true,
548 size: "small"
549 }, __('Remove', 'frontblocks')));
550 }
551 })), /*#__PURE__*/React.createElement("div", {
552 style: {
553 marginBottom: '12px'
554 }
555 }, /*#__PURE__*/React.createElement("p", {
556 style: {
557 marginBottom: '4px',
558 fontWeight: 500
559 }
560 }, __('Right arrow icon', 'frontblocks')), frblArrowRightUrl && /*#__PURE__*/React.createElement("img", {
561 src: frblArrowRightUrl,
562 alt: "",
563 style: {
564 display: 'block',
565 width: '32px',
566 height: '32px',
567 marginBottom: '6px',
568 objectFit: 'contain'
569 }
570 }), /*#__PURE__*/React.createElement(MediaUpload, {
571 onSelect: function onSelect(media) {
572 return props.setAttributes({
573 frblArrowRightUrl: media.url
574 });
575 },
576 allowedTypes: ['image'],
577 value: frblArrowRightUrl,
578 render: function render(_ref2) {
579 var open = _ref2.open;
580 return /*#__PURE__*/React.createElement("div", {
581 style: {
582 display: 'flex',
583 gap: '6px',
584 flexWrap: 'wrap'
585 }
586 }, /*#__PURE__*/React.createElement(Button, {
587 onClick: open,
588 variant: "secondary",
589 size: "small"
590 }, frblArrowRightUrl ? __('Change', 'frontblocks') : __('Select SVG', 'frontblocks')), frblArrowRightUrl && /*#__PURE__*/React.createElement(Button, {
591 onClick: function onClick() {
592 return props.setAttributes({
593 frblArrowRightUrl: ''
594 });
595 },
596 variant: "link",
597 isDestructive: true,
598 size: "small"
599 }, __('Remove', 'frontblocks')));
600 }
601 }))), /*#__PURE__*/React.createElement(PanelColorSettings, {
602 title: __('Button Colors', 'frontblocks'),
603 colorSettings: [{
604 value: frblButtonColor,
605 onChange: function onChange(color) {
606 return props.setAttributes({
607 frblButtonColor: color
608 });
609 },
610 label: __('Color button', 'frontblocks')
611 }, {
612 value: frblButtonBgColor,
613 onChange: function onChange(color) {
614 return props.setAttributes({
615 frblButtonBgColor: color
616 });
617 },
618 label: __('Color background button', 'frontblocks')
619 }]
620 }), /*#__PURE__*/React.createElement(ToggleControl, {
621 label: __('Disable on Desktop', 'frontblocks'),
622 checked: frblDisableOnDesktop,
623 onChange: function onChange(value) {
624 return props.setAttributes({
625 frblDisableOnDesktop: value
626 });
627 },
628 help: __('If enabled, carousel/slider will only work on mobile devices.', 'frontblocks')
629 })))));
630 };
631 }
632 addFilter('editor.BlockEdit', 'frontblocks/gb-grid-carousel-panel', addCustomCarouselPanel);
633