@cntrl-site/components 0.1.0-alpha.3 → 0.1.0-alpha.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { jsx, Fragment, jsxs } from "react/jsx-runtime";
2
- import React, { useState, useEffect, useRef, useMemo } from "react";
2
+ import React, { useState, useEffect, useRef, useMemo, useCallback } from "react";
3
3
  import { Splide, SplideSlide } from "@splidejs/react-splide";
4
4
  import cn from "classnames";
5
5
  import { createPortal } from "react-dom";
@@ -563,15 +563,28 @@ const ControlSliderComponent = {
563
563
  },
564
564
  offset: {
565
565
  type: "object",
566
+ title: "Offset",
566
567
  display: {
567
- type: "offset-controls"
568
+ type: "group"
568
569
  },
569
570
  properties: {
570
571
  x: {
571
- type: "number"
572
+ type: "number",
573
+ label: "X",
574
+ scalingEnabled: true,
575
+ display: {
576
+ type: "numeric-input",
577
+ visible: true
578
+ }
572
579
  },
573
580
  y: {
574
- type: "number"
581
+ type: "number",
582
+ label: "Y",
583
+ scalingEnabled: true,
584
+ display: {
585
+ type: "numeric-input",
586
+ visible: true
587
+ }
575
588
  }
576
589
  }
577
590
  },
@@ -624,15 +637,28 @@ const ControlSliderComponent = {
624
637
  },
625
638
  offset: {
626
639
  type: "object",
640
+ title: "Offset",
627
641
  display: {
628
- type: "offset-controls"
642
+ type: "group"
629
643
  },
630
644
  properties: {
631
645
  x: {
632
- type: "number"
646
+ type: "number",
647
+ label: "X",
648
+ scalingEnabled: true,
649
+ display: {
650
+ type: "numeric-input",
651
+ visible: true
652
+ }
633
653
  },
634
654
  y: {
635
- type: "number"
655
+ type: "number",
656
+ label: "Y",
657
+ scalingEnabled: true,
658
+ display: {
659
+ type: "numeric-input",
660
+ visible: true
661
+ }
636
662
  }
637
663
  }
638
664
  },
@@ -688,14 +714,26 @@ const ControlSliderComponent = {
688
714
  offset: {
689
715
  type: "object",
690
716
  display: {
691
- type: "offset-controls"
717
+ type: "group"
692
718
  },
693
719
  properties: {
694
720
  x: {
695
- type: "number"
721
+ type: "number",
722
+ label: "X",
723
+ scalingEnabled: true,
724
+ display: {
725
+ type: "numeric-input",
726
+ visible: true
727
+ }
696
728
  },
697
729
  y: {
698
- type: "number"
730
+ type: "number",
731
+ label: "Y",
732
+ scalingEnabled: true,
733
+ display: {
734
+ type: "numeric-input",
735
+ visible: true
736
+ }
699
737
  }
700
738
  }
701
739
  },
@@ -1441,6 +1479,7 @@ const ControlImageRevealSliderComponent = {
1441
1479
  }
1442
1480
  }
1443
1481
  };
1482
+ const background = "Lightbox-module__background___wf1Ii";
1444
1483
  const backdropStyle = "Lightbox-module__backdropStyle___y7avj";
1445
1484
  const editor = "Lightbox-module__editor___Vh82D";
1446
1485
  const contentStyle = "Lightbox-module__contentStyle___FzFaW";
@@ -1462,15 +1501,20 @@ const thumbsAlignStart = "Lightbox-module__thumbsAlignStart___uiFIV";
1462
1501
  const thumbsAlignCenter = "Lightbox-module__thumbsAlignCenter___sbUPA";
1463
1502
  const thumbsAlignEnd = "Lightbox-module__thumbsAlignEnd___OA9N4";
1464
1503
  const thumbItem = "Lightbox-module__thumbItem___zROyu";
1465
- const thumbImage = "Lightbox-module__thumbImage___xGakV";
1466
1504
  const closeButton = "Lightbox-module__closeButton___r3Dur";
1467
1505
  const fadeIn = "Lightbox-module__fadeIn___sHwRK";
1468
1506
  const slideInLeft = "Lightbox-module__slideInLeft___P-XRo";
1469
1507
  const slideInRight = "Lightbox-module__slideInRight___ZQqFi";
1470
1508
  const slideInTop = "Lightbox-module__slideInTop___XRKCs";
1471
1509
  const slideInBottom = "Lightbox-module__slideInBottom___TYOBS";
1510
+ const fadeOut = "Lightbox-module__fadeOut___h2fpQ";
1511
+ const slideOutLeft = "Lightbox-module__slideOutLeft___J-eMU";
1512
+ const slideOutRight = "Lightbox-module__slideOutRight___iZUQz";
1513
+ const slideOutTop = "Lightbox-module__slideOutTop___3TXF9";
1514
+ const slideOutBottom = "Lightbox-module__slideOutBottom___SB5ws";
1472
1515
  const scaleSlide = "Lightbox-module__scaleSlide___wS7d4";
1473
1516
  const styles = {
1517
+ background,
1474
1518
  backdropStyle,
1475
1519
  editor,
1476
1520
  contentStyle,
@@ -1492,16 +1536,20 @@ const styles = {
1492
1536
  thumbsAlignCenter,
1493
1537
  thumbsAlignEnd,
1494
1538
  thumbItem,
1495
- thumbImage,
1496
1539
  closeButton,
1497
1540
  fadeIn,
1498
1541
  slideInLeft,
1499
1542
  slideInRight,
1500
1543
  slideInTop,
1501
1544
  slideInBottom,
1545
+ fadeOut,
1546
+ slideOutLeft,
1547
+ slideOutRight,
1548
+ slideOutTop,
1549
+ slideOutBottom,
1502
1550
  scaleSlide
1503
1551
  };
1504
- const getPositionStyles = (position, offset) => {
1552
+ const getPositionStyles = (position, offset, isEditor) => {
1505
1553
  const styles2 = {};
1506
1554
  const [vertical, horizontal] = position.split("-");
1507
1555
  if (vertical === "top") {
@@ -1525,16 +1573,41 @@ const getPositionStyles = (position, offset) => {
1525
1573
  styles2.right = "0";
1526
1574
  }
1527
1575
  if (vertical === "middle" && horizontal === "center") {
1528
- styles2.transform = `translate(calc(-50% + ${offset.x}px), calc(-50% + ${offset.y}px))`;
1576
+ styles2.transform = `translate(calc(-50% + ${scalingValue(offset.x, isEditor)}), calc(-50% + ${scalingValue(offset.y, isEditor)}))`;
1529
1577
  } else if (vertical === "middle") {
1530
- styles2.transform = `translate(${offset.x}px, calc(-50% + ${offset.y}px))`;
1578
+ styles2.transform = `translate(${scalingValue(offset.x, isEditor)}, calc(-50% + ${scalingValue(offset.y, isEditor)}))`;
1531
1579
  } else if (horizontal === "center") {
1532
- styles2.transform = `translate(calc(-50% + ${offset.x}px), ${offset.y}px)`;
1580
+ styles2.transform = `translate(calc(-50% + ${scalingValue(offset.x, isEditor)}), ${scalingValue(offset.y, isEditor)})`;
1533
1581
  } else {
1534
- styles2.transform = `translate(${offset.x}px, ${offset.y}px)`;
1582
+ styles2.transform = `translate(${scalingValue(offset.x, isEditor)}, ${scalingValue(offset.y, isEditor)})`;
1535
1583
  }
1536
1584
  return styles2;
1537
1585
  };
1586
+ function getDisplayedImageRect(img2) {
1587
+ const container = img2.getBoundingClientRect();
1588
+ const containerW = container.width;
1589
+ const containerH = container.height;
1590
+ const imgW = img2.naturalWidth;
1591
+ const imgH = img2.naturalHeight;
1592
+ const containerRatio = containerW / containerH;
1593
+ const imgRatio = imgW / imgH;
1594
+ let renderedW, renderedH;
1595
+ if (imgRatio > containerRatio) {
1596
+ renderedW = containerW;
1597
+ renderedH = containerW / imgRatio;
1598
+ } else {
1599
+ renderedH = containerH;
1600
+ renderedW = containerH * imgRatio;
1601
+ }
1602
+ const offsetX = (containerW - renderedW) / 2 + container.left;
1603
+ const offsetY = (containerH - renderedH) / 2 + container.top;
1604
+ return {
1605
+ x: offsetX,
1606
+ y: offsetY,
1607
+ width: renderedW,
1608
+ height: renderedH
1609
+ };
1610
+ }
1538
1611
  function LightboxGallery({ settings, content, styles: styles2, portalId, activeEvent, isEditor }) {
1539
1612
  const [open, setOpen] = React.useState(false);
1540
1613
  const { url } = settings.thumbnailBlock.cover;
@@ -1556,34 +1629,147 @@ function LightboxGallery({ settings, content, styles: styles2, portalId, activeE
1556
1629
  onClick: () => setOpen(true)
1557
1630
  }
1558
1631
  ),
1559
- /* @__PURE__ */ jsx(Lightbox, { isOpen: open, onClose: () => setOpen(false), content, settings, portalId, isEditor })
1632
+ /* @__PURE__ */ jsx(Lightbox, { isOpen: open, onClose: () => setOpen(false), content, settings, styles: styles2, portalId, isEditor, activeEvent })
1560
1633
  ] });
1561
1634
  }
1562
- const Lightbox = ({ isOpen, onClose, content, settings, closeOnBackdropClick = true, closeOnEsc = true, portalId, isEditor }) => {
1635
+ const Lightbox = ({ isOpen, onClose, content, styles: lightboxStyles, settings, portalId, isEditor }) => {
1636
+ const { widthSettings, fontSettings, letterSpacing, textAlign, wordSpacing, fontSizeLineHeight, textAppearance, color } = lightboxStyles.caption;
1563
1637
  const [currentIndex, setCurrentIndex] = React.useState(0);
1638
+ const [splideKey, setSplideKey] = React.useState(0);
1639
+ const [isClosing, setIsClosing] = React.useState(false);
1564
1640
  const lightboxRef = useRef(null);
1565
- const resizeObserverRef = useRef(null);
1641
+ const prevSliderTypeRef = useRef(null);
1642
+ const imageRef = useRef(null);
1643
+ const isClosingRef = useRef(false);
1644
+ const contentRef = useRef(null);
1645
+ const animationEndHandlerRef = useRef(null);
1646
+ const appearAnimationEndHandlerRef = useRef(null);
1566
1647
  const { appear, triggers, slider, thumbnail, controls, area, caption: caption2, layout } = settings.lightboxBlock;
1648
+ const appearDurationMs = appear.duration ? parseInt(appear.duration) : 300;
1649
+ useEffect(() => {
1650
+ window.addEventListener("ArticleEditor.Layout:change", () => {
1651
+ var _a, _b;
1652
+ (_b = (_a = lightboxRef.current) == null ? void 0 : _a.splide) == null ? void 0 : _b.refresh();
1653
+ });
1654
+ return () => {
1655
+ window.removeEventListener("ArticleEditor.Layout:change", () => {
1656
+ var _a, _b;
1657
+ (_b = (_a = lightboxRef.current) == null ? void 0 : _a.splide) == null ? void 0 : _b.refresh();
1658
+ });
1659
+ };
1660
+ }, []);
1661
+ const handleClose = useCallback(() => {
1662
+ const isMobile = window.matchMedia("(max-width: 768px)").matches;
1663
+ const colorAlpha = getColorAlpha(area.color);
1664
+ if (isMobile && !isEditor && colorAlpha > 0.9) {
1665
+ document.body.style.backgroundColor = "";
1666
+ }
1667
+ setIsClosing(true);
1668
+ isClosingRef.current = true;
1669
+ const handleAnimationEnd = (e) => {
1670
+ if (e.target === contentRef.current && e.animationName) {
1671
+ if (contentRef.current && animationEndHandlerRef.current) {
1672
+ contentRef.current.removeEventListener("animationend", animationEndHandlerRef.current);
1673
+ }
1674
+ animationEndHandlerRef.current = null;
1675
+ onClose();
1676
+ setIsClosing(false);
1677
+ }
1678
+ };
1679
+ if (contentRef.current) {
1680
+ animationEndHandlerRef.current = handleAnimationEnd;
1681
+ contentRef.current.addEventListener("animationend", handleAnimationEnd);
1682
+ }
1683
+ }, [onClose, appearDurationMs, area.color, isEditor]);
1567
1684
  const handleBackdropClick = (e) => {
1568
- if (!closeOnBackdropClick) return;
1569
1685
  if (e.target === e.currentTarget) {
1570
- onClose();
1686
+ handleClose();
1571
1687
  }
1572
1688
  };
1573
1689
  const handleImageWrapperClick = (e) => {
1574
- if (!closeOnBackdropClick) return;
1575
- if (e.target === e.currentTarget) {
1576
- onClose();
1690
+ var _a, _b;
1691
+ const currentImage = content[currentIndex];
1692
+ const isCover = (currentImage == null ? void 0 : currentImage.image.objectFit) === "cover";
1693
+ let clientX;
1694
+ let clientY;
1695
+ if ("changedTouches" in e && e.changedTouches.length > 0) {
1696
+ clientX = e.changedTouches[0].clientX;
1697
+ clientY = e.changedTouches[0].clientY;
1698
+ } else if ("clientX" in e) {
1699
+ clientX = e.clientX;
1700
+ clientY = e.clientY;
1701
+ } else {
1702
+ return;
1703
+ }
1704
+ let inside;
1705
+ if (isCover && imageRef.current) {
1706
+ const imgRect = imageRef.current.getBoundingClientRect();
1707
+ inside = clientX >= imgRect.left && clientX <= imgRect.right && clientY >= imgRect.top && clientY <= imgRect.bottom;
1708
+ } else {
1709
+ const rect = imageRef.current ? getDisplayedImageRect(imageRef.current) : null;
1710
+ if (!rect) {
1711
+ if (e.target === e.currentTarget) {
1712
+ handleClose();
1713
+ }
1714
+ return;
1715
+ }
1716
+ inside = clientX >= rect.x && clientX <= rect.x + rect.width && clientY >= rect.y && clientY <= rect.y + rect.height;
1717
+ }
1718
+ if (inside) {
1719
+ if (triggers.type === "click" && triggers.switch === "image") {
1720
+ if (triggers.repeat === "close" && currentIndex === content.length - 1) {
1721
+ handleClose();
1722
+ } else {
1723
+ (_a = lightboxRef.current) == null ? void 0 : _a.go("+1");
1724
+ }
1725
+ } else if (triggers.type === "click" && triggers.switch === "50/50") {
1726
+ const img2 = imageRef.current;
1727
+ if (img2) {
1728
+ const imgRect = img2.getBoundingClientRect();
1729
+ const clickX = clientX - imgRect.left;
1730
+ const clickY = clientY - imgRect.top;
1731
+ const imgWidth = imgRect.width;
1732
+ const imgHeight = imgRect.height;
1733
+ let dir;
1734
+ if (slider.direction === "horiz") {
1735
+ dir = clickX < imgWidth / 2 ? "-1" : "+1";
1736
+ } else {
1737
+ dir = clickY < imgHeight / 2 ? "-1" : "+1";
1738
+ }
1739
+ (_b = lightboxRef.current) == null ? void 0 : _b.go(dir);
1740
+ }
1741
+ }
1742
+ } else {
1743
+ handleClose();
1744
+ }
1745
+ };
1746
+ const handleContentClick = (e) => {
1747
+ const target = e.target;
1748
+ const currentTarget = e.currentTarget;
1749
+ if (target === currentTarget) {
1750
+ handleClose();
1751
+ return;
1752
+ }
1753
+ const isImg = target.tagName === "IMG" || target.closest("img");
1754
+ const isButton = target.tagName === "BUTTON" || target.closest("button");
1755
+ const isSplide = target.closest(".splide") || target.closest('[class*="splide"]');
1756
+ const isCaption = target.closest(`.${styles.caption}`);
1757
+ const isThumbnail = target.closest(`.${styles.thumbsContainer}`);
1758
+ if (!isImg && !isButton && !isSplide && !isCaption && !isThumbnail) {
1759
+ handleClose();
1577
1760
  }
1578
1761
  };
1579
1762
  const onImageClick = (e) => {
1580
1763
  var _a, _b;
1764
+ e.stopPropagation();
1581
1765
  if (triggers.type === "click" && triggers.switch === "image") {
1582
- e.stopPropagation();
1583
- (_a = lightboxRef.current) == null ? void 0 : _a.go("+1");
1766
+ if (triggers.repeat === "close" && currentIndex === content.length - 1) {
1767
+ handleClose();
1768
+ } else {
1769
+ (_a = lightboxRef.current) == null ? void 0 : _a.go("+1");
1770
+ }
1584
1771
  }
1585
1772
  if (triggers.type === "click" && triggers.switch === "50/50") {
1586
- e.stopPropagation();
1587
1773
  const img2 = e.currentTarget;
1588
1774
  const rect = img2.getBoundingClientRect();
1589
1775
  const clickX = e.clientX - rect.left;
@@ -1600,10 +1786,10 @@ const Lightbox = ({ isOpen, onClose, content, settings, closeOnBackdropClick = t
1600
1786
  }
1601
1787
  };
1602
1788
  useEffect(() => {
1603
- if (!isOpen || !closeOnEsc) return;
1789
+ if (!isOpen) return;
1604
1790
  const onKeyDown = (event) => {
1605
1791
  if (event.key === "Escape") {
1606
- onClose();
1792
+ handleClose();
1607
1793
  return;
1608
1794
  }
1609
1795
  if (event.key === "ArrowRight") {
@@ -1618,58 +1804,62 @@ const Lightbox = ({ isOpen, onClose, content, settings, closeOnBackdropClick = t
1618
1804
  return () => {
1619
1805
  window.removeEventListener("keydown", onKeyDown);
1620
1806
  };
1621
- }, [isOpen, closeOnEsc, onClose, content.length]);
1807
+ }, [isOpen, handleClose, content.length]);
1622
1808
  useEffect(() => {
1623
- if (isOpen) setCurrentIndex(0);
1809
+ if (isOpen) {
1810
+ setCurrentIndex(0);
1811
+ isClosingRef.current = false;
1812
+ setIsClosing(false);
1813
+ }
1814
+ return () => {
1815
+ if (contentRef.current && animationEndHandlerRef.current) {
1816
+ contentRef.current.removeEventListener("animationend", animationEndHandlerRef.current);
1817
+ animationEndHandlerRef.current = null;
1818
+ }
1819
+ };
1624
1820
  }, [isOpen]);
1625
1821
  useEffect(() => {
1626
- if (!isOpen) return;
1627
- if (resizeObserverRef.current) {
1628
- resizeObserverRef.current.disconnect();
1629
- resizeObserverRef.current = null;
1822
+ if (prevSliderTypeRef.current !== null && prevSliderTypeRef.current !== slider.type) {
1823
+ setSplideKey((prev) => prev + 1);
1630
1824
  }
1631
- const timeoutId = setTimeout(() => {
1632
- const activeSlide = document.querySelector(".splide__slide.is-active");
1633
- if (!activeSlide) return;
1634
- const img2 = activeSlide.querySelector("img");
1635
- const container = activeSlide.querySelector(`.${styles.imgWrapper}`);
1636
- if (!img2 || !container) return;
1637
- const updateImageSize = () => {
1638
- if (!img2.naturalWidth || !img2.naturalHeight) return;
1639
- const imageAspectRatio = img2.naturalWidth / img2.naturalHeight;
1640
- const containerWidth = container.clientWidth;
1641
- const containerHeight = container.clientHeight;
1642
- const containerAspectRatio = containerWidth / containerHeight;
1643
- if (imageAspectRatio > containerAspectRatio) {
1644
- img2.style.width = "100%";
1645
- } else {
1646
- img2.style.height = "100%";
1825
+ prevSliderTypeRef.current = slider.type;
1826
+ }, [slider.type]);
1827
+ useEffect(() => {
1828
+ if (!isOpen) return;
1829
+ const originalOverflow = document.body.style.overflow;
1830
+ document.body.style.overflow = "hidden";
1831
+ const isMobile = window.matchMedia("(max-width: 768px)").matches;
1832
+ const colorAlpha = getColorAlpha(area.color);
1833
+ const handleAppearAnimationEnd = (e) => {
1834
+ if (e.target === contentRef.current && !isClosingRef.current && e.animationName) {
1835
+ if (isMobile && !isEditor && colorAlpha > 0.9) {
1836
+ document.body.style.backgroundColor = area.color;
1647
1837
  }
1648
- };
1649
- if (img2.complete) {
1650
- updateImageSize();
1651
- } else {
1652
- img2.onload = updateImageSize;
1838
+ if (contentRef.current && appearAnimationEndHandlerRef.current) {
1839
+ contentRef.current.removeEventListener("animationend", appearAnimationEndHandlerRef.current);
1840
+ }
1841
+ appearAnimationEndHandlerRef.current = null;
1653
1842
  }
1654
- resizeObserverRef.current = new ResizeObserver(() => {
1655
- updateImageSize();
1656
- });
1657
- resizeObserverRef.current.observe(container);
1658
- resizeObserverRef.current.observe(img2);
1659
- }, 0);
1843
+ };
1844
+ if (contentRef.current && isMobile && !isEditor && colorAlpha > 0.9) {
1845
+ appearAnimationEndHandlerRef.current = handleAppearAnimationEnd;
1846
+ contentRef.current.addEventListener("animationend", handleAppearAnimationEnd);
1847
+ }
1848
+ const preventScroll = (e) => e.preventDefault();
1849
+ document.addEventListener("touchmove", preventScroll, { passive: false });
1660
1850
  return () => {
1661
- clearTimeout(timeoutId);
1662
- if (resizeObserverRef.current) {
1663
- resizeObserverRef.current.disconnect();
1664
- resizeObserverRef.current = null;
1851
+ document.body.style.overflow = originalOverflow;
1852
+ document.removeEventListener("touchmove", preventScroll);
1853
+ if (contentRef.current && appearAnimationEndHandlerRef.current) {
1854
+ contentRef.current.removeEventListener("animationend", appearAnimationEndHandlerRef.current);
1855
+ appearAnimationEndHandlerRef.current = null;
1665
1856
  }
1666
1857
  };
1667
- }, [isOpen, currentIndex, content]);
1858
+ }, [isOpen, area.color, isEditor]);
1668
1859
  const handleArrowClick = (dir) => {
1669
1860
  var _a;
1670
1861
  (_a = lightboxRef.current) == null ? void 0 : _a.go(dir);
1671
1862
  };
1672
- const appearDurationMs = appear.duration ? parseInt(appear.duration) : 300;
1673
1863
  const backdropDurationMs = appear.type === "fade in" || appear.type === "mix" ? Math.floor(appearDurationMs * 0.7) : appearDurationMs;
1674
1864
  const appearClass = (() => {
1675
1865
  if (appear.type === "fade in") return styles.fadeIn;
@@ -1707,247 +1897,400 @@ const Lightbox = ({ isOpen, onClose, content, settings, closeOnBackdropClick = t
1707
1897
  }
1708
1898
  return styles.fadeIn;
1709
1899
  })();
1710
- if (!isOpen) return null;
1900
+ const backdropDisappearClass = (() => {
1901
+ if (appear.type === "fade in" || appear.type === "mix") return styles.fadeOut;
1902
+ if (appear.type === "slide in") {
1903
+ switch (appear.direction) {
1904
+ case "left":
1905
+ return styles.slideOutLeft;
1906
+ case "right":
1907
+ return styles.slideOutRight;
1908
+ case "top":
1909
+ return styles.slideOutTop;
1910
+ case "bottom":
1911
+ return styles.slideOutBottom;
1912
+ default:
1913
+ return styles.slideOutRight;
1914
+ }
1915
+ }
1916
+ return styles.fadeOut;
1917
+ })();
1918
+ const disappearClass = (() => {
1919
+ if (appear.type === "fade in") return styles.fadeOut;
1920
+ if (appear.type === "slide in" || appear.type === "mix") {
1921
+ switch (appear.direction) {
1922
+ case "left":
1923
+ return styles.slideOutLeft;
1924
+ case "right":
1925
+ return styles.slideOutRight;
1926
+ case "top":
1927
+ return styles.slideOutTop;
1928
+ case "bottom":
1929
+ return styles.slideOutBottom;
1930
+ default:
1931
+ return styles.slideOutRight;
1932
+ }
1933
+ }
1934
+ return styles.fadeOut;
1935
+ })();
1936
+ useEffect(() => {
1937
+ if (!isOpen) return;
1938
+ const handleTouchEnd = (e) => {
1939
+ if (isClosingRef.current) {
1940
+ e.stopPropagation();
1941
+ return;
1942
+ }
1943
+ if (e.touches.length === 0 && e.changedTouches.length > 0) {
1944
+ const currentImage = content[currentIndex];
1945
+ const isCover = (currentImage == null ? void 0 : currentImage.image.objectFit) === "cover";
1946
+ const touch = e.changedTouches[0];
1947
+ let inside;
1948
+ if (isCover && imageRef.current) {
1949
+ const imgRect = imageRef.current.getBoundingClientRect();
1950
+ inside = touch.clientX >= imgRect.left && touch.clientX <= imgRect.right && touch.clientY >= imgRect.top && touch.clientY <= imgRect.bottom;
1951
+ } else {
1952
+ const rect = imageRef.current ? getDisplayedImageRect(imageRef.current) : null;
1953
+ if (!rect) return;
1954
+ inside = touch.clientX >= rect.x && touch.clientX <= rect.x + rect.width && touch.clientY >= rect.y && touch.clientY <= rect.y + rect.height;
1955
+ }
1956
+ if (!inside) {
1957
+ e.stopPropagation();
1958
+ isClosingRef.current = true;
1959
+ const blockNextClick = (clickEvent) => {
1960
+ clickEvent.stopPropagation();
1961
+ clickEvent.preventDefault();
1962
+ document.removeEventListener("click", blockNextClick, true);
1963
+ };
1964
+ document.addEventListener("click", blockNextClick, true);
1965
+ handleClose();
1966
+ }
1967
+ }
1968
+ };
1969
+ document.addEventListener("touchend", handleTouchEnd, { passive: true });
1970
+ return () => {
1971
+ document.removeEventListener("touchend", handleTouchEnd);
1972
+ };
1973
+ }, [isOpen, handleClose, currentIndex, content]);
1974
+ if (!isOpen && !isClosing) return null;
1711
1975
  return createPortal(
1712
- /* @__PURE__ */ jsx(
1713
- "div",
1714
- {
1715
- className: cn(styles.backdropStyle, backdropAppearClass, { [styles.editor]: isEditor }),
1716
- style: { backgroundColor: area.color, backdropFilter: `blur(${area.blur}px)`, animationDuration: `${backdropDurationMs}ms`, animationTimingFunction: "ease", animationFillMode: "both" },
1717
- onClick: handleBackdropClick,
1718
- children: /* @__PURE__ */ jsxs(
1719
- "div",
1720
- {
1721
- className: cn(styles.contentStyle, appearClass),
1722
- style: {
1723
- padding: `${layout.padding.top}px ${layout.padding.right}px ${layout.padding.bottom}px ${layout.padding.left}px`,
1724
- animationDuration: `${appearDurationMs}ms`,
1725
- animationTimingFunction: "ease",
1726
- animationFillMode: "both",
1727
- ...appear.type === "mix" && { animationDelay: `${backdropDurationMs}ms` },
1728
- "--splide-speed": triggers.duration || "500ms"
1729
- },
1730
- children: [
1731
- /* @__PURE__ */ jsx(
1732
- Splide,
1733
- {
1734
- onMove: (splide) => {
1735
- setCurrentIndex(splide.index);
1736
- },
1737
- ref: lightboxRef,
1738
- className: styles.lightboxSplide,
1739
- options: {
1740
- arrows: false,
1741
- speed: triggers.duration ? parseInt(triggers.duration) : 500,
1742
- direction: slider.direction === "horiz" || slider.type === "fade" || slider.type === "scale" ? "ltr" : "ttb",
1743
- pagination: false,
1744
- drag: triggers.type === "drag",
1745
- perPage: 1,
1746
- width: "100%",
1747
- height: "100%",
1748
- type: slider.type === "fade" || slider.type === "scale" ? "fade" : "loop",
1749
- padding: 0,
1750
- rewind: (slider.type === "scale" || slider.type === "fade") && appear.repeat !== "close"
1751
- },
1752
- style: { "--splide-speed": triggers.duration || "500ms" },
1753
- children: content.map((item, index) => {
1754
- const positionStyles = getPositionStyles(layout.position, layout.offset);
1755
- const imageStyle2 = slider.type === "scale" ? (() => {
1756
- const { transform, ...restStyles } = positionStyles;
1757
- return {
1758
- ...restStyles,
1759
- "--position-transform": transform || "none"
1760
- };
1761
- })() : positionStyles;
1762
- return /* @__PURE__ */ jsx(SplideSlide, { children: /* @__PURE__ */ jsx(
1763
- "div",
1764
- {
1765
- className: styles.imgWrapper,
1766
- onClick: handleImageWrapperClick,
1767
- style: {
1768
- padding: `${layout.padding.top}px ${layout.padding.right}px ${layout.padding.bottom}px ${layout.padding.left}px`
1769
- },
1770
- children: /* @__PURE__ */ jsx(
1771
- "img",
1772
- {
1773
- className: cn(styles.imageStyle, {
1774
- [styles.contain]: item.image.objectFit === "contain",
1775
- [styles.cover]: item.image.objectFit === "cover",
1776
- [styles.scaleSlide]: slider.type === "scale"
1777
- }),
1778
- src: item.image.url,
1779
- alt: item.image.name ?? "",
1780
- onClick: onImageClick,
1781
- style: imageStyle2
1782
- }
1783
- )
1784
- }
1785
- ) }, index);
1786
- })
1787
- }
1788
- ),
1789
- controls.isActive && /* @__PURE__ */ jsxs(Fragment, { children: [
1976
+ /* @__PURE__ */ jsxs(Fragment, { children: [
1977
+ /* @__PURE__ */ jsx(
1978
+ "div",
1979
+ {
1980
+ className: cn(styles.background, isClosing ? backdropDisappearClass : backdropAppearClass),
1981
+ style: {
1982
+ ...isEditor && { display: "none" },
1983
+ backgroundColor: area.color,
1984
+ backdropFilter: `blur(${area.blur}px)`,
1985
+ animationDuration: `${appearDurationMs}ms`,
1986
+ animationTimingFunction: "ease",
1987
+ animationFillMode: "both"
1988
+ }
1989
+ }
1990
+ ),
1991
+ /* @__PURE__ */ jsx(
1992
+ "div",
1993
+ {
1994
+ className: cn(styles.backdropStyle, { [styles.editor]: isEditor, [isClosing ? backdropDisappearClass : backdropAppearClass]: isEditor }),
1995
+ style: { ...isEditor && {
1996
+ backgroundColor: area.color,
1997
+ backdropFilter: `blur(${area.blur}px)`,
1998
+ animationDuration: `${appearDurationMs}ms`,
1999
+ animationTimingFunction: "ease",
2000
+ animationFillMode: "both"
2001
+ } },
2002
+ onClick: handleBackdropClick,
2003
+ onTouchEnd: handleBackdropClick,
2004
+ onTouchStart: handleBackdropClick,
2005
+ children: /* @__PURE__ */ jsxs(
2006
+ "div",
2007
+ {
2008
+ ref: contentRef,
2009
+ className: cn(styles.contentStyle, isClosing ? disappearClass : appearClass),
2010
+ onClick: handleContentClick,
2011
+ style: {
2012
+ animationDuration: `${appearDurationMs}ms`,
2013
+ animationTimingFunction: "ease",
2014
+ animationFillMode: "both",
2015
+ ...appear.type === "mix" && !isClosing && { animationDelay: `${backdropDurationMs / 2}ms` },
2016
+ ...appear.type === "mix" && isClosing && { animationDelay: "0ms" }
2017
+ },
2018
+ children: [
1790
2019
  /* @__PURE__ */ jsx(
2020
+ Splide,
2021
+ {
2022
+ onMove: (splide) => {
2023
+ setCurrentIndex(splide.index);
2024
+ },
2025
+ ref: lightboxRef,
2026
+ className: styles.lightboxSplide,
2027
+ options: {
2028
+ arrows: false,
2029
+ speed: slider.duration ? parseInt(slider.duration) : 500,
2030
+ direction: slider.direction === "horiz" || slider.type === "fade" || slider.type === "scale" ? "ltr" : "ttb",
2031
+ pagination: false,
2032
+ drag: triggers.type === "drag",
2033
+ perPage: 1,
2034
+ width: "100%",
2035
+ height: "100%",
2036
+ type: slider.type === "fade" || slider.type === "scale" ? "fade" : "loop",
2037
+ padding: 0,
2038
+ rewind: (slider.type === "scale" || slider.type === "fade") && triggers.repeat === "loop"
2039
+ },
2040
+ style: { "--splide-speed": slider.duration || "500ms" },
2041
+ children: content.map((item, index) => {
2042
+ const positionStyles = getPositionStyles(layout.position, layout.offset, isEditor);
2043
+ const imageStyle2 = slider.type === "scale" ? (() => {
2044
+ const { transform, ...restStyles } = positionStyles;
2045
+ return {
2046
+ ...restStyles,
2047
+ "--position-transform": transform || "none"
2048
+ };
2049
+ })() : positionStyles;
2050
+ return /* @__PURE__ */ jsx(SplideSlide, { children: /* @__PURE__ */ jsx(
2051
+ "div",
2052
+ {
2053
+ className: styles.imgWrapper,
2054
+ onClick: handleImageWrapperClick,
2055
+ style: { padding: scalingValue(layout.padding.top, isEditor) + " " + scalingValue(layout.padding.right, isEditor) + " " + scalingValue(layout.padding.bottom, isEditor) + " " + scalingValue(layout.padding.left, isEditor) },
2056
+ children: /* @__PURE__ */ jsx(
2057
+ "img",
2058
+ {
2059
+ ref: index === currentIndex ? imageRef : null,
2060
+ className: cn(styles.imageStyle, {
2061
+ [styles.contain]: item.image.objectFit === "contain",
2062
+ [styles.cover]: item.image.objectFit === "cover",
2063
+ [styles.scaleSlide]: slider.type === "scale"
2064
+ }),
2065
+ onClick: item.image.objectFit !== "contain" ? onImageClick : void 0,
2066
+ src: item.image.url,
2067
+ alt: item.image.name ?? "",
2068
+ style: {
2069
+ ...imageStyle2,
2070
+ ...item.image.objectFit === "contain" ? {
2071
+ pointerEvents: "none"
2072
+ } : {}
2073
+ }
2074
+ }
2075
+ )
2076
+ }
2077
+ ) }, index);
2078
+ })
2079
+ },
2080
+ splideKey
2081
+ ),
2082
+ controls.isActive && controls.arrowsImgUrl && /* @__PURE__ */ jsxs(Fragment, { children: [
2083
+ /* @__PURE__ */ jsx(
2084
+ "div",
2085
+ {
2086
+ className: cn(styles.arrow, { [styles.arrowVertical]: slider.direction === "vert" }),
2087
+ style: { color: controls.color, ["--arrow-hover-color"]: controls.hover },
2088
+ children: /* @__PURE__ */ jsx(
2089
+ "button",
2090
+ {
2091
+ className: styles.arrowInner,
2092
+ style: {
2093
+ transform: `translate(${scalingValue(controls.offset.x, isEditor)}, ${scalingValue(controls.offset.y * (slider.direction === "horiz" ? 1 : -1), isEditor)}) scale(${controls.scale}) rotate(${slider.direction === "horiz" ? "0deg" : "90deg"})`
2094
+ },
2095
+ onClick: (e) => {
2096
+ handleArrowClick("-1");
2097
+ },
2098
+ children: controls.arrowsImgUrl && /* @__PURE__ */ jsx(
2099
+ SvgImage,
2100
+ {
2101
+ url: controls.arrowsImgUrl,
2102
+ fill: controls.color,
2103
+ hoverFill: controls.hover,
2104
+ className: cn(styles.arrowImg, styles.mirror)
2105
+ }
2106
+ )
2107
+ }
2108
+ )
2109
+ }
2110
+ ),
2111
+ /* @__PURE__ */ jsx(
2112
+ "div",
2113
+ {
2114
+ className: cn(styles.arrow, styles.nextArrow, { [styles.arrowVertical]: slider.direction === "vert" }),
2115
+ style: { color: controls.color, ["--arrow-hover-color"]: controls.hover },
2116
+ children: /* @__PURE__ */ jsx(
2117
+ "button",
2118
+ {
2119
+ className: styles.arrowInner,
2120
+ style: {
2121
+ transform: `translate(${scalingValue(controls.offset.x * (slider.direction === "horiz" ? -1 : 1), isEditor)}, ${scalingValue(controls.offset.y, isEditor)}) scale(${controls.scale}) rotate(${slider.direction === "horiz" ? "0deg" : "90deg"})`
2122
+ },
2123
+ onClick: (e) => {
2124
+ handleArrowClick("+1");
2125
+ },
2126
+ "aria-label": "Next",
2127
+ children: controls.arrowsImgUrl && /* @__PURE__ */ jsx(
2128
+ SvgImage,
2129
+ {
2130
+ url: controls.arrowsImgUrl,
2131
+ fill: controls.color,
2132
+ hoverFill: controls.hover,
2133
+ className: styles.arrowImg
2134
+ }
2135
+ )
2136
+ }
2137
+ )
2138
+ }
2139
+ )
2140
+ ] }),
2141
+ area.closeIconUrl && (() => {
2142
+ const positionStyles = getPositionStyles(area.closeIconAlign, area.closeIconOffset, isEditor);
2143
+ const scaleTransform = `scale(${area.closeIconScale})`;
2144
+ const combinedTransform = positionStyles.transform ? `${positionStyles.transform} ${scaleTransform}` : scaleTransform;
2145
+ return /* @__PURE__ */ jsx(
2146
+ "button",
2147
+ {
2148
+ className: styles.closeButton,
2149
+ style: {
2150
+ ...positionStyles,
2151
+ transform: combinedTransform
2152
+ },
2153
+ onClick: handleClose,
2154
+ children: /* @__PURE__ */ jsx(SvgImage, { url: area.closeIconUrl })
2155
+ }
2156
+ );
2157
+ })(),
2158
+ caption2.isActive && /* @__PURE__ */ jsx(
1791
2159
  "div",
1792
2160
  {
1793
- className: cn(styles.arrow, { [styles.arrowVertical]: slider.direction === "vert" }),
1794
- style: { color: controls.color, ["--arrow-hover-color"]: controls.hover },
2161
+ className: styles.caption,
2162
+ style: {
2163
+ ...getPositionStyles(caption2.alignment, caption2.offset, isEditor),
2164
+ fontFamily: fontSettings.fontFamily,
2165
+ fontWeight: fontSettings.fontWeight,
2166
+ fontStyle: fontSettings.fontStyle,
2167
+ width: widthSettings.sizing === "auto" ? "max-content" : scalingValue(widthSettings.width, isEditor),
2168
+ letterSpacing: scalingValue(letterSpacing, isEditor),
2169
+ wordSpacing: scalingValue(wordSpacing, isEditor),
2170
+ textAlign,
2171
+ fontSize: scalingValue(fontSizeLineHeight.fontSize, isEditor),
2172
+ lineHeight: scalingValue(fontSizeLineHeight.lineHeight, isEditor),
2173
+ textTransform: textAppearance.textTransform ?? "none",
2174
+ textDecoration: textAppearance.textDecoration ?? "none",
2175
+ fontVariant: textAppearance.fontVariant ?? "normal",
2176
+ color,
2177
+ transitionDuration: slider.duration ? `${Math.round(parseInt(slider.duration) / 2)}ms` : "500ms"
2178
+ },
2179
+ onClick: (e) => e.stopPropagation(),
1795
2180
  children: /* @__PURE__ */ jsx(
1796
- "button",
2181
+ "div",
1797
2182
  {
1798
- className: styles.arrowInner,
2183
+ "data-styles": "caption",
2184
+ className: styles.captionTextInner,
1799
2185
  style: {
1800
- transform: `translate(${scalingValue(controls.offset.x)}, ${scalingValue(controls.offset.y * (slider.direction === "horiz" ? 1 : -1))}) scale(${controls.scale}) rotate(${slider.direction === "horiz" ? "0deg" : "90deg"})`
1801
- },
1802
- onClick: (e) => {
1803
- handleArrowClick("-1");
2186
+ "--link-hover-color": caption2.hover,
2187
+ position: "relative"
1804
2188
  },
1805
- children: controls.arrowsImgUrl && /* @__PURE__ */ jsx(
1806
- SvgImage,
1807
- {
1808
- url: controls.arrowsImgUrl,
1809
- fill: controls.color,
1810
- hoverFill: controls.hover,
1811
- className: cn(styles.arrowImg, styles.mirror)
1812
- }
1813
- )
2189
+ children: /* @__PURE__ */ jsx(RichTextRenderer, { content: content[currentIndex].imageCaption })
1814
2190
  }
1815
2191
  )
1816
2192
  }
1817
2193
  ),
1818
- /* @__PURE__ */ jsx(
2194
+ thumbnail.isActive && /* @__PURE__ */ jsx(
1819
2195
  "div",
1820
2196
  {
1821
- className: cn(styles.arrow, styles.nextArrow, { [styles.arrowVertical]: slider.direction === "vert" }),
1822
- style: { color: controls.color, ["--arrow-hover-color"]: controls.hover },
1823
- children: /* @__PURE__ */ jsx(
1824
- "button",
2197
+ className: cn(
2198
+ styles.thumbsContainer,
1825
2199
  {
1826
- className: styles.arrowInner,
1827
- style: {
1828
- transform: `translate(${scalingValue(controls.offset.x * (slider.direction === "horiz" ? -1 : 1))}, ${scalingValue(controls.offset.y)}) scale(${controls.scale}) rotate(${slider.direction === "horiz" ? "0deg" : "90deg"})`
1829
- },
1830
- onClick: (e) => {
1831
- handleArrowClick("+1");
1832
- },
1833
- "aria-label": "Next",
1834
- children: controls.arrowsImgUrl && /* @__PURE__ */ jsx(
1835
- SvgImage,
1836
- {
1837
- url: controls.arrowsImgUrl,
1838
- fill: controls.color,
1839
- hoverFill: controls.hover,
1840
- className: styles.arrowImg
1841
- }
1842
- )
2200
+ [styles.thumbsContainerVertical]: slider.direction === "vert",
2201
+ [styles.thumbsAlignStart]: thumbnail.align === "start",
2202
+ [styles.thumbsAlignCenter]: thumbnail.align === "center",
2203
+ [styles.thumbsAlignEnd]: thumbnail.align === "end"
1843
2204
  }
1844
- )
1845
- }
1846
- )
1847
- ] }),
1848
- area.closeIconUrl && (() => {
1849
- const positionStyles = getPositionStyles(area.closeIconAlign, area.closeIconOffset);
1850
- const scaleTransform = `scale(${area.closeIconScale})`;
1851
- const combinedTransform = positionStyles.transform ? `${positionStyles.transform} ${scaleTransform}` : scaleTransform;
1852
- return /* @__PURE__ */ jsx(
1853
- "button",
1854
- {
1855
- className: styles.closeButton,
2205
+ ),
1856
2206
  style: {
1857
- ...positionStyles,
1858
- transform: combinedTransform
2207
+ gap: `${scalingValue(thumbnail.grid.gap, isEditor)}`,
2208
+ ...getPositionStyles(thumbnail.position, thumbnail.offset, isEditor)
1859
2209
  },
1860
- onClick: onClose,
1861
- children: /* @__PURE__ */ jsx(SvgImage, { url: area.closeIconUrl })
1862
- }
1863
- );
1864
- })(),
1865
- caption2.isActive && /* @__PURE__ */ jsx(
1866
- "div",
1867
- {
1868
- className: styles.caption,
1869
- style: {
1870
- ...getPositionStyles(caption2.alignment, caption2.offset),
1871
- ["--link-hover-color"]: caption2.hover
1872
- },
1873
- children: /* @__PURE__ */ jsx(RichTextRenderer, { content: content[currentIndex].imageCaption })
1874
- }
1875
- ),
1876
- thumbnail.isActive && /* @__PURE__ */ jsx(
1877
- "div",
1878
- {
1879
- className: cn(
1880
- styles.thumbsContainer,
1881
- {
1882
- [styles.thumbsContainerVertical]: slider.direction === "vert",
1883
- [styles.thumbsAlignStart]: thumbnail.align === "start",
1884
- [styles.thumbsAlignCenter]: thumbnail.align === "center",
1885
- [styles.thumbsAlignEnd]: thumbnail.align === "end"
1886
- }
1887
- ),
1888
- style: {
1889
- gap: `${thumbnail.grid.gap}px`,
1890
- ...slider.direction === "horiz" ? { height: `${thumbnail.grid.height}px` } : {},
1891
- ...slider.direction === "vert" ? { width: `${thumbnail.grid.width}px` } : {},
1892
- ...getPositionStyles(thumbnail.position, thumbnail.offset)
1893
- },
1894
- children: content.map((item, index) => {
1895
- const isActive = index === currentIndex;
1896
- return /* @__PURE__ */ jsx(
1897
- "button",
1898
- {
1899
- className: styles.thumbItem,
1900
- style: {
1901
- transform: `scale(${isActive ? thumbnail.activeState.scale : 1})`,
1902
- ...slider.direction === "horiz" ? { height: "100%" } : {},
1903
- ...slider.direction === "vert" ? { width: "100%" } : {},
1904
- opacity: isActive ? thumbnail.activeState.opacity : thumbnail.opacity,
1905
- ["--thumb-hover"]: thumbnail.activeState.opacity
1906
- },
1907
- onClick: (e) => {
1908
- var _a;
1909
- e.stopPropagation();
1910
- setCurrentIndex(index);
1911
- (_a = lightboxRef.current) == null ? void 0 : _a.go(index);
1912
- },
1913
- children: /* @__PURE__ */ jsx(
1914
- "img",
1915
- {
1916
- src: item.image.url,
1917
- alt: item.image.name ?? "",
1918
- className: styles.thumbImage,
1919
- style: {
1920
- objectFit: thumbnail.fit === "cover" ? "cover" : "contain",
1921
- ...slider.direction === "horiz" ? { height: "100%" } : {},
1922
- ...slider.direction === "vert" ? { width: "100%" } : {}
2210
+ children: content.map((item, index) => {
2211
+ const isActive = index === currentIndex;
2212
+ return /* @__PURE__ */ jsx(
2213
+ "button",
2214
+ {
2215
+ className: styles.thumbItem,
2216
+ style: {
2217
+ ...slider.direction === "horiz" ? { height: isActive ? `${scalingValue(thumbnail.grid.height * (isActive ? thumbnail.activeState.scale : 1), isEditor)}` : `${scalingValue(thumbnail.grid.height, isEditor)}` } : {},
2218
+ ...slider.direction === "vert" ? { width: isActive ? `${scalingValue(thumbnail.grid.width * (isActive ? thumbnail.activeState.scale : 1), isEditor)}` : `${scalingValue(thumbnail.grid.width, isEditor)}` } : {},
2219
+ ...thumbnail.fit === "cover" && slider.direction === "horiz" ? { width: isActive ? `${scalingValue(thumbnail.grid.width * (isActive ? thumbnail.activeState.scale : 1), isEditor)}` : `${scalingValue(thumbnail.grid.width, isEditor)}` } : {},
2220
+ ...thumbnail.fit === "cover" && slider.direction === "vert" ? { height: isActive ? `${scalingValue(thumbnail.grid.height * (isActive ? thumbnail.activeState.scale : 1), isEditor)}` : `${scalingValue(thumbnail.grid.height, isEditor)}` } : {},
2221
+ transition: isActive ? "all 0.2s ease" : "none",
2222
+ opacity: isActive ? thumbnail.activeState.opacity / 100 : thumbnail.opacity / 100,
2223
+ ["--thumb-hover"]: thumbnail.activeState.opacity / 100
2224
+ },
2225
+ onClick: (e) => {
2226
+ var _a;
2227
+ e.stopPropagation();
2228
+ setCurrentIndex(index);
2229
+ (_a = lightboxRef.current) == null ? void 0 : _a.go(index);
2230
+ },
2231
+ onMouseEnter: () => {
2232
+ var _a;
2233
+ if (thumbnail.triggers === "hov") {
2234
+ (_a = lightboxRef.current) == null ? void 0 : _a.go(index);
1923
2235
  }
1924
- }
1925
- )
1926
- },
1927
- `${item.image.url}-${index}`
1928
- );
1929
- })
1930
- }
1931
- )
1932
- ]
1933
- }
1934
- )
1935
- }
1936
- ),
2236
+ },
2237
+ children: /* @__PURE__ */ jsx(
2238
+ "img",
2239
+ {
2240
+ src: item.image.url,
2241
+ alt: item.image.name ?? "",
2242
+ style: {
2243
+ objectFit: thumbnail.fit === "cover" ? "cover" : "contain",
2244
+ ...thumbnail.fit === "fit" ? { maxWidth: "100%", maxHeight: "100%", objectFit: "contain" } : {},
2245
+ ...thumbnail.fit === "cover" && slider.direction === "horiz" ? { width: "100%", height: "100%" } : {}
2246
+ }
2247
+ }
2248
+ )
2249
+ },
2250
+ `${item.image.url}-${index}`
2251
+ );
2252
+ })
2253
+ }
2254
+ )
2255
+ ]
2256
+ }
2257
+ )
2258
+ }
2259
+ )
2260
+ ] }),
1937
2261
  document.getElementById(portalId)
1938
2262
  );
1939
2263
  };
2264
+ const getColorAlpha = (color) => {
2265
+ const rgbaMatch = color.match(/rgba?\(([^)]+)\)/);
2266
+ if (rgbaMatch) {
2267
+ const values = rgbaMatch[1].split(",").map((v) => parseFloat(v.trim()));
2268
+ if (values.length === 4) {
2269
+ return values[3];
2270
+ }
2271
+ return 1;
2272
+ }
2273
+ const hexMatch = color.match(/^#([0-9a-fA-F]{8})$/);
2274
+ if (hexMatch) {
2275
+ const alphaHex = hexMatch[1].substring(6, 8);
2276
+ return parseInt(alphaHex, 16) / 255;
2277
+ }
2278
+ if (color.match(/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/)) {
2279
+ return 1;
2280
+ }
2281
+ return 1;
2282
+ };
1940
2283
  const LightboxComponent = {
1941
2284
  element: LightboxGallery,
1942
2285
  id: "lightbox",
1943
2286
  name: "Lightbox",
1944
2287
  preview: {
1945
2288
  type: "video",
1946
- url: "https://cdn.cntrl.site/projects/01GJ2SPDSH73MC92WW7ZA2CWBY/articles-assets/01KA24CHYZXJBZ0Q714B05A7VD.mp4"
2289
+ url: "https://cdn.cntrl.site/component-assets/lightbox.mp4"
1947
2290
  },
1948
2291
  defaultSize: {
1949
- width: 400,
1950
- height: 400
2292
+ width: 440,
2293
+ height: 550
1951
2294
  },
1952
2295
  schema: {
1953
2296
  type: "object",
@@ -1972,7 +2315,7 @@ const LightboxComponent = {
1972
2315
  url: {
1973
2316
  type: "string",
1974
2317
  display: {
1975
- type: "settings-image-input"
2318
+ type: "cover-image-input"
1976
2319
  }
1977
2320
  }
1978
2321
  }
@@ -2014,14 +2357,6 @@ const LightboxComponent = {
2014
2357
  type: "direction-control"
2015
2358
  },
2016
2359
  enum: ["top", "left", "right", "bottom"]
2017
- },
2018
- repeat: {
2019
- type: "string",
2020
- title: "Repeat",
2021
- display: {
2022
- type: "ratio-group"
2023
- },
2024
- enum: ["close", "loop"]
2025
2360
  }
2026
2361
  }
2027
2362
  },
@@ -2045,13 +2380,14 @@ const LightboxComponent = {
2045
2380
  },
2046
2381
  enum: ["image", "50/50"]
2047
2382
  },
2048
- duration: {
2383
+ repeat: {
2049
2384
  type: "string",
2050
- label: "T",
2385
+ title: "Repeat",
2051
2386
  display: {
2052
- type: "step-selector"
2387
+ visible: false,
2388
+ type: "ratio-group"
2053
2389
  },
2054
- enum: ["100ms", "250ms", "500ms", "1000ms", "1500ms", "2000ms"]
2390
+ enum: ["close", "loop"]
2055
2391
  }
2056
2392
  }
2057
2393
  },
@@ -2074,6 +2410,14 @@ const LightboxComponent = {
2074
2410
  type: "ratio-group"
2075
2411
  },
2076
2412
  enum: ["horiz", "vert"]
2413
+ },
2414
+ duration: {
2415
+ type: "string",
2416
+ label: "T",
2417
+ display: {
2418
+ type: "step-selector"
2419
+ },
2420
+ enum: ["100ms", "250ms", "500ms", "1000ms", "1500ms", "2000ms"]
2077
2421
  }
2078
2422
  }
2079
2423
  },
@@ -2131,13 +2475,16 @@ const LightboxComponent = {
2131
2475
  height: {
2132
2476
  type: "number",
2133
2477
  label: "H",
2478
+ scalingEnabled: true,
2134
2479
  display: {
2135
- type: "numeric-input"
2480
+ type: "numeric-input",
2481
+ visible: true
2136
2482
  }
2137
2483
  },
2138
2484
  width: {
2139
2485
  type: "number",
2140
2486
  label: "W",
2487
+ scalingEnabled: true,
2141
2488
  display: {
2142
2489
  type: "numeric-input",
2143
2490
  visible: false
@@ -2146,6 +2493,7 @@ const LightboxComponent = {
2146
2493
  gap: {
2147
2494
  type: "number",
2148
2495
  label: "Gap",
2496
+ scalingEnabled: true,
2149
2497
  display: {
2150
2498
  type: "numeric-input"
2151
2499
  }
@@ -2154,15 +2502,28 @@ const LightboxComponent = {
2154
2502
  },
2155
2503
  offset: {
2156
2504
  type: "object",
2505
+ title: "Offset",
2157
2506
  display: {
2158
- type: "offset-controls"
2507
+ type: "group"
2159
2508
  },
2160
2509
  properties: {
2161
2510
  x: {
2162
- type: "number"
2511
+ type: "number",
2512
+ label: "X",
2513
+ scalingEnabled: true,
2514
+ display: {
2515
+ type: "numeric-input",
2516
+ visible: true
2517
+ }
2163
2518
  },
2164
2519
  y: {
2165
- type: "number"
2520
+ type: "number",
2521
+ label: "Y",
2522
+ scalingEnabled: true,
2523
+ display: {
2524
+ type: "numeric-input",
2525
+ visible: true
2526
+ }
2166
2527
  }
2167
2528
  }
2168
2529
  },
@@ -2187,7 +2548,7 @@ const LightboxComponent = {
2187
2548
  scale: {
2188
2549
  type: "number",
2189
2550
  title: "Scale",
2190
- min: 0.5,
2551
+ min: 1,
2191
2552
  max: 5,
2192
2553
  step: 0.1,
2193
2554
  display: {
@@ -2224,15 +2585,28 @@ const LightboxComponent = {
2224
2585
  },
2225
2586
  offset: {
2226
2587
  type: "object",
2588
+ title: "Offset",
2227
2589
  display: {
2228
- type: "offset-controls"
2590
+ type: "group"
2229
2591
  },
2230
2592
  properties: {
2231
2593
  x: {
2232
- type: "number"
2594
+ type: "number",
2595
+ label: "X",
2596
+ scalingEnabled: true,
2597
+ display: {
2598
+ type: "numeric-input",
2599
+ visible: true
2600
+ }
2233
2601
  },
2234
2602
  y: {
2235
- type: "number"
2603
+ type: "number",
2604
+ label: "Y",
2605
+ scalingEnabled: true,
2606
+ display: {
2607
+ type: "numeric-input",
2608
+ visible: true
2609
+ }
2236
2610
  }
2237
2611
  }
2238
2612
  },
@@ -2244,15 +2618,23 @@ const LightboxComponent = {
2244
2618
  },
2245
2619
  properties: {
2246
2620
  top: {
2621
+ min: 0,
2622
+ step: 1,
2247
2623
  type: "number"
2248
2624
  },
2249
2625
  left: {
2626
+ min: 0,
2627
+ step: 1,
2250
2628
  type: "number"
2251
2629
  },
2252
2630
  right: {
2631
+ min: 0,
2632
+ step: 1,
2253
2633
  type: "number"
2254
2634
  },
2255
2635
  bottom: {
2636
+ min: 0,
2637
+ step: 1,
2256
2638
  type: "number"
2257
2639
  }
2258
2640
  }
@@ -2278,16 +2660,29 @@ const LightboxComponent = {
2278
2660
  }
2279
2661
  },
2280
2662
  offset: {
2663
+ title: "Offset",
2281
2664
  type: "object",
2282
2665
  display: {
2283
- type: "offset-controls"
2666
+ type: "group"
2284
2667
  },
2285
2668
  properties: {
2286
2669
  x: {
2287
- type: "number"
2670
+ type: "number",
2671
+ label: "X",
2672
+ scalingEnabled: true,
2673
+ display: {
2674
+ type: "numeric-input",
2675
+ visible: true
2676
+ }
2288
2677
  },
2289
2678
  y: {
2290
- type: "number"
2679
+ type: "number",
2680
+ label: "Y",
2681
+ scalingEnabled: true,
2682
+ display: {
2683
+ type: "numeric-input",
2684
+ visible: true
2685
+ }
2291
2686
  }
2292
2687
  }
2293
2688
  },
@@ -2366,15 +2761,28 @@ const LightboxComponent = {
2366
2761
  },
2367
2762
  closeIconOffset: {
2368
2763
  type: "object",
2764
+ title: "Offset",
2369
2765
  display: {
2370
- type: "offset-controls"
2766
+ type: "group"
2371
2767
  },
2372
2768
  properties: {
2373
2769
  x: {
2374
- type: "number"
2770
+ type: "number",
2771
+ label: "X",
2772
+ scalingEnabled: true,
2773
+ display: {
2774
+ type: "numeric-input",
2775
+ visible: true
2776
+ }
2375
2777
  },
2376
2778
  y: {
2377
- type: "number"
2779
+ type: "number",
2780
+ label: "Y",
2781
+ scalingEnabled: true,
2782
+ display: {
2783
+ type: "numeric-input",
2784
+ visible: true
2785
+ }
2378
2786
  }
2379
2787
  }
2380
2788
  }
@@ -2400,16 +2808,29 @@ const LightboxComponent = {
2400
2808
  enum: ["top-left", "top-center", "top-right", "middle-left", "middle-center", "middle-right", "bottom-left", "bottom-center", "bottom-right"]
2401
2809
  },
2402
2810
  offset: {
2811
+ title: "Offset",
2403
2812
  type: "object",
2404
2813
  display: {
2405
- type: "offset-controls"
2814
+ type: "group"
2406
2815
  },
2407
2816
  properties: {
2408
2817
  x: {
2409
- type: "number"
2818
+ type: "number",
2819
+ label: "X",
2820
+ scalingEnabled: true,
2821
+ display: {
2822
+ type: "numeric-input",
2823
+ visible: true
2824
+ }
2410
2825
  },
2411
2826
  y: {
2412
- type: "number"
2827
+ type: "number",
2828
+ label: "Y",
2829
+ scalingEnabled: true,
2830
+ display: {
2831
+ type: "numeric-input",
2832
+ visible: true
2833
+ }
2413
2834
  }
2414
2835
  }
2415
2836
  },
@@ -2429,38 +2850,38 @@ const LightboxComponent = {
2429
2850
  default: {
2430
2851
  thumbnailBlock: {
2431
2852
  cover: {
2432
- url: "https://cdn.cntrl.site/projects/01JJKT02AWY2FGN2QJ7A173RNZ/articles-assets/01K7ERMHNP08T27H1649S67NZV.png"
2853
+ url: "https://cdn.cntrl.site/component-assets/Cover.jpg"
2433
2854
  }
2434
2855
  },
2435
2856
  lightboxBlock: {
2436
2857
  appear: {
2437
- type: "slide in",
2858
+ type: "fade in",
2438
2859
  duration: "1000ms",
2439
- direction: "right",
2440
- repeat: "close"
2860
+ direction: "right"
2441
2861
  },
2442
2862
  triggers: {
2443
2863
  type: "click",
2444
- switch: "image",
2445
- duration: "2000ms"
2864
+ switch: "50/50",
2865
+ repeat: "loop"
2446
2866
  },
2447
2867
  slider: {
2448
- type: "fade",
2449
- direction: "horiz"
2868
+ type: "slide",
2869
+ direction: "horiz",
2870
+ duration: "1000ms"
2450
2871
  },
2451
2872
  thumbnail: {
2452
2873
  isActive: true,
2453
2874
  position: "bottom-center",
2454
- fit: "cover",
2875
+ fit: "fit",
2455
2876
  align: "center",
2456
2877
  triggers: "clk",
2457
2878
  grid: {
2458
- height: 60,
2459
- width: 60,
2460
- gap: 8
2879
+ height: 0.03,
2880
+ width: 0.03,
2881
+ gap: 8e-3
2461
2882
  },
2462
2883
  offset: { x: 0, y: 0 },
2463
- opacity: 100,
2884
+ opacity: 80,
2464
2885
  activeState: {
2465
2886
  scale: 1,
2466
2887
  opacity: 100
@@ -2469,7 +2890,7 @@ const LightboxComponent = {
2469
2890
  layout: {
2470
2891
  position: "middle-center",
2471
2892
  offset: { x: 0, y: 0 },
2472
- padding: { top: 0, right: 0, bottom: 0, left: 0 }
2893
+ padding: { top: 0.04, right: 0, bottom: 0.04, left: 0 }
2473
2894
  },
2474
2895
  controls: {
2475
2896
  isActive: true,
@@ -2480,7 +2901,7 @@ const LightboxComponent = {
2480
2901
  hover: "#cccccc"
2481
2902
  },
2482
2903
  area: {
2483
- color: "rgba(0,0,0,0.9)",
2904
+ color: "rgba(64,67,71,0.9)",
2484
2905
  blur: 0,
2485
2906
  closeIconUrl: null,
2486
2907
  closeIconAlign: "top-right",
@@ -2512,7 +2933,7 @@ const LightboxComponent = {
2512
2933
  value: "vert"
2513
2934
  },
2514
2935
  then: {
2515
- name: "properties.lightboxBlock.properties.thumbnail.properties.position.display.direction",
2936
+ name: "properties.lightboxBlock.properties.thumbnail.properties.align.display.direction",
2516
2937
  value: "vertical"
2517
2938
  }
2518
2939
  },
@@ -2577,44 +2998,14 @@ const LightboxComponent = {
2577
2998
  }
2578
2999
  },
2579
3000
  {
2580
- if: {
2581
- name: "lightboxBlock.triggers.type",
2582
- value: "click"
2583
- },
2584
- then: {
2585
- name: "properties.lightboxBlock.properties.triggers.properties.duration.display.visible",
2586
- value: true
2587
- }
2588
- },
2589
- {
2590
- if: {
2591
- name: "lightboxBlock.triggers.type",
2592
- value: "click"
2593
- },
3001
+ if: [
3002
+ { name: "lightboxBlock.triggers.type", value: "click" },
3003
+ { name: "lightboxBlock.triggers.switch", value: "image" }
3004
+ ],
2594
3005
  then: {
2595
- name: "properties.lightboxBlock.properties.triggers.properties.switch.display.visible",
3006
+ name: "properties.lightboxBlock.properties.triggers.properties.repeat.display.visible",
2596
3007
  value: true
2597
3008
  }
2598
- },
2599
- {
2600
- if: {
2601
- name: "lightboxBlock.triggers.type",
2602
- value: "drag"
2603
- },
2604
- then: {
2605
- name: "properties.lightboxBlock.properties.triggers.properties.duration.display.visible",
2606
- value: false
2607
- }
2608
- },
2609
- {
2610
- if: {
2611
- name: "lightboxBlock.triggers.type",
2612
- value: "drag"
2613
- },
2614
- then: {
2615
- name: "properties.lightboxBlock.properties.triggers.properties.switch.display.visible",
2616
- value: false
2617
- }
2618
3009
  }
2619
3010
  ]
2620
3011
  },
@@ -2666,7 +3057,7 @@ const LightboxComponent = {
2666
3057
  {
2667
3058
  image: {
2668
3059
  objectFit: "contain",
2669
- url: "https://cdn.cntrl.site/projects/01JJKT02AWY2FGN2QJ7A173RNZ/articles-assets/01K7ERMHNP08T27H1649S67NZV.png",
3060
+ url: "https://cdn.cntrl.site/component-assets/2.jpg",
2670
3061
  name: "Slider-1.png"
2671
3062
  },
2672
3063
  imageCaption: [
@@ -2679,7 +3070,7 @@ const LightboxComponent = {
2679
3070
  {
2680
3071
  image: {
2681
3072
  objectFit: "contain",
2682
- url: "https://cdn.cntrl.site/projects/01JJKT02AWY2FGN2QJ7A173RNZ/articles-assets/01K7ERMTZA3RYMXKF0M095D6JD.png",
3073
+ url: "https://cdn.cntrl.site/component-assets/3.jpg",
2683
3074
  name: "Slider-2.png"
2684
3075
  },
2685
3076
  imageCaption: [
@@ -2692,7 +3083,7 @@ const LightboxComponent = {
2692
3083
  {
2693
3084
  image: {
2694
3085
  objectFit: "contain",
2695
- url: "https://cdn.cntrl.site/projects/01JJKT02AWY2FGN2QJ7A173RNZ/articles-assets/01K7ERMVSCMPVJBG2WF5KJZYHZ.png",
3086
+ url: "https://cdn.cntrl.site/component-assets/4.jpg",
2696
3087
  name: "Slider-3.png"
2697
3088
  },
2698
3089
  imageCaption: [