Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
88fe18b
Added support for rendering 3d NFTs
JustinTime42 Dec 22, 2022
1d2836f
added common three.js props like camera position, frustrum, and ambie…
JustinTime42 Dec 22, 2022
67cdbe2
fixed linting errors
JustinTime42 Dec 22, 2022
c72b2b3
changed 3d nft rendering to user <model-viewer>
JustinTime42 Dec 27, 2022
52a41f4
fixed some typings
JustinTime42 Dec 30, 2022
f21e64d
Revert "fixed some typings"
JustinTime42 Dec 31, 2022
09a776d
fixed some typings
JustinTime42 Dec 30, 2022
283e8be
removed three.js, model-viewer, and associated types from dependencies
JustinTime42 Dec 31, 2022
c9cf85f
removed model-viewer dependency
JustinTime42 Dec 31, 2022
ffcc359
deleted package-lock.json
JustinTime42 Jan 4, 2023
e61f2ec
Merge branch 'main' into three
jnsdls Jan 9, 2023
1d532f3
merged upstread update
JustinTime42 Jan 10, 2023
c2a2f13
merged upstream update
JustinTime42 Jan 10, 2023
442f981
fixed bug preventing more than one 3d model from rendering on screen
JustinTime42 Jan 10, 2023
8e26b7f
Merge branch 'three' of https://github.com/JustinTime42/thirdweb-jsmo…
JustinTime42 Jan 10, 2023
64174b1
fixed 'any' type in MediaRenderer
JustinTime42 Jan 11, 2023
b6bdf7e
Merge branch 'thirdweb-dev:main' into three
JustinTime42 Jan 11, 2023
f7a79b6
Merge branch 'thirdweb-dev:main' into three
JustinTime42 Jan 12, 2023
c394dbf
using model-viewer via dynamic import
JustinTime42 Jan 12, 2023
0277dbd
removed unused code from MediaRenderer
JustinTime42 Jan 12, 2023
9b99f1f
Merge branch 'main' into three
jnsdls Jan 14, 2023
335b01b
added displayName to ModelViewer
JustinTime42 Jan 14, 2023
eeddf2a
Merge branch 'main' into three
JustinTime42 Jan 16, 2023
f43cd50
Merge branch 'main' of https://github.com/JustinTime42/thirdweb-jsmon…
JustinTime42 Jan 18, 2023
badd3bd
moved ModelViewer to its own component file for lazy loading
JustinTime42 Jan 18, 2023
d559d47
Merge branch 'three' of https://github.com/JustinTime42/thirdweb-jsmo…
JustinTime42 Jan 18, 2023
0f140d2
wrapped lazy loaded ModelViewer in React.Suspense
JustinTime42 Jan 18, 2023
36ef9cc
Merge branch 'main' into three
jarrodwatts Jan 20, 2023
c1906ff
Merge branch 'main' into three
JustinTime42 Jan 24, 2023
18f6339
Merge branch 'main' into three
jnsdls Jan 26, 2023
666508b
ModelViewer now properly accepts style props
JustinTime42 Jan 26, 2023
ce02baa
Merge branch 'main' into three
jnsdls Jan 26, 2023
d16c7e3
couple of fixes
jnsdls Jan 27, 2023
7f95d53
Merge branch 'main' into three
jnsdls Jan 27, 2023
30b965e
this is a patch change
jnsdls Jan 27, 2023
0237f00
merge
jnsdls Jan 27, 2023
f95f7a0
fixed dimensions of 3d model
JustinTime42 Jan 27, 2023
b91e2f7
Merge branch 'main' of https://github.com/thirdweb-dev/js into three
nachoiacovino Jan 28, 2023
f7718e1
merge
nachoiacovino Jan 28, 2023
01b3d5e
fixed width issues with model viewer
JustinTime42 Jan 28, 2023
384635b
Merge branch 'three' of https://github.com/JustinTime42/thirdweb-jsmo…
JustinTime42 Jan 28, 2023
6a9f8aa
removed unused props
JustinTime42 Jan 28, 2023
905e69b
removed unused props
JustinTime42 Jan 28, 2023
5ada5fc
Merge branch 'main' into three
JustinTime42 Jan 30, 2023
c1ef9e7
Prettify
nachoiacovino Jan 30, 2023
ae2f6a6
fixed styling in ModelViewer
JustinTime42 Jan 31, 2023
6322cb9
Merge branch 'main' into three
nachoiacovino Jan 31, 2023
354f82e
Merge branch 'main' of https://github.com/thirdweb-dev/js into three
nachoiacovino Feb 1, 2023
60f8767
merge
nachoiacovino Feb 1, 2023
54b36a6
moved styling to ThirdwebNftMedia component
JustinTime42 Feb 2, 2023
612f9b3
Merge branch 'main' into three
jnsdls Feb 2, 2023
3eee693
Merge branch 'main' into three
JustinTime42 Feb 2, 2023
4d6af17
moved default style to MediaRenderer
JustinTime42 Feb 3, 2023
b239eee
Merge branch 'main' into three
jnsdls Feb 3, 2023
8e4c439
Add width/height default props
nachoiacovino Feb 3, 2023
6693ce0
Add better comments
nachoiacovino Feb 3, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/flat-birds-march.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@thirdweb-dev/react": patch
---

Added support for displaying 3d model NFTs
1 change: 1 addition & 0 deletions packages/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@
"dependencies": {
"@emotion/react": "^11.10.0",
"@emotion/styled": "^11.10.0",
"@google/model-viewer": "^2.1.1",
"@react-icons/all-files": "^4.1.0",
"@safe-global/safe-core-sdk": "^3.2.0",
"@safe-global/safe-ethers-adapters": "0.1.0-alpha.13",
Expand Down
45 changes: 42 additions & 3 deletions packages/react/src/evm/components/MediaRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,19 @@ import {
CarbonPlayFilledAlt,
} from "./Icons";
import { useQuery } from "@tanstack/react-query";
import React, { useEffect, useMemo, useRef, useState } from "react";
import React, {
ReactNode,
useEffect,
useMemo,
useRef,
useState,
lazy,
Suspense,
} from "react";
import useDimensions from "react-cool-dimensions";

const ModelViewer = lazy(() => import("./ModelViewer"));

export interface SharedMediaProps {
className?: string;
style?: React.CSSProperties;
Expand All @@ -25,6 +35,8 @@ export interface SharedMediaProps {
* Show the media controls (where applicable) (default false)
*/
controls?: HTMLVideoElement["controls"];

children?: ReactNode;
}

/**
Expand All @@ -45,6 +57,8 @@ export interface MediaRendererProps extends SharedMediaProps {
* The media poster image uri. (if applicable)
*/
poster?: string | null;
width?: string;
height?: string;
}

interface PlayButtonProps {
Expand Down Expand Up @@ -399,6 +413,7 @@ LinkPlayer.displayName = "LinkPlayer";
* This component can be used to render any media type, including image, audio, video, and html files.
* Its convenient for rendering NFT media files, as these can be a variety of different types.
* The component falls back to a external link if the media type is not supported.
* The default size is 300px by 300px, but this can be changed using the `width` and `height` props.
*
* Props: {@link MediaRendererProps}
*
Expand All @@ -420,10 +435,10 @@ export const MediaRenderer = React.forwardRef<
MediaRendererProps
>(
(
{ src, poster, alt, requireInteraction = false, style, ...restProps },
{ src, poster, alt, requireInteraction = false, width = "300px", height = "300px", style, ...restProps },
ref,
) => {
const mergedStyle: React.CSSProperties = { objectFit: "contain", ...style };
const mergedStyle: React.CSSProperties = { objectFit: "contain", width, height, ...style };
const videoOrImageSrc = useResolvedMediaType(src ?? undefined);
const possiblePosterSrc = useResolvedMediaType(poster ?? undefined);
if (!videoOrImageSrc.mimeType) {
Expand All @@ -445,6 +460,30 @@ export const MediaRenderer = React.forwardRef<
{...restProps}
/>
);
} else if (videoOrImageSrc.mimeType.startsWith("model")) {
return (
<Suspense
fallback={
poster ? (
<img
style={mergedStyle}
src={poster}
alt={alt}
ref={ref as unknown as React.LegacyRef<HTMLImageElement>}
{...restProps}
/>
) : null
}
>
<ModelViewer
style={mergedStyle}
src={videoOrImageSrc.url || ""}
poster={poster}
alt={alt}
{...restProps}
/>
</Suspense>
);
} else if (shouldRenderVideoTag(videoOrImageSrc.mimeType)) {
return (
<VideoPlayer
Expand Down
34 changes: 34 additions & 0 deletions packages/react/src/evm/components/ModelViewer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import type { MediaRendererProps } from "./MediaRenderer";
import "@google/model-viewer";
import type { ModelViewerElement } from "@google/model-viewer";
import React from "react";

declare global {
namespace JSX {
interface IntrinsicElements {
"model-viewer": Partial<ModelViewerElement>;
}
}
}

export const ModelViewer = React.forwardRef<HTMLDivElement, MediaRendererProps>(
({ src, alt, poster, style }, ref) => {
return (
<div style={{ ...style }} ref={ref}>
{src ? (
<model-viewer
src={src}
alt={alt || "3D Model"}
camera-controls
poster={poster ? poster : null}
style={{ width: '100%', height: '100%'} as CSSStyleDeclaration}
/>
) : null}
</div>
);
},
);

ModelViewer.displayName = "ModelViewer";

export default ModelViewer;
10 changes: 9 additions & 1 deletion packages/react/src/evm/components/NftMedia.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,15 @@ export interface ThirdwebNftMediaProps extends SharedMediaProps {
* The NFT metadata of the NFT returned by the thirdweb sdk.
*/
metadata: NFTMetadata;
width?: string;
height?: string;
}

/**
* This component can be used to render NFTs from the thirdweb SDK.
* It will render the animation_url if it exists, otherwise it will render the image.
* The default size is 300px by 300px, but this can be changed using the `width` and `height` props.
*
* Props: {@link ThirdwebNftMediaProps}
*
* @example
Expand All @@ -38,13 +43,16 @@ export interface ThirdwebNftMediaProps extends SharedMediaProps {
export const ThirdwebNftMedia = React.forwardRef<
HTMLMediaElement,
ThirdwebNftMediaProps
>(({ metadata, ...props }, ref) => {
>(({ metadata, width = "300px", height = "300px", style, ...props }, ref) => {
return (
<MediaRenderer
src={metadata.animation_url || metadata.image}
poster={metadata.image}
alt={metadata.name?.toString() || ""}
ref={ref}
width={width}
height={height}
style={{ ...style }}
{...props}
/>
);
Expand Down
Loading