@adland/react 0.13.1 → 0.14.0
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/CHANGELOG.md +6 -0
- package/package.json +3 -3
- package/src/components/Ad.tsx +11 -4
- package/src/hooks/useAdContext.ts +3 -0
- package/src/types.ts +6 -0
- package/src/utils/ad-actions.ts +35 -2
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adland/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"lucide-react": "0.561.0",
|
|
35
35
|
"tsup": "^8.0.1",
|
|
36
36
|
"viem": "^2.0.0",
|
|
37
|
-
"@
|
|
38
|
-
"@
|
|
37
|
+
"@0xslots/sdk": "0.10.1",
|
|
38
|
+
"@adland/data": "0.14.1"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@typescript-eslint/eslint-plugin": "^7.13.1",
|
package/src/components/Ad.tsx
CHANGED
|
@@ -6,7 +6,7 @@ import { createReadClient, fetchAdFromURI, fetchMetadataURI } from "../fetch";
|
|
|
6
6
|
import { AdContext, useAd } from "../hooks/useAdContext";
|
|
7
7
|
import { useFetch } from "../hooks/useFetch";
|
|
8
8
|
import { AdDataQueryError, type AdProps } from "../types";
|
|
9
|
-
import { performAdAction } from "../utils/ad-actions";
|
|
9
|
+
import { performAdAction, performEmptyAdAction } from "../utils/ad-actions";
|
|
10
10
|
import { getAdDescription, getAdImage, getAdTitle, getAdType } from "../utils/ad-fields";
|
|
11
11
|
import { adCardIcon, adCardLabel } from "../utils/constants";
|
|
12
12
|
|
|
@@ -30,6 +30,7 @@ export function Ad({
|
|
|
30
30
|
data: staticData,
|
|
31
31
|
chainId = SlotsChain.BASE,
|
|
32
32
|
rpcUrl,
|
|
33
|
+
baseLinkUrl = "https://app.0xslots.org",
|
|
33
34
|
children,
|
|
34
35
|
...props
|
|
35
36
|
}: AdProps) {
|
|
@@ -72,11 +73,15 @@ export function Ad({
|
|
|
72
73
|
target.tagName === "BUTTON" ||
|
|
73
74
|
target.closest("a") !== null ||
|
|
74
75
|
target.closest("button") !== null;
|
|
75
|
-
if (
|
|
76
|
+
if (isInteractive) return;
|
|
77
|
+
|
|
78
|
+
if (adData) {
|
|
76
79
|
performAdAction(adData);
|
|
80
|
+
} else if (isEmpty && slot) {
|
|
81
|
+
performEmptyAdAction(slot, chainId, baseLinkUrl);
|
|
77
82
|
}
|
|
78
83
|
},
|
|
79
|
-
[adData],
|
|
84
|
+
[adData, isEmpty, slot, chainId, baseLinkUrl],
|
|
80
85
|
);
|
|
81
86
|
|
|
82
87
|
return (
|
|
@@ -87,6 +92,8 @@ export function Ad({
|
|
|
87
92
|
error,
|
|
88
93
|
isEmpty,
|
|
89
94
|
slot,
|
|
95
|
+
baseLinkUrl,
|
|
96
|
+
chainId,
|
|
90
97
|
}}
|
|
91
98
|
>
|
|
92
99
|
<div ref={ref} onClick={onClick} {...props}>
|
|
@@ -172,7 +179,7 @@ export function AdLoading({ children, ...props }: AdStatusProps) {
|
|
|
172
179
|
export function AdEmpty({ children, ...props }: AdStatusProps) {
|
|
173
180
|
const { isEmpty } = useAd();
|
|
174
181
|
if (!isEmpty) return null;
|
|
175
|
-
return <div {...props}>{children ?? "
|
|
182
|
+
return <div {...props}>{children ?? "Your ad here"}</div>;
|
|
176
183
|
}
|
|
177
184
|
|
|
178
185
|
export function AdError({ children, ...props }: AdStatusProps) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { SlotsChain } from "@0xslots/sdk";
|
|
1
2
|
import type { AdData } from "@adland/data";
|
|
2
3
|
import { createContext, useContext } from "react";
|
|
3
4
|
|
|
@@ -7,6 +8,8 @@ export interface AdContextValue {
|
|
|
7
8
|
error: unknown;
|
|
8
9
|
isEmpty: boolean;
|
|
9
10
|
slot?: string;
|
|
11
|
+
baseLinkUrl: string;
|
|
12
|
+
chainId: SlotsChain;
|
|
10
13
|
}
|
|
11
14
|
|
|
12
15
|
export const AdContext = createContext<AdContextValue | null>(null);
|
package/src/types.ts
CHANGED
|
@@ -19,6 +19,12 @@ export interface AdProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
19
19
|
* Optional RPC URL override. If not provided, uses public RPC for the chain.
|
|
20
20
|
*/
|
|
21
21
|
rpcUrl?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Base URL for the "Your ad here" CTA link.
|
|
24
|
+
* Empty-state click navigates to `${baseLinkUrl}/slots/${slot}?chain=${chainId}`.
|
|
25
|
+
* Defaults to "https://app.0xslots.org".
|
|
26
|
+
*/
|
|
27
|
+
baseLinkUrl?: string;
|
|
22
28
|
/**
|
|
23
29
|
* Compound children (AdImage, AdTitle, etc.)
|
|
24
30
|
*/
|
package/src/utils/ad-actions.ts
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
|
+
import type { SlotsChain } from "@0xslots/sdk";
|
|
1
2
|
import type { AdData } from "@adland/data";
|
|
2
3
|
import sdk from "@farcaster/miniapp-sdk";
|
|
3
4
|
|
|
5
|
+
async function isMiniApp(): Promise<boolean> {
|
|
6
|
+
try {
|
|
7
|
+
const context = await Promise.race([
|
|
8
|
+
sdk.context,
|
|
9
|
+
new Promise((r) => setTimeout(r, 500)),
|
|
10
|
+
]);
|
|
11
|
+
return !!context;
|
|
12
|
+
} catch {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
4
17
|
export function performAdAction(adData: AdData) {
|
|
5
18
|
try {
|
|
6
19
|
switch (adData.type) {
|
|
@@ -17,10 +30,30 @@ export function performAdAction(adData: AdData) {
|
|
|
17
30
|
sdk.actions.viewToken({ token: adData.data.address });
|
|
18
31
|
break;
|
|
19
32
|
case "farcasterProfile":
|
|
20
|
-
sdk.actions.viewProfile({
|
|
33
|
+
sdk.actions.viewProfile({
|
|
34
|
+
fid: Number.parseInt(adData.data.fid, 10),
|
|
35
|
+
});
|
|
21
36
|
break;
|
|
22
37
|
}
|
|
23
38
|
} catch (err) {
|
|
24
|
-
|
|
39
|
+
// Fallback for web (non-miniapp) context
|
|
40
|
+
if (adData.type === "link" || adData.type === "miniapp") {
|
|
41
|
+
window.open(adData.data.url, "_blank");
|
|
42
|
+
} else {
|
|
43
|
+
console.error("[@adland/react] Failed to perform ad action:", err);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export async function performEmptyAdAction(
|
|
49
|
+
slot: string,
|
|
50
|
+
chainId: SlotsChain,
|
|
51
|
+
baseLinkUrl: string,
|
|
52
|
+
) {
|
|
53
|
+
const url = `${baseLinkUrl}/slots/${slot}?chain=${chainId}`;
|
|
54
|
+
if (await isMiniApp()) {
|
|
55
|
+
sdk.actions.openMiniApp({ url });
|
|
56
|
+
} else {
|
|
57
|
+
window.open(url, "_blank");
|
|
25
58
|
}
|
|
26
59
|
}
|