triiiceratops 0.15.5 → 0.16.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 +1 -0
- package/dist/components/OSDViewer.svelte +32 -0
- package/dist/components/ThumbnailGallery.svelte +148 -90
- package/dist/components/TriiiceratopsViewer.svelte +2 -2
- package/dist/triiiceratops-bundle.js +1904 -1795
- package/dist/triiiceratops-element.iife.js +12 -14
- package/dist/triiiceratops.css +1 -1
- package/dist/types/config.d.ts +9 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -22,6 +22,7 @@ This project is heavily inspired by Mirador 4, which I still view as the premier
|
|
|
22
22
|
- **Multi-language**: Language-aware metadata with fallback chain; UI translations for English and German
|
|
23
23
|
- **Image Services**: Detects and uses IIIF Image API services (v1, v2, v3) for tiled deep-zoom
|
|
24
24
|
- **Theming**: 35 built-in DaisyUI themes plus custom theme configuration
|
|
25
|
+
- **OpenSeadragon Customization**: Pass custom OSD options (e.g. max zoom level, animation speed) via `openSeadragonConfig`
|
|
25
26
|
|
|
26
27
|
## Current Limitations
|
|
27
28
|
|
|
@@ -184,6 +184,8 @@
|
|
|
184
184
|
animationTime: 0.5,
|
|
185
185
|
springStiffness: 7.0,
|
|
186
186
|
zoomPerClick: 2.0,
|
|
187
|
+
// Consumer-provided OSD overrides
|
|
188
|
+
...(viewerState.config?.openSeadragonConfig ?? {}),
|
|
187
189
|
// Enable double-click to zoom, but keep clickToZoom disabled for Annotorious
|
|
188
190
|
gestureSettingsMouse: {
|
|
189
191
|
clickToZoom: false,
|
|
@@ -227,6 +229,16 @@
|
|
|
227
229
|
};
|
|
228
230
|
});
|
|
229
231
|
|
|
232
|
+
// Apply consumer OSD config overrides reactively
|
|
233
|
+
$effect(() => {
|
|
234
|
+
if (!viewer) return;
|
|
235
|
+
const overrides = viewerState.config?.openSeadragonConfig;
|
|
236
|
+
if (!overrides) return;
|
|
237
|
+
for (const [key, value] of Object.entries(overrides)) {
|
|
238
|
+
viewer[key] = value;
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
|
|
230
242
|
// Load tile source when it changes
|
|
231
243
|
$effect(() => {
|
|
232
244
|
if (!viewer || !tileSources) return;
|
|
@@ -282,6 +294,26 @@
|
|
|
282
294
|
};
|
|
283
295
|
});
|
|
284
296
|
viewer.open(spread);
|
|
297
|
+
|
|
298
|
+
// Zoom to the active canvas once OSD finishes loading,
|
|
299
|
+
// so the user doesn't see the default zoomed-out view of all canvases.
|
|
300
|
+
viewer.addOnceHandler('open', () => {
|
|
301
|
+
const currentIndex = viewerState.currentCanvasIndex;
|
|
302
|
+
let imageIndex = 0;
|
|
303
|
+
for (let i = 0; i < currentIndex; i++) {
|
|
304
|
+
const canvas = viewerState.canvases[i];
|
|
305
|
+
let imgs = canvas.getImages?.() || [];
|
|
306
|
+
if ((!imgs || !imgs.length) && canvas.getContent) {
|
|
307
|
+
imgs = canvas.getContent();
|
|
308
|
+
}
|
|
309
|
+
const count = imgs ? imgs.length : 0;
|
|
310
|
+
imageIndex += count;
|
|
311
|
+
}
|
|
312
|
+
const item = viewer.world.getItemAt(imageIndex);
|
|
313
|
+
if (item) {
|
|
314
|
+
viewer.viewport.fitBounds(item.getBounds(), true);
|
|
315
|
+
}
|
|
316
|
+
});
|
|
285
317
|
} else if (mode === 'paged' && sources.length === 2) {
|
|
286
318
|
const gap = 0.025;
|
|
287
319
|
const offset = 1 + gap;
|
|
@@ -642,14 +642,17 @@
|
|
|
642
642
|
<!-- Floating Window -->
|
|
643
643
|
<div
|
|
644
644
|
bind:this={galleryElement}
|
|
645
|
-
class={
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
(
|
|
651
|
-
|
|
652
|
-
|
|
645
|
+
class={[
|
|
646
|
+
dockSide !== 'none' &&
|
|
647
|
+
'relative z-50 bg-base-100 shadow-xl border-base-300 flex transition-all duration-200 select-none w-full h-full',
|
|
648
|
+
dockSide === 'none' &&
|
|
649
|
+
'fixed z-900 bg-base-100 shadow-2xl rounded-lg flex flex-col border border-base-300 overflow-hidden select-none',
|
|
650
|
+
(dockSide === 'bottom' || dockSide === 'top') &&
|
|
651
|
+
'flex-row border-t',
|
|
652
|
+
(dockSide === 'left' || dockSide === 'right') &&
|
|
653
|
+
'flex-col border-x',
|
|
654
|
+
viewerState.isGalleryDragging && 'pointer-events-none opacity-80',
|
|
655
|
+
]}
|
|
653
656
|
style={dockSide !== 'none'
|
|
654
657
|
? ''
|
|
655
658
|
: `left: ${viewerState.galleryPosition.x}px; top: ${viewerState.galleryPosition.y}px; width: ${viewerState.gallerySize.width}px; height: ${viewerState.gallerySize.height}px;`}
|
|
@@ -668,27 +671,39 @@
|
|
|
668
671
|
<!-- Header Area (only show drag handle when draggable OR when floating) -->
|
|
669
672
|
{#if draggable || dockSide === 'none'}
|
|
670
673
|
<div
|
|
671
|
-
class={
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
674
|
+
class={[
|
|
675
|
+
'bg-base-100 flex shrink-0 select-none relative',
|
|
676
|
+
(dockSide === 'bottom' || dockSide === 'top') &&
|
|
677
|
+
'flex-row h-full items-center border-r border-base-200',
|
|
678
|
+
dockSide !== 'bottom' &&
|
|
679
|
+
dockSide !== 'top' &&
|
|
680
|
+
'flex-col w-full border-b border-base-200',
|
|
681
|
+
]}
|
|
675
682
|
>
|
|
676
683
|
<!-- Drag Handle -->
|
|
677
684
|
<div
|
|
678
|
-
class={
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
685
|
+
class={[
|
|
686
|
+
'cursor-move flex items-center justify-center hover:bg-base-200/50 active:bg-base-200 transition-colors',
|
|
687
|
+
(dockSide === 'bottom' || dockSide === 'top') &&
|
|
688
|
+
'w-8 h-full',
|
|
689
|
+
dockSide !== 'bottom' &&
|
|
690
|
+
dockSide !== 'top' &&
|
|
691
|
+
'h-6 w-full',
|
|
692
|
+
]}
|
|
682
693
|
onmousedown={startDrag}
|
|
683
694
|
role="button"
|
|
684
695
|
tabindex="0"
|
|
685
696
|
aria-label="Drag Gallery"
|
|
686
697
|
>
|
|
687
698
|
<div
|
|
688
|
-
class={
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
699
|
+
class={[
|
|
700
|
+
'bg-base-300 rounded-full',
|
|
701
|
+
(dockSide === 'bottom' || dockSide === 'top') &&
|
|
702
|
+
'w-1.5 h-12',
|
|
703
|
+
dockSide !== 'bottom' &&
|
|
704
|
+
dockSide !== 'top' &&
|
|
705
|
+
'w-12 h-1.5',
|
|
706
|
+
]}
|
|
692
707
|
></div>
|
|
693
708
|
</div>
|
|
694
709
|
</div>
|
|
@@ -696,14 +711,17 @@
|
|
|
696
711
|
|
|
697
712
|
<!-- Content (Grid or Horizontal Scroll) -->
|
|
698
713
|
<div
|
|
699
|
-
class=
|
|
700
|
-
|
|
701
|
-
|
|
714
|
+
class={[
|
|
715
|
+
'flex-1 p-1 bg-base-100',
|
|
716
|
+
isHorizontal && 'overflow-x-auto overflow-y-hidden h-full',
|
|
717
|
+
!isHorizontal && 'overflow-y-auto overflow-x-hidden',
|
|
718
|
+
]}
|
|
702
719
|
>
|
|
703
720
|
<div
|
|
704
|
-
class={
|
|
705
|
-
|
|
706
|
-
|
|
721
|
+
class={[
|
|
722
|
+
isHorizontal && 'flex flex-row gap-2 h-full items-center',
|
|
723
|
+
!isHorizontal && 'grid gap-2',
|
|
724
|
+
]}
|
|
707
725
|
style={isHorizontal
|
|
708
726
|
? ''
|
|
709
727
|
: `grid-template-columns: repeat(auto-fill, minmax(${fixedHeight}px, 1fr));`}
|
|
@@ -714,20 +732,27 @@
|
|
|
714
732
|
{@const isGroupSelected = (() => {
|
|
715
733
|
const idx = thumbGroup.index;
|
|
716
734
|
const first = thumbnails[idx];
|
|
717
|
-
|
|
735
|
+
// Only check second canvas if this is a paired group (not a single page)
|
|
736
|
+
const isPairedGroup =
|
|
737
|
+
idx >= viewerState.pagedOffset;
|
|
738
|
+
const second = isPairedGroup
|
|
739
|
+
? thumbnails[idx + 1]
|
|
740
|
+
: null;
|
|
718
741
|
return (
|
|
719
742
|
viewerState.canvasId === first?.id ||
|
|
720
|
-
viewerState.canvasId === second
|
|
743
|
+
(second && viewerState.canvasId === second.id)
|
|
721
744
|
);
|
|
722
745
|
})()}
|
|
723
746
|
<button
|
|
724
|
-
class=
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
747
|
+
class={[
|
|
748
|
+
'group flex flex-col gap-1 p-1 rounded hover:bg-base-200 transition-colors text-left relative shrink-0 overflow-hidden',
|
|
749
|
+
isHorizontal && 'w-auto',
|
|
750
|
+
!isHorizontal &&
|
|
751
|
+
thumbGroup.srcs.length > 1 &&
|
|
752
|
+
'col-span-2',
|
|
753
|
+
isGroupSelected &&
|
|
754
|
+
'ring-2 ring-primary bg-primary/5',
|
|
755
|
+
]}
|
|
731
756
|
style={isHorizontal
|
|
732
757
|
? `height: ${fixedHeight + (thumbGroup.labels.length > 1 ? 40 : 24)}px`
|
|
733
758
|
: ''}
|
|
@@ -738,35 +763,48 @@
|
|
|
738
763
|
)}"
|
|
739
764
|
>
|
|
740
765
|
<div
|
|
741
|
-
class=
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
766
|
+
class={[
|
|
767
|
+
isHorizontal && 'h-full w-auto flex-row',
|
|
768
|
+
!isHorizontal &&
|
|
769
|
+
thumbGroup.srcs.length > 1 &&
|
|
770
|
+
'aspect-3/2 w-full',
|
|
771
|
+
!isHorizontal &&
|
|
772
|
+
thumbGroup.srcs.length <= 1 &&
|
|
773
|
+
'aspect-3/4 w-full',
|
|
774
|
+
'bg-base-300 rounded overflow-hidden relative flex items-center justify-center gap-px',
|
|
775
|
+
isRTL && 'flex-row-reverse',
|
|
776
|
+
]}
|
|
748
777
|
style={isHorizontal
|
|
749
778
|
? `height: ${fixedHeight}px`
|
|
750
779
|
: ''}
|
|
751
780
|
>
|
|
752
781
|
<div
|
|
753
|
-
class=
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
782
|
+
class={[
|
|
783
|
+
'flex items-center justify-center overflow-hidden',
|
|
784
|
+
isHorizontal && 'h-full w-auto',
|
|
785
|
+
!isHorizontal && 'h-full',
|
|
786
|
+
!isHorizontal &&
|
|
787
|
+
thumbGroup.srcs.length > 1 &&
|
|
788
|
+
'w-1/2',
|
|
789
|
+
!isHorizontal &&
|
|
790
|
+
thumbGroup.srcs.length <= 1 &&
|
|
791
|
+
'w-full',
|
|
792
|
+
]}
|
|
759
793
|
>
|
|
760
794
|
{#if thumbGroup.srcs[0]}
|
|
761
795
|
<img
|
|
762
796
|
src={thumbGroup.srcs[0]}
|
|
763
797
|
alt={thumbGroup.labels[0]}
|
|
764
|
-
class=
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
798
|
+
class={[
|
|
799
|
+
'object-contain',
|
|
800
|
+
isHorizontal && 'h-full w-auto',
|
|
801
|
+
!isHorizontal &&
|
|
802
|
+
'w-full h-full',
|
|
803
|
+
thumbGroup.srcs.length > 1 &&
|
|
804
|
+
'object-right',
|
|
805
|
+
thumbGroup.srcs.length <= 1 &&
|
|
806
|
+
'object-center',
|
|
807
|
+
]}
|
|
770
808
|
loading="lazy"
|
|
771
809
|
draggable="false"
|
|
772
810
|
/>
|
|
@@ -778,17 +816,23 @@
|
|
|
778
816
|
</div>
|
|
779
817
|
{#if thumbGroup.srcs.length > 1}
|
|
780
818
|
<div
|
|
781
|
-
class=
|
|
782
|
-
|
|
783
|
-
|
|
819
|
+
class={[
|
|
820
|
+
'flex items-center justify-center overflow-hidden',
|
|
821
|
+
isHorizontal && 'h-full w-auto',
|
|
822
|
+
!isHorizontal && 'h-full w-1/2',
|
|
823
|
+
]}
|
|
784
824
|
>
|
|
785
825
|
{#if thumbGroup.srcs[1]}
|
|
786
826
|
<img
|
|
787
827
|
src={thumbGroup.srcs[1]}
|
|
788
828
|
alt={thumbGroup.labels[1]}
|
|
789
|
-
class=
|
|
790
|
-
|
|
791
|
-
|
|
829
|
+
class={[
|
|
830
|
+
'object-contain object-left',
|
|
831
|
+
isHorizontal &&
|
|
832
|
+
'h-full w-auto',
|
|
833
|
+
!isHorizontal &&
|
|
834
|
+
'w-full h-full',
|
|
835
|
+
]}
|
|
792
836
|
loading="lazy"
|
|
793
837
|
draggable="false"
|
|
794
838
|
/>
|
|
@@ -801,9 +845,11 @@
|
|
|
801
845
|
{/if}
|
|
802
846
|
</div>
|
|
803
847
|
<div
|
|
804
|
-
class=
|
|
805
|
-
|
|
806
|
-
|
|
848
|
+
class={[
|
|
849
|
+
'text-xs font-medium opacity-70 group-hover:opacity-100 overflow-hidden',
|
|
850
|
+
isHorizontal && 'w-0 min-w-full',
|
|
851
|
+
!isHorizontal && 'w-full',
|
|
852
|
+
]}
|
|
807
853
|
title="{thumbGroup.index + 1}. {thumbGroup
|
|
808
854
|
.labels[0]}{thumbGroup.labels.length > 1
|
|
809
855
|
? ` / ${thumbGroup.index + 2}. ${thumbGroup.labels[1]}`
|
|
@@ -843,11 +889,12 @@
|
|
|
843
889
|
{:else}
|
|
844
890
|
{#each thumbnails as thumb}
|
|
845
891
|
<button
|
|
846
|
-
class=
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
892
|
+
class={[
|
|
893
|
+
'group flex flex-col gap-1 p-1 rounded hover:bg-base-200 transition-colors text-left relative shrink-0',
|
|
894
|
+
isHorizontal && 'w-auto',
|
|
895
|
+
viewerState.canvasId === thumb.id &&
|
|
896
|
+
'ring-2 ring-primary bg-primary/5',
|
|
897
|
+
]}
|
|
851
898
|
style={isHorizontal
|
|
852
899
|
? `height: ${fixedHeight + 24}px`
|
|
853
900
|
: ''}
|
|
@@ -856,9 +903,11 @@
|
|
|
856
903
|
aria-label="Select canvas {thumb.label}"
|
|
857
904
|
>
|
|
858
905
|
<div
|
|
859
|
-
class=
|
|
860
|
-
|
|
861
|
-
|
|
906
|
+
class={[
|
|
907
|
+
isHorizontal && 'h-full w-auto',
|
|
908
|
+
!isHorizontal && 'aspect-3/4 w-full',
|
|
909
|
+
'bg-base-300 rounded overflow-hidden relative flex items-center justify-center',
|
|
910
|
+
]}
|
|
862
911
|
style={isHorizontal
|
|
863
912
|
? `height: ${fixedHeight}px`
|
|
864
913
|
: ''}
|
|
@@ -867,9 +916,11 @@
|
|
|
867
916
|
<img
|
|
868
917
|
src={thumb.src}
|
|
869
918
|
alt={thumb.label}
|
|
870
|
-
class=
|
|
871
|
-
|
|
872
|
-
|
|
919
|
+
class={[
|
|
920
|
+
'object-contain',
|
|
921
|
+
isHorizontal && 'h-full w-auto',
|
|
922
|
+
!isHorizontal && 'w-full h-full',
|
|
923
|
+
]}
|
|
873
924
|
loading="lazy"
|
|
874
925
|
draggable="false"
|
|
875
926
|
/>
|
|
@@ -916,10 +967,11 @@
|
|
|
916
967
|
<!-- Drop Zones -->
|
|
917
968
|
<!-- Top -->
|
|
918
969
|
<div
|
|
919
|
-
class=
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
970
|
+
class={[
|
|
971
|
+
'absolute top-2 left-2 right-2 h-16 rounded-xl border-4 border-dashed border-primary/40 z-999 pointer-events-none flex items-center justify-center transition-all duration-200',
|
|
972
|
+
viewerState.dragOverSide === 'top' && 'bg-primary/20 scale-105',
|
|
973
|
+
viewerState.dragOverSide !== 'top' && 'bg-base-100/50',
|
|
974
|
+
]}
|
|
923
975
|
role="group"
|
|
924
976
|
>
|
|
925
977
|
<span class="font-bold text-primary opacity-50">Dock Top</span>
|
|
@@ -927,10 +979,12 @@
|
|
|
927
979
|
|
|
928
980
|
<!-- Bottom -->
|
|
929
981
|
<div
|
|
930
|
-
class=
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
982
|
+
class={[
|
|
983
|
+
'absolute bottom-2 left-2 right-2 h-16 rounded-xl border-4 border-dashed border-primary/40 z-999 pointer-events-none flex items-center justify-center transition-all duration-200',
|
|
984
|
+
viewerState.dragOverSide === 'bottom' &&
|
|
985
|
+
'bg-primary/20 scale-105',
|
|
986
|
+
viewerState.dragOverSide !== 'bottom' && 'bg-base-100/50',
|
|
987
|
+
]}
|
|
934
988
|
role="group"
|
|
935
989
|
>
|
|
936
990
|
<span class="font-bold text-primary opacity-50">Dock Bottom</span>
|
|
@@ -938,10 +992,12 @@
|
|
|
938
992
|
|
|
939
993
|
<!-- Left -->
|
|
940
994
|
<div
|
|
941
|
-
class=
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
995
|
+
class={[
|
|
996
|
+
'absolute top-2 bottom-2 left-2 w-16 rounded-xl border-4 border-dashed border-primary/40 z-999 pointer-events-none flex items-center justify-center transition-all duration-200',
|
|
997
|
+
viewerState.dragOverSide === 'left' &&
|
|
998
|
+
'bg-primary/20 scale-105',
|
|
999
|
+
viewerState.dragOverSide !== 'left' && 'bg-base-100/50',
|
|
1000
|
+
]}
|
|
945
1001
|
role="group"
|
|
946
1002
|
>
|
|
947
1003
|
<span
|
|
@@ -952,10 +1008,12 @@
|
|
|
952
1008
|
|
|
953
1009
|
<!-- Right -->
|
|
954
1010
|
<div
|
|
955
|
-
class=
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
1011
|
+
class={[
|
|
1012
|
+
'absolute top-2 bottom-2 right-2 w-16 rounded-xl border-4 border-dashed border-primary/40 z-999 pointer-events-none flex items-center justify-center transition-all duration-300',
|
|
1013
|
+
viewerState.dragOverSide === 'right' &&
|
|
1014
|
+
'bg-primary/20 scale-105',
|
|
1015
|
+
viewerState.dragOverSide !== 'right' && 'bg-base-100/50',
|
|
1016
|
+
]}
|
|
959
1017
|
role="group"
|
|
960
1018
|
>
|
|
961
1019
|
<span
|
|
@@ -575,7 +575,7 @@
|
|
|
575
575
|
{#if internalViewerState.showThumbnailGallery && internalViewerState.dockSide === 'top'}
|
|
576
576
|
<div
|
|
577
577
|
class="flex-none w-full pointer-events-auto relative z-20"
|
|
578
|
-
style="height: {internalViewerState.galleryFixedHeight +
|
|
578
|
+
style="height: {internalViewerState.galleryFixedHeight + 55}px"
|
|
579
579
|
>
|
|
580
580
|
<ThumbnailGallery {canvases} />
|
|
581
581
|
</div>
|
|
@@ -642,7 +642,7 @@
|
|
|
642
642
|
{#if internalViewerState.showThumbnailGallery && internalViewerState.dockSide === 'bottom'}
|
|
643
643
|
<div
|
|
644
644
|
class="flex-none w-full pointer-events-auto relative z-20"
|
|
645
|
-
style="height: {internalViewerState.galleryFixedHeight +
|
|
645
|
+
style="height: {internalViewerState.galleryFixedHeight + 55}px"
|
|
646
646
|
>
|
|
647
647
|
<ThumbnailGallery {canvases} />
|
|
648
648
|
</div>
|