@ericchen1990/pano-view 2.5.1 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -2244,12 +2244,13 @@ import { createXRStore, XR } from "@react-three/xr";
2244
2244
  import {
2245
2245
  forwardRef as forwardRef2,
2246
2246
  useCallback as useCallback6,
2247
- useContext as useContext14,
2248
- useEffect as useEffect12,
2247
+ useContext as useContext15,
2248
+ useEffect as useEffect13,
2249
2249
  useImperativeHandle as useImperativeHandle2,
2250
2250
  useMemo as useMemo7,
2251
- useRef as useRef12,
2252
- useState as useState5
2251
+ useRef as useRef13,
2252
+ useState as useState5,
2253
+ useSyncExternalStore as useSyncExternalStore6
2253
2254
  } from "react";
2254
2255
 
2255
2256
  // src/background-audio-host.ts
@@ -2294,6 +2295,107 @@ function cn(...values) {
2294
2295
  return values.filter(Boolean).join(" ");
2295
2296
  }
2296
2297
 
2298
+ // src/audio/howl.ts
2299
+ var import_howler = __toESM(require_howler());
2300
+ import_howler.Howler.autoUnlock = true;
2301
+ function resumePanoAudio() {
2302
+ if (!import_howler.Howler.ctx || import_howler.Howler.ctx.state === "running") {
2303
+ return Promise.resolve();
2304
+ }
2305
+ return import_howler.Howler.ctx.resume();
2306
+ }
2307
+ function sourceList(src) {
2308
+ if (src == null) {
2309
+ return [];
2310
+ }
2311
+ if (typeof src === "string") {
2312
+ return src ? [src] : [];
2313
+ }
2314
+ return src.filter((item) => Boolean(item));
2315
+ }
2316
+ function createUnlockingHowl({
2317
+ src,
2318
+ loop,
2319
+ crossOrigin,
2320
+ isActive,
2321
+ shouldRetryPlay,
2322
+ onEnded,
2323
+ onPlay,
2324
+ onPause,
2325
+ onLoadError,
2326
+ onPlayError
2327
+ }) {
2328
+ let disposed = false;
2329
+ let blockedNotified = false;
2330
+ const unlockListeners = [];
2331
+ const removeUnlockListeners = () => {
2332
+ for (const { type, listener } of unlockListeners) {
2333
+ window.removeEventListener(type, listener, true);
2334
+ }
2335
+ unlockListeners.length = 0;
2336
+ };
2337
+ const instance = new import_howler.Howl({
2338
+ src: [...src],
2339
+ html5: false,
2340
+ preload: true,
2341
+ loop,
2342
+ xhr: crossOrigin === "use-credentials" ? { withCredentials: true } : void 0,
2343
+ onend: () => {
2344
+ if (disposed || !isActive() || instance.loop()) {
2345
+ return;
2346
+ }
2347
+ onEnded?.();
2348
+ },
2349
+ onplay: () => {
2350
+ if (!disposed && isActive()) {
2351
+ onPlay?.();
2352
+ }
2353
+ },
2354
+ onpause: () => {
2355
+ if (!disposed && isActive()) {
2356
+ onPause?.();
2357
+ }
2358
+ },
2359
+ onloaderror: (_soundId, error) => {
2360
+ if (!disposed && isActive()) {
2361
+ onLoadError?.(error);
2362
+ }
2363
+ },
2364
+ onplayerror: (_soundId, error) => {
2365
+ if (disposed || !isActive()) {
2366
+ return;
2367
+ }
2368
+ if (!blockedNotified) {
2369
+ blockedNotified = true;
2370
+ onPlayError?.(error);
2371
+ }
2372
+ const retry = () => {
2373
+ removeUnlockListeners();
2374
+ if (!disposed && isActive() && shouldRetryPlay()) {
2375
+ void resumePanoAudio();
2376
+ instance.play();
2377
+ }
2378
+ };
2379
+ removeUnlockListeners();
2380
+ unlockListeners.push({ type: "pointerdown", listener: retry });
2381
+ unlockListeners.push({ type: "keydown", listener: retry });
2382
+ window.addEventListener("pointerdown", retry, { capture: true });
2383
+ window.addEventListener("keydown", retry, { capture: true });
2384
+ }
2385
+ });
2386
+ return {
2387
+ howl: instance,
2388
+ dispose: () => {
2389
+ if (disposed) {
2390
+ return;
2391
+ }
2392
+ disposed = true;
2393
+ removeUnlockListeners();
2394
+ instance.unload();
2395
+ }
2396
+ };
2397
+ }
2398
+
2297
2399
  // src/auto-rotate.tsx
2298
2400
  import { useFrame as useFrame2 } from "@react-three/fiber";
2299
2401
  import { useContext, useEffect as useEffect2, useRef as useRef2 } from "react";
@@ -2350,6 +2452,7 @@ var DEFAULT_ROTATE_DAMPING = 14;
2350
2452
  var DEFAULT_ZOOM_DAMPING = 16;
2351
2453
  var DEFAULT_FRICTION_STOP = 0.01;
2352
2454
  var VIEW_SETTLE_EPSILON = 1e-3;
2455
+ var DEFAULT_NAVIGATION_DURATION = 700;
2353
2456
  var PanoramaViewContext = createContext3(null);
2354
2457
  function clamp(value, min, max) {
2355
2458
  return Math.max(min, Math.min(max, value));
@@ -2369,6 +2472,15 @@ function resolveDamping(value, fallback) {
2369
2472
  function resolveFrictionStop(value) {
2370
2473
  return Number.isFinite(value) && value >= 0 ? value : DEFAULT_FRICTION_STOP;
2371
2474
  }
2475
+ function resolveNavigationDuration(value) {
2476
+ return Number.isFinite(value) && value >= 0 ? value : DEFAULT_NAVIGATION_DURATION;
2477
+ }
2478
+ function applyNavigationEasing(progress, easing) {
2479
+ if (easing === "linear") {
2480
+ return progress;
2481
+ }
2482
+ return progress < 0.5 ? 4 * progress * progress * progress : 1 - Math.pow(-2 * progress + 2, 3) / 2;
2483
+ }
2372
2484
  function viewsEqual(a, b) {
2373
2485
  return a.yaw === b.yaw && a.pitch === b.pitch && a.fov === b.fov;
2374
2486
  }
@@ -2402,13 +2514,14 @@ var PanoramaViewRuntime = forwardRef(function PanoramaViewRuntime2({ initialView
2402
2514
  const xrEulerRef = useRef(new Euler(0, 0, 0, "YXZ"));
2403
2515
  const minFovRef = useRef(minFov);
2404
2516
  const maxFovRef = useRef(maxFov);
2517
+ const activeNavigationRef = useRef(null);
2405
2518
  optionsRef.current = options;
2406
2519
  eventBusRef.current = eventBus;
2407
2520
  xrSessionRef.current = xrSession;
2408
2521
  minFovRef.current = minFov;
2409
2522
  maxFovRef.current = maxFov;
2410
2523
  const hasInertia = () => yawVelocityRef.current !== 0 || pitchVelocityRef.current !== 0 || zoomVelocityRef.current !== 0;
2411
- const isUserInteracting = () => mouseActiveRef.current || touchActiveRef.current || keyboardActiveRef.current || gyroActiveRef.current || interactionLockCountRef.current > 0 || xrSessionRef.current != null || hasInertia();
2524
+ const isUserInteracting = () => mouseActiveRef.current || touchActiveRef.current || keyboardActiveRef.current || gyroActiveRef.current || interactionLockCountRef.current > 0 || xrSessionRef.current != null || activeNavigationRef.current != null || hasInertia();
2412
2525
  const syncInteracting = () => {
2413
2526
  interactingRef.current = mouseActiveRef.current || touchActiveRef.current;
2414
2527
  };
@@ -2450,6 +2563,14 @@ var PanoramaViewRuntime = forwardRef(function PanoramaViewRuntime2({ initialView
2450
2563
  zoomVelocityRef.current = 0;
2451
2564
  lastVelocitySampleAtRef.current = null;
2452
2565
  };
2566
+ const cancelNavigation = () => {
2567
+ const navigation = activeNavigationRef.current;
2568
+ if (!navigation) {
2569
+ return;
2570
+ }
2571
+ activeNavigationRef.current = null;
2572
+ navigation.resolve({ status: "cancelled" });
2573
+ };
2453
2574
  const markDirty = () => {
2454
2575
  dirtyRef.current = true;
2455
2576
  settledRef.current = false;
@@ -2462,6 +2583,7 @@ var PanoramaViewRuntime = forwardRef(function PanoramaViewRuntime2({ initialView
2462
2583
  }
2463
2584
  };
2464
2585
  const acquireInteractionLock = () => {
2586
+ cancelNavigation();
2465
2587
  interactionLockCountRef.current += 1;
2466
2588
  stopVelocity();
2467
2589
  if (mouseActiveRef.current) {
@@ -2486,6 +2608,7 @@ var PanoramaViewRuntime = forwardRef(function PanoramaViewRuntime2({ initialView
2486
2608
  };
2487
2609
  };
2488
2610
  const setView = (view, setOptions) => {
2611
+ cancelNavigation();
2489
2612
  const nextView = hardConstrainView(view);
2490
2613
  if (gyroActiveRef.current) {
2491
2614
  gyroOffsetRef.current = {
@@ -2500,7 +2623,66 @@ var PanoramaViewRuntime = forwardRef(function PanoramaViewRuntime2({ initialView
2500
2623
  }
2501
2624
  markDirty();
2502
2625
  };
2626
+ const startNavigation = (targetInput, options2) => {
2627
+ cancelNavigation();
2628
+ if (xrSessionRef.current != null || gyroActiveRef.current || interactionLockCountRef.current > 0) {
2629
+ return Promise.resolve({ status: "cancelled" });
2630
+ }
2631
+ const from = { ...viewRef.current };
2632
+ const safeTargetInput = {
2633
+ yaw: targetInput.yaw !== void 0 && Number.isFinite(targetInput.yaw) ? targetInput.yaw : from.yaw,
2634
+ pitch: targetInput.pitch !== void 0 && Number.isFinite(targetInput.pitch) ? targetInput.pitch : from.pitch,
2635
+ fov: targetInput.fov !== void 0 && Number.isFinite(targetInput.fov) ? targetInput.fov : from.fov
2636
+ };
2637
+ const target = hardConstrainView(safeTargetInput, from);
2638
+ const duration = resolveNavigationDuration(options2?.duration);
2639
+ const rawYawDelta = targetInput.yaw !== void 0 && Number.isFinite(targetInput.yaw) ? safeTargetInput.yaw - from.yaw : 0;
2640
+ const yawDelta = options2?.shortestPath === false ? rawYawDelta : shortestYawDelta(from.yaw, target.yaw);
2641
+ stopVelocity();
2642
+ targetViewRef.current = target;
2643
+ markDirty();
2644
+ if (duration === 0) {
2645
+ viewRef.current = target;
2646
+ return Promise.resolve({ status: "completed" });
2647
+ }
2648
+ return new Promise((resolve) => {
2649
+ activeNavigationRef.current = {
2650
+ from,
2651
+ target,
2652
+ yawDelta,
2653
+ startedAt: performance.now(),
2654
+ duration,
2655
+ easing: options2?.easing,
2656
+ resolve
2657
+ };
2658
+ });
2659
+ };
2660
+ const lookTo = (position, options2) => startNavigation(
2661
+ {
2662
+ yaw: position.yaw,
2663
+ pitch: position.pitch,
2664
+ fov: options2?.fov ?? viewRef.current.fov
2665
+ },
2666
+ options2
2667
+ );
2668
+ const moveTo = (position, options2) => startNavigation(
2669
+ {
2670
+ yaw: position.yaw,
2671
+ pitch: position.pitch,
2672
+ fov: viewRef.current.fov
2673
+ },
2674
+ options2
2675
+ );
2676
+ const zoomTo = (fov, options2) => startNavigation(
2677
+ {
2678
+ yaw: viewRef.current.yaw,
2679
+ pitch: viewRef.current.pitch,
2680
+ fov
2681
+ },
2682
+ options2
2683
+ );
2503
2684
  const applyViewDelta = (delta, applyOptions) => {
2685
+ cancelNavigation();
2504
2686
  if (interactionLockCountRef.current > 0 || xrSessionRef.current != null) {
2505
2687
  return false;
2506
2688
  }
@@ -2551,10 +2733,16 @@ var PanoramaViewRuntime = forwardRef(function PanoramaViewRuntime2({ initialView
2551
2733
  getTargetView: () => ({ ...targetViewRef.current }),
2552
2734
  setView,
2553
2735
  reset: () => setView(initialViewRef.current),
2736
+ lookTo,
2737
+ moveTo,
2738
+ zoomTo,
2554
2739
  applyViewDelta,
2555
2740
  setKeyboardActive: (active) => {
2556
2741
  const wasActive = keyboardActiveRef.current;
2557
2742
  keyboardActiveRef.current = active;
2743
+ if (active) {
2744
+ cancelNavigation();
2745
+ }
2558
2746
  if (active && !wasActive) {
2559
2747
  eventBusRef.current.emit("viewinteractionstart", {
2560
2748
  source: "keyboard"
@@ -2572,6 +2760,9 @@ var PanoramaViewRuntime = forwardRef(function PanoramaViewRuntime2({ initialView
2572
2760
  } else {
2573
2761
  touchActiveRef.current = active;
2574
2762
  }
2763
+ if (active) {
2764
+ cancelNavigation();
2765
+ }
2575
2766
  syncInteracting();
2576
2767
  if (active && !wasActive) {
2577
2768
  eventBusRef.current.emit("viewinteractionstart", { source });
@@ -2588,6 +2779,9 @@ var PanoramaViewRuntime = forwardRef(function PanoramaViewRuntime2({ initialView
2588
2779
  isInteractionLocked: () => interactionLockCountRef.current > 0,
2589
2780
  isUserInteracting,
2590
2781
  setGyroActive: (active) => {
2782
+ if (active) {
2783
+ cancelNavigation();
2784
+ }
2591
2785
  gyroActiveRef.current = active;
2592
2786
  gyroOffsetRef.current = { yaw: 0, pitch: 0 };
2593
2787
  stopVelocity();
@@ -2624,7 +2818,7 @@ var PanoramaViewRuntime = forwardRef(function PanoramaViewRuntime2({ initialView
2624
2818
  acquireInteractionLock,
2625
2819
  applyAutoRotation: (yawDelta) => {
2626
2820
  const inertiaFinished = yawVelocityRef.current === 0 && pitchVelocityRef.current === 0 && zoomVelocityRef.current === 0;
2627
- if (!Number.isFinite(yawDelta) || xrSessionRef.current != null || gyroActiveRef.current || interactionLockCountRef.current > 0 || interactingRef.current || keyboardActiveRef.current || !inertiaFinished) {
2821
+ if (!Number.isFinite(yawDelta) || xrSessionRef.current != null || activeNavigationRef.current != null || gyroActiveRef.current || interactionLockCountRef.current > 0 || interactingRef.current || keyboardActiveRef.current || !inertiaFinished) {
2628
2822
  return false;
2629
2823
  }
2630
2824
  targetViewRef.current.yaw += yawDelta;
@@ -2634,6 +2828,12 @@ var PanoramaViewRuntime = forwardRef(function PanoramaViewRuntime2({ initialView
2634
2828
  }),
2635
2829
  []
2636
2830
  );
2831
+ useEffect(
2832
+ () => () => {
2833
+ cancelNavigation();
2834
+ },
2835
+ []
2836
+ );
2637
2837
  useEffect(() => {
2638
2838
  initialViewRef.current = { ...initialView };
2639
2839
  setView(initialView);
@@ -2643,6 +2843,7 @@ var PanoramaViewRuntime = forwardRef(function PanoramaViewRuntime2({ initialView
2643
2843
  return;
2644
2844
  }
2645
2845
  if (xrSessionRef.current && gl.xr.isPresenting) {
2846
+ cancelNavigation();
2646
2847
  const xrCamera = gl.xr.getCamera();
2647
2848
  xrEulerRef.current.setFromQuaternion(xrCamera.quaternion, "YXZ");
2648
2849
  const nextView2 = {
@@ -2663,6 +2864,48 @@ var PanoramaViewRuntime = forwardRef(function PanoramaViewRuntime2({ initialView
2663
2864
  }
2664
2865
  return;
2665
2866
  }
2867
+ const navigation = activeNavigationRef.current;
2868
+ if (navigation) {
2869
+ const progress = Math.min(
2870
+ 1,
2871
+ Math.max(0, (performance.now() - navigation.startedAt) / navigation.duration)
2872
+ );
2873
+ const easedProgress = applyNavigationEasing(progress, navigation.easing);
2874
+ const nextView2 = {
2875
+ yaw: normalizeYaw(navigation.from.yaw + navigation.yawDelta * easedProgress),
2876
+ pitch: navigation.from.pitch + (navigation.target.pitch - navigation.from.pitch) * easedProgress,
2877
+ fov: navigation.from.fov + (navigation.target.fov - navigation.from.fov) * easedProgress
2878
+ };
2879
+ const completed = progress === 1;
2880
+ viewRef.current = completed ? { ...navigation.target } : nextView2;
2881
+ eulerRef.current.set(
2882
+ MathUtils.degToRad(viewRef.current.pitch),
2883
+ MathUtils.degToRad(-viewRef.current.yaw),
2884
+ MathUtils.degToRad(cameraRollRef.current),
2885
+ "YXZ"
2886
+ );
2887
+ camera.quaternion.setFromEuler(eulerRef.current);
2888
+ camera.fov = viewRef.current.fov;
2889
+ camera.updateProjectionMatrix();
2890
+ camera.updateMatrixWorld();
2891
+ const emittedView = { ...viewRef.current };
2892
+ const lastEmitted2 = lastEmittedViewRef.current;
2893
+ if (!lastEmitted2 || !viewsEqual(lastEmitted2, emittedView)) {
2894
+ lastEmittedViewRef.current = emittedView;
2895
+ eventBusRef.current.emit("viewchange", emittedView);
2896
+ }
2897
+ if (completed) {
2898
+ activeNavigationRef.current = null;
2899
+ settledRef.current = true;
2900
+ eventBusRef.current.emit("viewsettled", emittedView);
2901
+ navigation.resolve({ status: "completed" });
2902
+ dirtyRef.current = false;
2903
+ } else {
2904
+ settledRef.current = false;
2905
+ dirtyRef.current = true;
2906
+ }
2907
+ return;
2908
+ }
2666
2909
  const frictionStop = resolveFrictionStop(optionsRef.current.frictionStop);
2667
2910
  const inertiaEnabled = optionsRef.current.inertia !== false;
2668
2911
  if (!interactingRef.current && !gyroActiveRef.current && inertiaEnabled) {
@@ -3013,6 +3256,30 @@ function useHotspotAccessibilityLayer() {
3013
3256
  return { controls, registry };
3014
3257
  }
3015
3258
 
3259
+ // src/hotspot/target-registry.ts
3260
+ import { createContext as createContext6 } from "react";
3261
+ var HotspotTargetRegistryContext = createContext6(
3262
+ null
3263
+ );
3264
+ function createHotspotTargetRegistry() {
3265
+ const targets = /* @__PURE__ */ new Map();
3266
+ return {
3267
+ getPosition: (id) => {
3268
+ const target = targets.get(id);
3269
+ return target ? { ...target.position } : null;
3270
+ },
3271
+ register: (id, position) => {
3272
+ const token = Symbol(id);
3273
+ targets.set(id, { token, position: { ...position } });
3274
+ return () => {
3275
+ if (targets.get(id)?.token === token) {
3276
+ targets.delete(id);
3277
+ }
3278
+ };
3279
+ }
3280
+ };
3281
+ }
3282
+
3016
3283
  // src/keyboard-controls.tsx
3017
3284
  import { useFrame as useFrame3, useThree as useThree2 } from "@react-three/fiber";
3018
3285
  import { useContext as useContext4, useEffect as useEffect4, useMemo as useMemo2, useRef as useRef4 } from "react";
@@ -3430,7 +3697,7 @@ function MouseControls({
3430
3697
  }
3431
3698
 
3432
3699
  // src/pano-filter/host.ts
3433
- import { createContext as createContext6, useContext as useContext6, useSyncExternalStore } from "react";
3700
+ import { createContext as createContext7, useContext as useContext6, useSyncExternalStore } from "react";
3434
3701
 
3435
3702
  // src/pano-filter/presets.ts
3436
3703
  var PANO_FILTER_PRESETS = [
@@ -3471,7 +3738,7 @@ function isPanoFilterActive(snapshot) {
3471
3738
  }
3472
3739
 
3473
3740
  // src/pano-filter/host.ts
3474
- var PanoFilterHostContext = createContext6(null);
3741
+ var PanoFilterHostContext = createContext7(null);
3475
3742
  function createPanoFilterHost() {
3476
3743
  return {
3477
3744
  snapshot: { ...DEFAULT_PANO_FILTER_SNAPSHOT },
@@ -3539,23 +3806,85 @@ function isProduction2() {
3539
3806
  return nodeEnv === "production";
3540
3807
  }
3541
3808
 
3809
+ // src/media-activation.tsx
3810
+ import { createContext as createContext8, useContext as useContext7, useEffect as useEffect6, useRef as useRef6 } from "react";
3811
+ import { jsx as jsx2 } from "react/jsx-runtime";
3812
+ var PanoMediaActivationHostContext = createContext8(null);
3813
+ function createPanoMediaActivationHost() {
3814
+ return { intents: /* @__PURE__ */ new Set(), listeners: /* @__PURE__ */ new Set(), revision: 0 };
3815
+ }
3816
+ function notify(host) {
3817
+ host.revision += 1;
3818
+ for (const listener of host.listeners) {
3819
+ listener();
3820
+ }
3821
+ }
3822
+ function getPanoMediaActivationRevision(host) {
3823
+ return host.revision;
3824
+ }
3825
+ function subscribePanoMediaActivation(host, listener) {
3826
+ host.listeners.add(listener);
3827
+ return () => {
3828
+ host.listeners.delete(listener);
3829
+ };
3830
+ }
3831
+ function hasPanoMediaActivationIntent(host) {
3832
+ return host.intents.size > 0;
3833
+ }
3834
+ function usePanoMediaActivationIntent(required) {
3835
+ const host = useContext7(PanoMediaActivationHostContext);
3836
+ const keyRef = useRef6(null);
3837
+ if (keyRef.current === null) {
3838
+ keyRef.current = /* @__PURE__ */ Symbol("pano-media-intent");
3839
+ }
3840
+ useEffect6(() => {
3841
+ if (!host || !required) {
3842
+ return;
3843
+ }
3844
+ const key = keyRef.current;
3845
+ host.intents.add(key);
3846
+ notify(host);
3847
+ return () => {
3848
+ host.intents.delete(key);
3849
+ notify(host);
3850
+ };
3851
+ }, [host, required]);
3852
+ }
3853
+ function PanoMediaActivationOverlay({
3854
+ ariaLabel = "Enable sound",
3855
+ className,
3856
+ message = "Tap to enable sound",
3857
+ onActivate
3858
+ }) {
3859
+ return /* @__PURE__ */ jsx2("div", { className: cn("pano-media-activation", className), children: /* @__PURE__ */ jsx2(
3860
+ "button",
3861
+ {
3862
+ "aria-label": ariaLabel,
3863
+ className: "pano-media-activation-button",
3864
+ onClick: onActivate,
3865
+ type: "button",
3866
+ children: message
3867
+ }
3868
+ ) });
3869
+ }
3870
+
3542
3871
  // src/pano-context-menu.tsx
3543
3872
  import {
3544
- createContext as createContext7,
3873
+ createContext as createContext9,
3545
3874
  useCallback as useCallback2,
3546
- useContext as useContext7,
3547
- useEffect as useEffect6,
3875
+ useContext as useContext8,
3876
+ useEffect as useEffect7,
3548
3877
  useId,
3549
3878
  useLayoutEffect,
3550
3879
  useMemo as useMemo3,
3551
- useRef as useRef6,
3880
+ useRef as useRef7,
3552
3881
  useState as useState2
3553
3882
  } from "react";
3554
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
3883
+ import { jsx as jsx3, jsxs } from "react/jsx-runtime";
3555
3884
  var DEFAULT_ICON_SIZE = 16;
3556
3885
  var MENU_EDGE_PADDING = 8;
3557
3886
  var MIN_PANO_CONTEXT_MENU_BACKGROUND_OPACITY = 0.4;
3558
- var PanoContextMenuOverlayContext = createContext7(null);
3887
+ var PanoContextMenuOverlayContext = createContext9(null);
3559
3888
  var DEFAULT_APPEARANCE = {
3560
3889
  background: "#161616",
3561
3890
  color: "#f4f4f4",
@@ -3595,7 +3924,7 @@ function DefaultContextMenuPanel({
3595
3924
  selectContext,
3596
3925
  onRequestClose
3597
3926
  }) {
3598
- const menuRef = useRef6(null);
3927
+ const menuRef = useRef7(null);
3599
3928
  const [activeIndex, setActiveIndex] = useState2(0);
3600
3929
  const resolved = { ...DEFAULT_APPEARANCE, ...appearance };
3601
3930
  const iconSize = Number.isFinite(resolved.iconSize) ? Math.max(0, resolved.iconSize) : DEFAULT_ICON_SIZE;
@@ -3617,7 +3946,7 @@ function DefaultContextMenuPanel({
3617
3946
  });
3618
3947
  return indices;
3619
3948
  }, [visibleItems]);
3620
- useEffect6(() => {
3949
+ useEffect7(() => {
3621
3950
  const first = focusableIndices[0];
3622
3951
  setActiveIndex(first ?? 0);
3623
3952
  const frame = requestAnimationFrame(() => {
@@ -3725,7 +4054,7 @@ function DefaultContextMenuPanel({
3725
4054
  style: panelStyle,
3726
4055
  tabIndex: -1,
3727
4056
  children: [
3728
- /* @__PURE__ */ jsx2(
4057
+ /* @__PURE__ */ jsx3(
3729
4058
  "div",
3730
4059
  {
3731
4060
  "aria-hidden": true,
@@ -3737,9 +4066,9 @@ function DefaultContextMenuPanel({
3737
4066
  }
3738
4067
  }
3739
4068
  ),
3740
- /* @__PURE__ */ jsx2("div", { className: "pano-context-menu-items", children: visibleItems.map((item, index) => {
4069
+ /* @__PURE__ */ jsx3("div", { className: "pano-context-menu-items", children: visibleItems.map((item, index) => {
3741
4070
  if (!isActionItem(item)) {
3742
- return /* @__PURE__ */ jsx2(
4071
+ return /* @__PURE__ */ jsx3(
3743
4072
  "div",
3744
4073
  {
3745
4074
  "aria-hidden": true,
@@ -3756,7 +4085,7 @@ function DefaultContextMenuPanel({
3756
4085
  );
3757
4086
  }
3758
4087
  const disabled = item.disabled === true;
3759
- const iconNode = item.icon ?? (item.image ? /* @__PURE__ */ jsx2(
4088
+ const iconNode = item.icon ?? (item.image ? /* @__PURE__ */ jsx3(
3760
4089
  "img",
3761
4090
  {
3762
4091
  alt: item.imageAlt ?? "",
@@ -3806,7 +4135,7 @@ function DefaultContextMenuPanel({
3806
4135
  tabIndex: disabled ? -1 : activeIndex === index ? 0 : -1,
3807
4136
  type: "button",
3808
4137
  children: [
3809
- /* @__PURE__ */ jsx2(
4138
+ /* @__PURE__ */ jsx3(
3810
4139
  "span",
3811
4140
  {
3812
4141
  "aria-hidden": true,
@@ -3818,7 +4147,7 @@ function DefaultContextMenuPanel({
3818
4147
  children: iconNode
3819
4148
  }
3820
4149
  ),
3821
- /* @__PURE__ */ jsx2("span", { style: { flex: 1 }, children: item.label })
4150
+ /* @__PURE__ */ jsx3("span", { style: { flex: 1 }, children: item.label })
3822
4151
  ]
3823
4152
  },
3824
4153
  item.id
@@ -3834,8 +4163,21 @@ function PositionedMenuShell({
3834
4163
  overlayElement,
3835
4164
  children
3836
4165
  }) {
3837
- const shellRef = useRef6(null);
4166
+ const shellRef = useRef7(null);
3838
4167
  const [offset, setOffset] = useState2({ left: 0, top: 0 });
4168
+ const [viewportRevision, setViewportRevision] = useState2(0);
4169
+ useEffect7(() => {
4170
+ const refresh = () => setViewportRevision((revision) => revision + 1);
4171
+ const viewport = window.visualViewport;
4172
+ window.addEventListener("resize", refresh);
4173
+ window.addEventListener("orientationchange", refresh);
4174
+ viewport?.addEventListener("resize", refresh);
4175
+ return () => {
4176
+ window.removeEventListener("resize", refresh);
4177
+ window.removeEventListener("orientationchange", refresh);
4178
+ viewport?.removeEventListener("resize", refresh);
4179
+ };
4180
+ }, []);
3839
4181
  useLayoutEffect(() => {
3840
4182
  const shell = shellRef.current;
3841
4183
  if (!overlayElement || !shell) {
@@ -3857,8 +4199,8 @@ function PositionedMenuShell({
3857
4199
  left: Math.min(Math.max(rawLeft, MENU_EDGE_PADDING), maxLeft),
3858
4200
  top: Math.min(Math.max(rawTop, MENU_EDGE_PADDING), maxTop)
3859
4201
  });
3860
- }, [clientX, clientY, overlayElement, children]);
3861
- return /* @__PURE__ */ jsx2(
4202
+ }, [clientX, clientY, overlayElement, children, viewportRevision]);
4203
+ return /* @__PURE__ */ jsx3(
3862
4204
  "div",
3863
4205
  {
3864
4206
  className: "pano-context-menu-shell",
@@ -3873,7 +4215,7 @@ function PositionedMenuShell({
3873
4215
  }
3874
4216
  function usePanoContextMenuOverlay() {
3875
4217
  const [session2, setSession] = useState2(null);
3876
- const overlayRef = useRef6(null);
4218
+ const overlayRef = useRef7(null);
3877
4219
  const [overlayElement, setOverlayElement] = useState2(
3878
4220
  null
3879
4221
  );
@@ -3885,7 +4227,7 @@ function usePanoContextMenuOverlay() {
3885
4227
  overlayRef.current = node;
3886
4228
  setOverlayElement(node);
3887
4229
  }, []);
3888
- useEffect6(() => {
4230
+ useEffect7(() => {
3889
4231
  if (!session2) {
3890
4232
  return;
3891
4233
  }
@@ -3917,7 +4259,7 @@ function usePanoContextMenuOverlay() {
3917
4259
  document.removeEventListener("keydown", handleKeyDown);
3918
4260
  };
3919
4261
  }, [session2]);
3920
- const overlay = /* @__PURE__ */ jsx2(
4262
+ const overlay = /* @__PURE__ */ jsx3(
3921
4263
  "div",
3922
4264
  {
3923
4265
  ref: setOverlayNode,
@@ -3928,7 +4270,7 @@ function usePanoContextMenuOverlay() {
3928
4270
  position: "absolute",
3929
4271
  zIndex: 20
3930
4272
  },
3931
- children: session2 ? /* @__PURE__ */ jsx2(
4273
+ children: session2 ? /* @__PURE__ */ jsx3(
3932
4274
  PositionedMenuShell,
3933
4275
  {
3934
4276
  clientX: session2.event.clientX,
@@ -3953,13 +4295,13 @@ function PanoContextMenu({
3953
4295
  separatorClassName,
3954
4296
  children
3955
4297
  }) {
3956
- const eventBus = useContext7(PanoEventBusContext);
3957
- const controlsRef = useContext7(PanoramaViewContext);
3958
- const overlayApi = useContext7(PanoContextMenuOverlayContext);
3959
- const actions = useContext7(PanoContextMenuActionsContext);
4298
+ const eventBus = useContext8(PanoEventBusContext);
4299
+ const controlsRef = useContext8(PanoramaViewContext);
4300
+ const overlayApi = useContext8(PanoContextMenuOverlayContext);
4301
+ const actions = useContext8(PanoContextMenuActionsContext);
3960
4302
  const instanceId = useId();
3961
- const sessionKeyRef = useRef6(0);
3962
- const propsRef = useRef6({
4303
+ const sessionKeyRef = useRef7(0);
4304
+ const propsRef = useRef7({
3963
4305
  items,
3964
4306
  prepend,
3965
4307
  append,
@@ -4021,9 +4363,9 @@ function PanoContextMenu({
4021
4363
  view,
4022
4364
  render: () => {
4023
4365
  if (hasCustomChildren && current.children) {
4024
- return /* @__PURE__ */ jsx2("div", { "data-pano-context-menu": true, style: { pointerEvents: "auto" }, children: current.children({ event, view, close }) });
4366
+ return /* @__PURE__ */ jsx3("div", { "data-pano-context-menu": true, style: { pointerEvents: "auto" }, children: current.children({ event, view, close }) });
4025
4367
  }
4026
- return /* @__PURE__ */ jsx2(
4368
+ return /* @__PURE__ */ jsx3(
4027
4369
  DefaultContextMenuPanel,
4028
4370
  {
4029
4371
  appearance: current.appearance,
@@ -4041,7 +4383,7 @@ function PanoContextMenu({
4041
4383
  },
4042
4384
  [actions, close, controlsRef, instanceId, overlayApi]
4043
4385
  );
4044
- useEffect6(() => {
4386
+ useEffect7(() => {
4045
4387
  const unsubscribeContextMenu = eventBus.subscribe(
4046
4388
  "contextmenu",
4047
4389
  openMenu
@@ -4074,14 +4416,14 @@ function ResetViewIcon() {
4074
4416
  viewBox: "0 0 16 16",
4075
4417
  width: "100%",
4076
4418
  children: [
4077
- /* @__PURE__ */ jsx2("path", { d: "M3.5 6.5A4.5 4.5 0 1 1 4 10" }),
4078
- /* @__PURE__ */ jsx2("path", { d: "M3.5 3.5v3h3" })
4419
+ /* @__PURE__ */ jsx3("path", { d: "M3.5 6.5A4.5 4.5 0 1 1 4 10" }),
4420
+ /* @__PURE__ */ jsx3("path", { d: "M3.5 3.5v3h3" })
4079
4421
  ]
4080
4422
  }
4081
4423
  );
4082
4424
  }
4083
4425
  function FullscreenIcon() {
4084
- return /* @__PURE__ */ jsx2(
4426
+ return /* @__PURE__ */ jsx3(
4085
4427
  "svg",
4086
4428
  {
4087
4429
  "aria-hidden": true,
@@ -4093,12 +4435,12 @@ function FullscreenIcon() {
4093
4435
  strokeWidth: "1.75",
4094
4436
  viewBox: "0 0 16 16",
4095
4437
  width: "100%",
4096
- children: /* @__PURE__ */ jsx2("path", { d: "M3 6V3h3M10 3h3v3M13 10v3h-3M6 13H3v-3" })
4438
+ children: /* @__PURE__ */ jsx3("path", { d: "M3 6V3h3M10 3h3v3M13 10v3h-3M6 13H3v-3" })
4097
4439
  }
4098
4440
  );
4099
4441
  }
4100
4442
  function ExitFullscreenIcon() {
4101
- return /* @__PURE__ */ jsx2(
4443
+ return /* @__PURE__ */ jsx3(
4102
4444
  "svg",
4103
4445
  {
4104
4446
  "aria-hidden": true,
@@ -4110,7 +4452,7 @@ function ExitFullscreenIcon() {
4110
4452
  strokeWidth: "1.75",
4111
4453
  viewBox: "0 0 16 16",
4112
4454
  width: "100%",
4113
- children: /* @__PURE__ */ jsx2("path", { d: "M6 3v3H3M10 3v3h3M3 10h3v3M10 10h3v3" })
4455
+ children: /* @__PURE__ */ jsx3("path", { d: "M6 3v3H3M10 3v3h3M3 10h3v3M10 10h3v3" })
4114
4456
  }
4115
4457
  );
4116
4458
  }
@@ -4119,7 +4461,7 @@ function createPanoContextMenuPresets(actions) {
4119
4461
  const resetView = {
4120
4462
  id: "pano-reset-view",
4121
4463
  label: "Reset view",
4122
- icon: /* @__PURE__ */ jsx2(ResetViewIcon, {}),
4464
+ icon: /* @__PURE__ */ jsx3(ResetViewIcon, {}),
4123
4465
  onSelect: () => {
4124
4466
  actions.reset();
4125
4467
  }
@@ -4127,7 +4469,7 @@ function createPanoContextMenuPresets(actions) {
4127
4469
  const fullscreen = {
4128
4470
  id: "pano-fullscreen",
4129
4471
  label: isFullscreen ? "Exit fullscreen" : "Enter fullscreen",
4130
- icon: isFullscreen ? /* @__PURE__ */ jsx2(ExitFullscreenIcon, {}) : /* @__PURE__ */ jsx2(FullscreenIcon, {}),
4472
+ icon: isFullscreen ? /* @__PURE__ */ jsx3(ExitFullscreenIcon, {}) : /* @__PURE__ */ jsx3(FullscreenIcon, {}),
4131
4473
  onSelect: () => {
4132
4474
  actions.toggleFullscreen();
4133
4475
  }
@@ -4220,19 +4562,19 @@ function composePanoContextMenuItems(props, presets) {
4220
4562
  ...resolvePanoContextMenuEntries(props.append ?? [], presets)
4221
4563
  ];
4222
4564
  }
4223
- var PanoContextMenuActionsContext = createContext7(null);
4565
+ var PanoContextMenuActionsContext = createContext9(null);
4224
4566
 
4225
4567
  // src/pano-cursor.tsx
4226
4568
  import { useThree as useThree4 } from "@react-three/fiber";
4227
4569
  import {
4228
- createContext as createContext8,
4570
+ createContext as createContext10,
4229
4571
  useCallback as useCallback3,
4230
- useContext as useContext8,
4231
- useEffect as useEffect7,
4572
+ useContext as useContext9,
4573
+ useEffect as useEffect8,
4232
4574
  useMemo as useMemo4,
4233
- useRef as useRef7
4575
+ useRef as useRef8
4234
4576
  } from "react";
4235
- import { jsx as jsx3 } from "react/jsx-runtime";
4577
+ import { jsx as jsx4 } from "react/jsx-runtime";
4236
4578
  var DEFAULT_PANO_CURSORS = {
4237
4579
  default: "grab",
4238
4580
  dragging: "grabbing",
@@ -4246,9 +4588,9 @@ var LAYER_PRIORITY = {
4246
4588
  hotspotDragging: 3,
4247
4589
  hidden: 4
4248
4590
  };
4249
- var PanoCursorContext = createContext8(null);
4591
+ var PanoCursorContext = createContext10(null);
4250
4592
  function usePanoCursor() {
4251
- return useContext8(PanoCursorContext);
4593
+ return useContext9(PanoCursorContext);
4252
4594
  }
4253
4595
  function hotspotCursorClaimId(id) {
4254
4596
  return `pano-cursor:hotspot:${id}`;
@@ -4300,10 +4642,10 @@ function PanoCursorController({
4300
4642
  children
4301
4643
  }) {
4302
4644
  const { gl } = useThree4();
4303
- const eventBus = useContext8(PanoEventBusContext);
4304
- const claimsRef = useRef7(/* @__PURE__ */ new Map());
4305
- const cursorsRef = useRef7(cursors);
4306
- const appliedCursorRef = useRef7(null);
4645
+ const eventBus = useContext9(PanoEventBusContext);
4646
+ const claimsRef = useRef8(/* @__PURE__ */ new Map());
4647
+ const cursorsRef = useRef8(cursors);
4648
+ const appliedCursorRef = useRef8(null);
4307
4649
  cursorsRef.current = cursors;
4308
4650
  const applyCursor = useCallback3(() => {
4309
4651
  const next = resolveHighestCursor(claimsRef.current, cursorsRef.current);
@@ -4337,7 +4679,7 @@ function PanoCursorController({
4337
4679
  }),
4338
4680
  [claim, cursors, release]
4339
4681
  );
4340
- useEffect7(() => {
4682
+ useEffect8(() => {
4341
4683
  const element = gl.domElement;
4342
4684
  const previous = element.style.cursor;
4343
4685
  return () => {
@@ -4346,10 +4688,10 @@ function PanoCursorController({
4346
4688
  element.style.cursor = previous;
4347
4689
  };
4348
4690
  }, [gl]);
4349
- useEffect7(() => {
4691
+ useEffect8(() => {
4350
4692
  applyCursor();
4351
4693
  }, [applyCursor, cursors]);
4352
- useEffect7(() => {
4694
+ useEffect8(() => {
4353
4695
  if (!eventBus) {
4354
4696
  return;
4355
4697
  }
@@ -4374,12 +4716,12 @@ function PanoCursorController({
4374
4716
  release(PANO_DRAG_CLAIM_ID);
4375
4717
  };
4376
4718
  }, [claim, eventBus, release]);
4377
- return /* @__PURE__ */ jsx3(PanoCursorContext.Provider, { value: api, children });
4719
+ return /* @__PURE__ */ jsx4(PanoCursorContext.Provider, { value: api, children });
4378
4720
  }
4379
4721
 
4380
4722
  // src/pano-events.tsx
4381
4723
  import { useFrame as useFrame4, useThree as useThree5 } from "@react-three/fiber";
4382
- import { useContext as useContext9, useEffect as useEffect8, useRef as useRef8 } from "react";
4724
+ import { useContext as useContext10, useEffect as useEffect9, useRef as useRef9 } from "react";
4383
4725
  var DEFAULT_IDLE_TIME_MS = 2e3;
4384
4726
  function resolveIdleTime(value) {
4385
4727
  return Number.isFinite(value) && value >= 0 ? value : DEFAULT_IDLE_TIME_MS;
@@ -4417,13 +4759,13 @@ function usePanoEvents({
4417
4759
  onVRDenied,
4418
4760
  onVRUnknownDevice
4419
4761
  }) {
4420
- const eventBus = useContext9(PanoEventBusContext);
4421
- const controlsRef = useContext9(PanoramaViewContext);
4762
+ const eventBus = useContext10(PanoEventBusContext);
4763
+ const controlsRef = useContext10(PanoramaViewContext);
4422
4764
  const { gl } = useThree5();
4423
4765
  if (!eventBus || !controlsRef) {
4424
4766
  throw new Error("usePanoEvents must be used inside <PanoViewer>.");
4425
4767
  }
4426
- const callbacksRef = useRef8({
4768
+ const callbacksRef = useRef9({
4427
4769
  onViewChange,
4428
4770
  onViewSettled,
4429
4771
  onViewInteractionStart,
@@ -4487,15 +4829,15 @@ function usePanoEvents({
4487
4829
  onVRDenied,
4488
4830
  onVRUnknownDevice
4489
4831
  };
4490
- const idleElapsedRef = useRef8(0);
4491
- const isIdleRef = useRef8(false);
4492
- const idleTimeRef = useRef8(resolveIdleTime(idleTime));
4832
+ const idleElapsedRef = useRef9(0);
4833
+ const isIdleRef = useRef9(false);
4834
+ const idleTimeRef = useRef9(resolveIdleTime(idleTime));
4493
4835
  idleTimeRef.current = resolveIdleTime(idleTime);
4494
- useEffect8(() => {
4836
+ useEffect9(() => {
4495
4837
  idleElapsedRef.current = 0;
4496
4838
  isIdleRef.current = false;
4497
4839
  }, [idleTime]);
4498
- useEffect8(() => {
4840
+ useEffect9(() => {
4499
4841
  const unsubscribers = [
4500
4842
  eventBus.subscribe("viewchange", (view) => {
4501
4843
  callbacksRef.current.onViewChange?.(view);
@@ -4576,7 +4918,7 @@ function usePanoEvents({
4576
4918
  }
4577
4919
  };
4578
4920
  }, [eventBus]);
4579
- useEffect8(() => {
4921
+ useEffect9(() => {
4580
4922
  const element = gl.domElement;
4581
4923
  const handleWheel = (nativeEvent) => {
4582
4924
  callbacksRef.current.onWheel?.({
@@ -4589,7 +4931,7 @@ function usePanoEvents({
4589
4931
  element.removeEventListener("wheel", handleWheel);
4590
4932
  };
4591
4933
  }, [gl]);
4592
- useEffect8(() => {
4934
+ useEffect9(() => {
4593
4935
  if (typeof document === "undefined") {
4594
4936
  return;
4595
4937
  }
@@ -4615,7 +4957,7 @@ function usePanoEvents({
4615
4957
  wasFullscreenRef.current = isViewerFullscreen();
4616
4958
  return subscribeFullscreenChange(handleFullscreenChange);
4617
4959
  }, [gl]);
4618
- useEffect8(() => {
4960
+ useEffect9(() => {
4619
4961
  const element = gl.domElement;
4620
4962
  if (typeof ResizeObserver === "undefined") {
4621
4963
  return;
@@ -4657,7 +4999,7 @@ function PanoEvents(props) {
4657
4999
 
4658
5000
  // src/panorama-event-surface.tsx
4659
5001
  import { useThree as useThree6 } from "@react-three/fiber";
4660
- import { useContext as useContext10, useEffect as useEffect9 } from "react";
5002
+ import { useContext as useContext11, useEffect as useEffect10 } from "react";
4661
5003
  import { BackSide, Raycaster, Vector2, Vector3 as Vector32 } from "three";
4662
5004
 
4663
5005
  // src/hotspot/coordinates.ts
@@ -4735,7 +5077,7 @@ var DEFAULT_PANORAMA_CAMERA_NEAR = 0.1;
4735
5077
  var DEFAULT_PANORAMA_CAMERA_FAR = DEFAULT_PANORAMA_RADIUS * 2;
4736
5078
 
4737
5079
  // src/panorama-event-surface.tsx
4738
- import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
5080
+ import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
4739
5081
  var EVENT_SURFACE_RADIUS = DEFAULT_PANORAMA_RADIUS - 1;
4740
5082
  function makePanoramaPointerEvent(event) {
4741
5083
  const nativeEvent = event.nativeEvent;
@@ -4750,9 +5092,9 @@ function makePanoramaPointerEvent(event) {
4750
5092
  };
4751
5093
  }
4752
5094
  function PanoramaEventSurface() {
4753
- const eventBus = useContext10(PanoEventBusContext);
5095
+ const eventBus = useContext11(PanoEventBusContext);
4754
5096
  const { camera, gl } = useThree6();
4755
- useEffect9(() => {
5097
+ useEffect10(() => {
4756
5098
  if (!eventBus) {
4757
5099
  return;
4758
5100
  }
@@ -4803,8 +5145,8 @@ function PanoramaEventSurface() {
4803
5145
  onPointerUp: (event) => emit("pointerup", event),
4804
5146
  onPointerMove: (event) => emit("pointermove", event),
4805
5147
  children: [
4806
- /* @__PURE__ */ jsx4("sphereGeometry", { args: [EVENT_SURFACE_RADIUS, 64, 32] }),
4807
- /* @__PURE__ */ jsx4(
5148
+ /* @__PURE__ */ jsx5("sphereGeometry", { args: [EVENT_SURFACE_RADIUS, 64, 32] }),
5149
+ /* @__PURE__ */ jsx5(
4808
5150
  "meshBasicMaterial",
4809
5151
  {
4810
5152
  colorWrite: false,
@@ -4821,8 +5163,8 @@ function PanoramaEventSurface() {
4821
5163
  }
4822
5164
 
4823
5165
  // src/scenes-host.ts
4824
- import { createContext as createContext9 } from "react";
4825
- var ScenesHostContext = createContext9(null);
5166
+ import { createContext as createContext11 } from "react";
5167
+ var ScenesHostContext = createContext11(null);
4826
5168
  function createScenesHost() {
4827
5169
  return {
4828
5170
  controller: null,
@@ -4839,7 +5181,7 @@ function notifyScenesHost(host) {
4839
5181
 
4840
5182
  // src/touch-controls.tsx
4841
5183
  import { useThree as useThree7 } from "@react-three/fiber";
4842
- import { useContext as useContext11, useEffect as useEffect10, useRef as useRef9 } from "react";
5184
+ import { useContext as useContext12, useEffect as useEffect11, useRef as useRef10 } from "react";
4843
5185
  var DEFAULT_ROTATE_SPEED3 = 0.35;
4844
5186
  function resolveSpeed3(value, fallback) {
4845
5187
  return Number.isFinite(value) && value >= 0 ? value : fallback;
@@ -4854,16 +5196,16 @@ function TouchControls({
4854
5196
  pinchZoom = true
4855
5197
  }) {
4856
5198
  useClaimControlChannel("touch");
4857
- const controlsRef = useContext11(PanoramaViewContext);
5199
+ const controlsRef = useContext12(PanoramaViewContext);
4858
5200
  const { gl } = useThree7();
4859
- const pointersRef = useRef9(/* @__PURE__ */ new Map());
4860
- const pinchDistanceRef = useRef9(null);
4861
- const optionsRef = useRef9({ rotateSpeed, invert, pinchZoom });
5201
+ const pointersRef = useRef10(/* @__PURE__ */ new Map());
5202
+ const pinchDistanceRef = useRef10(null);
5203
+ const optionsRef = useRef10({ rotateSpeed, invert, pinchZoom });
4862
5204
  if (!controlsRef) {
4863
5205
  throw new Error("<TouchControls> must be rendered inside <PanoViewer>.");
4864
5206
  }
4865
5207
  optionsRef.current = { rotateSpeed, invert, pinchZoom };
4866
- useEffect10(() => {
5208
+ useEffect11(() => {
4867
5209
  const element = gl.domElement;
4868
5210
  const clearPointers = () => {
4869
5211
  for (const pointerId of pointersRef.current.keys()) {
@@ -4985,9 +5327,9 @@ function TouchControls({
4985
5327
  }
4986
5328
 
4987
5329
  // src/video/chrome-overlay.tsx
4988
- import { createContext as createContext10, useCallback as useCallback4, useMemo as useMemo5, useState as useState3 } from "react";
4989
- import { jsx as jsx5 } from "react/jsx-runtime";
4990
- var PanoChromeOverlayContext = createContext10(null);
5330
+ import { createContext as createContext12, useCallback as useCallback4, useMemo as useMemo5, useState as useState3 } from "react";
5331
+ import { jsx as jsx6 } from "react/jsx-runtime";
5332
+ var PanoChromeOverlayContext = createContext12(null);
4991
5333
  function usePanoChromeOverlay() {
4992
5334
  const [overlayElement, setOverlayElement] = useState3(
4993
5335
  null
@@ -4999,7 +5341,7 @@ function usePanoChromeOverlay() {
4999
5341
  () => ({ overlayElement }),
5000
5342
  [overlayElement]
5001
5343
  );
5002
- const overlay = /* @__PURE__ */ jsx5(
5344
+ const overlay = /* @__PURE__ */ jsx6(
5003
5345
  "div",
5004
5346
  {
5005
5347
  className: "pano-chrome-overlay",
@@ -5011,9 +5353,9 @@ function usePanoChromeOverlay() {
5011
5353
  }
5012
5354
 
5013
5355
  // src/video/host.ts
5014
- import { createContext as createContext11, useContext as useContext12 } from "react";
5015
- var PanoVideoHostContext = createContext11(null);
5016
- var DefaultPanoVideoControlsContext = createContext11(false);
5356
+ import { createContext as createContext13, useContext as useContext13 } from "react";
5357
+ var PanoVideoHostContext = createContext13(null);
5358
+ var DefaultPanoVideoControlsContext = createContext13(false);
5017
5359
  function createPanoVideoHost() {
5018
5360
  return {
5019
5361
  controller: null,
@@ -5058,8 +5400,8 @@ function isProduction3() {
5058
5400
  return nodeEnv === "production";
5059
5401
  }
5060
5402
  function useClaimPanoVideoControls() {
5061
- const host = useContext12(PanoVideoHostContext);
5062
- const isDefault = useContext12(DefaultPanoVideoControlsContext);
5403
+ const host = useContext13(PanoVideoHostContext);
5404
+ const isDefault = useContext13(DefaultPanoVideoControlsContext);
5063
5405
  if (!host || isDefault) {
5064
5406
  return;
5065
5407
  }
@@ -5076,7 +5418,7 @@ import { useSyncExternalStore as useSyncExternalStore4 } from "react";
5076
5418
 
5077
5419
  // src/video/pano-video-captions.tsx
5078
5420
  import { useSyncExternalStore as useSyncExternalStore2 } from "react";
5079
- import { jsx as jsx6 } from "react/jsx-runtime";
5421
+ import { jsx as jsx7 } from "react/jsx-runtime";
5080
5422
  var DEFAULT_PANO_VIDEO_CAPTION_APPEARANCE = {
5081
5423
  color: "#ffffff",
5082
5424
  background: "rgba(0, 0, 0, 0.55)",
@@ -5124,13 +5466,13 @@ function PanoVideoCaptionsOverlay({
5124
5466
  textShadow: snapshot.captionAppearance.textShadow,
5125
5467
  whiteSpace: "pre-wrap"
5126
5468
  };
5127
- return /* @__PURE__ */ jsx6(
5469
+ return /* @__PURE__ */ jsx7(
5128
5470
  "div",
5129
5471
  {
5130
5472
  className: "pano-video-captions",
5131
5473
  "data-pano-video-captions": "",
5132
5474
  style: wrapperStyle,
5133
- children: /* @__PURE__ */ jsx6("div", { style: textStyle, children: snapshot.captionText })
5475
+ children: /* @__PURE__ */ jsx7("div", { style: textStyle, children: snapshot.captionText })
5134
5476
  }
5135
5477
  );
5136
5478
  }
@@ -5143,11 +5485,11 @@ function PanoVideoCaptions({
5143
5485
  // src/video/pano-video-controls.tsx
5144
5486
  import {
5145
5487
  useCallback as useCallback5,
5146
- useContext as useContext13,
5147
- useEffect as useEffect11,
5488
+ useContext as useContext14,
5489
+ useEffect as useEffect12,
5148
5490
  useId as useId2,
5149
5491
  useMemo as useMemo6,
5150
- useRef as useRef10,
5492
+ useRef as useRef11,
5151
5493
  useState as useState4,
5152
5494
  useSyncExternalStore as useSyncExternalStore3
5153
5495
  } from "react";
@@ -5282,7 +5624,7 @@ function cueText(cue) {
5282
5624
  }
5283
5625
 
5284
5626
  // src/video/pano-video-controls.tsx
5285
- import { Fragment, jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
5627
+ import { Fragment, jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
5286
5628
  var DEFAULT_PANO_VIDEO_CONTROLS_APPEARANCE = {
5287
5629
  background: "rgba(16, 16, 16, 0.88)",
5288
5630
  color: "#f4f4f4",
@@ -5343,7 +5685,7 @@ function volumeFromClientY(clientY, track) {
5343
5685
  return Math.max(0, Math.min(1, (rect.bottom - clientY) / rect.height));
5344
5686
  }
5345
5687
  function Icon({ path }) {
5346
- return /* @__PURE__ */ jsx7(
5688
+ return /* @__PURE__ */ jsx8(
5347
5689
  "svg",
5348
5690
  {
5349
5691
  "aria-hidden": true,
@@ -5355,7 +5697,7 @@ function Icon({ path }) {
5355
5697
  strokeWidth: "1.75",
5356
5698
  viewBox: "0 0 16 16",
5357
5699
  width: "16",
5358
- children: /* @__PURE__ */ jsx7("path", { d: path })
5700
+ children: /* @__PURE__ */ jsx8("path", { d: path })
5359
5701
  }
5360
5702
  );
5361
5703
  }
@@ -5367,7 +5709,7 @@ function ChromeButton({
5367
5709
  label,
5368
5710
  onClick
5369
5711
  }) {
5370
- return /* @__PURE__ */ jsx7(
5712
+ return /* @__PURE__ */ jsx8(
5371
5713
  "button",
5372
5714
  {
5373
5715
  "aria-label": label,
@@ -5393,14 +5735,14 @@ function ChromeMenu({
5393
5735
  labelledBy,
5394
5736
  items
5395
5737
  }) {
5396
- return /* @__PURE__ */ jsx7(
5738
+ return /* @__PURE__ */ jsx8(
5397
5739
  ChromeMenuSurface,
5398
5740
  {
5399
5741
  appearance,
5400
5742
  id,
5401
5743
  labelledBy,
5402
5744
  role: "menu",
5403
- children: items.map((item) => /* @__PURE__ */ jsx7(
5745
+ children: items.map((item) => /* @__PURE__ */ jsx8(
5404
5746
  ChromeMenuRadioItem,
5405
5747
  {
5406
5748
  active: item.active,
@@ -5420,7 +5762,7 @@ function ChromeMenuSurface({
5420
5762
  labelledBy,
5421
5763
  role
5422
5764
  }) {
5423
- return /* @__PURE__ */ jsx7(
5765
+ return /* @__PURE__ */ jsx8(
5424
5766
  "div",
5425
5767
  {
5426
5768
  "aria-labelledby": labelledBy,
@@ -5444,7 +5786,7 @@ function ChromeMenuRadioItem({
5444
5786
  label,
5445
5787
  onClick
5446
5788
  }) {
5447
- return /* @__PURE__ */ jsx7(
5789
+ return /* @__PURE__ */ jsx8(
5448
5790
  "button",
5449
5791
  {
5450
5792
  "aria-checked": active,
@@ -5484,7 +5826,7 @@ function ChromeMenuActionItem({
5484
5826
  },
5485
5827
  type: "button",
5486
5828
  children: [
5487
- /* @__PURE__ */ jsx7("span", { children: label }),
5829
+ /* @__PURE__ */ jsx8("span", { children: label }),
5488
5830
  secondary
5489
5831
  ]
5490
5832
  }
@@ -5493,10 +5835,10 @@ function ChromeMenuActionItem({
5493
5835
  function ChromeMenuSectionLabel({
5494
5836
  children
5495
5837
  }) {
5496
- return /* @__PURE__ */ jsx7("div", { className: "pano-video-chrome-menu-label", children });
5838
+ return /* @__PURE__ */ jsx8("div", { className: "pano-video-chrome-menu-label", children });
5497
5839
  }
5498
5840
  function ChromeMenuDivider() {
5499
- return /* @__PURE__ */ jsx7("div", { className: "pano-video-chrome-menu-divider" });
5841
+ return /* @__PURE__ */ jsx8("div", { className: "pano-video-chrome-menu-divider" });
5500
5842
  }
5501
5843
  function CaptionsMenu({
5502
5844
  appearance,
@@ -5509,7 +5851,7 @@ function CaptionsMenu({
5509
5851
  panel,
5510
5852
  snapshot
5511
5853
  }) {
5512
- return /* @__PURE__ */ jsx7(
5854
+ return /* @__PURE__ */ jsx8(
5513
5855
  ChromeMenuSurface,
5514
5856
  {
5515
5857
  appearance,
@@ -5518,7 +5860,7 @@ function CaptionsMenu({
5518
5860
  role: "menu",
5519
5861
  children: panel === "tracks" ? /* @__PURE__ */ jsxs3(Fragment, { children: [
5520
5862
  /* @__PURE__ */ jsxs3("div", { className: "pano-video-chrome-menu-list", children: [
5521
- /* @__PURE__ */ jsx7(
5863
+ /* @__PURE__ */ jsx8(
5522
5864
  ChromeMenuRadioItem,
5523
5865
  {
5524
5866
  active: snapshot.trackId === null,
@@ -5531,7 +5873,7 @@ function CaptionsMenu({
5531
5873
  ),
5532
5874
  snapshot.tracks.map((track) => {
5533
5875
  const trackItemId = panoVideoTrackId(track);
5534
- return /* @__PURE__ */ jsx7(
5876
+ return /* @__PURE__ */ jsx8(
5535
5877
  ChromeMenuRadioItem,
5536
5878
  {
5537
5879
  active: snapshot.trackId === trackItemId,
@@ -5545,29 +5887,29 @@ function CaptionsMenu({
5545
5887
  );
5546
5888
  })
5547
5889
  ] }),
5548
- /* @__PURE__ */ jsx7(ChromeMenuDivider, {}),
5549
- /* @__PURE__ */ jsx7(
5890
+ /* @__PURE__ */ jsx8(ChromeMenuDivider, {}),
5891
+ /* @__PURE__ */ jsx8(
5550
5892
  ChromeMenuActionItem,
5551
5893
  {
5552
5894
  appearance,
5553
5895
  label: "Settings",
5554
5896
  onClick: onOpenSettings,
5555
- secondary: /* @__PURE__ */ jsx7("span", { "aria-hidden": true, children: "\u203A" })
5897
+ secondary: /* @__PURE__ */ jsx8("span", { "aria-hidden": true, children: "\u203A" })
5556
5898
  }
5557
5899
  )
5558
5900
  ] }) : /* @__PURE__ */ jsxs3(Fragment, { children: [
5559
- /* @__PURE__ */ jsx7(
5901
+ /* @__PURE__ */ jsx8(
5560
5902
  ChromeMenuActionItem,
5561
5903
  {
5562
5904
  appearance,
5563
5905
  label: "Back",
5564
5906
  onClick: onShowTracks,
5565
- secondary: /* @__PURE__ */ jsx7("span", { "aria-hidden": true, children: "\u2039" })
5907
+ secondary: /* @__PURE__ */ jsx8("span", { "aria-hidden": true, children: "\u2039" })
5566
5908
  }
5567
5909
  ),
5568
- /* @__PURE__ */ jsx7(ChromeMenuDivider, {}),
5569
- /* @__PURE__ */ jsx7(ChromeMenuSectionLabel, { children: "Font size" }),
5570
- CAPTION_SIZE_OPTIONS.map((option) => /* @__PURE__ */ jsx7(
5910
+ /* @__PURE__ */ jsx8(ChromeMenuDivider, {}),
5911
+ /* @__PURE__ */ jsx8(ChromeMenuSectionLabel, { children: "Font size" }),
5912
+ CAPTION_SIZE_OPTIONS.map((option) => /* @__PURE__ */ jsx8(
5571
5913
  ChromeMenuRadioItem,
5572
5914
  {
5573
5915
  active: Number(snapshot.captionAppearance.fontSize) === option.value,
@@ -5579,9 +5921,9 @@ function CaptionsMenu({
5579
5921
  },
5580
5922
  option.id
5581
5923
  )),
5582
- /* @__PURE__ */ jsx7(ChromeMenuDivider, {}),
5583
- /* @__PURE__ */ jsx7(ChromeMenuSectionLabel, { children: "Background" }),
5584
- CAPTION_BACKGROUND_OPTIONS.map((option) => /* @__PURE__ */ jsx7(
5924
+ /* @__PURE__ */ jsx8(ChromeMenuDivider, {}),
5925
+ /* @__PURE__ */ jsx8(ChromeMenuSectionLabel, { children: "Background" }),
5926
+ CAPTION_BACKGROUND_OPTIONS.map((option) => /* @__PURE__ */ jsx8(
5585
5927
  ChromeMenuRadioItem,
5586
5928
  {
5587
5929
  active: snapshot.captionAppearance.background === option.value,
@@ -5602,7 +5944,7 @@ function VerticalVolumeSlider({
5602
5944
  onVolume,
5603
5945
  volume
5604
5946
  }) {
5605
- const trackRef = useRef10(null);
5947
+ const trackRef = useRef11(null);
5606
5948
  const applyPointer = (event) => {
5607
5949
  const track = trackRef.current;
5608
5950
  if (!track) {
@@ -5636,7 +5978,7 @@ function VerticalVolumeSlider({
5636
5978
  pointerEvents: "auto"
5637
5979
  },
5638
5980
  children: [
5639
- /* @__PURE__ */ jsx7(
5981
+ /* @__PURE__ */ jsx8(
5640
5982
  "span",
5641
5983
  {
5642
5984
  "aria-hidden": true,
@@ -5648,7 +5990,7 @@ function VerticalVolumeSlider({
5648
5990
  children: percentLabel
5649
5991
  }
5650
5992
  ),
5651
- /* @__PURE__ */ jsx7(
5993
+ /* @__PURE__ */ jsx8(
5652
5994
  "div",
5653
5995
  {
5654
5996
  style: {
@@ -5688,7 +6030,7 @@ function VerticalVolumeSlider({
5688
6030
  },
5689
6031
  tabIndex: 0,
5690
6032
  children: [
5691
- /* @__PURE__ */ jsx7(
6033
+ /* @__PURE__ */ jsx8(
5692
6034
  "div",
5693
6035
  {
5694
6036
  style: {
@@ -5703,7 +6045,7 @@ function VerticalVolumeSlider({
5703
6045
  }
5704
6046
  }
5705
6047
  ),
5706
- /* @__PURE__ */ jsx7(
6048
+ /* @__PURE__ */ jsx8(
5707
6049
  "div",
5708
6050
  {
5709
6051
  style: {
@@ -5738,14 +6080,14 @@ function VolumeControl({
5738
6080
  volume,
5739
6081
  volumeAdjustable
5740
6082
  }) {
5741
- const rootRef = useRef10(null);
6083
+ const rootRef = useRef11(null);
5742
6084
  const [open, setOpen] = useState4(false);
5743
6085
  const displayVolume = muted ? 0 : volume;
5744
6086
  const mutedOrSilent = muted || volume === 0;
5745
- useEffect11(() => {
6087
+ useEffect12(() => {
5746
6088
  onOpenChange(open);
5747
6089
  }, [onOpenChange, open]);
5748
- useEffect11(() => {
6090
+ useEffect12(() => {
5749
6091
  if (!open || !volumeAdjustable || hasFinePointerHover()) {
5750
6092
  return;
5751
6093
  }
@@ -5762,13 +6104,13 @@ function VolumeControl({
5762
6104
  };
5763
6105
  }, [open, volumeAdjustable]);
5764
6106
  if (!volumeAdjustable) {
5765
- return /* @__PURE__ */ jsx7(
6107
+ return /* @__PURE__ */ jsx8(
5766
6108
  ChromeButton,
5767
6109
  {
5768
6110
  appearance,
5769
6111
  label: mutedOrSilent ? "Unmute" : "Mute",
5770
6112
  onClick: onToggleMuted,
5771
- children: mutedOrSilent ? /* @__PURE__ */ jsx7(Icon, { path: "M3 6.5h2.2L8.5 4v8L5.2 9.5H3zM10.2 6.2l3.2 3.6M13.4 6.2l-3.2 3.6" }) : /* @__PURE__ */ jsx7(Icon, { path: "M3 6.5h2.2L8.5 4v8L5.2 9.5H3zM10.5 5.5a3 3 0 0 1 0 5" })
6113
+ children: mutedOrSilent ? /* @__PURE__ */ jsx8(Icon, { path: "M3 6.5h2.2L8.5 4v8L5.2 9.5H3zM10.2 6.2l3.2 3.6M13.4 6.2l-3.2 3.6" }) : /* @__PURE__ */ jsx8(Icon, { path: "M3 6.5h2.2L8.5 4v8L5.2 9.5H3zM10.5 5.5a3 3 0 0 1 0 5" })
5772
6114
  }
5773
6115
  );
5774
6116
  }
@@ -5800,7 +6142,7 @@ function VolumeControl({
5800
6142
  },
5801
6143
  ref: rootRef,
5802
6144
  children: [
5803
- open ? /* @__PURE__ */ jsx7(
6145
+ open ? /* @__PURE__ */ jsx8(
5804
6146
  VerticalVolumeSlider,
5805
6147
  {
5806
6148
  appearance,
@@ -5808,7 +6150,7 @@ function VolumeControl({
5808
6150
  volume: displayVolume
5809
6151
  }
5810
6152
  ) : null,
5811
- /* @__PURE__ */ jsx7(
6153
+ /* @__PURE__ */ jsx8(
5812
6154
  ChromeButton,
5813
6155
  {
5814
6156
  appearance,
@@ -5819,7 +6161,7 @@ function VolumeControl({
5819
6161
  }
5820
6162
  onToggleMuted();
5821
6163
  },
5822
- children: mutedOrSilent ? /* @__PURE__ */ jsx7(Icon, { path: "M3 6.5h2.2L8.5 4v8L5.2 9.5H3zM10.2 6.2l3.2 3.6M13.4 6.2l-3.2 3.6" }) : /* @__PURE__ */ jsx7(Icon, { path: "M3 6.5h2.2L8.5 4v8L5.2 9.5H3zM10.5 5.5a3 3 0 0 1 0 5" })
6164
+ children: mutedOrSilent ? /* @__PURE__ */ jsx8(Icon, { path: "M3 6.5h2.2L8.5 4v8L5.2 9.5H3zM10.2 6.2l3.2 3.6M13.4 6.2l-3.2 3.6" }) : /* @__PURE__ */ jsx8(Icon, { path: "M3 6.5h2.2L8.5 4v8L5.2 9.5H3zM10.5 5.5a3 3 0 0 1 0 5" })
5823
6165
  }
5824
6166
  )
5825
6167
  ]
@@ -5848,7 +6190,7 @@ function PanoVideoControlsHud({
5848
6190
  const [overlayWidth, setOverlayWidth] = useState4(
5849
6191
  () => overlayElement.clientWidth
5850
6192
  );
5851
- const idleTimerRef = useRef10(0);
6193
+ const idleTimerRef = useRef11(0);
5852
6194
  const barId = useId2();
5853
6195
  const rateMenuId = `${barId}-rate`;
5854
6196
  const variantMenuId = `${barId}-variant`;
@@ -5870,7 +6212,7 @@ function PanoVideoControlsHud({
5870
6212
  },
5871
6213
  [menu, volumeOpen]
5872
6214
  );
5873
- useEffect11(() => {
6215
+ useEffect12(() => {
5874
6216
  if (typeof ResizeObserver === "undefined") {
5875
6217
  return;
5876
6218
  }
@@ -5885,15 +6227,15 @@ function PanoVideoControlsHud({
5885
6227
  observer.disconnect();
5886
6228
  };
5887
6229
  }, [overlayElement]);
5888
- useEffect11(() => {
6230
+ useEffect12(() => {
5889
6231
  if (!compact && menu === "more") {
5890
6232
  setMenu(null);
5891
6233
  }
5892
6234
  }, [compact, menu]);
5893
- useEffect11(() => {
6235
+ useEffect12(() => {
5894
6236
  bumpVisibility(snapshot.playing);
5895
6237
  }, [bumpVisibility, snapshot.playing]);
5896
- useEffect11(() => {
6238
+ useEffect12(() => {
5897
6239
  const root = overlayElement.parentElement;
5898
6240
  if (!root) {
5899
6241
  return;
@@ -5952,7 +6294,7 @@ function PanoVideoControlsHud({
5952
6294
  document.removeEventListener("pointerdown", handlePointerDown, true);
5953
6295
  };
5954
6296
  }, [bumpVisibility, controller, menu, overlayElement, snapshot.playing, volumeOpen]);
5955
- useEffect11(
6297
+ useEffect12(
5956
6298
  () => () => {
5957
6299
  window.clearTimeout(idleTimerRef.current);
5958
6300
  },
@@ -5979,7 +6321,7 @@ function PanoVideoControlsHud({
5979
6321
  let menuNode = null;
5980
6322
  switch (menu) {
5981
6323
  case "rate":
5982
- menuNode = /* @__PURE__ */ jsx7(
6324
+ menuNode = /* @__PURE__ */ jsx8(
5983
6325
  ChromeMenu,
5984
6326
  {
5985
6327
  appearance: resolved,
@@ -5998,7 +6340,7 @@ function PanoVideoControlsHud({
5998
6340
  );
5999
6341
  break;
6000
6342
  case "variant":
6001
- menuNode = /* @__PURE__ */ jsx7(
6343
+ menuNode = /* @__PURE__ */ jsx8(
6002
6344
  ChromeMenu,
6003
6345
  {
6004
6346
  appearance: resolved,
@@ -6017,7 +6359,7 @@ function PanoVideoControlsHud({
6017
6359
  );
6018
6360
  break;
6019
6361
  case "captions":
6020
- menuNode = /* @__PURE__ */ jsx7(
6362
+ menuNode = /* @__PURE__ */ jsx8(
6021
6363
  CaptionsMenu,
6022
6364
  {
6023
6365
  appearance: resolved,
@@ -6041,7 +6383,7 @@ function PanoVideoControlsHud({
6041
6383
  );
6042
6384
  break;
6043
6385
  case "more":
6044
- menuNode = /* @__PURE__ */ jsx7(
6386
+ menuNode = /* @__PURE__ */ jsx8(
6045
6387
  ChromeMenu,
6046
6388
  {
6047
6389
  appearance: resolved,
@@ -6109,7 +6451,7 @@ function PanoVideoControlsHud({
6109
6451
  };
6110
6452
  const rateButton = /* @__PURE__ */ jsxs3("div", { className: "pano-video-menu", "data-pano-video-menu": "rate", children: [
6111
6453
  !compact && menu === "rate" ? menuNode : null,
6112
- /* @__PURE__ */ jsx7(
6454
+ /* @__PURE__ */ jsx8(
6113
6455
  ChromeButton,
6114
6456
  {
6115
6457
  appearance: resolved,
@@ -6117,13 +6459,13 @@ function PanoVideoControlsHud({
6117
6459
  onClick: () => {
6118
6460
  toggleMenu("rate");
6119
6461
  },
6120
- children: /* @__PURE__ */ jsx7("span", { className: "pano-video-chrome-label", id: `${barId}-rate-btn`, children: snapshot.playbackRate === 1 ? "1x" : `${snapshot.playbackRate}x` })
6462
+ children: /* @__PURE__ */ jsx8("span", { className: "pano-video-chrome-label", id: `${barId}-rate-btn`, children: snapshot.playbackRate === 1 ? "1x" : `${snapshot.playbackRate}x` })
6121
6463
  }
6122
6464
  )
6123
6465
  ] });
6124
6466
  const variantButton = canSwitchVariant ? /* @__PURE__ */ jsxs3("div", { className: "pano-video-menu", "data-pano-video-menu": "variant", children: [
6125
6467
  !compact && menu === "variant" ? menuNode : null,
6126
- /* @__PURE__ */ jsx7(
6468
+ /* @__PURE__ */ jsx8(
6127
6469
  ChromeButton,
6128
6470
  {
6129
6471
  appearance: resolved,
@@ -6131,13 +6473,13 @@ function PanoVideoControlsHud({
6131
6473
  onClick: () => {
6132
6474
  toggleMenu("variant");
6133
6475
  },
6134
- children: /* @__PURE__ */ jsx7("span", { className: "pano-video-chrome-label", id: `${barId}-variant-btn`, children: snapshot.variants.find((variant) => variant.id === snapshot.variantId)?.label ?? "Quality" })
6476
+ children: /* @__PURE__ */ jsx8("span", { className: "pano-video-chrome-label", id: `${barId}-variant-btn`, children: snapshot.variants.find((variant) => variant.id === snapshot.variantId)?.label ?? "Quality" })
6135
6477
  }
6136
6478
  )
6137
6479
  ] }) : null;
6138
6480
  const captionsButton = showCaptionsMenu ? /* @__PURE__ */ jsxs3("div", { className: "pano-video-menu", "data-pano-video-menu": "captions", children: [
6139
6481
  !compact && menu === "captions" ? menuNode : null,
6140
- /* @__PURE__ */ jsx7(
6482
+ /* @__PURE__ */ jsx8(
6141
6483
  ChromeButton,
6142
6484
  {
6143
6485
  appearance: resolved,
@@ -6145,7 +6487,7 @@ function PanoVideoControlsHud({
6145
6487
  onClick: () => {
6146
6488
  toggleMenu("captions");
6147
6489
  },
6148
- children: /* @__PURE__ */ jsx7("span", { id: `${barId}-captions-btn`, children: /* @__PURE__ */ jsx7(Icon, { path: "M2.5 4.5h11v7h-11zM5 7.2h2.4M5 9.2h5.5" }) })
6490
+ children: /* @__PURE__ */ jsx8("span", { id: `${barId}-captions-btn`, children: /* @__PURE__ */ jsx8(Icon, { path: "M2.5 4.5h11v7h-11zM5 7.2h2.4M5 9.2h5.5" }) })
6149
6491
  }
6150
6492
  )
6151
6493
  ] }) : null;
@@ -6156,7 +6498,7 @@ function PanoVideoControlsHud({
6156
6498
  "data-pano-video-controls": "",
6157
6499
  style: barStyle,
6158
6500
  children: [
6159
- /* @__PURE__ */ jsx7(
6501
+ /* @__PURE__ */ jsx8(
6160
6502
  ChromeButton,
6161
6503
  {
6162
6504
  appearance: resolved,
@@ -6164,11 +6506,11 @@ function PanoVideoControlsHud({
6164
6506
  onClick: () => {
6165
6507
  controller.togglePlay();
6166
6508
  },
6167
- children: snapshot.playing ? /* @__PURE__ */ jsx7(Icon, { path: "M5 3.5h2.2v9H5zM8.8 3.5H11v9H8.8z" }) : /* @__PURE__ */ jsx7(Icon, { path: "M5 3.2v9.6L13 8z" })
6509
+ children: snapshot.playing ? /* @__PURE__ */ jsx8(Icon, { path: "M5 3.5h2.2v9H5zM8.8 3.5H11v9H8.8z" }) : /* @__PURE__ */ jsx8(Icon, { path: "M5 3.2v9.6L13 8z" })
6168
6510
  }
6169
6511
  ),
6170
- hideTime ? null : /* @__PURE__ */ jsx7("span", { className: "pano-video-time", children: formatMediaTime(snapshot.currentTime) }),
6171
- /* @__PURE__ */ jsx7(
6512
+ hideTime ? null : /* @__PURE__ */ jsx8("span", { className: "pano-video-time", children: formatMediaTime(snapshot.currentTime) }),
6513
+ /* @__PURE__ */ jsx8(
6172
6514
  "input",
6173
6515
  {
6174
6516
  "aria-label": "Seek",
@@ -6190,8 +6532,8 @@ function PanoVideoControlsHud({
6190
6532
  value: duration > 0 ? snapshot.currentTime : 0
6191
6533
  }
6192
6534
  ),
6193
- hideTime ? null : /* @__PURE__ */ jsx7("span", { className: "pano-video-time", children: formatMediaTime(duration) }),
6194
- /* @__PURE__ */ jsx7(
6535
+ hideTime ? null : /* @__PURE__ */ jsx8("span", { className: "pano-video-time", children: formatMediaTime(duration) }),
6536
+ /* @__PURE__ */ jsx8(
6195
6537
  VolumeControl,
6196
6538
  {
6197
6539
  appearance: resolved,
@@ -6209,7 +6551,7 @@ function PanoVideoControlsHud({
6209
6551
  ),
6210
6552
  compact ? /* @__PURE__ */ jsxs3("div", { className: "pano-video-menu", "data-pano-video-menu": "more", children: [
6211
6553
  menu !== null ? menuNode : null,
6212
- /* @__PURE__ */ jsx7(
6554
+ /* @__PURE__ */ jsx8(
6213
6555
  ChromeButton,
6214
6556
  {
6215
6557
  appearance: resolved,
@@ -6218,7 +6560,7 @@ function PanoVideoControlsHud({
6218
6560
  onClick: () => {
6219
6561
  toggleMenu("more");
6220
6562
  },
6221
- children: /* @__PURE__ */ jsx7(Icon, { path: "M3 8a1 1 0 1 0 2 0 1 1 0 1 0-2 0M7 8a1 1 0 1 0 2 0 1 1 0 1 0-2 0M11 8a1 1 0 1 0 2 0 1 1 0 1 0-2 0" })
6563
+ children: /* @__PURE__ */ jsx8(Icon, { path: "M3 8a1 1 0 1 0 2 0 1 1 0 1 0-2 0M7 8a1 1 0 1 0 2 0 1 1 0 1 0-2 0M11 8a1 1 0 1 0 2 0 1 1 0 1 0-2 0" })
6222
6564
  }
6223
6565
  )
6224
6566
  ] }) : /* @__PURE__ */ jsxs3(Fragment, { children: [
@@ -6226,7 +6568,7 @@ function PanoVideoControlsHud({
6226
6568
  variantButton,
6227
6569
  captionsButton
6228
6570
  ] }),
6229
- showFullscreen ? /* @__PURE__ */ jsx7(
6571
+ showFullscreen ? /* @__PURE__ */ jsx8(
6230
6572
  ChromeButton,
6231
6573
  {
6232
6574
  appearance: resolved,
@@ -6234,7 +6576,7 @@ function PanoVideoControlsHud({
6234
6576
  onClick: () => {
6235
6577
  fullscreen?.toggleFullscreen();
6236
6578
  },
6237
- children: fullscreen?.isFullscreen ? /* @__PURE__ */ jsx7(Icon, { path: "M6 3.5H3.5V6M10 3.5h2.5V6M6 12.5H3.5V10M10 12.5h2.5V10" }) : /* @__PURE__ */ jsx7(Icon, { path: "M3.5 6V3.5H6M10 3.5h2.5V6M3.5 10v2.5H6M10 12.5h2.5V10" })
6579
+ children: fullscreen?.isFullscreen ? /* @__PURE__ */ jsx8(Icon, { path: "M6 3.5H3.5V6M10 3.5h2.5V6M6 12.5H3.5V10M10 12.5h2.5V10" }) : /* @__PURE__ */ jsx8(Icon, { path: "M3.5 6V3.5H6M10 3.5h2.5V6M3.5 10v2.5H6M10 12.5h2.5V10" })
6238
6580
  }
6239
6581
  ) : null
6240
6582
  ]
@@ -6243,7 +6585,7 @@ function PanoVideoControlsHud({
6243
6585
  }
6244
6586
  function PanoVideoControls({ appearance }) {
6245
6587
  useClaimPanoVideoControls();
6246
- const host = useContext13(PanoVideoHostContext);
6588
+ const host = useContext14(PanoVideoHostContext);
6247
6589
  if (host && appearance) {
6248
6590
  host.controls = appearance;
6249
6591
  }
@@ -6251,7 +6593,7 @@ function PanoVideoControls({ appearance }) {
6251
6593
  }
6252
6594
 
6253
6595
  // src/video/pano-video-chrome-bridge.tsx
6254
- import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
6596
+ import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
6255
6597
  function PanoVideoChromeBridge({
6256
6598
  fullscreen,
6257
6599
  host,
@@ -6267,7 +6609,7 @@ function PanoVideoChromeBridge({
6267
6609
  }
6268
6610
  const showDefaultControls = host.controller !== null && host.controls !== false && host.controlClaims === 0;
6269
6611
  return /* @__PURE__ */ jsxs4(Fragment2, { children: [
6270
- showDefaultControls ? /* @__PURE__ */ jsx8(
6612
+ showDefaultControls ? /* @__PURE__ */ jsx9(
6271
6613
  PanoVideoControlsHud,
6272
6614
  {
6273
6615
  appearance: typeof host.controls === "object" ? host.controls : void 0,
@@ -6276,7 +6618,7 @@ function PanoVideoChromeBridge({
6276
6618
  overlayElement
6277
6619
  }
6278
6620
  ) : null,
6279
- host.captions !== false && host.controller ? /* @__PURE__ */ jsx8(PanoVideoCaptionsOverlay, { controller: host.controller }) : null
6621
+ host.captions !== false && host.controller ? /* @__PURE__ */ jsx9(PanoVideoCaptionsOverlay, { controller: host.controller }) : null
6280
6622
  ] });
6281
6623
  }
6282
6624
 
@@ -6284,8 +6626,8 @@ function PanoVideoChromeBridge({
6284
6626
  import { useSyncExternalStore as useSyncExternalStore5 } from "react";
6285
6627
 
6286
6628
  // src/webvr/host.ts
6287
- import { createContext as createContext12 } from "react";
6288
- var WebVRRuntimeContext = createContext12(null);
6629
+ import { createContext as createContext14 } from "react";
6630
+ var WebVRRuntimeContext = createContext14(null);
6289
6631
  function createWebVRHost() {
6290
6632
  return {
6291
6633
  controller: null,
@@ -6429,7 +6771,7 @@ function clamp2(value, min, max) {
6429
6771
  }
6430
6772
 
6431
6773
  // src/webvr/chrome.tsx
6432
- import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
6774
+ import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
6433
6775
  function resolveAppearance(value) {
6434
6776
  return {
6435
6777
  ...DEFAULT_WEBVR_CHROME_APPEARANCE,
@@ -6441,7 +6783,7 @@ function ChromeButton2({
6441
6783
  children,
6442
6784
  onClick
6443
6785
  }) {
6444
- return /* @__PURE__ */ jsx9(
6786
+ return /* @__PURE__ */ jsx10(
6445
6787
  "button",
6446
6788
  {
6447
6789
  className: "pano-webvr-button",
@@ -6486,11 +6828,11 @@ function SetupPanel({
6486
6828
  role: "dialog",
6487
6829
  style: panelStyle,
6488
6830
  children: [
6489
- /* @__PURE__ */ jsx9("h2", { className: "pano-webvr-setup-title", children: appearance.setupTitle ?? "MobileVR Setup" }),
6831
+ /* @__PURE__ */ jsx10("h2", { className: "pano-webvr-setup-title", children: appearance.setupTitle ?? "MobileVR Setup" }),
6490
6832
  /* @__PURE__ */ jsxs5("label", { className: "pano-webvr-setup-field", children: [
6491
6833
  "Screen size (inch)",
6492
6834
  /* @__PURE__ */ jsxs5("div", { className: "pano-webvr-setup-row", children: [
6493
- /* @__PURE__ */ jsx9(
6835
+ /* @__PURE__ */ jsx10(
6494
6836
  "button",
6495
6837
  {
6496
6838
  "aria-label": "Decrease screen size",
@@ -6502,8 +6844,8 @@ function SetupPanel({
6502
6844
  children: "\u2039"
6503
6845
  }
6504
6846
  ),
6505
- /* @__PURE__ */ jsx9("strong", { className: "pano-webvr-setup-value", children: settings.screensize === "auto" ? "Auto" : settings.screensize.toFixed(1) }),
6506
- /* @__PURE__ */ jsx9(
6847
+ /* @__PURE__ */ jsx10("strong", { className: "pano-webvr-setup-value", children: settings.screensize === "auto" ? "Auto" : settings.screensize.toFixed(1) }),
6848
+ /* @__PURE__ */ jsx10(
6507
6849
  "button",
6508
6850
  {
6509
6851
  "aria-label": "Increase screen size",
@@ -6518,9 +6860,9 @@ function SetupPanel({
6518
6860
  ] })
6519
6861
  ] }),
6520
6862
  /* @__PURE__ */ jsxs5("fieldset", { className: "pano-webvr-setup-fieldset", children: [
6521
- /* @__PURE__ */ jsx9("legend", { className: "pano-webvr-setup-legend", children: "VR headset preset" }),
6863
+ /* @__PURE__ */ jsx10("legend", { className: "pano-webvr-setup-legend", children: "VR headset preset" }),
6522
6864
  /* @__PURE__ */ jsxs5("div", { className: "pano-webvr-setup-row", children: [
6523
- /* @__PURE__ */ jsx9(
6865
+ /* @__PURE__ */ jsx10(
6524
6866
  "button",
6525
6867
  {
6526
6868
  "aria-label": "Previous headset preset",
@@ -6530,8 +6872,8 @@ function SetupPanel({
6530
6872
  children: "\u2039"
6531
6873
  }
6532
6874
  ),
6533
- /* @__PURE__ */ jsx9("strong", { className: "pano-webvr-setup-value-wide", children: WEBVR_PROFILES[settings.profileId].label }),
6534
- /* @__PURE__ */ jsx9(
6875
+ /* @__PURE__ */ jsx10("strong", { className: "pano-webvr-setup-value-wide", children: WEBVR_PROFILES[settings.profileId].label }),
6876
+ /* @__PURE__ */ jsx10(
6535
6877
  "button",
6536
6878
  {
6537
6879
  "aria-label": "Next headset preset",
@@ -6543,7 +6885,7 @@ function SetupPanel({
6543
6885
  )
6544
6886
  ] })
6545
6887
  ] }),
6546
- /* @__PURE__ */ jsx9(
6888
+ /* @__PURE__ */ jsx10(
6547
6889
  ChromeButton2,
6548
6890
  {
6549
6891
  appearance,
@@ -6567,8 +6909,8 @@ function WebVRChromeBridge({ host }) {
6567
6909
  }
6568
6910
  const appearance = resolveAppearance(chrome);
6569
6911
  return /* @__PURE__ */ jsxs5(Fragment3, { children: [
6570
- /* @__PURE__ */ jsx9("div", { className: "pano-webvr-toolbar", children: mode ? /* @__PURE__ */ jsxs5("div", { className: "pano-webvr-toolbar-actions", children: [
6571
- mode !== "webxr" ? /* @__PURE__ */ jsx9(
6912
+ /* @__PURE__ */ jsx10("div", { className: "pano-webvr-toolbar", children: mode ? /* @__PURE__ */ jsxs5("div", { className: "pano-webvr-toolbar-actions", children: [
6913
+ mode !== "webxr" ? /* @__PURE__ */ jsx10(
6572
6914
  ChromeButton2,
6573
6915
  {
6574
6916
  appearance,
@@ -6576,7 +6918,7 @@ function WebVRChromeBridge({ host }) {
6576
6918
  children: "VR Setup"
6577
6919
  }
6578
6920
  ) : null,
6579
- /* @__PURE__ */ jsx9(
6921
+ /* @__PURE__ */ jsx10(
6580
6922
  ChromeButton2,
6581
6923
  {
6582
6924
  appearance,
@@ -6584,7 +6926,7 @@ function WebVRChromeBridge({ host }) {
6584
6926
  children: "Exit VR"
6585
6927
  }
6586
6928
  )
6587
- ] }) : /* @__PURE__ */ jsx9(
6929
+ ] }) : /* @__PURE__ */ jsx10(
6588
6930
  ChromeButton2,
6589
6931
  {
6590
6932
  appearance,
@@ -6592,7 +6934,7 @@ function WebVRChromeBridge({ host }) {
6592
6934
  children: available ? "Enter VR" : "VR unavailable"
6593
6935
  }
6594
6936
  ) }),
6595
- mode === "fake" ? /* @__PURE__ */ jsx9(
6937
+ mode === "fake" ? /* @__PURE__ */ jsx10(
6596
6938
  "p",
6597
6939
  {
6598
6940
  className: "pano-webvr-hint",
@@ -6600,7 +6942,7 @@ function WebVRChromeBridge({ host }) {
6600
6942
  children: "Simulated VR Mode \xB7 Click the view to lock the mouse, then move to look around. Use a headset or phone for real VR."
6601
6943
  }
6602
6944
  ) : null,
6603
- setupOpen ? /* @__PURE__ */ jsx9(
6945
+ setupOpen ? /* @__PURE__ */ jsx10(
6604
6946
  SetupPanel,
6605
6947
  {
6606
6948
  appearance,
@@ -6640,12 +6982,12 @@ function projectStereoHtmlPosition(el, camera, size, eye) {
6640
6982
  // src/webvr/xr-origin.tsx
6641
6983
  import { useFrame as useFrame5, useThree as useThree8 } from "@react-three/fiber";
6642
6984
  import { useXR as useXR2, XROrigin } from "@react-three/xr";
6643
- import { useRef as useRef11 } from "react";
6985
+ import { useRef as useRef12 } from "react";
6644
6986
  import { Vector3 as Vector34 } from "three";
6645
- import { jsx as jsx10 } from "react/jsx-runtime";
6987
+ import { jsx as jsx11 } from "react/jsx-runtime";
6646
6988
  function PanoramaXROrigin() {
6647
- const originRef = useRef11(null);
6648
- const localHeadPositionRef = useRef11(new Vector34());
6989
+ const originRef = useRef12(null);
6990
+ const localHeadPositionRef = useRef12(new Vector34());
6649
6991
  const session2 = useXR2((state) => state.session);
6650
6992
  const gl = useThree8((state) => state.gl);
6651
6993
  useFrame5(() => {
@@ -6658,11 +7000,11 @@ function PanoramaXROrigin() {
6658
7000
  origin.position.copy(localHeadPositionRef.current).multiplyScalar(-1);
6659
7001
  origin.updateMatrixWorld();
6660
7002
  }, -100);
6661
- return /* @__PURE__ */ jsx10(XROrigin, { ref: originRef });
7003
+ return /* @__PURE__ */ jsx11(XROrigin, { ref: originRef });
6662
7004
  }
6663
7005
 
6664
7006
  // src/pano-viewer.tsx
6665
- import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
7007
+ import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
6666
7008
  var DEFAULT_VIEW = {
6667
7009
  yaw: 0,
6668
7010
  pitch: 0,
@@ -6707,10 +7049,10 @@ function PanoCursorTree({
6707
7049
  if (!cursors) {
6708
7050
  return children;
6709
7051
  }
6710
- return /* @__PURE__ */ jsx11(PanoCursorController, { cursors, children });
7052
+ return /* @__PURE__ */ jsx12(PanoCursorController, { cursors, children });
6711
7053
  }
6712
7054
  function PanoVideoHostReset() {
6713
- const host = useContext14(PanoVideoHostContext);
7055
+ const host = useContext15(PanoVideoHostContext);
6714
7056
  if (host) {
6715
7057
  host.controlClaims = 0;
6716
7058
  }
@@ -6723,14 +7065,14 @@ function DefaultControlChannels({
6723
7065
  keyboardChannel,
6724
7066
  fovSpeed
6725
7067
  }) {
6726
- const claims = useContext14(ControlClaimsContext);
7068
+ const claims = useContext15(ControlClaimsContext);
6727
7069
  if (!claims) {
6728
7070
  return null;
6729
7071
  }
6730
7072
  return /* @__PURE__ */ jsxs6(DefaultControlChannelContext.Provider, { value: true, children: [
6731
- userControlsEnabled && mouseChannel.mount && claims.mouse === 0 ? /* @__PURE__ */ jsx11(MouseControls, { ...mouseChannel.props, fovSpeed }) : null,
6732
- userControlsEnabled && touchChannel.mount && claims.touch === 0 ? /* @__PURE__ */ jsx11(TouchControls, { ...touchChannel.props }) : null,
6733
- userControlsEnabled && keyboardChannel.mount && claims.keyboard === 0 ? /* @__PURE__ */ jsx11(
7073
+ userControlsEnabled && mouseChannel.mount && claims.mouse === 0 ? /* @__PURE__ */ jsx12(MouseControls, { ...mouseChannel.props, fovSpeed }) : null,
7074
+ userControlsEnabled && touchChannel.mount && claims.touch === 0 ? /* @__PURE__ */ jsx12(TouchControls, { ...touchChannel.props }) : null,
7075
+ userControlsEnabled && keyboardChannel.mount && claims.keyboard === 0 ? /* @__PURE__ */ jsx12(
6734
7076
  KeyboardControls,
6735
7077
  {
6736
7078
  ...keyboardChannel.props,
@@ -6748,6 +7090,7 @@ var PanoViewer = forwardRef2(
6748
7090
  controls = true,
6749
7091
  cursors,
6750
7092
  contextMenu = true,
7093
+ mediaActivation,
6751
7094
  onViewChange,
6752
7095
  onPanoramaClick,
6753
7096
  onPanoramaDoubleClick,
@@ -6757,10 +7100,11 @@ var PanoViewer = forwardRef2(
6757
7100
  "aria-label": ariaLabel = "Panorama viewer",
6758
7101
  ...divProps
6759
7102
  }, ref) {
6760
- const rootRef = useRef12(null);
6761
- const controlsRef = useRef12(null);
7103
+ const rootRef = useRef13(null);
7104
+ const controlsRef = useRef13(null);
6762
7105
  const eventBus = useMemo7(() => createPanoEventBus(), []);
6763
7106
  const { controls: hotspotAccessibilityControls, registry } = useHotspotAccessibilityLayer();
7107
+ const hotspotTargetRegistry = useMemo7(() => createHotspotTargetRegistry(), []);
6764
7108
  const { api: contextMenuOverlayApi, overlay: contextMenuOverlay } = usePanoContextMenuOverlay();
6765
7109
  const { api: chromeOverlayApi, setOverlayNode, overlayElement } = usePanoChromeOverlay();
6766
7110
  const videoHost = useMemo7(() => createPanoVideoHost(), []);
@@ -6768,6 +7112,17 @@ var PanoViewer = forwardRef2(
6768
7112
  const webVRHost = useMemo7(() => createWebVRHost(), []);
6769
7113
  const scenesHost = useMemo7(() => createScenesHost(), []);
6770
7114
  const bgmHost = useMemo7(() => createBackgroundAudioHost(), []);
7115
+ const mediaActivationHost = useMemo7(() => createPanoMediaActivationHost(), []);
7116
+ const mediaActivationOptions = useMemo7(
7117
+ () => mediaActivation === false ? null : mediaActivation ?? {},
7118
+ [mediaActivation]
7119
+ );
7120
+ const mediaActivationRevision = useSyncExternalStore6(
7121
+ (onStoreChange) => subscribePanoMediaActivation(mediaActivationHost, onStoreChange),
7122
+ () => getPanoMediaActivationRevision(mediaActivationHost),
7123
+ () => getPanoMediaActivationRevision(mediaActivationHost)
7124
+ );
7125
+ const [mediaActivated, setMediaActivated] = useState5(false);
6771
7126
  const stereoView = useMemo7(() => createWebVRStereoView(), []);
6772
7127
  const xrStore = useMemo7(
6773
7128
  () => createXRStore({
@@ -6785,7 +7140,33 @@ var PanoViewer = forwardRef2(
6785
7140
  }),
6786
7141
  []
6787
7142
  );
6788
- const fallbackViewRef = useRef12(DEFAULT_VIEW);
7143
+ const mediaActivationControls = useMemo7(
7144
+ () => ({
7145
+ resumeAudio: () => resumePanoAudio(),
7146
+ playVideo: async ({ unmute = false } = {}) => {
7147
+ const controller = videoHost.controller;
7148
+ if (!controller) {
7149
+ return false;
7150
+ }
7151
+ if (unmute) {
7152
+ controller.setMuted(false);
7153
+ }
7154
+ await controller.play();
7155
+ return !controller.getSnapshot().blocked;
7156
+ },
7157
+ playBackgroundAudio: () => bgmHost.controller?.play() ?? false
7158
+ }),
7159
+ [bgmHost, videoHost]
7160
+ );
7161
+ const activateMedia = useCallback6(() => {
7162
+ setMediaActivated(true);
7163
+ const resume = mediaActivationControls.resumeAudio();
7164
+ mediaActivationOptions?.onActivate?.(mediaActivationControls);
7165
+ return resume;
7166
+ }, [mediaActivationControls, mediaActivationOptions]);
7167
+ const hasMediaActivationIntent = mediaActivationRevision >= 0 && hasPanoMediaActivationIntent(mediaActivationHost);
7168
+ const shouldShowMediaActivation = mediaActivationOptions !== null && hasMediaActivationIntent && !mediaActivated;
7169
+ const fallbackViewRef = useRef13(DEFAULT_VIEW);
6789
7170
  const normalizedMinFov = Math.max(1, Math.min(minFov, maxFov - 1));
6790
7171
  const normalizedMaxFov = Math.min(
6791
7172
  179,
@@ -6888,7 +7269,7 @@ var PanoViewer = forwardRef2(
6888
7269
  await requestElementFullscreen(root);
6889
7270
  }, []);
6890
7271
  const [isViewerFullscreen, setIsViewerFullscreen] = useState5(false);
6891
- useEffect12(() => {
7272
+ useEffect13(() => {
6892
7273
  if (typeof document === "undefined") {
6893
7274
  return;
6894
7275
  }
@@ -6906,7 +7287,7 @@ var PanoViewer = forwardRef2(
6906
7287
  syncFullscreen();
6907
7288
  return subscribeFullscreenChange(syncFullscreen);
6908
7289
  }, []);
6909
- useEffect12(() => {
7290
+ useEffect13(() => {
6910
7291
  const root = rootRef.current;
6911
7292
  if (!root) {
6912
7293
  return;
@@ -6943,10 +7324,10 @@ var PanoViewer = forwardRef2(
6943
7324
  const [legacyAutoRotate, setLegacyAutoRotate] = useState5(
6944
7325
  legacyAutoRotateOptions.autoRotate ?? false
6945
7326
  );
6946
- useEffect12(() => {
7327
+ useEffect13(() => {
6947
7328
  setLegacyAutoRotate(legacyAutoRotateOptions.autoRotate ?? false);
6948
7329
  }, [legacyAutoRotateOptions.autoRotate]);
6949
- const isFullscreenRef = useRef12(false);
7330
+ const isFullscreenRef = useRef13(false);
6950
7331
  isFullscreenRef.current = isViewerFullscreen;
6951
7332
  useImperativeHandle2(
6952
7333
  ref,
@@ -6959,6 +7340,14 @@ var PanoViewer = forwardRef2(
6959
7340
  reset: () => {
6960
7341
  controlsRef.current?.reset();
6961
7342
  },
7343
+ lookTo: (position, options) => controlsRef.current?.lookTo(position, options) ?? Promise.resolve({ status: "cancelled" }),
7344
+ moveTo: (position, options) => controlsRef.current?.moveTo(position, options) ?? Promise.resolve({ status: "cancelled" }),
7345
+ zoomTo: (fov, options) => controlsRef.current?.zoomTo(fov, options) ?? Promise.resolve({ status: "cancelled" }),
7346
+ lookToHotspot: (id, options) => {
7347
+ const position = hotspotTargetRegistry.getPosition(id);
7348
+ return position ? controlsRef.current?.lookTo(position, options) ?? Promise.resolve({ status: "cancelled" }) : Promise.resolve({ status: "not-found" });
7349
+ },
7350
+ activateMedia,
6962
7351
  // -- Fullscreen --
6963
7352
  enterFullscreen,
6964
7353
  exitFullscreen,
@@ -7011,9 +7400,11 @@ var PanoViewer = forwardRef2(
7011
7400
  }),
7012
7401
  [
7013
7402
  bgmHost,
7403
+ activateMedia,
7014
7404
  enterFullscreen,
7015
7405
  exitFullscreen,
7016
7406
  scenesHost,
7407
+ hotspotTargetRegistry,
7017
7408
  toggleFullscreen,
7018
7409
  videoHost,
7019
7410
  webVRHost
@@ -7037,7 +7428,7 @@ var PanoViewer = forwardRef2(
7037
7428
  "aria-label": ariaLabel,
7038
7429
  style: rootStyle,
7039
7430
  children: [
7040
- /* @__PURE__ */ jsx11(
7431
+ /* @__PURE__ */ jsx12(
7041
7432
  Canvas,
7042
7433
  {
7043
7434
  "aria-label": `${ariaLabel} canvas`,
@@ -7059,23 +7450,23 @@ var PanoViewer = forwardRef2(
7059
7450
  ...DEFAULT_CANVAS_STYLE,
7060
7451
  touchAction: userControlsEnabled ? "none" : "auto"
7061
7452
  },
7062
- children: /* @__PURE__ */ jsx11(XR, { store: xrStore, children: /* @__PURE__ */ jsxs6(
7453
+ children: /* @__PURE__ */ jsx12(XR, { store: xrStore, children: /* @__PURE__ */ jsxs6(
7063
7454
  WebVRRuntimeContext.Provider,
7064
7455
  {
7065
7456
  value: { host: webVRHost, xrStore, stereoView },
7066
7457
  children: [
7067
- /* @__PURE__ */ jsx11(PanoramaXROrigin, {}),
7068
- /* @__PURE__ */ jsx11(HotspotAccessibilityContext.Provider, { value: registry, children: /* @__PURE__ */ jsx11(PanoEventBusContext.Provider, { value: eventBus, children: /* @__PURE__ */ jsx11(PanoCursorTree, { cursors: resolvedCursors, children: /* @__PURE__ */ jsx11(PanoramaViewContext.Provider, { value: controlsRef, children: /* @__PURE__ */ jsx11(
7458
+ /* @__PURE__ */ jsx12(PanoramaXROrigin, {}),
7459
+ /* @__PURE__ */ jsx12(HotspotAccessibilityContext.Provider, { value: registry, children: /* @__PURE__ */ jsx12(HotspotTargetRegistryContext.Provider, { value: hotspotTargetRegistry, children: /* @__PURE__ */ jsx12(PanoEventBusContext.Provider, { value: eventBus, children: /* @__PURE__ */ jsx12(PanoCursorTree, { cursors: resolvedCursors, children: /* @__PURE__ */ jsx12(PanoramaViewContext.Provider, { value: controlsRef, children: /* @__PURE__ */ jsx12(
7069
7460
  PanoContextMenuOverlayContext.Provider,
7070
7461
  {
7071
7462
  value: contextMenuOverlayApi,
7072
- children: /* @__PURE__ */ jsx11(PanoChromeOverlayContext.Provider, { value: chromeOverlayApi, children: /* @__PURE__ */ jsx11(PanoVideoHostContext.Provider, { value: videoHost, children: /* @__PURE__ */ jsx11(PanoFilterHostContext.Provider, { value: filterHost, children: /* @__PURE__ */ jsx11(
7463
+ children: /* @__PURE__ */ jsx12(PanoChromeOverlayContext.Provider, { value: chromeOverlayApi, children: /* @__PURE__ */ jsx12(PanoVideoHostContext.Provider, { value: videoHost, children: /* @__PURE__ */ jsx12(PanoFilterHostContext.Provider, { value: filterHost, children: /* @__PURE__ */ jsx12(
7073
7464
  PanoContextMenuActionsContext.Provider,
7074
7465
  {
7075
7466
  value: contextMenuActions,
7076
- children: /* @__PURE__ */ jsx11(ScenesHostContext.Provider, { value: scenesHost, children: /* @__PURE__ */ jsxs6(BackgroundAudioHostContext.Provider, { value: bgmHost, children: [
7077
- /* @__PURE__ */ jsx11(PanoVideoHostReset, {}),
7078
- /* @__PURE__ */ jsx11(
7467
+ children: /* @__PURE__ */ jsx12(ScenesHostContext.Provider, { value: scenesHost, children: /* @__PURE__ */ jsx12(BackgroundAudioHostContext.Provider, { value: bgmHost, children: /* @__PURE__ */ jsxs6(PanoMediaActivationHostContext.Provider, { value: mediaActivationHost, children: [
7468
+ /* @__PURE__ */ jsx12(PanoVideoHostReset, {}),
7469
+ /* @__PURE__ */ jsx12(
7079
7470
  PanoramaViewRuntime,
7080
7471
  {
7081
7472
  ref: controlsRef,
@@ -7086,7 +7477,7 @@ var PanoViewer = forwardRef2(
7086
7477
  options: controlOptions
7087
7478
  }
7088
7479
  ),
7089
- (onViewChange || onPanoramaClick || onPanoramaDoubleClick || onPanoramaPointerMove) && /* @__PURE__ */ jsx11(
7480
+ (onViewChange || onPanoramaClick || onPanoramaDoubleClick || onPanoramaPointerMove) && /* @__PURE__ */ jsx12(
7090
7481
  PanoEvents,
7091
7482
  {
7092
7483
  onViewChange,
@@ -7095,18 +7486,18 @@ var PanoViewer = forwardRef2(
7095
7486
  onPointerMove: onPanoramaPointerMove
7096
7487
  }
7097
7488
  ),
7098
- /* @__PURE__ */ jsx11(
7489
+ /* @__PURE__ */ jsx12(
7099
7490
  AutoRotate,
7100
7491
  {
7101
7492
  enabled: legacyAutoRotate,
7102
7493
  speed: legacyAutoRotateOptions.autoRotateSpeed
7103
7494
  }
7104
7495
  ),
7105
- /* @__PURE__ */ jsx11(PanoramaEventSurface, {}),
7106
- contextMenuChannel.mount ? /* @__PURE__ */ jsx11(PanoContextMenu, { ...contextMenuChannel.props }) : null,
7496
+ /* @__PURE__ */ jsx12(PanoramaEventSurface, {}),
7497
+ contextMenuChannel.mount ? /* @__PURE__ */ jsx12(PanoContextMenu, { ...contextMenuChannel.props }) : null,
7107
7498
  /* @__PURE__ */ jsxs6(ControlClaimsContext.Provider, { value: controlClaims, children: [
7108
7499
  children,
7109
- /* @__PURE__ */ jsx11(
7500
+ /* @__PURE__ */ jsx12(
7110
7501
  DefaultControlChannels,
7111
7502
  {
7112
7503
  fovSpeed: controlOptions.fovSpeed,
@@ -7117,11 +7508,11 @@ var PanoViewer = forwardRef2(
7117
7508
  }
7118
7509
  )
7119
7510
  ] })
7120
- ] }) })
7511
+ ] }) }) })
7121
7512
  }
7122
7513
  ) }) }) })
7123
7514
  }
7124
- ) }) }) }) })
7515
+ ) }) }) }) }) })
7125
7516
  ]
7126
7517
  }
7127
7518
  ) })
@@ -7134,7 +7525,7 @@ var PanoViewer = forwardRef2(
7134
7525
  "data-pano-chrome-overlay": "",
7135
7526
  ref: setOverlayNode,
7136
7527
  children: [
7137
- /* @__PURE__ */ jsx11(
7528
+ /* @__PURE__ */ jsx12(
7138
7529
  PanoVideoChromeBridge,
7139
7530
  {
7140
7531
  fullscreen: contextMenuActions,
@@ -7142,115 +7533,29 @@ var PanoViewer = forwardRef2(
7142
7533
  overlayElement
7143
7534
  }
7144
7535
  ),
7145
- /* @__PURE__ */ jsx11(WebVRChromeBridge, { host: webVRHost })
7536
+ /* @__PURE__ */ jsx12(WebVRChromeBridge, { host: webVRHost })
7146
7537
  ]
7147
7538
  }
7148
- ),
7149
- contextMenuOverlay,
7150
- hotspotAccessibilityControls
7151
- ]
7152
- }
7153
- );
7154
- }
7155
- );
7156
-
7157
- // src/background-audio.tsx
7158
- import { useContext as useContext15, useEffect as useEffect13, useMemo as useMemo8, useRef as useRef13, useState as useState6 } from "react";
7159
-
7160
- // src/audio/howl.ts
7161
- var import_howler = __toESM(require_howler());
7162
- import_howler.Howler.autoUnlock = true;
7163
- function sourceList(src) {
7164
- if (src == null) {
7165
- return [];
7166
- }
7167
- if (typeof src === "string") {
7168
- return src ? [src] : [];
7169
- }
7170
- return src.filter((item) => Boolean(item));
7171
- }
7172
- function createUnlockingHowl({
7173
- src,
7174
- loop,
7175
- crossOrigin,
7176
- isActive,
7177
- shouldRetryPlay,
7178
- onEnded,
7179
- onPlay,
7180
- onPause,
7181
- onLoadError,
7182
- onPlayError
7183
- }) {
7184
- let disposed = false;
7185
- let blockedNotified = false;
7186
- const unlockListeners = [];
7187
- const removeUnlockListeners = () => {
7188
- for (const { type, listener } of unlockListeners) {
7189
- window.removeEventListener(type, listener, true);
7190
- }
7191
- unlockListeners.length = 0;
7192
- };
7193
- const instance = new import_howler.Howl({
7194
- src: [...src],
7195
- html5: false,
7196
- preload: true,
7197
- loop,
7198
- xhr: crossOrigin === "use-credentials" ? { withCredentials: true } : void 0,
7199
- onend: () => {
7200
- if (disposed || !isActive() || instance.loop()) {
7201
- return;
7202
- }
7203
- onEnded?.();
7204
- },
7205
- onplay: () => {
7206
- if (!disposed && isActive()) {
7207
- onPlay?.();
7208
- }
7209
- },
7210
- onpause: () => {
7211
- if (!disposed && isActive()) {
7212
- onPause?.();
7213
- }
7214
- },
7215
- onloaderror: (_soundId, error) => {
7216
- if (!disposed && isActive()) {
7217
- onLoadError?.(error);
7218
- }
7219
- },
7220
- onplayerror: (_soundId, error) => {
7221
- if (disposed || !isActive()) {
7222
- return;
7223
- }
7224
- if (!blockedNotified) {
7225
- blockedNotified = true;
7226
- onPlayError?.(error);
7227
- }
7228
- const retry = () => {
7229
- removeUnlockListeners();
7230
- if (!disposed && isActive() && shouldRetryPlay()) {
7231
- void import_howler.Howler.ctx?.resume();
7232
- instance.play();
7233
- }
7234
- };
7235
- removeUnlockListeners();
7236
- unlockListeners.push({ type: "pointerdown", listener: retry });
7237
- unlockListeners.push({ type: "keydown", listener: retry });
7238
- window.addEventListener("pointerdown", retry, { capture: true });
7239
- window.addEventListener("keydown", retry, { capture: true });
7240
- }
7241
- });
7242
- return {
7243
- howl: instance,
7244
- dispose: () => {
7245
- if (disposed) {
7246
- return;
7539
+ ),
7540
+ contextMenuOverlay,
7541
+ hotspotAccessibilityControls,
7542
+ shouldShowMediaActivation ? /* @__PURE__ */ jsx12(
7543
+ PanoMediaActivationOverlay,
7544
+ {
7545
+ ...mediaActivationOptions,
7546
+ onActivate: () => {
7547
+ void activateMedia();
7548
+ }
7549
+ }
7550
+ ) : null
7551
+ ]
7247
7552
  }
7248
- disposed = true;
7249
- removeUnlockListeners();
7250
- instance.unload();
7251
- }
7252
- };
7253
- }
7553
+ );
7554
+ }
7555
+ );
7556
+
7557
+ // src/background-audio.tsx
7558
+ import { useContext as useContext16, useEffect as useEffect14, useMemo as useMemo8, useRef as useRef14, useState as useState6 } from "react";
7254
7559
 
7255
7560
  // src/hotspot/audio-spatial.ts
7256
7561
  import { MathUtils as MathUtils3, Vector3 as Vector35 } from "three";
@@ -7338,7 +7643,7 @@ function BackgroundAudio({
7338
7643
  onEnded,
7339
7644
  onError
7340
7645
  }) {
7341
- const controlsRef = useContext15(PanoramaViewContext);
7646
+ const controlsRef = useContext16(PanoramaViewContext);
7342
7647
  if (!controlsRef) {
7343
7648
  throw new Error("<BackgroundAudio> must be rendered inside <PanoViewer>.");
7344
7649
  }
@@ -7346,22 +7651,23 @@ function BackgroundAudio({
7346
7651
  const [internalPlaying, setInternalPlaying] = useState6(defaultPlaying);
7347
7652
  const playing = isControlled ? controlledPlaying : internalPlaying;
7348
7653
  const urls = resolveBackgroundAudioUrls(src, sources, sceneId);
7654
+ usePanoMediaActivationIntent(playing && urls.length > 0);
7349
7655
  const trackKey = urls.join("\0");
7350
- const currentRef = useRef13(null);
7351
- const outgoingRef = useRef13([]);
7352
- const fadingInRef = useRef13(false);
7353
- const isFirstTrackRef = useRef13(true);
7354
- const playingRef = useRef13(playing);
7355
- const loopRef = useRef13(loop);
7356
- const mutedRef = useRef13(muted);
7357
- const volumeRef = useRef13(volume);
7358
- const mutedPropRef = useRef13(muted);
7359
- const volumePropRef = useRef13(volume);
7360
- const fadeMsRef = useRef13(resolveFadeMs(fadeMs));
7361
- const onPlaybackStateChangeRef = useRef13(onPlaybackStateChange);
7362
- const onPlaybackErrorRef = useRef13(onPlaybackError);
7363
- const onEndedRef = useRef13(onEnded);
7364
- const onErrorRef = useRef13(onError);
7656
+ const currentRef = useRef14(null);
7657
+ const outgoingRef = useRef14([]);
7658
+ const fadingInRef = useRef14(false);
7659
+ const isFirstTrackRef = useRef14(true);
7660
+ const playingRef = useRef14(playing);
7661
+ const loopRef = useRef14(loop);
7662
+ const mutedRef = useRef14(muted);
7663
+ const volumeRef = useRef14(volume);
7664
+ const mutedPropRef = useRef14(muted);
7665
+ const volumePropRef = useRef14(volume);
7666
+ const fadeMsRef = useRef14(resolveFadeMs(fadeMs));
7667
+ const onPlaybackStateChangeRef = useRef14(onPlaybackStateChange);
7668
+ const onPlaybackErrorRef = useRef14(onPlaybackError);
7669
+ const onEndedRef = useRef14(onEnded);
7670
+ const onErrorRef = useRef14(onError);
7365
7671
  playingRef.current = playing;
7366
7672
  loopRef.current = loop;
7367
7673
  fadeMsRef.current = resolveFadeMs(fadeMs);
@@ -7377,7 +7683,7 @@ function BackgroundAudio({
7377
7683
  onPlaybackErrorRef.current = onPlaybackError;
7378
7684
  onEndedRef.current = onEnded;
7379
7685
  onErrorRef.current = onError;
7380
- const snapshotRef = useRef13({
7686
+ const snapshotRef = useRef14({
7381
7687
  ready: false,
7382
7688
  playing: false,
7383
7689
  blocked: false,
@@ -7385,7 +7691,7 @@ function BackgroundAudio({
7385
7691
  muted,
7386
7692
  volume
7387
7693
  });
7388
- const snapshotListenersRef = useRef13(/* @__PURE__ */ new Set());
7694
+ const snapshotListenersRef = useRef14(/* @__PURE__ */ new Set());
7389
7695
  const notifySnapshot = (patch) => {
7390
7696
  const prev = snapshotRef.current;
7391
7697
  snapshotRef.current = { ...prev, ...patch };
@@ -7393,7 +7699,7 @@ function BackgroundAudio({
7393
7699
  listener();
7394
7700
  }
7395
7701
  };
7396
- const isControlledRef = useRef13(isControlled);
7702
+ const isControlledRef = useRef14(isControlled);
7397
7703
  isControlledRef.current = isControlled;
7398
7704
  const controller = useMemo8(
7399
7705
  () => ({
@@ -7406,9 +7712,11 @@ function BackgroundAudio({
7406
7712
  getSnapshot: () => snapshotRef.current,
7407
7713
  play: () => {
7408
7714
  if (isControlledRef.current) {
7409
- return;
7715
+ return false;
7410
7716
  }
7717
+ currentRef.current?.handle.howl.play();
7411
7718
  setInternalPlaying(true);
7719
+ return true;
7412
7720
  },
7413
7721
  pause: () => {
7414
7722
  if (isControlledRef.current) {
@@ -7451,8 +7759,8 @@ function BackgroundAudio({
7451
7759
  }),
7452
7760
  []
7453
7761
  );
7454
- const bgmHost = useContext15(BackgroundAudioHostContext);
7455
- useEffect13(() => {
7762
+ const bgmHost = useContext16(BackgroundAudioHostContext);
7763
+ useEffect14(() => {
7456
7764
  if (!bgmHost) {
7457
7765
  return;
7458
7766
  }
@@ -7465,7 +7773,7 @@ function BackgroundAudio({
7465
7773
  }
7466
7774
  };
7467
7775
  }, [bgmHost, controller]);
7468
- useEffect13(() => {
7776
+ useEffect14(() => {
7469
7777
  return () => {
7470
7778
  fadingInRef.current = false;
7471
7779
  isFirstTrackRef.current = true;
@@ -7477,7 +7785,7 @@ function BackgroundAudio({
7477
7785
  outgoingRef.current = [];
7478
7786
  };
7479
7787
  }, []);
7480
- useEffect13(() => {
7788
+ useEffect14(() => {
7481
7789
  const previous = currentRef.current;
7482
7790
  if (previous?.key === trackKey && previous.crossOrigin === crossOrigin) {
7483
7791
  return;
@@ -7580,7 +7888,7 @@ function BackgroundAudio({
7580
7888
  retire(previous);
7581
7889
  }
7582
7890
  }, [crossOrigin, trackKey]);
7583
- useEffect13(() => {
7891
+ useEffect14(() => {
7584
7892
  const howl = currentRef.current?.handle.howl;
7585
7893
  if (!howl) {
7586
7894
  return;
@@ -7596,9 +7904,11 @@ function BackgroundAudio({
7596
7904
  outgoingRef.current = [];
7597
7905
  return;
7598
7906
  }
7599
- howl.play();
7907
+ if (!howl.playing()) {
7908
+ howl.play();
7909
+ }
7600
7910
  }, [playing, trackKey]);
7601
- useEffect13(() => {
7911
+ useEffect14(() => {
7602
7912
  const slot = currentRef.current;
7603
7913
  if (!slot) {
7604
7914
  return;
@@ -7613,7 +7923,7 @@ function BackgroundAudio({
7613
7923
  volume: clampAudioVolume(volumeRef.current)
7614
7924
  });
7615
7925
  }, [loop, muted, trackKey, volume]);
7616
- useEffect13(() => {
7926
+ useEffect14(() => {
7617
7927
  if (!pauseWhenHidden) {
7618
7928
  return;
7619
7929
  }
@@ -7639,13 +7949,13 @@ function BackgroundAudio({
7639
7949
  }
7640
7950
 
7641
7951
  // src/pano-filter/pano-filter.tsx
7642
- import { useContext as useContext16, useEffect as useEffect14, useMemo as useMemo9 } from "react";
7952
+ import { useContext as useContext17, useEffect as useEffect15, useMemo as useMemo9 } from "react";
7643
7953
  function PanoFilter({
7644
7954
  preset = "none",
7645
7955
  intensity,
7646
7956
  enabled = true
7647
7957
  }) {
7648
- const host = useContext16(PanoFilterHostContext);
7958
+ const host = useContext17(PanoFilterHostContext);
7649
7959
  if (!host) {
7650
7960
  throw new Error("<PanoFilter> must be rendered inside <PanoViewer>.");
7651
7961
  }
@@ -7653,13 +7963,13 @@ function PanoFilter({
7653
7963
  () => resolvePanoFilterSnapshot({ preset, intensity, enabled }),
7654
7964
  [enabled, intensity, preset]
7655
7965
  );
7656
- useEffect14(() => {
7966
+ useEffect15(() => {
7657
7967
  claimPanoFilter(host);
7658
7968
  return () => {
7659
7969
  releasePanoFilter(host);
7660
7970
  };
7661
7971
  }, [host]);
7662
- useEffect14(() => {
7972
+ useEffect15(() => {
7663
7973
  setPanoFilterSnapshot(host, snapshot);
7664
7974
  }, [host, snapshot]);
7665
7975
  return null;
@@ -7670,10 +7980,10 @@ import { useFrame as useFrame6, useThree as useThree9 } from "@react-three/fiber
7670
7980
  import {
7671
7981
  forwardRef as forwardRef3,
7672
7982
  useCallback as useCallback7,
7673
- useContext as useContext17,
7674
- useEffect as useEffect15,
7983
+ useContext as useContext18,
7984
+ useEffect as useEffect16,
7675
7985
  useImperativeHandle as useImperativeHandle3,
7676
- useRef as useRef14,
7986
+ useRef as useRef15,
7677
7987
  useState as useState7
7678
7988
  } from "react";
7679
7989
 
@@ -7775,24 +8085,24 @@ var Gyro = forwardRef3(function Gyro2({
7775
8085
  onDisable,
7776
8086
  onDenied
7777
8087
  }, ref) {
7778
- const controlsRef = useContext17(PanoramaViewContext);
7779
- const eventBus = useContext17(PanoEventBusContext);
8088
+ const controlsRef = useContext18(PanoramaViewContext);
8089
+ const eventBus = useContext18(PanoEventBusContext);
7780
8090
  const { gl } = useThree9();
7781
8091
  const [internallyDisabled, setInternallyDisabled] = useState7(false);
7782
- const availableRef = useRef14(false);
7783
- const availabilityReportedRef = useRef14(null);
7784
- const activeRef = useRef14(false);
7785
- const permissionRef = useRef14(deviceOrientationPermissionState);
7786
- const absoluteEventSourceRef = useRef14(null);
7787
- const rawQuaternionRef = useRef14(null);
7788
- const calibrationRef = useRef14(null);
7789
- const absoluteOffsetRef = useRef14({ yaw: 0, pitch: 0 });
7790
- const screenAngleRef = useRef14(getScreenOrientationAngle());
7791
- const startPoseRef = useRef14(null);
7792
- const enabledAtRef = useRef14(0);
7793
- const filteredPoseRef = useRef14(null);
7794
- const lastAppliedPoseRef = useRef14(null);
7795
- const callbacksRef = useRef14({
8092
+ const availableRef = useRef15(false);
8093
+ const availabilityReportedRef = useRef15(null);
8094
+ const activeRef = useRef15(false);
8095
+ const permissionRef = useRef15(deviceOrientationPermissionState);
8096
+ const absoluteEventSourceRef = useRef15(null);
8097
+ const rawQuaternionRef = useRef15(null);
8098
+ const calibrationRef = useRef15(null);
8099
+ const absoluteOffsetRef = useRef15({ yaw: 0, pitch: 0 });
8100
+ const screenAngleRef = useRef15(getScreenOrientationAngle());
8101
+ const startPoseRef = useRef15(null);
8102
+ const enabledAtRef = useRef15(0);
8103
+ const filteredPoseRef = useRef15(null);
8104
+ const lastAppliedPoseRef = useRef15(null);
8105
+ const callbacksRef = useRef15({
7796
8106
  onAvailable,
7797
8107
  onUnavailable,
7798
8108
  onEnable,
@@ -7937,22 +8247,22 @@ var Gyro = forwardRef3(function Gyro2({
7937
8247
  }),
7938
8248
  [requestPermission, resetSensor]
7939
8249
  );
7940
- useEffect15(() => {
8250
+ useEffect16(() => {
7941
8251
  if (!enabled) {
7942
8252
  setInternallyDisabled(false);
7943
8253
  }
7944
8254
  }, [enabled]);
7945
- useEffect15(() => {
8255
+ useEffect16(() => {
7946
8256
  const supported = typeof window !== "undefined" && window.isSecureContext && typeof DeviceOrientationEvent !== "undefined" && (desktopSupport || isMobileDevice());
7947
8257
  setAvailable(supported);
7948
8258
  return () => {
7949
8259
  availableRef.current = false;
7950
8260
  };
7951
8261
  }, [desktopSupport, setAvailable]);
7952
- useEffect15(() => {
8262
+ useEffect16(() => {
7953
8263
  controlsRef.current?.setGyroTouchMode(touchMode);
7954
8264
  }, [controlsRef, touchMode]);
7955
- useEffect15(() => {
8265
+ useEffect16(() => {
7956
8266
  if (!enabled || internallyDisabled || touchMode !== "disablegyro") {
7957
8267
  return;
7958
8268
  }
@@ -7966,7 +8276,7 @@ var Gyro = forwardRef3(function Gyro2({
7966
8276
  gl.domElement.removeEventListener("pointerdown", onPointerDown);
7967
8277
  };
7968
8278
  }, [enabled, gl, internallyDisabled, touchMode]);
7969
- useEffect15(() => {
8279
+ useEffect16(() => {
7970
8280
  if (!enabled || internallyDisabled || !availableRef.current) {
7971
8281
  deactivate();
7972
8282
  return;
@@ -8131,11 +8441,11 @@ import { useThree as useThree12 } from "@react-three/fiber";
8131
8441
  import {
8132
8442
  forwardRef as forwardRef4,
8133
8443
  useCallback as useCallback8,
8134
- useContext as useContext19,
8135
- useEffect as useEffect19,
8444
+ useContext as useContext20,
8445
+ useEffect as useEffect20,
8136
8446
  useImperativeHandle as useImperativeHandle4,
8137
8447
  useMemo as useMemo11,
8138
- useRef as useRef18,
8448
+ useRef as useRef19,
8139
8449
  useState as useState8
8140
8450
  } from "react";
8141
8451
 
@@ -8160,14 +8470,14 @@ async function detectWebVRCapabilities() {
8160
8470
 
8161
8471
  // src/webvr/reticle.tsx
8162
8472
  import { useFrame as useFrame7, useThree as useThree10 } from "@react-three/fiber";
8163
- import { useRef as useRef15 } from "react";
8473
+ import { useRef as useRef16 } from "react";
8164
8474
  import {
8165
8475
  DoubleSide,
8166
8476
  Raycaster as Raycaster2,
8167
8477
  Vector2 as Vector22,
8168
8478
  Vector3 as Vector37
8169
8479
  } from "three";
8170
- import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
8480
+ import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
8171
8481
  var CENTER_NDC = new Vector22(0, 0);
8172
8482
  var HUD_DISTANCE = 2;
8173
8483
  var RETICLE_SCALE = 1;
@@ -8251,13 +8561,13 @@ function WebVRReticle({
8251
8561
  dwellMs,
8252
8562
  visible
8253
8563
  }) {
8254
- const groupRef = useRef15(null);
8255
- const ringMeshRef = useRef15(null);
8256
- const directionRef = useRef15(new Vector37());
8257
- const raycasterRef = useRef15(new Raycaster2());
8258
- const hoveredRef = useRef15(null);
8259
- const dwellRef = useRef15(0);
8260
- const clickedRef = useRef15(false);
8564
+ const groupRef = useRef16(null);
8565
+ const ringMeshRef = useRef16(null);
8566
+ const directionRef = useRef16(new Vector37());
8567
+ const raycasterRef = useRef16(new Raycaster2());
8568
+ const hoveredRef = useRef16(null);
8569
+ const dwellRef = useRef16(0);
8570
+ const clickedRef = useRef16(false);
8261
8571
  const { camera, gl, scene } = useThree10();
8262
8572
  useFrame7((_, deltaSeconds) => {
8263
8573
  const group = groupRef.current;
@@ -8342,8 +8652,8 @@ function WebVRReticle({
8342
8652
  raycast: noopRaycast,
8343
8653
  renderOrder: RETICLE_RENDER_ORDER + 1,
8344
8654
  children: [
8345
- /* @__PURE__ */ jsx12("boxGeometry", { args: [CROSSHAIR_LENGTH, CROSSHAIR_THICKNESS, 1e-3] }),
8346
- /* @__PURE__ */ jsx12(
8655
+ /* @__PURE__ */ jsx13("boxGeometry", { args: [CROSSHAIR_LENGTH, CROSSHAIR_THICKNESS, 1e-3] }),
8656
+ /* @__PURE__ */ jsx13(
8347
8657
  "meshBasicMaterial",
8348
8658
  {
8349
8659
  color: "#ffffff",
@@ -8363,8 +8673,8 @@ function WebVRReticle({
8363
8673
  raycast: noopRaycast,
8364
8674
  renderOrder: RETICLE_RENDER_ORDER + 1,
8365
8675
  children: [
8366
- /* @__PURE__ */ jsx12("boxGeometry", { args: [CROSSHAIR_THICKNESS, CROSSHAIR_LENGTH, 1e-3] }),
8367
- /* @__PURE__ */ jsx12(
8676
+ /* @__PURE__ */ jsx13("boxGeometry", { args: [CROSSHAIR_THICKNESS, CROSSHAIR_LENGTH, 1e-3] }),
8677
+ /* @__PURE__ */ jsx13(
8368
8678
  "meshBasicMaterial",
8369
8679
  {
8370
8680
  color: "#ffffff",
@@ -8386,7 +8696,7 @@ function WebVRReticle({
8386
8696
  renderOrder: RETICLE_RENDER_ORDER + 2,
8387
8697
  visible: false,
8388
8698
  children: [
8389
- /* @__PURE__ */ jsx12(
8699
+ /* @__PURE__ */ jsx13(
8390
8700
  "ringGeometry",
8391
8701
  {
8392
8702
  args: [
@@ -8399,7 +8709,7 @@ function WebVRReticle({
8399
8709
  ]
8400
8710
  }
8401
8711
  ),
8402
- /* @__PURE__ */ jsx12(
8712
+ /* @__PURE__ */ jsx13(
8403
8713
  "meshBasicMaterial",
8404
8714
  {
8405
8715
  color: "#ffffff",
@@ -8420,7 +8730,7 @@ function WebVRReticle({
8420
8730
 
8421
8731
  // src/webvr/stereo.tsx
8422
8732
  import { useFrame as useFrame8, useThree as useThree11 } from "@react-three/fiber";
8423
- import { useContext as useContext18, useEffect as useEffect16, useMemo as useMemo10, useRef as useRef16 } from "react";
8733
+ import { useContext as useContext19, useEffect as useEffect17, useMemo as useMemo10, useRef as useRef17 } from "react";
8424
8734
  import {
8425
8735
  Mesh as Mesh2,
8426
8736
  OrthographicCamera,
@@ -8506,25 +8816,25 @@ function WebVRStereoRenderer({
8506
8816
  screensize
8507
8817
  }) {
8508
8818
  const { camera, gl } = useThree11();
8509
- const runtime = useContext18(WebVRRuntimeContext);
8510
- const fallbackStereoRef = useRef16(null);
8819
+ const runtime = useContext19(WebVRRuntimeContext);
8820
+ const fallbackStereoRef = useRef17(null);
8511
8821
  if (!fallbackStereoRef.current) {
8512
8822
  fallbackStereoRef.current = new StereoCamera2();
8513
8823
  }
8514
8824
  const stereo = runtime?.stereoView.stereo ?? fallbackStereoRef.current;
8515
- const stereoRef = useRef16(stereo);
8825
+ const stereoRef = useRef17(stereo);
8516
8826
  stereoRef.current = stereo;
8517
8827
  const resources = useMemo10(createDistortionResources, []);
8518
- const drawingSizeRef = useRef16(new Vector23());
8519
- const viewportRef = useRef16(new Vector4());
8520
- const scissorRef = useRef16(new Vector4());
8521
- const originalFovRef = useRef16(null);
8522
- const stereoActiveRef = useRef16(false);
8523
- const profileRef = useRef16(profile);
8524
- const screensizeRef = useRef16(screensize);
8828
+ const drawingSizeRef = useRef17(new Vector23());
8829
+ const viewportRef = useRef17(new Vector4());
8830
+ const scissorRef = useRef17(new Vector4());
8831
+ const originalFovRef = useRef17(null);
8832
+ const stereoActiveRef = useRef17(false);
8833
+ const profileRef = useRef17(profile);
8834
+ const screensizeRef = useRef17(screensize);
8525
8835
  profileRef.current = profile;
8526
8836
  screensizeRef.current = screensize;
8527
- useEffect16(
8837
+ useEffect17(
8528
8838
  () => () => {
8529
8839
  resources.geometry.dispose();
8530
8840
  resources.material.dispose();
@@ -8532,7 +8842,7 @@ function WebVRStereoRenderer({
8532
8842
  },
8533
8843
  [resources]
8534
8844
  );
8535
- useEffect16(() => {
8845
+ useEffect17(() => {
8536
8846
  const originalRender = gl.render.bind(gl);
8537
8847
  gl.render = (sceneToRender, cameraToRender) => {
8538
8848
  if (!stereoActiveRef.current || !(cameraToRender instanceof PerspectiveCamera2)) {
@@ -8596,7 +8906,7 @@ function WebVRStereoRenderer({
8596
8906
  gl.render = originalRender;
8597
8907
  };
8598
8908
  }, [gl, resources]);
8599
- useEffect16(
8909
+ useEffect17(
8600
8910
  () => () => {
8601
8911
  if (runtime) {
8602
8912
  runtime.stereoView.active = false;
@@ -8631,7 +8941,7 @@ function WebVRStereoRenderer({
8631
8941
  }
8632
8942
 
8633
8943
  // src/webvr/pointerlock.ts
8634
- import { useEffect as useEffect17, useRef as useRef17 } from "react";
8944
+ import { useEffect as useEffect18, useRef as useRef18 } from "react";
8635
8945
  var POINTER_LOCK_CURSOR_ID = "webvr:pointerlock";
8636
8946
  async function requestWebVRPointerLock(element) {
8637
8947
  if (typeof document === "undefined") {
@@ -8664,11 +8974,11 @@ function exitWebVRPointerLock(element) {
8664
8974
  }
8665
8975
  function useWebVRPointerLock(enabled, element) {
8666
8976
  const cursor = usePanoCursor();
8667
- const cursorRef = useRef17(cursor);
8668
- const enabledRef = useRef17(enabled);
8977
+ const cursorRef = useRef18(cursor);
8978
+ const enabledRef = useRef18(enabled);
8669
8979
  cursorRef.current = cursor;
8670
8980
  enabledRef.current = enabled;
8671
- useEffect17(() => {
8981
+ useEffect18(() => {
8672
8982
  if (!enabled || !element) {
8673
8983
  return;
8674
8984
  }
@@ -8698,7 +9008,7 @@ function useWebVRPointerLock(enabled, element) {
8698
9008
  }
8699
9009
 
8700
9010
  // src/webvr/wakelock.ts
8701
- import { useEffect as useEffect18 } from "react";
9011
+ import { useEffect as useEffect19 } from "react";
8702
9012
 
8703
9013
  // src/webvr/wakelock-fallback.ts
8704
9014
  var WEBVR_WAKELOCK_FALLBACK_VIDEO_BASE64 = "AAAAIGZ0eXBpc29tAAACAGlzb21pc28yYXZjMW1wNDEAAAbBbW9vdgAAAGxtdmhkAAAAAAAAAAAAAAAAAAAD6AAAD4AAAQAAAQAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAxt0cmFrAAAAXHRraGQAAAADAAAAAAAAAAAAAAABAAAAAAAAAggAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAABAAAAAQAAAAAAAkZWR0cwAAABxlbHN0AAAAAAAAAAEAAAIIAAAEAAABAAAAAAKTbWRpYQAAACBtZGhkAAAAAAAAAAAAAAAAAAAyAAAAGgBVxAAAAAAALWhkbHIAAAAAAAAAAHZpZGUAAAAAAAAAAAAAAABWaWRlb0hhbmRsZXIAAAACPm1pbmYAAAAUdm1oZAAAAAEAAAAAAAAAAAAAACRkaW5mAAAAHGRyZWYAAAAAAAAAAQAAAAx1cmwgAAAAAQAAAf5zdGJsAAAAvnN0c2QAAAAAAAAAAQAAAK5hdmMxAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAABAAEABIAAAASAAAAAAAAAABFUxhdmM2Mi4xMS4xMDAgbGlieDI2NAAAAAAAAAAAAAAAGP//AAAANGF2Y0MBZAAK/+EAF2dkAAqs2V7ARAAAAwAEAAADAMg8SJZYAQAGaOvjyyLA/fj4AAAAABBwYXNwAAAAAQAAAAEAAAAUYnRydAAAAAAAADQ5AAAAAAAAABhzdHRzAAAAAAAAAAEAAAANAAACAAAAABRzdHNzAAAAAAAAAAEAAAABAAAAeGN0dHMAAAAAAAAADQAAAAEAAAQAAAAAAQAACgAAAAABAAAEAAAAAAEAAAAAAAAAAQAAAgAAAAABAAAKAAAAAAEAAAQAAAAAAQAAAAAAAAABAAACAAAAAAEAAAoAAAAAAQAABAAAAAABAAAAAAAAAAEAAAIAAAAAKHN0c2MAAAAAAAAAAgAAAAEAAAADAAAAAQAAAAUAAAABAAAAAQAAAEhzdHN6AAAAAAAAAAAAAAANAAACxQAAAAwAAAAMAAAADAAAAAwAAAASAAAADgAAAAwAAAAMAAAAEgAAAA4AAAAMAAAADAAAACRzdGNvAAAAAAAAAAUAAAcGAAAJ5wAAChUAAAo/AAAKbwAAAtF0cmFrAAAAXHRraGQAAAADAAAAAAAAAAAAAAACAAAAAAAAD4AAAAAAAAAAAAAAAAEBAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAkZWR0cwAAABxlbHN0AAAAAAAAAAEAAA+AAAAEAAABAAAAAAJJbWRpYQAAACBtZGhkAAAAAAAAAAAAAAAAAAAfQAAAgABVxAAAAAAALWhkbHIAAAAAAAAAAHNvdW4AAAAAAAAAAAAAAABTb3VuZEhhbmRsZXIAAAAB9G1pbmYAAAAQc21oZAAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAABuHN0YmwAAAB+c3RzZAAAAAAAAAABAAAAbm1wNGEAAAAAAAAAAQAAAAAAAAAAAAEAEAAAAAAfQAAAAAAANmVzZHMAAAAAA4CAgCUAAgAEgICAF0AVAAAAAAAfQAAAARsFgICABRWIVuUABoCAgAECAAAAFGJ0cnQAAAAAAAAfQAAAARsAAAAYc3R0cwAAAAAAAAABAAAAIAAABAAAAAAoc3RzYwAAAAAAAAACAAAAAQAAAAEAAAABAAAABgAAABsAAAABAAAAlHN0c3oAAAAAAAAAAAAAACAAAAAVAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAChzdGNvAAAAAAAAAAYAAAbxAAAJ4wAAChEAAAo7AAAKawAACnsAAAAac2dwZAEAAAByb2xsAAAAAgAAAAH//wAAABxzYmdwAAAAAHJvbGwAAAABAAAAIAAAAAEAAABhdWR0YQAAAFltZXRhAAAAAAAAACFoZGxyAAAAAAAAAABtZGlyYXBwbAAAAAAAAAAAAAAAACxpbHN0AAAAJKl0b28AAAAcZGF0YQAAAAEAAAAATGF2ZjYyLjMuMTAwAAAACGZyZWUAAAP+bWRhdN4CAExhdmM2Mi4xMS4xMDAAAjBADgAAAq4GBf//qtxF6b3m2Ui3lizYINkj7u94MjY0IC0gY29yZSAxNjUgcjMyMjIgYjM1NjA1YSAtIEguMjY0L01QRUctNCBBVkMgY29kZWMgLSBDb3B5bGVmdCAyMDAzLTIwMjUgLSBodHRwOi8vd3d3LnZpZGVvbGFuLm9yZy94MjY0Lmh0bWwgLSBvcHRpb25zOiBjYWJhYz0xIHJlZj0zIGRlYmxvY2s9MTowOjAgYW5hbHlzZT0weDM6MHgxMTMgbWU9aGV4IHN1Ym1lPTcgcHN5PTEgcHN5X3JkPTEuMDA6MC4wMCBtaXhlZF9yZWY9MSBtZV9yYW5nZT0xNiBjaHJvbWFfbWU9MSB0cmVsbGlzPTEgOHg4ZGN0PTEgY3FtPTAgZGVhZHpvbmU9MjEsMTEgZmFzdF9wc2tpcD0xIGNocm9tYV9xcF9vZmZzZXQ9LTIgdGhyZWFkcz0xIGxvb2thaGVhZF90aHJlYWRzPTEgc2xpY2VkX3RocmVhZHM9MCBucj0wIGRlY2ltYXRlPTEgaW50ZXJsYWNlZD0wIGJsdXJheV9jb21wYXQ9MCBjb25zdHJhaW5lZF9pbnRyYT0wIGJmcmFtZXM9MyBiX3B5cmFtaWQ9MiBiX2FkYXB0PTEgYl9iaWFzPTAgZGlyZWN0PTEgd2VpZ2h0Yj0xIG9wZW5fZ29wPTAgd2VpZ2h0cD0yIGtleWludD0yNTAga2V5aW50X21pbj0yNSBzY2VuZWN1dD00MCBpbnRyYV9yZWZyZXNoPTAgcmNfbG9va2FoZWFkPTQwIHJjPWNyZiBtYnRyZWU9MSBjcmY9MjMuMCBxY29tcD0wLjYwIHFwbWluPTAgcXBtYXg9NjkgcXBzdGVwPTQgaXBfcmF0aW89MS40MCBhcT0xOjEuMDAAgAAAAA9liIQAO//+906/AptUwmEAAAAIQZokbEN//uAAAAAIQZ5CeIX/wYEBGCAHAAAACAGeYXRCv8SAAAAACAGeY2pCv8SBAAAADkGaaEmoQWiZTAhn//7hARggBwAAAApBnoZFESwv/8GBAAAACAGepXRCv8SBAAAACAGep2pCv8SAARggBwAAAA5BmqxJqEFsmUwIV//+wAAAAApBnspFFSwv/8GBAAAACAGe6XRCv8SAARggBwAAAAgBnutqQr/EgAEYIAcBGCAHARggBwEYIAcBGCAHARggBwEYIAcBGCAHARggBwEYIAcBGCAHARggBwEYIAcBGCAHARggBwEYIAcBGCAHARggBwEYIAcBGCAHARggBwEYIAcBGCAHARggBwEYIAcBGCAHARggBw==";
@@ -8832,7 +9142,7 @@ function releaseWebVRWakeLock() {
8832
9142
  stopFallbackVideo();
8833
9143
  }
8834
9144
  function useWebVRWakeLock(enabled) {
8835
- useEffect18(() => {
9145
+ useEffect19(() => {
8836
9146
  if (!enabled) {
8837
9147
  return;
8838
9148
  }
@@ -8851,7 +9161,7 @@ function useWebVRWakeLock(enabled) {
8851
9161
  }
8852
9162
 
8853
9163
  // src/webvr/webvr.tsx
8854
- import { Fragment as Fragment4, jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
9164
+ import { Fragment as Fragment4, jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
8855
9165
  function initializeSettings(screensize, profile) {
8856
9166
  const stored = loadWebVRSettings();
8857
9167
  return {
@@ -8880,24 +9190,24 @@ var WebVR = forwardRef4(function WebVR2({
8880
9190
  onDenied,
8881
9191
  onUnknownDevice
8882
9192
  }, ref) {
8883
- const runtime = useContext19(WebVRRuntimeContext);
8884
- const controlsRef = useContext19(PanoramaViewContext);
8885
- const eventBus = useContext19(PanoEventBusContext);
9193
+ const runtime = useContext20(WebVRRuntimeContext);
9194
+ const controlsRef = useContext20(PanoramaViewContext);
9195
+ const eventBus = useContext20(PanoEventBusContext);
8886
9196
  const gl = useThree12((state) => state.gl);
8887
- const gyroRef = useRef18(null);
8888
- const capabilitiesRef = useRef18({
9197
+ const gyroRef = useRef19(null);
9198
+ const capabilitiesRef = useRef19({
8889
9199
  mobile: false,
8890
9200
  sensor: false,
8891
9201
  webxr: false
8892
9202
  });
8893
- const availableRef = useRef18(false);
8894
- const modeRef = useRef18(null);
8895
- const webXRSessionRef = useRef18(null);
9203
+ const availableRef = useRef19(false);
9204
+ const modeRef = useRef19(null);
9205
+ const webXRSessionRef = useRef19(null);
8896
9206
  const [mode, setMode] = useState8(null);
8897
9207
  const [settings, setSettings] = useState8(
8898
9208
  () => initializeSettings(screensize, profile)
8899
9209
  );
8900
- const callbacksRef = useRef18({
9210
+ const callbacksRef = useRef19({
8901
9211
  onAvailable,
8902
9212
  onDenied,
8903
9213
  onEnterVR,
@@ -9107,7 +9417,7 @@ var WebVR = forwardRef4(function WebVR2({
9107
9417
  }),
9108
9418
  [enterVR, exitVR, requestPermission, toggleVR]
9109
9419
  );
9110
- useEffect19(() => {
9420
+ useEffect20(() => {
9111
9421
  let active = true;
9112
9422
  void detectWebVRCapabilities().then((capabilities) => {
9113
9423
  if (!active) {
@@ -9129,7 +9439,7 @@ var WebVR = forwardRef4(function WebVR2({
9129
9439
  active = false;
9130
9440
  };
9131
9441
  }, [desktopSupport, eventBus, fakeSupport, host, mobileVr]);
9132
- useEffect19(() => {
9442
+ useEffect20(() => {
9133
9443
  host.controller = controller;
9134
9444
  return () => {
9135
9445
  if (host.controller === controller) {
@@ -9138,10 +9448,10 @@ var WebVR = forwardRef4(function WebVR2({
9138
9448
  }
9139
9449
  };
9140
9450
  }, [controller, host]);
9141
- useEffect19(() => {
9451
+ useEffect20(() => {
9142
9452
  updateWebVRHost(host, { chrome, mode, settings });
9143
9453
  }, [chrome, host, mode, settings]);
9144
- useEffect19(() => {
9454
+ useEffect20(() => {
9145
9455
  if (mode !== "fake") {
9146
9456
  return;
9147
9457
  }
@@ -9165,7 +9475,7 @@ var WebVR = forwardRef4(function WebVR2({
9165
9475
  document.removeEventListener("mousemove", onMouseMove);
9166
9476
  };
9167
9477
  }, [controlsRef, gl.domElement, mode, mousePointerLock]);
9168
- useEffect19(
9478
+ useEffect20(
9169
9479
  () => () => {
9170
9480
  const session2 = webXRSessionRef.current;
9171
9481
  if (session2) {
@@ -9185,7 +9495,7 @@ var WebVR = forwardRef4(function WebVR2({
9185
9495
  wakelock && (mode === "mobilevr" || mode === "fake")
9186
9496
  );
9187
9497
  return /* @__PURE__ */ jsxs8(Fragment4, { children: [
9188
- /* @__PURE__ */ jsx13(
9498
+ /* @__PURE__ */ jsx14(
9189
9499
  Gyro,
9190
9500
  {
9191
9501
  ref: gyroRef,
@@ -9199,7 +9509,7 @@ var WebVR = forwardRef4(function WebVR2({
9199
9509
  touchMode: "off"
9200
9510
  }
9201
9511
  ),
9202
- /* @__PURE__ */ jsx13(
9512
+ /* @__PURE__ */ jsx14(
9203
9513
  WebVRStereoRenderer,
9204
9514
  {
9205
9515
  mode,
@@ -9207,7 +9517,7 @@ var WebVR = forwardRef4(function WebVR2({
9207
9517
  screensize: settings.screensize
9208
9518
  }
9209
9519
  ),
9210
- /* @__PURE__ */ jsx13(
9520
+ /* @__PURE__ */ jsx14(
9211
9521
  WebVRReticle,
9212
9522
  {
9213
9523
  dwellMs: cursorDwellMs,
@@ -9218,7 +9528,7 @@ var WebVR = forwardRef4(function WebVR2({
9218
9528
  });
9219
9529
 
9220
9530
  // src/use-pano-viewer.ts
9221
- import { useMemo as useMemo12, useRef as useRef19 } from "react";
9531
+ import { useMemo as useMemo12, useRef as useRef20 } from "react";
9222
9532
  function createPanoViewerHandle(ref) {
9223
9533
  return {
9224
9534
  getView: () => ref.current?.getView() ?? { yaw: 0, pitch: 0, fov: 75 },
@@ -9228,6 +9538,11 @@ function createPanoViewerHandle(ref) {
9228
9538
  reset: () => {
9229
9539
  ref.current?.reset();
9230
9540
  },
9541
+ lookTo: (position, options) => ref.current?.lookTo(position, options) ?? Promise.resolve({ status: "cancelled" }),
9542
+ moveTo: (position, options) => ref.current?.moveTo(position, options) ?? Promise.resolve({ status: "cancelled" }),
9543
+ zoomTo: (fov, options) => ref.current?.zoomTo(fov, options) ?? Promise.resolve({ status: "cancelled" }),
9544
+ lookToHotspot: (id, options) => ref.current?.lookToHotspot(id, options) ?? Promise.resolve({ status: "not-found" }),
9545
+ activateMedia: () => ref.current?.activateMedia() ?? Promise.resolve(),
9231
9546
  enterFullscreen: () => ref.current?.enterFullscreen() ?? Promise.resolve(),
9232
9547
  exitFullscreen: () => ref.current?.exitFullscreen() ?? Promise.resolve(),
9233
9548
  toggleFullscreen: () => ref.current?.toggleFullscreen() ?? Promise.resolve(),
@@ -9295,14 +9610,14 @@ function createPanoViewerHandle(ref) {
9295
9610
  };
9296
9611
  }
9297
9612
  function usePanoViewer() {
9298
- const ref = useRef19(null);
9613
+ const ref = useRef20(null);
9299
9614
  const handle = useMemo12(() => createPanoViewerHandle(ref), []);
9300
9615
  return useMemo12(() => ({ ref, ...handle }), [handle]);
9301
9616
  }
9302
9617
 
9303
9618
  // src/sphere.tsx
9304
9619
  import { useThree as useThree13 } from "@react-three/fiber";
9305
- import { useEffect as useEffect20, useMemo as useMemo14, useRef as useRef21, useState as useState9 } from "react";
9620
+ import { useEffect as useEffect21, useMemo as useMemo14, useRef as useRef22, useState as useState9 } from "react";
9306
9621
  import {
9307
9622
  BackSide as BackSide2,
9308
9623
  LinearFilter,
@@ -9335,7 +9650,7 @@ function resolveUrlAgainstFile(fileUrl, path) {
9335
9650
  }
9336
9651
 
9337
9652
  // src/pano-filter/pano-basic-material.tsx
9338
- import { useLayoutEffect as useLayoutEffect2, useMemo as useMemo13, useRef as useRef20 } from "react";
9653
+ import { useLayoutEffect as useLayoutEffect2, useMemo as useMemo13, useRef as useRef21 } from "react";
9339
9654
 
9340
9655
  // src/pano-filter/shaders.ts
9341
9656
  var GLSL_FILTER_COMMON = `
@@ -9486,7 +9801,7 @@ diffuseColor.rgb = mix(diffuseColor.rgb, applyPanoFilter(diffuseColor.rgb), clam
9486
9801
  }
9487
9802
 
9488
9803
  // src/pano-filter/pano-basic-material.tsx
9489
- import { jsx as jsx14 } from "react/jsx-runtime";
9804
+ import { jsx as jsx15 } from "react/jsx-runtime";
9490
9805
  function PanoBasicMaterial({
9491
9806
  map,
9492
9807
  side,
@@ -9495,9 +9810,9 @@ function PanoBasicMaterial({
9495
9810
  toneMapped = false
9496
9811
  }) {
9497
9812
  const snapshot = usePanoFilterSnapshot();
9498
- const materialRef = useRef20(null);
9499
- const intensityRef = useRef20(snapshot.intensity);
9500
- const intensityUniformRef = useRef20(null);
9813
+ const materialRef = useRef21(null);
9814
+ const intensityRef = useRef21(snapshot.intensity);
9815
+ const intensityUniformRef = useRef21(null);
9501
9816
  intensityRef.current = snapshot.intensity;
9502
9817
  const active = isPanoFilterActive(snapshot);
9503
9818
  const preset = snapshot.preset;
@@ -9533,7 +9848,7 @@ function PanoBasicMaterial({
9533
9848
  intensityUniformRef.current.value = snapshot.intensity;
9534
9849
  }
9535
9850
  }, [snapshot.intensity]);
9536
- return /* @__PURE__ */ jsx14(
9851
+ return /* @__PURE__ */ jsx15(
9537
9852
  "meshBasicMaterial",
9538
9853
  {
9539
9854
  ref: materialRef,
@@ -9549,14 +9864,14 @@ function PanoBasicMaterial({
9549
9864
  }
9550
9865
 
9551
9866
  // src/sphere.tsx
9552
- import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
9867
+ import { jsx as jsx16, jsxs as jsxs9 } from "react/jsx-runtime";
9553
9868
  function useEquirectTexture(url, anisotropy, generateMipmaps, onLoad, onError) {
9554
9869
  const [texture, setTexture] = useState9(null);
9555
- const onLoadRef = useRef21(onLoad);
9556
- const onErrorRef = useRef21(onError);
9870
+ const onLoadRef = useRef22(onLoad);
9871
+ const onErrorRef = useRef22(onError);
9557
9872
  onLoadRef.current = onLoad;
9558
9873
  onErrorRef.current = onError;
9559
- useEffect20(() => {
9874
+ useEffect21(() => {
9560
9875
  if (!url) {
9561
9876
  setTexture(null);
9562
9877
  return;
@@ -9595,7 +9910,7 @@ function useEquirectTexture(url, anisotropy, generateMipmaps, onLoad, onError) {
9595
9910
  active = false;
9596
9911
  };
9597
9912
  }, [anisotropy, generateMipmaps, url]);
9598
- useEffect20(
9913
+ useEffect21(
9599
9914
  () => () => {
9600
9915
  texture?.dispose();
9601
9916
  },
@@ -9634,11 +9949,11 @@ function Sphere({
9634
9949
  onPreviewError
9635
9950
  );
9636
9951
  const displayTexture = texture ?? previewTexture;
9637
- const readyRef = useRef21(false);
9638
- useEffect20(() => {
9952
+ const readyRef = useRef22(false);
9953
+ useEffect21(() => {
9639
9954
  readyRef.current = false;
9640
9955
  }, [resolvedPreviewUrl, src]);
9641
- useEffect20(() => {
9956
+ useEffect21(() => {
9642
9957
  if (!displayTexture || readyRef.current) {
9643
9958
  return;
9644
9959
  }
@@ -9654,8 +9969,8 @@ function Sphere({
9654
9969
  rotation: [0, MathUtils5.degToRad(90 + yawOffset), 0],
9655
9970
  visible,
9656
9971
  children: [
9657
- /* @__PURE__ */ jsx15("sphereGeometry", { args: [DEFAULT_PANORAMA_RADIUS, 128, 64] }),
9658
- /* @__PURE__ */ jsx15(
9972
+ /* @__PURE__ */ jsx16("sphereGeometry", { args: [DEFAULT_PANORAMA_RADIUS, 128, 64] }),
9973
+ /* @__PURE__ */ jsx16(
9659
9974
  PanoBasicMaterial,
9660
9975
  {
9661
9976
  map: displayTexture,
@@ -9672,11 +9987,11 @@ function Sphere({
9672
9987
  import { useThree as useThree14 } from "@react-three/fiber";
9673
9988
  import {
9674
9989
  useCallback as useCallback9,
9675
- useContext as useContext20,
9676
- useEffect as useEffect21,
9990
+ useContext as useContext21,
9991
+ useEffect as useEffect22,
9677
9992
  useLayoutEffect as useLayoutEffect3,
9678
9993
  useMemo as useMemo15,
9679
- useRef as useRef22,
9994
+ useRef as useRef23,
9680
9995
  useState as useState10
9681
9996
  } from "react";
9682
9997
  import {
@@ -9689,7 +10004,7 @@ import {
9689
10004
  TextureLoader as TextureLoader2,
9690
10005
  VideoTexture
9691
10006
  } from "three";
9692
- import { Fragment as Fragment5, jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
10007
+ import { Fragment as Fragment5, jsx as jsx17, jsxs as jsxs10 } from "react/jsx-runtime";
9693
10008
  var EMPTY_TRACKS = [];
9694
10009
  var EMPTY_RATES = DEFAULT_PANO_VIDEO_PLAYBACK_RATES;
9695
10010
  function createEmptySnapshot() {
@@ -9775,9 +10090,9 @@ function applyEquirectangularLayout(texture, anisotropy) {
9775
10090
  function usePosterTexture(poster, onError) {
9776
10091
  const gl = useThree14((state) => state.gl);
9777
10092
  const [texture, setTexture] = useState10(null);
9778
- const onErrorRef = useRef22(onError);
10093
+ const onErrorRef = useRef23(onError);
9779
10094
  onErrorRef.current = onError;
9780
- useEffect21(() => {
10095
+ useEffect22(() => {
9781
10096
  let active = true;
9782
10097
  setTexture(null);
9783
10098
  if (!poster) {
@@ -9814,7 +10129,7 @@ function usePosterTexture(poster, onError) {
9814
10129
  active = false;
9815
10130
  };
9816
10131
  }, [gl, poster]);
9817
- useEffect21(
10132
+ useEffect22(
9818
10133
  () => () => {
9819
10134
  texture?.dispose();
9820
10135
  },
@@ -9871,9 +10186,10 @@ function PanoVideo({
9871
10186
  onVariantChange,
9872
10187
  onTrackChange
9873
10188
  }) {
10189
+ usePanoMediaActivationIntent(autoPlay);
9874
10190
  const gl = useThree14((state) => state.gl);
9875
- const host = useContext20(PanoVideoHostContext);
9876
- const overlay = useContext20(PanoChromeOverlayContext);
10191
+ const host = useContext21(PanoVideoHostContext);
10192
+ const overlay = useContext21(PanoChromeOverlayContext);
9877
10193
  const variants = useMemo15(
9878
10194
  () => resolvePanoVideoVariants({ poster, src, variants: variantsProp }),
9879
10195
  [poster, src, variantsProp]
@@ -9893,17 +10209,17 @@ function PanoVideo({
9893
10209
  () => captionsEnabled ? defaultPanoVideoTrackId(tracks) : null
9894
10210
  );
9895
10211
  const [ready, setReady] = useState10(false);
9896
- const autoPlayRef = useRef22(autoPlay);
10212
+ const autoPlayRef = useRef23(autoPlay);
9897
10213
  autoPlayRef.current = autoPlay;
9898
- const blockedRef = useRef22(false);
9899
- const captionAppearanceOverrideRef = useRef22(
10214
+ const blockedRef = useRef23(false);
10215
+ const captionAppearanceOverrideRef = useRef23(
9900
10216
  {}
9901
10217
  );
9902
- const mediaCapabilitiesRef = useRef22({
10218
+ const mediaCapabilitiesRef = useRef23({
9903
10219
  volumeAdjustable: true,
9904
10220
  playbackRates: [...DEFAULT_PANO_VIDEO_PLAYBACK_RATES]
9905
10221
  });
9906
- const storeRef = useRef22(null);
10222
+ const storeRef = useRef23(null);
9907
10223
  if (!storeRef.current) {
9908
10224
  storeRef.current = {
9909
10225
  snapshot: {
@@ -9913,7 +10229,7 @@ function PanoVideo({
9913
10229
  listeners: /* @__PURE__ */ new Set()
9914
10230
  };
9915
10231
  }
9916
- const actionsRef = useRef22({
10232
+ const actionsRef = useRef23({
9917
10233
  play: async () => {
9918
10234
  },
9919
10235
  pause: () => {
@@ -9933,12 +10249,12 @@ function PanoVideo({
9933
10249
  setCaptionAppearance: (_appearance) => {
9934
10250
  }
9935
10251
  });
9936
- const onLoadRef = useRef22(onLoad);
9937
- const onErrorRef = useRef22(onError);
9938
- const onPlaybackStateChangeRef = useRef22(onPlaybackStateChange);
9939
- const onEndedRef = useRef22(onEnded);
9940
- const onVariantChangeRef = useRef22(onVariantChange);
9941
- const onTrackChangeRef = useRef22(onTrackChange);
10252
+ const onLoadRef = useRef23(onLoad);
10253
+ const onErrorRef = useRef23(onError);
10254
+ const onPlaybackStateChangeRef = useRef23(onPlaybackStateChange);
10255
+ const onEndedRef = useRef23(onEnded);
10256
+ const onVariantChangeRef = useRef23(onVariantChange);
10257
+ const onTrackChangeRef = useRef23(onTrackChange);
9942
10258
  onLoadRef.current = onLoad;
9943
10259
  onErrorRef.current = onError;
9944
10260
  onPlaybackStateChangeRef.current = onPlaybackStateChange;
@@ -9962,7 +10278,7 @@ function PanoVideo({
9962
10278
  texture.generateMipmaps = false;
9963
10279
  return { video, texture };
9964
10280
  }, []);
9965
- useEffect21(
10281
+ useEffect22(
9966
10282
  () => () => {
9967
10283
  if (!resource) {
9968
10284
  return;
@@ -9977,13 +10293,13 @@ function PanoVideo({
9977
10293
  },
9978
10294
  [resource]
9979
10295
  );
9980
- useEffect21(() => {
10296
+ useEffect22(() => {
9981
10297
  if (!resource) {
9982
10298
  return;
9983
10299
  }
9984
10300
  resource.texture.anisotropy = gl.capabilities.getMaxAnisotropy();
9985
10301
  }, [gl, resource]);
9986
- useEffect21(() => {
10302
+ useEffect22(() => {
9987
10303
  if (!resource || !overlay?.overlayElement) {
9988
10304
  return;
9989
10305
  }
@@ -10136,10 +10452,10 @@ function PanoVideo({
10136
10452
  };
10137
10453
  emitSnapshot();
10138
10454
  }, [emitSnapshot, playbackRates, resource]);
10139
- useEffect21(() => {
10455
+ useEffect22(() => {
10140
10456
  emitSnapshot();
10141
10457
  }, [emitSnapshot]);
10142
- useEffect21(() => {
10458
+ useEffect22(() => {
10143
10459
  if (!resource || !activeVariant || !mediaKey) {
10144
10460
  return;
10145
10461
  }
@@ -10196,7 +10512,7 @@ function PanoVideo({
10196
10512
  video.removeEventListener("error", handleError);
10197
10513
  };
10198
10514
  }, [mediaKey, resource]);
10199
- useEffect21(() => {
10515
+ useEffect22(() => {
10200
10516
  if (!resource) {
10201
10517
  return;
10202
10518
  }
@@ -10286,7 +10602,7 @@ function PanoVideo({
10286
10602
  }
10287
10603
  };
10288
10604
  }, [emitSnapshot, resource]);
10289
- useEffect21(() => {
10605
+ useEffect22(() => {
10290
10606
  if (!resource) {
10291
10607
  return;
10292
10608
  }
@@ -10297,9 +10613,16 @@ function PanoVideo({
10297
10613
  video.volume = clampVolume(volume);
10298
10614
  }
10299
10615
  video.playsInline = playsInline;
10616
+ if (playsInline) {
10617
+ video.setAttribute("playsinline", "true");
10618
+ video.setAttribute("webkit-playsinline", "true");
10619
+ } else {
10620
+ video.removeAttribute("playsinline");
10621
+ video.removeAttribute("webkit-playsinline");
10622
+ }
10300
10623
  video.preload = preload;
10301
10624
  }, [loop, muted, playsInline, preload, resource, volume]);
10302
- useEffect21(() => {
10625
+ useEffect22(() => {
10303
10626
  if (!resource) {
10304
10627
  return;
10305
10628
  }
@@ -10349,7 +10672,7 @@ function PanoVideo({
10349
10672
  video.removeEventListener("ratechange", handleVolume);
10350
10673
  };
10351
10674
  }, [emitSnapshot, resource]);
10352
- useEffect21(() => {
10675
+ useEffect22(() => {
10353
10676
  if (!resource) {
10354
10677
  return;
10355
10678
  }
@@ -10384,7 +10707,7 @@ function PanoVideo({
10384
10707
  video.textTracks.removeEventListener("change", applyModes);
10385
10708
  };
10386
10709
  }, [emitSnapshot, resource, trackId, tracks]);
10387
- useEffect21(() => {
10710
+ useEffect22(() => {
10388
10711
  if (!captionsEnabled) {
10389
10712
  setTrackId(null);
10390
10713
  return;
@@ -10402,8 +10725,8 @@ function PanoVideo({
10402
10725
  rotation: [0, MathUtils6.degToRad(90 + yawOffset), 0],
10403
10726
  visible,
10404
10727
  children: [
10405
- /* @__PURE__ */ jsx16("sphereGeometry", { args: [DEFAULT_PANORAMA_RADIUS, 128, 64] }),
10406
- /* @__PURE__ */ jsx16(
10728
+ /* @__PURE__ */ jsx17("sphereGeometry", { args: [DEFAULT_PANORAMA_RADIUS, 128, 64] }),
10729
+ /* @__PURE__ */ jsx17(
10407
10730
  PanoBasicMaterial,
10408
10731
  {
10409
10732
  map: activeTexture,
@@ -10414,7 +10737,7 @@ function PanoVideo({
10414
10737
  ]
10415
10738
  }
10416
10739
  ) : null,
10417
- captionsEnabled ? /* @__PURE__ */ jsx16(PanoVideoCaptions, { appearance: typeof captions === "object" ? captions : void 0 }) : null
10740
+ captionsEnabled ? /* @__PURE__ */ jsx17(PanoVideoCaptions, { appearance: typeof captions === "object" ? captions : void 0 }) : null
10418
10741
  ] });
10419
10742
  }
10420
10743
 
@@ -10423,10 +10746,10 @@ import { useFrame as useFrame12, useThree as useThree19 } from "@react-three/fib
10423
10746
  import {
10424
10747
  Fragment as Fragment6,
10425
10748
  useCallback as useCallback10,
10426
- useContext as useContext22,
10427
- useEffect as useEffect26,
10749
+ useContext as useContext23,
10750
+ useEffect as useEffect27,
10428
10751
  useMemo as useMemo20,
10429
- useRef as useRef26,
10752
+ useRef as useRef27,
10430
10753
  useState as useState12
10431
10754
  } from "react";
10432
10755
  import {
@@ -10483,7 +10806,7 @@ function isSnapshotTransition(preset) {
10483
10806
 
10484
10807
  // src/scene-transitions/particle-overlay.tsx
10485
10808
  import { useFrame as useFrame9, useThree as useThree15 } from "@react-three/fiber";
10486
- import { useEffect as useEffect22, useMemo as useMemo16, useRef as useRef23 } from "react";
10809
+ import { useEffect as useEffect23, useMemo as useMemo16, useRef as useRef24 } from "react";
10487
10810
  import {
10488
10811
  DoubleSide as DoubleSide2,
10489
10812
  InstancedBufferAttribute,
@@ -10546,7 +10869,7 @@ function overlayProgress(elapsedTime, duration, startTime) {
10546
10869
  }
10547
10870
 
10548
10871
  // src/scene-transitions/particle-overlay.tsx
10549
- import { jsx as jsx17 } from "react/jsx-runtime";
10872
+ import { jsx as jsx18 } from "react/jsx-runtime";
10550
10873
  var PARTICLE_GRID = 48;
10551
10874
  var PARTICLE_COUNT = PARTICLE_GRID * PARTICLE_GRID;
10552
10875
  var PARTICLE_VERTEX_SHADER = `
@@ -10623,10 +10946,10 @@ function ParticleOverlay({
10623
10946
  onFinish
10624
10947
  }) {
10625
10948
  const { camera } = useThree15();
10626
- const meshRef = useRef23(null);
10627
- const startRef = useRef23(null);
10628
- const finishedRef = useRef23(false);
10629
- const directionRef = useRef23(new Vector39());
10949
+ const meshRef = useRef24(null);
10950
+ const startRef = useRef24(null);
10951
+ const finishedRef = useRef24(false);
10952
+ const directionRef = useRef24(new Vector39());
10630
10953
  const geometry = useMemo16(() => createParticleGeometry(), []);
10631
10954
  const material = useMemo16(
10632
10955
  () => new ShaderMaterial2({
@@ -10644,9 +10967,9 @@ function ParticleOverlay({
10644
10967
  }),
10645
10968
  [snapshot.texture]
10646
10969
  );
10647
- useEffect22(() => () => geometry.dispose(), [geometry]);
10648
- useEffect22(() => () => material.dispose(), [material]);
10649
- useEffect22(() => {
10970
+ useEffect23(() => () => geometry.dispose(), [geometry]);
10971
+ useEffect23(() => () => material.dispose(), [material]);
10972
+ useEffect23(() => {
10650
10973
  startRef.current = null;
10651
10974
  finishedRef.current = false;
10652
10975
  material.uniforms.progress.value = 0;
@@ -10668,7 +10991,7 @@ function ParticleOverlay({
10668
10991
  onFinish();
10669
10992
  }
10670
10993
  });
10671
- return /* @__PURE__ */ jsx17(
10994
+ return /* @__PURE__ */ jsx18(
10672
10995
  "mesh",
10673
10996
  {
10674
10997
  ref: meshRef,
@@ -10682,7 +11005,7 @@ function ParticleOverlay({
10682
11005
 
10683
11006
  // src/scene-transitions/snapshot-overlay.tsx
10684
11007
  import { useFrame as useFrame10, useThree as useThree16 } from "@react-three/fiber";
10685
- import { useEffect as useEffect23, useMemo as useMemo17, useRef as useRef24 } from "react";
11008
+ import { useEffect as useEffect24, useMemo as useMemo17, useRef as useRef25 } from "react";
10686
11009
  import { Vector3 as Vector310 } from "three";
10687
11010
 
10688
11011
  // src/scene-transitions/snapshot-shaders.ts
@@ -10962,7 +11285,7 @@ function createSnapshotMaterial(preset, texture) {
10962
11285
  }
10963
11286
 
10964
11287
  // src/scene-transitions/snapshot-overlay.tsx
10965
- import { jsx as jsx18, jsxs as jsxs11 } from "react/jsx-runtime";
11288
+ import { jsx as jsx19, jsxs as jsxs11 } from "react/jsx-runtime";
10966
11289
  function SnapshotOverlay({
10967
11290
  snapshot,
10968
11291
  transition,
@@ -10971,18 +11294,18 @@ function SnapshotOverlay({
10971
11294
  onFinish
10972
11295
  }) {
10973
11296
  const { camera, gl } = useThree16();
10974
- const meshRef = useRef24(null);
10975
- const startRef = useRef24(null);
10976
- const finishedRef = useRef24(false);
10977
- const directionRef = useRef24(new Vector310());
11297
+ const meshRef = useRef25(null);
11298
+ const startRef = useRef25(null);
11299
+ const finishedRef = useRef25(false);
11300
+ const directionRef = useRef25(new Vector310());
10978
11301
  const material = useMemo17(() => {
10979
11302
  if (!isSnapshotTransition(transition.preset)) {
10980
11303
  return null;
10981
11304
  }
10982
11305
  return createSnapshotMaterial(transition.preset, snapshot.texture);
10983
11306
  }, [snapshot.texture, transition.preset]);
10984
- useEffect23(() => () => material?.dispose(), [material]);
10985
- useEffect23(() => {
11307
+ useEffect24(() => () => material?.dispose(), [material]);
11308
+ useEffect24(() => {
10986
11309
  startRef.current = null;
10987
11310
  finishedRef.current = false;
10988
11311
  if (material) {
@@ -11012,20 +11335,20 @@ function SnapshotOverlay({
11012
11335
  return null;
11013
11336
  }
11014
11337
  return /* @__PURE__ */ jsxs11("mesh", { ref: meshRef, renderOrder: OVERLAY_RENDER_ORDER, frustumCulled: false, children: [
11015
- /* @__PURE__ */ jsx18("primitive", { attach: "geometry", object: FULLSCREEN_PLANE }),
11016
- /* @__PURE__ */ jsx18("primitive", { attach: "material", object: material })
11338
+ /* @__PURE__ */ jsx19("primitive", { attach: "geometry", object: FULLSCREEN_PLANE }),
11339
+ /* @__PURE__ */ jsx19("primitive", { attach: "material", object: material })
11017
11340
  ] });
11018
11341
  }
11019
11342
 
11020
11343
  // src/scene-transitions/transition-overlay.tsx
11021
- import { jsx as jsx19 } from "react/jsx-runtime";
11344
+ import { jsx as jsx20 } from "react/jsx-runtime";
11022
11345
  function TransitionOverlay(props) {
11023
11346
  const { preset } = props.transition;
11024
11347
  switch (preset) {
11025
11348
  case "none":
11026
11349
  return null;
11027
11350
  case "particles":
11028
- return /* @__PURE__ */ jsx19(ParticleOverlay, { ...props });
11351
+ return /* @__PURE__ */ jsx20(ParticleOverlay, { ...props });
11029
11352
  case "crossfade":
11030
11353
  case "zoom":
11031
11354
  case "blackout":
@@ -11053,7 +11376,7 @@ function TransitionOverlay(props) {
11053
11376
  case "zoomBlur":
11054
11377
  case "hexDissolve":
11055
11378
  case "filmBurn":
11056
- return /* @__PURE__ */ jsx19(SnapshotOverlay, { ...props });
11379
+ return /* @__PURE__ */ jsx20(SnapshotOverlay, { ...props });
11057
11380
  default: {
11058
11381
  const exhaustive = preset;
11059
11382
  void exhaustive;
@@ -11065,9 +11388,9 @@ function TransitionOverlay(props) {
11065
11388
  // src/tile/texture-manager-context.tsx
11066
11389
  import { useThree as useThree17 } from "@react-three/fiber";
11067
11390
  import {
11068
- createContext as createContext13,
11069
- useContext as useContext21,
11070
- useEffect as useEffect24,
11391
+ createContext as createContext15,
11392
+ useContext as useContext22,
11393
+ useEffect as useEffect25,
11071
11394
  useMemo as useMemo18
11072
11395
  } from "react";
11073
11396
 
@@ -11298,8 +11621,8 @@ var TileTextureManager = class {
11298
11621
  };
11299
11622
 
11300
11623
  // src/tile/texture-manager-context.tsx
11301
- import { jsx as jsx20 } from "react/jsx-runtime";
11302
- var TileTextureManagerContext = createContext13(
11624
+ import { jsx as jsx21 } from "react/jsx-runtime";
11625
+ var TileTextureManagerContext = createContext15(
11303
11626
  null
11304
11627
  );
11305
11628
  function TileTextureManagerProvider({
@@ -11318,23 +11641,23 @@ function TileTextureManagerProvider({
11318
11641
  }),
11319
11642
  [anisotropy, maxConcurrentLoads, maxTextureMemoryMb]
11320
11643
  );
11321
- useEffect24(() => {
11644
+ useEffect25(() => {
11322
11645
  manager.resume();
11323
11646
  return () => manager.dispose();
11324
11647
  }, [manager]);
11325
- return /* @__PURE__ */ jsx20(TileTextureManagerContext.Provider, { value: manager, children });
11648
+ return /* @__PURE__ */ jsx21(TileTextureManagerContext.Provider, { value: manager, children });
11326
11649
  }
11327
11650
  function useSharedTileTextureManager() {
11328
- return useContext21(TileTextureManagerContext);
11651
+ return useContext22(TileTextureManagerContext);
11329
11652
  }
11330
11653
 
11331
11654
  // src/tile/tile.tsx
11332
11655
  import { useFrame as useFrame11, useThree as useThree18 } from "@react-three/fiber";
11333
11656
  import {
11334
11657
  memo,
11335
- useEffect as useEffect25,
11658
+ useEffect as useEffect26,
11336
11659
  useMemo as useMemo19,
11337
- useRef as useRef25,
11660
+ useRef as useRef26,
11338
11661
  useState as useState11
11339
11662
  } from "react";
11340
11663
  import {
@@ -11531,7 +11854,7 @@ function resolveTemplateUrl(template, address) {
11531
11854
  }
11532
11855
 
11533
11856
  // src/tile/tile.tsx
11534
- import { jsx as jsx21, jsxs as jsxs12 } from "react/jsx-runtime";
11857
+ import { jsx as jsx22, jsxs as jsxs12 } from "react/jsx-runtime";
11535
11858
  var MAX_LOD_UPDATE_INTERVAL_MS = 100;
11536
11859
  var FAST_ROTATION_THRESHOLD_RADIANS = Math.PI / 180;
11537
11860
  var FAST_FOV_THRESHOLD_DEGREES = 0.5;
@@ -11541,9 +11864,9 @@ var PREVIEW_RADIUS = CUBE_RADIUS + 0.05;
11541
11864
  var SHARED_TILE_GEOMETRY = new PlaneGeometry4(1, 1);
11542
11865
  function usePreviewTexture(url, anisotropy, onError) {
11543
11866
  const [texture, setTexture] = useState11(null);
11544
- const onErrorRef = useRef25(onError);
11867
+ const onErrorRef = useRef26(onError);
11545
11868
  onErrorRef.current = onError;
11546
- useEffect25(() => {
11869
+ useEffect26(() => {
11547
11870
  if (!url) {
11548
11871
  setTexture(null);
11549
11872
  return;
@@ -11580,7 +11903,7 @@ function usePreviewTexture(url, anisotropy, onError) {
11580
11903
  active = false;
11581
11904
  };
11582
11905
  }, [anisotropy, url]);
11583
- useEffect25(
11906
+ useEffect26(
11584
11907
  () => () => {
11585
11908
  texture?.dispose();
11586
11909
  },
@@ -11611,21 +11934,21 @@ function PreviewFace({
11611
11934
  uv.needsUpdate = true;
11612
11935
  return nextGeometry;
11613
11936
  }, [face, faceOrder]);
11614
- useEffect25(
11937
+ useEffect26(
11615
11938
  () => () => {
11616
11939
  geometry.dispose();
11617
11940
  },
11618
11941
  [geometry]
11619
11942
  );
11620
11943
  const transform = getFaceTransform(face, PREVIEW_RADIUS);
11621
- return /* @__PURE__ */ jsx21(
11944
+ return /* @__PURE__ */ jsx22(
11622
11945
  "mesh",
11623
11946
  {
11624
11947
  geometry,
11625
11948
  position: transform.position,
11626
11949
  renderOrder: -100,
11627
11950
  rotation: transform.rotation,
11628
- children: /* @__PURE__ */ jsx21(
11951
+ children: /* @__PURE__ */ jsx22(
11629
11952
  PanoBasicMaterial,
11630
11953
  {
11631
11954
  depthTest: false,
@@ -11641,7 +11964,7 @@ function PreviewCube({
11641
11964
  texture,
11642
11965
  faceOrder
11643
11966
  }) {
11644
- return CUBE_FACES.map((face) => /* @__PURE__ */ jsx21(
11967
+ return CUBE_FACES.map((face) => /* @__PURE__ */ jsx22(
11645
11968
  PreviewFace,
11646
11969
  {
11647
11970
  face,
@@ -11659,7 +11982,7 @@ function useManagedTexture(manager, key, url, address) {
11659
11982
  snapshot: manager.getSnapshot(key)
11660
11983
  }));
11661
11984
  const snapshot = managedState.manager === manager && managedState.key === key && managedState.url === url ? managedState.snapshot : manager.getSnapshot(key);
11662
- useEffect25(
11985
+ useEffect26(
11663
11986
  () => manager.acquire(key, url, address, (nextSnapshot) => {
11664
11987
  setManagedState({
11665
11988
  manager,
@@ -11686,14 +12009,14 @@ var TileMesh = memo(function TileMesh2({
11686
12009
  if (!snapshot.texture) {
11687
12010
  return null;
11688
12011
  }
11689
- return /* @__PURE__ */ jsx21("group", { position: transform.position, rotation: transform.rotation, children: /* @__PURE__ */ jsx21(
12012
+ return /* @__PURE__ */ jsx22("group", { position: transform.position, rotation: transform.rotation, children: /* @__PURE__ */ jsx22(
11690
12013
  "mesh",
11691
12014
  {
11692
12015
  geometry: SHARED_TILE_GEOMETRY,
11693
12016
  position: [layout.x, layout.y, 0],
11694
12017
  renderOrder,
11695
12018
  scale: [layout.width, layout.height, 1],
11696
- children: /* @__PURE__ */ jsx21(
12019
+ children: /* @__PURE__ */ jsx22(
11697
12020
  PanoBasicMaterial,
11698
12021
  {
11699
12022
  depthTest: false,
@@ -11710,7 +12033,7 @@ var TileLayerMeshes = memo(function TileLayerMeshes2({
11710
12033
  manager,
11711
12034
  resolveUrl
11712
12035
  }) {
11713
- return layer.addresses.map((address) => /* @__PURE__ */ jsx21(
12036
+ return layer.addresses.map((address) => /* @__PURE__ */ jsx22(
11714
12037
  TileMesh,
11715
12038
  {
11716
12039
  address,
@@ -11894,9 +12217,9 @@ function Tile({
11894
12217
  onPreviewError
11895
12218
  );
11896
12219
  const sharedManager = useSharedTileTextureManager();
11897
- const progressRef = useRef25(onLoadProgress);
11898
- const errorRef = useRef25(onTileError);
11899
- const levelChangeRef = useRef25(onLevelChange);
12220
+ const progressRef = useRef26(onLoadProgress);
12221
+ const errorRef = useRef26(onTileError);
12222
+ const levelChangeRef = useRef26(onLevelChange);
11900
12223
  progressRef.current = onLoadProgress;
11901
12224
  errorRef.current = onTileError;
11902
12225
  levelChangeRef.current = onLevelChange;
@@ -11921,7 +12244,7 @@ function Tile({
11921
12244
  ]
11922
12245
  );
11923
12246
  const manager = sharedManager ?? ownedManager;
11924
- useEffect25(() => {
12247
+ useEffect26(() => {
11925
12248
  manager.resume();
11926
12249
  return () => {
11927
12250
  if (manager === ownedManager) {
@@ -11931,11 +12254,11 @@ function Tile({
11931
12254
  queueMicrotask(() => manager.releaseUnused());
11932
12255
  };
11933
12256
  }, [manager, ownedManager]);
11934
- const readyRef = useRef25(false);
11935
- useEffect25(() => {
12257
+ const readyRef = useRef26(false);
12258
+ useEffect26(() => {
11936
12259
  readyRef.current = false;
11937
12260
  }, [effectivePreviewUrl]);
11938
- useEffect25(() => {
12261
+ useEffect26(() => {
11939
12262
  if (!previewTexture || readyRef.current) {
11940
12263
  return;
11941
12264
  }
@@ -11951,23 +12274,23 @@ function Tile({
11951
12274
  [baseUrl, resolveTileUrl, template]
11952
12275
  );
11953
12276
  const [layers, setLayers] = useState11([]);
11954
- const layerTokenRef = useRef25("");
11955
- const currentLevelRef = useRef25(1);
11956
- const lastUpdateAtRef = useRef25(-Infinity);
11957
- const visibilityDirtyRef = useRef25(true);
11958
- const lastVisibilityQuaternionRef = useRef25(camera.quaternion.clone());
11959
- const lastVisibilityFovRef = useRef25(Number.NaN);
11960
- const lastViewportRef = useRef25({ width: 0, height: 0, dpr: 0 });
11961
- const frustumRef = useRef25(new Frustum());
11962
- const projectionMatrixRef = useRef25(new Matrix4());
11963
- const visibilityCameraRef = useRef25(new PerspectiveCamera4());
11964
- useEffect25(() => {
12277
+ const layerTokenRef = useRef26("");
12278
+ const currentLevelRef = useRef26(1);
12279
+ const lastUpdateAtRef = useRef26(-Infinity);
12280
+ const visibilityDirtyRef = useRef26(true);
12281
+ const lastVisibilityQuaternionRef = useRef26(camera.quaternion.clone());
12282
+ const lastVisibilityFovRef = useRef26(Number.NaN);
12283
+ const lastViewportRef = useRef26({ width: 0, height: 0, dpr: 0 });
12284
+ const frustumRef = useRef26(new Frustum());
12285
+ const projectionMatrixRef = useRef26(new Matrix4());
12286
+ const visibilityCameraRef = useRef26(new PerspectiveCamera4());
12287
+ useEffect26(() => {
11965
12288
  currentLevelRef.current = 1;
11966
12289
  layerTokenRef.current = "";
11967
12290
  visibilityDirtyRef.current = true;
11968
12291
  setLayers([]);
11969
12292
  }, [manager, multiresToken]);
11970
- useEffect25(() => {
12293
+ useEffect26(() => {
11971
12294
  if (loadMode !== "preview") {
11972
12295
  return;
11973
12296
  }
@@ -12048,14 +12371,14 @@ function Tile({
12048
12371
  commitLayers(nextLayers);
12049
12372
  });
12050
12373
  return /* @__PURE__ */ jsxs12("group", { visible, children: [
12051
- previewTexture ? /* @__PURE__ */ jsx21(
12374
+ previewTexture ? /* @__PURE__ */ jsx22(
12052
12375
  PreviewCube,
12053
12376
  {
12054
12377
  texture: previewTexture,
12055
12378
  faceOrder: previewFaceOrder
12056
12379
  }
12057
12380
  ) : null,
12058
- layers.map((layer) => /* @__PURE__ */ jsx21(
12381
+ layers.map((layer) => /* @__PURE__ */ jsx22(
12059
12382
  TileLayerMeshes,
12060
12383
  {
12061
12384
  layer,
@@ -12068,7 +12391,7 @@ function Tile({
12068
12391
  }
12069
12392
 
12070
12393
  // src/scenes.tsx
12071
- import { jsx as jsx22, jsxs as jsxs13 } from "react/jsx-runtime";
12394
+ import { jsx as jsx23, jsxs as jsxs13 } from "react/jsx-runtime";
12072
12395
  function SceneSource({
12073
12396
  scene,
12074
12397
  visible,
@@ -12081,7 +12404,7 @@ function SceneSource({
12081
12404
  }
12082
12405
  switch (scene.type) {
12083
12406
  case "sphere":
12084
- return /* @__PURE__ */ jsx22(
12407
+ return /* @__PURE__ */ jsx23(
12085
12408
  Sphere,
12086
12409
  {
12087
12410
  src: scene.src,
@@ -12094,7 +12417,7 @@ function SceneSource({
12094
12417
  );
12095
12418
  case "tile": {
12096
12419
  const { id: _id, type: _type, ...tileProps } = scene;
12097
- return /* @__PURE__ */ jsx22(
12420
+ return /* @__PURE__ */ jsx23(
12098
12421
  Tile,
12099
12422
  {
12100
12423
  ...tileProps,
@@ -12118,9 +12441,9 @@ function SnapshotCapture({
12118
12441
  onCaptured
12119
12442
  }) {
12120
12443
  const { camera, gl, scene, size } = useThree19();
12121
- const capturedRequestRef = useRef26(0);
12122
- const renderTargetRef = useRef26(null);
12123
- useEffect26(
12444
+ const capturedRequestRef = useRef27(0);
12445
+ const renderTargetRef = useRef27(null);
12446
+ useEffect27(
12124
12447
  () => () => {
12125
12448
  renderTargetRef.current?.dispose();
12126
12449
  renderTargetRef.current = null;
@@ -12176,7 +12499,7 @@ function ScenesController({
12176
12499
  snapshotMaxPixels = 3686400,
12177
12500
  phaseRef: externalPhaseRef
12178
12501
  }) {
12179
- const controlsRef = useContext22(PanoramaViewContext);
12502
+ const controlsRef = useContext23(PanoramaViewContext);
12180
12503
  const manager = useSharedTileTextureManager();
12181
12504
  const transition = useMemo20(
12182
12505
  () => resolveTransition(transitionInput),
@@ -12199,13 +12522,13 @@ function ScenesController({
12199
12522
  const [transitionRunId, setTransitionRunId] = useState12(0);
12200
12523
  const [snapshot, setSnapshot] = useState12(null);
12201
12524
  const [recoveryKey, setRecoveryKey] = useState12(0);
12202
- const requestedSceneIdRef = useRef26(activeSceneId);
12203
- const captureReasonRef = useRef26("start");
12204
- const interactionReleaseRef = useRef26(null);
12205
- const slotsRef = useRef26(slots);
12206
- const phaseRef = useRef26(phase);
12207
- const liveSlotRef = useRef26(liveSlot);
12208
- const transitionFromRef = useRef26(initialScene);
12525
+ const requestedSceneIdRef = useRef27(activeSceneId);
12526
+ const captureReasonRef = useRef27("start");
12527
+ const interactionReleaseRef = useRef27(null);
12528
+ const slotsRef = useRef27(slots);
12529
+ const phaseRef = useRef27(phase);
12530
+ const liveSlotRef = useRef27(liveSlot);
12531
+ const transitionFromRef = useRef27(initialScene);
12209
12532
  slotsRef.current = slots;
12210
12533
  phaseRef.current = phase;
12211
12534
  if (externalPhaseRef) {
@@ -12230,7 +12553,7 @@ function ScenesController({
12230
12553
  setPendingSlot(nextSlot);
12231
12554
  setPhase("preloading");
12232
12555
  }, []);
12233
- useEffect26(() => {
12556
+ useEffect27(() => {
12234
12557
  const requested = sceneMap.get(activeSceneId);
12235
12558
  if (!requested) {
12236
12559
  reportError(activeSceneId, new Error(`Unknown panorama scene: ${activeSceneId}`));
@@ -12332,12 +12655,12 @@ function ScenesController({
12332
12655
  });
12333
12656
  }
12334
12657
  }, [onTransitionEnd, pendingSlot, releaseInteraction, snapshot, transition.preset]);
12335
- useEffect26(() => () => {
12658
+ useEffect27(() => () => {
12336
12659
  releaseInteraction();
12337
12660
  snapshot?.dispose();
12338
12661
  }, [releaseInteraction, snapshot]);
12339
12662
  const { gl } = useThree19();
12340
- useEffect26(() => {
12663
+ useEffect27(() => {
12341
12664
  const canvas = gl.domElement;
12342
12665
  const onContextLost = (event) => {
12343
12666
  event.preventDefault();
@@ -12362,7 +12685,7 @@ function ScenesController({
12362
12685
  const renderedScene = slots[liveSlot];
12363
12686
  const snapshotVisible = snapshot !== null && (phase === "transitioning" || phase === "recapturing" || phase === "preloading");
12364
12687
  return /* @__PURE__ */ jsxs13(Fragment6, { children: [
12365
- /* @__PURE__ */ jsx22(
12688
+ /* @__PURE__ */ jsx23(
12366
12689
  SnapshotCapture,
12367
12690
  {
12368
12691
  requestId: captureRequestId,
@@ -12374,7 +12697,7 @@ function ScenesController({
12374
12697
  const source = slots[slot];
12375
12698
  const isLive = slot === liveSlot;
12376
12699
  const isPending = slot === pendingSlot;
12377
- return /* @__PURE__ */ jsx22(
12700
+ return /* @__PURE__ */ jsx23(
12378
12701
  SceneSource,
12379
12702
  {
12380
12703
  scene: source,
@@ -12390,7 +12713,7 @@ function ScenesController({
12390
12713
  `${slot}:${source?.id ?? "empty"}:${recoveryKey}`
12391
12714
  );
12392
12715
  }),
12393
- snapshotVisible ? /* @__PURE__ */ jsx22(
12716
+ snapshotVisible ? /* @__PURE__ */ jsx23(
12394
12717
  TransitionOverlay,
12395
12718
  {
12396
12719
  snapshot,
@@ -12427,13 +12750,13 @@ function Scenes({
12427
12750
  },
12428
12751
  [isControlled, onActiveSceneIdChange]
12429
12752
  );
12430
- const scenesRef = useRef26(scenes);
12753
+ const scenesRef = useRef27(scenes);
12431
12754
  scenesRef.current = scenes;
12432
- const resolvedIdRef = useRef26(resolvedId);
12755
+ const resolvedIdRef = useRef27(resolvedId);
12433
12756
  resolvedIdRef.current = resolvedId;
12434
- const host = useContext22(ScenesHostContext);
12435
- const phaseRef = useRef26("idle");
12436
- useEffect26(() => {
12757
+ const host = useContext23(ScenesHostContext);
12758
+ const phaseRef = useRef27("idle");
12759
+ useEffect27(() => {
12437
12760
  if (!host) {
12438
12761
  return;
12439
12762
  }
@@ -12483,12 +12806,12 @@ function Scenes({
12483
12806
  }
12484
12807
  };
12485
12808
  }, [host, requestSceneChange]);
12486
- return /* @__PURE__ */ jsx22(
12809
+ return /* @__PURE__ */ jsx23(
12487
12810
  TileTextureManagerProvider,
12488
12811
  {
12489
12812
  maxTextureMemoryMb,
12490
12813
  maxConcurrentLoads: maxConcurrentTileLoads,
12491
- children: /* @__PURE__ */ jsx22(
12814
+ children: /* @__PURE__ */ jsx23(
12492
12815
  ScenesController,
12493
12816
  {
12494
12817
  ...rest,
@@ -12503,7 +12826,7 @@ function Scenes({
12503
12826
 
12504
12827
  // src/hotspot/image-hotspot.tsx
12505
12828
  import { useThree as useThree21 } from "@react-three/fiber";
12506
- import { useEffect as useEffect29, useRef as useRef28, useState as useState15 } from "react";
12829
+ import { useEffect as useEffect30, useRef as useRef29, useState as useState15 } from "react";
12507
12830
  import {
12508
12831
  ClampToEdgeWrapping as ClampToEdgeWrapping3,
12509
12832
  LinearFilter as LinearFilter6,
@@ -12515,11 +12838,11 @@ import {
12515
12838
  // src/hotspot/hotspot-anchor.tsx
12516
12839
  import { useFrame as useFrame13, useThree as useThree20 } from "@react-three/fiber";
12517
12840
  import {
12518
- useContext as useContext24,
12519
- useEffect as useEffect28,
12841
+ useContext as useContext25,
12842
+ useEffect as useEffect29,
12520
12843
  useLayoutEffect as useLayoutEffect4,
12521
12844
  useMemo as useMemo22,
12522
- useRef as useRef27,
12845
+ useRef as useRef28,
12523
12846
  useState as useState14
12524
12847
  } from "react";
12525
12848
  import {
@@ -12536,16 +12859,16 @@ import {
12536
12859
  } from "three";
12537
12860
 
12538
12861
  // src/hotspot/hotspot-tooltip.tsx
12539
- import { useEffect as useEffect27, useMemo as useMemo21, useState as useState13 } from "react";
12862
+ import { useEffect as useEffect28, useMemo as useMemo21, useState as useState13 } from "react";
12540
12863
 
12541
12864
  // src/webvr/stereo-html.tsx
12542
12865
  import { Html } from "@react-three/drei";
12543
- import { useContext as useContext23, useSyncExternalStore as useSyncExternalStore6 } from "react";
12544
- import { Fragment as Fragment7, jsx as jsx23, jsxs as jsxs14 } from "react/jsx-runtime";
12866
+ import { useContext as useContext24, useSyncExternalStore as useSyncExternalStore7 } from "react";
12867
+ import { Fragment as Fragment7, jsx as jsx24, jsxs as jsxs14 } from "react/jsx-runtime";
12545
12868
  function useFallbackStereoView() {
12546
- const runtime = useContext23(WebVRRuntimeContext);
12869
+ const runtime = useContext24(WebVRRuntimeContext);
12547
12870
  const host = runtime?.host ?? null;
12548
- const fallback = useSyncExternalStore6(
12871
+ const fallback = useSyncExternalStore7(
12549
12872
  (onStoreChange) => host ? subscribeWebVRHost(host, onStoreChange) : () => void 0,
12550
12873
  () => isFallbackStereoMode(host?.snapshot.mode ?? null),
12551
12874
  () => false
@@ -12566,10 +12889,10 @@ function stereoCalculatePosition(eye, stereoView) {
12566
12889
  function PanoHtml({ children, ...htmlProps }) {
12567
12890
  const stereoView = useFallbackStereoView();
12568
12891
  if (!stereoView) {
12569
- return /* @__PURE__ */ jsx23(Html, { ...htmlProps, children });
12892
+ return /* @__PURE__ */ jsx24(Html, { ...htmlProps, children });
12570
12893
  }
12571
12894
  return /* @__PURE__ */ jsxs14(Fragment7, { children: [
12572
- /* @__PURE__ */ jsx23(
12895
+ /* @__PURE__ */ jsx24(
12573
12896
  Html,
12574
12897
  {
12575
12898
  ...htmlProps,
@@ -12577,7 +12900,7 @@ function PanoHtml({ children, ...htmlProps }) {
12577
12900
  children
12578
12901
  }
12579
12902
  ),
12580
- /* @__PURE__ */ jsx23(
12903
+ /* @__PURE__ */ jsx24(
12581
12904
  Html,
12582
12905
  {
12583
12906
  ...htmlProps,
@@ -12590,7 +12913,7 @@ function PanoHtml({ children, ...htmlProps }) {
12590
12913
  }
12591
12914
 
12592
12915
  // src/hotspot/hotspot-tooltip.tsx
12593
- import { jsx as jsx24, jsxs as jsxs15 } from "react/jsx-runtime";
12916
+ import { jsx as jsx25, jsxs as jsxs15 } from "react/jsx-runtime";
12594
12917
  var DEFAULT_HOTSPOT_TOOLTIP_OFFSET = 12;
12595
12918
  var DEFAULT_HOTSPOT_TOOLTIP_APPEARANCE = {
12596
12919
  background: "rgba(22, 22, 22, 0.72)",
@@ -12660,7 +12983,7 @@ function HotspotTooltip({
12660
12983
  appearance
12661
12984
  }) {
12662
12985
  const [imageFailed, setImageFailed] = useState13(false);
12663
- useEffect27(() => {
12986
+ useEffect28(() => {
12664
12987
  setImageFailed(false);
12665
12988
  }, [content.image]);
12666
12989
  const showImage = Boolean(content.image) && !imageFailed;
@@ -12687,14 +13010,14 @@ function HotspotTooltip({
12687
13010
  if (!showImage && !content.text) {
12688
13011
  return null;
12689
13012
  }
12690
- return /* @__PURE__ */ jsx24(PanoHtml, { pointerEvents: "none", style: WRAPPER_STYLE, zIndexRange: [20, 10], children: /* @__PURE__ */ jsxs15(
13013
+ return /* @__PURE__ */ jsx25(PanoHtml, { pointerEvents: "none", style: WRAPPER_STYLE, zIndexRange: [20, 10], children: /* @__PURE__ */ jsxs15(
12691
13014
  "div",
12692
13015
  {
12693
13016
  className: "pano-hotspot-tooltip",
12694
13017
  role: "tooltip",
12695
13018
  style: bubbleStyle,
12696
13019
  children: [
12697
- showImage ? /* @__PURE__ */ jsx24(
13020
+ showImage ? /* @__PURE__ */ jsx25(
12698
13021
  "img",
12699
13022
  {
12700
13023
  alt: content.imageAlt ?? content.text ?? "",
@@ -12703,14 +13026,14 @@ function HotspotTooltip({
12703
13026
  src: content.image
12704
13027
  }
12705
13028
  ) : null,
12706
- content.text ? /* @__PURE__ */ jsx24("p", { className: "pano-hotspot-tooltip-text", children: content.text }) : null
13029
+ content.text ? /* @__PURE__ */ jsx25("p", { className: "pano-hotspot-tooltip-text", children: content.text }) : null
12707
13030
  ]
12708
13031
  }
12709
13032
  ) });
12710
13033
  }
12711
13034
 
12712
13035
  // src/hotspot/hotspot-anchor.tsx
12713
- import { jsx as jsx25, jsxs as jsxs16 } from "react/jsx-runtime";
13036
+ import { jsx as jsx26, jsxs as jsxs16 } from "react/jsx-runtime";
12714
13037
  var DEFAULT_FLOATING_DISTANCE = 10;
12715
13038
  var PANORAMA_RADIUS = DEFAULT_PANORAMA_RADIUS;
12716
13039
  var PANORAMA_SURFACE_INSET = 4;
@@ -13047,14 +13370,15 @@ function HotspotAnchor({
13047
13370
  onPositionChange,
13048
13371
  onDragEnd
13049
13372
  }) {
13050
- const controlsRef = useContext24(PanoramaViewContext);
13051
- const eventBus = useContext24(PanoEventBusContext);
13373
+ const controlsRef = useContext25(PanoramaViewContext);
13374
+ const hotspotTargetRegistry = useContext25(HotspotTargetRegistryContext);
13375
+ const eventBus = useContext25(PanoEventBusContext);
13052
13376
  const cursorApi = usePanoCursor();
13053
13377
  const { camera, size } = useThree20();
13054
- const groupRef = useRef27(null);
13055
- const tooltipAnchorRef = useRef27(null);
13056
- const dragStateRef = useRef27(null);
13057
- const suppressNextClickRef = useRef27(false);
13378
+ const groupRef = useRef28(null);
13379
+ const tooltipAnchorRef = useRef28(null);
13380
+ const dragStateRef = useRef28(null);
13381
+ const suppressNextClickRef = useRef28(false);
13058
13382
  const [hovered, setHovered] = useState14(false);
13059
13383
  const [dragging, setDragging] = useState14(false);
13060
13384
  const [pinned, setPinned] = useState14(false);
@@ -13063,6 +13387,12 @@ function HotspotAnchor({
13063
13387
  [tooltip]
13064
13388
  );
13065
13389
  const normalizedPosition = normalizePanoPosition(position);
13390
+ useEffect29(() => {
13391
+ if (!hotspotTargetRegistry) {
13392
+ return;
13393
+ }
13394
+ return hotspotTargetRegistry.register(id, normalizedPosition);
13395
+ }, [hotspotTargetRegistry, id, normalizedPosition.pitch, normalizedPosition.yaw]);
13066
13396
  const rendering = internalOrientation && internalPlacement ? { orientation: internalOrientation, placement: internalPlacement } : HOTSPOT_MODE_RENDERING[mode];
13067
13397
  const { orientation: orientation2, placement } = rendering;
13068
13398
  const resolvedScale = resolveScale(scale);
@@ -13111,14 +13441,14 @@ function HotspotAnchor({
13111
13441
  });
13112
13442
  const tooltipOpen = visible && tooltipContent !== null && isTooltipOpen(tooltipTrigger, hovered, focused, pinned);
13113
13443
  const cursorClaimId = hotspotCursorClaimId(id);
13114
- useEffect28(
13444
+ useEffect29(
13115
13445
  () => () => {
13116
13446
  dragStateRef.current?.releaseInteractionLock();
13117
13447
  dragStateRef.current = null;
13118
13448
  },
13119
13449
  []
13120
13450
  );
13121
- useEffect28(() => {
13451
+ useEffect29(() => {
13122
13452
  if (!cursorApi) {
13123
13453
  return;
13124
13454
  }
@@ -13140,14 +13470,14 @@ function HotspotAnchor({
13140
13470
  hovered,
13141
13471
  visible
13142
13472
  ]);
13143
- useEffect28(
13473
+ useEffect29(
13144
13474
  () => () => {
13145
13475
  cursorApi?.release(cursorClaimId);
13146
13476
  },
13147
13477
  [cursorApi, cursorClaimId]
13148
13478
  );
13149
- useEffect28(() => () => focusGeometry.dispose(), [focusGeometry]);
13150
- useEffect28(() => {
13479
+ useEffect29(() => () => focusGeometry.dispose(), [focusGeometry]);
13480
+ useEffect29(() => {
13151
13481
  if (tooltipTrigger !== "click") {
13152
13482
  setPinned(false);
13153
13483
  return;
@@ -13156,12 +13486,12 @@ function HotspotAnchor({
13156
13486
  setPinned(false);
13157
13487
  });
13158
13488
  }, [eventBus, tooltipTrigger]);
13159
- useEffect28(() => {
13489
+ useEffect29(() => {
13160
13490
  if (tooltipTrigger !== "hover") {
13161
13491
  setHovered(false);
13162
13492
  }
13163
13493
  }, [tooltipTrigger]);
13164
- useEffect28(() => {
13494
+ useEffect29(() => {
13165
13495
  if (acceptsPointer) {
13166
13496
  return;
13167
13497
  }
@@ -13350,18 +13680,18 @@ function HotspotAnchor({
13350
13680
  } : void 0,
13351
13681
  onPointerUp: acceptsPointer ? (event) => releasePointer(event, true) : void 0,
13352
13682
  children: [
13353
- focused ? focusContent ?? /* @__PURE__ */ jsx25(
13683
+ focused ? focusContent ?? /* @__PURE__ */ jsx26(
13354
13684
  "lineSegments",
13355
13685
  {
13356
13686
  geometry: focusGeometry,
13357
13687
  position: [0, 0, 0.01],
13358
13688
  renderOrder: renderOrder + 1,
13359
13689
  scale: [1.12, 1.12, 1],
13360
- children: /* @__PURE__ */ jsx25("lineBasicMaterial", { color: "#f5fbfc", depthTest: false })
13690
+ children: /* @__PURE__ */ jsx26("lineBasicMaterial", { color: "#f5fbfc", depthTest: false })
13361
13691
  }
13362
13692
  ) : null,
13363
13693
  children,
13364
- tooltipOpen && tooltipContent ? /* @__PURE__ */ jsx25("group", { ref: tooltipAnchorRef, children: /* @__PURE__ */ jsx25(
13694
+ tooltipOpen && tooltipContent ? /* @__PURE__ */ jsx26("group", { ref: tooltipAnchorRef, children: /* @__PURE__ */ jsx26(
13365
13695
  HotspotTooltip,
13366
13696
  {
13367
13697
  appearance: tooltipAppearance,
@@ -13382,7 +13712,7 @@ import {
13382
13712
  MeshBasicMaterial,
13383
13713
  Vector2 as Vector26
13384
13714
  } from "three";
13385
- import { jsx as jsx26, jsxs as jsxs17 } from "react/jsx-runtime";
13715
+ import { jsx as jsx27, jsxs as jsxs17 } from "react/jsx-runtime";
13386
13716
  var HOTSPOT_ALPHA_CUTOFF = 0.05;
13387
13717
  var SAMPLE_UV = new Vector26();
13388
13718
  var RAYCAST_HITS = [];
@@ -13485,8 +13815,8 @@ function HotspotPlane({
13485
13815
  opacity
13486
13816
  }) {
13487
13817
  return /* @__PURE__ */ jsxs17("mesh", { raycast: hotspotPlaneRaycast, children: [
13488
- /* @__PURE__ */ jsx26("planeGeometry", { args: [1, 1] }),
13489
- /* @__PURE__ */ jsx26(
13818
+ /* @__PURE__ */ jsx27("planeGeometry", { args: [1, 1] }),
13819
+ /* @__PURE__ */ jsx27(
13490
13820
  "meshBasicMaterial",
13491
13821
  {
13492
13822
  alphaTest: HOTSPOT_ALPHA_CUTOFF,
@@ -13502,15 +13832,15 @@ function HotspotPlane({
13502
13832
  }
13503
13833
 
13504
13834
  // src/hotspot/image-hotspot.tsx
13505
- import { jsx as jsx27 } from "react/jsx-runtime";
13835
+ import { jsx as jsx28 } from "react/jsx-runtime";
13506
13836
  function useHotspotImageTexture(src, onLoad, onError) {
13507
13837
  const gl = useThree21((state) => state.gl);
13508
13838
  const [texture, setTexture] = useState15(null);
13509
- const onLoadRef = useRef28(onLoad);
13510
- const onErrorRef = useRef28(onError);
13839
+ const onLoadRef = useRef29(onLoad);
13840
+ const onErrorRef = useRef29(onError);
13511
13841
  onLoadRef.current = onLoad;
13512
13842
  onErrorRef.current = onError;
13513
- useEffect29(() => {
13843
+ useEffect30(() => {
13514
13844
  let active = true;
13515
13845
  setTexture(null);
13516
13846
  if (!src) {
@@ -13548,7 +13878,7 @@ function useHotspotImageTexture(src, onLoad, onError) {
13548
13878
  active = false;
13549
13879
  };
13550
13880
  }, [gl, src]);
13551
- useEffect29(
13881
+ useEffect30(
13552
13882
  () => () => {
13553
13883
  texture?.dispose();
13554
13884
  },
@@ -13566,11 +13896,11 @@ function ImageHotspot({
13566
13896
  ...anchorProps
13567
13897
  }) {
13568
13898
  const texture = useHotspotImageTexture(src, onLoad, onError);
13569
- return /* @__PURE__ */ jsx27(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ jsx27(HotspotPlane, { map: texture, opacity }) });
13899
+ return /* @__PURE__ */ jsx28(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ jsx28(HotspotPlane, { map: texture, opacity }) });
13570
13900
  }
13571
13901
 
13572
13902
  // src/hotspot/polygon-hotspot.tsx
13573
- import { useEffect as useEffect30, useMemo as useMemo23, useRef as useRef30 } from "react";
13903
+ import { useEffect as useEffect31, useMemo as useMemo23, useRef as useRef31 } from "react";
13574
13904
  import {
13575
13905
  BufferGeometry,
13576
13906
  DoubleSide as DoubleSide5,
@@ -13585,13 +13915,13 @@ import {
13585
13915
  // src/hotspot/hotspot-stroke-line.tsx
13586
13916
  import { Line } from "@react-three/drei";
13587
13917
  import { useFrame as useFrame14, useThree as useThree22 } from "@react-three/fiber";
13588
- import { useLayoutEffect as useLayoutEffect5, useRef as useRef29 } from "react";
13918
+ import { useLayoutEffect as useLayoutEffect5, useRef as useRef30 } from "react";
13589
13919
  import {
13590
13920
  MathUtils as MathUtils8,
13591
13921
  PerspectiveCamera as PerspectiveCamera6,
13592
13922
  Vector3 as Vector314
13593
13923
  } from "three";
13594
- import { jsx as jsx28 } from "react/jsx-runtime";
13924
+ import { jsx as jsx29 } from "react/jsx-runtime";
13595
13925
  var LINE_WORLD_POSITION = new Vector314();
13596
13926
  function applyScreenSpaceDashScale(object, camera, viewportHeight) {
13597
13927
  const material = object?.material;
@@ -13622,7 +13952,7 @@ function HotspotStrokeLine({
13622
13952
  dashSize,
13623
13953
  gapSize
13624
13954
  }) {
13625
- const lineRef = useRef29(null);
13955
+ const lineRef = useRef30(null);
13626
13956
  const { camera, size } = useThree22();
13627
13957
  const dash = resolveDash(dashSize, gapSize);
13628
13958
  useLayoutEffect5(() => {
@@ -13637,7 +13967,7 @@ function HotspotStrokeLine({
13637
13967
  }
13638
13968
  applyScreenSpaceDashScale(lineRef.current, state.camera, state.size.height);
13639
13969
  });
13640
- return /* @__PURE__ */ jsx28(
13970
+ return /* @__PURE__ */ jsx29(
13641
13971
  Line,
13642
13972
  {
13643
13973
  ref: lineRef,
@@ -13659,7 +13989,7 @@ function HotspotStrokeLine({
13659
13989
  }
13660
13990
 
13661
13991
  // src/hotspot/polygon-hotspot.tsx
13662
- import { jsx as jsx29, jsxs as jsxs18 } from "react/jsx-runtime";
13992
+ import { jsx as jsx30, jsxs as jsxs18 } from "react/jsx-runtime";
13663
13993
  var POLYGON_RADIUS = 990;
13664
13994
  var MAX_FILL_SEGMENT_DEGREES = 7;
13665
13995
  function cloneVertices(vertices) {
@@ -13927,12 +14257,12 @@ function PolygonHotspot({
13927
14257
  [center, valid, vertices]
13928
14258
  );
13929
14259
  const resolvedStrokeOpacity = Math.max(0, Math.min(strokeOpacity, 1));
13930
- const startVerticesRef = useRef30(null);
14260
+ const startVerticesRef = useRef31(null);
13931
14261
  const issuesKey = issues.map((issue) => issue.code).join(",");
13932
- useEffect30(() => {
14262
+ useEffect31(() => {
13933
14263
  if (!valid) onInvalid?.(issues);
13934
14264
  }, [issues, issuesKey, onInvalid, valid]);
13935
- useEffect30(() => () => fillGeometry?.dispose(), [fillGeometry]);
14265
+ useEffect31(() => () => fillGeometry?.dispose(), [fillGeometry]);
13936
14266
  if (!valid || !center || !fillGeometry || !strokePoints || strokePoints.length < 2) {
13937
14267
  return null;
13938
14268
  }
@@ -13962,7 +14292,7 @@ function PolygonHotspot({
13962
14292
  draggable,
13963
14293
  interactive,
13964
14294
  useAngularScale: false,
13965
- focusContent: /* @__PURE__ */ jsx29(
14295
+ focusContent: /* @__PURE__ */ jsx30(
13966
14296
  HotspotStrokeLine,
13967
14297
  {
13968
14298
  color: "#75cbd3",
@@ -13984,7 +14314,7 @@ function PolygonHotspot({
13984
14314
  startVerticesRef.current = null;
13985
14315
  },
13986
14316
  children: [
13987
- /* @__PURE__ */ jsx29("mesh", { geometry: fillGeometry, renderOrder, children: /* @__PURE__ */ jsx29(
14317
+ /* @__PURE__ */ jsx30("mesh", { geometry: fillGeometry, renderOrder, children: /* @__PURE__ */ jsx30(
13988
14318
  "meshBasicMaterial",
13989
14319
  {
13990
14320
  color: fill,
@@ -13994,7 +14324,7 @@ function PolygonHotspot({
13994
14324
  transparent: true
13995
14325
  }
13996
14326
  ) }),
13997
- /* @__PURE__ */ jsx29(
14327
+ /* @__PURE__ */ jsx30(
13998
14328
  HotspotStrokeLine,
13999
14329
  {
14000
14330
  color: stroke,
@@ -14012,14 +14342,14 @@ function PolygonHotspot({
14012
14342
  }
14013
14343
 
14014
14344
  // src/hotspot/polyline-hotspot.tsx
14015
- import { useEffect as useEffect31, useMemo as useMemo24, useRef as useRef31 } from "react";
14345
+ import { useEffect as useEffect32, useMemo as useMemo24, useRef as useRef32 } from "react";
14016
14346
  import {
14017
14347
  MathUtils as MathUtils9,
14018
14348
  Matrix4 as Matrix44,
14019
14349
  Quaternion as Quaternion5,
14020
14350
  Vector3 as Vector316
14021
14351
  } from "three";
14022
- import { jsx as jsx30 } from "react/jsx-runtime";
14352
+ import { jsx as jsx31 } from "react/jsx-runtime";
14023
14353
  var POLYLINE_RADIUS = 990;
14024
14354
  var MAX_SEGMENT_DEGREES = 7;
14025
14355
  function cloneVertices2(vertices) {
@@ -14144,8 +14474,8 @@ function PolylineHotspot({
14144
14474
  [center, valid, vertices]
14145
14475
  );
14146
14476
  const opacity = Math.max(0, Math.min(strokeOpacity, 1));
14147
- const startVerticesRef = useRef31(null);
14148
- useEffect31(() => {
14477
+ const startVerticesRef = useRef32(null);
14478
+ useEffect32(() => {
14149
14479
  if (!valid) onInvalid?.(issues);
14150
14480
  }, [issues, onInvalid, valid]);
14151
14481
  if (!valid || !center || !linePoints || linePoints.length < 2) return null;
@@ -14159,7 +14489,7 @@ function PolylineHotspot({
14159
14489
  startPosition: event.startPosition
14160
14490
  });
14161
14491
  };
14162
- return /* @__PURE__ */ jsx30(
14492
+ return /* @__PURE__ */ jsx31(
14163
14493
  HotspotAnchor,
14164
14494
  {
14165
14495
  ...anchorProps,
@@ -14173,7 +14503,7 @@ function PolylineHotspot({
14173
14503
  renderOrder,
14174
14504
  draggable,
14175
14505
  useAngularScale: false,
14176
- focusContent: /* @__PURE__ */ jsx30(
14506
+ focusContent: /* @__PURE__ */ jsx31(
14177
14507
  HotspotStrokeLine,
14178
14508
  {
14179
14509
  color: "#75cbd3",
@@ -14194,7 +14524,7 @@ function PolylineHotspot({
14194
14524
  emitVerticesChange(event, onDragEnd);
14195
14525
  startVerticesRef.current = null;
14196
14526
  },
14197
- children: /* @__PURE__ */ jsx30(
14527
+ children: /* @__PURE__ */ jsx31(
14198
14528
  HotspotStrokeLine,
14199
14529
  {
14200
14530
  color: stroke,
@@ -14211,7 +14541,7 @@ function PolylineHotspot({
14211
14541
  }
14212
14542
 
14213
14543
  // src/hotspot/graphic-hotspot.tsx
14214
- import { useEffect as useEffect32, useRef as useRef32, useState as useState16 } from "react";
14544
+ import { useEffect as useEffect33, useRef as useRef33, useState as useState16 } from "react";
14215
14545
  import {
14216
14546
  CanvasTexture,
14217
14547
  ClampToEdgeWrapping as ClampToEdgeWrapping4,
@@ -14219,7 +14549,7 @@ import {
14219
14549
  LinearMipmapLinearFilter as LinearMipmapLinearFilter4,
14220
14550
  SRGBColorSpace as SRGBColorSpace6
14221
14551
  } from "three";
14222
- import { jsx as jsx31 } from "react/jsx-runtime";
14552
+ import { jsx as jsx32 } from "react/jsx-runtime";
14223
14553
  var GRAPHIC_TEXTURE_SIZE = 512;
14224
14554
  function resolveStrokeWidth(value) {
14225
14555
  return Number.isFinite(value) ? Math.max(value, 0) : 8;
@@ -14409,11 +14739,11 @@ function createGraphicTexture(graphic, aspectWidth, aspectHeight) {
14409
14739
  }
14410
14740
  function useGraphicTexture(graphic, aspectWidth, aspectHeight, onLoad, onError) {
14411
14741
  const [texture, setTexture] = useState16(null);
14412
- const onLoadRef = useRef32(onLoad);
14413
- const onErrorRef = useRef32(onError);
14742
+ const onLoadRef = useRef33(onLoad);
14743
+ const onErrorRef = useRef33(onError);
14414
14744
  onLoadRef.current = onLoad;
14415
14745
  onErrorRef.current = onError;
14416
- useEffect32(() => {
14746
+ useEffect33(() => {
14417
14747
  let nextTexture = null;
14418
14748
  try {
14419
14749
  nextTexture = createGraphicTexture(graphic, aspectWidth, aspectHeight);
@@ -14439,20 +14769,20 @@ function CanvasGraphicHotspot({
14439
14769
  ...anchorProps
14440
14770
  }) {
14441
14771
  const texture = useGraphicTexture(graphic, width, height, onLoad, onError);
14442
- return /* @__PURE__ */ jsx31(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ jsx31(HotspotPlane, { map: texture, opacity }) });
14772
+ return /* @__PURE__ */ jsx32(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ jsx32(HotspotPlane, { map: texture, opacity }) });
14443
14773
  }
14444
14774
  function GraphicHotspot(props) {
14445
14775
  const { graphic, ...restProps } = props;
14446
14776
  if (graphic.kind === "svg") {
14447
14777
  const imageProps = restProps;
14448
- return /* @__PURE__ */ jsx31(ImageHotspot, { ...imageProps, src: graphic.src });
14778
+ return /* @__PURE__ */ jsx32(ImageHotspot, { ...imageProps, src: graphic.src });
14449
14779
  }
14450
- return /* @__PURE__ */ jsx31(CanvasGraphicHotspot, { ...restProps, graphic });
14780
+ return /* @__PURE__ */ jsx32(CanvasGraphicHotspot, { ...restProps, graphic });
14451
14781
  }
14452
14782
 
14453
14783
  // src/hotspot/sequence-hotspot.tsx
14454
14784
  import { useFrame as useFrame15, useThree as useThree23 } from "@react-three/fiber";
14455
- import { useEffect as useEffect33, useRef as useRef33, useState as useState17 } from "react";
14785
+ import { useEffect as useEffect34, useRef as useRef34, useState as useState17 } from "react";
14456
14786
  import {
14457
14787
  ClampToEdgeWrapping as ClampToEdgeWrapping5,
14458
14788
  LinearFilter as LinearFilter8,
@@ -14460,7 +14790,7 @@ import {
14460
14790
  SRGBColorSpace as SRGBColorSpace7,
14461
14791
  TextureLoader as TextureLoader6
14462
14792
  } from "three";
14463
- import { jsx as jsx32 } from "react/jsx-runtime";
14793
+ import { jsx as jsx33 } from "react/jsx-runtime";
14464
14794
  var DEFAULT_SEQUENCE_FPS = 12;
14465
14795
  function resolveFps(value) {
14466
14796
  return Number.isFinite(value) && value > 0 ? value : DEFAULT_SEQUENCE_FPS;
@@ -14476,11 +14806,11 @@ function useSpriteTexture({
14476
14806
  }) {
14477
14807
  const gl = useThree23((state) => state.gl);
14478
14808
  const [texture, setTexture] = useState17(null);
14479
- const onErrorRef = useRef33(onError);
14480
- const onLoadProgressRef = useRef33(onLoadProgress);
14809
+ const onErrorRef = useRef34(onError);
14810
+ const onLoadProgressRef = useRef34(onLoadProgress);
14481
14811
  onErrorRef.current = onError;
14482
14812
  onLoadProgressRef.current = onLoadProgress;
14483
- useEffect33(() => {
14813
+ useEffect34(() => {
14484
14814
  let active = true;
14485
14815
  setTexture(null);
14486
14816
  if (!src) {
@@ -14521,7 +14851,7 @@ function useSpriteTexture({
14521
14851
  active = false;
14522
14852
  };
14523
14853
  }, [gl, id, src]);
14524
- useEffect33(
14854
+ useEffect34(
14525
14855
  () => () => {
14526
14856
  texture?.dispose();
14527
14857
  },
@@ -14551,23 +14881,23 @@ function SequenceHotspot({
14551
14881
  const frameCount = resolveFrameCount(requestedFrameCount);
14552
14882
  const safeFps = resolveFps(fps);
14553
14883
  const [frameIndex, setFrameIndex] = useState17(0);
14554
- const elapsedRef = useRef33(0);
14555
- const frameIndexRef = useRef33(0);
14556
- const endedRef = useRef33(false);
14557
- const lastPlaybackStateRef = useRef33(null);
14558
- const onFrameChangeRef = useRef33(onFrameChange);
14559
- const onPlaybackStateChangeRef = useRef33(onPlaybackStateChange);
14560
- const onEndedRef = useRef33(onEnded);
14884
+ const elapsedRef = useRef34(0);
14885
+ const frameIndexRef = useRef34(0);
14886
+ const endedRef = useRef34(false);
14887
+ const lastPlaybackStateRef = useRef34(null);
14888
+ const onFrameChangeRef = useRef34(onFrameChange);
14889
+ const onPlaybackStateChangeRef = useRef34(onPlaybackStateChange);
14890
+ const onEndedRef = useRef34(onEnded);
14561
14891
  onFrameChangeRef.current = onFrameChange;
14562
14892
  onPlaybackStateChangeRef.current = onPlaybackStateChange;
14563
14893
  onEndedRef.current = onEnded;
14564
- useEffect33(() => {
14894
+ useEffect34(() => {
14565
14895
  elapsedRef.current = 0;
14566
14896
  frameIndexRef.current = 0;
14567
14897
  endedRef.current = false;
14568
14898
  setFrameIndex(0);
14569
14899
  }, [frameCount, frameDirection, src]);
14570
- useEffect33(() => {
14900
+ useEffect34(() => {
14571
14901
  if (!texture) {
14572
14902
  return;
14573
14903
  }
@@ -14581,13 +14911,13 @@ function SequenceHotspot({
14581
14911
  );
14582
14912
  texture.needsUpdate = true;
14583
14913
  }, [frameCount, frameDirection, frameIndex, texture]);
14584
- useEffect33(() => {
14914
+ useEffect34(() => {
14585
14915
  if (!texture) {
14586
14916
  return;
14587
14917
  }
14588
14918
  onFrameChangeRef.current?.({ id, index: 0, src });
14589
14919
  }, [id, src, texture]);
14590
- useEffect33(() => {
14920
+ useEffect34(() => {
14591
14921
  if (!texture) {
14592
14922
  return;
14593
14923
  }
@@ -14636,12 +14966,12 @@ function SequenceHotspot({
14636
14966
  onFrameChangeRef.current?.({ id, index: nextIndex, src });
14637
14967
  }
14638
14968
  });
14639
- return /* @__PURE__ */ jsx32(HotspotAnchor, { ...anchorProps, id, height, width, children: /* @__PURE__ */ jsx32(HotspotPlane, { map: texture, opacity }) });
14969
+ return /* @__PURE__ */ jsx33(HotspotAnchor, { ...anchorProps, id, height, width, children: /* @__PURE__ */ jsx33(HotspotPlane, { map: texture, opacity }) });
14640
14970
  }
14641
14971
 
14642
14972
  // src/hotspot/video-hotspot.tsx
14643
14973
  import { useThree as useThree24 } from "@react-three/fiber";
14644
- import { useEffect as useEffect34, useRef as useRef34, useState as useState18 } from "react";
14974
+ import { useEffect as useEffect35, useRef as useRef35, useState as useState18 } from "react";
14645
14975
  import {
14646
14976
  ClampToEdgeWrapping as ClampToEdgeWrapping6,
14647
14977
  LinearFilter as LinearFilter9,
@@ -14650,7 +14980,7 @@ import {
14650
14980
  TextureLoader as TextureLoader7,
14651
14981
  VideoTexture as VideoTexture2
14652
14982
  } from "three";
14653
- import { jsx as jsx33 } from "react/jsx-runtime";
14983
+ import { jsx as jsx34 } from "react/jsx-runtime";
14654
14984
  function clampVolume2(volume) {
14655
14985
  if (!Number.isFinite(volume)) {
14656
14986
  return 1;
@@ -14660,9 +14990,9 @@ function clampVolume2(volume) {
14660
14990
  function usePosterTexture2(id, poster, onError) {
14661
14991
  const gl = useThree24((state) => state.gl);
14662
14992
  const [texture, setTexture] = useState18(null);
14663
- const onErrorRef = useRef34(onError);
14993
+ const onErrorRef = useRef35(onError);
14664
14994
  onErrorRef.current = onError;
14665
- useEffect34(() => {
14995
+ useEffect35(() => {
14666
14996
  let active = true;
14667
14997
  setTexture(null);
14668
14998
  if (!poster) {
@@ -14699,7 +15029,7 @@ function usePosterTexture2(id, poster, onError) {
14699
15029
  active = false;
14700
15030
  };
14701
15031
  }, [gl, id, poster]);
14702
- useEffect34(
15032
+ useEffect35(
14703
15033
  () => () => {
14704
15034
  texture?.dispose();
14705
15035
  },
@@ -14718,13 +15048,13 @@ function useVideoResource({
14718
15048
  src
14719
15049
  }) {
14720
15050
  const [resource, setResource] = useState18(null);
14721
- const onEndedRef = useRef34(onEnded);
14722
- const onErrorRef = useRef34(onError);
14723
- const onPlaybackStateChangeRef = useRef34(onPlaybackStateChange);
15051
+ const onEndedRef = useRef35(onEnded);
15052
+ const onErrorRef = useRef35(onError);
15053
+ const onPlaybackStateChangeRef = useRef35(onPlaybackStateChange);
14724
15054
  onEndedRef.current = onEnded;
14725
15055
  onErrorRef.current = onError;
14726
15056
  onPlaybackStateChangeRef.current = onPlaybackStateChange;
14727
- useEffect34(() => {
15057
+ useEffect35(() => {
14728
15058
  if (!src) {
14729
15059
  setResource(null);
14730
15060
  return;
@@ -14734,7 +15064,12 @@ function useVideoResource({
14734
15064
  if (crossOrigin !== void 0) {
14735
15065
  video.crossOrigin = crossOrigin;
14736
15066
  }
14737
- video.playsInline = playsInline ?? true;
15067
+ const inline = playsInline ?? true;
15068
+ video.playsInline = inline;
15069
+ if (inline) {
15070
+ video.setAttribute("playsinline", "true");
15071
+ video.setAttribute("webkit-playsinline", "true");
15072
+ }
14738
15073
  video.poster = poster ?? "";
14739
15074
  const texture = new VideoTexture2(video);
14740
15075
  texture.colorSpace = SRGBColorSpace8;
@@ -14814,6 +15149,7 @@ function VideoHotspot({
14814
15149
  onError,
14815
15150
  ...anchorProps
14816
15151
  }) {
15152
+ usePanoMediaActivationIntent(playing);
14817
15153
  const resource = useVideoResource({
14818
15154
  crossOrigin,
14819
15155
  id,
@@ -14825,11 +15161,11 @@ function VideoHotspot({
14825
15161
  src
14826
15162
  });
14827
15163
  const posterTexture = usePosterTexture2(id, poster, onError);
14828
- const onPlaybackErrorRef = useRef34(onPlaybackError);
14829
- const onPlaybackStateChangeRef = useRef34(onPlaybackStateChange);
15164
+ const onPlaybackErrorRef = useRef35(onPlaybackError);
15165
+ const onPlaybackStateChangeRef = useRef35(onPlaybackStateChange);
14830
15166
  onPlaybackErrorRef.current = onPlaybackError;
14831
15167
  onPlaybackStateChangeRef.current = onPlaybackStateChange;
14832
- useEffect34(() => {
15168
+ useEffect35(() => {
14833
15169
  if (!resource) {
14834
15170
  return;
14835
15171
  }
@@ -14837,9 +15173,16 @@ function VideoHotspot({
14837
15173
  resource.video.muted = muted;
14838
15174
  resource.video.volume = clampVolume2(volume);
14839
15175
  resource.video.playsInline = playsInline;
15176
+ if (playsInline) {
15177
+ resource.video.setAttribute("playsinline", "true");
15178
+ resource.video.setAttribute("webkit-playsinline", "true");
15179
+ } else {
15180
+ resource.video.removeAttribute("playsinline");
15181
+ resource.video.removeAttribute("webkit-playsinline");
15182
+ }
14840
15183
  resource.video.preload = preload;
14841
15184
  }, [loop, muted, playsInline, preload, resource, volume]);
14842
- useEffect34(() => {
15185
+ useEffect35(() => {
14843
15186
  if (!resource) {
14844
15187
  return;
14845
15188
  }
@@ -14862,12 +15205,12 @@ function VideoHotspot({
14862
15205
  };
14863
15206
  }, [playing, resource]);
14864
15207
  const activeTexture = resource?.ready ? resource.texture : posterTexture;
14865
- return /* @__PURE__ */ jsx33(HotspotAnchor, { ...anchorProps, id, height, width, children: /* @__PURE__ */ jsx33(HotspotPlane, { map: activeTexture, opacity }) });
15208
+ return /* @__PURE__ */ jsx34(HotspotAnchor, { ...anchorProps, id, height, width, children: /* @__PURE__ */ jsx34(HotspotPlane, { map: activeTexture, opacity }) });
14866
15209
  }
14867
15210
 
14868
15211
  // src/hotspot/audio-hotspot.tsx
14869
15212
  import { useFrame as useFrame16, useThree as useThree25 } from "@react-three/fiber";
14870
- import { useEffect as useEffect35, useRef as useRef35, useState as useState19 } from "react";
15213
+ import { useEffect as useEffect36, useRef as useRef36, useState as useState19 } from "react";
14871
15214
  import {
14872
15215
  CanvasTexture as CanvasTexture2,
14873
15216
  ClampToEdgeWrapping as ClampToEdgeWrapping7,
@@ -14876,7 +15219,7 @@ import {
14876
15219
  SRGBColorSpace as SRGBColorSpace9,
14877
15220
  TextureLoader as TextureLoader8
14878
15221
  } from "three";
14879
- import { jsx as jsx34 } from "react/jsx-runtime";
15222
+ import { jsx as jsx35 } from "react/jsx-runtime";
14880
15223
  var SPEAKER_TEXTURE_SIZE = 512;
14881
15224
  function paintSpeakerBody(context, center) {
14882
15225
  context.fillStyle = "#f5fbfc";
@@ -14941,7 +15284,7 @@ function createSpeakerTexture(state) {
14941
15284
  }
14942
15285
  function useSpeakerTextures(enabled) {
14943
15286
  const [textures, setTextures] = useState19({ playing: null, stopped: null });
14944
- useEffect35(() => {
15287
+ useEffect36(() => {
14945
15288
  if (!enabled) {
14946
15289
  setTextures({ playing: null, stopped: null });
14947
15290
  return;
@@ -14959,9 +15302,9 @@ function useSpeakerTextures(enabled) {
14959
15302
  function useIconTexture(icon, enabled, onError, id) {
14960
15303
  const gl = useThree25((state) => state.gl);
14961
15304
  const [texture, setTexture] = useState19(null);
14962
- const onErrorRef = useRef35(onError);
15305
+ const onErrorRef = useRef36(onError);
14963
15306
  onErrorRef.current = onError;
14964
- useEffect35(() => {
15307
+ useEffect36(() => {
14965
15308
  let active = true;
14966
15309
  setTexture(null);
14967
15310
  if (!enabled || !icon) {
@@ -14998,7 +15341,7 @@ function useIconTexture(icon, enabled, onError, id) {
14998
15341
  active = false;
14999
15342
  };
15000
15343
  }, [enabled, gl, icon, id]);
15001
- useEffect35(
15344
+ useEffect36(
15002
15345
  () => () => {
15003
15346
  texture?.dispose();
15004
15347
  },
@@ -15018,12 +15361,12 @@ function useAudioHowl({
15018
15361
  src
15019
15362
  }) {
15020
15363
  const [howl, setHowl] = useState19(null);
15021
- const playingRef = useRef35(playing);
15022
- const loopRef = useRef35(loop ?? false);
15023
- const onEndedRef = useRef35(onEnded);
15024
- const onErrorRef = useRef35(onError);
15025
- const onPlaybackErrorRef = useRef35(onPlaybackError);
15026
- const onPlaybackStateChangeRef = useRef35(onPlaybackStateChange);
15364
+ const playingRef = useRef36(playing);
15365
+ const loopRef = useRef36(loop ?? false);
15366
+ const onEndedRef = useRef36(onEnded);
15367
+ const onErrorRef = useRef36(onError);
15368
+ const onPlaybackErrorRef = useRef36(onPlaybackError);
15369
+ const onPlaybackStateChangeRef = useRef36(onPlaybackStateChange);
15027
15370
  playingRef.current = playing;
15028
15371
  loopRef.current = loop ?? false;
15029
15372
  onEndedRef.current = onEnded;
@@ -15031,7 +15374,7 @@ function useAudioHowl({
15031
15374
  onPlaybackErrorRef.current = onPlaybackError;
15032
15375
  onPlaybackStateChangeRef.current = onPlaybackStateChange;
15033
15376
  const sourcesKey = sourceList(src).join("\0");
15034
- useEffect35(() => {
15377
+ useEffect36(() => {
15035
15378
  const sources = sourcesKey.length > 0 ? sourcesKey.split("\0") : [];
15036
15379
  if (sources.length === 0) {
15037
15380
  setHowl(null);
@@ -15068,7 +15411,7 @@ function useAudioHowl({
15068
15411
  handle.dispose();
15069
15412
  };
15070
15413
  }, [crossOrigin, id, sourcesKey]);
15071
- useEffect35(() => {
15414
+ useEffect36(() => {
15072
15415
  howl?.loop(loop ?? false);
15073
15416
  }, [howl, loop]);
15074
15417
  return howl;
@@ -15095,6 +15438,7 @@ function AudioHotspot({
15095
15438
  onError,
15096
15439
  ...anchorProps
15097
15440
  }) {
15441
+ usePanoMediaActivationIntent(playing);
15098
15442
  const camera = useThree25((state) => state.camera);
15099
15443
  const howl = useAudioHowl({
15100
15444
  crossOrigin,
@@ -15111,15 +15455,15 @@ function AudioHotspot({
15111
15455
  const stoppedIconTexture = useIconTexture(icon, marker, onError, id);
15112
15456
  const playingIconTexture = useIconTexture(playingIcon, marker, onError, id);
15113
15457
  const markerTexture = playing ? playingIconTexture ?? stoppedIconTexture ?? speakerTextures.playing : stoppedIconTexture ?? speakerTextures.stopped;
15114
- const playingRef = useRef35(playing);
15458
+ const playingRef = useRef36(playing);
15115
15459
  playingRef.current = playing;
15116
- const mutedRef = useRef35(muted);
15117
- const volumeRef = useRef35(volume);
15118
- const rangeRef = useRef35(range);
15460
+ const mutedRef = useRef36(muted);
15461
+ const volumeRef = useRef36(volume);
15462
+ const rangeRef = useRef36(range);
15119
15463
  mutedRef.current = muted;
15120
15464
  volumeRef.current = volume;
15121
15465
  rangeRef.current = range;
15122
- useEffect35(() => {
15466
+ useEffect36(() => {
15123
15467
  if (!howl) {
15124
15468
  return;
15125
15469
  }
@@ -15129,7 +15473,7 @@ function AudioHotspot({
15129
15473
  }
15130
15474
  howl.play();
15131
15475
  }, [howl, playing]);
15132
- useEffect35(() => {
15476
+ useEffect36(() => {
15133
15477
  if (!howl || !pauseWhenHidden) {
15134
15478
  return;
15135
15479
  }
@@ -15160,11 +15504,11 @@ function AudioHotspot({
15160
15504
  howl.mute(mutedRef.current);
15161
15505
  howl.volume(clampAudioVolume(volumeRef.current) * spatial.gain);
15162
15506
  });
15163
- return /* @__PURE__ */ jsx34(HotspotAnchor, { ...anchorProps, id, height, width, children: marker ? /* @__PURE__ */ jsx34(HotspotPlane, { map: markerTexture, opacity }) : null });
15507
+ return /* @__PURE__ */ jsx35(HotspotAnchor, { ...anchorProps, id, height, width, children: marker ? /* @__PURE__ */ jsx35(HotspotPlane, { map: markerTexture, opacity }) : null });
15164
15508
  }
15165
15509
 
15166
15510
  // src/hotspot/text-hotspot.tsx
15167
- import { useEffect as useEffect36, useRef as useRef36, useState as useState20 } from "react";
15511
+ import { useEffect as useEffect37, useRef as useRef37, useState as useState20 } from "react";
15168
15512
  import {
15169
15513
  CanvasTexture as CanvasTexture3,
15170
15514
  ClampToEdgeWrapping as ClampToEdgeWrapping8,
@@ -15172,7 +15516,7 @@ import {
15172
15516
  LinearMipmapLinearFilter as LinearMipmapLinearFilter8,
15173
15517
  SRGBColorSpace as SRGBColorSpace10
15174
15518
  } from "three";
15175
- import { jsx as jsx35 } from "react/jsx-runtime";
15519
+ import { jsx as jsx36 } from "react/jsx-runtime";
15176
15520
  var TEXT_TEXTURE_LONG_SIDE = 1024;
15177
15521
  var DEFAULT_FONT_FAMILY = "system-ui, sans-serif";
15178
15522
  var DEFAULT_FONT_SIZE = 96;
@@ -15393,11 +15737,11 @@ function createTextTexture(text, width, height, style) {
15393
15737
  }
15394
15738
  function useTextTexture(text, width, height, style, onLoad, onError) {
15395
15739
  const [texture, setTexture] = useState20(null);
15396
- const onLoadRef = useRef36(onLoad);
15397
- const onErrorRef = useRef36(onError);
15740
+ const onLoadRef = useRef37(onLoad);
15741
+ const onErrorRef = useRef37(onError);
15398
15742
  onLoadRef.current = onLoad;
15399
15743
  onErrorRef.current = onError;
15400
- useEffect36(() => {
15744
+ useEffect37(() => {
15401
15745
  let cancelled = false;
15402
15746
  let nextTexture = null;
15403
15747
  const run = async () => {
@@ -15490,13 +15834,13 @@ function TextHotspot({
15490
15834
  whiteSpace
15491
15835
  };
15492
15836
  const texture = useTextTexture(text, width, height, style, onLoad, onError);
15493
- return /* @__PURE__ */ jsx35(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ jsx35(HotspotPlane, { map: texture, opacity }) });
15837
+ return /* @__PURE__ */ jsx36(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ jsx36(HotspotPlane, { map: texture, opacity }) });
15494
15838
  }
15495
15839
 
15496
15840
  // src/hotspot/iframe-hotspot.tsx
15497
15841
  import { Html as Html2 } from "@react-three/drei";
15498
15842
  import { DoubleSide as DoubleSide6 } from "three";
15499
- import { jsx as jsx36, jsxs as jsxs19 } from "react/jsx-runtime";
15843
+ import { jsx as jsx37, jsxs as jsxs19 } from "react/jsx-runtime";
15500
15844
  var IFRAME_LONG_SIDE = 800;
15501
15845
  var CSS3D_DISTANCE_FACTOR = 400;
15502
15846
  var DEFAULT_SANDBOX = "allow-scripts allow-popups allow-forms";
@@ -15563,8 +15907,8 @@ function IframeHotspot({
15563
15907
  width,
15564
15908
  children: [
15565
15909
  /* @__PURE__ */ jsxs19("mesh", { children: [
15566
- /* @__PURE__ */ jsx36("planeGeometry", { args: [1, 1] }),
15567
- /* @__PURE__ */ jsx36(
15910
+ /* @__PURE__ */ jsx37("planeGeometry", { args: [1, 1] }),
15911
+ /* @__PURE__ */ jsx37(
15568
15912
  "meshBasicMaterial",
15569
15913
  {
15570
15914
  depthWrite: false,
@@ -15575,7 +15919,7 @@ function IframeHotspot({
15575
15919
  }
15576
15920
  )
15577
15921
  ] }),
15578
- /* @__PURE__ */ jsx36(
15922
+ /* @__PURE__ */ jsx37(
15579
15923
  Html2,
15580
15924
  {
15581
15925
  distanceFactor: CSS3D_DISTANCE_FACTOR,
@@ -15590,7 +15934,7 @@ function IframeHotspot({
15590
15934
  },
15591
15935
  transform: true,
15592
15936
  zIndexRange: [10, 0],
15593
- children: /* @__PURE__ */ jsx36(
15937
+ children: /* @__PURE__ */ jsx37(
15594
15938
  "iframe",
15595
15939
  {
15596
15940
  allow,