├── .gitattributes ├── .github ├── CONTRIBUTING.md ├── FUNDING.yml ├── ISSUE_TEMPLATE │ └── bug_report.md ├── PULL_REQUEST_TEMPLATE.md ├── dependabot.yml └── workflows │ ├── build-test.yml │ ├── lint-and-prettify.yml │ └── release.yml ├── .gitignore ├── .gitmodules ├── .npmignore ├── .npmrc ├── .nvmrc ├── .prettierignore ├── .prettierrc.json ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── CODE_OF_CONDUCT.md ├── COMMUNITY_TEAM.md ├── CONTRIBUTING.md ├── GOVERNANCE.md ├── LICENSE.txt ├── README.md ├── __tests__ ├── configuration_options.js └── test.js ├── docs ├── .nojekyll ├── CNAME ├── assets │ ├── highlight.css │ ├── icons.svg │ └── style.css ├── classes │ └── _internal_.Metric.html ├── enums │ └── _internal_.StorageType.html ├── index.html ├── modules.html ├── modules │ └── _internal_.html └── types │ ├── IIIFContentHandlerConfig.html │ ├── _internal_.AVCenterPanel.html │ ├── _internal_.AVCenterPanelContent.html │ ├── _internal_.AVCenterPanelOptions.html │ ├── _internal_.AVDownloadDialogue.html │ ├── _internal_.AVDownloadDialogueContent.html │ ├── _internal_.AVDownloadDialogueOptions.html │ ├── _internal_.AVSettingsDialogue.html │ ├── _internal_.AVSettingsDialogueContent.html │ ├── _internal_.AVSettingsDialogueOptions.html │ ├── _internal_.AVShareDialogue.html │ ├── _internal_.AVShareDialogueContent.html │ ├── _internal_.AVShareDialogueOptions.html │ ├── _internal_.AdjustImageDialogue.html │ ├── _internal_.AdjustImageDialogueContent.html │ ├── _internal_.AdjustImageDialogueOptions.html │ ├── _internal_.AlephCenterPanel.html │ ├── _internal_.AlephCenterPanelContent.html │ ├── _internal_.AlephCenterPanelOptions.html │ ├── _internal_.AlephDownloadDialogue.html │ ├── _internal_.AlephDownloadDialogueContent.html │ ├── _internal_.AlephDownloadDialogueOptions.html │ ├── _internal_.AlephLeftPanel.html │ ├── _internal_.AlephLeftPanelContent.html │ ├── _internal_.AlephLeftPanelOptions.html │ ├── _internal_.AlephSettingsDialogue.html │ ├── _internal_.AlephSettingsDialogueContent.html │ ├── _internal_.AlephSettingsDialogueOptions.html │ ├── _internal_.AlephShareDialogue.html │ ├── _internal_.AlephShareDialogueContent.html │ ├── _internal_.AlephShareDialogueOptions.html │ ├── _internal_.AuthDialogue.html │ ├── _internal_.AuthDialogueContent.html │ ├── _internal_.AuthDialogueOptions.html │ ├── _internal_.BaseConfig.html │ ├── _internal_.CenterPanel.html │ ├── _internal_.CenterPanelContent.html │ ├── _internal_.CenterPanelOptions.html │ ├── _internal_.ClickThroughDialogue.html │ ├── _internal_.ClickThroughDialogueContent.html │ ├── _internal_.ClickThroughDialogueOptions.html │ ├── _internal_.Config-1.html │ ├── _internal_.Config-2.html │ ├── _internal_.Config-3.html │ ├── _internal_.Config-4.html │ ├── _internal_.Config-5.html │ ├── _internal_.Config-6.html │ ├── _internal_.Config-7.html │ ├── _internal_.Config.html │ ├── _internal_.Content.html │ ├── _internal_.ContentLeftPanel.html │ ├── _internal_.ContentLeftPanelContent.html │ ├── _internal_.ContentLeftPanelOptions.html │ ├── _internal_.DefaultDownloadDialogue.html │ ├── _internal_.DefaultDownloadDialogueContent.html │ ├── _internal_.DefaultDownloadDialogueOptions.html │ ├── _internal_.DefaultSettingsDialogue.html │ ├── _internal_.DefaultSettingsDialogueContent.html │ ├── _internal_.DefaultSettingsDialogueOptions.html │ ├── _internal_.DefaultShareDialogue.html │ ├── _internal_.DefaultShareDialogueContent.html │ ├── _internal_.DefaultShareDialogueOptions.html │ ├── _internal_.Dialogue.html │ ├── _internal_.DialogueContent.html │ ├── _internal_.DialogueOptions.html │ ├── _internal_.DownloadDialogue.html │ ├── _internal_.DownloadDialogueContent.html │ ├── _internal_.DownloadDialogueOptions.html │ ├── _internal_.EbookCenterPanel.html │ ├── _internal_.EbookCenterPanelContent.html │ ├── _internal_.EbookCenterPanelOptions.html │ ├── _internal_.EbookDownloadDialogue.html │ ├── _internal_.EbookDownloadDialogueContent.html │ ├── _internal_.EbookDownloadDialogueOptions.html │ ├── _internal_.EbookLeftPanel.html │ ├── _internal_.EbookLeftPanelContent.html │ ├── _internal_.EbookLeftPanelOptions.html │ ├── _internal_.EbookSettingsDialogue.html │ ├── _internal_.EbookSettingsDialogueContent.html │ ├── _internal_.EbookSettingsDialogueOptions.html │ ├── _internal_.EbookShareDialogue.html │ ├── _internal_.EbookShareDialogueContent.html │ ├── _internal_.EbookShareDialogueOptions.html │ ├── _internal_.ExpandPanel.html │ ├── _internal_.ExpandPanelContent.html │ ├── _internal_.ExpandPanelOptions.html │ ├── _internal_.FileLinkCenterPanel.html │ ├── _internal_.FileLinkCenterPanelContent.html │ ├── _internal_.FileLinkCenterPanelOptions.html │ ├── _internal_.FooterPanel.html │ ├── _internal_.FooterPanelContent.html │ ├── _internal_.FooterPanelOptions.html │ ├── _internal_.GenericDialogue.html │ ├── _internal_.GenericDialogueContent.html │ ├── _internal_.GenericDialogueOptions.html │ ├── _internal_.HeaderPanel.html │ ├── _internal_.HeaderPanelContent.html │ ├── _internal_.HeaderPanelOptions.html │ ├── _internal_.HelpDialogue.html │ ├── _internal_.HelpDialogueContent.html │ ├── _internal_.HelpDialogueOptions.html │ ├── _internal_.LeftPanel.html │ ├── _internal_.Locale.html │ ├── _internal_.Localisation.html │ ├── _internal_.LoginDialogue.html │ ├── _internal_.LoginDialogueContent.html │ ├── _internal_.LoginDialogueOptions.html │ ├── _internal_.MediaElementCenterPanel.html │ ├── _internal_.MediaElementCenterPanelContent.html │ ├── _internal_.MediaElementCenterPanelOptions.html │ ├── _internal_.MediaElementDownloadDialogue.html │ ├── _internal_.MediaElementDownloadDialogueContent.html │ ├── _internal_.MediaElementDownloadDialogueOptions.html │ ├── _internal_.MediaElementSettingsDialogue.html │ ├── _internal_.MediaElementSettingsDialogueContent.html │ ├── _internal_.MediaElementSettingsDialogueOptions.html │ ├── _internal_.MediaElementShareDialogue.html │ ├── _internal_.MediaElementShareDialogueContent.html │ ├── _internal_.MediaElementShareDialogueOptions.html │ ├── _internal_.MobileFooterPanel-1.html │ ├── _internal_.MobileFooterPanel-2.html │ ├── _internal_.MobileFooterPanel.html │ ├── _internal_.MobileFooterPanelContent-1.html │ ├── _internal_.MobileFooterPanelContent-2.html │ ├── _internal_.MobileFooterPanelContent.html │ ├── _internal_.MobileFooterPanelOptions-1.html │ ├── _internal_.MobileFooterPanelOptions-2.html │ ├── _internal_.MobileFooterPanelOptions.html │ ├── _internal_.ModelViewerCenterPanel.html │ ├── _internal_.ModelViewerCenterPanelContent.html │ ├── _internal_.ModelViewerCenterPanelOptions.html │ ├── _internal_.ModelViewerDownloadDialogue.html │ ├── _internal_.ModelViewerDownloadDialogueContent.html │ ├── _internal_.ModelViewerDownloadDialogueOptions.html │ ├── _internal_.ModelViewerSettingsDialogue.html │ ├── _internal_.ModelViewerSettingsDialogueContent.html │ ├── _internal_.ModelViewerSettingsDialogueOptions.html │ ├── _internal_.ModelViewerShareDialogue.html │ ├── _internal_.ModelViewerShareDialogueContent.html │ ├── _internal_.ModelViewerShareDialogueOptions.html │ ├── _internal_.ModuleConfig.html │ ├── _internal_.ModuleContent.html │ ├── _internal_.ModuleOptions.html │ ├── _internal_.Modules-1.html │ ├── _internal_.Modules-2.html │ ├── _internal_.Modules-3.html │ ├── _internal_.Modules-4.html │ ├── _internal_.Modules-5.html │ ├── _internal_.Modules-6.html │ ├── _internal_.Modules-7.html │ ├── _internal_.Modules.html │ ├── _internal_.MoreInfoRightPanel.html │ ├── _internal_.MoreInfoRightPanelContent.html │ ├── _internal_.MoreInfoRightPanelOptions.html │ ├── _internal_.MultiSelectDialogue.html │ ├── _internal_.MultiSelectDialogueContent.html │ ├── _internal_.MultiSelectDialogueOptions.html │ ├── _internal_.OSDDownloadDialogue.html │ ├── _internal_.OSDDownloadDialogueContent.html │ ├── _internal_.OSDDownloadDialogueOptions.html │ ├── _internal_.OSDSettingsDialogue.html │ ├── _internal_.OSDSettingsDialogueContent.html │ ├── _internal_.OSDSettingsDialogueOptions.html │ ├── _internal_.OSDShareDialogue.html │ ├── _internal_.OSDShareDialogueContent.html │ ├── _internal_.OSDShareDialogueOptions.html │ ├── _internal_.OpenSeadragonCenterPanel.html │ ├── _internal_.OpenSeadragonCenterPanelContent.html │ ├── _internal_.OpenSeadragonCenterPanelOptions.html │ ├── _internal_.Options.html │ ├── _internal_.PDFCenterPanel.html │ ├── _internal_.PDFCenterPanelContent.html │ ├── _internal_.PDFCenterPanelOptions.html │ ├── _internal_.PDFDownloadDialogue.html │ ├── _internal_.PDFDownloadDialogueContent.html │ ├── _internal_.PDFDownloadDialogueOptions.html │ ├── _internal_.PDFHeaderPanel.html │ ├── _internal_.PDFHeaderPanelContent.html │ ├── _internal_.PDFHeaderPanelOptions.html │ ├── _internal_.PDFSettingsDialogue.html │ ├── _internal_.PDFSettingsDialogueContent.html │ ├── _internal_.PDFSettingsDialogueOptions.html │ ├── _internal_.PDFShareDialogue.html │ ├── _internal_.PDFShareDialogueContent.html │ ├── _internal_.PDFShareDialogueOptions.html │ ├── _internal_.PagingHeaderPanel.html │ ├── _internal_.PagingHeaderPanelContent.html │ ├── _internal_.PagingHeaderPanelOptions.html │ ├── _internal_.RestrictedDialogue.html │ ├── _internal_.RestrictedDialogueContent.html │ ├── _internal_.RestrictedDialogueOptions.html │ ├── _internal_.SearchFooterPanel.html │ ├── _internal_.SearchFooterPanelContent.html │ ├── _internal_.SearchFooterPanelOptions.html │ ├── _internal_.SettingsDialogue.html │ ├── _internal_.SettingsDialogueContent.html │ ├── _internal_.SettingsDialogueOptions.html │ ├── _internal_.ShareDialogue.html │ ├── _internal_.ShareDialogueContent.html │ ├── _internal_.ShareDialogueOptions.html │ └── _internal_.ThumbsCacheInvalidation.html ├── esbuild.mjs ├── eslint.config.cjs ├── jest-puppeteer.config.js ├── jest.setup.js ├── npm-examples ├── esbuild │ ├── .gitignore │ ├── dist │ │ └── .gitkeep │ ├── esbuild.mjs │ ├── package.json │ └── src │ │ ├── index.ts │ │ └── main.css └── react-scripts │ ├── .env │ ├── .gitignore │ ├── package.json │ ├── public │ └── index.html │ └── src │ ├── App.js │ ├── index.js │ ├── style.css │ └── use-universal-viewer.js ├── package-lock.json ├── package.json ├── scripts └── validate_locale.ts ├── src ├── BaseContentHandler.ts ├── ContentType.ts ├── Events.ts ├── IContentHandler.ts ├── IUVData.ts ├── Init.ts ├── UVAdapter.ts ├── UniversalViewer.ts ├── Utils.spec.ts ├── Utils.ts ├── content-handlers │ ├── iiif │ │ ├── BaseConfig.ts │ │ ├── Docs.ts │ │ ├── EPubData.ts │ │ ├── IIIFContentHandler.ts │ │ ├── IIIFData.ts │ │ ├── IIIFEvents.ts │ │ ├── IIIFExtensionHost.ts │ │ ├── JQueryPlugins.ts │ │ ├── PubSub.spec.ts │ │ ├── PubSub.ts │ │ ├── URLAdapter.ts │ │ ├── content-state │ │ │ ├── content-state.ts │ │ │ ├── expand-target.ts │ │ │ ├── parse-selector.ts │ │ │ └── selector-extensions.ts │ │ ├── extensions │ │ │ ├── config │ │ │ │ ├── ContentLeftPanel.ts │ │ │ │ ├── ExpandPanel.ts │ │ │ │ ├── ExtendedLeftPanel.ts │ │ │ │ └── ResourcesLeftPanel.ts │ │ │ ├── uv-aleph-extension │ │ │ │ ├── DownloadDialogue.ts │ │ │ │ ├── Events.ts │ │ │ │ ├── Extension.ts │ │ │ │ ├── IAlephExtension.ts │ │ │ │ ├── IAlephExtensionData.ts │ │ │ │ ├── ISettings.d.ts │ │ │ │ ├── SettingsDialogue.ts │ │ │ │ ├── ShareDialogue.ts │ │ │ │ ├── config │ │ │ │ │ ├── Config.ts │ │ │ │ │ └── config.json │ │ │ │ ├── lib │ │ │ │ │ └── aleph.css │ │ │ │ └── theme │ │ │ │ │ └── theme.less │ │ │ ├── uv-av-extension │ │ │ │ ├── DownloadDialogue.ts │ │ │ │ ├── Events.ts │ │ │ │ ├── Extension.ts │ │ │ │ ├── IAVExtension.ts │ │ │ │ ├── IAVExtensionData.ts │ │ │ │ ├── ISettings.d.ts │ │ │ │ ├── SettingsDialogue.ts │ │ │ │ ├── ShareDialogue.ts │ │ │ │ ├── config │ │ │ │ │ ├── Config.ts │ │ │ │ │ └── config.json │ │ │ │ └── theme │ │ │ │ │ └── theme.less │ │ │ ├── uv-default-extension │ │ │ │ ├── Events.ts │ │ │ │ ├── Extension.ts │ │ │ │ ├── IDefaultExtension.ts │ │ │ │ ├── SettingsDialogue.ts │ │ │ │ ├── ShareDialogue.ts │ │ │ │ ├── config │ │ │ │ │ ├── Config.ts │ │ │ │ │ └── config.json │ │ │ │ └── theme │ │ │ │ │ └── theme.less │ │ │ ├── uv-ebook-extension │ │ │ │ ├── DownloadDialogue.ts │ │ │ │ ├── Events.ts │ │ │ │ ├── Extension.ts │ │ │ │ ├── IEbookExtension.ts │ │ │ │ ├── IEbookExtensionData.ts │ │ │ │ ├── ISettings.d.ts │ │ │ │ ├── SettingsDialogue.ts │ │ │ │ ├── ShareDialogue.ts │ │ │ │ ├── config │ │ │ │ │ ├── Config.ts │ │ │ │ │ └── config.json │ │ │ │ ├── dependencies.ts │ │ │ │ ├── lib │ │ │ │ │ └── uv-ebook-components.css │ │ │ │ └── theme │ │ │ │ │ └── theme.less │ │ │ ├── uv-mediaelement-extension │ │ │ │ ├── DownloadDialogue.ts │ │ │ │ ├── Events.ts │ │ │ │ ├── Extension.ts │ │ │ │ ├── IMediaElementExtension.ts │ │ │ │ ├── SettingsDialogue.ts │ │ │ │ ├── ShareDialogue.ts │ │ │ │ ├── config │ │ │ │ │ ├── Config.ts │ │ │ │ │ └── config.json │ │ │ │ └── theme │ │ │ │ │ └── theme.less │ │ │ ├── uv-model-viewer-extension │ │ │ │ ├── DownloadDialogue.ts │ │ │ │ ├── Events.ts │ │ │ │ ├── Extension.ts │ │ │ │ ├── Orbit.ts │ │ │ │ ├── SettingsDialogue.ts │ │ │ │ ├── ShareDialogue.ts │ │ │ │ ├── config │ │ │ │ │ ├── Config.ts │ │ │ │ │ └── config.json │ │ │ │ └── theme │ │ │ │ │ └── theme.less │ │ │ ├── uv-openseadragon-extension │ │ │ │ ├── AdjustImageDialogue.ts │ │ │ │ ├── CroppedImageDimensions.ts │ │ │ │ ├── DownloadDialogue.tsx │ │ │ │ ├── Events.ts │ │ │ │ ├── Extension.ts │ │ │ │ ├── IOpenSeadragonExtensionData.ts │ │ │ │ ├── ISettings.ts │ │ │ │ ├── Mode.ts │ │ │ │ ├── MultiSelectionArgs.ts │ │ │ │ ├── SettingsDialogue.ts │ │ │ │ ├── ShareDialogue.ts │ │ │ │ ├── Store.ts │ │ │ │ ├── config │ │ │ │ │ ├── Config.ts │ │ │ │ │ └── config.json │ │ │ │ └── theme │ │ │ │ │ └── theme.less │ │ │ └── uv-pdf-extension │ │ │ │ ├── DownloadDialogue.ts │ │ │ │ ├── Events.ts │ │ │ │ ├── Extension.ts │ │ │ │ ├── IPDFExtension.ts │ │ │ │ ├── IPDFExtensionData.ts │ │ │ │ ├── SettingsDialogue.ts │ │ │ │ ├── ShareDialogue.ts │ │ │ │ ├── config │ │ │ │ ├── Config.ts │ │ │ │ └── config.json │ │ │ │ └── theme │ │ │ │ ├── theme.less │ │ │ │ └── treeviewleftpanel.less │ │ ├── helpers.ts │ │ ├── img │ │ │ └── pixel.gif │ │ ├── js │ │ │ └── embed.js │ │ ├── modules │ │ │ ├── uv-alephcenterpanel-module │ │ │ │ ├── AlephCenterPanel.ts │ │ │ │ ├── ControlsType.ts │ │ │ │ ├── DisplayMode.ts │ │ │ │ ├── Orientation.ts │ │ │ │ ├── Units.ts │ │ │ │ └── css │ │ │ │ │ └── styles.less │ │ │ ├── uv-alephleftpanel-module │ │ │ │ ├── AlephLeftPanel.ts │ │ │ │ └── css │ │ │ │ │ └── styles.less │ │ │ ├── uv-avcenterpanel-module │ │ │ │ ├── AVCenterPanel.ts │ │ │ │ └── css │ │ │ │ │ └── styles.less │ │ │ ├── uv-avmobilefooterpanel-module │ │ │ │ ├── MobileFooter.ts │ │ │ │ ├── css │ │ │ │ │ └── styles.less │ │ │ │ └── img │ │ │ │ │ ├── exit_fullscreen.png │ │ │ │ │ └── fullscreen.png │ │ │ ├── uv-contentleftpanel-module │ │ │ │ ├── ContentLeftPanel.ts │ │ │ │ ├── GalleryView.ts │ │ │ │ ├── ThumbsView.tsx │ │ │ │ ├── TreeView.ts │ │ │ │ ├── css │ │ │ │ │ └── styles.less │ │ │ │ └── img │ │ │ │ │ ├── padlock.png │ │ │ │ │ └── thumb_placeholder.png │ │ │ ├── uv-dialogues-module │ │ │ │ ├── AdjustImageDialogue.ts │ │ │ │ ├── AuthDialogue.ts │ │ │ │ ├── ClickThroughDialogue.ts │ │ │ │ ├── DownloadDialogue.ts │ │ │ │ ├── ExternalContentDialogue.ts │ │ │ │ ├── HelpDialogue.ts │ │ │ │ ├── LoginDialogue.ts │ │ │ │ ├── RestrictedDialogue.ts │ │ │ │ ├── SettingsDialogue.ts │ │ │ │ ├── ShareDialogue.ts │ │ │ │ └── css │ │ │ │ │ ├── mobile.less │ │ │ │ │ └── styles.less │ │ │ ├── uv-ebookcenterpanel-module │ │ │ │ ├── EbookCenterPanel.ts │ │ │ │ └── css │ │ │ │ │ └── styles.less │ │ │ ├── uv-ebookleftpanel-module │ │ │ │ ├── EbookLeftPanel.ts │ │ │ │ └── css │ │ │ │ │ └── styles.less │ │ │ ├── uv-ebookmobilefooterpanel-module │ │ │ │ ├── MobileFooter.ts │ │ │ │ └── css │ │ │ │ │ └── styles.less │ │ │ ├── uv-filelinkcenterpanel-module │ │ │ │ ├── FileLinkCenterPanel.ts │ │ │ │ ├── css │ │ │ │ │ └── styles.less │ │ │ │ └── img │ │ │ │ │ └── download.png │ │ │ ├── uv-mediaelementcenterpanel-module │ │ │ │ ├── MediaElementCenterPanel.ts │ │ │ │ ├── assets │ │ │ │ │ └── mejs-controls.svg │ │ │ │ ├── css │ │ │ │ │ ├── overrides.less │ │ │ │ │ └── styles.less │ │ │ │ └── js │ │ │ │ │ └── source-chooser-fixed.js │ │ │ ├── uv-mediaelementmobilefooterpanel-module │ │ │ │ ├── MobileFooter.ts │ │ │ │ ├── css │ │ │ │ │ └── styles.less │ │ │ │ └── img │ │ │ │ │ ├── zoom_in.png │ │ │ │ │ └── zoom_out.png │ │ │ ├── uv-modelviewercenterpanel-module │ │ │ │ ├── ModelViewerCenterPanel.ts │ │ │ │ ├── css │ │ │ │ │ └── styles.less │ │ │ │ └── img │ │ │ │ │ └── pin.svg │ │ │ ├── uv-modelviewermobilefooterpanel-module │ │ │ │ ├── MobileFooter.ts │ │ │ │ └── css │ │ │ │ │ └── styles.less │ │ │ ├── uv-moreinforightpanel-module │ │ │ │ ├── MoreInfoRightPanel.ts │ │ │ │ ├── css │ │ │ │ │ └── styles.less │ │ │ │ └── img │ │ │ │ │ └── copy.png │ │ │ ├── uv-multiselectdialogue-module │ │ │ │ ├── MultiSelectDialogue.ts │ │ │ │ └── css │ │ │ │ │ └── styles.less │ │ │ ├── uv-openseadragoncenterpanel-module │ │ │ │ ├── OpenSeadragonCenterPanel.ts │ │ │ │ ├── css │ │ │ │ │ ├── mobile.less │ │ │ │ │ └── styles.less │ │ │ │ └── img │ │ │ │ │ ├── adjust.png │ │ │ │ │ ├── down_arrow.png │ │ │ │ │ ├── down_arrow_disabled.png │ │ │ │ │ ├── home.png │ │ │ │ │ ├── left_arrow.png │ │ │ │ │ ├── left_arrow_disabled.png │ │ │ │ │ ├── pin.svg │ │ │ │ │ ├── pixel.gif │ │ │ │ │ ├── right_arrow.png │ │ │ │ │ ├── right_arrow_disabled.png │ │ │ │ │ ├── rotate_right.png │ │ │ │ │ ├── up_arrow.png │ │ │ │ │ ├── up_arrow_disabled.png │ │ │ │ │ ├── zoom_in.png │ │ │ │ │ └── zoom_out.png │ │ │ ├── uv-osdmobilefooterpanel-module │ │ │ │ ├── MobileFooter.ts │ │ │ │ ├── css │ │ │ │ │ └── styles.less │ │ │ │ └── img │ │ │ │ │ ├── rotate_right.png │ │ │ │ │ ├── zoom_in.png │ │ │ │ │ └── zoom_out.png │ │ │ ├── uv-pagingheaderpanel-module │ │ │ │ ├── PagingHeaderPanel.ts │ │ │ │ ├── css │ │ │ │ │ ├── icons.less │ │ │ │ │ └── styles.less │ │ │ │ └── img │ │ │ │ │ ├── first.png │ │ │ │ │ ├── grid.png │ │ │ │ │ ├── last.png │ │ │ │ │ ├── next.png │ │ │ │ │ ├── one_up.png │ │ │ │ │ ├── prev.png │ │ │ │ │ ├── settings.png │ │ │ │ │ └── two_up.png │ │ │ ├── uv-pdfcenterpanel-module │ │ │ │ ├── PDFCenterPanel.ts │ │ │ │ ├── css │ │ │ │ │ └── styles.less │ │ │ │ └── img │ │ │ │ │ ├── left_arrow.png │ │ │ │ │ ├── left_arrow_disabled.png │ │ │ │ │ ├── right_arrow.png │ │ │ │ │ ├── right_arrow_disabled.png │ │ │ │ │ ├── zoom_in.png │ │ │ │ │ └── zoom_out.png │ │ │ ├── uv-pdfheaderpanel-module │ │ │ │ ├── PDFHeaderPanel.ts │ │ │ │ ├── css │ │ │ │ │ ├── icons.less │ │ │ │ │ └── styles.less │ │ │ │ └── img │ │ │ │ │ ├── first.png │ │ │ │ │ ├── last.png │ │ │ │ │ ├── next.png │ │ │ │ │ └── prev.png │ │ │ ├── uv-pdfmobilefooterpanel-module │ │ │ │ ├── MobileFooter.ts │ │ │ │ ├── css │ │ │ │ │ └── styles.less │ │ │ │ └── img │ │ │ │ │ ├── zoom_in.png │ │ │ │ │ └── zoom_out.png │ │ │ ├── uv-resourcesleftpanel-module │ │ │ │ ├── ResourcesLeftPanel.ts │ │ │ │ ├── ThumbsView.ts │ │ │ │ └── css │ │ │ │ │ └── styles.less │ │ │ ├── uv-searchfooterpanel-module │ │ │ │ ├── FooterPanel.ts │ │ │ │ ├── css │ │ │ │ │ └── styles.less │ │ │ │ └── img │ │ │ │ │ ├── next.png │ │ │ │ │ ├── placemarker_down.png │ │ │ │ │ ├── placemarker_down_hover.png │ │ │ │ │ ├── placemarker_up.png │ │ │ │ │ ├── prev.png │ │ │ │ │ ├── search.png │ │ │ │ │ └── spinner.gif │ │ │ └── uv-shared-module │ │ │ │ ├── AnnotationResults.ts │ │ │ │ ├── Auth09.ts │ │ │ │ ├── Auth1.ts │ │ │ │ ├── AutoComplete.ts │ │ │ │ ├── BaseExpandPanel.ts │ │ │ │ ├── BaseExtension.ts │ │ │ │ ├── BaseView.ts │ │ │ │ ├── Bookmark.ts │ │ │ │ ├── CenterPanel.ts │ │ │ │ ├── Dialogue.ts │ │ │ │ ├── DownloadOption.ts │ │ │ │ ├── ExtensionState.ts │ │ │ │ ├── FooterPanel.ts │ │ │ │ ├── GenericDialogue.ts │ │ │ │ ├── HeaderPanel.ts │ │ │ │ ├── IDependencies.ts │ │ │ │ ├── IExtension.ts │ │ │ │ ├── ILocale.ts │ │ │ │ ├── ILoginDialogueOptions.ts │ │ │ │ ├── IRenderingOption.ts │ │ │ │ ├── ISharePreview.ts │ │ │ │ ├── Information.ts │ │ │ │ ├── InformationAction.ts │ │ │ │ ├── InformationArgs.ts │ │ │ │ ├── InformationFactory.ts │ │ │ │ ├── InformationType.ts │ │ │ │ ├── LeftPanel.ts │ │ │ │ ├── LoginWarningMessages.ts │ │ │ │ ├── Panel.ts │ │ │ │ ├── Point.ts │ │ │ │ ├── Position.ts │ │ │ │ ├── RightPanel.ts │ │ │ │ ├── Shell.ts │ │ │ │ ├── StringValue.ts │ │ │ │ ├── TFragment.ts │ │ │ │ ├── TestExternalResource.ts │ │ │ │ ├── ThumbsView.ts │ │ │ │ ├── XYWHFragment.spec.ts │ │ │ │ ├── XYWHFragment.ts │ │ │ │ ├── css │ │ │ │ ├── button-groups.less │ │ │ │ ├── buttons.less │ │ │ │ ├── catch-all.less │ │ │ │ ├── center-panel.less │ │ │ │ ├── footer-panel.less │ │ │ │ ├── header-panel.less │ │ │ │ ├── icons.less │ │ │ │ ├── left-panel.less │ │ │ │ ├── lg.less │ │ │ │ ├── md.less │ │ │ │ ├── mixins-extended.less │ │ │ │ ├── mixins.less │ │ │ │ ├── overlays.less │ │ │ │ ├── range.less │ │ │ │ ├── right-panel.less │ │ │ │ ├── scaffolding.less │ │ │ │ ├── sm.less │ │ │ │ ├── styles.less │ │ │ │ ├── thumbs-view.less │ │ │ │ ├── variables.less │ │ │ │ └── xl.less │ │ │ │ └── img │ │ │ │ ├── arrows_left.png │ │ │ │ ├── arrows_right.png │ │ │ │ ├── audio.png │ │ │ │ ├── bookmark.png │ │ │ │ ├── close.png │ │ │ │ ├── close_message_box.png │ │ │ │ ├── collapse.png │ │ │ │ ├── copy.png │ │ │ │ ├── dialogue_arrow.png │ │ │ │ ├── download.png │ │ │ │ ├── embed.png │ │ │ │ ├── error.png │ │ │ │ ├── exit_fullscreen.png │ │ │ │ ├── expand.png │ │ │ │ ├── fast-forward.svg │ │ │ │ ├── fast-rewind.svg │ │ │ │ ├── feedback.png │ │ │ │ ├── fullscreen.png │ │ │ │ ├── help.png │ │ │ │ ├── hidden_thumb.png │ │ │ │ ├── iiif-black.webp │ │ │ │ ├── iiif-gray.png │ │ │ │ ├── minus.png │ │ │ │ ├── modal_bg.gif │ │ │ │ ├── moreinfo.png │ │ │ │ ├── next.png │ │ │ │ ├── open.png │ │ │ │ ├── pause.png │ │ │ │ ├── play.png │ │ │ │ ├── plus.png │ │ │ │ ├── previous.png │ │ │ │ ├── print.png │ │ │ │ ├── search_result.png │ │ │ │ ├── settings.png │ │ │ │ ├── share.png │ │ │ │ ├── sprite.png │ │ │ │ ├── toggle-left-panel.svg │ │ │ │ ├── unavailable.png │ │ │ │ ├── video.png │ │ │ │ ├── volume-off.png │ │ │ │ └── volume-on.png │ │ └── themes │ │ │ ├── cy-gb │ │ │ ├── footer-panel.less │ │ │ ├── header-panel.less │ │ │ └── theme.less │ │ │ ├── en-gb │ │ │ ├── footer-panel.less │ │ │ ├── header-panel.less │ │ │ └── theme.less │ │ │ └── theme.less │ └── youtube │ │ ├── YouTubeContentHandler.ts │ │ ├── YouTubeData.ts │ │ └── YouTubeEvents.ts ├── favicon.ico ├── globals.d.ts ├── iiif-collection.json ├── index.html ├── index.ts ├── locales │ ├── cy-GB.json │ ├── en-GB.json │ ├── fr-FR.json │ ├── pl-PL.json │ └── sv-SE.json ├── mobile.html ├── netlify.toml ├── production.html ├── shim-jquery.ts ├── uv-iiif-config.json ├── uv-youtube-config.json ├── uv.css ├── uv.html ├── vercel.json └── youtube-collection.json ├── tsconfig.json ├── tslint.json ├── typedoc.json ├── webpack.config.js └── webpack.dev-server.js /.gitattributes: -------------------------------------------------------------------------------- 1 | $ cat .gitattributes 2 | *.ts linguist-language=TypeScript 3 | **/*.ts linguist-language=TypeScript 4 | /src/content-handlers/iiif/extensions/uv-pdf-extension/lib/* linguist-vendored=true -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | 2 | # Help 3 | #### The issues section is for bug reports and feature requests only. If you need help, please use [stackoverflow](http://stackoverflow.com/questions/tagged/iiif). 4 | --- 5 | # Bugs 6 | #### Before reporting a bug 7 | 8 | 1. Search issue tracker for similar issues. 9 | 10 | #### How to report a bug 11 | 12 | 1. Specify the revision number of the UV where the bug occurred. 13 | 2. Specify your browser version, operating system, and graphics card. (for example, Chrome 23.0.1271.95, Windows 7, Nvidia Quadro 2000M) 14 | 3. Describe the problem in detail. Explain what happened, and what you expected would happen. 15 | 4. Provide a small test-case (http://jsfiddle.net / http://codepen.io / http://jsbin.com) 16 | 5. If helpful, include a screenshot. Annotate the screenshot for clarity. 17 | 18 | --- 19 | # Contribution 20 | #### How to contribute to the UV 21 | 22 | 1. Make sure you have a GitHub account. 23 | 2. Fork the repository on GitHub. 24 | 4. Make changes to your clone of the repository. 25 | 5. Submit a pull request. -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | open_collective: universalviewer 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug Reports 3 | about: Use to report issues with the UV 4 | 5 | --- 6 | 7 | **UV version:** 8 | 10 | ``` 11 | universalviewer@ 12 | ``` 13 | 14 | **I'm submitting a:** 15 | 16 | - [ ] bug report => please fork one of these [codesandbox examples](https://github.com/UniversalViewer/universalviewer/wiki/UV-Examples) with a repro of your issue and include a link to it below 17 | - [ ] feature request => please use the [user stories repo](https://github.com/UniversalViewer/user-stories) 18 | - [ ] support request => Please do not submit support requests here, use [stackoverflow](http://stackoverflow.com/questions/tagged/iiif) 19 | 20 | **Current behavior:** 21 | 22 | 23 | **Expected behavior:** 24 | 25 | 26 | **Steps to reproduce:** 27 | 29 | 30 | **Related code:** 31 | 32 | ``` 33 | // insert any relevant code here 34 | ``` 35 | 36 | **Other information:** 37 | 38 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 10 | 11 | #### Description of what you did: -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "npm" 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" 7 | target-branch: "dev" 8 | - package-ecosystem: "github-actions" 9 | directory: "/" 10 | schedule: 11 | interval: "weekly" 12 | target-branch: "dev" -------------------------------------------------------------------------------- /.github/workflows/build-test.yml: -------------------------------------------------------------------------------- 1 | name: NPM build + test 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | strategy: 9 | matrix: 10 | node: [ '18' ] 11 | 12 | name: Node ${{ matrix.node }} build 13 | steps: 14 | - uses: actions/checkout@v4 15 | - uses: actions/cache@v4 16 | with: 17 | path: ~/.npm 18 | key: ${{ runner.os }}-${{ matrix.node }}-npm-${{ hashFiles('**/package-lock.lock') }} 19 | restore-keys: | 20 | ${{ runner.os }}-npm- 21 | - name: Setup node 22 | uses: actions/setup-node@v4 23 | with: 24 | node-version: ${{ matrix.node }} 25 | 26 | - run: npm ci 27 | - run: npm run build 28 | # Disable AppArmor namespace behavior that breaks tests: 29 | - run: echo 0 | sudo tee /proc/sys/kernel/apparmor_restrict_unprivileged_userns 30 | - run: npm test 31 | -------------------------------------------------------------------------------- /.github/workflows/lint-and-prettify.yml: -------------------------------------------------------------------------------- 1 | name: Lint and Prettify code 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | lint-and-prettify: 7 | name: Lint and Prettify 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - name: Setup Node 12 | uses: actions/setup-node@v4 13 | with: 14 | node-version: '18' 15 | 16 | - name: Checkout 17 | uses: actions/checkout@v4 18 | 19 | - name: Install npm dependencies 20 | run: npm install 21 | 22 | - name: Lint code 23 | run: npm run lint 24 | 25 | - name: Prettify code 26 | run: npm run prettify 27 | 28 | - name: Auto-commit fixes 29 | uses: EndBug/add-and-commit@v9 30 | with: 31 | default_author: github_actions 32 | add: "['src/']" 33 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release NPM package 2 | 3 | on: 4 | push: 5 | tags: ['v*'] 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | name: Node build 11 | steps: 12 | - uses: actions/checkout@v4 13 | - uses: actions/cache@v4 14 | with: 15 | path: ~/.npm 16 | key: ${{ runner.os }}-${{ matrix.node }}-npm-${{ hashFiles('**/package-lock.lock') }} 17 | restore-keys: | 18 | ${{ runner.os }}-npm- 19 | - name: Setup node 20 | uses: actions/setup-node@v4 21 | with: 22 | node-version: '18.x' 23 | - run: npm ci 24 | - run: npm run build 25 | 26 | release: 27 | needs: [build] 28 | runs-on: ubuntu-latest 29 | name: Release 30 | steps: 31 | - uses: actions/checkout@v4 32 | - uses: actions/cache@v4 33 | with: 34 | path: ~/.npm 35 | key: ${{ runner.os }}-${{ matrix.node }}-npm-${{ hashFiles('**/package-lock.lock') }} 36 | restore-keys: | 37 | ${{ runner.os }}-npm- 38 | - name: Setup node 39 | uses: actions/setup-node@v4 40 | with: 41 | node-version: '18.x' 42 | 43 | - name: Set tag 44 | id: tagName 45 | run: echo ::set-output name=tag::${GITHUB_REF#refs/*/} 46 | 47 | - run: npm ci 48 | - run: npm run prepublishOnly 49 | 50 | - uses: JS-DevTools/npm-publish@v3 51 | with: 52 | token: ${{ secrets.NPM_TOKEN }} 53 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | buildcache 2 | dist 3 | 4 | ################# 5 | ## TypeScript 6 | ################# 7 | 8 | .tscache 9 | typings 10 | 11 | ################# 12 | ## Webstorm 13 | ################# 14 | 15 | .idea 16 | 17 | ################# 18 | ## Node 19 | ################# 20 | 21 | lib-cov 22 | *.seed 23 | *.log 24 | *.csv 25 | *.dat 26 | *.out 27 | *.pid 28 | *.gz 29 | 30 | pids 31 | logs 32 | results 33 | 34 | npm-debug.log 35 | node_modules 36 | 37 | ################# 38 | ## JavaScript 39 | ################# 40 | 41 | *.js 42 | *.js.map 43 | *.min.map 44 | /config.js 45 | !src/extensions/*/config.js 46 | !src/js/*.js 47 | !src/*/*/js/*.js 48 | !src/extensions/*/dependencies.js 49 | !jest.setup.js 50 | src/extensions/*/lib/*.js 51 | !src/extensions/*/lib/*.proxy.js 52 | !src/extensions/*/config.js 53 | 54 | ################# 55 | ## Misc 56 | ################# 57 | 58 | Thumbs.db 59 | Desktop.ini 60 | .DS_Store 61 | *.tmp.txt 62 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/.gitmodules -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/.npmignore -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | legacy-peer-deps=true -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v14.18.1 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/.prettierignore -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5" 3 | } 4 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "Jest Tests", 11 | "program": "${workspaceRoot}/node_modules/jest/bin/jest.js", 12 | "cwd": "${workspaceRoot}", 13 | "args": [ 14 | 15 | ] 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.exclude": { 3 | "**/.git": true, 4 | "**/.svn": true, 5 | "**/.DS_Store": true, 6 | "node_modules": false, 7 | "dist": false, 8 | "**/*.js": { "when": "$(basename).ts" }, 9 | "**/*.js.map": true 10 | }, 11 | "typescript.check.workspaceVersion": false, 12 | "typescript.tsdk": "node_modules\\typescript\\lib", 13 | "editor.defaultFormatter": "esbenp.prettier-vscode", 14 | "editor.formatOnSave": true, 15 | "prettier.requireConfig": true, 16 | "editor.tabSize": 2, 17 | "editor.detectIndentation": false, 18 | "editor.codeActionsOnSave": { 19 | "source.organizeImports": "never", 20 | "source.sortImports": "never" 21 | }, 22 | "eslint.validate": [ 23 | "typescript", 24 | "typescriptreact", 25 | "javascript", 26 | "javascriptreact" 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "npm:build", 6 | "type": "shell", 7 | "group": { 8 | "kind": "build", 9 | "isDefault": true 10 | }, 11 | "command": "npm run build", 12 | "problemMatcher": [] 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Wellcome Library 4 | http://wellcomelibrary.org 5 | 6 | Copyright (c) 2015 British Library 7 | http://bl.uk 8 | 9 | Copyright (c) 2015 National Library of Wales 10 | http://www.llgc.org.uk 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /__tests__/configuration_options.js: -------------------------------------------------------------------------------- 1 | describe('Configuration options', () => { 2 | describe('thumb cache invalidation', () => { 3 | beforeEach(async () => { 4 | await page.goto('http://localhost:4444/'); 5 | await page.waitForSelector('#thumb0'); 6 | }); 7 | it.skip('when set to false does not provide timestamp', async () => { 8 | await page.evaluate(() => uv.set( 9 | { config: { modules: { contentLeftPanel: { options: { thumbsCacheInvalidation: { enabled: false }}}}}} 10 | )); 11 | await page.waitForSelector('#thumb0'); 12 | const imageSrc = await page.$eval('#thumb0 img', e => e.src); 13 | expect(imageSrc).toEqual( 14 | expect.stringMatching( 15 | 'https://dlcs.io/iiif-img/wellcome/1/ff2085d5-a9c7-412e-9dbe-dda87712228d/full/90,/0/default.jpg' 16 | ) 17 | ); 18 | }); 19 | it.skip('has a configurable parameter type', async () => { 20 | await page.evaluate(() => uv.set( 21 | { config: { modules: { contentLeftPanel: { options: { thumbsCacheInvalidation: { paramType: '#' }}}}}} 22 | )); 23 | await page.waitForSelector('#thumb0'); 24 | const imageSrc = await page.$eval('#thumb0 img', e => e.src); 25 | expect(imageSrc).toEqual( 26 | expect.stringContaining( 27 | 'https://dlcs.io/iiif-img/wellcome/1/ff2085d5-a9c7-412e-9dbe-dda87712228d/full/90,/0/default.jpg#t=' 28 | ) 29 | ); 30 | }); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /__tests__/test.js: -------------------------------------------------------------------------------- 1 | test.skip('Configuration options', () => {}); 2 | 3 | const puppeteer = require('puppeteer'); 4 | 5 | describe('Universal Viewer', () => { 6 | let browser; 7 | let page; 8 | 9 | beforeAll(async () => { 10 | browser = await puppeteer.launch(); 11 | page = await browser.newPage(); 12 | await page.goto('http://localhost:4444'); 13 | }); 14 | 15 | afterAll(async () => { 16 | await browser.close(); 17 | }); 18 | 19 | it('has the correct page title', async () => { 20 | const title = await page.title(); 21 | expect(title).toBe('Universal Viewer Examples'); 22 | }); 23 | 24 | it('loads the viewer images', async () => { 25 | await page.waitForSelector('#thumb-0'); 26 | const imageSrc = await page.$eval('#thumb-0 img', e => e.src); 27 | expect(imageSrc).toEqual( 28 | expect.stringContaining( 29 | 'https://iiif.wellcomecollection.org/image/b18035723_0001.JP2/full/90,/0/default.jpg' 30 | ) 31 | ); 32 | }); 33 | 34 | it('can toggle thumbnail label truncation', async () => { 35 | await page.waitForSelector('#truncateThumbnailLabels'); 36 | 37 | const isCheckedBeforeToggle = await page.$eval('#truncateThumbnailLabels', checkbox => checkbox.checked); 38 | expect(isCheckedBeforeToggle).toBe(true); 39 | 40 | const labelOverflowBeforeToggle = await page.evaluate(() => { 41 | const label = document.querySelector('.thumbsView .thumbs .thumb .info .label'); 42 | return getComputedStyle(label).overflowX; 43 | }); 44 | expect(labelOverflowBeforeToggle).toBe('hidden'); 45 | 46 | await page.evaluate(() => { 47 | document.querySelector('#truncateThumbnailLabels').click(); 48 | }); 49 | 50 | const isCheckedAfterToggle = await page.$eval('#truncateThumbnailLabels', checkbox => checkbox.checked); 51 | expect(isCheckedAfterToggle).toBe(false); 52 | 53 | const labelOverflowAfterToggle = await page.evaluate(() => { 54 | const label = document.querySelector('.thumbsView .thumbs .thumb .info .label'); 55 | return getComputedStyle(label).overflowX; 56 | }); 57 | expect(labelOverflowAfterToggle).toBe('visible'); 58 | }); 59 | 60 | it('settings button is visible', async () => { 61 | 62 | await page.waitForSelector('.btn.imageBtn.settings'); 63 | 64 | const isSettingsButtonVisible = await page.evaluate(() => { 65 | const settingsButton = document.querySelector('.btn.imageBtn.settings'); 66 | const style = window.getComputedStyle(settingsButton); 67 | return style.getPropertyValue('visibility') !== 'hidden' && style.getPropertyValue('display') !== 'none'; 68 | }); 69 | 70 | expect(isSettingsButtonVisible).toBe(true); 71 | }); 72 | }); 73 | 74 | -------------------------------------------------------------------------------- /docs/.nojekyll: -------------------------------------------------------------------------------- 1 | TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. -------------------------------------------------------------------------------- /docs/CNAME: -------------------------------------------------------------------------------- 1 | docs.universalviewer.io 2 | -------------------------------------------------------------------------------- /docs/assets/highlight.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --light-code-background: #FFFFFF; 3 | --dark-code-background: #1E1E1E; 4 | } 5 | 6 | @media (prefers-color-scheme: light) { :root { 7 | --code-background: var(--light-code-background); 8 | } } 9 | 10 | @media (prefers-color-scheme: dark) { :root { 11 | --code-background: var(--dark-code-background); 12 | } } 13 | 14 | :root[data-theme='light'] { 15 | --code-background: var(--light-code-background); 16 | } 17 | 18 | :root[data-theme='dark'] { 19 | --code-background: var(--dark-code-background); 20 | } 21 | 22 | pre, code { background: var(--code-background); } 23 | -------------------------------------------------------------------------------- /esbuild.mjs: -------------------------------------------------------------------------------- 1 | import path from "path"; 2 | import { build } from "esbuild"; 3 | import { lessLoader } from "esbuild-plugin-less"; 4 | import svg from "esbuild-plugin-svg"; 5 | import fs from "fs"; 6 | import LessPluginCleanCSS from "less-plugin-clean-css"; 7 | 8 | const pkg = JSON.parse(fs.readFileSync("./package.json").toString()); 9 | 10 | // These are NPM packages that don't work with external bundlers without configuration. 11 | // To avoid confusion, this will ensure they are included in the ESM bundle. 12 | const bundledPackages = [ 13 | "jquery", 14 | "jsviews", 15 | "xss", 16 | "@iiif/vocabulary", 17 | "@edsilv/jquery-plugins", 18 | ]; 19 | 20 | // This plugin will ensure that mediaelement css is loaded correctly. It's currently using a webpack specific 21 | // format. 22 | let resolveMediaElement = { 23 | name: "resolve-media-element", 24 | setup(build) { 25 | // Hack for resolution of webpack specific. 26 | build.onResolve({ filter: /~mediaelement/ }, (args) => { 27 | const t = args.path.split("~mediaelement")[1]; 28 | return { 29 | path: path.join(process.cwd(), "./node_modules/mediaelement", t), 30 | }; 31 | }); 32 | }, 33 | }; 34 | 35 | async function main() { 36 | await build({ 37 | // Enables code splitting, similar to webpack. 38 | splitting: true, 39 | outdir: path.resolve(process.cwd(), "dist/esm"), 40 | entryPoints: [path.resolve(process.cwd(), "src/index.ts")], 41 | bundle: true, 42 | target: "es2020", 43 | format: "esm", 44 | globalName: "UV", 45 | minify: true, 46 | external: [ 47 | ...Object.keys(pkg.dependencies).filter( 48 | (t) => t.indexOf(bundledPackages) !== -1 49 | ), 50 | ], 51 | plugins: [ 52 | resolveMediaElement, 53 | lessLoader({ 54 | paths: [ 55 | "node_modules/", 56 | "./src/content-handlers/iiif/modules/uv-shared-module/img", 57 | "./src/content-handlers/iiif/modules/uv-pagingheaderpanel-module/img", 58 | "./src/content-handlers/iiif/modules/uv-openseadragoncenterpanel-module/img", 59 | "./src/content-handlers/iiif/modules/uv-searchfooterpanel-module/img", 60 | ], 61 | math: "always", 62 | javascriptEnabled: true, 63 | plugins: [ 64 | new LessPluginCleanCSS({ 65 | advanced: true, 66 | level: 2, 67 | }), 68 | ], 69 | }), 70 | svg(), 71 | ], 72 | loader: { 73 | ".ts": "ts", 74 | ".png": "dataurl", 75 | ".gif": "dataurl", 76 | }, 77 | }); 78 | } 79 | 80 | main(); 81 | -------------------------------------------------------------------------------- /eslint.config.cjs: -------------------------------------------------------------------------------- 1 | // eslint.config.js 2 | const { defineConfig } = require("eslint/config"); 3 | const tsPlugin = require("@typescript-eslint/eslint-plugin"); 4 | const tsParser = require("@typescript-eslint/parser"); 5 | const reactPlugin = require("eslint-plugin-react"); 6 | const prettierConfig = require("eslint-config-prettier"); 7 | 8 | module.exports = defineConfig([ 9 | { 10 | files: ["**/*.{js,jsx,ts,tsx}"], 11 | languageOptions: { 12 | parser: tsParser, 13 | parserOptions: { 14 | ecmaFeatures: { 15 | jsx: true, 16 | }, 17 | sourceType: "module", 18 | }, 19 | }, 20 | plugins: { 21 | "@typescript-eslint": tsPlugin, 22 | react: reactPlugin, 23 | }, 24 | rules: { 25 | semi: "error", 26 | "prefer-const": "error", 27 | }, 28 | settings: { 29 | react: { 30 | version: "detect", 31 | }, 32 | }, 33 | }, 34 | prettierConfig, 35 | ]); 36 | -------------------------------------------------------------------------------- /jest-puppeteer.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | launch: { 3 | headless: process.env.CI === 'true', 4 | args: [`--window-size=1920,1080`], 5 | defaultViewport: { 6 | width: 1920, 7 | height: 1080 8 | } 9 | }, 10 | server: { 11 | command: 'npm run e2eserve', 12 | port: 4444, 13 | }, 14 | setupFilesAfterEnv: [ 15 | './jest.setup.js' 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /jest.setup.js: -------------------------------------------------------------------------------- 1 | jest.setTimeout(10000); -------------------------------------------------------------------------------- /npm-examples/esbuild/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | package-lock.json 4 | yarn.lock 5 | !dist/.gitkeep -------------------------------------------------------------------------------- /npm-examples/esbuild/dist/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/npm-examples/esbuild/dist/.gitkeep -------------------------------------------------------------------------------- /npm-examples/esbuild/esbuild.mjs: -------------------------------------------------------------------------------- 1 | import { build } from 'esbuild'; 2 | import { writeFileSync } from "fs"; 3 | import * as path from 'path'; 4 | import serve, { error, log } from 'create-serve'; 5 | 6 | const watch = process.argv.includes('--watch') || process.argv.includes('-w'); 7 | 8 | async function main() { 9 | writeFileSync( 10 | path.join(process.cwd(), "./dist/index.html"), 11 | ` 12 | 13 | 14 | 15 | 16 | UV Frontend 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | ` 25 | ); 26 | 27 | build({ 28 | entryPoints: ["src/index.ts"], 29 | outfile: "dist/bundle.js", 30 | bundle: true, 31 | minify: true, 32 | watch: watch && { 33 | onRebuild(err) { 34 | serve.update(); 35 | err ? error('× Failed') : log('✓ Updated'); 36 | } 37 | }, 38 | sourcemap: true, 39 | target: ["chrome58"], 40 | }); 41 | 42 | serve.start({ 43 | port: 3001, 44 | root: 'dist' 45 | }); 46 | } 47 | 48 | main() -------------------------------------------------------------------------------- /npm-examples/esbuild/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "esbuild-demo", 3 | "scripts": { 4 | "start": "node esbuild.mjs -w", 5 | "build": "node esbuild.mjs" 6 | }, 7 | "dependencies": { 8 | "esbuild": "^0.13.12", 9 | "create-serve": "^1.0.1", 10 | "universalviewer": "../../" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /npm-examples/esbuild/src/index.ts: -------------------------------------------------------------------------------- 1 | import { init } from 'universalviewer'; 2 | import 'universalviewer/dist/esm/index.css'; 3 | import './main.css'; 4 | 5 | const container = document.getElementById('root') as HTMLDivElement; 6 | if (container) { 7 | init(container, { 8 | manifest: 'https://wellcomelibrary.org/iiif/b18035723/manifest', 9 | }) 10 | } -------------------------------------------------------------------------------- /npm-examples/esbuild/src/main.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | margin: 0; 3 | padding: 0; 4 | height: 100%; 5 | } 6 | 7 | .uv { 8 | height: 100%; 9 | } -------------------------------------------------------------------------------- /npm-examples/react-scripts/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true -------------------------------------------------------------------------------- /npm-examples/react-scripts/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | package-lock.json 4 | yarn.lock 5 | !src/*.js -------------------------------------------------------------------------------- /npm-examples/react-scripts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react", 3 | "version": "1.0.0", 4 | "description": "React example starter project", 5 | "keywords": [ 6 | "react", 7 | "starter" 8 | ], 9 | "main": "src/index.js", 10 | "dependencies": { 11 | "@google/model-viewer": "0.7.2", 12 | "babel-jest": "^26.6.3", 13 | "jquery": "^3.6.0", 14 | "react": "17.0.2", 15 | "react-dom": "17.0.2", 16 | "react-scripts": "4.0.0", 17 | "universalviewer": "../../" 18 | }, 19 | "devDependencies": { 20 | "@babel/runtime": "7.13.8", 21 | "typescript": "4.1.3" 22 | }, 23 | "scripts": { 24 | "start": "react-scripts start", 25 | "build": "react-scripts build", 26 | "test": "react-scripts test --env=jsdom", 27 | "eject": "react-scripts eject" 28 | }, 29 | "browserslist": [ 30 | ">0.2%", 31 | "not dead", 32 | "not ie <= 11", 33 | "not op_mini all" 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /npm-examples/react-scripts/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /npm-examples/react-scripts/src/App.js: -------------------------------------------------------------------------------- 1 | import React, { useRef, useState } from "react"; 2 | import "./style.css"; 3 | import "universalviewer/dist/esm/index.css"; 4 | import { useUniversalViewer, useEvent } from "./use-universal-viewer"; 5 | import { BaseEvents } from "universalviewer"; 6 | 7 | const UV = ({ manifest, parentWidth }) => { 8 | const el = useRef(); 9 | const viewer = useUniversalViewer( 10 | el, 11 | { 12 | manifest, 13 | }, 14 | [parentWidth] 15 | ); 16 | 17 | useEvent(viewer, BaseEvents.CANVAS_INDEX_CHANGE, (cidx) => { 18 | console.log("New canvas index", cidx); 19 | }); 20 | 21 | return
; 22 | }; 23 | 24 | export default function App() { 25 | const [view, setView] = useState("1"); 26 | 27 | return ( 28 |
29 |
30 | 31 | 32 |
33 |
34 |
41 | 45 |
46 | {view === "2" ? ( 47 |
48 | 52 |
53 | ) : null} 54 |
55 |
56 | ); 57 | } 58 | -------------------------------------------------------------------------------- /npm-examples/react-scripts/src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { createRoot } from "react-dom/client"; 3 | 4 | import App from "./App"; 5 | 6 | const rootElement = document.getElementById("root"); 7 | createRoot( 8 | 9 | 10 | , 11 | rootElement 12 | ); 13 | -------------------------------------------------------------------------------- /npm-examples/react-scripts/src/style.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | margin: 0; 3 | padding: 0; 4 | } -------------------------------------------------------------------------------- /npm-examples/react-scripts/src/use-universal-viewer.js: -------------------------------------------------------------------------------- 1 | import { useLayoutEffect, useState } from "react"; 2 | import { init } from "universalviewer"; 3 | 4 | export function useEvent(viewer, name, cb) { 5 | useLayoutEffect(() => { 6 | if (viewer) { 7 | return viewer.subscribe(name, cb); 8 | } 9 | }, [viewer]); 10 | } 11 | 12 | export function useUniversalViewer(ref, options, resizeIfTheseChange = []) { 13 | const [uv, setUv] = useState(); 14 | 15 | useLayoutEffect(() => { 16 | if (uv) { 17 | try { 18 | ref.current.firstChild.style.width = ref.current.offsetWidth + "px"; 19 | ref.current.firstChild.style.height = ref.current.offsetHeight + "px"; 20 | uv.resize(); 21 | } catch (e) { 22 | // This may fail if we are disposed. 23 | } 24 | } 25 | }, resizeIfTheseChange); 26 | 27 | useLayoutEffect(() => { 28 | const currentUv = init(ref.current, options); 29 | setUv(currentUv); 30 | 31 | return () => { 32 | currentUv.dispose(); 33 | }; 34 | }, []); 35 | 36 | return uv; 37 | } 38 | -------------------------------------------------------------------------------- /src/BaseContentHandler.ts: -------------------------------------------------------------------------------- 1 | import { IContentHandler } from "./IContentHandler"; 2 | import { IUVOptions } from "./UniversalViewer"; 3 | import { UVAdapter } from "./UVAdapter"; 4 | import { Events } from "./Events"; 5 | import { merge } from "./Utils"; 6 | 7 | export type EventListener = { 8 | name: string; 9 | cb: Function; 10 | ctx?: any; 11 | }; 12 | 13 | type EventListenerDictionaryItem = Pick; 14 | 15 | export default class BaseContentHandler 16 | implements IContentHandler 17 | { 18 | protected _el: HTMLElement; 19 | private _eventListeners: { 20 | [key: string]: EventListenerDictionaryItem[]; 21 | }; 22 | 23 | constructor( 24 | public options: IUVOptions, 25 | public adapter?: UVAdapter, 26 | eventListeners?: EventListener[] 27 | ) { 28 | this._el = this.options.target; 29 | 30 | // add event listeners 31 | if (eventListeners) { 32 | eventListeners.forEach(({ name, cb }) => { 33 | this.on(name, cb); 34 | }); 35 | } 36 | } 37 | 38 | public set(data: IUVData, initial?: boolean): void {} 39 | 40 | public on(name: string, cb: Function, ctx?: any): void { 41 | var e = this._eventListeners || (this._eventListeners = {}); 42 | 43 | (e[name] || (e[name] = [])).push({ 44 | cb, 45 | ctx, 46 | }); 47 | } 48 | 49 | public fire(name: string, ...args: any[]): void { 50 | var data = [].slice.call(arguments, 1); 51 | var evtArr = ( 52 | (this._eventListeners || (this._eventListeners = {}))[name] || [] 53 | ).slice(); 54 | var i = 0; 55 | var len = evtArr.length; 56 | 57 | for (i; i < len; i++) { 58 | evtArr[i].cb.apply(evtArr[i].ctx, data); 59 | } 60 | } 61 | 62 | public showSpinner(): void { 63 | this._el.parentElement?.classList.remove("loaded"); 64 | } 65 | 66 | public hideSpinner(): void { 67 | this._el.parentElement?.classList.add("loaded"); 68 | } 69 | 70 | public async configure(config: any): Promise { 71 | const promises: Promise[] = [] as any; 72 | 73 | this.fire(Events.CONFIGURE, { 74 | config, 75 | cb: (promise) => { 76 | promises.push(promise); 77 | }, 78 | }); 79 | 80 | if (promises.length) { 81 | const configs = await Promise.all(promises); 82 | 83 | const mergedConfigs = configs.reduce((previous, current) => { 84 | return merge(previous, current); 85 | }); 86 | 87 | config = merge(config, mergedConfigs); 88 | } 89 | 90 | return config; 91 | } 92 | 93 | public exitFullScreen(): void {} 94 | 95 | public resize(): void {} 96 | 97 | public dispose(): void { 98 | this._el.innerHTML = ""; 99 | this._el.className = ""; 100 | this.adapter?.dispose(); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/ContentType.ts: -------------------------------------------------------------------------------- 1 | export enum ContentType { 2 | IIIFLEGACY = "manifest", 3 | IIIF = "iiifManifestId", 4 | YOUTUBE = "youTubeVideoId", 5 | UNKNOWN = "unknown", 6 | } 7 | -------------------------------------------------------------------------------- /src/Events.ts: -------------------------------------------------------------------------------- 1 | export class Events { 2 | static CONFIGURE: string = "configure"; 3 | static CREATED: string = "created"; 4 | static DROP: string = "drop"; 5 | static ERROR: string = "error"; 6 | static EXIT_FULLSCREEN: string = "exitFullScreen"; 7 | static EXTERNAL_RESOURCE_OPENED: string = "externalResourceOpened"; 8 | static LOAD: string = "load"; 9 | static LOAD_FAILED: string = "loadFailed"; 10 | static RELOAD: string = "reload"; 11 | static RESIZE: string = "resize"; 12 | static TOGGLE_FULLSCREEN: string = "toggleFullScreen"; 13 | } 14 | -------------------------------------------------------------------------------- /src/IContentHandler.ts: -------------------------------------------------------------------------------- 1 | import { UVAdapter } from "./UVAdapter"; 2 | 3 | export interface IContentHandler { 4 | // adapter.bindTo() sets this. 5 | // when the content handler is disposed, it also disposes the adapter. 6 | adapter?: UVAdapter | undefined; 7 | set(data: IUVData, initial?: boolean): void; 8 | dispose(): void; 9 | on(name: string, callback: Function, ctx?: any): void; 10 | resize(): void; 11 | exitFullScreen(): void; 12 | } 13 | -------------------------------------------------------------------------------- /src/IUVData.ts: -------------------------------------------------------------------------------- 1 | import { EPubData } from "./content-handlers/iiif/EPubData"; 2 | import { IIIFData } from "./content-handlers/iiif/IIIFData"; 3 | import { YouTubeData } from "./content-handlers/youtube/YouTubeData"; 4 | import { ILocale } from "./content-handlers/iiif/modules/uv-shared-module/ILocale"; 5 | import { BaseConfig } from "./content-handlers/iiif/BaseConfig"; 6 | 7 | export interface IUVData 8 | extends IIIFData, 9 | EPubData, 10 | YouTubeData { 11 | config?: T; // do not pass this on initialisation, internal use only 12 | debug?: boolean; 13 | embedded?: boolean; 14 | isReload?: boolean; 15 | locales?: ILocale[]; 16 | target?: string; 17 | } 18 | -------------------------------------------------------------------------------- /src/UVAdapter.ts: -------------------------------------------------------------------------------- 1 | export class UVAdapter { 2 | public readonly: boolean = false; 3 | 4 | constructor(readonly: boolean) { 5 | this.readonly = readonly; 6 | } 7 | 8 | public get(_key: string, _defaultValue: T | undefined): T | undefined { 9 | return undefined; 10 | } 11 | 12 | public set(_key: string, _value: T): void {} 13 | 14 | public dispose(): void {} 15 | } 16 | -------------------------------------------------------------------------------- /src/Utils.spec.ts: -------------------------------------------------------------------------------- 1 | import { propertiesChanged } from "./Utils"; 2 | 3 | describe("Utils", () => { 4 | it("correctly detects manifestindex changes", () => { 5 | const propChanged: boolean = propertiesChanged( 6 | { manifestIndex: 0 }, 7 | { manifestIndex: 1 }, 8 | ["manifestIndex"] 9 | ); 10 | expect(propChanged).toEqual(true); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/Docs.ts: -------------------------------------------------------------------------------- 1 | import { Config as ModelViewerExtensionConfig } from "@/content-handlers/iiif/extensions/uv-model-viewer-extension/config/Config"; 2 | import { Config as AlephExtensionConfig } from "@/content-handlers/iiif/extensions/uv-aleph-extension/config/Config"; 3 | import { Config as AVExtensionConfig } from "@/content-handlers/iiif/extensions/uv-av-extension/config/Config"; 4 | import { Config as EbookExtensionConfig } from "@/content-handlers/iiif/extensions/uv-ebook-extension/config/Config"; 5 | import { Config as MediaElementExtensionConfig } from "@/content-handlers/iiif/extensions/uv-mediaelement-extension/config/Config"; 6 | import { Config as OSDExtensionConfig } from "@/content-handlers/iiif/extensions/uv-openseadragon-extension/config/Config"; 7 | import { Config as DefaultExtensionConfig } from "@/content-handlers/iiif/extensions/uv-default-extension/config/Config"; 8 | import { Config as PDFExtensionConfig } from "@/content-handlers/iiif/extensions/uv-pdf-extension/config/Config"; 9 | 10 | export type IIIFContentHandlerConfig = { 11 | aleph: AlephExtensionConfig; 12 | av: AVExtensionConfig; 13 | default: DefaultExtensionConfig; 14 | ebook: EbookExtensionConfig; 15 | mediaelement: MediaElementExtensionConfig; 16 | modelViewer: ModelViewerExtensionConfig; 17 | osd: OSDExtensionConfig; 18 | pdf: PDFExtensionConfig; 19 | }; 20 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/EPubData.ts: -------------------------------------------------------------------------------- 1 | export interface EPubData { 2 | cfi?: string; 3 | } 4 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/IIIFData.ts: -------------------------------------------------------------------------------- 1 | export interface IIIFData { 2 | annotations?: string; 3 | canvasId?: string; 4 | canvasIndex?: number; 5 | collectionIndex?: number; 6 | iiif_content?: string; 7 | iiifManifestId?: string; 8 | manifestIndex?: number; 9 | muted?: boolean; 10 | rangeId?: string; 11 | rotation?: number; 12 | xywh?: string; 13 | } 14 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/IIIFExtensionHost.ts: -------------------------------------------------------------------------------- 1 | import { IExtension } from "./modules/uv-shared-module/IExtension"; 2 | import { EventHandler, EventHandlerWithName } from "./PubSub"; 3 | import BaseContentHandler from "../../BaseContentHandler"; 4 | import { IIIFData } from "./IIIFData"; 5 | 6 | export interface IIIFExtensionHost extends BaseContentHandler { 7 | extension: IExtension | undefined; 8 | isFullScreen: boolean; 9 | publish(event: string, args?: any, extra?: any): void; 10 | subscribe(event: string, handler: EventHandler): void; 11 | subscribeAll(handler: EventHandlerWithName): void; 12 | resize(): void; 13 | exitFullScreen(): void; 14 | } 15 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/PubSub.spec.ts: -------------------------------------------------------------------------------- 1 | import { PubSub } from "./PubSub"; 2 | 3 | describe("PubSub", () => { 4 | it("subscribes to an event", () => { 5 | const pubsub = new PubSub(); 6 | 7 | const eventName = "test-event"; 8 | let eventArgs = undefined; 9 | let handled = false; 10 | 11 | const handler = (e) => { 12 | handled = true; 13 | eventArgs = e; 14 | }; 15 | 16 | pubsub.subscribe(eventName, handler); 17 | 18 | pubsub.publish(eventName, "test"); 19 | 20 | expect(handled).toEqual(true); 21 | expect(eventArgs).toEqual("test"); 22 | 23 | // test unsubscribe 24 | 25 | // eventArgs = undefined; 26 | // handled = false; 27 | 28 | // pubsub.unsubscribe(eventName, handler); 29 | 30 | // pubsub.publish(eventName, "test"); 31 | 32 | // expect(handled).toEqual(false); 33 | // expect(eventArgs).toEqual(undefined); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/PubSub.ts: -------------------------------------------------------------------------------- 1 | export type EventHandler = (args: any, extra?: any) => void; 2 | export type EventHandlerWithName = (event: string, args: any) => void; 3 | 4 | export class PubSub { 5 | events: { [key: string]: EventHandler[] } = {}; 6 | onPublishHandler: EventHandlerWithName = () => {}; 7 | 8 | constructor() {} 9 | 10 | public publish(name: string, args?: any, extra?: any) { 11 | const handlers: EventHandler[] = this.events[name]; 12 | if (handlers) { 13 | handlers.forEach((handler) => { 14 | handler.call(this, args, extra); 15 | }); 16 | } 17 | this.onPublishHandler.call(this, name, args); 18 | } 19 | 20 | public subscribe(name: string, handler: EventHandler) { 21 | let handlers: EventHandler[] = this.events[name]; 22 | if (handlers === undefined) { 23 | handlers = this.events[name] = []; 24 | } 25 | handlers.push(handler); 26 | } 27 | 28 | public subscribeAll(handler: EventHandlerWithName) { 29 | this.onPublishHandler = handler; 30 | } 31 | 32 | public unsubscribe(name: string, handler: EventHandler) { 33 | const handlers: EventHandler[] = this.events[name]; 34 | if (handlers === undefined) return; 35 | 36 | const handlerIdx: number = handlers.indexOf(handler); 37 | handlers.splice(handlerIdx); 38 | } 39 | 40 | public unsubscribeAll() { 41 | this.onPublishHandler = () => {}; 42 | } 43 | 44 | public dispose() { 45 | this.events = {}; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/content-state/selector-extensions.ts: -------------------------------------------------------------------------------- 1 | export type BoxSelector = { 2 | type: "BoxSelector"; 3 | unit?: "percent" | "pixel"; 4 | x: number; 5 | y: number; 6 | width: number; 7 | height: number; 8 | }; 9 | 10 | export type TemporalSelector = { 11 | type: "TemporalSelector"; 12 | startTime: number; 13 | endTime?: number; // optional end time. 14 | }; 15 | 16 | export type TemporalBoxSelector = { 17 | type: "TemporalBoxSelector"; 18 | x: number; 19 | y: number; 20 | width: number; 21 | height: number; 22 | startTime: number; 23 | endTime?: number; 24 | }; 25 | 26 | export type SupportedSelectors = 27 | | TemporalSelector 28 | | BoxSelector 29 | | TemporalBoxSelector; 30 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/config/ExpandPanel.ts: -------------------------------------------------------------------------------- 1 | import { ModuleConfig } from "../../BaseConfig"; 2 | 3 | export type ExpandPanelOptions = { 4 | /** Determines if expand full is enabled */ 5 | expandFullEnabled: boolean; 6 | /** Determines the duration of the panel expand/collapse animation */ 7 | panelAnimationDuration: number; 8 | /** Width of the collapsed panel */ 9 | panelCollapsedWidth: number; 10 | /** Width of the expanded panel */ 11 | panelExpandedWidth: number; 12 | /** Determines if the panel is open */ 13 | panelOpen: boolean; 14 | }; 15 | 16 | export type ExpandPanelContent = { 17 | collapse: string; 18 | collapseFull: string; 19 | expand: string; 20 | expandFull: string; 21 | }; 22 | 23 | export type ExpandPanel = ModuleConfig & { 24 | options: ExpandPanelOptions; 25 | content: ExpandPanelContent; 26 | }; 27 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/config/ExtendedLeftPanel.ts: -------------------------------------------------------------------------------- 1 | import { ContentLeftPanel } from "./ContentLeftPanel"; 2 | import { ResourcesLeftPanel } from "./ResourcesLeftPanel"; 3 | 4 | export type ExtendedLeftPanel = ContentLeftPanel & ResourcesLeftPanel & {}; 5 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/config/ResourcesLeftPanel.ts: -------------------------------------------------------------------------------- 1 | import { ModuleConfig } from "../../BaseConfig"; 2 | import { ExpandPanelContent, ExpandPanelOptions } from "./ExpandPanel"; 3 | 4 | type ResourcesLeftPanelOptions = ExpandPanelOptions & { 5 | /** Determines if full expansion is enabled */ 6 | expandFullEnabled: boolean; 7 | /** Duration of the panel animation */ 8 | panelAnimationDuration: number; 9 | /** Width of the panel when collapsed */ 10 | panelCollapsedWidth: number; 11 | /** Width of the panel when expanded */ 12 | panelExpandedWidth: number; 13 | /** Determines if the panel is open */ 14 | panelOpen: boolean; 15 | /** Width of the thumbnail in two column view */ 16 | twoColThumbWidth: number; 17 | /** Height of the thumbnail in two column view */ 18 | twoColThumbHeight: number; 19 | /** Width of the thumbnail in one column view */ 20 | oneColThumbWidth: number; 21 | /** Height of the thumbnail in one column view */ 22 | oneColThumbHeight: number; 23 | }; 24 | 25 | type ResourcesLeftPanelContent = ExpandPanelContent & { 26 | title: string; 27 | }; 28 | 29 | export type ResourcesLeftPanel = ModuleConfig & { 30 | options: ResourcesLeftPanelOptions; 31 | content: ResourcesLeftPanelContent; 32 | }; 33 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-aleph-extension/DownloadDialogue.ts: -------------------------------------------------------------------------------- 1 | import { DownloadDialogue as BaseDownloadDialogue } from "../../modules/uv-dialogues-module/DownloadDialogue"; 2 | import { DownloadOption } from "../../modules/uv-shared-module/DownloadOption"; 3 | 4 | export class DownloadDialogue extends BaseDownloadDialogue { 5 | constructor($element: JQuery) { 6 | super($element); 7 | } 8 | 9 | create(): void { 10 | this.setConfig("downloadDialogue"); 11 | 12 | super.create(); 13 | } 14 | 15 | open($triggerButton: HTMLElement) { 16 | super.open($triggerButton); 17 | 18 | this.addEntireFileDownloadOptions(); 19 | this.updateNoneAvailable(); 20 | 21 | this.resize(); 22 | } 23 | 24 | isDownloadOptionAvailable(option: DownloadOption): boolean { 25 | return super.isDownloadOptionAvailable(option); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-aleph-extension/Events.ts: -------------------------------------------------------------------------------- 1 | export class AlephExtensionEvents { 2 | static namespace: string = "alephExtension."; 3 | 4 | static BOUNDING_BOX_ENABLED_CHANGE: string = 5 | AlephExtensionEvents.namespace + "boundingBoxEnabledChange"; 6 | static CLEAR_GRAPH: string = AlephExtensionEvents.namespace + "clearGraph"; 7 | static CONTROLS_TYPE_CHANGE: string = 8 | AlephExtensionEvents.namespace + "controlsTypeChange"; 9 | static DELETE_ANGLE: string = AlephExtensionEvents.namespace + "deleteAngle"; 10 | static DELETE_EDGE: string = AlephExtensionEvents.namespace + "deleteEdge"; 11 | static DELETE_NODE: string = AlephExtensionEvents.namespace + "deleteNode"; 12 | static DISPLAY_MODE_CHANGE: string = 13 | AlephExtensionEvents.namespace + "displayModeChange"; 14 | static GRAPH_ENABLED_CHANGE: string = 15 | AlephExtensionEvents.namespace + "graphEnabledChangedChange"; 16 | static LOADED: string = AlephExtensionEvents.namespace + "loaded"; 17 | static ORIENTATION_CHANGE: string = 18 | AlephExtensionEvents.namespace + "orientationChange"; 19 | static RECENTER: string = AlephExtensionEvents.namespace + "recenter"; 20 | static SELECT_NODE: string = AlephExtensionEvents.namespace + "selectNode"; 21 | static SET_GRAPH: string = AlephExtensionEvents.namespace + "setGraph"; 22 | static SET_NODE: string = AlephExtensionEvents.namespace + "setNode"; 23 | static SLICES_INDEX_CHANGE: string = 24 | AlephExtensionEvents.namespace + "slicesIndexChange"; 25 | static SLICES_BRIGHTNESS_CHANGE: string = 26 | AlephExtensionEvents.namespace + "slicesBrightnessChange"; 27 | static SLICES_CONTRAST_CHANGE: string = 28 | AlephExtensionEvents.namespace + "slicesWindowWidthChange"; 29 | static UNITS_CHANGE: string = AlephExtensionEvents.namespace + "unitsChange"; 30 | static VIEWER_CHANGE: string = 31 | AlephExtensionEvents.namespace + "viewerChange"; 32 | static VOLUME_STEPS_CHANGE: string = 33 | AlephExtensionEvents.namespace + "volumeStepsChange"; 34 | static VOLUME_BRIGHTNESS_CHANGE: string = 35 | AlephExtensionEvents.namespace + "volumeBrightnessChange"; 36 | static VOLUME_CONTRAST_CHANGE: string = 37 | AlephExtensionEvents.namespace + "volumeContrastChange"; 38 | } 39 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-aleph-extension/IAlephExtension.ts: -------------------------------------------------------------------------------- 1 | import { IExtension } from "../../modules/uv-shared-module/IExtension"; 2 | 3 | export interface IAlephExtension extends IExtension { 4 | getEmbedScript(embedTemplate: string, width: number, height: number): string; 5 | } 6 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-aleph-extension/IAlephExtensionData.ts: -------------------------------------------------------------------------------- 1 | import { IUVData } from "../../../../IUVData"; 2 | import { Config } from "./config/Config"; 3 | 4 | export interface IAlephExtensionData extends IUVData {} 5 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-aleph-extension/ISettings.d.ts: -------------------------------------------------------------------------------- 1 | interface ISettings {} 2 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-aleph-extension/SettingsDialogue.ts: -------------------------------------------------------------------------------- 1 | import { SettingsDialogue as BaseSettingsDialogue } from "../../modules/uv-dialogues-module/SettingsDialogue"; 2 | 3 | export class SettingsDialogue extends BaseSettingsDialogue { 4 | constructor($element: JQuery) { 5 | super($element); 6 | } 7 | 8 | create(): void { 9 | this.setConfig("settingsDialogue"); 10 | 11 | super.create(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-aleph-extension/ShareDialogue.ts: -------------------------------------------------------------------------------- 1 | import { ShareDialogue as BaseShareDialogue } from "../../modules/uv-dialogues-module/ShareDialogue"; 2 | import { Config } from "../uv-aleph-extension/config/Config"; 3 | import { IAlephExtension } from "./IAlephExtension"; 4 | 5 | export class ShareDialogue extends BaseShareDialogue< 6 | Config["modules"]["shareDialogue"] 7 | > { 8 | constructor($element: JQuery) { 9 | super($element); 10 | } 11 | 12 | create(): void { 13 | this.setConfig("shareDialogue"); 14 | 15 | super.create(); 16 | } 17 | 18 | update(): void { 19 | super.update(); 20 | 21 | this.embedCode = (this.extension).getEmbedScript( 22 | this.options.embedTemplate, 23 | this.currentWidth, 24 | this.currentHeight 25 | ); 26 | 27 | this.$embedCode.val(this.embedCode); 28 | } 29 | 30 | resize(): void { 31 | super.resize(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-aleph-extension/config/Config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | BaseConfig, 3 | CenterPanelContent, 4 | CenterPanelOptions, 5 | DownloadDialogueContent, 6 | DownloadDialogueOptions, 7 | ModuleConfig, 8 | SettingsDialogueContent, 9 | SettingsDialogueOptions, 10 | ShareDialogueContent, 11 | ShareDialogueOptions, 12 | } from "@/content-handlers/iiif/BaseConfig"; 13 | import { 14 | ExpandPanelContent, 15 | ExpandPanelOptions, 16 | } from "../../config/ExpandPanel"; 17 | 18 | type AlephLeftPanelOptions = ExpandPanelOptions & { 19 | /** Determines if the console tab is enabled */ 20 | consoleTabEnabled: boolean; 21 | /** Determines if the graph tab is enabled */ 22 | graphTabEnabled: boolean; 23 | /** Determines if the settings tab is enabled */ 24 | settingsTabEnabled: boolean; 25 | /** Determines if the source tab is enabled */ 26 | srcTabEnabled: boolean; 27 | }; 28 | 29 | type AlephLeftPanelContent = ExpandPanelContent & { 30 | title: string; 31 | }; 32 | 33 | type AlephLeftPanel = { 34 | options: AlephLeftPanelOptions; 35 | content: AlephLeftPanelContent; 36 | }; 37 | 38 | type AlephCenterPanelOptions = CenterPanelOptions & {}; 39 | 40 | type AlephCenterPanelContent = CenterPanelContent & {}; 41 | 42 | type AlephCenterPanel = { 43 | options: AlephCenterPanelOptions; 44 | content: AlephCenterPanelContent; 45 | }; 46 | 47 | type AlephDownloadDialogueOptions = DownloadDialogueOptions & {}; 48 | 49 | type AlephDownloadDialogueContent = DownloadDialogueContent & {}; 50 | 51 | type AlephDownloadDialogue = ModuleConfig & { 52 | options: AlephDownloadDialogueOptions; 53 | content: AlephDownloadDialogueContent; 54 | }; 55 | 56 | type AlephShareDialogueOptions = ShareDialogueOptions & {}; 57 | 58 | type AlephShareDialogueContent = ShareDialogueContent & {}; 59 | 60 | type AlephShareDialogue = ModuleConfig & { 61 | options: AlephShareDialogueOptions; 62 | content: AlephShareDialogueContent; 63 | }; 64 | 65 | type AlephSettingsDialogueOptions = SettingsDialogueOptions & {}; 66 | 67 | type AlephSettingsDialogueContent = SettingsDialogueContent & {}; 68 | 69 | type AlephSettingsDialogue = ModuleConfig & { 70 | options: AlephSettingsDialogueOptions; 71 | content: AlephSettingsDialogueContent; 72 | }; 73 | 74 | type Modules = { 75 | alephLeftPanel: AlephLeftPanel; 76 | alephCenterPanel: AlephCenterPanel; 77 | downloadDialogue: AlephDownloadDialogue; 78 | shareDialogue: AlephShareDialogue; 79 | settingsDialogue: AlephSettingsDialogue; 80 | }; 81 | 82 | export type Config = BaseConfig & { 83 | modules: Modules; 84 | }; 85 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-aleph-extension/theme/theme.less: -------------------------------------------------------------------------------- 1 | @import "../../../modules/uv-dialogues-module/css/styles.less"; 2 | @import "../../../modules/uv-alephcenterpanel-module/css/styles.less"; 3 | @import "../../../modules/uv-alephleftpanel-module/css/styles.less"; 4 | @import "../../../modules/uv-moreinforightpanel-module/css/styles.less"; 5 | @import "../../../modules/uv-shared-module/css/styles.less"; 6 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-av-extension/Events.ts: -------------------------------------------------------------------------------- 1 | export class AVExtensionEvents { 2 | static namespace: string = "avExtension."; 3 | } 4 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-av-extension/IAVExtension.ts: -------------------------------------------------------------------------------- 1 | import { IExtension } from "../../modules/uv-shared-module/IExtension"; 2 | 3 | export interface IAVExtension extends IExtension { 4 | getEmbedScript(embedTemplate: string, width: number, height: number): string; 5 | } 6 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-av-extension/IAVExtensionData.ts: -------------------------------------------------------------------------------- 1 | import { IUVData } from "../../../../IUVData"; 2 | import { Config } from "./config/Config"; 3 | 4 | export interface IAVExtensionData extends IUVData {} 5 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-av-extension/ISettings.d.ts: -------------------------------------------------------------------------------- 1 | interface ISettings {} 2 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-av-extension/SettingsDialogue.ts: -------------------------------------------------------------------------------- 1 | import { SettingsDialogue as BaseSettingsDialogue } from "../../modules/uv-dialogues-module/SettingsDialogue"; 2 | 3 | export class SettingsDialogue extends BaseSettingsDialogue { 4 | constructor($element: JQuery) { 5 | super($element); 6 | } 7 | 8 | create(): void { 9 | this.setConfig("settingsDialogue"); 10 | 11 | super.create(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-av-extension/ShareDialogue.ts: -------------------------------------------------------------------------------- 1 | import { ShareDialogue as BaseShareDialogue } from "../../modules/uv-dialogues-module/ShareDialogue"; 2 | import { Config } from "../uv-av-extension/config/Config"; 3 | import { IAVExtension } from "./IAVExtension"; 4 | 5 | export class ShareDialogue extends BaseShareDialogue< 6 | Config["modules"]["shareDialogue"] 7 | > { 8 | constructor($element: JQuery) { 9 | super($element); 10 | } 11 | 12 | create(): void { 13 | this.setConfig("shareDialogue"); 14 | 15 | super.create(); 16 | } 17 | 18 | update(): void { 19 | super.update(); 20 | 21 | this.embedCode = (this.extension).getEmbedScript( 22 | this.options.embedTemplate, 23 | this.currentWidth, 24 | this.currentHeight 25 | ); 26 | 27 | this.$embedCode.val(this.embedCode); 28 | } 29 | 30 | resize(): void { 31 | super.resize(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-av-extension/theme/theme.less: -------------------------------------------------------------------------------- 1 | @import "../../../modules/uv-dialogues-module/css/styles.less"; 2 | @import "../../../modules/uv-avcenterpanel-module/css/styles.less"; 3 | @import "../../../modules/uv-contentleftpanel-module/css/styles.less"; 4 | @import "../../../modules/uv-moreinforightpanel-module/css/styles.less"; 5 | @import "../../../modules/uv-shared-module/css/styles.less"; 6 | @import "../../../modules/uv-avmobilefooterpanel-module/css/styles.less"; 7 | 8 | .iiif-av-component .canvas-timeline-container .ui-slider-range-min { 9 | background-color: rgba(66, 66, 66, 0.5) !important; 10 | } 11 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-default-extension/Events.ts: -------------------------------------------------------------------------------- 1 | export class DefaultExtensionEvents { 2 | static namespace: string = "defaultExtension."; 3 | } 4 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-default-extension/IDefaultExtension.ts: -------------------------------------------------------------------------------- 1 | import { IExtension } from "../../modules/uv-shared-module/IExtension"; 2 | 3 | export interface IDefaultExtension extends IExtension { 4 | getEmbedScript(embedTemplate: string, width: number, height: number): string; 5 | } 6 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-default-extension/SettingsDialogue.ts: -------------------------------------------------------------------------------- 1 | import { SettingsDialogue as BaseSettingsDialogue } from "../../modules/uv-dialogues-module/SettingsDialogue"; 2 | 3 | export class SettingsDialogue extends BaseSettingsDialogue { 4 | constructor($element: JQuery) { 5 | super($element); 6 | } 7 | 8 | create(): void { 9 | this.setConfig("settingsDialogue"); 10 | 11 | super.create(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-default-extension/ShareDialogue.ts: -------------------------------------------------------------------------------- 1 | import { ShareDialogue as BaseShareDialogue } from "../../modules/uv-dialogues-module/ShareDialogue"; 2 | import { Config } from "../uv-default-extension/config/Config"; 3 | import { IDefaultExtension } from "./IDefaultExtension"; 4 | 5 | export class ShareDialogue extends BaseShareDialogue< 6 | Config["modules"]["shareDialogue"] 7 | > { 8 | constructor($element: JQuery) { 9 | super($element); 10 | } 11 | 12 | create(): void { 13 | this.setConfig("shareDialogue"); 14 | 15 | super.create(); 16 | } 17 | 18 | update(): void { 19 | super.update(); 20 | 21 | this.embedCode = (this.extension).getEmbedScript( 22 | this.options.embedTemplate, 23 | this.currentWidth, 24 | this.currentHeight 25 | ); 26 | 27 | this.$embedCode.val(this.embedCode); 28 | } 29 | 30 | resize(): void { 31 | super.resize(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-default-extension/config/Config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | BaseConfig, 3 | CenterPanelContent, 4 | CenterPanelOptions, 5 | DownloadDialogueContent, 6 | DownloadDialogueOptions, 7 | ModuleConfig, 8 | SettingsDialogueContent, 9 | SettingsDialogueOptions, 10 | ShareDialogueContent, 11 | ShareDialogueOptions, 12 | } from "@/content-handlers/iiif/BaseConfig"; 13 | 14 | type FileLinkCenterPanelOptions = CenterPanelOptions & {}; 15 | 16 | type FileLinkCenterPanelContent = CenterPanelContent & {}; 17 | 18 | type FileLinkCenterPanel = { 19 | options: FileLinkCenterPanelOptions; 20 | content: FileLinkCenterPanelContent; 21 | }; 22 | 23 | type DefaultDownloadDialogueOptions = DownloadDialogueOptions & {}; 24 | 25 | type DefaultDownloadDialogueContent = DownloadDialogueContent & {}; 26 | 27 | type DefaultDownloadDialogue = ModuleConfig & { 28 | options: DefaultDownloadDialogueOptions; 29 | content: DefaultDownloadDialogueContent; 30 | }; 31 | 32 | type DefaultShareDialogueOptions = ShareDialogueOptions & {}; 33 | 34 | type DefaultShareDialogueContent = ShareDialogueContent & {}; 35 | 36 | type DefaultShareDialogue = ModuleConfig & { 37 | options: DefaultShareDialogueOptions; 38 | content: DefaultShareDialogueContent; 39 | }; 40 | 41 | type DefaultSettingsDialogueOptions = SettingsDialogueOptions & {}; 42 | 43 | type DefaultSettingsDialogueContent = SettingsDialogueContent & {}; 44 | 45 | type DefaultSettingsDialogue = ModuleConfig & { 46 | options: DefaultSettingsDialogueOptions; 47 | content: DefaultSettingsDialogueContent; 48 | }; 49 | 50 | type Modules = { 51 | fileLinkCenterPanel: FileLinkCenterPanel; 52 | downloadDialogue: DefaultDownloadDialogue; 53 | shareDialogue: DefaultShareDialogue; 54 | settingsDialogue: DefaultSettingsDialogue; 55 | }; 56 | 57 | export type Config = BaseConfig & { 58 | modules: Modules; 59 | }; 60 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-default-extension/theme/theme.less: -------------------------------------------------------------------------------- 1 | @import "../../../modules/uv-dialogues-module/css/styles.less"; 2 | @import "../../../modules/uv-resourcesleftpanel-module/css/styles.less"; 3 | @import "../../../modules/uv-moreinforightpanel-module/css/styles.less"; 4 | @import "../../../modules/uv-filelinkcenterpanel-module/css/styles.less"; 5 | @import "../../../modules/uv-shared-module/css/styles.less"; 6 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-ebook-extension/DownloadDialogue.ts: -------------------------------------------------------------------------------- 1 | import { DownloadDialogue as BaseDownloadDialogue } from "../../modules/uv-dialogues-module/DownloadDialogue"; 2 | import { DownloadOption } from "../../modules/uv-shared-module/DownloadOption"; 3 | 4 | export class DownloadDialogue extends BaseDownloadDialogue { 5 | constructor($element: JQuery) { 6 | super($element); 7 | } 8 | 9 | create(): void { 10 | this.setConfig("downloadDialogue"); 11 | 12 | super.create(); 13 | } 14 | 15 | open($triggerButton: HTMLElement) { 16 | super.open($triggerButton); 17 | 18 | this.addEntireFileDownloadOptions(); 19 | this.updateNoneAvailable(); 20 | 21 | this.resize(); 22 | } 23 | 24 | isDownloadOptionAvailable(option: DownloadOption): boolean { 25 | return super.isDownloadOptionAvailable(option); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-ebook-extension/Events.ts: -------------------------------------------------------------------------------- 1 | export class EbookExtensionEvents { 2 | static namespace: string = "ebookExtension."; 3 | 4 | static CFI_FRAGMENT_CHANGE: string = 5 | EbookExtensionEvents.namespace + "cfiFragmentChange"; 6 | static ITEM_CLICKED: string = EbookExtensionEvents.namespace + "itemClicked"; 7 | static LOADED_NAVIGATION: string = 8 | EbookExtensionEvents.namespace + "loadedNavigation"; 9 | static RELOCATED: string = EbookExtensionEvents.namespace + "relocated"; 10 | static RENDITION_ATTACHED: string = 11 | EbookExtensionEvents.namespace + "renditionAttached"; 12 | static TOC_READY: string = EbookExtensionEvents.namespace + "tocReady"; 13 | } 14 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-ebook-extension/IEbookExtension.ts: -------------------------------------------------------------------------------- 1 | import { IExtension } from "../../modules/uv-shared-module/IExtension"; 2 | 3 | export interface IEbookExtension extends IExtension { 4 | getEmbedScript(embedTemplate: string, width: number, height: number): string; 5 | } 6 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-ebook-extension/IEbookExtensionData.ts: -------------------------------------------------------------------------------- 1 | import { IUVData } from "../../../../IUVData"; 2 | import { Config } from "./config/Config"; 3 | 4 | export interface IEbookExtensionData extends IUVData { 5 | cfi: string; 6 | } 7 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-ebook-extension/ISettings.d.ts: -------------------------------------------------------------------------------- 1 | interface ISettings {} 2 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-ebook-extension/SettingsDialogue.ts: -------------------------------------------------------------------------------- 1 | import { SettingsDialogue as BaseSettingsDialogue } from "../../modules/uv-dialogues-module/SettingsDialogue"; 2 | 3 | export class SettingsDialogue extends BaseSettingsDialogue { 4 | constructor($element: JQuery) { 5 | super($element); 6 | } 7 | 8 | create(): void { 9 | this.setConfig("settingsDialogue"); 10 | 11 | super.create(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-ebook-extension/ShareDialogue.ts: -------------------------------------------------------------------------------- 1 | import { ShareDialogue as BaseShareDialogue } from "../../modules/uv-dialogues-module/ShareDialogue"; 2 | import { Config } from "../uv-ebook-extension/config/Config"; 3 | import { IEbookExtension } from "./IEbookExtension"; 4 | 5 | export class ShareDialogue extends BaseShareDialogue< 6 | Config["modules"]["shareDialogue"] 7 | > { 8 | constructor($element: JQuery) { 9 | super($element); 10 | } 11 | 12 | create(): void { 13 | this.setConfig("shareDialogue"); 14 | 15 | super.create(); 16 | } 17 | 18 | update(): void { 19 | super.update(); 20 | 21 | this.embedCode = (this.extension).getEmbedScript( 22 | this.options.embedTemplate, 23 | this.currentWidth, 24 | this.currentHeight 25 | ); 26 | 27 | this.$embedCode.val(this.embedCode); 28 | } 29 | 30 | resize(): void { 31 | super.resize(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-ebook-extension/config/Config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | BaseConfig, 3 | CenterPanelContent, 4 | CenterPanelOptions, 5 | DownloadDialogueContent, 6 | DownloadDialogueOptions, 7 | ModuleConfig, 8 | SettingsDialogueContent, 9 | SettingsDialogueOptions, 10 | ShareDialogueContent, 11 | ShareDialogueOptions, 12 | } from "@/content-handlers/iiif/BaseConfig"; 13 | import { 14 | ExpandPanelContent, 15 | ExpandPanelOptions, 16 | } from "../../config/ExpandPanel"; 17 | 18 | type EbookLeftPanelOptions = ExpandPanelOptions & {}; 19 | 20 | type EbookLeftPanelContent = ExpandPanelContent & { 21 | title: string; 22 | }; 23 | 24 | type EbookLeftPanel = { 25 | options: EbookLeftPanelOptions; 26 | content: EbookLeftPanelContent; 27 | }; 28 | 29 | type EbookCenterPanelOptions = CenterPanelOptions & {}; 30 | 31 | type EbookCenterPanelContent = CenterPanelContent & {}; 32 | 33 | type EbookCenterPanel = { 34 | options: EbookCenterPanelOptions; 35 | content: EbookCenterPanelContent; 36 | }; 37 | 38 | type EbookDownloadDialogueOptions = DownloadDialogueOptions & {}; 39 | 40 | type EbookDownloadDialogueContent = DownloadDialogueContent & {}; 41 | 42 | type EbookDownloadDialogue = ModuleConfig & { 43 | options: EbookDownloadDialogueOptions; 44 | content: EbookDownloadDialogueContent; 45 | }; 46 | 47 | type EbookShareDialogueOptions = ShareDialogueOptions & {}; 48 | 49 | type EbookShareDialogueContent = ShareDialogueContent & {}; 50 | 51 | type EbookShareDialogue = ModuleConfig & { 52 | options: EbookShareDialogueOptions; 53 | content: EbookShareDialogueContent; 54 | }; 55 | 56 | type EbookSettingsDialogueOptions = SettingsDialogueOptions & {}; 57 | 58 | type EbookSettingsDialogueContent = SettingsDialogueContent & {}; 59 | 60 | type EbookSettingsDialogue = ModuleConfig & { 61 | options: EbookSettingsDialogueOptions; 62 | content: EbookSettingsDialogueContent; 63 | }; 64 | 65 | type Modules = { 66 | ebookLeftPanel: EbookLeftPanel; 67 | ebookCenterPanel: EbookCenterPanel; 68 | downloadDialogue: EbookDownloadDialogue; 69 | shareDialogue: EbookShareDialogue; 70 | settingsDialogue: EbookSettingsDialogue; 71 | }; 72 | 73 | export type Config = BaseConfig & { 74 | modules: Modules; 75 | }; 76 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-ebook-extension/dependencies.ts: -------------------------------------------------------------------------------- 1 | define(function () { 2 | return function (formats: string[]) { 3 | return { 4 | async: ["MetadataComponent", "uv-ebook-extension.proxy"], 5 | }; 6 | }; 7 | }); 8 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-ebook-extension/lib/uv-ebook-components.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --toc-margin: 0; 3 | --toc-padding: 0; 4 | --toc-list-style-type: none; 5 | --toc-link-color: #4e4e4e; 6 | --toc-link-selected-color: #949494; 7 | --toc-link-padding: 0.25rem; 8 | --reader-arrow-color: #e2e2e2; 9 | --reader-arrow-hover-color: #777; 10 | --reader-spinner-color: #bdbdbd; 11 | } 12 | .disabled { 13 | pointer-events: none; 14 | opacity: 0.4; 15 | } 16 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-ebook-extension/theme/theme.less: -------------------------------------------------------------------------------- 1 | @import "../../../modules/uv-dialogues-module/css/styles.less"; 2 | @import "../../../modules/uv-ebookcenterpanel-module/css/styles.less"; 3 | @import "../../../modules/uv-ebookleftpanel-module/css/styles.less"; 4 | @import "../../../modules/uv-moreinforightpanel-module/css/styles.less"; 5 | @import "../../../modules/uv-shared-module/css/styles.less"; 6 | @import "../../../modules/uv-ebookmobilefooterpanel-module/css/styles.less"; 7 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-mediaelement-extension/DownloadDialogue.ts: -------------------------------------------------------------------------------- 1 | import { DownloadDialogue as BaseDownloadDialogue } from "../../modules/uv-dialogues-module/DownloadDialogue"; 2 | import { DownloadOption } from "../../modules/uv-shared-module/DownloadOption"; 3 | import { Canvas } from "manifesto.js"; 4 | 5 | export class DownloadDialogue extends BaseDownloadDialogue { 6 | constructor($element: JQuery) { 7 | super($element); 8 | } 9 | 10 | create(): void { 11 | this.setConfig("downloadDialogue"); 12 | 13 | super.create(); 14 | } 15 | 16 | open(triggerButton: HTMLElement) { 17 | super.open(triggerButton); 18 | 19 | this.addEntireFileDownloadOptions(); 20 | this.updateNoneAvailable(); 21 | 22 | // Download option for text representation 23 | const canvas: Canvas = this.extension.helper.getCurrentCanvas(); 24 | const content = canvas.getContent(); 25 | for (const annotation of content) { 26 | const body = annotation.getBody(); 27 | for (const item of body) { 28 | const format = item.getFormat(); 29 | if ( 30 | format && 31 | (format.toString() === "text/plain" || 32 | format.toString() === "text/vtt") 33 | ) { 34 | this.addEntireFileDownloadOption( 35 | item.id, 36 | item.getDefaultLabel() || 37 | `Download as text ${ 38 | item.__jsonld.language ? `(${item.__jsonld.language})` : "" 39 | }`, 40 | format.toString() 41 | ); 42 | } 43 | } 44 | } 45 | 46 | this.resize(); 47 | } 48 | 49 | isDownloadOptionAvailable(option: DownloadOption): boolean { 50 | return super.isDownloadOptionAvailable(option); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-mediaelement-extension/Events.ts: -------------------------------------------------------------------------------- 1 | export class MediaElementExtensionEvents { 2 | static namespace: string = "mediaelementExtension."; 3 | 4 | static MEDIA_ENDED: string = 5 | MediaElementExtensionEvents.namespace + "mediaEnded"; 6 | static MEDIA_MUTED: string = 7 | MediaElementExtensionEvents.namespace + "mediaMuted"; 8 | static MEDIA_PAUSED: string = 9 | MediaElementExtensionEvents.namespace + "mediaPaused"; 10 | static MEDIA_PLAYED: string = 11 | MediaElementExtensionEvents.namespace + "mediaPlayed"; 12 | static MEDIA_TIME_UPDATE: string = 13 | MediaElementExtensionEvents.namespace + "mediaTimeUpdate"; 14 | static MEDIA_UNMUTED: string = 15 | MediaElementExtensionEvents.namespace + "mediaUnmuted"; 16 | } 17 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-mediaelement-extension/IMediaElementExtension.ts: -------------------------------------------------------------------------------- 1 | import { IExtension } from "../../modules/uv-shared-module/IExtension"; 2 | 3 | export interface IMediaElementExtension extends IExtension { 4 | getEmbedScript(embedTemplate: string, width: number, height: number): string; 5 | getPosterImageUri(): string | null; 6 | isVideo(): boolean; 7 | } 8 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-mediaelement-extension/SettingsDialogue.ts: -------------------------------------------------------------------------------- 1 | import { SettingsDialogue as BaseSettingsDialogue } from "../../modules/uv-dialogues-module/SettingsDialogue"; 2 | 3 | export class SettingsDialogue extends BaseSettingsDialogue { 4 | constructor($element: JQuery) { 5 | super($element); 6 | } 7 | 8 | create(): void { 9 | this.setConfig("settingsDialogue"); 10 | 11 | super.create(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-mediaelement-extension/ShareDialogue.ts: -------------------------------------------------------------------------------- 1 | import { ShareDialogue as BaseShareDialogue } from "../../modules/uv-dialogues-module/ShareDialogue"; 2 | import { Config } from "../uv-mediaelement-extension/config/Config"; 3 | import { IMediaElementExtension } from "./IMediaElementExtension"; 4 | 5 | export class ShareDialogue extends BaseShareDialogue< 6 | Config["modules"]["shareDialogue"] 7 | > { 8 | constructor($element: JQuery) { 9 | super($element); 10 | } 11 | 12 | create(): void { 13 | this.setConfig("shareDialogue"); 14 | 15 | super.create(); 16 | } 17 | 18 | update(): void { 19 | super.update(); 20 | 21 | this.embedCode = (this.extension).getEmbedScript( 22 | this.options.embedTemplate, 23 | this.currentWidth, 24 | this.currentHeight 25 | ); 26 | 27 | this.$embedCode.val(this.embedCode); 28 | } 29 | 30 | resize(): void { 31 | super.resize(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-mediaelement-extension/config/Config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | BaseConfig, 3 | CenterPanelContent, 4 | CenterPanelOptions, 5 | DownloadDialogueContent, 6 | DownloadDialogueOptions, 7 | ModuleConfig, 8 | SettingsDialogueContent, 9 | SettingsDialogueOptions, 10 | ShareDialogueContent, 11 | ShareDialogueOptions, 12 | } from "@/content-handlers/iiif/BaseConfig"; 13 | 14 | type MediaElementCenterPanelOptions = CenterPanelOptions & { 15 | autoPlayOnSetTarget: boolean; 16 | defaultHeight: number; 17 | defaultWidth: number; 18 | }; 19 | 20 | type MediaElementCenterPanelContent = CenterPanelContent & {}; 21 | 22 | type MediaElementCenterPanel = { 23 | options: MediaElementCenterPanelOptions; 24 | content: MediaElementCenterPanelContent; 25 | }; 26 | 27 | type MediaElementDownloadDialogueOptions = DownloadDialogueOptions & {}; 28 | 29 | type MediaElementDownloadDialogueContent = DownloadDialogueContent & {}; 30 | 31 | type MediaElementDownloadDialogue = ModuleConfig & { 32 | options: MediaElementDownloadDialogueOptions; 33 | content: MediaElementDownloadDialogueContent; 34 | }; 35 | 36 | type MediaElementShareDialogueOptions = ShareDialogueOptions & {}; 37 | 38 | type MediaElementShareDialogueContent = ShareDialogueContent & {}; 39 | 40 | type MediaElementShareDialogue = ModuleConfig & { 41 | options: MediaElementShareDialogueOptions; 42 | content: MediaElementShareDialogueContent; 43 | }; 44 | 45 | type MediaElementSettingsDialogueOptions = SettingsDialogueOptions & {}; 46 | 47 | type MediaElementSettingsDialogueContent = SettingsDialogueContent & {}; 48 | 49 | type MediaElementSettingsDialogue = ModuleConfig & { 50 | options: MediaElementSettingsDialogueOptions; 51 | content: MediaElementSettingsDialogueContent; 52 | }; 53 | 54 | type Modules = { 55 | mediaElementCenterPanel: MediaElementCenterPanel; 56 | downloadDialogue: MediaElementDownloadDialogue; 57 | shareDialogue: MediaElementShareDialogue; 58 | settingsDialogue: MediaElementSettingsDialogue; 59 | }; 60 | 61 | export type Config = BaseConfig & { 62 | modules: Modules; 63 | }; 64 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-mediaelement-extension/theme/theme.less: -------------------------------------------------------------------------------- 1 | @import "../../../modules/uv-dialogues-module/css/styles.less"; 2 | @import "../../../modules/uv-resourcesleftpanel-module/css/styles.less"; 3 | @import "../../../modules/uv-moreinforightpanel-module/css/styles.less"; 4 | @import "../../../modules/uv-mediaelementcenterpanel-module/css/styles.less"; 5 | @import "../../../modules/uv-shared-module/css/styles.less"; 6 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-model-viewer-extension/DownloadDialogue.ts: -------------------------------------------------------------------------------- 1 | import { DownloadDialogue as BaseDownloadDialogue } from "../../modules/uv-dialogues-module/DownloadDialogue"; 2 | import { DownloadOption } from "../../modules/uv-shared-module/DownloadOption"; 3 | 4 | export class DownloadDialogue extends BaseDownloadDialogue { 5 | constructor($element: JQuery) { 6 | super($element); 7 | } 8 | 9 | create(): void { 10 | this.setConfig("downloadDialogue"); 11 | 12 | super.create(); 13 | } 14 | 15 | open(triggerButton: HTMLElement) { 16 | super.open(triggerButton); 17 | 18 | this.addEntireFileDownloadOptions(); 19 | this.updateNoneAvailable(); 20 | 21 | this.resize(); 22 | } 23 | 24 | isDownloadOptionAvailable(option: DownloadOption): boolean { 25 | return super.isDownloadOptionAvailable(option); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-model-viewer-extension/Events.ts: -------------------------------------------------------------------------------- 1 | export class ModelViewerExtensionEvents { 2 | static namespace: string = "modelviewerExtension."; 3 | static CAMERA_CHANGE: string = 4 | ModelViewerExtensionEvents.namespace + "cameraChange"; 5 | static DOUBLECLICK: string = 6 | ModelViewerExtensionEvents.namespace + "doubleClick"; 7 | } 8 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-model-viewer-extension/Orbit.ts: -------------------------------------------------------------------------------- 1 | // theta, phi, radius 2 | export class Orbit { 3 | public t: string; 4 | public p: string; 5 | public r: string; 6 | 7 | constructor(t: string, p: string, r: string) { 8 | this.t = t; 9 | this.p = p; 10 | this.r = r; 11 | } 12 | 13 | toString(): string { 14 | return `${this.t},${this.p},${this.r}`; 15 | } 16 | 17 | toAttributeString(): string { 18 | return `${this.t}rad ${this.p}rad ${this.r}m`; 19 | } 20 | 21 | static fromString(orbit: string): Orbit { 22 | orbit = orbit.replace("orbit=", ""); 23 | const orbitArr: string[] = orbit.split(","); 24 | return new Orbit(orbitArr[0], orbitArr[1], orbitArr[2]); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-model-viewer-extension/SettingsDialogue.ts: -------------------------------------------------------------------------------- 1 | import { SettingsDialogue as BaseSettingsDialogue } from "../../modules/uv-dialogues-module/SettingsDialogue"; 2 | 3 | export class SettingsDialogue extends BaseSettingsDialogue { 4 | constructor($element: JQuery) { 5 | super($element); 6 | } 7 | 8 | create(): void { 9 | this.setConfig("settingsDialogue"); 10 | 11 | super.create(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-model-viewer-extension/ShareDialogue.ts: -------------------------------------------------------------------------------- 1 | import { ShareDialogue as BaseShareDialogue } from "../../modules/uv-dialogues-module/ShareDialogue"; 2 | import { Config } from "../uv-model-viewer-extension/config/Config"; 3 | import ModelViewerExtension from "./Extension"; 4 | 5 | export class ShareDialogue extends BaseShareDialogue< 6 | Config["modules"]["shareDialogue"] 7 | > { 8 | constructor($element: JQuery) { 9 | super($element); 10 | } 11 | 12 | create(): void { 13 | this.setConfig("shareDialogue"); 14 | 15 | super.create(); 16 | } 17 | 18 | update(): void { 19 | super.update(); 20 | 21 | this.embedCode = (this.extension).getEmbedScript( 22 | this.options.embedTemplate, 23 | this.currentWidth, 24 | this.currentHeight 25 | ); 26 | 27 | this.$embedCode.val(this.embedCode); 28 | } 29 | 30 | resize(): void { 31 | super.resize(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-model-viewer-extension/config/Config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | BaseConfig, 3 | CenterPanelContent, 4 | CenterPanelOptions, 5 | DownloadDialogueContent, 6 | DownloadDialogueOptions, 7 | ModuleConfig, 8 | SettingsDialogueContent, 9 | SettingsDialogueOptions, 10 | ShareDialogueContent, 11 | ShareDialogueOptions, 12 | } from "@/content-handlers/iiif/BaseConfig"; 13 | 14 | type ModelViewerCenterPanelOptions = CenterPanelOptions & { 15 | /** Determines if auto rotation is enabled */ 16 | autoRotateEnabled: boolean; 17 | /** Delay in camera change */ 18 | cameraChangeDelay: number; 19 | /** Determines if double click annotation is enabled */ 20 | doubleClickAnnotationEnabled: boolean; 21 | /** Determines if interaction prompt is enabled */ 22 | interactionPromptEnabled: boolean; 23 | }; 24 | 25 | type ModelViewerCenterPanelContent = CenterPanelContent & {}; 26 | 27 | type ModelViewerCenterPanel = { 28 | options: ModelViewerCenterPanelOptions; 29 | content: ModelViewerCenterPanelContent; 30 | }; 31 | 32 | type ModelViewerDownloadDialogueOptions = DownloadDialogueOptions & {}; 33 | 34 | type ModelViewerDownloadDialogueContent = DownloadDialogueContent & {}; 35 | 36 | type ModelViewerDownloadDialogue = ModuleConfig & { 37 | options: ModelViewerDownloadDialogueOptions; 38 | content: ModelViewerDownloadDialogueContent; 39 | }; 40 | 41 | type ModelViewerShareDialogueOptions = ShareDialogueOptions & {}; 42 | 43 | type ModelViewerShareDialogueContent = ShareDialogueContent & {}; 44 | 45 | type ModelViewerShareDialogue = ModuleConfig & { 46 | options: ModelViewerShareDialogueOptions; 47 | content: ModelViewerShareDialogueContent; 48 | }; 49 | 50 | type ModelViewerSettingsDialogueOptions = SettingsDialogueOptions & {}; 51 | 52 | type ModelViewerSettingsDialogueContent = SettingsDialogueContent & {}; 53 | 54 | type ModelViewerSettingsDialogue = ModuleConfig & { 55 | options: ModelViewerSettingsDialogueOptions; 56 | content: ModelViewerSettingsDialogueContent; 57 | }; 58 | 59 | type Modules = { 60 | modelViewerCenterPanel: ModelViewerCenterPanel; 61 | downloadDialogue: ModelViewerDownloadDialogue; 62 | shareDialogue: ModelViewerShareDialogue; 63 | settingsDialogue: ModelViewerSettingsDialogue; 64 | }; 65 | 66 | export type Config = BaseConfig & { 67 | modules: Modules; 68 | }; 69 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-model-viewer-extension/theme/theme.less: -------------------------------------------------------------------------------- 1 | @import "../../../modules/uv-dialogues-module/css/styles.less"; 2 | @import "../../../modules/uv-contentleftpanel-module/css/styles.less"; 3 | @import "../../../modules/uv-moreinforightpanel-module/css/styles.less"; 4 | @import "../../../modules/uv-modelviewercenterpanel-module/css/styles.less"; 5 | @import "../../../modules/uv-shared-module/css/styles.less"; 6 | @import "../../../modules/uv-modelviewermobilefooterpanel-module/css/styles.less"; 7 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-openseadragon-extension/AdjustImageDialogue.ts: -------------------------------------------------------------------------------- 1 | import { AdjustImageDialogue as BaseAdjustImageDialogue } from "../../modules/uv-dialogues-module/AdjustImageDialogue"; 2 | import { Shell } from "../../modules/uv-shared-module/Shell"; 3 | 4 | export class AdjustImageDialogue extends BaseAdjustImageDialogue { 5 | constructor($element: JQuery, shell: Shell) { 6 | super($element, shell); 7 | } 8 | 9 | create(): void { 10 | this.setConfig("shareDialogue"); 11 | super.create(); 12 | } 13 | 14 | resize(): void { 15 | super.resize(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-openseadragon-extension/CroppedImageDimensions.ts: -------------------------------------------------------------------------------- 1 | import { Size } from "@edsilv/utils"; 2 | import { Point } from "../../modules/uv-shared-module/Point"; 3 | 4 | export class CroppedImageDimensions { 5 | region: Size = new Size(0, 0); 6 | regionPos: Point = new Point(0, 0); 7 | size: Size = new Size(0, 0); 8 | } 9 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-openseadragon-extension/Events.ts: -------------------------------------------------------------------------------- 1 | export class OpenSeadragonExtensionEvents { 2 | static namespace: string = "openseadragonExtension."; 3 | 4 | static CURRENT_VIEW_URI: string = 5 | OpenSeadragonExtensionEvents.namespace + "currentViewUri"; 6 | static DOUBLECLICK: string = 7 | OpenSeadragonExtensionEvents.namespace + "doubleClick"; 8 | static IMAGE_SEARCH: string = 9 | OpenSeadragonExtensionEvents.namespace + "imageSearch"; 10 | static MODE_CHANGE: string = 11 | OpenSeadragonExtensionEvents.namespace + "modeChange"; 12 | static NEXT_SEARCH_RESULT: string = 13 | OpenSeadragonExtensionEvents.namespace + "nextSearchResult"; 14 | static NEXT_IMAGES_SEARCH_RESULT_UNAVAILABLE: string = 15 | OpenSeadragonExtensionEvents.namespace + 16 | "nextImagesSearchResultUnavailable"; 17 | static PREV_IMAGES_SEARCH_RESULT_UNAVAILABLE: string = 18 | OpenSeadragonExtensionEvents.namespace + 19 | "prevImagesSearchResultUnavailable"; 20 | static PAGE_SEARCH: string = 21 | OpenSeadragonExtensionEvents.namespace + "pageSearch"; 22 | static PAGING_TOGGLED: string = 23 | OpenSeadragonExtensionEvents.namespace + "pagingToggled"; 24 | static PREV_SEARCH_RESULT: string = 25 | OpenSeadragonExtensionEvents.namespace + "prevSearchResult"; 26 | static PRINT: string = OpenSeadragonExtensionEvents.namespace + "print"; 27 | static ROTATE: string = OpenSeadragonExtensionEvents.namespace + "rotate"; 28 | static OPENSEADRAGON_ANIMATION_FINISH: string = 29 | OpenSeadragonExtensionEvents.namespace + "animationFinish"; 30 | static OPENSEADRAGON_ANIMATION_START: string = 31 | OpenSeadragonExtensionEvents.namespace + "animationStart"; 32 | static OPENSEADRAGON_ANIMATION: string = 33 | OpenSeadragonExtensionEvents.namespace + "animation"; 34 | static OPENSEADRAGON_OPEN: string = 35 | OpenSeadragonExtensionEvents.namespace + "open"; 36 | static OPENSEADRAGON_RESIZE: string = 37 | OpenSeadragonExtensionEvents.namespace + "resize"; 38 | static OPENSEADRAGON_ROTATION: string = 39 | OpenSeadragonExtensionEvents.namespace + "rotationChange"; 40 | static SEARCH_PREVIEW_FINISH: string = 41 | OpenSeadragonExtensionEvents.namespace + "searchPreviewFinish"; 42 | static SEARCH_PREVIEW_START: string = 43 | OpenSeadragonExtensionEvents.namespace + "searchPreviewStart"; 44 | static SEARCH: string = OpenSeadragonExtensionEvents.namespace + "search"; 45 | static XYWH_CHANGE: string = 46 | OpenSeadragonExtensionEvents.namespace + "xywhChange"; 47 | static ZOOM_IN: string = OpenSeadragonExtensionEvents.namespace + "zoomIn"; 48 | static ZOOM_OUT: string = OpenSeadragonExtensionEvents.namespace + "zoomOut"; 49 | } 50 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-openseadragon-extension/IOpenSeadragonExtensionData.ts: -------------------------------------------------------------------------------- 1 | import { IIIFData } from "../../IIIFData"; 2 | 3 | export interface IOpenSeadragonExtensionData extends IIIFData { 4 | highlight: string | undefined; 5 | rotation: number | undefined; 6 | xywh: string | undefined; 7 | } 8 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-openseadragon-extension/ISettings.ts: -------------------------------------------------------------------------------- 1 | interface ISettings { 2 | navigatorEnabled?: boolean; 3 | pagingEnabled?: boolean; 4 | leftPanelOpen?: boolean; 5 | rightPanelOpen?: boolean; 6 | preserveViewport?: boolean; 7 | clickToZoomEnabled?: boolean; 8 | reducedAnimation?: boolean; 9 | truncateThumbnailLabels?: boolean; 10 | contrastPercent?: number; 11 | brightnessPercent?: number; 12 | saturationPercent?: number; 13 | rememberSettings?: boolean; 14 | animationDuration?: number; 15 | } 16 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-openseadragon-extension/Mode.ts: -------------------------------------------------------------------------------- 1 | export class Mode { 2 | static image = new Mode("image"); 3 | static page = new Mode("page"); 4 | 5 | constructor(public value: string) {} 6 | 7 | toString() { 8 | return this.value; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-openseadragon-extension/MultiSelectionArgs.ts: -------------------------------------------------------------------------------- 1 | export class MultiSelectionArgs { 2 | allCanvases: boolean; 3 | canvases: string[]; 4 | format: string; 5 | manifestUri: string; 6 | sequence: string; 7 | } 8 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-openseadragon-extension/ShareDialogue.ts: -------------------------------------------------------------------------------- 1 | import { OpenSeadragonExtensionEvents } from "./Events"; 2 | import OpenSeadragonExtension from "./Extension"; 3 | import { ShareDialogue as BaseShareDialogue } from "../../modules/uv-dialogues-module/ShareDialogue"; 4 | import { Config } from "../uv-openseadragon-extension/config/Config"; 5 | 6 | export class ShareDialogue extends BaseShareDialogue< 7 | Config["modules"]["shareDialogue"] 8 | > { 9 | constructor($element: JQuery) { 10 | super($element); 11 | 12 | this.extensionHost.subscribe( 13 | OpenSeadragonExtensionEvents.OPENSEADRAGON_OPEN, 14 | () => { 15 | this.update(); 16 | } 17 | ); 18 | 19 | this.extensionHost.subscribe( 20 | OpenSeadragonExtensionEvents.OPENSEADRAGON_ANIMATION_FINISH, 21 | () => { 22 | this.update(); 23 | } 24 | ); 25 | } 26 | 27 | create(): void { 28 | this.setConfig("shareDialogue"); 29 | super.create(); 30 | } 31 | 32 | update(): void { 33 | super.update(); 34 | 35 | const xywh: string = ( 36 | (this.extension).getViewportBounds() 37 | ); 38 | const rotation: number = ( 39 | (this.extension).getViewerRotation() 40 | ); 41 | 42 | this.embedCode = (this.extension).getEmbedScript( 43 | this.options.embedTemplate, 44 | this.currentWidth, 45 | this.currentHeight, 46 | xywh, 47 | rotation 48 | ); 49 | 50 | this.$embedCode.val(this.embedCode); 51 | } 52 | 53 | resize(): void { 54 | super.resize(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-openseadragon-extension/Store.ts: -------------------------------------------------------------------------------- 1 | import { createStore as create } from "zustand/vanilla"; 2 | import type { ExtensionState } from "../../modules/uv-shared-module/ExtensionState"; 3 | 4 | export interface OpenSeadragonExtensionState extends ExtensionState {} 5 | 6 | export const createStore = () => 7 | create((set) => ({ 8 | downloadDialogueOpen: false, 9 | dialogueTriggerButton: null, 10 | openDownloadDialogue: (triggerButton: HTMLElement) => 11 | set({ downloadDialogueOpen: true, dialogueTriggerButton: triggerButton }), 12 | closeDialogue: () => 13 | set({ 14 | downloadDialogueOpen: false, 15 | dialogueTriggerButton: null, 16 | }), 17 | })); 18 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-openseadragon-extension/theme/theme.less: -------------------------------------------------------------------------------- 1 | @import "../../../modules/uv-dialogues-module/css/styles.less"; 2 | @import "../../../modules/uv-moreinforightpanel-module/css/styles.less"; 3 | @import "../../../modules/uv-pagingheaderpanel-module/css/styles.less"; 4 | @import "../../../modules/uv-openseadragoncenterpanel-module/css/styles.less"; 5 | @import "../../../modules/uv-contentleftpanel-module/css/styles.less"; 6 | @import "../../../modules/uv-searchfooterpanel-module/css/styles.less"; 7 | @import "../../../modules/uv-multiselectdialogue-module/css/styles.less"; 8 | @import "../../../modules/uv-shared-module/css/styles.less"; 9 | @import "../../../modules/uv-osdmobilefooterpanel-module/css/styles.less"; 10 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-pdf-extension/DownloadDialogue.ts: -------------------------------------------------------------------------------- 1 | import { DownloadDialogue as BaseDownloadDialogue } from "../../modules/uv-dialogues-module/DownloadDialogue"; 2 | import { DownloadOption } from "../../modules/uv-shared-module/DownloadOption"; 3 | 4 | export class DownloadDialogue extends BaseDownloadDialogue { 5 | constructor($element: JQuery) { 6 | super($element); 7 | } 8 | 9 | create(): void { 10 | this.setConfig("downloadDialogue"); 11 | 12 | super.create(); 13 | } 14 | 15 | open(triggerButton: HTMLElement) { 16 | super.open(triggerButton); 17 | 18 | this.addEntireFileDownloadOptions(); 19 | 20 | if (!this.$downloadOptions.find("li:visible").length) { 21 | this.$noneAvailable.show(); 22 | } else { 23 | // select first option. 24 | this.$noneAvailable.hide(); 25 | } 26 | 27 | this.resize(); 28 | } 29 | 30 | isDownloadOptionAvailable(option: DownloadOption): boolean { 31 | return super.isDownloadOptionAvailable(option); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-pdf-extension/Events.ts: -------------------------------------------------------------------------------- 1 | export class PDFExtensionEvents { 2 | static namespace: string = "pdfExtension."; 3 | 4 | static PDF_LOADED: string = PDFExtensionEvents.namespace + "pdfLoaded"; 5 | static PAGE_INDEX_CHANGE: string = 6 | PDFExtensionEvents.namespace + "pageIndexChange"; 7 | static SEARCH: string = PDFExtensionEvents.namespace + "search"; 8 | static ZOOM_IN: string = PDFExtensionEvents.namespace + "zoomIn"; 9 | static ZOOM_OUT: string = PDFExtensionEvents.namespace + "zoomOut"; 10 | } 11 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-pdf-extension/IPDFExtension.ts: -------------------------------------------------------------------------------- 1 | import { IExtension } from "../../modules/uv-shared-module/IExtension"; 2 | 3 | export interface IPDFExtension extends IExtension { 4 | getEmbedScript(embedTemplate: string, width: number, height: number): string; 5 | isPdfJsEnabled(): boolean; 6 | } 7 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-pdf-extension/IPDFExtensionData.ts: -------------------------------------------------------------------------------- 1 | import { IUVData } from "../../../../IUVData"; 2 | import { Config } from "./config/Config"; 3 | 4 | export interface IPDFExtensionData extends IUVData { 5 | anchor: string | null; 6 | } 7 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-pdf-extension/SettingsDialogue.ts: -------------------------------------------------------------------------------- 1 | import { SettingsDialogue as BaseSettingsDialogue } from "../../modules/uv-dialogues-module/SettingsDialogue"; 2 | 3 | export class SettingsDialogue extends BaseSettingsDialogue { 4 | constructor($element: JQuery) { 5 | super($element); 6 | } 7 | 8 | create(): void { 9 | this.setConfig("settingsDialogue"); 10 | 11 | super.create(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-pdf-extension/ShareDialogue.ts: -------------------------------------------------------------------------------- 1 | import { ShareDialogue as BaseShareDialogue } from "../../modules/uv-dialogues-module/ShareDialogue"; 2 | import { Config } from "../uv-pdf-extension/config/Config"; 3 | import { IPDFExtension } from "./IPDFExtension"; 4 | 5 | export class ShareDialogue extends BaseShareDialogue< 6 | Config["modules"]["shareDialogue"] 7 | > { 8 | constructor($element: JQuery) { 9 | super($element); 10 | } 11 | 12 | create(): void { 13 | this.setConfig("shareDialogue"); 14 | 15 | super.create(); 16 | } 17 | 18 | update(): void { 19 | super.update(); 20 | 21 | this.embedCode = (this.extension).getEmbedScript( 22 | this.options.embedTemplate, 23 | this.currentWidth, 24 | this.currentHeight 25 | ); 26 | 27 | this.$embedCode.val(this.embedCode); 28 | } 29 | 30 | resize(): void { 31 | super.resize(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-pdf-extension/theme/theme.less: -------------------------------------------------------------------------------- 1 | @import "../../../modules/uv-dialogues-module/css/styles.less"; 2 | @import "../../../modules/uv-resourcesleftpanel-module/css/styles.less"; 3 | @import "../../../modules/uv-moreinforightpanel-module/css/styles.less"; 4 | @import "../../../modules/uv-pdfheaderpanel-module/css/styles.less"; 5 | @import "../../../modules/uv-pdfcenterpanel-module/css/styles.less"; 6 | @import "../../../modules/uv-pdfmobilefooterpanel-module/css/styles.less"; 7 | @import "../../../modules/uv-shared-module/css/styles.less"; 8 | @import "./treeviewleftpanel.less"; 9 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/extensions/uv-pdf-extension/theme/treeviewleftpanel.less: -------------------------------------------------------------------------------- 1 | // this is an example of extending a module's css in order for it to work with the current (pdf) extension, 2 | // without adding anything non-generic to the theme. 3 | 4 | .uv { 5 | .leftPanel { 6 | .thumbsView { 7 | .thumb { 8 | .wrap { 9 | border: none; 10 | 11 | img { 12 | display: block; 13 | width: 90px; 14 | } 15 | } 16 | 17 | &.selected { 18 | .wrap { 19 | border: none; 20 | } 21 | } 22 | } 23 | } 24 | } 25 | 26 | .headerPanel { 27 | .centerOptions { 28 | .search { 29 | width: 123px; 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/helpers.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ContentState, 3 | normaliseContentState, 4 | NormalisedContentState, 5 | parseContentState, 6 | } from "./content-state/content-state"; 7 | export function parseContentStateParameter( 8 | contentState?: ContentState | string 9 | ): 10 | | NormalisedContentState 11 | | { type: "remote-content-state"; id: string } 12 | | null { 13 | if (!contentState) { 14 | return null; 15 | } 16 | 17 | if (typeof contentState === "string" && contentState.startsWith("http")) { 18 | return { type: "remote-content-state", id: contentState }; 19 | } 20 | 21 | try { 22 | return normaliseContentState( 23 | typeof contentState === "string" 24 | ? parseContentState(contentState) 25 | : contentState 26 | ); 27 | } catch (err) { 28 | return null; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/img/pixel.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/img/pixel.gif -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-alephcenterpanel-module/ControlsType.ts: -------------------------------------------------------------------------------- 1 | export enum ControlsType { 2 | ORBIT = "orbit", 3 | TRACKBALL = "trackball", 4 | } 5 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-alephcenterpanel-module/DisplayMode.ts: -------------------------------------------------------------------------------- 1 | export enum DisplayMode { 2 | SLICES = "slices", 3 | VOLUME = "volume", 4 | MESH = "mesh", 5 | } 6 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-alephcenterpanel-module/Orientation.ts: -------------------------------------------------------------------------------- 1 | export enum Orientation { 2 | CORONAL = "coronal", 3 | SAGGITAL = "saggital", 4 | AXIAL = "axial", 5 | } 6 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-alephcenterpanel-module/Units.ts: -------------------------------------------------------------------------------- 1 | export enum Units { 2 | METERS = "m", 3 | MILLIMETERS = "mm", 4 | } 5 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-alephcenterpanel-module/css/styles.less: -------------------------------------------------------------------------------- 1 | .uv-iiif-extension-host.uv-aleph-extension { 2 | .centerPanel { 3 | #container { 4 | // background-color: #000; 5 | // left: 0; 6 | // right: 0; 7 | // top: 0; 8 | // bottom: 0; 9 | // position: absolute; 10 | // width: 100%; 11 | // height: 100%; 12 | // overflow: hidden; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-alephleftpanel-module/css/styles.less: -------------------------------------------------------------------------------- 1 | .uv-iiif-extension-host.uv-aleph-extension { 2 | .leftPanel { 3 | .top { 4 | .title { 5 | text-transform: uppercase; 6 | } 7 | } 8 | 9 | .main { 10 | overflow: auto; 11 | padding: @padding-medium-vertical 0 0 0; 12 | //padding: @padding-medium-vertical @padding-medium-horizontal @padding-medium-vertical @padding-medium-horizontal; 13 | &.disabled { 14 | pointer-events: none; 15 | opacity: 0.4; 16 | } 17 | 18 | al-control-panel { 19 | --al-color-primary: #26b5cc; 20 | --al-color-dark: #100f10; 21 | --al-mesh-viewport-background-color: #000; 22 | --al-slices-viewport-background-color: #000; 23 | --al-volume-viewport-background-color: #000; 24 | --al-item-color: #c7c5c7; 25 | --al-item-selected-color: #00b0ff; 26 | --al-item-border-color: transparent; 27 | --al-controlpanel-background-color: #212121; /*#f7f7f7*/ 28 | --al-console-font-size: 0.75rem; 29 | 30 | --al-input-background-color: #333233; 31 | --al-input-font-size: 1rem; 32 | --al-input-color: #c7c5c7; 33 | --al-input-padding-start: 10px; 34 | --al-input-padding-top: 10px; 35 | --al-input-padding-end: 10px; 36 | --al-input-padding-bottom: 10px; 37 | 38 | --al-textarea-background-color: #333233; 39 | --al-textarea-font-size: 1rem; 40 | --al-textarea-color: #c7c5c7; 41 | --al-textarea-padding-start: 10px; 42 | --al-textarea-padding-top: 10px; 43 | --al-textarea-padding-end: 10px; 44 | --al-textarea-padding-bottom: 10px; 45 | 46 | --al-select-background-color: #333233; 47 | 48 | --color: var(--al-color-primary); 49 | --ion-item-color: var(--al-item-color); 50 | --ion-item-border-color: var(--al-item-border-color); 51 | --ion-text-color-rgb: 255, 255, 255; 52 | --ion-color-primary-rgb: 255, 255, 255; 53 | --ion-highlight-color-focused: var(--al-color-primary); 54 | --ion-color-primary-shade: var(--al-color-primary); 55 | --ion-color-primary-tint: var(--al-color-primary); 56 | --app-background-color: var(--al-controlpanel-background-color); 57 | --ion-background-color: var(--al-controlpanel-background-color); 58 | 59 | --ion-color-primary: #00b0ff; 60 | --ion-color-primary-rgb: 0, 176, 255; 61 | --ion-color-primary-contrast: #ffffff; 62 | --ion-color-primary-contrast-rgb: 255, 255, 255; 63 | --ion-color-primary-shade: #00b0ff; 64 | --ion-color-primary-tint: #00b0ff; 65 | 66 | //--graph-enabled-display: none; 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-avmobilefooterpanel-module/MobileFooter.ts: -------------------------------------------------------------------------------- 1 | import { Config } from "../../extensions/uv-av-extension/config/Config"; 2 | import { FooterPanel as BaseFooterPanel } from "../uv-shared-module/FooterPanel"; 3 | 4 | export class FooterPanel extends BaseFooterPanel< 5 | Config["modules"]["mobileFooterPanel"] 6 | > { 7 | $fullScreenBtn: JQuery; 8 | 9 | constructor($element: JQuery) { 10 | super($element); 11 | } 12 | 13 | create(): void { 14 | this.setConfig("mobileFooterPanel"); 15 | 16 | super.create(); 17 | } 18 | 19 | resize(): void { 20 | super.resize(); 21 | 22 | this.$options.css( 23 | "left", 24 | Math.floor(this.$element.width() / 2 - this.$options.width() / 2) 25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-avmobilefooterpanel-module/img/exit_fullscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-avmobilefooterpanel-module/img/exit_fullscreen.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-avmobilefooterpanel-module/img/fullscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-avmobilefooterpanel-module/img/fullscreen.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-contentleftpanel-module/GalleryView.ts: -------------------------------------------------------------------------------- 1 | import { IIIFEvents } from "../../IIIFEvents"; 2 | import { ContentLeftPanel } from "../../extensions/config/ContentLeftPanel"; 3 | import { BaseView } from "../uv-shared-module/BaseView"; 4 | import { GalleryComponent } from "@iiif/iiif-gallery-component"; 5 | import $ from "jquery"; 6 | 7 | export class GalleryView extends BaseView { 8 | isOpen: boolean = false; 9 | galleryComponent: any; 10 | galleryData: any; 11 | $gallery: JQuery; 12 | 13 | constructor( 14 | $element: JQuery, 15 | fitToParentWidth: boolean = true, 16 | fitToParentHeight: boolean = true 17 | ) { 18 | super($element, fitToParentWidth, fitToParentHeight); 19 | } 20 | 21 | create(): void { 22 | this.setConfig("contentLeftPanel"); 23 | super.create(); 24 | 25 | this.$gallery = $(''); 26 | this.$element.append(this.$gallery); 27 | } 28 | 29 | public setup(): void { 30 | const that = this; 31 | 32 | this.galleryComponent = new GalleryComponent({ 33 | target: this.$gallery[0], 34 | }); 35 | 36 | this.galleryComponent.on( 37 | "thumbSelected", 38 | function (thumb: any) { 39 | that.extensionHost.publish(IIIFEvents.GALLERY_THUMB_SELECTED, thumb); 40 | that.extensionHost.publish(IIIFEvents.THUMB_SELECTED, thumb); 41 | }, 42 | false 43 | ); 44 | 45 | this.galleryComponent.on( 46 | "decreaseSize", 47 | function () { 48 | that.extensionHost.publish(IIIFEvents.GALLERY_DECREASE_SIZE); 49 | }, 50 | false 51 | ); 52 | 53 | this.galleryComponent.on( 54 | "increaseSize", 55 | function () { 56 | that.extensionHost.publish(IIIFEvents.GALLERY_INCREASE_SIZE); 57 | }, 58 | false 59 | ); 60 | } 61 | 62 | public databind(): void { 63 | this.galleryComponent.options.data = this.galleryData; 64 | this.galleryComponent.set(this.galleryData); 65 | this.resize(); 66 | } 67 | 68 | show(): void { 69 | this.isOpen = true; 70 | this.$element.show(); 71 | 72 | // todo: would be better to have no imperative methods on components and use a reactive pattern 73 | setTimeout(() => { 74 | this.galleryComponent.selectIndex(this.extension.helper.canvasIndex); 75 | this.applyExtendedLabelsStyles(); 76 | }, 10); 77 | } 78 | 79 | hide(): void { 80 | this.isOpen = false; 81 | this.$element.hide(); 82 | } 83 | 84 | resize(): void { 85 | super.resize(); 86 | const $main: JQuery = this.$gallery.find(".main"); 87 | const $header: JQuery = this.$gallery.find(".header"); 88 | $main.height(this.$element.height() - $header.height()); 89 | } 90 | 91 | public applyExtendedLabelsStyles(): void { 92 | this.$gallery.addClass("label-extended"); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-contentleftpanel-module/img/padlock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-contentleftpanel-module/img/padlock.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-contentleftpanel-module/img/thumb_placeholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-contentleftpanel-module/img/thumb_placeholder.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-dialogues-module/ExternalContentDialogue.ts: -------------------------------------------------------------------------------- 1 | const $ = require("jquery"); 2 | import { IIIFEvents } from "../../IIIFEvents"; 3 | import { Config } from "../../extensions/uv-openseadragon-extension/config/Config"; 4 | import { Dialogue } from "../uv-shared-module/Dialogue"; 5 | 6 | export class ExternalContentDialogue extends Dialogue< 7 | Config["modules"]["multiSelectDialogue"] 8 | > { 9 | $iframe: JQuery; 10 | 11 | constructor($element: JQuery) { 12 | super($element); 13 | } 14 | 15 | create(): void { 16 | this.setConfig("externalContentDialogue"); 17 | 18 | super.create(); 19 | 20 | this.openCommand = IIIFEvents.SHOW_EXTERNALCONTENT_DIALOGUE; 21 | this.closeCommand = IIIFEvents.HIDE_EXTERNALCONTENT_DIALOGUE; 22 | 23 | this.extensionHost.subscribe(this.openCommand, (params: any) => { 24 | this.open(); 25 | this.$iframe.prop("src", params.uri); 26 | }); 27 | 28 | this.extensionHost.subscribe(this.closeCommand, () => { 29 | this.close(); 30 | }); 31 | 32 | this.$iframe = $(""); 33 | this.$content.append(this.$iframe); 34 | 35 | this.$element.hide(); 36 | } 37 | 38 | resize(): void { 39 | super.resize(); 40 | 41 | this.$iframe.width(this.$content.width()); 42 | this.$iframe.height(this.$content.height()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-dialogues-module/HelpDialogue.ts: -------------------------------------------------------------------------------- 1 | const $ = require("jquery"); 2 | import { BaseConfig } from "../../BaseConfig"; 3 | import { IIIFEvents } from "../../IIIFEvents"; 4 | import { Dialogue } from "../uv-shared-module/Dialogue"; 5 | 6 | export class HelpDialogue extends Dialogue< 7 | BaseConfig["modules"]["helpDialogue"] 8 | > { 9 | $message: JQuery; 10 | $scroll: JQuery; 11 | $title: JQuery; 12 | 13 | constructor($element: JQuery) { 14 | super($element); 15 | } 16 | 17 | create(): void { 18 | this.setConfig("helpDialogue"); 19 | 20 | super.create(); 21 | 22 | this.openCommand = IIIFEvents.SHOW_HELP_DIALOGUE; 23 | this.closeCommand = IIIFEvents.HIDE_HELP_DIALOGUE; 24 | 25 | this.extensionHost.subscribe(this.openCommand, () => { 26 | this.open(); 27 | }); 28 | 29 | this.extensionHost.subscribe(this.closeCommand, () => { 30 | this.close(); 31 | }); 32 | 33 | this.$title = $(`
`); 34 | this.$content.append(this.$title); 35 | 36 | this.$scroll = $('
'); 37 | this.$content.append(this.$scroll); 38 | 39 | this.$message = $("

"); 40 | this.$scroll.append(this.$message); 41 | 42 | // initialise ui. 43 | this.$title.text(this.content.title); 44 | this.$message.html(this.content.text); 45 | 46 | // ensure anchor tags link to _blank. 47 | this.$message.targetBlank(); 48 | 49 | this.$element.hide(); 50 | } 51 | 52 | resize(): void { 53 | super.resize(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-dialogues-module/css/mobile.less: -------------------------------------------------------------------------------- 1 | @media only screen and (min-width: @sm-min-width) { 2 | .uv { 3 | .overlay { 4 | &.share { 5 | padding: 0 0 0 8px; 6 | } 7 | 8 | &.download { 9 | padding: 0 0 0 8px; 10 | } 11 | 12 | &.moreInfo { 13 | padding: 0 0 0 8px; 14 | } 15 | 16 | &.auth { 17 | width: 250px; 18 | height: 250px; 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-ebookcenterpanel-module/css/styles.less: -------------------------------------------------------------------------------- 1 | .uv-iiif-extension-host.uv-ebook-extension { 2 | .centerPanel { 3 | background-color: #fff; 4 | 5 | uv-ebook-reader { 6 | --reader-spinner-color: #bdbdbd; 7 | --reader-arrow-color: #e2e2e2; 8 | --reader-arrow-hover-color: #777; 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-ebookleftpanel-module/css/styles.less: -------------------------------------------------------------------------------- 1 | .uv-iiif-extension-host.uv-ebook-extension { 2 | .mainPanel { 3 | .leftPanel { 4 | .top { 5 | .title { 6 | text-transform: uppercase; 7 | } 8 | } 9 | 10 | .main { 11 | //padding: @padding-medium-vertical @padding-medium-horizontal @padding-medium-vertical @padding-medium-horizontal; 12 | &.disabled { 13 | pointer-events: none; 14 | opacity: 0.4; 15 | } 16 | 17 | .container { 18 | overflow: auto; 19 | padding: @padding-medium; 20 | 21 | uv-ebook-toc { 22 | --toc-link-selected-color: @link-color; 23 | --toc-link-padding: 0.2rem; 24 | --toc-margin: 0; 25 | --toc-padding: 0; 26 | --toc-list-style-type: none; 27 | } 28 | } 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-ebookmobilefooterpanel-module/MobileFooter.ts: -------------------------------------------------------------------------------- 1 | import { Config } from "../../extensions/uv-ebook-extension/config/Config"; 2 | import { FooterPanel as BaseFooterPanel } from "../uv-shared-module/FooterPanel"; 3 | 4 | export class FooterPanel extends BaseFooterPanel< 5 | Config["modules"]["footerPanel"] 6 | > { 7 | $fullScreenBtn: JQuery; 8 | 9 | constructor($element: JQuery) { 10 | super($element); 11 | } 12 | 13 | create(): void { 14 | this.setConfig("mobileFooterPanel"); 15 | 16 | super.create(); 17 | } 18 | 19 | resize(): void { 20 | super.resize(); 21 | 22 | this.$options.css( 23 | "left", 24 | Math.floor(this.$element.width() / 2 - this.$options.width() / 2) 25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-ebookmobilefooterpanel-module/css/styles.less: -------------------------------------------------------------------------------- 1 | .left-options { 2 | min-width: 30px; 3 | } 4 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-filelinkcenterpanel-module/css/styles.less: -------------------------------------------------------------------------------- 1 | .uv-iiif-extension-host.uv-default-extension { 2 | .centerPanel { 3 | .content { 4 | .scroll { 5 | margin: @margin-medium-vertical @margin-medium-horizontal 6 | @margin-medium-vertical @margin-xlarge-horizontal; 7 | overflow: auto; 8 | 9 | ol { 10 | margin: @margin-medium-vertical 0 0 0; 11 | padding: 0; 12 | list-style-type: none; 13 | 14 | li { 15 | margin: 0 0 @margin-xlarge-vertical 0; 16 | overflow: hidden; 17 | 18 | img { 19 | float: left; 20 | width: 70px; 21 | margin: 0 @margin-large-horizontal 0 0; 22 | } 23 | 24 | .col2 { 25 | float: left; 26 | 27 | .filename { 28 | display: block; 29 | margin: 0 0 2px 0; 30 | font-size: 16px; 31 | } 32 | 33 | .label { 34 | display: block; 35 | margin: 0 0 2px 0; 36 | } 37 | 38 | .description { 39 | display: block; 40 | .icon-left(data-uri("../img/download.png"), 24px, 24px); 41 | line-height: 24px; 42 | margin: 0 0 0 -4px; 43 | } 44 | } 45 | } 46 | } 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-filelinkcenterpanel-module/img/download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-filelinkcenterpanel-module/img/download.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-mediaelementcenterpanel-module/css/overrides.less: -------------------------------------------------------------------------------- 1 | .uv .centerPanel .content { 2 | .mejs__time { 3 | height: 25px; 4 | } 5 | 6 | .attribution { 7 | z-index: 19; 8 | } 9 | 10 | .mejs__button > button:focus { 11 | outline: 2px solid AccentColor; 12 | outline-offset: 2px; 13 | } 14 | } 15 | 16 | .uv .overlays { 17 | z-index: 101 !important; 18 | } 19 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-mediaelementcenterpanel-module/css/styles.less: -------------------------------------------------------------------------------- 1 | @import "overrides.less"; 2 | 3 | .uv-iiif-extension-host.uv-mediaelement-extension { 4 | .mejs-container.mejs-uv { 5 | background-color: @body-bg; 6 | } 7 | 8 | .centerPanel { 9 | .content { 10 | position: relative; 11 | 12 | .attribution { 13 | .sm-mediaquery({ 14 | margin: 25px 20px; 15 | }); 16 | 17 | .md-mediaquery({ 18 | margin-bottom: 60px !important; 19 | }); 20 | } 21 | 22 | .wrapper { 23 | width: 100%; 24 | height: 100%; 25 | overflow: hidden; 26 | 27 | .container { 28 | display: flex; 29 | align-items: center; 30 | margin: auto; 31 | width: 100%; 32 | height: 100%; 33 | } 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-mediaelementmobilefooterpanel-module/MobileFooter.ts: -------------------------------------------------------------------------------- 1 | import { Config } from "../../extensions/uv-pdf-extension/config/Config"; 2 | import { FooterPanel as BaseFooterPanel } from "../uv-shared-module/FooterPanel"; 3 | 4 | export class FooterPanel extends BaseFooterPanel< 5 | Config["modules"]["mobileFooterPanel"] 6 | > { 7 | constructor($element: JQuery) { 8 | super($element); 9 | } 10 | 11 | create(): void { 12 | this.setConfig("mobileFooterPanel"); 13 | 14 | super.create(); 15 | } 16 | 17 | resize(): void { 18 | super.resize(); 19 | 20 | this.$options.css( 21 | "left", 22 | Math.floor(this.$element.width() / 2 - this.$options.width() / 2) 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-mediaelementmobilefooterpanel-module/css/styles.less: -------------------------------------------------------------------------------- 1 | .@{icon-prefix}-zoom-in { 2 | .icon-btn-2(data-uri("../img/zoom_in.png")); 3 | } 4 | 5 | .@{icon-prefix}-zoom-out { 6 | .icon-btn-2(data-uri("../img/zoom_out.png")); 7 | } 8 | .left-options { 9 | min-width: 30px; 10 | } 11 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-mediaelementmobilefooterpanel-module/img/zoom_in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-mediaelementmobilefooterpanel-module/img/zoom_in.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-mediaelementmobilefooterpanel-module/img/zoom_out.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-mediaelementmobilefooterpanel-module/img/zoom_out.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-modelviewercenterpanel-module/css/styles.less: -------------------------------------------------------------------------------- 1 | .uv-iiif-extension-host.uv-model-viewer-extension { 2 | .centerPanel { 3 | .content { 4 | position: relative; 5 | 6 | model-viewer { 7 | --progress-bar-color: #000; 8 | --progress-bar-height: 1px; 9 | --poster-color: transparent; 10 | } 11 | 12 | .spinner { 13 | position: absolute; 14 | width: 27px; 15 | height: 27px; 16 | border-radius: 27px; 17 | .loading(@loader-black-bg); 18 | } 19 | 20 | .annotationPin { 21 | // background-color: white; 22 | background-image: data-uri("../img/pin.svg") !important; 23 | width: 28px !important; 24 | height: 37px !important; 25 | background-position-x: 1px; 26 | transform: translate(0, -50%); 27 | overflow: hidden; 28 | cursor: pointer; 29 | 30 | span { 31 | color: #2a2a2a; 32 | user-select: none; 33 | display: block; 34 | width: 95%; 35 | text-align: center; 36 | margin-top: 8px; 37 | font-size: 11px; 38 | } 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-modelviewercenterpanel-module/img/pin.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-modelviewermobilefooterpanel-module/MobileFooter.ts: -------------------------------------------------------------------------------- 1 | import { BaseConfig } from "../../BaseConfig"; 2 | import { FooterPanel as BaseFooterPanel } from "../uv-shared-module/FooterPanel"; 3 | 4 | export class FooterPanel< 5 | T extends BaseConfig["modules"]["footerPanel"], 6 | > extends BaseFooterPanel { 7 | constructor($element: JQuery) { 8 | super($element); 9 | } 10 | 11 | create(): void { 12 | this.setConfig("mobileFooterPanel"); 13 | 14 | super.create(); 15 | } 16 | 17 | resize(): void { 18 | super.resize(); 19 | 20 | setTimeout(() => { 21 | this.$options.css( 22 | "left", 23 | Math.floor(this.$element.width() / 2 - this.$options.width() / 2) 24 | ); 25 | }, 100); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-modelviewermobilefooterpanel-module/css/styles.less: -------------------------------------------------------------------------------- 1 | .uv-iiif-extension-host.uv-model-viewer-extension { 2 | .mobileFooterPanel { 3 | text-align: center; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-moreinforightpanel-module/css/styles.less: -------------------------------------------------------------------------------- 1 | @import "@iiif/iiif-metadata-component/dist-css/styles.less"; 2 | 3 | .uv { 4 | .rightPanel { 5 | .top { 6 | .title { 7 | text-transform: uppercase; 8 | } 9 | } 10 | 11 | .content { 12 | padding: @padding-medium; 13 | } 14 | 15 | .main { 16 | overflow: auto; 17 | color: @text-color; 18 | 19 | &.loading { 20 | .loading(@loader-black-bg); 21 | } 22 | 23 | .noData { 24 | padding: 0 @padding-medium-horizontal (@padding-medium-vertical * 2) 25 | @padding-medium-horizontal; 26 | } 27 | 28 | .groups { 29 | padding: @padding-medium-vertical @padding-medium-horizontal 30 | (@padding-medium-vertical * 2) @padding-medium-horizontal; 31 | 32 | .group { 33 | .header { 34 | text-transform: uppercase; 35 | } 36 | } 37 | 38 | .items { 39 | .header { 40 | font-size: @font-size-small; 41 | text-transform: uppercase; 42 | } 43 | 44 | .item { 45 | .header { 46 | font-size: @font-size-small; 47 | text-transform: uppercase; 48 | } 49 | 50 | .value { 51 | color: @text-color; 52 | } 53 | } 54 | } 55 | 56 | [data-uv-navigate] { 57 | color: @link-secondary-color; 58 | cursor: pointer; 59 | 60 | &:hover { 61 | text-decoration: underline; 62 | color: @link-secondary-hover-color; 63 | } 64 | } 65 | } 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-moreinforightpanel-module/img/copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-moreinforightpanel-module/img/copy.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-multiselectdialogue-module/css/styles.less: -------------------------------------------------------------------------------- 1 | .uv { 2 | .overlays { 3 | > div.multiSelect { 4 | width: 480px; 5 | 6 | .content { 7 | height: 350px; 8 | 9 | .iiif-gallery-component { 10 | .header { 11 | .btn-primary { 12 | width: auto; 13 | } 14 | .right { 15 | .multiSelectOptions { 16 | .multiSelectAll { 17 | padding-top: 6px; 18 | label { 19 | padding-left: 2px; 20 | } 21 | } 22 | } 23 | } 24 | } 25 | .main { 26 | .thumb { 27 | .wrap { 28 | &.loading { 29 | .loading(@loader-white-bg); 30 | } 31 | } 32 | 33 | &.selected { 34 | .wrap { 35 | border: 2px solid @brand-primary; 36 | } 37 | } 38 | 39 | span { 40 | color: @text-secondary-color; 41 | } 42 | } 43 | } 44 | } 45 | } 46 | 47 | .bottom { 48 | background: none; 49 | } 50 | } 51 | } 52 | } 53 | 54 | .uv-iiif-extension-host.browser-Explorer { 55 | .overlays { 56 | > div.multiSelect { 57 | .content { 58 | .iiif-gallery-component { 59 | .header { 60 | input[type="range"] { 61 | margin-top: -11px; 62 | } 63 | } 64 | } 65 | } 66 | } 67 | } 68 | } 69 | 70 | .uv-iiif-extension-host.browser-Firefox { 71 | .overlays { 72 | > div.multiSelect { 73 | .content { 74 | .iiif-gallery-component { 75 | .header { 76 | input[type="range"] { 77 | margin-top: 9px; 78 | overflow: hidden; 79 | } 80 | } 81 | } 82 | } 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-openseadragoncenterpanel-module/css/mobile.less: -------------------------------------------------------------------------------- 1 | // @media only screen and (min-width: @sm-min-width) { 2 | // .uv-iiif-extension-host.uv-openseadragon-extension { 3 | // // .centerPanel { 4 | 5 | // // .title { 6 | // // padding-top: @margin-small-vertical !important; 7 | // // } 8 | // // } 9 | // } 10 | // } 11 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-openseadragoncenterpanel-module/img/adjust.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-openseadragoncenterpanel-module/img/adjust.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-openseadragoncenterpanel-module/img/down_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-openseadragoncenterpanel-module/img/down_arrow.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-openseadragoncenterpanel-module/img/down_arrow_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-openseadragoncenterpanel-module/img/down_arrow_disabled.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-openseadragoncenterpanel-module/img/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-openseadragoncenterpanel-module/img/home.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-openseadragoncenterpanel-module/img/left_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-openseadragoncenterpanel-module/img/left_arrow.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-openseadragoncenterpanel-module/img/left_arrow_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-openseadragoncenterpanel-module/img/left_arrow_disabled.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-openseadragoncenterpanel-module/img/pin.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-openseadragoncenterpanel-module/img/pixel.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-openseadragoncenterpanel-module/img/pixel.gif -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-openseadragoncenterpanel-module/img/right_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-openseadragoncenterpanel-module/img/right_arrow.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-openseadragoncenterpanel-module/img/right_arrow_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-openseadragoncenterpanel-module/img/right_arrow_disabled.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-openseadragoncenterpanel-module/img/rotate_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-openseadragoncenterpanel-module/img/rotate_right.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-openseadragoncenterpanel-module/img/up_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-openseadragoncenterpanel-module/img/up_arrow.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-openseadragoncenterpanel-module/img/up_arrow_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-openseadragoncenterpanel-module/img/up_arrow_disabled.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-openseadragoncenterpanel-module/img/zoom_in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-openseadragoncenterpanel-module/img/zoom_in.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-openseadragoncenterpanel-module/img/zoom_out.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-openseadragoncenterpanel-module/img/zoom_out.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-osdmobilefooterpanel-module/css/styles.less: -------------------------------------------------------------------------------- 1 | .@{icon-prefix}-rotate { 2 | .icon-btn-2(data-uri("../img/rotate_right.png")); 3 | } 4 | 5 | .@{icon-prefix}-zoom-in { 6 | .icon-btn-2(data-uri("../img/zoom_in.png")); 7 | } 8 | 9 | .@{icon-prefix}-zoom-out { 10 | .icon-btn-2(data-uri("../img/zoom_out.png")); 11 | } 12 | 13 | .left-options { 14 | min-width: 30px; 15 | } 16 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-osdmobilefooterpanel-module/img/rotate_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-osdmobilefooterpanel-module/img/rotate_right.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-osdmobilefooterpanel-module/img/zoom_in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-osdmobilefooterpanel-module/img/zoom_in.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-osdmobilefooterpanel-module/img/zoom_out.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-osdmobilefooterpanel-module/img/zoom_out.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-pagingheaderpanel-module/css/icons.less: -------------------------------------------------------------------------------- 1 | .@{icon-prefix}-first { 2 | .icon-btn-2(data-uri("../img/first.png")); 3 | } 4 | 5 | .@{icon-prefix}-prev { 6 | .icon-btn-2(data-uri("../img/prev.png")); 7 | } 8 | 9 | .@{icon-prefix}-next { 10 | .icon-btn-2(data-uri("../img/next.png")); 11 | } 12 | 13 | .@{icon-prefix}-last { 14 | .icon-btn-2(data-uri("../img/last.png")); 15 | } 16 | 17 | // Icon does not exist. 18 | //.@{icon-prefix}-go { 19 | // .icon-btn-2(data-uri('../img/go.png')); 20 | //} 21 | 22 | .@{icon-prefix}-one-up { 23 | .icon-btn-2(data-uri("../img/one_up.png")); 24 | } 25 | 26 | .@{icon-prefix}-two-up { 27 | .icon-btn-2(data-uri("../img/two_up.png")); 28 | } 29 | 30 | .@{icon-prefix}-gallery { 31 | .icon-btn-2(data-uri("../img/grid.png")); 32 | } 33 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-pagingheaderpanel-module/img/first.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-pagingheaderpanel-module/img/first.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-pagingheaderpanel-module/img/grid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-pagingheaderpanel-module/img/grid.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-pagingheaderpanel-module/img/last.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-pagingheaderpanel-module/img/last.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-pagingheaderpanel-module/img/next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-pagingheaderpanel-module/img/next.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-pagingheaderpanel-module/img/one_up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-pagingheaderpanel-module/img/one_up.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-pagingheaderpanel-module/img/prev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-pagingheaderpanel-module/img/prev.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-pagingheaderpanel-module/img/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-pagingheaderpanel-module/img/settings.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-pagingheaderpanel-module/img/two_up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-pagingheaderpanel-module/img/two_up.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-pdfcenterpanel-module/css/styles.less: -------------------------------------------------------------------------------- 1 | .uv-iiif-extension-host.uv-pdf-extension { 2 | .centerPanel { 3 | .content { 4 | position: relative; 5 | 6 | .pdfContainer { 7 | overflow: auto; 8 | text-align: center; 9 | 10 | canvas { 11 | display: inline; 12 | } 13 | } 14 | 15 | .spinner { 16 | position: absolute; 17 | width: 27px; 18 | height: 27px; 19 | border-radius: 27px; 20 | .loading(@loader-black-bg); 21 | } 22 | 23 | progress { 24 | position: absolute; 25 | width: 100px; 26 | height: 10px; 27 | } 28 | 29 | button { 30 | color: #fff; 31 | } 32 | 33 | // canvas { 34 | // position: absolute; 35 | // } 36 | 37 | .container { 38 | margin: 0 20px 0 20px; 39 | } 40 | 41 | .btn { 42 | position: absolute !important; 43 | width: 30px; 44 | height: 90px; 45 | background-repeat: no-repeat; 46 | background-color: @body-bg; 47 | background-position: 0px 50%; 48 | cursor: pointer; 49 | padding: 0px; 50 | border: none; 51 | border-radius: 0px; 52 | 53 | &.zoomIn { 54 | cursor: pointer !important; 55 | background-image: data-uri("../img/zoom_in.png") !important; 56 | width: 28px; 57 | height: 28px; 58 | margin: 3px !important; 59 | top: 0px; 60 | left: 0px; 61 | img { 62 | display: none; 63 | } 64 | &:focus { 65 | .tab-focus(); 66 | } 67 | } 68 | 69 | &.zoomOut { 70 | cursor: pointer !important; 71 | background-image: data-uri("../img/zoom_out.png") !important; 72 | width: 28px; 73 | height: 28px; 74 | margin: 3px !important; 75 | top: 0px; 76 | left: 32px; 77 | img { 78 | display: none; 79 | } 80 | &:focus { 81 | .tab-focus(); 82 | } 83 | } 84 | 85 | &.prev { 86 | margin-left: 5px; 87 | background-image: data-uri("../img/left_arrow.png"); 88 | &.disabled { 89 | background-image: data-uri("../img/left_arrow_disabled.png"); 90 | } 91 | } 92 | 93 | &.next { 94 | margin-right: 20px; 95 | background-image: data-uri("../img/right_arrow.png"); 96 | &.disabled { 97 | background-image: data-uri("../img/right_arrow_disabled.png"); 98 | } 99 | } 100 | } 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-pdfcenterpanel-module/img/left_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-pdfcenterpanel-module/img/left_arrow.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-pdfcenterpanel-module/img/left_arrow_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-pdfcenterpanel-module/img/left_arrow_disabled.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-pdfcenterpanel-module/img/right_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-pdfcenterpanel-module/img/right_arrow.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-pdfcenterpanel-module/img/right_arrow_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-pdfcenterpanel-module/img/right_arrow_disabled.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-pdfcenterpanel-module/img/zoom_in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-pdfcenterpanel-module/img/zoom_in.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-pdfcenterpanel-module/img/zoom_out.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-pdfcenterpanel-module/img/zoom_out.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-pdfheaderpanel-module/css/icons.less: -------------------------------------------------------------------------------- 1 | .@{icon-prefix}-first { 2 | .icon-btn-2(data-uri("../img/first.png")); 3 | } 4 | 5 | .@{icon-prefix}-prev { 6 | .icon-btn-2(data-uri("../img/prev.png")); 7 | } 8 | 9 | .@{icon-prefix}-next { 10 | .icon-btn-2(data-uri("../img/next.png")); 11 | } 12 | 13 | .@{icon-prefix}-last { 14 | .icon-btn-2(data-uri("../img/last.png")); 15 | } 16 | 17 | // .@{icon-prefix}-go { 18 | // .icon-btn-2(data-uri('../img/go.png')); 19 | // } 20 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-pdfheaderpanel-module/css/styles.less: -------------------------------------------------------------------------------- 1 | @import "icons"; 2 | 3 | .uv-iiif-extension-host.uv-pdf-extension { 4 | .headerPanel { 5 | color: @text-secondary-color; 6 | 7 | button.btn.imageBtn { 8 | padding-left: 2px; 9 | padding-right: 2px; 10 | 11 | &.first, 12 | &.prev, 13 | &.next, 14 | &.last { 15 | i { 16 | background-color: @gray; 17 | &:hover { 18 | background-color: @gray-dark; 19 | } 20 | } 21 | } 22 | 23 | &.disabled, 24 | &.disabled:hover, 25 | &.disabled i, 26 | &.disabled i:hover { 27 | background-color: transparent; 28 | } 29 | } 30 | 31 | .centerOptions { 32 | .prevOptions { 33 | float: left; 34 | margin: 0 15px 0 0; 35 | } 36 | 37 | .search { 38 | float: left; 39 | margin: 6px 0 0 5px; 40 | width: auto; 41 | 42 | .searchText { 43 | border: none; 44 | padding: 0 0 0 2px; 45 | } 46 | } 47 | 48 | .nextOptions { 49 | float: left; 50 | margin: 0 0 0 15px; 51 | } 52 | } 53 | 54 | .searchText { 55 | width: 30px; 56 | height: 19px; 57 | line-height: 19px; 58 | float: left; 59 | font-size: @font-size-small; 60 | padding: 0; 61 | margin-top: 6px; 62 | } 63 | 64 | .total { 65 | float: left; 66 | display: block; 67 | height: 18px; 68 | line-height: 18px; 69 | margin: 6px 5px 0 5px; 70 | width: 41px; 71 | font-size: @font-size-small; 72 | overflow: hidden; 73 | color: white; 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-pdfheaderpanel-module/img/first.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-pdfheaderpanel-module/img/first.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-pdfheaderpanel-module/img/last.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-pdfheaderpanel-module/img/last.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-pdfheaderpanel-module/img/next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-pdfheaderpanel-module/img/next.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-pdfheaderpanel-module/img/prev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-pdfheaderpanel-module/img/prev.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-pdfmobilefooterpanel-module/MobileFooter.ts: -------------------------------------------------------------------------------- 1 | const $ = require("jquery"); 2 | import { Config } from "../../extensions/uv-pdf-extension/config/Config"; 3 | import { PDFExtensionEvents } from "../../extensions/uv-pdf-extension/Events"; 4 | import { FooterPanel as BaseFooterPanel } from "../uv-shared-module/FooterPanel"; 5 | import { IPDFExtension } from "../../extensions/uv-pdf-extension/IPDFExtension"; 6 | 7 | export class FooterPanel extends BaseFooterPanel< 8 | Config["modules"]["mobileFooterPanel"] 9 | > { 10 | $fullScreenBtn: JQuery; 11 | $zoomInButton: JQuery; 12 | $zoomOutButton: JQuery; 13 | 14 | constructor($element: JQuery) { 15 | super($element); 16 | } 17 | 18 | create(): void { 19 | this.setConfig("mobileFooterPanel"); 20 | 21 | super.create(); 22 | 23 | this.$zoomOutButton = $(` 24 | 27 | `); 28 | 29 | this.$zoomInButton = $(` 30 | 33 | `); 34 | 35 | if ((this.extension).isPdfJsEnabled()) { 36 | this.$mainOptions.prepend(this.$zoomOutButton); 37 | this.$mainOptions.prepend(this.$zoomInButton); 38 | } 39 | 40 | this.$zoomInButton.onPressed(() => { 41 | this.extensionHost.publish(PDFExtensionEvents.ZOOM_IN); 42 | }); 43 | 44 | this.$zoomOutButton.onPressed(() => { 45 | this.extensionHost.publish(PDFExtensionEvents.ZOOM_OUT); 46 | }); 47 | } 48 | 49 | resize(): void { 50 | super.resize(); 51 | 52 | this.$options.css( 53 | "left", 54 | Math.floor(this.$element.width() / 2 - this.$options.width() / 2) 55 | ); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-pdfmobilefooterpanel-module/css/styles.less: -------------------------------------------------------------------------------- 1 | .@{icon-prefix}-zoom-in { 2 | .icon-btn-2(data-uri("../img/zoom_in.png")); 3 | } 4 | 5 | .@{icon-prefix}-zoom-out { 6 | .icon-btn-2(data-uri("../img/zoom_out.png")); 7 | } 8 | 9 | .left-options { 10 | min-width: 30px; 11 | } 12 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-pdfmobilefooterpanel-module/img/zoom_in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-pdfmobilefooterpanel-module/img/zoom_in.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-pdfmobilefooterpanel-module/img/zoom_out.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-pdfmobilefooterpanel-module/img/zoom_out.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-resourcesleftpanel-module/ThumbsView.ts: -------------------------------------------------------------------------------- 1 | import { ThumbsView as BaseView } from "../uv-shared-module/ThumbsView"; 2 | import { ExtendedLeftPanel } from "../../extensions/config/ExtendedLeftPanel"; 3 | 4 | export class ThumbsView extends BaseView { 5 | create(): void { 6 | this.setConfig("resourcesLeftPanel"); 7 | super.create(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-resourcesleftpanel-module/css/styles.less: -------------------------------------------------------------------------------- 1 | @import "../../uv-shared-module/css/thumbs-view.less"; 2 | 3 | .uv { 4 | .leftPanel { 5 | .top { 6 | .title { 7 | text-transform: uppercase; 8 | } 9 | } 10 | 11 | ul { 12 | margin: @margin-medium; 13 | padding: 0; 14 | list-style-type: none; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-searchfooterpanel-module/img/next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-searchfooterpanel-module/img/next.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-searchfooterpanel-module/img/placemarker_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-searchfooterpanel-module/img/placemarker_down.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-searchfooterpanel-module/img/placemarker_down_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-searchfooterpanel-module/img/placemarker_down_hover.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-searchfooterpanel-module/img/placemarker_up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-searchfooterpanel-module/img/placemarker_up.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-searchfooterpanel-module/img/prev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-searchfooterpanel-module/img/prev.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-searchfooterpanel-module/img/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-searchfooterpanel-module/img/search.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-searchfooterpanel-module/img/spinner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-searchfooterpanel-module/img/spinner.gif -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/AnnotationResults.ts: -------------------------------------------------------------------------------- 1 | import { AnnotationGroup } from "@iiif/manifold"; 2 | 3 | export class AnnotationResults { 4 | terms?: string; 5 | annotations: AnnotationGroup[]; 6 | } 7 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/BaseView.ts: -------------------------------------------------------------------------------- 1 | const $ = require("jquery"); 2 | import { Panel } from "./Panel"; 3 | import { IExtension } from "./IExtension"; 4 | import { IIIFExtensionHost } from "../../IIIFExtensionHost"; 5 | import { ModuleConfig } from "../../BaseConfig"; 6 | 7 | export class BaseView extends Panel { 8 | config: T; 9 | content: T["content"]; 10 | extension: IExtension; 11 | modules: string[]; 12 | options: T["options"]; 13 | 14 | constructor( 15 | $element: JQuery, 16 | fitToParentWidth?: boolean, 17 | fitToParentHeight?: boolean 18 | ) { 19 | super($element, fitToParentWidth, fitToParentHeight); 20 | } 21 | 22 | create(): void { 23 | this.extensionHost = this.$element 24 | .closest(".uv-iiif-extension-host") 25 | .data("component"); 26 | 27 | // console.log("extensionHost", this.extensionHost); 28 | 29 | super.create(); 30 | 31 | this.extension = ( 32 | (this.extensionHost).extension 33 | ); 34 | 35 | this.config = {} as T; 36 | this.config.content = {} as T["content"]; 37 | this.config.options = {} as T["options"]; 38 | 39 | var that = this; 40 | 41 | // build config inheritance chain 42 | if (that.modules && that.modules.length) { 43 | that.modules = that.modules.reverse(); 44 | that.modules.forEach((moduleName: string) => { 45 | that.config = $.extend( 46 | true, 47 | that.config, 48 | that.extension.data.config!.modules[moduleName] 49 | ); 50 | }); 51 | } 52 | 53 | this.content = this.config.content; 54 | this.options = this.config.options; 55 | } 56 | 57 | init(): void {} 58 | 59 | setConfig(moduleName: string): void { 60 | if (!this.modules) { 61 | this.modules = []; 62 | } 63 | this.modules.push(moduleName); 64 | } 65 | 66 | resize(): void { 67 | super.resize(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/Bookmark.ts: -------------------------------------------------------------------------------- 1 | export class Bookmark { 2 | public path: string; 3 | public index: number; 4 | public label: string | null; 5 | public thumb: string; 6 | public title: string | null; 7 | public trackingLabel: string; 8 | public type: string; 9 | 10 | constructor() {} 11 | } 12 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/DownloadOption.ts: -------------------------------------------------------------------------------- 1 | export enum DownloadOption { 2 | CANVAS_RENDERINGS = "canvasRenderings", 3 | CURRENT_VIEW = "currentView", 4 | ENTIRE_DOCUMENT_AS_PDF = "entireDocumentAsPdf", 5 | ENTIRE_DOCUMENT_AS_TEXT = "entireDocumentAsText", 6 | ENTIRE_FILE_AS_ORIGINAL = "entireFileAsOriginal", 7 | IMAGE_RENDERINGS = "imageRenderings", 8 | MANIFEST_RENDERINGS = "manifestRenderings", 9 | RANGE_RENDERINGS = "rangeRenderings", 10 | SELECTION = "selection", 11 | //SEQUENCE_RENDERINGS = "sequenceRenderings", 12 | UNKNOWN = "unknown", 13 | WHOLE_IMAGE_HIGH_RES = "wholeImageHighRes", 14 | WHOLE_IMAGE_LOW_RES = "wholeImageLowRes", 15 | WHOLE_IMAGES_HIGH_RES = "wholeImagesHighRes", 16 | } 17 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/ExtensionState.ts: -------------------------------------------------------------------------------- 1 | export interface ExtensionState { 2 | downloadDialogueOpen: boolean; 3 | dialogueTriggerButton: HTMLElement | null; 4 | openDownloadDialogue: (triggerButton: HTMLElement) => void; 5 | closeDialogue: () => void; 6 | } 7 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/GenericDialogue.ts: -------------------------------------------------------------------------------- 1 | const $ = require("jquery"); 2 | import { BaseConfig } from "../../BaseConfig"; 3 | import { IIIFEvents } from "../../IIIFEvents"; 4 | import { Dialogue } from "./Dialogue"; 5 | 6 | export class GenericDialogue extends Dialogue< 7 | BaseConfig["modules"]["genericDialogue"] 8 | > { 9 | acceptCallback: any; 10 | $acceptButton: JQuery; 11 | $message: JQuery; 12 | 13 | constructor($element: JQuery) { 14 | super($element); 15 | } 16 | 17 | create(): void { 18 | this.setConfig("genericDialogue"); 19 | 20 | super.create(); 21 | 22 | this.openCommand = IIIFEvents.SHOW_GENERIC_DIALOGUE; 23 | this.closeCommand = IIIFEvents.HIDE_GENERIC_DIALOGUE; 24 | 25 | this.extensionHost.subscribe(this.openCommand, (params: any) => { 26 | this.acceptCallback = params.acceptCallback; 27 | this.showMessage(params); 28 | }); 29 | 30 | this.extensionHost.subscribe(this.closeCommand, () => { 31 | this.close(); 32 | }); 33 | 34 | this.$message = $("

"); 35 | this.$content.append(this.$message); 36 | 37 | this.$acceptButton = $(` 38 | 41 | `); 42 | this.$buttons.append(this.$acceptButton); 43 | // Hide the redundant close button 44 | this.$buttons.find(".close").hide(); 45 | 46 | this.$acceptButton.onPressed(() => { 47 | this.accept(); 48 | }); 49 | 50 | this.returnFunc = () => { 51 | if (this.isActive) { 52 | this.accept(); 53 | } 54 | }; 55 | 56 | this.$element.hide(); 57 | } 58 | 59 | accept(): void { 60 | this.extensionHost.publish(IIIFEvents.CLOSE_ACTIVE_DIALOGUE); 61 | if (this.acceptCallback) this.acceptCallback(); 62 | } 63 | 64 | showMessage(params: any): void { 65 | this.$message.html(params.message); 66 | 67 | if (params.buttonText) { 68 | this.$acceptButton.text(params.buttonText); 69 | } else { 70 | this.$acceptButton.text(this.content.ok); 71 | } 72 | 73 | if (params.allowClose === false) { 74 | this.disableClose(); 75 | } 76 | 77 | this.open(); 78 | } 79 | 80 | resize(): void { 81 | super.resize(); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/IDependencies.ts: -------------------------------------------------------------------------------- 1 | export interface IDependencies { 2 | async: string[]; 3 | sync: string[]; 4 | } 5 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/ILocale.ts: -------------------------------------------------------------------------------- 1 | export interface ILocale { 2 | name: string; 3 | label?: string; 4 | } 5 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/ILoginDialogueOptions.ts: -------------------------------------------------------------------------------- 1 | export interface ILoginDialogueOptions { 2 | showCancelButton: boolean; 3 | warningMessage: string; 4 | topCloseButtonEnabled: boolean; 5 | } 6 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/IRenderingOption.ts: -------------------------------------------------------------------------------- 1 | import { DownloadOption } from "./DownloadOption"; 2 | 3 | export interface IRenderingOption { 4 | type: DownloadOption; 5 | button: JQuery; 6 | } 7 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/ISharePreview.ts: -------------------------------------------------------------------------------- 1 | export interface ISharePreview { 2 | title: string | null; 3 | image: string; 4 | } 5 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/Information.ts: -------------------------------------------------------------------------------- 1 | import { InformationAction } from "./InformationAction"; 2 | 3 | export class Information { 4 | constructor( 5 | public message: string, 6 | public actions: InformationAction[] 7 | ) {} 8 | } 9 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/InformationAction.ts: -------------------------------------------------------------------------------- 1 | export class InformationAction { 2 | public label: string | null; 3 | public action: () => void; 4 | 5 | constructor() {} 6 | } 7 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/InformationArgs.ts: -------------------------------------------------------------------------------- 1 | import { InformationType } from "./InformationType"; 2 | 3 | export class InformationArgs { 4 | constructor( 5 | public informationType: InformationType, 6 | public param: any 7 | ) {} 8 | } 9 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/InformationFactory.ts: -------------------------------------------------------------------------------- 1 | import { IIIFEvents } from "../../IIIFEvents"; 2 | import { Information } from "./Information"; 3 | import { InformationAction } from "./InformationAction"; 4 | import { InformationArgs } from "./InformationArgs"; 5 | import { InformationType } from "./InformationType"; 6 | import { IExtension } from "./IExtension"; 7 | import { IExternalResource } from "manifesto.js"; 8 | 9 | export class InformationFactory { 10 | extension: IExtension; 11 | 12 | constructor(extension: IExtension) { 13 | this.extension = extension; 14 | } 15 | 16 | public Get(args: InformationArgs): Information { 17 | switch (args.informationType) { 18 | case InformationType.AUTH_CORS_ERROR: 19 | return new Information( 20 | this.extension.data.config!.content.authCORSError, 21 | [] 22 | ); 23 | case InformationType.DEGRADED_RESOURCE: 24 | const actions: InformationAction[] = []; 25 | const loginAction: InformationAction = new InformationAction(); 26 | 27 | let label: string | null; 28 | 29 | if (args.param.loginService) { 30 | label = args.param.loginService.getConfirmLabel(); 31 | } else { 32 | label = args.param.kioskService.getConfirmLabel(); 33 | } 34 | 35 | if (!label) { 36 | label = 37 | this.extension.data.config!.content.fallbackDegradedLabel || 38 | "login"; 39 | } 40 | 41 | loginAction.label = label; 42 | 43 | const resource: IExternalResource = args.param; 44 | 45 | loginAction.action = () => { 46 | if (args.param.loginService) { 47 | resource.authHoldingPage = window.open("", "_blank"); 48 | } 49 | this.extension.extensionHost.publish(IIIFEvents.HIDE_INFORMATION); 50 | this.extension.extensionHost.publish( 51 | IIIFEvents.OPEN_EXTERNAL_RESOURCE, 52 | [[resource]] 53 | ); 54 | }; 55 | 56 | actions.push(loginAction); 57 | 58 | let message: string | null; 59 | 60 | if (args.param.loginService) { 61 | message = args.param.loginService.getServiceLabel(); 62 | } else { 63 | message = args.param.kioskService.getServiceLabel(); 64 | } 65 | 66 | if (!message) { 67 | message = this.extension.data.config!.content.fallbackDegradedMessage; 68 | } 69 | 70 | return new Information(message, actions); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/InformationType.ts: -------------------------------------------------------------------------------- 1 | export enum InformationType { 2 | AUTH_CORS_ERROR, 3 | DEGRADED_RESOURCE, 4 | } 5 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/LoginWarningMessages.ts: -------------------------------------------------------------------------------- 1 | export class LoginWarningMessages { 2 | static FORBIDDEN: string = "forbiddenResourceMessage"; 3 | } 4 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/Panel.ts: -------------------------------------------------------------------------------- 1 | import { IIIFExtensionHost } from "../../IIIFExtensionHost"; 2 | import { Async } from "@edsilv/utils"; 3 | import { Events } from "../../../../Events"; 4 | 5 | export class Panel { 6 | extensionHost: IIIFExtensionHost; 7 | $element: JQuery; 8 | fitToParentWidth: boolean; 9 | fitToParentHeight: boolean; 10 | isResized: boolean = false; 11 | 12 | constructor( 13 | $element: JQuery, 14 | fitToParentWidth?: boolean, 15 | fitToParentHeight?: boolean 16 | ) { 17 | this.$element = $element; 18 | this.fitToParentWidth = fitToParentWidth || false; 19 | this.fitToParentHeight = fitToParentHeight || false; 20 | 21 | this.create(); 22 | } 23 | 24 | create(): void { 25 | this.extensionHost?.subscribe(Events.RESIZE, () => { 26 | this.resize(); 27 | }); 28 | } 29 | 30 | whenResized(cb: () => void): void { 31 | Async.waitFor(() => { 32 | return this.isResized; 33 | }, cb); 34 | } 35 | 36 | onAccessibleClick( 37 | el: JQuery, 38 | callback: (e: JQueryEventObject) => void, 39 | withClick = true, 40 | treatAsButton = false 41 | ) { 42 | if (withClick) { 43 | el.on("click", (e) => { 44 | callback(e); 45 | }); 46 | } 47 | 48 | el.on("keydown", (e) => { 49 | // by passing treatAsButton as true this will become false 50 | // and so an anchor won't be excluded from Space presses 51 | const isAnchor = e.target.nodeName === "A" && !treatAsButton; 52 | 53 | // 13 = Enter, 32 = Space 54 | if ((e.which === 32 && !isAnchor) || e.which === 13) { 55 | // stops space scrolling the page 56 | e.preventDefault(); 57 | callback(e); 58 | } 59 | }); 60 | } 61 | 62 | resize(): void { 63 | const $parent: JQuery = this.$element.parent(); 64 | 65 | if (this.fitToParentWidth) { 66 | this.$element.width($parent.width()); 67 | } 68 | 69 | if (this.fitToParentHeight) { 70 | this.$element.height($parent.height()); 71 | } 72 | 73 | this.isResized = true; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/Point.ts: -------------------------------------------------------------------------------- 1 | export class Point { 2 | public x: number; 3 | public y: number; 4 | 5 | constructor(x: number, y: number) { 6 | this.x = x; 7 | this.y = y; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/Position.ts: -------------------------------------------------------------------------------- 1 | export enum Position { 2 | TOP_LEFT, 3 | TOP_CENTER, 4 | TOP_RIGHT, 5 | CENTER_LEFT, 6 | CENTER, 7 | CENTER_RIGHT, 8 | BOTTOM_LEFT, 9 | BOTTOM_CENTER, 10 | BOTTOM_RIGHT, 11 | } 12 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/StringValue.ts: -------------------------------------------------------------------------------- 1 | export class StringValue { 2 | public value: string = ""; 3 | 4 | constructor(value?: string) { 5 | if (value) { 6 | this.value = value.toLowerCase(); 7 | } 8 | } 9 | 10 | toString() { 11 | return this.value; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/TFragment.ts: -------------------------------------------------------------------------------- 1 | export class TFragment { 2 | public t: number | [number, number]; 3 | 4 | constructor(t: number | [number, number]) { 5 | this.t = t; 6 | } 7 | 8 | toString(): string { 9 | return `${this.t}`; 10 | } 11 | 12 | static fromString(time: string): TFragment { 13 | time = time.replace("t=", ""); 14 | if (time.includes(",")) { 15 | const [start, end] = time.split(","); 16 | return new TFragment([Number(start), Number(end)]); 17 | } 18 | return new TFragment(Number(time)); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/XYWHFragment.spec.ts: -------------------------------------------------------------------------------- 1 | import { XYWHFragment } from "./XYWHFragment"; 2 | 3 | describe("XYWH", () => { 4 | const xywh = new XYWHFragment(0, 5, 100, 95); 5 | 6 | it("has accessors available", () => { 7 | expect(xywh.x).toEqual(0); 8 | expect(xywh.y).toEqual(5); 9 | expect(xywh.w).toEqual(100); 10 | expect(xywh.h).toEqual(95); 11 | }); 12 | 13 | describe("toString", () => { 14 | it("is in format x,y,w,h", () => { 15 | expect(xywh.toString()).toEqual("0,5,100,95"); 16 | }); 17 | }); 18 | 19 | describe("fromString", () => { 20 | it("creates with arguments in correct order", () => { 21 | expect(XYWHFragment.fromString(xywh.toString()).toString()).toEqual( 22 | xywh.toString() 23 | ); 24 | }); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/XYWHFragment.ts: -------------------------------------------------------------------------------- 1 | export class XYWHFragment { 2 | public x: number; 3 | public y: number; 4 | public w: number; 5 | public h: number; 6 | 7 | constructor(x: number, y: number, w: number, h: number) { 8 | this.x = x; 9 | this.y = y; 10 | this.w = w; 11 | this.h = h; 12 | } 13 | 14 | toString(): string { 15 | return `${this.x},${this.y},${this.w},${this.h}`; 16 | } 17 | 18 | static fromString(bounds: string): XYWHFragment { 19 | bounds = bounds.replace("xywh=", ""); 20 | const boundsArr: string[] = bounds.split(","); 21 | return new XYWHFragment( 22 | Number(boundsArr[0]), 23 | Number(boundsArr[1]), 24 | Number(boundsArr[2]), 25 | Number(boundsArr[3]) 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/css/catch-all.less: -------------------------------------------------------------------------------- 1 | .uv { 2 | .headerPanel { 3 | .hidden(); 4 | } 5 | 6 | .footerPanel { 7 | .hidden(); 8 | } 9 | 10 | .mobileFooterPanel { 11 | .visible(); 12 | position: relative; 13 | height: 42px; 14 | 15 | .options { 16 | position: absolute; 17 | /*width: 315px;*/ 18 | height: 42px; 19 | 20 | display: flex; 21 | flex-direction: row; 22 | justify-content: space-between; 23 | align-items: center; 24 | width: 100%; 25 | 26 | .spacer { 27 | float: left; 28 | width: 30px; 29 | height: 41px; 30 | } 31 | 32 | .btn { 33 | margin-right: @margin-small-horizontal; 34 | 35 | color: white; 36 | font-size: 0; 37 | 38 | &.moreInfo { 39 | display: inline-block; 40 | } 41 | 42 | &.toggleLeftPanelButton { 43 | display: inline-block; 44 | } 45 | 46 | &.bookmark { 47 | display: none; 48 | } 49 | 50 | &.open { 51 | display: none; 52 | } 53 | 54 | &.feedback { 55 | display: none; 56 | } 57 | 58 | &.embed { 59 | display: none; 60 | } 61 | 62 | &.fullScreen { 63 | display: inline-block; 64 | } 65 | } 66 | } 67 | } 68 | } 69 | 70 | .uv.loaded .uv-iiif-extension-host { 71 | background-color: #000; 72 | } 73 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/css/footer-panel.less: -------------------------------------------------------------------------------- 1 | .uv { 2 | .footerPanel { 3 | .searchOptions { 4 | width: 425px; 5 | } 6 | 7 | .options { 8 | height: 42px; 9 | 10 | .left-options { 11 | min-width: 30px; 12 | } 13 | 14 | .btn { 15 | color: white; 16 | font-size: auto; 17 | 18 | &.moreInfo { 19 | display: none; 20 | } 21 | 22 | &.toggleLeftPanelButton { 23 | display: none; 24 | } 25 | 26 | &.fullScreen, 27 | &.exitFullscreen { 28 | float: right; 29 | } 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/css/header-panel.less: -------------------------------------------------------------------------------- 1 | .uv { 2 | .headerPanel { 3 | color: @text-secondary-color; 4 | 5 | button.imageBtn { 6 | float: left; 7 | i { 8 | height: 30px; 9 | width: 30px; 10 | } 11 | } 12 | 13 | &.showInformation { 14 | height: 80px; 15 | } 16 | 17 | .options { 18 | height: 40px; 19 | background-color: @panel-dark-bg; 20 | 21 | .centerOptions { 22 | position: absolute; 23 | } 24 | 25 | .rightOptions { 26 | float: right; 27 | 28 | // .help { 29 | // margin-left: 1em; 30 | // padding-right: 22px; 31 | // padding-bottom: 2px; 32 | // background: data-uri('@{img-path}sprite.png'); 33 | // background-repeat: no-repeat; 34 | // background-position: 0 -2999px; 35 | // margin-top: 6px; 36 | // } 37 | 38 | .settings { 39 | margin-right: 8px; 40 | } 41 | } 42 | } 43 | 44 | .informationBox { 45 | background: @brand-warning; 46 | color: @gray-dark; 47 | width: 100%; 48 | position: absolute; 49 | height: 40px; 50 | 51 | .message { 52 | float: left; 53 | margin: 13px; 54 | white-space: nowrap; 55 | overflow: hidden; 56 | text-overflow: ellipsis; 57 | } 58 | 59 | .actions { 60 | float: left; 61 | margin: 6px 0 0 0; 62 | 63 | .btn { 64 | margin: 0 6px 0 0; 65 | } 66 | } 67 | 68 | .close { 69 | background: 0 0; 70 | border: 0; 71 | color: @gray-dark; 72 | font-size: 1.5rem; 73 | cursor: pointer; 74 | margin-right: 6px; 75 | &:focus, 76 | &:hover { 77 | color: @gray-darker; 78 | } 79 | } 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/css/icons.less: -------------------------------------------------------------------------------- 1 | // Consolidated Icon Styles for UV 2 | // Icons that are images should be a size of 30px x 30px 3 | .uv { 4 | .@{icon-prefix}, 5 | i { 6 | display: inline-block; 7 | } 8 | 9 | .av-icon, 10 | .@{icon-prefix} { 11 | opacity: 0.8; 12 | transition: opacity 0.4s; 13 | &:hover { 14 | opacity: 1; 15 | } 16 | .btn:focus & { 17 | opacity: 1; 18 | } 19 | } 20 | } 21 | 22 | .@{icon-prefix}-more-info { 23 | .icon-btn-2(data-uri("../img/moreinfo.png")); 24 | } 25 | 26 | .@{icon-prefix}-toggle-left-panel { 27 | .icon-btn-2(data-uri("../img/toggle-left-panel.svg")); 28 | } 29 | 30 | .@{icon-prefix}-open { 31 | .icon-btn-2(data-uri("../img/moreinfo.png")); 32 | } 33 | 34 | .@{icon-prefix}-share { 35 | .icon-btn-2(data-uri("../img/share.png")); 36 | } 37 | 38 | .@{icon-prefix}-embed { 39 | .icon-btn-2(data-uri("../img/embed.png")); 40 | } 41 | 42 | .@{icon-prefix}-download { 43 | .icon-btn-2(data-uri("../img/download.png")); 44 | } 45 | 46 | .@{icon-prefix}-bookmark { 47 | .icon-btn-2(data-uri("../img/bookmark.png")); 48 | } 49 | 50 | .@{icon-prefix}-feedback { 51 | .icon-btn-2(data-uri("../img/feedback.png")); 52 | } 53 | 54 | .@{icon-prefix}-print { 55 | .icon-btn-2(data-uri("../img/print.png")); 56 | } 57 | 58 | .@{icon-prefix}-help { 59 | .icon-btn-2(data-uri("../img/help.png")); 60 | margin-left: -15px; 61 | } 62 | 63 | .@{icon-prefix}-fullscreen { 64 | .icon-btn-2(data-uri("../img/fullscreen.png")); 65 | } 66 | 67 | .@{icon-prefix}-exit-fullscreen { 68 | .icon-btn-2(data-uri("../img/exit_fullscreen.png")); 69 | } 70 | 71 | .@{icon-prefix}-settings { 72 | .icon-btn-2(data-uri("../img/settings.png")); 73 | } 74 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/css/left-panel.less: -------------------------------------------------------------------------------- 1 | .uv { 2 | @expandFullEnabled: false; 3 | 4 | .leftPanel { 5 | z-index: 10; 6 | 7 | a { 8 | color: @text-color; 9 | text-decoration: none; 10 | } 11 | 12 | .top { 13 | height: 35px; 14 | position: relative; 15 | 16 | .title { 17 | height: 20px; 18 | margin: 9px 0 0 10px; 19 | font-size: inherit; 20 | font-weight: normal; 21 | float: left; 22 | cursor: pointer; 23 | letter-spacing: 0.08rem; 24 | } 25 | 26 | .collapseButton { 27 | float: right; 28 | background: data-uri("../img/arrows_left.png"); 29 | background-repeat: no-repeat; 30 | width: 20px; 31 | height: 20px; 32 | cursor: pointer; 33 | margin: 7px 5px 0 0; 34 | display: block; 35 | } 36 | 37 | .expandFullButton { 38 | float: right; 39 | background: data-uri("../img/arrows_right.png"); 40 | background-repeat: no-repeat; 41 | width: 20px; 42 | height: 20px; 43 | cursor: pointer; 44 | margin: 7px 5px 0 0; 45 | display: none; 46 | } 47 | 48 | .expandFull(); 49 | } 50 | 51 | .closed { 52 | width: 25px; 53 | float: right; 54 | 55 | .title { 56 | .link-color-decoration(@text-color, none); 57 | white-space: nowrap; 58 | display: block; 59 | margin: 8px 8px 0 0px; 60 | cursor: pointer; 61 | text-transform: uppercase; 62 | .rotate(90deg); 63 | letter-spacing: 0.08rem; 64 | } 65 | 66 | .expandButton { 67 | background: data-uri("../img/arrows_right.png"); 68 | background-repeat: no-repeat; 69 | width: 20px; 70 | height: 20px; 71 | cursor: pointer; 72 | margin: 7px 5px 0 0; 73 | display: block; 74 | } 75 | } 76 | } 77 | 78 | .expandFull() when (@expandFullEnabled = true) { 79 | .expandFullButton { 80 | display: block; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/css/lg.less: -------------------------------------------------------------------------------- 1 | .uv { 2 | #debug { 3 | #lg { 4 | .lg-mediaquery({ 5 | display: block !important; 6 | }); 7 | } 8 | } 9 | 10 | .lg-mediaquery({ 11 | .headerPanel { 12 | display: block; 13 | visibility: visible; 14 | } 15 | 16 | .mainPanel { 17 | .leftPanel { 18 | display: block; 19 | visibility: visible; 20 | } 21 | 22 | .rightPanel { 23 | display: block; 24 | visibility: visible; 25 | } 26 | } 27 | 28 | .footerPanel { 29 | display: block; 30 | visibility: visible; 31 | } 32 | 33 | .mobileFooterPanel { 34 | display: none; 35 | visibility: hidden; 36 | } 37 | }); 38 | } 39 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/css/md.less: -------------------------------------------------------------------------------- 1 | .uv { 2 | #debug { 3 | #md { 4 | .md-mediaquery({ 5 | display: block !important; 6 | visibility: visible !important; 7 | }); 8 | } 9 | } 10 | 11 | .md-mediaquery({ 12 | .headerPanel { 13 | display: block; 14 | visibility: visible; 15 | } 16 | 17 | .mainPanel { 18 | .leftPanel { 19 | display: block; 20 | visibility: visible; 21 | } 22 | 23 | .rightPanel { 24 | display: block; 25 | visibility: visible; 26 | } 27 | } 28 | 29 | .footerPanel { 30 | display: block; 31 | visibility: visible; 32 | } 33 | 34 | .mobileFooterPanel { 35 | display: none; 36 | visibility: hidden; 37 | } 38 | }); 39 | } 40 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/css/sm.less: -------------------------------------------------------------------------------- 1 | .uv { 2 | #debug { 3 | #sm { 4 | .sm-mediaquery({ 5 | display: block !important; 6 | visibility: visible !important; 7 | }); 8 | } 9 | } 10 | 11 | .sm-mediaquery({ 12 | .headerPanel { 13 | display: none; 14 | visibility: hidden; 15 | } 16 | 17 | .footerPanel { 18 | display: none; 19 | visibility: hidden; 20 | } 21 | 22 | .mobileFooterPanel { 23 | display: block; 24 | visibility: visible; 25 | } 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/css/xl.less: -------------------------------------------------------------------------------- 1 | .uv { 2 | #debug { 3 | #xl { 4 | .xl-mediaquery({ 5 | display: block !important; 6 | visibility: visible !important; 7 | }); 8 | } 9 | } 10 | 11 | .xl-mediaquery({ 12 | .headerPanel { 13 | display: block; 14 | visibility: visible; 15 | } 16 | 17 | .mainPanel { 18 | .leftPanel { 19 | display: block; 20 | visibility: visible; 21 | } 22 | 23 | .rightPanel { 24 | display: block; 25 | visibility: visible; 26 | } 27 | } 28 | 29 | .footerPanel { 30 | display: block; 31 | visibility: visible; 32 | } 33 | 34 | .mobileFooterPanel { 35 | display: none; 36 | visibility: hidden; 37 | } 38 | }); 39 | } 40 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/arrows_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/arrows_left.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/arrows_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/arrows_right.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/audio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/audio.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/bookmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/bookmark.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/close.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/close_message_box.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/close_message_box.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/collapse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/collapse.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/copy.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/dialogue_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/dialogue_arrow.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/download.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/embed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/embed.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/error.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/exit_fullscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/exit_fullscreen.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/expand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/expand.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/fast-forward.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 20 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/fast-rewind.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 20 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/feedback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/feedback.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/fullscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/fullscreen.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/help.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/hidden_thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/hidden_thumb.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/iiif-black.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/iiif-black.webp -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/iiif-gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/iiif-gray.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/minus.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/modal_bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/modal_bg.gif -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/moreinfo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/moreinfo.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/next.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/open.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/pause.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/play.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/plus.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/previous.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/previous.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/print.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/print.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/search_result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/search_result.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/settings.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/share.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/sprite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/sprite.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/toggle-left-panel.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/unavailable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/unavailable.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/video.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/video.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/volume-off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/volume-off.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/modules/uv-shared-module/img/volume-on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/content-handlers/iiif/modules/uv-shared-module/img/volume-on.png -------------------------------------------------------------------------------- /src/content-handlers/iiif/themes/cy-gb/footer-panel.less: -------------------------------------------------------------------------------- 1 | .uv-iiif-extension-host.cy-gb { 2 | .footerPanel { 3 | .searchPager { 4 | .controls { 5 | .searchResultsInfo { 6 | width: 290px; 7 | } 8 | } 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/themes/cy-gb/header-panel.less: -------------------------------------------------------------------------------- 1 | .uv-iiif-extension-host.cy-gb { 2 | .headerPanel { 3 | .options { 4 | .centerOptions { 5 | width: 432px; 6 | 7 | .prevOptions { 8 | margin: 0 10px 0 0; 9 | } 10 | 11 | .nextOptions { 12 | margin: 0 0 0 10px; 13 | } 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/themes/cy-gb/theme.less: -------------------------------------------------------------------------------- 1 | @import "header-panel"; 2 | @import "footer-panel"; 3 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/themes/en-gb/footer-panel.less: -------------------------------------------------------------------------------- 1 | .uv-iiif-extension-host.en-gb { 2 | .footerPanel { 3 | .searchPager { 4 | .controls { 5 | .searchResultsInfo { 6 | width: 337px; 7 | } 8 | } 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/themes/en-gb/header-panel.less: -------------------------------------------------------------------------------- 1 | .uv-iiif-extension-host.en-gb { 2 | .headerPanel { 3 | .options { 4 | .centerOptions { 5 | width: 390px; 6 | } 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/themes/en-gb/theme.less: -------------------------------------------------------------------------------- 1 | @import "header-panel"; 2 | @import "footer-panel"; 3 | -------------------------------------------------------------------------------- /src/content-handlers/iiif/themes/theme.less: -------------------------------------------------------------------------------- 1 | @import "./en-gb/theme.less"; 2 | @import "./cy-gb/theme.less"; 3 | -------------------------------------------------------------------------------- /src/content-handlers/youtube/YouTubeData.ts: -------------------------------------------------------------------------------- 1 | export interface YouTubeData { 2 | autoPlay?: boolean; 3 | currentTime?: number; 4 | muted?: boolean; 5 | duration?: [number, number]; 6 | youTubeVideoId?: string; 7 | } 8 | -------------------------------------------------------------------------------- /src/content-handlers/youtube/YouTubeEvents.ts: -------------------------------------------------------------------------------- 1 | export class YouTubeEvents { 2 | static UNSTARTED: string = "unstarted"; 3 | static ENDED: string = "ended"; 4 | static PLAYING: string = "playing"; 5 | static PAUSED: string = "paused"; 6 | static BUFFERING: string = "buffering"; 7 | static CUED: string = "cued"; 8 | } 9 | -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UniversalViewer/universalviewer/e7114727a06df9f7c84d86865f766f38883bcfca/src/favicon.ico -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import "./shim-jquery"; 2 | export { ContentType } from "./ContentType"; 3 | export { 4 | URLAdapter as IIIFURLAdapter, 5 | URLAdapter as IIIFURLAdaptor, 6 | } from "./content-handlers/iiif/URLAdapter"; 7 | export { UniversalViewer as Viewer } from "./UniversalViewer"; 8 | export { Events } from "./Events"; 9 | export { IIIFEvents } from "./content-handlers/iiif/IIIFEvents"; 10 | export { YouTubeEvents } from "./content-handlers/youtube/YouTubeEvents"; 11 | export { init } from "./Init"; 12 | -------------------------------------------------------------------------------- /src/netlify.toml: -------------------------------------------------------------------------------- 1 | [[headers]] 2 | for = "/*" 3 | [headers.values] 4 | Access-Control-Allow-Origin = "*" 5 | 6 | [build] 7 | base = "" 8 | publish = "dist" 9 | command = "CI= npm run build" 10 | 11 | [build.environment] 12 | SHOW_NETLIFY_BADGE = "true" 13 | NODE_VERSION = "14" -------------------------------------------------------------------------------- /src/shim-jquery.ts: -------------------------------------------------------------------------------- 1 | import $ from "jquery"; 2 | window.$ = $; 3 | window.jQuery = $; 4 | -------------------------------------------------------------------------------- /src/uv-iiif-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "options": { 3 | "dropEnabled": true, 4 | "footerPanelEnabled": true, 5 | "headerPanelEnabled": true, 6 | "leftPanelEnabled": true, 7 | "limitLocales": false, 8 | "overrideFullScreen": false, 9 | "pagingEnabled": true, 10 | "preferMediaElementExtension": false, 11 | "rightPanelEnabled": true, 12 | "clickToZoomEnabled": false, 13 | "saveUserSettings": true, 14 | "animationDuration": 250 15 | }, 16 | "modules": { 17 | "avCenterPanel": { 18 | "options": { 19 | "mostSpecificRequiredStatement": true 20 | } 21 | }, 22 | "downloadDialogue": { 23 | "options": { 24 | "selectionEnabled": true 25 | } 26 | }, 27 | "headerPanel": { 28 | "options": { 29 | "localeToggleEnabled": false 30 | } 31 | }, 32 | "pagingHeaderPanel": { 33 | "options": { 34 | "pagingToggleEnabled": true 35 | } 36 | }, 37 | "openSeadragonCenterPanel": { 38 | "options": { 39 | "autoHideControls": false, 40 | "showHomeControl": false, 41 | "showAdjustImageControl": true 42 | } 43 | }, 44 | "mediaElementCenterPanel": { 45 | "options": { 46 | "autoPlayOnSetTarget": false 47 | } 48 | }, 49 | "footerPanel": { 50 | "options": { 51 | "downloadEnabled": true 52 | } 53 | }, 54 | "shareDialogue": { 55 | "options": { 56 | "embedPath": "/uv.html", 57 | "embedHost": null, 58 | "embedPort": null, 59 | "embedTemplate": "" 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/uv-youtube-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "controls": true 3 | } 4 | -------------------------------------------------------------------------------- /src/uv.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 22 | 23 | 24 |
25 | 26 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /src/vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "builds": [ 3 | { 4 | "src": "package.json", 5 | "use": "@vercel/static-build", 6 | "config": { "distDir": "dist" } 7 | } 8 | ], 9 | "headers": [ 10 | { 11 | "source": "/api/(.*)", 12 | "headers": [ 13 | { "key": "Access-Control-Allow-Credentials", "value": "true" }, 14 | { "key": "Access-Control-Allow-Origin", "value": "*" }, 15 | { 16 | "key": "Access-Control-Allow-Methods", 17 | "value": "GET,OPTIONS,PATCH,DELETE,POST,PUT" 18 | }, 19 | { 20 | "key": "Access-Control-Allow-Headers", 21 | "value": "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version" 22 | } 23 | ] 24 | }, 25 | { 26 | "source": "/(.*)", 27 | "headers": [ 28 | { 29 | "key": "Cache-Control", 30 | "value": "public, max-age=86400" 31 | } 32 | ] 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /src/youtube-collection.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "https://www.youtube.com/watch?v=Tax-S8PpJf4", 4 | "label": "Bacchus - God of Wine" 5 | }, 6 | { 7 | "id": "https://www.youtube.com/watch?v=Bz3CM38zHho", 8 | "label": "Bacchus Uncovered: Ancient God of Ecstasy" 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "jsx": "react", 4 | "baseUrl": ".", 5 | "paths": { 6 | "@/*": ["src/*"] 7 | }, 8 | "allowSyntheticDefaultImports": true, 9 | "incremental": true, 10 | "lib": ["ES2015", "DOM"], 11 | "module": "ESNext", 12 | "moduleResolution": "node", 13 | "noImplicitAny": false, 14 | "noImplicitReturns": true, 15 | "noImplicitThis": false, 16 | "noLib": false, 17 | "noUnusedLocals": true, 18 | "noUnusedParameters": false, 19 | "removeComments": false, 20 | "resolveJsonModule": true, 21 | "sourceMap": true, 22 | "strictNullChecks": true, 23 | "esModuleInterop": true, 24 | "target": "ES5", 25 | "tsBuildInfoFile": "./buildcache/front-end", 26 | "types": ["@iiif/base-component", "jest", "jquery", "node"], 27 | "skipLibCheck": true 28 | }, 29 | "exclude": ["node_modules", "src/**/*.test.ts", "src/**/*.spec.ts"], 30 | "include": ["src"] 31 | } 32 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["tslint:recommended", "tslint-config-prettier"], 3 | "rules": { 4 | "class-name": true, 5 | "comment-format": [true, "check-space"], 6 | "curly": true, 7 | "forin": true, 8 | "interface-name": [true, "never-prefix"], 9 | "jsdoc-format": true, 10 | "label-position": true, 11 | "member-ordering": [true], 12 | "no-any": true, 13 | "no-arg": true, 14 | "no-bitwise": true, 15 | "no-console": [true, "log", "error", "debug", "info", "time", "timeEnd", "trace"], 16 | "no-construct": true, 17 | "no-debugger": true, 18 | "no-duplicate-variable": true, 19 | "no-empty": true, 20 | "no-eval": true, 21 | "no-shadowed-variable": true, 22 | "no-string-literal": true, 23 | "no-switch-case-fall-through": true, 24 | "no-trailing-whitespace": false, 25 | "no-unused-expression": true, 26 | "no-use-before-declare": true, 27 | "object-literal-sort-keys": false, 28 | "radix": true, 29 | "switch-default": true, 30 | "triple-equals": [true, "allow-null-check"], 31 | "typedef": [true, "parameter", "property-declaration"], 32 | "variable-name": [ 33 | true, 34 | "ban-keywords", 35 | "check-format", 36 | "allow-leading-underscore", 37 | "allow-pascal-case" 38 | ] 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "entryPoints": ["src/content-handlers/iiif/Docs.ts"], 3 | "sourceLinkTemplate": "https://github.com/UniversalViewer/universalviewer/blob/dev/{path}#L{line}", 4 | "out": "docs" 5 | } 6 | --------------------------------------------------------------------------------