@knaw-huc/osd-iiif-viewer 0.1.0 → 0.1.1
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/dist/index.d.ts +1 -0
- package/dist/index.js +49 -12
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { useStore } from "zustand/index";
|
|
2
|
+
import { createContext, useContext, useEffect, useRef, useState, useCallback } from "react";
|
|
3
|
+
import { createStore } from "zustand/vanilla";
|
|
1
4
|
import { jsx } from "react/jsx-runtime";
|
|
2
5
|
import { Viewer } from "openseadragon";
|
|
3
|
-
import { createContext, useContext, useRef, useEffect, useState, useCallback } from "react";
|
|
4
|
-
import { createStore } from "zustand/vanilla";
|
|
5
|
-
import { useStore } from "zustand/index";
|
|
6
6
|
const createInstanceSlice = (set) => ({
|
|
7
7
|
viewer: null,
|
|
8
8
|
viewerReady: !1,
|
|
@@ -153,13 +153,55 @@ const defaultManifest = { data: null, url: "", isLoading: !1, error: null }, cre
|
|
|
153
153
|
function useViewerStore() {
|
|
154
154
|
return useContext(ViewerContext) ?? orThrow("viewer hook must be used within viewer provider");
|
|
155
155
|
}
|
|
156
|
-
function findTileSource(canvas) {
|
|
157
|
-
return canvas.imageServiceId + "/info.json";
|
|
158
|
-
}
|
|
159
156
|
function useViewerStoreSelector(selector) {
|
|
160
157
|
const store = useViewerStore();
|
|
161
158
|
return useStore(store, selector);
|
|
162
159
|
}
|
|
160
|
+
function useViewer() {
|
|
161
|
+
return useViewerStoreSelector((s) => s.viewer);
|
|
162
|
+
}
|
|
163
|
+
function useViewerReady() {
|
|
164
|
+
return useViewerStoreSelector((s) => s.viewerReady);
|
|
165
|
+
}
|
|
166
|
+
function assertSvgElement(element) {
|
|
167
|
+
if (!(element instanceof SVGElement))
|
|
168
|
+
throw new Error("Expected SVGElement");
|
|
169
|
+
}
|
|
170
|
+
function HighlightOverlay({ highlights, onHover = noop }) {
|
|
171
|
+
const viewer = useViewer(), ready = useViewerReady();
|
|
172
|
+
return useEffect(() => {
|
|
173
|
+
if (!viewer || !ready || !highlights.length)
|
|
174
|
+
return;
|
|
175
|
+
const item = viewer.world.getItemAt(0);
|
|
176
|
+
if (!item)
|
|
177
|
+
return;
|
|
178
|
+
const size = item.getContentSize(), imageRect = item.imageToViewportRectangle(0, 0, size.x, size.y), overlayElements = [];
|
|
179
|
+
for (const highlight of highlights) {
|
|
180
|
+
const container = document.createElement("div");
|
|
181
|
+
container.style.position = "absolute", container.style.pointerEvents = "none";
|
|
182
|
+
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
183
|
+
svg.setAttribute("viewBox", `0 0 ${size.x} ${size.y}`), svg.style.width = "100%", svg.style.height = "100%", svg.style.pointerEvents = "none";
|
|
184
|
+
const g = document.createElementNS("http://www.w3.org/2000/svg", "g");
|
|
185
|
+
g.innerHTML = highlight.path;
|
|
186
|
+
const shape = g.firstElementChild;
|
|
187
|
+
assertSvgElement(shape), shape.setAttribute("fill", "transparent"), shape.style.pointerEvents = "auto", shape.style.cursor = "pointer", shape.addEventListener("mouseenter", (event) => {
|
|
188
|
+
shape.setAttribute("fill", "rgba(0,0,0,0.1)"), onHover(highlight.id, event);
|
|
189
|
+
}), shape.addEventListener("mousemove", (event) => {
|
|
190
|
+
onHover(highlight.id, event);
|
|
191
|
+
}), shape.addEventListener("mouseleave", (event) => {
|
|
192
|
+
shape.setAttribute("fill", "transparent"), onHover(null, event);
|
|
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;
|
|
199
|
+
}
|
|
200
|
+
const noop = () => {
|
|
201
|
+
};
|
|
202
|
+
function findTileSource(canvas) {
|
|
203
|
+
return canvas.imageServiceId + "/info.json";
|
|
204
|
+
}
|
|
163
205
|
function useCanvas() {
|
|
164
206
|
const { currentIndex } = useViewerStoreSelector((s) => s.canvas), goTo = useViewerStoreSelector((s) => s.goToCanvas), next = useViewerStoreSelector((s) => s.nextCanvas), prev = useViewerStoreSelector((s) => s.prevCanvas), current = useViewerStoreSelector(
|
|
165
207
|
(s) => s.manifest.data?.canvases[s.canvas.currentIndex] ?? null
|
|
@@ -205,9 +247,6 @@ function ViewerProvider({ children }) {
|
|
|
205
247
|
const [store] = useState(() => createViewerStore());
|
|
206
248
|
return /* @__PURE__ */ jsx(ViewerContext.Provider, { value: store, children });
|
|
207
249
|
}
|
|
208
|
-
function useViewer() {
|
|
209
|
-
return useViewerStoreSelector((s) => s.viewer);
|
|
210
|
-
}
|
|
211
250
|
function useViewerControls(fullscreenRef) {
|
|
212
251
|
const viewer = useViewer(), store = useViewerStore(), zoomLevel = useViewerStoreSelector((s) => s.zoomLevel), zoomMin = useViewerStoreSelector((s) => s.zoomMin), zoomMax = useViewerStoreSelector((s) => s.zoomMax), isFullPage = useViewerStoreSelector((s) => s.isFullPage);
|
|
213
252
|
useEffect(() => {
|
|
@@ -240,9 +279,6 @@ function useViewerControls(fullscreenRef) {
|
|
|
240
279
|
isFullPage
|
|
241
280
|
};
|
|
242
281
|
}
|
|
243
|
-
function useViewerReady() {
|
|
244
|
-
return useViewerStoreSelector((s) => s.viewerReady);
|
|
245
|
-
}
|
|
246
282
|
function useManifest() {
|
|
247
283
|
return useViewerStoreSelector((s) => s.manifest);
|
|
248
284
|
}
|
|
@@ -250,6 +286,7 @@ function useLoadManifest() {
|
|
|
250
286
|
return useViewerStoreSelector((s) => s.loadManifest);
|
|
251
287
|
}
|
|
252
288
|
export {
|
|
289
|
+
HighlightOverlay,
|
|
253
290
|
ViewerCanvas,
|
|
254
291
|
ViewerProvider,
|
|
255
292
|
useCanvas,
|