@nektarlabs/adsterix-widget 1.0.1 → 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.
@@ -0,0 +1,9 @@
1
+ import * as React from 'react';
2
+
3
+ interface AdsterixWidgetProps {
4
+ castHash?: string;
5
+ onClose?: () => void;
6
+ }
7
+ declare const AdsterixWidget: React.FC<AdsterixWidgetProps>;
8
+
9
+ export { AdsterixWidget, type AdsterixWidgetProps };
package/dist/index.mjs ADDED
@@ -0,0 +1,306 @@
1
+ import * as React from 'react';
2
+ import { motion, AnimatePresence } from 'framer-motion';
3
+ import { X, ShoppingBag, ExternalLink, Sparkles } from 'lucide-react';
4
+ import { jsx, jsxs } from 'react/jsx-runtime';
5
+
6
+ // src/AdsterixWidget.tsx
7
+ var CtaButton = ({ label, icon, onClick, showLabel }) => /* @__PURE__ */ jsxs(
8
+ motion.div,
9
+ {
10
+ onClick,
11
+ style: {
12
+ display: "flex",
13
+ alignItems: "center",
14
+ gap: showLabel ? 6 : 0,
15
+ padding: showLabel ? "8px 14px" : "8px",
16
+ borderRadius: 20,
17
+ background: "rgba(255,255,255,0.9)",
18
+ backdropFilter: "blur(8px)",
19
+ color: "#0f172a",
20
+ fontSize: 13,
21
+ fontWeight: 600,
22
+ fontFamily: "system-ui, -apple-system, sans-serif",
23
+ boxShadow: "0 4px 12px rgba(0,0,0,0.15)",
24
+ cursor: "pointer"
25
+ },
26
+ whileHover: {
27
+ y: -2,
28
+ background: "rgba(255,255,255,0.98)",
29
+ boxShadow: "0 8px 20px rgba(0,0,0,0.2)"
30
+ },
31
+ transition: { type: "spring", stiffness: 400, damping: 15 },
32
+ children: [
33
+ showLabel && label,
34
+ /* @__PURE__ */ jsx(
35
+ motion.span,
36
+ {
37
+ style: { display: "flex", alignItems: "center" },
38
+ whileHover: { x: showLabel ? 2 : 0 },
39
+ transition: { type: "spring", stiffness: 400, damping: 15 },
40
+ children: icon
41
+ }
42
+ )
43
+ ]
44
+ }
45
+ );
46
+ var AdsterixWidget = ({ castHash, onClose }) => {
47
+ const [ctaDetails, setCtaDetails] = React.useState(null);
48
+ const [error, setError] = React.useState(null);
49
+ const [loading, setLoading] = React.useState(false);
50
+ const [imageLoaded, setImageLoaded] = React.useState(false);
51
+ const [visible, setVisible] = React.useState(true);
52
+ const [isSmall, setIsSmall] = React.useState(true);
53
+ const containerRef = React.useRef(null);
54
+ React.useEffect(() => {
55
+ if (!castHash) return;
56
+ const fetchCtaDetails = async () => {
57
+ setLoading(true);
58
+ setError(null);
59
+ try {
60
+ const response = await fetch(`https://www.adsterix.xyz/api/ads/cta-details/${castHash}`);
61
+ if (!response.ok) {
62
+ throw new Error(`Failed to fetch: ${response.status}`);
63
+ }
64
+ const data = await response.json();
65
+ setCtaDetails(data);
66
+ } catch (err) {
67
+ setError(err instanceof Error ? err.message : "Unknown error");
68
+ } finally {
69
+ setLoading(false);
70
+ }
71
+ };
72
+ fetchCtaDetails();
73
+ }, [castHash]);
74
+ React.useEffect(() => {
75
+ if (!containerRef.current) return;
76
+ const checkSize = (entries) => {
77
+ for (const entry of entries) {
78
+ const width = entry.contentRect.width;
79
+ setIsSmall(width < 270);
80
+ }
81
+ };
82
+ const resizeObserver = new ResizeObserver(checkSize);
83
+ resizeObserver.observe(containerRef.current);
84
+ if (containerRef.current) {
85
+ const width = containerRef.current.offsetWidth;
86
+ setIsSmall(width < 400);
87
+ }
88
+ return () => resizeObserver.disconnect();
89
+ }, [loading, ctaDetails]);
90
+ const handleAdClick = () => {
91
+ if (ctaDetails == null ? void 0 : ctaDetails.url) {
92
+ window.open(ctaDetails.url, "_blank", "noopener,noreferrer");
93
+ }
94
+ };
95
+ const handleBuySlotClick = (e) => {
96
+ e.stopPropagation();
97
+ if (ctaDetails == null ? void 0 : ctaDetails.buySlotUrl) window.open(ctaDetails.buySlotUrl, "_blank", "noopener,noreferrer");
98
+ };
99
+ const handleClose = (e) => {
100
+ e.stopPropagation();
101
+ setVisible(false);
102
+ onClose == null ? void 0 : onClose();
103
+ };
104
+ if (!visible) return null;
105
+ if (error) {
106
+ return /* @__PURE__ */ jsx(
107
+ motion.div,
108
+ {
109
+ initial: { opacity: 0, y: 10 },
110
+ animate: { opacity: 1, y: 0 },
111
+ style: {
112
+ display: "flex",
113
+ alignItems: "center",
114
+ justifyContent: "center",
115
+ padding: 16,
116
+ borderRadius: 12,
117
+ background: "linear-gradient(135deg, #0f172a 0%, #1e293b 100%)",
118
+ color: "#f87171",
119
+ fontSize: 14,
120
+ fontWeight: 500,
121
+ fontFamily: "system-ui, -apple-system, sans-serif"
122
+ },
123
+ children: "Unable to load ad"
124
+ }
125
+ );
126
+ }
127
+ if (loading || !ctaDetails) {
128
+ return /* @__PURE__ */ jsx(
129
+ "div",
130
+ {
131
+ ref: containerRef,
132
+ style: {
133
+ position: "relative",
134
+ width: "100%",
135
+ aspectRatio: "3 / 2",
136
+ borderRadius: 12,
137
+ background: "linear-gradient(135deg, #0f172a 0%, #1e293b 100%)",
138
+ overflow: "hidden"
139
+ },
140
+ children: /* @__PURE__ */ jsx(
141
+ motion.div,
142
+ {
143
+ style: {
144
+ position: "absolute",
145
+ inset: 0,
146
+ background: "linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.05) 50%, transparent 100%)"
147
+ },
148
+ animate: { x: ["-100%", "100%"] },
149
+ transition: { duration: 1.5, repeat: Infinity, ease: "linear" }
150
+ }
151
+ )
152
+ }
153
+ );
154
+ }
155
+ return /* @__PURE__ */ jsxs(
156
+ motion.div,
157
+ {
158
+ ref: containerRef,
159
+ onClick: handleAdClick,
160
+ initial: { opacity: 0, scale: 0.95 },
161
+ animate: { opacity: 1, scale: 1 },
162
+ exit: { opacity: 0, scale: 0.95 },
163
+ whileHover: { scale: 1.02 },
164
+ whileTap: { scale: 0.98 },
165
+ transition: { type: "spring", stiffness: 300, damping: 20 },
166
+ style: {
167
+ position: "relative",
168
+ width: "100%",
169
+ aspectRatio: "3 / 2",
170
+ borderRadius: 12,
171
+ overflow: "hidden",
172
+ cursor: "pointer",
173
+ boxShadow: "0 10px 30px rgba(0,0,0,0.2)"
174
+ },
175
+ children: [
176
+ /* @__PURE__ */ jsx(AnimatePresence, { children: imageLoaded && /* @__PURE__ */ jsx(
177
+ motion.img,
178
+ {
179
+ src: ctaDetails.image,
180
+ alt: "Advertisement",
181
+ initial: { opacity: 0 },
182
+ animate: { opacity: 1 },
183
+ transition: { duration: 0.4 },
184
+ style: {
185
+ position: "absolute",
186
+ inset: 0,
187
+ width: "100%",
188
+ height: "100%",
189
+ objectFit: "cover"
190
+ }
191
+ }
192
+ ) }),
193
+ /* @__PURE__ */ jsx("img", { src: ctaDetails.image, alt: "", onLoad: () => setImageLoaded(true), style: { display: "none" } }),
194
+ /* @__PURE__ */ jsx(
195
+ motion.div,
196
+ {
197
+ style: {
198
+ position: "absolute",
199
+ inset: 0,
200
+ background: "linear-gradient(to top, rgba(0,0,0,0.3) 0%, transparent 50%)"
201
+ },
202
+ whileHover: {
203
+ background: "linear-gradient(to top, rgba(0,0,0,0.6) 0%, transparent 60%)"
204
+ },
205
+ transition: { duration: 0.3 }
206
+ }
207
+ ),
208
+ /* @__PURE__ */ jsx(
209
+ motion.div,
210
+ {
211
+ onClick: handleClose,
212
+ style: {
213
+ position: "absolute",
214
+ top: 10,
215
+ right: 10,
216
+ display: "flex",
217
+ alignItems: "center",
218
+ justifyContent: "center",
219
+ width: 28,
220
+ height: 28,
221
+ borderRadius: "50%",
222
+ background: "rgba(0,0,0,0.5)",
223
+ backdropFilter: "blur(8px)",
224
+ color: "rgba(255,255,255,0.8)",
225
+ cursor: "pointer"
226
+ },
227
+ whileHover: {
228
+ background: "rgba(0,0,0,0.7)",
229
+ color: "rgba(255,255,255,1)",
230
+ scale: 1.1
231
+ },
232
+ whileTap: { scale: 0.95 },
233
+ transition: { type: "spring", stiffness: 400, damping: 15 },
234
+ children: /* @__PURE__ */ jsx(X, { size: 14, strokeWidth: 2.5 })
235
+ }
236
+ ),
237
+ /* @__PURE__ */ jsxs(
238
+ "div",
239
+ {
240
+ style: {
241
+ position: "absolute",
242
+ bottom: 12,
243
+ right: 12,
244
+ display: "flex",
245
+ gap: 8
246
+ },
247
+ children: [
248
+ /* @__PURE__ */ jsx(
249
+ CtaButton,
250
+ {
251
+ label: "Buy Slot",
252
+ icon: /* @__PURE__ */ jsx(ShoppingBag, { size: 14, strokeWidth: 2.5 }),
253
+ onClick: handleBuySlotClick,
254
+ showLabel: !isSmall
255
+ }
256
+ ),
257
+ /* @__PURE__ */ jsx(
258
+ CtaButton,
259
+ {
260
+ label: "Learn More",
261
+ icon: /* @__PURE__ */ jsx(ExternalLink, { size: 14, strokeWidth: 2.5 }),
262
+ onClick: (e) => {
263
+ e.stopPropagation();
264
+ handleAdClick();
265
+ },
266
+ showLabel: !isSmall
267
+ }
268
+ )
269
+ ]
270
+ }
271
+ ),
272
+ /* @__PURE__ */ jsxs(
273
+ "div",
274
+ {
275
+ style: {
276
+ position: "absolute",
277
+ top: 10,
278
+ left: 10,
279
+ display: "flex",
280
+ alignItems: "center",
281
+ gap: 4,
282
+ padding: "4px 8px",
283
+ borderRadius: 6,
284
+ background: "rgba(0,0,0,0.5)",
285
+ backdropFilter: "blur(8px)",
286
+ color: "rgba(255,255,255,0.8)",
287
+ fontSize: 10,
288
+ fontWeight: 500,
289
+ fontFamily: "system-ui, -apple-system, sans-serif",
290
+ letterSpacing: "0.5px",
291
+ textTransform: "uppercase"
292
+ },
293
+ children: [
294
+ /* @__PURE__ */ jsx(Sparkles, { size: 10 }),
295
+ "Ad"
296
+ ]
297
+ }
298
+ )
299
+ ]
300
+ }
301
+ );
302
+ };
303
+
304
+ export { AdsterixWidget };
305
+ //# sourceMappingURL=index.mjs.map
306
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/AdsterixWidget.tsx"],"names":[],"mappings":";;;;;;AAeA,IAAM,YAKD,CAAC,EAAE,OAAO,IAAA,EAAM,OAAA,EAAS,WAAU,qBACtC,IAAA;AAAA,EAAC,MAAA,CAAO,GAAA;AAAA,EAAP;AAAA,IACC,OAAA;AAAA,IACA,KAAA,EAAO;AAAA,MACL,OAAA,EAAS,MAAA;AAAA,MACT,UAAA,EAAY,QAAA;AAAA,MACZ,GAAA,EAAK,YAAY,CAAA,GAAI,CAAA;AAAA,MACrB,OAAA,EAAS,YAAY,UAAA,GAAa,KAAA;AAAA,MAClC,YAAA,EAAc,EAAA;AAAA,MACd,UAAA,EAAY,uBAAA;AAAA,MACZ,cAAA,EAAgB,WAAA;AAAA,MAChB,KAAA,EAAO,SAAA;AAAA,MACP,QAAA,EAAU,EAAA;AAAA,MACV,UAAA,EAAY,GAAA;AAAA,MACZ,UAAA,EAAY,sCAAA;AAAA,MACZ,SAAA,EAAW,6BAAA;AAAA,MACX,MAAA,EAAQ;AAAA,KACV;AAAA,IACA,UAAA,EAAY;AAAA,MACV,CAAA,EAAG,EAAA;AAAA,MACH,UAAA,EAAY,wBAAA;AAAA,MACZ,SAAA,EAAW;AAAA,KACb;AAAA,IACA,YAAY,EAAE,IAAA,EAAM,UAAU,SAAA,EAAW,GAAA,EAAK,SAAS,EAAA,EAAG;AAAA,IAEzD,QAAA,EAAA;AAAA,MAAA,SAAA,IAAa,KAAA;AAAA,sBACd,GAAA;AAAA,QAAC,MAAA,CAAO,IAAA;AAAA,QAAP;AAAA,UACC,KAAA,EAAO,EAAE,OAAA,EAAS,MAAA,EAAQ,YAAY,QAAA,EAAS;AAAA,UAC/C,UAAA,EAAY,EAAE,CAAA,EAAG,SAAA,GAAY,IAAI,CAAA,EAAE;AAAA,UACnC,YAAY,EAAE,IAAA,EAAM,UAAU,SAAA,EAAW,GAAA,EAAK,SAAS,EAAA,EAAG;AAAA,UAEzD,QAAA,EAAA;AAAA;AAAA;AACH;AAAA;AACF,CAAA;AAGK,IAAM,cAAA,GAAgD,CAAC,EAAE,QAAA,EAAU,SAAQ,KAAM;AACtF,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAU,eAA4B,IAAI,CAAA;AAC1E,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAU,eAAwB,IAAI,CAAA;AAC5D,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAU,eAAS,KAAK,CAAA;AAClD,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAU,eAAS,KAAK,CAAA;AAC1D,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAU,eAAS,IAAI,CAAA;AACjD,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAU,eAAS,IAAI,CAAA;AACjD,EAAA,MAAM,YAAA,GAAqB,aAAuB,IAAI,CAAA;AAEtD,EAAM,gBAAU,MAAM;AACpB,IAAA,IAAI,CAAC,QAAA,EAAU;AAEf,IAAA,MAAM,kBAAkB,YAAY;AAClC,MAAA,UAAA,CAAW,IAAI,CAAA;AACf,MAAA,QAAA,CAAS,IAAI,CAAA;AAEb,MAAA,IAAI;AACF,QAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,CAAA,6CAAA,EAAgD,QAAQ,CAAA,CAAE,CAAA;AAEvF,QAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,UAAA,MAAM,IAAI,KAAA,CAAM,CAAA,iBAAA,EAAoB,QAAA,CAAS,MAAM,CAAA,CAAE,CAAA;AAAA,QACvD;AAEA,QAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,QAAA,aAAA,CAAc,IAAI,CAAA;AAAA,MACpB,SAAS,GAAA,EAAK;AACZ,QAAA,QAAA,CAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,eAAe,CAAA;AAAA,MAC/D,CAAA,SAAE;AACA,QAAA,UAAA,CAAW,KAAK,CAAA;AAAA,MAClB;AAAA,IACF,CAAA;AAEA,IAAA,eAAA,EAAgB;AAAA,EAClB,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AAEb,EAAM,gBAAU,MAAM;AACpB,IAAA,IAAI,CAAC,aAAa,OAAA,EAAS;AAE3B,IAAA,MAAM,SAAA,GAAY,CAAC,OAAA,KAAmC;AACpD,MAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AAC3B,QAAA,MAAM,KAAA,GAAQ,MAAM,WAAA,CAAY,KAAA;AAChC,QAAA,UAAA,CAAW,QAAQ,GAAG,CAAA;AAAA,MACxB;AAAA,IACF,CAAA;AAEA,IAAA,MAAM,cAAA,GAAiB,IAAI,cAAA,CAAe,SAAS,CAAA;AACnD,IAAA,cAAA,CAAe,OAAA,CAAQ,aAAa,OAAO,CAAA;AAG3C,IAAA,IAAI,aAAa,OAAA,EAAS;AACxB,MAAA,MAAM,KAAA,GAAQ,aAAa,OAAA,CAAQ,WAAA;AACnC,MAAA,UAAA,CAAW,QAAQ,GAAG,CAAA;AAAA,IACxB;AAEA,IAAA,OAAO,MAAM,eAAe,UAAA,EAAW;AAAA,EACzC,CAAA,EAAG,CAAC,OAAA,EAAS,UAAU,CAAC,CAAA;AAExB,EAAA,MAAM,gBAAgB,MAAM;AAC1B,IAAA,IAAI,yCAAY,GAAA,EAAK;AACnB,MAAA,MAAA,CAAO,IAAA,CAAK,UAAA,CAAW,GAAA,EAAK,QAAA,EAAU,qBAAqB,CAAA;AAAA,IAC7D;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,kBAAA,GAAqB,CAAC,CAAA,KAAwB;AAClD,IAAA,CAAA,CAAE,eAAA,EAAgB;AAClB,IAAA,IAAI,yCAAY,UAAA,EAAY,MAAA,CAAO,KAAK,UAAA,CAAW,UAAA,EAAY,UAAU,qBAAqB,CAAA;AAAA,EAChG,CAAA;AAEA,EAAA,MAAM,WAAA,GAAc,CAAC,CAAA,KAAwB;AAC3C,IAAA,CAAA,CAAE,eAAA,EAAgB;AAClB,IAAA,UAAA,CAAW,KAAK,CAAA;AAChB,IAAA,OAAA,IAAA,IAAA,GAAA,MAAA,GAAA,OAAA,EAAA;AAAA,EACF,CAAA;AAEA,EAAA,IAAI,CAAC,SAAS,OAAO,IAAA;AAErB,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,uBACE,GAAA;AAAA,MAAC,MAAA,CAAO,GAAA;AAAA,MAAP;AAAA,QACC,OAAA,EAAS,EAAE,OAAA,EAAS,CAAA,EAAG,GAAG,EAAA,EAAG;AAAA,QAC7B,OAAA,EAAS,EAAE,OAAA,EAAS,CAAA,EAAG,GAAG,CAAA,EAAE;AAAA,QAC5B,KAAA,EAAO;AAAA,UACL,OAAA,EAAS,MAAA;AAAA,UACT,UAAA,EAAY,QAAA;AAAA,UACZ,cAAA,EAAgB,QAAA;AAAA,UAChB,OAAA,EAAS,EAAA;AAAA,UACT,YAAA,EAAc,EAAA;AAAA,UACd,UAAA,EAAY,mDAAA;AAAA,UACZ,KAAA,EAAO,SAAA;AAAA,UACP,QAAA,EAAU,EAAA;AAAA,UACV,UAAA,EAAY,GAAA;AAAA,UACZ,UAAA,EAAY;AAAA,SACd;AAAA,QACD,QAAA,EAAA;AAAA;AAAA,KAED;AAAA,EAEJ;AAEA,EAAA,IAAI,OAAA,IAAW,CAAC,UAAA,EAAY;AAC1B,IAAA,uBACE,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA,EAAK,YAAA;AAAA,QACL,KAAA,EAAO;AAAA,UACL,QAAA,EAAU,UAAA;AAAA,UACV,KAAA,EAAO,MAAA;AAAA,UACP,WAAA,EAAa,OAAA;AAAA,UACb,YAAA,EAAc,EAAA;AAAA,UACd,UAAA,EAAY,mDAAA;AAAA,UACZ,QAAA,EAAU;AAAA,SACZ;AAAA,QAEA,QAAA,kBAAA,GAAA;AAAA,UAAC,MAAA,CAAO,GAAA;AAAA,UAAP;AAAA,YACC,KAAA,EAAO;AAAA,cACL,QAAA,EAAU,UAAA;AAAA,cACV,KAAA,EAAO,CAAA;AAAA,cACP,UAAA,EAAY;AAAA,aACd;AAAA,YACA,SAAS,EAAE,CAAA,EAAG,CAAC,OAAA,EAAS,MAAM,CAAA,EAAE;AAAA,YAChC,YAAY,EAAE,QAAA,EAAU,KAAK,MAAA,EAAQ,QAAA,EAAU,MAAM,QAAA;AAAS;AAAA;AAChE;AAAA,KACF;AAAA,EAEJ;AAEA,EAAA,uBACE,IAAA;AAAA,IAAC,MAAA,CAAO,GAAA;AAAA,IAAP;AAAA,MACC,GAAA,EAAK,YAAA;AAAA,MACL,OAAA,EAAS,aAAA;AAAA,MACT,OAAA,EAAS,EAAE,OAAA,EAAS,CAAA,EAAG,OAAO,IAAA,EAAK;AAAA,MACnC,OAAA,EAAS,EAAE,OAAA,EAAS,CAAA,EAAG,OAAO,CAAA,EAAE;AAAA,MAChC,IAAA,EAAM,EAAE,OAAA,EAAS,CAAA,EAAG,OAAO,IAAA,EAAK;AAAA,MAChC,UAAA,EAAY,EAAE,KAAA,EAAO,IAAA,EAAK;AAAA,MAC1B,QAAA,EAAU,EAAE,KAAA,EAAO,IAAA,EAAK;AAAA,MACxB,YAAY,EAAE,IAAA,EAAM,UAAU,SAAA,EAAW,GAAA,EAAK,SAAS,EAAA,EAAG;AAAA,MAC1D,KAAA,EAAO;AAAA,QACL,QAAA,EAAU,UAAA;AAAA,QACV,KAAA,EAAO,MAAA;AAAA,QACP,WAAA,EAAa,OAAA;AAAA,QACb,YAAA,EAAc,EAAA;AAAA,QACd,QAAA,EAAU,QAAA;AAAA,QACV,MAAA,EAAQ,SAAA;AAAA,QACR,SAAA,EAAW;AAAA,OACb;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,mBACE,QAAA,EAAA,WAAA,oBACC,GAAA;AAAA,UAAC,MAAA,CAAO,GAAA;AAAA,UAAP;AAAA,YACC,KAAK,UAAA,CAAW,KAAA;AAAA,YAChB,GAAA,EAAI,eAAA;AAAA,YACJ,OAAA,EAAS,EAAE,OAAA,EAAS,CAAA,EAAE;AAAA,YACtB,OAAA,EAAS,EAAE,OAAA,EAAS,CAAA,EAAE;AAAA,YACtB,UAAA,EAAY,EAAE,QAAA,EAAU,GAAA,EAAI;AAAA,YAC5B,KAAA,EAAO;AAAA,cACL,QAAA,EAAU,UAAA;AAAA,cACV,KAAA,EAAO,CAAA;AAAA,cACP,KAAA,EAAO,MAAA;AAAA,cACP,MAAA,EAAQ,MAAA;AAAA,cACR,SAAA,EAAW;AAAA;AACb;AAAA,SACF,EAEJ,CAAA;AAAA,4BAEC,KAAA,EAAA,EAAI,GAAA,EAAK,UAAA,CAAW,KAAA,EAAO,KAAI,EAAA,EAAG,MAAA,EAAQ,MAAM,cAAA,CAAe,IAAI,CAAA,EAAG,KAAA,EAAO,EAAE,OAAA,EAAS,QAAO,EAAG,CAAA;AAAA,wBAEnG,GAAA;AAAA,UAAC,MAAA,CAAO,GAAA;AAAA,UAAP;AAAA,YACC,KAAA,EAAO;AAAA,cACL,QAAA,EAAU,UAAA;AAAA,cACV,KAAA,EAAO,CAAA;AAAA,cACP,UAAA,EAAY;AAAA,aACd;AAAA,YACA,UAAA,EAAY;AAAA,cACV,UAAA,EAAY;AAAA,aACd;AAAA,YACA,UAAA,EAAY,EAAE,QAAA,EAAU,GAAA;AAAI;AAAA,SAC9B;AAAA,wBAGA,GAAA;AAAA,UAAC,MAAA,CAAO,GAAA;AAAA,UAAP;AAAA,YACC,OAAA,EAAS,WAAA;AAAA,YACT,KAAA,EAAO;AAAA,cACL,QAAA,EAAU,UAAA;AAAA,cACV,GAAA,EAAK,EAAA;AAAA,cACL,KAAA,EAAO,EAAA;AAAA,cACP,OAAA,EAAS,MAAA;AAAA,cACT,UAAA,EAAY,QAAA;AAAA,cACZ,cAAA,EAAgB,QAAA;AAAA,cAChB,KAAA,EAAO,EAAA;AAAA,cACP,MAAA,EAAQ,EAAA;AAAA,cACR,YAAA,EAAc,KAAA;AAAA,cACd,UAAA,EAAY,iBAAA;AAAA,cACZ,cAAA,EAAgB,WAAA;AAAA,cAChB,KAAA,EAAO,uBAAA;AAAA,cACP,MAAA,EAAQ;AAAA,aACV;AAAA,YACA,UAAA,EAAY;AAAA,cACV,UAAA,EAAY,iBAAA;AAAA,cACZ,KAAA,EAAO,qBAAA;AAAA,cACP,KAAA,EAAO;AAAA,aACT;AAAA,YACA,QAAA,EAAU,EAAE,KAAA,EAAO,IAAA,EAAK;AAAA,YACxB,YAAY,EAAE,IAAA,EAAM,UAAU,SAAA,EAAW,GAAA,EAAK,SAAS,EAAA,EAAG;AAAA,YAE1D,QAAA,kBAAA,GAAA,CAAC,CAAA,EAAA,EAAE,IAAA,EAAM,EAAA,EAAI,aAAa,GAAA,EAAK;AAAA;AAAA,SACjC;AAAA,wBAEA,IAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,KAAA,EAAO;AAAA,cACL,QAAA,EAAU,UAAA;AAAA,cACV,MAAA,EAAQ,EAAA;AAAA,cACR,KAAA,EAAO,EAAA;AAAA,cACP,OAAA,EAAS,MAAA;AAAA,cACT,GAAA,EAAK;AAAA,aACP;AAAA,YAEA,QAAA,EAAA;AAAA,8BAAA,GAAA;AAAA,gBAAC,SAAA;AAAA,gBAAA;AAAA,kBACC,KAAA,EAAM,UAAA;AAAA,kBACN,sBAAM,GAAA,CAAC,WAAA,EAAA,EAAY,IAAA,EAAM,EAAA,EAAI,aAAa,GAAA,EAAK,CAAA;AAAA,kBAC/C,OAAA,EAAS,kBAAA;AAAA,kBACT,WAAW,CAAC;AAAA;AAAA,eACd;AAAA,8BACA,GAAA;AAAA,gBAAC,SAAA;AAAA,gBAAA;AAAA,kBACC,KAAA,EAAM,YAAA;AAAA,kBACN,sBAAM,GAAA,CAAC,YAAA,EAAA,EAAa,IAAA,EAAM,EAAA,EAAI,aAAa,GAAA,EAAK,CAAA;AAAA,kBAChD,OAAA,EAAS,CAAC,CAAA,KAAM;AACd,oBAAA,CAAA,CAAE,eAAA,EAAgB;AAClB,oBAAA,aAAA,EAAc;AAAA,kBAChB,CAAA;AAAA,kBACA,WAAW,CAAC;AAAA;AAAA;AACd;AAAA;AAAA,SACF;AAAA,wBAEA,IAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,KAAA,EAAO;AAAA,cACL,QAAA,EAAU,UAAA;AAAA,cACV,GAAA,EAAK,EAAA;AAAA,cACL,IAAA,EAAM,EAAA;AAAA,cACN,OAAA,EAAS,MAAA;AAAA,cACT,UAAA,EAAY,QAAA;AAAA,cACZ,GAAA,EAAK,CAAA;AAAA,cACL,OAAA,EAAS,SAAA;AAAA,cACT,YAAA,EAAc,CAAA;AAAA,cACd,UAAA,EAAY,iBAAA;AAAA,cACZ,cAAA,EAAgB,WAAA;AAAA,cAChB,KAAA,EAAO,uBAAA;AAAA,cACP,QAAA,EAAU,EAAA;AAAA,cACV,UAAA,EAAY,GAAA;AAAA,cACZ,UAAA,EAAY,sCAAA;AAAA,cACZ,aAAA,EAAe,OAAA;AAAA,cACf,aAAA,EAAe;AAAA,aACjB;AAAA,YAEA,QAAA,EAAA;AAAA,8BAAA,GAAA,CAAC,QAAA,EAAA,EAAS,MAAM,EAAA,EAAI,CAAA;AAAA,cAAE;AAAA;AAAA;AAAA;AAExB;AAAA;AAAA,GACF;AAEJ","file":"index.mjs","sourcesContent":["import * as React from \"react\"\nimport { motion, AnimatePresence } from \"framer-motion\"\nimport { ExternalLink, Sparkles, ShoppingBag, X } from \"lucide-react\"\n\nexport interface AdsterixWidgetProps {\n castHash?: string\n onClose?: () => void\n}\n\ninterface CtaDetails {\n image: string\n url: string\n buySlotUrl: string\n}\n\nconst CtaButton: React.FC<{\n label: string\n icon: React.ReactNode\n onClick: (e: React.MouseEvent) => void\n showLabel: boolean\n}> = ({ label, icon, onClick, showLabel }) => (\n <motion.div\n onClick={onClick}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: showLabel ? 6 : 0,\n padding: showLabel ? \"8px 14px\" : \"8px\",\n borderRadius: 20,\n background: \"rgba(255,255,255,0.9)\",\n backdropFilter: \"blur(8px)\",\n color: \"#0f172a\",\n fontSize: 13,\n fontWeight: 600,\n fontFamily: \"system-ui, -apple-system, sans-serif\",\n boxShadow: \"0 4px 12px rgba(0,0,0,0.15)\",\n cursor: \"pointer\",\n }}\n whileHover={{\n y: -2,\n background: \"rgba(255,255,255,0.98)\",\n boxShadow: \"0 8px 20px rgba(0,0,0,0.2)\",\n }}\n transition={{ type: \"spring\", stiffness: 400, damping: 15 }}\n >\n {showLabel && label}\n <motion.span\n style={{ display: \"flex\", alignItems: \"center\" }}\n whileHover={{ x: showLabel ? 2 : 0 }}\n transition={{ type: \"spring\", stiffness: 400, damping: 15 }}\n >\n {icon}\n </motion.span>\n </motion.div>\n)\n\nexport const AdsterixWidget: React.FC<AdsterixWidgetProps> = ({ castHash, onClose }) => {\n const [ctaDetails, setCtaDetails] = React.useState<CtaDetails | null>(null)\n const [error, setError] = React.useState<string | null>(null)\n const [loading, setLoading] = React.useState(false)\n const [imageLoaded, setImageLoaded] = React.useState(false)\n const [visible, setVisible] = React.useState(true)\n const [isSmall, setIsSmall] = React.useState(true) // Start with true to avoid flash\n const containerRef = React.useRef<HTMLDivElement>(null)\n\n React.useEffect(() => {\n if (!castHash) return\n\n const fetchCtaDetails = async () => {\n setLoading(true)\n setError(null)\n\n try {\n const response = await fetch(`https://www.adsterix.xyz/api/ads/cta-details/${castHash}`)\n\n if (!response.ok) {\n throw new Error(`Failed to fetch: ${response.status}`)\n }\n\n const data = await response.json()\n setCtaDetails(data)\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Unknown error\")\n } finally {\n setLoading(false)\n }\n }\n\n fetchCtaDetails()\n }, [castHash])\n\n React.useEffect(() => {\n if (!containerRef.current) return\n\n const checkSize = (entries: ResizeObserverEntry[]) => {\n for (const entry of entries) {\n const width = entry.contentRect.width\n setIsSmall(width < 270)\n }\n }\n\n const resizeObserver = new ResizeObserver(checkSize)\n resizeObserver.observe(containerRef.current)\n\n // Initial check\n if (containerRef.current) {\n const width = containerRef.current.offsetWidth\n setIsSmall(width < 400)\n }\n\n return () => resizeObserver.disconnect()\n }, [loading, ctaDetails]) // Re-run when content changes\n\n const handleAdClick = () => {\n if (ctaDetails?.url) {\n window.open(ctaDetails.url, \"_blank\", \"noopener,noreferrer\")\n }\n }\n\n const handleBuySlotClick = (e: React.MouseEvent) => {\n e.stopPropagation()\n if (ctaDetails?.buySlotUrl) window.open(ctaDetails.buySlotUrl, \"_blank\", \"noopener,noreferrer\")\n }\n\n const handleClose = (e: React.MouseEvent) => {\n e.stopPropagation()\n setVisible(false)\n onClose?.()\n }\n\n if (!visible) return null\n\n if (error) {\n return (\n <motion.div\n initial={{ opacity: 0, y: 10 }}\n animate={{ opacity: 1, y: 0 }}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: 16,\n borderRadius: 12,\n background: \"linear-gradient(135deg, #0f172a 0%, #1e293b 100%)\",\n color: \"#f87171\",\n fontSize: 14,\n fontWeight: 500,\n fontFamily: \"system-ui, -apple-system, sans-serif\",\n }}\n >\n Unable to load ad\n </motion.div>\n )\n }\n\n if (loading || !ctaDetails) {\n return (\n <div\n ref={containerRef}\n style={{\n position: \"relative\",\n width: \"100%\",\n aspectRatio: \"3 / 2\",\n borderRadius: 12,\n background: \"linear-gradient(135deg, #0f172a 0%, #1e293b 100%)\",\n overflow: \"hidden\",\n }}\n >\n <motion.div\n style={{\n position: \"absolute\",\n inset: 0,\n background: \"linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.05) 50%, transparent 100%)\",\n }}\n animate={{ x: [\"-100%\", \"100%\"] }}\n transition={{ duration: 1.5, repeat: Infinity, ease: \"linear\" }}\n />\n </div>\n )\n }\n\n return (\n <motion.div\n ref={containerRef}\n onClick={handleAdClick}\n initial={{ opacity: 0, scale: 0.95 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.95 }}\n whileHover={{ scale: 1.02 }}\n whileTap={{ scale: 0.98 }}\n transition={{ type: \"spring\", stiffness: 300, damping: 20 }}\n style={{\n position: \"relative\",\n width: \"100%\",\n aspectRatio: \"3 / 2\",\n borderRadius: 12,\n overflow: \"hidden\",\n cursor: \"pointer\",\n boxShadow: \"0 10px 30px rgba(0,0,0,0.2)\",\n }}\n >\n <AnimatePresence>\n {imageLoaded && (\n <motion.img\n src={ctaDetails.image}\n alt=\"Advertisement\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={{ duration: 0.4 }}\n style={{\n position: \"absolute\",\n inset: 0,\n width: \"100%\",\n height: \"100%\",\n objectFit: \"cover\",\n }}\n />\n )}\n </AnimatePresence>\n\n <img src={ctaDetails.image} alt=\"\" onLoad={() => setImageLoaded(true)} style={{ display: \"none\" }} />\n\n <motion.div\n style={{\n position: \"absolute\",\n inset: 0,\n background: \"linear-gradient(to top, rgba(0,0,0,0.3) 0%, transparent 50%)\",\n }}\n whileHover={{\n background: \"linear-gradient(to top, rgba(0,0,0,0.6) 0%, transparent 60%)\",\n }}\n transition={{ duration: 0.3 }}\n />\n\n {/* Close button */}\n <motion.div\n onClick={handleClose}\n style={{\n position: \"absolute\",\n top: 10,\n right: 10,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: 28,\n height: 28,\n borderRadius: \"50%\",\n background: \"rgba(0,0,0,0.5)\",\n backdropFilter: \"blur(8px)\",\n color: \"rgba(255,255,255,0.8)\",\n cursor: \"pointer\",\n }}\n whileHover={{\n background: \"rgba(0,0,0,0.7)\",\n color: \"rgba(255,255,255,1)\",\n scale: 1.1,\n }}\n whileTap={{ scale: 0.95 }}\n transition={{ type: \"spring\", stiffness: 400, damping: 15 }}\n >\n <X size={14} strokeWidth={2.5} />\n </motion.div>\n\n <div\n style={{\n position: \"absolute\",\n bottom: 12,\n right: 12,\n display: \"flex\",\n gap: 8,\n }}\n >\n <CtaButton\n label=\"Buy Slot\"\n icon={<ShoppingBag size={14} strokeWidth={2.5} />}\n onClick={handleBuySlotClick}\n showLabel={!isSmall}\n />\n <CtaButton\n label=\"Learn More\"\n icon={<ExternalLink size={14} strokeWidth={2.5} />}\n onClick={(e) => {\n e.stopPropagation()\n handleAdClick()\n }}\n showLabel={!isSmall}\n />\n </div>\n\n <div\n style={{\n position: \"absolute\",\n top: 10,\n left: 10,\n display: \"flex\",\n alignItems: \"center\",\n gap: 4,\n padding: \"4px 8px\",\n borderRadius: 6,\n background: \"rgba(0,0,0,0.5)\",\n backdropFilter: \"blur(8px)\",\n color: \"rgba(255,255,255,0.8)\",\n fontSize: 10,\n fontWeight: 500,\n fontFamily: \"system-ui, -apple-system, sans-serif\",\n letterSpacing: \"0.5px\",\n textTransform: \"uppercase\",\n }}\n >\n <Sparkles size={10} />\n Ad\n </div>\n </motion.div>\n )\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nektarlabs/adsterix-widget",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",