vim-web 0.3.44-dev.3 → 0.3.44-dev.31

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 (43) hide show
  1. package/README.md +2 -2
  2. package/dist/style.css +9 -8
  3. package/dist/types/core-viewers/ultra/index.d.ts +1 -1
  4. package/dist/types/core-viewers/ultra/viewer/camera.d.ts +2 -1
  5. package/dist/types/core-viewers/ultra/viewer/inputs/{inputKeyboard.d.ts → keyboardHandler.d.ts} +1 -1
  6. package/dist/types/core-viewers/ultra/viewer/inputs/{inputMouse.d.ts → mouseHandler.d.ts} +7 -6
  7. package/dist/types/core-viewers/ultra/viewer/inputs/{InputTouch.d.ts → touchHandler.d.ts} +1 -1
  8. package/dist/types/core-viewers/ultra/viewer/marshal.d.ts +1 -1
  9. package/dist/types/core-viewers/ultra/viewer/sectionBox.d.ts +1 -0
  10. package/dist/types/core-viewers/ultra/viewer/selection.d.ts +3 -0
  11. package/dist/types/core-viewers/ultra/viewer/vim.d.ts +1 -1
  12. package/dist/types/core-viewers/webgl/loader/materials/viewerMaterials.d.ts +1 -1
  13. package/dist/types/core-viewers/webgl/viewer/gizmos/sectionBox/sectionBoxHandle.d.ts +2 -0
  14. package/dist/types/core-viewers/webgl/viewer/inputs/inputHandler.d.ts +1 -0
  15. package/dist/types/react-viewers/bim/bimPanel.d.ts +3 -3
  16. package/dist/types/react-viewers/bim/bimTree.d.ts +2 -2
  17. package/dist/types/react-viewers/controlbar/controlBar.d.ts +1 -0
  18. package/dist/types/react-viewers/controlbar/controlBarIds.d.ts +29 -0
  19. package/dist/types/react-viewers/helpers/{inputs.d.ts → componentInputs.d.ts} +2 -2
  20. package/dist/types/react-viewers/helpers/isolation.d.ts +2 -2
  21. package/dist/types/react-viewers/helpers/reactUtils.d.ts +39 -0
  22. package/dist/types/react-viewers/index.d.ts +4 -0
  23. package/dist/types/react-viewers/panels/axesPanel.d.ts +2 -2
  24. package/dist/types/react-viewers/panels/contextMenu.d.ts +2 -2
  25. package/dist/types/react-viewers/panels/icons.d.ts +1 -0
  26. package/dist/types/react-viewers/state/cameraState.d.ts +22 -0
  27. package/dist/types/react-viewers/state/controlBarState.d.ts +31 -33
  28. package/dist/types/react-viewers/state/sectionBoxState.d.ts +12 -14
  29. package/dist/types/react-viewers/ultra/errors/ultraErrors.d.ts +1 -1
  30. package/dist/types/react-viewers/ultra/index.d.ts +1 -0
  31. package/dist/types/react-viewers/ultra/ultraCameraState.d.ts +2 -0
  32. package/dist/types/react-viewers/ultra/ultraComponent.d.ts +1 -7
  33. package/dist/types/react-viewers/ultra/ultraComponentRef.d.ts +36 -0
  34. package/dist/types/react-viewers/ultra/ultraControlBarState.d.ts +14 -1
  35. package/dist/types/react-viewers/urls.d.ts +1 -0
  36. package/dist/types/react-viewers/webgl/webglCameraState.d.ts +2 -0
  37. package/dist/types/react-viewers/webgl/webglComponentRef.d.ts +7 -2
  38. package/dist/vim-web.iife.js +529 -396
  39. package/dist/vim-web.iife.js.map +1 -1
  40. package/dist/vim-web.js +529 -396
  41. package/dist/vim-web.js.map +1 -1
  42. package/package.json +1 -1
  43. package/dist/types/react-viewers/helpers/camera.d.ts +0 -37
package/dist/vim-web.js CHANGED
@@ -45819,7 +45819,7 @@ class ElementNoMapping {
45819
45819
  }
45820
45820
  }
45821
45821
  class ElementMapping {
45822
- constructor(instances, instanceToElement, elementIds2, instanceMeshes) {
45822
+ constructor(instances, instanceToElement, elementIds, instanceMeshes) {
45823
45823
  __publicField(this, "_instanceToElement");
45824
45824
  __publicField(this, "_instanceMeshes");
45825
45825
  __publicField(this, "_elementToInstances");
@@ -45832,17 +45832,17 @@ class ElementMapping {
45832
45832
  this._elementToInstances = ElementMapping.invertMap(
45833
45833
  this._instanceToElement
45834
45834
  );
45835
- this._elementIds = elementIds2;
45836
- this._elementIdToElements = ElementMapping.invertArray(elementIds2);
45835
+ this._elementIds = elementIds;
45836
+ this._elementIdToElements = ElementMapping.invertArray(elementIds);
45837
45837
  this._instanceMeshes = instanceMeshes;
45838
45838
  }
45839
45839
  static async fromG3d(g3d2, bim) {
45840
45840
  const instanceToElement = await bim.node.getAllElementIndex();
45841
- const elementIds2 = await bim.element.getAllId();
45841
+ const elementIds = await bim.element.getAllId();
45842
45842
  return new ElementMapping(
45843
45843
  Array.from(g3d2.instanceNodes),
45844
45844
  instanceToElement,
45845
- elementIds2,
45845
+ elementIds,
45846
45846
  g3d2.instanceMeshes
45847
45847
  );
45848
45848
  }
@@ -48858,14 +48858,14 @@ const _ViewerMaterials = class _ViewerMaterials {
48858
48858
  this._onUpdate.dispatch();
48859
48859
  }
48860
48860
  /**
48861
- * Size of the blur convolution on the selection outline effect.
48861
+ * Size of the blur convolution on the selection outline effect. Minimum 2.
48862
48862
  */
48863
48863
  get outlineBlur() {
48864
48864
  return this.outline.strokeBlur;
48865
48865
  }
48866
48866
  set outlineBlur(value) {
48867
48867
  if (this.outline.strokeBlur === value) return;
48868
- this.outline.strokeBlur = value;
48868
+ this.outline.strokeBlur = Math.max(value, 2);
48869
48869
  this._onUpdate.dispatch();
48870
48870
  }
48871
48871
  /**
@@ -50617,8 +50617,12 @@ class CameraMovement {
50617
50617
  }
50618
50618
  frameSphere(sphere, forward) {
50619
50619
  const direction = this.getNormalizedDirection(forward);
50620
- const fov2 = this._camera.camPerspective.camera.fov * Math.PI / 180;
50621
- const dist2 = sphere.radius * 1.2 / Math.tan(fov2 / 2);
50620
+ this._camera.frustrumSizeAt(sphere.center);
50621
+ const vFov = this._camera.camPerspective.camera.fov * Math.PI / 180;
50622
+ const vDist = sphere.radius * 1.2 / Math.tan(vFov / 2);
50623
+ const hFov = vFov * this._camera.camPerspective.camera.aspect;
50624
+ const hDist = sphere.radius * 1.2 / Math.tan(hFov / 2);
50625
+ const dist2 = Math.max(vDist, hDist);
50622
50626
  const safeDist = Math.max(dist2, this._camera.camPerspective.camera.near * 2);
50623
50627
  const pos = direction.multiplyScalar(-safeDist).add(sphere.center);
50624
50628
  this.set(pos, sphere.center);
@@ -50648,7 +50652,7 @@ class CameraLerp extends CameraMovement {
50648
50652
  }
50649
50653
  init(duration) {
50650
50654
  this.cancel();
50651
- this._duration = duration;
50655
+ this._duration = Math.max(duration, 0.01);
50652
50656
  this._clock.start();
50653
50657
  }
50654
50658
  cancel() {
@@ -50969,6 +50973,7 @@ let Camera$1 = class Camera2 {
50969
50973
  * @returns {CameraMovement} The camera movement api.
50970
50974
  */
50971
50975
  lerp(duration = 1, force = false) {
50976
+ if (duration <= 0) return this.snap(force);
50972
50977
  this.stop();
50973
50978
  this._force = force;
50974
50979
  this._lerp.init(duration);
@@ -51281,7 +51286,7 @@ const KEYS = {
51281
51286
  KEY_Z: 90
51282
51287
  };
51283
51288
  const KeySet = new Set(Object.values(KEYS));
51284
- class KeyboardHandler extends InputHandler$1 {
51289
+ let KeyboardHandler$1 = class KeyboardHandler extends InputHandler$1 {
51285
51290
  constructor() {
51286
51291
  super(...arguments);
51287
51292
  // Settings
@@ -51387,7 +51392,7 @@ class KeyboardHandler extends InputHandler$1 {
51387
51392
  this.camera.localVelocity = move;
51388
51393
  }
51389
51394
  }
51390
- }
51395
+ };
51391
51396
  class SimpleInstanceSubmesh {
51392
51397
  constructor(mesh, index2) {
51393
51398
  __publicField(this, "mesh");
@@ -51636,7 +51641,7 @@ class InputAction {
51636
51641
  return this.raycast.object;
51637
51642
  }
51638
51643
  }
51639
- class TouchHandler extends InputHandler$1 {
51644
+ let TouchHandler$1 = class TouchHandler extends InputHandler$1 {
51640
51645
  constructor(viewer) {
51641
51646
  super(viewer);
51642
51647
  __publicField(this, "TAP_DURATION_MS", 500);
@@ -51789,8 +51794,8 @@ class TouchHandler extends InputHandler$1 {
51789
51794
  average(p1, p2) {
51790
51795
  return p1.clone().lerp(p2, 0.5);
51791
51796
  }
51792
- }
51793
- class MouseHandler extends InputHandler$1 {
51797
+ };
51798
+ let MouseHandler$1 = class MouseHandler extends InputHandler$1 {
51794
51799
  constructor(viewer) {
51795
51800
  super(viewer);
51796
51801
  __publicField(this, "_idleDelayMs", 150);
@@ -51870,10 +51875,10 @@ class MouseHandler extends InputHandler$1 {
51870
51875
  });
51871
51876
  __publicField(this, "onMouseUp", (event) => {
51872
51877
  event.stopImmediatePropagation();
51878
+ event.preventDefault();
51873
51879
  const btn = this.getButton(event);
51874
51880
  if (btn === this._buttonDown) return;
51875
51881
  this._viewer.gizmos.rectangle.visible = false;
51876
- event.preventDefault();
51877
51882
  if (!this._buttonDown) return;
51878
51883
  if (this.inputs.pointerActive === "rect" && this._hasMouseMoved && !this._hasCameraMoved) {
51879
51884
  this.onRectEnd();
@@ -52042,7 +52047,7 @@ class MouseHandler extends InputHandler$1 {
52042
52047
  this.gizmoRect.setCorners(this._downPosition, this._lastPosition);
52043
52048
  }
52044
52049
  }
52045
- }
52050
+ };
52046
52051
  var dist = {};
52047
52052
  var SimpleEventDispatcher = {};
52048
52053
  var hasRequiredSimpleEventDispatcher;
@@ -52312,9 +52317,9 @@ class Input {
52312
52317
  this.touch.unregister();
52313
52318
  });
52314
52319
  this._viewer = viewer;
52315
- this.keyboard = new KeyboardHandler(viewer);
52316
- this.mouse = new MouseHandler(viewer);
52317
- this.touch = new TouchHandler(viewer);
52320
+ this.keyboard = new KeyboardHandler$1(viewer);
52321
+ this.mouse = new MouseHandler$1(viewer);
52322
+ this.touch = new TouchHandler$1(viewer);
52318
52323
  this._scheme = new DefaultInputScheme(viewer);
52319
52324
  this.pointerActive = viewer.settings.camera.controls.orbit ? "orbit" : "look";
52320
52325
  this._pointerFallback = viewer.settings.camera.controls.orbit ? "look" : "orbit";
@@ -54880,7 +54885,6 @@ class MeasureGizmo {
54880
54885
  * Disposes all resources.
54881
54886
  */
54882
54887
  dispose() {
54883
- console.log("dispose");
54884
54888
  if (this._animId !== void 0) cancelAnimationFrame(this._animId);
54885
54889
  this._html.div.remove();
54886
54890
  this._viewer.renderer.remove(this._group);
@@ -55453,6 +55457,7 @@ class SectionBoxHandle extends Mesh {
55453
55457
  __publicField(this, "_color");
55454
55458
  __publicField(this, "_highlightColor");
55455
55459
  __publicField(this, "_materials");
55460
+ __publicField(this, "_camera");
55456
55461
  __publicField(this, "_camSub");
55457
55462
  this._materials = [matAlways, matBehind];
55458
55463
  this._forward = new Vector3();
@@ -55465,15 +55470,18 @@ class SectionBoxHandle extends Mesh {
55465
55470
  this.quaternion.setFromUnitVectors(new Vector3(0, -1, 0), this._forward);
55466
55471
  }
55467
55472
  trackCamera(camera2) {
55468
- const rescale = () => {
55469
- const size = camera2.frustrumSizeAt(this.position);
55470
- this.scale.set(size.x * 3e-3, size.x * 3e-3, size.x * 3e-3);
55471
- };
55472
- this._camSub = camera2.onMoved.subscribe(() => rescale());
55473
- rescale();
55473
+ this._camera = camera2;
55474
+ this.update();
55475
+ this._camSub = camera2.onMoved.subscribe(() => this.update());
55476
+ }
55477
+ update() {
55478
+ if (!this._camera) return;
55479
+ const size = this._camera.frustrumSizeAt(this.position);
55480
+ this.scale.set(size.x * 3e-3, size.x * 3e-3, size.x * 3e-3);
55474
55481
  }
55475
55482
  setPosition(position) {
55476
55483
  this.position.copy(position);
55484
+ this.update();
55477
55485
  }
55478
55486
  get forward() {
55479
55487
  return this._forward;
@@ -57611,7 +57619,37 @@ function clamp$1(value, min2, max2) {
57611
57619
  }
57612
57620
  return Math.min(Math.max(value, min2), max2);
57613
57621
  }
57614
- class InputMouse extends InputHandler2 {
57622
+ class CaptureStateMachine {
57623
+ constructor(canvas) {
57624
+ __publicField(this, "_canvas");
57625
+ __publicField(this, "state");
57626
+ __publicField(this, "id");
57627
+ this._canvas = canvas;
57628
+ this.state = "none";
57629
+ this.id = -1;
57630
+ }
57631
+ onPointerDown(event) {
57632
+ if (this.state === "captured") {
57633
+ this._canvas.releasePointerCapture(this.id);
57634
+ }
57635
+ this.id = event.pointerId;
57636
+ this.state = "captured";
57637
+ }
57638
+ onPointerMove(event) {
57639
+ if (this.state === "capture") {
57640
+ this._canvas.setPointerCapture(this.id);
57641
+ this.state = "captured";
57642
+ }
57643
+ }
57644
+ onPointerUp(event) {
57645
+ if (this.state === "captured") {
57646
+ this._canvas.releasePointerCapture(this.id);
57647
+ this.state = "none";
57648
+ this.id = -1;
57649
+ }
57650
+ }
57651
+ }
57652
+ class MouseHandler2 extends InputHandler2 {
57615
57653
  constructor(canvas, rpc, selection, camera2) {
57616
57654
  super();
57617
57655
  __publicField(this, "_rpc");
@@ -57619,45 +57657,47 @@ class InputMouse extends InputHandler2 {
57619
57657
  __publicField(this, "_lastMouseDownPosition", new Vector2(0, 0));
57620
57658
  __publicField(this, "_selection");
57621
57659
  __publicField(this, "_camera");
57660
+ __publicField(this, "_capture");
57622
57661
  this._canvas = canvas;
57623
57662
  this._rpc = rpc;
57624
57663
  this._selection = selection;
57625
57664
  this._camera = camera2;
57665
+ this._capture = new CaptureStateMachine(canvas);
57626
57666
  }
57627
57667
  register() {
57628
57668
  this.reg(this._canvas, "pointerdown", (e) => {
57629
- this.handlePointerDown(e);
57669
+ this.onPointerDown(e);
57630
57670
  });
57631
57671
  this.reg(this._canvas, "pointerup", (e) => {
57632
- this.handlePointerUp(e);
57672
+ this.onPointerUp(e);
57633
57673
  });
57634
57674
  this.reg(this._canvas, "pointermove", (e) => {
57635
- this.handlePointerMove(e);
57675
+ this.onPointerMove(e);
57636
57676
  });
57637
57677
  this.reg(this._canvas, "wheel", (e) => {
57638
- this.handleMouseScroll(e);
57678
+ this.onMouseScroll(e);
57639
57679
  });
57640
57680
  this.reg(this._canvas, "dblclick", (e) => {
57641
- this.handleDoubleClick(e);
57681
+ this.onDoubleClick(e);
57642
57682
  });
57643
57683
  }
57644
57684
  dispose() {
57645
57685
  this.unregister();
57646
57686
  }
57647
- handlePointerDown(event) {
57687
+ onPointerDown(event) {
57648
57688
  if (event.pointerType !== "mouse") return;
57649
57689
  const pos = this.relativePosition(event);
57650
57690
  this._rpc.RPCMouseButtonEvent(pos, event.button, true);
57651
57691
  this._lastMouseDownPosition = pos;
57652
- this._canvas.setPointerCapture(event.pointerId);
57692
+ this._capture.onPointerDown(event);
57653
57693
  event.preventDefault();
57654
57694
  }
57655
- handlePointerUp(event) {
57695
+ onPointerUp(event) {
57656
57696
  if (event.pointerType !== "mouse") return;
57657
57697
  const pos = this.relativePosition(event);
57658
57698
  this._rpc.RPCMouseButtonEvent(pos, event.button, false);
57659
57699
  this.handleMouseClick(event);
57660
- this._canvas.releasePointerCapture(event.pointerId);
57700
+ this._capture.onPointerUp(event);
57661
57701
  event.preventDefault();
57662
57702
  }
57663
57703
  async handleMouseClick(event) {
@@ -57677,21 +57717,24 @@ class InputMouse extends InputHandler2 {
57677
57717
  this._selection.select(hit.vim, hit.nodeIndex);
57678
57718
  }
57679
57719
  }
57680
- handlePointerMove(event) {
57720
+ onPointerMove(event) {
57681
57721
  if (event.pointerType !== "mouse") return;
57682
57722
  this._canvas.focus();
57723
+ this._capture.onPointerMove(event);
57683
57724
  const pos = this.relativePosition(event);
57684
57725
  this._rpc.RPCMouseMoveEvent(pos);
57685
57726
  }
57686
- async handleDoubleClick(event) {
57727
+ async onDoubleClick(event) {
57687
57728
  const pos = this.relativePosition(event);
57688
57729
  const hit = await this._selection.hitTest(pos);
57689
57730
  if (hit) {
57690
57731
  this._camera.frameVim(hit.vim, [hit.nodeIndex], 1);
57732
+ } else {
57733
+ this._camera.frameAll(1);
57691
57734
  }
57692
57735
  event.preventDefault();
57693
57736
  }
57694
- handleMouseScroll(event) {
57737
+ onMouseScroll(event) {
57695
57738
  this._rpc.RPCMouseScrollEvent(Math.sign(event.deltaY));
57696
57739
  event.preventDefault();
57697
57740
  }
@@ -57703,7 +57746,7 @@ class InputMouse extends InputHandler2 {
57703
57746
  );
57704
57747
  }
57705
57748
  }
57706
- class InputTouch extends InputHandler2 {
57749
+ class TouchHandler2 extends InputHandler2 {
57707
57750
  constructor(canvas, rpc) {
57708
57751
  super();
57709
57752
  __publicField(this, "_rpc");
@@ -58000,7 +58043,7 @@ class Marshal {
58000
58043
  // -------------------- SectionBox -------------------
58001
58044
  writeSectionBoxState(data2) {
58002
58045
  this.writeBoolean(data2.visible);
58003
- this.writeBoolean(data2.interactible);
58046
+ this.writeBoolean(data2.interactive);
58004
58047
  this.writeBoolean(data2.clip);
58005
58048
  this.writeBox3(data2.box);
58006
58049
  }
@@ -58155,12 +58198,12 @@ class ReadMarshal {
58155
58198
  }
58156
58199
  readSectionBoxState() {
58157
58200
  const visible2 = this.readBoolean();
58158
- const interactible = this.readBoolean();
58201
+ const interactive = this.readBoolean();
58159
58202
  const clip = this.readBoolean();
58160
58203
  const box = this.readBox3();
58161
58204
  return {
58162
58205
  visible: visible2,
58163
- interactible,
58206
+ interactive,
58164
58207
  clip,
58165
58208
  box
58166
58209
  };
@@ -59632,7 +59675,7 @@ const serverKeys = /* @__PURE__ */ new Set([
59632
59675
  "Control",
59633
59676
  "Shift"
59634
59677
  ]);
59635
- class InputKeyboard extends InputHandler2 {
59678
+ class KeyboardHandler2 extends InputHandler2 {
59636
59679
  constructor(rpc, selection, camera2, inputs) {
59637
59680
  super();
59638
59681
  __publicField(this, "_rpc");
@@ -59671,15 +59714,19 @@ class InputKeyboard extends InputHandler2 {
59671
59714
  switch (event.key) {
59672
59715
  case "Escape":
59673
59716
  this._selection.clear();
59717
+ event.preventDefault();
59674
59718
  break;
59675
59719
  case "f":
59676
59720
  this.frameContext();
59721
+ event.preventDefault();
59677
59722
  break;
59678
59723
  case "Home":
59679
59724
  this._camera.restoreSavedPosition();
59725
+ event.preventDefault();
59680
59726
  break;
59681
59727
  case " ":
59682
59728
  this._inputs.mode = this._inputs.mode === InputMode.Orbit ? InputMode.Free : InputMode.Orbit;
59729
+ event.preventDefault();
59683
59730
  break;
59684
59731
  }
59685
59732
  }
@@ -59710,9 +59757,9 @@ class Inputs extends InputHandler2 {
59710
59757
  this._canvas = canvas;
59711
59758
  this._rpc = rpc;
59712
59759
  this._renderer = renderer;
59713
- this._inputsMouse = new InputMouse(this._canvas, this._rpc, selection, camera2);
59714
- this._inputsTouch = new InputTouch(this._canvas, this._rpc);
59715
- this._keyboard = new InputKeyboard(this._rpc, selection, camera2, this);
59760
+ this._inputsMouse = new MouseHandler2(this._canvas, this._rpc, selection, camera2);
59761
+ this._inputsTouch = new TouchHandler2(this._canvas, this._rpc);
59762
+ this._keyboard = new KeyboardHandler2(this._rpc, selection, camera2, this);
59716
59763
  }
59717
59764
  onConnect() {
59718
59765
  this.register();
@@ -60721,11 +60768,20 @@ class Vim2 {
60721
60768
  */
60722
60769
  removeHighlight(nodes, fallback) {
60723
60770
  const toUpdate = [];
60724
- for (const node of nodes) {
60725
- const state = this._nodeStates.get(node);
60726
- if (state === "highlighted") {
60727
- this._nodeStates.set(node, fallback);
60728
- toUpdate.push(node);
60771
+ if (nodes === "all") {
60772
+ for (const [node, state] of this._nodeStates.entries()) {
60773
+ if (state === "highlighted") {
60774
+ this._nodeStates.set(node, fallback);
60775
+ toUpdate.push(node);
60776
+ }
60777
+ }
60778
+ } else {
60779
+ for (const node of nodes) {
60780
+ const state = this._nodeStates.get(node);
60781
+ if (state === "highlighted") {
60782
+ this._nodeStates.set(node, fallback);
60783
+ toUpdate.push(node);
60784
+ }
60729
60785
  }
60730
60786
  }
60731
60787
  if (toUpdate.length > 0) {
@@ -60796,8 +60852,8 @@ class Vim2 {
60796
60852
  if (nodes === "all") {
60797
60853
  this._rpc.RPCClearMaterialOverrides(this._handle);
60798
60854
  } else {
60799
- const ids = new Array(nodes.length).fill(MaterialHandles.Invalid);
60800
- this._rpc.RPCSetMaterialOverrides(this._handle, nodes, ids);
60855
+ const ids2 = new Array(nodes.length).fill(MaterialHandles.Invalid);
60856
+ this._rpc.RPCSetMaterialOverrides(this._handle, nodes, ids2);
60801
60857
  }
60802
60858
  }
60803
60859
  updateMap(nodes, state) {
@@ -60958,7 +61014,6 @@ class Viewport2 {
60958
61014
  * Cleans up resources by removing resize observer and clearing timeouts
60959
61015
  */
60960
61016
  dispose() {
60961
- console.log("Disposing Viewport");
60962
61017
  this._clearTimeout();
60963
61018
  this._observer.disconnect();
60964
61019
  }
@@ -61219,11 +61274,15 @@ class Camera3 {
61219
61274
  * Handles camera initialization when connection is established
61220
61275
  */
61221
61276
  onConnect() {
61277
+ this.set(new Vector3(-1e3, 1e3, 1e3), new Vector3(0, 0, 0), 0);
61222
61278
  this.restoreLastPosition();
61223
61279
  }
61224
61280
  onCameraPose(pose) {
61225
61281
  this._lastPosition = pose;
61226
61282
  }
61283
+ set(position, target, blendTime = this._defaultBlendTime) {
61284
+ this._rpc.RPCSetCameraPosition(new Segment(position, target), blendTime);
61285
+ }
61227
61286
  /**
61228
61287
  * Pauses or resumes rendering
61229
61288
  * @param value - True to pause rendering, false to resume
@@ -61287,6 +61346,9 @@ class ViewerSelection {
61287
61346
  get onValueChanged() {
61288
61347
  return this._onValueChanged.asEvent();
61289
61348
  }
61349
+ get() {
61350
+ return this._selectedNodes;
61351
+ }
61290
61352
  /**
61291
61353
  * Gets the total number of selected nodes across all VIMs.
61292
61354
  * @returns The total count of selected nodes.
@@ -61322,7 +61384,7 @@ class ViewerSelection {
61322
61384
  * @param node - A single node index or array of node indices to select.
61323
61385
  */
61324
61386
  select(vim, node) {
61325
- this.clear();
61387
+ this._clear();
61326
61388
  this.add(vim, node);
61327
61389
  }
61328
61390
  /**
@@ -61397,6 +61459,12 @@ class ViewerSelection {
61397
61459
  * @param vim - Optional. If provided, only clears selections for the specified VIM.
61398
61460
  */
61399
61461
  clear(vim) {
61462
+ const changed = this._clear(vim);
61463
+ if (changed) {
61464
+ this._onValueChanged.dispatch();
61465
+ }
61466
+ }
61467
+ _clear(vim) {
61400
61468
  let changed = false;
61401
61469
  this._selectedNodes.forEach((nodes, v) => {
61402
61470
  if (vim === void 0 || v === vim) {
@@ -61405,9 +61473,7 @@ class ViewerSelection {
61405
61473
  }
61406
61474
  });
61407
61475
  this._selectedNodes.clear();
61408
- if (changed) {
61409
- this._onValueChanged.dispatch();
61410
- }
61476
+ return changed;
61411
61477
  }
61412
61478
  /**
61413
61479
  * Calculates the bounding box encompassing all selected nodes.
@@ -61429,8 +61495,7 @@ class ViewerSelection {
61429
61495
  * Should be called when the selection manager is no longer needed.
61430
61496
  */
61431
61497
  dispose() {
61432
- this.clear();
61433
- this._selectedNodes = /* @__PURE__ */ new Map();
61498
+ this._clear();
61434
61499
  }
61435
61500
  }
61436
61501
  class VimCollection {
@@ -61727,13 +61792,14 @@ class Renderer2 {
61727
61792
  }
61728
61793
  class SectionBox2 {
61729
61794
  constructor(rpc) {
61730
- __publicField(this, "_visible", true);
61731
- __publicField(this, "_interactible", true);
61732
- __publicField(this, "_clip", true);
61795
+ __publicField(this, "_visible", false);
61796
+ __publicField(this, "_interactible", false);
61797
+ __publicField(this, "_clip", false);
61733
61798
  __publicField(this, "_box", new Box3());
61734
61799
  __publicField(this, "_rpc");
61735
61800
  __publicField(this, "_interval");
61736
61801
  __publicField(this, "_animationFrame");
61802
+ __publicField(this, "_pullId", 0);
61737
61803
  // Signals
61738
61804
  __publicField(this, "_onUpdate", new distExports$1.SignalDispatcher());
61739
61805
  this._rpc = rpc;
@@ -61750,6 +61816,7 @@ class SectionBox2 {
61750
61816
  this._interval = setInterval(() => this.pull(), 1e3);
61751
61817
  }
61752
61818
  scheduleUpdate() {
61819
+ this._pullId++;
61753
61820
  if (this._animationFrame) return;
61754
61821
  this._animationFrame = requestAnimationFrame(() => {
61755
61822
  this._animationFrame = void 0;
@@ -61758,13 +61825,15 @@ class SectionBox2 {
61758
61825
  }
61759
61826
  async pull() {
61760
61827
  if (this.needUpdate) return;
61828
+ const id2 = this._pullId;
61761
61829
  const state = await this._rpc.RPCGetSectionBox();
61830
+ if (id2 !== this._pullId) return;
61762
61831
  let changed = false;
61763
- if (state.visible !== this._visible || state.interactible !== this._interactible || state.clip !== this._clip || state.box !== this._box) {
61832
+ if (state.visible !== this._visible || state.interactive !== this._interactible || state.clip !== this._clip || state.box !== this._box) {
61764
61833
  changed = true;
61765
61834
  }
61766
61835
  this._visible = state.visible;
61767
- this._interactible = state.interactible;
61836
+ this._interactible = state.interactive;
61768
61837
  this._clip = state.clip;
61769
61838
  this._box = state.box;
61770
61839
  if (changed) {
@@ -61774,7 +61843,7 @@ class SectionBox2 {
61774
61843
  async push() {
61775
61844
  await this._rpc.RPCSetSectionBox({
61776
61845
  visible: this._visible,
61777
- interactible: this._interactible,
61846
+ interactive: this._interactible,
61778
61847
  clip: this._clip,
61779
61848
  box: this._box
61780
61849
  });
@@ -66801,6 +66870,25 @@ function hidden({ height, width, fill: fill2, className = "" }) {
66801
66870
  }
66802
66871
  );
66803
66872
  }
66873
+ function autoCamera({ height, width, fill: fill2 = "", className }) {
66874
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { className, height, width, viewBox: "0 0 256 256", children: [
66875
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { fill: "none", d: "M0 0h256v256H0z" }),
66876
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
66877
+ "path",
66878
+ {
66879
+ fill: fill2,
66880
+ d: "M 242.35934,69.720521 V 192.19034 c 0,9.46501 -7.97359,15.37204 -14.35248,10.67406 l -39.68884,-29.41993 v 8.38267 c 0,25.1595 -15.90243,45.64407 -35.51391,45.64407 H 48.520099 C 28.90861,227.51727 13.006195,206.98664 13.006195,181.80411 V 80.187338 c 0,-25.159506 15.902415,-45.644066 35.513904,-45.644066 H 152.55325 c 19.57566,0 35.51392,20.4385 35.51392,45.644066 v 8.382665 L 227.756,59.150074 c 6.33409,-4.801607 14.60334,1.162981 14.60334,10.570447 z"
66881
+ }
66882
+ ),
66883
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
66884
+ "path",
66885
+ {
66886
+ fill: "white",
66887
+ d: "m 134.24221,179.28573 -6.38,-16.771 H 73.539201 l -6.38,17.135 c -2.492,6.684 -4.618,11.211 -6.38,13.581 -1.763,2.309 -4.649,3.464 -8.659,3.464 -3.403,0 -6.411,-1.246 -9.024,-3.737 -2.613,-2.492 -3.919,-5.317 -3.919,-8.477 0,-1.823 0.304,-3.706 0.911,-5.651 0.608,-1.944 1.611,-4.648 3.008,-8.112 l 34.18,-86.771005 c 0.972,-2.491 2.127,-5.469 3.463,-8.932 1.398,-3.525 2.856,-6.441 4.375,-8.75 1.58,-2.309 3.616,-4.163 6.107,-5.56 2.552005,-1.458 5.682005,-2.188 9.388009,-2.188 3.768,0 6.897,0.73 9.388,2.188 2.552,1.397 4.588,3.22 6.107,5.469 1.58,2.248 2.886,4.678 3.919,7.291 1.094,2.552 2.461,5.986 4.102,10.3 l 34.909,86.224005 c 2.734,6.562 4.101,11.332 4.101,14.31 0,3.099 -1.306,5.955 -3.919,8.568 -2.552,2.552 -5.651,3.828 -9.297,3.828 -2.126,0 -3.949,-0.395 -5.468,-1.185 -1.52,-0.729 -2.796,-1.732 -3.829,-3.008 -1.033,-1.337 -2.157,-3.342 -3.372,-6.016 -1.155,-2.734 -2.157,-5.134 -3.008,-7.2 z m -53.594009,-37.097 h 39.922009 l -20.143,-55.143005 z"
66888
+ }
66889
+ )
66890
+ ] });
66891
+ }
66804
66892
  function orbit({ height, width, fill: fill2 = "", className }) {
66805
66893
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { className, height, width, viewBox: "0 0 256 256", children: [
66806
66894
  /* @__PURE__ */ jsxRuntimeExports.jsx("path", { fill: "none", d: "M0 0h256v256H0z" }),
@@ -67324,6 +67412,7 @@ function ghostDead({ height, width, fill: fill2, className }) {
67324
67412
  const icons = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
67325
67413
  __proto__: null,
67326
67414
  arrowLeft,
67415
+ autoCamera,
67327
67416
  camera,
67328
67417
  checkmark,
67329
67418
  close,
@@ -67470,7 +67559,7 @@ function AxesPanel(props) {
67470
67559
  );
67471
67560
  };
67472
67561
  const onHomeBtn = () => {
67473
- props.camera.reset();
67562
+ props.camera.reset.call();
67474
67563
  };
67475
67564
  const btnStyle2 = "vim-axes-button vc-flex vc-items-center vc-justify-center vc-text-gray-medium vc-transition-all hover:vc-text-primary-royal";
67476
67565
  const btnIsolation = /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -67561,6 +67650,41 @@ function createSection$1(section) {
67561
67650
  if (section.enable !== void 0 && !section.enable()) return null;
67562
67651
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `vim-control-bar-section ${section.style ?? sectionDefaultStyle}`, children: section.buttons.map((b) => createButton(b)) }, section.id);
67563
67652
  }
67653
+ const ids = {
67654
+ // Sections
67655
+ sectionCamera: "controlBar.sectionCamera",
67656
+ sectionInputs: "controlBar.sectionInputs",
67657
+ sectionActions: "controlBar.sectionActions",
67658
+ sectionTools: "controlBar.sectionTools",
67659
+ sectionSettings: "controlBar.sectionSettings",
67660
+ sectionMeasure: "controlBar.sectionMeasure",
67661
+ sectionSectionBox: "controlBar.sectionSectionBox",
67662
+ // Camera buttons
67663
+ buttonCameraAuto: "controlBar.camera.auto",
67664
+ buttonCameraOrbit: "controlBar.camera.orbit",
67665
+ buttonCameraLook: "controlBarcamera.look",
67666
+ buttonCameraPan: "controlBar.camera.pan",
67667
+ buttonCameraZoom: "controlBar.camera.zoom",
67668
+ buttonCameraZoomWindow: "controlBar.camera.zoomWindow",
67669
+ // Settings buttons
67670
+ buttonProjectInspector: "controlBar.projectInspector",
67671
+ buttonSettings: "controlBar.settings",
67672
+ buttonHelp: "controlBar.help",
67673
+ buttonMaximize: "controlBar.maximize",
67674
+ // Action Buttons
67675
+ buttonToggleIsolation: "controlBar.action.toggleIsolation",
67676
+ buttonZoomToFit: "controlBar.action.zoomToFit",
67677
+ // Tools buttons
67678
+ buttonSectionBox: "controlBar.sectionBox",
67679
+ buttonMeasure: "controlBar.measure",
67680
+ // Section box buttons
67681
+ buttonSectionBoxEnable: "controlBar.sectionBox.enable",
67682
+ buttonSectionBoxVisible: "controlBar.sectionBox.visible",
67683
+ buttonSectionBoxShrinkToSelection: "controlBar.sectionBox.shrinkToSelection",
67684
+ buttonSectionBoxAuto: "controlBar.sectionBox.auto",
67685
+ buttonSectionBoxReset: "controlBar.sectionBox.reset",
67686
+ buttonSectionBoxSettings: "controlBar.sectionBox.settings"
67687
+ };
67564
67688
  function ControlBar(props) {
67565
67689
  useEffect(() => {
67566
67690
  ReactTooltip.rebuild();
@@ -67590,6 +67714,7 @@ const controlBar = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePr
67590
67714
  buttonExpandStyle,
67591
67715
  createButton,
67592
67716
  createSection: createSection$1,
67717
+ ids,
67593
67718
  sectionBlueStyle,
67594
67719
  sectionDefaultStyle,
67595
67720
  sectionNoPadStyle
@@ -67775,95 +67900,62 @@ function getMeasureState(viewer, cursor) {
67775
67900
  clear
67776
67901
  };
67777
67902
  }
67778
- const elementIds = {
67779
- // Sections
67780
- sectionCamera: "controlBar.sectionCamera",
67781
- sectionActions: "controlBar.sectionActions",
67782
- sectionTools: "controlBar.sectionTools",
67783
- sectionSettings: "controlBar.sectionSettings",
67784
- sectionMeasure: "controlBar.sectionMeasure",
67785
- sectionSectionBox: "controlBar.sectionSectionBox",
67786
- // Camera buttons
67787
- buttonCameraOrbit: "controlBar.camera.orbit",
67788
- buttonCameraLook: "controlBarcamera.look",
67789
- buttonCameraPan: "controlBar.camera.pan",
67790
- buttonCameraZoom: "controlBar.camera.zoom",
67791
- buttonCameraZoomWindow: "controlBar.camera.zoomWindow",
67792
- // Settings buttons
67793
- buttonProjectInspector: "controlBar.projectInspector",
67794
- buttonSettings: "controlBar.settings",
67795
- buttonHelp: "controlBar.help",
67796
- buttonMaximize: "controlBar.maximize",
67797
- // Action Buttons
67798
- buttonToggleIsolation: "controlBar.action.toggleIsolation",
67799
- buttonZoomToFit: "controlBar.action.zoomToFit",
67800
- // Tools buttons
67801
- buttonSectionBox: "controlBar.sectionBox",
67802
- buttonMeasure: "controlBar.measure",
67803
- // Section box buttons
67804
- buttonSectionBoxEnable: "controlBar.sectionBox.enable",
67805
- buttonSectionBoxVisible: "controlBar.sectionBox.visible",
67806
- buttonSectionBoxShrinkToSelection: "controlBar.sectionBox.shrinkToSelection",
67807
- buttonSectionBoxAuto: "controlBar.sectionBox.auto",
67808
- buttonSectionBoxClip: "controlBar.sectionBox.clip",
67809
- buttonSectionBoxSettings: "controlBar.sectionBox.settings"
67810
- };
67811
67903
  function controlBarSectionBox(section, hasSelection) {
67812
67904
  return {
67813
- id: elementIds.sectionSectionBox,
67814
- style: section.getEnable() ? sectionNoPadStyle : sectionDefaultStyle,
67905
+ id: ids.sectionSectionBox,
67906
+ style: section.enable.get() ? sectionNoPadStyle : sectionDefaultStyle,
67815
67907
  //enable: () => section.getEnable(),
67816
67908
  buttons: [
67817
67909
  {
67818
- id: elementIds.buttonSectionBoxEnable,
67910
+ id: ids.buttonSectionBoxEnable,
67819
67911
  tip: "Enable Section Box",
67820
- isOn: () => section.getEnable(),
67912
+ isOn: () => section.enable.get(),
67821
67913
  style: (on) => buttonExpandStyle(on),
67822
- action: () => section.setEnable(!section.getEnable()),
67914
+ action: () => section.enable.set(!section.enable.get()),
67823
67915
  icon: sectionBox
67824
67916
  },
67825
67917
  {
67826
- id: elementIds.buttonSectionBoxShrinkToSelection,
67918
+ id: ids.buttonSectionBoxShrinkToSelection,
67827
67919
  tip: "Fit Section",
67828
- enabled: () => section.getEnable(),
67920
+ enabled: () => section.enable.get(),
67829
67921
  isOn: () => hasSelection,
67830
67922
  style: (on) => buttonDisableStyle(on),
67831
- action: () => section.sectionSelection(),
67923
+ action: () => section.sectionSelection.call(),
67832
67924
  icon: sectionBoxShrink
67833
67925
  },
67834
67926
  {
67835
- id: elementIds.buttonSectionBoxClip,
67927
+ id: ids.buttonSectionBoxReset,
67836
67928
  tip: "Reset Section",
67837
- enabled: () => section.getEnable(),
67929
+ enabled: () => section.enable.get(),
67838
67930
  style: (on) => buttonDefaultStyle(on),
67839
- action: () => section.sectionReset(),
67931
+ action: () => section.sectionReset.call(),
67840
67932
  icon: sectionBoxReset
67841
67933
  },
67842
67934
  {
67843
- id: elementIds.buttonSectionBoxVisible,
67935
+ id: ids.buttonSectionBoxVisible,
67844
67936
  tip: "Show Section Box",
67845
- enabled: () => section.getEnable(),
67846
- isOn: () => section.getVisible(),
67937
+ enabled: () => section.enable.get(),
67938
+ isOn: () => section.visible.get(),
67847
67939
  style: (on) => buttonDefaultStyle(on),
67848
- action: () => section.setVisible(!section.getVisible()),
67940
+ action: () => section.visible.set(!section.visible.get()),
67849
67941
  icon: visible
67850
67942
  },
67851
67943
  {
67852
- id: elementIds.buttonSectionBoxAuto,
67944
+ id: ids.buttonSectionBoxAuto,
67853
67945
  tip: "Auto Section",
67854
- enabled: () => section.getEnable(),
67855
- isOn: () => section.getAuto(),
67946
+ enabled: () => section.enable.get(),
67947
+ isOn: () => section.auto.get(),
67856
67948
  style: (on) => buttonDefaultStyle(on),
67857
- action: () => section.setAuto(!section.getAuto()),
67949
+ action: () => section.auto.set(!section.auto.get()),
67858
67950
  icon: sectionBoxAuto
67859
67951
  },
67860
67952
  {
67861
- id: elementIds.buttonSectionBoxSettings,
67953
+ id: ids.buttonSectionBoxSettings,
67862
67954
  tip: "Section Settings",
67863
- enabled: () => section.getEnable(),
67864
- isOn: () => section.getOffsetVisible(),
67955
+ enabled: () => section.enable.get(),
67956
+ isOn: () => section.showOffsetPanel.get(),
67865
67957
  style: (on) => buttonDefaultStyle(on),
67866
- action: () => section.setOffsetsVisible(!section.getOffsetVisible()),
67958
+ action: () => section.showOffsetPanel.set(!section.showOffsetPanel.get()),
67867
67959
  icon: slidersHoriz
67868
67960
  }
67869
67961
  ]
@@ -67872,12 +67964,12 @@ function controlBarSectionBox(section, hasSelection) {
67872
67964
  function controlBarPointer(viewer, camera2, settings2, section) {
67873
67965
  const pointer = getPointerState(viewer);
67874
67966
  return {
67875
- id: elementIds.sectionCamera,
67967
+ id: ids.sectionInputs,
67876
67968
  enable: () => anyUiCursorButton(settings2),
67877
67969
  style: sectionDefaultStyle,
67878
67970
  buttons: [
67879
67971
  {
67880
- id: elementIds.buttonCameraOrbit,
67972
+ id: ids.buttonCameraOrbit,
67881
67973
  enabled: () => isTrue(settings2.ui.orbit),
67882
67974
  tip: "Orbit",
67883
67975
  action: () => pointer.onButton("orbit"),
@@ -67886,7 +67978,7 @@ function controlBarPointer(viewer, camera2, settings2, section) {
67886
67978
  style: buttonDefaultStyle
67887
67979
  },
67888
67980
  {
67889
- id: elementIds.buttonCameraLook,
67981
+ id: ids.buttonCameraLook,
67890
67982
  enabled: () => isTrue(settings2.ui.lookAround),
67891
67983
  tip: "Look Around",
67892
67984
  action: () => pointer.onButton("look"),
@@ -67895,7 +67987,7 @@ function controlBarPointer(viewer, camera2, settings2, section) {
67895
67987
  style: buttonDefaultStyle
67896
67988
  },
67897
67989
  {
67898
- id: elementIds.buttonCameraPan,
67990
+ id: ids.buttonCameraPan,
67899
67991
  enabled: () => isTrue(settings2.ui.pan),
67900
67992
  tip: "Pan",
67901
67993
  action: () => pointer.onButton("pan"),
@@ -67904,7 +67996,7 @@ function controlBarPointer(viewer, camera2, settings2, section) {
67904
67996
  style: buttonDefaultStyle
67905
67997
  },
67906
67998
  {
67907
- id: elementIds.buttonCameraZoom,
67999
+ id: ids.buttonCameraZoom,
67908
68000
  enabled: () => isTrue(settings2.ui.zoom),
67909
68001
  tip: "Zoom",
67910
68002
  action: () => pointer.onButton("zoom"),
@@ -67913,7 +68005,7 @@ function controlBarPointer(viewer, camera2, settings2, section) {
67913
68005
  style: buttonDefaultStyle
67914
68006
  },
67915
68007
  {
67916
- id: elementIds.buttonCameraZoomWindow,
68008
+ id: ids.buttonCameraZoomWindow,
67917
68009
  enabled: () => isTrue(settings2.ui.zoomWindow),
67918
68010
  tip: "Zoom Window",
67919
68011
  action: () => {
@@ -67928,21 +68020,21 @@ function controlBarPointer(viewer, camera2, settings2, section) {
67928
68020
  }
67929
68021
  function controlBarActions(camera2, settings2, isolation, measure$1) {
67930
68022
  return {
67931
- id: elementIds.sectionActions,
68023
+ id: ids.sectionActions,
67932
68024
  enable: () => true,
67933
68025
  style: sectionDefaultStyle,
67934
68026
  buttons: [
67935
68027
  {
67936
- id: elementIds.buttonZoomToFit,
68028
+ id: ids.buttonZoomToFit,
67937
68029
  enabled: () => isTrue(settings2.ui.zoomToFit),
67938
68030
  tip: "Zoom to Fit",
67939
- action: () => camera2.frameContext(),
68031
+ action: () => camera2.frameSelection.call(),
67940
68032
  icon: frameSelection,
67941
68033
  isOn: () => false,
67942
68034
  style: buttonDefaultStyle
67943
68035
  },
67944
68036
  {
67945
- id: elementIds.buttonToggleIsolation,
68037
+ id: ids.buttonToggleIsolation,
67946
68038
  enabled: () => isTrue(settings2.ui.toggleIsolation),
67947
68039
  tip: "Toggle Isolation",
67948
68040
  action: () => isolation.toggle("controlBar"),
@@ -67950,7 +68042,7 @@ function controlBarActions(camera2, settings2, isolation, measure$1) {
67950
68042
  style: buttonDefaultStyle
67951
68043
  },
67952
68044
  {
67953
- id: elementIds.buttonMeasure,
68045
+ id: ids.buttonMeasure,
67954
68046
  enabled: () => isTrue(settings2.ui.measuringMode),
67955
68047
  isOn: () => measure$1.active,
67956
68048
  tip: "Measuring Mode",
@@ -67964,12 +68056,12 @@ function controlBarActions(camera2, settings2, isolation, measure$1) {
67964
68056
  function controlBarSettings(modal, side, settings$1) {
67965
68057
  const fullScreen = getFullScreenState();
67966
68058
  return {
67967
- id: elementIds.sectionSettings,
68059
+ id: ids.sectionSettings,
67968
68060
  enable: () => anyUiSettingButton(settings$1),
67969
68061
  style: sectionDefaultStyle,
67970
68062
  buttons: [
67971
68063
  {
67972
- id: elementIds.buttonProjectInspector,
68064
+ id: ids.buttonProjectInspector,
67973
68065
  enabled: () => isTrue(settings$1.ui.projectInspector) && (isTrue(settings$1.ui.bimTreePanel) || isTrue(settings$1.ui.bimInfoPanel)),
67974
68066
  tip: "Project Inspector",
67975
68067
  action: () => side.toggleContent("bim"),
@@ -67977,7 +68069,7 @@ function controlBarSettings(modal, side, settings$1) {
67977
68069
  style: buttonDefaultStyle
67978
68070
  },
67979
68071
  {
67980
- id: elementIds.buttonSettings,
68072
+ id: ids.buttonSettings,
67981
68073
  enabled: () => isTrue(settings$1.ui.settings),
67982
68074
  tip: "Settings",
67983
68075
  action: () => side.toggleContent("settings"),
@@ -67985,7 +68077,7 @@ function controlBarSettings(modal, side, settings$1) {
67985
68077
  style: buttonDefaultStyle
67986
68078
  },
67987
68079
  {
67988
- id: elementIds.buttonHelp,
68080
+ id: ids.buttonHelp,
67989
68081
  enabled: () => isTrue(settings$1.ui.help),
67990
68082
  tip: "Help",
67991
68083
  action: () => modal.help(true),
@@ -67993,7 +68085,7 @@ function controlBarSettings(modal, side, settings$1) {
67993
68085
  style: buttonDefaultStyle
67994
68086
  },
67995
68087
  {
67996
- id: elementIds.buttonMaximize,
68088
+ id: ids.buttonMaximize,
67997
68089
  enabled: () => isTrue(settings$1.ui.maximise) && settings$1.capacity.canGoFullScreen,
67998
68090
  tip: fullScreen.get() ? "Minimize" : "Fullscreen",
67999
68091
  action: () => fullScreen.toggle(),
@@ -68003,15 +68095,34 @@ function controlBarSettings(modal, side, settings$1) {
68003
68095
  ]
68004
68096
  };
68005
68097
  }
68098
+ function controlBarCamera(camera2) {
68099
+ return {
68100
+ id: ids.sectionCamera,
68101
+ enable: () => true,
68102
+ style: sectionDefaultStyle,
68103
+ buttons: [
68104
+ {
68105
+ id: ids.buttonCameraAuto,
68106
+ tip: "Auto Camera",
68107
+ isOn: () => camera2.autoCamera.get(),
68108
+ action: () => camera2.autoCamera.set(!camera2.autoCamera.get()),
68109
+ icon: autoCamera,
68110
+ style: buttonDefaultStyle
68111
+ }
68112
+ ]
68113
+ };
68114
+ }
68006
68115
  function useControlBar(viewer, camera2, modal, side, isolation, cursor, settings2, section, customization) {
68007
68116
  const measure2 = getMeasureState(viewer, cursor);
68008
68117
  const pointerSection = controlBarPointer(viewer, camera2, settings2);
68009
68118
  const actionSection = controlBarActions(camera2, settings2, isolation, measure2);
68010
68119
  const sectionBoxSection = controlBarSectionBox(section, viewer.selection.count > 0);
68011
68120
  const settingsSection = controlBarSettings(modal, side, settings2);
68121
+ const cameraSection = controlBarCamera(camera2);
68012
68122
  let controlBarSections = [
68013
68123
  pointerSection,
68014
68124
  actionSection,
68125
+ cameraSection,
68015
68126
  sectionBoxSection,
68016
68127
  // Optional section
68017
68128
  settingsSection
@@ -72006,42 +72117,21 @@ function VimContextMenu(props) {
72006
72117
  };
72007
72118
  const viewer = props.viewer;
72008
72119
  const camera2 = props.camera;
72009
- const [section, setSection] = useState({
72010
- visible: viewer.gizmos.sectionBox.visible,
72011
- clip: viewer.gizmos.sectionBox.clip
72012
- });
72013
- const isClipping = () => {
72014
- return !viewer.gizmos.sectionBox.box.containsBox(viewer.renderer.getBoundingBox());
72015
- };
72016
- const [clipping, setClipping] = useState(isClipping());
72017
72120
  const [, setVersion] = useState(0);
72018
72121
  const hidden2 = props.isolation.isActive();
72019
72122
  useEffect(() => {
72020
- const subState = viewer.gizmos.sectionBox.onStateChanged.subscribe(() => {
72021
- setSection({
72022
- visible: viewer.gizmos.sectionBox.visible,
72023
- clip: viewer.gizmos.sectionBox.clip
72024
- });
72025
- });
72026
- const subConfirm = viewer.gizmos.sectionBox.onBoxConfirm.subscribe(
72027
- () => setClipping(isClipping())
72028
- );
72029
72123
  props.isolation.onChanged.subscribe(() => setVersion((v) => v + 1));
72030
- return () => {
72031
- subState();
72032
- subConfirm();
72033
- };
72034
72124
  }, []);
72035
72125
  const onShowControlsBtn = (e) => {
72036
72126
  props.modal.help(true);
72037
72127
  e.stopPropagation();
72038
72128
  };
72039
72129
  const onCameraResetBtn = (e) => {
72040
- camera2.reset();
72130
+ camera2.reset.call();
72041
72131
  e.stopPropagation();
72042
72132
  };
72043
72133
  const onCameraFrameBtn = (e) => {
72044
- camera2.frameContext();
72134
+ camera2.frameSelection.call();
72045
72135
  e.stopPropagation();
72046
72136
  };
72047
72137
  const onSelectionIsolateBtn = (e) => {
@@ -72066,30 +72156,13 @@ function VimContextMenu(props) {
72066
72156
  props.isolation.show(getSelection(), "contextMenu");
72067
72157
  e.stopPropagation();
72068
72158
  };
72069
- const onSelectionClearBtn = (e) => {
72070
- viewer.selection.clear();
72071
- e.stopPropagation();
72072
- };
72073
72159
  const onShowAllBtn = (e) => {
72074
72160
  props.isolation.clear("contextMenu");
72075
72161
  e.stopPropagation();
72076
72162
  };
72077
- const onSectionToggleBtn = (e) => {
72078
- viewer.gizmos.sectionBox.clip = !viewer.gizmos.sectionBox.clip;
72079
- };
72080
- const onSectionResetBtn = (e) => {
72081
- viewer.gizmos.sectionBox.fitBox(viewer.renderer.getBoundingBox());
72082
- e.stopPropagation();
72083
- };
72084
72163
  const onMeasureDeleteBtn = (e) => {
72085
72164
  viewer.gizmos.measure.abort();
72086
72165
  };
72087
- const onFitSectionToSelectionBtn = (e) => {
72088
- const box = viewer.selection.getBoundingBox();
72089
- if (box) {
72090
- viewer.gizmos.sectionBox.fitBox(box);
72091
- }
72092
- };
72093
72166
  const createButton2 = (button) => {
72094
72167
  if (!button.enabled) return null;
72095
72168
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
@@ -72136,10 +72209,10 @@ function VimContextMenu(props) {
72136
72209
  },
72137
72210
  {
72138
72211
  id: contextMenuElementIds.zoomToFit,
72139
- label: "Zoom to Fit",
72212
+ label: "Focus Camera",
72140
72213
  keyboard: "F",
72141
72214
  action: onCameraFrameBtn,
72142
- enabled: true
72215
+ enabled: hasSelection
72143
72216
  },
72144
72217
  {
72145
72218
  id: contextMenuElementIds.dividerSelection,
@@ -72173,13 +72246,6 @@ function VimContextMenu(props) {
72173
72246
  action: onSelectionShowBtn,
72174
72247
  enabled: hasSelection && !hasVisibleSelection
72175
72248
  },
72176
- {
72177
- id: contextMenuElementIds.clearSelection,
72178
- label: "Clear Selection",
72179
- keyboard: "Esc",
72180
- action: onSelectionClearBtn,
72181
- enabled: hasSelection
72182
- },
72183
72249
  {
72184
72250
  id: contextMenuElementIds.showAll,
72185
72251
  label: "Show All",
@@ -72194,31 +72260,6 @@ function VimContextMenu(props) {
72194
72260
  keyboard: "",
72195
72261
  action: onMeasureDeleteBtn,
72196
72262
  enabled: measuring
72197
- },
72198
- {
72199
- id: contextMenuElementIds.dividerSection,
72200
- enabled: clipping || section.visible
72201
- },
72202
- {
72203
- id: contextMenuElementIds.ignoreSection,
72204
- label: section.clip ? "Ignore Section Box" : "Apply Section Box",
72205
- keyboard: "",
72206
- action: onSectionToggleBtn,
72207
- enabled: clipping
72208
- },
72209
- {
72210
- id: contextMenuElementIds.resetSection,
72211
- label: "Reset Section Box",
72212
- keyboard: "",
72213
- action: onSectionResetBtn,
72214
- enabled: clipping
72215
- },
72216
- {
72217
- id: contextMenuElementIds.fitSectionToSelection,
72218
- label: "Fit Section Box to Selection",
72219
- keyboard: "",
72220
- action: onFitSectionToSelectionBtn,
72221
- enabled: section.visible && hasSelection
72222
72263
  }
72223
72264
  ];
72224
72265
  elements = ((_c = props.customization) == null ? void 0 : _c.call(props, elements)) ?? elements;
@@ -72373,7 +72414,7 @@ function BimTree(props) {
72373
72414
  createInteractiveElementProps: (item, treeId, actions, renderFlags) => ({
72374
72415
  onKeyUp: (e) => {
72375
72416
  if (e.key === "f") {
72376
- props.camera.frameContext();
72417
+ props.camera.frameSelection.call();
72377
72418
  }
72378
72419
  if (e.key === "Escape") {
72379
72420
  props.viewer.selection.clear();
@@ -72416,7 +72457,7 @@ function BimTree(props) {
72416
72457
  },
72417
72458
  onPrimaryAction: (item, _) => {
72418
72459
  if (doubleClick.isDoubleClick(item.index)) {
72419
- props.camera.frameSelection();
72460
+ props.camera.frameSelection.call();
72420
72461
  }
72421
72462
  },
72422
72463
  onFocusItem: (item) => {
@@ -74707,7 +74748,7 @@ class ComponentInputs {
74707
74748
  return true;
74708
74749
  }
74709
74750
  case KEYS.KEY_F: {
74710
- this._camera.frameContext();
74751
+ this._camera.frameSelection.call();
74711
74752
  return true;
74712
74753
  }
74713
74754
  case KEYS.KEY_I: {
@@ -74901,7 +74942,7 @@ class Isolation {
74901
74942
  if (!this._settings.isolation.enable) return;
74902
74943
  this._isolation = objects ?? [];
74903
74944
  this._apply(source);
74904
- this._camera.frameVisibleObjects();
74945
+ this._camera.frameScene.call();
74905
74946
  }
74906
74947
  /**
74907
74948
  * Toggles isolation by using the current selection.
@@ -74916,7 +74957,7 @@ class Isolation {
74916
74957
  if (!this._settings.isolation.enable) return;
74917
74958
  this._isolation = [...this._viewer.selection.objects].filter((o) => o.type === "Object3D");
74918
74959
  this._apply(source);
74919
- this._camera.frameVisibleObjects();
74960
+ this._camera.frameScene.call();
74920
74961
  this._viewer.selection.clear();
74921
74962
  }
74922
74963
  /**
@@ -75016,75 +75057,6 @@ class Isolation {
75016
75057
  return objects;
75017
75058
  }
75018
75059
  }
75019
- class ComponentCamera {
75020
- constructor(viewer) {
75021
- __publicField(this, "_viewer");
75022
- this._viewer = viewer;
75023
- }
75024
- /**
75025
- * Resets the camera to its initial position.
75026
- */
75027
- reset() {
75028
- this._viewer.camera.lerp(1).reset();
75029
- }
75030
- /**
75031
- * Frames selected elements if there is an active selection; otherwise, frames all visible objects.
75032
- * @param duration Optional duration of the camera movement animation (default: 1).
75033
- */
75034
- frameContext(duration = 1) {
75035
- if (this._viewer.selection.count > 0) {
75036
- this.frameSelection(duration);
75037
- } else {
75038
- this.frameVisibleObjects(void 0, duration);
75039
- }
75040
- }
75041
- /**
75042
- * Frames selected elements if there is an active selection; otherwise, does nothing.
75043
- * @param duration Optional duration of the camera movement animation (default: 1).
75044
- */
75045
- frameSelection(duration = 1) {
75046
- if (this._viewer.selection.count === 0) return;
75047
- const box = this._viewer.selection.getBoundingBox();
75048
- if (box && this._viewer.gizmos.sectionBox.box.intersectsBox(box)) {
75049
- const movement = duration === 0 ? this._viewer.camera.snap() : this._viewer.camera.lerp(duration);
75050
- movement.frame(box);
75051
- }
75052
- }
75053
- /**
75054
- * Frames all visible objects in the scene.
75055
- * @param source Optional VIM to specify the source of objects to frame.
75056
- * @param duration Duration of the camera movement animation (default: 1).
75057
- */
75058
- frameVisibleObjects(source, duration = 1) {
75059
- const movement = duration === 0 ? this._viewer.camera.snap() : this._viewer.camera.lerp(duration);
75060
- const box = this.getVisibleBoundingBox(source);
75061
- movement.frame(box);
75062
- }
75063
- /**
75064
- * Returns the bounding box of all visible objects.
75065
- * @param source Optional VIM to specify the source of visible objects.
75066
- * @returns The bounding box of all visible objects.
75067
- */
75068
- getVisibleBoundingBox(source) {
75069
- let box;
75070
- const vimBoxUnion = (vim) => {
75071
- for (const obj of vim.getObjects()) {
75072
- if (!obj.visible) continue;
75073
- const b = obj.getBoundingBox();
75074
- if (!b) continue;
75075
- box = box ? box.union(b) : b == null ? void 0 : b.clone();
75076
- }
75077
- };
75078
- if (source) {
75079
- vimBoxUnion(source);
75080
- } else {
75081
- for (const vim of this._viewer.vims) {
75082
- vimBoxUnion(vim);
75083
- }
75084
- }
75085
- return box;
75086
- }
75087
- }
75088
75060
  function createContainer(element) {
75089
75061
  let root = element;
75090
75062
  if (root === void 0) {
@@ -75643,7 +75615,7 @@ function Modal(props) {
75643
75615
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
75644
75616
  "div",
75645
75617
  {
75646
- className: "vim-modal vc-absolute vc-inset-0 vc-z-40 vc-flex vc-items-center vc-justify-center vc-bg-overflow vc-backdrop-blur",
75618
+ className: "vim-modal vc-absolute vc-inset-0 vc-z-40 vc-flex vc-items-center vc-justify-center vc-bg-gray",
75647
75619
  onClick: ((_a2 = props.state.current) == null ? void 0 : _a2.canClose) ? () => {
75648
75620
  var _a3, _b3;
75649
75621
  return (_b3 = (_a3 = state.current) == null ? void 0 : _a3.onClose) == null ? void 0 : _b3.call(_a3);
@@ -75716,8 +75688,8 @@ function SectionBoxPanel(props) {
75716
75688
  resizeObserver.disconnect();
75717
75689
  }
75718
75690
  };
75719
- }, [props.state.getOffsetVisible()]);
75720
- if (!props.state.getOffsetVisible()) return null;
75691
+ }, [props.state.showOffsetPanel.get()]);
75692
+ if (!props.state.showOffsetPanel.get()) return null;
75721
75693
  const renderField = (id2, label, field) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "vim-sectionbox-offsets-entry vc-text-xs vc-flex vc-items-center vc-justify-center vc-justify-between vc-my-2", children: [
75722
75694
  /* @__PURE__ */ jsxRuntimeExports.jsx("dt", { className: "vc-w-1/2 vc-inline", children: label }),
75723
75695
  /* @__PURE__ */ jsxRuntimeExports.jsx("dd", { className: "vc-w-1/3 vc-inline", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -75725,10 +75697,10 @@ function SectionBoxPanel(props) {
75725
75697
  {
75726
75698
  id: id2,
75727
75699
  type: "text",
75728
- value: props.state.getText(field),
75729
- onChange: (e) => props.state.setText(field, e.target.value),
75700
+ value: field.get(),
75701
+ onChange: (e) => field.set(e.target.value),
75730
75702
  className: "vc-border vc-inline vc-border-gray-300 vc-py-1 vc-w-full vc-px-1",
75731
- onBlur: () => props.state.validate(field)
75703
+ onBlur: () => field.confirm()
75732
75704
  }
75733
75705
  ) })
75734
75706
  ] });
@@ -75750,15 +75722,15 @@ function SectionBoxPanel(props) {
75750
75722
  "button",
75751
75723
  {
75752
75724
  className: "vc-flex vc-border-none vc-bg-transparent vc-text-sm vc-cursor-pointer",
75753
- onClick: () => props.state.setOffsetsVisible(false),
75725
+ onClick: () => props.state.showOffsetPanel.set(false),
75754
75726
  children: close({ height: 12, width: 12, fill: "currentColor" })
75755
75727
  }
75756
75728
  )
75757
75729
  ] }),
75758
75730
  /* @__PURE__ */ jsxRuntimeExports.jsxs("dl", { className: "vc-text-xl vc-text-gray-darker vc-mb-2 vc-mx-2 ", children: [
75759
- renderField("topOffset", "Top Offset", "topOffset"),
75760
- renderField("sideOffseet", "Side Offset", "sideOffset"),
75761
- renderField("bottomOffset", "Bottom Offset", "bottomOffset")
75731
+ renderField("topOffset", "Top Offset", props.state.topOffset),
75732
+ renderField("sideOffseet", "Side Offset", props.state.sideOffset),
75733
+ renderField("bottomOffset", "Bottom Offset", props.state.bottomOffset)
75762
75734
  ] })
75763
75735
  ]
75764
75736
  }
@@ -75796,83 +75768,158 @@ function addBox(b1, b2) {
75796
75768
  r.max.z += b2.max.z;
75797
75769
  return r;
75798
75770
  }
75771
+ function useStateRef(initialValue) {
75772
+ const [value, setValue] = useState(initialValue);
75773
+ const ref = useRef(initialValue);
75774
+ const event = useRef(new distExports.SimpleEventDispatcher());
75775
+ const validate = useRef((value2) => value2);
75776
+ const confirm = useRef((value2) => value2);
75777
+ const set3 = (value2) => {
75778
+ const finalValue = validate.current(value2) ?? value2;
75779
+ if (finalValue === void 0) return;
75780
+ if (finalValue === ref.current) return;
75781
+ ref.current = finalValue;
75782
+ setValue(finalValue);
75783
+ event.current.dispatch(finalValue);
75784
+ };
75785
+ return {
75786
+ get() {
75787
+ return ref.current;
75788
+ },
75789
+ set: set3,
75790
+ confirm() {
75791
+ set3(confirm.current(ref.current));
75792
+ },
75793
+ useOnChange(on) {
75794
+ useEffect(() => {
75795
+ return event.current.subscribe(on);
75796
+ }, []);
75797
+ },
75798
+ useMemo(on, deps) {
75799
+ return useMemo(() => on(value), [...deps || [], value]);
75800
+ },
75801
+ useValidate(on) {
75802
+ useEffect(() => {
75803
+ validate.current = on;
75804
+ }, []);
75805
+ },
75806
+ useConfirm(on) {
75807
+ useEffect(() => {
75808
+ confirm.current = on;
75809
+ }, []);
75810
+ }
75811
+ };
75812
+ }
75813
+ function useActionRef(action) {
75814
+ const ref = useRef(action);
75815
+ return {
75816
+ call() {
75817
+ ref == null ? void 0 : ref.current();
75818
+ },
75819
+ set(func) {
75820
+ ref.current = func;
75821
+ }
75822
+ };
75823
+ }
75824
+ function useArgActionRef(action) {
75825
+ const ref = useRef(action);
75826
+ return {
75827
+ call(arg) {
75828
+ ref == null ? void 0 : ref.current(arg);
75829
+ },
75830
+ set(func) {
75831
+ ref.current = func;
75832
+ }
75833
+ };
75834
+ }
75835
+ function useFuncRef(func) {
75836
+ const ref = useRef(func);
75837
+ return {
75838
+ call() {
75839
+ return ref == null ? void 0 : ref.current();
75840
+ },
75841
+ set(func2) {
75842
+ ref.current = func2;
75843
+ }
75844
+ };
75845
+ }
75846
+ function useAsyncFuncRef(func) {
75847
+ const ref = useRef(func);
75848
+ return {
75849
+ async call() {
75850
+ return ref == null ? void 0 : ref.current();
75851
+ },
75852
+ set(func2) {
75853
+ ref.current = func2;
75854
+ }
75855
+ };
75856
+ }
75799
75857
  function useSectionBox(adapter) {
75800
- const [enable, setEnable] = useState(false);
75801
- const [visible2, setVisible] = useState(false);
75802
- const [offsetsVisible, setOffsetsVisible] = useState(false);
75803
- const [auto, setAuto] = useState(false);
75804
- const [offsets, setOffsets] = useState({
75805
- topOffset: "1",
75806
- sideOffset: "1",
75807
- bottomOffset: "1"
75808
- });
75858
+ const enable = useStateRef(false);
75859
+ const visible2 = useStateRef(false);
75860
+ const showOffsetPanel = useStateRef(false);
75861
+ const auto = useStateRef(false);
75862
+ const topOffset = useStateRef("1");
75863
+ const sideOffset = useStateRef("1");
75864
+ const bottomOffset = useStateRef("1");
75809
75865
  const boxRef = useRef(adapter.getBox());
75810
- const offsetBox = useMemo(() => offsetsToBox3(offsets), [offsets]);
75811
75866
  useEffect(() => {
75812
- setVisible(enable);
75813
- setAuto(false);
75814
- setOffsetsVisible(false);
75815
- setOffsets({
75816
- topOffset: "1",
75817
- sideOffset: "1",
75818
- bottomOffset: "1"
75867
+ adapter.setVisible(false);
75868
+ adapter.setClip(false);
75869
+ return adapter.onSelectionChanged.sub(() => {
75870
+ if (auto.get() && enable.get()) sectionSelection.call();
75819
75871
  });
75820
- void resetBox();
75821
- }, [enable]);
75822
- useEffect(() => {
75823
- if (auto) sectionSelection();
75824
- return auto ? adapter.onSelectionChanged.sub(sectionSelection) : () => {
75825
- };
75826
- }, [auto]);
75827
- useEffect(() => {
75828
- setBox(boxRef.current);
75829
- }, [offsets]);
75830
- useEffect(() => {
75831
- adapter.setVisible(visible2);
75832
- }, [visible2]);
75833
- const setText = (field, value) => {
75834
- const result = sanitize(value, false);
75835
- if (result !== void 0) {
75836
- setOffsets((prev) => ({ ...prev, [field]: result }));
75837
- }
75838
- };
75839
- const validate = (field) => {
75840
- const result = sanitize(offsets[field], true);
75841
- if (result !== void 0) {
75842
- setOffsets((prev) => ({ ...prev, [field]: result }));
75872
+ }, []);
75873
+ enable.useOnChange((v) => {
75874
+ adapter.setClip(v);
75875
+ visible2.set(v);
75876
+ showOffsetPanel.set(false);
75877
+ if (v && auto.get()) {
75878
+ sectionSelection.call();
75879
+ } else {
75880
+ sectionReset.call();
75843
75881
  }
75844
- };
75845
- const setBox = (baseBox) => {
75882
+ });
75883
+ visible2.useValidate((v) => enable.get() && v);
75884
+ showOffsetPanel.useValidate((v) => enable.get() && v);
75885
+ topOffset.useConfirm((v) => sanitize(v, true));
75886
+ sideOffset.useConfirm((v) => sanitize(v, true));
75887
+ bottomOffset.useConfirm((v) => sanitize(v, true));
75888
+ topOffset.useOnChange((v) => section.call(boxRef.current));
75889
+ sideOffset.useOnChange((v) => section.call(boxRef.current));
75890
+ bottomOffset.useOnChange((v) => section.call(boxRef.current));
75891
+ auto.useOnChange((v) => {
75892
+ if (v) sectionSelection.call();
75893
+ });
75894
+ visible2.useOnChange((v) => adapter.setVisible(v));
75895
+ const section = useArgActionRef((baseBox) => {
75846
75896
  boxRef.current = baseBox;
75847
- const newBox = addBox(baseBox, offsetBox);
75897
+ const newBox = addBox(baseBox, offsetsToBox3(topOffset.get(), sideOffset.get(), bottomOffset.get()));
75848
75898
  adapter.fitBox(newBox);
75849
- };
75850
- const sectionSelection = async () => {
75899
+ });
75900
+ const sectionSelection = useFuncRef(async () => {
75851
75901
  try {
75852
75902
  const box = await adapter.getSelectionBox() ?? await adapter.getRendererBox();
75853
- setBox(box);
75903
+ section.call(box);
75854
75904
  } catch (e) {
75855
75905
  console.error(e);
75856
75906
  }
75857
- };
75858
- const resetBox = async () => {
75907
+ });
75908
+ const sectionReset = useFuncRef(async () => {
75859
75909
  const box = await adapter.getRendererBox();
75860
- setBox(box);
75861
- };
75910
+ section.call(box);
75911
+ });
75862
75912
  return {
75863
- setEnable,
75864
- getEnable: () => enable,
75865
- getVisible: () => visible2,
75866
- setVisible,
75913
+ enable,
75914
+ visible: visible2,
75915
+ auto,
75916
+ showOffsetPanel,
75917
+ topOffset,
75918
+ sideOffset,
75919
+ bottomOffset,
75867
75920
  sectionSelection,
75868
- sectionReset: resetBox,
75869
- getOffsetVisible: () => offsetsVisible,
75870
- setOffsetsVisible,
75871
- getText: (field) => offsets[field],
75872
- setText,
75873
- getAuto: () => auto,
75874
- setAuto,
75875
- validate
75921
+ sectionReset,
75922
+ section
75876
75923
  };
75877
75924
  }
75878
75925
  const sanitize = (value, strict) => {
@@ -75885,18 +75932,21 @@ const sanitize = (value, strict) => {
75885
75932
  }
75886
75933
  return String(num);
75887
75934
  };
75888
- function offsetsToBox3(offsets) {
75889
- const getNumber = (field) => {
75890
- const num = parseFloat(offsets[field]);
75935
+ function offsetsToBox3(top, side, bottom) {
75936
+ const getNumber = (s) => {
75937
+ const num = parseFloat(s);
75891
75938
  return isNaN(num) ? 0 : num;
75892
75939
  };
75893
75940
  return new Box3(
75894
- new Vector3(-getNumber("sideOffset"), -getNumber("sideOffset"), -getNumber("bottomOffset")),
75895
- new Vector3(getNumber("sideOffset"), getNumber("sideOffset"), getNumber("topOffset"))
75941
+ new Vector3(-getNumber(side), -getNumber(side), -getNumber(bottom)),
75942
+ new Vector3(getNumber(side), getNumber(side), getNumber(top))
75896
75943
  );
75897
75944
  }
75898
75945
  function useWebglSectionBox(viewer) {
75899
75946
  const vimAdapter = {
75947
+ setClip: (b) => {
75948
+ viewer.gizmos.sectionBox.clip = b;
75949
+ },
75900
75950
  setVisible: (b) => {
75901
75951
  viewer.gizmos.sectionBox.visible = b;
75902
75952
  viewer.gizmos.sectionBox.interactive = b;
@@ -75905,12 +75955,59 @@ function useWebglSectionBox(viewer) {
75905
75955
  fitBox: (box) => viewer.gizmos.sectionBox.fitBox(box),
75906
75956
  getSelectionBox: () => Promise.resolve(viewer.selection.getBoundingBox()),
75907
75957
  getRendererBox: () => Promise.resolve(viewer.renderer.getBoundingBox()),
75908
- onSceneChanged: viewer.renderer.onBoxUpdated,
75909
75958
  onSelectionChanged: viewer.selection.onValueChanged
75910
75959
  };
75911
- viewer.gizmos.sectionBox.clip = true;
75912
75960
  return useSectionBox(vimAdapter);
75913
75961
  }
75962
+ function useCamera(adapter) {
75963
+ const autoCamera2 = useStateRef(false);
75964
+ autoCamera2.useOnChange((v) => {
75965
+ if (v) {
75966
+ frameSelection2.call();
75967
+ }
75968
+ });
75969
+ useEffect(() => {
75970
+ adapter.onSelectionChanged.sub(() => {
75971
+ if (autoCamera2.get()) {
75972
+ frameSelection2.call();
75973
+ }
75974
+ });
75975
+ }, []);
75976
+ const reset = useActionRef(() => adapter.resetCamera(1));
75977
+ const frameSelection2 = useAsyncFuncRef(async () => {
75978
+ if (!adapter.hasSelection()) {
75979
+ frameScene.call();
75980
+ return;
75981
+ }
75982
+ const box = await adapter.getSelectionBox();
75983
+ if (!box) {
75984
+ return;
75985
+ }
75986
+ adapter.frameCamera(box, 1);
75987
+ });
75988
+ const frameScene = useAsyncFuncRef(async () => {
75989
+ adapter.frameAll(1);
75990
+ });
75991
+ return {
75992
+ autoCamera: autoCamera2,
75993
+ reset,
75994
+ frameSelection: frameSelection2,
75995
+ frameScene
75996
+ };
75997
+ }
75998
+ function useWebglCamera(viewer) {
75999
+ return useCamera({
76000
+ onSelectionChanged: viewer.selection.onValueChanged,
76001
+ frameCamera: (box, duration) => viewer.camera.lerp(duration).frame(box),
76002
+ resetCamera: (duration) => viewer.camera.lerp(duration).reset(),
76003
+ frameAll: (duration) => {
76004
+ const box = viewer.renderer.getBoundingBox();
76005
+ viewer.camera.lerp(duration).frame(box);
76006
+ },
76007
+ hasSelection: () => viewer.selection.count > 0,
76008
+ getSelectionBox: () => Promise.resolve(viewer.selection.getBoundingBox())
76009
+ });
76010
+ }
75914
76011
  function createWebglComponent(container, componentSettings = {}, viewerSettings = {}) {
75915
76012
  const promise2 = new DeferredPromise2();
75916
76013
  const cmpContainer = container instanceof HTMLElement ? createContainer(container) : container ?? createContainer();
@@ -75942,7 +76039,7 @@ function VimComponent(props) {
75942
76039
  var _a2;
75943
76040
  const settings2 = useSettings(props.viewer, props.settings ?? {});
75944
76041
  const modal = useModal(settings2.value.capacity.canFollowUrl);
75945
- const camera2 = useMemo(() => new ComponentCamera(props.viewer), []);
76042
+ const camera2 = useWebglCamera(props.viewer);
75946
76043
  const cursor = useMemo(() => new CursorManager(props.viewer), []);
75947
76044
  const loader = useRef(new ComponentLoader(props.viewer, modal));
75948
76045
  const [isolation] = useState(() => new Isolation(props.viewer, camera2, settings2.value));
@@ -75983,6 +76080,9 @@ function VimComponent(props) {
75983
76080
  isolation,
75984
76081
  camera: camera2,
75985
76082
  settings: settings2,
76083
+ get sectionBox() {
76084
+ return sectionBox2;
76085
+ },
75986
76086
  contextMenu: {
75987
76087
  customize: (v) => setcontextMenu(() => v)
75988
76088
  },
@@ -76156,11 +76256,13 @@ const errorStyle = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePr
76156
76256
  vcRoboto
76157
76257
  }, Symbol.toStringTag, { value: "Module" }));
76158
76258
  const support = "https://docs.vimaec.com";
76259
+ const supportUltra = "https://docs.vimaec.com/docs/vim-for-windows/configuring-vim-ultra";
76159
76260
  const supportControls = "https://docs.vimaec.com/docs/vim-cloud/webgl-navigation-and-controls-guide";
76160
76261
  const urls = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
76161
76262
  __proto__: null,
76162
76263
  support,
76163
- supportControls
76264
+ supportControls,
76265
+ supportUltra
76164
76266
  }, Symbol.toStringTag, { value: "Module" }));
76165
76267
  function fileOpeningError(url) {
76166
76268
  return {
@@ -76206,12 +76308,12 @@ function serverFileDownloadingError(url, authToken, server) {
76206
76308
  }
76207
76309
  return {
76208
76310
  title: "File Downloading Error",
76209
- body: body$4(server, authToken, server),
76311
+ body: body$4(url, authToken, server),
76210
76312
  footer: footer(support),
76211
76313
  canClose: false
76212
76314
  };
76213
76315
  }
76214
- function body$4(url, server, authToken) {
76316
+ function body$4(url, authToken, server) {
76215
76317
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: vcRoboto, children: [
76216
76318
  mainText(/* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
76217
76319
  "Oops, it appears that there’s an ",
@@ -76276,7 +76378,7 @@ function body$2(url, local) {
76276
76378
  /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
76277
76379
  "Ensure that VIM Ultra",
76278
76380
  " ",
76279
- link(support, "process is running"),
76381
+ link(supportUltra, "process is running"),
76280
76382
  " ",
76281
76383
  "at ",
76282
76384
  detailText(url)
@@ -76358,7 +76460,7 @@ function getErrorMessage(state) {
76358
76460
  return serverStreamError(state.serverUrl);
76359
76461
  }
76360
76462
  }
76361
- function getRequestErrorMessage(source, error) {
76463
+ function getRequestErrorMessage(serverUrl, source, error) {
76362
76464
  console.log(error);
76363
76465
  switch (error) {
76364
76466
  case "loadingError":
@@ -76366,7 +76468,7 @@ function getRequestErrorMessage(source, error) {
76366
76468
  case "downloadingError":
76367
76469
  case "unknown":
76368
76470
  case "cancelled":
76369
- return serverFileDownloadingError(source.url);
76471
+ return serverFileDownloadingError(source.url, source.authToken, serverUrl);
76370
76472
  case "serverDisconnected":
76371
76473
  return serverConnectionError(source.url);
76372
76474
  }
@@ -76378,7 +76480,7 @@ function updateModal(modal, state) {
76378
76480
  }
76379
76481
  if (state.status === "connecting") {
76380
76482
  if (modal.current === void 0 || modal.current.type === "loading") {
76381
- modal.loading({ message: "Connecting to VIM Ultra server..." });
76483
+ modal.loading({ message: "Initializing..." });
76382
76484
  }
76383
76485
  }
76384
76486
  if (state.status === "error") {
@@ -76394,6 +76496,9 @@ async function updateProgress(request2, modal) {
76394
76496
  }
76395
76497
  function useUltraSectionBox(viewer) {
76396
76498
  const ultraAdapter = {
76499
+ setClip: (b) => {
76500
+ viewer.sectionBox.clip = b;
76501
+ },
76397
76502
  setVisible: (b) => {
76398
76503
  viewer.sectionBox.visible = b;
76399
76504
  viewer.sectionBox.interactive = b;
@@ -76402,15 +76507,26 @@ function useUltraSectionBox(viewer) {
76402
76507
  fitBox: (box) => viewer.sectionBox.fitBox(box),
76403
76508
  getSelectionBox: () => viewer.selection.getBoundingBox(),
76404
76509
  getRendererBox: () => viewer.renderer.getBoundingBox(),
76405
- onSelectionChanged: viewer.selection.onValueChanged,
76406
- onSceneChanged: viewer.vims.onChanged
76510
+ onSelectionChanged: viewer.selection.onValueChanged
76407
76511
  };
76408
76512
  return useSectionBox(ultraAdapter);
76409
76513
  }
76410
- function useUltraControlBar(viewer, section, customization) {
76411
- let controlBar2 = [controlBarSectionBox(section, viewer.selection.count > 0)];
76412
- controlBar2 = (customization == null ? void 0 : customization(controlBar2)) ?? controlBar2;
76413
- return controlBar2;
76514
+ function useUltraControlBar(viewer, section, camera2, customization) {
76515
+ const sectionSectionBox = controlBarSectionBox(section, viewer.selection.count > 0);
76516
+ const sectionCamera = controlBarCamera(camera2);
76517
+ let bar = [sectionCamera, sectionSectionBox];
76518
+ bar = (customization == null ? void 0 : customization(bar)) ?? bar;
76519
+ return bar;
76520
+ }
76521
+ function useUltraCamera(viewer) {
76522
+ return useCamera({
76523
+ onSelectionChanged: viewer.selection.onValueChanged,
76524
+ frameCamera: (box, duration) => void viewer.camera.frameBox(box, duration),
76525
+ frameAll: (duration) => viewer.camera.frameAll(duration),
76526
+ resetCamera: (duration) => viewer.camera.restoreSavedPosition(duration),
76527
+ hasSelection: () => viewer.selection.count > 0,
76528
+ getSelectionBox: () => viewer.selection.getBoundingBox()
76529
+ });
76414
76530
  }
76415
76531
  function createUltraComponent(container) {
76416
76532
  const promise2 = new DeferredPromise2();
@@ -76440,15 +76556,28 @@ function createUltraComponent(container) {
76440
76556
  function UltraComponent(props) {
76441
76557
  const modal = useModal(true);
76442
76558
  const sectionBox2 = useUltraSectionBox(props.viewer);
76443
- const controlBar2 = useUltraControlBar(props.viewer, sectionBox2, (_2) => _2);
76559
+ const camera2 = useUltraCamera(props.viewer);
76444
76560
  const side = useSideState(true, 400);
76445
76561
  const [_, setSelectState] = useState(0);
76562
+ const [controlBarCustom, setControlBarCustom] = useState(() => (c) => c);
76563
+ const controlBar2 = useUltraControlBar(props.viewer, sectionBox2, camera2, (_2) => _2);
76446
76564
  useEffect(() => {
76447
76565
  props.viewer.onStateChanged.subscribe((state) => updateModal(modal, state));
76448
76566
  props.viewer.selection.onValueChanged.subscribe(() => {
76449
76567
  setSelectState((i) => (i + 1) % 2);
76450
76568
  });
76451
- props.onMount(createComponentRef(props.viewer, modal));
76569
+ props.onMount({
76570
+ viewer: props.viewer,
76571
+ modal,
76572
+ sectionBox: sectionBox2,
76573
+ camera: camera2,
76574
+ dispose: () => {
76575
+ },
76576
+ controlBar: {
76577
+ customize: (v) => setControlBarCustom(() => v)
76578
+ },
76579
+ load: patchLoad(props.viewer, modal)
76580
+ });
76452
76581
  }, []);
76453
76582
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
76454
76583
  /* @__PURE__ */ jsxRuntimeExports.jsx(RestOfScreen, { side, content: () => {
@@ -76458,24 +76587,34 @@ function UltraComponent(props) {
76458
76587
  /* @__PURE__ */ jsxRuntimeExports.jsx(
76459
76588
  ControlBar,
76460
76589
  {
76461
- content: controlBar2,
76590
+ content: controlBarCustom(controlBar2),
76462
76591
  show: true
76463
76592
  }
76464
76593
  ),
76465
76594
  /* @__PURE__ */ jsxRuntimeExports.jsx(SectionBoxPanel, { state: sectionBox2 })
76466
76595
  ] });
76467
76596
  } }),
76468
- /* @__PURE__ */ jsxRuntimeExports.jsx(Modal, { state: modal })
76597
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Modal, { state: modal }),
76598
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
76599
+ ReactTooltip,
76600
+ {
76601
+ multiline: true,
76602
+ arrowColor: "transparent",
76603
+ type: "light",
76604
+ className: "!vc-max-w-xs !vc-border !vc-border-solid !vc-border-gray-medium !vc-bg-white !vc-text-xs !vc-text-gray-darkest !vc-opacity-100 !vc-shadow-[2px_6px_15px_rgba(0,0,0,0.3)] !vc-transition-opacity",
76605
+ delayShow: 200
76606
+ }
76607
+ )
76469
76608
  ] });
76470
76609
  }
76471
- function createComponentRef(viewer, modal) {
76472
- function load(source) {
76610
+ function patchLoad(viewer, modal) {
76611
+ return function load(source) {
76473
76612
  const request2 = viewer.loadVim(source);
76474
76613
  void updateProgress(request2, modal);
76475
76614
  void request2.getResult().then(
76476
76615
  (result) => {
76477
76616
  if (result.isError) {
76478
- modal.message(getRequestErrorMessage(source, result.error));
76617
+ modal.message(getRequestErrorMessage(viewer.serverUrl, source, result.error));
76479
76618
  return;
76480
76619
  }
76481
76620
  if (result.isSuccess) {
@@ -76484,13 +76623,6 @@ function createComponentRef(viewer, modal) {
76484
76623
  }
76485
76624
  );
76486
76625
  return request2;
76487
- }
76488
- return {
76489
- viewer,
76490
- modal,
76491
- dispose: () => {
76492
- },
76493
- load
76494
76626
  };
76495
76627
  }
76496
76628
  const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
@@ -76499,6 +76631,7 @@ const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
76499
76631
  createUltraComponent
76500
76632
  }, Symbol.toStringTag, { value: "Module" }));
76501
76633
  export {
76634
+ controlBar as ControlBar,
76502
76635
  errorStyle as ErrorStyle,
76503
76636
  errors as Errors,
76504
76637
  icons as Icons,