@tresjs/core 5.3.3 → 5.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * name: @tresjs/core
3
- * version: v5.3.3
3
+ * version: v5.4.0
4
4
  * (c) 2026
5
5
  * description: Declarative ThreeJS using Vue Components
6
6
  * author: Alvaro Saburido <hola@alvarosaburido.dev> (https://github.com/alvarosabu/)
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * name: @tresjs/core
3
- * version: v5.3.3
3
+ * version: v5.4.0
4
4
  * (c) 2026
5
5
  * description: Declarative ThreeJS using Vue Components
6
6
  * author: Alvaro Saburido <hola@alvarosaburido.dev> (https://github.com/alvarosabu/)
package/dist/tres.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * name: @tresjs/core
3
- * version: v5.3.3
3
+ * version: v5.4.0
4
4
  * (c) 2026
5
5
  * description: Declarative ThreeJS using Vue Components
6
6
  * author: Alvaro Saburido <hola@alvarosaburido.dev> (https://github.com/alvarosabu/)
7
7
  */
8
- import * as vue4 from "vue";
8
+ import * as vue6 from "vue";
9
9
  import { App, ComputedRef, DefineComponent, MaybeRef, MaybeRefOrGetter, Reactive, Ref, ShallowRef, VNode, VNodeRef } from "vue";
10
10
  import * as THREE from "three";
11
11
  import { BufferGeometry, Camera, Color, ColorRepresentation, ColorSpace, Event, Fog, Group, Layers, Light, Loader, LoadingManager, Material, Mesh, Object3D, Object3DEventMap, OrthographicCamera, PerspectiveCamera, Scene, ShadowMapType, ToneMapping, Vector3, WebGLRenderer } from "three";
@@ -321,11 +321,11 @@ declare function useRendererManager({
321
321
  onRender: _vueuse_core0.EventHookOn<TresRenderer>;
322
322
  onError: _vueuse_core0.EventHookOn<TresRendererError>;
323
323
  invalidate: (amountOfFramesToInvalidate?: number) => void;
324
- canBeInvalidated: vue4.ComputedRef<boolean>;
324
+ canBeInvalidated: vue6.ComputedRef<boolean>;
325
325
  mode: "always" | "on-demand" | "manual" | undefined;
326
326
  replaceRenderFunction: (fn: RenderFunction) => void;
327
- isInitialized: vue4.Ref<boolean, boolean>;
328
- error: vue4.Ref<TresRendererError | null, TresRendererError | null>;
327
+ isInitialized: vue6.Ref<boolean, boolean>;
328
+ error: vue6.Ref<TresRendererError | null, TresRendererError | null>;
329
329
  };
330
330
  type UseRendererManagerReturn = ReturnType<typeof useRendererManager>;
331
331
  //#endregion
@@ -437,6 +437,8 @@ type TresPrimitive = TresInstance & {
437
437
  interface TresScene extends THREE.Scene {
438
438
  __tres: {
439
439
  root: TresContext;
440
+ objects: TresObject[];
441
+ isUnmounting: boolean;
440
442
  };
441
443
  }
442
444
  interface MathRepresentation {
@@ -510,7 +512,7 @@ declare function buildGraph(object: Object3D | TresObject): TresObjectMap;
510
512
  //#endregion
511
513
  //#region src/composables/useLoader/component.vue.d.ts
512
514
  declare const __VLS_export$1: <T extends TresObjectMap>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
513
- props: vue4.PublicProps & __VLS_PrettifyLocal<{
515
+ props: vue6.PublicProps & __VLS_PrettifyLocal<{
514
516
  /**
515
517
  * The THREE.js loader to use
516
518
  */
@@ -524,8 +526,8 @@ declare const __VLS_export$1: <T extends TresObjectMap>(__VLS_props: NonNullable
524
526
  */
525
527
  manager?: LoadingManager;
526
528
  } & {
527
- onLoaded?: ((result: T) => any) | undefined;
528
529
  onError?: ((error: unknown) => any) | undefined;
530
+ onLoaded?: ((result: T) => any) | undefined;
529
531
  }> & (typeof globalThis extends {
530
532
  __VLS_PROPS_FALLBACK: infer P;
531
533
  } ? P : {});
@@ -533,20 +535,20 @@ declare const __VLS_export$1: <T extends TresObjectMap>(__VLS_props: NonNullable
533
535
  attrs: any;
534
536
  slots: {
535
537
  default?: (props: {
536
- state: vue4.UnwrapRef<T>;
538
+ state: vue6.UnwrapRef<T>;
537
539
  isLoading: boolean;
538
540
  error: unknown;
539
541
  }) => any;
540
542
  };
541
- emit: ((evt: "loaded", result: T) => void) & ((evt: "error", error: unknown) => void);
542
- }>) => vue4.VNode & {
543
+ emit: ((evt: "error", error: unknown) => void) & ((evt: "loaded", result: T) => void);
544
+ }>) => vue6.VNode & {
543
545
  __ctx?: Awaited<typeof __VLS_setup>;
544
546
  };
545
547
  declare const _default$1: typeof __VLS_export$1;
546
548
  type __VLS_PrettifyLocal<T> = (T extends any ? { [K in keyof T]: T[K] } : { [K in keyof T as K]: T[K] }) & {};
547
549
  //#endregion
548
550
  //#region src/composables/useGraph/index.d.ts
549
- declare const useGraph: (object: MaybeRef$1<TresObject | undefined>) => vue4.ComputedRef<TresObjectMap | undefined>;
551
+ declare const useGraph: (object: MaybeRef$1<TresObject | undefined>) => vue6.ComputedRef<TresObjectMap | undefined>;
550
552
  //#endregion
551
553
  //#region src/utils/createPriorityEventHook.d.ts
552
554
  type Callback<T> = Parameters<EventHookOff<T>>[0];
@@ -597,7 +599,7 @@ type LoopContext = RafLoopContext & TresPartialContext;
597
599
  declare const useLoop: () => {
598
600
  stop: () => void;
599
601
  start: () => void;
600
- isActive: Readonly<vue4.ShallowRef<boolean>>;
602
+ isActive: Readonly<vue6.ShallowRef<boolean>>;
601
603
  onBeforeRender: PriorityEventHookOn<LoopContext>;
602
604
  onRender: PriorityEventHookOn<LoopContext>;
603
605
  render: (fn: RenderFunction) => void;
@@ -704,7 +706,7 @@ interface TresCanvasInstance {
704
706
  type __VLS_Slots = {
705
707
  default: () => any;
706
708
  };
707
- declare const __VLS_base: vue4.DefineComponent<ContextProps, TresCanvasInstance, {}, {}, {}, vue4.ComponentOptionsMixin, vue4.ComponentOptionsMixin, {
709
+ declare const __VLS_base: vue6.DefineComponent<ContextProps, TresCanvasInstance, {}, {}, {}, vue6.ComponentOptionsMixin, vue6.ComponentOptionsMixin, {
708
710
  click: (event: TresPointerEvent) => any;
709
711
  contextmenu: (event: TresPointerEvent) => any;
710
712
  pointermove: (event: TresPointerEvent) => any;
@@ -718,13 +720,13 @@ declare const __VLS_base: vue4.DefineComponent<ContextProps, TresCanvasInstance,
718
720
  pointercancel: (event: TresPointerEvent) => any;
719
721
  lostpointercapture: (event: TresPointerEvent) => any;
720
722
  wheel: (event: TresPointerEvent) => any;
721
- error: (error: Error) => any;
722
723
  ready: (context: TresContext) => any;
724
+ error: (error: Error) => any;
723
725
  pointermissed: (event: TresPointerEvent) => any;
724
726
  render: (context: TresContext) => any;
725
727
  beforeLoop: (context: TresContextWithClock) => any;
726
728
  loop: (context: TresContextWithClock) => any;
727
- }, string, vue4.PublicProps, Readonly<ContextProps> & Readonly<{
729
+ }, string, vue6.PublicProps, Readonly<ContextProps> & Readonly<{
728
730
  onClick?: ((event: TresPointerEvent) => any) | undefined;
729
731
  onContextmenu?: ((event: TresPointerEvent) => any) | undefined;
730
732
  onPointermove?: ((event: TresPointerEvent) => any) | undefined;
@@ -738,14 +740,15 @@ declare const __VLS_base: vue4.DefineComponent<ContextProps, TresCanvasInstance,
738
740
  onPointercancel?: ((event: TresPointerEvent) => any) | undefined;
739
741
  onLostpointercapture?: ((event: TresPointerEvent) => any) | undefined;
740
742
  onWheel?: ((event: TresPointerEvent) => any) | undefined;
741
- onError?: ((error: Error) => any) | undefined;
742
743
  onReady?: ((context: TresContext) => any) | undefined;
744
+ onError?: ((error: Error) => any) | undefined;
743
745
  onPointermissed?: ((event: TresPointerEvent) => any) | undefined;
744
746
  onRender?: ((context: TresContext) => any) | undefined;
745
747
  onBeforeLoop?: ((context: TresContextWithClock) => any) | undefined;
746
748
  onLoop?: ((context: TresContextWithClock) => any) | undefined;
747
749
  }>, {
748
750
  windowSize: boolean;
751
+ enableProvideBridge: boolean;
749
752
  antialias: boolean;
750
753
  stencil: boolean;
751
754
  depth: boolean;
@@ -760,8 +763,7 @@ declare const __VLS_base: vue4.DefineComponent<ContextProps, TresCanvasInstance,
760
763
  shadowMapType: THREE.ShadowMapType;
761
764
  useLegacyLights: boolean;
762
765
  renderMode: "always" | "on-demand" | "manual";
763
- enableProvideBridge: boolean;
764
- }, {}, {}, {}, string, vue4.ComponentProvideOptions, false, {}, any>;
766
+ }, {}, {}, {}, string, vue6.ComponentProvideOptions, false, {}, any>;
765
767
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
766
768
  declare const _default: typeof __VLS_export;
767
769
  type __VLS_WithSlots<T, S> = T & {
package/dist/tres.js CHANGED
@@ -1,20 +1,20 @@
1
1
  /**
2
2
  * name: @tresjs/core
3
- * version: v5.3.3
3
+ * version: v5.4.0
4
4
  * (c) 2026
5
5
  * description: Declarative ThreeJS using Vue Components
6
6
  * author: Alvaro Saburido <hola@alvarosaburido.dev> (https://github.com/alvarosabu/)
7
7
  */
8
8
  import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createRenderer, defineComponent, getCurrentInstance, h, isRef, mergeProps, nextTick, normalizeClass, normalizeStyle, onMounted, onUnmounted, openBlock, provide, reactive, readonly, ref, renderSlot, shallowRef, toValue, unref, useSlots, watch, watchEffect, withCtx } from "vue";
9
9
  import * as THREE from "three";
10
- import { ACESFilmicToneMapping, ArrowHelper, BackSide, BufferAttribute, BufferGeometry, Clock, Color, DirectionalLightHelper, DoubleSide, Float32BufferAttribute, HemisphereLightHelper, Layers, Line, LineBasicMaterial, Material, MathUtils, Mesh, MeshBasicMaterial, Object3D, PCFSoftShadowMap, PerspectiveCamera, PointLightHelper, Scene, SpotLightHelper, Vector3, WebGLRenderer } from "three";
10
+ import { ACESFilmicToneMapping, ArrowHelper, BackSide, BufferAttribute, BufferGeometry, Clock, Color, DirectionalLightHelper, DoubleSide, Float32BufferAttribute, HemisphereLightHelper, Layers, Line, LineBasicMaterial, Material, MathUtils, Mesh, MeshBasicMaterial, PCFSoftShadowMap, PerspectiveCamera, PointLightHelper, Scene, SpotLightHelper, Vector3, WebGLRenderer } from "three";
11
11
  import { createEventHook, createInjectionState, promiseTimeout, refDebounced, tryOnScopeDispose, unrefElement, useAsyncState, useDevicePixelRatio, useElementSize, useFps, useMemory, useRafFn, useTimeout, useWindowSize, whenever } from "@vueuse/core";
12
12
  import { camel, isEqual, isFunction, isNumber, isObject, isString, isUndefined } from "radashi";
13
13
  import { forwardHtmlEvents, getVoidObject } from "@pmndrs/pointer-events";
14
14
  import { setupDevtoolsPlugin } from "@vue/devtools-api";
15
15
 
16
16
  //#region package.json
17
- var version = "5.3.3";
17
+ var version = "5.4.0";
18
18
 
19
19
  //#endregion
20
20
  //#region src/utils/makeMap.ts
@@ -824,7 +824,6 @@ Error details: ${rendererError.message}`, rendererError);
824
824
  errorEventHook.trigger(rendererError);
825
825
  }
826
826
  };
827
- initializeRenderer();
828
827
  const renderEventHook = createEventHook();
829
828
  const notifyFrameRendered = () => {
830
829
  frames.value = isModeAlways.value ? 1 : Math.max(0, frames.value - 1);
@@ -864,6 +863,7 @@ Error details: ${rendererError.message}`, rendererError);
864
863
  if (!isInitialized.value) return;
865
864
  setPixelRatio(renderer, sizes.pixelRatio.value, toValue(options.dpr));
866
865
  });
866
+ initializeRenderer();
867
867
  if (toValue(options.renderMode) === "on-demand") invalidate();
868
868
  if (toValue(options.renderMode) === "manual") useTimeout(100, { callback: advance });
869
869
  const clearColorAndAlpha = computed(() => {
@@ -996,7 +996,11 @@ const [useTresContextProvider, _useTresContext] = createInjectionState(({ scene,
996
996
  extend,
997
997
  events
998
998
  };
999
- ctx.scene.value.__tres = { root: ctx };
999
+ ctx.scene.value.__tres = {
1000
+ root: ctx,
1001
+ objects: [],
1002
+ isUnmounting: false
1003
+ };
1000
1004
  return ctx;
1001
1005
  }, { injectionKey: "useTres" });
1002
1006
  const useTresContext = () => {
@@ -1116,9 +1120,24 @@ const isSupportedPointerEvent = (event) => supportedPointerEvents.includes(event
1116
1120
 
1117
1121
  //#endregion
1118
1122
  //#region src/core/nodeOps.ts
1123
+ const textNodeSymbol = Symbol("tresTextNode");
1124
+ const commentNodeSymbol = Symbol("tresComment");
1119
1125
  const nodeOps = ({ context, options = { primitivePrefix: "" } }) => {
1120
1126
  const scene = context.scene.value;
1121
- function createElement(tag, _isSVG, _anchor, props) {
1127
+ const createTextNode = () => {
1128
+ if (scene?.__tres?.isUnmounting) return;
1129
+ return {
1130
+ [textNodeSymbol]: true,
1131
+ __tres: { parent: null }
1132
+ };
1133
+ };
1134
+ const createCommentNode = () => ({
1135
+ [commentNodeSymbol]: true,
1136
+ __tres: { parent: null }
1137
+ });
1138
+ const isTextNode = (node) => !!node && typeof node === "object" && textNodeSymbol in node;
1139
+ const isCommentNode = (node) => !!node && typeof node === "object" && commentNodeSymbol in node;
1140
+ function createElement(tag, _namespace, _isCustomizedBuiltIn, props) {
1122
1141
  if (!props) props = {};
1123
1142
  if (!props.args) props.args = [];
1124
1143
  if (isHTMLTag(tag)) return null;
@@ -1164,9 +1183,19 @@ const nodeOps = ({ context, options = { primitivePrefix: "" } }) => {
1164
1183
  }, context);
1165
1184
  return obj;
1166
1185
  }
1167
- function insert(child, parent) {
1186
+ function insert(child, parent, anchor) {
1168
1187
  if (!child) return;
1169
1188
  parent = parent || scene;
1189
+ if (isTextNode(child) || isCommentNode(child)) {
1190
+ const parentInstance$1 = parent.__tres ? parent : prepareTresInstance(parent, {}, context);
1191
+ child.__tres.parent = parentInstance$1;
1192
+ if (parentInstance$1.__tres.objects) {
1193
+ const insertIndex = anchor ? parentInstance$1.__tres.objects.findIndex((obj) => obj === anchor) : -1;
1194
+ if (insertIndex >= 0) parentInstance$1.__tres.objects.splice(insertIndex, 0, child);
1195
+ else parentInstance$1.__tres.objects.push(child);
1196
+ }
1197
+ return;
1198
+ }
1170
1199
  const childInstance = child.__tres ? child : prepareTresInstance(child, {}, context);
1171
1200
  const parentInstance = parent.__tres ? parent : prepareTresInstance(parent, {}, context);
1172
1201
  child = unboxTresPrimitive(childInstance);
@@ -1178,7 +1207,11 @@ const nodeOps = ({ context, options = { primitivePrefix: "" } }) => {
1178
1207
  child.dispatchEvent({ type: "added" });
1179
1208
  }
1180
1209
  childInstance.__tres.parent = parentInstance;
1181
- if (parentInstance.__tres.objects && !parentInstance.__tres.objects.includes(childInstance)) parentInstance.__tres.objects.push(childInstance);
1210
+ if (parentInstance.__tres.objects && !parentInstance.__tres.objects.includes(childInstance)) {
1211
+ const insertIndex = anchor ? parentInstance.__tres.objects.findIndex((obj) => obj === anchor) : -1;
1212
+ if (~insertIndex) parentInstance.__tres.objects.splice(insertIndex, 0, childInstance);
1213
+ else parentInstance.__tres.objects.push(childInstance);
1214
+ }
1182
1215
  }
1183
1216
  /**
1184
1217
  * @param node – the node root to remove
@@ -1186,6 +1219,12 @@ const nodeOps = ({ context, options = { primitivePrefix: "" } }) => {
1186
1219
  */
1187
1220
  function remove(node, dispose) {
1188
1221
  if (!node) return;
1222
+ if (isTextNode(node) || isCommentNode(node)) {
1223
+ const parent = node.__tres.parent;
1224
+ if (parent?.__tres?.objects) filterInPlace(parent.__tres.objects, (obj) => obj !== node);
1225
+ node.__tres.parent = null;
1226
+ return;
1227
+ }
1189
1228
  dispose = isUndefined(dispose) ? "default" : dispose;
1190
1229
  const userDispose = node.__tres?.dispose;
1191
1230
  if (!isUndefined(userDispose)) if (userDispose === null) dispose = false;
@@ -1285,23 +1324,10 @@ const nodeOps = ({ context, options = { primitivePrefix: "" } }) => {
1285
1324
  function parentNode(node) {
1286
1325
  return node?.__tres?.parent || null;
1287
1326
  }
1288
- /**
1289
- * createComment
1290
- *
1291
- * Creates a comment object that can be used to represent a commented out string in a vue template
1292
- * Used by Vue's internal runtime as a placeholder for v-if'd elements
1293
- *
1294
- * @param comment Any commented out string contaiend in a vue template, typically this is `v-if`
1295
- * @returns TresObject
1296
- */
1297
- function createComment(comment) {
1298
- const commentObj = prepareTresInstance(new Object3D(), { type: "Comment" }, context);
1299
- commentObj.name = comment;
1300
- return commentObj;
1301
- }
1302
1327
  function nextSibling(node) {
1328
+ if (!node || !("__tres" in node)) return null;
1303
1329
  const siblings = parentNode(node)?.__tres?.objects || [];
1304
- const index = siblings.indexOf(node);
1330
+ const index = siblings.findIndex((sibling) => sibling === node);
1305
1331
  if (index < 0 || index >= siblings.length - 1) return null;
1306
1332
  return siblings[index + 1];
1307
1333
  }
@@ -1312,8 +1338,8 @@ const nodeOps = ({ context, options = { primitivePrefix: "" } }) => {
1312
1338
  createElement,
1313
1339
  patchProp,
1314
1340
  parentNode,
1315
- createText: noop,
1316
- createComment,
1341
+ createText: createTextNode,
1342
+ createComment: createCommentNode,
1317
1343
  setText: noop,
1318
1344
  setElementText: noop,
1319
1345
  nextSibling,
@@ -2031,7 +2057,11 @@ var Context_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ define
2031
2057
  context$1.renderer.instance.forceContextLoss();
2032
2058
  }
2033
2059
  }
2034
- scene.value.__tres = { root: context$1 };
2060
+ scene.value.__tres = {
2061
+ root: context$1,
2062
+ objects: [],
2063
+ isUnmounting: true
2064
+ };
2035
2065
  };
2036
2066
  const context = shallowRef(useTresContextProvider({
2037
2067
  scene: scene.value,
@@ -2044,12 +2074,13 @@ var Context_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ define
2044
2074
  dispose: () => dispose(context.value, true)
2045
2075
  });
2046
2076
  const handleHMR = (context$1) => {
2047
- dispose(context$1);
2048
2077
  mountCustomRenderer(context$1);
2049
2078
  };
2050
2079
  const unmountCanvas = () => {
2051
- dispose(context.value);
2080
+ const isTresScene = (value) => isScene(value) && "__tres" in value;
2081
+ if (isTresScene(scene.value)) scene.value.__tres.isUnmounting = true;
2052
2082
  mountCustomRenderer(context.value, true);
2083
+ dispose(context.value);
2053
2084
  };
2054
2085
  const { camera, renderer } = context.value;
2055
2086
  const { registerCamera, cameras, activeCamera, deregisterCamera } = camera;
@@ -2495,7 +2526,7 @@ const vLightHelper = {
2495
2526
  el.parent?.add(new CurrentHelper(el, 1, el.color.getHex()));
2496
2527
  },
2497
2528
  updated: (el) => {
2498
- currentInstance = el.parent.children.find((child) => child instanceof CurrentHelper);
2529
+ currentInstance = el.parent?.children.find((child) => child instanceof CurrentHelper);
2499
2530
  if (currentInstance instanceof RectAreaLightHelper) return;
2500
2531
  currentInstance.update();
2501
2532
  },
@@ -2504,7 +2535,7 @@ const vLightHelper = {
2504
2535
  logWarning(`${el.type} is not a light`);
2505
2536
  return;
2506
2537
  }
2507
- currentInstance = el.parent.children.find((child) => child instanceof CurrentHelper);
2538
+ currentInstance = el.parent?.children.find((child) => child instanceof CurrentHelper);
2508
2539
  if (currentInstance && currentInstance.dispose) currentInstance.dispose();
2509
2540
  if (el.parent) el.parent.remove(currentInstance);
2510
2541
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tresjs/core",
3
3
  "type": "module",
4
- "version": "5.3.3",
4
+ "version": "5.4.0",
5
5
  "description": "Declarative ThreeJS using Vue Components",
6
6
  "author": "Alvaro Saburido <hola@alvarosaburido.dev> (https://github.com/alvarosabu/)",
7
7
  "license": "MIT",