triiiceratops 0.11.2 → 0.12.0

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 (39) hide show
  1. package/dist/{ArrowCounterClockwise-B_hB6fl1.js → ArrowCounterClockwise-CM9mGGcp.js} +1 -1
  2. package/dist/X-Bn7S7vUL.js +963 -0
  3. package/dist/{annotation_tool_point-rZvdAtGa.js → annotation_tool_point-LoRp_nrI.js} +1 -1
  4. package/dist/components/DemoHeader.svelte +69 -0
  5. package/dist/components/OSDViewer.svelte +31 -1
  6. package/dist/components/ThumbnailGallery.svelte +226 -35
  7. package/dist/components/Toolbar.svelte +102 -3
  8. package/dist/components/TriiiceratopsViewer.svelte +37 -12
  9. package/dist/{image_filters_reset-CAUhlDWt.js → image_filters_reset-CmWuQiOc.js} +1 -1
  10. package/dist/paraglide/messages/_index.d.ts +9 -0
  11. package/dist/paraglide/messages/_index.js +10 -1
  12. package/dist/paraglide/messages/settings_toggle_show_viewing_mode.d.ts +4 -0
  13. package/dist/paraglide/messages/settings_toggle_show_viewing_mode.js +33 -0
  14. package/dist/paraglide/messages/show_mode_toggle.d.ts +4 -0
  15. package/dist/paraglide/messages/show_mode_toggle.js +33 -0
  16. package/dist/paraglide/messages/toggle_single_page_mode.d.ts +4 -0
  17. package/dist/paraglide/messages/toggle_single_page_mode.js +33 -0
  18. package/dist/paraglide/messages/toggle_two_page_mode.d.ts +4 -0
  19. package/dist/paraglide/messages/toggle_two_page_mode.js +33 -0
  20. package/dist/paraglide/messages/two_page_mode.d.ts +4 -0
  21. package/dist/paraglide/messages/two_page_mode.js +33 -0
  22. package/dist/paraglide/messages/viewing_mode_individuals.d.ts +4 -0
  23. package/dist/paraglide/messages/viewing_mode_individuals.js +33 -0
  24. package/dist/paraglide/messages/viewing_mode_label.d.ts +4 -0
  25. package/dist/paraglide/messages/viewing_mode_label.js +33 -0
  26. package/dist/paraglide/messages/viewing_mode_paged.d.ts +4 -0
  27. package/dist/paraglide/messages/viewing_mode_paged.js +33 -0
  28. package/dist/paraglide/messages/viewing_mode_shift_pairing.d.ts +4 -0
  29. package/dist/paraglide/messages/viewing_mode_shift_pairing.js +33 -0
  30. package/dist/plugins/annotation-editor.js +3 -3
  31. package/dist/plugins/image-manipulation.js +3 -3
  32. package/dist/state/viewer.svelte.d.ts +18 -0
  33. package/dist/state/viewer.svelte.js +142 -8
  34. package/dist/triiiceratops-bundle.js +3047 -2511
  35. package/dist/triiiceratops-element.iife.js +25 -25
  36. package/dist/triiiceratops.css +1 -1
  37. package/dist/types/config.d.ts +33 -0
  38. package/package.json +1 -1
  39. package/dist/X-Boj9jj2h.js +0 -890
@@ -0,0 +1,963 @@
1
+ var Ve = Object.defineProperty;
2
+ var pe = (i) => {
3
+ throw TypeError(i);
4
+ };
5
+ var Te = (i, e, s) => e in i ? Ve(i, e, { enumerable: !0, configurable: !0, writable: !0, value: s }) : i[e] = s;
6
+ var O = (i, e, s) => Te(i, typeof e != "symbol" ? e + "" : e, s), Be = (i, e, s) => e.has(i) || pe("Cannot " + s);
7
+ var a = (i, e, s) => (Be(i, e, "read from private field"), s ? s.call(i) : e.get(i)), h = (i, e, s) => e.has(i) ? pe("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(i) : e.set(i, s);
8
+ import * as t from "svelte/internal/client";
9
+ import { SvelteMap as fe, SvelteSet as De } from "svelte/reactivity";
10
+ import * as Ge from "manifesto.js";
11
+ import "svelte/internal/disclose-version";
12
+ import { hasContext as Re, getContext as je } from "svelte";
13
+ var T;
14
+ class ze {
15
+ constructor() {
16
+ h(this, T, t.state(t.proxy({})));
17
+ O(this, "userAnnotations", new fe());
18
+ }
19
+ get manifests() {
20
+ return t.get(a(this, T));
21
+ }
22
+ set manifests(e) {
23
+ t.set(a(this, T), e, !0);
24
+ }
25
+ // === User Annotations API ===
26
+ userAnnotationKey(e, s) {
27
+ return `${e}::${s}`;
28
+ }
29
+ setUserAnnotations(e, s, n) {
30
+ const r = this.userAnnotationKey(e, s);
31
+ this.userAnnotations.set(r, n);
32
+ }
33
+ clearUserAnnotations(e, s) {
34
+ const n = this.userAnnotationKey(e, s);
35
+ this.userAnnotations.has(n) && this.userAnnotations.delete(n);
36
+ }
37
+ getUserAnnotations(e, s) {
38
+ const n = this.userAnnotationKey(e, s);
39
+ return this.userAnnotations.get(n) ?? [];
40
+ }
41
+ // === Manifest Fetching ===
42
+ async fetchManifest(e) {
43
+ if (!this.manifests[e]) {
44
+ this.manifests[e] = { isFetching: !0 };
45
+ try {
46
+ const s = await fetch(e);
47
+ if (!s.ok)
48
+ throw new Error(`HTTP error! status: ${s.status}`);
49
+ const n = await s.json(), r = Ge.parseManifest(n);
50
+ this.manifests[e] = { json: n, manifesto: r, isFetching: !1 };
51
+ } catch (s) {
52
+ this.manifests[e] = { error: s.message, isFetching: !1 };
53
+ }
54
+ }
55
+ }
56
+ getManifest(e) {
57
+ const s = this.manifests[e];
58
+ return s == null ? void 0 : s.manifesto;
59
+ }
60
+ getManifestEntry(e) {
61
+ return this.manifests[e];
62
+ }
63
+ async fetchAnnotationList(e) {
64
+ if (!this.manifests[e])
65
+ try {
66
+ const s = await fetch(e);
67
+ if (s.ok) {
68
+ const n = await s.json();
69
+ this.manifests[e] = { json: n };
70
+ } else
71
+ console.error(`Failed to fetch annotation list: ${e}`);
72
+ } catch (s) {
73
+ console.error(`Error fetching annotation list: ${e}`, s);
74
+ }
75
+ }
76
+ getCanvases(e) {
77
+ const s = this.getManifest(e);
78
+ if (!s)
79
+ return [];
80
+ const n = s.getSequences();
81
+ return !n || !n.length ? [] : n[0].getCanvases();
82
+ }
83
+ getAnnotations(e, s) {
84
+ const n = this.manualGetAnnotations(e, s), r = this.getUserAnnotations(e, s);
85
+ return [...n, ...r];
86
+ }
87
+ // We can refactor this to use Manifesto's resource handling later if needed.
88
+ manualGetAnnotations(e, s) {
89
+ const n = this.getManifest(e);
90
+ if (!n) return [];
91
+ const r = n.getSequences()[0].getCanvasById(s);
92
+ if (!r) return [];
93
+ const u = r.__jsonld, p = [], S = (c) => c.resources || c.items || [];
94
+ return u.otherContent && u.otherContent.forEach((c) => {
95
+ const m = c["@id"] || c.id;
96
+ if (m && !c.resources) {
97
+ const w = this.manifests[m];
98
+ if (w) {
99
+ if (w.json) {
100
+ const y = S(w.json);
101
+ p.push(...y);
102
+ }
103
+ } else
104
+ this.fetchAnnotationList(m);
105
+ } else c.resources && p.push(...c.resources);
106
+ }), u.annotations && u.annotations.forEach((c) => {
107
+ const m = c.id || c["@id"];
108
+ if (m && !c.items) {
109
+ const w = this.manifests[m];
110
+ if (w) {
111
+ if (w.json) {
112
+ const y = S(w.json);
113
+ p.push(...y);
114
+ }
115
+ } else
116
+ this.fetchAnnotationList(m);
117
+ } else c.items && p.push(...c.items);
118
+ }), p;
119
+ }
120
+ }
121
+ T = new WeakMap();
122
+ const k = new ze();
123
+ var B, D, G, R, j, z, F, Q, Z, $, H, N, U, q, K, W, J, X, Y, ee, te, se, ne, ae, ie, re, oe;
124
+ class ot {
125
+ constructor(e = null, s = null, n = []) {
126
+ h(this, B, t.state(null));
127
+ h(this, D, t.state(null));
128
+ h(this, G, t.state(!1));
129
+ h(this, R, t.state(!1));
130
+ h(this, j, t.state(!1));
131
+ h(this, z, t.state(!1));
132
+ h(this, F, t.state(!1));
133
+ h(this, Q, t.state(!1));
134
+ h(this, Z, t.state(!1));
135
+ h(this, $, t.state("bottom"));
136
+ O(this, "visibleAnnotationIds", new De());
137
+ h(this, H, t.state(t.proxy({})));
138
+ h(
139
+ this,
140
+ N,
141
+ // Pairing offset for paged mode: 0 = default (pairs start at 1+2), 1 = shifted (page 1 alone, pairs start at 2+3)
142
+ t.state(0)
143
+ );
144
+ h(this, U, t.state(t.proxy({ x: 20, y: 100 })));
145
+ h(this, q, t.state(t.proxy({ width: 300, height: 400 })));
146
+ h(this, K, t.state(!1));
147
+ h(this, W, t.state(t.proxy({ x: 0, y: 0 })));
148
+ h(this, J, t.state(null));
149
+ h(this, X, t.state(null));
150
+ O(this, "eventTarget", null);
151
+ /**
152
+ * Reference to the main viewer DOM element.
153
+ * Used for fullscreen toggling.
154
+ */
155
+ O(this, "viewerElement", null);
156
+ h(this, Y, t.state(""));
157
+ h(this, ee, t.state(null));
158
+ h(this, te, t.state(t.proxy([])));
159
+ h(this, se, t.state(!1));
160
+ h(this, ne, t.state(!1));
161
+ h(this, ae, t.state(t.proxy([])));
162
+ h(
163
+ this,
164
+ ie,
165
+ // ==================== PLUGIN STATE ====================
166
+ /** Plugin-registered menu buttons */
167
+ t.state(t.proxy([]))
168
+ );
169
+ h(this, re, t.state(t.proxy([])));
170
+ h(this, oe, t.state(null));
171
+ O(this, "pluginEventHandlers", new fe());
172
+ this.manifestId = e || null, this.canvasId = s || null, this.manifestId && k.fetchManifest(this.manifestId);
173
+ for (const r of n)
174
+ this.registerPlugin(r);
175
+ }
176
+ get manifestId() {
177
+ return t.get(a(this, B));
178
+ }
179
+ set manifestId(e) {
180
+ t.set(a(this, B), e, !0);
181
+ }
182
+ get canvasId() {
183
+ return t.get(a(this, D));
184
+ }
185
+ set canvasId(e) {
186
+ t.set(a(this, D), e, !0);
187
+ }
188
+ get showAnnotations() {
189
+ return t.get(a(this, G));
190
+ }
191
+ set showAnnotations(e) {
192
+ t.set(a(this, G), e, !0);
193
+ }
194
+ get showThumbnailGallery() {
195
+ return t.get(a(this, R));
196
+ }
197
+ set showThumbnailGallery(e) {
198
+ t.set(a(this, R), e, !0);
199
+ }
200
+ get toolbarOpen() {
201
+ return t.get(a(this, j));
202
+ }
203
+ set toolbarOpen(e) {
204
+ t.set(a(this, j), e, !0);
205
+ }
206
+ get isGalleryDockedBottom() {
207
+ return t.get(a(this, z));
208
+ }
209
+ set isGalleryDockedBottom(e) {
210
+ t.set(a(this, z), e, !0);
211
+ }
212
+ get isGalleryDockedRight() {
213
+ return t.get(a(this, F));
214
+ }
215
+ set isGalleryDockedRight(e) {
216
+ t.set(a(this, F), e, !0);
217
+ }
218
+ get isFullScreen() {
219
+ return t.get(a(this, Q));
220
+ }
221
+ set isFullScreen(e) {
222
+ t.set(a(this, Q), e, !0);
223
+ }
224
+ get showMetadataDialog() {
225
+ return t.get(a(this, Z));
226
+ }
227
+ set showMetadataDialog(e) {
228
+ t.set(a(this, Z), e, !0);
229
+ }
230
+ get dockSide() {
231
+ return t.get(a(this, $));
232
+ }
233
+ set dockSide(e) {
234
+ t.set(a(this, $), e, !0);
235
+ }
236
+ get config() {
237
+ return t.get(a(this, H));
238
+ }
239
+ set config(e) {
240
+ t.set(a(this, H), e, !0);
241
+ }
242
+ get showToggle() {
243
+ return this.config.showToggle ?? !0;
244
+ }
245
+ get showCanvasNav() {
246
+ return this.config.showCanvasNav ?? !0;
247
+ }
248
+ get showZoomControls() {
249
+ return this.config.showZoomControls ?? !0;
250
+ }
251
+ get galleryFixedHeight() {
252
+ var e;
253
+ return ((e = this.config.gallery) == null ? void 0 : e.fixedHeight) ?? 120;
254
+ }
255
+ get viewingMode() {
256
+ return this.config.viewingMode ?? "individuals";
257
+ }
258
+ set viewingMode(e) {
259
+ this.config.viewingMode = e;
260
+ }
261
+ get pagedOffset() {
262
+ return t.get(a(this, N));
263
+ }
264
+ set pagedOffset(e) {
265
+ t.set(a(this, N), e, !0);
266
+ }
267
+ get galleryPosition() {
268
+ return t.get(a(this, U));
269
+ }
270
+ set galleryPosition(e) {
271
+ t.set(a(this, U), e, !0);
272
+ }
273
+ get gallerySize() {
274
+ return t.get(a(this, q));
275
+ }
276
+ set gallerySize(e) {
277
+ t.set(a(this, q), e, !0);
278
+ }
279
+ get isGalleryDragging() {
280
+ return t.get(a(this, K));
281
+ }
282
+ set isGalleryDragging(e) {
283
+ t.set(a(this, K), e, !0);
284
+ }
285
+ get galleryDragOffset() {
286
+ return t.get(a(this, W));
287
+ }
288
+ set galleryDragOffset(e) {
289
+ t.set(a(this, W), e, !0);
290
+ }
291
+ get dragOverSide() {
292
+ return t.get(a(this, J));
293
+ }
294
+ set dragOverSide(e) {
295
+ t.set(a(this, J), e, !0);
296
+ }
297
+ get galleryCenterPanelRect() {
298
+ return t.get(a(this, X));
299
+ }
300
+ set galleryCenterPanelRect(e) {
301
+ t.set(a(this, X), e, !0);
302
+ }
303
+ setEventTarget(e) {
304
+ this.eventTarget = e;
305
+ }
306
+ /**
307
+ * Get current state as a plain object snapshot.
308
+ * Safe to use outside Svelte's reactive system.
309
+ * NOTE: We calculate currentCanvasIndex inline to avoid triggering the canvases getter
310
+ * which can cause infinite loops when it auto-sets canvasId.
311
+ */
312
+ getSnapshot() {
313
+ let e = -1;
314
+ return this.manifestId && this.canvasId && (e = k.getCanvases(this.manifestId).findIndex((n) => (n.id || n["@id"] || (n.getCanvasId ? n.getCanvasId() : null) || (n.getId ? n.getId() : null)) === this.canvasId)), {
315
+ manifestId: this.manifestId,
316
+ canvasId: this.canvasId,
317
+ currentCanvasIndex: e,
318
+ showAnnotations: this.showAnnotations,
319
+ showThumbnailGallery: this.showThumbnailGallery,
320
+ showSearchPanel: this.showSearchPanel,
321
+ toolbarOpen: this.toolbarOpen,
322
+ searchQuery: this.searchQuery,
323
+ isFullScreen: this.isFullScreen,
324
+ dockSide: this.dockSide,
325
+ viewingMode: this.viewingMode,
326
+ galleryPosition: this.galleryPosition,
327
+ gallerySize: this.gallerySize
328
+ };
329
+ }
330
+ /**
331
+ * Dispatch a state change event to the web component.
332
+ * No-op if eventTarget is null (Svelte component usage).
333
+ *
334
+ * Uses queueMicrotask to dispatch asynchronously AFTER the current
335
+ * reactive cycle completes, preventing infinite update loops.
336
+ */
337
+ dispatchStateChange(e = "statechange") {
338
+ console.log(`[ViewerState] Dispatching ${e}`, JSON.stringify(this.getSnapshot())), this.eventTarget && queueMicrotask(() => {
339
+ var s;
340
+ (s = this.eventTarget) == null || s.dispatchEvent(new CustomEvent(e, { detail: this.getSnapshot(), bubbles: !0, composed: !0 }));
341
+ });
342
+ }
343
+ get manifest() {
344
+ return this.manifestId ? k.getManifest(this.manifestId) : null;
345
+ }
346
+ get manifestEntry() {
347
+ return this.manifestId ? k.getManifestEntry(this.manifestId) : null;
348
+ }
349
+ get canvases() {
350
+ return this.manifestId ? k.getCanvases(this.manifestId) : [];
351
+ }
352
+ get currentCanvasIndex() {
353
+ return this.canvasId ? this.canvases.findIndex((e) => (e.id || e["@id"] || (e.getCanvasId ? e.getCanvasId() : null) || (e.getId ? e.getId() : null)) === this.canvasId) : this.canvases.length > 0 ? 0 : -1;
354
+ }
355
+ get hasNext() {
356
+ if (this.viewingMode === "paged") {
357
+ const e = this.pagedOffset;
358
+ return this.currentCanvasIndex < e ? this.currentCanvasIndex < this.canvases.length - 1 : this.currentCanvasIndex < this.canvases.length - 2;
359
+ } else
360
+ return this.currentCanvasIndex < this.canvases.length - 1;
361
+ }
362
+ get hasPrevious() {
363
+ return this.currentCanvasIndex > 0;
364
+ }
365
+ nextCanvas() {
366
+ if (this.hasNext)
367
+ if (this.viewingMode === "paged") {
368
+ const e = this.pagedOffset, s = this.currentCanvasIndex < e ? this.currentCanvasIndex + 1 : this.currentCanvasIndex + 2, n = this.canvases[s];
369
+ this.setCanvas(n.id);
370
+ } else {
371
+ const e = this.currentCanvasIndex + 1, s = this.canvases[e];
372
+ this.setCanvas(s.id);
373
+ }
374
+ }
375
+ previousCanvas() {
376
+ if (this.hasPrevious)
377
+ if (this.viewingMode === "paged") {
378
+ const e = this.pagedOffset;
379
+ let s;
380
+ this.currentCanvasIndex <= e ? s = this.currentCanvasIndex - 1 : s = Math.max(this.currentCanvasIndex - 2, e);
381
+ const n = this.canvases[s];
382
+ this.setCanvas(n.id);
383
+ } else {
384
+ const e = this.currentCanvasIndex - 1, s = this.canvases[e];
385
+ this.setCanvas(s.id);
386
+ }
387
+ }
388
+ zoomIn() {
389
+ this.osdViewer && this.osdViewer.viewport && (this.osdViewer.viewport.zoomBy(1.2), this.osdViewer.viewport.applyConstraints());
390
+ }
391
+ zoomOut() {
392
+ this.osdViewer && this.osdViewer.viewport && (this.osdViewer.viewport.zoomBy(0.8), this.osdViewer.viewport.applyConstraints());
393
+ }
394
+ setManifest(e) {
395
+ this.manifestId = e, this.canvasId = null, k.fetchManifest(e), this.dispatchStateChange("manifestchange");
396
+ }
397
+ setCanvas(e) {
398
+ this.canvasId = e, this.dispatchStateChange("canvaschange");
399
+ }
400
+ updateConfig(e) {
401
+ var n;
402
+ const s = this.config;
403
+ if (this.config = e, e.toolbarOpen !== void 0 && (this.toolbarOpen = e.toolbarOpen), e.viewingMode && (this.viewingMode = e.viewingMode), e.gallery && (e.gallery.open !== void 0 && (this.showThumbnailGallery = e.gallery.open), e.gallery.dockPosition !== void 0 && (this.dockSide = e.gallery.dockPosition), e.gallery.width !== void 0 && (this.gallerySize.width = e.gallery.width), e.gallery.height !== void 0 && (this.gallerySize.height = e.gallery.height), e.gallery.x !== void 0 && (this.galleryPosition.x = e.gallery.x), e.gallery.y !== void 0 && (this.galleryPosition.y = e.gallery.y)), e.search) {
404
+ e.search.open !== void 0 && (this.showSearchPanel = e.search.open);
405
+ const r = e.search.query, u = (n = s.search) == null ? void 0 : n.query;
406
+ r !== void 0 && r !== u && r !== this.searchQuery && this._performSearch(r);
407
+ }
408
+ e.annotations && e.annotations.open !== void 0 && (this.showAnnotations = e.annotations.open);
409
+ }
410
+ toggleAnnotations() {
411
+ this.showAnnotations = !this.showAnnotations, this.dispatchStateChange();
412
+ }
413
+ toggleToolbar() {
414
+ this.toolbarOpen = !this.toolbarOpen, this.dispatchStateChange();
415
+ }
416
+ toggleThumbnailGallery() {
417
+ this.showThumbnailGallery = !this.showThumbnailGallery, this.dispatchStateChange();
418
+ }
419
+ setViewerElement(e) {
420
+ this.viewerElement = e;
421
+ }
422
+ toggleFullScreen() {
423
+ if (document.fullscreenElement)
424
+ document.exitFullscreen();
425
+ else {
426
+ const e = this.viewerElement || document.getElementById("triiiceratops-viewer");
427
+ e ? e.requestFullscreen().catch((s) => {
428
+ console.warn("Fullscreen request failed", s);
429
+ }) : console.warn("Cannot toggle fullscreen: Viewer element not found");
430
+ }
431
+ }
432
+ toggleMetadataDialog() {
433
+ this.showMetadataDialog = !this.showMetadataDialog;
434
+ }
435
+ setViewingMode(e) {
436
+ if (this.viewingMode = e, e === "paged") {
437
+ const s = this.pagedOffset;
438
+ if (this.currentCanvasIndex >= s && (this.currentCanvasIndex - s) % 2 === 1) {
439
+ const r = this.currentCanvasIndex - 1, u = this.canvases[r];
440
+ this.setCanvas(u.id);
441
+ }
442
+ }
443
+ this.dispatchStateChange();
444
+ }
445
+ togglePagedOffset() {
446
+ this.pagedOffset = this.pagedOffset === 0 ? 1 : 0;
447
+ const e = this.pagedOffset;
448
+ if (this.currentCanvasIndex >= e && (this.currentCanvasIndex - e) % 2 === 1) {
449
+ const n = this.currentCanvasIndex - 1, r = this.canvases[n];
450
+ this.setCanvas(r.id);
451
+ }
452
+ this.dispatchStateChange();
453
+ }
454
+ get searchQuery() {
455
+ return t.get(a(this, Y));
456
+ }
457
+ set searchQuery(e) {
458
+ t.set(a(this, Y), e, !0);
459
+ }
460
+ get pendingSearchQuery() {
461
+ return t.get(a(this, ee));
462
+ }
463
+ set pendingSearchQuery(e) {
464
+ t.set(a(this, ee), e, !0);
465
+ }
466
+ get searchResults() {
467
+ return t.get(a(this, te));
468
+ }
469
+ set searchResults(e) {
470
+ t.set(a(this, te), e, !0);
471
+ }
472
+ get isSearching() {
473
+ return t.get(a(this, se));
474
+ }
475
+ set isSearching(e) {
476
+ t.set(a(this, se), e, !0);
477
+ }
478
+ get showSearchPanel() {
479
+ return t.get(a(this, ne));
480
+ }
481
+ set showSearchPanel(e) {
482
+ t.set(a(this, ne), e, !0);
483
+ }
484
+ toggleSearchPanel() {
485
+ this.showSearchPanel = !this.showSearchPanel, this.showSearchPanel || (this.searchAnnotations = []), this.dispatchStateChange();
486
+ }
487
+ get searchAnnotations() {
488
+ return t.get(a(this, ae));
489
+ }
490
+ set searchAnnotations(e) {
491
+ t.set(a(this, ae), e, !0);
492
+ }
493
+ get currentCanvasSearchAnnotations() {
494
+ if (!this.canvasId) return [];
495
+ if (this.viewingMode === "paged") {
496
+ let e = this.searchAnnotations.filter((r) => r.canvasId === this.canvasId);
497
+ const s = this.currentCanvasIndex, n = this.pagedOffset;
498
+ if (s >= n) {
499
+ const r = s + 1;
500
+ if (r < this.canvases.length) {
501
+ const u = this.canvases[r], p = u.id || u["@id"], c = this.canvases[s].getWidth() * 1.025, w = this.searchAnnotations.filter((y) => y.canvasId === p).map((y) => {
502
+ const C = y.on.split("#xywh="), b = C[1].split(",").map(Number), E = b[0] + c;
503
+ return {
504
+ ...y,
505
+ on: `${C[0]}#xywh=${E},${b[1]},${b[2]},${b[3]}`
506
+ };
507
+ });
508
+ e = e.concat(w);
509
+ }
510
+ }
511
+ return e;
512
+ } else
513
+ return this.searchAnnotations.filter((e) => e.canvasId === this.canvasId);
514
+ }
515
+ async search(e) {
516
+ this.dispatchStateChange(), await this._performSearch(e), this.dispatchStateChange();
517
+ }
518
+ async _performSearch(e) {
519
+ var s, n;
520
+ if (e.trim()) {
521
+ this.isSearching = !0, this.searchQuery = e, this.searchResults = [];
522
+ try {
523
+ const r = this.manifest;
524
+ if (!r) {
525
+ console.log("[ViewerState] Manifest not loaded, deferring search:", e), this.pendingSearchQuery = e;
526
+ return;
527
+ }
528
+ let u = r.getService("http://iiif.io/api/search/1/search") || r.getService("http://iiif.io/api/search/0/search");
529
+ if (u || r.__jsonld && r.__jsonld.service && (u = (Array.isArray(r.__jsonld.service) ? r.__jsonld.service : [r.__jsonld.service]).find((g) => g.profile === "http://iiif.io/api/search/1/search" || g.profile === "http://iiif.io/api/search/0/search")), !u) {
530
+ console.warn("No IIIF search service found in manifest"), this.isSearching = !1;
531
+ return;
532
+ }
533
+ const S = `${u.id || u["@id"]}?q=${encodeURIComponent(e)}`, c = await fetch(S);
534
+ if (!c.ok) throw new Error("Search request failed");
535
+ const m = await c.json(), w = m.resources || [], y = new fe(), C = (o) => {
536
+ const g = typeof o == "string" ? o : o["@id"] || o.id;
537
+ if (!g) return null;
538
+ const d = g.split("#xywh=");
539
+ if (d.length < 2) return null;
540
+ const x = d[1].split(",").map(Number);
541
+ return x.length === 4 ? x : null;
542
+ }, b = (o) => o ? o.replace(/&lt;mark&gt;/g, "<mark>").replace(/&lt;\/mark&gt;/g, "</mark>") : "";
543
+ if (m.hits)
544
+ for (const o of m.hits) {
545
+ const g = o.annotations || [];
546
+ let d = -1, x = null;
547
+ const I = [];
548
+ for (const l of g) {
549
+ const f = w.find((v) => v["@id"] === l || v.id === l);
550
+ if (f && f.on) {
551
+ const v = typeof f.on == "string" ? f.on : f.on["@id"] || f.on.id, ue = v.split("#")[0], V = C(v), A = this.canvases.findIndex((_) => _.id === ue);
552
+ A >= 0 && (d === -1 && (d = A), V && (I.push(V), x || (x = V)));
553
+ }
554
+ }
555
+ if (d >= 0) {
556
+ if (!y.has(d)) {
557
+ const l = this.canvases[d];
558
+ let f = "Canvas " + (d + 1);
559
+ try {
560
+ if (l.getLabel) {
561
+ const v = l.getLabel();
562
+ Array.isArray(v) && v.length > 0 ? f = v[0].value : typeof v == "string" && (f = v);
563
+ } else l.label && (typeof l.label == "string" ? f = l.label : Array.isArray(l.label) && (f = (s = l.label[0]) == null ? void 0 : s.value));
564
+ } catch {
565
+ }
566
+ y.set(d, { canvasIndex: d, canvasLabel: String(f), hits: [] });
567
+ }
568
+ y.get(d).hits.push({
569
+ type: "hit",
570
+ before: b(o.before),
571
+ match: b(o.match),
572
+ after: b(o.after),
573
+ bounds: x,
574
+ allBounds: I
575
+ });
576
+ }
577
+ }
578
+ else if (w.length > 0)
579
+ for (const o of w) {
580
+ const g = typeof o.on == "string" ? o.on : o.on["@id"] || o.on.id, d = g.split("#")[0], x = C(g), I = this.canvases.findIndex((l) => l.id === d);
581
+ if (I >= 0) {
582
+ const l = this.canvases[I];
583
+ let f = "Canvas " + (I + 1);
584
+ try {
585
+ if (l.getLabel) {
586
+ const v = l.getLabel();
587
+ Array.isArray(v) && v.length > 0 ? f = v[0].value : typeof v == "string" && (f = v);
588
+ } else l.label && (typeof l.label == "string" ? f = l.label : Array.isArray(l.label) && (f = (n = l.label[0]) == null ? void 0 : n.value));
589
+ } catch {
590
+ }
591
+ y.has(I) || y.set(I, { canvasIndex: I, canvasLabel: String(f), hits: [] }), y.get(I).hits.push({
592
+ type: "resource",
593
+ match: b(o.resource && o.resource.chars ? o.resource.chars : o.chars || ""),
594
+ bounds: x,
595
+ allBounds: x ? [x] : []
596
+ });
597
+ }
598
+ }
599
+ this.searchResults = Array.from(y.values()).sort((o, g) => o.canvasIndex - g.canvasIndex);
600
+ let E = 0;
601
+ this.searchAnnotations = this.searchResults.flatMap((o) => {
602
+ const g = this.canvases[o.canvasIndex];
603
+ return o.hits.flatMap((d) => (d.allBounds && d.allBounds.length > 0 ? d.allBounds : d.bounds ? [d.bounds] : []).map((I) => {
604
+ const l = `${g.id}#xywh=${I.join(",")}`;
605
+ return {
606
+ "@id": `urn:search-hit:${E++}`,
607
+ "@type": "oa:Annotation",
608
+ motivation: "sc:painting",
609
+ on: l,
610
+ canvasId: g.id,
611
+ resource: { "@type": "cnt:ContentAsText", chars: d.match },
612
+ // Flag to identify styling in Overlay?
613
+ // Or just standard rendering.
614
+ isSearchHit: !0
615
+ };
616
+ }));
617
+ });
618
+ } catch (r) {
619
+ console.error("Search error:", r), this.isSearching = !1;
620
+ } finally {
621
+ this.pendingSearchQuery || (this.isSearching = !1);
622
+ }
623
+ }
624
+ }
625
+ get pluginMenuButtons() {
626
+ return t.get(a(this, ie));
627
+ }
628
+ set pluginMenuButtons(e) {
629
+ t.set(a(this, ie), e, !0);
630
+ }
631
+ get pluginPanels() {
632
+ return t.get(a(this, re));
633
+ }
634
+ set pluginPanels(e) {
635
+ t.set(a(this, re), e, !0);
636
+ }
637
+ get osdViewer() {
638
+ return t.get(a(this, oe));
639
+ }
640
+ set osdViewer(e) {
641
+ t.set(a(this, oe), e);
642
+ }
643
+ registerPlugin(e) {
644
+ const s = e.id || `plugin-${Math.random().toString(36).substr(2, 9)}`;
645
+ let n = t.state(!1);
646
+ const r = {
647
+ id: `${s}:toggle`,
648
+ icon: e.icon,
649
+ tooltip: e.name,
650
+ onClick: () => {
651
+ t.set(n, !t.get(n));
652
+ },
653
+ isActive: () => t.get(n),
654
+ order: 200
655
+ // Default order for simple plugins
656
+ }, u = {
657
+ id: `${s}:panel`,
658
+ component: e.panel,
659
+ position: e.position || "left",
660
+ isVisible: () => t.get(n),
661
+ props: {
662
+ ...e.props,
663
+ // Pass closer to component
664
+ close: () => {
665
+ t.set(n, !1);
666
+ }
667
+ }
668
+ };
669
+ this.pluginMenuButtons = [...this.pluginMenuButtons, r], this.pluginPanels = [...this.pluginPanels, u], e.onInit && e.onInit(this);
670
+ }
671
+ /**
672
+ * Unregister a plugin's UI components by ID prefix.
673
+ * Note: This cleans up the menu button and panel, but doesn't remove listeners attached by the plugin itself
674
+ * since we don't have a handle on the plugin instance or its cleanup function anymore.
675
+ * Plugins should manage their own cleanup via component lifecycle (onDestroy) if possible.
676
+ */
677
+ unregisterPlugin(e) {
678
+ this.pluginMenuButtons = this.pluginMenuButtons.filter((s) => !s.id.startsWith(`${e}:`)), this.pluginPanels = this.pluginPanels.filter((s) => !s.id.startsWith(`${e}:`));
679
+ }
680
+ /**
681
+ * Notify that OSD viewer is ready.
682
+ * With the component-based system, we don't notify plugins individually.
683
+ * Instead, plugins should use the OSDViewer instance from context or listen for 'osd-ready' event (if we emitted one).
684
+ * But since we have direct access to osdViewer in this state, components can just react to it.
685
+ */
686
+ notifyOSDReady(e) {
687
+ this.osdViewer = e;
688
+ }
689
+ /**
690
+ * Cleanup everything.
691
+ */
692
+ destroyAllPlugins() {
693
+ this.pluginMenuButtons = [], this.pluginPanels = [], this.pluginEventHandlers.clear();
694
+ }
695
+ }
696
+ B = new WeakMap(), D = new WeakMap(), G = new WeakMap(), R = new WeakMap(), j = new WeakMap(), z = new WeakMap(), F = new WeakMap(), Q = new WeakMap(), Z = new WeakMap(), $ = new WeakMap(), H = new WeakMap(), N = new WeakMap(), U = new WeakMap(), q = new WeakMap(), K = new WeakMap(), W = new WeakMap(), J = new WeakMap(), X = new WeakMap(), Y = new WeakMap(), ee = new WeakMap(), te = new WeakMap(), se = new WeakMap(), ne = new WeakMap(), ae = new WeakMap(), ie = new WeakMap(), re = new WeakMap(), oe = new WeakMap();
697
+ const lt = "triiiceratops:viewerState";
698
+ let me = Symbol("phosphor-svelte");
699
+ function Fe() {
700
+ return Re(me) ? je(me) : {};
701
+ }
702
+ const Qe = "en", ve = (
703
+ /** @type {const} */
704
+ ["en", "de"]
705
+ ), we = "PARAGLIDE_LOCALE", Ze = 3456e4, Ie = [
706
+ "cookie",
707
+ "globalVariable",
708
+ "baseLocale"
709
+ ];
710
+ globalThis.__paraglide = {};
711
+ let ge, ye = !1, xe = () => {
712
+ let i;
713
+ for (const e of Ie) {
714
+ if (e === "cookie")
715
+ i = Ue();
716
+ else if (e === "baseLocale")
717
+ i = Qe;
718
+ else if (e === "globalVariable" && ge !== void 0)
719
+ i = ge;
720
+ else if (be(e) && de.has(e)) {
721
+ const s = de.get(e);
722
+ if (s) {
723
+ const n = s.getLocale();
724
+ if (n instanceof Promise)
725
+ continue;
726
+ i = n;
727
+ }
728
+ }
729
+ if (i !== void 0) {
730
+ const s = Ne(i);
731
+ return ye || (ge = s, ye = !0, Se(s, { reload: !1 })), s;
732
+ }
733
+ }
734
+ throw new Error("No locale found. Read the docs https://inlang.com/m/gerre34r/library-inlang-paraglideJs/errors#no-locale-found");
735
+ };
736
+ const $e = (i) => {
737
+ window.location.reload();
738
+ };
739
+ let Se = (i, e) => {
740
+ const s = {
741
+ reload: !0,
742
+ ...e
743
+ };
744
+ let n;
745
+ try {
746
+ n = xe();
747
+ } catch {
748
+ }
749
+ const r = [];
750
+ for (const p of Ie)
751
+ if (p === "globalVariable")
752
+ ge = i;
753
+ else if (p === "cookie") {
754
+ if (typeof document > "u" || typeof window > "u")
755
+ continue;
756
+ const S = `${we}=${i}; path=/; max-age=${Ze}`;
757
+ document.cookie = S;
758
+ } else {
759
+ if (p === "baseLocale")
760
+ continue;
761
+ if (be(p) && de.has(p)) {
762
+ const S = de.get(p);
763
+ if (S) {
764
+ let c = S.setLocale(i);
765
+ c instanceof Promise && (c = c.catch((m) => {
766
+ throw new Error(`Custom strategy "${p}" setLocale failed.`, {
767
+ cause: m
768
+ });
769
+ }), r.push(c));
770
+ }
771
+ }
772
+ }
773
+ const u = () => {
774
+ s.reload && window.location && i !== n && $e();
775
+ };
776
+ if (r.length)
777
+ return Promise.all(r).then(() => {
778
+ u();
779
+ });
780
+ u();
781
+ };
782
+ const ht = (i) => {
783
+ Se = /** @type {SetLocaleFn} */
784
+ i;
785
+ };
786
+ function He(i) {
787
+ return typeof i != "string" ? !1 : i ? ve.some((e) => e.toLowerCase() === i.toLowerCase()) : !1;
788
+ }
789
+ function Ne(i) {
790
+ if (typeof i != "string")
791
+ throw new Error(`Invalid locale: ${i}. Expected a string.`);
792
+ const e = i.toLowerCase(), s = ve.find((n) => n.toLowerCase() === e);
793
+ if (!s)
794
+ throw new Error(`Invalid locale: ${i}. Expected one of: ${ve.join(", ")}`);
795
+ return s;
796
+ }
797
+ function Ue() {
798
+ if (typeof document > "u" || !document.cookie)
799
+ return;
800
+ const i = document.cookie.match(new RegExp(`(^| )${we}=([^;]+)`)), e = i == null ? void 0 : i[2];
801
+ if (He(e))
802
+ return e;
803
+ }
804
+ const de = /* @__PURE__ */ new Map();
805
+ function be(i) {
806
+ return typeof i == "string" && /^custom-[A-Za-z0-9_-]+$/.test(i);
807
+ }
808
+ const qe = (
809
+ /** @type {(inputs: {}) => LocalizedString} */
810
+ () => (
811
+ /** @type {LocalizedString} */
812
+ "Close"
813
+ )
814
+ ), Ke = (
815
+ /** @type {(inputs: {}) => LocalizedString} */
816
+ () => (
817
+ /** @type {LocalizedString} */
818
+ "Schließen"
819
+ )
820
+ ), ct = /* @__NO_SIDE_EFFECTS__ */ (i = {}, e = {}) => (e.locale ?? xe()) === "en" ? qe() : Ke();
821
+ var We = t.from_svg('<path d="M208.49,191.51a12,12,0,0,1-17,17L128,145,64.49,208.49a12,12,0,0,1-17-17L111,128,47.51,64.49a12,12,0,0,1,17-17L128,111l63.51-63.52a12,12,0,0,1,17,17L145,128Z"></path>'), Je = t.from_svg('<path d="M216,56V200a16,16,0,0,1-16,16H56a16,16,0,0,1-16-16V56A16,16,0,0,1,56,40H200A16,16,0,0,1,216,56Z" opacity="0.2"></path><path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"></path>', 1), Xe = t.from_svg('<path d="M208,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32ZM181.66,170.34a8,8,0,0,1-11.32,11.32L128,139.31,85.66,181.66a8,8,0,0,1-11.32-11.32L116.69,128,74.34,85.66A8,8,0,0,1,85.66,74.34L128,116.69l42.34-42.35a8,8,0,0,1,11.32,11.32L139.31,128Z"></path>'), Ye = t.from_svg('<path d="M204.24,195.76a6,6,0,1,1-8.48,8.48L128,136.49,60.24,204.24a6,6,0,0,1-8.48-8.48L119.51,128,51.76,60.24a6,6,0,0,1,8.48-8.48L128,119.51l67.76-67.75a6,6,0,0,1,8.48,8.48L136.49,128Z"></path>'), et = t.from_svg('<path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"></path>'), tt = t.from_svg('<path d="M202.83,197.17a4,4,0,0,1-5.66,5.66L128,133.66,58.83,202.83a4,4,0,0,1-5.66-5.66L122.34,128,53.17,58.83a4,4,0,0,1,5.66-5.66L128,122.34l69.17-69.17a4,4,0,1,1,5.66,5.66L133.66,128Z"></path>'), st = t.from_svg('<svg><!><rect width="256" height="256" fill="none"></rect><!></svg>');
822
+ function gt(i, e) {
823
+ t.push(e, !0);
824
+ const s = Fe();
825
+ let n = t.rest_props(e, ["$$slots", "$$events", "$$legacy", "children"]), r = t.derived(() => e.weight ?? s.weight ?? "regular"), u = t.derived(() => e.color ?? s.color ?? "currentColor"), p = t.derived(() => e.size ?? s.size ?? "1em"), S = t.derived(() => e.mirrored ?? s.mirrored ?? !1);
826
+ function c(o) {
827
+ let { weight: g, color: d, size: x, mirrored: I, ...l } = o;
828
+ return l;
829
+ }
830
+ var m = st();
831
+ t.attribute_effect(
832
+ m,
833
+ (o, g) => ({
834
+ xmlns: "http://www.w3.org/2000/svg",
835
+ role: "img",
836
+ width: t.get(p),
837
+ height: t.get(p),
838
+ fill: t.get(u),
839
+ transform: t.get(S) ? "scale(-1, 1)" : void 0,
840
+ viewBox: "0 0 256 256",
841
+ ...o,
842
+ ...g
843
+ }),
844
+ [() => c(s), () => c(n)]
845
+ );
846
+ var w = t.child(m);
847
+ {
848
+ var y = (o) => {
849
+ var g = t.comment(), d = t.first_child(g);
850
+ t.snippet(d, () => e.children), t.append(o, g);
851
+ };
852
+ t.if(w, (o) => {
853
+ e.children && o(y);
854
+ });
855
+ }
856
+ var C = t.sibling(w, 2);
857
+ {
858
+ var b = (o) => {
859
+ var g = We();
860
+ t.append(o, g);
861
+ }, E = (o) => {
862
+ var g = t.comment(), d = t.first_child(g);
863
+ {
864
+ var x = (l) => {
865
+ var f = Je();
866
+ t.next(), t.append(l, f);
867
+ }, I = (l) => {
868
+ var f = t.comment(), v = t.first_child(f);
869
+ {
870
+ var ue = (A) => {
871
+ var _ = Xe();
872
+ t.append(A, _);
873
+ }, V = (A) => {
874
+ var _ = t.comment(), Ae = t.first_child(_);
875
+ {
876
+ var Ce = (M) => {
877
+ var le = Ye();
878
+ t.append(M, le);
879
+ }, _e = (M) => {
880
+ var le = t.comment(), Me = t.first_child(le);
881
+ {
882
+ var Le = (L) => {
883
+ var he = et();
884
+ t.append(L, he);
885
+ }, Pe = (L) => {
886
+ var he = t.comment(), Oe = t.first_child(he);
887
+ {
888
+ var ke = (P) => {
889
+ var ce = tt();
890
+ t.append(P, ce);
891
+ }, Ee = (P) => {
892
+ var ce = t.text();
893
+ ce.nodeValue = (console.error('Unsupported icon weight. Choose from "thin", "light", "regular", "bold", "fill", or "duotone".'), ""), t.append(P, ce);
894
+ };
895
+ t.if(
896
+ Oe,
897
+ (P) => {
898
+ t.get(r) === "thin" ? P(ke) : P(Ee, !1);
899
+ },
900
+ !0
901
+ );
902
+ }
903
+ t.append(L, he);
904
+ };
905
+ t.if(
906
+ Me,
907
+ (L) => {
908
+ t.get(r) === "regular" ? L(Le) : L(Pe, !1);
909
+ },
910
+ !0
911
+ );
912
+ }
913
+ t.append(M, le);
914
+ };
915
+ t.if(
916
+ Ae,
917
+ (M) => {
918
+ t.get(r) === "light" ? M(Ce) : M(_e, !1);
919
+ },
920
+ !0
921
+ );
922
+ }
923
+ t.append(A, _);
924
+ };
925
+ t.if(
926
+ v,
927
+ (A) => {
928
+ t.get(r) === "fill" ? A(ue) : A(V, !1);
929
+ },
930
+ !0
931
+ );
932
+ }
933
+ t.append(l, f);
934
+ };
935
+ t.if(
936
+ d,
937
+ (l) => {
938
+ t.get(r) === "duotone" ? l(x) : l(I, !1);
939
+ },
940
+ !0
941
+ );
942
+ }
943
+ t.append(o, g);
944
+ };
945
+ t.if(C, (o) => {
946
+ t.get(r) === "bold" ? o(b) : o(E, !1);
947
+ });
948
+ }
949
+ t.reset(m), t.append(i, m), t.pop();
950
+ }
951
+ export {
952
+ ze as M,
953
+ lt as V,
954
+ gt as X,
955
+ xe as a,
956
+ ot as b,
957
+ ct as c,
958
+ Fe as g,
959
+ ve as l,
960
+ k as m,
961
+ ht as o,
962
+ Se as s
963
+ };