@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,57 @@
1
+ import type { PlayerState } from '../core/player-state.js';
2
+ import { type VttCue } from './webvtt-parser.js';
3
+ /** A loaded track with its parsed cues */
4
+ export interface CaptionTrack {
5
+ srclang: string;
6
+ label: string;
7
+ cues: VttCue[];
8
+ isDefault: boolean;
9
+ }
10
+ /**
11
+ * Caption / subtitle renderer.
12
+ *
13
+ * Fetches `<track>` children via their `src` attribute, parses the
14
+ * WebVTT content, and renders the active cue as a HUD overlay
15
+ * positioned at the bottom of the player viewport.
16
+ *
17
+ * The overlay stays fixed relative to the viewport so that
18
+ * captions remain visible regardless of camera orientation in
19
+ * 360° video.
20
+ */
21
+ export declare class CaptionRenderer {
22
+ private tracks;
23
+ private activeTrackIndex;
24
+ private overlay;
25
+ private shadow;
26
+ private unsubscribes;
27
+ private lastCueId;
28
+ constructor(shadow: ShadowRoot, state: PlayerState);
29
+ /**
30
+ * Load all `<track>` children from the host element.
31
+ * Each track with a valid `src` is fetched and parsed.
32
+ */
33
+ loadTracks(hostElement: HTMLElement): Promise<void>;
34
+ /** Get all loaded tracks */
35
+ getTracks(): Readonly<CaptionTrack[]>;
36
+ /** Get the currently active track index (-1 = off) */
37
+ getActiveTrackIndex(): number;
38
+ /** Set the active caption track by index. -1 = off. */
39
+ setActiveTrack(index: number): void;
40
+ /** Toggle captions on/off. If off, activates the first available track. */
41
+ toggle(): void;
42
+ /** Whether captions are currently active */
43
+ isActive(): boolean;
44
+ /** Whether any tracks are loaded */
45
+ hasTracks(): boolean;
46
+ dispose(): void;
47
+ private fetchAndParse;
48
+ /** Find and render the active cue for the given time */
49
+ private renderCue;
50
+ /**
51
+ * Linear search for the active cue at the given time.
52
+ * WebVTT cue arrays are typically small (<200 entries),
53
+ * so linear scan is fine.
54
+ */
55
+ private findActiveCue;
56
+ }
57
+ //# sourceMappingURL=caption-renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"caption-renderer.d.ts","sourceRoot":"","sources":["../../src/captions/caption-renderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAe,KAAK,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAG9D,0CAA0C;AAC1C,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;GAUG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,gBAAgB,CAAM;IAC9B,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,YAAY,CAAyB;IAC7C,OAAO,CAAC,SAAS,CAAuB;gBAE5B,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW;IAiBlD;;;OAGG;IACG,UAAU,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BzD,4BAA4B;IAC5B,SAAS,IAAI,QAAQ,CAAC,YAAY,EAAE,CAAC;IAIrC,sDAAsD;IACtD,mBAAmB,IAAI,MAAM;IAI7B,uDAAuD;IACvD,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAWnC,2EAA2E;IAC3E,MAAM,IAAI,IAAI;IAad,4CAA4C;IAC5C,QAAQ,IAAI,OAAO;IAInB,oCAAoC;IACpC,SAAS,IAAI,OAAO;IAIpB,OAAO,IAAI,IAAI;YASD,aAAa;IA0B3B,wDAAwD;IACxD,OAAO,CAAC,SAAS;IA4BjB;;;;OAIG;IACH,OAAO,CAAC,aAAa;CAQtB"}
@@ -0,0 +1,3 @@
1
+ export { parseWebVTT, parseTimestamp, type VttCue } from './webvtt-parser.js';
2
+ export { CaptionRenderer, type CaptionTrack } from './caption-renderer.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/captions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,KAAK,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Minimal WebVTT parser.
3
+ *
4
+ * Handles:
5
+ * - UTF-8 BOM
6
+ * - Timestamp lines `HH:MM:SS.mmm --> HH:MM:SS.mmm`
7
+ * - Cue IDs (optional identifier line before timestamp)
8
+ * - NOTE blocks (skipped)
9
+ * - STYLE blocks (skipped)
10
+ * - REGION blocks (skipped)
11
+ * - Preserves <b>, <i>, <u> formatting tags; strips all others
12
+ */
13
+ export interface VttCue {
14
+ id: string;
15
+ startTime: number;
16
+ endTime: number;
17
+ text: string;
18
+ }
19
+ /**
20
+ * Parse a WebVTT timestamp string into seconds.
21
+ *
22
+ * Formats:
23
+ * HH:MM:SS.mmm
24
+ * MM:SS.mmm
25
+ */
26
+ export declare function parseTimestamp(ts: string): number;
27
+ /**
28
+ * Parse a WebVTT string into an array of cues.
29
+ */
30
+ export declare function parseWebVTT(input: string): VttCue[];
31
+ //# sourceMappingURL=webvtt-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webvtt-parser.d.ts","sourceRoot":"","sources":["../../src/captions/webvtt-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAUD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAoBjD;AAwBD;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAoHnD"}
@@ -0,0 +1,274 @@
1
+ import { p as purify } from "./annotations-C0ugfCn4.js";
2
+ const ALLOWED_TAGS = /* @__PURE__ */ new Set(["b", "i", "u", "br"]);
3
+ function stripBOM(str) {
4
+ return str.charCodeAt(0) === 65279 ? str.slice(1) : str;
5
+ }
6
+ function parseTimestamp(ts) {
7
+ const parts = ts.trim().split(":");
8
+ if (parts.length < 2 || parts.length > 3) return NaN;
9
+ let hours = 0;
10
+ let minutes;
11
+ let seconds;
12
+ if (parts.length === 3) {
13
+ hours = parseInt(parts[0], 10);
14
+ minutes = parseInt(parts[1], 10);
15
+ seconds = parseFloat(parts[2]);
16
+ } else {
17
+ minutes = parseInt(parts[0], 10);
18
+ seconds = parseFloat(parts[1]);
19
+ }
20
+ if (isNaN(hours) || isNaN(minutes) || isNaN(seconds)) return NaN;
21
+ return hours * 3600 + minutes * 60 + seconds;
22
+ }
23
+ function sanitizeText(raw) {
24
+ let text = raw.replace(/\n/g, "<br>");
25
+ text = text.replace(/<\/?([a-zA-Z][a-zA-Z0-9]*)\b[^>]*>/g, (match, tag) => {
26
+ const lower = tag.toLowerCase();
27
+ if (ALLOWED_TAGS.has(lower)) {
28
+ if (match.startsWith("</")) return `</${lower}>`;
29
+ if (lower === "br") return "<br>";
30
+ return `<${lower}>`;
31
+ }
32
+ return "";
33
+ });
34
+ return text.trim();
35
+ }
36
+ function parseWebVTT(input) {
37
+ const raw = stripBOM(input);
38
+ const lines = raw.replace(/\r\n/g, "\n").replace(/\r/g, "\n").split("\n");
39
+ const headerLine = lines[0]?.trim() ?? "";
40
+ if (!headerLine.startsWith("WEBVTT")) {
41
+ console.warn("[Vizor] Invalid WebVTT: missing WEBVTT header");
42
+ return [];
43
+ }
44
+ const cues = [];
45
+ const TIMESTAMP_RE = /^([\d:.]+)\s*-->\s*([\d:.]+)/;
46
+ let i = 1;
47
+ let cueIndex = 0;
48
+ while (i < lines.length) {
49
+ const line = lines[i];
50
+ if (line.trim() === "") {
51
+ i++;
52
+ continue;
53
+ }
54
+ if (line.trim().startsWith("NOTE")) {
55
+ i++;
56
+ while (i < lines.length && lines[i].trim() !== "") {
57
+ i++;
58
+ }
59
+ continue;
60
+ }
61
+ if (line.trim().startsWith("STYLE")) {
62
+ i++;
63
+ while (i < lines.length && lines[i].trim() !== "") {
64
+ i++;
65
+ }
66
+ continue;
67
+ }
68
+ if (line.trim().startsWith("REGION")) {
69
+ i++;
70
+ while (i < lines.length && lines[i].trim() !== "") {
71
+ i++;
72
+ }
73
+ continue;
74
+ }
75
+ let cueId;
76
+ const timestampMatch = line.match(TIMESTAMP_RE);
77
+ if (!timestampMatch) {
78
+ const nextLine = lines[i + 1] ?? "";
79
+ const nextMatch = nextLine.match(TIMESTAMP_RE);
80
+ if (nextMatch) {
81
+ cueId = line.trim();
82
+ i++;
83
+ const tsMatch = lines[i].match(TIMESTAMP_RE);
84
+ const startTime2 = parseTimestamp(tsMatch[1]);
85
+ const endTime2 = parseTimestamp(tsMatch[2]);
86
+ i++;
87
+ const textLines2 = [];
88
+ while (i < lines.length && lines[i].trim() !== "") {
89
+ textLines2.push(lines[i]);
90
+ i++;
91
+ }
92
+ if (!isNaN(startTime2) && !isNaN(endTime2) && textLines2.length > 0) {
93
+ cues.push({
94
+ id: cueId ?? String(cueIndex),
95
+ startTime: startTime2,
96
+ endTime: endTime2,
97
+ text: sanitizeText(textLines2.join("\n"))
98
+ });
99
+ cueIndex++;
100
+ }
101
+ } else {
102
+ i++;
103
+ }
104
+ continue;
105
+ }
106
+ const startTime = parseTimestamp(timestampMatch[1]);
107
+ const endTime = parseTimestamp(timestampMatch[2]);
108
+ i++;
109
+ const textLines = [];
110
+ while (i < lines.length && lines[i].trim() !== "") {
111
+ textLines.push(lines[i]);
112
+ i++;
113
+ }
114
+ if (!isNaN(startTime) && !isNaN(endTime) && textLines.length > 0) {
115
+ cues.push({
116
+ id: cueId ?? String(cueIndex),
117
+ startTime,
118
+ endTime,
119
+ text: sanitizeText(textLines.join("\n"))
120
+ });
121
+ cueIndex++;
122
+ }
123
+ }
124
+ return cues;
125
+ }
126
+ class CaptionRenderer {
127
+ tracks = [];
128
+ activeTrackIndex = -1;
129
+ overlay;
130
+ shadow;
131
+ unsubscribes = [];
132
+ lastCueId = null;
133
+ constructor(shadow, state) {
134
+ this.shadow = shadow;
135
+ this.overlay = document.createElement("div");
136
+ this.overlay.className = "vz-caption-overlay";
137
+ this.overlay.setAttribute("aria-live", "polite");
138
+ this.overlay.setAttribute("role", "status");
139
+ shadow.appendChild(this.overlay);
140
+ const unsub = state.subscribe("currentTime", (time) => {
141
+ this.renderCue(time);
142
+ });
143
+ this.unsubscribes.push(unsub);
144
+ }
145
+ /**
146
+ * Load all `<track>` children from the host element.
147
+ * Each track with a valid `src` is fetched and parsed.
148
+ */
149
+ async loadTracks(hostElement) {
150
+ const trackElements = hostElement.querySelectorAll("track");
151
+ if (trackElements.length === 0) return;
152
+ const promises = [];
153
+ trackElements.forEach((el) => {
154
+ const src = el.getAttribute("src");
155
+ if (!src) return;
156
+ const srclang = el.getAttribute("srclang") ?? "en";
157
+ const label = el.getAttribute("label") ?? srclang.toUpperCase();
158
+ const isDefault = el.hasAttribute("default");
159
+ promises.push(
160
+ this.fetchAndParse(src, srclang, label, isDefault)
161
+ );
162
+ });
163
+ await Promise.allSettled(promises);
164
+ if (this.tracks.length > 0) {
165
+ const defaultIndex = this.tracks.findIndex((t) => t.isDefault);
166
+ if (defaultIndex >= 0) {
167
+ this.activeTrackIndex = defaultIndex;
168
+ }
169
+ }
170
+ }
171
+ /** Get all loaded tracks */
172
+ getTracks() {
173
+ return this.tracks;
174
+ }
175
+ /** Get the currently active track index (-1 = off) */
176
+ getActiveTrackIndex() {
177
+ return this.activeTrackIndex;
178
+ }
179
+ /** Set the active caption track by index. -1 = off. */
180
+ setActiveTrack(index) {
181
+ if (index < -1 || index >= this.tracks.length) return;
182
+ this.activeTrackIndex = index;
183
+ this.lastCueId = null;
184
+ if (index === -1) {
185
+ this.overlay.innerHTML = "";
186
+ this.overlay.classList.remove("visible");
187
+ }
188
+ }
189
+ /** Toggle captions on/off. If off, activates the first available track. */
190
+ toggle() {
191
+ if (this.tracks.length === 0) return;
192
+ if (this.activeTrackIndex >= 0) {
193
+ this.setActiveTrack(-1);
194
+ } else {
195
+ const defaultIndex = this.tracks.findIndex((t) => t.isDefault);
196
+ this.setActiveTrack(defaultIndex >= 0 ? defaultIndex : 0);
197
+ }
198
+ }
199
+ /** Whether captions are currently active */
200
+ isActive() {
201
+ return this.activeTrackIndex >= 0;
202
+ }
203
+ /** Whether any tracks are loaded */
204
+ hasTracks() {
205
+ return this.tracks.length > 0;
206
+ }
207
+ dispose() {
208
+ for (const unsub of this.unsubscribes) unsub();
209
+ this.unsubscribes = [];
210
+ this.overlay.remove();
211
+ this.tracks = [];
212
+ }
213
+ // --- Private ---
214
+ async fetchAndParse(src, srclang, label, isDefault) {
215
+ try {
216
+ const response = await fetch(src);
217
+ if (!response.ok) {
218
+ console.warn(`[Vizor] Failed to fetch track: ${src} (${response.status})`);
219
+ return;
220
+ }
221
+ const text = await response.text();
222
+ const cues = parseWebVTT(text);
223
+ if (cues.length === 0) {
224
+ console.warn(`[Vizor] No cues found in track: ${src}`);
225
+ return;
226
+ }
227
+ this.tracks.push({ srclang, label, cues, isDefault });
228
+ } catch (err) {
229
+ console.warn(`[Vizor] Error loading track ${src}:`, err);
230
+ }
231
+ }
232
+ /** Find and render the active cue for the given time */
233
+ renderCue(currentTime) {
234
+ if (this.activeTrackIndex < 0 || this.activeTrackIndex >= this.tracks.length) {
235
+ return;
236
+ }
237
+ const track = this.tracks[this.activeTrackIndex];
238
+ const activeCue = this.findActiveCue(track.cues, currentTime);
239
+ if (!activeCue) {
240
+ if (this.lastCueId !== null) {
241
+ this.overlay.innerHTML = "";
242
+ this.overlay.classList.remove("visible");
243
+ this.lastCueId = null;
244
+ }
245
+ return;
246
+ }
247
+ if (activeCue.id !== this.lastCueId) {
248
+ this.overlay.innerHTML = purify.sanitize(activeCue.text, {
249
+ ALLOWED_TAGS: ["b", "i", "u", "span", "c", "ruby", "rt"],
250
+ ALLOWED_ATTR: ["class", "lang"]
251
+ });
252
+ this.overlay.classList.add("visible");
253
+ this.lastCueId = activeCue.id;
254
+ }
255
+ }
256
+ /**
257
+ * Linear search for the active cue at the given time.
258
+ * WebVTT cue arrays are typically small (<200 entries),
259
+ * so linear scan is fine.
260
+ */
261
+ findActiveCue(cues, time) {
262
+ for (const cue of cues) {
263
+ if (time >= cue.startTime && time < cue.endTime) {
264
+ return cue;
265
+ }
266
+ }
267
+ return null;
268
+ }
269
+ }
270
+ export {
271
+ CaptionRenderer as C,
272
+ parseWebVTT as p
273
+ };
274
+ //# sourceMappingURL=captions-BP0H2E03.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"captions-BP0H2E03.js","sources":["../src/captions/webvtt-parser.ts","../src/captions/caption-renderer.ts"],"sourcesContent":["/**\n * Minimal WebVTT parser.\n *\n * Handles:\n * - UTF-8 BOM\n * - Timestamp lines `HH:MM:SS.mmm --> HH:MM:SS.mmm`\n * - Cue IDs (optional identifier line before timestamp)\n * - NOTE blocks (skipped)\n * - STYLE blocks (skipped)\n * - REGION blocks (skipped)\n * - Preserves <b>, <i>, <u> formatting tags; strips all others\n */\n\nexport interface VttCue {\n id: string;\n startTime: number;\n endTime: number;\n text: string;\n}\n\n/** Set of tags allowed in cue text */\nconst ALLOWED_TAGS = new Set(['b', 'i', 'u', 'br']);\n\n/** Strip BOM if present */\nfunction stripBOM(str: string): string {\n return str.charCodeAt(0) === 0xfeff ? str.slice(1) : str;\n}\n\n/**\n * Parse a WebVTT timestamp string into seconds.\n *\n * Formats:\n * HH:MM:SS.mmm\n * MM:SS.mmm\n */\nexport function parseTimestamp(ts: string): number {\n const parts = ts.trim().split(':');\n if (parts.length < 2 || parts.length > 3) return NaN;\n\n let hours = 0;\n let minutes: number;\n let seconds: number;\n\n if (parts.length === 3) {\n hours = parseInt(parts[0]!, 10);\n minutes = parseInt(parts[1]!, 10);\n seconds = parseFloat(parts[2]!);\n } else {\n minutes = parseInt(parts[0]!, 10);\n seconds = parseFloat(parts[1]!);\n }\n\n if (isNaN(hours) || isNaN(minutes) || isNaN(seconds)) return NaN;\n\n return hours * 3600 + minutes * 60 + seconds;\n}\n\n/**\n * Sanitize cue text: keep only allowed HTML tags, convert `\\n` to `<br>`.\n */\nfunction sanitizeText(raw: string): string {\n // Replace newlines within a cue with <br>\n let text = raw.replace(/\\n/g, '<br>');\n\n // Strip disallowed tags but keep allowed ones\n text = text.replace(/<\\/?([a-zA-Z][a-zA-Z0-9]*)\\b[^>]*>/g, (match, tag: string) => {\n const lower = tag.toLowerCase();\n if (ALLOWED_TAGS.has(lower)) {\n // Return just the simple open/close tag (strip attributes)\n if (match.startsWith('</')) return `</${lower}>`;\n if (lower === 'br') return '<br>';\n return `<${lower}>`;\n }\n return '';\n });\n\n return text.trim();\n}\n\n/**\n * Parse a WebVTT string into an array of cues.\n */\nexport function parseWebVTT(input: string): VttCue[] {\n const raw = stripBOM(input);\n const lines = raw.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n').split('\\n');\n\n // Validate WEBVTT header\n const headerLine = lines[0]?.trim() ?? '';\n if (!headerLine.startsWith('WEBVTT')) {\n console.warn('[Vizor] Invalid WebVTT: missing WEBVTT header');\n return [];\n }\n\n const cues: VttCue[] = [];\n const TIMESTAMP_RE = /^([\\d:.]+)\\s*-->\\s*([\\d:.]+)/;\n\n let i = 1; // skip header line\n let cueIndex = 0;\n\n while (i < lines.length) {\n const line = lines[i]!;\n // Skip blank lines\n if (line.trim() === '') {\n i++;\n continue;\n }\n\n // Skip NOTE blocks\n if (line.trim().startsWith('NOTE')) {\n i++;\n while (i < lines.length && lines[i]!.trim() !== '') {\n i++;\n }\n continue;\n }\n\n // Skip STYLE blocks\n if (line.trim().startsWith('STYLE')) {\n i++;\n while (i < lines.length && lines[i]!.trim() !== '') {\n i++;\n }\n continue;\n }\n\n // Skip REGION blocks\n if (line.trim().startsWith('REGION')) {\n i++;\n while (i < lines.length && lines[i]!.trim() !== '') {\n i++;\n }\n continue;\n }\n\n // Try to parse a cue: might start with an ID line or directly with timestamp\n let cueId: string | undefined;\n const timestampMatch = line.match(TIMESTAMP_RE);\n\n if (!timestampMatch) {\n // This line might be a cue ID — check if next line is a timestamp\n const nextLine = lines[i + 1] ?? '';\n const nextMatch = nextLine.match(TIMESTAMP_RE);\n if (nextMatch) {\n cueId = line.trim();\n i++;\n // Now lines[i] is the timestamp line; parse it below\n const tsMatch = lines[i]!.match(TIMESTAMP_RE)!;\n const startTime = parseTimestamp(tsMatch[1]!);\n const endTime = parseTimestamp(tsMatch[2]!);\n i++;\n\n // Collect cue text lines\n const textLines: string[] = [];\n while (i < lines.length && lines[i]!.trim() !== '') {\n textLines.push(lines[i]!);\n i++;\n }\n\n if (!isNaN(startTime) && !isNaN(endTime) && textLines.length > 0) {\n cues.push({\n id: cueId ?? String(cueIndex),\n startTime,\n endTime,\n text: sanitizeText(textLines.join('\\n')),\n });\n cueIndex++;\n }\n } else {\n // Unknown line — skip\n i++;\n }\n continue;\n }\n\n // Direct timestamp line (no cue ID)\n const startTime = parseTimestamp(timestampMatch[1]!);\n const endTime = parseTimestamp(timestampMatch[2]!);\n i++;\n\n // Collect cue text lines\n const textLines: string[] = [];\n while (i < lines.length && lines[i]!.trim() !== '') {\n textLines.push(lines[i]!);\n i++;\n }\n\n if (!isNaN(startTime) && !isNaN(endTime) && textLines.length > 0) {\n cues.push({\n id: cueId ?? String(cueIndex),\n startTime,\n endTime,\n text: sanitizeText(textLines.join('\\n')),\n });\n cueIndex++;\n }\n }\n\n return cues;\n}\n","import type { PlayerState } from '../core/player-state.js';\nimport { parseWebVTT, type VttCue } from './webvtt-parser.js';\nimport DOMPurify from 'dompurify';\n\n/** A loaded track with its parsed cues */\nexport interface CaptionTrack {\n srclang: string;\n label: string;\n cues: VttCue[];\n isDefault: boolean;\n}\n\n/**\n * Caption / subtitle renderer.\n *\n * Fetches `<track>` children via their `src` attribute, parses the\n * WebVTT content, and renders the active cue as a HUD overlay\n * positioned at the bottom of the player viewport.\n *\n * The overlay stays fixed relative to the viewport so that\n * captions remain visible regardless of camera orientation in\n * 360° video.\n */\nexport class CaptionRenderer {\n private tracks: CaptionTrack[] = [];\n private activeTrackIndex = -1;\n private overlay: HTMLDivElement;\n private shadow: ShadowRoot;\n private unsubscribes: Array<() => void> = [];\n private lastCueId: string | null = null;\n\n constructor(shadow: ShadowRoot, state: PlayerState) {\n this.shadow = shadow;\n\n // Create the caption overlay element\n this.overlay = document.createElement('div');\n this.overlay.className = 'vz-caption-overlay';\n this.overlay.setAttribute('aria-live', 'polite');\n this.overlay.setAttribute('role', 'status');\n shadow.appendChild(this.overlay);\n\n // Subscribe to currentTime for cue updates\n const unsub = state.subscribe('currentTime', (time) => {\n this.renderCue(time);\n });\n this.unsubscribes.push(unsub);\n }\n\n /**\n * Load all `<track>` children from the host element.\n * Each track with a valid `src` is fetched and parsed.\n */\n async loadTracks(hostElement: HTMLElement): Promise<void> {\n const trackElements = hostElement.querySelectorAll('track');\n if (trackElements.length === 0) return;\n\n const promises: Promise<void>[] = [];\n\n trackElements.forEach((el) => {\n const src = el.getAttribute('src');\n if (!src) return;\n\n const srclang = el.getAttribute('srclang') ?? 'en';\n const label = el.getAttribute('label') ?? srclang.toUpperCase();\n const isDefault = el.hasAttribute('default');\n\n promises.push(\n this.fetchAndParse(src, srclang, label, isDefault),\n );\n });\n\n await Promise.allSettled(promises);\n\n // Activate the default track if one exists\n if (this.tracks.length > 0) {\n const defaultIndex = this.tracks.findIndex((t) => t.isDefault);\n if (defaultIndex >= 0) {\n this.activeTrackIndex = defaultIndex;\n }\n // If no default, leave captions off (activeTrackIndex = -1)\n }\n }\n\n /** Get all loaded tracks */\n getTracks(): Readonly<CaptionTrack[]> {\n return this.tracks;\n }\n\n /** Get the currently active track index (-1 = off) */\n getActiveTrackIndex(): number {\n return this.activeTrackIndex;\n }\n\n /** Set the active caption track by index. -1 = off. */\n setActiveTrack(index: number): void {\n if (index < -1 || index >= this.tracks.length) return;\n this.activeTrackIndex = index;\n this.lastCueId = null;\n\n if (index === -1) {\n this.overlay.innerHTML = '';\n this.overlay.classList.remove('visible');\n }\n }\n\n /** Toggle captions on/off. If off, activates the first available track. */\n toggle(): void {\n if (this.tracks.length === 0) return;\n\n if (this.activeTrackIndex >= 0) {\n // Turn off\n this.setActiveTrack(-1);\n } else {\n // Turn on — prefer default track, fallback to first\n const defaultIndex = this.tracks.findIndex((t) => t.isDefault);\n this.setActiveTrack(defaultIndex >= 0 ? defaultIndex : 0);\n }\n }\n\n /** Whether captions are currently active */\n isActive(): boolean {\n return this.activeTrackIndex >= 0;\n }\n\n /** Whether any tracks are loaded */\n hasTracks(): boolean {\n return this.tracks.length > 0;\n }\n\n dispose(): void {\n for (const unsub of this.unsubscribes) unsub();\n this.unsubscribes = [];\n this.overlay.remove();\n this.tracks = [];\n }\n\n // --- Private ---\n\n private async fetchAndParse(\n src: string,\n srclang: string,\n label: string,\n isDefault: boolean,\n ): Promise<void> {\n try {\n const response = await fetch(src);\n if (!response.ok) {\n console.warn(`[Vizor] Failed to fetch track: ${src} (${response.status})`);\n return;\n }\n const text = await response.text();\n const cues = parseWebVTT(text);\n\n if (cues.length === 0) {\n console.warn(`[Vizor] No cues found in track: ${src}`);\n return;\n }\n\n this.tracks.push({ srclang, label, cues, isDefault });\n } catch (err) {\n console.warn(`[Vizor] Error loading track ${src}:`, err);\n }\n }\n\n /** Find and render the active cue for the given time */\n private renderCue(currentTime: number): void {\n if (this.activeTrackIndex < 0 || this.activeTrackIndex >= this.tracks.length) {\n return;\n }\n\n const track = this.tracks[this.activeTrackIndex]!;\n const activeCue = this.findActiveCue(track.cues, currentTime);\n\n if (!activeCue) {\n if (this.lastCueId !== null) {\n this.overlay.innerHTML = '';\n this.overlay.classList.remove('visible');\n this.lastCueId = null;\n }\n return;\n }\n\n // Only update DOM if cue changed\n if (activeCue.id !== this.lastCueId) {\n this.overlay.innerHTML = DOMPurify.sanitize(activeCue.text, {\n ALLOWED_TAGS: ['b', 'i', 'u', 'span', 'c', 'ruby', 'rt'],\n ALLOWED_ATTR: ['class', 'lang'],\n });\n this.overlay.classList.add('visible');\n this.lastCueId = activeCue.id;\n }\n }\n\n /**\n * Linear search for the active cue at the given time.\n * WebVTT cue arrays are typically small (<200 entries),\n * so linear scan is fine.\n */\n private findActiveCue(cues: VttCue[], time: number): VttCue | null {\n for (const cue of cues) {\n if (time >= cue.startTime && time < cue.endTime) {\n return cue;\n }\n }\n return null;\n }\n}\n"],"names":["startTime","endTime","textLines","DOMPurify"],"mappings":"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"}