@knaw-huc/osd-iiif-viewer 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -1
- package/dist/Overlay.d.ts +6 -0
- package/dist/Viewer.d.ts +5 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.js +28 -38
- package/dist/useImageInfo.d.ts +5 -0
- package/package.json +5 -1
- package/dist/HighlightOverlay.d.ts +0 -11
- package/dist/ViewerCanvas.d.ts +0 -5
package/README.md
CHANGED
|
@@ -1 +1,46 @@
|
|
|
1
|
-
# osd-iiif-viewer
|
|
1
|
+
# @knaw-huc/osd-iiif-viewer
|
|
2
|
+
|
|
3
|
+
React wrapper around OpenSeadragon to display and browse image sources from iiif manifests.
|
|
4
|
+
|
|
5
|
+
Current features (WIP):
|
|
6
|
+
- Canvas navigation
|
|
7
|
+
- Highlight overlay
|
|
8
|
+
- Zoom and fullscreen controls
|
|
9
|
+
- Manifest parsing (iiif manifests v3, ImageService2)
|
|
10
|
+
|
|
11
|
+
## Minimal example
|
|
12
|
+
```tsx
|
|
13
|
+
import {useEffect} from 'react';
|
|
14
|
+
import {
|
|
15
|
+
ViewerProvider,
|
|
16
|
+
ViewerCanvas,
|
|
17
|
+
useLoadManifest,
|
|
18
|
+
useManifest,
|
|
19
|
+
} from '@knaw-huc/osd-iiif-viewer';
|
|
20
|
+
|
|
21
|
+
export function Example() {
|
|
22
|
+
return <ViewerProvider>
|
|
23
|
+
<Viewer/>
|
|
24
|
+
</ViewerProvider>
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function Viewer() {
|
|
28
|
+
const loadManifest = useLoadManifest();
|
|
29
|
+
const manifest = useManifest();
|
|
30
|
+
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
loadManifest('/manifest.json');
|
|
33
|
+
}, [loadManifest]);
|
|
34
|
+
|
|
35
|
+
if (!manifest.data) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<div style={{width: '100%', height: '100vh'}}>
|
|
41
|
+
<ViewerCanvas/>
|
|
42
|
+
</div>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
package/dist/Viewer.d.ts
ADDED
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export {
|
|
1
|
+
export { useImageInfo } from './useImageInfo.tsx';
|
|
2
|
+
export { Overlay } from './Overlay.tsx';
|
|
3
|
+
export { Viewer } from './Viewer.tsx';
|
|
3
4
|
export { ViewerProvider } from './ViewerProvider';
|
|
4
5
|
export { useViewer } from './useViewer';
|
|
5
6
|
export { useViewerControls } from './useViewerControls';
|
|
@@ -7,4 +8,4 @@ export { useViewerReady } from './useViewerReady';
|
|
|
7
8
|
export { useViewerStore } from './useViewerStore';
|
|
8
9
|
export { useManifest, useLoadManifest } from './manifest/useManifest';
|
|
9
10
|
export { useCanvas } from './manifest/useCanvas';
|
|
10
|
-
export type { ViewerManifest, ViewerCanvas
|
|
11
|
+
export type { ViewerManifest, ViewerCanvas, ViewerRange, ViewerMetadata } from './manifest/model';
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { useStore } from "zustand/index";
|
|
2
|
-
import { createContext, useContext, useEffect, useRef,
|
|
2
|
+
import { createContext, useContext, useMemo, useState, useEffect, useRef, useCallback } from "react";
|
|
3
3
|
import { createStore } from "zustand/vanilla";
|
|
4
|
+
import { createPortal } from "react-dom";
|
|
4
5
|
import { jsx } from "react/jsx-runtime";
|
|
5
|
-
import { Viewer } from "openseadragon";
|
|
6
|
+
import { Viewer as Viewer$1 } from "openseadragon";
|
|
6
7
|
const createInstanceSlice = (set) => ({
|
|
7
8
|
viewer: null,
|
|
8
9
|
viewerReady: !1,
|
|
@@ -163,42 +164,30 @@ function useViewer() {
|
|
|
163
164
|
function useViewerReady() {
|
|
164
165
|
return useViewerStoreSelector((s) => s.viewerReady);
|
|
165
166
|
}
|
|
166
|
-
function
|
|
167
|
-
if (!(element instanceof SVGElement))
|
|
168
|
-
throw new Error("Expected SVGElement");
|
|
169
|
-
}
|
|
170
|
-
function HighlightOverlay({ highlights, onHover = noop }) {
|
|
167
|
+
function useImageInfo() {
|
|
171
168
|
const viewer = useViewer(), ready = useViewerReady();
|
|
172
|
-
return
|
|
173
|
-
if (!viewer || !ready
|
|
174
|
-
return;
|
|
169
|
+
return useMemo(() => {
|
|
170
|
+
if (!viewer || !ready)
|
|
171
|
+
return null;
|
|
175
172
|
const item = viewer.world.getItemAt(0);
|
|
176
173
|
if (!item)
|
|
177
|
-
return;
|
|
178
|
-
const size = item.getContentSize()
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
}), svg.appendChild(g), container.appendChild(svg), viewer.addOverlay({ element: container, location: imageRect }), overlayElements.push(container);
|
|
194
|
-
}
|
|
195
|
-
return () => {
|
|
196
|
-
overlayElements.forEach((el) => viewer.removeOverlay(el));
|
|
197
|
-
};
|
|
198
|
-
}, [viewer, ready, highlights, onHover]), null;
|
|
174
|
+
return null;
|
|
175
|
+
const size = item.getContentSize();
|
|
176
|
+
return { location: item.imageToViewportRectangle(0, 0, size.x, size.y), size };
|
|
177
|
+
}, [viewer, ready]);
|
|
178
|
+
}
|
|
179
|
+
function Overlay({ location, children }) {
|
|
180
|
+
const viewer = useViewer(), [container] = useState(() => {
|
|
181
|
+
const el = document.createElement("div");
|
|
182
|
+
return el.style.position = "absolute", el.style.pointerEvents = "none", el;
|
|
183
|
+
});
|
|
184
|
+
return useEffect(() => {
|
|
185
|
+
if (viewer)
|
|
186
|
+
return viewer.addOverlay({ element: container, location }), () => {
|
|
187
|
+
viewer.removeOverlay(container);
|
|
188
|
+
};
|
|
189
|
+
}, [viewer, location, container]), viewer ? createPortal(children, container) : null;
|
|
199
190
|
}
|
|
200
|
-
const noop = () => {
|
|
201
|
-
};
|
|
202
191
|
function findTileSource(canvas) {
|
|
203
192
|
return canvas.imageServiceId + "/info.json";
|
|
204
193
|
}
|
|
@@ -210,12 +199,12 @@ function useCanvas() {
|
|
|
210
199
|
);
|
|
211
200
|
return { currentIndex, goTo, next, prev, current, total };
|
|
212
201
|
}
|
|
213
|
-
function
|
|
202
|
+
function Viewer({ showControls = !0 }) {
|
|
214
203
|
const containerRef = useRef(null), store = useViewerStore(), { current } = useCanvas(), tileSource = current ? findTileSource(current) : null;
|
|
215
204
|
return useEffect(() => {
|
|
216
205
|
if (!containerRef.current || !tileSource)
|
|
217
206
|
return;
|
|
218
|
-
const viewer = new Viewer({
|
|
207
|
+
const viewer = new Viewer$1({
|
|
219
208
|
element: containerRef.current,
|
|
220
209
|
prefixUrl: "https://openseadragon.github.io/openseadragon/images/",
|
|
221
210
|
crossOriginPolicy: "Anonymous",
|
|
@@ -286,10 +275,11 @@ function useLoadManifest() {
|
|
|
286
275
|
return useViewerStoreSelector((s) => s.loadManifest);
|
|
287
276
|
}
|
|
288
277
|
export {
|
|
289
|
-
|
|
290
|
-
|
|
278
|
+
Overlay,
|
|
279
|
+
Viewer,
|
|
291
280
|
ViewerProvider,
|
|
292
281
|
useCanvas,
|
|
282
|
+
useImageInfo,
|
|
293
283
|
useLoadManifest,
|
|
294
284
|
useManifest,
|
|
295
285
|
useViewer,
|
package/package.json
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@knaw-huc/osd-iiif-viewer",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"repository": {
|
|
5
|
+
"type": "git",
|
|
6
|
+
"url": "https://github.com/knaw-huc/osd-iiif-viewer.git"
|
|
7
|
+
},
|
|
4
8
|
"type": "module",
|
|
5
9
|
"main": "dist/index.js",
|
|
6
10
|
"types": "dist/index.d.ts",
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { Id } from './Id.ts';
|
|
2
|
-
export type Highlight = {
|
|
3
|
-
id: Id;
|
|
4
|
-
path: string;
|
|
5
|
-
};
|
|
6
|
-
type HighlightOverlayProps = {
|
|
7
|
-
highlights: Highlight[];
|
|
8
|
-
onHover?: (highlightId: Id | null, event: MouseEvent) => void;
|
|
9
|
-
};
|
|
10
|
-
export declare function HighlightOverlay({ highlights, onHover }: HighlightOverlayProps): null;
|
|
11
|
-
export {};
|