@mission-studio/puck 1.0.0 → 1.0.2
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/{chunk-ZZF2BIMW.mjs → chunk-RVOG4KFI.mjs} +201 -25
- package/dist/config-entry.js +220 -44
- package/dist/config-entry.mjs +1 -1
- package/dist/index.js +201 -25
- package/dist/index.mjs +1 -1
- package/dist/styles.css +1 -1
- package/package.json +21 -3
|
@@ -158,6 +158,75 @@ function Paragraph({
|
|
|
158
158
|
return /* @__PURE__ */ jsx2("p", { id, style, children: resolvedText });
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
+
// hooks/useGtmEvent.ts
|
|
162
|
+
function useGtmEvent() {
|
|
163
|
+
return (eventName, data) => {
|
|
164
|
+
if (typeof window === "undefined") return;
|
|
165
|
+
if (typeof window.gtag !== "function") {
|
|
166
|
+
console.warn("GTM not initialized. Make sure @next/third-parties/google GoogleTagManager is added to your layout.");
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
const eventData = {
|
|
170
|
+
event: eventName,
|
|
171
|
+
...data && { value: data }
|
|
172
|
+
};
|
|
173
|
+
window.gtag("event", eventName, data || {});
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// hooks/useUtmParams.ts
|
|
178
|
+
import { useEffect, useState } from "react";
|
|
179
|
+
function useUtmParams() {
|
|
180
|
+
const [utmParams, setUtmParams] = useState({});
|
|
181
|
+
useEffect(() => {
|
|
182
|
+
if (typeof window === "undefined") return;
|
|
183
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
184
|
+
const source = urlParams.get("utm_source");
|
|
185
|
+
const medium = urlParams.get("utm_medium");
|
|
186
|
+
const campaign = urlParams.get("utm_campaign");
|
|
187
|
+
const content = urlParams.get("utm_content");
|
|
188
|
+
const term = urlParams.get("utm_term");
|
|
189
|
+
const params = {};
|
|
190
|
+
if (source) {
|
|
191
|
+
params.source = source;
|
|
192
|
+
sessionStorage.setItem("utm_source", source);
|
|
193
|
+
} else {
|
|
194
|
+
const stored = sessionStorage.getItem("utm_source");
|
|
195
|
+
if (stored) params.source = stored;
|
|
196
|
+
}
|
|
197
|
+
if (medium) {
|
|
198
|
+
params.medium = medium;
|
|
199
|
+
sessionStorage.setItem("utm_medium", medium);
|
|
200
|
+
} else {
|
|
201
|
+
const stored = sessionStorage.getItem("utm_medium");
|
|
202
|
+
if (stored) params.medium = stored;
|
|
203
|
+
}
|
|
204
|
+
if (campaign) {
|
|
205
|
+
params.campaign = campaign;
|
|
206
|
+
sessionStorage.setItem("utm_campaign", campaign);
|
|
207
|
+
} else {
|
|
208
|
+
const stored = sessionStorage.getItem("utm_campaign");
|
|
209
|
+
if (stored) params.campaign = stored;
|
|
210
|
+
}
|
|
211
|
+
if (content) {
|
|
212
|
+
params.content = content;
|
|
213
|
+
sessionStorage.setItem("utm_content", content);
|
|
214
|
+
} else {
|
|
215
|
+
const stored = sessionStorage.getItem("utm_content");
|
|
216
|
+
if (stored) params.content = stored;
|
|
217
|
+
}
|
|
218
|
+
if (term) {
|
|
219
|
+
params.term = term;
|
|
220
|
+
sessionStorage.setItem("utm_term", term);
|
|
221
|
+
} else {
|
|
222
|
+
const stored = sessionStorage.getItem("utm_term");
|
|
223
|
+
if (stored) params.term = stored;
|
|
224
|
+
}
|
|
225
|
+
setUtmParams(params);
|
|
226
|
+
}, []);
|
|
227
|
+
return utmParams;
|
|
228
|
+
}
|
|
229
|
+
|
|
161
230
|
// components/page/Button.tsx
|
|
162
231
|
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
163
232
|
var sizeStyles = {
|
|
@@ -194,6 +263,8 @@ function Button({
|
|
|
194
263
|
}) {
|
|
195
264
|
const { resolveColor: resolveColor2 } = useTheme();
|
|
196
265
|
const { getEntryValue } = useEntries();
|
|
266
|
+
const sendEvent = useGtmEvent();
|
|
267
|
+
const utm = useUtmParams();
|
|
197
268
|
const resolvedText = (() => {
|
|
198
269
|
if (!text) return "Button";
|
|
199
270
|
if (typeof text === "string") return text;
|
|
@@ -205,6 +276,14 @@ function Button({
|
|
|
205
276
|
}
|
|
206
277
|
return "Button";
|
|
207
278
|
})();
|
|
279
|
+
const handleClick = () => {
|
|
280
|
+
sendEvent("button_click", {
|
|
281
|
+
text: resolvedText,
|
|
282
|
+
href: href || void 0,
|
|
283
|
+
variant,
|
|
284
|
+
...utm
|
|
285
|
+
});
|
|
286
|
+
};
|
|
208
287
|
const resolvedColor = (() => {
|
|
209
288
|
if (!color) return resolveColor2("primary");
|
|
210
289
|
if (typeof color === "string") return { color, opacity: 100 };
|
|
@@ -278,11 +357,12 @@ function Button({
|
|
|
278
357
|
target,
|
|
279
358
|
style,
|
|
280
359
|
rel: target === "_blank" ? "noopener noreferrer" : void 0,
|
|
360
|
+
onClick: handleClick,
|
|
281
361
|
children: resolvedText
|
|
282
362
|
}
|
|
283
363
|
) });
|
|
284
364
|
}
|
|
285
|
-
return /* @__PURE__ */ jsx3("div", { style: wrapperStyle, children: /* @__PURE__ */ jsx3("button", { id, type: "button", style, children: resolvedText }) });
|
|
365
|
+
return /* @__PURE__ */ jsx3("div", { style: wrapperStyle, children: /* @__PURE__ */ jsx3("button", { id, type: "button", style, onClick: handleClick, children: resolvedText }) });
|
|
286
366
|
}
|
|
287
367
|
|
|
288
368
|
// components/page/Image.tsx
|
|
@@ -415,7 +495,7 @@ function Image({
|
|
|
415
495
|
}
|
|
416
496
|
|
|
417
497
|
// components/page/ImageCarousel.tsx
|
|
418
|
-
import { useState } from "react";
|
|
498
|
+
import { useState as useState2 } from "react";
|
|
419
499
|
import { Fragment, jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
420
500
|
var aspectRatioMap2 = {
|
|
421
501
|
"16:9": "16 / 9",
|
|
@@ -442,8 +522,10 @@ function ImageCarousel({
|
|
|
442
522
|
dotColor,
|
|
443
523
|
id
|
|
444
524
|
}) {
|
|
445
|
-
const [currentIndex, setCurrentIndex] =
|
|
525
|
+
const [currentIndex, setCurrentIndex] = useState2(0);
|
|
446
526
|
const { resolveColor: resolveColor2 } = useTheme();
|
|
527
|
+
const sendEvent = useGtmEvent();
|
|
528
|
+
const utm = useUtmParams();
|
|
447
529
|
const resolvedArrowColor = (() => {
|
|
448
530
|
if (!arrowColor) return { color: "#FFFFFF", opacity: 100 };
|
|
449
531
|
if (typeof arrowColor === "string")
|
|
@@ -464,13 +546,33 @@ function ImageCarousel({
|
|
|
464
546
|
return resolveColor2("primary");
|
|
465
547
|
})();
|
|
466
548
|
const goToPrevious = () => {
|
|
467
|
-
|
|
549
|
+
const newIndex = currentIndex === 0 ? images.length - 1 : currentIndex - 1;
|
|
550
|
+
setCurrentIndex(newIndex);
|
|
551
|
+
sendEvent("carousel_navigate", {
|
|
552
|
+
direction: "previous",
|
|
553
|
+
slideIndex: newIndex,
|
|
554
|
+
totalSlides: images.length,
|
|
555
|
+
...utm
|
|
556
|
+
});
|
|
468
557
|
};
|
|
469
558
|
const goToNext = () => {
|
|
470
|
-
|
|
559
|
+
const newIndex = currentIndex === images.length - 1 ? 0 : currentIndex + 1;
|
|
560
|
+
setCurrentIndex(newIndex);
|
|
561
|
+
sendEvent("carousel_navigate", {
|
|
562
|
+
direction: "next",
|
|
563
|
+
slideIndex: newIndex,
|
|
564
|
+
totalSlides: images.length,
|
|
565
|
+
...utm
|
|
566
|
+
});
|
|
471
567
|
};
|
|
472
568
|
const goToSlide = (index) => {
|
|
473
569
|
setCurrentIndex(index);
|
|
570
|
+
sendEvent("carousel_navigate", {
|
|
571
|
+
direction: "direct",
|
|
572
|
+
slideIndex: index,
|
|
573
|
+
totalSlides: images.length,
|
|
574
|
+
...utm
|
|
575
|
+
});
|
|
474
576
|
};
|
|
475
577
|
if (images.length === 0) {
|
|
476
578
|
return /* @__PURE__ */ jsx5(
|
|
@@ -1575,11 +1677,27 @@ function Footer({
|
|
|
1575
1677
|
puck
|
|
1576
1678
|
}) {
|
|
1577
1679
|
const DropZone = puck?.renderDropZone;
|
|
1680
|
+
const sendEvent = useGtmEvent();
|
|
1681
|
+
const utm = useUtmParams();
|
|
1682
|
+
const getSocialPlatform = (url) => {
|
|
1683
|
+
if (url.includes("facebook")) return "facebook";
|
|
1684
|
+
if (url.includes("instagram")) return "instagram";
|
|
1685
|
+
if (url.includes("twitter")) return "twitter";
|
|
1686
|
+
return "social";
|
|
1687
|
+
};
|
|
1688
|
+
const handleSocialClick = (url) => {
|
|
1689
|
+
const platform = getSocialPlatform(url);
|
|
1690
|
+
sendEvent("social_click", {
|
|
1691
|
+
platform,
|
|
1692
|
+
url,
|
|
1693
|
+
...utm
|
|
1694
|
+
});
|
|
1695
|
+
};
|
|
1578
1696
|
const socialLinks = [
|
|
1579
1697
|
{ url: facebookUrl, Icon: Facebook },
|
|
1580
1698
|
{ url: instagramUrl, Icon: Instagram },
|
|
1581
1699
|
{ url: twitterUrl, Icon: Twitter }
|
|
1582
|
-
].filter((link) => link.url);
|
|
1700
|
+
].filter((link) => !!link.url);
|
|
1583
1701
|
return /* @__PURE__ */ jsx18(
|
|
1584
1702
|
"footer",
|
|
1585
1703
|
{
|
|
@@ -1595,6 +1713,7 @@ function Footer({
|
|
|
1595
1713
|
target: "_blank",
|
|
1596
1714
|
rel: "noopener noreferrer",
|
|
1597
1715
|
className: "transition-opacity hover:opacity-80",
|
|
1716
|
+
onClick: () => handleSocialClick(url),
|
|
1598
1717
|
children: /* @__PURE__ */ jsx18(Icon3, { size: 24, style: { color: textColor } })
|
|
1599
1718
|
},
|
|
1600
1719
|
index
|
|
@@ -1606,7 +1725,7 @@ function Footer({
|
|
|
1606
1725
|
}
|
|
1607
1726
|
|
|
1608
1727
|
// components/page/Topbar.tsx
|
|
1609
|
-
import { useState as
|
|
1728
|
+
import { useState as useState3 } from "react";
|
|
1610
1729
|
import Link from "next/link";
|
|
1611
1730
|
import { Menu, X } from "lucide-react";
|
|
1612
1731
|
import { jsx as jsx19, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
@@ -1620,7 +1739,25 @@ function Topbar({
|
|
|
1620
1739
|
puck
|
|
1621
1740
|
}) {
|
|
1622
1741
|
const DropZone = puck?.renderDropZone;
|
|
1623
|
-
const [mobileMenuOpen, setMobileMenuOpen] =
|
|
1742
|
+
const [mobileMenuOpen, setMobileMenuOpen] = useState3(false);
|
|
1743
|
+
const sendEvent = useGtmEvent();
|
|
1744
|
+
const utm = useUtmParams();
|
|
1745
|
+
const handleNavClick = (item) => {
|
|
1746
|
+
sendEvent("nav_click", {
|
|
1747
|
+
name: item.name,
|
|
1748
|
+
url: item.url,
|
|
1749
|
+
linkType: item.linkType || "internal",
|
|
1750
|
+
...utm
|
|
1751
|
+
});
|
|
1752
|
+
};
|
|
1753
|
+
const handleMobileMenuToggle = () => {
|
|
1754
|
+
const newState = !mobileMenuOpen;
|
|
1755
|
+
setMobileMenuOpen(newState);
|
|
1756
|
+
sendEvent("mobile_menu_toggle", {
|
|
1757
|
+
open: newState,
|
|
1758
|
+
...utm
|
|
1759
|
+
});
|
|
1760
|
+
};
|
|
1624
1761
|
const renderLink = (item, index) => {
|
|
1625
1762
|
const className = "hover:opacity-80 transition-opacity";
|
|
1626
1763
|
if (item.linkType === "external") {
|
|
@@ -1631,15 +1768,34 @@ function Topbar({
|
|
|
1631
1768
|
target: "_blank",
|
|
1632
1769
|
rel: "noopener noreferrer",
|
|
1633
1770
|
className,
|
|
1771
|
+
onClick: () => handleNavClick(item),
|
|
1634
1772
|
children: item.name
|
|
1635
1773
|
},
|
|
1636
1774
|
index
|
|
1637
1775
|
);
|
|
1638
1776
|
}
|
|
1639
1777
|
if (item.linkType === "scrollTo") {
|
|
1640
|
-
return /* @__PURE__ */ jsx19(
|
|
1778
|
+
return /* @__PURE__ */ jsx19(
|
|
1779
|
+
"a",
|
|
1780
|
+
{
|
|
1781
|
+
href: item.url,
|
|
1782
|
+
className,
|
|
1783
|
+
onClick: () => handleNavClick(item),
|
|
1784
|
+
children: item.name
|
|
1785
|
+
},
|
|
1786
|
+
index
|
|
1787
|
+
);
|
|
1641
1788
|
}
|
|
1642
|
-
return /* @__PURE__ */ jsx19(
|
|
1789
|
+
return /* @__PURE__ */ jsx19(
|
|
1790
|
+
Link,
|
|
1791
|
+
{
|
|
1792
|
+
href: item.url,
|
|
1793
|
+
className,
|
|
1794
|
+
onClick: () => handleNavClick(item),
|
|
1795
|
+
children: item.name
|
|
1796
|
+
},
|
|
1797
|
+
index
|
|
1798
|
+
);
|
|
1643
1799
|
};
|
|
1644
1800
|
return /* @__PURE__ */ jsxs8(
|
|
1645
1801
|
"nav",
|
|
@@ -1653,19 +1809,25 @@ function Topbar({
|
|
|
1653
1809
|
className: "mx-auto flex items-center justify-between",
|
|
1654
1810
|
style: { maxWidth },
|
|
1655
1811
|
children: [
|
|
1656
|
-
/* @__PURE__ */ jsx19(
|
|
1812
|
+
/* @__PURE__ */ jsx19(
|
|
1813
|
+
Link,
|
|
1814
|
+
{
|
|
1815
|
+
href: logoUrl,
|
|
1816
|
+
className: "flex-shrink-0",
|
|
1817
|
+
onClick: () => sendEvent("nav_click", {
|
|
1818
|
+
name: "logo",
|
|
1819
|
+
url: logoUrl,
|
|
1820
|
+
linkType: "internal",
|
|
1821
|
+
...utm
|
|
1822
|
+
}),
|
|
1823
|
+
children: logo ? /* @__PURE__ */ jsx19("img", { src: logo, alt: "Logo", className: "h-8" }) : /* @__PURE__ */ jsx19("span", { className: "text-xl font-bold", children: "Logo" })
|
|
1824
|
+
}
|
|
1825
|
+
),
|
|
1657
1826
|
/* @__PURE__ */ jsxs8("div", { className: "hidden items-center gap-8 md:flex", children: [
|
|
1658
1827
|
navItems.map(renderLink),
|
|
1659
1828
|
DropZone && /* @__PURE__ */ jsx19(DropZone, { zone: "cta" })
|
|
1660
1829
|
] }),
|
|
1661
|
-
/* @__PURE__ */ jsx19(
|
|
1662
|
-
"button",
|
|
1663
|
-
{
|
|
1664
|
-
className: "md:hidden",
|
|
1665
|
-
onClick: () => setMobileMenuOpen(!mobileMenuOpen),
|
|
1666
|
-
children: mobileMenuOpen ? /* @__PURE__ */ jsx19(X, { size: 24 }) : /* @__PURE__ */ jsx19(Menu, { size: 24 })
|
|
1667
|
-
}
|
|
1668
|
-
)
|
|
1830
|
+
/* @__PURE__ */ jsx19("button", { className: "md:hidden", onClick: handleMobileMenuToggle, children: mobileMenuOpen ? /* @__PURE__ */ jsx19(X, { size: 24 }) : /* @__PURE__ */ jsx19(Menu, { size: 24 }) })
|
|
1669
1831
|
]
|
|
1670
1832
|
}
|
|
1671
1833
|
),
|
|
@@ -1686,7 +1848,7 @@ function Topbar({
|
|
|
1686
1848
|
}
|
|
1687
1849
|
|
|
1688
1850
|
// components/page/Popup.tsx
|
|
1689
|
-
import { useState as
|
|
1851
|
+
import { useState as useState4 } from "react";
|
|
1690
1852
|
import { icons as icons4, X as X2 } from "lucide-react";
|
|
1691
1853
|
import { Fragment as Fragment2, jsx as jsx20, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1692
1854
|
function Icon2({ name, ...props }) {
|
|
@@ -1716,11 +1878,25 @@ function Popup({
|
|
|
1716
1878
|
textLink = false,
|
|
1717
1879
|
puck
|
|
1718
1880
|
}) {
|
|
1719
|
-
const [isOpen, setIsOpen] =
|
|
1881
|
+
const [isOpen, setIsOpen] = useState4(false);
|
|
1882
|
+
const sendEvent = useGtmEvent();
|
|
1883
|
+
const utm = useUtmParams();
|
|
1884
|
+
const handleOpen = () => {
|
|
1885
|
+
setIsOpen(true);
|
|
1886
|
+
sendEvent("popup_open", {
|
|
1887
|
+
ctaText,
|
|
1888
|
+
type: textLink ? "link" : "button",
|
|
1889
|
+
...utm
|
|
1890
|
+
});
|
|
1891
|
+
};
|
|
1892
|
+
const handleClose = () => {
|
|
1893
|
+
setIsOpen(false);
|
|
1894
|
+
sendEvent("popup_close", { ctaText, ...utm });
|
|
1895
|
+
};
|
|
1720
1896
|
const trigger = textLink ? /* @__PURE__ */ jsx20(
|
|
1721
1897
|
"button",
|
|
1722
1898
|
{
|
|
1723
|
-
onClick:
|
|
1899
|
+
onClick: handleOpen,
|
|
1724
1900
|
className: "underline hover:opacity-80",
|
|
1725
1901
|
style: { color: buttonColor },
|
|
1726
1902
|
children: ctaText
|
|
@@ -1728,7 +1904,7 @@ function Popup({
|
|
|
1728
1904
|
) : /* @__PURE__ */ jsxs9(
|
|
1729
1905
|
"button",
|
|
1730
1906
|
{
|
|
1731
|
-
onClick:
|
|
1907
|
+
onClick: handleOpen,
|
|
1732
1908
|
className: cn(
|
|
1733
1909
|
"flex items-center gap-2 rounded-full font-medium",
|
|
1734
1910
|
sizeMap8[size]
|
|
@@ -1747,7 +1923,7 @@ function Popup({
|
|
|
1747
1923
|
"div",
|
|
1748
1924
|
{
|
|
1749
1925
|
className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4",
|
|
1750
|
-
onClick:
|
|
1926
|
+
onClick: handleClose,
|
|
1751
1927
|
children: /* @__PURE__ */ jsxs9(
|
|
1752
1928
|
"div",
|
|
1753
1929
|
{
|
|
@@ -1760,7 +1936,7 @@ function Popup({
|
|
|
1760
1936
|
/* @__PURE__ */ jsx20(
|
|
1761
1937
|
"button",
|
|
1762
1938
|
{
|
|
1763
|
-
onClick:
|
|
1939
|
+
onClick: handleClose,
|
|
1764
1940
|
className: "absolute top-4 right-4 text-gray-500 hover:text-gray-700",
|
|
1765
1941
|
children: /* @__PURE__ */ jsx20(X2, { size: 24 })
|
|
1766
1942
|
}
|