@ericchen1990/pano-view 3.1.3 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -2278,6 +2278,7 @@ __export(index_exports, {
2278
2278
  Scenes: () => Scenes,
2279
2279
  SequenceHotspot: () => SequenceHotspot,
2280
2280
  Sphere: () => Sphere,
2281
+ SphereTile: () => SphereTile,
2281
2282
  TextHotspot: () => TextHotspot,
2282
2283
  Tile: () => Tile,
2283
2284
  TouchControls: () => TouchControls,
@@ -3786,7 +3787,9 @@ var DEFAULT_PANO_FILTER_INTENSITY = 1;
3786
3787
  var DEFAULT_PANO_FILTER_SNAPSHOT = {
3787
3788
  preset: "none",
3788
3789
  intensity: DEFAULT_PANO_FILTER_INTENSITY,
3789
- enabled: true
3790
+ enabled: true,
3791
+ colorMatrix: null,
3792
+ colorMatrixScope: "panorama"
3790
3793
  };
3791
3794
  function clampPanoFilterIntensity(value) {
3792
3795
  if (!Number.isFinite(value)) {
@@ -3795,15 +3798,17 @@ function clampPanoFilterIntensity(value) {
3795
3798
  return Math.max(0, Math.min(value, 1));
3796
3799
  }
3797
3800
  function resolvePanoFilterSnapshot(input) {
3801
+ if (input.colorMatrix && (input.colorMatrix.length !== 20 || input.colorMatrix.some((value) => !Number.isFinite(value)))) {
3802
+ throw new Error("colorMatrix must contain 20 finite numbers");
3803
+ }
3798
3804
  return {
3805
+ colorMatrix: input.colorMatrix ? [...input.colorMatrix] : null,
3806
+ colorMatrixScope: input.colorMatrixScope ?? "panorama",
3799
3807
  preset: input.preset ?? "none",
3800
3808
  intensity: clampPanoFilterIntensity(input.intensity),
3801
3809
  enabled: input.enabled !== false
3802
3810
  };
3803
3811
  }
3804
- function isPanoFilterActive(snapshot) {
3805
- return snapshot.enabled && snapshot.preset !== "none";
3806
- }
3807
3812
 
3808
3813
  // src/pano-filter/host.ts
3809
3814
  var PanoFilterHostContext = (0, import_react10.createContext)(null);
@@ -8055,15 +8060,23 @@ var import_react28 = require("react");
8055
8060
  function PanoFilter({
8056
8061
  preset = "none",
8057
8062
  intensity,
8058
- enabled = true
8063
+ enabled = true,
8064
+ colorMatrix,
8065
+ colorMatrixScope
8059
8066
  }) {
8060
8067
  const host = (0, import_react28.useContext)(PanoFilterHostContext);
8061
8068
  if (!host) {
8062
8069
  throw new Error("<PanoFilter> must be rendered inside <PanoViewer>.");
8063
8070
  }
8064
8071
  const snapshot = (0, import_react28.useMemo)(
8065
- () => resolvePanoFilterSnapshot({ preset, intensity, enabled }),
8066
- [enabled, intensity, preset]
8072
+ () => resolvePanoFilterSnapshot({
8073
+ preset,
8074
+ intensity,
8075
+ enabled,
8076
+ colorMatrix,
8077
+ colorMatrixScope
8078
+ }),
8079
+ [enabled, intensity, preset, colorMatrix, colorMatrixScope]
8067
8080
  );
8068
8081
  (0, import_react28.useEffect)(() => {
8069
8082
  claimPanoFilter(host);
@@ -9684,10 +9697,10 @@ function usePanoViewer() {
9684
9697
  return (0, import_react35.useMemo)(() => ({ ref, ...handle }), [handle]);
9685
9698
  }
9686
9699
 
9687
- // src/sphere.tsx
9700
+ // src/sphere-tile/sphere-tile.tsx
9688
9701
  var import_fiber15 = require("@react-three/fiber");
9689
- var import_react37 = require("react");
9690
- var import_three10 = require("three");
9702
+ var import_react38 = require("react");
9703
+ var import_three14 = require("three");
9691
9704
 
9692
9705
  // src/asset-url.ts
9693
9706
  function isAbsoluteAssetUrl(url) {
@@ -9712,6 +9725,7 @@ function resolveUrlAgainstFile(fileUrl, path) {
9712
9725
 
9713
9726
  // src/pano-filter/pano-basic-material.tsx
9714
9727
  var import_react36 = require("react");
9728
+ var import_three10 = require("three");
9715
9729
 
9716
9730
  // src/pano-filter/shaders.ts
9717
9731
  var GLSL_FILTER_COMMON = `
@@ -9860,77 +9874,327 @@ ${applyPanoFilterFunction(panoFilterBody(preset))}`
9860
9874
  diffuseColor.rgb = mix(diffuseColor.rgb, applyPanoFilter(diffuseColor.rgb), clamp(uPanoFilterIntensity, 0.0, 1.0));`
9861
9875
  );
9862
9876
  }
9877
+ function injectPanoColorMatrixShader(shader) {
9878
+ shader.fragmentShader = shader.fragmentShader.replace(
9879
+ "#include <common>",
9880
+ `#include <common>
9881
+ uniform mat4 uPanoColorMatrix;
9882
+ uniform vec4 uPanoColorOffset;
9883
+ uniform float uPanoColorMatrixIntensity;`
9884
+ ).replace(
9885
+ "#include <colorspace_fragment>",
9886
+ `#include <colorspace_fragment>
9887
+ gl_FragColor = mix(gl_FragColor, clamp(uPanoColorMatrix * gl_FragColor + uPanoColorOffset, 0.0, 1.0), uPanoColorMatrixIntensity);`
9888
+ );
9889
+ }
9863
9890
 
9864
9891
  // src/pano-filter/pano-basic-material.tsx
9865
9892
  var import_jsx_runtime14 = require("react/jsx-runtime");
9893
+ function matrixUniforms(matrix) {
9894
+ return {
9895
+ matrix: new import_three10.Matrix4().set(
9896
+ matrix[0],
9897
+ matrix[1],
9898
+ matrix[2],
9899
+ matrix[3],
9900
+ matrix[5],
9901
+ matrix[6],
9902
+ matrix[7],
9903
+ matrix[8],
9904
+ matrix[10],
9905
+ matrix[11],
9906
+ matrix[12],
9907
+ matrix[13],
9908
+ matrix[15],
9909
+ matrix[16],
9910
+ matrix[17],
9911
+ matrix[18]
9912
+ ),
9913
+ offset: new import_three10.Vector4(matrix[4], matrix[9], matrix[14], matrix[19])
9914
+ };
9915
+ }
9866
9916
  function PanoBasicMaterial({
9867
- map,
9868
- side,
9869
- depthTest,
9870
- depthWrite,
9871
- toneMapped = false
9917
+ target = "panorama",
9918
+ ...props
9872
9919
  }) {
9873
9920
  const snapshot = usePanoFilterSnapshot();
9874
- const materialRef = (0, import_react36.useRef)(null);
9875
- const intensityRef = (0, import_react36.useRef)(snapshot.intensity);
9876
- const intensityUniformRef = (0, import_react36.useRef)(null);
9877
- intensityRef.current = snapshot.intensity;
9878
- const active = isPanoFilterActive(snapshot);
9879
- const preset = snapshot.preset;
9921
+ const preset = snapshot.enabled && target === "panorama" ? snapshot.preset : "none";
9922
+ const matrix = snapshot.enabled && (target === "panorama" || snapshot.colorMatrixScope === "all") ? snapshot.colorMatrix : null;
9923
+ const hasMatrix = matrix !== null;
9924
+ const currentRef = (0, import_react36.useRef)({ matrix, intensity: snapshot.intensity });
9925
+ currentRef.current = { matrix, intensity: snapshot.intensity };
9926
+ const shaderRef = (0, import_react36.useRef)(null);
9880
9927
  const onBeforeCompile = (0, import_react36.useMemo)(() => {
9881
- if (!active || preset === "none") {
9882
- return void 0;
9883
- }
9884
9928
  const compile = (shader) => {
9885
- injectPanoFilterShader(shader, preset);
9886
- const intensityUniform = shader.uniforms.uPanoFilterIntensity;
9887
- intensityUniform.value = intensityRef.current;
9888
- intensityUniformRef.current = intensityUniform;
9889
- const material = materialRef.current;
9890
- if (material) {
9891
- material.userData.uPanoFilterIntensity = intensityUniform;
9929
+ shaderRef.current = shader;
9930
+ if (preset !== "none") {
9931
+ injectPanoFilterShader(shader, preset);
9932
+ shader.uniforms.uPanoFilterIntensity.value = currentRef.current.intensity;
9933
+ }
9934
+ if (hasMatrix && currentRef.current.matrix) {
9935
+ injectPanoColorMatrixShader(shader);
9936
+ const values = matrixUniforms(currentRef.current.matrix);
9937
+ shader.uniforms.uPanoColorMatrix = { value: values.matrix };
9938
+ shader.uniforms.uPanoColorOffset = { value: values.offset };
9939
+ shader.uniforms.uPanoColorMatrixIntensity = {
9940
+ value: currentRef.current.intensity
9941
+ };
9892
9942
  }
9893
9943
  };
9894
- compile.toString = () => `pano-filter:${preset}`;
9944
+ compile.toString = () => `pano-filter:${preset}:matrix:${hasMatrix}`;
9895
9945
  return compile;
9896
- }, [active, preset]);
9897
- (0, import_react36.useLayoutEffect)(() => {
9898
- if (!active) {
9899
- intensityUniformRef.current = null;
9900
- }
9901
- const material = materialRef.current;
9902
- if (!material) {
9903
- return;
9904
- }
9905
- material.needsUpdate = true;
9906
- }, [active, preset]);
9946
+ }, [preset, hasMatrix]);
9907
9947
  (0, import_react36.useLayoutEffect)(() => {
9908
- if (intensityUniformRef.current) {
9909
- intensityUniformRef.current.value = snapshot.intensity;
9910
- }
9911
- }, [snapshot.intensity]);
9948
+ const shader = shaderRef.current;
9949
+ if (!shader) return;
9950
+ if (shader.uniforms.uPanoFilterIntensity)
9951
+ shader.uniforms.uPanoFilterIntensity.value = snapshot.intensity;
9952
+ if (shader.uniforms.uPanoColorMatrix && matrix) {
9953
+ const values = matrixUniforms(matrix);
9954
+ shader.uniforms.uPanoColorMatrix.value = values.matrix;
9955
+ shader.uniforms.uPanoColorOffset.value = values.offset;
9956
+ shader.uniforms.uPanoColorMatrixIntensity.value = snapshot.intensity;
9957
+ }
9958
+ }, [matrix, snapshot.intensity]);
9912
9959
  return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
9913
9960
  "meshBasicMaterial",
9914
9961
  {
9915
- ref: materialRef,
9916
- depthTest,
9917
- depthWrite,
9918
- map,
9919
- onBeforeCompile,
9920
- side,
9921
- toneMapped
9962
+ toneMapped: false,
9963
+ ...props,
9964
+ onBeforeCompile
9922
9965
  },
9923
- active ? preset : "none"
9966
+ `${preset}:${hasMatrix}`
9924
9967
  );
9925
9968
  }
9926
9969
 
9927
- // src/sphere.tsx
9928
- var import_jsx_runtime15 = require("react/jsx-runtime");
9929
- function useEquirectTexture(url, anisotropy, generateMipmaps, onLoad, onError) {
9970
+ // src/tile/texture-manager.ts
9971
+ var import_three11 = require("three");
9972
+ var EMPTY_TEXTURE_SNAPSHOT = {
9973
+ status: "idle",
9974
+ texture: null,
9975
+ error: null
9976
+ };
9977
+ var TileTextureManager = class {
9978
+ constructor(options) {
9979
+ this.loader = new import_three11.TextureLoader();
9980
+ this.entries = /* @__PURE__ */ new Map();
9981
+ this.queue = [];
9982
+ this.activeLoads = 0;
9983
+ this.totalBytes = 0;
9984
+ this.requested = 0;
9985
+ this.loaded = 0;
9986
+ this.failed = 0;
9987
+ this.disposed = false;
9988
+ this.generation = 0;
9989
+ this.options = options;
9990
+ }
9991
+ resume() {
9992
+ this.disposed = false;
9993
+ this.drain();
9994
+ }
9995
+ getSnapshot(key) {
9996
+ const entry = this.entries.get(key);
9997
+ return entry ? this.snapshot(entry) : EMPTY_TEXTURE_SNAPSHOT;
9998
+ }
9999
+ acquire(key, url, address, listener) {
10000
+ let entry = this.entries.get(key);
10001
+ if (!entry) {
10002
+ entry = {
10003
+ key,
10004
+ url,
10005
+ address,
10006
+ status: "idle",
10007
+ texture: null,
10008
+ error: null,
10009
+ refs: 0,
10010
+ listeners: /* @__PURE__ */ new Set(),
10011
+ lastUsed: performance.now(),
10012
+ bytes: 0
10013
+ };
10014
+ this.entries.set(key, entry);
10015
+ }
10016
+ entry.refs += 1;
10017
+ entry.lastUsed = performance.now();
10018
+ entry.listeners.add(listener);
10019
+ listener(this.snapshot(entry));
10020
+ if (entry.status === "idle") {
10021
+ entry.status = "queued";
10022
+ this.queue.push(entry);
10023
+ this.requested += 1;
10024
+ this.emitProgress();
10025
+ this.drain();
10026
+ }
10027
+ return () => {
10028
+ entry.listeners.delete(listener);
10029
+ entry.refs = Math.max(0, entry.refs - 1);
10030
+ entry.lastUsed = performance.now();
10031
+ if (entry.refs === 0 && entry.status === "queued") {
10032
+ const queueIndex = this.queue.indexOf(entry);
10033
+ if (queueIndex >= 0) {
10034
+ this.queue.splice(queueIndex, 1);
10035
+ }
10036
+ entry.status = "idle";
10037
+ this.entries.delete(entry.key);
10038
+ this.requested = Math.max(0, this.requested - 1);
10039
+ this.emitProgress();
10040
+ this.drain();
10041
+ return;
10042
+ }
10043
+ this.evict();
10044
+ };
10045
+ }
10046
+ dispose() {
10047
+ this.disposed = true;
10048
+ this.generation += 1;
10049
+ this.queue.length = 0;
10050
+ for (const entry of this.entries.values()) {
10051
+ entry.texture?.dispose();
10052
+ entry.listeners.clear();
10053
+ }
10054
+ this.entries.clear();
10055
+ this.totalBytes = 0;
10056
+ }
10057
+ /**
10058
+ * Releases textures that are no longer rendered by any Tile instance.
10059
+ * Scene transitions call this after the outgoing panorama has been
10060
+ * snapshotted, so the incoming scene never competes with stale GPU tiles.
10061
+ */
10062
+ releaseUnused() {
10063
+ for (const entry of Array.from(this.entries.values())) {
10064
+ if (entry.refs > 0) {
10065
+ continue;
10066
+ }
10067
+ entry.texture?.dispose();
10068
+ this.totalBytes -= entry.bytes;
10069
+ this.entries.delete(entry.key);
10070
+ }
10071
+ this.totalBytes = Math.max(0, this.totalBytes);
10072
+ }
10073
+ snapshot(entry) {
10074
+ return {
10075
+ status: entry.status,
10076
+ texture: entry.texture,
10077
+ error: entry.error
10078
+ };
10079
+ }
10080
+ notify(entry) {
10081
+ const snapshot = this.snapshot(entry);
10082
+ for (const listener of entry.listeners) {
10083
+ listener(snapshot);
10084
+ }
10085
+ }
10086
+ emitProgress() {
10087
+ this.options.onProgress?.({
10088
+ requested: this.requested,
10089
+ loaded: this.loaded,
10090
+ failed: this.failed,
10091
+ active: this.activeLoads,
10092
+ queued: this.queue.length
10093
+ });
10094
+ }
10095
+ drain() {
10096
+ while (!this.disposed && this.activeLoads < this.options.concurrency && this.queue.length > 0) {
10097
+ const entry = this.queue.shift();
10098
+ if (entry.refs === 0) {
10099
+ entry.status = "idle";
10100
+ this.entries.delete(entry.key);
10101
+ this.requested = Math.max(0, this.requested - 1);
10102
+ continue;
10103
+ }
10104
+ entry.status = "loading";
10105
+ this.activeLoads += 1;
10106
+ this.notify(entry);
10107
+ this.emitProgress();
10108
+ void this.loadAndFinish(entry);
10109
+ }
10110
+ }
10111
+ async load(entry, generation) {
10112
+ let lastError = null;
10113
+ for (let attempt = 0; attempt <= this.options.retryCount; attempt += 1) {
10114
+ if (this.disposed || generation !== this.generation) return;
10115
+ try {
10116
+ const texture = await this.loader.loadAsync(entry.url);
10117
+ if (this.disposed || generation !== this.generation) {
10118
+ texture.dispose();
10119
+ return;
10120
+ }
10121
+ this.configureTexture(texture);
10122
+ entry.texture = texture;
10123
+ entry.status = "loaded";
10124
+ entry.error = null;
10125
+ entry.bytes = entry.address.width * entry.address.height * 4;
10126
+ entry.lastUsed = performance.now();
10127
+ this.totalBytes += entry.bytes;
10128
+ this.loaded += 1;
10129
+ this.notify(entry);
10130
+ return;
10131
+ } catch (error) {
10132
+ lastError = error;
10133
+ }
10134
+ }
10135
+ if (!this.disposed && generation === this.generation) {
10136
+ entry.status = "error";
10137
+ entry.error = lastError;
10138
+ this.failed += 1;
10139
+ this.notify(entry);
10140
+ this.options.onError?.({
10141
+ address: entry.address,
10142
+ url: entry.url,
10143
+ error: lastError
10144
+ });
10145
+ }
10146
+ }
10147
+ configureTexture(texture) {
10148
+ texture.colorSpace = import_three11.SRGBColorSpace;
10149
+ texture.wrapS = import_three11.ClampToEdgeWrapping;
10150
+ texture.wrapT = import_three11.ClampToEdgeWrapping;
10151
+ texture.magFilter = import_three11.LinearFilter;
10152
+ texture.minFilter = import_three11.LinearFilter;
10153
+ texture.generateMipmaps = false;
10154
+ texture.anisotropy = Math.min(4, this.options.anisotropy);
10155
+ texture.needsUpdate = true;
10156
+ }
10157
+ evict() {
10158
+ if (this.totalBytes <= this.options.maxBytes) {
10159
+ return;
10160
+ }
10161
+ const candidates = Array.from(this.entries.values()).filter((entry) => entry.refs === 0 && entry.texture).sort((a, b) => a.lastUsed - b.lastUsed);
10162
+ for (const entry of candidates) {
10163
+ if (this.totalBytes <= this.options.maxBytes) {
10164
+ break;
10165
+ }
10166
+ entry.texture?.dispose();
10167
+ this.totalBytes -= entry.bytes;
10168
+ this.entries.delete(entry.key);
10169
+ }
10170
+ this.totalBytes = Math.max(0, this.totalBytes);
10171
+ }
10172
+ finishLoad(generation) {
10173
+ this.activeLoads = Math.max(0, this.activeLoads - 1);
10174
+ if (!this.disposed && generation === this.generation) {
10175
+ this.emitProgress();
10176
+ this.evict();
10177
+ }
10178
+ if (!this.disposed) {
10179
+ this.drain();
10180
+ }
10181
+ }
10182
+ async loadAndFinish(entry) {
10183
+ const generation = this.generation;
10184
+ try {
10185
+ await this.load(entry, generation);
10186
+ } finally {
10187
+ this.finishLoad(generation);
10188
+ }
10189
+ }
10190
+ };
10191
+
10192
+ // src/tile/texture-hooks.ts
10193
+ var import_react37 = require("react");
10194
+ var import_three12 = require("three");
10195
+ function usePreviewTexture(url, anisotropy, onError) {
9930
10196
  const [texture, setTexture] = (0, import_react37.useState)(null);
9931
- const onLoadRef = (0, import_react37.useRef)(onLoad);
9932
10197
  const onErrorRef = (0, import_react37.useRef)(onError);
9933
- onLoadRef.current = onLoad;
9934
10198
  onErrorRef.current = onError;
9935
10199
  (0, import_react37.useEffect)(() => {
9936
10200
  if (!url) {
@@ -9938,7 +10202,7 @@ function useEquirectTexture(url, anisotropy, generateMipmaps, onLoad, onError) {
9938
10202
  return;
9939
10203
  }
9940
10204
  let active = true;
9941
- const loader = new import_three10.TextureLoader();
10205
+ const loader = new import_three12.TextureLoader();
9942
10206
  setTexture(null);
9943
10207
  loader.load(
9944
10208
  url,
@@ -9947,14 +10211,472 @@ function useEquirectTexture(url, anisotropy, generateMipmaps, onLoad, onError) {
9947
10211
  loadedTexture.dispose();
9948
10212
  return;
9949
10213
  }
9950
- loadedTexture.colorSpace = import_three10.SRGBColorSpace;
9951
- loadedTexture.wrapS = import_three10.RepeatWrapping;
9952
- loadedTexture.repeat.x = -1;
9953
- loadedTexture.offset.x = 1;
9954
- loadedTexture.anisotropy = anisotropy;
9955
- loadedTexture.magFilter = import_three10.LinearFilter;
9956
- loadedTexture.minFilter = generateMipmaps ? import_three10.LinearMipmapLinearFilter : import_three10.LinearFilter;
9957
- loadedTexture.generateMipmaps = generateMipmaps;
10214
+ loadedTexture.colorSpace = import_three12.SRGBColorSpace;
10215
+ loadedTexture.wrapS = import_three12.ClampToEdgeWrapping;
10216
+ loadedTexture.wrapT = import_three12.ClampToEdgeWrapping;
10217
+ loadedTexture.magFilter = import_three12.LinearFilter;
10218
+ loadedTexture.minFilter = import_three12.LinearFilter;
10219
+ loadedTexture.generateMipmaps = false;
10220
+ loadedTexture.anisotropy = Math.min(4, anisotropy);
10221
+ loadedTexture.needsUpdate = true;
10222
+ setTexture(loadedTexture);
10223
+ },
10224
+ void 0,
10225
+ (error) => {
10226
+ if (active) {
10227
+ setTexture(null);
10228
+ onErrorRef.current?.(error);
10229
+ }
10230
+ }
10231
+ );
10232
+ return () => {
10233
+ active = false;
10234
+ };
10235
+ }, [anisotropy, url]);
10236
+ (0, import_react37.useEffect)(
10237
+ () => () => {
10238
+ texture?.dispose();
10239
+ },
10240
+ [texture]
10241
+ );
10242
+ return texture;
10243
+ }
10244
+ function useManagedTexture(manager, key, url, address) {
10245
+ const [managedState, setManagedState] = (0, import_react37.useState)(() => ({
10246
+ manager,
10247
+ key,
10248
+ url,
10249
+ snapshot: manager.getSnapshot(key)
10250
+ }));
10251
+ const snapshot = managedState.manager === manager && managedState.key === key && managedState.url === url ? managedState.snapshot : manager.getSnapshot(key);
10252
+ (0, import_react37.useEffect)(
10253
+ () => manager.acquire(key, url, address, (nextSnapshot) => {
10254
+ setManagedState({
10255
+ manager,
10256
+ key,
10257
+ url,
10258
+ snapshot: nextSnapshot
10259
+ });
10260
+ }),
10261
+ [key, manager, url]
10262
+ );
10263
+ return snapshot;
10264
+ }
10265
+
10266
+ // src/sphere-tile/layout.ts
10267
+ var import_three13 = require("three");
10268
+ function positiveInteger(value, name) {
10269
+ if (!Number.isSafeInteger(value) || value <= 0) {
10270
+ throw new Error(`${name} must be a positive safe integer`);
10271
+ }
10272
+ return value;
10273
+ }
10274
+ function parseSphereMultires(input) {
10275
+ const parts = typeof input === "string" ? input.split(",").map((part) => part.trim()) : null;
10276
+ const tileSize = positiveInteger(
10277
+ parts ? Number(parts[0]) : input.tileSize,
10278
+ "tileSize"
10279
+ );
10280
+ const levels = parts ? parts.slice(1).map((part) => {
10281
+ const match = /^(\d+)\s*x\s*(\d+)$/i.exec(part);
10282
+ if (!match)
10283
+ throw new Error("sphere multires levels must use widthxheight");
10284
+ return { width: Number(match[1]), height: Number(match[2]) };
10285
+ }) : input.levels.map((level) => ({ ...level }));
10286
+ if (levels.length === 0)
10287
+ throw new Error("sphere multires needs at least one level");
10288
+ levels.forEach((level, index) => {
10289
+ positiveInteger(level.width, "level width");
10290
+ positiveInteger(level.height, "level height");
10291
+ if (Math.abs(level.width - level.height * 2) > 2)
10292
+ throw new Error("sphere levels must be full 2:1 equirectangular images");
10293
+ const previous = levels[index - 1];
10294
+ if (previous && (level.width <= previous.width || level.height <= previous.height)) {
10295
+ throw new Error("sphere multires dimensions must be strictly ascending");
10296
+ }
10297
+ });
10298
+ return { tileSize, levels };
10299
+ }
10300
+ function resolveSphereTemplateUrl(template, address, indexBase = 1) {
10301
+ return template.replace(/%l/g, String(address.level + indexBase)).replace(
10302
+ /%(0*)([hxucvywr])/g,
10303
+ (_match, zeroes, placeholder) => String(
10304
+ ("hxuc".includes(placeholder) ? address.col : address.row) + indexBase
10305
+ ).padStart(zeroes.length + 1, "0")
10306
+ );
10307
+ }
10308
+ function sphereTileKey(address) {
10309
+ return `${address.level}/${address.row}/${address.col}`;
10310
+ }
10311
+ function sphereTileAddresses(size, level, tileSize) {
10312
+ const addresses = [];
10313
+ for (let row = 0; row < Math.ceil(size.height / tileSize); row++) {
10314
+ for (let col = 0; col < Math.ceil(size.width / tileSize); col++) {
10315
+ addresses.push({
10316
+ level,
10317
+ col,
10318
+ row,
10319
+ imageWidth: size.width,
10320
+ imageHeight: size.height,
10321
+ tileSize,
10322
+ width: Math.min(tileSize, size.width - col * tileSize),
10323
+ height: Math.min(tileSize, size.height - row * tileSize)
10324
+ });
10325
+ }
10326
+ }
10327
+ return addresses;
10328
+ }
10329
+ function sphereTileRange(address) {
10330
+ return {
10331
+ left: address.col * address.tileSize / address.imageWidth,
10332
+ right: (address.col * address.tileSize + address.width) / address.imageWidth,
10333
+ top: address.row * address.tileSize / address.imageHeight,
10334
+ bottom: (address.row * address.tileSize + address.height) / address.imageHeight
10335
+ };
10336
+ }
10337
+ function spherePoint(u, v, yawOffset = 0, radius = DEFAULT_PANORAMA_RADIUS) {
10338
+ const yaw = (u - 0.5) * Math.PI * 2 + import_three13.MathUtils.degToRad(yawOffset);
10339
+ const pitch = (0.5 - v) * Math.PI;
10340
+ return new import_three13.Vector3(
10341
+ Math.sin(yaw) * Math.cos(pitch) * radius,
10342
+ Math.sin(pitch) * radius,
10343
+ -Math.cos(yaw) * Math.cos(pitch) * radius
10344
+ );
10345
+ }
10346
+ function sphereTileBounds(address, yawOffset) {
10347
+ const { left, right, top, bottom } = sphereTileRange(address);
10348
+ const us = [left, right];
10349
+ for (let i = -4; i <= 8; i++) {
10350
+ const u = 0.5 + (i * 90 - yawOffset % 360) / 360;
10351
+ if (u > left && u < right) us.push(u);
10352
+ }
10353
+ const vs = top < 0.5 && bottom > 0.5 ? [top, 0.5, bottom] : [top, bottom];
10354
+ return new import_three13.Box3().setFromPoints(
10355
+ us.flatMap((u) => vs.map((v) => spherePoint(u, v, yawOffset)))
10356
+ );
10357
+ }
10358
+ function sphereTileGeometry(address, yawOffset, radius = DEFAULT_PANORAMA_RADIUS) {
10359
+ const { left, right, top, bottom } = sphereTileRange(address);
10360
+ const columns = Math.max(2, Math.ceil((right - left) * 360 / 3));
10361
+ const rows = Math.max(2, Math.ceil((bottom - top) * 180 / 3));
10362
+ const positions = [], uvs = [], indices = [];
10363
+ for (let row = 0; row <= rows; row++) {
10364
+ for (let col = 0; col <= columns; col++) {
10365
+ const u = col / columns, v = row / rows;
10366
+ const point = spherePoint(
10367
+ left + (right - left) * u,
10368
+ top + (bottom - top) * v,
10369
+ yawOffset,
10370
+ radius
10371
+ );
10372
+ positions.push(point.x, point.y, point.z);
10373
+ uvs.push(u, 1 - v);
10374
+ if (row < rows && col < columns) {
10375
+ const a = row * (columns + 1) + col, b = a + 1, c = a + columns + 1, d = c + 1;
10376
+ indices.push(a, b, c, b, d, c);
10377
+ }
10378
+ }
10379
+ }
10380
+ const geometry = new import_three13.BufferGeometry();
10381
+ geometry.setAttribute("position", new import_three13.Float32BufferAttribute(positions, 3));
10382
+ geometry.setAttribute("uv", new import_three13.Float32BufferAttribute(uvs, 2));
10383
+ geometry.setIndex(indices);
10384
+ geometry.computeBoundingSphere();
10385
+ return geometry;
10386
+ }
10387
+ function preferredSphereLevel(levels, height, dpr, verticalFov) {
10388
+ const needed = height * dpr * 180 / Math.max(1, verticalFov);
10389
+ const index = levels.findIndex((level) => level.height >= needed);
10390
+ return index < 0 ? levels.length - 1 : index;
10391
+ }
10392
+
10393
+ // src/sphere-tile/sphere-tile.tsx
10394
+ var import_jsx_runtime15 = require("react/jsx-runtime");
10395
+ function SpherePatch({
10396
+ address,
10397
+ texture,
10398
+ yawOffset,
10399
+ preview = false
10400
+ }) {
10401
+ const geometry = (0, import_react38.useMemo)(
10402
+ () => sphereTileGeometry(
10403
+ address,
10404
+ yawOffset,
10405
+ DEFAULT_PANORAMA_RADIUS + (preview ? 0.05 : 0)
10406
+ ),
10407
+ [address, yawOffset, preview]
10408
+ );
10409
+ (0, import_react38.useEffect)(() => () => geometry.dispose(), [geometry]);
10410
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
10411
+ "mesh",
10412
+ {
10413
+ geometry,
10414
+ renderOrder: preview ? -1e3 : -900 + address.level,
10415
+ children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
10416
+ PanoBasicMaterial,
10417
+ {
10418
+ map: texture,
10419
+ side: import_three14.BackSide,
10420
+ depthTest: false,
10421
+ depthWrite: false,
10422
+ toneMapped: false
10423
+ }
10424
+ )
10425
+ }
10426
+ );
10427
+ }
10428
+ var ManagedPatch = (0, import_react38.memo)(function ManagedPatch2({
10429
+ address,
10430
+ manager,
10431
+ resolveUrl,
10432
+ yawOffset,
10433
+ ready
10434
+ }) {
10435
+ const url = resolveUrl(address);
10436
+ const snapshot = useManagedTexture(
10437
+ manager,
10438
+ `${url}\0${sphereTileKey(address)}`,
10439
+ url,
10440
+ address
10441
+ );
10442
+ (0, import_react38.useEffect)(() => {
10443
+ if (snapshot.texture) ready();
10444
+ }, [snapshot.texture, ready]);
10445
+ return snapshot.texture ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
10446
+ SpherePatch,
10447
+ {
10448
+ address,
10449
+ texture: snapshot.texture,
10450
+ yawOffset
10451
+ }
10452
+ ) : null;
10453
+ });
10454
+ function SphereTileSource({
10455
+ config,
10456
+ baseUrl,
10457
+ previewUrl,
10458
+ urlTemplate = "tiles/%l/%h_%v.webp",
10459
+ indexBase = 1,
10460
+ resolveTileUrl,
10461
+ yawOffset = 0,
10462
+ maxTextureMemoryMb = 128,
10463
+ maxConcurrentLoads = 4,
10464
+ retryCount = 1,
10465
+ loadMode = "full",
10466
+ visible = true,
10467
+ onReady,
10468
+ onPreviewError,
10469
+ onLoadProgress,
10470
+ onTileError,
10471
+ onLevelChange
10472
+ }) {
10473
+ const { camera, gl, size } = (0, import_fiber15.useThree)();
10474
+ const anisotropy = gl.capabilities.getMaxAnisotropy();
10475
+ const preview = usePreviewTexture(
10476
+ resolveAssetUrl(baseUrl, previewUrl),
10477
+ anisotropy,
10478
+ onPreviewError
10479
+ );
10480
+ const callbacks = (0, import_react38.useRef)({
10481
+ onReady,
10482
+ onLoadProgress,
10483
+ onTileError,
10484
+ onLevelChange
10485
+ });
10486
+ callbacks.current = { onReady, onLoadProgress, onTileError, onLevelChange };
10487
+ const budget = Math.max(
10488
+ 1,
10489
+ Number.isFinite(maxTextureMemoryMb) ? maxTextureMemoryMb : 128
10490
+ ) * 1024 * 1024;
10491
+ const manager = (0, import_react38.useMemo)(
10492
+ () => new TileTextureManager({
10493
+ anisotropy,
10494
+ maxBytes: budget,
10495
+ concurrency: Math.max(
10496
+ 1,
10497
+ Math.floor(
10498
+ Number.isFinite(maxConcurrentLoads) ? maxConcurrentLoads : 4
10499
+ )
10500
+ ),
10501
+ retryCount: Math.max(
10502
+ 0,
10503
+ Math.floor(Number.isFinite(retryCount) ? retryCount : 1)
10504
+ ),
10505
+ onProgress: (progress) => callbacks.current.onLoadProgress?.(progress),
10506
+ onError: (error) => callbacks.current.onTileError?.(error)
10507
+ }),
10508
+ [anisotropy, budget, maxConcurrentLoads, retryCount]
10509
+ );
10510
+ const readyRef = (0, import_react38.useRef)(false);
10511
+ const ready = (0, import_react38.useCallback)(() => {
10512
+ if (!readyRef.current) {
10513
+ readyRef.current = true;
10514
+ callbacks.current.onReady?.();
10515
+ }
10516
+ }, []);
10517
+ (0, import_react38.useEffect)(() => {
10518
+ if (preview) ready();
10519
+ }, [preview, ready]);
10520
+ (0, import_react38.useEffect)(() => {
10521
+ manager.resume();
10522
+ return () => manager.dispose();
10523
+ }, [manager]);
10524
+ const resolveUrl = (0, import_react38.useMemo)(
10525
+ () => (address) => resolveAssetUrl(
10526
+ baseUrl,
10527
+ resolveTileUrl ? resolveTileUrl(address) : resolveSphereTemplateUrl(urlTemplate, address, indexBase)
10528
+ ),
10529
+ [baseUrl, resolveTileUrl, urlTemplate, indexBase]
10530
+ );
10531
+ const candidates = (0, import_react38.useMemo)(
10532
+ () => config.levels.map(
10533
+ (level, index) => sphereTileAddresses(level, index, config.tileSize).map((address) => ({
10534
+ address,
10535
+ bounds: sphereTileBounds(address, yawOffset)
10536
+ }))
10537
+ ),
10538
+ [config, yawOffset]
10539
+ );
10540
+ const previewAddress = (0, import_react38.useMemo)(
10541
+ () => sphereTileAddresses({ width: 2, height: 1 }, 0, 2)[0],
10542
+ []
10543
+ );
10544
+ const [layers, setLayers] = (0, import_react38.useState)([]);
10545
+ const scratch = (0, import_react38.useMemo)(
10546
+ () => ({
10547
+ camera: new import_three14.PerspectiveCamera(),
10548
+ frustum: new import_three14.Frustum(),
10549
+ matrix: new import_three14.Matrix4(),
10550
+ quaternion: camera.quaternion.clone(),
10551
+ fov: NaN,
10552
+ width: 0,
10553
+ height: 0,
10554
+ dpr: 0,
10555
+ time: -Infinity,
10556
+ token: "",
10557
+ level: -1,
10558
+ loadMode: "",
10559
+ manager: null
10560
+ }),
10561
+ [camera, candidates]
10562
+ );
10563
+ (0, import_fiber15.useFrame)(() => {
10564
+ if (!(camera instanceof import_three14.PerspectiveCamera)) return;
10565
+ const now = performance.now(), dpr = gl.getPixelRatio();
10566
+ const reset = scratch.manager !== manager || scratch.loadMode !== loadMode;
10567
+ if (!reset && (now - scratch.time < 100 || scratch.fov === camera.fov && scratch.width === size.width && scratch.height === size.height && scratch.dpr === dpr && scratch.quaternion.angleTo(camera.quaternion) < 1e-4))
10568
+ return;
10569
+ scratch.time = now;
10570
+ scratch.fov = camera.fov;
10571
+ scratch.width = size.width;
10572
+ scratch.height = size.height;
10573
+ scratch.dpr = dpr;
10574
+ scratch.quaternion.copy(camera.quaternion);
10575
+ scratch.manager = manager;
10576
+ scratch.loadMode = loadMode;
10577
+ scratch.camera.copy(camera, false);
10578
+ scratch.camera.fov = Math.min(179, camera.fov + 8);
10579
+ scratch.camera.updateProjectionMatrix();
10580
+ scratch.camera.updateMatrixWorld();
10581
+ scratch.matrix.multiplyMatrices(
10582
+ scratch.camera.projectionMatrix,
10583
+ scratch.camera.matrixWorldInverse
10584
+ );
10585
+ scratch.frustum.setFromProjectionMatrix(scratch.matrix);
10586
+ let level = loadMode === "preview" ? -1 : loadMode === "base" ? 0 : preferredSphereLevel(config.levels, size.height, dpr, camera.fov);
10587
+ const next = [];
10588
+ let residentBytes = 0;
10589
+ for (let index = 0; index <= level; index++) {
10590
+ const addresses = candidates[index].filter(
10591
+ ({ bounds }) => scratch.frustum.intersectsBox(bounds)
10592
+ ).map(({ address }) => address);
10593
+ const bytes = addresses.reduce(
10594
+ (total, address) => total + address.width * address.height * 4,
10595
+ 0
10596
+ );
10597
+ if (residentBytes + bytes > budget) {
10598
+ level = index - 1;
10599
+ break;
10600
+ }
10601
+ residentBytes += bytes;
10602
+ next.push({ level: index, addresses });
10603
+ }
10604
+ if (level !== scratch.level) {
10605
+ scratch.level = level;
10606
+ if (level >= 0) callbacks.current.onLevelChange?.(level);
10607
+ }
10608
+ const token = next.map((layer) => layer.addresses.map(sphereTileKey).join(",")).join(";");
10609
+ if (token !== scratch.token || reset) {
10610
+ scratch.token = token;
10611
+ setLayers(next);
10612
+ }
10613
+ });
10614
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("group", { visible, children: [
10615
+ preview ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
10616
+ SpherePatch,
10617
+ {
10618
+ address: previewAddress,
10619
+ texture: preview,
10620
+ yawOffset,
10621
+ preview: true
10622
+ }
10623
+ ) : null,
10624
+ loadMode !== "preview" ? layers.flatMap(
10625
+ (layer) => layer.addresses.map((address) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
10626
+ ManagedPatch,
10627
+ {
10628
+ address,
10629
+ manager,
10630
+ resolveUrl,
10631
+ yawOffset,
10632
+ ready
10633
+ },
10634
+ sphereTileKey(address)
10635
+ ))
10636
+ ) : null
10637
+ ] });
10638
+ }
10639
+ function SphereTile({ multires, ...props }) {
10640
+ const token = typeof multires === "string" ? multires : JSON.stringify(multires);
10641
+ const config = (0, import_react38.useMemo)(() => parseSphereMultires(multires), [token]);
10642
+ const sourceKey = `${props.baseUrl}\0${token}\0${props.previewUrl}\0${props.urlTemplate ?? ""}\0${props.indexBase ?? 1}`;
10643
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(SphereTileSource, { ...props, config }, sourceKey);
10644
+ }
10645
+
10646
+ // src/sphere.tsx
10647
+ var import_fiber16 = require("@react-three/fiber");
10648
+ var import_react39 = require("react");
10649
+ var import_three15 = require("three");
10650
+ var import_jsx_runtime16 = require("react/jsx-runtime");
10651
+ function useEquirectTexture(url, anisotropy, generateMipmaps, onLoad, onError) {
10652
+ const [texture, setTexture] = (0, import_react39.useState)(null);
10653
+ const onLoadRef = (0, import_react39.useRef)(onLoad);
10654
+ const onErrorRef = (0, import_react39.useRef)(onError);
10655
+ onLoadRef.current = onLoad;
10656
+ onErrorRef.current = onError;
10657
+ (0, import_react39.useEffect)(() => {
10658
+ if (!url) {
10659
+ setTexture(null);
10660
+ return;
10661
+ }
10662
+ let active = true;
10663
+ const loader = new import_three15.TextureLoader();
10664
+ setTexture(null);
10665
+ loader.load(
10666
+ url,
10667
+ (loadedTexture) => {
10668
+ if (!active) {
10669
+ loadedTexture.dispose();
10670
+ return;
10671
+ }
10672
+ loadedTexture.colorSpace = import_three15.SRGBColorSpace;
10673
+ loadedTexture.wrapS = import_three15.RepeatWrapping;
10674
+ loadedTexture.repeat.x = -1;
10675
+ loadedTexture.offset.x = 1;
10676
+ loadedTexture.anisotropy = anisotropy;
10677
+ loadedTexture.magFilter = import_three15.LinearFilter;
10678
+ loadedTexture.minFilter = generateMipmaps ? import_three15.LinearMipmapLinearFilter : import_three15.LinearFilter;
10679
+ loadedTexture.generateMipmaps = generateMipmaps;
9958
10680
  loadedTexture.needsUpdate = true;
9959
10681
  setTexture(loadedTexture);
9960
10682
  onLoadRef.current?.(loadedTexture);
@@ -9971,7 +10693,7 @@ function useEquirectTexture(url, anisotropy, generateMipmaps, onLoad, onError) {
9971
10693
  active = false;
9972
10694
  };
9973
10695
  }, [anisotropy, generateMipmaps, url]);
9974
- (0, import_react37.useEffect)(
10696
+ (0, import_react39.useEffect)(
9975
10697
  () => () => {
9976
10698
  texture?.dispose();
9977
10699
  },
@@ -9989,9 +10711,9 @@ function Sphere({
9989
10711
  onPreviewError,
9990
10712
  visible = true
9991
10713
  }) {
9992
- const gl = (0, import_fiber15.useThree)((state) => state.gl);
10714
+ const gl = (0, import_fiber16.useThree)((state) => state.gl);
9993
10715
  const anisotropy = gl.capabilities.getMaxAnisotropy();
9994
- const resolvedPreviewUrl = (0, import_react37.useMemo)(
10716
+ const resolvedPreviewUrl = (0, import_react39.useMemo)(
9995
10717
  () => resolveUrlAgainstFile(src, previewUrl),
9996
10718
  [previewUrl, src]
9997
10719
  );
@@ -10010,11 +10732,11 @@ function Sphere({
10010
10732
  onPreviewError
10011
10733
  );
10012
10734
  const displayTexture = texture ?? previewTexture;
10013
- const readyRef = (0, import_react37.useRef)(false);
10014
- (0, import_react37.useEffect)(() => {
10735
+ const readyRef = (0, import_react39.useRef)(false);
10736
+ (0, import_react39.useEffect)(() => {
10015
10737
  readyRef.current = false;
10016
10738
  }, [resolvedPreviewUrl, src]);
10017
- (0, import_react37.useEffect)(() => {
10739
+ (0, import_react39.useEffect)(() => {
10018
10740
  if (!displayTexture || readyRef.current) {
10019
10741
  return;
10020
10742
  }
@@ -10024,18 +10746,18 @@ function Sphere({
10024
10746
  if (!displayTexture) {
10025
10747
  return null;
10026
10748
  }
10027
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
10749
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
10028
10750
  "mesh",
10029
10751
  {
10030
- rotation: [0, import_three10.MathUtils.degToRad(90 + yawOffset), 0],
10752
+ rotation: [0, import_three15.MathUtils.degToRad(90 + yawOffset), 0],
10031
10753
  visible,
10032
10754
  children: [
10033
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("sphereGeometry", { args: [DEFAULT_PANORAMA_RADIUS, 128, 64] }),
10034
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
10755
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("sphereGeometry", { args: [DEFAULT_PANORAMA_RADIUS, 128, 64] }),
10756
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
10035
10757
  PanoBasicMaterial,
10036
10758
  {
10037
10759
  map: displayTexture,
10038
- side: import_three10.BackSide,
10760
+ side: import_three15.BackSide,
10039
10761
  toneMapped: false
10040
10762
  }
10041
10763
  )
@@ -10045,10 +10767,10 @@ function Sphere({
10045
10767
  }
10046
10768
 
10047
10769
  // src/video/pano-video.tsx
10048
- var import_fiber16 = require("@react-three/fiber");
10049
- var import_react38 = require("react");
10050
- var import_three11 = require("three");
10051
- var import_jsx_runtime16 = require("react/jsx-runtime");
10770
+ var import_fiber17 = require("@react-three/fiber");
10771
+ var import_react40 = require("react");
10772
+ var import_three16 = require("three");
10773
+ var import_jsx_runtime17 = require("react/jsx-runtime");
10052
10774
  var EMPTY_TRACKS = [];
10053
10775
  var EMPTY_RATES = DEFAULT_PANO_VIDEO_PLAYBACK_RATES;
10054
10776
  function createEmptySnapshot() {
@@ -10124,19 +10846,19 @@ function findTextTrack(video, tracks, trackId) {
10124
10846
  return list.length > 0 ? list[0] : null;
10125
10847
  }
10126
10848
  function applyEquirectangularLayout(texture, anisotropy) {
10127
- texture.colorSpace = import_three11.SRGBColorSpace;
10128
- texture.wrapS = import_three11.RepeatWrapping;
10849
+ texture.colorSpace = import_three16.SRGBColorSpace;
10850
+ texture.wrapS = import_three16.RepeatWrapping;
10129
10851
  texture.repeat.x = -1;
10130
10852
  texture.offset.x = 1;
10131
10853
  texture.anisotropy = anisotropy;
10132
10854
  texture.needsUpdate = true;
10133
10855
  }
10134
10856
  function usePosterTexture(poster, onError) {
10135
- const gl = (0, import_fiber16.useThree)((state) => state.gl);
10136
- const [texture, setTexture] = (0, import_react38.useState)(null);
10137
- const onErrorRef = (0, import_react38.useRef)(onError);
10857
+ const gl = (0, import_fiber17.useThree)((state) => state.gl);
10858
+ const [texture, setTexture] = (0, import_react40.useState)(null);
10859
+ const onErrorRef = (0, import_react40.useRef)(onError);
10138
10860
  onErrorRef.current = onError;
10139
- (0, import_react38.useEffect)(() => {
10861
+ (0, import_react40.useEffect)(() => {
10140
10862
  let active = true;
10141
10863
  setTexture(null);
10142
10864
  if (!poster) {
@@ -10144,7 +10866,7 @@ function usePosterTexture(poster, onError) {
10144
10866
  active = false;
10145
10867
  };
10146
10868
  }
10147
- const loader = new import_three11.TextureLoader();
10869
+ const loader = new import_three16.TextureLoader();
10148
10870
  loader.load(
10149
10871
  poster,
10150
10872
  (loadedTexture) => {
@@ -10156,9 +10878,9 @@ function usePosterTexture(poster, onError) {
10156
10878
  loadedTexture,
10157
10879
  gl.capabilities.getMaxAnisotropy()
10158
10880
  );
10159
- loadedTexture.wrapT = import_three11.RepeatWrapping;
10160
- loadedTexture.magFilter = import_three11.LinearFilter;
10161
- loadedTexture.minFilter = import_three11.LinearMipmapLinearFilter;
10881
+ loadedTexture.wrapT = import_three16.RepeatWrapping;
10882
+ loadedTexture.magFilter = import_three16.LinearFilter;
10883
+ loadedTexture.minFilter = import_three16.LinearMipmapLinearFilter;
10162
10884
  loadedTexture.generateMipmaps = true;
10163
10885
  setTexture(loadedTexture);
10164
10886
  },
@@ -10173,7 +10895,7 @@ function usePosterTexture(poster, onError) {
10173
10895
  active = false;
10174
10896
  };
10175
10897
  }, [gl, poster]);
10176
- (0, import_react38.useEffect)(
10898
+ (0, import_react40.useEffect)(
10177
10899
  () => () => {
10178
10900
  texture?.dispose();
10179
10901
  },
@@ -10231,39 +10953,39 @@ function PanoVideo({
10231
10953
  onTrackChange
10232
10954
  }) {
10233
10955
  usePanoMediaActivationIntent(autoPlay);
10234
- const gl = (0, import_fiber16.useThree)((state) => state.gl);
10235
- const host = (0, import_react38.useContext)(PanoVideoHostContext);
10236
- const overlay = (0, import_react38.useContext)(PanoChromeOverlayContext);
10237
- const variants = (0, import_react38.useMemo)(
10956
+ const gl = (0, import_fiber17.useThree)((state) => state.gl);
10957
+ const host = (0, import_react40.useContext)(PanoVideoHostContext);
10958
+ const overlay = (0, import_react40.useContext)(PanoChromeOverlayContext);
10959
+ const variants = (0, import_react40.useMemo)(
10238
10960
  () => resolvePanoVideoVariants({ poster, src, variants: variantsProp }),
10239
10961
  [poster, src, variantsProp]
10240
10962
  );
10241
10963
  const tracks = tracksProp ?? EMPTY_TRACKS;
10242
10964
  const captionsEnabled = captions !== false;
10243
- const captionAppearance = (0, import_react38.useMemo)(
10965
+ const captionAppearance = (0, import_react40.useMemo)(
10244
10966
  () => resolvePanoVideoCaptionAppearance(
10245
10967
  typeof captions === "object" ? captions : void 0
10246
10968
  ),
10247
10969
  [captions]
10248
10970
  );
10249
- const [variantId, setVariantId] = (0, import_react38.useState)(
10971
+ const [variantId, setVariantId] = (0, import_react40.useState)(
10250
10972
  () => resolvePanoVideoVariantId(variants, defaultVariantId)
10251
10973
  );
10252
- const [trackId, setTrackId] = (0, import_react38.useState)(
10974
+ const [trackId, setTrackId] = (0, import_react40.useState)(
10253
10975
  () => captionsEnabled ? defaultPanoVideoTrackId(tracks) : null
10254
10976
  );
10255
- const [ready, setReady] = (0, import_react38.useState)(false);
10256
- const autoPlayRef = (0, import_react38.useRef)(autoPlay);
10977
+ const [ready, setReady] = (0, import_react40.useState)(false);
10978
+ const autoPlayRef = (0, import_react40.useRef)(autoPlay);
10257
10979
  autoPlayRef.current = autoPlay;
10258
- const blockedRef = (0, import_react38.useRef)(false);
10259
- const captionAppearanceOverrideRef = (0, import_react38.useRef)(
10980
+ const blockedRef = (0, import_react40.useRef)(false);
10981
+ const captionAppearanceOverrideRef = (0, import_react40.useRef)(
10260
10982
  {}
10261
10983
  );
10262
- const mediaCapabilitiesRef = (0, import_react38.useRef)({
10984
+ const mediaCapabilitiesRef = (0, import_react40.useRef)({
10263
10985
  volumeAdjustable: true,
10264
10986
  playbackRates: [...DEFAULT_PANO_VIDEO_PLAYBACK_RATES]
10265
10987
  });
10266
- const storeRef = (0, import_react38.useRef)(null);
10988
+ const storeRef = (0, import_react40.useRef)(null);
10267
10989
  if (!storeRef.current) {
10268
10990
  storeRef.current = {
10269
10991
  snapshot: {
@@ -10273,7 +10995,7 @@ function PanoVideo({
10273
10995
  listeners: /* @__PURE__ */ new Set()
10274
10996
  };
10275
10997
  }
10276
- const actionsRef = (0, import_react38.useRef)({
10998
+ const actionsRef = (0, import_react40.useRef)({
10277
10999
  play: async () => {
10278
11000
  },
10279
11001
  pause: () => {
@@ -10293,19 +11015,19 @@ function PanoVideo({
10293
11015
  setCaptionAppearance: (_appearance) => {
10294
11016
  }
10295
11017
  });
10296
- const onLoadRef = (0, import_react38.useRef)(onLoad);
10297
- const onErrorRef = (0, import_react38.useRef)(onError);
10298
- const onPlaybackStateChangeRef = (0, import_react38.useRef)(onPlaybackStateChange);
10299
- const onEndedRef = (0, import_react38.useRef)(onEnded);
10300
- const onVariantChangeRef = (0, import_react38.useRef)(onVariantChange);
10301
- const onTrackChangeRef = (0, import_react38.useRef)(onTrackChange);
11018
+ const onLoadRef = (0, import_react40.useRef)(onLoad);
11019
+ const onErrorRef = (0, import_react40.useRef)(onError);
11020
+ const onPlaybackStateChangeRef = (0, import_react40.useRef)(onPlaybackStateChange);
11021
+ const onEndedRef = (0, import_react40.useRef)(onEnded);
11022
+ const onVariantChangeRef = (0, import_react40.useRef)(onVariantChange);
11023
+ const onTrackChangeRef = (0, import_react40.useRef)(onTrackChange);
10302
11024
  onLoadRef.current = onLoad;
10303
11025
  onErrorRef.current = onError;
10304
11026
  onPlaybackStateChangeRef.current = onPlaybackStateChange;
10305
11027
  onEndedRef.current = onEnded;
10306
11028
  onVariantChangeRef.current = onVariantChange;
10307
11029
  onTrackChangeRef.current = onTrackChange;
10308
- const resource = (0, import_react38.useMemo)(() => {
11030
+ const resource = (0, import_react40.useMemo)(() => {
10309
11031
  if (typeof document === "undefined") {
10310
11032
  return null;
10311
11033
  }
@@ -10315,14 +11037,14 @@ function PanoVideo({
10315
11037
  video.setAttribute("playsinline", "true");
10316
11038
  video.setAttribute("webkit-playsinline", "true");
10317
11039
  video.preload = "metadata";
10318
- const texture = new import_three11.VideoTexture(video);
11040
+ const texture = new import_three16.VideoTexture(video);
10319
11041
  applyEquirectangularLayout(texture, 1);
10320
- texture.magFilter = import_three11.LinearFilter;
10321
- texture.minFilter = import_three11.LinearFilter;
11042
+ texture.magFilter = import_three16.LinearFilter;
11043
+ texture.minFilter = import_three16.LinearFilter;
10322
11044
  texture.generateMipmaps = false;
10323
11045
  return { video, texture };
10324
11046
  }, []);
10325
- (0, import_react38.useEffect)(
11047
+ (0, import_react40.useEffect)(
10326
11048
  () => () => {
10327
11049
  if (!resource) {
10328
11050
  return;
@@ -10337,13 +11059,13 @@ function PanoVideo({
10337
11059
  },
10338
11060
  [resource]
10339
11061
  );
10340
- (0, import_react38.useEffect)(() => {
11062
+ (0, import_react40.useEffect)(() => {
10341
11063
  if (!resource) {
10342
11064
  return;
10343
11065
  }
10344
11066
  resource.texture.anisotropy = gl.capabilities.getMaxAnisotropy();
10345
11067
  }, [gl, resource]);
10346
- (0, import_react38.useEffect)(() => {
11068
+ (0, import_react40.useEffect)(() => {
10347
11069
  if (!resource || !overlay?.overlayElement) {
10348
11070
  return;
10349
11071
  }
@@ -10366,7 +11088,7 @@ function PanoVideo({
10366
11088
  activeVariant?.poster ?? poster,
10367
11089
  onError
10368
11090
  );
10369
- const emitSnapshot = (0, import_react38.useCallback)(
11091
+ const emitSnapshot = (0, import_react40.useCallback)(
10370
11092
  (patch) => {
10371
11093
  const store = storeRef.current;
10372
11094
  const video = resource?.video;
@@ -10418,7 +11140,7 @@ function PanoVideo({
10418
11140
  captionAppearance
10419
11141
  ]
10420
11142
  );
10421
- const controller = (0, import_react38.useMemo)(
11143
+ const controller = (0, import_react40.useMemo)(
10422
11144
  () => ({
10423
11145
  subscribe: (onStoreChange) => {
10424
11146
  const store = storeRef.current;
@@ -10470,7 +11192,7 @@ function PanoVideo({
10470
11192
  }),
10471
11193
  []
10472
11194
  );
10473
- (0, import_react38.useLayoutEffect)(() => {
11195
+ (0, import_react40.useLayoutEffect)(() => {
10474
11196
  if (!host || variants.length === 0) {
10475
11197
  return;
10476
11198
  }
@@ -10483,7 +11205,7 @@ function PanoVideo({
10483
11205
  notifyPanoVideoHost(host);
10484
11206
  };
10485
11207
  }, [captionsEnabled, controller, controls, host, variants.length]);
10486
- (0, import_react38.useLayoutEffect)(() => {
11208
+ (0, import_react40.useLayoutEffect)(() => {
10487
11209
  if (!resource) {
10488
11210
  return;
10489
11211
  }
@@ -10496,10 +11218,10 @@ function PanoVideo({
10496
11218
  };
10497
11219
  emitSnapshot();
10498
11220
  }, [emitSnapshot, playbackRates, resource]);
10499
- (0, import_react38.useEffect)(() => {
11221
+ (0, import_react40.useEffect)(() => {
10500
11222
  emitSnapshot();
10501
11223
  }, [emitSnapshot]);
10502
- (0, import_react38.useEffect)(() => {
11224
+ (0, import_react40.useEffect)(() => {
10503
11225
  if (!resource || !activeVariant || !mediaKey) {
10504
11226
  return;
10505
11227
  }
@@ -10556,7 +11278,7 @@ function PanoVideo({
10556
11278
  video.removeEventListener("error", handleError);
10557
11279
  };
10558
11280
  }, [mediaKey, resource]);
10559
- (0, import_react38.useEffect)(() => {
11281
+ (0, import_react40.useEffect)(() => {
10560
11282
  if (!resource) {
10561
11283
  return;
10562
11284
  }
@@ -10648,7 +11370,7 @@ function PanoVideo({
10648
11370
  }
10649
11371
  };
10650
11372
  }, [emitSnapshot, resource]);
10651
- (0, import_react38.useEffect)(() => {
11373
+ (0, import_react40.useEffect)(() => {
10652
11374
  if (!resource) {
10653
11375
  return;
10654
11376
  }
@@ -10668,7 +11390,7 @@ function PanoVideo({
10668
11390
  }
10669
11391
  video.preload = preload;
10670
11392
  }, [loop, muted, playsInline, preload, resource, volume]);
10671
- (0, import_react38.useEffect)(() => {
11393
+ (0, import_react40.useEffect)(() => {
10672
11394
  if (!resource) {
10673
11395
  return;
10674
11396
  }
@@ -10718,7 +11440,7 @@ function PanoVideo({
10718
11440
  video.removeEventListener("ratechange", handleVolume);
10719
11441
  };
10720
11442
  }, [emitSnapshot, resource]);
10721
- (0, import_react38.useEffect)(() => {
11443
+ (0, import_react40.useEffect)(() => {
10722
11444
  if (!resource) {
10723
11445
  return;
10724
11446
  }
@@ -10753,7 +11475,7 @@ function PanoVideo({
10753
11475
  video.textTracks.removeEventListener("change", applyModes);
10754
11476
  };
10755
11477
  }, [emitSnapshot, resource, trackId, tracks]);
10756
- (0, import_react38.useEffect)(() => {
11478
+ (0, import_react40.useEffect)(() => {
10757
11479
  if (!captionsEnabled) {
10758
11480
  setTrackId(null);
10759
11481
  return;
@@ -10764,33 +11486,33 @@ function PanoVideo({
10764
11486
  if (variants.length === 0) {
10765
11487
  return null;
10766
11488
  }
10767
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
10768
- activeTexture ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
11489
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
11490
+ activeTexture ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
10769
11491
  "mesh",
10770
11492
  {
10771
- rotation: [0, import_three11.MathUtils.degToRad(90 + yawOffset), 0],
11493
+ rotation: [0, import_three16.MathUtils.degToRad(90 + yawOffset), 0],
10772
11494
  visible,
10773
11495
  children: [
10774
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("sphereGeometry", { args: [DEFAULT_PANORAMA_RADIUS, 128, 64] }),
10775
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
11496
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("sphereGeometry", { args: [DEFAULT_PANORAMA_RADIUS, 128, 64] }),
11497
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
10776
11498
  PanoBasicMaterial,
10777
11499
  {
10778
11500
  map: activeTexture,
10779
- side: import_three11.BackSide,
11501
+ side: import_three16.BackSide,
10780
11502
  toneMapped: false
10781
11503
  }
10782
11504
  )
10783
11505
  ]
10784
11506
  }
10785
11507
  ) : null,
10786
- captionsEnabled ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(PanoVideoCaptions, { appearance: typeof captions === "object" ? captions : void 0 }) : null
11508
+ captionsEnabled ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(PanoVideoCaptions, { appearance: typeof captions === "object" ? captions : void 0 }) : null
10787
11509
  ] });
10788
11510
  }
10789
11511
 
10790
11512
  // src/scenes.tsx
10791
- var import_fiber21 = require("@react-three/fiber");
10792
- var import_react43 = require("react");
10793
- var import_three19 = require("three");
11513
+ var import_fiber22 = require("@react-three/fiber");
11514
+ var import_react45 = require("react");
11515
+ var import_three23 = require("three");
10794
11516
 
10795
11517
  // src/scene-transitions/presets.ts
10796
11518
  var TRANSITION_DEFAULTS = {
@@ -10839,9 +11561,9 @@ function isSnapshotTransition(preset) {
10839
11561
  }
10840
11562
 
10841
11563
  // src/scene-transitions/particle-overlay.tsx
10842
- var import_fiber17 = require("@react-three/fiber");
10843
- var import_react39 = require("react");
10844
- var import_three13 = require("three");
11564
+ var import_fiber18 = require("@react-three/fiber");
11565
+ var import_react41 = require("react");
11566
+ var import_three18 = require("three");
10845
11567
 
10846
11568
  // src/scene-transitions/glsl.ts
10847
11569
  var GLSL_COMMON = `
@@ -10874,9 +11596,9 @@ float fbm(vec2 p) {
10874
11596
  `;
10875
11597
 
10876
11598
  // src/scene-transitions/overlay-utils.ts
10877
- var import_three12 = require("three");
11599
+ var import_three17 = require("three");
10878
11600
  var OVERLAY_RENDER_ORDER = 1e4;
10879
- var FULLSCREEN_PLANE = new import_three12.PlaneGeometry(1, 1);
11601
+ var FULLSCREEN_PLANE = new import_three17.PlaneGeometry(1, 1);
10880
11602
  function isPerspectiveCamera(camera) {
10881
11603
  return camera.isPerspectiveCamera === true;
10882
11604
  }
@@ -10895,7 +11617,7 @@ function overlayProgress(elapsedTime, duration, startTime) {
10895
11617
  }
10896
11618
 
10897
11619
  // src/scene-transitions/particle-overlay.tsx
10898
- var import_jsx_runtime17 = require("react/jsx-runtime");
11620
+ var import_jsx_runtime18 = require("react/jsx-runtime");
10899
11621
  var PARTICLE_GRID = 48;
10900
11622
  var PARTICLE_COUNT = PARTICLE_GRID * PARTICLE_GRID;
10901
11623
  var PARTICLE_VERTEX_SHADER = `
@@ -10948,8 +11670,8 @@ var PARTICLE_FRAGMENT_SHADER = `
10948
11670
  }
10949
11671
  `;
10950
11672
  function createParticleGeometry() {
10951
- const quad = new import_three13.PlaneGeometry(1, 1);
10952
- const geometry = new import_three13.InstancedBufferGeometry();
11673
+ const quad = new import_three18.PlaneGeometry(1, 1);
11674
+ const geometry = new import_three18.InstancedBufferGeometry();
10953
11675
  if (quad.index) {
10954
11676
  geometry.setIndex(quad.index.clone());
10955
11677
  }
@@ -10959,7 +11681,7 @@ function createParticleGeometry() {
10959
11681
  for (let i = 0; i < PARTICLE_COUNT; i += 1) {
10960
11682
  indexes[i] = i;
10961
11683
  }
10962
- geometry.setAttribute("instanceIndex", new import_three13.InstancedBufferAttribute(indexes, 1));
11684
+ geometry.setAttribute("instanceIndex", new import_three18.InstancedBufferAttribute(indexes, 1));
10963
11685
  geometry.instanceCount = PARTICLE_COUNT;
10964
11686
  quad.dispose();
10965
11687
  return geometry;
@@ -10971,36 +11693,36 @@ function ParticleOverlay({
10971
11693
  runId,
10972
11694
  onFinish
10973
11695
  }) {
10974
- const { camera } = (0, import_fiber17.useThree)();
10975
- const meshRef = (0, import_react39.useRef)(null);
10976
- const startRef = (0, import_react39.useRef)(null);
10977
- const finishedRef = (0, import_react39.useRef)(false);
10978
- const directionRef = (0, import_react39.useRef)(new import_three13.Vector3());
10979
- const geometry = (0, import_react39.useMemo)(() => createParticleGeometry(), []);
10980
- const material = (0, import_react39.useMemo)(
10981
- () => new import_three13.ShaderMaterial({
11696
+ const { camera } = (0, import_fiber18.useThree)();
11697
+ const meshRef = (0, import_react41.useRef)(null);
11698
+ const startRef = (0, import_react41.useRef)(null);
11699
+ const finishedRef = (0, import_react41.useRef)(false);
11700
+ const directionRef = (0, import_react41.useRef)(new import_three18.Vector3());
11701
+ const geometry = (0, import_react41.useMemo)(() => createParticleGeometry(), []);
11702
+ const material = (0, import_react41.useMemo)(
11703
+ () => new import_three18.ShaderMaterial({
10982
11704
  transparent: true,
10983
11705
  depthTest: false,
10984
11706
  depthWrite: false,
10985
- side: import_three13.DoubleSide,
11707
+ side: import_three18.DoubleSide,
10986
11708
  uniforms: {
10987
11709
  map: { value: snapshot.texture },
10988
11710
  progress: { value: 0 },
10989
- grid: { value: new import_three13.Vector2(PARTICLE_GRID, PARTICLE_GRID) }
11711
+ grid: { value: new import_three18.Vector2(PARTICLE_GRID, PARTICLE_GRID) }
10990
11712
  },
10991
11713
  vertexShader: PARTICLE_VERTEX_SHADER,
10992
11714
  fragmentShader: PARTICLE_FRAGMENT_SHADER
10993
11715
  }),
10994
11716
  [snapshot.texture]
10995
11717
  );
10996
- (0, import_react39.useEffect)(() => () => geometry.dispose(), [geometry]);
10997
- (0, import_react39.useEffect)(() => () => material.dispose(), [material]);
10998
- (0, import_react39.useEffect)(() => {
11718
+ (0, import_react41.useEffect)(() => () => geometry.dispose(), [geometry]);
11719
+ (0, import_react41.useEffect)(() => () => material.dispose(), [material]);
11720
+ (0, import_react41.useEffect)(() => {
10999
11721
  startRef.current = null;
11000
11722
  finishedRef.current = false;
11001
11723
  material.uniforms.progress.value = 0;
11002
11724
  }, [material, runId]);
11003
- (0, import_fiber17.useFrame)((state) => {
11725
+ (0, import_fiber18.useFrame)((state) => {
11004
11726
  const mesh = meshRef.current;
11005
11727
  if (!mesh || !isPerspectiveCamera(camera)) {
11006
11728
  return;
@@ -11017,7 +11739,7 @@ function ParticleOverlay({
11017
11739
  onFinish();
11018
11740
  }
11019
11741
  });
11020
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
11742
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
11021
11743
  "mesh",
11022
11744
  {
11023
11745
  ref: meshRef,
@@ -11030,12 +11752,12 @@ function ParticleOverlay({
11030
11752
  }
11031
11753
 
11032
11754
  // src/scene-transitions/snapshot-overlay.tsx
11033
- var import_fiber18 = require("@react-three/fiber");
11034
- var import_react40 = require("react");
11035
- var import_three15 = require("three");
11755
+ var import_fiber19 = require("@react-three/fiber");
11756
+ var import_react42 = require("react");
11757
+ var import_three20 = require("three");
11036
11758
 
11037
11759
  // src/scene-transitions/snapshot-shaders.ts
11038
- var import_three14 = require("three");
11760
+ var import_three19 = require("three");
11039
11761
  var SNAPSHOT_VERTEX_SHADER = `
11040
11762
  varying vec2 vUv;
11041
11763
  void main() {
@@ -11295,15 +12017,15 @@ var SNAPSHOT_FRAGMENT_SHADERS = {
11295
12017
  `)
11296
12018
  };
11297
12019
  function createSnapshotMaterial(preset, texture) {
11298
- return new import_three14.ShaderMaterial({
12020
+ return new import_three19.ShaderMaterial({
11299
12021
  transparent: true,
11300
12022
  depthTest: false,
11301
12023
  depthWrite: false,
11302
- side: import_three14.DoubleSide,
12024
+ side: import_three19.DoubleSide,
11303
12025
  uniforms: {
11304
12026
  map: { value: texture },
11305
12027
  progress: { value: 0 },
11306
- resolution: { value: new import_three14.Vector2(1, 1) }
12028
+ resolution: { value: new import_three19.Vector2(1, 1) }
11307
12029
  },
11308
12030
  vertexShader: SNAPSHOT_VERTEX_SHADER,
11309
12031
  fragmentShader: SNAPSHOT_FRAGMENT_SHADERS[preset]
@@ -11311,7 +12033,7 @@ function createSnapshotMaterial(preset, texture) {
11311
12033
  }
11312
12034
 
11313
12035
  // src/scene-transitions/snapshot-overlay.tsx
11314
- var import_jsx_runtime18 = require("react/jsx-runtime");
12036
+ var import_jsx_runtime19 = require("react/jsx-runtime");
11315
12037
  function SnapshotOverlay({
11316
12038
  snapshot,
11317
12039
  transition,
@@ -11319,26 +12041,26 @@ function SnapshotOverlay({
11319
12041
  runId,
11320
12042
  onFinish
11321
12043
  }) {
11322
- const { camera, gl } = (0, import_fiber18.useThree)();
11323
- const meshRef = (0, import_react40.useRef)(null);
11324
- const startRef = (0, import_react40.useRef)(null);
11325
- const finishedRef = (0, import_react40.useRef)(false);
11326
- const directionRef = (0, import_react40.useRef)(new import_three15.Vector3());
11327
- const material = (0, import_react40.useMemo)(() => {
12044
+ const { camera, gl } = (0, import_fiber19.useThree)();
12045
+ const meshRef = (0, import_react42.useRef)(null);
12046
+ const startRef = (0, import_react42.useRef)(null);
12047
+ const finishedRef = (0, import_react42.useRef)(false);
12048
+ const directionRef = (0, import_react42.useRef)(new import_three20.Vector3());
12049
+ const material = (0, import_react42.useMemo)(() => {
11328
12050
  if (!isSnapshotTransition(transition.preset)) {
11329
12051
  return null;
11330
12052
  }
11331
12053
  return createSnapshotMaterial(transition.preset, snapshot.texture);
11332
12054
  }, [snapshot.texture, transition.preset]);
11333
- (0, import_react40.useEffect)(() => () => material?.dispose(), [material]);
11334
- (0, import_react40.useEffect)(() => {
12055
+ (0, import_react42.useEffect)(() => () => material?.dispose(), [material]);
12056
+ (0, import_react42.useEffect)(() => {
11335
12057
  startRef.current = null;
11336
12058
  finishedRef.current = false;
11337
12059
  if (material) {
11338
12060
  material.uniforms.progress.value = 0;
11339
12061
  }
11340
12062
  }, [material, runId]);
11341
- (0, import_fiber18.useFrame)((state) => {
12063
+ (0, import_fiber19.useFrame)((state) => {
11342
12064
  const mesh = meshRef.current;
11343
12065
  if (!mesh || !material || !isPerspectiveCamera(camera)) {
11344
12066
  return;
@@ -11360,21 +12082,21 @@ function SnapshotOverlay({
11360
12082
  if (!material) {
11361
12083
  return null;
11362
12084
  }
11363
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("mesh", { ref: meshRef, renderOrder: OVERLAY_RENDER_ORDER, frustumCulled: false, children: [
11364
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("primitive", { attach: "geometry", object: FULLSCREEN_PLANE }),
11365
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("primitive", { attach: "material", object: material })
12085
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("mesh", { ref: meshRef, renderOrder: OVERLAY_RENDER_ORDER, frustumCulled: false, children: [
12086
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("primitive", { attach: "geometry", object: FULLSCREEN_PLANE }),
12087
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("primitive", { attach: "material", object: material })
11366
12088
  ] });
11367
12089
  }
11368
12090
 
11369
12091
  // src/scene-transitions/transition-overlay.tsx
11370
- var import_jsx_runtime19 = require("react/jsx-runtime");
12092
+ var import_jsx_runtime20 = require("react/jsx-runtime");
11371
12093
  function TransitionOverlay(props) {
11372
12094
  const { preset } = props.transition;
11373
12095
  switch (preset) {
11374
12096
  case "none":
11375
12097
  return null;
11376
12098
  case "particles":
11377
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ParticleOverlay, { ...props });
12099
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ParticleOverlay, { ...props });
11378
12100
  case "crossfade":
11379
12101
  case "zoom":
11380
12102
  case "blackout":
@@ -11402,7 +12124,7 @@ function TransitionOverlay(props) {
11402
12124
  case "zoomBlur":
11403
12125
  case "hexDissolve":
11404
12126
  case "filmBurn":
11405
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(SnapshotOverlay, { ...props });
12127
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(SnapshotOverlay, { ...props });
11406
12128
  default: {
11407
12129
  const exhaustive = preset;
11408
12130
  void exhaustive;
@@ -11412,233 +12134,10 @@ function TransitionOverlay(props) {
11412
12134
  }
11413
12135
 
11414
12136
  // src/tile/texture-manager-context.tsx
11415
- var import_fiber19 = require("@react-three/fiber");
11416
- var import_react41 = require("react");
11417
-
11418
- // src/tile/texture-manager.ts
11419
- var import_three16 = require("three");
11420
- var EMPTY_TEXTURE_SNAPSHOT = {
11421
- status: "idle",
11422
- texture: null,
11423
- error: null
11424
- };
11425
- var TileTextureManager = class {
11426
- constructor(options) {
11427
- this.loader = new import_three16.TextureLoader();
11428
- this.entries = /* @__PURE__ */ new Map();
11429
- this.queue = [];
11430
- this.activeLoads = 0;
11431
- this.totalBytes = 0;
11432
- this.requested = 0;
11433
- this.loaded = 0;
11434
- this.failed = 0;
11435
- this.disposed = false;
11436
- this.generation = 0;
11437
- this.options = options;
11438
- }
11439
- resume() {
11440
- this.disposed = false;
11441
- this.drain();
11442
- }
11443
- getSnapshot(key) {
11444
- const entry = this.entries.get(key);
11445
- return entry ? this.snapshot(entry) : EMPTY_TEXTURE_SNAPSHOT;
11446
- }
11447
- acquire(key, url, address, listener) {
11448
- let entry = this.entries.get(key);
11449
- if (!entry) {
11450
- entry = {
11451
- key,
11452
- url,
11453
- address,
11454
- status: "idle",
11455
- texture: null,
11456
- error: null,
11457
- refs: 0,
11458
- listeners: /* @__PURE__ */ new Set(),
11459
- lastUsed: performance.now(),
11460
- bytes: 0
11461
- };
11462
- this.entries.set(key, entry);
11463
- }
11464
- entry.refs += 1;
11465
- entry.lastUsed = performance.now();
11466
- entry.listeners.add(listener);
11467
- listener(this.snapshot(entry));
11468
- if (entry.status === "idle") {
11469
- entry.status = "queued";
11470
- this.queue.push(entry);
11471
- this.requested += 1;
11472
- this.emitProgress();
11473
- this.drain();
11474
- }
11475
- return () => {
11476
- entry.listeners.delete(listener);
11477
- entry.refs = Math.max(0, entry.refs - 1);
11478
- entry.lastUsed = performance.now();
11479
- if (entry.refs === 0 && entry.status === "queued") {
11480
- const queueIndex = this.queue.indexOf(entry);
11481
- if (queueIndex >= 0) {
11482
- this.queue.splice(queueIndex, 1);
11483
- }
11484
- entry.status = "idle";
11485
- this.entries.delete(entry.key);
11486
- this.requested = Math.max(0, this.requested - 1);
11487
- this.emitProgress();
11488
- this.drain();
11489
- return;
11490
- }
11491
- this.evict();
11492
- };
11493
- }
11494
- dispose() {
11495
- this.disposed = true;
11496
- this.generation += 1;
11497
- this.queue.length = 0;
11498
- for (const entry of this.entries.values()) {
11499
- entry.texture?.dispose();
11500
- entry.listeners.clear();
11501
- }
11502
- this.entries.clear();
11503
- this.totalBytes = 0;
11504
- }
11505
- /**
11506
- * Releases textures that are no longer rendered by any Tile instance.
11507
- * Scene transitions call this after the outgoing panorama has been
11508
- * snapshotted, so the incoming scene never competes with stale GPU tiles.
11509
- */
11510
- releaseUnused() {
11511
- for (const entry of Array.from(this.entries.values())) {
11512
- if (entry.refs > 0) {
11513
- continue;
11514
- }
11515
- entry.texture?.dispose();
11516
- this.totalBytes -= entry.bytes;
11517
- this.entries.delete(entry.key);
11518
- }
11519
- this.totalBytes = Math.max(0, this.totalBytes);
11520
- }
11521
- snapshot(entry) {
11522
- return {
11523
- status: entry.status,
11524
- texture: entry.texture,
11525
- error: entry.error
11526
- };
11527
- }
11528
- notify(entry) {
11529
- const snapshot = this.snapshot(entry);
11530
- for (const listener of entry.listeners) {
11531
- listener(snapshot);
11532
- }
11533
- }
11534
- emitProgress() {
11535
- this.options.onProgress?.({
11536
- requested: this.requested,
11537
- loaded: this.loaded,
11538
- failed: this.failed,
11539
- active: this.activeLoads,
11540
- queued: this.queue.length
11541
- });
11542
- }
11543
- drain() {
11544
- while (!this.disposed && this.activeLoads < this.options.concurrency && this.queue.length > 0) {
11545
- const entry = this.queue.shift();
11546
- if (entry.refs === 0) {
11547
- entry.status = "idle";
11548
- this.entries.delete(entry.key);
11549
- this.requested = Math.max(0, this.requested - 1);
11550
- continue;
11551
- }
11552
- entry.status = "loading";
11553
- this.activeLoads += 1;
11554
- this.notify(entry);
11555
- this.emitProgress();
11556
- void this.loadAndFinish(entry);
11557
- }
11558
- }
11559
- async load(entry, generation) {
11560
- let lastError = null;
11561
- for (let attempt = 0; attempt <= this.options.retryCount; attempt += 1) {
11562
- try {
11563
- const texture = await this.loader.loadAsync(entry.url);
11564
- if (this.disposed || generation !== this.generation) {
11565
- texture.dispose();
11566
- return;
11567
- }
11568
- this.configureTexture(texture);
11569
- entry.texture = texture;
11570
- entry.status = "loaded";
11571
- entry.error = null;
11572
- entry.bytes = entry.address.width * entry.address.height * 4;
11573
- entry.lastUsed = performance.now();
11574
- this.totalBytes += entry.bytes;
11575
- this.loaded += 1;
11576
- this.notify(entry);
11577
- return;
11578
- } catch (error) {
11579
- lastError = error;
11580
- }
11581
- }
11582
- if (!this.disposed && generation === this.generation) {
11583
- entry.status = "error";
11584
- entry.error = lastError;
11585
- this.failed += 1;
11586
- this.notify(entry);
11587
- this.options.onError?.({
11588
- address: entry.address,
11589
- url: entry.url,
11590
- error: lastError
11591
- });
11592
- }
11593
- }
11594
- configureTexture(texture) {
11595
- texture.colorSpace = import_three16.SRGBColorSpace;
11596
- texture.wrapS = import_three16.ClampToEdgeWrapping;
11597
- texture.wrapT = import_three16.ClampToEdgeWrapping;
11598
- texture.magFilter = import_three16.LinearFilter;
11599
- texture.minFilter = import_three16.LinearFilter;
11600
- texture.generateMipmaps = false;
11601
- texture.anisotropy = Math.min(4, this.options.anisotropy);
11602
- texture.needsUpdate = true;
11603
- }
11604
- evict() {
11605
- if (this.totalBytes <= this.options.maxBytes) {
11606
- return;
11607
- }
11608
- const candidates = Array.from(this.entries.values()).filter((entry) => entry.refs === 0 && entry.texture).sort((a, b) => a.lastUsed - b.lastUsed);
11609
- for (const entry of candidates) {
11610
- if (this.totalBytes <= this.options.maxBytes) {
11611
- break;
11612
- }
11613
- entry.texture?.dispose();
11614
- this.totalBytes -= entry.bytes;
11615
- this.entries.delete(entry.key);
11616
- }
11617
- this.totalBytes = Math.max(0, this.totalBytes);
11618
- }
11619
- finishLoad(generation) {
11620
- this.activeLoads = Math.max(0, this.activeLoads - 1);
11621
- if (!this.disposed && generation === this.generation) {
11622
- this.emitProgress();
11623
- this.evict();
11624
- }
11625
- if (!this.disposed) {
11626
- this.drain();
11627
- }
11628
- }
11629
- async loadAndFinish(entry) {
11630
- const generation = this.generation;
11631
- try {
11632
- await this.load(entry, generation);
11633
- } finally {
11634
- this.finishLoad(generation);
11635
- }
11636
- }
11637
- };
11638
-
11639
- // src/tile/texture-manager-context.tsx
11640
- var import_jsx_runtime20 = require("react/jsx-runtime");
11641
- var TileTextureManagerContext = (0, import_react41.createContext)(
12137
+ var import_fiber20 = require("@react-three/fiber");
12138
+ var import_react43 = require("react");
12139
+ var import_jsx_runtime21 = require("react/jsx-runtime");
12140
+ var TileTextureManagerContext = (0, import_react43.createContext)(
11642
12141
  null
11643
12142
  );
11644
12143
  function TileTextureManagerProvider({
@@ -11646,9 +12145,9 @@ function TileTextureManagerProvider({
11646
12145
  maxTextureMemoryMb = 128,
11647
12146
  maxConcurrentLoads = 4
11648
12147
  }) {
11649
- const gl = (0, import_fiber19.useThree)((state) => state.gl);
12148
+ const gl = (0, import_fiber20.useThree)((state) => state.gl);
11650
12149
  const anisotropy = gl.capabilities.getMaxAnisotropy();
11651
- const manager = (0, import_react41.useMemo)(
12150
+ const manager = (0, import_react43.useMemo)(
11652
12151
  () => new TileTextureManager({
11653
12152
  anisotropy,
11654
12153
  maxBytes: Math.max(1, maxTextureMemoryMb) * 1024 * 1024,
@@ -11657,23 +12156,23 @@ function TileTextureManagerProvider({
11657
12156
  }),
11658
12157
  [anisotropy, maxConcurrentLoads, maxTextureMemoryMb]
11659
12158
  );
11660
- (0, import_react41.useEffect)(() => {
12159
+ (0, import_react43.useEffect)(() => {
11661
12160
  manager.resume();
11662
12161
  return () => manager.dispose();
11663
12162
  }, [manager]);
11664
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TileTextureManagerContext.Provider, { value: manager, children });
12163
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TileTextureManagerContext.Provider, { value: manager, children });
11665
12164
  }
11666
12165
  function useSharedTileTextureManager() {
11667
- return (0, import_react41.useContext)(TileTextureManagerContext);
12166
+ return (0, import_react43.useContext)(TileTextureManagerContext);
11668
12167
  }
11669
12168
 
11670
12169
  // src/tile/tile.tsx
11671
- var import_fiber20 = require("@react-three/fiber");
11672
- var import_react42 = require("react");
11673
- var import_three18 = require("three");
12170
+ var import_fiber21 = require("@react-three/fiber");
12171
+ var import_react44 = require("react");
12172
+ var import_three22 = require("three");
11674
12173
 
11675
12174
  // src/tile/face-layout.ts
11676
- var import_three17 = require("three");
12175
+ var import_three21 = require("three");
11677
12176
  var CUBE_FACES = ["f", "r", "b", "l", "u", "d"];
11678
12177
  var PREVIEW_FACE_ORDER = ["l", "f", "r", "b", "u", "d"];
11679
12178
  var CUBE_RADIUS = DEFAULT_PANORAMA_RADIUS;
@@ -11724,8 +12223,8 @@ function getFaceQuaternion(face) {
11724
12223
  return cached;
11725
12224
  }
11726
12225
  const transform = getFaceTransform(face);
11727
- const quaternion = new import_three17.Quaternion().setFromEuler(
11728
- new import_three17.Euler(...transform.rotation, "XYZ")
12226
+ const quaternion = new import_three21.Quaternion().setFromEuler(
12227
+ new import_three21.Euler(...transform.rotation, "XYZ")
11729
12228
  );
11730
12229
  faceQuaternionCache.set(face, quaternion);
11731
12230
  return quaternion;
@@ -11736,17 +12235,17 @@ function getTileBoundingBox(address, radius = CUBE_RADIUS) {
11736
12235
  const halfWidth = local.width / 2;
11737
12236
  const halfHeight = local.height / 2;
11738
12237
  const quaternion = getFaceQuaternion(address.face);
11739
- const position = new import_three17.Vector3(...transform.position);
12238
+ const position = new import_three21.Vector3(...transform.position);
11740
12239
  const corners = [
11741
- new import_three17.Vector3(local.x - halfWidth, local.y - halfHeight, 0),
11742
- new import_three17.Vector3(local.x + halfWidth, local.y - halfHeight, 0),
11743
- new import_three17.Vector3(local.x - halfWidth, local.y + halfHeight, 0),
11744
- new import_three17.Vector3(local.x + halfWidth, local.y + halfHeight, 0)
12240
+ new import_three21.Vector3(local.x - halfWidth, local.y - halfHeight, 0),
12241
+ new import_three21.Vector3(local.x + halfWidth, local.y - halfHeight, 0),
12242
+ new import_three21.Vector3(local.x - halfWidth, local.y + halfHeight, 0),
12243
+ new import_three21.Vector3(local.x + halfWidth, local.y + halfHeight, 0)
11745
12244
  ];
11746
12245
  for (const corner of corners) {
11747
12246
  corner.applyQuaternion(quaternion).add(position);
11748
12247
  }
11749
- return new import_three17.Box3().setFromPoints(corners);
12248
+ return new import_three21.Box3().setFromPoints(corners);
11750
12249
  }
11751
12250
  function makeTileAddress(face, level, faceSize, tileSize, col, row) {
11752
12251
  const left = (col - 1) * tileSize;
@@ -11793,7 +12292,7 @@ function previewAtlasVRange(face, faceOrder = PREVIEW_FACE_ORDER) {
11793
12292
  }
11794
12293
 
11795
12294
  // src/tile/multires.ts
11796
- function positiveInteger(value, name) {
12295
+ function positiveInteger2(value, name) {
11797
12296
  if (!Number.isFinite(value) || value <= 0 || !Number.isInteger(value)) {
11798
12297
  throw new Error(`${name} must be a positive integer, received ${String(value)}`);
11799
12298
  }
@@ -11809,110 +12308,61 @@ function ascendingLevels(levels) {
11809
12308
  }
11810
12309
  function parseMultires(multires) {
11811
12310
  if (typeof multires !== "string") {
11812
- const tileSize2 = positiveInteger(multires.tileSize, "multires.tileSize");
12311
+ const tileSize2 = positiveInteger2(multires.tileSize, "multires.tileSize");
11813
12312
  if (multires.levels.length === 0) {
11814
12313
  throw new Error("multires.levels must contain at least one face size");
11815
12314
  }
11816
12315
  const levels2 = ascendingLevels(
11817
12316
  multires.levels.map(
11818
- (level, index) => positiveInteger(level, `multires.levels[${index}]`)
12317
+ (level, index) => positiveInteger2(level, `multires.levels[${index}]`)
11819
12318
  )
11820
12319
  );
11821
- return { tileSize: tileSize2, levels: levels2 };
11822
- }
11823
- const values = multires.split(",").map((part) => Number(part.trim()));
11824
- if (values.length < 2 || values.some((value) => !Number.isFinite(value))) {
11825
- throw new Error(
11826
- "multires must contain a tile size followed by at least one face size"
11827
- );
11828
- }
11829
- const tileSize = positiveInteger(values[0], "multires tile size");
11830
- const levels = ascendingLevels(
11831
- values.slice(1).map(
11832
- (level, index) => positiveInteger(level, `multires level ${index + 1}`)
11833
- )
11834
- );
11835
- return { tileSize, levels };
11836
- }
11837
- var DEFAULT_TILE_URL_TEMPLATE = "tiles/%s/l%l/%v/l%l_%s_%h_%v.webp";
11838
- function buildDefaultTileUrlTemplate() {
11839
- return DEFAULT_TILE_URL_TEMPLATE;
11840
- }
11841
- function resolveRelativeTileUrl(baseUrl, relativePath) {
11842
- return resolveRelativeAssetUrl(baseUrl, relativePath);
11843
- }
11844
- function resolveTemplateUrl(template, address) {
11845
- return template.replace(/%s/g, address.face).replace(/%l/g, String(address.level)).replace(/%(0*)([hxucvywr])/g, (_match, zeroes, placeholder) => {
11846
- const value = "hxuc".includes(placeholder) ? address.col : address.row;
11847
- return String(value).padStart(zeroes.length + 1, "0");
11848
- });
11849
- }
11850
-
11851
- // src/tile/tile.tsx
11852
- var import_jsx_runtime21 = require("react/jsx-runtime");
11853
- var MAX_LOD_UPDATE_INTERVAL_MS = 100;
11854
- var FAST_ROTATION_THRESHOLD_RADIANS = Math.PI / 180;
11855
- var FAST_FOV_THRESHOLD_DEGREES = 0.5;
11856
- var VIEW_CHANGE_EPSILON = 1e-4;
11857
- var VISIBILITY_FOV_PADDING_DEGREES = 8;
11858
- var PREVIEW_RADIUS = CUBE_RADIUS + 0.05;
11859
- var SHARED_TILE_GEOMETRY = new import_three18.PlaneGeometry(1, 1);
11860
- function usePreviewTexture(url, anisotropy, onError) {
11861
- const [texture, setTexture] = (0, import_react42.useState)(null);
11862
- const onErrorRef = (0, import_react42.useRef)(onError);
11863
- onErrorRef.current = onError;
11864
- (0, import_react42.useEffect)(() => {
11865
- if (!url) {
11866
- setTexture(null);
11867
- return;
11868
- }
11869
- let active = true;
11870
- const loader = new import_three18.TextureLoader();
11871
- setTexture(null);
11872
- loader.load(
11873
- url,
11874
- (loadedTexture) => {
11875
- if (!active) {
11876
- loadedTexture.dispose();
11877
- return;
11878
- }
11879
- loadedTexture.colorSpace = import_three18.SRGBColorSpace;
11880
- loadedTexture.wrapS = import_three18.ClampToEdgeWrapping;
11881
- loadedTexture.wrapT = import_three18.ClampToEdgeWrapping;
11882
- loadedTexture.magFilter = import_three18.LinearFilter;
11883
- loadedTexture.minFilter = import_three18.LinearFilter;
11884
- loadedTexture.generateMipmaps = false;
11885
- loadedTexture.anisotropy = Math.min(4, anisotropy);
11886
- loadedTexture.needsUpdate = true;
11887
- setTexture(loadedTexture);
11888
- },
11889
- void 0,
11890
- (error) => {
11891
- if (active) {
11892
- setTexture(null);
11893
- onErrorRef.current?.(error);
11894
- }
11895
- }
11896
- );
11897
- return () => {
11898
- active = false;
11899
- };
11900
- }, [anisotropy, url]);
11901
- (0, import_react42.useEffect)(
11902
- () => () => {
11903
- texture?.dispose();
11904
- },
11905
- [texture]
12320
+ return { tileSize: tileSize2, levels: levels2 };
12321
+ }
12322
+ const values = multires.split(",").map((part) => Number(part.trim()));
12323
+ if (values.length < 2 || values.some((value) => !Number.isFinite(value))) {
12324
+ throw new Error(
12325
+ "multires must contain a tile size followed by at least one face size"
12326
+ );
12327
+ }
12328
+ const tileSize = positiveInteger2(values[0], "multires tile size");
12329
+ const levels = ascendingLevels(
12330
+ values.slice(1).map(
12331
+ (level, index) => positiveInteger2(level, `multires level ${index + 1}`)
12332
+ )
11906
12333
  );
11907
- return texture;
12334
+ return { tileSize, levels };
12335
+ }
12336
+ var DEFAULT_TILE_URL_TEMPLATE = "tiles/%s/l%l/%v/l%l_%s_%h_%v.webp";
12337
+ function buildDefaultTileUrlTemplate() {
12338
+ return DEFAULT_TILE_URL_TEMPLATE;
12339
+ }
12340
+ function resolveRelativeTileUrl(baseUrl, relativePath) {
12341
+ return resolveRelativeAssetUrl(baseUrl, relativePath);
12342
+ }
12343
+ function resolveTemplateUrl(template, address) {
12344
+ return template.replace(/%s/g, address.face).replace(/%l/g, String(address.level)).replace(/%(0*)([hxucvywr])/g, (_match, zeroes, placeholder) => {
12345
+ const value = "hxuc".includes(placeholder) ? address.col : address.row;
12346
+ return String(value).padStart(zeroes.length + 1, "0");
12347
+ });
11908
12348
  }
12349
+
12350
+ // src/tile/tile.tsx
12351
+ var import_jsx_runtime22 = require("react/jsx-runtime");
12352
+ var MAX_LOD_UPDATE_INTERVAL_MS = 100;
12353
+ var FAST_ROTATION_THRESHOLD_RADIANS = Math.PI / 180;
12354
+ var FAST_FOV_THRESHOLD_DEGREES = 0.5;
12355
+ var VIEW_CHANGE_EPSILON = 1e-4;
12356
+ var VISIBILITY_FOV_PADDING_DEGREES = 8;
12357
+ var PREVIEW_RADIUS = CUBE_RADIUS + 0.05;
12358
+ var SHARED_TILE_GEOMETRY = new import_three22.PlaneGeometry(1, 1);
11909
12359
  function PreviewFace({
11910
12360
  face,
11911
12361
  texture,
11912
12362
  faceOrder
11913
12363
  }) {
11914
- const geometry = (0, import_react42.useMemo)(() => {
11915
- const nextGeometry = new import_three18.PlaneGeometry(
12364
+ const geometry = (0, import_react44.useMemo)(() => {
12365
+ const nextGeometry = new import_three22.PlaneGeometry(
11916
12366
  PREVIEW_RADIUS * 2,
11917
12367
  PREVIEW_RADIUS * 2
11918
12368
  );
@@ -11921,29 +12371,26 @@ function PreviewFace({
11921
12371
  const inset = scale / 512;
11922
12372
  for (let index = 0; index < uv.count; index += 1) {
11923
12373
  const sourceV = uv.getY(index);
11924
- uv.setY(
11925
- index,
11926
- offset + inset + sourceV * Math.max(0, scale - inset * 2)
11927
- );
12374
+ uv.setY(index, offset + inset + sourceV * Math.max(0, scale - inset * 2));
11928
12375
  }
11929
12376
  uv.needsUpdate = true;
11930
12377
  return nextGeometry;
11931
12378
  }, [face, faceOrder]);
11932
- (0, import_react42.useEffect)(
12379
+ (0, import_react44.useEffect)(
11933
12380
  () => () => {
11934
12381
  geometry.dispose();
11935
12382
  },
11936
12383
  [geometry]
11937
12384
  );
11938
12385
  const transform = getFaceTransform(face, PREVIEW_RADIUS);
11939
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
12386
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
11940
12387
  "mesh",
11941
12388
  {
11942
12389
  geometry,
11943
12390
  position: transform.position,
11944
12391
  renderOrder: -100,
11945
12392
  rotation: transform.rotation,
11946
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
12393
+ children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
11947
12394
  PanoBasicMaterial,
11948
12395
  {
11949
12396
  depthTest: false,
@@ -11959,7 +12406,7 @@ function PreviewCube({
11959
12406
  texture,
11960
12407
  faceOrder
11961
12408
  }) {
11962
- return CUBE_FACES.map((face) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
12409
+ return CUBE_FACES.map((face) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
11963
12410
  PreviewFace,
11964
12411
  {
11965
12412
  face,
@@ -11969,28 +12416,7 @@ function PreviewCube({
11969
12416
  face
11970
12417
  ));
11971
12418
  }
11972
- function useManagedTexture(manager, key, url, address) {
11973
- const [managedState, setManagedState] = (0, import_react42.useState)(() => ({
11974
- manager,
11975
- key,
11976
- url,
11977
- snapshot: manager.getSnapshot(key)
11978
- }));
11979
- const snapshot = managedState.manager === manager && managedState.key === key && managedState.url === url ? managedState.snapshot : manager.getSnapshot(key);
11980
- (0, import_react42.useEffect)(
11981
- () => manager.acquire(key, url, address, (nextSnapshot) => {
11982
- setManagedState({
11983
- manager,
11984
- key,
11985
- url,
11986
- snapshot: nextSnapshot
11987
- });
11988
- }),
11989
- [key, manager, url]
11990
- );
11991
- return snapshot;
11992
- }
11993
- var TileMesh = (0, import_react42.memo)(function TileMesh2({
12419
+ var TileMesh = (0, import_react44.memo)(function TileMesh2({
11994
12420
  address,
11995
12421
  manager,
11996
12422
  renderOrder,
@@ -12004,14 +12430,14 @@ var TileMesh = (0, import_react42.memo)(function TileMesh2({
12004
12430
  if (!snapshot.texture) {
12005
12431
  return null;
12006
12432
  }
12007
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("group", { position: transform.position, rotation: transform.rotation, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
12433
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("group", { position: transform.position, rotation: transform.rotation, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
12008
12434
  "mesh",
12009
12435
  {
12010
12436
  geometry: SHARED_TILE_GEOMETRY,
12011
12437
  position: [layout.x, layout.y, 0],
12012
12438
  renderOrder,
12013
12439
  scale: [layout.width, layout.height, 1],
12014
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
12440
+ children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
12015
12441
  PanoBasicMaterial,
12016
12442
  {
12017
12443
  depthTest: false,
@@ -12023,12 +12449,12 @@ var TileMesh = (0, import_react42.memo)(function TileMesh2({
12023
12449
  }
12024
12450
  ) });
12025
12451
  });
12026
- var TileLayerMeshes = (0, import_react42.memo)(function TileLayerMeshes2({
12452
+ var TileLayerMeshes = (0, import_react44.memo)(function TileLayerMeshes2({
12027
12453
  layer,
12028
12454
  manager,
12029
12455
  resolveUrl
12030
12456
  }) {
12031
- return layer.addresses.map((address) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
12457
+ return layer.addresses.map((address) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
12032
12458
  TileMesh,
12033
12459
  {
12034
12460
  address,
@@ -12128,8 +12554,8 @@ function parentAddresses(child, parentLevel, parentFaceSize, tileSize) {
12128
12554
  return addresses;
12129
12555
  }
12130
12556
  function centerFacingAddress(candidates, camera) {
12131
- const direction = camera.getWorldDirection(new import_three18.Vector3());
12132
- const center = new import_three18.Vector3();
12557
+ const direction = camera.getWorldDirection(new import_three22.Vector3());
12558
+ const center = new import_three22.Vector3();
12133
12559
  let bestCandidate = candidates[0];
12134
12560
  let bestAlignment = -Infinity;
12135
12561
  for (const candidate of candidates) {
@@ -12174,9 +12600,7 @@ function buildLayers(targetLevel, levels, tileSize, frustum, camera, candidatesB
12174
12600
  }));
12175
12601
  }
12176
12602
  function layerToken(layers) {
12177
- return layers.map(
12178
- (layer) => `${layer.level}:${layer.addresses.map(tileKey).join(",")}`
12179
- ).join("|");
12603
+ return layers.map((layer) => `${layer.level}:${layer.addresses.map(tileKey).join(",")}`).join("|");
12180
12604
  }
12181
12605
  function Tile({
12182
12606
  baseUrl,
@@ -12196,11 +12620,11 @@ function Tile({
12196
12620
  onTileError,
12197
12621
  onLevelChange
12198
12622
  }) {
12199
- const { camera, gl, size } = (0, import_fiber20.useThree)();
12200
- const multiresConfig = (0, import_react42.useMemo)(() => parseMultires(multires), [multires]);
12623
+ const { camera, gl, size } = (0, import_fiber21.useThree)();
12624
+ const multiresConfig = (0, import_react44.useMemo)(() => parseMultires(multires), [multires]);
12201
12625
  const { levels, tileSize } = multiresConfig;
12202
12626
  const multiresToken = `${tileSize}:${levels.join(",")}`;
12203
- const candidatesByLevel = (0, import_react42.useMemo)(
12627
+ const candidatesByLevel = (0, import_react44.useMemo)(
12204
12628
  () => buildTileCandidates(levels, tileSize),
12205
12629
  [levels, tileSize]
12206
12630
  );
@@ -12212,13 +12636,13 @@ function Tile({
12212
12636
  onPreviewError
12213
12637
  );
12214
12638
  const sharedManager = useSharedTileTextureManager();
12215
- const progressRef = (0, import_react42.useRef)(onLoadProgress);
12216
- const errorRef = (0, import_react42.useRef)(onTileError);
12217
- const levelChangeRef = (0, import_react42.useRef)(onLevelChange);
12639
+ const progressRef = (0, import_react44.useRef)(onLoadProgress);
12640
+ const errorRef = (0, import_react44.useRef)(onTileError);
12641
+ const levelChangeRef = (0, import_react44.useRef)(onLevelChange);
12218
12642
  progressRef.current = onLoadProgress;
12219
12643
  errorRef.current = onTileError;
12220
12644
  levelChangeRef.current = onLevelChange;
12221
- const ownedManager = (0, import_react42.useMemo)(
12645
+ const ownedManager = (0, import_react44.useMemo)(
12222
12646
  () => new TileTextureManager({
12223
12647
  anisotropy,
12224
12648
  maxBytes: Math.max(1, maxTextureMemoryMb) * 1024 * 1024,
@@ -12239,7 +12663,7 @@ function Tile({
12239
12663
  ]
12240
12664
  );
12241
12665
  const manager = sharedManager ?? ownedManager;
12242
- (0, import_react42.useEffect)(() => {
12666
+ (0, import_react44.useEffect)(() => {
12243
12667
  manager.resume();
12244
12668
  return () => {
12245
12669
  if (manager === ownedManager) {
@@ -12249,11 +12673,11 @@ function Tile({
12249
12673
  queueMicrotask(() => manager.releaseUnused());
12250
12674
  };
12251
12675
  }, [manager, ownedManager]);
12252
- const readyRef = (0, import_react42.useRef)(false);
12253
- (0, import_react42.useEffect)(() => {
12676
+ const readyRef = (0, import_react44.useRef)(false);
12677
+ (0, import_react44.useEffect)(() => {
12254
12678
  readyRef.current = false;
12255
12679
  }, [effectivePreviewUrl]);
12256
- (0, import_react42.useEffect)(() => {
12680
+ (0, import_react44.useEffect)(() => {
12257
12681
  if (!previewTexture || readyRef.current) {
12258
12682
  return;
12259
12683
  }
@@ -12261,31 +12685,31 @@ function Tile({
12261
12685
  onReady?.();
12262
12686
  }, [onReady, previewTexture]);
12263
12687
  const template = urlTemplate ?? buildDefaultTileUrlTemplate();
12264
- const resolveUrl = (0, import_react42.useMemo)(
12688
+ const resolveUrl = (0, import_react44.useMemo)(
12265
12689
  () => (address) => {
12266
12690
  const relativePath = resolveTileUrl ? resolveTileUrl(address) : resolveTemplateUrl(template, address);
12267
12691
  return resolveRelativeTileUrl(baseUrl, relativePath);
12268
12692
  },
12269
12693
  [baseUrl, resolveTileUrl, template]
12270
12694
  );
12271
- const [layers, setLayers] = (0, import_react42.useState)([]);
12272
- const layerTokenRef = (0, import_react42.useRef)("");
12273
- const currentLevelRef = (0, import_react42.useRef)(1);
12274
- const lastUpdateAtRef = (0, import_react42.useRef)(-Infinity);
12275
- const visibilityDirtyRef = (0, import_react42.useRef)(true);
12276
- const lastVisibilityQuaternionRef = (0, import_react42.useRef)(camera.quaternion.clone());
12277
- const lastVisibilityFovRef = (0, import_react42.useRef)(Number.NaN);
12278
- const lastViewportRef = (0, import_react42.useRef)({ width: 0, height: 0, dpr: 0 });
12279
- const frustumRef = (0, import_react42.useRef)(new import_three18.Frustum());
12280
- const projectionMatrixRef = (0, import_react42.useRef)(new import_three18.Matrix4());
12281
- const visibilityCameraRef = (0, import_react42.useRef)(new import_three18.PerspectiveCamera());
12282
- (0, import_react42.useEffect)(() => {
12695
+ const [layers, setLayers] = (0, import_react44.useState)([]);
12696
+ const layerTokenRef = (0, import_react44.useRef)("");
12697
+ const currentLevelRef = (0, import_react44.useRef)(1);
12698
+ const lastUpdateAtRef = (0, import_react44.useRef)(-Infinity);
12699
+ const visibilityDirtyRef = (0, import_react44.useRef)(true);
12700
+ const lastVisibilityQuaternionRef = (0, import_react44.useRef)(camera.quaternion.clone());
12701
+ const lastVisibilityFovRef = (0, import_react44.useRef)(Number.NaN);
12702
+ const lastViewportRef = (0, import_react44.useRef)({ width: 0, height: 0, dpr: 0 });
12703
+ const frustumRef = (0, import_react44.useRef)(new import_three22.Frustum());
12704
+ const projectionMatrixRef = (0, import_react44.useRef)(new import_three22.Matrix4());
12705
+ const visibilityCameraRef = (0, import_react44.useRef)(new import_three22.PerspectiveCamera());
12706
+ (0, import_react44.useEffect)(() => {
12283
12707
  currentLevelRef.current = 1;
12284
12708
  layerTokenRef.current = "";
12285
12709
  visibilityDirtyRef.current = true;
12286
12710
  setLayers([]);
12287
12711
  }, [manager, multiresToken]);
12288
- (0, import_react42.useEffect)(() => {
12712
+ (0, import_react44.useEffect)(() => {
12289
12713
  if (loadMode !== "preview") {
12290
12714
  return;
12291
12715
  }
@@ -12299,11 +12723,11 @@ function Tile({
12299
12723
  setLayers(nextLayers);
12300
12724
  }
12301
12725
  };
12302
- (0, import_fiber20.useFrame)(() => {
12726
+ (0, import_fiber21.useFrame)(() => {
12303
12727
  if (loadMode === "preview") {
12304
12728
  return;
12305
12729
  }
12306
- if (!(camera instanceof import_three18.PerspectiveCamera)) {
12730
+ if (!(camera instanceof import_three22.PerspectiveCamera)) {
12307
12731
  return;
12308
12732
  }
12309
12733
  const now = performance.now();
@@ -12365,15 +12789,9 @@ function Tile({
12365
12789
  };
12366
12790
  commitLayers(nextLayers);
12367
12791
  });
12368
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("group", { visible, children: [
12369
- previewTexture ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
12370
- PreviewCube,
12371
- {
12372
- texture: previewTexture,
12373
- faceOrder: previewFaceOrder
12374
- }
12375
- ) : null,
12376
- layers.map((layer) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
12792
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("group", { visible, children: [
12793
+ previewTexture ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(PreviewCube, { texture: previewTexture, faceOrder: previewFaceOrder }) : null,
12794
+ layers.map((layer) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
12377
12795
  TileLayerMeshes,
12378
12796
  {
12379
12797
  layer,
@@ -12386,7 +12804,7 @@ function Tile({
12386
12804
  }
12387
12805
 
12388
12806
  // src/scenes.tsx
12389
- var import_jsx_runtime22 = require("react/jsx-runtime");
12807
+ var import_jsx_runtime23 = require("react/jsx-runtime");
12390
12808
  function SceneSource({
12391
12809
  scene,
12392
12810
  visible,
@@ -12399,7 +12817,7 @@ function SceneSource({
12399
12817
  }
12400
12818
  switch (scene.type) {
12401
12819
  case "sphere":
12402
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
12820
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
12403
12821
  Sphere,
12404
12822
  {
12405
12823
  src: scene.src,
@@ -12412,7 +12830,7 @@ function SceneSource({
12412
12830
  );
12413
12831
  case "tile": {
12414
12832
  const { id: _id, type: _type, ...tileProps } = scene;
12415
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
12833
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
12416
12834
  Tile,
12417
12835
  {
12418
12836
  ...tileProps,
@@ -12435,17 +12853,17 @@ function SnapshotCapture({
12435
12853
  maxPixels,
12436
12854
  onCaptured
12437
12855
  }) {
12438
- const { camera, gl, scene, size } = (0, import_fiber21.useThree)();
12439
- const capturedRequestRef = (0, import_react43.useRef)(0);
12440
- const renderTargetRef = (0, import_react43.useRef)(null);
12441
- (0, import_react43.useEffect)(
12856
+ const { camera, gl, scene, size } = (0, import_fiber22.useThree)();
12857
+ const capturedRequestRef = (0, import_react45.useRef)(0);
12858
+ const renderTargetRef = (0, import_react45.useRef)(null);
12859
+ (0, import_react45.useEffect)(
12442
12860
  () => () => {
12443
12861
  renderTargetRef.current?.dispose();
12444
12862
  renderTargetRef.current = null;
12445
12863
  },
12446
12864
  []
12447
12865
  );
12448
- (0, import_fiber21.useFrame)(() => {
12866
+ (0, import_fiber22.useFrame)(() => {
12449
12867
  if (requestId === 0 || requestId === capturedRequestRef.current) {
12450
12868
  return;
12451
12869
  }
@@ -12455,14 +12873,14 @@ function SnapshotCapture({
12455
12873
  const scale = Math.min(1, Math.sqrt(maxPixels / (sourceWidth * sourceHeight)));
12456
12874
  const width = Math.max(1, Math.floor(sourceWidth * scale));
12457
12875
  const height = Math.max(1, Math.floor(sourceHeight * scale));
12458
- const nextTarget = new import_three19.WebGLRenderTarget(width, height, {
12876
+ const nextTarget = new import_three23.WebGLRenderTarget(width, height, {
12459
12877
  depthBuffer: false,
12460
12878
  stencilBuffer: false
12461
12879
  });
12462
- nextTarget.texture.colorSpace = import_three19.LinearSRGBColorSpace;
12880
+ nextTarget.texture.colorSpace = import_three23.LinearSRGBColorSpace;
12463
12881
  nextTarget.texture.generateMipmaps = false;
12464
- nextTarget.texture.minFilter = import_three19.LinearFilter;
12465
- nextTarget.texture.magFilter = import_three19.LinearFilter;
12882
+ nextTarget.texture.minFilter = import_three23.LinearFilter;
12883
+ nextTarget.texture.magFilter = import_three23.LinearFilter;
12466
12884
  const previousTarget = gl.getRenderTarget();
12467
12885
  gl.setRenderTarget(nextTarget);
12468
12886
  gl.clear();
@@ -12494,50 +12912,50 @@ function ScenesController({
12494
12912
  snapshotMaxPixels = 3686400,
12495
12913
  phaseRef: externalPhaseRef
12496
12914
  }) {
12497
- const controlsRef = (0, import_react43.useContext)(PanoramaViewContext);
12915
+ const controlsRef = (0, import_react45.useContext)(PanoramaViewContext);
12498
12916
  const manager = useSharedTileTextureManager();
12499
- const transition = (0, import_react43.useMemo)(
12917
+ const transition = (0, import_react45.useMemo)(
12500
12918
  () => resolveTransition(transitionInput),
12501
12919
  [transitionInput]
12502
12920
  );
12503
- const sceneMap = (0, import_react43.useMemo)(
12921
+ const sceneMap = (0, import_react45.useMemo)(
12504
12922
  () => new Map(scenes.map((scene) => [scene.id, scene])),
12505
12923
  [scenes]
12506
12924
  );
12507
12925
  const initialScene = sceneMap.get(activeSceneId) ?? null;
12508
- const [slots, setSlots] = (0, import_react43.useState)([
12926
+ const [slots, setSlots] = (0, import_react45.useState)([
12509
12927
  initialScene,
12510
12928
  null
12511
12929
  ]);
12512
- const [activeSlot, setActiveSlot] = (0, import_react43.useState)(0);
12513
- const [liveSlot, setLiveSlot] = (0, import_react43.useState)(0);
12514
- const [pendingSlot, setPendingSlot] = (0, import_react43.useState)(null);
12515
- const [phase, setPhase] = (0, import_react43.useState)(initialScene ? "idle" : "preloading");
12516
- const [captureRequestId, setCaptureRequestId] = (0, import_react43.useState)(0);
12517
- const [transitionRunId, setTransitionRunId] = (0, import_react43.useState)(0);
12518
- const [snapshot, setSnapshot] = (0, import_react43.useState)(null);
12519
- const [recoveryKey, setRecoveryKey] = (0, import_react43.useState)(0);
12520
- const requestedSceneIdRef = (0, import_react43.useRef)(activeSceneId);
12521
- const captureReasonRef = (0, import_react43.useRef)("start");
12522
- const interactionReleaseRef = (0, import_react43.useRef)(null);
12523
- const slotsRef = (0, import_react43.useRef)(slots);
12524
- const phaseRef = (0, import_react43.useRef)(phase);
12525
- const liveSlotRef = (0, import_react43.useRef)(liveSlot);
12526
- const transitionFromRef = (0, import_react43.useRef)(initialScene);
12930
+ const [activeSlot, setActiveSlot] = (0, import_react45.useState)(0);
12931
+ const [liveSlot, setLiveSlot] = (0, import_react45.useState)(0);
12932
+ const [pendingSlot, setPendingSlot] = (0, import_react45.useState)(null);
12933
+ const [phase, setPhase] = (0, import_react45.useState)(initialScene ? "idle" : "preloading");
12934
+ const [captureRequestId, setCaptureRequestId] = (0, import_react45.useState)(0);
12935
+ const [transitionRunId, setTransitionRunId] = (0, import_react45.useState)(0);
12936
+ const [snapshot, setSnapshot] = (0, import_react45.useState)(null);
12937
+ const [recoveryKey, setRecoveryKey] = (0, import_react45.useState)(0);
12938
+ const requestedSceneIdRef = (0, import_react45.useRef)(activeSceneId);
12939
+ const captureReasonRef = (0, import_react45.useRef)("start");
12940
+ const interactionReleaseRef = (0, import_react45.useRef)(null);
12941
+ const slotsRef = (0, import_react45.useRef)(slots);
12942
+ const phaseRef = (0, import_react45.useRef)(phase);
12943
+ const liveSlotRef = (0, import_react45.useRef)(liveSlot);
12944
+ const transitionFromRef = (0, import_react45.useRef)(initialScene);
12527
12945
  slotsRef.current = slots;
12528
12946
  phaseRef.current = phase;
12529
12947
  if (externalPhaseRef) {
12530
12948
  externalPhaseRef.current = phase;
12531
12949
  }
12532
12950
  liveSlotRef.current = liveSlot;
12533
- const releaseInteraction = (0, import_react43.useCallback)(() => {
12951
+ const releaseInteraction = (0, import_react45.useCallback)(() => {
12534
12952
  interactionReleaseRef.current?.();
12535
12953
  interactionReleaseRef.current = null;
12536
12954
  }, []);
12537
- const reportError = (0, import_react43.useCallback)((sceneId, error) => {
12955
+ const reportError = (0, import_react45.useCallback)((sceneId, error) => {
12538
12956
  onTransitionError?.({ sceneId, error });
12539
12957
  }, [onTransitionError]);
12540
- const startPreload = (0, import_react43.useCallback)((scene) => {
12958
+ const startPreload = (0, import_react45.useCallback)((scene) => {
12541
12959
  const nextSlot = 1 - liveSlotRef.current;
12542
12960
  requestedSceneIdRef.current = scene.id;
12543
12961
  setSlots((current) => {
@@ -12548,7 +12966,7 @@ function ScenesController({
12548
12966
  setPendingSlot(nextSlot);
12549
12967
  setPhase("preloading");
12550
12968
  }, []);
12551
- (0, import_react43.useEffect)(() => {
12969
+ (0, import_react45.useEffect)(() => {
12552
12970
  const requested = sceneMap.get(activeSceneId);
12553
12971
  if (!requested) {
12554
12972
  reportError(activeSceneId, new Error(`Unknown panorama scene: ${activeSceneId}`));
@@ -12572,7 +12990,7 @@ function ScenesController({
12572
12990
  }
12573
12991
  startPreload(requested);
12574
12992
  }, [activeSceneId, pendingSlot, reportError, sceneMap, startPreload]);
12575
- const handleReady = (0, import_react43.useCallback)((slot) => {
12993
+ const handleReady = (0, import_react45.useCallback)((slot) => {
12576
12994
  if (slot !== pendingSlot || phaseRef.current !== "preloading") {
12577
12995
  return;
12578
12996
  }
@@ -12603,7 +13021,7 @@ function ScenesController({
12603
13021
  setPhase("capturing");
12604
13022
  setCaptureRequestId((current) => current + 1);
12605
13023
  }, [controlsRef, onTransitionEnd, pendingSlot, transition.preset]);
12606
- const handleCaptured = (0, import_react43.useCallback)((nextSnapshot) => {
13024
+ const handleCaptured = (0, import_react45.useCallback)((nextSnapshot) => {
12607
13025
  setSnapshot((current) => {
12608
13026
  current?.dispose();
12609
13027
  return nextSnapshot;
@@ -12625,7 +13043,7 @@ function ScenesController({
12625
13043
  setPhase("transitioning");
12626
13044
  setTransitionRunId((current) => current + 1);
12627
13045
  }, [manager, pendingSlot, sceneMap, startPreload]);
12628
- const finishTransition = (0, import_react43.useCallback)(() => {
13046
+ const finishTransition = (0, import_react45.useCallback)(() => {
12629
13047
  const nextSlot = pendingSlot;
12630
13048
  const previousScene = transitionFromRef.current;
12631
13049
  const nextScene = nextSlot === null ? null : slotsRef.current[nextSlot];
@@ -12650,12 +13068,12 @@ function ScenesController({
12650
13068
  });
12651
13069
  }
12652
13070
  }, [onTransitionEnd, pendingSlot, releaseInteraction, snapshot, transition.preset]);
12653
- (0, import_react43.useEffect)(() => () => {
13071
+ (0, import_react45.useEffect)(() => () => {
12654
13072
  releaseInteraction();
12655
13073
  snapshot?.dispose();
12656
13074
  }, [releaseInteraction, snapshot]);
12657
- const { gl } = (0, import_fiber21.useThree)();
12658
- (0, import_react43.useEffect)(() => {
13075
+ const { gl } = (0, import_fiber22.useThree)();
13076
+ (0, import_react45.useEffect)(() => {
12659
13077
  const canvas = gl.domElement;
12660
13078
  const onContextLost = (event) => {
12661
13079
  event.preventDefault();
@@ -12679,8 +13097,8 @@ function ScenesController({
12679
13097
  }, [gl, manager, releaseInteraction, snapshot]);
12680
13098
  const renderedScene = slots[liveSlot];
12681
13099
  const snapshotVisible = snapshot !== null && (phase === "transitioning" || phase === "recapturing" || phase === "preloading");
12682
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react43.Fragment, { children: [
12683
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
13100
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_react45.Fragment, { children: [
13101
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
12684
13102
  SnapshotCapture,
12685
13103
  {
12686
13104
  requestId: captureRequestId,
@@ -12692,7 +13110,7 @@ function ScenesController({
12692
13110
  const source = slots[slot];
12693
13111
  const isLive = slot === liveSlot;
12694
13112
  const isPending = slot === pendingSlot;
12695
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
13113
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
12696
13114
  SceneSource,
12697
13115
  {
12698
13116
  scene: source,
@@ -12708,7 +13126,7 @@ function ScenesController({
12708
13126
  `${slot}:${source?.id ?? "empty"}:${recoveryKey}`
12709
13127
  );
12710
13128
  }),
12711
- snapshotVisible ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
13129
+ snapshotVisible ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
12712
13130
  TransitionOverlay,
12713
13131
  {
12714
13132
  snapshot,
@@ -12731,11 +13149,11 @@ function Scenes({
12731
13149
  ...rest
12732
13150
  }) {
12733
13151
  const isControlled = controlledId !== void 0;
12734
- const [internalId, setInternalId] = (0, import_react43.useState)(
13152
+ const [internalId, setInternalId] = (0, import_react45.useState)(
12735
13153
  () => controlledId ?? defaultActiveSceneId ?? scenes[0]?.id ?? ""
12736
13154
  );
12737
13155
  const resolvedId = isControlled ? controlledId : internalId;
12738
- const requestSceneChange = (0, import_react43.useCallback)(
13156
+ const requestSceneChange = (0, import_react45.useCallback)(
12739
13157
  (id) => {
12740
13158
  if (isControlled) {
12741
13159
  onActiveSceneIdChange?.(id);
@@ -12745,13 +13163,13 @@ function Scenes({
12745
13163
  },
12746
13164
  [isControlled, onActiveSceneIdChange]
12747
13165
  );
12748
- const scenesRef = (0, import_react43.useRef)(scenes);
13166
+ const scenesRef = (0, import_react45.useRef)(scenes);
12749
13167
  scenesRef.current = scenes;
12750
- const resolvedIdRef = (0, import_react43.useRef)(resolvedId);
13168
+ const resolvedIdRef = (0, import_react45.useRef)(resolvedId);
12751
13169
  resolvedIdRef.current = resolvedId;
12752
- const host = (0, import_react43.useContext)(ScenesHostContext);
12753
- const phaseRef = (0, import_react43.useRef)("idle");
12754
- (0, import_react43.useEffect)(() => {
13170
+ const host = (0, import_react45.useContext)(ScenesHostContext);
13171
+ const phaseRef = (0, import_react45.useRef)("idle");
13172
+ (0, import_react45.useEffect)(() => {
12755
13173
  if (!host) {
12756
13174
  return;
12757
13175
  }
@@ -12801,12 +13219,12 @@ function Scenes({
12801
13219
  }
12802
13220
  };
12803
13221
  }, [host, requestSceneChange]);
12804
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
13222
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
12805
13223
  TileTextureManagerProvider,
12806
13224
  {
12807
13225
  maxTextureMemoryMb,
12808
13226
  maxConcurrentLoads: maxConcurrentTileLoads,
12809
- children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
13227
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
12810
13228
  ScenesController,
12811
13229
  {
12812
13230
  ...rest,
@@ -12820,26 +13238,26 @@ function Scenes({
12820
13238
  }
12821
13239
 
12822
13240
  // src/hotspot/image-hotspot.tsx
12823
- var import_fiber23 = require("@react-three/fiber");
12824
- var import_react47 = require("react");
12825
- var import_three22 = require("three");
13241
+ var import_fiber24 = require("@react-three/fiber");
13242
+ var import_react49 = require("react");
13243
+ var import_three26 = require("three");
12826
13244
 
12827
13245
  // src/hotspot/hotspot-anchor.tsx
12828
- var import_fiber22 = require("@react-three/fiber");
12829
- var import_react46 = require("react");
12830
- var import_three20 = require("three");
13246
+ var import_fiber23 = require("@react-three/fiber");
13247
+ var import_react48 = require("react");
13248
+ var import_three24 = require("three");
12831
13249
 
12832
13250
  // src/hotspot/hotspot-tooltip.tsx
12833
- var import_react45 = require("react");
13251
+ var import_react47 = require("react");
12834
13252
 
12835
13253
  // src/webvr/stereo-html.tsx
12836
13254
  var import_drei = require("@react-three/drei");
12837
- var import_react44 = require("react");
12838
- var import_jsx_runtime23 = require("react/jsx-runtime");
13255
+ var import_react46 = require("react");
13256
+ var import_jsx_runtime24 = require("react/jsx-runtime");
12839
13257
  function useFallbackStereoView() {
12840
- const runtime = (0, import_react44.useContext)(WebVRRuntimeContext);
13258
+ const runtime = (0, import_react46.useContext)(WebVRRuntimeContext);
12841
13259
  const host = runtime?.host ?? null;
12842
- const fallback = (0, import_react44.useSyncExternalStore)(
13260
+ const fallback = (0, import_react46.useSyncExternalStore)(
12843
13261
  (onStoreChange) => host ? subscribeWebVRHost(host, onStoreChange) : () => void 0,
12844
13262
  () => isFallbackStereoMode(host?.snapshot.mode ?? null),
12845
13263
  () => false
@@ -12860,10 +13278,10 @@ function stereoCalculatePosition(eye, stereoView) {
12860
13278
  function PanoHtml({ children, ...htmlProps }) {
12861
13279
  const stereoView = useFallbackStereoView();
12862
13280
  if (!stereoView) {
12863
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_drei.Html, { ...htmlProps, children });
13281
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_drei.Html, { ...htmlProps, children });
12864
13282
  }
12865
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
12866
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
13283
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
13284
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12867
13285
  import_drei.Html,
12868
13286
  {
12869
13287
  ...htmlProps,
@@ -12871,7 +13289,7 @@ function PanoHtml({ children, ...htmlProps }) {
12871
13289
  children
12872
13290
  }
12873
13291
  ),
12874
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
13292
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12875
13293
  import_drei.Html,
12876
13294
  {
12877
13295
  ...htmlProps,
@@ -12884,7 +13302,7 @@ function PanoHtml({ children, ...htmlProps }) {
12884
13302
  }
12885
13303
 
12886
13304
  // src/hotspot/hotspot-tooltip.tsx
12887
- var import_jsx_runtime24 = require("react/jsx-runtime");
13305
+ var import_jsx_runtime25 = require("react/jsx-runtime");
12888
13306
  var DEFAULT_HOTSPOT_TOOLTIP_OFFSET = 12;
12889
13307
  var DEFAULT_HOTSPOT_TOOLTIP_APPEARANCE = {
12890
13308
  background: "rgba(22, 22, 22, 0.72)",
@@ -12893,7 +13311,10 @@ var DEFAULT_HOTSPOT_TOOLTIP_APPEARANCE = {
12893
13311
  borderRadius: 8,
12894
13312
  shadow: "0 8px 24px rgba(0, 0, 0, 0.35)",
12895
13313
  padding: 8,
12896
- fontSize: 12
13314
+ fontSize: 12,
13315
+ fontFamily: "inherit",
13316
+ lineHeight: 1.4,
13317
+ letterSpacing: "normal"
12897
13318
  };
12898
13319
  var WRAPPER_STYLE = {
12899
13320
  pointerEvents: "none"
@@ -12953,16 +13374,16 @@ function HotspotTooltip({
12953
13374
  offset = DEFAULT_HOTSPOT_TOOLTIP_OFFSET,
12954
13375
  appearance
12955
13376
  }) {
12956
- const [imageFailed, setImageFailed] = (0, import_react45.useState)(false);
12957
- (0, import_react45.useEffect)(() => {
13377
+ const [imageFailed, setImageFailed] = (0, import_react47.useState)(false);
13378
+ (0, import_react47.useEffect)(() => {
12958
13379
  setImageFailed(false);
12959
13380
  }, [content.image]);
12960
13381
  const showImage = Boolean(content.image) && !imageFailed;
12961
- const resolvedAppearance = (0, import_react45.useMemo)(
13382
+ const resolvedAppearance = (0, import_react47.useMemo)(
12962
13383
  () => resolveHotspotTooltipAppearance(appearance),
12963
13384
  [appearance]
12964
13385
  );
12965
- const bubbleStyle = (0, import_react45.useMemo)(
13386
+ const bubbleStyle = (0, import_react47.useMemo)(
12966
13387
  () => ({
12967
13388
  background: resolvedAppearance.background,
12968
13389
  border: resolvedAppearance.border,
@@ -12970,6 +13391,9 @@ function HotspotTooltip({
12970
13391
  boxShadow: resolvedAppearance.shadow,
12971
13392
  color: resolvedAppearance.color,
12972
13393
  fontSize: toCssLength(resolvedAppearance.fontSize),
13394
+ fontFamily: resolvedAppearance.fontFamily,
13395
+ lineHeight: resolvedAppearance.lineHeight,
13396
+ letterSpacing: resolvedAppearance.letterSpacing,
12973
13397
  padding: toCssLength(resolvedAppearance.padding),
12974
13398
  transform: tooltipBubbleTransform(
12975
13399
  placement,
@@ -12981,30 +13405,33 @@ function HotspotTooltip({
12981
13405
  if (!showImage && !content.text) {
12982
13406
  return null;
12983
13407
  }
12984
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(PanoHtml, { pointerEvents: "none", style: WRAPPER_STYLE, zIndexRange: [20, 10], children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
12985
- "div",
12986
- {
12987
- className: "pano-hotspot-tooltip",
12988
- role: "tooltip",
12989
- style: bubbleStyle,
12990
- children: [
12991
- showImage ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12992
- "img",
12993
- {
12994
- alt: content.imageAlt ?? content.text ?? "",
12995
- className: "pano-hotspot-tooltip-image",
12996
- onError: () => setImageFailed(true),
12997
- src: content.image
12998
- }
12999
- ) : null,
13000
- content.text ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "pano-hotspot-tooltip-text", children: content.text }) : null
13001
- ]
13002
- }
13003
- ) });
13408
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(PanoHtml, { pointerEvents: "none", style: WRAPPER_STYLE, zIndexRange: [20, 10], children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "pano-hotspot-tooltip", role: "tooltip", style: bubbleStyle, children: [
13409
+ showImage ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
13410
+ "img",
13411
+ {
13412
+ alt: content.imageAlt ?? content.text ?? "",
13413
+ className: "pano-hotspot-tooltip-image",
13414
+ onError: () => setImageFailed(true),
13415
+ src: content.image
13416
+ }
13417
+ ) : null,
13418
+ content.text ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
13419
+ "p",
13420
+ {
13421
+ className: "pano-hotspot-tooltip-text",
13422
+ style: {
13423
+ lineHeight: "inherit",
13424
+ letterSpacing: "inherit",
13425
+ fontFamily: "inherit"
13426
+ },
13427
+ children: content.text
13428
+ }
13429
+ ) : null
13430
+ ] }) });
13004
13431
  }
13005
13432
 
13006
13433
  // src/hotspot/hotspot-anchor.tsx
13007
- var import_jsx_runtime25 = require("react/jsx-runtime");
13434
+ var import_jsx_runtime26 = require("react/jsx-runtime");
13008
13435
  var DEFAULT_FLOATING_DISTANCE = 10;
13009
13436
  var PANORAMA_RADIUS = DEFAULT_PANORAMA_RADIUS;
13010
13437
  var PANORAMA_SURFACE_INSET = 4;
@@ -13012,28 +13439,28 @@ var DEFAULT_REFERENCE_FOV = 75;
13012
13439
  var MIN_ANGULAR_SIZE = 0.01;
13013
13440
  var MAX_ANGULAR_SIZE = 179;
13014
13441
  var DRAG_EPSILON_DEGREES = 1e-3;
13015
- var LOCAL_FORWARD = new import_three20.Vector3(0, 0, 1);
13016
- var TOOLTIP_WORLD_BOX = new import_three20.Box3();
13017
- var TOOLTIP_LOCAL_BOX = new import_three20.Box3();
13018
- var TOOLTIP_CORNER = new import_three20.Vector3();
13019
- var TOOLTIP_INVERSE = new import_three20.Matrix4();
13020
- var TOOLTIP_WORLD_CORNER = new import_three20.Vector3();
13021
- var TOOLTIP_PROJECTED = new import_three20.Vector3();
13022
- var TOOLTIP_RAY_ORIGIN = new import_three20.Vector3();
13023
- var TOOLTIP_RAY_FAR = new import_three20.Vector3();
13024
- var TOOLTIP_RAY_DIRECTION = new import_three20.Vector3();
13025
- var TOOLTIP_RAY = new import_three20.Ray();
13026
- var TOOLTIP_PLANE = new import_three20.Plane();
13027
- var TOOLTIP_INTERSECTION = new import_three20.Vector3();
13028
- var TOOLTIP_PLANE_NORMAL = new import_three20.Vector3();
13029
- var TOOLTIP_PLANE_POINT = new import_three20.Vector3();
13442
+ var LOCAL_FORWARD = new import_three24.Vector3(0, 0, 1);
13443
+ var TOOLTIP_WORLD_BOX = new import_three24.Box3();
13444
+ var TOOLTIP_LOCAL_BOX = new import_three24.Box3();
13445
+ var TOOLTIP_CORNER = new import_three24.Vector3();
13446
+ var TOOLTIP_INVERSE = new import_three24.Matrix4();
13447
+ var TOOLTIP_WORLD_CORNER = new import_three24.Vector3();
13448
+ var TOOLTIP_PROJECTED = new import_three24.Vector3();
13449
+ var TOOLTIP_RAY_ORIGIN = new import_three24.Vector3();
13450
+ var TOOLTIP_RAY_FAR = new import_three24.Vector3();
13451
+ var TOOLTIP_RAY_DIRECTION = new import_three24.Vector3();
13452
+ var TOOLTIP_RAY = new import_three24.Ray();
13453
+ var TOOLTIP_PLANE = new import_three24.Plane();
13454
+ var TOOLTIP_INTERSECTION = new import_three24.Vector3();
13455
+ var TOOLTIP_PLANE_NORMAL = new import_three24.Vector3();
13456
+ var TOOLTIP_PLANE_POINT = new import_three24.Vector3();
13030
13457
  var HOTSPOT_MODE_RENDERING = {
13031
13458
  surface: { orientation: "surface", placement: "surface" },
13032
13459
  billboard: { orientation: "billboard", placement: "floating" }
13033
13460
  };
13034
13461
  function angularSizeToWorldSize(size, radius) {
13035
- const safeSize = Number.isFinite(size) ? import_three20.MathUtils.clamp(Math.abs(size), MIN_ANGULAR_SIZE, MAX_ANGULAR_SIZE) : MIN_ANGULAR_SIZE;
13036
- return 2 * radius * Math.tan(import_three20.MathUtils.degToRad(safeSize) / 2);
13462
+ const safeSize = Number.isFinite(size) ? import_three24.MathUtils.clamp(Math.abs(size), MIN_ANGULAR_SIZE, MAX_ANGULAR_SIZE) : MIN_ANGULAR_SIZE;
13463
+ return 2 * radius * Math.tan(import_three24.MathUtils.degToRad(safeSize) / 2);
13037
13464
  }
13038
13465
  function resolveScale(scale) {
13039
13466
  return Number.isFinite(scale) && scale > 0 ? scale : 1;
@@ -13046,7 +13473,7 @@ function resolveDistance(placement, distance, width, height) {
13046
13473
  if (!Number.isFinite(distance)) {
13047
13474
  return DEFAULT_FLOATING_DISTANCE;
13048
13475
  }
13049
- return import_three20.MathUtils.clamp(Math.abs(distance), 0.1, maximumDistance);
13476
+ return import_three24.MathUtils.clamp(Math.abs(distance), 0.1, maximumDistance);
13050
13477
  }
13051
13478
  function applyHotspotTransform(group, camera, orientation2, surfaceQuaternion3, rotation, scaleMode, referenceFov, useAngularScale, worldWidth, worldHeight) {
13052
13479
  if (orientation2 === "billboard") {
@@ -13054,8 +13481,8 @@ function applyHotspotTransform(group, camera, orientation2, surfaceQuaternion3,
13054
13481
  } else {
13055
13482
  group.quaternion.copy(surfaceQuaternion3);
13056
13483
  }
13057
- group.rotateOnAxis(LOCAL_FORWARD, import_three20.MathUtils.degToRad(-rotation));
13058
- const scaleFactor = scaleMode === "fixed" && camera instanceof import_three20.PerspectiveCamera ? fixedScaleFactor(camera.fov, referenceFov) : 1;
13484
+ group.rotateOnAxis(LOCAL_FORWARD, import_three24.MathUtils.degToRad(-rotation));
13485
+ const scaleFactor = scaleMode === "fixed" && camera instanceof import_three24.PerspectiveCamera ? fixedScaleFactor(camera.fov, referenceFov) : 1;
13059
13486
  group.scale.set(
13060
13487
  (useAngularScale ? worldWidth : 1) * scaleFactor,
13061
13488
  (useAngularScale ? worldHeight : 1) * scaleFactor,
@@ -13064,40 +13491,40 @@ function applyHotspotTransform(group, camera, orientation2, surfaceQuaternion3,
13064
13491
  group.updateMatrixWorld();
13065
13492
  }
13066
13493
  function maximumHotspotDistance(width, height) {
13067
- const safeWidth = import_three20.MathUtils.clamp(
13494
+ const safeWidth = import_three24.MathUtils.clamp(
13068
13495
  Math.abs(Number.isFinite(width) ? width : MIN_ANGULAR_SIZE),
13069
13496
  MIN_ANGULAR_SIZE,
13070
13497
  MAX_ANGULAR_SIZE
13071
13498
  );
13072
- const safeHeight = import_three20.MathUtils.clamp(
13499
+ const safeHeight = import_three24.MathUtils.clamp(
13073
13500
  Math.abs(Number.isFinite(height) ? height : MIN_ANGULAR_SIZE),
13074
13501
  MIN_ANGULAR_SIZE,
13075
13502
  MAX_ANGULAR_SIZE
13076
13503
  );
13077
13504
  const cornerFactor = Math.hypot(
13078
13505
  1,
13079
- Math.tan(import_three20.MathUtils.degToRad(safeWidth) / 2),
13080
- Math.tan(import_three20.MathUtils.degToRad(safeHeight) / 2)
13506
+ Math.tan(import_three24.MathUtils.degToRad(safeWidth) / 2),
13507
+ Math.tan(import_three24.MathUtils.degToRad(safeHeight) / 2)
13081
13508
  );
13082
13509
  return (PANORAMA_RADIUS - PANORAMA_SURFACE_INSET) / cornerFactor;
13083
13510
  }
13084
13511
  function fixedScaleFactor(cameraFov, referenceFov) {
13085
- const safeReferenceFov = import_three20.MathUtils.clamp(referenceFov, 1, 179);
13086
- return Math.tan(import_three20.MathUtils.degToRad(cameraFov) / 2) / Math.tan(import_three20.MathUtils.degToRad(safeReferenceFov) / 2);
13512
+ const safeReferenceFov = import_three24.MathUtils.clamp(referenceFov, 1, 179);
13513
+ return Math.tan(import_three24.MathUtils.degToRad(cameraFov) / 2) / Math.tan(import_three24.MathUtils.degToRad(safeReferenceFov) / 2);
13087
13514
  }
13088
13515
  function createSurfaceQuaternion(position) {
13089
13516
  const outward = panoPositionToVector3(position).normalize();
13090
13517
  const inward = outward.clone().negate();
13091
- const pitch = import_three20.MathUtils.degToRad(position.pitch);
13092
- const yaw = import_three20.MathUtils.degToRad(position.yaw);
13093
- const localUp = new import_three20.Vector3(
13518
+ const pitch = import_three24.MathUtils.degToRad(position.pitch);
13519
+ const yaw = import_three24.MathUtils.degToRad(position.yaw);
13520
+ const localUp = new import_three24.Vector3(
13094
13521
  -Math.sin(pitch) * Math.sin(yaw),
13095
13522
  Math.cos(pitch),
13096
13523
  Math.sin(pitch) * Math.cos(yaw)
13097
13524
  ).normalize();
13098
13525
  const localRight = localUp.clone().cross(inward).normalize();
13099
- const basis = new import_three20.Matrix4().makeBasis(localRight, localUp, inward);
13100
- return new import_three20.Quaternion().setFromRotationMatrix(basis);
13526
+ const basis = new import_three24.Matrix4().makeBasis(localRight, localUp, inward);
13527
+ return new import_three24.Quaternion().setFromRotationMatrix(basis);
13101
13528
  }
13102
13529
  function makeInteractionEvent(id, position, event) {
13103
13530
  return {
@@ -13110,7 +13537,7 @@ function makeInteractionEvent(id, position, event) {
13110
13537
  function angularDistance(a, b) {
13111
13538
  const aVector = panoPositionToVector3(a);
13112
13539
  const bVector = panoPositionToVector3(b);
13113
- return import_three20.MathUtils.radToDeg(aVector.angleTo(bVector));
13540
+ return import_three24.MathUtils.radToDeg(aVector.angleTo(bVector));
13114
13541
  }
13115
13542
  function isTooltipOpen(trigger, hovered, focused, pinned) {
13116
13543
  switch (trigger) {
@@ -13341,24 +13768,24 @@ function HotspotAnchor({
13341
13768
  onPositionChange,
13342
13769
  onDragEnd
13343
13770
  }) {
13344
- const controlsRef = (0, import_react46.useContext)(PanoramaViewContext);
13345
- const hotspotTargetRegistry = (0, import_react46.useContext)(HotspotTargetRegistryContext);
13346
- const eventBus = (0, import_react46.useContext)(PanoEventBusContext);
13771
+ const controlsRef = (0, import_react48.useContext)(PanoramaViewContext);
13772
+ const hotspotTargetRegistry = (0, import_react48.useContext)(HotspotTargetRegistryContext);
13773
+ const eventBus = (0, import_react48.useContext)(PanoEventBusContext);
13347
13774
  const cursorApi = usePanoCursor();
13348
- const { camera, size } = (0, import_fiber22.useThree)();
13349
- const groupRef = (0, import_react46.useRef)(null);
13350
- const tooltipAnchorRef = (0, import_react46.useRef)(null);
13351
- const dragStateRef = (0, import_react46.useRef)(null);
13352
- const suppressNextClickRef = (0, import_react46.useRef)(false);
13353
- const [hovered, setHovered] = (0, import_react46.useState)(false);
13354
- const [dragging, setDragging] = (0, import_react46.useState)(false);
13355
- const [pinned, setPinned] = (0, import_react46.useState)(false);
13356
- const tooltipContent = (0, import_react46.useMemo)(
13775
+ const { camera, size } = (0, import_fiber23.useThree)();
13776
+ const groupRef = (0, import_react48.useRef)(null);
13777
+ const tooltipAnchorRef = (0, import_react48.useRef)(null);
13778
+ const dragStateRef = (0, import_react48.useRef)(null);
13779
+ const suppressNextClickRef = (0, import_react48.useRef)(false);
13780
+ const [hovered, setHovered] = (0, import_react48.useState)(false);
13781
+ const [dragging, setDragging] = (0, import_react48.useState)(false);
13782
+ const [pinned, setPinned] = (0, import_react48.useState)(false);
13783
+ const tooltipContent = (0, import_react48.useMemo)(
13357
13784
  () => resolveHotspotTooltipContent(tooltip),
13358
13785
  [tooltip]
13359
13786
  );
13360
13787
  const normalizedPosition = normalizePanoPosition(position);
13361
- (0, import_react46.useEffect)(() => {
13788
+ (0, import_react48.useEffect)(() => {
13362
13789
  if (!hotspotTargetRegistry) {
13363
13790
  return;
13364
13791
  }
@@ -13375,19 +13802,19 @@ function HotspotAnchor({
13375
13802
  scaledWidth,
13376
13803
  scaledHeight
13377
13804
  );
13378
- const worldPosition = (0, import_react46.useMemo)(
13805
+ const worldPosition = (0, import_react48.useMemo)(
13379
13806
  () => panoPositionToVector3(normalizedPosition, resolvedDistance),
13380
13807
  [normalizedPosition.pitch, normalizedPosition.yaw, resolvedDistance]
13381
13808
  );
13382
- const surfaceQuaternion3 = (0, import_react46.useMemo)(
13809
+ const surfaceQuaternion3 = (0, import_react48.useMemo)(
13383
13810
  () => createSurfaceQuaternion(normalizedPosition),
13384
13811
  [normalizedPosition.pitch, normalizedPosition.yaw]
13385
13812
  );
13386
13813
  const worldWidth = angularSizeToWorldSize(scaledWidth, resolvedDistance);
13387
13814
  const worldHeight = angularSizeToWorldSize(scaledHeight, resolvedDistance);
13388
- const focusGeometry = (0, import_react46.useMemo)(() => {
13389
- const planeGeometry = new import_three20.PlaneGeometry(1, 1);
13390
- const geometry = new import_three20.EdgesGeometry(planeGeometry);
13815
+ const focusGeometry = (0, import_react48.useMemo)(() => {
13816
+ const planeGeometry = new import_three24.PlaneGeometry(1, 1);
13817
+ const geometry = new import_three24.EdgesGeometry(planeGeometry);
13391
13818
  planeGeometry.dispose();
13392
13819
  return geometry;
13393
13820
  }, []);
@@ -13412,14 +13839,14 @@ function HotspotAnchor({
13412
13839
  });
13413
13840
  const tooltipOpen = visible && tooltipContent !== null && isTooltipOpen(tooltipTrigger, hovered, focused, pinned);
13414
13841
  const cursorClaimId = hotspotCursorClaimId(id);
13415
- (0, import_react46.useEffect)(
13842
+ (0, import_react48.useEffect)(
13416
13843
  () => () => {
13417
13844
  dragStateRef.current?.releaseInteractionLock();
13418
13845
  dragStateRef.current = null;
13419
13846
  },
13420
13847
  []
13421
13848
  );
13422
- (0, import_react46.useEffect)(() => {
13849
+ (0, import_react48.useEffect)(() => {
13423
13850
  if (!cursorApi) {
13424
13851
  return;
13425
13852
  }
@@ -13441,14 +13868,14 @@ function HotspotAnchor({
13441
13868
  hovered,
13442
13869
  visible
13443
13870
  ]);
13444
- (0, import_react46.useEffect)(
13871
+ (0, import_react48.useEffect)(
13445
13872
  () => () => {
13446
13873
  cursorApi?.release(cursorClaimId);
13447
13874
  },
13448
13875
  [cursorApi, cursorClaimId]
13449
13876
  );
13450
- (0, import_react46.useEffect)(() => () => focusGeometry.dispose(), [focusGeometry]);
13451
- (0, import_react46.useEffect)(() => {
13877
+ (0, import_react48.useEffect)(() => () => focusGeometry.dispose(), [focusGeometry]);
13878
+ (0, import_react48.useEffect)(() => {
13452
13879
  if (tooltipTrigger !== "click") {
13453
13880
  setPinned(false);
13454
13881
  return;
@@ -13457,12 +13884,12 @@ function HotspotAnchor({
13457
13884
  setPinned(false);
13458
13885
  });
13459
13886
  }, [eventBus, tooltipTrigger]);
13460
- (0, import_react46.useEffect)(() => {
13887
+ (0, import_react48.useEffect)(() => {
13461
13888
  if (tooltipTrigger !== "hover") {
13462
13889
  setHovered(false);
13463
13890
  }
13464
13891
  }, [tooltipTrigger]);
13465
- (0, import_react46.useEffect)(() => {
13892
+ (0, import_react48.useEffect)(() => {
13466
13893
  if (acceptsPointer) {
13467
13894
  return;
13468
13895
  }
@@ -13475,7 +13902,7 @@ function HotspotAnchor({
13475
13902
  dragStateRef.current = null;
13476
13903
  setDragging(false);
13477
13904
  }, [acceptsPointer]);
13478
- (0, import_react46.useLayoutEffect)(() => {
13905
+ (0, import_react48.useLayoutEffect)(() => {
13479
13906
  const group = groupRef.current;
13480
13907
  if (!group) {
13481
13908
  return;
@@ -13516,7 +13943,7 @@ function HotspotAnchor({
13516
13943
  worldHeight,
13517
13944
  worldWidth
13518
13945
  ]);
13519
- (0, import_fiber22.useFrame)((state) => {
13946
+ (0, import_fiber23.useFrame)((state) => {
13520
13947
  const group = groupRef.current;
13521
13948
  if (!group) {
13522
13949
  return;
@@ -13574,7 +14001,7 @@ function HotspotAnchor({
13574
14001
  setHovered(true);
13575
14002
  }
13576
14003
  };
13577
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
14004
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
13578
14005
  "group",
13579
14006
  {
13580
14007
  ref: groupRef,
@@ -13651,18 +14078,18 @@ function HotspotAnchor({
13651
14078
  } : void 0,
13652
14079
  onPointerUp: acceptsPointer ? (event) => releasePointer(event, true) : void 0,
13653
14080
  children: [
13654
- focused ? focusContent ?? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
14081
+ focused ? focusContent ?? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
13655
14082
  "lineSegments",
13656
14083
  {
13657
14084
  geometry: focusGeometry,
13658
14085
  position: [0, 0, 0.01],
13659
14086
  renderOrder: renderOrder + 1,
13660
14087
  scale: [1.12, 1.12, 1],
13661
- children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("lineBasicMaterial", { color: "#f5fbfc", depthTest: false })
14088
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("lineBasicMaterial", { color: "#f5fbfc", depthTest: false })
13662
14089
  }
13663
14090
  ) : null,
13664
14091
  children,
13665
- tooltipOpen && tooltipContent ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("group", { ref: tooltipAnchorRef, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
14092
+ tooltipOpen && tooltipContent ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("group", { ref: tooltipAnchorRef, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
13666
14093
  HotspotTooltip,
13667
14094
  {
13668
14095
  appearance: tooltipAppearance,
@@ -13677,10 +14104,10 @@ function HotspotAnchor({
13677
14104
  }
13678
14105
 
13679
14106
  // src/hotspot/hotspot-plane.tsx
13680
- var import_three21 = require("three");
13681
- var import_jsx_runtime26 = require("react/jsx-runtime");
14107
+ var import_three25 = require("three");
14108
+ var import_jsx_runtime27 = require("react/jsx-runtime");
13682
14109
  var HOTSPOT_ALPHA_CUTOFF = 0.05;
13683
- var SAMPLE_UV = new import_three21.Vector2();
14110
+ var SAMPLE_UV = new import_three25.Vector2();
13684
14111
  var RAYCAST_HITS = [];
13685
14112
  var IMAGE_DATA_CACHE = /* @__PURE__ */ new WeakMap();
13686
14113
  function clampOpacity(opacity) {
@@ -13754,8 +14181,8 @@ function sampleTextureAlpha(texture, u, v) {
13754
14181
  }
13755
14182
  function hotspotPlaneRaycast(raycaster, intersects2) {
13756
14183
  const material = Array.isArray(this.material) ? this.material[0] : this.material;
13757
- if (!(material instanceof import_three21.MeshBasicMaterial)) {
13758
- import_three21.Mesh.prototype.raycast.call(this, raycaster, intersects2);
14184
+ if (!(material instanceof import_three25.MeshBasicMaterial)) {
14185
+ import_three25.Mesh.prototype.raycast.call(this, raycaster, intersects2);
13759
14186
  return;
13760
14187
  }
13761
14188
  const cutoff = Math.max(material.alphaTest, HOTSPOT_ALPHA_CUTOFF);
@@ -13763,7 +14190,7 @@ function hotspotPlaneRaycast(raycaster, intersects2) {
13763
14190
  return;
13764
14191
  }
13765
14192
  RAYCAST_HITS.length = 0;
13766
- import_three21.Mesh.prototype.raycast.call(this, raycaster, RAYCAST_HITS);
14193
+ import_three25.Mesh.prototype.raycast.call(this, raycaster, RAYCAST_HITS);
13767
14194
  const map = material.map;
13768
14195
  for (const hit of RAYCAST_HITS) {
13769
14196
  if (!map || !hit.uv) {
@@ -13780,16 +14207,17 @@ function HotspotPlane({
13780
14207
  map,
13781
14208
  opacity
13782
14209
  }) {
13783
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("mesh", { raycast: hotspotPlaneRaycast, children: [
13784
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("planeGeometry", { args: [1, 1] }),
13785
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
13786
- "meshBasicMaterial",
14210
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("mesh", { raycast: hotspotPlaneRaycast, children: [
14211
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("planeGeometry", { args: [1, 1] }),
14212
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
14213
+ PanoBasicMaterial,
13787
14214
  {
14215
+ target: "hotspot",
13788
14216
  alphaTest: HOTSPOT_ALPHA_CUTOFF,
13789
14217
  alphaToCoverage: true,
13790
14218
  map,
13791
14219
  opacity: map ? clampOpacity(opacity) : 0,
13792
- side: import_three21.DoubleSide,
14220
+ side: import_three25.DoubleSide,
13793
14221
  toneMapped: false,
13794
14222
  transparent: true
13795
14223
  }
@@ -13798,15 +14226,15 @@ function HotspotPlane({
13798
14226
  }
13799
14227
 
13800
14228
  // src/hotspot/image-hotspot.tsx
13801
- var import_jsx_runtime27 = require("react/jsx-runtime");
14229
+ var import_jsx_runtime28 = require("react/jsx-runtime");
13802
14230
  function useHotspotImageTexture(src, onLoad, onError) {
13803
- const gl = (0, import_fiber23.useThree)((state) => state.gl);
13804
- const [texture, setTexture] = (0, import_react47.useState)(null);
13805
- const onLoadRef = (0, import_react47.useRef)(onLoad);
13806
- const onErrorRef = (0, import_react47.useRef)(onError);
14231
+ const gl = (0, import_fiber24.useThree)((state) => state.gl);
14232
+ const [texture, setTexture] = (0, import_react49.useState)(null);
14233
+ const onLoadRef = (0, import_react49.useRef)(onLoad);
14234
+ const onErrorRef = (0, import_react49.useRef)(onError);
13807
14235
  onLoadRef.current = onLoad;
13808
14236
  onErrorRef.current = onError;
13809
- (0, import_react47.useEffect)(() => {
14237
+ (0, import_react49.useEffect)(() => {
13810
14238
  let active = true;
13811
14239
  setTexture(null);
13812
14240
  if (!src) {
@@ -13814,7 +14242,7 @@ function useHotspotImageTexture(src, onLoad, onError) {
13814
14242
  active = false;
13815
14243
  };
13816
14244
  }
13817
- const loader = new import_three22.TextureLoader();
14245
+ const loader = new import_three26.TextureLoader();
13818
14246
  loader.load(
13819
14247
  src,
13820
14248
  (loadedTexture) => {
@@ -13822,11 +14250,11 @@ function useHotspotImageTexture(src, onLoad, onError) {
13822
14250
  loadedTexture.dispose();
13823
14251
  return;
13824
14252
  }
13825
- loadedTexture.colorSpace = import_three22.SRGBColorSpace;
13826
- loadedTexture.wrapS = import_three22.ClampToEdgeWrapping;
13827
- loadedTexture.wrapT = import_three22.ClampToEdgeWrapping;
13828
- loadedTexture.magFilter = import_three22.LinearFilter;
13829
- loadedTexture.minFilter = import_three22.LinearMipmapLinearFilter;
14253
+ loadedTexture.colorSpace = import_three26.SRGBColorSpace;
14254
+ loadedTexture.wrapS = import_three26.ClampToEdgeWrapping;
14255
+ loadedTexture.wrapT = import_three26.ClampToEdgeWrapping;
14256
+ loadedTexture.magFilter = import_three26.LinearFilter;
14257
+ loadedTexture.minFilter = import_three26.LinearMipmapLinearFilter;
13830
14258
  loadedTexture.generateMipmaps = true;
13831
14259
  loadedTexture.anisotropy = gl.capabilities.getMaxAnisotropy();
13832
14260
  loadedTexture.needsUpdate = true;
@@ -13844,7 +14272,7 @@ function useHotspotImageTexture(src, onLoad, onError) {
13844
14272
  active = false;
13845
14273
  };
13846
14274
  }, [gl, src]);
13847
- (0, import_react47.useEffect)(
14275
+ (0, import_react49.useEffect)(
13848
14276
  () => () => {
13849
14277
  texture?.dispose();
13850
14278
  },
@@ -13862,20 +14290,20 @@ function ImageHotspot({
13862
14290
  ...anchorProps
13863
14291
  }) {
13864
14292
  const texture = useHotspotImageTexture(src, onLoad, onError);
13865
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(HotspotPlane, { map: texture, opacity }) });
14293
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(HotspotPlane, { map: texture, opacity }) });
13866
14294
  }
13867
14295
 
13868
14296
  // src/hotspot/polygon-hotspot.tsx
13869
- var import_react49 = require("react");
13870
- var import_three24 = require("three");
14297
+ var import_react51 = require("react");
14298
+ var import_three28 = require("three");
13871
14299
 
13872
14300
  // src/hotspot/hotspot-stroke-line.tsx
13873
14301
  var import_drei2 = require("@react-three/drei");
13874
- var import_fiber24 = require("@react-three/fiber");
13875
- var import_react48 = require("react");
13876
- var import_three23 = require("three");
13877
- var import_jsx_runtime28 = require("react/jsx-runtime");
13878
- var LINE_WORLD_POSITION = new import_three23.Vector3();
14302
+ var import_fiber25 = require("@react-three/fiber");
14303
+ var import_react50 = require("react");
14304
+ var import_three27 = require("three");
14305
+ var import_jsx_runtime29 = require("react/jsx-runtime");
14306
+ var LINE_WORLD_POSITION = new import_three27.Vector3();
13879
14307
  function applyScreenSpaceDashScale(object, camera, viewportHeight) {
13880
14308
  const material = object?.material;
13881
14309
  if (!object || typeof material?.dashScale !== "number") {
@@ -13883,8 +14311,8 @@ function applyScreenSpaceDashScale(object, camera, viewportHeight) {
13883
14311
  }
13884
14312
  object.getWorldPosition(LINE_WORLD_POSITION);
13885
14313
  const depth = Math.max(camera.position.distanceTo(LINE_WORLD_POSITION), 1);
13886
- const fov = camera instanceof import_three23.PerspectiveCamera ? camera.fov : 75;
13887
- material.dashScale = viewportHeight / (2 * Math.tan(import_three23.MathUtils.degToRad(fov) * 0.5) * depth);
14314
+ const fov = camera instanceof import_three27.PerspectiveCamera ? camera.fov : 75;
14315
+ material.dashScale = viewportHeight / (2 * Math.tan(import_three27.MathUtils.degToRad(fov) * 0.5) * depth);
13888
14316
  }
13889
14317
  function resolveDash(dashSize, gapSize) {
13890
14318
  if (dashSize === void 0 || !Number.isFinite(dashSize) || dashSize <= 0) {
@@ -13905,22 +14333,22 @@ function HotspotStrokeLine({
13905
14333
  dashSize,
13906
14334
  gapSize
13907
14335
  }) {
13908
- const lineRef = (0, import_react48.useRef)(null);
13909
- const { camera, size } = (0, import_fiber24.useThree)();
14336
+ const lineRef = (0, import_react50.useRef)(null);
14337
+ const { camera, size } = (0, import_fiber25.useThree)();
13910
14338
  const dash = resolveDash(dashSize, gapSize);
13911
- (0, import_react48.useLayoutEffect)(() => {
14339
+ (0, import_react50.useLayoutEffect)(() => {
13912
14340
  if (!dash.dashed) {
13913
14341
  return;
13914
14342
  }
13915
14343
  applyScreenSpaceDashScale(lineRef.current, camera, size.height);
13916
14344
  }, [camera, dash.dashed, dash.dashSize, dash.gapSize, size.height]);
13917
- (0, import_fiber24.useFrame)((state) => {
14345
+ (0, import_fiber25.useFrame)((state) => {
13918
14346
  if (!dash.dashed) {
13919
14347
  return;
13920
14348
  }
13921
14349
  applyScreenSpaceDashScale(lineRef.current, state.camera, state.size.height);
13922
14350
  });
13923
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
14351
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
13924
14352
  import_drei2.Line,
13925
14353
  {
13926
14354
  ref: lineRef,
@@ -13942,7 +14370,7 @@ function HotspotStrokeLine({
13942
14370
  }
13943
14371
 
13944
14372
  // src/hotspot/polygon-hotspot.tsx
13945
- var import_jsx_runtime29 = require("react/jsx-runtime");
14373
+ var import_jsx_runtime30 = require("react/jsx-runtime");
13946
14374
  var POLYGON_RADIUS = 990;
13947
14375
  var MAX_FILL_SEGMENT_DEGREES = 7;
13948
14376
  function cloneVertices(vertices) {
@@ -13977,7 +14405,7 @@ function intersects(a, b, c, d) {
13977
14405
  }
13978
14406
  function hasSelfIntersection(vertices) {
13979
14407
  const points = vertices.map(
13980
- (vertex) => new import_three24.Vector2(vertex.unwrappedYaw, vertex.pitch)
14408
+ (vertex) => new import_three28.Vector2(vertex.unwrappedYaw, vertex.pitch)
13981
14409
  );
13982
14410
  for (let index = 0; index < points.length; index += 1) {
13983
14411
  const nextIndex = (index + 1) % points.length;
@@ -14014,7 +14442,7 @@ function polygonContainsDirection(vertices, direction) {
14014
14442
  }
14015
14443
  function fitsHemisphere(vertices) {
14016
14444
  const directions = vertices.map((vertex) => panoPositionToVector3(vertex).normalize());
14017
- const candidates = [new import_three24.Vector3()];
14445
+ const candidates = [new import_three28.Vector3()];
14018
14446
  for (const direction of directions) {
14019
14447
  candidates[0].add(direction);
14020
14448
  candidates.push(direction.clone());
@@ -14038,7 +14466,7 @@ function validatePolygonVertices(vertices) {
14038
14466
  if (hasSelfIntersection(unwrapped)) {
14039
14467
  issues.push({ code: "self_intersection", message: "Polygon edges cannot cross." });
14040
14468
  }
14041
- if (polygonContainsDirection(normalized, new import_three24.Vector3(0, 1, 0)) || polygonContainsDirection(normalized, new import_three24.Vector3(0, -1, 0))) {
14469
+ if (polygonContainsDirection(normalized, new import_three28.Vector3(0, 1, 0)) || polygonContainsDirection(normalized, new import_three28.Vector3(0, -1, 0))) {
14042
14470
  issues.push({ code: "contains_pole", message: "Polygons cannot contain a panorama pole." });
14043
14471
  }
14044
14472
  if (!fitsHemisphere(normalized)) {
@@ -14049,7 +14477,7 @@ function validatePolygonVertices(vertices) {
14049
14477
  function polygonCenter(vertices) {
14050
14478
  const sum = vertices.reduce(
14051
14479
  (total, vertex) => total.add(panoPositionToVector3(vertex).normalize()),
14052
- new import_three24.Vector3()
14480
+ new import_three28.Vector3()
14053
14481
  );
14054
14482
  return sum.lengthSq() > 1e-8 ? vector3ToPanoPosition(sum) : normalizePanoPosition(vertices[0]);
14055
14483
  }
@@ -14058,20 +14486,20 @@ function surfaceQuaternion(position) {
14058
14486
  const inward = outward.clone().negate();
14059
14487
  const pitch = position.pitch * Math.PI / 180;
14060
14488
  const yaw = position.yaw * Math.PI / 180;
14061
- const localUp = new import_three24.Vector3(
14489
+ const localUp = new import_three28.Vector3(
14062
14490
  -Math.sin(pitch) * Math.sin(yaw),
14063
14491
  Math.cos(pitch),
14064
14492
  Math.sin(pitch) * Math.cos(yaw)
14065
14493
  ).normalize();
14066
- return new import_three24.Quaternion().setFromRotationMatrix(
14067
- new import_three24.Matrix4().makeBasis(localUp.clone().cross(inward).normalize(), localUp, inward)
14494
+ return new import_three28.Quaternion().setFromRotationMatrix(
14495
+ new import_three28.Matrix4().makeBasis(localUp.clone().cross(inward).normalize(), localUp, inward)
14068
14496
  );
14069
14497
  }
14070
14498
  function makeWorldToLocal(center) {
14071
- return new import_three24.Matrix4().compose(
14499
+ return new import_three28.Matrix4().compose(
14072
14500
  panoPositionToVector3(center, POLYGON_RADIUS),
14073
14501
  surfaceQuaternion(center),
14074
- new import_three24.Vector3(1, 1, 1)
14502
+ new import_three28.Vector3(1, 1, 1)
14075
14503
  ).invert();
14076
14504
  }
14077
14505
  function projectedPoint(a, b, c, weightB, weightC, radius, worldToLocal) {
@@ -14126,8 +14554,8 @@ function addSubdividedTriangle(positions, indices, a, b, c, worldToLocal, steps)
14126
14554
  }
14127
14555
  function makeFillGeometry(vertices, center) {
14128
14556
  const unwrapped = unwrapPolygonVertices(vertices);
14129
- const contour = unwrapped.map((vertex) => new import_three24.Vector2(vertex.unwrappedYaw, vertex.pitch));
14130
- const triangles = import_three24.ShapeUtils.triangulateShape(contour, []);
14557
+ const contour = unwrapped.map((vertex) => new import_three28.Vector2(vertex.unwrappedYaw, vertex.pitch));
14558
+ const triangles = import_three28.ShapeUtils.triangulateShape(contour, []);
14131
14559
  const positions = [];
14132
14560
  const indices = [];
14133
14561
  const worldToLocal = makeWorldToLocal(center);
@@ -14143,7 +14571,7 @@ function makeFillGeometry(vertices, center) {
14143
14571
  steps
14144
14572
  );
14145
14573
  }
14146
- return new import_three24.BufferGeometry().setAttribute("position", new import_three24.Float32BufferAttribute(positions, 3)).setIndex(indices);
14574
+ return new import_three28.BufferGeometry().setAttribute("position", new import_three28.Float32BufferAttribute(positions, 3)).setIndex(indices);
14147
14575
  }
14148
14576
  function makeStrokePositions(vertices, center) {
14149
14577
  const points = [];
@@ -14198,24 +14626,24 @@ function PolygonHotspot({
14198
14626
  onInvalid,
14199
14627
  ...anchorProps
14200
14628
  }) {
14201
- const issues = (0, import_react49.useMemo)(() => validatePolygonVertices(vertices), [vertices]);
14629
+ const issues = (0, import_react51.useMemo)(() => validatePolygonVertices(vertices), [vertices]);
14202
14630
  const valid = issues.length === 0;
14203
- const center = (0, import_react49.useMemo)(() => valid ? polygonCenter(vertices) : null, [valid, vertices]);
14204
- const fillGeometry = (0, import_react49.useMemo)(
14631
+ const center = (0, import_react51.useMemo)(() => valid ? polygonCenter(vertices) : null, [valid, vertices]);
14632
+ const fillGeometry = (0, import_react51.useMemo)(
14205
14633
  () => valid && center ? makeFillGeometry(vertices, center) : null,
14206
14634
  [center, valid, vertices]
14207
14635
  );
14208
- const strokePoints = (0, import_react49.useMemo)(
14636
+ const strokePoints = (0, import_react51.useMemo)(
14209
14637
  () => valid && center ? makeStrokePositions(vertices, center) : null,
14210
14638
  [center, valid, vertices]
14211
14639
  );
14212
14640
  const resolvedStrokeOpacity = Math.max(0, Math.min(strokeOpacity, 1));
14213
- const startVerticesRef = (0, import_react49.useRef)(null);
14641
+ const startVerticesRef = (0, import_react51.useRef)(null);
14214
14642
  const issuesKey = issues.map((issue) => issue.code).join(",");
14215
- (0, import_react49.useEffect)(() => {
14643
+ (0, import_react51.useEffect)(() => {
14216
14644
  if (!valid) onInvalid?.(issues);
14217
14645
  }, [issues, issuesKey, onInvalid, valid]);
14218
- (0, import_react49.useEffect)(() => () => fillGeometry?.dispose(), [fillGeometry]);
14646
+ (0, import_react51.useEffect)(() => () => fillGeometry?.dispose(), [fillGeometry]);
14219
14647
  if (!valid || !center || !fillGeometry || !strokePoints || strokePoints.length < 2) {
14220
14648
  return null;
14221
14649
  }
@@ -14230,7 +14658,7 @@ function PolygonHotspot({
14230
14658
  startPosition: event.startPosition
14231
14659
  });
14232
14660
  };
14233
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
14661
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
14234
14662
  HotspotAnchor,
14235
14663
  {
14236
14664
  ...anchorProps,
@@ -14245,7 +14673,7 @@ function PolygonHotspot({
14245
14673
  draggable,
14246
14674
  interactive,
14247
14675
  useAngularScale: false,
14248
- focusContent: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
14676
+ focusContent: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
14249
14677
  HotspotStrokeLine,
14250
14678
  {
14251
14679
  color: "#75cbd3",
@@ -14267,17 +14695,17 @@ function PolygonHotspot({
14267
14695
  startVerticesRef.current = null;
14268
14696
  },
14269
14697
  children: [
14270
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("mesh", { geometry: fillGeometry, renderOrder, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
14698
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("mesh", { geometry: fillGeometry, renderOrder, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
14271
14699
  "meshBasicMaterial",
14272
14700
  {
14273
14701
  color: fill,
14274
14702
  depthWrite: false,
14275
14703
  opacity: Math.max(0, Math.min(fillOpacity, 1)),
14276
- side: import_three24.DoubleSide,
14704
+ side: import_three28.DoubleSide,
14277
14705
  transparent: true
14278
14706
  }
14279
14707
  ) }),
14280
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
14708
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
14281
14709
  HotspotStrokeLine,
14282
14710
  {
14283
14711
  color: stroke,
@@ -14295,9 +14723,9 @@ function PolygonHotspot({
14295
14723
  }
14296
14724
 
14297
14725
  // src/hotspot/polyline-hotspot.tsx
14298
- var import_react50 = require("react");
14299
- var import_three25 = require("three");
14300
- var import_jsx_runtime30 = require("react/jsx-runtime");
14726
+ var import_react52 = require("react");
14727
+ var import_three29 = require("three");
14728
+ var import_jsx_runtime31 = require("react/jsx-runtime");
14301
14729
  var POLYLINE_RADIUS = 990;
14302
14730
  var MAX_SEGMENT_DEGREES = 7;
14303
14731
  function cloneVertices2(vertices) {
@@ -14322,29 +14750,29 @@ function unwrapVertices(vertices) {
14322
14750
  function polylineCenter(vertices) {
14323
14751
  const sum = vertices.reduce(
14324
14752
  (total, vertex) => total.add(panoPositionToVector3(vertex).normalize()),
14325
- new import_three25.Vector3()
14753
+ new import_three29.Vector3()
14326
14754
  );
14327
14755
  return sum.lengthSq() > 1e-8 ? vector3ToPanoPosition(sum) : normalizePanoPosition(vertices[0]);
14328
14756
  }
14329
14757
  function surfaceQuaternion2(position) {
14330
14758
  const outward = panoPositionToVector3(position).normalize();
14331
14759
  const inward = outward.clone().negate();
14332
- const pitch = import_three25.MathUtils.degToRad(position.pitch);
14333
- const yaw = import_three25.MathUtils.degToRad(position.yaw);
14334
- const localUp = new import_three25.Vector3(
14760
+ const pitch = import_three29.MathUtils.degToRad(position.pitch);
14761
+ const yaw = import_three29.MathUtils.degToRad(position.yaw);
14762
+ const localUp = new import_three29.Vector3(
14335
14763
  -Math.sin(pitch) * Math.sin(yaw),
14336
14764
  Math.cos(pitch),
14337
14765
  Math.sin(pitch) * Math.cos(yaw)
14338
14766
  ).normalize();
14339
- return new import_three25.Quaternion().setFromRotationMatrix(
14340
- new import_three25.Matrix4().makeBasis(localUp.clone().cross(inward).normalize(), localUp, inward)
14767
+ return new import_three29.Quaternion().setFromRotationMatrix(
14768
+ new import_three29.Matrix4().makeBasis(localUp.clone().cross(inward).normalize(), localUp, inward)
14341
14769
  );
14342
14770
  }
14343
14771
  function makeWorldToLocal2(center) {
14344
- return new import_three25.Matrix4().compose(
14772
+ return new import_three29.Matrix4().compose(
14345
14773
  panoPositionToVector3(center, POLYLINE_RADIUS),
14346
14774
  surfaceQuaternion2(center),
14347
- new import_three25.Vector3(1, 1, 1)
14775
+ new import_three29.Vector3(1, 1, 1)
14348
14776
  ).invert();
14349
14777
  }
14350
14778
  function subdivisionSteps(vertices) {
@@ -14359,7 +14787,7 @@ function subdivisionSteps(vertices) {
14359
14787
  }
14360
14788
  return Math.min(
14361
14789
  8,
14362
- Math.max(1, Math.ceil(import_three25.MathUtils.radToDeg(maxAngle) / MAX_SEGMENT_DEGREES))
14790
+ Math.max(1, Math.ceil(import_three29.MathUtils.radToDeg(maxAngle) / MAX_SEGMENT_DEGREES))
14363
14791
  );
14364
14792
  }
14365
14793
  function makeLinePositions(vertices, center) {
@@ -14414,16 +14842,16 @@ function PolylineHotspot({
14414
14842
  onInvalid,
14415
14843
  ...anchorProps
14416
14844
  }) {
14417
- const issues = (0, import_react50.useMemo)(() => validatePolylineVertices(vertices), [vertices]);
14845
+ const issues = (0, import_react52.useMemo)(() => validatePolylineVertices(vertices), [vertices]);
14418
14846
  const valid = issues.length === 0;
14419
- const center = (0, import_react50.useMemo)(() => valid ? polylineCenter(vertices) : null, [valid, vertices]);
14420
- const linePoints = (0, import_react50.useMemo)(
14847
+ const center = (0, import_react52.useMemo)(() => valid ? polylineCenter(vertices) : null, [valid, vertices]);
14848
+ const linePoints = (0, import_react52.useMemo)(
14421
14849
  () => valid && center ? makeLinePositions(vertices, center) : null,
14422
14850
  [center, valid, vertices]
14423
14851
  );
14424
14852
  const opacity = Math.max(0, Math.min(strokeOpacity, 1));
14425
- const startVerticesRef = (0, import_react50.useRef)(null);
14426
- (0, import_react50.useEffect)(() => {
14853
+ const startVerticesRef = (0, import_react52.useRef)(null);
14854
+ (0, import_react52.useEffect)(() => {
14427
14855
  if (!valid) onInvalid?.(issues);
14428
14856
  }, [issues, onInvalid, valid]);
14429
14857
  if (!valid || !center || !linePoints || linePoints.length < 2) return null;
@@ -14437,7 +14865,7 @@ function PolylineHotspot({
14437
14865
  startPosition: event.startPosition
14438
14866
  });
14439
14867
  };
14440
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
14868
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
14441
14869
  HotspotAnchor,
14442
14870
  {
14443
14871
  ...anchorProps,
@@ -14451,7 +14879,7 @@ function PolylineHotspot({
14451
14879
  renderOrder,
14452
14880
  draggable,
14453
14881
  useAngularScale: false,
14454
- focusContent: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
14882
+ focusContent: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
14455
14883
  HotspotStrokeLine,
14456
14884
  {
14457
14885
  color: "#75cbd3",
@@ -14472,7 +14900,7 @@ function PolylineHotspot({
14472
14900
  emitVerticesChange(event, onDragEnd);
14473
14901
  startVerticesRef.current = null;
14474
14902
  },
14475
- children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
14903
+ children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
14476
14904
  HotspotStrokeLine,
14477
14905
  {
14478
14906
  color: stroke,
@@ -14489,9 +14917,9 @@ function PolylineHotspot({
14489
14917
  }
14490
14918
 
14491
14919
  // src/hotspot/graphic-hotspot.tsx
14492
- var import_react51 = require("react");
14493
- var import_three26 = require("three");
14494
- var import_jsx_runtime31 = require("react/jsx-runtime");
14920
+ var import_react53 = require("react");
14921
+ var import_three30 = require("three");
14922
+ var import_jsx_runtime32 = require("react/jsx-runtime");
14495
14923
  var GRAPHIC_TEXTURE_SIZE = 512;
14496
14924
  function resolveStrokeWidth(value) {
14497
14925
  return Number.isFinite(value) ? Math.max(value, 0) : 8;
@@ -14669,23 +15097,23 @@ function createGraphicTexture(graphic, aspectWidth, aspectHeight) {
14669
15097
  throw new Error("Canvas 2D is unavailable for this graphic hotspot.");
14670
15098
  }
14671
15099
  drawGraphic(context, graphic, aspectWidth, aspectHeight);
14672
- const texture = new import_three26.CanvasTexture(canvas);
14673
- texture.colorSpace = import_three26.SRGBColorSpace;
14674
- texture.wrapS = import_three26.ClampToEdgeWrapping;
14675
- texture.wrapT = import_three26.ClampToEdgeWrapping;
14676
- texture.magFilter = import_three26.LinearFilter;
14677
- texture.minFilter = import_three26.LinearMipmapLinearFilter;
15100
+ const texture = new import_three30.CanvasTexture(canvas);
15101
+ texture.colorSpace = import_three30.SRGBColorSpace;
15102
+ texture.wrapS = import_three30.ClampToEdgeWrapping;
15103
+ texture.wrapT = import_three30.ClampToEdgeWrapping;
15104
+ texture.magFilter = import_three30.LinearFilter;
15105
+ texture.minFilter = import_three30.LinearMipmapLinearFilter;
14678
15106
  texture.generateMipmaps = true;
14679
15107
  texture.needsUpdate = true;
14680
15108
  return texture;
14681
15109
  }
14682
15110
  function useGraphicTexture(graphic, aspectWidth, aspectHeight, onLoad, onError) {
14683
- const [texture, setTexture] = (0, import_react51.useState)(null);
14684
- const onLoadRef = (0, import_react51.useRef)(onLoad);
14685
- const onErrorRef = (0, import_react51.useRef)(onError);
15111
+ const [texture, setTexture] = (0, import_react53.useState)(null);
15112
+ const onLoadRef = (0, import_react53.useRef)(onLoad);
15113
+ const onErrorRef = (0, import_react53.useRef)(onError);
14686
15114
  onLoadRef.current = onLoad;
14687
15115
  onErrorRef.current = onError;
14688
- (0, import_react51.useEffect)(() => {
15116
+ (0, import_react53.useEffect)(() => {
14689
15117
  let nextTexture = null;
14690
15118
  try {
14691
15119
  nextTexture = createGraphicTexture(graphic, aspectWidth, aspectHeight);
@@ -14711,22 +15139,22 @@ function CanvasGraphicHotspot({
14711
15139
  ...anchorProps
14712
15140
  }) {
14713
15141
  const texture = useGraphicTexture(graphic, width, height, onLoad, onError);
14714
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(HotspotPlane, { map: texture, opacity }) });
15142
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(HotspotPlane, { map: texture, opacity }) });
14715
15143
  }
14716
15144
  function GraphicHotspot(props) {
14717
15145
  const { graphic, ...restProps } = props;
14718
15146
  if (graphic.kind === "svg") {
14719
15147
  const imageProps = restProps;
14720
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(ImageHotspot, { ...imageProps, src: graphic.src });
15148
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ImageHotspot, { ...imageProps, src: graphic.src });
14721
15149
  }
14722
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(CanvasGraphicHotspot, { ...restProps, graphic });
15150
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(CanvasGraphicHotspot, { ...restProps, graphic });
14723
15151
  }
14724
15152
 
14725
15153
  // src/hotspot/sequence-hotspot.tsx
14726
- var import_fiber25 = require("@react-three/fiber");
14727
- var import_react52 = require("react");
14728
- var import_three27 = require("three");
14729
- var import_jsx_runtime32 = require("react/jsx-runtime");
15154
+ var import_fiber26 = require("@react-three/fiber");
15155
+ var import_react54 = require("react");
15156
+ var import_three31 = require("three");
15157
+ var import_jsx_runtime33 = require("react/jsx-runtime");
14730
15158
  var DEFAULT_SEQUENCE_FPS = 12;
14731
15159
  function resolveFps(value) {
14732
15160
  return Number.isFinite(value) && value > 0 ? value : DEFAULT_SEQUENCE_FPS;
@@ -14740,13 +15168,13 @@ function useSpriteTexture({
14740
15168
  onError,
14741
15169
  onLoadProgress
14742
15170
  }) {
14743
- const gl = (0, import_fiber25.useThree)((state) => state.gl);
14744
- const [texture, setTexture] = (0, import_react52.useState)(null);
14745
- const onErrorRef = (0, import_react52.useRef)(onError);
14746
- const onLoadProgressRef = (0, import_react52.useRef)(onLoadProgress);
15171
+ const gl = (0, import_fiber26.useThree)((state) => state.gl);
15172
+ const [texture, setTexture] = (0, import_react54.useState)(null);
15173
+ const onErrorRef = (0, import_react54.useRef)(onError);
15174
+ const onLoadProgressRef = (0, import_react54.useRef)(onLoadProgress);
14747
15175
  onErrorRef.current = onError;
14748
15176
  onLoadProgressRef.current = onLoadProgress;
14749
- (0, import_react52.useEffect)(() => {
15177
+ (0, import_react54.useEffect)(() => {
14750
15178
  let active = true;
14751
15179
  setTexture(null);
14752
15180
  if (!src) {
@@ -14755,7 +15183,7 @@ function useSpriteTexture({
14755
15183
  active = false;
14756
15184
  };
14757
15185
  }
14758
- const loader = new import_three27.TextureLoader();
15186
+ const loader = new import_three31.TextureLoader();
14759
15187
  loader.load(
14760
15188
  src,
14761
15189
  (loadedTexture) => {
@@ -14763,11 +15191,11 @@ function useSpriteTexture({
14763
15191
  loadedTexture.dispose();
14764
15192
  return;
14765
15193
  }
14766
- loadedTexture.colorSpace = import_three27.SRGBColorSpace;
14767
- loadedTexture.wrapS = import_three27.ClampToEdgeWrapping;
14768
- loadedTexture.wrapT = import_three27.ClampToEdgeWrapping;
14769
- loadedTexture.magFilter = import_three27.LinearFilter;
14770
- loadedTexture.minFilter = import_three27.LinearMipmapLinearFilter;
15194
+ loadedTexture.colorSpace = import_three31.SRGBColorSpace;
15195
+ loadedTexture.wrapS = import_three31.ClampToEdgeWrapping;
15196
+ loadedTexture.wrapT = import_three31.ClampToEdgeWrapping;
15197
+ loadedTexture.magFilter = import_three31.LinearFilter;
15198
+ loadedTexture.minFilter = import_three31.LinearMipmapLinearFilter;
14771
15199
  loadedTexture.generateMipmaps = true;
14772
15200
  loadedTexture.anisotropy = gl.capabilities.getMaxAnisotropy();
14773
15201
  loadedTexture.needsUpdate = true;
@@ -14787,7 +15215,7 @@ function useSpriteTexture({
14787
15215
  active = false;
14788
15216
  };
14789
15217
  }, [gl, id, src]);
14790
- (0, import_react52.useEffect)(
15218
+ (0, import_react54.useEffect)(
14791
15219
  () => () => {
14792
15220
  texture?.dispose();
14793
15221
  },
@@ -14816,24 +15244,24 @@ function SequenceHotspot({
14816
15244
  const texture = useSpriteTexture({ id, src, onError, onLoadProgress });
14817
15245
  const frameCount = resolveFrameCount(requestedFrameCount);
14818
15246
  const safeFps = resolveFps(fps);
14819
- const [frameIndex, setFrameIndex] = (0, import_react52.useState)(0);
14820
- const elapsedRef = (0, import_react52.useRef)(0);
14821
- const frameIndexRef = (0, import_react52.useRef)(0);
14822
- const endedRef = (0, import_react52.useRef)(false);
14823
- const lastPlaybackStateRef = (0, import_react52.useRef)(null);
14824
- const onFrameChangeRef = (0, import_react52.useRef)(onFrameChange);
14825
- const onPlaybackStateChangeRef = (0, import_react52.useRef)(onPlaybackStateChange);
14826
- const onEndedRef = (0, import_react52.useRef)(onEnded);
15247
+ const [frameIndex, setFrameIndex] = (0, import_react54.useState)(0);
15248
+ const elapsedRef = (0, import_react54.useRef)(0);
15249
+ const frameIndexRef = (0, import_react54.useRef)(0);
15250
+ const endedRef = (0, import_react54.useRef)(false);
15251
+ const lastPlaybackStateRef = (0, import_react54.useRef)(null);
15252
+ const onFrameChangeRef = (0, import_react54.useRef)(onFrameChange);
15253
+ const onPlaybackStateChangeRef = (0, import_react54.useRef)(onPlaybackStateChange);
15254
+ const onEndedRef = (0, import_react54.useRef)(onEnded);
14827
15255
  onFrameChangeRef.current = onFrameChange;
14828
15256
  onPlaybackStateChangeRef.current = onPlaybackStateChange;
14829
15257
  onEndedRef.current = onEnded;
14830
- (0, import_react52.useEffect)(() => {
15258
+ (0, import_react54.useEffect)(() => {
14831
15259
  elapsedRef.current = 0;
14832
15260
  frameIndexRef.current = 0;
14833
15261
  endedRef.current = false;
14834
15262
  setFrameIndex(0);
14835
15263
  }, [frameCount, frameDirection, src]);
14836
- (0, import_react52.useEffect)(() => {
15264
+ (0, import_react54.useEffect)(() => {
14837
15265
  if (!texture) {
14838
15266
  return;
14839
15267
  }
@@ -14847,13 +15275,13 @@ function SequenceHotspot({
14847
15275
  );
14848
15276
  texture.needsUpdate = true;
14849
15277
  }, [frameCount, frameDirection, frameIndex, texture]);
14850
- (0, import_react52.useEffect)(() => {
15278
+ (0, import_react54.useEffect)(() => {
14851
15279
  if (!texture) {
14852
15280
  return;
14853
15281
  }
14854
15282
  onFrameChangeRef.current?.({ id, index: 0, src });
14855
15283
  }, [id, src, texture]);
14856
- (0, import_react52.useEffect)(() => {
15284
+ (0, import_react54.useEffect)(() => {
14857
15285
  if (!texture) {
14858
15286
  return;
14859
15287
  }
@@ -14872,7 +15300,7 @@ function SequenceHotspot({
14872
15300
  onPlaybackStateChangeRef.current?.(nextState);
14873
15301
  }
14874
15302
  }, [playing, texture]);
14875
- (0, import_fiber25.useFrame)((_, deltaSeconds) => {
15303
+ (0, import_fiber26.useFrame)((_, deltaSeconds) => {
14876
15304
  if (!texture || !playing || endedRef.current) {
14877
15305
  return;
14878
15306
  }
@@ -14902,14 +15330,14 @@ function SequenceHotspot({
14902
15330
  onFrameChangeRef.current?.({ id, index: nextIndex, src });
14903
15331
  }
14904
15332
  });
14905
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(HotspotAnchor, { ...anchorProps, id, height, width, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(HotspotPlane, { map: texture, opacity }) });
15333
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(HotspotAnchor, { ...anchorProps, id, height, width, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(HotspotPlane, { map: texture, opacity }) });
14906
15334
  }
14907
15335
 
14908
15336
  // src/hotspot/video-hotspot.tsx
14909
- var import_fiber26 = require("@react-three/fiber");
14910
- var import_react53 = require("react");
14911
- var import_three28 = require("three");
14912
- var import_jsx_runtime33 = require("react/jsx-runtime");
15337
+ var import_fiber27 = require("@react-three/fiber");
15338
+ var import_react55 = require("react");
15339
+ var import_three32 = require("three");
15340
+ var import_jsx_runtime34 = require("react/jsx-runtime");
14913
15341
  function clampVolume2(volume) {
14914
15342
  if (!Number.isFinite(volume)) {
14915
15343
  return 1;
@@ -14917,11 +15345,11 @@ function clampVolume2(volume) {
14917
15345
  return Math.max(0, Math.min(volume, 1));
14918
15346
  }
14919
15347
  function usePosterTexture2(id, poster, onError) {
14920
- const gl = (0, import_fiber26.useThree)((state) => state.gl);
14921
- const [texture, setTexture] = (0, import_react53.useState)(null);
14922
- const onErrorRef = (0, import_react53.useRef)(onError);
15348
+ const gl = (0, import_fiber27.useThree)((state) => state.gl);
15349
+ const [texture, setTexture] = (0, import_react55.useState)(null);
15350
+ const onErrorRef = (0, import_react55.useRef)(onError);
14923
15351
  onErrorRef.current = onError;
14924
- (0, import_react53.useEffect)(() => {
15352
+ (0, import_react55.useEffect)(() => {
14925
15353
  let active = true;
14926
15354
  setTexture(null);
14927
15355
  if (!poster) {
@@ -14929,7 +15357,7 @@ function usePosterTexture2(id, poster, onError) {
14929
15357
  active = false;
14930
15358
  };
14931
15359
  }
14932
- const loader = new import_three28.TextureLoader();
15360
+ const loader = new import_three32.TextureLoader();
14933
15361
  loader.load(
14934
15362
  poster,
14935
15363
  (loadedTexture) => {
@@ -14937,11 +15365,11 @@ function usePosterTexture2(id, poster, onError) {
14937
15365
  loadedTexture.dispose();
14938
15366
  return;
14939
15367
  }
14940
- loadedTexture.colorSpace = import_three28.SRGBColorSpace;
14941
- loadedTexture.wrapS = import_three28.ClampToEdgeWrapping;
14942
- loadedTexture.wrapT = import_three28.ClampToEdgeWrapping;
14943
- loadedTexture.magFilter = import_three28.LinearFilter;
14944
- loadedTexture.minFilter = import_three28.LinearMipmapLinearFilter;
15368
+ loadedTexture.colorSpace = import_three32.SRGBColorSpace;
15369
+ loadedTexture.wrapS = import_three32.ClampToEdgeWrapping;
15370
+ loadedTexture.wrapT = import_three32.ClampToEdgeWrapping;
15371
+ loadedTexture.magFilter = import_three32.LinearFilter;
15372
+ loadedTexture.minFilter = import_three32.LinearMipmapLinearFilter;
14945
15373
  loadedTexture.generateMipmaps = true;
14946
15374
  loadedTexture.anisotropy = gl.capabilities.getMaxAnisotropy();
14947
15375
  loadedTexture.needsUpdate = true;
@@ -14958,7 +15386,7 @@ function usePosterTexture2(id, poster, onError) {
14958
15386
  active = false;
14959
15387
  };
14960
15388
  }, [gl, id, poster]);
14961
- (0, import_react53.useEffect)(
15389
+ (0, import_react55.useEffect)(
14962
15390
  () => () => {
14963
15391
  texture?.dispose();
14964
15392
  },
@@ -14976,14 +15404,14 @@ function useVideoResource({
14976
15404
  poster,
14977
15405
  src
14978
15406
  }) {
14979
- const [resource, setResource] = (0, import_react53.useState)(null);
14980
- const onEndedRef = (0, import_react53.useRef)(onEnded);
14981
- const onErrorRef = (0, import_react53.useRef)(onError);
14982
- const onPlaybackStateChangeRef = (0, import_react53.useRef)(onPlaybackStateChange);
15407
+ const [resource, setResource] = (0, import_react55.useState)(null);
15408
+ const onEndedRef = (0, import_react55.useRef)(onEnded);
15409
+ const onErrorRef = (0, import_react55.useRef)(onError);
15410
+ const onPlaybackStateChangeRef = (0, import_react55.useRef)(onPlaybackStateChange);
14983
15411
  onEndedRef.current = onEnded;
14984
15412
  onErrorRef.current = onError;
14985
15413
  onPlaybackStateChangeRef.current = onPlaybackStateChange;
14986
- (0, import_react53.useEffect)(() => {
15414
+ (0, import_react55.useEffect)(() => {
14987
15415
  if (!src) {
14988
15416
  setResource(null);
14989
15417
  return;
@@ -15000,12 +15428,12 @@ function useVideoResource({
15000
15428
  video.setAttribute("webkit-playsinline", "true");
15001
15429
  }
15002
15430
  video.poster = poster ?? "";
15003
- const texture = new import_three28.VideoTexture(video);
15004
- texture.colorSpace = import_three28.SRGBColorSpace;
15005
- texture.wrapS = import_three28.ClampToEdgeWrapping;
15006
- texture.wrapT = import_three28.ClampToEdgeWrapping;
15007
- texture.magFilter = import_three28.LinearFilter;
15008
- texture.minFilter = import_three28.LinearFilter;
15431
+ const texture = new import_three32.VideoTexture(video);
15432
+ texture.colorSpace = import_three32.SRGBColorSpace;
15433
+ texture.wrapS = import_three32.ClampToEdgeWrapping;
15434
+ texture.wrapT = import_three32.ClampToEdgeWrapping;
15435
+ texture.magFilter = import_three32.LinearFilter;
15436
+ texture.minFilter = import_three32.LinearFilter;
15009
15437
  texture.generateMipmaps = false;
15010
15438
  const notifyState = (state) => {
15011
15439
  if (active) {
@@ -15090,11 +15518,11 @@ function VideoHotspot({
15090
15518
  src
15091
15519
  });
15092
15520
  const posterTexture = usePosterTexture2(id, poster, onError);
15093
- const onPlaybackErrorRef = (0, import_react53.useRef)(onPlaybackError);
15094
- const onPlaybackStateChangeRef = (0, import_react53.useRef)(onPlaybackStateChange);
15521
+ const onPlaybackErrorRef = (0, import_react55.useRef)(onPlaybackError);
15522
+ const onPlaybackStateChangeRef = (0, import_react55.useRef)(onPlaybackStateChange);
15095
15523
  onPlaybackErrorRef.current = onPlaybackError;
15096
15524
  onPlaybackStateChangeRef.current = onPlaybackStateChange;
15097
- (0, import_react53.useEffect)(() => {
15525
+ (0, import_react55.useEffect)(() => {
15098
15526
  if (!resource) {
15099
15527
  return;
15100
15528
  }
@@ -15111,7 +15539,7 @@ function VideoHotspot({
15111
15539
  }
15112
15540
  resource.video.preload = preload;
15113
15541
  }, [loop, muted, playsInline, preload, resource, volume]);
15114
- (0, import_react53.useEffect)(() => {
15542
+ (0, import_react55.useEffect)(() => {
15115
15543
  if (!resource) {
15116
15544
  return;
15117
15545
  }
@@ -15134,14 +15562,14 @@ function VideoHotspot({
15134
15562
  };
15135
15563
  }, [playing, resource]);
15136
15564
  const activeTexture = resource?.ready ? resource.texture : posterTexture;
15137
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(HotspotAnchor, { ...anchorProps, id, height, width, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(HotspotPlane, { map: activeTexture, opacity }) });
15565
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(HotspotAnchor, { ...anchorProps, id, height, width, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(HotspotPlane, { map: activeTexture, opacity }) });
15138
15566
  }
15139
15567
 
15140
15568
  // src/hotspot/audio-hotspot.tsx
15141
- var import_fiber27 = require("@react-three/fiber");
15142
- var import_react54 = require("react");
15143
- var import_three29 = require("three");
15144
- var import_jsx_runtime34 = require("react/jsx-runtime");
15569
+ var import_fiber28 = require("@react-three/fiber");
15570
+ var import_react56 = require("react");
15571
+ var import_three33 = require("three");
15572
+ var import_jsx_runtime35 = require("react/jsx-runtime");
15145
15573
  var SPEAKER_TEXTURE_SIZE = 512;
15146
15574
  function paintSpeakerBody(context, center) {
15147
15575
  context.fillStyle = "#f5fbfc";
@@ -15194,19 +15622,19 @@ function createSpeakerTexture(state) {
15194
15622
  return exhaustive;
15195
15623
  }
15196
15624
  }
15197
- const texture = new import_three29.CanvasTexture(canvas);
15198
- texture.colorSpace = import_three29.SRGBColorSpace;
15199
- texture.wrapS = import_three29.ClampToEdgeWrapping;
15200
- texture.wrapT = import_three29.ClampToEdgeWrapping;
15201
- texture.magFilter = import_three29.LinearFilter;
15202
- texture.minFilter = import_three29.LinearMipmapLinearFilter;
15625
+ const texture = new import_three33.CanvasTexture(canvas);
15626
+ texture.colorSpace = import_three33.SRGBColorSpace;
15627
+ texture.wrapS = import_three33.ClampToEdgeWrapping;
15628
+ texture.wrapT = import_three33.ClampToEdgeWrapping;
15629
+ texture.magFilter = import_three33.LinearFilter;
15630
+ texture.minFilter = import_three33.LinearMipmapLinearFilter;
15203
15631
  texture.generateMipmaps = true;
15204
15632
  texture.needsUpdate = true;
15205
15633
  return texture;
15206
15634
  }
15207
15635
  function useSpeakerTextures(enabled) {
15208
- const [textures, setTextures] = (0, import_react54.useState)({ playing: null, stopped: null });
15209
- (0, import_react54.useEffect)(() => {
15636
+ const [textures, setTextures] = (0, import_react56.useState)({ playing: null, stopped: null });
15637
+ (0, import_react56.useEffect)(() => {
15210
15638
  if (!enabled) {
15211
15639
  setTextures({ playing: null, stopped: null });
15212
15640
  return;
@@ -15222,11 +15650,11 @@ function useSpeakerTextures(enabled) {
15222
15650
  return textures;
15223
15651
  }
15224
15652
  function useIconTexture(icon, enabled, onError, id) {
15225
- const gl = (0, import_fiber27.useThree)((state) => state.gl);
15226
- const [texture, setTexture] = (0, import_react54.useState)(null);
15227
- const onErrorRef = (0, import_react54.useRef)(onError);
15653
+ const gl = (0, import_fiber28.useThree)((state) => state.gl);
15654
+ const [texture, setTexture] = (0, import_react56.useState)(null);
15655
+ const onErrorRef = (0, import_react56.useRef)(onError);
15228
15656
  onErrorRef.current = onError;
15229
- (0, import_react54.useEffect)(() => {
15657
+ (0, import_react56.useEffect)(() => {
15230
15658
  let active = true;
15231
15659
  setTexture(null);
15232
15660
  if (!enabled || !icon) {
@@ -15234,7 +15662,7 @@ function useIconTexture(icon, enabled, onError, id) {
15234
15662
  active = false;
15235
15663
  };
15236
15664
  }
15237
- const loader = new import_three29.TextureLoader();
15665
+ const loader = new import_three33.TextureLoader();
15238
15666
  loader.load(
15239
15667
  icon,
15240
15668
  (loadedTexture) => {
@@ -15242,11 +15670,11 @@ function useIconTexture(icon, enabled, onError, id) {
15242
15670
  loadedTexture.dispose();
15243
15671
  return;
15244
15672
  }
15245
- loadedTexture.colorSpace = import_three29.SRGBColorSpace;
15246
- loadedTexture.wrapS = import_three29.ClampToEdgeWrapping;
15247
- loadedTexture.wrapT = import_three29.ClampToEdgeWrapping;
15248
- loadedTexture.magFilter = import_three29.LinearFilter;
15249
- loadedTexture.minFilter = import_three29.LinearMipmapLinearFilter;
15673
+ loadedTexture.colorSpace = import_three33.SRGBColorSpace;
15674
+ loadedTexture.wrapS = import_three33.ClampToEdgeWrapping;
15675
+ loadedTexture.wrapT = import_three33.ClampToEdgeWrapping;
15676
+ loadedTexture.magFilter = import_three33.LinearFilter;
15677
+ loadedTexture.minFilter = import_three33.LinearMipmapLinearFilter;
15250
15678
  loadedTexture.generateMipmaps = true;
15251
15679
  loadedTexture.anisotropy = gl.capabilities.getMaxAnisotropy();
15252
15680
  loadedTexture.needsUpdate = true;
@@ -15263,7 +15691,7 @@ function useIconTexture(icon, enabled, onError, id) {
15263
15691
  active = false;
15264
15692
  };
15265
15693
  }, [enabled, gl, icon, id]);
15266
- (0, import_react54.useEffect)(
15694
+ (0, import_react56.useEffect)(
15267
15695
  () => () => {
15268
15696
  texture?.dispose();
15269
15697
  },
@@ -15282,13 +15710,13 @@ function useAudioHowl({
15282
15710
  playing,
15283
15711
  src
15284
15712
  }) {
15285
- const [howl, setHowl] = (0, import_react54.useState)(null);
15286
- const playingRef = (0, import_react54.useRef)(playing);
15287
- const loopRef = (0, import_react54.useRef)(loop ?? false);
15288
- const onEndedRef = (0, import_react54.useRef)(onEnded);
15289
- const onErrorRef = (0, import_react54.useRef)(onError);
15290
- const onPlaybackErrorRef = (0, import_react54.useRef)(onPlaybackError);
15291
- const onPlaybackStateChangeRef = (0, import_react54.useRef)(onPlaybackStateChange);
15713
+ const [howl, setHowl] = (0, import_react56.useState)(null);
15714
+ const playingRef = (0, import_react56.useRef)(playing);
15715
+ const loopRef = (0, import_react56.useRef)(loop ?? false);
15716
+ const onEndedRef = (0, import_react56.useRef)(onEnded);
15717
+ const onErrorRef = (0, import_react56.useRef)(onError);
15718
+ const onPlaybackErrorRef = (0, import_react56.useRef)(onPlaybackError);
15719
+ const onPlaybackStateChangeRef = (0, import_react56.useRef)(onPlaybackStateChange);
15292
15720
  playingRef.current = playing;
15293
15721
  loopRef.current = loop ?? false;
15294
15722
  onEndedRef.current = onEnded;
@@ -15296,7 +15724,7 @@ function useAudioHowl({
15296
15724
  onPlaybackErrorRef.current = onPlaybackError;
15297
15725
  onPlaybackStateChangeRef.current = onPlaybackStateChange;
15298
15726
  const sourcesKey = sourceList(src).join("\0");
15299
- (0, import_react54.useEffect)(() => {
15727
+ (0, import_react56.useEffect)(() => {
15300
15728
  const sources = sourcesKey.length > 0 ? sourcesKey.split("\0") : [];
15301
15729
  if (sources.length === 0) {
15302
15730
  setHowl(null);
@@ -15333,7 +15761,7 @@ function useAudioHowl({
15333
15761
  handle.dispose();
15334
15762
  };
15335
15763
  }, [crossOrigin, id, sourcesKey]);
15336
- (0, import_react54.useEffect)(() => {
15764
+ (0, import_react56.useEffect)(() => {
15337
15765
  howl?.loop(loop ?? false);
15338
15766
  }, [howl, loop]);
15339
15767
  return howl;
@@ -15361,7 +15789,7 @@ function AudioHotspot({
15361
15789
  ...anchorProps
15362
15790
  }) {
15363
15791
  usePanoMediaActivationIntent(playing);
15364
- const camera = (0, import_fiber27.useThree)((state) => state.camera);
15792
+ const camera = (0, import_fiber28.useThree)((state) => state.camera);
15365
15793
  const howl = useAudioHowl({
15366
15794
  crossOrigin,
15367
15795
  id,
@@ -15377,15 +15805,15 @@ function AudioHotspot({
15377
15805
  const stoppedIconTexture = useIconTexture(icon, marker, onError, id);
15378
15806
  const playingIconTexture = useIconTexture(playingIcon, marker, onError, id);
15379
15807
  const markerTexture = playing ? playingIconTexture ?? stoppedIconTexture ?? speakerTextures.playing : stoppedIconTexture ?? speakerTextures.stopped;
15380
- const playingRef = (0, import_react54.useRef)(playing);
15808
+ const playingRef = (0, import_react56.useRef)(playing);
15381
15809
  playingRef.current = playing;
15382
- const mutedRef = (0, import_react54.useRef)(muted);
15383
- const volumeRef = (0, import_react54.useRef)(volume);
15384
- const rangeRef = (0, import_react54.useRef)(range);
15810
+ const mutedRef = (0, import_react56.useRef)(muted);
15811
+ const volumeRef = (0, import_react56.useRef)(volume);
15812
+ const rangeRef = (0, import_react56.useRef)(range);
15385
15813
  mutedRef.current = muted;
15386
15814
  volumeRef.current = volume;
15387
15815
  rangeRef.current = range;
15388
- (0, import_react54.useEffect)(() => {
15816
+ (0, import_react56.useEffect)(() => {
15389
15817
  if (!howl) {
15390
15818
  return;
15391
15819
  }
@@ -15395,7 +15823,7 @@ function AudioHotspot({
15395
15823
  }
15396
15824
  howl.play();
15397
15825
  }, [howl, playing]);
15398
- (0, import_react54.useEffect)(() => {
15826
+ (0, import_react56.useEffect)(() => {
15399
15827
  if (!howl || !pauseWhenHidden) {
15400
15828
  return;
15401
15829
  }
@@ -15413,7 +15841,7 @@ function AudioHotspot({
15413
15841
  document.removeEventListener("visibilitychange", handleVisibility);
15414
15842
  };
15415
15843
  }, [howl, pauseWhenHidden]);
15416
- (0, import_fiber27.useFrame)(() => {
15844
+ (0, import_fiber28.useFrame)(() => {
15417
15845
  if (!howl) {
15418
15846
  return;
15419
15847
  }
@@ -15426,13 +15854,13 @@ function AudioHotspot({
15426
15854
  howl.mute(mutedRef.current);
15427
15855
  howl.volume(clampAudioVolume(volumeRef.current) * spatial.gain);
15428
15856
  });
15429
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(HotspotAnchor, { ...anchorProps, id, height, width, children: marker ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(HotspotPlane, { map: markerTexture, opacity }) : null });
15857
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(HotspotAnchor, { ...anchorProps, id, height, width, children: marker ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(HotspotPlane, { map: markerTexture, opacity }) : null });
15430
15858
  }
15431
15859
 
15432
15860
  // src/hotspot/text-hotspot.tsx
15433
- var import_react55 = require("react");
15434
- var import_three30 = require("three");
15435
- var import_jsx_runtime35 = require("react/jsx-runtime");
15861
+ var import_react57 = require("react");
15862
+ var import_three34 = require("three");
15863
+ var import_jsx_runtime36 = require("react/jsx-runtime");
15436
15864
  var TEXT_TEXTURE_LONG_SIDE = 1024;
15437
15865
  var DEFAULT_FONT_FAMILY = "system-ui, sans-serif";
15438
15866
  var DEFAULT_FONT_SIZE = 96;
@@ -15641,23 +16069,23 @@ function createTextTexture(text, width, height, style) {
15641
16069
  throw new Error("Canvas 2D is unavailable for this text hotspot.");
15642
16070
  }
15643
16071
  drawTextHotspot(context, canvasWidth, canvasHeight, text, style);
15644
- const texture = new import_three30.CanvasTexture(canvas);
15645
- texture.colorSpace = import_three30.SRGBColorSpace;
15646
- texture.wrapS = import_three30.ClampToEdgeWrapping;
15647
- texture.wrapT = import_three30.ClampToEdgeWrapping;
15648
- texture.magFilter = import_three30.LinearFilter;
15649
- texture.minFilter = import_three30.LinearMipmapLinearFilter;
16072
+ const texture = new import_three34.CanvasTexture(canvas);
16073
+ texture.colorSpace = import_three34.SRGBColorSpace;
16074
+ texture.wrapS = import_three34.ClampToEdgeWrapping;
16075
+ texture.wrapT = import_three34.ClampToEdgeWrapping;
16076
+ texture.magFilter = import_three34.LinearFilter;
16077
+ texture.minFilter = import_three34.LinearMipmapLinearFilter;
15650
16078
  texture.generateMipmaps = true;
15651
16079
  texture.needsUpdate = true;
15652
16080
  return texture;
15653
16081
  }
15654
16082
  function useTextTexture(text, width, height, style, onLoad, onError) {
15655
- const [texture, setTexture] = (0, import_react55.useState)(null);
15656
- const onLoadRef = (0, import_react55.useRef)(onLoad);
15657
- const onErrorRef = (0, import_react55.useRef)(onError);
16083
+ const [texture, setTexture] = (0, import_react57.useState)(null);
16084
+ const onLoadRef = (0, import_react57.useRef)(onLoad);
16085
+ const onErrorRef = (0, import_react57.useRef)(onError);
15658
16086
  onLoadRef.current = onLoad;
15659
16087
  onErrorRef.current = onError;
15660
- (0, import_react55.useEffect)(() => {
16088
+ (0, import_react57.useEffect)(() => {
15661
16089
  let cancelled = false;
15662
16090
  let nextTexture = null;
15663
16091
  const run = async () => {
@@ -15750,13 +16178,13 @@ function TextHotspot({
15750
16178
  whiteSpace
15751
16179
  };
15752
16180
  const texture = useTextTexture(text, width, height, style, onLoad, onError);
15753
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(HotspotPlane, { map: texture, opacity }) });
16181
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(HotspotAnchor, { ...anchorProps, height, width, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(HotspotPlane, { map: texture, opacity }) });
15754
16182
  }
15755
16183
 
15756
16184
  // src/hotspot/iframe-hotspot.tsx
15757
16185
  var import_drei3 = require("@react-three/drei");
15758
- var import_three31 = require("three");
15759
- var import_jsx_runtime36 = require("react/jsx-runtime");
16186
+ var import_three35 = require("three");
16187
+ var import_jsx_runtime37 = require("react/jsx-runtime");
15760
16188
  var IFRAME_LONG_SIDE = 800;
15761
16189
  var CSS3D_DISTANCE_FACTOR = 400;
15762
16190
  var DEFAULT_SANDBOX = "allow-scripts allow-popups allow-forms";
@@ -15813,7 +16241,7 @@ function IframeHotspot({
15813
16241
  interactive,
15814
16242
  pointerEvents
15815
16243
  );
15816
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
16244
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
15817
16245
  HotspotAnchor,
15818
16246
  {
15819
16247
  ...anchorProps,
@@ -15822,20 +16250,20 @@ function IframeHotspot({
15822
16250
  pointerEvents,
15823
16251
  width,
15824
16252
  children: [
15825
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("mesh", { children: [
15826
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("planeGeometry", { args: [1, 1] }),
15827
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
16253
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("mesh", { children: [
16254
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("planeGeometry", { args: [1, 1] }),
16255
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
15828
16256
  "meshBasicMaterial",
15829
16257
  {
15830
16258
  depthWrite: false,
15831
16259
  opacity: 0,
15832
- side: import_three31.DoubleSide,
16260
+ side: import_three35.DoubleSide,
15833
16261
  toneMapped: false,
15834
16262
  transparent: true
15835
16263
  }
15836
16264
  )
15837
16265
  ] }),
15838
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
16266
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
15839
16267
  import_drei3.Html,
15840
16268
  {
15841
16269
  distanceFactor: CSS3D_DISTANCE_FACTOR,
@@ -15850,7 +16278,7 @@ function IframeHotspot({
15850
16278
  },
15851
16279
  transform: true,
15852
16280
  zIndexRange: [10, 0],
15853
- children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
16281
+ children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
15854
16282
  "iframe",
15855
16283
  {
15856
16284
  allow,
@@ -15903,6 +16331,7 @@ function IframeHotspot({
15903
16331
  Scenes,
15904
16332
  SequenceHotspot,
15905
16333
  Sphere,
16334
+ SphereTile,
15906
16335
  TextHotspot,
15907
16336
  Tile,
15908
16337
  TouchControls,