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,236 @@
1
+ import { useContext, useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Button, Chip, Dialog, DialogActions, DialogTitle, Link, MenuList, MenuItem, Typography } from '@mui/material';
4
+ import ArrowBackIcon from '@mui/icons-material/ArrowBackSharp';
5
+ import Skeleton from '@mui/material/Skeleton';
6
+ import { styled } from '@mui/material/styles';
7
+ import { useTranslation } from 'react-i18next';
8
+ import asArray from '../lib/asArray';
9
+ import LabelValueMetadata from '../containers/LabelValueMetadata';
10
+ import CollapsibleSection from '../containers/CollapsibleSection';
11
+ import ScrollIndicatedDialogContent from '../containers/ScrollIndicatedDialogContent';
12
+ import ManifestInfo from '../containers/ManifestInfo';
13
+ import WorkspaceContext from '../contexts/WorkspaceContext';
14
+ import { IIIFResourceLabel } from './IIIFResourceLabel';
15
+
16
+ const StyledScrollIndicatedDialogContent = styled(ScrollIndicatedDialogContent)(() => ({
17
+ padding: (theme) => theme.spacing(1),
18
+ }));
19
+
20
+ const StyledCollectionMetadata = styled('div')(() => ({
21
+ '& .MuiPaper-root': {
22
+ background: 'transparent',
23
+ },
24
+ padding: (theme) => theme.spacing(2),
25
+ }));
26
+
27
+ const StyledCollectionFilter = styled('div')(() => ({
28
+ padding: (theme) => theme.spacing(2),
29
+ paddingTop: 0,
30
+ }));
31
+
32
+ /** */
33
+ const Placeholder = ({ onClose, container }) => (
34
+ <Dialog variant="contained" onClose={onClose} open container={container}>
35
+ <DialogTitle id="select-collection">
36
+ <Skeleton variant="text" />
37
+ </DialogTitle>
38
+ <ScrollIndicatedDialogContent>
39
+ <Skeleton variant="text" />
40
+ <Skeleton variant="text" />
41
+ </ScrollIndicatedDialogContent>
42
+ </Dialog>
43
+ );
44
+
45
+ Placeholder.propTypes = {
46
+ container: PropTypes.instanceOf(Element).isRequired,
47
+ onClose: PropTypes.func.isRequired,
48
+ };
49
+
50
+ /**
51
+ * a dialog providing the possibility to select the collection
52
+ */
53
+ // eslint-disable-next-line complexity
54
+ export function CollectionDialog({
55
+ addWindow,
56
+ collection = null,
57
+ dialogCollectionPath = [],
58
+ error = null,
59
+ hideCollectionDialog,
60
+ isMultipart = false,
61
+ manifest,
62
+ manifestId,
63
+ ready = false,
64
+ setWorkspaceAddVisibility,
65
+ showCollectionDialog,
66
+ updateWindow,
67
+ windowId = null,
68
+ }) {
69
+ const container = useContext(WorkspaceContext);
70
+ const { t } = useTranslation();
71
+ const [filter, setFilter] = useState(null);
72
+
73
+ /** */
74
+ const hideDialog = () => {
75
+ hideCollectionDialog(windowId);
76
+ };
77
+
78
+ /** */
79
+ const selectCollection = (c) => {
80
+ showCollectionDialog(c.id, [...dialogCollectionPath, manifestId], windowId);
81
+ };
82
+
83
+ /** */
84
+ const goToPreviousCollection = () => {
85
+ showCollectionDialog(dialogCollectionPath[dialogCollectionPath.length - 1], dialogCollectionPath.slice(0, -1), windowId);
86
+ };
87
+
88
+ /** */
89
+ const selectManifest = (m) => {
90
+ if (windowId) {
91
+ updateWindow(windowId, {
92
+ canvasId: null,
93
+ collectionPath: [...dialogCollectionPath, manifestId],
94
+ manifestId: m.id,
95
+ });
96
+ } else {
97
+ addWindow({ collectionPath: [...dialogCollectionPath, manifestId], manifestId: m.id });
98
+ }
99
+
100
+ hideDialog();
101
+ setWorkspaceAddVisibility(false);
102
+ };
103
+
104
+ /** */
105
+ const dialogContainer = (container?.current || document.body).querySelector(`#${windowId}`);
106
+
107
+ if (error) return null;
108
+ if (!dialogContainer) {
109
+ return null;
110
+ }
111
+
112
+ if (!ready) return <Placeholder container={dialogContainer} onClose={hideDialog} />;
113
+
114
+ const rights = manifest && asArray(manifest.getProperty('rights') || manifest.getProperty('license'));
115
+
116
+ const requiredStatement =
117
+ manifest &&
118
+ asArray(manifest.getRequiredStatement())
119
+ .filter((l) => l && l.getValue())
120
+ .map((labelValuePair) => ({
121
+ label: null,
122
+ values: labelValuePair.getValues(),
123
+ }));
124
+
125
+ const collections = manifest.getCollections();
126
+
127
+ const currentFilter = filter || (collections.length > 0 ? 'collections' : 'manifests');
128
+
129
+ return (
130
+ <Dialog variant="contained" onClose={hideDialog} container={dialogContainer} open>
131
+ <DialogTitle id="select-collection">
132
+ <Typography component="div" variant="overline">
133
+ {t(isMultipart ? 'multipartCollection' : 'collection')}
134
+ </Typography>
135
+ <Typography component="div" variant="h3">
136
+ <IIIFResourceLabel resource={manifest} />
137
+ </Typography>
138
+ </DialogTitle>
139
+ <StyledScrollIndicatedDialogContent>
140
+ {collection && (
141
+ <Button startIcon={<ArrowBackIcon />} onClick={() => goToPreviousCollection()}>
142
+ <IIIFResourceLabel resource={collection} />
143
+ </Button>
144
+ )}
145
+
146
+ <StyledCollectionMetadata>
147
+ <ManifestInfo manifestId={manifest.id} />
148
+ <CollapsibleSection id="select-collection-rights" label={t('attributionTitle')}>
149
+ {requiredStatement && <LabelValueMetadata labelValuePairs={requiredStatement} defaultLabel={t('attribution')} />}
150
+ {rights && rights.length > 0 && (
151
+ <>
152
+ <Typography variant="subtitle2" component="dt">
153
+ {t('rights')}
154
+ </Typography>
155
+ {rights.map((v) => (
156
+ <Typography variant="body1" component="dd" key={v}>
157
+ <Link target="_blank" rel="noopener noreferrer" href={v}>
158
+ {v}
159
+ </Link>
160
+ </Typography>
161
+ ))}
162
+ </>
163
+ )}
164
+ </CollapsibleSection>
165
+ </StyledCollectionMetadata>
166
+ <StyledCollectionFilter>
167
+ {manifest.getTotalCollections() > 0 && (
168
+ <Chip
169
+ clickable
170
+ color={currentFilter === 'collections' ? 'primary' : 'default'}
171
+ onClick={() => setFilter('collections')}
172
+ label={t('totalCollections', { count: manifest.getTotalCollections() })}
173
+ />
174
+ )}
175
+ {manifest.getTotalManifests() > 0 && (
176
+ <Chip
177
+ clickable
178
+ color={currentFilter === 'manifests' ? 'primary' : 'default'}
179
+ onClick={() => setFilter('manifests')}
180
+ label={t('totalManifests', { count: manifest.getTotalManifests() })}
181
+ />
182
+ )}
183
+ </StyledCollectionFilter>
184
+ {currentFilter === 'collections' && (
185
+ <MenuList>
186
+ {collections.map((c) => (
187
+ <MenuItem
188
+ key={c.id}
189
+ onClick={() => {
190
+ selectCollection(c);
191
+ }}
192
+ variant="multiline"
193
+ >
194
+ <IIIFResourceLabel resource={c} />
195
+ </MenuItem>
196
+ ))}
197
+ </MenuList>
198
+ )}
199
+ {currentFilter === 'manifests' && (
200
+ <MenuList>
201
+ {manifest.getManifests().map((m) => (
202
+ <MenuItem
203
+ key={m.id}
204
+ onClick={() => {
205
+ selectManifest(m);
206
+ }}
207
+ variant="multiline"
208
+ >
209
+ <IIIFResourceLabel resource={m} />
210
+ </MenuItem>
211
+ ))}
212
+ </MenuList>
213
+ )}
214
+ </StyledScrollIndicatedDialogContent>
215
+ <DialogActions>
216
+ <Button onClick={hideDialog}>{t('close')}</Button>
217
+ </DialogActions>
218
+ </Dialog>
219
+ );
220
+ }
221
+
222
+ CollectionDialog.propTypes = {
223
+ addWindow: PropTypes.func.isRequired,
224
+ collection: PropTypes.object,
225
+ dialogCollectionPath: PropTypes.arrayOf(PropTypes.string),
226
+ error: PropTypes.string,
227
+ hideCollectionDialog: PropTypes.func.isRequired,
228
+ isMultipart: PropTypes.bool,
229
+ manifest: PropTypes.object.isRequired,
230
+ manifestId: PropTypes.string.isRequired,
231
+ ready: PropTypes.bool,
232
+ setWorkspaceAddVisibility: PropTypes.func.isRequired,
233
+ showCollectionDialog: PropTypes.func.isRequired,
234
+ updateWindow: PropTypes.func.isRequired,
235
+ windowId: PropTypes.string,
236
+ };
@@ -0,0 +1,48 @@
1
+ import { useId } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import Button from '@mui/material/Button';
4
+ import Typography from '@mui/material/Typography';
5
+ import ViewListIcon from '@mui/icons-material/ViewListSharp';
6
+ import { useTranslation } from 'react-i18next';
7
+ import CollapsibleSection from '../containers/CollapsibleSection';
8
+
9
+ /**
10
+ * CollectionInfo
11
+ */
12
+ export function CollectionInfo({ collectionLabel = null, collectionPath = [], showCollectionDialog, windowId = null }) {
13
+ const { t } = useTranslation();
14
+ const id = useId();
15
+ const titleId = useId();
16
+
17
+ /**
18
+ * Show the containing collection.
19
+ */
20
+ const openCollectionDialog = () => {
21
+ const manifestId = collectionPath[collectionPath.length - 1];
22
+
23
+ showCollectionDialog(manifestId, collectionPath.slice(0, -1), windowId);
24
+ };
25
+
26
+ if (collectionPath.length === 0) return null;
27
+
28
+ return (
29
+ <CollapsibleSection id={id} label={t('collection')}>
30
+ {collectionLabel && (
31
+ <Typography aria-labelledby={`${id} ${titleId}`} id={titleId} variant="h4">
32
+ {collectionLabel}
33
+ </Typography>
34
+ )}
35
+
36
+ <Button color="primary" onClick={openCollectionDialog} startIcon={<ViewListIcon />}>
37
+ {t('showCollection')}
38
+ </Button>
39
+ </CollapsibleSection>
40
+ );
41
+ }
42
+
43
+ CollectionInfo.propTypes = {
44
+ collectionLabel: PropTypes.string,
45
+ collectionPath: PropTypes.arrayOf(PropTypes.string),
46
+ showCollectionDialog: PropTypes.func.isRequired,
47
+ windowId: PropTypes.string,
48
+ };
@@ -0,0 +1,140 @@
1
+ import PropTypes from 'prop-types';
2
+ import { styled } from '@mui/material/styles';
3
+ import Slide from '@mui/material/Slide';
4
+ import ArrowLeftIcon from '@mui/icons-material/ArrowLeftSharp';
5
+ import ArrowRightIcon from '@mui/icons-material/ArrowRightSharp';
6
+ import classNames from 'classnames';
7
+ import { useTranslation } from 'react-i18next';
8
+ import CompanionWindowFactory from '../containers/CompanionWindowFactory';
9
+ import MiradorMenuButton from '../containers/MiradorMenuButton';
10
+ import ns from '../config/css-ns';
11
+
12
+ const Root = styled('div', { name: 'CompanionArea', slot: 'root' })(({ ownerState, theme }) => ({
13
+ display: 'flex',
14
+ minHeight: 0,
15
+ position: 'relative',
16
+ zIndex: theme.zIndex.appBar - 2,
17
+ ...((ownerState.position === 'bottom' || ownerState.position === 'far-bottom') && {
18
+ flexDirection: 'column',
19
+ width: '100%',
20
+ }),
21
+ }));
22
+
23
+ const Container = styled('div', { name: 'CompanionArea', slot: 'container' })(({ ownerState }) => ({
24
+ display: ownerState?.companionAreaOpen ? 'flex' : 'none',
25
+ ...((ownerState?.position === 'bottom' || ownerState?.position === 'far-bottom') && {
26
+ flexDirection: 'column',
27
+ width: '100%',
28
+ }),
29
+ ...(ownerState?.position === 'left' &&
30
+ ownerState?.companionWindowIds &&
31
+ ownerState.companionWindowIds.length > 0 && {
32
+ minWidth: '235px',
33
+ }),
34
+ }));
35
+
36
+ const StyledToggle = styled('div', { name: 'CompanionArea', slot: 'toggle' })(({ theme }) => ({
37
+ alignItems: 'center',
38
+ backgroundColor: theme.palette.background.paper,
39
+ border: `1px solid ${theme.palette.shades?.dark}`,
40
+ ...theme.applyStyles('dark', { borderColor: theme.palette.divider }),
41
+ borderInlineStart: 0,
42
+ borderRadius: 0,
43
+ display: 'inline-flex',
44
+ height: '48px',
45
+ left: '100%',
46
+ marginTop: '1rem',
47
+ overflow: 'hidden',
48
+ padding: 2,
49
+ position: 'absolute',
50
+ width: '23px',
51
+ zIndex: theme.zIndex.drawer,
52
+ }));
53
+
54
+ /** */
55
+ export function CompanionArea({
56
+ classes = {},
57
+ className = undefined,
58
+ direction,
59
+ companionWindowIds,
60
+ companionAreaOpen,
61
+ setCompanionAreaOpen = () => {},
62
+ position,
63
+ sideBarOpen = false,
64
+ windowId,
65
+ }) {
66
+ const { t } = useTranslation();
67
+ /** */
68
+ const areaLayoutClass = position === 'bottom' || position === 'far-bottom' ? classes.horizontal : null;
69
+
70
+ /** */
71
+ const collapseIcon = (() => {
72
+ if (direction === 'rtl') {
73
+ if (companionAreaOpen) return <ArrowRightIcon />;
74
+ return <ArrowLeftIcon />;
75
+ }
76
+
77
+ if (companionAreaOpen) return <ArrowLeftIcon />;
78
+ return <ArrowRightIcon />;
79
+ })();
80
+
81
+ /** */
82
+ const slideDirection = (() => {
83
+ const defaultPosition = direction === 'rtl' ? 'left' : 'right';
84
+ const oppositePosition = direction === 'rtl' ? 'right' : 'left';
85
+
86
+ switch (position) {
87
+ case 'right':
88
+ case 'far-right':
89
+ return oppositePosition;
90
+ case 'bottom':
91
+ case 'far-bottom':
92
+ return 'up';
93
+ default:
94
+ return defaultPosition;
95
+ }
96
+ })();
97
+
98
+ const rootClasses = classNames(areaLayoutClass, ns(`companion-area-${position}`), className);
99
+ // eslint-disable-next-line prefer-rest-params
100
+ const ownerState = arguments[0];
101
+
102
+ return (
103
+ <Root ownerState={ownerState} className={rootClasses}>
104
+ <Slide in={companionAreaOpen} direction={slideDirection}>
105
+ <Container ownerState={ownerState} className={`${ns('companion-windows')}`}>
106
+ {companionWindowIds.map((id) => (
107
+ <CompanionWindowFactory id={id} key={id} windowId={windowId} />
108
+ ))}
109
+ </Container>
110
+ </Slide>
111
+ {setCompanionAreaOpen && position === 'left' && sideBarOpen && companionWindowIds.length > 0 && (
112
+ <StyledToggle>
113
+ <MiradorMenuButton
114
+ aria-expanded={companionAreaOpen}
115
+ aria-label={companionAreaOpen ? t('collapseSidePanel') : t('expandSidePanel')}
116
+ edge="start"
117
+ onClick={() => {
118
+ setCompanionAreaOpen(windowId, !companionAreaOpen);
119
+ }}
120
+ TooltipProps={{ placement: 'right' }}
121
+ >
122
+ {collapseIcon}
123
+ </MiradorMenuButton>
124
+ </StyledToggle>
125
+ )}
126
+ </Root>
127
+ );
128
+ }
129
+
130
+ CompanionArea.propTypes = {
131
+ classes: PropTypes.objectOf(PropTypes.string),
132
+ className: PropTypes.string,
133
+ companionAreaOpen: PropTypes.bool.isRequired,
134
+ companionWindowIds: PropTypes.arrayOf(PropTypes.string).isRequired,
135
+ direction: PropTypes.string.isRequired,
136
+ position: PropTypes.string.isRequired,
137
+ setCompanionAreaOpen: PropTypes.func,
138
+ sideBarOpen: PropTypes.bool,
139
+ windowId: PropTypes.string.isRequired,
140
+ };
@@ -0,0 +1,228 @@
1
+ /* eslint-disable react/require-default-props */
2
+ import { Children, cloneElement, forwardRef } from 'react';
3
+ import { useSelector } from 'react-redux';
4
+ import PropTypes from 'prop-types';
5
+ import { styled } from '@mui/material/styles';
6
+ import CloseIcon from '@mui/icons-material/CloseSharp';
7
+ import OpenInNewIcon from '@mui/icons-material/OpenInNewSharp';
8
+ import MoveIcon from '@mui/icons-material/DragIndicatorSharp';
9
+ import Paper from '@mui/material/Paper';
10
+ import Typography from '@mui/material/Typography';
11
+ import Toolbar from '@mui/material/Toolbar';
12
+ import { useTranslation } from 'react-i18next';
13
+ import { Rnd } from 'react-rnd';
14
+ import { useElementSize } from '@custom-react-hooks/use-element-size';
15
+ import mergeRefs from 'merge-refs';
16
+ import MiradorMenuButton from '../containers/MiradorMenuButton';
17
+ import ns from '../config/css-ns';
18
+ import LocaleContext from '../contexts/LocaleContext';
19
+ import { getCompanionWindowLocale } from '../state/selectors/companionWindows';
20
+
21
+ const Root = styled(Paper, { name: 'CompanionWindow', slot: 'root' })({});
22
+ const StyledToolbar = styled(Toolbar, { name: 'CompanionWindow', slot: 'toolbar' })({});
23
+ const StyledTitle = styled(Typography, { name: 'CompanionWindow', slot: 'title' })({});
24
+ const StyledTitleControls = styled('div', { name: 'CompanionWindow', slot: 'controls' })({});
25
+ const Contents = styled(Paper, { name: 'CompanionWindow', slot: 'contents' })({});
26
+ const StyledRnd = styled(Rnd, { name: 'CompanionWindow', slot: 'resize' })({});
27
+ const StyledPositionButton = styled(MiradorMenuButton, {
28
+ name: 'CompanionWindow',
29
+ slot: 'positionButton',
30
+ })({});
31
+ const StyledCloseButton = styled(MiradorMenuButton, {
32
+ name: 'CompanionWindow',
33
+ slot: 'closeButton',
34
+ })({});
35
+
36
+ /**
37
+ * CompanionWindow
38
+ */
39
+ // eslint-disable-next-line complexity
40
+ export const CompanionWindow = forwardRef((props, innerRef) => {
41
+ const {
42
+ ariaLabel = undefined,
43
+ classes = {},
44
+ direction,
45
+ id,
46
+ paperClassName = '',
47
+ onCloseClick = () => {},
48
+ updateCompanionWindow = undefined,
49
+ isDisplayed = false,
50
+ position = null,
51
+ title = null,
52
+ children = undefined,
53
+ titleControls = null,
54
+ defaultSidebarPanelWidth = 235,
55
+ defaultSidebarPanelHeight = 201,
56
+ } = props;
57
+ const [sizeRef, size] = useElementSize();
58
+ const { t } = useTranslation();
59
+ const locale = useSelector((state) => getCompanionWindowLocale(state, { companionWindowId: id }), [id]);
60
+
61
+ /** */
62
+ const openInNewStyle = direction === 'rtl' ? { transform: 'scale(-1, 1)' } : {};
63
+
64
+ /** */
65
+ const resizeHandles = (() => {
66
+ const positions = {
67
+ ltr: {
68
+ default: 'left',
69
+ opposite: 'right',
70
+ },
71
+ rtl: {
72
+ default: 'right',
73
+ opposite: 'left',
74
+ },
75
+ };
76
+
77
+ const base = {
78
+ bottom: false,
79
+ bottomLeft: false,
80
+ bottomRight: false,
81
+ left: false,
82
+ right: false,
83
+ top: false,
84
+ topLeft: false,
85
+ topRight: false,
86
+ };
87
+
88
+ if (position === 'right' || position === 'far-right') {
89
+ return { ...base, [positions[direction].default]: true };
90
+ }
91
+
92
+ if (position === 'left') {
93
+ return { ...base, [positions[direction].opposite]: true };
94
+ }
95
+
96
+ if (position === 'bottom' || position === 'far-bottom') {
97
+ return { ...base, top: true };
98
+ }
99
+
100
+ return base;
101
+ })();
102
+
103
+ const isBottom = position === 'bottom' || position === 'far-bottom';
104
+
105
+ const childrenWithAdditionalProps = Children.map(children, (child) => {
106
+ if (!child) return null;
107
+ return cloneElement(child, {
108
+ parentactions: {
109
+ closeCompanionWindow: onCloseClick,
110
+ },
111
+ });
112
+ });
113
+
114
+ return (
115
+ <Root
116
+ ownerState={props}
117
+ ref={mergeRefs(innerRef, sizeRef)}
118
+ style={{
119
+ display: isDisplayed ? null : 'none',
120
+ order: position === 'left' ? -1 : null,
121
+ }}
122
+ className={[
123
+ ns(`companion-window-${position}`),
124
+ paperClassName,
125
+ position === 'bottom' ? classes.horizontal : classes.vertical,
126
+ ].join(' ')}
127
+ square
128
+ component="aside"
129
+ role="region"
130
+ aria-label={ariaLabel || title}
131
+ >
132
+ <LocaleContext.Provider value={locale}>
133
+ <StyledRnd
134
+ style={{ display: 'inherit', position: 'inherit' }}
135
+ ownerState={props}
136
+ default={{
137
+ height: isBottom ? defaultSidebarPanelHeight : '100%',
138
+ width: isBottom ? 'auto' : defaultSidebarPanelWidth,
139
+ }}
140
+ disableDragging
141
+ enableResizing={resizeHandles}
142
+ minHeight={50}
143
+ minWidth={position === 'left' ? 235 : 100}
144
+ >
145
+ <StyledToolbar
146
+ variant="dense"
147
+ className={[ns('companion-window-header'), size.width < 370 ? 'test' : null].join(' ')}
148
+ disableGutters
149
+ >
150
+ <StyledTitle variant="h3">{title}</StyledTitle>
151
+ {position === 'left' ? (
152
+ updateCompanionWindow && (
153
+ <MiradorMenuButton
154
+ aria-label={t('openInCompanionWindow')}
155
+ onClick={() => {
156
+ updateCompanionWindow({ position: 'right' });
157
+ }}
158
+ >
159
+ <OpenInNewIcon style={openInNewStyle} />
160
+ </MiradorMenuButton>
161
+ )
162
+ ) : (
163
+ <>
164
+ {updateCompanionWindow && (
165
+ <StyledPositionButton
166
+ aria-label={position === 'bottom' ? t('moveCompanionWindowToRight') : t('moveCompanionWindowToBottom')}
167
+ onClick={() => {
168
+ updateCompanionWindow({
169
+ position: position === 'bottom' ? 'right' : 'bottom',
170
+ });
171
+ }}
172
+ >
173
+ <MoveIcon />
174
+ </StyledPositionButton>
175
+ )}
176
+ <StyledCloseButton
177
+ sx={{
178
+ ...(size.width < 370 && {
179
+ order: 'unset',
180
+ }),
181
+ }}
182
+ aria-label={t('closeCompanionWindow')}
183
+ onClick={onCloseClick}
184
+ >
185
+ <CloseIcon />
186
+ </StyledCloseButton>
187
+ </>
188
+ )}
189
+ {titleControls && (
190
+ <StyledTitleControls
191
+ ownerState={{ position }}
192
+ sx={{
193
+ order: isBottom || size.width < 370 ? 'unset' : 1000,
194
+ }}
195
+ className={ns('companion-window-title-controls')}
196
+ >
197
+ {titleControls}
198
+ </StyledTitleControls>
199
+ )}
200
+ </StyledToolbar>
201
+ <Contents className={ns('scrollto-scrollable')} elevation={0}>
202
+ {childrenWithAdditionalProps}
203
+ </Contents>
204
+ </StyledRnd>
205
+ </LocaleContext.Provider>
206
+ </Root>
207
+ );
208
+ });
209
+
210
+ CompanionWindow.propTypes = {
211
+ ariaLabel: PropTypes.string,
212
+ children: PropTypes.node,
213
+ classes: PropTypes.objectOf(PropTypes.string),
214
+ defaultSidebarPanelHeight: PropTypes.number,
215
+ defaultSidebarPanelWidth: PropTypes.number,
216
+ direction: PropTypes.string.isRequired,
217
+ id: PropTypes.string.isRequired,
218
+ isDisplayed: PropTypes.bool,
219
+ onCloseClick: PropTypes.func,
220
+ paperClassName: PropTypes.string,
221
+ position: PropTypes.string,
222
+ size: PropTypes.shape({ width: PropTypes.number }),
223
+ title: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
224
+ titleControls: PropTypes.node,
225
+ updateCompanionWindow: PropTypes.func,
226
+ };
227
+
228
+ CompanionWindow.displayName = 'CompanionWindow';
@@ -0,0 +1,38 @@
1
+ import { useCallback } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { ErrorBoundary } from 'react-error-boundary';
4
+ import { useTranslation } from 'react-i18next';
5
+ import CompanionWindowRegistry from '../lib/CompanionWindowRegistry';
6
+ import CompanionWindow from '../containers/CompanionWindow';
7
+ import ErrorContent from '../containers/ErrorContent';
8
+
9
+ /**
10
+ * Render a companion window using the appropriate component for the content
11
+ */
12
+ export function CompanionWindowFactory({ content = null, id, windowId }) {
13
+ const { t } = useTranslation();
14
+ const ErroredCompanionWindow = useCallback(
15
+ ({ error }) => (
16
+ <CompanionWindow title={t('error')} windowId={windowId} id={id}>
17
+ <ErrorContent error={error} windowId={windowId} companionWindowId={id} />
18
+ </CompanionWindow>
19
+ ),
20
+ [windowId, t, id],
21
+ );
22
+
23
+ const DynamicCompanionWindowType = CompanionWindowRegistry[content];
24
+
25
+ if (!DynamicCompanionWindowType) return null;
26
+
27
+ return (
28
+ <ErrorBoundary fallbackComponent={ErroredCompanionWindow}>
29
+ <DynamicCompanionWindowType id={id} windowId={windowId} />
30
+ </ErrorBoundary>
31
+ );
32
+ }
33
+
34
+ CompanionWindowFactory.propTypes = {
35
+ content: PropTypes.string,
36
+ id: PropTypes.string.isRequired,
37
+ windowId: PropTypes.string.isRequired,
38
+ };