triiiceratops 0.11.1 → 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.
- package/README.md +17 -9
- package/dist/{ArrowCounterClockwise-CN8KGaI0.js → ArrowCounterClockwise-CM9mGGcp.js} +1 -1
- package/dist/X-Bn7S7vUL.js +963 -0
- package/dist/{annotation_tool_point-BpZXtX5D.js → annotation_tool_point-LoRp_nrI.js} +1 -1
- package/dist/annotorious-openseadragon.es-tb5X-LtF.js +33045 -0
- package/dist/components/AnnotationOverlay.svelte +10 -17
- package/dist/components/DemoHeader.svelte +73 -5
- package/dist/components/MetadataDialog.svelte +4 -1
- package/dist/components/OSDViewer.svelte +39 -3
- package/dist/components/SearchPanel.svelte +8 -5
- package/dist/components/ThemeToggle.svelte +1 -1
- package/dist/components/ThumbnailGallery.svelte +229 -38
- package/dist/components/Toolbar.svelte +105 -6
- package/dist/components/TriiiceratopsViewer.svelte +37 -12
- package/dist/components/TriiiceratopsViewerElement.svelte +3 -1
- package/dist/custom-element.js +1 -0
- package/dist/{image_filters_reset-CyWg622b.js → image_filters_reset-CmWuQiOc.js} +1 -1
- package/dist/paraglide/messages/_index.d.ts +9 -0
- package/dist/paraglide/messages/_index.js +10 -1
- package/dist/paraglide/messages/settings_toggle_show_viewing_mode.d.ts +4 -0
- package/dist/paraglide/messages/settings_toggle_show_viewing_mode.js +33 -0
- package/dist/paraglide/messages/show_mode_toggle.d.ts +4 -0
- package/dist/paraglide/messages/show_mode_toggle.js +33 -0
- package/dist/paraglide/messages/toggle_single_page_mode.d.ts +4 -0
- package/dist/paraglide/messages/toggle_single_page_mode.js +33 -0
- package/dist/paraglide/messages/toggle_two_page_mode.d.ts +4 -0
- package/dist/paraglide/messages/toggle_two_page_mode.js +33 -0
- package/dist/paraglide/messages/two_page_mode.d.ts +4 -0
- package/dist/paraglide/messages/two_page_mode.js +33 -0
- package/dist/paraglide/messages/viewing_mode_individuals.d.ts +4 -0
- package/dist/paraglide/messages/viewing_mode_individuals.js +33 -0
- package/dist/paraglide/messages/viewing_mode_label.d.ts +4 -0
- package/dist/paraglide/messages/viewing_mode_label.js +33 -0
- package/dist/paraglide/messages/viewing_mode_paged.d.ts +4 -0
- package/dist/paraglide/messages/viewing_mode_paged.js +33 -0
- package/dist/paraglide/messages/viewing_mode_shift_pairing.d.ts +4 -0
- package/dist/paraglide/messages/viewing_mode_shift_pairing.js +33 -0
- package/dist/plugins/annotation-editor/AnnotationEditorController.svelte +5 -3
- package/dist/plugins/annotation-editor/AnnotationEditorPanel.svelte +3 -3
- package/dist/plugins/annotation-editor/AnnotationManager.svelte.d.ts +3 -0
- package/dist/plugins/annotation-editor/AnnotationManager.svelte.js +19 -14
- package/dist/plugins/annotation-editor/loader.svelte.js +2 -2
- package/dist/plugins/annotation-editor.js +1228 -32159
- package/dist/plugins/image-manipulation/ImageManipulationController.svelte +1 -1
- package/dist/plugins/image-manipulation.js +3 -3
- package/dist/state/manifests.svelte.d.ts +2 -1
- package/dist/state/manifests.svelte.js +5 -9
- package/dist/state/manifests.test.js +52 -50
- package/dist/state/viewer.svelte.d.ts +20 -1
- package/dist/state/viewer.svelte.js +150 -16
- package/dist/triiiceratops-bundle.js +3107 -2584
- package/dist/triiiceratops-element.iife.js +26 -26
- package/dist/triiiceratops.css +1 -1
- package/dist/types/config.d.ts +33 -0
- package/dist/utils/annotationAdapter.js +2 -2
- package/dist/utils/annotationAdapter.test.js +0 -1
- package/package.json +12 -2
- package/dist/X-i_EmjXwW.js +0 -906
|
@@ -42,18 +42,15 @@
|
|
|
42
42
|
const shouldBeVisible =
|
|
43
43
|
viewerState.config.annotations?.visible ?? true;
|
|
44
44
|
|
|
45
|
+
viewerState.visibleAnnotationIds.clear();
|
|
45
46
|
if (shouldBeVisible) {
|
|
46
|
-
const newSet = new Set<string>();
|
|
47
47
|
annotations.forEach((a: any) => {
|
|
48
48
|
const id = getAnnotationId(a);
|
|
49
|
-
if (id)
|
|
49
|
+
if (id) viewerState.visibleAnnotationIds.add(id);
|
|
50
50
|
});
|
|
51
|
-
viewerState.visibleAnnotationIds = newSet;
|
|
52
|
-
} else {
|
|
53
|
-
viewerState.visibleAnnotationIds = new Set();
|
|
54
51
|
}
|
|
55
52
|
} else {
|
|
56
|
-
viewerState.visibleAnnotationIds
|
|
53
|
+
viewerState.visibleAnnotationIds.clear();
|
|
57
54
|
}
|
|
58
55
|
});
|
|
59
56
|
|
|
@@ -72,24 +69,19 @@
|
|
|
72
69
|
} else {
|
|
73
70
|
viewerState.visibleAnnotationIds.add(id);
|
|
74
71
|
}
|
|
75
|
-
// Reassign to trigger reactivity
|
|
76
|
-
viewerState.visibleAnnotationIds = new Set(
|
|
77
|
-
viewerState.visibleAnnotationIds,
|
|
78
|
-
);
|
|
79
72
|
}
|
|
80
73
|
|
|
81
74
|
function toggleAllAnnotations() {
|
|
82
75
|
if (isAllVisible) {
|
|
83
76
|
// Hide all
|
|
84
|
-
viewerState.visibleAnnotationIds
|
|
77
|
+
viewerState.visibleAnnotationIds.clear();
|
|
85
78
|
} else {
|
|
86
79
|
// Show all
|
|
87
|
-
|
|
80
|
+
viewerState.visibleAnnotationIds.clear();
|
|
88
81
|
annotations.forEach((a: any) => {
|
|
89
82
|
const id = getAnnotationId(a);
|
|
90
|
-
if (id)
|
|
83
|
+
if (id) viewerState.visibleAnnotationIds.add(id);
|
|
91
84
|
});
|
|
92
|
-
viewerState.visibleAnnotationIds = newSet;
|
|
93
85
|
}
|
|
94
86
|
}
|
|
95
87
|
|
|
@@ -98,7 +90,7 @@
|
|
|
98
90
|
let toolbarContainer: HTMLElement | undefined = $state();
|
|
99
91
|
|
|
100
92
|
// Calculate coordinates for connecting line
|
|
101
|
-
let
|
|
93
|
+
let _connectingLine = $derived.by(() => {
|
|
102
94
|
if (!hoveredAnnotationId) return null;
|
|
103
95
|
return null;
|
|
104
96
|
});
|
|
@@ -254,7 +246,7 @@
|
|
|
254
246
|
<div
|
|
255
247
|
class="absolute right-0 mt-2 w-96 bg-base-200/95 backdrop-blur shadow-xl rounded-box p-0 max-h-[60vh] overflow-y-auto border border-base-300 flex flex-col divide-y divide-base-300"
|
|
256
248
|
>
|
|
257
|
-
{#each renderedAnnotations as anno, i}
|
|
249
|
+
{#each renderedAnnotations as anno, i (anno.id)}
|
|
258
250
|
{@const isVisible = viewerState.visibleAnnotationIds.has(
|
|
259
251
|
anno.id,
|
|
260
252
|
)}
|
|
@@ -315,7 +307,7 @@
|
|
|
315
307
|
? ''
|
|
316
308
|
: 'opacity-50'} space-y-2"
|
|
317
309
|
>
|
|
318
|
-
{#each anno.bodies as body}
|
|
310
|
+
{#each anno.bodies as body, i (i)}
|
|
319
311
|
<div
|
|
320
312
|
class="flex flex-wrap gap-2 pointer-events-auto"
|
|
321
313
|
>
|
|
@@ -354,6 +346,7 @@
|
|
|
354
346
|
<!-- Commenting / Default -->
|
|
355
347
|
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
|
356
348
|
{#if body.isHtml}
|
|
349
|
+
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
|
357
350
|
{@html body.value}
|
|
358
351
|
{:else}
|
|
359
352
|
{body.value || '(No content)'}
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
|
-
} catch
|
|
82
|
+
} catch {
|
|
83
83
|
/* ignore */
|
|
84
84
|
}
|
|
85
85
|
return `Canvas ${index + 1}`;
|
|
@@ -213,7 +213,7 @@
|
|
|
213
213
|
onchange={(e) => setLocale(e.currentTarget.value as any)}
|
|
214
214
|
aria-label={m.language_select_label()}
|
|
215
215
|
>
|
|
216
|
-
{#each locales as lang}
|
|
216
|
+
{#each locales as lang (lang)}
|
|
217
217
|
<option value={lang}>{languageNames[lang] || lang}</option>
|
|
218
218
|
{/each}
|
|
219
219
|
</select>
|
|
@@ -230,7 +230,6 @@
|
|
|
230
230
|
>
|
|
231
231
|
<Gear size={20} />
|
|
232
232
|
</div>
|
|
233
|
-
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
|
|
234
233
|
<ul
|
|
235
234
|
tabindex="-1"
|
|
236
235
|
class="dropdown-content z-20 menu bg-base-100 rounded-box w-80 p-2 shadow border border-base-300 max-h-[80vh] overflow-y-auto block invisible pointer-events-none group-focus-within:visible group-focus-within:pointer-events-auto"
|
|
@@ -435,6 +434,49 @@
|
|
|
435
434
|
/>
|
|
436
435
|
</label>
|
|
437
436
|
</li>
|
|
437
|
+
<li>
|
|
438
|
+
<label class="label cursor-pointer py-1">
|
|
439
|
+
<span class="label-text"
|
|
440
|
+
>{m.settings_toggle_show_viewing_mode()}</span
|
|
441
|
+
>
|
|
442
|
+
<input
|
|
443
|
+
type="checkbox"
|
|
444
|
+
class="checkbox checkbox-xs"
|
|
445
|
+
checked={config.toolbar
|
|
446
|
+
?.showViewingMode ?? true}
|
|
447
|
+
onchange={(e) => {
|
|
448
|
+
if (!config.toolbar)
|
|
449
|
+
config.toolbar = {};
|
|
450
|
+
config.toolbar.showViewingMode =
|
|
451
|
+
e.currentTarget.checked;
|
|
452
|
+
}}
|
|
453
|
+
/>
|
|
454
|
+
</label>
|
|
455
|
+
</li>
|
|
456
|
+
<li>
|
|
457
|
+
<label class="label cursor-pointer py-1">
|
|
458
|
+
<span class="label-text"
|
|
459
|
+
>{m.viewing_mode_label()}</span
|
|
460
|
+
>
|
|
461
|
+
<select
|
|
462
|
+
class="select select-bordered select-xs"
|
|
463
|
+
value={config.viewingMode ??
|
|
464
|
+
'individuals'}
|
|
465
|
+
onchange={(e) => {
|
|
466
|
+
config.viewingMode = (
|
|
467
|
+
e.currentTarget as HTMLSelectElement
|
|
468
|
+
).value as 'individuals' | 'paged';
|
|
469
|
+
}}
|
|
470
|
+
>
|
|
471
|
+
<option value="individuals"
|
|
472
|
+
>{m.viewing_mode_individuals()}</option
|
|
473
|
+
>
|
|
474
|
+
<option value="paged"
|
|
475
|
+
>{m.viewing_mode_paged()}</option
|
|
476
|
+
>
|
|
477
|
+
</select>
|
|
478
|
+
</label>
|
|
479
|
+
</li>
|
|
438
480
|
</ul>
|
|
439
481
|
</details>
|
|
440
482
|
</li>
|
|
@@ -535,6 +577,32 @@
|
|
|
535
577
|
</select>
|
|
536
578
|
</label>
|
|
537
579
|
</li>
|
|
580
|
+
<li>
|
|
581
|
+
<label class="label cursor-pointer py-1 gap-2">
|
|
582
|
+
<span class="label-text"
|
|
583
|
+
>Thumbnail Height</span
|
|
584
|
+
>
|
|
585
|
+
<input
|
|
586
|
+
type="range"
|
|
587
|
+
min="50"
|
|
588
|
+
max="300"
|
|
589
|
+
value={config.gallery?.fixedHeight ??
|
|
590
|
+
120}
|
|
591
|
+
class="range range-xs range-primary w-24"
|
|
592
|
+
oninput={(e) => {
|
|
593
|
+
if (!config.gallery)
|
|
594
|
+
config.gallery = {};
|
|
595
|
+
config.gallery.fixedHeight =
|
|
596
|
+
parseInt(e.currentTarget.value);
|
|
597
|
+
}}
|
|
598
|
+
/>
|
|
599
|
+
<span
|
|
600
|
+
class="text-xs opacity-50 w-8 text-right"
|
|
601
|
+
>{config.gallery?.fixedHeight ??
|
|
602
|
+
120}px</span
|
|
603
|
+
>
|
|
604
|
+
</label>
|
|
605
|
+
</li>
|
|
538
606
|
</ul>
|
|
539
607
|
</details>
|
|
540
608
|
</li>
|
|
@@ -731,7 +799,7 @@
|
|
|
731
799
|
value={isCustom ? 'custom' : manifestUrl}
|
|
732
800
|
onchange={handleSelectChange}
|
|
733
801
|
>
|
|
734
|
-
{#each SUGGESTED_MANIFESTS as manifest}
|
|
802
|
+
{#each SUGGESTED_MANIFESTS as manifest (manifest.url)}
|
|
735
803
|
<option value={manifest.url}>{manifest.label}</option>
|
|
736
804
|
{/each}
|
|
737
805
|
<option value="custom">{m.try_your_own()}</option>
|
|
@@ -770,7 +838,7 @@
|
|
|
770
838
|
{#if canvases.length === 0}
|
|
771
839
|
<option value="" disabled>{m.no_canvases_loaded()}</option>
|
|
772
840
|
{:else}
|
|
773
|
-
{#each canvases as canvas, i}
|
|
841
|
+
{#each canvases as canvas, i (canvas.id)}
|
|
774
842
|
<option value={canvas.id}>
|
|
775
843
|
{getCanvasLabel(canvas, i)}
|
|
776
844
|
</option>
|
|
@@ -98,6 +98,7 @@
|
|
|
98
98
|
<div class="py-4 overflow-y-auto max-h-[70vh]">
|
|
99
99
|
{#if description}
|
|
100
100
|
<div class="mb-6 prose">
|
|
101
|
+
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
|
101
102
|
<p>{@html description}</p>
|
|
102
103
|
</div>
|
|
103
104
|
{/if}
|
|
@@ -107,6 +108,7 @@
|
|
|
107
108
|
<dt class="font-bold text-lg opacity-70 mt-6">
|
|
108
109
|
{m.attribution()}
|
|
109
110
|
</dt>
|
|
111
|
+
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
|
110
112
|
<dd class="text-sm ps-2">{@html attribution}</dd>
|
|
111
113
|
{/if}
|
|
112
114
|
|
|
@@ -124,10 +126,11 @@
|
|
|
124
126
|
</dd>
|
|
125
127
|
{/if}
|
|
126
128
|
|
|
127
|
-
{#each metadata as item}
|
|
129
|
+
{#each metadata as item, i (i)}
|
|
128
130
|
<dt class="font-bold text-lg opacity-70 mt-6">
|
|
129
131
|
{item.label}
|
|
130
132
|
</dt>
|
|
133
|
+
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
|
131
134
|
<dd class="text-sm ps-2">{@html item.value}</dd>
|
|
132
135
|
{/each}
|
|
133
136
|
</dl>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { onMount } from 'svelte';
|
|
3
|
+
import { SvelteSet } from 'svelte/reactivity';
|
|
3
4
|
import { parseAnnotations } from '../utils/annotationAdapter';
|
|
4
5
|
import { manifestsState } from '../state/manifests.svelte';
|
|
5
6
|
import type { ViewerState } from '../state/viewer.svelte';
|
|
@@ -16,6 +17,8 @@
|
|
|
16
17
|
|
|
17
18
|
// Track OSD state changes for reactivity
|
|
18
19
|
let osdVersion = $state(0);
|
|
20
|
+
// Track last opened tile source to prevent unnecessary resets
|
|
21
|
+
let lastTileSourceStr = '';
|
|
19
22
|
|
|
20
23
|
// Get all annotations for current canvas (manifest + search)
|
|
21
24
|
let allAnnotations = $derived.by(() => {
|
|
@@ -32,7 +35,7 @@
|
|
|
32
35
|
|
|
33
36
|
// Get search hit IDs for styling
|
|
34
37
|
let searchHitIds = $derived.by(() => {
|
|
35
|
-
const ids = new
|
|
38
|
+
const ids = new SvelteSet<string>();
|
|
36
39
|
viewerState.currentCanvasSearchAnnotations.forEach((anno: any) => {
|
|
37
40
|
const id = anno.id || anno['@id'];
|
|
38
41
|
if (id) ids.add(id);
|
|
@@ -48,7 +51,7 @@
|
|
|
48
51
|
// Rendered annotations with pixel coordinates
|
|
49
52
|
let renderedAnnotations = $derived.by(() => {
|
|
50
53
|
// Depend on osdVersion to trigger updates
|
|
51
|
-
osdVersion;
|
|
54
|
+
void osdVersion;
|
|
52
55
|
|
|
53
56
|
if (!viewer || !OSD || !parsedAnnotations.length) {
|
|
54
57
|
return [];
|
|
@@ -160,9 +163,13 @@
|
|
|
160
163
|
onMount(() => {
|
|
161
164
|
if (!container) return;
|
|
162
165
|
|
|
166
|
+
let mounted = true;
|
|
167
|
+
|
|
163
168
|
(async () => {
|
|
164
169
|
// Dynamically import OpenSeadragon to avoid SSR issues
|
|
165
170
|
const osdModule = await import('openseadragon');
|
|
171
|
+
if (!mounted) return;
|
|
172
|
+
|
|
166
173
|
OSD = osdModule.default || osdModule;
|
|
167
174
|
|
|
168
175
|
// Initialize OpenSeadragon viewer
|
|
@@ -191,6 +198,7 @@
|
|
|
191
198
|
})();
|
|
192
199
|
|
|
193
200
|
return () => {
|
|
201
|
+
mounted = false;
|
|
194
202
|
viewer?.destroy();
|
|
195
203
|
viewerState.osdViewer = null;
|
|
196
204
|
};
|
|
@@ -225,7 +233,35 @@
|
|
|
225
233
|
$effect(() => {
|
|
226
234
|
if (!viewer || !tileSources) return;
|
|
227
235
|
|
|
228
|
-
|
|
236
|
+
// Check if source actually changed to avoid resetting zoom
|
|
237
|
+
const currentStr = JSON.stringify(tileSources);
|
|
238
|
+
if (currentStr === lastTileSourceStr) return;
|
|
239
|
+
lastTileSourceStr = currentStr;
|
|
240
|
+
|
|
241
|
+
if (
|
|
242
|
+
viewerState.viewingMode === 'paged' &&
|
|
243
|
+
tileSources instanceof Array &&
|
|
244
|
+
tileSources.length === 2
|
|
245
|
+
) {
|
|
246
|
+
const secondPageLocation = 1.025;
|
|
247
|
+
const twoPageSpread = [
|
|
248
|
+
{
|
|
249
|
+
tileSource: tileSources[0],
|
|
250
|
+
x: 0,
|
|
251
|
+
y: 0,
|
|
252
|
+
width: 1.0,
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
tileSource: tileSources[1],
|
|
256
|
+
x: secondPageLocation, // small gap between pages
|
|
257
|
+
y: 0,
|
|
258
|
+
width: 1.0,
|
|
259
|
+
},
|
|
260
|
+
];
|
|
261
|
+
viewer.open(twoPageSpread);
|
|
262
|
+
} else {
|
|
263
|
+
viewer.open(tileSources);
|
|
264
|
+
}
|
|
229
265
|
});
|
|
230
266
|
</script>
|
|
231
267
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { getContext, untrack } from 'svelte';
|
|
3
3
|
import MagnifyingGlass from 'phosphor-svelte/lib/MagnifyingGlass';
|
|
4
|
-
import Spinner from 'phosphor-svelte/lib/Spinner';
|
|
5
4
|
import X from 'phosphor-svelte/lib/X';
|
|
6
5
|
import { VIEWER_STATE_KEY, type ViewerState } from '../state/viewer.svelte';
|
|
7
6
|
import { m } from '../state/i18n.svelte';
|
|
@@ -10,7 +9,6 @@
|
|
|
10
9
|
|
|
11
10
|
// We'll initialize from viewerState to preserve context.
|
|
12
11
|
let searchQuery = $state('');
|
|
13
|
-
let resultsContainer: HTMLElement;
|
|
14
12
|
|
|
15
13
|
let showCloseButton = $derived(
|
|
16
14
|
viewerState.config.search?.showCloseButton ?? true,
|
|
@@ -124,7 +122,7 @@
|
|
|
124
122
|
})}
|
|
125
123
|
</div>
|
|
126
124
|
|
|
127
|
-
{#each viewerState.searchResults as group}
|
|
125
|
+
{#each viewerState.searchResults as group (group.canvasIndex)}
|
|
128
126
|
<button
|
|
129
127
|
class="w-full text-left bg-base-100 shadow-sm border border-base-200 rounded-box cursor-pointer hover:shadow-md transition-all block p-0 select-none {viewerState.currentCanvasIndex ===
|
|
130
128
|
group.canvasIndex
|
|
@@ -144,21 +142,26 @@
|
|
|
144
142
|
>
|
|
145
143
|
</div>
|
|
146
144
|
<div class="p-0">
|
|
147
|
-
{#each group.hits.slice(0, 1) as result}
|
|
145
|
+
{#each group.hits.slice(0, 1) as result, i (i)}
|
|
148
146
|
<div
|
|
149
147
|
class="p-3 text-sm border-b border-base-200 last:border-none hover:bg-base-200/30 transition-colors"
|
|
150
148
|
>
|
|
151
149
|
{#if result.type === 'hit'}
|
|
152
150
|
<div class="leading-relaxed">
|
|
151
|
+
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
|
153
152
|
<span>{@html result.before}</span>
|
|
154
153
|
<span
|
|
155
154
|
class="bg-yellow-200 text-yellow-900 font-bold px-0.5 rounded"
|
|
156
|
-
>{@html result.match}</span
|
|
157
155
|
>
|
|
156
|
+
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
|
157
|
+
{@html result.match}
|
|
158
|
+
</span>
|
|
159
|
+
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
|
158
160
|
<span>{@html result.after}</span>
|
|
159
161
|
</div>
|
|
160
162
|
{:else}
|
|
161
163
|
<div class="leading-relaxed">
|
|
164
|
+
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
|
162
165
|
{@html result.match}
|
|
163
166
|
</div>
|
|
164
167
|
{/if}
|