@vizor-vr/player 0.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.
Files changed (344) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +58 -0
  3. package/dist/__tests__/adapter-factory.test.d.ts +2 -0
  4. package/dist/__tests__/adapter-factory.test.d.ts.map +1 -0
  5. package/dist/__tests__/analytics-collector.test.d.ts +2 -0
  6. package/dist/__tests__/analytics-collector.test.d.ts.map +1 -0
  7. package/dist/__tests__/annotation-manager.test.d.ts +2 -0
  8. package/dist/__tests__/annotation-manager.test.d.ts.map +1 -0
  9. package/dist/__tests__/annotation-popup.test.d.ts +2 -0
  10. package/dist/__tests__/annotation-popup.test.d.ts.map +1 -0
  11. package/dist/__tests__/annotation-sprite.test.d.ts +2 -0
  12. package/dist/__tests__/annotation-sprite.test.d.ts.map +1 -0
  13. package/dist/__tests__/audio-manager.test.d.ts +2 -0
  14. package/dist/__tests__/audio-manager.test.d.ts.map +1 -0
  15. package/dist/__tests__/base-element-attrs.test.d.ts +2 -0
  16. package/dist/__tests__/base-element-attrs.test.d.ts.map +1 -0
  17. package/dist/__tests__/camera-controller.test.d.ts +2 -0
  18. package/dist/__tests__/camera-controller.test.d.ts.map +1 -0
  19. package/dist/__tests__/caption-renderer.test.d.ts +2 -0
  20. package/dist/__tests__/caption-renderer.test.d.ts.map +1 -0
  21. package/dist/__tests__/cc-button.test.d.ts +2 -0
  22. package/dist/__tests__/cc-button.test.d.ts.map +1 -0
  23. package/dist/__tests__/chat-button.test.d.ts +2 -0
  24. package/dist/__tests__/chat-button.test.d.ts.map +1 -0
  25. package/dist/__tests__/chat-panel.test.d.ts +2 -0
  26. package/dist/__tests__/chat-panel.test.d.ts.map +1 -0
  27. package/dist/__tests__/cinema-projection.test.d.ts +2 -0
  28. package/dist/__tests__/cinema-projection.test.d.ts.map +1 -0
  29. package/dist/__tests__/collab-client.test.d.ts +2 -0
  30. package/dist/__tests__/collab-client.test.d.ts.map +1 -0
  31. package/dist/__tests__/compass.test.d.ts +2 -0
  32. package/dist/__tests__/compass.test.d.ts.map +1 -0
  33. package/dist/__tests__/controls-overlay.test.d.ts +2 -0
  34. package/dist/__tests__/controls-overlay.test.d.ts.map +1 -0
  35. package/dist/__tests__/cubemap-projection.test.d.ts +2 -0
  36. package/dist/__tests__/cubemap-projection.test.d.ts.map +1 -0
  37. package/dist/__tests__/dash-adapter.test.d.ts +2 -0
  38. package/dist/__tests__/dash-adapter.test.d.ts.map +1 -0
  39. package/dist/__tests__/eac-projection.test.d.ts +2 -0
  40. package/dist/__tests__/eac-projection.test.d.ts.map +1 -0
  41. package/dist/__tests__/equirect-projection.test.d.ts +2 -0
  42. package/dist/__tests__/equirect-projection.test.d.ts.map +1 -0
  43. package/dist/__tests__/event-emitter.test.d.ts +2 -0
  44. package/dist/__tests__/event-emitter.test.d.ts.map +1 -0
  45. package/dist/__tests__/feature-gates-branding.test.d.ts +2 -0
  46. package/dist/__tests__/feature-gates-branding.test.d.ts.map +1 -0
  47. package/dist/__tests__/feature-gates.test.d.ts +2 -0
  48. package/dist/__tests__/feature-gates.test.d.ts.map +1 -0
  49. package/dist/__tests__/fisheye-projection.test.d.ts +2 -0
  50. package/dist/__tests__/fisheye-projection.test.d.ts.map +1 -0
  51. package/dist/__tests__/flat-projection.test.d.ts +2 -0
  52. package/dist/__tests__/flat-projection.test.d.ts.map +1 -0
  53. package/dist/__tests__/flat-video-integration.test.d.ts +2 -0
  54. package/dist/__tests__/flat-video-integration.test.d.ts.map +1 -0
  55. package/dist/__tests__/fullscreen-button.test.d.ts +2 -0
  56. package/dist/__tests__/fullscreen-button.test.d.ts.map +1 -0
  57. package/dist/__tests__/gaze-cursor-manager.test.d.ts +2 -0
  58. package/dist/__tests__/gaze-cursor-manager.test.d.ts.map +1 -0
  59. package/dist/__tests__/gaze-sender.test.d.ts +2 -0
  60. package/dist/__tests__/gaze-sender.test.d.ts.map +1 -0
  61. package/dist/__tests__/gaze-tracker.test.d.ts +2 -0
  62. package/dist/__tests__/gaze-tracker.test.d.ts.map +1 -0
  63. package/dist/__tests__/hls-adapter.test.d.ts +2 -0
  64. package/dist/__tests__/hls-adapter.test.d.ts.map +1 -0
  65. package/dist/__tests__/hotspot-interaction.test.d.ts +2 -0
  66. package/dist/__tests__/hotspot-interaction.test.d.ts.map +1 -0
  67. package/dist/__tests__/hotspot-manager.test.d.ts +2 -0
  68. package/dist/__tests__/hotspot-manager.test.d.ts.map +1 -0
  69. package/dist/__tests__/hotspot-renderer.test.d.ts +2 -0
  70. package/dist/__tests__/hotspot-renderer.test.d.ts.map +1 -0
  71. package/dist/__tests__/integrity.test.d.ts +2 -0
  72. package/dist/__tests__/integrity.test.d.ts.map +1 -0
  73. package/dist/__tests__/keyboard-shortcuts.test.d.ts +2 -0
  74. package/dist/__tests__/keyboard-shortcuts.test.d.ts.map +1 -0
  75. package/dist/__tests__/license-checker.test.d.ts +2 -0
  76. package/dist/__tests__/license-checker.test.d.ts.map +1 -0
  77. package/dist/__tests__/live-indicator.test.d.ts +2 -0
  78. package/dist/__tests__/live-indicator.test.d.ts.map +1 -0
  79. package/dist/__tests__/live.test.d.ts +2 -0
  80. package/dist/__tests__/live.test.d.ts.map +1 -0
  81. package/dist/__tests__/master-key.test.d.ts +2 -0
  82. package/dist/__tests__/master-key.test.d.ts.map +1 -0
  83. package/dist/__tests__/media-element.test.d.ts +2 -0
  84. package/dist/__tests__/media-element.test.d.ts.map +1 -0
  85. package/dist/__tests__/meta-config.test.d.ts +2 -0
  86. package/dist/__tests__/meta-config.test.d.ts.map +1 -0
  87. package/dist/__tests__/play-button.test.d.ts +2 -0
  88. package/dist/__tests__/play-button.test.d.ts.map +1 -0
  89. package/dist/__tests__/player-exports.test.d.ts +2 -0
  90. package/dist/__tests__/player-exports.test.d.ts.map +1 -0
  91. package/dist/__tests__/player-state.test.d.ts +2 -0
  92. package/dist/__tests__/player-state.test.d.ts.map +1 -0
  93. package/dist/__tests__/playlist-controls.test.d.ts +2 -0
  94. package/dist/__tests__/playlist-controls.test.d.ts.map +1 -0
  95. package/dist/__tests__/playlist-panel.test.d.ts +2 -0
  96. package/dist/__tests__/playlist-panel.test.d.ts.map +1 -0
  97. package/dist/__tests__/playlist.test.d.ts +2 -0
  98. package/dist/__tests__/playlist.test.d.ts.map +1 -0
  99. package/dist/__tests__/progressive-adapter.test.d.ts +2 -0
  100. package/dist/__tests__/progressive-adapter.test.d.ts.map +1 -0
  101. package/dist/__tests__/quality-selector.test.d.ts +2 -0
  102. package/dist/__tests__/quality-selector.test.d.ts.map +1 -0
  103. package/dist/__tests__/renderer.test.d.ts +2 -0
  104. package/dist/__tests__/renderer.test.d.ts.map +1 -0
  105. package/dist/__tests__/security/license-key-exposure.test.d.ts +2 -0
  106. package/dist/__tests__/security/license-key-exposure.test.d.ts.map +1 -0
  107. package/dist/__tests__/security/sanitize-xss.test.d.ts +2 -0
  108. package/dist/__tests__/security/sanitize-xss.test.d.ts.map +1 -0
  109. package/dist/__tests__/security/sri-generation.test.d.ts +2 -0
  110. package/dist/__tests__/security/sri-generation.test.d.ts.map +1 -0
  111. package/dist/__tests__/security/xss-annotations.test.d.ts +2 -0
  112. package/dist/__tests__/security/xss-annotations.test.d.ts.map +1 -0
  113. package/dist/__tests__/security/xss-captions.test.d.ts +2 -0
  114. package/dist/__tests__/security/xss-captions.test.d.ts.map +1 -0
  115. package/dist/__tests__/seek-bar.test.d.ts +2 -0
  116. package/dist/__tests__/seek-bar.test.d.ts.map +1 -0
  117. package/dist/__tests__/source-manager.test.d.ts +2 -0
  118. package/dist/__tests__/source-manager.test.d.ts.map +1 -0
  119. package/dist/__tests__/sprint1-memory-disposal.test.d.ts +10 -0
  120. package/dist/__tests__/sprint1-memory-disposal.test.d.ts.map +1 -0
  121. package/dist/__tests__/sprint3-frustum-adaptive.test.d.ts +9 -0
  122. package/dist/__tests__/sprint3-frustum-adaptive.test.d.ts.map +1 -0
  123. package/dist/__tests__/sprint5-bundle-memory.test.d.ts +18 -0
  124. package/dist/__tests__/sprint5-bundle-memory.test.d.ts.map +1 -0
  125. package/dist/__tests__/voice-button.test.d.ts +2 -0
  126. package/dist/__tests__/voice-button.test.d.ts.map +1 -0
  127. package/dist/__tests__/voice-manager.test.d.ts +2 -0
  128. package/dist/__tests__/voice-manager.test.d.ts.map +1 -0
  129. package/dist/__tests__/volume-control.test.d.ts +2 -0
  130. package/dist/__tests__/volume-control.test.d.ts.map +1 -0
  131. package/dist/__tests__/vr-button.test.d.ts +2 -0
  132. package/dist/__tests__/vr-button.test.d.ts.map +1 -0
  133. package/dist/__tests__/vz-cinema-element.test.d.ts +2 -0
  134. package/dist/__tests__/vz-cinema-element.test.d.ts.map +1 -0
  135. package/dist/__tests__/vz-img-element.test.d.ts +2 -0
  136. package/dist/__tests__/vz-img-element.test.d.ts.map +1 -0
  137. package/dist/__tests__/vz-playlist-element.test.d.ts +2 -0
  138. package/dist/__tests__/vz-playlist-element.test.d.ts.map +1 -0
  139. package/dist/__tests__/vz-tour-element.test.d.ts +2 -0
  140. package/dist/__tests__/vz-tour-element.test.d.ts.map +1 -0
  141. package/dist/__tests__/vz-tour-img.test.d.ts +2 -0
  142. package/dist/__tests__/vz-tour-img.test.d.ts.map +1 -0
  143. package/dist/__tests__/vz-tour-portal.test.d.ts +2 -0
  144. package/dist/__tests__/vz-tour-portal.test.d.ts.map +1 -0
  145. package/dist/__tests__/vz-video-element.test.d.ts +2 -0
  146. package/dist/__tests__/vz-video-element.test.d.ts.map +1 -0
  147. package/dist/__tests__/watermark-guard.test.d.ts +2 -0
  148. package/dist/__tests__/watermark-guard.test.d.ts.map +1 -0
  149. package/dist/__tests__/watermark.test.d.ts +2 -0
  150. package/dist/__tests__/watermark.test.d.ts.map +1 -0
  151. package/dist/__tests__/webvtt-parser.test.d.ts +2 -0
  152. package/dist/__tests__/webvtt-parser.test.d.ts.map +1 -0
  153. package/dist/__tests__/xr-controller.test.d.ts +2 -0
  154. package/dist/__tests__/xr-controller.test.d.ts.map +1 -0
  155. package/dist/__tests__/xr-manager.test.d.ts +2 -0
  156. package/dist/__tests__/xr-manager.test.d.ts.map +1 -0
  157. package/dist/analytics/analytics-collector.d.ts +29 -0
  158. package/dist/analytics/analytics-collector.d.ts.map +1 -0
  159. package/dist/analytics/gaze-tracker.d.ts +44 -0
  160. package/dist/analytics/gaze-tracker.d.ts.map +1 -0
  161. package/dist/analytics/index.d.ts +32 -0
  162. package/dist/analytics/index.d.ts.map +1 -0
  163. package/dist/annotations/annotation-manager.d.ts +31 -0
  164. package/dist/annotations/annotation-manager.d.ts.map +1 -0
  165. package/dist/annotations/annotation-popup.d.ts +21 -0
  166. package/dist/annotations/annotation-popup.d.ts.map +1 -0
  167. package/dist/annotations/annotation-sprite.d.ts +10 -0
  168. package/dist/annotations/annotation-sprite.d.ts.map +1 -0
  169. package/dist/annotations/index.d.ts +4 -0
  170. package/dist/annotations/index.d.ts.map +1 -0
  171. package/dist/annotations-C0ugfCn4.js +2158 -0
  172. package/dist/annotations-C0ugfCn4.js.map +1 -0
  173. package/dist/audio/ambisonic-renderer.d.ts +36 -0
  174. package/dist/audio/ambisonic-renderer.d.ts.map +1 -0
  175. package/dist/audio/audio-manager.d.ts +44 -0
  176. package/dist/audio/audio-manager.d.ts.map +1 -0
  177. package/dist/captions/caption-renderer.d.ts +57 -0
  178. package/dist/captions/caption-renderer.d.ts.map +1 -0
  179. package/dist/captions/index.d.ts +3 -0
  180. package/dist/captions/index.d.ts.map +1 -0
  181. package/dist/captions/webvtt-parser.d.ts +31 -0
  182. package/dist/captions/webvtt-parser.d.ts.map +1 -0
  183. package/dist/captions-BP0H2E03.js +274 -0
  184. package/dist/captions-BP0H2E03.js.map +1 -0
  185. package/dist/collab-BXPomrS0.js +978 -0
  186. package/dist/collab-BXPomrS0.js.map +1 -0
  187. package/dist/collaborative/chat-button.d.ts +22 -0
  188. package/dist/collaborative/chat-button.d.ts.map +1 -0
  189. package/dist/collaborative/chat-panel.d.ts +46 -0
  190. package/dist/collaborative/chat-panel.d.ts.map +1 -0
  191. package/dist/collaborative/collab-client.d.ts +73 -0
  192. package/dist/collaborative/collab-client.d.ts.map +1 -0
  193. package/dist/collaborative/gaze-cursor-manager.d.ts +29 -0
  194. package/dist/collaborative/gaze-cursor-manager.d.ts.map +1 -0
  195. package/dist/collaborative/gaze-sender.d.ts +29 -0
  196. package/dist/collaborative/gaze-sender.d.ts.map +1 -0
  197. package/dist/collaborative/voice-button.d.ts +25 -0
  198. package/dist/collaborative/voice-button.d.ts.map +1 -0
  199. package/dist/collaborative/voice-manager.d.ts +45 -0
  200. package/dist/collaborative/voice-manager.d.ts.map +1 -0
  201. package/dist/config/format-registry.d.ts +2 -0
  202. package/dist/config/format-registry.d.ts.map +1 -0
  203. package/dist/config/meta-config.d.ts +14 -0
  204. package/dist/config/meta-config.d.ts.map +1 -0
  205. package/dist/controls/cc-button.d.ts +24 -0
  206. package/dist/controls/cc-button.d.ts.map +1 -0
  207. package/dist/controls/compass.d.ts +15 -0
  208. package/dist/controls/compass.d.ts.map +1 -0
  209. package/dist/controls/controls-overlay.d.ts +46 -0
  210. package/dist/controls/controls-overlay.d.ts.map +1 -0
  211. package/dist/controls/fullscreen-button.d.ts +16 -0
  212. package/dist/controls/fullscreen-button.d.ts.map +1 -0
  213. package/dist/controls/icons.d.ts +23 -0
  214. package/dist/controls/icons.d.ts.map +1 -0
  215. package/dist/controls/keyboard-shortcuts.d.ts +21 -0
  216. package/dist/controls/keyboard-shortcuts.d.ts.map +1 -0
  217. package/dist/controls/live-indicator.d.ts +17 -0
  218. package/dist/controls/live-indicator.d.ts.map +1 -0
  219. package/dist/controls/play-button.d.ts +14 -0
  220. package/dist/controls/play-button.d.ts.map +1 -0
  221. package/dist/controls/playlist-controls.d.ts +18 -0
  222. package/dist/controls/playlist-controls.d.ts.map +1 -0
  223. package/dist/controls/playlist-panel.d.ts +27 -0
  224. package/dist/controls/playlist-panel.d.ts.map +1 -0
  225. package/dist/controls/quality-menu.d.ts +17 -0
  226. package/dist/controls/quality-menu.d.ts.map +1 -0
  227. package/dist/controls/seek-bar.d.ts +23 -0
  228. package/dist/controls/seek-bar.d.ts.map +1 -0
  229. package/dist/controls/volume-control.d.ts +14 -0
  230. package/dist/controls/volume-control.d.ts.map +1 -0
  231. package/dist/controls/vr-button.d.ts +14 -0
  232. package/dist/controls/vr-button.d.ts.map +1 -0
  233. package/dist/core/base-element.d.ts +53 -0
  234. package/dist/core/base-element.d.ts.map +1 -0
  235. package/dist/core/event-emitter.d.ts +23 -0
  236. package/dist/core/event-emitter.d.ts.map +1 -0
  237. package/dist/core/html-element.d.ts +13 -0
  238. package/dist/core/html-element.d.ts.map +1 -0
  239. package/dist/core/media-element.d.ts +86 -0
  240. package/dist/core/media-element.d.ts.map +1 -0
  241. package/dist/core/player-state.d.ts +63 -0
  242. package/dist/core/player-state.d.ts.map +1 -0
  243. package/dist/dash-adapter-tid9ZyhO.js +75 -0
  244. package/dist/dash-adapter-tid9ZyhO.js.map +1 -0
  245. package/dist/elements/vz-annotation.d.ts +26 -0
  246. package/dist/elements/vz-annotation.d.ts.map +1 -0
  247. package/dist/elements/vz-cinema.d.ts +28 -0
  248. package/dist/elements/vz-cinema.d.ts.map +1 -0
  249. package/dist/elements/vz-img.d.ts +27 -0
  250. package/dist/elements/vz-img.d.ts.map +1 -0
  251. package/dist/elements/vz-live.d.ts +36 -0
  252. package/dist/elements/vz-live.d.ts.map +1 -0
  253. package/dist/elements/vz-playlist.d.ts +74 -0
  254. package/dist/elements/vz-playlist.d.ts.map +1 -0
  255. package/dist/elements/vz-tour-img.d.ts +21 -0
  256. package/dist/elements/vz-tour-img.d.ts.map +1 -0
  257. package/dist/elements/vz-tour-portal.d.ts +19 -0
  258. package/dist/elements/vz-tour-portal.d.ts.map +1 -0
  259. package/dist/elements/vz-tour.d.ts +49 -0
  260. package/dist/elements/vz-tour.d.ts.map +1 -0
  261. package/dist/elements/vz-video.d.ts +21 -0
  262. package/dist/elements/vz-video.d.ts.map +1 -0
  263. package/dist/hls-adapter-BivH46L_.js +97 -0
  264. package/dist/hls-adapter-BivH46L_.js.map +1 -0
  265. package/dist/hotspots/hotspot-interaction.d.ts +23 -0
  266. package/dist/hotspots/hotspot-interaction.d.ts.map +1 -0
  267. package/dist/hotspots/hotspot-manager.d.ts +18 -0
  268. package/dist/hotspots/hotspot-manager.d.ts.map +1 -0
  269. package/dist/hotspots/hotspot-renderer.d.ts +26 -0
  270. package/dist/hotspots/hotspot-renderer.d.ts.map +1 -0
  271. package/dist/index.d.ts +48 -0
  272. package/dist/index.d.ts.map +1 -0
  273. package/dist/license/feature-gates.d.ts +6 -0
  274. package/dist/license/feature-gates.d.ts.map +1 -0
  275. package/dist/license/integrity.d.ts +33 -0
  276. package/dist/license/integrity.d.ts.map +1 -0
  277. package/dist/license/license-checker.d.ts +18 -0
  278. package/dist/license/license-checker.d.ts.map +1 -0
  279. package/dist/license/master-key.d.ts +14 -0
  280. package/dist/license/master-key.d.ts.map +1 -0
  281. package/dist/license/watermark-guard.d.ts +24 -0
  282. package/dist/license/watermark-guard.d.ts.map +1 -0
  283. package/dist/license/watermark.d.ts +19 -0
  284. package/dist/license/watermark.d.ts.map +1 -0
  285. package/dist/register-CwnmiGEs.js +5740 -0
  286. package/dist/register-CwnmiGEs.js.map +1 -0
  287. package/dist/register.d.ts +6 -0
  288. package/dist/register.d.ts.map +1 -0
  289. package/dist/register.js +5 -0
  290. package/dist/register.js.map +1 -0
  291. package/dist/renderer/camera-controller.d.ts +75 -0
  292. package/dist/renderer/camera-controller.d.ts.map +1 -0
  293. package/dist/renderer/projections/cinema-projection.d.ts +32 -0
  294. package/dist/renderer/projections/cinema-projection.d.ts.map +1 -0
  295. package/dist/renderer/projections/cubemap-projection.d.ts +34 -0
  296. package/dist/renderer/projections/cubemap-projection.d.ts.map +1 -0
  297. package/dist/renderer/projections/eac-projection.d.ts +35 -0
  298. package/dist/renderer/projections/eac-projection.d.ts.map +1 -0
  299. package/dist/renderer/projections/equirect-projection.d.ts +27 -0
  300. package/dist/renderer/projections/equirect-projection.d.ts.map +1 -0
  301. package/dist/renderer/projections/fisheye-projection.d.ts +28 -0
  302. package/dist/renderer/projections/fisheye-projection.d.ts.map +1 -0
  303. package/dist/renderer/projections/flat-projection.d.ts +32 -0
  304. package/dist/renderer/projections/flat-projection.d.ts.map +1 -0
  305. package/dist/renderer/projections/projection.d.ts +18 -0
  306. package/dist/renderer/projections/projection.d.ts.map +1 -0
  307. package/dist/renderer/renderer.d.ts +72 -0
  308. package/dist/renderer/renderer.d.ts.map +1 -0
  309. package/dist/renderer/shaders/eac.glsl.d.ts +12 -0
  310. package/dist/renderer/shaders/eac.glsl.d.ts.map +1 -0
  311. package/dist/renderer/shaders/fisheye.glsl.d.ts +22 -0
  312. package/dist/renderer/shaders/fisheye.glsl.d.ts.map +1 -0
  313. package/dist/spatial-BeadwNJA.js +146 -0
  314. package/dist/spatial-BeadwNJA.js.map +1 -0
  315. package/dist/sri.json +12 -0
  316. package/dist/streaming/adapter-factory.d.ts +8 -0
  317. package/dist/streaming/adapter-factory.d.ts.map +1 -0
  318. package/dist/streaming/dash-adapter.d.ts +21 -0
  319. package/dist/streaming/dash-adapter.d.ts.map +1 -0
  320. package/dist/streaming/hls-adapter.d.ts +26 -0
  321. package/dist/streaming/hls-adapter.d.ts.map +1 -0
  322. package/dist/streaming/progressive-adapter.d.ts +18 -0
  323. package/dist/streaming/progressive-adapter.d.ts.map +1 -0
  324. package/dist/streaming/quality-selector.d.ts +25 -0
  325. package/dist/streaming/quality-selector.d.ts.map +1 -0
  326. package/dist/streaming/source-manager.d.ts +46 -0
  327. package/dist/streaming/source-manager.d.ts.map +1 -0
  328. package/dist/streaming/types.d.ts +25 -0
  329. package/dist/streaming/types.d.ts.map +1 -0
  330. package/dist/styles/controls.d.ts +15 -0
  331. package/dist/styles/controls.d.ts.map +1 -0
  332. package/dist/three-Bci7aSeI.js +20078 -0
  333. package/dist/three-Bci7aSeI.js.map +1 -0
  334. package/dist/utils/fullscreen.d.ts +6 -0
  335. package/dist/utils/fullscreen.d.ts.map +1 -0
  336. package/dist/utils/sanitize.d.ts +19 -0
  337. package/dist/utils/sanitize.d.ts.map +1 -0
  338. package/dist/vizor.js +113 -0
  339. package/dist/vizor.js.map +1 -0
  340. package/dist/xr/xr-controller.d.ts +27 -0
  341. package/dist/xr/xr-controller.d.ts.map +1 -0
  342. package/dist/xr/xr-manager.d.ts +43 -0
  343. package/dist/xr/xr-manager.d.ts.map +1 -0
  344. package/package.json +94 -0
@@ -0,0 +1,978 @@
1
+ import { C as CanvasTexture, L as LinearFilter, S as SpriteMaterial, a as Sprite } from "./three-Bci7aSeI.js";
2
+ import { C as COLLAB_GAZE_LERP_FACTOR, l as latLonToSpherical, a as COLLAB_GAZE_INTERVAL, b as COLLAB_GAZE_THRESHOLD } from "./annotations-C0ugfCn4.js";
3
+ const ICON_PLAY = `<svg viewBox="0 0 24 24"><path d="M8 5v14l11-7z"/></svg>`;
4
+ const ICON_PAUSE = `<svg viewBox="0 0 24 24"><path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/></svg>`;
5
+ const ICON_VOLUME_HIGH = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5" fill="currentColor" stroke="none"/><path d="M19.07 4.93a10 10 0 0 1 0 14.14"/><path d="M15.54 8.46a5 5 0 0 1 0 7.07"/></svg>`;
6
+ const ICON_VOLUME_LOW = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5" fill="currentColor" stroke="none"/><path d="M15.54 8.46a5 5 0 0 1 0 7.07"/></svg>`;
7
+ const ICON_VOLUME_MUTED = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5" fill="currentColor" stroke="none"/><line x1="23" y1="9" x2="17" y2="15"/><line x1="17" y1="9" x2="23" y2="15"/></svg>`;
8
+ const ICON_FULLSCREEN = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 3 21 3 21 9"/><polyline points="9 21 3 21 3 15"/><line x1="21" y1="3" x2="14" y2="10"/><line x1="3" y1="21" x2="10" y2="14"/></svg>`;
9
+ const ICON_FULLSCREEN_EXIT = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 14 10 14 10 20"/><polyline points="20 10 14 10 14 4"/><line x1="14" y1="10" x2="21" y2="3"/><line x1="3" y1="21" x2="10" y2="14"/></svg>`;
10
+ const ICON_VR = `<svg viewBox="0 0 24 24"><path d="M20.74 6H3.21C2.55 6 2 6.57 2 7.28v10.44c0 .7.55 1.28 1.23 1.28h4.79c.52 0 .96-.3 1.19-.77l1.58-3.15c.28-.58.84-.94 1.43-.94h1.56c.59 0 1.15.36 1.43.94l1.58 3.15c.23.47.67.77 1.19.77h4.79c.68 0 1.23-.57 1.23-1.28V7.28C22 6.57 21.43 6 20.74 6zM7.5 14.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5zm9 0c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/></svg>`;
11
+ const ICON_COMPASS = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><polygon points="16.24 7.76 14.12 14.12 7.76 16.24 9.88 9.88 16.24 7.76" fill="currentColor"/></svg>`;
12
+ const ICON_SETTINGS = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>`;
13
+ const ICON_PLAYLIST_NEXT = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polygon points="5 4 15 12 5 20 5 4" fill="currentColor"/><line x1="19" y1="5" x2="19" y2="19"/></svg>`;
14
+ const ICON_PLAYLIST_PREV = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polygon points="19 20 9 12 19 4 19 20" fill="currentColor"/><line x1="5" y1="19" x2="5" y2="5"/></svg>`;
15
+ const ICON_LIVE_DOT = `<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="6" fill="currentColor"/></svg>`;
16
+ const ICON_CC = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="4" width="20" height="16" rx="2" ry="2"/><path d="M7 10.5c0-.83.67-1.5 1.5-1.5s1.5.67 1.5 1.5"/><path d="M7 13.5c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5"/><path d="M14 10.5c0-.83.67-1.5 1.5-1.5s1.5.67 1.5 1.5"/><path d="M14 13.5c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5"/></svg>`;
17
+ const ICON_CHAT = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>`;
18
+ const ICON_MIC = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" y1="19" x2="12" y2="23"/><line x1="8" y1="23" x2="16" y2="23"/></svg>`;
19
+ const ICON_MIC_MUTED = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><line x1="1" y1="1" x2="23" y2="23"/><path d="M9 9v3a3 3 0 0 0 5.12 2.12M15 9.34V4a3 3 0 0 0-5.94-.6"/><path d="M17 16.95A7 7 0 0 1 5 12v-2m14 0v2c0 .64-.09 1.26-.26 1.85"/><line x1="12" y1="19" x2="12" y2="23"/><line x1="8" y1="23" x2="16" y2="23"/></svg>`;
20
+ const DRIFT_THRESHOLD = 1;
21
+ const RECONNECT_DELAY = 3e3;
22
+ const PLAYBACK_THROTTLE = 250;
23
+ class CollaborativeClient {
24
+ ws = null;
25
+ options;
26
+ unsubscribes = [];
27
+ reconnectTimer = null;
28
+ disposed = false;
29
+ lastPlaybackSend = 0;
30
+ connected = false;
31
+ constructor(options) {
32
+ this.options = options;
33
+ }
34
+ /** Connect to the collaborative server */
35
+ connect() {
36
+ if (this.disposed) return;
37
+ try {
38
+ this.ws = new WebSocket(this.options.serverUrl);
39
+ } catch {
40
+ this.scheduleReconnect();
41
+ return;
42
+ }
43
+ this.ws.onopen = () => {
44
+ this.connected = true;
45
+ this.send({
46
+ type: "join",
47
+ roomCode: this.options.roomCode,
48
+ userId: this.options.userId,
49
+ displayName: this.options.displayName,
50
+ password: this.options.password
51
+ });
52
+ if (this.options.role === "host") {
53
+ this.subscribeHostState();
54
+ }
55
+ };
56
+ this.ws.onmessage = (event) => {
57
+ try {
58
+ const msg = JSON.parse(event.data);
59
+ this.handleMessage(msg);
60
+ } catch {
61
+ }
62
+ };
63
+ this.ws.onclose = () => {
64
+ this.connected = false;
65
+ this.cleanupSubscriptions();
66
+ if (!this.disposed) {
67
+ this.scheduleReconnect();
68
+ }
69
+ };
70
+ this.ws.onerror = () => {
71
+ };
72
+ }
73
+ /** Whether the client is currently connected */
74
+ isConnected() {
75
+ return this.connected;
76
+ }
77
+ /** Gracefully disconnect and clean up */
78
+ dispose() {
79
+ this.disposed = true;
80
+ if (this.reconnectTimer) {
81
+ clearTimeout(this.reconnectTimer);
82
+ this.reconnectTimer = null;
83
+ }
84
+ this.cleanupSubscriptions();
85
+ if (this.ws) {
86
+ if (this.ws.readyState === WebSocket.OPEN) {
87
+ this.send({ type: "leave" });
88
+ }
89
+ this.ws.close();
90
+ this.ws = null;
91
+ }
92
+ this.connected = false;
93
+ }
94
+ // --- Private ---
95
+ handleMessage(msg) {
96
+ switch (msg.type) {
97
+ case "room_state":
98
+ this.handleRoomState(msg.users, msg.playing, msg.currentTime);
99
+ break;
100
+ case "sync":
101
+ this.handleSync(msg.playing, msg.currentTime);
102
+ break;
103
+ case "user_joined":
104
+ this.options.onUserJoined?.(msg.user);
105
+ this.options.onParticipantsChange?.([]);
106
+ break;
107
+ case "user_left":
108
+ this.options.onUserLeft?.(msg.userId);
109
+ this.options.onParticipantsChange?.([]);
110
+ break;
111
+ case "error":
112
+ console.warn(`[Vizor Collab] Server error: ${msg.code} — ${msg.message}`);
113
+ break;
114
+ case "peer_gaze":
115
+ this.options.onPeerGaze?.(msg.userId, msg.lat, msg.lon);
116
+ break;
117
+ case "chat_message":
118
+ this.options.onChatMessage?.(msg.userId, msg.displayName, msg.text, msg.timestamp);
119
+ break;
120
+ case "voice_signal":
121
+ this.options.onVoiceSignal?.(msg.fromUserId, msg.sdp, msg.candidate);
122
+ break;
123
+ }
124
+ }
125
+ handleRoomState(users, playing, currentTime) {
126
+ this.options.onParticipantsChange?.(users);
127
+ if (this.options.role === "viewer") {
128
+ this.applySync(playing, currentTime);
129
+ }
130
+ }
131
+ handleSync(playing, currentTime) {
132
+ if (this.options.role !== "viewer") return;
133
+ this.applySync(playing, currentTime);
134
+ }
135
+ applySync(playing, currentTime) {
136
+ const { state, mediaElement } = this.options;
137
+ const localTime = mediaElement.currentTime;
138
+ const drift = Math.abs(currentTime - localTime);
139
+ if (drift > DRIFT_THRESHOLD) {
140
+ mediaElement.seek(currentTime);
141
+ }
142
+ const localPlaying = state.get("playing");
143
+ if (playing && !localPlaying) {
144
+ Promise.resolve(mediaElement.play()).catch(() => {
145
+ });
146
+ } else if (!playing && localPlaying) {
147
+ mediaElement.pause();
148
+ }
149
+ }
150
+ /** Host: subscribe to local state changes and broadcast them */
151
+ subscribeHostState() {
152
+ const { state } = this.options;
153
+ const unsubPlaying = state.subscribe("playing", (playing) => {
154
+ this.sendPlaybackState(playing, state.get("currentTime"));
155
+ });
156
+ this.unsubscribes.push(unsubPlaying);
157
+ const unsubSeeking = state.subscribe("seeking", (seeking, prevSeeking) => {
158
+ if (!seeking && prevSeeking) {
159
+ this.send({
160
+ type: "seek",
161
+ currentTime: state.get("currentTime")
162
+ });
163
+ }
164
+ });
165
+ this.unsubscribes.push(unsubSeeking);
166
+ }
167
+ /** Throttled playback state sender */
168
+ sendPlaybackState(playing, currentTime) {
169
+ const now = Date.now();
170
+ if (now - this.lastPlaybackSend < PLAYBACK_THROTTLE) return;
171
+ this.lastPlaybackSend = now;
172
+ this.send({
173
+ type: "playback_state",
174
+ playing,
175
+ currentTime,
176
+ timestamp: now
177
+ });
178
+ }
179
+ /** Send a chat message */
180
+ sendChat(text) {
181
+ this.send({ type: "chat", text });
182
+ }
183
+ /** Send a voice signal (SDP offer/answer or ICE candidate) to a specific peer */
184
+ sendVoiceSignal(targetUserId, sdp, candidate) {
185
+ this.send({ type: "voice_signal", targetUserId, sdp, candidate });
186
+ }
187
+ /** Send a message to the server */
188
+ send(msg) {
189
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
190
+ this.ws.send(JSON.stringify(msg));
191
+ }
192
+ }
193
+ scheduleReconnect() {
194
+ if (this.disposed || this.reconnectTimer) return;
195
+ this.reconnectTimer = setTimeout(() => {
196
+ this.reconnectTimer = null;
197
+ this.connect();
198
+ }, RECONNECT_DELAY);
199
+ }
200
+ /** Register a cleanup function to run on dispose */
201
+ addCleanup(fn) {
202
+ this.unsubscribes.push(fn);
203
+ }
204
+ cleanupSubscriptions() {
205
+ for (const unsub of this.unsubscribes) unsub();
206
+ this.unsubscribes = [];
207
+ }
208
+ }
209
+ const PEER_COLORS$1 = [
210
+ "#FF6B6B",
211
+ "#4ECDC4",
212
+ "#45B7D1",
213
+ "#FFA07A",
214
+ "#98D8C8",
215
+ "#F7DC6F",
216
+ "#BB8FCE",
217
+ "#85C1E9",
218
+ "#F1948A",
219
+ "#82E0AA"
220
+ ];
221
+ const CURSOR_DISTANCE = 195;
222
+ const CURSOR_SCALE = 6;
223
+ const LABEL_SCALE_X = 14;
224
+ const LABEL_SCALE_Y = 5;
225
+ const CURSOR_CANVAS_SIZE = 64;
226
+ const LABEL_CANVAS_WIDTH = 256;
227
+ const LABEL_CANVAS_HEIGHT = 64;
228
+ class GazeCursorManager {
229
+ scene;
230
+ cursors = /* @__PURE__ */ new Map();
231
+ colorIndex = 0;
232
+ constructor(scene) {
233
+ this.scene = scene;
234
+ }
235
+ /** Add a cursor for a new peer */
236
+ addPeer(userId, displayName) {
237
+ if (this.cursors.has(userId)) return;
238
+ const color = PEER_COLORS$1[this.colorIndex % PEER_COLORS$1.length];
239
+ this.colorIndex++;
240
+ const sprite = this.createCursorSprite(color);
241
+ const nameLabel = this.createLabelSprite(displayName, color);
242
+ nameLabel.visible = true;
243
+ this.scene.add(sprite);
244
+ this.scene.add(nameLabel);
245
+ this.cursors.set(userId, {
246
+ sprite,
247
+ nameLabel,
248
+ targetLat: 0,
249
+ targetLon: 0,
250
+ currentLat: 0,
251
+ currentLon: 0,
252
+ displayName,
253
+ color
254
+ });
255
+ }
256
+ /** Remove a peer's cursor */
257
+ removePeer(userId) {
258
+ const cursor = this.cursors.get(userId);
259
+ if (!cursor) return;
260
+ this.scene.remove(cursor.sprite);
261
+ this.scene.remove(cursor.nameLabel);
262
+ cursor.sprite.material.map?.dispose();
263
+ cursor.sprite.material.dispose();
264
+ cursor.nameLabel.material.map?.dispose();
265
+ cursor.nameLabel.material.dispose();
266
+ this.cursors.delete(userId);
267
+ }
268
+ /** Update the target gaze position for a peer */
269
+ updateGaze(userId, lat, lon) {
270
+ const cursor = this.cursors.get(userId);
271
+ if (!cursor) return;
272
+ cursor.targetLat = lat;
273
+ cursor.targetLon = lon;
274
+ }
275
+ /** Called each animation frame. Lerps all cursors toward their target positions. */
276
+ update() {
277
+ for (const [, cursor] of this.cursors) {
278
+ cursor.currentLat += (cursor.targetLat - cursor.currentLat) * COLLAB_GAZE_LERP_FACTOR;
279
+ cursor.currentLon += (cursor.targetLon - cursor.currentLon) * COLLAB_GAZE_LERP_FACTOR;
280
+ const { phi, theta } = latLonToSpherical(cursor.currentLat, cursor.currentLon);
281
+ const x = CURSOR_DISTANCE * Math.sin(phi) * Math.cos(theta);
282
+ const y = CURSOR_DISTANCE * Math.cos(phi);
283
+ const z = CURSOR_DISTANCE * Math.sin(phi) * Math.sin(theta);
284
+ cursor.sprite.position.set(x, y, z);
285
+ cursor.nameLabel.position.set(x, y + CURSOR_SCALE * 0.8, z);
286
+ }
287
+ }
288
+ /** Get the number of tracked peers */
289
+ getPeerCount() {
290
+ return this.cursors.size;
291
+ }
292
+ /** Clean up all cursors */
293
+ dispose() {
294
+ for (const [userId] of this.cursors) {
295
+ this.removePeer(userId);
296
+ }
297
+ }
298
+ /** Create a colored circle sprite for the cursor dot */
299
+ createCursorSprite(color) {
300
+ const canvas = document.createElement("canvas");
301
+ canvas.width = CURSOR_CANVAS_SIZE;
302
+ canvas.height = CURSOR_CANVAS_SIZE;
303
+ const ctx = canvas.getContext("2d");
304
+ const cx = CURSOR_CANVAS_SIZE / 2;
305
+ const cy = CURSOR_CANVAS_SIZE / 2;
306
+ const radius = CURSOR_CANVAS_SIZE / 2 - 4;
307
+ ctx.fillStyle = color;
308
+ ctx.beginPath();
309
+ ctx.arc(cx, cy, radius, 0, Math.PI * 2);
310
+ ctx.fill();
311
+ ctx.strokeStyle = "#ffffff";
312
+ ctx.lineWidth = 3;
313
+ ctx.stroke();
314
+ const texture = new CanvasTexture(canvas);
315
+ texture.minFilter = LinearFilter;
316
+ texture.magFilter = LinearFilter;
317
+ const material = new SpriteMaterial({
318
+ map: texture,
319
+ sizeAttenuation: true,
320
+ depthTest: false,
321
+ transparent: true
322
+ });
323
+ const sprite = new Sprite(material);
324
+ sprite.scale.set(CURSOR_SCALE, CURSOR_SCALE, 1);
325
+ return sprite;
326
+ }
327
+ /** Create a text label sprite showing the peer's display name */
328
+ createLabelSprite(name, color) {
329
+ const canvas = document.createElement("canvas");
330
+ canvas.width = LABEL_CANVAS_WIDTH;
331
+ canvas.height = LABEL_CANVAS_HEIGHT;
332
+ const ctx = canvas.getContext("2d");
333
+ const padding = 10;
334
+ ctx.fillStyle = "rgba(0, 0, 0, 0.6)";
335
+ ctx.beginPath();
336
+ ctx.roundRect(padding, padding, LABEL_CANVAS_WIDTH - padding * 2, LABEL_CANVAS_HEIGHT - padding * 2, 8);
337
+ ctx.fill();
338
+ ctx.fillStyle = color;
339
+ ctx.font = "bold 24px sans-serif";
340
+ ctx.textAlign = "center";
341
+ ctx.textBaseline = "middle";
342
+ ctx.fillText(name, LABEL_CANVAS_WIDTH / 2, LABEL_CANVAS_HEIGHT / 2);
343
+ const texture = new CanvasTexture(canvas);
344
+ texture.minFilter = LinearFilter;
345
+ texture.magFilter = LinearFilter;
346
+ const material = new SpriteMaterial({
347
+ map: texture,
348
+ sizeAttenuation: true,
349
+ depthTest: false,
350
+ transparent: true
351
+ });
352
+ const sprite = new Sprite(material);
353
+ sprite.scale.set(LABEL_SCALE_X, LABEL_SCALE_Y, 1);
354
+ return sprite;
355
+ }
356
+ }
357
+ class GazeSender {
358
+ timer = null;
359
+ lastSentLat = NaN;
360
+ lastSentLon = NaN;
361
+ orientationProvider;
362
+ sendFn;
363
+ constructor(orientationProvider, sendFn) {
364
+ this.orientationProvider = orientationProvider;
365
+ this.sendFn = sendFn;
366
+ }
367
+ /** Start sampling and sending gaze messages */
368
+ start() {
369
+ if (this.timer) return;
370
+ this.timer = setInterval(() => this.sample(), COLLAB_GAZE_INTERVAL);
371
+ }
372
+ /** Stop sampling */
373
+ stop() {
374
+ if (this.timer) {
375
+ clearInterval(this.timer);
376
+ this.timer = null;
377
+ }
378
+ }
379
+ /** Clean up */
380
+ dispose() {
381
+ this.stop();
382
+ }
383
+ sample() {
384
+ const { lat, lon } = this.orientationProvider.getOrientation();
385
+ const dLat = Math.abs(lat - this.lastSentLat);
386
+ const dLon = Math.abs(lon - this.lastSentLon);
387
+ if (dLat > COLLAB_GAZE_THRESHOLD || dLon > COLLAB_GAZE_THRESHOLD || isNaN(this.lastSentLat)) {
388
+ this.lastSentLat = lat;
389
+ this.lastSentLon = lon;
390
+ this.sendFn({ type: "gaze", lat, lon });
391
+ }
392
+ }
393
+ }
394
+ const PEER_COLORS = [
395
+ "#FF6B6B",
396
+ "#4ECDC4",
397
+ "#45B7D1",
398
+ "#FFA07A",
399
+ "#98D8C8",
400
+ "#F7DC6F",
401
+ "#BB8FCE",
402
+ "#85C1E9",
403
+ "#F1948A",
404
+ "#82E0AA"
405
+ ];
406
+ const CHAT_CSS = `
407
+ .vz-chat-panel {
408
+ position: absolute;
409
+ right: 0;
410
+ top: 0;
411
+ bottom: 0;
412
+ width: 300px;
413
+ max-width: 70%;
414
+ background: rgba(15, 15, 25, 0.95);
415
+ backdrop-filter: blur(16px);
416
+ -webkit-backdrop-filter: blur(16px);
417
+ z-index: 25;
418
+ display: flex;
419
+ flex-direction: column;
420
+ transform: translateX(100%);
421
+ transition: transform 0.3s ease;
422
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
423
+ }
424
+ .vz-chat-panel.open {
425
+ transform: translateX(0);
426
+ }
427
+ .vz-chat-header {
428
+ display: flex;
429
+ align-items: center;
430
+ justify-content: space-between;
431
+ padding: 12px 16px;
432
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
433
+ flex-shrink: 0;
434
+ }
435
+ .vz-chat-title {
436
+ color: #fff;
437
+ font-size: 14px;
438
+ font-weight: 600;
439
+ }
440
+ .vz-chat-close {
441
+ background: none;
442
+ border: none;
443
+ color: rgba(255, 255, 255, 0.6);
444
+ font-size: 18px;
445
+ cursor: pointer;
446
+ padding: 0 4px;
447
+ line-height: 1;
448
+ }
449
+ .vz-chat-close:hover {
450
+ color: #fff;
451
+ }
452
+ .vz-chat-messages {
453
+ flex: 1;
454
+ overflow-y: auto;
455
+ padding: 8px 12px;
456
+ scrollbar-width: thin;
457
+ scrollbar-color: rgba(255,255,255,0.2) transparent;
458
+ }
459
+ .vz-chat-messages::-webkit-scrollbar {
460
+ width: 4px;
461
+ }
462
+ .vz-chat-messages::-webkit-scrollbar-thumb {
463
+ background: rgba(255,255,255,0.2);
464
+ border-radius: 2px;
465
+ }
466
+ .vz-chat-message {
467
+ margin: 4px 0;
468
+ padding: 4px 0;
469
+ }
470
+ .vz-chat-msg-header {
471
+ display: flex;
472
+ align-items: baseline;
473
+ gap: 6px;
474
+ }
475
+ .vz-chat-msg-name {
476
+ font-weight: 600;
477
+ font-size: 12px;
478
+ }
479
+ .vz-chat-msg-time {
480
+ font-size: 11px;
481
+ color: rgba(255, 255, 255, 0.4);
482
+ }
483
+ .vz-chat-msg-text {
484
+ font-size: 13px;
485
+ color: rgba(255, 255, 255, 0.9);
486
+ word-break: break-word;
487
+ margin-top: 2px;
488
+ line-height: 1.4;
489
+ }
490
+ .vz-chat-input-row {
491
+ display: flex;
492
+ gap: 6px;
493
+ padding: 8px 12px;
494
+ border-top: 1px solid rgba(255, 255, 255, 0.1);
495
+ flex-shrink: 0;
496
+ }
497
+ .vz-chat-input {
498
+ flex: 1;
499
+ height: 32px;
500
+ border-radius: 6px;
501
+ border: none;
502
+ background: rgba(255, 255, 255, 0.1);
503
+ color: #fff;
504
+ padding: 0 10px;
505
+ font-size: 13px;
506
+ outline: none;
507
+ }
508
+ .vz-chat-input::placeholder {
509
+ color: rgba(255, 255, 255, 0.3);
510
+ }
511
+ .vz-chat-input:focus {
512
+ background: rgba(255, 255, 255, 0.15);
513
+ }
514
+ .vz-chat-send {
515
+ width: 32px;
516
+ height: 32px;
517
+ border-radius: 6px;
518
+ border: none;
519
+ background: var(--vz-primary, #f43f5e);
520
+ color: #fff;
521
+ font-size: 16px;
522
+ cursor: pointer;
523
+ display: flex;
524
+ align-items: center;
525
+ justify-content: center;
526
+ flex-shrink: 0;
527
+ }
528
+ .vz-chat-send:hover {
529
+ opacity: 0.85;
530
+ }
531
+ .vz-chat-empty {
532
+ color: rgba(255, 255, 255, 0.3);
533
+ font-size: 13px;
534
+ text-align: center;
535
+ padding: 24px 16px;
536
+ }
537
+ `;
538
+ class ChatPanel {
539
+ panel;
540
+ messagesEl;
541
+ inputEl;
542
+ emptyEl;
543
+ styleEl;
544
+ isOpen = false;
545
+ messages = [];
546
+ colorMap = /* @__PURE__ */ new Map();
547
+ colorIndex = 0;
548
+ onSend;
549
+ shadowRoot;
550
+ constructor(shadowRoot, onSend) {
551
+ this.shadowRoot = shadowRoot;
552
+ this.onSend = onSend;
553
+ this.styleEl = document.createElement("style");
554
+ this.styleEl.textContent = CHAT_CSS;
555
+ shadowRoot.appendChild(this.styleEl);
556
+ this.panel = document.createElement("div");
557
+ this.panel.className = "vz-chat-panel";
558
+ const header = document.createElement("div");
559
+ header.className = "vz-chat-header";
560
+ const title = document.createElement("span");
561
+ title.className = "vz-chat-title";
562
+ title.textContent = "Chat";
563
+ const closeBtn = document.createElement("button");
564
+ closeBtn.className = "vz-chat-close";
565
+ closeBtn.textContent = "✕";
566
+ closeBtn.addEventListener("click", () => this.close());
567
+ header.appendChild(title);
568
+ header.appendChild(closeBtn);
569
+ this.panel.appendChild(header);
570
+ this.messagesEl = document.createElement("div");
571
+ this.messagesEl.className = "vz-chat-messages";
572
+ this.emptyEl = document.createElement("div");
573
+ this.emptyEl.className = "vz-chat-empty";
574
+ this.emptyEl.textContent = "No messages yet";
575
+ this.messagesEl.appendChild(this.emptyEl);
576
+ this.panel.appendChild(this.messagesEl);
577
+ const inputRow = document.createElement("div");
578
+ inputRow.className = "vz-chat-input-row";
579
+ this.inputEl = document.createElement("input");
580
+ this.inputEl.className = "vz-chat-input";
581
+ this.inputEl.type = "text";
582
+ this.inputEl.placeholder = "Type a message...";
583
+ this.inputEl.maxLength = 500;
584
+ this.inputEl.addEventListener("keydown", (e) => {
585
+ e.stopPropagation();
586
+ if (e.key === "Enter") {
587
+ this.handleSend();
588
+ }
589
+ });
590
+ const sendBtn = document.createElement("button");
591
+ sendBtn.className = "vz-chat-send";
592
+ sendBtn.innerHTML = "➤";
593
+ sendBtn.addEventListener("click", () => this.handleSend());
594
+ inputRow.appendChild(this.inputEl);
595
+ inputRow.appendChild(sendBtn);
596
+ this.panel.appendChild(inputRow);
597
+ shadowRoot.appendChild(this.panel);
598
+ }
599
+ /** Add a chat message to the panel */
600
+ addMessage(msg) {
601
+ this.messages.push(msg);
602
+ if (this.emptyEl.parentNode) {
603
+ this.emptyEl.remove();
604
+ }
605
+ this.renderMessage(msg);
606
+ this.scrollToBottom();
607
+ }
608
+ /** Toggle panel open/closed */
609
+ toggle() {
610
+ if (this.isOpen) {
611
+ this.close();
612
+ } else {
613
+ this.open();
614
+ }
615
+ }
616
+ /** Open the panel */
617
+ open() {
618
+ this.isOpen = true;
619
+ this.panel.classList.add("open");
620
+ this.inputEl.focus();
621
+ }
622
+ /** Close the panel */
623
+ close() {
624
+ this.isOpen = false;
625
+ this.panel.classList.remove("open");
626
+ }
627
+ /** Whether the panel is currently visible */
628
+ isVisible() {
629
+ return this.isOpen;
630
+ }
631
+ /** Get message count */
632
+ getMessageCount() {
633
+ return this.messages.length;
634
+ }
635
+ /** Clean up */
636
+ dispose() {
637
+ this.panel.remove();
638
+ this.styleEl.remove();
639
+ }
640
+ handleSend() {
641
+ const text = this.inputEl.value.trim();
642
+ if (!text) return;
643
+ this.inputEl.value = "";
644
+ this.onSend(text);
645
+ }
646
+ renderMessage(msg) {
647
+ const el = document.createElement("div");
648
+ el.className = "vz-chat-message";
649
+ const headerEl = document.createElement("div");
650
+ headerEl.className = "vz-chat-msg-header";
651
+ const nameEl = document.createElement("span");
652
+ nameEl.className = "vz-chat-msg-name";
653
+ nameEl.style.color = this.getColorForUser(msg.userId);
654
+ nameEl.textContent = msg.isLocal ? "You" : msg.displayName;
655
+ const timeEl = document.createElement("span");
656
+ timeEl.className = "vz-chat-msg-time";
657
+ timeEl.textContent = this.formatTime(msg.timestamp);
658
+ headerEl.appendChild(nameEl);
659
+ headerEl.appendChild(timeEl);
660
+ const textEl = document.createElement("div");
661
+ textEl.className = "vz-chat-msg-text";
662
+ textEl.textContent = msg.text;
663
+ el.appendChild(headerEl);
664
+ el.appendChild(textEl);
665
+ this.messagesEl.appendChild(el);
666
+ }
667
+ scrollToBottom() {
668
+ this.messagesEl.scrollTop = this.messagesEl.scrollHeight;
669
+ }
670
+ getColorForUser(userId) {
671
+ if (!this.colorMap.has(userId)) {
672
+ this.colorMap.set(userId, PEER_COLORS[this.colorIndex % PEER_COLORS.length]);
673
+ this.colorIndex++;
674
+ }
675
+ return this.colorMap.get(userId);
676
+ }
677
+ formatTime(ts) {
678
+ const d = new Date(ts);
679
+ const h = d.getHours().toString().padStart(2, "0");
680
+ const m = d.getMinutes().toString().padStart(2, "0");
681
+ return `${h}:${m}`;
682
+ }
683
+ }
684
+ class ChatButton {
685
+ container;
686
+ badge;
687
+ unreadCount = 0;
688
+ chatPanel;
689
+ constructor(chatPanel) {
690
+ this.chatPanel = chatPanel;
691
+ this.container = document.createElement("div");
692
+ this.container.style.position = "relative";
693
+ this.container.style.display = "inline-flex";
694
+ const btn = document.createElement("button");
695
+ btn.className = "vz-btn vz-chat-btn";
696
+ btn.innerHTML = ICON_CHAT;
697
+ btn.title = "Chat (T)";
698
+ btn.addEventListener("click", (e) => {
699
+ e.stopPropagation();
700
+ this.chatPanel.toggle();
701
+ if (this.chatPanel.isVisible()) {
702
+ this.resetUnread();
703
+ }
704
+ });
705
+ this.badge = document.createElement("span");
706
+ this.badge.className = "vz-chat-badge";
707
+ this.badge.style.display = "none";
708
+ this.container.appendChild(btn);
709
+ this.container.appendChild(this.badge);
710
+ }
711
+ /** Increment unread count and show badge */
712
+ incrementUnread() {
713
+ this.unreadCount++;
714
+ this.updateBadge();
715
+ }
716
+ /** Reset unread count and hide badge */
717
+ resetUnread() {
718
+ this.unreadCount = 0;
719
+ this.updateBadge();
720
+ }
721
+ /** Get the DOM element to insert into controls */
722
+ getElement() {
723
+ return this.container;
724
+ }
725
+ /** Clean up */
726
+ dispose() {
727
+ this.container.remove();
728
+ }
729
+ updateBadge() {
730
+ if (this.unreadCount > 0) {
731
+ this.badge.textContent = this.unreadCount > 99 ? "99+" : String(this.unreadCount);
732
+ this.badge.style.display = "flex";
733
+ } else {
734
+ this.badge.textContent = "";
735
+ this.badge.style.display = "none";
736
+ }
737
+ }
738
+ }
739
+ const STUN_SERVERS = [
740
+ { urls: "stun:stun.l.google.com:19302" },
741
+ { urls: "stun:stun1.l.google.com:19302" }
742
+ ];
743
+ class VoiceManager {
744
+ localStream = null;
745
+ peers = /* @__PURE__ */ new Map();
746
+ state = "inactive";
747
+ sendSignal;
748
+ constructor(sendSignal) {
749
+ this.sendSignal = sendSignal;
750
+ }
751
+ /** Get current voice state */
752
+ getState() {
753
+ return this.state;
754
+ }
755
+ /** Start voice — request microphone and begin connections */
756
+ async start() {
757
+ if (this.state !== "inactive") return;
758
+ try {
759
+ this.localStream = await navigator.mediaDevices.getUserMedia({ audio: true });
760
+ this.state = "active";
761
+ } catch (err) {
762
+ console.warn("[Vizor Voice] getUserMedia failed:", err);
763
+ throw err;
764
+ }
765
+ }
766
+ /** Toggle mute on/off */
767
+ toggleMute() {
768
+ if (!this.localStream) return;
769
+ if (this.state === "active") {
770
+ this.localStream.getAudioTracks().forEach((t) => t.enabled = false);
771
+ this.state = "muted";
772
+ } else if (this.state === "muted") {
773
+ this.localStream.getAudioTracks().forEach((t) => t.enabled = true);
774
+ this.state = "active";
775
+ }
776
+ }
777
+ /** Whether voice is currently active (active or muted) */
778
+ isActive() {
779
+ return this.state !== "inactive";
780
+ }
781
+ /** Whether mic is currently muted */
782
+ isMuted() {
783
+ return this.state === "muted";
784
+ }
785
+ /**
786
+ * Initiate a WebRTC connection to a peer (caller side).
787
+ * Creates an offer and sends it via signaling.
788
+ */
789
+ async connectToPeer(peerId) {
790
+ if (!this.localStream || this.peers.has(peerId)) return;
791
+ const pc = this.createPeerConnection(peerId);
792
+ this.localStream.getTracks().forEach((track) => {
793
+ pc.addTrack(track, this.localStream);
794
+ });
795
+ const offer = await pc.createOffer();
796
+ await pc.setLocalDescription(offer);
797
+ this.sendSignal(peerId, JSON.stringify(offer));
798
+ }
799
+ /**
800
+ * Handle an incoming voice signal (SDP offer/answer or ICE candidate).
801
+ */
802
+ async handleSignal(fromUserId, sdp, candidate) {
803
+ if (!this.localStream) return;
804
+ if (sdp) {
805
+ const desc = JSON.parse(sdp);
806
+ if (desc.type === "offer") {
807
+ const pc = this.createPeerConnection(fromUserId);
808
+ this.localStream.getTracks().forEach((track) => {
809
+ pc.addTrack(track, this.localStream);
810
+ });
811
+ await pc.setRemoteDescription(new RTCSessionDescription(desc));
812
+ const answer = await pc.createAnswer();
813
+ await pc.setLocalDescription(answer);
814
+ this.sendSignal(fromUserId, JSON.stringify(answer));
815
+ } else if (desc.type === "answer") {
816
+ const peerConn = this.peers.get(fromUserId);
817
+ if (peerConn) {
818
+ await peerConn.pc.setRemoteDescription(new RTCSessionDescription(desc));
819
+ }
820
+ }
821
+ } else if (candidate) {
822
+ const peerConn = this.peers.get(fromUserId);
823
+ if (peerConn) {
824
+ const iceCandidate = new RTCIceCandidate(JSON.parse(candidate));
825
+ await peerConn.pc.addIceCandidate(iceCandidate);
826
+ }
827
+ }
828
+ }
829
+ /** Remove a peer connection (when peer leaves) */
830
+ removePeer(peerId) {
831
+ const peerConn = this.peers.get(peerId);
832
+ if (!peerConn) return;
833
+ peerConn.pc.close();
834
+ peerConn.audioEl.srcObject = null;
835
+ peerConn.audioEl.remove();
836
+ this.peers.delete(peerId);
837
+ }
838
+ /** Stop voice — release microphone and close all connections */
839
+ stop() {
840
+ this.peers.forEach((peerConn, peerId) => {
841
+ peerConn.pc.close();
842
+ peerConn.audioEl.srcObject = null;
843
+ peerConn.audioEl.remove();
844
+ });
845
+ this.peers.clear();
846
+ if (this.localStream) {
847
+ this.localStream.getTracks().forEach((t) => t.stop());
848
+ this.localStream = null;
849
+ }
850
+ this.state = "inactive";
851
+ }
852
+ /** Get the number of active peer connections */
853
+ getPeerCount() {
854
+ return this.peers.size;
855
+ }
856
+ /** Clean up everything */
857
+ dispose() {
858
+ this.stop();
859
+ }
860
+ // --- Private ---
861
+ createPeerConnection(peerId) {
862
+ if (this.peers.has(peerId)) {
863
+ this.removePeer(peerId);
864
+ }
865
+ const pc = new RTCPeerConnection({ iceServers: STUN_SERVERS });
866
+ const audioEl = document.createElement("audio");
867
+ audioEl.autoplay = true;
868
+ pc.ontrack = (event) => {
869
+ audioEl.srcObject = event.streams[0] ?? new MediaStream([event.track]);
870
+ };
871
+ pc.onicecandidate = (event) => {
872
+ if (event.candidate) {
873
+ this.sendSignal(peerId, void 0, JSON.stringify(event.candidate));
874
+ }
875
+ };
876
+ pc.onconnectionstatechange = () => {
877
+ if (pc.connectionState === "failed" || pc.connectionState === "disconnected") {
878
+ this.removePeer(peerId);
879
+ }
880
+ };
881
+ this.peers.set(peerId, { pc, audioEl });
882
+ return pc;
883
+ }
884
+ }
885
+ class VoiceButton {
886
+ container;
887
+ btn;
888
+ voiceManager;
889
+ onVoiceStarted;
890
+ constructor(voiceManager, onVoiceStarted) {
891
+ this.voiceManager = voiceManager;
892
+ this.onVoiceStarted = onVoiceStarted;
893
+ this.container = document.createElement("div");
894
+ this.container.style.position = "relative";
895
+ this.container.style.display = "inline-flex";
896
+ this.btn = document.createElement("button");
897
+ this.btn.className = "vz-btn vz-voice-btn";
898
+ this.btn.innerHTML = ICON_MIC;
899
+ this.btn.title = "Voice Chat (V)";
900
+ this.btn.style.opacity = "0.5";
901
+ this.btn.addEventListener("click", (e) => {
902
+ e.stopPropagation();
903
+ this.handleClick();
904
+ });
905
+ this.container.appendChild(this.btn);
906
+ }
907
+ /** Get the DOM element to insert into controls */
908
+ getElement() {
909
+ return this.container;
910
+ }
911
+ /** Update button icon based on current voice state */
912
+ updateState() {
913
+ const state = this.voiceManager.getState();
914
+ switch (state) {
915
+ case "inactive":
916
+ this.btn.innerHTML = ICON_MIC;
917
+ this.btn.style.opacity = "0.5";
918
+ this.btn.title = "Start Voice Chat (V)";
919
+ break;
920
+ case "active":
921
+ this.btn.innerHTML = ICON_MIC;
922
+ this.btn.style.opacity = "1";
923
+ this.btn.title = "Mute (V)";
924
+ break;
925
+ case "muted":
926
+ this.btn.innerHTML = ICON_MIC_MUTED;
927
+ this.btn.style.opacity = "1";
928
+ this.btn.title = "Unmute (V)";
929
+ break;
930
+ }
931
+ }
932
+ /** Handle toggle via keyboard shortcut */
933
+ toggle() {
934
+ this.handleClick();
935
+ }
936
+ /** Clean up */
937
+ dispose() {
938
+ this.container.remove();
939
+ }
940
+ // --- Private ---
941
+ handleClick() {
942
+ if (!this.voiceManager.isActive()) {
943
+ this.voiceManager.start().then(() => {
944
+ this.updateState();
945
+ this.onVoiceStarted?.();
946
+ }).catch((err) => {
947
+ console.warn("[Vizor Voice] Failed to start:", err);
948
+ });
949
+ } else {
950
+ this.voiceManager.toggleMute();
951
+ this.updateState();
952
+ }
953
+ }
954
+ }
955
+ export {
956
+ ChatButton as C,
957
+ GazeCursorManager as G,
958
+ ICON_PLAY as I,
959
+ VoiceButton as V,
960
+ ChatPanel as a,
961
+ CollaborativeClient as b,
962
+ GazeSender as c,
963
+ VoiceManager as d,
964
+ ICON_PAUSE as e,
965
+ ICON_VOLUME_HIGH as f,
966
+ ICON_VOLUME_LOW as g,
967
+ ICON_VOLUME_MUTED as h,
968
+ ICON_FULLSCREEN as i,
969
+ ICON_FULLSCREEN_EXIT as j,
970
+ ICON_VR as k,
971
+ ICON_COMPASS as l,
972
+ ICON_SETTINGS as m,
973
+ ICON_LIVE_DOT as n,
974
+ ICON_CC as o,
975
+ ICON_PLAYLIST_PREV as p,
976
+ ICON_PLAYLIST_NEXT as q
977
+ };
978
+ //# sourceMappingURL=collab-BXPomrS0.js.map