{"_rev":"3-37476e037784d283b3435a032c1d71a3","time":{"created":"2026-01-08T11:48:42.561Z","modified":"2026-01-08T11:48:43.415Z","1.0.0":"2026-01-08T10:20:32.385Z","1.0.1":"2026-01-08T11:48:42.851Z"},"_id":"@3lens/angular-bridge","name":"@3lens/angular-bridge","dist-tags":{"latest":"1.0.1"},"versions":{"1.0.1":{"name":"@3lens/angular-bridge","version":"1.0.1","description":"Angular integration for 3Lens - the three.js devtool","keywords":["three.js","threejs","angular","devtools","debugging"],"homepage":"https://github.com/adriandarian/3Lens","repository":{"type":"git","url":"git+https://github.com/adriandarian/3Lens.git","directory":"packages/angular-bridge"},"license":"MIT","author":{"name":"Adrian Darian","email":"adrian.the.hactus@gmail.com","url":"https://github.com/adriandarian"},"type":"module","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"main":"./dist/index.js","types":"./dist/index.d.ts","dependencies":{"@3lens/core":"1.0.1"},"devDependencies":{"@angular/core":"^17.0.0","rxjs":"^7.8.0","three":"^0.160.0","zone.js":"^0.14.0"},"peerDependencies":{"@angular/core":">=14.0.0","rxjs":">=7.0.0","three":">=0.150.0"},"scripts":{"build":"vite build","dev":"vite build --watch","typecheck":"tsc --noEmit","clean":"rm -rf dist"},"_id":"@3lens/angular-bridge@1.0.1","bugs":{"url":"https://github.com/adriandarian/3Lens/issues"},"_integrity":"sha512-vHhgnjO3Y+YNSEYYYF6vXZIC22/Wm+HxpDZuvd0/+QXcIpE6F30JIgYVLy3lFU8Av4aQb2rgqF5C+pJEMJaF4Q==","_resolved":"/tmp/3fec50f918462cb2aa4e1c1e060469bd/3lens-angular-bridge-1.0.1.tgz","_from":"file:3lens-angular-bridge-1.0.1.tgz","_nodeVersion":"20.19.6","_npmVersion":"10.8.2","dist":{"integrity":"sha512-vHhgnjO3Y+YNSEYYYF6vXZIC22/Wm+HxpDZuvd0/+QXcIpE6F30JIgYVLy3lFU8Av4aQb2rgqF5C+pJEMJaF4Q==","shasum":"e6e11c18110c77e3b055a05bc2b1b151e030d4e9","tarball":"https://registry.npmjs.org/@3lens/angular-bridge/-/angular-bridge-1.0.1.tgz","fileCount":15,"unpackedSize":115652,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@3lens%2fangular-bridge@1.0.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCatsvsSwtljBE0AgkQhagXnfEYlw7xCZN+B9EMNgVW7QIgNbDBtncN5vBQp1HJn2uPf8HTiYeoYiEEEfsTA9XyNVM="}]},"_npmUser":{"name":"adriandarian","email":"adrian.the.hactus@gmail.com"},"directories":{},"maintainers":[{"name":"adriandarian","email":"adrian.the.hactus@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/angular-bridge_1.0.1_1767872922691_0.7116384991381739"},"_hasShrinkwrap":false}},"maintainers":[{"name":"adriandarian","email":"adrian.the.hactus@gmail.com"}],"description":"Angular integration for 3Lens - the three.js devtool","homepage":"https://github.com/adriandarian/3Lens","keywords":["three.js","threejs","angular","devtools","debugging"],"repository":{"type":"git","url":"git+https://github.com/adriandarian/3Lens.git","directory":"packages/angular-bridge"},"author":{"name":"Adrian Darian","email":"adrian.the.hactus@gmail.com","url":"https://github.com/adriandarian"},"bugs":{"url":"https://github.com/adriandarian/3Lens/issues"},"license":"MIT","readme":"# @3lens/angular-bridge\n\nAngular integration for 3Lens - the three.js devtool.\n\n## Installation\n\n```bash\nnpm install @3lens/angular-bridge @3lens/core @3lens/overlay\n# or\npnpm add @3lens/angular-bridge @3lens/core @3lens/overlay\n```\n\n## Quick Start\n\n### Module-based Setup\n\n```typescript\nimport { NgModule } from '@angular/core';\nimport { ThreeLensModule } from '@3lens/angular-bridge';\n\n@NgModule({\n  imports: [\n    ThreeLensModule.forRoot({\n      appName: 'My Angular Three.js App',\n      debug: false,\n      showOverlay: true,\n    }),\n  ],\n})\nexport class AppModule {}\n```\n\n### Standalone Components Setup\n\n```typescript\nimport { bootstrapApplication } from '@angular/platform-browser';\nimport { provideThreeLens } from '@3lens/angular-bridge';\n\nbootstrapApplication(AppComponent, {\n  providers: [\n    provideThreeLens({ appName: 'My App' }),\n  ],\n});\n```\n\n### Using the Service\n\n```typescript\nimport { Component, OnInit, OnDestroy } from '@angular/core';\nimport { ThreeLensService } from '@3lens/angular-bridge';\nimport * as THREE from 'three';\n\n@Component({\n  selector: 'app-scene',\n  template: `\n    <div class=\"stats\">\n      <div>FPS: {{ fps$ | async | number:'1.0-0' }}</div>\n      <div>Draw Calls: {{ drawCalls$ | async }}</div>\n      <div>Triangles: {{ triangles$ | async | number }}</div>\n    </div>\n    <canvas #canvas></canvas>\n  `,\n})\nexport class SceneComponent implements OnInit, OnDestroy {\n  fps$ = this.threeLens.fps$;\n  drawCalls$ = this.threeLens.drawCalls$;\n  triangles$ = this.threeLens.triangles$;\n\n  private renderer!: THREE.WebGLRenderer;\n  private scene!: THREE.Scene;\n  private camera!: THREE.PerspectiveCamera;\n\n  constructor(private threeLens: ThreeLensService) {}\n\n  ngOnInit(): void {\n    // Set up Three.js\n    this.renderer = new THREE.WebGLRenderer();\n    this.scene = new THREE.Scene();\n    this.camera = new THREE.PerspectiveCamera(75, 1, 0.1, 1000);\n\n    // Connect 3Lens\n    this.threeLens.observeRenderer(this.renderer);\n    this.threeLens.observeScene(this.scene);\n\n    // Optional: Initialize helpers\n    this.threeLens.initializeTransformGizmo(\n      this.scene,\n      this.camera,\n      this.renderer.domElement,\n      THREE\n    );\n  }\n\n  ngOnDestroy(): void {\n    this.renderer.dispose();\n  }\n}\n```\n\n## Service API\n\n### Observables\n\n```typescript\n// Frame stats (updates every frame)\nframeStats$: Observable<FrameStats | null>\n\n// Convenience observables\nfps$: Observable<number>\ndrawCalls$: Observable<number>\ntriangles$: Observable<number>\nframeTime$: Observable<number>\ngpuMemory$: Observable<number>\n\n// Scene state\nsnapshot$: Observable<SceneSnapshot | null>\nselectedNode$: Observable<SceneNode | null>\nisReady$: Observable<boolean>\nisOverlayVisible$: Observable<boolean>\n```\n\n### Methods\n\n```typescript\n// Scene observation\nobserveRenderer(renderer: THREE.WebGLRenderer): void\nobserveScene(scene: THREE.Scene): void\n\n// Snapshots\ntakeSnapshot(): SceneSnapshot | null\n\n// Selection\nselectObject(uuid: string): void\nclearSelection(): void\nfocusOnSelected(): void\nflyToSelected(): void\n\n// Entity registration\nregisterEntity(object: THREE.Object3D, options?: EntityOptions): void\nunregisterEntity(object: THREE.Object3D): void\n\n// Overlay control\nshowOverlay(): void\nhideOverlay(): void\ntoggleOverlay(): void\n```\n\n## Entity Registration\n\nRegister Three.js objects with meaningful names and metadata:\n\n```typescript\n@Component({...})\nexport class PlayerComponent implements AfterViewInit {\n  private playerMesh!: THREE.Mesh;\n\n  constructor(private threeLens: ThreeLensService) {}\n\n  ngAfterViewInit(): void {\n    this.playerMesh = this.createPlayerMesh();\n\n    this.threeLens.registerEntity(this.playerMesh, {\n      name: 'Player',\n      module: 'game/entities',\n      metadata: {\n        health: 100,\n        level: 5,\n        class: 'Warrior',\n      },\n      tags: ['player', 'controllable', 'saveable'],\n    });\n  }\n\n  ngOnDestroy(): void {\n    this.threeLens.unregisterEntity(this.playerMesh);\n  }\n}\n```\n\n## Directive Usage\n\nFor declarative entity registration:\n\n```typescript\nimport { ThreeLensEntityDirective } from '@3lens/angular-bridge';\n\n@Component({\n  selector: 'app-enemy',\n  standalone: true,\n  imports: [ThreeLensEntityDirective],\n  template: `<ng-content></ng-content>`,\n})\nexport class EnemyComponent implements AfterViewInit {\n  @Input() enemyData: any;\n\n  mesh!: THREE.Mesh;\n\n  // Use programmatically with the directive's inputs\n  entityName = 'Enemy';\n  entityModule = 'game/enemies';\n  entityMetadata = { type: 'goblin' };\n}\n```\n\n## Nx Workspace Integration\n\nFor Nx monorepos, use the `NxLibraryHelper` to maintain consistent naming:\n\n```typescript\nimport { Injectable } from '@angular/core';\nimport { ThreeLensService, NxLibraryHelper } from '@3lens/angular-bridge';\n\n@Injectable({ providedIn: 'root' })\nexport class TerrainService {\n  private nxHelper: NxLibraryHelper;\n\n  constructor(private threeLens: ThreeLensService) {\n    this.nxHelper = new NxLibraryHelper(threeLens, {\n      name: 'feature-terrain',\n      scope: 'world',\n      type: 'feature',\n    });\n  }\n\n  createTerrain(): THREE.Mesh {\n    const terrain = new THREE.Mesh(/* ... */);\n\n    // Registers as @world/feature-terrain/MainTerrain\n    this.nxHelper.registerEntity(terrain, 'MainTerrain', {\n      metadata: { size: 1000, resolution: 256 },\n    });\n\n    return terrain;\n  }\n}\n```\n\n### Scoped Registration\n\nFor components with multiple parts:\n\n```typescript\nconst registerPart = this.nxHelper.createScopedRegistrar('Vehicle');\n\n// Registers as @game/feature-vehicles/Vehicle/Body\nregisterPart(bodyMesh, 'Body');\n\n// Registers as @game/feature-vehicles/Vehicle/Wheel_FL\nregisterPart(wheelFLMesh, 'Wheel_FL');\n```\n\n## Injection Tokens\n\nFor advanced use cases, inject the probe directly:\n\n```typescript\nimport { Inject } from '@angular/core';\nimport { THREELENS_PROBE, DevtoolProbe } from '@3lens/angular-bridge';\n\n@Component({...})\nexport class AdvancedComponent {\n  constructor(@Inject(THREELENS_PROBE) private probe: DevtoolProbe) {\n    // Direct probe access\n    const stats = probe.getLatestFrameStats();\n  }\n}\n```\n\n## TypeScript\n\nAll exports are fully typed:\n\n```typescript\nimport type {\n  ThreeLensModuleConfig,\n  EntityOptions,\n  NxLibraryOptions,\n  FrameStats,\n  SceneSnapshot,\n  SceneNode,\n} from '@3lens/angular-bridge';\n```\n\n## License\n\nMIT\n\n","readmeFilename":"README.md"}