@ericchen1990/pano-view 3.3.0 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -9988,6 +9988,27 @@ function PanoBasicMaterial({
9988
9988
  );
9989
9989
  }
9990
9990
 
9991
+ // src/scene-detail.tsx
9992
+ import { createContext as createContext15, useContext as useContext21 } from "react";
9993
+ var SceneDetailContext = createContext15(null);
9994
+ function useSceneDetailReporter() {
9995
+ return useContext21(SceneDetailContext);
9996
+ }
9997
+ function viewTilesAreDrawable(textures) {
9998
+ return textures.length > 0 && textures.every((texture) => texture != null);
9999
+ }
10000
+ function publishSceneDetail(reporter, lastToken, ready) {
10001
+ if (!reporter) {
10002
+ return;
10003
+ }
10004
+ const token = `${reporter.generation}:${ready ? 1 : 0}`;
10005
+ if (lastToken.current === token) {
10006
+ return;
10007
+ }
10008
+ lastToken.current = token;
10009
+ reporter.report(ready);
10010
+ }
10011
+
9991
10012
  // src/tile/texture-manager.ts
9992
10013
  import {
9993
10014
  ClampToEdgeWrapping,
@@ -10221,13 +10242,13 @@ var TileTextureManager = class {
10221
10242
  // src/tile/texture-manager-context.tsx
10222
10243
  import { useThree as useThree13 } from "@react-three/fiber";
10223
10244
  import {
10224
- createContext as createContext15,
10225
- useContext as useContext21,
10245
+ createContext as createContext16,
10246
+ useContext as useContext22,
10226
10247
  useEffect as useEffect21,
10227
10248
  useMemo as useMemo14
10228
10249
  } from "react";
10229
10250
  import { jsx as jsx15 } from "react/jsx-runtime";
10230
- var TileTextureManagerContext = createContext15(null);
10251
+ var TileTextureManagerContext = createContext16(null);
10231
10252
  function TileTextureManagerProvider({
10232
10253
  children,
10233
10254
  maxTextureMemoryMb = 128,
@@ -10251,7 +10272,7 @@ function TileTextureManagerProvider({
10251
10272
  return /* @__PURE__ */ jsx15(TileTextureManagerContext.Provider, { value: manager, children });
10252
10273
  }
10253
10274
  function useSharedTileTextureManager() {
10254
- return useContext21(TileTextureManagerContext);
10275
+ return useContext22(TileTextureManagerContext);
10255
10276
  }
10256
10277
 
10257
10278
  // src/tile/texture-hooks.ts
@@ -10468,6 +10489,15 @@ function preferredSphereLevel(levels, height, dpr, verticalFov) {
10468
10489
 
10469
10490
  // src/sphere-tile/sphere-tile.tsx
10470
10491
  import { jsx as jsx16, jsxs as jsxs9 } from "react/jsx-runtime";
10492
+ function sphereTileViewShouldRefresh(input) {
10493
+ if (input.loadModeChanged || input.managerChanged) {
10494
+ return true;
10495
+ }
10496
+ if (input.elapsedMs < 100 || input.viewUnchanged) {
10497
+ return false;
10498
+ }
10499
+ return true;
10500
+ }
10471
10501
  function SpherePatch({
10472
10502
  address,
10473
10503
  texture,
@@ -10627,6 +10657,11 @@ function SphereTileSource({
10627
10657
  []
10628
10658
  );
10629
10659
  const [layers, setLayers] = useState10([]);
10660
+ const detailReporter = useSceneDetailReporter();
10661
+ const detailReporterRef = useRef23(detailReporter);
10662
+ detailReporterRef.current = detailReporter;
10663
+ const detailTokenRef = useRef23("");
10664
+ const targetKeysRef = useRef23([]);
10630
10665
  const scratch = useMemo15(
10631
10666
  () => ({
10632
10667
  camera: new PerspectiveCamera3(),
@@ -10648,53 +10683,72 @@ function SphereTileSource({
10648
10683
  useFrame9(() => {
10649
10684
  if (!(camera instanceof PerspectiveCamera3)) return;
10650
10685
  const now = performance.now(), dpr = gl.getPixelRatio();
10651
- const reset = scratch.manager !== manager || scratch.loadMode !== loadMode;
10652
- if (!reset && (now - scratch.time < 100 || scratch.fov === camera.fov && scratch.width === size.width && scratch.height === size.height && scratch.dpr === dpr && scratch.quaternion.angleTo(camera.quaternion) < 1e-4))
10653
- return;
10654
- scratch.time = now;
10655
- scratch.fov = camera.fov;
10656
- scratch.width = size.width;
10657
- scratch.height = size.height;
10658
- scratch.dpr = dpr;
10659
- scratch.quaternion.copy(camera.quaternion);
10660
- scratch.manager = manager;
10661
- scratch.loadMode = loadMode;
10662
- scratch.camera.copy(camera, false);
10663
- scratch.camera.fov = Math.min(179, camera.fov + 8);
10664
- scratch.camera.updateProjectionMatrix();
10665
- scratch.camera.updateMatrixWorld();
10666
- scratch.matrix.multiplyMatrices(
10667
- scratch.camera.projectionMatrix,
10668
- scratch.camera.matrixWorldInverse
10669
- );
10670
- scratch.frustum.setFromProjectionMatrix(scratch.matrix);
10671
- let level = loadMode === "preview" ? -1 : loadMode === "base" ? 0 : preferredSphereLevel(config.levels, size.height, dpr, camera.fov);
10672
- const next = [];
10673
- let residentBytes = 0;
10674
- for (let index = 0; index <= level; index++) {
10675
- const addresses = candidates[index].filter(
10676
- ({ bounds }) => scratch.frustum.intersectsBox(bounds)
10677
- ).map(({ address }) => address);
10678
- const bytes = addresses.reduce(
10679
- (total, address) => total + address.width * address.height * 4,
10680
- 0
10686
+ const managerChanged = scratch.manager !== manager;
10687
+ const loadModeChanged = scratch.loadMode !== loadMode;
10688
+ const viewUnchanged = scratch.fov === camera.fov && scratch.width === size.width && scratch.height === size.height && scratch.dpr === dpr && scratch.quaternion.angleTo(camera.quaternion) < 1e-4;
10689
+ if (sphereTileViewShouldRefresh({
10690
+ loadModeChanged,
10691
+ managerChanged,
10692
+ elapsedMs: now - scratch.time,
10693
+ viewUnchanged
10694
+ })) {
10695
+ const reset = managerChanged || loadModeChanged;
10696
+ scratch.time = now;
10697
+ scratch.fov = camera.fov;
10698
+ scratch.width = size.width;
10699
+ scratch.height = size.height;
10700
+ scratch.dpr = dpr;
10701
+ scratch.quaternion.copy(camera.quaternion);
10702
+ scratch.manager = manager;
10703
+ scratch.loadMode = loadMode;
10704
+ scratch.camera.copy(camera, false);
10705
+ scratch.camera.fov = Math.min(179, camera.fov + 8);
10706
+ scratch.camera.updateProjectionMatrix();
10707
+ scratch.camera.updateMatrixWorld();
10708
+ scratch.matrix.multiplyMatrices(
10709
+ scratch.camera.projectionMatrix,
10710
+ scratch.camera.matrixWorldInverse
10681
10711
  );
10682
- if (residentBytes + bytes > budget) {
10683
- level = index - 1;
10684
- break;
10712
+ scratch.frustum.setFromProjectionMatrix(scratch.matrix);
10713
+ let level = loadMode === "preview" ? -1 : loadMode === "base" ? 0 : preferredSphereLevel(config.levels, size.height, dpr, camera.fov);
10714
+ const next = [];
10715
+ let residentBytes = 0;
10716
+ for (let index = 0; index <= level; index++) {
10717
+ const addresses = candidates[index].filter(
10718
+ ({ bounds }) => scratch.frustum.intersectsBox(bounds)
10719
+ ).map(({ address }) => address);
10720
+ const bytes = addresses.reduce(
10721
+ (total, address) => total + address.width * address.height * 4,
10722
+ 0
10723
+ );
10724
+ if (residentBytes + bytes > budget) {
10725
+ level = index - 1;
10726
+ break;
10727
+ }
10728
+ residentBytes += bytes;
10729
+ next.push({ level: index, addresses });
10730
+ }
10731
+ const targetLayer = loadMode === "full" ? next[next.length - 1] : void 0;
10732
+ targetKeysRef.current = targetLayer ? targetLayer.addresses.map(
10733
+ (address) => `${resolveUrl(address)}\0${sphereTileKey(address)}`
10734
+ ) : [];
10735
+ if (level !== scratch.level) {
10736
+ scratch.level = level;
10737
+ if (level >= 0) callbacks.current.onLevelChange?.(level);
10738
+ }
10739
+ const token = next.map((layer) => layer.addresses.map(sphereTileKey).join(",")).join(";");
10740
+ if (token !== scratch.token || reset) {
10741
+ scratch.token = token;
10742
+ setLayers(next);
10685
10743
  }
10686
- residentBytes += bytes;
10687
- next.push({ level: index, addresses });
10688
- }
10689
- if (level !== scratch.level) {
10690
- scratch.level = level;
10691
- if (level >= 0) callbacks.current.onLevelChange?.(level);
10692
- }
10693
- const token = next.map((layer) => layer.addresses.map(sphereTileKey).join(",")).join(";");
10694
- if (token !== scratch.token || reset) {
10695
- scratch.token = token;
10696
- setLayers(next);
10697
10744
  }
10745
+ publishSceneDetail(
10746
+ detailReporterRef.current,
10747
+ detailTokenRef,
10748
+ loadMode === "full" && viewTilesAreDrawable(
10749
+ targetKeysRef.current.map((key) => manager.getSnapshot(key).texture)
10750
+ )
10751
+ );
10698
10752
  });
10699
10753
  return /* @__PURE__ */ jsxs9("group", { visible, children: [
10700
10754
  preview ? /* @__PURE__ */ jsx16(
@@ -10826,9 +10880,19 @@ function Sphere({
10826
10880
  );
10827
10881
  const displayTexture = texture ?? previewTexture;
10828
10882
  const readyRef = useRef24(false);
10883
+ const detailReporter = useSceneDetailReporter();
10829
10884
  useEffect24(() => {
10830
10885
  readyRef.current = false;
10831
10886
  }, [resolvedPreviewUrl, src]);
10887
+ useEffect24(() => {
10888
+ if (!detailReporter) {
10889
+ return;
10890
+ }
10891
+ detailReporter.report(texture != null);
10892
+ return () => {
10893
+ detailReporter.report(false);
10894
+ };
10895
+ }, [detailReporter, texture]);
10832
10896
  useEffect24(() => {
10833
10897
  if (!displayTexture || readyRef.current) {
10834
10898
  return;
@@ -10863,7 +10927,7 @@ function Sphere({
10863
10927
  import { useThree as useThree16 } from "@react-three/fiber";
10864
10928
  import {
10865
10929
  useCallback as useCallback10,
10866
- useContext as useContext22,
10930
+ useContext as useContext23,
10867
10931
  useEffect as useEffect25,
10868
10932
  useLayoutEffect as useLayoutEffect3,
10869
10933
  useMemo as useMemo17,
@@ -11064,8 +11128,8 @@ function PanoVideo({
11064
11128
  }) {
11065
11129
  usePanoMediaActivationIntent(autoPlay);
11066
11130
  const gl = useThree16((state) => state.gl);
11067
- const host = useContext22(PanoVideoHostContext);
11068
- const overlay = useContext22(PanoChromeOverlayContext);
11131
+ const host = useContext23(PanoVideoHostContext);
11132
+ const overlay = useContext23(PanoChromeOverlayContext);
11069
11133
  const variants = useMemo17(
11070
11134
  () => resolvePanoVideoVariants({ poster, src, variants: variantsProp }),
11071
11135
  [poster, src, variantsProp]
@@ -11620,14 +11684,14 @@ function PanoVideo({
11620
11684
  }
11621
11685
 
11622
11686
  // src/scenes.tsx
11623
- import { useFrame as useFrame13, useThree as useThree20 } from "@react-three/fiber";
11687
+ import { useFrame as useFrame14, useThree as useThree21 } from "@react-three/fiber";
11624
11688
  import {
11625
11689
  Fragment as Fragment6,
11626
11690
  useCallback as useCallback11,
11627
- useContext as useContext23,
11628
- useEffect as useEffect29,
11629
- useMemo as useMemo21,
11630
- useRef as useRef29,
11691
+ useContext as useContext24,
11692
+ useEffect as useEffect30,
11693
+ useMemo as useMemo22,
11694
+ useRef as useRef30,
11631
11695
  useState as useState14
11632
11696
  } from "react";
11633
11697
  import {
@@ -11682,18 +11746,34 @@ function isSnapshotTransition(preset) {
11682
11746
  return preset !== "none" && preset !== "particles";
11683
11747
  }
11684
11748
 
11685
- // src/scene-transitions/particle-overlay.tsx
11749
+ // src/scene-transitions/snapshot-hold.tsx
11686
11750
  import { useFrame as useFrame10, useThree as useThree17 } from "@react-three/fiber";
11687
11751
  import { useEffect as useEffect26, useMemo as useMemo18, useRef as useRef26 } from "react";
11688
- import {
11689
- DoubleSide as DoubleSide2,
11690
- InstancedBufferAttribute,
11691
- InstancedBufferGeometry,
11692
- PlaneGeometry as PlaneGeometry3,
11693
- ShaderMaterial as ShaderMaterial2,
11694
- Vector2 as Vector24,
11695
- Vector3 as Vector310
11696
- } from "three";
11752
+ import { Vector3 as Vector310 } from "three";
11753
+
11754
+ // src/scene-transitions/overlay-utils.ts
11755
+ import { PlaneGeometry as PlaneGeometry2 } from "three";
11756
+ var OVERLAY_RENDER_ORDER = 1e4;
11757
+ var FULLSCREEN_PLANE = new PlaneGeometry2(1, 1);
11758
+ function isPerspectiveCamera(camera) {
11759
+ return camera.isPerspectiveCamera === true;
11760
+ }
11761
+ function placeFullscreenOverlay(mesh, camera, direction) {
11762
+ const distance = Math.max(camera.near * 1.1, 0.11);
11763
+ camera.getWorldDirection(direction);
11764
+ mesh.position.copy(camera.position).addScaledVector(direction, distance);
11765
+ mesh.quaternion.copy(camera.quaternion);
11766
+ const height = 2 * distance * Math.tan(camera.fov * Math.PI / 360);
11767
+ mesh.scale.set(height * camera.aspect, height, 1);
11768
+ }
11769
+ function overlayProgress(elapsedTime, duration, startTime) {
11770
+ const started = startTime ?? elapsedTime;
11771
+ const progress = duration === 0 ? 1 : Math.min(1, (elapsedTime - started) / duration);
11772
+ return { startTime: started, progress };
11773
+ }
11774
+
11775
+ // src/scene-transitions/snapshot-shaders.ts
11776
+ import { DoubleSide as DoubleSide2, ShaderMaterial as ShaderMaterial2, Vector2 as Vector24 } from "three";
11697
11777
 
11698
11778
  // src/scene-transitions/glsl.ts
11699
11779
  var GLSL_COMMON = `
@@ -11725,169 +11805,7 @@ float fbm(vec2 p) {
11725
11805
  }
11726
11806
  `;
11727
11807
 
11728
- // src/scene-transitions/overlay-utils.ts
11729
- import { PlaneGeometry as PlaneGeometry2 } from "three";
11730
- var OVERLAY_RENDER_ORDER = 1e4;
11731
- var FULLSCREEN_PLANE = new PlaneGeometry2(1, 1);
11732
- function isPerspectiveCamera(camera) {
11733
- return camera.isPerspectiveCamera === true;
11734
- }
11735
- function placeFullscreenOverlay(mesh, camera, direction) {
11736
- const distance = Math.max(camera.near * 1.1, 0.11);
11737
- camera.getWorldDirection(direction);
11738
- mesh.position.copy(camera.position).addScaledVector(direction, distance);
11739
- mesh.quaternion.copy(camera.quaternion);
11740
- const height = 2 * distance * Math.tan(camera.fov * Math.PI / 360);
11741
- mesh.scale.set(height * camera.aspect, height, 1);
11742
- }
11743
- function overlayProgress(elapsedTime, duration, startTime) {
11744
- const started = startTime ?? elapsedTime;
11745
- const progress = duration === 0 ? 1 : Math.min(1, (elapsedTime - started) / duration);
11746
- return { startTime: started, progress };
11747
- }
11748
-
11749
- // src/scene-transitions/particle-overlay.tsx
11750
- import { jsx as jsx19 } from "react/jsx-runtime";
11751
- var PARTICLE_GRID = 48;
11752
- var PARTICLE_COUNT = PARTICLE_GRID * PARTICLE_GRID;
11753
- var PARTICLE_VERTEX_SHADER = `
11754
- attribute float instanceIndex;
11755
- uniform float progress;
11756
- uniform vec2 grid;
11757
- varying vec2 vUv;
11758
- varying float vAlpha;
11759
- ${GLSL_COMMON}
11760
-
11761
- void main() {
11762
- float id = instanceIndex;
11763
- float gx = mod(id, grid.x);
11764
- float gy = floor(id / grid.x);
11765
- vec2 cell = vec2(gx, gy);
11766
- float h = hash(cell);
11767
- float h2 = hash(cell + 19.2);
11768
- float h3 = hash(cell + 7.7);
11769
- vec2 randomDir = normalize(vec2(h, h2) * 2.0 - 1.0 + 1e-5);
11770
- vec2 fromCenter = (cell + 0.5) / grid - 0.5 + 1e-5;
11771
- vec2 dir = normalize(mix(randomDir, normalize(fromCenter), 0.65));
11772
- float delay = h3 * 0.28;
11773
- float lt = clamp((progress - delay) / max(1.0 - delay, 0.001), 0.0, 1.0);
11774
- float explode = lt * lt;
11775
- float scale = mix(1.0, 0.18, explode);
11776
- float angle = (h * 2.0 - 1.0) * explode * 4.2;
11777
- float ca = cos(angle);
11778
- float sa = sin(angle);
11779
- vec2 cellSize = 1.0 / grid;
11780
- vec2 local = position.xy * cellSize * scale;
11781
- vec2 rotated = vec2(local.x * ca - local.y * sa, local.x * sa + local.y * ca);
11782
- vec2 planeCenter = (cell + 0.5) / grid - 0.5;
11783
- vec2 exploded = planeCenter + dir * explode * 0.9;
11784
- vec3 pos = vec3(exploded + rotated, -explode * 0.14);
11785
- vUv = (cell + uv) / grid;
11786
- vAlpha = 1.0 - explode;
11787
- gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
11788
- }
11789
- `;
11790
- var PARTICLE_FRAGMENT_SHADER = `
11791
- uniform sampler2D map;
11792
- varying vec2 vUv;
11793
- varying float vAlpha;
11794
-
11795
- void main() {
11796
- vec4 old = texture2D(map, vUv);
11797
- old.rgb *= 1.0 + 0.22 * (1.0 - vAlpha);
11798
- gl_FragColor = vec4(old.rgb, old.a * vAlpha);
11799
- #include <colorspace_fragment>
11800
- }
11801
- `;
11802
- function createParticleGeometry() {
11803
- const quad = new PlaneGeometry3(1, 1);
11804
- const geometry = new InstancedBufferGeometry();
11805
- if (quad.index) {
11806
- geometry.setIndex(quad.index.clone());
11807
- }
11808
- geometry.setAttribute("position", quad.attributes.position.clone());
11809
- geometry.setAttribute("uv", quad.attributes.uv.clone());
11810
- const indexes = new Float32Array(PARTICLE_COUNT);
11811
- for (let i = 0; i < PARTICLE_COUNT; i += 1) {
11812
- indexes[i] = i;
11813
- }
11814
- geometry.setAttribute("instanceIndex", new InstancedBufferAttribute(indexes, 1));
11815
- geometry.instanceCount = PARTICLE_COUNT;
11816
- quad.dispose();
11817
- return geometry;
11818
- }
11819
- function ParticleOverlay({
11820
- snapshot,
11821
- transition,
11822
- running,
11823
- runId,
11824
- onFinish
11825
- }) {
11826
- const { camera } = useThree17();
11827
- const meshRef = useRef26(null);
11828
- const startRef = useRef26(null);
11829
- const finishedRef = useRef26(false);
11830
- const directionRef = useRef26(new Vector310());
11831
- const geometry = useMemo18(() => createParticleGeometry(), []);
11832
- const material = useMemo18(
11833
- () => new ShaderMaterial2({
11834
- transparent: true,
11835
- depthTest: false,
11836
- depthWrite: false,
11837
- side: DoubleSide2,
11838
- uniforms: {
11839
- map: { value: snapshot.texture },
11840
- progress: { value: 0 },
11841
- grid: { value: new Vector24(PARTICLE_GRID, PARTICLE_GRID) }
11842
- },
11843
- vertexShader: PARTICLE_VERTEX_SHADER,
11844
- fragmentShader: PARTICLE_FRAGMENT_SHADER
11845
- }),
11846
- [snapshot.texture]
11847
- );
11848
- useEffect26(() => () => geometry.dispose(), [geometry]);
11849
- useEffect26(() => () => material.dispose(), [material]);
11850
- useEffect26(() => {
11851
- startRef.current = null;
11852
- finishedRef.current = false;
11853
- material.uniforms.progress.value = 0;
11854
- }, [material, runId]);
11855
- useFrame10((state) => {
11856
- const mesh = meshRef.current;
11857
- if (!mesh || !isPerspectiveCamera(camera)) {
11858
- return;
11859
- }
11860
- placeFullscreenOverlay(mesh, camera, directionRef.current);
11861
- if (!running || finishedRef.current) {
11862
- return;
11863
- }
11864
- const next = overlayProgress(state.clock.elapsedTime, transition.duration, startRef.current);
11865
- startRef.current = next.startTime;
11866
- material.uniforms.progress.value = next.progress;
11867
- if (next.progress === 1) {
11868
- finishedRef.current = true;
11869
- onFinish();
11870
- }
11871
- });
11872
- return /* @__PURE__ */ jsx19(
11873
- "mesh",
11874
- {
11875
- ref: meshRef,
11876
- frustumCulled: false,
11877
- geometry,
11878
- material,
11879
- renderOrder: OVERLAY_RENDER_ORDER
11880
- }
11881
- );
11882
- }
11883
-
11884
- // src/scene-transitions/snapshot-overlay.tsx
11885
- import { useFrame as useFrame11, useThree as useThree18 } from "@react-three/fiber";
11886
- import { useEffect as useEffect27, useMemo as useMemo19, useRef as useRef27 } from "react";
11887
- import { Vector3 as Vector311 } from "three";
11888
-
11889
11808
  // src/scene-transitions/snapshot-shaders.ts
11890
- import { DoubleSide as DoubleSide3, ShaderMaterial as ShaderMaterial3, Vector2 as Vector25 } from "three";
11891
11809
  var SNAPSHOT_VERTEX_SHADER = `
11892
11810
  varying vec2 vUv;
11893
11811
  void main() {
@@ -12147,50 +12065,285 @@ var SNAPSHOT_FRAGMENT_SHADERS = {
12147
12065
  `)
12148
12066
  };
12149
12067
  function createSnapshotMaterial(preset, texture) {
12150
- return new ShaderMaterial3({
12068
+ return new ShaderMaterial2({
12151
12069
  transparent: true,
12152
12070
  depthTest: false,
12153
12071
  depthWrite: false,
12154
- side: DoubleSide3,
12072
+ side: DoubleSide2,
12155
12073
  uniforms: {
12156
12074
  map: { value: texture },
12157
12075
  progress: { value: 0 },
12158
- resolution: { value: new Vector25(1, 1) }
12076
+ resolution: { value: new Vector24(1, 1) }
12159
12077
  },
12160
12078
  vertexShader: SNAPSHOT_VERTEX_SHADER,
12161
12079
  fragmentShader: SNAPSHOT_FRAGMENT_SHADERS[preset]
12162
12080
  });
12163
12081
  }
12164
12082
 
12165
- // src/scene-transitions/snapshot-overlay.tsx
12166
- import { jsx as jsx20, jsxs as jsxs12 } from "react/jsx-runtime";
12167
- function SnapshotOverlay({
12083
+ // src/scene-transitions/snapshot-hold.tsx
12084
+ import { jsx as jsx19, jsxs as jsxs12 } from "react/jsx-runtime";
12085
+ function SnapshotHold({ snapshot }) {
12086
+ const { camera, gl } = useThree17();
12087
+ const meshRef = useRef26(null);
12088
+ const directionRef = useRef26(new Vector310());
12089
+ const material = useMemo18(
12090
+ () => createSnapshotMaterial("crossfade", snapshot.texture),
12091
+ [snapshot.texture]
12092
+ );
12093
+ useEffect26(() => () => material.dispose(), [material]);
12094
+ useFrame10(() => {
12095
+ const mesh = meshRef.current;
12096
+ if (!mesh || !isPerspectiveCamera(camera)) {
12097
+ return;
12098
+ }
12099
+ placeFullscreenOverlay(mesh, camera, directionRef.current);
12100
+ const context = gl.getContext();
12101
+ material.uniforms.resolution.value.set(
12102
+ context.drawingBufferWidth,
12103
+ context.drawingBufferHeight
12104
+ );
12105
+ material.uniforms.progress.value = 0;
12106
+ });
12107
+ return /* @__PURE__ */ jsxs12("mesh", { frustumCulled: false, ref: meshRef, renderOrder: OVERLAY_RENDER_ORDER, children: [
12108
+ /* @__PURE__ */ jsx19("primitive", { attach: "geometry", object: FULLSCREEN_PLANE }),
12109
+ /* @__PURE__ */ jsx19("primitive", { attach: "material", object: material })
12110
+ ] });
12111
+ }
12112
+
12113
+ // src/scene-transition-policy.ts
12114
+ function pendingSceneUsesBaseLayer(phase, isPending) {
12115
+ return isPending && (phase === "preloading" || phase === "capturing");
12116
+ }
12117
+ function normalizeTransitionWaitMs(value) {
12118
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
12119
+ return 0;
12120
+ }
12121
+ return value;
12122
+ }
12123
+ function planDetailHold(input) {
12124
+ if (input.waitMs <= 0) {
12125
+ return null;
12126
+ }
12127
+ return {
12128
+ generation: input.generation,
12129
+ sceneId: input.sceneId,
12130
+ deadline: input.now + input.waitMs
12131
+ };
12132
+ }
12133
+ function acceptDetailWait(wait, signal) {
12134
+ if (!wait) {
12135
+ return { wait: null, start: false };
12136
+ }
12137
+ switch (signal.kind) {
12138
+ case "ready":
12139
+ if (signal.generation !== wait.generation || signal.sceneId !== wait.sceneId) {
12140
+ return { wait, start: false };
12141
+ }
12142
+ return { wait: null, start: true };
12143
+ case "timeout":
12144
+ if (signal.generation !== wait.generation || signal.now < wait.deadline) {
12145
+ return { wait, start: false };
12146
+ }
12147
+ return { wait: null, start: true };
12148
+ case "cancel":
12149
+ if (signal.generation !== wait.generation) {
12150
+ return { wait, start: false };
12151
+ }
12152
+ return { wait: null, start: false };
12153
+ default: {
12154
+ const exhaustive = signal;
12155
+ return exhaustive;
12156
+ }
12157
+ }
12158
+ }
12159
+ function phaseAfterSnapshot(preset, hold) {
12160
+ if (hold) {
12161
+ return "awaitingDetail";
12162
+ }
12163
+ if (preset === "none") {
12164
+ return "idle";
12165
+ }
12166
+ return "transitioning";
12167
+ }
12168
+
12169
+ // src/scene-transitions/particle-overlay.tsx
12170
+ import { useFrame as useFrame11, useThree as useThree18 } from "@react-three/fiber";
12171
+ import { useEffect as useEffect27, useMemo as useMemo19, useRef as useRef27 } from "react";
12172
+ import {
12173
+ DoubleSide as DoubleSide3,
12174
+ InstancedBufferAttribute,
12175
+ InstancedBufferGeometry,
12176
+ PlaneGeometry as PlaneGeometry3,
12177
+ ShaderMaterial as ShaderMaterial3,
12178
+ Vector2 as Vector25,
12179
+ Vector3 as Vector311
12180
+ } from "three";
12181
+ import { jsx as jsx20 } from "react/jsx-runtime";
12182
+ var PARTICLE_GRID = 48;
12183
+ var PARTICLE_COUNT = PARTICLE_GRID * PARTICLE_GRID;
12184
+ var PARTICLE_VERTEX_SHADER = `
12185
+ attribute float instanceIndex;
12186
+ uniform float progress;
12187
+ uniform vec2 grid;
12188
+ varying vec2 vUv;
12189
+ varying float vAlpha;
12190
+ ${GLSL_COMMON}
12191
+
12192
+ void main() {
12193
+ float id = instanceIndex;
12194
+ float gx = mod(id, grid.x);
12195
+ float gy = floor(id / grid.x);
12196
+ vec2 cell = vec2(gx, gy);
12197
+ float h = hash(cell);
12198
+ float h2 = hash(cell + 19.2);
12199
+ float h3 = hash(cell + 7.7);
12200
+ vec2 randomDir = normalize(vec2(h, h2) * 2.0 - 1.0 + 1e-5);
12201
+ vec2 fromCenter = (cell + 0.5) / grid - 0.5 + 1e-5;
12202
+ vec2 dir = normalize(mix(randomDir, normalize(fromCenter), 0.65));
12203
+ float delay = h3 * 0.28;
12204
+ float lt = clamp((progress - delay) / max(1.0 - delay, 0.001), 0.0, 1.0);
12205
+ float explode = lt * lt;
12206
+ float scale = mix(1.0, 0.18, explode);
12207
+ float angle = (h * 2.0 - 1.0) * explode * 4.2;
12208
+ float ca = cos(angle);
12209
+ float sa = sin(angle);
12210
+ vec2 cellSize = 1.0 / grid;
12211
+ vec2 local = position.xy * cellSize * scale;
12212
+ vec2 rotated = vec2(local.x * ca - local.y * sa, local.x * sa + local.y * ca);
12213
+ vec2 planeCenter = (cell + 0.5) / grid - 0.5;
12214
+ vec2 exploded = planeCenter + dir * explode * 0.9;
12215
+ vec3 pos = vec3(exploded + rotated, -explode * 0.14);
12216
+ vUv = (cell + uv) / grid;
12217
+ vAlpha = 1.0 - explode;
12218
+ gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
12219
+ }
12220
+ `;
12221
+ var PARTICLE_FRAGMENT_SHADER = `
12222
+ uniform sampler2D map;
12223
+ varying vec2 vUv;
12224
+ varying float vAlpha;
12225
+
12226
+ void main() {
12227
+ vec4 old = texture2D(map, vUv);
12228
+ old.rgb *= 1.0 + 0.22 * (1.0 - vAlpha);
12229
+ gl_FragColor = vec4(old.rgb, old.a * vAlpha);
12230
+ #include <colorspace_fragment>
12231
+ }
12232
+ `;
12233
+ function createParticleGeometry() {
12234
+ const quad = new PlaneGeometry3(1, 1);
12235
+ const geometry = new InstancedBufferGeometry();
12236
+ if (quad.index) {
12237
+ geometry.setIndex(quad.index.clone());
12238
+ }
12239
+ geometry.setAttribute("position", quad.attributes.position.clone());
12240
+ geometry.setAttribute("uv", quad.attributes.uv.clone());
12241
+ const indexes = new Float32Array(PARTICLE_COUNT);
12242
+ for (let i = 0; i < PARTICLE_COUNT; i += 1) {
12243
+ indexes[i] = i;
12244
+ }
12245
+ geometry.setAttribute("instanceIndex", new InstancedBufferAttribute(indexes, 1));
12246
+ geometry.instanceCount = PARTICLE_COUNT;
12247
+ quad.dispose();
12248
+ return geometry;
12249
+ }
12250
+ function ParticleOverlay({
12168
12251
  snapshot,
12169
12252
  transition,
12170
12253
  running,
12171
12254
  runId,
12172
12255
  onFinish
12173
12256
  }) {
12174
- const { camera, gl } = useThree18();
12257
+ const { camera } = useThree18();
12175
12258
  const meshRef = useRef27(null);
12176
12259
  const startRef = useRef27(null);
12177
12260
  const finishedRef = useRef27(false);
12178
12261
  const directionRef = useRef27(new Vector311());
12179
- const material = useMemo19(() => {
12262
+ const geometry = useMemo19(() => createParticleGeometry(), []);
12263
+ const material = useMemo19(
12264
+ () => new ShaderMaterial3({
12265
+ transparent: true,
12266
+ depthTest: false,
12267
+ depthWrite: false,
12268
+ side: DoubleSide3,
12269
+ uniforms: {
12270
+ map: { value: snapshot.texture },
12271
+ progress: { value: 0 },
12272
+ grid: { value: new Vector25(PARTICLE_GRID, PARTICLE_GRID) }
12273
+ },
12274
+ vertexShader: PARTICLE_VERTEX_SHADER,
12275
+ fragmentShader: PARTICLE_FRAGMENT_SHADER
12276
+ }),
12277
+ [snapshot.texture]
12278
+ );
12279
+ useEffect27(() => () => geometry.dispose(), [geometry]);
12280
+ useEffect27(() => () => material.dispose(), [material]);
12281
+ useEffect27(() => {
12282
+ startRef.current = null;
12283
+ finishedRef.current = false;
12284
+ material.uniforms.progress.value = 0;
12285
+ }, [material, runId]);
12286
+ useFrame11((state) => {
12287
+ const mesh = meshRef.current;
12288
+ if (!mesh || !isPerspectiveCamera(camera)) {
12289
+ return;
12290
+ }
12291
+ placeFullscreenOverlay(mesh, camera, directionRef.current);
12292
+ if (!running || finishedRef.current) {
12293
+ return;
12294
+ }
12295
+ const next = overlayProgress(state.clock.elapsedTime, transition.duration, startRef.current);
12296
+ startRef.current = next.startTime;
12297
+ material.uniforms.progress.value = next.progress;
12298
+ if (next.progress === 1) {
12299
+ finishedRef.current = true;
12300
+ onFinish();
12301
+ }
12302
+ });
12303
+ return /* @__PURE__ */ jsx20(
12304
+ "mesh",
12305
+ {
12306
+ ref: meshRef,
12307
+ frustumCulled: false,
12308
+ geometry,
12309
+ material,
12310
+ renderOrder: OVERLAY_RENDER_ORDER
12311
+ }
12312
+ );
12313
+ }
12314
+
12315
+ // src/scene-transitions/snapshot-overlay.tsx
12316
+ import { useFrame as useFrame12, useThree as useThree19 } from "@react-three/fiber";
12317
+ import { useEffect as useEffect28, useMemo as useMemo20, useRef as useRef28 } from "react";
12318
+ import { Vector3 as Vector312 } from "three";
12319
+ import { jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
12320
+ function SnapshotOverlay({
12321
+ snapshot,
12322
+ transition,
12323
+ running,
12324
+ runId,
12325
+ onFinish
12326
+ }) {
12327
+ const { camera, gl } = useThree19();
12328
+ const meshRef = useRef28(null);
12329
+ const startRef = useRef28(null);
12330
+ const finishedRef = useRef28(false);
12331
+ const directionRef = useRef28(new Vector312());
12332
+ const material = useMemo20(() => {
12180
12333
  if (!isSnapshotTransition(transition.preset)) {
12181
12334
  return null;
12182
12335
  }
12183
12336
  return createSnapshotMaterial(transition.preset, snapshot.texture);
12184
12337
  }, [snapshot.texture, transition.preset]);
12185
- useEffect27(() => () => material?.dispose(), [material]);
12186
- useEffect27(() => {
12338
+ useEffect28(() => () => material?.dispose(), [material]);
12339
+ useEffect28(() => {
12187
12340
  startRef.current = null;
12188
12341
  finishedRef.current = false;
12189
12342
  if (material) {
12190
12343
  material.uniforms.progress.value = 0;
12191
12344
  }
12192
12345
  }, [material, runId]);
12193
- useFrame11((state) => {
12346
+ useFrame12((state) => {
12194
12347
  const mesh = meshRef.current;
12195
12348
  if (!mesh || !material || !isPerspectiveCamera(camera)) {
12196
12349
  return;
@@ -12212,21 +12365,21 @@ function SnapshotOverlay({
12212
12365
  if (!material) {
12213
12366
  return null;
12214
12367
  }
12215
- return /* @__PURE__ */ jsxs12("mesh", { ref: meshRef, renderOrder: OVERLAY_RENDER_ORDER, frustumCulled: false, children: [
12216
- /* @__PURE__ */ jsx20("primitive", { attach: "geometry", object: FULLSCREEN_PLANE }),
12217
- /* @__PURE__ */ jsx20("primitive", { attach: "material", object: material })
12368
+ return /* @__PURE__ */ jsxs13("mesh", { ref: meshRef, renderOrder: OVERLAY_RENDER_ORDER, frustumCulled: false, children: [
12369
+ /* @__PURE__ */ jsx21("primitive", { attach: "geometry", object: FULLSCREEN_PLANE }),
12370
+ /* @__PURE__ */ jsx21("primitive", { attach: "material", object: material })
12218
12371
  ] });
12219
12372
  }
12220
12373
 
12221
12374
  // src/scene-transitions/transition-overlay.tsx
12222
- import { jsx as jsx21 } from "react/jsx-runtime";
12375
+ import { jsx as jsx22 } from "react/jsx-runtime";
12223
12376
  function TransitionOverlay(props) {
12224
12377
  const { preset } = props.transition;
12225
12378
  switch (preset) {
12226
12379
  case "none":
12227
12380
  return null;
12228
12381
  case "particles":
12229
- return /* @__PURE__ */ jsx21(ParticleOverlay, { ...props });
12382
+ return /* @__PURE__ */ jsx22(ParticleOverlay, { ...props });
12230
12383
  case "crossfade":
12231
12384
  case "zoom":
12232
12385
  case "blackout":
@@ -12254,7 +12407,7 @@ function TransitionOverlay(props) {
12254
12407
  case "zoomBlur":
12255
12408
  case "hexDissolve":
12256
12409
  case "filmBurn":
12257
- return /* @__PURE__ */ jsx21(SnapshotOverlay, { ...props });
12410
+ return /* @__PURE__ */ jsx22(SnapshotOverlay, { ...props });
12258
12411
  default: {
12259
12412
  const exhaustive = preset;
12260
12413
  void exhaustive;
@@ -12264,14 +12417,14 @@ function TransitionOverlay(props) {
12264
12417
  }
12265
12418
 
12266
12419
  // src/tile/tile.tsx
12267
- import { useFrame as useFrame12, useThree as useThree19 } from "@react-three/fiber";
12268
- import { memo as memo2, useEffect as useEffect28, useMemo as useMemo20, useRef as useRef28, useState as useState13 } from "react";
12420
+ import { useFrame as useFrame13, useThree as useThree20 } from "@react-three/fiber";
12421
+ import { memo as memo2, useEffect as useEffect29, useMemo as useMemo21, useRef as useRef29, useState as useState13 } from "react";
12269
12422
  import {
12270
12423
  Frustum as Frustum2,
12271
12424
  Matrix4 as Matrix43,
12272
12425
  PlaneGeometry as PlaneGeometry4,
12273
12426
  PerspectiveCamera as PerspectiveCamera5,
12274
- Vector3 as Vector313
12427
+ Vector3 as Vector314
12275
12428
  } from "three";
12276
12429
 
12277
12430
  // src/tile/face-layout.ts
@@ -12279,7 +12432,7 @@ import {
12279
12432
  Box3 as Box32,
12280
12433
  Euler as Euler3,
12281
12434
  Quaternion as Quaternion2,
12282
- Vector3 as Vector312
12435
+ Vector3 as Vector313
12283
12436
  } from "three";
12284
12437
  var CUBE_FACES = ["f", "r", "b", "l", "u", "d"];
12285
12438
  var PREVIEW_FACE_ORDER = ["l", "f", "r", "b", "u", "d"];
@@ -12343,12 +12496,12 @@ function getTileBoundingBox(address, radius = CUBE_RADIUS) {
12343
12496
  const halfWidth = local.width / 2;
12344
12497
  const halfHeight = local.height / 2;
12345
12498
  const quaternion = getFaceQuaternion(address.face);
12346
- const position = new Vector312(...transform.position);
12499
+ const position = new Vector313(...transform.position);
12347
12500
  const corners = [
12348
- new Vector312(local.x - halfWidth, local.y - halfHeight, 0),
12349
- new Vector312(local.x + halfWidth, local.y - halfHeight, 0),
12350
- new Vector312(local.x - halfWidth, local.y + halfHeight, 0),
12351
- new Vector312(local.x + halfWidth, local.y + halfHeight, 0)
12501
+ new Vector313(local.x - halfWidth, local.y - halfHeight, 0),
12502
+ new Vector313(local.x + halfWidth, local.y - halfHeight, 0),
12503
+ new Vector313(local.x - halfWidth, local.y + halfHeight, 0),
12504
+ new Vector313(local.x + halfWidth, local.y + halfHeight, 0)
12352
12505
  ];
12353
12506
  for (const corner of corners) {
12354
12507
  corner.applyQuaternion(quaternion).add(position);
@@ -12456,11 +12609,27 @@ function resolveTemplateUrl(template, address) {
12456
12609
  }
12457
12610
 
12458
12611
  // src/tile/tile.tsx
12459
- import { jsx as jsx22, jsxs as jsxs13 } from "react/jsx-runtime";
12612
+ import { jsx as jsx23, jsxs as jsxs14 } from "react/jsx-runtime";
12460
12613
  var MAX_LOD_UPDATE_INTERVAL_MS = 100;
12461
12614
  var FAST_ROTATION_THRESHOLD_RADIANS = Math.PI / 180;
12462
12615
  var FAST_FOV_THRESHOLD_DEGREES = 0.5;
12463
12616
  var VIEW_CHANGE_EPSILON = 1e-4;
12617
+ function decideTileLodUpdate(input) {
12618
+ if (input.loadMode === "preview") {
12619
+ return false;
12620
+ }
12621
+ const loadModeChanged = input.loadMode !== input.trackedLoadMode;
12622
+ const viewChanged = input.visibilityDirty || loadModeChanged || input.viewportChanged || input.rotationDelta > VIEW_CHANGE_EPSILON || input.fovDelta > VIEW_CHANGE_EPSILON;
12623
+ if (!viewChanged) {
12624
+ return false;
12625
+ }
12626
+ const movingQuickly = input.rotationDelta >= FAST_ROTATION_THRESHOLD_RADIANS || input.fovDelta >= FAST_FOV_THRESHOLD_DEGREES;
12627
+ const immediate = input.visibilityDirty || loadModeChanged || input.viewportChanged || movingQuickly;
12628
+ if (!immediate && input.now - input.lastUpdateAt < MAX_LOD_UPDATE_INTERVAL_MS) {
12629
+ return false;
12630
+ }
12631
+ return true;
12632
+ }
12464
12633
  var VISIBILITY_FOV_PADDING_DEGREES = 8;
12465
12634
  var PREVIEW_RADIUS = CUBE_RADIUS + 0.05;
12466
12635
  var SHARED_TILE_GEOMETRY = new PlaneGeometry4(1, 1);
@@ -12469,7 +12638,7 @@ function PreviewFace({
12469
12638
  texture,
12470
12639
  faceOrder
12471
12640
  }) {
12472
- const geometry = useMemo20(() => {
12641
+ const geometry = useMemo21(() => {
12473
12642
  const nextGeometry = new PlaneGeometry4(
12474
12643
  PREVIEW_RADIUS * 2,
12475
12644
  PREVIEW_RADIUS * 2
@@ -12484,21 +12653,21 @@ function PreviewFace({
12484
12653
  uv.needsUpdate = true;
12485
12654
  return nextGeometry;
12486
12655
  }, [face, faceOrder]);
12487
- useEffect28(
12656
+ useEffect29(
12488
12657
  () => () => {
12489
12658
  geometry.dispose();
12490
12659
  },
12491
12660
  [geometry]
12492
12661
  );
12493
12662
  const transform = getFaceTransform(face, PREVIEW_RADIUS);
12494
- return /* @__PURE__ */ jsx22(
12663
+ return /* @__PURE__ */ jsx23(
12495
12664
  "mesh",
12496
12665
  {
12497
12666
  geometry,
12498
12667
  position: transform.position,
12499
12668
  renderOrder: -100,
12500
12669
  rotation: transform.rotation,
12501
- children: /* @__PURE__ */ jsx22(
12670
+ children: /* @__PURE__ */ jsx23(
12502
12671
  PanoBasicMaterial,
12503
12672
  {
12504
12673
  depthTest: false,
@@ -12514,7 +12683,7 @@ function PreviewCube({
12514
12683
  texture,
12515
12684
  faceOrder
12516
12685
  }) {
12517
- return CUBE_FACES.map((face) => /* @__PURE__ */ jsx22(
12686
+ return CUBE_FACES.map((face) => /* @__PURE__ */ jsx23(
12518
12687
  PreviewFace,
12519
12688
  {
12520
12689
  face,
@@ -12538,14 +12707,14 @@ var TileMesh = memo2(function TileMesh2({
12538
12707
  if (!snapshot.texture) {
12539
12708
  return null;
12540
12709
  }
12541
- return /* @__PURE__ */ jsx22("group", { position: transform.position, rotation: transform.rotation, children: /* @__PURE__ */ jsx22(
12710
+ return /* @__PURE__ */ jsx23("group", { position: transform.position, rotation: transform.rotation, children: /* @__PURE__ */ jsx23(
12542
12711
  "mesh",
12543
12712
  {
12544
12713
  geometry: SHARED_TILE_GEOMETRY,
12545
12714
  position: [layout.x, layout.y, 0],
12546
12715
  renderOrder,
12547
12716
  scale: [layout.width, layout.height, 1],
12548
- children: /* @__PURE__ */ jsx22(
12717
+ children: /* @__PURE__ */ jsx23(
12549
12718
  PanoBasicMaterial,
12550
12719
  {
12551
12720
  depthTest: false,
@@ -12562,7 +12731,7 @@ var TileLayerMeshes = memo2(function TileLayerMeshes2({
12562
12731
  manager,
12563
12732
  resolveUrl
12564
12733
  }) {
12565
- return layer.addresses.map((address) => /* @__PURE__ */ jsx22(
12734
+ return layer.addresses.map((address) => /* @__PURE__ */ jsx23(
12566
12735
  TileMesh,
12567
12736
  {
12568
12737
  address,
@@ -12662,8 +12831,8 @@ function parentAddresses(child, parentLevel, parentFaceSize, tileSize) {
12662
12831
  return addresses;
12663
12832
  }
12664
12833
  function centerFacingAddress(candidates, camera) {
12665
- const direction = camera.getWorldDirection(new Vector313());
12666
- const center = new Vector313();
12834
+ const direction = camera.getWorldDirection(new Vector314());
12835
+ const center = new Vector314();
12667
12836
  let bestCandidate = candidates[0];
12668
12837
  let bestAlignment = -Infinity;
12669
12838
  for (const candidate of candidates) {
@@ -12728,11 +12897,11 @@ function Tile({
12728
12897
  onTileError,
12729
12898
  onLevelChange
12730
12899
  }) {
12731
- const { camera, gl, size } = useThree19();
12732
- const multiresConfig = useMemo20(() => parseMultires(multires), [multires]);
12900
+ const { camera, gl, size } = useThree20();
12901
+ const multiresConfig = useMemo21(() => parseMultires(multires), [multires]);
12733
12902
  const { levels, tileSize } = multiresConfig;
12734
12903
  const multiresToken = `${tileSize}:${levels.join(",")}`;
12735
- const candidatesByLevel = useMemo20(
12904
+ const candidatesByLevel = useMemo21(
12736
12905
  () => buildTileCandidates(levels, tileSize),
12737
12906
  [levels, tileSize]
12738
12907
  );
@@ -12744,13 +12913,13 @@ function Tile({
12744
12913
  onPreviewError
12745
12914
  );
12746
12915
  const sharedManager = useSharedTileTextureManager();
12747
- const progressRef = useRef28(onLoadProgress);
12748
- const errorRef = useRef28(onTileError);
12749
- const levelChangeRef = useRef28(onLevelChange);
12916
+ const progressRef = useRef29(onLoadProgress);
12917
+ const errorRef = useRef29(onTileError);
12918
+ const levelChangeRef = useRef29(onLevelChange);
12750
12919
  progressRef.current = onLoadProgress;
12751
12920
  errorRef.current = onTileError;
12752
12921
  levelChangeRef.current = onLevelChange;
12753
- const ownedManager = useMemo20(
12922
+ const ownedManager = useMemo21(
12754
12923
  () => new TileTextureManager({
12755
12924
  anisotropy,
12756
12925
  maxBytes: Math.max(1, maxTextureMemoryMb) * 1024 * 1024,
@@ -12771,7 +12940,7 @@ function Tile({
12771
12940
  ]
12772
12941
  );
12773
12942
  const manager = sharedManager ?? ownedManager;
12774
- useEffect28(() => {
12943
+ useEffect29(() => {
12775
12944
  manager.resume();
12776
12945
  return () => {
12777
12946
  if (manager === ownedManager) {
@@ -12781,11 +12950,11 @@ function Tile({
12781
12950
  queueMicrotask(() => manager.releaseUnused());
12782
12951
  };
12783
12952
  }, [manager, ownedManager]);
12784
- const readyRef = useRef28(false);
12785
- useEffect28(() => {
12953
+ const readyRef = useRef29(false);
12954
+ useEffect29(() => {
12786
12955
  readyRef.current = false;
12787
12956
  }, [effectivePreviewUrl]);
12788
- useEffect28(() => {
12957
+ useEffect29(() => {
12789
12958
  if (!previewTexture || readyRef.current) {
12790
12959
  return;
12791
12960
  }
@@ -12793,7 +12962,7 @@ function Tile({
12793
12962
  onReady?.();
12794
12963
  }, [onReady, previewTexture]);
12795
12964
  const template = urlTemplate ?? buildDefaultTileUrlTemplate();
12796
- const resolveUrl = useMemo20(
12965
+ const resolveUrl = useMemo21(
12797
12966
  () => (address) => {
12798
12967
  const relativePath = resolveTileUrl ? resolveTileUrl(address) : resolveTemplateUrl(template, address);
12799
12968
  return resolveRelativeTileUrl(baseUrl, relativePath);
@@ -12801,23 +12970,29 @@ function Tile({
12801
12970
  [baseUrl, resolveTileUrl, template]
12802
12971
  );
12803
12972
  const [layers, setLayers] = useState13([]);
12804
- const layerTokenRef = useRef28("");
12805
- const currentLevelRef = useRef28(1);
12806
- const lastUpdateAtRef = useRef28(-Infinity);
12807
- const visibilityDirtyRef = useRef28(true);
12808
- const lastVisibilityQuaternionRef = useRef28(camera.quaternion.clone());
12809
- const lastVisibilityFovRef = useRef28(Number.NaN);
12810
- const lastViewportRef = useRef28({ width: 0, height: 0, dpr: 0 });
12811
- const frustumRef = useRef28(new Frustum2());
12812
- const projectionMatrixRef = useRef28(new Matrix43());
12813
- const visibilityCameraRef = useRef28(new PerspectiveCamera5());
12814
- useEffect28(() => {
12973
+ const layerTokenRef = useRef29("");
12974
+ const currentLevelRef = useRef29(1);
12975
+ const lastUpdateAtRef = useRef29(-Infinity);
12976
+ const visibilityDirtyRef = useRef29(true);
12977
+ const lastVisibilityQuaternionRef = useRef29(camera.quaternion.clone());
12978
+ const lastVisibilityFovRef = useRef29(Number.NaN);
12979
+ const lastViewportRef = useRef29({ width: 0, height: 0, dpr: 0 });
12980
+ const frustumRef = useRef29(new Frustum2());
12981
+ const projectionMatrixRef = useRef29(new Matrix43());
12982
+ const visibilityCameraRef = useRef29(new PerspectiveCamera5());
12983
+ const trackedLoadModeRef = useRef29(loadMode);
12984
+ const targetKeysRef = useRef29([]);
12985
+ const detailTokenRef = useRef29("");
12986
+ const detailReporter = useSceneDetailReporter();
12987
+ const detailReporterRef = useRef29(detailReporter);
12988
+ detailReporterRef.current = detailReporter;
12989
+ useEffect29(() => {
12815
12990
  currentLevelRef.current = 1;
12816
12991
  layerTokenRef.current = "";
12817
12992
  visibilityDirtyRef.current = true;
12818
12993
  setLayers([]);
12819
12994
  }, [manager, multiresToken]);
12820
- useEffect28(() => {
12995
+ useEffect29(() => {
12821
12996
  if (loadMode !== "preview") {
12822
12997
  return;
12823
12998
  }
@@ -12831,11 +13006,14 @@ function Tile({
12831
13006
  setLayers(nextLayers);
12832
13007
  }
12833
13008
  };
12834
- useFrame12(() => {
12835
- if (loadMode === "preview") {
13009
+ useFrame13(() => {
13010
+ if (!(camera instanceof PerspectiveCamera5)) {
12836
13011
  return;
12837
13012
  }
12838
- if (!(camera instanceof PerspectiveCamera5)) {
13013
+ if (loadMode === "preview") {
13014
+ trackedLoadModeRef.current = "preview";
13015
+ targetKeysRef.current = [];
13016
+ publishSceneDetail(detailReporterRef.current, detailTokenRef, false);
12839
13017
  return;
12840
13018
  }
12841
13019
  const now = performance.now();
@@ -12843,63 +13021,78 @@ function Tile({
12843
13021
  const rotationDelta = lastVisibilityQuaternionRef.current.angleTo(
12844
13022
  camera.quaternion
12845
13023
  );
12846
- const fovDelta = Number.isFinite(lastVisibilityFovRef.current) ? Math.abs(camera.fov - lastVisibilityFovRef.current) : Infinity;
12847
- const lastViewport = lastViewportRef.current;
12848
- const viewportChanged = lastViewport.width !== size.width || lastViewport.height !== size.height || lastViewport.dpr !== pixelRatio;
12849
- const viewChanged = visibilityDirtyRef.current || viewportChanged || rotationDelta > VIEW_CHANGE_EPSILON || fovDelta > VIEW_CHANGE_EPSILON;
12850
- const movingQuickly = rotationDelta >= FAST_ROTATION_THRESHOLD_RADIANS || fovDelta >= FAST_FOV_THRESHOLD_DEGREES;
12851
- if (!viewChanged) {
12852
- return;
12853
- }
12854
- const needsImmediateUpdate = visibilityDirtyRef.current || viewportChanged || movingQuickly;
12855
- if (!needsImmediateUpdate && now - lastUpdateAtRef.current < MAX_LOD_UPDATE_INTERVAL_MS) {
12856
- return;
12857
- }
12858
- lastUpdateAtRef.current = now;
12859
- const targetLevel = loadMode === "base" ? 1 : getPreferredLevel(
12860
- levels,
12861
- size.height,
12862
- pixelRatio,
12863
- camera.fov,
12864
- currentLevelRef.current
12865
- );
12866
- if (targetLevel !== currentLevelRef.current) {
12867
- currentLevelRef.current = targetLevel;
12868
- levelChangeRef.current?.(targetLevel);
12869
- }
12870
- const visibilityCamera = visibilityCameraRef.current;
12871
- visibilityCamera.copy(camera, false);
12872
- visibilityCamera.fov = Math.min(
12873
- 179,
12874
- camera.fov + VISIBILITY_FOV_PADDING_DEGREES
12875
- );
12876
- visibilityCamera.aspect = camera.aspect;
12877
- updateVisibilityFrustum(
12878
- visibilityCamera,
12879
- projectionMatrixRef.current,
12880
- frustumRef.current
12881
- );
12882
- const nextLayers = buildLayers(
12883
- targetLevel,
12884
- levels,
12885
- tileSize,
12886
- frustumRef.current,
12887
- camera,
12888
- candidatesByLevel
13024
+ const fovDelta = Number.isFinite(lastVisibilityFovRef.current) ? Math.abs(camera.fov - lastVisibilityFovRef.current) : Infinity;
13025
+ const lastViewport = lastViewportRef.current;
13026
+ const viewportChanged = lastViewport.width !== size.width || lastViewport.height !== size.height || lastViewport.dpr !== pixelRatio;
13027
+ const updateLod = decideTileLodUpdate({
13028
+ loadMode,
13029
+ trackedLoadMode: trackedLoadModeRef.current,
13030
+ now,
13031
+ lastUpdateAt: lastUpdateAtRef.current,
13032
+ visibilityDirty: visibilityDirtyRef.current,
13033
+ viewportChanged,
13034
+ rotationDelta,
13035
+ fovDelta
13036
+ });
13037
+ if (updateLod) {
13038
+ trackedLoadModeRef.current = loadMode;
13039
+ lastUpdateAtRef.current = now;
13040
+ const targetLevel = loadMode === "base" ? 1 : getPreferredLevel(
13041
+ levels,
13042
+ size.height,
13043
+ pixelRatio,
13044
+ camera.fov,
13045
+ currentLevelRef.current
13046
+ );
13047
+ if (targetLevel !== currentLevelRef.current) {
13048
+ currentLevelRef.current = targetLevel;
13049
+ levelChangeRef.current?.(targetLevel);
13050
+ }
13051
+ const visibilityCamera = visibilityCameraRef.current;
13052
+ visibilityCamera.copy(camera, false);
13053
+ visibilityCamera.fov = Math.min(
13054
+ 179,
13055
+ camera.fov + VISIBILITY_FOV_PADDING_DEGREES
13056
+ );
13057
+ visibilityCamera.aspect = camera.aspect;
13058
+ updateVisibilityFrustum(
13059
+ visibilityCamera,
13060
+ projectionMatrixRef.current,
13061
+ frustumRef.current
13062
+ );
13063
+ const nextLayers = buildLayers(
13064
+ targetLevel,
13065
+ levels,
13066
+ tileSize,
13067
+ frustumRef.current,
13068
+ camera,
13069
+ candidatesByLevel
13070
+ );
13071
+ visibilityDirtyRef.current = false;
13072
+ lastVisibilityQuaternionRef.current.copy(camera.quaternion);
13073
+ lastVisibilityFovRef.current = camera.fov;
13074
+ lastViewportRef.current = {
13075
+ width: size.width,
13076
+ height: size.height,
13077
+ dpr: pixelRatio
13078
+ };
13079
+ const targetLayer = nextLayers.find((layer) => layer.level === targetLevel);
13080
+ targetKeysRef.current = loadMode === "full" ? (targetLayer?.addresses ?? []).map(
13081
+ (address) => `${resolveUrl(address)}\0${tileKey(address)}`
13082
+ ) : [];
13083
+ commitLayers(nextLayers);
13084
+ }
13085
+ publishSceneDetail(
13086
+ detailReporterRef.current,
13087
+ detailTokenRef,
13088
+ loadMode === "full" && viewTilesAreDrawable(
13089
+ targetKeysRef.current.map((key) => manager.getSnapshot(key).texture)
13090
+ )
12889
13091
  );
12890
- visibilityDirtyRef.current = false;
12891
- lastVisibilityQuaternionRef.current.copy(camera.quaternion);
12892
- lastVisibilityFovRef.current = camera.fov;
12893
- lastViewportRef.current = {
12894
- width: size.width,
12895
- height: size.height,
12896
- dpr: pixelRatio
12897
- };
12898
- commitLayers(nextLayers);
12899
13092
  });
12900
- return /* @__PURE__ */ jsxs13("group", { visible, children: [
12901
- previewTexture ? /* @__PURE__ */ jsx22(PreviewCube, { texture: previewTexture, faceOrder: previewFaceOrder }) : null,
12902
- layers.map((layer) => /* @__PURE__ */ jsx22(
13093
+ return /* @__PURE__ */ jsxs14("group", { visible, children: [
13094
+ previewTexture ? /* @__PURE__ */ jsx23(PreviewCube, { texture: previewTexture, faceOrder: previewFaceOrder }) : null,
13095
+ layers.map((layer) => /* @__PURE__ */ jsx23(
12903
13096
  TileLayerMeshes,
12904
13097
  {
12905
13098
  layer,
@@ -12912,7 +13105,7 @@ function Tile({
12912
13105
  }
12913
13106
 
12914
13107
  // src/scenes.tsx
12915
- import { jsx as jsx23, jsxs as jsxs14 } from "react/jsx-runtime";
13108
+ import { jsx as jsx24, jsxs as jsxs15 } from "react/jsx-runtime";
12916
13109
  function SceneSource({
12917
13110
  scene,
12918
13111
  visible,
@@ -12925,7 +13118,7 @@ function SceneSource({
12925
13118
  }
12926
13119
  switch (scene.type) {
12927
13120
  case "sphere":
12928
- return /* @__PURE__ */ jsx23(
13121
+ return /* @__PURE__ */ jsx24(
12929
13122
  Sphere,
12930
13123
  {
12931
13124
  src: scene.src,
@@ -12938,7 +13131,7 @@ function SceneSource({
12938
13131
  );
12939
13132
  case "tile": {
12940
13133
  const { id: _id, type: _type, ...tileProps } = scene;
12941
- return /* @__PURE__ */ jsx23(
13134
+ return /* @__PURE__ */ jsx24(
12942
13135
  Tile,
12943
13136
  {
12944
13137
  ...tileProps,
@@ -12951,7 +13144,7 @@ function SceneSource({
12951
13144
  }
12952
13145
  case "sphereTile": {
12953
13146
  const { id: _id, type: _type, ...tileProps } = scene;
12954
- return /* @__PURE__ */ jsx23(
13147
+ return /* @__PURE__ */ jsx24(
12955
13148
  SphereTile,
12956
13149
  {
12957
13150
  ...tileProps,
@@ -12974,17 +13167,17 @@ function SnapshotCapture({
12974
13167
  maxPixels,
12975
13168
  onCaptured
12976
13169
  }) {
12977
- const { camera, gl, scene, size } = useThree20();
12978
- const capturedRequestRef = useRef29(0);
12979
- const renderTargetRef = useRef29(null);
12980
- useEffect29(
13170
+ const { camera, gl, scene, size } = useThree21();
13171
+ const capturedRequestRef = useRef30(0);
13172
+ const renderTargetRef = useRef30(null);
13173
+ useEffect30(
12981
13174
  () => () => {
12982
13175
  renderTargetRef.current?.dispose();
12983
13176
  renderTargetRef.current = null;
12984
13177
  },
12985
13178
  []
12986
13179
  );
12987
- useFrame13(() => {
13180
+ useFrame14(() => {
12988
13181
  if (requestId === 0 || requestId === capturedRequestRef.current) {
12989
13182
  return;
12990
13183
  }
@@ -13032,15 +13225,16 @@ function ScenesController({
13032
13225
  onTransitionEnd,
13033
13226
  onTransitionError,
13034
13227
  snapshotMaxPixels = 3686400,
13228
+ transitionWaitForDetailMs,
13035
13229
  phaseRef: externalPhaseRef
13036
13230
  }) {
13037
- const controlsRef = useContext23(PanoramaViewContext);
13231
+ const controlsRef = useContext24(PanoramaViewContext);
13038
13232
  const manager = useSharedTileTextureManager();
13039
- const transition = useMemo21(
13233
+ const transition = useMemo22(
13040
13234
  () => resolveTransition(transitionInput),
13041
13235
  [transitionInput]
13042
13236
  );
13043
- const sceneMap = useMemo21(
13237
+ const sceneMap = useMemo22(
13044
13238
  () => new Map(scenes.map((scene) => [scene.id, scene])),
13045
13239
  [scenes]
13046
13240
  );
@@ -13057,14 +13251,21 @@ function ScenesController({
13057
13251
  const [transitionRunId, setTransitionRunId] = useState14(0);
13058
13252
  const [snapshot, setSnapshot] = useState14(null);
13059
13253
  const [recoveryKey, setRecoveryKey] = useState14(0);
13060
- const requestedSceneIdRef = useRef29(activeSceneId);
13061
- const captureReasonRef = useRef29("start");
13062
- const interactionReleaseRef = useRef29(null);
13063
- const slotsRef = useRef29(slots);
13064
- const phaseRef = useRef29(phase);
13065
- const liveSlotRef = useRef29(liveSlot);
13066
- const transitionFromRef = useRef29(initialScene);
13067
- const readySceneRef = useRef29(null);
13254
+ const requestedSceneIdRef = useRef30(activeSceneId);
13255
+ const captureReasonRef = useRef30("start");
13256
+ const interactionReleaseRef = useRef30(null);
13257
+ const slotsRef = useRef30(slots);
13258
+ const phaseRef = useRef30(phase);
13259
+ const liveSlotRef = useRef30(liveSlot);
13260
+ const transitionFromRef = useRef30(initialScene);
13261
+ const readySceneRef = useRef30(null);
13262
+ const waitRef = useRef30(null);
13263
+ const waitTimerRef = useRef30(null);
13264
+ const detailGenerationRef = useRef30(0);
13265
+ const [detailGeneration, setDetailGeneration] = useState14(0);
13266
+ const mountedRef = useRef30(true);
13267
+ const waitForDetailMsRef = useRef30(0);
13268
+ waitForDetailMsRef.current = normalizeTransitionWaitMs(transitionWaitForDetailMs);
13068
13269
  slotsRef.current = slots;
13069
13270
  phaseRef.current = phase;
13070
13271
  if (externalPhaseRef) {
@@ -13078,7 +13279,36 @@ function ScenesController({
13078
13279
  const reportError = useCallback11((sceneId, error) => {
13079
13280
  onTransitionError?.({ sceneId, error });
13080
13281
  }, [onTransitionError]);
13282
+ const clearDetailWait = useCallback11((bumpGeneration) => {
13283
+ if (waitTimerRef.current !== null) {
13284
+ clearTimeout(waitTimerRef.current);
13285
+ waitTimerRef.current = null;
13286
+ }
13287
+ const generation = waitRef.current?.generation;
13288
+ if (generation === void 0) {
13289
+ waitRef.current = null;
13290
+ } else {
13291
+ waitRef.current = acceptDetailWait(waitRef.current, {
13292
+ kind: "cancel",
13293
+ generation
13294
+ }).wait;
13295
+ }
13296
+ if (!bumpGeneration || !mountedRef.current) {
13297
+ return;
13298
+ }
13299
+ const nextGeneration = detailGenerationRef.current + 1;
13300
+ detailGenerationRef.current = nextGeneration;
13301
+ setDetailGeneration(nextGeneration);
13302
+ }, []);
13303
+ useEffect30(() => {
13304
+ mountedRef.current = true;
13305
+ return () => {
13306
+ mountedRef.current = false;
13307
+ clearDetailWait(false);
13308
+ };
13309
+ }, [clearDetailWait]);
13081
13310
  const startPreload = useCallback11((scene) => {
13311
+ clearDetailWait(true);
13082
13312
  const nextSlot = 1 - liveSlotRef.current;
13083
13313
  requestedSceneIdRef.current = scene.id;
13084
13314
  setSlots((current) => {
@@ -13088,8 +13318,8 @@ function ScenesController({
13088
13318
  });
13089
13319
  setPendingSlot(nextSlot);
13090
13320
  setPhase("preloading");
13091
- }, []);
13092
- useEffect29(() => {
13321
+ }, [clearDetailWait]);
13322
+ useEffect30(() => {
13093
13323
  const requested = sceneMap.get(activeSceneId);
13094
13324
  if (!requested) {
13095
13325
  reportError(activeSceneId, new Error(`Unknown panorama scene: ${activeSceneId}`));
@@ -13104,16 +13334,17 @@ function ScenesController({
13104
13334
  requestedSceneIdRef.current = requested.id;
13105
13335
  return;
13106
13336
  }
13107
- if (phaseRef.current === "transitioning" || phaseRef.current === "capturing") {
13337
+ if (phaseRef.current === "transitioning" || phaseRef.current === "capturing" || phaseRef.current === "awaitingDetail") {
13108
13338
  if (requestedSceneIdRef.current === requested.id) return;
13109
13339
  requestedSceneIdRef.current = requested.id;
13110
13340
  captureReasonRef.current = "interrupt";
13341
+ clearDetailWait(true);
13111
13342
  setPhase("recapturing");
13112
13343
  setCaptureRequestId((current) => current + 1);
13113
13344
  return;
13114
13345
  }
13115
13346
  startPreload(requested);
13116
- }, [activeSceneId, pendingSlot, reportError, sceneMap, startPreload]);
13347
+ }, [activeSceneId, clearDetailWait, pendingSlot, reportError, sceneMap, startPreload]);
13117
13348
  const notifySceneReady = useCallback11((scene) => {
13118
13349
  if (!scene || readySceneRef.current === scene) return;
13119
13350
  readySceneRef.current = scene;
@@ -13127,7 +13358,7 @@ function ScenesController({
13127
13358
  if (slot !== pendingSlot || phaseRef.current !== "preloading") {
13128
13359
  return;
13129
13360
  }
13130
- if (transition.preset === "none") {
13361
+ if (transition.preset === "none" && waitForDetailMsRef.current === 0) {
13131
13362
  const previousScene = slotsRef.current[liveSlotRef.current];
13132
13363
  const nextScene = slotsRef.current[slot];
13133
13364
  setSlots((current) => {
@@ -13155,29 +13386,6 @@ function ScenesController({
13155
13386
  setPhase("capturing");
13156
13387
  setCaptureRequestId((current) => current + 1);
13157
13388
  }, [controlsRef, notifySceneReady, onTransitionEnd, pendingSlot, transition.preset]);
13158
- const handleCaptured = useCallback11((nextSnapshot) => {
13159
- setSnapshot((current) => {
13160
- current?.dispose();
13161
- return nextSnapshot;
13162
- });
13163
- if (captureReasonRef.current === "interrupt") {
13164
- startPreload(sceneMap.get(requestedSceneIdRef.current));
13165
- return;
13166
- }
13167
- const sourceSlot = liveSlotRef.current;
13168
- setSlots((current) => {
13169
- const next = [...current];
13170
- next[sourceSlot] = null;
13171
- return next;
13172
- });
13173
- manager?.releaseUnused();
13174
- if (pendingSlot !== null) {
13175
- notifySceneReady(slotsRef.current[pendingSlot]);
13176
- setLiveSlot(pendingSlot);
13177
- }
13178
- setPhase("transitioning");
13179
- setTransitionRunId((current) => current + 1);
13180
- }, [manager, notifySceneReady, pendingSlot, sceneMap, startPreload]);
13181
13389
  const finishTransition = useCallback11(() => {
13182
13390
  const nextSlot = pendingSlot;
13183
13391
  const previousScene = transitionFromRef.current;
@@ -13203,16 +13411,142 @@ function ScenesController({
13203
13411
  });
13204
13412
  }
13205
13413
  }, [onTransitionEnd, pendingSlot, releaseInteraction, snapshot, transition.preset]);
13206
- useEffect29(() => () => {
13414
+ const finishTransitionRef = useRef30(finishTransition);
13415
+ finishTransitionRef.current = finishTransition;
13416
+ const transitionRef = useRef30(transition);
13417
+ transitionRef.current = transition;
13418
+ const consumeDetailSignal = useCallback11((signal) => {
13419
+ const decision = acceptDetailWait(waitRef.current, signal);
13420
+ waitRef.current = decision.wait;
13421
+ if (!decision.start) {
13422
+ return;
13423
+ }
13424
+ if (waitTimerRef.current !== null) {
13425
+ clearTimeout(waitTimerRef.current);
13426
+ waitTimerRef.current = null;
13427
+ }
13428
+ if (!mountedRef.current) {
13429
+ return;
13430
+ }
13431
+ if (transitionRef.current.preset === "none") {
13432
+ finishTransitionRef.current();
13433
+ return;
13434
+ }
13435
+ setPhase("transitioning");
13436
+ setTransitionRunId((current) => current + 1);
13437
+ }, []);
13438
+ const handleCaptured = useCallback11((nextSnapshot) => {
13439
+ if (captureReasonRef.current === "interrupt") {
13440
+ setSnapshot((current) => {
13441
+ current?.dispose();
13442
+ return nextSnapshot;
13443
+ });
13444
+ startPreload(sceneMap.get(requestedSceneIdRef.current));
13445
+ return;
13446
+ }
13447
+ const sourceSlot = liveSlotRef.current;
13448
+ const incoming = pendingSlot === null ? null : slotsRef.current[pendingSlot];
13449
+ setSlots((current) => {
13450
+ const next = [...current];
13451
+ next[sourceSlot] = null;
13452
+ return next;
13453
+ });
13454
+ manager?.releaseUnused();
13455
+ if (pendingSlot !== null && incoming) {
13456
+ notifySceneReady(incoming);
13457
+ setLiveSlot(pendingSlot);
13458
+ }
13459
+ if (waitTimerRef.current !== null) {
13460
+ clearTimeout(waitTimerRef.current);
13461
+ waitTimerRef.current = null;
13462
+ }
13463
+ waitRef.current = null;
13464
+ let hold = null;
13465
+ if (incoming && waitForDetailMsRef.current > 0) {
13466
+ const now = performance.now();
13467
+ const generation = detailGenerationRef.current + 1;
13468
+ detailGenerationRef.current = generation;
13469
+ hold = planDetailHold({
13470
+ waitMs: waitForDetailMsRef.current,
13471
+ now,
13472
+ generation,
13473
+ sceneId: incoming.id
13474
+ });
13475
+ if (hold) {
13476
+ const deadline = hold.deadline;
13477
+ waitRef.current = hold;
13478
+ setDetailGeneration(generation);
13479
+ waitTimerRef.current = setTimeout(() => {
13480
+ consumeDetailSignal({
13481
+ kind: "timeout",
13482
+ generation,
13483
+ now: deadline
13484
+ });
13485
+ }, Math.max(0, deadline - performance.now()));
13486
+ }
13487
+ }
13488
+ const nextPhase = phaseAfterSnapshot(transition.preset, hold);
13489
+ if (nextPhase === "awaitingDetail") {
13490
+ setSnapshot((current) => {
13491
+ current?.dispose();
13492
+ return nextSnapshot;
13493
+ });
13494
+ setPhase("awaitingDetail");
13495
+ return;
13496
+ }
13497
+ if (nextPhase === "idle") {
13498
+ nextSnapshot.dispose();
13499
+ setSnapshot((current) => {
13500
+ current?.dispose();
13501
+ return null;
13502
+ });
13503
+ if (pendingSlot !== null) {
13504
+ setActiveSlot(pendingSlot);
13505
+ }
13506
+ setPendingSlot(null);
13507
+ setPhase("idle");
13508
+ releaseInteraction();
13509
+ const previousScene = transitionFromRef.current;
13510
+ if (previousScene && incoming) {
13511
+ onTransitionEnd?.({
13512
+ previousSceneId: previousScene.id,
13513
+ sceneId: incoming.id,
13514
+ preset: "none"
13515
+ });
13516
+ }
13517
+ return;
13518
+ }
13519
+ setSnapshot((current) => {
13520
+ current?.dispose();
13521
+ return nextSnapshot;
13522
+ });
13523
+ setPhase("transitioning");
13524
+ setTransitionRunId((current) => current + 1);
13525
+ }, [
13526
+ consumeDetailSignal,
13527
+ manager,
13528
+ notifySceneReady,
13529
+ onTransitionEnd,
13530
+ pendingSlot,
13531
+ releaseInteraction,
13532
+ sceneMap,
13533
+ startPreload,
13534
+ transition.preset
13535
+ ]);
13536
+ const snapshotRef = useRef30(snapshot);
13537
+ snapshotRef.current = snapshot;
13538
+ useEffect30(() => () => {
13207
13539
  releaseInteraction();
13208
- snapshot?.dispose();
13209
- }, [releaseInteraction, snapshot]);
13210
- const { gl } = useThree20();
13211
- useEffect29(() => {
13540
+ snapshotRef.current?.dispose();
13541
+ snapshotRef.current = null;
13542
+ }, [releaseInteraction]);
13543
+ const { gl } = useThree21();
13544
+ useEffect30(() => {
13212
13545
  const canvas = gl.domElement;
13213
13546
  const onContextLost = (event) => {
13214
13547
  event.preventDefault();
13215
13548
  releaseInteraction();
13549
+ clearDetailWait(true);
13216
13550
  manager?.dispose();
13217
13551
  snapshot?.dispose();
13218
13552
  setSnapshot(null);
@@ -13230,11 +13564,30 @@ function ScenesController({
13230
13564
  canvas.removeEventListener("webglcontextlost", onContextLost);
13231
13565
  canvas.removeEventListener("webglcontextrestored", onContextRestored);
13232
13566
  };
13233
- }, [gl, manager, releaseInteraction, snapshot]);
13567
+ }, [clearDetailWait, gl, manager, releaseInteraction, snapshot]);
13234
13568
  const renderedScene = slots[liveSlot];
13235
13569
  const snapshotVisible = snapshot !== null && (phase === "transitioning" || phase === "recapturing" || phase === "preloading");
13236
- return /* @__PURE__ */ jsxs14(Fragment6, { children: [
13237
- /* @__PURE__ */ jsx23(
13570
+ const slotSceneKey = `${slots[0]?.id ?? ""}
13571
+ ${slots[1]?.id ?? ""}`;
13572
+ const detailReporters = useMemo22(() => {
13573
+ const [firstSceneId = "", secondSceneId = ""] = slotSceneKey.split("\n");
13574
+ const sceneIds = [firstSceneId, secondSceneId];
13575
+ return sceneIds.map((sceneId) => ({
13576
+ generation: detailGeneration,
13577
+ report: (ready) => {
13578
+ if (!ready || sceneId === "") {
13579
+ return;
13580
+ }
13581
+ consumeDetailSignal({
13582
+ kind: "ready",
13583
+ generation: detailGeneration,
13584
+ sceneId
13585
+ });
13586
+ }
13587
+ }));
13588
+ }, [consumeDetailSignal, detailGeneration, slotSceneKey]);
13589
+ return /* @__PURE__ */ jsxs15(Fragment6, { children: [
13590
+ /* @__PURE__ */ jsx24(
13238
13591
  SnapshotCapture,
13239
13592
  {
13240
13593
  requestId: captureRequestId,
@@ -13246,23 +13599,30 @@ function ScenesController({
13246
13599
  const source = slots[slot];
13247
13600
  const isLive = slot === liveSlot;
13248
13601
  const isPending = slot === pendingSlot;
13249
- return /* @__PURE__ */ jsx23(
13250
- SceneSource,
13602
+ return /* @__PURE__ */ jsx24(
13603
+ SceneDetailContext.Provider,
13251
13604
  {
13252
- scene: source,
13253
- visible: isLive,
13254
- baseOnly: isPending && phase !== "idle",
13255
- onReady: () => handleReady(slot),
13256
- onError: (error) => {
13257
- if (source) {
13258
- reportError(source.id, error);
13605
+ value: detailReporters[slot],
13606
+ children: /* @__PURE__ */ jsx24(
13607
+ SceneSource,
13608
+ {
13609
+ scene: source,
13610
+ visible: isLive,
13611
+ baseOnly: pendingSceneUsesBaseLayer(phase, isPending),
13612
+ onReady: () => handleReady(slot),
13613
+ onError: (error) => {
13614
+ if (source) {
13615
+ reportError(source.id, error);
13616
+ }
13617
+ }
13259
13618
  }
13260
- }
13619
+ )
13261
13620
  },
13262
13621
  `${slot}:${source?.id ?? "empty"}:${recoveryKey}`
13263
13622
  );
13264
13623
  }),
13265
- snapshotVisible ? /* @__PURE__ */ jsx23(
13624
+ snapshot !== null && phase === "awaitingDetail" ? /* @__PURE__ */ jsx24(SnapshotHold, { snapshot }) : null,
13625
+ snapshotVisible ? /* @__PURE__ */ jsx24(
13266
13626
  TransitionOverlay,
13267
13627
  {
13268
13628
  snapshot,
@@ -13299,13 +13659,13 @@ function Scenes({
13299
13659
  },
13300
13660
  [isControlled, onActiveSceneIdChange]
13301
13661
  );
13302
- const scenesRef = useRef29(scenes);
13662
+ const scenesRef = useRef30(scenes);
13303
13663
  scenesRef.current = scenes;
13304
- const resolvedIdRef = useRef29(resolvedId);
13664
+ const resolvedIdRef = useRef30(resolvedId);
13305
13665
  resolvedIdRef.current = resolvedId;
13306
- const host = useContext23(ScenesHostContext);
13307
- const phaseRef = useRef29("idle");
13308
- useEffect29(() => {
13666
+ const host = useContext24(ScenesHostContext);
13667
+ const phaseRef = useRef30("idle");
13668
+ useEffect30(() => {
13309
13669
  if (!host) {
13310
13670
  return;
13311
13671
  }
@@ -13355,12 +13715,12 @@ function Scenes({
13355
13715
  }
13356
13716
  };
13357
13717
  }, [host, requestSceneChange]);
13358
- return /* @__PURE__ */ jsx23(
13718
+ return /* @__PURE__ */ jsx24(
13359
13719
  TileTextureManagerProvider,
13360
13720
  {
13361
13721
  maxTextureMemoryMb,
13362
13722
  maxConcurrentLoads: maxConcurrentTileLoads,
13363
- children: /* @__PURE__ */ jsx23(
13723
+ children: /* @__PURE__ */ jsx24(
13364
13724
  ScenesController,
13365
13725
  {
13366
13726
  ...rest,
@@ -13374,8 +13734,8 @@ function Scenes({
13374
13734
  }
13375
13735
 
13376
13736
  // src/hotspot/image-hotspot.tsx
13377
- import { useThree as useThree23 } from "@react-three/fiber";
13378
- import { useEffect as useEffect32, useRef as useRef32, useState as useState17 } from "react";
13737
+ import { useThree as useThree24 } from "@react-three/fiber";
13738
+ import { useEffect as useEffect33, useRef as useRef33, useState as useState17 } from "react";
13379
13739
  import {
13380
13740
  ClampToEdgeWrapping as ClampToEdgeWrapping3,
13381
13741
  LinearFilter as LinearFilter6,
@@ -13385,13 +13745,13 @@ import {
13385
13745
  } from "three";
13386
13746
 
13387
13747
  // src/hotspot/hotspot-anchor.tsx
13388
- import { useFrame as useFrame15, useThree as useThree22 } from "@react-three/fiber";
13748
+ import { useFrame as useFrame16, useThree as useThree23 } from "@react-three/fiber";
13389
13749
  import {
13390
- useContext as useContext25,
13391
- useEffect as useEffect31,
13750
+ useContext as useContext26,
13751
+ useEffect as useEffect32,
13392
13752
  useLayoutEffect as useLayoutEffect5,
13393
- useMemo as useMemo23,
13394
- useRef as useRef31,
13753
+ useMemo as useMemo24,
13754
+ useRef as useRef32,
13395
13755
  useState as useState16
13396
13756
  } from "react";
13397
13757
  import {
@@ -13403,25 +13763,25 @@ import {
13403
13763
  PlaneGeometry as PlaneGeometry5,
13404
13764
  Quaternion as Quaternion4,
13405
13765
  Ray,
13406
- Vector3 as Vector316
13766
+ Vector3 as Vector317
13407
13767
  } from "three";
13408
13768
 
13409
13769
  // src/hotspot/hotspot-tooltip.tsx
13410
- import { useEffect as useEffect30, useMemo as useMemo22, useState as useState15 } from "react";
13770
+ import { useEffect as useEffect31, useMemo as useMemo23, useState as useState15 } from "react";
13411
13771
 
13412
13772
  // src/webvr/stereo-html.tsx
13413
- import { useFrame as useFrame14, useThree as useThree21 } from "@react-three/fiber";
13773
+ import { useFrame as useFrame15, useThree as useThree22 } from "@react-three/fiber";
13414
13774
  import {
13415
- useContext as useContext24,
13775
+ useContext as useContext25,
13416
13776
  useLayoutEffect as useLayoutEffect4,
13417
- useRef as useRef30,
13777
+ useRef as useRef31,
13418
13778
  useSyncExternalStore as useSyncExternalStore7
13419
13779
  } from "react";
13420
13780
  import { createRoot } from "react-dom/client";
13421
- import { Vector3 as Vector314 } from "three";
13422
- import { Fragment as Fragment7, jsx as jsx24, jsxs as jsxs15 } from "react/jsx-runtime";
13781
+ import { Vector3 as Vector315 } from "three";
13782
+ import { Fragment as Fragment7, jsx as jsx25, jsxs as jsxs16 } from "react/jsx-runtime";
13423
13783
  function useFallbackStereoView() {
13424
- const runtime = useContext24(WebVRRuntimeContext);
13784
+ const runtime = useContext25(WebVRRuntimeContext);
13425
13785
  const host = runtime?.host ?? null;
13426
13786
  const fallback = useSyncExternalStore7(
13427
13787
  (onStoreChange) => host ? subscribeWebVRHost(host, onStoreChange) : () => void 0,
@@ -13438,10 +13798,10 @@ function ProjectedHtml({
13438
13798
  stereoView,
13439
13799
  eye
13440
13800
  }) {
13441
- const { camera, gl, events, size } = useThree21();
13442
- const group = useRef30(null);
13443
- const overlay = useRef30(null);
13444
- const scratch = useRef30(new Vector314());
13801
+ const { camera, gl, events, size } = useThree22();
13802
+ const group = useRef31(null);
13803
+ const overlay = useRef31(null);
13804
+ const scratch = useRef31(new Vector315());
13445
13805
  const target = events.connected || gl.domElement.parentElement;
13446
13806
  const updatePosition = () => {
13447
13807
  const anchor = group.current;
@@ -13489,7 +13849,7 @@ function ProjectedHtml({
13489
13849
  }, [target]);
13490
13850
  useLayoutEffect4(() => {
13491
13851
  overlay.current?.root.render(
13492
- /* @__PURE__ */ jsx24(
13852
+ /* @__PURE__ */ jsx25(
13493
13853
  "div",
13494
13854
  {
13495
13855
  "aria-hidden": eye === "right" || void 0,
@@ -13500,19 +13860,19 @@ function ProjectedHtml({
13500
13860
  );
13501
13861
  updatePosition();
13502
13862
  });
13503
- useFrame14(updatePosition);
13504
- return /* @__PURE__ */ jsx24("group", { ref: group });
13863
+ useFrame15(updatePosition);
13864
+ return /* @__PURE__ */ jsx25("group", { ref: group });
13505
13865
  }
13506
13866
  function PanoHtml(props) {
13507
13867
  const stereoView = useFallbackStereoView();
13508
- return stereoView ? /* @__PURE__ */ jsxs15(Fragment7, { children: [
13509
- /* @__PURE__ */ jsx24(ProjectedHtml, { ...props, stereoView, eye: "left" }),
13510
- /* @__PURE__ */ jsx24(ProjectedHtml, { ...props, stereoView, eye: "right" })
13511
- ] }) : /* @__PURE__ */ jsx24(ProjectedHtml, { ...props });
13868
+ return stereoView ? /* @__PURE__ */ jsxs16(Fragment7, { children: [
13869
+ /* @__PURE__ */ jsx25(ProjectedHtml, { ...props, stereoView, eye: "left" }),
13870
+ /* @__PURE__ */ jsx25(ProjectedHtml, { ...props, stereoView, eye: "right" })
13871
+ ] }) : /* @__PURE__ */ jsx25(ProjectedHtml, { ...props });
13512
13872
  }
13513
13873
 
13514
13874
  // src/hotspot/hotspot-tooltip.tsx
13515
- import { jsx as jsx25, jsxs as jsxs16 } from "react/jsx-runtime";
13875
+ import { jsx as jsx26, jsxs as jsxs17 } from "react/jsx-runtime";
13516
13876
  var DEFAULT_HOTSPOT_TOOLTIP_OFFSET = 12;
13517
13877
  var DEFAULT_HOTSPOT_TOOLTIP_APPEARANCE = {
13518
13878
  background: "rgba(22, 22, 22, 0.72)",
@@ -13585,15 +13945,15 @@ function HotspotTooltip({
13585
13945
  appearance
13586
13946
  }) {
13587
13947
  const [imageFailed, setImageFailed] = useState15(false);
13588
- useEffect30(() => {
13948
+ useEffect31(() => {
13589
13949
  setImageFailed(false);
13590
13950
  }, [content.image]);
13591
13951
  const showImage = Boolean(content.image) && !imageFailed;
13592
- const resolvedAppearance = useMemo22(
13952
+ const resolvedAppearance = useMemo23(
13593
13953
  () => resolveHotspotTooltipAppearance(appearance),
13594
13954
  [appearance]
13595
13955
  );
13596
- const bubbleStyle = useMemo22(
13956
+ const bubbleStyle = useMemo23(
13597
13957
  () => ({
13598
13958
  background: resolvedAppearance.background,
13599
13959
  border: resolvedAppearance.border,
@@ -13615,8 +13975,8 @@ function HotspotTooltip({
13615
13975
  if (!showImage && !content.text) {
13616
13976
  return null;
13617
13977
  }
13618
- return /* @__PURE__ */ jsx25(PanoHtml, { pointerEvents: "none", style: WRAPPER_STYLE, zIndexRange: [20, 10], children: /* @__PURE__ */ jsxs16("div", { className: "pano-hotspot-tooltip", role: "tooltip", style: bubbleStyle, children: [
13619
- showImage ? /* @__PURE__ */ jsx25(
13978
+ return /* @__PURE__ */ jsx26(PanoHtml, { pointerEvents: "none", style: WRAPPER_STYLE, zIndexRange: [20, 10], children: /* @__PURE__ */ jsxs17("div", { className: "pano-hotspot-tooltip", role: "tooltip", style: bubbleStyle, children: [
13979
+ showImage ? /* @__PURE__ */ jsx26(
13620
13980
  "img",
13621
13981
  {
13622
13982
  alt: content.imageAlt ?? content.text ?? "",
@@ -13625,7 +13985,7 @@ function HotspotTooltip({
13625
13985
  src: content.image
13626
13986
  }
13627
13987
  ) : null,
13628
- content.text ? /* @__PURE__ */ jsx25(
13988
+ content.text ? /* @__PURE__ */ jsx26(
13629
13989
  "p",
13630
13990
  {
13631
13991
  className: "pano-hotspot-tooltip-text",
@@ -13644,10 +14004,10 @@ function HotspotTooltip({
13644
14004
  import {
13645
14005
  MathUtils as MathUtils8,
13646
14006
  PerspectiveCamera as PerspectiveCamera6,
13647
- Vector3 as Vector315
14007
+ Vector3 as Vector316
13648
14008
  } from "three";
13649
- var LOCAL_FORWARD = new Vector315(0, 0, 1);
13650
- var CAMERA_POSITION = new Vector315();
14009
+ var LOCAL_FORWARD = new Vector316(0, 0, 1);
14010
+ var CAMERA_POSITION = new Vector316();
13651
14011
  function applyHotspotTransform(group, camera, orientation2, surfaceQuaternion3, rotation, scaleMode, referenceFov, useAngularScale, worldWidth, worldHeight, distance) {
13652
14012
  if (orientation2 === "billboard") {
13653
14013
  group.quaternion.copy(camera.quaternion);
@@ -13676,7 +14036,7 @@ function fixedScaleFactor(cameraFov, referenceFov) {
13676
14036
  }
13677
14037
 
13678
14038
  // src/hotspot/hotspot-anchor.tsx
13679
- import { jsx as jsx26, jsxs as jsxs17 } from "react/jsx-runtime";
14039
+ import { jsx as jsx27, jsxs as jsxs18 } from "react/jsx-runtime";
13680
14040
  var DEFAULT_FLOATING_DISTANCE = 10;
13681
14041
  var PANORAMA_RADIUS = DEFAULT_PANORAMA_RADIUS;
13682
14042
  var PANORAMA_SURFACE_INSET = 4;
@@ -13686,18 +14046,18 @@ var MAX_ANGULAR_SIZE = 179;
13686
14046
  var DRAG_EPSILON_DEGREES = 1e-3;
13687
14047
  var TOOLTIP_WORLD_BOX = new Box34();
13688
14048
  var TOOLTIP_LOCAL_BOX = new Box34();
13689
- var TOOLTIP_CORNER = new Vector316();
14049
+ var TOOLTIP_CORNER = new Vector317();
13690
14050
  var TOOLTIP_INVERSE = new Matrix44();
13691
- var TOOLTIP_WORLD_CORNER = new Vector316();
13692
- var TOOLTIP_PROJECTED = new Vector316();
13693
- var TOOLTIP_RAY_ORIGIN = new Vector316();
13694
- var TOOLTIP_RAY_FAR = new Vector316();
13695
- var TOOLTIP_RAY_DIRECTION = new Vector316();
14051
+ var TOOLTIP_WORLD_CORNER = new Vector317();
14052
+ var TOOLTIP_PROJECTED = new Vector317();
14053
+ var TOOLTIP_RAY_ORIGIN = new Vector317();
14054
+ var TOOLTIP_RAY_FAR = new Vector317();
14055
+ var TOOLTIP_RAY_DIRECTION = new Vector317();
13696
14056
  var TOOLTIP_RAY = new Ray();
13697
14057
  var TOOLTIP_PLANE = new Plane();
13698
- var TOOLTIP_INTERSECTION = new Vector316();
13699
- var TOOLTIP_PLANE_NORMAL = new Vector316();
13700
- var TOOLTIP_PLANE_POINT = new Vector316();
14058
+ var TOOLTIP_INTERSECTION = new Vector317();
14059
+ var TOOLTIP_PLANE_NORMAL = new Vector317();
14060
+ var TOOLTIP_PLANE_POINT = new Vector317();
13701
14061
  var HOTSPOT_MODE_RENDERING = {
13702
14062
  surface: { orientation: "surface", placement: "surface" },
13703
14063
  billboard: { orientation: "billboard", placement: "floating" }
@@ -13742,7 +14102,7 @@ function createSurfaceQuaternion(position) {
13742
14102
  const inward = outward.clone().negate();
13743
14103
  const pitch = MathUtils9.degToRad(position.pitch);
13744
14104
  const yaw = MathUtils9.degToRad(position.yaw);
13745
- const localUp = new Vector316(
14105
+ const localUp = new Vector317(
13746
14106
  -Math.sin(pitch) * Math.sin(yaw),
13747
14107
  Math.cos(pitch),
13748
14108
  Math.sin(pitch) * Math.cos(yaw)
@@ -13993,24 +14353,24 @@ function HotspotAnchor({
13993
14353
  onPositionChange,
13994
14354
  onDragEnd
13995
14355
  }) {
13996
- const controlsRef = useContext25(PanoramaViewContext);
13997
- const hotspotTargetRegistry = useContext25(HotspotTargetRegistryContext);
13998
- const eventBus = useContext25(PanoEventBusContext);
14356
+ const controlsRef = useContext26(PanoramaViewContext);
14357
+ const hotspotTargetRegistry = useContext26(HotspotTargetRegistryContext);
14358
+ const eventBus = useContext26(PanoEventBusContext);
13999
14359
  const cursorApi = usePanoCursor();
14000
- const { camera, size } = useThree22();
14001
- const groupRef = useRef31(null);
14002
- const tooltipAnchorRef = useRef31(null);
14003
- const dragStateRef = useRef31(null);
14004
- const suppressNextClickRef = useRef31(false);
14360
+ const { camera, size } = useThree23();
14361
+ const groupRef = useRef32(null);
14362
+ const tooltipAnchorRef = useRef32(null);
14363
+ const dragStateRef = useRef32(null);
14364
+ const suppressNextClickRef = useRef32(false);
14005
14365
  const [hovered, setHovered] = useState16(false);
14006
14366
  const [dragging, setDragging] = useState16(false);
14007
14367
  const [pinned, setPinned] = useState16(false);
14008
- const tooltipContent = useMemo23(
14368
+ const tooltipContent = useMemo24(
14009
14369
  () => resolveHotspotTooltipContent(tooltip),
14010
14370
  [tooltip]
14011
14371
  );
14012
14372
  const normalizedPosition = normalizePanoPosition(position);
14013
- useEffect31(() => {
14373
+ useEffect32(() => {
14014
14374
  if (!hotspotTargetRegistry) {
14015
14375
  return;
14016
14376
  }
@@ -14027,17 +14387,17 @@ function HotspotAnchor({
14027
14387
  scaledWidth,
14028
14388
  scaledHeight
14029
14389
  );
14030
- const worldPosition = useMemo23(
14390
+ const worldPosition = useMemo24(
14031
14391
  () => panoPositionToVector3(normalizedPosition, resolvedDistance),
14032
14392
  [normalizedPosition.pitch, normalizedPosition.yaw, resolvedDistance]
14033
14393
  );
14034
- const surfaceQuaternion3 = useMemo23(
14394
+ const surfaceQuaternion3 = useMemo24(
14035
14395
  () => createSurfaceQuaternion(normalizedPosition),
14036
14396
  [normalizedPosition.pitch, normalizedPosition.yaw]
14037
14397
  );
14038
14398
  const worldWidth = angularSizeToWorldSize(scaledWidth, resolvedDistance);
14039
14399
  const worldHeight = angularSizeToWorldSize(scaledHeight, resolvedDistance);
14040
- const focusGeometry = useMemo23(() => {
14400
+ const focusGeometry = useMemo24(() => {
14041
14401
  const planeGeometry = new PlaneGeometry5(1, 1);
14042
14402
  const geometry = new EdgesGeometry(planeGeometry);
14043
14403
  planeGeometry.dispose();
@@ -14064,14 +14424,14 @@ function HotspotAnchor({
14064
14424
  });
14065
14425
  const tooltipOpen = visible && tooltipContent !== null && isTooltipOpen(tooltipTrigger, hovered, focused, pinned);
14066
14426
  const cursorClaimId = hotspotCursorClaimId(id);
14067
- useEffect31(
14427
+ useEffect32(
14068
14428
  () => () => {
14069
14429
  dragStateRef.current?.releaseInteractionLock();
14070
14430
  dragStateRef.current = null;
14071
14431
  },
14072
14432
  []
14073
14433
  );
14074
- useEffect31(() => {
14434
+ useEffect32(() => {
14075
14435
  if (!cursorApi) {
14076
14436
  return;
14077
14437
  }
@@ -14093,14 +14453,14 @@ function HotspotAnchor({
14093
14453
  hovered,
14094
14454
  visible
14095
14455
  ]);
14096
- useEffect31(
14456
+ useEffect32(
14097
14457
  () => () => {
14098
14458
  cursorApi?.release(cursorClaimId);
14099
14459
  },
14100
14460
  [cursorApi, cursorClaimId]
14101
14461
  );
14102
- useEffect31(() => () => focusGeometry.dispose(), [focusGeometry]);
14103
- useEffect31(() => {
14462
+ useEffect32(() => () => focusGeometry.dispose(), [focusGeometry]);
14463
+ useEffect32(() => {
14104
14464
  if (tooltipTrigger !== "click") {
14105
14465
  setPinned(false);
14106
14466
  return;
@@ -14109,12 +14469,12 @@ function HotspotAnchor({
14109
14469
  setPinned(false);
14110
14470
  });
14111
14471
  }, [eventBus, tooltipTrigger]);
14112
- useEffect31(() => {
14472
+ useEffect32(() => {
14113
14473
  if (tooltipTrigger !== "hover") {
14114
14474
  setHovered(false);
14115
14475
  }
14116
14476
  }, [tooltipTrigger]);
14117
- useEffect31(() => {
14477
+ useEffect32(() => {
14118
14478
  if (acceptsPointer) {
14119
14479
  return;
14120
14480
  }
@@ -14170,7 +14530,7 @@ function HotspotAnchor({
14170
14530
  worldHeight,
14171
14531
  worldWidth
14172
14532
  ]);
14173
- useFrame15((state) => {
14533
+ useFrame16((state) => {
14174
14534
  const group = groupRef.current;
14175
14535
  if (!group) {
14176
14536
  return;
@@ -14229,7 +14589,7 @@ function HotspotAnchor({
14229
14589
  setHovered(true);
14230
14590
  }
14231
14591
  };
14232
- return /* @__PURE__ */ jsxs17(
14592
+ return /* @__PURE__ */ jsxs18(
14233
14593
  "group",
14234
14594
  {
14235
14595
  ref: groupRef,
@@ -14306,18 +14666,18 @@ function HotspotAnchor({
14306
14666
  } : void 0,
14307
14667
  onPointerUp: acceptsPointer ? (event) => releasePointer(event, true) : void 0,
14308
14668
  children: [
14309
- focused ? focusContent ?? /* @__PURE__ */ jsx26(
14669
+ focused ? focusContent ?? /* @__PURE__ */ jsx27(
14310
14670
  "lineSegments",
14311
14671
  {
14312
14672
  geometry: focusGeometry,
14313
14673
  position: [0, 0, 0.01],
14314
14674
  renderOrder: renderOrder + 1,
14315
14675
  scale: [1.12, 1.12, 1],
14316
- children: /* @__PURE__ */ jsx26("lineBasicMaterial", { color: "#f5fbfc", depthTest: false })
14676
+ children: /* @__PURE__ */ jsx27("lineBasicMaterial", { color: "#f5fbfc", depthTest: false })
14317
14677
  }
14318
14678
  ) : null,
14319
14679
  children,
14320
- tooltipOpen && tooltipContent ? /* @__PURE__ */ jsx26("group", { ref: tooltipAnchorRef, children: /* @__PURE__ */ jsx26(
14680
+ tooltipOpen && tooltipContent ? /* @__PURE__ */ jsx27("group", { ref: tooltipAnchorRef, children: /* @__PURE__ */ jsx27(
14321
14681
  HotspotTooltip,
14322
14682
  {
14323
14683
  appearance: tooltipAppearance,
@@ -14334,11 +14694,11 @@ function HotspotAnchor({
14334
14694
  // src/hotspot/hotspot-plane.tsx
14335
14695
  import {
14336
14696
  DoubleSide as DoubleSide4,
14337
- Mesh as Mesh5,
14697
+ Mesh as Mesh6,
14338
14698
  MeshBasicMaterial,
14339
14699
  Vector2 as Vector26
14340
14700
  } from "three";
14341
- import { jsx as jsx27, jsxs as jsxs18 } from "react/jsx-runtime";
14701
+ import { jsx as jsx28, jsxs as jsxs19 } from "react/jsx-runtime";
14342
14702
  var HOTSPOT_ALPHA_CUTOFF = 0.05;
14343
14703
  var SAMPLE_UV = new Vector26();
14344
14704
  var RAYCAST_HITS = [];
@@ -14415,7 +14775,7 @@ function sampleTextureAlpha(texture, u, v) {
14415
14775
  function hotspotPlaneRaycast(raycaster, intersects2) {
14416
14776
  const material = Array.isArray(this.material) ? this.material[0] : this.material;
14417
14777
  if (!(material instanceof MeshBasicMaterial)) {
14418
- Mesh5.prototype.raycast.call(this, raycaster, intersects2);
14778
+ Mesh6.prototype.raycast.call(this, raycaster, intersects2);
14419
14779
  return;
14420
14780
  }
14421
14781
  const cutoff = Math.max(material.alphaTest, HOTSPOT_ALPHA_CUTOFF);
@@ -14423,7 +14783,7 @@ function hotspotPlaneRaycast(raycaster, intersects2) {
14423
14783
  return;
14424
14784
  }
14425
14785
  RAYCAST_HITS.length = 0;
14426
- Mesh5.prototype.raycast.call(this, raycaster, RAYCAST_HITS);
14786
+ Mesh6.prototype.raycast.call(this, raycaster, RAYCAST_HITS);
14427
14787
  const map = material.map;
14428
14788
  for (const hit of RAYCAST_HITS) {
14429
14789
  if (!map || !hit.uv) {
@@ -14440,9 +14800,9 @@ function HotspotPlane({
14440
14800
  map,
14441
14801
  opacity
14442
14802
  }) {
14443
- return /* @__PURE__ */ jsxs18("mesh", { raycast: hotspotPlaneRaycast, children: [
14444
- /* @__PURE__ */ jsx27("planeGeometry", { args: [1, 1] }),
14445
- /* @__PURE__ */ jsx27(
14803
+ return /* @__PURE__ */ jsxs19("mesh", { raycast: hotspotPlaneRaycast, children: [
14804
+ /* @__PURE__ */ jsx28("planeGeometry", { args: [1, 1] }),
14805
+ /* @__PURE__ */ jsx28(
14446
14806
  PanoBasicMaterial,
14447
14807
  {
14448
14808
  target: "hotspot",
@@ -14458,15 +14818,15 @@ function HotspotPlane({
14458
14818
  }
14459
14819
 
14460
14820
  // src/hotspot/image-hotspot.tsx
14461
- import { jsx as jsx28 } from "react/jsx-runtime";
14821
+ import { jsx as jsx29 } from "react/jsx-runtime";
14462
14822
  function useHotspotImageTexture(src, onLoad, onError) {
14463
- const gl = useThree23((state) => state.gl);
14823
+ const gl = useThree24((state) => state.gl);
14464
14824
  const [texture, setTexture] = useState17(null);
14465
- const onLoadRef = useRef32(onLoad);
14466
- const onErrorRef = useRef32(onError);
14825
+ const onLoadRef = useRef33(onLoad);
14826
+ const onErrorRef = useRef33(onError);
14467
14827
  onLoadRef.current = onLoad;
14468
14828
  onErrorRef.current = onError;
14469
- useEffect32(() => {
14829
+ useEffect33(() => {
14470
14830
  let active = true;
14471
14831
  setTexture(null);
14472
14832
  if (!src) {
@@ -14504,7 +14864,7 @@ function useHotspotImageTexture(src, onLoad, onError) {
14504
14864
  active = false;
14505
14865
  };
14506
14866
  }, [gl, src]);
14507
- useEffect32(
14867
+ useEffect33(
14508
14868
  () => () => {
14509
14869
  texture?.dispose();
14510
14870
  },
@@ -14522,11 +14882,11 @@ function ImageHotspot({
14522
14882
  ...anchorProps
14523
14883
  }) {
14524
14884
  const texture = useHotspotImageTexture(src, onLoad, onError);
14525
- return /* @__PURE__ */ jsx28(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ jsx28(HotspotPlane, { map: texture, opacity }) });
14885
+ return /* @__PURE__ */ jsx29(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ jsx29(HotspotPlane, { map: texture, opacity }) });
14526
14886
  }
14527
14887
 
14528
14888
  // src/hotspot/polygon-hotspot.tsx
14529
- import { useEffect as useEffect33, useMemo as useMemo24, useRef as useRef34 } from "react";
14889
+ import { useEffect as useEffect34, useMemo as useMemo25, useRef as useRef35 } from "react";
14530
14890
  import {
14531
14891
  BufferGeometry as BufferGeometry2,
14532
14892
  DoubleSide as DoubleSide5,
@@ -14535,20 +14895,20 @@ import {
14535
14895
  Quaternion as Quaternion5,
14536
14896
  ShapeUtils,
14537
14897
  Vector2 as Vector27,
14538
- Vector3 as Vector318
14898
+ Vector3 as Vector319
14539
14899
  } from "three";
14540
14900
 
14541
14901
  // src/hotspot/hotspot-stroke-line.tsx
14542
14902
  import { Line } from "@react-three/drei";
14543
- import { useFrame as useFrame16, useThree as useThree24 } from "@react-three/fiber";
14544
- import { useLayoutEffect as useLayoutEffect6, useRef as useRef33 } from "react";
14903
+ import { useFrame as useFrame17, useThree as useThree25 } from "@react-three/fiber";
14904
+ import { useLayoutEffect as useLayoutEffect6, useRef as useRef34 } from "react";
14545
14905
  import {
14546
14906
  MathUtils as MathUtils10,
14547
14907
  PerspectiveCamera as PerspectiveCamera7,
14548
- Vector3 as Vector317
14908
+ Vector3 as Vector318
14549
14909
  } from "three";
14550
- import { jsx as jsx29 } from "react/jsx-runtime";
14551
- var LINE_WORLD_POSITION = new Vector317();
14910
+ import { jsx as jsx30 } from "react/jsx-runtime";
14911
+ var LINE_WORLD_POSITION = new Vector318();
14552
14912
  function applyScreenSpaceDashScale(object, camera, viewportHeight) {
14553
14913
  const material = object?.material;
14554
14914
  if (!object || typeof material?.dashScale !== "number") {
@@ -14578,8 +14938,8 @@ function HotspotStrokeLine({
14578
14938
  dashSize,
14579
14939
  gapSize
14580
14940
  }) {
14581
- const lineRef = useRef33(null);
14582
- const { camera, size } = useThree24();
14941
+ const lineRef = useRef34(null);
14942
+ const { camera, size } = useThree25();
14583
14943
  const dash = resolveDash(dashSize, gapSize);
14584
14944
  useLayoutEffect6(() => {
14585
14945
  if (!dash.dashed) {
@@ -14587,13 +14947,13 @@ function HotspotStrokeLine({
14587
14947
  }
14588
14948
  applyScreenSpaceDashScale(lineRef.current, camera, size.height);
14589
14949
  }, [camera, dash.dashed, dash.dashSize, dash.gapSize, size.height]);
14590
- useFrame16((state) => {
14950
+ useFrame17((state) => {
14591
14951
  if (!dash.dashed) {
14592
14952
  return;
14593
14953
  }
14594
14954
  applyScreenSpaceDashScale(lineRef.current, state.camera, state.size.height);
14595
14955
  });
14596
- return /* @__PURE__ */ jsx29(
14956
+ return /* @__PURE__ */ jsx30(
14597
14957
  Line,
14598
14958
  {
14599
14959
  ref: lineRef,
@@ -14615,7 +14975,7 @@ function HotspotStrokeLine({
14615
14975
  }
14616
14976
 
14617
14977
  // src/hotspot/polygon-hotspot.tsx
14618
- import { jsx as jsx30, jsxs as jsxs19 } from "react/jsx-runtime";
14978
+ import { jsx as jsx31, jsxs as jsxs20 } from "react/jsx-runtime";
14619
14979
  var POLYGON_RADIUS = 990;
14620
14980
  var MAX_FILL_SEGMENT_DEGREES = 7;
14621
14981
  function cloneVertices(vertices) {
@@ -14687,7 +15047,7 @@ function polygonContainsDirection(vertices, direction) {
14687
15047
  }
14688
15048
  function fitsHemisphere(vertices) {
14689
15049
  const directions = vertices.map((vertex) => panoPositionToVector3(vertex).normalize());
14690
- const candidates = [new Vector318()];
15050
+ const candidates = [new Vector319()];
14691
15051
  for (const direction of directions) {
14692
15052
  candidates[0].add(direction);
14693
15053
  candidates.push(direction.clone());
@@ -14711,7 +15071,7 @@ function validatePolygonVertices(vertices) {
14711
15071
  if (hasSelfIntersection(unwrapped)) {
14712
15072
  issues.push({ code: "self_intersection", message: "Polygon edges cannot cross." });
14713
15073
  }
14714
- if (polygonContainsDirection(normalized, new Vector318(0, 1, 0)) || polygonContainsDirection(normalized, new Vector318(0, -1, 0))) {
15074
+ if (polygonContainsDirection(normalized, new Vector319(0, 1, 0)) || polygonContainsDirection(normalized, new Vector319(0, -1, 0))) {
14715
15075
  issues.push({ code: "contains_pole", message: "Polygons cannot contain a panorama pole." });
14716
15076
  }
14717
15077
  if (!fitsHemisphere(normalized)) {
@@ -14722,7 +15082,7 @@ function validatePolygonVertices(vertices) {
14722
15082
  function polygonCenter(vertices) {
14723
15083
  const sum = vertices.reduce(
14724
15084
  (total, vertex) => total.add(panoPositionToVector3(vertex).normalize()),
14725
- new Vector318()
15085
+ new Vector319()
14726
15086
  );
14727
15087
  return sum.lengthSq() > 1e-8 ? vector3ToPanoPosition(sum) : normalizePanoPosition(vertices[0]);
14728
15088
  }
@@ -14731,7 +15091,7 @@ function surfaceQuaternion(position) {
14731
15091
  const inward = outward.clone().negate();
14732
15092
  const pitch = position.pitch * Math.PI / 180;
14733
15093
  const yaw = position.yaw * Math.PI / 180;
14734
- const localUp = new Vector318(
15094
+ const localUp = new Vector319(
14735
15095
  -Math.sin(pitch) * Math.sin(yaw),
14736
15096
  Math.cos(pitch),
14737
15097
  Math.sin(pitch) * Math.cos(yaw)
@@ -14744,7 +15104,7 @@ function makeWorldToLocal(center) {
14744
15104
  return new Matrix45().compose(
14745
15105
  panoPositionToVector3(center, POLYGON_RADIUS),
14746
15106
  surfaceQuaternion(center),
14747
- new Vector318(1, 1, 1)
15107
+ new Vector319(1, 1, 1)
14748
15108
  ).invert();
14749
15109
  }
14750
15110
  function projectedPoint(a, b, c, weightB, weightC, radius, worldToLocal) {
@@ -14871,24 +15231,24 @@ function PolygonHotspot({
14871
15231
  onInvalid,
14872
15232
  ...anchorProps
14873
15233
  }) {
14874
- const issues = useMemo24(() => validatePolygonVertices(vertices), [vertices]);
15234
+ const issues = useMemo25(() => validatePolygonVertices(vertices), [vertices]);
14875
15235
  const valid = issues.length === 0;
14876
- const center = useMemo24(() => valid ? polygonCenter(vertices) : null, [valid, vertices]);
14877
- const fillGeometry = useMemo24(
15236
+ const center = useMemo25(() => valid ? polygonCenter(vertices) : null, [valid, vertices]);
15237
+ const fillGeometry = useMemo25(
14878
15238
  () => valid && center ? makeFillGeometry(vertices, center) : null,
14879
15239
  [center, valid, vertices]
14880
15240
  );
14881
- const strokePoints = useMemo24(
15241
+ const strokePoints = useMemo25(
14882
15242
  () => valid && center ? makeStrokePositions(vertices, center) : null,
14883
15243
  [center, valid, vertices]
14884
15244
  );
14885
15245
  const resolvedStrokeOpacity = Math.max(0, Math.min(strokeOpacity, 1));
14886
- const startVerticesRef = useRef34(null);
15246
+ const startVerticesRef = useRef35(null);
14887
15247
  const issuesKey = issues.map((issue) => issue.code).join(",");
14888
- useEffect33(() => {
15248
+ useEffect34(() => {
14889
15249
  if (!valid) onInvalid?.(issues);
14890
15250
  }, [issues, issuesKey, onInvalid, valid]);
14891
- useEffect33(() => () => fillGeometry?.dispose(), [fillGeometry]);
15251
+ useEffect34(() => () => fillGeometry?.dispose(), [fillGeometry]);
14892
15252
  if (!valid || !center || !fillGeometry || !strokePoints || strokePoints.length < 2) {
14893
15253
  return null;
14894
15254
  }
@@ -14903,7 +15263,7 @@ function PolygonHotspot({
14903
15263
  startPosition: event.startPosition
14904
15264
  });
14905
15265
  };
14906
- return /* @__PURE__ */ jsxs19(
15266
+ return /* @__PURE__ */ jsxs20(
14907
15267
  HotspotAnchor,
14908
15268
  {
14909
15269
  ...anchorProps,
@@ -14918,7 +15278,7 @@ function PolygonHotspot({
14918
15278
  draggable,
14919
15279
  interactive,
14920
15280
  useAngularScale: false,
14921
- focusContent: /* @__PURE__ */ jsx30(
15281
+ focusContent: /* @__PURE__ */ jsx31(
14922
15282
  HotspotStrokeLine,
14923
15283
  {
14924
15284
  color: "#75cbd3",
@@ -14940,7 +15300,7 @@ function PolygonHotspot({
14940
15300
  startVerticesRef.current = null;
14941
15301
  },
14942
15302
  children: [
14943
- /* @__PURE__ */ jsx30("mesh", { geometry: fillGeometry, renderOrder, children: /* @__PURE__ */ jsx30(
15303
+ /* @__PURE__ */ jsx31("mesh", { geometry: fillGeometry, renderOrder, children: /* @__PURE__ */ jsx31(
14944
15304
  "meshBasicMaterial",
14945
15305
  {
14946
15306
  color: fill,
@@ -14950,7 +15310,7 @@ function PolygonHotspot({
14950
15310
  transparent: true
14951
15311
  }
14952
15312
  ) }),
14953
- /* @__PURE__ */ jsx30(
15313
+ /* @__PURE__ */ jsx31(
14954
15314
  HotspotStrokeLine,
14955
15315
  {
14956
15316
  color: stroke,
@@ -14968,14 +15328,14 @@ function PolygonHotspot({
14968
15328
  }
14969
15329
 
14970
15330
  // src/hotspot/polyline-hotspot.tsx
14971
- import { useEffect as useEffect34, useMemo as useMemo25, useRef as useRef35 } from "react";
15331
+ import { useEffect as useEffect35, useMemo as useMemo26, useRef as useRef36 } from "react";
14972
15332
  import {
14973
15333
  MathUtils as MathUtils11,
14974
15334
  Matrix4 as Matrix46,
14975
15335
  Quaternion as Quaternion6,
14976
- Vector3 as Vector319
15336
+ Vector3 as Vector320
14977
15337
  } from "three";
14978
- import { jsx as jsx31 } from "react/jsx-runtime";
15338
+ import { jsx as jsx32 } from "react/jsx-runtime";
14979
15339
  var POLYLINE_RADIUS = 990;
14980
15340
  var MAX_SEGMENT_DEGREES = 7;
14981
15341
  function cloneVertices2(vertices) {
@@ -15000,7 +15360,7 @@ function unwrapVertices(vertices) {
15000
15360
  function polylineCenter(vertices) {
15001
15361
  const sum = vertices.reduce(
15002
15362
  (total, vertex) => total.add(panoPositionToVector3(vertex).normalize()),
15003
- new Vector319()
15363
+ new Vector320()
15004
15364
  );
15005
15365
  return sum.lengthSq() > 1e-8 ? vector3ToPanoPosition(sum) : normalizePanoPosition(vertices[0]);
15006
15366
  }
@@ -15009,7 +15369,7 @@ function surfaceQuaternion2(position) {
15009
15369
  const inward = outward.clone().negate();
15010
15370
  const pitch = MathUtils11.degToRad(position.pitch);
15011
15371
  const yaw = MathUtils11.degToRad(position.yaw);
15012
- const localUp = new Vector319(
15372
+ const localUp = new Vector320(
15013
15373
  -Math.sin(pitch) * Math.sin(yaw),
15014
15374
  Math.cos(pitch),
15015
15375
  Math.sin(pitch) * Math.cos(yaw)
@@ -15022,7 +15382,7 @@ function makeWorldToLocal2(center) {
15022
15382
  return new Matrix46().compose(
15023
15383
  panoPositionToVector3(center, POLYLINE_RADIUS),
15024
15384
  surfaceQuaternion2(center),
15025
- new Vector319(1, 1, 1)
15385
+ new Vector320(1, 1, 1)
15026
15386
  ).invert();
15027
15387
  }
15028
15388
  function subdivisionSteps(vertices) {
@@ -15092,16 +15452,16 @@ function PolylineHotspot({
15092
15452
  onInvalid,
15093
15453
  ...anchorProps
15094
15454
  }) {
15095
- const issues = useMemo25(() => validatePolylineVertices(vertices), [vertices]);
15455
+ const issues = useMemo26(() => validatePolylineVertices(vertices), [vertices]);
15096
15456
  const valid = issues.length === 0;
15097
- const center = useMemo25(() => valid ? polylineCenter(vertices) : null, [valid, vertices]);
15098
- const linePoints = useMemo25(
15457
+ const center = useMemo26(() => valid ? polylineCenter(vertices) : null, [valid, vertices]);
15458
+ const linePoints = useMemo26(
15099
15459
  () => valid && center ? makeLinePositions(vertices, center) : null,
15100
15460
  [center, valid, vertices]
15101
15461
  );
15102
15462
  const opacity = Math.max(0, Math.min(strokeOpacity, 1));
15103
- const startVerticesRef = useRef35(null);
15104
- useEffect34(() => {
15463
+ const startVerticesRef = useRef36(null);
15464
+ useEffect35(() => {
15105
15465
  if (!valid) onInvalid?.(issues);
15106
15466
  }, [issues, onInvalid, valid]);
15107
15467
  if (!valid || !center || !linePoints || linePoints.length < 2) return null;
@@ -15115,7 +15475,7 @@ function PolylineHotspot({
15115
15475
  startPosition: event.startPosition
15116
15476
  });
15117
15477
  };
15118
- return /* @__PURE__ */ jsx31(
15478
+ return /* @__PURE__ */ jsx32(
15119
15479
  HotspotAnchor,
15120
15480
  {
15121
15481
  ...anchorProps,
@@ -15129,7 +15489,7 @@ function PolylineHotspot({
15129
15489
  renderOrder,
15130
15490
  draggable,
15131
15491
  useAngularScale: false,
15132
- focusContent: /* @__PURE__ */ jsx31(
15492
+ focusContent: /* @__PURE__ */ jsx32(
15133
15493
  HotspotStrokeLine,
15134
15494
  {
15135
15495
  color: "#75cbd3",
@@ -15150,7 +15510,7 @@ function PolylineHotspot({
15150
15510
  emitVerticesChange(event, onDragEnd);
15151
15511
  startVerticesRef.current = null;
15152
15512
  },
15153
- children: /* @__PURE__ */ jsx31(
15513
+ children: /* @__PURE__ */ jsx32(
15154
15514
  HotspotStrokeLine,
15155
15515
  {
15156
15516
  color: stroke,
@@ -15167,7 +15527,7 @@ function PolylineHotspot({
15167
15527
  }
15168
15528
 
15169
15529
  // src/hotspot/graphic-hotspot.tsx
15170
- import { useEffect as useEffect35, useRef as useRef36, useState as useState18 } from "react";
15530
+ import { useEffect as useEffect36, useRef as useRef37, useState as useState18 } from "react";
15171
15531
  import {
15172
15532
  CanvasTexture,
15173
15533
  ClampToEdgeWrapping as ClampToEdgeWrapping4,
@@ -15175,7 +15535,7 @@ import {
15175
15535
  LinearMipmapLinearFilter as LinearMipmapLinearFilter4,
15176
15536
  SRGBColorSpace as SRGBColorSpace6
15177
15537
  } from "three";
15178
- import { jsx as jsx32 } from "react/jsx-runtime";
15538
+ import { jsx as jsx33 } from "react/jsx-runtime";
15179
15539
  var GRAPHIC_TEXTURE_SIZE = 512;
15180
15540
  function resolveStrokeWidth(value) {
15181
15541
  return Number.isFinite(value) ? Math.max(value, 0) : 8;
@@ -15365,11 +15725,11 @@ function createGraphicTexture(graphic, aspectWidth, aspectHeight) {
15365
15725
  }
15366
15726
  function useGraphicTexture(graphic, aspectWidth, aspectHeight, onLoad, onError) {
15367
15727
  const [texture, setTexture] = useState18(null);
15368
- const onLoadRef = useRef36(onLoad);
15369
- const onErrorRef = useRef36(onError);
15728
+ const onLoadRef = useRef37(onLoad);
15729
+ const onErrorRef = useRef37(onError);
15370
15730
  onLoadRef.current = onLoad;
15371
15731
  onErrorRef.current = onError;
15372
- useEffect35(() => {
15732
+ useEffect36(() => {
15373
15733
  let nextTexture = null;
15374
15734
  try {
15375
15735
  nextTexture = createGraphicTexture(graphic, aspectWidth, aspectHeight);
@@ -15395,20 +15755,20 @@ function CanvasGraphicHotspot({
15395
15755
  ...anchorProps
15396
15756
  }) {
15397
15757
  const texture = useGraphicTexture(graphic, width, height, onLoad, onError);
15398
- return /* @__PURE__ */ jsx32(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ jsx32(HotspotPlane, { map: texture, opacity }) });
15758
+ return /* @__PURE__ */ jsx33(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ jsx33(HotspotPlane, { map: texture, opacity }) });
15399
15759
  }
15400
15760
  function GraphicHotspot(props) {
15401
15761
  const { graphic, ...restProps } = props;
15402
15762
  if (graphic.kind === "svg") {
15403
15763
  const imageProps = restProps;
15404
- return /* @__PURE__ */ jsx32(ImageHotspot, { ...imageProps, src: graphic.src });
15764
+ return /* @__PURE__ */ jsx33(ImageHotspot, { ...imageProps, src: graphic.src });
15405
15765
  }
15406
- return /* @__PURE__ */ jsx32(CanvasGraphicHotspot, { ...restProps, graphic });
15766
+ return /* @__PURE__ */ jsx33(CanvasGraphicHotspot, { ...restProps, graphic });
15407
15767
  }
15408
15768
 
15409
15769
  // src/hotspot/sequence-hotspot.tsx
15410
- import { useFrame as useFrame17, useThree as useThree25 } from "@react-three/fiber";
15411
- import { useEffect as useEffect36, useRef as useRef37, useState as useState19 } from "react";
15770
+ import { useFrame as useFrame18, useThree as useThree26 } from "@react-three/fiber";
15771
+ import { useEffect as useEffect37, useRef as useRef38, useState as useState19 } from "react";
15412
15772
  import {
15413
15773
  ClampToEdgeWrapping as ClampToEdgeWrapping5,
15414
15774
  LinearFilter as LinearFilter8,
@@ -15416,7 +15776,7 @@ import {
15416
15776
  SRGBColorSpace as SRGBColorSpace7,
15417
15777
  TextureLoader as TextureLoader6
15418
15778
  } from "three";
15419
- import { jsx as jsx33 } from "react/jsx-runtime";
15779
+ import { jsx as jsx34 } from "react/jsx-runtime";
15420
15780
  var DEFAULT_SEQUENCE_FPS = 12;
15421
15781
  function resolveFps(value) {
15422
15782
  return Number.isFinite(value) && value > 0 ? value : DEFAULT_SEQUENCE_FPS;
@@ -15430,13 +15790,13 @@ function useSpriteTexture({
15430
15790
  onError,
15431
15791
  onLoadProgress
15432
15792
  }) {
15433
- const gl = useThree25((state) => state.gl);
15793
+ const gl = useThree26((state) => state.gl);
15434
15794
  const [texture, setTexture] = useState19(null);
15435
- const onErrorRef = useRef37(onError);
15436
- const onLoadProgressRef = useRef37(onLoadProgress);
15795
+ const onErrorRef = useRef38(onError);
15796
+ const onLoadProgressRef = useRef38(onLoadProgress);
15437
15797
  onErrorRef.current = onError;
15438
15798
  onLoadProgressRef.current = onLoadProgress;
15439
- useEffect36(() => {
15799
+ useEffect37(() => {
15440
15800
  let active = true;
15441
15801
  setTexture(null);
15442
15802
  if (!src) {
@@ -15477,7 +15837,7 @@ function useSpriteTexture({
15477
15837
  active = false;
15478
15838
  };
15479
15839
  }, [gl, id, src]);
15480
- useEffect36(
15840
+ useEffect37(
15481
15841
  () => () => {
15482
15842
  texture?.dispose();
15483
15843
  },
@@ -15507,23 +15867,23 @@ function SequenceHotspot({
15507
15867
  const frameCount = resolveFrameCount(requestedFrameCount);
15508
15868
  const safeFps = resolveFps(fps);
15509
15869
  const [frameIndex, setFrameIndex] = useState19(0);
15510
- const elapsedRef = useRef37(0);
15511
- const frameIndexRef = useRef37(0);
15512
- const endedRef = useRef37(false);
15513
- const lastPlaybackStateRef = useRef37(null);
15514
- const onFrameChangeRef = useRef37(onFrameChange);
15515
- const onPlaybackStateChangeRef = useRef37(onPlaybackStateChange);
15516
- const onEndedRef = useRef37(onEnded);
15870
+ const elapsedRef = useRef38(0);
15871
+ const frameIndexRef = useRef38(0);
15872
+ const endedRef = useRef38(false);
15873
+ const lastPlaybackStateRef = useRef38(null);
15874
+ const onFrameChangeRef = useRef38(onFrameChange);
15875
+ const onPlaybackStateChangeRef = useRef38(onPlaybackStateChange);
15876
+ const onEndedRef = useRef38(onEnded);
15517
15877
  onFrameChangeRef.current = onFrameChange;
15518
15878
  onPlaybackStateChangeRef.current = onPlaybackStateChange;
15519
15879
  onEndedRef.current = onEnded;
15520
- useEffect36(() => {
15880
+ useEffect37(() => {
15521
15881
  elapsedRef.current = 0;
15522
15882
  frameIndexRef.current = 0;
15523
15883
  endedRef.current = false;
15524
15884
  setFrameIndex(0);
15525
15885
  }, [frameCount, frameDirection, src]);
15526
- useEffect36(() => {
15886
+ useEffect37(() => {
15527
15887
  if (!texture) {
15528
15888
  return;
15529
15889
  }
@@ -15537,13 +15897,13 @@ function SequenceHotspot({
15537
15897
  );
15538
15898
  texture.needsUpdate = true;
15539
15899
  }, [frameCount, frameDirection, frameIndex, texture]);
15540
- useEffect36(() => {
15900
+ useEffect37(() => {
15541
15901
  if (!texture) {
15542
15902
  return;
15543
15903
  }
15544
15904
  onFrameChangeRef.current?.({ id, index: 0, src });
15545
15905
  }, [id, src, texture]);
15546
- useEffect36(() => {
15906
+ useEffect37(() => {
15547
15907
  if (!texture) {
15548
15908
  return;
15549
15909
  }
@@ -15562,7 +15922,7 @@ function SequenceHotspot({
15562
15922
  onPlaybackStateChangeRef.current?.(nextState);
15563
15923
  }
15564
15924
  }, [playing, texture]);
15565
- useFrame17((_, deltaSeconds) => {
15925
+ useFrame18((_, deltaSeconds) => {
15566
15926
  if (!texture || !playing || endedRef.current) {
15567
15927
  return;
15568
15928
  }
@@ -15592,12 +15952,12 @@ function SequenceHotspot({
15592
15952
  onFrameChangeRef.current?.({ id, index: nextIndex, src });
15593
15953
  }
15594
15954
  });
15595
- return /* @__PURE__ */ jsx33(HotspotAnchor, { ...anchorProps, id, height, width, children: /* @__PURE__ */ jsx33(HotspotPlane, { map: texture, opacity }) });
15955
+ return /* @__PURE__ */ jsx34(HotspotAnchor, { ...anchorProps, id, height, width, children: /* @__PURE__ */ jsx34(HotspotPlane, { map: texture, opacity }) });
15596
15956
  }
15597
15957
 
15598
15958
  // src/hotspot/video-hotspot.tsx
15599
- import { useThree as useThree26 } from "@react-three/fiber";
15600
- import { useEffect as useEffect37, useRef as useRef38, useState as useState20 } from "react";
15959
+ import { useThree as useThree27 } from "@react-three/fiber";
15960
+ import { useEffect as useEffect38, useRef as useRef39, useState as useState20 } from "react";
15601
15961
  import {
15602
15962
  ClampToEdgeWrapping as ClampToEdgeWrapping6,
15603
15963
  LinearFilter as LinearFilter9,
@@ -15606,7 +15966,7 @@ import {
15606
15966
  TextureLoader as TextureLoader7,
15607
15967
  VideoTexture as VideoTexture2
15608
15968
  } from "three";
15609
- import { jsx as jsx34 } from "react/jsx-runtime";
15969
+ import { jsx as jsx35 } from "react/jsx-runtime";
15610
15970
  function clampVolume2(volume) {
15611
15971
  if (!Number.isFinite(volume)) {
15612
15972
  return 1;
@@ -15614,11 +15974,11 @@ function clampVolume2(volume) {
15614
15974
  return Math.max(0, Math.min(volume, 1));
15615
15975
  }
15616
15976
  function usePosterTexture2(id, poster, onError) {
15617
- const gl = useThree26((state) => state.gl);
15977
+ const gl = useThree27((state) => state.gl);
15618
15978
  const [texture, setTexture] = useState20(null);
15619
- const onErrorRef = useRef38(onError);
15979
+ const onErrorRef = useRef39(onError);
15620
15980
  onErrorRef.current = onError;
15621
- useEffect37(() => {
15981
+ useEffect38(() => {
15622
15982
  let active = true;
15623
15983
  setTexture(null);
15624
15984
  if (!poster) {
@@ -15655,7 +16015,7 @@ function usePosterTexture2(id, poster, onError) {
15655
16015
  active = false;
15656
16016
  };
15657
16017
  }, [gl, id, poster]);
15658
- useEffect37(
16018
+ useEffect38(
15659
16019
  () => () => {
15660
16020
  texture?.dispose();
15661
16021
  },
@@ -15674,13 +16034,13 @@ function useVideoResource({
15674
16034
  src
15675
16035
  }) {
15676
16036
  const [resource, setResource] = useState20(null);
15677
- const onEndedRef = useRef38(onEnded);
15678
- const onErrorRef = useRef38(onError);
15679
- const onPlaybackStateChangeRef = useRef38(onPlaybackStateChange);
16037
+ const onEndedRef = useRef39(onEnded);
16038
+ const onErrorRef = useRef39(onError);
16039
+ const onPlaybackStateChangeRef = useRef39(onPlaybackStateChange);
15680
16040
  onEndedRef.current = onEnded;
15681
16041
  onErrorRef.current = onError;
15682
16042
  onPlaybackStateChangeRef.current = onPlaybackStateChange;
15683
- useEffect37(() => {
16043
+ useEffect38(() => {
15684
16044
  if (!src) {
15685
16045
  setResource(null);
15686
16046
  return;
@@ -15787,11 +16147,11 @@ function VideoHotspot({
15787
16147
  src
15788
16148
  });
15789
16149
  const posterTexture = usePosterTexture2(id, poster, onError);
15790
- const onPlaybackErrorRef = useRef38(onPlaybackError);
15791
- const onPlaybackStateChangeRef = useRef38(onPlaybackStateChange);
16150
+ const onPlaybackErrorRef = useRef39(onPlaybackError);
16151
+ const onPlaybackStateChangeRef = useRef39(onPlaybackStateChange);
15792
16152
  onPlaybackErrorRef.current = onPlaybackError;
15793
16153
  onPlaybackStateChangeRef.current = onPlaybackStateChange;
15794
- useEffect37(() => {
16154
+ useEffect38(() => {
15795
16155
  if (!resource) {
15796
16156
  return;
15797
16157
  }
@@ -15808,7 +16168,7 @@ function VideoHotspot({
15808
16168
  }
15809
16169
  resource.video.preload = preload;
15810
16170
  }, [loop, muted, playsInline, preload, resource, volume]);
15811
- useEffect37(() => {
16171
+ useEffect38(() => {
15812
16172
  if (!resource) {
15813
16173
  return;
15814
16174
  }
@@ -15831,12 +16191,12 @@ function VideoHotspot({
15831
16191
  };
15832
16192
  }, [playing, resource]);
15833
16193
  const activeTexture = resource?.ready ? resource.texture : posterTexture;
15834
- return /* @__PURE__ */ jsx34(HotspotAnchor, { ...anchorProps, id, height, width, children: /* @__PURE__ */ jsx34(HotspotPlane, { map: activeTexture, opacity }) });
16194
+ return /* @__PURE__ */ jsx35(HotspotAnchor, { ...anchorProps, id, height, width, children: /* @__PURE__ */ jsx35(HotspotPlane, { map: activeTexture, opacity }) });
15835
16195
  }
15836
16196
 
15837
16197
  // src/hotspot/audio-hotspot.tsx
15838
- import { useFrame as useFrame18, useThree as useThree27 } from "@react-three/fiber";
15839
- import { useEffect as useEffect38, useRef as useRef39, useState as useState21 } from "react";
16198
+ import { useFrame as useFrame19, useThree as useThree28 } from "@react-three/fiber";
16199
+ import { useEffect as useEffect39, useRef as useRef40, useState as useState21 } from "react";
15840
16200
  import {
15841
16201
  CanvasTexture as CanvasTexture2,
15842
16202
  ClampToEdgeWrapping as ClampToEdgeWrapping7,
@@ -15845,7 +16205,7 @@ import {
15845
16205
  SRGBColorSpace as SRGBColorSpace9,
15846
16206
  TextureLoader as TextureLoader8
15847
16207
  } from "three";
15848
- import { jsx as jsx35 } from "react/jsx-runtime";
16208
+ import { jsx as jsx36 } from "react/jsx-runtime";
15849
16209
  var SPEAKER_TEXTURE_SIZE = 512;
15850
16210
  function paintSpeakerBody(context, center) {
15851
16211
  context.fillStyle = "#f5fbfc";
@@ -15910,7 +16270,7 @@ function createSpeakerTexture(state) {
15910
16270
  }
15911
16271
  function useSpeakerTextures(enabled) {
15912
16272
  const [textures, setTextures] = useState21({ playing: null, stopped: null });
15913
- useEffect38(() => {
16273
+ useEffect39(() => {
15914
16274
  if (!enabled) {
15915
16275
  setTextures({ playing: null, stopped: null });
15916
16276
  return;
@@ -15926,11 +16286,11 @@ function useSpeakerTextures(enabled) {
15926
16286
  return textures;
15927
16287
  }
15928
16288
  function useIconTexture(icon, enabled, onError, id) {
15929
- const gl = useThree27((state) => state.gl);
16289
+ const gl = useThree28((state) => state.gl);
15930
16290
  const [texture, setTexture] = useState21(null);
15931
- const onErrorRef = useRef39(onError);
16291
+ const onErrorRef = useRef40(onError);
15932
16292
  onErrorRef.current = onError;
15933
- useEffect38(() => {
16293
+ useEffect39(() => {
15934
16294
  let active = true;
15935
16295
  setTexture(null);
15936
16296
  if (!enabled || !icon) {
@@ -15967,7 +16327,7 @@ function useIconTexture(icon, enabled, onError, id) {
15967
16327
  active = false;
15968
16328
  };
15969
16329
  }, [enabled, gl, icon, id]);
15970
- useEffect38(
16330
+ useEffect39(
15971
16331
  () => () => {
15972
16332
  texture?.dispose();
15973
16333
  },
@@ -15987,12 +16347,12 @@ function useAudioHowl({
15987
16347
  src
15988
16348
  }) {
15989
16349
  const [howl, setHowl] = useState21(null);
15990
- const playingRef = useRef39(playing);
15991
- const loopRef = useRef39(loop ?? false);
15992
- const onEndedRef = useRef39(onEnded);
15993
- const onErrorRef = useRef39(onError);
15994
- const onPlaybackErrorRef = useRef39(onPlaybackError);
15995
- const onPlaybackStateChangeRef = useRef39(onPlaybackStateChange);
16350
+ const playingRef = useRef40(playing);
16351
+ const loopRef = useRef40(loop ?? false);
16352
+ const onEndedRef = useRef40(onEnded);
16353
+ const onErrorRef = useRef40(onError);
16354
+ const onPlaybackErrorRef = useRef40(onPlaybackError);
16355
+ const onPlaybackStateChangeRef = useRef40(onPlaybackStateChange);
15996
16356
  playingRef.current = playing;
15997
16357
  loopRef.current = loop ?? false;
15998
16358
  onEndedRef.current = onEnded;
@@ -16000,7 +16360,7 @@ function useAudioHowl({
16000
16360
  onPlaybackErrorRef.current = onPlaybackError;
16001
16361
  onPlaybackStateChangeRef.current = onPlaybackStateChange;
16002
16362
  const sourcesKey = sourceList(src).join("\0");
16003
- useEffect38(() => {
16363
+ useEffect39(() => {
16004
16364
  const sources = sourcesKey.length > 0 ? sourcesKey.split("\0") : [];
16005
16365
  if (sources.length === 0) {
16006
16366
  setHowl(null);
@@ -16037,7 +16397,7 @@ function useAudioHowl({
16037
16397
  handle.dispose();
16038
16398
  };
16039
16399
  }, [crossOrigin, id, sourcesKey]);
16040
- useEffect38(() => {
16400
+ useEffect39(() => {
16041
16401
  howl?.loop(loop ?? false);
16042
16402
  }, [howl, loop]);
16043
16403
  return howl;
@@ -16065,7 +16425,7 @@ function AudioHotspot({
16065
16425
  ...anchorProps
16066
16426
  }) {
16067
16427
  usePanoMediaActivationIntent(playing);
16068
- const camera = useThree27((state) => state.camera);
16428
+ const camera = useThree28((state) => state.camera);
16069
16429
  const howl = useAudioHowl({
16070
16430
  crossOrigin,
16071
16431
  id,
@@ -16081,15 +16441,15 @@ function AudioHotspot({
16081
16441
  const stoppedIconTexture = useIconTexture(icon, marker, onError, id);
16082
16442
  const playingIconTexture = useIconTexture(playingIcon, marker, onError, id);
16083
16443
  const markerTexture = playing ? playingIconTexture ?? stoppedIconTexture ?? speakerTextures.playing : stoppedIconTexture ?? speakerTextures.stopped;
16084
- const playingRef = useRef39(playing);
16444
+ const playingRef = useRef40(playing);
16085
16445
  playingRef.current = playing;
16086
- const mutedRef = useRef39(muted);
16087
- const volumeRef = useRef39(volume);
16088
- const rangeRef = useRef39(range);
16446
+ const mutedRef = useRef40(muted);
16447
+ const volumeRef = useRef40(volume);
16448
+ const rangeRef = useRef40(range);
16089
16449
  mutedRef.current = muted;
16090
16450
  volumeRef.current = volume;
16091
16451
  rangeRef.current = range;
16092
- useEffect38(() => {
16452
+ useEffect39(() => {
16093
16453
  if (!howl) {
16094
16454
  return;
16095
16455
  }
@@ -16099,7 +16459,7 @@ function AudioHotspot({
16099
16459
  }
16100
16460
  howl.play();
16101
16461
  }, [howl, playing]);
16102
- useEffect38(() => {
16462
+ useEffect39(() => {
16103
16463
  if (!howl || !pauseWhenHidden) {
16104
16464
  return;
16105
16465
  }
@@ -16117,7 +16477,7 @@ function AudioHotspot({
16117
16477
  document.removeEventListener("visibilitychange", handleVisibility);
16118
16478
  };
16119
16479
  }, [howl, pauseWhenHidden]);
16120
- useFrame18(() => {
16480
+ useFrame19(() => {
16121
16481
  if (!howl) {
16122
16482
  return;
16123
16483
  }
@@ -16130,11 +16490,11 @@ function AudioHotspot({
16130
16490
  howl.mute(mutedRef.current);
16131
16491
  howl.volume(clampAudioVolume(volumeRef.current) * spatial.gain);
16132
16492
  });
16133
- return /* @__PURE__ */ jsx35(HotspotAnchor, { ...anchorProps, id, height, width, children: marker ? /* @__PURE__ */ jsx35(HotspotPlane, { map: markerTexture, opacity }) : null });
16493
+ return /* @__PURE__ */ jsx36(HotspotAnchor, { ...anchorProps, id, height, width, children: marker ? /* @__PURE__ */ jsx36(HotspotPlane, { map: markerTexture, opacity }) : null });
16134
16494
  }
16135
16495
 
16136
16496
  // src/hotspot/text-hotspot.tsx
16137
- import { useEffect as useEffect39, useRef as useRef40, useState as useState22 } from "react";
16497
+ import { useEffect as useEffect40, useRef as useRef41, useState as useState22 } from "react";
16138
16498
  import {
16139
16499
  CanvasTexture as CanvasTexture3,
16140
16500
  ClampToEdgeWrapping as ClampToEdgeWrapping8,
@@ -16142,7 +16502,7 @@ import {
16142
16502
  LinearMipmapLinearFilter as LinearMipmapLinearFilter8,
16143
16503
  SRGBColorSpace as SRGBColorSpace10
16144
16504
  } from "three";
16145
- import { jsx as jsx36 } from "react/jsx-runtime";
16505
+ import { jsx as jsx37 } from "react/jsx-runtime";
16146
16506
  var TEXT_TEXTURE_LONG_SIDE = 1024;
16147
16507
  var DEFAULT_FONT_FAMILY = "system-ui, sans-serif";
16148
16508
  var DEFAULT_FONT_SIZE = 96;
@@ -16363,11 +16723,11 @@ function createTextTexture(text, width, height, style) {
16363
16723
  }
16364
16724
  function useTextTexture(text, width, height, style, onLoad, onError) {
16365
16725
  const [texture, setTexture] = useState22(null);
16366
- const onLoadRef = useRef40(onLoad);
16367
- const onErrorRef = useRef40(onError);
16726
+ const onLoadRef = useRef41(onLoad);
16727
+ const onErrorRef = useRef41(onError);
16368
16728
  onLoadRef.current = onLoad;
16369
16729
  onErrorRef.current = onError;
16370
- useEffect39(() => {
16730
+ useEffect40(() => {
16371
16731
  let cancelled = false;
16372
16732
  let nextTexture = null;
16373
16733
  const run = async () => {
@@ -16460,13 +16820,13 @@ function TextHotspot({
16460
16820
  whiteSpace
16461
16821
  };
16462
16822
  const texture = useTextTexture(text, width, height, style, onLoad, onError);
16463
- return /* @__PURE__ */ jsx36(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ jsx36(HotspotPlane, { map: texture, opacity }) });
16823
+ return /* @__PURE__ */ jsx37(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ jsx37(HotspotPlane, { map: texture, opacity }) });
16464
16824
  }
16465
16825
 
16466
16826
  // src/hotspot/iframe-hotspot.tsx
16467
16827
  import { Html } from "@react-three/drei";
16468
16828
  import { DoubleSide as DoubleSide6 } from "three";
16469
- import { jsx as jsx37, jsxs as jsxs20 } from "react/jsx-runtime";
16829
+ import { jsx as jsx38, jsxs as jsxs21 } from "react/jsx-runtime";
16470
16830
  var IFRAME_LONG_SIDE = 800;
16471
16831
  var CSS3D_DISTANCE_FACTOR = 400;
16472
16832
  var DEFAULT_SANDBOX = "allow-scripts allow-popups allow-forms";
@@ -16523,7 +16883,7 @@ function IframeHotspot({
16523
16883
  interactive,
16524
16884
  pointerEvents
16525
16885
  );
16526
- return /* @__PURE__ */ jsxs20(
16886
+ return /* @__PURE__ */ jsxs21(
16527
16887
  HotspotAnchor,
16528
16888
  {
16529
16889
  ...anchorProps,
@@ -16532,9 +16892,9 @@ function IframeHotspot({
16532
16892
  pointerEvents,
16533
16893
  width,
16534
16894
  children: [
16535
- /* @__PURE__ */ jsxs20("mesh", { children: [
16536
- /* @__PURE__ */ jsx37("planeGeometry", { args: [1, 1] }),
16537
- /* @__PURE__ */ jsx37(
16895
+ /* @__PURE__ */ jsxs21("mesh", { children: [
16896
+ /* @__PURE__ */ jsx38("planeGeometry", { args: [1, 1] }),
16897
+ /* @__PURE__ */ jsx38(
16538
16898
  "meshBasicMaterial",
16539
16899
  {
16540
16900
  depthWrite: false,
@@ -16545,7 +16905,7 @@ function IframeHotspot({
16545
16905
  }
16546
16906
  )
16547
16907
  ] }),
16548
- /* @__PURE__ */ jsx37(
16908
+ /* @__PURE__ */ jsx38(
16549
16909
  Html,
16550
16910
  {
16551
16911
  distanceFactor: CSS3D_DISTANCE_FACTOR,
@@ -16560,7 +16920,7 @@ function IframeHotspot({
16560
16920
  },
16561
16921
  transform: true,
16562
16922
  zIndexRange: [10, 0],
16563
- children: /* @__PURE__ */ jsx37(
16923
+ children: /* @__PURE__ */ jsx38(
16564
16924
  "iframe",
16565
16925
  {
16566
16926
  allow,