@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 CHANGED
@@ -1,3 +1,4 @@
1
+ export { HighlightOverlay, type Highlight } from './HighlightOverlay.tsx';
1
2
  export { ViewerCanvas } from './ViewerCanvas';
2
3
  export { ViewerProvider } from './ViewerProvider';
3
4
  export { useViewer } from './useViewer';
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,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knaw-huc/osd-iiif-viewer",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",