angular-three 1.9.11 → 1.9.13

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.
Files changed (35) hide show
  1. package/esm2020/lib/canvas.mjs +18 -22
  2. package/esm2020/lib/di/before-render.mjs +2 -2
  3. package/esm2020/lib/di/ref.mjs +9 -11
  4. package/esm2020/lib/di/run-in-context.mjs +6 -1
  5. package/esm2020/lib/directives/args.mjs +5 -7
  6. package/esm2020/lib/directives/common.mjs +6 -5
  7. package/esm2020/lib/directives/parent.mjs +3 -3
  8. package/esm2020/lib/directives/repeat.mjs +3 -3
  9. package/esm2020/lib/loader.mjs +10 -6
  10. package/esm2020/lib/pipes/push.mjs +16 -21
  11. package/esm2020/lib/portal.mjs +46 -50
  12. package/esm2020/lib/renderer/provider.mjs +3 -5
  13. package/esm2020/lib/renderer/renderer.mjs +9 -8
  14. package/esm2020/lib/renderer/store.mjs +376 -0
  15. package/esm2020/lib/renderer/utils.mjs +16 -27
  16. package/esm2020/lib/routed-scene.mjs +6 -5
  17. package/esm2020/lib/stores/rx-store.mjs +17 -40
  18. package/esm2020/lib/stores/store.mjs +15 -21
  19. package/esm2020/lib/utils/instance.mjs +3 -1
  20. package/esm2020/lib/utils/safe-detect-changes.mjs +4 -2
  21. package/fesm2015/angular-three.mjs +183 -238
  22. package/fesm2015/angular-three.mjs.map +1 -1
  23. package/fesm2020/angular-three.mjs +190 -246
  24. package/fesm2020/angular-three.mjs.map +1 -1
  25. package/lib/canvas.d.ts +2 -2
  26. package/lib/di/run-in-context.d.ts +5 -0
  27. package/lib/pipes/push.d.ts +1 -0
  28. package/lib/portal.d.ts +2 -2
  29. package/lib/renderer/renderer.d.ts +4 -4
  30. package/lib/renderer/{state.d.ts → store.d.ts} +2 -2
  31. package/lib/stores/rx-store.d.ts +2 -8
  32. package/lib/utils/safe-detect-changes.d.ts +1 -1
  33. package/package.json +5 -5
  34. package/plugin/package.json +2 -2
  35. package/esm2020/lib/renderer/state.mjs +0 -381
@@ -1,11 +1,11 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { inject, ChangeDetectorRef, ElementRef, Injectable, InjectionToken, ViewContainerRef, TemplateRef, Directive, Input, EventEmitter, getDebugNode, RendererFactory2, makeEnvironmentProviders, EnvironmentInjector, createEnvironmentInjector, Component, HostBinding, Output, ViewChild, Injector, Pipe, SkipSelf, ContentChild } from '@angular/core';
3
3
  import { provideNgxResizeOptions, NgxResize } from 'ngx-resize';
4
- import { isObservable, of, map, from, tap, retry, catchError, share, ReplaySubject, switchMap, forkJoin, take, BehaviorSubject, startWith, combineLatest, distinctUntilChanged, filter, takeUntil, merge } from 'rxjs';
4
+ import { isObservable, of, map, from, tap, retry, catchError, share, ReplaySubject, switchMap, forkJoin, take, BehaviorSubject, startWith, combineLatest, filter, distinctUntilChanged, takeUntil, merge } from 'rxjs';
5
5
  import * as THREE from 'three';
6
- import { __rest, __classPrivateFieldGet } from 'tslib';
6
+ import { __rest } from 'tslib';
7
7
  import { DOCUMENT, NgForOf, NgIf } from '@angular/common';
8
- import { RxState, selectSlice } from '@rx-angular/state';
8
+ import { RxState } from '@rx-angular/state';
9
9
  import * as i1 from '@angular/router';
10
10
  import { ActivationEnd, RouterOutlet } from '@angular/router';
11
11
 
@@ -52,10 +52,24 @@ function makeObjectGraph(object) {
52
52
  return data;
53
53
  }
54
54
 
55
+ function safeDetectChanges(cdr) {
56
+ if (!cdr)
57
+ return;
58
+ try {
59
+ // dynamic created component with ViewContainerRef#createComponent does not have Context
60
+ // but it has _attachedToViewContainer
61
+ if (cdr['context'] || cdr['_attachedToViewContainer']) {
62
+ cdr.detectChanges();
63
+ }
64
+ }
65
+ catch (e) {
66
+ cdr.markForCheck();
67
+ }
68
+ }
69
+
55
70
  const cached = new Map();
56
- function injectLoader(loaderConstructorFactory, input, extensions, onProgress) {
71
+ function load(loaderConstructorFactory, input, extensions, onProgress) {
57
72
  const urls$ = isObservable(input) ? input : of(input);
58
- const cdr = inject(ChangeDetectorRef);
59
73
  return urls$.pipe(map((inputs) => {
60
74
  const loaderConstructor = loaderConstructorFactory(inputs);
61
75
  const loader = new loaderConstructor();
@@ -77,7 +91,11 @@ function injectLoader(loaderConstructorFactory, input, extensions, onProgress) {
77
91
  }),
78
92
  inputs,
79
93
  ];
80
- }), switchMap(([observables$, inputs]) => {
94
+ }));
95
+ }
96
+ function injectLoader(loaderConstructorFactory, input, extensions, onProgress) {
97
+ const cdr = inject(ChangeDetectorRef);
98
+ return load(loaderConstructorFactory, input, extensions, onProgress).pipe(switchMap(([observables$, inputs]) => {
81
99
  return forkJoin(observables$).pipe(map((results) => {
82
100
  if (Array.isArray(inputs))
83
101
  return results;
@@ -89,7 +107,7 @@ function injectLoader(loaderConstructorFactory, input, extensions, onProgress) {
89
107
  return result;
90
108
  }, {});
91
109
  }), tap(() => {
92
- requestAnimationFrame(() => cdr.detectChanges());
110
+ requestAnimationFrame(() => void safeDetectChanges(cdr));
93
111
  }));
94
112
  }));
95
113
  }
@@ -97,7 +115,7 @@ injectLoader.destroy = () => {
97
115
  cached.clear();
98
116
  };
99
117
  injectLoader.preLoad = (loaderConstructorFactory, inputs, extensions) => {
100
- injectLoader(loaderConstructorFactory, inputs, extensions).pipe(take(1)).subscribe();
118
+ load(loaderConstructorFactory, inputs, extensions).pipe(take(1)).subscribe();
101
119
  };
102
120
  const injectNgtLoader = injectLoader;
103
121
 
@@ -341,6 +359,8 @@ function prepare(object, localState) {
341
359
  const current = instance.__ngt__[type].value;
342
360
  const foundIndex = current.indexOf((obj) => obj === object);
343
361
  if (foundIndex > -1) {
362
+ // if we add an object with the same reference, then we switch it out
363
+ // and update the BehaviorSubject
344
364
  current.splice(foundIndex, 1, object);
345
365
  instance.__ngt__[type].next(current);
346
366
  }
@@ -461,7 +481,6 @@ const startWithUndefined = () => startWith(undefined);
461
481
  * - can optionally return a `cleanUp` function that
462
482
  * invokes from the 2nd `next` notification onward and on `unsubscribe` (destroyed)
463
483
  *
464
- *
465
484
  * @example
466
485
  * ```typescript
467
486
  * source$.pipe(
@@ -482,26 +501,20 @@ function tapEffect(effectFn) {
482
501
  let cleanupFn = () => { };
483
502
  let firstRun = false;
484
503
  let prev = undefined;
485
- const teardown = (error) => {
486
- return () => {
487
- if (cleanupFn) {
488
- cleanupFn({ prev, complete: true, error });
489
- }
490
- };
504
+ const teardown = (error) => () => {
505
+ if (cleanupFn)
506
+ cleanupFn({ prev, complete: true, error });
491
507
  };
492
508
  return tap({
493
509
  next: (value) => {
494
- if (cleanupFn && firstRun) {
510
+ if (cleanupFn && firstRun)
495
511
  cleanupFn({ prev, complete: false, error: false });
496
- }
497
512
  const cleanUpOrVoid = effectFn(value);
498
- if (cleanUpOrVoid) {
513
+ if (cleanUpOrVoid)
499
514
  cleanupFn = cleanUpOrVoid;
500
- }
501
515
  prev = value;
502
- if (!firstRun) {
516
+ if (!firstRun)
503
517
  firstRun = true;
504
- }
505
518
  },
506
519
  complete: teardown(false),
507
520
  unsubscribe: teardown(false),
@@ -511,7 +524,6 @@ function tapEffect(effectFn) {
511
524
  class NgtRxStore extends RxState {
512
525
  constructor() {
513
526
  super();
514
- this.cache = {};
515
527
  // set a dummy property so that initial this.get() won't return undefined
516
528
  this.set({ __ngt_dummy__: '__ngt_dummy__' });
517
529
  // override set so our consumers don't have to handle undefined for state that already have default values
@@ -534,14 +546,11 @@ class NgtRxStore extends RxState {
534
546
  // override get to return {} if get() returns undefined
535
547
  const originalGet = this.get.bind(this);
536
548
  Object.defineProperty(this, 'get', {
537
- get: () => {
538
- return (...args) => {
539
- var _a;
540
- if (args.length === 0) {
541
- return (_a = originalGet()) !== null && _a !== void 0 ? _a : {};
542
- }
543
- return originalGet(...args);
544
- };
549
+ get: () => (...args) => {
550
+ var _a;
551
+ if (args.length === 0)
552
+ return (_a = originalGet()) !== null && _a !== void 0 ? _a : {};
553
+ return originalGet(...args);
545
554
  },
546
555
  });
547
556
  // call initialize that might be setup by derived Stores
@@ -558,26 +567,12 @@ class NgtRxStore extends RxState {
558
567
  if (keys.length) {
559
568
  $ = combineLatest(keys.map((key) => { var _a; return this.select(key).pipe(startWith((_a = this.get(key)) !== null && _a !== void 0 ? _a : undefined)); }));
560
569
  }
561
- this.hold($, () => {
562
- requestAnimationFrame(() => void cdr.detectChanges());
563
- });
564
- }
565
- key$(...keys) {
566
- var _a;
567
- const key = keys.join('.');
568
- if (!this.cache[key]) {
569
- this.cache[key] = this.select(...keys).pipe(startWith((_a = this.get(...keys)) !== null && _a !== void 0 ? _a : undefined), distinctUntilChanged());
570
- }
571
- return this.cache[key];
572
- }
573
- ngOnDestroy() {
574
- this.cache = {};
575
- super.ngOnDestroy();
570
+ this.hold($, () => void requestAnimationFrame(() => void safeDetectChanges(cdr)));
576
571
  }
577
572
  }
578
- NgtRxStore.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgtRxStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
579
- NgtRxStore.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgtRxStore });
580
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgtRxStore, decorators: [{
573
+ NgtRxStore.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: NgtRxStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
574
+ NgtRxStore.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: NgtRxStore });
575
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: NgtRxStore, decorators: [{
581
576
  type: Injectable
582
577
  }], ctorParameters: function () { return []; } });
583
578
 
@@ -620,7 +615,6 @@ class NgtStore extends NgtRxStore {
620
615
  const w = h * aspect;
621
616
  return { width: w, height: h, top, left, factor: width / w, distance, aspect };
622
617
  };
623
- const pointer = new THREE.Vector2();
624
618
  let performanceTimeout;
625
619
  const setPerformanceCurrent = (current) => {
626
620
  this.set((state) => ({ performance: Object.assign(Object.assign({}, state.performance), { current }) }));
@@ -639,7 +633,7 @@ class NgtStore extends NgtRxStore {
639
633
  flat: false,
640
634
  controls: null,
641
635
  clock: new THREE.Clock(),
642
- pointer,
636
+ pointer: new THREE.Vector2(),
643
637
  frameloop: 'always',
644
638
  performance: {
645
639
  current: 1,
@@ -755,14 +749,12 @@ class NgtStore extends NgtRxStore {
755
749
  const stateToUpdate = {};
756
750
  // setup renderer
757
751
  let gl = state.gl;
758
- if (!state.gl) {
752
+ if (!state.gl)
759
753
  stateToUpdate.gl = gl = makeDefaultRenderer(glOptions, canvasElement);
760
- }
761
754
  // setup raycaster
762
755
  let raycaster = state.raycaster;
763
- if (!raycaster) {
756
+ if (!raycaster)
764
757
  stateToUpdate.raycaster = raycaster = new THREE.Raycaster();
765
- }
766
758
  // set raycaster options
767
759
  const _b = raycasterOptions || {}, { params } = _b, options = __rest(_b, ["params"]);
768
760
  if (!is.equ(options, raycaster, shallowLoose))
@@ -898,9 +890,7 @@ class NgtStore extends NgtRxStore {
898
890
  this.invalidate();
899
891
  }
900
892
  destroy(canvas) {
901
- this.set((state) => ({
902
- internal: Object.assign(Object.assign({}, state.internal), { active: false }),
903
- }));
893
+ this.set((state) => ({ internal: Object.assign(Object.assign({}, state.internal), { active: false }) }));
904
894
  setTimeout(() => {
905
895
  const { gl, xr, events } = this.get();
906
896
  if (gl) {
@@ -923,8 +913,7 @@ class NgtStore extends NgtRxStore {
923
913
  let oldSize = state.size;
924
914
  let oldDpr = state.viewport.dpr;
925
915
  let oldCamera = state.camera;
926
- this.hold(this.select(selectSlice(['camera', 'size', 'viewport', 'gl'])), () => {
927
- const { camera, size, viewport, gl, set } = this.get();
916
+ this.hold(combineLatest([this.select('camera'), this.select('size'), this.select('viewport'), this.select('gl')]), ([camera, size, viewport, gl]) => {
928
917
  // resize camera and renderer on changes to size and dpr
929
918
  if (size !== oldSize || viewport.dpr !== oldDpr) {
930
919
  oldSize = size;
@@ -938,7 +927,9 @@ class NgtStore extends NgtRxStore {
938
927
  if (camera !== oldCamera) {
939
928
  updateCamera(camera, size);
940
929
  oldCamera = camera;
941
- set((state) => ({ viewport: Object.assign(Object.assign({}, state.viewport), state.viewport.getCurrentViewport(camera)) }));
930
+ this.set((state) => ({
931
+ viewport: Object.assign(Object.assign({}, state.viewport), state.viewport.getCurrentViewport(camera)),
932
+ }));
942
933
  }
943
934
  });
944
935
  }
@@ -946,18 +937,16 @@ class NgtStore extends NgtRxStore {
946
937
  this.hold(this.select(), () => invalidate(this));
947
938
  }
948
939
  }
949
- NgtStore.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgtStore, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
950
- NgtStore.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgtStore });
951
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgtStore, decorators: [{
940
+ NgtStore.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: NgtStore, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
941
+ NgtStore.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: NgtStore });
942
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: NgtStore, decorators: [{
952
943
  type: Injectable
953
944
  }] });
954
945
  function computeInitialSize(canvas, defaultSize) {
955
- if (defaultSize) {
946
+ if (defaultSize)
956
947
  return defaultSize;
957
- }
958
948
  if (canvas instanceof HTMLCanvasElement && canvas.parentElement) {
959
- const { width, height, top, left } = canvas.parentElement.getBoundingClientRect();
960
- return { width, height, top, left };
949
+ return canvas.parentElement.getBoundingClientRect();
961
950
  }
962
951
  return { width: 0, height: 0, top: 0, left: 0 };
963
952
  }
@@ -998,13 +987,13 @@ class NgtCommonDirective {
998
987
  this.view.destroy();
999
988
  }
1000
989
  this.view = this.vcr.createEmbeddedView(this.template);
1001
- this.view.detectChanges();
990
+ safeDetectChanges(this.view);
1002
991
  }
1003
992
  }
1004
993
  }
1005
- NgtCommonDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgtCommonDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1006
- NgtCommonDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.0", type: NgtCommonDirective, ngImport: i0 });
1007
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgtCommonDirective, decorators: [{
994
+ NgtCommonDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: NgtCommonDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
995
+ NgtCommonDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.5", type: NgtCommonDirective, ngImport: i0 });
996
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: NgtCommonDirective, decorators: [{
1008
997
  type: Directive
1009
998
  }], ctorParameters: function () { return []; } });
1010
999
 
@@ -1014,9 +1003,7 @@ class NgtArgs extends NgtCommonDirective {
1014
1003
  this.injectedArgs = [];
1015
1004
  }
1016
1005
  set args(args) {
1017
- if (args == null || !Array.isArray(args))
1018
- return;
1019
- if (args.length === 1 && args[0] === null)
1006
+ if (args == null || !Array.isArray(args) || (args.length === 1 && args[0] === null))
1020
1007
  return;
1021
1008
  this.injected = false;
1022
1009
  this.injectedArgs = args;
@@ -1033,9 +1020,9 @@ class NgtArgs extends NgtCommonDirective {
1033
1020
  return !this.injected && !!this.injectedArgs.length;
1034
1021
  }
1035
1022
  }
1036
- NgtArgs.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgtArgs, deps: null, target: i0.ɵɵFactoryTarget.Directive });
1037
- NgtArgs.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.0", type: NgtArgs, isStandalone: true, selector: "[args]", inputs: { args: "args" }, usesInheritance: true, ngImport: i0 });
1038
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgtArgs, decorators: [{
1023
+ NgtArgs.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: NgtArgs, deps: null, target: i0.ɵɵFactoryTarget.Directive });
1024
+ NgtArgs.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.5", type: NgtArgs, isStandalone: true, selector: "[args]", inputs: { args: "args" }, usesInheritance: true, ngImport: i0 });
1025
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: NgtArgs, decorators: [{
1039
1026
  type: Directive,
1040
1027
  args: [{ selector: '[args]', standalone: true }]
1041
1028
  }], propDecorators: { args: [{
@@ -1065,9 +1052,9 @@ class NgtParent extends NgtCommonDirective {
1065
1052
  return !this.injected && !!this.injectedParent;
1066
1053
  }
1067
1054
  }
1068
- NgtParent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgtParent, deps: null, target: i0.ɵɵFactoryTarget.Directive });
1069
- NgtParent.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.0", type: NgtParent, isStandalone: true, selector: "[parent]", inputs: { parent: "parent" }, usesInheritance: true, ngImport: i0 });
1070
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgtParent, decorators: [{
1055
+ NgtParent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: NgtParent, deps: null, target: i0.ɵɵFactoryTarget.Directive });
1056
+ NgtParent.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.5", type: NgtParent, isStandalone: true, selector: "[parent]", inputs: { parent: "parent" }, usesInheritance: true, ngImport: i0 });
1057
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: NgtParent, decorators: [{
1071
1058
  type: Directive,
1072
1059
  args: [{ selector: '[parent]', standalone: true }]
1073
1060
  }], propDecorators: { parent: [{
@@ -1512,9 +1499,8 @@ function attachThreeChild(parent, child) {
1512
1499
  }
1513
1500
  pLS.add(child, added ? 'objects' : 'nonObjects');
1514
1501
  cLS.parent = parent;
1515
- if (cLS.afterAttach) {
1502
+ if (cLS.afterAttach)
1516
1503
  cLS.afterAttach.emit({ parent, node: child });
1517
- }
1518
1504
  invalidateInstance(child);
1519
1505
  invalidateInstance(parent);
1520
1506
  }
@@ -1525,12 +1511,10 @@ function removeThreeChild(parent, child, dispose) {
1525
1511
  // clear parent ref
1526
1512
  cLS.parent = null;
1527
1513
  // remove child from parent
1528
- if (pLS.objects) {
1514
+ if (pLS.objects)
1529
1515
  pLS.remove(child, 'objects');
1530
- }
1531
- if (pLS.nonObjects) {
1516
+ if (pLS.nonObjects)
1532
1517
  pLS.remove(child, 'nonObjects');
1533
- }
1534
1518
  if (cLS.attach) {
1535
1519
  detach(parent, child, cLS.attach);
1536
1520
  }
@@ -1554,7 +1538,6 @@ function removeThreeRecursive(array, parent, dispose) {
1554
1538
  [...array].forEach((child) => removeThreeChild(parent, child, dispose));
1555
1539
  }
1556
1540
  function processThreeEvent(instance, priority, eventName, callback, cdr, targetCdr) {
1557
- var _a;
1558
1541
  const lS = getLocalState(instance);
1559
1542
  if (eventName === SPECIAL_EVENTS.BEFORE_RENDER) {
1560
1543
  return lS.store
@@ -1562,15 +1545,14 @@ function processThreeEvent(instance, priority, eventName, callback, cdr, targetC
1562
1545
  .subscribe((state) => callback({ state, object: instance }), priority || lS.priority || 0);
1563
1546
  }
1564
1547
  if (eventName === SPECIAL_EVENTS.AFTER_UPDATE || eventName === SPECIAL_EVENTS.AFTER_ATTACH) {
1565
- if (!lS[eventName]) {
1566
- lS[eventName] = new EventEmitter();
1567
- }
1568
- const sub = (_a = lS[eventName]) === null || _a === void 0 ? void 0 : _a.subscribe(callback);
1548
+ let emitter = lS[eventName];
1549
+ if (!emitter)
1550
+ emitter = new EventEmitter();
1551
+ const sub = emitter.subscribe(callback);
1569
1552
  return sub.unsubscribe.bind(sub);
1570
1553
  }
1571
- if (!lS.handlers) {
1554
+ if (!lS.handlers)
1572
1555
  lS.handlers = {};
1573
- }
1574
1556
  // try to get the previous handler. compound might have one, the THREE object might also have one with the same name
1575
1557
  const previousHandler = lS.handlers[eventName];
1576
1558
  // readjust the callback
@@ -1579,37 +1561,32 @@ function processThreeEvent(instance, priority, eventName, callback, cdr, targetC
1579
1561
  previousHandler(event);
1580
1562
  callback(event);
1581
1563
  };
1582
- lS.handlers = Object.assign(Object.assign({}, lS.handlers), { [eventName]: eventToHandler(updatedCallback, cdr, targetCdr) });
1564
+ Object.assign(lS.handlers, { [eventName]: eventToHandler(updatedCallback, cdr, targetCdr) });
1583
1565
  // increment the count everytime
1584
1566
  lS.eventCount += 1;
1585
1567
  // but only add the instance (target) to the interaction array (so that it is handled by the EventManager with Raycast)
1586
1568
  // the first time eventCount is incremented
1587
- if (lS.eventCount === 1 && instance['raycast']) {
1569
+ if (lS.eventCount === 1 && instance['raycast'])
1588
1570
  lS.store.get('addInteraction')(instance);
1589
- }
1590
1571
  // clean up the event listener by removing the target from the interaction array
1591
1572
  return () => {
1592
1573
  const localState = getLocalState(instance);
1593
- if (localState && localState.eventCount) {
1574
+ if (localState && localState.eventCount)
1594
1575
  localState.store.get('removeInteraction')(instance['uuid']);
1595
- }
1596
1576
  };
1597
1577
  }
1598
1578
  function eventToHandler(callback, cdr, targetCdr) {
1599
1579
  return (event) => {
1600
1580
  callback(event);
1601
- if (targetCdr)
1602
- targetCdr.detectChanges();
1603
- cdr.detectChanges();
1581
+ safeDetectChanges(targetCdr);
1582
+ safeDetectChanges(cdr);
1604
1583
  };
1605
1584
  }
1606
1585
  function kebabToPascal(str) {
1607
1586
  // split the string at each hyphen
1608
1587
  const parts = str.split('-');
1609
1588
  // map over the parts, capitalizing the first letter of each part
1610
- const pascalParts = parts.map((part) => {
1611
- return part.charAt(0).toUpperCase() + part.slice(1);
1612
- });
1589
+ const pascalParts = parts.map((part) => part.charAt(0).toUpperCase() + part.slice(1));
1613
1590
  // join the parts together to create the final PascalCase string
1614
1591
  return pascalParts.join('');
1615
1592
  }
@@ -1639,9 +1616,8 @@ class NgtRendererStore {
1639
1616
  ];
1640
1617
  const rendererNode = Object.assign(node, { __ngt_renderer__: state });
1641
1618
  // assign ownerDocument to node so we can use HostListener in Component
1642
- if (!rendererNode['ownerDocument']) {
1619
+ if (!rendererNode['ownerDocument'])
1643
1620
  rendererNode['ownerDocument'] = this.root.document;
1644
- }
1645
1621
  // assign injectorFactory on non-three type since
1646
1622
  // rendererNode is an instance of DOM Node
1647
1623
  if (state[0 /* NgtRendererClassId.type */] !== 'three') {
@@ -1651,9 +1627,9 @@ class NgtRendererStore {
1651
1627
  // we attach an arrow function to the Comment node
1652
1628
  // In our directives, we can call this function to then start tracking the RendererNode
1653
1629
  // this is done to limit the amount of Nodes we need to process for getCreationState
1654
- rendererNode['__ngt_renderer_add_comment__'] = (portalNode) => {
1655
- if (portalNode && portalNode.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'portal') {
1656
- this.portals.push(portalNode);
1630
+ rendererNode['__ngt_renderer_add_comment__'] = (node) => {
1631
+ if (node && node.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'portal') {
1632
+ this.portals.push(node);
1657
1633
  }
1658
1634
  else {
1659
1635
  this.comments.push(rendererNode);
@@ -1690,15 +1666,11 @@ class NgtRendererStore {
1690
1666
  rS[7 /* NgtRendererClassId.compounded */] = instance;
1691
1667
  const attributes = Object.keys(rS[9 /* NgtRendererClassId.attributes */]);
1692
1668
  const properties = Object.keys(rS[10 /* NgtRendererClassId.properties */]);
1693
- if (attributes.length) {
1694
- for (const key of attributes) {
1695
- this.applyAttribute(instance, key, rS[9 /* NgtRendererClassId.attributes */][key]);
1696
- }
1669
+ for (const key of attributes) {
1670
+ this.applyAttribute(instance, key, rS[9 /* NgtRendererClassId.attributes */][key]);
1697
1671
  }
1698
- if (properties.length) {
1699
- for (const key of properties) {
1700
- this.applyProperty(instance, key, rS[10 /* NgtRendererClassId.properties */][key]);
1701
- }
1672
+ for (const key of properties) {
1673
+ this.applyProperty(instance, key, rS[10 /* NgtRendererClassId.properties */][key]);
1702
1674
  }
1703
1675
  this.executeOperation(compound);
1704
1676
  }
@@ -1995,6 +1967,7 @@ class NgtRendererFactory {
1995
1967
  this.catalogue = inject(NGT_CATALOGUE);
1996
1968
  this.rendererMap = new Map();
1997
1969
  this.routedSet = new Set();
1970
+ // all Renderer instances share the same Store
1998
1971
  this.rendererStore = new NgtRendererStore({
1999
1972
  store: inject(NgtStore),
2000
1973
  cdr: inject(ChangeDetectorRef),
@@ -2020,9 +1993,9 @@ class NgtRendererFactory {
2020
1993
  return renderer;
2021
1994
  }
2022
1995
  }
2023
- NgtRendererFactory.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgtRendererFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2024
- NgtRendererFactory.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgtRendererFactory });
2025
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgtRendererFactory, decorators: [{
1996
+ NgtRendererFactory.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: NgtRendererFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1997
+ NgtRendererFactory.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: NgtRendererFactory });
1998
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: NgtRendererFactory, decorators: [{
2026
1999
  type: Injectable
2027
2000
  }] });
2028
2001
  /**
@@ -2292,9 +2265,8 @@ class NgtRenderer {
2292
2265
  // if target is DOM node, then we pass that to delegate Renderer
2293
2266
  const callbackWithCdr = (event) => {
2294
2267
  const value = callback(event);
2295
- if (targetCdr)
2296
- targetCdr.detectChanges();
2297
- this.store.rootCdr.detectChanges();
2268
+ safeDetectChanges(targetCdr);
2269
+ safeDetectChanges(this.store.rootCdr);
2298
2270
  return value;
2299
2271
  };
2300
2272
  if (this.store.isDOM(target)) {
@@ -2332,12 +2304,10 @@ class NgtRenderer {
2332
2304
  }
2333
2305
 
2334
2306
  function provideNgtRenderer({ store, changeDetectorRef, compoundPrefixes = [] }) {
2335
- if (!compoundPrefixes.includes('ngts')) {
2307
+ if (!compoundPrefixes.includes('ngts'))
2336
2308
  compoundPrefixes.push('ngts');
2337
- }
2338
- if (!compoundPrefixes.includes('ngtp')) {
2309
+ if (!compoundPrefixes.includes('ngtp'))
2339
2310
  compoundPrefixes.push('ngtp');
2340
- }
2341
2311
  return makeEnvironmentProviders([
2342
2312
  { provide: RendererFactory2, useClass: NgtRendererFactory },
2343
2313
  { provide: NgtStore, useValue: store },
@@ -2422,7 +2392,7 @@ class NgtCanvas extends NgtRxStore {
2422
2392
  this.envInjector = inject(EnvironmentInjector);
2423
2393
  this.host = inject(ElementRef);
2424
2394
  this.store = inject(NgtStore);
2425
- this.hostClass = true;
2395
+ this.hbClass = true;
2426
2396
  this.sceneGraphInputs = {};
2427
2397
  this.compoundPrefixes = [];
2428
2398
  this.created = new EventEmitter();
@@ -2441,7 +2411,7 @@ class NgtCanvas extends NgtRxStore {
2441
2411
  events: createPointerEvents,
2442
2412
  });
2443
2413
  }
2444
- get pointerEvents() {
2414
+ get hbPointerEvents() {
2445
2415
  return this.get('eventSource') !== this.host.nativeElement ? 'none' : 'auto';
2446
2416
  }
2447
2417
  set linear(linear) {
@@ -2502,7 +2472,7 @@ class NgtCanvas extends NgtRxStore {
2502
2472
  this.store.set({
2503
2473
  onPointerMissed: (event) => {
2504
2474
  this.pointerMissed.emit(event);
2505
- this.cdr.detectChanges();
2475
+ safeDetectChanges(this.cdr);
2506
2476
  },
2507
2477
  });
2508
2478
  }
@@ -2541,22 +2511,17 @@ class NgtCanvas extends NgtRxStore {
2541
2511
  });
2542
2512
  }
2543
2513
  // emit created event if observed
2544
- if (this.created.observed) {
2514
+ if (this.created.observed)
2545
2515
  this.created.emit(this.store.get());
2546
- this.cdr.detectChanges();
2547
- }
2548
2516
  // render
2549
2517
  if (this.glRef)
2550
2518
  this.glRef.destroy();
2551
2519
  requestAnimationFrame(() => {
2552
- this.glEnvInjector = createEnvironmentInjector([
2553
- provideNgtRenderer({
2554
- store: this.store,
2555
- changeDetectorRef: this.cdr,
2556
- compoundPrefixes: this.compoundPrefixes,
2557
- }),
2558
- ], this.envInjector);
2520
+ const { store, cdr: changeDetectorRef, compoundPrefixes } = this;
2521
+ this.glEnvInjector = createEnvironmentInjector([provideNgtRenderer({ store, changeDetectorRef, compoundPrefixes })], this.envInjector);
2559
2522
  this.glRef = this.glAnchor.createComponent(this.sceneGraph, { environmentInjector: this.glEnvInjector });
2523
+ // detach the Scene graph from Change Detection mechanism
2524
+ // everything from this point forward will trigger CD manually with detectChanges
2560
2525
  this.glRef.changeDetectorRef.detach();
2561
2526
  this.setSceneGraphInputs();
2562
2527
  // here, we override the detectChanges to also call detectChanges on the ComponentRef
@@ -2578,34 +2543,33 @@ class NgtCanvas extends NgtRxStore {
2578
2543
  this.cdr.detectChanges = () => {
2579
2544
  var _a;
2580
2545
  originalDetectChanges();
2581
- (_a = this.glRef) === null || _a === void 0 ? void 0 : _a.changeDetectorRef.detectChanges();
2546
+ safeDetectChanges((_a = this.glRef) === null || _a === void 0 ? void 0 : _a.changeDetectorRef);
2582
2547
  };
2583
2548
  }
2584
2549
  setSceneGraphInputs() {
2585
- var _a;
2586
2550
  for (const key of Object.keys(this.sceneGraphInputs)) {
2587
- (_a = this.glRef) === null || _a === void 0 ? void 0 : _a.setInput(key, this.sceneGraphInputs[key]);
2551
+ this.glRef.setInput(key, this.sceneGraphInputs[key]);
2588
2552
  }
2589
- this.cdr.detectChanges();
2553
+ safeDetectChanges(this.cdr);
2590
2554
  }
2591
2555
  }
2592
- NgtCanvas.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgtCanvas, deps: null, target: i0.ɵɵFactoryTarget.Component });
2593
- NgtCanvas.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.0", type: NgtCanvas, isStandalone: true, selector: "ngt-canvas", inputs: { sceneGraph: "sceneGraph", sceneGraphInputs: "sceneGraphInputs", compoundPrefixes: "compoundPrefixes", linear: "linear", legacy: "legacy", flat: "flat", orthographic: "orthographic", frameloop: "frameloop", dpr: "dpr", raycaster: "raycaster", shadows: "shadows", camera: "camera", gl: "gl", eventSource: "eventSource", eventPrefix: "eventPrefix", lookAt: "lookAt", performance: "performance" }, outputs: { created: "created", pointerMissed: "pointerMissed" }, host: { properties: { "class.ngt-canvas": "this.hostClass", "style.pointerEvents": "this.pointerEvents" } }, providers: [NgtStore, provideNgxResizeOptions({ emitInZone: false })], viewQueries: [{ propertyName: "glCanvas", first: true, predicate: ["glCanvas"], descendants: true, static: true }, { propertyName: "glAnchor", first: true, predicate: ["glCanvas"], descendants: true, read: ViewContainerRef, static: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: `
2556
+ NgtCanvas.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: NgtCanvas, deps: null, target: i0.ɵɵFactoryTarget.Component });
2557
+ NgtCanvas.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.5", type: NgtCanvas, isStandalone: true, selector: "ngt-canvas", inputs: { sceneGraph: "sceneGraph", sceneGraphInputs: "sceneGraphInputs", compoundPrefixes: "compoundPrefixes", linear: "linear", legacy: "legacy", flat: "flat", orthographic: "orthographic", frameloop: "frameloop", dpr: "dpr", raycaster: "raycaster", shadows: "shadows", camera: "camera", gl: "gl", eventSource: "eventSource", eventPrefix: "eventPrefix", lookAt: "lookAt", performance: "performance" }, outputs: { created: "created", pointerMissed: "pointerMissed" }, host: { properties: { "class.ngt-canvas": "this.hbClass", "style.pointerEvents": "this.hbPointerEvents" } }, providers: [NgtStore, provideNgxResizeOptions({ emitInZone: false })], viewQueries: [{ propertyName: "glCanvas", first: true, predicate: ["glCanvas"], descendants: true, static: true }, { propertyName: "glAnchor", first: true, predicate: ["glCanvas"], descendants: true, read: ViewContainerRef, static: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: `
2594
2558
  <div (ngxResize)="onResize($event)" style="height: 100%; width: 100%;">
2595
2559
  <canvas #glCanvas style="display: block;"></canvas>
2596
2560
  </div>
2597
2561
  `, isInline: true, styles: [":host{display:block;position:relative;width:100%;height:100%;overflow:hidden}\n"], dependencies: [{ kind: "directive", type: NgxResize, selector: "[ngxResize]", inputs: ["ngxResizeOptions"], outputs: ["ngxResize"] }] });
2598
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgtCanvas, decorators: [{
2562
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: NgtCanvas, decorators: [{
2599
2563
  type: Component,
2600
2564
  args: [{ selector: 'ngt-canvas', standalone: true, template: `
2601
2565
  <div (ngxResize)="onResize($event)" style="height: 100%; width: 100%;">
2602
2566
  <canvas #glCanvas style="display: block;"></canvas>
2603
2567
  </div>
2604
2568
  `, imports: [NgxResize], providers: [NgtStore, provideNgxResizeOptions({ emitInZone: false })], styles: [":host{display:block;position:relative;width:100%;height:100%;overflow:hidden}\n"] }]
2605
- }], propDecorators: { hostClass: [{
2569
+ }], propDecorators: { hbClass: [{
2606
2570
  type: HostBinding,
2607
2571
  args: ['class.ngt-canvas']
2608
- }], pointerEvents: [{
2572
+ }], hbPointerEvents: [{
2609
2573
  type: HostBinding,
2610
2574
  args: ['style.pointerEvents']
2611
2575
  }], sceneGraph: [{
@@ -2678,7 +2642,7 @@ function injectNgtDestroy(cb) {
2678
2642
  function injectBeforeRender(cb, priority = 0) {
2679
2643
  try {
2680
2644
  const store = inject(NgtStore);
2681
- const sub = store.get('internal').subscribe((state) => cb(state), priority, store);
2645
+ const sub = store.get('internal').subscribe(cb, priority, store);
2682
2646
  injectNgtDestroy(() => void sub());
2683
2647
  return sub;
2684
2648
  }
@@ -2687,35 +2651,19 @@ function injectBeforeRender(cb, priority = 0) {
2687
2651
  }
2688
2652
  }
2689
2653
 
2690
- function safeDetectChanges(cdr) {
2691
- if (!cdr)
2692
- return;
2693
- try {
2694
- if (cdr['context']) {
2695
- cdr.detectChanges();
2696
- }
2697
- }
2698
- catch (e) {
2699
- cdr.markForCheck();
2700
- }
2701
- }
2702
-
2703
2654
  function injectNgtRef(initialValue = null) {
2704
2655
  const ref = is.ref(initialValue) ? initialValue : new ElementRef(initialValue);
2705
2656
  let lastValue = ref.nativeElement;
2706
2657
  const cdRefs = [];
2707
2658
  const ref$ = new BehaviorSubject(lastValue);
2708
- const { destroy$, cdr } = injectNgtDestroy(() => {
2709
- ref$.complete();
2710
- });
2659
+ const { destroy$, cdr } = injectNgtDestroy(() => void ref$.complete());
2711
2660
  cdRefs.push(cdr);
2712
2661
  const obs$ = ref$.asObservable().pipe(distinctUntilChanged(), takeUntil(destroy$));
2713
- const subscribe = (callback) => {
2714
- return obs$.subscribe((current) => {
2715
- callback(current, lastValue);
2716
- lastValue = current;
2717
- });
2718
- };
2662
+ const subscribe = (callback) => obs$.subscribe((current) => {
2663
+ callback(current, lastValue);
2664
+ lastValue = current;
2665
+ });
2666
+ const useCDR = (cdr) => void cdRefs.push(cdr);
2719
2667
  const $ = obs$.pipe(filter((value, index) => index > 0 || value != null), takeUntil(destroy$));
2720
2668
  const children$ = (type = 'objects') => $.pipe(switchMap((instance) => {
2721
2669
  const localState = getLocalState(instance);
@@ -2734,6 +2682,7 @@ function injectNgtRef(initialValue = null) {
2734
2682
  }
2735
2683
  return of([]);
2736
2684
  }), filter((children, index) => index > 0 || children.length > 0), takeUntil(destroy$));
2685
+ // here, we override nativeElement to add more functionalities to nativeElement
2737
2686
  Object.defineProperty(ref, 'nativeElement', {
2738
2687
  set: (newVal) => {
2739
2688
  if (ref.nativeElement !== newVal) {
@@ -2758,9 +2707,14 @@ function injectNgtRef(initialValue = null) {
2758
2707
  },
2759
2708
  get: () => ref$.value,
2760
2709
  });
2761
- return Object.assign(ref, { subscribe, $, children$, useCDR: (cdr) => void cdRefs.push(cdr) });
2710
+ return Object.assign(ref, { subscribe, $, children$, useCDR });
2762
2711
  }
2763
2712
 
2713
+ /**
2714
+ * Please use this sparringly and know what you're doing.
2715
+ *
2716
+ * Create a runInContext function that has access to the NodeInjector as well
2717
+ */
2764
2718
  function createRunInContext() {
2765
2719
  const nodeInjector = inject(Injector);
2766
2720
  const envInjector = inject(EnvironmentInjector);
@@ -2800,9 +2754,9 @@ class NgtRepeat extends NgForOf {
2800
2754
  this.ngForOf = Number.isInteger(count) ? Array.from({ length: count }, (_, i) => i) : [];
2801
2755
  }
2802
2756
  }
2803
- NgtRepeat.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgtRepeat, deps: null, target: i0.ɵɵFactoryTarget.Directive });
2804
- NgtRepeat.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.0", type: NgtRepeat, isStandalone: true, selector: "[ngFor][ngForRepeat]", inputs: { ngForRepeat: "ngForRepeat" }, usesInheritance: true, ngImport: i0 });
2805
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgtRepeat, decorators: [{
2757
+ NgtRepeat.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: NgtRepeat, deps: null, target: i0.ɵɵFactoryTarget.Directive });
2758
+ NgtRepeat.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.5", type: NgtRepeat, isStandalone: true, selector: "[ngFor][ngForRepeat]", inputs: { ngForRepeat: "ngForRepeat" }, usesInheritance: true, ngImport: i0 });
2759
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: NgtRepeat, decorators: [{
2806
2760
  type: Directive,
2807
2761
  args: [{ selector: '[ngFor][ngForRepeat]', standalone: true }]
2808
2762
  }], propDecorators: { ngForRepeat: [{
@@ -2817,50 +2771,43 @@ class NgtPush {
2817
2771
  constructor() {
2818
2772
  this.cdr = inject(ChangeDetectorRef);
2819
2773
  this.parentCdr = inject(ChangeDetectorRef, { skipSelf: true, optional: true });
2774
+ this.envCdr = inject(EnvironmentInjector).get(ChangeDetectorRef, null);
2820
2775
  }
2821
2776
  transform(value, defaultValue = null) {
2822
- if (this.obj === value) {
2777
+ if (this.obj === value)
2823
2778
  return this.latestValue;
2824
- }
2825
2779
  this.obj = value;
2826
2780
  this.latestValue = defaultValue;
2827
- if (this.sub) {
2781
+ if (this.sub)
2828
2782
  this.sub.unsubscribe();
2829
- }
2830
- if (isObservable(this.obj)) {
2783
+ if (isObservable(this.obj))
2831
2784
  this.sub = this.obj.subscribe(this.updateValue.bind(this));
2832
- }
2833
- else if (isPromise(this.obj)) {
2785
+ else if (isPromise(this.obj))
2834
2786
  this.obj.then(this.updateValue.bind(this));
2835
- }
2836
- else {
2787
+ else
2837
2788
  throw new Error(`[NGT] Invalid value passed to ngtPush pipe`);
2838
- }
2839
2789
  return this.latestValue;
2840
2790
  }
2841
2791
  updateValue(val) {
2842
2792
  this.latestValue = val;
2843
- this.cdr.detectChanges();
2844
- if (this.parentCdr) {
2845
- this.parentCdr.detectChanges();
2846
- }
2793
+ safeDetectChanges(this.cdr);
2794
+ safeDetectChanges(this.parentCdr);
2795
+ safeDetectChanges(this.envCdr);
2847
2796
  }
2848
2797
  ngOnDestroy() {
2849
- if (this.sub) {
2798
+ if (this.sub)
2850
2799
  this.sub.unsubscribe();
2851
- }
2852
2800
  this.latestValue = undefined;
2853
2801
  this.obj = undefined;
2854
2802
  }
2855
2803
  }
2856
- NgtPush.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgtPush, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
2857
- NgtPush.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "15.2.0", ngImport: i0, type: NgtPush, isStandalone: true, name: "ngtPush", pure: false });
2858
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgtPush, decorators: [{
2804
+ NgtPush.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: NgtPush, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
2805
+ NgtPush.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "15.2.5", ngImport: i0, type: NgtPush, isStandalone: true, name: "ngtPush", pure: false });
2806
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: NgtPush, decorators: [{
2859
2807
  type: Pipe,
2860
2808
  args: [{ name: 'ngtPush', pure: false, standalone: true }]
2861
2809
  }] });
2862
2810
 
2863
- var _NgtPortal_instances, _NgtPortal_inject;
2864
2811
  const privateKeys = [
2865
2812
  'get',
2866
2813
  'set',
@@ -2906,14 +2853,11 @@ class NgtPortalBeforeRender {
2906
2853
  (_a = this.subscription) === null || _a === void 0 ? void 0 : _a.call(this);
2907
2854
  }
2908
2855
  }
2909
- NgtPortalBeforeRender.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgtPortalBeforeRender, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2910
- NgtPortalBeforeRender.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.0", type: NgtPortalBeforeRender, isStandalone: true, selector: "ngt-portal-before-render", inputs: { renderPriority: "renderPriority", parentScene: "parentScene", parentCamera: "parentCamera" }, outputs: { beforeRender: "beforeRender" }, ngImport: i0 });
2911
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgtPortalBeforeRender, decorators: [{
2856
+ NgtPortalBeforeRender.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: NgtPortalBeforeRender, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2857
+ NgtPortalBeforeRender.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.5", type: NgtPortalBeforeRender, isStandalone: true, selector: "[ngtPortalBeforeRender]", inputs: { renderPriority: "renderPriority", parentScene: "parentScene", parentCamera: "parentCamera" }, outputs: { beforeRender: "beforeRender" }, ngImport: i0 });
2858
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: NgtPortalBeforeRender, decorators: [{
2912
2859
  type: Directive,
2913
- args: [{
2914
- selector: 'ngt-portal-before-render',
2915
- standalone: true,
2916
- }]
2860
+ args: [{ selector: '[ngtPortalBeforeRender]', standalone: true }]
2917
2861
  }], propDecorators: { renderPriority: [{
2918
2862
  type: Input
2919
2863
  }], parentScene: [{
@@ -2932,9 +2876,9 @@ class NgtPortalContent {
2932
2876
  }
2933
2877
  }
2934
2878
  }
2935
- NgtPortalContent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgtPortalContent, deps: [{ token: i0.ViewContainerRef }, { token: i0.ViewContainerRef, skipSelf: true }], target: i0.ɵɵFactoryTarget.Directive });
2936
- NgtPortalContent.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.0", type: NgtPortalContent, isStandalone: true, selector: "ng-template[ngtPortalContent]", ngImport: i0 });
2937
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgtPortalContent, decorators: [{
2879
+ NgtPortalContent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: NgtPortalContent, deps: [{ token: i0.ViewContainerRef }, { token: i0.ViewContainerRef, skipSelf: true }], target: i0.ɵɵFactoryTarget.Directive });
2880
+ NgtPortalContent.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.5", type: NgtPortalContent, isStandalone: true, selector: "ng-template[ngtPortalContent]", ngImport: i0 });
2881
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: NgtPortalContent, decorators: [{
2938
2882
  type: Directive,
2939
2883
  args: [{ selector: 'ng-template[ngtPortalContent]', standalone: true }]
2940
2884
  }], ctorParameters: function () {
@@ -2945,7 +2889,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.0", ngImpor
2945
2889
  class NgtPortal extends NgtRxStore {
2946
2890
  constructor() {
2947
2891
  super(...arguments);
2948
- _NgtPortal_instances.add(this);
2949
2892
  this.autoRender = true;
2950
2893
  this.autoRenderPriority = 1;
2951
2894
  this.beforeRender = new EventEmitter();
@@ -2981,9 +2924,9 @@ class NgtPortal extends NgtRxStore {
2981
2924
  localState.store = this.portalStore;
2982
2925
  }
2983
2926
  this.portalStore.set(Object.assign(Object.assign(Object.assign(Object.assign({}, previousState), { scene: container, raycaster: this.raycaster, pointer: this.pointer, previousStore: this.parentStore, events: Object.assign(Object.assign({}, previousState.events), (events || {})), size: Object.assign(Object.assign({}, previousState.size), (size || {})) }), restInputsState), { get: this.portalStore.get.bind(this.portalStore), set: this.portalStore.set.bind(this.portalStore), select: this.portalStore.select.bind(this.portalStore), setEvents: (events) => this.portalStore.set((state) => (Object.assign(Object.assign({}, state), { events: Object.assign(Object.assign({}, state.events), events) }))) }));
2984
- this.hold(this.parentStore.select(), (previous) => this.portalStore.set((state) => __classPrivateFieldGet(this, _NgtPortal_instances, "m", _NgtPortal_inject).call(this, previous, state)));
2927
+ this.hold(this.parentStore.select(), (previous) => this.portalStore.set((state) => this.inject(previous, state)));
2985
2928
  requestAnimationFrame(() => {
2986
- this.portalStore.set((injectState) => __classPrivateFieldGet(this, _NgtPortal_instances, "m", _NgtPortal_inject).call(this, this.parentStore.get(), injectState));
2929
+ this.portalStore.set((injectState) => this.inject(this.parentStore.get(), injectState));
2987
2930
  });
2988
2931
  this.portalContentView = this.portalContentAnchor.createEmbeddedView(this.portalContentTemplate);
2989
2932
  this.portalContentView.detectChanges();
@@ -3001,47 +2944,49 @@ class NgtPortal extends NgtRxStore {
3001
2944
  }
3002
2945
  super.ngOnDestroy();
3003
2946
  }
3004
- }
3005
- _NgtPortal_instances = new WeakSet(), _NgtPortal_inject = function _NgtPortal_inject(rootState, injectState) {
3006
- const intersect = Object.assign({}, rootState);
3007
- Object.keys(intersect).forEach((key) => {
3008
- if (privateKeys.includes(key) ||
3009
- rootState[key] !== injectState[key]) {
3010
- delete intersect[key];
2947
+ inject(rootState, injectState) {
2948
+ const intersect = Object.assign({}, rootState);
2949
+ Object.keys(intersect).forEach((key) => {
2950
+ if (privateKeys.includes(key) ||
2951
+ rootState[key] !== injectState[key]) {
2952
+ delete intersect[key];
2953
+ }
2954
+ });
2955
+ const inputs = this.get();
2956
+ const _a = inputs.state || {}, { size, events } = _a, restInputsState = __rest(_a, ["size", "events"]);
2957
+ let viewport = undefined;
2958
+ if (injectState && size) {
2959
+ const camera = injectState.camera;
2960
+ viewport = rootState.viewport.getCurrentViewport(camera, new THREE.Vector3(), size);
2961
+ if (camera !== rootState.camera)
2962
+ updateCamera(camera, size);
3011
2963
  }
3012
- });
3013
- const inputs = this.get();
3014
- const _a = inputs.state || {}, { size, events } = _a, restInputsState = __rest(_a, ["size", "events"]);
3015
- let viewport = undefined;
3016
- if (injectState && size) {
3017
- const camera = injectState.camera;
3018
- viewport = rootState.viewport.getCurrentViewport(camera, new THREE.Vector3(), size);
3019
- if (camera !== rootState.camera)
3020
- updateCamera(camera, size);
3021
- }
3022
- return Object.assign(Object.assign(Object.assign({}, intersect), { scene: is.ref(inputs.container) ? inputs.container.nativeElement : inputs.container, raycaster: this.raycaster, pointer: this.pointer, previousStore: this.parentStore, events: Object.assign(Object.assign(Object.assign({}, rootState.events), ((injectState === null || injectState === void 0 ? void 0 : injectState.events) || {})), events), size: Object.assign(Object.assign({}, rootState.size), size), viewport: Object.assign(Object.assign({}, rootState.viewport), (viewport || {})) }), restInputsState);
3023
- };
3024
- NgtPortal.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgtPortal, deps: null, target: i0.ɵɵFactoryTarget.Component });
3025
- NgtPortal.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.0", type: NgtPortal, isStandalone: true, selector: "ngt-portal", inputs: { container: "container", state: "state", autoRender: "autoRender", autoRenderPriority: "autoRenderPriority" }, outputs: { beforeRender: "beforeRender" }, providers: [NgtStore], queries: [{ propertyName: "portalContentTemplate", first: true, predicate: NgtPortalContent, descendants: true, read: TemplateRef, static: true }], viewQueries: [{ propertyName: "portalContentAnchor", first: true, predicate: ["portalContentAnchor"], descendants: true, read: ViewContainerRef, static: true }], usesInheritance: true, ngImport: i0, template: `
2964
+ return Object.assign(Object.assign(Object.assign({}, intersect), { scene: is.ref(inputs.container) ? inputs.container.nativeElement : inputs.container, raycaster: this.raycaster, pointer: this.pointer, previousStore: this.parentStore, events: Object.assign(Object.assign(Object.assign({}, rootState.events), ((injectState === null || injectState === void 0 ? void 0 : injectState.events) || {})), events), size: Object.assign(Object.assign({}, rootState.size), size), viewport: Object.assign(Object.assign({}, rootState.viewport), (viewport || {})) }), restInputsState);
2965
+ }
2966
+ }
2967
+ NgtPortal.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: NgtPortal, deps: null, target: i0.ɵɵFactoryTarget.Component });
2968
+ NgtPortal.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.5", type: NgtPortal, isStandalone: true, selector: "ngt-portal", inputs: { container: "container", state: "state", autoRender: "autoRender", autoRenderPriority: "autoRenderPriority" }, outputs: { beforeRender: "beforeRender" }, providers: [NgtStore], queries: [{ propertyName: "portalContentTemplate", first: true, predicate: NgtPortalContent, descendants: true, read: TemplateRef, static: true }], viewQueries: [{ propertyName: "portalContentAnchor", first: true, predicate: ["portalContentAnchor"], descendants: true, read: ViewContainerRef, static: true }], usesInheritance: true, ngImport: i0, template: `
3026
2969
  <ng-container #portalContentAnchor>
3027
- <ngt-portal-before-render
2970
+ <ng-container
3028
2971
  *ngIf="autoRender && portalContentRendered"
2972
+ ngtPortalBeforeRender
3029
2973
  [renderPriority]="autoRenderPriority"
3030
2974
  [parentScene]="parentScene"
3031
2975
  [parentCamera]="parentCamera"
3032
2976
  (beforeRender)="onBeforeRender($event)"
3033
2977
  />
3034
2978
  </ng-container>
3035
- `, isInline: true, dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgtPortalBeforeRender, selector: "ngt-portal-before-render", inputs: ["renderPriority", "parentScene", "parentCamera"], outputs: ["beforeRender"] }] });
3036
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgtPortal, decorators: [{
2979
+ `, isInline: true, dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgtPortalBeforeRender, selector: "[ngtPortalBeforeRender]", inputs: ["renderPriority", "parentScene", "parentCamera"], outputs: ["beforeRender"] }] });
2980
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: NgtPortal, decorators: [{
3037
2981
  type: Component,
3038
2982
  args: [{
3039
2983
  selector: 'ngt-portal',
3040
2984
  standalone: true,
3041
2985
  template: `
3042
2986
  <ng-container #portalContentAnchor>
3043
- <ngt-portal-before-render
2987
+ <ng-container
3044
2988
  *ngIf="autoRender && portalContentRendered"
2989
+ ngtPortalBeforeRender
3045
2990
  [renderPriority]="autoRenderPriority"
3046
2991
  [parentScene]="parentScene"
3047
2992
  [parentCamera]="parentCamera"
@@ -3075,13 +3020,13 @@ class NgtRoutedScene {
3075
3020
  const { destroy$, cdr } = injectNgtDestroy();
3076
3021
  router.events
3077
3022
  .pipe(filter((event) => event instanceof ActivationEnd), takeUntil(destroy$))
3078
- .subscribe(cdr.detectChanges.bind(cdr));
3023
+ .subscribe(() => safeDetectChanges(cdr));
3079
3024
  }
3080
3025
  }
3081
3026
  NgtRoutedScene.isRoutedScene = true;
3082
- NgtRoutedScene.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgtRoutedScene, deps: [{ token: i1.Router }], target: i0.ɵɵFactoryTarget.Component });
3083
- NgtRoutedScene.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.0", type: NgtRoutedScene, isStandalone: true, selector: "ngt-routed-scene", ngImport: i0, template: `<router-outlet />`, isInline: true, dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }] });
3084
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: NgtRoutedScene, decorators: [{
3027
+ NgtRoutedScene.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: NgtRoutedScene, deps: [{ token: i1.Router }], target: i0.ɵɵFactoryTarget.Component });
3028
+ NgtRoutedScene.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.5", type: NgtRoutedScene, isStandalone: true, selector: "ngt-routed-scene", ngImport: i0, template: `<router-outlet />`, isInline: true, dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }] });
3029
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: NgtRoutedScene, decorators: [{
3085
3030
  type: Component,
3086
3031
  args: [{
3087
3032
  standalone: true,