triiiceratops 0.11.0 → 0.11.2

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.
Files changed (36) hide show
  1. package/README.md +17 -9
  2. package/dist/{ArrowCounterClockwise-CN8KGaI0.js → ArrowCounterClockwise-B_hB6fl1.js} +1 -1
  3. package/dist/X-Boj9jj2h.js +890 -0
  4. package/dist/{annotation_tool_point-BpZXtX5D.js → annotation_tool_point-rZvdAtGa.js} +1 -1
  5. package/dist/annotorious-openseadragon.es-tb5X-LtF.js +33045 -0
  6. package/dist/components/AnnotationOverlay.svelte +10 -17
  7. package/dist/components/DemoHeader.svelte +4 -5
  8. package/dist/components/MetadataDialog.svelte +4 -1
  9. package/dist/components/OSDViewer.svelte +8 -2
  10. package/dist/components/SearchPanel.svelte +8 -5
  11. package/dist/components/ThemeToggle.svelte +1 -1
  12. package/dist/components/ThumbnailGallery.svelte +4 -4
  13. package/dist/components/Toolbar.svelte +5 -4
  14. package/dist/components/TriiiceratopsViewerElement.svelte +3 -1
  15. package/dist/custom-element.js +1 -0
  16. package/dist/{image_filters_reset-CyWg622b.js → image_filters_reset-CAUhlDWt.js} +1 -1
  17. package/dist/plugins/annotation-editor/AnnotationEditorController.svelte +5 -3
  18. package/dist/plugins/annotation-editor/AnnotationEditorPanel.svelte +3 -3
  19. package/dist/plugins/annotation-editor/AnnotationManager.svelte.d.ts +3 -0
  20. package/dist/plugins/annotation-editor/AnnotationManager.svelte.js +19 -14
  21. package/dist/plugins/annotation-editor/loader.svelte.js +2 -2
  22. package/dist/plugins/annotation-editor.js +1228 -32159
  23. package/dist/plugins/image-manipulation/ImageManipulationController.svelte +1 -1
  24. package/dist/plugins/image-manipulation.js +3 -3
  25. package/dist/state/manifests.svelte.d.ts +2 -1
  26. package/dist/state/manifests.svelte.js +5 -9
  27. package/dist/state/manifests.test.js +52 -50
  28. package/dist/state/viewer.svelte.d.ts +2 -1
  29. package/dist/state/viewer.svelte.js +8 -8
  30. package/dist/triiiceratops-bundle.js +1167 -1179
  31. package/dist/triiiceratops-element.iife.js +26 -26
  32. package/dist/triiiceratops.css +1 -1
  33. package/dist/utils/annotationAdapter.js +2 -2
  34. package/dist/utils/annotationAdapter.test.js +0 -1
  35. package/package.json +12 -2
  36. package/dist/X-i_EmjXwW.js +0 -906
@@ -9,7 +9,7 @@
9
9
  import ImageManipulationPanel from './ImageManipulationPanel.svelte';
10
10
 
11
11
  // Props from the plugin system
12
- let { isOpen = false, close } = $props();
12
+ let { isOpen: _isOpen = false, close } = $props();
13
13
 
14
14
  const viewerState = getContext<ViewerState>(VIEWER_STATE_KEY);
15
15
  let filters = $state<ImageFilters>({ ...DEFAULT_FILTERS });
@@ -1,9 +1,9 @@
1
1
  import "svelte/internal/disclose-version";
2
2
  import * as e from "svelte/internal/client";
3
3
  import { getContext as s0 } from "svelte";
4
- import { l as l0, s as i0, X as n0, c as o0, V as c0, g as v0 } from "../X-i_EmjXwW.js";
5
- import { A as d0 } from "../ArrowCounterClockwise-CN8KGaI0.js";
6
- import { i as _0, a as g0, b as f0, g as u0, c as h0, e as m0, d as p0, f as b0 } from "../image_filters_reset-CyWg622b.js";
4
+ import { l as l0, s as i0, X as n0, c as o0, V as c0, g as v0 } from "../X-Boj9jj2h.js";
5
+ import { A as d0 } from "../ArrowCounterClockwise-B_hB6fl1.js";
6
+ import { i as _0, a as g0, b as f0, g as u0, c as h0, e as m0, d as p0, f as b0 } from "../image_filters_reset-CAUhlDWt.js";
7
7
  const G = {
8
8
  brightness: 100,
9
9
  contrast: 100,
@@ -1,3 +1,4 @@
1
+ import { SvelteMap } from 'svelte/reactivity';
1
2
  export interface ManifestEntry {
2
3
  json?: any;
3
4
  manifesto?: any;
@@ -6,7 +7,7 @@ export interface ManifestEntry {
6
7
  }
7
8
  export declare class ManifestsState {
8
9
  manifests: Record<string, ManifestEntry>;
9
- userAnnotations: Map<string, any[]>;
10
+ userAnnotations: SvelteMap<string, any[]>;
10
11
  constructor();
11
12
  private userAnnotationKey;
12
13
  setUserAnnotations(manifestId: string, canvasId: string, annotations: any[]): void;
@@ -1,8 +1,9 @@
1
+ import { SvelteMap } from 'svelte/reactivity';
1
2
  import * as manifesto from 'manifesto.js';
2
3
  export class ManifestsState {
3
4
  manifests = $state({});
4
5
  // User-created annotations (from plugins like annotation editor)
5
- userAnnotations = $state(new Map());
6
+ userAnnotations = new SvelteMap();
6
7
  constructor() { }
7
8
  // === User Annotations API ===
8
9
  userAnnotationKey(manifestId, canvasId) {
@@ -10,17 +11,12 @@ export class ManifestsState {
10
11
  }
11
12
  setUserAnnotations(manifestId, canvasId, annotations) {
12
13
  const key = this.userAnnotationKey(manifestId, canvasId);
13
- // Create a new Map to trigger reactivity
14
- const newMap = new Map(this.userAnnotations);
15
- newMap.set(key, annotations);
16
- this.userAnnotations = newMap;
14
+ this.userAnnotations.set(key, annotations);
17
15
  }
18
16
  clearUserAnnotations(manifestId, canvasId) {
19
17
  const key = this.userAnnotationKey(manifestId, canvasId);
20
18
  if (this.userAnnotations.has(key)) {
21
- const newMap = new Map(this.userAnnotations);
22
- newMap.delete(key);
23
- this.userAnnotations = newMap;
19
+ this.userAnnotations.delete(key);
24
20
  }
25
21
  }
26
22
  getUserAnnotations(manifestId, canvasId) {
@@ -109,7 +105,7 @@ export class ManifestsState {
109
105
  // Manifesto wraps the JSON. We can access the underlying JSON via canvas.__jsonld
110
106
  // Or better, use canvas.getContent() if it works, but for external lists manual fetch is robust.
111
107
  const canvasJson = canvas.__jsonld;
112
- let annotations = [];
108
+ const annotations = [];
113
109
  // Helper to parse list using Manifesto
114
110
  const parseList = (listJson) => {
115
111
  // manifesto.create is not available in 4.3.0 or not exported nicely?
@@ -1,33 +1,33 @@
1
- import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
- import { ManifestsState } from "./manifests.svelte";
3
- import * as manifesto from "manifesto.js";
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
+ import { ManifestsState } from './manifests.svelte';
3
+ import * as manifesto from 'manifesto.js';
4
4
  // Mock manifesto.js since it's an external dependency
5
- vi.mock("manifesto.js", async (importOriginal) => {
5
+ vi.mock('manifesto.js', async (importOriginal) => {
6
6
  const actual = await importOriginal();
7
7
  return {
8
8
  ...actual,
9
- parseManifest: vi.fn((json) => {
9
+ parseManifest: vi.fn((_json) => {
10
10
  // Minimal mock of a manifesto object
11
11
  return {
12
12
  getSequences: () => [
13
13
  {
14
- getCanvases: () => [{ id: "canvas1" }],
14
+ getCanvases: () => [{ id: 'canvas1' }],
15
15
  getCanvasById: (id) => {
16
- if (id === "canvas1") {
16
+ if (id === 'canvas1') {
17
17
  return {
18
- id: "canvas1",
18
+ id: 'canvas1',
19
19
  __jsonld: {
20
20
  otherContent: [
21
21
  {
22
- "@id": "http://example.org/list1",
23
- "@type": "sc:AnnotationList",
22
+ '@id': 'http://example.org/list1',
23
+ '@type': 'sc:AnnotationList',
24
24
  },
25
25
  ],
26
26
  annotations: [
27
27
  // v3 style
28
28
  {
29
- id: "http://example.org/list2",
30
- type: "AnnotationPage",
29
+ id: 'http://example.org/list2',
30
+ type: 'AnnotationPage',
31
31
  },
32
32
  ],
33
33
  },
@@ -41,80 +41,82 @@ vi.mock("manifesto.js", async (importOriginal) => {
41
41
  }),
42
42
  };
43
43
  });
44
- describe("ManifestsState", () => {
44
+ describe('ManifestsState', () => {
45
45
  let state;
46
46
  const mockFetch = vi.fn();
47
47
  beforeEach(() => {
48
- vi.stubGlobal("fetch", mockFetch);
48
+ vi.stubGlobal('fetch', mockFetch);
49
49
  state = new ManifestsState();
50
50
  mockFetch.mockReset();
51
51
  });
52
52
  afterEach(() => {
53
53
  vi.restoreAllMocks();
54
54
  });
55
- describe("fetchManifest", () => {
56
- it("should fetch and store a manifest", async () => {
55
+ describe('fetchManifest', () => {
56
+ it('should fetch and store a manifest', async () => {
57
57
  const mockManifest = {
58
- "@id": "http://example.org/manifest",
59
- label: "Test Manifest",
58
+ '@id': 'http://example.org/manifest',
59
+ label: 'Test Manifest',
60
60
  };
61
61
  mockFetch.mockResolvedValueOnce({
62
62
  ok: true,
63
63
  json: async () => mockManifest,
64
64
  });
65
- await state.fetchManifest("http://example.org/manifest");
66
- expect(mockFetch).toHaveBeenCalledWith("http://example.org/manifest");
67
- expect(state.manifests["http://example.org/manifest"]).toBeDefined();
68
- expect(state.manifests["http://example.org/manifest"].json).toEqual(mockManifest);
69
- expect(state.manifests["http://example.org/manifest"].isFetching).toBe(false);
65
+ await state.fetchManifest('http://example.org/manifest');
66
+ expect(mockFetch).toHaveBeenCalledWith('http://example.org/manifest');
67
+ expect(state.manifests['http://example.org/manifest']).toBeDefined();
68
+ expect(state.manifests['http://example.org/manifest'].json).toEqual(mockManifest);
69
+ expect(state.manifests['http://example.org/manifest'].isFetching).toBe(false);
70
70
  expect(manifesto.parseManifest).toHaveBeenCalledWith(mockManifest);
71
71
  });
72
- it("should handle fetch errors", async () => {
73
- mockFetch.mockRejectedValueOnce(new Error("Network Error"));
74
- await state.fetchManifest("http://example.org/error");
75
- expect(state.manifests["http://example.org/error"].error).toBe("Network Error");
76
- expect(state.manifests["http://example.org/error"].isFetching).toBe(false);
72
+ it('should handle fetch errors', async () => {
73
+ mockFetch.mockRejectedValueOnce(new Error('Network Error'));
74
+ await state.fetchManifest('http://example.org/error');
75
+ expect(state.manifests['http://example.org/error'].error).toBe('Network Error');
76
+ expect(state.manifests['http://example.org/error'].isFetching).toBe(false);
77
77
  });
78
- it("should not fetch if already fetched", async () => {
78
+ it('should not fetch if already fetched', async () => {
79
79
  // Prime the state
80
- state.manifests["http://example.org/cached"] = {
80
+ state.manifests['http://example.org/cached'] = {
81
81
  isFetching: false,
82
82
  json: {},
83
83
  };
84
- await state.fetchManifest("http://example.org/cached");
84
+ await state.fetchManifest('http://example.org/cached');
85
85
  expect(mockFetch).not.toHaveBeenCalled();
86
86
  });
87
87
  });
88
- describe("getCanvases", () => {
89
- it("should return canvases from parsed manifest", async () => {
88
+ describe('getCanvases', () => {
89
+ it('should return canvases from parsed manifest', async () => {
90
90
  // Mock internal state directly to avoid fetch overhead
91
- state.manifests["http://example.org/manifest"] = {
91
+ state.manifests['http://example.org/manifest'] = {
92
92
  manifesto: {
93
93
  getSequences: () => [
94
94
  {
95
- getCanvases: () => ["mockCanvas1", "mockCanvas2"],
95
+ getCanvases: () => ['mockCanvas1', 'mockCanvas2'],
96
96
  },
97
97
  ],
98
98
  },
99
99
  };
100
- const canvases = state.getCanvases("http://example.org/manifest");
101
- expect(canvases).toEqual(["mockCanvas1", "mockCanvas2"]);
100
+ const canvases = state.getCanvases('http://example.org/manifest');
101
+ expect(canvases).toEqual(['mockCanvas1', 'mockCanvas2']);
102
102
  });
103
- it("should return empty array if manifest not found", () => {
104
- const canvases = state.getCanvases("http://example.org/missing");
103
+ it('should return empty array if manifest not found', () => {
104
+ const canvases = state.getCanvases('http://example.org/missing');
105
105
  expect(canvases).toEqual([]);
106
106
  });
107
107
  });
108
- describe("manualGetAnnotations", () => {
109
- it("should extract annotations and trigger fetch for external lists", async () => {
108
+ describe('manualGetAnnotations', () => {
109
+ it('should extract annotations and trigger fetch for external lists', async () => {
110
110
  // Setup mock state with a manifest that has a canvas
111
- state.manifests["http://example.org/manifest"] = {
111
+ state.manifests['http://example.org/manifest'] = {
112
112
  manifesto: {
113
113
  getSequences: () => [
114
114
  {
115
115
  getCanvasById: () => ({
116
116
  __jsonld: {
117
- otherContent: [{ "@id": "http://example.org/list1" }],
117
+ otherContent: [
118
+ { '@id': 'http://example.org/list1' },
119
+ ],
118
120
  },
119
121
  }),
120
122
  },
@@ -124,24 +126,24 @@ describe("ManifestsState", () => {
124
126
  // Mock the fetch for the annotation list
125
127
  mockFetch.mockResolvedValue({
126
128
  ok: true,
127
- json: async () => ({ resources: [{ "@id": "anno1" }] }),
129
+ json: async () => ({ resources: [{ '@id': 'anno1' }] }),
128
130
  });
129
131
  // First call triggers fetch
130
132
  // manualGetAnnotations calls fetchAnnotationList which is async, but manualGetAnnotations itself is synchronous and returns partial data
131
- state.manualGetAnnotations("http://example.org/manifest", "canvas1");
133
+ state.manualGetAnnotations('http://example.org/manifest', 'canvas1');
132
134
  // We need to wait for the async fetchAnnotationList to complete.
133
135
  // Since it's not returned, we can wait a tick or use `vi.waitFor` if available,
134
136
  // but simpler here is just to await a small delay since we are mocking.
135
137
  await new Promise((resolve) => setTimeout(resolve, 0));
136
- expect(mockFetch).toHaveBeenCalledWith("http://example.org/list1");
138
+ expect(mockFetch).toHaveBeenCalledWith('http://example.org/list1');
137
139
  // Simulate update after fetch (in real app this is reactive, here we manually update state)
138
- state.manifests["http://example.org/list1"] = {
139
- json: { resources: [{ "@id": "anno1" }] },
140
+ state.manifests['http://example.org/list1'] = {
141
+ json: { resources: [{ '@id': 'anno1' }] },
140
142
  };
141
143
  // Second call should return the annotations
142
- const annos = state.manualGetAnnotations("http://example.org/manifest", "canvas1");
144
+ const annos = state.manualGetAnnotations('http://example.org/manifest', 'canvas1');
143
145
  expect(annos).toHaveLength(1);
144
- expect(annos[0]["@id"]).toBe("anno1");
146
+ expect(annos[0]['@id']).toBe('anno1');
145
147
  });
146
148
  });
147
149
  });
@@ -1,3 +1,4 @@
1
+ import { SvelteSet } from 'svelte/reactivity';
1
2
  import type { ViewerConfig } from '../types/config';
2
3
  import type { PluginMenuButton, PluginPanel, PluginDef } from '../types/plugin';
3
4
  /**
@@ -27,7 +28,7 @@ export declare class ViewerState {
27
28
  isFullScreen: boolean;
28
29
  showMetadataDialog: boolean;
29
30
  dockSide: string;
30
- visibleAnnotationIds: Set<string>;
31
+ visibleAnnotationIds: SvelteSet<string>;
31
32
  config: ViewerConfig;
32
33
  get showToggle(): boolean;
33
34
  get showCanvasNav(): boolean;
@@ -1,3 +1,4 @@
1
+ import { SvelteSet, SvelteMap } from 'svelte/reactivity';
1
2
  import { manifestsState } from './manifests.svelte.js';
2
3
  export class ViewerState {
3
4
  manifestId = $state(null);
@@ -10,7 +11,7 @@ export class ViewerState {
10
11
  isFullScreen = $state(false);
11
12
  showMetadataDialog = $state(false);
12
13
  dockSide = $state('bottom');
13
- visibleAnnotationIds = $state(new Set());
14
+ visibleAnnotationIds = new SvelteSet();
14
15
  // UI Configuration
15
16
  config = $state({});
16
17
  // Derived configuration specific getters
@@ -328,7 +329,7 @@ export class ViewerState {
328
329
  const data = await response.json();
329
330
  const resources = data.resources || [];
330
331
  // Group results by canvas index
331
- const resultsByCanvas = new Map();
332
+ const resultsByCanvas = new SvelteMap();
332
333
  // Helper to parse xywh
333
334
  const parseSelector = (onVal) => {
334
335
  const val = typeof onVal === 'string'
@@ -362,7 +363,7 @@ export class ViewerState {
362
363
  // We will take the first valid canvas we find for the annotations.
363
364
  let canvasIndex = -1;
364
365
  let bounds = null;
365
- let allBounds = [];
366
+ const allBounds = [];
366
367
  for (const annoId of annotations) {
367
368
  const annotation = resources.find((r) => r['@id'] === annoId || r.id === annoId);
368
369
  if (annotation && annotation.on) {
@@ -406,7 +407,7 @@ export class ViewerState {
406
407
  label = canvas.label[0]?.value;
407
408
  }
408
409
  }
409
- catch (e) {
410
+ catch (_e) {
410
411
  /* ignore */
411
412
  }
412
413
  resultsByCanvas.set(canvasIndex, {
@@ -454,7 +455,7 @@ export class ViewerState {
454
455
  label = canvas.label[0]?.value;
455
456
  }
456
457
  }
457
- catch (e) {
458
+ catch (_e) {
458
459
  /* ignore */
459
460
  }
460
461
  if (!resultsByCanvas.has(canvasIndex)) {
@@ -527,7 +528,7 @@ export class ViewerState {
527
528
  /** OpenSeadragon viewer instance (set by OSDViewer) */
528
529
  osdViewer = $state.raw(null);
529
530
  /** Event handlers for inter-plugin communication */
530
- pluginEventHandlers = new Map();
531
+ pluginEventHandlers = new SvelteMap();
531
532
  // ==================== PLUGIN METHODS ====================
532
533
  /**
533
534
  * Register a plugin with this viewer instance.
@@ -557,8 +558,7 @@ export class ViewerState {
557
558
  isVisible: () => isOpen,
558
559
  props: {
559
560
  ...def.props,
560
- // Pass isOpen state and closer to component
561
- isOpen: isOpen,
561
+ // Pass closer to component
562
562
  close: () => {
563
563
  isOpen = false;
564
564
  },