@nulib/clover 0.0.0-stage → 4.0.0-beta.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 (410) hide show
  1. package/LICENSE +9 -0
  2. package/README.md +120 -2
  3. package/dist/components/Annotations/Annotations.mjs +674 -0
  4. package/dist/components/Annotations/EntryBodies.mjs +52 -0
  5. package/dist/components/Annotations/languages.mjs +43 -0
  6. package/dist/components/Body/Body.mjs +51 -0
  7. package/dist/components/Body/BodyAlert.mjs +25 -0
  8. package/dist/components/Body/Caption.mjs +90 -0
  9. package/dist/components/Body/CaptionDetails.mjs +50 -0
  10. package/dist/components/Body/Pending.mjs +9 -0
  11. package/dist/components/Body/glyphs.mjs +66 -0
  12. package/dist/components/Body/renderers.mjs +30 -0
  13. package/dist/components/Body/useControlsVisibility.mjs +204 -0
  14. package/dist/components/Body/useNearViewport.mjs +27 -0
  15. package/dist/components/Canvas/AnnotationMenu.mjs +128 -0
  16. package/dist/components/Canvas/AnnotationState.mjs +338 -0
  17. package/dist/components/Canvas/Annotations.mjs +497 -0
  18. package/dist/components/Canvas/CanvasView.mjs +669 -0
  19. package/dist/components/Canvas/ChoiceMenu.mjs +77 -0
  20. package/dist/components/Canvas/Connected.mjs +228 -0
  21. package/dist/components/Canvas/ControlMenu.mjs +67 -0
  22. package/dist/components/Canvas/Controls.mjs +233 -0
  23. package/dist/components/Canvas/FrameAnimation.mjs +344 -0
  24. package/dist/components/Canvas/LoadedCanvas.mjs +177 -0
  25. package/dist/components/Canvas/Placeholder.mjs +105 -0
  26. package/dist/components/Canvas/fromManifest.mjs +44 -0
  27. package/dist/components/Canvas/index.mjs +19 -0
  28. package/dist/components/Canvas/layout.mjs +369 -0
  29. package/dist/components/Canvas/media/MediaBody.mjs +285 -0
  30. package/dist/components/Canvas/media/Player.mjs +193 -0
  31. package/dist/components/Canvas/media/Transport.mjs +511 -0
  32. package/dist/components/Canvas/media/TransportButton.mjs +39 -0
  33. package/dist/components/Canvas/media/useBarHeight.mjs +28 -0
  34. package/dist/components/Canvas/media/useCaptionTracks.mjs +131 -0
  35. package/dist/components/Canvas/media/useMediaController.mjs +77 -0
  36. package/dist/components/Canvas/media/useMediaElement.mjs +100 -0
  37. package/dist/components/Canvas/panClearOfControls.mjs +92 -0
  38. package/dist/components/Canvas/rendererSurface.mjs +6 -0
  39. package/dist/components/Canvas/surface.mjs +5 -0
  40. package/dist/components/Canvas/track.mjs +43 -0
  41. package/dist/components/Canvas/useSvgReader.mjs +23 -0
  42. package/dist/components/Collection/Collection.mjs +76 -0
  43. package/dist/components/CollectionSelect/CollectionSelect.mjs +114 -0
  44. package/dist/components/Contents/Contents.mjs +120 -0
  45. package/dist/components/Download/Download.mjs +105 -0
  46. package/dist/components/Items/Item.mjs +184 -0
  47. package/dist/components/Items/Items.mjs +455 -0
  48. package/dist/components/Items/Pager.mjs +190 -0
  49. package/dist/components/Items/StandaloneItems.mjs +80 -0
  50. package/dist/components/Items/clamped.mjs +90 -0
  51. package/dist/components/Label/Label.mjs +39 -0
  52. package/dist/components/Map/LoadedMap.mjs +26 -0
  53. package/dist/components/Map/Map.mjs +38 -0
  54. package/dist/components/Map/MapView.mjs +538 -0
  55. package/dist/components/Map/basemap.mjs +50 -0
  56. package/dist/components/Map/overlayImage.mjs +17 -0
  57. package/dist/components/Panel/About.mjs +143 -0
  58. package/dist/components/Panel/Panel.mjs +259 -0
  59. package/dist/components/Panel/PanelToggle.mjs +43 -0
  60. package/dist/components/Panel/PartOfManifest.mjs +52 -0
  61. package/dist/components/Primitives/Primitives.mjs +263 -0
  62. package/dist/components/Primitives/resource.mjs +11 -0
  63. package/dist/components/Provider/Provider.mjs +174 -0
  64. package/dist/components/Root/Announcer.mjs +58 -0
  65. package/dist/components/Root/Root.mjs +29 -0
  66. package/dist/components/Root/useRootState.mjs +188 -0
  67. package/dist/components/Scene/Connected.mjs +48 -0
  68. package/dist/components/Scene/Loaded.mjs +56 -0
  69. package/dist/components/Scene/RotatePad.mjs +204 -0
  70. package/dist/components/Scene/Scene.mjs +20 -0
  71. package/dist/components/Scene/SceneView.mjs +539 -0
  72. package/dist/components/Scene/cloverEngine.mjs +105 -0
  73. package/dist/components/Scene/engine.mjs +141 -0
  74. package/dist/components/Scene/engines.mjs +23 -0
  75. package/dist/components/Scene/gestures.mjs +74 -0
  76. package/dist/components/Scene/models.mjs +78 -0
  77. package/dist/components/Scene/orbit.mjs +60 -0
  78. package/dist/components/Search/Search.mjs +246 -0
  79. package/dist/components/Split/Split.mjs +203 -0
  80. package/dist/components/Split/splitting.mjs +203 -0
  81. package/dist/components/Status/Status.mjs +47 -0
  82. package/dist/components/Timeline/Connected.mjs +25 -0
  83. package/dist/components/Timeline/Timeline.mjs +40 -0
  84. package/dist/components/Timeline/playerSurface.mjs +84 -0
  85. package/dist/components/Transcript/Transcript.mjs +377 -0
  86. package/dist/components/Viewer/Viewer.mjs +19 -0
  87. package/dist/core/annotation-bodies.mjs +29 -0
  88. package/dist/core/annotation-collection.mjs +55 -0
  89. package/dist/core/annotation-name.mjs +31 -0
  90. package/dist/core/annotation-sets.mjs +155 -0
  91. package/dist/core/annotations-content.mjs +27 -0
  92. package/dist/core/annotations.mjs +73 -0
  93. package/dist/core/clover.mjs +393 -0
  94. package/dist/core/content-state-reader.mjs +82 -0
  95. package/dist/core/content-state.mjs +43 -0
  96. package/dist/core/direction.mjs +12 -0
  97. package/dist/core/geo-detect.mjs +30 -0
  98. package/dist/core/geo.mjs +283 -0
  99. package/dist/core/items.mjs +74 -0
  100. package/dist/core/keep-fragments.mjs +40 -0
  101. package/dist/core/link.mjs +28 -0
  102. package/dist/core/load.mjs +176 -0
  103. package/dist/core/map-config.mjs +12 -0
  104. package/dist/core/markdown.mjs +139 -0
  105. package/dist/core/pages.mjs +51 -0
  106. package/dist/core/painted-bodies.mjs +20 -0
  107. package/dist/core/painting.mjs +17 -0
  108. package/dist/core/presentation.mjs +27 -0
  109. package/dist/core/ranges.mjs +133 -0
  110. package/dist/core/region.mjs +32 -0
  111. package/dist/core/request.mjs +40 -0
  112. package/dist/core/sanitize.mjs +72 -0
  113. package/dist/core/search-service.mjs +22 -0
  114. package/dist/core/search.mjs +154 -0
  115. package/dist/core/selectors.mjs +94 -0
  116. package/dist/core/sequence.mjs +70 -0
  117. package/dist/core/show-link.mjs +16 -0
  118. package/dist/core/store.mjs +40 -0
  119. package/dist/core/svg-shape.mjs +183 -0
  120. package/dist/core/text.mjs +36 -0
  121. package/dist/core/thumbnail.mjs +55 -0
  122. package/dist/core/value.mjs +39 -0
  123. package/dist/core/vtt.mjs +111 -0
  124. package/dist/hooks/useFullscreen.mjs +21 -0
  125. package/dist/hooks/useFullscreenSupported.mjs +11 -0
  126. package/dist/hooks/useLoaded.mjs +27 -0
  127. package/dist/hooks/useWithinFullscreen.mjs +24 -0
  128. package/dist/i18n/config.mjs +170 -0
  129. package/dist/i18n/hostLanguage.mjs +6 -0
  130. package/dist/i18n/locales/en.json.mjs +5 -0
  131. package/dist/i18n/locales/es.json.mjs +5 -0
  132. package/dist/i18n/locales/fi.json.mjs +5 -0
  133. package/dist/i18n/locales/fr.json.mjs +5 -0
  134. package/dist/i18n/locales/index.mjs +13 -0
  135. package/dist/i18n/locales/nb.json.mjs +5 -0
  136. package/dist/i18n/locales/nn.json.mjs +5 -0
  137. package/dist/i18n/locales/no.json.mjs +5 -0
  138. package/dist/i18n/locales/pt.json.mjs +5 -0
  139. package/dist/i18n/reader.mjs +13 -0
  140. package/dist/i18n/useCloverTranslation.mjs +28 -0
  141. package/dist/index.d.mts +2204 -0
  142. package/dist/index.mjs +133 -0
  143. package/dist/lib/asArray.mjs +5 -0
  144. package/dist/lib/classnames.mjs +5 -0
  145. package/dist/lib/fullscreen.mjs +65 -0
  146. package/dist/lib/gltf/bounds.mjs +44 -0
  147. package/dist/lib/gltf/load.mjs +156 -0
  148. package/dist/lib/gltf/mat4.mjs +150 -0
  149. package/dist/lib/gltf/renderer.mjs +342 -0
  150. package/dist/lib/gltf/shaders.mjs +192 -0
  151. package/dist/lib/hls.mjs +6 -0
  152. package/dist/lib/pointer.mjs +38 -0
  153. package/dist/lib/renderer/CanvasRenderer.mjs +857 -0
  154. package/dist/lib/renderer/backends/backend.mjs +21 -0
  155. package/dist/lib/renderer/backends/canvas2d/Canvas2DBackend.mjs +91 -0
  156. package/dist/lib/renderer/backends/contexts.mjs +27 -0
  157. package/dist/lib/renderer/backends/dom/DomLayers.mjs +91 -0
  158. package/dist/lib/renderer/backends/webgl2/WebGL2Backend.mjs +248 -0
  159. package/dist/lib/renderer/backends/webgl2/shaders.mjs +28 -0
  160. package/dist/lib/renderer/camera/Camera.mjs +64 -0
  161. package/dist/lib/renderer/camera/CameraAnimator.mjs +90 -0
  162. package/dist/lib/renderer/input/GestureController.mjs +252 -0
  163. package/dist/lib/renderer/io/TileCache.mjs +207 -0
  164. package/dist/lib/renderer/io/decode.mjs +156 -0
  165. package/dist/lib/renderer/loop/FrameLoop.mjs +50 -0
  166. package/dist/lib/renderer/math/affine.mjs +68 -0
  167. package/dist/lib/renderer/math/rect.mjs +45 -0
  168. package/dist/lib/renderer/overlays/Navigator.mjs +141 -0
  169. package/dist/lib/renderer/overlays/OverlayLayer.mjs +94 -0
  170. package/dist/lib/renderer/scene/planFrame.mjs +168 -0
  171. package/dist/lib/renderer/scene/regions.mjs +30 -0
  172. package/dist/lib/renderer/scene/sceneItem.mjs +114 -0
  173. package/dist/lib/renderer/scene/uploadBudget.mjs +30 -0
  174. package/dist/lib/renderer/sources/imageService.mjs +160 -0
  175. package/dist/lib/renderer/sources/sizedImage.mjs +38 -0
  176. package/dist/lib/renderer/sources/tilePyramid.mjs +172 -0
  177. package/dist/lib/time.mjs +21 -0
  178. package/dist/map/index.d.mts +184 -0
  179. package/dist/map/index.mjs +16 -0
  180. package/dist/react/context.mjs +46 -0
  181. package/dist/react/hooks.mjs +69 -0
  182. package/dist/react/language.mjs +30 -0
  183. package/dist/styles.css +1 -0
  184. package/dist/templates/default/Default.mjs +229 -0
  185. package/dist/templates/document/Document.mjs +286 -0
  186. package/dist/templates/document/DocumentPanel.mjs +9 -0
  187. package/dist/templates/document/Sheets.mjs +360 -0
  188. package/dist/templates/gallery/Gallery.mjs +62 -0
  189. package/dist/templates/index.d.mts +273 -0
  190. package/dist/templates/index.mjs +11 -0
  191. package/dist/templates/shared/Lightbox.mjs +111 -0
  192. package/dist/templates/shared/LightboxBody.mjs +9 -0
  193. package/dist/templates/shared/dragToClose.mjs +129 -0
  194. package/dist/templates/shared/useDragToClose.mjs +35 -0
  195. package/dist/templates/shared/useDrawer.mjs +113 -0
  196. package/dist/templates/shared/useFollowFocus.mjs +24 -0
  197. package/dist/templates/shared/useSlide.mjs +52 -0
  198. package/dist/templates/shared/useSpine.mjs +26 -0
  199. package/dist/templates.css +1 -0
  200. package/dist/three/index.d.mts +6 -0
  201. package/dist/three/index.mjs +8 -0
  202. package/dist/ui/Button.mjs +53 -0
  203. package/dist/ui/ControlCluster.mjs +87 -0
  204. package/dist/ui/Cue.mjs +13 -0
  205. package/dist/ui/ErrorBoundary.mjs +26 -0
  206. package/dist/ui/ExitFullscreen.mjs +46 -0
  207. package/dist/ui/FieldPill.mjs +153 -0
  208. package/dist/ui/HideToggle.mjs +57 -0
  209. package/dist/ui/Loading.mjs +20 -0
  210. package/dist/ui/Markup.mjs +95 -0
  211. package/dist/ui/ReadMore.mjs +84 -0
  212. package/dist/ui/Sections.mjs +448 -0
  213. package/dist/ui/Steps.mjs +84 -0
  214. package/dist/ui/Tip.mjs +196 -0
  215. package/dist/ui/bringIntoView.mjs +27 -0
  216. package/dist/ui/controlGlyphs.mjs +120 -0
  217. package/dist/ui/heading.mjs +19 -0
  218. package/dist/ui/languageCode.mjs +8 -0
  219. package/dist/ui/mediaIcons.mjs +104 -0
  220. package/dist/ui/useClusterReach.mjs +50 -0
  221. package/dist/ui/useContainerName.mjs +19 -0
  222. package/dist/ui/useOneOpen.mjs +22 -0
  223. package/dist/ui/useRovingFocus.mjs +64 -0
  224. package/dist/ui/useScrollTrack.mjs +150 -0
  225. package/dist/ui/useUniqueId.mjs +10 -0
  226. package/dist/ui/visuallyHidden.mjs +15 -0
  227. package/dist/web-components/About-uKa1wfDr.mjs +1 -0
  228. package/dist/web-components/AnnotationMenu-BGIYRXW6.mjs +1 -0
  229. package/dist/web-components/AnnotationState-D2UIgIEC.mjs +1 -0
  230. package/dist/web-components/Annotations-BhwAv3ah.mjs +1 -0
  231. package/dist/web-components/Annotations-C_tBJHo3.mjs +2 -0
  232. package/dist/web-components/Body-DMEERFuB.mjs +1 -0
  233. package/dist/web-components/BodyAlert-BP8voSLv.mjs +1 -0
  234. package/dist/web-components/Button-Cl02BFDd.mjs +1 -0
  235. package/dist/web-components/Camera-Dw51CAfF.mjs +1 -0
  236. package/dist/web-components/Canvas2DBackend-RRN2bEkc.mjs +1 -0
  237. package/dist/web-components/CanvasView-B8lMMSou.mjs +1 -0
  238. package/dist/web-components/CaptionDetails-KLMDv-ec.mjs +1 -0
  239. package/dist/web-components/ChoiceMenu-CXrVOmJl.mjs +1 -0
  240. package/dist/web-components/Collection-DL4Ui4hF.mjs +1 -0
  241. package/dist/web-components/CollectionSelect-DL-bbpwJ.mjs +1 -0
  242. package/dist/web-components/Connected-B0S1HXQb.mjs +1 -0
  243. package/dist/web-components/Connected-BcjRA5si.mjs +1 -0
  244. package/dist/web-components/Connected-Q7iizBb8.mjs +1 -0
  245. package/dist/web-components/Contents-ZC8TiGaW.mjs +1 -0
  246. package/dist/web-components/ControlMenu-DIoU797-.mjs +1 -0
  247. package/dist/web-components/Cue-CJxnDMEy.mjs +1 -0
  248. package/dist/web-components/Document-DHBRAFEK.mjs +1 -0
  249. package/dist/web-components/DocumentPanel-CqvE2pu9.mjs +1 -0
  250. package/dist/web-components/DomLayers-BsR2AOy-.mjs +1 -0
  251. package/dist/web-components/Download-DBksL1C0.mjs +1 -0
  252. package/dist/web-components/EntryBodies-VwEkTVrw.mjs +1 -0
  253. package/dist/web-components/ErrorBoundary-Cy9PGoZv.mjs +1 -0
  254. package/dist/web-components/FieldPill-DCJBz6Vj.mjs +1 -0
  255. package/dist/web-components/FrameAnimation-DRbmgGpF.mjs +1 -0
  256. package/dist/web-components/Gallery-BM7-VJkB.mjs +1 -0
  257. package/dist/web-components/HideToggle-BdYgG7us.mjs +1 -0
  258. package/dist/web-components/Items-_1Jz3FMs.mjs +1 -0
  259. package/dist/web-components/Label-CAiJ49eA.mjs +1 -0
  260. package/dist/web-components/LightboxBody-DyhUZiDf.mjs +1 -0
  261. package/dist/web-components/Loaded-wQurAeJz.mjs +1 -0
  262. package/dist/web-components/LoadedCanvas-DWz5IK5m.mjs +1 -0
  263. package/dist/web-components/LoadedMap-DIeW313M.mjs +1 -0
  264. package/dist/web-components/Loading-BmA--pzr.mjs +1 -0
  265. package/dist/web-components/Map-DzVGblIS.mjs +1 -0
  266. package/dist/web-components/MapView-BJaN7VBI.mjs +1 -0
  267. package/dist/web-components/Markup-D91DbxLk.mjs +2 -0
  268. package/dist/web-components/MediaBody-BYcVPo2X.mjs +1 -0
  269. package/dist/web-components/MediaBody-FEzH8VVw.mjs +1 -0
  270. package/dist/web-components/Navigator-CIJFA3q1.mjs +1 -0
  271. package/dist/web-components/Pager-BGwCurxE.mjs +1 -0
  272. package/dist/web-components/Panel-B-GXOkzF.mjs +1 -0
  273. package/dist/web-components/PanelToggle-BYjV2t1j.mjs +1 -0
  274. package/dist/web-components/PartOfManifest-ClbGepVM.mjs +1 -0
  275. package/dist/web-components/Pending-BspZajh5.mjs +1 -0
  276. package/dist/web-components/Primitives-CTh59wvs.mjs +1 -0
  277. package/dist/web-components/Provider-C6rIiDXH.mjs +1 -0
  278. package/dist/web-components/ReadMore-BJ2i-0uN.mjs +1 -0
  279. package/dist/web-components/Root-DkkYDtur.mjs +1 -0
  280. package/dist/web-components/Scene-B_PU_TiX.mjs +1 -0
  281. package/dist/web-components/SceneView-qcW_sT3j.mjs +1 -0
  282. package/dist/web-components/Search-UOneIUcP.mjs +1 -0
  283. package/dist/web-components/Sections-we9U9fXq.mjs +2 -0
  284. package/dist/web-components/StandaloneItems-DU8oCFc_.mjs +1 -0
  285. package/dist/web-components/Status-Cs5ZvFvL.mjs +1 -0
  286. package/dist/web-components/Timeline-WtYZ1bIJ.mjs +1 -0
  287. package/dist/web-components/Tip-C8J3qsIK.mjs +1 -0
  288. package/dist/web-components/Transcript-CRL2zToL.mjs +1 -0
  289. package/dist/web-components/annotation-collection-ZPyvpLFc.mjs +1 -0
  290. package/dist/web-components/annotations-content-BZChKhJZ.mjs +1 -0
  291. package/dist/web-components/assets/maplibre-gl-worker-kTz9OPxr.js +13831 -0
  292. package/dist/web-components/body-UntgrmoV.mjs +1 -0
  293. package/dist/web-components/bringIntoView-CQH5ZgMM.mjs +1 -0
  294. package/dist/web-components/canvas-d_U4v_mh.mjs +1 -0
  295. package/dist/web-components/classnames-DukgfdpI.mjs +1 -0
  296. package/dist/web-components/cloverEngine-Dbv-26NP.mjs +164 -0
  297. package/dist/web-components/content-state-reader-DjdKWjit.mjs +1 -0
  298. package/dist/web-components/contexts-ByL3eA_T.mjs +1 -0
  299. package/dist/web-components/controls-qRYf2jO2.mjs +1 -0
  300. package/dist/web-components/custom-elements.json +2739 -0
  301. package/dist/web-components/dragToClose-C-Pf1IeO.mjs +1 -0
  302. package/dist/web-components/engine-D8JLgzqq.mjs +4228 -0
  303. package/dist/web-components/engines-BwVb9R_A.mjs +1 -0
  304. package/dist/web-components/es-BwMkoRod.mjs +1 -0
  305. package/dist/web-components/fi-gPFOn9RK.mjs +1 -0
  306. package/dist/web-components/fr-DUHmgdJo.mjs +1 -0
  307. package/dist/web-components/fromManifest-UrMJgktp.mjs +1 -0
  308. package/dist/web-components/glyphs-BoX0a88P.mjs +1 -0
  309. package/dist/web-components/heading-Cjt0f-Eu.mjs +1 -0
  310. package/dist/web-components/hls-CdKrthkC.mjs +40 -0
  311. package/dist/web-components/hooks-Dp8pjU8l.mjs +1 -0
  312. package/dist/web-components/imageService-C3yg9DxB.mjs +1 -0
  313. package/dist/web-components/index-DWxMuwDL.mjs +1 -0
  314. package/dist/web-components/index.d.mts +604 -0
  315. package/dist/web-components/index.mjs +1 -0
  316. package/dist/web-components/index.umd.js +18 -0
  317. package/dist/web-components/items--Tu7ZM3L.mjs +1 -0
  318. package/dist/web-components/items-W2vrwArM.mjs +1 -0
  319. package/dist/web-components/keep-fragments-B5nlv2ck.mjs +1 -0
  320. package/dist/web-components/label-CYQ7tVl6.mjs +1 -0
  321. package/dist/web-components/languageCode-cCpiU0b0.mjs +1 -0
  322. package/dist/web-components/layout-KL0V-iJu.mjs +1 -0
  323. package/dist/web-components/link-DRRTY4lY.mjs +1 -0
  324. package/dist/web-components/logo-CnQUCB3Y.mjs +1 -0
  325. package/dist/web-components/maplibre-gl-CQ4OueXY.mjs +823 -0
  326. package/dist/web-components/markdown-CCYJwzFn.mjs +5 -0
  327. package/dist/web-components/models-BP2qp9nT.mjs +1 -0
  328. package/dist/web-components/nb-BSvnQ6jd.mjs +1 -0
  329. package/dist/web-components/nn-Dg2_HdZu.mjs +1 -0
  330. package/dist/web-components/no-BSvnQ6jd.mjs +1 -0
  331. package/dist/web-components/nodes-Bf-Fb7e5.mjs +1 -0
  332. package/dist/web-components/overlayImage-DdPs2EGY.mjs +1 -0
  333. package/dist/web-components/panClearOfControls-ac9uf-Qs.mjs +1 -0
  334. package/dist/web-components/panel-CiqEFDzv.mjs +1 -0
  335. package/dist/web-components/part-CUBY90_b.mjs +1 -0
  336. package/dist/web-components/playerSurface-i2TJz-F4.mjs +1 -0
  337. package/dist/web-components/provider-LUmAQSoP.mjs +1 -0
  338. package/dist/web-components/pt-B3J80JgO.mjs +1 -0
  339. package/dist/web-components/read-more-BaaO77el.mjs +1 -0
  340. package/dist/web-components/rendererSurface-DAvatpMF.mjs +22 -0
  341. package/dist/web-components/renderers-Bg4QqawN.mjs +1 -0
  342. package/dist/web-components/resource-DzIvB_4m.mjs +1 -0
  343. package/dist/web-components/sanitize-Dc7nOsgO.mjs +3 -0
  344. package/dist/web-components/search-DgcgsI3I.mjs +1 -0
  345. package/dist/web-components/shared-J3w3gnXD.mjs +1 -0
  346. package/dist/web-components/show-link-DWRRXSBy.mjs +1 -0
  347. package/dist/web-components/sizedImage-DfjlV2-i.mjs +1 -0
  348. package/dist/web-components/split-m-_XivaW.mjs +1 -0
  349. package/dist/web-components/splitting-BnQUxxgH.mjs +1 -0
  350. package/dist/web-components/status-DDS7jLNd.mjs +1 -0
  351. package/dist/web-components/styles-Ypl9KrSK.mjs +1 -0
  352. package/dist/web-components/svg-shape-DLY3g7oq.mjs +1 -0
  353. package/dist/web-components/text-BTAkxEfQ.mjs +5 -0
  354. package/dist/web-components/three.mjs +1 -0
  355. package/dist/web-components/thumbnail-BZvLSwWW.mjs +1 -0
  356. package/dist/web-components/time-B9GZoYcm.mjs +1 -0
  357. package/dist/web-components/tip-BXByhOJ9.mjs +1 -0
  358. package/dist/web-components/toggle-AS72kq6v.mjs +1 -0
  359. package/dist/web-components/upgrader-XNxI-5jo.mjs +1 -0
  360. package/dist/web-components/useContainerName-DCbE5JXi.mjs +1 -0
  361. package/dist/web-components/useNearViewport-CyoK3l8W.mjs +1 -0
  362. package/dist/web-components/useScrollTrack-dLFWnT8N.mjs +1 -0
  363. package/dist/web-components/viewer/AnnotationMenu-Dd4tnzNV.mjs +1 -0
  364. package/dist/web-components/viewer/AnnotationState-DZaSy5lH.mjs +1 -0
  365. package/dist/web-components/viewer/Annotations-D1h-Yi5J.mjs +1 -0
  366. package/dist/web-components/viewer/Annotations-sj79EMen.mjs +2 -0
  367. package/dist/web-components/viewer/Canvas2DBackend-CkvI0wUT.mjs +1 -0
  368. package/dist/web-components/viewer/CaptionDetails-B_JdNjJ7.mjs +1 -0
  369. package/dist/web-components/viewer/ChoiceMenu-xa51a1DV.mjs +1 -0
  370. package/dist/web-components/viewer/Collection-CxuLCspj.mjs +1 -0
  371. package/dist/web-components/viewer/Connected-BSUBc3Ci.mjs +1 -0
  372. package/dist/web-components/viewer/Connected-CPIxNjF2.mjs +1 -0
  373. package/dist/web-components/viewer/Contents-DNh9mnsF.mjs +1 -0
  374. package/dist/web-components/viewer/ControlMenu-DdgIvBdf.mjs +1 -0
  375. package/dist/web-components/viewer/Cue-90H9_dXz.mjs +1 -0
  376. package/dist/web-components/viewer/Document-CNCpzkiN.mjs +1 -0
  377. package/dist/web-components/viewer/DocumentPanel-BdG4TVLE.mjs +1 -0
  378. package/dist/web-components/viewer/DomLayers-Dybz_aJv.mjs +1 -0
  379. package/dist/web-components/viewer/EntryBodies-DGXjFP3N.mjs +1 -0
  380. package/dist/web-components/viewer/FieldPill-Icmd98OY.mjs +1 -0
  381. package/dist/web-components/viewer/FrameAnimation-DJZN3Rd4.mjs +1 -0
  382. package/dist/web-components/viewer/Gallery-CEp3-bh2.mjs +1 -0
  383. package/dist/web-components/viewer/HideToggle-DB6HTmAO.mjs +1 -0
  384. package/dist/web-components/viewer/LightboxBody-ClQ4yrTh.mjs +1 -0
  385. package/dist/web-components/viewer/MapView-BVSdybIC.mjs +1 -0
  386. package/dist/web-components/viewer/MediaBody-BBbSMT1i.mjs +1 -0
  387. package/dist/web-components/viewer/MediaBody-BzMXMHIF.mjs +1 -0
  388. package/dist/web-components/viewer/Navigator-Duc69Yes.mjs +1 -0
  389. package/dist/web-components/viewer/PartOfManifest-X9_q-2t6.mjs +1 -0
  390. package/dist/web-components/viewer/Search-S4N5QU4R.mjs +1 -0
  391. package/dist/web-components/viewer/StandaloneItems-BO4VyWRW.mjs +1 -0
  392. package/dist/web-components/viewer/Transcript-BbDaS064.mjs +1 -0
  393. package/dist/web-components/viewer/annotation-collection-BjZ1DAHq.mjs +1 -0
  394. package/dist/web-components/viewer/annotations-content-jn3n5Y2-.mjs +1 -0
  395. package/dist/web-components/viewer/cloverEngine-CjuYjUhI.mjs +164 -0
  396. package/dist/web-components/viewer/content-state-reader-CPiShIjP.mjs +1 -0
  397. package/dist/web-components/viewer/host-yWi4R1bP.mjs +1 -0
  398. package/dist/web-components/viewer/index.d.mts +7 -0
  399. package/dist/web-components/viewer/index.mjs +1 -0
  400. package/dist/web-components/viewer/index.umd.js +18 -0
  401. package/dist/web-components/viewer/link-CwE-fg5G.mjs +1 -0
  402. package/dist/web-components/viewer/overlayImage-BpOgqsZ0.mjs +1 -0
  403. package/dist/web-components/viewer/renderers-L-IlGI1r.mjs +1 -0
  404. package/dist/web-components/viewer/search-DWkwRPo_.mjs +1 -0
  405. package/dist/web-components/viewer/styles-BRCkEU3w.mjs +1 -0
  406. package/dist/web-components/viewer/viewer--TreVlJ_.mjs +28 -0
  407. package/dist/web-components/viewer/vtt-1ZJwtElI.mjs +5 -0
  408. package/dist/web-components/viewer-DyV864Qe.mjs +1 -0
  409. package/dist/web-components/vtt-GFssZH8Y.mjs +5 -0
  410. package/package.json +110 -4
@@ -0,0 +1,857 @@
1
+ "use client";
2
+ var __defProp = Object.defineProperty;
3
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
5
+ import { claimContext, returnContext } from "./backends/contexts.mjs";
6
+ import { WebGL2Backend } from "./backends/webgl2/WebGL2Backend.mjs";
7
+ import { fitCamera, visibleWorldRect, screenPointToWorld, anchoredCenter, worldPointToScreen, sameCamera } from "./camera/Camera.mjs";
8
+ import { CameraAnimator } from "./camera/CameraAnimator.mjs";
9
+ import { GestureController, DEFAULT_GESTURES } from "./input/GestureController.mjs";
10
+ import { TileCache } from "./io/TileCache.mjs";
11
+ import { loadImage } from "./io/decode.mjs";
12
+ import { FrameLoop } from "./loop/FrameLoop.mjs";
13
+ import { uploadBudget } from "./scene/uploadBudget.mjs";
14
+ import { apply, compose, rotate, scale } from "./math/affine.mjs";
15
+ import { union, clamp } from "./math/rect.mjs";
16
+ import { planFrame } from "./scene/planFrame.mjs";
17
+ import { sameSpec, prepareItem, layoutItems, pixelsToWorld, MEDIA_KEY_PREFIX } from "./scene/sceneItem.mjs";
18
+ const DEFAULTS = {
19
+ maxZoomPixelRatio: 1.1,
20
+ minZoomImageRatio: 0.9,
21
+ animationTime: 0.09,
22
+ request: void 0,
23
+ byteBudget: 192 * 1024 * 1024,
24
+ maxInFlight: 6,
25
+ releaseAfterMs: 2e3
26
+ };
27
+ const MAX_PIXEL_RATIO = 2;
28
+ const MAX_CONTEXT_LOSSES = 3;
29
+ const ANNOTATION_PADDING = 0.1;
30
+ const ZOOM_EPSILON = 1e-6;
31
+ const NO_INSET = { top: 0, right: 0, bottom: 0, left: 0 };
32
+ function readInset(host) {
33
+ if (typeof getComputedStyle !== "function") return NO_INSET;
34
+ const style = getComputedStyle(host);
35
+ const px = (value) => parseFloat(value) || 0;
36
+ return {
37
+ top: px(style.paddingTop),
38
+ right: px(style.paddingRight),
39
+ bottom: px(style.paddingBottom),
40
+ left: px(style.paddingLeft)
41
+ };
42
+ }
43
+ const sameInset = (a, b) => a.top === b.top && a.right === b.right && a.bottom === b.bottom && a.left === b.left;
44
+ let canvas2d;
45
+ class CanvasRenderer {
46
+ constructor(host, options = {}) {
47
+ __publicField(this, "host");
48
+ /**
49
+ * Annotation hotspots and anything else pinned to a world rectangle: made by the first
50
+ * thing pinned (`overlaysOf`, in the hotspots' chunk), so a Canvas with none never
51
+ * loads it.
52
+ */
53
+ __publicField(this, "overlays", null);
54
+ __publicField(this, "options");
55
+ __publicField(this, "backend", null);
56
+ __publicField(this, "backendPreference");
57
+ __publicField(this, "contextLosses", 0);
58
+ /** Its place among the page's WebGL contexts (`backends/contexts`). */
59
+ __publicField(this, "holder", {
60
+ hiddenSince: null,
61
+ release: () => this.giveBack()
62
+ });
63
+ /** In the window, as last seen: only then does it hold a context. */
64
+ __publicField(this, "visible", true);
65
+ /**
66
+ * Elements the backend does not draw (`dom` video, pixels WebGL may not read): made,
67
+ * its code loaded, the first time a frame holds one.
68
+ */
69
+ __publicField(this, "dom", null);
70
+ __publicField(this, "domAsked", false);
71
+ /** A canvas waiting for Canvas2D's code, the host's background showing meanwhile. */
72
+ __publicField(this, "pending", null);
73
+ __publicField(this, "camera");
74
+ __publicField(this, "loop");
75
+ __publicField(this, "gestures");
76
+ /** The gesture options the renderer was created with; `setGestures` layers on these. */
77
+ __publicField(this, "gestureOptions", {});
78
+ __publicField(this, "cache");
79
+ __publicField(this, "navigator", null);
80
+ /** Counts `attachNavigator` calls, so only the latest one's navigator is made. */
81
+ __publicField(this, "navigatorAsked", 0);
82
+ __publicField(this, "viewport", { width: 1, height: 1 });
83
+ /** The host's padding: the space the home view keeps clear around the picture. */
84
+ __publicField(this, "inset", NO_INSET);
85
+ __publicField(this, "pixelRatio", 1);
86
+ __publicField(this, "items", []);
87
+ __publicField(this, "worldBounds", null);
88
+ /** Bumped when the scene or its loaded tiles change: the navigator redraws on it. */
89
+ __publicField(this, "contentVersion", 0);
90
+ /** Tiles WebGL refused (no CORS): shown as DOM layers from then on. */
91
+ __publicField(this, "opaqueUrls", /* @__PURE__ */ new Set());
92
+ /** Media items' elements, by their one tile's key. Never in the tile cache. */
93
+ __publicField(this, "mediaByKey", /* @__PURE__ */ new Map());
94
+ __publicField(this, "detachMedia", []);
95
+ __publicField(this, "opened", false);
96
+ /** True until the reader moves the camera; a resize then refits rather than crops. */
97
+ __publicField(this, "atHome", true);
98
+ __publicField(this, "lastEmitted", null);
99
+ __publicField(this, "generation", 0);
100
+ __publicField(this, "listeners", /* @__PURE__ */ new Map());
101
+ __publicField(this, "resizeObserver", null);
102
+ __publicField(this, "intersectionObserver", null);
103
+ __publicField(this, "releaseTimer", null);
104
+ __publicField(this, "dprQuery", null);
105
+ __publicField(this, "disposed", false);
106
+ __publicField(this, "dismisser", null);
107
+ // ─── Frame ────────────────────────────────────────────────────────────────
108
+ __publicField(this, "tick", (dt) => {
109
+ var _a, _b;
110
+ if (this.disposed) return false;
111
+ const animating = this.camera.step(dt, this.viewport);
112
+ const camera = this.camera.current;
113
+ const backend = this.backend;
114
+ const uploads = uploadBudget(
115
+ this.getTile,
116
+ (url) => backend ? backend.has(url) : true
117
+ );
118
+ const plan = planFrame({
119
+ items: this.items,
120
+ camera,
121
+ viewport: this.viewport,
122
+ pixelRatio: this.pixelRatio,
123
+ getTile: uploads.getTile,
124
+ wantOverview: Boolean(this.navigator),
125
+ // Fetch for where the camera lands, not for each view on the way.
126
+ destination: animating ? this.camera.destination : void 0
127
+ });
128
+ this.cache.update(
129
+ plan.wants.filter((want) => !want.url.startsWith(MEDIA_KEY_PREFIX))
130
+ );
131
+ this.paint(plan.draws);
132
+ (_a = this.overlays) == null ? void 0 : _a.position(camera, this.viewport);
133
+ (_b = this.navigator) == null ? void 0 : _b.render(
134
+ this.items.filter((item) => !item.spec.hidden),
135
+ this.worldBounds,
136
+ visibleWorldRect(camera, this.viewport),
137
+ this.pixelRatio,
138
+ this.getTile,
139
+ this.contentVersion
140
+ );
141
+ if (!this.lastEmitted || !sameCamera(this.lastEmitted, camera)) {
142
+ this.lastEmitted = { ...camera };
143
+ if (this.opened) this.emit("viewport");
144
+ }
145
+ return animating || uploads.deferred;
146
+ });
147
+ __publicField(this, "getTile", (url) => this.mediaByKey.get(url) ?? this.cache.get(url));
148
+ /*
149
+ * The browser took the context (too many on the page, a GPU reset). Its canvas goes at
150
+ * once, so the browser's picture of a lost context never shows, only the host's
151
+ * background; Canvas2D draws on from the decoded tiles, nothing refetched, and WebGL is
152
+ * tried again when it next comes into view (a GPU that keeps dropping it, never).
153
+ */
154
+ __publicField(this, "onContextLost", () => {
155
+ this.contextLosses += 1;
156
+ this.releaseBackend();
157
+ if (this.visible) this.acquireBackend(false);
158
+ else this.host.dataset.backend = "released";
159
+ });
160
+ __publicField(this, "onPixelRatioChange", () => {
161
+ this.measure();
162
+ this.watchPixelRatio();
163
+ });
164
+ this.host = host;
165
+ this.backendPreference = options.backend ?? "auto";
166
+ this.options = {
167
+ ...DEFAULTS,
168
+ ...stripUndefined(options)
169
+ };
170
+ if (prefersReducedMotion()) this.options.animationTime = 0;
171
+ this.camera = new CameraAnimator(
172
+ { x: 0, y: 0, zoom: 1, rotation: 0 },
173
+ this.options.animationTime
174
+ );
175
+ this.loop = new FrameLoop(this.tick);
176
+ this.gestureOptions = stripUndefined(options.gestures ?? {});
177
+ this.gestures = new GestureController(host, this, {
178
+ ...DEFAULT_GESTURES,
179
+ ...this.gestureOptions
180
+ });
181
+ this.cache = new TileCache({
182
+ load: (url, signal) => this.loadTile(url, signal),
183
+ onSettled: () => {
184
+ this.contentVersion++;
185
+ this.invalidate();
186
+ },
187
+ onEvict: (url) => {
188
+ var _a;
189
+ return (_a = this.backend) == null ? void 0 : _a.release(url);
190
+ },
191
+ byteBudget: this.options.byteBudget,
192
+ maxInFlight: this.options.maxInFlight
193
+ });
194
+ this.visible = inWindow(host);
195
+ if (this.visible) this.acquireBackend();
196
+ else this.holder.hiddenSince = now();
197
+ this.measure();
198
+ this.observe();
199
+ }
200
+ // ─── Public API ────────────────────────────────────────────────────────────
201
+ get backendKind() {
202
+ var _a;
203
+ return ((_a = this.backend) == null ? void 0 : _a.kind) ?? "none";
204
+ }
205
+ get isOpen() {
206
+ return this.opened;
207
+ }
208
+ /** Whether the camera is at home: false once the reader zooms, pans or turns it. */
209
+ get isAtHome() {
210
+ return this.atHome;
211
+ }
212
+ on(event, listener) {
213
+ let set = this.listeners.get(event);
214
+ if (!set) {
215
+ set = /* @__PURE__ */ new Set();
216
+ this.listeners.set(event, set);
217
+ }
218
+ set.add(listener);
219
+ return () => set == null ? void 0 : set.delete(listener);
220
+ }
221
+ /**
222
+ * Replace the scene.
223
+ *
224
+ * New items are resolved — `info.json` fetched, coarsest tiles decoded — before they
225
+ * replace the old ones, so a swap never flashes empty. Items whose description is
226
+ * unchanged are kept as they are, and tiles are cached by URL, so swapping between two
227
+ * regions of one image costs nothing at all.
228
+ */
229
+ async setImages(images, {
230
+ world,
231
+ fit = false
232
+ } = {}) {
233
+ const generation = ++this.generation;
234
+ const previous = new Map(this.items.map((item) => [item.id, item]));
235
+ const results = await Promise.allSettled(
236
+ images.map((spec) => {
237
+ const kept = previous.get(spec.id);
238
+ if (kept && sameSpec(kept.spec, spec)) {
239
+ kept.spec = spec;
240
+ return Promise.resolve(kept);
241
+ }
242
+ return prepareItem(spec, {
243
+ cache: this.cache,
244
+ loadStatic: (url) => this.loadTile(url),
245
+ infoOptions: { request: this.options.request }
246
+ });
247
+ })
248
+ );
249
+ if (generation !== this.generation || this.disposed) return;
250
+ const items = results.filter(
251
+ (r) => r.status === "fulfilled"
252
+ ).map((r) => r.value);
253
+ const errors = results.filter((r) => r.status === "rejected").map((r) => r.reason);
254
+ this.items = items;
255
+ this.watchMedia(items);
256
+ const laidOut = layoutItems(items);
257
+ this.worldBounds = world ? laidOut ? union([world, laidOut]) : world : laidOut;
258
+ this.contentVersion++;
259
+ if (errors.length) this.emit("error", errors);
260
+ if (!this.worldBounds) {
261
+ this.invalidate();
262
+ return;
263
+ }
264
+ if (!this.opened) {
265
+ this.opened = true;
266
+ this.home(true);
267
+ this.emit("open");
268
+ } else if (fit) {
269
+ this.home(true);
270
+ this.emit("change");
271
+ } else {
272
+ this.camera.set(this.constrain(this.camera.current));
273
+ this.emit("change");
274
+ }
275
+ this.invalidate();
276
+ }
277
+ /**
278
+ * Put the scene away at once: from the next frame nothing of it is drawn, and a swap
279
+ * still preparing is dropped. For moving to a different resource, whose pictures should
280
+ * never show beside the last one's while they load; `setImages` then draws the new
281
+ * scene, framed afresh. A swap within one resource keeps the old scene up instead.
282
+ */
283
+ clear() {
284
+ this.generation++;
285
+ this.items = [];
286
+ this.watchMedia([]);
287
+ this.worldBounds = null;
288
+ this.contentVersion++;
289
+ this.invalidate();
290
+ }
291
+ /**
292
+ * Show only some of the scene's images, keeping the others loaded: the frames of an
293
+ * animation. Nothing is prepared, laid out or reported; the next frame draws the change.
294
+ */
295
+ setHidden(ids) {
296
+ const hidden = new Set(ids);
297
+ let changed = false;
298
+ for (const item of this.items) {
299
+ const next = hidden.has(item.id);
300
+ if (Boolean(item.spec.hidden) === next) continue;
301
+ item.spec = { ...item.spec, hidden: next };
302
+ changed = true;
303
+ }
304
+ if (changed) this.invalidate();
305
+ }
306
+ /**
307
+ * Whether an image can be drawn now: it is in the scene and its coarsest level is
308
+ * loaded. An animation waits on this before showing a frame, rather than blink empty.
309
+ */
310
+ isReady(id) {
311
+ const item = this.items.find((candidate) => candidate.id === id);
312
+ if (!item) return false;
313
+ if (item.spec.media) return true;
314
+ const level = item.pyramid.levels[0];
315
+ if (!level) return false;
316
+ for (let row = 0; row < level.rows; row++) {
317
+ for (let col = 0; col < level.cols; col++) {
318
+ if (!this.getTile(item.pyramid.tile({ level: 0, col, row }).url)) {
319
+ return false;
320
+ }
321
+ }
322
+ }
323
+ return true;
324
+ }
325
+ /** Frame `bounds` (world units) in the viewport. */
326
+ fitBounds(bounds, immediate = false) {
327
+ const target = fitCamera(
328
+ bounds,
329
+ this.viewport,
330
+ this.camera.destination.rotation,
331
+ 0
332
+ );
333
+ this.atHome = false;
334
+ this.animateTo(
335
+ this.constrain(target, { allowBeyondLimits: true }),
336
+ immediate
337
+ );
338
+ }
339
+ /**
340
+ * Zoom to a rectangle in item `index`'s own coordinates — an annotation's `xywh` — with
341
+ * OpenSeadragon's padding.
342
+ */
343
+ fitItemRect(index, rect, immediate = false) {
344
+ const world = this.itemRectToWorld(index, rect);
345
+ if (world) this.fitAnnotation(world, immediate);
346
+ }
347
+ /** Zoom to a world rectangle with OpenSeadragon's annotation padding. */
348
+ fitAnnotation(world, immediate = false) {
349
+ const first = this.items[0];
350
+ if (!first) return;
351
+ const pad = first.rect.width * ANNOTATION_PADDING;
352
+ this.fitBounds(
353
+ {
354
+ x: world.x - pad,
355
+ y: world.y - pad,
356
+ width: world.width + pad * 2,
357
+ height: world.height + pad * 2
358
+ },
359
+ immediate
360
+ );
361
+ }
362
+ /** The world rectangle currently visible (its bounding box when rotated). */
363
+ getBounds() {
364
+ return visibleWorldRect(this.camera.current, this.viewport);
365
+ }
366
+ getHomeBounds() {
367
+ return this.worldBounds ? { ...this.worldBounds } : null;
368
+ }
369
+ getCamera() {
370
+ return { ...this.camera.current };
371
+ }
372
+ getZoomLimits() {
373
+ var _a;
374
+ const home = ((_a = this.homeCamera()) == null ? void 0 : _a.zoom) ?? 1;
375
+ const worldPerPixel = this.items.length ? Math.min(...this.items.map((item) => pixelsToWorld(item).x)) : 1;
376
+ return {
377
+ home,
378
+ min: home * this.options.minZoomImageRatio,
379
+ max: Math.max(home, this.options.maxZoomPixelRatio / worldPerPixel)
380
+ };
381
+ }
382
+ home(immediate = false) {
383
+ const home = this.homeCamera();
384
+ if (!home) return;
385
+ this.atHome = true;
386
+ this.animateTo(home, immediate);
387
+ }
388
+ /** Zoomed in as far as it goes, or on the way there. */
389
+ atMaxZoom() {
390
+ return this.camera.destination.zoom >= this.getZoomLimits().max * (1 - ZOOM_EPSILON);
391
+ }
392
+ zoomBy(factor, at, animate = true) {
393
+ const base = animate ? this.camera.destination : this.camera.current;
394
+ const screen = at ?? {
395
+ x: this.viewport.width / 2,
396
+ y: this.viewport.height / 2
397
+ };
398
+ const world = screenPointToWorld(base, this.viewport, screen);
399
+ const { min, max } = this.getZoomLimits();
400
+ const zoom = clamp(base.zoom * factor, min, max);
401
+ const center = anchoredCenter(
402
+ world,
403
+ screen,
404
+ zoom,
405
+ base.rotation,
406
+ this.viewport
407
+ );
408
+ const target = this.constrain({ ...base, ...center, zoom });
409
+ this.atHome = false;
410
+ if (animate) {
411
+ this.camera.animateTo(
412
+ { state: target, anchor: { world, screen } },
413
+ this.viewport
414
+ );
415
+ } else {
416
+ this.camera.set(target);
417
+ }
418
+ this.invalidate();
419
+ }
420
+ panBy(dx, dy, animate = false) {
421
+ const base = animate ? this.camera.destination : this.camera.current;
422
+ const shift = apply(compose(scale(1 / base.zoom), rotate(-base.rotation)), {
423
+ x: dx,
424
+ y: dy
425
+ });
426
+ const target = this.constrain({
427
+ ...base,
428
+ x: base.x - shift.x,
429
+ y: base.y - shift.y
430
+ });
431
+ this.atHome = false;
432
+ if (animate) this.camera.animateTo({ state: target }, this.viewport);
433
+ else this.camera.set(target);
434
+ this.invalidate();
435
+ }
436
+ /** Center the view on a world point. */
437
+ panTo(point, immediate = false) {
438
+ const base = immediate ? this.camera.current : this.camera.destination;
439
+ this.atHome = false;
440
+ this.animateTo(this.constrain({ ...base, ...point }), immediate);
441
+ }
442
+ flick(vx, vy) {
443
+ this.panBy(vx * 0.25, vy * 0.25, true);
444
+ }
445
+ rotateBy(degrees) {
446
+ const base = this.camera.destination;
447
+ this.setRotation(base.rotation * 180 / Math.PI + degrees);
448
+ }
449
+ /** Rotate about the viewport center. Degrees, clockwise, like OpenSeadragon. */
450
+ setRotation(degrees, immediate = false) {
451
+ const base = this.camera.destination;
452
+ const rotation = degrees * Math.PI / 180;
453
+ this.animateTo(this.constrain({ ...base, rotation }), immediate);
454
+ }
455
+ getRotation() {
456
+ return this.camera.destination.rotation * 180 / Math.PI;
457
+ }
458
+ tap(at) {
459
+ this.emit("tap", at);
460
+ }
461
+ /**
462
+ * What a tap off every control and hotspot puts away first: the handler returns whether
463
+ * it put anything away, and if it did, the tap neither zooms nor is reported.
464
+ */
465
+ setDismiss(handler) {
466
+ this.dismisser = handler;
467
+ }
468
+ dismiss() {
469
+ var _a;
470
+ return ((_a = this.dismisser) == null ? void 0 : _a.call(this)) ?? false;
471
+ }
472
+ /** Change how pointer, wheel and keyboard drive the camera. */
473
+ setGestures(gestures) {
474
+ this.gestures.setOptions({
475
+ ...DEFAULT_GESTURES,
476
+ ...this.gestureOptions,
477
+ ...stripUndefined(gestures)
478
+ });
479
+ }
480
+ setInteracting(interacting) {
481
+ if (interacting) this.camera.stop();
482
+ }
483
+ worldToScreenPoint(point) {
484
+ return worldPointToScreen(this.camera.current, this.viewport, point);
485
+ }
486
+ screenToWorldPoint(point) {
487
+ return screenPointToWorld(this.camera.current, this.viewport, point);
488
+ }
489
+ /**
490
+ * A rectangle in item `index`'s own coordinates (its declared size — what an
491
+ * annotation's `xywh` targets) → world units.
492
+ */
493
+ itemRectToWorld(index, rect) {
494
+ const item = this.items[index];
495
+ if (!item) return null;
496
+ const { contentClip } = item;
497
+ const kx = item.rect.width / contentClip.width;
498
+ const ky = item.rect.height / contentClip.height;
499
+ return {
500
+ x: item.rect.x + (rect.x - contentClip.x) * kx,
501
+ y: item.rect.y + (rect.y - contentClip.y) * ky,
502
+ width: rect.width * kx,
503
+ height: rect.height * ky
504
+ };
505
+ }
506
+ /**
507
+ * Show an overview of the scene in `element`. Returns a function that removes it. It is
508
+ * off by default, so its code loads the first time one is asked for, and draws then.
509
+ */
510
+ attachNavigator(element) {
511
+ var _a;
512
+ (_a = this.navigator) == null ? void 0 : _a.dispose();
513
+ this.navigator = null;
514
+ const asked = ++this.navigatorAsked;
515
+ let navigator = null;
516
+ let removed = false;
517
+ void import("./overlays/Navigator.mjs").then((module) => {
518
+ if (removed || this.disposed || asked !== this.navigatorAsked) return;
519
+ navigator = new module.Navigator(
520
+ element,
521
+ (point, immediate) => this.panTo(point, immediate)
522
+ );
523
+ this.navigator = navigator;
524
+ this.invalidate();
525
+ });
526
+ return () => {
527
+ removed = true;
528
+ navigator == null ? void 0 : navigator.dispose();
529
+ if (navigator && this.navigator === navigator) this.navigator = null;
530
+ };
531
+ }
532
+ invalidate() {
533
+ this.loop.invalidate();
534
+ }
535
+ dispose() {
536
+ var _a, _b, _c, _d, _e, _f, _g;
537
+ if (this.disposed) return;
538
+ this.disposed = true;
539
+ this.generation++;
540
+ this.loop.dispose();
541
+ this.gestures.dispose();
542
+ (_a = this.resizeObserver) == null ? void 0 : _a.disconnect();
543
+ (_b = this.intersectionObserver) == null ? void 0 : _b.disconnect();
544
+ (_d = (_c = this.dprQuery) == null ? void 0 : _c.removeEventListener) == null ? void 0 : _d.call(_c, "change", this.onPixelRatioChange);
545
+ if (this.releaseTimer) clearTimeout(this.releaseTimer);
546
+ (_e = this.navigator) == null ? void 0 : _e.dispose();
547
+ this.navigator = null;
548
+ this.releaseBackend();
549
+ this.cache.dispose();
550
+ (_f = this.dom) == null ? void 0 : _f.dispose();
551
+ (_g = this.overlays) == null ? void 0 : _g.dispose();
552
+ this.items = [];
553
+ this.detachMedia.forEach((detach) => detach());
554
+ this.mediaByKey.clear();
555
+ this.listeners.clear();
556
+ delete this.host.dataset.backend;
557
+ }
558
+ /**
559
+ * Track the scene's media elements: redraw when one has a new frame to show (it
560
+ * started, seeked, or loaded), and drop the listeners when the scene changes.
561
+ */
562
+ watchMedia(items) {
563
+ this.detachMedia.forEach((detach) => detach());
564
+ this.detachMedia = [];
565
+ this.mediaByKey.clear();
566
+ for (const item of items) {
567
+ if (!item.media || item.media.kind !== "media") continue;
568
+ const key = item.pyramid.tile({ level: 0, col: 0, row: 0 }).url;
569
+ this.mediaByKey.set(key, item.media);
570
+ const element = item.media.source;
571
+ const redraw = () => this.invalidate();
572
+ const events = ["play", "seeked", "loadeddata", "resize"];
573
+ events.forEach((type) => element.addEventListener(type, redraw));
574
+ this.detachMedia.push(
575
+ () => events.forEach((type) => element.removeEventListener(type, redraw))
576
+ );
577
+ }
578
+ }
579
+ paint(draws) {
580
+ const backend = this.backend;
581
+ const domItems = [];
582
+ const webgl = (backend == null ? void 0 : backend.kind) === "webgl2";
583
+ backend == null ? void 0 : backend.begin();
584
+ for (const draw of draws) {
585
+ const { image } = draw;
586
+ const asDom = image.kind === "media" || image.kind === "element" && webgl && (image.opaque || this.opaqueUrls.has(draw.url));
587
+ if (!asDom && backend) {
588
+ const result = backend.draw({
589
+ key: draw.url,
590
+ source: image.source,
591
+ width: image.width,
592
+ height: image.height,
593
+ transform: draw.transform,
594
+ crop: draw.crop,
595
+ opacity: 1,
596
+ bleed: draw.bleed
597
+ });
598
+ if (result !== "tainted" || image.kind === "bitmap") continue;
599
+ this.opaqueUrls.add(draw.url);
600
+ }
601
+ if (image.kind === "element" || image.kind === "media") {
602
+ domItems.push({
603
+ key: `${draw.item.id}|${draw.url}`,
604
+ element: image.source,
605
+ width: image.width,
606
+ height: image.height,
607
+ transform: draw.transform,
608
+ crop: draw.crop,
609
+ opacity: 1
610
+ });
611
+ }
612
+ }
613
+ backend == null ? void 0 : backend.end();
614
+ if (this.dom) this.dom.sync(domItems);
615
+ else if (domItems.length && !this.domAsked) {
616
+ this.domAsked = true;
617
+ void import("./backends/dom/DomLayers.mjs").then(({ DomLayers }) => {
618
+ if (this.disposed) return;
619
+ const dom = new DomLayers(this.host);
620
+ if (this.overlays)
621
+ this.host.insertBefore(dom.container, this.overlays.container);
622
+ this.dom = dom;
623
+ this.invalidate();
624
+ });
625
+ }
626
+ }
627
+ loadTile(url, signal) {
628
+ return loadImage(url, {
629
+ signal,
630
+ request: this.options.request,
631
+ maxTextureSize: this.backend instanceof WebGL2Backend ? this.backend.maxTextureSize : void 0
632
+ });
633
+ }
634
+ // ─── Camera helpers ───────────────────────────────────────────────────────
635
+ animateTo(state, immediate) {
636
+ this.camera.animateTo({ state }, this.viewport, immediate);
637
+ this.invalidate();
638
+ }
639
+ /**
640
+ * Home is the whole world, upright — Clover's home control also resets rotation. Upright
641
+ * is the whole turn nearest where the camera is heading, so four quarter turns right then
642
+ * home does not spin a full turn back, and three come upright by one more quarter.
643
+ */
644
+ homeCamera() {
645
+ if (!this.worldBounds) return null;
646
+ const turn = 2 * Math.PI;
647
+ const upright = Math.round(this.camera.destination.rotation / turn) * turn || 0;
648
+ const { top, right, bottom, left } = this.inset;
649
+ const camera = fitCamera(
650
+ this.worldBounds,
651
+ {
652
+ width: Math.max(1, this.viewport.width - left - right),
653
+ height: Math.max(1, this.viewport.height - top - bottom)
654
+ },
655
+ upright
656
+ );
657
+ camera.x -= (left - right) / 2 / camera.zoom;
658
+ camera.y -= (top - bottom) / 2 / camera.zoom;
659
+ return camera;
660
+ }
661
+ /**
662
+ * Keep the camera usable: zoom within limits, and the center over the world so the
663
+ * picture cannot be flung out of sight.
664
+ */
665
+ constrain(state, { allowBeyondLimits = false } = {}) {
666
+ const bounds = this.worldBounds;
667
+ if (!bounds) return state;
668
+ const { min, max } = this.getZoomLimits();
669
+ const zoom = allowBeyondLimits ? clamp(state.zoom, min, Math.max(max, state.zoom)) : clamp(state.zoom, min, max);
670
+ return {
671
+ ...state,
672
+ zoom,
673
+ x: clamp(state.x, bounds.x, bounds.x + bounds.width),
674
+ y: clamp(state.y, bounds.y, bounds.y + bounds.height)
675
+ };
676
+ }
677
+ // ─── Backend lifecycle ────────────────────────────────────────────────────
678
+ /** @param webgl false to draw with Canvas2D whatever the preference, as after a loss. */
679
+ acquireBackend(webgl = true) {
680
+ var _a, _b;
681
+ if (this.backend || this.pending || this.disposed) return;
682
+ const canvas = document.createElement("canvas");
683
+ canvas.className = "clover-canvas-surface";
684
+ canvas.setAttribute("aria-hidden", "true");
685
+ Object.assign(canvas.style, {
686
+ position: "absolute",
687
+ inset: "0",
688
+ width: "100%",
689
+ height: "100%",
690
+ display: "block",
691
+ pointerEvents: "none"
692
+ });
693
+ this.host.insertBefore(
694
+ canvas,
695
+ ((_a = this.dom) == null ? void 0 : _a.container) ?? ((_b = this.overlays) == null ? void 0 : _b.container) ?? null
696
+ );
697
+ const tryWebGL = webgl && (this.backendPreference === "webgl2" || this.backendPreference === "auto" && this.contextLosses < MAX_CONTEXT_LOSSES);
698
+ let backend = null;
699
+ if (tryWebGL && (claimContext(this.holder) || this.backendPreference === "webgl2")) {
700
+ backend = WebGL2Backend.create(canvas, { onLost: this.onContextLost });
701
+ if (!backend) returnContext(this.holder);
702
+ }
703
+ if (backend) this.install(backend);
704
+ else if (this.backendPreference === "webgl2") this.none(canvas);
705
+ else {
706
+ this.pending = canvas;
707
+ void (canvas2d ?? (canvas2d = import("./backends/canvas2d/Canvas2DBackend.mjs"))).then(
708
+ ({ Canvas2DBackend }) => {
709
+ if (this.pending !== canvas) return;
710
+ this.pending = null;
711
+ const made = Canvas2DBackend.create(canvas);
712
+ if (made) this.install(made);
713
+ else this.none(canvas);
714
+ }
715
+ );
716
+ }
717
+ }
718
+ none(canvas) {
719
+ canvas.remove();
720
+ this.host.dataset.backend = "none";
721
+ }
722
+ install(backend) {
723
+ this.backend = backend;
724
+ this.host.dataset.backend = backend.kind;
725
+ backend.resize(this.viewport.width, this.viewport.height, this.pixelRatio);
726
+ if (backend.kind === "canvas2d") this.opaqueUrls.clear();
727
+ this.emit("backend", backend.kind);
728
+ this.invalidate();
729
+ }
730
+ releaseBackend() {
731
+ var _a;
732
+ returnContext(this.holder);
733
+ (_a = this.pending) == null ? void 0 : _a.remove();
734
+ this.pending = null;
735
+ if (!this.backend) return;
736
+ const canvas = this.backend.canvas;
737
+ this.backend.dispose();
738
+ canvas.remove();
739
+ this.backend = null;
740
+ }
741
+ /** Its context given back, out of view or to make room for one in view. */
742
+ giveBack() {
743
+ if (this.releaseTimer) clearTimeout(this.releaseTimer);
744
+ this.releaseTimer = null;
745
+ this.releaseBackend();
746
+ this.host.dataset.backend = "released";
747
+ }
748
+ // ─── Observation ──────────────────────────────────────────────────────────
749
+ observe() {
750
+ if (typeof ResizeObserver !== "undefined") {
751
+ this.resizeObserver = new ResizeObserver(() => this.measure(true));
752
+ this.resizeObserver.observe(this.host);
753
+ }
754
+ if (typeof IntersectionObserver !== "undefined") {
755
+ this.intersectionObserver = new IntersectionObserver((entries) => {
756
+ const visible = entries.some((entry) => entry.isIntersecting);
757
+ this.setVisible(visible);
758
+ });
759
+ this.intersectionObserver.observe(this.host);
760
+ }
761
+ this.watchPixelRatio();
762
+ }
763
+ /**
764
+ * Browsers cap live WebGL contexts per page and silently kill the oldest beyond it.
765
+ * An instance scrolled out of view gives its context back after a grace period, or at
766
+ * once when one in view needs it (`backends/contexts`), and takes a fresh one on
767
+ * return; decoded tiles stay in memory, so nothing is refetched.
768
+ */
769
+ setVisible(visible) {
770
+ var _a;
771
+ this.visible = visible;
772
+ if (visible) {
773
+ this.holder.hiddenSince = null;
774
+ if (this.releaseTimer) clearTimeout(this.releaseTimer);
775
+ this.releaseTimer = null;
776
+ if (!this.backend) this.acquireBackend();
777
+ return;
778
+ }
779
+ (_a = this.holder).hiddenSince ?? (_a.hiddenSince = now());
780
+ if (!this.backend || this.releaseTimer) return;
781
+ this.releaseTimer = setTimeout(
782
+ () => this.giveBack(),
783
+ this.options.releaseAfterMs
784
+ );
785
+ }
786
+ /**
787
+ * @param now draw at once, for a ResizeObserver: resizing the canvas clears it, and
788
+ * the observer runs too late in the frame for the next frame to be in time. Without
789
+ * it, dragging a pane's edge blinks the picture on every step.
790
+ */
791
+ measure(now2 = false) {
792
+ var _a;
793
+ const rect = this.host.getBoundingClientRect();
794
+ const width = Math.max(1, rect.width);
795
+ const height = Math.max(1, rect.height);
796
+ const inset = readInset(this.host);
797
+ const pixelRatio = Math.min(
798
+ typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1,
799
+ MAX_PIXEL_RATIO
800
+ );
801
+ if (width === this.viewport.width && height === this.viewport.height && pixelRatio === this.pixelRatio && sameInset(inset, this.inset)) {
802
+ return;
803
+ }
804
+ const previous = this.viewport;
805
+ this.viewport = { width, height };
806
+ this.inset = inset;
807
+ this.pixelRatio = pixelRatio;
808
+ (_a = this.backend) == null ? void 0 : _a.resize(width, height, pixelRatio);
809
+ if (this.opened) {
810
+ if (this.atHome) {
811
+ this.home(true);
812
+ } else {
813
+ const current = this.camera.current;
814
+ const ratio = width / Math.max(previous.width, 1);
815
+ this.camera.set(
816
+ this.constrain({ ...current, zoom: current.zoom * ratio })
817
+ );
818
+ }
819
+ }
820
+ if (now2) this.loop.drawNow();
821
+ else this.invalidate();
822
+ }
823
+ watchPixelRatio() {
824
+ var _a, _b, _c, _d;
825
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
826
+ return;
827
+ }
828
+ (_b = (_a = this.dprQuery) == null ? void 0 : _a.removeEventListener) == null ? void 0 : _b.call(_a, "change", this.onPixelRatioChange);
829
+ this.dprQuery = window.matchMedia(
830
+ `(resolution: ${window.devicePixelRatio || 1}dppx)`
831
+ );
832
+ (_d = (_c = this.dprQuery).addEventListener) == null ? void 0 : _d.call(_c, "change", this.onPixelRatioChange);
833
+ }
834
+ emit(event, detail) {
835
+ var _a;
836
+ (_a = this.listeners.get(event)) == null ? void 0 : _a.forEach((listener) => listener(detail));
837
+ }
838
+ }
839
+ const now = () => typeof performance !== "undefined" ? performance.now() : Date.now();
840
+ function inWindow(host) {
841
+ if (typeof IntersectionObserver === "undefined" || typeof window === "undefined") {
842
+ return true;
843
+ }
844
+ const { top, left, width, height } = host.getBoundingClientRect();
845
+ return top + height >= 0 && left + width >= 0 && top <= window.innerHeight && left <= window.innerWidth;
846
+ }
847
+ function prefersReducedMotion() {
848
+ return typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
849
+ }
850
+ function stripUndefined(value) {
851
+ return Object.fromEntries(
852
+ Object.entries(value).filter(([, v]) => v !== void 0)
853
+ );
854
+ }
855
+ export {
856
+ CanvasRenderer
857
+ };