Skip to content

Commit 0fb9728

Browse files
committed
init nft widget
1 parent 5431f89 commit 0fb9728

File tree

8 files changed

+7793
-183
lines changed

8 files changed

+7793
-183
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
node_modules
2+
.parcel-cache
3+
.DS_Store
4+
dist/

LICENSE

+183-183
Large diffs are not rendered by default.

dev-iframe.html

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head> </head>
4+
<body>
5+
<iframe
6+
src="http://localhost:1234/"
7+
width="1100px"
8+
height="1100px"
9+
frameborder="0"
10+
></iframe>
11+
</body>
12+
</html>

package.json

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"name": "thirdweb-widgets",
3+
"version": "1.0.0",
4+
"description": "",
5+
"scripts": {
6+
"serve": "parcel src/widgets/nft.html",
7+
"build": "yarn clean && parcel build src/widgets/nft.html",
8+
"clean": "rm -rf ./dist"
9+
},
10+
"repository": {
11+
"type": "git",
12+
"url": "git+https://github.com/nftlabs/widgets.git"
13+
},
14+
"author": "Non-Fungible Labs, Inc",
15+
"license": "Apache-2.0",
16+
"bugs": {
17+
"url": "https://github.com/nftlabs/widgets/issues"
18+
},
19+
"homepage": "https://github.com/nftlabs/widgets#readme",
20+
"browserslist": "> 0.5%, last 2 versions, not dead",
21+
"devDependencies": {
22+
"@types/react": "^17.0.37",
23+
"@types/react-dom": "^17.0.11",
24+
"parcel": "^2.0.1"
25+
},
26+
"dependencies": {
27+
"@3rdweb/hooks": "^1.3.3",
28+
"@3rdweb/react": "^1.3.1",
29+
"@3rdweb/sdk": "^1.21.0",
30+
"@chakra-ui/react": "^1.7.2",
31+
"@emotion/react": "^11",
32+
"@emotion/styled": "^11",
33+
"ethers": "^5.5.2",
34+
"framer-motion": "^4",
35+
"react": "^17.0.2",
36+
"react-dom": "^17.0.2"
37+
}
38+
}

src/shared/powered-by.tsx

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import Icon, { IconProps } from "@chakra-ui/icon";
2+
import { Link } from "@chakra-ui/react";
3+
4+
export const PoweredBy: React.FC<IconProps> = (props) => {
5+
return (
6+
<Link isExternal href="https://thirdweb.com?utm_source=embed">
7+
<Icon
8+
xmlns="http://www.w3.org/2000/svg"
9+
width="123px"
10+
height="46px"
11+
viewBox="0 0 123 46"
12+
fill="none"
13+
{...props}
14+
>
15+
<path
16+
d="M44.233 15H45.4659V11.2812H47.6932C50.0646 11.2812 51.1335 9.83949 51.1335 8.03977C51.1335 6.24006 50.0646 4.81818 47.6733 4.81818H44.233V15ZM45.4659 10.1875V5.91193H47.6335C49.2891 5.91193 49.9205 6.81676 49.9205 8.03977C49.9205 9.26278 49.2891 10.1875 47.6534 10.1875H45.4659ZM55.9808 15.1591C58.049 15.1591 59.4411 13.5881 59.4411 11.2216C59.4411 8.83523 58.049 7.2642 55.9808 7.2642C53.9126 7.2642 52.5206 8.83523 52.5206 11.2216C52.5206 13.5881 53.9126 15.1591 55.9808 15.1591ZM55.9808 14.1051C54.4098 14.1051 53.6939 12.7528 53.6939 11.2216C53.6939 9.69034 54.4098 8.31818 55.9808 8.31818C57.5518 8.31818 58.2678 9.69034 58.2678 11.2216C58.2678 12.7528 57.5518 14.1051 55.9808 14.1051ZM62.7024 15H63.8558L65.5263 9.13352H65.6456L67.3161 15H68.4695L70.7962 7.36364H69.5632L67.9126 13.1903H67.8331L66.2223 7.36364H64.9695L63.3388 13.2102H63.2592L61.6087 7.36364H60.3757L62.7024 15ZM75.2892 15.1591C76.8404 15.1591 77.9739 14.3835 78.3319 13.2301L77.1983 12.9119C76.9 13.7074 76.209 14.1051 75.2892 14.1051C73.9121 14.1051 72.9625 13.2152 72.9078 11.5795H78.4512V11.0824C78.4512 8.23864 76.7608 7.2642 75.1699 7.2642C73.1017 7.2642 71.7296 8.89489 71.7296 11.2415C71.7296 13.5881 73.0819 15.1591 75.2892 15.1591ZM72.9078 10.5653C72.9874 9.37713 73.8276 8.31818 75.1699 8.31818C76.4426 8.31818 77.258 9.27273 77.258 10.5653H72.9078ZM80.236 15H81.4093V10.1676C81.4093 9.13352 82.2246 8.37784 83.3382 8.37784C83.6515 8.37784 83.9746 8.4375 84.0542 8.45739V7.2642C83.9199 7.25426 83.6117 7.24432 83.4377 7.24432C82.5229 7.24432 81.7275 7.76136 81.449 8.51705H81.3695V7.36364H80.236V15ZM88.4142 15.1591C89.9654 15.1591 91.0989 14.3835 91.4569 13.2301L90.3233 12.9119C90.025 13.7074 89.334 14.1051 88.4142 14.1051C87.0371 14.1051 86.0875 13.2152 86.0328 11.5795H91.5762V11.0824C91.5762 8.23864 89.8858 7.2642 88.2949 7.2642C86.2267 7.2642 84.8546 8.89489 84.8546 11.2415C84.8546 13.5881 86.2069 15.1591 88.4142 15.1591ZM86.0328 10.5653C86.1124 9.37713 86.9526 8.31818 88.2949 8.31818C89.5676 8.31818 90.383 9.27273 90.383 10.5653H86.0328ZM96.2445 15.1591C97.7161 15.1591 98.2132 14.2443 98.4718 13.8267H98.611V15H99.7445V4.81818H98.5712V8.5767H98.4718C98.2132 8.17898 97.7559 7.2642 96.2644 7.2642C94.3354 7.2642 93.003 8.79545 93.003 11.2017C93.003 13.6278 94.3354 15.1591 96.2445 15.1591ZM96.4036 14.1051C94.932 14.1051 94.1763 12.8125 94.1763 11.1818C94.1763 9.57102 94.9121 8.31818 96.4036 8.31818C97.8354 8.31818 98.5911 9.47159 98.5911 11.1818C98.5911 12.9119 97.8155 14.1051 96.4036 14.1051ZM106.153 15H107.286V13.8267H107.426C107.684 14.2443 108.181 15.1591 109.653 15.1591C111.562 15.1591 112.894 13.6278 112.894 11.2017C112.894 8.79545 111.562 7.2642 109.633 7.2642C108.142 7.2642 107.684 8.17898 107.426 8.5767H107.326V4.81818H106.153V15ZM107.306 11.1818C107.306 9.47159 108.062 8.31818 109.494 8.31818C110.985 8.31818 111.721 9.57102 111.721 11.1818C111.721 12.8125 110.965 14.1051 109.494 14.1051C108.082 14.1051 107.306 12.9119 107.306 11.1818ZM115.171 17.8636C116.23 17.8636 116.976 17.3018 117.419 16.1136L120.67 7.38352L119.387 7.36364L117.279 13.4489H117.2L115.092 7.36364H113.819L116.643 15.0398L116.424 15.6364C115.997 16.7997 115.47 16.9091 114.615 16.6903L114.316 17.7244C114.436 17.7841 114.774 17.8636 115.171 17.8636Z"
17+
fill="#AEAEB2"
18+
/>
19+
20+
<path
21+
fillRule="evenodd"
22+
d="M57.4209 28.6277C56.3797 28.6277 55.526 29.4709 55.526 30.546C55.526 31.6 56.3797 32.4432 57.4209 32.4432C58.462 32.4432 59.3157 31.6 59.3157 30.546C59.3157 29.4709 58.462 28.6277 57.4209 28.6277ZM59.0867 33.4129H55.7759V44.7751H59.0867V33.4129ZM36.4526 29.0493H39.6801V33.4129H42.158V36.4485H39.6801V40.4537C39.6801 41.044 40.1382 41.5077 40.7004 41.5077H42.1371V44.733H40.7004C38.3683 44.733 36.4526 42.8147 36.4526 40.4326V36.4274H34.9534V33.3919H36.4526V29.0493ZM50.0497 33.16C48.5505 33.16 47.3636 33.7924 46.9055 34.7831V29.0493H43.5947V44.7541H46.9055V38.3879C46.9055 37.0598 47.7592 36.1323 48.9669 36.1323C50.1955 36.1323 50.8826 36.9333 50.8826 38.2825V44.7752H54.1934V37.8608C54.1934 34.9096 52.6942 33.16 50.0497 33.16ZM63.8133 33.3918V34.9518C64.313 33.8134 65.5207 33.16 67.0408 33.1389C67.2698 33.1389 67.5613 33.16 67.9153 33.2021V36.3642C67.5821 36.3009 67.2073 36.2587 66.8117 36.2587C64.9169 36.2587 63.8133 37.3338 63.8133 39.21V44.7541H60.5025V33.3918H63.8133ZM77.2231 34.8885C76.8899 33.8978 75.5781 33.2021 73.8915 33.2021C72.3089 33.2021 70.9763 33.7713 69.9143 34.9096C68.8732 36.0269 68.3318 37.4392 68.3318 39.0835C68.3318 40.7278 68.8732 42.1191 69.9143 43.2785C70.9763 44.3957 72.3089 44.9649 73.8915 44.9649C75.5781 44.9649 76.8899 44.2692 77.2231 43.2785V44.7752H80.5338V29.0493H77.2231V34.8885ZM76.5567 41.1072C75.9945 41.6553 75.3074 41.9083 74.4953 41.9083C73.704 41.9083 73.0169 41.6342 72.4755 41.1072C71.9133 40.538 71.6426 39.8635 71.6426 39.0835C71.6426 38.3035 71.9133 37.629 72.4755 37.0809C73.0377 36.5117 73.704 36.2377 74.4953 36.2377C75.3282 36.2377 76.0154 36.5117 76.5567 37.0809C77.1398 37.629 77.4313 38.3035 77.4313 39.0835C77.4313 39.8635 77.1398 40.538 76.5567 41.1072ZM90.0914 33.4551L93.0898 38.8516L95.1096 33.4129H98.3579L93.7353 45.4286L90.0914 38.8937L86.4474 45.4286L81.8457 33.4129H85.094L87.0929 38.8516L90.0914 33.4551ZM103.813 33.1389C102.106 33.1389 100.669 33.687 99.5447 34.7831C98.4411 35.8582 97.8789 37.2917 97.8789 39.0624V39.1678C97.8789 40.9385 98.4411 42.372 99.5447 43.4471C100.69 44.5011 102.148 45.0492 103.98 45.0492C105.687 45.0492 107.082 44.7119 108.144 44.0163V41.0861C107.103 41.8239 105.771 42.1823 104.167 42.1823C102.418 42.1823 101.273 41.318 101.211 39.9689H109.435C109.477 39.6316 109.498 39.2521 109.498 38.8727C109.498 37.2495 108.956 35.9004 107.915 34.8042C106.874 33.687 105.479 33.1389 103.813 33.1389ZM101.211 37.7976C101.231 37.2706 101.502 36.8279 102.002 36.4696C102.522 36.1112 103.105 35.9215 103.813 35.9215C105.125 35.9215 106.145 36.7858 106.145 37.7976H101.211ZM117.39 33.2021C118.972 33.2021 120.305 33.7713 121.346 34.9096C122.408 36.048 122.949 37.4182 122.949 39.0624C122.949 40.7067 122.408 42.098 121.346 43.2574C120.305 44.3746 118.972 44.9438 117.39 44.9438C115.703 44.9438 114.391 44.2481 114.058 43.2574V44.7541H110.747V29.0493H114.058V34.8885C114.391 33.8978 115.703 33.2021 117.39 33.2021ZM116.786 41.9082C117.577 41.9082 118.243 41.6553 118.806 41.1072C119.368 40.538 119.639 39.8635 119.639 39.0835C119.639 38.3035 119.368 37.629 118.806 37.0809C118.264 36.5117 117.577 36.2377 116.786 36.2377C115.974 36.2377 115.287 36.5117 114.704 37.0809C114.141 37.629 113.85 38.3035 113.85 39.0835C113.85 39.8635 114.141 40.538 114.704 41.1072C115.266 41.6342 115.953 41.9082 116.786 41.9082Z"
23+
fill="#AEAEB2"
24+
/>
25+
26+
<path
27+
fillRule="evenodd"
28+
d="M0.0784805 29.5145C-0.210081 28.7865 0.327693 28 1.11468 28H6.00055C6.45963 28 6.86624 28.273 7.03675 28.6955L10.9258 38.3934C11.0307 38.6534 11.0307 38.9459 10.9258 39.2124L8.47956 45.3029C8.10574 46.2324 6.78098 46.2324 6.40716 45.3029L0.0784805 29.5145ZM9.51596 29.482C9.25363 28.7605 9.79141 28 10.5653 28H14.8216C15.2938 28 15.7135 28.2925 15.8709 28.728L19.4058 38.4259C19.491 38.6664 19.491 38.9329 19.4058 39.1799L17.2809 45.0104C16.9267 45.9854 15.5364 45.9854 15.1823 45.0104L9.51596 29.482ZM19.0713 28C18.2843 28 17.7466 28.7865 18.0351 29.5145L24.3638 45.3029C24.7376 46.2324 26.0624 46.2324 26.4362 45.3029L28.8824 39.2124C28.9873 38.9459 28.9873 38.6534 28.8824 38.3934L24.9934 28.6955C24.8229 28.273 24.4163 28 23.9572 28H19.0713Z"
29+
fill="#AEAEB2"
30+
/>
31+
</Icon>
32+
</Link>
33+
);
34+
};

src/widgets/nft.html

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1" />
7+
</head>
8+
<body>
9+
<div id="root"></div>
10+
<script type="module">
11+
import runNFT from "./nft.tsx";
12+
runNFT();
13+
</script>
14+
</body>
15+
</html>

src/widgets/nft.tsx

+180
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
import React, { useEffect, useMemo, useState } from "react";
2+
import ReactDOM from "react-dom";
3+
import {
4+
ChakraProvider,
5+
Flex,
6+
Heading,
7+
Image,
8+
Stack,
9+
AspectRatio,
10+
Box,
11+
IconButton,
12+
} from "@chakra-ui/react";
13+
import { ThirdwebWeb3Provider, useWeb3 } from "@3rdweb/hooks";
14+
import { PoweredBy } from "../shared/powered-by";
15+
import { ConnectWallet } from "@3rdweb/react";
16+
import { ThirdwebSDK, NFTMetadata, ModuleMetadata } from "@3rdweb/sdk";
17+
import { ChevronRightIcon, ChevronLeftIcon } from "@chakra-ui/icons";
18+
19+
const connectors = {
20+
injected: {},
21+
};
22+
23+
const Providers: React.FC = () => {
24+
return (
25+
<ThirdwebWeb3Provider supportedChainIds={[137]} connectors={connectors}>
26+
<ChakraProvider>
27+
<App />
28+
</ChakraProvider>
29+
</ThirdwebWeb3Provider>
30+
);
31+
};
32+
33+
const App: React.FC = () => {
34+
return <Layout title="Foo Bar" />;
35+
};
36+
37+
export default function runNFT() {
38+
ReactDOM.render(<Providers />, document.getElementById("root"));
39+
}
40+
41+
interface LayoutProps {
42+
title: string;
43+
}
44+
45+
const Layout: React.FC<LayoutProps> = ({ title }) => {
46+
const { address, provider } = useWeb3();
47+
48+
const collection = useMemo(() => {
49+
if (!provider) {
50+
return null;
51+
}
52+
return new ThirdwebSDK(provider).getNFTModule(
53+
"0x294261Ce5C5A5F8a709E1cA94D15b954bB42C2C8"
54+
);
55+
}, [provider]);
56+
57+
const [owned, setOwned] = useState<NFTMetadata[]>([]);
58+
const [metadata, setMetadata] = useState<ModuleMetadata>(undefined);
59+
60+
useEffect(() => {
61+
let __mounted = true;
62+
const getAsyncData = async () => {
63+
const _owned = await collection.getOwned(address);
64+
const _metadata = await collection.getMetadata();
65+
if (__mounted) {
66+
setOwned(_owned);
67+
setMetadata(_metadata);
68+
}
69+
};
70+
if (address) {
71+
getAsyncData();
72+
}
73+
return () => {
74+
__mounted = false;
75+
};
76+
}, [collection, address]);
77+
78+
const [currentIndex, setCurrentIndex] = useState(0);
79+
80+
const next = () => {
81+
setCurrentIndex((val) => {
82+
let next = val + 1;
83+
if (next >= owned.length) {
84+
next = 0;
85+
}
86+
return next;
87+
});
88+
};
89+
const prev = () => {
90+
setCurrentIndex((val) => {
91+
let prev = val - 1;
92+
if (prev < 0) {
93+
prev = owned.length - 1;
94+
}
95+
return prev;
96+
});
97+
};
98+
99+
return (
100+
<Flex flexDir="column" w="100vw" h="100vh" px={10} pb={10}>
101+
<Flex
102+
as="header"
103+
flexShrink={0}
104+
py={4}
105+
justify="space-between"
106+
align="center"
107+
>
108+
<Heading as="h1">{metadata?.metadata?.name || ""}</Heading>
109+
<ConnectWallet />
110+
</Flex>
111+
<Flex
112+
py={4}
113+
borderTop="1px solid rgba(0,0,0,.1)"
114+
as="main"
115+
flexGrow={1}
116+
justify="center"
117+
position="relative"
118+
overflow="hidden"
119+
>
120+
{owned.map((nft, idx) => (
121+
<Stack
122+
key={nft.id}
123+
justify="center"
124+
align="center"
125+
w="100%"
126+
position="absolute"
127+
left={"calc(100% * " + idx + ")"}
128+
transform={`translateX(${currentIndex * -100}%)`}
129+
transition="transform .5s ease"
130+
>
131+
<AspectRatio ratio={1} w="80%">
132+
<Box
133+
borderRadius="lg"
134+
overflow="hidden"
135+
bg="black"
136+
border="1px solid rgba(0, 0, 0, 0.1);"
137+
>
138+
<Image
139+
w="100%"
140+
h="100%"
141+
objectFit="contain"
142+
src={nft.image}
143+
alt={nft.name}
144+
/>
145+
</Box>
146+
</AspectRatio>
147+
<Heading fontWeight={500} fontSize="18px" size="sm" as="h3">
148+
{nft.name}
149+
</Heading>
150+
</Stack>
151+
))}
152+
<IconButton
153+
aria-label="next"
154+
icon={<ChevronRightIcon />}
155+
onClick={next}
156+
borderRadius="full"
157+
variant="ghost"
158+
position="absolute"
159+
top="50%"
160+
right="5px"
161+
transform="translateY(-50%)"
162+
/>
163+
<IconButton
164+
aria-label="previous"
165+
icon={<ChevronLeftIcon />}
166+
onClick={prev}
167+
borderRadius="full"
168+
variant="ghost"
169+
position="absolute"
170+
top="50%"
171+
left="5px"
172+
transform="translateY(-50%)"
173+
/>
174+
</Flex>
175+
<Flex as="footer" flexShrink={0} py={4} justify="flex-end">
176+
<PoweredBy />
177+
</Flex>
178+
</Flex>
179+
);
180+
};

0 commit comments

Comments
 (0)