@adland/react 0.14.0 → 0.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +489 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +68 -0
- package/dist/index.d.ts +68 -0
- package/dist/index.js +442 -0
- package/dist/index.js.map +1 -0
- package/dist/types.cjs +35 -0
- package/dist/types.cjs.map +1 -0
- package/dist/types.d.cts +38 -0
- package/dist/types.d.ts +38 -0
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -0
- package/package.json +6 -3
- package/.eslintrc.js +0 -34
- package/CHANGELOG.md +0 -180
- package/src/components/Ad.tsx +0 -195
- package/src/fetch.ts +0 -79
- package/src/hooks/useAdContext.ts +0 -21
- package/src/hooks/useFetch.ts +0 -133
- package/src/index.ts +0 -35
- package/src/types.ts +0 -37
- package/src/utils/ad-actions.ts +0 -59
- package/src/utils/ad-fields.ts +0 -45
- package/src/utils/constants.ts +0 -36
- package/src/utils/fetchCache.ts +0 -51
- package/tsconfig.json +0 -28
- package/tsup.config.ts +0 -14
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var src_exports = {};
|
|
32
|
+
__export(src_exports, {
|
|
33
|
+
Ad: () => Ad,
|
|
34
|
+
AdBadge: () => AdBadge,
|
|
35
|
+
AdDescription: () => AdDescription,
|
|
36
|
+
AdEmpty: () => AdEmpty,
|
|
37
|
+
AdError: () => AdError,
|
|
38
|
+
AdImage: () => AdImage,
|
|
39
|
+
AdLabel: () => AdLabel,
|
|
40
|
+
AdLoaded: () => AdLoaded,
|
|
41
|
+
AdLoading: () => AdLoading,
|
|
42
|
+
AdTitle: () => AdTitle,
|
|
43
|
+
adCardIcon: () => adCardIcon,
|
|
44
|
+
adCardLabel: () => adCardLabel,
|
|
45
|
+
getAdDescription: () => getAdDescription,
|
|
46
|
+
getAdImage: () => getAdImage,
|
|
47
|
+
getAdTitle: () => getAdTitle,
|
|
48
|
+
getAdType: () => getAdType,
|
|
49
|
+
useAd: () => useAd
|
|
50
|
+
});
|
|
51
|
+
module.exports = __toCommonJS(src_exports);
|
|
52
|
+
|
|
53
|
+
// src/components/Ad.tsx
|
|
54
|
+
var import_sdk2 = require("@0xslots/sdk");
|
|
55
|
+
var import_react3 = require("react");
|
|
56
|
+
|
|
57
|
+
// src/fetch.ts
|
|
58
|
+
var import_sdk = require("@0xslots/sdk");
|
|
59
|
+
var import_viem = require("viem");
|
|
60
|
+
var import_chains = require("viem/chains");
|
|
61
|
+
var IPFS_GATEWAY = "https://amethyst-representative-mandrill-369.mypinata.cloud/ipfs/";
|
|
62
|
+
var viemChains = {
|
|
63
|
+
8453: import_chains.base,
|
|
64
|
+
84532: import_chains.baseSepolia
|
|
65
|
+
};
|
|
66
|
+
function createReadClient(chainId, rpcUrl) {
|
|
67
|
+
const chain = viemChains[chainId];
|
|
68
|
+
if (!chain) throw new Error(`Unsupported chain: ${chainId}`);
|
|
69
|
+
const publicClient = (0, import_viem.createPublicClient)({
|
|
70
|
+
chain,
|
|
71
|
+
transport: (0, import_viem.http)(rpcUrl)
|
|
72
|
+
});
|
|
73
|
+
return new import_sdk.SlotsClient({ chainId, publicClient });
|
|
74
|
+
}
|
|
75
|
+
var fetchAdFromURI = async (uri) => {
|
|
76
|
+
if (!uri) throw new Error("NO_AD" /* NO_AD */);
|
|
77
|
+
const url = uri.startsWith("ipfs://") ? `${IPFS_GATEWAY}${uri.slice(7)}` : uri;
|
|
78
|
+
const res = await fetch(url, {
|
|
79
|
+
method: "GET",
|
|
80
|
+
headers: { Accept: "application/json" }
|
|
81
|
+
});
|
|
82
|
+
if (!res.ok) {
|
|
83
|
+
if (res.status === 404) throw new Error("NO_AD" /* NO_AD */);
|
|
84
|
+
throw new Error("ERROR" /* ERROR */);
|
|
85
|
+
}
|
|
86
|
+
const data = await res.json();
|
|
87
|
+
if (data.error) throw new Error(data.error);
|
|
88
|
+
return data;
|
|
89
|
+
};
|
|
90
|
+
var fetchMetadataURI = async (client, slotAddress) => {
|
|
91
|
+
const info = await client.getSlotInfo(slotAddress);
|
|
92
|
+
const moduleAddress = info.module;
|
|
93
|
+
if (!moduleAddress || moduleAddress === "0x0000000000000000000000000000000000000000") {
|
|
94
|
+
return "";
|
|
95
|
+
}
|
|
96
|
+
return client.modules.metadata.getURI(
|
|
97
|
+
moduleAddress,
|
|
98
|
+
slotAddress
|
|
99
|
+
);
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// src/hooks/useAdContext.ts
|
|
103
|
+
var import_react = require("react");
|
|
104
|
+
var AdContext = (0, import_react.createContext)(null);
|
|
105
|
+
function useAd() {
|
|
106
|
+
const ctx = (0, import_react.useContext)(AdContext);
|
|
107
|
+
if (!ctx) throw new Error("useAd must be used within an <Ad> component");
|
|
108
|
+
return ctx;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// src/hooks/useFetch.ts
|
|
112
|
+
var import_react2 = require("react");
|
|
113
|
+
|
|
114
|
+
// src/utils/fetchCache.ts
|
|
115
|
+
var FetchCache = class {
|
|
116
|
+
cache = /* @__PURE__ */ new Map();
|
|
117
|
+
activeFetches = /* @__PURE__ */ new Map();
|
|
118
|
+
get(key, ttl) {
|
|
119
|
+
const cached = this.cache.get(key);
|
|
120
|
+
if (!cached) return null;
|
|
121
|
+
if (ttl && Date.now() - cached.ts > ttl) {
|
|
122
|
+
this.cache.delete(key);
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
return cached.data;
|
|
126
|
+
}
|
|
127
|
+
has(key, ttl) {
|
|
128
|
+
const cached = this.cache.get(key);
|
|
129
|
+
if (!cached) return false;
|
|
130
|
+
if (ttl && Date.now() - cached.ts > ttl) {
|
|
131
|
+
this.cache.delete(key);
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
set(key, data) {
|
|
137
|
+
this.cache.set(key, { data, ts: Date.now() });
|
|
138
|
+
}
|
|
139
|
+
getActiveFetch(key) {
|
|
140
|
+
return this.activeFetches.get(key);
|
|
141
|
+
}
|
|
142
|
+
setActiveFetch(key, promise) {
|
|
143
|
+
this.activeFetches.set(key, promise);
|
|
144
|
+
promise.finally(() => {
|
|
145
|
+
this.activeFetches.delete(key);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
clear() {
|
|
149
|
+
this.cache.clear();
|
|
150
|
+
this.activeFetches.clear();
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
var fetchCache_default = FetchCache;
|
|
154
|
+
|
|
155
|
+
// src/hooks/useFetch.ts
|
|
156
|
+
var globalCache = new fetchCache_default();
|
|
157
|
+
function useFetch(key, fetcher, opts) {
|
|
158
|
+
const { enabled = true, ttl = 0 } = opts ?? {};
|
|
159
|
+
const getCachedData = () => {
|
|
160
|
+
return globalCache.get(key, ttl || void 0);
|
|
161
|
+
};
|
|
162
|
+
const hasCachedData = () => {
|
|
163
|
+
return globalCache.has(key, ttl || void 0);
|
|
164
|
+
};
|
|
165
|
+
const getActiveFetch = () => {
|
|
166
|
+
return globalCache.getActiveFetch(key);
|
|
167
|
+
};
|
|
168
|
+
const cachedData = getCachedData();
|
|
169
|
+
const [data, setData] = (0, import_react2.useState)(cachedData);
|
|
170
|
+
const [error, setError] = (0, import_react2.useState)(null);
|
|
171
|
+
const [status, setStatus] = (0, import_react2.useState)(cachedData ? "success" : "idle");
|
|
172
|
+
const refetch = async () => {
|
|
173
|
+
const cached = getCachedData();
|
|
174
|
+
if (cached) {
|
|
175
|
+
setData(cached);
|
|
176
|
+
setStatus("success");
|
|
177
|
+
return cached;
|
|
178
|
+
}
|
|
179
|
+
const activeFetch = getActiveFetch();
|
|
180
|
+
if (activeFetch) {
|
|
181
|
+
try {
|
|
182
|
+
const res = await activeFetch;
|
|
183
|
+
setData(res);
|
|
184
|
+
setStatus("success");
|
|
185
|
+
return res;
|
|
186
|
+
} catch (e) {
|
|
187
|
+
setError(e);
|
|
188
|
+
setStatus("error");
|
|
189
|
+
throw e;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
setStatus("loading");
|
|
193
|
+
setError(null);
|
|
194
|
+
try {
|
|
195
|
+
const fetchPromise = fetcher();
|
|
196
|
+
globalCache.setActiveFetch(key, fetchPromise);
|
|
197
|
+
const res = await fetchPromise;
|
|
198
|
+
globalCache.set(key, res);
|
|
199
|
+
setData(res);
|
|
200
|
+
setStatus("success");
|
|
201
|
+
return res;
|
|
202
|
+
} catch (e) {
|
|
203
|
+
setError(e);
|
|
204
|
+
setStatus("error");
|
|
205
|
+
throw e;
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
(0, import_react2.useEffect)(() => {
|
|
209
|
+
if (!enabled) return;
|
|
210
|
+
const cached = getCachedData();
|
|
211
|
+
if (cached) {
|
|
212
|
+
setData(cached);
|
|
213
|
+
setStatus("success");
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
const activeFetch = getActiveFetch();
|
|
217
|
+
if (activeFetch) {
|
|
218
|
+
setStatus("loading");
|
|
219
|
+
activeFetch.then((res) => {
|
|
220
|
+
setData(res);
|
|
221
|
+
setStatus("success");
|
|
222
|
+
}).catch((e) => {
|
|
223
|
+
setError(e);
|
|
224
|
+
setStatus("error");
|
|
225
|
+
});
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
if (status !== "loading" && status !== "success") {
|
|
229
|
+
refetch();
|
|
230
|
+
}
|
|
231
|
+
}, [key, enabled]);
|
|
232
|
+
const hasValidCache = hasCachedData();
|
|
233
|
+
const isLoading = status === "loading" && !hasValidCache;
|
|
234
|
+
return {
|
|
235
|
+
data,
|
|
236
|
+
error,
|
|
237
|
+
status,
|
|
238
|
+
isIdle: status === "idle",
|
|
239
|
+
isLoading,
|
|
240
|
+
isSuccess: status === "success",
|
|
241
|
+
isError: status === "error",
|
|
242
|
+
refetch
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// src/utils/ad-actions.ts
|
|
247
|
+
var import_miniapp_sdk = __toESM(require("@farcaster/miniapp-sdk"), 1);
|
|
248
|
+
var _isMiniApp = null;
|
|
249
|
+
var _miniAppPromise = import_miniapp_sdk.default.isInMiniApp().then((v) => {
|
|
250
|
+
_isMiniApp = v;
|
|
251
|
+
return v;
|
|
252
|
+
}).catch(() => {
|
|
253
|
+
_isMiniApp = false;
|
|
254
|
+
return false;
|
|
255
|
+
});
|
|
256
|
+
async function isMiniApp() {
|
|
257
|
+
if (_isMiniApp !== null) return _isMiniApp;
|
|
258
|
+
return _miniAppPromise;
|
|
259
|
+
}
|
|
260
|
+
function performAdAction(adData) {
|
|
261
|
+
try {
|
|
262
|
+
switch (adData.type) {
|
|
263
|
+
case "link":
|
|
264
|
+
import_miniapp_sdk.default.actions.openUrl(adData.data.url);
|
|
265
|
+
break;
|
|
266
|
+
case "cast":
|
|
267
|
+
import_miniapp_sdk.default.actions.viewCast({ hash: adData.data.hash });
|
|
268
|
+
break;
|
|
269
|
+
case "miniapp":
|
|
270
|
+
import_miniapp_sdk.default.actions.openMiniApp({ url: adData.data.url });
|
|
271
|
+
break;
|
|
272
|
+
case "token":
|
|
273
|
+
import_miniapp_sdk.default.actions.viewToken({ token: adData.data.address });
|
|
274
|
+
break;
|
|
275
|
+
case "farcasterProfile":
|
|
276
|
+
import_miniapp_sdk.default.actions.viewProfile({
|
|
277
|
+
fid: Number.parseInt(adData.data.fid, 10)
|
|
278
|
+
});
|
|
279
|
+
break;
|
|
280
|
+
}
|
|
281
|
+
} catch (err) {
|
|
282
|
+
if (adData.type === "link" || adData.type === "miniapp") {
|
|
283
|
+
window.open(adData.data.url, "_blank");
|
|
284
|
+
} else {
|
|
285
|
+
console.error("[@adland/react] Failed to perform ad action:", err);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
async function performEmptyAdAction(slot, chainId, baseLinkUrl) {
|
|
290
|
+
const url = `${baseLinkUrl}/slots/${slot}?chain=${chainId}`;
|
|
291
|
+
if (await isMiniApp()) {
|
|
292
|
+
import_miniapp_sdk.default.actions.openMiniApp({ url });
|
|
293
|
+
} else {
|
|
294
|
+
window.open(url, "_blank");
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// src/utils/ad-fields.ts
|
|
299
|
+
var IMAGE_KEYS = ["image", "icon", "pfpUrl", "logoURI", "imageUrl"];
|
|
300
|
+
var TITLE_KEYS = ["title", "displayName", "username", "name", "symbol"];
|
|
301
|
+
var DESC_KEYS = ["description", "bio", "text", "name"];
|
|
302
|
+
function flatFields(data) {
|
|
303
|
+
return { ...data.data, ...data.metadata ?? {} };
|
|
304
|
+
}
|
|
305
|
+
function getAdImage(data) {
|
|
306
|
+
if (!data) return null;
|
|
307
|
+
const fields = flatFields(data);
|
|
308
|
+
for (const key of IMAGE_KEYS) {
|
|
309
|
+
const v = fields[key];
|
|
310
|
+
if (typeof v === "string" && v) return v;
|
|
311
|
+
}
|
|
312
|
+
return null;
|
|
313
|
+
}
|
|
314
|
+
function getAdTitle(data) {
|
|
315
|
+
if (!data) return null;
|
|
316
|
+
const fields = flatFields(data);
|
|
317
|
+
for (const key of TITLE_KEYS) {
|
|
318
|
+
const v = fields[key];
|
|
319
|
+
if (typeof v === "string" && v) return v;
|
|
320
|
+
}
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
323
|
+
function getAdDescription(data) {
|
|
324
|
+
if (!data) return null;
|
|
325
|
+
const fields = flatFields(data);
|
|
326
|
+
const title = getAdTitle(data);
|
|
327
|
+
for (const key of DESC_KEYS) {
|
|
328
|
+
const v = fields[key];
|
|
329
|
+
if (typeof v === "string" && v && v !== title) return v;
|
|
330
|
+
}
|
|
331
|
+
return null;
|
|
332
|
+
}
|
|
333
|
+
function getAdType(data) {
|
|
334
|
+
if (!data) return null;
|
|
335
|
+
return data.type;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// src/utils/constants.ts
|
|
339
|
+
var import_lucide_react = require("lucide-react");
|
|
340
|
+
var adCardIcon = {
|
|
341
|
+
link: import_lucide_react.Link,
|
|
342
|
+
cast: import_lucide_react.MessageCircle,
|
|
343
|
+
miniapp: import_lucide_react.LayoutGrid,
|
|
344
|
+
token: import_lucide_react.Coins,
|
|
345
|
+
farcasterProfile: import_lucide_react.User
|
|
346
|
+
};
|
|
347
|
+
var adCardLabel = {
|
|
348
|
+
link: "Link",
|
|
349
|
+
cast: "Cast",
|
|
350
|
+
miniapp: "Miniapp",
|
|
351
|
+
token: "Token",
|
|
352
|
+
farcasterProfile: "Profile"
|
|
353
|
+
};
|
|
354
|
+
var adlandApiUrl = process.env.NODE_ENV === "development" ? "http://localhost:3069" : "https://api.adland.space";
|
|
355
|
+
|
|
356
|
+
// src/components/Ad.tsx
|
|
357
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
358
|
+
function Ad({
|
|
359
|
+
slot,
|
|
360
|
+
data: staticData,
|
|
361
|
+
chainId = import_sdk2.SlotsChain.BASE,
|
|
362
|
+
rpcUrl,
|
|
363
|
+
baseLinkUrl = "https://app.0xslots.org",
|
|
364
|
+
children,
|
|
365
|
+
...props
|
|
366
|
+
}) {
|
|
367
|
+
const ref = (0, import_react3.useRef)(null);
|
|
368
|
+
const client = (0, import_react3.useMemo)(
|
|
369
|
+
() => slot ? createReadClient(chainId, rpcUrl) : null,
|
|
370
|
+
[slot, chainId, rpcUrl]
|
|
371
|
+
);
|
|
372
|
+
const {
|
|
373
|
+
data: fetchedData,
|
|
374
|
+
isLoading,
|
|
375
|
+
error
|
|
376
|
+
} = useFetch(
|
|
377
|
+
`ad-data-${slot}`,
|
|
378
|
+
async () => {
|
|
379
|
+
if (!client || !slot) throw new Error("NO_AD" /* NO_AD */);
|
|
380
|
+
const uri = await fetchMetadataURI(client, slot);
|
|
381
|
+
if (!uri) throw new Error("NO_AD" /* NO_AD */);
|
|
382
|
+
return fetchAdFromURI(uri);
|
|
383
|
+
},
|
|
384
|
+
{ enabled: !!slot && !staticData }
|
|
385
|
+
);
|
|
386
|
+
const adData = staticData ?? fetchedData;
|
|
387
|
+
const isEmpty = !adData && !isLoading && (error instanceof Error ? error.message === "NO_AD" /* NO_AD */ : !error);
|
|
388
|
+
const onClick = (0, import_react3.useCallback)(
|
|
389
|
+
(e) => {
|
|
390
|
+
const target = e.target;
|
|
391
|
+
const isInteractive = target.tagName === "A" || target.tagName === "BUTTON" || target.closest("a") !== null || target.closest("button") !== null;
|
|
392
|
+
if (isInteractive) return;
|
|
393
|
+
if (adData) {
|
|
394
|
+
performAdAction(adData);
|
|
395
|
+
} else if (isEmpty && slot) {
|
|
396
|
+
performEmptyAdAction(slot, chainId, baseLinkUrl);
|
|
397
|
+
}
|
|
398
|
+
},
|
|
399
|
+
[adData, isEmpty, slot, chainId, baseLinkUrl]
|
|
400
|
+
);
|
|
401
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
402
|
+
AdContext.Provider,
|
|
403
|
+
{
|
|
404
|
+
value: {
|
|
405
|
+
data: adData ?? null,
|
|
406
|
+
isLoading: !!slot && !staticData && isLoading,
|
|
407
|
+
error,
|
|
408
|
+
isEmpty,
|
|
409
|
+
slot,
|
|
410
|
+
baseLinkUrl,
|
|
411
|
+
chainId
|
|
412
|
+
},
|
|
413
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref, onClick, ...props, children })
|
|
414
|
+
}
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
function AdImage({ fallback, ...props }) {
|
|
418
|
+
const { data } = useAd();
|
|
419
|
+
const src = getAdImage(data);
|
|
420
|
+
if (!src) return fallback ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: fallback }) : null;
|
|
421
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src, alt: "", ...props });
|
|
422
|
+
}
|
|
423
|
+
function AdTitle({ fallback, children, ...props }) {
|
|
424
|
+
const { data } = useAd();
|
|
425
|
+
const title = getAdTitle(data);
|
|
426
|
+
if (!title) return fallback ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: fallback }) : null;
|
|
427
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { ...props, children: children ?? title });
|
|
428
|
+
}
|
|
429
|
+
function AdDescription({ fallback, children, ...props }) {
|
|
430
|
+
const { data } = useAd();
|
|
431
|
+
const description = getAdDescription(data);
|
|
432
|
+
if (!description) return fallback ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: fallback }) : null;
|
|
433
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { ...props, children: children ?? description });
|
|
434
|
+
}
|
|
435
|
+
function AdBadge({ children, ...props }) {
|
|
436
|
+
const { data } = useAd();
|
|
437
|
+
const type = getAdType(data);
|
|
438
|
+
if (!type) return null;
|
|
439
|
+
const Icon = adCardIcon[type];
|
|
440
|
+
const label = adCardLabel[type];
|
|
441
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { ...props, children: children ?? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
442
|
+
Icon && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, { className: "size-3" }),
|
|
443
|
+
label
|
|
444
|
+
] }) });
|
|
445
|
+
}
|
|
446
|
+
function AdLabel({ children, ...props }) {
|
|
447
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { ...props, children: children ?? "AD" });
|
|
448
|
+
}
|
|
449
|
+
function AdLoading({ children, ...props }) {
|
|
450
|
+
const { isLoading } = useAd();
|
|
451
|
+
if (!isLoading) return null;
|
|
452
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ...props, children: children ?? "Loading..." });
|
|
453
|
+
}
|
|
454
|
+
function AdEmpty({ children, ...props }) {
|
|
455
|
+
const { isEmpty } = useAd();
|
|
456
|
+
if (!isEmpty) return null;
|
|
457
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ...props, children: children ?? "Your ad here" });
|
|
458
|
+
}
|
|
459
|
+
function AdError({ children, ...props }) {
|
|
460
|
+
const { error, isEmpty } = useAd();
|
|
461
|
+
if (!error || isEmpty) return null;
|
|
462
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ...props, children: children ?? "Error loading ad" });
|
|
463
|
+
}
|
|
464
|
+
function AdLoaded({ children, ...props }) {
|
|
465
|
+
const { data } = useAd();
|
|
466
|
+
if (!data) return null;
|
|
467
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ...props, children });
|
|
468
|
+
}
|
|
469
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
470
|
+
0 && (module.exports = {
|
|
471
|
+
Ad,
|
|
472
|
+
AdBadge,
|
|
473
|
+
AdDescription,
|
|
474
|
+
AdEmpty,
|
|
475
|
+
AdError,
|
|
476
|
+
AdImage,
|
|
477
|
+
AdLabel,
|
|
478
|
+
AdLoaded,
|
|
479
|
+
AdLoading,
|
|
480
|
+
AdTitle,
|
|
481
|
+
adCardIcon,
|
|
482
|
+
adCardLabel,
|
|
483
|
+
getAdDescription,
|
|
484
|
+
getAdImage,
|
|
485
|
+
getAdTitle,
|
|
486
|
+
getAdType,
|
|
487
|
+
useAd
|
|
488
|
+
});
|
|
489
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/components/Ad.tsx","../src/fetch.ts","../src/hooks/useAdContext.ts","../src/hooks/useFetch.ts","../src/utils/fetchCache.ts","../src/utils/ad-actions.ts","../src/utils/ad-fields.ts","../src/utils/constants.ts"],"sourcesContent":["// Compound Ad components\nexport {\n Ad,\n AdBadge,\n AdDescription,\n AdEmpty,\n AdError,\n AdImage,\n AdLabel,\n AdLoaded,\n AdLoading,\n AdTitle,\n} from \"./components/Ad\";\n\nexport type {\n AdBadgeProps,\n AdDescriptionProps,\n AdImageProps,\n AdLabelProps,\n AdStatusProps,\n AdTitleProps,\n} from \"./components/Ad\";\n\n// Context hook\nexport { useAd } from \"./hooks/useAdContext\";\nexport type { AdContextValue } from \"./hooks/useAdContext\";\n\n// Field helpers\nexport { getAdDescription, getAdImage, getAdTitle, getAdType } from \"./utils/ad-fields\";\n\n// Types\nexport type { AdProps, AdDataQueryError } from \"./types\";\n\n// Constants\nexport { adCardIcon, adCardLabel } from \"./utils/constants\";\n","import { SlotsChain } from \"@0xslots/sdk\";\nimport type { AdData } from \"@adland/data\";\nimport { useCallback, useMemo, useRef } from \"react\";\n\nimport { createReadClient, fetchAdFromURI, fetchMetadataURI } from \"../fetch\";\nimport { AdContext, useAd } from \"../hooks/useAdContext\";\nimport { useFetch } from \"../hooks/useFetch\";\nimport { AdDataQueryError, type AdProps } from \"../types\";\nimport { performAdAction, performEmptyAdAction } from \"../utils/ad-actions\";\nimport { getAdDescription, getAdImage, getAdTitle, getAdType } from \"../utils/ad-fields\";\nimport { adCardIcon, adCardLabel } from \"../utils/constants\";\n\n// ─── Root component ──────────────────────────────────────────────────────────\n\n/**\n * Root Ad component — compound pattern.\n *\n * @example\n * ```tsx\n * <Ad slot=\"0xabc...123\" className=\"rounded-md border p-3\">\n * <AdImage className=\"size-10 rounded-md\" />\n * <AdTitle className=\"text-sm font-medium\" />\n * <AdDescription className=\"text-xs text-muted-foreground\" />\n * <AdBadge />\n * </Ad>\n * ```\n */\nexport function Ad({\n slot,\n data: staticData,\n chainId = SlotsChain.BASE,\n rpcUrl,\n baseLinkUrl = \"https://app.0xslots.org\",\n children,\n ...props\n}: AdProps) {\n const ref = useRef<HTMLDivElement>(null);\n\n const client = useMemo(\n () => (slot ? createReadClient(chainId, rpcUrl) : null),\n [slot, chainId, rpcUrl],\n );\n\n const {\n data: fetchedData,\n isLoading,\n error,\n } = useFetch<AdData>(\n `ad-data-${slot}`,\n async () => {\n if (!client || !slot) throw new Error(AdDataQueryError.NO_AD);\n const uri = await fetchMetadataURI(client, slot);\n if (!uri) throw new Error(AdDataQueryError.NO_AD);\n return fetchAdFromURI(uri);\n },\n { enabled: !!slot && !staticData },\n );\n\n const adData = staticData ?? fetchedData;\n\n const isEmpty =\n !adData &&\n !isLoading &&\n (error instanceof Error\n ? error.message === AdDataQueryError.NO_AD\n : !error);\n\n const onClick = useCallback(\n (e: React.MouseEvent<HTMLDivElement>) => {\n const target = e.target as HTMLElement;\n const isInteractive =\n target.tagName === \"A\" ||\n target.tagName === \"BUTTON\" ||\n target.closest(\"a\") !== null ||\n target.closest(\"button\") !== null;\n if (isInteractive) return;\n\n if (adData) {\n performAdAction(adData);\n } else if (isEmpty && slot) {\n performEmptyAdAction(slot, chainId, baseLinkUrl);\n }\n },\n [adData, isEmpty, slot, chainId, baseLinkUrl],\n );\n\n return (\n <AdContext.Provider\n value={{\n data: adData ?? null,\n isLoading: !!slot && !staticData && isLoading,\n error,\n isEmpty,\n slot,\n baseLinkUrl,\n chainId,\n }}\n >\n <div ref={ref} onClick={onClick} {...props}>\n {children}\n </div>\n </AdContext.Provider>\n );\n}\n\n// ─── Sub-components ──────────────────────────────────────────────────────────\n\nexport interface AdImageProps extends React.ImgHTMLAttributes<HTMLImageElement> {\n fallback?: React.ReactNode;\n}\n\nexport function AdImage({ fallback, ...props }: AdImageProps) {\n const { data } = useAd();\n const src = getAdImage(data);\n if (!src) return fallback ? <>{fallback}</> : null;\n return <img src={src} alt=\"\" {...props} />;\n}\n\nexport interface AdTitleProps extends React.HTMLAttributes<HTMLParagraphElement> {\n fallback?: React.ReactNode;\n}\n\nexport function AdTitle({ fallback, children, ...props }: AdTitleProps) {\n const { data } = useAd();\n const title = getAdTitle(data);\n if (!title) return fallback ? <>{fallback}</> : null;\n return <p {...props}>{children ?? title}</p>;\n}\n\nexport interface AdDescriptionProps extends React.HTMLAttributes<HTMLParagraphElement> {\n fallback?: React.ReactNode;\n}\n\nexport function AdDescription({ fallback, children, ...props }: AdDescriptionProps) {\n const { data } = useAd();\n const description = getAdDescription(data);\n if (!description) return fallback ? <>{fallback}</> : null;\n return <p {...props}>{children ?? description}</p>;\n}\n\nexport interface AdBadgeProps extends React.HTMLAttributes<HTMLSpanElement> {}\n\nexport function AdBadge({ children, ...props }: AdBadgeProps) {\n const { data } = useAd();\n const type = getAdType(data);\n if (!type) return null;\n const Icon = adCardIcon[type];\n const label = adCardLabel[type];\n return (\n <span {...props}>\n {children ?? (\n <>\n {Icon && <Icon className=\"size-3\" />}\n {label}\n </>\n )}\n </span>\n );\n}\n\nexport interface AdLabelProps extends React.HTMLAttributes<HTMLSpanElement> {}\n\nexport function AdLabel({ children, ...props }: AdLabelProps) {\n return <span {...props}>{children ?? \"AD\"}</span>;\n}\n\n// ─── State components ────────────────────────────────────────────────────────\n\nexport interface AdStatusProps extends React.HTMLAttributes<HTMLDivElement> {\n children?: React.ReactNode;\n}\n\nexport function AdLoading({ children, ...props }: AdStatusProps) {\n const { isLoading } = useAd();\n if (!isLoading) return null;\n return <div {...props}>{children ?? \"Loading...\"}</div>;\n}\n\nexport function AdEmpty({ children, ...props }: AdStatusProps) {\n const { isEmpty } = useAd();\n if (!isEmpty) return null;\n return <div {...props}>{children ?? \"Your ad here\"}</div>;\n}\n\nexport function AdError({ children, ...props }: AdStatusProps) {\n const { error, isEmpty } = useAd();\n if (!error || isEmpty) return null;\n return <div {...props}>{children ?? \"Error loading ad\"}</div>;\n}\n\nexport function AdLoaded({ children, ...props }: AdStatusProps) {\n const { data } = useAd();\n if (!data) return null;\n return <div {...props}>{children}</div>;\n}\n","import { SlotsClient, type SlotsChain } from \"@0xslots/sdk\";\nimport { type Address, createPublicClient, http } from \"viem\";\nimport { base, baseSepolia } from \"viem/chains\";\n\nimport { AdDataQueryError } from \"./types\";\n\nconst IPFS_GATEWAY = \"https://amethyst-representative-mandrill-369.mypinata.cloud/ipfs/\";\n\nconst viemChains: Record<number, typeof base> = {\n 8453: base,\n 84532: baseSepolia,\n};\n\n/**\n * Create a read-only SlotsClient for a given chain.\n */\nexport function createReadClient(\n chainId: SlotsChain,\n rpcUrl?: string,\n): SlotsClient {\n const chain = viemChains[chainId];\n if (!chain) throw new Error(`Unsupported chain: ${chainId}`);\n\n const publicClient = createPublicClient({\n chain,\n transport: http(rpcUrl),\n });\n\n return new SlotsClient({ chainId, publicClient });\n}\n\n/**\n * Fetch ad content from a metadata URI (IPFS or HTTP)\n */\nexport const fetchAdFromURI = async (uri: string) => {\n if (!uri) throw new Error(AdDataQueryError.NO_AD);\n\n const url = uri.startsWith(\"ipfs://\")\n ? `${IPFS_GATEWAY}${uri.slice(7)}`\n : uri;\n\n const res = await fetch(url, {\n method: \"GET\",\n headers: { Accept: \"application/json\" },\n });\n\n if (!res.ok) {\n if (res.status === 404) throw new Error(AdDataQueryError.NO_AD);\n throw new Error(AdDataQueryError.ERROR);\n }\n\n const data = await res.json();\n if (data.error) throw new Error(data.error);\n\n return data;\n};\n\n/**\n * Fetch the metadata URI for a slot using the SDK.\n */\nexport const fetchMetadataURI = async (\n client: SlotsClient,\n slotAddress: string,\n): Promise<string> => {\n const info = await client.getSlotInfo(slotAddress as Address);\n const moduleAddress = (info as { module: Address }).module;\n\n if (\n !moduleAddress ||\n moduleAddress === \"0x0000000000000000000000000000000000000000\"\n ) {\n return \"\";\n }\n\n return client.modules.metadata.getURI(\n moduleAddress,\n slotAddress as Address,\n );\n};\n","import type { SlotsChain } from \"@0xslots/sdk\";\nimport type { AdData } from \"@adland/data\";\nimport { createContext, useContext } from \"react\";\n\nexport interface AdContextValue {\n data: AdData | null;\n isLoading: boolean;\n error: unknown;\n isEmpty: boolean;\n slot?: string;\n baseLinkUrl: string;\n chainId: SlotsChain;\n}\n\nexport const AdContext = createContext<AdContextValue | null>(null);\n\nexport function useAd(): AdContextValue {\n const ctx = useContext(AdContext);\n if (!ctx) throw new Error(\"useAd must be used within an <Ad> component\");\n return ctx;\n}\n","import { useEffect, useState } from \"react\";\nimport FetchCache from \"../utils/fetchCache\";\n\ntype Status = \"idle\" | \"loading\" | \"success\" | \"error\";\n\nconst globalCache = new FetchCache();\n\nexport const fetchCache = {\n clear: () => globalCache.clear(),\n};\n\nexport function useFetch<T>(\n key: string,\n fetcher: () => Promise<T>,\n opts?: {\n enabled?: boolean;\n ttl?: number; // ms\n },\n) {\n const { enabled = true, ttl = 0 } = opts ?? {};\n\n // Get cached data from global cache\n const getCachedData = (): T | null => {\n return globalCache.get<T>(key, ttl || undefined);\n };\n\n const hasCachedData = () => {\n return globalCache.has(key, ttl || undefined);\n };\n\n // Check if there's an active fetch for this key (dedupe concurrent requests)\n const getActiveFetch = (): Promise<T> | undefined => {\n return globalCache.getActiveFetch<T>(key);\n };\n\n const cachedData = getCachedData();\n const [data, setData] = useState<T | null>(cachedData);\n const [error, setError] = useState<unknown>(null);\n // If we have cached data, start with success status to avoid showing loader\n const [status, setStatus] = useState<Status>(cachedData ? \"success\" : \"idle\");\n\n const refetch = async () => {\n // ALWAYS check cache first - never show loading if we have valid cached data\n const cached = getCachedData();\n if (cached) {\n // Already have valid cached data, ensure state is correct\n setData(cached);\n setStatus(\"success\");\n return cached;\n }\n\n // Check if there's already an active fetch for this key (dedupe)\n const activeFetch = getActiveFetch();\n if (activeFetch) {\n try {\n const res = await activeFetch;\n setData(res);\n setStatus(\"success\");\n return res;\n } catch (e) {\n setError(e);\n setStatus(\"error\");\n throw e;\n }\n }\n\n // Only set loading if we actually need to fetch\n setStatus(\"loading\");\n setError(null);\n\n try {\n // Create fetch promise and store it for deduplication\n const fetchPromise = fetcher();\n globalCache.setActiveFetch(key, fetchPromise);\n\n const res = await fetchPromise;\n globalCache.set(key, res);\n setData(res);\n setStatus(\"success\");\n return res;\n } catch (e) {\n setError(e);\n setStatus(\"error\");\n throw e;\n }\n };\n\n useEffect(() => {\n if (!enabled) return;\n\n const cached = getCachedData();\n\n if (cached) {\n setData(cached);\n setStatus(\"success\");\n return;\n }\n\n const activeFetch = getActiveFetch();\n if (activeFetch) {\n setStatus(\"loading\");\n activeFetch\n .then((res) => {\n setData(res);\n setStatus(\"success\");\n })\n .catch((e) => {\n setError(e);\n setStatus(\"error\");\n });\n return;\n }\n\n if (status !== \"loading\" && status !== \"success\") {\n refetch();\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [key, enabled]);\n\n const hasValidCache = hasCachedData();\n const isLoading = status === \"loading\" && !hasValidCache;\n\n return {\n data,\n error,\n status,\n isIdle: status === \"idle\",\n isLoading,\n isSuccess: status === \"success\",\n isError: status === \"error\",\n refetch,\n };\n}\n","class FetchCache {\n private cache = new Map<string, { data: unknown; ts: number }>();\n private activeFetches = new Map<string, Promise<unknown>>();\n\n get<T>(key: string, ttl?: number): T | null {\n const cached = this.cache.get(key);\n if (!cached) return null;\n\n if (ttl && Date.now() - cached.ts > ttl) {\n // Cache expired, remove it\n this.cache.delete(key);\n return null;\n }\n\n return cached.data as T;\n }\n\n has(key: string, ttl?: number): boolean {\n const cached = this.cache.get(key);\n if (!cached) return false;\n\n if (ttl && Date.now() - cached.ts > ttl) {\n this.cache.delete(key);\n return false;\n }\n\n return true;\n }\n\n set<T>(key: string, data: T): void {\n this.cache.set(key, { data, ts: Date.now() });\n }\n\n getActiveFetch<T>(key: string): Promise<T> | undefined {\n return this.activeFetches.get(key) as Promise<T> | undefined;\n }\n\n setActiveFetch<T>(key: string, promise: Promise<T>): void {\n this.activeFetches.set(key, promise);\n promise.finally(() => {\n this.activeFetches.delete(key);\n });\n }\n\n clear(): void {\n this.cache.clear();\n this.activeFetches.clear();\n }\n}\n\nexport default FetchCache;\n","import type { SlotsChain } from \"@0xslots/sdk\";\nimport type { AdData } from \"@adland/data\";\nimport sdk from \"@farcaster/miniapp-sdk\";\n\n// Cache the miniapp check at module level — resolved once, sync thereafter\nlet _isMiniApp: boolean | null = null;\nconst _miniAppPromise = sdk.isInMiniApp().then((v) => {\n _isMiniApp = v;\n return v;\n}).catch(() => {\n _isMiniApp = false;\n return false;\n});\n\nasync function isMiniApp(): Promise<boolean> {\n if (_isMiniApp !== null) return _isMiniApp;\n return _miniAppPromise;\n}\n\nexport function performAdAction(adData: AdData) {\n try {\n switch (adData.type) {\n case \"link\":\n sdk.actions.openUrl(adData.data.url);\n break;\n case \"cast\":\n sdk.actions.viewCast({ hash: adData.data.hash });\n break;\n case \"miniapp\":\n sdk.actions.openMiniApp({ url: adData.data.url });\n break;\n case \"token\":\n sdk.actions.viewToken({ token: adData.data.address });\n break;\n case \"farcasterProfile\":\n sdk.actions.viewProfile({\n fid: Number.parseInt(adData.data.fid, 10),\n });\n break;\n }\n } catch (err) {\n // Fallback for web (non-miniapp) context\n if (adData.type === \"link\" || adData.type === \"miniapp\") {\n window.open(adData.data.url, \"_blank\");\n } else {\n console.error(\"[@adland/react] Failed to perform ad action:\", err);\n }\n }\n}\n\nexport async function performEmptyAdAction(\n slot: string,\n chainId: SlotsChain,\n baseLinkUrl: string,\n) {\n const url = `${baseLinkUrl}/slots/${slot}?chain=${chainId}`;\n if (await isMiniApp()) {\n sdk.actions.openMiniApp({ url });\n } else {\n window.open(url, \"_blank\");\n }\n}\n","import type { AdData, AdType } from \"@adland/data\";\n\nconst IMAGE_KEYS = [\"image\", \"icon\", \"pfpUrl\", \"logoURI\", \"imageUrl\"] as const;\nconst TITLE_KEYS = [\"title\", \"displayName\", \"username\", \"name\", \"symbol\"] as const;\nconst DESC_KEYS = [\"description\", \"bio\", \"text\", \"name\"] as const;\n\nfunction flatFields(data: AdData): Record<string, unknown> {\n return { ...data.data, ...(data.metadata ?? {}) };\n}\n\nexport function getAdImage(data: AdData | null): string | null {\n if (!data) return null;\n const fields = flatFields(data);\n for (const key of IMAGE_KEYS) {\n const v = fields[key];\n if (typeof v === \"string\" && v) return v;\n }\n return null;\n}\n\nexport function getAdTitle(data: AdData | null): string | null {\n if (!data) return null;\n const fields = flatFields(data);\n for (const key of TITLE_KEYS) {\n const v = fields[key];\n if (typeof v === \"string\" && v) return v;\n }\n return null;\n}\n\nexport function getAdDescription(data: AdData | null): string | null {\n if (!data) return null;\n const fields = flatFields(data);\n const title = getAdTitle(data);\n for (const key of DESC_KEYS) {\n const v = fields[key];\n if (typeof v === \"string\" && v && v !== title) return v;\n }\n return null;\n}\n\nexport function getAdType(data: AdData | null): AdType | null {\n if (!data) return null;\n return data.type as AdType;\n}\n","import { AdType } from \"@adland/data\";\nimport { ForwardRefExoticComponent, RefAttributes } from \"react\";\nimport {\n Link,\n MessageCircle,\n LayoutGrid,\n LucideProps,\n Coins,\n User,\n} from \"lucide-react\";\n\nexport const adCardIcon: Record<\n AdType,\n ForwardRefExoticComponent<\n Omit<LucideProps, \"ref\"> & RefAttributes<SVGSVGElement>\n >\n> = {\n link: Link,\n cast: MessageCircle,\n miniapp: LayoutGrid,\n token: Coins,\n farcasterProfile: User,\n};\n\nexport const adCardLabel: Record<AdType, string> = {\n link: \"Link\",\n cast: \"Cast\",\n miniapp: \"Miniapp\",\n token: \"Token\",\n farcasterProfile: \"Profile\",\n};\n\nexport const adlandApiUrl =\n process.env.NODE_ENV === \"development\"\n ? \"http://localhost:3069\"\n : \"https://api.adland.space\";\n"],"mappings":"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","names":["import_sdk","import_react","import_react","sdk"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { AdProps } from './types.cjs';
|
|
3
|
+
export { AdDataQueryError } from './types.cjs';
|
|
4
|
+
import { SlotsChain } from '@0xslots/sdk';
|
|
5
|
+
import { AdData, AdType } from '@adland/data';
|
|
6
|
+
import { ForwardRefExoticComponent, RefAttributes } from 'react';
|
|
7
|
+
import { LucideProps } from 'lucide-react';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Root Ad component — compound pattern.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```tsx
|
|
14
|
+
* <Ad slot="0xabc...123" className="rounded-md border p-3">
|
|
15
|
+
* <AdImage className="size-10 rounded-md" />
|
|
16
|
+
* <AdTitle className="text-sm font-medium" />
|
|
17
|
+
* <AdDescription className="text-xs text-muted-foreground" />
|
|
18
|
+
* <AdBadge />
|
|
19
|
+
* </Ad>
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
declare function Ad({ slot, data: staticData, chainId, rpcUrl, baseLinkUrl, children, ...props }: AdProps): react_jsx_runtime.JSX.Element;
|
|
23
|
+
interface AdImageProps extends React.ImgHTMLAttributes<HTMLImageElement> {
|
|
24
|
+
fallback?: React.ReactNode;
|
|
25
|
+
}
|
|
26
|
+
declare function AdImage({ fallback, ...props }: AdImageProps): react_jsx_runtime.JSX.Element | null;
|
|
27
|
+
interface AdTitleProps extends React.HTMLAttributes<HTMLParagraphElement> {
|
|
28
|
+
fallback?: React.ReactNode;
|
|
29
|
+
}
|
|
30
|
+
declare function AdTitle({ fallback, children, ...props }: AdTitleProps): react_jsx_runtime.JSX.Element | null;
|
|
31
|
+
interface AdDescriptionProps extends React.HTMLAttributes<HTMLParagraphElement> {
|
|
32
|
+
fallback?: React.ReactNode;
|
|
33
|
+
}
|
|
34
|
+
declare function AdDescription({ fallback, children, ...props }: AdDescriptionProps): react_jsx_runtime.JSX.Element | null;
|
|
35
|
+
interface AdBadgeProps extends React.HTMLAttributes<HTMLSpanElement> {
|
|
36
|
+
}
|
|
37
|
+
declare function AdBadge({ children, ...props }: AdBadgeProps): react_jsx_runtime.JSX.Element | null;
|
|
38
|
+
interface AdLabelProps extends React.HTMLAttributes<HTMLSpanElement> {
|
|
39
|
+
}
|
|
40
|
+
declare function AdLabel({ children, ...props }: AdLabelProps): react_jsx_runtime.JSX.Element;
|
|
41
|
+
interface AdStatusProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
42
|
+
children?: React.ReactNode;
|
|
43
|
+
}
|
|
44
|
+
declare function AdLoading({ children, ...props }: AdStatusProps): react_jsx_runtime.JSX.Element | null;
|
|
45
|
+
declare function AdEmpty({ children, ...props }: AdStatusProps): react_jsx_runtime.JSX.Element | null;
|
|
46
|
+
declare function AdError({ children, ...props }: AdStatusProps): react_jsx_runtime.JSX.Element | null;
|
|
47
|
+
declare function AdLoaded({ children, ...props }: AdStatusProps): react_jsx_runtime.JSX.Element | null;
|
|
48
|
+
|
|
49
|
+
interface AdContextValue {
|
|
50
|
+
data: AdData | null;
|
|
51
|
+
isLoading: boolean;
|
|
52
|
+
error: unknown;
|
|
53
|
+
isEmpty: boolean;
|
|
54
|
+
slot?: string;
|
|
55
|
+
baseLinkUrl: string;
|
|
56
|
+
chainId: SlotsChain;
|
|
57
|
+
}
|
|
58
|
+
declare function useAd(): AdContextValue;
|
|
59
|
+
|
|
60
|
+
declare function getAdImage(data: AdData | null): string | null;
|
|
61
|
+
declare function getAdTitle(data: AdData | null): string | null;
|
|
62
|
+
declare function getAdDescription(data: AdData | null): string | null;
|
|
63
|
+
declare function getAdType(data: AdData | null): AdType | null;
|
|
64
|
+
|
|
65
|
+
declare const adCardIcon: Record<AdType, ForwardRefExoticComponent<Omit<LucideProps, "ref"> & RefAttributes<SVGSVGElement>>>;
|
|
66
|
+
declare const adCardLabel: Record<AdType, string>;
|
|
67
|
+
|
|
68
|
+
export { Ad, AdBadge, type AdBadgeProps, type AdContextValue, AdDescription, type AdDescriptionProps, AdEmpty, AdError, AdImage, type AdImageProps, AdLabel, type AdLabelProps, AdLoaded, AdLoading, AdProps, type AdStatusProps, AdTitle, type AdTitleProps, adCardIcon, adCardLabel, getAdDescription, getAdImage, getAdTitle, getAdType, useAd };
|