@ericchen1990/pano-view 2.3.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -2296,6 +2296,7 @@ __export(index_exports, {
2296
2296
  resolvePanoContextMenuEntries: () => resolvePanoContextMenuEntries,
2297
2297
  unwrapPolygonVertices: () => unwrapPolygonVertices,
2298
2298
  usePanoEvents: () => usePanoEvents,
2299
+ usePanoViewer: () => usePanoViewer,
2299
2300
  validatePolygonVertices: () => validatePolygonVertices,
2300
2301
  validatePolylineVertices: () => validatePolylineVertices,
2301
2302
  vector3ToPanoPosition: () => vector3ToPanoPosition
@@ -2305,7 +2306,30 @@ module.exports = __toCommonJS(index_exports);
2305
2306
  // src/pano-viewer.tsx
2306
2307
  var import_fiber10 = require("@react-three/fiber");
2307
2308
  var import_xr3 = require("@react-three/xr");
2308
- var import_react22 = require("react");
2309
+ var import_react24 = require("react");
2310
+
2311
+ // src/background-audio-host.ts
2312
+ var import_react = require("react");
2313
+ var BackgroundAudioHostContext = (0, import_react.createContext)(null);
2314
+ function createBackgroundAudioHost() {
2315
+ return {
2316
+ controller: null,
2317
+ revision: 0,
2318
+ listeners: /* @__PURE__ */ new Set()
2319
+ };
2320
+ }
2321
+ function notifyBackgroundAudioHost(host) {
2322
+ host.revision += 1;
2323
+ for (const listener of host.listeners) {
2324
+ listener();
2325
+ }
2326
+ }
2327
+ function subscribeBackgroundAudioHost(host, listener) {
2328
+ host.listeners.add(listener);
2329
+ return () => {
2330
+ host.listeners.delete(listener);
2331
+ };
2332
+ }
2309
2333
 
2310
2334
  // src/cn.ts
2311
2335
  function cn(...values) {
@@ -2314,10 +2338,10 @@ function cn(...values) {
2314
2338
 
2315
2339
  // src/auto-rotate.tsx
2316
2340
  var import_fiber2 = require("@react-three/fiber");
2317
- var import_react3 = require("react");
2341
+ var import_react4 = require("react");
2318
2342
 
2319
2343
  // src/pano-event-bus.ts
2320
- var import_react = require("react");
2344
+ var import_react2 = require("react");
2321
2345
  function createPanoEventBus() {
2322
2346
  const listeners = /* @__PURE__ */ new Map();
2323
2347
  return {
@@ -2346,12 +2370,12 @@ function createPanoEventBus() {
2346
2370
  }
2347
2371
  };
2348
2372
  }
2349
- var PanoEventBusContext = (0, import_react.createContext)(null);
2373
+ var PanoEventBusContext = (0, import_react2.createContext)(null);
2350
2374
 
2351
2375
  // src/panorama-view-runtime.tsx
2352
2376
  var import_fiber = require("@react-three/fiber");
2353
2377
  var import_xr = require("@react-three/xr");
2354
- var import_react2 = require("react");
2378
+ var import_react3 = require("react");
2355
2379
  var import_three = require("three");
2356
2380
  var MAX_PITCH = 90;
2357
2381
  var BOUNCE_OVERSHOOT_PITCH = 12;
@@ -2362,7 +2386,7 @@ var DEFAULT_ROTATE_DAMPING = 14;
2362
2386
  var DEFAULT_ZOOM_DAMPING = 16;
2363
2387
  var DEFAULT_FRICTION_STOP = 0.01;
2364
2388
  var VIEW_SETTLE_EPSILON = 1e-3;
2365
- var PanoramaViewContext = (0, import_react2.createContext)(null);
2389
+ var PanoramaViewContext = (0, import_react3.createContext)(null);
2366
2390
  function clamp(value, min, max) {
2367
2391
  return Math.max(min, Math.min(max, value));
2368
2392
  }
@@ -2384,36 +2408,36 @@ function resolveFrictionStop(value) {
2384
2408
  function viewsEqual(a, b) {
2385
2409
  return a.yaw === b.yaw && a.pitch === b.pitch && a.fov === b.fov;
2386
2410
  }
2387
- var PanoramaViewRuntime = (0, import_react2.forwardRef)(function PanoramaViewRuntime2({ initialView, minFov, maxFov, options, eventBus }, ref) {
2411
+ var PanoramaViewRuntime = (0, import_react3.forwardRef)(function PanoramaViewRuntime2({ initialView, minFov, maxFov, options, eventBus }, ref) {
2388
2412
  const { camera, gl } = (0, import_fiber.useThree)();
2389
2413
  const xrSession = (0, import_xr.useXR)((state) => state.session);
2390
- const xrSessionRef = (0, import_react2.useRef)(xrSession);
2391
- const viewRef = (0, import_react2.useRef)({ ...initialView });
2392
- const targetViewRef = (0, import_react2.useRef)({ ...initialView });
2393
- const initialViewRef = (0, import_react2.useRef)({ ...initialView });
2394
- const yawVelocityRef = (0, import_react2.useRef)(0);
2395
- const pitchVelocityRef = (0, import_react2.useRef)(0);
2396
- const zoomVelocityRef = (0, import_react2.useRef)(0);
2397
- const dirtyRef = (0, import_react2.useRef)(true);
2398
- const settledRef = (0, import_react2.useRef)(false);
2399
- const interactingRef = (0, import_react2.useRef)(false);
2400
- const mouseActiveRef = (0, import_react2.useRef)(false);
2401
- const touchActiveRef = (0, import_react2.useRef)(false);
2402
- const interactionLockCountRef = (0, import_react2.useRef)(0);
2403
- const keyboardActiveRef = (0, import_react2.useRef)(false);
2404
- const gyroActiveRef = (0, import_react2.useRef)(false);
2405
- const gyroPoseRef = (0, import_react2.useRef)({ yaw: 0, pitch: 0, roll: 0 });
2406
- const gyroOffsetRef = (0, import_react2.useRef)({ yaw: 0, pitch: 0 });
2407
- const gyroTouchModeRef = (0, import_react2.useRef)("full");
2408
- const cameraRollRef = (0, import_react2.useRef)(0);
2409
- const lastVelocitySampleAtRef = (0, import_react2.useRef)(null);
2410
- const optionsRef = (0, import_react2.useRef)(options);
2411
- const eventBusRef = (0, import_react2.useRef)(eventBus);
2412
- const lastEmittedViewRef = (0, import_react2.useRef)(null);
2413
- const eulerRef = (0, import_react2.useRef)(new import_three.Euler(0, 0, 0, "YXZ"));
2414
- const xrEulerRef = (0, import_react2.useRef)(new import_three.Euler(0, 0, 0, "YXZ"));
2415
- const minFovRef = (0, import_react2.useRef)(minFov);
2416
- const maxFovRef = (0, import_react2.useRef)(maxFov);
2414
+ const xrSessionRef = (0, import_react3.useRef)(xrSession);
2415
+ const viewRef = (0, import_react3.useRef)({ ...initialView });
2416
+ const targetViewRef = (0, import_react3.useRef)({ ...initialView });
2417
+ const initialViewRef = (0, import_react3.useRef)({ ...initialView });
2418
+ const yawVelocityRef = (0, import_react3.useRef)(0);
2419
+ const pitchVelocityRef = (0, import_react3.useRef)(0);
2420
+ const zoomVelocityRef = (0, import_react3.useRef)(0);
2421
+ const dirtyRef = (0, import_react3.useRef)(true);
2422
+ const settledRef = (0, import_react3.useRef)(false);
2423
+ const interactingRef = (0, import_react3.useRef)(false);
2424
+ const mouseActiveRef = (0, import_react3.useRef)(false);
2425
+ const touchActiveRef = (0, import_react3.useRef)(false);
2426
+ const interactionLockCountRef = (0, import_react3.useRef)(0);
2427
+ const keyboardActiveRef = (0, import_react3.useRef)(false);
2428
+ const gyroActiveRef = (0, import_react3.useRef)(false);
2429
+ const gyroPoseRef = (0, import_react3.useRef)({ yaw: 0, pitch: 0, roll: 0 });
2430
+ const gyroOffsetRef = (0, import_react3.useRef)({ yaw: 0, pitch: 0 });
2431
+ const gyroTouchModeRef = (0, import_react3.useRef)("full");
2432
+ const cameraRollRef = (0, import_react3.useRef)(0);
2433
+ const lastVelocitySampleAtRef = (0, import_react3.useRef)(null);
2434
+ const optionsRef = (0, import_react3.useRef)(options);
2435
+ const eventBusRef = (0, import_react3.useRef)(eventBus);
2436
+ const lastEmittedViewRef = (0, import_react3.useRef)(null);
2437
+ const eulerRef = (0, import_react3.useRef)(new import_three.Euler(0, 0, 0, "YXZ"));
2438
+ const xrEulerRef = (0, import_react3.useRef)(new import_three.Euler(0, 0, 0, "YXZ"));
2439
+ const minFovRef = (0, import_react3.useRef)(minFov);
2440
+ const maxFovRef = (0, import_react3.useRef)(maxFov);
2417
2441
  optionsRef.current = options;
2418
2442
  eventBusRef.current = eventBus;
2419
2443
  xrSessionRef.current = xrSession;
@@ -2556,7 +2580,7 @@ var PanoramaViewRuntime = (0, import_react2.forwardRef)(function PanoramaViewRun
2556
2580
  }
2557
2581
  return true;
2558
2582
  };
2559
- (0, import_react2.useImperativeHandle)(
2583
+ (0, import_react3.useImperativeHandle)(
2560
2584
  ref,
2561
2585
  () => ({
2562
2586
  getView: () => ({ ...viewRef.current }),
@@ -2646,7 +2670,7 @@ var PanoramaViewRuntime = (0, import_react2.forwardRef)(function PanoramaViewRun
2646
2670
  }),
2647
2671
  []
2648
2672
  );
2649
- (0, import_react2.useEffect)(() => {
2673
+ (0, import_react3.useEffect)(() => {
2650
2674
  initialViewRef.current = { ...initialView };
2651
2675
  setView(initialView);
2652
2676
  }, [initialView.fov, initialView.pitch, initialView.yaw]);
@@ -2775,16 +2799,16 @@ function AutoRotate({
2775
2799
  acceleration = DEFAULT_AUTO_ROTATE_ACCELERATION,
2776
2800
  startDelay = DEFAULT_AUTO_ROTATE_START_DELAY
2777
2801
  }) {
2778
- const controlsRef = (0, import_react3.useContext)(PanoramaViewContext);
2779
- const eventBus = (0, import_react3.useContext)(PanoEventBusContext);
2780
- const elapsedRef = (0, import_react3.useRef)(0);
2781
- const rotationSpeedRef = (0, import_react3.useRef)(0);
2782
- const rotatingRef = (0, import_react3.useRef)(false);
2783
- const yawAccumulatedRef = (0, import_react3.useRef)(0);
2802
+ const controlsRef = (0, import_react4.useContext)(PanoramaViewContext);
2803
+ const eventBus = (0, import_react4.useContext)(PanoEventBusContext);
2804
+ const elapsedRef = (0, import_react4.useRef)(0);
2805
+ const rotationSpeedRef = (0, import_react4.useRef)(0);
2806
+ const rotatingRef = (0, import_react4.useRef)(false);
2807
+ const yawAccumulatedRef = (0, import_react4.useRef)(0);
2784
2808
  if (!controlsRef) {
2785
2809
  throw new Error("<AutoRotate> must be rendered inside <PanoViewer>.");
2786
2810
  }
2787
- (0, import_react3.useEffect)(() => {
2811
+ (0, import_react4.useEffect)(() => {
2788
2812
  elapsedRef.current = 0;
2789
2813
  rotationSpeedRef.current = 0;
2790
2814
  yawAccumulatedRef.current = 0;
@@ -2839,9 +2863,9 @@ function AutoRotate({
2839
2863
  }
2840
2864
 
2841
2865
  // src/control-claims.ts
2842
- var import_react4 = require("react");
2843
- var ControlClaimsContext = (0, import_react4.createContext)(null);
2844
- var DefaultControlChannelContext = (0, import_react4.createContext)(false);
2866
+ var import_react5 = require("react");
2867
+ var ControlClaimsContext = (0, import_react5.createContext)(null);
2868
+ var DefaultControlChannelContext = (0, import_react5.createContext)(false);
2845
2869
  var CHANNEL_COMPONENT = {
2846
2870
  mouse: "MouseControls",
2847
2871
  touch: "TouchControls",
@@ -2860,8 +2884,8 @@ function isProduction() {
2860
2884
  return nodeEnv === "production";
2861
2885
  }
2862
2886
  function useClaimControlChannel(channel) {
2863
- const claims = (0, import_react4.useContext)(ControlClaimsContext);
2864
- const isDefault = (0, import_react4.useContext)(DefaultControlChannelContext);
2887
+ const claims = (0, import_react5.useContext)(ControlClaimsContext);
2888
+ const isDefault = (0, import_react5.useContext)(DefaultControlChannelContext);
2865
2889
  if (!claims || isDefault) {
2866
2890
  return;
2867
2891
  }
@@ -2922,9 +2946,9 @@ function subscribeFullscreenChange(onChange) {
2922
2946
  }
2923
2947
 
2924
2948
  // src/hotspot/accessibility.tsx
2925
- var import_react5 = require("react");
2949
+ var import_react6 = require("react");
2926
2950
  var import_jsx_runtime = require("react/jsx-runtime");
2927
- var HotspotAccessibilityContext = (0, import_react5.createContext)(null);
2951
+ var HotspotAccessibilityContext = (0, import_react6.createContext)(null);
2928
2952
  function warnAboutMissingLabel(id) {
2929
2953
  const nodeEnv = globalThis.process?.env?.NODE_ENV;
2930
2954
  if (nodeEnv !== "production") {
@@ -2938,12 +2962,12 @@ function useHotspotAccessibility({
2938
2962
  ariaLabel,
2939
2963
  onActivate
2940
2964
  }) {
2941
- const registry = (0, import_react5.useContext)(HotspotAccessibilityContext);
2942
- const [focused, setFocused] = (0, import_react5.useState)(false);
2943
- const activateRef = (0, import_react5.useRef)(onActivate);
2965
+ const registry = (0, import_react6.useContext)(HotspotAccessibilityContext);
2966
+ const [focused, setFocused] = (0, import_react6.useState)(false);
2967
+ const activateRef = (0, import_react6.useRef)(onActivate);
2944
2968
  const enabled = Boolean(onActivate);
2945
2969
  activateRef.current = onActivate;
2946
- (0, import_react5.useEffect)(() => {
2970
+ (0, import_react6.useEffect)(() => {
2947
2971
  if (!enabled) {
2948
2972
  setFocused(false);
2949
2973
  return;
@@ -2965,8 +2989,8 @@ function useHotspotAccessibility({
2965
2989
  return focused;
2966
2990
  }
2967
2991
  function useHotspotAccessibilityLayer() {
2968
- const [entries, setEntries] = (0, import_react5.useState)(() => /* @__PURE__ */ new Map());
2969
- const register = (0, import_react5.useCallback)(
2992
+ const [entries, setEntries] = (0, import_react6.useState)(() => /* @__PURE__ */ new Map());
2993
+ const register = (0, import_react6.useCallback)(
2970
2994
  (entry) => {
2971
2995
  const token = Symbol(entry.id);
2972
2996
  const nextEntry = { ...entry, token };
@@ -2988,11 +3012,11 @@ function useHotspotAccessibilityLayer() {
2988
3012
  },
2989
3013
  []
2990
3014
  );
2991
- const registry = (0, import_react5.useMemo)(
3015
+ const registry = (0, import_react6.useMemo)(
2992
3016
  () => ({ register }),
2993
3017
  [register]
2994
3018
  );
2995
- const controls = (0, import_react5.useMemo)(
3019
+ const controls = (0, import_react6.useMemo)(
2996
3020
  () => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { "aria-label": "Panorama hotspots", style: { pointerEvents: "none" }, children: Array.from(entries.values()).map((entry) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2997
3021
  "button",
2998
3022
  {
@@ -3019,7 +3043,7 @@ function useHotspotAccessibilityLayer() {
3019
3043
 
3020
3044
  // src/keyboard-controls.tsx
3021
3045
  var import_fiber3 = require("@react-three/fiber");
3022
- var import_react6 = require("react");
3046
+ var import_react7 = require("react");
3023
3047
  var DEFAULT_ROTATE_SPEED = 60;
3024
3048
  var DEFAULT_ZOOM_SPEED = 30;
3025
3049
  var DEFAULT_SHIFT_MULTIPLIER = 3;
@@ -3089,15 +3113,15 @@ function KeyboardControls({
3089
3113
  onNextScene
3090
3114
  }) {
3091
3115
  useClaimControlChannel("keyboard");
3092
- const controlsRef = (0, import_react6.useContext)(PanoramaViewContext);
3116
+ const controlsRef = (0, import_react7.useContext)(PanoramaViewContext);
3093
3117
  const { gl } = (0, import_fiber3.useThree)();
3094
- const pressedRef = (0, import_react6.useRef)(/* @__PURE__ */ new Set());
3095
- const shiftHeldRef = (0, import_react6.useRef)(false);
3096
- const invertRef = (0, import_react6.useRef)(invert);
3097
- const fovSpeedRef = (0, import_react6.useRef)(fovSpeed);
3098
- const onPreviousSceneRef = (0, import_react6.useRef)(onPreviousScene);
3099
- const onNextSceneRef = (0, import_react6.useRef)(onNextScene);
3100
- const keyMap = (0, import_react6.useMemo)(() => resolveKeyMap(keys), [keys]);
3118
+ const pressedRef = (0, import_react7.useRef)(/* @__PURE__ */ new Set());
3119
+ const shiftHeldRef = (0, import_react7.useRef)(false);
3120
+ const invertRef = (0, import_react7.useRef)(invert);
3121
+ const fovSpeedRef = (0, import_react7.useRef)(fovSpeed);
3122
+ const onPreviousSceneRef = (0, import_react7.useRef)(onPreviousScene);
3123
+ const onNextSceneRef = (0, import_react7.useRef)(onNextScene);
3124
+ const keyMap = (0, import_react7.useMemo)(() => resolveKeyMap(keys), [keys]);
3101
3125
  if (!controlsRef) {
3102
3126
  throw new Error("<KeyboardControls> must be rendered inside <PanoViewer>.");
3103
3127
  }
@@ -3105,7 +3129,7 @@ function KeyboardControls({
3105
3129
  fovSpeedRef.current = fovSpeed;
3106
3130
  onPreviousSceneRef.current = onPreviousScene;
3107
3131
  onNextSceneRef.current = onNextScene;
3108
- (0, import_react6.useEffect)(() => {
3132
+ (0, import_react7.useEffect)(() => {
3109
3133
  const element = gl.domElement;
3110
3134
  if (!enabled) {
3111
3135
  pressedRef.current.clear();
@@ -3263,7 +3287,7 @@ function KeyboardControls({
3263
3287
 
3264
3288
  // src/mouse-controls.tsx
3265
3289
  var import_fiber4 = require("@react-three/fiber");
3266
- var import_react7 = require("react");
3290
+ var import_react8 = require("react");
3267
3291
  var DEFAULT_ROTATE_SPEED2 = 0.35;
3268
3292
  var DEFAULT_ZOOM_SPEED2 = 0.08;
3269
3293
  var BUTTON_FLAG = {
@@ -3288,12 +3312,12 @@ function MouseControls({
3288
3312
  fovSpeed
3289
3313
  }) {
3290
3314
  useClaimControlChannel("mouse");
3291
- const controlsRef = (0, import_react7.useContext)(PanoramaViewContext);
3315
+ const controlsRef = (0, import_react8.useContext)(PanoramaViewContext);
3292
3316
  const { gl } = (0, import_fiber4.useThree)();
3293
- const pointersRef = (0, import_react7.useRef)(
3317
+ const pointersRef = (0, import_react8.useRef)(
3294
3318
  /* @__PURE__ */ new Map()
3295
3319
  );
3296
- const optionsRef = (0, import_react7.useRef)({
3320
+ const optionsRef = (0, import_react8.useRef)({
3297
3321
  rotateSpeed,
3298
3322
  zoomSpeed,
3299
3323
  wheel,
@@ -3310,7 +3334,7 @@ function MouseControls({
3310
3334
  invert,
3311
3335
  fovSpeed
3312
3336
  };
3313
- (0, import_react7.useEffect)(() => {
3337
+ (0, import_react8.useEffect)(() => {
3314
3338
  const element = gl.domElement;
3315
3339
  const allowedButtons = resolveButtons(buttons);
3316
3340
  const clearPointers = () => {
@@ -3434,7 +3458,7 @@ function MouseControls({
3434
3458
  }
3435
3459
 
3436
3460
  // src/pano-filter/host.ts
3437
- var import_react8 = require("react");
3461
+ var import_react9 = require("react");
3438
3462
 
3439
3463
  // src/pano-filter/presets.ts
3440
3464
  var PANO_FILTER_PRESETS = [
@@ -3475,7 +3499,7 @@ function isPanoFilterActive(snapshot) {
3475
3499
  }
3476
3500
 
3477
3501
  // src/pano-filter/host.ts
3478
- var PanoFilterHostContext = (0, import_react8.createContext)(null);
3502
+ var PanoFilterHostContext = (0, import_react9.createContext)(null);
3479
3503
  function createPanoFilterHost() {
3480
3504
  return {
3481
3505
  snapshot: { ...DEFAULT_PANO_FILTER_SNAPSHOT },
@@ -3529,8 +3553,8 @@ function subscribeNoop() {
3529
3553
  };
3530
3554
  }
3531
3555
  function usePanoFilterSnapshot() {
3532
- const host = (0, import_react8.useContext)(PanoFilterHostContext);
3533
- const revision = (0, import_react8.useSyncExternalStore)(
3556
+ const host = (0, import_react9.useContext)(PanoFilterHostContext);
3557
+ const revision = (0, import_react9.useSyncExternalStore)(
3534
3558
  host ? (onStoreChange) => subscribePanoFilterHost(host, onStoreChange) : subscribeNoop,
3535
3559
  () => host ? getPanoFilterHostRevision(host) : 0,
3536
3560
  () => host ? getPanoFilterHostRevision(host) : 0
@@ -3544,12 +3568,12 @@ function isProduction2() {
3544
3568
  }
3545
3569
 
3546
3570
  // src/pano-context-menu.tsx
3547
- var import_react9 = require("react");
3571
+ var import_react10 = require("react");
3548
3572
  var import_jsx_runtime2 = require("react/jsx-runtime");
3549
3573
  var DEFAULT_ICON_SIZE = 16;
3550
3574
  var MENU_EDGE_PADDING = 8;
3551
3575
  var MIN_PANO_CONTEXT_MENU_BACKGROUND_OPACITY = 0.4;
3552
- var PanoContextMenuOverlayContext = (0, import_react9.createContext)(null);
3576
+ var PanoContextMenuOverlayContext = (0, import_react10.createContext)(null);
3553
3577
  var DEFAULT_APPEARANCE = {
3554
3578
  background: "#161616",
3555
3579
  color: "#f4f4f4",
@@ -3589,11 +3613,11 @@ function DefaultContextMenuPanel({
3589
3613
  selectContext,
3590
3614
  onRequestClose
3591
3615
  }) {
3592
- const menuRef = (0, import_react9.useRef)(null);
3593
- const [activeIndex, setActiveIndex] = (0, import_react9.useState)(0);
3616
+ const menuRef = (0, import_react10.useRef)(null);
3617
+ const [activeIndex, setActiveIndex] = (0, import_react10.useState)(0);
3594
3618
  const resolved = { ...DEFAULT_APPEARANCE, ...appearance };
3595
3619
  const iconSize = Number.isFinite(resolved.iconSize) ? Math.max(0, resolved.iconSize) : DEFAULT_ICON_SIZE;
3596
- const visibleItems = (0, import_react9.useMemo)(
3620
+ const visibleItems = (0, import_react10.useMemo)(
3597
3621
  () => items.filter((item) => {
3598
3622
  if (!isActionItem(item)) {
3599
3623
  return true;
@@ -3602,7 +3626,7 @@ function DefaultContextMenuPanel({
3602
3626
  }),
3603
3627
  [items]
3604
3628
  );
3605
- const focusableIndices = (0, import_react9.useMemo)(() => {
3629
+ const focusableIndices = (0, import_react10.useMemo)(() => {
3606
3630
  const indices = [];
3607
3631
  visibleItems.forEach((item, index) => {
3608
3632
  if (isActionItem(item) && !item.disabled) {
@@ -3611,7 +3635,7 @@ function DefaultContextMenuPanel({
3611
3635
  });
3612
3636
  return indices;
3613
3637
  }, [visibleItems]);
3614
- (0, import_react9.useEffect)(() => {
3638
+ (0, import_react10.useEffect)(() => {
3615
3639
  const first = focusableIndices[0];
3616
3640
  setActiveIndex(first ?? 0);
3617
3641
  const frame = requestAnimationFrame(() => {
@@ -3622,7 +3646,7 @@ function DefaultContextMenuPanel({
3622
3646
  });
3623
3647
  return () => cancelAnimationFrame(frame);
3624
3648
  }, [focusableIndices]);
3625
- const activateItem = (0, import_react9.useCallback)(
3649
+ const activateItem = (0, import_react10.useCallback)(
3626
3650
  (item) => {
3627
3651
  if (item.disabled) {
3628
3652
  return;
@@ -3828,9 +3852,9 @@ function PositionedMenuShell({
3828
3852
  overlayElement,
3829
3853
  children
3830
3854
  }) {
3831
- const shellRef = (0, import_react9.useRef)(null);
3832
- const [offset, setOffset] = (0, import_react9.useState)({ left: 0, top: 0 });
3833
- (0, import_react9.useLayoutEffect)(() => {
3855
+ const shellRef = (0, import_react10.useRef)(null);
3856
+ const [offset, setOffset] = (0, import_react10.useState)({ left: 0, top: 0 });
3857
+ (0, import_react10.useLayoutEffect)(() => {
3834
3858
  const shell = shellRef.current;
3835
3859
  if (!overlayElement || !shell) {
3836
3860
  return;
@@ -3866,20 +3890,20 @@ function PositionedMenuShell({
3866
3890
  );
3867
3891
  }
3868
3892
  function usePanoContextMenuOverlay() {
3869
- const [session2, setSession] = (0, import_react9.useState)(null);
3870
- const overlayRef = (0, import_react9.useRef)(null);
3871
- const [overlayElement, setOverlayElement] = (0, import_react9.useState)(
3893
+ const [session2, setSession] = (0, import_react10.useState)(null);
3894
+ const overlayRef = (0, import_react10.useRef)(null);
3895
+ const [overlayElement, setOverlayElement] = (0, import_react10.useState)(
3872
3896
  null
3873
3897
  );
3874
- const api = (0, import_react9.useMemo)(
3898
+ const api = (0, import_react10.useMemo)(
3875
3899
  () => ({ setSession, overlayRef }),
3876
3900
  []
3877
3901
  );
3878
- const setOverlayNode = (0, import_react9.useCallback)((node) => {
3902
+ const setOverlayNode = (0, import_react10.useCallback)((node) => {
3879
3903
  overlayRef.current = node;
3880
3904
  setOverlayElement(node);
3881
3905
  }, []);
3882
- (0, import_react9.useEffect)(() => {
3906
+ (0, import_react10.useEffect)(() => {
3883
3907
  if (!session2) {
3884
3908
  return;
3885
3909
  }
@@ -3947,13 +3971,13 @@ function PanoContextMenu({
3947
3971
  separatorClassName,
3948
3972
  children
3949
3973
  }) {
3950
- const eventBus = (0, import_react9.useContext)(PanoEventBusContext);
3951
- const controlsRef = (0, import_react9.useContext)(PanoramaViewContext);
3952
- const overlayApi = (0, import_react9.useContext)(PanoContextMenuOverlayContext);
3953
- const actions = (0, import_react9.useContext)(PanoContextMenuActionsContext);
3954
- const instanceId = (0, import_react9.useId)();
3955
- const sessionKeyRef = (0, import_react9.useRef)(0);
3956
- const propsRef = (0, import_react9.useRef)({
3974
+ const eventBus = (0, import_react10.useContext)(PanoEventBusContext);
3975
+ const controlsRef = (0, import_react10.useContext)(PanoramaViewContext);
3976
+ const overlayApi = (0, import_react10.useContext)(PanoContextMenuOverlayContext);
3977
+ const actions = (0, import_react10.useContext)(PanoContextMenuActionsContext);
3978
+ const instanceId = (0, import_react10.useId)();
3979
+ const sessionKeyRef = (0, import_react10.useRef)(0);
3980
+ const propsRef = (0, import_react10.useRef)({
3957
3981
  items,
3958
3982
  prepend,
3959
3983
  append,
@@ -3983,10 +4007,10 @@ function PanoContextMenu({
3983
4007
  "<PanoContextMenu> requires the PanoViewer context-menu overlay host."
3984
4008
  );
3985
4009
  }
3986
- const close = (0, import_react9.useCallback)(() => {
4010
+ const close = (0, import_react10.useCallback)(() => {
3987
4011
  overlayApi.setSession(null);
3988
4012
  }, [overlayApi]);
3989
- const openMenu = (0, import_react9.useCallback)(
4013
+ const openMenu = (0, import_react10.useCallback)(
3990
4014
  (event) => {
3991
4015
  event.nativeEvent.preventDefault();
3992
4016
  const view = controlsRef.current?.getView() ?? {
@@ -4035,7 +4059,7 @@ function PanoContextMenu({
4035
4059
  },
4036
4060
  [actions, close, controlsRef, instanceId, overlayApi]
4037
4061
  );
4038
- (0, import_react9.useEffect)(() => {
4062
+ (0, import_react10.useEffect)(() => {
4039
4063
  const unsubscribeContextMenu = eventBus.subscribe(
4040
4064
  "contextmenu",
4041
4065
  openMenu
@@ -4214,11 +4238,11 @@ function composePanoContextMenuItems(props, presets) {
4214
4238
  ...resolvePanoContextMenuEntries(props.append ?? [], presets)
4215
4239
  ];
4216
4240
  }
4217
- var PanoContextMenuActionsContext = (0, import_react9.createContext)(null);
4241
+ var PanoContextMenuActionsContext = (0, import_react10.createContext)(null);
4218
4242
 
4219
4243
  // src/pano-cursor.tsx
4220
4244
  var import_fiber5 = require("@react-three/fiber");
4221
- var import_react10 = require("react");
4245
+ var import_react11 = require("react");
4222
4246
  var import_jsx_runtime3 = require("react/jsx-runtime");
4223
4247
  var DEFAULT_PANO_CURSORS = {
4224
4248
  default: "grab",
@@ -4233,9 +4257,9 @@ var LAYER_PRIORITY = {
4233
4257
  hotspotDragging: 3,
4234
4258
  hidden: 4
4235
4259
  };
4236
- var PanoCursorContext = (0, import_react10.createContext)(null);
4260
+ var PanoCursorContext = (0, import_react11.createContext)(null);
4237
4261
  function usePanoCursor() {
4238
- return (0, import_react10.useContext)(PanoCursorContext);
4262
+ return (0, import_react11.useContext)(PanoCursorContext);
4239
4263
  }
4240
4264
  function hotspotCursorClaimId(id) {
4241
4265
  return `pano-cursor:hotspot:${id}`;
@@ -4287,12 +4311,12 @@ function PanoCursorController({
4287
4311
  children
4288
4312
  }) {
4289
4313
  const { gl } = (0, import_fiber5.useThree)();
4290
- const eventBus = (0, import_react10.useContext)(PanoEventBusContext);
4291
- const claimsRef = (0, import_react10.useRef)(/* @__PURE__ */ new Map());
4292
- const cursorsRef = (0, import_react10.useRef)(cursors);
4293
- const appliedCursorRef = (0, import_react10.useRef)(null);
4314
+ const eventBus = (0, import_react11.useContext)(PanoEventBusContext);
4315
+ const claimsRef = (0, import_react11.useRef)(/* @__PURE__ */ new Map());
4316
+ const cursorsRef = (0, import_react11.useRef)(cursors);
4317
+ const appliedCursorRef = (0, import_react11.useRef)(null);
4294
4318
  cursorsRef.current = cursors;
4295
- const applyCursor = (0, import_react10.useCallback)(() => {
4319
+ const applyCursor = (0, import_react11.useCallback)(() => {
4296
4320
  const next = resolveHighestCursor(claimsRef.current, cursorsRef.current);
4297
4321
  const element = gl.domElement;
4298
4322
  if (appliedCursorRef.current === next && element.style.cursor === next) {
@@ -4301,14 +4325,14 @@ function PanoCursorController({
4301
4325
  element.style.cursor = next;
4302
4326
  appliedCursorRef.current = next;
4303
4327
  }, [gl]);
4304
- const claim = (0, import_react10.useCallback)(
4328
+ const claim = (0, import_react11.useCallback)(
4305
4329
  (id, layer, cursor) => {
4306
4330
  claimsRef.current.set(id, { layer, cursor });
4307
4331
  applyCursor();
4308
4332
  },
4309
4333
  [applyCursor]
4310
4334
  );
4311
- const release = (0, import_react10.useCallback)(
4335
+ const release = (0, import_react11.useCallback)(
4312
4336
  (id) => {
4313
4337
  if (claimsRef.current.delete(id)) {
4314
4338
  applyCursor();
@@ -4316,7 +4340,7 @@ function PanoCursorController({
4316
4340
  },
4317
4341
  [applyCursor]
4318
4342
  );
4319
- const api = (0, import_react10.useMemo)(
4343
+ const api = (0, import_react11.useMemo)(
4320
4344
  () => ({
4321
4345
  cursors,
4322
4346
  claim,
@@ -4324,7 +4348,7 @@ function PanoCursorController({
4324
4348
  }),
4325
4349
  [claim, cursors, release]
4326
4350
  );
4327
- (0, import_react10.useEffect)(() => {
4351
+ (0, import_react11.useEffect)(() => {
4328
4352
  const element = gl.domElement;
4329
4353
  const previous = element.style.cursor;
4330
4354
  return () => {
@@ -4333,10 +4357,10 @@ function PanoCursorController({
4333
4357
  element.style.cursor = previous;
4334
4358
  };
4335
4359
  }, [gl]);
4336
- (0, import_react10.useEffect)(() => {
4360
+ (0, import_react11.useEffect)(() => {
4337
4361
  applyCursor();
4338
4362
  }, [applyCursor, cursors]);
4339
- (0, import_react10.useEffect)(() => {
4363
+ (0, import_react11.useEffect)(() => {
4340
4364
  if (!eventBus) {
4341
4365
  return;
4342
4366
  }
@@ -4366,7 +4390,7 @@ function PanoCursorController({
4366
4390
 
4367
4391
  // src/pano-events.tsx
4368
4392
  var import_fiber6 = require("@react-three/fiber");
4369
- var import_react11 = require("react");
4393
+ var import_react12 = require("react");
4370
4394
  var DEFAULT_IDLE_TIME_MS = 2e3;
4371
4395
  function resolveIdleTime(value) {
4372
4396
  return Number.isFinite(value) && value >= 0 ? value : DEFAULT_IDLE_TIME_MS;
@@ -4404,13 +4428,13 @@ function usePanoEvents({
4404
4428
  onVRDenied,
4405
4429
  onVRUnknownDevice
4406
4430
  }) {
4407
- const eventBus = (0, import_react11.useContext)(PanoEventBusContext);
4408
- const controlsRef = (0, import_react11.useContext)(PanoramaViewContext);
4431
+ const eventBus = (0, import_react12.useContext)(PanoEventBusContext);
4432
+ const controlsRef = (0, import_react12.useContext)(PanoramaViewContext);
4409
4433
  const { gl } = (0, import_fiber6.useThree)();
4410
4434
  if (!eventBus || !controlsRef) {
4411
4435
  throw new Error("usePanoEvents must be used inside <PanoViewer>.");
4412
4436
  }
4413
- const callbacksRef = (0, import_react11.useRef)({
4437
+ const callbacksRef = (0, import_react12.useRef)({
4414
4438
  onViewChange,
4415
4439
  onViewSettled,
4416
4440
  onViewInteractionStart,
@@ -4474,15 +4498,15 @@ function usePanoEvents({
4474
4498
  onVRDenied,
4475
4499
  onVRUnknownDevice
4476
4500
  };
4477
- const idleElapsedRef = (0, import_react11.useRef)(0);
4478
- const isIdleRef = (0, import_react11.useRef)(false);
4479
- const idleTimeRef = (0, import_react11.useRef)(resolveIdleTime(idleTime));
4501
+ const idleElapsedRef = (0, import_react12.useRef)(0);
4502
+ const isIdleRef = (0, import_react12.useRef)(false);
4503
+ const idleTimeRef = (0, import_react12.useRef)(resolveIdleTime(idleTime));
4480
4504
  idleTimeRef.current = resolveIdleTime(idleTime);
4481
- (0, import_react11.useEffect)(() => {
4505
+ (0, import_react12.useEffect)(() => {
4482
4506
  idleElapsedRef.current = 0;
4483
4507
  isIdleRef.current = false;
4484
4508
  }, [idleTime]);
4485
- (0, import_react11.useEffect)(() => {
4509
+ (0, import_react12.useEffect)(() => {
4486
4510
  const unsubscribers = [
4487
4511
  eventBus.subscribe("viewchange", (view) => {
4488
4512
  callbacksRef.current.onViewChange?.(view);
@@ -4563,7 +4587,7 @@ function usePanoEvents({
4563
4587
  }
4564
4588
  };
4565
4589
  }, [eventBus]);
4566
- (0, import_react11.useEffect)(() => {
4590
+ (0, import_react12.useEffect)(() => {
4567
4591
  const element = gl.domElement;
4568
4592
  const handleWheel = (nativeEvent) => {
4569
4593
  callbacksRef.current.onWheel?.({
@@ -4576,7 +4600,7 @@ function usePanoEvents({
4576
4600
  element.removeEventListener("wheel", handleWheel);
4577
4601
  };
4578
4602
  }, [gl]);
4579
- (0, import_react11.useEffect)(() => {
4603
+ (0, import_react12.useEffect)(() => {
4580
4604
  if (typeof document === "undefined") {
4581
4605
  return;
4582
4606
  }
@@ -4602,7 +4626,7 @@ function usePanoEvents({
4602
4626
  wasFullscreenRef.current = isViewerFullscreen();
4603
4627
  return subscribeFullscreenChange(handleFullscreenChange);
4604
4628
  }, [gl]);
4605
- (0, import_react11.useEffect)(() => {
4629
+ (0, import_react12.useEffect)(() => {
4606
4630
  const element = gl.domElement;
4607
4631
  if (typeof ResizeObserver === "undefined") {
4608
4632
  return;
@@ -4644,7 +4668,7 @@ function PanoEvents(props) {
4644
4668
 
4645
4669
  // src/panorama-event-surface.tsx
4646
4670
  var import_fiber7 = require("@react-three/fiber");
4647
- var import_react12 = require("react");
4671
+ var import_react13 = require("react");
4648
4672
  var import_three3 = require("three");
4649
4673
 
4650
4674
  // src/hotspot/coordinates.ts
@@ -4737,9 +4761,9 @@ function makePanoramaPointerEvent(event) {
4737
4761
  };
4738
4762
  }
4739
4763
  function PanoramaEventSurface() {
4740
- const eventBus = (0, import_react12.useContext)(PanoEventBusContext);
4764
+ const eventBus = (0, import_react13.useContext)(PanoEventBusContext);
4741
4765
  const { camera, gl } = (0, import_fiber7.useThree)();
4742
- (0, import_react12.useEffect)(() => {
4766
+ (0, import_react13.useEffect)(() => {
4743
4767
  if (!eventBus) {
4744
4768
  return;
4745
4769
  }
@@ -4807,9 +4831,26 @@ function PanoramaEventSurface() {
4807
4831
  );
4808
4832
  }
4809
4833
 
4834
+ // src/scenes-host.ts
4835
+ var import_react14 = require("react");
4836
+ var ScenesHostContext = (0, import_react14.createContext)(null);
4837
+ function createScenesHost() {
4838
+ return {
4839
+ controller: null,
4840
+ revision: 0,
4841
+ listeners: /* @__PURE__ */ new Set()
4842
+ };
4843
+ }
4844
+ function notifyScenesHost(host) {
4845
+ host.revision += 1;
4846
+ for (const listener of host.listeners) {
4847
+ listener();
4848
+ }
4849
+ }
4850
+
4810
4851
  // src/touch-controls.tsx
4811
4852
  var import_fiber8 = require("@react-three/fiber");
4812
- var import_react13 = require("react");
4853
+ var import_react15 = require("react");
4813
4854
  var DEFAULT_ROTATE_SPEED3 = 0.35;
4814
4855
  function resolveSpeed3(value, fallback) {
4815
4856
  return Number.isFinite(value) && value >= 0 ? value : fallback;
@@ -4824,16 +4865,16 @@ function TouchControls({
4824
4865
  pinchZoom = true
4825
4866
  }) {
4826
4867
  useClaimControlChannel("touch");
4827
- const controlsRef = (0, import_react13.useContext)(PanoramaViewContext);
4868
+ const controlsRef = (0, import_react15.useContext)(PanoramaViewContext);
4828
4869
  const { gl } = (0, import_fiber8.useThree)();
4829
- const pointersRef = (0, import_react13.useRef)(/* @__PURE__ */ new Map());
4830
- const pinchDistanceRef = (0, import_react13.useRef)(null);
4831
- const optionsRef = (0, import_react13.useRef)({ rotateSpeed, invert, pinchZoom });
4870
+ const pointersRef = (0, import_react15.useRef)(/* @__PURE__ */ new Map());
4871
+ const pinchDistanceRef = (0, import_react15.useRef)(null);
4872
+ const optionsRef = (0, import_react15.useRef)({ rotateSpeed, invert, pinchZoom });
4832
4873
  if (!controlsRef) {
4833
4874
  throw new Error("<TouchControls> must be rendered inside <PanoViewer>.");
4834
4875
  }
4835
4876
  optionsRef.current = { rotateSpeed, invert, pinchZoom };
4836
- (0, import_react13.useEffect)(() => {
4877
+ (0, import_react15.useEffect)(() => {
4837
4878
  const element = gl.domElement;
4838
4879
  const clearPointers = () => {
4839
4880
  for (const pointerId of pointersRef.current.keys()) {
@@ -4955,17 +4996,17 @@ function TouchControls({
4955
4996
  }
4956
4997
 
4957
4998
  // src/video/chrome-overlay.tsx
4958
- var import_react14 = require("react");
4999
+ var import_react16 = require("react");
4959
5000
  var import_jsx_runtime5 = require("react/jsx-runtime");
4960
- var PanoChromeOverlayContext = (0, import_react14.createContext)(null);
5001
+ var PanoChromeOverlayContext = (0, import_react16.createContext)(null);
4961
5002
  function usePanoChromeOverlay() {
4962
- const [overlayElement, setOverlayElement] = (0, import_react14.useState)(
5003
+ const [overlayElement, setOverlayElement] = (0, import_react16.useState)(
4963
5004
  null
4964
5005
  );
4965
- const setOverlayNode = (0, import_react14.useCallback)((node) => {
5006
+ const setOverlayNode = (0, import_react16.useCallback)((node) => {
4966
5007
  setOverlayElement(node);
4967
5008
  }, []);
4968
- const api = (0, import_react14.useMemo)(
5009
+ const api = (0, import_react16.useMemo)(
4969
5010
  () => ({ overlayElement }),
4970
5011
  [overlayElement]
4971
5012
  );
@@ -4981,9 +5022,9 @@ function usePanoChromeOverlay() {
4981
5022
  }
4982
5023
 
4983
5024
  // src/video/host.ts
4984
- var import_react15 = require("react");
4985
- var PanoVideoHostContext = (0, import_react15.createContext)(null);
4986
- var DefaultPanoVideoControlsContext = (0, import_react15.createContext)(false);
5025
+ var import_react17 = require("react");
5026
+ var PanoVideoHostContext = (0, import_react17.createContext)(null);
5027
+ var DefaultPanoVideoControlsContext = (0, import_react17.createContext)(false);
4987
5028
  function createPanoVideoHost() {
4988
5029
  return {
4989
5030
  controller: null,
@@ -5014,8 +5055,8 @@ function isProduction3() {
5014
5055
  return nodeEnv === "production";
5015
5056
  }
5016
5057
  function useClaimPanoVideoControls() {
5017
- const host = (0, import_react15.useContext)(PanoVideoHostContext);
5018
- const isDefault = (0, import_react15.useContext)(DefaultPanoVideoControlsContext);
5058
+ const host = (0, import_react17.useContext)(PanoVideoHostContext);
5059
+ const isDefault = (0, import_react17.useContext)(DefaultPanoVideoControlsContext);
5019
5060
  if (!host || isDefault) {
5020
5061
  return;
5021
5062
  }
@@ -5028,10 +5069,10 @@ function useClaimPanoVideoControls() {
5028
5069
  }
5029
5070
 
5030
5071
  // src/video/pano-video-chrome-bridge.tsx
5031
- var import_react18 = require("react");
5072
+ var import_react20 = require("react");
5032
5073
 
5033
5074
  // src/video/pano-video-captions.tsx
5034
- var import_react16 = require("react");
5075
+ var import_react18 = require("react");
5035
5076
  var import_jsx_runtime6 = require("react/jsx-runtime");
5036
5077
  var DEFAULT_PANO_VIDEO_CAPTION_APPEARANCE = {
5037
5078
  color: "#ffffff",
@@ -5055,7 +5096,7 @@ function resolvePanoVideoCaptionAppearance(appearance) {
5055
5096
  function PanoVideoCaptionsOverlay({
5056
5097
  controller
5057
5098
  }) {
5058
- const snapshot = (0, import_react16.useSyncExternalStore)(
5099
+ const snapshot = (0, import_react18.useSyncExternalStore)(
5059
5100
  controller.subscribe,
5060
5101
  controller.getSnapshot,
5061
5102
  controller.getSnapshot
@@ -5097,7 +5138,7 @@ function PanoVideoCaptions({
5097
5138
  }
5098
5139
 
5099
5140
  // src/video/pano-video-controls.tsx
5100
- var import_react17 = require("react");
5141
+ var import_react19 = require("react");
5101
5142
 
5102
5143
  // src/video/format.ts
5103
5144
  var DEFAULT_PANO_VIDEO_PLAYBACK_RATES = [0.5, 1, 1.25, 1.5, 2];
@@ -5549,7 +5590,7 @@ function VerticalVolumeSlider({
5549
5590
  onVolume,
5550
5591
  volume
5551
5592
  }) {
5552
- const trackRef = (0, import_react17.useRef)(null);
5593
+ const trackRef = (0, import_react19.useRef)(null);
5553
5594
  const applyPointer = (event) => {
5554
5595
  const track = trackRef.current;
5555
5596
  if (!track) {
@@ -5685,14 +5726,14 @@ function VolumeControl({
5685
5726
  volume,
5686
5727
  volumeAdjustable
5687
5728
  }) {
5688
- const rootRef = (0, import_react17.useRef)(null);
5689
- const [open, setOpen] = (0, import_react17.useState)(false);
5729
+ const rootRef = (0, import_react19.useRef)(null);
5730
+ const [open, setOpen] = (0, import_react19.useState)(false);
5690
5731
  const displayVolume = muted ? 0 : volume;
5691
5732
  const mutedOrSilent = muted || volume === 0;
5692
- (0, import_react17.useEffect)(() => {
5733
+ (0, import_react19.useEffect)(() => {
5693
5734
  onOpenChange(open);
5694
5735
  }, [onOpenChange, open]);
5695
- (0, import_react17.useEffect)(() => {
5736
+ (0, import_react19.useEffect)(() => {
5696
5737
  if (!open || !volumeAdjustable || hasFinePointerHover()) {
5697
5738
  return;
5698
5739
  }
@@ -5779,24 +5820,24 @@ function PanoVideoControlsHud({
5779
5820
  fullscreen,
5780
5821
  overlayElement
5781
5822
  }) {
5782
- const resolved = (0, import_react17.useMemo)(
5823
+ const resolved = (0, import_react19.useMemo)(
5783
5824
  () => resolveControlsAppearance(appearance),
5784
5825
  [appearance]
5785
5826
  );
5786
- const snapshot = (0, import_react17.useSyncExternalStore)(
5827
+ const snapshot = (0, import_react19.useSyncExternalStore)(
5787
5828
  controller.subscribe,
5788
5829
  controller.getSnapshot,
5789
5830
  controller.getSnapshot
5790
5831
  );
5791
- const [menu, setMenu] = (0, import_react17.useState)(null);
5792
- const [captionsPanel, setCaptionsPanel] = (0, import_react17.useState)("tracks");
5793
- const [visible, setVisible] = (0, import_react17.useState)(true);
5794
- const [volumeOpen, setVolumeOpen] = (0, import_react17.useState)(false);
5795
- const [overlayWidth, setOverlayWidth] = (0, import_react17.useState)(
5832
+ const [menu, setMenu] = (0, import_react19.useState)(null);
5833
+ const [captionsPanel, setCaptionsPanel] = (0, import_react19.useState)("tracks");
5834
+ const [visible, setVisible] = (0, import_react19.useState)(true);
5835
+ const [volumeOpen, setVolumeOpen] = (0, import_react19.useState)(false);
5836
+ const [overlayWidth, setOverlayWidth] = (0, import_react19.useState)(
5796
5837
  () => overlayElement.clientWidth
5797
5838
  );
5798
- const idleTimerRef = (0, import_react17.useRef)(0);
5799
- const barId = (0, import_react17.useId)();
5839
+ const idleTimerRef = (0, import_react19.useRef)(0);
5840
+ const barId = (0, import_react19.useId)();
5800
5841
  const rateMenuId = `${barId}-rate`;
5801
5842
  const variantMenuId = `${barId}-variant`;
5802
5843
  const captionsMenuId = `${barId}-captions`;
@@ -5804,7 +5845,7 @@ function PanoVideoControlsHud({
5804
5845
  const compact = overlayWidth < COMPACT_CONTROLS_WIDTH;
5805
5846
  const hideTime = overlayWidth < NARROW_CONTROLS_WIDTH;
5806
5847
  const showFullscreen = isFullscreenEnabled();
5807
- const bumpVisibility = (0, import_react17.useCallback)(
5848
+ const bumpVisibility = (0, import_react19.useCallback)(
5808
5849
  (playing) => {
5809
5850
  setVisible(true);
5810
5851
  window.clearTimeout(idleTimerRef.current);
@@ -5817,7 +5858,7 @@ function PanoVideoControlsHud({
5817
5858
  },
5818
5859
  [menu, volumeOpen]
5819
5860
  );
5820
- (0, import_react17.useEffect)(() => {
5861
+ (0, import_react19.useEffect)(() => {
5821
5862
  if (typeof ResizeObserver === "undefined") {
5822
5863
  return;
5823
5864
  }
@@ -5832,15 +5873,15 @@ function PanoVideoControlsHud({
5832
5873
  observer.disconnect();
5833
5874
  };
5834
5875
  }, [overlayElement]);
5835
- (0, import_react17.useEffect)(() => {
5876
+ (0, import_react19.useEffect)(() => {
5836
5877
  if (!compact && menu === "more") {
5837
5878
  setMenu(null);
5838
5879
  }
5839
5880
  }, [compact, menu]);
5840
- (0, import_react17.useEffect)(() => {
5881
+ (0, import_react19.useEffect)(() => {
5841
5882
  bumpVisibility(snapshot.playing);
5842
5883
  }, [bumpVisibility, snapshot.playing]);
5843
- (0, import_react17.useEffect)(() => {
5884
+ (0, import_react19.useEffect)(() => {
5844
5885
  const root = overlayElement.parentElement;
5845
5886
  if (!root) {
5846
5887
  return;
@@ -5899,7 +5940,7 @@ function PanoVideoControlsHud({
5899
5940
  document.removeEventListener("pointerdown", handlePointerDown, true);
5900
5941
  };
5901
5942
  }, [bumpVisibility, controller, menu, overlayElement, snapshot.playing, volumeOpen]);
5902
- (0, import_react17.useEffect)(
5943
+ (0, import_react19.useEffect)(
5903
5944
  () => () => {
5904
5945
  window.clearTimeout(idleTimerRef.current);
5905
5946
  },
@@ -6190,7 +6231,7 @@ function PanoVideoControlsHud({
6190
6231
  }
6191
6232
  function PanoVideoControls({ appearance }) {
6192
6233
  useClaimPanoVideoControls();
6193
- const host = (0, import_react17.useContext)(PanoVideoHostContext);
6234
+ const host = (0, import_react19.useContext)(PanoVideoHostContext);
6194
6235
  if (host && appearance) {
6195
6236
  host.controls = appearance;
6196
6237
  }
@@ -6204,7 +6245,7 @@ function PanoVideoChromeBridge({
6204
6245
  host,
6205
6246
  overlayElement
6206
6247
  }) {
6207
- (0, import_react18.useSyncExternalStore)(
6248
+ (0, import_react20.useSyncExternalStore)(
6208
6249
  (onStoreChange) => subscribePanoVideoHost(host, onStoreChange),
6209
6250
  () => getPanoVideoHostRevision(host),
6210
6251
  () => getPanoVideoHostRevision(host)
@@ -6228,11 +6269,11 @@ function PanoVideoChromeBridge({
6228
6269
  }
6229
6270
 
6230
6271
  // src/webvr/chrome.tsx
6231
- var import_react20 = require("react");
6272
+ var import_react22 = require("react");
6232
6273
 
6233
6274
  // src/webvr/host.ts
6234
- var import_react19 = require("react");
6235
- var WebVRRuntimeContext = (0, import_react19.createContext)(null);
6275
+ var import_react21 = require("react");
6276
+ var WebVRRuntimeContext = (0, import_react21.createContext)(null);
6236
6277
  function createWebVRHost() {
6237
6278
  return {
6238
6279
  controller: null,
@@ -6503,7 +6544,7 @@ function SetupPanel({
6503
6544
  );
6504
6545
  }
6505
6546
  function WebVRChromeBridge({ host }) {
6506
- (0, import_react20.useSyncExternalStore)(
6547
+ (0, import_react22.useSyncExternalStore)(
6507
6548
  (listener) => subscribeWebVRHost(host, listener),
6508
6549
  () => host.revision,
6509
6550
  () => host.revision
@@ -6587,12 +6628,12 @@ function projectStereoHtmlPosition(el, camera, size, eye) {
6587
6628
  // src/webvr/xr-origin.tsx
6588
6629
  var import_fiber9 = require("@react-three/fiber");
6589
6630
  var import_xr2 = require("@react-three/xr");
6590
- var import_react21 = require("react");
6631
+ var import_react23 = require("react");
6591
6632
  var import_three5 = require("three");
6592
6633
  var import_jsx_runtime10 = require("react/jsx-runtime");
6593
6634
  function PanoramaXROrigin() {
6594
- const originRef = (0, import_react21.useRef)(null);
6595
- const localHeadPositionRef = (0, import_react21.useRef)(new import_three5.Vector3());
6635
+ const originRef = (0, import_react23.useRef)(null);
6636
+ const localHeadPositionRef = (0, import_react23.useRef)(new import_three5.Vector3());
6596
6637
  const session2 = (0, import_xr2.useXR)((state) => state.session);
6597
6638
  const gl = (0, import_fiber9.useThree)((state) => state.gl);
6598
6639
  (0, import_fiber9.useFrame)(() => {
@@ -6657,7 +6698,7 @@ function PanoCursorTree({
6657
6698
  return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(PanoCursorController, { cursors, children });
6658
6699
  }
6659
6700
  function PanoVideoHostReset() {
6660
- const host = (0, import_react22.useContext)(PanoVideoHostContext);
6701
+ const host = (0, import_react24.useContext)(PanoVideoHostContext);
6661
6702
  if (host) {
6662
6703
  host.controlClaims = 0;
6663
6704
  }
@@ -6670,7 +6711,7 @@ function DefaultControlChannels({
6670
6711
  keyboardChannel,
6671
6712
  fovSpeed
6672
6713
  }) {
6673
- const claims = (0, import_react22.useContext)(ControlClaimsContext);
6714
+ const claims = (0, import_react24.useContext)(ControlClaimsContext);
6674
6715
  if (!claims) {
6675
6716
  return null;
6676
6717
  }
@@ -6686,7 +6727,7 @@ function DefaultControlChannels({
6686
6727
  ) : null
6687
6728
  ] });
6688
6729
  }
6689
- var PanoViewer = (0, import_react22.forwardRef)(
6730
+ var PanoViewer = (0, import_react24.forwardRef)(
6690
6731
  function PanoViewer2({
6691
6732
  children,
6692
6733
  initialView,
@@ -6704,17 +6745,19 @@ var PanoViewer = (0, import_react22.forwardRef)(
6704
6745
  "aria-label": ariaLabel = "Panorama viewer",
6705
6746
  ...divProps
6706
6747
  }, ref) {
6707
- const rootRef = (0, import_react22.useRef)(null);
6708
- const controlsRef = (0, import_react22.useRef)(null);
6709
- const eventBus = (0, import_react22.useMemo)(() => createPanoEventBus(), []);
6748
+ const rootRef = (0, import_react24.useRef)(null);
6749
+ const controlsRef = (0, import_react24.useRef)(null);
6750
+ const eventBus = (0, import_react24.useMemo)(() => createPanoEventBus(), []);
6710
6751
  const { controls: hotspotAccessibilityControls, registry } = useHotspotAccessibilityLayer();
6711
6752
  const { api: contextMenuOverlayApi, overlay: contextMenuOverlay } = usePanoContextMenuOverlay();
6712
6753
  const { api: chromeOverlayApi, setOverlayNode, overlayElement } = usePanoChromeOverlay();
6713
- const videoHost = (0, import_react22.useMemo)(() => createPanoVideoHost(), []);
6714
- const filterHost = (0, import_react22.useMemo)(() => createPanoFilterHost(), []);
6715
- const webVRHost = (0, import_react22.useMemo)(() => createWebVRHost(), []);
6716
- const stereoView = (0, import_react22.useMemo)(() => createWebVRStereoView(), []);
6717
- const xrStore = (0, import_react22.useMemo)(
6754
+ const videoHost = (0, import_react24.useMemo)(() => createPanoVideoHost(), []);
6755
+ const filterHost = (0, import_react24.useMemo)(() => createPanoFilterHost(), []);
6756
+ const webVRHost = (0, import_react24.useMemo)(() => createWebVRHost(), []);
6757
+ const scenesHost = (0, import_react24.useMemo)(() => createScenesHost(), []);
6758
+ const bgmHost = (0, import_react24.useMemo)(() => createBackgroundAudioHost(), []);
6759
+ const stereoView = (0, import_react24.useMemo)(() => createWebVRStereoView(), []);
6760
+ const xrStore = (0, import_react24.useMemo)(
6718
6761
  () => (0, import_xr3.createXRStore)({
6719
6762
  anchors: false,
6720
6763
  bodyTracking: false,
@@ -6730,13 +6773,13 @@ var PanoViewer = (0, import_react22.forwardRef)(
6730
6773
  }),
6731
6774
  []
6732
6775
  );
6733
- const fallbackViewRef = (0, import_react22.useRef)(DEFAULT_VIEW);
6776
+ const fallbackViewRef = (0, import_react24.useRef)(DEFAULT_VIEW);
6734
6777
  const normalizedMinFov = Math.max(1, Math.min(minFov, maxFov - 1));
6735
6778
  const normalizedMaxFov = Math.min(
6736
6779
  179,
6737
6780
  Math.max(maxFov, normalizedMinFov + 1)
6738
6781
  );
6739
- const normalizedInitialView = (0, import_react22.useMemo)(
6782
+ const normalizedInitialView = (0, import_react24.useMemo)(
6740
6783
  () => ({
6741
6784
  yaw: initialView?.yaw ?? DEFAULT_VIEW.yaw,
6742
6785
  pitch: clampPanoPitch(initialView?.pitch ?? DEFAULT_VIEW.pitch),
@@ -6754,10 +6797,10 @@ var PanoViewer = (0, import_react22.forwardRef)(
6754
6797
  ]
6755
6798
  );
6756
6799
  fallbackViewRef.current = normalizedInitialView;
6757
- const controlClaims = (0, import_react22.useMemo)(() => createControlClaims(), []);
6800
+ const controlClaims = (0, import_react24.useMemo)(() => createControlClaims(), []);
6758
6801
  resetControlClaims(controlClaims);
6759
6802
  const controlsEnabled = controls !== false;
6760
- const controlOptions = (0, import_react22.useMemo)(
6803
+ const controlOptions = (0, import_react24.useMemo)(
6761
6804
  () => typeof controls === "object" ? controls : {},
6762
6805
  [controls]
6763
6806
  );
@@ -6765,7 +6808,7 @@ var PanoViewer = (0, import_react22.forwardRef)(
6765
6808
  const allModeInvert = controlOptions.invert === true;
6766
6809
  const topRotateSpeed = controlOptions.rotateSpeed ?? DEFAULT_POINTER_ROTATE_SPEED;
6767
6810
  const topZoomSpeed = controlOptions.zoomSpeed ?? DEFAULT_MOUSE_ZOOM_SPEED;
6768
- const mouseChannel = (0, import_react22.useMemo)(
6811
+ const mouseChannel = (0, import_react24.useMemo)(
6769
6812
  () => resolveChannel(controlOptions.mouse, {
6770
6813
  enabled: true,
6771
6814
  rotateSpeed: topRotateSpeed,
@@ -6781,7 +6824,7 @@ var PanoViewer = (0, import_react22.forwardRef)(
6781
6824
  topZoomSpeed
6782
6825
  ]
6783
6826
  );
6784
- const touchChannel = (0, import_react22.useMemo)(
6827
+ const touchChannel = (0, import_react24.useMemo)(
6785
6828
  () => resolveChannel(controlOptions.touch, {
6786
6829
  enabled: true,
6787
6830
  rotateSpeed: topRotateSpeed,
@@ -6790,13 +6833,35 @@ var PanoViewer = (0, import_react22.forwardRef)(
6790
6833
  }),
6791
6834
  [allModeInvert, controlOptions.touch, topRotateSpeed]
6792
6835
  );
6793
- const keyboardChannel = (0, import_react22.useMemo)(
6836
+ const keyboardChannel = (0, import_react24.useMemo)(
6794
6837
  () => resolveChannel(controlOptions.keyboard, {
6795
6838
  enabled: true
6796
6839
  }),
6797
6840
  [controlOptions.keyboard]
6798
6841
  );
6799
- const toggleFullscreen = (0, import_react22.useCallback)(async () => {
6842
+ const enterFullscreen = (0, import_react24.useCallback)(async () => {
6843
+ if (typeof document === "undefined") {
6844
+ return;
6845
+ }
6846
+ if (getFullscreenElement()) {
6847
+ return;
6848
+ }
6849
+ const root = rootRef.current;
6850
+ if (!root) {
6851
+ return;
6852
+ }
6853
+ await requestElementFullscreen(root);
6854
+ }, []);
6855
+ const exitFullscreen = (0, import_react24.useCallback)(async () => {
6856
+ if (typeof document === "undefined") {
6857
+ return;
6858
+ }
6859
+ if (!getFullscreenElement()) {
6860
+ return;
6861
+ }
6862
+ await exitElementFullscreen();
6863
+ }, []);
6864
+ const toggleFullscreen = (0, import_react24.useCallback)(async () => {
6800
6865
  if (typeof document === "undefined") {
6801
6866
  return;
6802
6867
  }
@@ -6810,8 +6875,8 @@ var PanoViewer = (0, import_react22.forwardRef)(
6810
6875
  }
6811
6876
  await requestElementFullscreen(root);
6812
6877
  }, []);
6813
- const [isViewerFullscreen, setIsViewerFullscreen] = (0, import_react22.useState)(false);
6814
- (0, import_react22.useEffect)(() => {
6878
+ const [isViewerFullscreen, setIsViewerFullscreen] = (0, import_react24.useState)(false);
6879
+ (0, import_react24.useEffect)(() => {
6815
6880
  if (typeof document === "undefined") {
6816
6881
  return;
6817
6882
  }
@@ -6829,7 +6894,7 @@ var PanoViewer = (0, import_react22.forwardRef)(
6829
6894
  syncFullscreen();
6830
6895
  return subscribeFullscreenChange(syncFullscreen);
6831
6896
  }, []);
6832
- (0, import_react22.useEffect)(() => {
6897
+ (0, import_react24.useEffect)(() => {
6833
6898
  const root = rootRef.current;
6834
6899
  if (!root) {
6835
6900
  return;
@@ -6842,7 +6907,7 @@ var PanoViewer = (0, import_react22.forwardRef)(
6842
6907
  root.removeEventListener("contextmenu", suppressNativeContextMenu, true);
6843
6908
  };
6844
6909
  }, []);
6845
- const contextMenuActions = (0, import_react22.useMemo)(
6910
+ const contextMenuActions = (0, import_react24.useMemo)(
6846
6911
  () => ({
6847
6912
  reset: () => {
6848
6913
  controlsRef.current?.reset();
@@ -6854,24 +6919,27 @@ var PanoViewer = (0, import_react22.forwardRef)(
6854
6919
  }),
6855
6920
  [isViewerFullscreen, toggleFullscreen]
6856
6921
  );
6857
- const contextMenuChannel = (0, import_react22.useMemo)(
6922
+ const contextMenuChannel = (0, import_react24.useMemo)(
6858
6923
  () => resolveContextMenuChannel(contextMenu),
6859
6924
  [contextMenu]
6860
6925
  );
6861
- const resolvedCursors = (0, import_react22.useMemo)(
6926
+ const resolvedCursors = (0, import_react24.useMemo)(
6862
6927
  () => resolvePanoCursors(cursors),
6863
6928
  [cursors]
6864
6929
  );
6865
6930
  const legacyAutoRotateOptions = controlOptions;
6866
- const [legacyAutoRotate, setLegacyAutoRotate] = (0, import_react22.useState)(
6931
+ const [legacyAutoRotate, setLegacyAutoRotate] = (0, import_react24.useState)(
6867
6932
  legacyAutoRotateOptions.autoRotate ?? false
6868
6933
  );
6869
- (0, import_react22.useEffect)(() => {
6934
+ (0, import_react24.useEffect)(() => {
6870
6935
  setLegacyAutoRotate(legacyAutoRotateOptions.autoRotate ?? false);
6871
6936
  }, [legacyAutoRotateOptions.autoRotate]);
6872
- (0, import_react22.useImperativeHandle)(
6937
+ const isFullscreenRef = (0, import_react24.useRef)(false);
6938
+ isFullscreenRef.current = isViewerFullscreen;
6939
+ (0, import_react24.useImperativeHandle)(
6873
6940
  ref,
6874
6941
  () => ({
6942
+ // -- View --
6875
6943
  getView: () => controlsRef.current?.getView() ?? { ...fallbackViewRef.current },
6876
6944
  setView: (view, options) => {
6877
6945
  controlsRef.current?.setView(view, options);
@@ -6879,17 +6947,67 @@ var PanoViewer = (0, import_react22.forwardRef)(
6879
6947
  reset: () => {
6880
6948
  controlsRef.current?.reset();
6881
6949
  },
6950
+ // -- Fullscreen --
6951
+ enterFullscreen,
6952
+ exitFullscreen,
6953
+ toggleFullscreen,
6954
+ isFullscreen: () => isFullscreenRef.current,
6955
+ // -- Scenes --
6956
+ setScene: (id) => scenesHost.controller?.setScene(id) ?? false,
6957
+ nextScene: () => scenesHost.controller?.nextScene() ?? false,
6958
+ previousScene: () => scenesHost.controller?.previousScene() ?? false,
6959
+ getActiveSceneId: () => scenesHost.controller?.getActiveSceneId() ?? null,
6960
+ getSceneIds: () => scenesHost.controller?.getSceneIds() ?? [],
6961
+ isSceneTransitioning: () => scenesHost.controller?.isTransitioning() ?? false,
6962
+ // -- WebVR --
6963
+ enterVR: () => webVRHost.controller?.enterVR() ?? Promise.resolve(false),
6964
+ exitVR: () => webVRHost.controller?.exitVR() ?? Promise.resolve(),
6965
+ toggleVR: () => webVRHost.controller?.toggleVR() ?? Promise.resolve(false),
6966
+ isVRAvailable: () => webVRHost.snapshot.available,
6967
+ isVREnabled: () => webVRHost.snapshot.mode !== null,
6968
+ getVRMode: () => webVRHost.snapshot.mode,
6969
+ requestVRPermission: () => webVRHost.controller?.requestPermission() ?? Promise.resolve(false),
6970
+ // -- Video --
6971
+ getVideo: () => videoHost.controller,
6972
+ subscribeVideo: (onStoreChange) => subscribePanoVideoHost(videoHost, onStoreChange),
6973
+ playVideo: () => videoHost.controller?.play() ?? Promise.resolve(),
6974
+ pauseVideo: () => videoHost.controller?.pause(),
6975
+ toggleVideo: () => videoHost.controller?.togglePlay(),
6976
+ seekVideo: (time) => videoHost.controller?.seek(time),
6977
+ setVideoVolume: (vol) => videoHost.controller?.setVolume(vol),
6978
+ setVideoMuted: (m) => videoHost.controller?.setMuted(m),
6979
+ toggleVideoMuted: () => videoHost.controller?.toggleMuted(),
6980
+ // -- Background Audio --
6981
+ getBackgroundAudio: () => bgmHost.controller,
6982
+ subscribeBackgroundAudio: (onStoreChange) => subscribeBackgroundAudioHost(bgmHost, onStoreChange),
6983
+ playBackgroundAudio: () => {
6984
+ bgmHost.controller?.play();
6985
+ return Promise.resolve();
6986
+ },
6987
+ pauseBackgroundAudio: () => bgmHost.controller?.pause(),
6988
+ toggleBackgroundAudio: () => bgmHost.controller?.togglePlay(),
6989
+ setBackgroundAudioVolume: (vol) => bgmHost.controller?.setVolume(vol),
6990
+ setBackgroundAudioMuted: (m) => bgmHost.controller?.setMuted(m),
6991
+ toggleBackgroundAudioMuted: () => bgmHost.controller?.toggleMuted(),
6992
+ // -- Deprecated --
6882
6993
  startAutoRotate: () => {
6883
6994
  setLegacyAutoRotate(true);
6884
6995
  },
6885
6996
  stopAutoRotate: () => {
6886
6997
  setLegacyAutoRotate(false);
6887
- },
6888
- toggleFullscreen
6998
+ }
6889
6999
  }),
6890
- [toggleFullscreen]
7000
+ [
7001
+ bgmHost,
7002
+ enterFullscreen,
7003
+ exitFullscreen,
7004
+ scenesHost,
7005
+ toggleFullscreen,
7006
+ videoHost,
7007
+ webVRHost
7008
+ ]
6891
7009
  );
6892
- const rootStyle = (0, import_react22.useMemo)(
7010
+ const rootStyle = (0, import_react24.useMemo)(
6893
7011
  () => ({
6894
7012
  overflow: "hidden",
6895
7013
  position: "relative",
@@ -6939,11 +7057,11 @@ var PanoViewer = (0, import_react22.forwardRef)(
6939
7057
  PanoContextMenuOverlayContext.Provider,
6940
7058
  {
6941
7059
  value: contextMenuOverlayApi,
6942
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(PanoChromeOverlayContext.Provider, { value: chromeOverlayApi, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(PanoVideoHostContext.Provider, { value: videoHost, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(PanoFilterHostContext.Provider, { value: filterHost, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
7060
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(PanoChromeOverlayContext.Provider, { value: chromeOverlayApi, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(PanoVideoHostContext.Provider, { value: videoHost, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(PanoFilterHostContext.Provider, { value: filterHost, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
6943
7061
  PanoContextMenuActionsContext.Provider,
6944
7062
  {
6945
7063
  value: contextMenuActions,
6946
- children: [
7064
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ScenesHostContext.Provider, { value: scenesHost, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(BackgroundAudioHostContext.Provider, { value: bgmHost, children: [
6947
7065
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(PanoVideoHostReset, {}),
6948
7066
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
6949
7067
  PanoramaViewRuntime,
@@ -6987,7 +7105,7 @@ var PanoViewer = (0, import_react22.forwardRef)(
6987
7105
  }
6988
7106
  )
6989
7107
  ] })
6990
- ]
7108
+ ] }) })
6991
7109
  }
6992
7110
  ) }) }) })
6993
7111
  }
@@ -7025,7 +7143,7 @@ var PanoViewer = (0, import_react22.forwardRef)(
7025
7143
  );
7026
7144
 
7027
7145
  // src/background-audio.tsx
7028
- var import_react23 = require("react");
7146
+ var import_react25 = require("react");
7029
7147
 
7030
7148
  // src/audio/howl.ts
7031
7149
  var import_howler = __toESM(require_howler());
@@ -7195,7 +7313,8 @@ function BackgroundAudio({
7195
7313
  src,
7196
7314
  sources,
7197
7315
  sceneId,
7198
- playing,
7316
+ playing: controlledPlaying,
7317
+ defaultPlaying = false,
7199
7318
  loop = true,
7200
7319
  muted = false,
7201
7320
  volume = 1,
@@ -7207,25 +7326,28 @@ function BackgroundAudio({
7207
7326
  onEnded,
7208
7327
  onError
7209
7328
  }) {
7210
- const controlsRef = (0, import_react23.useContext)(PanoramaViewContext);
7329
+ const controlsRef = (0, import_react25.useContext)(PanoramaViewContext);
7211
7330
  if (!controlsRef) {
7212
7331
  throw new Error("<BackgroundAudio> must be rendered inside <PanoViewer>.");
7213
7332
  }
7333
+ const isControlled = controlledPlaying !== void 0;
7334
+ const [internalPlaying, setInternalPlaying] = (0, import_react25.useState)(defaultPlaying);
7335
+ const playing = isControlled ? controlledPlaying : internalPlaying;
7214
7336
  const urls = resolveBackgroundAudioUrls(src, sources, sceneId);
7215
7337
  const trackKey = urls.join("\0");
7216
- const currentRef = (0, import_react23.useRef)(null);
7217
- const outgoingRef = (0, import_react23.useRef)([]);
7218
- const fadingInRef = (0, import_react23.useRef)(false);
7219
- const isFirstTrackRef = (0, import_react23.useRef)(true);
7220
- const playingRef = (0, import_react23.useRef)(playing);
7221
- const loopRef = (0, import_react23.useRef)(loop);
7222
- const mutedRef = (0, import_react23.useRef)(muted);
7223
- const volumeRef = (0, import_react23.useRef)(volume);
7224
- const fadeMsRef = (0, import_react23.useRef)(resolveFadeMs(fadeMs));
7225
- const onPlaybackStateChangeRef = (0, import_react23.useRef)(onPlaybackStateChange);
7226
- const onPlaybackErrorRef = (0, import_react23.useRef)(onPlaybackError);
7227
- const onEndedRef = (0, import_react23.useRef)(onEnded);
7228
- const onErrorRef = (0, import_react23.useRef)(onError);
7338
+ const currentRef = (0, import_react25.useRef)(null);
7339
+ const outgoingRef = (0, import_react25.useRef)([]);
7340
+ const fadingInRef = (0, import_react25.useRef)(false);
7341
+ const isFirstTrackRef = (0, import_react25.useRef)(true);
7342
+ const playingRef = (0, import_react25.useRef)(playing);
7343
+ const loopRef = (0, import_react25.useRef)(loop);
7344
+ const mutedRef = (0, import_react25.useRef)(muted);
7345
+ const volumeRef = (0, import_react25.useRef)(volume);
7346
+ const fadeMsRef = (0, import_react25.useRef)(resolveFadeMs(fadeMs));
7347
+ const onPlaybackStateChangeRef = (0, import_react25.useRef)(onPlaybackStateChange);
7348
+ const onPlaybackErrorRef = (0, import_react25.useRef)(onPlaybackError);
7349
+ const onEndedRef = (0, import_react25.useRef)(onEnded);
7350
+ const onErrorRef = (0, import_react25.useRef)(onError);
7229
7351
  playingRef.current = playing;
7230
7352
  loopRef.current = loop;
7231
7353
  mutedRef.current = muted;
@@ -7235,7 +7357,100 @@ function BackgroundAudio({
7235
7357
  onPlaybackErrorRef.current = onPlaybackError;
7236
7358
  onEndedRef.current = onEnded;
7237
7359
  onErrorRef.current = onError;
7238
- (0, import_react23.useEffect)(() => {
7360
+ const snapshotRef = (0, import_react25.useRef)({
7361
+ ready: false,
7362
+ playing: false,
7363
+ blocked: false,
7364
+ ended: false,
7365
+ muted,
7366
+ volume
7367
+ });
7368
+ const snapshotListenersRef = (0, import_react25.useRef)(/* @__PURE__ */ new Set());
7369
+ const notifySnapshot = (patch) => {
7370
+ const prev = snapshotRef.current;
7371
+ snapshotRef.current = { ...prev, ...patch };
7372
+ for (const listener of snapshotListenersRef.current) {
7373
+ listener();
7374
+ }
7375
+ };
7376
+ const isControlledRef = (0, import_react25.useRef)(isControlled);
7377
+ isControlledRef.current = isControlled;
7378
+ const controller = (0, import_react25.useMemo)(
7379
+ () => ({
7380
+ subscribe: (onStoreChange) => {
7381
+ snapshotListenersRef.current.add(onStoreChange);
7382
+ return () => {
7383
+ snapshotListenersRef.current.delete(onStoreChange);
7384
+ };
7385
+ },
7386
+ getSnapshot: () => snapshotRef.current,
7387
+ play: () => {
7388
+ if (isControlledRef.current) {
7389
+ return;
7390
+ }
7391
+ setInternalPlaying(true);
7392
+ },
7393
+ pause: () => {
7394
+ if (isControlledRef.current) {
7395
+ return;
7396
+ }
7397
+ setInternalPlaying(false);
7398
+ },
7399
+ togglePlay: () => {
7400
+ if (isControlledRef.current) {
7401
+ return;
7402
+ }
7403
+ setInternalPlaying((prev) => !prev);
7404
+ },
7405
+ setVolume: (vol) => {
7406
+ if (isControlledRef.current) {
7407
+ return;
7408
+ }
7409
+ const howl = currentRef.current?.handle.howl;
7410
+ if (howl) {
7411
+ howl.volume(clampAudioVolume(vol));
7412
+ }
7413
+ notifySnapshot({ volume: clampAudioVolume(vol) });
7414
+ },
7415
+ setMuted: (m) => {
7416
+ if (isControlledRef.current) {
7417
+ return;
7418
+ }
7419
+ const howl = currentRef.current?.handle.howl;
7420
+ if (howl) {
7421
+ howl.mute(m);
7422
+ }
7423
+ notifySnapshot({ muted: m });
7424
+ },
7425
+ toggleMuted: () => {
7426
+ if (isControlledRef.current) {
7427
+ return;
7428
+ }
7429
+ const next = !snapshotRef.current.muted;
7430
+ const howl = currentRef.current?.handle.howl;
7431
+ if (howl) {
7432
+ howl.mute(next);
7433
+ }
7434
+ notifySnapshot({ muted: next });
7435
+ }
7436
+ }),
7437
+ []
7438
+ );
7439
+ const bgmHost = (0, import_react25.useContext)(BackgroundAudioHostContext);
7440
+ (0, import_react25.useEffect)(() => {
7441
+ if (!bgmHost) {
7442
+ return;
7443
+ }
7444
+ bgmHost.controller = controller;
7445
+ notifyBackgroundAudioHost(bgmHost);
7446
+ return () => {
7447
+ if (bgmHost.controller === controller) {
7448
+ bgmHost.controller = null;
7449
+ notifyBackgroundAudioHost(bgmHost);
7450
+ }
7451
+ };
7452
+ }, [bgmHost, controller]);
7453
+ (0, import_react25.useEffect)(() => {
7239
7454
  return () => {
7240
7455
  fadingInRef.current = false;
7241
7456
  isFirstTrackRef.current = true;
@@ -7247,7 +7462,7 @@ function BackgroundAudio({
7247
7462
  outgoingRef.current = [];
7248
7463
  };
7249
7464
  }, []);
7250
- (0, import_react23.useEffect)(() => {
7465
+ (0, import_react25.useEffect)(() => {
7251
7466
  const previous = currentRef.current;
7252
7467
  if (previous?.key === trackKey && previous.crossOrigin === crossOrigin) {
7253
7468
  return;
@@ -7281,6 +7496,7 @@ function BackgroundAudio({
7281
7496
  isActive: () => currentRef.current?.key === trackKey,
7282
7497
  shouldRetryPlay: () => currentRef.current?.key === trackKey && playingRef.current,
7283
7498
  onEnded: () => {
7499
+ notifySnapshot({ playing: false, ended: true });
7284
7500
  onPlaybackStateChangeRef.current?.("ended");
7285
7501
  onEndedRef.current?.();
7286
7502
  },
@@ -7292,15 +7508,18 @@ function BackgroundAudio({
7292
7508
  durationMs
7293
7509
  );
7294
7510
  }
7511
+ notifySnapshot({ ready: true, playing: true, blocked: false, ended: false });
7295
7512
  onPlaybackStateChangeRef.current?.("playing");
7296
7513
  },
7297
7514
  onPause: () => {
7515
+ notifySnapshot({ playing: false });
7298
7516
  onPlaybackStateChangeRef.current?.("paused");
7299
7517
  },
7300
7518
  onLoadError: (error) => {
7301
7519
  onErrorRef.current?.({ error });
7302
7520
  },
7303
7521
  onPlayError: (error) => {
7522
+ notifySnapshot({ blocked: true });
7304
7523
  onPlaybackStateChangeRef.current?.("blocked");
7305
7524
  onPlaybackErrorRef.current?.(error);
7306
7525
  }
@@ -7343,7 +7562,7 @@ function BackgroundAudio({
7343
7562
  retire(previous);
7344
7563
  }
7345
7564
  }, [crossOrigin, trackKey]);
7346
- (0, import_react23.useEffect)(() => {
7565
+ (0, import_react25.useEffect)(() => {
7347
7566
  const howl = currentRef.current?.handle.howl;
7348
7567
  if (!howl) {
7349
7568
  return;
@@ -7359,7 +7578,7 @@ function BackgroundAudio({
7359
7578
  }
7360
7579
  howl.play();
7361
7580
  }, [playing, trackKey]);
7362
- (0, import_react23.useEffect)(() => {
7581
+ (0, import_react25.useEffect)(() => {
7363
7582
  const slot = currentRef.current;
7364
7583
  if (!slot) {
7365
7584
  return;
@@ -7369,8 +7588,9 @@ function BackgroundAudio({
7369
7588
  if (!fadingInRef.current) {
7370
7589
  slot.handle.howl.volume(clampAudioVolume(volume));
7371
7590
  }
7591
+ notifySnapshot({ muted, volume: clampAudioVolume(volume) });
7372
7592
  }, [loop, muted, trackKey, volume]);
7373
- (0, import_react23.useEffect)(() => {
7593
+ (0, import_react25.useEffect)(() => {
7374
7594
  if (!pauseWhenHidden) {
7375
7595
  return;
7376
7596
  }
@@ -7396,27 +7616,27 @@ function BackgroundAudio({
7396
7616
  }
7397
7617
 
7398
7618
  // src/pano-filter/pano-filter.tsx
7399
- var import_react24 = require("react");
7619
+ var import_react26 = require("react");
7400
7620
  function PanoFilter({
7401
7621
  preset = "none",
7402
7622
  intensity,
7403
7623
  enabled = true
7404
7624
  }) {
7405
- const host = (0, import_react24.useContext)(PanoFilterHostContext);
7625
+ const host = (0, import_react26.useContext)(PanoFilterHostContext);
7406
7626
  if (!host) {
7407
7627
  throw new Error("<PanoFilter> must be rendered inside <PanoViewer>.");
7408
7628
  }
7409
- const snapshot = (0, import_react24.useMemo)(
7629
+ const snapshot = (0, import_react26.useMemo)(
7410
7630
  () => resolvePanoFilterSnapshot({ preset, intensity, enabled }),
7411
7631
  [enabled, intensity, preset]
7412
7632
  );
7413
- (0, import_react24.useEffect)(() => {
7633
+ (0, import_react26.useEffect)(() => {
7414
7634
  claimPanoFilter(host);
7415
7635
  return () => {
7416
7636
  releasePanoFilter(host);
7417
7637
  };
7418
7638
  }, [host]);
7419
- (0, import_react24.useEffect)(() => {
7639
+ (0, import_react26.useEffect)(() => {
7420
7640
  setPanoFilterSnapshot(host, snapshot);
7421
7641
  }, [host, snapshot]);
7422
7642
  return null;
@@ -7424,7 +7644,7 @@ function PanoFilter({
7424
7644
 
7425
7645
  // src/gyro.tsx
7426
7646
  var import_fiber11 = require("@react-three/fiber");
7427
- var import_react25 = require("react");
7647
+ var import_react27 = require("react");
7428
7648
 
7429
7649
  // src/gyro-orientation.ts
7430
7650
  var import_three7 = require("three");
@@ -7509,7 +7729,7 @@ function resolveSoftstart(value) {
7509
7729
  function posesNearlyEqual(a, b) {
7510
7730
  return Math.abs(shortestYawDelta2(a.yaw, b.yaw)) < 1e-4 && Math.abs(a.pitch - b.pitch) < 1e-4 && Math.abs(a.roll - b.roll) < 1e-4;
7511
7731
  }
7512
- var Gyro = (0, import_react25.forwardRef)(function Gyro2({
7732
+ var Gyro = (0, import_react27.forwardRef)(function Gyro2({
7513
7733
  enabled = false,
7514
7734
  camroll = true,
7515
7735
  absolute = false,
@@ -7524,24 +7744,24 @@ var Gyro = (0, import_react25.forwardRef)(function Gyro2({
7524
7744
  onDisable,
7525
7745
  onDenied
7526
7746
  }, ref) {
7527
- const controlsRef = (0, import_react25.useContext)(PanoramaViewContext);
7528
- const eventBus = (0, import_react25.useContext)(PanoEventBusContext);
7747
+ const controlsRef = (0, import_react27.useContext)(PanoramaViewContext);
7748
+ const eventBus = (0, import_react27.useContext)(PanoEventBusContext);
7529
7749
  const { gl } = (0, import_fiber11.useThree)();
7530
- const [internallyDisabled, setInternallyDisabled] = (0, import_react25.useState)(false);
7531
- const availableRef = (0, import_react25.useRef)(false);
7532
- const availabilityReportedRef = (0, import_react25.useRef)(null);
7533
- const activeRef = (0, import_react25.useRef)(false);
7534
- const permissionRef = (0, import_react25.useRef)(deviceOrientationPermissionState);
7535
- const absoluteEventSourceRef = (0, import_react25.useRef)(null);
7536
- const rawQuaternionRef = (0, import_react25.useRef)(null);
7537
- const calibrationRef = (0, import_react25.useRef)(null);
7538
- const absoluteOffsetRef = (0, import_react25.useRef)({ yaw: 0, pitch: 0 });
7539
- const screenAngleRef = (0, import_react25.useRef)(getScreenOrientationAngle());
7540
- const startPoseRef = (0, import_react25.useRef)(null);
7541
- const enabledAtRef = (0, import_react25.useRef)(0);
7542
- const filteredPoseRef = (0, import_react25.useRef)(null);
7543
- const lastAppliedPoseRef = (0, import_react25.useRef)(null);
7544
- const callbacksRef = (0, import_react25.useRef)({
7750
+ const [internallyDisabled, setInternallyDisabled] = (0, import_react27.useState)(false);
7751
+ const availableRef = (0, import_react27.useRef)(false);
7752
+ const availabilityReportedRef = (0, import_react27.useRef)(null);
7753
+ const activeRef = (0, import_react27.useRef)(false);
7754
+ const permissionRef = (0, import_react27.useRef)(deviceOrientationPermissionState);
7755
+ const absoluteEventSourceRef = (0, import_react27.useRef)(null);
7756
+ const rawQuaternionRef = (0, import_react27.useRef)(null);
7757
+ const calibrationRef = (0, import_react27.useRef)(null);
7758
+ const absoluteOffsetRef = (0, import_react27.useRef)({ yaw: 0, pitch: 0 });
7759
+ const screenAngleRef = (0, import_react27.useRef)(getScreenOrientationAngle());
7760
+ const startPoseRef = (0, import_react27.useRef)(null);
7761
+ const enabledAtRef = (0, import_react27.useRef)(0);
7762
+ const filteredPoseRef = (0, import_react27.useRef)(null);
7763
+ const lastAppliedPoseRef = (0, import_react27.useRef)(null);
7764
+ const callbacksRef = (0, import_react27.useRef)({
7545
7765
  onAvailable,
7546
7766
  onUnavailable,
7547
7767
  onEnable,
@@ -7558,7 +7778,7 @@ var Gyro = (0, import_react25.forwardRef)(function Gyro2({
7558
7778
  if (!controlsRef) {
7559
7779
  throw new Error("<Gyro> must be rendered inside <PanoViewer>.");
7560
7780
  }
7561
- const emit = (0, import_react25.useCallback)(
7781
+ const emit = (0, import_react27.useCallback)(
7562
7782
  (type) => {
7563
7783
  eventBus?.emit(type, void 0);
7564
7784
  switch (type) {
@@ -7585,7 +7805,7 @@ var Gyro = (0, import_react25.forwardRef)(function Gyro2({
7585
7805
  },
7586
7806
  [eventBus]
7587
7807
  );
7588
- const setAvailable = (0, import_react25.useCallback)(
7808
+ const setAvailable = (0, import_react27.useCallback)(
7589
7809
  (available) => {
7590
7810
  availableRef.current = available;
7591
7811
  if (availabilityReportedRef.current === available) {
@@ -7596,7 +7816,7 @@ var Gyro = (0, import_react25.forwardRef)(function Gyro2({
7596
7816
  },
7597
7817
  [emit]
7598
7818
  );
7599
- const requestPermission = (0, import_react25.useCallback)(async () => {
7819
+ const requestPermission = (0, import_react27.useCallback)(async () => {
7600
7820
  if (!availableRef.current) {
7601
7821
  return false;
7602
7822
  }
@@ -7629,7 +7849,7 @@ var Gyro = (0, import_react25.forwardRef)(function Gyro2({
7629
7849
  emit("gyrodenied");
7630
7850
  return false;
7631
7851
  }, [emit, setAvailable]);
7632
- const deactivate = (0, import_react25.useCallback)(() => {
7852
+ const deactivate = (0, import_react27.useCallback)(() => {
7633
7853
  if (activeRef.current) {
7634
7854
  activeRef.current = false;
7635
7855
  controlsRef.current?.setGyroActive(false);
@@ -7641,7 +7861,7 @@ var Gyro = (0, import_react25.forwardRef)(function Gyro2({
7641
7861
  filteredPoseRef.current = null;
7642
7862
  lastAppliedPoseRef.current = null;
7643
7863
  }, [controlsRef, emit]);
7644
- const resetSensor = (0, import_react25.useCallback)(
7864
+ const resetSensor = (0, import_react27.useCallback)(
7645
7865
  (yaw, pitch) => {
7646
7866
  const rawQuaternion = rawQuaternionRef.current;
7647
7867
  if (!rawQuaternion) {
@@ -7676,7 +7896,7 @@ var Gyro = (0, import_react25.forwardRef)(function Gyro2({
7676
7896
  },
7677
7897
  [absolute, controlsRef, north]
7678
7898
  );
7679
- (0, import_react25.useImperativeHandle)(
7899
+ (0, import_react27.useImperativeHandle)(
7680
7900
  ref,
7681
7901
  () => ({
7682
7902
  resetSensor,
@@ -7686,22 +7906,22 @@ var Gyro = (0, import_react25.forwardRef)(function Gyro2({
7686
7906
  }),
7687
7907
  [requestPermission, resetSensor]
7688
7908
  );
7689
- (0, import_react25.useEffect)(() => {
7909
+ (0, import_react27.useEffect)(() => {
7690
7910
  if (!enabled) {
7691
7911
  setInternallyDisabled(false);
7692
7912
  }
7693
7913
  }, [enabled]);
7694
- (0, import_react25.useEffect)(() => {
7914
+ (0, import_react27.useEffect)(() => {
7695
7915
  const supported = typeof window !== "undefined" && window.isSecureContext && typeof DeviceOrientationEvent !== "undefined" && (desktopSupport || isMobileDevice());
7696
7916
  setAvailable(supported);
7697
7917
  return () => {
7698
7918
  availableRef.current = false;
7699
7919
  };
7700
7920
  }, [desktopSupport, setAvailable]);
7701
- (0, import_react25.useEffect)(() => {
7921
+ (0, import_react27.useEffect)(() => {
7702
7922
  controlsRef.current?.setGyroTouchMode(touchMode);
7703
7923
  }, [controlsRef, touchMode]);
7704
- (0, import_react25.useEffect)(() => {
7924
+ (0, import_react27.useEffect)(() => {
7705
7925
  if (!enabled || internallyDisabled || touchMode !== "disablegyro") {
7706
7926
  return;
7707
7927
  }
@@ -7715,7 +7935,7 @@ var Gyro = (0, import_react25.forwardRef)(function Gyro2({
7715
7935
  gl.domElement.removeEventListener("pointerdown", onPointerDown);
7716
7936
  };
7717
7937
  }, [enabled, gl, internallyDisabled, touchMode]);
7718
- (0, import_react25.useEffect)(() => {
7938
+ (0, import_react27.useEffect)(() => {
7719
7939
  if (!enabled || internallyDisabled || !availableRef.current) {
7720
7940
  deactivate();
7721
7941
  return;
@@ -7877,7 +8097,7 @@ var Gyro = (0, import_react25.forwardRef)(function Gyro2({
7877
8097
 
7878
8098
  // src/webvr/webvr.tsx
7879
8099
  var import_fiber14 = require("@react-three/fiber");
7880
- var import_react30 = require("react");
8100
+ var import_react32 = require("react");
7881
8101
 
7882
8102
  // src/webvr/detect.ts
7883
8103
  function isMobileVRDevice() {
@@ -7900,7 +8120,7 @@ async function detectWebVRCapabilities() {
7900
8120
 
7901
8121
  // src/webvr/reticle.tsx
7902
8122
  var import_fiber12 = require("@react-three/fiber");
7903
- var import_react26 = require("react");
8123
+ var import_react28 = require("react");
7904
8124
  var import_three8 = require("three");
7905
8125
  var import_jsx_runtime12 = require("react/jsx-runtime");
7906
8126
  var CENTER_NDC = new import_three8.Vector2(0, 0);
@@ -7986,13 +8206,13 @@ function WebVRReticle({
7986
8206
  dwellMs,
7987
8207
  visible
7988
8208
  }) {
7989
- const groupRef = (0, import_react26.useRef)(null);
7990
- const ringMeshRef = (0, import_react26.useRef)(null);
7991
- const directionRef = (0, import_react26.useRef)(new import_three8.Vector3());
7992
- const raycasterRef = (0, import_react26.useRef)(new import_three8.Raycaster());
7993
- const hoveredRef = (0, import_react26.useRef)(null);
7994
- const dwellRef = (0, import_react26.useRef)(0);
7995
- const clickedRef = (0, import_react26.useRef)(false);
8209
+ const groupRef = (0, import_react28.useRef)(null);
8210
+ const ringMeshRef = (0, import_react28.useRef)(null);
8211
+ const directionRef = (0, import_react28.useRef)(new import_three8.Vector3());
8212
+ const raycasterRef = (0, import_react28.useRef)(new import_three8.Raycaster());
8213
+ const hoveredRef = (0, import_react28.useRef)(null);
8214
+ const dwellRef = (0, import_react28.useRef)(0);
8215
+ const clickedRef = (0, import_react28.useRef)(false);
7996
8216
  const { camera, gl, scene } = (0, import_fiber12.useThree)();
7997
8217
  (0, import_fiber12.useFrame)((_, deltaSeconds) => {
7998
8218
  const group = groupRef.current;
@@ -8155,7 +8375,7 @@ function WebVRReticle({
8155
8375
 
8156
8376
  // src/webvr/stereo.tsx
8157
8377
  var import_fiber13 = require("@react-three/fiber");
8158
- var import_react27 = require("react");
8378
+ var import_react29 = require("react");
8159
8379
  var import_three9 = require("three");
8160
8380
  var vertexShader = `
8161
8381
  varying vec2 vUv;
@@ -8230,25 +8450,25 @@ function WebVRStereoRenderer({
8230
8450
  screensize
8231
8451
  }) {
8232
8452
  const { camera, gl } = (0, import_fiber13.useThree)();
8233
- const runtime = (0, import_react27.useContext)(WebVRRuntimeContext);
8234
- const fallbackStereoRef = (0, import_react27.useRef)(null);
8453
+ const runtime = (0, import_react29.useContext)(WebVRRuntimeContext);
8454
+ const fallbackStereoRef = (0, import_react29.useRef)(null);
8235
8455
  if (!fallbackStereoRef.current) {
8236
8456
  fallbackStereoRef.current = new import_three9.StereoCamera();
8237
8457
  }
8238
8458
  const stereo = runtime?.stereoView.stereo ?? fallbackStereoRef.current;
8239
- const stereoRef = (0, import_react27.useRef)(stereo);
8459
+ const stereoRef = (0, import_react29.useRef)(stereo);
8240
8460
  stereoRef.current = stereo;
8241
- const resources = (0, import_react27.useMemo)(createDistortionResources, []);
8242
- const drawingSizeRef = (0, import_react27.useRef)(new import_three9.Vector2());
8243
- const viewportRef = (0, import_react27.useRef)(new import_three9.Vector4());
8244
- const scissorRef = (0, import_react27.useRef)(new import_three9.Vector4());
8245
- const originalFovRef = (0, import_react27.useRef)(null);
8246
- const stereoActiveRef = (0, import_react27.useRef)(false);
8247
- const profileRef = (0, import_react27.useRef)(profile);
8248
- const screensizeRef = (0, import_react27.useRef)(screensize);
8461
+ const resources = (0, import_react29.useMemo)(createDistortionResources, []);
8462
+ const drawingSizeRef = (0, import_react29.useRef)(new import_three9.Vector2());
8463
+ const viewportRef = (0, import_react29.useRef)(new import_three9.Vector4());
8464
+ const scissorRef = (0, import_react29.useRef)(new import_three9.Vector4());
8465
+ const originalFovRef = (0, import_react29.useRef)(null);
8466
+ const stereoActiveRef = (0, import_react29.useRef)(false);
8467
+ const profileRef = (0, import_react29.useRef)(profile);
8468
+ const screensizeRef = (0, import_react29.useRef)(screensize);
8249
8469
  profileRef.current = profile;
8250
8470
  screensizeRef.current = screensize;
8251
- (0, import_react27.useEffect)(
8471
+ (0, import_react29.useEffect)(
8252
8472
  () => () => {
8253
8473
  resources.geometry.dispose();
8254
8474
  resources.material.dispose();
@@ -8256,7 +8476,7 @@ function WebVRStereoRenderer({
8256
8476
  },
8257
8477
  [resources]
8258
8478
  );
8259
- (0, import_react27.useEffect)(() => {
8479
+ (0, import_react29.useEffect)(() => {
8260
8480
  const originalRender = gl.render.bind(gl);
8261
8481
  gl.render = (sceneToRender, cameraToRender) => {
8262
8482
  if (!stereoActiveRef.current || !(cameraToRender instanceof import_three9.PerspectiveCamera)) {
@@ -8320,7 +8540,7 @@ function WebVRStereoRenderer({
8320
8540
  gl.render = originalRender;
8321
8541
  };
8322
8542
  }, [gl, resources]);
8323
- (0, import_react27.useEffect)(
8543
+ (0, import_react29.useEffect)(
8324
8544
  () => () => {
8325
8545
  if (runtime) {
8326
8546
  runtime.stereoView.active = false;
@@ -8355,7 +8575,7 @@ function WebVRStereoRenderer({
8355
8575
  }
8356
8576
 
8357
8577
  // src/webvr/pointerlock.ts
8358
- var import_react28 = require("react");
8578
+ var import_react30 = require("react");
8359
8579
  var POINTER_LOCK_CURSOR_ID = "webvr:pointerlock";
8360
8580
  async function requestWebVRPointerLock(element) {
8361
8581
  if (typeof document === "undefined") {
@@ -8388,11 +8608,11 @@ function exitWebVRPointerLock(element) {
8388
8608
  }
8389
8609
  function useWebVRPointerLock(enabled, element) {
8390
8610
  const cursor = usePanoCursor();
8391
- const cursorRef = (0, import_react28.useRef)(cursor);
8392
- const enabledRef = (0, import_react28.useRef)(enabled);
8611
+ const cursorRef = (0, import_react30.useRef)(cursor);
8612
+ const enabledRef = (0, import_react30.useRef)(enabled);
8393
8613
  cursorRef.current = cursor;
8394
8614
  enabledRef.current = enabled;
8395
- (0, import_react28.useEffect)(() => {
8615
+ (0, import_react30.useEffect)(() => {
8396
8616
  if (!enabled || !element) {
8397
8617
  return;
8398
8618
  }
@@ -8422,7 +8642,7 @@ function useWebVRPointerLock(enabled, element) {
8422
8642
  }
8423
8643
 
8424
8644
  // src/webvr/wakelock.ts
8425
- var import_react29 = require("react");
8645
+ var import_react31 = require("react");
8426
8646
 
8427
8647
  // src/webvr/wakelock-fallback.ts
8428
8648
  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==";
@@ -8556,7 +8776,7 @@ function releaseWebVRWakeLock() {
8556
8776
  stopFallbackVideo();
8557
8777
  }
8558
8778
  function useWebVRWakeLock(enabled) {
8559
- (0, import_react29.useEffect)(() => {
8779
+ (0, import_react31.useEffect)(() => {
8560
8780
  if (!enabled) {
8561
8781
  return;
8562
8782
  }
@@ -8586,7 +8806,7 @@ function initializeSettings(screensize, profile) {
8586
8806
  function getViewerElement(canvas) {
8587
8807
  return canvas.closest("[data-pano-viewer]") ?? canvas.parentElement ?? canvas;
8588
8808
  }
8589
- var WebVR = (0, import_react30.forwardRef)(function WebVR2({
8809
+ var WebVR = (0, import_react32.forwardRef)(function WebVR2({
8590
8810
  chrome = true,
8591
8811
  mobileVr = true,
8592
8812
  desktopSupport = false,
@@ -8604,24 +8824,24 @@ var WebVR = (0, import_react30.forwardRef)(function WebVR2({
8604
8824
  onDenied,
8605
8825
  onUnknownDevice
8606
8826
  }, ref) {
8607
- const runtime = (0, import_react30.useContext)(WebVRRuntimeContext);
8608
- const controlsRef = (0, import_react30.useContext)(PanoramaViewContext);
8609
- const eventBus = (0, import_react30.useContext)(PanoEventBusContext);
8827
+ const runtime = (0, import_react32.useContext)(WebVRRuntimeContext);
8828
+ const controlsRef = (0, import_react32.useContext)(PanoramaViewContext);
8829
+ const eventBus = (0, import_react32.useContext)(PanoEventBusContext);
8610
8830
  const gl = (0, import_fiber14.useThree)((state) => state.gl);
8611
- const gyroRef = (0, import_react30.useRef)(null);
8612
- const capabilitiesRef = (0, import_react30.useRef)({
8831
+ const gyroRef = (0, import_react32.useRef)(null);
8832
+ const capabilitiesRef = (0, import_react32.useRef)({
8613
8833
  mobile: false,
8614
8834
  sensor: false,
8615
8835
  webxr: false
8616
8836
  });
8617
- const availableRef = (0, import_react30.useRef)(false);
8618
- const modeRef = (0, import_react30.useRef)(null);
8619
- const webXRSessionRef = (0, import_react30.useRef)(null);
8620
- const [mode, setMode] = (0, import_react30.useState)(null);
8621
- const [settings, setSettings] = (0, import_react30.useState)(
8837
+ const availableRef = (0, import_react32.useRef)(false);
8838
+ const modeRef = (0, import_react32.useRef)(null);
8839
+ const webXRSessionRef = (0, import_react32.useRef)(null);
8840
+ const [mode, setMode] = (0, import_react32.useState)(null);
8841
+ const [settings, setSettings] = (0, import_react32.useState)(
8622
8842
  () => initializeSettings(screensize, profile)
8623
8843
  );
8624
- const callbacksRef = (0, import_react30.useRef)({
8844
+ const callbacksRef = (0, import_react32.useRef)({
8625
8845
  onAvailable,
8626
8846
  onDenied,
8627
8847
  onEnterVR,
@@ -8641,22 +8861,22 @@ var WebVR = (0, import_react30.forwardRef)(function WebVR2({
8641
8861
  throw new Error("<WebVR> must be rendered inside <PanoViewer>.");
8642
8862
  }
8643
8863
  const { host, xrStore } = runtime;
8644
- const resolvedProfile = (0, import_react30.useMemo)(
8864
+ const resolvedProfile = (0, import_react32.useMemo)(
8645
8865
  () => resolveWebVRProfile(profile, settings.profileId),
8646
8866
  [profile, settings.profileId]
8647
8867
  );
8648
- const reportDenied = (0, import_react30.useCallback)(
8868
+ const reportDenied = (0, import_react32.useCallback)(
8649
8869
  (error) => {
8650
8870
  eventBus.emit("vrdenied", { error });
8651
8871
  callbacksRef.current.onDenied?.(error);
8652
8872
  },
8653
8873
  [eventBus]
8654
8874
  );
8655
- const reportUnknownDevice = (0, import_react30.useCallback)(() => {
8875
+ const reportUnknownDevice = (0, import_react32.useCallback)(() => {
8656
8876
  eventBus.emit("vrunknowndevice", void 0);
8657
8877
  callbacksRef.current.onUnknownDevice?.();
8658
8878
  }, [eventBus]);
8659
- const activate = (0, import_react30.useCallback)(
8879
+ const activate = (0, import_react32.useCallback)(
8660
8880
  (nextMode) => {
8661
8881
  if (modeRef.current === nextMode) {
8662
8882
  return;
@@ -8671,7 +8891,7 @@ var WebVR = (0, import_react30.forwardRef)(function WebVR2({
8671
8891
  },
8672
8892
  [controlsRef, eventBus]
8673
8893
  );
8674
- const deactivate = (0, import_react30.useCallback)(
8894
+ const deactivate = (0, import_react32.useCallback)(
8675
8895
  (expectedMode) => {
8676
8896
  const previousMode = modeRef.current;
8677
8897
  if (!previousMode || expectedMode && previousMode !== expectedMode) {
@@ -8688,10 +8908,10 @@ var WebVR = (0, import_react30.forwardRef)(function WebVR2({
8688
8908
  },
8689
8909
  [controlsRef, eventBus, gl.domElement]
8690
8910
  );
8691
- const requestPermission = (0, import_react30.useCallback)(async () => {
8911
+ const requestPermission = (0, import_react32.useCallback)(async () => {
8692
8912
  return await gyroRef.current?.requestPermission() ?? false;
8693
8913
  }, []);
8694
- const enterVR = (0, import_react30.useCallback)(async () => {
8914
+ const enterVR = (0, import_react32.useCallback)(async () => {
8695
8915
  if (modeRef.current) {
8696
8916
  return true;
8697
8917
  }
@@ -8776,7 +8996,7 @@ var WebVR = (0, import_react30.forwardRef)(function WebVR2({
8776
8996
  wakelock,
8777
8997
  xrStore
8778
8998
  ]);
8779
- const exitVR = (0, import_react30.useCallback)(async () => {
8999
+ const exitVR = (0, import_react32.useCallback)(async () => {
8780
9000
  if (modeRef.current === "webxr") {
8781
9001
  const session2 = webXRSessionRef.current ?? xrStore.getState().session ?? null;
8782
9002
  if (session2) {
@@ -8791,14 +9011,14 @@ var WebVR = (0, import_react30.forwardRef)(function WebVR2({
8791
9011
  await exitElementFullscreen();
8792
9012
  }
8793
9013
  }, [deactivate, xrStore]);
8794
- const toggleVR = (0, import_react30.useCallback)(async () => {
9014
+ const toggleVR = (0, import_react32.useCallback)(async () => {
8795
9015
  if (modeRef.current) {
8796
9016
  await exitVR();
8797
9017
  return false;
8798
9018
  }
8799
9019
  return enterVR();
8800
9020
  }, [enterVR, exitVR]);
8801
- const updateSettings = (0, import_react30.useCallback)((next) => {
9021
+ const updateSettings = (0, import_react32.useCallback)((next) => {
8802
9022
  const normalized = {
8803
9023
  profileId: next.profileId,
8804
9024
  screensize: next.screensize === "auto" ? "auto" : Math.round(Math.max(3, Math.min(20, next.screensize)) * 10) / 10
@@ -8806,18 +9026,19 @@ var WebVR = (0, import_react30.forwardRef)(function WebVR2({
8806
9026
  setSettings(normalized);
8807
9027
  saveWebVRSettings(normalized);
8808
9028
  }, []);
8809
- const controller = (0, import_react30.useMemo)(
9029
+ const controller = (0, import_react32.useMemo)(
8810
9030
  () => ({
8811
9031
  closeSetup: () => updateWebVRHost(host, { setupOpen: false }),
8812
9032
  enterVR,
8813
9033
  exitVR,
8814
9034
  openSetup: () => updateWebVRHost(host, { setupOpen: true }),
9035
+ requestPermission,
8815
9036
  toggleVR,
8816
9037
  updateSettings
8817
9038
  }),
8818
- [enterVR, exitVR, host, toggleVR, updateSettings]
9039
+ [enterVR, exitVR, host, requestPermission, toggleVR, updateSettings]
8819
9040
  );
8820
- (0, import_react30.useImperativeHandle)(
9041
+ (0, import_react32.useImperativeHandle)(
8821
9042
  ref,
8822
9043
  () => ({
8823
9044
  enterVR,
@@ -8830,7 +9051,7 @@ var WebVR = (0, import_react30.forwardRef)(function WebVR2({
8830
9051
  }),
8831
9052
  [enterVR, exitVR, requestPermission, toggleVR]
8832
9053
  );
8833
- (0, import_react30.useEffect)(() => {
9054
+ (0, import_react32.useEffect)(() => {
8834
9055
  let active = true;
8835
9056
  void detectWebVRCapabilities().then((capabilities) => {
8836
9057
  if (!active) {
@@ -8852,7 +9073,7 @@ var WebVR = (0, import_react30.forwardRef)(function WebVR2({
8852
9073
  active = false;
8853
9074
  };
8854
9075
  }, [desktopSupport, eventBus, fakeSupport, host, mobileVr]);
8855
- (0, import_react30.useEffect)(() => {
9076
+ (0, import_react32.useEffect)(() => {
8856
9077
  host.controller = controller;
8857
9078
  return () => {
8858
9079
  if (host.controller === controller) {
@@ -8861,10 +9082,10 @@ var WebVR = (0, import_react30.forwardRef)(function WebVR2({
8861
9082
  }
8862
9083
  };
8863
9084
  }, [controller, host]);
8864
- (0, import_react30.useEffect)(() => {
9085
+ (0, import_react32.useEffect)(() => {
8865
9086
  updateWebVRHost(host, { chrome, mode, settings });
8866
9087
  }, [chrome, host, mode, settings]);
8867
- (0, import_react30.useEffect)(() => {
9088
+ (0, import_react32.useEffect)(() => {
8868
9089
  if (mode !== "fake") {
8869
9090
  return;
8870
9091
  }
@@ -8888,7 +9109,7 @@ var WebVR = (0, import_react30.forwardRef)(function WebVR2({
8888
9109
  document.removeEventListener("mousemove", onMouseMove);
8889
9110
  };
8890
9111
  }, [controlsRef, gl.domElement, mode, mousePointerLock]);
8891
- (0, import_react30.useEffect)(
9112
+ (0, import_react32.useEffect)(
8892
9113
  () => () => {
8893
9114
  const session2 = webXRSessionRef.current;
8894
9115
  if (session2) {
@@ -8940,9 +9161,92 @@ var WebVR = (0, import_react30.forwardRef)(function WebVR2({
8940
9161
  ] });
8941
9162
  });
8942
9163
 
9164
+ // src/use-pano-viewer.ts
9165
+ var import_react33 = require("react");
9166
+ function createPanoViewerHandle(ref) {
9167
+ return {
9168
+ getView: () => ref.current?.getView() ?? { yaw: 0, pitch: 0, fov: 75 },
9169
+ setView: (view, options) => {
9170
+ ref.current?.setView(view, options);
9171
+ },
9172
+ reset: () => {
9173
+ ref.current?.reset();
9174
+ },
9175
+ enterFullscreen: () => ref.current?.enterFullscreen() ?? Promise.resolve(),
9176
+ exitFullscreen: () => ref.current?.exitFullscreen() ?? Promise.resolve(),
9177
+ toggleFullscreen: () => ref.current?.toggleFullscreen() ?? Promise.resolve(),
9178
+ isFullscreen: () => ref.current?.isFullscreen() ?? false,
9179
+ setScene: (id) => ref.current?.setScene(id) ?? false,
9180
+ nextScene: () => ref.current?.nextScene() ?? false,
9181
+ previousScene: () => ref.current?.previousScene() ?? false,
9182
+ getActiveSceneId: () => ref.current?.getActiveSceneId() ?? null,
9183
+ getSceneIds: () => ref.current?.getSceneIds() ?? [],
9184
+ isSceneTransitioning: () => ref.current?.isSceneTransitioning() ?? false,
9185
+ enterVR: () => ref.current?.enterVR() ?? Promise.resolve(false),
9186
+ exitVR: () => ref.current?.exitVR() ?? Promise.resolve(),
9187
+ toggleVR: () => ref.current?.toggleVR() ?? Promise.resolve(false),
9188
+ isVRAvailable: () => ref.current?.isVRAvailable() ?? false,
9189
+ isVREnabled: () => ref.current?.isVREnabled() ?? false,
9190
+ getVRMode: () => ref.current?.getVRMode() ?? null,
9191
+ requestVRPermission: () => ref.current?.requestVRPermission() ?? Promise.resolve(false),
9192
+ getVideo: () => ref.current?.getVideo() ?? null,
9193
+ subscribeVideo: (onStoreChange) => ref.current?.subscribeVideo(onStoreChange) ?? (() => {
9194
+ }),
9195
+ playVideo: () => ref.current?.playVideo() ?? Promise.resolve(),
9196
+ pauseVideo: () => {
9197
+ ref.current?.pauseVideo();
9198
+ },
9199
+ toggleVideo: () => {
9200
+ ref.current?.toggleVideo();
9201
+ },
9202
+ seekVideo: (time) => {
9203
+ ref.current?.seekVideo(time);
9204
+ },
9205
+ setVideoVolume: (volume) => {
9206
+ ref.current?.setVideoVolume(volume);
9207
+ },
9208
+ setVideoMuted: (muted) => {
9209
+ ref.current?.setVideoMuted(muted);
9210
+ },
9211
+ toggleVideoMuted: () => {
9212
+ ref.current?.toggleVideoMuted();
9213
+ },
9214
+ getBackgroundAudio: () => ref.current?.getBackgroundAudio() ?? null,
9215
+ subscribeBackgroundAudio: (onStoreChange) => ref.current?.subscribeBackgroundAudio(onStoreChange) ?? (() => {
9216
+ }),
9217
+ playBackgroundAudio: () => ref.current?.playBackgroundAudio() ?? Promise.resolve(),
9218
+ pauseBackgroundAudio: () => {
9219
+ ref.current?.pauseBackgroundAudio();
9220
+ },
9221
+ toggleBackgroundAudio: () => {
9222
+ ref.current?.toggleBackgroundAudio();
9223
+ },
9224
+ setBackgroundAudioVolume: (volume) => {
9225
+ ref.current?.setBackgroundAudioVolume(volume);
9226
+ },
9227
+ setBackgroundAudioMuted: (muted) => {
9228
+ ref.current?.setBackgroundAudioMuted(muted);
9229
+ },
9230
+ toggleBackgroundAudioMuted: () => {
9231
+ ref.current?.toggleBackgroundAudioMuted();
9232
+ },
9233
+ startAutoRotate: () => {
9234
+ ref.current?.startAutoRotate();
9235
+ },
9236
+ stopAutoRotate: () => {
9237
+ ref.current?.stopAutoRotate();
9238
+ }
9239
+ };
9240
+ }
9241
+ function usePanoViewer() {
9242
+ const ref = (0, import_react33.useRef)(null);
9243
+ const handle = (0, import_react33.useMemo)(() => createPanoViewerHandle(ref), []);
9244
+ return (0, import_react33.useMemo)(() => ({ ref, ...handle }), [handle]);
9245
+ }
9246
+
8943
9247
  // src/sphere.tsx
8944
9248
  var import_fiber15 = require("@react-three/fiber");
8945
- var import_react32 = require("react");
9249
+ var import_react35 = require("react");
8946
9250
  var import_three10 = require("three");
8947
9251
 
8948
9252
  // src/asset-url.ts
@@ -8967,7 +9271,7 @@ function resolveUrlAgainstFile(fileUrl, path) {
8967
9271
  }
8968
9272
 
8969
9273
  // src/pano-filter/pano-basic-material.tsx
8970
- var import_react31 = require("react");
9274
+ var import_react34 = require("react");
8971
9275
 
8972
9276
  // src/pano-filter/shaders.ts
8973
9277
  var GLSL_FILTER_COMMON = `
@@ -9127,13 +9431,13 @@ function PanoBasicMaterial({
9127
9431
  toneMapped = false
9128
9432
  }) {
9129
9433
  const snapshot = usePanoFilterSnapshot();
9130
- const materialRef = (0, import_react31.useRef)(null);
9131
- const intensityRef = (0, import_react31.useRef)(snapshot.intensity);
9132
- const intensityUniformRef = (0, import_react31.useRef)(null);
9434
+ const materialRef = (0, import_react34.useRef)(null);
9435
+ const intensityRef = (0, import_react34.useRef)(snapshot.intensity);
9436
+ const intensityUniformRef = (0, import_react34.useRef)(null);
9133
9437
  intensityRef.current = snapshot.intensity;
9134
9438
  const active = isPanoFilterActive(snapshot);
9135
9439
  const preset = snapshot.preset;
9136
- const onBeforeCompile = (0, import_react31.useMemo)(() => {
9440
+ const onBeforeCompile = (0, import_react34.useMemo)(() => {
9137
9441
  if (!active || preset === "none") {
9138
9442
  return void 0;
9139
9443
  }
@@ -9150,7 +9454,7 @@ function PanoBasicMaterial({
9150
9454
  compile.toString = () => `pano-filter:${preset}`;
9151
9455
  return compile;
9152
9456
  }, [active, preset]);
9153
- (0, import_react31.useLayoutEffect)(() => {
9457
+ (0, import_react34.useLayoutEffect)(() => {
9154
9458
  if (!active) {
9155
9459
  intensityUniformRef.current = null;
9156
9460
  }
@@ -9160,7 +9464,7 @@ function PanoBasicMaterial({
9160
9464
  }
9161
9465
  material.needsUpdate = true;
9162
9466
  }, [active, preset]);
9163
- (0, import_react31.useLayoutEffect)(() => {
9467
+ (0, import_react34.useLayoutEffect)(() => {
9164
9468
  if (intensityUniformRef.current) {
9165
9469
  intensityUniformRef.current.value = snapshot.intensity;
9166
9470
  }
@@ -9183,12 +9487,12 @@ function PanoBasicMaterial({
9183
9487
  // src/sphere.tsx
9184
9488
  var import_jsx_runtime15 = require("react/jsx-runtime");
9185
9489
  function useEquirectTexture(url, anisotropy, generateMipmaps, onLoad, onError) {
9186
- const [texture, setTexture] = (0, import_react32.useState)(null);
9187
- const onLoadRef = (0, import_react32.useRef)(onLoad);
9188
- const onErrorRef = (0, import_react32.useRef)(onError);
9490
+ const [texture, setTexture] = (0, import_react35.useState)(null);
9491
+ const onLoadRef = (0, import_react35.useRef)(onLoad);
9492
+ const onErrorRef = (0, import_react35.useRef)(onError);
9189
9493
  onLoadRef.current = onLoad;
9190
9494
  onErrorRef.current = onError;
9191
- (0, import_react32.useEffect)(() => {
9495
+ (0, import_react35.useEffect)(() => {
9192
9496
  if (!url) {
9193
9497
  setTexture(null);
9194
9498
  return;
@@ -9227,7 +9531,7 @@ function useEquirectTexture(url, anisotropy, generateMipmaps, onLoad, onError) {
9227
9531
  active = false;
9228
9532
  };
9229
9533
  }, [anisotropy, generateMipmaps, url]);
9230
- (0, import_react32.useEffect)(
9534
+ (0, import_react35.useEffect)(
9231
9535
  () => () => {
9232
9536
  texture?.dispose();
9233
9537
  },
@@ -9247,7 +9551,7 @@ function Sphere({
9247
9551
  }) {
9248
9552
  const gl = (0, import_fiber15.useThree)((state) => state.gl);
9249
9553
  const anisotropy = gl.capabilities.getMaxAnisotropy();
9250
- const resolvedPreviewUrl = (0, import_react32.useMemo)(
9554
+ const resolvedPreviewUrl = (0, import_react35.useMemo)(
9251
9555
  () => resolveUrlAgainstFile(src, previewUrl),
9252
9556
  [previewUrl, src]
9253
9557
  );
@@ -9266,11 +9570,11 @@ function Sphere({
9266
9570
  onPreviewError
9267
9571
  );
9268
9572
  const displayTexture = texture ?? previewTexture;
9269
- const readyRef = (0, import_react32.useRef)(false);
9270
- (0, import_react32.useEffect)(() => {
9573
+ const readyRef = (0, import_react35.useRef)(false);
9574
+ (0, import_react35.useEffect)(() => {
9271
9575
  readyRef.current = false;
9272
9576
  }, [resolvedPreviewUrl, src]);
9273
- (0, import_react32.useEffect)(() => {
9577
+ (0, import_react35.useEffect)(() => {
9274
9578
  if (!displayTexture || readyRef.current) {
9275
9579
  return;
9276
9580
  }
@@ -9302,7 +9606,7 @@ function Sphere({
9302
9606
 
9303
9607
  // src/video/pano-video.tsx
9304
9608
  var import_fiber16 = require("@react-three/fiber");
9305
- var import_react33 = require("react");
9609
+ var import_react36 = require("react");
9306
9610
  var import_three11 = require("three");
9307
9611
  var import_jsx_runtime16 = require("react/jsx-runtime");
9308
9612
  var EMPTY_TRACKS = [];
@@ -9389,10 +9693,10 @@ function applyEquirectangularLayout(texture, anisotropy) {
9389
9693
  }
9390
9694
  function usePosterTexture(poster, onError) {
9391
9695
  const gl = (0, import_fiber16.useThree)((state) => state.gl);
9392
- const [texture, setTexture] = (0, import_react33.useState)(null);
9393
- const onErrorRef = (0, import_react33.useRef)(onError);
9696
+ const [texture, setTexture] = (0, import_react36.useState)(null);
9697
+ const onErrorRef = (0, import_react36.useRef)(onError);
9394
9698
  onErrorRef.current = onError;
9395
- (0, import_react33.useEffect)(() => {
9699
+ (0, import_react36.useEffect)(() => {
9396
9700
  let active = true;
9397
9701
  setTexture(null);
9398
9702
  if (!poster) {
@@ -9429,7 +9733,7 @@ function usePosterTexture(poster, onError) {
9429
9733
  active = false;
9430
9734
  };
9431
9735
  }, [gl, poster]);
9432
- (0, import_react33.useEffect)(
9736
+ (0, import_react36.useEffect)(
9433
9737
  () => () => {
9434
9738
  texture?.dispose();
9435
9739
  },
@@ -9487,38 +9791,38 @@ function PanoVideo({
9487
9791
  onTrackChange
9488
9792
  }) {
9489
9793
  const gl = (0, import_fiber16.useThree)((state) => state.gl);
9490
- const host = (0, import_react33.useContext)(PanoVideoHostContext);
9491
- const overlay = (0, import_react33.useContext)(PanoChromeOverlayContext);
9492
- const variants = (0, import_react33.useMemo)(
9794
+ const host = (0, import_react36.useContext)(PanoVideoHostContext);
9795
+ const overlay = (0, import_react36.useContext)(PanoChromeOverlayContext);
9796
+ const variants = (0, import_react36.useMemo)(
9493
9797
  () => resolvePanoVideoVariants({ poster, src, variants: variantsProp }),
9494
9798
  [poster, src, variantsProp]
9495
9799
  );
9496
9800
  const tracks = tracksProp ?? EMPTY_TRACKS;
9497
9801
  const captionsEnabled = captions !== false;
9498
- const captionAppearance = (0, import_react33.useMemo)(
9802
+ const captionAppearance = (0, import_react36.useMemo)(
9499
9803
  () => resolvePanoVideoCaptionAppearance(
9500
9804
  typeof captions === "object" ? captions : void 0
9501
9805
  ),
9502
9806
  [captions]
9503
9807
  );
9504
- const [variantId, setVariantId] = (0, import_react33.useState)(
9808
+ const [variantId, setVariantId] = (0, import_react36.useState)(
9505
9809
  () => resolvePanoVideoVariantId(variants, defaultVariantId)
9506
9810
  );
9507
- const [trackId, setTrackId] = (0, import_react33.useState)(
9811
+ const [trackId, setTrackId] = (0, import_react36.useState)(
9508
9812
  () => captionsEnabled ? defaultPanoVideoTrackId(tracks) : null
9509
9813
  );
9510
- const [ready, setReady] = (0, import_react33.useState)(false);
9511
- const autoPlayRef = (0, import_react33.useRef)(autoPlay);
9814
+ const [ready, setReady] = (0, import_react36.useState)(false);
9815
+ const autoPlayRef = (0, import_react36.useRef)(autoPlay);
9512
9816
  autoPlayRef.current = autoPlay;
9513
- const blockedRef = (0, import_react33.useRef)(false);
9514
- const captionAppearanceOverrideRef = (0, import_react33.useRef)(
9817
+ const blockedRef = (0, import_react36.useRef)(false);
9818
+ const captionAppearanceOverrideRef = (0, import_react36.useRef)(
9515
9819
  {}
9516
9820
  );
9517
- const mediaCapabilitiesRef = (0, import_react33.useRef)({
9821
+ const mediaCapabilitiesRef = (0, import_react36.useRef)({
9518
9822
  volumeAdjustable: true,
9519
9823
  playbackRates: [...DEFAULT_PANO_VIDEO_PLAYBACK_RATES]
9520
9824
  });
9521
- const storeRef = (0, import_react33.useRef)(null);
9825
+ const storeRef = (0, import_react36.useRef)(null);
9522
9826
  if (!storeRef.current) {
9523
9827
  storeRef.current = {
9524
9828
  snapshot: {
@@ -9528,7 +9832,7 @@ function PanoVideo({
9528
9832
  listeners: /* @__PURE__ */ new Set()
9529
9833
  };
9530
9834
  }
9531
- const actionsRef = (0, import_react33.useRef)({
9835
+ const actionsRef = (0, import_react36.useRef)({
9532
9836
  play: async () => {
9533
9837
  },
9534
9838
  pause: () => {
@@ -9548,19 +9852,19 @@ function PanoVideo({
9548
9852
  setCaptionAppearance: (_appearance) => {
9549
9853
  }
9550
9854
  });
9551
- const onLoadRef = (0, import_react33.useRef)(onLoad);
9552
- const onErrorRef = (0, import_react33.useRef)(onError);
9553
- const onPlaybackStateChangeRef = (0, import_react33.useRef)(onPlaybackStateChange);
9554
- const onEndedRef = (0, import_react33.useRef)(onEnded);
9555
- const onVariantChangeRef = (0, import_react33.useRef)(onVariantChange);
9556
- const onTrackChangeRef = (0, import_react33.useRef)(onTrackChange);
9855
+ const onLoadRef = (0, import_react36.useRef)(onLoad);
9856
+ const onErrorRef = (0, import_react36.useRef)(onError);
9857
+ const onPlaybackStateChangeRef = (0, import_react36.useRef)(onPlaybackStateChange);
9858
+ const onEndedRef = (0, import_react36.useRef)(onEnded);
9859
+ const onVariantChangeRef = (0, import_react36.useRef)(onVariantChange);
9860
+ const onTrackChangeRef = (0, import_react36.useRef)(onTrackChange);
9557
9861
  onLoadRef.current = onLoad;
9558
9862
  onErrorRef.current = onError;
9559
9863
  onPlaybackStateChangeRef.current = onPlaybackStateChange;
9560
9864
  onEndedRef.current = onEnded;
9561
9865
  onVariantChangeRef.current = onVariantChange;
9562
9866
  onTrackChangeRef.current = onTrackChange;
9563
- const resource = (0, import_react33.useMemo)(() => {
9867
+ const resource = (0, import_react36.useMemo)(() => {
9564
9868
  if (typeof document === "undefined") {
9565
9869
  return null;
9566
9870
  }
@@ -9577,7 +9881,7 @@ function PanoVideo({
9577
9881
  texture.generateMipmaps = false;
9578
9882
  return { video, texture };
9579
9883
  }, []);
9580
- (0, import_react33.useEffect)(
9884
+ (0, import_react36.useEffect)(
9581
9885
  () => () => {
9582
9886
  if (!resource) {
9583
9887
  return;
@@ -9592,13 +9896,13 @@ function PanoVideo({
9592
9896
  },
9593
9897
  [resource]
9594
9898
  );
9595
- (0, import_react33.useEffect)(() => {
9899
+ (0, import_react36.useEffect)(() => {
9596
9900
  if (!resource) {
9597
9901
  return;
9598
9902
  }
9599
9903
  resource.texture.anisotropy = gl.capabilities.getMaxAnisotropy();
9600
9904
  }, [gl, resource]);
9601
- (0, import_react33.useEffect)(() => {
9905
+ (0, import_react36.useEffect)(() => {
9602
9906
  if (!resource || !overlay?.overlayElement) {
9603
9907
  return;
9604
9908
  }
@@ -9621,7 +9925,7 @@ function PanoVideo({
9621
9925
  activeVariant?.poster ?? poster,
9622
9926
  onError
9623
9927
  );
9624
- const emitSnapshot = (0, import_react33.useCallback)(
9928
+ const emitSnapshot = (0, import_react36.useCallback)(
9625
9929
  (patch) => {
9626
9930
  const store = storeRef.current;
9627
9931
  const video = resource?.video;
@@ -9673,7 +9977,7 @@ function PanoVideo({
9673
9977
  captionAppearance
9674
9978
  ]
9675
9979
  );
9676
- const controller = (0, import_react33.useMemo)(
9980
+ const controller = (0, import_react36.useMemo)(
9677
9981
  () => ({
9678
9982
  subscribe: (onStoreChange) => {
9679
9983
  const store = storeRef.current;
@@ -9725,7 +10029,7 @@ function PanoVideo({
9725
10029
  }),
9726
10030
  []
9727
10031
  );
9728
- (0, import_react33.useLayoutEffect)(() => {
10032
+ (0, import_react36.useLayoutEffect)(() => {
9729
10033
  if (!host || variants.length === 0) {
9730
10034
  return;
9731
10035
  }
@@ -9738,7 +10042,7 @@ function PanoVideo({
9738
10042
  notifyPanoVideoHost(host);
9739
10043
  };
9740
10044
  }, [captionsEnabled, controller, controls, host, variants.length]);
9741
- (0, import_react33.useLayoutEffect)(() => {
10045
+ (0, import_react36.useLayoutEffect)(() => {
9742
10046
  if (!resource) {
9743
10047
  return;
9744
10048
  }
@@ -9751,10 +10055,10 @@ function PanoVideo({
9751
10055
  };
9752
10056
  emitSnapshot();
9753
10057
  }, [emitSnapshot, playbackRates, resource]);
9754
- (0, import_react33.useEffect)(() => {
10058
+ (0, import_react36.useEffect)(() => {
9755
10059
  emitSnapshot();
9756
10060
  }, [emitSnapshot]);
9757
- (0, import_react33.useEffect)(() => {
10061
+ (0, import_react36.useEffect)(() => {
9758
10062
  if (!resource || !activeVariant || !mediaKey) {
9759
10063
  return;
9760
10064
  }
@@ -9811,7 +10115,7 @@ function PanoVideo({
9811
10115
  video.removeEventListener("error", handleError);
9812
10116
  };
9813
10117
  }, [mediaKey, resource]);
9814
- (0, import_react33.useEffect)(() => {
10118
+ (0, import_react36.useEffect)(() => {
9815
10119
  if (!resource) {
9816
10120
  return;
9817
10121
  }
@@ -9901,7 +10205,7 @@ function PanoVideo({
9901
10205
  }
9902
10206
  };
9903
10207
  }, [emitSnapshot, resource]);
9904
- (0, import_react33.useEffect)(() => {
10208
+ (0, import_react36.useEffect)(() => {
9905
10209
  if (!resource) {
9906
10210
  return;
9907
10211
  }
@@ -9914,7 +10218,7 @@ function PanoVideo({
9914
10218
  video.playsInline = playsInline;
9915
10219
  video.preload = preload;
9916
10220
  }, [loop, muted, playsInline, preload, resource, volume]);
9917
- (0, import_react33.useEffect)(() => {
10221
+ (0, import_react36.useEffect)(() => {
9918
10222
  if (!resource) {
9919
10223
  return;
9920
10224
  }
@@ -9964,7 +10268,7 @@ function PanoVideo({
9964
10268
  video.removeEventListener("ratechange", handleVolume);
9965
10269
  };
9966
10270
  }, [emitSnapshot, resource]);
9967
- (0, import_react33.useEffect)(() => {
10271
+ (0, import_react36.useEffect)(() => {
9968
10272
  if (!resource) {
9969
10273
  return;
9970
10274
  }
@@ -9999,7 +10303,7 @@ function PanoVideo({
9999
10303
  video.textTracks.removeEventListener("change", applyModes);
10000
10304
  };
10001
10305
  }, [emitSnapshot, resource, trackId, tracks]);
10002
- (0, import_react33.useEffect)(() => {
10306
+ (0, import_react36.useEffect)(() => {
10003
10307
  if (!captionsEnabled) {
10004
10308
  setTrackId(null);
10005
10309
  return;
@@ -10035,7 +10339,7 @@ function PanoVideo({
10035
10339
 
10036
10340
  // src/scenes.tsx
10037
10341
  var import_fiber21 = require("@react-three/fiber");
10038
- var import_react38 = require("react");
10342
+ var import_react41 = require("react");
10039
10343
  var import_three19 = require("three");
10040
10344
 
10041
10345
  // src/scene-transitions/presets.ts
@@ -10086,7 +10390,7 @@ function isSnapshotTransition(preset) {
10086
10390
 
10087
10391
  // src/scene-transitions/particle-overlay.tsx
10088
10392
  var import_fiber17 = require("@react-three/fiber");
10089
- var import_react34 = require("react");
10393
+ var import_react37 = require("react");
10090
10394
  var import_three13 = require("three");
10091
10395
 
10092
10396
  // src/scene-transitions/glsl.ts
@@ -10218,12 +10522,12 @@ function ParticleOverlay({
10218
10522
  onFinish
10219
10523
  }) {
10220
10524
  const { camera } = (0, import_fiber17.useThree)();
10221
- const meshRef = (0, import_react34.useRef)(null);
10222
- const startRef = (0, import_react34.useRef)(null);
10223
- const finishedRef = (0, import_react34.useRef)(false);
10224
- const directionRef = (0, import_react34.useRef)(new import_three13.Vector3());
10225
- const geometry = (0, import_react34.useMemo)(() => createParticleGeometry(), []);
10226
- const material = (0, import_react34.useMemo)(
10525
+ const meshRef = (0, import_react37.useRef)(null);
10526
+ const startRef = (0, import_react37.useRef)(null);
10527
+ const finishedRef = (0, import_react37.useRef)(false);
10528
+ const directionRef = (0, import_react37.useRef)(new import_three13.Vector3());
10529
+ const geometry = (0, import_react37.useMemo)(() => createParticleGeometry(), []);
10530
+ const material = (0, import_react37.useMemo)(
10227
10531
  () => new import_three13.ShaderMaterial({
10228
10532
  transparent: true,
10229
10533
  depthTest: false,
@@ -10239,9 +10543,9 @@ function ParticleOverlay({
10239
10543
  }),
10240
10544
  [snapshot.texture]
10241
10545
  );
10242
- (0, import_react34.useEffect)(() => () => geometry.dispose(), [geometry]);
10243
- (0, import_react34.useEffect)(() => () => material.dispose(), [material]);
10244
- (0, import_react34.useEffect)(() => {
10546
+ (0, import_react37.useEffect)(() => () => geometry.dispose(), [geometry]);
10547
+ (0, import_react37.useEffect)(() => () => material.dispose(), [material]);
10548
+ (0, import_react37.useEffect)(() => {
10245
10549
  startRef.current = null;
10246
10550
  finishedRef.current = false;
10247
10551
  material.uniforms.progress.value = 0;
@@ -10277,7 +10581,7 @@ function ParticleOverlay({
10277
10581
 
10278
10582
  // src/scene-transitions/snapshot-overlay.tsx
10279
10583
  var import_fiber18 = require("@react-three/fiber");
10280
- var import_react35 = require("react");
10584
+ var import_react38 = require("react");
10281
10585
  var import_three15 = require("three");
10282
10586
 
10283
10587
  // src/scene-transitions/snapshot-shaders.ts
@@ -10566,18 +10870,18 @@ function SnapshotOverlay({
10566
10870
  onFinish
10567
10871
  }) {
10568
10872
  const { camera, gl } = (0, import_fiber18.useThree)();
10569
- const meshRef = (0, import_react35.useRef)(null);
10570
- const startRef = (0, import_react35.useRef)(null);
10571
- const finishedRef = (0, import_react35.useRef)(false);
10572
- const directionRef = (0, import_react35.useRef)(new import_three15.Vector3());
10573
- const material = (0, import_react35.useMemo)(() => {
10873
+ const meshRef = (0, import_react38.useRef)(null);
10874
+ const startRef = (0, import_react38.useRef)(null);
10875
+ const finishedRef = (0, import_react38.useRef)(false);
10876
+ const directionRef = (0, import_react38.useRef)(new import_three15.Vector3());
10877
+ const material = (0, import_react38.useMemo)(() => {
10574
10878
  if (!isSnapshotTransition(transition.preset)) {
10575
10879
  return null;
10576
10880
  }
10577
10881
  return createSnapshotMaterial(transition.preset, snapshot.texture);
10578
10882
  }, [snapshot.texture, transition.preset]);
10579
- (0, import_react35.useEffect)(() => () => material?.dispose(), [material]);
10580
- (0, import_react35.useEffect)(() => {
10883
+ (0, import_react38.useEffect)(() => () => material?.dispose(), [material]);
10884
+ (0, import_react38.useEffect)(() => {
10581
10885
  startRef.current = null;
10582
10886
  finishedRef.current = false;
10583
10887
  if (material) {
@@ -10659,7 +10963,7 @@ function TransitionOverlay(props) {
10659
10963
 
10660
10964
  // src/tile/texture-manager-context.tsx
10661
10965
  var import_fiber19 = require("@react-three/fiber");
10662
- var import_react36 = require("react");
10966
+ var import_react39 = require("react");
10663
10967
 
10664
10968
  // src/tile/texture-manager.ts
10665
10969
  var import_three16 = require("three");
@@ -10884,7 +11188,7 @@ var TileTextureManager = class {
10884
11188
 
10885
11189
  // src/tile/texture-manager-context.tsx
10886
11190
  var import_jsx_runtime20 = require("react/jsx-runtime");
10887
- var TileTextureManagerContext = (0, import_react36.createContext)(
11191
+ var TileTextureManagerContext = (0, import_react39.createContext)(
10888
11192
  null
10889
11193
  );
10890
11194
  function TileTextureManagerProvider({
@@ -10894,7 +11198,7 @@ function TileTextureManagerProvider({
10894
11198
  }) {
10895
11199
  const gl = (0, import_fiber19.useThree)((state) => state.gl);
10896
11200
  const anisotropy = gl.capabilities.getMaxAnisotropy();
10897
- const manager = (0, import_react36.useMemo)(
11201
+ const manager = (0, import_react39.useMemo)(
10898
11202
  () => new TileTextureManager({
10899
11203
  anisotropy,
10900
11204
  maxBytes: Math.max(1, maxTextureMemoryMb) * 1024 * 1024,
@@ -10903,19 +11207,19 @@ function TileTextureManagerProvider({
10903
11207
  }),
10904
11208
  [anisotropy, maxConcurrentLoads, maxTextureMemoryMb]
10905
11209
  );
10906
- (0, import_react36.useEffect)(() => {
11210
+ (0, import_react39.useEffect)(() => {
10907
11211
  manager.resume();
10908
11212
  return () => manager.dispose();
10909
11213
  }, [manager]);
10910
11214
  return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TileTextureManagerContext.Provider, { value: manager, children });
10911
11215
  }
10912
11216
  function useSharedTileTextureManager() {
10913
- return (0, import_react36.useContext)(TileTextureManagerContext);
11217
+ return (0, import_react39.useContext)(TileTextureManagerContext);
10914
11218
  }
10915
11219
 
10916
11220
  // src/tile/tile.tsx
10917
11221
  var import_fiber20 = require("@react-three/fiber");
10918
- var import_react37 = require("react");
11222
+ var import_react40 = require("react");
10919
11223
  var import_three18 = require("three");
10920
11224
 
10921
11225
  // src/tile/face-layout.ts
@@ -11104,10 +11408,10 @@ var VISIBILITY_FOV_PADDING_DEGREES = 8;
11104
11408
  var PREVIEW_RADIUS = CUBE_RADIUS + 0.05;
11105
11409
  var SHARED_TILE_GEOMETRY = new import_three18.PlaneGeometry(1, 1);
11106
11410
  function usePreviewTexture(url, anisotropy, onError) {
11107
- const [texture, setTexture] = (0, import_react37.useState)(null);
11108
- const onErrorRef = (0, import_react37.useRef)(onError);
11411
+ const [texture, setTexture] = (0, import_react40.useState)(null);
11412
+ const onErrorRef = (0, import_react40.useRef)(onError);
11109
11413
  onErrorRef.current = onError;
11110
- (0, import_react37.useEffect)(() => {
11414
+ (0, import_react40.useEffect)(() => {
11111
11415
  if (!url) {
11112
11416
  setTexture(null);
11113
11417
  return;
@@ -11144,7 +11448,7 @@ function usePreviewTexture(url, anisotropy, onError) {
11144
11448
  active = false;
11145
11449
  };
11146
11450
  }, [anisotropy, url]);
11147
- (0, import_react37.useEffect)(
11451
+ (0, import_react40.useEffect)(
11148
11452
  () => () => {
11149
11453
  texture?.dispose();
11150
11454
  },
@@ -11157,7 +11461,7 @@ function PreviewFace({
11157
11461
  texture,
11158
11462
  faceOrder
11159
11463
  }) {
11160
- const geometry = (0, import_react37.useMemo)(() => {
11464
+ const geometry = (0, import_react40.useMemo)(() => {
11161
11465
  const nextGeometry = new import_three18.PlaneGeometry(
11162
11466
  PREVIEW_RADIUS * 2,
11163
11467
  PREVIEW_RADIUS * 2
@@ -11175,7 +11479,7 @@ function PreviewFace({
11175
11479
  uv.needsUpdate = true;
11176
11480
  return nextGeometry;
11177
11481
  }, [face, faceOrder]);
11178
- (0, import_react37.useEffect)(
11482
+ (0, import_react40.useEffect)(
11179
11483
  () => () => {
11180
11484
  geometry.dispose();
11181
11485
  },
@@ -11216,14 +11520,14 @@ function PreviewCube({
11216
11520
  ));
11217
11521
  }
11218
11522
  function useManagedTexture(manager, key, url, address) {
11219
- const [managedState, setManagedState] = (0, import_react37.useState)(() => ({
11523
+ const [managedState, setManagedState] = (0, import_react40.useState)(() => ({
11220
11524
  manager,
11221
11525
  key,
11222
11526
  url,
11223
11527
  snapshot: manager.getSnapshot(key)
11224
11528
  }));
11225
11529
  const snapshot = managedState.manager === manager && managedState.key === key && managedState.url === url ? managedState.snapshot : manager.getSnapshot(key);
11226
- (0, import_react37.useEffect)(
11530
+ (0, import_react40.useEffect)(
11227
11531
  () => manager.acquire(key, url, address, (nextSnapshot) => {
11228
11532
  setManagedState({
11229
11533
  manager,
@@ -11236,7 +11540,7 @@ function useManagedTexture(manager, key, url, address) {
11236
11540
  );
11237
11541
  return snapshot;
11238
11542
  }
11239
- var TileMesh = (0, import_react37.memo)(function TileMesh2({
11543
+ var TileMesh = (0, import_react40.memo)(function TileMesh2({
11240
11544
  address,
11241
11545
  manager,
11242
11546
  renderOrder,
@@ -11269,7 +11573,7 @@ var TileMesh = (0, import_react37.memo)(function TileMesh2({
11269
11573
  }
11270
11574
  ) });
11271
11575
  });
11272
- var TileLayerMeshes = (0, import_react37.memo)(function TileLayerMeshes2({
11576
+ var TileLayerMeshes = (0, import_react40.memo)(function TileLayerMeshes2({
11273
11577
  layer,
11274
11578
  manager,
11275
11579
  resolveUrl
@@ -11443,10 +11747,10 @@ function Tile({
11443
11747
  onLevelChange
11444
11748
  }) {
11445
11749
  const { camera, gl, size } = (0, import_fiber20.useThree)();
11446
- const multiresConfig = (0, import_react37.useMemo)(() => parseMultires(multires), [multires]);
11750
+ const multiresConfig = (0, import_react40.useMemo)(() => parseMultires(multires), [multires]);
11447
11751
  const { levels, tileSize } = multiresConfig;
11448
11752
  const multiresToken = `${tileSize}:${levels.join(",")}`;
11449
- const candidatesByLevel = (0, import_react37.useMemo)(
11753
+ const candidatesByLevel = (0, import_react40.useMemo)(
11450
11754
  () => buildTileCandidates(levels, tileSize),
11451
11755
  [levels, tileSize]
11452
11756
  );
@@ -11458,13 +11762,13 @@ function Tile({
11458
11762
  onPreviewError
11459
11763
  );
11460
11764
  const sharedManager = useSharedTileTextureManager();
11461
- const progressRef = (0, import_react37.useRef)(onLoadProgress);
11462
- const errorRef = (0, import_react37.useRef)(onTileError);
11463
- const levelChangeRef = (0, import_react37.useRef)(onLevelChange);
11765
+ const progressRef = (0, import_react40.useRef)(onLoadProgress);
11766
+ const errorRef = (0, import_react40.useRef)(onTileError);
11767
+ const levelChangeRef = (0, import_react40.useRef)(onLevelChange);
11464
11768
  progressRef.current = onLoadProgress;
11465
11769
  errorRef.current = onTileError;
11466
11770
  levelChangeRef.current = onLevelChange;
11467
- const ownedManager = (0, import_react37.useMemo)(
11771
+ const ownedManager = (0, import_react40.useMemo)(
11468
11772
  () => new TileTextureManager({
11469
11773
  anisotropy,
11470
11774
  maxBytes: Math.max(1, maxTextureMemoryMb) * 1024 * 1024,
@@ -11485,7 +11789,7 @@ function Tile({
11485
11789
  ]
11486
11790
  );
11487
11791
  const manager = sharedManager ?? ownedManager;
11488
- (0, import_react37.useEffect)(() => {
11792
+ (0, import_react40.useEffect)(() => {
11489
11793
  manager.resume();
11490
11794
  return () => {
11491
11795
  if (manager === ownedManager) {
@@ -11495,11 +11799,11 @@ function Tile({
11495
11799
  queueMicrotask(() => manager.releaseUnused());
11496
11800
  };
11497
11801
  }, [manager, ownedManager]);
11498
- const readyRef = (0, import_react37.useRef)(false);
11499
- (0, import_react37.useEffect)(() => {
11802
+ const readyRef = (0, import_react40.useRef)(false);
11803
+ (0, import_react40.useEffect)(() => {
11500
11804
  readyRef.current = false;
11501
11805
  }, [effectivePreviewUrl]);
11502
- (0, import_react37.useEffect)(() => {
11806
+ (0, import_react40.useEffect)(() => {
11503
11807
  if (!previewTexture || readyRef.current) {
11504
11808
  return;
11505
11809
  }
@@ -11507,31 +11811,31 @@ function Tile({
11507
11811
  onReady?.();
11508
11812
  }, [onReady, previewTexture]);
11509
11813
  const template = urlTemplate ?? buildDefaultTileUrlTemplate();
11510
- const resolveUrl = (0, import_react37.useMemo)(
11814
+ const resolveUrl = (0, import_react40.useMemo)(
11511
11815
  () => (address) => {
11512
11816
  const relativePath = resolveTileUrl ? resolveTileUrl(address) : resolveTemplateUrl(template, address);
11513
11817
  return resolveRelativeTileUrl(baseUrl, relativePath);
11514
11818
  },
11515
11819
  [baseUrl, resolveTileUrl, template]
11516
11820
  );
11517
- const [layers, setLayers] = (0, import_react37.useState)([]);
11518
- const layerTokenRef = (0, import_react37.useRef)("");
11519
- const currentLevelRef = (0, import_react37.useRef)(1);
11520
- const lastUpdateAtRef = (0, import_react37.useRef)(-Infinity);
11521
- const visibilityDirtyRef = (0, import_react37.useRef)(true);
11522
- const lastVisibilityQuaternionRef = (0, import_react37.useRef)(camera.quaternion.clone());
11523
- const lastVisibilityFovRef = (0, import_react37.useRef)(Number.NaN);
11524
- const lastViewportRef = (0, import_react37.useRef)({ width: 0, height: 0, dpr: 0 });
11525
- const frustumRef = (0, import_react37.useRef)(new import_three18.Frustum());
11526
- const projectionMatrixRef = (0, import_react37.useRef)(new import_three18.Matrix4());
11527
- const visibilityCameraRef = (0, import_react37.useRef)(new import_three18.PerspectiveCamera());
11528
- (0, import_react37.useEffect)(() => {
11821
+ const [layers, setLayers] = (0, import_react40.useState)([]);
11822
+ const layerTokenRef = (0, import_react40.useRef)("");
11823
+ const currentLevelRef = (0, import_react40.useRef)(1);
11824
+ const lastUpdateAtRef = (0, import_react40.useRef)(-Infinity);
11825
+ const visibilityDirtyRef = (0, import_react40.useRef)(true);
11826
+ const lastVisibilityQuaternionRef = (0, import_react40.useRef)(camera.quaternion.clone());
11827
+ const lastVisibilityFovRef = (0, import_react40.useRef)(Number.NaN);
11828
+ const lastViewportRef = (0, import_react40.useRef)({ width: 0, height: 0, dpr: 0 });
11829
+ const frustumRef = (0, import_react40.useRef)(new import_three18.Frustum());
11830
+ const projectionMatrixRef = (0, import_react40.useRef)(new import_three18.Matrix4());
11831
+ const visibilityCameraRef = (0, import_react40.useRef)(new import_three18.PerspectiveCamera());
11832
+ (0, import_react40.useEffect)(() => {
11529
11833
  currentLevelRef.current = 1;
11530
11834
  layerTokenRef.current = "";
11531
11835
  visibilityDirtyRef.current = true;
11532
11836
  setLayers([]);
11533
11837
  }, [manager, multiresToken]);
11534
- (0, import_react37.useEffect)(() => {
11838
+ (0, import_react40.useEffect)(() => {
11535
11839
  if (loadMode !== "preview") {
11536
11840
  return;
11537
11841
  }
@@ -11682,9 +11986,9 @@ function SnapshotCapture({
11682
11986
  onCaptured
11683
11987
  }) {
11684
11988
  const { camera, gl, scene, size } = (0, import_fiber21.useThree)();
11685
- const capturedRequestRef = (0, import_react38.useRef)(0);
11686
- const renderTargetRef = (0, import_react38.useRef)(null);
11687
- (0, import_react38.useEffect)(
11989
+ const capturedRequestRef = (0, import_react41.useRef)(0);
11990
+ const renderTargetRef = (0, import_react41.useRef)(null);
11991
+ (0, import_react41.useEffect)(
11688
11992
  () => () => {
11689
11993
  renderTargetRef.current?.dispose();
11690
11994
  renderTargetRef.current = null;
@@ -11737,49 +12041,53 @@ function ScenesController({
11737
12041
  renderHotspots,
11738
12042
  onTransitionEnd,
11739
12043
  onTransitionError,
11740
- snapshotMaxPixels = 3686400
12044
+ snapshotMaxPixels = 3686400,
12045
+ phaseRef: externalPhaseRef
11741
12046
  }) {
11742
- const controlsRef = (0, import_react38.useContext)(PanoramaViewContext);
12047
+ const controlsRef = (0, import_react41.useContext)(PanoramaViewContext);
11743
12048
  const manager = useSharedTileTextureManager();
11744
- const transition = (0, import_react38.useMemo)(
12049
+ const transition = (0, import_react41.useMemo)(
11745
12050
  () => resolveTransition(transitionInput),
11746
12051
  [transitionInput]
11747
12052
  );
11748
- const sceneMap = (0, import_react38.useMemo)(
12053
+ const sceneMap = (0, import_react41.useMemo)(
11749
12054
  () => new Map(scenes.map((scene) => [scene.id, scene])),
11750
12055
  [scenes]
11751
12056
  );
11752
12057
  const initialScene = sceneMap.get(activeSceneId) ?? null;
11753
- const [slots, setSlots] = (0, import_react38.useState)([
12058
+ const [slots, setSlots] = (0, import_react41.useState)([
11754
12059
  initialScene,
11755
12060
  null
11756
12061
  ]);
11757
- const [activeSlot, setActiveSlot] = (0, import_react38.useState)(0);
11758
- const [liveSlot, setLiveSlot] = (0, import_react38.useState)(0);
11759
- const [pendingSlot, setPendingSlot] = (0, import_react38.useState)(null);
11760
- const [phase, setPhase] = (0, import_react38.useState)(initialScene ? "idle" : "preloading");
11761
- const [captureRequestId, setCaptureRequestId] = (0, import_react38.useState)(0);
11762
- const [transitionRunId, setTransitionRunId] = (0, import_react38.useState)(0);
11763
- const [snapshot, setSnapshot] = (0, import_react38.useState)(null);
11764
- const [recoveryKey, setRecoveryKey] = (0, import_react38.useState)(0);
11765
- const requestedSceneIdRef = (0, import_react38.useRef)(activeSceneId);
11766
- const captureReasonRef = (0, import_react38.useRef)("start");
11767
- const interactionReleaseRef = (0, import_react38.useRef)(null);
11768
- const slotsRef = (0, import_react38.useRef)(slots);
11769
- const phaseRef = (0, import_react38.useRef)(phase);
11770
- const liveSlotRef = (0, import_react38.useRef)(liveSlot);
11771
- const transitionFromRef = (0, import_react38.useRef)(initialScene);
12062
+ const [activeSlot, setActiveSlot] = (0, import_react41.useState)(0);
12063
+ const [liveSlot, setLiveSlot] = (0, import_react41.useState)(0);
12064
+ const [pendingSlot, setPendingSlot] = (0, import_react41.useState)(null);
12065
+ const [phase, setPhase] = (0, import_react41.useState)(initialScene ? "idle" : "preloading");
12066
+ const [captureRequestId, setCaptureRequestId] = (0, import_react41.useState)(0);
12067
+ const [transitionRunId, setTransitionRunId] = (0, import_react41.useState)(0);
12068
+ const [snapshot, setSnapshot] = (0, import_react41.useState)(null);
12069
+ const [recoveryKey, setRecoveryKey] = (0, import_react41.useState)(0);
12070
+ const requestedSceneIdRef = (0, import_react41.useRef)(activeSceneId);
12071
+ const captureReasonRef = (0, import_react41.useRef)("start");
12072
+ const interactionReleaseRef = (0, import_react41.useRef)(null);
12073
+ const slotsRef = (0, import_react41.useRef)(slots);
12074
+ const phaseRef = (0, import_react41.useRef)(phase);
12075
+ const liveSlotRef = (0, import_react41.useRef)(liveSlot);
12076
+ const transitionFromRef = (0, import_react41.useRef)(initialScene);
11772
12077
  slotsRef.current = slots;
11773
12078
  phaseRef.current = phase;
12079
+ if (externalPhaseRef) {
12080
+ externalPhaseRef.current = phase;
12081
+ }
11774
12082
  liveSlotRef.current = liveSlot;
11775
- const releaseInteraction = (0, import_react38.useCallback)(() => {
12083
+ const releaseInteraction = (0, import_react41.useCallback)(() => {
11776
12084
  interactionReleaseRef.current?.();
11777
12085
  interactionReleaseRef.current = null;
11778
12086
  }, []);
11779
- const reportError = (0, import_react38.useCallback)((sceneId, error) => {
12087
+ const reportError = (0, import_react41.useCallback)((sceneId, error) => {
11780
12088
  onTransitionError?.({ sceneId, error });
11781
12089
  }, [onTransitionError]);
11782
- const startPreload = (0, import_react38.useCallback)((scene) => {
12090
+ const startPreload = (0, import_react41.useCallback)((scene) => {
11783
12091
  const nextSlot = 1 - liveSlotRef.current;
11784
12092
  requestedSceneIdRef.current = scene.id;
11785
12093
  setSlots((current) => {
@@ -11790,7 +12098,7 @@ function ScenesController({
11790
12098
  setPendingSlot(nextSlot);
11791
12099
  setPhase("preloading");
11792
12100
  }, []);
11793
- (0, import_react38.useEffect)(() => {
12101
+ (0, import_react41.useEffect)(() => {
11794
12102
  const requested = sceneMap.get(activeSceneId);
11795
12103
  if (!requested) {
11796
12104
  reportError(activeSceneId, new Error(`Unknown panorama scene: ${activeSceneId}`));
@@ -11814,7 +12122,7 @@ function ScenesController({
11814
12122
  }
11815
12123
  startPreload(requested);
11816
12124
  }, [activeSceneId, pendingSlot, reportError, sceneMap, startPreload]);
11817
- const handleReady = (0, import_react38.useCallback)((slot) => {
12125
+ const handleReady = (0, import_react41.useCallback)((slot) => {
11818
12126
  if (slot !== pendingSlot || phaseRef.current !== "preloading") {
11819
12127
  return;
11820
12128
  }
@@ -11845,7 +12153,7 @@ function ScenesController({
11845
12153
  setPhase("capturing");
11846
12154
  setCaptureRequestId((current) => current + 1);
11847
12155
  }, [controlsRef, onTransitionEnd, pendingSlot, transition.preset]);
11848
- const handleCaptured = (0, import_react38.useCallback)((nextSnapshot) => {
12156
+ const handleCaptured = (0, import_react41.useCallback)((nextSnapshot) => {
11849
12157
  setSnapshot((current) => {
11850
12158
  current?.dispose();
11851
12159
  return nextSnapshot;
@@ -11867,7 +12175,7 @@ function ScenesController({
11867
12175
  setPhase("transitioning");
11868
12176
  setTransitionRunId((current) => current + 1);
11869
12177
  }, [manager, pendingSlot, sceneMap, startPreload]);
11870
- const finishTransition = (0, import_react38.useCallback)(() => {
12178
+ const finishTransition = (0, import_react41.useCallback)(() => {
11871
12179
  const nextSlot = pendingSlot;
11872
12180
  const previousScene = transitionFromRef.current;
11873
12181
  const nextScene = nextSlot === null ? null : slotsRef.current[nextSlot];
@@ -11892,12 +12200,12 @@ function ScenesController({
11892
12200
  });
11893
12201
  }
11894
12202
  }, [onTransitionEnd, pendingSlot, releaseInteraction, snapshot, transition.preset]);
11895
- (0, import_react38.useEffect)(() => () => {
12203
+ (0, import_react41.useEffect)(() => () => {
11896
12204
  releaseInteraction();
11897
12205
  snapshot?.dispose();
11898
12206
  }, [releaseInteraction, snapshot]);
11899
12207
  const { gl } = (0, import_fiber21.useThree)();
11900
- (0, import_react38.useEffect)(() => {
12208
+ (0, import_react41.useEffect)(() => {
11901
12209
  const canvas = gl.domElement;
11902
12210
  const onContextLost = (event) => {
11903
12211
  event.preventDefault();
@@ -11921,7 +12229,7 @@ function ScenesController({
11921
12229
  }, [gl, manager, releaseInteraction, snapshot]);
11922
12230
  const renderedScene = slots[liveSlot];
11923
12231
  const snapshotVisible = snapshot !== null && (phase === "transitioning" || phase === "recapturing" || phase === "preloading");
11924
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react38.Fragment, { children: [
12232
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react41.Fragment, { children: [
11925
12233
  /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
11926
12234
  SnapshotCapture,
11927
12235
  {
@@ -11966,39 +12274,122 @@ function ScenesController({
11966
12274
  function Scenes({
11967
12275
  maxTextureMemoryMb,
11968
12276
  maxConcurrentTileLoads,
11969
- ...props
12277
+ activeSceneId: controlledId,
12278
+ defaultActiveSceneId,
12279
+ onActiveSceneIdChange,
12280
+ scenes,
12281
+ ...rest
11970
12282
  }) {
12283
+ const isControlled = controlledId !== void 0;
12284
+ const [internalId, setInternalId] = (0, import_react41.useState)(
12285
+ () => controlledId ?? defaultActiveSceneId ?? scenes[0]?.id ?? ""
12286
+ );
12287
+ const resolvedId = isControlled ? controlledId : internalId;
12288
+ const requestSceneChange = (0, import_react41.useCallback)(
12289
+ (id) => {
12290
+ if (isControlled) {
12291
+ onActiveSceneIdChange?.(id);
12292
+ } else {
12293
+ setInternalId(id);
12294
+ }
12295
+ },
12296
+ [isControlled, onActiveSceneIdChange]
12297
+ );
12298
+ const scenesRef = (0, import_react41.useRef)(scenes);
12299
+ scenesRef.current = scenes;
12300
+ const resolvedIdRef = (0, import_react41.useRef)(resolvedId);
12301
+ resolvedIdRef.current = resolvedId;
12302
+ const host = (0, import_react41.useContext)(ScenesHostContext);
12303
+ const phaseRef = (0, import_react41.useRef)("idle");
12304
+ (0, import_react41.useEffect)(() => {
12305
+ if (!host) {
12306
+ return;
12307
+ }
12308
+ const controller = {
12309
+ setScene: (id) => {
12310
+ const match = scenesRef.current.find((s) => s.id === id);
12311
+ if (!match) {
12312
+ return false;
12313
+ }
12314
+ requestSceneChange(id);
12315
+ return true;
12316
+ },
12317
+ nextScene: () => {
12318
+ const next = cycleSceneId(
12319
+ scenesRef.current,
12320
+ resolvedIdRef.current,
12321
+ 1
12322
+ );
12323
+ if (next === null) {
12324
+ return false;
12325
+ }
12326
+ requestSceneChange(next);
12327
+ return true;
12328
+ },
12329
+ previousScene: () => {
12330
+ const next = cycleSceneId(
12331
+ scenesRef.current,
12332
+ resolvedIdRef.current,
12333
+ -1
12334
+ );
12335
+ if (next === null) {
12336
+ return false;
12337
+ }
12338
+ requestSceneChange(next);
12339
+ return true;
12340
+ },
12341
+ getActiveSceneId: () => resolvedIdRef.current,
12342
+ getSceneIds: () => scenesRef.current.map((s) => s.id),
12343
+ isTransitioning: () => phaseRef.current !== "idle"
12344
+ };
12345
+ host.controller = controller;
12346
+ notifyScenesHost(host);
12347
+ return () => {
12348
+ if (host.controller === controller) {
12349
+ host.controller = null;
12350
+ notifyScenesHost(host);
12351
+ }
12352
+ };
12353
+ }, [host, requestSceneChange]);
11971
12354
  return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
11972
12355
  TileTextureManagerProvider,
11973
12356
  {
11974
12357
  maxTextureMemoryMb,
11975
12358
  maxConcurrentLoads: maxConcurrentTileLoads,
11976
- children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ScenesController, { ...props })
12359
+ children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
12360
+ ScenesController,
12361
+ {
12362
+ ...rest,
12363
+ scenes,
12364
+ activeSceneId: resolvedId,
12365
+ phaseRef
12366
+ }
12367
+ )
11977
12368
  }
11978
12369
  );
11979
12370
  }
11980
12371
 
11981
12372
  // src/hotspot/image-hotspot.tsx
11982
12373
  var import_fiber23 = require("@react-three/fiber");
11983
- var import_react42 = require("react");
12374
+ var import_react45 = require("react");
11984
12375
  var import_three22 = require("three");
11985
12376
 
11986
12377
  // src/hotspot/hotspot-anchor.tsx
11987
12378
  var import_fiber22 = require("@react-three/fiber");
11988
- var import_react41 = require("react");
12379
+ var import_react44 = require("react");
11989
12380
  var import_three20 = require("three");
11990
12381
 
11991
12382
  // src/hotspot/hotspot-tooltip.tsx
11992
- var import_react40 = require("react");
12383
+ var import_react43 = require("react");
11993
12384
 
11994
12385
  // src/webvr/stereo-html.tsx
11995
12386
  var import_drei = require("@react-three/drei");
11996
- var import_react39 = require("react");
12387
+ var import_react42 = require("react");
11997
12388
  var import_jsx_runtime23 = require("react/jsx-runtime");
11998
12389
  function useFallbackStereoView() {
11999
- const runtime = (0, import_react39.useContext)(WebVRRuntimeContext);
12390
+ const runtime = (0, import_react42.useContext)(WebVRRuntimeContext);
12000
12391
  const host = runtime?.host ?? null;
12001
- const fallback = (0, import_react39.useSyncExternalStore)(
12392
+ const fallback = (0, import_react42.useSyncExternalStore)(
12002
12393
  (onStoreChange) => host ? subscribeWebVRHost(host, onStoreChange) : () => void 0,
12003
12394
  () => isFallbackStereoMode(host?.snapshot.mode ?? null),
12004
12395
  () => false
@@ -12112,16 +12503,16 @@ function HotspotTooltip({
12112
12503
  offset = DEFAULT_HOTSPOT_TOOLTIP_OFFSET,
12113
12504
  appearance
12114
12505
  }) {
12115
- const [imageFailed, setImageFailed] = (0, import_react40.useState)(false);
12116
- (0, import_react40.useEffect)(() => {
12506
+ const [imageFailed, setImageFailed] = (0, import_react43.useState)(false);
12507
+ (0, import_react43.useEffect)(() => {
12117
12508
  setImageFailed(false);
12118
12509
  }, [content.image]);
12119
12510
  const showImage = Boolean(content.image) && !imageFailed;
12120
- const resolvedAppearance = (0, import_react40.useMemo)(
12511
+ const resolvedAppearance = (0, import_react43.useMemo)(
12121
12512
  () => resolveHotspotTooltipAppearance(appearance),
12122
12513
  [appearance]
12123
12514
  );
12124
- const bubbleStyle = (0, import_react40.useMemo)(
12515
+ const bubbleStyle = (0, import_react43.useMemo)(
12125
12516
  () => ({
12126
12517
  background: resolvedAppearance.background,
12127
12518
  border: resolvedAppearance.border,
@@ -12500,18 +12891,18 @@ function HotspotAnchor({
12500
12891
  onPositionChange,
12501
12892
  onDragEnd
12502
12893
  }) {
12503
- const controlsRef = (0, import_react41.useContext)(PanoramaViewContext);
12504
- const eventBus = (0, import_react41.useContext)(PanoEventBusContext);
12894
+ const controlsRef = (0, import_react44.useContext)(PanoramaViewContext);
12895
+ const eventBus = (0, import_react44.useContext)(PanoEventBusContext);
12505
12896
  const cursorApi = usePanoCursor();
12506
12897
  const { camera, size } = (0, import_fiber22.useThree)();
12507
- const groupRef = (0, import_react41.useRef)(null);
12508
- const tooltipAnchorRef = (0, import_react41.useRef)(null);
12509
- const dragStateRef = (0, import_react41.useRef)(null);
12510
- const suppressNextClickRef = (0, import_react41.useRef)(false);
12511
- const [hovered, setHovered] = (0, import_react41.useState)(false);
12512
- const [dragging, setDragging] = (0, import_react41.useState)(false);
12513
- const [pinned, setPinned] = (0, import_react41.useState)(false);
12514
- const tooltipContent = (0, import_react41.useMemo)(
12898
+ const groupRef = (0, import_react44.useRef)(null);
12899
+ const tooltipAnchorRef = (0, import_react44.useRef)(null);
12900
+ const dragStateRef = (0, import_react44.useRef)(null);
12901
+ const suppressNextClickRef = (0, import_react44.useRef)(false);
12902
+ const [hovered, setHovered] = (0, import_react44.useState)(false);
12903
+ const [dragging, setDragging] = (0, import_react44.useState)(false);
12904
+ const [pinned, setPinned] = (0, import_react44.useState)(false);
12905
+ const tooltipContent = (0, import_react44.useMemo)(
12515
12906
  () => resolveHotspotTooltipContent(tooltip),
12516
12907
  [tooltip]
12517
12908
  );
@@ -12527,17 +12918,17 @@ function HotspotAnchor({
12527
12918
  scaledWidth,
12528
12919
  scaledHeight
12529
12920
  );
12530
- const worldPosition = (0, import_react41.useMemo)(
12921
+ const worldPosition = (0, import_react44.useMemo)(
12531
12922
  () => panoPositionToVector3(normalizedPosition, resolvedDistance),
12532
12923
  [normalizedPosition.pitch, normalizedPosition.yaw, resolvedDistance]
12533
12924
  );
12534
- const surfaceQuaternion3 = (0, import_react41.useMemo)(
12925
+ const surfaceQuaternion3 = (0, import_react44.useMemo)(
12535
12926
  () => createSurfaceQuaternion(normalizedPosition),
12536
12927
  [normalizedPosition.pitch, normalizedPosition.yaw]
12537
12928
  );
12538
12929
  const worldWidth = angularSizeToWorldSize(scaledWidth, resolvedDistance);
12539
12930
  const worldHeight = angularSizeToWorldSize(scaledHeight, resolvedDistance);
12540
- const focusGeometry = (0, import_react41.useMemo)(() => {
12931
+ const focusGeometry = (0, import_react44.useMemo)(() => {
12541
12932
  const planeGeometry = new import_three20.PlaneGeometry(1, 1);
12542
12933
  const geometry = new import_three20.EdgesGeometry(planeGeometry);
12543
12934
  planeGeometry.dispose();
@@ -12564,14 +12955,14 @@ function HotspotAnchor({
12564
12955
  });
12565
12956
  const tooltipOpen = visible && tooltipContent !== null && isTooltipOpen(tooltipTrigger, hovered, focused, pinned);
12566
12957
  const cursorClaimId = hotspotCursorClaimId(id);
12567
- (0, import_react41.useEffect)(
12958
+ (0, import_react44.useEffect)(
12568
12959
  () => () => {
12569
12960
  dragStateRef.current?.releaseInteractionLock();
12570
12961
  dragStateRef.current = null;
12571
12962
  },
12572
12963
  []
12573
12964
  );
12574
- (0, import_react41.useEffect)(() => {
12965
+ (0, import_react44.useEffect)(() => {
12575
12966
  if (!cursorApi) {
12576
12967
  return;
12577
12968
  }
@@ -12593,14 +12984,14 @@ function HotspotAnchor({
12593
12984
  hovered,
12594
12985
  visible
12595
12986
  ]);
12596
- (0, import_react41.useEffect)(
12987
+ (0, import_react44.useEffect)(
12597
12988
  () => () => {
12598
12989
  cursorApi?.release(cursorClaimId);
12599
12990
  },
12600
12991
  [cursorApi, cursorClaimId]
12601
12992
  );
12602
- (0, import_react41.useEffect)(() => () => focusGeometry.dispose(), [focusGeometry]);
12603
- (0, import_react41.useEffect)(() => {
12993
+ (0, import_react44.useEffect)(() => () => focusGeometry.dispose(), [focusGeometry]);
12994
+ (0, import_react44.useEffect)(() => {
12604
12995
  if (tooltipTrigger !== "click") {
12605
12996
  setPinned(false);
12606
12997
  return;
@@ -12609,12 +13000,12 @@ function HotspotAnchor({
12609
13000
  setPinned(false);
12610
13001
  });
12611
13002
  }, [eventBus, tooltipTrigger]);
12612
- (0, import_react41.useEffect)(() => {
13003
+ (0, import_react44.useEffect)(() => {
12613
13004
  if (tooltipTrigger !== "hover") {
12614
13005
  setHovered(false);
12615
13006
  }
12616
13007
  }, [tooltipTrigger]);
12617
- (0, import_react41.useEffect)(() => {
13008
+ (0, import_react44.useEffect)(() => {
12618
13009
  if (acceptsPointer) {
12619
13010
  return;
12620
13011
  }
@@ -12627,7 +13018,7 @@ function HotspotAnchor({
12627
13018
  dragStateRef.current = null;
12628
13019
  setDragging(false);
12629
13020
  }, [acceptsPointer]);
12630
- (0, import_react41.useLayoutEffect)(() => {
13021
+ (0, import_react44.useLayoutEffect)(() => {
12631
13022
  const group = groupRef.current;
12632
13023
  if (!group) {
12633
13024
  return;
@@ -12953,12 +13344,12 @@ function HotspotPlane({
12953
13344
  var import_jsx_runtime27 = require("react/jsx-runtime");
12954
13345
  function useHotspotImageTexture(src, onLoad, onError) {
12955
13346
  const gl = (0, import_fiber23.useThree)((state) => state.gl);
12956
- const [texture, setTexture] = (0, import_react42.useState)(null);
12957
- const onLoadRef = (0, import_react42.useRef)(onLoad);
12958
- const onErrorRef = (0, import_react42.useRef)(onError);
13347
+ const [texture, setTexture] = (0, import_react45.useState)(null);
13348
+ const onLoadRef = (0, import_react45.useRef)(onLoad);
13349
+ const onErrorRef = (0, import_react45.useRef)(onError);
12959
13350
  onLoadRef.current = onLoad;
12960
13351
  onErrorRef.current = onError;
12961
- (0, import_react42.useEffect)(() => {
13352
+ (0, import_react45.useEffect)(() => {
12962
13353
  let active = true;
12963
13354
  setTexture(null);
12964
13355
  if (!src) {
@@ -12996,7 +13387,7 @@ function useHotspotImageTexture(src, onLoad, onError) {
12996
13387
  active = false;
12997
13388
  };
12998
13389
  }, [gl, src]);
12999
- (0, import_react42.useEffect)(
13390
+ (0, import_react45.useEffect)(
13000
13391
  () => () => {
13001
13392
  texture?.dispose();
13002
13393
  },
@@ -13018,13 +13409,13 @@ function ImageHotspot({
13018
13409
  }
13019
13410
 
13020
13411
  // src/hotspot/polygon-hotspot.tsx
13021
- var import_react44 = require("react");
13412
+ var import_react47 = require("react");
13022
13413
  var import_three24 = require("three");
13023
13414
 
13024
13415
  // src/hotspot/hotspot-stroke-line.tsx
13025
13416
  var import_drei2 = require("@react-three/drei");
13026
13417
  var import_fiber24 = require("@react-three/fiber");
13027
- var import_react43 = require("react");
13418
+ var import_react46 = require("react");
13028
13419
  var import_three23 = require("three");
13029
13420
  var import_jsx_runtime28 = require("react/jsx-runtime");
13030
13421
  var LINE_WORLD_POSITION = new import_three23.Vector3();
@@ -13057,10 +13448,10 @@ function HotspotStrokeLine({
13057
13448
  dashSize,
13058
13449
  gapSize
13059
13450
  }) {
13060
- const lineRef = (0, import_react43.useRef)(null);
13451
+ const lineRef = (0, import_react46.useRef)(null);
13061
13452
  const { camera, size } = (0, import_fiber24.useThree)();
13062
13453
  const dash = resolveDash(dashSize, gapSize);
13063
- (0, import_react43.useLayoutEffect)(() => {
13454
+ (0, import_react46.useLayoutEffect)(() => {
13064
13455
  if (!dash.dashed) {
13065
13456
  return;
13066
13457
  }
@@ -13350,24 +13741,24 @@ function PolygonHotspot({
13350
13741
  onInvalid,
13351
13742
  ...anchorProps
13352
13743
  }) {
13353
- const issues = (0, import_react44.useMemo)(() => validatePolygonVertices(vertices), [vertices]);
13744
+ const issues = (0, import_react47.useMemo)(() => validatePolygonVertices(vertices), [vertices]);
13354
13745
  const valid = issues.length === 0;
13355
- const center = (0, import_react44.useMemo)(() => valid ? polygonCenter(vertices) : null, [valid, vertices]);
13356
- const fillGeometry = (0, import_react44.useMemo)(
13746
+ const center = (0, import_react47.useMemo)(() => valid ? polygonCenter(vertices) : null, [valid, vertices]);
13747
+ const fillGeometry = (0, import_react47.useMemo)(
13357
13748
  () => valid && center ? makeFillGeometry(vertices, center) : null,
13358
13749
  [center, valid, vertices]
13359
13750
  );
13360
- const strokePoints = (0, import_react44.useMemo)(
13751
+ const strokePoints = (0, import_react47.useMemo)(
13361
13752
  () => valid && center ? makeStrokePositions(vertices, center) : null,
13362
13753
  [center, valid, vertices]
13363
13754
  );
13364
13755
  const resolvedStrokeOpacity = Math.max(0, Math.min(strokeOpacity, 1));
13365
- const startVerticesRef = (0, import_react44.useRef)(null);
13756
+ const startVerticesRef = (0, import_react47.useRef)(null);
13366
13757
  const issuesKey = issues.map((issue) => issue.code).join(",");
13367
- (0, import_react44.useEffect)(() => {
13758
+ (0, import_react47.useEffect)(() => {
13368
13759
  if (!valid) onInvalid?.(issues);
13369
13760
  }, [issues, issuesKey, onInvalid, valid]);
13370
- (0, import_react44.useEffect)(() => () => fillGeometry?.dispose(), [fillGeometry]);
13761
+ (0, import_react47.useEffect)(() => () => fillGeometry?.dispose(), [fillGeometry]);
13371
13762
  if (!valid || !center || !fillGeometry || !strokePoints || strokePoints.length < 2) {
13372
13763
  return null;
13373
13764
  }
@@ -13447,7 +13838,7 @@ function PolygonHotspot({
13447
13838
  }
13448
13839
 
13449
13840
  // src/hotspot/polyline-hotspot.tsx
13450
- var import_react45 = require("react");
13841
+ var import_react48 = require("react");
13451
13842
  var import_three25 = require("three");
13452
13843
  var import_jsx_runtime30 = require("react/jsx-runtime");
13453
13844
  var POLYLINE_RADIUS = 990;
@@ -13566,16 +13957,16 @@ function PolylineHotspot({
13566
13957
  onInvalid,
13567
13958
  ...anchorProps
13568
13959
  }) {
13569
- const issues = (0, import_react45.useMemo)(() => validatePolylineVertices(vertices), [vertices]);
13960
+ const issues = (0, import_react48.useMemo)(() => validatePolylineVertices(vertices), [vertices]);
13570
13961
  const valid = issues.length === 0;
13571
- const center = (0, import_react45.useMemo)(() => valid ? polylineCenter(vertices) : null, [valid, vertices]);
13572
- const linePoints = (0, import_react45.useMemo)(
13962
+ const center = (0, import_react48.useMemo)(() => valid ? polylineCenter(vertices) : null, [valid, vertices]);
13963
+ const linePoints = (0, import_react48.useMemo)(
13573
13964
  () => valid && center ? makeLinePositions(vertices, center) : null,
13574
13965
  [center, valid, vertices]
13575
13966
  );
13576
13967
  const opacity = Math.max(0, Math.min(strokeOpacity, 1));
13577
- const startVerticesRef = (0, import_react45.useRef)(null);
13578
- (0, import_react45.useEffect)(() => {
13968
+ const startVerticesRef = (0, import_react48.useRef)(null);
13969
+ (0, import_react48.useEffect)(() => {
13579
13970
  if (!valid) onInvalid?.(issues);
13580
13971
  }, [issues, onInvalid, valid]);
13581
13972
  if (!valid || !center || !linePoints || linePoints.length < 2) return null;
@@ -13641,7 +14032,7 @@ function PolylineHotspot({
13641
14032
  }
13642
14033
 
13643
14034
  // src/hotspot/graphic-hotspot.tsx
13644
- var import_react46 = require("react");
14035
+ var import_react49 = require("react");
13645
14036
  var import_three26 = require("three");
13646
14037
  var import_jsx_runtime31 = require("react/jsx-runtime");
13647
14038
  var GRAPHIC_TEXTURE_SIZE = 512;
@@ -13832,12 +14223,12 @@ function createGraphicTexture(graphic, aspectWidth, aspectHeight) {
13832
14223
  return texture;
13833
14224
  }
13834
14225
  function useGraphicTexture(graphic, aspectWidth, aspectHeight, onLoad, onError) {
13835
- const [texture, setTexture] = (0, import_react46.useState)(null);
13836
- const onLoadRef = (0, import_react46.useRef)(onLoad);
13837
- const onErrorRef = (0, import_react46.useRef)(onError);
14226
+ const [texture, setTexture] = (0, import_react49.useState)(null);
14227
+ const onLoadRef = (0, import_react49.useRef)(onLoad);
14228
+ const onErrorRef = (0, import_react49.useRef)(onError);
13838
14229
  onLoadRef.current = onLoad;
13839
14230
  onErrorRef.current = onError;
13840
- (0, import_react46.useEffect)(() => {
14231
+ (0, import_react49.useEffect)(() => {
13841
14232
  let nextTexture = null;
13842
14233
  try {
13843
14234
  nextTexture = createGraphicTexture(graphic, aspectWidth, aspectHeight);
@@ -13876,7 +14267,7 @@ function GraphicHotspot(props) {
13876
14267
 
13877
14268
  // src/hotspot/sequence-hotspot.tsx
13878
14269
  var import_fiber25 = require("@react-three/fiber");
13879
- var import_react47 = require("react");
14270
+ var import_react50 = require("react");
13880
14271
  var import_three27 = require("three");
13881
14272
  var import_jsx_runtime32 = require("react/jsx-runtime");
13882
14273
  var DEFAULT_SEQUENCE_FPS = 12;
@@ -13893,12 +14284,12 @@ function useSpriteTexture({
13893
14284
  onLoadProgress
13894
14285
  }) {
13895
14286
  const gl = (0, import_fiber25.useThree)((state) => state.gl);
13896
- const [texture, setTexture] = (0, import_react47.useState)(null);
13897
- const onErrorRef = (0, import_react47.useRef)(onError);
13898
- const onLoadProgressRef = (0, import_react47.useRef)(onLoadProgress);
14287
+ const [texture, setTexture] = (0, import_react50.useState)(null);
14288
+ const onErrorRef = (0, import_react50.useRef)(onError);
14289
+ const onLoadProgressRef = (0, import_react50.useRef)(onLoadProgress);
13899
14290
  onErrorRef.current = onError;
13900
14291
  onLoadProgressRef.current = onLoadProgress;
13901
- (0, import_react47.useEffect)(() => {
14292
+ (0, import_react50.useEffect)(() => {
13902
14293
  let active = true;
13903
14294
  setTexture(null);
13904
14295
  if (!src) {
@@ -13939,7 +14330,7 @@ function useSpriteTexture({
13939
14330
  active = false;
13940
14331
  };
13941
14332
  }, [gl, id, src]);
13942
- (0, import_react47.useEffect)(
14333
+ (0, import_react50.useEffect)(
13943
14334
  () => () => {
13944
14335
  texture?.dispose();
13945
14336
  },
@@ -13968,24 +14359,24 @@ function SequenceHotspot({
13968
14359
  const texture = useSpriteTexture({ id, src, onError, onLoadProgress });
13969
14360
  const frameCount = resolveFrameCount(requestedFrameCount);
13970
14361
  const safeFps = resolveFps(fps);
13971
- const [frameIndex, setFrameIndex] = (0, import_react47.useState)(0);
13972
- const elapsedRef = (0, import_react47.useRef)(0);
13973
- const frameIndexRef = (0, import_react47.useRef)(0);
13974
- const endedRef = (0, import_react47.useRef)(false);
13975
- const lastPlaybackStateRef = (0, import_react47.useRef)(null);
13976
- const onFrameChangeRef = (0, import_react47.useRef)(onFrameChange);
13977
- const onPlaybackStateChangeRef = (0, import_react47.useRef)(onPlaybackStateChange);
13978
- const onEndedRef = (0, import_react47.useRef)(onEnded);
14362
+ const [frameIndex, setFrameIndex] = (0, import_react50.useState)(0);
14363
+ const elapsedRef = (0, import_react50.useRef)(0);
14364
+ const frameIndexRef = (0, import_react50.useRef)(0);
14365
+ const endedRef = (0, import_react50.useRef)(false);
14366
+ const lastPlaybackStateRef = (0, import_react50.useRef)(null);
14367
+ const onFrameChangeRef = (0, import_react50.useRef)(onFrameChange);
14368
+ const onPlaybackStateChangeRef = (0, import_react50.useRef)(onPlaybackStateChange);
14369
+ const onEndedRef = (0, import_react50.useRef)(onEnded);
13979
14370
  onFrameChangeRef.current = onFrameChange;
13980
14371
  onPlaybackStateChangeRef.current = onPlaybackStateChange;
13981
14372
  onEndedRef.current = onEnded;
13982
- (0, import_react47.useEffect)(() => {
14373
+ (0, import_react50.useEffect)(() => {
13983
14374
  elapsedRef.current = 0;
13984
14375
  frameIndexRef.current = 0;
13985
14376
  endedRef.current = false;
13986
14377
  setFrameIndex(0);
13987
14378
  }, [frameCount, frameDirection, src]);
13988
- (0, import_react47.useEffect)(() => {
14379
+ (0, import_react50.useEffect)(() => {
13989
14380
  if (!texture) {
13990
14381
  return;
13991
14382
  }
@@ -13999,13 +14390,13 @@ function SequenceHotspot({
13999
14390
  );
14000
14391
  texture.needsUpdate = true;
14001
14392
  }, [frameCount, frameDirection, frameIndex, texture]);
14002
- (0, import_react47.useEffect)(() => {
14393
+ (0, import_react50.useEffect)(() => {
14003
14394
  if (!texture) {
14004
14395
  return;
14005
14396
  }
14006
14397
  onFrameChangeRef.current?.({ id, index: 0, src });
14007
14398
  }, [id, src, texture]);
14008
- (0, import_react47.useEffect)(() => {
14399
+ (0, import_react50.useEffect)(() => {
14009
14400
  if (!texture) {
14010
14401
  return;
14011
14402
  }
@@ -14059,7 +14450,7 @@ function SequenceHotspot({
14059
14450
 
14060
14451
  // src/hotspot/video-hotspot.tsx
14061
14452
  var import_fiber26 = require("@react-three/fiber");
14062
- var import_react48 = require("react");
14453
+ var import_react51 = require("react");
14063
14454
  var import_three28 = require("three");
14064
14455
  var import_jsx_runtime33 = require("react/jsx-runtime");
14065
14456
  function clampVolume2(volume) {
@@ -14070,10 +14461,10 @@ function clampVolume2(volume) {
14070
14461
  }
14071
14462
  function usePosterTexture2(id, poster, onError) {
14072
14463
  const gl = (0, import_fiber26.useThree)((state) => state.gl);
14073
- const [texture, setTexture] = (0, import_react48.useState)(null);
14074
- const onErrorRef = (0, import_react48.useRef)(onError);
14464
+ const [texture, setTexture] = (0, import_react51.useState)(null);
14465
+ const onErrorRef = (0, import_react51.useRef)(onError);
14075
14466
  onErrorRef.current = onError;
14076
- (0, import_react48.useEffect)(() => {
14467
+ (0, import_react51.useEffect)(() => {
14077
14468
  let active = true;
14078
14469
  setTexture(null);
14079
14470
  if (!poster) {
@@ -14110,7 +14501,7 @@ function usePosterTexture2(id, poster, onError) {
14110
14501
  active = false;
14111
14502
  };
14112
14503
  }, [gl, id, poster]);
14113
- (0, import_react48.useEffect)(
14504
+ (0, import_react51.useEffect)(
14114
14505
  () => () => {
14115
14506
  texture?.dispose();
14116
14507
  },
@@ -14128,14 +14519,14 @@ function useVideoResource({
14128
14519
  poster,
14129
14520
  src
14130
14521
  }) {
14131
- const [resource, setResource] = (0, import_react48.useState)(null);
14132
- const onEndedRef = (0, import_react48.useRef)(onEnded);
14133
- const onErrorRef = (0, import_react48.useRef)(onError);
14134
- const onPlaybackStateChangeRef = (0, import_react48.useRef)(onPlaybackStateChange);
14522
+ const [resource, setResource] = (0, import_react51.useState)(null);
14523
+ const onEndedRef = (0, import_react51.useRef)(onEnded);
14524
+ const onErrorRef = (0, import_react51.useRef)(onError);
14525
+ const onPlaybackStateChangeRef = (0, import_react51.useRef)(onPlaybackStateChange);
14135
14526
  onEndedRef.current = onEnded;
14136
14527
  onErrorRef.current = onError;
14137
14528
  onPlaybackStateChangeRef.current = onPlaybackStateChange;
14138
- (0, import_react48.useEffect)(() => {
14529
+ (0, import_react51.useEffect)(() => {
14139
14530
  if (!src) {
14140
14531
  setResource(null);
14141
14532
  return;
@@ -14236,11 +14627,11 @@ function VideoHotspot({
14236
14627
  src
14237
14628
  });
14238
14629
  const posterTexture = usePosterTexture2(id, poster, onError);
14239
- const onPlaybackErrorRef = (0, import_react48.useRef)(onPlaybackError);
14240
- const onPlaybackStateChangeRef = (0, import_react48.useRef)(onPlaybackStateChange);
14630
+ const onPlaybackErrorRef = (0, import_react51.useRef)(onPlaybackError);
14631
+ const onPlaybackStateChangeRef = (0, import_react51.useRef)(onPlaybackStateChange);
14241
14632
  onPlaybackErrorRef.current = onPlaybackError;
14242
14633
  onPlaybackStateChangeRef.current = onPlaybackStateChange;
14243
- (0, import_react48.useEffect)(() => {
14634
+ (0, import_react51.useEffect)(() => {
14244
14635
  if (!resource) {
14245
14636
  return;
14246
14637
  }
@@ -14250,7 +14641,7 @@ function VideoHotspot({
14250
14641
  resource.video.playsInline = playsInline;
14251
14642
  resource.video.preload = preload;
14252
14643
  }, [loop, muted, playsInline, preload, resource, volume]);
14253
- (0, import_react48.useEffect)(() => {
14644
+ (0, import_react51.useEffect)(() => {
14254
14645
  if (!resource) {
14255
14646
  return;
14256
14647
  }
@@ -14278,7 +14669,7 @@ function VideoHotspot({
14278
14669
 
14279
14670
  // src/hotspot/audio-hotspot.tsx
14280
14671
  var import_fiber27 = require("@react-three/fiber");
14281
- var import_react49 = require("react");
14672
+ var import_react52 = require("react");
14282
14673
  var import_three29 = require("three");
14283
14674
  var import_jsx_runtime34 = require("react/jsx-runtime");
14284
14675
  var SPEAKER_TEXTURE_SIZE = 512;
@@ -14344,8 +14735,8 @@ function createSpeakerTexture(state) {
14344
14735
  return texture;
14345
14736
  }
14346
14737
  function useSpeakerTextures(enabled) {
14347
- const [textures, setTextures] = (0, import_react49.useState)({ playing: null, stopped: null });
14348
- (0, import_react49.useEffect)(() => {
14738
+ const [textures, setTextures] = (0, import_react52.useState)({ playing: null, stopped: null });
14739
+ (0, import_react52.useEffect)(() => {
14349
14740
  if (!enabled) {
14350
14741
  setTextures({ playing: null, stopped: null });
14351
14742
  return;
@@ -14362,10 +14753,10 @@ function useSpeakerTextures(enabled) {
14362
14753
  }
14363
14754
  function useIconTexture(icon, enabled, onError, id) {
14364
14755
  const gl = (0, import_fiber27.useThree)((state) => state.gl);
14365
- const [texture, setTexture] = (0, import_react49.useState)(null);
14366
- const onErrorRef = (0, import_react49.useRef)(onError);
14756
+ const [texture, setTexture] = (0, import_react52.useState)(null);
14757
+ const onErrorRef = (0, import_react52.useRef)(onError);
14367
14758
  onErrorRef.current = onError;
14368
- (0, import_react49.useEffect)(() => {
14759
+ (0, import_react52.useEffect)(() => {
14369
14760
  let active = true;
14370
14761
  setTexture(null);
14371
14762
  if (!enabled || !icon) {
@@ -14402,7 +14793,7 @@ function useIconTexture(icon, enabled, onError, id) {
14402
14793
  active = false;
14403
14794
  };
14404
14795
  }, [enabled, gl, icon, id]);
14405
- (0, import_react49.useEffect)(
14796
+ (0, import_react52.useEffect)(
14406
14797
  () => () => {
14407
14798
  texture?.dispose();
14408
14799
  },
@@ -14421,13 +14812,13 @@ function useAudioHowl({
14421
14812
  playing,
14422
14813
  src
14423
14814
  }) {
14424
- const [howl, setHowl] = (0, import_react49.useState)(null);
14425
- const playingRef = (0, import_react49.useRef)(playing);
14426
- const loopRef = (0, import_react49.useRef)(loop ?? false);
14427
- const onEndedRef = (0, import_react49.useRef)(onEnded);
14428
- const onErrorRef = (0, import_react49.useRef)(onError);
14429
- const onPlaybackErrorRef = (0, import_react49.useRef)(onPlaybackError);
14430
- const onPlaybackStateChangeRef = (0, import_react49.useRef)(onPlaybackStateChange);
14815
+ const [howl, setHowl] = (0, import_react52.useState)(null);
14816
+ const playingRef = (0, import_react52.useRef)(playing);
14817
+ const loopRef = (0, import_react52.useRef)(loop ?? false);
14818
+ const onEndedRef = (0, import_react52.useRef)(onEnded);
14819
+ const onErrorRef = (0, import_react52.useRef)(onError);
14820
+ const onPlaybackErrorRef = (0, import_react52.useRef)(onPlaybackError);
14821
+ const onPlaybackStateChangeRef = (0, import_react52.useRef)(onPlaybackStateChange);
14431
14822
  playingRef.current = playing;
14432
14823
  loopRef.current = loop ?? false;
14433
14824
  onEndedRef.current = onEnded;
@@ -14435,7 +14826,7 @@ function useAudioHowl({
14435
14826
  onPlaybackErrorRef.current = onPlaybackError;
14436
14827
  onPlaybackStateChangeRef.current = onPlaybackStateChange;
14437
14828
  const sourcesKey = sourceList(src).join("\0");
14438
- (0, import_react49.useEffect)(() => {
14829
+ (0, import_react52.useEffect)(() => {
14439
14830
  const sources = sourcesKey.length > 0 ? sourcesKey.split("\0") : [];
14440
14831
  if (sources.length === 0) {
14441
14832
  setHowl(null);
@@ -14472,7 +14863,7 @@ function useAudioHowl({
14472
14863
  handle.dispose();
14473
14864
  };
14474
14865
  }, [crossOrigin, id, sourcesKey]);
14475
- (0, import_react49.useEffect)(() => {
14866
+ (0, import_react52.useEffect)(() => {
14476
14867
  howl?.loop(loop ?? false);
14477
14868
  }, [howl, loop]);
14478
14869
  return howl;
@@ -14515,15 +14906,15 @@ function AudioHotspot({
14515
14906
  const stoppedIconTexture = useIconTexture(icon, marker, onError, id);
14516
14907
  const playingIconTexture = useIconTexture(playingIcon, marker, onError, id);
14517
14908
  const markerTexture = playing ? playingIconTexture ?? stoppedIconTexture ?? speakerTextures.playing : stoppedIconTexture ?? speakerTextures.stopped;
14518
- const playingRef = (0, import_react49.useRef)(playing);
14909
+ const playingRef = (0, import_react52.useRef)(playing);
14519
14910
  playingRef.current = playing;
14520
- const mutedRef = (0, import_react49.useRef)(muted);
14521
- const volumeRef = (0, import_react49.useRef)(volume);
14522
- const rangeRef = (0, import_react49.useRef)(range);
14911
+ const mutedRef = (0, import_react52.useRef)(muted);
14912
+ const volumeRef = (0, import_react52.useRef)(volume);
14913
+ const rangeRef = (0, import_react52.useRef)(range);
14523
14914
  mutedRef.current = muted;
14524
14915
  volumeRef.current = volume;
14525
14916
  rangeRef.current = range;
14526
- (0, import_react49.useEffect)(() => {
14917
+ (0, import_react52.useEffect)(() => {
14527
14918
  if (!howl) {
14528
14919
  return;
14529
14920
  }
@@ -14533,7 +14924,7 @@ function AudioHotspot({
14533
14924
  }
14534
14925
  howl.play();
14535
14926
  }, [howl, playing]);
14536
- (0, import_react49.useEffect)(() => {
14927
+ (0, import_react52.useEffect)(() => {
14537
14928
  if (!howl || !pauseWhenHidden) {
14538
14929
  return;
14539
14930
  }
@@ -14568,7 +14959,7 @@ function AudioHotspot({
14568
14959
  }
14569
14960
 
14570
14961
  // src/hotspot/text-hotspot.tsx
14571
- var import_react50 = require("react");
14962
+ var import_react53 = require("react");
14572
14963
  var import_three30 = require("three");
14573
14964
  var import_jsx_runtime35 = require("react/jsx-runtime");
14574
14965
  var TEXT_TEXTURE_LONG_SIDE = 1024;
@@ -14790,12 +15181,12 @@ function createTextTexture(text, width, height, style) {
14790
15181
  return texture;
14791
15182
  }
14792
15183
  function useTextTexture(text, width, height, style, onLoad, onError) {
14793
- const [texture, setTexture] = (0, import_react50.useState)(null);
14794
- const onLoadRef = (0, import_react50.useRef)(onLoad);
14795
- const onErrorRef = (0, import_react50.useRef)(onError);
15184
+ const [texture, setTexture] = (0, import_react53.useState)(null);
15185
+ const onLoadRef = (0, import_react53.useRef)(onLoad);
15186
+ const onErrorRef = (0, import_react53.useRef)(onError);
14796
15187
  onLoadRef.current = onLoad;
14797
15188
  onErrorRef.current = onError;
14798
- (0, import_react50.useEffect)(() => {
15189
+ (0, import_react53.useEffect)(() => {
14799
15190
  let cancelled = false;
14800
15191
  let nextTexture = null;
14801
15192
  const run = async () => {
@@ -15059,6 +15450,7 @@ function IframeHotspot({
15059
15450
  resolvePanoContextMenuEntries,
15060
15451
  unwrapPolygonVertices,
15061
15452
  usePanoEvents,
15453
+ usePanoViewer,
15062
15454
  validatePolygonVertices,
15063
15455
  validatePolylineVertices,
15064
15456
  vector3ToPanoPosition