From 60105457f2df0f5b64003494adee43cf056cce2e Mon Sep 17 00:00:00 2001 From: ReflectiveChimp <55021052+ReflectiveChimp@users.noreply.github.com> Date: Fri, 24 Nov 2023 00:11:19 +0000 Subject: [PATCH] v1 --- package.json | 4 +- src/components/Common/Header/Header.tsx | 1 + src/components/Home/Hero/Background.tsx | 268 ++++++++++++++++++++++++ src/components/Home/Hero/Hero.tsx | 28 +-- src/images/hero/coin-face-bump-map.png | Bin 0 -> 22108 bytes src/images/hero/coin-side-bump-map.png | Bin 0 -> 2391 bytes src/images/networks/arbitrum.svg | 15 +- src/images/networks/aurora.svg | 2 +- src/images/networks/avax.svg | 2 +- src/images/networks/base.svg | 1 + src/images/networks/bsc.svg | 2 +- src/images/networks/canto.svg | 3 +- src/images/networks/celo.svg | 2 +- src/images/networks/cronos.svg | 2 +- src/images/networks/emerald.svg | 2 +- src/images/networks/ethereum.svg | 2 +- src/images/networks/fantom.svg | 2 +- src/images/networks/fuse.svg | 2 +- src/images/networks/gnosis.svg | 4 + src/images/networks/harmony.svg | 2 +- src/images/networks/heco.svg | 2 +- src/images/networks/kava.svg | 2 +- src/images/networks/metis.svg | 2 +- src/images/networks/moonbeam.svg | 2 +- src/images/networks/moonriver.svg | 2 +- src/images/networks/optimism.svg | 2 +- src/images/networks/polygon.svg | 2 +- src/images/networks/zkevm.svg | 2 +- src/images/networks/zksync.svg | 2 +- src/theme.ts | 6 +- src/utils/network-utils.ts | 12 ++ yarn.lock | 35 ++++ 32 files changed, 369 insertions(+), 46 deletions(-) create mode 100644 src/components/Home/Hero/Background.tsx create mode 100644 src/images/hero/coin-face-bump-map.png create mode 100644 src/images/hero/coin-side-bump-map.png create mode 100644 src/images/networks/base.svg create mode 100644 src/images/networks/gnosis.svg create mode 100644 src/utils/network-utils.ts diff --git a/package.json b/package.json index 490b756..0f1d23a 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,8 @@ "react-page-visibility": "^7.0.0", "react-redux": "^8.0.2", "react-ticker": "^1.3.2", - "slugify": "^1.6.5" + "slugify": "^1.6.5", + "three": "^0.158.0" }, "devDependencies": { "@types/gatsby-transformer-remark": "^2.9.1", @@ -56,6 +57,7 @@ "@types/react": "^18.0.15", "@types/react-dom": "^18.0.6", "@types/react-page-visibility": "^6.4.1", + "@types/three": "^0.158.3", "@types/webpack-env": "^1.17.0", "escape-string-regexp": "^5.0.0", "fast-glob": "^3.2.11", diff --git a/src/components/Common/Header/Header.tsx b/src/components/Common/Header/Header.tsx index 812ae6a..4b9a901 100644 --- a/src/components/Common/Header/Header.tsx +++ b/src/components/Common/Header/Header.tsx @@ -20,6 +20,7 @@ const OuterOnTop = styled(Outer)` top: 0; left: 0; right: 0; + z-index: 10; @media (max-width: ${theme.breakpoints.sm}px) { background-size: auto; } diff --git a/src/components/Home/Hero/Background.tsx b/src/components/Home/Hero/Background.tsx new file mode 100644 index 0000000..8bfd651 --- /dev/null +++ b/src/components/Home/Hero/Background.tsx @@ -0,0 +1,268 @@ +import React, { memo, useEffect } from 'react'; +import styled from '@emotion/styled'; +import { + AmbientLight, + Box2, + CylinderGeometry, + DirectionalLight, + Mesh, + MeshPhongMaterial, + OrthographicCamera, + PointLight, + RepeatWrapping, + Scene, + SRGBColorSpace, + Texture, + TextureLoader, + Vector2, + WebGLRenderer, +} from 'three'; +import faceBumpMapUrl from '!url-loader?limit=false!../../../images/hero/coin-face-bump-map.png'; +import sideBumpMapUrl from '!url-loader?limit=false!../../../images/hero/coin-side-bump-map.png'; +import { getNetworkIconSrc } from '../../../utils/network-utils'; +import { theme } from '../../../theme'; + +const Container = styled.div` + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +`; + +const chains = Object.entries(theme.chains).map(([chainId, color]) => ({ + chainId, + color: chainId === 'base' ? '#0052FF' : color, + src: getNetworkIconSrc(chainId), +})); + +class Coins { + private camera: OrthographicCamera; + private scene: Scene; + private renderer: WebGLRenderer; + private rendering: boolean = false; + private frameRequest: number | undefined; + private coins: Mesh[]; + private velocities: Vector2[]; + private textureLoader: TextureLoader; + private lastTime: DOMHighResTimeStamp | undefined; + private faceBumpMap: Texture | undefined; + private sideBumpMap: Texture | undefined; + private coinGeometry: CylinderGeometry | undefined; + private coinRadius: number = 5 / 100; + private coinHeight: number = 1 / 100; + private boundingBox: Box2; + + constructor(protected container: HTMLDivElement) { + this.render = this.render.bind(this); + this.resize = this.resize.bind(this); + + this.textureLoader = new TextureLoader(); + this.camera = this.createCamera(); + this.boundingBox = this.createBoundingBox(); + this.coins = this.createCoins(); + this.velocities = this.coins.map(() => new Vector2(this.randomSpeed(), this.randomSpeed())); + this.scene = this.createScene(); + this.renderer = this.createRenderer(); + this.attachEvents(); + } + + private loadTexture(url: string) { + const texture = this.textureLoader.load(url); + texture.colorSpace = SRGBColorSpace; + return texture; + } + + private createCoins() { + this.faceBumpMap = this.loadTexture(faceBumpMapUrl); + this.sideBumpMap = this.loadTexture(sideBumpMapUrl); + this.coinGeometry = new CylinderGeometry(this.coinRadius, this.coinRadius, this.coinHeight, 32); + this.coinGeometry.rotateX(Math.PI / 2); + this.coinGeometry.rotateZ(Math.PI / 2); + + return chains.map(({ chainId, color, src }) => this.createCoin(chainId, color, src)); + } + + private createCoin(chainId: string, color: string, src: string) { + const textureMap = this.loadTexture(src); + const oppositeFaceTextureMap = this.loadTexture(src); + oppositeFaceTextureMap.flipY = false; + oppositeFaceTextureMap.wrapS = RepeatWrapping; + oppositeFaceTextureMap.repeat.x = -1; + + const side = new MeshPhongMaterial({ + color, + specular: 0xffffff, + shininess: 10, + bumpMap: this.sideBumpMap!, + bumpScale: 10, + }); + + const face = new MeshPhongMaterial({ + specular: 0xffffff, + shininess: 10, + bumpMap: this.faceBumpMap!, + bumpScale: 10, + map: textureMap, + }); + + const oppositeFace = new MeshPhongMaterial({ + specular: 0xffffff, + shininess: 10, + bumpMap: this.faceBumpMap!, + bumpScale: 10, + map: oppositeFaceTextureMap, + }); + + return new Mesh(this.coinGeometry!, [side, oppositeFace, face]); + } + + private createScene() { + const scene = new Scene(); + const ambientLight = new AmbientLight(0xffffff, 1); + const directionalLight = new DirectionalLight(0xffffff, 5); + const spotLight = new PointLight(0xffffff, 10); + spotLight.position.set(3.5, 0, 50); + + this.coins.forEach((coin, i) => { + const x = Math.random() * this.camera.right; + const y = Math.random(); + coin.position.set(x, y, i); + coin.rotation.y = Math.random() * Math.PI * 2; + }); + + scene.add(...this.coins); + scene.add(ambientLight); + scene.add(directionalLight); + scene.add(spotLight); + + return scene; + } + + private createRenderer() { + const renderer = new WebGLRenderer({ + antialias: true, + }); + renderer.setSize(this.container.offsetWidth, this.container.offsetHeight); + renderer.setClearColor('#141520', 0); + this.container.appendChild(renderer.domElement); + return renderer; + } + + private createBoundingBox(): Box2 { + return new Box2( + new Vector2(this.coinRadius, this.coinRadius), + new Vector2(this.camera.right - this.coinRadius, 1 - this.coinRadius) + ); + } + + private createCamera() { + const aspect = this.container.offsetWidth / this.container.offsetHeight; + const camera = new OrthographicCamera(0, aspect, 0, 1); + camera.position.z = 50; + return camera; + } + + public startRendering() { + if (!this.rendering) { + this.rendering = true; + this.frameRequest = requestAnimationFrame(this.render); + } + } + + public stopRendering() { + this.rendering = false; + this.lastTime = undefined; + if (this.frameRequest) { + cancelAnimationFrame(this.frameRequest); + this.frameRequest = undefined; + } + } + + private randomSpeed() { + return Math.max(Math.random(), 0.1) / 2000; + } + + private update(time: DOMHighResTimeStamp) { + const delta = this.lastTime === undefined ? 0 : time - this.lastTime; + this.lastTime = time; + + this.coins.forEach((coin, i) => { + const velocity = this.velocities[i]; + + coin.rotation.y += delta / 1000; + coin.position.set( + coin.position.x + velocity.x * delta, + coin.position.y + velocity.y * delta, + i + ); + + if (coin.position.y >= this.boundingBox.max.y) { + coin.position.y = this.boundingBox.max.y; + velocity.y = -this.randomSpeed(); + } else if (coin.position.y <= this.boundingBox.min.y) { + coin.position.y = this.boundingBox.min.y; + velocity.y = this.randomSpeed(); + } + + if (coin.position.x >= this.boundingBox.max.x) { + coin.position.x = this.boundingBox.max.x; + velocity.x = -this.randomSpeed(); + } else if (coin.position.x <= this.boundingBox.min.x) { + coin.position.x = this.boundingBox.min.x; + velocity.x = this.randomSpeed(); + } + }); + } + + private render(time: DOMHighResTimeStamp) { + if (!this.rendering) { + return; + } + this.update(time); + this.frameRequest = requestAnimationFrame(this.render); + this.renderer.render(this.scene, this.camera); + } + + private resize() { + this.camera.right = this.container.offsetWidth / this.container.offsetHeight; + this.camera.updateProjectionMatrix(); + this.renderer.setSize(this.container.offsetWidth, this.container.offsetHeight); + this.boundingBox.max.set(this.camera.right - this.coinRadius, 1 - this.coinRadius); + } + + private attachEvents() { + ['load', 'resize', 'orientationchange'].forEach(event => { + window.addEventListener(event, this.resize); + }); + } + + private detachEvents() { + ['load', 'resize', 'orientationchange'].forEach(event => { + window.removeEventListener(event, this.resize); + }); + } + + private destroyRenderer() { + this.stopRendering(); + this.renderer.domElement.remove(); + this.renderer.dispose(); + } + + public cleanup() { + this.detachEvents(); + this.destroyRenderer(); + } +} + +export const Background = memo(function Background() { + const containerRef = React.useRef(null); + + useEffect(() => { + const coins = new Coins(containerRef.current!); + coins.startRendering(); + return () => coins.cleanup(); + }, []); + + return ; +}); diff --git a/src/components/Home/Hero/Hero.tsx b/src/components/Home/Hero/Hero.tsx index e8dc095..e2a5adf 100644 --- a/src/components/Home/Hero/Hero.tsx +++ b/src/components/Home/Hero/Hero.tsx @@ -1,14 +1,11 @@ import React, { memo } from 'react'; import styled from '@emotion/styled'; import { FluidInner } from '../../Common/Inner'; -import bottomLeft from '../../../images/hero-bottom-left.png'; -import bottomRight from '../../../images/hero-bottom-right.png'; -import topLeft from '../../../images/hero-top-left.png'; -import topRight from '../../../images/hero-top-right.png'; import { theme } from '../../../theme'; import { PrimaryExternalLink, SecondaryExternalLink } from '../../Common/Buttons'; import { useAppUrl } from '../../../utils/react-utils'; import { useChainCount } from '../../../data/queries/total-chains'; +import { Background } from './Background'; // Background images const w = 390; @@ -16,27 +13,14 @@ const h = 320; const r = h / w; const CustomInner = styled(FluidInner)` + position: relative; display: flex; align-items: center; padding: ${40 + 24 * 2}px 0px; - background-image: url(${topLeft}), url(${topRight}), url(${bottomLeft}), url(${bottomRight}); - background-repeat: no-repeat; - background-position: left 64px, right 64px, left bottom, right bottom; - background-size: ${(360 - 48) / 2}px ${((360 - 48) / 2) * r}px; min-height: 100vh; text-align: center; flex-direction: column; justify-content: center; - - @media (min-width: ${theme.breakpoints.sm}px) { - background-position: left 5%, right 5%, left bottom, right bottom; - background-size: ${(theme.breakpoints.sm - 48) / 2}px ${((theme.breakpoints.sm - 48) / 2) * r}px; - } - - @media (min-width: ${theme.breakpoints.lg}px) { - width: ${theme.containers.lg}px; - background-size: ${w}px ${h}px; - } `; const Title = styled.div` @@ -74,7 +58,8 @@ const Buttons = styled.div` justify-content: center; `; -const Container = styled.div` +const Centered = styled.div` + position: relative; display: flex; align-items: center; flex-direction: column; @@ -91,7 +76,8 @@ export const Hero = memo(function Hero() { return ( - + + Multichain Yield Optimizer Earn the highest APYs across {chains} chains with safety and efficiency in mind. @@ -104,7 +90,7 @@ export const Hero = memo(function Hero() { View Docs - + ); }); diff --git a/src/images/hero/coin-face-bump-map.png b/src/images/hero/coin-face-bump-map.png new file mode 100644 index 0000000000000000000000000000000000000000..7481a3ea2681113e8e8eea2261bbab615bc1e806 GIT binary patch literal 22108 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 literal 0 HcmV?d00001 diff --git a/src/images/hero/coin-side-bump-map.png b/src/images/hero/coin-side-bump-map.png new file mode 100644 index 0000000000000000000000000000000000000000..76e82e10fe60ab3bc356e596bf3128747fc0aaa8 GIT binary patch literal 2391 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911L)MWvCLk0$x6`3IsB@w}FfdWk9d zNvV1jxdlLZ1_m4Zih{)C?9>v4q}24xJX@vryZ0+8WTx0Eg`4^s_!c;)W@LI)6{QAO z`Gq7`WhYyvDB0U_*;H5o4aiL`NmQuF&B-gas<2f8n`;GRgM{^!6u?SKvTcHG#s;$}=}HJvBTtr6dDk z8bZP+H7^}Q2IRV&Qc(1U=4Ar?V}vj*0wHIsWNrjZSfEG;n-_^y3LY0$VE6gvrvRO2 z4AzB^@^p3%D9TUE%mK<32e~^bc)B{98Csf|=^E)lyaJ3kE1=%Yv`Ux65}+z010!Qy zLqlC7;}9c5D?<}2L*pp0p*gGQlZZK>-}UR*A`=ps`gdD9TSMO-@Y#+Y2-fB3qoFR#Ki=lpvcDNDSfEB^g%fd<}e$545!f9X)5&Lc&aJllUj5$kZnd7pVNcc6kgtwfxvv&}Tu@$@c=2`J!agyn%;n~bByN3q z6EUOfTV?;@zU{VUYfnA@w{@53)qn$m$~J2%+`~?Rw%O z`!;{gXpGP86aR5L%~nQ=F@5m{^SEOdjlzVgydvWI^rxQDI{N#D{>K$BcSd%~KFXD7 zkx=iL?&&6}=wR<`#Qx%-|N1p6Cfxr%+uqr&NOY#@wTqFeeoT||0yhW6PL&XjojNh) z?z{i@_epJJtY5fGo#X2HXTi{QEEx3G?JR^EcLl@~TYvQy_5xHn<_uC~3kFD8BF zJ#D{wQU+`Bw1jiOT7t8{BeIx*fm;}a85w5Hkzin8I^pT!7*a9k?d6Sv4Guiajz0fw zXG_^7|0_%G-8B38g?Dmq(~s@{fB)Zp_v{@#3?9M^nM?}43`;m0Oc*DqFbP0l+XkK-c<5- literal 0 HcmV?d00001 diff --git a/src/images/networks/arbitrum.svg b/src/images/networks/arbitrum.svg index a843636..607c4b1 100644 --- a/src/images/networks/arbitrum.svg +++ b/src/images/networks/arbitrum.svg @@ -1 +1,14 @@ - \ No newline at end of file + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/images/networks/aurora.svg b/src/images/networks/aurora.svg index 5d0cdb8..f787c03 100644 --- a/src/images/networks/aurora.svg +++ b/src/images/networks/aurora.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/images/networks/avax.svg b/src/images/networks/avax.svg index cced36f..38b1192 100644 --- a/src/images/networks/avax.svg +++ b/src/images/networks/avax.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/images/networks/base.svg b/src/images/networks/base.svg new file mode 100644 index 0000000..fa62005 --- /dev/null +++ b/src/images/networks/base.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/images/networks/bsc.svg b/src/images/networks/bsc.svg index 8f1dc72..0b3d003 100644 --- a/src/images/networks/bsc.svg +++ b/src/images/networks/bsc.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/images/networks/canto.svg b/src/images/networks/canto.svg index 107cd10..c4e14c1 100644 --- a/src/images/networks/canto.svg +++ b/src/images/networks/canto.svg @@ -1,5 +1,4 @@ - - + \ No newline at end of file diff --git a/src/images/networks/celo.svg b/src/images/networks/celo.svg index d9a900a..fe00d18 100644 --- a/src/images/networks/celo.svg +++ b/src/images/networks/celo.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/images/networks/cronos.svg b/src/images/networks/cronos.svg index 5772990..c5dc593 100644 --- a/src/images/networks/cronos.svg +++ b/src/images/networks/cronos.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/images/networks/emerald.svg b/src/images/networks/emerald.svg index 047bc09..99bfaa5 100644 --- a/src/images/networks/emerald.svg +++ b/src/images/networks/emerald.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/images/networks/ethereum.svg b/src/images/networks/ethereum.svg index 311e1e7..2789162 100644 --- a/src/images/networks/ethereum.svg +++ b/src/images/networks/ethereum.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/images/networks/fantom.svg b/src/images/networks/fantom.svg index e8bda3d..fc2d60c 100644 --- a/src/images/networks/fantom.svg +++ b/src/images/networks/fantom.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/images/networks/fuse.svg b/src/images/networks/fuse.svg index 523fbd7..a2fd1e0 100644 --- a/src/images/networks/fuse.svg +++ b/src/images/networks/fuse.svg @@ -1,4 +1,4 @@ - + diff --git a/src/images/networks/gnosis.svg b/src/images/networks/gnosis.svg new file mode 100644 index 0000000..3f6c466 --- /dev/null +++ b/src/images/networks/gnosis.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/images/networks/harmony.svg b/src/images/networks/harmony.svg index 8b80aae..f81909e 100644 --- a/src/images/networks/harmony.svg +++ b/src/images/networks/harmony.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/images/networks/heco.svg b/src/images/networks/heco.svg index 6fdcaaa..810327f 100644 --- a/src/images/networks/heco.svg +++ b/src/images/networks/heco.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/images/networks/kava.svg b/src/images/networks/kava.svg index 3bb3364..4ae7438 100644 --- a/src/images/networks/kava.svg +++ b/src/images/networks/kava.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/images/networks/metis.svg b/src/images/networks/metis.svg index caefe10..640b124 100644 --- a/src/images/networks/metis.svg +++ b/src/images/networks/metis.svg @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/src/images/networks/moonbeam.svg b/src/images/networks/moonbeam.svg index b31c84e..e38180e 100644 --- a/src/images/networks/moonbeam.svg +++ b/src/images/networks/moonbeam.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/images/networks/moonriver.svg b/src/images/networks/moonriver.svg index 167a848..539587d 100644 --- a/src/images/networks/moonriver.svg +++ b/src/images/networks/moonriver.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/images/networks/optimism.svg b/src/images/networks/optimism.svg index d3cafba..cbb1a40 100644 --- a/src/images/networks/optimism.svg +++ b/src/images/networks/optimism.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/images/networks/polygon.svg b/src/images/networks/polygon.svg index 7cf2d69..1008cc8 100644 --- a/src/images/networks/polygon.svg +++ b/src/images/networks/polygon.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/images/networks/zkevm.svg b/src/images/networks/zkevm.svg index a9ccf26..c19ec96 100644 --- a/src/images/networks/zkevm.svg +++ b/src/images/networks/zkevm.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/images/networks/zksync.svg b/src/images/networks/zksync.svg index 6cf65bf..61d60c2 100644 --- a/src/images/networks/zksync.svg +++ b/src/images/networks/zksync.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/theme.ts b/src/theme.ts index 64c2005..2e11639 100644 --- a/src/theme.ts +++ b/src/theme.ts @@ -90,10 +90,10 @@ class Theme { fantom: '#1969FF', harmony: '#01d8af', arbitrum: '#2d374b', - celo: '#35cf7f', + celo: '#FCFF52', moonriver: '#c3136f', cronos: '#121926', - fuse: '#c0db64', + fuse: '#B4F9BA', metis: '#00dacc', aurora: '#70d44b', moonbeam: '#211438', @@ -104,6 +104,8 @@ class Theme { canto: '#06fc99', zksync: '#fff', zkevm: '#8247e4', + base: '#fff', + gnosis: '#133629', }; public spacing(times: number = 1) { diff --git a/src/utils/network-utils.ts b/src/utils/network-utils.ts new file mode 100644 index 0000000..9f12a07 --- /dev/null +++ b/src/utils/network-utils.ts @@ -0,0 +1,12 @@ +const networkIconRequire = require.context('../images/networks', false, /\.svg$/); +const networkToFile = Object.fromEntries( + networkIconRequire.keys().map(path => [path.substring(2, path.lastIndexOf('.')), path]) +); + +export function getNetworkIconSrc(chainId: string) { + if (chainId in networkToFile) { + return networkIconRequire(networkToFile[chainId]).default; + } + + throw new Error(`No network icon found for ${chainId}`); +} diff --git a/yarn.lock b/yarn.lock index 45fa9cb..f5ade3d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2995,6 +2995,21 @@ dependencies: "@types/node" "*" +"@types/stats.js@*": + version "0.17.3" + resolved "https://registry.yarnpkg.com/@types/stats.js/-/stats.js-0.17.3.tgz#705446e12ce0fad618557dd88236f51148b7a935" + integrity sha512-pXNfAD3KHOdif9EQXZ9deK82HVNaXP5ZIF5RP2QG6OQFNTaY2YIetfrE9t528vEreGQvEPRDDc8muaoYeK0SxQ== + +"@types/three@^0.158.3": + version "0.158.3" + resolved "https://registry.yarnpkg.com/@types/three/-/three-0.158.3.tgz#f53e26c50709c7f972934e4e8c1ca51add0cfa9f" + integrity sha512-6Qs1rUvLSbkJ4hlIe6/rdwIf61j1x2UKvGJg7s8KjswYsz1C1qDTs6voVXXB8kYaI0hgklgZgbZUupfL1l9xdA== + dependencies: + "@types/stats.js" "*" + "@types/webxr" "*" + fflate "~0.6.10" + meshoptimizer "~0.18.1" + "@types/tmp@^0.0.33": version "0.0.33" resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.0.33.tgz#1073c4bc824754ae3d10cfab88ab0237ba964e4d" @@ -3022,6 +3037,11 @@ dependencies: "@types/node" "*" +"@types/webxr@*": + version "0.5.10" + resolved "https://registry.yarnpkg.com/@types/webxr/-/webxr-0.5.10.tgz#19c76208ec015ca3f139505e14d94d6b740f518a" + integrity sha512-n3u5sqXQJhf1CS68mw3Wf16FQ4cRPNBBwdYLFzq3UddiADOim1Pn3Y6PBdDilz1vOJF3ybLxJ8ZEDlLIzrOQZg== + "@types/yoga-layout@1.9.2": version "1.9.2" resolved "https://registry.yarnpkg.com/@types/yoga-layout/-/yoga-layout-1.9.2.tgz#efaf9e991a7390dc081a0b679185979a83a9639a" @@ -5882,6 +5902,11 @@ fd@~0.0.2: resolved "https://registry.yarnpkg.com/fd/-/fd-0.0.3.tgz#b3240de86dbf5a345baae7382a07d4713566ff0c" integrity sha512-iAHrIslQb3U68OcMSP0kkNWabp7sSN6d2TBSb2JO3gcLJVDd4owr/hKM4SFJovFOUeeXeItjYgouEDTMWiVAnA== +fflate@~0.6.10: + version "0.6.10" + resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.6.10.tgz#5f40f9659205936a2d18abf88b2e7781662b6d43" + integrity sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg== + figures@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" @@ -8608,6 +8633,11 @@ meros@1.1.4: resolved "https://registry.yarnpkg.com/meros/-/meros-1.1.4.tgz#c17994d3133db8b23807f62bec7f0cb276cfd948" integrity sha512-E9ZXfK9iQfG9s73ars9qvvvbSIkJZF5yOo9j4tcwM5tN8mUKfj/EKN5PzOr3ZH0y5wL7dLAHw3RVEfpQV9Q7VQ== +meshoptimizer@~0.18.1: + version "0.18.1" + resolved "https://registry.yarnpkg.com/meshoptimizer/-/meshoptimizer-0.18.1.tgz#cdb90907f30a7b5b1190facd3b7ee6b7087797d8" + integrity sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw== + methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" @@ -11508,6 +11538,11 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== +three@^0.158.0: + version "0.158.0" + resolved "https://registry.yarnpkg.com/three/-/three-0.158.0.tgz#03ddd5b60ce9c31be8fb69f27a6d9efd49908ac3" + integrity sha512-TALj4EOpdDPF1henk2Q+s17K61uEAAWQ7TJB68nr7FKxqwyDr3msOt5IWdbGm4TaWKjrtWS8DJJWe9JnvsWOhQ== + through@^2.3.6, through@^2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"