9 | [](https://pmndrs.github.io/xr/examples/room-with-shadows/)
10 |
11 |
12 | [](https://pmndrs.github.io/xr/examples/stage/)
13 |
14 |
15 | [](https://pmndrs.github.io/xr/examples/rag-doll/)
16 |
17 |
18 | [](https://pmndrs.github.io/xr/examples/watch/)
19 |
20 |
21 | [](https://pmndrs.github.io/xr/examples/minecraft/)
22 |
23 |
24 | [](https://pmndrs.github.io/xr/examples/pingpong/)
25 |
26 |
27 | [](https://pmndrs.github.io/xr/examples/layers/)
28 |
29 |
30 | [](https://pmndrs.github.io/xr/examples/secondary-input-sources/)
31 |
32 |
33 | [](https://pmndrs.github.io/xr/examples/editor/)
34 |
35 |
36 | [](https://pmndrs.github.io/xr/examples/hit-testing/)
37 | by [Sung Powley](https://bsky.app/profile/sung-powley.bsky.social)
38 |
39 |
40 | [](https://pmndrs.github.io/xr/examples/uikit/)
41 |
42 |
43 | [](https://pmndrs.github.io/xr/examples/portal/)
44 |
10 | 
11 | [Spatial development hub](https://volu.dev)
12 |
13 |
14 |
15 | Are we missing your public product? Please message us via [Twitter](https://x.com/BelaBohlender) or [Discord](https://discord.gg/poimandres).
--------------------------------------------------------------------------------
/docs/getting-started/showcases/volu-dev.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pmndrs/xr/82c1b0320e6e3bf06e464fdf2ae4a62fb50ad251/docs/getting-started/showcases/volu-dev.gif
--------------------------------------------------------------------------------
/docs/getting-started/stage-demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pmndrs/xr/82c1b0320e6e3bf06e464fdf2ae4a62fb50ad251/docs/getting-started/stage-demo.gif
--------------------------------------------------------------------------------
/docs/getting-started/uikit.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pmndrs/xr/82c1b0320e6e3bf06e464fdf2ae4a62fb50ad251/docs/getting-started/uikit.gif
--------------------------------------------------------------------------------
/docs/getting-started/watch-demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pmndrs/xr/82c1b0320e6e3bf06e464fdf2ae4a62fb50ad251/docs/getting-started/watch-demo.gif
--------------------------------------------------------------------------------
/docs/handles/annotated-door.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pmndrs/xr/82c1b0320e6e3bf06e464fdf2ae4a62fb50ad251/docs/handles/annotated-door.jpg
--------------------------------------------------------------------------------
/docs/handles/door-handle.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pmndrs/xr/82c1b0320e6e3bf06e464fdf2ae4a62fb50ad251/docs/handles/door-handle.gif
--------------------------------------------------------------------------------
/docs/handles/editor.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pmndrs/xr/82c1b0320e6e3bf06e464fdf2ae4a62fb50ad251/docs/handles/editor.gif
--------------------------------------------------------------------------------
/docs/handles/pivot.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pmndrs/xr/82c1b0320e6e3bf06e464fdf2ae4a62fb50ad251/docs/handles/pivot.gif
--------------------------------------------------------------------------------
/docs/handles/prebuild-handles.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pmndrs/xr/82c1b0320e6e3bf06e464fdf2ae4a62fb50ad251/docs/handles/prebuild-handles.gif
--------------------------------------------------------------------------------
/docs/handles/react-three-handle-gif-1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pmndrs/xr/82c1b0320e6e3bf06e464fdf2ae4a62fb50ad251/docs/handles/react-three-handle-gif-1.gif
--------------------------------------------------------------------------------
/docs/handles/transform.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pmndrs/xr/82c1b0320e6e3bf06e464fdf2ae4a62fb50ad251/docs/handles/transform.gif
--------------------------------------------------------------------------------
/docs/migration/from-natuerlich.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: from Natuerlich
3 | description: Migrate your application from natuerlich
4 | nav: 24
5 | ---
6 |
7 | @react-three/xr is inspired by natuerlich, and therefore, many things are similar, especially the way interactions are handled. However, a few things have been changed and renamed.
8 |
9 | - use `XROrigin` instead of `ImmersiveSessionOrigin`
10 | - use `` instead of `XRCanvas`
11 | - configure settings such as `foveation` through `createXRStore`
12 | - use `store.enterXR` instead of `useEnterXR`
13 | - use `DragControls` **TBD** instead of `Grabbale`
14 | - don't add hands and controllers yourself, and configure them through the `createXRStore` options. Click [here](../tutorials/custom-inputs.md) for more info regarding controller/hand/... customization.
15 | - use teleport as described [here](../tutorials/teleport.md)
16 |
--------------------------------------------------------------------------------
/docs/migration/from-react-three-xr-5.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: from @react-three/xr v5
3 | description: Migrate your application from @react-three/xr v5
4 | nav: 23
5 | ---
6 |
7 | The goal of @react-three/xr v6 is to align this library closer to the react-three ecosystem. We, therefore, focussed on supporting the react-three/fiber event handlers. Another focus of v6 is to reduce boilerplate and provide more defaults while also giving developers more access to the lower-level WebXR primitives. In combination, these changes allow developers to build XR experiences that interoperate with the whole react-three ecosystem using only a few lines of code.
8 |
9 | For everybody that is transitioning from v5 to v6, we have created a small compatibility layer that includes `XRButton`, `ARButton`, `VRButton`, `useInteraction`, `useXREvent`, `Interactive`, and `RayGrab`. However, we recommend transitioning away from the compatibility layer as the new recommended way of building with @react-three/xr is more aligned with the whole react-three ecosystem.
10 |
11 | For the `Controllers` and `Hands` components there are not correspondances in @react-three/xr v6 since input methods such as controllers, hands, but also transient-pointers are added by default. Users can configure the default implementation of those input methods as described [here](../tutorials/custom-inputs.md). The teleportation feature of @react-three/xr v5 has also slightly changed. The new API is explained [here](../tutorials/teleport.md).
--------------------------------------------------------------------------------
/docs/tutorials/anchors.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Anchors
3 | description: How to create and manage anchors in your AR experience?
4 | nav: 17
5 | ---
6 |
7 | Anchors allow to anchor virtual objects into the physical world in AR experiences. `react-three/xr` offers a multitude of ways to create and manage anchors. A simple solution is `useXRAnchor`, which works similarly to `useState` as it returns the current anchor and a function to request a new anchor as a tuple.
8 |
9 | ```tsx
10 | const [anchor, requestAnchor] = useXRAnchor()
11 | ```
12 |
13 | With the `requestAnchor` function, we can request an anchor relative to the `"world"`, a `"space"`, or a `"hitTestResult"`
14 |
15 | ```tsx
16 | requestAnchor({ relativeTo: "space", space: ... })
17 | ```
18 |
19 | Once the anchor is created, the `useXRAnchor` hook exposes it as `anchor`. We can now use this `anchor` to put content into it using the `` component.
20 |
21 | ```tsx
22 | ...your content
23 | ```
24 |
25 | The following example shows a `Anchor` component that uses the `useXRAnchor` hook and the `XRSpace` component to anchor a Box to the position of the right hand or controller when the respective hand or controller is selected (pinch/trigger).
26 |
27 | ```tsx
28 | export function Anchor() {
29 | const [anchor, requestAnchor] = useXRAnchor()
30 | const controllerState = useXRInputSourceState('controller', 'right')
31 | const handState = useXRInputSourceState('hand', 'right')
32 | const inputSource = controllerState?.inputSource ?? handState?.inputSource
33 | useXRInputSourceEvent(
34 | inputSource,
35 | 'select',
36 | async () => {
37 | if (inputSource == null) {
38 | return
39 | }
40 | requestAnchor({ relativeTo: 'space', space: inputSource.targetRaySpace })
41 | },
42 | [requestAnchor, inputSource],
43 | )
44 | if (anchor == null) {
45 | return null
46 | }
47 | return (
48 |
49 |
50 |
51 |
52 |
53 | )
54 | }
55 | ```
56 |
--------------------------------------------------------------------------------
/docs/tutorials/dom-overlay.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Dom Overlay
3 | description: How to add HTML elements for hand-held AR experiences with Dom overlay?
4 | nav: 18
5 | ---
6 |
7 | For hand-held AR experiences, such as those using a Smartphone, WebXR offers the dom overlay capability, allowing developers to use HTML code overlayed over the experience. In case scene 3D overlays or overlays in non-handheld AR/VR experiences are needed, check out [pmndrs/uikit](https://github.com/pmndrs/uikit).
8 |
9 | We can add dom overlay content to an experience using the `XRDomOverlay` component, which allows to write html code inside it. This HTML code will be overlayed over the hand-held AR experience.
10 |
11 | ```tsx
12 |
15 |
Hello World
16 |
17 | ```
18 |
19 | The following shows the complete code for a simple AR experience with a `Hello World` button that can toggle its color when clicked on.
20 |
21 | ```tsx
22 | const store = createXRStore()
23 |
24 | export function App() {
25 | const [bool, setBool] = useState(false)
26 | return (
27 | <>
28 |
29 |
44 | >
45 | )
46 | }
47 | ```
48 |
--------------------------------------------------------------------------------
/docs/tutorials/guards.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Guards
3 | description: Render and show parts of your application conditionally using guards
4 | nav: 20
5 | ---
6 |
7 | Guards allow to conditionally display or include content. For instance, the `IfInSessionMode` guard allows only displaying a background when the session is not an AR session. The `IfInSessionMode` can receive either a list of `allow` session modes or a list of `deny` session modes.
8 |
9 | ```tsx
10 | import { Canvas } from '@react-three/fiber'
11 | import { IfInSessionMode, XR, createXRStore } from '@react-three/xr'
12 |
13 | const store = createXRStore()
14 |
15 | export function App() {
16 | return (
17 | <>
18 |
19 |
26 | >
27 | )
28 | }
29 | ```
30 |
--------------------------------------------------------------------------------
/docs/tutorials/hit-test.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Hit Test
3 | description: How to add hit testing capabilities to your AR experiences?
4 | nav: 19
5 | ---
6 |
7 | Hit testing allows to check intersections with real-world geometry in AR experiences. `@react-three/xr` provides various hooks and components for setting up hit testing.
8 | The following example shows how to set up a hit test inside the right hand using the `XRHitTest` component, how to get the first hit test result using the `onResults` callback, and how to get the world position of that result into a vector.
9 |
10 | ```tsx
11 | const matrixHelper = new Matrix4()
12 | const hitTestPosition = new Vector3()
13 |
14 | const store = createXRStore({
15 | hand: {
16 | right: () => {
17 | const state = useXRHandState()
18 | return (
19 | <>
20 |
21 | {
24 | if (results.length === 0) {
25 | return
26 | }
27 | getWorldMatrix(matrixHelper, results[0])
28 | hitTestPosition.setFromMatrixPosition(matrixHelper)
29 | }}
30 | />
31 | >
32 | )
33 | },
34 | },
35 | })
36 | ```
37 |
38 | With the `hitTestPosition` containing the world position of the last hit test, we can use it to create a 3d object and sync it to the object's position on every frame.
39 |
40 | ```tsx
41 | function Point() {
42 | const ref = useRef(null)
43 | useFrame(() => ref.current?.position.copy(hitTestPosition))
44 | return (
45 |
46 |
47 |
48 |
49 | )
50 | }
51 | ```
52 |
53 | Alternatively, for devices that provide mesh detection, we can also add normal pointer events listeners to the XR Mesh to achieve the same behavior. Check out [this tutorial](./object-detection.md) for more information about mesh detection.
54 |
--------------------------------------------------------------------------------
/docs/tutorials/layers.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Layers
3 | description: How to use display images, videos, and custom renders at high quality on quad, cylinder, and equirectangular shapes?
4 | nav: 15
5 | ---
6 |
7 | Layers allow to render videos, images, and complete scenes with higher performance and higher quality while preserving battery life and latency for quad, cylinder, and equirectangular shapes using the WebXR Layer API. Layers are perfect for use cases that display flat, high-quality content, such as videos, images, and user interfaces. The following example illustrates how to create a layer that renders a video.
8 |
9 | First, we create a layer at `0, 1.5, -0.5` with a scale of `0.5` that displays a video assigned to `src` and starts that video when clicked.
10 |
11 | ```tsx
12 | video.play()} scale={0.5} src={video} />
13 | ```
14 |
15 | The assigned video is an HTML video element that is loaded from `test.mp4`.
16 |
17 | ```tsx
18 | const video = useMemo(() => {
19 | const result = document.createElement('video')
20 | result.src = 'test.mp4'
21 | return result
22 | }, [])
23 | ```
24 |
25 | Combined, the final app looks like this
26 |
27 | ```tsx
28 | export function App() {
29 | const video = useMemo(() => {
30 | const result = document.createElement('video')
31 | result.src = 'test.mp4'
32 | return result
33 | }, [])
34 | return (
35 |
40 | )
41 | }
42 | ```
43 |
44 | Instead of images and videos, Layers can also be used to display dynamically rendered content. The following example illustrates how to render a red cube onto the layer. This scene will be re-rendered every frame, allowing for fully dynamic content.
45 |
46 | ```tsx
47 |
48 |
49 |
50 |
51 |
52 |
53 | ```
54 |
--------------------------------------------------------------------------------
/docs/tutorials/object-detection.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Object Detection
3 | description: Use detected objects such as meshes and planes for rendering, scene understanding, physics, and more
4 | nav: 10
5 | ---
6 |
7 | @react-three/xr allows to use the devices mesh and plane detection functionality to detect the meshes and planes in the environment to modify the rendering, allow physics interactions with the environment, and more.
8 |
9 | ## Detected Planes
10 |
11 | The detected planes are accessible through the `useXRPlanes` hook or directly from `useXR(xr => xr.detectPlanes)` and manually go through the returned array. To render the planes in the correct place, the planes' space must provided to the `XRSpace` component. The following example shows how to render the red planes for all detected walls.
12 |
13 | ```tsx
14 | function RedWalls() {
15 | const wallPlanes = useXRPlanes('wall')
16 | return (
17 | <>
18 | {wallPlanes.map((plane) => (
19 |
20 |
21 |
22 |
23 |
24 | ))}
25 | >
26 | )
27 | }
28 | ```
29 |
30 | ## Detected Meshes
31 |
32 | Mesh detection provides access to the geometry of the environment. Similarly to xr planes, @react-three/fiber allows to retrieve detected meshes using `useXRMeshes` and offers the `XRMeshModel` to render the individual meshes.
33 |
--------------------------------------------------------------------------------
/docs/tutorials/secondary-input-sources.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Secondary Input Sources
3 | description: How to use primary and secondary input sources (multiple controllers and hands) simultaneously?
4 | nav: 14
5 | ---
6 |
7 | Most standalone XR headsets support hand and controller tracking. While typical XR experiences often support both input methods, they only use the primary inputs, which refers to one input per hand and limits the inputs to `2`. However, the headset often also tracks the secondary input sources. By enabling the `secondaryInputSources` flag when creating an xr store, we can access the secondary input sources and use them to track real-world objects, for example.
8 |
9 | ```ts
10 | createXRStore({ secondaryInputSources: true })
11 | ```
12 |
13 | Secondary input sources are exposed to the developer just like primary input sources, with the exception of the `isPrimary` flat, which is false. The following example illustrates how to show the primary input controllers using the default controller components while rendering the secondary input controllers as simple cubes.
14 |
15 | ```tsx
16 | createXRStore({
17 | secondaryInputSources: true,
18 | controller: () => {
19 | const { isPrimary } = useXRInputSourceStateContext('controller')
20 | if (isPrimary) {
21 | return
22 | }
23 | return (
24 |
25 |
26 |
27 | )
28 | },
29 | })
30 | ```
31 |
--------------------------------------------------------------------------------
/docs/tutorials/teleport-example.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pmndrs/xr/82c1b0320e6e3bf06e464fdf2ae4a62fb50ad251/docs/tutorials/teleport-example.gif
--------------------------------------------------------------------------------
/examples/demo-controller/.gitignore:
--------------------------------------------------------------------------------
1 | dist
--------------------------------------------------------------------------------
/examples/demo-controller/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Document
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/examples/demo-controller/index.tsx:
--------------------------------------------------------------------------------
1 | import { StrictMode } from 'react'
2 | import { createRoot } from 'react-dom/client'
3 | import { App } from './app.js'
4 |
5 | createRoot(document.getElementById('root')!).render(
6 |
7 |
8 | ,
9 | )
10 |
--------------------------------------------------------------------------------
/examples/demo-controller/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "@pmndrs/xr": "workspace:~",
4 | "@react-three/uikit": "^0.5.3",
5 | "@react-three/xr": "workspace:~"
6 | },
7 | "scripts": {
8 | "dev": "vite --host",
9 | "check:eslint": "eslint \"*.{ts,tsx}\"",
10 | "fix:eslint": "eslint \"*.{ts,tsx}\" --fix"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/examples/demo-controller/vite.config.ts:
--------------------------------------------------------------------------------
1 | import basicSsl from '@vitejs/plugin-basic-ssl'
2 | import react from '@vitejs/plugin-react'
3 | import { defineConfig } from 'vite'
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | plugins: [react(), basicSsl()],
8 | resolve: {
9 | dedupe: ['@react-three/fiber', 'three'],
10 | },
11 | })
12 |
--------------------------------------------------------------------------------
/examples/editor/.gitignore:
--------------------------------------------------------------------------------
1 | dist
--------------------------------------------------------------------------------
/examples/editor/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pmndrs/xr/82c1b0320e6e3bf06e464fdf2ae4a62fb50ad251/examples/editor/README.md
--------------------------------------------------------------------------------
/examples/editor/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Document
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/examples/editor/index.tsx:
--------------------------------------------------------------------------------
1 | import { StrictMode } from 'react'
2 | import { createRoot } from 'react-dom/client'
3 | import { App } from './app.js'
4 |
5 | createRoot(document.getElementById('root')!).render(
6 |
7 |
8 | ,
9 | )
10 |
--------------------------------------------------------------------------------
/examples/editor/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "@pmndrs/handle": "workspace:~",
4 | "@pmndrs/pointer-events": "workspace:~",
5 | "@react-three/handle": "workspace:~",
6 | "@react-three/xr": "workspace:~",
7 | "meshline": "^3.3.1",
8 | "postprocessing": "^6.36.6",
9 | "zustand": "^4.5.2"
10 | },
11 | "scripts": {
12 | "dev": "vite --host",
13 | "build": "vite build",
14 | "check:eslint": "eslint \"*.{ts,tsx}\"",
15 | "fix:eslint": "eslint \"*.{ts,tsx}\" --fix"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/examples/editor/public/camera.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pmndrs/xr/82c1b0320e6e3bf06e464fdf2ae4a62fb50ad251/examples/editor/public/camera.glb
--------------------------------------------------------------------------------
/examples/editor/public/end.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pmndrs/xr/82c1b0320e6e3bf06e464fdf2ae4a62fb50ad251/examples/editor/public/end.mp3
--------------------------------------------------------------------------------
/examples/editor/public/rotate.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pmndrs/xr/82c1b0320e6e3bf06e464fdf2ae4a62fb50ad251/examples/editor/public/rotate.glb
--------------------------------------------------------------------------------
/examples/editor/public/start.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pmndrs/xr/82c1b0320e6e3bf06e464fdf2ae4a62fb50ad251/examples/editor/public/start.mp3
--------------------------------------------------------------------------------
/examples/editor/public/sun.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pmndrs/xr/82c1b0320e6e3bf06e464fdf2ae4a62fb50ad251/examples/editor/public/sun.glb
--------------------------------------------------------------------------------
/examples/editor/vite.config.ts:
--------------------------------------------------------------------------------
1 | import basicSsl from '@vitejs/plugin-basic-ssl'
2 | import react from '@vitejs/plugin-react'
3 | import { defineConfig } from 'vite'
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | plugins: [react(), basicSsl()],
8 | base: '/xr/examples/editor/',
9 | resolve: {
10 | dedupe: ['@react-three/fiber', 'three'],
11 | },
12 | })
13 |
--------------------------------------------------------------------------------
/examples/handheld-ar/.gitignore:
--------------------------------------------------------------------------------
1 | dist
--------------------------------------------------------------------------------
/examples/handheld-ar/app.tsx:
--------------------------------------------------------------------------------
1 | import { Canvas } from '@react-three/fiber'
2 | import { createXRStore, XR, XRDomOverlay, XROrigin } from '@react-three/xr'
3 | import { useState } from 'react'
4 | import {} from '@react-three/drei'
5 |
6 | const store = createXRStore()
7 |
8 | export function App() {
9 | const [bool, setBool] = useState(false)
10 | return (
11 | <>
12 |
13 |
29 | >
30 | )
31 | }
32 |
--------------------------------------------------------------------------------
/examples/handheld-ar/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Document
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/examples/handheld-ar/index.tsx:
--------------------------------------------------------------------------------
1 | import { StrictMode } from 'react'
2 | import { createRoot } from 'react-dom/client'
3 | import { App } from './app.js'
4 |
5 | createRoot(document.getElementById('root')!).render(
6 |
7 |
8 | ,
9 | )
10 |
--------------------------------------------------------------------------------
/examples/handheld-ar/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "@react-three/xr": "workspace:~"
4 | },
5 | "scripts": {
6 | "dev": "vite --host",
7 | "check:eslint": "eslint \"*.{ts,tsx}\"",
8 | "fix:eslint": "eslint \"*.{ts,tsx}\" --fix"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/examples/handheld-ar/vite.config.ts:
--------------------------------------------------------------------------------
1 | import basicSsl from '@vitejs/plugin-basic-ssl'
2 | import react from '@vitejs/plugin-react'
3 | import { defineConfig } from 'vite'
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | plugins: [react(), basicSsl()],
8 | resolve: {
9 | dedupe: ['@react-three/fiber', 'three'],
10 | },
11 | })
12 |
--------------------------------------------------------------------------------
/examples/handle-vanilla/.gitignore:
--------------------------------------------------------------------------------
1 | dist
--------------------------------------------------------------------------------
/examples/handle-vanilla/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Document
7 |
8 |
9 |
10 |