Full Code of pmndrs/react-three-fiber for AI

master 9525ea0d63c8 cached
173 files
792.4 KB
284.4k tokens
415 symbols
1 requests
Download .txt
Showing preview only (842K chars total). Download the full file or copy to clipboard to get everything.
Repository: pmndrs/react-three-fiber
Branch: master
Commit: 9525ea0d63c8
Files: 173
Total size: 792.4 KB

Directory structure:
gitextract_tr77z8gq/

├── .changeset/
│   ├── README.md
│   └── config.json
├── .codesandbox/
│   └── ci.json
├── .eslintignore
├── .eslintrc.json
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   ├── issue_template.md
│   └── workflows/
│       ├── canary.yml
│       ├── docs.yml
│       └── test.yml
├── .gitignore
├── .husky/
│   ├── .gitignore
│   └── pre-commit
├── .prettierignore
├── .prettierrc
├── CONTRIBUTING.md
├── LICENSE
├── babel.config.js
├── docs/
│   ├── API/
│   │   ├── additional-exports.mdx
│   │   ├── canvas.mdx
│   │   ├── events.mdx
│   │   ├── hooks.mdx
│   │   ├── objects.mdx
│   │   ├── testing.mdx
│   │   └── typescript.mdx
│   ├── advanced/
│   │   ├── pitfalls.mdx
│   │   └── scaling-performance.mdx
│   ├── getting-started/
│   │   ├── basic-example-sandpack/
│   │   │   ├── index.jsx
│   │   │   └── styles.css
│   │   ├── community-r3f-components.mdx
│   │   ├── examples.mdx
│   │   ├── installation.mdx
│   │   ├── introduction.mdx
│   │   └── your-first-scene.mdx
│   └── tutorials/
│       ├── basic-animations.mdx
│       ├── events-and-interaction.mdx
│       ├── how-it-works.mdx
│       ├── loading-models.mdx
│       ├── loading-textures.mdx
│       └── v9-migration-guide.mdx
├── example/
│   ├── .gitignore
│   ├── CHANGELOG.md
│   ├── index.html
│   ├── package.json
│   ├── public/
│   │   ├── Parrot.glb
│   │   ├── Stork.glb
│   │   ├── apple.gltf
│   │   ├── bottle.gltf
│   │   ├── farm.gltf
│   │   ├── lightning.gltf
│   │   └── ramen.gltf
│   ├── src/
│   │   ├── App.tsx
│   │   ├── components.tsx
│   │   ├── demos/
│   │   │   ├── Activity.tsx
│   │   │   ├── AutoDispose.tsx
│   │   │   ├── ChangeTexture.tsx
│   │   │   ├── ClickAndHover.tsx
│   │   │   ├── ContextMenuOverride.tsx
│   │   │   ├── FlushSync.tsx
│   │   │   ├── Gestures.tsx
│   │   │   ├── Gltf.tsx
│   │   │   ├── Inject.tsx
│   │   │   ├── Layers.tsx
│   │   │   ├── Lines.tsx
│   │   │   ├── MultiMaterial.tsx
│   │   │   ├── MultiRender.tsx
│   │   │   ├── MultiView.tsx
│   │   │   ├── Pointcloud.tsx
│   │   │   ├── Portals.tsx
│   │   │   ├── Reparenting.tsx
│   │   │   ├── ResetProps.tsx
│   │   │   ├── SVGRenderer.tsx
│   │   │   ├── Selection.tsx
│   │   │   ├── StopPropagation.tsx
│   │   │   ├── SuspenseAndErrors.tsx
│   │   │   ├── SuspenseMaterial.tsx
│   │   │   ├── Test.tsx
│   │   │   ├── ViewTracking.tsx
│   │   │   ├── Viewcube.tsx
│   │   │   ├── WebGPU.tsx
│   │   │   └── index.tsx
│   │   ├── index.tsx
│   │   └── styles.css
│   ├── tsconfig.json
│   └── vite.config.ts
├── jest.config.js
├── package.json
├── packages/
│   ├── eslint-plugin/
│   │   ├── .npmignore
│   │   ├── CHANGELOG.md
│   │   ├── README.md
│   │   ├── docs/
│   │   │   └── rules/
│   │   │       ├── no-clone-in-loop.md
│   │   │       └── no-new-in-loop.md
│   │   ├── package.json
│   │   ├── scripts/
│   │   │   └── codegen.ts
│   │   ├── src/
│   │   │   ├── configs/
│   │   │   │   ├── all.ts
│   │   │   │   └── recommended.ts
│   │   │   ├── index.ts
│   │   │   ├── lib/
│   │   │   │   └── url.ts
│   │   │   └── rules/
│   │   │       ├── index.ts
│   │   │       ├── no-clone-in-loop.ts
│   │   │       └── no-new-in-loop.ts
│   │   └── tests/
│   │       └── rules/
│   │           ├── no-clone-in-loop.test.ts
│   │           └── no-new-in-loop.test.ts
│   ├── fiber/
│   │   ├── .npmignore
│   │   ├── CHANGELOG.md
│   │   ├── __mocks__/
│   │   │   ├── expo-asset.ts
│   │   │   ├── expo-file-system.ts
│   │   │   ├── expo-gl.ts
│   │   │   ├── react-native.ts
│   │   │   └── react-use-measure.ts
│   │   ├── native/
│   │   │   └── package.json
│   │   ├── package.json
│   │   ├── readme.md
│   │   ├── src/
│   │   │   ├── core/
│   │   │   │   ├── events.ts
│   │   │   │   ├── hooks.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   ├── loop.ts
│   │   │   │   ├── reconciler.tsx
│   │   │   │   ├── renderer.tsx
│   │   │   │   ├── store.ts
│   │   │   │   └── utils.tsx
│   │   │   ├── index.tsx
│   │   │   ├── native/
│   │   │   │   ├── Canvas.tsx
│   │   │   │   ├── events.ts
│   │   │   │   └── polyfills.ts
│   │   │   ├── native.tsx
│   │   │   ├── three-types.ts
│   │   │   └── web/
│   │   │       ├── Canvas.tsx
│   │   │       └── events.ts
│   │   └── tests/
│   │       ├── __snapshots__/
│   │       │   ├── canvas.native.test.tsx.snap
│   │       │   ├── canvas.test.tsx.snap
│   │       │   ├── index.test.tsx.snap
│   │       │   └── utils.test.ts.snap
│   │       ├── canvas.native.test.tsx
│   │       ├── canvas.test.tsx
│   │       ├── events.test.tsx
│   │       ├── hooks.test.tsx
│   │       ├── index.test.tsx
│   │       ├── polyfills.test.ts
│   │       ├── reconciler.test.ts
│   │       ├── renderer.test.tsx
│   │       └── utils.test.ts
│   ├── shared/
│   │   └── setupTests.ts
│   └── test-renderer/
│       ├── .npmignore
│       ├── CHANGELOG.md
│       ├── README.md
│       ├── markdown/
│       │   ├── rttr-instance.md
│       │   └── rttr.md
│       ├── package.json
│       └── src/
│           ├── WebGL2RenderingContext.ts
│           ├── __tests__/
│           │   ├── RTTR.core.test.tsx
│           │   ├── RTTR.events.test.tsx
│           │   ├── RTTR.hooks.test.tsx
│           │   ├── RTTR.methods.test.tsx
│           │   └── __snapshots__/
│           │       └── RTTR.core.test.tsx.snap
│           ├── createTestCanvas.ts
│           ├── createTestInstance.ts
│           ├── fireEvent.ts
│           ├── helpers/
│           │   ├── events.ts
│           │   ├── graph.ts
│           │   ├── strings.ts
│           │   ├── testInstance.ts
│           │   ├── tree.ts
│           │   └── waitFor.ts
│           ├── index.tsx
│           └── types/
│               ├── index.ts
│               ├── internal.ts
│               └── public.ts
├── readme.md
├── tsconfig.json
└── vite.config.ts

================================================
FILE CONTENTS
================================================

================================================
FILE: .changeset/README.md
================================================
# Changesets

Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
with multi-package repos, or single-package repos to help you version and publish your code. You can
find the full documentation for it [in our repository](https://github.com/changesets/changesets)

We have a quick list of common questions to get you started engaging with this project in
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)


================================================
FILE: .changeset/config.json
================================================
{
  "$schema": "https://unpkg.com/@changesets/config@1.6.0/schema.json",
  "changelog": "@changesets/changelog-git",
  "commit": true,
  "linked": [],
  "access": "public",
  "baseBranch": "master",
  "updateInternalDependencies": "minor",
  "ignore": [],
  "___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": {
    "onlyUpdatePeerDependentsWhenOutOfRange": true
  }
}


================================================
FILE: .codesandbox/ci.json
================================================
{
  "sandboxes": ["/example"],
  "node": "18"
}


================================================
FILE: .eslintignore
================================================
dist/
node_modules/
.yarn/

================================================
FILE: .eslintrc.json
================================================
{
  "env": {
    "browser": true,
    "es6": true,
    "node": true
  },
  "extends": [
    "prettier",
    "plugin:prettier/recommended",
    "plugin:react-hooks/recommended",
    "plugin:import/recommended",
    "plugin:@react-three/recommended"
  ],
  "plugins": ["@typescript-eslint", "react", "react-hooks", "import", "jest", "prettier", "@react-three"],
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "ecmaFeatures": {
      "jsx": true
    },
    "ecmaVersion": 2018,
    "sourceType": "module",
    "rules": {
      "curly": ["warn", "multi-line", "consistent"],
      "no-console": "off",
      "no-empty-pattern": "warn",
      "no-duplicate-imports": "error",
      "import/no-unresolved": "off",
      "import/export": "error",
      // https://github.com/typescript-eslint/typescript-eslint/blob/master/docs/getting-started/linting/FAQ.md#eslint-plugin-import
      // We recommend you do not use the following import/* rules, as TypeScript provides the same checks as part of standard type checking:
      "import/named": "off",
      "import/namespace": "off",
      "import/default": "off",
      "no-unused-vars": ["warn", { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_" }],
      "@typescript-eslint/no-unused-vars": ["warn", { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_" }],
      "@typescript-eslint/no-use-before-define": "off",
      "@typescript-eslint/no-empty-function": "off",
      "@typescript-eslint/no-empty-interface": "off",
      "@typescript-eslint/no-explicit-any": "off",
      "jest/consistent-test-it": ["error", { "fn": "it", "withinDescribe": "it" }]
    }
  },
  "settings": {
    "react": {
      "version": "detect"
    },
    "import/extensions": [".js", ".jsx", ".ts", ".tsx"],
    "import/parsers": {
      "@typescript-eslint/parser": [".js", ".jsx", ".ts", ".tsx"]
    },
    "import/resolver": {
      "node": {
        "extensions": [".js", ".jsx", ".ts", ".tsx", ".json"],
        "paths": ["src"]
      },
      "alias": {
        "extensions": [".js", ".jsx", ".ts", ".tsx", ".json"],
        "map": [["@react-three/fiber", "./packages/fiber/src/web"]]
      }
    }
  },
  "overrides": [
    {
      "files": ["src"],
      "parserOptions": {
        "project": "./tsconfig.json"
      }
    }
  ],
  "rules": {
    "import/no-unresolved": "off",
    "import/named": "off",
    "import/namespace": "off",
    "import/no-named-as-default-member": "off"
  }
}


================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms

github: drcmda
open_collective: react-three-fiber


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---

👋 hi there, for issues that aren't that pressing, that could be related to threejs etc, please consider [github discussions](https://github.com/pmndrs/react-three-fiber/discussions).


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---


================================================
FILE: .github/issue_template.md
================================================
Hi, 👋

if this is about a bug, before you go ahead, please do us a favour and make sure to check the [threejs issue tracker](https://github.com/mrdoob/three.js/issues) for the problem you are experiencing. This library is just a soft wrap around threejs without direct dependencies. So if something is flipped upside down, or doesn't project the way you intent to, there's a good chance others will have experienced the same issue with plain threejs.


================================================
FILE: .github/workflows/canary.yml
================================================
name: Canary Release

on:
  push:
    branches: [v10]
  workflow_dispatch:

permissions:
  id-token: write # Required for npm OIDC
  contents: read

jobs:
  canary:
    name: Publish canary
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repo
        uses: actions/checkout@v4

      - name: Install pnpm
        uses: pnpm/action-setup@v4
        with:
          run_install: false

      - name: Use Node 22
        uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: 'pnpm'
          registry-url: 'https://registry.npmjs.org'

      - name: Update npm for OIDC
        run: npm install -g npm@latest

      - name: Install deps
        run: pnpm install

      - name: Build
        run: pnpm build

      - name: Set canary versions
        run: |
          CANARY_VERSION="10.0.0-canary.$(git rev-parse --short HEAD)"
          echo "Publishing canary version: $CANARY_VERSION"
          cd packages/fiber && npm version $CANARY_VERSION --no-git-tag-version
          cd ../eslint-plugin && npm version $CANARY_VERSION --no-git-tag-version
          cd ../test-renderer && npm version $CANARY_VERSION --no-git-tag-version

      - name: Publish to npm
        run: |
          pnpm --filter @react-three/fiber publish --tag canary --no-git-checks --provenance
          pnpm --filter @react-three/eslint-plugin publish --tag canary --no-git-checks --provenance
          pnpm --filter @react-three/test-renderer publish --tag canary --no-git-checks --provenance


================================================
FILE: .github/workflows/docs.yml
================================================
name: Build documentation and deploy to GitHub Pages
on:
  push:
    branches: ['master']
  workflow_dispatch:

# Cancel previous run (see: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#concurrency)
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  build:
    uses: pmndrs/docs/.github/workflows/build.yml@v3
    with:
      mdx: 'docs'
      libname: 'React Three Fiber'
      libname_short: 'r3f'
      home_redirect: '/getting-started/introduction'
      icon: '🇨🇭'
      logo: '/logo.jpg'
      github: 'https://github.com/pmndrs/react-three-fiber'
      discord: 'https://discord.com/channels/740090768164651008/740093168770613279'

  deploy:
    needs: build
    runs-on: ubuntu-latest

    # Grant GITHUB_TOKEN the permissions required to make a Pages deployment
    permissions:
      pages: write # to deploy to Pages
      id-token: write # to verify the deployment originates from an appropriate source

    # Deploy to the github-pages environment
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}

    steps:
      - id: deployment
        uses: actions/deploy-pages@v4


================================================
FILE: .github/workflows/test.yml
================================================
name: Test
on:
  push:
    branches:
      - 'master'
  pull_request: {}
jobs:
  build:
    name: Build, lint, and test (React ${{ matrix.react-version }})
    runs-on: ubuntu-latest

    strategy:
      fail-fast: false
      matrix:
        react-version:
          - 19.0.0
          - latest

    steps:
      - name: Checkout repo
        uses: actions/checkout@v4

      - name: Use Node 20
        uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Cache node_modules and Yarn cache
        uses: actions/cache@v4
        with:
          path: |
            **/node_modules
            .yarn/cache
          key: >
            ${{ runner.os }}-node20-react-${{ matrix.react-version }}-${{ hashFiles('**/yarn.lock') }}
          restore-keys: |
            ${{ runner.os }}-node20-react-${{ matrix.react-version }}-

      - name: Install deps and build (with cache)
        uses: bahmutov/npm-install@v1
        with:
          install-command: yarn --immutable --silent

      - name: Override React version (${{ matrix.react-version }})
        run: |
          yarn add @types/react@${{ matrix.react-version }} react@${{ matrix.react-version }} @types/react-dom@${{ matrix.react-version }} react-dom@${{ matrix.react-version }} --dev -W

      - name: Check types
        run: yarn run typecheck

      - name: Check lint
        run: yarn run eslint

      - name: Build
        run: yarn run build

      - name: Rsbuild (strict)
        run: yarn add @rsbuild/core -D -W && yarn rsbuild build --root ./packages/fiber

      - name: Jest run
        run: yarn run dev && yarn run test

      - name: Report Fiber size
        run: yarn run analyze-fiber

      - name: Report Test Renderer size
        run: yarn run analyze-test

      - name: Check formatting
        run: yarn run format


================================================
FILE: .gitignore
================================================
node_modules/
coverage/
dist/
build/
types/
packages/fiber/react-reconciler/
# commit types in src
!packages/*/src/types/
Thumbs.db
ehthumbs.db
Desktop.ini
$RECYCLE.BIN/
.DS_Store
.vscode
.docz/
package-lock.json
coverage/
.idea
yarn-error.log
.size-snapshot.json
__tests__/__image_snapshots__/__diff_output__


================================================
FILE: .husky/.gitignore
================================================
_


================================================
FILE: .husky/pre-commit
================================================
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx pretty-quick --staged


================================================
FILE: .prettierignore
================================================
dist/
coverage/
node_modules/
packages/fiber/react-reconciler/
.yarn/
*.gltf
*.mdx

================================================
FILE: .prettierrc
================================================
{
  "semi": false,
  "trailingComma": "all",
  "singleQuote": true,
  "tabWidth": 2,
  "printWidth": 120,
  "bracketSameLine": true,
  "endOfLine": "auto"
}


================================================
FILE: CONTRIBUTING.md
================================================
## Contributing

This project uses [semantic commits](https://conventionalcommits.org) and [semver](https://semver.org).

To get started, make sure you have [Node](https://nodejs.org) and [Yarn 1](https://classic.yarnpkg.com) (newer versions of Yarn do not work) installed. Install dependencies with:

```bash
yarn
```

[Preconstruct](https://github.com/preconstruct/preconstruct) will automatically build and link packages for local development via symlinks. If you ever need to do this manually, try running:

```bash
yarn dev
```

> **Note**: Some Windows users may need to [enable developer mode](https://howtogeek.com/292914/what-is-developer-mode-in-windows-10) if experiencing `EPERM: operation not permitted, symlink` with Preconstruct. If this persists, you might be running on an unsupported drive/format. In which case, consider using [Docker](https://docs.docker.com/docker-for-windows).

### Development

Locally run examples against the library with:

```bash
yarn examples
```

### Testing

Run test suites against the library with:

```bash
yarn test

# or, to test live against changes
yarn test:watch
```

If your code invalidates a snapshot, you can update it with:

```bash
yarn test -u
```

> **Note**: Use discretion when updating snapshots, as they represent the integrity of the package.
>
> If the difference is complex or you're unsure of the changes, leave it for review and we'll unblock it.

### Publishing

We use [atlassian/changesets](https://github.com/atlassian/changesets) to publish our packages, which will automatically document and version changes.

To publish a release on NPM, run the following and complete the dialog (see [FAQ](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)):

```bash
# Describe the changes you've made as you would semantic commits for CHANGELOG.md
yarn changeset:add

# Tag which packages should receive an update and be published.
yarn vers

# Commit and publish changes to NPM.
yarn release
```

We don't have automatic CI deployments yet, so make sure to [create a release](https://github.com/pmndrs/react-three-fiber/releases/new) on GitHub to notify people when it's ready. Choose or create the version generated by your changeset, and you can leave the rest to auto-fill via the "Generate release notes" button to describe PRs since the last release.

### Prerelease

Follow the same steps as before, but specify a tag for [prerelease mode](https://github.com/changesets/changesets/blob/main/docs/prereleases.md) with:

```bash
yarn changeset pre enter <alpha | beta | rc>
```

To cancel or leave prerelease mode, try running:

```bash
yarn changeset pre exit
```


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2019-2025 Poimandres

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: babel.config.js
================================================
module.exports = {
  plugins: [],
  presets: [
    [
      '@babel/preset-env',
      {
        include: [
          '@babel/plugin-proposal-class-properties',
          '@babel/plugin-proposal-optional-chaining',
          '@babel/plugin-proposal-nullish-coalescing-operator',
          '@babel/plugin-proposal-numeric-separator',
          '@babel/plugin-proposal-logical-assignment-operators',
        ],
        bugfixes: true,
        loose: true,
        modules: false,
        targets: '> 1%, not dead, not ie 11, not op_mini all',
      },
    ],
    ['@babel/preset-react', { runtime: 'automatic' }],
    '@babel/preset-typescript',
  ],
}


================================================
FILE: docs/API/additional-exports.mdx
================================================
---
title: Additional Exports
nav: 8
---

| export               | usage                                                          |
| -------------------- | -------------------------------------------------------------- |
| `addEffect`          | Adds a global render callback which is called each frame       |
| `addAfterEffect`     | Adds a global after-render callback which is called each frame |
| `addTail`            | Adds a global callback which is called when rendering stops    |
| `buildGraph`         | Collects nodes and materials from a THREE.Object3D             |
| `flushGlobalEffects` | Flushes global render-effects for when manually driving a loop |
| `flushSync`          | Force React to flush any updates synchronously and immediately |
| `invalidate`         | Forces view global invalidation                                |
| `advance`            | Advances the frameloop (given that it's set to 'never')        |
| `extend`             | Extends the native-object catalogue                            |
| `createPortal`       | Creates a portal (it's a React feature for re-parenting)       |
| `createRoot`         | Creates a root that can render three JSX into a canvas         |
| `events`             | Dom pointer-event system                                       |
| `applyProps`         | `applyProps(element, props)` sets element properties,          |
| `act`                | usage with react-testing                                       |
| `useInstanceHandle`  | Exposes react-internal local state from `instance.__r3f`       |
|                      |                                                                |


================================================
FILE: docs/API/canvas.mdx
================================================
---
title: Canvas
description: The Canvas object is your portal into three.js
nav: 4
---

The `Canvas` object is where you start to define your React Three Fiber Scene.

```jsx
import React from 'react'
import { Canvas } from '@react-three/fiber'

const App = () => (
  <Canvas>
    <pointLight position={[10, 10, 10]} />
    <mesh>
      <sphereGeometry />
      <meshStandardMaterial color="hotpink" />
    </mesh>
  </Canvas>
)
```

## Properties

| Prop            | Description                                                                                                                                       | Default                                                    |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
| children        | three.js JSX elements or regular components                                                                                                       |                                                            |
| fallback        | optional DOM JSX elements or regular components in case GL is not supported                                                                       |                                                            |
| gl              | Props that go into the default renderer. Accepts sync/async callback with default props `gl={defaults => new Renderer({ ...defaults })}`          | `{}`                                                       |
| camera          | Props that go into the default camera, or your own `THREE.Camera`                                                                                 | `{ fov: 75, near: 0.1, far: 1000, position: [0, 0, 5] }`   |
| scene           | Props that go into the default scene, or your own `THREE.Scene`                                                                                   | `{}`                                                       |
| shadows         | Props that go into `gl.shadowMap`, can be set true for `PCFsoft` or one of the following: 'basic', 'percentage', 'soft', 'variance'               | `false`                                                    |
| raycaster       | Props that go into the default raycaster                                                                                                          | `{}`                                                       |
| frameloop       | Render mode: always, demand, never                                                                                                                | `always`                                                   |
| resize          | Resize config, see react-use-measure's options                                                                                                    | `{ scroll: true, debounce: { scroll: 50, resize: 0 } }`    |
| orthographic    | Creates an orthographic camera                                                                                                                    | `false`                                                    |
| dpr             | Pixel-ratio, use `window.devicePixelRatio`, or automatic: [min, max]                                                                              | `[1, 2]`                                                   |
| legacy          | Enables THREE.ColorManagement in three r139 or later                                                                                              | `false`                                                    |
| linear          | Switch off automatic sRGB color space and gamma correction                                                                                        | `false`                                                    |
| events          | Configuration for the event manager, as a function of state                                                                                       | `import { events } from "@react-three/fiber"`              |
| eventSource     | The source where events are being subscribed to, HTMLElement                                                                                      | `React.RefObject<HTMLElement>`, `gl.domElement.parentNode` |
| eventPrefix     | The event prefix that is cast into canvas pointer x/y events                                                                                      | `offset`                                                   |
| flat            | Use `THREE.NoToneMapping` instead of `THREE.ACESFilmicToneMapping`                                                                                | `false`                                                    |
| onCreated       | Callback after the canvas has rendered (but not yet committed)                                                                                    | `(state) => {}`                                            |
| onPointerMissed | Response for pointer clicks that have missed any target                                                                                           | `(event) => {}`                                            |

## Defaults

Canvas uses [createRoot](#createroot) which will create a translucent `THREE.WebGLRenderer` with the following constructor args:

- antialias=true
- alpha=true
- powerPreference="high-performance"

and with the following properties:

- outputColorSpace = THREE.SRGBColorSpace
- toneMapping = THREE.ACESFilmicToneMapping

It will also create the following scene internals:

- A `THREE.Perspective` camera
- A `THREE.Orthographic` cam if `orthographic` is true
- A `THREE.PCFSoftShadowMap` if `shadows` is true
- A `THREE.Scene` (into which all the JSX is rendered) and a `THREE.Raycaster`

In recent versions of threejs, `THREE.ColorManagement.enabled` will be set to `true` to enable automatic conversion of colors according to the renderer's configured color space. R3F will handle texture color space conversion. For more on this topic, see [https://threejs.org/docs/#manual/en/introduction/Color-management](https://threejs.org/docs/#manual/en/introduction/Color-management).

## Errors and fallbacks

On some systems WebGL may not be supported, you can provide a fallback component that will be rendered instead of the canvas:

```jsx
<Canvas fallback={<div>Sorry no WebGL supported!</div>}>
  <mesh />
</Canvas>
```

You should also safeguard the canvas against WebGL context crashes, for instance if users have the GPU disabled or GPU drivers are faulty.

```jsx
import { useErrorBoundary } from 'use-error-boundary'

function App() {
  const { ErrorBoundary, didCatch, error } = useErrorBoundary()
  return didCatch ? (
    <div>{error.message}</div>
  ) : (
    <ErrorBoundary>
      <Canvas>
        <mesh />
      </Canvas>
    </ErrorBoundary>
  )
}
```

> [!NOTE]
> Ideally, and if possible, your fallback is a seamless, visual replacement for what the canvas would have otherwise rendered.

## WebGPU

Recent Three.js now includes a WebGPU renderer. While still a work in progress and not fully backward-compatible with all of Three's features, the renderer requires an async initialization method. R3F streamlines this by allowing the gl prop to return a promise.

```tsx
import * as THREE from 'three/webgpu'
import * as TSL from 'three/tsl'
import { Canvas, extend, useFrame, useThree } from '@react-three/fiber'

declare module '@react-three/fiber' {
  interface ThreeElements extends ThreeToJSXElements<typeof THREE> {}
}

extend(THREE as any)

export default () => (
  <Canvas
    gl={async (props) => {
      const renderer = new THREE.WebGPURenderer(props as any)
      await renderer.init()
      return renderer
    }}>
      <mesh>
        <meshBasicNodeMaterial />
        <boxGeometry />
      </mesh>
  </Canvas>
)
```

## Custom Canvas

R3F can render to a root, similar to how `react-dom` and all the other React renderers work. This allows you to shave off `react-dom` (~40kb), `react-use-measure` (~3kb) and, if you don't need them, `pointer-events` (~7kb) (you need to explicitly import `events` and add them to the config otherwise).

Roots have the same options and properties as `Canvas`, but you are responsible for resizing it. It requires an existing DOM `<canvas>` object into which it renders.

### CreateRoot

Creates a root targeting a canvas, rendering JSX.

```jsx
import * as THREE from 'three'
import { extend, createRoot, events } from '@react-three/fiber'

// Register the THREE namespace as native JSX elements.
// See below for notes on tree-shaking
extend(THREE)

// Create a react root
const root = createRoot(document.querySelector('canvas'))

async function app() {
  // Configure the root, inject events optionally, set camera, etc
  // This *must* be called before render, and it must be awaited
  await root.configure({ events, camera: { position: [0, 0, 50] } })

  // createRoot by design is not responsive, you have to take care of resize yourself
  window.addEventListener('resize', () => {
    root.configure({ size: { width: window.innerWidth, height: window.innerHeight } })
  })

  // Trigger resize
  window.dispatchEvent(new Event('resize'))

  // Render entry point
  root.render(<App />)

  // Unmount and dispose of memory
  // root.unmount()
}

app()
```

## Tree-shaking

New with v8, the underlying reconciler no longer pulls in the THREE namespace automatically.

This enables a granular catalogue which also enables tree-shaking via the `extend` API:

```jsx
import { extend, createRoot } from '@react-three/fiber'
import { Mesh, BoxGeometry, MeshStandardMaterial } from 'three'

extend({ Mesh, BoxGeometry, MeshStandardMaterial })

createRoot(canvas).render(
  <>
    <mesh>
      <boxGeometry />
      <meshStandardMaterial />
    </mesh>
  </>,
)
```

There's an [official babel plugin](https://github.com/pmndrs/react-three-babel) which will do this for you automatically:

```jsx
// In:

import { createRoot } from '@react-three/fiber'

createRoot(canvasNode).render(
  <mesh>
    <boxGeometry />
    <meshStandardMaterial />
  </mesh>,
)

// Out:

import { createRoot, extend } from '@react-three/fiber'
import { Mesh as _Mesh, BoxGeometry as _BoxGeometry, MeshStandardMaterial as _MeshStandardMaterial } from 'three'

extend({
  Mesh: _Mesh,
  BoxGeometry: _BoxGeometry,
  MeshStandardMaterial: _MeshStandardMaterial,
})

createRoot(canvasNode).render(
  <mesh>
    <boxGeometry />
    <meshStandardMaterial />
  </mesh>,
)
```


================================================
FILE: docs/API/events.mdx
================================================
---
title: Events
description: All the events you can hook up to
nav: 7
---

`three.js` objects that implement their own `raycast` method (meshes, lines, etc) can be interacted with by declaring events on them. We support pointer events, clicks and wheel-scroll. Events contain the browser event as well as the `three.js` event data (object, point, distance, etc). You may want to [polyfill](https://github.com/jquery/PEP) them, if that's a concern.

Additionally, there's a special `onUpdate` that is called every time the object gets fresh props, which is good for things like `self => (self.verticesNeedUpdate = true)`.

Also notice the `onPointerMissed` on the canvas element, which fires on clicks that haven't hit _any_ meshes.

```jsx
<mesh
  onClick={(e) => console.log('click')}
  onContextMenu={(e) => console.log('context menu')}
  onDoubleClick={(e) => console.log('double click')}
  onWheel={(e) => console.log('wheel spins')}
  onPointerUp={(e) => console.log('up')}
  onPointerDown={(e) => console.log('down')}
  onPointerOver={(e) => console.log('over')}
  onPointerOut={(e) => console.log('out')}
  onPointerEnter={(e) => console.log('enter')} // see note 1
  onPointerLeave={(e) => console.log('leave')} // see note 1
  onPointerMove={(e) => console.log('move')}
  onPointerMissed={() => console.log('missed')}
  onUpdate={(self) => console.log('props have been updated')}
/>
```

### Event data

```jsx
({
  ...DomEvent                   // All the original event data
  ...Intersection                 // All of Three's intersection data - see note 2
  intersections: Intersection[]    // The first intersection of each intersected object
  object: Object3D              // The object that was actually hit
  eventObject: Object3D         // The object that registered the event
  unprojectedPoint: Vector3     // Camera-unprojected point
  ray: Ray                      // The ray that was used to strike the object
  camera: Camera                // The camera that was used in the raycaster
  sourceEvent: DomEvent         // A reference to the host event
  delta: number                 // Distance between mouse down and mouse up event in pixels
}) => ...
```

### How the event-system works, bubbling and capture

> [!NOTE]
> - `pointerenter` and `pointerleave` events work exactly the same as pointerover and pointerout.
> - `pointerenter` and `pointerleave` semantics are not implemented.

> [!NOTE]
> Some events (such as `pointerout`) happen when there is no intersection between `eventObject` and
the ray. When this happens, the event will contain intersection data from a previous event with
this object.

### Event propagation (bubbling)

Propagation works a bit differently to the DOM because objects can occlude each other in 3D. The `intersections` array in the event includes all objects intersecting the ray, not just the nearest. Only the first intersection with each object is included.
The event is first delivered to the object nearest the camera, and then bubbles up through its ancestors like in the DOM. After that, it is delivered to the next nearest object, and then its ancestors, and so on. This means objects are transparent to pointer events by default, even if the object handles the event.

`event.stopPropagation()` doesn't just stop this event from bubbling up, it also stops it from being delivered to farther objects (objects behind this one). All other objects, nearer or farther, no longer count as being hit while the pointer is over this object. If they were previously delivered pointerover events, they will immediately be delivered pointerout events. If you want an object to block pointer events from objects behind it, it needs to have an event handler as follows:

```jsx
onPointerOver={e => {
  e.stopPropagation()
  // ...
}}
```

even if you don't want this object to respond to the pointer event. If you do want to handle the event as well as using `stopPropagation()`, remember that the pointerout events will happen **during** the `stopPropagation()` call. You probably want your other event handling to happen after this.

### Pointer capture

Because events go to all intersected objects, capturing the pointer also works differently. In the DOM, the capturing object **replaces** the hit test, but in React Three Fiber, the capturing object is **added** to the hit test result: if the capturing object was not hit, then all of the hit objects (and their ancestors) get the event first, followed by the capturing object and its ancestors. The capturing object can also use `event.stopPropagation()` so that objects that really were hit get pointerout events.

Note that you can access the `setPointerCapture` and `releasePointerCapture` methods **only** via `event.target`: they don't get added to the `Object3D` instances in the scene graph.

`setPointerCapture` and `releasePointerCapture` take a `pointerId` parameter like in the DOM, but for now they don't have support for multiple active pointers. PRs are welcome!

```jsx
onPointerDown={e => {
  // Only the mesh closest to the camera will be processed
  e.stopPropagation()
  // You may optionally capture the target
  e.target.setPointerCapture(e.pointerId)
}}
onPointerUp={e => {
  e.stopPropagation()
  // Optionally release capture
  e.target.releasePointerCapture(e.pointerId)
}}
```

### Customizing the event settings

For some advanced usage it's possible to customize the setting of the event manager globally with the `events` prop on `<Canvas/>`:

```tsx
import { Canvas, events } from '@react-three/fiber'

const eventManagerFactory: Parameters<typeof Canvas>[0]['events'] = (state) => ({
  // Default configuration
  ...events(state),

  // Determines if the event layer is active
  enabled: true,

  // Event layer priority, higher prioritized layers come first and may stop(-propagate) lower layer
  priority: 1,

  // The filter can re-order or re-structure the intersections
  filter: (items: THREE.Intersection[], state: RootState) => items,

  // The compute defines how pointer events are translated into the raycaster and pointer vector2
  compute: (event: DomEvent, state: RootState, previous?: RootState) => {
    state.pointer.set((event.offsetX / state.size.width) * 2 - 1, -(event.offsetY / state.size.height) * 2 + 1)
    state.raycaster.setFromCamera(state.pointer, state.camera)
  },

  // Find more configuration default on ./packages/fiber/src/web/events.ts
  // And type definitions in ./packages/fiber/src/core/events.ts
})

function App() {
  return (
    <Canvas events={eventManagerFactory}>
}
```

### Using a different target element

There are cases in which you may want to connect the event handlers to another DOM element instead of the canvas. This is usually done to have events on a shared parent, which allows both the canvas, and dom overlays to receive events.

You can either use the event manager:

```jsx
const events => useThree(state => state.events)
useEffect(() => {
  state.events.connect(domNode)
```

Or, the `eventSource` shortcut on the canvas (DOM only), which accepts dom-nodes and React.RefObjects to dom-nodes.

```jsx
function App() {
  const target = useRef()
  return (
    <div ref={target}>
      <Canvas eventSource={target.current}>
```

### Using a different prefix (DOM only)

By default Fiber will use offsetX/offsetY to set up the raycaster. You can change this with the `eventPrefix` shortcut.

```jsx
function App() {
  return (
    <Canvas eventPrefix="client">
```

### Allow raycast without user interaction

By default Fiber will only raycast when the user is interacting with the canvas. If, for instance, the camera moves a hoverable object underneath the cursor it will not trigger a hover event. If this is wanted behaviour you can force a raycast by executing `update()`, call it whenever necessary.

```jsx
const events => useThree(state => state.events)
useEffect(() => {
  // Will trigger a onPointerMove with the last-known pointer event
  state.events.update()
```

You can abstract this into more complex logic.

```jsx
function RaycastWhenCameraMoves() {
  const matrix = new THREE.Matrix4()
  useFrame((state) => {
    // Act only when the camera has moved
    if (!matrix.equals(state.camera.matrixWorld)) {
      state.events.update()
      matrix.copy(state.camera.matrixWorld)
    }
  })
}
```


================================================
FILE: docs/API/hooks.mdx
================================================
---
title: Hooks
description: Hooks are the heart of react-three-fiber
nav: 6
---

Hooks allow you to tie or request specific information to your component. For instance, components that want to participate in the renderloop can use `useFrame`, components that need to be informed of three.js specifics can use `useThree` and so on. All hooks clean up after themselves once the component unmounts.

> [!NOTE]
> Hooks can only be used inside the Canvas element because they rely on context!

❌ You cannot expect something like this to work:

```jsx
import { useThree } from '@react-three/fiber'

function App() {
  const { size } = useThree() // This will just crash
  return (
    <Canvas>
      <mesh>
```

✅ Do this instead:

```jsx
function Foo() {
  const { size } = useThree()
  ...
}

function App() {
  return (
    <Canvas>
      <Foo />
```

## `useThree`

This hook gives you access to the state model which contains the default renderer, the scene, your camera, and so on. It also gives you the current size of the canvas in screen and viewport coordinates.

```jsx
import { useThree } from '@react-three/fiber'

function Foo() {
  const state = useThree()
```

The hook is reactive, if you resize the browser for instance, you get fresh measurements, same applies to any of the state objects that may change.

### `state` properties

| Prop              | Description                                                                   | Type                                                                                                                                                                                                           |
| ----------------- | ----------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `gl`              | Renderer                                                                      | `THREE.WebGLRenderer`                                                                                                                                                                                          |
| `scene`           | Scene                                                                         | `THREE.Scene`                                                                                                                                                                                                  |
| `camera`          | Camera                                                                        | `THREE.PerspectiveCamera`                                                                                                                                                                                      |
| `raycaster`       | Default raycaster                                                             | `THREE.Raycaster`                                                                                                                                                                                              |
| `pointer`         | Contains updated, normalized, centric pointer coordinates                     | `THREE.Vector2`                                                                                                                                                                                                |
| `mouse`           | Note: this is deprecated, use `pointer` instead! Normalized event coordinates | `THREE.Vector2`                                                                                                                                                                                                |
| `clock`           | Running system clock                                                          | `THREE.Clock`                                                                                                                                                                                                  |
| `linear`          | True when the colorspace is linear                                            | `boolean`                                                                                                                                                                                                      |
| `flat`            | True when no tonemapping is used                                              | `boolean`                                                                                                                                                                                                      |
| `legacy`          | Disables global color management via `THREE.ColorManagement`                  | `boolean`                                                                                                                                                                                                      |
| `frameloop`       | Render mode: always, demand, never                                            | `always`, `demand`, `never`                                                                                                                                                                                    |
| `performance`     | System regression                                                             | `{ current: number, min: number, max: number, debounce: number, regress: () => void }`                                                                                                                         |
| `size`            | Canvas size in pixels                                                         | `{ width: number, height: number, top: number, left: number }`                                                                                                                                                 |
| `viewport`        | Canvas viewport size in three.js units. Note: This is different from [`gl.getViewport`](https://threejs.org/docs/#api/en/renderers/WebGLRenderer.getViewport) which returns the drawbuffer size                                               | `{ width: number, height: number, initialDpr: number, dpr: number, factor: number, distance: number, aspect: number, getCurrentViewport: (camera?: Camera, target?: THREE.Vector3, size?: Size) => Viewport }` |
| `xr`              | XR interface, manages WebXR rendering                                         | `{ connect: () => void, disconnect: () => void }`                                                                                                                                                              |
| `set`             | Allows you to set any state property                                          | `(state: SetState<RootState>) => void`                                                                                                                                                                         |
| `get`             | Allows you to retrieve any state property non-reactively                      | `() => GetState<RootState>`                                                                                                                                                                                    |
| `invalidate`      | Request a new render, given that `frameloop === 'demand'`                     | `() => void`                                                                                                                                                                                                   |
| `advance`         | Advance one tick, given that `frameloop === 'never'`                          | `(timestamp: number, runGlobalEffects?: boolean) => void`                                                                                                                                                      |
| `setSize`         | Resize the canvas                                                             | `(width: number, height: number, top?: number, left?: number) => void`                                                                                                                                         |
| `setDpr`          | Set the pixel-ratio                                                           | `(dpr: number) => void`                                                                                                                                                                                        |
| `setFrameloop`    | Shortcut to set the current render mode                                       | `(frameloop?: 'always', 'demand', 'never') => void`                                                                                                                                                            |
| `setEvents`       | Shortcut to setting the event layer                                           | `(events: Partial<EventManager<any>>) => void`                                                                                                                                                                 |
| `onPointerMissed` | Response for pointer clicks that have missed a target                         | `() => void`                                                                                                                                                                                                   |
| `events`          | Pointer-event handling                                                        | `{ connected: TargetNode, handlers: Events, connect: (target: TargetNode) => void, disconnect: () => void }`                                                                                                   |

### Selector

You can also select properties, this allows you to avoid needless re-render for components that are interested only in particulars. Reactivity does not include deeper three.js internals!

```jsx
// Will only trigger re-render when the default camera is exchanged
const camera = useThree((state) => state.camera)
// Will only re-render on resize changes
const viewport = useThree((state) => state.viewport)
// ❌ You cannot expect reactivity from three.js internals!
const zoom = useThree((state) => state.camera.zoom)
```

### Reading state from outside of the component cycle

```jsx
function Foo() {
  const get = useThree((state) => state.get)
  ...
  get() // Get fresh state from anywhere you want
```

### Exchanging defaults

```jsx
function Foo() {
  const set = useThree((state) => state.set)
  ...
  useEffect(() => {
    set({ camera: new THREE.OrthographicCamera(...) })
  }, [])
```

## `useFrame`

This hook allows you to execute code on every rendered frame, like running effects, updating controls, and so on. You receive the state (same as `useThree`) and a clock delta. Your callback function will be invoked just before a frame is rendered. When the component unmounts it is unsubscribed automatically from the render-loop.

```jsx
import { useFrame } from '@react-three/fiber'

function Foo() {
  useFrame((state, delta, xrFrame) => {
    // This function runs at the native refresh rate inside of a shared render-loop
  })
```

> [!CAUTION]
> Be careful about what you do inside useFrame! You should never setState in there! Your calculations should be slim and
> you should mind all the commonly known pitfalls when dealing with loops in general, like re-use of variables, etc.

### Taking over the render-loop

If you need more control you may pass a numerical `renderPriority` value. This will cause React Three Fiber to disable automatic rendering altogether. It will now be your responsibility to render, which is useful when you're working with effect composers, heads-up displays, etc.

```jsx
function Render() {
  // Takes over the render-loop, the user has the responsibility to render
  useFrame(({ gl, scene, camera }) => {
    gl.render(scene, camera)
  }, 1)

function RenderOnTop() {
  // This will execute *after* Render's useframe
  useFrame(({ gl, ... }) => {
    gl.render(...)
  }, 2)
```

> [!NOTE]
> Callbacks will be executed in order of ascending priority values (lowest first, highest last.), similar to the DOM's z-order.

### Negative indices

Using negative indices will **not take over the render loop**, but it can be useful if you really must order the sequence of useFrames across the component tree.

```jsx
function A() {
  // This will execute first
  useFrame(() => ..., -2)

function B() {
  // This useFrame will execute *after* A's
  useFrame(() => ..., -1)
```

## `useLoader`

This hook loads assets and suspends for easier fallback- and error-handling. It can take any three.js loader as its first argument: GLTFLoader, OBJLoader, TextureLoader, FontLoader, etc. It is based on [React.Suspense](https://react.dev/reference/react/Suspense), so fallback-handling and [error-handling](https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary) happen at the parental level.

```jsx
import { Suspense } from 'react'
import { useLoader } from '@react-three/fiber'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'

function Model() {
  const result = useLoader(GLTFLoader, '/model.glb')
  // You don't need to check for the presence of the result, when we're here
  // the result is guaranteed to be present since useLoader suspends the component
  return <primitive object={result.scene} />
}

function App() {
  return (
    <Suspense fallback={<FallbackComponent /> /* or null */}>
      <Model />
    </Suspense>
  )
}
```

> [!TIP]
> Internally, `useLoader` relies on [`suspend-react`](https://github.com/pmndrs/suspend-react).

> [!NOTE]
> Assets loaded with useLoader are cached by default. The urls given serve as cache-keys. This allows you to re-use loaded data everywhere in the component tree.

> [!WARNING]
> Be very careful with mutating or disposing of loaded assets, especially when you plan to re-use them. Refer to the automatic disposal section in the API.

### Loader extensions

You can provide a callback as the third argument if you need to configure your loader:

```jsx
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'

useLoader(GLTFLoader, url, (loader) => {
  const dracoLoader = new DRACOLoader()
  dracoLoader.setDecoderPath('/draco-gltf/')
  loader.setDRACOLoader(dracoLoader)
})
```

### Loading multiple assets at once

It can also make multiple requests in parallel:

```jsx
const [bumpMap, specMap, normalMap] = useLoader(TextureLoader, [url1, url2, url2])
```

### Loading status

You can get the loading status from a callback you provide as the fourth argument. Though consider alternatives like THREE.DefaultLoadingManager or better yet, [Drei's](https://github.com/pmndrs/drei) loading helpers.

```jsx
useLoader(loader, url, extensions, (xhr) => {
  console.log((xhr.loaded / xhr.total) * 100 + '% loaded')
})
```

### Special treatment of GLTFLoaders and all loaders that return a scene prop

If a `result.scene` prop is found the hook will automatically create a object & material collection: `{ nodes, materials }`. This lets you build immutable scene graphs selectively. You can also specifically alter the data without having to traverse it. [GLTFJSX](https://github.com/pmndrs/gltfjsx) specifically relies on this data.

```jsx
const { nodes, materials } = useLoader(GLTFLoader, url)
```

### Pre-loading assets

You can pre-load assets in global space so that models can be loaded in anticipation before they're mounted in the component tree.

```jsx
useLoader.preload(GLTFLoader, '/model.glb' /* extensions */)
```

## `useGraph`

Convenience hook which creates a memoized, named object/material collection from any [`Object3D`](https://threejs.org/docs/#api/en/core/Object3D).

```jsx
import { useLoader, useGraph } from '@react-three/fiber'

function Model(url) {
  const scene = useLoader(OBJLoader, url)
  const { nodes, materials } = useGraph(scene)
  return <mesh geometry={nodes.robot.geometry} material={materials.metal} />
}
```


================================================
FILE: docs/API/objects.mdx
================================================
---
title: Objects, properties and constructor arguments
description: All the effective ways of using React Three Fiber
nav: 5
---

## Declaring objects

You can use [three.js's entire object catalogue and all properties](https://threejs.org/docs). When in doubt, always consult the docs.

❌ You could lay out an object like this:

```jsx
<mesh
  visible
  userData={{ hello: 'world' }}
  position={new THREE.Vector3(1, 2, 3)}
  rotation={new THREE.Euler(Math.PI / 2, 0, 0)}
  geometry={new THREE.SphereGeometry(1, 16, 16)}
  material={new THREE.MeshBasicMaterial({ color: new THREE.Color('hotpink'), transparent: true })}
/>
```

✅ The problem is that all of these properties will always be re-created. Instead, you should define properties declaratively.

```jsx
<mesh visible userData={{ hello: 'world' }} position={[1, 2, 3]} rotation={[Math.PI / 2, 0, 0]}>
  <sphereGeometry args={[1, 16, 16]} />
  <meshStandardMaterial color="hotpink" transparent />
</mesh>
```

## Constructor arguments

In three.js objects are classes that are instantiated. These classes can receive one-time constructor arguments (`new THREE.SphereGeometry(1, 32)`), and properties (`someObject.visible = true`). In React Three Fiber, constructor arguments are always passed as an array via `args`. If args change later on, the object must naturally get reconstructed from scratch!

```jsx
<sphereGeometry args={[1, 32]} />
```

## Shortcuts

### Set

All properties whose underlying object has a `.set()` method can directly receive the same arguments that `set` would otherwise take. For example [`THREE.Color.set`](https://threejs.org/docs/#api/en/math/Color.set) can take a color string, so instead of `color={new THREE.Color('hotpink')}` you can simply write `color="hotpink"`. Some `set` methods take multiple arguments, for instance [`THREE.Vector3`](https://threejs.org/docs/#api/en/math/Vector3.set), give it an array in that case `position={[100, 0, 0]}`.

```jsx
<mesh position={[1, 2, 3]} />
  <meshStandardMaterial color="hotpink" />
```

> [!NOTE]
> If you do link up an existing object to a property, for instance a THREE.Vector3() to a position, be aware that this will end up copying the object in most cases as it calls .copy() on the target. This only applies to objects that expose both .set() and .copy() (Vectors, Eulers, Matrix, ...). If you link up an existing material or geometry on the other hand, it will overwrite, because more these objects do not have a .set() method.

### SetScalar

Properties that have a `setScalar` method (for instance `Vector3`) can be set like so:

```jsx
// Translates to <mesh scale={[1, 1, 1]} />
<mesh scale={1} />
```

## Piercing into nested properties

If you want to reach into nested attributes (for instance: `mesh.rotation.x`), just use dash-case.

```jsx
<mesh rotation-x={1} material-uniforms-resolution-value={[512, 512]} />
```

## Dealing with non-scene objects

You can put non-Object3D primitives (geometries, materials, etc) into the render tree as well. They take the same properties and constructor arguments they normally would.

You might be wondering why you would want to put something in the "scene" that normally would not be part of it, in a vanilla three.js app at least. For the same reason you declare any object: it becomes managed, reactive and auto-disposes. These objects are not technically part of the scene, but they "attach" to a parent which is.

### Attach

Use `attach` to bind objects to their parent. If you unmount the attached object it will be taken off its parent automatically.

The following attaches a material to the `material` property of a mesh and a geometry to the `geometry` property:

```jsx
<mesh>
  <meshBasicMaterial attach="material" />
  <boxGeometry attach="geometry" />
```

> [!NOTE]
> All objects extending `THREE.Material` receive `attach="material"`, and all objects extending `THREE.BufferGeometry` receive `attach="geometry"`. You do not have to type it out!

```jsx
<mesh>
  <meshBasicMaterial />
  <boxGeometry />
```

You can also deeply nest attach through piercing. The following adds a buffer-attribute to `geometry.attributes.position` and then adds the buffer geometry to `mesh.geometry`.

```jsx
<mesh>
  <bufferGeometry>
    <bufferAttribute attach="attributes-position" args={[v, 3]} />
```

#### More examples

```jsx
// Attach bar to foo.a
<foo>
  <bar attach="a" />

// Attach bar to foo.a.b and foo.a.b.c (nested object attach)
<foo>
  <bar attach="a-b" />
  <bar attach="a-b-c" />

// Attach bar to foo.a[0] and foo.a[1] (array attach is just object attach)
<foo>
  <bar attach="a-0" />
  <bar attach="a-1" />

// Attach bar to foo via explicit add/remove functions
<foo>
  <bar attach={(parent, self) => {
    parent.add(self)
    return () => parent.remove(self)
  }} />

// The same as a one liner
<foo>
  <bar attach={(parent, self) => (parent.add(self), () => parent.remove(self))} />
```

#### Real-world use-cases:

Attaching to nested objects, for instance a shadow-camera:

```diff
- <directionalLight
-   castShadow
-   position={[2.5, 8, 5]}
-   shadow-mapSize={[1024, 1024]}
-   shadow-camera-far={50}
-   shadow-camera-left={-10}
-   shadow-camera-right={10}
-   shadow-camera-top={10}
-   shadow-camera-bottom={-10}
- />
+ <directionalLight castShadow position={[2.5, 8, 5]} shadow-mapSize={[1024, 1024]}>
+   <orthographicCamera attach="shadow-camera" args={[-10, 10, 10, -10]} />
+ </directionalLight>
```

Arrays must have explicit order, for instance multi-materials:

```jsx
<mesh>
  {colors.map((color, index) => <meshBasicMaterial key={index} attach={`material-${index}`} color={color} />}
</mesh>
```

## Putting already existing objects into the scene-graph

You can use the `primitive` placeholder for that. You can still give it properties or attach nodes to it. Never add the same object multiple times, this is not allowed in three.js! Primitives will not dispose of the object they carry on unmount, you are responsible for disposing of it!

```jsx
const mesh = new THREE.Mesh(geometry, material)

function Component() {
  return <primitive object={mesh} position={[10, 0, 0]} />
```

> [!NOTE]
> Scene objects can only ever be added once in Threejs. If you attempt to add one and the same object in two places Threejs will remove the first instance automatically. This will also happen with primitive! If you want to re-use an existing object, you must clone it first.

## Using 3rd-party objects declaratively

The `extend` function extends React Three Fiber's catalogue of JSX elements. Components added this way can then be referenced in the scene-graph using camel casing similar to other primitives.

```jsx
import { extend } from '@react-three/fiber'
import { OrbitControls, TransformControls } from 'three-stdlib'
extend({ OrbitControls, TransformControls })

// ...
return (
  <>
    <orbitControls />
    <transformControls />
```

If you're using TypeScript, you'll also need to [extend the JSX namespace](/tutorials/v9-migration-guide#threeelements).

## Disposal

Freeing resources is a [manual chore in `three.js`](https://threejs.org/docs/#manual/en/introduction/How-to-dispose-of-objects), but React is aware of object-lifecycles, hence React Three Fiber will attempt to free resources for you by calling `object.dispose()`, if present, on all unmounted objects.

If you manage assets by yourself, globally or in a cache, this may _not_ be what you want. You can switch it off by placing `dispose={null}` onto meshes, materials, etc, or even on parent containers like groups, it is now valid for the entire tree.

```jsx
const globalGeometry = new THREE.BoxGeometry()
const globalMaterial = new THREE.MeshBasicMaterial()

function Mesh() {
  return (
    <group dispose={null}>
      <mesh geometry={globalGeometry} material={globalMaterial} />
```


================================================
FILE: docs/API/testing.mdx
================================================
---
title: 'Testing'
description: How to handle unit tests
nav: 10
---

Like with every other application testing is an important factor when it comes to releasing an application into the wild and when it comes to React Three Fiber we can use React Three Test Renderer to achieve this.

We will be testing the [sandbox](https://codesandbox.io/s/98ppy) we created in [events and interactions](events-and-interaction).

## How to test React Three Fiber

Let's start by installing the React Three Test Renderer:

```bash
npm install @react-three/test-renderer --save-dev
```

Afterwards, if you are using Create React App you can just add a file that ends in `.test.js` and start writing your code, because React Three Test Renderer is testing library agnostic, so it works with libraries such as `jest`, `jasmine` etc.

Let's create an `App.test.js` and set up all our test cases:

```jsx
import ReactThreeTestRenderer from '@react-three/test-renderer'
import { MyRotatingBox } from './App'

test('mesh to have two children', async () => {
  const renderer = await ReactThreeTestRenderer.create(<MyRotatingBox />)
})

test('click event makes box bigger', async () => {
  const renderer = await ReactThreeTestRenderer.create(<MyRotatingBox />)
})
```

In here we created three tests and in each we made sure we created the renderer by using the `create` function.

Let's start with the first test and make sure our mesh has two children, the material and cube.

We can start by getting the scene and it's children from the test instance we just created like so:

```js
const meshChildren = renderer.scene.children
```

If you log this mesh out you can see that it returns an array of one element since that's all we have in the scene.

Using this we can make sure to get that first child and use the `allChildren` property on it like so:

```js
const meshChildren = renderer.scene.children[0].allChildren
```

There is also one property called `children` but this one is meant to be used for things like groups as this one does not return the geometry and the materials, for that we need `allChildren`.

Now to create our assertion:

```js
expect(meshChildren.length).toBe(2)
```

Our first test case looks like this:

```js
test('mesh to have two children', async () => {
  const renderer = await ReactThreeTestRenderer.create(<MyRotatingBox />)
  const mesh = renderer.scene.children[0].allChildren
  expect(mesh.length).toBe(2)
})
```

## Testing interactions

Now that we have gotten the first test out of the way we can test our interaction and make sure that when we click on the mesh it does indeed update the scale.

We can do that by utilizing the `fireEvent` method existing in a test instance.

We know we can get the mesh with:

```js
const mesh = renderer.scene.children[0]
```

Since we already have that we can fire an event in it like so:

```js
await renderer.fireEvent(mesh, 'click')
```

With that done, all that's left to do is the tree demonstration of our scene and make sure the scale prop on our mesh has updated:

```js
expect(mesh.props.scale).toBe(1.5)
```

In the end our test looks something like this:

```js
test('click event makes box bigger', async () => {
  const renderer = await ReactThreeTestRenderer.create(<MyRotatingBox />)
  const mesh = renderer.scene.children[0]
  expect(mesh.props.scale).toBe(1)
  await renderer.fireEvent(mesh, 'click')
  expect(mesh.props.scale).toBe(1.5)
})
```

If you want to learn more about React Three Test Renderer you can checkout the repo and their docs:

- [Repo](https://github.com/pmndrs/react-three-fiber/blob/master/packages/test-renderer)
- [React Three Test Renderer API](https://github.com/pmndrs/react-three-fiber/blob/master/packages/test-renderer/markdown/rttr.md#create)
- [React Three Test Instance API](https://github.com/pmndrs/react-three-fiber/blob/master/packages/test-renderer/markdown/rttr-instance.md)

## Exercises

- Check the color of the Box we created
- Check the rotation using the `advanceFrames` method.

<Codesandbox id="hqut4" tests />


================================================
FILE: docs/API/typescript.mdx
================================================
---
title: TypeScript
description: Common scenarios and how to approach them with TypeScript
nav: 9
---

## Typing with `useRef`

React's `useRef` won't automatically infer types despite pointing it to a typed ref.

You can type the ref yourself by passing a type through `useRef`'s generics:

```tsx
import { useRef, useEffect } from 'react'
import { Mesh } from 'three'

function Box(props) {
  const meshRef = useRef<Mesh>(null!)

  useEffect(() => {
    console.log(Boolean(meshRef.current))
  }, [])

  return (
    <mesh {...props} ref={meshRef}>
      <boxGeometry />
      <meshBasicMaterial />
    </mesh>
  )
}
```

The exclamation mark is a non-null assertion that will let TS know that `ref.current` is defined when we access it in effects, useFrame et al. You do not need to check against null, the element is assumed to exist.

## Accessing typed three-elements

Whenever you want to spread props or type components that rely on three elements, you can use the `ThreeElements` interface to extract the mesh, group, or any other three element, including custom elements.

```tsx
import { ThreeElements } from '@react-three/fiber'

type FooProps = ThreeElements['mesh'] & { bar: boolean }

function Foo({ bar, ...props}: FooProps) {
  useEffect(() => {
    console.log(bar)
  }, [bar])
  return <mesh {...props} />
}
```

## Extend usage

react-three-fiber can also accept third-party elements and extend them into its internal catalogue.

```tsx
import { useRef, useEffect } from 'react'
import { GridHelper } from 'three'
import { extend } from '@react-three/fiber'

// Create our custom element
class CustomElement extends GridHelper {}

// Extend so the reconciler will learn about it
extend({ CustomElement })

<customElement />
```

The catalogue teaches the underlying reconciler how to create fibers for these elements and treat them within the scene.

You can then declaratively create custom elements with primitives, but TypeScript won't know about them nor their props.

```html
// error: 'customElement' does not exist on type 'JSX.IntrinsicElements'

<customElement />
```

### Extending ThreeElements

To define our element in JSX, we'll use the `ThreeElement` interface to extend `ThreeElements`. This interface describes three.js classes that are available in the R3F catalog and can be used as native elements.

```tsx
import { useRef, useEffect } from 'react'
import { GridHelper } from 'three'
import { extend, ThreeElement } from '@react-three/fiber'

// Create our custom element
class CustomElement extends GridHelper {}

// Extend so the reconciler will learn about it
extend({ CustomElement })

// Add types to ThreeElements elements so primitives pick up on it
declare module '@react-three/fiber' {
  interface ThreeElements {
    customElement: ThreeElement<typeof CustomElement>
  }
}

// react-three-fiber will create your custom component and TypeScript will understand it
<customComponent />
```

You can shorten element definition by using the `extend` factory signature, which will automatically extend the element locally. This will also prevent namespace bleeding.

```tsx
// Create our custom element
class CustomElement extends GridHelper {}

// Extend so the reconciler will learn about it, types will be inferred
const Element = extend(CustomElement)

// react-three-fiber will create your custom component and TypeScript will understand it
<Element />
```

## Extending three default elements

If you open your own root instead of using `<Canvas>`, you can extend the default elements with `extend`. But keep in mind that the `* as THREE` namespace contains classes, functions, numbers, strings. At the moment we suggest you use `any` or `@ts-ignore` unless you extract the exact classes you need (`extend({ Mesh, Group, ... })`).

```tsx
import * as THREE from 'three'
import { extend, createRoot, events } from '@react-three/fiber'

// Register the THREE namespace as native JSX elements.
extend(THREE as any)

// Create a react root
const root = createRoot(document.querySelector('canvas'))
```

## Exported types

react-three-fiber is extensible and exports types for its internals, such as render props, canvas props, and events:

```tsx
// Event raycaster intersection
Intersection

// `useFrame` internal subscription and render callback
Subscription
RenderCallback

// `useThree`'s returned internal state
RootState
Performance
Dpr
Size
Viewport
Camera

// Canvas props
CanvasProps

// Supported events
Events

// Event manager signature (is completely modular)
EventManager

// Wraps a platform event as it's passed through the event manager
ThreeEvent
```


================================================
FILE: docs/advanced/pitfalls.mdx
================================================
---
title: Performance pitfalls
description: Performance 1x1
nav: 12
---

## Tips and Tricks

This is a good overview: https://discoverthreejs.com/tips-and-tricks

The most important gotcha in three.js is that creating objects can be expensive, think twice before you mount/unmount things! Every material or light that you put into the scene has to compile, every geometry you create will be processed. Share materials and geometries if you can, either in global scope or locally:

```jsx
const geom = useMemo(() => new BoxGeometry(), [])
const mat = useMemo(() => new MeshBasicMaterial(), [])
return items.map(i => <mesh geometry={geom} material={mat} ...
```

Try to use [instancing](https://codesandbox.io/s/r3f-instanced-colors-8fo01) as much as you can when you need to display many objects of a similar type!

## Avoid setState in loops

TLDR, don't, mutate inside `useFrame`!

- Threejs has a render-loop, it does not work like the DOM does. **Fast updates are carried out in `useFrame` by mutation**. `useFrame` is your per-component render-loop.

- It is not enough to set values in succession, _you need frame deltas_. Instead of `position.x += 0.1` consider `position.x += delta` or your project will run at different speeds depending on the end-users system. Many updates in threejs need to be paired with update flags (`.needsUpdate = true`), or imperative functions (`.updateProjectionMatrix()`).

- You might be tempted to setState inside `useFrame` but there is no reason to. You would only complicate something as simple as an update by routing it through React's scheduler, triggering component render etc.

### ❌ `setState` in loops is bad

```jsx
useEffect(() => {
  const interval = setInterval(() => setX((x) => x + 0.1), 1)
  return () => clearInterval(interval)
}, [])
```

### ❌ `setState` in useFrame is bad

```jsx
const [x, setX] = useState(0)
useFrame(() => setX((x) => x + 0.1))
return <mesh position-x={x} />
```

### ❌ `setState` in fast events is bad

```jsx
<mesh onPointerMove={(e) => setX((x) => e.point.x)} />
```

### ✅ Instead, just mutate, use deltas

In general you should prefer useFrame. Consider mutating props safe as long as the component is the only entity that mutates. Use deltas instead of fixed values so that your app is refresh-rate independent and runs at the same speed everywhere!

```jsx
const meshRef = useRef()
useFrame((state, delta) => (meshRef.current.position.x += delta))
return <mesh ref={meshRef} />
```

Same goes for events, use references.

```jsx
<mesh onPointerMove={(e) => (ref.current.position.x = e.point.x)} />
```

If you must use intervals, use references as well, but keep in mind that this is not refresh-rate independent.

```jsx
useEffect(() => {
  const interval = setInterval(() => ref.current.position.x += 0.1, 1)
  return () => clearInterval(interval)
}, [])
```

## Handle animations in loops

The frame loop is where you should place your animations. For instance using lerp, or damp.

### ✅ Use `lerp` + `useFrame`

```jsx
function Signal({ active }) {
  const meshRef = useRef()
  useFrame((state, delta) => {
    meshRef.current.position.x = THREE.MathUtils.lerp(meshRef.current.position.x, active ? 100 : 0, 0.1)
  })
  return <mesh ref={meshRef} />
```

### ✅ Or react-spring

Or, use animation libraries. React-spring has its own frame-loop and animates outside of React. Framer-motion is another popular alternative.

```jsx
import { a, useSpring } from '@react-spring/three'

function Signal({ active }) {
  const { x } = useSpring({ x: active ? 100 : 0 })
  return <a.mesh position-x={x} />
```

## Do not bind to fast state reactively

Using state-managers and selective state is fine, but not for updates that happen rapidly for the same reason as above.

### ❌ Don't bind reactive fast-state

```jsx
import { useSelector } from 'react-redux'

// Assuming that x gets animated inside the store 60fps
const x = useSelector((state) => state.x)
return <mesh position-x={x} />
```

### ✅ Fetch state directly

For instance using [Zustand](https://github.com/pmndrs/zustand) (same in Redux et al).

```jsx
useFrame(() => (ref.current.position.x = api.getState().x))
return <mesh ref={ref} />
```

## Don't mount indiscriminately

In threejs it is very common to not re-mount at all, see the ["disposing of things"](https://discoverthreejs.com/tips-and-tricks/) section in discover-three. This is because buffers and materials get re-initialized/compiled, which can be expensive.

### ❌ Avoid mounting runtime

```jsx
{
  stage === 1 && <Stage1 />
}
{
  stage === 2 && <Stage2 />
}
{
  stage === 3 && <Stage3 />
}
```

### ✅ Consider using visibility instead

```jsx
<Stage1 visible={stage === 1} />
<Stage2 visible={stage === 2} />
<Stage3 visible={stage === 3} />

function Stage1(props) {
  return (
    <group {...props}>
      ...
```

### ✅ Use `startTransition` for expensive ops

React 18 introduces the `startTransition` and `useTransition` APIs to defer and schedule work and state updates. Use these to de-prioritize expensive operations.

Since version 8 of Fiber canvases use concurrent mode by default, which means React will schedule and defer expensive operations. You don't need to do anything, but you can play around with the [experimental scheduler](https://github.com/drcmda/scheduler-test) and see if marking ops with a lesser priority makes a difference.

```jsx
import { useTransition } from 'react'
import { Points } from '@react-three/drei'

const [isPending, startTransition] = useTransition()
const [radius, setRadius] = useState(1)
const positions = calculatePositions(radius)
const colors = calculateColors(radius)
const sizes = calculateSizes(radius)

<Points
  positions={positions}
  colors={colors}
  sizes={sizes}
  onPointerOut={() => {
    startTransition(() => {
      setRadius(prev => prev + 1)
    })
  }}
>
  <meshBasicMaterial vertexColors />
</Points>
```

## Don't re-create objects in loops

Try to avoid creating too much effort for the garbage collector, re-pool objects when you can!

### ❌ Bad news for the GC

This creates a new vector 60 times a second, which allocates memory and forces the GC to eventually kick in.

```jsx
useFrame(() => {
  ref.current.position.lerp(new THREE.Vector3(x, y, z), 0.1)
})
```

### ✅ Better re-use object

Set up re-used objects in global or local space, now the GC will be silent.

```jsx
function Foo(props)
  const vec = new THREE.Vector()
  useFrame(() => {
    ref.current.position.lerp(vec.set(x, y, z), 0.1)
  })
```

## `useLoader` instead of plain loaders

Threejs loaders give you the ability to load async assets (models, textures, etc), but if you do not re-use assets it can quickly become problematic.

### ❌ No re-use is bad for perf

This re-fetches, re-parses for every component instance.

```jsx
function Component() {
  const [texture, set] = useState()
  useEffect(() => void new TextureLoader().load(url, set), [])
  return texture ? (
    <mesh>
      <sphereGeometry />
      <meshBasicMaterial map={texture} />
    </mesh>
  ) : null
}
```

Instead use useLoader, which caches assets and makes them available throughout the scene.

### ✅ Cache and re-use objects

```jsx
function Component() {
  const texture = useLoader(TextureLoader, url)
  return (
    <mesh>
      <sphereGeometry />
      <meshBasicMaterial map={texture} />
    </mesh>
  )
}
```

Regarding GLTF's try to use [GLTFJSX](https://github.com/pmndrs/gltfjsx) as much as you can, this will create immutable JSX graphs which allow you to even re-use full models.


================================================
FILE: docs/advanced/scaling-performance.mdx
================================================
---
title: Scaling performance
description: This is a short primer on how to scale performance.
nav: 11
---

Running WebGL can be quite expensive depending on how powerful your devices are. In order to mitigate this, especially if you want to make your application available to a broad variety of devices, including weaker options, you should look into performance optimizations. This article goes through a couple of them.

## On-demand rendering

three.js apps usually run in a game-loop that executes 60 times a second, React Three Fiber is no different. This is perfectly fine when your scene has _constantly_ moving parts in it. This is what generally drains batteries the most and makes fans spin up.

But if the moving parts in your scene are allowed to come to rest, then it would be wasteful to keep rendering. In such cases you can opt into on-demand rendering, which will only render when necessary. This saves battery and keeps noisy fans in check.

Open the sandbox below in a full screen and look into dev tools, you will see that it is completely idle when nothing is going on. It renders only when you move the model.

<Codesandbox id="wvgxp" />

All you need to do is set the canvas `frameloop` prop to `demand`. It will render frames whenever it detects prop changes throughout the component tree.

```jsx
<Canvas frameloop="demand">
```

### Triggering manual frames

One major caveat is that if anything in the tree _mutates_ props, then React cannot be aware of it and the display would be stale. For instance, camera controls just grab into the camera and mutate its values. Here you can use React Three Fiber's `invalidate` function to trigger frames manually.

```jsx
function Controls() {
  const orbitControlsRef = useRef()
  const { invalidate, camera, gl } = useThree()
  useEffect(() => {
    orbitControlsRef.current.addEventListener('change', invalidate)
    return () => orbitControlsRef.current.removeEventListener('change', invalidate)
  }, [])
  return <orbitControls ref={orbitControlsRef} args={[camera, gl.domElement]} />
```

> [!NOTE]
> Drei's controls do this automatically for you.

Generally you can call invalidate whenever you need to render:

```jsx
invalidate()
```

> [!IMPORTANT]
> Calling `invalidate()` will not render immediately, it merely requests a
new frame to be rendered out. Calling invalidate multiple times will not render multiple times.
Think of it as a flag to tell the system that something has changed.

### Sync animations with on-demand-rendering and invalidate

Since `invalidate()` is only a flag that schedules render, you might bump into syncing issues when you run animations that are synchronous (as in, they start immediately). By the time fiber renders the first frame the animation has already progressed which leads to a visible jump. In such cases you should pre-emptively schedule a render and then start the animation in the next frame.

```jsx
<mesh
  onClick={() => {
    // Pre-emptively schedule a render
    invalidate()
    // Wait for the next frame to start the animation
    requestAnimationFrame(() => controls.dolly(1, true))
  }}
```

## Re-using geometries and materials

Each geometry and material means additional overhead for the GPU. You should try to re-use resources if you know they will repeat.

You could do this globally:

```jsx
const red = new THREE.MeshLambertMaterial({ color: "red" })
const sphere = new THREE.SphereGeometry(1, 28, 28)

function Scene() {
  return (
    <>
      <mesh geometry={sphere} material={red} />
      <mesh position={[1, 2, 3]} geometry={sphere} material={red} />
```

If you create a material or color in global space - outside of React Three Fiber's `Canvas` context - you should enable [ColorManagement](https://threejs.org/docs/#manual/en/introduction/Color-management) in three.js. This will allow certain conversions (for hexadecimal and CSS colors in sRGB) to be made automatically, producing correct colors in all cases.

```jsx
import * as THREE from 'three'

// r150
THREE.ColorManagement.enabled = true

// r139-r149
THREE.ColorManagement.legacyMode = false
```

### Caching with `useLoader`

> [!NOTE]
> Every resource that is loaded with useLoader is cached automatically!

If you access a resource via useLoader with the same URL, throughout the component tree, then you will always refer to the same asset and thereby re-use it. This is especially useful if you run your GLTF assets through [GLTFJSX](https://github.com/pmndrs/gltfjsx) because it links up geometries and materials and thereby creates re-usable models.

<Codesandbox id="dix1y" />

```jsx
function Shoe(props) {
  const { nodes, materials } = useLoader(GLTFLoader, "/shoe.glb")
  return (
    <group {...props} dispose={null}>
      <mesh geometry={nodes.shoe.geometry} material={materials.canvas} />
    </group>
  )
}

<Shoe position={[1, 2, 3]} />
<Shoe position={[4, 5, 6]} />
```

## Instancing

Each mesh is a draw call, you should be mindful of how many of these you employ: no more than 1000 as the very maximum, and optimally a few hundred or less. You can win performance back by reducing draw calls, for example by instancing repeating objects. This way you can have hundreds of thousands of objects in a single draw call.

<Codesandbox id="h873k" />

Setting up instancing is not so hard, consult [the three.js docs](https://threejs.org/docs/#api/en/objects/InstancedMesh) if you need help.

```jsx
function Instances({ count = 100000, temp = new THREE.Object3D() }) {
  const instancedMeshRef = useRef()
  useEffect(() => {
    // Set positions
    for (let i = 0; i < count; i++) {
      temp.position.set(Math.random(), Math.random(), Math.random())
      temp.updateMatrix()
      instancedMeshRef.current.setMatrixAt(i, temp.matrix)
    }
    // Update the instance
    instancedMeshRef.current.instanceMatrix.needsUpdate = true
  }, [])
  return (
    <instancedMesh ref={instancedMeshRef} args={[null, null, count]}>
      <boxGeometry />
      <meshPhongMaterial />
    </instancedMesh>
  )
}
```

## Level of detail

Sometimes it can be beneficial to reduce the quality of an object the further it is away from the camera. Why would you display it full resolution if it is barely visible. This can be a good strategy to reduce the overall vertex-count which means less work for the GPU.

Scroll in and out to see the effect:

<Codesandbox id="12nmp" />

There is a small component in Drei called `<Detailed />` which sets up LOD without boilerplate. You load or prepare a couple of resolution stages, as many as you like, and then give them the same amount of distances from the camera, starting from highest quality to lowest.

```jsx
import { Detailed, useGLTF } from '@react-three/drei'

function Model() {
  const [low, mid, high] = useGLTF(["/low.glb", "/mid.glb", "/high.glb"])
  return (
    <Detailed distances={[0, 10, 20]}>
      <mesh geometry={high} />
      <mesh geometry={mid} />
      <mesh geometry={low} />
    <Detailed/>
  )
}
```

## Nested loading

Nested loading means that lesser textures and models are loaded first, higher-resolution later.

The following sandbox goes through three loading stages:

- A loading indicator
- Low quality
- High quality

<Codesandbox id="7duy8" />

And this is how easy it is to achieve it, you can nest suspense and even use it as a fallback:

```jsx
function App() {
  return (
    <Suspense fallback={<span>loading...</span>}>
      <Canvas>
        <Suspense fallback={<Model url="/low-quality.glb" />}>
          <Model url="/high-quality.glb" />
        </Suspense>
      </Canvas>
    </Suspense>
  )
}

function Model({ url }) {
  const { scene } = useGLTF(url)
  return <primitive object={scene} />
}
```

## Performance monitoring

Drei has a new component [PerformanceMonitor](https://github.com/pmndrs/drei#performancemonitor) that allows you to monitor, and adapt to, device performance. This component will collect the average fps (frames per second) over time. If after a couple of iterations the averages are below or above a threshold it will trigger onIncline and onDecline callbacks that allow you to respond. Typically you would reduce the quality of your scene, the resolution, effects, the amount of stuff to render, or, increase it if you have enough framerate to fill.

Since this would normally cause ping-ponging between the two callbacks you define upper and lower framerate bounds, as long as you stay within that margin nothing will trigger. Ideally your app should find its way into that margin by gradually altering quality.

A simple example for regulating the resolution. It starts out with 1.5, if the system falls below the bounds it goes to 1, if it's fast enough it goes to 2.

```jsx
function App() {
  const [dpr, setDpr] = useState(1.5)
  return (
    <Canvas dpr={dpr}>
      <PerformanceMonitor onIncline={() => setDpr(2)} onDecline={() => setDpr(1)} >
```

You can also use the onChange callback to get notified when the average changes in whichever direction. This allows you to make gradual changes. It gives you a factor between 0 and 1, which is increased by incline and decreased by decline. The factor is initially 0.5 by default.

```jsx
import round from 'lodash/round'

const [dpr, setDpr] = useState(1)
return (
 <Canvas dpr={dpr}>
  <PerformanceMonitor onChange={({ factor }) => setDpr(round(0.5 + 1.5 * factor, 1))}>
```

If you still experience flip flops despite the bounds you can define a limit of flipflops. If it is met onFallback will be triggered which typically sets a lowest possible baseline for the app. After the fallback has been called PerformanceMonitor will shut down.

```jsx
<PerformanceMonitor flipflops={3} onFallback={() => setDpr(1)}>
```

PerformanceMonitor can also have children, if you wrap your app in it you get to use usePerformanceMonitor which allows individual components down the nested tree to respond to performance changes on their own.

```jsx
;<PerformanceMonitor>
  <Effects />
</PerformanceMonitor>

function Effects() {
  usePerformanceMonitor({ onIncline, onDecline, onFallback, onChange })
  // ...
}
```

## Movement regression

Websites like Sketchfab make sure the scene is always fluid, running at 60 fps, and responsive, no matter which device is being used or how expensive a loaded model is. They do this by regressing movement, where effects, textures, shadows will slightly reduce quality until still-stand

The following sandbox uses expensive lights and post-processing. In order for it to run relatively smooth it will scale the pixel ratio on movement and also skip heavy post-processing effects like ambient occlusion.

<Codesandbox id="pz0q6" />

When you inspect the state model you will notice an object called `performance`.

```jsx
performance: {
  current: 1,
  min: 0.1,
  max: 1,
  debounce: 200,
  regress: () => void,
},
```

- `current`: Performance factor alternates between min and max
- `min`: Performance lower bound (should be less than 1)
- `max`: Performance upper bound (no higher than 1)
- `debounce`: Debounce timeout until it goes to upper bound (1) again
- `regress()`: Function that temporarily regresses performance

You can define defaults like so:

```jsx
<Canvas performance={{ min: 0.5 }}>...</Canvas>
```

### This is how you can put the system into regression

The only thing you have to do is call `regress()`. When exactly you do that, that is up to you, but it could be when the mouse moves, or the scene is moving, for instance when controls fire their change-event.

Say you are using controls, then the following code puts the system in regress when they are active:

```jsx
const regress = useThree((state) => state.performance.regress)
useEffect(() => {
  controls.current?.addEventListener('change', regress)
```

### This is how you can respond to it

> [!NOTE]
> Mere calls to `regress()` will not change or affect anything!

Your app has to opt into performance scaling by listening to the performance `current`! The number itself will tell you what to do. 1 (max) means everything is ok, the default. Less than 1 (min) means a regression is requested and the number itself tells you how far you should go when scaling down.

For instance, you could simply multiply `current` with the pixel ratio to cut down on resolution. If you have defined `min: 0.5` that would mean it will half the resolution for at least 200ms (delay) when regress is called. It can be used for anything else, too: switching off lights when `current < 1`, using lower-res textures, skip post-processing effects, etc. You could of course also animate/lerp these changes.

Here is a small prototype component that scales the pixel ratio:

```jsx
function AdaptivePixelRatio() {
  const current = useThree((state) => state.performance.current)
  const setPixelRatio = useThree((state) => state.setDpr)
  useEffect(() => {
    setPixelRatio(window.devicePixelRatio * current)
  }, [current])
  return null
}
```

Drop this component into the scene, combine it with the code above that calls `regress()`, and you have adaptive resolution:

```jsx
<AdaptivePixelRatio />
```

There are pre-made components for this already in the [Drei library](https://github.com/pmndrs/drei/#performance).

## Enable concurrency

React 18 introduces concurrent scheduling, specifically time slicing via `startTransition` and `useTransition`. This will virtualize the component graph, which then allows you to prioritise components and actions. Think of how a virtual list avoids scaling issues because it only renders as many items as the screen can take, it is not affected by the amount of items it has to render, be it 10 or 100.000.000.

React 18 functions very similar to this, it can potentially defer load and heavy tasks in ways that would be hard or impossible to achieve in a vanilla application. It thereby holds on to a stable framerate even in the most demanding situations.

The following benchmark shows how powerful concurrency can be: https://github.com/drcmda/scheduler-test

It simulates heavy load by creating hundreds of THREE.TextGeometry instances (510 to be exact). This class, like many others in three.js, is expensive and takes a while to construct. If all 510 instances are created the same time **it will cause approximately 1.5 seconds of pure jank** (Apple M1), the tab would normally freeze. It runs in an interval and **will execute every 2 seconds**.

|          | Distributed | At-once |
| -------- | ----------- | ------- |
| three.js | ~20fps      | ~5fps   |
| React    | ~60fps      | ~60fps  |

<p align="center">
  <img
    aria-label="three.js distributed"
    style={{ width: '50%', display: 'inline-block' }}
    src="https://github.com/drcmda/scheduler-test/raw/master/assets/three-distributed.jpg"
  />
  <img
    aria-label="three.js at once"
    style={{ width: '50%', display: 'inline-block' }}
    src="https://github.com/drcmda/scheduler-test/raw/master/assets/three-at-once.jpg"
  />
  <img
    aria-label="React distributed"
    style={{ width: '50%', display: 'inline-block' }}
    src="https://github.com/drcmda/scheduler-test/raw/master/assets/react-distributed.jpg"
  />
  <img
    aria-label="React at once"
    style={{ width: '50%', display: 'inline-block' }}
    src="https://github.com/drcmda/scheduler-test/raw/master/assets/react-at-once.jpg"
  />
</p>

For more on how to use this API, see [use startTransition for expensive ops](/docs/advanced/pitfalls#use-starttransition-for-expensive-ops).


================================================
FILE: docs/getting-started/basic-example-sandpack/index.jsx
================================================
import { createRoot } from 'react-dom/client'
import React, { useRef, useState } from 'react'
import { Canvas, useFrame } from '@react-three/fiber'
import './styles.css'

function Box(props) {
  // This reference will give us direct access to the mesh
  const meshRef = useRef()
  // Set up state for the hovered and active state
  const [hovered, setHover] = useState(false)
  const [active, setActive] = useState(false)
  // Subscribe this component to the render-loop, rotate the mesh every frame
  useFrame((state, delta) => (meshRef.current.rotation.x += delta))
  // Return view, these are regular three.js elements expressed in JSX
  return (
    <mesh
      {...props}
      ref={meshRef}
      scale={active ? 1.5 : 1}
      onClick={(event) => setActive(!active)}
      onPointerOver={(event) => setHover(true)}
      onPointerOut={(event) => setHover(false)}>
      <boxGeometry args={[1, 1, 1]} />
      <meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />
    </mesh>
  )
}

createRoot(document.getElementById('root')).render(
  <Canvas>
    <ambientLight intensity={Math.PI / 2} />
    <spotLight position={[10, 10, 10]} angle={0.15} penumbra={1} decay={0} intensity={Math.PI} />
    <pointLight position={[-10, -10, -10]} decay={0} intensity={Math.PI} />
    <Box position={[-1.2, 0, 0]} />
    <Box position={[1.2, 0, 0]} />
  </Canvas>,
)


================================================
FILE: docs/getting-started/basic-example-sandpack/styles.css
================================================
html,
body,
#root {
  height: 100%;
  margin: unset;
}


================================================
FILE: docs/getting-started/community-r3f-components.mdx
================================================
---
title: Community R3F Components
description: This page showcases some React Three Fiber/r3f community components that have not been merged to the drei components collection or to another pmndrs project. 
nav: 4
---

If you'd like to list new community components, please make a PR to [this doc](https://github.com/pmndrs/react-three-fiber/tree/master/docs/getting-started/community-r3f-components.mdx) file. It showcases some r3f community components that have not been merged to to the [drei](http://drei.docs.pmnd.rs) components collection or to another [pmndrs](https://github.com/pmndrs) project.

## R3F community components 

### Repos and docs

This page showcases some React Three Fiber/r3f community components that have not been merged to the [drei](http://drei.docs.pmnd.rs) components collection or to another [pmndrs](https://github.com/pmndrs) project. If you'd like to list new community components, please make a PR to [this doc](https://github.com/pmndrs/react-three-fiber/tree/master/docs/getting-started/community-r3f-components.mdx) file. 

#### Data sources

 - [NASA-AMMOS/3DTilesRendererJS](https://github.com/NASA-AMMOS/3DTilesRendererJS/) (r3f [readme](https://github.com/NASA-AMMOS/3DTilesRendererJS/blob/master/src/r3f/README.md)) repo with doc
 - Luma Labs [Gaussian Splats](https://cdn-luma.com/public/lumalabs.ai/luma-web-library/0.2/fefe154/index.html#react-three-fiber) renderer doc with demos
 - [NYTimes/three-loader-3dtiles](https://nytimes.github.io/three-loader-3dtiles) 

#### Renderers & frameworks

 - Takram three-geospatial [clouds doc](https://github.com/takram-design-engineering/three-geospatial/tree/main/packages/clouds) and [demos](https://takram-design-engineering.github.io/three-geospatial/?path=/story/clouds-3d-tiles-renderer-integration--tokyo), and [atmosphere doc](https://github.com/takram-design-engineering/three-geospatial/tree/main/packages/atmosphere)
 - [Looking Glass](https://docs.lookingglassfactory.com/developer-tools/webxr/react-three-fiber) doc and demos
 - [Theatre-js](https://github.com/theatre-js/theatre) repo and [doc](https://www.theatrejs.com/docs/latest)

#### Materials

 - [FarazzShaikh/CustomShaderMaterial](https://github.com/FarazzShaikh/THREE-CustomShaderMaterial)
 - [pmndrs/THREE.MeshLine](https://github.com/pmndrs/meshline)
 - [ektogamat/R3F-Ultimate-Lens-Flare](https://github.com/ektogamat/R3F-Ultimate-Lens-Flare)
 - [troika-three-text](https://github.com/protectwise/troika/tree/main/packages/troika-three-text)

#### Utilities

 - [utsuboco/r3f-perf](https://github.com/utsuboco/r3f-perf)


### Codesandboxes and demos

<Grid cols={3}>
  <li>
    [NASA-AMMOS/3DTilesRendererJS](https://github.com/NASA-AMMOS/3DTilesRendererJS)

    [<Img src="https://raw.githubusercontent.com/NASA-AMMOS/3DTilesRendererJS/master/images/header-mars.png" alt="3DTilesRendererJS r3f demo" className="aspect-[16/9] object-cover"  width="1763" height="926" />](https://nasa-ammos.github.io/3DTilesRendererJS/example/bundle/r3f/basic.html)
  </li>
  <li>
    [Takram three-geospatial clouds](https://github.com/takram-design-engineering/three-geospatial/tree/main/packages/clouds)

    [<Img src="https://github.com/takram-design-engineering/three-geospatial/raw/main/packages/clouds/docs/london.jpg" alt="Takram three-geospatial clouds" className="aspect-[16/9] object-cover"  width="1763" height="926" />](https://takram-design-engineering.github.io/three-geospatial/?path=/story/clouds-3d-tiles-renderer-integration--tokyo)
  </li>
  <li>
    [Luma Gaussian Splats](https://cdn-luma.com/public/lumalabs.ai/luma-web-library/0.2/fefe154/index.html#react-three-fiber)
    <Codesandbox id="h2fkgq" />
  </li>
  <li>
    [NYTimes/three-loader-3dtiles](https://github.com/nytimes/three-loader-3dtiles/blob/dev/examples/r3f/src/index.tsx)

    [<Img src="https://rd.nytimes.com/static/1ffcbe7f02d6168aecebdb7a84929dcf/1b9fc/7579e21f-3af0-46bb-a073-28c4a97594f9_Demo4.jpg" alt="three-loader-3dtiles r3f demo" className="aspect-[16/9] object-cover"  width="1763" height="926" />](https://nytimes.github.io/three-loader-3dtiles/dist/web/examples/demos/realitycapture/)
  </li>
  <li>
    [Looking Glass](https://docs.lookingglassfactory.com/developer-tools/webxr/react-three-fiber)
    <Codesandbox id="xzlmzz" screenshot_url="https://blog.lookingglassfactory.com/content/images/size/w2000/2024/05/LKG-32-Spatial-Display-Portrait-Cleopatra-1.jpg"/> 
  </li> 
  <li>
    [Theatre-js](https://github.com/theatre-js/theatre)
    <Codesandbox id="6xfrsv" screenshot_url="https://www.theatrejs.com/images/docs/0.5/manual/studio/ui.png" />
  </li>
  <li>
    [Farazz/CustomShaderMaterial](https://github.com/FarazzShaikh/THREE-CustomShaderMaterial)

    [<Img src="https://raw.githubusercontent.com/FarazzShaikh/THREE-CustomShaderMaterial/main/assets/waves-demo.png" alt="THREE-CustomShaderMaterial r3f demo" className="aspect-[16/9] object-cover"  width="1763" height="926" />](https://farazzshaikh.github.io/THREE-CustomShaderMaterial/#/caustics)
  </li>
  <li>
    [Takram three-geospatial atmosphere](https://github.com/takram-design-engineering/three-geospatial/tree/main/packages/atmosphere)

    [<Img src="https://media.githubusercontent.com/media/takram-design-engineering/three-geospatial/main/packages/atmosphere/docs/manhattan.jpg" alt="Takram three-geospatial atmosphere" className="aspect-[16/9] object-cover"  width="1763" height="926" />](https://takram-design-engineering.github.io/three-geospatial/?path=/story/atmosphere-3d-tiles-renderer-integration--manhattan)
  </li>
  <li>
    [utsuboco/r3f-perf](https://github.com/utsuboco/r3f-perf)
    <Codesandbox id="ykfpwf" />
  </li>
  <li>
    [pmndrs/THREE.MeshLine](https://github.com/pmndrs/meshline)
    <Codesandbox id="vl221" />
  </li>
  <li>
    [ektogamat/R3F-Ultimate-Lens-Flare](https://github.com/ektogamat/R3F-Ultimate-Lens-Flare)

    [<Img src="https://raw.githubusercontent.com/ektogamat/R3F-Ultimate-Lens-Flare/main/thumbnail.png" alt="R3F-Ultimate-Lens-Flare demo" className="aspect-[16/9] object-cover"  width="1763" height="926" />](https://ultimate-lens-flare.vercel.app/)
  </li>
</Grid>


================================================
FILE: docs/getting-started/examples.mdx
================================================
---
title: Examples
description: A few examples that demonstrate what you can do with React Three Fiber
nav: 3
---

## Showcase

<Grid cols={1}>
  <li>
    <Codesandbox id="6d97z4" tags={['selection', 'tiltshift']} />
  </li>
</Grid>
<Grid cols={2}>
  <li>
    <Codesandbox id="9s2wd9" tags={['border-radius']} />
  </li>
  <li>
    <Codesandbox id="7qytdw" tags={['bruno', 'simon', 'threejs-journey', 'fisheye']} />
  </li>
  <li>
    <Codesandbox id="xy8c8z" tags={['lusion', 'n8ao']} />
  </li>
  <li>
    <Codesandbox id="nvk9pf" tags={['ecctrl', 'character-controller']} />
  </li>
  <li>
    <Codesandbox id="bst0cy" tags={['effects', 'bloom', 'dof', 'reflections']} />
  </li>
  <li>
    <Codesandbox id="2ycs3" tags={['effects', 'dof', 'bananas']} />
  </li>
  <li>
    <Codesandbox id="ioxywi" tags={['configurator', 't-shirt', 'soft-shadows']} />
  </li>
  <li>
    <Codesandbox id="szj6p7" tags={['caustics', 'effects', 'soft-shadows']} />
  </li>
</Grid>
<Grid cols={4}>
  <li>
    <Codesandbox id="5w35n6" tags={['ssgi', 'rapier']} />
  </li>
  <li>
    <Codesandbox id="gwthnh" tags={['clouds']} />
  </li>
  <li>
    <Codesandbox id="2y73c6" tags={['motion-path', 'clouds']} />
  </li>
  <li>
    <Codesandbox id="ykfpwf" tags={['caustics', 'effects', 'soft-shadows']} />
  </li>
  <li>
    <Codesandbox id="yggpw5" tags={['godrays', 'reflections']} />
  </li>
  <li>
    <Codesandbox id="9m4tpc" tags={['portals']} />
  </li>
  <li>
    <Codesandbox id="qvk72r" tags={['portals']} />
  </li>
  <li>
    <Codesandbox id="drc6qg" tags={['portals']} />
  </li>
  <li>
    <Codesandbox id="hmbn1l" tags={['video', 'cookies', 'caustics']} />
  </li>
  <li>
    <Codesandbox id="dq6wwe" tags={['glass', 'transmission', 'bloom']} />
  </li>
  <li>
    <Codesandbox id="dc5fjy" tags={['cards', 'image']} />
  </li>
  <li>
    <Codesandbox id="3ywzzx" tags={['refraction']} />
  </li>
  <li>
    <Codesandbox id="lx2h8" tags={['reflections', 'annotations']} />
  </li>
  <li>
    <Codesandbox id="l4klb" tags={['scroll', 'controls']} />
  </li>
  <li>
    <Codesandbox id="zxpv7" tags={['physics']} />
  </li>
  <li>
    <Codesandbox id="0n9it" tags={['html', 'annotations']} />
  </li>
  <li>
    <Codesandbox id="imn42" tags={['frosted', 'glass', 'transmission']} />
  </li>
  <li>
    <Codesandbox id="pbwi6i" tags={['gltfjsx', 'effects', 'bloom', 'soft-shadows']} />
  </li>
  <li>
    <Codesandbox id="fslt99" tags={['effects', 'reflections', 'ssr', 'bloom']} />
  </li>
  <li>
    <Codesandbox id="2qfxj4" tags={['rapier', 'physics', 'soft-shadows']} />
  </li>
  <li>
    <Codesandbox id="2n98yj" tags={['scroll', 'refraction', 'lens']} />
  </li>
  <li>
    <Codesandbox id="e662p3" tags={['effects', 'bloom', 'reflections']} />
  </li>
  <li>
    <Codesandbox id="j3ycvl" tags={['effects', 'bloom']} />
  </li>
  <li>
    <Codesandbox id="lwo219" tags={['custom', 'environments']} />
  </li>
  <li>
    <Codesandbox id="qxjoj" tags={['gltfjsx', 'configurator']} />
  </li>
  <li>
    <Codesandbox id="dvokj" tags={['audio', 'analyser']} />
  </li>
  <li>
    <Codesandbox id="bfplr" tags={['ground', 'reflections', 'video-texture']} />
  </li>
  <li>
    <Codesandbox id="ni6v4" tags={['bruno-simon', 'threejs-journey']} />
  </li>
  <li>
    <Codesandbox id="9keg6" tags={['html', 'iframe']} />
  </li>
  <li>
    <Codesandbox id="f79ucc" tags={['splinetool', 'iframe']} />
  </li>
  <li>
    <Codesandbox id="zqrreo" tags={['refraction']} />
  </li>
  <li>
    <Codesandbox id="4gy946" tags={['refraction', 'instanced']} />
  </li>
  <li>
    <Codesandbox id="q48jgy" tags={['ground-projected-env']} />
  </li>
  <li>
    <Codesandbox id="ju368j" tags={['splinetool', 'transmission']} />
  </li>
  <li>
    <Codesandbox id="mlgzsc" tags={['transmission', 'csg']} />
  </li>
  <li>
    <Codesandbox id="y52tmt" tags={['csg']} />
  </li>
  <li>
    <Codesandbox id="hg3ejl" tags={['scroll', 'animation', 'effects', 'tiltshift']} />
  </li>
  <li>
    <Codesandbox id="ssbdsw" tags={['physics', 'effects', 'n8ao']} />
  </li>
  <li>
    <Codesandbox id="024uom" tags={['html', 'input']} />
  </li>
  <li>
    <Codesandbox id="gsm1y" tags={['scroll']} />
  </li>
  <li>
    <Codesandbox id="x8gvs" tags={['scroll']} />
  </li>
  <li>
    <Codesandbox id="yjhzv" tags={['scroll']} />
  </li>
  <li>
    <Codesandbox id="qpfgyp" tags={['effects', 'particles']} />
  </li>
  <li>
    <Codesandbox id="62o18n" tags={['cross-fade', 'transitions']} />
  </li>
  <li>
    <Codesandbox id="8j36ok" tags={['transmission', 'portals', 'physics']} />
  </li>
  <li>
    <Codesandbox id="n7jf0f" tags={['transmission', 'portals']} />
  </li>
  <li>
    <Codesandbox id="ik11ln" tags={['portals', 'blend']} />
  </li>
  <li>
    <Codesandbox id="lxvqek" />
  </li>
  <li>
    <Codesandbox id="if9crg" />
  </li>
  <li>
    <Codesandbox id="xzi6ps" />
  </li>
  <li>
    <Codesandbox id="qvb1vk" />
  </li>
  <li>
    <Codesandbox id="hxcc1x" />
  </li>
  <li>
    <Codesandbox id="8pbw1f" />
  </li>
  <li>
    <Codesandbox id="mw0dtc" />
  </li>
  <li>
    <Codesandbox id="8flefh" />
  </li>
  <li>
    <Codesandbox id="7e9y1b" />
  </li>
  <li>
    <Codesandbox id="whnhyr" />
  </li>
  <li>
    <Codesandbox id="0c5hv9" />
  </li>
  <li>
    <Codesandbox id="0fqow2" />
  </li>
  <li>
    <Codesandbox id="2ij9u" />
  </li>
  <li>
    <Codesandbox id="42glz0" />
  </li>
  <li>
    <Codesandbox id="ledhe1" />
  </li>
  <li>
    <Codesandbox id="nurp5t" />
  </li>
  <li>
    <Codesandbox id="2csbr1" />
  </li>
  <li>
    <Codesandbox id="go0b4w" />
  </li>
  <li>
    <Codesandbox id="s006f" />
  </li>
  <li>
    <Codesandbox id="l900i" />
  </li>
  <li>
    <Codesandbox id="qyz5r" />
  </li>
  <li>
    <Codesandbox id="kv7tv" />
  </li>
  <li>
    <Codesandbox id="ls503" />
  </li>
  <li>
    <Codesandbox id="n60qg" />
  </li>
  <li>
    <Codesandbox id="4jr4p" />
  </li>
  <li>
    <Codesandbox id="kud9p" />
  </li>
  <li>
    <Codesandbox id="zgsyn" />
  </li>
  <li>
    <Codesandbox id="i6t0j" />
  </li>
  <li>
    <Codesandbox id="h8o2d" />
  </li>
  <li>
    <Codesandbox id="wu51m" />
  </li>
  <li>
    <Codesandbox id="tu24h" />
  </li>
  <li>
    <Codesandbox id="jz9l97qn89" />
  </li>
  <li>
    <Codesandbox id="prb9t" />
  </li>
  <li>
    <Codesandbox id="pecl6" />
  </li>
  <li>
    <Codesandbox id="sbf2i" />
  </li>
  <li>
    <Codesandbox id="t4l0f" />
  </li>
  <li>
    <Codesandbox id="wdzv4" />
  </li>
  <li>
    <Codesandbox id="6hi1y" />
  </li>
  <li>
    <Codesandbox id="1sccp" />
  </li>
  <li>
    <Codesandbox id="q23sw" />
  </li>
  <li>
    <Codesandbox id="gpioq" />
  </li>
  <li>
    <Codesandbox id="3rjsl" />
  </li>
  <li>
    <Codesandbox id="4j2q2" />
  </li>
  <li>
    <Codesandbox id="dh2jc" />
  </li>
  <li>
    <Codesandbox id="gkfhr" />
  </li>
  <li>
    <Codesandbox id="0buje" />
  </li>
  <li>
    <Codesandbox id="5oufp" />
  </li>
  <li>
    <Codesandbox id="f1ixt" />
  </li>
  <li>
    <Codesandbox id="7psew" />
  </li>
  <li>
    <Codesandbox id="vl221" />
  </li>
  <li>
    <Codesandbox id="oep9o" />
  </li>
  <li>
    <Codesandbox id="tx1pq" />
  </li>
</Grid>

## Game prototypes

<Grid>
  <li>
    <Codesandbox id="lo6kp" />
  </li>
  <li>
    <Codesandbox id="rmfcq" />
  </li>
  <li>
    <Codesandbox id="i2160" />
  </li>
  <li>
    <Codesandbox id="vkgi6" />
  </li>
  <li>
    <Codesandbox id="2yqpv" />
  </li>
  <li>
    <Codesandbox id="ptdgrn" />
  </li>
  <li>
    <Codesandbox id="66cd7" />
  </li>
</Grid>

## Basic examples

<Grid>
  <li>
    <Codesandbox id="rrppl0y8l4" />
  </li>
  <li>
    <Codesandbox id="yup2o" />
  </li>
  <li>
    <Codesandbox id="0z8i2c" />
  </li>
  <li>
    <Codesandbox id="txzeq8" />
  </li>
  <li>
    <Codesandbox id="pj7zjq" />
  </li>
  <li>
    <Codesandbox id="wlz1o0" />
  </li>
  <li>
    <Codesandbox id="7n2yru" />
  </li>
  <li>
    <Codesandbox id="z3f2mw" />
  </li>
  <li>
    <Codesandbox id="btsbj" />
  </li>
  <li>
    <Codesandbox id="rz2g0" />
  </li>
  <li>
    <Codesandbox id="8fo01" />
  </li>
  <li>
    <Codesandbox id="7duy8" />
  </li>
  <li>
    <Codesandbox id="bp6tmc" tags={['views', 'portals']} />
  </li>
  <li>
    <Codesandbox id="r9w2ob" tags={['views', 'portals']} />
  </li>
  <li>
    <Codesandbox id="p9umgf" tags={['html', 'scroll']} />
  </li>
  <li>
    <Codesandbox id="k8phr" />
  </li>
  <li>
    <Codesandbox id="dix1y" />
  </li>
  <li>
    <Codesandbox id="zcuqh" />
  </li>
  <li>
    <Codesandbox id="7ucso" />
  </li>
  <li>
    <Codesandbox id="py4db" />
  </li>
  <li>
    <Codesandbox id="hf1cs" />
  </li>
  <li>
    <Codesandbox id="39hg8" />
  </li>
  <li>
    <Codesandbox id="wbrfs" />
  </li>
  <li>
    <Codesandbox id="itfgk" />
  </li>
  <li>
    <Codesandbox id="iup24" />
  </li>
  <li>
    <Codesandbox id="zu2wo" />
  </li>
  <li>
    <Codesandbox id="1g4qq" />
  </li>
  <li>
    <Codesandbox id="z8e6m" />
  </li>
  <li>
    <Codesandbox id="h545c" />
  </li>
  <li>
    <Codesandbox id="0k27n" />
  </li>
  <li>
    <Codesandbox id="d36mw" />
  </li>
  <li>
    <Codesandbox id="h873k" />
  </li>
  <li>
    <Codesandbox id="08s1u" />
  </li>
  <li>
    <Codesandbox id="wvgxp" />
  </li>
  <li>
    <Codesandbox id="5xho4" />
  </li>
  <li>
    <Codesandbox id="mbfzf" />
  </li>
  <li>
    <Codesandbox id="mkq8e" />
  </li>
  <li>
    <Codesandbox id="12nmp" />
  </li>
  <li>
    <Codesandbox id="6oei7" />
  </li>
  <li>
    <Codesandbox id="3k4g6" />
  </li>
  <li>
    <Codesandbox id="3878x" />
  </li>
  <li>
    <Codesandbox id="1b40u" />
  </li>
  <li>
    <Codesandbox id="0ycwe" />
  </li>
  <li>
    <Codesandbox id="ib0jc" />
  </li>
</Grid>


================================================
FILE: docs/getting-started/installation.mdx
================================================
---
title: Installation
description: Learn how to install react-three-fiber
nav: 1
---

```bash
npm install three @react-three/fiber
```

> [!WARNING]  
> Fiber is compatible with React v18 and v19 and works with ReactDOM and React Native. Fiber is a React renderer, it must pair with a major version of React, just like react-dom, react-native, etc. @react-three/fiber@8 pairs with react@18, @react-three/fiber@9 pairs with react@19.

Getting started with React Three Fiber is not nearly as hard as you might have thought, but various frameworks may require particular attention.

We've put together guides for getting started with each popular framework:

- Vite.js
- Next.js
- CDN w/o build tools
- React Native

If you just want to give it a try, fork this [example on codesandbox](https://codesandbox.io/s/rrppl0y8l4?file=/src/App.js)!

## Vite.js

`vite` will also work out of the box.

```bash
# Create app
npm create vite my-app

# Select react as framework

# Install dependencies
cd my-app
npm install three @react-three/fiber

# Start development server
npm run dev
```

## Next.js

It should work out of the box but you will encounter untranspiled add-ons in the three.js ecosystem, in that case,

### Next.js 13.1 or latest version

You need to add three to `transpilePackages` property in `next.config.js`:

```js
transpilePackages: ['three'],
```

### Next.js 13.0 or oldest version

You can install the `next-transpile-modules` module:

```bash
npm install next-transpile-modules --save-dev
```

then, add this to your `next.config.js`

```js
const withTM = require('next-transpile-modules')(['three'])
module.exports = withTM()
```

Make sure to check out our [official next.js starter](https://github.com/pmndrs/react-three-next), too!

## Without build tools

You can use React Three Fiber with browser-ready ES Modules from [esm.sh](https://esm.sh) and a JSX-like syntax powered by [htm](https://github.com/developit/htm).

```jsx
import ReactDOM from 'https://esm.sh/react-dom'
import React, { useRef, useState } from 'https://esm.sh/react'
import { Canvas, useFrame } from 'https://esm.sh/@react-three/fiber'
import htm from 'https://esm.sh/htm'

const html = htm.bind(React.createElement)
ReactDOM.render(html`<${Canvas}>...<//>`, document.getElementById('root'))
```

<details>
<summary>Full example</summary>

```jsx
import ReactDOM from 'https://esm.sh/react-dom'
import React, { useRef, useState } from 'https://esm.sh/react'
import { Canvas, useFrame } from 'https://esm.sh/@react-three/fiber'
import htm from 'https://esm.sh/htm'

const html = htm.bind(React.createElement)

function Box(props) {
  const meshRef = useRef()
  const [hovered, setHover] = useState(false)
  const [active, setActive] = useState(false)
  useFrame(() => (meshRef.current.rotation.x = meshRef.current.rotation.y += 0.01))
  return html` <mesh
    ...${props}
    ref=${meshRef}
    scale=${active ? 1.5 : 1}
    onClick=${() => setActive(!active)}
    onPointerOver=${() => setHover(true)}
    onPointerOut=${() => setHover(false)}
  >
    <boxGeometry args=${[1, 1, 1]} />
    <meshStandardMaterial color=${hovered ? 'hotpink' : 'orange'} />
  </mesh>`
}

ReactDOM.render(
  html` <${Canvas}>
    <ambientLight />
    <pointLight position=${[10, 10, 10]} />
    <${Box} position=${[-1.2, 0, 0]} />
    <${Box} position=${[1.2, 0, 0]} />
  <//>`,
  document.getElementById('root'),
)
```

</details>

## React Native

R3F v8 adds support for react-native and can be imported from `@react-three/fiber/native`. We use `expo-gl` and `expo-asset` under the hood for WebGL2 bindings and ensuring interplay between Metro and three.js loaders.

To get started, create an app via `expo` or `react-native`:

```bash
# Create a managed/bare app
npx create-expo-app
cd my-app

# or

# Create and link bare app
npx react-native init my-app
npx install-expo-modules@latest
cd my-app
```

Then install dependencies (for manual installation or migration, see [expo modules installation](https://docs.expo.dev/bare/installing-expo-modules)):

```bash
# Automatically install
expo install expo-gl

# Install NPM dependencies
npm install three @react-three/fiber
```

Some configuration may be required to tell the Metro bundler about your assets if you use `useLoader` or Drei abstractions like `useGLTF` and `useTexture`:

```js
// metro.config.js
module.exports = {
  resolver: {
    sourceExts: ['js', 'jsx', 'json', 'ts', 'tsx', 'cjs', 'mjs'],
    assetExts: ['glb', 'gltf', 'png', 'jpg'],
  },
}
```

R3F's API is completely x-platform, so you can use [events](/api/events) and [hooks](/api/hooks) just as you would on the web.

> [!NOTE]
> Make sure to import from `@react-three/fiber/native` or `@react-three/drei/native` for correct IntelliSense and platform-specific abstractions.

> [!NOTE]
> iOS simulators often have incomplete or unreliable OpenGL ES support, which can cause EXC_BAD_ACCESS crashes when rendering 3D content. Always test on a physical iOS device (iPhone/iPad running iOS 16 or later) to ensure stable WebGL rendering.

```jsx
import { Suspense } from 'react'
import { Canvas } from '@react-three/fiber/native'
import { useGLTF } from '@react-three/drei/native'
import modelPath from './path/to/model.glb'

function Model(props) {
  const gltf = useGLTF(modelPath)
  return <primitive {...props} object={gltf.scene} />
}

export default function App() {
  return (
    <Canvas>
      <ambientLight />
      <Suspense>
        <Model />
      </Suspense>
    </Canvas>
  )
}
```


================================================
FILE: docs/getting-started/introduction.mdx
================================================
---
title: Introduction
description: React-three-fiber is a React renderer for three.js.
nav: 0
---

<Intro>
  Build your scene declaratively with re-usable, self-contained components that react to state, are readily interactive and can participate in [React](https://react.dev)'s ecosystem.
</Intro>

[![React Three Fiber banner](../banner-r3f.jpg)](/getting-started/examples)

```bash
npm install three @types/three @react-three/fiber
```
> [!WARNING]  
> Three-fiber is a React renderer, it must pair with a major version of React, just like react-dom, react-native, etc. @react-three/fiber@8 pairs with react@18, @react-three/fiber@9 pairs with react@19.

## Does it have limitations?

None. Everything that works in Threejs will work here without exception.

## Is it slower than plain Threejs?

No. There is no overhead. Components render outside of React. It outperforms Threejs in scale due to React's scheduling abilities.

## Can it keep up with frequent feature updates to Threejs?

Yes. It merely expresses Threejs in JSX, `<mesh />` dynamically turns into `new THREE.Mesh()`. If a new Threejs version adds, removes or changes features, it will be available to you instantly without depending on updates to this library.

## What does it look like?

Let's make a re-usable component that has its own state, reacts to user-input and participates in the render-loop:

<Sandpack
  customSetup={{
    dependencies: {
      'react': 'latest',
      'react-dom': 'latest',
      'three': 'latest',
      '@react-three/fiber': 'latest'
    },
    entry: '/index.jsx',
  }}
  folder="basic-example-sandpack"
/>

<details>
  <summary>Show TypeScript example</summary>

```bash
npm install @types/three
```

<Sandpack
  customSetup={{
    dependencies: {
      'react': 'latest',
      'react-dom': 'latest',
      'three': 'latest',
      '@types/three': 'latest',
      '@react-three/fiber': 'latest'
    },
    entry: '/index.tsx',
    main: '/index.tsx',
  }}
  files={{
    '/styles.css': `html,body,#root {height:100%;margin:unset;}`,
    '/index.tsx': `import * as THREE from 'three'
import { createRoot } from 'react-dom/client'
import React, { useRef, useState } from 'react'
import { Canvas, useFrame, ThreeElements } from '@react-three/fiber'
import './styles.css'

function Box(props: ThreeElements['mesh']) {
  const meshRef = useRef<THREE.Mesh>(null!)
  const [hovered, setHover] = useState(false)
  const [active, setActive] = useState(false)
  useFrame((state, delta) => (meshRef.current.rotation.x += delta))
  return (
    <mesh
      {...props}
      ref={meshRef}
      scale={active ? 1.5 : 1}
      onClick={(event) => setActive(!active)}
      onPointerOver={(event) => setHover(true)}
      onPointerOut={(event) => setHover(false)}>
      <boxGeometry args={[1, 1, 1]} />
      <meshStandardMaterial color={hovered ? 'hotpink' : '#2f74c0'} />
    </mesh>
  )
}

createRoot(document.getElementById('root')).render(
  <Canvas>
    <ambientLight intensity={Math.PI / 2} />
    <spotLight position={[10, 10, 10]} angle={0.15} penumbra={1} decay={0} intensity={Math.PI} />
    <pointLight position={[-10, -10, -10]} decay={0} intensity={Math.PI} />
    <Box position={[-1.2, 0, 0]} />
    <Box position={[1.2, 0, 0]} />
  </Canvas>,
)`,
  }}
/>

</details>

<details>
  <summary>Show React Native example</summary>

For installation instructions see [react native installation instructions](/getting-started/installation#react-native).

```jsx
import React, { useRef, useState } from 'react'
import { Canvas, useFrame } from '@react-three/fiber/native'

function Box(props) {
  const meshRef = useRef(null)
  const [hovered, setHover] = useState(false)
  const [active, setActive] = useState(false)
  useFrame((state, delta) => (meshRef.current.rotation.x += delta))
  return (
    <mesh
      {...props}
      ref={meshRef}
      scale={active ? 1.5 : 1}
      onClick={(event) => setActive(!active)}
      onPointerOver={(event) => setHover(true)}
      onPointerOut={(event) => setHover(false)}>
      <boxGeometry args={[1, 1, 1]} />
      <meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />
    </mesh>
  )
}

export default function App() {
  return (
    <Canvas>
      <ambientLight intensity={Math.PI / 2} />
      <spotLight position={[10, 10, 10]} angle={0.15} penumbra={1} decay={0} intensity={Math.PI} />
      <pointLight position={[-10, -10, -10]} decay={0} intensity={Math.PI} />
      <Box position={[-1.2, 0, 0]} />
      <Box position={[1.2, 0, 0]} />
    </Canvas>
  )
}
```

</details>

## First steps

You need to be versed in both React and Threejs before rushing into this. If you are unsure about React consult the official [React docs](https://react.dev/learn), especially [the section about hooks](https://react.dev/reference/react). As for Threejs, make sure you at least glance over the following links:

1. Make sure you have a [basic grasp of Threejs](https://threejs.org/docs/index.html#manual/en/introduction/Creating-a-scene). Keep that site open.
2. When you know what a scene is, a camera, mesh, geometry, material, fork the [demo above](https://github.com/pmndrs/react-three-fiber#what-does-it-look-like).
3. [Look up](https://threejs.org/docs/index.html#api/en/objects/Mesh) the JSX elements that you see (mesh, ambientLight, etc), _all_ threejs exports are native to three-fiber.
4. Try changing some values, scroll through our [API](/api/canvas) to see what the various settings and hooks do.

Some helpful material:

- [Threejs-docs](https://threejs.org/docs) and [examples](https://threejs.org/examples)
- [Discover Threejs](https://discoverthreejs.com), especially the [Tips and Tricks](https://discoverthreejs.com/tips-and-tricks) chapter for best practices
- [Bruno Simons Threejs Journey](https://threejs-journey.com), arguably the best learning resource, now includes a full [R3F chapter](https://threejs-journey.com/lessons/what-are-react-and-react-three-fiber)

<a href="https://threejs-journey.com">
  <img src="../banner-journey.jpg" />
</a>

## Eco system

There is a vibrant and extensive eco system around three-fiber, full of libraries, helpers and abstractions.

- [`@react-three/drei`](https://github.com/pmndrs/drei) &ndash; useful helpers, this is an eco system in itself
- [`@react-three/gltfjsx`](https://github.com/pmndrs/gltfjsx) &ndash; turns GLTFs into JSX components
- [`@react-three/postprocessing`](https://github.com/pmndrs/react-postprocessing) &ndash; post-processing effects
- [`@react-three/test-renderer`](https://github.com/pmndrs/react-three-fiber/tree/master/packages/test-renderer) &ndash; for unit tests in node
- [`@react-three/flex`](https://github.com/pmndrs/react-three-flex) &ndash; flexbox for react-three-fiber
- [`@react-three/xr`](https://github.com/pmndrs/react-xr) &ndash; VR/AR controllers and events
- [`@react-three/csg`](https://github.com/pmndrs/react-three-csg) &ndash; constructive solid geometry
- [`@react-three/rapier`](https://github.com/pmndrs/react-three-rapier) &ndash; 3D physics using Rapier
- [`@react-three/cannon`](https://github.com/pmndrs/use-cannon) &ndash; 3D physics using Cannon
- [`@react-three/p2`](https://github.com/pmndrs/use-p2) &ndash; 2D physics using P2
- [`@react-three/a11y`](https://github.com/pmndrs/react-three-a11y) &ndash; real a11y for your scene
- [`@react-three/gpu-pathtracer`](https://github.com/pmndrs/react-three-gpu-pathtracer) &ndash; realistic path tracing
- [`create-r3f-app next`](https://github.com/pmndrs/react-three-next) &ndash; nextjs starter
- [`lamina`](https://github.com/pmndrs/lamina) &ndash; layer based shader materials
- [`zustand`](https://github.com/pmndrs/zustand) &ndash; flux based state management
- [`jotai`](https://github.com/pmndrs/jotai) &ndash; atoms based state management
- [`valtio`](https://github.com/pmndrs/valtio) &ndash; proxy based state management
- [`react-spring`](https://github.com/pmndrs/react-spring) &ndash; a spring-physics-based animation library
- [`framer-motion-3d`](https://www.framer.com/docs/three-introduction/) &ndash; framer motion, a popular animation library
- [`use-gesture`](https://github.com/pmndrs/react-use-gesture) &ndash; mouse/touch gestures
- [`leva`](https://github.com/pmndrs/leva) &ndash; create GUI controls in seconds
- [`maath`](https://github.com/pmndrs/maath) &ndash; a kitchen sink for math helpers
- [`miniplex`](https://github.com/hmans/miniplex) &ndash; ECS (entity management system)
- [`composer-suite`](https://github.com/hmans/composer-suite) &ndash; composing shaders, particles, effects and game mechanics

## How to contribute

If you like this project, please consider helping out. All contributions are welcome as well as donations to [Opencollective](https://opencollective.com/react-three-fiber), or in crypto `BTC: 36fuguTPxGCNnYZSRdgdh6Ea94brCAjMbH`, `ETH: 0x6E3f79Ea1d0dcedeb33D3fC6c34d2B1f156F2682`.

## Backers

Thank you to all our backers! 🙏

<a href="https://opencollective.com/react-three-fiber#backers" target="_blank">
  <img src="https://opencollective.com/react-three-fiber/backers.svg?width=890" width="890" height="207" />
</a>

## Contributors

This project exists thanks to all the people who contribute.

<a href="https://github.com/pmndrs/react-three-fiber/graphs/contributors">
  <img src="https://opencollective.com/react-three-fiber/contributors.svg?width=890" width="890" height="411" />
</a>


================================================
FILE: docs/getting-started/your-first-scene.mdx
================================================
---
title: Your first scene
description: This guide will help you setup your first React Three Fiber scene and introduce you to its core concepts.
nav: 2
---

This tutorial will assume some React knowledge.

## Setting up the Canvas

We'll start by importing the `<Canvas />` component from `@react-three/fiber` and putting it in our React tree.

```jsx
import { createRoot } from 'react-dom/client'
import { Canvas } from '@react-three/fiber'

function App() {
  return (
    <div id="canvas-container">
      <Canvas />
    </div>
  )
}

createRoot(document.getElementById('root')).render(<App />)
```

The Canvas component does some important setup work behind the scenes:

- It sets up a **Scene** and a **Camera**, the basic building blocks necessary for rendering
- It renders our scene every frame, you do not need a traditional render-loop

> [!NOTE]
> Canvas is responsive to fit the parent node, so you can control how big it is by changing the parents width and height, in this case #canvas-container.

## Adding a Mesh Component

To actually see something in our scene, we'll add a lowercase `<mesh />` native element, which is the direct equivalent to new THREE.Mesh().

```js
<Canvas>
  <mesh />
```

> [!NOTE]
> Note that we don't need to import anything, All three.js objects will be treated as native JSX elements, just like you can just write &lt;div /&gt; or &lt;span /&gt; in regular ReactDOM. The general rule is that Fiber components are available under the camel-case version of their name in three.js.

A [`Mesh`](https://threejs.org/docs/#api/en/objects/Mesh) is a basic scene object in three.js, and it's used to hold the geometry and the material needed to represent a shape in 3D space.
We'll create a new mesh using a **BoxGeometry** and a **MeshStandardMaterial** which [automatically attach](/api/objects#attach) to their parent.

```jsx
<Canvas>
  <mesh>
    <boxGeometry />
    <meshStandardMaterial />
  </mesh>
</Canvas>
```

Let's pause for a moment to understand exactly what is happening here. The code we just wrote is the equivalent to this three.js code:

```jsx
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000)

const renderer = new THREE.WebGLRenderer()
renderer.setSize(width, height)
document.querySelector('#canvas-container').appendChild(renderer.domElement)

const mesh = new THREE.Mesh()
mesh.geometry = new THREE.BoxGeometry()
mesh.material = new THREE.MeshStandardMaterial()

scene.add(mesh)

function animate() {
  requestAnimationFrame(animate)
  renderer.render(scene, camera)
}

animate()
```

### Constructor arguments

According to the [docs for `BoxGeometry`](https://threejs.org/docs/#api/en/geometries/BoxGeometry) we can optionally pass three arguments for: width, length and depth:

```js
new THREE.BoxGeometry(2, 2, 2)
```

In order to do this in Fiber we use the `args` prop, which _always_ takes an array whose items represent the constructor arguments.

```jsx
<boxGeometry args={[2, 2, 2]} />
```

> [!NOTE]
> Note that every time you change args, the object must be re-constructed!

## Adding lights

Next, we will add some lights to our scene, by putting these components into our canvas.

```jsx
<Canvas>
  <ambientLight intensity={0.1} />
  <directionalLight color="red" position={[0, 0, 5]} />
```

### Props

This introduces us to the last fundamental concept of Fiber, how React `props` work on three.js objects. When you set any prop on a Fiber component, it will set the property of the same name on the three.js instance.

Let's focus on our `ambientLight`, whose [documentation](https://threejs.org/docs/#api/en/lights/AmbientLight) tells us that we can optionally construct it with a color, but it can also receive props.

```jsx
<ambientLight intensity={0.1} />
```

Which is the equivalent to:

```jsx
const light = new THREE.AmbientLight()
light.intensity = 0.1
```

### Shortcuts

There are a few shortcuts for props that have a `.set()` method (colors, vectors, etc).

```jsx
const light = new THREE.DirectionalLight()
light.position.set(0, 0, 5)
light.color.set('red')
```

Which is the same as the following in JSX:

```jsx
<directionalLight position={[0, 0, 5]} color="red" />
```

Please refer to the API for [a deeper explanation](/api/objects).

## The result

<Sandpack
  template="react"
  customSetup={{
    dependencies: {
      'react': 'latest',
      'react-dom': 'latest',
      'three': 'latest',
      '@types/three': 'latest',
      '@react-three/fiber': 'latest'
    },
  }}
  files={{
    '/styles.css': `html,body,#root {height:100%;margin:unset;}`,
    '/App.js': `import { Canvas } from "@react-three/fiber";

export default function App() {
  return (
      <Canvas>
        <mesh>
          <boxGeometry args={[2, 2, 2]} />
          <meshPhongMaterial />
        </mesh>
        <ambientLight intensity={0.1} />
        <directionalLight position={[0, 0, 5]} color="red" />
      </Canvas>
  );
}`,
  }}
/>

> [!TIP]
> You can live-edit the code above:
> - try different materials, like [`MeshNormalMaterial`](https://threejs.org/docs/#api/en/materials/MeshNormalMaterial) or [`MeshBasicMaterial`](https://threejs.org/docs/#api/en/materials/MeshBasicMaterial), give them a color
> - try different geometries, like [`SphereGeometry`](https://threejs.org/docs/#api/en/geometries/SphereGeometry) or [`OctahedronGeometry`](https://threejs.org/docs/#api/en/geometries/OctahedronGeometry)
> - try changing the `position` on our `mesh` component, by setting the prop with the same name
> - try extracting our mesh to a new component


================================================
FILE: docs/tutorials/basic-animations.mdx
================================================
---
title: Basic Animations
description: This guide will help you understand refs, useFrame and how to make basic animations with Fiber
nav: 17
---

This tutorial will assume some React knowledge, and will be based on [this starter codesandbox](https://codesandbox.io/s/getting-started-01-12q81?from-embed), so just fork it and follow along!

We will build a really small, continuous animation loop, that will be the basic building block of more advanced animations later on.

## `useFrame`

`useFrame` is a Fiber hook that lets you execute code on every frame of Fiber's render loop. This can have a lot of uses, but we will focus on building an animation with it.

It's important to remember that **Fiber hooks can only be called inside a `<Canvas />` parent**!

```jsx
import { useFrame } from '@react-three/fiber'

function MyAnimatedBox() {
  useFrame(() => {
    console.log("Hey, I'm executing every frame!")
  })
  return (
    <mesh>
      <boxGeometry />
      <meshBasicMaterial color="royalblue" />
    </mesh>
  )
}
```

This loop is the basic building block of our animation, the callback we pass to `useFrame` will be executed every frame and it will be passed an object containing the state of our Fiber scene:

For example, we can extract time information from the `clock` parameter, to know how much time has elapsed in our application, and use that time to animate a value:

```jsx
useFrame(({ clock }) => {
  const a = clock.elapsedTime
  console.log(a) // the value will be 0 at scene initialization and grow each frame
})
```

`clock` is a [three.js Clock](https://threejs.org/docs/#api/en/core/Clock) object, from which we are getting the total elapsed time, which will be key for our animations.

## Animating with Refs

It would be tempting to just update the state of our component via `setState` and let it change the `mesh` via props, but going through state isn't ideal, when dealing with continuous updates, commonly know as [transient updates]().
Instead, we want to **directly mutate our mesh each frame**. First, we'll have to get a `reference` to it, via the `useRef` React hook:

```jsx
import React from 'react'

function MyAnimatedBox() {
  const myMesh = React.useRef()
  return (
    <mesh ref={myMesh}>
      <boxGeometry />
      <meshBasicMaterial color="royalblue" />
    </mesh>
  )
}
```

`myMesh` will now hold a reference to the actual three.js object, which we can now freely mutate in `useFrame`, without having to worry about React:

```jsx
useFrame(({ clock }) => {
  myMesh.current.rotation.x = clock.elapsedTime
})
```

Let's have a closer look:

- We are destructuring `clock` from the argument passed to `useFrame`, which we know is the state of our Fiber scene.
- We are accessing the `rotation.x` property of `myMesh.current` object, which is a reference to our mesh object
- We are assigning our time-dependent value `a` to the `rotation` on the `x` axis, meaning our object will now infinitely rotate between -1 and 1 radians around the x axis!

<Codesandbox id="29gxw" />

**Exercises**

- Try `Math.sin(clock.elapsedTime)` and see how your animation changes

## Next steps

Now that you understand the basic technique for animating in Fiber, [learn how event works](/tutorials/events-and-interaction)!

If you want to go deeper into animations, check these out:

- [Animating with React Spring](/tutorials/using-with-react-spring)


================================================
FILE: docs/tutorials/events-and-interaction.mdx
================================================
---
title: 'Events and Interaction'
description: Let's make our meshes react to user input.
nav: 14
---

This tutorial will assume some React knowledge, and will be based on [this starter codesandbox](https://codesandbox.io/s/getting-started-01-12q81?from-embed), so just fork it and follow along!

After we have our continuous loop running the next step would be to allow our mesh to react to user interaction, so in this part let's attach a click handler to the cube and make it bigger on click.

## User Interaction

Any Object3D that has a raycast method can receive a large number of events, for instance a mesh:

```jsx
<mesh
  onClick={(e) => console.log('click')}
  onContextMenu={(e) => console.log('context menu')}
  onDoubleClick={(e) => console.log('double click')}
  onWheel={(e) => console.log('wheel spins')}
  onPointerUp={(e) => console.log('up')}
  onPointerDown={(e) => console.log('down')}
  onPointerOver={(e) => console.log('over')}
  onPointerOut={(e) => console.log('out')}
  onPointerEnter={(e) => console.log('enter')}
  onPointerLeave={(e) => console.log('leave')}
  onPointerMove={(e) => console.log('move')}
  onPointerMissed={() => console.log('missed')}
  onUpdate={(self) => console.log('props have been updated')}
/>
```

From this we can see that what we need to do is use the old `onClick` event we use on any DOM element to react to a user clicking the mesh.

Let's add it then:

```jsx
<mesh onClick={() => alert('Hellooo')}>
  <boxGeometry />
  <meshPhongMaterial color="royalblue" />
</mesh>
```

We did it! We created the most boring interaction in the story of 3D and we made an alert show up. Now let's make it actually animate our mesh.

Let's start by setting some state to check if the mesh is active:

```jsx
const [active, setActive] = useState(false)
```

After we have this we can set the scale with a ternary operator like so:

```jsx
<mesh scale={active ? 1.5 : 1} onClick={() => setActive(!active)}>
  <boxGeometry />
  <meshPhongMaterial color="royalblue" />
</mesh>
```

If you try to click on your mesh now, it scales up and down. We just made our first interactive 3D mesh!

What we did in this chapter was:

- Attached a click handler to our mesh
- Added some state to track if the mesh is currently active
- Changed the scale based on that state

<Codesandbox id="98ppy" />

**Exercises**

- Change other props of the mesh like the `position` or even the `color` of the material.
- Use `onPointerOver` and `onPointerOut` to change the props of the mesh on hover events.

## Next steps

We just made our mesh react to user interaction but it looks pretty bland without any transition, right?
In the next chapter let's integrate `react-spring` into our project to make this into an actual animation.


================================================
FILE: docs/tutorials/how-it-works.mdx
================================================
---
title: How does it work?
description: This is an advanced guide on the inner workings of Fiber, if you are just getting started, take a
  look at our introduction!
nav: 18
---

React Three Fiber is a React <a href="https://reactjs.org/docs/codebase-overview.html#renderers">renderer</a> for **three.js**.

This means that each Fiber component will effectively create a new THREE object that will be added to a `scene`.
Understanding how this works is not necessarily needed to use Fiber, but it will better arm you to deal with anything that you might need in your projects, reading other people's Fiber code and even help you contribute.

Let's take a small React example:

```jsx
import { Canvas } from '@react-three/fiber'

function MyApp() {
  return (
    <Canvas>
      <group>
        <mesh>
          <meshNormalMaterial />
          <boxGeometry args={[2, 2, 2]} />
        </mesh>
      </group>
    </Canvas>
  )
}
```

In three.js, this is equivalent to:

```js
import * as THREE from 'three'

const scene = new THREE.Scene() // <Canvas>

const group = new THREE.Group() // <group>

const mesh = new THREE.Mesh() // <mesh />
const material = new THREE.MeshNormalMaterial() // <meshNormalMaterial />
const geometry = new THREE.BoxGeometry(2, 2, 2) // <boxGeometry />

mesh.material = material
mesh.geometry = geometry

group.add(mesh)
scene.add(group)
```

Our `Canvas` element will create a new scene, and Fiber will instantiate new objects for each component and correctly compose them together in a scene graph!

Additionally, Fiber will:

- Setup a new perspective camera at [0, 0, 0] and set it as default
- Setup a **render loop** with automatic render to screen
- Setup pointer events via raycasting on all meshes with `onPointer` props
- Setup tone mapping
- Automatically handle window resize

**Let's break this down!**

## Creating THREE objects

In three.js, we can create new object using the classic JS API:

```js
const myBox = new THREE.BoxGeometry(1, 2, 3)
```

Object creation is handled transparently by the Fiber renderer, the name of the constructor `BoxGeometry` is equivalent to the camel case component `<boxGeometry />`, while the constructor arguments - in our example `[1, 2, 3]` - are passed via the `args` prop:

```jsx
<boxGeometry args={[1, 2, 3]} />
```

> [!NOTE]
> Note that the object will be created only when first adding the component to the React tree!

## The `attach` props

Fiber always tries to correctly infer the relationship between components and their parents, for example:

```jsx
<group>
  <mesh />
</group>
```

Here, we always know that a group can only have children, so Fiber just calls the `add` method on the group:

```js
group.add(mesh)
```

For meshes and other three.js objects, rules can be different. Looking at the three.js documentation, we can see how a `THREE.Mesh` object is constructed using a `material` and a `geometry`.

With the `attach` prop, we can precisely tell the renderer what property to attach each component to:

```jsx
<mesh>
  <meshNormalMaterial attach="material" />
  <boxGeometry attach="geometry" />
</mesh>
```

This will _explicitly_ tell Fiber to render like this:

```js
mesh.material = new THREE.MeshNormalMaterial()
mesh.geometry = new THREE.BoxGeometry()
```

As you can see, the `attach` prop is telling Fiber to set the parent's `material` property to a reference to our `<meshNormalMaterial />` object.

Note that while we used geometry and material for this example, Fiber also infers the attach property from the
constructor name, so anything with `material` or `geometry` will automatically get attached to the correct property of
its parent.

## Props

With Fiber, you can pass any three.js property as a React property, and it will be assigned to the constructed object:

```jsx
<meshBasicMaterial color="red" />
```

is equivalent to:

```jsx
const material = new THREE.MeshBasicMaterial()
material.color = 'red'
```

Fiber will check the type of the property value and either:

- assign the new value directly
- if the value is an object with a `set` method, call that
- construct a new object if needed.
- convert between formats

```jsx
<mesh scale={[1, 2, 3]} />
```

is equivalent to:

```jsx
const mesh = new THREE.Mesh()
mesh.scale = new THREE.Vector3(1, 2, 3)

// on update, it will instead `set()` the vector
mesh.scale.set(3, 4, 5)
```

## Pointer Events

[Pointer Events](/api/events) are transparently handled by Fiber. On startup, it will create a [raycaster](https://threejs.org/docs/#api/en/core/Raycaster) for mouse picking.

Every object with `onPointer` props will be added to the array of objects checked every frame by the raycaster:

```jsx
<mesh onPointerDown={console.log}>...</mesh>
```

The ray's `origin` and `direction` are updated every time the mouse moves on the `<Canvas />` element or the window is resized.
Fiber also handles camera switching, meaning that the raycaster will always use the currently active camera.

When using the `raycast` prop, the object will instead be picked using a custom ray:

```jsx
import { useCamera } from '@react-three/drei'

return <mesh raycast={useCamera(anotherCamera)} />
```

## Render Loop

By default, Fiber will setup a render loop that renders the default `scene` from the default `camera` to a [WebGLRenderer](https://threejs.org/docs/#api/en/renderers/WebGLRenderer).

The loop is setup using [setAnimationLoop](https://threejs.org/docs/#api/en/renderers/WebGLRenderer.setAnimationLoop), which will execute its callback every time a new frame is renderable. This is what will happen every render:

1. All global before effects are executed
2. Clock delta is saved - implying all `useFrame` calls will share the same `delta`
3. `useFrame` callbacks are executed in order
4. `renderer.render(scene, camera)` is called, effectively rendering the scene to screen
5. All global after effects are executed


================================================
FILE: docs/tutorials/loading-models.mdx
================================================
---
title: 'Loading Models'
description: 3D Software to the web!
nav: 15
---

> All the models in this page were created by Sara Vieira and are freely available to download from any of the sandboxes.

There are many types of 3D model extensions, in this page we will focus on loading the three most common ones: `GLTF`, `FBX` and `OBJ`. All of these will use the `useLoader` function but in slightly different ways.

This whole section will assume you have placed your models in the public folder or in a place in your application where you can import them easily.

## Loading GLTF models

Starting with the open standard and the one that has more support in React Three Fiber we will load a `.gltf` model.

Let's start by importing the two things we need:

```js
import { useLoader } from '@react-three/fiber'
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'
```

With this we can create a Model component and place it in our scene like so:

```jsx
function Scene() {
  const gltf = useLoader(GLTFLoader, '/Poimandres.gltf')
  return <primitive object={gltf.scene} />
}
```

You can play with the sandbox and see how it looks here after I added an HDRI background:

<Codesandbox id="6etx1" />

### Loading GLTF models as JSX Components

Here comes the really fancy part, you can transform these models into React components and then use them as you would any React component.

To do this, grab your `GLTF` model and head over to [https://gltf.pmnd.rs/](https://gltf.pmnd.rs/) and drop your `GLTF`, after that you should see something like:

![gltfjsx](gltfjsx.png)

Let's now copy the code and move it over to `Model.js`:

```jsx
/*
Auto-generated by: https://github.com/pmndrs/gltfjsx
*/

import React, { useRef } from 'react'
import { useGLTF } from '@react-three/drei'

export default function Model(props) {
  const groupRef = useRef()
  const { nodes, materials } = useGLTF('/Poimandres.gltf')
  return (
    <group ref={groupRef} {...props} dispose={null}>
      <mesh castShadow receiveShadow geometry={nodes.Curve007_1.geometry} material={materials['Material.001']} />
      <mesh castShadow receiveShadow geometry={nodes.Curve007_2.geometry} material={materials['Material.002']} />
    </group>
  )
}

useGLTF.preload('/Poimandres.gltf')
```

Now we can import our model like we would import any React component and use it in our app:

```jsx
import { Suspense } from 'react'
import { Canvas } from '@react-three/fiber'
import { Environment } from '@react-three/drei'

import Model from './Model'

export default function App() {
  return (
    <div className="App">
      <Canvas>
        <Suspense fallback={null}>
          <Model />
          <Environment preset="sunset" background />
        </Suspense>
      </Canvas>
    </div>
  )
}
```

You can play with the sandbox here:

<Codesandbox id="vbnbf" />

## Loading OBJ models

In this case, we will use the trusted `useLoader` hook but in combination with `three.js` `OBJLoader`.

```js
import { OBJLoader } from 'three/addons/loaders/OBJLoader.js'
import { useLoader } from '@react-three/fiber'
```

With these imported let's get the mesh into our scene:

```jsx
function Scene() {
  const obj = useLoader(OBJLoader, '/Poimandres.obj')
  return <primitive object={obj} />
}
```

And here we go, we have an OBJ model showing on the web! Pretty cool ah?

You can play with the sandbox here:

<Codesandbox id="51zks" />

## Loading FBX models

Let's again use the trusted `useLoader` but this time with the `FBXLoader` that comes from `three.js`

```js
import { useLoader } from '@react-three/fiber'
import { FBXLoader } from 'three/addons/loaders/FBXLoader.js'
```

To create our scene we can get the FBX as a return value of the useLoader by passing the `FBXloader` and the location of our file like so:

```jsx
function Scene() {
  const fbx = useLoader(FBXLoader, '/Poimandres.fbx')
  return <primitive object={fbx} />
}
```

You can play with the sandbox here:

<Codesandbox id="ssrfg" />

### Loading FBX models using `useFBX`

[@react-three/drei](https://github.com/pmndrs/drei) exports a very useful helper when it comes to loading FBX models and it's called `useFBX`, in this case there is no need to import anything from `three.js` as it is all done behind the scenes and we can just pass the location of the file to `useFBX` like so:

```jsx
function Scene() {
  const fbx = useFBX('/Poimandres.fbx')
  return <primitive object={fbx} />
}
```

You can play with the sandbox here:

<Codesandbox id="m6p73" />

## Showing a loader

If your model is big and takes a while to load, it's always good to show a small loader of how much is already is loaded and again [@react-three/drei](https://github.com/pmndrs/drei) is here to help with `Html` and `useProgress`.

- `Html` allows you place plain ol' HTML in your canvas and render it like you would a normal DOM element.
- `useProgress` is a hook that gives you a bunch of information about the loading status of your model.

With these two things, we can create a very bare-bones loading component like so:

```jsx
import { Html, useProgress } from '@react-three/drei'

function Loader() {
  const { progress } = useProgress()
  return <Html center>{progress} % loaded</Html>
}
```

We can then wrap our model in it using `Suspense` like so:

```jsx
export default function App() {
  return (
    <Canvas>
      <Suspense fallback={<Loader />}>
        <Model />
      </Suspense>
    </Canvas>
  )
}
```

The hook returns much more than just the progress so there is a lot you can do there to give the user more information about the loading status of the application. You can play with all of them in this sandbox:

<Codesandbox id="nn2m7" />


================================================
FILE: docs/tutorials/loading-textures.mdx
================================================
---
title: 'Loading Textures'
description: Let's load some fancy textures.
nav: 16
---

> All textures used in this chapter were downloaded from [cc0textures](https://cc0textures.com/).

## Using `TextureLoader` and `useLoader`

To load the textures we will use the `TextureLoader` from three.js in combination with `useLoader` that will allow us to pass the location of the texture and get the map back.

It's better to explain with code, let's say you downloaded [this texture](https://cc0textures.com/view?id=PavingStones092) and placed it in the public folder of your site, to get the color map from it you could do:

```js
const colorMap = useLoader(TextureLoader, 'PavingStones092_1K_Color.jpg')
```

Let's then with this information create a small scene where we can use this texture:

```jsx
import { Suspense } from 'react'
import { Canvas, useLoader } from '@react-three/fiber'
import { TextureLoader } from 'three'

function Scene() {
  const colorMap = useLoader(TextureLoader, 'PavingStones092_1K_Color.jpg')
  return (
    <>
      <ambientLight intensity={0.2} />
      <directionalLight />
      <mesh>
        <sphereGeometry args={[1, 32, 32]} />
        <meshStandardMaterial />
      </mesh>
    </>
  )
}

export default function App() {
  return (
    <Canvas>
      <Suspense fallback={null}>
        <Scene />
      </Suspense>
    </Canvas>
  )
}
```

If everything went according to plan, you should now be able to apply this texture to the sphere like so:

```jsx
<meshStandardMaterial map={colorMap} />
```

Awesome! That works but we have a lot more textures to import and do we have to create a different useLoader for each of them?

That's the great part! You don't, the second argument is an array where you can pass all the textures you have and the maps will be returned and ready to use:

```js
const [colorMap, displacementMap, normalMap, roughnessMap, aoMap] = useLoader(TextureLoader, [
  'PavingStones092_1K_Color.jpg',
  'PavingStones092_1K_Displacement.jpg',
  'PavingStones092_1K_Normal.jpg',
  'PavingStones092_1K_Roughness.jpg',
  'PavingStones092_1K_AmbientOcclusion.jpg',
])
```

Now we can place them in our mesh like so:

```jsx
<meshStandardMaterial
  map={colorMap}
  displacementMap={displacementMap}
  normalMap={normalMap}
  roughnessMap={roughnessMap}
  aoMap={aoMap}
/>
```

The displacement will probably be too much, usually setting it to 0.2 will make it look good. Our final code would look something like:

```jsx
function Scene() {
  const [colorMap, displacementMap, normalMap, roughnessMap, aoMap] = useLoader(TextureLoader, [
    'PavingStones092_1K_Color.jpg',
    'PavingStones092_1K_Displacement.jpg',
    'PavingStones092_1K_Normal.jpg',
    'PavingStones092_1K_Roughness.jpg',
    'PavingStones092_1K_AmbientOcclusion.jpg',
  ])
  return (
    <mesh>
      {/* Width and height segments for displacementMap */}
      <sphereGeometry args={[1, 100, 100]} />
      <meshStandardMaterial
        displacementScale={0.2}
        map={colorMap}
        displacementMap={displacementMap}
        normalMap={normalMap}
        roughnessMap={roughnessMap}
        aoMap={aoMap}
      />
    </mesh>
  )
}
```

## Using `useTexture`

Another way to import these is using `useTexture` from [`@react-three/drei`](https://github.com/pmndrs/drei), that will make it slightly easier and there is no need to import the `TextureLoader`, our code would look like:

```js
import { useTexture } from "@react-three/drei"

...

const [colorMap, displacementMap, normalMap, roughnessMap, aoMap] = useTexture([
  'PavingStones092_1K_Color.jpg',
  'PavingStones092_1K_Displacement.jpg',
  'PavingStones092_1K_Normal.jpg',
  'PavingStones092_1K_Roughness.jpg',
  'PavingStones092_1K_AmbientOcclusion.jpg',
])
```

You can also use object-notation which is the most convenient:

```jsx
const props = useTexture({
  map: 'PavingStones092_1K_Color.jpg',
  displacementMap: 'PavingStones092_1K_Displacement.jpg',
  normalMap: 'PavingStones092_1K_Normal.jpg',
  roughnessMap: 'PavingStones092_1K_Roughness.jpg',
  aoMap: 'PavingStones092_1K_AmbientOcclusion.jpg',
})

return (
  <mesh>
    <sphereGeometry args={[1, 32, 32]} />
    <meshStandardMaterial {...props} />
  </mesh>
)
```

You can play with the sandbox and see how it looks:

<Codesandbox id="rusfd" />


================================================
FILE: docs/tutorials/v9-migration-guide.mdx
================================================
---
title: 'v9 Migration Guide'
description: Changes and new features with v9 and React 19
nav: 13
---

This is a compatibility release for React 19, which brings further performance, stability, and type improvements. You can check out the React 19 changelog [here](https://react.dev/blog/2024/04/25/react-19).

We would like to express our gratitude to the community for their continued support, as well as to all our contributors, including the React team at Meta and Vercel, for ensuring this upgrade went smoothly. 🎉

> [!WARNING]  
> This release contains breaking changes when using Strict Mode, which can highlight bugs during development. See [StrictMode](#strictmode).

## Features

### useLoader Accepts Loader Instance

`useLoader` now supports re-use of external loader instances for more controlled pooling and setup.

```jsx
import { GLTFLoader } from 'three/addons'
import { useLoader } from '@react-three/fiber'

function Model() {
  const gltf = useLoader(GLTFLoader, '/path/to/model.glb')
  // ...
}

// or,

const loader = new GLTFLoader()
function Model() {
  const gltf = useLoader(loader, '/path/to/model.glb')
  // ...
}
```

### Factory extend Signature

`extend` can now produce a component when a three.js class is passed to it individually instead of a catalog of named classes. This is backwards compatible and reduces TypeScript boilerplate and JSX collisions. We recommend libraries migrate to this signature so internal components don't clash with user-land declarations.

```tsx
import { OrbitControls } from 'three/addons'
import { type ThreeElement, type ThreeElements } from '@react-three/fiber'

declare module '@react-three/fiber' {
  interface ThreeElements {
    orbitControls: ThreeElement<typeof OrbitControls>
  }
}

extend({ OrbitControls })

<orbitControls args={[camera, gl.domElement]}>

// or,

const Controls = extend(OrbitControls)
<Controls args={[camera, gl.domElement]} />
```

### Async GL prop

The Canvas GL prop accepts constructor parameters, properties, or a renderer instance via a callback. The callback now passes constructor parameters instead of just a canvas reference.

```diff
<Canvas
  gl={{ reverseDepthBuffer: true }}
- gl={(canvas) => new WebGLRenderer({ canvas })}
+ gl={(props) => new WebGLRenderer(props)}
>
```

Further, a callback passed to GL can now return a promise for async constructors like `WebGPURenderer` (see [WebGPU](#webgpu)).

```tsx
<Canvas
  gl={async (props) => {
    // ...
    return renderer
  }}
>
````

## WebGPU

Recent Three.js now includes a WebGPU renderer. While still a work in progress and not fully backward-compatible with all of Three's features, the renderer requires an async initialization method. R3F streamlines this by allowing the gl prop to return a promise.

```tsx
import * as THREE from 'three/webgpu'
import * as TSL from 'three/tsl'
import { Canvas, extend, useFrame, useThree } from '@react-three/fiber'

declare module '@react-three/fiber' {
  interface ThreeElements extends ThreeToJSXElements<typeof THREE> {}
}

extend(THREE as any)

export default () => (
  <Canvas
    gl={async (props) => {
      const renderer = new THREE.WebGPURenderer(props as any)
      await renderer.init()
      return renderer
    }}>
      <mesh>
        <meshBasicNodeMaterial />
        <boxGeometry />
      </mesh>
  </Canvas>
)
```

## Fixes

### Color Management of Textures

Automatic sRGB conversion of texture props has been removed. Color textures are now handled automatically for built-in materials, aligning with vanilla Three.js behavior. This prevents issues where data textures (e.g., normals or displacement) become corrupted or non-linear. For custom materials or shaders, annotate color textures with `texture.colorSpace = THREE.SRGBColorSpace` or `texture-colorSpace={THREE.SRGBColorSpace}` in JSX.

For more details, see https://threejs.org/docs/#manual/en/introduction/Color-management.

### Suspense and Side-Effects

The handling of Suspense and fallback content has improved in React and R3F. Side-effects like attach and constructor effects (e.g., controls adding event listeners) no longer fire repeatedly without proper cleanup during suspension.

```jsx
import { ThreeElement, useThree } from '@react-three/fiber'
import { OrbitControls } from 'three/addons'

declare module '@react-three/fiber' {
  interface ThreeElements {
    OrbitControls: ThreeElement<typeof OrbitControls>
  }
}

extend({ OrbitControls })

function Controls() {
  const camera = useThree((state) => state.camera)
  const gl = useThree((state) => state.gl)

  // Will only initialize when tree is connected to screen
  return <orbitControls args={[camera, gl.domElement]}>
}

<Suspense>
  <Controls />
  <AsyncComponent />
</Suspense>
```

### Swapping with args and primitives

Swapping elements when changing the `args` or primitive `object` prop has been improved for structured children like arrays or iterators (React supports both, including async iterators). Previously, primitives sharing an object could update out of order or be removed from the scene along with their children.

See: https://github.com/pmndrs/react-three-fiber/pull/3272

## TypeScript Changes

### Props renamed to CanvasProps

Canvas `Props` is now called `CanvasProps` for clarity. These were aliased in v8 for forward compatibility, but `Props` is removed with v9.

```diff
-function Canvas(props: Props)
+function Canvas(props: CanvasProps)
```

### Dynamic JSX Types

Since R3F's creation, JSX types had to be maintained in accordance with additions to three core API. Although missing or future types could be ignored or resilient for forward and backwards compatibility, this was a major maintenance burden for us and those extending three. Furthermore, libraries which wrap or bind to the known catalog of elements (e.g. React Spring `<animated.mesh />`) had no way of knowing which elements belonged to a renderer.

Since v8, we've added a catalog of known elements to a `ThreeElements` interface, and with v9 automatically map three API to JSX types. As types are now dynamically mapped, hardcoded exports like `MeshProps` have been removed, and can be accessed as `ThreeElements['mesh']`. Helper types like `Color` or `Vector3` remain to reflect the JSX `MathType` API for shorthand expression.

```diff
-import { MeshProps } from '@react-three/fiber'
-type Props = MeshProps

+import { ThreeElements } from '@react-three/fiber'
+type Props = ThreeElements['mesh']
```

### Node Helpers

Specialized `Node` type helpers for extending JSX (`Node`, `Object3DNode`, `BufferGeometryNode`, `MaterialNode`, `LightNode`) are removed and combined into 'ThreeElement', which accepts a single type representing the extended element instance.

```tsx
import { type ThreeElement } from '@react-three/fiber'

declare module '@react-three/fiber' {
  interface ThreeElements {
    customElement: ThreeElement<typeof CustomElement>
  }
}

extend({ CustomElement })
```

### ThreeElements

`ThreeElements` was added as an interface since v8.1.0 and is the current way of declaring or accessing JSX within R3F since React's depreciation of `global` JSX (see https://react.dev/blog/2024/04/25/react-19-upgrade-guide#the-jsx-namespace-in-typescript). All JSX types belonging to R3F are accessible from `ThreeElements`.

```diff
-import { type Node } from '@react-three/fiber'
-
-declare global {
-  namespace JSX {
-    interface IntrinsicElements {
-      customElement: Node<CustomElement, typeof CustomElement>
-    }
-  }
-}
-
-extend({ CustomElement })

+import { type ThreeElement } from '@react-three/fiber'
+
+declare module '@react-three/fiber' {
+  interface ThreeElements {
+    customElement: ThreeElement<typeof CustomElement>
+  }
+}
+
+extend({ CustomElement })
```

## Testing

### StrictMode

`StrictMode` is now correctly inherited from a parent renderer like react-dom. Previously, `<StrictMode />` mounted in another root such as react-dom would not affect the R3F canvas, so it had to be redeclared within the canvas as well.

```diff
<StrictMode>
  <Canvas>
-    <StrictMode>
-      // ...
-    </StrictMode>
+    // ...
  </Canvas>
</StrictMode>
```

Keep in mind, this change may affect the behavior of your application. If you encounter anything that worked before and fails now, profile it first in dev and then production. If it works in prod then strict mode has flushed out a side-effect in your code.

### Act

`act` is now exported from React itself and can be used for all renderers. It will return the contents of a passed async callback like before and recursively flush async effects to synchronously test React output.

```tsx
import { act } from 'react'
import { createRoot } from '@react-three/fiber'

const store = await act(async () => createRoot(canvas).render(<App />))
console.log(store.getState())
```


================================================
FILE: example/.gitignore
================================================
node_modules
.DS_Store
dist
dist-ssr
*.local


================================================
FILE: example/CHANGELOG.md
================================================
# example

## 1.1.0

### Minor Changes

- 85c80e70: eventsource and eventprefix on the canvas component

## 1.0.0

### Major Changes

- 385ba9c: v8 major, react-18 compat
- 04c07b8: v8 major, react-18 compat

## 1.0.0-beta.0

### Major Changes

- 385ba9c: v8 major, react-18 compat


================================================
FILE: example/index.html
================================================
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="favicon.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>react-three-fiber example</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/index.tsx"></script>
  </body>
</html>


================================================
FILE: example/package.json
================================================
{
  "name": "example",
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "serve": "vite preview"
  },
  "dependencies": {
    "@react-three/drei": "^9.105.5",
    "@use-gesture/react": "latest",
    "react": "19.2.0",
    "react-dom": "19.2.0",
    "react-use-refs": "^1.0.1",
    "three": "^0.172.0",
    "three-stdlib": "^2.35.16",
    "use-error-boundary": "^2.0.6",
    "wouter": "^2.12.1",
    "zustand": "^4.4.7"
  },
  "devDependencies": {
    "@types/three": "^0.172.0",
    "@types/react": "^19.2.7",
    "@types/react-dom": "^19.2.3",
    "@vitejs/plugin-react-refresh": "^1.3.6",
    "@vitejs/plugin-react": "^4.2.1",
    "typescript": "^5.3.3",
    "vite": "^5.2.10"
  }
}


================================================
FILE: example/public/apple.gltf
================================================
{
  "extensionsUsed": ["KHR_materials_unlit", "KHR_draco_mesh_compression"],
  "asset": { "generator": "UniGLTF-1.27", "version": "2.0" },
  "buffers": [
    {
      "name": "buffer",
      "byteLength": 1696,
      "uri": "data:application/octet-stream;base64,RFJBQ08CAgEBAAAAN1oCWQcCCgotJQMa/9dWpdX0i6qqtp6qKlXVt6mqatUa1WoVagEBARCJEgr00rCEsS4YXjNuNiYK7mJjgYkSCvTSsISxLhheM242JgruYmOBA/8AAQABAAEBAAEACQMAAAIBAQkDAAEDAQMJAgACAgQBAQAMFykBfQMhD00QIRbRBRF00sExHVy3tfP6lKXEK4h/paitf5YCMTeQkpZLWwBQB5LoY4wEQHjuyzQ/AIBnAKy2DAC65AoAHBYCgKcLZQagSi8AGjcF4DIu5QIwB4DGvAGIBQAAtsRP0/zqCIA/2AAImgKAeXUAcBkRAAAAAGBEAFDW+wCeAViLFsB2BoD8PAQAGo4BkmMA8JQhKgGQFSeAAPUAQKXEM0CfdV0BZAUKAPAMINpJAFzbUAE8UwFAAwAIAsj6BgDgGSB6EgBXN29A/A0AAACwFgC6DA4AABJkBHR3z1k+Ywp1YtrjsQIDPbiACVUDLRxDAAAAAAD/BwAAAAAAAAAAAABxAcm9cQFJPgsGAwEBBf8B4SERD8UD////600LO9ceXZzLlIO59ofGhlg2nkMijGIoHQM8NcEonHpn+D+ZOGmUM6hkykciQAH89m3Y48JQPF4WzjCRk8+B/wAAAH8AAAD/AphLCAUBAQALA00LwRvVAg9NAxEHxQsoDbzuCkBZ7AvEul4PskkInEwKkfbQSqFNY8Ru2lgRkvuXrW2dqIJNgAnj+6GqiIfY5QYAOgi2UaiqooRd/OmeKWCi/1GrgYKCFxK3ZyJrQckhUIoAXAyqVSCAx0YQSsqecO7SKkQ+50moZMK6RFmqaisoKAqihGGYMKg6KpWRz4Y/obT1pLsmyAvQnomsBSWHQCkCcPEHq+inVYFqFQjgsRGEUlLjOLpNmx6CIwBPKnwVqxGEUrJbGO/SArlLqwBYAAAAAQJiRgAAAAD/AwAA3Ex3wMDQpcBIuglBCgAAAERSQUNPAgIBAQAAAAgKAgoAAANfqxT/ARFiBNT4SIFiBNT4SIED/wABAAEAAQEAAQAJAwAAAgEBCQMAAQMBAwkCAAICAQEBAAwDAQgbARADASgEAFQ3gYQLgMEHB4CCAwAABgeAAPi6GACA+wCg4PgFMAYAAAAA/wcAAAAAAABdixY+lXEdvAAmMz0LBgMBAQQCmTlpBgWCrc9Ugf8AAAB/AAAA/wJZQQgFAQEACgM1E80MDzUDzQwBEAgoVyk70ATJgsQBYcPKsDEL4KCY35eAK8QAYYArYYAm3wAKAAAAAQKgQAAAAAD/AwAAkLTBvnpe0MDDefxACgAAAERSQUNPAgIBAQAAABgaAhoEAhYMAxQBCt/evV2zNdmadi3/ARH/AtdB/wLXQQP/AAEAAAABAAABAAkDAAACAQEJAwABAwEDCQIAAgIBAQEADCOtAq0SqSoGBSopT++AAODrYgHQxzkB0A/xAPD1xgCgZwsAYJhWAABNywB4PxQACB0AAOjtcgAg1kMAjFM/ACgcAACC+SEAtiEVAN8VCQAYbQUA6NQzANBzBQCobQnAmZYBoPYFAIDQAQAAnQoCAAAAAP8HAAAAAAAAjW2IPKuzpb2rsyU+CwYDAQEDAQFAAQD/AAAAfwAAAP8CoUEIBQEBAAsDVQ1ZLRtVBQad5eYTf4HFer0TkCagqCEiAooIoiIWAAAAAQJnQQAAAAD/AwAAjt1LwJLVkMCO3ctACgBEUkFDTwICAQEAAAAIBAIEAAAC7wv/ASL/ASL/ASID/wABAAAAAQAAAQAJAwAAAgEBCQMAAQMBAwkCAAICAQEBAAwjARgBCAEgBACKJoIAAMAxAETNAQAs92YA2DQGwI3HDwBRbwBAmsYA2DgGAAAAAP8HAAAAAAAAMHuOPRx0y7wcdEs9CwYDAQEDAQFAAQD/AAAAfwAAAP8CiEAIBQEBAAsDARABEBsBIAQAHBiEjkntQNTo/Bw3EDUCBAAAAAECQEAAAAAA/wMAANxPer/qOyPA3E/6PwpEUkFDTwICAQEAAAAEAgICAAABL/8BEf8BEQEBEAP/AAEAAAABAQABAAkDAAACAQEJAwABAwEDCQIAAgIBAQEADAMBIAEQHwEQAwAUkPA/AAIAAgAAAAD/BwAAAAAAAF2LFj5BVrC7QVYwPAsGAwEBAwEBQAEA/wAAAH8AAAD/AkRACAUBAQALHwEgAwEgAwDYkL4G0KsAxoLFAsYBBZIBAgAAAAEBIAAAAAD/AwAAkLTBvrtR0MC0aNw/Cg=="
    }
  ],
  "bufferViews": [
    { "buffer": 0, "byteOffset": 0, "byteLength": 733 },
    { "buffer": 0, "byteOffset": 736, "byteLength": 249 },
    { "buffer": 0, "byteOffset": 988, "byteLength": 303 },
    { "buffer": 0, "byteOffset": 1292, "byteLength": 216 },
    { "buffer": 0, "byteOffset": 1508, "byteLength": 188 }
  ],
  "accessors": [
    { "type": "SCALAR", "componentType": 5125, "count": 270, "min": [0], "max": [135] },
    {
      "type": "VEC3",
      "componentType": 5126,
      "count": 136,
      "max": [0.09829112117938082, 0.15707400633348856, 0.09824317429100063],
      "min": [-0.00009589377676037153, -0.00009589377676037153, -0.09824317429100064]
    },
    {
      "type": "VEC3",
      "componentType": 5126,
      "count": 136,
      "min": [-1.007843137254902, -1.007843137254902, -0.9083239440824471],
      "max": [0.9058823529411764, 1.007843137254902, 0.9112838990548078]
    },
    {
      "type": "VEC2",
      "componentType": 5126,
      "count": 136,
      "min": [-3.872480570978666, -5.190146624750639],
      "max": [3.868810683984095, 3.4346615669198286]
    },
    { "type": "SCALAR", "componentType": 5125, "count": 30, "min": [0], "max": [19] },
    {
      "type": "VEC3",
      "componentType": 5126,
      "count": 20,
      "max": [0.00963633247975553, 0.19077478181780055, 0.009620332180030559],
      "min": [-0.000021366590864202948, 0.1469946371370487, -0.009630966188616297]
    },
    {
      "type": "VEC3",
      "componentType": 5126,
      "count": 20,
      "min": [-1.0078249400737238, -0.10404930024170408, -1.0031846588733149],
      "max": [1.003184658873315, 1.007092190227088, 1.0000000000000002]
    },
    {
      "type": "VEC2",
      "componentType": 5126,
      "count": 20,
      "min": [-0.38604318408089766, -6.51924526003915],
      "max": [0.3852044690039851, 1.386043184080898]
    },
    { "type": "SCALAR", "componentType": 5125, "count": 78, "min": [0], "max": [23] },
    {
      "type": "VEC3",
      "componentType": 5126,
      "count": 24,
      "max": [0.00007905138808456816, 0.1404482741236439, 0.08098814709264007],
      "min": [-0.00007905138808456816, 0.016574748995125614, -0.08098814709264009]
    },
    {
      "type": "VEC3",
      "componentType": 5126,
      "count": 24,
      "min": [-1.003921568627451, -0.00392156862745098, -0.00392156862745098],
      "max": [-0.996078431372549, 0.00392156862745098, 0.00392156862745098]
    },
    {
      "type": "VEC2",
      "componentType": 5126,
      "count": 24,
      "min": [-3.191625186308621, -4.532298156126736],
      "max": [3.191625186308621, 0.35010993375806176]
    },
    { "type": "SCALAR", "componentType": 5125, "count": 12, "min": [0], "max": [7] },
    {
      "type": "VEC3",
      "componentType": 5126,
      "count": 8,
      "max": [0.00002426540176054298, 0.09019649050616613, 0.024859904103676285],
      "min": [-0.00002426540176054298, 0.06954663360794405, -0.024859904103676285]
    },
    {
      "type": "VEC3",
      "componentType": 5126,
      "count": 8,
      "min": [-1.003921568627451, -0.00392156862745098, -0.00392156862745098],
      "max": [-0.996078431372549, 0.00392156862745098, 0.00392156862745098]
    },
    {
      "type": "VEC2",
      "componentType": 5126,
      "count": 8,
      "min": [-0.9796926527778425, -2.552443459586314],
      "max": [0.9796926527778425, -1.7361922152231166]
    },
    { "type": "SCALAR", "componentType": 5125, "count": 6, "min": [0], "max": [5] },
    {
      "type": "VEC3",
      "componentType": 5126,
      "count": 6,
      "max": [0.005384004925540091, 0.147021261545223, 0.00538663383419514],
      "min": [-0.000005257817310097745, 0.1470107459106028, -0.00538663383419514]
    },
    {
      "type": "VEC3",
      "componentType": 5126,
      "count": 6,
      "min": [-0.00392156862745098, 0.996078431372549, -0.00392156862745098],
      "max": [0.00392156862745098, 1.003921568627451, 0.00392156862745098]
    },
    {
      "type": "VEC2",
      "componentType": 5126,
      "count": 6,
      "min": [-0.38001393852345755, -6.511660094834492],
      "max": [0.21416659508982017, -4.786348347090556]
    }
  ],
  "materials": [
    {
      "name": "red",
      "pbrMetallicRoughness": {
        "baseColorFactor": [0.9098039, 0.333333343, 0.3254902, 1],
        "metallicFactor": 1,
        "roughnessFactor": 1
      },
      "doubleSided": false,
      "alphaMode": "OPAQUE",
      "emissiveFactor": [0, 0, 0]
    },
    {
      "name": "brown",
      "pbrMetallicRoughness": {
        "baseColorFactor": [0.827451, 0.5647059, 0.403921574, 1],
        "metallicFactor": 1,
        "roughnessFactor": 1
      },
      "doubleSided": false,
      "alphaMode": "OPAQUE",
      "emissiveFactor": [0, 0, 0]
    },
    {
      "name": "brownLight",
      "pbrMetallicRoughness": {
        "baseColorFactor": [0.9764706, 0.772549033, 0.549019635, 1],
        "metallicFactor": 1,
        "roughnessFactor": 1
      },
      "doubleSided": false,
      "alphaMode": "OPAQUE",
      "emissiveFactor": [0, 0, 0]
    },
    {
      "name": "brownDark",
      "pbrMetallicRoughness": {
        "baseColorFactor": [0.6392157, 0.3882353, 0.2784314, 1],
        "metallicFactor": 1,
        "roughnessFactor": 1
      },
      "doubleSided": false,
      "alphaMode": "OPAQUE",
      "emissiveFactor": [0, 0, 0]
    },
    {
      "name": "_defaultMat",
      "pbrMetallicRoughness": { "baseColorFactor": [1, 1, 1, 1], "metallicFactor": 1, "roughnessFactor": 1 },
      "doubleSided": false,
      "alphaMode": "OPAQUE",
      "emissiveFactor": [0, 0, 0]
    }
  ],
  "meshes": [
    {
      "name": "Mesh appleHalf",
      "primitives": [
        {
          "mode": 4,
          "indices": 0,
          "attributes": { "POSITION": 1, "NORMAL": 2, "TEXCOORD_0": 3 },
          "material": 0,
          "extensions": {
            "KHR_draco_mesh_compression": {
              "bufferView": 0,
              "attributes": { "POSITION": 0, "NORMAL": 1, "TEXCOORD_0": 2 }
            }
          }
        },
        {
          "mode": 4,
          "indices": 4,
          "attributes": { "POSITION": 5, "NORMAL": 6, "TEXCOORD_0": 7 },
          "material": 1,
          "extensions": {
            "KHR_draco_mesh_compression": {
              "bufferView": 1,
              "attributes": { "POSITION": 0, "NORMAL": 1, "TEXCOORD_0": 2 }
            }
          }
        },
        {
          "mode": 4,
          "indices": 8,
          "attributes": { "POSITION": 9, "NORMAL": 10, "TEXCOORD_0": 11 },
          "material": 2,
          "extensions": {
            "KHR_draco_mesh_compression": {
              "bufferView": 2,
              "attributes": { "POSITION": 0, "NORMAL": 1, "TEXCOORD_0": 2 }
            }
          }
        },
        {
          "mode": 4,
          "indices": 12,
          "attributes": { "POSITION": 13, "NORMAL": 14, "TEXCOORD_0": 15 },
          "material": 3,
          "extensions": {
            "KHR_draco_mesh_compression": {
              "bufferView": 3,
              "attributes": { "POSITION": 0, "NORMAL": 1, "TEXCOORD_0": 2 }
            }
          }
        },
        {
          "mode": 4,
          "indices": 16,
          "attributes": { "POSITION": 17, "NORMAL": 18, "TEXCOORD_0": 19 },
          "material": 4,
          "extensions": {
            "KHR_draco_mesh_compression": {
              "bufferView": 4,
              "attributes": { "POSITION": 0, "NORMAL": 1, "TEXCOORD_0": 2 }
            }
          }
        }
      ]
    }
  ],
  "nodes": [
    { "children": [1], "name": "tmpParent", "translation": [0, 0, 0], "rotation": [0, 0, 0, 1], "scale": [1, 1, 1] },
    { "name": "appleHalf", "translation": [0, 0, 0], "rotation": [0, 0, 0, 1], "scale": [1, 1, 1], "mesh": 0 }
  ],
  "scenes": [{ "nodes": [1] }],
  "scene": 0,
  "extensionsRequired": ["KHR_draco_mesh_compression"]
}


================================================
FILE: example/public/bottle.gltf
================================================
{
  "extensionsUsed": ["KHR_materials_unlit", "KHR_draco_mesh_compression"],
  "asset": { "generator": "UniGLTF-1.27", "version": "2.0" },
  "buffers": [
    {
      "name": "buffer",
      "byteLength": 1004,
      "uri": "data:application/octet-stream;base64,RFJBQ08CAgEBAAAAJDQCMwMCGQ8ZCwMQ79auW9NWVfEva0vXddGiAIACAHFkC4gpS5BuMmCDL1WAZAuIKUuQbjJggy9VgAP/AAEAAQABAQABAAkDAAACAQEJAwABAwEDCQIAAgIEAQEADAPJARPlCFUVHQeRE1UFDCNY15ilc8hSzX+8Xw48sQv+QBEc5E7EKhDg+xP/AYACUHwHAPgEAPgHADgKABwFAb5B8R8AngAOQQEoqgCQFRQAQBAAHFIAAPALsHPUBgQCYCUAELwBwMUCAIAbAAAAgDNtALBYAF1+ucTMJ4DFJwBGEgEAABcBNBEFAKgBwG0AAA63BNHgA4EaWQWKsQfEQgarA7/KggRAA0CIgAAAAAD/BwAA5dK4vQAAAADnD6C9uDkFPwsGAwEBBP8B4Sy5Cf///+9pCSHsJJGNFX1HBAI97/XOnNfjTSqhdGtLEH5V8IWKRsmHS4D/AAAAfwAAAP8CGEgIBQEBAAsDKQi9GUEBC+EBJQM5F6Ac4zcnvBmY1hE3kfWoH7ZVdyCtMA/1+1Uf6eVPgI6JnaMhYg6H8Bqi8K6h6DuH8BoiKQHAa4jCu4aigP+j6Ugk6pKmi9QCSJoOUQsgabpILYCk6SI8mo6oGXjhOhIYrl/ArpjyukrsIqSzxy6qdSXxYSOKe5EduyBeiJgSOyIRQErsiEQAKbGDDOB67CJK6nb0IiIUQEcvqnj0ggA0AAAAAQKCQwAAAAD/AwAAXsAvwPpQmcGLV7RBCgBEUkFDTwICAQEAAAAeKAIoAQEnCwEMX7tu7fK1bakWVS0t/wEiiAnoNmQvEM0Sa4CICeg2ZC8QzRJrgAP/AAEAAQABAQABAAkDAAACAQEJAwABAwEDCQIAAgIEAQEADAOJCA/NDEUEAzUTaQbNDAuvfqTVRnKEpXCJbjoGgLSQIGoADCfUlBoBPisAnj0CAJ8B8CwSQg0A4oQaACTQawXgAwkApGPUlgEAADxtAdgJ4DGAtQAA3AKwE7gA8LT1mCfwANgJ3AHAswPqHwA6wP4BAAqzA5uFTBxlBg5hgZ55gAAAAAAAAP8HAAAA1aq9mwUaPuPxk72E69E+CwYDAQEEAkE4wQcL0OIw5NWXSnUq+5b/AAAAfwAAAP8C3UQIBQEBAAsDhQ9VFekCA/gD+K0K8QG1CRbt1EYh/80XV9wKBm+OKvgrGjszv/+VFP3JQJIgRUpOlCQ6kZIUJYlyEABFSaIwUZLoREpSlCTKENIA2oD44ICKAmDin6IAoKIAkAioKAAm/ikKACoKvvkVEIguxiIrJgAAAAECf0IAAAAA/wMAAF0t0r/6gajBJXy6QQo="
    }
  ],
  "bufferViews": [
    { "buffer": 0, "byteOffset": 0, "byteLength": 571 },
    { "buffer": 0, "byteOffset": 572, "byteLength": 432 }
  ],
  "accessors": [
    { "type": "SCALAR", "componentType": 5125, "count": 156, "min": [0], "max": [101] },
    {
      "type": "VEC3",
      "componentType": 5126,
      "count": 102,
      "max": [0.09051262757649467, 0.5206661997740596, 0.07845129908718129],
      "min": [-0.09050023093870575, -0.00025423154285842753, -0.07840956285646851]
    },
    {
      "type": "VEC3",
      "componentType": 5126,
      "count": 102,
      "min": [-0.8701851585332085, -1.0078100779477288, -1.0035950162831475],
      "max": [0.8714622238103082, 0.38238379674799305, 1.0035950162831475]
    },
    {
      "type": "VEC2",
      "componentType": 5126,
      "count": 102,
      "min": [-2.768152080789456, -19.186575256601223],
      "max": [2.762863699408687, 3.400242172494778]
    },
    { "type": "SCALAR", "componentType": 5125, "count": 120, "min": [0], "max": [65] },
    {
      "type": "VEC3",
      "componentType": 5126,
      "count": 66,
      "max": [0.0836303700134704, 0.5606122827917177, 0.07237291420137934],
      "min": [-0.0836143708616335, 0.15021171506346873, -0.07243899915514775]
    },
    {
      "type": "VEC3",
      "componentType": 5126,
      "count": 66,
      "min": [-0.8738685851003609, -1.007843137254902, -1.007843137254902],
      "max": [0.8751510227427763, 1.007843137254902, 1.007843137254902]
    },
    {
      "type": "VEC2",
      "componentType": 5126,
      "count": 66,
      "min": [-1.6647959047981256, -21.086251645726776],
      "max": [1.6620370837134235, 2.2699388558097837]
    }
  ],
  "materials": [
    {
      "name": "brownDark",
      "pbrMetallicRoughness": {
        "baseColorFactor": [0.6392157, 0.3882353, 0.2784314, 1],
        "metallicFactor": 1,
        "roughnessFactor": 1
      },
      "doubleSided": false,
      "alphaMode": "OPAQUE",
      "emissiveFactor": [0, 0, 0]
    },
    {
      "name": "red",
      "pbrMetallicRoughness": {
        "baseColorFactor": [0.9098039, 0.333333343, 0.3254902, 1],
        "metallicFactor": 1,
        "roughnessFactor": 1
      },
      "doubleSided": false,
      "alphaMode": "OPAQUE",
      "emissiveFactor": [0, 0, 0]
    }
  ],
  "meshes": [
    {
      "name": "Mesh sodaBottle",
      "primitives": [
        {
          "mode": 4,
          "indices": 0,
          "attributes": { "POSITION": 1, "NORMAL": 2, "TEXCOORD_0": 3 },
          "material": 0,
          "extensions": {
            "KHR_draco_mesh_compression": {
              "bufferView": 0,
              "attributes": { "POSITION": 0, "NORMAL": 1, "TEXCOORD_0": 2 }
            }
          }
        },
        {
          "mode": 4,
          "indices": 4,
          "attributes": { "POSITION": 5, "NORMAL": 6, "TEXCOORD_0": 7 },
          "material": 1,
          "extensions": {
            "KHR_draco_mesh_compression": {
              "bufferView": 1,
              "attributes": { "POSITION": 0, "NORMAL": 1, "TEXCOORD_0": 2 }
            }
          }
        }
      ]
    }
  ],
  "nodes": [
    { "children": [1], "name": "tmpParent", "translation": [0, 0, 0], "rotation": [0, 0, 0, 1], "scale": [1, 1, 1] },
    { "name": "sodaBottle", "translation": [0, 0, 0], "rotation": [0, 0, 0, 1], "scale": [1, 1, 1], "mesh": 0 }
  ],
  "scenes": [{ "nodes": [1] }],
  "scene": 0,
  "extensionsRequired": ["KHR_draco_mesh_compression"]
}


================================================
FILE: example/public/farm.gltf
================================================
{
  "asset": { "generator": "Khronos glTF Blender I/O v1.5.17", "version": "2.0" },
  "scene": 0,
  "scenes": [{ "name": "Scene", "nodes": [0, 1, 2, 3, 4, 5, 6, 7, 8] }],
  "nodes": [
    {
      "mesh": 0,
      "name": "Circle",
      "scale": [3.7607693672180176, 3.7607693672180176, 3.7607693672180176],
      "translation": [0.47165822982788086, 0, -0.6066201329231262],
      "rotation": [0, 0, 0, 1]
    },
    {
      "mesh": 1,
      "name": "WindMill.001",
      "scale": [0.4821113348007202, 0.4821113348007202, 0.4821113348007202],
      "translation": [1.263749599456787, 1.900821566581726, 0.1711728870868683],
      "rotation": [0, 0, 0, 1]
    },
    {
      "mesh": 2,
      "name": "Fence_White.013",
      "rotation": [0, 0.7071068286895752, 0, 0.7071068286895752],
      "scale": [0.09888678789138794, 0.09888678789138794, 0.09888678789138794],
      "translation": [1.3952089548110962, -0.005745698232203722, -2.4713940620422363]
    },
    {
      "mesh": 3,
      "name": "Wooden Box",
      "scale": [0.4007795751094818, 0.4007795751094818, 0.4007795751094818],
      "translation": [0.19056254625320435, 0.05061200261116028, 0.21082305908203125],
      "rotation": [0, 0, 0, 1]
    },
    {
      "mesh": 4,
      "name": "Plane",
      "scale": [0.0304397102445364, 0.0304397102445364, 0.0304397102445364],
      "translation": [-0.16933752596378326, 1.0484503507614136, 0.31743738055229187],
      "rotation": [0, 0, 0, 1]
    },
    {
      "mesh": 5,
      "name": "Well",
      "scale": [0.1421276479959488, 0.12818977236747742, 0.1421276479959488],
      "translation": [2.077780246734619, 0.22757045924663544, -0.05814981460571289],
      "rotation": [0, 0, 0, 1]
    },
    {
      "mesh": 6,
      "name": "Trees",
      "scale": [62.94956588745117, 62.94956588745117, 62.94956588745117],
      "translation": [0.37176066637039185, 0.14777842164039612, -1.3625603914260864],
      "rotation": [0, 0, 0, 1]
    },
    {
      "mesh": 7,
      "name": "Barn_01",
      "scale": [1.1511201858520508, 1.1511201858520508, 1.1511201858520508],
      "translation": [-0.17597436904907227, 0.4125245213508606, -0.17850732803344727],
      "rotation": [0, 0, 0, 1]
    },
    {
      "mesh": 8,
      "name": "WindMill",
      "scale": [0.4821113348007202, 0.4821113348007202, 0.4821113348007202],
      "translation": [1.2636184692382812, 1.564571499824524, 0.07810831815004349],
      "rotation": [0, 0, 0, 1]
    }
  ],
  "materials": [
    {
      "doubleSided": true,
      "name": "Farm_Pack_001",
      "pbrMetallicRoughness": {
        "baseColorTexture": { "index": 0, "texCoord": 0 },
        "metallicFactor": 0,
        "roughnessFactor": 0.9863636493682861,
        "baseColorFactor": [1, 1, 1, 1]
      },
      "emissiveFactor": [0, 0, 0],
      "alphaMode": "OPAQUE"
    },
    { "name": "default", "emissiveFactor": [0, 0, 0], "alphaMode": "OPAQUE", "doubleSided": false }
  ],
  "meshes": [
    {
      "name": "Circle",
      "primitives": [
        {
          "attributes": { "POSITION": 1, "NORMAL": 2 },
          "indices": 0,
          "mode": 4,
          "material": 1,
          "extensions": {
            "KHR_draco_mesh_compression": { "bufferView": 0, "attributes": { "POSITION": 0, "NORMAL": 1 } }
          }
        }
      ]
    },
    {
      "name": "Cube.029",
      "primitives": [
        {
          "attributes": { "POSITION": 4, "NORMAL": 5, "TEXCOORD_0": 6 },
          "indices": 3,
          "material": 0,
          "mode": 4,
          "extensions": {
            "KHR_draco_mesh_compression": {
              "bufferView": 1,
              "attributes": { "POSITION": 0, "NORMAL": 1, "TEXCOORD_0": 2 }
            }
          }
        }
      ]
    },
    {
      "name": "Cube.027",
      "primitives": [
        {
          "attributes": { "POSITION": 8, "NORMAL": 9, "TEXCOORD_0": 10 },
          "indices": 7,
          "material": 0,
          "mode": 4,
          "extensions": {
            "KHR_draco_mesh_compression": {
              "bufferView": 2,
              "attributes": { "POSITION": 0, "NORMAL": 1, "TEXCOORD_0": 2 }
            }
          }
        }
      ]
    },
    {
      "name": "Cube.005",
      "primitives": [
        {
          "attributes": { "POSITION": 12, "NORMAL": 13, "TEXCOORD_0": 14 },
          "indices": 11,
          "material": 0,
          "mode": 4,
          "extensions": {
            "KHR_draco_mesh_compression": {
              "bufferView": 3,
              "attributes": { "POSITION": 0, "NORMAL": 1, "TEXCOORD_0": 2 }
            }
          }
        }
      ]
    },
    {
      "name": "Plane.003",
      "primitives": [
        {
          "attributes": { "POSITION": 16, "NORMAL": 17, "TEXCOORD_0": 18 },
          "indices": 15,
          "material": 0,
          "mode": 4,
          "extensions": {
            "KHR_draco_mesh_compression": {
              "bufferView": 4,
              "attributes": { "POSITION": 0, "NORMAL": 1, "TEXCOORD_0": 2 }
            }
          }
        }
      ]
    },
    {
      "name": "Cylinder.001",
      "primitives": [
        {
          "attributes": { "POSITION": 20, "NORMAL": 21, "TEXCOORD_0": 22 },
          "indices": 19,
          "material": 0,
          "mode": 4,
          "extensions": {
            "KHR_draco_mesh_compression": {
              "bufferView": 5,
              "attributes": { "POSITION": 0, "NORMAL": 1, "TEXCOORD_0": 2 }
            }
          }
        }
      ]
    },
    {
      "name": "Plane.002",
      "primitives": [
        {
          "attributes": { "POSITION": 24, "NORMAL": 25, "TEXCOORD_0": 26 },
          "indices": 23,
          "material": 0,
          "mode": 4,
          "extensions": {
            "KHR_draco_mesh_compression": {
              "bufferView": 6,
              "attributes": { "POSITION": 0, "NORMAL": 1, "TEXCOORD_0": 2 }
            }
          }
        }
      ]
    },
    {
      "name": "Cube.002",
      "primitives": [
        {
          "attributes": { "POSITION": 28, "NORMAL": 29, "TEXCOORD_0": 30 },
          "indices": 27,
          "material": 0,
          "mode": 4,
          "extensions": {
            "KHR_draco_mesh_compression": {
              "bufferView": 7,
              "attributes": { "POSITION": 0, "NORMAL": 1, "TEXCOORD_0": 2 }
            }
          }
        }
      ]
    },
    {
      "name": "Cube",
      "primitives": [
        {
          "attributes": { "POSITION": 32, "NORMAL": 33, "TEXCOORD_0": 34 },
          "indices": 31,
          "material": 0,
          "mode": 4,
          "extensions": {
            "KHR_draco_mesh_compression": {
              "bufferView": 8,
              "attributes": { "POSITION": 0, "NORMAL": 1, "TEXCOORD_0": 2 }
            }
          }
        }
      ]
    }
  ],
  "textures": [{ "sampler": 0, "source": 0 }],
  "images": [{ "bufferView": 9, "mimeType": "image/jpeg", "name": "Diffuse_palette_noise" }],
  "accessors": [
    { "componentType": 5123, "count": 90, "type": "SCALAR" },
    {
      "componentType": 5126,
      "count": 32,
      "max": [0.8007816435886583, 0.0007816316677292907, 0.8007816435886583],
      "min": [-0.8007816435886582, -0.0007816316677292907, -0.8007816435886582],
      "type": "VEC3"
    },
    { "componentType": 5126, "count": 32, "type": "VEC3" },
    { "componentType": 5123, "count": 2076, "type": "SCALAR" },
    {
      "componentType": 5126,
      "count": 1322,
      "max": [0.8385503353814003, 0.8385502161721108, 0.05095415724360425],
      "min": [-0.8385503353814002, -0.8385504545906898, -0.1684030803183433],
      "type": "VEC3"
    },
    { "componentType": 5126, "count": 1322, "type": "VEC3" },
    { "componentType": 5126, "count": 1322, "type": "VEC2" },
    { "componentType": 5123, "count": 3060, "type": "SCALAR" },
    {
      "componentType": 5126,
      "count": 2000,
      "max": [0.10322994759563642, 1.6502795766030693, 2.2154936462014696],
      "min": [-39.21565765908245, -0.019190028951344522, -23.70925850441937],
      "type": "VEC3"
    },
    { "componentType": 5126, "count": 2000, "type": "VEC3" },
    { "componentType": 5126, "count": 2000, "type": "VEC2" },
    { "componentType": 5123, "count": 2292, "type": "SCALAR" },
    {
      "componentType": 5126,
      "count": 1694,
      "max": [0.18579399166423982, 0.1461265524262385, 0.14491311928442063],
      "min": [-0.14491329809835496, -0.1464015217702681, -0.9569067778270537],
      "type": "VEC3"
    },
    { "componentType": 5126, "count": 1694, "type": "VEC3" },
    { "componentType": 5126, "count": 1694, "type": "VEC2" },
    { "componentType": 5123, "count": 822, "type": "SCALAR" },
    {
      "componentType": 5126,
      "count": 624,
      "max": [4.812053583748002, 0.0031038604833231176, 0.24871478110741096],
      "min": [-5.050960444099564, -8.329193495399613, -0.3048462795087286],
      "type": "VEC3"
    },
    { "componentType": 5126, "count": 624, "type": "VEC3" },
    { "componentType": 5126, "count": 624, "type": "VEC2" },
    { "componentType": 5123, "count": 2370, "type": "SCALAR" },
    {
      "componentType": 5126,
      "count": 1493,
      "max": [1.5453098778265772, 1.1136803437164486, 0.867781436321033],
      "min": [-1.307572226612872, -1.810559492199725, -1.2458345700195492],
      "type": "VEC3"
    },
    { "componentType": 5126, "count": 1493, "type": "VEC3" },
    { "componentType": 5126, "count": 1493, "type": "VEC2" },
    { "componentType": 5123, "count": 768, "type": "SCALAR" },
    {
      "componentType": 5126,
      "count": 526,
      "max": [0.016896564860131663, 0.017585191424480177, 0.004240338889400612],
      "min": [-0.013106122959639949, -0.0036612214727812227, -0.01328685355582468],
      "type": "VEC3"
    },
    { "componentType": 5126, "count": 526, "type": "VEC3" },
    { "componentType": 5126, "count": 526, "type": "VEC2" },
    { "componentType": 5123, "count": 2226, "type": "SCALAR" },
    {
      "componentType": 5126,
      "count": 1338,
      "max": [0.32661417775988055, 0.3417208139262784, 0.47399327198237284],
      "min": [-0.3267274502870451, -0.36584189573496684, -0.44418025056094035],
      "type": "VEC3"
    },
    { "componentType": 5126, "count": 1338, "type": "VEC3" },
    { "componentType": 5126, "count": 1338, "type": "VEC2" },
    { "componentType": 5123, "count": 984, "type": "SCALAR" },
    {
      "componentType": 5126,
      "count": 638,
      "max": [0.7299346994293803, 0.958772202963706, 0.4743475615832653],
      "min": [-0.7322520222614961, -3.2909023966740327, -1.4544944968174653],
      "type": "VEC3"
    },
    { "componentType": 5126, "count": 638, "type": "VEC3" },
    { "componentType": 5126, "count": 638, "type": "VEC2" }
  ],
  "bufferViews": [
    { "buffer": 0, "byteOffset": 0, "byteLength": 251 },
    { "buffer": 0, "byteOffset": 252, "byteLength": 3939 },
    { "buffer": 0, "byteOffset": 4192, "byteLength": 2986 },
    { "buffer": 0, "byteOffset": 7180, "byteLength": 2912 },
    { "buffer": 0, "byteOffset": 10092, "byteLength": 1908 },
    { "buffer": 0, "byteOffset": 12000, "byteLength": 4237 },
    { "buffer": 0, "byteOffset": 16240, "byteLength": 1432 },
    { "buffer": 0, "byteOffset": 17672, "byteLength": 2925 },
    { "buffer": 0, "byteOffset": 20600, "byteLength": 1771 },
    { "buffer": 0, "byteOffset": 22372, "byteLength": 85348 }
  ],
  "samplers": [{ "magFilter": 9729, "minFilter": 9987, "wrapS": 10497, "wrapT": 10497 }],
  "buffers": [
    {
      "name": "buffer",
      "byteLength": 107720,
      "uri": "data:application/octet-stream;base64,RFJBQ08CAgEBAAAAIB4BHg4ADH/+5M+f5M+f5E+eAf8BEf8C+0EC/wABAAAAAQAJAwAAAgEBCQMAAQMBAQEADCMBDgEUAR4IAJmQq+3CF2n/BwAAHAaAk78A5mAQADBqHIDN5AUA810AwmIFAHA8AQBKOAcAeJIOgL8vAgAGOQOg8csBkFcsgF1vBABWTAiAE3QSAHMADIDOBQHwIscB4CxeAC7nBUDsVQAQRxQAAIV0AEAn5wAADCMAXHAzABzHHIB4HQdgsxMCAAUAAAAA/wcAAM3MTL8AAAAAzcxMv83MzD8LBgMBAQMBAUABAP8AAAB/AAAA/wI0QggARFJBQ08CAgEBAAAAjgO0BQKyBQgDLhb/BAcBSQezAV/7VCtVLVUtVS1VLVUtVS1VTyldl1JKUfhaVVpVWlVaVb5WlVaVVpVWla9VpVWlVaVV5WtVaVVpVWlV+VpVWlVaVVpVvlaVVpVWlVaVr1WlVaVVpVXla1VpVWlVaVX5WlVaVVpVWlW+VpVWlVaVVpWvVaVVpVWlVeVrVWlVaVVpVflaVVpVWlVaVb5WlVaVVpVWla9VpVWlVaVV5WtVaVVpVWlV+dOn1mctVeu6lCotpSgA5AOkCVFgegBR7eRTtgyllipOecnumPEzbfWKvZQliEjiZ0+M88MryilDwxUh0zQyC2kLk7PGrnC0kBATdYQ+vitjihwjhY/1fm1cow9NeGmiplSLGUUyETv6rjZgVj6tWcmTGJ8pogR/z8nA0azEVV1S3xO7IeOdPx9MocjPAvuDj376tnxcZOu9NGGY5K3KgdvuV3cebTT6b67vHDX+kc2p1PpY7Trcu05IorCaGYF3KtrUwNWFoygY0jOMNMIEN+fEA+1Yj4t6Z4rpgLz317RFCjIHFGodoBa1R6i5AWlOP68EQL8wfwt6cSHQUcm6HjHfXb5ZrcvtgCeFiPDrGEgD/wABAAEAAQEAAQAJAwAAAgEBCQMAAQMBAwkCAAICBAEBAAwDkRAdBgORBx0GUQWBBEUGMQTFAaEFngEBOVZZSid48yHgWTOXuWoIjBbXJ5iJCI2zpMiOdMx31/UTTEU8UOtSVr3JAMYX3x8MElOy1lZs5q9YDhldN/7R/LqkFIhhYvlfCZ3ihHaHFHL6jP1IId/zrkSMVLZI9EKjVOyKERdH/BJ5nJLf/XyY9bcJK2yv/9GODYurTgsVQgSWFIhhYrNA4tj4mgZLkxfIwvNwy253UaWfJuXOgM39v2GWYATAJCMMpNn5xXQcwEhAAB0wwtC7CwC2bwDQwsBFJEDAIgDQ3PzifQMA/RTgAjCAKQAgiQEAODe/wLkAwKoHAC4MBGACXEgCAM7OLzECBOPc+wXGRzDyyDsy2ra21bQkTsoKdQZBISi0lYjAWSMbB8JQ0aIDgF+LXwBWvK/Hq6g1u9Y2LBIodYWnEJRJAxHLKapg0hFIehsKAQjwWuY+YG9B5lenZE6hbptqQC2SFcrnoUkqcB0RYNyI8jaMqdYcyLTTXYCU/Nanh6zV9Om2rE+MdIVeDyVqIZECK5phzgVRX8YMQIjy7rIHPKMg5g+7ZLRob4tqB/aMFQjqhEooQGURMN+MYD4QRLVDAgjdb7YAhXnrj8Rca9bsbV2gz1wh5Akl1kJwoYpi2BEFsZ7QGwAgBPwSeABQCmBuU0sGAPs2qPZnXFgBgFUogOjnE0wAAGwo5AcQQDVgAhj/BxYANAf/1YhrAbi+jf2UiysAWKHAGkDNKIJiwBTAOkgAAABw+IQ9ABqFMceLJKtFextVo1QSrBCEOqESwqKNIIs3IsgGDFLdiAAYz68FJMxZf4m8WrZmb+tJI+GKIE+osEaEJkskxQ0pBPWE2wAgYLmvfQDfoshRr8ieOt3Gt2AkoFgh6PPQlUiDG8HFjbhRwrDpa5tAXdMuIEpu7zvW04LadNsX2SdX5PXQoUYmXBUiGt5cDPXlywAQCS3L+wPIRyhx3gey2bS2WbTPHMgKeAZBiURi0Ag6a5JJ3TAsenSA4IzuC7iK+/bKSbRoz9rmni3QFZ1CUCWNCNOLiII3gyXdzYQAQEgEwP8AExAK3NaG7DqAbQYtF3+yAqwAUAABhX6aAB80giAkBAb9QQMIxr+ADDgIPOE1WtgBbGNc+umKVQCoggZQrIkM+ANY0AAECQAAx/UjewCPAOAFACMAAEBjIOCB/QAgqk0YoPkCgD8Qb0CwA8CGAAAJAIAKQJxkDwB0IPYA/gCgA26HEOu2dDudVWqzYWTcExegXoPEAlEneUx4NJ9Xhx+QaEq42QdC0XSFY6ueHZpxInJ6mVZFueZTRjU7HZaAzAFKGEoR3p/cJ05go8dyFgyod8Vovq76Z3HWUBAwBDDseYAAAAAA/wcAAJh1Vr+adVa/S5srvph11j8LBgMBAQf/ARUavQjlBE0CrQF0UERwOBgUCP///48IBxggMDAsLMDUGQGRAz0LoAda5c4/5buYdp9mfv5MO7OcdOwSX710rtXbCFtTs3lUczS3GGF3cL1EUhef97tpYrIrtM1cQqWVDHFTSAlL59Vt5ZXGcQF9bMOP9qcy/PWVM10gWUztX7u76CvY4Z7dmjqhoEZ9hdWh7nRgOckm247hjbdV6erkwlB5XVlZKJo+CMT2LtY1GjDTtlL6cDDwtm3XZKwsTOFK+CrH3YGq45HL8hfObrXhTIhaT5rVxGCfQzsd+QXE71eTQyC52ZOoFfETW6x8jOFK+JqYfiG0p8ZZRg5tODf16ekeFVez11sqm4d+e1z81lAa1Zjk6/2+WNDZ242RwwXRvddqg3Wqm/9sd0S0egyUaElPO8S5gfLacA1Vc0RSubDy4RAj2JG5vNr4VMLZJWAGpr7e9phgJP4xAfPm+swSG/s3lQXaxfqNJPnP6rzMh+eomXbHNHqqVFp2WPa74okHRonMVEv4Z3nbfXYfJfzqQxvqFA1unJWXwBRQOauuBw3YDzAeS/iCoN66krTKqvyLy+7TQc8cEoN30+dC6kEYCsGJB0bK6YWS8pzlRMI1TDj3aHKwzHgmUjeS6rbE5VzFXAjEU2v05T5jiup+tQgvBUUZCyDayuv4kqoVmnht/Dl1Wdovbw/gG8eshqlzNNZqbc+gp2weD15ZeptkD4zn+gDeFA9KQjaUY2Oe8pDD91W/mW+AVaC8zIIGbfCCk4/UQBsxpTnl7xZY/SUlACtqIbVLnQfbEXbjgSHjG11PcnFQvmmV6IcwBKW8YvOZ0WuzCS9aVYhfTWOsh5bUJyqib7rZ1Ro98kSRyNqo+7FvldXkO0+jhLX1DbqEUa6hA5GKClyBEVnBRC3gUlDpch8i2obs0HoE2mbI+db94reBYADK8kVIJksCUutmx/8/DXi2dAXnNXnJGyur6yrIQ8Sip+jAz+3wEd+2zmvGqusG5o3vVyVIJIz9zhloW+wqthLOnBuNKQQOVXDdJY1O+vPiYqHGlset+dchtnhamZsyQEOsbe+QcetdlhIJcNzsk2+KlnBzUm+m+8x7PQ0l5rACySJvz3NYUJtfztjIr+qLuPo6xYAjsGrRaoNr0RSGn9Hqy4crx90qw+fuwBEIbN61AK3wMzPkWt4QoIs8BeV4XmSnWUHeIG7SteOf0QiotbZiwFt29awGvxmzGIUr/gLZlToptdXfvCvHvGHo8koATyCnvb9NXaYrtM0H/s/5kB9dpiu0zQIWIf+k/wAAAH8AAAD/A6tRiwgFAQEACwPNCgUTAQVVCJkDVQStAyUEmQOJAecCq2EhKzLHoZU3eRR9jqOGYh4mA3CDblP+IwfA0RVXhyElWsWqprl61DHdV/d+4BtSAiEO64CvMRsBpY+tvbNvs04+Mvt3VfF5jNd9usBgFVHN4vs+xweOjDz3Uuoef1TknSPV6RlJv44r5JlMCQ4/5UFjWPZ8KAjMJN/TDQfFcH68sUtllEIStnpx/vomcrPbf7B0BhZpHpgkIcJsYfh2wHUfKmWmyTpj9akxjDlFUNaQ3OuJyOmqbXlBjhK9eIMlUUzoMScKn6xkmyObipTGIMWERStvc7UOujrEZa6UU48AhD6iS1qbs0qgm1hw6HWBSXX+Zu8ahWgsL8N+SkVDb3Ts4aF8DMOnZ0iRYmvaiULQ6igg6ox3MDffAJB5CoOlOVNsBux5tBwd8ItAUnSoadmKP2fS40UWyPG4u11hvZAldCo0RdFgOYipd7IB1qWJ74rF7v0glcXvWTbqodqrnJOWUAXCz5bKYgtoHxdAuYJIOmxPLPoAPB+FaXou8QPNH3nm+iJpK64Kaji20kOjjaBkZxuzAmDo0UumALJCVJfnN7dJYMsYtjBaoysZuAYKuDzA80XqjieCmASAIqC6sATYF8CYVF8bsAOQKwCWDituDOC6kATYFwC5BMCfATMALQLwM6RIMQAsgwKQIgA5Qy+AppsCyBXgpzDcW2YoHMm8wedfCiwiGtoc8JNCjaClwAEBjWieRAuIigooEGpFfCxqksmCYCqDLiqscDpaQFdKKKoiCawBdkWAoyKy+CQgwCMiKtIBoLqgCO4ILNokvECoWIHxhcqS5E8INQrWpDJ22OghrvalBougqXSKCxgKAL0oBoM/KoUUK0CLbkU2CvJF2xVlICqiCmqXYqfTz3RFGYiKyCKBOgAYiqrQDBEA+mjCA8CMWJQehbjE9dETEtQI1qPP+NuXGiyCjirJgACpcFg6yaQClIJkqbGoELYChlRFhQ2WKqVpAXdFgKMiqiDk/1dIICqiiW4xCEAqumDR6L/AJIoigcEaBy4gKiZxYShggHImID8h1Ajeohf4+5cKiwiWYhlQwClaCKAqN7GR6DaRqDQBQIJjgoIjyvQpKmBAd3yCA8OqiIMM+A8O0gpyC7AGAHAKBKAqeGhDUovbkkmZHTiirEgaSKJdpodKDiQoo4OBhCihqoKEHwSCgiigooKKRP8HTKL4ES1AKhy+NsTHoqrgAaKQpbmosMJpSz6Cg9AqagCO/+Ag9IZSC5hOAlCCHYcBpLrgg7PAoi5xIIh1Cm58oiKICRKCBhIqqHhpOOCIt1SDggigqoKOvCwLwIgwRypGMDCIqsLSArZo1mRDfcFy2uJAUFMiHoCvHbhQZysOBK0gNYH0MoCiaJDKCwQMQiUYBDVajB4p4lIAigSUgaKCiI37iQQUgaKChn4ZAJgiazg4x6UCmIZSqbFQwQ3AqAaTN3iqlM7zCQ5CoohaiCyA4GAhiqgDXvUApqoLDmn+C1yiMMyGKq4KGGJJhgIGS4vQgISABBIqaGi8H0gISCChgogeTgOgglSnAqjCWGwk6gh5JPrjLyAJVgCpTCsDWMoLxuBgJIqIg6wGAA5Sq4gFoksDmKpKAQKnaNouqMpsqCQGBpJoi0CpyEhdWbGQqFhqPn4DkCna0ZEJmQXKiZgoGF/2FBv4EMgjir6giDQzx4CWo+ykqPbVGp2Iac1xqDaykIlyGspPgSwFLIAoBZnDBqYCAAAlNVuq/Nkeuoug8On59PidFJuTvspfxSV4MWhSWc2OYPSg/M/c69fr8fn49edxhyfa2/CoRPqAAAAAAP8DAAAUgQY/sM9dP2xeOj4KAERSQUNPAgIBAQAAAowG/AcC/ActLRkHGgcQBxoHGgcQBxoHGgcQBxoHGgcQBxoHGgcQBxoHGgcQBxoHGgcQBxoHGgcQBxoHGgcQBxoHGgcQBxoHGgcQBxoHGgcQBxoHGgcQBxoHGgcQBxoHGgcQB///////H/8CokVpoAGKqCTPySIM67OH1ECFFRN8IgStVdN/qSPtMc7NCShUvB6ekJICgeSDbxfb/w+wFvXLWVsdOm1+LngmAzETx21W1b9rXLrjYIVXoQ+BeV4lfE3YVc4IwYyqzp8W0X9oYYZEPZNBVYUrbbceemLJ2Epaxz4dQQo0lwFCaaaGXs4slT+Xm64+uFE8c6IQfTRvauSgL3kMoYnGyW5Uq5bSihmB/wOf+onhAQECBAPNDEUE8S4guw5UfaQrjCuMK4wrjCuMK4wrjCuMK4wrjCuMK4wrvrrDAQECBAdRLLETGDTIX6FAsLaM3afdXCwzaoWfsGCkEc5djeABAQIFJREHuRklFS5IojZLiT9m5Ezdi5ydmcH2QCdtiMfA1E5V5xmXQItk/4bFfSFcx03o6Xs/OnSdwwEBAgSxEwdRLBgUA6o/XayaRvB+OnYcZIrMGBZnBlAVAIy0AQEBAQFAAQAAA/8AAQABAAEAA
Download .txt
gitextract_tr77z8gq/

├── .changeset/
│   ├── README.md
│   └── config.json
├── .codesandbox/
│   └── ci.json
├── .eslintignore
├── .eslintrc.json
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   ├── issue_template.md
│   └── workflows/
│       ├── canary.yml
│       ├── docs.yml
│       └── test.yml
├── .gitignore
├── .husky/
│   ├── .gitignore
│   └── pre-commit
├── .prettierignore
├── .prettierrc
├── CONTRIBUTING.md
├── LICENSE
├── babel.config.js
├── docs/
│   ├── API/
│   │   ├── additional-exports.mdx
│   │   ├── canvas.mdx
│   │   ├── events.mdx
│   │   ├── hooks.mdx
│   │   ├── objects.mdx
│   │   ├── testing.mdx
│   │   └── typescript.mdx
│   ├── advanced/
│   │   ├── pitfalls.mdx
│   │   └── scaling-performance.mdx
│   ├── getting-started/
│   │   ├── basic-example-sandpack/
│   │   │   ├── index.jsx
│   │   │   └── styles.css
│   │   ├── community-r3f-components.mdx
│   │   ├── examples.mdx
│   │   ├── installation.mdx
│   │   ├── introduction.mdx
│   │   └── your-first-scene.mdx
│   └── tutorials/
│       ├── basic-animations.mdx
│       ├── events-and-interaction.mdx
│       ├── how-it-works.mdx
│       ├── loading-models.mdx
│       ├── loading-textures.mdx
│       └── v9-migration-guide.mdx
├── example/
│   ├── .gitignore
│   ├── CHANGELOG.md
│   ├── index.html
│   ├── package.json
│   ├── public/
│   │   ├── Parrot.glb
│   │   ├── Stork.glb
│   │   ├── apple.gltf
│   │   ├── bottle.gltf
│   │   ├── farm.gltf
│   │   ├── lightning.gltf
│   │   └── ramen.gltf
│   ├── src/
│   │   ├── App.tsx
│   │   ├── components.tsx
│   │   ├── demos/
│   │   │   ├── Activity.tsx
│   │   │   ├── AutoDispose.tsx
│   │   │   ├── ChangeTexture.tsx
│   │   │   ├── ClickAndHover.tsx
│   │   │   ├── ContextMenuOverride.tsx
│   │   │   ├── FlushSync.tsx
│   │   │   ├── Gestures.tsx
│   │   │   ├── Gltf.tsx
│   │   │   ├── Inject.tsx
│   │   │   ├── Layers.tsx
│   │   │   ├── Lines.tsx
│   │   │   ├── MultiMaterial.tsx
│   │   │   ├── MultiRender.tsx
│   │   │   ├── MultiView.tsx
│   │   │   ├── Pointcloud.tsx
│   │   │   ├── Portals.tsx
│   │   │   ├── Reparenting.tsx
│   │   │   ├── ResetProps.tsx
│   │   │   ├── SVGRenderer.tsx
│   │   │   ├── Selection.tsx
│   │   │   ├── StopPropagation.tsx
│   │   │   ├── SuspenseAndErrors.tsx
│   │   │   ├── SuspenseMaterial.tsx
│   │   │   ├── Test.tsx
│   │   │   ├── ViewTracking.tsx
│   │   │   ├── Viewcube.tsx
│   │   │   ├── WebGPU.tsx
│   │   │   └── index.tsx
│   │   ├── index.tsx
│   │   └── styles.css
│   ├── tsconfig.json
│   └── vite.config.ts
├── jest.config.js
├── package.json
├── packages/
│   ├── eslint-plugin/
│   │   ├── .npmignore
│   │   ├── CHANGELOG.md
│   │   ├── README.md
│   │   ├── docs/
│   │   │   └── rules/
│   │   │       ├── no-clone-in-loop.md
│   │   │       └── no-new-in-loop.md
│   │   ├── package.json
│   │   ├── scripts/
│   │   │   └── codegen.ts
│   │   ├── src/
│   │   │   ├── configs/
│   │   │   │   ├── all.ts
│   │   │   │   └── recommended.ts
│   │   │   ├── index.ts
│   │   │   ├── lib/
│   │   │   │   └── url.ts
│   │   │   └── rules/
│   │   │       ├── index.ts
│   │   │       ├── no-clone-in-loop.ts
│   │   │       └── no-new-in-loop.ts
│   │   └── tests/
│   │       └── rules/
│   │           ├── no-clone-in-loop.test.ts
│   │           └── no-new-in-loop.test.ts
│   ├── fiber/
│   │   ├── .npmignore
│   │   ├── CHANGELOG.md
│   │   ├── __mocks__/
│   │   │   ├── expo-asset.ts
│   │   │   ├── expo-file-system.ts
│   │   │   ├── expo-gl.ts
│   │   │   ├── react-native.ts
│   │   │   └── react-use-measure.ts
│   │   ├── native/
│   │   │   └── package.json
│   │   ├── package.json
│   │   ├── readme.md
│   │   ├── src/
│   │   │   ├── core/
│   │   │   │   ├── events.ts
│   │   │   │   ├── hooks.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   ├── loop.ts
│   │   │   │   ├── reconciler.tsx
│   │   │   │   ├── renderer.tsx
│   │   │   │   ├── store.ts
│   │   │   │   └── utils.tsx
│   │   │   ├── index.tsx
│   │   │   ├── native/
│   │   │   │   ├── Canvas.tsx
│   │   │   │   ├── events.ts
│   │   │   │   └── polyfills.ts
│   │   │   ├── native.tsx
│   │   │   ├── three-types.ts
│   │   │   └── web/
│   │   │       ├── Canvas.tsx
│   │   │       └── events.ts
│   │   └── tests/
│   │       ├── __snapshots__/
│   │       │   ├── canvas.native.test.tsx.snap
│   │       │   ├── canvas.test.tsx.snap
│   │       │   ├── index.test.tsx.snap
│   │       │   └── utils.test.ts.snap
│   │       ├── canvas.native.test.tsx
│   │       ├── canvas.test.tsx
│   │       ├── events.test.tsx
│   │       ├── hooks.test.tsx
│   │       ├── index.test.tsx
│   │       ├── polyfills.test.ts
│   │       ├── reconciler.test.ts
│   │       ├── renderer.test.tsx
│   │       └── utils.test.ts
│   ├── shared/
│   │   └── setupTests.ts
│   └── test-renderer/
│       ├── .npmignore
│       ├── CHANGELOG.md
│       ├── README.md
│       ├── markdown/
│       │   ├── rttr-instance.md
│       │   └── rttr.md
│       ├── package.json
│       └── src/
│           ├── WebGL2RenderingContext.ts
│           ├── __tests__/
│           │   ├── RTTR.core.test.tsx
│           │   ├── RTTR.events.test.tsx
│           │   ├── RTTR.hooks.test.tsx
│           │   ├── RTTR.methods.test.tsx
│           │   └── __snapshots__/
│           │       └── RTTR.core.test.tsx.snap
│           ├── createTestCanvas.ts
│           ├── createTestInstance.ts
│           ├── fireEvent.ts
│           ├── helpers/
│           │   ├── events.ts
│           │   ├── graph.ts
│           │   ├── strings.ts
│           │   ├── testInstance.ts
│           │   ├── tree.ts
│           │   └── waitFor.ts
│           ├── index.tsx
│           └── types/
│               ├── index.ts
│               ├── internal.ts
│               └── public.ts
├── readme.md
├── tsconfig.json
└── vite.config.ts
Download .txt
SYMBOL INDEX (415 symbols across 71 files)

FILE: docs/getting-started/basic-example-sandpack/index.jsx
  function Box (line 6) | function Box(props) {

FILE: example/src/App.tsx
  constant DEFAULT_COMPONENT_NAME (line 10) | const DEFAULT_COMPONENT_NAME = 'Portals'
  function ErrorBoundary (line 13) | function ErrorBoundary({ children, fallback, name }: any) {
  function Demo (line 18) | function Demo() {
  function Dots (line 30) | function Dots() {
  function App (line 47) | function App() {

FILE: example/src/demos/Activity.tsx
  function SceneA (line 9) | function SceneA({ onSelect }: { onSelect: Function }) {
  function SceneB (line 46) | function SceneB({ onSelect }: { onSelect: Function }) {
  function App (line 70) | function App() {

FILE: example/src/demos/AutoDispose.tsx
  type BoxProps (line 5) | type BoxProps = ThreeElements['object3D'] & {
  function Box1 (line 10) | function Box1(props: BoxProps) {
  function Box2 (line 28) | function Box2(props: BoxProps) {
  function Switcher (line 48) | function Switcher() {
  function App (line 59) | function App() {

FILE: example/src/demos/ChangeTexture.tsx
  function App (line 5) | function App() {
  function Plane (line 13) | function Plane() {

FILE: example/src/demos/ClickAndHover.tsx
  function Box (line 9) | function Box(props: ThreeElements['mesh']) {
  function Box2 (line 32) | function Box2(props: ThreeElements['group']) {
  function App (line 36) | function App() {

FILE: example/src/demos/ContextMenuOverride.tsx
  function App (line 4) | function App() {

FILE: example/src/demos/FlushSync.tsx
  function Capture (line 6) | function Capture() {
  function App (line 37) | function App() {

FILE: example/src/demos/Gestures.tsx
  function Object (line 6) | function Object({ scale = 1, z = 0, opacity = 1 }) {
  function App (line 47) | function App() {

FILE: example/src/demos/Gltf.tsx
  function Test (line 5) | function Test() {
  function App (line 17) | function App() {

FILE: example/src/demos/Inject.tsx
  type CubeProps (line 5) | type CubeProps = ThreeElements['mesh'] & { color: string }
  function App (line 10) | function App() {
  function Cube (line 37) | function Cube({ color, ...props }: CubeProps) {

FILE: example/src/demos/Layers.tsx
  function Box (line 12) | function Box(props: ThreeElements['mesh']) {
  function Sphere (line 21) | function Sphere(props: ThreeElements['mesh']) {
  function App (line 30) | function App() {

FILE: example/src/demos/Lines.tsx
  function PolyLine (line 5) | function PolyLine({
  function EndPoint (line 24) | function EndPoint({
  function App (line 60) | function App() {

FILE: example/src/demos/MultiMaterial.tsx
  function ReuseMaterial (line 7) | function ReuseMaterial(props: ThreeElements['mesh']) {
  function TestReuse (line 16) | function TestReuse() {
  function TestMultiMaterial (line 32) | function TestMultiMaterial(props: ThreeElements['mesh']) {
  function TestMultiDelete (line 62) | function TestMultiDelete(props: ThreeElements['mesh']) {
  function TestMix (line 88) | function TestMix(props: ThreeElements['mesh']) {
  function Test (line 110) | function Test() {

FILE: example/src/demos/MultiRender.tsx
  function App (line 46) | function App() {

FILE: example/src/demos/MultiView.tsx
  function useHover (line 24) | function useHover() {
  function Soda (line 36) | function Soda(props: ThreeElements['group']) {
  function View (line 50) | function View({
  function Container (line 127) | function Container({
  function Scene (line 184) | function Scene({

FILE: example/src/demos/Pointcloud.tsx
  class DotMaterialImpl (line 5) | class DotMaterialImpl extends THREE.ShaderMaterial {
    method constructor (line 6) | constructor() {
  function Particles (line 25) | function Particles({ pointCount }: { pointCount: number }) {
  function App (line 56) | function App() {

FILE: example/src/demos/Portals.tsx
  function Lights (line 6) | function Lights() {
  function Farm (line 17) | function Farm(props: ThreeElements['group']) {
  function Ramen (line 22) | function Ramen(props: ThreeElements['group']) {
  function Soda (line 27) | function Soda(props: ThreeElements['group']) {
  function useHover (line 40) | function useHover() {
  function Portal (line 45) | function Portal({
  function Test (line 108) | function Test() {
  function App (line 114) | function App() {

FILE: example/src/demos/Reparenting.tsx
  function Icosahedron (line 5) | function Icosahedron() {
  function RenderToPortal (line 16) | function RenderToPortal({ targets }: { targets: THREE.Group[] }) {
  function Group (line 27) | function Group() {

FILE: example/src/demos/ResetProps.tsx
  function AdaptivePixelRatio (line 6) | function AdaptivePixelRatio() {
  function AdaptiveEvents (line 30) | function AdaptiveEvents() {
  function Scene (line 44) | function Scene() {
  function App (line 91) | function App() {

FILE: example/src/demos/SVGRenderer.tsx
  function TorusKnot (line 6) | function TorusKnot() {

FILE: example/src/demos/Selection.tsx
  function Sphere (line 4) | function Sphere() {
  function Circle (line 15) | function Circle() {
  function App (line 26) | function App() {

FILE: example/src/demos/StopPropagation.tsx
  function useHover (line 6) | function useHover() {
  function Soda (line 18) | function Soda(props: ThreeElements['group']) {
  function Hud (line 32) | function Hud({ priority = 1, children }: { priority?: number; children: ...
  function Plane (line 49) | function Plane({
  function App (line 78) | function App() {

FILE: example/src/demos/SuspenseAndErrors.tsx
  function AsyncComponent (line 8) | function AsyncComponent({ cacheKey }: { cacheKey: string }) {
  function SimulateError (line 14) | function SimulateError() {
  function App (line 19) | function App() {

FILE: example/src/demos/SuspenseMaterial.tsx
  function SlowMaterial (line 5) | function SlowMaterial({ arg = 0 }) {
  function FallbackMaterial (line 10) | function FallbackMaterial() {
  function App (line 14) | function App() {

FILE: example/src/demos/Test.tsx
  function Box (line 6) | function Box({ color = 'orange', ...props }) {
  function App (line 27) | function App() {

FILE: example/src/demos/ViewTracking.tsx
  function useHover (line 15) | function useHover() {
  function Soda (line 27) | function Soda(props: ThreeElements['group']) {
  function Duck (line 44) | function Duck(props: ThreeElements['group']) {
  function Candy (line 50) | function Candy(props: ThreeElements['group']) {
  function Flash (line 58) | function Flash(props: ThreeElements['group']) {
  function Apple (line 64) | function Apple(props: ThreeElements['group']) {
  function Container (line 74) | function Container({
  function Scene (line 173) | function Scene() {
  function App (line 184) | function App() {

FILE: example/src/demos/Viewcube.tsx
  function Viewcube (line 6) | function Viewcube() {
  function App (line 62) | function App() {

FILE: example/src/demos/WebGPU.tsx
  type ThreeElements (line 8) | interface ThreeElements extends ThreeToJSXElements<typeof THREE> {}
  function Plane (line 13) | function Plane(props: ThreeElements['mesh']) {
  function App (line 38) | function App() {

FILE: packages/eslint-plugin/scripts/codegen.ts
  type FoundRule (line 12) | interface FoundRule {
  type GeneratedConfig (line 17) | interface GeneratedConfig {
  function ruleDocsPath (line 29) | async function ruleDocsPath(name: string): Promise<string> {
  function generateConfig (line 41) | async function generateConfig(name: string, rules: FoundRule[]) {
  function writeFile (line 57) | async function writeFile(filepath: string, code: string) {
  function generateRuleIndex (line 62) | async function generateRuleIndex(rules: FoundRule[]) {
  function generatePluginIndex (line 75) | async function generatePluginIndex() {
  function generateReadme (line 93) | async function generateReadme(rules: FoundRule[]) {
  function generate (line 129) | async function generate() {

FILE: packages/eslint-plugin/src/lib/url.ts
  function gitHubUrl (line 1) | function gitHubUrl(name: string) {

FILE: packages/eslint-plugin/src/rules/no-clone-in-loop.ts
  method create (line 17) | create(ctx) {

FILE: packages/eslint-plugin/src/rules/no-new-in-loop.ts
  method create (line 17) | create(ctx) {

FILE: packages/fiber/__mocks__/expo-asset.ts
  class Asset (line 1) | class Asset {
    method downloadAsync (line 12) | async downloadAsync() {

FILE: packages/fiber/__mocks__/expo-gl.ts
  function GLView (line 5) | function GLView({ onContextCreate, ref, ...props }: GLViewProps & any) {

FILE: packages/fiber/__mocks__/react-native.ts
  class View (line 4) | class View extends React.Component<Omit<ViewProps, 'children'> & { child...
    method componentDidMount (line 5) | componentDidMount() {
    method render (line 18) | render() {
  method getSize (line 39) | getSize(_uri: string, res: Function, rej?: Function) {
  method get (line 51) | get() {

FILE: packages/fiber/__mocks__/react-use-measure.ts
  function useMeasure (line 3) | function useMeasure() {

FILE: packages/fiber/src/core/events.ts
  type Intersection (line 6) | interface Intersection extends THREE.Intersection {
  type IntersectionEvent (line 11) | interface IntersectionEvent<TSourceEvent> extends Intersection {
  type Camera (line 34) | type Camera = THREE.OrthographicCamera | THREE.PerspectiveCamera
  type ThreeEvent (line 35) | type ThreeEvent<TEvent> = IntersectionEvent<TEvent> & Properties<TEvent>
  type DomEvent (line 36) | type DomEvent = PointerEvent | MouseEvent | WheelEvent
  type Events (line 38) | interface Events {
  type EventHandlers (line 51) | interface EventHandlers {
  type FilterFunction (line 68) | type FilterFunction = (items: THREE.Intersection[], state: RootState) =>...
  type ComputeFunction (line 69) | type ComputeFunction = (event: DomEvent, root: RootState, previous?: Roo...
  type EventManager (line 71) | interface EventManager<TTarget> {
  type PointerCaptureTarget (line 94) | interface PointerCaptureTarget {
  function makeId (line 99) | function makeId(event: Intersection) {
  function releaseInternalPointerCapture (line 107) | function releaseInternalPointerCapture(
  function removeInteractivity (line 124) | function removeInteractivity(store: RootStore, object: THREE.Object3D) {
  function createEvents (line 140) | function createEvents(store: RootStore) {

FILE: packages/fiber/src/core/hooks.tsx
  function useInstanceHandle (line 14) | function useInstanceHandle<T>(ref: React.RefObject<T>): React.RefObject<...
  function useStore (line 24) | function useStore(): RootStore {
  function useThree (line 34) | function useThree<T = RootState>(
  function useFrame (line 46) | function useFrame(callback: RenderCallback, renderPriority: number = 0):...
  function useGraph (line 60) | function useGraph(object: THREE.Object3D): ObjectMap {
  type InputLike (line 64) | type InputLike = string | string[] | string[][] | Readonly<string | stri...
  type LoaderLike (line 65) | type LoaderLike = THREE.Loader<any, InputLike>
  type GLTFLike (line 66) | type GLTFLike = { scene: THREE.Object3D }
  type LoaderInstance (line 68) | type LoaderInstance<T extends LoaderLike | ConstructorRepresentation<Loa...
  type LoaderResult (line 71) | type LoaderResult<T extends LoaderLike | ConstructorRepresentation<Loade...
  type Extensions (line 79) | type Extensions<T extends LoaderLike | ConstructorRepresentation<LoaderL...
  function loadingFn (line 90) | function loadingFn<L extends LoaderLike | ConstructorRepresentation<THRE...
  function useLoader (line 137) | function useLoader<I extends InputLike, L extends LoaderLike | Construct...

FILE: packages/fiber/src/core/loop.ts
  type GlobalRenderCallback (line 4) | type GlobalRenderCallback = (timestamp: number) => void
  type SubItem (line 5) | interface SubItem {
  function createSubs (line 9) | function createSubs(callback: GlobalRenderCallback, subs: Set<SubItem>):...
  function run (line 37) | function run(effects: Set<SubItem>, timestamp: number) {
  type GlobalEffectType (line 44) | type GlobalEffectType = 'before' | 'after' | 'tail'
  function flushGlobalEffects (line 46) | function flushGlobalEffects(type: GlobalEffectType, timestamp: number): ...
  function update (line 60) | function update(timestamp: number, state: RootState, frame?: XRFrame) {
  function loop (line 92) | function loop(timestamp: number): void {
  function invalidate (line 134) | function invalidate(state?: RootState, frames = 1): void {
  function advance (line 163) | function advance(timestamp: number, runGlobalEffects: boolean = true, st...

FILE: packages/fiber/src/core/reconciler.tsx
  type Fiber (line 26) | type Fiber = Omit<Reconciler.Fiber, 'alternate'> & { refCleanup: null | ...
  function createReconciler (line 28) | function createReconciler<
  type Root (line 71) | interface Root {
  type AttachFnType (line 76) | type AttachFnType<O = any> = (parent: any, self: O) => () => void
  type AttachType (line 77) | type AttachType<O = any> = string | AttachFnType<O>
  type ConstructorRepresentation (line 79) | type ConstructorRepresentation<T = any> = new (...args: any[]) => T
  type Catalogue (line 81) | interface Catalogue {
  type Args (line 88) | type Args<T> = T extends ConstructorRepresentation
  type ArgsProp (line 94) | type ArgsProp<P> = P extends ConstructorRepresentation
  type InstanceProps (line 100) | type InstanceProps<T = any, P = any> = ArgsProp<P> & {
  type Instance (line 107) | interface Instance<O = any> {
  type HostConfig (line 121) | interface HostConfig {
  constant PREFIX_REGEX (line 140) | const PREFIX_REGEX = /^three(?=[A-Z])/
  function extend (line 150) | function extend<T extends Catalogue | ConstructorRepresentation>(
  function validateInstance (line 162) | function validateInstance(type: string, props: HostConfig['props']): void {
  function createInstance (line 180) | function createInstance(type: string, props: HostConfig['props'], root: ...
  function hideInstance (line 192) | function hideInstance(instance: HostConfig['instance']): void {
  function unhideInstance (line 205) | function unhideInstance(instance: HostConfig['instance']): void {
  function handleContainerEffects (line 220) | function handleContainerEffects(parent: Instance, child: Instance, befor...
  function appendChild (line 270) | function appendChild(parent: HostConfig['instance'], child: HostConfig['...
  function insertBefore (line 281) | function insertBefore(
  function disposeOnIdle (line 298) | function disposeOnIdle(object: any) {
  function removeChild (line 315) | function removeChild(
  function setFiberRef (line 362) | function setFiberRef(fiber: Fiber, publicInstance: HostConfig['publicIns...
  function swapInstances (line 378) | function swapInstances(): void {
  constant NO_CONTEXT (line 451) | const NO_CONTEXT: HostConfig['hostContext'] = {}
  method appendChildToContainer (line 485) | appendChildToContainer(container, child) {
  method removeChildFromContainer (line 491) | removeChildFromContainer(container, child) {
  method insertInContainerBefore (line 497) | insertInContainerBefore(container, child, beforeChild) {
  method commitUpdate (line 505) | commitUpdate(
  method commitMount (line 540) | commitMount() {}
  method beforeActiveInstanceBlur (line 556) | beforeActiveInstanceBlur() {}
  method afterActiveInstanceBlur (line 557) | afterActiveInstanceBlur() {}
  method detachDeletedInstance (line 558) | detachDeletedInstance() {}
  method prepareScopeUpdate (line 559) | prepareScopeUpdate() {}
  method requestPostPaintCallback (line 565) | requestPostPaintCallback() {}
  method suspendInstance (line 568) | suspendInstance() {}
  method setCurrentUpdatePriority (line 576) | setCurrentUpdatePriority(newPriority: number) {
  method getCurrentUpdatePriority (line 579) | getCurrentUpdatePriority() {
  method resolveUpdatePriority (line 582) | resolveUpdatePriority() {
  method resetFormInstance (line 604) | resetFormInstance() {}
  method applyViewTransitionName (line 611) | applyViewTransitionName(_instance: any, _name: any, _className: any) {}
  method restoreViewTransitionName (line 612) | restoreViewTransitionName(_instance: any, _props: any) {}
  method cancelViewTransitionName (line 613) | cancelViewTransitionName(_instance: any, _name: any, _props: any) {}
  method cancelRootViewTransitionName (line 614) | cancelRootViewTransitionName(_rootContainer: any) {}
  method restoreRootViewTransitionName (line 615) | restoreRootViewTransitionName(_rootContainer: any) {}
  method suspendOnActiveViewTransition (line 624) | suspendOnActiveViewTransition(_state: any, _container: any) {}
  method stopViewTransition (line 630) | stopViewTransition(_transition: null) {}
  method getCurrentGestureOffset (line 637) | getCurrentGestureOffset(_provider: null): number {
  method cloneMutableInstance (line 642) | cloneMutableInstance(instance: any, _keepChildren: any) {
  method cloneMutableTextInstance (line 645) | cloneMutableTextInstance(textInstance: any) {
  method cloneRootViewTransitionContainer (line 648) | cloneRootViewTransitionContainer(_rootContainer: any) {
  method removeRootViewTransitionClone (line 651) | removeRootViewTransitionClone(_rootContainer: any, _clone: any) {
  method updateFragmentInstanceFiber (line 657) | updateFragmentInstanceFiber(_fiber: any, _instance: any): void {}
  method commitNewChildToFragmentInstance (line 658) | commitNewChildToFragmentInstance(_child: any, _fragmentInstance: any): v...
  method deleteChildFromFragmentInstance (line 659) | deleteChildFromFragmentInstance(_child: any, _fragmentInstance: any): vo...

FILE: packages/fiber/src/core/renderer.tsx
  type OffscreenCanvas (line 39) | interface OffscreenCanvas extends EventTarget {}
  type DefaultGLProps (line 45) | type DefaultGLProps = Omit<THREE.WebGLRendererParameters, 'canvas'> & {
  type GLProps (line 49) | type GLProps =
  type CameraProps (line 55) | type CameraProps = (
  type RenderProps (line 67) | interface RenderProps<TCanvas extends HTMLCanvasElement | OffscreenCanva...
  type ReconcilerRoot (line 115) | interface ReconcilerRoot<TCanvas extends HTMLCanvasElement | OffscreenCa...
  function computeInitialSize (line 121) | function computeInitialSize(canvas: HTMLCanvasElement | OffscreenCanvas,...
  function createRoot (line 142) | function createRoot<TCanvas extends HTMLCanvasElement | OffscreenCanvas>(
  type ProviderProps (line 426) | interface ProviderProps<TCanvas extends HTMLCanvasElement | OffscreenCan...
  function Provider (line 433) | function Provider<TCanvas extends HTMLCanvasElement | OffscreenCanvas>({
  function unmountComponentAtNode (line 453) | function unmountComponentAtNode<TCanvas extends HTMLCanvasElement | Offs...
  type InjectState (line 482) | type InjectState = Partial<
  function createPortal (line 493) | function createPortal(
  type PortalProps (line 501) | interface PortalProps {
  function Portal (line 507) | function Portal({ state = {}, children, container }: PortalProps): React...
  function flushSync (line 580) | function flushSync<R>(fn: () => R): R {

FILE: packages/fiber/src/core/store.ts
  type Intersection (line 8) | interface Intersection extends THREE.Intersection {
  type Subscription (line 12) | type Subscription = {
  type Dpr (line 18) | type Dpr = number | [min: number, max: number]
  type Size (line 19) | interface Size {
  type Frameloop (line 25) | type Frameloop = 'always' | 'demand' | 'never'
  type Viewport (line 26) | interface Viewport extends Size {
  type RenderCallback (line 39) | type RenderCallback = (state: RootState, delta: number, frame?: XRFrame)...
  type Performance (line 41) | interface Performance {
  type Renderer (line 54) | interface Renderer {
  type InternalState (line 59) | interface InternalState {
  type XRManager (line 73) | interface XRManager {
  type RootState (line 78) | interface RootState {
  type RootStore (line 142) | type RootStore = UseBoundStoreWithEqualityFn<StoreApi<RootState>>
  function getCurrentViewport (line 154) | function getCurrentViewport(

FILE: packages/fiber/src/core/utils.tsx
  type NonFunctionKeys (line 8) | type NonFunctionKeys<P> = { [K in keyof P]-?: P[K] extends Function ? ne...
  type Overwrite (line 9) | type Overwrite<P, O> = Omit<P, NonFunctionKeys<O>> & O
  type Properties (line 10) | type Properties<T> = Pick<T, NonFunctionKeys<T>>
  type Mutable (line 11) | type Mutable<P> = { [K in keyof P]: P[K] | Readonly<P[K]> }
  type IsOptional (line 12) | type IsOptional<T> = undefined extends T ? true : false
  type IsAllOptional (line 13) | type IsAllOptional<T extends any[]> = T extends [infer First, ...infer R...
  function findInitialRoot (line 22) | function findInitialRoot<T>(instance: Instance<T>): RootStore {
  type Act (line 28) | type Act = <T = any>(cb: () => Promise<T>) => Promise<T>
  type Camera (line 38) | type Camera = (THREE.OrthographicCamera | THREE.PerspectiveCamera) & { m...
  function useMutableCallback (line 60) | function useMutableCallback<T>(fn: T): React.RefObject<T> {
  type Bridge (line 66) | type Bridge = React.FC<{ children?: React.ReactNode }>
  function useBridge (line 71) | function useBridge(): Bridge {
  type SetBlock (line 91) | type SetBlock = false | Promise<null> | null
  type UnblockProps (line 92) | type UnblockProps = { set: React.Dispatch<React.SetStateAction<SetBlock>...
  function Block (line 94) | function Block({ set }: Omit<UnblockProps, 'children'>) {
  method componentDidCatch (line 110) | componentDidCatch(err: Error) {
  method render (line 113) | render() {
  type ObjectMap (line 118) | interface ObjectMap {
  function calculateDpr (line 124) | function calculateDpr(dpr: Dpr): number {
  function getRootState (line 134) | function getRootState<T extends THREE.Object3D = THREE.Object3D>(obj: T) {
  type EquConfig (line 138) | interface EquConfig {
  method equ (line 157) | equ(a: any, b: any, { arrays = 'shallow', objects = 'reference', strict ...
  function buildGraph (line 192) | function buildGraph(object: THREE.Object3D): ObjectMap {
  type Disposable (line 204) | interface Disposable {
  function dispose (line 210) | function dispose<T extends Disposable>(obj: T): void {
  constant REACT_INTERNAL_PROPS (line 218) | const REACT_INTERNAL_PROPS = ['children', 'key', 'ref']
  function getInstanceProps (line 221) | function getInstanceProps<T = any>(pendingProps: Record<string, unknown>...
  function prepare (line 232) | function prepare<T = any>(target: T, root: RootStore, type: string, prop...
  function resolve (line 256) | function resolve(root: any, key: string): { root: any; key: string; targ...
  constant INDEX_REGEX (line 287) | const INDEX_REGEX = /-\d+$/
  function attach (line 289) | function attach(parent: Instance, child: Instance): void {
  function detach (line 306) | function detach(parent: Instance, child: Instance): void {
  constant RESERVED_PROPS (line 321) | const RESERVED_PROPS = [
  constant MEMOIZED_PROTOTYPES (line 333) | const MEMOIZED_PROTOTYPES = new Map()
  function getMemoizedPrototype (line 335) | function getMemoizedPrototype(root: any) {
  function diffProps (line 349) | function diffProps<T = any>(instance: Instance<T>, newProps: Instance<T>...
  constant EVENT_REGEX (line 396) | const EVENT_REGEX = /^on(Pointer|Click|DoubleClick|ContextMenu|Wheel)/
  type ClassConstructor (line 398) | type ClassConstructor = { new (): void }
  function applyProps (line 401) | function applyProps<T = any>(object: Instance<T>['object'], props: Insta...
  function invalidateInstance (line 523) | function invalidateInstance(instance: Instance): void {
  function updateCamera (line 532) | function updateCamera(camera: Camera, size: Size): void {

FILE: packages/fiber/src/native/Canvas.tsx
  type CanvasProps (line 24) | interface CanvasProps extends Omit<RenderProps<HTMLCanvasElement>, 'size...
  function CanvasImpl (line 30) | function CanvasImpl({
  function Canvas (line 241) | function Canvas(props: CanvasProps) {

FILE: packages/fiber/src/native/events.ts
  function createTouchEvents (line 6) | function createTouchEvents(store: RootStore): EventManager<HTMLElement> {

FILE: packages/fiber/src/native/polyfills.ts
  function uuidv4 (line 18) | function uuidv4() {
  function getAsset (line 26) | async function getAsset(input: string | number): Promise<string> {
  function polyfills (line 79) | function polyfills() {

FILE: packages/fiber/src/three-types.ts
  type MutableOrReadonlyParameters (line 8) | type MutableOrReadonlyParameters<T extends (...args: any) => any> = Para...
  type MathRepresentation (line 10) | interface MathRepresentation {
  type VectorRepresentation (line 13) | interface VectorRepresentation extends MathRepresentation {
  type MathTypes (line 16) | type MathTypes = MathRepresentation | THREE.Euler | THREE.Color
  type MathType (line 18) | type MathType<T extends MathTypes> = T extends THREE.Color
  type MathProps (line 24) | type MathProps<P> = {
  type Vector2 (line 28) | type Vector2 = MathType<THREE.Vector2>
  type Vector3 (line 29) | type Vector3 = MathType<THREE.Vector3>
  type Vector4 (line 30) | type Vector4 = MathType<THREE.Vector4>
  type Color (line 31) | type Color = MathType<THREE.Color>
  type Layers (line 32) | type Layers = MathType<THREE.Layers>
  type Quaternion (line 33) | type Quaternion = MathType<THREE.Quaternion>
  type Euler (line 34) | type Euler = MathType<THREE.Euler>
  type Matrix3 (line 35) | type Matrix3 = MathType<THREE.Matrix3>
  type Matrix4 (line 36) | type Matrix4 = MathType<THREE.Matrix4>
  type RaycastableRepresentation (line 38) | interface RaycastableRepresentation {
  type EventProps (line 41) | type EventProps<P> = P extends RaycastableRepresentation ? Partial<Event...
  type ReactProps (line 43) | interface ReactProps<P> {
  type ElementProps (line 49) | type ElementProps<T extends ConstructorRepresentation, P = InstanceType<...
  type ThreeElement (line 53) | type ThreeElement<T extends ConstructorRepresentation> = Mutable<
  type ThreeToJSXElements (line 57) | type ThreeToJSXElements<T extends Record<string, any>> = {
  type ThreeExports (line 61) | type ThreeExports = typeof THREE
  type ThreeElementsImpl (line 62) | type ThreeElementsImpl = ThreeToJSXElements<ThreeExports>
  type ThreeElements (line 64) | interface ThreeElements extends Omit<ThreeElementsImpl, 'audio' | 'sourc...
  type IntrinsicElements (line 75) | interface IntrinsicElements extends ThreeElements {}
  type IntrinsicElements (line 81) | interface IntrinsicElements extends ThreeElements {}
  type IntrinsicElements (line 87) | interface IntrinsicElements extends ThreeElements {}

FILE: packages/fiber/src/web/Canvas.tsx
  type CanvasProps (line 18) | interface CanvasProps
  function CanvasImpl (line 36) | function CanvasImpl({
  function Canvas (line 173) | function Canvas(props: CanvasProps) {

FILE: packages/fiber/src/web/events.ts
  constant DOM_EVENTS (line 4) | const DOM_EVENTS = {
  function createPointerEvents (line 18) | function createPointerEvents(store: RootStore): EventManager<HTMLElement> {

FILE: packages/fiber/tests/canvas.native.test.tsx
  function Test (line 38) | function Test() {

FILE: packages/fiber/tests/canvas.test.tsx
  function Test (line 36) | function Test() {

FILE: packages/fiber/tests/events.test.tsx
  function PointerCaptureTest (line 280) | function PointerCaptureTest(props: { hasMesh: boolean; manualRelease?: b...

FILE: packages/fiber/tests/hooks.test.tsx
  type GLTF (line 93) | interface GLTF {
  class GLTFLoader (line 96) | class GLTFLoader extends THREE.Loader<GLTF, string> {
    method load (line 97) | load(url: string, onLoad: (gltf: GLTF) => void): void {
  class TestLoader (line 130) | class TestLoader extends THREE.Loader {
  class Loader (line 163) | class Loader extends THREE.Loader<null, string> {
    method load (line 164) | load(_url: string, onLoad: (result: null) => void): void {
    method load (line 182) | load(_url: string, onLoad: (result: null) => void): void {
  function Test (line 172) | function Test(): null {
  class Loader (line 181) | class Loader extends THREE.Loader<null, string> {
    method load (line 164) | load(_url: string, onLoad: (result: null) => void): void {
    method load (line 182) | load(_url: string, onLoad: (result: null) => void): void {
  function Test (line 189) | function Test(): null {
  function Component (line 266) | function Component() {

FILE: packages/fiber/tests/index.test.tsx
  function createRoot (line 22) | function createRoot() {
  class Renderer (line 183) | class Renderer extends THREE.WebGLRenderer {}
  function Test (line 198) | function Test() {
  function Test (line 268) | function Test(props: any) {
  function getExports (line 291) | function getExports(source: string): string[] {

FILE: packages/fiber/tests/reconciler.test.ts
  function act (line 4) | async function act<T>(fn: () => Promise<T>) {
  function Test (line 47) | function Test() {

FILE: packages/fiber/tests/renderer.test.tsx
  class Mock (line 8) | class Mock extends THREE.Group {
    method constructor (line 10) | constructor(name: string = '') {
  type ThreeElements (line 18) | interface ThreeElements {
  type ComponentMesh (line 26) | type ComponentMesh = THREE.Mesh<THREE.BoxGeometry, THREE.MeshBasicMaterial>
  function Parent (line 92) | function Parent({ children, show }: { children: React.ReactNode; show: b...
  function Component (line 96) | function Component({ show }: { show: boolean }) {
  function Parent (line 121) | function Parent({ children, primitiveKey }: { children: React.ReactNode;...
  function Component (line 129) | function Component({ primitiveKey }: { primitiveKey: string }) {
  function Test (line 155) | function Test() {
  function SuspenseComponent (line 566) | function SuspenseComponent({ reconstruct = false }: { reconstruct?: bool...
  function Test (line 584) | function Test(props: { reconstruct?: boolean }) {
  function AsyncPrimitive (line 612) | function AsyncPrimitive({ object }: { object: Promise<THREE.Object3D> }) {
  function Fallback (line 647) | function Fallback() {
  function AsyncPrimitive (line 651) | function AsyncPrimitive({ object }: { object: Promise<THREE.Object3D> }) {
  function TestComponent (line 845) | function TestComponent() {

FILE: packages/fiber/tests/utils.test.ts
  function createMockStore (line 19) | function createMockStore(): RootStore {
  class Test (line 424) | class Test {
  class SuperTest (line 428) | class SuperTest extends Test {

FILE: packages/shared/setupTests.ts
  method constructor (line 30) | constructor(type: string, params: PointerEventInit = {}) {

FILE: packages/test-renderer/src/WebGL2RenderingContext.ts
  class WebGL2RenderingContext (line 716) | class WebGL2RenderingContext {
    method constructor (line 719) | constructor(canvas: HTMLCanvasElement) {
    method getParameter (line 743) | getParameter(paramId: number) {
    method getExtension (line 753) | getExtension(ext: string) {

FILE: packages/test-renderer/src/__tests__/RTTR.core.test.tsx
  type ExampleComp (line 7) | type ExampleComp = THREE.Mesh<THREE.BoxGeometry, THREE.Material>
  class Parent (line 80) | class Parent extends React.Component {
    method render (line 81) | render() {
  class Component (line 108) | class Component extends React.PureComponent {
    method componentDidMount (line 113) | componentDidMount() {
    method render (line 119) | render() {
  class Instance (line 175) | class Instance extends React.PureComponent {
    method handleStandard (line 178) | handleStandard() {
    method render (line 182) | render() {
  class Log (line 247) | class Log extends React.Component<{ name: string }> {
    method render (line 248) | render() {
    method componentDidMount (line 257) | componentDidMount() {
    method componentWillUnmount (line 260) | componentWillUnmount() {

FILE: packages/test-renderer/src/__tests__/RTTR.hooks.test.tsx
  class Loader (line 39) | class Loader extends THREE.Loader<THREE.Mesh, string> {
    method load (line 40) | load(url: string, onLoad: (mesh: THREE.Mesh) => void): void {

FILE: packages/test-renderer/src/createTestCanvas.ts
  class WebGLRenderingContext (line 32) | class WebGLRenderingContext extends WebGL2RenderingContext {}

FILE: packages/test-renderer/src/createTestInstance.ts
  class ReactThreeTestInstance (line 33) | class ReactThreeTestInstance<TObject extends THREE.Object3D = THREE.Obje...
    method constructor (line 36) | constructor(fiber: Instance<TObject>) {
    method fiber (line 40) | public get fiber(): Instance<TObject> {
    method instance (line 44) | public get instance(): TObject {
    method type (line 48) | public get type(): string {
    method props (line 52) | public get props(): Obj {
    method parent (line 56) | public get parent(): ReactThreeTestInstance | null {
    method children (line 64) | public get children(): ReactThreeTestInstance[] {
    method allChildren (line 68) | public get allChildren(): ReactThreeTestInstance[] {

FILE: packages/test-renderer/src/helpers/graph.ts
  function processThreeChildren (line 16) | function processThreeChildren(children: THREE.Object3D[]): SceneGraphIte...

FILE: packages/test-renderer/src/helpers/testInstance.ts
  type FindAllOptions (line 31) | interface FindAllOptions {

FILE: packages/test-renderer/src/helpers/waitFor.ts
  type WaitOptions (line 3) | interface WaitOptions {
  function waitFor (line 8) | async function waitFor(

FILE: packages/test-renderer/src/index.tsx
  method unmount (line 43) | async unmount() {
  method getInstance (line 48) | getInstance() {
  method update (line 59) | async update(newElement: React.ReactNode) {
  method toTree (line 66) | toTree() {
  method toGraph (line 69) | toGraph() {
  method advanceFrames (line 73) | async advanceFrames(frames: number, delta: number | number[] = 1) {

FILE: packages/test-renderer/src/types/internal.ts
  type CreateCanvasParameters (line 1) | type CreateCanvasParameters = {
  type Obj (line 7) | interface Obj {
  type MockEventData (line 17) | type MockEventData = {
  type TestInstanceChildOpts (line 21) | interface TestInstanceChildOpts {

FILE: packages/test-renderer/src/types/public.ts
  type MockSyntheticEvent (line 9) | type MockSyntheticEvent = {
  type CreateOptions (line 18) | type CreateOptions = CreateCanvasParameters & RenderProps<HTMLCanvasElem...
  type Renderer (line 20) | type Renderer = {
  type SceneGraphItem (line 31) | interface SceneGraphItem {
  type SceneGraph (line 37) | type SceneGraph = SceneGraphItem[]
  type TreeNode (line 39) | interface TreeNode {
  type Tree (line 47) | type Tree = TreeNode[]

FILE: vite.config.ts
  method transform (line 30) | transform(code, id) {
  method generateBundle (line 43) | generateBundle(_options, bundle) {
  method handler (line 57) | handler(code, { fileName }) {
Condensed preview — 173 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (849K chars).
[
  {
    "path": ".changeset/README.md",
    "chars": 510,
    "preview": "# Changesets\n\nHello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that wo"
  },
  {
    "path": ".changeset/config.json",
    "chars": 370,
    "preview": "{\n  \"$schema\": \"https://unpkg.com/@changesets/config@1.6.0/schema.json\",\n  \"changelog\": \"@changesets/changelog-git\",\n  \""
  },
  {
    "path": ".codesandbox/ci.json",
    "chars": 48,
    "preview": "{\n  \"sandboxes\": [\"/example\"],\n  \"node\": \"18\"\n}\n"
  },
  {
    "path": ".eslintignore",
    "chars": 26,
    "preview": "dist/\nnode_modules/\n.yarn/"
  },
  {
    "path": ".eslintrc.json",
    "chars": 2447,
    "preview": "{\n  \"env\": {\n    \"browser\": true,\n    \"es6\": true,\n    \"node\": true\n  },\n  \"extends\": [\n    \"prettier\",\n    \"plugin:pret"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 97,
    "preview": "# These are supported funding model platforms\n\ngithub: drcmda\nopen_collective: react-three-fiber\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 286,
    "preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n---\n\n👋 hi there, for i"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 105,
    "preview": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n---\n"
  },
  {
    "path": ".github/issue_template.md",
    "chars": 451,
    "preview": "Hi, 👋\n\nif this is about a bug, before you go ahead, please do us a favour and make sure to check the [threejs issue trac"
  },
  {
    "path": ".github/workflows/canary.yml",
    "chars": 1515,
    "preview": "name: Canary Release\n\non:\n  push:\n    branches: [v10]\n  workflow_dispatch:\n\npermissions:\n  id-token: write # Required fo"
  },
  {
    "path": ".github/workflows/docs.yml",
    "chars": 1216,
    "preview": "name: Build documentation and deploy to GitHub Pages\non:\n  push:\n    branches: ['master']\n  workflow_dispatch:\n\n# Cancel"
  },
  {
    "path": ".github/workflows/test.yml",
    "chars": 1836,
    "preview": "name: Test\non:\n  push:\n    branches:\n      - 'master'\n  pull_request: {}\njobs:\n  build:\n    name: Build, lint, and test "
  },
  {
    "path": ".gitignore",
    "chars": 331,
    "preview": "node_modules/\r\ncoverage/\r\ndist/\r\nbuild/\r\ntypes/\r\npackages/fiber/react-reconciler/\r\n# commit types in src\r\n!packages/*/sr"
  },
  {
    "path": ".husky/.gitignore",
    "chars": 2,
    "preview": "_\n"
  },
  {
    "path": ".husky/pre-commit",
    "chars": 68,
    "preview": "#!/bin/sh\n. \"$(dirname \"$0\")/_/husky.sh\"\n\nnpx pretty-quick --staged\n"
  },
  {
    "path": ".prettierignore",
    "chars": 82,
    "preview": "dist/\ncoverage/\nnode_modules/\npackages/fiber/react-reconciler/\n.yarn/\n*.gltf\n*.mdx"
  },
  {
    "path": ".prettierrc",
    "chars": 157,
    "preview": "{\n  \"semi\": false,\n  \"trailingComma\": \"all\",\n  \"singleQuote\": true,\n  \"tabWidth\": 2,\n  \"printWidth\": 120,\n  \"bracketSame"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 2663,
    "preview": "## Contributing\n\nThis project uses [semantic commits](https://conventionalcommits.org) and [semver](https://semver.org)."
  },
  {
    "path": "LICENSE",
    "chars": 1072,
    "preview": "MIT License\n\nCopyright (c) 2019-2025 Poimandres\n\nPermission is hereby granted, free of charge, to any person obtaining a"
  },
  {
    "path": "babel.config.js",
    "chars": 650,
    "preview": "module.exports = {\n  plugins: [],\n  presets: [\n    [\n      '@babel/preset-env',\n      {\n        include: [\n          '@b"
  },
  {
    "path": "docs/API/additional-exports.mdx",
    "chars": 1662,
    "preview": "---\ntitle: Additional Exports\nnav: 8\n---\n\n| export               | usage                                                "
  },
  {
    "path": "docs/API/canvas.mdx",
    "chars": 10584,
    "preview": "---\ntitle: Canvas\ndescription: The Canvas object is your portal into three.js\nnav: 4\n---\n\nThe `Canvas` object is where y"
  },
  {
    "path": "docs/API/events.mdx",
    "chars": 8325,
    "preview": "---\ntitle: Events\ndescription: All the events you can hook up to\nnav: 7\n---\n\n`three.js` objects that implement their own"
  },
  {
    "path": "docs/API/hooks.mdx",
    "chars": 16234,
    "preview": "---\ntitle: Hooks\ndescription: Hooks are the heart of react-three-fiber\nnav: 6\n---\n\nHooks allow you to tie or request spe"
  },
  {
    "path": "docs/API/objects.mdx",
    "chars": 7813,
    "preview": "---\ntitle: Objects, properties and constructor arguments\ndescription: All the effective ways of using React Three Fiber\n"
  },
  {
    "path": "docs/API/testing.mdx",
    "chars": 4037,
    "preview": "---\ntitle: 'Testing'\ndescription: How to handle unit tests\nnav: 10\n---\n\nLike with every other application testing is an "
  },
  {
    "path": "docs/API/typescript.mdx",
    "chars": 4618,
    "preview": "---\ntitle: TypeScript\ndescription: Common scenarios and how to approach them with TypeScript\nnav: 9\n---\n\n## Typing with "
  },
  {
    "path": "docs/advanced/pitfalls.mdx",
    "chars": 7533,
    "preview": "---\ntitle: Performance pitfalls\ndescription: Performance 1x1\nnav: 12\n---\n\n## Tips and Tricks\n\nThis is a good overview: h"
  },
  {
    "path": "docs/advanced/scaling-performance.mdx",
    "chars": 15463,
    "preview": "---\ntitle: Scaling performance\ndescription: This is a short primer on how to scale performance.\nnav: 11\n---\n\nRunning Web"
  },
  {
    "path": "docs/getting-started/basic-example-sandpack/index.jsx",
    "chars": 1367,
    "preview": "import { createRoot } from 'react-dom/client'\nimport React, { useRef, useState } from 'react'\nimport { Canvas, useFrame "
  },
  {
    "path": "docs/getting-started/basic-example-sandpack/styles.css",
    "chars": 55,
    "preview": "html,\nbody,\n#root {\n  height: 100%;\n  margin: unset;\n}\n"
  },
  {
    "path": "docs/getting-started/community-r3f-components.mdx",
    "chars": 6139,
    "preview": "---\ntitle: Community R3F Components\ndescription: This page showcases some React Three Fiber/r3f community components tha"
  },
  {
    "path": "docs/getting-started/examples.mdx",
    "chars": 9654,
    "preview": "---\ntitle: Examples\ndescription: A few examples that demonstrate what you can do with React Three Fiber\nnav: 3\n---\n\n## S"
  },
  {
    "path": "docs/getting-started/installation.mdx",
    "chars": 5497,
    "preview": "---\ntitle: Installation\ndescription: Learn how to install react-three-fiber\nnav: 1\n---\n\n```bash\nnpm install three @react"
  },
  {
    "path": "docs/getting-started/introduction.mdx",
    "chars": 9381,
    "preview": "---\ntitle: Introduction\ndescription: React-three-fiber is a React renderer for three.js.\nnav: 0\n---\n\n<Intro>\n  Build you"
  },
  {
    "path": "docs/getting-started/your-first-scene.mdx",
    "chars": 5592,
    "preview": "---\ntitle: Your first scene\ndescription: This guide will help you setup your first React Three Fiber scene and introduce"
  },
  {
    "path": "docs/tutorials/basic-animations.mdx",
    "chars": 3392,
    "preview": "---\ntitle: Basic Animations\ndescription: This guide will help you understand refs, useFrame and how to make basic animat"
  },
  {
    "path": "docs/tutorials/events-and-interaction.mdx",
    "chars": 2756,
    "preview": "---\ntitle: 'Events and Interaction'\ndescription: Let's make our meshes react to user input.\nnav: 14\n---\n\nThis tutorial w"
  },
  {
    "path": "docs/tutorials/how-it-works.mdx",
    "chars": 5895,
    "preview": "---\ntitle: How does it work?\ndescription: This is an advanced guide on the inner workings of Fiber, if you are just gett"
  },
  {
    "path": "docs/tutorials/loading-models.mdx",
    "chars": 5686,
    "preview": "---\ntitle: 'Loading Models'\ndescription: 3D Software to the web!\nnav: 15\n---\n\n> All the models in this page were created"
  },
  {
    "path": "docs/tutorials/loading-textures.mdx",
    "chars": 4304,
    "preview": "---\ntitle: 'Loading Textures'\ndescription: Let's load some fancy textures.\nnav: 16\n---\n\n> All textures used in this chap"
  },
  {
    "path": "docs/tutorials/v9-migration-guide.mdx",
    "chars": 8822,
    "preview": "---\ntitle: 'v9 Migration Guide'\ndescription: Changes and new features with v9 and React 19\nnav: 13\n---\n\nThis is a compat"
  },
  {
    "path": "example/.gitignore",
    "chars": 45,
    "preview": "node_modules\n.DS_Store\ndist\ndist-ssr\n*.local\n"
  },
  {
    "path": "example/CHANGELOG.md",
    "chars": 282,
    "preview": "# example\n\n## 1.1.0\n\n### Minor Changes\n\n- 85c80e70: eventsource and eventprefix on the canvas component\n\n## 1.0.0\n\n### M"
  },
  {
    "path": "example/index.html",
    "chars": 377,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"f"
  },
  {
    "path": "example/package.json",
    "chars": 742,
    "preview": "{\n  \"name\": \"example\",\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite bu"
  },
  {
    "path": "example/public/apple.gltf",
    "chars": 10407,
    "preview": "{\n  \"extensionsUsed\": [\"KHR_materials_unlit\", \"KHR_draco_mesh_compression\"],\n  \"asset\": { \"generator\": \"UniGLTF-1.27\", \""
  },
  {
    "path": "example/public/bottle.gltf",
    "chars": 5071,
    "preview": "{\n  \"extensionsUsed\": [\"KHR_materials_unlit\", \"KHR_draco_mesh_compression\"],\n  \"asset\": { \"generator\": \"UniGLTF-1.27\", \""
  },
  {
    "path": "example/public/farm.gltf",
    "chars": 155334,
    "preview": "{\n  \"asset\": { \"generator\": \"Khronos glTF Blender I/O v1.5.17\", \"version\": \"2.0\" },\n  \"scene\": 0,\n  \"scenes\": [{ \"name\":"
  },
  {
    "path": "example/public/lightning.gltf",
    "chars": 12557,
    "preview": "{\n  \"asset\": {\n    \"generator\": \"Khronos glTF Blender I/O v1.5.17\",\n    \"version\": \"2.0\"\n  },\n  \"scene\": 0,\n  \"scenes\": "
  },
  {
    "path": "example/public/ramen.gltf",
    "chars": 14756,
    "preview": "{\n  \"extensionsUsed\": [\"KHR_materials_unlit\", \"KHR_draco_mesh_compression\"],\n  \"asset\": { \"generator\": \"UniGLTF-1.27\", \""
  },
  {
    "path": "example/src/App.tsx",
    "chars": 1831,
    "preview": "import * as React from 'react'\nimport { useErrorBoundary } from 'use-error-boundary'\nimport { Redirect, Route, useRoute "
  },
  {
    "path": "example/src/components.tsx",
    "chars": 667,
    "preview": "import * as React from 'react'\nimport { type LinkProps, Link } from 'wouter'\n\nexport const Page = (props: { children?: R"
  },
  {
    "path": "example/src/demos/Activity.tsx",
    "chars": 2560,
    "preview": "import { useRef, useEffectEvent, Suspense, use, useState, Activity } from 'react'\nimport { useFrame, Canvas } from '@rea"
  },
  {
    "path": "example/src/demos/AutoDispose.tsx",
    "chars": 1788,
    "preview": "import { Canvas, type ThreeElements, useFrame } from '@react-three/fiber'\nimport { useRef, useState } from 'react'\nimpor"
  },
  {
    "path": "example/src/demos/ChangeTexture.tsx",
    "chars": 750,
    "preview": "import { useTexture } from '@react-three/drei'\nimport { Canvas } from '@react-three/fiber'\nimport { useDeferredValue, us"
  },
  {
    "path": "example/src/demos/ClickAndHover.tsx",
    "chars": 1245,
    "preview": "import { Canvas, type ThreeElements, useFrame } from '@react-three/fiber'\nimport { useRef, useState } from 'react'\nimpor"
  },
  {
    "path": "example/src/demos/ContextMenuOverride.tsx",
    "chars": 809,
    "preview": "import { Canvas } from '@react-three/fiber'\nimport { useState } from 'react'\n\nexport default function App() {\n  const [s"
  },
  {
    "path": "example/src/demos/FlushSync.tsx",
    "chars": 1347,
    "preview": "import { Canvas, flushSync, useThree } from '@react-three/fiber'\nimport { useCallback, useRef, useState } from 'react'\n\n"
  },
  {
    "path": "example/src/demos/Gestures.tsx",
    "chars": 1600,
    "preview": "import { Canvas, useFrame, useThree } from '@react-three/fiber'\nimport { useDrag } from '@use-gesture/react'\nimport { us"
  },
  {
    "path": "example/src/demos/Gltf.tsx",
    "chars": 687,
    "preview": "import { Canvas, useLoader } from '@react-three/fiber'\nimport { Suspense, useEffect, useReducer } from 'react'\nimport { "
  },
  {
    "path": "example/src/demos/Inject.tsx",
    "chars": 1566,
    "preview": "import { Canvas, createPortal, getRootState, type ThreeElements, useThree } from '@react-three/fiber'\nimport { useEffect"
  },
  {
    "path": "example/src/demos/Layers.tsx",
    "chars": 1166,
    "preview": "import { Canvas, type ThreeElements } from '@react-three/fiber'\nimport { useEffect, useReducer } from 'react'\nimport * a"
  },
  {
    "path": "example/src/demos/Lines.tsx",
    "chars": 1954,
    "preview": "import { Line } from '@react-three/drei'\nimport { Canvas, type ThreeElements, type ThreeEvent, type Vector3 } from '@rea"
  },
  {
    "path": "example/src/demos/MultiMaterial.tsx",
    "chars": 3764,
    "preview": "import { Canvas, type ThreeElements } from '@react-three/fiber'\nimport { useEffect, useMemo, useRef, useState } from 're"
  },
  {
    "path": "example/src/demos/MultiRender.tsx",
    "chars": 1105,
    "preview": "import { Canvas, useFrame } from '@react-three/fiber'\nimport { useEffect, useRef, useState } from 'react'\nimport * as TH"
  },
  {
    "path": "example/src/demos/MultiView.tsx",
    "chars": 5693,
    "preview": "import {\n  ArcballControls,\n  Bounds,\n  CameraShake,\n  Environment,\n  OrbitControls,\n  OrthographicCamera,\n  Perspective"
  },
  {
    "path": "example/src/demos/Pointcloud.tsx",
    "chars": 2161,
    "preview": "import { Canvas, ThreeEvent, extend } from '@react-three/fiber'\nimport { useCallback, useMemo, useRef } from 'react'\nimp"
  },
  {
    "path": "example/src/demos/Portals.tsx",
    "chars": 5207,
    "preview": "import { Environment, OrbitControls, useFBO, useGLTF } from '@react-three/drei'\nimport { Canvas, ComputeFunction, create"
  },
  {
    "path": "example/src/demos/Reparenting.tsx",
    "chars": 1393,
    "preview": "import { Canvas, createPortal } from '@react-three/fiber'\nimport { useCallback, useEffect, useReducer, useState } from '"
  },
  {
    "path": "example/src/demos/ResetProps.tsx",
    "chars": 3027,
    "preview": "import { OrbitControls } from '@react-three/drei'\nimport { Canvas, useFrame, useThree } from '@react-three/fiber'\nimport"
  },
  {
    "path": "example/src/demos/SVGRenderer.tsx",
    "chars": 1166,
    "preview": "import { Canvas, useFrame } from '@react-three/fiber'\nimport { useEffect, useRef, useState } from 'react'\nimport * as TH"
  },
  {
    "path": "example/src/demos/Selection.tsx",
    "chars": 2054,
    "preview": "import { Canvas } from '@react-three/fiber'\nimport { useState } from 'react'\n\nfunction Sphere() {\n  const [hovered, setH"
  },
  {
    "path": "example/src/demos/StopPropagation.tsx",
    "chars": 3042,
    "preview": "import { Environment, OrbitControls, useGLTF } from '@react-three/drei'\nimport { Canvas, createPortal, type ThreeElement"
  },
  {
    "path": "example/src/demos/SuspenseAndErrors.tsx",
    "chars": 1177,
    "preview": "import * as React from 'react'\nimport { useState, useEffect } from 'react'\nimport { Canvas, useLoader } from '@react-thr"
  },
  {
    "path": "example/src/demos/SuspenseMaterial.tsx",
    "chars": 805,
    "preview": "import { Canvas } from '@react-three/fiber'\nimport { Suspense, useReducer } from 'react'\nimport { suspend } from 'suspen"
  },
  {
    "path": "example/src/demos/Test.tsx",
    "chars": 1658,
    "preview": "import * as THREE from 'three'\nimport { Canvas, useFrame } from '@react-three/fiber'\nimport { OrbitControls, Hud } from "
  },
  {
    "path": "example/src/demos/ViewTracking.tsx",
    "chars": 8549,
    "preview": "import { Environment, OrbitControls, PerspectiveCamera, Preload, TransformControls, useGLTF } from '@react-three/drei'\ni"
  },
  {
    "path": "example/src/demos/Viewcube.tsx",
    "chars": 2224,
    "preview": "import { OrbitControls } from '@react-three/drei'\nimport { Canvas, createPortal, useFrame, useThree } from '@react-three"
  },
  {
    "path": "example/src/demos/WebGPU.tsx",
    "chars": 1788,
    "preview": "import { Canvas, extend, type ThreeToJSXElements, useFrame, type ThreeElements } from '@react-three/fiber'\nimport { easi"
  },
  {
    "path": "example/src/demos/index.tsx",
    "chars": 2286,
    "preview": "import { lazy } from 'react'\n\nconst Activity = { Component: lazy(() => import('./Activity')) }\nconst AutoDispose = { Com"
  },
  {
    "path": "example/src/index.tsx",
    "chars": 140,
    "preview": "import * as ReactDOM from 'react-dom/client'\nimport App from './App'\n\nReactDOM.createRoot(document.getElementById('root'"
  },
  {
    "path": "example/src/styles.css",
    "chars": 2895,
    "preview": "/* @import url('@pmndrs/branding/styles.css'); */\n@import url('https://rsms.me/inter/inter.css');\n\n.pmndrs-menu {\n  font"
  },
  {
    "path": "example/tsconfig.json",
    "chars": 511,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"ESNext\",\n    \"lib\": [\"DOM\", \"DOM.Iterable\", \"ESNext\"],\n    \"allowJs\": false,\n   "
  },
  {
    "path": "example/vite.config.ts",
    "chars": 193,
    "preview": "import { defineConfig } from 'vite'\nimport react from '@vitejs/plugin-react'\n\nexport default defineConfig({\n  optimizeDe"
  },
  {
    "path": "jest.config.js",
    "chars": 811,
    "preview": "/** @type {import('jest').Config} */\nmodule.exports = {\n  preset: 'ts-jest',\n  testEnvironment: 'jsdom',\n  testPathIgnor"
  },
  {
    "path": "package.json",
    "chars": 2933,
    "preview": "{\n  \"name\": \"react-three-fiber--root\",\n  \"version\": \"0.0.0\",\n  \"license\": \"MIT\",\n  \"private\": true,\n  \"workspaces\": [\n  "
  },
  {
    "path": "packages/eslint-plugin/.npmignore",
    "chars": 23,
    "preview": "scripts/\nsrc/\nindex.js\n"
  },
  {
    "path": "packages/eslint-plugin/CHANGELOG.md",
    "chars": 260,
    "preview": "# @react-three/eslint-plugin\n\n## 0.1.2\n\n### Patch Changes\n\n- 6c907263: fix(eslint-plugin): include type declare files\n\n#"
  },
  {
    "path": "packages/eslint-plugin/README.md",
    "chars": 3200,
    "preview": "# @react-three/eslint-plugin\n\n[![Version](https://img.shields.io/npm/v/@react-three/eslint-plugin?style=flat&colorA=0000"
  },
  {
    "path": "packages/eslint-plugin/docs/rules/no-clone-in-loop.md",
    "chars": 1260,
    "preview": "Cloning vectors in the frame loop instantiates new objects wasting large amounts of memory,\nwhich is especially bad for "
  },
  {
    "path": "packages/eslint-plugin/docs/rules/no-new-in-loop.md",
    "chars": 1241,
    "preview": "Instantiating new objects in the frame loop can waste large amounts of memory,\nwhich is especially bad for large CPU con"
  },
  {
    "path": "packages/eslint-plugin/package.json",
    "chars": 1325,
    "preview": "{\n  \"name\": \"@react-three/eslint-plugin\",\n  \"version\": \"0.1.2\",\n  \"description\": \"An ESLint plugin which provides lint r"
  },
  {
    "path": "packages/eslint-plugin/scripts/codegen.ts",
    "chars": 4489,
    "preview": "import type { Rule } from 'eslint'\nimport fs from 'fs/promises'\nimport { join, extname, relative } from 'path'\nimport { "
  },
  {
    "path": "packages/eslint-plugin/src/configs/all.ts",
    "chars": 236,
    "preview": "// THIS FILE WAS GENERATED DO NOT MODIFY BY HAND\n// @command yarn codegen:eslint\n\nexport default {\n  plugins: ['@react-t"
  },
  {
    "path": "packages/eslint-plugin/src/configs/recommended.ts",
    "chars": 236,
    "preview": "// THIS FILE WAS GENERATED DO NOT MODIFY BY HAND\n// @command yarn codegen:eslint\n\nexport default {\n  plugins: ['@react-t"
  },
  {
    "path": "packages/eslint-plugin/src/index.ts",
    "chars": 262,
    "preview": "// THIS FILE WAS GENERATED DO NOT MODIFY BY HAND\n// @command yarn codegen:eslint\n\nimport all from './configs/all'\nimport"
  },
  {
    "path": "packages/eslint-plugin/src/lib/url.ts",
    "chars": 156,
    "preview": "export function gitHubUrl(name: string) {\n  return `https://github.com/pmndrs/react-three-fiber/blob/master/packages/esl"
  },
  {
    "path": "packages/eslint-plugin/src/rules/index.ts",
    "chars": 262,
    "preview": "// THIS FILE WAS GENERATED DO NOT MODIFY BY HAND\n// @command yarn codegen:eslint\n\nimport noCloneInLoop from './no-clone-"
  },
  {
    "path": "packages/eslint-plugin/src/rules/no-clone-in-loop.ts",
    "chars": 856,
    "preview": "import type { Rule } from 'eslint'\nimport * as ESTree from 'estree'\nimport { gitHubUrl } from '../lib/url'\n\nconst rule: "
  },
  {
    "path": "packages/eslint-plugin/src/rules/no-new-in-loop.ts",
    "chars": 812,
    "preview": "import type { Rule } from 'eslint'\nimport * as ESTree from 'estree'\nimport { gitHubUrl } from '../lib/url'\n\nconst rule: "
  },
  {
    "path": "packages/eslint-plugin/tests/rules/no-clone-in-loop.test.ts",
    "chars": 629,
    "preview": "import { RuleTester } from 'eslint'\nimport rule from '../../src/rules/no-clone-in-loop'\n\nconst tester = new RuleTester({"
  },
  {
    "path": "packages/eslint-plugin/tests/rules/no-new-in-loop.test.ts",
    "chars": 1069,
    "preview": "import { RuleTester } from 'eslint'\nimport rule from '../../src/rules/no-new-in-loop'\n\nconst tester = new RuleTester({\n "
  },
  {
    "path": "packages/fiber/.npmignore",
    "chars": 82,
    "preview": "examples/\nexample/\n.codesandbox/\n.github/\n.husky/\nmarkdown/\n/src/\ntests/\n__mocks__"
  },
  {
    "path": "packages/fiber/CHANGELOG.md",
    "chars": 17955,
    "preview": "# @react-three/fiber\n\n## 9.5.0\n\n### Minor Changes\n\n- 1050a62bd4bc15e60ab3a65deea08dedfcf24989: Support React 19.2\n\n## 9."
  },
  {
    "path": "packages/fiber/__mocks__/expo-asset.ts",
    "chars": 499,
    "preview": "class Asset {\n  name = 'test asset'\n  type = 'glb'\n  hash = null\n  localUri: string | null = null\n  uri = 'test://null'\n"
  },
  {
    "path": "packages/fiber/__mocks__/expo-file-system.ts",
    "chars": 246,
    "preview": "export const EncodingType = { UTF8: 'utf8', Base64: 'base64' }\nexport const cacheDirectory = 'file:///test/'\nexport cons"
  },
  {
    "path": "packages/fiber/__mocks__/expo-gl.ts",
    "chars": 509,
    "preview": "import * as React from 'react'\nimport type { GLViewProps } from 'expo-gl'\nimport { WebGL2RenderingContext } from '@react"
  },
  {
    "path": "packages/fiber/__mocks__/react-native.ts",
    "chars": 972,
    "preview": "import * as React from 'react'\nimport { ViewProps, LayoutChangeEvent } from 'react-native'\n\nexport class View extends Re"
  },
  {
    "path": "packages/fiber/__mocks__/react-use-measure.ts",
    "chars": 427,
    "preview": "import * as React from 'react'\n\nexport default function useMeasure() {\n  const element = React.useRef<HTMLElement | null"
  },
  {
    "path": "packages/fiber/native/package.json",
    "chars": 158,
    "preview": "{\n  \"main\": \"dist/react-three-fiber-native.cjs.js\",\n  \"module\": \"dist/react-three-fiber-native.esm.js\",\n  \"types\": \"dist"
  },
  {
    "path": "packages/fiber/package.json",
    "chars": 2205,
    "preview": "{\n  \"name\": \"@react-three/fiber\",\n  \"version\": \"9.5.0\",\n  \"description\": \"A React renderer for Threejs\",\n  \"keywords\": ["
  },
  {
    "path": "packages/fiber/readme.md",
    "chars": 10105,
    "preview": "<h1>react-three-fiber</h1>\n\n[![Version](https://img.shields.io/npm/v/@react-three/fiber?style=flat&colorA=000000&colorB="
  },
  {
    "path": "packages/fiber/src/core/events.ts",
    "chars": 21693,
    "preview": "import * as THREE from 'three'\nimport { type Properties, getRootState } from './utils'\nimport type { Instance } from './"
  },
  {
    "path": "packages/fiber/src/core/hooks.tsx",
    "chars": 6191,
    "preview": "import * as THREE from 'three'\nimport * as React from 'react'\nimport { suspend, preload, clear } from 'suspend-react'\nim"
  },
  {
    "path": "packages/fiber/src/core/index.tsx",
    "chars": 1125,
    "preview": "export type {\n  Intersection,\n  ThreeEvent,\n  DomEvent,\n  Events,\n  EventHandlers,\n  FilterFunction,\n  ComputeFunction,\n"
  },
  {
    "path": "packages/fiber/src/core/loop.ts",
    "chars": 5494,
    "preview": "import { _roots } from './renderer'\nimport type { RootState, Subscription } from './store'\n\nexport type GlobalRenderCall"
  },
  {
    "path": "packages/fiber/src/core/reconciler.tsx",
    "chars": 22348,
    "preview": "import packageData from '../../package.json'\nimport * as THREE from 'three'\nimport * as React from 'react'\nimport Reconc"
  },
  {
    "path": "packages/fiber/src/core/renderer.tsx",
    "chars": 20495,
    "preview": "import * as React from 'react'\nimport { ConcurrentRoot } from '../../react-reconciler/constants.js'\nimport * as THREE fr"
  },
  {
    "path": "packages/fiber/src/core/store.ts",
    "chars": 12067,
    "preview": "import * as THREE from 'three'\nimport * as React from 'react'\nimport { type StoreApi } from 'zustand'\nimport { createWit"
  },
  {
    "path": "packages/fiber/src/core/utils.tsx",
    "chars": 19139,
    "preview": "import * as THREE from 'three'\nimport * as React from 'react'\nimport { useFiber, traverseFiber, useContextBridge } from "
  },
  {
    "path": "packages/fiber/src/index.tsx",
    "chars": 219,
    "preview": "import * as ReactThreeFiber from './three-types'\nexport { ReactThreeFiber }\nexport * from './three-types'\nexport * from "
  },
  {
    "path": "packages/fiber/src/native/Canvas.tsx",
    "chars": 7945,
    "preview": "import * as React from 'react'\nimport * as THREE from 'three'\nimport {\n  View,\n  type ViewProps,\n  type ViewStyle,\n  typ"
  },
  {
    "path": "packages/fiber/src/native/events.ts",
    "chars": 2689,
    "preview": "import { RootState, RootStore } from '../core/store'\nimport { createEvents, DomEvent, EventManager, Events } from '../co"
  },
  {
    "path": "packages/fiber/src/native/polyfills.ts",
    "chars": 6023,
    "preview": "import * as THREE from 'three'\nimport { Image, NativeModules, Platform } from 'react-native'\nimport { Asset } from 'expo"
  },
  {
    "path": "packages/fiber/src/native.tsx",
    "chars": 351,
    "preview": "import * as ReactThreeFiber from './three-types'\nexport { ReactThreeFiber }\nexport * from './three-types'\nexport * from "
  },
  {
    "path": "packages/fiber/src/three-types.ts",
    "chars": 3149,
    "preview": "import type * as THREE from 'three'\nimport type {} from 'react'\nimport type {} from 'react/jsx-runtime'\nimport type {} f"
  },
  {
    "path": "packages/fiber/src/web/Canvas.tsx",
    "chars": 5451,
    "preview": "import * as React from 'react'\nimport * as THREE from 'three'\nimport useMeasure, { Options as ResizeOptions } from 'reac"
  },
  {
    "path": "packages/fiber/src/web/events.ts",
    "chars": 2604,
    "preview": "import { RootState, RootStore } from '../core/store'\nimport { EventManager, Events, createEvents, DomEvent } from '../co"
  },
  {
    "path": "packages/fiber/tests/__snapshots__/canvas.native.test.tsx.snap",
    "chars": 513,
    "preview": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`native Canvas should correctly mount 1`] = `\"{\\\\\"type\\\\\":\\\\\"view\\\\\""
  },
  {
    "path": "packages/fiber/tests/__snapshots__/canvas.test.tsx.snap",
    "chars": 460,
    "preview": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`web Canvas should correctly mount 1`] = `\n<div>\n  <div\n    style=\"p"
  },
  {
    "path": "packages/fiber/tests/__snapshots__/index.test.tsx.snap",
    "chars": 1570,
    "preview": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`exports matches public API 1`] = `\nArray [\n  \"Act\",\n  \"Args\",\n  \"At"
  },
  {
    "path": "packages/fiber/tests/__snapshots__/utils.test.ts.snap",
    "chars": 445,
    "preview": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`updateCamera updates camera matrices 1`] = `\nArray [\n  2.1445069205"
  },
  {
    "path": "packages/fiber/tests/canvas.native.test.tsx",
    "chars": 1452,
    "preview": "import * as React from 'react'\nimport { View } from 'react-native'\n// @ts-ignore TS2305 remove with modern TS config\nimp"
  },
  {
    "path": "packages/fiber/tests/canvas.test.tsx",
    "chars": 1654,
    "preview": "import React from 'react'\nimport { render } from '@testing-library/react'\nimport { Canvas, act } from '../src'\n\ndescribe"
  },
  {
    "path": "packages/fiber/tests/events.test.tsx",
    "chars": 15115,
    "preview": "import * as React from 'react'\nimport { render, fireEvent, RenderResult } from '@testing-library/react'\nimport { Canvas,"
  },
  {
    "path": "packages/fiber/tests/hooks.test.tsx",
    "chars": 7381,
    "preview": "import * as React from 'react'\nimport * as THREE from 'three'\nimport { createCanvas } from '@react-three/test-renderer/s"
  },
  {
    "path": "packages/fiber/tests/index.test.tsx",
    "chars": 9229,
    "preview": "import * as React from 'react'\nimport * as THREE from 'three'\nimport ts from 'typescript'\nimport * as path from 'path'\ni"
  },
  {
    "path": "packages/fiber/tests/polyfills.test.ts",
    "chars": 1419,
    "preview": "import * as THREE from 'three'\nimport { polyfills } from '../src/native/polyfills'\n\npolyfills()\n\nconst pixel =\n  'data:i"
  },
  {
    "path": "packages/fiber/tests/reconciler.test.ts",
    "chars": 2286,
    "preview": "import * as THREE from 'three'\nimport { createCanvas } from '@react-three/test-renderer/src/createTestCanvas'\n\nasync fun"
  },
  {
    "path": "packages/fiber/tests/renderer.test.tsx",
    "chars": 28871,
    "preview": "import * as React from 'react'\nimport * as THREE from 'three'\nimport { ReconcilerRoot, createRoot, act, extend, ThreeEle"
  },
  {
    "path": "packages/fiber/tests/utils.test.ts",
    "chars": 18620,
    "preview": "import * as THREE from 'three'\nimport { type RootStore, type Instance, act, createRoot } from '../src'\nimport {\n  is,\n  "
  },
  {
    "path": "packages/shared/setupTests.ts",
    "chars": 1593,
    "preview": "import * as THREE from 'three'\nimport { WebGL2RenderingContext } from '@react-three/test-renderer/src/WebGL2RenderingCon"
  },
  {
    "path": "packages/test-renderer/.npmignore",
    "chars": 15,
    "preview": "/src/\nmarkdown/"
  },
  {
    "path": "packages/test-renderer/CHANGELOG.md",
    "chars": 8083,
    "preview": "# @react-three/test-renderer\n\n## 9.1.0\n\n### Minor Changes\n\n- 31781e5a1fdc464cb67617cc3d7bc5d8690cd4cd: feat(RTTR): handl"
  },
  {
    "path": "packages/test-renderer/README.md",
    "chars": 2768,
    "preview": "# React Three Test Renderer ⚛️🔼🧪\n\n[![Version](https://img.shields.io/npm/v/@react-three/test-renderer?style=flat&colorA="
  },
  {
    "path": "packages/test-renderer/markdown/rttr-instance.md",
    "chars": 3951,
    "preview": "# React Three Test Instance API\n\n## Table of Contents\n\n- [`ReactThreeTestInstance`](#instance)\n  - Properties\n    - [`in"
  },
  {
    "path": "packages/test-renderer/markdown/rttr.md",
    "chars": 4629,
    "preview": "# React Three Test Renderer API\n\n## Table of Contents\n\n- [`create()`](#create)\n  - [`scene`](#create-scene)\n  - [`getIns"
  },
  {
    "path": "packages/test-renderer/package.json",
    "chars": 812,
    "preview": "{\n  \"name\": \"@react-three/test-renderer\",\n  \"version\": \"9.1.0\",\n  \"description\": \"Test Renderer for react-three-fiber\",\n"
  },
  {
    "path": "packages/test-renderer/src/WebGL2RenderingContext.ts",
    "chars": 18816,
    "preview": "const functions = [\n  'activeTexture',\n  'attachShader',\n  'beginQuery',\n  'beginTransformFeedback',\n  'bindAttribLocati"
  },
  {
    "path": "packages/test-renderer/src/__tests__/RTTR.core.test.tsx",
    "chars": 12841,
    "preview": "import { useFrame } from '@react-three/fiber'\nimport * as React from 'react'\nimport * as THREE from 'three'\n\nimport Reac"
  },
  {
    "path": "packages/test-renderer/src/__tests__/RTTR.events.test.tsx",
    "chars": 2036,
    "preview": "import * as React from 'react'\n\nimport ReactThreeTestRenderer from '../index'\nimport type { ReactThreeTest } from '../in"
  },
  {
    "path": "packages/test-renderer/src/__tests__/RTTR.hooks.test.tsx",
    "chars": 2310,
    "preview": "import * as React from 'react'\nimport * as THREE from 'three'\nimport { useFrame, useLoader, useThree } from '@react-thre"
  },
  {
    "path": "packages/test-renderer/src/__tests__/RTTR.methods.test.tsx",
    "chars": 3532,
    "preview": "import * as React from 'react'\n\nimport ReactThreeTestRenderer from '../index'\n\ndescribe('ReactThreeTestRenderer instance"
  },
  {
    "path": "packages/test-renderer/src/__tests__/__snapshots__/RTTR.core.test.tsx.snap",
    "chars": 9802,
    "preview": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`ReactThreeTestRenderer Core can render a composite component & corr"
  },
  {
    "path": "packages/test-renderer/src/createTestCanvas.ts",
    "chars": 1334,
    "preview": "import { WebGL2RenderingContext } from './WebGL2RenderingContext'\nimport type { CreateCanvasParameters } from './types/i"
  },
  {
    "path": "packages/test-renderer/src/createTestInstance.ts",
    "chars": 4176,
    "preview": "import type * as THREE from 'three'\nimport type { Instance } from '@react-three/fiber'\n\nimport type { Obj, TestInstanceC"
  },
  {
    "path": "packages/test-renderer/src/fireEvent.ts",
    "chars": 1966,
    "preview": "import type { RootStore } from '@react-three/fiber'\n\nimport { toEventHandlerName } from './helpers/strings'\n\nimport { Re"
  },
  {
    "path": "packages/test-renderer/src/helpers/events.ts",
    "chars": 378,
    "preview": "import type { MockEventData } from '../types/internal'\n\nexport const calculateDistance = (event: MockEventData) => {\n  i"
  },
  {
    "path": "packages/test-renderer/src/helpers/graph.ts",
    "chars": 1204,
    "preview": "import type { Instance } from '@react-three/fiber'\nimport type { SceneGraphItem } from '../types/public'\nimport type * a"
  },
  {
    "path": "packages/test-renderer/src/helpers/strings.ts",
    "chars": 221,
    "preview": "export const lowerCaseFirstLetter = (str: string) => `${str.charAt(0).toLowerCase()}${str.slice(1)}`\n\nexport const toEve"
  },
  {
    "path": "packages/test-renderer/src/helpers/testInstance.ts",
    "chars": 1660,
    "preview": "import type { ReactThreeTestInstance } from '../createTestInstance'\nimport type { Obj } from '../types/internal'\n\nexport"
  },
  {
    "path": "packages/test-renderer/src/helpers/tree.ts",
    "chars": 706,
    "preview": "import * as THREE from 'three'\nimport type { Instance } from '@react-three/fiber'\nimport type { TreeNode, Tree } from '."
  },
  {
    "path": "packages/test-renderer/src/helpers/waitFor.ts",
    "chars": 613,
    "preview": "import { act } from '@react-three/fiber'\n\nexport interface WaitOptions {\n  interval?: number\n  timeout?: number\n}\n\nexpor"
  },
  {
    "path": "packages/test-renderer/src/index.tsx",
    "chars": 2942,
    "preview": "import * as React from 'react'\nimport * as THREE from 'three'\n\nimport { extend, _roots as mockRoots, createRoot, reconci"
  },
  {
    "path": "packages/test-renderer/src/types/index.ts",
    "chars": 25,
    "preview": "export * from './public'\n"
  },
  {
    "path": "packages/test-renderer/src/types/internal.ts",
    "chars": 442,
    "preview": "export type CreateCanvasParameters = {\n  beforeReturn?: (canvas: HTMLCanvasElement) => void\n  width?: number\n  height?: "
  },
  {
    "path": "packages/test-renderer/src/types/public.ts",
    "chars": 1286,
    "preview": "import type { Camera, RenderProps } from '@react-three/fiber'\n\nimport { ReactThreeTestInstance } from '../createTestInst"
  },
  {
    "path": "readme.md",
    "chars": 14428,
    "preview": "<h1>@react-three/fiber</h1>\n\n[![Version](https://img.shields.io/npm/v/@react-three/fiber?style=flat&colorA=000000&colorB"
  },
  {
    "path": "tsconfig.json",
    "chars": 547,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"es6\",\n    \"lib\": [\"es2019\", \"dom\"],\n    \"module\": \"commonjs\",\n    \"moduleResolut"
  },
  {
    "path": "vite.config.ts",
    "chars": 1951,
    "preview": "import { defineConfig, transformWithEsbuild } from 'vite'\nimport * as path from 'node:path'\nimport * as fs from 'node:fs"
  }
]

// ... and 2 more files (download for full content)

About this extraction

This page contains the full source code of the pmndrs/react-three-fiber GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 173 files (792.4 KB), approximately 284.4k tokens, and a symbol index with 415 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!