@ericchen1990/pano-view 3.2.3 → 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.cjs CHANGED
@@ -9699,8 +9699,8 @@ function usePanoViewer() {
9699
9699
  }
9700
9700
 
9701
9701
  // src/sphere-tile/sphere-tile.tsx
9702
- var import_fiber15 = require("@react-three/fiber");
9703
- var import_react38 = require("react");
9702
+ var import_fiber16 = require("@react-three/fiber");
9703
+ var import_react40 = require("react");
9704
9704
  var import_three14 = require("three");
9705
9705
 
9706
9706
  // src/asset-url.ts
@@ -9968,6 +9968,27 @@ function PanoBasicMaterial({
9968
9968
  );
9969
9969
  }
9970
9970
 
9971
+ // src/scene-detail.tsx
9972
+ var import_react37 = require("react");
9973
+ var SceneDetailContext = (0, import_react37.createContext)(null);
9974
+ function useSceneDetailReporter() {
9975
+ return (0, import_react37.useContext)(SceneDetailContext);
9976
+ }
9977
+ function viewTilesAreDrawable(textures) {
9978
+ return textures.length > 0 && textures.every((texture) => texture != null);
9979
+ }
9980
+ function publishSceneDetail(reporter, lastToken, ready) {
9981
+ if (!reporter) {
9982
+ return;
9983
+ }
9984
+ const token = `${reporter.generation}:${ready ? 1 : 0}`;
9985
+ if (lastToken.current === token) {
9986
+ return;
9987
+ }
9988
+ lastToken.current = token;
9989
+ reporter.report(ready);
9990
+ }
9991
+
9971
9992
  // src/tile/texture-manager.ts
9972
9993
  var import_three11 = require("three");
9973
9994
  var EMPTY_TEXTURE_SNAPSHOT = {
@@ -9989,6 +10010,9 @@ var TileTextureManager = class {
9989
10010
  this.generation = 0;
9990
10011
  this.options = options;
9991
10012
  }
10013
+ get memoryBudgetBytes() {
10014
+ return this.options.maxBytes;
10015
+ }
9992
10016
  resume() {
9993
10017
  this.disposed = false;
9994
10018
  this.drain();
@@ -10056,7 +10080,7 @@ var TileTextureManager = class {
10056
10080
  this.totalBytes = 0;
10057
10081
  }
10058
10082
  /**
10059
- * Releases textures that are no longer rendered by any Tile instance.
10083
+ * Releases textures that are no longer rendered by any tile source.
10060
10084
  * Scene transitions call this after the outgoing panorama has been
10061
10085
  * snapshotted, so the incoming scene never competes with stale GPU tiles.
10062
10086
  */
@@ -10190,14 +10214,45 @@ var TileTextureManager = class {
10190
10214
  }
10191
10215
  };
10192
10216
 
10217
+ // src/tile/texture-manager-context.tsx
10218
+ var import_fiber15 = require("@react-three/fiber");
10219
+ var import_react38 = require("react");
10220
+ var import_jsx_runtime15 = require("react/jsx-runtime");
10221
+ var TileTextureManagerContext = (0, import_react38.createContext)(null);
10222
+ function TileTextureManagerProvider({
10223
+ children,
10224
+ maxTextureMemoryMb = 128,
10225
+ maxConcurrentLoads = 4
10226
+ }) {
10227
+ const gl = (0, import_fiber15.useThree)((state) => state.gl);
10228
+ const anisotropy = gl.capabilities.getMaxAnisotropy();
10229
+ const manager = (0, import_react38.useMemo)(
10230
+ () => new TileTextureManager({
10231
+ anisotropy,
10232
+ maxBytes: Math.max(1, maxTextureMemoryMb) * 1024 * 1024,
10233
+ concurrency: Math.max(1, Math.floor(maxConcurrentLoads)),
10234
+ retryCount: 1
10235
+ }),
10236
+ [anisotropy, maxConcurrentLoads, maxTextureMemoryMb]
10237
+ );
10238
+ (0, import_react38.useEffect)(() => {
10239
+ manager.resume();
10240
+ return () => manager.dispose();
10241
+ }, [manager]);
10242
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TileTextureManagerContext.Provider, { value: manager, children });
10243
+ }
10244
+ function useSharedTileTextureManager() {
10245
+ return (0, import_react38.useContext)(TileTextureManagerContext);
10246
+ }
10247
+
10193
10248
  // src/tile/texture-hooks.ts
10194
- var import_react37 = require("react");
10249
+ var import_react39 = require("react");
10195
10250
  var import_three12 = require("three");
10196
10251
  function usePreviewTexture(url, anisotropy, onError) {
10197
- const [texture, setTexture] = (0, import_react37.useState)(null);
10198
- const onErrorRef = (0, import_react37.useRef)(onError);
10252
+ const [texture, setTexture] = (0, import_react39.useState)(null);
10253
+ const onErrorRef = (0, import_react39.useRef)(onError);
10199
10254
  onErrorRef.current = onError;
10200
- (0, import_react37.useEffect)(() => {
10255
+ (0, import_react39.useEffect)(() => {
10201
10256
  if (!url) {
10202
10257
  setTexture(null);
10203
10258
  return;
@@ -10234,7 +10289,7 @@ function usePreviewTexture(url, anisotropy, onError) {
10234
10289
  active = false;
10235
10290
  };
10236
10291
  }, [anisotropy, url]);
10237
- (0, import_react37.useEffect)(
10292
+ (0, import_react39.useEffect)(
10238
10293
  () => () => {
10239
10294
  texture?.dispose();
10240
10295
  },
@@ -10243,14 +10298,14 @@ function usePreviewTexture(url, anisotropy, onError) {
10243
10298
  return texture;
10244
10299
  }
10245
10300
  function useManagedTexture(manager, key, url, address) {
10246
- const [managedState, setManagedState] = (0, import_react37.useState)(() => ({
10301
+ const [managedState, setManagedState] = (0, import_react39.useState)(() => ({
10247
10302
  manager,
10248
10303
  key,
10249
10304
  url,
10250
10305
  snapshot: manager.getSnapshot(key)
10251
10306
  }));
10252
10307
  const snapshot = managedState.manager === manager && managedState.key === key && managedState.url === url ? managedState.snapshot : manager.getSnapshot(key);
10253
- (0, import_react37.useEffect)(
10308
+ (0, import_react39.useEffect)(
10254
10309
  () => manager.acquire(key, url, address, (nextSnapshot) => {
10255
10310
  setManagedState({
10256
10311
  manager,
@@ -10392,14 +10447,23 @@ function preferredSphereLevel(levels, height, dpr, verticalFov) {
10392
10447
  }
10393
10448
 
10394
10449
  // src/sphere-tile/sphere-tile.tsx
10395
- var import_jsx_runtime15 = require("react/jsx-runtime");
10450
+ var import_jsx_runtime16 = require("react/jsx-runtime");
10451
+ function sphereTileViewShouldRefresh(input) {
10452
+ if (input.loadModeChanged || input.managerChanged) {
10453
+ return true;
10454
+ }
10455
+ if (input.elapsedMs < 100 || input.viewUnchanged) {
10456
+ return false;
10457
+ }
10458
+ return true;
10459
+ }
10396
10460
  function SpherePatch({
10397
10461
  address,
10398
10462
  texture,
10399
10463
  yawOffset,
10400
10464
  preview = false
10401
10465
  }) {
10402
- const geometry = (0, import_react38.useMemo)(
10466
+ const geometry = (0, import_react40.useMemo)(
10403
10467
  () => sphereTileGeometry(
10404
10468
  address,
10405
10469
  yawOffset,
@@ -10407,13 +10471,13 @@ function SpherePatch({
10407
10471
  ),
10408
10472
  [address, yawOffset, preview]
10409
10473
  );
10410
- (0, import_react38.useEffect)(() => () => geometry.dispose(), [geometry]);
10411
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
10474
+ (0, import_react40.useEffect)(() => () => geometry.dispose(), [geometry]);
10475
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
10412
10476
  "mesh",
10413
10477
  {
10414
10478
  geometry,
10415
10479
  renderOrder: preview ? -1e3 : -900 + address.level,
10416
- children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
10480
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
10417
10481
  PanoBasicMaterial,
10418
10482
  {
10419
10483
  map: texture,
@@ -10426,7 +10490,7 @@ function SpherePatch({
10426
10490
  }
10427
10491
  );
10428
10492
  }
10429
- var ManagedPatch = (0, import_react38.memo)(function ManagedPatch2({
10493
+ var ManagedPatch = (0, import_react40.memo)(function ManagedPatch2({
10430
10494
  address,
10431
10495
  manager,
10432
10496
  resolveUrl,
@@ -10440,10 +10504,10 @@ var ManagedPatch = (0, import_react38.memo)(function ManagedPatch2({
10440
10504
  url,
10441
10505
  address
10442
10506
  );
10443
- (0, import_react38.useEffect)(() => {
10507
+ (0, import_react40.useEffect)(() => {
10444
10508
  if (snapshot.texture) ready();
10445
10509
  }, [snapshot.texture, ready]);
10446
- return snapshot.texture ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
10510
+ return snapshot.texture ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
10447
10511
  SpherePatch,
10448
10512
  {
10449
10513
  address,
@@ -10471,28 +10535,29 @@ function SphereTileSource({
10471
10535
  onTileError,
10472
10536
  onLevelChange
10473
10537
  }) {
10474
- const { camera, gl, size } = (0, import_fiber15.useThree)();
10538
+ const { camera, gl, size } = (0, import_fiber16.useThree)();
10475
10539
  const anisotropy = gl.capabilities.getMaxAnisotropy();
10476
10540
  const preview = usePreviewTexture(
10477
10541
  resolveAssetUrl(baseUrl, previewUrl),
10478
10542
  anisotropy,
10479
10543
  onPreviewError
10480
10544
  );
10481
- const callbacks = (0, import_react38.useRef)({
10545
+ const callbacks = (0, import_react40.useRef)({
10482
10546
  onReady,
10483
10547
  onLoadProgress,
10484
10548
  onTileError,
10485
10549
  onLevelChange
10486
10550
  });
10487
10551
  callbacks.current = { onReady, onLoadProgress, onTileError, onLevelChange };
10488
- const budget = Math.max(
10552
+ const sharedManager = useSharedTileTextureManager();
10553
+ const ownedBudget = Math.max(
10489
10554
  1,
10490
10555
  Number.isFinite(maxTextureMemoryMb) ? maxTextureMemoryMb : 128
10491
10556
  ) * 1024 * 1024;
10492
- const manager = (0, import_react38.useMemo)(
10557
+ const ownedManager = (0, import_react40.useMemo)(
10493
10558
  () => new TileTextureManager({
10494
10559
  anisotropy,
10495
- maxBytes: budget,
10560
+ maxBytes: ownedBudget,
10496
10561
  concurrency: Math.max(
10497
10562
  1,
10498
10563
  Math.floor(
@@ -10506,30 +10571,38 @@ function SphereTileSource({
10506
10571
  onProgress: (progress) => callbacks.current.onLoadProgress?.(progress),
10507
10572
  onError: (error) => callbacks.current.onTileError?.(error)
10508
10573
  }),
10509
- [anisotropy, budget, maxConcurrentLoads, retryCount]
10574
+ [anisotropy, ownedBudget, maxConcurrentLoads, retryCount]
10510
10575
  );
10511
- const readyRef = (0, import_react38.useRef)(false);
10512
- const ready = (0, import_react38.useCallback)(() => {
10576
+ const manager = sharedManager ?? ownedManager;
10577
+ const budget = manager.memoryBudgetBytes;
10578
+ const readyRef = (0, import_react40.useRef)(false);
10579
+ const ready = (0, import_react40.useCallback)(() => {
10513
10580
  if (!readyRef.current) {
10514
10581
  readyRef.current = true;
10515
10582
  callbacks.current.onReady?.();
10516
10583
  }
10517
10584
  }, []);
10518
- (0, import_react38.useEffect)(() => {
10585
+ (0, import_react40.useEffect)(() => {
10519
10586
  if (preview) ready();
10520
10587
  }, [preview, ready]);
10521
- (0, import_react38.useEffect)(() => {
10588
+ (0, import_react40.useEffect)(() => {
10522
10589
  manager.resume();
10523
- return () => manager.dispose();
10524
- }, [manager]);
10525
- const resolveUrl = (0, import_react38.useMemo)(
10590
+ return () => {
10591
+ if (manager === ownedManager) {
10592
+ manager.dispose();
10593
+ return;
10594
+ }
10595
+ queueMicrotask(() => manager.releaseUnused());
10596
+ };
10597
+ }, [manager, ownedManager]);
10598
+ const resolveUrl = (0, import_react40.useMemo)(
10526
10599
  () => (address) => resolveAssetUrl(
10527
10600
  baseUrl,
10528
10601
  resolveTileUrl ? resolveTileUrl(address) : resolveSphereTemplateUrl(urlTemplate, address, indexBase)
10529
10602
  ),
10530
10603
  [baseUrl, resolveTileUrl, urlTemplate, indexBase]
10531
10604
  );
10532
- const candidates = (0, import_react38.useMemo)(
10605
+ const candidates = (0, import_react40.useMemo)(
10533
10606
  () => config.levels.map(
10534
10607
  (level, index) => sphereTileAddresses(level, index, config.tileSize).map((address) => ({
10535
10608
  address,
@@ -10538,12 +10611,17 @@ function SphereTileSource({
10538
10611
  ),
10539
10612
  [config, yawOffset]
10540
10613
  );
10541
- const previewAddress = (0, import_react38.useMemo)(
10614
+ const previewAddress = (0, import_react40.useMemo)(
10542
10615
  () => sphereTileAddresses({ width: 2, height: 1 }, 0, 2)[0],
10543
10616
  []
10544
10617
  );
10545
- const [layers, setLayers] = (0, import_react38.useState)([]);
10546
- const scratch = (0, import_react38.useMemo)(
10618
+ const [layers, setLayers] = (0, import_react40.useState)([]);
10619
+ const detailReporter = useSceneDetailReporter();
10620
+ const detailReporterRef = (0, import_react40.useRef)(detailReporter);
10621
+ detailReporterRef.current = detailReporter;
10622
+ const detailTokenRef = (0, import_react40.useRef)("");
10623
+ const targetKeysRef = (0, import_react40.useRef)([]);
10624
+ const scratch = (0, import_react40.useMemo)(
10547
10625
  () => ({
10548
10626
  camera: new import_three14.PerspectiveCamera(),
10549
10627
  frustum: new import_three14.Frustum(),
@@ -10561,59 +10639,78 @@ function SphereTileSource({
10561
10639
  }),
10562
10640
  [camera, candidates]
10563
10641
  );
10564
- (0, import_fiber15.useFrame)(() => {
10642
+ (0, import_fiber16.useFrame)(() => {
10565
10643
  if (!(camera instanceof import_three14.PerspectiveCamera)) return;
10566
10644
  const now = performance.now(), dpr = gl.getPixelRatio();
10567
- const reset = scratch.manager !== manager || scratch.loadMode !== loadMode;
10568
- 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))
10569
- return;
10570
- scratch.time = now;
10571
- scratch.fov = camera.fov;
10572
- scratch.width = size.width;
10573
- scratch.height = size.height;
10574
- scratch.dpr = dpr;
10575
- scratch.quaternion.copy(camera.quaternion);
10576
- scratch.manager = manager;
10577
- scratch.loadMode = loadMode;
10578
- scratch.camera.copy(camera, false);
10579
- scratch.camera.fov = Math.min(179, camera.fov + 8);
10580
- scratch.camera.updateProjectionMatrix();
10581
- scratch.camera.updateMatrixWorld();
10582
- scratch.matrix.multiplyMatrices(
10583
- scratch.camera.projectionMatrix,
10584
- scratch.camera.matrixWorldInverse
10585
- );
10586
- scratch.frustum.setFromProjectionMatrix(scratch.matrix);
10587
- let level = loadMode === "preview" ? -1 : loadMode === "base" ? 0 : preferredSphereLevel(config.levels, size.height, dpr, camera.fov);
10588
- const next = [];
10589
- let residentBytes = 0;
10590
- for (let index = 0; index <= level; index++) {
10591
- const addresses = candidates[index].filter(
10592
- ({ bounds }) => scratch.frustum.intersectsBox(bounds)
10593
- ).map(({ address }) => address);
10594
- const bytes = addresses.reduce(
10595
- (total, address) => total + address.width * address.height * 4,
10596
- 0
10645
+ const managerChanged = scratch.manager !== manager;
10646
+ const loadModeChanged = scratch.loadMode !== loadMode;
10647
+ const viewUnchanged = scratch.fov === camera.fov && scratch.width === size.width && scratch.height === size.height && scratch.dpr === dpr && scratch.quaternion.angleTo(camera.quaternion) < 1e-4;
10648
+ if (sphereTileViewShouldRefresh({
10649
+ loadModeChanged,
10650
+ managerChanged,
10651
+ elapsedMs: now - scratch.time,
10652
+ viewUnchanged
10653
+ })) {
10654
+ const reset = managerChanged || loadModeChanged;
10655
+ scratch.time = now;
10656
+ scratch.fov = camera.fov;
10657
+ scratch.width = size.width;
10658
+ scratch.height = size.height;
10659
+ scratch.dpr = dpr;
10660
+ scratch.quaternion.copy(camera.quaternion);
10661
+ scratch.manager = manager;
10662
+ scratch.loadMode = loadMode;
10663
+ scratch.camera.copy(camera, false);
10664
+ scratch.camera.fov = Math.min(179, camera.fov + 8);
10665
+ scratch.camera.updateProjectionMatrix();
10666
+ scratch.camera.updateMatrixWorld();
10667
+ scratch.matrix.multiplyMatrices(
10668
+ scratch.camera.projectionMatrix,
10669
+ scratch.camera.matrixWorldInverse
10597
10670
  );
10598
- if (residentBytes + bytes > budget) {
10599
- level = index - 1;
10600
- break;
10671
+ scratch.frustum.setFromProjectionMatrix(scratch.matrix);
10672
+ let level = loadMode === "preview" ? -1 : loadMode === "base" ? 0 : preferredSphereLevel(config.levels, size.height, dpr, camera.fov);
10673
+ const next = [];
10674
+ let residentBytes = 0;
10675
+ for (let index = 0; index <= level; index++) {
10676
+ const addresses = candidates[index].filter(
10677
+ ({ bounds }) => scratch.frustum.intersectsBox(bounds)
10678
+ ).map(({ address }) => address);
10679
+ const bytes = addresses.reduce(
10680
+ (total, address) => total + address.width * address.height * 4,
10681
+ 0
10682
+ );
10683
+ if (residentBytes + bytes > budget) {
10684
+ level = index - 1;
10685
+ break;
10686
+ }
10687
+ residentBytes += bytes;
10688
+ next.push({ level: index, addresses });
10689
+ }
10690
+ const targetLayer = loadMode === "full" ? next[next.length - 1] : void 0;
10691
+ targetKeysRef.current = targetLayer ? targetLayer.addresses.map(
10692
+ (address) => `${resolveUrl(address)}\0${sphereTileKey(address)}`
10693
+ ) : [];
10694
+ if (level !== scratch.level) {
10695
+ scratch.level = level;
10696
+ if (level >= 0) callbacks.current.onLevelChange?.(level);
10697
+ }
10698
+ const token = next.map((layer) => layer.addresses.map(sphereTileKey).join(",")).join(";");
10699
+ if (token !== scratch.token || reset) {
10700
+ scratch.token = token;
10701
+ setLayers(next);
10601
10702
  }
10602
- residentBytes += bytes;
10603
- next.push({ level: index, addresses });
10604
- }
10605
- if (level !== scratch.level) {
10606
- scratch.level = level;
10607
- if (level >= 0) callbacks.current.onLevelChange?.(level);
10608
- }
10609
- const token = next.map((layer) => layer.addresses.map(sphereTileKey).join(",")).join(";");
10610
- if (token !== scratch.token || reset) {
10611
- scratch.token = token;
10612
- setLayers(next);
10613
10703
  }
10704
+ publishSceneDetail(
10705
+ detailReporterRef.current,
10706
+ detailTokenRef,
10707
+ loadMode === "full" && viewTilesAreDrawable(
10708
+ targetKeysRef.current.map((key) => manager.getSnapshot(key).texture)
10709
+ )
10710
+ );
10614
10711
  });
10615
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("group", { visible, children: [
10616
- preview ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
10712
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("group", { visible, children: [
10713
+ preview ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
10617
10714
  SpherePatch,
10618
10715
  {
10619
10716
  address: previewAddress,
@@ -10623,7 +10720,7 @@ function SphereTileSource({
10623
10720
  }
10624
10721
  ) : null,
10625
10722
  loadMode !== "preview" ? layers.flatMap(
10626
- (layer) => layer.addresses.map((address) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
10723
+ (layer) => layer.addresses.map((address) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
10627
10724
  ManagedPatch,
10628
10725
  {
10629
10726
  address,
@@ -10639,23 +10736,23 @@ function SphereTileSource({
10639
10736
  }
10640
10737
  function SphereTile({ multires, ...props }) {
10641
10738
  const token = typeof multires === "string" ? multires : JSON.stringify(multires);
10642
- const config = (0, import_react38.useMemo)(() => parseSphereMultires(multires), [token]);
10739
+ const config = (0, import_react40.useMemo)(() => parseSphereMultires(multires), [token]);
10643
10740
  const sourceKey = `${props.baseUrl}\0${token}\0${props.previewUrl}\0${props.urlTemplate ?? ""}\0${props.indexBase ?? 1}`;
10644
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(SphereTileSource, { ...props, config }, sourceKey);
10741
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(SphereTileSource, { ...props, config }, sourceKey);
10645
10742
  }
10646
10743
 
10647
10744
  // src/sphere.tsx
10648
- var import_fiber16 = require("@react-three/fiber");
10649
- var import_react39 = require("react");
10745
+ var import_fiber17 = require("@react-three/fiber");
10746
+ var import_react41 = require("react");
10650
10747
  var import_three15 = require("three");
10651
- var import_jsx_runtime16 = require("react/jsx-runtime");
10748
+ var import_jsx_runtime17 = require("react/jsx-runtime");
10652
10749
  function useEquirectTexture(url, anisotropy, generateMipmaps, onLoad, onError) {
10653
- const [texture, setTexture] = (0, import_react39.useState)(null);
10654
- const onLoadRef = (0, import_react39.useRef)(onLoad);
10655
- const onErrorRef = (0, import_react39.useRef)(onError);
10750
+ const [texture, setTexture] = (0, import_react41.useState)(null);
10751
+ const onLoadRef = (0, import_react41.useRef)(onLoad);
10752
+ const onErrorRef = (0, import_react41.useRef)(onError);
10656
10753
  onLoadRef.current = onLoad;
10657
10754
  onErrorRef.current = onError;
10658
- (0, import_react39.useEffect)(() => {
10755
+ (0, import_react41.useEffect)(() => {
10659
10756
  if (!url) {
10660
10757
  setTexture(null);
10661
10758
  return;
@@ -10694,7 +10791,7 @@ function useEquirectTexture(url, anisotropy, generateMipmaps, onLoad, onError) {
10694
10791
  active = false;
10695
10792
  };
10696
10793
  }, [anisotropy, generateMipmaps, url]);
10697
- (0, import_react39.useEffect)(
10794
+ (0, import_react41.useEffect)(
10698
10795
  () => () => {
10699
10796
  texture?.dispose();
10700
10797
  },
@@ -10712,9 +10809,9 @@ function Sphere({
10712
10809
  onPreviewError,
10713
10810
  visible = true
10714
10811
  }) {
10715
- const gl = (0, import_fiber16.useThree)((state) => state.gl);
10812
+ const gl = (0, import_fiber17.useThree)((state) => state.gl);
10716
10813
  const anisotropy = gl.capabilities.getMaxAnisotropy();
10717
- const resolvedPreviewUrl = (0, import_react39.useMemo)(
10814
+ const resolvedPreviewUrl = (0, import_react41.useMemo)(
10718
10815
  () => resolveUrlAgainstFile(src, previewUrl),
10719
10816
  [previewUrl, src]
10720
10817
  );
@@ -10733,11 +10830,21 @@ function Sphere({
10733
10830
  onPreviewError
10734
10831
  );
10735
10832
  const displayTexture = texture ?? previewTexture;
10736
- const readyRef = (0, import_react39.useRef)(false);
10737
- (0, import_react39.useEffect)(() => {
10833
+ const readyRef = (0, import_react41.useRef)(false);
10834
+ const detailReporter = useSceneDetailReporter();
10835
+ (0, import_react41.useEffect)(() => {
10738
10836
  readyRef.current = false;
10739
10837
  }, [resolvedPreviewUrl, src]);
10740
- (0, import_react39.useEffect)(() => {
10838
+ (0, import_react41.useEffect)(() => {
10839
+ if (!detailReporter) {
10840
+ return;
10841
+ }
10842
+ detailReporter.report(texture != null);
10843
+ return () => {
10844
+ detailReporter.report(false);
10845
+ };
10846
+ }, [detailReporter, texture]);
10847
+ (0, import_react41.useEffect)(() => {
10741
10848
  if (!displayTexture || readyRef.current) {
10742
10849
  return;
10743
10850
  }
@@ -10747,14 +10854,14 @@ function Sphere({
10747
10854
  if (!displayTexture) {
10748
10855
  return null;
10749
10856
  }
10750
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
10857
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
10751
10858
  "mesh",
10752
10859
  {
10753
10860
  rotation: [0, import_three15.MathUtils.degToRad(90 + yawOffset), 0],
10754
10861
  visible,
10755
10862
  children: [
10756
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("sphereGeometry", { args: [DEFAULT_PANORAMA_RADIUS, 128, 64] }),
10757
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
10863
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("sphereGeometry", { args: [DEFAULT_PANORAMA_RADIUS, 128, 64] }),
10864
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
10758
10865
  PanoBasicMaterial,
10759
10866
  {
10760
10867
  map: displayTexture,
@@ -10768,10 +10875,10 @@ function Sphere({
10768
10875
  }
10769
10876
 
10770
10877
  // src/video/pano-video.tsx
10771
- var import_fiber17 = require("@react-three/fiber");
10772
- var import_react40 = require("react");
10878
+ var import_fiber18 = require("@react-three/fiber");
10879
+ var import_react42 = require("react");
10773
10880
  var import_three16 = require("three");
10774
- var import_jsx_runtime17 = require("react/jsx-runtime");
10881
+ var import_jsx_runtime18 = require("react/jsx-runtime");
10775
10882
  var EMPTY_TRACKS = [];
10776
10883
  var EMPTY_RATES = DEFAULT_PANO_VIDEO_PLAYBACK_RATES;
10777
10884
  function createEmptySnapshot() {
@@ -10855,11 +10962,11 @@ function applyEquirectangularLayout(texture, anisotropy) {
10855
10962
  texture.needsUpdate = true;
10856
10963
  }
10857
10964
  function usePosterTexture(poster, onError) {
10858
- const gl = (0, import_fiber17.useThree)((state) => state.gl);
10859
- const [texture, setTexture] = (0, import_react40.useState)(null);
10860
- const onErrorRef = (0, import_react40.useRef)(onError);
10965
+ const gl = (0, import_fiber18.useThree)((state) => state.gl);
10966
+ const [texture, setTexture] = (0, import_react42.useState)(null);
10967
+ const onErrorRef = (0, import_react42.useRef)(onError);
10861
10968
  onErrorRef.current = onError;
10862
- (0, import_react40.useEffect)(() => {
10969
+ (0, import_react42.useEffect)(() => {
10863
10970
  let active = true;
10864
10971
  setTexture(null);
10865
10972
  if (!poster) {
@@ -10896,7 +11003,7 @@ function usePosterTexture(poster, onError) {
10896
11003
  active = false;
10897
11004
  };
10898
11005
  }, [gl, poster]);
10899
- (0, import_react40.useEffect)(
11006
+ (0, import_react42.useEffect)(
10900
11007
  () => () => {
10901
11008
  texture?.dispose();
10902
11009
  },
@@ -10954,39 +11061,39 @@ function PanoVideo({
10954
11061
  onTrackChange
10955
11062
  }) {
10956
11063
  usePanoMediaActivationIntent(autoPlay);
10957
- const gl = (0, import_fiber17.useThree)((state) => state.gl);
10958
- const host = (0, import_react40.useContext)(PanoVideoHostContext);
10959
- const overlay = (0, import_react40.useContext)(PanoChromeOverlayContext);
10960
- const variants = (0, import_react40.useMemo)(
11064
+ const gl = (0, import_fiber18.useThree)((state) => state.gl);
11065
+ const host = (0, import_react42.useContext)(PanoVideoHostContext);
11066
+ const overlay = (0, import_react42.useContext)(PanoChromeOverlayContext);
11067
+ const variants = (0, import_react42.useMemo)(
10961
11068
  () => resolvePanoVideoVariants({ poster, src, variants: variantsProp }),
10962
11069
  [poster, src, variantsProp]
10963
11070
  );
10964
11071
  const tracks = tracksProp ?? EMPTY_TRACKS;
10965
11072
  const captionsEnabled = captions !== false;
10966
- const captionAppearance = (0, import_react40.useMemo)(
11073
+ const captionAppearance = (0, import_react42.useMemo)(
10967
11074
  () => resolvePanoVideoCaptionAppearance(
10968
11075
  typeof captions === "object" ? captions : void 0
10969
11076
  ),
10970
11077
  [captions]
10971
11078
  );
10972
- const [variantId, setVariantId] = (0, import_react40.useState)(
11079
+ const [variantId, setVariantId] = (0, import_react42.useState)(
10973
11080
  () => resolvePanoVideoVariantId(variants, defaultVariantId)
10974
11081
  );
10975
- const [trackId, setTrackId] = (0, import_react40.useState)(
11082
+ const [trackId, setTrackId] = (0, import_react42.useState)(
10976
11083
  () => captionsEnabled ? defaultPanoVideoTrackId(tracks) : null
10977
11084
  );
10978
- const [ready, setReady] = (0, import_react40.useState)(false);
10979
- const autoPlayRef = (0, import_react40.useRef)(autoPlay);
11085
+ const [ready, setReady] = (0, import_react42.useState)(false);
11086
+ const autoPlayRef = (0, import_react42.useRef)(autoPlay);
10980
11087
  autoPlayRef.current = autoPlay;
10981
- const blockedRef = (0, import_react40.useRef)(false);
10982
- const captionAppearanceOverrideRef = (0, import_react40.useRef)(
11088
+ const blockedRef = (0, import_react42.useRef)(false);
11089
+ const captionAppearanceOverrideRef = (0, import_react42.useRef)(
10983
11090
  {}
10984
11091
  );
10985
- const mediaCapabilitiesRef = (0, import_react40.useRef)({
11092
+ const mediaCapabilitiesRef = (0, import_react42.useRef)({
10986
11093
  volumeAdjustable: true,
10987
11094
  playbackRates: [...DEFAULT_PANO_VIDEO_PLAYBACK_RATES]
10988
11095
  });
10989
- const storeRef = (0, import_react40.useRef)(null);
11096
+ const storeRef = (0, import_react42.useRef)(null);
10990
11097
  if (!storeRef.current) {
10991
11098
  storeRef.current = {
10992
11099
  snapshot: {
@@ -10996,7 +11103,7 @@ function PanoVideo({
10996
11103
  listeners: /* @__PURE__ */ new Set()
10997
11104
  };
10998
11105
  }
10999
- const actionsRef = (0, import_react40.useRef)({
11106
+ const actionsRef = (0, import_react42.useRef)({
11000
11107
  play: async () => {
11001
11108
  },
11002
11109
  pause: () => {
@@ -11016,19 +11123,19 @@ function PanoVideo({
11016
11123
  setCaptionAppearance: (_appearance) => {
11017
11124
  }
11018
11125
  });
11019
- const onLoadRef = (0, import_react40.useRef)(onLoad);
11020
- const onErrorRef = (0, import_react40.useRef)(onError);
11021
- const onPlaybackStateChangeRef = (0, import_react40.useRef)(onPlaybackStateChange);
11022
- const onEndedRef = (0, import_react40.useRef)(onEnded);
11023
- const onVariantChangeRef = (0, import_react40.useRef)(onVariantChange);
11024
- const onTrackChangeRef = (0, import_react40.useRef)(onTrackChange);
11126
+ const onLoadRef = (0, import_react42.useRef)(onLoad);
11127
+ const onErrorRef = (0, import_react42.useRef)(onError);
11128
+ const onPlaybackStateChangeRef = (0, import_react42.useRef)(onPlaybackStateChange);
11129
+ const onEndedRef = (0, import_react42.useRef)(onEnded);
11130
+ const onVariantChangeRef = (0, import_react42.useRef)(onVariantChange);
11131
+ const onTrackChangeRef = (0, import_react42.useRef)(onTrackChange);
11025
11132
  onLoadRef.current = onLoad;
11026
11133
  onErrorRef.current = onError;
11027
11134
  onPlaybackStateChangeRef.current = onPlaybackStateChange;
11028
11135
  onEndedRef.current = onEnded;
11029
11136
  onVariantChangeRef.current = onVariantChange;
11030
11137
  onTrackChangeRef.current = onTrackChange;
11031
- const resource = (0, import_react40.useMemo)(() => {
11138
+ const resource = (0, import_react42.useMemo)(() => {
11032
11139
  if (typeof document === "undefined") {
11033
11140
  return null;
11034
11141
  }
@@ -11045,7 +11152,7 @@ function PanoVideo({
11045
11152
  texture.generateMipmaps = false;
11046
11153
  return { video, texture };
11047
11154
  }, []);
11048
- (0, import_react40.useEffect)(
11155
+ (0, import_react42.useEffect)(
11049
11156
  () => () => {
11050
11157
  if (!resource) {
11051
11158
  return;
@@ -11060,13 +11167,13 @@ function PanoVideo({
11060
11167
  },
11061
11168
  [resource]
11062
11169
  );
11063
- (0, import_react40.useEffect)(() => {
11170
+ (0, import_react42.useEffect)(() => {
11064
11171
  if (!resource) {
11065
11172
  return;
11066
11173
  }
11067
11174
  resource.texture.anisotropy = gl.capabilities.getMaxAnisotropy();
11068
11175
  }, [gl, resource]);
11069
- (0, import_react40.useEffect)(() => {
11176
+ (0, import_react42.useEffect)(() => {
11070
11177
  if (!resource || !overlay?.overlayElement) {
11071
11178
  return;
11072
11179
  }
@@ -11089,7 +11196,7 @@ function PanoVideo({
11089
11196
  activeVariant?.poster ?? poster,
11090
11197
  onError
11091
11198
  );
11092
- const emitSnapshot = (0, import_react40.useCallback)(
11199
+ const emitSnapshot = (0, import_react42.useCallback)(
11093
11200
  (patch) => {
11094
11201
  const store = storeRef.current;
11095
11202
  const video = resource?.video;
@@ -11141,7 +11248,7 @@ function PanoVideo({
11141
11248
  captionAppearance
11142
11249
  ]
11143
11250
  );
11144
- const controller = (0, import_react40.useMemo)(
11251
+ const controller = (0, import_react42.useMemo)(
11145
11252
  () => ({
11146
11253
  subscribe: (onStoreChange) => {
11147
11254
  const store = storeRef.current;
@@ -11193,7 +11300,7 @@ function PanoVideo({
11193
11300
  }),
11194
11301
  []
11195
11302
  );
11196
- (0, import_react40.useLayoutEffect)(() => {
11303
+ (0, import_react42.useLayoutEffect)(() => {
11197
11304
  if (!host || variants.length === 0) {
11198
11305
  return;
11199
11306
  }
@@ -11206,7 +11313,7 @@ function PanoVideo({
11206
11313
  notifyPanoVideoHost(host);
11207
11314
  };
11208
11315
  }, [captionsEnabled, controller, controls, host, variants.length]);
11209
- (0, import_react40.useLayoutEffect)(() => {
11316
+ (0, import_react42.useLayoutEffect)(() => {
11210
11317
  if (!resource) {
11211
11318
  return;
11212
11319
  }
@@ -11219,10 +11326,10 @@ function PanoVideo({
11219
11326
  };
11220
11327
  emitSnapshot();
11221
11328
  }, [emitSnapshot, playbackRates, resource]);
11222
- (0, import_react40.useEffect)(() => {
11329
+ (0, import_react42.useEffect)(() => {
11223
11330
  emitSnapshot();
11224
11331
  }, [emitSnapshot]);
11225
- (0, import_react40.useEffect)(() => {
11332
+ (0, import_react42.useEffect)(() => {
11226
11333
  if (!resource || !activeVariant || !mediaKey) {
11227
11334
  return;
11228
11335
  }
@@ -11279,7 +11386,7 @@ function PanoVideo({
11279
11386
  video.removeEventListener("error", handleError);
11280
11387
  };
11281
11388
  }, [mediaKey, resource]);
11282
- (0, import_react40.useEffect)(() => {
11389
+ (0, import_react42.useEffect)(() => {
11283
11390
  if (!resource) {
11284
11391
  return;
11285
11392
  }
@@ -11371,7 +11478,7 @@ function PanoVideo({
11371
11478
  }
11372
11479
  };
11373
11480
  }, [emitSnapshot, resource]);
11374
- (0, import_react40.useEffect)(() => {
11481
+ (0, import_react42.useEffect)(() => {
11375
11482
  if (!resource) {
11376
11483
  return;
11377
11484
  }
@@ -11391,7 +11498,7 @@ function PanoVideo({
11391
11498
  }
11392
11499
  video.preload = preload;
11393
11500
  }, [loop, muted, playsInline, preload, resource, volume]);
11394
- (0, import_react40.useEffect)(() => {
11501
+ (0, import_react42.useEffect)(() => {
11395
11502
  if (!resource) {
11396
11503
  return;
11397
11504
  }
@@ -11441,7 +11548,7 @@ function PanoVideo({
11441
11548
  video.removeEventListener("ratechange", handleVolume);
11442
11549
  };
11443
11550
  }, [emitSnapshot, resource]);
11444
- (0, import_react40.useEffect)(() => {
11551
+ (0, import_react42.useEffect)(() => {
11445
11552
  if (!resource) {
11446
11553
  return;
11447
11554
  }
@@ -11476,7 +11583,7 @@ function PanoVideo({
11476
11583
  video.textTracks.removeEventListener("change", applyModes);
11477
11584
  };
11478
11585
  }, [emitSnapshot, resource, trackId, tracks]);
11479
- (0, import_react40.useEffect)(() => {
11586
+ (0, import_react42.useEffect)(() => {
11480
11587
  if (!captionsEnabled) {
11481
11588
  setTrackId(null);
11482
11589
  return;
@@ -11487,15 +11594,15 @@ function PanoVideo({
11487
11594
  if (variants.length === 0) {
11488
11595
  return null;
11489
11596
  }
11490
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
11491
- activeTexture ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
11597
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
11598
+ activeTexture ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
11492
11599
  "mesh",
11493
11600
  {
11494
11601
  rotation: [0, import_three16.MathUtils.degToRad(90 + yawOffset), 0],
11495
11602
  visible,
11496
11603
  children: [
11497
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("sphereGeometry", { args: [DEFAULT_PANORAMA_RADIUS, 128, 64] }),
11498
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
11604
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("sphereGeometry", { args: [DEFAULT_PANORAMA_RADIUS, 128, 64] }),
11605
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
11499
11606
  PanoBasicMaterial,
11500
11607
  {
11501
11608
  map: activeTexture,
@@ -11506,14 +11613,14 @@ function PanoVideo({
11506
11613
  ]
11507
11614
  }
11508
11615
  ) : null,
11509
- captionsEnabled ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(PanoVideoCaptions, { appearance: typeof captions === "object" ? captions : void 0 }) : null
11616
+ captionsEnabled ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(PanoVideoCaptions, { appearance: typeof captions === "object" ? captions : void 0 }) : null
11510
11617
  ] });
11511
11618
  }
11512
11619
 
11513
11620
  // src/scenes.tsx
11514
- var import_fiber22 = require("@react-three/fiber");
11515
- var import_react45 = require("react");
11516
- var import_three23 = require("three");
11621
+ var import_fiber23 = require("@react-three/fiber");
11622
+ var import_react47 = require("react");
11623
+ var import_three24 = require("three");
11517
11624
 
11518
11625
  // src/scene-transitions/presets.ts
11519
11626
  var TRANSITION_DEFAULTS = {
@@ -11561,9 +11668,33 @@ function isSnapshotTransition(preset) {
11561
11668
  return preset !== "none" && preset !== "particles";
11562
11669
  }
11563
11670
 
11564
- // src/scene-transitions/particle-overlay.tsx
11565
- var import_fiber18 = require("@react-three/fiber");
11566
- var import_react41 = require("react");
11671
+ // src/scene-transitions/snapshot-hold.tsx
11672
+ var import_fiber19 = require("@react-three/fiber");
11673
+ var import_react43 = require("react");
11674
+ var import_three19 = require("three");
11675
+
11676
+ // src/scene-transitions/overlay-utils.ts
11677
+ var import_three17 = require("three");
11678
+ var OVERLAY_RENDER_ORDER = 1e4;
11679
+ var FULLSCREEN_PLANE = new import_three17.PlaneGeometry(1, 1);
11680
+ function isPerspectiveCamera(camera) {
11681
+ return camera.isPerspectiveCamera === true;
11682
+ }
11683
+ function placeFullscreenOverlay(mesh, camera, direction) {
11684
+ const distance = Math.max(camera.near * 1.1, 0.11);
11685
+ camera.getWorldDirection(direction);
11686
+ mesh.position.copy(camera.position).addScaledVector(direction, distance);
11687
+ mesh.quaternion.copy(camera.quaternion);
11688
+ const height = 2 * distance * Math.tan(camera.fov * Math.PI / 360);
11689
+ mesh.scale.set(height * camera.aspect, height, 1);
11690
+ }
11691
+ function overlayProgress(elapsedTime, duration, startTime) {
11692
+ const started = startTime ?? elapsedTime;
11693
+ const progress = duration === 0 ? 1 : Math.min(1, (elapsedTime - started) / duration);
11694
+ return { startTime: started, progress };
11695
+ }
11696
+
11697
+ // src/scene-transitions/snapshot-shaders.ts
11567
11698
  var import_three18 = require("three");
11568
11699
 
11569
11700
  // src/scene-transitions/glsl.ts
@@ -11596,182 +11727,20 @@ float fbm(vec2 p) {
11596
11727
  }
11597
11728
  `;
11598
11729
 
11599
- // src/scene-transitions/overlay-utils.ts
11600
- var import_three17 = require("three");
11601
- var OVERLAY_RENDER_ORDER = 1e4;
11602
- var FULLSCREEN_PLANE = new import_three17.PlaneGeometry(1, 1);
11603
- function isPerspectiveCamera(camera) {
11604
- return camera.isPerspectiveCamera === true;
11605
- }
11606
- function placeFullscreenOverlay(mesh, camera, direction) {
11607
- const distance = Math.max(camera.near * 1.1, 0.11);
11608
- camera.getWorldDirection(direction);
11609
- mesh.position.copy(camera.position).addScaledVector(direction, distance);
11610
- mesh.quaternion.copy(camera.quaternion);
11611
- const height = 2 * distance * Math.tan(camera.fov * Math.PI / 360);
11612
- mesh.scale.set(height * camera.aspect, height, 1);
11613
- }
11614
- function overlayProgress(elapsedTime, duration, startTime) {
11615
- const started = startTime ?? elapsedTime;
11616
- const progress = duration === 0 ? 1 : Math.min(1, (elapsedTime - started) / duration);
11617
- return { startTime: started, progress };
11618
- }
11619
-
11620
- // src/scene-transitions/particle-overlay.tsx
11621
- var import_jsx_runtime18 = require("react/jsx-runtime");
11622
- var PARTICLE_GRID = 48;
11623
- var PARTICLE_COUNT = PARTICLE_GRID * PARTICLE_GRID;
11624
- var PARTICLE_VERTEX_SHADER = `
11625
- attribute float instanceIndex;
11626
- uniform float progress;
11627
- uniform vec2 grid;
11730
+ // src/scene-transitions/snapshot-shaders.ts
11731
+ var SNAPSHOT_VERTEX_SHADER = `
11628
11732
  varying vec2 vUv;
11629
- varying float vAlpha;
11630
- ${GLSL_COMMON}
11631
-
11632
11733
  void main() {
11633
- float id = instanceIndex;
11634
- float gx = mod(id, grid.x);
11635
- float gy = floor(id / grid.x);
11636
- vec2 cell = vec2(gx, gy);
11637
- float h = hash(cell);
11638
- float h2 = hash(cell + 19.2);
11639
- float h3 = hash(cell + 7.7);
11640
- vec2 randomDir = normalize(vec2(h, h2) * 2.0 - 1.0 + 1e-5);
11641
- vec2 fromCenter = (cell + 0.5) / grid - 0.5 + 1e-5;
11642
- vec2 dir = normalize(mix(randomDir, normalize(fromCenter), 0.65));
11643
- float delay = h3 * 0.28;
11644
- float lt = clamp((progress - delay) / max(1.0 - delay, 0.001), 0.0, 1.0);
11645
- float explode = lt * lt;
11646
- float scale = mix(1.0, 0.18, explode);
11647
- float angle = (h * 2.0 - 1.0) * explode * 4.2;
11648
- float ca = cos(angle);
11649
- float sa = sin(angle);
11650
- vec2 cellSize = 1.0 / grid;
11651
- vec2 local = position.xy * cellSize * scale;
11652
- vec2 rotated = vec2(local.x * ca - local.y * sa, local.x * sa + local.y * ca);
11653
- vec2 planeCenter = (cell + 0.5) / grid - 0.5;
11654
- vec2 exploded = planeCenter + dir * explode * 0.9;
11655
- vec3 pos = vec3(exploded + rotated, -explode * 0.14);
11656
- vUv = (cell + uv) / grid;
11657
- vAlpha = 1.0 - explode;
11658
- gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
11734
+ vUv = uv;
11735
+ gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
11659
11736
  }
11660
11737
  `;
11661
- var PARTICLE_FRAGMENT_SHADER = `
11662
- uniform sampler2D map;
11663
- varying vec2 vUv;
11664
- varying float vAlpha;
11665
-
11666
- void main() {
11667
- vec4 old = texture2D(map, vUv);
11668
- old.rgb *= 1.0 + 0.22 * (1.0 - vAlpha);
11669
- gl_FragColor = vec4(old.rgb, old.a * vAlpha);
11670
- #include <colorspace_fragment>
11671
- }
11672
- `;
11673
- function createParticleGeometry() {
11674
- const quad = new import_three18.PlaneGeometry(1, 1);
11675
- const geometry = new import_three18.InstancedBufferGeometry();
11676
- if (quad.index) {
11677
- geometry.setIndex(quad.index.clone());
11678
- }
11679
- geometry.setAttribute("position", quad.attributes.position.clone());
11680
- geometry.setAttribute("uv", quad.attributes.uv.clone());
11681
- const indexes = new Float32Array(PARTICLE_COUNT);
11682
- for (let i = 0; i < PARTICLE_COUNT; i += 1) {
11683
- indexes[i] = i;
11684
- }
11685
- geometry.setAttribute("instanceIndex", new import_three18.InstancedBufferAttribute(indexes, 1));
11686
- geometry.instanceCount = PARTICLE_COUNT;
11687
- quad.dispose();
11688
- return geometry;
11689
- }
11690
- function ParticleOverlay({
11691
- snapshot,
11692
- transition,
11693
- running,
11694
- runId,
11695
- onFinish
11696
- }) {
11697
- const { camera } = (0, import_fiber18.useThree)();
11698
- const meshRef = (0, import_react41.useRef)(null);
11699
- const startRef = (0, import_react41.useRef)(null);
11700
- const finishedRef = (0, import_react41.useRef)(false);
11701
- const directionRef = (0, import_react41.useRef)(new import_three18.Vector3());
11702
- const geometry = (0, import_react41.useMemo)(() => createParticleGeometry(), []);
11703
- const material = (0, import_react41.useMemo)(
11704
- () => new import_three18.ShaderMaterial({
11705
- transparent: true,
11706
- depthTest: false,
11707
- depthWrite: false,
11708
- side: import_three18.DoubleSide,
11709
- uniforms: {
11710
- map: { value: snapshot.texture },
11711
- progress: { value: 0 },
11712
- grid: { value: new import_three18.Vector2(PARTICLE_GRID, PARTICLE_GRID) }
11713
- },
11714
- vertexShader: PARTICLE_VERTEX_SHADER,
11715
- fragmentShader: PARTICLE_FRAGMENT_SHADER
11716
- }),
11717
- [snapshot.texture]
11718
- );
11719
- (0, import_react41.useEffect)(() => () => geometry.dispose(), [geometry]);
11720
- (0, import_react41.useEffect)(() => () => material.dispose(), [material]);
11721
- (0, import_react41.useEffect)(() => {
11722
- startRef.current = null;
11723
- finishedRef.current = false;
11724
- material.uniforms.progress.value = 0;
11725
- }, [material, runId]);
11726
- (0, import_fiber18.useFrame)((state) => {
11727
- const mesh = meshRef.current;
11728
- if (!mesh || !isPerspectiveCamera(camera)) {
11729
- return;
11730
- }
11731
- placeFullscreenOverlay(mesh, camera, directionRef.current);
11732
- if (!running || finishedRef.current) {
11733
- return;
11734
- }
11735
- const next = overlayProgress(state.clock.elapsedTime, transition.duration, startRef.current);
11736
- startRef.current = next.startTime;
11737
- material.uniforms.progress.value = next.progress;
11738
- if (next.progress === 1) {
11739
- finishedRef.current = true;
11740
- onFinish();
11741
- }
11742
- });
11743
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
11744
- "mesh",
11745
- {
11746
- ref: meshRef,
11747
- frustumCulled: false,
11748
- geometry,
11749
- material,
11750
- renderOrder: OVERLAY_RENDER_ORDER
11751
- }
11752
- );
11753
- }
11754
-
11755
- // src/scene-transitions/snapshot-overlay.tsx
11756
- var import_fiber19 = require("@react-three/fiber");
11757
- var import_react42 = require("react");
11758
- var import_three20 = require("three");
11759
-
11760
- // src/scene-transitions/snapshot-shaders.ts
11761
- var import_three19 = require("three");
11762
- var SNAPSHOT_VERTEX_SHADER = `
11763
- varying vec2 vUv;
11764
- void main() {
11765
- vUv = uv;
11766
- gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
11767
- }
11768
- `;
11769
- var HEADER = `
11770
- uniform sampler2D map;
11771
- uniform float progress;
11772
- uniform vec2 resolution;
11773
- varying vec2 vUv;
11774
- ${GLSL_COMMON}
11738
+ var HEADER = `
11739
+ uniform sampler2D map;
11740
+ uniform float progress;
11741
+ uniform vec2 resolution;
11742
+ varying vec2 vUv;
11743
+ ${GLSL_COMMON}
11775
11744
 
11776
11745
  vec2 aspectGrid(float rows) {
11777
11746
  float aspect = resolution.x / max(resolution.y, 1.0);
@@ -12018,23 +11987,250 @@ var SNAPSHOT_FRAGMENT_SHADERS = {
12018
11987
  `)
12019
11988
  };
12020
11989
  function createSnapshotMaterial(preset, texture) {
12021
- return new import_three19.ShaderMaterial({
11990
+ return new import_three18.ShaderMaterial({
12022
11991
  transparent: true,
12023
11992
  depthTest: false,
12024
11993
  depthWrite: false,
12025
- side: import_three19.DoubleSide,
11994
+ side: import_three18.DoubleSide,
12026
11995
  uniforms: {
12027
11996
  map: { value: texture },
12028
11997
  progress: { value: 0 },
12029
- resolution: { value: new import_three19.Vector2(1, 1) }
11998
+ resolution: { value: new import_three18.Vector2(1, 1) }
12030
11999
  },
12031
12000
  vertexShader: SNAPSHOT_VERTEX_SHADER,
12032
12001
  fragmentShader: SNAPSHOT_FRAGMENT_SHADERS[preset]
12033
12002
  });
12034
12003
  }
12035
12004
 
12036
- // src/scene-transitions/snapshot-overlay.tsx
12005
+ // src/scene-transitions/snapshot-hold.tsx
12037
12006
  var import_jsx_runtime19 = require("react/jsx-runtime");
12007
+ function SnapshotHold({ snapshot }) {
12008
+ const { camera, gl } = (0, import_fiber19.useThree)();
12009
+ const meshRef = (0, import_react43.useRef)(null);
12010
+ const directionRef = (0, import_react43.useRef)(new import_three19.Vector3());
12011
+ const material = (0, import_react43.useMemo)(
12012
+ () => createSnapshotMaterial("crossfade", snapshot.texture),
12013
+ [snapshot.texture]
12014
+ );
12015
+ (0, import_react43.useEffect)(() => () => material.dispose(), [material]);
12016
+ (0, import_fiber19.useFrame)(() => {
12017
+ const mesh = meshRef.current;
12018
+ if (!mesh || !isPerspectiveCamera(camera)) {
12019
+ return;
12020
+ }
12021
+ placeFullscreenOverlay(mesh, camera, directionRef.current);
12022
+ const context = gl.getContext();
12023
+ material.uniforms.resolution.value.set(
12024
+ context.drawingBufferWidth,
12025
+ context.drawingBufferHeight
12026
+ );
12027
+ material.uniforms.progress.value = 0;
12028
+ });
12029
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("mesh", { frustumCulled: false, ref: meshRef, renderOrder: OVERLAY_RENDER_ORDER, children: [
12030
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("primitive", { attach: "geometry", object: FULLSCREEN_PLANE }),
12031
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("primitive", { attach: "material", object: material })
12032
+ ] });
12033
+ }
12034
+
12035
+ // src/scene-transition-policy.ts
12036
+ function pendingSceneUsesBaseLayer(phase, isPending) {
12037
+ return isPending && (phase === "preloading" || phase === "capturing");
12038
+ }
12039
+ function normalizeTransitionWaitMs(value) {
12040
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
12041
+ return 0;
12042
+ }
12043
+ return value;
12044
+ }
12045
+ function planDetailHold(input) {
12046
+ if (input.waitMs <= 0) {
12047
+ return null;
12048
+ }
12049
+ return {
12050
+ generation: input.generation,
12051
+ sceneId: input.sceneId,
12052
+ deadline: input.now + input.waitMs
12053
+ };
12054
+ }
12055
+ function acceptDetailWait(wait, signal) {
12056
+ if (!wait) {
12057
+ return { wait: null, start: false };
12058
+ }
12059
+ switch (signal.kind) {
12060
+ case "ready":
12061
+ if (signal.generation !== wait.generation || signal.sceneId !== wait.sceneId) {
12062
+ return { wait, start: false };
12063
+ }
12064
+ return { wait: null, start: true };
12065
+ case "timeout":
12066
+ if (signal.generation !== wait.generation || signal.now < wait.deadline) {
12067
+ return { wait, start: false };
12068
+ }
12069
+ return { wait: null, start: true };
12070
+ case "cancel":
12071
+ if (signal.generation !== wait.generation) {
12072
+ return { wait, start: false };
12073
+ }
12074
+ return { wait: null, start: false };
12075
+ default: {
12076
+ const exhaustive = signal;
12077
+ return exhaustive;
12078
+ }
12079
+ }
12080
+ }
12081
+ function phaseAfterSnapshot(preset, hold) {
12082
+ if (hold) {
12083
+ return "awaitingDetail";
12084
+ }
12085
+ if (preset === "none") {
12086
+ return "idle";
12087
+ }
12088
+ return "transitioning";
12089
+ }
12090
+
12091
+ // src/scene-transitions/particle-overlay.tsx
12092
+ var import_fiber20 = require("@react-three/fiber");
12093
+ var import_react44 = require("react");
12094
+ var import_three20 = require("three");
12095
+ var import_jsx_runtime20 = require("react/jsx-runtime");
12096
+ var PARTICLE_GRID = 48;
12097
+ var PARTICLE_COUNT = PARTICLE_GRID * PARTICLE_GRID;
12098
+ var PARTICLE_VERTEX_SHADER = `
12099
+ attribute float instanceIndex;
12100
+ uniform float progress;
12101
+ uniform vec2 grid;
12102
+ varying vec2 vUv;
12103
+ varying float vAlpha;
12104
+ ${GLSL_COMMON}
12105
+
12106
+ void main() {
12107
+ float id = instanceIndex;
12108
+ float gx = mod(id, grid.x);
12109
+ float gy = floor(id / grid.x);
12110
+ vec2 cell = vec2(gx, gy);
12111
+ float h = hash(cell);
12112
+ float h2 = hash(cell + 19.2);
12113
+ float h3 = hash(cell + 7.7);
12114
+ vec2 randomDir = normalize(vec2(h, h2) * 2.0 - 1.0 + 1e-5);
12115
+ vec2 fromCenter = (cell + 0.5) / grid - 0.5 + 1e-5;
12116
+ vec2 dir = normalize(mix(randomDir, normalize(fromCenter), 0.65));
12117
+ float delay = h3 * 0.28;
12118
+ float lt = clamp((progress - delay) / max(1.0 - delay, 0.001), 0.0, 1.0);
12119
+ float explode = lt * lt;
12120
+ float scale = mix(1.0, 0.18, explode);
12121
+ float angle = (h * 2.0 - 1.0) * explode * 4.2;
12122
+ float ca = cos(angle);
12123
+ float sa = sin(angle);
12124
+ vec2 cellSize = 1.0 / grid;
12125
+ vec2 local = position.xy * cellSize * scale;
12126
+ vec2 rotated = vec2(local.x * ca - local.y * sa, local.x * sa + local.y * ca);
12127
+ vec2 planeCenter = (cell + 0.5) / grid - 0.5;
12128
+ vec2 exploded = planeCenter + dir * explode * 0.9;
12129
+ vec3 pos = vec3(exploded + rotated, -explode * 0.14);
12130
+ vUv = (cell + uv) / grid;
12131
+ vAlpha = 1.0 - explode;
12132
+ gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
12133
+ }
12134
+ `;
12135
+ var PARTICLE_FRAGMENT_SHADER = `
12136
+ uniform sampler2D map;
12137
+ varying vec2 vUv;
12138
+ varying float vAlpha;
12139
+
12140
+ void main() {
12141
+ vec4 old = texture2D(map, vUv);
12142
+ old.rgb *= 1.0 + 0.22 * (1.0 - vAlpha);
12143
+ gl_FragColor = vec4(old.rgb, old.a * vAlpha);
12144
+ #include <colorspace_fragment>
12145
+ }
12146
+ `;
12147
+ function createParticleGeometry() {
12148
+ const quad = new import_three20.PlaneGeometry(1, 1);
12149
+ const geometry = new import_three20.InstancedBufferGeometry();
12150
+ if (quad.index) {
12151
+ geometry.setIndex(quad.index.clone());
12152
+ }
12153
+ geometry.setAttribute("position", quad.attributes.position.clone());
12154
+ geometry.setAttribute("uv", quad.attributes.uv.clone());
12155
+ const indexes = new Float32Array(PARTICLE_COUNT);
12156
+ for (let i = 0; i < PARTICLE_COUNT; i += 1) {
12157
+ indexes[i] = i;
12158
+ }
12159
+ geometry.setAttribute("instanceIndex", new import_three20.InstancedBufferAttribute(indexes, 1));
12160
+ geometry.instanceCount = PARTICLE_COUNT;
12161
+ quad.dispose();
12162
+ return geometry;
12163
+ }
12164
+ function ParticleOverlay({
12165
+ snapshot,
12166
+ transition,
12167
+ running,
12168
+ runId,
12169
+ onFinish
12170
+ }) {
12171
+ const { camera } = (0, import_fiber20.useThree)();
12172
+ const meshRef = (0, import_react44.useRef)(null);
12173
+ const startRef = (0, import_react44.useRef)(null);
12174
+ const finishedRef = (0, import_react44.useRef)(false);
12175
+ const directionRef = (0, import_react44.useRef)(new import_three20.Vector3());
12176
+ const geometry = (0, import_react44.useMemo)(() => createParticleGeometry(), []);
12177
+ const material = (0, import_react44.useMemo)(
12178
+ () => new import_three20.ShaderMaterial({
12179
+ transparent: true,
12180
+ depthTest: false,
12181
+ depthWrite: false,
12182
+ side: import_three20.DoubleSide,
12183
+ uniforms: {
12184
+ map: { value: snapshot.texture },
12185
+ progress: { value: 0 },
12186
+ grid: { value: new import_three20.Vector2(PARTICLE_GRID, PARTICLE_GRID) }
12187
+ },
12188
+ vertexShader: PARTICLE_VERTEX_SHADER,
12189
+ fragmentShader: PARTICLE_FRAGMENT_SHADER
12190
+ }),
12191
+ [snapshot.texture]
12192
+ );
12193
+ (0, import_react44.useEffect)(() => () => geometry.dispose(), [geometry]);
12194
+ (0, import_react44.useEffect)(() => () => material.dispose(), [material]);
12195
+ (0, import_react44.useEffect)(() => {
12196
+ startRef.current = null;
12197
+ finishedRef.current = false;
12198
+ material.uniforms.progress.value = 0;
12199
+ }, [material, runId]);
12200
+ (0, import_fiber20.useFrame)((state) => {
12201
+ const mesh = meshRef.current;
12202
+ if (!mesh || !isPerspectiveCamera(camera)) {
12203
+ return;
12204
+ }
12205
+ placeFullscreenOverlay(mesh, camera, directionRef.current);
12206
+ if (!running || finishedRef.current) {
12207
+ return;
12208
+ }
12209
+ const next = overlayProgress(state.clock.elapsedTime, transition.duration, startRef.current);
12210
+ startRef.current = next.startTime;
12211
+ material.uniforms.progress.value = next.progress;
12212
+ if (next.progress === 1) {
12213
+ finishedRef.current = true;
12214
+ onFinish();
12215
+ }
12216
+ });
12217
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
12218
+ "mesh",
12219
+ {
12220
+ ref: meshRef,
12221
+ frustumCulled: false,
12222
+ geometry,
12223
+ material,
12224
+ renderOrder: OVERLAY_RENDER_ORDER
12225
+ }
12226
+ );
12227
+ }
12228
+
12229
+ // src/scene-transitions/snapshot-overlay.tsx
12230
+ var import_fiber21 = require("@react-three/fiber");
12231
+ var import_react45 = require("react");
12232
+ var import_three21 = require("three");
12233
+ var import_jsx_runtime21 = require("react/jsx-runtime");
12038
12234
  function SnapshotOverlay({
12039
12235
  snapshot,
12040
12236
  transition,
@@ -12042,26 +12238,26 @@ function SnapshotOverlay({
12042
12238
  runId,
12043
12239
  onFinish
12044
12240
  }) {
12045
- const { camera, gl } = (0, import_fiber19.useThree)();
12046
- const meshRef = (0, import_react42.useRef)(null);
12047
- const startRef = (0, import_react42.useRef)(null);
12048
- const finishedRef = (0, import_react42.useRef)(false);
12049
- const directionRef = (0, import_react42.useRef)(new import_three20.Vector3());
12050
- const material = (0, import_react42.useMemo)(() => {
12241
+ const { camera, gl } = (0, import_fiber21.useThree)();
12242
+ const meshRef = (0, import_react45.useRef)(null);
12243
+ const startRef = (0, import_react45.useRef)(null);
12244
+ const finishedRef = (0, import_react45.useRef)(false);
12245
+ const directionRef = (0, import_react45.useRef)(new import_three21.Vector3());
12246
+ const material = (0, import_react45.useMemo)(() => {
12051
12247
  if (!isSnapshotTransition(transition.preset)) {
12052
12248
  return null;
12053
12249
  }
12054
12250
  return createSnapshotMaterial(transition.preset, snapshot.texture);
12055
12251
  }, [snapshot.texture, transition.preset]);
12056
- (0, import_react42.useEffect)(() => () => material?.dispose(), [material]);
12057
- (0, import_react42.useEffect)(() => {
12252
+ (0, import_react45.useEffect)(() => () => material?.dispose(), [material]);
12253
+ (0, import_react45.useEffect)(() => {
12058
12254
  startRef.current = null;
12059
12255
  finishedRef.current = false;
12060
12256
  if (material) {
12061
12257
  material.uniforms.progress.value = 0;
12062
12258
  }
12063
12259
  }, [material, runId]);
12064
- (0, import_fiber19.useFrame)((state) => {
12260
+ (0, import_fiber21.useFrame)((state) => {
12065
12261
  const mesh = meshRef.current;
12066
12262
  if (!mesh || !material || !isPerspectiveCamera(camera)) {
12067
12263
  return;
@@ -12083,21 +12279,21 @@ function SnapshotOverlay({
12083
12279
  if (!material) {
12084
12280
  return null;
12085
12281
  }
12086
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("mesh", { ref: meshRef, renderOrder: OVERLAY_RENDER_ORDER, frustumCulled: false, children: [
12087
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("primitive", { attach: "geometry", object: FULLSCREEN_PLANE }),
12088
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("primitive", { attach: "material", object: material })
12282
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("mesh", { ref: meshRef, renderOrder: OVERLAY_RENDER_ORDER, frustumCulled: false, children: [
12283
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("primitive", { attach: "geometry", object: FULLSCREEN_PLANE }),
12284
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("primitive", { attach: "material", object: material })
12089
12285
  ] });
12090
12286
  }
12091
12287
 
12092
12288
  // src/scene-transitions/transition-overlay.tsx
12093
- var import_jsx_runtime20 = require("react/jsx-runtime");
12289
+ var import_jsx_runtime22 = require("react/jsx-runtime");
12094
12290
  function TransitionOverlay(props) {
12095
12291
  const { preset } = props.transition;
12096
12292
  switch (preset) {
12097
12293
  case "none":
12098
12294
  return null;
12099
12295
  case "particles":
12100
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ParticleOverlay, { ...props });
12296
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ParticleOverlay, { ...props });
12101
12297
  case "crossfade":
12102
12298
  case "zoom":
12103
12299
  case "blackout":
@@ -12125,7 +12321,7 @@ function TransitionOverlay(props) {
12125
12321
  case "zoomBlur":
12126
12322
  case "hexDissolve":
12127
12323
  case "filmBurn":
12128
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(SnapshotOverlay, { ...props });
12324
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(SnapshotOverlay, { ...props });
12129
12325
  default: {
12130
12326
  const exhaustive = preset;
12131
12327
  void exhaustive;
@@ -12134,46 +12330,13 @@ function TransitionOverlay(props) {
12134
12330
  }
12135
12331
  }
12136
12332
 
12137
- // src/tile/texture-manager-context.tsx
12138
- var import_fiber20 = require("@react-three/fiber");
12139
- var import_react43 = require("react");
12140
- var import_jsx_runtime21 = require("react/jsx-runtime");
12141
- var TileTextureManagerContext = (0, import_react43.createContext)(
12142
- null
12143
- );
12144
- function TileTextureManagerProvider({
12145
- children,
12146
- maxTextureMemoryMb = 128,
12147
- maxConcurrentLoads = 4
12148
- }) {
12149
- const gl = (0, import_fiber20.useThree)((state) => state.gl);
12150
- const anisotropy = gl.capabilities.getMaxAnisotropy();
12151
- const manager = (0, import_react43.useMemo)(
12152
- () => new TileTextureManager({
12153
- anisotropy,
12154
- maxBytes: Math.max(1, maxTextureMemoryMb) * 1024 * 1024,
12155
- concurrency: Math.max(1, Math.floor(maxConcurrentLoads)),
12156
- retryCount: 1
12157
- }),
12158
- [anisotropy, maxConcurrentLoads, maxTextureMemoryMb]
12159
- );
12160
- (0, import_react43.useEffect)(() => {
12161
- manager.resume();
12162
- return () => manager.dispose();
12163
- }, [manager]);
12164
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TileTextureManagerContext.Provider, { value: manager, children });
12165
- }
12166
- function useSharedTileTextureManager() {
12167
- return (0, import_react43.useContext)(TileTextureManagerContext);
12168
- }
12169
-
12170
12333
  // src/tile/tile.tsx
12171
- var import_fiber21 = require("@react-three/fiber");
12172
- var import_react44 = require("react");
12173
- var import_three22 = require("three");
12334
+ var import_fiber22 = require("@react-three/fiber");
12335
+ var import_react46 = require("react");
12336
+ var import_three23 = require("three");
12174
12337
 
12175
12338
  // src/tile/face-layout.ts
12176
- var import_three21 = require("three");
12339
+ var import_three22 = require("three");
12177
12340
  var CUBE_FACES = ["f", "r", "b", "l", "u", "d"];
12178
12341
  var PREVIEW_FACE_ORDER = ["l", "f", "r", "b", "u", "d"];
12179
12342
  var CUBE_RADIUS = DEFAULT_PANORAMA_RADIUS;
@@ -12224,8 +12387,8 @@ function getFaceQuaternion(face) {
12224
12387
  return cached;
12225
12388
  }
12226
12389
  const transform = getFaceTransform(face);
12227
- const quaternion = new import_three21.Quaternion().setFromEuler(
12228
- new import_three21.Euler(...transform.rotation, "XYZ")
12390
+ const quaternion = new import_three22.Quaternion().setFromEuler(
12391
+ new import_three22.Euler(...transform.rotation, "XYZ")
12229
12392
  );
12230
12393
  faceQuaternionCache.set(face, quaternion);
12231
12394
  return quaternion;
@@ -12236,17 +12399,17 @@ function getTileBoundingBox(address, radius = CUBE_RADIUS) {
12236
12399
  const halfWidth = local.width / 2;
12237
12400
  const halfHeight = local.height / 2;
12238
12401
  const quaternion = getFaceQuaternion(address.face);
12239
- const position = new import_three21.Vector3(...transform.position);
12402
+ const position = new import_three22.Vector3(...transform.position);
12240
12403
  const corners = [
12241
- new import_three21.Vector3(local.x - halfWidth, local.y - halfHeight, 0),
12242
- new import_three21.Vector3(local.x + halfWidth, local.y - halfHeight, 0),
12243
- new import_three21.Vector3(local.x - halfWidth, local.y + halfHeight, 0),
12244
- new import_three21.Vector3(local.x + halfWidth, local.y + halfHeight, 0)
12404
+ new import_three22.Vector3(local.x - halfWidth, local.y - halfHeight, 0),
12405
+ new import_three22.Vector3(local.x + halfWidth, local.y - halfHeight, 0),
12406
+ new import_three22.Vector3(local.x - halfWidth, local.y + halfHeight, 0),
12407
+ new import_three22.Vector3(local.x + halfWidth, local.y + halfHeight, 0)
12245
12408
  ];
12246
12409
  for (const corner of corners) {
12247
12410
  corner.applyQuaternion(quaternion).add(position);
12248
12411
  }
12249
- return new import_three21.Box3().setFromPoints(corners);
12412
+ return new import_three22.Box3().setFromPoints(corners);
12250
12413
  }
12251
12414
  function makeTileAddress(face, level, faceSize, tileSize, col, row) {
12252
12415
  const left = (col - 1) * tileSize;
@@ -12349,21 +12512,37 @@ function resolveTemplateUrl(template, address) {
12349
12512
  }
12350
12513
 
12351
12514
  // src/tile/tile.tsx
12352
- var import_jsx_runtime22 = require("react/jsx-runtime");
12515
+ var import_jsx_runtime23 = require("react/jsx-runtime");
12353
12516
  var MAX_LOD_UPDATE_INTERVAL_MS = 100;
12354
12517
  var FAST_ROTATION_THRESHOLD_RADIANS = Math.PI / 180;
12355
12518
  var FAST_FOV_THRESHOLD_DEGREES = 0.5;
12356
12519
  var VIEW_CHANGE_EPSILON = 1e-4;
12520
+ function decideTileLodUpdate(input) {
12521
+ if (input.loadMode === "preview") {
12522
+ return false;
12523
+ }
12524
+ const loadModeChanged = input.loadMode !== input.trackedLoadMode;
12525
+ const viewChanged = input.visibilityDirty || loadModeChanged || input.viewportChanged || input.rotationDelta > VIEW_CHANGE_EPSILON || input.fovDelta > VIEW_CHANGE_EPSILON;
12526
+ if (!viewChanged) {
12527
+ return false;
12528
+ }
12529
+ const movingQuickly = input.rotationDelta >= FAST_ROTATION_THRESHOLD_RADIANS || input.fovDelta >= FAST_FOV_THRESHOLD_DEGREES;
12530
+ const immediate = input.visibilityDirty || loadModeChanged || input.viewportChanged || movingQuickly;
12531
+ if (!immediate && input.now - input.lastUpdateAt < MAX_LOD_UPDATE_INTERVAL_MS) {
12532
+ return false;
12533
+ }
12534
+ return true;
12535
+ }
12357
12536
  var VISIBILITY_FOV_PADDING_DEGREES = 8;
12358
12537
  var PREVIEW_RADIUS = CUBE_RADIUS + 0.05;
12359
- var SHARED_TILE_GEOMETRY = new import_three22.PlaneGeometry(1, 1);
12538
+ var SHARED_TILE_GEOMETRY = new import_three23.PlaneGeometry(1, 1);
12360
12539
  function PreviewFace({
12361
12540
  face,
12362
12541
  texture,
12363
12542
  faceOrder
12364
12543
  }) {
12365
- const geometry = (0, import_react44.useMemo)(() => {
12366
- const nextGeometry = new import_three22.PlaneGeometry(
12544
+ const geometry = (0, import_react46.useMemo)(() => {
12545
+ const nextGeometry = new import_three23.PlaneGeometry(
12367
12546
  PREVIEW_RADIUS * 2,
12368
12547
  PREVIEW_RADIUS * 2
12369
12548
  );
@@ -12377,21 +12556,21 @@ function PreviewFace({
12377
12556
  uv.needsUpdate = true;
12378
12557
  return nextGeometry;
12379
12558
  }, [face, faceOrder]);
12380
- (0, import_react44.useEffect)(
12559
+ (0, import_react46.useEffect)(
12381
12560
  () => () => {
12382
12561
  geometry.dispose();
12383
12562
  },
12384
12563
  [geometry]
12385
12564
  );
12386
12565
  const transform = getFaceTransform(face, PREVIEW_RADIUS);
12387
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
12566
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
12388
12567
  "mesh",
12389
12568
  {
12390
12569
  geometry,
12391
12570
  position: transform.position,
12392
12571
  renderOrder: -100,
12393
12572
  rotation: transform.rotation,
12394
- children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
12573
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
12395
12574
  PanoBasicMaterial,
12396
12575
  {
12397
12576
  depthTest: false,
@@ -12407,7 +12586,7 @@ function PreviewCube({
12407
12586
  texture,
12408
12587
  faceOrder
12409
12588
  }) {
12410
- return CUBE_FACES.map((face) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
12589
+ return CUBE_FACES.map((face) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
12411
12590
  PreviewFace,
12412
12591
  {
12413
12592
  face,
@@ -12417,7 +12596,7 @@ function PreviewCube({
12417
12596
  face
12418
12597
  ));
12419
12598
  }
12420
- var TileMesh = (0, import_react44.memo)(function TileMesh2({
12599
+ var TileMesh = (0, import_react46.memo)(function TileMesh2({
12421
12600
  address,
12422
12601
  manager,
12423
12602
  renderOrder,
@@ -12431,14 +12610,14 @@ var TileMesh = (0, import_react44.memo)(function TileMesh2({
12431
12610
  if (!snapshot.texture) {
12432
12611
  return null;
12433
12612
  }
12434
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("group", { position: transform.position, rotation: transform.rotation, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
12613
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("group", { position: transform.position, rotation: transform.rotation, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
12435
12614
  "mesh",
12436
12615
  {
12437
12616
  geometry: SHARED_TILE_GEOMETRY,
12438
12617
  position: [layout.x, layout.y, 0],
12439
12618
  renderOrder,
12440
12619
  scale: [layout.width, layout.height, 1],
12441
- children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
12620
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
12442
12621
  PanoBasicMaterial,
12443
12622
  {
12444
12623
  depthTest: false,
@@ -12450,12 +12629,12 @@ var TileMesh = (0, import_react44.memo)(function TileMesh2({
12450
12629
  }
12451
12630
  ) });
12452
12631
  });
12453
- var TileLayerMeshes = (0, import_react44.memo)(function TileLayerMeshes2({
12632
+ var TileLayerMeshes = (0, import_react46.memo)(function TileLayerMeshes2({
12454
12633
  layer,
12455
12634
  manager,
12456
12635
  resolveUrl
12457
12636
  }) {
12458
- return layer.addresses.map((address) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
12637
+ return layer.addresses.map((address) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
12459
12638
  TileMesh,
12460
12639
  {
12461
12640
  address,
@@ -12555,8 +12734,8 @@ function parentAddresses(child, parentLevel, parentFaceSize, tileSize) {
12555
12734
  return addresses;
12556
12735
  }
12557
12736
  function centerFacingAddress(candidates, camera) {
12558
- const direction = camera.getWorldDirection(new import_three22.Vector3());
12559
- const center = new import_three22.Vector3();
12737
+ const direction = camera.getWorldDirection(new import_three23.Vector3());
12738
+ const center = new import_three23.Vector3();
12560
12739
  let bestCandidate = candidates[0];
12561
12740
  let bestAlignment = -Infinity;
12562
12741
  for (const candidate of candidates) {
@@ -12621,11 +12800,11 @@ function Tile({
12621
12800
  onTileError,
12622
12801
  onLevelChange
12623
12802
  }) {
12624
- const { camera, gl, size } = (0, import_fiber21.useThree)();
12625
- const multiresConfig = (0, import_react44.useMemo)(() => parseMultires(multires), [multires]);
12803
+ const { camera, gl, size } = (0, import_fiber22.useThree)();
12804
+ const multiresConfig = (0, import_react46.useMemo)(() => parseMultires(multires), [multires]);
12626
12805
  const { levels, tileSize } = multiresConfig;
12627
12806
  const multiresToken = `${tileSize}:${levels.join(",")}`;
12628
- const candidatesByLevel = (0, import_react44.useMemo)(
12807
+ const candidatesByLevel = (0, import_react46.useMemo)(
12629
12808
  () => buildTileCandidates(levels, tileSize),
12630
12809
  [levels, tileSize]
12631
12810
  );
@@ -12637,13 +12816,13 @@ function Tile({
12637
12816
  onPreviewError
12638
12817
  );
12639
12818
  const sharedManager = useSharedTileTextureManager();
12640
- const progressRef = (0, import_react44.useRef)(onLoadProgress);
12641
- const errorRef = (0, import_react44.useRef)(onTileError);
12642
- const levelChangeRef = (0, import_react44.useRef)(onLevelChange);
12819
+ const progressRef = (0, import_react46.useRef)(onLoadProgress);
12820
+ const errorRef = (0, import_react46.useRef)(onTileError);
12821
+ const levelChangeRef = (0, import_react46.useRef)(onLevelChange);
12643
12822
  progressRef.current = onLoadProgress;
12644
12823
  errorRef.current = onTileError;
12645
12824
  levelChangeRef.current = onLevelChange;
12646
- const ownedManager = (0, import_react44.useMemo)(
12825
+ const ownedManager = (0, import_react46.useMemo)(
12647
12826
  () => new TileTextureManager({
12648
12827
  anisotropy,
12649
12828
  maxBytes: Math.max(1, maxTextureMemoryMb) * 1024 * 1024,
@@ -12664,7 +12843,7 @@ function Tile({
12664
12843
  ]
12665
12844
  );
12666
12845
  const manager = sharedManager ?? ownedManager;
12667
- (0, import_react44.useEffect)(() => {
12846
+ (0, import_react46.useEffect)(() => {
12668
12847
  manager.resume();
12669
12848
  return () => {
12670
12849
  if (manager === ownedManager) {
@@ -12674,11 +12853,11 @@ function Tile({
12674
12853
  queueMicrotask(() => manager.releaseUnused());
12675
12854
  };
12676
12855
  }, [manager, ownedManager]);
12677
- const readyRef = (0, import_react44.useRef)(false);
12678
- (0, import_react44.useEffect)(() => {
12856
+ const readyRef = (0, import_react46.useRef)(false);
12857
+ (0, import_react46.useEffect)(() => {
12679
12858
  readyRef.current = false;
12680
12859
  }, [effectivePreviewUrl]);
12681
- (0, import_react44.useEffect)(() => {
12860
+ (0, import_react46.useEffect)(() => {
12682
12861
  if (!previewTexture || readyRef.current) {
12683
12862
  return;
12684
12863
  }
@@ -12686,31 +12865,37 @@ function Tile({
12686
12865
  onReady?.();
12687
12866
  }, [onReady, previewTexture]);
12688
12867
  const template = urlTemplate ?? buildDefaultTileUrlTemplate();
12689
- const resolveUrl = (0, import_react44.useMemo)(
12868
+ const resolveUrl = (0, import_react46.useMemo)(
12690
12869
  () => (address) => {
12691
12870
  const relativePath = resolveTileUrl ? resolveTileUrl(address) : resolveTemplateUrl(template, address);
12692
12871
  return resolveRelativeTileUrl(baseUrl, relativePath);
12693
12872
  },
12694
12873
  [baseUrl, resolveTileUrl, template]
12695
12874
  );
12696
- const [layers, setLayers] = (0, import_react44.useState)([]);
12697
- const layerTokenRef = (0, import_react44.useRef)("");
12698
- const currentLevelRef = (0, import_react44.useRef)(1);
12699
- const lastUpdateAtRef = (0, import_react44.useRef)(-Infinity);
12700
- const visibilityDirtyRef = (0, import_react44.useRef)(true);
12701
- const lastVisibilityQuaternionRef = (0, import_react44.useRef)(camera.quaternion.clone());
12702
- const lastVisibilityFovRef = (0, import_react44.useRef)(Number.NaN);
12703
- const lastViewportRef = (0, import_react44.useRef)({ width: 0, height: 0, dpr: 0 });
12704
- const frustumRef = (0, import_react44.useRef)(new import_three22.Frustum());
12705
- const projectionMatrixRef = (0, import_react44.useRef)(new import_three22.Matrix4());
12706
- const visibilityCameraRef = (0, import_react44.useRef)(new import_three22.PerspectiveCamera());
12707
- (0, import_react44.useEffect)(() => {
12875
+ const [layers, setLayers] = (0, import_react46.useState)([]);
12876
+ const layerTokenRef = (0, import_react46.useRef)("");
12877
+ const currentLevelRef = (0, import_react46.useRef)(1);
12878
+ const lastUpdateAtRef = (0, import_react46.useRef)(-Infinity);
12879
+ const visibilityDirtyRef = (0, import_react46.useRef)(true);
12880
+ const lastVisibilityQuaternionRef = (0, import_react46.useRef)(camera.quaternion.clone());
12881
+ const lastVisibilityFovRef = (0, import_react46.useRef)(Number.NaN);
12882
+ const lastViewportRef = (0, import_react46.useRef)({ width: 0, height: 0, dpr: 0 });
12883
+ const frustumRef = (0, import_react46.useRef)(new import_three23.Frustum());
12884
+ const projectionMatrixRef = (0, import_react46.useRef)(new import_three23.Matrix4());
12885
+ const visibilityCameraRef = (0, import_react46.useRef)(new import_three23.PerspectiveCamera());
12886
+ const trackedLoadModeRef = (0, import_react46.useRef)(loadMode);
12887
+ const targetKeysRef = (0, import_react46.useRef)([]);
12888
+ const detailTokenRef = (0, import_react46.useRef)("");
12889
+ const detailReporter = useSceneDetailReporter();
12890
+ const detailReporterRef = (0, import_react46.useRef)(detailReporter);
12891
+ detailReporterRef.current = detailReporter;
12892
+ (0, import_react46.useEffect)(() => {
12708
12893
  currentLevelRef.current = 1;
12709
12894
  layerTokenRef.current = "";
12710
12895
  visibilityDirtyRef.current = true;
12711
12896
  setLayers([]);
12712
12897
  }, [manager, multiresToken]);
12713
- (0, import_react44.useEffect)(() => {
12898
+ (0, import_react46.useEffect)(() => {
12714
12899
  if (loadMode !== "preview") {
12715
12900
  return;
12716
12901
  }
@@ -12724,11 +12909,14 @@ function Tile({
12724
12909
  setLayers(nextLayers);
12725
12910
  }
12726
12911
  };
12727
- (0, import_fiber21.useFrame)(() => {
12728
- if (loadMode === "preview") {
12912
+ (0, import_fiber22.useFrame)(() => {
12913
+ if (!(camera instanceof import_three23.PerspectiveCamera)) {
12729
12914
  return;
12730
12915
  }
12731
- if (!(camera instanceof import_three22.PerspectiveCamera)) {
12916
+ if (loadMode === "preview") {
12917
+ trackedLoadModeRef.current = "preview";
12918
+ targetKeysRef.current = [];
12919
+ publishSceneDetail(detailReporterRef.current, detailTokenRef, false);
12732
12920
  return;
12733
12921
  }
12734
12922
  const now = performance.now();
@@ -12739,60 +12927,75 @@ function Tile({
12739
12927
  const fovDelta = Number.isFinite(lastVisibilityFovRef.current) ? Math.abs(camera.fov - lastVisibilityFovRef.current) : Infinity;
12740
12928
  const lastViewport = lastViewportRef.current;
12741
12929
  const viewportChanged = lastViewport.width !== size.width || lastViewport.height !== size.height || lastViewport.dpr !== pixelRatio;
12742
- const viewChanged = visibilityDirtyRef.current || viewportChanged || rotationDelta > VIEW_CHANGE_EPSILON || fovDelta > VIEW_CHANGE_EPSILON;
12743
- const movingQuickly = rotationDelta >= FAST_ROTATION_THRESHOLD_RADIANS || fovDelta >= FAST_FOV_THRESHOLD_DEGREES;
12744
- if (!viewChanged) {
12745
- return;
12746
- }
12747
- const needsImmediateUpdate = visibilityDirtyRef.current || viewportChanged || movingQuickly;
12748
- if (!needsImmediateUpdate && now - lastUpdateAtRef.current < MAX_LOD_UPDATE_INTERVAL_MS) {
12749
- return;
12750
- }
12751
- lastUpdateAtRef.current = now;
12752
- const targetLevel = loadMode === "base" ? 1 : getPreferredLevel(
12753
- levels,
12754
- size.height,
12755
- pixelRatio,
12756
- camera.fov,
12757
- currentLevelRef.current
12758
- );
12759
- if (targetLevel !== currentLevelRef.current) {
12760
- currentLevelRef.current = targetLevel;
12761
- levelChangeRef.current?.(targetLevel);
12762
- }
12763
- const visibilityCamera = visibilityCameraRef.current;
12764
- visibilityCamera.copy(camera, false);
12765
- visibilityCamera.fov = Math.min(
12766
- 179,
12767
- camera.fov + VISIBILITY_FOV_PADDING_DEGREES
12768
- );
12769
- visibilityCamera.aspect = camera.aspect;
12770
- updateVisibilityFrustum(
12771
- visibilityCamera,
12772
- projectionMatrixRef.current,
12773
- frustumRef.current
12774
- );
12775
- const nextLayers = buildLayers(
12776
- targetLevel,
12777
- levels,
12778
- tileSize,
12779
- frustumRef.current,
12780
- camera,
12781
- candidatesByLevel
12930
+ const updateLod = decideTileLodUpdate({
12931
+ loadMode,
12932
+ trackedLoadMode: trackedLoadModeRef.current,
12933
+ now,
12934
+ lastUpdateAt: lastUpdateAtRef.current,
12935
+ visibilityDirty: visibilityDirtyRef.current,
12936
+ viewportChanged,
12937
+ rotationDelta,
12938
+ fovDelta
12939
+ });
12940
+ if (updateLod) {
12941
+ trackedLoadModeRef.current = loadMode;
12942
+ lastUpdateAtRef.current = now;
12943
+ const targetLevel = loadMode === "base" ? 1 : getPreferredLevel(
12944
+ levels,
12945
+ size.height,
12946
+ pixelRatio,
12947
+ camera.fov,
12948
+ currentLevelRef.current
12949
+ );
12950
+ if (targetLevel !== currentLevelRef.current) {
12951
+ currentLevelRef.current = targetLevel;
12952
+ levelChangeRef.current?.(targetLevel);
12953
+ }
12954
+ const visibilityCamera = visibilityCameraRef.current;
12955
+ visibilityCamera.copy(camera, false);
12956
+ visibilityCamera.fov = Math.min(
12957
+ 179,
12958
+ camera.fov + VISIBILITY_FOV_PADDING_DEGREES
12959
+ );
12960
+ visibilityCamera.aspect = camera.aspect;
12961
+ updateVisibilityFrustum(
12962
+ visibilityCamera,
12963
+ projectionMatrixRef.current,
12964
+ frustumRef.current
12965
+ );
12966
+ const nextLayers = buildLayers(
12967
+ targetLevel,
12968
+ levels,
12969
+ tileSize,
12970
+ frustumRef.current,
12971
+ camera,
12972
+ candidatesByLevel
12973
+ );
12974
+ visibilityDirtyRef.current = false;
12975
+ lastVisibilityQuaternionRef.current.copy(camera.quaternion);
12976
+ lastVisibilityFovRef.current = camera.fov;
12977
+ lastViewportRef.current = {
12978
+ width: size.width,
12979
+ height: size.height,
12980
+ dpr: pixelRatio
12981
+ };
12982
+ const targetLayer = nextLayers.find((layer) => layer.level === targetLevel);
12983
+ targetKeysRef.current = loadMode === "full" ? (targetLayer?.addresses ?? []).map(
12984
+ (address) => `${resolveUrl(address)}\0${tileKey(address)}`
12985
+ ) : [];
12986
+ commitLayers(nextLayers);
12987
+ }
12988
+ publishSceneDetail(
12989
+ detailReporterRef.current,
12990
+ detailTokenRef,
12991
+ loadMode === "full" && viewTilesAreDrawable(
12992
+ targetKeysRef.current.map((key) => manager.getSnapshot(key).texture)
12993
+ )
12782
12994
  );
12783
- visibilityDirtyRef.current = false;
12784
- lastVisibilityQuaternionRef.current.copy(camera.quaternion);
12785
- lastVisibilityFovRef.current = camera.fov;
12786
- lastViewportRef.current = {
12787
- width: size.width,
12788
- height: size.height,
12789
- dpr: pixelRatio
12790
- };
12791
- commitLayers(nextLayers);
12792
12995
  });
12793
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("group", { visible, children: [
12794
- previewTexture ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(PreviewCube, { texture: previewTexture, faceOrder: previewFaceOrder }) : null,
12795
- layers.map((layer) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
12996
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("group", { visible, children: [
12997
+ previewTexture ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PreviewCube, { texture: previewTexture, faceOrder: previewFaceOrder }) : null,
12998
+ layers.map((layer) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
12796
12999
  TileLayerMeshes,
12797
13000
  {
12798
13001
  layer,
@@ -12805,7 +13008,7 @@ function Tile({
12805
13008
  }
12806
13009
 
12807
13010
  // src/scenes.tsx
12808
- var import_jsx_runtime23 = require("react/jsx-runtime");
13011
+ var import_jsx_runtime24 = require("react/jsx-runtime");
12809
13012
  function SceneSource({
12810
13013
  scene,
12811
13014
  visible,
@@ -12818,7 +13021,7 @@ function SceneSource({
12818
13021
  }
12819
13022
  switch (scene.type) {
12820
13023
  case "sphere":
12821
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
13024
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12822
13025
  Sphere,
12823
13026
  {
12824
13027
  src: scene.src,
@@ -12831,7 +13034,7 @@ function SceneSource({
12831
13034
  );
12832
13035
  case "tile": {
12833
13036
  const { id: _id, type: _type, ...tileProps } = scene;
12834
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
13037
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12835
13038
  Tile,
12836
13039
  {
12837
13040
  ...tileProps,
@@ -12842,6 +13045,19 @@ function SceneSource({
12842
13045
  }
12843
13046
  );
12844
13047
  }
13048
+ case "sphereTile": {
13049
+ const { id: _id, type: _type, ...tileProps } = scene;
13050
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
13051
+ SphereTile,
13052
+ {
13053
+ ...tileProps,
13054
+ visible,
13055
+ loadMode: baseOnly ? "base" : "full",
13056
+ onReady,
13057
+ onPreviewError: onError
13058
+ }
13059
+ );
13060
+ }
12845
13061
  default: {
12846
13062
  const exhaustive = scene;
12847
13063
  void exhaustive;
@@ -12854,17 +13070,17 @@ function SnapshotCapture({
12854
13070
  maxPixels,
12855
13071
  onCaptured
12856
13072
  }) {
12857
- const { camera, gl, scene, size } = (0, import_fiber22.useThree)();
12858
- const capturedRequestRef = (0, import_react45.useRef)(0);
12859
- const renderTargetRef = (0, import_react45.useRef)(null);
12860
- (0, import_react45.useEffect)(
13073
+ const { camera, gl, scene, size } = (0, import_fiber23.useThree)();
13074
+ const capturedRequestRef = (0, import_react47.useRef)(0);
13075
+ const renderTargetRef = (0, import_react47.useRef)(null);
13076
+ (0, import_react47.useEffect)(
12861
13077
  () => () => {
12862
13078
  renderTargetRef.current?.dispose();
12863
13079
  renderTargetRef.current = null;
12864
13080
  },
12865
13081
  []
12866
13082
  );
12867
- (0, import_fiber22.useFrame)(() => {
13083
+ (0, import_fiber23.useFrame)(() => {
12868
13084
  if (requestId === 0 || requestId === capturedRequestRef.current) {
12869
13085
  return;
12870
13086
  }
@@ -12874,14 +13090,14 @@ function SnapshotCapture({
12874
13090
  const scale = Math.min(1, Math.sqrt(maxPixels / (sourceWidth * sourceHeight)));
12875
13091
  const width = Math.max(1, Math.floor(sourceWidth * scale));
12876
13092
  const height = Math.max(1, Math.floor(sourceHeight * scale));
12877
- const nextTarget = new import_three23.WebGLRenderTarget(width, height, {
13093
+ const nextTarget = new import_three24.WebGLRenderTarget(width, height, {
12878
13094
  depthBuffer: false,
12879
13095
  stencilBuffer: false
12880
13096
  });
12881
- nextTarget.texture.colorSpace = import_three23.LinearSRGBColorSpace;
13097
+ nextTarget.texture.colorSpace = import_three24.LinearSRGBColorSpace;
12882
13098
  nextTarget.texture.generateMipmaps = false;
12883
- nextTarget.texture.minFilter = import_three23.LinearFilter;
12884
- nextTarget.texture.magFilter = import_three23.LinearFilter;
13099
+ nextTarget.texture.minFilter = import_three24.LinearFilter;
13100
+ nextTarget.texture.magFilter = import_three24.LinearFilter;
12885
13101
  const previousTarget = gl.getRenderTarget();
12886
13102
  gl.setRenderTarget(nextTarget);
12887
13103
  gl.clear();
@@ -12908,55 +13124,94 @@ function ScenesController({
12908
13124
  activeSceneId,
12909
13125
  transition: transitionInput,
12910
13126
  renderHotspots,
13127
+ onSceneReady,
12911
13128
  onTransitionEnd,
12912
13129
  onTransitionError,
12913
13130
  snapshotMaxPixels = 3686400,
13131
+ transitionWaitForDetailMs,
12914
13132
  phaseRef: externalPhaseRef
12915
13133
  }) {
12916
- const controlsRef = (0, import_react45.useContext)(PanoramaViewContext);
13134
+ const controlsRef = (0, import_react47.useContext)(PanoramaViewContext);
12917
13135
  const manager = useSharedTileTextureManager();
12918
- const transition = (0, import_react45.useMemo)(
13136
+ const transition = (0, import_react47.useMemo)(
12919
13137
  () => resolveTransition(transitionInput),
12920
13138
  [transitionInput]
12921
13139
  );
12922
- const sceneMap = (0, import_react45.useMemo)(
13140
+ const sceneMap = (0, import_react47.useMemo)(
12923
13141
  () => new Map(scenes.map((scene) => [scene.id, scene])),
12924
13142
  [scenes]
12925
13143
  );
12926
13144
  const initialScene = sceneMap.get(activeSceneId) ?? null;
12927
- const [slots, setSlots] = (0, import_react45.useState)([
13145
+ const [slots, setSlots] = (0, import_react47.useState)([
12928
13146
  initialScene,
12929
13147
  null
12930
13148
  ]);
12931
- const [activeSlot, setActiveSlot] = (0, import_react45.useState)(0);
12932
- const [liveSlot, setLiveSlot] = (0, import_react45.useState)(0);
12933
- const [pendingSlot, setPendingSlot] = (0, import_react45.useState)(null);
12934
- const [phase, setPhase] = (0, import_react45.useState)(initialScene ? "idle" : "preloading");
12935
- const [captureRequestId, setCaptureRequestId] = (0, import_react45.useState)(0);
12936
- const [transitionRunId, setTransitionRunId] = (0, import_react45.useState)(0);
12937
- const [snapshot, setSnapshot] = (0, import_react45.useState)(null);
12938
- const [recoveryKey, setRecoveryKey] = (0, import_react45.useState)(0);
12939
- const requestedSceneIdRef = (0, import_react45.useRef)(activeSceneId);
12940
- const captureReasonRef = (0, import_react45.useRef)("start");
12941
- const interactionReleaseRef = (0, import_react45.useRef)(null);
12942
- const slotsRef = (0, import_react45.useRef)(slots);
12943
- const phaseRef = (0, import_react45.useRef)(phase);
12944
- const liveSlotRef = (0, import_react45.useRef)(liveSlot);
12945
- const transitionFromRef = (0, import_react45.useRef)(initialScene);
13149
+ const [activeSlot, setActiveSlot] = (0, import_react47.useState)(0);
13150
+ const [liveSlot, setLiveSlot] = (0, import_react47.useState)(0);
13151
+ const [pendingSlot, setPendingSlot] = (0, import_react47.useState)(null);
13152
+ const [phase, setPhase] = (0, import_react47.useState)(initialScene ? "idle" : "preloading");
13153
+ const [captureRequestId, setCaptureRequestId] = (0, import_react47.useState)(0);
13154
+ const [transitionRunId, setTransitionRunId] = (0, import_react47.useState)(0);
13155
+ const [snapshot, setSnapshot] = (0, import_react47.useState)(null);
13156
+ const [recoveryKey, setRecoveryKey] = (0, import_react47.useState)(0);
13157
+ const requestedSceneIdRef = (0, import_react47.useRef)(activeSceneId);
13158
+ const captureReasonRef = (0, import_react47.useRef)("start");
13159
+ const interactionReleaseRef = (0, import_react47.useRef)(null);
13160
+ const slotsRef = (0, import_react47.useRef)(slots);
13161
+ const phaseRef = (0, import_react47.useRef)(phase);
13162
+ const liveSlotRef = (0, import_react47.useRef)(liveSlot);
13163
+ const transitionFromRef = (0, import_react47.useRef)(initialScene);
13164
+ const readySceneRef = (0, import_react47.useRef)(null);
13165
+ const waitRef = (0, import_react47.useRef)(null);
13166
+ const waitTimerRef = (0, import_react47.useRef)(null);
13167
+ const detailGenerationRef = (0, import_react47.useRef)(0);
13168
+ const [detailGeneration, setDetailGeneration] = (0, import_react47.useState)(0);
13169
+ const mountedRef = (0, import_react47.useRef)(true);
13170
+ const waitForDetailMsRef = (0, import_react47.useRef)(0);
13171
+ waitForDetailMsRef.current = normalizeTransitionWaitMs(transitionWaitForDetailMs);
12946
13172
  slotsRef.current = slots;
12947
13173
  phaseRef.current = phase;
12948
13174
  if (externalPhaseRef) {
12949
13175
  externalPhaseRef.current = phase;
12950
13176
  }
12951
13177
  liveSlotRef.current = liveSlot;
12952
- const releaseInteraction = (0, import_react45.useCallback)(() => {
13178
+ const releaseInteraction = (0, import_react47.useCallback)(() => {
12953
13179
  interactionReleaseRef.current?.();
12954
13180
  interactionReleaseRef.current = null;
12955
13181
  }, []);
12956
- const reportError = (0, import_react45.useCallback)((sceneId, error) => {
13182
+ const reportError = (0, import_react47.useCallback)((sceneId, error) => {
12957
13183
  onTransitionError?.({ sceneId, error });
12958
13184
  }, [onTransitionError]);
12959
- const startPreload = (0, import_react45.useCallback)((scene) => {
13185
+ const clearDetailWait = (0, import_react47.useCallback)((bumpGeneration) => {
13186
+ if (waitTimerRef.current !== null) {
13187
+ clearTimeout(waitTimerRef.current);
13188
+ waitTimerRef.current = null;
13189
+ }
13190
+ const generation = waitRef.current?.generation;
13191
+ if (generation === void 0) {
13192
+ waitRef.current = null;
13193
+ } else {
13194
+ waitRef.current = acceptDetailWait(waitRef.current, {
13195
+ kind: "cancel",
13196
+ generation
13197
+ }).wait;
13198
+ }
13199
+ if (!bumpGeneration || !mountedRef.current) {
13200
+ return;
13201
+ }
13202
+ const nextGeneration = detailGenerationRef.current + 1;
13203
+ detailGenerationRef.current = nextGeneration;
13204
+ setDetailGeneration(nextGeneration);
13205
+ }, []);
13206
+ (0, import_react47.useEffect)(() => {
13207
+ mountedRef.current = true;
13208
+ return () => {
13209
+ mountedRef.current = false;
13210
+ clearDetailWait(false);
13211
+ };
13212
+ }, [clearDetailWait]);
13213
+ const startPreload = (0, import_react47.useCallback)((scene) => {
13214
+ clearDetailWait(true);
12960
13215
  const nextSlot = 1 - liveSlotRef.current;
12961
13216
  requestedSceneIdRef.current = scene.id;
12962
13217
  setSlots((current) => {
@@ -12966,8 +13221,8 @@ function ScenesController({
12966
13221
  });
12967
13222
  setPendingSlot(nextSlot);
12968
13223
  setPhase("preloading");
12969
- }, []);
12970
- (0, import_react45.useEffect)(() => {
13224
+ }, [clearDetailWait]);
13225
+ (0, import_react47.useEffect)(() => {
12971
13226
  const requested = sceneMap.get(activeSceneId);
12972
13227
  if (!requested) {
12973
13228
  reportError(activeSceneId, new Error(`Unknown panorama scene: ${activeSceneId}`));
@@ -12982,20 +13237,31 @@ function ScenesController({
12982
13237
  requestedSceneIdRef.current = requested.id;
12983
13238
  return;
12984
13239
  }
12985
- if (phaseRef.current === "transitioning" || phaseRef.current === "capturing") {
13240
+ if (phaseRef.current === "transitioning" || phaseRef.current === "capturing" || phaseRef.current === "awaitingDetail") {
13241
+ if (requestedSceneIdRef.current === requested.id) return;
12986
13242
  requestedSceneIdRef.current = requested.id;
12987
13243
  captureReasonRef.current = "interrupt";
13244
+ clearDetailWait(true);
12988
13245
  setPhase("recapturing");
12989
13246
  setCaptureRequestId((current) => current + 1);
12990
13247
  return;
12991
13248
  }
12992
13249
  startPreload(requested);
12993
- }, [activeSceneId, pendingSlot, reportError, sceneMap, startPreload]);
12994
- const handleReady = (0, import_react45.useCallback)((slot) => {
13250
+ }, [activeSceneId, clearDetailWait, pendingSlot, reportError, sceneMap, startPreload]);
13251
+ const notifySceneReady = (0, import_react47.useCallback)((scene) => {
13252
+ if (!scene || readySceneRef.current === scene) return;
13253
+ readySceneRef.current = scene;
13254
+ onSceneReady?.(scene.id);
13255
+ }, [onSceneReady]);
13256
+ const handleReady = (0, import_react47.useCallback)((slot) => {
13257
+ if (slot === liveSlotRef.current && pendingSlot === null && phaseRef.current === "idle") {
13258
+ notifySceneReady(slotsRef.current[slot]);
13259
+ return;
13260
+ }
12995
13261
  if (slot !== pendingSlot || phaseRef.current !== "preloading") {
12996
13262
  return;
12997
13263
  }
12998
- if (transition.preset === "none") {
13264
+ if (transition.preset === "none" && waitForDetailMsRef.current === 0) {
12999
13265
  const previousScene = slotsRef.current[liveSlotRef.current];
13000
13266
  const nextScene = slotsRef.current[slot];
13001
13267
  setSlots((current) => {
@@ -13007,6 +13273,7 @@ function ScenesController({
13007
13273
  setActiveSlot(slot);
13008
13274
  setPendingSlot(null);
13009
13275
  setPhase("idle");
13276
+ notifySceneReady(nextScene);
13010
13277
  if (previousScene && nextScene) {
13011
13278
  onTransitionEnd?.({
13012
13279
  previousSceneId: previousScene.id,
@@ -13021,64 +13288,168 @@ function ScenesController({
13021
13288
  captureReasonRef.current = "start";
13022
13289
  setPhase("capturing");
13023
13290
  setCaptureRequestId((current) => current + 1);
13024
- }, [controlsRef, onTransitionEnd, pendingSlot, transition.preset]);
13025
- const handleCaptured = (0, import_react45.useCallback)((nextSnapshot) => {
13026
- setSnapshot((current) => {
13027
- current?.dispose();
13028
- return nextSnapshot;
13029
- });
13291
+ }, [controlsRef, notifySceneReady, onTransitionEnd, pendingSlot, transition.preset]);
13292
+ const finishTransition = (0, import_react47.useCallback)(() => {
13293
+ const nextSlot = pendingSlot;
13294
+ const previousScene = transitionFromRef.current;
13295
+ const nextScene = nextSlot === null ? null : slotsRef.current[nextSlot];
13296
+ if (nextSlot === null || !nextScene) {
13297
+ releaseInteraction();
13298
+ setPhase("idle");
13299
+ return;
13300
+ }
13301
+ setActiveSlot(nextSlot);
13302
+ setLiveSlot(nextSlot);
13303
+ setPendingSlot(null);
13304
+ setPhase("idle");
13305
+ const oldSnapshot = snapshot;
13306
+ setSnapshot(null);
13307
+ oldSnapshot?.dispose();
13308
+ releaseInteraction();
13309
+ if (previousScene) {
13310
+ onTransitionEnd?.({
13311
+ previousSceneId: previousScene.id,
13312
+ sceneId: nextScene.id,
13313
+ preset: transition.preset
13314
+ });
13315
+ }
13316
+ }, [onTransitionEnd, pendingSlot, releaseInteraction, snapshot, transition.preset]);
13317
+ const finishTransitionRef = (0, import_react47.useRef)(finishTransition);
13318
+ finishTransitionRef.current = finishTransition;
13319
+ const transitionRef = (0, import_react47.useRef)(transition);
13320
+ transitionRef.current = transition;
13321
+ const consumeDetailSignal = (0, import_react47.useCallback)((signal) => {
13322
+ const decision = acceptDetailWait(waitRef.current, signal);
13323
+ waitRef.current = decision.wait;
13324
+ if (!decision.start) {
13325
+ return;
13326
+ }
13327
+ if (waitTimerRef.current !== null) {
13328
+ clearTimeout(waitTimerRef.current);
13329
+ waitTimerRef.current = null;
13330
+ }
13331
+ if (!mountedRef.current) {
13332
+ return;
13333
+ }
13334
+ if (transitionRef.current.preset === "none") {
13335
+ finishTransitionRef.current();
13336
+ return;
13337
+ }
13338
+ setPhase("transitioning");
13339
+ setTransitionRunId((current) => current + 1);
13340
+ }, []);
13341
+ const handleCaptured = (0, import_react47.useCallback)((nextSnapshot) => {
13030
13342
  if (captureReasonRef.current === "interrupt") {
13343
+ setSnapshot((current) => {
13344
+ current?.dispose();
13345
+ return nextSnapshot;
13346
+ });
13031
13347
  startPreload(sceneMap.get(requestedSceneIdRef.current));
13032
13348
  return;
13033
13349
  }
13034
- const sourceSlot = liveSlotRef.current;
13035
- setSlots((current) => {
13036
- const next = [...current];
13037
- next[sourceSlot] = null;
13038
- return next;
13350
+ const sourceSlot = liveSlotRef.current;
13351
+ const incoming = pendingSlot === null ? null : slotsRef.current[pendingSlot];
13352
+ setSlots((current) => {
13353
+ const next = [...current];
13354
+ next[sourceSlot] = null;
13355
+ return next;
13356
+ });
13357
+ manager?.releaseUnused();
13358
+ if (pendingSlot !== null && incoming) {
13359
+ notifySceneReady(incoming);
13360
+ setLiveSlot(pendingSlot);
13361
+ }
13362
+ if (waitTimerRef.current !== null) {
13363
+ clearTimeout(waitTimerRef.current);
13364
+ waitTimerRef.current = null;
13365
+ }
13366
+ waitRef.current = null;
13367
+ let hold = null;
13368
+ if (incoming && waitForDetailMsRef.current > 0) {
13369
+ const now = performance.now();
13370
+ const generation = detailGenerationRef.current + 1;
13371
+ detailGenerationRef.current = generation;
13372
+ hold = planDetailHold({
13373
+ waitMs: waitForDetailMsRef.current,
13374
+ now,
13375
+ generation,
13376
+ sceneId: incoming.id
13377
+ });
13378
+ if (hold) {
13379
+ const deadline = hold.deadline;
13380
+ waitRef.current = hold;
13381
+ setDetailGeneration(generation);
13382
+ waitTimerRef.current = setTimeout(() => {
13383
+ consumeDetailSignal({
13384
+ kind: "timeout",
13385
+ generation,
13386
+ now: deadline
13387
+ });
13388
+ }, Math.max(0, deadline - performance.now()));
13389
+ }
13390
+ }
13391
+ const nextPhase = phaseAfterSnapshot(transition.preset, hold);
13392
+ if (nextPhase === "awaitingDetail") {
13393
+ setSnapshot((current) => {
13394
+ current?.dispose();
13395
+ return nextSnapshot;
13396
+ });
13397
+ setPhase("awaitingDetail");
13398
+ return;
13399
+ }
13400
+ if (nextPhase === "idle") {
13401
+ nextSnapshot.dispose();
13402
+ setSnapshot((current) => {
13403
+ current?.dispose();
13404
+ return null;
13405
+ });
13406
+ if (pendingSlot !== null) {
13407
+ setActiveSlot(pendingSlot);
13408
+ }
13409
+ setPendingSlot(null);
13410
+ setPhase("idle");
13411
+ releaseInteraction();
13412
+ const previousScene = transitionFromRef.current;
13413
+ if (previousScene && incoming) {
13414
+ onTransitionEnd?.({
13415
+ previousSceneId: previousScene.id,
13416
+ sceneId: incoming.id,
13417
+ preset: "none"
13418
+ });
13419
+ }
13420
+ return;
13421
+ }
13422
+ setSnapshot((current) => {
13423
+ current?.dispose();
13424
+ return nextSnapshot;
13039
13425
  });
13040
- manager?.releaseUnused();
13041
- if (pendingSlot !== null) {
13042
- setLiveSlot(pendingSlot);
13043
- }
13044
13426
  setPhase("transitioning");
13045
13427
  setTransitionRunId((current) => current + 1);
13046
- }, [manager, pendingSlot, sceneMap, startPreload]);
13047
- const finishTransition = (0, import_react45.useCallback)(() => {
13048
- const nextSlot = pendingSlot;
13049
- const previousScene = transitionFromRef.current;
13050
- const nextScene = nextSlot === null ? null : slotsRef.current[nextSlot];
13051
- if (nextSlot === null || !nextScene) {
13052
- releaseInteraction();
13053
- setPhase("idle");
13054
- return;
13055
- }
13056
- setActiveSlot(nextSlot);
13057
- setLiveSlot(nextSlot);
13058
- setPendingSlot(null);
13059
- setPhase("idle");
13060
- const oldSnapshot = snapshot;
13061
- setSnapshot(null);
13062
- oldSnapshot?.dispose();
13063
- releaseInteraction();
13064
- if (previousScene) {
13065
- onTransitionEnd?.({
13066
- previousSceneId: previousScene.id,
13067
- sceneId: nextScene.id,
13068
- preset: transition.preset
13069
- });
13070
- }
13071
- }, [onTransitionEnd, pendingSlot, releaseInteraction, snapshot, transition.preset]);
13072
- (0, import_react45.useEffect)(() => () => {
13428
+ }, [
13429
+ consumeDetailSignal,
13430
+ manager,
13431
+ notifySceneReady,
13432
+ onTransitionEnd,
13433
+ pendingSlot,
13434
+ releaseInteraction,
13435
+ sceneMap,
13436
+ startPreload,
13437
+ transition.preset
13438
+ ]);
13439
+ const snapshotRef = (0, import_react47.useRef)(snapshot);
13440
+ snapshotRef.current = snapshot;
13441
+ (0, import_react47.useEffect)(() => () => {
13073
13442
  releaseInteraction();
13074
- snapshot?.dispose();
13075
- }, [releaseInteraction, snapshot]);
13076
- const { gl } = (0, import_fiber22.useThree)();
13077
- (0, import_react45.useEffect)(() => {
13443
+ snapshotRef.current?.dispose();
13444
+ snapshotRef.current = null;
13445
+ }, [releaseInteraction]);
13446
+ const { gl } = (0, import_fiber23.useThree)();
13447
+ (0, import_react47.useEffect)(() => {
13078
13448
  const canvas = gl.domElement;
13079
13449
  const onContextLost = (event) => {
13080
13450
  event.preventDefault();
13081
13451
  releaseInteraction();
13452
+ clearDetailWait(true);
13082
13453
  manager?.dispose();
13083
13454
  snapshot?.dispose();
13084
13455
  setSnapshot(null);
@@ -13086,6 +13457,7 @@ function ScenesController({
13086
13457
  setPhase("idle");
13087
13458
  };
13088
13459
  const onContextRestored = () => {
13460
+ readySceneRef.current = null;
13089
13461
  manager?.resume();
13090
13462
  setRecoveryKey((current) => current + 1);
13091
13463
  };
@@ -13095,11 +13467,30 @@ function ScenesController({
13095
13467
  canvas.removeEventListener("webglcontextlost", onContextLost);
13096
13468
  canvas.removeEventListener("webglcontextrestored", onContextRestored);
13097
13469
  };
13098
- }, [gl, manager, releaseInteraction, snapshot]);
13470
+ }, [clearDetailWait, gl, manager, releaseInteraction, snapshot]);
13099
13471
  const renderedScene = slots[liveSlot];
13100
13472
  const snapshotVisible = snapshot !== null && (phase === "transitioning" || phase === "recapturing" || phase === "preloading");
13101
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_react45.Fragment, { children: [
13102
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
13473
+ const slotSceneKey = `${slots[0]?.id ?? ""}
13474
+ ${slots[1]?.id ?? ""}`;
13475
+ const detailReporters = (0, import_react47.useMemo)(() => {
13476
+ const [firstSceneId = "", secondSceneId = ""] = slotSceneKey.split("\n");
13477
+ const sceneIds = [firstSceneId, secondSceneId];
13478
+ return sceneIds.map((sceneId) => ({
13479
+ generation: detailGeneration,
13480
+ report: (ready) => {
13481
+ if (!ready || sceneId === "") {
13482
+ return;
13483
+ }
13484
+ consumeDetailSignal({
13485
+ kind: "ready",
13486
+ generation: detailGeneration,
13487
+ sceneId
13488
+ });
13489
+ }
13490
+ }));
13491
+ }, [consumeDetailSignal, detailGeneration, slotSceneKey]);
13492
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react47.Fragment, { children: [
13493
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
13103
13494
  SnapshotCapture,
13104
13495
  {
13105
13496
  requestId: captureRequestId,
@@ -13111,23 +13502,30 @@ function ScenesController({
13111
13502
  const source = slots[slot];
13112
13503
  const isLive = slot === liveSlot;
13113
13504
  const isPending = slot === pendingSlot;
13114
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
13115
- SceneSource,
13505
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
13506
+ SceneDetailContext.Provider,
13116
13507
  {
13117
- scene: source,
13118
- visible: isLive,
13119
- baseOnly: isPending && phase !== "idle",
13120
- onReady: () => handleReady(slot),
13121
- onError: (error) => {
13122
- if (source) {
13123
- reportError(source.id, error);
13508
+ value: detailReporters[slot],
13509
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
13510
+ SceneSource,
13511
+ {
13512
+ scene: source,
13513
+ visible: isLive,
13514
+ baseOnly: pendingSceneUsesBaseLayer(phase, isPending),
13515
+ onReady: () => handleReady(slot),
13516
+ onError: (error) => {
13517
+ if (source) {
13518
+ reportError(source.id, error);
13519
+ }
13520
+ }
13124
13521
  }
13125
- }
13522
+ )
13126
13523
  },
13127
13524
  `${slot}:${source?.id ?? "empty"}:${recoveryKey}`
13128
13525
  );
13129
13526
  }),
13130
- snapshotVisible ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
13527
+ snapshot !== null && phase === "awaitingDetail" ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SnapshotHold, { snapshot }) : null,
13528
+ snapshotVisible ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
13131
13529
  TransitionOverlay,
13132
13530
  {
13133
13531
  snapshot,
@@ -13150,11 +13548,11 @@ function Scenes({
13150
13548
  ...rest
13151
13549
  }) {
13152
13550
  const isControlled = controlledId !== void 0;
13153
- const [internalId, setInternalId] = (0, import_react45.useState)(
13551
+ const [internalId, setInternalId] = (0, import_react47.useState)(
13154
13552
  () => controlledId ?? defaultActiveSceneId ?? scenes[0]?.id ?? ""
13155
13553
  );
13156
13554
  const resolvedId = isControlled ? controlledId : internalId;
13157
- const requestSceneChange = (0, import_react45.useCallback)(
13555
+ const requestSceneChange = (0, import_react47.useCallback)(
13158
13556
  (id) => {
13159
13557
  if (isControlled) {
13160
13558
  onActiveSceneIdChange?.(id);
@@ -13164,13 +13562,13 @@ function Scenes({
13164
13562
  },
13165
13563
  [isControlled, onActiveSceneIdChange]
13166
13564
  );
13167
- const scenesRef = (0, import_react45.useRef)(scenes);
13565
+ const scenesRef = (0, import_react47.useRef)(scenes);
13168
13566
  scenesRef.current = scenes;
13169
- const resolvedIdRef = (0, import_react45.useRef)(resolvedId);
13567
+ const resolvedIdRef = (0, import_react47.useRef)(resolvedId);
13170
13568
  resolvedIdRef.current = resolvedId;
13171
- const host = (0, import_react45.useContext)(ScenesHostContext);
13172
- const phaseRef = (0, import_react45.useRef)("idle");
13173
- (0, import_react45.useEffect)(() => {
13569
+ const host = (0, import_react47.useContext)(ScenesHostContext);
13570
+ const phaseRef = (0, import_react47.useRef)("idle");
13571
+ (0, import_react47.useEffect)(() => {
13174
13572
  if (!host) {
13175
13573
  return;
13176
13574
  }
@@ -13220,12 +13618,12 @@ function Scenes({
13220
13618
  }
13221
13619
  };
13222
13620
  }, [host, requestSceneChange]);
13223
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
13621
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
13224
13622
  TileTextureManagerProvider,
13225
13623
  {
13226
13624
  maxTextureMemoryMb,
13227
13625
  maxConcurrentLoads: maxConcurrentTileLoads,
13228
- children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
13626
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
13229
13627
  ScenesController,
13230
13628
  {
13231
13629
  ...rest,
@@ -13239,28 +13637,28 @@ function Scenes({
13239
13637
  }
13240
13638
 
13241
13639
  // src/hotspot/image-hotspot.tsx
13242
- var import_fiber25 = require("@react-three/fiber");
13243
- var import_react49 = require("react");
13244
- var import_three28 = require("three");
13640
+ var import_fiber26 = require("@react-three/fiber");
13641
+ var import_react51 = require("react");
13642
+ var import_three29 = require("three");
13245
13643
 
13246
13644
  // src/hotspot/hotspot-anchor.tsx
13247
- var import_fiber24 = require("@react-three/fiber");
13248
- var import_react48 = require("react");
13249
- var import_three26 = require("three");
13645
+ var import_fiber25 = require("@react-three/fiber");
13646
+ var import_react50 = require("react");
13647
+ var import_three27 = require("three");
13250
13648
 
13251
13649
  // src/hotspot/hotspot-tooltip.tsx
13252
- var import_react47 = require("react");
13650
+ var import_react49 = require("react");
13253
13651
 
13254
13652
  // src/webvr/stereo-html.tsx
13255
- var import_fiber23 = require("@react-three/fiber");
13256
- var import_react46 = require("react");
13653
+ var import_fiber24 = require("@react-three/fiber");
13654
+ var import_react48 = require("react");
13257
13655
  var import_client = require("react-dom/client");
13258
- var import_three24 = require("three");
13259
- var import_jsx_runtime24 = require("react/jsx-runtime");
13656
+ var import_three25 = require("three");
13657
+ var import_jsx_runtime25 = require("react/jsx-runtime");
13260
13658
  function useFallbackStereoView() {
13261
- const runtime = (0, import_react46.useContext)(WebVRRuntimeContext);
13659
+ const runtime = (0, import_react48.useContext)(WebVRRuntimeContext);
13262
13660
  const host = runtime?.host ?? null;
13263
- const fallback = (0, import_react46.useSyncExternalStore)(
13661
+ const fallback = (0, import_react48.useSyncExternalStore)(
13264
13662
  (onStoreChange) => host ? subscribeWebVRHost(host, onStoreChange) : () => void 0,
13265
13663
  () => isFallbackStereoMode(host?.snapshot.mode ?? null),
13266
13664
  () => false
@@ -13275,10 +13673,10 @@ function ProjectedHtml({
13275
13673
  stereoView,
13276
13674
  eye
13277
13675
  }) {
13278
- const { camera, gl, events, size } = (0, import_fiber23.useThree)();
13279
- const group = (0, import_react46.useRef)(null);
13280
- const overlay = (0, import_react46.useRef)(null);
13281
- const scratch = (0, import_react46.useRef)(new import_three24.Vector3());
13676
+ const { camera, gl, events, size } = (0, import_fiber24.useThree)();
13677
+ const group = (0, import_react48.useRef)(null);
13678
+ const overlay = (0, import_react48.useRef)(null);
13679
+ const scratch = (0, import_react48.useRef)(new import_three25.Vector3());
13282
13680
  const target = events.connected || gl.domElement.parentElement;
13283
13681
  const updatePosition = () => {
13284
13682
  const anchor = group.current;
@@ -13306,7 +13704,7 @@ function ProjectedHtml({
13306
13704
  )
13307
13705
  );
13308
13706
  };
13309
- (0, import_react46.useLayoutEffect)(() => {
13707
+ (0, import_react48.useLayoutEffect)(() => {
13310
13708
  if (!target) return;
13311
13709
  const element = document.createElement("div");
13312
13710
  Object.assign(element.style, {
@@ -13324,9 +13722,9 @@ function ProjectedHtml({
13324
13722
  queueMicrotask(() => root.unmount());
13325
13723
  };
13326
13724
  }, [target]);
13327
- (0, import_react46.useLayoutEffect)(() => {
13725
+ (0, import_react48.useLayoutEffect)(() => {
13328
13726
  overlay.current?.root.render(
13329
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
13727
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
13330
13728
  "div",
13331
13729
  {
13332
13730
  "aria-hidden": eye === "right" || void 0,
@@ -13337,19 +13735,19 @@ function ProjectedHtml({
13337
13735
  );
13338
13736
  updatePosition();
13339
13737
  });
13340
- (0, import_fiber23.useFrame)(updatePosition);
13341
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("group", { ref: group });
13738
+ (0, import_fiber24.useFrame)(updatePosition);
13739
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("group", { ref: group });
13342
13740
  }
13343
13741
  function PanoHtml(props) {
13344
13742
  const stereoView = useFallbackStereoView();
13345
- return stereoView ? /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
13346
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ProjectedHtml, { ...props, stereoView, eye: "left" }),
13347
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ProjectedHtml, { ...props, stereoView, eye: "right" })
13348
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ProjectedHtml, { ...props });
13743
+ return stereoView ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
13744
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ProjectedHtml, { ...props, stereoView, eye: "left" }),
13745
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ProjectedHtml, { ...props, stereoView, eye: "right" })
13746
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ProjectedHtml, { ...props });
13349
13747
  }
13350
13748
 
13351
13749
  // src/hotspot/hotspot-tooltip.tsx
13352
- var import_jsx_runtime25 = require("react/jsx-runtime");
13750
+ var import_jsx_runtime26 = require("react/jsx-runtime");
13353
13751
  var DEFAULT_HOTSPOT_TOOLTIP_OFFSET = 12;
13354
13752
  var DEFAULT_HOTSPOT_TOOLTIP_APPEARANCE = {
13355
13753
  background: "rgba(22, 22, 22, 0.72)",
@@ -13421,16 +13819,16 @@ function HotspotTooltip({
13421
13819
  offset = DEFAULT_HOTSPOT_TOOLTIP_OFFSET,
13422
13820
  appearance
13423
13821
  }) {
13424
- const [imageFailed, setImageFailed] = (0, import_react47.useState)(false);
13425
- (0, import_react47.useEffect)(() => {
13822
+ const [imageFailed, setImageFailed] = (0, import_react49.useState)(false);
13823
+ (0, import_react49.useEffect)(() => {
13426
13824
  setImageFailed(false);
13427
13825
  }, [content.image]);
13428
13826
  const showImage = Boolean(content.image) && !imageFailed;
13429
- const resolvedAppearance = (0, import_react47.useMemo)(
13827
+ const resolvedAppearance = (0, import_react49.useMemo)(
13430
13828
  () => resolveHotspotTooltipAppearance(appearance),
13431
13829
  [appearance]
13432
13830
  );
13433
- const bubbleStyle = (0, import_react47.useMemo)(
13831
+ const bubbleStyle = (0, import_react49.useMemo)(
13434
13832
  () => ({
13435
13833
  background: resolvedAppearance.background,
13436
13834
  border: resolvedAppearance.border,
@@ -13452,8 +13850,8 @@ function HotspotTooltip({
13452
13850
  if (!showImage && !content.text) {
13453
13851
  return null;
13454
13852
  }
13455
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(PanoHtml, { pointerEvents: "none", style: WRAPPER_STYLE, zIndexRange: [20, 10], children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "pano-hotspot-tooltip", role: "tooltip", style: bubbleStyle, children: [
13456
- showImage ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
13853
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(PanoHtml, { pointerEvents: "none", style: WRAPPER_STYLE, zIndexRange: [20, 10], children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "pano-hotspot-tooltip", role: "tooltip", style: bubbleStyle, children: [
13854
+ showImage ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
13457
13855
  "img",
13458
13856
  {
13459
13857
  alt: content.imageAlt ?? content.text ?? "",
@@ -13462,7 +13860,7 @@ function HotspotTooltip({
13462
13860
  src: content.image
13463
13861
  }
13464
13862
  ) : null,
13465
- content.text ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
13863
+ content.text ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
13466
13864
  "p",
13467
13865
  {
13468
13866
  className: "pano-hotspot-tooltip-text",
@@ -13478,18 +13876,18 @@ function HotspotTooltip({
13478
13876
  }
13479
13877
 
13480
13878
  // src/hotspot/transform.ts
13481
- var import_three25 = require("three");
13482
- var LOCAL_FORWARD = new import_three25.Vector3(0, 0, 1);
13483
- var CAMERA_POSITION = new import_three25.Vector3();
13879
+ var import_three26 = require("three");
13880
+ var LOCAL_FORWARD = new import_three26.Vector3(0, 0, 1);
13881
+ var CAMERA_POSITION = new import_three26.Vector3();
13484
13882
  function applyHotspotTransform(group, camera, orientation2, surfaceQuaternion3, rotation, scaleMode, referenceFov, useAngularScale, worldWidth, worldHeight, distance) {
13485
13883
  if (orientation2 === "billboard") {
13486
13884
  group.quaternion.copy(camera.quaternion);
13487
13885
  } else {
13488
13886
  group.quaternion.copy(surfaceQuaternion3);
13489
13887
  }
13490
- group.rotateOnAxis(LOCAL_FORWARD, import_three25.MathUtils.degToRad(-rotation));
13491
- let scaleFactor = scaleMode === "fixed" && camera instanceof import_three25.PerspectiveCamera ? fixedScaleFactor(camera.fov, referenceFov) : 1;
13492
- if (scaleMode === "fixed" && orientation2 === "billboard" && useAngularScale && camera instanceof import_three25.PerspectiveCamera) {
13888
+ group.rotateOnAxis(LOCAL_FORWARD, import_three26.MathUtils.degToRad(-rotation));
13889
+ let scaleFactor = scaleMode === "fixed" && camera instanceof import_three26.PerspectiveCamera ? fixedScaleFactor(camera.fov, referenceFov) : 1;
13890
+ if (scaleMode === "fixed" && orientation2 === "billboard" && useAngularScale && camera instanceof import_three26.PerspectiveCamera) {
13493
13891
  group.updateWorldMatrix(true, false);
13494
13892
  CAMERA_POSITION.setFromMatrixPosition(group.matrixWorld).applyMatrix4(
13495
13893
  camera.matrixWorldInverse
@@ -13504,12 +13902,12 @@ function applyHotspotTransform(group, camera, orientation2, surfaceQuaternion3,
13504
13902
  group.updateMatrixWorld();
13505
13903
  }
13506
13904
  function fixedScaleFactor(cameraFov, referenceFov) {
13507
- const safeReferenceFov = import_three25.MathUtils.clamp(referenceFov, 1, 179);
13508
- return Math.tan(import_three25.MathUtils.degToRad(cameraFov) / 2) / Math.tan(import_three25.MathUtils.degToRad(safeReferenceFov) / 2);
13905
+ const safeReferenceFov = import_three26.MathUtils.clamp(referenceFov, 1, 179);
13906
+ return Math.tan(import_three26.MathUtils.degToRad(cameraFov) / 2) / Math.tan(import_three26.MathUtils.degToRad(safeReferenceFov) / 2);
13509
13907
  }
13510
13908
 
13511
13909
  // src/hotspot/hotspot-anchor.tsx
13512
- var import_jsx_runtime26 = require("react/jsx-runtime");
13910
+ var import_jsx_runtime27 = require("react/jsx-runtime");
13513
13911
  var DEFAULT_FLOATING_DISTANCE = 10;
13514
13912
  var PANORAMA_RADIUS = DEFAULT_PANORAMA_RADIUS;
13515
13913
  var PANORAMA_SURFACE_INSET = 4;
@@ -13517,27 +13915,27 @@ var DEFAULT_REFERENCE_FOV = 75;
13517
13915
  var MIN_ANGULAR_SIZE = 0.01;
13518
13916
  var MAX_ANGULAR_SIZE = 179;
13519
13917
  var DRAG_EPSILON_DEGREES = 1e-3;
13520
- var TOOLTIP_WORLD_BOX = new import_three26.Box3();
13521
- var TOOLTIP_LOCAL_BOX = new import_three26.Box3();
13522
- var TOOLTIP_CORNER = new import_three26.Vector3();
13523
- var TOOLTIP_INVERSE = new import_three26.Matrix4();
13524
- var TOOLTIP_WORLD_CORNER = new import_three26.Vector3();
13525
- var TOOLTIP_PROJECTED = new import_three26.Vector3();
13526
- var TOOLTIP_RAY_ORIGIN = new import_three26.Vector3();
13527
- var TOOLTIP_RAY_FAR = new import_three26.Vector3();
13528
- var TOOLTIP_RAY_DIRECTION = new import_three26.Vector3();
13529
- var TOOLTIP_RAY = new import_three26.Ray();
13530
- var TOOLTIP_PLANE = new import_three26.Plane();
13531
- var TOOLTIP_INTERSECTION = new import_three26.Vector3();
13532
- var TOOLTIP_PLANE_NORMAL = new import_three26.Vector3();
13533
- var TOOLTIP_PLANE_POINT = new import_three26.Vector3();
13918
+ var TOOLTIP_WORLD_BOX = new import_three27.Box3();
13919
+ var TOOLTIP_LOCAL_BOX = new import_three27.Box3();
13920
+ var TOOLTIP_CORNER = new import_three27.Vector3();
13921
+ var TOOLTIP_INVERSE = new import_three27.Matrix4();
13922
+ var TOOLTIP_WORLD_CORNER = new import_three27.Vector3();
13923
+ var TOOLTIP_PROJECTED = new import_three27.Vector3();
13924
+ var TOOLTIP_RAY_ORIGIN = new import_three27.Vector3();
13925
+ var TOOLTIP_RAY_FAR = new import_three27.Vector3();
13926
+ var TOOLTIP_RAY_DIRECTION = new import_three27.Vector3();
13927
+ var TOOLTIP_RAY = new import_three27.Ray();
13928
+ var TOOLTIP_PLANE = new import_three27.Plane();
13929
+ var TOOLTIP_INTERSECTION = new import_three27.Vector3();
13930
+ var TOOLTIP_PLANE_NORMAL = new import_three27.Vector3();
13931
+ var TOOLTIP_PLANE_POINT = new import_three27.Vector3();
13534
13932
  var HOTSPOT_MODE_RENDERING = {
13535
13933
  surface: { orientation: "surface", placement: "surface" },
13536
13934
  billboard: { orientation: "billboard", placement: "floating" }
13537
13935
  };
13538
13936
  function angularSizeToWorldSize(size, radius) {
13539
- const safeSize = Number.isFinite(size) ? import_three26.MathUtils.clamp(Math.abs(size), MIN_ANGULAR_SIZE, MAX_ANGULAR_SIZE) : MIN_ANGULAR_SIZE;
13540
- return 2 * radius * Math.tan(import_three26.MathUtils.degToRad(safeSize) / 2);
13937
+ const safeSize = Number.isFinite(size) ? import_three27.MathUtils.clamp(Math.abs(size), MIN_ANGULAR_SIZE, MAX_ANGULAR_SIZE) : MIN_ANGULAR_SIZE;
13938
+ return 2 * radius * Math.tan(import_three27.MathUtils.degToRad(safeSize) / 2);
13541
13939
  }
13542
13940
  function resolveScale(scale) {
13543
13941
  return Number.isFinite(scale) && scale > 0 ? scale : 1;
@@ -13550,39 +13948,39 @@ function resolveDistance(placement, distance, width, height) {
13550
13948
  if (!Number.isFinite(distance)) {
13551
13949
  return DEFAULT_FLOATING_DISTANCE;
13552
13950
  }
13553
- return import_three26.MathUtils.clamp(Math.abs(distance), 0.1, maximumDistance);
13951
+ return import_three27.MathUtils.clamp(Math.abs(distance), 0.1, maximumDistance);
13554
13952
  }
13555
13953
  function maximumHotspotDistance(width, height) {
13556
- const safeWidth = import_three26.MathUtils.clamp(
13954
+ const safeWidth = import_three27.MathUtils.clamp(
13557
13955
  Math.abs(Number.isFinite(width) ? width : MIN_ANGULAR_SIZE),
13558
13956
  MIN_ANGULAR_SIZE,
13559
13957
  MAX_ANGULAR_SIZE
13560
13958
  );
13561
- const safeHeight = import_three26.MathUtils.clamp(
13959
+ const safeHeight = import_three27.MathUtils.clamp(
13562
13960
  Math.abs(Number.isFinite(height) ? height : MIN_ANGULAR_SIZE),
13563
13961
  MIN_ANGULAR_SIZE,
13564
13962
  MAX_ANGULAR_SIZE
13565
13963
  );
13566
13964
  const cornerFactor = Math.hypot(
13567
13965
  1,
13568
- Math.tan(import_three26.MathUtils.degToRad(safeWidth) / 2),
13569
- Math.tan(import_three26.MathUtils.degToRad(safeHeight) / 2)
13966
+ Math.tan(import_three27.MathUtils.degToRad(safeWidth) / 2),
13967
+ Math.tan(import_three27.MathUtils.degToRad(safeHeight) / 2)
13570
13968
  );
13571
13969
  return (PANORAMA_RADIUS - PANORAMA_SURFACE_INSET) / cornerFactor;
13572
13970
  }
13573
13971
  function createSurfaceQuaternion(position) {
13574
13972
  const outward = panoPositionToVector3(position).normalize();
13575
13973
  const inward = outward.clone().negate();
13576
- const pitch = import_three26.MathUtils.degToRad(position.pitch);
13577
- const yaw = import_three26.MathUtils.degToRad(position.yaw);
13578
- const localUp = new import_three26.Vector3(
13974
+ const pitch = import_three27.MathUtils.degToRad(position.pitch);
13975
+ const yaw = import_three27.MathUtils.degToRad(position.yaw);
13976
+ const localUp = new import_three27.Vector3(
13579
13977
  -Math.sin(pitch) * Math.sin(yaw),
13580
13978
  Math.cos(pitch),
13581
13979
  Math.sin(pitch) * Math.cos(yaw)
13582
13980
  ).normalize();
13583
13981
  const localRight = localUp.clone().cross(inward).normalize();
13584
- const basis = new import_three26.Matrix4().makeBasis(localRight, localUp, inward);
13585
- return new import_three26.Quaternion().setFromRotationMatrix(basis);
13982
+ const basis = new import_three27.Matrix4().makeBasis(localRight, localUp, inward);
13983
+ return new import_three27.Quaternion().setFromRotationMatrix(basis);
13586
13984
  }
13587
13985
  function makeInteractionEvent(id, position, event) {
13588
13986
  return {
@@ -13595,7 +13993,7 @@ function makeInteractionEvent(id, position, event) {
13595
13993
  function angularDistance(a, b) {
13596
13994
  const aVector = panoPositionToVector3(a);
13597
13995
  const bVector = panoPositionToVector3(b);
13598
- return import_three26.MathUtils.radToDeg(aVector.angleTo(bVector));
13996
+ return import_three27.MathUtils.radToDeg(aVector.angleTo(bVector));
13599
13997
  }
13600
13998
  function isTooltipOpen(trigger, hovered, focused, pinned) {
13601
13999
  switch (trigger) {
@@ -13826,24 +14224,24 @@ function HotspotAnchor({
13826
14224
  onPositionChange,
13827
14225
  onDragEnd
13828
14226
  }) {
13829
- const controlsRef = (0, import_react48.useContext)(PanoramaViewContext);
13830
- const hotspotTargetRegistry = (0, import_react48.useContext)(HotspotTargetRegistryContext);
13831
- const eventBus = (0, import_react48.useContext)(PanoEventBusContext);
14227
+ const controlsRef = (0, import_react50.useContext)(PanoramaViewContext);
14228
+ const hotspotTargetRegistry = (0, import_react50.useContext)(HotspotTargetRegistryContext);
14229
+ const eventBus = (0, import_react50.useContext)(PanoEventBusContext);
13832
14230
  const cursorApi = usePanoCursor();
13833
- const { camera, size } = (0, import_fiber24.useThree)();
13834
- const groupRef = (0, import_react48.useRef)(null);
13835
- const tooltipAnchorRef = (0, import_react48.useRef)(null);
13836
- const dragStateRef = (0, import_react48.useRef)(null);
13837
- const suppressNextClickRef = (0, import_react48.useRef)(false);
13838
- const [hovered, setHovered] = (0, import_react48.useState)(false);
13839
- const [dragging, setDragging] = (0, import_react48.useState)(false);
13840
- const [pinned, setPinned] = (0, import_react48.useState)(false);
13841
- const tooltipContent = (0, import_react48.useMemo)(
14231
+ const { camera, size } = (0, import_fiber25.useThree)();
14232
+ const groupRef = (0, import_react50.useRef)(null);
14233
+ const tooltipAnchorRef = (0, import_react50.useRef)(null);
14234
+ const dragStateRef = (0, import_react50.useRef)(null);
14235
+ const suppressNextClickRef = (0, import_react50.useRef)(false);
14236
+ const [hovered, setHovered] = (0, import_react50.useState)(false);
14237
+ const [dragging, setDragging] = (0, import_react50.useState)(false);
14238
+ const [pinned, setPinned] = (0, import_react50.useState)(false);
14239
+ const tooltipContent = (0, import_react50.useMemo)(
13842
14240
  () => resolveHotspotTooltipContent(tooltip),
13843
14241
  [tooltip]
13844
14242
  );
13845
14243
  const normalizedPosition = normalizePanoPosition(position);
13846
- (0, import_react48.useEffect)(() => {
14244
+ (0, import_react50.useEffect)(() => {
13847
14245
  if (!hotspotTargetRegistry) {
13848
14246
  return;
13849
14247
  }
@@ -13860,19 +14258,19 @@ function HotspotAnchor({
13860
14258
  scaledWidth,
13861
14259
  scaledHeight
13862
14260
  );
13863
- const worldPosition = (0, import_react48.useMemo)(
14261
+ const worldPosition = (0, import_react50.useMemo)(
13864
14262
  () => panoPositionToVector3(normalizedPosition, resolvedDistance),
13865
14263
  [normalizedPosition.pitch, normalizedPosition.yaw, resolvedDistance]
13866
14264
  );
13867
- const surfaceQuaternion3 = (0, import_react48.useMemo)(
14265
+ const surfaceQuaternion3 = (0, import_react50.useMemo)(
13868
14266
  () => createSurfaceQuaternion(normalizedPosition),
13869
14267
  [normalizedPosition.pitch, normalizedPosition.yaw]
13870
14268
  );
13871
14269
  const worldWidth = angularSizeToWorldSize(scaledWidth, resolvedDistance);
13872
14270
  const worldHeight = angularSizeToWorldSize(scaledHeight, resolvedDistance);
13873
- const focusGeometry = (0, import_react48.useMemo)(() => {
13874
- const planeGeometry = new import_three26.PlaneGeometry(1, 1);
13875
- const geometry = new import_three26.EdgesGeometry(planeGeometry);
14271
+ const focusGeometry = (0, import_react50.useMemo)(() => {
14272
+ const planeGeometry = new import_three27.PlaneGeometry(1, 1);
14273
+ const geometry = new import_three27.EdgesGeometry(planeGeometry);
13876
14274
  planeGeometry.dispose();
13877
14275
  return geometry;
13878
14276
  }, []);
@@ -13897,14 +14295,14 @@ function HotspotAnchor({
13897
14295
  });
13898
14296
  const tooltipOpen = visible && tooltipContent !== null && isTooltipOpen(tooltipTrigger, hovered, focused, pinned);
13899
14297
  const cursorClaimId = hotspotCursorClaimId(id);
13900
- (0, import_react48.useEffect)(
14298
+ (0, import_react50.useEffect)(
13901
14299
  () => () => {
13902
14300
  dragStateRef.current?.releaseInteractionLock();
13903
14301
  dragStateRef.current = null;
13904
14302
  },
13905
14303
  []
13906
14304
  );
13907
- (0, import_react48.useEffect)(() => {
14305
+ (0, import_react50.useEffect)(() => {
13908
14306
  if (!cursorApi) {
13909
14307
  return;
13910
14308
  }
@@ -13926,14 +14324,14 @@ function HotspotAnchor({
13926
14324
  hovered,
13927
14325
  visible
13928
14326
  ]);
13929
- (0, import_react48.useEffect)(
14327
+ (0, import_react50.useEffect)(
13930
14328
  () => () => {
13931
14329
  cursorApi?.release(cursorClaimId);
13932
14330
  },
13933
14331
  [cursorApi, cursorClaimId]
13934
14332
  );
13935
- (0, import_react48.useEffect)(() => () => focusGeometry.dispose(), [focusGeometry]);
13936
- (0, import_react48.useEffect)(() => {
14333
+ (0, import_react50.useEffect)(() => () => focusGeometry.dispose(), [focusGeometry]);
14334
+ (0, import_react50.useEffect)(() => {
13937
14335
  if (tooltipTrigger !== "click") {
13938
14336
  setPinned(false);
13939
14337
  return;
@@ -13942,12 +14340,12 @@ function HotspotAnchor({
13942
14340
  setPinned(false);
13943
14341
  });
13944
14342
  }, [eventBus, tooltipTrigger]);
13945
- (0, import_react48.useEffect)(() => {
14343
+ (0, import_react50.useEffect)(() => {
13946
14344
  if (tooltipTrigger !== "hover") {
13947
14345
  setHovered(false);
13948
14346
  }
13949
14347
  }, [tooltipTrigger]);
13950
- (0, import_react48.useEffect)(() => {
14348
+ (0, import_react50.useEffect)(() => {
13951
14349
  if (acceptsPointer) {
13952
14350
  return;
13953
14351
  }
@@ -13960,7 +14358,7 @@ function HotspotAnchor({
13960
14358
  dragStateRef.current = null;
13961
14359
  setDragging(false);
13962
14360
  }, [acceptsPointer]);
13963
- (0, import_react48.useLayoutEffect)(() => {
14361
+ (0, import_react50.useLayoutEffect)(() => {
13964
14362
  const group = groupRef.current;
13965
14363
  if (!group) {
13966
14364
  return;
@@ -14003,7 +14401,7 @@ function HotspotAnchor({
14003
14401
  worldHeight,
14004
14402
  worldWidth
14005
14403
  ]);
14006
- (0, import_fiber24.useFrame)((state) => {
14404
+ (0, import_fiber25.useFrame)((state) => {
14007
14405
  const group = groupRef.current;
14008
14406
  if (!group) {
14009
14407
  return;
@@ -14062,7 +14460,7 @@ function HotspotAnchor({
14062
14460
  setHovered(true);
14063
14461
  }
14064
14462
  };
14065
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
14463
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
14066
14464
  "group",
14067
14465
  {
14068
14466
  ref: groupRef,
@@ -14139,18 +14537,18 @@ function HotspotAnchor({
14139
14537
  } : void 0,
14140
14538
  onPointerUp: acceptsPointer ? (event) => releasePointer(event, true) : void 0,
14141
14539
  children: [
14142
- focused ? focusContent ?? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
14540
+ focused ? focusContent ?? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
14143
14541
  "lineSegments",
14144
14542
  {
14145
14543
  geometry: focusGeometry,
14146
14544
  position: [0, 0, 0.01],
14147
14545
  renderOrder: renderOrder + 1,
14148
14546
  scale: [1.12, 1.12, 1],
14149
- children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("lineBasicMaterial", { color: "#f5fbfc", depthTest: false })
14547
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("lineBasicMaterial", { color: "#f5fbfc", depthTest: false })
14150
14548
  }
14151
14549
  ) : null,
14152
14550
  children,
14153
- tooltipOpen && tooltipContent ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("group", { ref: tooltipAnchorRef, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
14551
+ tooltipOpen && tooltipContent ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("group", { ref: tooltipAnchorRef, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
14154
14552
  HotspotTooltip,
14155
14553
  {
14156
14554
  appearance: tooltipAppearance,
@@ -14165,10 +14563,10 @@ function HotspotAnchor({
14165
14563
  }
14166
14564
 
14167
14565
  // src/hotspot/hotspot-plane.tsx
14168
- var import_three27 = require("three");
14169
- var import_jsx_runtime27 = require("react/jsx-runtime");
14566
+ var import_three28 = require("three");
14567
+ var import_jsx_runtime28 = require("react/jsx-runtime");
14170
14568
  var HOTSPOT_ALPHA_CUTOFF = 0.05;
14171
- var SAMPLE_UV = new import_three27.Vector2();
14569
+ var SAMPLE_UV = new import_three28.Vector2();
14172
14570
  var RAYCAST_HITS = [];
14173
14571
  var IMAGE_DATA_CACHE = /* @__PURE__ */ new WeakMap();
14174
14572
  function clampOpacity(opacity) {
@@ -14242,8 +14640,8 @@ function sampleTextureAlpha(texture, u, v) {
14242
14640
  }
14243
14641
  function hotspotPlaneRaycast(raycaster, intersects2) {
14244
14642
  const material = Array.isArray(this.material) ? this.material[0] : this.material;
14245
- if (!(material instanceof import_three27.MeshBasicMaterial)) {
14246
- import_three27.Mesh.prototype.raycast.call(this, raycaster, intersects2);
14643
+ if (!(material instanceof import_three28.MeshBasicMaterial)) {
14644
+ import_three28.Mesh.prototype.raycast.call(this, raycaster, intersects2);
14247
14645
  return;
14248
14646
  }
14249
14647
  const cutoff = Math.max(material.alphaTest, HOTSPOT_ALPHA_CUTOFF);
@@ -14251,7 +14649,7 @@ function hotspotPlaneRaycast(raycaster, intersects2) {
14251
14649
  return;
14252
14650
  }
14253
14651
  RAYCAST_HITS.length = 0;
14254
- import_three27.Mesh.prototype.raycast.call(this, raycaster, RAYCAST_HITS);
14652
+ import_three28.Mesh.prototype.raycast.call(this, raycaster, RAYCAST_HITS);
14255
14653
  const map = material.map;
14256
14654
  for (const hit of RAYCAST_HITS) {
14257
14655
  if (!map || !hit.uv) {
@@ -14268,16 +14666,16 @@ function HotspotPlane({
14268
14666
  map,
14269
14667
  opacity
14270
14668
  }) {
14271
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("mesh", { raycast: hotspotPlaneRaycast, children: [
14272
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("planeGeometry", { args: [1, 1] }),
14273
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
14669
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("mesh", { raycast: hotspotPlaneRaycast, children: [
14670
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("planeGeometry", { args: [1, 1] }),
14671
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
14274
14672
  PanoBasicMaterial,
14275
14673
  {
14276
14674
  target: "hotspot",
14277
14675
  alphaTest: HOTSPOT_ALPHA_CUTOFF,
14278
14676
  map,
14279
14677
  opacity: map ? clampOpacity(opacity) : 0,
14280
- side: import_three27.DoubleSide,
14678
+ side: import_three28.DoubleSide,
14281
14679
  toneMapped: false,
14282
14680
  transparent: true
14283
14681
  }
@@ -14286,15 +14684,15 @@ function HotspotPlane({
14286
14684
  }
14287
14685
 
14288
14686
  // src/hotspot/image-hotspot.tsx
14289
- var import_jsx_runtime28 = require("react/jsx-runtime");
14687
+ var import_jsx_runtime29 = require("react/jsx-runtime");
14290
14688
  function useHotspotImageTexture(src, onLoad, onError) {
14291
- const gl = (0, import_fiber25.useThree)((state) => state.gl);
14292
- const [texture, setTexture] = (0, import_react49.useState)(null);
14293
- const onLoadRef = (0, import_react49.useRef)(onLoad);
14294
- const onErrorRef = (0, import_react49.useRef)(onError);
14689
+ const gl = (0, import_fiber26.useThree)((state) => state.gl);
14690
+ const [texture, setTexture] = (0, import_react51.useState)(null);
14691
+ const onLoadRef = (0, import_react51.useRef)(onLoad);
14692
+ const onErrorRef = (0, import_react51.useRef)(onError);
14295
14693
  onLoadRef.current = onLoad;
14296
14694
  onErrorRef.current = onError;
14297
- (0, import_react49.useEffect)(() => {
14695
+ (0, import_react51.useEffect)(() => {
14298
14696
  let active = true;
14299
14697
  setTexture(null);
14300
14698
  if (!src) {
@@ -14302,7 +14700,7 @@ function useHotspotImageTexture(src, onLoad, onError) {
14302
14700
  active = false;
14303
14701
  };
14304
14702
  }
14305
- const loader = new import_three28.TextureLoader();
14703
+ const loader = new import_three29.TextureLoader();
14306
14704
  loader.load(
14307
14705
  src,
14308
14706
  (loadedTexture) => {
@@ -14310,11 +14708,11 @@ function useHotspotImageTexture(src, onLoad, onError) {
14310
14708
  loadedTexture.dispose();
14311
14709
  return;
14312
14710
  }
14313
- loadedTexture.colorSpace = import_three28.SRGBColorSpace;
14314
- loadedTexture.wrapS = import_three28.ClampToEdgeWrapping;
14315
- loadedTexture.wrapT = import_three28.ClampToEdgeWrapping;
14316
- loadedTexture.magFilter = import_three28.LinearFilter;
14317
- loadedTexture.minFilter = import_three28.LinearMipmapLinearFilter;
14711
+ loadedTexture.colorSpace = import_three29.SRGBColorSpace;
14712
+ loadedTexture.wrapS = import_three29.ClampToEdgeWrapping;
14713
+ loadedTexture.wrapT = import_three29.ClampToEdgeWrapping;
14714
+ loadedTexture.magFilter = import_three29.LinearFilter;
14715
+ loadedTexture.minFilter = import_three29.LinearMipmapLinearFilter;
14318
14716
  loadedTexture.generateMipmaps = true;
14319
14717
  loadedTexture.anisotropy = gl.capabilities.getMaxAnisotropy();
14320
14718
  loadedTexture.needsUpdate = true;
@@ -14332,7 +14730,7 @@ function useHotspotImageTexture(src, onLoad, onError) {
14332
14730
  active = false;
14333
14731
  };
14334
14732
  }, [gl, src]);
14335
- (0, import_react49.useEffect)(
14733
+ (0, import_react51.useEffect)(
14336
14734
  () => () => {
14337
14735
  texture?.dispose();
14338
14736
  },
@@ -14350,20 +14748,20 @@ function ImageHotspot({
14350
14748
  ...anchorProps
14351
14749
  }) {
14352
14750
  const texture = useHotspotImageTexture(src, onLoad, onError);
14353
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(HotspotPlane, { map: texture, opacity }) });
14751
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(HotspotPlane, { map: texture, opacity }) });
14354
14752
  }
14355
14753
 
14356
14754
  // src/hotspot/polygon-hotspot.tsx
14357
- var import_react51 = require("react");
14358
- var import_three30 = require("three");
14755
+ var import_react53 = require("react");
14756
+ var import_three31 = require("three");
14359
14757
 
14360
14758
  // src/hotspot/hotspot-stroke-line.tsx
14361
14759
  var import_drei = require("@react-three/drei");
14362
- var import_fiber26 = require("@react-three/fiber");
14363
- var import_react50 = require("react");
14364
- var import_three29 = require("three");
14365
- var import_jsx_runtime29 = require("react/jsx-runtime");
14366
- var LINE_WORLD_POSITION = new import_three29.Vector3();
14760
+ var import_fiber27 = require("@react-three/fiber");
14761
+ var import_react52 = require("react");
14762
+ var import_three30 = require("three");
14763
+ var import_jsx_runtime30 = require("react/jsx-runtime");
14764
+ var LINE_WORLD_POSITION = new import_three30.Vector3();
14367
14765
  function applyScreenSpaceDashScale(object, camera, viewportHeight) {
14368
14766
  const material = object?.material;
14369
14767
  if (!object || typeof material?.dashScale !== "number") {
@@ -14371,8 +14769,8 @@ function applyScreenSpaceDashScale(object, camera, viewportHeight) {
14371
14769
  }
14372
14770
  object.getWorldPosition(LINE_WORLD_POSITION);
14373
14771
  const depth = Math.max(camera.position.distanceTo(LINE_WORLD_POSITION), 1);
14374
- const fov = camera instanceof import_three29.PerspectiveCamera ? camera.fov : 75;
14375
- material.dashScale = viewportHeight / (2 * Math.tan(import_three29.MathUtils.degToRad(fov) * 0.5) * depth);
14772
+ const fov = camera instanceof import_three30.PerspectiveCamera ? camera.fov : 75;
14773
+ material.dashScale = viewportHeight / (2 * Math.tan(import_three30.MathUtils.degToRad(fov) * 0.5) * depth);
14376
14774
  }
14377
14775
  function resolveDash(dashSize, gapSize) {
14378
14776
  if (dashSize === void 0 || !Number.isFinite(dashSize) || dashSize <= 0) {
@@ -14393,22 +14791,22 @@ function HotspotStrokeLine({
14393
14791
  dashSize,
14394
14792
  gapSize
14395
14793
  }) {
14396
- const lineRef = (0, import_react50.useRef)(null);
14397
- const { camera, size } = (0, import_fiber26.useThree)();
14794
+ const lineRef = (0, import_react52.useRef)(null);
14795
+ const { camera, size } = (0, import_fiber27.useThree)();
14398
14796
  const dash = resolveDash(dashSize, gapSize);
14399
- (0, import_react50.useLayoutEffect)(() => {
14797
+ (0, import_react52.useLayoutEffect)(() => {
14400
14798
  if (!dash.dashed) {
14401
14799
  return;
14402
14800
  }
14403
14801
  applyScreenSpaceDashScale(lineRef.current, camera, size.height);
14404
14802
  }, [camera, dash.dashed, dash.dashSize, dash.gapSize, size.height]);
14405
- (0, import_fiber26.useFrame)((state) => {
14803
+ (0, import_fiber27.useFrame)((state) => {
14406
14804
  if (!dash.dashed) {
14407
14805
  return;
14408
14806
  }
14409
14807
  applyScreenSpaceDashScale(lineRef.current, state.camera, state.size.height);
14410
14808
  });
14411
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
14809
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
14412
14810
  import_drei.Line,
14413
14811
  {
14414
14812
  ref: lineRef,
@@ -14430,7 +14828,7 @@ function HotspotStrokeLine({
14430
14828
  }
14431
14829
 
14432
14830
  // src/hotspot/polygon-hotspot.tsx
14433
- var import_jsx_runtime30 = require("react/jsx-runtime");
14831
+ var import_jsx_runtime31 = require("react/jsx-runtime");
14434
14832
  var POLYGON_RADIUS = 990;
14435
14833
  var MAX_FILL_SEGMENT_DEGREES = 7;
14436
14834
  function cloneVertices(vertices) {
@@ -14465,7 +14863,7 @@ function intersects(a, b, c, d) {
14465
14863
  }
14466
14864
  function hasSelfIntersection(vertices) {
14467
14865
  const points = vertices.map(
14468
- (vertex) => new import_three30.Vector2(vertex.unwrappedYaw, vertex.pitch)
14866
+ (vertex) => new import_three31.Vector2(vertex.unwrappedYaw, vertex.pitch)
14469
14867
  );
14470
14868
  for (let index = 0; index < points.length; index += 1) {
14471
14869
  const nextIndex = (index + 1) % points.length;
@@ -14502,7 +14900,7 @@ function polygonContainsDirection(vertices, direction) {
14502
14900
  }
14503
14901
  function fitsHemisphere(vertices) {
14504
14902
  const directions = vertices.map((vertex) => panoPositionToVector3(vertex).normalize());
14505
- const candidates = [new import_three30.Vector3()];
14903
+ const candidates = [new import_three31.Vector3()];
14506
14904
  for (const direction of directions) {
14507
14905
  candidates[0].add(direction);
14508
14906
  candidates.push(direction.clone());
@@ -14526,7 +14924,7 @@ function validatePolygonVertices(vertices) {
14526
14924
  if (hasSelfIntersection(unwrapped)) {
14527
14925
  issues.push({ code: "self_intersection", message: "Polygon edges cannot cross." });
14528
14926
  }
14529
- if (polygonContainsDirection(normalized, new import_three30.Vector3(0, 1, 0)) || polygonContainsDirection(normalized, new import_three30.Vector3(0, -1, 0))) {
14927
+ if (polygonContainsDirection(normalized, new import_three31.Vector3(0, 1, 0)) || polygonContainsDirection(normalized, new import_three31.Vector3(0, -1, 0))) {
14530
14928
  issues.push({ code: "contains_pole", message: "Polygons cannot contain a panorama pole." });
14531
14929
  }
14532
14930
  if (!fitsHemisphere(normalized)) {
@@ -14537,7 +14935,7 @@ function validatePolygonVertices(vertices) {
14537
14935
  function polygonCenter(vertices) {
14538
14936
  const sum = vertices.reduce(
14539
14937
  (total, vertex) => total.add(panoPositionToVector3(vertex).normalize()),
14540
- new import_three30.Vector3()
14938
+ new import_three31.Vector3()
14541
14939
  );
14542
14940
  return sum.lengthSq() > 1e-8 ? vector3ToPanoPosition(sum) : normalizePanoPosition(vertices[0]);
14543
14941
  }
@@ -14546,20 +14944,20 @@ function surfaceQuaternion(position) {
14546
14944
  const inward = outward.clone().negate();
14547
14945
  const pitch = position.pitch * Math.PI / 180;
14548
14946
  const yaw = position.yaw * Math.PI / 180;
14549
- const localUp = new import_three30.Vector3(
14947
+ const localUp = new import_three31.Vector3(
14550
14948
  -Math.sin(pitch) * Math.sin(yaw),
14551
14949
  Math.cos(pitch),
14552
14950
  Math.sin(pitch) * Math.cos(yaw)
14553
14951
  ).normalize();
14554
- return new import_three30.Quaternion().setFromRotationMatrix(
14555
- new import_three30.Matrix4().makeBasis(localUp.clone().cross(inward).normalize(), localUp, inward)
14952
+ return new import_three31.Quaternion().setFromRotationMatrix(
14953
+ new import_three31.Matrix4().makeBasis(localUp.clone().cross(inward).normalize(), localUp, inward)
14556
14954
  );
14557
14955
  }
14558
14956
  function makeWorldToLocal(center) {
14559
- return new import_three30.Matrix4().compose(
14957
+ return new import_three31.Matrix4().compose(
14560
14958
  panoPositionToVector3(center, POLYGON_RADIUS),
14561
14959
  surfaceQuaternion(center),
14562
- new import_three30.Vector3(1, 1, 1)
14960
+ new import_three31.Vector3(1, 1, 1)
14563
14961
  ).invert();
14564
14962
  }
14565
14963
  function projectedPoint(a, b, c, weightB, weightC, radius, worldToLocal) {
@@ -14614,8 +15012,8 @@ function addSubdividedTriangle(positions, indices, a, b, c, worldToLocal, steps)
14614
15012
  }
14615
15013
  function makeFillGeometry(vertices, center) {
14616
15014
  const unwrapped = unwrapPolygonVertices(vertices);
14617
- const contour = unwrapped.map((vertex) => new import_three30.Vector2(vertex.unwrappedYaw, vertex.pitch));
14618
- const triangles = import_three30.ShapeUtils.triangulateShape(contour, []);
15015
+ const contour = unwrapped.map((vertex) => new import_three31.Vector2(vertex.unwrappedYaw, vertex.pitch));
15016
+ const triangles = import_three31.ShapeUtils.triangulateShape(contour, []);
14619
15017
  const positions = [];
14620
15018
  const indices = [];
14621
15019
  const worldToLocal = makeWorldToLocal(center);
@@ -14631,7 +15029,7 @@ function makeFillGeometry(vertices, center) {
14631
15029
  steps
14632
15030
  );
14633
15031
  }
14634
- return new import_three30.BufferGeometry().setAttribute("position", new import_three30.Float32BufferAttribute(positions, 3)).setIndex(indices);
15032
+ return new import_three31.BufferGeometry().setAttribute("position", new import_three31.Float32BufferAttribute(positions, 3)).setIndex(indices);
14635
15033
  }
14636
15034
  function makeStrokePositions(vertices, center) {
14637
15035
  const points = [];
@@ -14686,24 +15084,24 @@ function PolygonHotspot({
14686
15084
  onInvalid,
14687
15085
  ...anchorProps
14688
15086
  }) {
14689
- const issues = (0, import_react51.useMemo)(() => validatePolygonVertices(vertices), [vertices]);
15087
+ const issues = (0, import_react53.useMemo)(() => validatePolygonVertices(vertices), [vertices]);
14690
15088
  const valid = issues.length === 0;
14691
- const center = (0, import_react51.useMemo)(() => valid ? polygonCenter(vertices) : null, [valid, vertices]);
14692
- const fillGeometry = (0, import_react51.useMemo)(
15089
+ const center = (0, import_react53.useMemo)(() => valid ? polygonCenter(vertices) : null, [valid, vertices]);
15090
+ const fillGeometry = (0, import_react53.useMemo)(
14693
15091
  () => valid && center ? makeFillGeometry(vertices, center) : null,
14694
15092
  [center, valid, vertices]
14695
15093
  );
14696
- const strokePoints = (0, import_react51.useMemo)(
15094
+ const strokePoints = (0, import_react53.useMemo)(
14697
15095
  () => valid && center ? makeStrokePositions(vertices, center) : null,
14698
15096
  [center, valid, vertices]
14699
15097
  );
14700
15098
  const resolvedStrokeOpacity = Math.max(0, Math.min(strokeOpacity, 1));
14701
- const startVerticesRef = (0, import_react51.useRef)(null);
15099
+ const startVerticesRef = (0, import_react53.useRef)(null);
14702
15100
  const issuesKey = issues.map((issue) => issue.code).join(",");
14703
- (0, import_react51.useEffect)(() => {
15101
+ (0, import_react53.useEffect)(() => {
14704
15102
  if (!valid) onInvalid?.(issues);
14705
15103
  }, [issues, issuesKey, onInvalid, valid]);
14706
- (0, import_react51.useEffect)(() => () => fillGeometry?.dispose(), [fillGeometry]);
15104
+ (0, import_react53.useEffect)(() => () => fillGeometry?.dispose(), [fillGeometry]);
14707
15105
  if (!valid || !center || !fillGeometry || !strokePoints || strokePoints.length < 2) {
14708
15106
  return null;
14709
15107
  }
@@ -14718,7 +15116,7 @@ function PolygonHotspot({
14718
15116
  startPosition: event.startPosition
14719
15117
  });
14720
15118
  };
14721
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
15119
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
14722
15120
  HotspotAnchor,
14723
15121
  {
14724
15122
  ...anchorProps,
@@ -14733,7 +15131,7 @@ function PolygonHotspot({
14733
15131
  draggable,
14734
15132
  interactive,
14735
15133
  useAngularScale: false,
14736
- focusContent: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
15134
+ focusContent: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
14737
15135
  HotspotStrokeLine,
14738
15136
  {
14739
15137
  color: "#75cbd3",
@@ -14755,17 +15153,17 @@ function PolygonHotspot({
14755
15153
  startVerticesRef.current = null;
14756
15154
  },
14757
15155
  children: [
14758
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("mesh", { geometry: fillGeometry, renderOrder, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
15156
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("mesh", { geometry: fillGeometry, renderOrder, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
14759
15157
  "meshBasicMaterial",
14760
15158
  {
14761
15159
  color: fill,
14762
15160
  depthWrite: false,
14763
15161
  opacity: Math.max(0, Math.min(fillOpacity, 1)),
14764
- side: import_three30.DoubleSide,
15162
+ side: import_three31.DoubleSide,
14765
15163
  transparent: true
14766
15164
  }
14767
15165
  ) }),
14768
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
15166
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
14769
15167
  HotspotStrokeLine,
14770
15168
  {
14771
15169
  color: stroke,
@@ -14783,9 +15181,9 @@ function PolygonHotspot({
14783
15181
  }
14784
15182
 
14785
15183
  // src/hotspot/polyline-hotspot.tsx
14786
- var import_react52 = require("react");
14787
- var import_three31 = require("three");
14788
- var import_jsx_runtime31 = require("react/jsx-runtime");
15184
+ var import_react54 = require("react");
15185
+ var import_three32 = require("three");
15186
+ var import_jsx_runtime32 = require("react/jsx-runtime");
14789
15187
  var POLYLINE_RADIUS = 990;
14790
15188
  var MAX_SEGMENT_DEGREES = 7;
14791
15189
  function cloneVertices2(vertices) {
@@ -14810,29 +15208,29 @@ function unwrapVertices(vertices) {
14810
15208
  function polylineCenter(vertices) {
14811
15209
  const sum = vertices.reduce(
14812
15210
  (total, vertex) => total.add(panoPositionToVector3(vertex).normalize()),
14813
- new import_three31.Vector3()
15211
+ new import_three32.Vector3()
14814
15212
  );
14815
15213
  return sum.lengthSq() > 1e-8 ? vector3ToPanoPosition(sum) : normalizePanoPosition(vertices[0]);
14816
15214
  }
14817
15215
  function surfaceQuaternion2(position) {
14818
15216
  const outward = panoPositionToVector3(position).normalize();
14819
15217
  const inward = outward.clone().negate();
14820
- const pitch = import_three31.MathUtils.degToRad(position.pitch);
14821
- const yaw = import_three31.MathUtils.degToRad(position.yaw);
14822
- const localUp = new import_three31.Vector3(
15218
+ const pitch = import_three32.MathUtils.degToRad(position.pitch);
15219
+ const yaw = import_three32.MathUtils.degToRad(position.yaw);
15220
+ const localUp = new import_three32.Vector3(
14823
15221
  -Math.sin(pitch) * Math.sin(yaw),
14824
15222
  Math.cos(pitch),
14825
15223
  Math.sin(pitch) * Math.cos(yaw)
14826
15224
  ).normalize();
14827
- return new import_three31.Quaternion().setFromRotationMatrix(
14828
- new import_three31.Matrix4().makeBasis(localUp.clone().cross(inward).normalize(), localUp, inward)
15225
+ return new import_three32.Quaternion().setFromRotationMatrix(
15226
+ new import_three32.Matrix4().makeBasis(localUp.clone().cross(inward).normalize(), localUp, inward)
14829
15227
  );
14830
15228
  }
14831
15229
  function makeWorldToLocal2(center) {
14832
- return new import_three31.Matrix4().compose(
15230
+ return new import_three32.Matrix4().compose(
14833
15231
  panoPositionToVector3(center, POLYLINE_RADIUS),
14834
15232
  surfaceQuaternion2(center),
14835
- new import_three31.Vector3(1, 1, 1)
15233
+ new import_three32.Vector3(1, 1, 1)
14836
15234
  ).invert();
14837
15235
  }
14838
15236
  function subdivisionSteps(vertices) {
@@ -14847,7 +15245,7 @@ function subdivisionSteps(vertices) {
14847
15245
  }
14848
15246
  return Math.min(
14849
15247
  8,
14850
- Math.max(1, Math.ceil(import_three31.MathUtils.radToDeg(maxAngle) / MAX_SEGMENT_DEGREES))
15248
+ Math.max(1, Math.ceil(import_three32.MathUtils.radToDeg(maxAngle) / MAX_SEGMENT_DEGREES))
14851
15249
  );
14852
15250
  }
14853
15251
  function makeLinePositions(vertices, center) {
@@ -14902,16 +15300,16 @@ function PolylineHotspot({
14902
15300
  onInvalid,
14903
15301
  ...anchorProps
14904
15302
  }) {
14905
- const issues = (0, import_react52.useMemo)(() => validatePolylineVertices(vertices), [vertices]);
15303
+ const issues = (0, import_react54.useMemo)(() => validatePolylineVertices(vertices), [vertices]);
14906
15304
  const valid = issues.length === 0;
14907
- const center = (0, import_react52.useMemo)(() => valid ? polylineCenter(vertices) : null, [valid, vertices]);
14908
- const linePoints = (0, import_react52.useMemo)(
15305
+ const center = (0, import_react54.useMemo)(() => valid ? polylineCenter(vertices) : null, [valid, vertices]);
15306
+ const linePoints = (0, import_react54.useMemo)(
14909
15307
  () => valid && center ? makeLinePositions(vertices, center) : null,
14910
15308
  [center, valid, vertices]
14911
15309
  );
14912
15310
  const opacity = Math.max(0, Math.min(strokeOpacity, 1));
14913
- const startVerticesRef = (0, import_react52.useRef)(null);
14914
- (0, import_react52.useEffect)(() => {
15311
+ const startVerticesRef = (0, import_react54.useRef)(null);
15312
+ (0, import_react54.useEffect)(() => {
14915
15313
  if (!valid) onInvalid?.(issues);
14916
15314
  }, [issues, onInvalid, valid]);
14917
15315
  if (!valid || !center || !linePoints || linePoints.length < 2) return null;
@@ -14925,7 +15323,7 @@ function PolylineHotspot({
14925
15323
  startPosition: event.startPosition
14926
15324
  });
14927
15325
  };
14928
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
15326
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
14929
15327
  HotspotAnchor,
14930
15328
  {
14931
15329
  ...anchorProps,
@@ -14939,7 +15337,7 @@ function PolylineHotspot({
14939
15337
  renderOrder,
14940
15338
  draggable,
14941
15339
  useAngularScale: false,
14942
- focusContent: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
15340
+ focusContent: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
14943
15341
  HotspotStrokeLine,
14944
15342
  {
14945
15343
  color: "#75cbd3",
@@ -14960,7 +15358,7 @@ function PolylineHotspot({
14960
15358
  emitVerticesChange(event, onDragEnd);
14961
15359
  startVerticesRef.current = null;
14962
15360
  },
14963
- children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
15361
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
14964
15362
  HotspotStrokeLine,
14965
15363
  {
14966
15364
  color: stroke,
@@ -14977,9 +15375,9 @@ function PolylineHotspot({
14977
15375
  }
14978
15376
 
14979
15377
  // src/hotspot/graphic-hotspot.tsx
14980
- var import_react53 = require("react");
14981
- var import_three32 = require("three");
14982
- var import_jsx_runtime32 = require("react/jsx-runtime");
15378
+ var import_react55 = require("react");
15379
+ var import_three33 = require("three");
15380
+ var import_jsx_runtime33 = require("react/jsx-runtime");
14983
15381
  var GRAPHIC_TEXTURE_SIZE = 512;
14984
15382
  function resolveStrokeWidth(value) {
14985
15383
  return Number.isFinite(value) ? Math.max(value, 0) : 8;
@@ -15157,23 +15555,23 @@ function createGraphicTexture(graphic, aspectWidth, aspectHeight) {
15157
15555
  throw new Error("Canvas 2D is unavailable for this graphic hotspot.");
15158
15556
  }
15159
15557
  drawGraphic(context, graphic, aspectWidth, aspectHeight);
15160
- const texture = new import_three32.CanvasTexture(canvas);
15161
- texture.colorSpace = import_three32.SRGBColorSpace;
15162
- texture.wrapS = import_three32.ClampToEdgeWrapping;
15163
- texture.wrapT = import_three32.ClampToEdgeWrapping;
15164
- texture.magFilter = import_three32.LinearFilter;
15165
- texture.minFilter = import_three32.LinearMipmapLinearFilter;
15558
+ const texture = new import_three33.CanvasTexture(canvas);
15559
+ texture.colorSpace = import_three33.SRGBColorSpace;
15560
+ texture.wrapS = import_three33.ClampToEdgeWrapping;
15561
+ texture.wrapT = import_three33.ClampToEdgeWrapping;
15562
+ texture.magFilter = import_three33.LinearFilter;
15563
+ texture.minFilter = import_three33.LinearMipmapLinearFilter;
15166
15564
  texture.generateMipmaps = true;
15167
15565
  texture.needsUpdate = true;
15168
15566
  return texture;
15169
15567
  }
15170
15568
  function useGraphicTexture(graphic, aspectWidth, aspectHeight, onLoad, onError) {
15171
- const [texture, setTexture] = (0, import_react53.useState)(null);
15172
- const onLoadRef = (0, import_react53.useRef)(onLoad);
15173
- const onErrorRef = (0, import_react53.useRef)(onError);
15569
+ const [texture, setTexture] = (0, import_react55.useState)(null);
15570
+ const onLoadRef = (0, import_react55.useRef)(onLoad);
15571
+ const onErrorRef = (0, import_react55.useRef)(onError);
15174
15572
  onLoadRef.current = onLoad;
15175
15573
  onErrorRef.current = onError;
15176
- (0, import_react53.useEffect)(() => {
15574
+ (0, import_react55.useEffect)(() => {
15177
15575
  let nextTexture = null;
15178
15576
  try {
15179
15577
  nextTexture = createGraphicTexture(graphic, aspectWidth, aspectHeight);
@@ -15199,22 +15597,22 @@ function CanvasGraphicHotspot({
15199
15597
  ...anchorProps
15200
15598
  }) {
15201
15599
  const texture = useGraphicTexture(graphic, width, height, onLoad, onError);
15202
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(HotspotPlane, { map: texture, opacity }) });
15600
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(HotspotPlane, { map: texture, opacity }) });
15203
15601
  }
15204
15602
  function GraphicHotspot(props) {
15205
15603
  const { graphic, ...restProps } = props;
15206
15604
  if (graphic.kind === "svg") {
15207
15605
  const imageProps = restProps;
15208
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ImageHotspot, { ...imageProps, src: graphic.src });
15606
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ImageHotspot, { ...imageProps, src: graphic.src });
15209
15607
  }
15210
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(CanvasGraphicHotspot, { ...restProps, graphic });
15608
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CanvasGraphicHotspot, { ...restProps, graphic });
15211
15609
  }
15212
15610
 
15213
15611
  // src/hotspot/sequence-hotspot.tsx
15214
- var import_fiber27 = require("@react-three/fiber");
15215
- var import_react54 = require("react");
15216
- var import_three33 = require("three");
15217
- var import_jsx_runtime33 = require("react/jsx-runtime");
15612
+ var import_fiber28 = require("@react-three/fiber");
15613
+ var import_react56 = require("react");
15614
+ var import_three34 = require("three");
15615
+ var import_jsx_runtime34 = require("react/jsx-runtime");
15218
15616
  var DEFAULT_SEQUENCE_FPS = 12;
15219
15617
  function resolveFps(value) {
15220
15618
  return Number.isFinite(value) && value > 0 ? value : DEFAULT_SEQUENCE_FPS;
@@ -15228,13 +15626,13 @@ function useSpriteTexture({
15228
15626
  onError,
15229
15627
  onLoadProgress
15230
15628
  }) {
15231
- const gl = (0, import_fiber27.useThree)((state) => state.gl);
15232
- const [texture, setTexture] = (0, import_react54.useState)(null);
15233
- const onErrorRef = (0, import_react54.useRef)(onError);
15234
- const onLoadProgressRef = (0, import_react54.useRef)(onLoadProgress);
15629
+ const gl = (0, import_fiber28.useThree)((state) => state.gl);
15630
+ const [texture, setTexture] = (0, import_react56.useState)(null);
15631
+ const onErrorRef = (0, import_react56.useRef)(onError);
15632
+ const onLoadProgressRef = (0, import_react56.useRef)(onLoadProgress);
15235
15633
  onErrorRef.current = onError;
15236
15634
  onLoadProgressRef.current = onLoadProgress;
15237
- (0, import_react54.useEffect)(() => {
15635
+ (0, import_react56.useEffect)(() => {
15238
15636
  let active = true;
15239
15637
  setTexture(null);
15240
15638
  if (!src) {
@@ -15243,7 +15641,7 @@ function useSpriteTexture({
15243
15641
  active = false;
15244
15642
  };
15245
15643
  }
15246
- const loader = new import_three33.TextureLoader();
15644
+ const loader = new import_three34.TextureLoader();
15247
15645
  loader.load(
15248
15646
  src,
15249
15647
  (loadedTexture) => {
@@ -15251,11 +15649,11 @@ function useSpriteTexture({
15251
15649
  loadedTexture.dispose();
15252
15650
  return;
15253
15651
  }
15254
- loadedTexture.colorSpace = import_three33.SRGBColorSpace;
15255
- loadedTexture.wrapS = import_three33.ClampToEdgeWrapping;
15256
- loadedTexture.wrapT = import_three33.ClampToEdgeWrapping;
15257
- loadedTexture.magFilter = import_three33.LinearFilter;
15258
- loadedTexture.minFilter = import_three33.LinearMipmapLinearFilter;
15652
+ loadedTexture.colorSpace = import_three34.SRGBColorSpace;
15653
+ loadedTexture.wrapS = import_three34.ClampToEdgeWrapping;
15654
+ loadedTexture.wrapT = import_three34.ClampToEdgeWrapping;
15655
+ loadedTexture.magFilter = import_three34.LinearFilter;
15656
+ loadedTexture.minFilter = import_three34.LinearMipmapLinearFilter;
15259
15657
  loadedTexture.generateMipmaps = true;
15260
15658
  loadedTexture.anisotropy = gl.capabilities.getMaxAnisotropy();
15261
15659
  loadedTexture.needsUpdate = true;
@@ -15275,7 +15673,7 @@ function useSpriteTexture({
15275
15673
  active = false;
15276
15674
  };
15277
15675
  }, [gl, id, src]);
15278
- (0, import_react54.useEffect)(
15676
+ (0, import_react56.useEffect)(
15279
15677
  () => () => {
15280
15678
  texture?.dispose();
15281
15679
  },
@@ -15304,24 +15702,24 @@ function SequenceHotspot({
15304
15702
  const texture = useSpriteTexture({ id, src, onError, onLoadProgress });
15305
15703
  const frameCount = resolveFrameCount(requestedFrameCount);
15306
15704
  const safeFps = resolveFps(fps);
15307
- const [frameIndex, setFrameIndex] = (0, import_react54.useState)(0);
15308
- const elapsedRef = (0, import_react54.useRef)(0);
15309
- const frameIndexRef = (0, import_react54.useRef)(0);
15310
- const endedRef = (0, import_react54.useRef)(false);
15311
- const lastPlaybackStateRef = (0, import_react54.useRef)(null);
15312
- const onFrameChangeRef = (0, import_react54.useRef)(onFrameChange);
15313
- const onPlaybackStateChangeRef = (0, import_react54.useRef)(onPlaybackStateChange);
15314
- const onEndedRef = (0, import_react54.useRef)(onEnded);
15705
+ const [frameIndex, setFrameIndex] = (0, import_react56.useState)(0);
15706
+ const elapsedRef = (0, import_react56.useRef)(0);
15707
+ const frameIndexRef = (0, import_react56.useRef)(0);
15708
+ const endedRef = (0, import_react56.useRef)(false);
15709
+ const lastPlaybackStateRef = (0, import_react56.useRef)(null);
15710
+ const onFrameChangeRef = (0, import_react56.useRef)(onFrameChange);
15711
+ const onPlaybackStateChangeRef = (0, import_react56.useRef)(onPlaybackStateChange);
15712
+ const onEndedRef = (0, import_react56.useRef)(onEnded);
15315
15713
  onFrameChangeRef.current = onFrameChange;
15316
15714
  onPlaybackStateChangeRef.current = onPlaybackStateChange;
15317
15715
  onEndedRef.current = onEnded;
15318
- (0, import_react54.useEffect)(() => {
15716
+ (0, import_react56.useEffect)(() => {
15319
15717
  elapsedRef.current = 0;
15320
15718
  frameIndexRef.current = 0;
15321
15719
  endedRef.current = false;
15322
15720
  setFrameIndex(0);
15323
15721
  }, [frameCount, frameDirection, src]);
15324
- (0, import_react54.useEffect)(() => {
15722
+ (0, import_react56.useEffect)(() => {
15325
15723
  if (!texture) {
15326
15724
  return;
15327
15725
  }
@@ -15335,13 +15733,13 @@ function SequenceHotspot({
15335
15733
  );
15336
15734
  texture.needsUpdate = true;
15337
15735
  }, [frameCount, frameDirection, frameIndex, texture]);
15338
- (0, import_react54.useEffect)(() => {
15736
+ (0, import_react56.useEffect)(() => {
15339
15737
  if (!texture) {
15340
15738
  return;
15341
15739
  }
15342
15740
  onFrameChangeRef.current?.({ id, index: 0, src });
15343
15741
  }, [id, src, texture]);
15344
- (0, import_react54.useEffect)(() => {
15742
+ (0, import_react56.useEffect)(() => {
15345
15743
  if (!texture) {
15346
15744
  return;
15347
15745
  }
@@ -15360,7 +15758,7 @@ function SequenceHotspot({
15360
15758
  onPlaybackStateChangeRef.current?.(nextState);
15361
15759
  }
15362
15760
  }, [playing, texture]);
15363
- (0, import_fiber27.useFrame)((_, deltaSeconds) => {
15761
+ (0, import_fiber28.useFrame)((_, deltaSeconds) => {
15364
15762
  if (!texture || !playing || endedRef.current) {
15365
15763
  return;
15366
15764
  }
@@ -15390,14 +15788,14 @@ function SequenceHotspot({
15390
15788
  onFrameChangeRef.current?.({ id, index: nextIndex, src });
15391
15789
  }
15392
15790
  });
15393
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(HotspotAnchor, { ...anchorProps, id, height, width, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(HotspotPlane, { map: texture, opacity }) });
15791
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(HotspotAnchor, { ...anchorProps, id, height, width, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(HotspotPlane, { map: texture, opacity }) });
15394
15792
  }
15395
15793
 
15396
15794
  // src/hotspot/video-hotspot.tsx
15397
- var import_fiber28 = require("@react-three/fiber");
15398
- var import_react55 = require("react");
15399
- var import_three34 = require("three");
15400
- var import_jsx_runtime34 = require("react/jsx-runtime");
15795
+ var import_fiber29 = require("@react-three/fiber");
15796
+ var import_react57 = require("react");
15797
+ var import_three35 = require("three");
15798
+ var import_jsx_runtime35 = require("react/jsx-runtime");
15401
15799
  function clampVolume2(volume) {
15402
15800
  if (!Number.isFinite(volume)) {
15403
15801
  return 1;
@@ -15405,11 +15803,11 @@ function clampVolume2(volume) {
15405
15803
  return Math.max(0, Math.min(volume, 1));
15406
15804
  }
15407
15805
  function usePosterTexture2(id, poster, onError) {
15408
- const gl = (0, import_fiber28.useThree)((state) => state.gl);
15409
- const [texture, setTexture] = (0, import_react55.useState)(null);
15410
- const onErrorRef = (0, import_react55.useRef)(onError);
15806
+ const gl = (0, import_fiber29.useThree)((state) => state.gl);
15807
+ const [texture, setTexture] = (0, import_react57.useState)(null);
15808
+ const onErrorRef = (0, import_react57.useRef)(onError);
15411
15809
  onErrorRef.current = onError;
15412
- (0, import_react55.useEffect)(() => {
15810
+ (0, import_react57.useEffect)(() => {
15413
15811
  let active = true;
15414
15812
  setTexture(null);
15415
15813
  if (!poster) {
@@ -15417,7 +15815,7 @@ function usePosterTexture2(id, poster, onError) {
15417
15815
  active = false;
15418
15816
  };
15419
15817
  }
15420
- const loader = new import_three34.TextureLoader();
15818
+ const loader = new import_three35.TextureLoader();
15421
15819
  loader.load(
15422
15820
  poster,
15423
15821
  (loadedTexture) => {
@@ -15425,11 +15823,11 @@ function usePosterTexture2(id, poster, onError) {
15425
15823
  loadedTexture.dispose();
15426
15824
  return;
15427
15825
  }
15428
- loadedTexture.colorSpace = import_three34.SRGBColorSpace;
15429
- loadedTexture.wrapS = import_three34.ClampToEdgeWrapping;
15430
- loadedTexture.wrapT = import_three34.ClampToEdgeWrapping;
15431
- loadedTexture.magFilter = import_three34.LinearFilter;
15432
- loadedTexture.minFilter = import_three34.LinearMipmapLinearFilter;
15826
+ loadedTexture.colorSpace = import_three35.SRGBColorSpace;
15827
+ loadedTexture.wrapS = import_three35.ClampToEdgeWrapping;
15828
+ loadedTexture.wrapT = import_three35.ClampToEdgeWrapping;
15829
+ loadedTexture.magFilter = import_three35.LinearFilter;
15830
+ loadedTexture.minFilter = import_three35.LinearMipmapLinearFilter;
15433
15831
  loadedTexture.generateMipmaps = true;
15434
15832
  loadedTexture.anisotropy = gl.capabilities.getMaxAnisotropy();
15435
15833
  loadedTexture.needsUpdate = true;
@@ -15446,7 +15844,7 @@ function usePosterTexture2(id, poster, onError) {
15446
15844
  active = false;
15447
15845
  };
15448
15846
  }, [gl, id, poster]);
15449
- (0, import_react55.useEffect)(
15847
+ (0, import_react57.useEffect)(
15450
15848
  () => () => {
15451
15849
  texture?.dispose();
15452
15850
  },
@@ -15464,14 +15862,14 @@ function useVideoResource({
15464
15862
  poster,
15465
15863
  src
15466
15864
  }) {
15467
- const [resource, setResource] = (0, import_react55.useState)(null);
15468
- const onEndedRef = (0, import_react55.useRef)(onEnded);
15469
- const onErrorRef = (0, import_react55.useRef)(onError);
15470
- const onPlaybackStateChangeRef = (0, import_react55.useRef)(onPlaybackStateChange);
15865
+ const [resource, setResource] = (0, import_react57.useState)(null);
15866
+ const onEndedRef = (0, import_react57.useRef)(onEnded);
15867
+ const onErrorRef = (0, import_react57.useRef)(onError);
15868
+ const onPlaybackStateChangeRef = (0, import_react57.useRef)(onPlaybackStateChange);
15471
15869
  onEndedRef.current = onEnded;
15472
15870
  onErrorRef.current = onError;
15473
15871
  onPlaybackStateChangeRef.current = onPlaybackStateChange;
15474
- (0, import_react55.useEffect)(() => {
15872
+ (0, import_react57.useEffect)(() => {
15475
15873
  if (!src) {
15476
15874
  setResource(null);
15477
15875
  return;
@@ -15488,12 +15886,12 @@ function useVideoResource({
15488
15886
  video.setAttribute("webkit-playsinline", "true");
15489
15887
  }
15490
15888
  video.poster = poster ?? "";
15491
- const texture = new import_three34.VideoTexture(video);
15492
- texture.colorSpace = import_three34.SRGBColorSpace;
15493
- texture.wrapS = import_three34.ClampToEdgeWrapping;
15494
- texture.wrapT = import_three34.ClampToEdgeWrapping;
15495
- texture.magFilter = import_three34.LinearFilter;
15496
- texture.minFilter = import_three34.LinearFilter;
15889
+ const texture = new import_three35.VideoTexture(video);
15890
+ texture.colorSpace = import_three35.SRGBColorSpace;
15891
+ texture.wrapS = import_three35.ClampToEdgeWrapping;
15892
+ texture.wrapT = import_three35.ClampToEdgeWrapping;
15893
+ texture.magFilter = import_three35.LinearFilter;
15894
+ texture.minFilter = import_three35.LinearFilter;
15497
15895
  texture.generateMipmaps = false;
15498
15896
  const notifyState = (state) => {
15499
15897
  if (active) {
@@ -15578,11 +15976,11 @@ function VideoHotspot({
15578
15976
  src
15579
15977
  });
15580
15978
  const posterTexture = usePosterTexture2(id, poster, onError);
15581
- const onPlaybackErrorRef = (0, import_react55.useRef)(onPlaybackError);
15582
- const onPlaybackStateChangeRef = (0, import_react55.useRef)(onPlaybackStateChange);
15979
+ const onPlaybackErrorRef = (0, import_react57.useRef)(onPlaybackError);
15980
+ const onPlaybackStateChangeRef = (0, import_react57.useRef)(onPlaybackStateChange);
15583
15981
  onPlaybackErrorRef.current = onPlaybackError;
15584
15982
  onPlaybackStateChangeRef.current = onPlaybackStateChange;
15585
- (0, import_react55.useEffect)(() => {
15983
+ (0, import_react57.useEffect)(() => {
15586
15984
  if (!resource) {
15587
15985
  return;
15588
15986
  }
@@ -15599,7 +15997,7 @@ function VideoHotspot({
15599
15997
  }
15600
15998
  resource.video.preload = preload;
15601
15999
  }, [loop, muted, playsInline, preload, resource, volume]);
15602
- (0, import_react55.useEffect)(() => {
16000
+ (0, import_react57.useEffect)(() => {
15603
16001
  if (!resource) {
15604
16002
  return;
15605
16003
  }
@@ -15622,14 +16020,14 @@ function VideoHotspot({
15622
16020
  };
15623
16021
  }, [playing, resource]);
15624
16022
  const activeTexture = resource?.ready ? resource.texture : posterTexture;
15625
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(HotspotAnchor, { ...anchorProps, id, height, width, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(HotspotPlane, { map: activeTexture, opacity }) });
16023
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(HotspotAnchor, { ...anchorProps, id, height, width, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(HotspotPlane, { map: activeTexture, opacity }) });
15626
16024
  }
15627
16025
 
15628
16026
  // src/hotspot/audio-hotspot.tsx
15629
- var import_fiber29 = require("@react-three/fiber");
15630
- var import_react56 = require("react");
15631
- var import_three35 = require("three");
15632
- var import_jsx_runtime35 = require("react/jsx-runtime");
16027
+ var import_fiber30 = require("@react-three/fiber");
16028
+ var import_react58 = require("react");
16029
+ var import_three36 = require("three");
16030
+ var import_jsx_runtime36 = require("react/jsx-runtime");
15633
16031
  var SPEAKER_TEXTURE_SIZE = 512;
15634
16032
  function paintSpeakerBody(context, center) {
15635
16033
  context.fillStyle = "#f5fbfc";
@@ -15682,19 +16080,19 @@ function createSpeakerTexture(state) {
15682
16080
  return exhaustive;
15683
16081
  }
15684
16082
  }
15685
- const texture = new import_three35.CanvasTexture(canvas);
15686
- texture.colorSpace = import_three35.SRGBColorSpace;
15687
- texture.wrapS = import_three35.ClampToEdgeWrapping;
15688
- texture.wrapT = import_three35.ClampToEdgeWrapping;
15689
- texture.magFilter = import_three35.LinearFilter;
15690
- texture.minFilter = import_three35.LinearMipmapLinearFilter;
16083
+ const texture = new import_three36.CanvasTexture(canvas);
16084
+ texture.colorSpace = import_three36.SRGBColorSpace;
16085
+ texture.wrapS = import_three36.ClampToEdgeWrapping;
16086
+ texture.wrapT = import_three36.ClampToEdgeWrapping;
16087
+ texture.magFilter = import_three36.LinearFilter;
16088
+ texture.minFilter = import_three36.LinearMipmapLinearFilter;
15691
16089
  texture.generateMipmaps = true;
15692
16090
  texture.needsUpdate = true;
15693
16091
  return texture;
15694
16092
  }
15695
16093
  function useSpeakerTextures(enabled) {
15696
- const [textures, setTextures] = (0, import_react56.useState)({ playing: null, stopped: null });
15697
- (0, import_react56.useEffect)(() => {
16094
+ const [textures, setTextures] = (0, import_react58.useState)({ playing: null, stopped: null });
16095
+ (0, import_react58.useEffect)(() => {
15698
16096
  if (!enabled) {
15699
16097
  setTextures({ playing: null, stopped: null });
15700
16098
  return;
@@ -15710,11 +16108,11 @@ function useSpeakerTextures(enabled) {
15710
16108
  return textures;
15711
16109
  }
15712
16110
  function useIconTexture(icon, enabled, onError, id) {
15713
- const gl = (0, import_fiber29.useThree)((state) => state.gl);
15714
- const [texture, setTexture] = (0, import_react56.useState)(null);
15715
- const onErrorRef = (0, import_react56.useRef)(onError);
16111
+ const gl = (0, import_fiber30.useThree)((state) => state.gl);
16112
+ const [texture, setTexture] = (0, import_react58.useState)(null);
16113
+ const onErrorRef = (0, import_react58.useRef)(onError);
15716
16114
  onErrorRef.current = onError;
15717
- (0, import_react56.useEffect)(() => {
16115
+ (0, import_react58.useEffect)(() => {
15718
16116
  let active = true;
15719
16117
  setTexture(null);
15720
16118
  if (!enabled || !icon) {
@@ -15722,7 +16120,7 @@ function useIconTexture(icon, enabled, onError, id) {
15722
16120
  active = false;
15723
16121
  };
15724
16122
  }
15725
- const loader = new import_three35.TextureLoader();
16123
+ const loader = new import_three36.TextureLoader();
15726
16124
  loader.load(
15727
16125
  icon,
15728
16126
  (loadedTexture) => {
@@ -15730,11 +16128,11 @@ function useIconTexture(icon, enabled, onError, id) {
15730
16128
  loadedTexture.dispose();
15731
16129
  return;
15732
16130
  }
15733
- loadedTexture.colorSpace = import_three35.SRGBColorSpace;
15734
- loadedTexture.wrapS = import_three35.ClampToEdgeWrapping;
15735
- loadedTexture.wrapT = import_three35.ClampToEdgeWrapping;
15736
- loadedTexture.magFilter = import_three35.LinearFilter;
15737
- loadedTexture.minFilter = import_three35.LinearMipmapLinearFilter;
16131
+ loadedTexture.colorSpace = import_three36.SRGBColorSpace;
16132
+ loadedTexture.wrapS = import_three36.ClampToEdgeWrapping;
16133
+ loadedTexture.wrapT = import_three36.ClampToEdgeWrapping;
16134
+ loadedTexture.magFilter = import_three36.LinearFilter;
16135
+ loadedTexture.minFilter = import_three36.LinearMipmapLinearFilter;
15738
16136
  loadedTexture.generateMipmaps = true;
15739
16137
  loadedTexture.anisotropy = gl.capabilities.getMaxAnisotropy();
15740
16138
  loadedTexture.needsUpdate = true;
@@ -15751,7 +16149,7 @@ function useIconTexture(icon, enabled, onError, id) {
15751
16149
  active = false;
15752
16150
  };
15753
16151
  }, [enabled, gl, icon, id]);
15754
- (0, import_react56.useEffect)(
16152
+ (0, import_react58.useEffect)(
15755
16153
  () => () => {
15756
16154
  texture?.dispose();
15757
16155
  },
@@ -15770,13 +16168,13 @@ function useAudioHowl({
15770
16168
  playing,
15771
16169
  src
15772
16170
  }) {
15773
- const [howl, setHowl] = (0, import_react56.useState)(null);
15774
- const playingRef = (0, import_react56.useRef)(playing);
15775
- const loopRef = (0, import_react56.useRef)(loop ?? false);
15776
- const onEndedRef = (0, import_react56.useRef)(onEnded);
15777
- const onErrorRef = (0, import_react56.useRef)(onError);
15778
- const onPlaybackErrorRef = (0, import_react56.useRef)(onPlaybackError);
15779
- const onPlaybackStateChangeRef = (0, import_react56.useRef)(onPlaybackStateChange);
16171
+ const [howl, setHowl] = (0, import_react58.useState)(null);
16172
+ const playingRef = (0, import_react58.useRef)(playing);
16173
+ const loopRef = (0, import_react58.useRef)(loop ?? false);
16174
+ const onEndedRef = (0, import_react58.useRef)(onEnded);
16175
+ const onErrorRef = (0, import_react58.useRef)(onError);
16176
+ const onPlaybackErrorRef = (0, import_react58.useRef)(onPlaybackError);
16177
+ const onPlaybackStateChangeRef = (0, import_react58.useRef)(onPlaybackStateChange);
15780
16178
  playingRef.current = playing;
15781
16179
  loopRef.current = loop ?? false;
15782
16180
  onEndedRef.current = onEnded;
@@ -15784,7 +16182,7 @@ function useAudioHowl({
15784
16182
  onPlaybackErrorRef.current = onPlaybackError;
15785
16183
  onPlaybackStateChangeRef.current = onPlaybackStateChange;
15786
16184
  const sourcesKey = sourceList(src).join("\0");
15787
- (0, import_react56.useEffect)(() => {
16185
+ (0, import_react58.useEffect)(() => {
15788
16186
  const sources = sourcesKey.length > 0 ? sourcesKey.split("\0") : [];
15789
16187
  if (sources.length === 0) {
15790
16188
  setHowl(null);
@@ -15821,7 +16219,7 @@ function useAudioHowl({
15821
16219
  handle.dispose();
15822
16220
  };
15823
16221
  }, [crossOrigin, id, sourcesKey]);
15824
- (0, import_react56.useEffect)(() => {
16222
+ (0, import_react58.useEffect)(() => {
15825
16223
  howl?.loop(loop ?? false);
15826
16224
  }, [howl, loop]);
15827
16225
  return howl;
@@ -15849,7 +16247,7 @@ function AudioHotspot({
15849
16247
  ...anchorProps
15850
16248
  }) {
15851
16249
  usePanoMediaActivationIntent(playing);
15852
- const camera = (0, import_fiber29.useThree)((state) => state.camera);
16250
+ const camera = (0, import_fiber30.useThree)((state) => state.camera);
15853
16251
  const howl = useAudioHowl({
15854
16252
  crossOrigin,
15855
16253
  id,
@@ -15865,15 +16263,15 @@ function AudioHotspot({
15865
16263
  const stoppedIconTexture = useIconTexture(icon, marker, onError, id);
15866
16264
  const playingIconTexture = useIconTexture(playingIcon, marker, onError, id);
15867
16265
  const markerTexture = playing ? playingIconTexture ?? stoppedIconTexture ?? speakerTextures.playing : stoppedIconTexture ?? speakerTextures.stopped;
15868
- const playingRef = (0, import_react56.useRef)(playing);
16266
+ const playingRef = (0, import_react58.useRef)(playing);
15869
16267
  playingRef.current = playing;
15870
- const mutedRef = (0, import_react56.useRef)(muted);
15871
- const volumeRef = (0, import_react56.useRef)(volume);
15872
- const rangeRef = (0, import_react56.useRef)(range);
16268
+ const mutedRef = (0, import_react58.useRef)(muted);
16269
+ const volumeRef = (0, import_react58.useRef)(volume);
16270
+ const rangeRef = (0, import_react58.useRef)(range);
15873
16271
  mutedRef.current = muted;
15874
16272
  volumeRef.current = volume;
15875
16273
  rangeRef.current = range;
15876
- (0, import_react56.useEffect)(() => {
16274
+ (0, import_react58.useEffect)(() => {
15877
16275
  if (!howl) {
15878
16276
  return;
15879
16277
  }
@@ -15883,7 +16281,7 @@ function AudioHotspot({
15883
16281
  }
15884
16282
  howl.play();
15885
16283
  }, [howl, playing]);
15886
- (0, import_react56.useEffect)(() => {
16284
+ (0, import_react58.useEffect)(() => {
15887
16285
  if (!howl || !pauseWhenHidden) {
15888
16286
  return;
15889
16287
  }
@@ -15901,7 +16299,7 @@ function AudioHotspot({
15901
16299
  document.removeEventListener("visibilitychange", handleVisibility);
15902
16300
  };
15903
16301
  }, [howl, pauseWhenHidden]);
15904
- (0, import_fiber29.useFrame)(() => {
16302
+ (0, import_fiber30.useFrame)(() => {
15905
16303
  if (!howl) {
15906
16304
  return;
15907
16305
  }
@@ -15914,13 +16312,13 @@ function AudioHotspot({
15914
16312
  howl.mute(mutedRef.current);
15915
16313
  howl.volume(clampAudioVolume(volumeRef.current) * spatial.gain);
15916
16314
  });
15917
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(HotspotAnchor, { ...anchorProps, id, height, width, children: marker ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(HotspotPlane, { map: markerTexture, opacity }) : null });
16315
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(HotspotAnchor, { ...anchorProps, id, height, width, children: marker ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(HotspotPlane, { map: markerTexture, opacity }) : null });
15918
16316
  }
15919
16317
 
15920
16318
  // src/hotspot/text-hotspot.tsx
15921
- var import_react57 = require("react");
15922
- var import_three36 = require("three");
15923
- var import_jsx_runtime36 = require("react/jsx-runtime");
16319
+ var import_react59 = require("react");
16320
+ var import_three37 = require("three");
16321
+ var import_jsx_runtime37 = require("react/jsx-runtime");
15924
16322
  var TEXT_TEXTURE_LONG_SIDE = 1024;
15925
16323
  var DEFAULT_FONT_FAMILY = "system-ui, sans-serif";
15926
16324
  var DEFAULT_FONT_SIZE = 96;
@@ -16129,23 +16527,23 @@ function createTextTexture(text, width, height, style) {
16129
16527
  throw new Error("Canvas 2D is unavailable for this text hotspot.");
16130
16528
  }
16131
16529
  drawTextHotspot(context, canvasWidth, canvasHeight, text, style);
16132
- const texture = new import_three36.CanvasTexture(canvas);
16133
- texture.colorSpace = import_three36.SRGBColorSpace;
16134
- texture.wrapS = import_three36.ClampToEdgeWrapping;
16135
- texture.wrapT = import_three36.ClampToEdgeWrapping;
16136
- texture.magFilter = import_three36.LinearFilter;
16137
- texture.minFilter = import_three36.LinearMipmapLinearFilter;
16530
+ const texture = new import_three37.CanvasTexture(canvas);
16531
+ texture.colorSpace = import_three37.SRGBColorSpace;
16532
+ texture.wrapS = import_three37.ClampToEdgeWrapping;
16533
+ texture.wrapT = import_three37.ClampToEdgeWrapping;
16534
+ texture.magFilter = import_three37.LinearFilter;
16535
+ texture.minFilter = import_three37.LinearMipmapLinearFilter;
16138
16536
  texture.generateMipmaps = true;
16139
16537
  texture.needsUpdate = true;
16140
16538
  return texture;
16141
16539
  }
16142
16540
  function useTextTexture(text, width, height, style, onLoad, onError) {
16143
- const [texture, setTexture] = (0, import_react57.useState)(null);
16144
- const onLoadRef = (0, import_react57.useRef)(onLoad);
16145
- const onErrorRef = (0, import_react57.useRef)(onError);
16541
+ const [texture, setTexture] = (0, import_react59.useState)(null);
16542
+ const onLoadRef = (0, import_react59.useRef)(onLoad);
16543
+ const onErrorRef = (0, import_react59.useRef)(onError);
16146
16544
  onLoadRef.current = onLoad;
16147
16545
  onErrorRef.current = onError;
16148
- (0, import_react57.useEffect)(() => {
16546
+ (0, import_react59.useEffect)(() => {
16149
16547
  let cancelled = false;
16150
16548
  let nextTexture = null;
16151
16549
  const run = async () => {
@@ -16238,13 +16636,13 @@ function TextHotspot({
16238
16636
  whiteSpace
16239
16637
  };
16240
16638
  const texture = useTextTexture(text, width, height, style, onLoad, onError);
16241
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(HotspotPlane, { map: texture, opacity }) });
16639
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(HotspotPlane, { map: texture, opacity }) });
16242
16640
  }
16243
16641
 
16244
16642
  // src/hotspot/iframe-hotspot.tsx
16245
16643
  var import_drei2 = require("@react-three/drei");
16246
- var import_three37 = require("three");
16247
- var import_jsx_runtime37 = require("react/jsx-runtime");
16644
+ var import_three38 = require("three");
16645
+ var import_jsx_runtime38 = require("react/jsx-runtime");
16248
16646
  var IFRAME_LONG_SIDE = 800;
16249
16647
  var CSS3D_DISTANCE_FACTOR = 400;
16250
16648
  var DEFAULT_SANDBOX = "allow-scripts allow-popups allow-forms";
@@ -16301,7 +16699,7 @@ function IframeHotspot({
16301
16699
  interactive,
16302
16700
  pointerEvents
16303
16701
  );
16304
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
16702
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
16305
16703
  HotspotAnchor,
16306
16704
  {
16307
16705
  ...anchorProps,
@@ -16310,20 +16708,20 @@ function IframeHotspot({
16310
16708
  pointerEvents,
16311
16709
  width,
16312
16710
  children: [
16313
- /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("mesh", { children: [
16314
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("planeGeometry", { args: [1, 1] }),
16315
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
16711
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("mesh", { children: [
16712
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("planeGeometry", { args: [1, 1] }),
16713
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
16316
16714
  "meshBasicMaterial",
16317
16715
  {
16318
16716
  depthWrite: false,
16319
16717
  opacity: 0,
16320
- side: import_three37.DoubleSide,
16718
+ side: import_three38.DoubleSide,
16321
16719
  toneMapped: false,
16322
16720
  transparent: true
16323
16721
  }
16324
16722
  )
16325
16723
  ] }),
16326
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
16724
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
16327
16725
  import_drei2.Html,
16328
16726
  {
16329
16727
  distanceFactor: CSS3D_DISTANCE_FACTOR,
@@ -16338,7 +16736,7 @@ function IframeHotspot({
16338
16736
  },
16339
16737
  transform: true,
16340
16738
  zIndexRange: [10, 0],
16341
- children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
16739
+ children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
16342
16740
  "iframe",
16343
16741
  {
16344
16742
  allow,