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,99 @@
1
+ import { useCallback, useId, useMemo, useState } from 'react';
2
+ import Button from '@mui/material/Button';
3
+ import DialogActions from '@mui/material/DialogActions';
4
+ import DialogTitle from '@mui/material/DialogTitle';
5
+ import DialogContent from '@mui/material/DialogContent';
6
+ import Typography from '@mui/material/Typography';
7
+ import Snackbar from '@mui/material/Snackbar';
8
+ import IconButton from '@mui/material/IconButton';
9
+ import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
10
+ import CloseIcon from '@mui/icons-material/Close';
11
+ import Accordion from '@mui/material/Accordion';
12
+ import AccordionSummary from '@mui/material/AccordionSummary';
13
+ import AccordionDetails from '@mui/material/AccordionDetails';
14
+ import PropTypes from 'prop-types';
15
+ import copy from 'copy-to-clipboard';
16
+ import { useTranslation } from 'react-i18next';
17
+ import { WorkspaceDialog } from './WorkspaceDialog';
18
+
19
+ /**
20
+ */
21
+ export function WorkspaceExport({
22
+ children = null,
23
+ container = null,
24
+ id = undefined,
25
+ open = false,
26
+ handleClose,
27
+ exportableState,
28
+ }) {
29
+ const { t } = useTranslation();
30
+ const [copied, setCopied] = useState(false);
31
+ const titleId = useId();
32
+ const exportedState = useMemo(() => JSON.stringify(exportableState, null, 2), [exportableState]);
33
+ const onCopyClick = useCallback(() => {
34
+ copy(exportedState);
35
+ setCopied(true);
36
+ }, [exportedState, setCopied]);
37
+
38
+ if (copied) {
39
+ return (
40
+ <Snackbar
41
+ anchorOrigin={{
42
+ horizontal: 'center',
43
+ vertical: 'top',
44
+ }}
45
+ open
46
+ autoHideDuration={6000}
47
+ onClose={handleClose}
48
+ message={t('exportCopied')}
49
+ action={
50
+ <IconButton size="small" aria-label={t('dismiss')} color="inherit" onClick={handleClose}>
51
+ <CloseIcon fontSize="small" />
52
+ </IconButton>
53
+ }
54
+ />
55
+ );
56
+ }
57
+ return (
58
+ <WorkspaceDialog
59
+ aria-labelledby={titleId}
60
+ id={id}
61
+ container={container}
62
+ open={open}
63
+ onClose={handleClose}
64
+ scroll="paper"
65
+ fullWidth
66
+ maxWidth="sm"
67
+ >
68
+ <DialogTitle id={titleId}>{t('downloadExport')}</DialogTitle>
69
+
70
+ <DialogContent>
71
+ <Accordion slotProps={{ heading: { component: 'h4' } }} elevation={2}>
72
+ <AccordionSummary expandIcon={<ExpandMoreIcon />}>
73
+ <Typography>{t('viewWorkspaceConfiguration')}</Typography>
74
+ </AccordionSummary>
75
+ <AccordionDetails sx={{ overflow: 'scroll' }}>
76
+ {children}
77
+ <pre>{exportedState}</pre>
78
+ </AccordionDetails>
79
+ </Accordion>
80
+ </DialogContent>
81
+
82
+ <DialogActions>
83
+ <Button onClick={handleClose}>{t('cancel')}</Button>
84
+ <Button onClick={onCopyClick} variant="contained" color="primary">
85
+ {t('copy')}
86
+ </Button>
87
+ </DialogActions>
88
+ </WorkspaceDialog>
89
+ );
90
+ }
91
+
92
+ WorkspaceExport.propTypes = {
93
+ children: PropTypes.node,
94
+ container: PropTypes.object,
95
+ exportableState: PropTypes.object.isRequired,
96
+ handleClose: PropTypes.func.isRequired,
97
+ id: PropTypes.string,
98
+ open: PropTypes.bool,
99
+ };
@@ -0,0 +1,89 @@
1
+ import { useId, useState } from 'react';
2
+ import DialogTitle from '@mui/material/DialogTitle';
3
+ import PropTypes from 'prop-types';
4
+ import { DialogActions, TextField } from '@mui/material';
5
+ import Button from '@mui/material/Button';
6
+ import { useTranslation } from 'react-i18next';
7
+ import { WorkspaceDialog } from './WorkspaceDialog';
8
+ import ScrollIndicatedDialogContent from '../containers/ScrollIndicatedDialogContent';
9
+
10
+ /**
11
+ */
12
+ export function WorkspaceImport({
13
+ addError,
14
+ container = null,
15
+ id = undefined,
16
+ importConfig,
17
+ classes = {},
18
+ handleClose,
19
+ open = false,
20
+ }) {
21
+ const { t } = useTranslation();
22
+ const [configImportValue, setConfigImportValue] = useState('');
23
+ const titleId = useId();
24
+
25
+ /** */
26
+ const handleChange = (event) => {
27
+ event.preventDefault();
28
+ setConfigImportValue(event.target.value);
29
+ };
30
+
31
+ /** */
32
+ const handleImportConfig = (_event) => {
33
+ try {
34
+ const configJSON = JSON.parse(configImportValue);
35
+ importConfig(configJSON);
36
+ handleClose();
37
+ } catch (ex) {
38
+ addError(ex.toString());
39
+ }
40
+ };
41
+
42
+ return (
43
+ <WorkspaceDialog
44
+ aria-labelledby={titleId}
45
+ container={container}
46
+ id={id}
47
+ onClose={handleClose}
48
+ open={open}
49
+ fullWidth
50
+ maxWidth="sm"
51
+ >
52
+ <DialogTitle id={titleId}>{t('importWorkspace')}</DialogTitle>
53
+ <ScrollIndicatedDialogContent>
54
+ <TextField
55
+ className={classes.textField}
56
+ id="workspace-import-input"
57
+ multiline
58
+ onChange={handleChange}
59
+ minRows={15}
60
+ variant="filled"
61
+ sx={{
62
+ '& .MuiInputBase-input': { fontFamily: 'monospace' },
63
+ width: '100%',
64
+ }}
65
+ helperText={t('importWorkspaceHint')}
66
+ slotProps={{
67
+ htmlInput: { autoFocus: 'autofocus' },
68
+ }}
69
+ />
70
+ </ScrollIndicatedDialogContent>
71
+ <DialogActions>
72
+ <Button onClick={handleClose}>{t('cancel')}</Button>
73
+ <Button color="primary" onClick={handleImportConfig} variant="contained">
74
+ {t('import')}
75
+ </Button>
76
+ </DialogActions>
77
+ </WorkspaceDialog>
78
+ );
79
+ }
80
+
81
+ WorkspaceImport.propTypes = {
82
+ addError: PropTypes.func.isRequired,
83
+ classes: PropTypes.objectOf(PropTypes.string),
84
+ container: PropTypes.object,
85
+ handleClose: PropTypes.func.isRequired,
86
+ id: PropTypes.string,
87
+ importConfig: PropTypes.func.isRequired,
88
+ open: PropTypes.bool,
89
+ };
@@ -0,0 +1,126 @@
1
+ import { useContext, useState } from 'react';
2
+ import Menu from '@mui/material/Menu';
3
+ import MenuItem from '@mui/material/MenuItem';
4
+ import Typography from '@mui/material/Typography';
5
+ import PropTypes from 'prop-types';
6
+ import { useTranslation } from 'react-i18next';
7
+ import LanguageSettings from '../containers/LanguageSettings';
8
+ import { NestedMenu } from './NestedMenu';
9
+ import WorkspaceSelectionDialog from '../containers/WorkspaceSelectionDialog';
10
+ import ChangeThemeDialog from '../containers/ChangeThemeDialog';
11
+ import { PluginHook } from './PluginHook';
12
+ import WorkspaceContext from '../contexts/WorkspaceContext';
13
+
14
+ /**
15
+ */
16
+ export function WorkspaceMenu({
17
+ handleClose,
18
+ showThemePicker = false,
19
+ isWorkspaceAddVisible = false,
20
+ tReady = false,
21
+ toggleZoomControls = () => {},
22
+ showZoomControls = false,
23
+ ...menuProps
24
+ }) {
25
+ const { t } = useTranslation();
26
+ const container = useContext(WorkspaceContext);
27
+ const [selectedOption, setSelectedOption] = useState(null);
28
+
29
+ // eslint-disable-next-line prefer-rest-params
30
+ const pluginProps = arguments[0];
31
+
32
+ /** */
33
+ const handleClick = (option, e) => {
34
+ setSelectedOption(option);
35
+ handleClose(e);
36
+ };
37
+
38
+ /** */
39
+ const handleDialogClose = () => {
40
+ setSelectedOption(null);
41
+ };
42
+
43
+ /** */
44
+ const handleZoomToggleClick = (e) => {
45
+ toggleZoomControls(!showZoomControls);
46
+ handleClose(e);
47
+ };
48
+
49
+ return (
50
+ <>
51
+ <Menu
52
+ container={container?.current}
53
+ anchorOrigin={{
54
+ horizontal: 'right',
55
+ vertical: 'top',
56
+ }}
57
+ transformOrigin={{
58
+ horizontal: 'left',
59
+ vertical: 'top',
60
+ }}
61
+ onClose={handleClose}
62
+ {...menuProps}
63
+ >
64
+ <MenuItem
65
+ aria-haspopup="true"
66
+ aria-expanded={selectedOption === 'workspaceSelection'}
67
+ disabled={isWorkspaceAddVisible}
68
+ onClick={(e) => {
69
+ handleZoomToggleClick(e);
70
+ }}
71
+ aria-owns={selectedOption === 'toggleZoom' ? 'toggle-zoom-menu' : undefined}
72
+ >
73
+ <Typography variant="body1">{showZoomControls ? t('hideZoomControls') : t('showZoomControls')}</Typography>
74
+ </MenuItem>
75
+ <MenuItem
76
+ aria-haspopup="true"
77
+ onClick={(e) => {
78
+ handleClick('workspaceSelection', e);
79
+ }}
80
+ aria-owns={selectedOption === 'workspaceSelection' ? 'workspace-selection' : undefined}
81
+ >
82
+ <Typography variant="body1">{t('selectWorkspaceMenu')}</Typography>
83
+ </MenuItem>
84
+
85
+ <NestedMenu label={t('language')}>
86
+ <LanguageSettings afterSelect={handleClose} />
87
+ </NestedMenu>
88
+ {showThemePicker && (
89
+ <MenuItem
90
+ aria-haspopup="true"
91
+ onClick={(e) => {
92
+ handleClick('changeTheme', e);
93
+ }}
94
+ aria-owns={selectedOption === 'changeTheme' ? 'change-theme' : undefined}
95
+ >
96
+ <Typography variant="body1">{t('changeTheme')}</Typography>
97
+ </MenuItem>
98
+ )}
99
+ <PluginHook targetName="WorkspaceMenu" {...pluginProps} />
100
+ </Menu>
101
+ {selectedOption === 'changeTheme' && (
102
+ <ChangeThemeDialog
103
+ container={container?.current}
104
+ handleClose={handleDialogClose}
105
+ open={selectedOption === 'changeTheme'}
106
+ />
107
+ )}
108
+ {selectedOption === 'workspaceSelection' && (
109
+ <WorkspaceSelectionDialog
110
+ open={selectedOption === 'workspaceSelection'}
111
+ container={container?.current}
112
+ handleClose={handleDialogClose}
113
+ />
114
+ )}
115
+ </>
116
+ );
117
+ }
118
+
119
+ WorkspaceMenu.propTypes = {
120
+ handleClose: PropTypes.func.isRequired,
121
+ isWorkspaceAddVisible: PropTypes.bool,
122
+ showThemePicker: PropTypes.bool,
123
+ showZoomControls: PropTypes.bool,
124
+ toggleZoomControls: PropTypes.func,
125
+ tReady: PropTypes.bool,
126
+ };
@@ -0,0 +1,42 @@
1
+ import { useId, useState } from 'react';
2
+ import SettingsIcon from '@mui/icons-material/SettingsSharp';
3
+ import { useTranslation } from 'react-i18next';
4
+ import WorkspaceMenu from '../containers/WorkspaceMenu';
5
+ import MiradorMenuButton from '../containers/MiradorMenuButton';
6
+
7
+ /**
8
+ */
9
+ export function WorkspaceMenuButton() {
10
+ const { t } = useTranslation();
11
+ const [anchorEl, setAnchorEl] = useState(null);
12
+ const [open, setOpen] = useState(false);
13
+ const id = useId();
14
+
15
+ /** */
16
+ const handleMenuClick = (event) => {
17
+ setAnchorEl(event.currentTarget);
18
+ setOpen(true);
19
+ };
20
+
21
+ /** */
22
+ const handleMenuClose = () => {
23
+ setAnchorEl(null);
24
+ setOpen(false);
25
+ };
26
+
27
+ return (
28
+ <>
29
+ <MiradorMenuButton
30
+ aria-haspopup="true"
31
+ aria-label={t('workspaceMenu')}
32
+ aria-owns={open ? id : undefined}
33
+ selected={open}
34
+ id="menuBtn"
35
+ onClick={handleMenuClick}
36
+ >
37
+ <SettingsIcon />
38
+ </MiradorMenuButton>
39
+ <WorkspaceMenu anchorEl={anchorEl} id={id} handleClose={handleMenuClose} open={open} />
40
+ </>
41
+ );
42
+ }
@@ -0,0 +1,149 @@
1
+ import { useContext, useEffect, useRef } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { styled } from '@mui/material/styles';
4
+ import GlobalStyles from '@mui/material/GlobalStyles';
5
+ import { DndContext } from 'react-dnd';
6
+ import { Mosaic, MosaicWindow, getLeaves, createBalancedTreeFromLeaves, convertLegacyToNary } from 'react-mosaic-component';
7
+ import isEqual from 'lodash/isEqual';
8
+ import classNames from 'classnames';
9
+ import MosaicRenderPreview from '../containers/MosaicRenderPreview';
10
+ import Window from '../containers/Window';
11
+ import MosaicLayout from '../lib/MosaicLayout';
12
+ import globalReactMosaicStyles from '../styles/react-mosaic-component';
13
+
14
+ const StyledMosaic = styled(Mosaic)({
15
+ '& .mosaic-preview': {
16
+ boxShadow: 'none',
17
+ },
18
+ '& .mosaic-tile': {
19
+ boxShadow: '0 1px 3px 0 rgba(0, 0, 0, .2), 0 1px 1px 0 rgba(0, 0, 0, .2), 0 2px 1px -1px rgba(0, 0, 0, .2)',
20
+ },
21
+ '& .mosaic-window': {
22
+ boxShadow: 'none',
23
+ },
24
+ '& .mosaic-window-toolbar': {
25
+ display: 'none !important',
26
+ },
27
+ });
28
+
29
+ /** */
30
+ const RenderPreview = ({ windowId }) => (
31
+ <div className="mosaic-preview" aria-hidden>
32
+ <MosaicRenderPreview windowId={windowId} />
33
+ </div>
34
+ );
35
+
36
+ RenderPreview.propTypes = {
37
+ windowId: PropTypes.string.isRequired,
38
+ };
39
+
40
+ /** */
41
+ const ZeroStateView = () => <div />;
42
+
43
+ /**
44
+ * Used to regenerate a new layout when windows are added or removed
45
+ */
46
+ const determineWorkspaceLayout = (currentLayout, windowIds, currentWindowPaths = {}) => {
47
+ const leaveKeys = getLeaves(currentLayout);
48
+ const mosaicLayout = new MosaicLayout(currentLayout);
49
+
50
+ // Add new windows to layout
51
+ const addedWindows = windowIds.filter((windowId) => !leaveKeys.includes(windowId));
52
+ if (addedWindows.length > 0) mosaicLayout.addWindows(addedWindows);
53
+
54
+ const removedWindows = leaveKeys.filter((leaveKey) => !windowIds.includes(leaveKey));
55
+
56
+ // if we have paths for the removed windows, we can gracefully remove them and
57
+ // preserve the existing layout for the remaining windows
58
+ if (removedWindows.every((e) => currentWindowPaths[e])) {
59
+ mosaicLayout.removeWindows(removedWindows, currentWindowPaths);
60
+ } else {
61
+ // Windows were removed (perhaps in a different Workspace). We don't have a
62
+ // way to reconfigure.. so we have to random generate
63
+
64
+ return createBalancedTreeFromLeaves(windowIds);
65
+ }
66
+
67
+ return mosaicLayout.layout;
68
+ };
69
+
70
+ /**
71
+ * Represents a work area that contains any number of windows
72
+ * @memberof Workspace
73
+ * @private
74
+ */
75
+ export function WorkspaceMosaic({ layout = undefined, updateWorkspaceMosaicLayout, windowIds = [], workspaceId }) {
76
+ const windowPaths = useRef({});
77
+ const dndContext = useContext(DndContext);
78
+
79
+ // Convert legacy layout format to new format if needed
80
+ const normalizedLayout = layout ? convertLegacyToNary(layout) : layout;
81
+
82
+ useEffect(() => {
83
+ const leaveKeys = getLeaves(normalizedLayout);
84
+ // Handle some trivial layout cases:
85
+ // 1. No layout
86
+ // 2. No windows
87
+ // 3. Not enough windows to create a layout
88
+ if (!normalizedLayout || windowIds.length === 0 || leaveKeys.length < 2) {
89
+ updateWorkspaceMosaicLayout(createBalancedTreeFromLeaves(windowIds));
90
+
91
+ return undefined;
92
+ }
93
+
94
+ // nothing was added or removed, and all the windows are accounted for in the layout
95
+ if (windowIds.every((e) => leaveKeys.includes(e)) && leaveKeys.every((e) => windowIds.includes(e))) {
96
+ return undefined;
97
+ }
98
+
99
+ const newLayout = determineWorkspaceLayout(normalizedLayout, windowIds, windowPaths.current);
100
+
101
+ if (!isEqual(newLayout, normalizedLayout)) updateWorkspaceMosaicLayout(newLayout);
102
+
103
+ return undefined;
104
+ }, [normalizedLayout, windowIds, windowPaths, updateWorkspaceMosaicLayout]);
105
+
106
+ const toolbarControls = [];
107
+
108
+ /**
109
+ * Render a tile (Window) in the Mosaic.
110
+ */
111
+ const tileRenderer = (id, path) => {
112
+ if (!windowIds.includes(id)) return null;
113
+ windowPaths.current[id] = path;
114
+
115
+ return (
116
+ <MosaicWindow toolbarControls={toolbarControls} path={path} windowId={id} renderPreview={RenderPreview}>
117
+ <Window key={`${id}-${workspaceId}`} windowId={id} />
118
+ </MosaicWindow>
119
+ );
120
+ };
121
+
122
+ /**
123
+ * Update the redux store when the Mosaic is changed.
124
+ */
125
+ const mosaicChange = (newLayout) => {
126
+ updateWorkspaceMosaicLayout(newLayout);
127
+ };
128
+
129
+ return (
130
+ <>
131
+ <GlobalStyles styles={{ ...globalReactMosaicStyles }} />
132
+ <StyledMosaic
133
+ dragAndDropManager={dndContext.dragDropManager}
134
+ renderTile={tileRenderer}
135
+ initialValue={normalizedLayout || createBalancedTreeFromLeaves(windowIds)}
136
+ onChange={mosaicChange}
137
+ className={classNames('mirador-mosaic')}
138
+ zeroStateView={<ZeroStateView />}
139
+ />
140
+ </>
141
+ );
142
+ }
143
+
144
+ WorkspaceMosaic.propTypes = {
145
+ layout: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
146
+ updateWorkspaceMosaicLayout: PropTypes.func.isRequired,
147
+ windowIds: PropTypes.arrayOf(PropTypes.string),
148
+ workspaceId: PropTypes.string.isRequired,
149
+ };
@@ -0,0 +1,35 @@
1
+ import { useState } from 'react';
2
+ import MoreHorizontalIcon from '@mui/icons-material/MoreHorizSharp';
3
+ import { useTranslation } from 'react-i18next';
4
+ import MiradorMenuButton from '../containers/MiradorMenuButton';
5
+ import WorkspaceOptionsMenu from '../containers/WorkspaceOptionsMenu';
6
+
7
+ /**
8
+ * WorkspaceOptionsButton ~
9
+ */
10
+ export function WorkspaceOptionsButton() {
11
+ const { t } = useTranslation();
12
+ const [anchorEl, setAnchorEl] = useState(null);
13
+ const [open, setOpen] = useState(false);
14
+
15
+ /** */
16
+ const handleMenuClick = (event) => {
17
+ setAnchorEl(event.currentTarget);
18
+ setOpen(true);
19
+ };
20
+
21
+ /** */
22
+ const handleMenuClose = () => {
23
+ setAnchorEl(null);
24
+ setOpen(false);
25
+ };
26
+
27
+ return (
28
+ <>
29
+ <MiradorMenuButton aria-label={t('workspaceOptions')} onClick={handleMenuClick} selected={open}>
30
+ <MoreHorizontalIcon />
31
+ </MiradorMenuButton>
32
+ <WorkspaceOptionsMenu anchorEl={anchorEl} handleClose={handleMenuClose} open={open} />
33
+ </>
34
+ );
35
+ }
@@ -0,0 +1,112 @@
1
+ import { useContext, useId, useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import ImportIcon from '@mui/icons-material/Input';
4
+ import SaveAltIcon from '@mui/icons-material/SaveAltSharp';
5
+ import ListItemIcon from '@mui/material/ListItemIcon';
6
+ import Menu from '@mui/material/Menu';
7
+ import MenuItem from '@mui/material/MenuItem';
8
+ import Typography from '@mui/material/Typography';
9
+ import { useTranslation } from 'react-i18next';
10
+ import WorkspaceExport from '../containers/WorkspaceExport';
11
+ import WorkspaceImport from '../containers/WorkspaceImport';
12
+ import WorkspaceContext from '../contexts/WorkspaceContext';
13
+ import { PluginHook } from './PluginHook';
14
+
15
+ /**
16
+ * WorkspaceOptionsMenu ~ the menu for workspace options such as import/export
17
+ */
18
+ export function WorkspaceOptionsMenu({ anchorEl = null, handleClose, open = false, ...rest }) {
19
+ const { t } = useTranslation();
20
+ const container = useContext(WorkspaceContext);
21
+ const [selectedOption, setSelectedOption] = useState(null);
22
+ const exportId = useId();
23
+ const importId = useId();
24
+
25
+ const pluginProps = {
26
+ anchorEl,
27
+ container,
28
+ handleClose,
29
+ open,
30
+ t,
31
+ ...rest,
32
+ };
33
+
34
+ /** */
35
+ const handleClick = (option) => {
36
+ setSelectedOption(option);
37
+ handleClose();
38
+ };
39
+
40
+ /** */
41
+ const handleDialogClose = () => {
42
+ setSelectedOption(null);
43
+ };
44
+
45
+ return (
46
+ <>
47
+ <Menu
48
+ id="workspace-options-menu"
49
+ container={container?.current}
50
+ anchorEl={anchorEl}
51
+ anchorOrigin={{
52
+ horizontal: 'right',
53
+ vertical: 'top',
54
+ }}
55
+ transformOrigin={{
56
+ horizontal: 'left',
57
+ vertical: 'top',
58
+ }}
59
+ open={open}
60
+ onClose={handleClose}
61
+ >
62
+ <MenuItem
63
+ aria-haspopup="true"
64
+ onClick={() => {
65
+ handleClick('exportWorkspace');
66
+ }}
67
+ aria-owns={selectedOption === 'exportWorkspace' ? exportId : undefined}
68
+ >
69
+ <ListItemIcon>
70
+ <SaveAltIcon />
71
+ </ListItemIcon>
72
+ <Typography variant="body1">{t('downloadExportWorkspace')}</Typography>
73
+ </MenuItem>
74
+ <MenuItem
75
+ aria-haspopup="true"
76
+ onClick={() => {
77
+ handleClick('importWorkspace');
78
+ }}
79
+ aria-owns={selectedOption === 'importWorkspace' ? importId : undefined}
80
+ >
81
+ <ListItemIcon>
82
+ <ImportIcon />
83
+ </ListItemIcon>
84
+ <Typography variant="body1">{t('importWorkspace')}</Typography>
85
+ </MenuItem>
86
+ <PluginHook targetName="WorkspaceOptionsMenu" {...pluginProps} />
87
+ </Menu>
88
+ {selectedOption === 'exportWorkspace' && (
89
+ <WorkspaceExport
90
+ id={exportId}
91
+ open={selectedOption === 'exportWorkspace'}
92
+ container={container?.current}
93
+ handleClose={handleDialogClose}
94
+ />
95
+ )}
96
+ {selectedOption === 'importWorkspace' && (
97
+ <WorkspaceImport
98
+ id={importId}
99
+ open={selectedOption === 'importWorkspace'}
100
+ container={container?.current}
101
+ handleClose={handleDialogClose}
102
+ />
103
+ )}
104
+ </>
105
+ );
106
+ }
107
+
108
+ WorkspaceOptionsMenu.propTypes = {
109
+ anchorEl: PropTypes.object,
110
+ handleClose: PropTypes.func.isRequired,
111
+ open: PropTypes.bool,
112
+ };