@uptrademedia/site-kit 1.0.1 → 1.0.4

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.
Files changed (159) hide show
  1. package/dist/SetupWizard-Cki06kB0.d.mts +12 -0
  2. package/dist/SetupWizard-Cki06kB0.d.ts +12 -0
  3. package/dist/analytics/index.d.mts +87 -0
  4. package/dist/analytics/index.d.ts +87 -0
  5. package/dist/blog/index.d.mts +24 -0
  6. package/dist/blog/index.d.ts +24 -0
  7. package/dist/blog/index.js.map +1 -1
  8. package/dist/blog/index.mjs.map +1 -1
  9. package/dist/chunk-2IHTEKHU.mjs +332 -0
  10. package/dist/chunk-2IHTEKHU.mjs.map +1 -0
  11. package/dist/chunk-5R4R3WDP.js +1451 -0
  12. package/dist/chunk-5R4R3WDP.js.map +1 -0
  13. package/dist/{chunk-RV7H3I6J.js → chunk-ADHVEFWD.js} +68 -2
  14. package/dist/chunk-ADHVEFWD.js.map +1 -0
  15. package/dist/chunk-BGJLOJ7T.mjs +605 -0
  16. package/dist/chunk-BGJLOJ7T.mjs.map +1 -0
  17. package/dist/chunk-BZBJVG5Y.js +88 -0
  18. package/dist/chunk-BZBJVG5Y.js.map +1 -0
  19. package/dist/{chunk-COI6GOX2.mjs → chunk-DOHML47I.mjs} +3 -3
  20. package/dist/chunk-DOHML47I.mjs.map +1 -0
  21. package/dist/chunk-DRFTRTKV.js +809 -0
  22. package/dist/chunk-DRFTRTKV.js.map +1 -0
  23. package/dist/chunk-EL5QTAA3.mjs +805 -0
  24. package/dist/chunk-EL5QTAA3.mjs.map +1 -0
  25. package/dist/chunk-GAJLEDRD.js +334 -0
  26. package/dist/chunk-GAJLEDRD.js.map +1 -0
  27. package/dist/{chunk-3MUOUXHV.js → chunk-K2HWVOEO.js} +3 -3
  28. package/dist/chunk-K2HWVOEO.js.map +1 -0
  29. package/dist/chunk-O2OHHBUD.js +997 -0
  30. package/dist/chunk-O2OHHBUD.js.map +1 -0
  31. package/dist/chunk-QAYJV4KK.js +608 -0
  32. package/dist/chunk-QAYJV4KK.js.map +1 -0
  33. package/dist/{chunk-FEBYQGY4 2.mjs → chunk-SMUFNQLM.mjs} +67 -3
  34. package/dist/chunk-SMUFNQLM.mjs.map +1 -0
  35. package/dist/chunk-VDMZZL2O.mjs +83 -0
  36. package/dist/chunk-VDMZZL2O.mjs.map +1 -0
  37. package/dist/chunk-XFRPT5ZX.mjs +1449 -0
  38. package/dist/chunk-XFRPT5ZX.mjs.map +1 -0
  39. package/dist/chunk-XQJX252G.mjs +981 -0
  40. package/dist/chunk-XQJX252G.mjs.map +1 -0
  41. package/dist/commerce/index.d.mts +168 -0
  42. package/dist/commerce/index.d.ts +168 -0
  43. package/dist/commerce/index.js +38 -38
  44. package/dist/commerce/index.mjs +1 -1
  45. package/dist/commerce/server.d.mts +98 -0
  46. package/dist/commerce/server.d.ts +98 -0
  47. package/dist/engage/index.d.mts +27 -0
  48. package/dist/engage/index.d.ts +27 -0
  49. package/dist/engage/index.js +7 -40
  50. package/dist/engage/index.js.map +1 -1
  51. package/dist/engage/index.mjs +1 -41
  52. package/dist/engage/index.mjs.map +1 -1
  53. package/dist/forms/index.d.mts +437 -0
  54. package/dist/forms/index.d.ts +437 -0
  55. package/dist/forms/index.js +13 -5
  56. package/dist/forms/index.js.map +1 -1
  57. package/dist/forms/index.mjs +2 -2
  58. package/dist/forms/index.mjs.map +1 -1
  59. package/dist/{generators-7Y5ABRYV 2.mjs → generators-TO2FKJR6.mjs} +134 -3
  60. package/dist/generators-TO2FKJR6.mjs.map +1 -0
  61. package/dist/{generators-GWIYCA5M.js → generators-YZWIGHCO.js} +135 -2
  62. package/dist/generators-YZWIGHCO.js.map +1 -0
  63. package/dist/images/index.d.mts +133 -0
  64. package/dist/images/index.d.ts +133 -0
  65. package/dist/images/index.js +41 -0
  66. package/dist/images/index.js.map +1 -0
  67. package/dist/images/index.mjs +8 -0
  68. package/dist/images/index.mjs.map +1 -0
  69. package/dist/index.d.mts +649 -0
  70. package/dist/index.d.ts +649 -0
  71. package/dist/index.js +1355 -104
  72. package/dist/index.js.map +1 -1
  73. package/dist/index.mjs +1242 -76
  74. package/dist/index.mjs.map +1 -1
  75. package/dist/redirects/index.d.mts +72 -0
  76. package/dist/redirects/index.d.ts +72 -0
  77. package/dist/redirects/index.js +25 -0
  78. package/dist/redirects/index.js.map +1 -0
  79. package/dist/redirects/index.mjs +4 -0
  80. package/dist/redirects/index.mjs.map +1 -0
  81. package/dist/routing-BWjUF7lp.d.ts +105 -0
  82. package/dist/routing-CgmRi9tD.d.mts +105 -0
  83. package/dist/{scanner-MF7P3CDE 2.mjs → scanner-AZV5I6US.mjs} +123 -4
  84. package/dist/scanner-AZV5I6US.mjs.map +1 -0
  85. package/dist/{scanner-NT6YG4TD 2.js → scanner-ETJAMIT7.js} +124 -3
  86. package/dist/scanner-ETJAMIT7.js.map +1 -0
  87. package/dist/seo/index.d.mts +273 -0
  88. package/dist/seo/index.d.ts +273 -0
  89. package/dist/seo/server.d.mts +89 -0
  90. package/dist/seo/server.d.ts +89 -0
  91. package/dist/setup/client.d.mts +60 -0
  92. package/dist/setup/client.d.ts +60 -0
  93. package/dist/setup/client.js +30 -0
  94. package/dist/setup/client.js.map +1 -0
  95. package/dist/setup/client.mjs +5 -0
  96. package/dist/setup/client.mjs.map +1 -0
  97. package/dist/setup/index.d.mts +5 -0
  98. package/dist/setup/index.d.ts +5 -0
  99. package/dist/setup/index.js +28 -1043
  100. package/dist/setup/index.js.map +1 -1
  101. package/dist/setup/index.mjs +3 -1043
  102. package/dist/setup/index.mjs.map +1 -1
  103. package/dist/setup/server.d.mts +14 -0
  104. package/dist/setup/server.d.ts +14 -0
  105. package/dist/setup/server.js +13 -0
  106. package/dist/setup/server.js.map +1 -0
  107. package/dist/setup/server.mjs +4 -0
  108. package/dist/setup/server.mjs.map +1 -0
  109. package/dist/sitemap/index.d.mts +78 -0
  110. package/dist/sitemap/index.d.ts +78 -0
  111. package/dist/types-BDojCvvL.d.mts +156 -0
  112. package/dist/types-BDojCvvL.d.ts +156 -0
  113. package/dist/types-BmzutFwy.d.mts +227 -0
  114. package/dist/types-BmzutFwy.d.ts +227 -0
  115. package/dist/types-C0pJGfbH.d.mts +155 -0
  116. package/dist/types-C0pJGfbH.d.ts +155 -0
  117. package/dist/types-DA_Kocle.d.mts +127 -0
  118. package/dist/types-DA_Kocle.d.ts +127 -0
  119. package/dist/types-lFLKKn0G.d.mts +163 -0
  120. package/dist/types-lFLKKn0G.d.ts +163 -0
  121. package/dist/types-nB206tPK.d.mts +309 -0
  122. package/dist/types-nB206tPK.d.ts +309 -0
  123. package/dist/useEventModal-6U1pF3_g.d.mts +209 -0
  124. package/dist/useEventModal-BA8g-1-P.d.ts +209 -0
  125. package/package.json +21 -1
  126. package/dist/chunk-3MUOUXHV.js.map +0 -1
  127. package/dist/chunk-4HVYXYQL 2.mjs +0 -255
  128. package/dist/chunk-4HVYXYQL.mjs +0 -255
  129. package/dist/chunk-4HVYXYQL.mjs.map +0 -1
  130. package/dist/chunk-COI6GOX2.mjs.map +0 -1
  131. package/dist/chunk-EQCVQC35.js 2.map +0 -1
  132. package/dist/chunk-FEBYQGY4.mjs +0 -251
  133. package/dist/chunk-FEBYQGY4.mjs.map +0 -1
  134. package/dist/chunk-NYKRE2FL 2.mjs +0 -31
  135. package/dist/chunk-NYKRE2FL.mjs 2.map +0 -1
  136. package/dist/chunk-RV7H3I6J.js 2.map +0 -1
  137. package/dist/chunk-RV7H3I6J.js.map +0 -1
  138. package/dist/chunk-TUKGA3UK.js +0 -257
  139. package/dist/chunk-TUKGA3UK.js 2.map +0 -1
  140. package/dist/chunk-TUKGA3UK.js.map +0 -1
  141. package/dist/generators-7Y5ABRYV.mjs +0 -161
  142. package/dist/generators-7Y5ABRYV.mjs 2.map +0 -1
  143. package/dist/generators-7Y5ABRYV.mjs.map +0 -1
  144. package/dist/generators-GWIYCA5M.js 2.map +0 -1
  145. package/dist/generators-GWIYCA5M.js.map +0 -1
  146. package/dist/index 2.mjs +0 -74
  147. package/dist/index.js 2.map +0 -1
  148. package/dist/migrator-V6KS75EA 2.mjs +0 -265
  149. package/dist/migrator-V6KS75EA.mjs 2.map +0 -1
  150. package/dist/migrator-XKM7YQCY.js 2.map +0 -1
  151. package/dist/scanner-MF7P3CDE.mjs +0 -14386
  152. package/dist/scanner-MF7P3CDE.mjs 2.map +0 -1
  153. package/dist/scanner-MF7P3CDE.mjs.map +0 -1
  154. package/dist/scanner-NT6YG4TD.js +0 -14397
  155. package/dist/scanner-NT6YG4TD.js 2.map +0 -1
  156. package/dist/scanner-NT6YG4TD.js.map +0 -1
  157. package/dist/web-vitals-BH55V7EJ.js 2.map +0 -1
  158. package/dist/web-vitals-RJYPWAR3 2.mjs +0 -241
  159. package/dist/web-vitals-RJYPWAR3.mjs 2.map +0 -1
@@ -1,255 +0,0 @@
1
- import { useState, useEffect, useCallback } from 'react';
2
- import { usePathname } from 'next/navigation';
3
- import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
4
-
5
- // src/engage/EngageWidget.tsx
6
- function getApiConfig() {
7
- const apiUrl = typeof window !== "undefined" ? window.__SITE_KIT_API_URL__ || "https://api.uptrademedia.com" : "https://api.uptrademedia.com";
8
- const apiKey = typeof window !== "undefined" ? window.__SITE_KIT_API_KEY__ : void 0;
9
- return { apiUrl, apiKey };
10
- }
11
- function EngageWidget({
12
- apiUrl: propApiUrl,
13
- apiKey: propApiKey,
14
- position = "bottom-right",
15
- zIndex = 9999,
16
- chatEnabled = true,
17
- debug = false
18
- }) {
19
- const pathname = usePathname();
20
- const [elements, setElements] = useState([]);
21
- const [activeElements, setActiveElements] = useState([]);
22
- const [dismissedElements, setDismissedElements] = useState(/* @__PURE__ */ new Set());
23
- useEffect(() => {
24
- async function loadElements() {
25
- const { apiUrl: globalApiUrl, apiKey: globalApiKey } = getApiConfig();
26
- const apiUrl = propApiUrl || globalApiUrl;
27
- const apiKey = propApiKey || globalApiKey;
28
- if (!apiKey) {
29
- if (debug) console.warn("[Engage] No API key configured");
30
- return;
31
- }
32
- try {
33
- const response = await fetch(`${apiUrl}/api/public/engage/elements`, {
34
- method: "POST",
35
- headers: {
36
- "Content-Type": "application/json",
37
- "x-api-key": apiKey
38
- },
39
- body: JSON.stringify({})
40
- });
41
- if (!response.ok) {
42
- if (debug) console.error("[Engage] Error loading elements:", response.statusText);
43
- return;
44
- }
45
- const data = await response.json();
46
- if (debug) console.log("[Engage] Loaded elements:", data.elements);
47
- setElements(data.elements || []);
48
- } catch (error) {
49
- if (debug) console.error("[Engage] Error loading elements:", error);
50
- }
51
- }
52
- loadElements();
53
- }, [propApiUrl, propApiKey, debug]);
54
- useEffect(() => {
55
- if (!elements.length) return;
56
- const checkElement = (element) => {
57
- if (dismissedElements.has(element.id)) return false;
58
- if (element.targeting?.pages) {
59
- const { include, exclude } = element.targeting.pages;
60
- if (exclude?.some((p) => matchPath(pathname, p))) return false;
61
- if (include && !include.some((p) => matchPath(pathname, p))) return false;
62
- }
63
- if (element.targeting?.devices) {
64
- const device = getDeviceType();
65
- if (!element.targeting.devices.includes(device)) return false;
66
- }
67
- if (element.trigger?.frequency) {
68
- const { type, days } = element.trigger.frequency;
69
- const key = `_engage_${element.id}`;
70
- if (type === "once") {
71
- if (localStorage.getItem(key)) return false;
72
- } else if (type === "once-per-session") {
73
- if (sessionStorage.getItem(key)) return false;
74
- } else if (type === "every-n-days" && days) {
75
- const lastShown = localStorage.getItem(key);
76
- if (lastShown) {
77
- const elapsed = Date.now() - parseInt(lastShown, 10);
78
- if (elapsed < days * 24 * 60 * 60 * 1e3) return false;
79
- }
80
- }
81
- }
82
- return true;
83
- };
84
- const eligible = elements.filter(checkElement);
85
- if (debug) console.log("[Engage] Eligible elements:", eligible);
86
- eligible.forEach((element) => {
87
- const trigger = element.trigger;
88
- if (trigger?.type === "immediate" || !trigger?.type) {
89
- setActiveElements((prev) => [...prev, element.id]);
90
- } else if (trigger?.type === "delay" && trigger.delay) {
91
- setTimeout(() => {
92
- setActiveElements((prev) => [...prev, element.id]);
93
- }, trigger.delay * 1e3);
94
- } else if (trigger?.type === "exit-intent") {
95
- const handleMouseLeave = (e) => {
96
- if (e.clientY < 10) {
97
- setActiveElements((prev) => [...prev, element.id]);
98
- document.removeEventListener("mouseleave", handleMouseLeave);
99
- }
100
- };
101
- document.addEventListener("mouseleave", handleMouseLeave);
102
- } else if (trigger?.type === "scroll" && trigger.scrollPercent) {
103
- const handleScroll = () => {
104
- const scrollPercent = window.scrollY / (document.body.scrollHeight - window.innerHeight) * 100;
105
- if (scrollPercent >= (trigger.scrollPercent || 50)) {
106
- setActiveElements((prev) => [...prev, element.id]);
107
- window.removeEventListener("scroll", handleScroll);
108
- }
109
- };
110
- window.addEventListener("scroll", handleScroll);
111
- }
112
- });
113
- }, [elements, pathname, dismissedElements, debug]);
114
- const handleDismiss = useCallback((elementId) => {
115
- setDismissedElements((prev) => /* @__PURE__ */ new Set([...prev, elementId]));
116
- setActiveElements((prev) => prev.filter((id) => id !== elementId));
117
- const element = elements.find((e) => e.id === elementId);
118
- if (element?.trigger?.frequency) {
119
- const key = `_engage_${elementId}`;
120
- if (element.trigger.frequency.type === "once-per-session") {
121
- sessionStorage.setItem(key, "true");
122
- } else {
123
- localStorage.setItem(key, Date.now().toString());
124
- }
125
- }
126
- }, [elements]);
127
- return /* @__PURE__ */ jsx(Fragment, { children: activeElements.map((elementId) => {
128
- const element = elements.find((e) => e.id === elementId);
129
- if (!element) return null;
130
- return /* @__PURE__ */ jsx(
131
- EngageElementRenderer,
132
- {
133
- element,
134
- onDismiss: () => handleDismiss(element.id),
135
- zIndex
136
- },
137
- element.id
138
- );
139
- }) });
140
- }
141
- function EngageElementRenderer({
142
- element,
143
- onDismiss,
144
- zIndex
145
- }) {
146
- if (element.type === "popup") {
147
- return /* @__PURE__ */ jsx(
148
- "div",
149
- {
150
- style: {
151
- position: "fixed",
152
- top: 0,
153
- left: 0,
154
- right: 0,
155
- bottom: 0,
156
- backgroundColor: "rgba(0,0,0,0.5)",
157
- display: "flex",
158
- alignItems: "center",
159
- justifyContent: "center",
160
- zIndex
161
- },
162
- onClick: onDismiss,
163
- children: /* @__PURE__ */ jsxs(
164
- "div",
165
- {
166
- style: {
167
- backgroundColor: "white",
168
- padding: 24,
169
- borderRadius: 8,
170
- maxWidth: 500,
171
- width: "90%"
172
- },
173
- onClick: (e) => e.stopPropagation(),
174
- children: [
175
- /* @__PURE__ */ jsx(
176
- "button",
177
- {
178
- onClick: onDismiss,
179
- style: {
180
- position: "absolute",
181
- top: 8,
182
- right: 8,
183
- background: "none",
184
- border: "none",
185
- fontSize: 24,
186
- cursor: "pointer"
187
- },
188
- children: "\xD7"
189
- }
190
- ),
191
- element.content?.title && /* @__PURE__ */ jsx("h2", { children: element.content.title }),
192
- element.content?.body && /* @__PURE__ */ jsx("p", { children: element.content.body })
193
- ]
194
- }
195
- )
196
- }
197
- );
198
- }
199
- if (element.type === "bar") {
200
- return /* @__PURE__ */ jsxs(
201
- "div",
202
- {
203
- style: {
204
- position: "fixed",
205
- top: 0,
206
- left: 0,
207
- right: 0,
208
- backgroundColor: element.styles?.backgroundColor || "#3b82f6",
209
- color: element.styles?.textColor || "white",
210
- padding: "12px 24px",
211
- display: "flex",
212
- alignItems: "center",
213
- justifyContent: "center",
214
- gap: 16,
215
- zIndex
216
- },
217
- children: [
218
- /* @__PURE__ */ jsx("span", { children: element.content?.body }),
219
- /* @__PURE__ */ jsx(
220
- "button",
221
- {
222
- onClick: onDismiss,
223
- style: {
224
- background: "none",
225
- border: "none",
226
- color: "inherit",
227
- fontSize: 20,
228
- cursor: "pointer"
229
- },
230
- children: "\xD7"
231
- }
232
- )
233
- ]
234
- }
235
- );
236
- }
237
- return null;
238
- }
239
- function matchPath(pathname, pattern) {
240
- if (pattern.endsWith("*")) {
241
- return pathname.startsWith(pattern.slice(0, -1));
242
- }
243
- return pathname === pattern;
244
- }
245
- function getDeviceType() {
246
- if (typeof window === "undefined") return "desktop";
247
- const ua = navigator.userAgent;
248
- if (/tablet|ipad|playbook|silk/i.test(ua)) return "tablet";
249
- if (/mobile|iphone|ipod|android|blackberry|opera mini|iemobile/i.test(ua)) return "mobile";
250
- return "desktop";
251
- }
252
-
253
- export { EngageWidget };
254
- //# sourceMappingURL=chunk-4HVYXYQL.mjs.map
255
- //# sourceMappingURL=chunk-4HVYXYQL.mjs.map
@@ -1,255 +0,0 @@
1
- import { useState, useEffect, useCallback } from 'react';
2
- import { usePathname } from 'next/navigation';
3
- import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
4
-
5
- // src/engage/EngageWidget.tsx
6
- function getApiConfig() {
7
- const apiUrl = typeof window !== "undefined" ? window.__SITE_KIT_API_URL__ || "https://api.uptrademedia.com" : "https://api.uptrademedia.com";
8
- const apiKey = typeof window !== "undefined" ? window.__SITE_KIT_API_KEY__ : void 0;
9
- return { apiUrl, apiKey };
10
- }
11
- function EngageWidget({
12
- apiUrl: propApiUrl,
13
- apiKey: propApiKey,
14
- position = "bottom-right",
15
- zIndex = 9999,
16
- chatEnabled = true,
17
- debug = false
18
- }) {
19
- const pathname = usePathname();
20
- const [elements, setElements] = useState([]);
21
- const [activeElements, setActiveElements] = useState([]);
22
- const [dismissedElements, setDismissedElements] = useState(/* @__PURE__ */ new Set());
23
- useEffect(() => {
24
- async function loadElements() {
25
- const { apiUrl: globalApiUrl, apiKey: globalApiKey } = getApiConfig();
26
- const apiUrl = propApiUrl || globalApiUrl;
27
- const apiKey = propApiKey || globalApiKey;
28
- if (!apiKey) {
29
- if (debug) console.warn("[Engage] No API key configured");
30
- return;
31
- }
32
- try {
33
- const response = await fetch(`${apiUrl}/api/public/engage/elements`, {
34
- method: "POST",
35
- headers: {
36
- "Content-Type": "application/json",
37
- "x-api-key": apiKey
38
- },
39
- body: JSON.stringify({})
40
- });
41
- if (!response.ok) {
42
- if (debug) console.error("[Engage] Error loading elements:", response.statusText);
43
- return;
44
- }
45
- const data = await response.json();
46
- if (debug) console.log("[Engage] Loaded elements:", data.elements);
47
- setElements(data.elements || []);
48
- } catch (error) {
49
- if (debug) console.error("[Engage] Error loading elements:", error);
50
- }
51
- }
52
- loadElements();
53
- }, [propApiUrl, propApiKey, debug]);
54
- useEffect(() => {
55
- if (!elements.length) return;
56
- const checkElement = (element) => {
57
- if (dismissedElements.has(element.id)) return false;
58
- if (element.targeting?.pages) {
59
- const { include, exclude } = element.targeting.pages;
60
- if (exclude?.some((p) => matchPath(pathname, p))) return false;
61
- if (include && !include.some((p) => matchPath(pathname, p))) return false;
62
- }
63
- if (element.targeting?.devices) {
64
- const device = getDeviceType();
65
- if (!element.targeting.devices.includes(device)) return false;
66
- }
67
- if (element.trigger?.frequency) {
68
- const { type, days } = element.trigger.frequency;
69
- const key = `_engage_${element.id}`;
70
- if (type === "once") {
71
- if (localStorage.getItem(key)) return false;
72
- } else if (type === "once-per-session") {
73
- if (sessionStorage.getItem(key)) return false;
74
- } else if (type === "every-n-days" && days) {
75
- const lastShown = localStorage.getItem(key);
76
- if (lastShown) {
77
- const elapsed = Date.now() - parseInt(lastShown, 10);
78
- if (elapsed < days * 24 * 60 * 60 * 1e3) return false;
79
- }
80
- }
81
- }
82
- return true;
83
- };
84
- const eligible = elements.filter(checkElement);
85
- if (debug) console.log("[Engage] Eligible elements:", eligible);
86
- eligible.forEach((element) => {
87
- const trigger = element.trigger;
88
- if (trigger?.type === "immediate" || !trigger?.type) {
89
- setActiveElements((prev) => [...prev, element.id]);
90
- } else if (trigger?.type === "delay" && trigger.delay) {
91
- setTimeout(() => {
92
- setActiveElements((prev) => [...prev, element.id]);
93
- }, trigger.delay * 1e3);
94
- } else if (trigger?.type === "exit-intent") {
95
- const handleMouseLeave = (e) => {
96
- if (e.clientY < 10) {
97
- setActiveElements((prev) => [...prev, element.id]);
98
- document.removeEventListener("mouseleave", handleMouseLeave);
99
- }
100
- };
101
- document.addEventListener("mouseleave", handleMouseLeave);
102
- } else if (trigger?.type === "scroll" && trigger.scrollPercent) {
103
- const handleScroll = () => {
104
- const scrollPercent = window.scrollY / (document.body.scrollHeight - window.innerHeight) * 100;
105
- if (scrollPercent >= (trigger.scrollPercent || 50)) {
106
- setActiveElements((prev) => [...prev, element.id]);
107
- window.removeEventListener("scroll", handleScroll);
108
- }
109
- };
110
- window.addEventListener("scroll", handleScroll);
111
- }
112
- });
113
- }, [elements, pathname, dismissedElements, debug]);
114
- const handleDismiss = useCallback((elementId) => {
115
- setDismissedElements((prev) => /* @__PURE__ */ new Set([...prev, elementId]));
116
- setActiveElements((prev) => prev.filter((id) => id !== elementId));
117
- const element = elements.find((e) => e.id === elementId);
118
- if (element?.trigger?.frequency) {
119
- const key = `_engage_${elementId}`;
120
- if (element.trigger.frequency.type === "once-per-session") {
121
- sessionStorage.setItem(key, "true");
122
- } else {
123
- localStorage.setItem(key, Date.now().toString());
124
- }
125
- }
126
- }, [elements]);
127
- return /* @__PURE__ */ jsx(Fragment, { children: activeElements.map((elementId) => {
128
- const element = elements.find((e) => e.id === elementId);
129
- if (!element) return null;
130
- return /* @__PURE__ */ jsx(
131
- EngageElementRenderer,
132
- {
133
- element,
134
- onDismiss: () => handleDismiss(element.id),
135
- zIndex
136
- },
137
- element.id
138
- );
139
- }) });
140
- }
141
- function EngageElementRenderer({
142
- element,
143
- onDismiss,
144
- zIndex
145
- }) {
146
- if (element.type === "popup") {
147
- return /* @__PURE__ */ jsx(
148
- "div",
149
- {
150
- style: {
151
- position: "fixed",
152
- top: 0,
153
- left: 0,
154
- right: 0,
155
- bottom: 0,
156
- backgroundColor: "rgba(0,0,0,0.5)",
157
- display: "flex",
158
- alignItems: "center",
159
- justifyContent: "center",
160
- zIndex
161
- },
162
- onClick: onDismiss,
163
- children: /* @__PURE__ */ jsxs(
164
- "div",
165
- {
166
- style: {
167
- backgroundColor: "white",
168
- padding: 24,
169
- borderRadius: 8,
170
- maxWidth: 500,
171
- width: "90%"
172
- },
173
- onClick: (e) => e.stopPropagation(),
174
- children: [
175
- /* @__PURE__ */ jsx(
176
- "button",
177
- {
178
- onClick: onDismiss,
179
- style: {
180
- position: "absolute",
181
- top: 8,
182
- right: 8,
183
- background: "none",
184
- border: "none",
185
- fontSize: 24,
186
- cursor: "pointer"
187
- },
188
- children: "\xD7"
189
- }
190
- ),
191
- element.content?.title && /* @__PURE__ */ jsx("h2", { children: element.content.title }),
192
- element.content?.body && /* @__PURE__ */ jsx("p", { children: element.content.body })
193
- ]
194
- }
195
- )
196
- }
197
- );
198
- }
199
- if (element.type === "bar") {
200
- return /* @__PURE__ */ jsxs(
201
- "div",
202
- {
203
- style: {
204
- position: "fixed",
205
- top: 0,
206
- left: 0,
207
- right: 0,
208
- backgroundColor: element.styles?.backgroundColor || "#3b82f6",
209
- color: element.styles?.textColor || "white",
210
- padding: "12px 24px",
211
- display: "flex",
212
- alignItems: "center",
213
- justifyContent: "center",
214
- gap: 16,
215
- zIndex
216
- },
217
- children: [
218
- /* @__PURE__ */ jsx("span", { children: element.content?.body }),
219
- /* @__PURE__ */ jsx(
220
- "button",
221
- {
222
- onClick: onDismiss,
223
- style: {
224
- background: "none",
225
- border: "none",
226
- color: "inherit",
227
- fontSize: 20,
228
- cursor: "pointer"
229
- },
230
- children: "\xD7"
231
- }
232
- )
233
- ]
234
- }
235
- );
236
- }
237
- return null;
238
- }
239
- function matchPath(pathname, pattern) {
240
- if (pattern.endsWith("*")) {
241
- return pathname.startsWith(pattern.slice(0, -1));
242
- }
243
- return pathname === pattern;
244
- }
245
- function getDeviceType() {
246
- if (typeof window === "undefined") return "desktop";
247
- const ua = navigator.userAgent;
248
- if (/tablet|ipad|playbook|silk/i.test(ua)) return "tablet";
249
- if (/mobile|iphone|ipod|android|blackberry|opera mini|iemobile/i.test(ua)) return "mobile";
250
- return "desktop";
251
- }
252
-
253
- export { EngageWidget };
254
- //# sourceMappingURL=chunk-4HVYXYQL.mjs.map
255
- //# sourceMappingURL=chunk-4HVYXYQL.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/engage/EngageWidget.tsx"],"names":[],"mappings":"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","file":"chunk-4HVYXYQL.mjs","sourcesContent":["/**\n * @uptrade/site-kit/engage - Engage Widget\n * \n * Loads and renders engagement widgets (popups, nudges, bars) via Portal API\n */\n\n'use client'\n\nimport React, { useEffect, useState, useCallback } from 'react'\nimport { usePathname } from 'next/navigation'\nimport type { EngageElement } from './types'\n\ninterface EngageWidgetProps {\n apiUrl?: string\n apiKey?: string\n position?: 'bottom-right' | 'bottom-left'\n zIndex?: number\n chatEnabled?: boolean\n debug?: boolean\n}\n\nfunction getApiConfig() {\n const apiUrl = typeof window !== 'undefined' \n ? (window as any).__SITE_KIT_API_URL__ || 'https://api.uptrademedia.com'\n : 'https://api.uptrademedia.com'\n const apiKey = typeof window !== 'undefined' \n ? (window as any).__SITE_KIT_API_KEY__\n : undefined\n return { apiUrl, apiKey }\n}\n\nexport function EngageWidget({\n apiUrl: propApiUrl,\n apiKey: propApiKey,\n position = 'bottom-right',\n zIndex = 9999,\n chatEnabled = true,\n debug = false,\n}: EngageWidgetProps) {\n const pathname = usePathname()\n const [elements, setElements] = useState<EngageElement[]>([])\n const [activeElements, setActiveElements] = useState<string[]>([])\n const [dismissedElements, setDismissedElements] = useState<Set<string>>(new Set())\n \n // Load elements from API\n useEffect(() => {\n async function loadElements() {\n const { apiUrl: globalApiUrl, apiKey: globalApiKey } = getApiConfig()\n const apiUrl = propApiUrl || globalApiUrl\n const apiKey = propApiKey || globalApiKey\n \n if (!apiKey) {\n if (debug) console.warn('[Engage] No API key configured')\n return\n }\n \n try {\n const response = await fetch(`${apiUrl}/api/public/engage/elements`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n },\n body: JSON.stringify({}),\n })\n \n if (!response.ok) {\n if (debug) console.error('[Engage] Error loading elements:', response.statusText)\n return\n }\n \n const data = await response.json()\n if (debug) console.log('[Engage] Loaded elements:', data.elements)\n setElements(data.elements || [])\n } catch (error) {\n if (debug) console.error('[Engage] Error loading elements:', error)\n }\n }\n \n loadElements()\n }, [propApiUrl, propApiKey, debug])\n \n // Check targeting and trigger for each element\n useEffect(() => {\n if (!elements.length) return\n \n const checkElement = (element: EngageElement): boolean => {\n // Check if dismissed\n if (dismissedElements.has(element.id)) return false\n \n // Check page targeting\n if (element.targeting?.pages) {\n const { include, exclude } = element.targeting.pages\n \n if (exclude?.some(p => matchPath(pathname, p))) return false\n if (include && !include.some(p => matchPath(pathname, p))) return false\n }\n \n // Check device targeting\n if (element.targeting?.devices) {\n const device = getDeviceType()\n if (!element.targeting.devices.includes(device)) return false\n }\n \n // Check frequency capping\n if (element.trigger?.frequency) {\n const { type, days } = element.trigger.frequency\n const key = `_engage_${element.id}`\n \n if (type === 'once') {\n if (localStorage.getItem(key)) return false\n } else if (type === 'once-per-session') {\n if (sessionStorage.getItem(key)) return false\n } else if (type === 'every-n-days' && days) {\n const lastShown = localStorage.getItem(key)\n if (lastShown) {\n const elapsed = Date.now() - parseInt(lastShown, 10)\n if (elapsed < days * 24 * 60 * 60 * 1000) return false\n }\n }\n }\n \n return true\n }\n \n // Filter elements that pass targeting\n const eligible = elements.filter(checkElement)\n \n if (debug) console.log('[Engage] Eligible elements:', eligible)\n \n // Set up triggers for eligible elements\n eligible.forEach(element => {\n const trigger = element.trigger\n \n if (trigger?.type === 'immediate' || !trigger?.type) {\n setActiveElements(prev => [...prev, element.id])\n } else if (trigger?.type === 'delay' && trigger.delay) {\n setTimeout(() => {\n setActiveElements(prev => [...prev, element.id])\n }, trigger.delay * 1000)\n } else if (trigger?.type === 'exit-intent') {\n const handleMouseLeave = (e: MouseEvent) => {\n if (e.clientY < 10) {\n setActiveElements(prev => [...prev, element.id])\n document.removeEventListener('mouseleave', handleMouseLeave)\n }\n }\n document.addEventListener('mouseleave', handleMouseLeave)\n } else if (trigger?.type === 'scroll' && trigger.scrollPercent) {\n const handleScroll = () => {\n const scrollPercent = (window.scrollY / (document.body.scrollHeight - window.innerHeight)) * 100\n if (scrollPercent >= (trigger.scrollPercent || 50)) {\n setActiveElements(prev => [...prev, element.id])\n window.removeEventListener('scroll', handleScroll)\n }\n }\n window.addEventListener('scroll', handleScroll)\n }\n })\n }, [elements, pathname, dismissedElements, debug])\n \n const handleDismiss = useCallback((elementId: string) => {\n setDismissedElements(prev => new Set([...prev, elementId]))\n setActiveElements(prev => prev.filter(id => id !== elementId))\n \n // Record dismissal in storage\n const element = elements.find(e => e.id === elementId)\n if (element?.trigger?.frequency) {\n const key = `_engage_${elementId}`\n if (element.trigger.frequency.type === 'once-per-session') {\n sessionStorage.setItem(key, 'true')\n } else {\n localStorage.setItem(key, Date.now().toString())\n }\n }\n }, [elements])\n \n // Render active elements\n return (\n <>\n {activeElements.map(elementId => {\n const element = elements.find(e => e.id === elementId)\n if (!element) return null\n \n return (\n <EngageElementRenderer\n key={element.id}\n element={element}\n onDismiss={() => handleDismiss(element.id)}\n zIndex={zIndex}\n />\n )\n })}\n </>\n )\n}\n\n// Helper components\nfunction EngageElementRenderer({ \n element, \n onDismiss,\n zIndex,\n}: { \n element: EngageElement\n onDismiss: () => void\n zIndex: number\n}) {\n // Simple popup rendering - expand as needed\n if (element.type === 'popup') {\n return (\n <div\n style={{\n position: 'fixed',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n backgroundColor: 'rgba(0,0,0,0.5)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n zIndex,\n }}\n onClick={onDismiss}\n >\n <div\n style={{\n backgroundColor: 'white',\n padding: 24,\n borderRadius: 8,\n maxWidth: 500,\n width: '90%',\n }}\n onClick={e => e.stopPropagation()}\n >\n <button\n onClick={onDismiss}\n style={{\n position: 'absolute',\n top: 8,\n right: 8,\n background: 'none',\n border: 'none',\n fontSize: 24,\n cursor: 'pointer',\n }}\n >\n ×\n </button>\n {element.content?.title && <h2>{element.content.title}</h2>}\n {element.content?.body && <p>{element.content.body}</p>}\n </div>\n </div>\n )\n }\n \n // Bar/banner rendering\n if (element.type === 'bar') {\n return (\n <div\n style={{\n position: 'fixed',\n top: 0,\n left: 0,\n right: 0,\n backgroundColor: element.styles?.backgroundColor || '#3b82f6',\n color: element.styles?.textColor || 'white',\n padding: '12px 24px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 16,\n zIndex,\n }}\n >\n <span>{element.content?.body}</span>\n <button\n onClick={onDismiss}\n style={{\n background: 'none',\n border: 'none',\n color: 'inherit',\n fontSize: 20,\n cursor: 'pointer',\n }}\n >\n ×\n </button>\n </div>\n )\n }\n \n return null\n}\n\n// Utilities\nfunction matchPath(pathname: string, pattern: string): boolean {\n if (pattern.endsWith('*')) {\n return pathname.startsWith(pattern.slice(0, -1))\n }\n return pathname === pattern\n}\n\nfunction getDeviceType(): 'desktop' | 'mobile' | 'tablet' {\n if (typeof window === 'undefined') return 'desktop'\n const ua = navigator.userAgent\n if (/tablet|ipad|playbook|silk/i.test(ua)) return 'tablet'\n if (/mobile|iphone|ipod|android|blackberry|opera mini|iemobile/i.test(ua)) return 'mobile'\n return 'desktop'\n}\n"]}