Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions assets/icons/arrow-left.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions assets/icons/arrow-right.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions assets/icons/arrows-fullscreen.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions assets/icons/house.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions assets/icons/zoom-in.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions assets/icons/zoom-out.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
32 changes: 31 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,12 @@
"license": "MIT",
"dependencies": {
"@geomatico/maplibre-cog-protocol": "^0.5.0",
"@iiif/presentation-2": "^1.0.4",
"@iiif/presentation-3": "^2.2.3",
"@shoelace-style/shoelace": "^2.20.1",
"@terraformer/wkt": "^2.2.1",
"d3-scale": "^4.0.2",
"maplibre-gl": "^5.6.0"
"maplibre-gl": "^5.6.0",
"openseadragon": "^5.0.1"
}
}
36 changes: 36 additions & 0 deletions src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import { EaseToOptions } from "maplibre-gl";
export { OgmRecord } from "./utils/record";
export { EaseToOptions } from "maplibre-gl";
export namespace Components {
interface OgmImage {
"record": OgmRecord;
"theme": 'light' | 'dark';
}
interface OgmMap {
"easeMapTo": (options: EaseToOptions) => Promise<maplibregl.Map>;
"previewOpacity": number;
Expand All @@ -35,10 +39,15 @@ export namespace Components {
"theme": 'light' | 'dark';
}
interface OgmViewer {
"loadRecord": (record: OgmRecord) => Promise<void>;
"recordUrl": string;
"theme": 'light' | 'dark';
}
}
export interface OgmImageCustomEvent<T> extends CustomEvent<T> {
detail: T;
target: HTMLOgmImageElement;
}
export interface OgmMapCustomEvent<T> extends CustomEvent<T> {
detail: T;
target: HTMLOgmMapElement;
Expand All @@ -52,6 +61,24 @@ export interface OgmSettingsCustomEvent<T> extends CustomEvent<T> {
target: HTMLOgmSettingsElement;
}
declare global {
interface HTMLOgmImageElementEventMap {
"imageLoaded": void;
"imageLoading": void;
}
interface HTMLOgmImageElement extends Components.OgmImage, HTMLStencilElement {
addEventListener<K extends keyof HTMLOgmImageElementEventMap>(type: K, listener: (this: HTMLOgmImageElement, ev: OgmImageCustomEvent<HTMLOgmImageElementEventMap[K]>) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener<K extends keyof DocumentEventMap>(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof HTMLOgmImageElementEventMap>(type: K, listener: (this: HTMLOgmImageElement, ev: OgmImageCustomEvent<HTMLOgmImageElementEventMap[K]>) => any, options?: boolean | EventListenerOptions): void;
removeEventListener<K extends keyof DocumentEventMap>(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
var HTMLOgmImageElement: {
prototype: HTMLOgmImageElement;
new (): HTMLOgmImageElement;
};
interface HTMLOgmMapElementEventMap {
"mapIdle": void;
"mapLoading": void;
Expand Down Expand Up @@ -123,6 +150,7 @@ declare global {
new (): HTMLOgmViewerElement;
};
interface HTMLElementTagNameMap {
"ogm-image": HTMLOgmImageElement;
"ogm-map": HTMLOgmMapElement;
"ogm-menubar": HTMLOgmMenubarElement;
"ogm-metadata": HTMLOgmMetadataElement;
Expand All @@ -132,6 +160,12 @@ declare global {
}
}
declare namespace LocalJSX {
interface OgmImage {
"onImageLoaded"?: (event: OgmImageCustomEvent<void>) => void;
"onImageLoading"?: (event: OgmImageCustomEvent<void>) => void;
"record"?: OgmRecord;
"theme"?: 'light' | 'dark';
}
interface OgmMap {
"onMapIdle"?: (event: OgmMapCustomEvent<void>) => void;
"onMapLoading"?: (event: OgmMapCustomEvent<void>) => void;
Expand Down Expand Up @@ -164,6 +198,7 @@ declare namespace LocalJSX {
"theme"?: 'light' | 'dark';
}
interface IntrinsicElements {
"ogm-image": OgmImage;
"ogm-map": OgmMap;
"ogm-menubar": OgmMenubar;
"ogm-metadata": OgmMetadata;
Expand All @@ -176,6 +211,7 @@ export { LocalJSX as JSX };
declare module "@stencil/core" {
export namespace JSX {
interface IntrinsicElements {
"ogm-image": LocalJSX.OgmImage & JSXBase.HTMLAttributes<HTMLOgmImageElement>;
"ogm-map": LocalJSX.OgmMap & JSXBase.HTMLAttributes<HTMLOgmMapElement>;
"ogm-menubar": LocalJSX.OgmMenubar & JSXBase.HTMLAttributes<HTMLOgmMenubarElement>;
"ogm-metadata": LocalJSX.OgmMetadata & JSXBase.HTMLAttributes<HTMLOgmMetadataElement>;
Expand Down
21 changes: 21 additions & 0 deletions src/components/ogm-image/ogm-image.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
:host {
display: block;
width: 100%;
height: 100%;
position: relative;
}

#openseadragon {
height: 100%;
background-color: var(--sl-panel-background-color);
}

.controls {
position: absolute;
top: 0.5rem;
right: 0.5rem;
z-index: 1;
display: flex;
flex-direction: column;
gap: 0.5rem;
}
82 changes: 82 additions & 0 deletions src/components/ogm-image/ogm-image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { Component, Element, h, Host, Watch, Prop, Event, EventEmitter } from '@stencil/core';
import { Viewer } from 'openseadragon';

import type { OgmRecord } from '../../utils/record';

@Component({
tag: 'ogm-image',
styleUrl: 'ogm-image.css',
shadow: true,
})
export class OgmImage {
@Element() el: HTMLElement;
@Prop() record: OgmRecord;
@Prop() theme: 'light' | 'dark';
@Event() imageLoaded: EventEmitter<void>;
@Event() imageLoading: EventEmitter<void>;

// OpenSeadragon viewer instance
private viewer: Viewer;

// Set up OpenSeadragon viewer on load
async componentDidLoad() {
this.viewer = new Viewer({
element: this.el.shadowRoot.getElementById('openseadragon'),
prefixUrl: 'https://cdnjs.cloudflare.com/ajax/libs/openseadragon/2.4.2/images/',
visibilityRatio: 1,
sequenceMode: true,
drawer: (typeof jest === 'undefined') ? 'webgl' : 'html', // No WebGL in tests
zoomInButton: this.el.shadowRoot.querySelector('.zoom-in'),
zoomOutButton: this.el.shadowRoot.querySelector('.zoom-out'),
homeButton: this.el.shadowRoot.querySelector('.home'),
fullPageButton: this.el.shadowRoot.querySelector('.full-page'),
nextButton: this.el.shadowRoot.querySelector('.next'),
previousButton: this.el.shadowRoot.querySelector('.prev'),
});
this.viewer.addHandler('open', () => this.imageLoaded.emit());
if (this.record) await this.loadImages();
}

// Update preview when record changes
@Watch('record')
async onRecordChange() {
if (this.record) await this.loadImages();
}

// Get all of the IIIF image URLs and send them to OpenSeadragon
// This makes a request to fetch and cache the manifest
private async loadImages() {
this.imageLoading.emit();
const images = await this.record.references.iiifImages();
this.viewer.open(images);
}

render() {
return (
<Host>
<div id="openseadragon">
<div class="controls">
<sl-button class="zoom-in" size="small" circle>
<sl-icon name="zoom-in" label="Zoom In"></sl-icon>
</sl-button>
<sl-button class="zoom-out" size="small" circle>
<sl-icon name="zoom-out" label="Zoom Out"></sl-icon>
</sl-button>
<sl-button class="home" size="small" circle>
<sl-icon name="house" label="Reset View"></sl-icon>
</sl-button>
<sl-button class="full-page" size="small" circle>
<sl-icon name="arrows-fullscreen" label="Full Screen"></sl-icon>
</sl-button>
<sl-button class="next" size="small" circle>
<sl-icon name="arrow-right" label="Next"></sl-icon>
</sl-button>
<sl-button class="prev" size="small" circle>
<sl-icon name="arrow-left" label="Previous"></sl-icon>
</sl-button>
</div>
</div>
</Host>
);
}
}
1 change: 1 addition & 0 deletions src/components/ogm-map/ogm-map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export class OgmMap {
this.containerEl = this.el.parentElement.parentElement;
this.addControls();
this.map.on('idle', () => this.mapIdle.emit());
this.map.on('load', () => this.previewRecord(this.record));
}

// Add controls to the map
Expand Down
2 changes: 1 addition & 1 deletion src/components/ogm-settings/ogm-settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export class OgmSettings {
render() {
return (
<div class="settings">
<sl-range label="Layer opacity" min="0" max="100" step="1" value="100"></sl-range>
<sl-range disabled={!this.record || this.record.references.iiifOnly} label="Layer opacity" min="0" max="100" step="1" value="100"></sl-range>
</div>
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/ogm-viewer/ogm-viewer.css
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
height: 100%;
}

.map-container {
.main-container {
position: relative;
min-height: 400px;
height: 100%;
Expand Down
Loading
Loading