From 684dc8434a2526bc372394a781d795a09e794616 Mon Sep 17 00:00:00 2001 From: Vitor Date: Thu, 30 Nov 2023 16:46:44 -0300 Subject: [PATCH] refactor: standardize components --- apps/www/content/docs/components/nonce.mdx | 1 + .../registry/styles/default/address.json | 2 +- .../registry/styles/default/blockie.json | 2 +- .../registry/styles/default/ens-address.json | 2 +- .../registry/styles/default/ens-avatar.json | 2 +- .../registry/styles/default/ens-name.json | 2 +- .../styles/default/erc721-metadata.json | 2 +- .../registry/styles/default/image-ipfs.json | 2 +- .../styles/default/is-wallet-connected.json | 2 +- .../public/registry/styles/default/nonce.json | 2 +- .../styles/default/transaction-status.json | 2 +- .../registry/styles/default/transaction.json | 2 +- .../styles/default/wallet-connect.json | 2 +- .../styles/default/wallet-disconnect.json | 2 +- apps/www/registry/default/buidl/address.tsx | 18 ++--- apps/www/registry/default/buidl/blockie.tsx | 55 ++++++++----- .../registry/default/buidl/ens-address.tsx | 12 +-- .../www/registry/default/buidl/ens-avatar.tsx | 33 +++++--- apps/www/registry/default/buidl/ens-name.tsx | 13 ++- .../default/buidl/erc20/erc20-selector.tsx | 7 +- .../default/buidl/erc721/erc721-metadata.tsx | 8 +- .../www/registry/default/buidl/image-ipfs.tsx | 81 ++++++++++++------- .../default/buidl/is-wallet-connected.tsx | 4 +- apps/www/registry/default/buidl/nonce.tsx | 10 +-- .../default/buidl/transaction-status.tsx | 24 +++--- .../registry/default/buidl/transaction.tsx | 2 +- .../registry/default/buidl/wallet-connect.tsx | 7 +- .../default/buidl/wallet-disconnect.tsx | 2 +- .../registry/default/example/address-demo.tsx | 7 +- .../registry/default/example/blockie-demo.tsx | 7 +- .../default/example/ens-avatar-demo.tsx | 6 +- .../default/example/image-ipfs-demo.tsx | 3 +- .../example/is-wallet-disconnected-demo.tsx | 3 +- .../default/example/transaction-demo.tsx | 43 ++++++++-- .../example/transaction-status-demo.tsx | 3 +- 35 files changed, 218 insertions(+), 157 deletions(-) diff --git a/apps/www/content/docs/components/nonce.mdx b/apps/www/content/docs/components/nonce.mdx index d9c71a9..a78dee7 100644 --- a/apps/www/content/docs/components/nonce.mdx +++ b/apps/www/content/docs/components/nonce.mdx @@ -59,4 +59,5 @@ import { Nonce } from "@/registry/default/buidl/nonce" ```tsx + ``` diff --git a/apps/www/public/registry/styles/default/address.json b/apps/www/public/registry/styles/default/address.json index 94cfc60..1638c73 100644 --- a/apps/www/public/registry/styles/default/address.json +++ b/apps/www/public/registry/styles/default/address.json @@ -6,7 +6,7 @@ "files": [ { "name": "address.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Copy } from \"lucide-react\"\nimport { useAccount, useNetwork, type Address as AddressType } from \"wagmi\"\nimport { mainnet } from \"wagmi/chains\"\n\nimport { cn } from \"@/lib/utils\"\nimport { toast } from \"@/registry/default/ui/use-toast\"\n\nexport interface AddressProps\n extends Omit, \"children\"> {\n address?: AddressType\n truncate?: boolean\n truncateAmount?: number\n link?: boolean\n copy?: boolean\n}\n\nconst AddressCopy = React.forwardRef<\n HTMLSpanElement,\n React.HTMLAttributes & {\n address: AddressType\n }\n>(({ address, className, children, ...props }, ref) => {\n return (\n {\n await navigator.clipboard.writeText(address)\n toast({\n title: \"Copied address\",\n description: \"The address has been copied to your clipboard.\",\n })\n }}\n {...props}\n >\n {children ?? address}\n Copy address\n \n \n )\n})\n\nAddressCopy.displayName = \"AddressCopy\"\n\nconst AddressLink = React.forwardRef<\n HTMLElement,\n React.HTMLAttributes & {\n address: AddressType\n }\n>(({ address, className, children, ...props }, ref) => {\n const { chain: currentChain } = useNetwork()\n\n // Use mainnet as default chain\n const chain = currentChain ?? mainnet\n\n return (\n \n {chain.blockExplorers?.default.url ? (\n \n {children ?? address}\n \n ) : (\n <>{children ?? address}\n )}\n \n )\n})\n\nAddressLink.displayName = \"AddressLink\"\n\nconst Address = React.forwardRef(\n (\n { address, className, truncate, truncateAmount = 4, link, copy, ...props },\n ref\n ) => {\n const { address: connectedAddress } = useAccount()\n\n const selectedAddress = address ?? connectedAddress\n\n const formattedAddress = React.useMemo(\n () =>\n truncate\n ? `${selectedAddress?.slice(\n 0,\n truncateAmount + 2\n )}...${selectedAddress?.slice(-Number(truncateAmount))}`\n : selectedAddress,\n [selectedAddress, truncate, truncateAmount]\n )\n\n if (!selectedAddress) {\n return null\n }\n\n if (link) {\n return (\n \n {copy ? (\n \n {formattedAddress}\n \n ) : (\n <>{formattedAddress}\n )}\n \n )\n }\n\n if (copy) {\n return (\n \n {formattedAddress}\n \n )\n }\n\n return (\n \n {formattedAddress}\n \n )\n }\n)\n\nAddress.displayName = \"Address\"\n\nexport { Address, AddressCopy, AddressLink }\n" + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Copy } from \"lucide-react\"\nimport { useAccount, useNetwork, type Address as AddressType } from \"wagmi\"\nimport { mainnet } from \"wagmi/chains\"\n\nimport { cn } from \"@/lib/utils\"\nimport { toast } from \"@/registry/default/ui/use-toast\"\n\nexport interface AddressProps\n extends Omit, \"children\"> {\n address?: AddressType\n truncate?: boolean\n truncateAmount?: number\n link?: boolean\n copy?: boolean\n}\n\nconst AddressCopy = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes & {\n address: AddressType\n }\n>(({ address, className, children, ...props }, ref) => {\n return (\n {\n await navigator.clipboard.writeText(address)\n toast({\n title: \"Copied address\",\n description: \"The address has been copied to your clipboard.\",\n })\n }}\n {...props}\n >\n {children ?? address}\n Copy address\n \n \n )\n})\n\nAddressCopy.displayName = \"AddressCopy\"\n\nconst AddressLink = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes & {\n address: AddressType\n }\n>(({ address, className, children, ...props }, ref) => {\n const { chain: currentChain } = useNetwork()\n\n // Use mainnet as default chain\n const chain = currentChain ?? mainnet\n\n return (\n \n {chain.blockExplorers?.default.url ? (\n \n {children ?? address}\n \n ) : (\n <>{children ?? address}\n )}\n \n )\n})\n\nAddressLink.displayName = \"AddressLink\"\n\nconst Address = React.forwardRef(\n (\n { address, className, truncate, truncateAmount = 4, link, copy, ...props },\n ref\n ) => {\n const { address: connectedAddress } = useAccount()\n\n const selectedAddress = address ?? connectedAddress\n\n const formattedAddress = React.useMemo(\n () =>\n truncate\n ? `${selectedAddress?.slice(\n 0,\n truncateAmount + 2\n )}...${selectedAddress?.slice(-Number(truncateAmount))}`\n : selectedAddress,\n [selectedAddress, truncate, truncateAmount]\n )\n\n if (!selectedAddress) {\n return null\n }\n\n if (link) {\n return (\n \n {copy ? (\n \n {formattedAddress}\n \n ) : (\n <>{formattedAddress}\n )}\n \n )\n }\n\n if (copy) {\n return (\n \n {formattedAddress}\n \n )\n }\n\n return (\n \n {formattedAddress}\n \n )\n }\n)\n\nAddress.displayName = \"Address\"\n\nexport { Address, AddressCopy, AddressLink }\n" } ], "type": "components:buidl" diff --git a/apps/www/public/registry/styles/default/blockie.json b/apps/www/public/registry/styles/default/blockie.json index 88c31b0..396dff0 100644 --- a/apps/www/public/registry/styles/default/blockie.json +++ b/apps/www/public/registry/styles/default/blockie.json @@ -6,7 +6,7 @@ "files": [ { "name": "blockie.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { VariantProps, cva } from \"class-variance-authority\"\nimport makeBlockie from \"ethereum-blockies-base64\"\nimport { useAccount } from \"wagmi\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst blockieVariants = cva(\"inline-block\", {\n variants: {\n variant: {\n default:\n \"rounded-full border-2 border-primary-foreground shadow-sm hover:shadow-md\",\n curved:\n \"rounded-md border-2 border-primary-foreground shadow-sm hover:shadow-md\",\n },\n size: {\n default: \"h-10 w-10\",\n sm: \"h-7 w-7\",\n lg: \"h-12 w-12\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n})\n\nexport type BlockieProps = React.HTMLAttributes &\n VariantProps & {\n address?: `0x${string}`\n }\n\nexport const Blockie = ({\n className,\n address,\n variant,\n size,\n ...props\n}: BlockieProps) => {\n const { address: connectedAddress } = useAccount()\n const selectedAddress = address ?? connectedAddress\n\n if (!selectedAddress) return null\n\n return (\n \n )\n}\n" + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { VariantProps, cva } from \"class-variance-authority\"\nimport makeBlockie from \"ethereum-blockies-base64\"\nimport { useAccount } from \"wagmi\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Skeleton } from \"@/registry/default/ui/skeleton\"\n\nconst blockieVariants = cva(\"inline-block\", {\n variants: {\n variant: {\n default:\n \"rounded-full border-2 border-primary-foreground shadow-sm hover:shadow-md\",\n curved:\n \"rounded-md border-2 border-primary-foreground shadow-sm hover:shadow-md\",\n },\n size: {\n default: \"h-10 w-10\",\n sm: \"h-7 w-7\",\n lg: \"h-12 w-12\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n})\n\nexport type BlockieProps = React.HTMLAttributes &\n VariantProps & {\n address?: `0x${string}`\n }\n\nconst Blockie = React.forwardRef(\n ({ className, address, variant, size, ...props }, ref) => {\n const [isLoading, setIsLoading] = React.useState(true)\n const { address: connectedAddress, isConnecting } = useAccount()\n const selectedAddress = address ?? connectedAddress ?? \"0x0\"\n\n return (\n <>\n {isLoading || isConnecting ? (\n \n ) : null}\n setIsLoading(false)}\n className={cn(\n blockieVariants({ variant, size, className }),\n (isLoading || isConnecting) && \"hidden\"\n )}\n src={makeBlockie(selectedAddress)}\n {...props}\n />\n \n )\n }\n)\n\nBlockie.displayName = \"Blockie\"\n\nexport { Blockie }\n" } ], "type": "components:buidl" diff --git a/apps/www/public/registry/styles/default/ens-address.json b/apps/www/public/registry/styles/default/ens-address.json index f6eaa54..bbf01e0 100644 --- a/apps/www/public/registry/styles/default/ens-address.json +++ b/apps/www/public/registry/styles/default/ens-address.json @@ -6,7 +6,7 @@ "files": [ { "name": "ens-address.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { useEnsAddress } from \"wagmi\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Address, AddressProps } from \"@/registry/default/buidl/address\"\nimport { Skeleton } from \"@/registry/default/ui/skeleton\"\n\nconst ErrorMessage = ({ error }: { error: Error | null }) => {\n return (\n
\n {error?.message ?? \"Error while fetching fee data\"}\n
\n )\n}\n\ninterface EnsAddressProps extends Omit {\n name: string\n}\n\nconst EnsAddress = React.forwardRef(\n ({ name, className, ...props }, ref) => {\n const { data, isLoading, isSuccess, isError, error } = useEnsAddress({\n chainId: 1,\n name,\n })\n\n if (isLoading) {\n return (\n \n )\n }\n\n if (isSuccess && data) {\n return (\n
\n )\n }\n\n if (isError) {\n return \n }\n\n return null\n }\n)\n\nEnsAddress.displayName = \"EnsAddress\"\n\nexport { EnsAddress }\n" + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { useEnsAddress } from \"wagmi\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Address, AddressProps } from \"@/registry/default/buidl/address\"\nimport { Skeleton } from \"@/registry/default/ui/skeleton\"\n\nconst ErrorMessage = ({ error }: { error: Error | null }) => {\n return (\n
\n {error?.message ?? \"Error while fetching fee data\"}\n
\n )\n}\n\ninterface EnsAddressProps extends Omit {\n name: string\n}\n\nconst EnsAddress = React.forwardRef(\n ({ name, className, ...props }, ref) => {\n const { data, isLoading, isSuccess, isError, error } = useEnsAddress({\n chainId: 1,\n name,\n })\n\n if (isError) {\n return \n }\n\n if (isLoading || !data) {\n return (\n \n )\n }\n\n if (isSuccess && data) {\n return (\n
\n )\n }\n\n return null\n }\n)\n\nEnsAddress.displayName = \"EnsAddress\"\n\nexport { EnsAddress }\n" } ], "type": "components:buidl" diff --git a/apps/www/public/registry/styles/default/ens-avatar.json b/apps/www/public/registry/styles/default/ens-avatar.json index f1a308f..c6e32cd 100644 --- a/apps/www/public/registry/styles/default/ens-avatar.json +++ b/apps/www/public/registry/styles/default/ens-avatar.json @@ -6,7 +6,7 @@ "files": [ { "name": "ens-avatar.tsx", - "content": "\"useClient\"\n\nimport * as React from \"react\"\nimport { VariantProps, cva } from \"class-variance-authority\"\nimport { useAccount, useEnsAvatar, useEnsName } from \"wagmi\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Blockie } from \"@/registry/default/buidl/blockie\"\nimport { Skeleton } from \"@/registry/default/ui/skeleton\"\n\nconst ensAvatarVariants = cva(\"inline-block\", {\n variants: {\n variant: {\n default:\n \"rounded-full border-2 border-primary-foreground shadow-sm hover:shadow-md\",\n curved:\n \"rounded-md border-2 border-primary-foreground shadow-sm hover:shadow-md\",\n },\n size: {\n default: \"h-10 w-10\",\n sm: \"h-7 w-7\",\n lg: \"h-12 w-12\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n})\n\ninterface EnsAvatarProps\n extends React.HTMLAttributes,\n VariantProps {\n address?: `0x${string}`\n name?: string\n displayLoading?: boolean\n}\n\nconst EnsAvatar = React.forwardRef(\n (\n {\n className,\n address,\n name,\n variant,\n size,\n displayLoading = true,\n ...props\n },\n ref\n ) => {\n const { address: connectedAddress } = useAccount()\n const selectedAddress = address ?? connectedAddress\n\n const { data: dataEnsName, isLoading: isLoadingEnsName } = useEnsName({\n chainId: 1,\n address: selectedAddress,\n enabled: !name && !!selectedAddress,\n })\n\n const ensName = name ?? dataEnsName\n\n const { data: dataEnsAvatar, isLoading: isLoadingEnsAvatar } = useEnsAvatar(\n {\n chainId: 1,\n name: ensName,\n enabled: !!ensName,\n }\n )\n\n if (\n displayLoading &&\n (isLoadingEnsName || isLoadingEnsAvatar || !selectedAddress)\n ) {\n return (\n \n )\n }\n\n if (dataEnsAvatar) {\n return (\n \n )\n }\n\n return (\n \n )\n }\n)\n\nEnsAvatar.displayName = \"EnsAvatar\"\n\nexport { EnsAvatar }\n" + "content": "\"useClient\"\n\nimport * as React from \"react\"\nimport { VariantProps, cva } from \"class-variance-authority\"\nimport { useAccount, useEnsAvatar, useEnsName } from \"wagmi\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Blockie } from \"@/registry/default/buidl/blockie\"\nimport { Skeleton } from \"@/registry/default/ui/skeleton\"\n\nconst ensAvatarVariants = cva(\"inline-block\", {\n variants: {\n variant: {\n default:\n \"rounded-full border-2 border-primary-foreground shadow-sm hover:shadow-md\",\n curved:\n \"rounded-md border-2 border-primary-foreground shadow-sm hover:shadow-md\",\n },\n size: {\n default: \"h-10 w-10\",\n sm: \"h-7 w-7\",\n lg: \"h-12 w-12\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n})\n\ninterface EnsAvatarProps\n extends React.HTMLAttributes,\n VariantProps {\n address?: `0x${string}`\n name?: string\n displayLoading?: boolean\n}\n\nconst EnsAvatar = React.forwardRef(\n (\n {\n className,\n address,\n name,\n variant,\n size,\n displayLoading = true,\n ...props\n },\n ref\n ) => {\n const [isLoadingImg, setIsLoadingImg] = React.useState(true)\n\n const { address: connectedAddress } = useAccount()\n const selectedAddress = address ?? connectedAddress\n\n const { data: dataEnsName, isLoading: isLoadingEnsName } = useEnsName({\n chainId: 1,\n address: selectedAddress,\n enabled: !name && !!selectedAddress,\n })\n\n const ensName = name ?? dataEnsName\n\n const { data: dataEnsAvatar, isLoading: isLoadingEnsAvatar } = useEnsAvatar(\n {\n chainId: 1,\n name: ensName,\n enabled: !!ensName,\n }\n )\n\n if (\n displayLoading &&\n (isLoadingEnsName || isLoadingEnsAvatar || !selectedAddress)\n ) {\n return (\n \n )\n }\n\n if (dataEnsAvatar) {\n return (\n <>\n {isLoadingImg ? (\n \n ) : null}\n {\n setIsLoadingImg(false)\n }}\n src={dataEnsAvatar}\n {...props}\n />\n \n )\n }\n\n return (\n \n )\n }\n)\n\nEnsAvatar.displayName = \"EnsAvatar\"\n\nexport { EnsAvatar }\n" } ], "type": "components:buidl" diff --git a/apps/www/public/registry/styles/default/ens-name.json b/apps/www/public/registry/styles/default/ens-name.json index e9225a2..e81a1e8 100644 --- a/apps/www/public/registry/styles/default/ens-name.json +++ b/apps/www/public/registry/styles/default/ens-name.json @@ -6,7 +6,7 @@ "files": [ { "name": "ens-name.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { useAccount, useEnsName } from \"wagmi\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Address } from \"@/registry/default/buidl/address\"\n\nimport { Skeleton } from \"../ui/skeleton\"\n\ninterface EnsNameProps extends React.HTMLAttributes {\n address?: `0x${string}`\n}\n\nconst EnsName = React.forwardRef(\n ({ address, className, ...props }, ref) => {\n const { address: connectedAddress } = useAccount()\n const selectedAddress = address ?? connectedAddress\n\n const { data, isLoading, isSuccess } = useEnsName({\n chainId: 1,\n address: selectedAddress,\n enabled: !!selectedAddress,\n })\n\n if (isSuccess && data) {\n return (\n \n {data}\n \n )\n }\n\n if (isLoading) {\n return \n }\n\n return (\n
\n )\n }\n)\n\nEnsName.displayName = \"EnsName\"\n\nexport { EnsName }\n" + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { useAccount, useEnsName } from \"wagmi\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Address } from \"@/registry/default/buidl/address\"\nimport { Skeleton } from \"@/registry/default/ui/skeleton\"\n\ninterface EnsNameProps extends React.HTMLAttributes {\n address?: `0x${string}`\n}\n\nconst EnsName = React.forwardRef(\n ({ address, className, ...props }, ref) => {\n const { address: connectedAddress } = useAccount()\n const selectedAddress = address ?? connectedAddress\n\n const { data, isLoading, isSuccess } = useEnsName({\n chainId: 1,\n address: selectedAddress,\n enabled: !!selectedAddress,\n })\n\n if (isSuccess && data) {\n return (\n
\n {data}\n
\n )\n }\n\n if (isLoading || !selectedAddress) {\n return \n }\n\n return (\n
\n )\n }\n)\n\nEnsName.displayName = \"EnsName\"\n\nexport { EnsName }\n" } ], "type": "components:buidl" diff --git a/apps/www/public/registry/styles/default/erc721-metadata.json b/apps/www/public/registry/styles/default/erc721-metadata.json index cb694ad..9b0942b 100644 --- a/apps/www/public/registry/styles/default/erc721-metadata.json +++ b/apps/www/public/registry/styles/default/erc721-metadata.json @@ -6,7 +6,7 @@ "files": [ { "name": "erc721-metadata.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { useContractRead, useQuery, type Address } from \"wagmi\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Skeleton } from \"@/registry/default/ui/skeleton\"\n\nconst erc721TokenUriAbi = [\n {\n inputs: [\n {\n internalType: \"uint256\",\n name: \"tokenId\",\n type: \"uint256\",\n },\n ],\n name: \"tokenURI\",\n outputs: [\n {\n internalType: \"string\",\n name: \"\",\n type: \"string\",\n },\n ],\n stateMutability: \"view\",\n type: \"function\",\n },\n] as const\n\ninterface useERC721MetadataProps {\n tokenId: bigint\n ipfsGatewayUrl?: string\n address?: Address\n chainId?: number\n}\ninterface IERC721Metadata {\n name?: string\n description?: string\n image: string\n attributes: Array<{\n trait_type: string\n value: string\n }>\n}\n\nfunction useERC721Metadata({\n address,\n chainId,\n tokenId,\n ipfsGatewayUrl = \"https://ipfs.io/ipfs\",\n}: useERC721MetadataProps) {\n const { data, isLoading, isError, error } = useContractRead({\n address,\n abi: erc721TokenUriAbi,\n functionName: \"tokenURI\",\n args: [tokenId],\n chainId,\n })\n\n const metadataQuery = useQuery(\n [\"erc721-metadata\", address, chainId, tokenId, data],\n {\n queryFn: async () => {\n if (!data) throw new Error(\"No tokenUri found\")\n const uri = data.replace(\"ipfs://\", \"\")\n const response = await fetch(`${ipfsGatewayUrl}/${uri}`)\n const json = (await response.json()) as IERC721Metadata\n\n if (!json.image) throw new Error(\"No image found in metadata\")\n if (!json.attributes) throw new Error(\"No attributes found in metadata\")\n\n json.image = json.image.startsWith(\"ipfs://\")\n ? json.image.replace(\"ipfs://\", `${ipfsGatewayUrl}/`)\n : json.image\n return json\n },\n enabled: !!data,\n }\n )\n\n return {\n isLoading: isLoading || metadataQuery.isLoading,\n isError: isError || metadataQuery.isError,\n error: error || metadataQuery.error,\n data: metadataQuery.data,\n }\n}\n\nconst ErrorMessage = ({ error }: { error: Error | null }) => {\n return (\n
\n {error?.message ?? \"Error while fetching ERC721 data\"}\n
\n )\n}\n\nexport type Erc721MetadataProps = React.HTMLAttributes & {\n address: `0x${string}`\n tokenId: number | string | bigint\n chainId?: number\n ipfsGatewayUrl?: string\n}\n\nconst Erc721MetadataImage = React.forwardRef<\n HTMLImageElement,\n Erc721MetadataProps\n>(({ chainId, address, tokenId, ipfsGatewayUrl, ...props }, ref) => {\n const { data, isLoading, isError, error } = useERC721Metadata({\n address,\n chainId,\n tokenId: BigInt(tokenId),\n ipfsGatewayUrl,\n })\n\n console.log(data)\n\n if (isLoading) {\n return \n }\n\n if (isError) {\n return \n }\n\n if (data?.image === undefined) {\n return null\n }\n\n return {`${tokenId}\n})\n\nErc721MetadataImage.displayName = \"Erc721MetadataImage\"\n\nexport { Erc721MetadataImage }\n" + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { useContractRead, useQuery, type Address } from \"wagmi\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Skeleton } from \"@/registry/default/ui/skeleton\"\n\nconst erc721TokenUriAbi = [\n {\n inputs: [\n {\n internalType: \"uint256\",\n name: \"tokenId\",\n type: \"uint256\",\n },\n ],\n name: \"tokenURI\",\n outputs: [\n {\n internalType: \"string\",\n name: \"\",\n type: \"string\",\n },\n ],\n stateMutability: \"view\",\n type: \"function\",\n },\n] as const\n\ninterface useERC721MetadataProps {\n tokenId: bigint\n ipfsGatewayUrl?: string\n address?: Address\n chainId?: number\n}\ninterface IERC721Metadata {\n name?: string\n description?: string\n image: string\n attributes: Array<{\n trait_type: string\n value: string\n }>\n}\n\nfunction useERC721Metadata({\n address,\n chainId,\n tokenId,\n ipfsGatewayUrl = \"https://ipfs.io/ipfs/\",\n}: useERC721MetadataProps) {\n const { data, isLoading, isError, error } = useContractRead({\n address,\n abi: erc721TokenUriAbi,\n functionName: \"tokenURI\",\n args: [tokenId],\n chainId,\n })\n\n const metadataQuery = useQuery(\n [\"erc721-metadata\", address, chainId, tokenId, data],\n {\n queryFn: async () => {\n if (!data) throw new Error(\"No tokenUri found\")\n const uri = data.replace(\"ipfs://\", \"\")\n const response = await fetch(`${ipfsGatewayUrl}${uri}`)\n const json = (await response.json()) as IERC721Metadata\n\n if (!json.image) throw new Error(\"No image found in metadata\")\n if (!json.attributes) throw new Error(\"No attributes found in metadata\")\n\n json.image = json.image.startsWith(\"ipfs://\")\n ? json.image.replace(\"ipfs://\", `${ipfsGatewayUrl}`)\n : json.image\n return json\n },\n enabled: !!data,\n }\n )\n\n return {\n isLoading: isLoading || metadataQuery.isLoading,\n isError: isError || metadataQuery.isError,\n error: error || metadataQuery.error,\n data: metadataQuery.data,\n }\n}\n\nconst ErrorMessage = ({ error }: { error: Error | null }) => {\n return (\n
\n {error?.message ?? \"Error while fetching ERC721 data\"}\n
\n )\n}\n\nexport type Erc721MetadataProps = React.HTMLAttributes & {\n address: `0x${string}`\n tokenId: number | string | bigint\n chainId?: number\n ipfsGatewayUrl?: string\n}\n\nconst Erc721MetadataImage = React.forwardRef<\n HTMLImageElement,\n Erc721MetadataProps\n>(({ chainId, address, tokenId, ipfsGatewayUrl, ...props }, ref) => {\n const { data, isLoading, isError, error } = useERC721Metadata({\n address,\n chainId,\n tokenId: BigInt(tokenId),\n ipfsGatewayUrl,\n })\n\n if (isLoading) {\n return \n }\n\n if (isError) {\n return \n }\n\n if (data?.image === undefined) {\n return null\n }\n\n return {`${tokenId}\n})\n\nErc721MetadataImage.displayName = \"Erc721MetadataImage\"\n\nexport { Erc721MetadataImage }\n" } ], "folder": "erc721", diff --git a/apps/www/public/registry/styles/default/image-ipfs.json b/apps/www/public/registry/styles/default/image-ipfs.json index cc706e0..d997aee 100644 --- a/apps/www/public/registry/styles/default/image-ipfs.json +++ b/apps/www/public/registry/styles/default/image-ipfs.json @@ -6,7 +6,7 @@ "files": [ { "name": "image-ipfs.tsx", - "content": "import { useMemo } from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype ImageIpfs = React.HTMLAttributes & {\n src: string\n alt: string\n width?: string\n height?: string\n}\n\nexport const ImageIpfs = ({\n className,\n src,\n alt,\n width,\n height,\n}: ImageIpfs) => {\n const classes = cn(className)\n\n const imgSrc = useMemo(\n () =>\n src?.startsWith(\"ipfs://\")\n ? src.replace(\"ipfs://\", \"https://gateway.ipfs.io/ipfs/\")\n : src,\n [src]\n )\n\n if (!imgSrc) return null\n\n return (\n \n )\n}\n" + "content": "import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Skeleton } from \"@/registry/default/ui/skeleton\"\n\nconst ErrorMessage = ({ error }: { error: Error | null }) => {\n return (\n
\n {error?.message ?? \"Error while fetching image\"}\n
\n )\n}\n\ninterface ImageIpfsProps extends React.HTMLAttributes {\n ipfsGatewayUrl?: string\n src: string\n alt: string\n}\n\nconst ImageIpfs = React.forwardRef(\n (\n { className, src, alt, ipfsGatewayUrl = \"https://ipfs.io/ipfs/\", ...props },\n ref\n ) => {\n const [isLoading, setIsLoading] = React.useState(true)\n const [isError, setIsError] = React.useState(false)\n\n const imgSrc = React.useMemo(\n () =>\n src?.startsWith(\"ipfs://\")\n ? src.replace(\"ipfs://\", ipfsGatewayUrl)\n : src,\n [src, ipfsGatewayUrl]\n )\n\n return (\n <>\n {isError ? (\n \n ) : isLoading ? (\n \n ) : null}\n setIsLoading(false)}\n onError={() => setIsError(true)}\n className={cn((isLoading || isError) && \"hidden\", className)}\n {...props}\n />\n \n )\n }\n)\n\nImageIpfs.displayName = \"ImageIpfs\"\n\nexport { ImageIpfs }\n" } ], "type": "components:buidl" diff --git a/apps/www/public/registry/styles/default/is-wallet-connected.json b/apps/www/public/registry/styles/default/is-wallet-connected.json index 3393f1c..4fa770a 100644 --- a/apps/www/public/registry/styles/default/is-wallet-connected.json +++ b/apps/www/public/registry/styles/default/is-wallet-connected.json @@ -6,7 +6,7 @@ "files": [ { "name": "is-wallet-connected.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { useAccount } from \"wagmi\"\n\nconst IsWalletConnected = ({ children }: { children: React.ReactNode }) => {\n const { isConnected } = useAccount()\n\n if (isConnected) return <>{children}\n\n return null\n}\n\nexport { IsWalletConnected }\n" + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { useAccount } from \"wagmi\"\n\nconst IsWalletConnected = ({ children }: { children: React.ReactNode }) => {\n const { isConnected, isConnecting } = useAccount()\n\n if (isConnected || isConnecting) return <>{children}\n\n return null\n}\n\nexport { IsWalletConnected }\n" } ], "type": "components:buidl" diff --git a/apps/www/public/registry/styles/default/nonce.json b/apps/www/public/registry/styles/default/nonce.json index 167b4bc..51c0ad8 100644 --- a/apps/www/public/registry/styles/default/nonce.json +++ b/apps/www/public/registry/styles/default/nonce.json @@ -6,7 +6,7 @@ "files": [ { "name": "nonce.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport {\n useAccount,\n useChainId,\n usePublicClient,\n useQuery,\n type PublicClient,\n} from \"wagmi\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Skeleton } from \"@/registry/default/ui/skeleton\"\n\ninterface NonceProps extends React.HTMLAttributes {\n address?: `0x${string}`\n chainId?: number\n}\n\nconst useNonce = ({\n address,\n publicClient,\n}: Pick & { publicClient: PublicClient }) => {\n return useQuery([\"wallet-nonce\", address, publicClient.chain.id], {\n queryFn: () => {\n if (!address) return\n return publicClient?.getTransactionCount({\n address,\n })\n },\n enabled: !!address && !!publicClient,\n })\n}\n\nconst Nonce = React.forwardRef(\n ({ className, address, chainId, ...props }: NonceProps) => {\n const connectedChainId = useChainId()\n const selectedChainId = chainId ?? connectedChainId\n\n const publicClient = usePublicClient({\n chainId: selectedChainId,\n })\n\n const { address: connectedAddress } = useAccount()\n const selectedAddress = address ?? connectedAddress\n\n const { data, isLoading } = useNonce({\n publicClient,\n address: selectedAddress,\n })\n\n if (isLoading) {\n return \n }\n\n return (\n \n {data}\n \n )\n }\n)\n\nNonce.displayName = \"Nonce\"\n\nexport { Nonce }\n" + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport {\n useAccount,\n useChainId,\n usePublicClient,\n useQuery,\n type PublicClient,\n} from \"wagmi\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Skeleton } from \"@/registry/default/ui/skeleton\"\n\ninterface NonceProps extends React.HTMLAttributes {\n address?: `0x${string}`\n chainId?: number\n}\n\nconst useNonce = ({\n address,\n publicClient,\n}: Pick & { publicClient: PublicClient }) => {\n return useQuery([\"wallet-nonce\", address, publicClient.chain.id], {\n queryFn: () => {\n if (!address) return\n return publicClient?.getTransactionCount({\n address,\n })\n },\n enabled: !!address && !!publicClient,\n })\n}\n\nconst Nonce = React.forwardRef(\n ({ className, address, chainId, ...props }, ref) => {\n const connectedChainId = useChainId()\n const selectedChainId = chainId ?? connectedChainId\n\n const publicClient = usePublicClient({\n chainId: selectedChainId,\n })\n\n const { address: connectedAddress } = useAccount()\n const selectedAddress = address ?? connectedAddress\n\n const { data, isLoading } = useNonce({\n publicClient,\n address: selectedAddress,\n })\n\n if (isLoading) {\n return \n }\n\n return (\n
\n {data}\n
\n )\n }\n)\n\nNonce.displayName = \"Nonce\"\n\nexport { Nonce }\n" } ], "type": "components:buidl" diff --git a/apps/www/public/registry/styles/default/transaction-status.json b/apps/www/public/registry/styles/default/transaction-status.json index 832a3b0..1698af9 100644 --- a/apps/www/public/registry/styles/default/transaction-status.json +++ b/apps/www/public/registry/styles/default/transaction-status.json @@ -6,7 +6,7 @@ "files": [ { "name": "transaction-status.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { useChainId, useWaitForTransaction } from \"wagmi\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Skeleton } from \"@/registry/default/ui/skeleton\"\n\nconst ErrorMessage = ({ error }: { error: Error | null }) => {\n return (\n
\n {error?.message ?? \"Error while fetching ERC721 data\"}\n
\n )\n}\n\nconst TransactionStatus = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes & {\n hash: `0x${string}`\n chainId?: number\n }\n>(({ chainId: selectedChainId, children, className, hash, ...props }, ref) => {\n const currentChainId = useChainId()\n\n const { isLoading, isSuccess, isError, error, isFetching } =\n useWaitForTransaction({\n hash: hash,\n chainId: selectedChainId ?? currentChainId,\n })\n\n if (isFetching)\n return \n\n if (isError) return \n\n return (\n <>\n \n {(isLoading || isSuccess) && (\n <>\n {isLoading && \"Processing transaction...\"}\n {isSuccess && \"Transaction successful!\"}\n {children}\n \n )}\n \n \n )\n})\n\nTransactionStatus.displayName = \"TransactionStatus\"\n\nexport { TransactionStatus }\n" + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { useChainId, useWaitForTransaction } from \"wagmi\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Skeleton } from \"@/registry/default/ui/skeleton\"\n\nconst ErrorMessage = ({ error }: { error: Error | null }) => {\n return (\n
\n {error?.message ?? \"Error while fetching ERC721 data\"}\n
\n )\n}\n\nconst TransactionStatus = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes & {\n hash: `0x${string}`\n chainId?: number\n }\n>(({ chainId: selectedChainId, children, className, hash, ...props }, ref) => {\n const currentChainId = useChainId()\n\n const { isLoading, isSuccess, isError, error, isFetching } =\n useWaitForTransaction({\n hash: hash,\n chainId: selectedChainId ?? currentChainId,\n })\n\n if (isFetching)\n return \n\n if (isError) return \n\n return (\n \n {isLoading && \"Processing transaction...\"}\n {isSuccess && \"Transaction successful!\"}\n {children}\n \n )\n})\n\nTransactionStatus.displayName = \"TransactionStatus\"\n\nexport { TransactionStatus }\n" } ], "type": "components:buidl" diff --git a/apps/www/public/registry/styles/default/transaction.json b/apps/www/public/registry/styles/default/transaction.json index 6c5a845..78d29a5 100644 --- a/apps/www/public/registry/styles/default/transaction.json +++ b/apps/www/public/registry/styles/default/transaction.json @@ -6,7 +6,7 @@ "files": [ { "name": "transaction.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { useTransaction } from \"wagmi\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Skeleton } from \"@/registry/default/ui/skeleton\"\n\ninterface TransactionProps\n extends Omit, \"children\"> {\n hash: `0x${string}`\n chainId?: number\n displayLoading?: boolean\n displayError?: boolean\n}\n\nconst ErrorMessage = ({ error }: { error: Error | null }) => {\n return (\n
\n {error?.message ?? \"Error while fetching transaction data\"}\n
\n )\n}\n\nconst TransactionBlockHash = React.forwardRef(\n (\n {\n chainId,\n hash,\n className,\n displayError = true,\n displayLoading = true,\n ...props\n },\n ref\n ) => {\n const { data, isSuccess, isLoading, isError, error } = useTransaction({\n hash,\n chainId,\n })\n\n if (isLoading && displayLoading)\n return \n\n if (isError && displayError) return \n\n if (isSuccess) {\n return (\n
\n {data?.blockHash}\n
\n )\n }\n\n return null\n }\n)\n\nTransactionBlockHash.displayName = \"TransactionBlockHash\"\n\nconst TransactionBlockNumber = React.forwardRef<\n HTMLDivElement,\n TransactionProps\n>(\n (\n {\n chainId,\n hash,\n className,\n displayError = true,\n displayLoading = true,\n ...props\n },\n ref\n ) => {\n const { data, isSuccess, isLoading, isError, error } = useTransaction({\n hash,\n chainId,\n })\n\n if (isLoading && displayLoading)\n return \n\n if (isError && displayError) return \n\n if (isSuccess) {\n return (\n
\n {data?.blockNumber.toString()}\n
\n )\n }\n\n return null\n }\n)\n\nTransactionBlockNumber.displayName = \"TransactionBlockNumber\"\n\nconst TransactionFrom = React.forwardRef(\n (\n {\n chainId,\n hash,\n className,\n displayError = true,\n displayLoading = true,\n ...props\n },\n ref\n ) => {\n const { data, isSuccess, isLoading, isError, error } = useTransaction({\n hash,\n chainId,\n })\n\n if (isLoading && displayLoading)\n return \n\n if (isError && displayError) return \n\n if (isSuccess) {\n return (\n
\n {data?.from}\n
\n )\n }\n\n return null\n }\n)\n\nTransactionFrom.displayName = \"TransactionFrom\"\n\nconst TransactionTo = React.forwardRef(\n (\n {\n chainId,\n hash,\n className,\n displayError = true,\n displayLoading = true,\n ...props\n },\n ref\n ) => {\n const { data, isSuccess, isLoading, isError, error } = useTransaction({\n hash,\n chainId,\n })\n\n if (isLoading && displayLoading)\n return \n\n if (isError && displayError) return \n\n if (isSuccess) {\n return (\n
\n {data?.from}\n
\n )\n }\n\n return null\n }\n)\n\nTransactionTo.displayName = \"TransactionTo\"\n\nconst TransactionGas = React.forwardRef(\n (\n {\n chainId,\n hash,\n className,\n displayError = true,\n displayLoading = true,\n ...props\n },\n ref\n ) => {\n const { data, isSuccess, isLoading, isError, error } = useTransaction({\n hash,\n chainId,\n })\n\n if (isLoading && displayLoading)\n return \n\n if (isError && displayError) return \n\n if (isSuccess) {\n return (\n
\n {data?.gas.toString()}\n
\n )\n }\n\n return null\n }\n)\n\nTransactionGas.displayName = \"TransactionGas\"\n\nconst TransactionGasPrice = React.forwardRef(\n (\n {\n chainId,\n hash,\n className,\n displayError = true,\n displayLoading = true,\n ...props\n },\n ref\n ) => {\n const { data, isSuccess, isLoading, isError, error } = useTransaction({\n hash,\n chainId,\n })\n\n if (isLoading && displayLoading)\n return \n\n if (isError && displayError) return \n\n if (isSuccess) {\n return (\n
\n {data?.gasPrice?.toString()}\n
\n )\n }\n\n return null\n }\n)\n\nTransactionGasPrice.displayName = \"TransactionGasPrice\"\n\nconst TransactionNonce = React.forwardRef(\n (\n {\n chainId,\n hash,\n className,\n displayError = true,\n displayLoading = true,\n ...props\n },\n ref\n ) => {\n const { data, isSuccess, isLoading, isError, error } = useTransaction({\n hash,\n chainId,\n })\n\n if (isLoading && displayLoading)\n return \n\n if (isError && displayError) return \n\n if (isSuccess) {\n return (\n
\n {data?.nonce.toString()}\n
\n )\n }\n return null\n }\n)\n\nTransactionNonce.displayName = \"TransactionNonce\"\n\nexport {\n TransactionBlockHash,\n TransactionBlockNumber,\n TransactionFrom,\n TransactionGas,\n TransactionGasPrice,\n TransactionNonce,\n TransactionTo,\n}\n" + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { useTransaction } from \"wagmi\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Skeleton } from \"@/registry/default/ui/skeleton\"\n\ninterface TransactionProps\n extends Omit, \"children\"> {\n hash: `0x${string}`\n chainId?: number\n displayLoading?: boolean\n displayError?: boolean\n}\n\nconst ErrorMessage = ({ error }: { error: Error | null }) => {\n return (\n
\n {error?.message ?? \"Error while fetching transaction data\"}\n
\n )\n}\n\nconst TransactionBlockHash = React.forwardRef(\n (\n {\n chainId,\n hash,\n className,\n displayError = true,\n displayLoading = true,\n ...props\n },\n ref\n ) => {\n const { data, isSuccess, isLoading, isError, error } = useTransaction({\n hash,\n chainId,\n })\n\n if (isLoading && displayLoading)\n return \n\n if (isError && displayError) return \n\n if (isSuccess) {\n return (\n
\n {data?.blockHash}\n
\n )\n }\n\n return null\n }\n)\n\nTransactionBlockHash.displayName = \"TransactionBlockHash\"\n\nconst TransactionBlockNumber = React.forwardRef<\n HTMLDivElement,\n TransactionProps\n>(\n (\n {\n chainId,\n hash,\n className,\n displayError = true,\n displayLoading = true,\n ...props\n },\n ref\n ) => {\n const { data, isSuccess, isLoading, isError, error } = useTransaction({\n hash,\n chainId,\n })\n\n if (isLoading && displayLoading)\n return \n\n if (isError && displayError) return \n\n if (isSuccess) {\n return (\n
\n {data?.blockNumber.toString()}\n
\n )\n }\n\n return null\n }\n)\n\nTransactionBlockNumber.displayName = \"TransactionBlockNumber\"\n\nconst TransactionFrom = React.forwardRef(\n (\n {\n chainId,\n hash,\n className,\n displayError = true,\n displayLoading = true,\n ...props\n },\n ref\n ) => {\n const { data, isSuccess, isLoading, isError, error } = useTransaction({\n hash,\n chainId,\n })\n\n if (isLoading && displayLoading)\n return \n\n if (isError && displayError) return \n\n if (isSuccess) {\n return (\n
\n {data?.from}\n
\n )\n }\n\n return null\n }\n)\n\nTransactionFrom.displayName = \"TransactionFrom\"\n\nconst TransactionTo = React.forwardRef(\n (\n {\n chainId,\n hash,\n className,\n displayError = true,\n displayLoading = true,\n ...props\n },\n ref\n ) => {\n const { data, isSuccess, isLoading, isError, error } = useTransaction({\n hash,\n chainId,\n })\n\n if (isLoading && displayLoading)\n return \n\n if (isError && displayError) return \n\n if (isSuccess) {\n return (\n
\n {data?.from}\n
\n )\n }\n\n return null\n }\n)\n\nTransactionTo.displayName = \"TransactionTo\"\n\nconst TransactionGas = React.forwardRef(\n (\n {\n chainId,\n hash,\n className,\n displayError = true,\n displayLoading = true,\n ...props\n },\n ref\n ) => {\n const { data, isSuccess, isLoading, isError, error } = useTransaction({\n hash,\n chainId,\n })\n\n if (isLoading && displayLoading)\n return \n\n if (isError && displayError) return \n\n if (isSuccess) {\n return (\n
\n {data?.gas.toString()}\n
\n )\n }\n\n return null\n }\n)\n\nTransactionGas.displayName = \"TransactionGas\"\n\nconst TransactionGasPrice = React.forwardRef(\n (\n {\n chainId,\n hash,\n className,\n displayError = true,\n displayLoading = true,\n ...props\n },\n ref\n ) => {\n const { data, isSuccess, isLoading, isError, error } = useTransaction({\n hash,\n chainId,\n })\n\n if (isLoading && displayLoading)\n return \n\n if (isError && displayError) return \n\n if (isSuccess) {\n return (\n
\n {data?.gasPrice?.toString()}\n
\n )\n }\n\n return null\n }\n)\n\nTransactionGasPrice.displayName = \"TransactionGasPrice\"\n\nconst TransactionNonce = React.forwardRef(\n (\n {\n chainId,\n hash,\n className,\n displayError = true,\n displayLoading = true,\n ...props\n },\n ref\n ) => {\n const { data, isSuccess, isLoading, isError, error } = useTransaction({\n hash,\n chainId,\n })\n\n if (isLoading && displayLoading)\n return \n\n if (isError && displayError) return \n\n if (isSuccess) {\n return (\n
\n {data?.nonce.toString()}\n
\n )\n }\n return null\n }\n)\n\nTransactionNonce.displayName = \"TransactionNonce\"\n\nexport {\n TransactionBlockHash,\n TransactionBlockNumber,\n TransactionFrom,\n TransactionGas,\n TransactionGasPrice,\n TransactionNonce,\n TransactionTo,\n}\n" } ], "type": "components:buidl" diff --git a/apps/www/public/registry/styles/default/wallet-connect.json b/apps/www/public/registry/styles/default/wallet-connect.json index 21e3083..785c57d 100644 --- a/apps/www/public/registry/styles/default/wallet-connect.json +++ b/apps/www/public/registry/styles/default/wallet-connect.json @@ -6,7 +6,7 @@ "files": [ { "name": "wallet-connect.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { useAccount, useConnect, type Connector } from \"wagmi\"\n\nimport { cn } from \"@/lib/utils\"\n\nimport { Button, ButtonProps } from \"../ui/button\"\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"../ui/dialog\"\n\nconst WalletConnect = React.forwardRef(\n ({ children, className, ...props }, ref) => {\n const { address } = useAccount()\n const { connectors } = useConnect()\n\n if (address) {\n return {address}\n }\n\n return (\n \n \n \n \n \n \n Connect Wallet\n
\n
\n
\n {connectors.map((connector, index) => (\n \n ))}\n
\n
\n
\n )\n }\n)\n\nWalletConnect.displayName = \"WalletConnect\"\n\nconst WalletPreview = React.forwardRef<\n HTMLButtonElement,\n Omit & {\n connector: Connector\n }\n>(({ className, connector, ...props }, ref) => {\n const { connect, isLoading, isError, error } = useConnect()\n\n const handleConnect = () => {\n connect({ connector })\n }\n\n return (\n \n

{connector.name}

\n {isLoading && (\n

\n Accept the connection request in your wallet\n

\n )}\n {isError && (\n
\n {error?.message ?? \"Error while connecting wallet\"}\n
\n )}\n \n )\n})\n\nWalletPreview.displayName = \"WalletPreview\"\n\nexport { WalletConnect, WalletPreview }\n" + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { useAccount, useConnect, type Connector } from \"wagmi\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button, ButtonProps } from \"@/registry/default/ui/button\"\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"@/registry/default/ui/dialog\"\n\nconst WalletConnect = React.forwardRef(\n ({ children, className, ...props }, ref) => {\n const { address } = useAccount()\n const { connectors } = useConnect()\n\n if (address) {\n return
{address}
\n }\n\n return (\n \n \n \n \n \n \n Connect Wallet\n
\n
\n
\n {connectors.map((connector, index) => (\n \n ))}\n
\n
\n
\n )\n }\n)\n\nWalletConnect.displayName = \"WalletConnect\"\n\nconst WalletPreview = React.forwardRef<\n HTMLButtonElement,\n Omit & {\n connector: Connector\n }\n>(({ className, connector, ...props }, ref) => {\n const { connect, isLoading, isError, error } = useConnect()\n\n const handleConnect = () => {\n connect({ connector })\n }\n\n return (\n \n

{connector.name}

\n {isLoading && (\n

\n Accept the connection request in your wallet\n

\n )}\n {isError && (\n
\n {error?.message ?? \"Error while connecting wallet\"}\n
\n )}\n \n )\n})\n\nWalletPreview.displayName = \"WalletPreview\"\n\nexport { WalletConnect, WalletPreview }\n" } ], "type": "components:buidl" diff --git a/apps/www/public/registry/styles/default/wallet-disconnect.json b/apps/www/public/registry/styles/default/wallet-disconnect.json index e7707e7..3ff7a09 100644 --- a/apps/www/public/registry/styles/default/wallet-disconnect.json +++ b/apps/www/public/registry/styles/default/wallet-disconnect.json @@ -6,7 +6,7 @@ "files": [ { "name": "wallet-disconnect.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { useDisconnect } from \"wagmi\"\n\nimport { Button, type ButtonProps } from \"../ui/button\"\n\nconst WalletDisconnect = React.forwardRef<\n HTMLButtonElement,\n Omit\n>(({ children, ...props }, ref) => {\n const { disconnect } = useDisconnect()\n\n return (\n {\n disconnect()\n }}\n {...props}\n >\n {children ?? \"Disconnect\"}\n \n )\n})\n\nWalletDisconnect.displayName = \"WalletDisconnect\"\n\nexport { WalletDisconnect }\n" + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { useDisconnect } from \"wagmi\"\n\nimport { Button, type ButtonProps } from \"@/registry/default/ui/button\"\n\nconst WalletDisconnect = React.forwardRef<\n HTMLButtonElement,\n Omit\n>(({ children, ...props }, ref) => {\n const { disconnect } = useDisconnect()\n\n return (\n {\n disconnect()\n }}\n {...props}\n >\n {children ?? \"Disconnect\"}\n \n )\n})\n\nWalletDisconnect.displayName = \"WalletDisconnect\"\n\nexport { WalletDisconnect }\n" } ], "type": "components:buidl" diff --git a/apps/www/registry/default/buidl/address.tsx b/apps/www/registry/default/buidl/address.tsx index 6354649..d88fb66 100644 --- a/apps/www/registry/default/buidl/address.tsx +++ b/apps/www/registry/default/buidl/address.tsx @@ -18,13 +18,13 @@ export interface AddressProps } const AddressCopy = React.forwardRef< - HTMLSpanElement, - React.HTMLAttributes & { + HTMLDivElement, + React.HTMLAttributes & { address: AddressType } >(({ address, className, children, ...props }, ref) => { return ( - { @@ -39,15 +39,15 @@ const AddressCopy = React.forwardRef< {children ?? address} Copy address - + ) }) AddressCopy.displayName = "AddressCopy" const AddressLink = React.forwardRef< - HTMLElement, - React.HTMLAttributes & { + HTMLDivElement, + React.HTMLAttributes & { address: AddressType } >(({ address, className, children, ...props }, ref) => { @@ -57,7 +57,7 @@ const AddressLink = React.forwardRef< const chain = currentChain ?? mainnet return ( - {children ?? address} )} - + ) }) AddressLink.displayName = "AddressLink" -const Address = React.forwardRef( +const Address = React.forwardRef( ( { address, className, truncate, truncateAmount = 4, link, copy, ...props }, ref diff --git a/apps/www/registry/default/buidl/blockie.tsx b/apps/www/registry/default/buidl/blockie.tsx index b0d1a36..8228324 100644 --- a/apps/www/registry/default/buidl/blockie.tsx +++ b/apps/www/registry/default/buidl/blockie.tsx @@ -6,6 +6,7 @@ import makeBlockie from "ethereum-blockies-base64" import { useAccount } from "wagmi" import { cn } from "@/lib/utils" +import { Skeleton } from "@/registry/default/ui/skeleton" const blockieVariants = cva("inline-block", { variants: { @@ -32,24 +33,36 @@ export type BlockieProps = React.HTMLAttributes & address?: `0x${string}` } -export const Blockie = ({ - className, - address, - variant, - size, - ...props -}: BlockieProps) => { - const { address: connectedAddress } = useAccount() - const selectedAddress = address ?? connectedAddress - - if (!selectedAddress) return null - - return ( - {`${address} - ) -} +const Blockie = React.forwardRef( + ({ className, address, variant, size, ...props }, ref) => { + const [isLoading, setIsLoading] = React.useState(true) + const { address: connectedAddress, isConnecting } = useAccount() + const selectedAddress = address ?? connectedAddress ?? "0x0" + + return ( + <> + {isLoading || isConnecting ? ( + + ) : null} + {`${address} setIsLoading(false)} + className={cn( + blockieVariants({ variant, size, className }), + (isLoading || isConnecting) && "hidden" + )} + src={makeBlockie(selectedAddress)} + {...props} + /> + + ) + } +) + +Blockie.displayName = "Blockie" + +export { Blockie } diff --git a/apps/www/registry/default/buidl/ens-address.tsx b/apps/www/registry/default/buidl/ens-address.tsx index 2168f12..7374ff3 100644 --- a/apps/www/registry/default/buidl/ens-address.tsx +++ b/apps/www/registry/default/buidl/ens-address.tsx @@ -19,14 +19,18 @@ interface EnsAddressProps extends Omit { name: string } -const EnsAddress = React.forwardRef( +const EnsAddress = React.forwardRef( ({ name, className, ...props }, ref) => { const { data, isLoading, isSuccess, isError, error } = useEnsAddress({ chainId: 1, name, }) - if (isLoading) { + if (isError) { + return + } + + if (isLoading || !data) { return ( ( ) } - if (isError) { - return - } - return null } ) diff --git a/apps/www/registry/default/buidl/ens-avatar.tsx b/apps/www/registry/default/buidl/ens-avatar.tsx index 1345c58..2c0cc91 100644 --- a/apps/www/registry/default/buidl/ens-avatar.tsx +++ b/apps/www/registry/default/buidl/ens-avatar.tsx @@ -49,6 +49,8 @@ const EnsAvatar = React.forwardRef( }, ref ) => { + const [isLoadingImg, setIsLoadingImg] = React.useState(true) + const { address: connectedAddress } = useAccount() const selectedAddress = address ?? connectedAddress @@ -76,8 +78,7 @@ const EnsAvatar = React.forwardRef( ) @@ -85,13 +86,27 @@ const EnsAvatar = React.forwardRef( if (dataEnsAvatar) { return ( - {`${selectedAddress} + <> + {isLoadingImg ? ( + + ) : null} + {`${selectedAddress} { + setIsLoadingImg(false) + }} + src={dataEnsAvatar} + {...props} + /> + ) } diff --git a/apps/www/registry/default/buidl/ens-name.tsx b/apps/www/registry/default/buidl/ens-name.tsx index 14e0c7a..d560510 100644 --- a/apps/www/registry/default/buidl/ens-name.tsx +++ b/apps/www/registry/default/buidl/ens-name.tsx @@ -5,14 +5,13 @@ import { useAccount, useEnsName } from "wagmi" import { cn } from "@/lib/utils" import { Address } from "@/registry/default/buidl/address" +import { Skeleton } from "@/registry/default/ui/skeleton" -import { Skeleton } from "../ui/skeleton" - -interface EnsNameProps extends React.HTMLAttributes { +interface EnsNameProps extends React.HTMLAttributes { address?: `0x${string}` } -const EnsName = React.forwardRef( +const EnsName = React.forwardRef( ({ address, className, ...props }, ref) => { const { address: connectedAddress } = useAccount() const selectedAddress = address ?? connectedAddress @@ -25,13 +24,13 @@ const EnsName = React.forwardRef( if (isSuccess && data) { return ( - +
{data} - +
) } - if (isLoading) { + if (isLoading || !selectedAddress) { return } diff --git a/apps/www/registry/default/buidl/erc20/erc20-selector.tsx b/apps/www/registry/default/buidl/erc20/erc20-selector.tsx index 899c662..deb61bf 100644 --- a/apps/www/registry/default/buidl/erc20/erc20-selector.tsx +++ b/apps/www/registry/default/buidl/erc20/erc20-selector.tsx @@ -1,18 +1,17 @@ "use client" import { useCallback, useMemo, useState } from "react" -import Image from "next/image" import { cn } from "@/lib/utils" - +import { ImageIpfs } from "@/registry/default/buidl/image-ipfs" import { CommandDialog, CommandEmpty, CommandInput, CommandItem, CommandList, -} from "../../ui/command" -import { ImageIpfs } from "../image-ipfs" +} from "@/registry/default/ui/command" + import { Token, TokenList } from "./types" interface Erc20SelectorProps { diff --git a/apps/www/registry/default/buidl/erc721/erc721-metadata.tsx b/apps/www/registry/default/buidl/erc721/erc721-metadata.tsx index 6811952..22a5287 100644 --- a/apps/www/registry/default/buidl/erc721/erc721-metadata.tsx +++ b/apps/www/registry/default/buidl/erc721/erc721-metadata.tsx @@ -48,7 +48,7 @@ function useERC721Metadata({ address, chainId, tokenId, - ipfsGatewayUrl = "https://ipfs.io/ipfs", + ipfsGatewayUrl = "https://ipfs.io/ipfs/", }: useERC721MetadataProps) { const { data, isLoading, isError, error } = useContractRead({ address, @@ -64,14 +64,14 @@ function useERC721Metadata({ queryFn: async () => { if (!data) throw new Error("No tokenUri found") const uri = data.replace("ipfs://", "") - const response = await fetch(`${ipfsGatewayUrl}/${uri}`) + const response = await fetch(`${ipfsGatewayUrl}${uri}`) const json = (await response.json()) as IERC721Metadata if (!json.image) throw new Error("No image found in metadata") if (!json.attributes) throw new Error("No attributes found in metadata") json.image = json.image.startsWith("ipfs://") - ? json.image.replace("ipfs://", `${ipfsGatewayUrl}/`) + ? json.image.replace("ipfs://", `${ipfsGatewayUrl}`) : json.image return json }, @@ -113,8 +113,6 @@ const Erc721MetadataImage = React.forwardRef< ipfsGatewayUrl, }) - console.log(data) - if (isLoading) { return } diff --git a/apps/www/registry/default/buidl/image-ipfs.tsx b/apps/www/registry/default/buidl/image-ipfs.tsx index e93a6b9..2ab7f55 100644 --- a/apps/www/registry/default/buidl/image-ipfs.tsx +++ b/apps/www/registry/default/buidl/image-ipfs.tsx @@ -1,40 +1,59 @@ -import { useMemo } from "react" +import * as React from "react" import { cn } from "@/lib/utils" +import { Skeleton } from "@/registry/default/ui/skeleton" -type ImageIpfs = React.HTMLAttributes & { +const ErrorMessage = ({ error }: { error: Error | null }) => { + return ( +
+ {error?.message ?? "Error while fetching image"} +
+ ) +} + +interface ImageIpfsProps extends React.HTMLAttributes { + ipfsGatewayUrl?: string src: string alt: string - width?: string - height?: string } -export const ImageIpfs = ({ - className, - src, - alt, - width, - height, -}: ImageIpfs) => { - const classes = cn(className) - - const imgSrc = useMemo( - () => - src?.startsWith("ipfs://") - ? src.replace("ipfs://", "https://gateway.ipfs.io/ipfs/") - : src, - [src] - ) +const ImageIpfs = React.forwardRef( + ( + { className, src, alt, ipfsGatewayUrl = "https://ipfs.io/ipfs/", ...props }, + ref + ) => { + const [isLoading, setIsLoading] = React.useState(true) + const [isError, setIsError] = React.useState(false) - if (!imgSrc) return null + const imgSrc = React.useMemo( + () => + src?.startsWith("ipfs://") + ? src.replace("ipfs://", ipfsGatewayUrl) + : src, + [src, ipfsGatewayUrl] + ) - return ( - {alt} - ) -} + return ( + <> + {isError ? ( + + ) : isLoading ? ( + + ) : null} + {alt} setIsLoading(false)} + onError={() => setIsError(true)} + className={cn((isLoading || isError) && "hidden", className)} + {...props} + /> + + ) + } +) + +ImageIpfs.displayName = "ImageIpfs" + +export { ImageIpfs } diff --git a/apps/www/registry/default/buidl/is-wallet-connected.tsx b/apps/www/registry/default/buidl/is-wallet-connected.tsx index 681306e..98e52d4 100644 --- a/apps/www/registry/default/buidl/is-wallet-connected.tsx +++ b/apps/www/registry/default/buidl/is-wallet-connected.tsx @@ -4,9 +4,9 @@ import * as React from "react" import { useAccount } from "wagmi" const IsWalletConnected = ({ children }: { children: React.ReactNode }) => { - const { isConnected } = useAccount() + const { isConnected, isConnecting } = useAccount() - if (isConnected) return <>{children} + if (isConnected || isConnecting) return <>{children} return null } diff --git a/apps/www/registry/default/buidl/nonce.tsx b/apps/www/registry/default/buidl/nonce.tsx index 9364ab9..6827681 100644 --- a/apps/www/registry/default/buidl/nonce.tsx +++ b/apps/www/registry/default/buidl/nonce.tsx @@ -12,7 +12,7 @@ import { import { cn } from "@/lib/utils" import { Skeleton } from "@/registry/default/ui/skeleton" -interface NonceProps extends React.HTMLAttributes { +interface NonceProps extends React.HTMLAttributes { address?: `0x${string}` chainId?: number } @@ -32,8 +32,8 @@ const useNonce = ({ }) } -const Nonce = React.forwardRef( - ({ className, address, chainId, ...props }: NonceProps) => { +const Nonce = React.forwardRef( + ({ className, address, chainId, ...props }, ref) => { const connectedChainId = useChainId() const selectedChainId = chainId ?? connectedChainId @@ -54,9 +54,9 @@ const Nonce = React.forwardRef( } return ( - +
{data} - +
) } ) diff --git a/apps/www/registry/default/buidl/transaction-status.tsx b/apps/www/registry/default/buidl/transaction-status.tsx index 3c12894..e8bba57 100644 --- a/apps/www/registry/default/buidl/transaction-status.tsx +++ b/apps/www/registry/default/buidl/transaction-status.tsx @@ -35,21 +35,15 @@ const TransactionStatus = React.forwardRef< if (isError) return return ( - <> -
- {(isLoading || isSuccess) && ( - <> - {isLoading && "Processing transaction..."} - {isSuccess && "Transaction successful!"} - {children} - - )} -
- +
+ {isLoading && "Processing transaction..."} + {isSuccess && "Transaction successful!"} + {children} +
) }) diff --git a/apps/www/registry/default/buidl/transaction.tsx b/apps/www/registry/default/buidl/transaction.tsx index d03c5f1..b5e90df 100644 --- a/apps/www/registry/default/buidl/transaction.tsx +++ b/apps/www/registry/default/buidl/transaction.tsx @@ -40,7 +40,7 @@ const TransactionBlockHash = React.forwardRef( }) if (isLoading && displayLoading) - return + return if (isError && displayError) return diff --git a/apps/www/registry/default/buidl/wallet-connect.tsx b/apps/www/registry/default/buidl/wallet-connect.tsx index c4f3775..1b8d820 100644 --- a/apps/www/registry/default/buidl/wallet-connect.tsx +++ b/apps/www/registry/default/buidl/wallet-connect.tsx @@ -4,15 +4,14 @@ import * as React from "react" import { useAccount, useConnect, type Connector } from "wagmi" import { cn } from "@/lib/utils" - -import { Button, ButtonProps } from "../ui/button" +import { Button, ButtonProps } from "@/registry/default/ui/button" import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger, -} from "../ui/dialog" +} from "@/registry/default/ui/dialog" const WalletConnect = React.forwardRef( ({ children, className, ...props }, ref) => { @@ -20,7 +19,7 @@ const WalletConnect = React.forwardRef( const { connectors } = useConnect() if (address) { - return {address} + return
{address}
} return ( diff --git a/apps/www/registry/default/buidl/wallet-disconnect.tsx b/apps/www/registry/default/buidl/wallet-disconnect.tsx index 3c57926..b898d40 100644 --- a/apps/www/registry/default/buidl/wallet-disconnect.tsx +++ b/apps/www/registry/default/buidl/wallet-disconnect.tsx @@ -3,7 +3,7 @@ import * as React from "react" import { useDisconnect } from "wagmi" -import { Button, type ButtonProps } from "../ui/button" +import { Button, type ButtonProps } from "@/registry/default/ui/button" const WalletDisconnect = React.forwardRef< HTMLButtonElement, diff --git a/apps/www/registry/default/example/address-demo.tsx b/apps/www/registry/default/example/address-demo.tsx index 43c2ad3..a7c9b3b 100644 --- a/apps/www/registry/default/example/address-demo.tsx +++ b/apps/www/registry/default/example/address-demo.tsx @@ -3,10 +3,9 @@ import { AddressCopy, AddressLink, } from "@/registry/default/buidl/address" - -import { IsWalletConnected } from "../buidl/is-wallet-connected" -import { IsWalletDisconnected } from "../buidl/is-wallet-disconnected" -import { WalletConnect } from "../buidl/wallet-connect" +import { IsWalletConnected } from "@/registry/default/buidl/is-wallet-connected" +import { IsWalletDisconnected } from "@/registry/default/buidl/is-wallet-disconnected" +import { WalletConnect } from "@/registry/default/buidl/wallet-connect" export const ADDRESS_EXAMPLE = "0x761d584f1C2d43cBc3F42ECd739701a36dFFAa31" diff --git a/apps/www/registry/default/example/blockie-demo.tsx b/apps/www/registry/default/example/blockie-demo.tsx index 717dda4..45586fb 100644 --- a/apps/www/registry/default/example/blockie-demo.tsx +++ b/apps/www/registry/default/example/blockie-demo.tsx @@ -1,8 +1,7 @@ import { Blockie } from "@/registry/default/buidl/blockie" - -import { IsWalletConnected } from "../buidl/is-wallet-connected" -import { IsWalletDisconnected } from "../buidl/is-wallet-disconnected" -import { WalletConnect } from "../buidl/wallet-connect" +import { IsWalletConnected } from "@/registry/default/buidl/is-wallet-connected" +import { IsWalletDisconnected } from "@/registry/default/buidl/is-wallet-disconnected" +import { WalletConnect } from "@/registry/default/buidl/wallet-connect" const ADDRESS_EXAMPLE = "0x761d584f1C2d43cBc3F42ECd739701a36dFFAa31" diff --git a/apps/www/registry/default/example/ens-avatar-demo.tsx b/apps/www/registry/default/example/ens-avatar-demo.tsx index b7ff5bd..5af6e76 100644 --- a/apps/www/registry/default/example/ens-avatar-demo.tsx +++ b/apps/www/registry/default/example/ens-avatar-demo.tsx @@ -1,7 +1,5 @@ import { EnsAvatar } from "@/registry/default/buidl/ens-avatar" import { IsWalletConnected } from "@/registry/default/buidl/is-wallet-connected" -import { IsWalletDisconnected } from "@/registry/default/buidl/is-wallet-disconnected" -import { WalletConnect } from "@/registry/default/buidl/wallet-connect" const ADDRESS_EXAMPLE = "0x761d584f1C2d43cBc3F42ECd739701a36dFFAa31" @@ -15,9 +13,9 @@ export default function EnsAvatarDemo() { - + {/* - + */}

Input ENS name (vitalik.eth)

diff --git a/apps/www/registry/default/example/image-ipfs-demo.tsx b/apps/www/registry/default/example/image-ipfs-demo.tsx index 5c86f6f..f9598cf 100644 --- a/apps/www/registry/default/example/image-ipfs-demo.tsx +++ b/apps/www/registry/default/example/image-ipfs-demo.tsx @@ -3,8 +3,7 @@ import { ImageIpfs } from "@/registry/default/buidl/image-ipfs" export default function ImageIpfsDemo() { return ( diff --git a/apps/www/registry/default/example/is-wallet-disconnected-demo.tsx b/apps/www/registry/default/example/is-wallet-disconnected-demo.tsx index faa0d46..d8184ef 100644 --- a/apps/www/registry/default/example/is-wallet-disconnected-demo.tsx +++ b/apps/www/registry/default/example/is-wallet-disconnected-demo.tsx @@ -1,8 +1,7 @@ import { IsWalletConnected } from "@/registry/default/buidl/is-wallet-connected" import { IsWalletDisconnected } from "@/registry/default/buidl/is-wallet-disconnected" import { WalletConnect } from "@/registry/default/buidl/wallet-connect" - -import { WalletDisconnect } from "../buidl/wallet-disconnect" +import { WalletDisconnect } from "@/registry/default/buidl/wallet-disconnect" export default function IsWalletDisconnectedDemo() { return ( diff --git a/apps/www/registry/default/example/transaction-demo.tsx b/apps/www/registry/default/example/transaction-demo.tsx index dd70126..46d70a1 100644 --- a/apps/www/registry/default/example/transaction-demo.tsx +++ b/apps/www/registry/default/example/transaction-demo.tsx @@ -17,20 +17,36 @@ export default function TransactionStatusDemo() {

Transaction

From:

- +

To:

- +

BlockHash:

- +

BlockNumber:

Gas:

- +

Gas Price:

- +

Nonce:

- +
diff --git a/apps/www/registry/default/example/transaction-status-demo.tsx b/apps/www/registry/default/example/transaction-status-demo.tsx index 8b6f1f1..6c5da9b 100644 --- a/apps/www/registry/default/example/transaction-status-demo.tsx +++ b/apps/www/registry/default/example/transaction-status-demo.tsx @@ -1,7 +1,6 @@ +import { BlockExplorerLink } from "@/registry/default/buidl/block-explorer-link" import { TransactionStatus } from "@/registry/default/buidl/transaction-status" -import { BlockExplorerLink } from "../buidl/block-explorer-link" - export default function TransactionStatusDemo() { return (