dbf-mirador 4.2.3

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 (384) hide show
  1. package/LICENSE +203 -0
  2. package/README.md +133 -0
  3. package/dist/CommentSharp-B0J_-jEq.js +325 -0
  4. package/dist/CommentSharp-B0J_-jEq.js.map +1 -0
  5. package/dist/FailedImageContext-aQXnWSHN.js +318 -0
  6. package/dist/FailedImageContext-aQXnWSHN.js.map +1 -0
  7. package/dist/PluginHook-CFw_6P5c.js +54 -0
  8. package/dist/PluginHook-CFw_6P5c.js.map +1 -0
  9. package/dist/WindowCanvasNavigationControls-CUX723BQ.js +242 -0
  10. package/dist/WindowCanvasNavigationControls-CUX723BQ.js.map +1 -0
  11. package/dist/action-types-DjIbTE-A.js +74 -0
  12. package/dist/action-types-DjIbTE-A.js.map +1 -0
  13. package/dist/canvas-C8oHvXFN.js +41 -0
  14. package/dist/canvas-C8oHvXFN.js.map +1 -0
  15. package/dist/canvases-gRqhr-IH.js +3154 -0
  16. package/dist/canvases-gRqhr-IH.js.map +1 -0
  17. package/dist/createSvgIcon-Cwt8YPfm.js +2 -0
  18. package/dist/getters-COus7Mvg.js +2066 -0
  19. package/dist/getters-COus7Mvg.js.map +1 -0
  20. package/dist/index.module-CbBRf_R8.js +403 -0
  21. package/dist/index.module-CbBRf_R8.js.map +1 -0
  22. package/dist/mirador.es.js +39600 -0
  23. package/dist/mirador.es.js.map +1 -0
  24. package/dist/mirador.min.js +334 -0
  25. package/dist/mirador.min.js.map +1 -0
  26. package/dist/react-error-boundary.esm-B_pT-oCS.js +67 -0
  27. package/dist/react-error-boundary.esm-B_pT-oCS.js.map +1 -0
  28. package/dist/visuallyHidden-DmYvwNdU.js +98 -0
  29. package/dist/visuallyHidden-DmYvwNdU.js.map +1 -0
  30. package/dist/window-zelwU7wz.js +138 -0
  31. package/dist/window-zelwU7wz.js.map +1 -0
  32. package/package.json +138 -0
  33. package/src/components/AccessTokenSender.jsx +34 -0
  34. package/src/components/AnnotationSettings.jsx +31 -0
  35. package/src/components/AnnotationsOverlay.jsx +328 -0
  36. package/src/components/App.jsx +34 -0
  37. package/src/components/AppProviders.jsx +129 -0
  38. package/src/components/AttributionPanel.jsx +78 -0
  39. package/src/components/AudioViewer.jsx +39 -0
  40. package/src/components/BackgroundPluginArea.jsx +9 -0
  41. package/src/components/Branding.jsx +33 -0
  42. package/src/components/CanvasAnnotations.jsx +125 -0
  43. package/src/components/CanvasInfo.jsx +46 -0
  44. package/src/components/CanvasLayers.jsx +367 -0
  45. package/src/components/ChangeThemeDialog.jsx +65 -0
  46. package/src/components/CollapsibleSection.jsx +53 -0
  47. package/src/components/CollectionDialog.jsx +236 -0
  48. package/src/components/CollectionInfo.jsx +48 -0
  49. package/src/components/CompanionArea.jsx +140 -0
  50. package/src/components/CompanionWindow.jsx +228 -0
  51. package/src/components/CompanionWindowFactory.jsx +38 -0
  52. package/src/components/CompanionWindowSection.jsx +11 -0
  53. package/src/components/CustomPanel.jsx +22 -0
  54. package/src/components/ErrorContent.jsx +65 -0
  55. package/src/components/ErrorDialog.jsx +47 -0
  56. package/src/components/FullScreenButton.jsx +47 -0
  57. package/src/components/GalleryView.jsx +36 -0
  58. package/src/components/GalleryViewThumbnail.jsx +160 -0
  59. package/src/components/IIIFAuthentication.jsx +144 -0
  60. package/src/components/IIIFDropTarget.jsx +168 -0
  61. package/src/components/IIIFIFrameCommunication.jsx +45 -0
  62. package/src/components/IIIFResourceLabel.jsx +26 -0
  63. package/src/components/IIIFThumbnail.jsx +214 -0
  64. package/src/components/ImageFailureMessage.jsx +42 -0
  65. package/src/components/LabelValueMetadata.jsx +46 -0
  66. package/src/components/LanguageSettings.jsx +46 -0
  67. package/src/components/LayersPanel.jsx +24 -0
  68. package/src/components/LocalePicker.jsx +56 -0
  69. package/src/components/ManifestForm.jsx +79 -0
  70. package/src/components/ManifestInfo.jsx +67 -0
  71. package/src/components/ManifestListItem.jsx +209 -0
  72. package/src/components/ManifestListItemError.jsx +53 -0
  73. package/src/components/ManifestRelatedLinks.jsx +154 -0
  74. package/src/components/MinimalWindow.jsx +104 -0
  75. package/src/components/MiradorMenuButton.jsx +71 -0
  76. package/src/components/MosaicRenderPreview.jsx +16 -0
  77. package/src/components/NestedMenu.jsx +42 -0
  78. package/src/components/NewBrowserWindow.jsx +34 -0
  79. package/src/components/OpenSeadragonComponent.jsx +258 -0
  80. package/src/components/OpenSeadragonTileSource.jsx +105 -0
  81. package/src/components/OpenSeadragonViewer.jsx +161 -0
  82. package/src/components/PluginHook.jsx +27 -0
  83. package/src/components/PrimaryWindow.jsx +115 -0
  84. package/src/components/SanitizedHtml.jsx +37 -0
  85. package/src/components/ScrollIndicatedDialogContent.jsx +60 -0
  86. package/src/components/ScrollTo.jsx +61 -0
  87. package/src/components/SearchHit.jsx +220 -0
  88. package/src/components/SearchPanel.jsx +80 -0
  89. package/src/components/SearchPanelControls.jsx +174 -0
  90. package/src/components/SearchPanelNavigation.jsx +84 -0
  91. package/src/components/SearchResults.jsx +138 -0
  92. package/src/components/SelectCollection.jsx +44 -0
  93. package/src/components/SidebarIndexItem.jsx +11 -0
  94. package/src/components/SidebarIndexList.jsx +73 -0
  95. package/src/components/SidebarIndexTableOfContents.jsx +170 -0
  96. package/src/components/SidebarIndexThumbnail.jsx +22 -0
  97. package/src/components/TextViewer.jsx +37 -0
  98. package/src/components/ThumbnailCanvasGrouping.jsx +122 -0
  99. package/src/components/ThumbnailNavigation.jsx +231 -0
  100. package/src/components/VideoViewer.jsx +35 -0
  101. package/src/components/ViewerInfo.jsx +55 -0
  102. package/src/components/ViewerNavigation.jsx +72 -0
  103. package/src/components/Window.jsx +150 -0
  104. package/src/components/WindowAuthenticationBar.jsx +176 -0
  105. package/src/components/WindowCanvasNavigationControls.jsx +91 -0
  106. package/src/components/WindowList.jsx +71 -0
  107. package/src/components/WindowListButton.jsx +57 -0
  108. package/src/components/WindowSideBar.jsx +48 -0
  109. package/src/components/WindowSideBarAnnotationsPanel.jsx +51 -0
  110. package/src/components/WindowSideBarButtons.jsx +151 -0
  111. package/src/components/WindowSideBarCanvasPanel.jsx +165 -0
  112. package/src/components/WindowSideBarCollectionPanel.jsx +179 -0
  113. package/src/components/WindowSideBarInfoPanel.jsx +67 -0
  114. package/src/components/WindowThumbnailSettings.jsx +130 -0
  115. package/src/components/WindowTopBar.jsx +125 -0
  116. package/src/components/WindowTopBarPluginArea.jsx +8 -0
  117. package/src/components/WindowTopBarPluginMenu.jsx +78 -0
  118. package/src/components/WindowTopBarTitle.jsx +73 -0
  119. package/src/components/WindowTopMenu.jsx +81 -0
  120. package/src/components/WindowTopMenuButton.jsx +49 -0
  121. package/src/components/WindowViewSettings.jsx +95 -0
  122. package/src/components/WindowViewer.jsx +26 -0
  123. package/src/components/Workspace.jsx +124 -0
  124. package/src/components/WorkspaceAdd.jsx +221 -0
  125. package/src/components/WorkspaceAddButton.jsx +73 -0
  126. package/src/components/WorkspaceArea.jsx +66 -0
  127. package/src/components/WorkspaceControlPanel.jsx +85 -0
  128. package/src/components/WorkspaceControlPanelButtons.jsx +20 -0
  129. package/src/components/WorkspaceDialog.jsx +11 -0
  130. package/src/components/WorkspaceElastic.jsx +88 -0
  131. package/src/components/WorkspaceElasticWindow.jsx +79 -0
  132. package/src/components/WorkspaceExport.jsx +99 -0
  133. package/src/components/WorkspaceImport.jsx +89 -0
  134. package/src/components/WorkspaceMenu.jsx +126 -0
  135. package/src/components/WorkspaceMenuButton.jsx +42 -0
  136. package/src/components/WorkspaceMosaic.jsx +149 -0
  137. package/src/components/WorkspaceOptionsButton.jsx +35 -0
  138. package/src/components/WorkspaceOptionsMenu.jsx +112 -0
  139. package/src/components/WorkspaceSelectionDialog.jsx +165 -0
  140. package/src/components/ZoomControls.jsx +57 -0
  141. package/src/components/icons/BookViewIcon.jsx +14 -0
  142. package/src/components/icons/CanvasIndexIcon.jsx +14 -0
  143. package/src/components/icons/GalleryViewIcon.jsx +17 -0
  144. package/src/components/icons/MiradorIcon.jsx +14 -0
  145. package/src/components/icons/RestoreZoomIcon.jsx +15 -0
  146. package/src/components/icons/ThumbnailNavigationBottomIcon.jsx +15 -0
  147. package/src/components/icons/ThumbnailNavigationRightIcon.jsx +16 -0
  148. package/src/components/icons/WindowMaxIcon.jsx +15 -0
  149. package/src/components/icons/WindowMinIcon.jsx +15 -0
  150. package/src/components/icons/WindowOptionsIcon.jsx +16 -0
  151. package/src/components/icons/WorkspaceTypeElasticIcon.jsx +157 -0
  152. package/src/components/icons/WorkspaceTypeMosaicIcon.jsx +162 -0
  153. package/src/components/icons/index.js +27 -0
  154. package/src/components/index.js +108 -0
  155. package/src/config/css-ns.js +10 -0
  156. package/src/config/index.js +2 -0
  157. package/src/config/settings.js +607 -0
  158. package/src/containers/AnnotationSettings.js +27 -0
  159. package/src/containers/AnnotationsOverlay.js +51 -0
  160. package/src/containers/AppProviders.js +20 -0
  161. package/src/containers/AttributionPanel.js +20 -0
  162. package/src/containers/AudioViewer.js +16 -0
  163. package/src/containers/BackgroundPluginArea.js +4 -0
  164. package/src/containers/Branding.js +4 -0
  165. package/src/containers/CanvasAnnotations.js +32 -0
  166. package/src/containers/CanvasInfo.js +20 -0
  167. package/src/containers/CanvasLayers.js +25 -0
  168. package/src/containers/ChangeThemeDialog.js +29 -0
  169. package/src/containers/CollapsibleSection.js +3 -0
  170. package/src/containers/CollectionDialog.js +48 -0
  171. package/src/containers/CollectionInfo.js +29 -0
  172. package/src/containers/CompanionArea.js +22 -0
  173. package/src/containers/CompanionWindow.js +40 -0
  174. package/src/containers/CompanionWindowFactory.js +23 -0
  175. package/src/containers/CustomPanel.js +13 -0
  176. package/src/containers/ErrorContent.js +20 -0
  177. package/src/containers/ErrorDialog.js +28 -0
  178. package/src/containers/FullScreenButton.js +22 -0
  179. package/src/containers/GalleryView.js +23 -0
  180. package/src/containers/GalleryViewThumbnail.js +51 -0
  181. package/src/containers/IIIFAuthentication.js +86 -0
  182. package/src/containers/IIIFThumbnail.js +17 -0
  183. package/src/containers/LabelValueMetadata.js +14 -0
  184. package/src/containers/LanguageSettings.js +26 -0
  185. package/src/containers/LayersPanel.js +16 -0
  186. package/src/containers/LocalePicker.js +3 -0
  187. package/src/containers/ManifestForm.js +16 -0
  188. package/src/containers/ManifestInfo.js +29 -0
  189. package/src/containers/ManifestListItem.js +52 -0
  190. package/src/containers/ManifestListItemError.js +15 -0
  191. package/src/containers/ManifestRelatedLinks.js +28 -0
  192. package/src/containers/MinimalWindow.js +25 -0
  193. package/src/containers/MiradorMenuButton.js +7 -0
  194. package/src/containers/MosaicRenderPreview.js +14 -0
  195. package/src/containers/OpenSeadragonViewer.js +59 -0
  196. package/src/containers/PrimaryWindow.js +27 -0
  197. package/src/containers/SanitizedHtml.js +3 -0
  198. package/src/containers/ScrollIndicatedDialogContent.js +3 -0
  199. package/src/containers/SearchHit.js +71 -0
  200. package/src/containers/SearchPanel.js +23 -0
  201. package/src/containers/SearchPanelControls.js +36 -0
  202. package/src/containers/SearchPanelNavigation.js +39 -0
  203. package/src/containers/SearchResults.js +38 -0
  204. package/src/containers/SelectCollection.js +24 -0
  205. package/src/containers/SidebarIndexItem.js +8 -0
  206. package/src/containers/SidebarIndexList.js +28 -0
  207. package/src/containers/SidebarIndexTableOfContents.js +31 -0
  208. package/src/containers/SidebarIndexThumbnail.js +18 -0
  209. package/src/containers/TextViewer.js +19 -0
  210. package/src/containers/ThumbnailCanvasGrouping.js +29 -0
  211. package/src/containers/ThumbnailNavigation.js +48 -0
  212. package/src/containers/VideoViewer.js +16 -0
  213. package/src/containers/ViewerInfo.js +30 -0
  214. package/src/containers/ViewerNavigation.js +31 -0
  215. package/src/containers/Window.js +45 -0
  216. package/src/containers/WindowAuthenticationBar.js +7 -0
  217. package/src/containers/WindowCanvasNavigationControls.js +15 -0
  218. package/src/containers/WindowList.js +30 -0
  219. package/src/containers/WindowListButton.js +15 -0
  220. package/src/containers/WindowSideBar.js +20 -0
  221. package/src/containers/WindowSideBarAnnotationsPanel.js +23 -0
  222. package/src/containers/WindowSideBarButtons.js +75 -0
  223. package/src/containers/WindowSideBarCanvasPanel.js +50 -0
  224. package/src/containers/WindowSideBarCollectionPanel.js +48 -0
  225. package/src/containers/WindowSideBarInfoPanel.js +35 -0
  226. package/src/containers/WindowThumbnailSettings.js +31 -0
  227. package/src/containers/WindowTopBar.js +39 -0
  228. package/src/containers/WindowTopBarPluginArea.js +8 -0
  229. package/src/containers/WindowTopBarPluginMenu.js +7 -0
  230. package/src/containers/WindowTopBarTitle.js +17 -0
  231. package/src/containers/WindowTopMenu.js +28 -0
  232. package/src/containers/WindowTopMenuButton.js +7 -0
  233. package/src/containers/WindowViewSettings.js +30 -0
  234. package/src/containers/WindowViewer.js +10 -0
  235. package/src/containers/Workspace.js +36 -0
  236. package/src/containers/WorkspaceAdd.js +27 -0
  237. package/src/containers/WorkspaceAddButton.js +30 -0
  238. package/src/containers/WorkspaceArea.js +21 -0
  239. package/src/containers/WorkspaceControlPanel.js +10 -0
  240. package/src/containers/WorkspaceControlPanelButtons.js +7 -0
  241. package/src/containers/WorkspaceElastic.js +41 -0
  242. package/src/containers/WorkspaceElasticWindow.js +36 -0
  243. package/src/containers/WorkspaceExport.js +18 -0
  244. package/src/containers/WorkspaceImport.js +19 -0
  245. package/src/containers/WorkspaceMenu.js +30 -0
  246. package/src/containers/WorkspaceMenuButton.js +10 -0
  247. package/src/containers/WorkspaceMosaic.js +32 -0
  248. package/src/containers/WorkspaceOptionsButton.js +7 -0
  249. package/src/containers/WorkspaceOptionsMenu.js +3 -0
  250. package/src/containers/WorkspaceSelectionDialog.js +26 -0
  251. package/src/containers/ZoomControls.js +26 -0
  252. package/src/containers/index.js +94 -0
  253. package/src/contexts/FailedImageContext.js +8 -0
  254. package/src/contexts/FailedImageProvider.jsx +34 -0
  255. package/src/contexts/FullScreenContext.js +5 -0
  256. package/src/contexts/LocaleContext.js +5 -0
  257. package/src/contexts/OpenSeadragonViewerContext.js +5 -0
  258. package/src/contexts/WorkspaceContext.js +5 -0
  259. package/src/contexts/index.js +4 -0
  260. package/src/extend/PluginContext.js +5 -0
  261. package/src/extend/PluginProvider.jsx +22 -0
  262. package/src/extend/index.js +9 -0
  263. package/src/extend/pluginMapping.js +44 -0
  264. package/src/extend/pluginPreprocessing.js +45 -0
  265. package/src/extend/pluginValidation.js +58 -0
  266. package/src/extend/usePlugins.js +13 -0
  267. package/src/extend/withPlugins.jsx +46 -0
  268. package/src/hooks/index.js +4 -0
  269. package/src/hooks/useCanvasWorldService.js +10 -0
  270. package/src/hooks/useThumbnailService.js +8 -0
  271. package/src/i18n.js +71 -0
  272. package/src/index.js +18 -0
  273. package/src/init.js +20 -0
  274. package/src/lib/AnnotationFactory.js +23 -0
  275. package/src/lib/AnnotationItem.js +123 -0
  276. package/src/lib/AnnotationList.js +31 -0
  277. package/src/lib/AnnotationPage.js +41 -0
  278. package/src/lib/AnnotationResource.js +122 -0
  279. package/src/lib/CanvasAnnotationDisplay.js +148 -0
  280. package/src/lib/CanvasGroupings.js +55 -0
  281. package/src/lib/CanvasWorld.js +214 -0
  282. package/src/lib/CompanionWindowRegistry.js +23 -0
  283. package/src/lib/FullScreenHandle.jsx +76 -0
  284. package/src/lib/MiradorCanvas.js +211 -0
  285. package/src/lib/MiradorManifest.js +44 -0
  286. package/src/lib/MiradorViewer.jsx +53 -0
  287. package/src/lib/MosaicLayout.js +77 -0
  288. package/src/lib/OpenSeadragonCanvasOverlay.js +114 -0
  289. package/src/lib/ThumbnailFactory.js +310 -0
  290. package/src/lib/TruncatedHit.js +34 -0
  291. package/src/lib/asArray.js +11 -0
  292. package/src/lib/htmlRules.js +28 -0
  293. package/src/lib/iiif.js +12 -0
  294. package/src/lib/index.js +23 -0
  295. package/src/lib/readImageMetadata.js +21 -0
  296. package/src/lib/svgShapesToPath.js +49 -0
  297. package/src/locales/README.md +60 -0
  298. package/src/locales/ar/translation.json +141 -0
  299. package/src/locales/bg/translation.json +164 -0
  300. package/src/locales/de/translation.json +169 -0
  301. package/src/locales/en/translation.json +170 -0
  302. package/src/locales/et/translation.json +164 -0
  303. package/src/locales/fa/translation.json +164 -0
  304. package/src/locales/fr/translation.json +158 -0
  305. package/src/locales/hr/translation.json +164 -0
  306. package/src/locales/hu/translation.json +166 -0
  307. package/src/locales/it/translation.json +162 -0
  308. package/src/locales/ja/translation.json +156 -0
  309. package/src/locales/kr/translation.json +162 -0
  310. package/src/locales/lt/translation.json +153 -0
  311. package/src/locales/nbNo/translation.json +162 -0
  312. package/src/locales/nl/translation.json +139 -0
  313. package/src/locales/pl/translation.json +162 -0
  314. package/src/locales/ptBr/translation.json +133 -0
  315. package/src/locales/sr/translation.json +155 -0
  316. package/src/locales/sv/translation.json +157 -0
  317. package/src/locales/ta/translation.json +167 -0
  318. package/src/locales/vi/translation.json +156 -0
  319. package/src/locales/zhCn/translation.json +163 -0
  320. package/src/locales/zhTw/translation.json +163 -0
  321. package/src/plugins/OSDReferences.js +15 -0
  322. package/src/plugins/index.js +1 -0
  323. package/src/state/actions/action-types.js +76 -0
  324. package/src/state/actions/annotation.js +123 -0
  325. package/src/state/actions/auth.js +109 -0
  326. package/src/state/actions/canvas.js +65 -0
  327. package/src/state/actions/catalog.js +22 -0
  328. package/src/state/actions/companionWindow.js +107 -0
  329. package/src/state/actions/config.js +49 -0
  330. package/src/state/actions/elasticLayout.js +10 -0
  331. package/src/state/actions/errors.js +22 -0
  332. package/src/state/actions/index.js +19 -0
  333. package/src/state/actions/infoResponse.js +90 -0
  334. package/src/state/actions/layers.js +14 -0
  335. package/src/state/actions/manifest.js +65 -0
  336. package/src/state/actions/search.js +97 -0
  337. package/src/state/actions/window.js +209 -0
  338. package/src/state/actions/workspace.js +84 -0
  339. package/src/state/createPluggableStore.js +24 -0
  340. package/src/state/createStore.js +33 -0
  341. package/src/state/index.js +21 -0
  342. package/src/state/reducers/accessTokens.js +59 -0
  343. package/src/state/reducers/annotations.js +48 -0
  344. package/src/state/reducers/auth.js +43 -0
  345. package/src/state/reducers/catalog.js +30 -0
  346. package/src/state/reducers/companionWindows.js +49 -0
  347. package/src/state/reducers/config.js +39 -0
  348. package/src/state/reducers/elasticLayout.js +29 -0
  349. package/src/state/reducers/errors.js +51 -0
  350. package/src/state/reducers/index.js +15 -0
  351. package/src/state/reducers/infoResponses.js +61 -0
  352. package/src/state/reducers/layers.js +23 -0
  353. package/src/state/reducers/manifests.js +52 -0
  354. package/src/state/reducers/rootReducer.js +44 -0
  355. package/src/state/reducers/search.js +145 -0
  356. package/src/state/reducers/utils.js +45 -0
  357. package/src/state/reducers/viewers.js +42 -0
  358. package/src/state/reducers/windows.js +185 -0
  359. package/src/state/reducers/workspace.js +111 -0
  360. package/src/state/sagas/annotations.js +48 -0
  361. package/src/state/sagas/app.js +56 -0
  362. package/src/state/sagas/auth.js +151 -0
  363. package/src/state/sagas/iiif.js +233 -0
  364. package/src/state/sagas/index.js +30 -0
  365. package/src/state/sagas/windows.js +293 -0
  366. package/src/state/selectors/annotations.js +138 -0
  367. package/src/state/selectors/auth.js +100 -0
  368. package/src/state/selectors/canvases.js +260 -0
  369. package/src/state/selectors/companionWindows.js +182 -0
  370. package/src/state/selectors/config.js +100 -0
  371. package/src/state/selectors/getters.js +90 -0
  372. package/src/state/selectors/index.js +17 -0
  373. package/src/state/selectors/layers.js +79 -0
  374. package/src/state/selectors/manifests.js +433 -0
  375. package/src/state/selectors/ranges.js +147 -0
  376. package/src/state/selectors/searches.js +249 -0
  377. package/src/state/selectors/sequences.js +134 -0
  378. package/src/state/selectors/thumbnails.js +28 -0
  379. package/src/state/selectors/utils.js +18 -0
  380. package/src/state/selectors/viewer.js +19 -0
  381. package/src/state/selectors/windows.js +98 -0
  382. package/src/state/selectors/workspace.js +52 -0
  383. package/src/state/selectors/wrappers.js +15 -0
  384. package/src/styles/react-mosaic-component.js +288 -0
@@ -0,0 +1,328 @@
1
+ import { useRef, useEffect, useCallback, useMemo } from 'react';
2
+ import ReactDOM from 'react-dom';
3
+ import PropTypes from 'prop-types';
4
+ import { useDebouncedCallback } from 'use-debounce';
5
+ import sortBy from 'lodash/sortBy';
6
+ import xor from 'lodash/xor';
7
+ import OpenSeadragonCanvasOverlay from '../lib/OpenSeadragonCanvasOverlay';
8
+ import CanvasWorld from '../lib/CanvasWorld';
9
+ import CanvasAnnotationDisplay from '../lib/CanvasAnnotationDisplay';
10
+ import { buildPath2D } from '../lib/svgShapesToPath';
11
+
12
+ /** @private */
13
+ function isAnnotationAtPoint(canvasWorld, osdCanvasOverlay, resource, canvas, point) {
14
+ const [canvasX, canvasY] = canvasWorld.canvasToWorldCoordinates(canvas.id);
15
+ const relativeX = point.x - canvasX;
16
+ const relativeY = point.y - canvasY;
17
+
18
+ if (resource.svgSelector) {
19
+ const context = osdCanvasOverlay.context2d;
20
+ const { svgPaths } = new CanvasAnnotationDisplay({ resource });
21
+ return [...svgPaths].some((path) => context.isPointInPath(buildPath2D(path), relativeX, relativeY));
22
+ }
23
+
24
+ if (resource.fragmentSelector) {
25
+ const [x, y, w, h] = resource.fragmentSelector;
26
+ return x <= relativeX && relativeX <= x + w && y <= relativeY && relativeY <= y + h;
27
+ }
28
+ return false;
29
+ }
30
+
31
+ /**
32
+ * See: https://openseadragon.github.io/docs/OpenSeadragon.Viewer.html#.event:canvas-click
33
+ * Gestures returned from this method are likely viewer interactions such as pan and zoom,
34
+ * not taps and clicks targeted to an annotation.
35
+ * In deciding whether to change the display of the annotation overlay,
36
+ * we want to ignore these irrelevant gestures.
37
+ * @private
38
+ */
39
+ function isIgnoredGesture(event) {
40
+ const pointerType = event.originalEvent?.pointerType;
41
+ return (pointerType === 'touch' || pointerType === 'pen') && event.quick === false;
42
+ }
43
+
44
+ /**
45
+ * Represents a OpenSeadragonViewer in the mirador workspace. Responsible for mounting
46
+ * and rendering OSD.
47
+ */
48
+ export function AnnotationsOverlay({
49
+ annotations = [],
50
+ canvasWorld,
51
+ deselectAnnotation = () => {},
52
+ drawAnnotations = true,
53
+ drawSearchAnnotations = true,
54
+ highlightAllAnnotations = false,
55
+ hoverAnnotation = () => {},
56
+ hoveredAnnotationIds = [],
57
+ palette = {},
58
+ searchAnnotations = [],
59
+ selectAnnotation = () => {},
60
+ selectedAnnotationId = null,
61
+ viewer = null,
62
+ windowId,
63
+ }) {
64
+ const ref = useRef();
65
+
66
+ const osdCanvasOverlay = useMemo(() => new OpenSeadragonCanvasOverlay(viewer, ref), [ref, viewer]);
67
+
68
+ const toggleAnnotation = useCallback(
69
+ (id) => {
70
+ if (selectedAnnotationId === id) {
71
+ deselectAnnotation(windowId, id);
72
+ } else {
73
+ selectAnnotation(windowId, id);
74
+ }
75
+ },
76
+ [selectedAnnotationId, deselectAnnotation, selectAnnotation, windowId],
77
+ );
78
+
79
+ /**
80
+ * annotationsToContext - converts anontations to a canvas context
81
+ */
82
+ const annotationsToContext = useCallback(
83
+ (renderedAnnotations, currentPalette) => {
84
+ const context = osdCanvasOverlay.context2d;
85
+ renderedAnnotations.forEach((annotation) => {
86
+ annotation.resources.forEach((resource) => {
87
+ const osdCanvasIndex = canvasWorld.canvases.findIndex((canvas) => canvas.id === resource.targetId);
88
+ if (osdCanvasIndex === -1) return;
89
+ const viewportCanvas = viewer.world.getItemAt(osdCanvasIndex);
90
+ if (!viewportCanvas) return;
91
+ const offset = canvasWorld.offsetByCanvas(resource.targetId);
92
+ const zoomRatio = viewportCanvas.viewportToImageZoom(viewer.viewport.getZoom(true));
93
+ const canvasAnnotationDisplay = new CanvasAnnotationDisplay({
94
+ hovered: hoveredAnnotationIds.includes(resource.id),
95
+ offset,
96
+ palette: {
97
+ ...currentPalette,
98
+ default: {
99
+ ...currentPalette.default,
100
+ ...(!highlightAllAnnotations && currentPalette.hidden),
101
+ },
102
+ },
103
+ resource,
104
+ selected: selectedAnnotationId === resource.id,
105
+ zoomRatio,
106
+ });
107
+ canvasAnnotationDisplay.toContext(context);
108
+ });
109
+ });
110
+ },
111
+ [osdCanvasOverlay, viewer, canvasWorld, highlightAllAnnotations, hoveredAnnotationIds, selectedAnnotationId],
112
+ );
113
+
114
+ const renderAnnotations = useCallback(() => {
115
+ if (drawSearchAnnotations) {
116
+ annotationsToContext(searchAnnotations, palette.search);
117
+ }
118
+
119
+ if (drawAnnotations) {
120
+ annotationsToContext(annotations, palette.annotations);
121
+ }
122
+ }, [annotations, annotationsToContext, drawAnnotations, drawSearchAnnotations, palette, searchAnnotations]);
123
+
124
+ const updateCanvas = useCallback(() => {
125
+ if (!osdCanvasOverlay) return;
126
+
127
+ osdCanvasOverlay.clear();
128
+ osdCanvasOverlay.resize();
129
+ osdCanvasOverlay.canvasUpdate(renderAnnotations);
130
+ }, [osdCanvasOverlay, renderAnnotations]);
131
+
132
+ const annotationsAtPoint = useCallback(
133
+ (canvas, point) => {
134
+ const lists = [...annotations, ...searchAnnotations];
135
+ const annos = lists
136
+ .flatMap((l) => l.resources)
137
+ .filter((resource) => {
138
+ if (canvas.id !== resource.targetId) return false;
139
+
140
+ return isAnnotationAtPoint(canvasWorld, osdCanvasOverlay, resource, canvas, point);
141
+ });
142
+
143
+ return annos;
144
+ },
145
+ [annotations, canvasWorld, osdCanvasOverlay, searchAnnotations],
146
+ );
147
+
148
+ const onCanvasClick = useCallback(
149
+ (event) => {
150
+ if (isIgnoredGesture(event)) return;
151
+
152
+ const {
153
+ position: webPosition,
154
+ eventSource: { viewport },
155
+ } = event;
156
+ const point = viewport.pointFromPixel(webPosition);
157
+
158
+ const canvas = canvasWorld.canvasAtPoint(point);
159
+ if (!canvas) return;
160
+ const [_canvasX, _canvasY, canvasWidth, canvasHeight] = canvasWorld.canvasToWorldCoordinates(canvas.id);
161
+
162
+ // get all the annotations that contain the click
163
+ const annos = annotationsAtPoint(canvas, point);
164
+
165
+ if (annos.length > 0) {
166
+ event.preventDefaultAction = true; // eslint-disable-line no-param-reassign
167
+ }
168
+
169
+ if (annos.length === 1) {
170
+ toggleAnnotation(annos[0].id);
171
+ } else if (annos.length > 0) {
172
+ /**
173
+ * Try to find the "right" annotation to select after a click.
174
+ *
175
+ * This is perhaps a naive method, but seems to deal with rectangles and SVG shapes:
176
+ *
177
+ * - figure out how many points around a circle are inside the annotation shape
178
+ * - if there's a shape with the fewest interior points, it's probably the one
179
+ * with the closest boundary?
180
+ * - if there's a tie, make the circle bigger and try again.
181
+ */
182
+ const annosWithClickScore = (radius) => {
183
+ const degreesToRadians = Math.PI / 180;
184
+
185
+ return (anno) => {
186
+ let score = 0;
187
+ for (let degrees = 0; degrees < 360; degrees += 1) {
188
+ const x = Math.cos(degrees * degreesToRadians) * radius + point.x;
189
+ const y = Math.sin(degrees * degreesToRadians) * radius + point.y;
190
+
191
+ if (isAnnotationAtPoint(canvasWorld, osdCanvasOverlay, anno, canvas, { x, y })) score += 1;
192
+ }
193
+
194
+ return { anno, score };
195
+ };
196
+ };
197
+
198
+ let radius = 1;
199
+ let annosWithScore = sortBy(annos.map(annosWithClickScore(radius)), 'score');
200
+
201
+ while (radius < Math.max(canvasWidth, canvasHeight) && annosWithScore[0].score === annosWithScore[1].score) {
202
+ radius *= 2;
203
+ annosWithScore = sortBy(annos.map(annosWithClickScore(radius)), 'score');
204
+ }
205
+
206
+ toggleAnnotation(annosWithScore[0].anno.id);
207
+ }
208
+ },
209
+ [annotationsAtPoint, canvasWorld, osdCanvasOverlay, toggleAnnotation],
210
+ );
211
+
212
+ const onCanvasMouseMove = useDebouncedCallback(
213
+ useCallback(
214
+ (event) => {
215
+ if (annotations.length === 0 && searchAnnotations.length === 0) return;
216
+
217
+ const { position: webPosition } = event;
218
+ const point = viewer.viewport.pointFromPixel(webPosition);
219
+
220
+ const canvas = canvasWorld.canvasAtPoint(point);
221
+ if (!canvas) {
222
+ hoverAnnotation(windowId, []);
223
+ return;
224
+ }
225
+
226
+ const annos = annotationsAtPoint(canvas, point);
227
+
228
+ if (
229
+ xor(
230
+ hoveredAnnotationIds,
231
+ annos.map((a) => a.id),
232
+ ).length > 0
233
+ ) {
234
+ hoverAnnotation(
235
+ windowId,
236
+ annos.map((a) => a.id),
237
+ );
238
+ }
239
+ },
240
+ [annotations, annotationsAtPoint, canvasWorld, hoverAnnotation, hoveredAnnotationIds, searchAnnotations, viewer, windowId],
241
+ ),
242
+ 10,
243
+ );
244
+
245
+ const onCanvasExit = useCallback(() => {
246
+ // a move event may be queued up by the debouncer
247
+ onCanvasMouseMove.cancel();
248
+ hoverAnnotation(windowId, []);
249
+ }, [hoverAnnotation, onCanvasMouseMove, windowId]);
250
+
251
+ const onUpdateViewport = useCallback(() => {
252
+ updateCanvas();
253
+ }, [updateCanvas]);
254
+
255
+ useEffect(() => {
256
+ if (!viewer) return undefined;
257
+
258
+ viewer.addHandler('canvas-click', onCanvasClick);
259
+ viewer.addHandler('canvas-exit', onCanvasExit);
260
+ viewer.addHandler('mouse-move', onCanvasMouseMove);
261
+ viewer.addHandler('update-viewport', onUpdateViewport);
262
+
263
+ return () => {
264
+ viewer.removeHandler('canvas-click', onCanvasClick);
265
+ viewer.removeHandler('canvas-exit', onCanvasExit);
266
+ viewer.removeHandler('mouse-move', onCanvasMouseMove);
267
+ viewer.removeHandler('update-viewport', onUpdateViewport);
268
+ };
269
+ }, [onCanvasClick, onCanvasExit, onCanvasMouseMove, onUpdateViewport, viewer]);
270
+
271
+ useEffect(() => {
272
+ if (viewer) viewer.forceRedraw();
273
+ }, [
274
+ annotations,
275
+ drawAnnotations,
276
+ drawSearchAnnotations,
277
+ highlightAllAnnotations,
278
+ hoveredAnnotationIds,
279
+ searchAnnotations,
280
+ selectedAnnotationId,
281
+ viewer,
282
+ ]);
283
+
284
+ useEffect(() => {
285
+ if (!ref.current) return;
286
+
287
+ if (hoveredAnnotationIds.length > 0) {
288
+ ref.current.style.cursor = 'pointer';
289
+ } else {
290
+ ref.current.style.cursor = '';
291
+ }
292
+ }, [hoveredAnnotationIds, ref]);
293
+
294
+ if (!viewer) return null;
295
+
296
+ return ReactDOM.createPortal(
297
+ <div
298
+ ref={ref}
299
+ style={{
300
+ height: '100%',
301
+ left: 0,
302
+ position: 'absolute',
303
+ top: 0,
304
+ width: '100%',
305
+ }}
306
+ >
307
+ <canvas />
308
+ </div>,
309
+ viewer.canvas,
310
+ );
311
+ }
312
+
313
+ AnnotationsOverlay.propTypes = {
314
+ annotations: PropTypes.arrayOf(PropTypes.object),
315
+ canvasWorld: PropTypes.instanceOf(CanvasWorld).isRequired,
316
+ deselectAnnotation: PropTypes.func,
317
+ drawAnnotations: PropTypes.bool,
318
+ drawSearchAnnotations: PropTypes.bool,
319
+ highlightAllAnnotations: PropTypes.bool,
320
+ hoverAnnotation: PropTypes.func,
321
+ hoveredAnnotationIds: PropTypes.arrayOf(PropTypes.string),
322
+ palette: PropTypes.object,
323
+ searchAnnotations: PropTypes.arrayOf(PropTypes.object),
324
+ selectAnnotation: PropTypes.func,
325
+ selectedAnnotationId: PropTypes.string,
326
+ viewer: PropTypes.object,
327
+ windowId: PropTypes.string.isRequired,
328
+ };
@@ -0,0 +1,34 @@
1
+ import { createRef, lazy, Suspense } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import PluginProvider from '../extend/PluginProvider';
4
+ import AppProviders from '../containers/AppProviders';
5
+ import WorkspaceContext from '../contexts/WorkspaceContext';
6
+
7
+ const WorkspaceArea = lazy(() => import('../containers/WorkspaceArea'));
8
+
9
+ /**
10
+ * This is the top level Mirador component.
11
+ * @prop {Object} manifests
12
+ */
13
+ export function App({ dndManager = undefined, plugins = [] }) {
14
+ const areaRef = createRef();
15
+
16
+ return (
17
+ <PluginProvider plugins={plugins}>
18
+ <AppProviders dndManager={dndManager}>
19
+ <WorkspaceContext.Provider value={areaRef}>
20
+ <Suspense fallback={<div />}>
21
+ <WorkspaceArea areaRef={areaRef} />
22
+ </Suspense>
23
+ </WorkspaceContext.Provider>
24
+ </AppProviders>
25
+ </PluginProvider>
26
+ );
27
+ }
28
+
29
+ App.propTypes = {
30
+ dndManager: PropTypes.object,
31
+ plugins: PropTypes.array,
32
+ };
33
+
34
+ export default App;
@@ -0,0 +1,129 @@
1
+ import { useState, useEffect } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { I18nextProvider } from 'react-i18next';
4
+ import { ThemeProvider, StyledEngineProvider, createTheme } from '@mui/material/styles';
5
+ import { DndContext, DndProvider } from 'react-dnd';
6
+ import { MultiBackend } from 'react-dnd-multi-backend';
7
+ import { HTML5toTouch } from 'rdndmb-html5-to-touch';
8
+ import rtlPlugin from 'stylis-plugin-rtl';
9
+ import { prefixer } from 'stylis';
10
+ import { CacheProvider } from '@emotion/react';
11
+ import createCache from '@emotion/cache';
12
+ import createI18nInstance from '../i18n';
13
+ import FailedImageProvider from '../contexts/FailedImageProvider';
14
+ import { FullScreen, useFullScreenHandle } from '../lib/FullScreenHandle';
15
+ import FullScreenContext from '../contexts/FullScreenContext';
16
+ import LocaleContext from '../contexts/LocaleContext';
17
+
18
+ /**
19
+ * Allow applications to opt-out of (or provide their own) drag and drop context
20
+ */
21
+ const MaybeDndProvider = ({ dndManager = undefined, children }) => {
22
+ if (dndManager === false) {
23
+ return children;
24
+ }
25
+
26
+ if (dndManager === undefined) {
27
+ return (
28
+ <DndProvider backend={MultiBackend} options={HTML5toTouch}>
29
+ {children}
30
+ </DndProvider>
31
+ );
32
+ }
33
+
34
+ return <DndContext.Provider value={dndManager}>{children}</DndContext.Provider>;
35
+ };
36
+
37
+ MaybeDndProvider.propTypes = {
38
+ children: PropTypes.node.isRequired,
39
+ dndManager: PropTypes.oneOf([undefined, false, PropTypes.object]),
40
+ };
41
+
42
+ /**
43
+ * Shim to inject the full screen handle into a context
44
+ */
45
+ const FullScreenShim = ({ children }) => {
46
+ const handle = useFullScreenHandle();
47
+
48
+ return (
49
+ <FullScreen handle={handle}>
50
+ <FullScreenContext.Provider value={handle}>{children}</FullScreenContext.Provider>
51
+ </FullScreen>
52
+ );
53
+ };
54
+
55
+ FullScreenShim.propTypes = {
56
+ children: PropTypes.node.isRequired,
57
+ };
58
+
59
+ /**
60
+ * Hook up the I18next provider to the configuration in redux to allow
61
+ * plugins + config to inject additional translations.
62
+ */
63
+ const StoreAwareI18nextProvider = ({ children, language, translations }) => {
64
+ const [i18n] = useState(createI18nInstance({ lng: language }));
65
+ useEffect(() => {
66
+ if (i18n && i18n.language !== language) i18n.changeLanguage(language);
67
+ }, [i18n, language]);
68
+
69
+ useEffect(() => {
70
+ Object.keys(translations).forEach((lng) => {
71
+ i18n.addResourceBundle(lng, 'translation', translations[lng], true, true);
72
+ });
73
+ }, [i18n, translations]);
74
+
75
+ return <I18nextProvider i18n={i18n}>{children}</I18nextProvider>;
76
+ };
77
+
78
+ StoreAwareI18nextProvider.propTypes = {
79
+ children: PropTypes.node.isRequired,
80
+ language: PropTypes.string.isRequired,
81
+ translations: PropTypes.object.isRequired,
82
+ };
83
+
84
+ /**
85
+ * Create rtl emotion cache
86
+ */
87
+ const cacheRtl = createCache({
88
+ key: 'muirtl',
89
+ stylisPlugins: [prefixer, rtlPlugin],
90
+ });
91
+
92
+ /**
93
+ * Create default emotion cache
94
+ */
95
+ const cacheDefault = createCache({
96
+ key: 'mui',
97
+ });
98
+
99
+ /**
100
+ * This component adds viewer-specific providers.
101
+ * @prop {Object} manifests
102
+ */
103
+ export function AppProviders({ children = null, language, theme, translations, dndManager = undefined }) {
104
+ return (
105
+ <FullScreenShim>
106
+ <StoreAwareI18nextProvider language={language} translations={translations}>
107
+ <LocaleContext.Provider value={language}>
108
+ <StyledEngineProvider injectFirst>
109
+ <CacheProvider value={theme.direction === 'rtl' ? cacheRtl : cacheDefault}>
110
+ <ThemeProvider theme={createTheme(theme)}>
111
+ <MaybeDndProvider dndManager={dndManager}>
112
+ <FailedImageProvider>{children}</FailedImageProvider>
113
+ </MaybeDndProvider>
114
+ </ThemeProvider>
115
+ </CacheProvider>
116
+ </StyledEngineProvider>
117
+ </LocaleContext.Provider>
118
+ </StoreAwareI18nextProvider>
119
+ </FullScreenShim>
120
+ );
121
+ }
122
+
123
+ AppProviders.propTypes = {
124
+ children: PropTypes.node,
125
+ dndManager: PropTypes.object,
126
+ language: PropTypes.string.isRequired,
127
+ theme: PropTypes.object.isRequired,
128
+ translations: PropTypes.object.isRequired,
129
+ };
@@ -0,0 +1,78 @@
1
+ import PropTypes from 'prop-types';
2
+ import { styled } from '@mui/material/styles';
3
+ import Typography from '@mui/material/Typography';
4
+ import Link from '@mui/material/Link';
5
+ import Skeleton from '@mui/material/Skeleton';
6
+ import { useTranslation } from 'react-i18next';
7
+ import { Img } from 'react-image';
8
+ import CompanionWindow from '../containers/CompanionWindow';
9
+ import { CompanionWindowSection } from './CompanionWindowSection';
10
+ import LabelValueMetadata from '../containers/LabelValueMetadata';
11
+ import ns from '../config/css-ns';
12
+ import { PluginHook } from './PluginHook';
13
+
14
+ const StyledLogo = styled(Img)(() => ({
15
+ maxWidth: '100%',
16
+ }));
17
+
18
+ const StyledPlaceholder = styled(Skeleton)(({ theme }) => ({
19
+ backgroundColor: theme.palette.grey[300],
20
+ }));
21
+
22
+ /**
23
+ * WindowSideBarInfoPanel
24
+ */
25
+ export function AttributionPanel({ manifestLogo = null, requiredStatement = null, rights = null, windowId, id }) {
26
+ const { t } = useTranslation();
27
+
28
+ // eslint-disable-next-line prefer-rest-params
29
+ const pluginProps = arguments[0];
30
+
31
+ return (
32
+ <CompanionWindow title={t('attributionTitle')} paperClassName={ns('attribution-panel')} windowId={windowId} id={id}>
33
+ <CompanionWindowSection>
34
+ {requiredStatement && <LabelValueMetadata labelValuePairs={requiredStatement} defaultLabel={t('attribution')} />}
35
+ {rights && rights.length > 0 && (
36
+ <dl className={ns('label-value-metadata')}>
37
+ <Typography variant="subtitle2" component="dt">
38
+ {t('rights')}
39
+ </Typography>
40
+ {rights.map((v) => (
41
+ <Typography variant="body1" component="dd" key={v.toString()}>
42
+ <Link target="_blank" rel="noopener noreferrer" href={v}>
43
+ {v}
44
+ </Link>
45
+ </Typography>
46
+ ))}
47
+ </dl>
48
+ )}
49
+ </CompanionWindowSection>
50
+
51
+ {manifestLogo && (
52
+ <CompanionWindowSection>
53
+ <StyledLogo
54
+ src={[manifestLogo]}
55
+ alt=""
56
+ role="presentation"
57
+ unloader={<StyledPlaceholder variant="rectangular" height={60} width={60} />}
58
+ />
59
+ </CompanionWindowSection>
60
+ )}
61
+
62
+ <PluginHook targetName="AttributionPanel" {...pluginProps} />
63
+ </CompanionWindow>
64
+ );
65
+ }
66
+
67
+ AttributionPanel.propTypes = {
68
+ id: PropTypes.string.isRequired,
69
+ manifestLogo: PropTypes.string,
70
+ requiredStatement: PropTypes.arrayOf(
71
+ PropTypes.shape({
72
+ label: PropTypes.string,
73
+ value: PropTypes.string,
74
+ }),
75
+ ),
76
+ rights: PropTypes.arrayOf(PropTypes.string),
77
+ windowId: PropTypes.string.isRequired,
78
+ };
@@ -0,0 +1,39 @@
1
+ import { Fragment } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { styled } from '@mui/material/styles';
4
+
5
+ const StyledContainer = styled('div')({
6
+ alignItems: 'center',
7
+ display: 'flex',
8
+ width: '100%',
9
+ });
10
+
11
+ const StyledAudio = styled('audio')({
12
+ width: '100%',
13
+ });
14
+
15
+ /** */
16
+ export function AudioViewer({ audioOptions = {}, audioResources = [], captions = [] }) {
17
+ return (
18
+ <StyledContainer>
19
+ <StyledAudio {...audioOptions}>
20
+ {audioResources.map((audio) => (
21
+ <Fragment key={audio.id}>
22
+ <source src={audio.id} type={audio.getFormat()} />
23
+ </Fragment>
24
+ ))}
25
+ {captions.map((caption) => (
26
+ <Fragment key={caption.id}>
27
+ <track src={caption.id} label={caption.getDefaultLabel()} srcLang={caption.getProperty('language')} />
28
+ </Fragment>
29
+ ))}
30
+ </StyledAudio>
31
+ </StyledContainer>
32
+ );
33
+ }
34
+
35
+ AudioViewer.propTypes = {
36
+ audioOptions: PropTypes.object,
37
+ audioResources: PropTypes.arrayOf(PropTypes.object),
38
+ captions: PropTypes.arrayOf(PropTypes.object),
39
+ };
@@ -0,0 +1,9 @@
1
+ import ns from '../config/css-ns';
2
+ import { PluginHook } from './PluginHook';
3
+
4
+ /** invisible area where background plugins can add to */
5
+ export const BackgroundPluginArea = ({ ...props }) => (
6
+ <div className={ns('background-plugin-area')} style={{ display: 'none' }}>
7
+ <PluginHook targetName="BackgroundPluginArea" {...props} />
8
+ </div>
9
+ );
@@ -0,0 +1,33 @@
1
+ import PropTypes from 'prop-types';
2
+ import IconButton from '@mui/material/IconButton';
3
+ import Typography from '@mui/material/Typography';
4
+ import Stack from '@mui/material/Stack';
5
+ import { useTranslation } from 'react-i18next';
6
+ import MiradorIcon from './icons/MiradorIcon';
7
+
8
+ /**
9
+ * Display a branding icon
10
+ */
11
+ export function Branding({ variant = 'default', ...ContainerProps }) {
12
+ const { t } = useTranslation();
13
+ return (
14
+ <Stack sx={{ alignItems: 'center' }} {...ContainerProps}>
15
+ {variant === 'wide' && (
16
+ <div>
17
+ <Typography align="center" component="p" variant="h3">
18
+ {t('mirador')}
19
+ </Typography>
20
+ </div>
21
+ )}
22
+ <Typography align="center">
23
+ <IconButton component="a" href="https://projectmirador.org" target="_blank" rel="noopener" size="large">
24
+ <MiradorIcon aria-label={t('aboutMirador')} titleAccess={t('aboutMirador')} fontSize="large" />
25
+ </IconButton>
26
+ </Typography>
27
+ </Stack>
28
+ );
29
+ }
30
+
31
+ Branding.propTypes = {
32
+ variant: PropTypes.oneOf(['default', 'wide']),
33
+ };