@ericchen1990/pano-view 2.5.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -2244,12 +2244,13 @@ import { createXRStore, XR } from "@react-three/xr";
2244
2244
  import {
2245
2245
  forwardRef as forwardRef2,
2246
2246
  useCallback as useCallback6,
2247
- useContext as useContext14,
2248
- useEffect as useEffect12,
2247
+ useContext as useContext15,
2248
+ useEffect as useEffect13,
2249
2249
  useImperativeHandle as useImperativeHandle2,
2250
2250
  useMemo as useMemo7,
2251
- useRef as useRef12,
2252
- useState as useState5
2251
+ useRef as useRef13,
2252
+ useState as useState5,
2253
+ useSyncExternalStore as useSyncExternalStore6
2253
2254
  } from "react";
2254
2255
 
2255
2256
  // src/background-audio-host.ts
@@ -2274,12 +2275,127 @@ function subscribeBackgroundAudioHost(host, listener) {
2274
2275
  host.listeners.delete(listener);
2275
2276
  };
2276
2277
  }
2278
+ function subscribeBackgroundAudioStore(host, onStoreChange) {
2279
+ let unsubscribeController = host.controller?.subscribe(onStoreChange) ?? (() => {
2280
+ });
2281
+ const unsubscribeHost = subscribeBackgroundAudioHost(host, () => {
2282
+ unsubscribeController();
2283
+ unsubscribeController = host.controller?.subscribe(onStoreChange) ?? (() => {
2284
+ });
2285
+ onStoreChange();
2286
+ });
2287
+ return () => {
2288
+ unsubscribeController();
2289
+ unsubscribeHost();
2290
+ };
2291
+ }
2277
2292
 
2278
2293
  // src/cn.ts
2279
2294
  function cn(...values) {
2280
2295
  return values.filter(Boolean).join(" ");
2281
2296
  }
2282
2297
 
2298
+ // src/audio/howl.ts
2299
+ var import_howler = __toESM(require_howler());
2300
+ import_howler.Howler.autoUnlock = true;
2301
+ function resumePanoAudio() {
2302
+ if (!import_howler.Howler.ctx || import_howler.Howler.ctx.state === "running") {
2303
+ return Promise.resolve();
2304
+ }
2305
+ return import_howler.Howler.ctx.resume();
2306
+ }
2307
+ function sourceList(src) {
2308
+ if (src == null) {
2309
+ return [];
2310
+ }
2311
+ if (typeof src === "string") {
2312
+ return src ? [src] : [];
2313
+ }
2314
+ return src.filter((item) => Boolean(item));
2315
+ }
2316
+ function createUnlockingHowl({
2317
+ src,
2318
+ loop,
2319
+ crossOrigin,
2320
+ isActive,
2321
+ shouldRetryPlay,
2322
+ onEnded,
2323
+ onPlay,
2324
+ onPause,
2325
+ onLoadError,
2326
+ onPlayError
2327
+ }) {
2328
+ let disposed = false;
2329
+ let blockedNotified = false;
2330
+ const unlockListeners = [];
2331
+ const removeUnlockListeners = () => {
2332
+ for (const { type, listener } of unlockListeners) {
2333
+ window.removeEventListener(type, listener, true);
2334
+ }
2335
+ unlockListeners.length = 0;
2336
+ };
2337
+ const instance = new import_howler.Howl({
2338
+ src: [...src],
2339
+ html5: false,
2340
+ preload: true,
2341
+ loop,
2342
+ xhr: crossOrigin === "use-credentials" ? { withCredentials: true } : void 0,
2343
+ onend: () => {
2344
+ if (disposed || !isActive() || instance.loop()) {
2345
+ return;
2346
+ }
2347
+ onEnded?.();
2348
+ },
2349
+ onplay: () => {
2350
+ if (!disposed && isActive()) {
2351
+ onPlay?.();
2352
+ }
2353
+ },
2354
+ onpause: () => {
2355
+ if (!disposed && isActive()) {
2356
+ onPause?.();
2357
+ }
2358
+ },
2359
+ onloaderror: (_soundId, error) => {
2360
+ if (!disposed && isActive()) {
2361
+ onLoadError?.(error);
2362
+ }
2363
+ },
2364
+ onplayerror: (_soundId, error) => {
2365
+ if (disposed || !isActive()) {
2366
+ return;
2367
+ }
2368
+ if (!blockedNotified) {
2369
+ blockedNotified = true;
2370
+ onPlayError?.(error);
2371
+ }
2372
+ const retry = () => {
2373
+ removeUnlockListeners();
2374
+ if (!disposed && isActive() && shouldRetryPlay()) {
2375
+ void resumePanoAudio();
2376
+ instance.play();
2377
+ }
2378
+ };
2379
+ removeUnlockListeners();
2380
+ unlockListeners.push({ type: "pointerdown", listener: retry });
2381
+ unlockListeners.push({ type: "keydown", listener: retry });
2382
+ window.addEventListener("pointerdown", retry, { capture: true });
2383
+ window.addEventListener("keydown", retry, { capture: true });
2384
+ }
2385
+ });
2386
+ return {
2387
+ howl: instance,
2388
+ dispose: () => {
2389
+ if (disposed) {
2390
+ return;
2391
+ }
2392
+ disposed = true;
2393
+ removeUnlockListeners();
2394
+ instance.unload();
2395
+ }
2396
+ };
2397
+ }
2398
+
2283
2399
  // src/auto-rotate.tsx
2284
2400
  import { useFrame as useFrame2 } from "@react-three/fiber";
2285
2401
  import { useContext, useEffect as useEffect2, useRef as useRef2 } from "react";
@@ -3525,23 +3641,85 @@ function isProduction2() {
3525
3641
  return nodeEnv === "production";
3526
3642
  }
3527
3643
 
3644
+ // src/media-activation.tsx
3645
+ import { createContext as createContext7, useContext as useContext7, useEffect as useEffect6, useRef as useRef6 } from "react";
3646
+ import { jsx as jsx2 } from "react/jsx-runtime";
3647
+ var PanoMediaActivationHostContext = createContext7(null);
3648
+ function createPanoMediaActivationHost() {
3649
+ return { intents: /* @__PURE__ */ new Set(), listeners: /* @__PURE__ */ new Set(), revision: 0 };
3650
+ }
3651
+ function notify(host) {
3652
+ host.revision += 1;
3653
+ for (const listener of host.listeners) {
3654
+ listener();
3655
+ }
3656
+ }
3657
+ function getPanoMediaActivationRevision(host) {
3658
+ return host.revision;
3659
+ }
3660
+ function subscribePanoMediaActivation(host, listener) {
3661
+ host.listeners.add(listener);
3662
+ return () => {
3663
+ host.listeners.delete(listener);
3664
+ };
3665
+ }
3666
+ function hasPanoMediaActivationIntent(host) {
3667
+ return host.intents.size > 0;
3668
+ }
3669
+ function usePanoMediaActivationIntent(required) {
3670
+ const host = useContext7(PanoMediaActivationHostContext);
3671
+ const keyRef = useRef6(null);
3672
+ if (keyRef.current === null) {
3673
+ keyRef.current = /* @__PURE__ */ Symbol("pano-media-intent");
3674
+ }
3675
+ useEffect6(() => {
3676
+ if (!host || !required) {
3677
+ return;
3678
+ }
3679
+ const key = keyRef.current;
3680
+ host.intents.add(key);
3681
+ notify(host);
3682
+ return () => {
3683
+ host.intents.delete(key);
3684
+ notify(host);
3685
+ };
3686
+ }, [host, required]);
3687
+ }
3688
+ function PanoMediaActivationOverlay({
3689
+ ariaLabel = "Enable sound",
3690
+ className,
3691
+ message = "Tap to enable sound",
3692
+ onActivate
3693
+ }) {
3694
+ return /* @__PURE__ */ jsx2("div", { className: cn("pano-media-activation", className), children: /* @__PURE__ */ jsx2(
3695
+ "button",
3696
+ {
3697
+ "aria-label": ariaLabel,
3698
+ className: "pano-media-activation-button",
3699
+ onClick: onActivate,
3700
+ type: "button",
3701
+ children: message
3702
+ }
3703
+ ) });
3704
+ }
3705
+
3528
3706
  // src/pano-context-menu.tsx
3529
3707
  import {
3530
- createContext as createContext7,
3708
+ createContext as createContext8,
3531
3709
  useCallback as useCallback2,
3532
- useContext as useContext7,
3533
- useEffect as useEffect6,
3710
+ useContext as useContext8,
3711
+ useEffect as useEffect7,
3534
3712
  useId,
3535
3713
  useLayoutEffect,
3536
3714
  useMemo as useMemo3,
3537
- useRef as useRef6,
3715
+ useRef as useRef7,
3538
3716
  useState as useState2
3539
3717
  } from "react";
3540
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
3718
+ import { jsx as jsx3, jsxs } from "react/jsx-runtime";
3541
3719
  var DEFAULT_ICON_SIZE = 16;
3542
3720
  var MENU_EDGE_PADDING = 8;
3543
3721
  var MIN_PANO_CONTEXT_MENU_BACKGROUND_OPACITY = 0.4;
3544
- var PanoContextMenuOverlayContext = createContext7(null);
3722
+ var PanoContextMenuOverlayContext = createContext8(null);
3545
3723
  var DEFAULT_APPEARANCE = {
3546
3724
  background: "#161616",
3547
3725
  color: "#f4f4f4",
@@ -3581,7 +3759,7 @@ function DefaultContextMenuPanel({
3581
3759
  selectContext,
3582
3760
  onRequestClose
3583
3761
  }) {
3584
- const menuRef = useRef6(null);
3762
+ const menuRef = useRef7(null);
3585
3763
  const [activeIndex, setActiveIndex] = useState2(0);
3586
3764
  const resolved = { ...DEFAULT_APPEARANCE, ...appearance };
3587
3765
  const iconSize = Number.isFinite(resolved.iconSize) ? Math.max(0, resolved.iconSize) : DEFAULT_ICON_SIZE;
@@ -3603,7 +3781,7 @@ function DefaultContextMenuPanel({
3603
3781
  });
3604
3782
  return indices;
3605
3783
  }, [visibleItems]);
3606
- useEffect6(() => {
3784
+ useEffect7(() => {
3607
3785
  const first = focusableIndices[0];
3608
3786
  setActiveIndex(first ?? 0);
3609
3787
  const frame = requestAnimationFrame(() => {
@@ -3711,7 +3889,7 @@ function DefaultContextMenuPanel({
3711
3889
  style: panelStyle,
3712
3890
  tabIndex: -1,
3713
3891
  children: [
3714
- /* @__PURE__ */ jsx2(
3892
+ /* @__PURE__ */ jsx3(
3715
3893
  "div",
3716
3894
  {
3717
3895
  "aria-hidden": true,
@@ -3723,9 +3901,9 @@ function DefaultContextMenuPanel({
3723
3901
  }
3724
3902
  }
3725
3903
  ),
3726
- /* @__PURE__ */ jsx2("div", { className: "pano-context-menu-items", children: visibleItems.map((item, index) => {
3904
+ /* @__PURE__ */ jsx3("div", { className: "pano-context-menu-items", children: visibleItems.map((item, index) => {
3727
3905
  if (!isActionItem(item)) {
3728
- return /* @__PURE__ */ jsx2(
3906
+ return /* @__PURE__ */ jsx3(
3729
3907
  "div",
3730
3908
  {
3731
3909
  "aria-hidden": true,
@@ -3742,7 +3920,7 @@ function DefaultContextMenuPanel({
3742
3920
  );
3743
3921
  }
3744
3922
  const disabled = item.disabled === true;
3745
- const iconNode = item.icon ?? (item.image ? /* @__PURE__ */ jsx2(
3923
+ const iconNode = item.icon ?? (item.image ? /* @__PURE__ */ jsx3(
3746
3924
  "img",
3747
3925
  {
3748
3926
  alt: item.imageAlt ?? "",
@@ -3792,7 +3970,7 @@ function DefaultContextMenuPanel({
3792
3970
  tabIndex: disabled ? -1 : activeIndex === index ? 0 : -1,
3793
3971
  type: "button",
3794
3972
  children: [
3795
- /* @__PURE__ */ jsx2(
3973
+ /* @__PURE__ */ jsx3(
3796
3974
  "span",
3797
3975
  {
3798
3976
  "aria-hidden": true,
@@ -3804,7 +3982,7 @@ function DefaultContextMenuPanel({
3804
3982
  children: iconNode
3805
3983
  }
3806
3984
  ),
3807
- /* @__PURE__ */ jsx2("span", { style: { flex: 1 }, children: item.label })
3985
+ /* @__PURE__ */ jsx3("span", { style: { flex: 1 }, children: item.label })
3808
3986
  ]
3809
3987
  },
3810
3988
  item.id
@@ -3820,8 +3998,21 @@ function PositionedMenuShell({
3820
3998
  overlayElement,
3821
3999
  children
3822
4000
  }) {
3823
- const shellRef = useRef6(null);
4001
+ const shellRef = useRef7(null);
3824
4002
  const [offset, setOffset] = useState2({ left: 0, top: 0 });
4003
+ const [viewportRevision, setViewportRevision] = useState2(0);
4004
+ useEffect7(() => {
4005
+ const refresh = () => setViewportRevision((revision) => revision + 1);
4006
+ const viewport = window.visualViewport;
4007
+ window.addEventListener("resize", refresh);
4008
+ window.addEventListener("orientationchange", refresh);
4009
+ viewport?.addEventListener("resize", refresh);
4010
+ return () => {
4011
+ window.removeEventListener("resize", refresh);
4012
+ window.removeEventListener("orientationchange", refresh);
4013
+ viewport?.removeEventListener("resize", refresh);
4014
+ };
4015
+ }, []);
3825
4016
  useLayoutEffect(() => {
3826
4017
  const shell = shellRef.current;
3827
4018
  if (!overlayElement || !shell) {
@@ -3843,8 +4034,8 @@ function PositionedMenuShell({
3843
4034
  left: Math.min(Math.max(rawLeft, MENU_EDGE_PADDING), maxLeft),
3844
4035
  top: Math.min(Math.max(rawTop, MENU_EDGE_PADDING), maxTop)
3845
4036
  });
3846
- }, [clientX, clientY, overlayElement, children]);
3847
- return /* @__PURE__ */ jsx2(
4037
+ }, [clientX, clientY, overlayElement, children, viewportRevision]);
4038
+ return /* @__PURE__ */ jsx3(
3848
4039
  "div",
3849
4040
  {
3850
4041
  className: "pano-context-menu-shell",
@@ -3859,7 +4050,7 @@ function PositionedMenuShell({
3859
4050
  }
3860
4051
  function usePanoContextMenuOverlay() {
3861
4052
  const [session2, setSession] = useState2(null);
3862
- const overlayRef = useRef6(null);
4053
+ const overlayRef = useRef7(null);
3863
4054
  const [overlayElement, setOverlayElement] = useState2(
3864
4055
  null
3865
4056
  );
@@ -3871,7 +4062,7 @@ function usePanoContextMenuOverlay() {
3871
4062
  overlayRef.current = node;
3872
4063
  setOverlayElement(node);
3873
4064
  }, []);
3874
- useEffect6(() => {
4065
+ useEffect7(() => {
3875
4066
  if (!session2) {
3876
4067
  return;
3877
4068
  }
@@ -3903,7 +4094,7 @@ function usePanoContextMenuOverlay() {
3903
4094
  document.removeEventListener("keydown", handleKeyDown);
3904
4095
  };
3905
4096
  }, [session2]);
3906
- const overlay = /* @__PURE__ */ jsx2(
4097
+ const overlay = /* @__PURE__ */ jsx3(
3907
4098
  "div",
3908
4099
  {
3909
4100
  ref: setOverlayNode,
@@ -3914,7 +4105,7 @@ function usePanoContextMenuOverlay() {
3914
4105
  position: "absolute",
3915
4106
  zIndex: 20
3916
4107
  },
3917
- children: session2 ? /* @__PURE__ */ jsx2(
4108
+ children: session2 ? /* @__PURE__ */ jsx3(
3918
4109
  PositionedMenuShell,
3919
4110
  {
3920
4111
  clientX: session2.event.clientX,
@@ -3939,13 +4130,13 @@ function PanoContextMenu({
3939
4130
  separatorClassName,
3940
4131
  children
3941
4132
  }) {
3942
- const eventBus = useContext7(PanoEventBusContext);
3943
- const controlsRef = useContext7(PanoramaViewContext);
3944
- const overlayApi = useContext7(PanoContextMenuOverlayContext);
3945
- const actions = useContext7(PanoContextMenuActionsContext);
4133
+ const eventBus = useContext8(PanoEventBusContext);
4134
+ const controlsRef = useContext8(PanoramaViewContext);
4135
+ const overlayApi = useContext8(PanoContextMenuOverlayContext);
4136
+ const actions = useContext8(PanoContextMenuActionsContext);
3946
4137
  const instanceId = useId();
3947
- const sessionKeyRef = useRef6(0);
3948
- const propsRef = useRef6({
4138
+ const sessionKeyRef = useRef7(0);
4139
+ const propsRef = useRef7({
3949
4140
  items,
3950
4141
  prepend,
3951
4142
  append,
@@ -4007,9 +4198,9 @@ function PanoContextMenu({
4007
4198
  view,
4008
4199
  render: () => {
4009
4200
  if (hasCustomChildren && current.children) {
4010
- return /* @__PURE__ */ jsx2("div", { "data-pano-context-menu": true, style: { pointerEvents: "auto" }, children: current.children({ event, view, close }) });
4201
+ return /* @__PURE__ */ jsx3("div", { "data-pano-context-menu": true, style: { pointerEvents: "auto" }, children: current.children({ event, view, close }) });
4011
4202
  }
4012
- return /* @__PURE__ */ jsx2(
4203
+ return /* @__PURE__ */ jsx3(
4013
4204
  DefaultContextMenuPanel,
4014
4205
  {
4015
4206
  appearance: current.appearance,
@@ -4027,7 +4218,7 @@ function PanoContextMenu({
4027
4218
  },
4028
4219
  [actions, close, controlsRef, instanceId, overlayApi]
4029
4220
  );
4030
- useEffect6(() => {
4221
+ useEffect7(() => {
4031
4222
  const unsubscribeContextMenu = eventBus.subscribe(
4032
4223
  "contextmenu",
4033
4224
  openMenu
@@ -4060,14 +4251,14 @@ function ResetViewIcon() {
4060
4251
  viewBox: "0 0 16 16",
4061
4252
  width: "100%",
4062
4253
  children: [
4063
- /* @__PURE__ */ jsx2("path", { d: "M3.5 6.5A4.5 4.5 0 1 1 4 10" }),
4064
- /* @__PURE__ */ jsx2("path", { d: "M3.5 3.5v3h3" })
4254
+ /* @__PURE__ */ jsx3("path", { d: "M3.5 6.5A4.5 4.5 0 1 1 4 10" }),
4255
+ /* @__PURE__ */ jsx3("path", { d: "M3.5 3.5v3h3" })
4065
4256
  ]
4066
4257
  }
4067
4258
  );
4068
4259
  }
4069
4260
  function FullscreenIcon() {
4070
- return /* @__PURE__ */ jsx2(
4261
+ return /* @__PURE__ */ jsx3(
4071
4262
  "svg",
4072
4263
  {
4073
4264
  "aria-hidden": true,
@@ -4079,12 +4270,12 @@ function FullscreenIcon() {
4079
4270
  strokeWidth: "1.75",
4080
4271
  viewBox: "0 0 16 16",
4081
4272
  width: "100%",
4082
- children: /* @__PURE__ */ jsx2("path", { d: "M3 6V3h3M10 3h3v3M13 10v3h-3M6 13H3v-3" })
4273
+ children: /* @__PURE__ */ jsx3("path", { d: "M3 6V3h3M10 3h3v3M13 10v3h-3M6 13H3v-3" })
4083
4274
  }
4084
4275
  );
4085
4276
  }
4086
4277
  function ExitFullscreenIcon() {
4087
- return /* @__PURE__ */ jsx2(
4278
+ return /* @__PURE__ */ jsx3(
4088
4279
  "svg",
4089
4280
  {
4090
4281
  "aria-hidden": true,
@@ -4096,7 +4287,7 @@ function ExitFullscreenIcon() {
4096
4287
  strokeWidth: "1.75",
4097
4288
  viewBox: "0 0 16 16",
4098
4289
  width: "100%",
4099
- children: /* @__PURE__ */ jsx2("path", { d: "M6 3v3H3M10 3v3h3M3 10h3v3M10 10h3v3" })
4290
+ children: /* @__PURE__ */ jsx3("path", { d: "M6 3v3H3M10 3v3h3M3 10h3v3M10 10h3v3" })
4100
4291
  }
4101
4292
  );
4102
4293
  }
@@ -4105,7 +4296,7 @@ function createPanoContextMenuPresets(actions) {
4105
4296
  const resetView = {
4106
4297
  id: "pano-reset-view",
4107
4298
  label: "Reset view",
4108
- icon: /* @__PURE__ */ jsx2(ResetViewIcon, {}),
4299
+ icon: /* @__PURE__ */ jsx3(ResetViewIcon, {}),
4109
4300
  onSelect: () => {
4110
4301
  actions.reset();
4111
4302
  }
@@ -4113,7 +4304,7 @@ function createPanoContextMenuPresets(actions) {
4113
4304
  const fullscreen = {
4114
4305
  id: "pano-fullscreen",
4115
4306
  label: isFullscreen ? "Exit fullscreen" : "Enter fullscreen",
4116
- icon: isFullscreen ? /* @__PURE__ */ jsx2(ExitFullscreenIcon, {}) : /* @__PURE__ */ jsx2(FullscreenIcon, {}),
4307
+ icon: isFullscreen ? /* @__PURE__ */ jsx3(ExitFullscreenIcon, {}) : /* @__PURE__ */ jsx3(FullscreenIcon, {}),
4117
4308
  onSelect: () => {
4118
4309
  actions.toggleFullscreen();
4119
4310
  }
@@ -4206,19 +4397,19 @@ function composePanoContextMenuItems(props, presets) {
4206
4397
  ...resolvePanoContextMenuEntries(props.append ?? [], presets)
4207
4398
  ];
4208
4399
  }
4209
- var PanoContextMenuActionsContext = createContext7(null);
4400
+ var PanoContextMenuActionsContext = createContext8(null);
4210
4401
 
4211
4402
  // src/pano-cursor.tsx
4212
4403
  import { useThree as useThree4 } from "@react-three/fiber";
4213
4404
  import {
4214
- createContext as createContext8,
4405
+ createContext as createContext9,
4215
4406
  useCallback as useCallback3,
4216
- useContext as useContext8,
4217
- useEffect as useEffect7,
4407
+ useContext as useContext9,
4408
+ useEffect as useEffect8,
4218
4409
  useMemo as useMemo4,
4219
- useRef as useRef7
4410
+ useRef as useRef8
4220
4411
  } from "react";
4221
- import { jsx as jsx3 } from "react/jsx-runtime";
4412
+ import { jsx as jsx4 } from "react/jsx-runtime";
4222
4413
  var DEFAULT_PANO_CURSORS = {
4223
4414
  default: "grab",
4224
4415
  dragging: "grabbing",
@@ -4232,9 +4423,9 @@ var LAYER_PRIORITY = {
4232
4423
  hotspotDragging: 3,
4233
4424
  hidden: 4
4234
4425
  };
4235
- var PanoCursorContext = createContext8(null);
4426
+ var PanoCursorContext = createContext9(null);
4236
4427
  function usePanoCursor() {
4237
- return useContext8(PanoCursorContext);
4428
+ return useContext9(PanoCursorContext);
4238
4429
  }
4239
4430
  function hotspotCursorClaimId(id) {
4240
4431
  return `pano-cursor:hotspot:${id}`;
@@ -4286,10 +4477,10 @@ function PanoCursorController({
4286
4477
  children
4287
4478
  }) {
4288
4479
  const { gl } = useThree4();
4289
- const eventBus = useContext8(PanoEventBusContext);
4290
- const claimsRef = useRef7(/* @__PURE__ */ new Map());
4291
- const cursorsRef = useRef7(cursors);
4292
- const appliedCursorRef = useRef7(null);
4480
+ const eventBus = useContext9(PanoEventBusContext);
4481
+ const claimsRef = useRef8(/* @__PURE__ */ new Map());
4482
+ const cursorsRef = useRef8(cursors);
4483
+ const appliedCursorRef = useRef8(null);
4293
4484
  cursorsRef.current = cursors;
4294
4485
  const applyCursor = useCallback3(() => {
4295
4486
  const next = resolveHighestCursor(claimsRef.current, cursorsRef.current);
@@ -4323,7 +4514,7 @@ function PanoCursorController({
4323
4514
  }),
4324
4515
  [claim, cursors, release]
4325
4516
  );
4326
- useEffect7(() => {
4517
+ useEffect8(() => {
4327
4518
  const element = gl.domElement;
4328
4519
  const previous = element.style.cursor;
4329
4520
  return () => {
@@ -4332,10 +4523,10 @@ function PanoCursorController({
4332
4523
  element.style.cursor = previous;
4333
4524
  };
4334
4525
  }, [gl]);
4335
- useEffect7(() => {
4526
+ useEffect8(() => {
4336
4527
  applyCursor();
4337
4528
  }, [applyCursor, cursors]);
4338
- useEffect7(() => {
4529
+ useEffect8(() => {
4339
4530
  if (!eventBus) {
4340
4531
  return;
4341
4532
  }
@@ -4360,12 +4551,12 @@ function PanoCursorController({
4360
4551
  release(PANO_DRAG_CLAIM_ID);
4361
4552
  };
4362
4553
  }, [claim, eventBus, release]);
4363
- return /* @__PURE__ */ jsx3(PanoCursorContext.Provider, { value: api, children });
4554
+ return /* @__PURE__ */ jsx4(PanoCursorContext.Provider, { value: api, children });
4364
4555
  }
4365
4556
 
4366
4557
  // src/pano-events.tsx
4367
4558
  import { useFrame as useFrame4, useThree as useThree5 } from "@react-three/fiber";
4368
- import { useContext as useContext9, useEffect as useEffect8, useRef as useRef8 } from "react";
4559
+ import { useContext as useContext10, useEffect as useEffect9, useRef as useRef9 } from "react";
4369
4560
  var DEFAULT_IDLE_TIME_MS = 2e3;
4370
4561
  function resolveIdleTime(value) {
4371
4562
  return Number.isFinite(value) && value >= 0 ? value : DEFAULT_IDLE_TIME_MS;
@@ -4403,13 +4594,13 @@ function usePanoEvents({
4403
4594
  onVRDenied,
4404
4595
  onVRUnknownDevice
4405
4596
  }) {
4406
- const eventBus = useContext9(PanoEventBusContext);
4407
- const controlsRef = useContext9(PanoramaViewContext);
4597
+ const eventBus = useContext10(PanoEventBusContext);
4598
+ const controlsRef = useContext10(PanoramaViewContext);
4408
4599
  const { gl } = useThree5();
4409
4600
  if (!eventBus || !controlsRef) {
4410
4601
  throw new Error("usePanoEvents must be used inside <PanoViewer>.");
4411
4602
  }
4412
- const callbacksRef = useRef8({
4603
+ const callbacksRef = useRef9({
4413
4604
  onViewChange,
4414
4605
  onViewSettled,
4415
4606
  onViewInteractionStart,
@@ -4473,15 +4664,15 @@ function usePanoEvents({
4473
4664
  onVRDenied,
4474
4665
  onVRUnknownDevice
4475
4666
  };
4476
- const idleElapsedRef = useRef8(0);
4477
- const isIdleRef = useRef8(false);
4478
- const idleTimeRef = useRef8(resolveIdleTime(idleTime));
4667
+ const idleElapsedRef = useRef9(0);
4668
+ const isIdleRef = useRef9(false);
4669
+ const idleTimeRef = useRef9(resolveIdleTime(idleTime));
4479
4670
  idleTimeRef.current = resolveIdleTime(idleTime);
4480
- useEffect8(() => {
4671
+ useEffect9(() => {
4481
4672
  idleElapsedRef.current = 0;
4482
4673
  isIdleRef.current = false;
4483
4674
  }, [idleTime]);
4484
- useEffect8(() => {
4675
+ useEffect9(() => {
4485
4676
  const unsubscribers = [
4486
4677
  eventBus.subscribe("viewchange", (view) => {
4487
4678
  callbacksRef.current.onViewChange?.(view);
@@ -4562,7 +4753,7 @@ function usePanoEvents({
4562
4753
  }
4563
4754
  };
4564
4755
  }, [eventBus]);
4565
- useEffect8(() => {
4756
+ useEffect9(() => {
4566
4757
  const element = gl.domElement;
4567
4758
  const handleWheel = (nativeEvent) => {
4568
4759
  callbacksRef.current.onWheel?.({
@@ -4575,7 +4766,7 @@ function usePanoEvents({
4575
4766
  element.removeEventListener("wheel", handleWheel);
4576
4767
  };
4577
4768
  }, [gl]);
4578
- useEffect8(() => {
4769
+ useEffect9(() => {
4579
4770
  if (typeof document === "undefined") {
4580
4771
  return;
4581
4772
  }
@@ -4601,7 +4792,7 @@ function usePanoEvents({
4601
4792
  wasFullscreenRef.current = isViewerFullscreen();
4602
4793
  return subscribeFullscreenChange(handleFullscreenChange);
4603
4794
  }, [gl]);
4604
- useEffect8(() => {
4795
+ useEffect9(() => {
4605
4796
  const element = gl.domElement;
4606
4797
  if (typeof ResizeObserver === "undefined") {
4607
4798
  return;
@@ -4643,7 +4834,7 @@ function PanoEvents(props) {
4643
4834
 
4644
4835
  // src/panorama-event-surface.tsx
4645
4836
  import { useThree as useThree6 } from "@react-three/fiber";
4646
- import { useContext as useContext10, useEffect as useEffect9 } from "react";
4837
+ import { useContext as useContext11, useEffect as useEffect10 } from "react";
4647
4838
  import { BackSide, Raycaster, Vector2, Vector3 as Vector32 } from "three";
4648
4839
 
4649
4840
  // src/hotspot/coordinates.ts
@@ -4721,7 +4912,7 @@ var DEFAULT_PANORAMA_CAMERA_NEAR = 0.1;
4721
4912
  var DEFAULT_PANORAMA_CAMERA_FAR = DEFAULT_PANORAMA_RADIUS * 2;
4722
4913
 
4723
4914
  // src/panorama-event-surface.tsx
4724
- import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
4915
+ import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
4725
4916
  var EVENT_SURFACE_RADIUS = DEFAULT_PANORAMA_RADIUS - 1;
4726
4917
  function makePanoramaPointerEvent(event) {
4727
4918
  const nativeEvent = event.nativeEvent;
@@ -4736,9 +4927,9 @@ function makePanoramaPointerEvent(event) {
4736
4927
  };
4737
4928
  }
4738
4929
  function PanoramaEventSurface() {
4739
- const eventBus = useContext10(PanoEventBusContext);
4930
+ const eventBus = useContext11(PanoEventBusContext);
4740
4931
  const { camera, gl } = useThree6();
4741
- useEffect9(() => {
4932
+ useEffect10(() => {
4742
4933
  if (!eventBus) {
4743
4934
  return;
4744
4935
  }
@@ -4789,8 +4980,8 @@ function PanoramaEventSurface() {
4789
4980
  onPointerUp: (event) => emit("pointerup", event),
4790
4981
  onPointerMove: (event) => emit("pointermove", event),
4791
4982
  children: [
4792
- /* @__PURE__ */ jsx4("sphereGeometry", { args: [EVENT_SURFACE_RADIUS, 64, 32] }),
4793
- /* @__PURE__ */ jsx4(
4983
+ /* @__PURE__ */ jsx5("sphereGeometry", { args: [EVENT_SURFACE_RADIUS, 64, 32] }),
4984
+ /* @__PURE__ */ jsx5(
4794
4985
  "meshBasicMaterial",
4795
4986
  {
4796
4987
  colorWrite: false,
@@ -4807,8 +4998,8 @@ function PanoramaEventSurface() {
4807
4998
  }
4808
4999
 
4809
5000
  // src/scenes-host.ts
4810
- import { createContext as createContext9 } from "react";
4811
- var ScenesHostContext = createContext9(null);
5001
+ import { createContext as createContext10 } from "react";
5002
+ var ScenesHostContext = createContext10(null);
4812
5003
  function createScenesHost() {
4813
5004
  return {
4814
5005
  controller: null,
@@ -4825,7 +5016,7 @@ function notifyScenesHost(host) {
4825
5016
 
4826
5017
  // src/touch-controls.tsx
4827
5018
  import { useThree as useThree7 } from "@react-three/fiber";
4828
- import { useContext as useContext11, useEffect as useEffect10, useRef as useRef9 } from "react";
5019
+ import { useContext as useContext12, useEffect as useEffect11, useRef as useRef10 } from "react";
4829
5020
  var DEFAULT_ROTATE_SPEED3 = 0.35;
4830
5021
  function resolveSpeed3(value, fallback) {
4831
5022
  return Number.isFinite(value) && value >= 0 ? value : fallback;
@@ -4840,16 +5031,16 @@ function TouchControls({
4840
5031
  pinchZoom = true
4841
5032
  }) {
4842
5033
  useClaimControlChannel("touch");
4843
- const controlsRef = useContext11(PanoramaViewContext);
5034
+ const controlsRef = useContext12(PanoramaViewContext);
4844
5035
  const { gl } = useThree7();
4845
- const pointersRef = useRef9(/* @__PURE__ */ new Map());
4846
- const pinchDistanceRef = useRef9(null);
4847
- const optionsRef = useRef9({ rotateSpeed, invert, pinchZoom });
5036
+ const pointersRef = useRef10(/* @__PURE__ */ new Map());
5037
+ const pinchDistanceRef = useRef10(null);
5038
+ const optionsRef = useRef10({ rotateSpeed, invert, pinchZoom });
4848
5039
  if (!controlsRef) {
4849
5040
  throw new Error("<TouchControls> must be rendered inside <PanoViewer>.");
4850
5041
  }
4851
5042
  optionsRef.current = { rotateSpeed, invert, pinchZoom };
4852
- useEffect10(() => {
5043
+ useEffect11(() => {
4853
5044
  const element = gl.domElement;
4854
5045
  const clearPointers = () => {
4855
5046
  for (const pointerId of pointersRef.current.keys()) {
@@ -4971,9 +5162,9 @@ function TouchControls({
4971
5162
  }
4972
5163
 
4973
5164
  // src/video/chrome-overlay.tsx
4974
- import { createContext as createContext10, useCallback as useCallback4, useMemo as useMemo5, useState as useState3 } from "react";
4975
- import { jsx as jsx5 } from "react/jsx-runtime";
4976
- var PanoChromeOverlayContext = createContext10(null);
5165
+ import { createContext as createContext11, useCallback as useCallback4, useMemo as useMemo5, useState as useState3 } from "react";
5166
+ import { jsx as jsx6 } from "react/jsx-runtime";
5167
+ var PanoChromeOverlayContext = createContext11(null);
4977
5168
  function usePanoChromeOverlay() {
4978
5169
  const [overlayElement, setOverlayElement] = useState3(
4979
5170
  null
@@ -4985,7 +5176,7 @@ function usePanoChromeOverlay() {
4985
5176
  () => ({ overlayElement }),
4986
5177
  [overlayElement]
4987
5178
  );
4988
- const overlay = /* @__PURE__ */ jsx5(
5179
+ const overlay = /* @__PURE__ */ jsx6(
4989
5180
  "div",
4990
5181
  {
4991
5182
  className: "pano-chrome-overlay",
@@ -4997,9 +5188,9 @@ function usePanoChromeOverlay() {
4997
5188
  }
4998
5189
 
4999
5190
  // src/video/host.ts
5000
- import { createContext as createContext11, useContext as useContext12 } from "react";
5001
- var PanoVideoHostContext = createContext11(null);
5002
- var DefaultPanoVideoControlsContext = createContext11(false);
5191
+ import { createContext as createContext12, useContext as useContext13 } from "react";
5192
+ var PanoVideoHostContext = createContext12(null);
5193
+ var DefaultPanoVideoControlsContext = createContext12(false);
5003
5194
  function createPanoVideoHost() {
5004
5195
  return {
5005
5196
  controller: null,
@@ -5022,6 +5213,20 @@ function subscribePanoVideoHost(host, onStoreChange) {
5022
5213
  host.listeners.delete(onStoreChange);
5023
5214
  };
5024
5215
  }
5216
+ function subscribePanoVideoStore(host, onStoreChange) {
5217
+ let unsubscribeController = host.controller?.subscribe(onStoreChange) ?? (() => {
5218
+ });
5219
+ const unsubscribeHost = subscribePanoVideoHost(host, () => {
5220
+ unsubscribeController();
5221
+ unsubscribeController = host.controller?.subscribe(onStoreChange) ?? (() => {
5222
+ });
5223
+ onStoreChange();
5224
+ });
5225
+ return () => {
5226
+ unsubscribeController();
5227
+ unsubscribeHost();
5228
+ };
5229
+ }
5025
5230
  function getPanoVideoHostRevision(host) {
5026
5231
  return host.revision;
5027
5232
  }
@@ -5030,8 +5235,8 @@ function isProduction3() {
5030
5235
  return nodeEnv === "production";
5031
5236
  }
5032
5237
  function useClaimPanoVideoControls() {
5033
- const host = useContext12(PanoVideoHostContext);
5034
- const isDefault = useContext12(DefaultPanoVideoControlsContext);
5238
+ const host = useContext13(PanoVideoHostContext);
5239
+ const isDefault = useContext13(DefaultPanoVideoControlsContext);
5035
5240
  if (!host || isDefault) {
5036
5241
  return;
5037
5242
  }
@@ -5048,7 +5253,7 @@ import { useSyncExternalStore as useSyncExternalStore4 } from "react";
5048
5253
 
5049
5254
  // src/video/pano-video-captions.tsx
5050
5255
  import { useSyncExternalStore as useSyncExternalStore2 } from "react";
5051
- import { jsx as jsx6 } from "react/jsx-runtime";
5256
+ import { jsx as jsx7 } from "react/jsx-runtime";
5052
5257
  var DEFAULT_PANO_VIDEO_CAPTION_APPEARANCE = {
5053
5258
  color: "#ffffff",
5054
5259
  background: "rgba(0, 0, 0, 0.55)",
@@ -5096,13 +5301,13 @@ function PanoVideoCaptionsOverlay({
5096
5301
  textShadow: snapshot.captionAppearance.textShadow,
5097
5302
  whiteSpace: "pre-wrap"
5098
5303
  };
5099
- return /* @__PURE__ */ jsx6(
5304
+ return /* @__PURE__ */ jsx7(
5100
5305
  "div",
5101
5306
  {
5102
5307
  className: "pano-video-captions",
5103
5308
  "data-pano-video-captions": "",
5104
5309
  style: wrapperStyle,
5105
- children: /* @__PURE__ */ jsx6("div", { style: textStyle, children: snapshot.captionText })
5310
+ children: /* @__PURE__ */ jsx7("div", { style: textStyle, children: snapshot.captionText })
5106
5311
  }
5107
5312
  );
5108
5313
  }
@@ -5115,11 +5320,11 @@ function PanoVideoCaptions({
5115
5320
  // src/video/pano-video-controls.tsx
5116
5321
  import {
5117
5322
  useCallback as useCallback5,
5118
- useContext as useContext13,
5119
- useEffect as useEffect11,
5323
+ useContext as useContext14,
5324
+ useEffect as useEffect12,
5120
5325
  useId as useId2,
5121
5326
  useMemo as useMemo6,
5122
- useRef as useRef10,
5327
+ useRef as useRef11,
5123
5328
  useState as useState4,
5124
5329
  useSyncExternalStore as useSyncExternalStore3
5125
5330
  } from "react";
@@ -5254,7 +5459,7 @@ function cueText(cue) {
5254
5459
  }
5255
5460
 
5256
5461
  // src/video/pano-video-controls.tsx
5257
- import { Fragment, jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
5462
+ import { Fragment, jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
5258
5463
  var DEFAULT_PANO_VIDEO_CONTROLS_APPEARANCE = {
5259
5464
  background: "rgba(16, 16, 16, 0.88)",
5260
5465
  color: "#f4f4f4",
@@ -5315,7 +5520,7 @@ function volumeFromClientY(clientY, track) {
5315
5520
  return Math.max(0, Math.min(1, (rect.bottom - clientY) / rect.height));
5316
5521
  }
5317
5522
  function Icon({ path }) {
5318
- return /* @__PURE__ */ jsx7(
5523
+ return /* @__PURE__ */ jsx8(
5319
5524
  "svg",
5320
5525
  {
5321
5526
  "aria-hidden": true,
@@ -5327,7 +5532,7 @@ function Icon({ path }) {
5327
5532
  strokeWidth: "1.75",
5328
5533
  viewBox: "0 0 16 16",
5329
5534
  width: "16",
5330
- children: /* @__PURE__ */ jsx7("path", { d: path })
5535
+ children: /* @__PURE__ */ jsx8("path", { d: path })
5331
5536
  }
5332
5537
  );
5333
5538
  }
@@ -5339,7 +5544,7 @@ function ChromeButton({
5339
5544
  label,
5340
5545
  onClick
5341
5546
  }) {
5342
- return /* @__PURE__ */ jsx7(
5547
+ return /* @__PURE__ */ jsx8(
5343
5548
  "button",
5344
5549
  {
5345
5550
  "aria-label": label,
@@ -5365,14 +5570,14 @@ function ChromeMenu({
5365
5570
  labelledBy,
5366
5571
  items
5367
5572
  }) {
5368
- return /* @__PURE__ */ jsx7(
5573
+ return /* @__PURE__ */ jsx8(
5369
5574
  ChromeMenuSurface,
5370
5575
  {
5371
5576
  appearance,
5372
5577
  id,
5373
5578
  labelledBy,
5374
5579
  role: "menu",
5375
- children: items.map((item) => /* @__PURE__ */ jsx7(
5580
+ children: items.map((item) => /* @__PURE__ */ jsx8(
5376
5581
  ChromeMenuRadioItem,
5377
5582
  {
5378
5583
  active: item.active,
@@ -5392,7 +5597,7 @@ function ChromeMenuSurface({
5392
5597
  labelledBy,
5393
5598
  role
5394
5599
  }) {
5395
- return /* @__PURE__ */ jsx7(
5600
+ return /* @__PURE__ */ jsx8(
5396
5601
  "div",
5397
5602
  {
5398
5603
  "aria-labelledby": labelledBy,
@@ -5416,7 +5621,7 @@ function ChromeMenuRadioItem({
5416
5621
  label,
5417
5622
  onClick
5418
5623
  }) {
5419
- return /* @__PURE__ */ jsx7(
5624
+ return /* @__PURE__ */ jsx8(
5420
5625
  "button",
5421
5626
  {
5422
5627
  "aria-checked": active,
@@ -5456,7 +5661,7 @@ function ChromeMenuActionItem({
5456
5661
  },
5457
5662
  type: "button",
5458
5663
  children: [
5459
- /* @__PURE__ */ jsx7("span", { children: label }),
5664
+ /* @__PURE__ */ jsx8("span", { children: label }),
5460
5665
  secondary
5461
5666
  ]
5462
5667
  }
@@ -5465,10 +5670,10 @@ function ChromeMenuActionItem({
5465
5670
  function ChromeMenuSectionLabel({
5466
5671
  children
5467
5672
  }) {
5468
- return /* @__PURE__ */ jsx7("div", { className: "pano-video-chrome-menu-label", children });
5673
+ return /* @__PURE__ */ jsx8("div", { className: "pano-video-chrome-menu-label", children });
5469
5674
  }
5470
5675
  function ChromeMenuDivider() {
5471
- return /* @__PURE__ */ jsx7("div", { className: "pano-video-chrome-menu-divider" });
5676
+ return /* @__PURE__ */ jsx8("div", { className: "pano-video-chrome-menu-divider" });
5472
5677
  }
5473
5678
  function CaptionsMenu({
5474
5679
  appearance,
@@ -5481,7 +5686,7 @@ function CaptionsMenu({
5481
5686
  panel,
5482
5687
  snapshot
5483
5688
  }) {
5484
- return /* @__PURE__ */ jsx7(
5689
+ return /* @__PURE__ */ jsx8(
5485
5690
  ChromeMenuSurface,
5486
5691
  {
5487
5692
  appearance,
@@ -5490,7 +5695,7 @@ function CaptionsMenu({
5490
5695
  role: "menu",
5491
5696
  children: panel === "tracks" ? /* @__PURE__ */ jsxs3(Fragment, { children: [
5492
5697
  /* @__PURE__ */ jsxs3("div", { className: "pano-video-chrome-menu-list", children: [
5493
- /* @__PURE__ */ jsx7(
5698
+ /* @__PURE__ */ jsx8(
5494
5699
  ChromeMenuRadioItem,
5495
5700
  {
5496
5701
  active: snapshot.trackId === null,
@@ -5503,7 +5708,7 @@ function CaptionsMenu({
5503
5708
  ),
5504
5709
  snapshot.tracks.map((track) => {
5505
5710
  const trackItemId = panoVideoTrackId(track);
5506
- return /* @__PURE__ */ jsx7(
5711
+ return /* @__PURE__ */ jsx8(
5507
5712
  ChromeMenuRadioItem,
5508
5713
  {
5509
5714
  active: snapshot.trackId === trackItemId,
@@ -5517,29 +5722,29 @@ function CaptionsMenu({
5517
5722
  );
5518
5723
  })
5519
5724
  ] }),
5520
- /* @__PURE__ */ jsx7(ChromeMenuDivider, {}),
5521
- /* @__PURE__ */ jsx7(
5725
+ /* @__PURE__ */ jsx8(ChromeMenuDivider, {}),
5726
+ /* @__PURE__ */ jsx8(
5522
5727
  ChromeMenuActionItem,
5523
5728
  {
5524
5729
  appearance,
5525
5730
  label: "Settings",
5526
5731
  onClick: onOpenSettings,
5527
- secondary: /* @__PURE__ */ jsx7("span", { "aria-hidden": true, children: "\u203A" })
5732
+ secondary: /* @__PURE__ */ jsx8("span", { "aria-hidden": true, children: "\u203A" })
5528
5733
  }
5529
5734
  )
5530
5735
  ] }) : /* @__PURE__ */ jsxs3(Fragment, { children: [
5531
- /* @__PURE__ */ jsx7(
5736
+ /* @__PURE__ */ jsx8(
5532
5737
  ChromeMenuActionItem,
5533
5738
  {
5534
5739
  appearance,
5535
5740
  label: "Back",
5536
5741
  onClick: onShowTracks,
5537
- secondary: /* @__PURE__ */ jsx7("span", { "aria-hidden": true, children: "\u2039" })
5742
+ secondary: /* @__PURE__ */ jsx8("span", { "aria-hidden": true, children: "\u2039" })
5538
5743
  }
5539
5744
  ),
5540
- /* @__PURE__ */ jsx7(ChromeMenuDivider, {}),
5541
- /* @__PURE__ */ jsx7(ChromeMenuSectionLabel, { children: "Font size" }),
5542
- CAPTION_SIZE_OPTIONS.map((option) => /* @__PURE__ */ jsx7(
5745
+ /* @__PURE__ */ jsx8(ChromeMenuDivider, {}),
5746
+ /* @__PURE__ */ jsx8(ChromeMenuSectionLabel, { children: "Font size" }),
5747
+ CAPTION_SIZE_OPTIONS.map((option) => /* @__PURE__ */ jsx8(
5543
5748
  ChromeMenuRadioItem,
5544
5749
  {
5545
5750
  active: Number(snapshot.captionAppearance.fontSize) === option.value,
@@ -5551,9 +5756,9 @@ function CaptionsMenu({
5551
5756
  },
5552
5757
  option.id
5553
5758
  )),
5554
- /* @__PURE__ */ jsx7(ChromeMenuDivider, {}),
5555
- /* @__PURE__ */ jsx7(ChromeMenuSectionLabel, { children: "Background" }),
5556
- CAPTION_BACKGROUND_OPTIONS.map((option) => /* @__PURE__ */ jsx7(
5759
+ /* @__PURE__ */ jsx8(ChromeMenuDivider, {}),
5760
+ /* @__PURE__ */ jsx8(ChromeMenuSectionLabel, { children: "Background" }),
5761
+ CAPTION_BACKGROUND_OPTIONS.map((option) => /* @__PURE__ */ jsx8(
5557
5762
  ChromeMenuRadioItem,
5558
5763
  {
5559
5764
  active: snapshot.captionAppearance.background === option.value,
@@ -5574,7 +5779,7 @@ function VerticalVolumeSlider({
5574
5779
  onVolume,
5575
5780
  volume
5576
5781
  }) {
5577
- const trackRef = useRef10(null);
5782
+ const trackRef = useRef11(null);
5578
5783
  const applyPointer = (event) => {
5579
5784
  const track = trackRef.current;
5580
5785
  if (!track) {
@@ -5608,7 +5813,7 @@ function VerticalVolumeSlider({
5608
5813
  pointerEvents: "auto"
5609
5814
  },
5610
5815
  children: [
5611
- /* @__PURE__ */ jsx7(
5816
+ /* @__PURE__ */ jsx8(
5612
5817
  "span",
5613
5818
  {
5614
5819
  "aria-hidden": true,
@@ -5620,7 +5825,7 @@ function VerticalVolumeSlider({
5620
5825
  children: percentLabel
5621
5826
  }
5622
5827
  ),
5623
- /* @__PURE__ */ jsx7(
5828
+ /* @__PURE__ */ jsx8(
5624
5829
  "div",
5625
5830
  {
5626
5831
  style: {
@@ -5660,7 +5865,7 @@ function VerticalVolumeSlider({
5660
5865
  },
5661
5866
  tabIndex: 0,
5662
5867
  children: [
5663
- /* @__PURE__ */ jsx7(
5868
+ /* @__PURE__ */ jsx8(
5664
5869
  "div",
5665
5870
  {
5666
5871
  style: {
@@ -5675,7 +5880,7 @@ function VerticalVolumeSlider({
5675
5880
  }
5676
5881
  }
5677
5882
  ),
5678
- /* @__PURE__ */ jsx7(
5883
+ /* @__PURE__ */ jsx8(
5679
5884
  "div",
5680
5885
  {
5681
5886
  style: {
@@ -5710,14 +5915,14 @@ function VolumeControl({
5710
5915
  volume,
5711
5916
  volumeAdjustable
5712
5917
  }) {
5713
- const rootRef = useRef10(null);
5918
+ const rootRef = useRef11(null);
5714
5919
  const [open, setOpen] = useState4(false);
5715
5920
  const displayVolume = muted ? 0 : volume;
5716
5921
  const mutedOrSilent = muted || volume === 0;
5717
- useEffect11(() => {
5922
+ useEffect12(() => {
5718
5923
  onOpenChange(open);
5719
5924
  }, [onOpenChange, open]);
5720
- useEffect11(() => {
5925
+ useEffect12(() => {
5721
5926
  if (!open || !volumeAdjustable || hasFinePointerHover()) {
5722
5927
  return;
5723
5928
  }
@@ -5734,13 +5939,13 @@ function VolumeControl({
5734
5939
  };
5735
5940
  }, [open, volumeAdjustable]);
5736
5941
  if (!volumeAdjustable) {
5737
- return /* @__PURE__ */ jsx7(
5942
+ return /* @__PURE__ */ jsx8(
5738
5943
  ChromeButton,
5739
5944
  {
5740
5945
  appearance,
5741
5946
  label: mutedOrSilent ? "Unmute" : "Mute",
5742
5947
  onClick: onToggleMuted,
5743
- children: mutedOrSilent ? /* @__PURE__ */ jsx7(Icon, { path: "M3 6.5h2.2L8.5 4v8L5.2 9.5H3zM10.2 6.2l3.2 3.6M13.4 6.2l-3.2 3.6" }) : /* @__PURE__ */ jsx7(Icon, { path: "M3 6.5h2.2L8.5 4v8L5.2 9.5H3zM10.5 5.5a3 3 0 0 1 0 5" })
5948
+ children: mutedOrSilent ? /* @__PURE__ */ jsx8(Icon, { path: "M3 6.5h2.2L8.5 4v8L5.2 9.5H3zM10.2 6.2l3.2 3.6M13.4 6.2l-3.2 3.6" }) : /* @__PURE__ */ jsx8(Icon, { path: "M3 6.5h2.2L8.5 4v8L5.2 9.5H3zM10.5 5.5a3 3 0 0 1 0 5" })
5744
5949
  }
5745
5950
  );
5746
5951
  }
@@ -5772,7 +5977,7 @@ function VolumeControl({
5772
5977
  },
5773
5978
  ref: rootRef,
5774
5979
  children: [
5775
- open ? /* @__PURE__ */ jsx7(
5980
+ open ? /* @__PURE__ */ jsx8(
5776
5981
  VerticalVolumeSlider,
5777
5982
  {
5778
5983
  appearance,
@@ -5780,7 +5985,7 @@ function VolumeControl({
5780
5985
  volume: displayVolume
5781
5986
  }
5782
5987
  ) : null,
5783
- /* @__PURE__ */ jsx7(
5988
+ /* @__PURE__ */ jsx8(
5784
5989
  ChromeButton,
5785
5990
  {
5786
5991
  appearance,
@@ -5791,7 +5996,7 @@ function VolumeControl({
5791
5996
  }
5792
5997
  onToggleMuted();
5793
5998
  },
5794
- children: mutedOrSilent ? /* @__PURE__ */ jsx7(Icon, { path: "M3 6.5h2.2L8.5 4v8L5.2 9.5H3zM10.2 6.2l3.2 3.6M13.4 6.2l-3.2 3.6" }) : /* @__PURE__ */ jsx7(Icon, { path: "M3 6.5h2.2L8.5 4v8L5.2 9.5H3zM10.5 5.5a3 3 0 0 1 0 5" })
5999
+ children: mutedOrSilent ? /* @__PURE__ */ jsx8(Icon, { path: "M3 6.5h2.2L8.5 4v8L5.2 9.5H3zM10.2 6.2l3.2 3.6M13.4 6.2l-3.2 3.6" }) : /* @__PURE__ */ jsx8(Icon, { path: "M3 6.5h2.2L8.5 4v8L5.2 9.5H3zM10.5 5.5a3 3 0 0 1 0 5" })
5795
6000
  }
5796
6001
  )
5797
6002
  ]
@@ -5820,7 +6025,7 @@ function PanoVideoControlsHud({
5820
6025
  const [overlayWidth, setOverlayWidth] = useState4(
5821
6026
  () => overlayElement.clientWidth
5822
6027
  );
5823
- const idleTimerRef = useRef10(0);
6028
+ const idleTimerRef = useRef11(0);
5824
6029
  const barId = useId2();
5825
6030
  const rateMenuId = `${barId}-rate`;
5826
6031
  const variantMenuId = `${barId}-variant`;
@@ -5842,7 +6047,7 @@ function PanoVideoControlsHud({
5842
6047
  },
5843
6048
  [menu, volumeOpen]
5844
6049
  );
5845
- useEffect11(() => {
6050
+ useEffect12(() => {
5846
6051
  if (typeof ResizeObserver === "undefined") {
5847
6052
  return;
5848
6053
  }
@@ -5857,15 +6062,15 @@ function PanoVideoControlsHud({
5857
6062
  observer.disconnect();
5858
6063
  };
5859
6064
  }, [overlayElement]);
5860
- useEffect11(() => {
6065
+ useEffect12(() => {
5861
6066
  if (!compact && menu === "more") {
5862
6067
  setMenu(null);
5863
6068
  }
5864
6069
  }, [compact, menu]);
5865
- useEffect11(() => {
6070
+ useEffect12(() => {
5866
6071
  bumpVisibility(snapshot.playing);
5867
6072
  }, [bumpVisibility, snapshot.playing]);
5868
- useEffect11(() => {
6073
+ useEffect12(() => {
5869
6074
  const root = overlayElement.parentElement;
5870
6075
  if (!root) {
5871
6076
  return;
@@ -5924,7 +6129,7 @@ function PanoVideoControlsHud({
5924
6129
  document.removeEventListener("pointerdown", handlePointerDown, true);
5925
6130
  };
5926
6131
  }, [bumpVisibility, controller, menu, overlayElement, snapshot.playing, volumeOpen]);
5927
- useEffect11(
6132
+ useEffect12(
5928
6133
  () => () => {
5929
6134
  window.clearTimeout(idleTimerRef.current);
5930
6135
  },
@@ -5951,7 +6156,7 @@ function PanoVideoControlsHud({
5951
6156
  let menuNode = null;
5952
6157
  switch (menu) {
5953
6158
  case "rate":
5954
- menuNode = /* @__PURE__ */ jsx7(
6159
+ menuNode = /* @__PURE__ */ jsx8(
5955
6160
  ChromeMenu,
5956
6161
  {
5957
6162
  appearance: resolved,
@@ -5970,7 +6175,7 @@ function PanoVideoControlsHud({
5970
6175
  );
5971
6176
  break;
5972
6177
  case "variant":
5973
- menuNode = /* @__PURE__ */ jsx7(
6178
+ menuNode = /* @__PURE__ */ jsx8(
5974
6179
  ChromeMenu,
5975
6180
  {
5976
6181
  appearance: resolved,
@@ -5989,7 +6194,7 @@ function PanoVideoControlsHud({
5989
6194
  );
5990
6195
  break;
5991
6196
  case "captions":
5992
- menuNode = /* @__PURE__ */ jsx7(
6197
+ menuNode = /* @__PURE__ */ jsx8(
5993
6198
  CaptionsMenu,
5994
6199
  {
5995
6200
  appearance: resolved,
@@ -6013,7 +6218,7 @@ function PanoVideoControlsHud({
6013
6218
  );
6014
6219
  break;
6015
6220
  case "more":
6016
- menuNode = /* @__PURE__ */ jsx7(
6221
+ menuNode = /* @__PURE__ */ jsx8(
6017
6222
  ChromeMenu,
6018
6223
  {
6019
6224
  appearance: resolved,
@@ -6081,7 +6286,7 @@ function PanoVideoControlsHud({
6081
6286
  };
6082
6287
  const rateButton = /* @__PURE__ */ jsxs3("div", { className: "pano-video-menu", "data-pano-video-menu": "rate", children: [
6083
6288
  !compact && menu === "rate" ? menuNode : null,
6084
- /* @__PURE__ */ jsx7(
6289
+ /* @__PURE__ */ jsx8(
6085
6290
  ChromeButton,
6086
6291
  {
6087
6292
  appearance: resolved,
@@ -6089,13 +6294,13 @@ function PanoVideoControlsHud({
6089
6294
  onClick: () => {
6090
6295
  toggleMenu("rate");
6091
6296
  },
6092
- children: /* @__PURE__ */ jsx7("span", { className: "pano-video-chrome-label", id: `${barId}-rate-btn`, children: snapshot.playbackRate === 1 ? "1x" : `${snapshot.playbackRate}x` })
6297
+ children: /* @__PURE__ */ jsx8("span", { className: "pano-video-chrome-label", id: `${barId}-rate-btn`, children: snapshot.playbackRate === 1 ? "1x" : `${snapshot.playbackRate}x` })
6093
6298
  }
6094
6299
  )
6095
6300
  ] });
6096
6301
  const variantButton = canSwitchVariant ? /* @__PURE__ */ jsxs3("div", { className: "pano-video-menu", "data-pano-video-menu": "variant", children: [
6097
6302
  !compact && menu === "variant" ? menuNode : null,
6098
- /* @__PURE__ */ jsx7(
6303
+ /* @__PURE__ */ jsx8(
6099
6304
  ChromeButton,
6100
6305
  {
6101
6306
  appearance: resolved,
@@ -6103,13 +6308,13 @@ function PanoVideoControlsHud({
6103
6308
  onClick: () => {
6104
6309
  toggleMenu("variant");
6105
6310
  },
6106
- children: /* @__PURE__ */ jsx7("span", { className: "pano-video-chrome-label", id: `${barId}-variant-btn`, children: snapshot.variants.find((variant) => variant.id === snapshot.variantId)?.label ?? "Quality" })
6311
+ children: /* @__PURE__ */ jsx8("span", { className: "pano-video-chrome-label", id: `${barId}-variant-btn`, children: snapshot.variants.find((variant) => variant.id === snapshot.variantId)?.label ?? "Quality" })
6107
6312
  }
6108
6313
  )
6109
6314
  ] }) : null;
6110
6315
  const captionsButton = showCaptionsMenu ? /* @__PURE__ */ jsxs3("div", { className: "pano-video-menu", "data-pano-video-menu": "captions", children: [
6111
6316
  !compact && menu === "captions" ? menuNode : null,
6112
- /* @__PURE__ */ jsx7(
6317
+ /* @__PURE__ */ jsx8(
6113
6318
  ChromeButton,
6114
6319
  {
6115
6320
  appearance: resolved,
@@ -6117,7 +6322,7 @@ function PanoVideoControlsHud({
6117
6322
  onClick: () => {
6118
6323
  toggleMenu("captions");
6119
6324
  },
6120
- children: /* @__PURE__ */ jsx7("span", { id: `${barId}-captions-btn`, children: /* @__PURE__ */ jsx7(Icon, { path: "M2.5 4.5h11v7h-11zM5 7.2h2.4M5 9.2h5.5" }) })
6325
+ children: /* @__PURE__ */ jsx8("span", { id: `${barId}-captions-btn`, children: /* @__PURE__ */ jsx8(Icon, { path: "M2.5 4.5h11v7h-11zM5 7.2h2.4M5 9.2h5.5" }) })
6121
6326
  }
6122
6327
  )
6123
6328
  ] }) : null;
@@ -6128,7 +6333,7 @@ function PanoVideoControlsHud({
6128
6333
  "data-pano-video-controls": "",
6129
6334
  style: barStyle,
6130
6335
  children: [
6131
- /* @__PURE__ */ jsx7(
6336
+ /* @__PURE__ */ jsx8(
6132
6337
  ChromeButton,
6133
6338
  {
6134
6339
  appearance: resolved,
@@ -6136,11 +6341,11 @@ function PanoVideoControlsHud({
6136
6341
  onClick: () => {
6137
6342
  controller.togglePlay();
6138
6343
  },
6139
- children: snapshot.playing ? /* @__PURE__ */ jsx7(Icon, { path: "M5 3.5h2.2v9H5zM8.8 3.5H11v9H8.8z" }) : /* @__PURE__ */ jsx7(Icon, { path: "M5 3.2v9.6L13 8z" })
6344
+ children: snapshot.playing ? /* @__PURE__ */ jsx8(Icon, { path: "M5 3.5h2.2v9H5zM8.8 3.5H11v9H8.8z" }) : /* @__PURE__ */ jsx8(Icon, { path: "M5 3.2v9.6L13 8z" })
6140
6345
  }
6141
6346
  ),
6142
- hideTime ? null : /* @__PURE__ */ jsx7("span", { className: "pano-video-time", children: formatMediaTime(snapshot.currentTime) }),
6143
- /* @__PURE__ */ jsx7(
6347
+ hideTime ? null : /* @__PURE__ */ jsx8("span", { className: "pano-video-time", children: formatMediaTime(snapshot.currentTime) }),
6348
+ /* @__PURE__ */ jsx8(
6144
6349
  "input",
6145
6350
  {
6146
6351
  "aria-label": "Seek",
@@ -6162,8 +6367,8 @@ function PanoVideoControlsHud({
6162
6367
  value: duration > 0 ? snapshot.currentTime : 0
6163
6368
  }
6164
6369
  ),
6165
- hideTime ? null : /* @__PURE__ */ jsx7("span", { className: "pano-video-time", children: formatMediaTime(duration) }),
6166
- /* @__PURE__ */ jsx7(
6370
+ hideTime ? null : /* @__PURE__ */ jsx8("span", { className: "pano-video-time", children: formatMediaTime(duration) }),
6371
+ /* @__PURE__ */ jsx8(
6167
6372
  VolumeControl,
6168
6373
  {
6169
6374
  appearance: resolved,
@@ -6181,7 +6386,7 @@ function PanoVideoControlsHud({
6181
6386
  ),
6182
6387
  compact ? /* @__PURE__ */ jsxs3("div", { className: "pano-video-menu", "data-pano-video-menu": "more", children: [
6183
6388
  menu !== null ? menuNode : null,
6184
- /* @__PURE__ */ jsx7(
6389
+ /* @__PURE__ */ jsx8(
6185
6390
  ChromeButton,
6186
6391
  {
6187
6392
  appearance: resolved,
@@ -6190,7 +6395,7 @@ function PanoVideoControlsHud({
6190
6395
  onClick: () => {
6191
6396
  toggleMenu("more");
6192
6397
  },
6193
- children: /* @__PURE__ */ jsx7(Icon, { path: "M3 8a1 1 0 1 0 2 0 1 1 0 1 0-2 0M7 8a1 1 0 1 0 2 0 1 1 0 1 0-2 0M11 8a1 1 0 1 0 2 0 1 1 0 1 0-2 0" })
6398
+ children: /* @__PURE__ */ jsx8(Icon, { path: "M3 8a1 1 0 1 0 2 0 1 1 0 1 0-2 0M7 8a1 1 0 1 0 2 0 1 1 0 1 0-2 0M11 8a1 1 0 1 0 2 0 1 1 0 1 0-2 0" })
6194
6399
  }
6195
6400
  )
6196
6401
  ] }) : /* @__PURE__ */ jsxs3(Fragment, { children: [
@@ -6198,7 +6403,7 @@ function PanoVideoControlsHud({
6198
6403
  variantButton,
6199
6404
  captionsButton
6200
6405
  ] }),
6201
- showFullscreen ? /* @__PURE__ */ jsx7(
6406
+ showFullscreen ? /* @__PURE__ */ jsx8(
6202
6407
  ChromeButton,
6203
6408
  {
6204
6409
  appearance: resolved,
@@ -6206,7 +6411,7 @@ function PanoVideoControlsHud({
6206
6411
  onClick: () => {
6207
6412
  fullscreen?.toggleFullscreen();
6208
6413
  },
6209
- children: fullscreen?.isFullscreen ? /* @__PURE__ */ jsx7(Icon, { path: "M6 3.5H3.5V6M10 3.5h2.5V6M6 12.5H3.5V10M10 12.5h2.5V10" }) : /* @__PURE__ */ jsx7(Icon, { path: "M3.5 6V3.5H6M10 3.5h2.5V6M3.5 10v2.5H6M10 12.5h2.5V10" })
6414
+ children: fullscreen?.isFullscreen ? /* @__PURE__ */ jsx8(Icon, { path: "M6 3.5H3.5V6M10 3.5h2.5V6M6 12.5H3.5V10M10 12.5h2.5V10" }) : /* @__PURE__ */ jsx8(Icon, { path: "M3.5 6V3.5H6M10 3.5h2.5V6M3.5 10v2.5H6M10 12.5h2.5V10" })
6210
6415
  }
6211
6416
  ) : null
6212
6417
  ]
@@ -6215,7 +6420,7 @@ function PanoVideoControlsHud({
6215
6420
  }
6216
6421
  function PanoVideoControls({ appearance }) {
6217
6422
  useClaimPanoVideoControls();
6218
- const host = useContext13(PanoVideoHostContext);
6423
+ const host = useContext14(PanoVideoHostContext);
6219
6424
  if (host && appearance) {
6220
6425
  host.controls = appearance;
6221
6426
  }
@@ -6223,7 +6428,7 @@ function PanoVideoControls({ appearance }) {
6223
6428
  }
6224
6429
 
6225
6430
  // src/video/pano-video-chrome-bridge.tsx
6226
- import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
6431
+ import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
6227
6432
  function PanoVideoChromeBridge({
6228
6433
  fullscreen,
6229
6434
  host,
@@ -6239,7 +6444,7 @@ function PanoVideoChromeBridge({
6239
6444
  }
6240
6445
  const showDefaultControls = host.controller !== null && host.controls !== false && host.controlClaims === 0;
6241
6446
  return /* @__PURE__ */ jsxs4(Fragment2, { children: [
6242
- showDefaultControls ? /* @__PURE__ */ jsx8(
6447
+ showDefaultControls ? /* @__PURE__ */ jsx9(
6243
6448
  PanoVideoControlsHud,
6244
6449
  {
6245
6450
  appearance: typeof host.controls === "object" ? host.controls : void 0,
@@ -6248,7 +6453,7 @@ function PanoVideoChromeBridge({
6248
6453
  overlayElement
6249
6454
  }
6250
6455
  ) : null,
6251
- host.captions !== false && host.controller ? /* @__PURE__ */ jsx8(PanoVideoCaptionsOverlay, { controller: host.controller }) : null
6456
+ host.captions !== false && host.controller ? /* @__PURE__ */ jsx9(PanoVideoCaptionsOverlay, { controller: host.controller }) : null
6252
6457
  ] });
6253
6458
  }
6254
6459
 
@@ -6256,8 +6461,8 @@ function PanoVideoChromeBridge({
6256
6461
  import { useSyncExternalStore as useSyncExternalStore5 } from "react";
6257
6462
 
6258
6463
  // src/webvr/host.ts
6259
- import { createContext as createContext12 } from "react";
6260
- var WebVRRuntimeContext = createContext12(null);
6464
+ import { createContext as createContext13 } from "react";
6465
+ var WebVRRuntimeContext = createContext13(null);
6261
6466
  function createWebVRHost() {
6262
6467
  return {
6263
6468
  controller: null,
@@ -6401,7 +6606,7 @@ function clamp2(value, min, max) {
6401
6606
  }
6402
6607
 
6403
6608
  // src/webvr/chrome.tsx
6404
- import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
6609
+ import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
6405
6610
  function resolveAppearance(value) {
6406
6611
  return {
6407
6612
  ...DEFAULT_WEBVR_CHROME_APPEARANCE,
@@ -6413,7 +6618,7 @@ function ChromeButton2({
6413
6618
  children,
6414
6619
  onClick
6415
6620
  }) {
6416
- return /* @__PURE__ */ jsx9(
6621
+ return /* @__PURE__ */ jsx10(
6417
6622
  "button",
6418
6623
  {
6419
6624
  className: "pano-webvr-button",
@@ -6458,11 +6663,11 @@ function SetupPanel({
6458
6663
  role: "dialog",
6459
6664
  style: panelStyle,
6460
6665
  children: [
6461
- /* @__PURE__ */ jsx9("h2", { className: "pano-webvr-setup-title", children: appearance.setupTitle ?? "MobileVR Setup" }),
6666
+ /* @__PURE__ */ jsx10("h2", { className: "pano-webvr-setup-title", children: appearance.setupTitle ?? "MobileVR Setup" }),
6462
6667
  /* @__PURE__ */ jsxs5("label", { className: "pano-webvr-setup-field", children: [
6463
6668
  "Screen size (inch)",
6464
6669
  /* @__PURE__ */ jsxs5("div", { className: "pano-webvr-setup-row", children: [
6465
- /* @__PURE__ */ jsx9(
6670
+ /* @__PURE__ */ jsx10(
6466
6671
  "button",
6467
6672
  {
6468
6673
  "aria-label": "Decrease screen size",
@@ -6474,8 +6679,8 @@ function SetupPanel({
6474
6679
  children: "\u2039"
6475
6680
  }
6476
6681
  ),
6477
- /* @__PURE__ */ jsx9("strong", { className: "pano-webvr-setup-value", children: settings.screensize === "auto" ? "Auto" : settings.screensize.toFixed(1) }),
6478
- /* @__PURE__ */ jsx9(
6682
+ /* @__PURE__ */ jsx10("strong", { className: "pano-webvr-setup-value", children: settings.screensize === "auto" ? "Auto" : settings.screensize.toFixed(1) }),
6683
+ /* @__PURE__ */ jsx10(
6479
6684
  "button",
6480
6685
  {
6481
6686
  "aria-label": "Increase screen size",
@@ -6490,9 +6695,9 @@ function SetupPanel({
6490
6695
  ] })
6491
6696
  ] }),
6492
6697
  /* @__PURE__ */ jsxs5("fieldset", { className: "pano-webvr-setup-fieldset", children: [
6493
- /* @__PURE__ */ jsx9("legend", { className: "pano-webvr-setup-legend", children: "VR headset preset" }),
6698
+ /* @__PURE__ */ jsx10("legend", { className: "pano-webvr-setup-legend", children: "VR headset preset" }),
6494
6699
  /* @__PURE__ */ jsxs5("div", { className: "pano-webvr-setup-row", children: [
6495
- /* @__PURE__ */ jsx9(
6700
+ /* @__PURE__ */ jsx10(
6496
6701
  "button",
6497
6702
  {
6498
6703
  "aria-label": "Previous headset preset",
@@ -6502,8 +6707,8 @@ function SetupPanel({
6502
6707
  children: "\u2039"
6503
6708
  }
6504
6709
  ),
6505
- /* @__PURE__ */ jsx9("strong", { className: "pano-webvr-setup-value-wide", children: WEBVR_PROFILES[settings.profileId].label }),
6506
- /* @__PURE__ */ jsx9(
6710
+ /* @__PURE__ */ jsx10("strong", { className: "pano-webvr-setup-value-wide", children: WEBVR_PROFILES[settings.profileId].label }),
6711
+ /* @__PURE__ */ jsx10(
6507
6712
  "button",
6508
6713
  {
6509
6714
  "aria-label": "Next headset preset",
@@ -6515,7 +6720,7 @@ function SetupPanel({
6515
6720
  )
6516
6721
  ] })
6517
6722
  ] }),
6518
- /* @__PURE__ */ jsx9(
6723
+ /* @__PURE__ */ jsx10(
6519
6724
  ChromeButton2,
6520
6725
  {
6521
6726
  appearance,
@@ -6539,8 +6744,8 @@ function WebVRChromeBridge({ host }) {
6539
6744
  }
6540
6745
  const appearance = resolveAppearance(chrome);
6541
6746
  return /* @__PURE__ */ jsxs5(Fragment3, { children: [
6542
- /* @__PURE__ */ jsx9("div", { className: "pano-webvr-toolbar", children: mode ? /* @__PURE__ */ jsxs5("div", { className: "pano-webvr-toolbar-actions", children: [
6543
- mode !== "webxr" ? /* @__PURE__ */ jsx9(
6747
+ /* @__PURE__ */ jsx10("div", { className: "pano-webvr-toolbar", children: mode ? /* @__PURE__ */ jsxs5("div", { className: "pano-webvr-toolbar-actions", children: [
6748
+ mode !== "webxr" ? /* @__PURE__ */ jsx10(
6544
6749
  ChromeButton2,
6545
6750
  {
6546
6751
  appearance,
@@ -6548,7 +6753,7 @@ function WebVRChromeBridge({ host }) {
6548
6753
  children: "VR Setup"
6549
6754
  }
6550
6755
  ) : null,
6551
- /* @__PURE__ */ jsx9(
6756
+ /* @__PURE__ */ jsx10(
6552
6757
  ChromeButton2,
6553
6758
  {
6554
6759
  appearance,
@@ -6556,7 +6761,7 @@ function WebVRChromeBridge({ host }) {
6556
6761
  children: "Exit VR"
6557
6762
  }
6558
6763
  )
6559
- ] }) : /* @__PURE__ */ jsx9(
6764
+ ] }) : /* @__PURE__ */ jsx10(
6560
6765
  ChromeButton2,
6561
6766
  {
6562
6767
  appearance,
@@ -6564,7 +6769,7 @@ function WebVRChromeBridge({ host }) {
6564
6769
  children: available ? "Enter VR" : "VR unavailable"
6565
6770
  }
6566
6771
  ) }),
6567
- mode === "fake" ? /* @__PURE__ */ jsx9(
6772
+ mode === "fake" ? /* @__PURE__ */ jsx10(
6568
6773
  "p",
6569
6774
  {
6570
6775
  className: "pano-webvr-hint",
@@ -6572,7 +6777,7 @@ function WebVRChromeBridge({ host }) {
6572
6777
  children: "Simulated VR Mode \xB7 Click the view to lock the mouse, then move to look around. Use a headset or phone for real VR."
6573
6778
  }
6574
6779
  ) : null,
6575
- setupOpen ? /* @__PURE__ */ jsx9(
6780
+ setupOpen ? /* @__PURE__ */ jsx10(
6576
6781
  SetupPanel,
6577
6782
  {
6578
6783
  appearance,
@@ -6612,12 +6817,12 @@ function projectStereoHtmlPosition(el, camera, size, eye) {
6612
6817
  // src/webvr/xr-origin.tsx
6613
6818
  import { useFrame as useFrame5, useThree as useThree8 } from "@react-three/fiber";
6614
6819
  import { useXR as useXR2, XROrigin } from "@react-three/xr";
6615
- import { useRef as useRef11 } from "react";
6820
+ import { useRef as useRef12 } from "react";
6616
6821
  import { Vector3 as Vector34 } from "three";
6617
- import { jsx as jsx10 } from "react/jsx-runtime";
6822
+ import { jsx as jsx11 } from "react/jsx-runtime";
6618
6823
  function PanoramaXROrigin() {
6619
- const originRef = useRef11(null);
6620
- const localHeadPositionRef = useRef11(new Vector34());
6824
+ const originRef = useRef12(null);
6825
+ const localHeadPositionRef = useRef12(new Vector34());
6621
6826
  const session2 = useXR2((state) => state.session);
6622
6827
  const gl = useThree8((state) => state.gl);
6623
6828
  useFrame5(() => {
@@ -6630,11 +6835,11 @@ function PanoramaXROrigin() {
6630
6835
  origin.position.copy(localHeadPositionRef.current).multiplyScalar(-1);
6631
6836
  origin.updateMatrixWorld();
6632
6837
  }, -100);
6633
- return /* @__PURE__ */ jsx10(XROrigin, { ref: originRef });
6838
+ return /* @__PURE__ */ jsx11(XROrigin, { ref: originRef });
6634
6839
  }
6635
6840
 
6636
6841
  // src/pano-viewer.tsx
6637
- import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
6842
+ import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
6638
6843
  var DEFAULT_VIEW = {
6639
6844
  yaw: 0,
6640
6845
  pitch: 0,
@@ -6679,10 +6884,10 @@ function PanoCursorTree({
6679
6884
  if (!cursors) {
6680
6885
  return children;
6681
6886
  }
6682
- return /* @__PURE__ */ jsx11(PanoCursorController, { cursors, children });
6887
+ return /* @__PURE__ */ jsx12(PanoCursorController, { cursors, children });
6683
6888
  }
6684
6889
  function PanoVideoHostReset() {
6685
- const host = useContext14(PanoVideoHostContext);
6890
+ const host = useContext15(PanoVideoHostContext);
6686
6891
  if (host) {
6687
6892
  host.controlClaims = 0;
6688
6893
  }
@@ -6695,14 +6900,14 @@ function DefaultControlChannels({
6695
6900
  keyboardChannel,
6696
6901
  fovSpeed
6697
6902
  }) {
6698
- const claims = useContext14(ControlClaimsContext);
6903
+ const claims = useContext15(ControlClaimsContext);
6699
6904
  if (!claims) {
6700
6905
  return null;
6701
6906
  }
6702
6907
  return /* @__PURE__ */ jsxs6(DefaultControlChannelContext.Provider, { value: true, children: [
6703
- userControlsEnabled && mouseChannel.mount && claims.mouse === 0 ? /* @__PURE__ */ jsx11(MouseControls, { ...mouseChannel.props, fovSpeed }) : null,
6704
- userControlsEnabled && touchChannel.mount && claims.touch === 0 ? /* @__PURE__ */ jsx11(TouchControls, { ...touchChannel.props }) : null,
6705
- userControlsEnabled && keyboardChannel.mount && claims.keyboard === 0 ? /* @__PURE__ */ jsx11(
6908
+ userControlsEnabled && mouseChannel.mount && claims.mouse === 0 ? /* @__PURE__ */ jsx12(MouseControls, { ...mouseChannel.props, fovSpeed }) : null,
6909
+ userControlsEnabled && touchChannel.mount && claims.touch === 0 ? /* @__PURE__ */ jsx12(TouchControls, { ...touchChannel.props }) : null,
6910
+ userControlsEnabled && keyboardChannel.mount && claims.keyboard === 0 ? /* @__PURE__ */ jsx12(
6706
6911
  KeyboardControls,
6707
6912
  {
6708
6913
  ...keyboardChannel.props,
@@ -6720,6 +6925,7 @@ var PanoViewer = forwardRef2(
6720
6925
  controls = true,
6721
6926
  cursors,
6722
6927
  contextMenu = true,
6928
+ mediaActivation,
6723
6929
  onViewChange,
6724
6930
  onPanoramaClick,
6725
6931
  onPanoramaDoubleClick,
@@ -6729,8 +6935,8 @@ var PanoViewer = forwardRef2(
6729
6935
  "aria-label": ariaLabel = "Panorama viewer",
6730
6936
  ...divProps
6731
6937
  }, ref) {
6732
- const rootRef = useRef12(null);
6733
- const controlsRef = useRef12(null);
6938
+ const rootRef = useRef13(null);
6939
+ const controlsRef = useRef13(null);
6734
6940
  const eventBus = useMemo7(() => createPanoEventBus(), []);
6735
6941
  const { controls: hotspotAccessibilityControls, registry } = useHotspotAccessibilityLayer();
6736
6942
  const { api: contextMenuOverlayApi, overlay: contextMenuOverlay } = usePanoContextMenuOverlay();
@@ -6740,6 +6946,17 @@ var PanoViewer = forwardRef2(
6740
6946
  const webVRHost = useMemo7(() => createWebVRHost(), []);
6741
6947
  const scenesHost = useMemo7(() => createScenesHost(), []);
6742
6948
  const bgmHost = useMemo7(() => createBackgroundAudioHost(), []);
6949
+ const mediaActivationHost = useMemo7(() => createPanoMediaActivationHost(), []);
6950
+ const mediaActivationOptions = useMemo7(
6951
+ () => mediaActivation === false ? null : mediaActivation ?? {},
6952
+ [mediaActivation]
6953
+ );
6954
+ const mediaActivationRevision = useSyncExternalStore6(
6955
+ (onStoreChange) => subscribePanoMediaActivation(mediaActivationHost, onStoreChange),
6956
+ () => getPanoMediaActivationRevision(mediaActivationHost),
6957
+ () => getPanoMediaActivationRevision(mediaActivationHost)
6958
+ );
6959
+ const [mediaActivated, setMediaActivated] = useState5(false);
6743
6960
  const stereoView = useMemo7(() => createWebVRStereoView(), []);
6744
6961
  const xrStore = useMemo7(
6745
6962
  () => createXRStore({
@@ -6757,7 +6974,33 @@ var PanoViewer = forwardRef2(
6757
6974
  }),
6758
6975
  []
6759
6976
  );
6760
- const fallbackViewRef = useRef12(DEFAULT_VIEW);
6977
+ const mediaActivationControls = useMemo7(
6978
+ () => ({
6979
+ resumeAudio: () => resumePanoAudio(),
6980
+ playVideo: async ({ unmute = false } = {}) => {
6981
+ const controller = videoHost.controller;
6982
+ if (!controller) {
6983
+ return false;
6984
+ }
6985
+ if (unmute) {
6986
+ controller.setMuted(false);
6987
+ }
6988
+ await controller.play();
6989
+ return !controller.getSnapshot().blocked;
6990
+ },
6991
+ playBackgroundAudio: () => bgmHost.controller?.play() ?? false
6992
+ }),
6993
+ [bgmHost, videoHost]
6994
+ );
6995
+ const activateMedia = useCallback6(() => {
6996
+ setMediaActivated(true);
6997
+ const resume = mediaActivationControls.resumeAudio();
6998
+ mediaActivationOptions?.onActivate?.(mediaActivationControls);
6999
+ return resume;
7000
+ }, [mediaActivationControls, mediaActivationOptions]);
7001
+ const hasMediaActivationIntent = mediaActivationRevision >= 0 && hasPanoMediaActivationIntent(mediaActivationHost);
7002
+ const shouldShowMediaActivation = mediaActivationOptions !== null && hasMediaActivationIntent && !mediaActivated;
7003
+ const fallbackViewRef = useRef13(DEFAULT_VIEW);
6761
7004
  const normalizedMinFov = Math.max(1, Math.min(minFov, maxFov - 1));
6762
7005
  const normalizedMaxFov = Math.min(
6763
7006
  179,
@@ -6860,7 +7103,7 @@ var PanoViewer = forwardRef2(
6860
7103
  await requestElementFullscreen(root);
6861
7104
  }, []);
6862
7105
  const [isViewerFullscreen, setIsViewerFullscreen] = useState5(false);
6863
- useEffect12(() => {
7106
+ useEffect13(() => {
6864
7107
  if (typeof document === "undefined") {
6865
7108
  return;
6866
7109
  }
@@ -6878,7 +7121,7 @@ var PanoViewer = forwardRef2(
6878
7121
  syncFullscreen();
6879
7122
  return subscribeFullscreenChange(syncFullscreen);
6880
7123
  }, []);
6881
- useEffect12(() => {
7124
+ useEffect13(() => {
6882
7125
  const root = rootRef.current;
6883
7126
  if (!root) {
6884
7127
  return;
@@ -6915,10 +7158,10 @@ var PanoViewer = forwardRef2(
6915
7158
  const [legacyAutoRotate, setLegacyAutoRotate] = useState5(
6916
7159
  legacyAutoRotateOptions.autoRotate ?? false
6917
7160
  );
6918
- useEffect12(() => {
7161
+ useEffect13(() => {
6919
7162
  setLegacyAutoRotate(legacyAutoRotateOptions.autoRotate ?? false);
6920
7163
  }, [legacyAutoRotateOptions.autoRotate]);
6921
- const isFullscreenRef = useRef12(false);
7164
+ const isFullscreenRef = useRef13(false);
6922
7165
  isFullscreenRef.current = isViewerFullscreen;
6923
7166
  useImperativeHandle2(
6924
7167
  ref,
@@ -6931,6 +7174,7 @@ var PanoViewer = forwardRef2(
6931
7174
  reset: () => {
6932
7175
  controlsRef.current?.reset();
6933
7176
  },
7177
+ activateMedia,
6934
7178
  // -- Fullscreen --
6935
7179
  enterFullscreen,
6936
7180
  exitFullscreen,
@@ -6953,7 +7197,7 @@ var PanoViewer = forwardRef2(
6953
7197
  requestVRPermission: () => webVRHost.controller?.requestPermission() ?? Promise.resolve(false),
6954
7198
  // -- Video --
6955
7199
  getVideo: () => videoHost.controller,
6956
- subscribeVideo: (onStoreChange) => subscribePanoVideoHost(videoHost, onStoreChange),
7200
+ subscribeVideo: (onStoreChange) => subscribePanoVideoStore(videoHost, onStoreChange),
6957
7201
  playVideo: () => videoHost.controller?.play() ?? Promise.resolve(),
6958
7202
  pauseVideo: () => videoHost.controller?.pause(),
6959
7203
  toggleVideo: () => videoHost.controller?.togglePlay(),
@@ -6963,7 +7207,7 @@ var PanoViewer = forwardRef2(
6963
7207
  toggleVideoMuted: () => videoHost.controller?.toggleMuted(),
6964
7208
  // -- Background Audio --
6965
7209
  getBackgroundAudio: () => bgmHost.controller,
6966
- subscribeBackgroundAudio: (onStoreChange) => subscribeBackgroundAudioHost(bgmHost, onStoreChange),
7210
+ subscribeBackgroundAudio: (onStoreChange) => subscribeBackgroundAudioStore(bgmHost, onStoreChange),
6967
7211
  playBackgroundAudio: () => {
6968
7212
  bgmHost.controller?.play();
6969
7213
  return Promise.resolve();
@@ -6983,6 +7227,7 @@ var PanoViewer = forwardRef2(
6983
7227
  }),
6984
7228
  [
6985
7229
  bgmHost,
7230
+ activateMedia,
6986
7231
  enterFullscreen,
6987
7232
  exitFullscreen,
6988
7233
  scenesHost,
@@ -7009,7 +7254,7 @@ var PanoViewer = forwardRef2(
7009
7254
  "aria-label": ariaLabel,
7010
7255
  style: rootStyle,
7011
7256
  children: [
7012
- /* @__PURE__ */ jsx11(
7257
+ /* @__PURE__ */ jsx12(
7013
7258
  Canvas,
7014
7259
  {
7015
7260
  "aria-label": `${ariaLabel} canvas`,
@@ -7031,23 +7276,23 @@ var PanoViewer = forwardRef2(
7031
7276
  ...DEFAULT_CANVAS_STYLE,
7032
7277
  touchAction: userControlsEnabled ? "none" : "auto"
7033
7278
  },
7034
- children: /* @__PURE__ */ jsx11(XR, { store: xrStore, children: /* @__PURE__ */ jsxs6(
7279
+ children: /* @__PURE__ */ jsx12(XR, { store: xrStore, children: /* @__PURE__ */ jsxs6(
7035
7280
  WebVRRuntimeContext.Provider,
7036
7281
  {
7037
7282
  value: { host: webVRHost, xrStore, stereoView },
7038
7283
  children: [
7039
- /* @__PURE__ */ jsx11(PanoramaXROrigin, {}),
7040
- /* @__PURE__ */ jsx11(HotspotAccessibilityContext.Provider, { value: registry, children: /* @__PURE__ */ jsx11(PanoEventBusContext.Provider, { value: eventBus, children: /* @__PURE__ */ jsx11(PanoCursorTree, { cursors: resolvedCursors, children: /* @__PURE__ */ jsx11(PanoramaViewContext.Provider, { value: controlsRef, children: /* @__PURE__ */ jsx11(
7284
+ /* @__PURE__ */ jsx12(PanoramaXROrigin, {}),
7285
+ /* @__PURE__ */ jsx12(HotspotAccessibilityContext.Provider, { value: registry, children: /* @__PURE__ */ jsx12(PanoEventBusContext.Provider, { value: eventBus, children: /* @__PURE__ */ jsx12(PanoCursorTree, { cursors: resolvedCursors, children: /* @__PURE__ */ jsx12(PanoramaViewContext.Provider, { value: controlsRef, children: /* @__PURE__ */ jsx12(
7041
7286
  PanoContextMenuOverlayContext.Provider,
7042
7287
  {
7043
7288
  value: contextMenuOverlayApi,
7044
- children: /* @__PURE__ */ jsx11(PanoChromeOverlayContext.Provider, { value: chromeOverlayApi, children: /* @__PURE__ */ jsx11(PanoVideoHostContext.Provider, { value: videoHost, children: /* @__PURE__ */ jsx11(PanoFilterHostContext.Provider, { value: filterHost, children: /* @__PURE__ */ jsx11(
7289
+ children: /* @__PURE__ */ jsx12(PanoChromeOverlayContext.Provider, { value: chromeOverlayApi, children: /* @__PURE__ */ jsx12(PanoVideoHostContext.Provider, { value: videoHost, children: /* @__PURE__ */ jsx12(PanoFilterHostContext.Provider, { value: filterHost, children: /* @__PURE__ */ jsx12(
7045
7290
  PanoContextMenuActionsContext.Provider,
7046
7291
  {
7047
7292
  value: contextMenuActions,
7048
- children: /* @__PURE__ */ jsx11(ScenesHostContext.Provider, { value: scenesHost, children: /* @__PURE__ */ jsxs6(BackgroundAudioHostContext.Provider, { value: bgmHost, children: [
7049
- /* @__PURE__ */ jsx11(PanoVideoHostReset, {}),
7050
- /* @__PURE__ */ jsx11(
7293
+ children: /* @__PURE__ */ jsx12(ScenesHostContext.Provider, { value: scenesHost, children: /* @__PURE__ */ jsx12(BackgroundAudioHostContext.Provider, { value: bgmHost, children: /* @__PURE__ */ jsxs6(PanoMediaActivationHostContext.Provider, { value: mediaActivationHost, children: [
7294
+ /* @__PURE__ */ jsx12(PanoVideoHostReset, {}),
7295
+ /* @__PURE__ */ jsx12(
7051
7296
  PanoramaViewRuntime,
7052
7297
  {
7053
7298
  ref: controlsRef,
@@ -7058,7 +7303,7 @@ var PanoViewer = forwardRef2(
7058
7303
  options: controlOptions
7059
7304
  }
7060
7305
  ),
7061
- (onViewChange || onPanoramaClick || onPanoramaDoubleClick || onPanoramaPointerMove) && /* @__PURE__ */ jsx11(
7306
+ (onViewChange || onPanoramaClick || onPanoramaDoubleClick || onPanoramaPointerMove) && /* @__PURE__ */ jsx12(
7062
7307
  PanoEvents,
7063
7308
  {
7064
7309
  onViewChange,
@@ -7067,18 +7312,18 @@ var PanoViewer = forwardRef2(
7067
7312
  onPointerMove: onPanoramaPointerMove
7068
7313
  }
7069
7314
  ),
7070
- /* @__PURE__ */ jsx11(
7315
+ /* @__PURE__ */ jsx12(
7071
7316
  AutoRotate,
7072
7317
  {
7073
7318
  enabled: legacyAutoRotate,
7074
7319
  speed: legacyAutoRotateOptions.autoRotateSpeed
7075
7320
  }
7076
7321
  ),
7077
- /* @__PURE__ */ jsx11(PanoramaEventSurface, {}),
7078
- contextMenuChannel.mount ? /* @__PURE__ */ jsx11(PanoContextMenu, { ...contextMenuChannel.props }) : null,
7322
+ /* @__PURE__ */ jsx12(PanoramaEventSurface, {}),
7323
+ contextMenuChannel.mount ? /* @__PURE__ */ jsx12(PanoContextMenu, { ...contextMenuChannel.props }) : null,
7079
7324
  /* @__PURE__ */ jsxs6(ControlClaimsContext.Provider, { value: controlClaims, children: [
7080
7325
  children,
7081
- /* @__PURE__ */ jsx11(
7326
+ /* @__PURE__ */ jsx12(
7082
7327
  DefaultControlChannels,
7083
7328
  {
7084
7329
  fovSpeed: controlOptions.fovSpeed,
@@ -7089,7 +7334,7 @@ var PanoViewer = forwardRef2(
7089
7334
  }
7090
7335
  )
7091
7336
  ] })
7092
- ] }) })
7337
+ ] }) }) })
7093
7338
  }
7094
7339
  ) }) }) })
7095
7340
  }
@@ -7106,7 +7351,7 @@ var PanoViewer = forwardRef2(
7106
7351
  "data-pano-chrome-overlay": "",
7107
7352
  ref: setOverlayNode,
7108
7353
  children: [
7109
- /* @__PURE__ */ jsx11(
7354
+ /* @__PURE__ */ jsx12(
7110
7355
  PanoVideoChromeBridge,
7111
7356
  {
7112
7357
  fullscreen: contextMenuActions,
@@ -7114,115 +7359,29 @@ var PanoViewer = forwardRef2(
7114
7359
  overlayElement
7115
7360
  }
7116
7361
  ),
7117
- /* @__PURE__ */ jsx11(WebVRChromeBridge, { host: webVRHost })
7362
+ /* @__PURE__ */ jsx12(WebVRChromeBridge, { host: webVRHost })
7118
7363
  ]
7119
7364
  }
7120
7365
  ),
7121
7366
  contextMenuOverlay,
7122
- hotspotAccessibilityControls
7123
- ]
7124
- }
7125
- );
7126
- }
7127
- );
7128
-
7129
- // src/background-audio.tsx
7130
- import { useContext as useContext15, useEffect as useEffect13, useMemo as useMemo8, useRef as useRef13, useState as useState6 } from "react";
7131
-
7132
- // src/audio/howl.ts
7133
- var import_howler = __toESM(require_howler());
7134
- import_howler.Howler.autoUnlock = true;
7135
- function sourceList(src) {
7136
- if (src == null) {
7137
- return [];
7138
- }
7139
- if (typeof src === "string") {
7140
- return src ? [src] : [];
7141
- }
7142
- return src.filter((item) => Boolean(item));
7143
- }
7144
- function createUnlockingHowl({
7145
- src,
7146
- loop,
7147
- crossOrigin,
7148
- isActive,
7149
- shouldRetryPlay,
7150
- onEnded,
7151
- onPlay,
7152
- onPause,
7153
- onLoadError,
7154
- onPlayError
7155
- }) {
7156
- let disposed = false;
7157
- let blockedNotified = false;
7158
- const unlockListeners = [];
7159
- const removeUnlockListeners = () => {
7160
- for (const { type, listener } of unlockListeners) {
7161
- window.removeEventListener(type, listener, true);
7162
- }
7163
- unlockListeners.length = 0;
7164
- };
7165
- const instance = new import_howler.Howl({
7166
- src: [...src],
7167
- html5: false,
7168
- preload: true,
7169
- loop,
7170
- xhr: crossOrigin === "use-credentials" ? { withCredentials: true } : void 0,
7171
- onend: () => {
7172
- if (disposed || !isActive() || instance.loop()) {
7173
- return;
7174
- }
7175
- onEnded?.();
7176
- },
7177
- onplay: () => {
7178
- if (!disposed && isActive()) {
7179
- onPlay?.();
7180
- }
7181
- },
7182
- onpause: () => {
7183
- if (!disposed && isActive()) {
7184
- onPause?.();
7185
- }
7186
- },
7187
- onloaderror: (_soundId, error) => {
7188
- if (!disposed && isActive()) {
7189
- onLoadError?.(error);
7190
- }
7191
- },
7192
- onplayerror: (_soundId, error) => {
7193
- if (disposed || !isActive()) {
7194
- return;
7195
- }
7196
- if (!blockedNotified) {
7197
- blockedNotified = true;
7198
- onPlayError?.(error);
7199
- }
7200
- const retry = () => {
7201
- removeUnlockListeners();
7202
- if (!disposed && isActive() && shouldRetryPlay()) {
7203
- void import_howler.Howler.ctx?.resume();
7204
- instance.play();
7205
- }
7206
- };
7207
- removeUnlockListeners();
7208
- unlockListeners.push({ type: "pointerdown", listener: retry });
7209
- unlockListeners.push({ type: "keydown", listener: retry });
7210
- window.addEventListener("pointerdown", retry, { capture: true });
7211
- window.addEventListener("keydown", retry, { capture: true });
7212
- }
7213
- });
7214
- return {
7215
- howl: instance,
7216
- dispose: () => {
7217
- if (disposed) {
7218
- return;
7219
- }
7220
- disposed = true;
7221
- removeUnlockListeners();
7222
- instance.unload();
7223
- }
7224
- };
7225
- }
7367
+ hotspotAccessibilityControls,
7368
+ shouldShowMediaActivation ? /* @__PURE__ */ jsx12(
7369
+ PanoMediaActivationOverlay,
7370
+ {
7371
+ ...mediaActivationOptions,
7372
+ onActivate: () => {
7373
+ void activateMedia();
7374
+ }
7375
+ }
7376
+ ) : null
7377
+ ]
7378
+ }
7379
+ );
7380
+ }
7381
+ );
7382
+
7383
+ // src/background-audio.tsx
7384
+ import { useContext as useContext16, useEffect as useEffect14, useMemo as useMemo8, useRef as useRef14, useState as useState6 } from "react";
7226
7385
 
7227
7386
  // src/hotspot/audio-spatial.ts
7228
7387
  import { MathUtils as MathUtils3, Vector3 as Vector35 } from "three";
@@ -7310,7 +7469,7 @@ function BackgroundAudio({
7310
7469
  onEnded,
7311
7470
  onError
7312
7471
  }) {
7313
- const controlsRef = useContext15(PanoramaViewContext);
7472
+ const controlsRef = useContext16(PanoramaViewContext);
7314
7473
  if (!controlsRef) {
7315
7474
  throw new Error("<BackgroundAudio> must be rendered inside <PanoViewer>.");
7316
7475
  }
@@ -7318,30 +7477,39 @@ function BackgroundAudio({
7318
7477
  const [internalPlaying, setInternalPlaying] = useState6(defaultPlaying);
7319
7478
  const playing = isControlled ? controlledPlaying : internalPlaying;
7320
7479
  const urls = resolveBackgroundAudioUrls(src, sources, sceneId);
7480
+ usePanoMediaActivationIntent(playing && urls.length > 0);
7321
7481
  const trackKey = urls.join("\0");
7322
- const currentRef = useRef13(null);
7323
- const outgoingRef = useRef13([]);
7324
- const fadingInRef = useRef13(false);
7325
- const isFirstTrackRef = useRef13(true);
7326
- const playingRef = useRef13(playing);
7327
- const loopRef = useRef13(loop);
7328
- const mutedRef = useRef13(muted);
7329
- const volumeRef = useRef13(volume);
7330
- const fadeMsRef = useRef13(resolveFadeMs(fadeMs));
7331
- const onPlaybackStateChangeRef = useRef13(onPlaybackStateChange);
7332
- const onPlaybackErrorRef = useRef13(onPlaybackError);
7333
- const onEndedRef = useRef13(onEnded);
7334
- const onErrorRef = useRef13(onError);
7482
+ const currentRef = useRef14(null);
7483
+ const outgoingRef = useRef14([]);
7484
+ const fadingInRef = useRef14(false);
7485
+ const isFirstTrackRef = useRef14(true);
7486
+ const playingRef = useRef14(playing);
7487
+ const loopRef = useRef14(loop);
7488
+ const mutedRef = useRef14(muted);
7489
+ const volumeRef = useRef14(volume);
7490
+ const mutedPropRef = useRef14(muted);
7491
+ const volumePropRef = useRef14(volume);
7492
+ const fadeMsRef = useRef14(resolveFadeMs(fadeMs));
7493
+ const onPlaybackStateChangeRef = useRef14(onPlaybackStateChange);
7494
+ const onPlaybackErrorRef = useRef14(onPlaybackError);
7495
+ const onEndedRef = useRef14(onEnded);
7496
+ const onErrorRef = useRef14(onError);
7335
7497
  playingRef.current = playing;
7336
7498
  loopRef.current = loop;
7337
- mutedRef.current = muted;
7338
- volumeRef.current = volume;
7339
7499
  fadeMsRef.current = resolveFadeMs(fadeMs);
7500
+ if (mutedPropRef.current !== muted) {
7501
+ mutedPropRef.current = muted;
7502
+ mutedRef.current = muted;
7503
+ }
7504
+ if (volumePropRef.current !== volume) {
7505
+ volumePropRef.current = volume;
7506
+ volumeRef.current = volume;
7507
+ }
7340
7508
  onPlaybackStateChangeRef.current = onPlaybackStateChange;
7341
7509
  onPlaybackErrorRef.current = onPlaybackError;
7342
7510
  onEndedRef.current = onEnded;
7343
7511
  onErrorRef.current = onError;
7344
- const snapshotRef = useRef13({
7512
+ const snapshotRef = useRef14({
7345
7513
  ready: false,
7346
7514
  playing: false,
7347
7515
  blocked: false,
@@ -7349,7 +7517,7 @@ function BackgroundAudio({
7349
7517
  muted,
7350
7518
  volume
7351
7519
  });
7352
- const snapshotListenersRef = useRef13(/* @__PURE__ */ new Set());
7520
+ const snapshotListenersRef = useRef14(/* @__PURE__ */ new Set());
7353
7521
  const notifySnapshot = (patch) => {
7354
7522
  const prev = snapshotRef.current;
7355
7523
  snapshotRef.current = { ...prev, ...patch };
@@ -7357,7 +7525,7 @@ function BackgroundAudio({
7357
7525
  listener();
7358
7526
  }
7359
7527
  };
7360
- const isControlledRef = useRef13(isControlled);
7528
+ const isControlledRef = useRef14(isControlled);
7361
7529
  isControlledRef.current = isControlled;
7362
7530
  const controller = useMemo8(
7363
7531
  () => ({
@@ -7370,9 +7538,11 @@ function BackgroundAudio({
7370
7538
  getSnapshot: () => snapshotRef.current,
7371
7539
  play: () => {
7372
7540
  if (isControlledRef.current) {
7373
- return;
7541
+ return false;
7374
7542
  }
7543
+ currentRef.current?.handle.howl.play();
7375
7544
  setInternalPlaying(true);
7545
+ return true;
7376
7546
  },
7377
7547
  pause: () => {
7378
7548
  if (isControlledRef.current) {
@@ -7390,20 +7560,17 @@ function BackgroundAudio({
7390
7560
  if (isControlledRef.current) {
7391
7561
  return;
7392
7562
  }
7393
- const howl = currentRef.current?.handle.howl;
7394
- if (howl) {
7395
- howl.volume(clampAudioVolume(vol));
7396
- }
7397
- notifySnapshot({ volume: clampAudioVolume(vol) });
7563
+ const next = clampAudioVolume(vol);
7564
+ volumeRef.current = next;
7565
+ currentRef.current?.handle.howl.volume(next);
7566
+ notifySnapshot({ volume: next });
7398
7567
  },
7399
7568
  setMuted: (m) => {
7400
7569
  if (isControlledRef.current) {
7401
7570
  return;
7402
7571
  }
7403
- const howl = currentRef.current?.handle.howl;
7404
- if (howl) {
7405
- howl.mute(m);
7406
- }
7572
+ mutedRef.current = m;
7573
+ currentRef.current?.handle.howl.mute(m);
7407
7574
  notifySnapshot({ muted: m });
7408
7575
  },
7409
7576
  toggleMuted: () => {
@@ -7411,17 +7578,15 @@ function BackgroundAudio({
7411
7578
  return;
7412
7579
  }
7413
7580
  const next = !snapshotRef.current.muted;
7414
- const howl = currentRef.current?.handle.howl;
7415
- if (howl) {
7416
- howl.mute(next);
7417
- }
7581
+ mutedRef.current = next;
7582
+ currentRef.current?.handle.howl.mute(next);
7418
7583
  notifySnapshot({ muted: next });
7419
7584
  }
7420
7585
  }),
7421
7586
  []
7422
7587
  );
7423
- const bgmHost = useContext15(BackgroundAudioHostContext);
7424
- useEffect13(() => {
7588
+ const bgmHost = useContext16(BackgroundAudioHostContext);
7589
+ useEffect14(() => {
7425
7590
  if (!bgmHost) {
7426
7591
  return;
7427
7592
  }
@@ -7434,7 +7599,7 @@ function BackgroundAudio({
7434
7599
  }
7435
7600
  };
7436
7601
  }, [bgmHost, controller]);
7437
- useEffect13(() => {
7602
+ useEffect14(() => {
7438
7603
  return () => {
7439
7604
  fadingInRef.current = false;
7440
7605
  isFirstTrackRef.current = true;
@@ -7446,7 +7611,7 @@ function BackgroundAudio({
7446
7611
  outgoingRef.current = [];
7447
7612
  };
7448
7613
  }, []);
7449
- useEffect13(() => {
7614
+ useEffect14(() => {
7450
7615
  const previous = currentRef.current;
7451
7616
  if (previous?.key === trackKey && previous.crossOrigin === crossOrigin) {
7452
7617
  return;
@@ -7481,6 +7646,9 @@ function BackgroundAudio({
7481
7646
  shouldRetryPlay: () => currentRef.current?.key === trackKey && playingRef.current,
7482
7647
  onEnded: () => {
7483
7648
  notifySnapshot({ playing: false, ended: true });
7649
+ if (!isControlledRef.current) {
7650
+ setInternalPlaying(false);
7651
+ }
7484
7652
  onPlaybackStateChangeRef.current?.("ended");
7485
7653
  onEndedRef.current?.();
7486
7654
  },
@@ -7546,35 +7714,42 @@ function BackgroundAudio({
7546
7714
  retire(previous);
7547
7715
  }
7548
7716
  }, [crossOrigin, trackKey]);
7549
- useEffect13(() => {
7717
+ useEffect14(() => {
7550
7718
  const howl = currentRef.current?.handle.howl;
7551
7719
  if (!howl) {
7552
7720
  return;
7553
7721
  }
7554
7722
  if (!playing) {
7555
7723
  fadingInRef.current = false;
7556
- howl.pause();
7724
+ if (howl.playing()) {
7725
+ howl.pause();
7726
+ }
7557
7727
  for (const slot of outgoingRef.current) {
7558
7728
  slot.handle.dispose();
7559
7729
  }
7560
7730
  outgoingRef.current = [];
7561
7731
  return;
7562
7732
  }
7563
- howl.play();
7733
+ if (!howl.playing()) {
7734
+ howl.play();
7735
+ }
7564
7736
  }, [playing, trackKey]);
7565
- useEffect13(() => {
7737
+ useEffect14(() => {
7566
7738
  const slot = currentRef.current;
7567
7739
  if (!slot) {
7568
7740
  return;
7569
7741
  }
7570
7742
  slot.handle.howl.loop(loop);
7571
- slot.handle.howl.mute(muted);
7743
+ slot.handle.howl.mute(mutedRef.current);
7572
7744
  if (!fadingInRef.current) {
7573
- slot.handle.howl.volume(clampAudioVolume(volume));
7745
+ slot.handle.howl.volume(clampAudioVolume(volumeRef.current));
7574
7746
  }
7575
- notifySnapshot({ muted, volume: clampAudioVolume(volume) });
7747
+ notifySnapshot({
7748
+ muted: mutedRef.current,
7749
+ volume: clampAudioVolume(volumeRef.current)
7750
+ });
7576
7751
  }, [loop, muted, trackKey, volume]);
7577
- useEffect13(() => {
7752
+ useEffect14(() => {
7578
7753
  if (!pauseWhenHidden) {
7579
7754
  return;
7580
7755
  }
@@ -7600,13 +7775,13 @@ function BackgroundAudio({
7600
7775
  }
7601
7776
 
7602
7777
  // src/pano-filter/pano-filter.tsx
7603
- import { useContext as useContext16, useEffect as useEffect14, useMemo as useMemo9 } from "react";
7778
+ import { useContext as useContext17, useEffect as useEffect15, useMemo as useMemo9 } from "react";
7604
7779
  function PanoFilter({
7605
7780
  preset = "none",
7606
7781
  intensity,
7607
7782
  enabled = true
7608
7783
  }) {
7609
- const host = useContext16(PanoFilterHostContext);
7784
+ const host = useContext17(PanoFilterHostContext);
7610
7785
  if (!host) {
7611
7786
  throw new Error("<PanoFilter> must be rendered inside <PanoViewer>.");
7612
7787
  }
@@ -7614,13 +7789,13 @@ function PanoFilter({
7614
7789
  () => resolvePanoFilterSnapshot({ preset, intensity, enabled }),
7615
7790
  [enabled, intensity, preset]
7616
7791
  );
7617
- useEffect14(() => {
7792
+ useEffect15(() => {
7618
7793
  claimPanoFilter(host);
7619
7794
  return () => {
7620
7795
  releasePanoFilter(host);
7621
7796
  };
7622
7797
  }, [host]);
7623
- useEffect14(() => {
7798
+ useEffect15(() => {
7624
7799
  setPanoFilterSnapshot(host, snapshot);
7625
7800
  }, [host, snapshot]);
7626
7801
  return null;
@@ -7631,10 +7806,10 @@ import { useFrame as useFrame6, useThree as useThree9 } from "@react-three/fiber
7631
7806
  import {
7632
7807
  forwardRef as forwardRef3,
7633
7808
  useCallback as useCallback7,
7634
- useContext as useContext17,
7635
- useEffect as useEffect15,
7809
+ useContext as useContext18,
7810
+ useEffect as useEffect16,
7636
7811
  useImperativeHandle as useImperativeHandle3,
7637
- useRef as useRef14,
7812
+ useRef as useRef15,
7638
7813
  useState as useState7
7639
7814
  } from "react";
7640
7815
 
@@ -7736,24 +7911,24 @@ var Gyro = forwardRef3(function Gyro2({
7736
7911
  onDisable,
7737
7912
  onDenied
7738
7913
  }, ref) {
7739
- const controlsRef = useContext17(PanoramaViewContext);
7740
- const eventBus = useContext17(PanoEventBusContext);
7914
+ const controlsRef = useContext18(PanoramaViewContext);
7915
+ const eventBus = useContext18(PanoEventBusContext);
7741
7916
  const { gl } = useThree9();
7742
7917
  const [internallyDisabled, setInternallyDisabled] = useState7(false);
7743
- const availableRef = useRef14(false);
7744
- const availabilityReportedRef = useRef14(null);
7745
- const activeRef = useRef14(false);
7746
- const permissionRef = useRef14(deviceOrientationPermissionState);
7747
- const absoluteEventSourceRef = useRef14(null);
7748
- const rawQuaternionRef = useRef14(null);
7749
- const calibrationRef = useRef14(null);
7750
- const absoluteOffsetRef = useRef14({ yaw: 0, pitch: 0 });
7751
- const screenAngleRef = useRef14(getScreenOrientationAngle());
7752
- const startPoseRef = useRef14(null);
7753
- const enabledAtRef = useRef14(0);
7754
- const filteredPoseRef = useRef14(null);
7755
- const lastAppliedPoseRef = useRef14(null);
7756
- const callbacksRef = useRef14({
7918
+ const availableRef = useRef15(false);
7919
+ const availabilityReportedRef = useRef15(null);
7920
+ const activeRef = useRef15(false);
7921
+ const permissionRef = useRef15(deviceOrientationPermissionState);
7922
+ const absoluteEventSourceRef = useRef15(null);
7923
+ const rawQuaternionRef = useRef15(null);
7924
+ const calibrationRef = useRef15(null);
7925
+ const absoluteOffsetRef = useRef15({ yaw: 0, pitch: 0 });
7926
+ const screenAngleRef = useRef15(getScreenOrientationAngle());
7927
+ const startPoseRef = useRef15(null);
7928
+ const enabledAtRef = useRef15(0);
7929
+ const filteredPoseRef = useRef15(null);
7930
+ const lastAppliedPoseRef = useRef15(null);
7931
+ const callbacksRef = useRef15({
7757
7932
  onAvailable,
7758
7933
  onUnavailable,
7759
7934
  onEnable,
@@ -7898,22 +8073,22 @@ var Gyro = forwardRef3(function Gyro2({
7898
8073
  }),
7899
8074
  [requestPermission, resetSensor]
7900
8075
  );
7901
- useEffect15(() => {
8076
+ useEffect16(() => {
7902
8077
  if (!enabled) {
7903
8078
  setInternallyDisabled(false);
7904
8079
  }
7905
8080
  }, [enabled]);
7906
- useEffect15(() => {
8081
+ useEffect16(() => {
7907
8082
  const supported = typeof window !== "undefined" && window.isSecureContext && typeof DeviceOrientationEvent !== "undefined" && (desktopSupport || isMobileDevice());
7908
8083
  setAvailable(supported);
7909
8084
  return () => {
7910
8085
  availableRef.current = false;
7911
8086
  };
7912
8087
  }, [desktopSupport, setAvailable]);
7913
- useEffect15(() => {
8088
+ useEffect16(() => {
7914
8089
  controlsRef.current?.setGyroTouchMode(touchMode);
7915
8090
  }, [controlsRef, touchMode]);
7916
- useEffect15(() => {
8091
+ useEffect16(() => {
7917
8092
  if (!enabled || internallyDisabled || touchMode !== "disablegyro") {
7918
8093
  return;
7919
8094
  }
@@ -7927,7 +8102,7 @@ var Gyro = forwardRef3(function Gyro2({
7927
8102
  gl.domElement.removeEventListener("pointerdown", onPointerDown);
7928
8103
  };
7929
8104
  }, [enabled, gl, internallyDisabled, touchMode]);
7930
- useEffect15(() => {
8105
+ useEffect16(() => {
7931
8106
  if (!enabled || internallyDisabled || !availableRef.current) {
7932
8107
  deactivate();
7933
8108
  return;
@@ -8092,11 +8267,11 @@ import { useThree as useThree12 } from "@react-three/fiber";
8092
8267
  import {
8093
8268
  forwardRef as forwardRef4,
8094
8269
  useCallback as useCallback8,
8095
- useContext as useContext19,
8096
- useEffect as useEffect19,
8270
+ useContext as useContext20,
8271
+ useEffect as useEffect20,
8097
8272
  useImperativeHandle as useImperativeHandle4,
8098
8273
  useMemo as useMemo11,
8099
- useRef as useRef18,
8274
+ useRef as useRef19,
8100
8275
  useState as useState8
8101
8276
  } from "react";
8102
8277
 
@@ -8121,14 +8296,14 @@ async function detectWebVRCapabilities() {
8121
8296
 
8122
8297
  // src/webvr/reticle.tsx
8123
8298
  import { useFrame as useFrame7, useThree as useThree10 } from "@react-three/fiber";
8124
- import { useRef as useRef15 } from "react";
8299
+ import { useRef as useRef16 } from "react";
8125
8300
  import {
8126
8301
  DoubleSide,
8127
8302
  Raycaster as Raycaster2,
8128
8303
  Vector2 as Vector22,
8129
8304
  Vector3 as Vector37
8130
8305
  } from "three";
8131
- import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
8306
+ import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
8132
8307
  var CENTER_NDC = new Vector22(0, 0);
8133
8308
  var HUD_DISTANCE = 2;
8134
8309
  var RETICLE_SCALE = 1;
@@ -8212,13 +8387,13 @@ function WebVRReticle({
8212
8387
  dwellMs,
8213
8388
  visible
8214
8389
  }) {
8215
- const groupRef = useRef15(null);
8216
- const ringMeshRef = useRef15(null);
8217
- const directionRef = useRef15(new Vector37());
8218
- const raycasterRef = useRef15(new Raycaster2());
8219
- const hoveredRef = useRef15(null);
8220
- const dwellRef = useRef15(0);
8221
- const clickedRef = useRef15(false);
8390
+ const groupRef = useRef16(null);
8391
+ const ringMeshRef = useRef16(null);
8392
+ const directionRef = useRef16(new Vector37());
8393
+ const raycasterRef = useRef16(new Raycaster2());
8394
+ const hoveredRef = useRef16(null);
8395
+ const dwellRef = useRef16(0);
8396
+ const clickedRef = useRef16(false);
8222
8397
  const { camera, gl, scene } = useThree10();
8223
8398
  useFrame7((_, deltaSeconds) => {
8224
8399
  const group = groupRef.current;
@@ -8303,8 +8478,8 @@ function WebVRReticle({
8303
8478
  raycast: noopRaycast,
8304
8479
  renderOrder: RETICLE_RENDER_ORDER + 1,
8305
8480
  children: [
8306
- /* @__PURE__ */ jsx12("boxGeometry", { args: [CROSSHAIR_LENGTH, CROSSHAIR_THICKNESS, 1e-3] }),
8307
- /* @__PURE__ */ jsx12(
8481
+ /* @__PURE__ */ jsx13("boxGeometry", { args: [CROSSHAIR_LENGTH, CROSSHAIR_THICKNESS, 1e-3] }),
8482
+ /* @__PURE__ */ jsx13(
8308
8483
  "meshBasicMaterial",
8309
8484
  {
8310
8485
  color: "#ffffff",
@@ -8324,8 +8499,8 @@ function WebVRReticle({
8324
8499
  raycast: noopRaycast,
8325
8500
  renderOrder: RETICLE_RENDER_ORDER + 1,
8326
8501
  children: [
8327
- /* @__PURE__ */ jsx12("boxGeometry", { args: [CROSSHAIR_THICKNESS, CROSSHAIR_LENGTH, 1e-3] }),
8328
- /* @__PURE__ */ jsx12(
8502
+ /* @__PURE__ */ jsx13("boxGeometry", { args: [CROSSHAIR_THICKNESS, CROSSHAIR_LENGTH, 1e-3] }),
8503
+ /* @__PURE__ */ jsx13(
8329
8504
  "meshBasicMaterial",
8330
8505
  {
8331
8506
  color: "#ffffff",
@@ -8347,7 +8522,7 @@ function WebVRReticle({
8347
8522
  renderOrder: RETICLE_RENDER_ORDER + 2,
8348
8523
  visible: false,
8349
8524
  children: [
8350
- /* @__PURE__ */ jsx12(
8525
+ /* @__PURE__ */ jsx13(
8351
8526
  "ringGeometry",
8352
8527
  {
8353
8528
  args: [
@@ -8360,7 +8535,7 @@ function WebVRReticle({
8360
8535
  ]
8361
8536
  }
8362
8537
  ),
8363
- /* @__PURE__ */ jsx12(
8538
+ /* @__PURE__ */ jsx13(
8364
8539
  "meshBasicMaterial",
8365
8540
  {
8366
8541
  color: "#ffffff",
@@ -8381,7 +8556,7 @@ function WebVRReticle({
8381
8556
 
8382
8557
  // src/webvr/stereo.tsx
8383
8558
  import { useFrame as useFrame8, useThree as useThree11 } from "@react-three/fiber";
8384
- import { useContext as useContext18, useEffect as useEffect16, useMemo as useMemo10, useRef as useRef16 } from "react";
8559
+ import { useContext as useContext19, useEffect as useEffect17, useMemo as useMemo10, useRef as useRef17 } from "react";
8385
8560
  import {
8386
8561
  Mesh as Mesh2,
8387
8562
  OrthographicCamera,
@@ -8467,25 +8642,25 @@ function WebVRStereoRenderer({
8467
8642
  screensize
8468
8643
  }) {
8469
8644
  const { camera, gl } = useThree11();
8470
- const runtime = useContext18(WebVRRuntimeContext);
8471
- const fallbackStereoRef = useRef16(null);
8645
+ const runtime = useContext19(WebVRRuntimeContext);
8646
+ const fallbackStereoRef = useRef17(null);
8472
8647
  if (!fallbackStereoRef.current) {
8473
8648
  fallbackStereoRef.current = new StereoCamera2();
8474
8649
  }
8475
8650
  const stereo = runtime?.stereoView.stereo ?? fallbackStereoRef.current;
8476
- const stereoRef = useRef16(stereo);
8651
+ const stereoRef = useRef17(stereo);
8477
8652
  stereoRef.current = stereo;
8478
8653
  const resources = useMemo10(createDistortionResources, []);
8479
- const drawingSizeRef = useRef16(new Vector23());
8480
- const viewportRef = useRef16(new Vector4());
8481
- const scissorRef = useRef16(new Vector4());
8482
- const originalFovRef = useRef16(null);
8483
- const stereoActiveRef = useRef16(false);
8484
- const profileRef = useRef16(profile);
8485
- const screensizeRef = useRef16(screensize);
8654
+ const drawingSizeRef = useRef17(new Vector23());
8655
+ const viewportRef = useRef17(new Vector4());
8656
+ const scissorRef = useRef17(new Vector4());
8657
+ const originalFovRef = useRef17(null);
8658
+ const stereoActiveRef = useRef17(false);
8659
+ const profileRef = useRef17(profile);
8660
+ const screensizeRef = useRef17(screensize);
8486
8661
  profileRef.current = profile;
8487
8662
  screensizeRef.current = screensize;
8488
- useEffect16(
8663
+ useEffect17(
8489
8664
  () => () => {
8490
8665
  resources.geometry.dispose();
8491
8666
  resources.material.dispose();
@@ -8493,7 +8668,7 @@ function WebVRStereoRenderer({
8493
8668
  },
8494
8669
  [resources]
8495
8670
  );
8496
- useEffect16(() => {
8671
+ useEffect17(() => {
8497
8672
  const originalRender = gl.render.bind(gl);
8498
8673
  gl.render = (sceneToRender, cameraToRender) => {
8499
8674
  if (!stereoActiveRef.current || !(cameraToRender instanceof PerspectiveCamera2)) {
@@ -8557,7 +8732,7 @@ function WebVRStereoRenderer({
8557
8732
  gl.render = originalRender;
8558
8733
  };
8559
8734
  }, [gl, resources]);
8560
- useEffect16(
8735
+ useEffect17(
8561
8736
  () => () => {
8562
8737
  if (runtime) {
8563
8738
  runtime.stereoView.active = false;
@@ -8592,7 +8767,7 @@ function WebVRStereoRenderer({
8592
8767
  }
8593
8768
 
8594
8769
  // src/webvr/pointerlock.ts
8595
- import { useEffect as useEffect17, useRef as useRef17 } from "react";
8770
+ import { useEffect as useEffect18, useRef as useRef18 } from "react";
8596
8771
  var POINTER_LOCK_CURSOR_ID = "webvr:pointerlock";
8597
8772
  async function requestWebVRPointerLock(element) {
8598
8773
  if (typeof document === "undefined") {
@@ -8625,11 +8800,11 @@ function exitWebVRPointerLock(element) {
8625
8800
  }
8626
8801
  function useWebVRPointerLock(enabled, element) {
8627
8802
  const cursor = usePanoCursor();
8628
- const cursorRef = useRef17(cursor);
8629
- const enabledRef = useRef17(enabled);
8803
+ const cursorRef = useRef18(cursor);
8804
+ const enabledRef = useRef18(enabled);
8630
8805
  cursorRef.current = cursor;
8631
8806
  enabledRef.current = enabled;
8632
- useEffect17(() => {
8807
+ useEffect18(() => {
8633
8808
  if (!enabled || !element) {
8634
8809
  return;
8635
8810
  }
@@ -8659,7 +8834,7 @@ function useWebVRPointerLock(enabled, element) {
8659
8834
  }
8660
8835
 
8661
8836
  // src/webvr/wakelock.ts
8662
- import { useEffect as useEffect18 } from "react";
8837
+ import { useEffect as useEffect19 } from "react";
8663
8838
 
8664
8839
  // src/webvr/wakelock-fallback.ts
8665
8840
  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==";
@@ -8793,7 +8968,7 @@ function releaseWebVRWakeLock() {
8793
8968
  stopFallbackVideo();
8794
8969
  }
8795
8970
  function useWebVRWakeLock(enabled) {
8796
- useEffect18(() => {
8971
+ useEffect19(() => {
8797
8972
  if (!enabled) {
8798
8973
  return;
8799
8974
  }
@@ -8812,7 +8987,7 @@ function useWebVRWakeLock(enabled) {
8812
8987
  }
8813
8988
 
8814
8989
  // src/webvr/webvr.tsx
8815
- import { Fragment as Fragment4, jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
8990
+ import { Fragment as Fragment4, jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
8816
8991
  function initializeSettings(screensize, profile) {
8817
8992
  const stored = loadWebVRSettings();
8818
8993
  return {
@@ -8841,24 +9016,24 @@ var WebVR = forwardRef4(function WebVR2({
8841
9016
  onDenied,
8842
9017
  onUnknownDevice
8843
9018
  }, ref) {
8844
- const runtime = useContext19(WebVRRuntimeContext);
8845
- const controlsRef = useContext19(PanoramaViewContext);
8846
- const eventBus = useContext19(PanoEventBusContext);
9019
+ const runtime = useContext20(WebVRRuntimeContext);
9020
+ const controlsRef = useContext20(PanoramaViewContext);
9021
+ const eventBus = useContext20(PanoEventBusContext);
8847
9022
  const gl = useThree12((state) => state.gl);
8848
- const gyroRef = useRef18(null);
8849
- const capabilitiesRef = useRef18({
9023
+ const gyroRef = useRef19(null);
9024
+ const capabilitiesRef = useRef19({
8850
9025
  mobile: false,
8851
9026
  sensor: false,
8852
9027
  webxr: false
8853
9028
  });
8854
- const availableRef = useRef18(false);
8855
- const modeRef = useRef18(null);
8856
- const webXRSessionRef = useRef18(null);
9029
+ const availableRef = useRef19(false);
9030
+ const modeRef = useRef19(null);
9031
+ const webXRSessionRef = useRef19(null);
8857
9032
  const [mode, setMode] = useState8(null);
8858
9033
  const [settings, setSettings] = useState8(
8859
9034
  () => initializeSettings(screensize, profile)
8860
9035
  );
8861
- const callbacksRef = useRef18({
9036
+ const callbacksRef = useRef19({
8862
9037
  onAvailable,
8863
9038
  onDenied,
8864
9039
  onEnterVR,
@@ -9068,7 +9243,7 @@ var WebVR = forwardRef4(function WebVR2({
9068
9243
  }),
9069
9244
  [enterVR, exitVR, requestPermission, toggleVR]
9070
9245
  );
9071
- useEffect19(() => {
9246
+ useEffect20(() => {
9072
9247
  let active = true;
9073
9248
  void detectWebVRCapabilities().then((capabilities) => {
9074
9249
  if (!active) {
@@ -9090,7 +9265,7 @@ var WebVR = forwardRef4(function WebVR2({
9090
9265
  active = false;
9091
9266
  };
9092
9267
  }, [desktopSupport, eventBus, fakeSupport, host, mobileVr]);
9093
- useEffect19(() => {
9268
+ useEffect20(() => {
9094
9269
  host.controller = controller;
9095
9270
  return () => {
9096
9271
  if (host.controller === controller) {
@@ -9099,10 +9274,10 @@ var WebVR = forwardRef4(function WebVR2({
9099
9274
  }
9100
9275
  };
9101
9276
  }, [controller, host]);
9102
- useEffect19(() => {
9277
+ useEffect20(() => {
9103
9278
  updateWebVRHost(host, { chrome, mode, settings });
9104
9279
  }, [chrome, host, mode, settings]);
9105
- useEffect19(() => {
9280
+ useEffect20(() => {
9106
9281
  if (mode !== "fake") {
9107
9282
  return;
9108
9283
  }
@@ -9126,7 +9301,7 @@ var WebVR = forwardRef4(function WebVR2({
9126
9301
  document.removeEventListener("mousemove", onMouseMove);
9127
9302
  };
9128
9303
  }, [controlsRef, gl.domElement, mode, mousePointerLock]);
9129
- useEffect19(
9304
+ useEffect20(
9130
9305
  () => () => {
9131
9306
  const session2 = webXRSessionRef.current;
9132
9307
  if (session2) {
@@ -9146,7 +9321,7 @@ var WebVR = forwardRef4(function WebVR2({
9146
9321
  wakelock && (mode === "mobilevr" || mode === "fake")
9147
9322
  );
9148
9323
  return /* @__PURE__ */ jsxs8(Fragment4, { children: [
9149
- /* @__PURE__ */ jsx13(
9324
+ /* @__PURE__ */ jsx14(
9150
9325
  Gyro,
9151
9326
  {
9152
9327
  ref: gyroRef,
@@ -9160,7 +9335,7 @@ var WebVR = forwardRef4(function WebVR2({
9160
9335
  touchMode: "off"
9161
9336
  }
9162
9337
  ),
9163
- /* @__PURE__ */ jsx13(
9338
+ /* @__PURE__ */ jsx14(
9164
9339
  WebVRStereoRenderer,
9165
9340
  {
9166
9341
  mode,
@@ -9168,7 +9343,7 @@ var WebVR = forwardRef4(function WebVR2({
9168
9343
  screensize: settings.screensize
9169
9344
  }
9170
9345
  ),
9171
- /* @__PURE__ */ jsx13(
9346
+ /* @__PURE__ */ jsx14(
9172
9347
  WebVRReticle,
9173
9348
  {
9174
9349
  dwellMs: cursorDwellMs,
@@ -9179,7 +9354,7 @@ var WebVR = forwardRef4(function WebVR2({
9179
9354
  });
9180
9355
 
9181
9356
  // src/use-pano-viewer.ts
9182
- import { useMemo as useMemo12, useRef as useRef19 } from "react";
9357
+ import { useMemo as useMemo12, useRef as useRef20 } from "react";
9183
9358
  function createPanoViewerHandle(ref) {
9184
9359
  return {
9185
9360
  getView: () => ref.current?.getView() ?? { yaw: 0, pitch: 0, fov: 75 },
@@ -9189,6 +9364,7 @@ function createPanoViewerHandle(ref) {
9189
9364
  reset: () => {
9190
9365
  ref.current?.reset();
9191
9366
  },
9367
+ activateMedia: () => ref.current?.activateMedia() ?? Promise.resolve(),
9192
9368
  enterFullscreen: () => ref.current?.enterFullscreen() ?? Promise.resolve(),
9193
9369
  exitFullscreen: () => ref.current?.exitFullscreen() ?? Promise.resolve(),
9194
9370
  toggleFullscreen: () => ref.current?.toggleFullscreen() ?? Promise.resolve(),
@@ -9256,14 +9432,14 @@ function createPanoViewerHandle(ref) {
9256
9432
  };
9257
9433
  }
9258
9434
  function usePanoViewer() {
9259
- const ref = useRef19(null);
9435
+ const ref = useRef20(null);
9260
9436
  const handle = useMemo12(() => createPanoViewerHandle(ref), []);
9261
9437
  return useMemo12(() => ({ ref, ...handle }), [handle]);
9262
9438
  }
9263
9439
 
9264
9440
  // src/sphere.tsx
9265
9441
  import { useThree as useThree13 } from "@react-three/fiber";
9266
- import { useEffect as useEffect20, useMemo as useMemo14, useRef as useRef21, useState as useState9 } from "react";
9442
+ import { useEffect as useEffect21, useMemo as useMemo14, useRef as useRef22, useState as useState9 } from "react";
9267
9443
  import {
9268
9444
  BackSide as BackSide2,
9269
9445
  LinearFilter,
@@ -9296,7 +9472,7 @@ function resolveUrlAgainstFile(fileUrl, path) {
9296
9472
  }
9297
9473
 
9298
9474
  // src/pano-filter/pano-basic-material.tsx
9299
- import { useLayoutEffect as useLayoutEffect2, useMemo as useMemo13, useRef as useRef20 } from "react";
9475
+ import { useLayoutEffect as useLayoutEffect2, useMemo as useMemo13, useRef as useRef21 } from "react";
9300
9476
 
9301
9477
  // src/pano-filter/shaders.ts
9302
9478
  var GLSL_FILTER_COMMON = `
@@ -9447,7 +9623,7 @@ diffuseColor.rgb = mix(diffuseColor.rgb, applyPanoFilter(diffuseColor.rgb), clam
9447
9623
  }
9448
9624
 
9449
9625
  // src/pano-filter/pano-basic-material.tsx
9450
- import { jsx as jsx14 } from "react/jsx-runtime";
9626
+ import { jsx as jsx15 } from "react/jsx-runtime";
9451
9627
  function PanoBasicMaterial({
9452
9628
  map,
9453
9629
  side,
@@ -9456,9 +9632,9 @@ function PanoBasicMaterial({
9456
9632
  toneMapped = false
9457
9633
  }) {
9458
9634
  const snapshot = usePanoFilterSnapshot();
9459
- const materialRef = useRef20(null);
9460
- const intensityRef = useRef20(snapshot.intensity);
9461
- const intensityUniformRef = useRef20(null);
9635
+ const materialRef = useRef21(null);
9636
+ const intensityRef = useRef21(snapshot.intensity);
9637
+ const intensityUniformRef = useRef21(null);
9462
9638
  intensityRef.current = snapshot.intensity;
9463
9639
  const active = isPanoFilterActive(snapshot);
9464
9640
  const preset = snapshot.preset;
@@ -9494,7 +9670,7 @@ function PanoBasicMaterial({
9494
9670
  intensityUniformRef.current.value = snapshot.intensity;
9495
9671
  }
9496
9672
  }, [snapshot.intensity]);
9497
- return /* @__PURE__ */ jsx14(
9673
+ return /* @__PURE__ */ jsx15(
9498
9674
  "meshBasicMaterial",
9499
9675
  {
9500
9676
  ref: materialRef,
@@ -9510,14 +9686,14 @@ function PanoBasicMaterial({
9510
9686
  }
9511
9687
 
9512
9688
  // src/sphere.tsx
9513
- import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
9689
+ import { jsx as jsx16, jsxs as jsxs9 } from "react/jsx-runtime";
9514
9690
  function useEquirectTexture(url, anisotropy, generateMipmaps, onLoad, onError) {
9515
9691
  const [texture, setTexture] = useState9(null);
9516
- const onLoadRef = useRef21(onLoad);
9517
- const onErrorRef = useRef21(onError);
9692
+ const onLoadRef = useRef22(onLoad);
9693
+ const onErrorRef = useRef22(onError);
9518
9694
  onLoadRef.current = onLoad;
9519
9695
  onErrorRef.current = onError;
9520
- useEffect20(() => {
9696
+ useEffect21(() => {
9521
9697
  if (!url) {
9522
9698
  setTexture(null);
9523
9699
  return;
@@ -9556,7 +9732,7 @@ function useEquirectTexture(url, anisotropy, generateMipmaps, onLoad, onError) {
9556
9732
  active = false;
9557
9733
  };
9558
9734
  }, [anisotropy, generateMipmaps, url]);
9559
- useEffect20(
9735
+ useEffect21(
9560
9736
  () => () => {
9561
9737
  texture?.dispose();
9562
9738
  },
@@ -9595,11 +9771,11 @@ function Sphere({
9595
9771
  onPreviewError
9596
9772
  );
9597
9773
  const displayTexture = texture ?? previewTexture;
9598
- const readyRef = useRef21(false);
9599
- useEffect20(() => {
9774
+ const readyRef = useRef22(false);
9775
+ useEffect21(() => {
9600
9776
  readyRef.current = false;
9601
9777
  }, [resolvedPreviewUrl, src]);
9602
- useEffect20(() => {
9778
+ useEffect21(() => {
9603
9779
  if (!displayTexture || readyRef.current) {
9604
9780
  return;
9605
9781
  }
@@ -9615,8 +9791,8 @@ function Sphere({
9615
9791
  rotation: [0, MathUtils5.degToRad(90 + yawOffset), 0],
9616
9792
  visible,
9617
9793
  children: [
9618
- /* @__PURE__ */ jsx15("sphereGeometry", { args: [DEFAULT_PANORAMA_RADIUS, 128, 64] }),
9619
- /* @__PURE__ */ jsx15(
9794
+ /* @__PURE__ */ jsx16("sphereGeometry", { args: [DEFAULT_PANORAMA_RADIUS, 128, 64] }),
9795
+ /* @__PURE__ */ jsx16(
9620
9796
  PanoBasicMaterial,
9621
9797
  {
9622
9798
  map: displayTexture,
@@ -9633,11 +9809,11 @@ function Sphere({
9633
9809
  import { useThree as useThree14 } from "@react-three/fiber";
9634
9810
  import {
9635
9811
  useCallback as useCallback9,
9636
- useContext as useContext20,
9637
- useEffect as useEffect21,
9812
+ useContext as useContext21,
9813
+ useEffect as useEffect22,
9638
9814
  useLayoutEffect as useLayoutEffect3,
9639
9815
  useMemo as useMemo15,
9640
- useRef as useRef22,
9816
+ useRef as useRef23,
9641
9817
  useState as useState10
9642
9818
  } from "react";
9643
9819
  import {
@@ -9650,7 +9826,7 @@ import {
9650
9826
  TextureLoader as TextureLoader2,
9651
9827
  VideoTexture
9652
9828
  } from "three";
9653
- import { Fragment as Fragment5, jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
9829
+ import { Fragment as Fragment5, jsx as jsx17, jsxs as jsxs10 } from "react/jsx-runtime";
9654
9830
  var EMPTY_TRACKS = [];
9655
9831
  var EMPTY_RATES = DEFAULT_PANO_VIDEO_PLAYBACK_RATES;
9656
9832
  function createEmptySnapshot() {
@@ -9736,9 +9912,9 @@ function applyEquirectangularLayout(texture, anisotropy) {
9736
9912
  function usePosterTexture(poster, onError) {
9737
9913
  const gl = useThree14((state) => state.gl);
9738
9914
  const [texture, setTexture] = useState10(null);
9739
- const onErrorRef = useRef22(onError);
9915
+ const onErrorRef = useRef23(onError);
9740
9916
  onErrorRef.current = onError;
9741
- useEffect21(() => {
9917
+ useEffect22(() => {
9742
9918
  let active = true;
9743
9919
  setTexture(null);
9744
9920
  if (!poster) {
@@ -9775,7 +9951,7 @@ function usePosterTexture(poster, onError) {
9775
9951
  active = false;
9776
9952
  };
9777
9953
  }, [gl, poster]);
9778
- useEffect21(
9954
+ useEffect22(
9779
9955
  () => () => {
9780
9956
  texture?.dispose();
9781
9957
  },
@@ -9832,9 +10008,10 @@ function PanoVideo({
9832
10008
  onVariantChange,
9833
10009
  onTrackChange
9834
10010
  }) {
10011
+ usePanoMediaActivationIntent(autoPlay);
9835
10012
  const gl = useThree14((state) => state.gl);
9836
- const host = useContext20(PanoVideoHostContext);
9837
- const overlay = useContext20(PanoChromeOverlayContext);
10013
+ const host = useContext21(PanoVideoHostContext);
10014
+ const overlay = useContext21(PanoChromeOverlayContext);
9838
10015
  const variants = useMemo15(
9839
10016
  () => resolvePanoVideoVariants({ poster, src, variants: variantsProp }),
9840
10017
  [poster, src, variantsProp]
@@ -9854,17 +10031,17 @@ function PanoVideo({
9854
10031
  () => captionsEnabled ? defaultPanoVideoTrackId(tracks) : null
9855
10032
  );
9856
10033
  const [ready, setReady] = useState10(false);
9857
- const autoPlayRef = useRef22(autoPlay);
10034
+ const autoPlayRef = useRef23(autoPlay);
9858
10035
  autoPlayRef.current = autoPlay;
9859
- const blockedRef = useRef22(false);
9860
- const captionAppearanceOverrideRef = useRef22(
10036
+ const blockedRef = useRef23(false);
10037
+ const captionAppearanceOverrideRef = useRef23(
9861
10038
  {}
9862
10039
  );
9863
- const mediaCapabilitiesRef = useRef22({
10040
+ const mediaCapabilitiesRef = useRef23({
9864
10041
  volumeAdjustable: true,
9865
10042
  playbackRates: [...DEFAULT_PANO_VIDEO_PLAYBACK_RATES]
9866
10043
  });
9867
- const storeRef = useRef22(null);
10044
+ const storeRef = useRef23(null);
9868
10045
  if (!storeRef.current) {
9869
10046
  storeRef.current = {
9870
10047
  snapshot: {
@@ -9874,7 +10051,7 @@ function PanoVideo({
9874
10051
  listeners: /* @__PURE__ */ new Set()
9875
10052
  };
9876
10053
  }
9877
- const actionsRef = useRef22({
10054
+ const actionsRef = useRef23({
9878
10055
  play: async () => {
9879
10056
  },
9880
10057
  pause: () => {
@@ -9894,12 +10071,12 @@ function PanoVideo({
9894
10071
  setCaptionAppearance: (_appearance) => {
9895
10072
  }
9896
10073
  });
9897
- const onLoadRef = useRef22(onLoad);
9898
- const onErrorRef = useRef22(onError);
9899
- const onPlaybackStateChangeRef = useRef22(onPlaybackStateChange);
9900
- const onEndedRef = useRef22(onEnded);
9901
- const onVariantChangeRef = useRef22(onVariantChange);
9902
- const onTrackChangeRef = useRef22(onTrackChange);
10074
+ const onLoadRef = useRef23(onLoad);
10075
+ const onErrorRef = useRef23(onError);
10076
+ const onPlaybackStateChangeRef = useRef23(onPlaybackStateChange);
10077
+ const onEndedRef = useRef23(onEnded);
10078
+ const onVariantChangeRef = useRef23(onVariantChange);
10079
+ const onTrackChangeRef = useRef23(onTrackChange);
9903
10080
  onLoadRef.current = onLoad;
9904
10081
  onErrorRef.current = onError;
9905
10082
  onPlaybackStateChangeRef.current = onPlaybackStateChange;
@@ -9923,7 +10100,7 @@ function PanoVideo({
9923
10100
  texture.generateMipmaps = false;
9924
10101
  return { video, texture };
9925
10102
  }, []);
9926
- useEffect21(
10103
+ useEffect22(
9927
10104
  () => () => {
9928
10105
  if (!resource) {
9929
10106
  return;
@@ -9938,13 +10115,13 @@ function PanoVideo({
9938
10115
  },
9939
10116
  [resource]
9940
10117
  );
9941
- useEffect21(() => {
10118
+ useEffect22(() => {
9942
10119
  if (!resource) {
9943
10120
  return;
9944
10121
  }
9945
10122
  resource.texture.anisotropy = gl.capabilities.getMaxAnisotropy();
9946
10123
  }, [gl, resource]);
9947
- useEffect21(() => {
10124
+ useEffect22(() => {
9948
10125
  if (!resource || !overlay?.overlayElement) {
9949
10126
  return;
9950
10127
  }
@@ -10097,10 +10274,10 @@ function PanoVideo({
10097
10274
  };
10098
10275
  emitSnapshot();
10099
10276
  }, [emitSnapshot, playbackRates, resource]);
10100
- useEffect21(() => {
10277
+ useEffect22(() => {
10101
10278
  emitSnapshot();
10102
10279
  }, [emitSnapshot]);
10103
- useEffect21(() => {
10280
+ useEffect22(() => {
10104
10281
  if (!resource || !activeVariant || !mediaKey) {
10105
10282
  return;
10106
10283
  }
@@ -10157,7 +10334,7 @@ function PanoVideo({
10157
10334
  video.removeEventListener("error", handleError);
10158
10335
  };
10159
10336
  }, [mediaKey, resource]);
10160
- useEffect21(() => {
10337
+ useEffect22(() => {
10161
10338
  if (!resource) {
10162
10339
  return;
10163
10340
  }
@@ -10247,7 +10424,7 @@ function PanoVideo({
10247
10424
  }
10248
10425
  };
10249
10426
  }, [emitSnapshot, resource]);
10250
- useEffect21(() => {
10427
+ useEffect22(() => {
10251
10428
  if (!resource) {
10252
10429
  return;
10253
10430
  }
@@ -10258,9 +10435,16 @@ function PanoVideo({
10258
10435
  video.volume = clampVolume(volume);
10259
10436
  }
10260
10437
  video.playsInline = playsInline;
10438
+ if (playsInline) {
10439
+ video.setAttribute("playsinline", "true");
10440
+ video.setAttribute("webkit-playsinline", "true");
10441
+ } else {
10442
+ video.removeAttribute("playsinline");
10443
+ video.removeAttribute("webkit-playsinline");
10444
+ }
10261
10445
  video.preload = preload;
10262
10446
  }, [loop, muted, playsInline, preload, resource, volume]);
10263
- useEffect21(() => {
10447
+ useEffect22(() => {
10264
10448
  if (!resource) {
10265
10449
  return;
10266
10450
  }
@@ -10310,7 +10494,7 @@ function PanoVideo({
10310
10494
  video.removeEventListener("ratechange", handleVolume);
10311
10495
  };
10312
10496
  }, [emitSnapshot, resource]);
10313
- useEffect21(() => {
10497
+ useEffect22(() => {
10314
10498
  if (!resource) {
10315
10499
  return;
10316
10500
  }
@@ -10345,7 +10529,7 @@ function PanoVideo({
10345
10529
  video.textTracks.removeEventListener("change", applyModes);
10346
10530
  };
10347
10531
  }, [emitSnapshot, resource, trackId, tracks]);
10348
- useEffect21(() => {
10532
+ useEffect22(() => {
10349
10533
  if (!captionsEnabled) {
10350
10534
  setTrackId(null);
10351
10535
  return;
@@ -10363,8 +10547,8 @@ function PanoVideo({
10363
10547
  rotation: [0, MathUtils6.degToRad(90 + yawOffset), 0],
10364
10548
  visible,
10365
10549
  children: [
10366
- /* @__PURE__ */ jsx16("sphereGeometry", { args: [DEFAULT_PANORAMA_RADIUS, 128, 64] }),
10367
- /* @__PURE__ */ jsx16(
10550
+ /* @__PURE__ */ jsx17("sphereGeometry", { args: [DEFAULT_PANORAMA_RADIUS, 128, 64] }),
10551
+ /* @__PURE__ */ jsx17(
10368
10552
  PanoBasicMaterial,
10369
10553
  {
10370
10554
  map: activeTexture,
@@ -10375,7 +10559,7 @@ function PanoVideo({
10375
10559
  ]
10376
10560
  }
10377
10561
  ) : null,
10378
- captionsEnabled ? /* @__PURE__ */ jsx16(PanoVideoCaptions, { appearance: typeof captions === "object" ? captions : void 0 }) : null
10562
+ captionsEnabled ? /* @__PURE__ */ jsx17(PanoVideoCaptions, { appearance: typeof captions === "object" ? captions : void 0 }) : null
10379
10563
  ] });
10380
10564
  }
10381
10565
 
@@ -10384,10 +10568,10 @@ import { useFrame as useFrame12, useThree as useThree19 } from "@react-three/fib
10384
10568
  import {
10385
10569
  Fragment as Fragment6,
10386
10570
  useCallback as useCallback10,
10387
- useContext as useContext22,
10388
- useEffect as useEffect26,
10571
+ useContext as useContext23,
10572
+ useEffect as useEffect27,
10389
10573
  useMemo as useMemo20,
10390
- useRef as useRef26,
10574
+ useRef as useRef27,
10391
10575
  useState as useState12
10392
10576
  } from "react";
10393
10577
  import {
@@ -10444,7 +10628,7 @@ function isSnapshotTransition(preset) {
10444
10628
 
10445
10629
  // src/scene-transitions/particle-overlay.tsx
10446
10630
  import { useFrame as useFrame9, useThree as useThree15 } from "@react-three/fiber";
10447
- import { useEffect as useEffect22, useMemo as useMemo16, useRef as useRef23 } from "react";
10631
+ import { useEffect as useEffect23, useMemo as useMemo16, useRef as useRef24 } from "react";
10448
10632
  import {
10449
10633
  DoubleSide as DoubleSide2,
10450
10634
  InstancedBufferAttribute,
@@ -10507,7 +10691,7 @@ function overlayProgress(elapsedTime, duration, startTime) {
10507
10691
  }
10508
10692
 
10509
10693
  // src/scene-transitions/particle-overlay.tsx
10510
- import { jsx as jsx17 } from "react/jsx-runtime";
10694
+ import { jsx as jsx18 } from "react/jsx-runtime";
10511
10695
  var PARTICLE_GRID = 48;
10512
10696
  var PARTICLE_COUNT = PARTICLE_GRID * PARTICLE_GRID;
10513
10697
  var PARTICLE_VERTEX_SHADER = `
@@ -10584,10 +10768,10 @@ function ParticleOverlay({
10584
10768
  onFinish
10585
10769
  }) {
10586
10770
  const { camera } = useThree15();
10587
- const meshRef = useRef23(null);
10588
- const startRef = useRef23(null);
10589
- const finishedRef = useRef23(false);
10590
- const directionRef = useRef23(new Vector39());
10771
+ const meshRef = useRef24(null);
10772
+ const startRef = useRef24(null);
10773
+ const finishedRef = useRef24(false);
10774
+ const directionRef = useRef24(new Vector39());
10591
10775
  const geometry = useMemo16(() => createParticleGeometry(), []);
10592
10776
  const material = useMemo16(
10593
10777
  () => new ShaderMaterial2({
@@ -10605,9 +10789,9 @@ function ParticleOverlay({
10605
10789
  }),
10606
10790
  [snapshot.texture]
10607
10791
  );
10608
- useEffect22(() => () => geometry.dispose(), [geometry]);
10609
- useEffect22(() => () => material.dispose(), [material]);
10610
- useEffect22(() => {
10792
+ useEffect23(() => () => geometry.dispose(), [geometry]);
10793
+ useEffect23(() => () => material.dispose(), [material]);
10794
+ useEffect23(() => {
10611
10795
  startRef.current = null;
10612
10796
  finishedRef.current = false;
10613
10797
  material.uniforms.progress.value = 0;
@@ -10629,7 +10813,7 @@ function ParticleOverlay({
10629
10813
  onFinish();
10630
10814
  }
10631
10815
  });
10632
- return /* @__PURE__ */ jsx17(
10816
+ return /* @__PURE__ */ jsx18(
10633
10817
  "mesh",
10634
10818
  {
10635
10819
  ref: meshRef,
@@ -10643,7 +10827,7 @@ function ParticleOverlay({
10643
10827
 
10644
10828
  // src/scene-transitions/snapshot-overlay.tsx
10645
10829
  import { useFrame as useFrame10, useThree as useThree16 } from "@react-three/fiber";
10646
- import { useEffect as useEffect23, useMemo as useMemo17, useRef as useRef24 } from "react";
10830
+ import { useEffect as useEffect24, useMemo as useMemo17, useRef as useRef25 } from "react";
10647
10831
  import { Vector3 as Vector310 } from "three";
10648
10832
 
10649
10833
  // src/scene-transitions/snapshot-shaders.ts
@@ -10923,7 +11107,7 @@ function createSnapshotMaterial(preset, texture) {
10923
11107
  }
10924
11108
 
10925
11109
  // src/scene-transitions/snapshot-overlay.tsx
10926
- import { jsx as jsx18, jsxs as jsxs11 } from "react/jsx-runtime";
11110
+ import { jsx as jsx19, jsxs as jsxs11 } from "react/jsx-runtime";
10927
11111
  function SnapshotOverlay({
10928
11112
  snapshot,
10929
11113
  transition,
@@ -10932,18 +11116,18 @@ function SnapshotOverlay({
10932
11116
  onFinish
10933
11117
  }) {
10934
11118
  const { camera, gl } = useThree16();
10935
- const meshRef = useRef24(null);
10936
- const startRef = useRef24(null);
10937
- const finishedRef = useRef24(false);
10938
- const directionRef = useRef24(new Vector310());
11119
+ const meshRef = useRef25(null);
11120
+ const startRef = useRef25(null);
11121
+ const finishedRef = useRef25(false);
11122
+ const directionRef = useRef25(new Vector310());
10939
11123
  const material = useMemo17(() => {
10940
11124
  if (!isSnapshotTransition(transition.preset)) {
10941
11125
  return null;
10942
11126
  }
10943
11127
  return createSnapshotMaterial(transition.preset, snapshot.texture);
10944
11128
  }, [snapshot.texture, transition.preset]);
10945
- useEffect23(() => () => material?.dispose(), [material]);
10946
- useEffect23(() => {
11129
+ useEffect24(() => () => material?.dispose(), [material]);
11130
+ useEffect24(() => {
10947
11131
  startRef.current = null;
10948
11132
  finishedRef.current = false;
10949
11133
  if (material) {
@@ -10973,20 +11157,20 @@ function SnapshotOverlay({
10973
11157
  return null;
10974
11158
  }
10975
11159
  return /* @__PURE__ */ jsxs11("mesh", { ref: meshRef, renderOrder: OVERLAY_RENDER_ORDER, frustumCulled: false, children: [
10976
- /* @__PURE__ */ jsx18("primitive", { attach: "geometry", object: FULLSCREEN_PLANE }),
10977
- /* @__PURE__ */ jsx18("primitive", { attach: "material", object: material })
11160
+ /* @__PURE__ */ jsx19("primitive", { attach: "geometry", object: FULLSCREEN_PLANE }),
11161
+ /* @__PURE__ */ jsx19("primitive", { attach: "material", object: material })
10978
11162
  ] });
10979
11163
  }
10980
11164
 
10981
11165
  // src/scene-transitions/transition-overlay.tsx
10982
- import { jsx as jsx19 } from "react/jsx-runtime";
11166
+ import { jsx as jsx20 } from "react/jsx-runtime";
10983
11167
  function TransitionOverlay(props) {
10984
11168
  const { preset } = props.transition;
10985
11169
  switch (preset) {
10986
11170
  case "none":
10987
11171
  return null;
10988
11172
  case "particles":
10989
- return /* @__PURE__ */ jsx19(ParticleOverlay, { ...props });
11173
+ return /* @__PURE__ */ jsx20(ParticleOverlay, { ...props });
10990
11174
  case "crossfade":
10991
11175
  case "zoom":
10992
11176
  case "blackout":
@@ -11014,7 +11198,7 @@ function TransitionOverlay(props) {
11014
11198
  case "zoomBlur":
11015
11199
  case "hexDissolve":
11016
11200
  case "filmBurn":
11017
- return /* @__PURE__ */ jsx19(SnapshotOverlay, { ...props });
11201
+ return /* @__PURE__ */ jsx20(SnapshotOverlay, { ...props });
11018
11202
  default: {
11019
11203
  const exhaustive = preset;
11020
11204
  void exhaustive;
@@ -11026,9 +11210,9 @@ function TransitionOverlay(props) {
11026
11210
  // src/tile/texture-manager-context.tsx
11027
11211
  import { useThree as useThree17 } from "@react-three/fiber";
11028
11212
  import {
11029
- createContext as createContext13,
11030
- useContext as useContext21,
11031
- useEffect as useEffect24,
11213
+ createContext as createContext14,
11214
+ useContext as useContext22,
11215
+ useEffect as useEffect25,
11032
11216
  useMemo as useMemo18
11033
11217
  } from "react";
11034
11218
 
@@ -11259,8 +11443,8 @@ var TileTextureManager = class {
11259
11443
  };
11260
11444
 
11261
11445
  // src/tile/texture-manager-context.tsx
11262
- import { jsx as jsx20 } from "react/jsx-runtime";
11263
- var TileTextureManagerContext = createContext13(
11446
+ import { jsx as jsx21 } from "react/jsx-runtime";
11447
+ var TileTextureManagerContext = createContext14(
11264
11448
  null
11265
11449
  );
11266
11450
  function TileTextureManagerProvider({
@@ -11279,23 +11463,23 @@ function TileTextureManagerProvider({
11279
11463
  }),
11280
11464
  [anisotropy, maxConcurrentLoads, maxTextureMemoryMb]
11281
11465
  );
11282
- useEffect24(() => {
11466
+ useEffect25(() => {
11283
11467
  manager.resume();
11284
11468
  return () => manager.dispose();
11285
11469
  }, [manager]);
11286
- return /* @__PURE__ */ jsx20(TileTextureManagerContext.Provider, { value: manager, children });
11470
+ return /* @__PURE__ */ jsx21(TileTextureManagerContext.Provider, { value: manager, children });
11287
11471
  }
11288
11472
  function useSharedTileTextureManager() {
11289
- return useContext21(TileTextureManagerContext);
11473
+ return useContext22(TileTextureManagerContext);
11290
11474
  }
11291
11475
 
11292
11476
  // src/tile/tile.tsx
11293
11477
  import { useFrame as useFrame11, useThree as useThree18 } from "@react-three/fiber";
11294
11478
  import {
11295
11479
  memo,
11296
- useEffect as useEffect25,
11480
+ useEffect as useEffect26,
11297
11481
  useMemo as useMemo19,
11298
- useRef as useRef25,
11482
+ useRef as useRef26,
11299
11483
  useState as useState11
11300
11484
  } from "react";
11301
11485
  import {
@@ -11492,7 +11676,7 @@ function resolveTemplateUrl(template, address) {
11492
11676
  }
11493
11677
 
11494
11678
  // src/tile/tile.tsx
11495
- import { jsx as jsx21, jsxs as jsxs12 } from "react/jsx-runtime";
11679
+ import { jsx as jsx22, jsxs as jsxs12 } from "react/jsx-runtime";
11496
11680
  var MAX_LOD_UPDATE_INTERVAL_MS = 100;
11497
11681
  var FAST_ROTATION_THRESHOLD_RADIANS = Math.PI / 180;
11498
11682
  var FAST_FOV_THRESHOLD_DEGREES = 0.5;
@@ -11502,9 +11686,9 @@ var PREVIEW_RADIUS = CUBE_RADIUS + 0.05;
11502
11686
  var SHARED_TILE_GEOMETRY = new PlaneGeometry4(1, 1);
11503
11687
  function usePreviewTexture(url, anisotropy, onError) {
11504
11688
  const [texture, setTexture] = useState11(null);
11505
- const onErrorRef = useRef25(onError);
11689
+ const onErrorRef = useRef26(onError);
11506
11690
  onErrorRef.current = onError;
11507
- useEffect25(() => {
11691
+ useEffect26(() => {
11508
11692
  if (!url) {
11509
11693
  setTexture(null);
11510
11694
  return;
@@ -11541,7 +11725,7 @@ function usePreviewTexture(url, anisotropy, onError) {
11541
11725
  active = false;
11542
11726
  };
11543
11727
  }, [anisotropy, url]);
11544
- useEffect25(
11728
+ useEffect26(
11545
11729
  () => () => {
11546
11730
  texture?.dispose();
11547
11731
  },
@@ -11572,21 +11756,21 @@ function PreviewFace({
11572
11756
  uv.needsUpdate = true;
11573
11757
  return nextGeometry;
11574
11758
  }, [face, faceOrder]);
11575
- useEffect25(
11759
+ useEffect26(
11576
11760
  () => () => {
11577
11761
  geometry.dispose();
11578
11762
  },
11579
11763
  [geometry]
11580
11764
  );
11581
11765
  const transform = getFaceTransform(face, PREVIEW_RADIUS);
11582
- return /* @__PURE__ */ jsx21(
11766
+ return /* @__PURE__ */ jsx22(
11583
11767
  "mesh",
11584
11768
  {
11585
11769
  geometry,
11586
11770
  position: transform.position,
11587
11771
  renderOrder: -100,
11588
11772
  rotation: transform.rotation,
11589
- children: /* @__PURE__ */ jsx21(
11773
+ children: /* @__PURE__ */ jsx22(
11590
11774
  PanoBasicMaterial,
11591
11775
  {
11592
11776
  depthTest: false,
@@ -11602,7 +11786,7 @@ function PreviewCube({
11602
11786
  texture,
11603
11787
  faceOrder
11604
11788
  }) {
11605
- return CUBE_FACES.map((face) => /* @__PURE__ */ jsx21(
11789
+ return CUBE_FACES.map((face) => /* @__PURE__ */ jsx22(
11606
11790
  PreviewFace,
11607
11791
  {
11608
11792
  face,
@@ -11620,7 +11804,7 @@ function useManagedTexture(manager, key, url, address) {
11620
11804
  snapshot: manager.getSnapshot(key)
11621
11805
  }));
11622
11806
  const snapshot = managedState.manager === manager && managedState.key === key && managedState.url === url ? managedState.snapshot : manager.getSnapshot(key);
11623
- useEffect25(
11807
+ useEffect26(
11624
11808
  () => manager.acquire(key, url, address, (nextSnapshot) => {
11625
11809
  setManagedState({
11626
11810
  manager,
@@ -11647,14 +11831,14 @@ var TileMesh = memo(function TileMesh2({
11647
11831
  if (!snapshot.texture) {
11648
11832
  return null;
11649
11833
  }
11650
- return /* @__PURE__ */ jsx21("group", { position: transform.position, rotation: transform.rotation, children: /* @__PURE__ */ jsx21(
11834
+ return /* @__PURE__ */ jsx22("group", { position: transform.position, rotation: transform.rotation, children: /* @__PURE__ */ jsx22(
11651
11835
  "mesh",
11652
11836
  {
11653
11837
  geometry: SHARED_TILE_GEOMETRY,
11654
11838
  position: [layout.x, layout.y, 0],
11655
11839
  renderOrder,
11656
11840
  scale: [layout.width, layout.height, 1],
11657
- children: /* @__PURE__ */ jsx21(
11841
+ children: /* @__PURE__ */ jsx22(
11658
11842
  PanoBasicMaterial,
11659
11843
  {
11660
11844
  depthTest: false,
@@ -11671,7 +11855,7 @@ var TileLayerMeshes = memo(function TileLayerMeshes2({
11671
11855
  manager,
11672
11856
  resolveUrl
11673
11857
  }) {
11674
- return layer.addresses.map((address) => /* @__PURE__ */ jsx21(
11858
+ return layer.addresses.map((address) => /* @__PURE__ */ jsx22(
11675
11859
  TileMesh,
11676
11860
  {
11677
11861
  address,
@@ -11855,9 +12039,9 @@ function Tile({
11855
12039
  onPreviewError
11856
12040
  );
11857
12041
  const sharedManager = useSharedTileTextureManager();
11858
- const progressRef = useRef25(onLoadProgress);
11859
- const errorRef = useRef25(onTileError);
11860
- const levelChangeRef = useRef25(onLevelChange);
12042
+ const progressRef = useRef26(onLoadProgress);
12043
+ const errorRef = useRef26(onTileError);
12044
+ const levelChangeRef = useRef26(onLevelChange);
11861
12045
  progressRef.current = onLoadProgress;
11862
12046
  errorRef.current = onTileError;
11863
12047
  levelChangeRef.current = onLevelChange;
@@ -11882,7 +12066,7 @@ function Tile({
11882
12066
  ]
11883
12067
  );
11884
12068
  const manager = sharedManager ?? ownedManager;
11885
- useEffect25(() => {
12069
+ useEffect26(() => {
11886
12070
  manager.resume();
11887
12071
  return () => {
11888
12072
  if (manager === ownedManager) {
@@ -11892,11 +12076,11 @@ function Tile({
11892
12076
  queueMicrotask(() => manager.releaseUnused());
11893
12077
  };
11894
12078
  }, [manager, ownedManager]);
11895
- const readyRef = useRef25(false);
11896
- useEffect25(() => {
12079
+ const readyRef = useRef26(false);
12080
+ useEffect26(() => {
11897
12081
  readyRef.current = false;
11898
12082
  }, [effectivePreviewUrl]);
11899
- useEffect25(() => {
12083
+ useEffect26(() => {
11900
12084
  if (!previewTexture || readyRef.current) {
11901
12085
  return;
11902
12086
  }
@@ -11912,23 +12096,23 @@ function Tile({
11912
12096
  [baseUrl, resolveTileUrl, template]
11913
12097
  );
11914
12098
  const [layers, setLayers] = useState11([]);
11915
- const layerTokenRef = useRef25("");
11916
- const currentLevelRef = useRef25(1);
11917
- const lastUpdateAtRef = useRef25(-Infinity);
11918
- const visibilityDirtyRef = useRef25(true);
11919
- const lastVisibilityQuaternionRef = useRef25(camera.quaternion.clone());
11920
- const lastVisibilityFovRef = useRef25(Number.NaN);
11921
- const lastViewportRef = useRef25({ width: 0, height: 0, dpr: 0 });
11922
- const frustumRef = useRef25(new Frustum());
11923
- const projectionMatrixRef = useRef25(new Matrix4());
11924
- const visibilityCameraRef = useRef25(new PerspectiveCamera4());
11925
- useEffect25(() => {
12099
+ const layerTokenRef = useRef26("");
12100
+ const currentLevelRef = useRef26(1);
12101
+ const lastUpdateAtRef = useRef26(-Infinity);
12102
+ const visibilityDirtyRef = useRef26(true);
12103
+ const lastVisibilityQuaternionRef = useRef26(camera.quaternion.clone());
12104
+ const lastVisibilityFovRef = useRef26(Number.NaN);
12105
+ const lastViewportRef = useRef26({ width: 0, height: 0, dpr: 0 });
12106
+ const frustumRef = useRef26(new Frustum());
12107
+ const projectionMatrixRef = useRef26(new Matrix4());
12108
+ const visibilityCameraRef = useRef26(new PerspectiveCamera4());
12109
+ useEffect26(() => {
11926
12110
  currentLevelRef.current = 1;
11927
12111
  layerTokenRef.current = "";
11928
12112
  visibilityDirtyRef.current = true;
11929
12113
  setLayers([]);
11930
12114
  }, [manager, multiresToken]);
11931
- useEffect25(() => {
12115
+ useEffect26(() => {
11932
12116
  if (loadMode !== "preview") {
11933
12117
  return;
11934
12118
  }
@@ -12009,14 +12193,14 @@ function Tile({
12009
12193
  commitLayers(nextLayers);
12010
12194
  });
12011
12195
  return /* @__PURE__ */ jsxs12("group", { visible, children: [
12012
- previewTexture ? /* @__PURE__ */ jsx21(
12196
+ previewTexture ? /* @__PURE__ */ jsx22(
12013
12197
  PreviewCube,
12014
12198
  {
12015
12199
  texture: previewTexture,
12016
12200
  faceOrder: previewFaceOrder
12017
12201
  }
12018
12202
  ) : null,
12019
- layers.map((layer) => /* @__PURE__ */ jsx21(
12203
+ layers.map((layer) => /* @__PURE__ */ jsx22(
12020
12204
  TileLayerMeshes,
12021
12205
  {
12022
12206
  layer,
@@ -12029,7 +12213,7 @@ function Tile({
12029
12213
  }
12030
12214
 
12031
12215
  // src/scenes.tsx
12032
- import { jsx as jsx22, jsxs as jsxs13 } from "react/jsx-runtime";
12216
+ import { jsx as jsx23, jsxs as jsxs13 } from "react/jsx-runtime";
12033
12217
  function SceneSource({
12034
12218
  scene,
12035
12219
  visible,
@@ -12042,7 +12226,7 @@ function SceneSource({
12042
12226
  }
12043
12227
  switch (scene.type) {
12044
12228
  case "sphere":
12045
- return /* @__PURE__ */ jsx22(
12229
+ return /* @__PURE__ */ jsx23(
12046
12230
  Sphere,
12047
12231
  {
12048
12232
  src: scene.src,
@@ -12055,7 +12239,7 @@ function SceneSource({
12055
12239
  );
12056
12240
  case "tile": {
12057
12241
  const { id: _id, type: _type, ...tileProps } = scene;
12058
- return /* @__PURE__ */ jsx22(
12242
+ return /* @__PURE__ */ jsx23(
12059
12243
  Tile,
12060
12244
  {
12061
12245
  ...tileProps,
@@ -12079,9 +12263,9 @@ function SnapshotCapture({
12079
12263
  onCaptured
12080
12264
  }) {
12081
12265
  const { camera, gl, scene, size } = useThree19();
12082
- const capturedRequestRef = useRef26(0);
12083
- const renderTargetRef = useRef26(null);
12084
- useEffect26(
12266
+ const capturedRequestRef = useRef27(0);
12267
+ const renderTargetRef = useRef27(null);
12268
+ useEffect27(
12085
12269
  () => () => {
12086
12270
  renderTargetRef.current?.dispose();
12087
12271
  renderTargetRef.current = null;
@@ -12137,7 +12321,7 @@ function ScenesController({
12137
12321
  snapshotMaxPixels = 3686400,
12138
12322
  phaseRef: externalPhaseRef
12139
12323
  }) {
12140
- const controlsRef = useContext22(PanoramaViewContext);
12324
+ const controlsRef = useContext23(PanoramaViewContext);
12141
12325
  const manager = useSharedTileTextureManager();
12142
12326
  const transition = useMemo20(
12143
12327
  () => resolveTransition(transitionInput),
@@ -12160,13 +12344,13 @@ function ScenesController({
12160
12344
  const [transitionRunId, setTransitionRunId] = useState12(0);
12161
12345
  const [snapshot, setSnapshot] = useState12(null);
12162
12346
  const [recoveryKey, setRecoveryKey] = useState12(0);
12163
- const requestedSceneIdRef = useRef26(activeSceneId);
12164
- const captureReasonRef = useRef26("start");
12165
- const interactionReleaseRef = useRef26(null);
12166
- const slotsRef = useRef26(slots);
12167
- const phaseRef = useRef26(phase);
12168
- const liveSlotRef = useRef26(liveSlot);
12169
- const transitionFromRef = useRef26(initialScene);
12347
+ const requestedSceneIdRef = useRef27(activeSceneId);
12348
+ const captureReasonRef = useRef27("start");
12349
+ const interactionReleaseRef = useRef27(null);
12350
+ const slotsRef = useRef27(slots);
12351
+ const phaseRef = useRef27(phase);
12352
+ const liveSlotRef = useRef27(liveSlot);
12353
+ const transitionFromRef = useRef27(initialScene);
12170
12354
  slotsRef.current = slots;
12171
12355
  phaseRef.current = phase;
12172
12356
  if (externalPhaseRef) {
@@ -12191,7 +12375,7 @@ function ScenesController({
12191
12375
  setPendingSlot(nextSlot);
12192
12376
  setPhase("preloading");
12193
12377
  }, []);
12194
- useEffect26(() => {
12378
+ useEffect27(() => {
12195
12379
  const requested = sceneMap.get(activeSceneId);
12196
12380
  if (!requested) {
12197
12381
  reportError(activeSceneId, new Error(`Unknown panorama scene: ${activeSceneId}`));
@@ -12293,12 +12477,12 @@ function ScenesController({
12293
12477
  });
12294
12478
  }
12295
12479
  }, [onTransitionEnd, pendingSlot, releaseInteraction, snapshot, transition.preset]);
12296
- useEffect26(() => () => {
12480
+ useEffect27(() => () => {
12297
12481
  releaseInteraction();
12298
12482
  snapshot?.dispose();
12299
12483
  }, [releaseInteraction, snapshot]);
12300
12484
  const { gl } = useThree19();
12301
- useEffect26(() => {
12485
+ useEffect27(() => {
12302
12486
  const canvas = gl.domElement;
12303
12487
  const onContextLost = (event) => {
12304
12488
  event.preventDefault();
@@ -12323,7 +12507,7 @@ function ScenesController({
12323
12507
  const renderedScene = slots[liveSlot];
12324
12508
  const snapshotVisible = snapshot !== null && (phase === "transitioning" || phase === "recapturing" || phase === "preloading");
12325
12509
  return /* @__PURE__ */ jsxs13(Fragment6, { children: [
12326
- /* @__PURE__ */ jsx22(
12510
+ /* @__PURE__ */ jsx23(
12327
12511
  SnapshotCapture,
12328
12512
  {
12329
12513
  requestId: captureRequestId,
@@ -12335,7 +12519,7 @@ function ScenesController({
12335
12519
  const source = slots[slot];
12336
12520
  const isLive = slot === liveSlot;
12337
12521
  const isPending = slot === pendingSlot;
12338
- return /* @__PURE__ */ jsx22(
12522
+ return /* @__PURE__ */ jsx23(
12339
12523
  SceneSource,
12340
12524
  {
12341
12525
  scene: source,
@@ -12351,7 +12535,7 @@ function ScenesController({
12351
12535
  `${slot}:${source?.id ?? "empty"}:${recoveryKey}`
12352
12536
  );
12353
12537
  }),
12354
- snapshotVisible ? /* @__PURE__ */ jsx22(
12538
+ snapshotVisible ? /* @__PURE__ */ jsx23(
12355
12539
  TransitionOverlay,
12356
12540
  {
12357
12541
  snapshot,
@@ -12388,13 +12572,13 @@ function Scenes({
12388
12572
  },
12389
12573
  [isControlled, onActiveSceneIdChange]
12390
12574
  );
12391
- const scenesRef = useRef26(scenes);
12575
+ const scenesRef = useRef27(scenes);
12392
12576
  scenesRef.current = scenes;
12393
- const resolvedIdRef = useRef26(resolvedId);
12577
+ const resolvedIdRef = useRef27(resolvedId);
12394
12578
  resolvedIdRef.current = resolvedId;
12395
- const host = useContext22(ScenesHostContext);
12396
- const phaseRef = useRef26("idle");
12397
- useEffect26(() => {
12579
+ const host = useContext23(ScenesHostContext);
12580
+ const phaseRef = useRef27("idle");
12581
+ useEffect27(() => {
12398
12582
  if (!host) {
12399
12583
  return;
12400
12584
  }
@@ -12444,12 +12628,12 @@ function Scenes({
12444
12628
  }
12445
12629
  };
12446
12630
  }, [host, requestSceneChange]);
12447
- return /* @__PURE__ */ jsx22(
12631
+ return /* @__PURE__ */ jsx23(
12448
12632
  TileTextureManagerProvider,
12449
12633
  {
12450
12634
  maxTextureMemoryMb,
12451
12635
  maxConcurrentLoads: maxConcurrentTileLoads,
12452
- children: /* @__PURE__ */ jsx22(
12636
+ children: /* @__PURE__ */ jsx23(
12453
12637
  ScenesController,
12454
12638
  {
12455
12639
  ...rest,
@@ -12464,7 +12648,7 @@ function Scenes({
12464
12648
 
12465
12649
  // src/hotspot/image-hotspot.tsx
12466
12650
  import { useThree as useThree21 } from "@react-three/fiber";
12467
- import { useEffect as useEffect29, useRef as useRef28, useState as useState15 } from "react";
12651
+ import { useEffect as useEffect30, useRef as useRef29, useState as useState15 } from "react";
12468
12652
  import {
12469
12653
  ClampToEdgeWrapping as ClampToEdgeWrapping3,
12470
12654
  LinearFilter as LinearFilter6,
@@ -12476,11 +12660,11 @@ import {
12476
12660
  // src/hotspot/hotspot-anchor.tsx
12477
12661
  import { useFrame as useFrame13, useThree as useThree20 } from "@react-three/fiber";
12478
12662
  import {
12479
- useContext as useContext24,
12480
- useEffect as useEffect28,
12663
+ useContext as useContext25,
12664
+ useEffect as useEffect29,
12481
12665
  useLayoutEffect as useLayoutEffect4,
12482
12666
  useMemo as useMemo22,
12483
- useRef as useRef27,
12667
+ useRef as useRef28,
12484
12668
  useState as useState14
12485
12669
  } from "react";
12486
12670
  import {
@@ -12497,16 +12681,16 @@ import {
12497
12681
  } from "three";
12498
12682
 
12499
12683
  // src/hotspot/hotspot-tooltip.tsx
12500
- import { useEffect as useEffect27, useMemo as useMemo21, useState as useState13 } from "react";
12684
+ import { useEffect as useEffect28, useMemo as useMemo21, useState as useState13 } from "react";
12501
12685
 
12502
12686
  // src/webvr/stereo-html.tsx
12503
12687
  import { Html } from "@react-three/drei";
12504
- import { useContext as useContext23, useSyncExternalStore as useSyncExternalStore6 } from "react";
12505
- import { Fragment as Fragment7, jsx as jsx23, jsxs as jsxs14 } from "react/jsx-runtime";
12688
+ import { useContext as useContext24, useSyncExternalStore as useSyncExternalStore7 } from "react";
12689
+ import { Fragment as Fragment7, jsx as jsx24, jsxs as jsxs14 } from "react/jsx-runtime";
12506
12690
  function useFallbackStereoView() {
12507
- const runtime = useContext23(WebVRRuntimeContext);
12691
+ const runtime = useContext24(WebVRRuntimeContext);
12508
12692
  const host = runtime?.host ?? null;
12509
- const fallback = useSyncExternalStore6(
12693
+ const fallback = useSyncExternalStore7(
12510
12694
  (onStoreChange) => host ? subscribeWebVRHost(host, onStoreChange) : () => void 0,
12511
12695
  () => isFallbackStereoMode(host?.snapshot.mode ?? null),
12512
12696
  () => false
@@ -12527,10 +12711,10 @@ function stereoCalculatePosition(eye, stereoView) {
12527
12711
  function PanoHtml({ children, ...htmlProps }) {
12528
12712
  const stereoView = useFallbackStereoView();
12529
12713
  if (!stereoView) {
12530
- return /* @__PURE__ */ jsx23(Html, { ...htmlProps, children });
12714
+ return /* @__PURE__ */ jsx24(Html, { ...htmlProps, children });
12531
12715
  }
12532
12716
  return /* @__PURE__ */ jsxs14(Fragment7, { children: [
12533
- /* @__PURE__ */ jsx23(
12717
+ /* @__PURE__ */ jsx24(
12534
12718
  Html,
12535
12719
  {
12536
12720
  ...htmlProps,
@@ -12538,7 +12722,7 @@ function PanoHtml({ children, ...htmlProps }) {
12538
12722
  children
12539
12723
  }
12540
12724
  ),
12541
- /* @__PURE__ */ jsx23(
12725
+ /* @__PURE__ */ jsx24(
12542
12726
  Html,
12543
12727
  {
12544
12728
  ...htmlProps,
@@ -12551,7 +12735,7 @@ function PanoHtml({ children, ...htmlProps }) {
12551
12735
  }
12552
12736
 
12553
12737
  // src/hotspot/hotspot-tooltip.tsx
12554
- import { jsx as jsx24, jsxs as jsxs15 } from "react/jsx-runtime";
12738
+ import { jsx as jsx25, jsxs as jsxs15 } from "react/jsx-runtime";
12555
12739
  var DEFAULT_HOTSPOT_TOOLTIP_OFFSET = 12;
12556
12740
  var DEFAULT_HOTSPOT_TOOLTIP_APPEARANCE = {
12557
12741
  background: "rgba(22, 22, 22, 0.72)",
@@ -12621,7 +12805,7 @@ function HotspotTooltip({
12621
12805
  appearance
12622
12806
  }) {
12623
12807
  const [imageFailed, setImageFailed] = useState13(false);
12624
- useEffect27(() => {
12808
+ useEffect28(() => {
12625
12809
  setImageFailed(false);
12626
12810
  }, [content.image]);
12627
12811
  const showImage = Boolean(content.image) && !imageFailed;
@@ -12648,14 +12832,14 @@ function HotspotTooltip({
12648
12832
  if (!showImage && !content.text) {
12649
12833
  return null;
12650
12834
  }
12651
- return /* @__PURE__ */ jsx24(PanoHtml, { pointerEvents: "none", style: WRAPPER_STYLE, zIndexRange: [20, 10], children: /* @__PURE__ */ jsxs15(
12835
+ return /* @__PURE__ */ jsx25(PanoHtml, { pointerEvents: "none", style: WRAPPER_STYLE, zIndexRange: [20, 10], children: /* @__PURE__ */ jsxs15(
12652
12836
  "div",
12653
12837
  {
12654
12838
  className: "pano-hotspot-tooltip",
12655
12839
  role: "tooltip",
12656
12840
  style: bubbleStyle,
12657
12841
  children: [
12658
- showImage ? /* @__PURE__ */ jsx24(
12842
+ showImage ? /* @__PURE__ */ jsx25(
12659
12843
  "img",
12660
12844
  {
12661
12845
  alt: content.imageAlt ?? content.text ?? "",
@@ -12664,14 +12848,14 @@ function HotspotTooltip({
12664
12848
  src: content.image
12665
12849
  }
12666
12850
  ) : null,
12667
- content.text ? /* @__PURE__ */ jsx24("p", { className: "pano-hotspot-tooltip-text", children: content.text }) : null
12851
+ content.text ? /* @__PURE__ */ jsx25("p", { className: "pano-hotspot-tooltip-text", children: content.text }) : null
12668
12852
  ]
12669
12853
  }
12670
12854
  ) });
12671
12855
  }
12672
12856
 
12673
12857
  // src/hotspot/hotspot-anchor.tsx
12674
- import { jsx as jsx25, jsxs as jsxs16 } from "react/jsx-runtime";
12858
+ import { jsx as jsx26, jsxs as jsxs16 } from "react/jsx-runtime";
12675
12859
  var DEFAULT_FLOATING_DISTANCE = 10;
12676
12860
  var PANORAMA_RADIUS = DEFAULT_PANORAMA_RADIUS;
12677
12861
  var PANORAMA_SURFACE_INSET = 4;
@@ -13008,14 +13192,14 @@ function HotspotAnchor({
13008
13192
  onPositionChange,
13009
13193
  onDragEnd
13010
13194
  }) {
13011
- const controlsRef = useContext24(PanoramaViewContext);
13012
- const eventBus = useContext24(PanoEventBusContext);
13195
+ const controlsRef = useContext25(PanoramaViewContext);
13196
+ const eventBus = useContext25(PanoEventBusContext);
13013
13197
  const cursorApi = usePanoCursor();
13014
13198
  const { camera, size } = useThree20();
13015
- const groupRef = useRef27(null);
13016
- const tooltipAnchorRef = useRef27(null);
13017
- const dragStateRef = useRef27(null);
13018
- const suppressNextClickRef = useRef27(false);
13199
+ const groupRef = useRef28(null);
13200
+ const tooltipAnchorRef = useRef28(null);
13201
+ const dragStateRef = useRef28(null);
13202
+ const suppressNextClickRef = useRef28(false);
13019
13203
  const [hovered, setHovered] = useState14(false);
13020
13204
  const [dragging, setDragging] = useState14(false);
13021
13205
  const [pinned, setPinned] = useState14(false);
@@ -13072,14 +13256,14 @@ function HotspotAnchor({
13072
13256
  });
13073
13257
  const tooltipOpen = visible && tooltipContent !== null && isTooltipOpen(tooltipTrigger, hovered, focused, pinned);
13074
13258
  const cursorClaimId = hotspotCursorClaimId(id);
13075
- useEffect28(
13259
+ useEffect29(
13076
13260
  () => () => {
13077
13261
  dragStateRef.current?.releaseInteractionLock();
13078
13262
  dragStateRef.current = null;
13079
13263
  },
13080
13264
  []
13081
13265
  );
13082
- useEffect28(() => {
13266
+ useEffect29(() => {
13083
13267
  if (!cursorApi) {
13084
13268
  return;
13085
13269
  }
@@ -13101,14 +13285,14 @@ function HotspotAnchor({
13101
13285
  hovered,
13102
13286
  visible
13103
13287
  ]);
13104
- useEffect28(
13288
+ useEffect29(
13105
13289
  () => () => {
13106
13290
  cursorApi?.release(cursorClaimId);
13107
13291
  },
13108
13292
  [cursorApi, cursorClaimId]
13109
13293
  );
13110
- useEffect28(() => () => focusGeometry.dispose(), [focusGeometry]);
13111
- useEffect28(() => {
13294
+ useEffect29(() => () => focusGeometry.dispose(), [focusGeometry]);
13295
+ useEffect29(() => {
13112
13296
  if (tooltipTrigger !== "click") {
13113
13297
  setPinned(false);
13114
13298
  return;
@@ -13117,12 +13301,12 @@ function HotspotAnchor({
13117
13301
  setPinned(false);
13118
13302
  });
13119
13303
  }, [eventBus, tooltipTrigger]);
13120
- useEffect28(() => {
13304
+ useEffect29(() => {
13121
13305
  if (tooltipTrigger !== "hover") {
13122
13306
  setHovered(false);
13123
13307
  }
13124
13308
  }, [tooltipTrigger]);
13125
- useEffect28(() => {
13309
+ useEffect29(() => {
13126
13310
  if (acceptsPointer) {
13127
13311
  return;
13128
13312
  }
@@ -13311,18 +13495,18 @@ function HotspotAnchor({
13311
13495
  } : void 0,
13312
13496
  onPointerUp: acceptsPointer ? (event) => releasePointer(event, true) : void 0,
13313
13497
  children: [
13314
- focused ? focusContent ?? /* @__PURE__ */ jsx25(
13498
+ focused ? focusContent ?? /* @__PURE__ */ jsx26(
13315
13499
  "lineSegments",
13316
13500
  {
13317
13501
  geometry: focusGeometry,
13318
13502
  position: [0, 0, 0.01],
13319
13503
  renderOrder: renderOrder + 1,
13320
13504
  scale: [1.12, 1.12, 1],
13321
- children: /* @__PURE__ */ jsx25("lineBasicMaterial", { color: "#f5fbfc", depthTest: false })
13505
+ children: /* @__PURE__ */ jsx26("lineBasicMaterial", { color: "#f5fbfc", depthTest: false })
13322
13506
  }
13323
13507
  ) : null,
13324
13508
  children,
13325
- tooltipOpen && tooltipContent ? /* @__PURE__ */ jsx25("group", { ref: tooltipAnchorRef, children: /* @__PURE__ */ jsx25(
13509
+ tooltipOpen && tooltipContent ? /* @__PURE__ */ jsx26("group", { ref: tooltipAnchorRef, children: /* @__PURE__ */ jsx26(
13326
13510
  HotspotTooltip,
13327
13511
  {
13328
13512
  appearance: tooltipAppearance,
@@ -13343,7 +13527,7 @@ import {
13343
13527
  MeshBasicMaterial,
13344
13528
  Vector2 as Vector26
13345
13529
  } from "three";
13346
- import { jsx as jsx26, jsxs as jsxs17 } from "react/jsx-runtime";
13530
+ import { jsx as jsx27, jsxs as jsxs17 } from "react/jsx-runtime";
13347
13531
  var HOTSPOT_ALPHA_CUTOFF = 0.05;
13348
13532
  var SAMPLE_UV = new Vector26();
13349
13533
  var RAYCAST_HITS = [];
@@ -13446,8 +13630,8 @@ function HotspotPlane({
13446
13630
  opacity
13447
13631
  }) {
13448
13632
  return /* @__PURE__ */ jsxs17("mesh", { raycast: hotspotPlaneRaycast, children: [
13449
- /* @__PURE__ */ jsx26("planeGeometry", { args: [1, 1] }),
13450
- /* @__PURE__ */ jsx26(
13633
+ /* @__PURE__ */ jsx27("planeGeometry", { args: [1, 1] }),
13634
+ /* @__PURE__ */ jsx27(
13451
13635
  "meshBasicMaterial",
13452
13636
  {
13453
13637
  alphaTest: HOTSPOT_ALPHA_CUTOFF,
@@ -13463,15 +13647,15 @@ function HotspotPlane({
13463
13647
  }
13464
13648
 
13465
13649
  // src/hotspot/image-hotspot.tsx
13466
- import { jsx as jsx27 } from "react/jsx-runtime";
13650
+ import { jsx as jsx28 } from "react/jsx-runtime";
13467
13651
  function useHotspotImageTexture(src, onLoad, onError) {
13468
13652
  const gl = useThree21((state) => state.gl);
13469
13653
  const [texture, setTexture] = useState15(null);
13470
- const onLoadRef = useRef28(onLoad);
13471
- const onErrorRef = useRef28(onError);
13654
+ const onLoadRef = useRef29(onLoad);
13655
+ const onErrorRef = useRef29(onError);
13472
13656
  onLoadRef.current = onLoad;
13473
13657
  onErrorRef.current = onError;
13474
- useEffect29(() => {
13658
+ useEffect30(() => {
13475
13659
  let active = true;
13476
13660
  setTexture(null);
13477
13661
  if (!src) {
@@ -13509,7 +13693,7 @@ function useHotspotImageTexture(src, onLoad, onError) {
13509
13693
  active = false;
13510
13694
  };
13511
13695
  }, [gl, src]);
13512
- useEffect29(
13696
+ useEffect30(
13513
13697
  () => () => {
13514
13698
  texture?.dispose();
13515
13699
  },
@@ -13527,11 +13711,11 @@ function ImageHotspot({
13527
13711
  ...anchorProps
13528
13712
  }) {
13529
13713
  const texture = useHotspotImageTexture(src, onLoad, onError);
13530
- return /* @__PURE__ */ jsx27(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ jsx27(HotspotPlane, { map: texture, opacity }) });
13714
+ return /* @__PURE__ */ jsx28(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ jsx28(HotspotPlane, { map: texture, opacity }) });
13531
13715
  }
13532
13716
 
13533
13717
  // src/hotspot/polygon-hotspot.tsx
13534
- import { useEffect as useEffect30, useMemo as useMemo23, useRef as useRef30 } from "react";
13718
+ import { useEffect as useEffect31, useMemo as useMemo23, useRef as useRef31 } from "react";
13535
13719
  import {
13536
13720
  BufferGeometry,
13537
13721
  DoubleSide as DoubleSide5,
@@ -13546,13 +13730,13 @@ import {
13546
13730
  // src/hotspot/hotspot-stroke-line.tsx
13547
13731
  import { Line } from "@react-three/drei";
13548
13732
  import { useFrame as useFrame14, useThree as useThree22 } from "@react-three/fiber";
13549
- import { useLayoutEffect as useLayoutEffect5, useRef as useRef29 } from "react";
13733
+ import { useLayoutEffect as useLayoutEffect5, useRef as useRef30 } from "react";
13550
13734
  import {
13551
13735
  MathUtils as MathUtils8,
13552
13736
  PerspectiveCamera as PerspectiveCamera6,
13553
13737
  Vector3 as Vector314
13554
13738
  } from "three";
13555
- import { jsx as jsx28 } from "react/jsx-runtime";
13739
+ import { jsx as jsx29 } from "react/jsx-runtime";
13556
13740
  var LINE_WORLD_POSITION = new Vector314();
13557
13741
  function applyScreenSpaceDashScale(object, camera, viewportHeight) {
13558
13742
  const material = object?.material;
@@ -13583,7 +13767,7 @@ function HotspotStrokeLine({
13583
13767
  dashSize,
13584
13768
  gapSize
13585
13769
  }) {
13586
- const lineRef = useRef29(null);
13770
+ const lineRef = useRef30(null);
13587
13771
  const { camera, size } = useThree22();
13588
13772
  const dash = resolveDash(dashSize, gapSize);
13589
13773
  useLayoutEffect5(() => {
@@ -13598,7 +13782,7 @@ function HotspotStrokeLine({
13598
13782
  }
13599
13783
  applyScreenSpaceDashScale(lineRef.current, state.camera, state.size.height);
13600
13784
  });
13601
- return /* @__PURE__ */ jsx28(
13785
+ return /* @__PURE__ */ jsx29(
13602
13786
  Line,
13603
13787
  {
13604
13788
  ref: lineRef,
@@ -13620,7 +13804,7 @@ function HotspotStrokeLine({
13620
13804
  }
13621
13805
 
13622
13806
  // src/hotspot/polygon-hotspot.tsx
13623
- import { jsx as jsx29, jsxs as jsxs18 } from "react/jsx-runtime";
13807
+ import { jsx as jsx30, jsxs as jsxs18 } from "react/jsx-runtime";
13624
13808
  var POLYGON_RADIUS = 990;
13625
13809
  var MAX_FILL_SEGMENT_DEGREES = 7;
13626
13810
  function cloneVertices(vertices) {
@@ -13888,12 +14072,12 @@ function PolygonHotspot({
13888
14072
  [center, valid, vertices]
13889
14073
  );
13890
14074
  const resolvedStrokeOpacity = Math.max(0, Math.min(strokeOpacity, 1));
13891
- const startVerticesRef = useRef30(null);
14075
+ const startVerticesRef = useRef31(null);
13892
14076
  const issuesKey = issues.map((issue) => issue.code).join(",");
13893
- useEffect30(() => {
14077
+ useEffect31(() => {
13894
14078
  if (!valid) onInvalid?.(issues);
13895
14079
  }, [issues, issuesKey, onInvalid, valid]);
13896
- useEffect30(() => () => fillGeometry?.dispose(), [fillGeometry]);
14080
+ useEffect31(() => () => fillGeometry?.dispose(), [fillGeometry]);
13897
14081
  if (!valid || !center || !fillGeometry || !strokePoints || strokePoints.length < 2) {
13898
14082
  return null;
13899
14083
  }
@@ -13923,7 +14107,7 @@ function PolygonHotspot({
13923
14107
  draggable,
13924
14108
  interactive,
13925
14109
  useAngularScale: false,
13926
- focusContent: /* @__PURE__ */ jsx29(
14110
+ focusContent: /* @__PURE__ */ jsx30(
13927
14111
  HotspotStrokeLine,
13928
14112
  {
13929
14113
  color: "#75cbd3",
@@ -13945,7 +14129,7 @@ function PolygonHotspot({
13945
14129
  startVerticesRef.current = null;
13946
14130
  },
13947
14131
  children: [
13948
- /* @__PURE__ */ jsx29("mesh", { geometry: fillGeometry, renderOrder, children: /* @__PURE__ */ jsx29(
14132
+ /* @__PURE__ */ jsx30("mesh", { geometry: fillGeometry, renderOrder, children: /* @__PURE__ */ jsx30(
13949
14133
  "meshBasicMaterial",
13950
14134
  {
13951
14135
  color: fill,
@@ -13955,7 +14139,7 @@ function PolygonHotspot({
13955
14139
  transparent: true
13956
14140
  }
13957
14141
  ) }),
13958
- /* @__PURE__ */ jsx29(
14142
+ /* @__PURE__ */ jsx30(
13959
14143
  HotspotStrokeLine,
13960
14144
  {
13961
14145
  color: stroke,
@@ -13973,14 +14157,14 @@ function PolygonHotspot({
13973
14157
  }
13974
14158
 
13975
14159
  // src/hotspot/polyline-hotspot.tsx
13976
- import { useEffect as useEffect31, useMemo as useMemo24, useRef as useRef31 } from "react";
14160
+ import { useEffect as useEffect32, useMemo as useMemo24, useRef as useRef32 } from "react";
13977
14161
  import {
13978
14162
  MathUtils as MathUtils9,
13979
14163
  Matrix4 as Matrix44,
13980
14164
  Quaternion as Quaternion5,
13981
14165
  Vector3 as Vector316
13982
14166
  } from "three";
13983
- import { jsx as jsx30 } from "react/jsx-runtime";
14167
+ import { jsx as jsx31 } from "react/jsx-runtime";
13984
14168
  var POLYLINE_RADIUS = 990;
13985
14169
  var MAX_SEGMENT_DEGREES = 7;
13986
14170
  function cloneVertices2(vertices) {
@@ -14105,8 +14289,8 @@ function PolylineHotspot({
14105
14289
  [center, valid, vertices]
14106
14290
  );
14107
14291
  const opacity = Math.max(0, Math.min(strokeOpacity, 1));
14108
- const startVerticesRef = useRef31(null);
14109
- useEffect31(() => {
14292
+ const startVerticesRef = useRef32(null);
14293
+ useEffect32(() => {
14110
14294
  if (!valid) onInvalid?.(issues);
14111
14295
  }, [issues, onInvalid, valid]);
14112
14296
  if (!valid || !center || !linePoints || linePoints.length < 2) return null;
@@ -14120,7 +14304,7 @@ function PolylineHotspot({
14120
14304
  startPosition: event.startPosition
14121
14305
  });
14122
14306
  };
14123
- return /* @__PURE__ */ jsx30(
14307
+ return /* @__PURE__ */ jsx31(
14124
14308
  HotspotAnchor,
14125
14309
  {
14126
14310
  ...anchorProps,
@@ -14134,7 +14318,7 @@ function PolylineHotspot({
14134
14318
  renderOrder,
14135
14319
  draggable,
14136
14320
  useAngularScale: false,
14137
- focusContent: /* @__PURE__ */ jsx30(
14321
+ focusContent: /* @__PURE__ */ jsx31(
14138
14322
  HotspotStrokeLine,
14139
14323
  {
14140
14324
  color: "#75cbd3",
@@ -14155,7 +14339,7 @@ function PolylineHotspot({
14155
14339
  emitVerticesChange(event, onDragEnd);
14156
14340
  startVerticesRef.current = null;
14157
14341
  },
14158
- children: /* @__PURE__ */ jsx30(
14342
+ children: /* @__PURE__ */ jsx31(
14159
14343
  HotspotStrokeLine,
14160
14344
  {
14161
14345
  color: stroke,
@@ -14172,7 +14356,7 @@ function PolylineHotspot({
14172
14356
  }
14173
14357
 
14174
14358
  // src/hotspot/graphic-hotspot.tsx
14175
- import { useEffect as useEffect32, useRef as useRef32, useState as useState16 } from "react";
14359
+ import { useEffect as useEffect33, useRef as useRef33, useState as useState16 } from "react";
14176
14360
  import {
14177
14361
  CanvasTexture,
14178
14362
  ClampToEdgeWrapping as ClampToEdgeWrapping4,
@@ -14180,7 +14364,7 @@ import {
14180
14364
  LinearMipmapLinearFilter as LinearMipmapLinearFilter4,
14181
14365
  SRGBColorSpace as SRGBColorSpace6
14182
14366
  } from "three";
14183
- import { jsx as jsx31 } from "react/jsx-runtime";
14367
+ import { jsx as jsx32 } from "react/jsx-runtime";
14184
14368
  var GRAPHIC_TEXTURE_SIZE = 512;
14185
14369
  function resolveStrokeWidth(value) {
14186
14370
  return Number.isFinite(value) ? Math.max(value, 0) : 8;
@@ -14370,11 +14554,11 @@ function createGraphicTexture(graphic, aspectWidth, aspectHeight) {
14370
14554
  }
14371
14555
  function useGraphicTexture(graphic, aspectWidth, aspectHeight, onLoad, onError) {
14372
14556
  const [texture, setTexture] = useState16(null);
14373
- const onLoadRef = useRef32(onLoad);
14374
- const onErrorRef = useRef32(onError);
14557
+ const onLoadRef = useRef33(onLoad);
14558
+ const onErrorRef = useRef33(onError);
14375
14559
  onLoadRef.current = onLoad;
14376
14560
  onErrorRef.current = onError;
14377
- useEffect32(() => {
14561
+ useEffect33(() => {
14378
14562
  let nextTexture = null;
14379
14563
  try {
14380
14564
  nextTexture = createGraphicTexture(graphic, aspectWidth, aspectHeight);
@@ -14400,20 +14584,20 @@ function CanvasGraphicHotspot({
14400
14584
  ...anchorProps
14401
14585
  }) {
14402
14586
  const texture = useGraphicTexture(graphic, width, height, onLoad, onError);
14403
- return /* @__PURE__ */ jsx31(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ jsx31(HotspotPlane, { map: texture, opacity }) });
14587
+ return /* @__PURE__ */ jsx32(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ jsx32(HotspotPlane, { map: texture, opacity }) });
14404
14588
  }
14405
14589
  function GraphicHotspot(props) {
14406
14590
  const { graphic, ...restProps } = props;
14407
14591
  if (graphic.kind === "svg") {
14408
14592
  const imageProps = restProps;
14409
- return /* @__PURE__ */ jsx31(ImageHotspot, { ...imageProps, src: graphic.src });
14593
+ return /* @__PURE__ */ jsx32(ImageHotspot, { ...imageProps, src: graphic.src });
14410
14594
  }
14411
- return /* @__PURE__ */ jsx31(CanvasGraphicHotspot, { ...restProps, graphic });
14595
+ return /* @__PURE__ */ jsx32(CanvasGraphicHotspot, { ...restProps, graphic });
14412
14596
  }
14413
14597
 
14414
14598
  // src/hotspot/sequence-hotspot.tsx
14415
14599
  import { useFrame as useFrame15, useThree as useThree23 } from "@react-three/fiber";
14416
- import { useEffect as useEffect33, useRef as useRef33, useState as useState17 } from "react";
14600
+ import { useEffect as useEffect34, useRef as useRef34, useState as useState17 } from "react";
14417
14601
  import {
14418
14602
  ClampToEdgeWrapping as ClampToEdgeWrapping5,
14419
14603
  LinearFilter as LinearFilter8,
@@ -14421,7 +14605,7 @@ import {
14421
14605
  SRGBColorSpace as SRGBColorSpace7,
14422
14606
  TextureLoader as TextureLoader6
14423
14607
  } from "three";
14424
- import { jsx as jsx32 } from "react/jsx-runtime";
14608
+ import { jsx as jsx33 } from "react/jsx-runtime";
14425
14609
  var DEFAULT_SEQUENCE_FPS = 12;
14426
14610
  function resolveFps(value) {
14427
14611
  return Number.isFinite(value) && value > 0 ? value : DEFAULT_SEQUENCE_FPS;
@@ -14437,11 +14621,11 @@ function useSpriteTexture({
14437
14621
  }) {
14438
14622
  const gl = useThree23((state) => state.gl);
14439
14623
  const [texture, setTexture] = useState17(null);
14440
- const onErrorRef = useRef33(onError);
14441
- const onLoadProgressRef = useRef33(onLoadProgress);
14624
+ const onErrorRef = useRef34(onError);
14625
+ const onLoadProgressRef = useRef34(onLoadProgress);
14442
14626
  onErrorRef.current = onError;
14443
14627
  onLoadProgressRef.current = onLoadProgress;
14444
- useEffect33(() => {
14628
+ useEffect34(() => {
14445
14629
  let active = true;
14446
14630
  setTexture(null);
14447
14631
  if (!src) {
@@ -14482,7 +14666,7 @@ function useSpriteTexture({
14482
14666
  active = false;
14483
14667
  };
14484
14668
  }, [gl, id, src]);
14485
- useEffect33(
14669
+ useEffect34(
14486
14670
  () => () => {
14487
14671
  texture?.dispose();
14488
14672
  },
@@ -14512,23 +14696,23 @@ function SequenceHotspot({
14512
14696
  const frameCount = resolveFrameCount(requestedFrameCount);
14513
14697
  const safeFps = resolveFps(fps);
14514
14698
  const [frameIndex, setFrameIndex] = useState17(0);
14515
- const elapsedRef = useRef33(0);
14516
- const frameIndexRef = useRef33(0);
14517
- const endedRef = useRef33(false);
14518
- const lastPlaybackStateRef = useRef33(null);
14519
- const onFrameChangeRef = useRef33(onFrameChange);
14520
- const onPlaybackStateChangeRef = useRef33(onPlaybackStateChange);
14521
- const onEndedRef = useRef33(onEnded);
14699
+ const elapsedRef = useRef34(0);
14700
+ const frameIndexRef = useRef34(0);
14701
+ const endedRef = useRef34(false);
14702
+ const lastPlaybackStateRef = useRef34(null);
14703
+ const onFrameChangeRef = useRef34(onFrameChange);
14704
+ const onPlaybackStateChangeRef = useRef34(onPlaybackStateChange);
14705
+ const onEndedRef = useRef34(onEnded);
14522
14706
  onFrameChangeRef.current = onFrameChange;
14523
14707
  onPlaybackStateChangeRef.current = onPlaybackStateChange;
14524
14708
  onEndedRef.current = onEnded;
14525
- useEffect33(() => {
14709
+ useEffect34(() => {
14526
14710
  elapsedRef.current = 0;
14527
14711
  frameIndexRef.current = 0;
14528
14712
  endedRef.current = false;
14529
14713
  setFrameIndex(0);
14530
14714
  }, [frameCount, frameDirection, src]);
14531
- useEffect33(() => {
14715
+ useEffect34(() => {
14532
14716
  if (!texture) {
14533
14717
  return;
14534
14718
  }
@@ -14542,13 +14726,13 @@ function SequenceHotspot({
14542
14726
  );
14543
14727
  texture.needsUpdate = true;
14544
14728
  }, [frameCount, frameDirection, frameIndex, texture]);
14545
- useEffect33(() => {
14729
+ useEffect34(() => {
14546
14730
  if (!texture) {
14547
14731
  return;
14548
14732
  }
14549
14733
  onFrameChangeRef.current?.({ id, index: 0, src });
14550
14734
  }, [id, src, texture]);
14551
- useEffect33(() => {
14735
+ useEffect34(() => {
14552
14736
  if (!texture) {
14553
14737
  return;
14554
14738
  }
@@ -14597,12 +14781,12 @@ function SequenceHotspot({
14597
14781
  onFrameChangeRef.current?.({ id, index: nextIndex, src });
14598
14782
  }
14599
14783
  });
14600
- return /* @__PURE__ */ jsx32(HotspotAnchor, { ...anchorProps, id, height, width, children: /* @__PURE__ */ jsx32(HotspotPlane, { map: texture, opacity }) });
14784
+ return /* @__PURE__ */ jsx33(HotspotAnchor, { ...anchorProps, id, height, width, children: /* @__PURE__ */ jsx33(HotspotPlane, { map: texture, opacity }) });
14601
14785
  }
14602
14786
 
14603
14787
  // src/hotspot/video-hotspot.tsx
14604
14788
  import { useThree as useThree24 } from "@react-three/fiber";
14605
- import { useEffect as useEffect34, useRef as useRef34, useState as useState18 } from "react";
14789
+ import { useEffect as useEffect35, useRef as useRef35, useState as useState18 } from "react";
14606
14790
  import {
14607
14791
  ClampToEdgeWrapping as ClampToEdgeWrapping6,
14608
14792
  LinearFilter as LinearFilter9,
@@ -14611,7 +14795,7 @@ import {
14611
14795
  TextureLoader as TextureLoader7,
14612
14796
  VideoTexture as VideoTexture2
14613
14797
  } from "three";
14614
- import { jsx as jsx33 } from "react/jsx-runtime";
14798
+ import { jsx as jsx34 } from "react/jsx-runtime";
14615
14799
  function clampVolume2(volume) {
14616
14800
  if (!Number.isFinite(volume)) {
14617
14801
  return 1;
@@ -14621,9 +14805,9 @@ function clampVolume2(volume) {
14621
14805
  function usePosterTexture2(id, poster, onError) {
14622
14806
  const gl = useThree24((state) => state.gl);
14623
14807
  const [texture, setTexture] = useState18(null);
14624
- const onErrorRef = useRef34(onError);
14808
+ const onErrorRef = useRef35(onError);
14625
14809
  onErrorRef.current = onError;
14626
- useEffect34(() => {
14810
+ useEffect35(() => {
14627
14811
  let active = true;
14628
14812
  setTexture(null);
14629
14813
  if (!poster) {
@@ -14660,7 +14844,7 @@ function usePosterTexture2(id, poster, onError) {
14660
14844
  active = false;
14661
14845
  };
14662
14846
  }, [gl, id, poster]);
14663
- useEffect34(
14847
+ useEffect35(
14664
14848
  () => () => {
14665
14849
  texture?.dispose();
14666
14850
  },
@@ -14679,13 +14863,13 @@ function useVideoResource({
14679
14863
  src
14680
14864
  }) {
14681
14865
  const [resource, setResource] = useState18(null);
14682
- const onEndedRef = useRef34(onEnded);
14683
- const onErrorRef = useRef34(onError);
14684
- const onPlaybackStateChangeRef = useRef34(onPlaybackStateChange);
14866
+ const onEndedRef = useRef35(onEnded);
14867
+ const onErrorRef = useRef35(onError);
14868
+ const onPlaybackStateChangeRef = useRef35(onPlaybackStateChange);
14685
14869
  onEndedRef.current = onEnded;
14686
14870
  onErrorRef.current = onError;
14687
14871
  onPlaybackStateChangeRef.current = onPlaybackStateChange;
14688
- useEffect34(() => {
14872
+ useEffect35(() => {
14689
14873
  if (!src) {
14690
14874
  setResource(null);
14691
14875
  return;
@@ -14695,7 +14879,12 @@ function useVideoResource({
14695
14879
  if (crossOrigin !== void 0) {
14696
14880
  video.crossOrigin = crossOrigin;
14697
14881
  }
14698
- video.playsInline = playsInline ?? true;
14882
+ const inline = playsInline ?? true;
14883
+ video.playsInline = inline;
14884
+ if (inline) {
14885
+ video.setAttribute("playsinline", "true");
14886
+ video.setAttribute("webkit-playsinline", "true");
14887
+ }
14699
14888
  video.poster = poster ?? "";
14700
14889
  const texture = new VideoTexture2(video);
14701
14890
  texture.colorSpace = SRGBColorSpace8;
@@ -14775,6 +14964,7 @@ function VideoHotspot({
14775
14964
  onError,
14776
14965
  ...anchorProps
14777
14966
  }) {
14967
+ usePanoMediaActivationIntent(playing);
14778
14968
  const resource = useVideoResource({
14779
14969
  crossOrigin,
14780
14970
  id,
@@ -14786,11 +14976,11 @@ function VideoHotspot({
14786
14976
  src
14787
14977
  });
14788
14978
  const posterTexture = usePosterTexture2(id, poster, onError);
14789
- const onPlaybackErrorRef = useRef34(onPlaybackError);
14790
- const onPlaybackStateChangeRef = useRef34(onPlaybackStateChange);
14979
+ const onPlaybackErrorRef = useRef35(onPlaybackError);
14980
+ const onPlaybackStateChangeRef = useRef35(onPlaybackStateChange);
14791
14981
  onPlaybackErrorRef.current = onPlaybackError;
14792
14982
  onPlaybackStateChangeRef.current = onPlaybackStateChange;
14793
- useEffect34(() => {
14983
+ useEffect35(() => {
14794
14984
  if (!resource) {
14795
14985
  return;
14796
14986
  }
@@ -14798,9 +14988,16 @@ function VideoHotspot({
14798
14988
  resource.video.muted = muted;
14799
14989
  resource.video.volume = clampVolume2(volume);
14800
14990
  resource.video.playsInline = playsInline;
14991
+ if (playsInline) {
14992
+ resource.video.setAttribute("playsinline", "true");
14993
+ resource.video.setAttribute("webkit-playsinline", "true");
14994
+ } else {
14995
+ resource.video.removeAttribute("playsinline");
14996
+ resource.video.removeAttribute("webkit-playsinline");
14997
+ }
14801
14998
  resource.video.preload = preload;
14802
14999
  }, [loop, muted, playsInline, preload, resource, volume]);
14803
- useEffect34(() => {
15000
+ useEffect35(() => {
14804
15001
  if (!resource) {
14805
15002
  return;
14806
15003
  }
@@ -14823,12 +15020,12 @@ function VideoHotspot({
14823
15020
  };
14824
15021
  }, [playing, resource]);
14825
15022
  const activeTexture = resource?.ready ? resource.texture : posterTexture;
14826
- return /* @__PURE__ */ jsx33(HotspotAnchor, { ...anchorProps, id, height, width, children: /* @__PURE__ */ jsx33(HotspotPlane, { map: activeTexture, opacity }) });
15023
+ return /* @__PURE__ */ jsx34(HotspotAnchor, { ...anchorProps, id, height, width, children: /* @__PURE__ */ jsx34(HotspotPlane, { map: activeTexture, opacity }) });
14827
15024
  }
14828
15025
 
14829
15026
  // src/hotspot/audio-hotspot.tsx
14830
15027
  import { useFrame as useFrame16, useThree as useThree25 } from "@react-three/fiber";
14831
- import { useEffect as useEffect35, useRef as useRef35, useState as useState19 } from "react";
15028
+ import { useEffect as useEffect36, useRef as useRef36, useState as useState19 } from "react";
14832
15029
  import {
14833
15030
  CanvasTexture as CanvasTexture2,
14834
15031
  ClampToEdgeWrapping as ClampToEdgeWrapping7,
@@ -14837,7 +15034,7 @@ import {
14837
15034
  SRGBColorSpace as SRGBColorSpace9,
14838
15035
  TextureLoader as TextureLoader8
14839
15036
  } from "three";
14840
- import { jsx as jsx34 } from "react/jsx-runtime";
15037
+ import { jsx as jsx35 } from "react/jsx-runtime";
14841
15038
  var SPEAKER_TEXTURE_SIZE = 512;
14842
15039
  function paintSpeakerBody(context, center) {
14843
15040
  context.fillStyle = "#f5fbfc";
@@ -14902,7 +15099,7 @@ function createSpeakerTexture(state) {
14902
15099
  }
14903
15100
  function useSpeakerTextures(enabled) {
14904
15101
  const [textures, setTextures] = useState19({ playing: null, stopped: null });
14905
- useEffect35(() => {
15102
+ useEffect36(() => {
14906
15103
  if (!enabled) {
14907
15104
  setTextures({ playing: null, stopped: null });
14908
15105
  return;
@@ -14920,9 +15117,9 @@ function useSpeakerTextures(enabled) {
14920
15117
  function useIconTexture(icon, enabled, onError, id) {
14921
15118
  const gl = useThree25((state) => state.gl);
14922
15119
  const [texture, setTexture] = useState19(null);
14923
- const onErrorRef = useRef35(onError);
15120
+ const onErrorRef = useRef36(onError);
14924
15121
  onErrorRef.current = onError;
14925
- useEffect35(() => {
15122
+ useEffect36(() => {
14926
15123
  let active = true;
14927
15124
  setTexture(null);
14928
15125
  if (!enabled || !icon) {
@@ -14959,7 +15156,7 @@ function useIconTexture(icon, enabled, onError, id) {
14959
15156
  active = false;
14960
15157
  };
14961
15158
  }, [enabled, gl, icon, id]);
14962
- useEffect35(
15159
+ useEffect36(
14963
15160
  () => () => {
14964
15161
  texture?.dispose();
14965
15162
  },
@@ -14979,12 +15176,12 @@ function useAudioHowl({
14979
15176
  src
14980
15177
  }) {
14981
15178
  const [howl, setHowl] = useState19(null);
14982
- const playingRef = useRef35(playing);
14983
- const loopRef = useRef35(loop ?? false);
14984
- const onEndedRef = useRef35(onEnded);
14985
- const onErrorRef = useRef35(onError);
14986
- const onPlaybackErrorRef = useRef35(onPlaybackError);
14987
- const onPlaybackStateChangeRef = useRef35(onPlaybackStateChange);
15179
+ const playingRef = useRef36(playing);
15180
+ const loopRef = useRef36(loop ?? false);
15181
+ const onEndedRef = useRef36(onEnded);
15182
+ const onErrorRef = useRef36(onError);
15183
+ const onPlaybackErrorRef = useRef36(onPlaybackError);
15184
+ const onPlaybackStateChangeRef = useRef36(onPlaybackStateChange);
14988
15185
  playingRef.current = playing;
14989
15186
  loopRef.current = loop ?? false;
14990
15187
  onEndedRef.current = onEnded;
@@ -14992,7 +15189,7 @@ function useAudioHowl({
14992
15189
  onPlaybackErrorRef.current = onPlaybackError;
14993
15190
  onPlaybackStateChangeRef.current = onPlaybackStateChange;
14994
15191
  const sourcesKey = sourceList(src).join("\0");
14995
- useEffect35(() => {
15192
+ useEffect36(() => {
14996
15193
  const sources = sourcesKey.length > 0 ? sourcesKey.split("\0") : [];
14997
15194
  if (sources.length === 0) {
14998
15195
  setHowl(null);
@@ -15029,7 +15226,7 @@ function useAudioHowl({
15029
15226
  handle.dispose();
15030
15227
  };
15031
15228
  }, [crossOrigin, id, sourcesKey]);
15032
- useEffect35(() => {
15229
+ useEffect36(() => {
15033
15230
  howl?.loop(loop ?? false);
15034
15231
  }, [howl, loop]);
15035
15232
  return howl;
@@ -15056,6 +15253,7 @@ function AudioHotspot({
15056
15253
  onError,
15057
15254
  ...anchorProps
15058
15255
  }) {
15256
+ usePanoMediaActivationIntent(playing);
15059
15257
  const camera = useThree25((state) => state.camera);
15060
15258
  const howl = useAudioHowl({
15061
15259
  crossOrigin,
@@ -15072,15 +15270,15 @@ function AudioHotspot({
15072
15270
  const stoppedIconTexture = useIconTexture(icon, marker, onError, id);
15073
15271
  const playingIconTexture = useIconTexture(playingIcon, marker, onError, id);
15074
15272
  const markerTexture = playing ? playingIconTexture ?? stoppedIconTexture ?? speakerTextures.playing : stoppedIconTexture ?? speakerTextures.stopped;
15075
- const playingRef = useRef35(playing);
15273
+ const playingRef = useRef36(playing);
15076
15274
  playingRef.current = playing;
15077
- const mutedRef = useRef35(muted);
15078
- const volumeRef = useRef35(volume);
15079
- const rangeRef = useRef35(range);
15275
+ const mutedRef = useRef36(muted);
15276
+ const volumeRef = useRef36(volume);
15277
+ const rangeRef = useRef36(range);
15080
15278
  mutedRef.current = muted;
15081
15279
  volumeRef.current = volume;
15082
15280
  rangeRef.current = range;
15083
- useEffect35(() => {
15281
+ useEffect36(() => {
15084
15282
  if (!howl) {
15085
15283
  return;
15086
15284
  }
@@ -15090,7 +15288,7 @@ function AudioHotspot({
15090
15288
  }
15091
15289
  howl.play();
15092
15290
  }, [howl, playing]);
15093
- useEffect35(() => {
15291
+ useEffect36(() => {
15094
15292
  if (!howl || !pauseWhenHidden) {
15095
15293
  return;
15096
15294
  }
@@ -15121,11 +15319,11 @@ function AudioHotspot({
15121
15319
  howl.mute(mutedRef.current);
15122
15320
  howl.volume(clampAudioVolume(volumeRef.current) * spatial.gain);
15123
15321
  });
15124
- return /* @__PURE__ */ jsx34(HotspotAnchor, { ...anchorProps, id, height, width, children: marker ? /* @__PURE__ */ jsx34(HotspotPlane, { map: markerTexture, opacity }) : null });
15322
+ return /* @__PURE__ */ jsx35(HotspotAnchor, { ...anchorProps, id, height, width, children: marker ? /* @__PURE__ */ jsx35(HotspotPlane, { map: markerTexture, opacity }) : null });
15125
15323
  }
15126
15324
 
15127
15325
  // src/hotspot/text-hotspot.tsx
15128
- import { useEffect as useEffect36, useRef as useRef36, useState as useState20 } from "react";
15326
+ import { useEffect as useEffect37, useRef as useRef37, useState as useState20 } from "react";
15129
15327
  import {
15130
15328
  CanvasTexture as CanvasTexture3,
15131
15329
  ClampToEdgeWrapping as ClampToEdgeWrapping8,
@@ -15133,7 +15331,7 @@ import {
15133
15331
  LinearMipmapLinearFilter as LinearMipmapLinearFilter8,
15134
15332
  SRGBColorSpace as SRGBColorSpace10
15135
15333
  } from "three";
15136
- import { jsx as jsx35 } from "react/jsx-runtime";
15334
+ import { jsx as jsx36 } from "react/jsx-runtime";
15137
15335
  var TEXT_TEXTURE_LONG_SIDE = 1024;
15138
15336
  var DEFAULT_FONT_FAMILY = "system-ui, sans-serif";
15139
15337
  var DEFAULT_FONT_SIZE = 96;
@@ -15354,11 +15552,11 @@ function createTextTexture(text, width, height, style) {
15354
15552
  }
15355
15553
  function useTextTexture(text, width, height, style, onLoad, onError) {
15356
15554
  const [texture, setTexture] = useState20(null);
15357
- const onLoadRef = useRef36(onLoad);
15358
- const onErrorRef = useRef36(onError);
15555
+ const onLoadRef = useRef37(onLoad);
15556
+ const onErrorRef = useRef37(onError);
15359
15557
  onLoadRef.current = onLoad;
15360
15558
  onErrorRef.current = onError;
15361
- useEffect36(() => {
15559
+ useEffect37(() => {
15362
15560
  let cancelled = false;
15363
15561
  let nextTexture = null;
15364
15562
  const run = async () => {
@@ -15451,13 +15649,13 @@ function TextHotspot({
15451
15649
  whiteSpace
15452
15650
  };
15453
15651
  const texture = useTextTexture(text, width, height, style, onLoad, onError);
15454
- return /* @__PURE__ */ jsx35(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ jsx35(HotspotPlane, { map: texture, opacity }) });
15652
+ return /* @__PURE__ */ jsx36(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ jsx36(HotspotPlane, { map: texture, opacity }) });
15455
15653
  }
15456
15654
 
15457
15655
  // src/hotspot/iframe-hotspot.tsx
15458
15656
  import { Html as Html2 } from "@react-three/drei";
15459
15657
  import { DoubleSide as DoubleSide6 } from "three";
15460
- import { jsx as jsx36, jsxs as jsxs19 } from "react/jsx-runtime";
15658
+ import { jsx as jsx37, jsxs as jsxs19 } from "react/jsx-runtime";
15461
15659
  var IFRAME_LONG_SIDE = 800;
15462
15660
  var CSS3D_DISTANCE_FACTOR = 400;
15463
15661
  var DEFAULT_SANDBOX = "allow-scripts allow-popups allow-forms";
@@ -15524,8 +15722,8 @@ function IframeHotspot({
15524
15722
  width,
15525
15723
  children: [
15526
15724
  /* @__PURE__ */ jsxs19("mesh", { children: [
15527
- /* @__PURE__ */ jsx36("planeGeometry", { args: [1, 1] }),
15528
- /* @__PURE__ */ jsx36(
15725
+ /* @__PURE__ */ jsx37("planeGeometry", { args: [1, 1] }),
15726
+ /* @__PURE__ */ jsx37(
15529
15727
  "meshBasicMaterial",
15530
15728
  {
15531
15729
  depthWrite: false,
@@ -15536,7 +15734,7 @@ function IframeHotspot({
15536
15734
  }
15537
15735
  )
15538
15736
  ] }),
15539
- /* @__PURE__ */ jsx36(
15737
+ /* @__PURE__ */ jsx37(
15540
15738
  Html2,
15541
15739
  {
15542
15740
  distanceFactor: CSS3D_DISTANCE_FACTOR,
@@ -15551,7 +15749,7 @@ function IframeHotspot({
15551
15749
  },
15552
15750
  transform: true,
15553
15751
  zIndexRange: [10, 0],
15554
- children: /* @__PURE__ */ jsx36(
15752
+ children: /* @__PURE__ */ jsx37(
15555
15753
  "iframe",
15556
15754
  {
15557
15755
  allow,