@nektarlabs/adsterix-widget 1.0.2 → 1.3.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/README.md +24 -4
- package/dist/index.d.mts +15 -0
- package/dist/index.mjs +111 -126
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -53,10 +53,30 @@ To display an ad, you need a cast hash of the corresponding Farcaster cast. Foll
|
|
|
53
53
|
|
|
54
54
|
## Props
|
|
55
55
|
|
|
56
|
-
| Prop
|
|
57
|
-
|
|
|
58
|
-
| `castHash`
|
|
59
|
-
| `onClose`
|
|
56
|
+
| Prop | Type | Default | Description |
|
|
57
|
+
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ---------------- | -------------------------------------------------------------------------------- |
|
|
58
|
+
| `castHash` | `string` | — | The Farcaster cast hash of the ad to display |
|
|
59
|
+
| `onClose` | `() => void` | — | Callback fired when the user closes the ad |
|
|
60
|
+
| `width` | `string \| number` | `"100%"` | Width of the widget (px or string) |
|
|
61
|
+
| `height` | `string \| number` | — | Height of the widget (px or string). If not provided, maintains 3:2 aspect ratio |
|
|
62
|
+
| `showAdSparkleLabel` | `boolean` | — | Whether to show the "Ad ✨" label overlay |
|
|
63
|
+
| `showCloseButton` | `boolean` | — | Whether to show the close button |
|
|
64
|
+
| `showBuySlotButton` | `boolean` | — | Whether to show the "Buy Slot" button |
|
|
65
|
+
| `showCtaButton` | `boolean` | — | Whether to show the CTA (call-to-action) button |
|
|
66
|
+
| `showCtaButtonIcon` | `boolean` | — | Whether to show the external link icon on the CTA button |
|
|
67
|
+
| `ctaButtonText` | `string` | — | Custom text for the CTA button |
|
|
68
|
+
| `onBuySlotClick` | `(buySlotUrl: string) => void` | — | Callback fired when the "Buy Slot" button is clicked, receives the buy slot URL |
|
|
69
|
+
| `onAdClick` | `(url: string) => void` | — | Callback fired when the CTA button is clicked, receives the ad's target URL |
|
|
70
|
+
| `position` | `"bottom-left" \| "bottom-right" \| "top-left" \| "top-right" \| "bottom-center" \| "top-center" \| "center-left" \| "center-right"` | `"bottom-right"` | Position of the CTA buttons container |
|
|
71
|
+
| `containerStyle` | `React.CSSProperties` | — | Custom styles for the CTA buttons container |
|
|
72
|
+
| `buySlotButtonStyle` | `React.CSSProperties` | — | Custom styles for the "Buy Slot" button |
|
|
73
|
+
| `ctaButtonStyle` | `React.CSSProperties` | — | Custom styles for the CTA button |
|
|
74
|
+
|
|
75
|
+
## Example
|
|
76
|
+
|
|
77
|
+
<p align="center">
|
|
78
|
+
<img src="./resources/miniapp.png" alt="Miniapp" width="300"/>
|
|
79
|
+
</p>
|
|
60
80
|
|
|
61
81
|
## License
|
|
62
82
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,8 +1,23 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
|
|
3
|
+
type CtaPosition = "bottom-left" | "bottom-right" | "top-left" | "top-right" | "bottom-center" | "top-center" | "center-left" | "center-right";
|
|
3
4
|
interface AdsterixWidgetProps {
|
|
4
5
|
castHash?: string;
|
|
5
6
|
onClose?: () => void;
|
|
7
|
+
width?: string | number;
|
|
8
|
+
height?: string | number;
|
|
9
|
+
showAdSparkleLabel?: boolean;
|
|
10
|
+
showCloseButton?: boolean;
|
|
11
|
+
showBuySlotButton?: boolean;
|
|
12
|
+
showCtaButton?: boolean;
|
|
13
|
+
showCtaButtonIcon?: boolean;
|
|
14
|
+
ctaButtonText?: string;
|
|
15
|
+
onBuySlotClick?: (buySlotUrl: string) => void;
|
|
16
|
+
onAdClick?: (url: string) => void;
|
|
17
|
+
position?: CtaPosition;
|
|
18
|
+
containerStyle?: React.CSSProperties;
|
|
19
|
+
buySlotButtonStyle?: React.CSSProperties;
|
|
20
|
+
ctaButtonStyle?: React.CSSProperties;
|
|
6
21
|
}
|
|
7
22
|
declare const AdsterixWidget: React.FC<AdsterixWidgetProps>;
|
|
8
23
|
|
package/dist/index.mjs
CHANGED
|
@@ -1,49 +1,67 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { AnimatePresence, motion } from 'framer-motion';
|
|
3
3
|
import { X, ShoppingBag, ExternalLink, Sparkles } from 'lucide-react';
|
|
4
4
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
5
5
|
|
|
6
6
|
// src/AdsterixWidget.tsx
|
|
7
|
-
var
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
);
|
|
46
|
-
|
|
7
|
+
var getPositionStyles = (position) => {
|
|
8
|
+
const baseStyles = {
|
|
9
|
+
position: "absolute",
|
|
10
|
+
display: "flex",
|
|
11
|
+
gap: 8
|
|
12
|
+
};
|
|
13
|
+
const positionMap = {
|
|
14
|
+
"bottom-right": { bottom: 12, right: 12 },
|
|
15
|
+
"bottom-left": { bottom: 12, left: 12 },
|
|
16
|
+
"top-right": { top: 12, right: 12 },
|
|
17
|
+
"top-left": { top: 12, left: 12 },
|
|
18
|
+
"bottom-center": { bottom: 12, left: "50%", transform: "translateX(-50%)" },
|
|
19
|
+
"top-center": { top: 12, left: "50%", transform: "translateX(-50%)" },
|
|
20
|
+
"center-left": { top: "50%", left: 12, transform: "translateY(-50%)" },
|
|
21
|
+
"center-right": { top: "50%", right: 12, transform: "translateY(-50%)" }
|
|
22
|
+
};
|
|
23
|
+
return { ...baseStyles, ...positionMap[position] };
|
|
24
|
+
};
|
|
25
|
+
var CtaButton = ({ label, icon, onClick, showLabel, style = {} }) => {
|
|
26
|
+
const defaultStyle = {
|
|
27
|
+
display: "flex",
|
|
28
|
+
alignItems: "center",
|
|
29
|
+
gap: showLabel ? 6 : 0,
|
|
30
|
+
padding: showLabel ? "8px 14px" : "8px",
|
|
31
|
+
borderRadius: 20,
|
|
32
|
+
background: "rgba(255,255,255,0.9)",
|
|
33
|
+
backdropFilter: "blur(8px)",
|
|
34
|
+
color: "#0f172a",
|
|
35
|
+
fontSize: 13,
|
|
36
|
+
fontWeight: 600,
|
|
37
|
+
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
38
|
+
boxShadow: "0 4px 12px rgba(0,0,0,0.15)",
|
|
39
|
+
cursor: "pointer"
|
|
40
|
+
};
|
|
41
|
+
const mergedStyle = { ...defaultStyle, ...style };
|
|
42
|
+
return /* @__PURE__ */ jsxs("div", { onClick, style: mergedStyle, children: [
|
|
43
|
+
showLabel && label,
|
|
44
|
+
/* @__PURE__ */ jsx("span", { style: { display: "flex", alignItems: "center" }, children: icon })
|
|
45
|
+
] });
|
|
46
|
+
};
|
|
47
|
+
var AdsterixWidget = ({
|
|
48
|
+
castHash,
|
|
49
|
+
onClose,
|
|
50
|
+
width = "100%",
|
|
51
|
+
position = "bottom-right",
|
|
52
|
+
height,
|
|
53
|
+
showAdSparkleLabel = false,
|
|
54
|
+
showCloseButton = false,
|
|
55
|
+
showBuySlotButton = false,
|
|
56
|
+
showCtaButton = false,
|
|
57
|
+
showCtaButtonIcon = false,
|
|
58
|
+
ctaButtonText = "Learn More",
|
|
59
|
+
ctaButtonStyle,
|
|
60
|
+
buySlotButtonStyle,
|
|
61
|
+
onBuySlotClick,
|
|
62
|
+
onAdClick,
|
|
63
|
+
containerStyle: _containerStyle
|
|
64
|
+
}) => {
|
|
47
65
|
const [ctaDetails, setCtaDetails] = React.useState(null);
|
|
48
66
|
const [error, setError] = React.useState(null);
|
|
49
67
|
const [loading, setLoading] = React.useState(false);
|
|
@@ -75,45 +93,55 @@ var AdsterixWidget = ({ castHash, onClose }) => {
|
|
|
75
93
|
if (!containerRef.current) return;
|
|
76
94
|
const checkSize = (entries) => {
|
|
77
95
|
for (const entry of entries) {
|
|
78
|
-
const
|
|
79
|
-
setIsSmall(
|
|
96
|
+
const width2 = entry.contentRect.width;
|
|
97
|
+
setIsSmall(width2 < 270);
|
|
80
98
|
}
|
|
81
99
|
};
|
|
82
100
|
const resizeObserver = new ResizeObserver(checkSize);
|
|
83
101
|
resizeObserver.observe(containerRef.current);
|
|
84
102
|
if (containerRef.current) {
|
|
85
|
-
const
|
|
86
|
-
setIsSmall(
|
|
103
|
+
const width2 = containerRef.current.offsetWidth;
|
|
104
|
+
setIsSmall(width2 < 400);
|
|
87
105
|
}
|
|
88
106
|
return () => resizeObserver.disconnect();
|
|
89
107
|
}, [loading, ctaDetails]);
|
|
90
108
|
const handleAdClick = () => {
|
|
91
109
|
if (ctaDetails == null ? void 0 : ctaDetails.url) {
|
|
92
110
|
window.open(ctaDetails.url, "_blank", "noopener,noreferrer");
|
|
111
|
+
onAdClick == null ? void 0 : onAdClick(ctaDetails.url);
|
|
93
112
|
}
|
|
94
113
|
};
|
|
95
114
|
const handleBuySlotClick = (e) => {
|
|
96
115
|
e.stopPropagation();
|
|
97
|
-
if (ctaDetails == null ? void 0 : ctaDetails.buySlotUrl)
|
|
116
|
+
if (ctaDetails == null ? void 0 : ctaDetails.buySlotUrl) {
|
|
117
|
+
window.open(ctaDetails.buySlotUrl, "_blank", "noopener,noreferrer");
|
|
118
|
+
onBuySlotClick == null ? void 0 : onBuySlotClick(ctaDetails == null ? void 0 : ctaDetails.buySlotUrl);
|
|
119
|
+
}
|
|
98
120
|
};
|
|
99
121
|
const handleClose = (e) => {
|
|
100
122
|
e.stopPropagation();
|
|
101
123
|
setVisible(false);
|
|
102
124
|
onClose == null ? void 0 : onClose();
|
|
103
125
|
};
|
|
126
|
+
const containerStyle = {
|
|
127
|
+
position: "relative",
|
|
128
|
+
width: typeof width === "number" ? `${width}px` : width,
|
|
129
|
+
...height ? { height: typeof height === "number" ? `${height}px` : height } : { aspectRatio: "3 / 2" },
|
|
130
|
+
borderRadius: 12,
|
|
131
|
+
overflow: "hidden",
|
|
132
|
+
..._containerStyle
|
|
133
|
+
};
|
|
104
134
|
if (!visible) return null;
|
|
105
135
|
if (error) {
|
|
106
136
|
return /* @__PURE__ */ jsx(
|
|
107
|
-
|
|
137
|
+
"div",
|
|
108
138
|
{
|
|
109
|
-
initial: { opacity: 0, y: 10 },
|
|
110
|
-
animate: { opacity: 1, y: 0 },
|
|
111
139
|
style: {
|
|
140
|
+
...containerStyle,
|
|
112
141
|
display: "flex",
|
|
113
142
|
alignItems: "center",
|
|
114
143
|
justifyContent: "center",
|
|
115
144
|
padding: 16,
|
|
116
|
-
borderRadius: 12,
|
|
117
145
|
background: "linear-gradient(135deg, #0f172a 0%, #1e293b 100%)",
|
|
118
146
|
color: "#f87171",
|
|
119
147
|
fontSize: 14,
|
|
@@ -130,46 +158,27 @@ var AdsterixWidget = ({ castHash, onClose }) => {
|
|
|
130
158
|
{
|
|
131
159
|
ref: containerRef,
|
|
132
160
|
style: {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
aspectRatio: "3 / 2",
|
|
136
|
-
borderRadius: 12,
|
|
137
|
-
background: "linear-gradient(135deg, #0f172a 0%, #1e293b 100%)",
|
|
138
|
-
overflow: "hidden"
|
|
161
|
+
...containerStyle,
|
|
162
|
+
background: "linear-gradient(135deg, #0f172a 0%, #1e293b 100%)"
|
|
139
163
|
},
|
|
140
164
|
children: /* @__PURE__ */ jsx(
|
|
141
|
-
|
|
165
|
+
"div",
|
|
142
166
|
{
|
|
143
167
|
style: {
|
|
144
168
|
position: "absolute",
|
|
145
169
|
inset: 0,
|
|
146
170
|
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" }
|
|
171
|
+
}
|
|
150
172
|
}
|
|
151
173
|
)
|
|
152
174
|
}
|
|
153
175
|
);
|
|
154
176
|
}
|
|
155
177
|
return /* @__PURE__ */ jsxs(
|
|
156
|
-
|
|
178
|
+
"div",
|
|
157
179
|
{
|
|
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
180
|
style: {
|
|
167
|
-
|
|
168
|
-
width: "100%",
|
|
169
|
-
aspectRatio: "3 / 2",
|
|
170
|
-
borderRadius: 12,
|
|
171
|
-
overflow: "hidden",
|
|
172
|
-
cursor: "pointer",
|
|
181
|
+
...containerStyle,
|
|
173
182
|
boxShadow: "0 10px 30px rgba(0,0,0,0.2)"
|
|
174
183
|
},
|
|
175
184
|
children: [
|
|
@@ -191,21 +200,7 @@ var AdsterixWidget = ({ castHash, onClose }) => {
|
|
|
191
200
|
}
|
|
192
201
|
) }),
|
|
193
202
|
/* @__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(
|
|
203
|
+
showCloseButton && /* @__PURE__ */ jsx(
|
|
209
204
|
motion.div,
|
|
210
205
|
{
|
|
211
206
|
onClick: handleClose,
|
|
@@ -234,42 +229,32 @@ var AdsterixWidget = ({ castHash, onClose }) => {
|
|
|
234
229
|
children: /* @__PURE__ */ jsx(X, { size: 14, strokeWidth: 2.5 })
|
|
235
230
|
}
|
|
236
231
|
),
|
|
237
|
-
/* @__PURE__ */ jsxs(
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
e.stopPropagation();
|
|
264
|
-
handleAdClick();
|
|
265
|
-
},
|
|
266
|
-
showLabel: !isSmall
|
|
267
|
-
}
|
|
268
|
-
)
|
|
269
|
-
]
|
|
270
|
-
}
|
|
271
|
-
),
|
|
272
|
-
/* @__PURE__ */ jsxs(
|
|
232
|
+
/* @__PURE__ */ jsxs("div", { style: getPositionStyles(position), children: [
|
|
233
|
+
showBuySlotButton && /* @__PURE__ */ jsx(
|
|
234
|
+
CtaButton,
|
|
235
|
+
{
|
|
236
|
+
label: "Buy Slot",
|
|
237
|
+
icon: /* @__PURE__ */ jsx(ShoppingBag, { size: 14, strokeWidth: 2.5 }),
|
|
238
|
+
onClick: handleBuySlotClick,
|
|
239
|
+
showLabel: !isSmall,
|
|
240
|
+
style: buySlotButtonStyle
|
|
241
|
+
}
|
|
242
|
+
),
|
|
243
|
+
showCtaButton && /* @__PURE__ */ jsx(
|
|
244
|
+
CtaButton,
|
|
245
|
+
{
|
|
246
|
+
label: ctaButtonText,
|
|
247
|
+
icon: showCtaButtonIcon && /* @__PURE__ */ jsx(ExternalLink, { size: 14, strokeWidth: 2.5 }),
|
|
248
|
+
onClick: (e) => {
|
|
249
|
+
e.stopPropagation();
|
|
250
|
+
handleAdClick();
|
|
251
|
+
},
|
|
252
|
+
showLabel: !isSmall,
|
|
253
|
+
style: ctaButtonStyle
|
|
254
|
+
}
|
|
255
|
+
)
|
|
256
|
+
] }),
|
|
257
|
+
showAdSparkleLabel && /* @__PURE__ */ jsxs(
|
|
273
258
|
"div",
|
|
274
259
|
{
|
|
275
260
|
style: {
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/AdsterixWidget.tsx"],"names":[],"mappings":"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","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"]}
|
|
1
|
+
{"version":3,"sources":["../src/AdsterixWidget.tsx"],"names":["width"],"mappings":"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","file":"index.mjs","sourcesContent":["import * as React from \"react\"\nimport { motion, AnimatePresence } from \"framer-motion\"\nimport { ExternalLink, Sparkles, ShoppingBag, X } from \"lucide-react\"\n\ntype CtaPosition =\n | \"bottom-left\"\n | \"bottom-right\"\n | \"top-left\"\n | \"top-right\"\n | \"bottom-center\"\n | \"top-center\"\n | \"center-left\"\n | \"center-right\"\n\nexport interface AdsterixWidgetProps {\n castHash?: string\n onClose?: () => void\n width?: string | number\n height?: string | number\n showAdSparkleLabel?: boolean\n showCloseButton?: boolean\n showBuySlotButton?: boolean\n showCtaButton?: boolean\n showCtaButtonIcon?: boolean\n ctaButtonText?: string\n onBuySlotClick?: (buySlotUrl: string) => void\n onAdClick?: (url: string) => void\n position?: CtaPosition\n containerStyle?: React.CSSProperties\n buySlotButtonStyle?: React.CSSProperties\n ctaButtonStyle?: React.CSSProperties\n}\n\ninterface CtaButtonProps {\n label: string\n icon: React.ReactNode\n onClick: (e: React.MouseEvent) => void\n showLabel: boolean\n style?: React.CSSProperties\n}\n\ninterface CtaDetails {\n image: string\n url: string\n buySlotUrl: string\n}\n\nconst getPositionStyles = (position: CtaPosition): React.CSSProperties => {\n const baseStyles: React.CSSProperties = {\n position: \"absolute\",\n display: \"flex\",\n gap: 8,\n }\n\n const positionMap: Record<CtaPosition, React.CSSProperties> = {\n \"bottom-right\": { bottom: 12, right: 12 },\n \"bottom-left\": { bottom: 12, left: 12 },\n \"top-right\": { top: 12, right: 12 },\n \"top-left\": { top: 12, left: 12 },\n \"bottom-center\": { bottom: 12, left: \"50%\", transform: \"translateX(-50%)\" },\n \"top-center\": { top: 12, left: \"50%\", transform: \"translateX(-50%)\" },\n \"center-left\": { top: \"50%\", left: 12, transform: \"translateY(-50%)\" },\n \"center-right\": { top: \"50%\", right: 12, transform: \"translateY(-50%)\" },\n }\n\n return { ...baseStyles, ...positionMap[position] }\n}\n\nconst CtaButton: React.FC<CtaButtonProps> = ({ label, icon, onClick, showLabel, style = {} }) => {\n const defaultStyle: React.CSSProperties = {\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\n const mergedStyle = { ...defaultStyle, ...style }\n\n return (\n <div onClick={onClick} style={mergedStyle}>\n {showLabel && label}\n <span style={{ display: \"flex\", alignItems: \"center\" }}>{icon}</span>\n </div>\n )\n}\n\nexport const AdsterixWidget: React.FC<AdsterixWidgetProps> = ({\n castHash,\n onClose,\n width = \"100%\",\n position = \"bottom-right\",\n height,\n showAdSparkleLabel = false,\n showCloseButton = false,\n showBuySlotButton = false,\n showCtaButton = false,\n showCtaButtonIcon = false,\n ctaButtonText = \"Learn More\",\n ctaButtonStyle,\n buySlotButtonStyle,\n onBuySlotClick,\n onAdClick,\n containerStyle: _containerStyle,\n}) => {\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 onAdClick?.(ctaDetails.url)\n }\n }\n\n const handleBuySlotClick = (e: React.MouseEvent) => {\n e.stopPropagation()\n if (ctaDetails?.buySlotUrl) {\n window.open(ctaDetails.buySlotUrl, \"_blank\", \"noopener,noreferrer\")\n onBuySlotClick?.(ctaDetails?.buySlotUrl)\n }\n }\n\n const handleClose = (e: React.MouseEvent) => {\n e.stopPropagation()\n setVisible(false)\n onClose?.()\n }\n\n const containerStyle: React.CSSProperties = {\n position: \"relative\",\n width: typeof width === \"number\" ? `${width}px` : width,\n ...(height ? { height: typeof height === \"number\" ? `${height}px` : height } : { aspectRatio: \"3 / 2\" }),\n borderRadius: 12,\n overflow: \"hidden\",\n ..._containerStyle,\n }\n\n if (!visible) return null\n\n if (error) {\n return (\n <div\n style={{\n ...containerStyle,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: 16,\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 </div>\n )\n }\n\n if (loading || !ctaDetails) {\n return (\n <div\n ref={containerRef}\n style={{\n ...containerStyle,\n background: \"linear-gradient(135deg, #0f172a 0%, #1e293b 100%)\",\n }}\n >\n <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 />\n </div>\n )\n }\n\n return (\n <div\n style={{\n ...containerStyle,\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 {/* Close button */}\n {showCloseButton && (\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\n <div style={getPositionStyles(position)}>\n {showBuySlotButton && (\n <CtaButton\n label=\"Buy Slot\"\n icon={<ShoppingBag size={14} strokeWidth={2.5} />}\n onClick={handleBuySlotClick}\n showLabel={!isSmall}\n style={buySlotButtonStyle}\n />\n )}\n {showCtaButton && (\n <CtaButton\n label={ctaButtonText}\n icon={showCtaButtonIcon && <ExternalLink size={14} strokeWidth={2.5} />}\n onClick={(e) => {\n e.stopPropagation()\n handleAdClick()\n }}\n showLabel={!isSmall}\n style={ctaButtonStyle}\n />\n )}\n </div>\n\n {showAdSparkleLabel && (\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 )}\n </div>\n )\n}\n"]}
|