Browse Source

chore: linting and formatting (#389)

* docs: updated contribuition guide

* chore: lint

* chore: lint fix playground

* chore: lint docs

* chore: fix docs build
Alvaro Saburido 1 year ago
parent
commit
bd573a6d0b
81 changed files with 2085 additions and 1002 deletions
  1. 3 1
      .eslintignore
  2. 0 38
      .eslintrc.cjs
  3. 7 0
      .eslintrc.json
  4. 0 4
      .prettierrc.cjs
  5. 31 10
      CONTRIBUTING.md
  6. 4 0
      docs/.eslintrc.json
  7. 3 3
      docs/.vitepress/config.ts
  8. 5 1
      docs/.vitepress/theme/components/DonutExample.vue
  9. 1 0
      docs/.vitepress/theme/components/EmbedExperiment.vue
  10. 15 4
      docs/.vitepress/theme/components/ExtendExample.vue
  11. 35 7
      docs/.vitepress/theme/components/FirstScene.vue
  12. 12 2
      docs/.vitepress/theme/components/FirstSceneLightToon.vue
  13. 281 266
      docs/.vitepress/theme/components/LocalOrbitControls.vue
  14. 9 6
      docs/.vitepress/theme/components/LoveVueThreeJS.vue
  15. 14 4
      docs/.vitepress/theme/components/StackBlitzEmbed.vue
  16. 1 0
      docs/.vitepress/theme/index.ts
  17. 5 5
      docs/package.json
  18. 2 2
      docs/vite.config.ts
  19. 10 9
      package.json
  20. 0 63
      playground/.eslintrc-auto-import.json
  21. 0 5
      playground/.eslintrc.cjs
  22. 7 0
      playground/.eslintrc.json
  23. 2 2
      playground/package.json
  24. 10 2
      playground/src/components/AnimatedModel.vue
  25. 28 18
      playground/src/components/Cameras.vue
  26. 4 1
      playground/src/components/DebugUI.vue
  27. 10 2
      playground/src/components/FBXModels.vue
  28. 112 92
      playground/src/components/LocalOrbitControls.vue
  29. 45 14
      playground/src/components/MultipleCanvas.vue
  30. 1 0
      playground/src/components/Responsiveness.vue
  31. 7 1
      playground/src/components/TestSphere.vue
  32. 8 3
      playground/src/components/Text3D.vue
  33. 28 5
      playground/src/components/TheBasic.vue
  34. 7 8
      playground/src/components/TheCameraOperator.vue
  35. 26 6
      playground/src/components/TheConditional.vue
  36. 45 9
      playground/src/components/TheEnvironment.vue
  37. 24 22
      playground/src/components/TheEvents.vue
  38. 41 10
      playground/src/components/TheExperience.vue
  39. 9 2
      playground/src/components/TheFirstScene.vue
  40. 27 7
      playground/src/components/TheGizmos.vue
  41. 26 5
      playground/src/components/TheGroups.vue
  42. 17 3
      playground/src/components/TheParticles.vue
  43. 16 3
      playground/src/components/TheSmallExperience.vue
  44. 5 1
      playground/src/components/TheSphere.vue
  45. 27 5
      playground/src/components/VectorSetProps.vue
  46. 10 3
      playground/src/components/gltf/TheModel.vue
  47. 17 3
      playground/src/components/gltf/index.vue
  48. 7 2
      playground/src/components/meshWobbleMaterial/index.vue
  49. 2 1
      playground/src/components/meshWobbleMaterial/material.ts
  50. 5 1
      playground/src/components/portal-journey/TheFireFlies.vue
  51. 30 27
      playground/src/components/portal-journey/ThePortal.vue
  52. 12 2
      playground/src/components/portal-journey/index.vue
  53. 12 4
      playground/src/components/shaders-experiment/index.vue
  54. 17 3
      playground/src/components/udsz/index.vue
  55. 1 0
      playground/src/pages/index.vue
  56. 48 14
      playground/src/pages/multiple-cameras.vue
  57. 1 0
      playground/src/pages/multiple.vue
  58. 13 4
      playground/src/pages/no-camera.vue
  59. 114 29
      playground/src/pages/shapes.vue
  60. 22 22
      playground/src/router.ts
  61. 1 1
      playground/vite.config.ts
  62. 570 0
      pnpm-lock.yaml
  63. 34 31
      src/components/TresCanvas.vue
  64. 5 6
      src/composables/useCamera/index.ts
  65. 2 2
      src/composables/useLoader/index.ts
  66. 1 0
      src/composables/useLogger.ts
  67. 8 9
      src/composables/usePointerEventHandler/index.ts
  68. 7 6
      src/composables/useRaycaster/index.ts
  69. 11 12
      src/composables/useRenderLoop/index.ts
  70. 26 28
      src/composables/useRenderer/index.ts
  71. 1 1
      src/composables/useSeek/index.ts
  72. 18 17
      src/composables/useTexture/index.ts
  73. 29 29
      src/composables/useTresContextProvider/index.ts
  74. 4 3
      src/core/catalogue.ts
  75. 24 25
      src/core/nodeOps.ts
  76. 6 9
      src/index.ts
  77. 14 12
      src/types/index.ts
  78. 36 37
      src/utils/index.ts
  79. 5 4
      src/utils/normalize.ts
  80. 1 1
      src/utils/template-compiler-options.ts
  81. 1 3
      src/utils/test-utils.ts

+ 3 - 1
.eslintignore

@@ -3,4 +3,6 @@ dist
 **.test.ts
 **.test.js
 **.cy.js
-**/cypress/**
+**/cypress/**
+docs/.vitepress/cache
+docs/.vitepress/dist

+ 0 - 38
.eslintrc.cjs

@@ -1,38 +0,0 @@
-module.exports = {
-  root: true,
-  env: {
-    node: true,
-    browser: true,
-    es6: true,
-  },
-  parser: 'vue-eslint-parser',
-  plugins: ['vue', '@typescript-eslint'],
-  extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'plugin:vue/vue3-recommended', 'prettier'],
-  parserOptions: {
-    tsconfigRootDir: __dirname,
-    parser: '@typescript-eslint/parser',
-    ecmaVersion: 2020,
-    sourceType: 'module',
-    allowImportExportEverywhere: true,
-  },
-  ignorePatterns: ['**/*.test.ts', 'packages/**/dist', 'package.json'],
-  rules: {
-    'arrow-parens': ['error', 'as-needed'],
-    'comma-dangle': 'off',
-    'space-before-function-paren': 'off',
-    'max-len': [1, { code: 120 }],
-    'require-jsdoc': 0,
-    'no-invalid-this': 0,
-    'import/no-absolute-path': 'off',
-    '@typescript-eslint/no-explicit-any': 'off',
-    '@typescript-eslint/no-empty-interface': 'off',
-    'vue/no-deprecated-slot-attribute': 'off',
-    'vue/require-default-prop': 'off',
-    'vue/html-self-closing': 'off',
-    'vue/max-attributes-per-line': 'off',
-    'vue/multi-word-component-names': 0,
-    'vue/no-multiple-template-root': 'off',
-    'vue/first-attribute-linebreak': 'off',
-    'vue/setup-compiler-macros': 0,
-  },
-}

+ 7 - 0
.eslintrc.json

@@ -0,0 +1,7 @@
+{
+  "extends": "@tresjs/eslint-config-vue",
+  "rules": {
+    "@typescript-eslint/no-use-before-define": "off"
+    /*     "@typescript-eslint/indent": "off" */
+  }
+}

+ 0 - 4
.prettierrc.cjs

@@ -1,4 +0,0 @@
-module.exports = {
-  ...require('@alvarosabu/prettier-config'),
-  printWidth: 120,
-}

+ 31 - 10
CONTRIBUTING.md

@@ -1,4 +1,4 @@
-![repository-banner.png](/public/repo-banner.png)
+![repository-banner.png](https://res.cloudinary.com/alvarosaburido/image/upload/v1683452574/repo-banner_d2xeem.png)
 
 # Tres Contributing Guide
 
@@ -8,9 +8,25 @@ No contribution is too small, whether it is a typo in the docs, a bug report or
 
 Thanks from the heart 💚 for taking the time to help out. This guide will help you to get started with the project.
 
+## Ecosystem
+- [@tresjs/core](https://github.com/Tresjs/tres) - The core package.
+- [@tresjs/cientos](https://github.com/Tresjs/cientos) - The abstractions package.
+- [@tresjs/postprocessing](https://github.com/Tresjs/post-processing) - The post-processing package.
+
 ## Setup
 
-Tresjs is a monorepo using [pnpm workspaces](https://pnpm.io/workspaces). Pnpm is a package manager that is faster than npm and yarn, and it also uses symlinks to avoid code duplication.
+All the packages in the ecosystem uses [pnpm workspaces](https://pnpm.io/workspaces). Pnpm is a package manager that is faster than npm and yarn, and it also uses symlinks to avoid code duplication.
+
+
+The `workspace` have the following structure:
+
+```
+.
+├── docs // The documentation
+├── playground // The playground to test the package
+├── src // The source code
+
+```
 
 Make sure you are using [Node.js](https://nodejs.org/en/) version 14 or higher.
 
@@ -28,21 +44,22 @@ If you have the package manager installed, you can install pnpm using the follow
 brew install pnpm
 ```
 
-To develop Tres core or any of the packages, run `pnpm install` in the root of the project. This will install all the dependencies and link the packages together. There is also a `postinstall` script that will build all the packages.
 
 ## Development
 
-TresJS is an ecosystem of packages, each one of them has its own purpose. The main package is `@tresjs/core` which is the core of the library. The other packages are plugins that extend the core functionality, like `@tresjs/cientos` which is a plugin that adds a bunch abstractions and composables to make it easier to create 3D scenes.
+To start developing, you can run `pnpm run playground` in the root folder.
+
+This will start the dev server for the playground `http://localhost:5174/` where you can test the changes you are making on the `src` folder. 
 
-### Core
+> **Important**
+> There is no need to run anything in the `src` folder or in the root, the `playground` will take care of it
 
-You can go to the `packages/tres` folder and run `pnpm dev` to start the dev server. This will start a vite server that will watch for changes in the code and rebuild the package.
 
-This is only a playground to test the core package, to keep the `App.vue` clean create a new component with your scene and import it in the `App.vue` file.
+Whenever you are working on a new feature or fixing a bug, make sure to add a demo under `playground/src/pages` and create a route in the `playground/src/router.ts` to test the changes you are making.
 
-### Cientos
+> **Warning**
+> Make sure to check if there is already a demo for the feature you are working on, if there is, you can add your changes to the existing demo.
 
-You can go to the `packages/cientos` folder and run `pnpm build --watch` to build the package and watch for changes. That way you can test the changes in the playground on the `packages/tres` folder.
 
 ### Docs
 
@@ -72,6 +89,10 @@ Before opening a pull request, make sure to run `pnpm lint` to make sure the cod
   - Create a `fix/{issue-number}-fix-test-in-core` branch for this bug fix.
   - If you are resolving a special issue, add `(fix #xxx[,#xxx])` (#xxx is the issue id) in your PR title for a better release log, e.g. `update entities encoding/decoding (fix #3899)`.
 
+## Third Party Libraries
+
+Adding a new third party library is generally discouraged, unless it is absolutely necessary. If you want to add a new library, please open an issue first to discuss the best approach.
+
 ## Keep core small
 
-The core package should be as small as possible, it should only contain the core functionality of the library. If you are adding a new feature, please consider adding it as a plugin instead, for example, if you want to add support for [Effect Composer](https://threejs.org/examples/?q=compo#webgl_postprocessing_effectcomposer) you should create a new package called `@tresjs/postprocessing` and add it as a plugin. If it's a smaller scope you can always add it to `cientos` package.
+The core package should be as small as possible, it should only contain the core functionality of the library. If you are adding a new feature, please consider adding it as a plugin instead, for example, if you want to add support for [Effect Composer](https://threejs.org/examples/?q=compo#webgl_postprocessing_effectcomposer) you should create a new package called `@tresjs/post-processing` and add it as a plugin. If it's a smaller scope you can always add it to `cientos` package.

+ 4 - 0
docs/.eslintrc.json

@@ -0,0 +1,4 @@
+{
+  "extends": "@tresjs/eslint-config-vue"
+}
+  

+ 3 - 3
docs/.vitepress/config.ts

@@ -90,7 +90,7 @@ export default defineConfig({
         text: 'Ecosystem',
         items: [
           {
-            text: `Cientos 💛`,
+            text: 'Cientos 💛',
             link: 'https://cientos.tresjs.org/',
           },
         ],
@@ -107,13 +107,13 @@ export default defineConfig({
           { text: 'Releases', link: 'https://github.com/Tresjs/tres/releases' },
           {
             text: 'Playground',
-            link: 'https://playground.tresjs.org/'
+            link: 'https://playground.tresjs.org/',
           },
           {
             text: 'Ecosystem',
             items: [
               {
-                text: `Cientos 💛`,
+                text: 'Cientos 💛',
                 link: 'https://cientos.tresjs.org/',
               },
             ],

+ 5 - 1
docs/.vitepress/theme/components/DonutExample.vue

@@ -16,7 +16,11 @@ const gl = {
 
 <template>
   <TresCanvas v-bind="gl">
-    <TresPerspectiveCamera :position="[3, 3, 3]" :fov="45" :look-at="[0, 0, 0]" />
+    <TresPerspectiveCamera
+      :position="[3, 3, 3]"
+      :fov="45"
+      :look-at="[0, 0, 0]"
+    />
     <OrbitControls />
     <TresMesh>
       <TresTorusGeometry :args="[1, 0.5, 16, 32]" />

+ 1 - 0
docs/.vitepress/theme/components/EmbedExperiment.vue

@@ -3,6 +3,7 @@ defineProps<{
   url: string
 }>()
 </script>
+
 <template>
   <iframe
     frameborder="0"

+ 15 - 4
docs/.vitepress/theme/components/ExtendExample.vue

@@ -10,16 +10,27 @@ const styles = {
 }
 
 const { camera, renderer } = useTresContext()
-
 </script>
+
 <template>
   <ClientOnly>
-    <TresCanvas shadows clear-color="#fff" :style="styles">
+    <TresCanvas
+      shadows
+      clear-color="#fff"
+      :style="styles"
+    >
       <TresPerspectiveCamera :position="[0, 2, 4]" />
       <TresScene>
-        <TresOrbitControls v-if="renderer" :args="[camera, renderer?.domElement]" />
+        <TresOrbitControls
+          v-if="renderer"
+          :args="[camera, renderer?.domElement]"
+        />
 
-        <TresDirectionalLight :position="[0, 2, 4]" :intensity="2" cast-shadow />
+        <TresDirectionalLight
+          :position="[0, 2, 4]"
+          :intensity="2"
+          cast-shadow
+        />
         <TresMesh :rotation="[-Math.PI / 4, -Math.PI / 4, Math.PI / 4]">
           <TresTorusGeometry :args="[1, 0.5, 16, 32]" />
           <TresMeshToonMaterial color="#FBB03B" />

+ 35 - 7
docs/.vitepress/theme/components/FirstScene.vue

@@ -16,26 +16,54 @@ const gl = {
 
 <template>
   <TresCanvas v-bind="gl">
-    <TresPerspectiveCamera :position="[11, 11, 11]" :fov="45" :aspect="1" :near="0.1" :far="1000" :look-at="[0, 0, 0]" />
+    <TresPerspectiveCamera
+      :position="[11, 11, 11]"
+      :fov="45"
+      :aspect="1"
+      :near="0.1"
+      :far="1000"
+      :look-at="[0, 0, 0]"
+    />
     <OrbitControls />
-    <TresMesh :position="[-2, 6, 0]" :rotation="[0, Math.PI, 0]" cast-shadow>
+    <TresMesh
+      :position="[-2, 6, 0]"
+      :rotation="[0, Math.PI, 0]"
+      cast-shadow
+    >
       <TresConeGeometry :args="[1, 1.5, 3]" />
       <TresMeshToonMaterial color="#82DBC5" />
     </TresMesh>
-    <TresMesh :position="[0, 4, 0]" cast-shadow>
+    <TresMesh
+      :position="[0, 4, 0]"
+      cast-shadow
+    >
       <TresBoxGeometry :args="[1.5, 1.5, 1.5]" />
       <TresMeshToonMaterial color="#4F4F4F" />
     </TresMesh>
-    <TresMesh :position="[2, 2, 0]" cast-shadow>
+    <TresMesh
+      :position="[2, 2, 0]"
+      cast-shadow
+    >
       <TresSphereGeometry />
       <TresMeshToonMaterial color="#FBB03B" />
     </TresMesh>
-    <TresDirectionalLight :position="[0, 8, 4]" :intensity="0.7" cast-shadow />
-    <TresMesh :rotation="[-Math.PI / 2, 0, 0]" receive-shadow>
+    <TresDirectionalLight
+      :position="[0, 8, 4]"
+      :intensity="0.7"
+      cast-shadow
+    />
+    <TresMesh
+      :rotation="[-Math.PI / 2, 0, 0]"
+      receive-shadow
+    >
       <TresPlaneGeometry :args="[10, 10, 10, 10]" />
       <TresMeshToonMaterial color="#D3FC8A" />
     </TresMesh>
     <TresAmbientLight :intensity="0.75" />
-    <TresDirectionalLight ref="LightRef" :position="[0, 2, 4]" :intensity="2" cast-shadow />
+    <TresDirectionalLight
+      :position="[0, 2, 4]"
+      :intensity="2"
+      cast-shadow
+    />
   </TresCanvas>
 </template>

+ 12 - 2
docs/.vitepress/theme/components/FirstSceneLightToon.vue

@@ -1,5 +1,6 @@
 <script setup lang="ts">
 import { TresCanvas } from '@tresjs/core'
+
 /* import { OrbitControls } from '@tresjs/cientos' */
 
 const styles = {
@@ -10,12 +11,21 @@ const styles = {
   overflow: 'hidden',
 }
 </script>
+
 <template>
   <ClientOnly>
-    <TresCanvas shadows clear-color="#fff" :style="styles">
+    <TresCanvas
+      shadows
+      clear-color="#fff"
+      :style="styles"
+    >
       <TresPerspectiveCamera :position="[0, 2, 4]" />
       <OrbitControls />
-      <TresDirectionalLight :position="[0, 2, 4]" :intensity="2" cast-shadow />
+      <TresDirectionalLight
+        :position="[0, 2, 4]"
+        :intensity="2"
+        cast-shadow
+      />
       <TresMesh :rotation="[-Math.PI / 4, -Math.PI / 4, Math.PI / 4]">
         <TresTorusGeometry :args="[1, 0.5, 16, 32]" />
         <TresMeshToonMaterial color="#FBB03B" />

+ 281 - 266
docs/.vitepress/theme/components/LocalOrbitControls.vue

@@ -1,302 +1,317 @@
 <script lang="ts" setup>
-import { Camera } from 'three'
+import type { Camera } from 'three'
 import { OrbitControls } from 'three-stdlib'
 import { ref, unref, onUnmounted, onMounted, watchEffect } from 'vue'
-import { TresVector3, extend, useRenderLoop, useTresContext } from '@tresjs/core'
+import type { TresVector3 } from '@tresjs/core'
+import { extend, useRenderLoop, useTresContext } from '@tresjs/core'
 import { useEventListener } from '@vueuse/core'
 
 export interface OrbitControlsProps {
-    /**
-     * Whether to make this the default controls.
-     *
-     * @default false
-     * @type {boolean}
-     * @memberof OrbitControlsProps
-     */
-    makeDefault?: boolean
-    /**
-     * The camera to control.
-     *
-     * @type {Camera}
-     * @memberof OrbitControlsProps
-     * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.camera
-     */
-    camera?: Camera
-    /**
-     * The dom element to listen to.
-     *
-     * @type {HTMLElement}
-     * @memberof OrbitControlsProps
-     * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.domElement
-     */
-    domElement?: HTMLElement
-    /**
-     * The target to orbit around.
-     *
-     * @type {TresVector3}
-     * @memberof OrbitControlsProps
-     * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.target
-     */
-    target?: TresVector3
-    /**
-     * Whether to enable damping (inertia)
-     *
-     * @default false
-     * @type {boolean}
-     * @memberof OrbitControlsProps
-     * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.enableDamping
-     */
-    enableDamping?: boolean
-    /**
-     * The damping inertia used if `.enableDamping` is set to true
-     *
-     * @default 0.05
-     * @type {number}
-     * @memberof OrbitControlsProps
-     * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.dampingFactor
-     */
-    dampingFactor?: number
-    /**
-     * Set to true to automatically rotate around the target.
-     *
-     * @default false
-     * @type {boolean}
-     * @memberof OrbitControlsProps
-     * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.autoRotate
-     */
-    autoRotate?: boolean
-    /**
-     * How fast to rotate around the target if `.autoRotate` is true.
-     *
-     * @default 2
-     * @type {number}
-     * @memberof OrbitControlsProps
-     * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.autoRotateSpeed
-     */
-    autoRotateSpeed?: number
-    /**
-     * Whether to enable panning.
-     *
-     * @default true
-     * @type {boolean}
-     * @memberof OrbitControlsProps
-     * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.enablePan
-     */
-    enablePan?: boolean
-    /**
-     * How fast to pan the camera when the keyboard is used. Default is 7.0 pixels per keypress.
-     *
-     * @default 7.0
-     * @type {number}
-     * @memberof OrbitControlsProps
-     * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.keyPanSpeed
-     */
-    keyPanSpeed?: number
-    /**
-     * This object contains references to the keycodes for controlling camera panning.
-     * Default is the 4 arrow keys.
-     *
-     * @default `{ LEFT: 'ArrowLeft', UP: 'ArrowUp', RIGHT: 'ArrowRight', BOTTOM: 'ArrowDown' }`
-     * @type Record<string, string>
-     * @memberof OrbitControlsProps
-     * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.keys
-     */
-    keys?: Record<string, string>
-    /**
-     * How far you can orbit horizontally, upper limit.
-     * If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ],
-     * with ( max - min < 2 PI ). Default is Infinity.
-     *
-     * @default Infinity
-     * @type {number}
-     * @memberof OrbitControlsProps
-     * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.maxAzimuthAngle
-     */
-    maxAzimuthAngle?: number
-    /**
-     * How far you can orbit horizontally, lower limit.
-     * If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ],
-     * with ( max - min < 2 PI ).
-     * Default is - Infinity.
-     *
-     * @default -Infinity
-     * @type {number}
-     * @memberof OrbitControlsProps
-     * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.minAzimuthAngle
-     */
-    minAzimuthAngle?: number
-    /**
-     * How far you can orbit vertically, upper limit.
-     * Range is 0 to Math.PI radians, and default is Math.PI.
-     *
-     * @default Math.PI
-     * @type {number}
-     * @memberof OrbitControlsProps
-     * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.maxPolarAngle
-     */
-    maxPolarAngle?: number
-    /**
-     * How far you can orbit vertically, lower limit.
-     * Range is 0 to Math.PI radians, and default is 0.
-     *
-     * @default 0
-     * @type {number}
-     * @memberof OrbitControlsProps
-     * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.minPolarAngle
-     */
-    minPolarAngle?: number
-    /**
-     * The minimum distance of the camera to the target.
-     * Default is 0.
-     *
-     * @default 0
-     * @type {number}
-     * @memberof OrbitControlsProps
-     * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.minDistance
-     */
-    minDistance?: number
-    /**
-     * The maximum distance of the camera to the target.
-     * Default is Infinity.
-     *
-     * @default Infinity
-     * @type {number}
-     * @memberof OrbitControlsProps
-     * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.maxDistance
-     */
-    maxDistance?: number
-    /**
-     * The minimum field of view angle, in radians.
-     * Default is 0.
-     *
-     * @default 0
-     * @type {number}
-     * @memberof OrbitControlsProps
-     * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.minZoom
-     */
-    minZoom?: number
-    /**
-     * The maximum field of view angle, in radians.
-     * ( OrthographicCamera only ).
-     * Default is Infinity.
-     *
-     * @default Infinity
-     * @type {number}
-     * @memberof OrbitControlsProps
-     * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.maxZoom
-     */
-    maxZoom?: number
-    touches?: {
-        ONE?: number
-        TWO?: number
-    }
-    /**
-     * Whether to enable zooming.
-     *
-     * @default true
-     * @type {boolean}
-     * @memberof OrbitControlsProps
-     * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.enableZoom
-     */
-    enableZoom?: boolean
-    /**
-     * How fast to zoom in and out. Default is 1.
-     *
-     * @default 1
-     * @type {number}
-     * @memberof OrbitControlsProps
-     * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.zoomSpeed
-     */
-    zoomSpeed?: number
-    /**
-     * Whether to enable rotating.
-     *
-     * @default true
-     * @type {boolean}
-     * @memberof OrbitControlsProps
-     * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.enableRotate
-     */
-    enableRotate?: boolean
-    /**
-     * How fast to rotate around the target. Default is 1.
-     *
-     * @default 1
-     * @type {number}
-     * @memberof OrbitControlsProps
-     * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.rotateSpeed
-     */
-    rotateSpeed?: number
+  /**
+      * Whether to make this the default controls.
+      *
+      * @default false
+      * @type {boolean}
+      * @memberof OrbitControlsProps
+      */
+  makeDefault?: boolean
+  /**
+      * The camera to control.
+      *
+      * @type {Camera}
+      * @memberof OrbitControlsProps
+      * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.camera
+      */
+  camera?: Camera
+  /**
+      * The dom element to listen to.
+      *
+      * @type {HTMLElement}
+      * @memberof OrbitControlsProps
+      * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.domElement
+      */
+  domElement?: HTMLElement
+  /**
+      * The target to orbit around.
+      *
+      * @type {TresVector3}
+      * @memberof OrbitControlsProps
+      * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.target
+      */
+  target?: TresVector3
+  /**
+      * Whether to enable damping (inertia)
+      *
+      * @default false
+      * @type {boolean}
+      * @memberof OrbitControlsProps
+      * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.enableDamping
+      */
+  enableDamping?: boolean
+  /**
+      * The damping inertia used if `.enableDamping` is set to true
+      *
+      * @default 0.05
+      * @type {number}
+      * @memberof OrbitControlsProps
+      * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.dampingFactor
+      */
+  dampingFactor?: number
+  /**
+      * Set to true to automatically rotate around the target.
+      *
+      * @default false
+      * @type {boolean}
+      * @memberof OrbitControlsProps
+      * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.autoRotate
+      */
+  autoRotate?: boolean
+  /**
+      * How fast to rotate around the target if `.autoRotate` is true.
+      *
+      * @default 2
+      * @type {number}
+      * @memberof OrbitControlsProps
+      * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.autoRotateSpeed
+      */
+  autoRotateSpeed?: number
+  /**
+      * Whether to enable panning.
+      *
+      * @default true
+      * @type {boolean}
+      * @memberof OrbitControlsProps
+      * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.enablePan
+      */
+  enablePan?: boolean
+  /**
+      * How fast to pan the camera when the keyboard is used. Default is 7.0 pixels per keypress.
+      *
+      * @default 7.0
+      * @type {number}
+      * @memberof OrbitControlsProps
+      * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.keyPanSpeed
+      */
+  keyPanSpeed?: number
+  /**
+      * This object contains references to the keycodes for controlling camera panning.
+      * Default is the 4 arrow keys.
+      *
+      * @default `{ LEFT: 'ArrowLeft', UP: 'ArrowUp', RIGHT: 'ArrowRight', BOTTOM: 'ArrowDown' }`
+      * @type Record<string, string>
+      * @memberof OrbitControlsProps
+      * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.keys
+      */
+  keys?: Record<string, string>
+  /**
+      * How far you can orbit horizontally, upper limit.
+      * If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ],
+      * with ( max - min < 2 PI ). Default is Infinity.
+      *
+      * @default Infinity
+      * @type {number}
+      * @memberof OrbitControlsProps
+      * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.maxAzimuthAngle
+      */
+  maxAzimuthAngle?: number
+  /**
+      * How far you can orbit horizontally, lower limit.
+      * If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ],
+      * with ( max - min < 2 PI ).
+      * Default is - Infinity.
+      *
+      * @default -Infinity
+      * @type {number}
+      * @memberof OrbitControlsProps
+      * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.minAzimuthAngle
+      */
+  minAzimuthAngle?: number
+  /**
+      * How far you can orbit vertically, upper limit.
+      * Range is 0 to Math.PI radians, and default is Math.PI.
+      *
+      * @default Math.PI
+      * @type {number}
+      * @memberof OrbitControlsProps
+      * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.maxPolarAngle
+      */
+  maxPolarAngle?: number
+  /**
+      * How far you can orbit vertically, lower limit.
+      * Range is 0 to Math.PI radians, and default is 0.
+      *
+      * @default 0
+      * @type {number}
+      * @memberof OrbitControlsProps
+      * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.minPolarAngle
+      */
+  minPolarAngle?: number
+  /**
+      * The minimum distance of the camera to the target.
+      * Default is 0.
+      *
+      * @default 0
+      * @type {number}
+      * @memberof OrbitControlsProps
+      * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.minDistance
+      */
+  minDistance?: number
+  /**
+      * The maximum distance of the camera to the target.
+      * Default is Infinity.
+      *
+      * @default Infinity
+      * @type {number}
+      * @memberof OrbitControlsProps
+      * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.maxDistance
+      */
+  maxDistance?: number
+  /**
+      * The minimum field of view angle, in radians.
+      * Default is 0.
+      *
+      * @default 0
+      * @type {number}
+      * @memberof OrbitControlsProps
+      * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.minZoom
+      */
+  minZoom?: number
+  /**
+      * The maximum field of view angle, in radians.
+      * ( OrthographicCamera only ).
+      * Default is Infinity.
+      *
+      * @default Infinity
+      * @type {number}
+      * @memberof OrbitControlsProps
+      * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.maxZoom
+      */
+  maxZoom?: number
+  touches?: {
+    ONE?: number
+    TWO?: number
+  }
+  /**
+      * Whether to enable zooming.
+      *
+      * @default true
+      * @type {boolean}
+      * @memberof OrbitControlsProps
+      * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.enableZoom
+      */
+  enableZoom?: boolean
+  /**
+      * How fast to zoom in and out. Default is 1.
+      *
+      * @default 1
+      * @type {number}
+      * @memberof OrbitControlsProps
+      * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.zoomSpeed
+      */
+  zoomSpeed?: number
+  /**
+      * Whether to enable rotating.
+      *
+      * @default true
+      * @type {boolean}
+      * @memberof OrbitControlsProps
+      * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.enableRotate
+      */
+  enableRotate?: boolean
+  /**
+      * How fast to rotate around the target. Default is 1.
+      *
+      * @default 1
+      * @type {number}
+      * @memberof OrbitControlsProps
+      * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.rotateSpeed
+      */
+  rotateSpeed?: number
 }
 
 // TODO: remove disable once eslint is updated to support vue 3.3
 // eslint-disable-next-line vue/no-setup-props-destructure
 const {
-    makeDefault = false,
-    autoRotate = false,
-    autoRotateSpeed = 2,
-    enableDamping = false,
-    dampingFactor = 0.05,
-    enablePan = true,
-    keyPanSpeed = 7,
-    maxAzimuthAngle = Infinity,
-    minAzimuthAngle = -Infinity,
-    maxPolarAngle = Math.PI,
-    minPolarAngle = 0,
-    minDistance = 0,
-    maxDistance = Infinity,
-    minZoom = 0,
-    maxZoom = Infinity,
-    enableZoom = true,
-    zoomSpeed = 1,
-    enableRotate = true,
-    rotateSpeed = 1,
-    target = [0, 0, 0],
+  makeDefault = false,
+  autoRotate = false,
+  autoRotateSpeed = 2,
+  enableDamping = false,
+  dampingFactor = 0.05,
+  enablePan = true,
+  keyPanSpeed = 7,
+  maxAzimuthAngle = Infinity,
+  minAzimuthAngle = -Infinity,
+  maxPolarAngle = Math.PI,
+  minPolarAngle = 0,
+  minDistance = 0,
+  maxDistance = Infinity,
+  minZoom = 0,
+  maxZoom = Infinity,
+  enableZoom = true,
+  zoomSpeed = 1,
+  enableRotate = true,
+  rotateSpeed = 1,
+  target = [0, 0, 0],
 } = defineProps<OrbitControlsProps>()
 
+const emit = defineEmits(['change', 'start', 'end'])
+
 const { renderer, camera: activeCamera } = useTresContext()
 
 const controls = ref<OrbitControls | null>(null)
 
 extend({ OrbitControls })
 
-const emit = defineEmits(['change', 'start', 'end'])
-
 function addEventListeners() {
-    useEventListener(controls.value as any, 'change', () => emit('change', controls.value))
-    useEventListener(controls.value as any, 'start', () => emit('start', controls.value))
-    useEventListener(controls.value as any, 'end', () => emit('end', controls.value))
+  useEventListener(controls.value as any, 'change', () => emit('change', controls.value))
+  useEventListener(controls.value as any, 'start', () => emit('start', controls.value))
+  useEventListener(controls.value as any, 'end', () => emit('end', controls.value))
 }
 
 const { onLoop } = useRenderLoop()
 
 onLoop(() => {
-    if (controls.value && (enableDamping || autoRotate)) {
-        controls.value.update()
-    }
+  if (controls.value && (enableDamping || autoRotate)) {
+    controls.value.update()
+  }
 })
 
 onMounted(() => {
-    addEventListeners()
+  addEventListeners()
 })
 
 onUnmounted(() => {
-    if (controls.value) {
-        controls.value.dispose()
-    }
-})
-
-watchEffect(() => {
-    console.log('activeCamera', activeCamera.value)
-    console.log('renderer', renderer.value)
+  if (controls.value) {
+    controls.value.dispose()
+  }
 })
 </script>
 
 <template>
-    <TresOrbitControls v-if="activeCamera && renderer" ref="controls" :target="target" :auto-rotate="autoRotate"
-        :auto-rotate-speed="autoRotateSpeed" :enable-damping="enableDamping" :damping-factor="dampingFactor"
-        :enable-pan="enablePan" :key-pan-speed="keyPanSpeed" :keys="keys" :max-azimuth-angle="maxAzimuthAngle"
-        :min-azimuth-angle="minAzimuthAngle" :max-polar-angle="maxPolarAngle" :min-polar-angle="minPolarAngle"
-        :min-distance="minDistance" :max-distance="maxDistance" :min-zoom="minZoom" :max-zoom="maxZoom" :touches="touches"
-        :enable-zoom="enableZoom" :zoom-speed="zoomSpeed" :enable-rotate="enableRotate" :rotate-speed="rotateSpeed"
-        :args="[unref(activeCamera) || camera, renderer?.domElement || domElement]" />
+  <TresOrbitControls
+    v-if="activeCamera && renderer"
+    ref="controls"
+    :target="target"
+    :auto-rotate="autoRotate"
+    :auto-rotate-speed="autoRotateSpeed"
+    :enable-damping="enableDamping"
+    :damping-factor="dampingFactor"
+    :enable-pan="enablePan"
+    :key-pan-speed="keyPanSpeed"
+    :keys="keys"
+    :max-azimuth-angle="maxAzimuthAngle"
+    :min-azimuth-angle="minAzimuthAngle"
+    :max-polar-angle="maxPolarAngle"
+    :min-polar-angle="minPolarAngle"
+    :min-distance="minDistance"
+    :max-distance="maxDistance"
+    :min-zoom="minZoom"
+    :max-zoom="maxZoom"
+    :touches="touches"
+    :enable-zoom="enableZoom"
+    :zoom-speed="zoomSpeed"
+    :enable-rotate="enableRotate"
+    :rotate-speed="rotateSpeed"
+    :args="[unref(activeCamera) || camera, renderer?.domElement || domElement]"
+  />
 </template>

+ 9 - 6
docs/.vitepress/theme/components/LoveVueThreeJS.vue

@@ -1,10 +1,10 @@
 <script setup lang="ts">
 ///<reference types="vite-svg-loader" />
+import { gsap } from 'gsap'
+import { onMounted, ref } from 'vue'
 import Triangle from '../assets/triangle.svg'
 import SecondRow from '../assets/second-row.svg'
 import ThirdRow from '../assets/third-row.svg'
-import {gsap} from 'gsap'
-import { onMounted, ref } from 'vue'
 
 const triangleRef = ref()
 const secondRowRef = ref()
@@ -19,13 +19,13 @@ async function restartAnimation() {
   gsap.to(secondRowRef.value.$el, {
     duration: 1,
     y: 0,
-    ease: "elastic.out(0.7, 0.2)",
+    ease: 'elastic.out(0.7, 0.2)',
   })
   await gsap.to(thirdRowRef.value.$el, {
     delay: 0.65,
     duration: 1,
     y: 0,
-    ease: "steps(4)",
+    ease: 'steps(4)',
   })
 
   tl2r.restart()
@@ -43,13 +43,16 @@ onMounted(() => {
     delay: 1.25,
     duration: 2,
     y: -(12 * heightOfSignleSvg),
-    ease: "power1.out",
+    ease: 'power1.out',
   })
 })
 </script>
 
 <template>
-  <div class="grid items-center w-full min-w-370px -translate-x-20px md:translate-x-20px h-full scale-75" @click="restartAnimation">
+  <div
+    class="grid items-center w-full min-w-370px -translate-x-20px md:translate-x-20px h-full scale-75"
+    @click="restartAnimation"
+  >
     <div class="grid grid-cols-3 gap-8 overflow-hidden h-93px">
       <Triangle ref="triangleRef" />
       <SecondRow ref="secondRowRef" />

+ 14 - 4
docs/.vitepress/theme/components/StackBlitzEmbed.vue

@@ -1,5 +1,6 @@
 <script setup lang="ts">
-import sdk, { EmbedOptions } from '@stackblitz/sdk'
+import type { EmbedOptions } from '@stackblitz/sdk'
+import sdk from '@stackblitz/sdk'
 import { ref, watch } from 'vue'
 
 const props = withDefaults(
@@ -23,16 +24,25 @@ const isSnippetLoaded = ref(false)
 
 watch(
   () => embed.value,
-  value => {
+  (value) => {
     if (value) {
       sdk.embedProjectId(value, props.projectId, props.options)
     }
   },
 )
 </script>
+
 <template>
-  <div ref="embed" class="stackblitz-embed">
-    <div v-if="!isSnippetLoaded" class="text-gray-500 text-2xl">Loading...</div>
+  <div
+    ref="embed"
+    class="stackblitz-embed"
+  >
+    <div
+      v-if="!isSnippetLoaded"
+      class="text-gray-500 text-2xl"
+    >
+      Loading...
+    </div>
   </div>
 </template>
 

+ 1 - 0
docs/.vitepress/theme/index.ts

@@ -1,4 +1,5 @@
 import 'uno.css'
+
 // .vitepress/theme/index.ts
 import DefaultTheme from 'vitepress/theme'
 import './config.css'

+ 5 - 5
docs/package.json

@@ -1,18 +1,18 @@
 {
   "name": "docs",
-  "private": true,
-  "version": "0.0.0",
   "type": "module",
+  "version": "0.0.0",
+  "private": true,
   "scripts": {
     "dev": "vitepress dev",
     "build": "vitepress build",
     "preview": "vitepress preview"
   },
+  "dependencies": {
+    "@tresjs/core": "workspace:^3.1.1"
+  },
   "devDependencies": {
     "unocss": "^0.54.0",
     "vite-svg-loader": "^4.0.0"
-  },
-  "dependencies": {
-    "@tresjs/core": "workspace:^3.1.1"
   }
 }

+ 2 - 2
docs/vite.config.ts

@@ -18,6 +18,6 @@ export default defineConfig({
     }),
   ],
   vue: {
-    ...templateCompilerOptions
-  }
+    ...templateCompilerOptions,
+  },
 })

+ 10 - 9
package.json

@@ -1,11 +1,18 @@
 {
   "name": "@tresjs/core",
-  "description": "Declarative ThreeJS using Vue Components",
-  "version": "3.1.1",
   "type": "module",
+  "version": "3.1.1",
   "packageManager": "pnpm@8.3.1",
+  "description": "Declarative ThreeJS using Vue Components",
   "author": "Alvaro Saburido <hola@alvarosaburido.dev> (https://github.com/alvarosabu/)",
   "license": "MIT",
+  "keywords": [
+    "vue",
+    "3d",
+    "threejs",
+    "three",
+    "threejs-vue"
+  ],
   "sideEffects": false,
   "exports": {
     ".": {
@@ -36,13 +43,6 @@
   "publishConfig": {
     "access": "public"
   },
-  "keywords": [
-    "vue",
-    "3d",
-    "threejs",
-    "three",
-    "threejs-vue"
-  ],
   "scripts": {
     "build": "vite build",
     "playground": "cd playground && npm run dev",
@@ -72,6 +72,7 @@
     "@release-it/conventional-changelog": "^7.0.0",
     "@stackblitz/sdk": "^1.9.0",
     "@tresjs/cientos": "3.1.0",
+    "@tresjs/eslint-config-vue": "^0.1.1",
     "@types/three": "^0.155.1",
     "@typescript-eslint/eslint-plugin": "^6.4.1",
     "@typescript-eslint/parser": "^6.4.1",

+ 0 - 63
playground/.eslintrc-auto-import.json

@@ -1,63 +0,0 @@
-{
-  "globals": {
-    "Component": true,
-    "ComponentPublicInstance": true,
-    "ComputedRef": true,
-    "EffectScope": true,
-    "InjectionKey": true,
-    "PropType": true,
-    "Ref": true,
-    "VNode": true,
-    "computed": true,
-    "createApp": true,
-    "customRef": true,
-    "defineAsyncComponent": true,
-    "defineComponent": true,
-    "effectScope": true,
-    "getCurrentInstance": true,
-    "getCurrentScope": true,
-    "h": true,
-    "inject": true,
-    "isProxy": true,
-    "isReactive": true,
-    "isReadonly": true,
-    "isRef": true,
-    "markRaw": true,
-    "nextTick": true,
-    "onActivated": true,
-    "onBeforeMount": true,
-    "onBeforeUnmount": true,
-    "onBeforeUpdate": true,
-    "onDeactivated": true,
-    "onErrorCaptured": true,
-    "onMounted": true,
-    "onRenderTracked": true,
-    "onRenderTriggered": true,
-    "onScopeDispose": true,
-    "onServerPrefetch": true,
-    "onUnmounted": true,
-    "onUpdated": true,
-    "provide": true,
-    "reactive": true,
-    "readonly": true,
-    "ref": true,
-    "resolveComponent": true,
-    "shallowReactive": true,
-    "shallowReadonly": true,
-    "shallowRef": true,
-    "toRaw": true,
-    "toRef": true,
-    "toRefs": true,
-    "triggerRef": true,
-    "unref": true,
-    "useAttrs": true,
-    "useCssModule": true,
-    "useCssVars": true,
-    "useSlots": true,
-    "watch": true,
-    "watchEffect": true,
-    "watchPostEffect": true,
-    "watchSyncEffect": true,
-    "toValue": true
-  }
-}

+ 0 - 5
playground/.eslintrc.cjs

@@ -1,5 +0,0 @@
-module.exports = {
-    extends: [
-        './.eslintrc-auto-import.json',
-    ],
-}

+ 7 - 0
playground/.eslintrc.json

@@ -0,0 +1,7 @@
+{
+  "extends": "@tresjs/eslint-config-vue",
+  "rules": {
+    "no-console": "off"
+  }
+}
+  

+ 2 - 2
playground/package.json

@@ -1,8 +1,8 @@
 {
   "name": "playground",
-  "private": true,
-  "version": "0.0.0",
   "type": "module",
+  "version": "0.0.0",
+  "private": true,
   "scripts": {
     "dev": "vite",
     "build": "vue-tsc && vite build",

+ 10 - 2
playground/src/components/AnimatedModel.vue

@@ -50,10 +50,18 @@ console.log({ model, animations, actions, mixer })
       power-preference="high-performance"
       :output-encoding="SRGBColorSpace"
     >
-      <TresPerspectiveCamera :position="[8, 8, 8]" :fov="45" :near="0.1" :far="10000" />
+      <TresPerspectiveCamera
+        :position="[8, 8, 8]"
+        :fov="45"
+        :near="0.1"
+        :far="10000"
+      />
       <OrbitControls />
 
-      <TresAmbientLight :color="0xffffff" :intensity="2" />
+      <TresAmbientLight
+        :color="0xffffff"
+        :intensity="2"
+      />
       <TresMesh v-bind="model" />
       <TresDirectionalLight />
     </TresCanvas>

+ 28 - 18
playground/src/components/Cameras.vue

@@ -21,6 +21,13 @@ const state = reactive({
 state.camera.position.set(5, 5, 5)
 state.camera.lookAt(0, 0, 0)
 const { pane } = useTweakPane()
+const perspectiveFolder = pane.addFolder({
+  title: 'Perspective Camera',
+})
+
+const orthographicFolder = pane.addFolder({
+  title: 'Ortographic Camera',
+})
 
 pane
   .addBlade({
@@ -32,10 +39,10 @@ pane
     ],
     value: 'perspective',
   })
-  .on('change', e => {
+  .on('change', (e) => {
     state.cameraType = e.value
-    const newCamera =
-      e.value === 'perspective'
+    const newCamera
+      = e.value === 'perspective'
         ? new PerspectiveCamera(75, 1, 0.1, 1000)
         : new OrthographicCamera(-10, 10, 10, -10, 0.1, 1000)
 
@@ -47,21 +54,13 @@ pane
     /* context.value.state.accio += 1 */
   })
 
-const perspectiveFolder = pane.addFolder({
-  title: 'Perspective Camera',
-})
-
-const orthographicFolder = pane.addFolder({
-  title: 'Ortographic Camera',
-})
-
 orthographicFolder.hidden = true
 
 watch(
   () => state.cameraType,
   () => {
     if (state.cameraType === 'orthographic') {
-      perspectiveFolder.children.forEach(child => {
+      perspectiveFolder.children.forEach((child) => {
         child.dispose()
       })
       orthographicFolder.addInput(state.camera, 'left', { min: -50, max: 50 })
@@ -70,8 +69,9 @@ watch(
       orthographicFolder.addInput(state.camera, 'bottom', { min: -50, max: 50 })
       orthographicFolder.addInput(state.camera, 'near', { min: 0, max: 50 })
       orthographicFolder.addInput(state.camera, 'far', { min: 0, max: 50 })
-    } else {
-      orthographicFolder.children.forEach(child => {
+    }
+    else {
+      orthographicFolder.children.forEach((child) => {
         child.dispose()
       })
       perspectiveFolder.addInput(state.camera, 'fov', { min: 0, max: 180 })
@@ -100,14 +100,24 @@ setTimeout(() => {
 </script>
 
 <template>
-  <TresCanvas v-bind="gl" ref="context" :camera="state.camera">
+  <TresCanvas
+    v-bind="gl"
+    ref="context"
+    :camera="state.camera"
+  >
     <!--     <TresPerspectiveCamera v-if="state.cameraType === 'perspective'" :position="[11, 11, 11]" />
     <TresOrthographicCamera v-if="state.cameraType === 'orthographic'" :position="[11, 11, 11]" /> -->
-    <Box :position="[0, 1, 0]" :scale="[2, 2, 2]">
-      <TresMeshNormalMaterial :color="'teal'" />
+    <Box
+      :position="[0, 1, 0]"
+      :scale="[2, 2, 2]"
+    >
+      <TresMeshNormalMaterial color="teal" />
     </Box>
     <TresGridHelper />
     <TresAmbientLight :intensity="1" />
-    <TresDirectionalLight :position="[3, 3, 3]" :intensity="1" />
+    <TresDirectionalLight
+      :position="[3, 3, 3]"
+      :intensity="1"
+    />
   </TresCanvas>
 </template>

+ 4 - 1
playground/src/components/DebugUI.vue

@@ -28,7 +28,10 @@ setTimeout(() => {
 </script>
 
 <template>
-  <TresCanvas v-bind="gl" :window-size="true">
+  <TresCanvas
+    v-bind="gl"
+    :window-size="true"
+  >
     <TresPerspectiveCamera :look-at="[0, 4, 0]" />
     <OrbitControls />
     <TresMesh :position="[0, 1, 0]">

+ 10 - 2
playground/src/components/FBXModels.vue

@@ -30,10 +30,18 @@ watch(jeepRef, ({ model }) => {
     power-preference="high-performance"
     :output-encoding="SRGBColorSpace"
   >
-    <TresPerspectiveCamera :position="8" :fov="45" :near="0.1" :far="10000" />
+    <TresPerspectiveCamera
+      :position="8"
+      :fov="45"
+      :near="0.1"
+      :far="10000"
+    />
     <OrbitControls />
 
-    <TresAmbientLight :color="0xffffff" :intensity="0.75" />
+    <TresAmbientLight
+      :color="0xffffff"
+      :intensity="0.75"
+    />
     <TresMesh v-bind="model" />
     <Suspense>
       <FBXModel

+ 112 - 92
playground/src/components/LocalOrbitControls.vue

@@ -1,44 +1,45 @@
 <script lang="ts" setup>
-import { Camera } from 'three'
+import type { Camera } from 'three'
 import { OrbitControls } from 'three-stdlib'
 import { ref, unref, onUnmounted } from 'vue'
-import { TresVector3, extend, useRenderLoop, useTresContext } from '@tresjs/core'
+import type { TresVector3 } from '@tresjs/core'
+import { extend, useRenderLoop, useTresContext } from '@tresjs/core'
 import { useEventListener } from '@vueuse/core'
 
 export interface OrbitControlsProps {
-    /**
+  /**
      * Whether to make this the default controls.
      *
      * @default false
      * @type {boolean}
      * @memberof OrbitControlsProps
      */
-    makeDefault?: boolean
-    /**
+  makeDefault?: boolean
+  /**
      * The camera to control.
      *
      * @type {Camera}
      * @memberof OrbitControlsProps
      * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.camera
      */
-    camera?: Camera
-    /**
+  camera?: Camera
+  /**
      * The dom element to listen to.
      *
      * @type {HTMLElement}
      * @memberof OrbitControlsProps
      * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.domElement
      */
-    domElement?: HTMLElement
-    /**
+  domElement?: HTMLElement
+  /**
      * The target to orbit around.
      *
      * @type {TresVector3}
      * @memberof OrbitControlsProps
      * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.target
      */
-    target?: TresVector3
-    /**
+  target?: TresVector3
+  /**
      * Whether to enable damping (inertia)
      *
      * @default false
@@ -46,8 +47,8 @@ export interface OrbitControlsProps {
      * @memberof OrbitControlsProps
      * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.enableDamping
      */
-    enableDamping?: boolean
-    /**
+  enableDamping?: boolean
+  /**
      * The damping inertia used if `.enableDamping` is set to true
      *
      * @default 0.05
@@ -55,8 +56,8 @@ export interface OrbitControlsProps {
      * @memberof OrbitControlsProps
      * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.dampingFactor
      */
-    dampingFactor?: number
-    /**
+  dampingFactor?: number
+  /**
      * Set to true to automatically rotate around the target.
      *
      * @default false
@@ -64,8 +65,8 @@ export interface OrbitControlsProps {
      * @memberof OrbitControlsProps
      * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.autoRotate
      */
-    autoRotate?: boolean
-    /**
+  autoRotate?: boolean
+  /**
      * How fast to rotate around the target if `.autoRotate` is true.
      *
      * @default 2
@@ -73,8 +74,8 @@ export interface OrbitControlsProps {
      * @memberof OrbitControlsProps
      * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.autoRotateSpeed
      */
-    autoRotateSpeed?: number
-    /**
+  autoRotateSpeed?: number
+  /**
      * Whether to enable panning.
      *
      * @default true
@@ -82,8 +83,8 @@ export interface OrbitControlsProps {
      * @memberof OrbitControlsProps
      * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.enablePan
      */
-    enablePan?: boolean
-    /**
+  enablePan?: boolean
+  /**
      * How fast to pan the camera when the keyboard is used. Default is 7.0 pixels per keypress.
      *
      * @default 7.0
@@ -91,8 +92,8 @@ export interface OrbitControlsProps {
      * @memberof OrbitControlsProps
      * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.keyPanSpeed
      */
-    keyPanSpeed?: number
-    /**
+  keyPanSpeed?: number
+  /**
      * This object contains references to the keycodes for controlling camera panning.
      * Default is the 4 arrow keys.
      *
@@ -101,8 +102,8 @@ export interface OrbitControlsProps {
      * @memberof OrbitControlsProps
      * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.keys
      */
-    keys?: Record<string, string>
-    /**
+  keys?: Record<string, string>
+  /**
      * How far you can orbit horizontally, upper limit.
      * If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ],
      * with ( max - min < 2 PI ). Default is Infinity.
@@ -112,8 +113,8 @@ export interface OrbitControlsProps {
      * @memberof OrbitControlsProps
      * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.maxAzimuthAngle
      */
-    maxAzimuthAngle?: number
-    /**
+  maxAzimuthAngle?: number
+  /**
      * How far you can orbit horizontally, lower limit.
      * If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ],
      * with ( max - min < 2 PI ).
@@ -124,8 +125,8 @@ export interface OrbitControlsProps {
      * @memberof OrbitControlsProps
      * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.minAzimuthAngle
      */
-    minAzimuthAngle?: number
-    /**
+  minAzimuthAngle?: number
+  /**
      * How far you can orbit vertically, upper limit.
      * Range is 0 to Math.PI radians, and default is Math.PI.
      *
@@ -134,8 +135,8 @@ export interface OrbitControlsProps {
      * @memberof OrbitControlsProps
      * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.maxPolarAngle
      */
-    maxPolarAngle?: number
-    /**
+  maxPolarAngle?: number
+  /**
      * How far you can orbit vertically, lower limit.
      * Range is 0 to Math.PI radians, and default is 0.
      *
@@ -144,8 +145,8 @@ export interface OrbitControlsProps {
      * @memberof OrbitControlsProps
      * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.minPolarAngle
      */
-    minPolarAngle?: number
-    /**
+  minPolarAngle?: number
+  /**
      * The minimum distance of the camera to the target.
      * Default is 0.
      *
@@ -154,8 +155,8 @@ export interface OrbitControlsProps {
      * @memberof OrbitControlsProps
      * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.minDistance
      */
-    minDistance?: number
-    /**
+  minDistance?: number
+  /**
      * The maximum distance of the camera to the target.
      * Default is Infinity.
      *
@@ -164,8 +165,8 @@ export interface OrbitControlsProps {
      * @memberof OrbitControlsProps
      * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.maxDistance
      */
-    maxDistance?: number
-    /**
+  maxDistance?: number
+  /**
      * The minimum field of view angle, in radians.
      * Default is 0.
      *
@@ -174,8 +175,8 @@ export interface OrbitControlsProps {
      * @memberof OrbitControlsProps
      * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.minZoom
      */
-    minZoom?: number
-    /**
+  minZoom?: number
+  /**
      * The maximum field of view angle, in radians.
      * ( OrthographicCamera only ).
      * Default is Infinity.
@@ -185,12 +186,12 @@ export interface OrbitControlsProps {
      * @memberof OrbitControlsProps
      * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.maxZoom
      */
-    maxZoom?: number
-    touches?: {
-        ONE?: number
-        TWO?: number
-    }
-    /**
+  maxZoom?: number
+  touches?: {
+    ONE?: number
+    TWO?: number
+  }
+  /**
      * Whether to enable zooming.
      *
      * @default true
@@ -198,8 +199,8 @@ export interface OrbitControlsProps {
      * @memberof OrbitControlsProps
      * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.enableZoom
      */
-    enableZoom?: boolean
-    /**
+  enableZoom?: boolean
+  /**
      * How fast to zoom in and out. Default is 1.
      *
      * @default 1
@@ -207,8 +208,8 @@ export interface OrbitControlsProps {
      * @memberof OrbitControlsProps
      * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.zoomSpeed
      */
-    zoomSpeed?: number
-    /**
+  zoomSpeed?: number
+  /**
      * Whether to enable rotating.
      *
      * @default true
@@ -216,8 +217,8 @@ export interface OrbitControlsProps {
      * @memberof OrbitControlsProps
      * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.enableRotate
      */
-    enableRotate?: boolean
-    /**
+  enableRotate?: boolean
+  /**
      * How fast to rotate around the target. Default is 1.
      *
      * @default 1
@@ -225,77 +226,96 @@ export interface OrbitControlsProps {
      * @memberof OrbitControlsProps
      * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.rotateSpeed
      */
-    rotateSpeed?: number
+  rotateSpeed?: number
 }
 
 // TODO: remove disable once eslint is updated to support vue 3.3
 // eslint-disable-next-line vue/no-setup-props-destructure
 const {
-    autoRotate = false,
-    autoRotateSpeed = 2,
-    enableDamping = false,
-    dampingFactor = 0.05,
-    enablePan = true,
-    keyPanSpeed = 7,
-    maxAzimuthAngle = Infinity,
-    minAzimuthAngle = -Infinity,
-    maxPolarAngle = Math.PI,
-    minPolarAngle = 0,
-    minDistance = 0,
-    maxDistance = Infinity,
-    minZoom = 0,
-    maxZoom = Infinity,
-    enableZoom = true,
-    zoomSpeed = 1,
-    enableRotate = true,
-    rotateSpeed = 1,
-    target = [0, 0, 0],
+  autoRotate = false,
+  autoRotateSpeed = 2,
+  enableDamping = false,
+  dampingFactor = 0.05,
+  enablePan = true,
+  keyPanSpeed = 7,
+  maxAzimuthAngle = Infinity,
+  minAzimuthAngle = -Infinity,
+  maxPolarAngle = Math.PI,
+  minPolarAngle = 0,
+  minDistance = 0,
+  maxDistance = Infinity,
+  minZoom = 0,
+  maxZoom = Infinity,
+  enableZoom = true,
+  zoomSpeed = 1,
+  enableRotate = true,
+  rotateSpeed = 1,
+  target = [0, 0, 0],
 } = defineProps<OrbitControlsProps>()
 
+const emit = defineEmits(['change', 'start', 'end'])
+
 const { renderer, camera: activeCamera } = useTresContext()
 
 const controls = ref<OrbitControls | null>(null)
 
 extend({ OrbitControls })
 
-const emit = defineEmits(['change', 'start', 'end'])
-
 function addEventListeners() {
-    useEventListener(controls.value as any, 'change', () => emit('change', controls.value))
-    useEventListener(controls.value as any, 'start', () => emit('start', controls.value))
-    useEventListener(controls.value as any, 'end', () => emit('end', controls.value))
+  useEventListener(controls.value as any, 'change', () => emit('change', controls.value))
+  useEventListener(controls.value as any, 'start', () => emit('start', controls.value))
+  useEventListener(controls.value as any, 'end', () => emit('end', controls.value))
 }
 
 const { onLoop } = useRenderLoop()
 
 onLoop(() => {
-    if (controls.value && (enableDamping || autoRotate)) {
-        controls.value.update()
-    }
+  if (controls.value && (enableDamping || autoRotate)) {
+    controls.value.update()
+  }
 })
 
 onMounted(() => {
-    addEventListeners()
+  addEventListeners()
 })
 
 onUnmounted(() => {
-    if (controls.value) {
-        controls.value.dispose()
-    }
+  if (controls.value) {
+    controls.value.dispose()
+  }
 })
 
 watchEffect(() => {
-    console.log('activeCamera', activeCamera.value)
-    console.log('renderer', renderer.value)
+  console.log('activeCamera', activeCamera.value)
+  console.log('renderer', renderer.value)
 })
 </script>
 
 <template>
-    <TresOrbitControls v-if="activeCamera && renderer" ref="controls" :target="target" :auto-rotate="autoRotate"
-        :auto-rotate-speed="autoRotateSpeed" :enable-damping="enableDamping" :damping-factor="dampingFactor"
-        :enable-pan="enablePan" :key-pan-speed="keyPanSpeed" :keys="keys" :max-azimuth-angle="maxAzimuthAngle"
-        :min-azimuth-angle="minAzimuthAngle" :max-polar-angle="maxPolarAngle" :min-polar-angle="minPolarAngle"
-        :min-distance="minDistance" :max-distance="maxDistance" :min-zoom="minZoom" :max-zoom="maxZoom" :touches="touches"
-        :enable-zoom="enableZoom" :zoom-speed="zoomSpeed" :enable-rotate="enableRotate" :rotate-speed="rotateSpeed"
-        :args="[unref(activeCamera) || camera, renderer?.domElement || domElement]" />
+  <TresOrbitControls
+    v-if="activeCamera && renderer"
+    ref="controls"
+    :target="target"
+    :auto-rotate="autoRotate"
+    :auto-rotate-speed="autoRotateSpeed"
+    :enable-damping="enableDamping"
+    :damping-factor="dampingFactor"
+    :enable-pan="enablePan"
+    :key-pan-speed="keyPanSpeed"
+    :keys="keys"
+    :max-azimuth-angle="maxAzimuthAngle"
+    :min-azimuth-angle="minAzimuthAngle"
+    :max-polar-angle="maxPolarAngle"
+    :min-polar-angle="minPolarAngle"
+    :min-distance="minDistance"
+    :max-distance="maxDistance"
+    :min-zoom="minZoom"
+    :max-zoom="maxZoom"
+    :touches="touches"
+    :enable-zoom="enableZoom"
+    :zoom-speed="zoomSpeed"
+    :enable-rotate="enableRotate"
+    :rotate-speed="rotateSpeed"
+    :args="[unref(activeCamera) || camera, renderer?.domElement || domElement]"
+  />
 </template>

+ 45 - 14
playground/src/components/MultipleCanvas.vue

@@ -1,6 +1,7 @@
 <script setup lang="ts">
 import { BasicShadowMap, NoToneMapping, SRGBColorSpace } from 'three'
 import { TresCanvas } from '@tresjs/core'
+
 // import { GLTFModel, OrbitControls } from '@tresjs/cientos'
 
 const state = reactive({
@@ -11,7 +12,7 @@ const state = reactive({
   outputColorSpace: SRGBColorSpace,
   toneMapping: NoToneMapping,
   disableRender: false,
-  stencil: false
+  stencil: false,
 })
 
 const state2 = reactive({
@@ -27,18 +28,36 @@ const state2 = reactive({
 const log = () => {
   console.log(3)
 }
-
 </script>
+
 <template>
   <div class="flex">
-    <input id="" v-model="state.clearColor" type="text" name="">
-    <input v-model="state.stencil" type="checkbox" name="">
+    <input
+      id=""
+      v-model="state.clearColor"
+      type="text"
+      name=""
+    >
+    <input
+      v-model="state.stencil"
+      type="checkbox"
+      name=""
+    >
     <div class="w-1/2 aspect-video">
       <TresCanvas v-bind="state">
-        <TresPerspectiveCamera :position="[5, 5, 5]" :fov="45" :near="0.1" :far="1000" :look-at="[0, 4, 0]" />
+        <TresPerspectiveCamera
+          :position="[5, 5, 5]"
+          :fov="45"
+          :near="0.1"
+          :far="1000"
+          :look-at="[0, 4, 0]"
+        />
 
         <TresAmbientLight :intensity="0.5" />
-        <TresMesh :position="[0, 4, 0]" @click="log">
+        <TresMesh
+          :position="[0, 4, 0]"
+          @click="log"
+        >
           <TresBoxGeometry :args="[1, 1, 1]" />
           <TresMeshToonMaterial color="cyan" />
         </TresMesh>
@@ -46,24 +65,36 @@ const log = () => {
         <Suspense>
           <TestSphere />
         </Suspense>
-        <TresDirectionalLight :position="[0, 2, 4]" :intensity="1" />
+        <TresDirectionalLight
+          :position="[0, 2, 4]"
+          :intensity="1"
+        />
       </TresCanvas>
     </div>
     <div class="w-1/2 aspect-video">
       <TresCanvas v-bind="state2">
-        <TresPerspectiveCamera :position="[5, 5, 5]" :fov="45" :near="0.1" :far="1000" :look-at="[0, 4, 0]" />
+        <TresPerspectiveCamera
+          :position="[5, 5, 5]"
+          :fov="45"
+          :near="0.1"
+          :far="1000"
+          :look-at="[0, 4, 0]"
+        />
         <TresAmbientLight :intensity="0.5" />
 
-        <TresMesh :position="[0, 4, 0]" cast-shadow>
+        <TresMesh
+          :position="[0, 4, 0]"
+          cast-shadow
+        >
           <TresSphereGeometry :args="[2, 32, 32]" />
           <TresMeshToonMaterial color="yellow" />
         </TresMesh>
 
-        <!-- <Suspense>
-          <GLTFModel path="https://raw.githubusercontent.com/Tresjs/assets/main/models/gltf/aku-aku/AkuAku.gltf" draco />
-        </Suspense> -->
-
-        <TresDirectionalLight :position="[0, 2, 4]" :intensity="1" cast-shadow />
+        <TresDirectionalLight
+          :position="[0, 2, 4]"
+          :intensity="1"
+          cast-shadow
+        />
       </TresCanvas>
     </div>
   </div>

+ 1 - 0
playground/src/components/Responsiveness.vue

@@ -1,6 +1,7 @@
 <script setup lang="ts">
 import TheEnvironment from './TheEnvironment.vue'
 </script>
+
 <template>
   <div class="modal">
     <TheEnvironment />

+ 7 - 1
playground/src/components/TestSphere.vue

@@ -22,8 +22,14 @@ const pbrTexture = await useTexture({
     'https://raw.githubusercontent.com/Tresjs/assets/main/textures/black-rock/Rock035_2K_AmbientOcclusion.jpg',
 })
 </script>
+
 <template>
-  <TresMesh ref="sphereRef" :position="[-2, 2, 2]" :scale="1" cast-shadow>
+  <TresMesh
+    ref="sphereRef"
+    :position="[-2, 2, 2]"
+    :scale="1"
+    cast-shadow
+  >
     <TresSphereGeometry :args="[1, 500, 500]" />
     <TresMeshStandardMaterial v-bind="pbrTexture" />
   </TresMesh>

+ 8 - 3
playground/src/components/Text3D.vue

@@ -22,19 +22,24 @@ const loader = new FontLoader()
 
 const font = await new Promise((resolve, reject) => {
   try {
-    loader.load(fontPath, font => {
+    loader.load(fontPath, (font) => {
       resolve(font)
     })
-  } catch (error) {
+  }
+  catch (error) {
     reject(console.error('cientos', error))
   }
 })
 
 const matcapTexture = await useTexture(['https://raw.githubusercontent.com/Tresjs/assets/main/textures/matcaps/7.png'])
 </script>
+
 <template>
   <TresMesh>
-    <TresTextGeometry :args="['TresJS', { font, ...fontOptions }]" center />
+    <TresTextGeometry
+      :args="['TresJS', { font, ...fontOptions }]"
+      center
+    />
     <TresMeshNormalMaterial :matcap="matcapTexture" />
   </TresMesh>
 </template>

+ 28 - 5
playground/src/components/TheBasic.vue

@@ -29,23 +29,46 @@ function onPointerEnter(ev) {
   }
 }
 </script>
+
 <template>
   <TresCanvas v-bind="state">
-    <TresPerspectiveCamera :position="[5, 5, 5]" :fov="45" :near="0.1" :far="1000" :look-at="[0, 0, 0]" />
+    <TresPerspectiveCamera
+      :position="[5, 5, 5]"
+      :fov="45"
+      :near="0.1"
+      :far="1000"
+      :look-at="[0, 0, 0]"
+    />
     <OrbitControls />
     <TresAmbientLight :intensity="0.5" />
 
-    <TresMesh ref="sphereRef" :position="[0, 4, 0]" cast-shadow @pointer-enter="onPointerEnter">
+    <TresMesh
+      ref="sphereRef"
+      :position="[0, 4, 0]"
+      cast-shadow
+      @pointer-enter="onPointerEnter"
+    >
       <TresSphereGeometry :args="[2, 32, 32]" />
       <TresMeshToonMaterial color="cyan" />
     </TresMesh>
 
-    <TresDirectionalLight :position="[0, 8, 4]" :intensity="0.7" cast-shadow />
-    <TresMesh :rotation="[-Math.PI / 2, 0, 0]" receive-shadow>
+    <TresDirectionalLight
+      :position="[0, 8, 4]"
+      :intensity="0.7"
+      cast-shadow
+    />
+    <TresMesh
+      :rotation="[-Math.PI / 2, 0, 0]"
+      receive-shadow
+    >
       <TresPlaneGeometry :args="[10, 10, 10, 10]" />
       <TresMeshToonMaterial />
     </TresMesh>
-    <TresDirectionalLight :position="[0, 2, 4]" :intensity="1" cast-shadow />
+    <TresDirectionalLight
+      :position="[0, 2, 4]"
+      :intensity="1"
+      cast-shadow
+    />
     <TransformControls :object="sphereRef" />
   </TresCanvas>
 </template>

+ 7 - 8
playground/src/components/TheCameraOperator.vue

@@ -1,19 +1,18 @@
-<template>
-  <slot></slot>
-</template>
-
 <script lang="ts" setup>
-import { useTresContext } from '@tresjs/core';
-
-const { setCameraActive } = useTresContext()
+import { useTresContext } from '@tresjs/core'
 
 const props = defineProps<{
   activeCameraUuid?: string
 }>()
 
+const { setCameraActive } = useTresContext()
+
 watchEffect(() => {
   if (props.activeCameraUuid)
     setCameraActive(props.activeCameraUuid)
 })
-
 </script>
+
+<template>
+  <slot />
+</template>

+ 26 - 6
playground/src/components/TheConditional.vue

@@ -30,16 +30,36 @@ const material = new MeshPhongMaterial({ color: '#ff0000' })
 
 <template>
   <TresCanvas v-bind="state">
-    <TresPerspectiveCamera :position="[11, 11, 11]" :fov="45" :near="0.1" :far="1000" :look-at="[-8, 3, -3]" />
-    <TresDirectionalLight :position="[0, 8, 4]" :intensity="0.2" cast-shadow />
-    <TresMesh v-if="paneElements.boxPropMaterialVisible" :position="[0, 0, 0]" :material="material">
+    <TresPerspectiveCamera
+      :position="[11, 11, 11]"
+      :fov="45"
+      :near="0.1"
+      :far="1000"
+      :look-at="[-8, 3, -3]"
+    />
+    <TresDirectionalLight
+      :position="[0, 8, 4]"
+      :intensity="0.2"
+      cast-shadow
+    />
+    <TresMesh
+      v-if="paneElements.boxPropMaterialVisible"
+      :position="[0, 0, 0]"
+      :material="material"
+    >
       <TresBoxGeometry :args="[1, 1, 1]" />
     </TresMesh>
-    <TresMesh v-if="paneElements.boxVisible" :position="[4, 0, 0]">
+    <TresMesh
+      v-if="paneElements.boxVisible"
+      :position="[4, 0, 0]"
+    >
       <TresBoxGeometry :args="[1, 1, 1]" />
       <TresMeshToonMaterial color="#efefef" />
     </TresMesh>
-    <TresGroup v-if="paneElements.groupVisible" :position="[0, -4, -5]">
+    <TresGroup
+      v-if="paneElements.groupVisible"
+      :position="[0, -4, -5]"
+    >
       <TresGroup>
         <TresMesh :position="[0, 0, 0]">
           <TresBoxGeometry :args="[1, 1, 1]" />
@@ -47,7 +67,7 @@ const material = new MeshPhongMaterial({ color: '#ff0000' })
         </TresMesh>
       </TresGroup>
     </TresGroup>
-    <OrbitControls></OrbitControls>
+    <OrbitControls />
     <TresAmbientLight :intensity="0.5" />
   </TresCanvas>
 </template>

+ 45 - 9
playground/src/components/TheEnvironment.vue

@@ -2,6 +2,7 @@
 import { ref, shallowRef, watch } from 'vue'
 import { Environment, Box, PamCameraMouse } from '@tresjs/cientos'
 import { TresCanvas } from '@tresjs/core'
+
 /* import { OrbitControls, GLTFModel } from '@tresjs/cientos' */
 
 const sphereRef = ref()
@@ -25,33 +26,68 @@ watch(environmentTexture, ({ getTexture }) => {
   envMap = getTexture()
 })
 </script>
+
 <template>
   <!--   <TresCanvas v-bind="state"> -->
   <TresCanvas preset="realistic">
-    <TresPerspectiveCamera :position="[10, 10, 18]" :fov="45" :near="0.1" :far="1000" :look-at="[-8, 3, -3]" />
+    <TresPerspectiveCamera
+      :position="[10, 10, 18]"
+      :fov="45"
+      :near="0.1"
+      :far="1000"
+      :look-at="[-8, 3, -3]"
+    />
     <PamCameraMouse :factor="2" />
 
     <Environment
       ref="environmentTexture"
       background
       :files="environmentFiles"
-      :path="'https://raw.githubusercontent.com/Tresjs/assets/main/textures/environmentMap'"
+      path="https://raw.githubusercontent.com/Tresjs/assets/main/textures/environmentMap"
     />
     <!--  <Environment ref="environmentTexture" background preset="sunset" /> -->
     <TresAmbientLight :intensity="0.5" />
 
-    <TresMesh ref="sphereRef" :position="[0, 4, 0]" cast-shadow>
+    <TresMesh
+      ref="sphereRef"
+      :position="[0, 4, 0]"
+      cast-shadow
+    >
       <TresSphereGeometry />
-      <TresMeshStandardMaterial color="#FBB03B" :map="envMap" :metalness="1" :roughness="0" />
+      <TresMeshStandardMaterial
+        color="#FBB03B"
+        :map="envMap"
+        :metalness="1"
+        :roughness="0"
+      />
     </TresMesh>
-    <Box :position="[2, 6, 0]" cast-shadow>
-      <TresMeshStandardMaterial color="#008080" :map="envMap" :metalness="1" :roughness="0" />
+    <Box
+      :position="[2, 6, 0]"
+      cast-shadow
+    >
+      <TresMeshStandardMaterial
+        color="#008080"
+        :map="envMap"
+        :metalness="1"
+        :roughness="0"
+      />
     </Box>
-    <TresDirectionalLight :position="[0, 8, 4]" :intensity="0.7" cast-shadow />
-    <TresMesh :rotation="[-Math.PI / 2, 0, 0]" receive-shadow>
+    <TresDirectionalLight
+      :position="[0, 8, 4]"
+      :intensity="0.7"
+      cast-shadow
+    />
+    <TresMesh
+      :rotation="[-Math.PI / 2, 0, 0]"
+      receive-shadow
+    >
       <TresPlaneGeometry :args="[20, 20, 20, 10]" />
       <TresMeshToonMaterial />
     </TresMesh>
-    <TresDirectionalLight :position="[0, 2, 4]" :intensity="1" cast-shadow />
+    <TresDirectionalLight
+      :position="[0, 2, 4]"
+      :intensity="1"
+      cast-shadow
+    />
   </TresCanvas>
 </template>

+ 24 - 22
playground/src/components/TheEvents.vue

@@ -41,30 +41,32 @@ const visible = ref(true)
 </script>
 
 <template>
-  <button @click="visible = !visible"></button>
+  <button @click="visible = !visible" />
   <div v-if="visible">
-    <TresCanvas window-size v-bind="gl">
-  
-    <OrbitControls />
+    <TresCanvas
+      window-size
+      v-bind="gl"
+    >
+      <OrbitControls />
 
-    <template v-for="x in [-2.5, 0, 2.5]">
-      <template v-for="y in [-2.5, 0, 2.5]">
-        <TresMesh
-          v-for="z in [-2.5, 0, 2.5]"
-          :key="`${[x, y, z]}`"
-          :position="[x, y, z]"
-          @click="onClick"
-          @pointer-enter="onPointerEnter"
-          @pointer-leave="onPointerLeave"
-          @pointer-move="onPointerMove"
-        >
-          <TresBoxGeometry :args="[1, 1, 1]" />
-          <TresMeshToonMaterial color="#efefef" />
-        </TresMesh>
+      <template v-for="x in [-2.5, 0, 2.5]">
+        <template v-for="y in [-2.5, 0, 2.5]">
+          <TresMesh
+            v-for="z in [-2.5, 0, 2.5]"
+            :key="`${[x, y, z]}`"
+            :position="[x, y, z]"
+            @click="onClick"
+            @pointer-enter="onPointerEnter"
+            @pointer-leave="onPointerLeave"
+            @pointer-move="onPointerMove"
+          >
+            <TresBoxGeometry :args="[1, 1, 1]" />
+            <TresMeshToonMaterial color="#efefef" />
+          </TresMesh>
+        </template>
       </template>
-    </template>
-    <TresDirectionalLight :intensity="1" />
-    <TresAmbientLight :intensity="1" />
-  </TresCanvas>
+      <TresDirectionalLight :intensity="1" />
+      <TresAmbientLight :intensity="1" />
+    </TresCanvas>
   </div>
 </template>

+ 41 - 10
playground/src/components/TheExperience.vue

@@ -2,8 +2,8 @@
 import { ref, watchEffect } from 'vue'
 import { BasicShadowMap, SRGBColorSpace, NoToneMapping } from 'three'
 import { TresCanvas } from '@tresjs/core'
-import TheSphere from './TheSphere.vue'
 import { OrbitControls } from '@tresjs/cientos'
+import TheSphere from './TheSphere.vue'
 
 const gl = {
   clearColor: '#82DBC5',
@@ -26,27 +26,58 @@ watchEffect(() => {
 </script>
 
 <template>
-  <div><button @click="wireframe = !wireframe">Click</button></div>
+  <div>
+    <button @click="wireframe = !wireframe">
+      Click
+    </button>
+  </div>
   <pre>{{ wireframe }}</pre>
-  <TresCanvas v-bind="gl" ref="context">
-    <TresPerspectiveCamera :position="[7, 7, 7]" :look-at="[0, 4, 0]" />
+  <TresCanvas
+    v-bind="gl"
+    ref="context"
+  >
+    <TresPerspectiveCamera
+      :position="[7, 7, 7]"
+      :look-at="[0, 4, 0]"
+    />
     <OrbitControls />
-    <TresFog :color="gl.clearColor" :near="5" :far="15" />
-    <TresMesh :position="[-2, 6, 0]" :rotation="[0, Math.PI, 0]" cast-shadow>
+    <TresFog
+      :color="gl.clearColor"
+      :near="5"
+      :far="15"
+    />
+    <TresMesh
+      :position="[-2, 6, 0]"
+      :rotation="[0, Math.PI, 0]"
+      cast-shadow
+    >
       <TresConeGeometry :args="[1, 1.5, 3]" />
       <TresMeshToonMaterial color="#82DBC5" />
     </TresMesh>
-    <TresMesh :position="[0, 4, 0]" cast-shadow>
+    <TresMesh
+      :position="[0, 4, 0]"
+      cast-shadow
+    >
       <TresBoxGeometry :args="[1.5, 1.5, 1.5]" />
-      <TresMeshToonMaterial color="#4F4F4F" :wireframe="wireframe" />
+      <TresMeshToonMaterial
+        color="#4F4F4F"
+        :wireframe="wireframe"
+      />
     </TresMesh>
-    <TresMesh :rotation="[-Math.PI / 2, 0, 0]" receive-shadow>
+    <TresMesh
+      :rotation="[-Math.PI / 2, 0, 0]"
+      receive-shadow
+    >
       <TresPlaneGeometry :args="[10, 10, 10, 10]" />
       <TresMeshToonMaterial color="#D3FC8A" />
     </TresMesh>
     <TheSphere />
     <TresAxesHelper :args="[1]" />
-    <TresDirectionalLight :position="[0, 2, 4]" :intensity="2" cast-shadow />
+    <TresDirectionalLight
+      :position="[0, 2, 4]"
+      :intensity="2"
+      cast-shadow
+    />
     <TresOrthographicCamera />
   </TresCanvas>
 </template>

+ 9 - 2
playground/src/components/TheFirstScene.vue

@@ -4,9 +4,16 @@ import { Vector3 } from 'three'
 </script>
 
 <template>
-  <TresCanvas ref="context" clear-color="#82DBC5" window-size>
+  <TresCanvas
+    clear-color="#82DBC5"
+    window-size
+  >
     <TresPerspectiveCamera />
-    <TresMesh :position="[1, 2, 3]" :scale="new Vector3(2, 2, 2)" :rotation="{ x: 1, y: 1, z: 1 }">
+    <TresMesh
+      :position="[1, 2, 3]"
+      :scale="new Vector3(2, 2, 2)"
+      :rotation="{ x: 1, y: 1, z: 1 }"
+    >
       <TresTorusGeometry :args="[1, 0.5, 16, 32]" />
       <TresMeshBasicMaterial color="orange" />
     </TresMesh>

+ 27 - 7
playground/src/components/TheGizmos.vue

@@ -37,7 +37,7 @@ pane
     ],
     value: transformState.mode,
   })
-  .on('change', ev => {
+  .on('change', (ev) => {
     transformState.mode = ev.value
   })
 
@@ -60,7 +60,7 @@ axisFolder
     ],
     value: transformState.axis,
   })
-  .on('change', ev => {
+  .on('change', (ev) => {
     transformState.axis = ev.value
   })
 axisFolder.addInput(transformState, 'showX')
@@ -70,20 +70,40 @@ axisFolder.addInput(transformState, 'showZ')
 
 <template>
   <TresCanvas v-bind="state">
-    <TresPerspectiveCamera :position="[11, 11, 11]" :fov="45" :near="0.1" :far="1000" :look-at="[-8, 3, -3]" />
+    <TresPerspectiveCamera
+      :position="[11, 11, 11]"
+      :fov="45"
+      :near="0.1"
+      :far="1000"
+      :look-at="[-8, 3, -3]"
+    />
 
     <OrbitControls make-default />
-    <TresMesh ref="boxRef" :position="[0, 4, 0]" cast-shadow>
+    <TresMesh
+      ref="boxRef"
+      :position="[0, 4, 0]"
+      cast-shadow
+    >
       <TresBoxGeometry :args="[1.5, 1.5, 1.5]" />
       <TresMeshToonMaterial color="#FBB03B" />
     </TresMesh>
-    <TransformControls :object="boxRef" v-bind="transformState" />
+    <TransformControls
+      :object="boxRef"
+      v-bind="transformState"
+    />
 
-    <TresMesh :rotation="[-Math.PI / 2, 0, 0]" receive-shadow>
+    <TresMesh
+      :rotation="[-Math.PI / 2, 0, 0]"
+      receive-shadow
+    >
       <TresPlaneGeometry :args="[10, 10, 10, 10]" />
       <TresMeshToonMaterial />
     </TresMesh>
     <TresAmbientLight :intensity="0.5" />
-    <TresDirectionalLight :position="[0, 8, 4]" :intensity="1.5" cast-shadow />
+    <TresDirectionalLight
+      :position="[0, 8, 4]"
+      :intensity="1.5"
+      cast-shadow
+    />
   </TresCanvas>
 </template>

+ 26 - 5
playground/src/components/TheGroups.vue

@@ -13,18 +13,39 @@ onLoop(() => {
   }
 })
 </script>
+
 <template>
   <div class="container">
     <TresCanvas>
-      <TresPerspectiveCamera :position="[5, 5, 5]" :fov="75" :aspect="1" :near="0.1" :far="1000" />
+      <TresPerspectiveCamera
+        :position="[5, 5, 5]"
+        :fov="75"
+        :aspect="1"
+        :near="0.1"
+        :far="1000"
+      />
       <OrbitControls />
-      <TresAmbientLight :color="0xffffff" :intensity="0.5" />
-      <TresGroup ref="groupRef" :position="[0, -4, -5]">
-        <TresMesh :scale="1" :position="[-4, 0, 0]" cast-shadow>
+      <TresAmbientLight
+        :color="0xffffff"
+        :intensity="0.5"
+      />
+      <TresGroup
+        ref="groupRef"
+        :position="[0, -4, -5]"
+      >
+        <TresMesh
+          :scale="1"
+          :position="[-4, 0, 0]"
+          cast-shadow
+        >
           <TresSphereGeometry :args="[1, 500, 500]" />
           <TresMeshToonMaterial color="#FBB03B" />
         </TresMesh>
-        <TresMesh :scale="1" :position="[4, 0, 0]" cast-shadow>
+        <TresMesh
+          :scale="1"
+          :position="[4, 0, 0]"
+          cast-shadow
+        >
           <TresSphereGeometry :args="[1, 500, 500]" />
           <TresMeshToonMaterial color="teal" />
         </TresMesh>

+ 17 - 3
playground/src/components/TheParticles.vue

@@ -67,15 +67,29 @@ onLoop(({ elapsed }) => {
   shader.uniforms.uTime.value = elapsed
 })
 </script>
+
 <template>
   <TresCanvas v-bind="gl">
-    <TresPerspectiveCamera :position="[5, 5, 5]" :fov="45" :near="0.1" :far="1000" :look-at="[-8, 3, -3]" />
+    <TresPerspectiveCamera
+      :position="[5, 5, 5]"
+      :fov="45"
+      :near="0.1"
+      :far="1000"
+      :look-at="[-8, 3, -3]"
+    />
     <OrbitControls />
     <TresAmbientLight :intensity="0.5" />
     <TresPoints>
-      <TresBufferGeometry :position="[positionArray, 3]" :a-scale="[scaleArray, 1]" />
+      <TresBufferGeometry
+        :position="[positionArray, 3]"
+        :a-scale="[scaleArray, 1]"
+      />
       <TresShaderMaterial v-bind="shader" />
     </TresPoints>
-    <TresDirectionalLight :position="[0, 2, 4]" :intensity="1" cast-shadow />
+    <TresDirectionalLight
+      :position="[0, 2, 4]"
+      :intensity="1"
+      cast-shadow
+    />
   </TresCanvas>
 </template>

+ 16 - 3
playground/src/components/TheSmallExperience.vue

@@ -2,13 +2,26 @@
 import { TresCanvas } from '@tresjs/core'
 import { OrbitControls } from '@tresjs/cientos/'
 </script>
+
 <template>
   <div class="container">
     <TresCanvas>
-      <TresPerspectiveCamera :position="[5, 5, 5]" :fov="75" :aspect="1" :near="0.1" :far="1000" />
+      <TresPerspectiveCamera
+        :position="[5, 5, 5]"
+        :fov="75"
+        :aspect="1"
+        :near="0.1"
+        :far="1000"
+      />
       <OrbitControls />
-      <TresAmbientLight :color="0xffffff" :intensity="0.5" />
-      <TresMesh ref="sphereRef" :scale="1" cast-shadow>
+      <TresAmbientLight
+        :color="0xffffff"
+        :intensity="0.5"
+      />
+      <TresMesh
+        :scale="1"
+        cast-shadow
+      >
         <TresSphereGeometry :args="[1, 500, 500]" />
         <TresMeshToonMaterial color="#FBB03B" />
       </TresMesh>

+ 5 - 1
playground/src/components/TheSphere.vue

@@ -1,6 +1,10 @@
 <script setup lang="ts"></script>
+
 <template>
-  <TresMesh :position="[2, 2, 0]" cast-shadow>
+  <TresMesh
+    :position="[2, 2, 0]"
+    cast-shadow
+  >
     <TresSphereGeometry />
     <TresMeshToonMaterial color="#FBB03B" />
   </TresMesh>

+ 27 - 5
playground/src/components/VectorSetProps.vue

@@ -2,6 +2,7 @@
 import { SRGBColorSpace, BasicShadowMap, NoToneMapping } from 'three'
 import { TresCanvas } from '@tresjs/core'
 import { OrbitControls } from '@tresjs/cientos'
+
 // import { useRenderLoop } from '..'
 /* import { OrbitControls, GLTFModel } from '@tresjs/cientos' */
 
@@ -23,8 +24,12 @@ watchEffect(() => {
   }
 })
 </script>
+
 <template>
-  <TresCanvas v-bind="state" ref="context">
+  <TresCanvas
+    v-bind="state"
+    ref="context"
+  >
     <TresPerspectiveCamera
       :position-x="5"
       :position-y="5"
@@ -63,13 +68,30 @@ watchEffect(() => {
       cast-shadow
     >
       <TresBoxGeometry />
-      <TresMeshToonMaterial :color-r="0xff / 255" :color-g="0x0 / 255" :color-b="0xff / 255" />
+      <TresMeshToonMaterial
+        :color-r="0xff / 255"
+        :color-g="0x0 / 255"
+        :color-b="0xff / 255"
+      />
     </TresMesh>
-    <TresDirectionalLight :position-y="8" :position-z="4" :intensity="0.7" cast-shadow />
-    <TresMesh :rotation="[-Math.PI / 2, 0, 0]" receive-shadow>
+    <TresDirectionalLight
+      :position-y="8"
+      :position-z="4"
+      :intensity="0.7"
+      cast-shadow
+    />
+    <TresMesh
+      :rotation="[-Math.PI / 2, 0, 0]"
+      receive-shadow
+    >
       <TresPlaneGeometry :args="[10, 10, 10, 10]" />
       <TresMeshToonMaterial />
     </TresMesh>
-    <TresDirectionalLight :position-y="2" :position-z="4" :intensity="1" cast-shadow />
+    <TresDirectionalLight
+      :position-y="2"
+      :position-z="4"
+      :intensity="1"
+      cast-shadow
+    />
   </TresCanvas>
 </template>

+ 10 - 3
playground/src/components/gltf/TheModel.vue

@@ -12,13 +12,20 @@ const { nodes, materials } = await useGLTF(
 
 const akuAkuRef = ref(null)
 
-watch(akuAkuRef, value => {
+watch(akuAkuRef, (value) => {
   console.log('akuAkuRef', value)
 })
 </script>
 
 <template>
-  <primitive ref="akuAkuRef" :object="nodes.Cactus">
-    <MeshWobbleMaterial :speed="10" :factor="0.4" :map="materials.Cactus.map" />
+  <primitive
+    ref="akuAkuRef"
+    :object="nodes.Cactus"
+  >
+    <MeshWobbleMaterial
+      :speed="10"
+      :factor="0.4"
+      :map="materials.Cactus.map"
+    />
   </primitive>
 </template>

+ 17 - 3
playground/src/components/gltf/index.vue

@@ -22,9 +22,19 @@ watchEffect(() => {
   }
 })
 </script>
+
 <template>
-  <TresCanvas v-bind="state" ref="context">
-    <TresPerspectiveCamera :position="[5, 5, 5]" :fov="45" :near="0.1" :far="1000" :look-at="[-8, 3, -3]" />
+  <TresCanvas
+    v-bind="state"
+    ref="context"
+  >
+    <TresPerspectiveCamera
+      :position="[5, 5, 5]"
+      :fov="45"
+      :near="0.1"
+      :far="1000"
+      :look-at="[-8, 3, -3]"
+    />
     <OrbitControls make-default />
     <TresAmbientLight :intensity="0.5" />
 
@@ -39,7 +49,11 @@ watchEffect(() => {
       </TresGroup>
     </Suspense>
     <TresAxesHelper />
-    <TresDirectionalLight :position="[0, 2, 4]" :intensity="1" cast-shadow />
+    <TresDirectionalLight
+      :position="[0, 2, 4]"
+      :intensity="1"
+      cast-shadow
+    />
   </TresCanvas>
 </template>
 0.5

+ 7 - 2
playground/src/components/meshWobbleMaterial/index.vue

@@ -1,8 +1,8 @@
 <script setup lang="ts">
 import { useRenderLoop, extend } from '@tresjs/core'
 
-import { WobbleMaterialImpl as MeshWobbleMaterial } from './material'
 import { shallowRef, watchEffect } from 'vue'
+import { WobbleMaterialImpl as MeshWobbleMaterial } from './material'
 
 const props = withDefaults(
   defineProps<{
@@ -31,6 +31,11 @@ onLoop(({ elapsed }) => {
   }
 })
 </script>
+
 <template>
-  <TresMeshWobbleMaterial ref="materialRef" :factor="factor" v-bind="$attrs" />
+  <TresMeshWobbleMaterial
+    ref="materialRef"
+    :factor="factor"
+    v-bind="$attrs"
+  />
 </template>

+ 2 - 1
playground/src/components/meshWobbleMaterial/material.ts

@@ -1,4 +1,5 @@
-import { MeshStandardMaterial, MeshStandardMaterialParameters, Shader } from 'three'
+import type { MeshStandardMaterialParameters, Shader } from 'three'
+import { MeshStandardMaterial } from 'three'
 
 // Borrowed from @pmdrs drei implementation https://github.com/pmndrs/drei/blob/master/src/core/MeshWobbleMaterial.tsx
 interface Uniform<T> {

+ 5 - 1
playground/src/components/portal-journey/TheFireFlies.vue

@@ -35,9 +35,13 @@ onLoop(({ elapsed }) => {
   shader.uniforms.uTime.value = elapsed
 })
 </script>
+
 <template>
   <TresPoints>
-    <TresBufferGeometry :position="[positionArray, 3]" :a-scale="[scaleArray, 1]" />
+    <TresBufferGeometry
+      :position="[positionArray, 3]"
+      :a-scale="[scaleArray, 1]"
+    />
     <TresShaderMaterial v-bind="shader" />
   </TresPoints>
 </template>

+ 30 - 27
playground/src/components/portal-journey/ThePortal.vue

@@ -1,5 +1,6 @@
 <script setup lang="ts">
-import { SRGBColorSpace, DoubleSide, MeshBasicMaterial, ShaderMaterial, Color, Mesh } from 'three'
+import type { Mesh } from 'three'
+import { SRGBColorSpace, DoubleSide, MeshBasicMaterial, ShaderMaterial, Color } from 'three'
 import { useRenderLoop, useTexture } from '@tresjs/core'
 import { useGLTF, useTweakPane } from '@tresjs/cientos'
 
@@ -11,30 +12,6 @@ const experiment = {
   portalColorEnd: '#ddc0ff',
 }
 
-const { pane } = useTweakPane()
-
-const portalCtrls = pane.addFolder({ title: 'Portal' })
-portalCtrls
-  .addInput(experiment, 'portalColorStart', {
-    label: 'color start',
-    min: 0,
-    max: 1,
-    step: 0.01,
-  })
-  .on('change', ({ value }) => {
-    portalLightMaterial.uniforms.uColorStart.value.set(value)
-  })
-portalCtrls
-  .addInput(experiment, 'portalColorEnd', {
-    label: 'color end',
-    min: 0,
-    max: 1,
-    step: 0.01,
-  })
-  .on('change', ({ value }) => {
-    portalLightMaterial.uniforms.uColorEnd.value.set(value)
-  })
-
 const { scene: portal } = await useGLTF(
   'https://raw.githubusercontent.com/Tresjs/assets/main/models/gltf/portal/portal.glb',
   {
@@ -68,16 +45,42 @@ const portalLightMaterial = new ShaderMaterial({
 
 const portalObj = portal
 const bakedMesh = portalObj.children.find(child => child.name === 'baked')
-;(bakedMesh as Mesh).material = bakedMaterial
+  ; (bakedMesh as Mesh).material = bakedMaterial
 const portalCircle = portalObj.children.find(child => child.name === 'portalCircle')
-;(portalCircle as Mesh).material = portalLightMaterial
+  ; (portalCircle as Mesh).material = portalLightMaterial
 
 const { onLoop } = useRenderLoop()
 
 onLoop(({ elapsed }) => {
   portalLightMaterial.uniforms.uTime.value = elapsed
 })
+
+// Controls
+const { pane } = useTweakPane()
+
+const portalCtrls = pane.addFolder({ title: 'Portal' })
+portalCtrls
+  .addInput(experiment, 'portalColorStart', {
+    label: 'color start',
+    min: 0,
+    max: 1,
+    step: 0.01,
+  })
+  .on('change', ({ value }) => {
+    portalLightMaterial.uniforms.uColorStart.value.set(value)
+  })
+portalCtrls
+  .addInput(experiment, 'portalColorEnd', {
+    label: 'color end',
+    min: 0,
+    max: 1,
+    step: 0.01,
+  })
+  .on('change', ({ value }) => {
+    portalLightMaterial.uniforms.uColorEnd.value.set(value)
+  })
 </script>
+
 <template>
   <TresMesh v-bind="portal" />
 </template>

+ 12 - 2
playground/src/components/portal-journey/index.vue

@@ -13,13 +13,23 @@ const gl = {
 
 <template>
   <TresCanvas v-bind="gl">
-    <TresPerspectiveCamera :position="[5, 5, 5]" :fov="45" :aspect="1" :near="0.1" :far="1000" />
+    <TresPerspectiveCamera
+      :position="[5, 5, 5]"
+      :fov="45"
+      :aspect="1"
+      :near="0.1"
+      :far="1000"
+    />
     <OrbitControls />
     <TresFog :args="[gl.clearColor, 0.1, 75]" />
     <Suspense>
       <ThePortal />
     </Suspense>
     <TheFireFlies />
-    <TresAmbientLight :position="[10, 10, 10]" :intensity="1.5" color="#00ff00" />
+    <TresAmbientLight
+      :position="[10, 10, 10]"
+      :intensity="1.5"
+      color="#00ff00"
+    />
   </TresCanvas>
 </template>

+ 12 - 4
playground/src/components/shaders-experiment/index.vue

@@ -1,10 +1,11 @@
 <script setup lang="ts">
 import { BasicShadowMap, SRGBColorSpace, NoToneMapping, Vector2 } from 'three'
-import { TresCanvas, TresInstance, useRenderLoop } from '@tresjs/core'
+import type { TresInstance } from '@tresjs/core'
+import { TresCanvas, useRenderLoop } from '@tresjs/core'
 import { OrbitControls } from '@tresjs/cientos'
+import type { ShallowRef } from 'vue'
 import vertexShader from './shaders/vertex.glsl'
 import fragmentShader from './shaders/fragment.glsl'
-import { ShallowRef } from 'vue'
 
 const gl = {
   clearColor: '#4f4f4f',
@@ -35,9 +36,16 @@ onLoop(({ elapsed }) => {
   <TresCanvas v-bind="gl">
     <TresPerspectiveCamera :position="[11, 11, 11]" />
     <OrbitControls />
-    <TresMesh ref="blobRef" :position="[0, 4, 0]">
+    <TresMesh
+      ref="blobRef"
+      :position="[0, 4, 0]"
+    >
       <TresSphereGeometry :args="[2, 32, 32]" />
-      <TresShaderMaterial :vertex-shader="vertexShader" :fragment-shader="fragmentShader" :uniforms="uniforms" />
+      <TresShaderMaterial
+        :vertex-shader="vertexShader"
+        :fragment-shader="fragmentShader"
+        :uniforms="uniforms"
+      />
     </TresMesh>
     <TresMesh :rotation="[-Math.PI / 2, 0, 0]">
       <TresPlaneGeometry :args="[10, 10, 10, 10]" />

+ 17 - 3
playground/src/components/udsz/index.vue

@@ -22,9 +22,19 @@ watchEffect(() => {
   }
 })
 </script>
+
 <template>
-  <TresCanvas v-bind="state" ref="context">
-    <TresPerspectiveCamera :position="[5, 5, 5]" :fov="45" :near="0.1" :far="1000" :look-at="[-8, 3, -3]" />
+  <TresCanvas
+    v-bind="state"
+    ref="context"
+  >
+    <TresPerspectiveCamera
+      :position="[5, 5, 5]"
+      :fov="45"
+      :near="0.1"
+      :far="1000"
+      :look-at="[-8, 3, -3]"
+    />
     <OrbitControls make-default />
     <TresAmbientLight :intensity="0.5" />
 
@@ -32,6 +42,10 @@ watchEffect(() => {
       <TheUSDZModel />
     </Suspense>
     <TresAxesHelper />
-    <TresDirectionalLight :position="[0, 2, 4]" :intensity="1" cast-shadow />
+    <TresDirectionalLight
+      :position="[0, 2, 4]"
+      :intensity="1"
+      cast-shadow
+    />
   </TresCanvas>
 </template>

+ 1 - 0
playground/src/pages/index.vue

@@ -1,4 +1,5 @@
 <script setup lang="ts"></script>
+
 <template>
   <DebugUI />
 </template>

+ 48 - 14
playground/src/pages/multiple-cameras.vue

@@ -1,8 +1,9 @@
 <script setup lang="ts">
-import { Camera } from 'three'
+import type { Camera } from 'three'
 import { TresCanvas } from '@tresjs/core'
-import { TresLeches, useControls } from '@tresjs/leches';
+import { TresLeches, useControls } from '@tresjs/leches'
 import '@tresjs/leches/styles'
+
 const state = reactive({
   clearColor: '#4f4f4f',
   shadows: true,
@@ -15,7 +16,6 @@ const camera1 = shallowRef<Camera>()
 const camera2 = shallowRef<Camera>()
 const camera3 = shallowRef<Camera>()
 
-
 const activeCameraUuid = ref<string>()
 
 watchEffect(() => {
@@ -29,20 +29,51 @@ const camera3Exists = ref(false)
   <div>
     {{ activeCameraUuid }}
     <select v-model="activeCameraUuid">
-      <option :value="camera1?.uuid">cam 1</option>
-      <option :value="camera2?.uuid">cam 2</option>
-      <option v-if="camera3Exists" :value="camera3?.uuid">cam 3</option>
+      <option :value="camera1?.uuid">
+        cam 1
+      </option>
+      <option :value="camera2?.uuid">
+        cam 2
+      </option>
+      <option
+        v-if="camera3Exists"
+        :value="camera3?.uuid"
+      >
+        cam 3
+      </option>
     </select>
-    <input v-model="camera3Exists" type="checkbox">
+    <input
+      v-model="camera3Exists"
+      type="checkbox"
+    >
     <div class="w-1/2 aspect-video">
       <TresCanvas v-bind="state">
         <TheCameraOperator :active-camera-uuid="activeCameraUuid">
-          <TresPerspectiveCamera ref="camera1" :position="[5, 5, 5]" :fov="45" :near="0.1" :far="1000"
-            :look-at="[0, 4, 0]" />
-          <TresPerspectiveCamera ref="camera2" :position="[15, 5, 5]" :fov="45" :near="0.1" :far="1000"
-            :look-at="[0, 4, 0]" />
-          <TresPerspectiveCamera v-if="camera3Exists" ref="camera3" :position="[-15, 8, 5]" :fov="25" :near="0.1"
-            :far="1000" :look-at="[0, 4, 0]" />
+          <TresPerspectiveCamera
+            ref="camera1"
+            :position="[5, 5, 5]"
+            :fov="45"
+            :near="0.1"
+            :far="1000"
+            :look-at="[0, 4, 0]"
+          />
+          <TresPerspectiveCamera
+            ref="camera2"
+            :position="[15, 5, 5]"
+            :fov="45"
+            :near="0.1"
+            :far="1000"
+            :look-at="[0, 4, 0]"
+          />
+          <TresPerspectiveCamera
+            v-if="camera3Exists"
+            ref="camera3"
+            :position="[-15, 8, 5]"
+            :fov="25"
+            :near="0.1"
+            :far="1000"
+            :look-at="[0, 4, 0]"
+          />
         </TheCameraOperator>
         <LocalOrbitControls />
         <TresAmbientLight :intensity="0.5" />
@@ -54,7 +85,10 @@ const camera3Exists = ref(false)
         <Suspense>
           <TestSphere />
         </Suspense>
-        <TresDirectionalLight :position="[0, 2, 4]" :intensity="1" />
+        <TresDirectionalLight
+          :position="[0, 2, 4]"
+          :intensity="1"
+        />
       </TresCanvas>
     </div>
     <TresLeches />

+ 1 - 0
playground/src/pages/multiple.vue

@@ -1,4 +1,5 @@
 <script setup lang="ts"></script>
+
 <template>
   <Suspense>
     <MultipleCanvas />

+ 13 - 4
playground/src/pages/no-camera.vue

@@ -1,6 +1,6 @@
 <script setup lang="ts">
 import { TresCanvas } from '@tresjs/core'
-import { PerspectiveCamera } from 'three';
+import { PerspectiveCamera } from 'three'
 
 const state = reactive({
   clearColor: '#4f4f4f',
@@ -17,9 +17,15 @@ const useOwnCamera = ref(false)
 
 <template>
   <div>
-    <input v-model="useOwnCamera" type="checkbox">
+    <input
+      v-model="useOwnCamera"
+      type="checkbox"
+    >
     <div class="w-1/2 aspect-video">
-      <TresCanvas v-bind="state" :camera="useOwnCamera ? camera : undefined">
+      <TresCanvas
+        v-bind="state"
+        :camera="useOwnCamera ? camera : undefined"
+      >
         <LocalOrbitControls />
         <TresAmbientLight :intensity="0.5" />
         <TresMesh :position="[0, 4, 0]">
@@ -30,7 +36,10 @@ const useOwnCamera = ref(false)
         <Suspense>
           <TestSphere />
         </Suspense>
-        <TresDirectionalLight :position="[0, 2, 4]" :intensity="1" />
+        <TresDirectionalLight
+          :position="[0, 2, 4]"
+          :intensity="1"
+        />
       </TresCanvas>
     </div>
   </div>

+ 114 - 29
playground/src/pages/shapes.vue

@@ -39,37 +39,37 @@ const icosahedronRef = shallowRef()
 const octahedronRef = shallowRef()
 const dodecahedronRef = shallowRef()
 
-watch(planeRef, plane => {
+watch(planeRef, (plane) => {
   console.log('plane', plane.value.position)
 })
-watch(boxRef, box => {
+watch(boxRef, (box) => {
   console.log('box', box.value.position)
 })
-watch(torusRef, torus => {
+watch(torusRef, (torus) => {
   console.log('torus', torus.value.position)
 })
-watch(torusKnotRef, torusKnot => {
+watch(torusKnotRef, (torusKnot) => {
   console.log('torusKnot', torusKnot.value.position)
 })
-watch(circleRef, circle => {
+watch(circleRef, (circle) => {
   console.log('circle', circle.value.position)
 })
-watch(tubeRef, tube => {
+watch(tubeRef, (tube) => {
   console.log('tube', tube.value.position)
 })
-watch(ringRef, ring => {
+watch(ringRef, (ring) => {
   console.log('ring', ring.value.position)
 })
-watch(tetrahedronRef, tetrahedron => {
+watch(tetrahedronRef, (tetrahedron) => {
   console.log('tetrahedron', tetrahedron.value.position)
 })
-watch(icosahedronRef, icosahedron => {
+watch(icosahedronRef, (icosahedron) => {
   console.log('icosahedron', icosahedron.value.position)
 })
-watch(octahedronRef, octahedron => {
+watch(octahedronRef, (octahedron) => {
   console.log('octahedron', octahedron.value.position)
 })
-watch(dodecahedronRef, dodecahedron => {
+watch(dodecahedronRef, (dodecahedron) => {
   console.log('dodecahedron', dodecahedron.value.position)
 })
 
@@ -83,47 +83,132 @@ const tubePath = new CubicBezierCurve3(
 
 <template>
   <TresCanvas v-bind="state">
-    <TresPerspectiveCamera :position="[5, 5, 5]" :fov="75" :aspect="1" :near="0.1" :far="1000" />
+    <TresPerspectiveCamera
+      :position="[5, 5, 5]"
+      :fov="75"
+      :aspect="1"
+      :near="0.1"
+      :far="1000"
+    />
 
-    <TresAmbientLight :color="0xffffff" :intensity="1" />
-    <TresDirectionalLight :position="[0, 8, 4]" :intensity="0.7" cast-shadow />
-    <Plane ref="planeRef" :args="[12, 8]" :position="[-2, 4, 0]" receive-shadow>
+    <TresAmbientLight
+      :color="0xffffff"
+      :intensity="1"
+    />
+    <TresDirectionalLight
+      :position="[0, 8, 4]"
+      :intensity="0.7"
+      cast-shadow
+    />
+    <Plane
+      ref="planeRef"
+      :args="[12, 8]"
+      :position="[-2, 4, 0]"
+      receive-shadow
+    >
       <TresMeshToonMaterial color="teal" />
     </Plane>
-    <Box ref="boxRef" :arg0s="[1, 1, 1]" :position="[0, 6, 0]" cast-shadow>
+    <Box
+      ref="boxRef"
+      :arg0s="[1, 1, 1]"
+      :position="[0, 6, 0]"
+      cast-shadow
+    >
       <TresMeshToonMaterial color="orange" />
     </Box>
-    <Sphere ref="sphereRef" :args="[1, 32, 16]" :position="[2, 6, 0]" cast-shadow>
+    <Sphere
+      :args="[1, 32, 16]"
+      :position="[2, 6, 0]"
+      cast-shadow
+    >
       <TresMeshToonMaterial color="pink" />
     </Sphere>
-    <Torus ref="torusRef" :args="[0.75, 0.4, 16, 80]" :position="[-2, 6, 0]" cast-shadow>
+    <Torus
+      ref="torusRef"
+      :args="[0.75, 0.4, 16, 80]"
+      :position="[-2, 6, 0]"
+      cast-shadow
+    >
       <TresMeshToonMaterial color="cyan" />
     </Torus>
-    <TorusKnot ref="torusKnotRef" :args="[0.6, 0.2, 64, 8]" :position="[-2, 6, 2]" cast-shadow>
+    <TorusKnot
+      ref="torusKnotRef"
+      :args="[0.6, 0.2, 64, 8]"
+      :position="[-2, 6, 2]"
+      cast-shadow
+    >
       <TresMeshToonMaterial color="lime" />
     </TorusKnot>
-    <Circle ref="circleRef" :args="[0.9, 32]" :position="[0, 6, 2]" :rotation="[Math.PI, 0, 0]" cast-shadow>
-      <TresMeshToonMaterial color="lightsalmon" :side="DoubleSide" />
+    <Circle
+      ref="circleRef"
+      :args="[0.9, 32]"
+      :position="[0, 6, 2]"
+      :rotation="[Math.PI, 0, 0]"
+      cast-shadow
+    >
+      <TresMeshToonMaterial
+        color="lightsalmon"
+        :side="DoubleSide"
+      />
     </Circle>
-    <Cone ref="coneRef" :args="[1, 1, 6]" :position="[2, 6, 2]" :rotation="[Math.PI, 0, 0]" cast-shadow>
+    <Cone
+      :args="[1, 1, 6]"
+      :position="[2, 6, 2]"
+      :rotation="[Math.PI, 0, 0]"
+      cast-shadow
+    >
       <TresMeshToonMaterial color="slateblue" />
     </Cone>
-    <Tube ref="tubeRef" :args="[tubePath, 20, 0.2, 8, false]" :position="[2, 6, -2]" cast-shadow>
+    <Tube
+      ref="tubeRef"
+      :args="[tubePath, 20, 0.2, 8, false]"
+      :position="[2, 6, -2]"
+      cast-shadow
+    >
       <TresMeshToonMaterial color="lightblue" />
     </Tube>
-    <Ring ref="ringRef" :args="[0.5, 1, 32]" :position="[0, 6, -2]" :rotation="[Math.PI, 0, 0]" cast-shadow>
-      <TresMeshToonMaterial color="purple" :side="DoubleSide" />
+    <Ring
+      ref="ringRef"
+      :args="[0.5, 1, 32]"
+      :position="[0, 6, -2]"
+      :rotation="[Math.PI, 0, 0]"
+      cast-shadow
+    >
+      <TresMeshToonMaterial
+        color="purple"
+        :side="DoubleSide"
+      />
     </Ring>
-    <Tetrahedron ref="tetrahedronRef" :args="[1, 0]" :position="[-2, 6, -2]" cast-shadow>
+    <Tetrahedron
+      ref="tetrahedronRef"
+      :args="[1, 0]"
+      :position="[-2, 6, -2]"
+      cast-shadow
+    >
       <TresMeshToonMaterial color="yellow" />
     </Tetrahedron>
-    <Icosahedron ref="icosahedronRef" :args="[1, 0]" :position="[-4, 6, -2]" cast-shadow>
+    <Icosahedron
+      ref="icosahedronRef"
+      :args="[1, 0]"
+      :position="[-4, 6, -2]"
+      cast-shadow
+    >
       <TresMeshToonMaterial color="red" />
     </Icosahedron>
-    <Octahedron ref="octahedronRef" :args="[1, 0]" :position="[-4, 6, 0]" cast-shadow>
+    <Octahedron
+      ref="octahedronRef"
+      :args="[1, 0]"
+      :position="[-4, 6, 0]"
+      cast-shadow
+    >
       <TresMeshToonMaterial color="greenyellow" />
     </Octahedron>
-    <Dodecahedron ref="dodecahedronRef" :args="[1, 0]" :position="[-4, 6, 2]" cast-shadow>
+    <Dodecahedron
+      ref="dodecahedronRef"
+      :args="[1, 0]"
+      :position="[-4, 6, 2]"
+      cast-shadow
+    >
       <TresMeshToonMaterial color="deeppink" />
     </Dodecahedron>
   </TresCanvas>

+ 22 - 22
playground/src/router.ts

@@ -1,28 +1,28 @@
 import { createRouter, createWebHistory } from 'vue-router'
 
 const routes = [
-    {
-        path: '/',
-        name: 'Home',
-        component: () => import('./pages/index.vue'),
-    },
-    {
-        path: '/multiple',
-        name: 'Multiple',
-        component: () => import('./pages/multiple.vue'),
-    },
-    {
-        path: '/multiple-cameras',
-        name: 'Multiple Cameras',
-        component: () => import('./pages/multiple-cameras.vue'),
-    },
-    {
-        path: '/no-camera',
-        name: 'No Camera',
-        component: () => import('./pages/no-camera.vue'),
-    },
+  {
+    path: '/',
+    name: 'Home',
+    component: () => import('./pages/index.vue'),
+  },
+  {
+    path: '/multiple',
+    name: 'Multiple',
+    component: () => import('./pages/multiple.vue'),
+  },
+  {
+    path: '/multiple-cameras',
+    name: 'Multiple Cameras',
+    component: () => import('./pages/multiple-cameras.vue'),
+  },
+  {
+    path: '/no-camera',
+    name: 'No Camera',
+    component: () => import('./pages/no-camera.vue'),
+  },
 ]
 export const router = createRouter({
-    history: createWebHistory(),
-    routes
+  history: createWebHistory(),
+  routes,
 })

+ 1 - 1
playground/vite.config.ts

@@ -15,7 +15,7 @@ export default defineConfig({
       script: {
         propsDestructure: true,
       },
-      ...templateCompilerOptions
+      ...templateCompilerOptions,
     }),
     AutoImport({
       dts: true,

+ 570 - 0
pnpm-lock.yaml

@@ -30,6 +30,9 @@ importers:
       '@tresjs/cientos':
         specifier: 3.1.0
         version: 3.1.0(three@0.155.0)(tweakpane@4.0.0)(vue@3.3.4)
+      '@tresjs/eslint-config-vue':
+        specifier: ^0.1.1
+        version: 0.1.1(@typescript-eslint/eslint-plugin@6.4.1)(eslint@8.47.0)(typescript@5.1.6)
       '@types/three':
         specifier: ^0.155.1
         version: 0.155.1
@@ -1408,6 +1411,70 @@ packages:
     transitivePeerDependencies:
       - '@vue/composition-api'
 
+  /@tresjs/eslint-config-base@0.1.1(@typescript-eslint/eslint-plugin@6.4.1)(@typescript-eslint/parser@6.4.1)(eslint@8.47.0):
+    resolution: {integrity: sha512-BAbFYERV23H3dkFZ9ITQQrpPgPVvNqsl+CcyDlpav54ailN2zuIY28NNXkREHf8KL+QeQZZLedcDWJbffKxMgg==}
+    peerDependencies:
+      eslint: '>=7.4.0'
+    dependencies:
+      eslint: 8.47.0
+      eslint-plugin-eslint-comments: 3.2.0(eslint@8.47.0)
+      eslint-plugin-html: 7.1.0
+      eslint-plugin-import: 2.28.1(@typescript-eslint/parser@6.4.1)(eslint@8.47.0)
+      eslint-plugin-jsonc: 2.9.0(eslint@8.47.0)
+      eslint-plugin-markdown: 3.0.1(eslint@8.47.0)
+      eslint-plugin-n: 16.0.2(eslint@8.47.0)
+      eslint-plugin-no-only-tests: 3.1.0
+      eslint-plugin-promise: 6.1.1(eslint@8.47.0)
+      eslint-plugin-unicorn: 48.0.1(eslint@8.47.0)
+      eslint-plugin-unused-imports: 3.0.0(@typescript-eslint/eslint-plugin@6.4.1)(eslint@8.47.0)
+      eslint-plugin-yml: 1.8.0(eslint@8.47.0)
+      jsonc-eslint-parser: 2.3.0
+      yaml-eslint-parser: 1.2.2
+    transitivePeerDependencies:
+      - '@typescript-eslint/eslint-plugin'
+      - '@typescript-eslint/parser'
+      - eslint-import-resolver-typescript
+      - eslint-import-resolver-webpack
+      - supports-color
+    dev: true
+
+  /@tresjs/eslint-config-ts@0.1.1(eslint@8.47.0)(typescript@5.1.6):
+    resolution: {integrity: sha512-VkW0Pgd8OswsP1m0P5S0bupIvunA+mvtVX7vz3b08ONpxTvYzBos1FL0GmxaUrCjT1FkMDXGvNH9lth25X1Y4w==}
+    peerDependencies:
+      eslint: '>=7.4.0'
+      typescript: '>=3.9'
+    dependencies:
+      '@tresjs/eslint-config-base': 0.1.1(@typescript-eslint/eslint-plugin@6.4.1)(@typescript-eslint/parser@6.4.1)(eslint@8.47.0)
+      '@typescript-eslint/eslint-plugin': 6.4.1(@typescript-eslint/parser@6.4.1)(eslint@8.47.0)(typescript@5.1.6)
+      '@typescript-eslint/parser': 6.4.1(eslint@8.47.0)(typescript@5.1.6)
+      eslint: 8.47.0
+      typescript: 5.1.6
+    transitivePeerDependencies:
+      - eslint-import-resolver-typescript
+      - eslint-import-resolver-webpack
+      - supports-color
+    dev: true
+
+  /@tresjs/eslint-config-vue@0.1.1(@typescript-eslint/eslint-plugin@6.4.1)(eslint@8.47.0)(typescript@5.1.6):
+    resolution: {integrity: sha512-1zE4mPkwdNA/Tz44thZ0b11F2thZqzICxshGJFUZCpqSQa28gxXFpOyChjNA9sjAbSuGBvTdSRmJXUz2+naO4Q==}
+    peerDependencies:
+      eslint: '>=7.4.0'
+      typescript: '>=3.9'
+    dependencies:
+      '@tresjs/eslint-config-base': 0.1.1(@typescript-eslint/eslint-plugin@6.4.1)(@typescript-eslint/parser@6.4.1)(eslint@8.47.0)
+      '@tresjs/eslint-config-ts': 0.1.1(eslint@8.47.0)(typescript@5.1.6)
+      '@typescript-eslint/parser': 6.4.1(eslint@8.47.0)(typescript@5.1.6)
+      eslint: 8.47.0
+      eslint-plugin-vue: 9.17.0(eslint@8.47.0)
+      local-pkg: 0.4.3
+      typescript: 5.1.6
+    transitivePeerDependencies:
+      - '@typescript-eslint/eslint-plugin'
+      - eslint-import-resolver-typescript
+      - eslint-import-resolver-webpack
+      - supports-color
+    dev: true
+
   /@tresjs/leches@0.7.0(vue@3.3.4):
     resolution: {integrity: sha512-WuPAvFdNuxaLTS5x6/6rTd9+X/VlxOiyWFz2f2sibAOOb9uAmugVKRvKJ3wiCCNHQetx1G4zFUfVWzZHx4DFRw==}
     peerDependencies:
@@ -1482,6 +1549,16 @@ packages:
     resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==}
     dev: true
 
+  /@types/json5@0.0.29:
+    resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
+    dev: true
+
+  /@types/mdast@3.0.12:
+    resolution: {integrity: sha512-DT+iNIRNX884cx0/Q1ja7NyUPpZuv0KPyL5rGNxm1WC1OtHstl7n4Jb7nk+xacNShQMbczJjt8uFzznpp6kYBg==}
+    dependencies:
+      '@types/unist': 2.0.8
+    dev: true
+
   /@types/minimatch@5.1.2:
     resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==}
     dev: true
@@ -1524,6 +1601,10 @@ packages:
       meshoptimizer: 0.18.1
     dev: true
 
+  /@types/unist@2.0.8:
+    resolution: {integrity: sha512-d0XxK3YTObnWVp6rZuev3c49+j4Lo8g4L1ZRm9z5L0xpoZycUPshHgczK5gsUMaZOstjVYYi09p5gYvUtfChYw==}
+    dev: true
+
   /@types/web-bluetooth@0.0.17:
     resolution: {integrity: sha512-4p9vcSmxAayx72yn70joFoL44c9MO/0+iVEBIQXe3v2h2SiAsEIo/G5v6ObFWvNKRFjbrVadNf9LqEEZeQPzdA==}
 
@@ -2312,11 +2393,53 @@ packages:
     resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==}
     dev: true
 
+  /array-includes@3.1.6:
+    resolution: {integrity: sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      call-bind: 1.0.2
+      define-properties: 1.2.0
+      es-abstract: 1.22.1
+      get-intrinsic: 1.2.1
+      is-string: 1.0.7
+    dev: true
+
   /array-union@2.1.0:
     resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
     engines: {node: '>=8'}
     dev: true
 
+  /array.prototype.findlastindex@1.2.3:
+    resolution: {integrity: sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      call-bind: 1.0.2
+      define-properties: 1.2.0
+      es-abstract: 1.22.1
+      es-shim-unscopables: 1.0.0
+      get-intrinsic: 1.2.1
+    dev: true
+
+  /array.prototype.flat@1.3.1:
+    resolution: {integrity: sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      call-bind: 1.0.2
+      define-properties: 1.2.0
+      es-abstract: 1.22.1
+      es-shim-unscopables: 1.0.0
+    dev: true
+
+  /array.prototype.flatmap@1.3.1:
+    resolution: {integrity: sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      call-bind: 1.0.2
+      define-properties: 1.2.0
+      es-abstract: 1.22.1
+      es-shim-unscopables: 1.0.0
+    dev: true
+
   /array.prototype.map@1.0.5:
     resolution: {integrity: sha512-gfaKntvwqYIuC7mLLyv2wzZIJqrRhn5PZ9EfFejSx6a78sV7iDsGpG9P+3oUPtm1Rerqm6nrKS4FYuTIvWfo3g==}
     engines: {node: '>= 0.4'}
@@ -2481,6 +2604,17 @@ packages:
       ieee754: 1.2.1
     dev: true
 
+  /builtin-modules@3.3.0:
+    resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==}
+    engines: {node: '>=6'}
+    dev: true
+
+  /builtins@5.0.1:
+    resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==}
+    dependencies:
+      semver: 7.5.4
+    dev: true
+
   /bundle-name@3.0.0:
     resolution: {integrity: sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==}
     engines: {node: '>=12'}
@@ -2610,6 +2744,18 @@ packages:
     engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
     dev: true
 
+  /character-entities-legacy@1.1.4:
+    resolution: {integrity: sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==}
+    dev: true
+
+  /character-entities@1.2.4:
+    resolution: {integrity: sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==}
+    dev: true
+
+  /character-reference-invalid@1.1.4:
+    resolution: {integrity: sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==}
+    dev: true
+
   /chardet@0.7.0:
     resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==}
     dev: true
@@ -2648,6 +2794,13 @@ packages:
     engines: {node: '>=8'}
     dev: true
 
+  /clean-regexp@1.0.0:
+    resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==}
+    engines: {node: '>=4'}
+    dependencies:
+      escape-string-regexp: 1.0.5
+    dev: true
+
   /cli-boxes@3.0.0:
     resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==}
     engines: {node: '>=10'}
@@ -3058,6 +3211,17 @@ packages:
     resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==}
     dev: true
 
+  /debug@3.2.7:
+    resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
+    peerDependencies:
+      supports-color: '*'
+    peerDependenciesMeta:
+      supports-color:
+        optional: true
+    dependencies:
+      ms: 2.1.2
+    dev: true
+
   /debug@4.3.4:
     resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
     engines: {node: '>=6.0'}
@@ -3199,6 +3363,13 @@ packages:
       path-type: 4.0.0
     dev: true
 
+  /doctrine@2.1.0:
+    resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      esutils: 2.0.3
+    dev: true
+
   /doctrine@3.0.0:
     resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
     engines: {node: '>=6.0.0'}
@@ -3375,6 +3546,12 @@ packages:
       has-tostringtag: 1.0.0
     dev: true
 
+  /es-shim-unscopables@1.0.0:
+    resolution: {integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==}
+    dependencies:
+      has: 1.0.3
+    dev: true
+
   /es-to-primitive@1.2.1:
     resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==}
     engines: {node: '>= 0.4'}
@@ -3490,6 +3667,202 @@ packages:
       eslint: 8.47.0
     dev: true
 
+  /eslint-import-resolver-node@0.3.9:
+    resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==}
+    dependencies:
+      debug: 3.2.7
+      is-core-module: 2.13.0
+      resolve: 1.22.4
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.4.1)(eslint-import-resolver-node@0.3.9)(eslint@8.47.0):
+    resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==}
+    engines: {node: '>=4'}
+    peerDependencies:
+      '@typescript-eslint/parser': '*'
+      eslint: '*'
+      eslint-import-resolver-node: '*'
+      eslint-import-resolver-typescript: '*'
+      eslint-import-resolver-webpack: '*'
+    peerDependenciesMeta:
+      '@typescript-eslint/parser':
+        optional: true
+      eslint:
+        optional: true
+      eslint-import-resolver-node:
+        optional: true
+      eslint-import-resolver-typescript:
+        optional: true
+      eslint-import-resolver-webpack:
+        optional: true
+    dependencies:
+      '@typescript-eslint/parser': 6.4.1(eslint@8.47.0)(typescript@5.1.6)
+      debug: 3.2.7
+      eslint: 8.47.0
+      eslint-import-resolver-node: 0.3.9
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /eslint-plugin-es-x@7.2.0(eslint@8.47.0):
+    resolution: {integrity: sha512-9dvv5CcvNjSJPqnS5uZkqb3xmbeqRLnvXKK7iI5+oK/yTusyc46zbBZKENGsOfojm/mKfszyZb+wNqNPAPeGXA==}
+    engines: {node: ^14.18.0 || >=16.0.0}
+    peerDependencies:
+      eslint: '>=8'
+    dependencies:
+      '@eslint-community/eslint-utils': 4.4.0(eslint@8.47.0)
+      '@eslint-community/regexpp': 4.7.0
+      eslint: 8.47.0
+    dev: true
+
+  /eslint-plugin-eslint-comments@3.2.0(eslint@8.47.0):
+    resolution: {integrity: sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==}
+    engines: {node: '>=6.5.0'}
+    peerDependencies:
+      eslint: '>=4.19.1'
+    dependencies:
+      escape-string-regexp: 1.0.5
+      eslint: 8.47.0
+      ignore: 5.2.4
+    dev: true
+
+  /eslint-plugin-html@7.1.0:
+    resolution: {integrity: sha512-fNLRraV/e6j8e3XYOC9xgND4j+U7b1Rq+OygMlLcMg+wI/IpVbF+ubQa3R78EjKB9njT6TQOlcK5rFKBVVtdfg==}
+    dependencies:
+      htmlparser2: 8.0.2
+    dev: true
+
+  /eslint-plugin-import@2.28.1(@typescript-eslint/parser@6.4.1)(eslint@8.47.0):
+    resolution: {integrity: sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==}
+    engines: {node: '>=4'}
+    peerDependencies:
+      '@typescript-eslint/parser': '*'
+      eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8
+    peerDependenciesMeta:
+      '@typescript-eslint/parser':
+        optional: true
+    dependencies:
+      '@typescript-eslint/parser': 6.4.1(eslint@8.47.0)(typescript@5.1.6)
+      array-includes: 3.1.6
+      array.prototype.findlastindex: 1.2.3
+      array.prototype.flat: 1.3.1
+      array.prototype.flatmap: 1.3.1
+      debug: 3.2.7
+      doctrine: 2.1.0
+      eslint: 8.47.0
+      eslint-import-resolver-node: 0.3.9
+      eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.4.1)(eslint-import-resolver-node@0.3.9)(eslint@8.47.0)
+      has: 1.0.3
+      is-core-module: 2.13.0
+      is-glob: 4.0.3
+      minimatch: 3.1.2
+      object.fromentries: 2.0.7
+      object.groupby: 1.0.1
+      object.values: 1.1.7
+      semver: 6.3.1
+      tsconfig-paths: 3.14.2
+    transitivePeerDependencies:
+      - eslint-import-resolver-typescript
+      - eslint-import-resolver-webpack
+      - supports-color
+    dev: true
+
+  /eslint-plugin-jsonc@2.9.0(eslint@8.47.0):
+    resolution: {integrity: sha512-RK+LeONVukbLwT2+t7/OY54NJRccTXh/QbnXzPuTLpFMVZhPuq1C9E07+qWenGx7rrQl0kAalAWl7EmB+RjpGA==}
+    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+    peerDependencies:
+      eslint: '>=6.0.0'
+    dependencies:
+      '@eslint-community/eslint-utils': 4.4.0(eslint@8.47.0)
+      eslint: 8.47.0
+      jsonc-eslint-parser: 2.3.0
+      natural-compare: 1.4.0
+    dev: true
+
+  /eslint-plugin-markdown@3.0.1(eslint@8.47.0):
+    resolution: {integrity: sha512-8rqoc148DWdGdmYF6WSQFT3uQ6PO7zXYgeBpHAOAakX/zpq+NvFYbDA/H7PYzHajwtmaOzAwfxyl++x0g1/N9A==}
+    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+    peerDependencies:
+      eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
+    dependencies:
+      eslint: 8.47.0
+      mdast-util-from-markdown: 0.8.5
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /eslint-plugin-n@16.0.2(eslint@8.47.0):
+    resolution: {integrity: sha512-Y66uDfUNbBzypsr0kELWrIz+5skicECrLUqlWuXawNSLUq3ltGlCwu6phboYYOTSnoTdHgTLrc+5Ydo6KjzZog==}
+    engines: {node: '>=16.0.0'}
+    peerDependencies:
+      eslint: '>=7.0.0'
+    dependencies:
+      '@eslint-community/eslint-utils': 4.4.0(eslint@8.47.0)
+      builtins: 5.0.1
+      eslint: 8.47.0
+      eslint-plugin-es-x: 7.2.0(eslint@8.47.0)
+      ignore: 5.2.4
+      is-core-module: 2.13.0
+      minimatch: 3.1.2
+      resolve: 1.22.4
+      semver: 7.5.4
+    dev: true
+
+  /eslint-plugin-no-only-tests@3.1.0:
+    resolution: {integrity: sha512-Lf4YW/bL6Un1R6A76pRZyE1dl1vr31G/ev8UzIc/geCgFWyrKil8hVjYqWVKGB/UIGmb6Slzs9T0wNezdSVegw==}
+    engines: {node: '>=5.0.0'}
+    dev: true
+
+  /eslint-plugin-promise@6.1.1(eslint@8.47.0):
+    resolution: {integrity: sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==}
+    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+    peerDependencies:
+      eslint: ^7.0.0 || ^8.0.0
+    dependencies:
+      eslint: 8.47.0
+    dev: true
+
+  /eslint-plugin-unicorn@48.0.1(eslint@8.47.0):
+    resolution: {integrity: sha512-FW+4r20myG/DqFcCSzoumaddKBicIPeFnTrifon2mWIzlfyvzwyqZjqVP7m4Cqr/ZYisS2aiLghkUWaPg6vtCw==}
+    engines: {node: '>=16'}
+    peerDependencies:
+      eslint: '>=8.44.0'
+    dependencies:
+      '@babel/helper-validator-identifier': 7.22.5
+      '@eslint-community/eslint-utils': 4.4.0(eslint@8.47.0)
+      ci-info: 3.8.0
+      clean-regexp: 1.0.0
+      eslint: 8.47.0
+      esquery: 1.5.0
+      indent-string: 4.0.0
+      is-builtin-module: 3.2.1
+      jsesc: 3.0.2
+      lodash: 4.17.21
+      pluralize: 8.0.0
+      read-pkg-up: 7.0.1
+      regexp-tree: 0.1.27
+      regjsparser: 0.10.0
+      semver: 7.5.4
+      strip-indent: 3.0.0
+    dev: true
+
+  /eslint-plugin-unused-imports@3.0.0(@typescript-eslint/eslint-plugin@6.4.1)(eslint@8.47.0):
+    resolution: {integrity: sha512-sduiswLJfZHeeBJ+MQaG+xYzSWdRXoSw61DpU13mzWumCkR0ufD0HmO4kdNokjrkluMHpj/7PJeN35pgbhW3kw==}
+    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+    peerDependencies:
+      '@typescript-eslint/eslint-plugin': ^6.0.0
+      eslint: ^8.0.0
+    peerDependenciesMeta:
+      '@typescript-eslint/eslint-plugin':
+        optional: true
+    dependencies:
+      '@typescript-eslint/eslint-plugin': 6.4.1(@typescript-eslint/parser@6.4.1)(eslint@8.47.0)(typescript@5.1.6)
+      eslint: 8.47.0
+      eslint-rule-composer: 0.3.0
+    dev: true
+
   /eslint-plugin-vue@9.17.0(eslint@8.47.0):
     resolution: {integrity: sha512-r7Bp79pxQk9I5XDP0k2dpUC7Ots3OSWgvGZNu3BxmKK6Zg7NgVtcOB6OCna5Kb9oQwJPl5hq183WD0SY5tZtIQ==}
     engines: {node: ^14.17.0 || >=16.0.0}
@@ -3508,6 +3881,26 @@ packages:
       - supports-color
     dev: true
 
+  /eslint-plugin-yml@1.8.0(eslint@8.47.0):
+    resolution: {integrity: sha512-fgBiJvXD0P2IN7SARDJ2J7mx8t0bLdG6Zcig4ufOqW5hOvSiFxeUyc2g5I1uIm8AExbo26NNYCcTGZT0MXTsyg==}
+    engines: {node: ^14.17.0 || >=16.0.0}
+    peerDependencies:
+      eslint: '>=6.0.0'
+    dependencies:
+      debug: 4.3.4
+      eslint: 8.47.0
+      lodash: 4.17.21
+      natural-compare: 1.4.0
+      yaml-eslint-parser: 1.2.2
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /eslint-rule-composer@0.3.0:
+    resolution: {integrity: sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==}
+    engines: {node: '>=4.0.0'}
+    dev: true
+
   /eslint-scope@7.2.2:
     resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==}
     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -4216,6 +4609,15 @@ packages:
     resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
     dev: true
 
+  /htmlparser2@8.0.2:
+    resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==}
+    dependencies:
+      domelementtype: 2.3.0
+      domhandler: 5.0.3
+      domutils: 3.1.0
+      entities: 4.5.0
+    dev: true
+
   /http-cache-semantics@4.1.1:
     resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==}
     dev: true
@@ -4388,6 +4790,17 @@ packages:
     resolution: {integrity: sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==}
     dev: true
 
+  /is-alphabetical@1.0.4:
+    resolution: {integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==}
+    dev: true
+
+  /is-alphanumerical@1.0.4:
+    resolution: {integrity: sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==}
+    dependencies:
+      is-alphabetical: 1.0.4
+      is-decimal: 1.0.4
+    dev: true
+
   /is-arguments@1.1.1:
     resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==}
     engines: {node: '>= 0.4'}
@@ -4429,6 +4842,13 @@ packages:
       has-tostringtag: 1.0.0
     dev: true
 
+  /is-builtin-module@3.2.1:
+    resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==}
+    engines: {node: '>=6'}
+    dependencies:
+      builtin-modules: 3.3.0
+    dev: true
+
   /is-callable@1.2.7:
     resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
     engines: {node: '>= 0.4'}
@@ -4454,6 +4874,10 @@ packages:
       has-tostringtag: 1.0.0
     dev: true
 
+  /is-decimal@1.0.4:
+    resolution: {integrity: sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==}
+    dev: true
+
   /is-docker@2.2.1:
     resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==}
     engines: {node: '>=8'}
@@ -4483,6 +4907,10 @@ packages:
       is-extglob: 2.1.1
     dev: true
 
+  /is-hexadecimal@1.0.4:
+    resolution: {integrity: sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==}
+    dev: true
+
   /is-inside-container@1.0.0:
     resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==}
     engines: {node: '>=14.16'}
@@ -4783,12 +5211,23 @@ packages:
       - utf-8-validate
     dev: true
 
+  /jsesc@0.5.0:
+    resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==}
+    hasBin: true
+    dev: true
+
   /jsesc@2.5.2:
     resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==}
     engines: {node: '>=4'}
     hasBin: true
     dev: true
 
+  /jsesc@3.0.2:
+    resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==}
+    engines: {node: '>=6'}
+    hasBin: true
+    dev: true
+
   /json-buffer@3.0.1:
     resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
     dev: true
@@ -4813,6 +5252,23 @@ packages:
     resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==}
     dev: true
 
+  /json5@1.0.2:
+    resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==}
+    hasBin: true
+    dependencies:
+      minimist: 1.2.8
+    dev: true
+
+  /jsonc-eslint-parser@2.3.0:
+    resolution: {integrity: sha512-9xZPKVYp9DxnM3sd1yAsh/d59iIaswDkai8oTxbursfKYbg/ibjX0IzFt35+VZ8iEW453TVTXztnRvYUQlAfUQ==}
+    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+    dependencies:
+      acorn: 8.10.0
+      eslint-visitor-keys: 3.4.3
+      espree: 9.6.1
+      semver: 7.5.4
+    dev: true
+
   /jsonc-parser@3.2.0:
     resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==}
     dev: true
@@ -5024,6 +5480,22 @@ packages:
     resolution: {integrity: sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==}
     dev: true
 
+  /mdast-util-from-markdown@0.8.5:
+    resolution: {integrity: sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==}
+    dependencies:
+      '@types/mdast': 3.0.12
+      mdast-util-to-string: 2.0.0
+      micromark: 2.11.4
+      parse-entities: 2.0.0
+      unist-util-stringify-position: 2.0.3
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /mdast-util-to-string@2.0.0:
+    resolution: {integrity: sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==}
+    dev: true
+
   /mdn-data@2.0.28:
     resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==}
     dev: true
@@ -5062,6 +5534,15 @@ packages:
     resolution: {integrity: sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw==}
     dev: true
 
+  /micromark@2.11.4:
+    resolution: {integrity: sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA==}
+    dependencies:
+      debug: 4.3.4
+      parse-entities: 2.0.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
   /micromatch@4.0.5:
     resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
     engines: {node: '>=8.6'}
@@ -5325,6 +5806,33 @@ packages:
       object-keys: 1.1.1
     dev: true
 
+  /object.fromentries@2.0.7:
+    resolution: {integrity: sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      call-bind: 1.0.2
+      define-properties: 1.2.0
+      es-abstract: 1.22.1
+    dev: true
+
+  /object.groupby@1.0.1:
+    resolution: {integrity: sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==}
+    dependencies:
+      call-bind: 1.0.2
+      define-properties: 1.2.0
+      es-abstract: 1.22.1
+      get-intrinsic: 1.2.1
+    dev: true
+
+  /object.values@1.1.7:
+    resolution: {integrity: sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      call-bind: 1.0.2
+      define-properties: 1.2.0
+      es-abstract: 1.22.1
+    dev: true
+
   /ofetch@1.2.1:
     resolution: {integrity: sha512-WEX1TEfGuAFJhzRW6Qv9RcxCyek+YogEeXlCWl1XoqBSW2fc6jU4LTk3VotwC1YfXv8Uz06LSofU6uW/ZIT+6g==}
     dependencies:
@@ -5550,6 +6058,17 @@ packages:
       callsites: 3.1.0
     dev: true
 
+  /parse-entities@2.0.0:
+    resolution: {integrity: sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==}
+    dependencies:
+      character-entities: 1.2.4
+      character-entities-legacy: 1.1.4
+      character-reference-invalid: 1.1.4
+      is-alphanumerical: 1.0.4
+      is-decimal: 1.0.4
+      is-hexadecimal: 1.0.4
+    dev: true
+
   /parse-json@4.0.0:
     resolution: {integrity: sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==}
     engines: {node: '>=4'}
@@ -5670,6 +6189,11 @@ packages:
     engines: {node: '>=10'}
     dev: true
 
+  /pluralize@8.0.0:
+    resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==}
+    engines: {node: '>=4'}
+    dev: true
+
   /postcss-selector-parser@6.0.13:
     resolution: {integrity: sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==}
     engines: {node: '>=4'}
@@ -5887,6 +6411,11 @@ packages:
   /regexp-to-ast@0.5.0:
     resolution: {integrity: sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==}
 
+  /regexp-tree@0.1.27:
+    resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==}
+    hasBin: true
+    dev: true
+
   /regexp.prototype.flags@1.5.0:
     resolution: {integrity: sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==}
     engines: {node: '>= 0.4'}
@@ -5910,6 +6439,13 @@ packages:
       rc: 1.2.8
     dev: true
 
+  /regjsparser@0.10.0:
+    resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==}
+    hasBin: true
+    dependencies:
+      jsesc: 0.5.0
+    dev: true
+
   /release-it@16.1.5:
     resolution: {integrity: sha512-w/zCljPZBSYcCwR9fjDB1zaYwie1CAQganUrwNqjtXacXhrrsS5E6dDUNLcxm2ypu8GWAgZNMJfuBJqIO2E7fA==}
     engines: {node: '>=16'}
@@ -6151,6 +6687,11 @@ packages:
     hasBin: true
     dev: true
 
+  /semver@6.3.1:
+    resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
+    hasBin: true
+    dev: true
+
   /semver@7.5.1:
     resolution: {integrity: sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==}
     engines: {node: '>=10'}
@@ -6637,6 +7178,15 @@ packages:
       typescript: 5.1.6
     dev: true
 
+  /tsconfig-paths@3.14.2:
+    resolution: {integrity: sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==}
+    dependencies:
+      '@types/json5': 0.0.29
+      json5: 1.0.2
+      minimist: 1.2.8
+      strip-bom: 3.0.0
+    dev: true
+
   /tslib@2.6.2:
     resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
     dev: true
@@ -6828,6 +7378,12 @@ packages:
       crypto-random-string: 4.0.0
     dev: true
 
+  /unist-util-stringify-position@2.0.3:
+    resolution: {integrity: sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==}
+    dependencies:
+      '@types/unist': 2.0.8
+    dev: true
+
   /universal-user-agent@6.0.0:
     resolution: {integrity: sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==}
     dev: true
@@ -7550,6 +8106,20 @@ packages:
     resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
     dev: true
 
+  /yaml-eslint-parser@1.2.2:
+    resolution: {integrity: sha512-pEwzfsKbTrB8G3xc/sN7aw1v6A6c/pKxLAkjclnAyo5g5qOh6eL9WGu0o3cSDQZKrTNk4KL4lQSwZW+nBkANEg==}
+    engines: {node: ^14.17.0 || >=16.0.0}
+    dependencies:
+      eslint-visitor-keys: 3.4.3
+      lodash: 4.17.21
+      yaml: 2.3.2
+    dev: true
+
+  /yaml@2.3.2:
+    resolution: {integrity: sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==}
+    engines: {node: '>= 14'}
+    dev: true
+
   /yargs-parser@20.2.9:
     resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==}
     engines: {node: '>=10'}

+ 34 - 31
src/components/TresCanvas.vue

@@ -2,17 +2,19 @@
 import {
   PerspectiveCamera,
   Scene,
+} from 'three'
+import type {
   WebGLRendererParameters,
-  type ColorSpace,
-  type ShadowMapType,
-  type ToneMapping,
+  ColorSpace,
+  ShadowMapType,
+  ToneMapping,
 } from 'three'
-import { Ref, computed, onMounted, provide, ref, shallowRef, watch, watchEffect } from 'vue'
-import { Fragment, defineComponent, h } from 'vue'
+import type { Ref } from 'vue'
+import { computed, onMounted, provide, ref, shallowRef, watch, watchEffect, Fragment, defineComponent, h } from 'vue'
 import {
   useTresContextProvider, useLogger,
   usePointerEventHandler,
-  useRenderLoop, type TresContext
+  useRenderLoop, type TresContext,
 } from '../composables'
 import { extend } from '../core/catalogue'
 import { render } from '../core/renderer'
@@ -24,7 +26,6 @@ import {
 import type { RendererPresetsType } from '../composables/useRenderer/const'
 import type { TresCamera, TresObject } from '../types/'
 
-
 export interface TresCanvasProps extends Omit<WebGLRendererParameters, 'canvas'> {
   // required by for useRenderer
   shadows?: boolean
@@ -39,7 +40,7 @@ export interface TresCanvasProps extends Omit<WebGLRendererParameters, 'canvas'>
   windowSize?: boolean
   preset?: RendererPresetsType
   disableRender?: boolean
-  camera?: TresCamera,
+  camera?: TresCamera
 }
 
 const props = withDefaults(defineProps<TresCanvasProps>(), {
@@ -67,15 +68,13 @@ const slots = defineSlots<{
   default(): any
 }>()
 
-const createInternalComponent = (context: TresContext) => {
-  return defineComponent({
-    setup() {
-      provide('useTres', context)
-      provide('extend', extend)
-      return () => h(Fragment, null, slots?.default ? slots.default() : [])
-    }
-  })
-}
+const createInternalComponent = (context: TresContext) => defineComponent({
+  setup() {
+    provide('useTres', context)
+    provide('extend', extend)
+    return () => h(Fragment, null, slots?.default ? slots.default() : [])
+  },
+})
 
 const mountCustomRenderer = (context: TresContext) => {
   const InternalComponent = createInternalComponent(context)
@@ -132,13 +131,13 @@ onMounted(() => {
       removeCamera(oldCamera)
     }
   }, {
-    immediate: true
+    immediate: true,
   })
 
   if (!camera.value) {
     logWarning(
-      'No camera found. Creating a default perspective camera. ' +
-      'To have full control over a camera, please add one to the scene.'
+      'No camera found. Creating a default perspective camera. '
+      + 'To have full control over a camera, please add one to the scene.',
     )
     addDefaultCamera()
   }
@@ -147,16 +146,20 @@ onMounted(() => {
     import.meta.hot.on('vite:afterUpdate', () => dispose(context))
 })
 </script>
+
 <template>
-  <canvas ref="canvas" :data-scene="scene.uuid" :style="{
-    display: 'block',
-    width: '100%',
-    height: '100%',
-    position: windowSize ? 'fixed' : 'relative',
-    top: 0,
-    left: 0,
-    pointerEvents: 'auto',
-    touchAction: 'none',
-  }">
-  </canvas>
+  <canvas
+    ref="canvas"
+    :data-scene="scene.uuid"
+    :style="{
+      display: 'block',
+      width: '100%',
+      height: '100%',
+      position: windowSize ? 'fixed' : 'relative',
+      top: 0,
+      left: 0,
+      pointerEvents: 'auto',
+      touchAction: 'none',
+    }"
+  />
 </template>

+ 5 - 6
src/composables/useCamera/index.ts

@@ -4,13 +4,12 @@ import { Camera, OrthographicCamera, PerspectiveCamera } from 'three'
 import type { TresScene } from '../../types'
 import type { TresContext } from '../useTresContextProvider'
 
-
 export const useCamera = ({ sizes, scene }: Pick<TresContext, 'sizes'> & { scene: TresScene }) => {
 
   // the computed does not trigger, when for example the camera postion changes
   const cameras = ref<Camera[]>([])
   const camera = computed<Camera | undefined>(
-    () => cameras.value[0]
+    () => cameras.value[0],
   )
 
   const addCamera = (newCamera: Camera, active = false) => {
@@ -29,9 +28,9 @@ export const useCamera = ({ sizes, scene }: Pick<TresContext, 'sizes'> & { scene
   }
 
   const setCameraActive = (cameraOrUuid: string | Camera) => {
-    const camera = cameraOrUuid instanceof Camera ?
-      cameraOrUuid :
-      cameras.value.find((camera: Camera) => camera.uuid === cameraOrUuid)
+    const camera = cameraOrUuid instanceof Camera
+      ? cameraOrUuid
+      : cameras.value.find((camera: Camera) => camera.uuid === cameraOrUuid)
 
     if (!camera) return
 
@@ -46,7 +45,7 @@ export const useCamera = ({ sizes, scene }: Pick<TresContext, 'sizes'> & { scene
           camera.aspect = sizes.aspectRatio.value
 
         if (camera instanceof PerspectiveCamera || camera instanceof OrthographicCamera)
-          camera.updateProjectionMatrix();
+          camera.updateProjectionMatrix()
       })
     }
   })

+ 2 - 2
src/composables/useLoader/index.ts

@@ -1,5 +1,5 @@
 import { isArray } from '@alvarosabu/utils'
-import { Object3D } from 'three'
+import type { Object3D } from 'three'
 import { useLogger } from '../useLogger'
 
 export interface TresLoader<T> extends THREE.Loader {
@@ -88,7 +88,7 @@ export async function useLoader<T extends LoaderProto<T>, U extends string | str
       new Promise((resolve, reject) => {
         proto.load(
           path,
-          data => {
+          (data) => {
             if (data.scene) {
               Object.assign(data, trasverseObjects(data.scene))
             }

+ 1 - 0
src/composables/useLogger.ts

@@ -23,6 +23,7 @@ export function useLogger(): LoggerComposition {
       console.log(`${logPrefix} - ${name}:`, value)
     }
   }
+  /*eslint-enable no-console */
 
   return {
     logError,

+ 8 - 9
src/composables/usePointerEventHandler/index.ts

@@ -1,15 +1,15 @@
+import { computed, reactive } from 'vue'
+import type { Intersection, Event, Object3D } from 'three'
+import type { TresScene } from 'src/types'
 import { uniqueBy } from '../../utils'
 import { useRaycaster } from '../useRaycaster'
-import { computed, reactive } from 'vue'
 
 import type { TresContext } from '../useTresContextProvider'
-import type { Intersection, Event, Object3D } from 'three'
-import { TresScene } from 'src/types'
 
 type CallbackFn = (intersection: Intersection<Object3D<Event>>, event: PointerEvent) => void
 type CallbackFnPointerLeave = (object: Object3D<Event>, event: PointerEvent) => void
 
-export type EventProps = {
+export interface EventProps {
   onClick?: CallbackFn
   onPointerEnter?: CallbackFn
   onPointerMove?: CallbackFn
@@ -18,10 +18,10 @@ export type EventProps = {
 
 export const usePointerEventHandler = (
   { scene, contextParts }:
-    {
-      scene: TresScene,
-      contextParts: Pick<TresContext, 'renderer' | 'camera' | 'raycaster'>
-    }
+  {
+    scene: TresScene
+    contextParts: Pick<TresContext, 'renderer' | 'camera' | 'raycaster'>
+  },
 ) => {
   const objectsWithEventListeners = reactive({
     click: new Map<Object3D, CallbackFn>(),
@@ -47,7 +47,6 @@ export const usePointerEventHandler = (
   scene.userData.tres__registerAtPointerEventHandler = registerObject
   scene.userData.tres__deregisterAtPointerEventHandler = deregisterObject
 
-
   const objectsToWatch = computed(() =>
     uniqueBy(
       Object.values(objectsWithEventListeners)

+ 7 - 6
src/composables/useRaycaster/index.ts

@@ -1,10 +1,12 @@
-import { type Intersection, Object3D, Vector2 } from 'three'
-import { Ref, computed, onUnmounted } from 'vue'
-import { EventHook, createEventHook, useElementBounding, usePointer } from '@vueuse/core'
+import { Vector2 } from 'three'
+import type { Object3D, type Intersection } from 'three'
+import type { Ref } from 'vue'
+import { computed, onUnmounted } from 'vue'
+import type { EventHook } from '@vueuse/core'
+import { createEventHook, useElementBounding, usePointer } from '@vueuse/core'
 
 import { type TresContext } from '../useTresContextProvider'
 
-
 export type Intersects = Intersection<THREE.Object3D<THREE.Event>>[]
 interface PointerMoveEventPayload {
   intersects?: Intersects
@@ -18,7 +20,7 @@ interface PointerClickEventPayload {
 
 export const useRaycaster = (
   objects: Ref<THREE.Object3D[]>,
-  { renderer, camera, raycaster }: Pick<TresContext, 'renderer' | 'camera' | 'raycaster'>
+  { renderer, camera, raycaster }: Pick<TresContext, 'renderer' | 'camera' | 'raycaster'>,
 ) => {
   // having a seperate computed makes useElementBounding work
   const canvas = computed(() => renderer.value.domElement as HTMLCanvasElement)
@@ -27,7 +29,6 @@ export const useRaycaster = (
 
   const { width, height, top, left } = useElementBounding(canvas)
 
-
   const getRelativePointerPosition = ({ x, y }: { x: number; y: number }) => {
     if (!canvas.value) return
 

+ 11 - 12
src/composables/useRenderLoop/index.ts

@@ -1,5 +1,6 @@
-import { createEventHook, EventHookOn, Fn, useRafFn } from '@vueuse/core'
-import { Ref } from 'vue'
+import type { EventHookOn, Fn } from '@vueuse/core'
+import { createEventHook, useRafFn } from '@vueuse/core'
+import type { Ref } from 'vue'
 import { Clock } from 'three'
 
 export interface RenderLoop {
@@ -39,13 +40,11 @@ onAfterLoop.on(() => {
   elapsed = clock.getElapsedTime()
 })
 
-export const useRenderLoop = (): UseRenderLoopReturn => {
-  return {
-    onBeforeLoop: onBeforeLoop.on,
-    onLoop: onLoop.on,
-    onAfterLoop: onAfterLoop.on,
-    pause,
-    resume,
-    isActive,
-  }
-}
+export const useRenderLoop = (): UseRenderLoopReturn => ({
+  onBeforeLoop: onBeforeLoop.on,
+  onLoop: onLoop.on,
+  onAfterLoop: onAfterLoop.on,
+  pause,
+  resume,
+  isActive,
+})

+ 26 - 28
src/composables/useRenderer/index.ts

@@ -1,5 +1,4 @@
 import { Color, WebGLRenderer } from 'three'
-import { rendererPresets, RendererPresetsType } from './const'
 import { shallowRef, watchEffect, onUnmounted, type MaybeRef, computed, watch } from 'vue'
 import {
   toValue,
@@ -8,26 +7,28 @@ import {
   useDevicePixelRatio,
 } from '@vueuse/core'
 
-import { get, merge, set } from '../../utils'
+import type { Scene, ToneMapping,
+  ColorSpace,
+  ShadowMapType,
+  WebGLRendererParameters,
+} from 'three'
 import { useLogger } from '../useLogger'
-import { TresColor } from '../../types'
+import type { TresColor } from '../../types'
 import { useRenderLoop } from '../useRenderLoop'
 import { normalizeColor } from '../../utils/normalize'
 
-import type { Scene, ToneMapping } from 'three'
 import type { TresContext } from '../useTresContextProvider'
-import type {
-  ColorSpace,
-  ShadowMapType,
-  WebGLRendererParameters,
-} from 'three'
+import { get, merge, set } from '../../utils'
+
 // eslint-disable-next-line max-len
 // Solution taken from Thretle that actually support different versions https://github.com/threlte/threlte/blob/5fa541179460f0dadc7dc17ae5e6854d1689379e/packages/core/src/lib/lib/useRenderer.ts
 import { revision } from '../../core/revision'
+import { rendererPresets } from './const'
+import type { RendererPresetsType } from './const'
 
 type TransformToMaybeRefOrGetter<T> = {
   [K in keyof T]: MaybeRefOrGetter<T[K]> | MaybeRefOrGetter<T[K]>;
-};
+}
 
 export interface UseRendererOptions extends TransformToMaybeRefOrGetter<WebGLRendererParameters> {
   /**
@@ -111,13 +112,13 @@ export function useRenderer(
     disableRender,
     contextParts: { sizes, camera },
   }:
-    {
-      canvas: MaybeRef<HTMLCanvasElement>
-      scene: Scene
-      options: UseRendererOptions
-      contextParts: Pick<TresContext, 'sizes' | 'camera'>
-      disableRender: MaybeRefOrGetter<boolean>
-    }
+  {
+    canvas: MaybeRef<HTMLCanvasElement>
+    scene: Scene
+    options: UseRendererOptions
+    contextParts: Pick<TresContext, 'sizes' | 'camera'>
+    disableRender: MaybeRefOrGetter<boolean>
+  },
 ) {
 
   const webGLRendererConstructorParameters = computed<WebGLRendererParameters>(() => ({
@@ -126,15 +127,15 @@ export function useRenderer(
     canvas: unrefElement(canvas),
     context: toValue(options.context),
     stencil: toValue(options.stencil),
-    antialias: toValue(options.antialias) === undefined ? // an opinionated default of tres
-      true :
-      toValue(options.antialias),
+    antialias: toValue(options.antialias) === undefined // an opinionated default of tres
+      ? true
+      : toValue(options.antialias),
     precision: toValue(options.precision),
     powerPreference: toValue(options.powerPreference),
     premultipliedAlpha: toValue(options.premultipliedAlpha),
     preserveDrawingBuffer: toValue(options.preserveDrawingBuffer),
     logarithmicDepthBuffer: toValue(options.logarithmicDepthBuffer),
-    failIfMajorPerformanceCaveat: toValue(options.failIfMajorPerformanceCaveat)
+    failIfMajorPerformanceCaveat: toValue(options.failIfMajorPerformanceCaveat),
   }))
 
   const renderer = shallowRef<WebGLRenderer>(new WebGLRenderer(webGLRendererConstructorParameters.value))
@@ -150,7 +151,6 @@ export function useRenderer(
     renderer.value.setSize(sizes.width.value, sizes.height.value)
   })
 
-
   const { pixelRatio } = useDevicePixelRatio()
 
   watchEffect(() => {
@@ -184,7 +184,7 @@ export function useRenderer(
 
     if (rendererPreset) {
       if (!(rendererPreset in rendererPresets))
-        logError('Renderer Preset must be one of these: ' + Object.keys(rendererPresets).join(', '))
+        logError(`Renderer Preset must be one of these: ${Object.keys(rendererPresets).join(', ')}`)
 
       merge(renderer.value, rendererPresets[rendererPreset])
     }
@@ -199,7 +199,6 @@ export function useRenderer(
         return get(rendererPresets[rendererPreset], pathInThree)
       }
 
-
       if (value !== undefined)
         return value
 
@@ -228,9 +227,9 @@ export function useRenderer(
 
     if (clearColor)
       renderer.value.setClearColor(
-        clearColor ?
-          normalizeColor(clearColor) :
-          new Color(0x000000) // default clear color is not easily/efficiently retrievable from three
+        clearColor
+          ? normalizeColor(clearColor)
+          : new Color(0x000000), // default clear color is not easily/efficiently retrievable from three
       )
 
   })
@@ -253,7 +252,6 @@ export function useRenderer(
   if (import.meta.hot)
     import.meta.hot.on('vite:afterUpdate', resume)
 
-
   return {
     renderer,
   }

+ 1 - 1
src/composables/useSeek/index.ts

@@ -31,7 +31,7 @@ export function useSeek(): UseSeekReturn {
   function seek(parent: THREE.Scene | THREE.Object3D, property: string, value: string): THREE.Object3D | null {
     let foundChild: THREE.Object3D | null = null
 
-    parent.traverse(child => {
+    parent.traverse((child) => {
       if ((child as any)[property] === value) {
         foundChild = child
       }

+ 18 - 17
src/composables/useTexture/index.ts

@@ -1,5 +1,6 @@
 import { isArray } from '@alvarosabu/utils'
-import { LoadingManager, Texture, TextureLoader } from 'three'
+import type { Texture } from 'three'
+import { LoadingManager, TextureLoader } from 'three'
 
 export interface PBRMaterialOptions {
   /**
@@ -58,29 +59,29 @@ export async function useTexture(
    * @param {string} url
    * @return {*}  {Promise<Texture>}
    */
-  const loadTexture = (url: string): Promise<Texture> => {
-    return new Promise((resolve, reject) => {
-      textureLoader.load(
-        url,
-        texture => resolve(texture),
-        () => null,
-        () => {
-          reject(new Error('[useTextures] - Failed to load texture'))
-        },
-      )
-    })
-  }
+  const loadTexture = (url: string): Promise<Texture> => new Promise((resolve, reject) => {
+    textureLoader.load(
+      url,
+      texture => resolve(texture),
+      () => null,
+      () => {
+        reject(new Error('[useTextures] - Failed to load texture'))
+      },
+    )
+  })
 
   if (isArray(paths)) {
     const textures = await Promise.all((paths as Array<string>).map(path => loadTexture(path)))
     if ((paths as Array<string>).length > 1) {
       return textures
-    } else {
+    }
+    else {
       return textures[0]
     }
-  } else {
-    const { map, displacementMap, normalMap, roughnessMap, metalnessMap, aoMap, alphaMap, matcap
-     } = paths as { [key: string]: string }
+  }
+  else {
+    const { map, displacementMap, normalMap, roughnessMap, metalnessMap, aoMap, alphaMap, matcap,
+    } = paths as { [key: string]: string }
     return {
       map: map ? await loadTexture(map) : null,
       displacementMap: displacementMap ? await loadTexture(displacementMap) : null,

+ 29 - 29
src/composables/useTresContextProvider/index.ts

@@ -1,25 +1,26 @@
-import { toValue, useElementSize, useWindowSize } from '@vueuse/core';
-import { inject, provide, readonly, shallowRef, computed, ref } from 'vue';
-import { useCamera } from '../useCamera';
-import { Camera, EventDispatcher, Raycaster, Scene, WebGLRenderer } from 'three';
-import { UseRendererOptions, useRenderer } from '../useRenderer';
-import { extend } from '../../core/catalogue';
-
-import type { ComputedRef, DeepReadonly, MaybeRef, MaybeRefOrGetter, Ref, ShallowRef } from 'vue';
-
-export type TresContext = {
-  scene: ShallowRef<Scene>;
-  camera: ComputedRef<Camera | undefined>;
-  cameras: DeepReadonly<Ref<Camera[]>>;
+import { toValue, useElementSize, useWindowSize } from '@vueuse/core'
+import { inject, provide, readonly, shallowRef, computed, ref } from 'vue'
+import type { Camera, EventDispatcher, Scene, WebGLRenderer } from 'three'
+import { Raycaster } from 'three'
+import type { ComputedRef, DeepReadonly, MaybeRef, MaybeRefOrGetter, Ref, ShallowRef } from 'vue'
+import { useCamera } from '../useCamera'
+import type { UseRendererOptions } from '../useRenderer'
+import { useRenderer } from '../useRenderer'
+import { extend } from '../../core/catalogue'
+
+export interface TresContext {
+  scene: ShallowRef<Scene>
+  camera: ComputedRef<Camera | undefined>
+  cameras: DeepReadonly<Ref<Camera[]>>
   renderer: ShallowRef<WebGLRenderer>
   raycaster: ShallowRef<Raycaster>
   controls: Ref<(EventDispatcher & { enabled: boolean }) | null>
   extend: (objects: any) => void
-  addCamera: (camera: Camera) => void;
+  addCamera: (camera: Camera) => void
   removeCamera: (camera: Camera) => void
-  setCameraActive: (cameraOrUuid: Camera | string) => void;
+  setCameraActive: (cameraOrUuid: Camera | string) => void
 
-  sizes: { height: Ref<number>, width: Ref<number>, aspectRatio: ComputedRef<number> }
+  sizes: { height: Ref<number>; width: Ref<number>; aspectRatio: ComputedRef<number> }
 }
 
 export function useTresContextProvider({
@@ -27,9 +28,9 @@ export function useTresContextProvider({
   canvas,
   windowSize,
   disableRender,
-  rendererOptions
+  rendererOptions,
 }: {
-  scene: Scene,
+  scene: Scene
   canvas: MaybeRef<HTMLCanvasElement>
   windowSize: MaybeRefOrGetter<boolean>
   disableRender: MaybeRefOrGetter<boolean>
@@ -39,28 +40,27 @@ export function useTresContextProvider({
   const elementSize = computed(() =>
     toValue(windowSize)
       ? useWindowSize()
-      : useElementSize(toValue(canvas).parentElement)
+      : useElementSize(toValue(canvas).parentElement),
   )
 
   const width = computed(() => elementSize.value.width.value)
   const height = computed(() => elementSize.value.height.value)
 
-
   const aspectRatio = computed(() => width.value / height.value)
 
   const sizes = {
     height,
     width,
-    aspectRatio
+    aspectRatio,
   }
-  const localScene = shallowRef<Scene>(scene);
+  const localScene = shallowRef<Scene>(scene)
   const {
     camera,
     cameras,
     addCamera,
     removeCamera,
     setCameraActive,
-  } = useCamera({ sizes, scene });
+  } = useCamera({ sizes, scene })
 
   const { renderer } = useRenderer(
     {
@@ -85,19 +85,19 @@ export function useTresContextProvider({
     setCameraActive,
   }
 
-  provide('useTres', toProvide);
+  provide('useTres', toProvide)
 
-  return toProvide;
+  return toProvide
 }
 
 export function useTresContext(): TresContext {
-  const context = inject<Partial<TresContext>>('useTres');
+  const context = inject<Partial<TresContext>>('useTres')
 
   if (!context) {
-    throw new Error('useTresContext must be used together with useTresContextProvider');
+    throw new Error('useTresContext must be used together with useTresContextProvider')
   }
 
-  return context as TresContext;
+  return context as TresContext
 }
 
-export const useTres = useTresContext;
+export const useTres = useTresContext

+ 4 - 3
src/core/catalogue.ts

@@ -1,8 +1,9 @@
-import { Ref, ref } from 'vue'
-import { TresCatalogue } from '../types'
+import type { Ref } from 'vue'
+import { ref } from 'vue'
+import type { TresCatalogue } from '../types'
 
 export const catalogue: Ref<TresCatalogue> = ref({})
 
-export const extend = (objects: any) => void Object.assign(catalogue.value, objects)
+export const extend = (objects: any) => Object.assign(catalogue.value, objects)
 
 export default { catalogue, extend }

+ 24 - 25
src/core/nodeOps.ts

@@ -1,12 +1,12 @@
-import { RendererOptions } from 'vue'
+import type { RendererOptions } from 'vue'
 import { BufferAttribute } from 'three'
 import { isFunction } from '@alvarosabu/utils'
+import type { Object3D, Camera } from 'three'
 import { useLogger } from '../composables'
-import { catalogue } from './catalogue'
 import { deepArrayEqual, isHTMLTag, kebabToCamel } from '../utils'
 
-import type { Object3D, Camera } from 'three'
 import type { TresObject, TresObject3D, TresScene } from '../types'
+import { catalogue } from './catalogue'
 
 const onRE = /^on[^a-z]/
 export const isOn = (key: string) => onRE.test(key)
@@ -33,11 +33,12 @@ export const nodeOps: RendererOptions<TresObject, TresObject> = {
     let instance
 
     if (tag === 'primitive') {
-      if (props?.object === undefined) logError(`Tres primitives need a prop 'object'`)
+      if (props?.object === undefined) logError('Tres primitives need a prop \'object\'')
       const object = props.object as TresObject
       name = object.type
       instance = Object.assign(object, { type: name, attach: props.attach, primitive: true })
-    } else {
+    }
+    else {
       const target = catalogue.value[name]
       if (!target) {
         logError(`${name} is not defined on the THREE namespace. Use extend to add it to the catalog.`)
@@ -71,7 +72,7 @@ export const nodeOps: RendererOptions<TresObject, TresObject> = {
     // we take the tag name and we save it on the userData for later use in the re-instancing process.
     instance.userData = {
       ...instance.userData,
-      tres__name: name
+      tres__name: name,
     }
 
     return instance
@@ -79,13 +80,14 @@ export const nodeOps: RendererOptions<TresObject, TresObject> = {
   insert(child, parent) {
     if (parent && parent.isScene) scene = parent as unknown as TresScene
     if (
-      (child?.__vnode?.type === 'TresGroup' || child?.__vnode?.type === 'TresObject3D') &&
-      parent === null &&
-      !child?.__vnode?.ctx?.asyncResolved
+      (child?.__vnode?.type === 'TresGroup' || child?.__vnode?.type === 'TresObject3D')
+      && parent === null
+      && !child?.__vnode?.ctx?.asyncResolved
     ) {
       fallback = child
       return
-    } else if (child?.__vnode?.type.includes('Controls') && parent === null) {
+    }
+    else if (child?.__vnode?.type.includes('Controls') && parent === null) {
       fallback = scene as unknown as TresObject
     }
 
@@ -99,12 +101,11 @@ export const nodeOps: RendererOptions<TresObject, TresObject> = {
         scene?.userData.tres__registerCamera?.(child as unknown as Camera)
       }
 
-
       if (
-        child?.onClick ||
-        child?.onPointerMove ||
-        child?.onPointerEnter ||
-        child?.onPointerLeave
+        child?.onClick
+        || child?.onPointerMove
+        || child?.onPointerEnter
+        || child?.onPointerLeave
       ) {
         if (!scene?.userData.tres__registerAtPointerEventHandler)
           throw 'could not find tres__registerAtPointerEventHandler on scene\'s userData'
@@ -113,13 +114,14 @@ export const nodeOps: RendererOptions<TresObject, TresObject> = {
       }
     }
 
-
     if (child?.isObject3D && parent?.isObject3D) {
       parent.add(child)
       child.dispatchEvent({ type: 'added' })
-    } else if (child?.isFog) {
+    }
+    else if (child?.isFog) {
       parent.fog = child
-    } else if (typeof child?.attach === 'string') {
+    }
+    else if (typeof child?.attach === 'string') {
       child.__previousAttach = child[parent?.attach as string]
       if (parent) {
         parent[child.attach] = child
@@ -143,28 +145,25 @@ export const nodeOps: RendererOptions<TresObject, TresObject> = {
 
       const deregisterAtPointerEventHandler = scene?.userData.tres__deregisterAtPointerEventHandler
 
-
       const deregisterAtPointerEventHandlerIfRequired = (object: TresObject) => {
         if (!deregisterAtPointerEventHandler)
           throw 'could not find tres__deregisterAtPointerEventHandler on scene\'s userData'
 
         if (
-          object?.onClick ||
-          object?.onPointerMove ||
-          object?.onPointerEnter ||
-          object?.onPointerLeave
+          object?.onClick
+          || object?.onPointerMove
+          || object?.onPointerEnter
+          || object?.onPointerLeave
         )
           deregisterAtPointerEventHandler?.(object as Object3D)
       }
 
-
       const deregisterCameraIfRequired = (object: Object3D) => {
         const deregisterCamera = scene?.userData.tres__deregisterCamera
 
         if (!deregisterCamera)
           throw 'could not find tres__deregisterCamera on scene\'s userData'
 
-
         if ((object as Camera).isCamera)
           deregisterCamera?.(object as Camera)
       }

+ 6 - 9
src/index.ts

@@ -1,13 +1,12 @@
-import { App } from 'vue'
+import type { App } from 'vue'
 import TresCanvas from './components/TresCanvas.vue'
+import { normalizeColor, normalizeVectorFlexibleParam } from './utils/normalize'
+import templateCompilerOptions from './utils/template-compiler-options'
+
 export * from './composables'
 export * from './core/catalogue'
 export * from './components'
 export * from './types'
-import { useTresContext, type TresContext } from './composables'
-
-import { normalizeColor, normalizeVectorFlexibleParam } from './utils/normalize'
-import templateCompilerOptions from './utils/template-compiler-options'
 
 export interface TresOptions {
   extends?: Record<string, unknown>
@@ -20,16 +19,14 @@ export interface TresPlugin {
 const plugin: TresPlugin = {
   install(app: App) {
     // Register core components
-    app.component(`TresCanvas`, TresCanvas)
+    app.component('TresCanvas', TresCanvas)
   },
 }
 
 export default plugin
 
 export {
-  TresContext,
-  useTresContext,
   normalizeColor,
   normalizeVectorFlexibleParam,
-  templateCompilerOptions
+  templateCompilerOptions,
 }

+ 14 - 12
src/types/index.ts

@@ -1,5 +1,5 @@
 /* eslint-disable @typescript-eslint/ban-types */
-import { DefineComponent, Ref, VNode } from 'vue'
+import type { DefineComponent, Ref, VNode } from 'vue'
 
 import type * as THREE from 'three'
 import type { EventProps as PointerEventHandlerEventProps } from '../composables/usePointerEventHandler'
@@ -53,15 +53,16 @@ export type TresObject = TresBaseObject & (TresObject3D | THREE.BufferGeometry |
 export interface TresScene extends THREE.Scene {
   userData: {
     // keys are prefixed with tres__ to avoid name collisions
-    tres__registerCamera?: (newCamera: THREE.Camera, active?: boolean) => void,
-    tres__deregisterCamera?: (camera: THREE.Camera) => void,
-    tres__registerAtPointerEventHandler?: (object: THREE.Object3D & PointerEventHandlerEventProps) => void,
-    tres__deregisterAtPointerEventHandler?: (object: THREE.Object3D) => void,
-    [key: string]: any;
-  };
+    tres__registerCamera?: (newCamera: THREE.Camera, active?: boolean) => void
+    tres__deregisterCamera?: (camera: THREE.Camera) => void
+    tres__registerAtPointerEventHandler?: (object: THREE.Object3D & PointerEventHandlerEventProps) => void
+    tres__deregisterAtPointerEventHandler?: (object: THREE.Object3D) => void
+    [key: string]: any
+  }
 }
 
 // Events
+// eslint-disable-next-line import/namespace
 export interface Intersection extends THREE.Intersection {
   /** The event source (the object which registered the handler) */
   eventObject: TresObject
@@ -137,9 +138,8 @@ export interface VectorCoordinates {
 
 export type MathType<T extends MathRepresentation | THREE.Euler> = T extends THREE.Color
   ? ConstructorParameters<typeof THREE.Color> | THREE.ColorRepresentation
-  : T extends VectorRepresentation | THREE.Layers | THREE.Euler
-  ? T | Parameters<T['set']> | number | VectorCoordinates
-  : T | Parameters<T['set']>
+  // eslint-disable-next-line max-len
+  : T extends VectorRepresentation | THREE.Layers | THREE.Euler ? T | Parameters<T['set']> | number | VectorCoordinates : T | Parameters<T['set']>
 
 export type TresVector2 = MathType<THREE.Vector2>
 export type TresVector3 = MathType<THREE.Vector3>
@@ -173,8 +173,8 @@ export type ThreeElement<T extends ConstructorRepresentation> = Mutable<
 type ThreeExports = typeof THREE
 type ThreeInstancesImpl = {
   [K in keyof ThreeExports as Uncapitalize<K>]: ThreeExports[K] extends ConstructorRepresentation
-  ? ThreeElement<ThreeExports[K]>
-  : never
+    ? ThreeElement<ThreeExports[K]>
+    : never
 }
 
 export interface ThreeInstances extends ThreeInstancesImpl {
@@ -188,3 +188,5 @@ type TresComponents = {
 declare module 'vue' {
   export interface GlobalComponents extends TresComponents { }
 }
+/* eslint-enable @typescript-eslint/ban-types */
+

+ 36 - 37
src/utils/index.ts

@@ -1,5 +1,5 @@
 export function toSetMethodName(key: string) {
-  return 'set' + key[0].toUpperCase() + key.slice(1)
+  return `set${key[0].toUpperCase()}${key.slice(1)}`
 }
 
 export const merge = (target: any, source: any) => {
@@ -13,21 +13,21 @@ export const merge = (target: any, source: any) => {
   return target
 }
 
-const HTML_TAGS =
-  'html,body,base,head,link,meta,style,title,address,article,aside,footer,' +
-  'header,hgroup,h1,h2,h3,h4,h5,h6,nav,section,div,dd,dl,dt,figcaption,' +
-  'figure,picture,hr,img,li,main,ol,p,pre,ul,a,b,abbr,bdi,bdo,br,cite,code,' +
-  'data,dfn,em,i,kbd,mark,q,rp,rt,ruby,s,samp,small,span,strong,sub,sup,' +
-  'time,u,var,wbr,area,audio,map,track,video,embed,object,param,source,' +
-  'canvas,script,noscript,del,ins,caption,col,colgroup,table,thead,tbody,td,' +
-  'th,tr,button,datalist,fieldset,form,input,label,legend,meter,optgroup,' +
-  'option,output,progress,select,textarea,details,dialog,menu,' +
-  'summary,template,blockquote,iframe,tfoot'
+const HTML_TAGS
+  = 'html,body,base,head,link,meta,style,title,address,article,aside,footer,'
+  + 'header,hgroup,h1,h2,h3,h4,h5,h6,nav,section,div,dd,dl,dt,figcaption,'
+  + 'figure,picture,hr,img,li,main,ol,p,pre,ul,a,b,abbr,bdi,bdo,br,cite,code,'
+  + 'data,dfn,em,i,kbd,mark,q,rp,rt,ruby,s,samp,small,span,strong,sub,sup,'
+  + 'time,u,var,wbr,area,audio,map,track,video,embed,object,param,source,'
+  + 'canvas,script,noscript,del,ins,caption,col,colgroup,table,thead,tbody,td,'
+  + 'th,tr,button,datalist,fieldset,form,input,label,legend,meter,optgroup,'
+  + 'option,output,progress,select,textarea,details,dialog,menu,'
+  + 'summary,template,blockquote,iframe,tfoot'
 
 export const isHTMLTag = /*#__PURE__*/ makeMap(HTML_TAGS)
 
 export function isDOMElement(obj: any): obj is HTMLElement {
-  return obj && obj.nodeType === 1;
+  return obj && obj.nodeType === 1
 }
 
 export function kebabToCamel(str: string) {
@@ -59,67 +59,66 @@ export const uniqueBy = <T, K>(array: T[], iteratee: (value: T) => K): T[] => {
 }
 
 export const get = <T>(obj: any, path: string | string[]): T | undefined => {
-  if (!path) return undefined;
+  if (!path) return undefined
 
   // Regex explained: https://regexr.com/58j0k
-  const pathArray = Array.isArray(path) ? path : path.match(/([^[.\]])+/g);
+  const pathArray = Array.isArray(path) ? path : path.match(/([^[.\]])+/g)
 
-  return pathArray?.reduce((prevObj, key) => prevObj && prevObj[key], obj);
-};
+  return pathArray?.reduce((prevObj, key) => prevObj && prevObj[key], obj)
+}
 
 export const set = (obj: any, path: string | string[], value: any): void => {
   // Regex explained: https://regexr.com/58j0k
-  const pathArray = Array.isArray(path) ? path : path.match(/([^[.\]])+/g);
+  const pathArray = Array.isArray(path) ? path : path.match(/([^[.\]])+/g)
 
   if (pathArray)
     pathArray.reduce((acc, key, i) => {
-      if (acc[key] === undefined) acc[key] = {};
-      if (i === pathArray.length - 1) acc[key] = value;
-      return acc[key];
-    }, obj);
-};
-
+      if (acc[key] === undefined) acc[key] = {}
+      if (i === pathArray.length - 1) acc[key] = value
+      return acc[key]
+    }, obj)
+}
 
 export function deepEqual(a: any, b: any): boolean {
   if (isDOMElement(a) && isDOMElement(b)) {
-    const attrsA = a.attributes;
-    const attrsB = b.attributes;
+    const attrsA = a.attributes
+    const attrsB = b.attributes
 
-    if (attrsA.length !== attrsB.length) return false;
+    if (attrsA.length !== attrsB.length) return false
 
-    return Array.from(attrsA).every(({ name, value }) => b.getAttribute(name) === value);
+    return Array.from(attrsA).every(({ name, value }) => b.getAttribute(name) === value)
   }
   // If both are primitives, return true if they are equal
-  if (a === b) return true;
+  if (a === b) return true
 
   // If either of them is null or not an object, return false
-  if (a === null || typeof a !== "object" || b === null || typeof b !== "object") return false;
+  if (a === null || typeof a !== 'object' || b === null || typeof b !== 'object') return false
 
   // Get the keys of both objects
-  const keysA = Object.keys(a), keysB = Object.keys(b);
+  const keysA = Object.keys(a), keysB = Object.keys(b)
 
   // If they have different number of keys, they are not equal
-  if (keysA.length !== keysB.length) return false;
+  if (keysA.length !== keysB.length) return false
 
   // Check each key in A to see if it exists in B and its value is the same in both
   for (const key of keysA) {
-    if (!keysB.includes(key) || !deepEqual(a[key], b[key])) return false;
+    if (!keysB.includes(key) || !deepEqual(a[key], b[key])) return false
   }
 
-  return true;
+  return true
 }
 
 export function deepArrayEqual(arr1: any[], arr2: any[]): boolean {
   // If they're not both arrays, return false
-  if (!Array.isArray(arr1) || !Array.isArray(arr2)) return false;
+  if (!Array.isArray(arr1) || !Array.isArray(arr2)) return false
 
   // If they don't have the same length, they're not equal
-  if (arr1.length !== arr2.length) return false;
+  if (arr1.length !== arr2.length) return false
 
   // Check each element of arr1 against the corresponding element of arr2
   for (let i = 0; i < arr1.length; i++) {
-    if (!deepEqual(arr1[i], arr2[i])) return false;
+    if (!deepEqual(arr1[i], arr2[i])) return false
   }
 
-  return true;
+  return true
 }

+ 5 - 4
src/utils/normalize.ts

@@ -1,11 +1,12 @@
-import { Vector3, Color, ColorRepresentation } from 'three'
+import type { ColorRepresentation } from 'three'
+import { Vector3, Color } from 'three'
 
 export type SizeFlexibleParams =
   | number[]
   | {
-      width: number
-      height: number
-    }
+    width: number
+    height: number
+  }
 
 export interface Vector2PropInterface {
   x?: number

+ 1 - 1
src/utils/template-compiler-options.ts

@@ -10,6 +10,6 @@ const templateCompilerOptions = {
       isCustomElement: (tag: string) => tag.startsWith('Tres') && !whitelist.includes(tag) || tag === 'primitive',
     },
   },
-};
+}
 
 export default templateCompilerOptions

+ 1 - 3
src/utils/test-utils.ts

@@ -6,9 +6,7 @@ export function withSetup(composable) {
     setup() {
       result = composable()
       // suppress missing template warning
-      return () => {
-        return null
-      }
+      return () => null
     },
   })
   app.mount(document.createElement('div'))