triiiceratops 0.8.2 → 0.9.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 (89) hide show
  1. package/dist/components/AnnotationOverlay.svelte +288 -0
  2. package/dist/components/AnnotationOverlay.svelte.d.ts +3 -0
  3. package/dist/components/CanvasNavigation.svelte +32 -0
  4. package/dist/components/CanvasNavigation.svelte.d.ts +11 -0
  5. package/dist/components/DemoHeader.svelte +703 -0
  6. package/dist/components/DemoHeader.svelte.d.ts +9 -0
  7. package/dist/components/FloatingMenu.svelte +208 -0
  8. package/dist/components/FloatingMenu.svelte.d.ts +3 -0
  9. package/dist/components/LeftFab.svelte +69 -0
  10. package/dist/components/LeftFab.svelte.d.ts +3 -0
  11. package/dist/components/MetadataDialog.svelte +151 -0
  12. package/dist/components/MetadataDialog.svelte.d.ts +3 -0
  13. package/dist/components/OSDViewer.svelte +260 -0
  14. package/dist/components/OSDViewer.svelte.d.ts +8 -0
  15. package/dist/components/SearchPanel.svelte +150 -0
  16. package/dist/components/SearchPanel.svelte.d.ts +3 -0
  17. package/dist/components/ThemeToggle.svelte +118 -0
  18. package/dist/components/ThemeToggle.svelte.d.ts +3 -0
  19. package/dist/components/ThumbnailGallery.svelte +601 -0
  20. package/dist/components/ThumbnailGallery.svelte.d.ts +36 -0
  21. package/dist/components/TriiiceratopsViewer.svelte +434 -0
  22. package/dist/components/TriiiceratopsViewer.svelte.d.ts +20 -0
  23. package/dist/components/TriiiceratopsViewerElement.svelte +139 -0
  24. package/dist/components/TriiiceratopsViewerElement.svelte.d.ts +27 -0
  25. package/dist/components/TriiiceratopsViewerElementImage.svelte +143 -0
  26. package/dist/components/TriiiceratopsViewerElementImage.svelte.d.ts +27 -0
  27. package/dist/custom-element-image.d.ts +1 -0
  28. package/dist/custom-element-image.js +2 -0
  29. package/dist/custom-element.d.ts +1 -0
  30. package/dist/custom-element.js +3 -0
  31. package/dist/{src/lib/index.d.ts → index.d.ts} +1 -0
  32. package/dist/index.js +10 -4153
  33. package/dist/plugins/image-manipulation/ImageManipulationPanel.svelte +134 -0
  34. package/dist/plugins/image-manipulation/ImageManipulationPanel.svelte.d.ts +10 -0
  35. package/dist/{src/lib/plugins → plugins}/image-manipulation/ImageManipulationPlugin.svelte.d.ts +2 -2
  36. package/dist/plugins/image-manipulation/ImageManipulationPlugin.svelte.js +122 -0
  37. package/dist/{src/lib/plugins → plugins}/image-manipulation/filters.d.ts +1 -1
  38. package/dist/plugins/image-manipulation/filters.js +48 -0
  39. package/dist/plugins/image-manipulation/index.js +2 -0
  40. package/dist/plugins/image-manipulation/types.js +7 -0
  41. package/dist/state/i18n.svelte.d.ts +4 -0
  42. package/dist/state/i18n.svelte.js +18 -0
  43. package/dist/state/manifests.svelte.js +210 -0
  44. package/dist/state/manifests.test.d.ts +1 -0
  45. package/dist/state/manifests.test.js +242 -0
  46. package/dist/{src/lib/state → state}/viewer.svelte.d.ts +4 -4
  47. package/dist/state/viewer.svelte.js +693 -0
  48. package/dist/theme/colorUtils.js +196 -0
  49. package/dist/theme/colorUtils.test.d.ts +1 -0
  50. package/dist/theme/colorUtils.test.js +90 -0
  51. package/dist/theme/index.js +52 -0
  52. package/dist/{src/lib/theme → theme}/themeManager.d.ts +4 -1
  53. package/dist/theme/themeManager.js +177 -0
  54. package/dist/theme/types.js +40 -0
  55. package/dist/triiiceratops-bundle.js +4676 -0
  56. package/dist/types/config.js +1 -0
  57. package/dist/{src/lib/types → types}/plugin.d.ts +3 -3
  58. package/dist/types/plugin.js +36 -0
  59. package/dist/utils/annotationAdapter.js +354 -0
  60. package/dist/utils/annotationAdapter.test.d.ts +1 -0
  61. package/dist/utils/annotationAdapter.test.js +91 -0
  62. package/package.json +6 -5
  63. package/dist/plugin-CHYleMsW.js +0 -538
  64. package/dist/plugins/image-manipulation.js +0 -411
  65. package/dist/src/lib/components/AnnotationOverlay.svelte.d.ts +0 -1
  66. package/dist/src/lib/components/CanvasNavigation.svelte.d.ts +0 -1
  67. package/dist/src/lib/components/FloatingMenu.svelte.d.ts +0 -1
  68. package/dist/src/lib/components/LeftFab.svelte.d.ts +0 -1
  69. package/dist/src/lib/components/MetadataDialog.svelte.d.ts +0 -1
  70. package/dist/src/lib/components/OSDViewer.svelte.d.ts +0 -1
  71. package/dist/src/lib/components/SearchPanel.svelte.d.ts +0 -1
  72. package/dist/src/lib/components/ThumbnailGallery.svelte.d.ts +0 -1
  73. package/dist/src/lib/components/TriiiceratopsViewer.svelte.d.ts +0 -1
  74. package/dist/src/lib/custom-element-image.d.ts +0 -0
  75. package/dist/src/lib/custom-element.d.ts +0 -0
  76. package/dist/src/lib/paraglide/messages/de.d.ts +0 -96
  77. package/dist/src/lib/paraglide/messages/en.d.ts +0 -96
  78. package/dist/src/lib/paraglide/messages.d.ts +0 -272
  79. package/dist/src/lib/paraglide/runtime.d.ts +0 -52
  80. package/dist/src/lib/plugins/image-manipulation/ImageManipulationPanel.svelte.d.ts +0 -1
  81. package/dist/src/lib/state/i18n.svelte.d.ts +0 -5
  82. /package/dist/{src/lib/plugins → plugins}/image-manipulation/index.d.ts +0 -0
  83. /package/dist/{src/lib/plugins → plugins}/image-manipulation/types.d.ts +0 -0
  84. /package/dist/{src/lib/state → state}/manifests.svelte.d.ts +0 -0
  85. /package/dist/{src/lib/theme → theme}/colorUtils.d.ts +0 -0
  86. /package/dist/{src/lib/theme → theme}/index.d.ts +0 -0
  87. /package/dist/{src/lib/theme → theme}/types.d.ts +0 -0
  88. /package/dist/{src/lib/types → types}/config.d.ts +0 -0
  89. /package/dist/{src/lib/utils → utils}/annotationAdapter.d.ts +0 -0
@@ -0,0 +1,9 @@
1
+ declare const DemoHeader: import("svelte").Component<{
2
+ manifestUrl?: any;
3
+ onLoad: any;
4
+ viewerMode?: string;
5
+ canvasId?: string;
6
+ config?: Record<string, any>;
7
+ }, {}, "canvasId" | "config" | "manifestUrl" | "viewerMode">;
8
+ type DemoHeader = ReturnType<typeof DemoHeader>;
9
+ export default DemoHeader;
@@ -0,0 +1,208 @@
1
+ <script lang="ts">
2
+ import { getContext } from 'svelte';
3
+ import ChatCenteredText from 'phosphor-svelte/lib/ChatCenteredText';
4
+ import CornersIn from 'phosphor-svelte/lib/CornersIn';
5
+ import CornersOut from 'phosphor-svelte/lib/CornersOut';
6
+ import X from 'phosphor-svelte/lib/X';
7
+ import Info from 'phosphor-svelte/lib/Info';
8
+ import MagnifyingGlass from 'phosphor-svelte/lib/MagnifyingGlass';
9
+ import List from 'phosphor-svelte/lib/List';
10
+ import Slideshow from 'phosphor-svelte/lib/Slideshow';
11
+ import { VIEWER_STATE_KEY, type ViewerState } from '../state/viewer.svelte';
12
+ import { m } from '../state/i18n.svelte';
13
+
14
+ const viewerState = getContext<ViewerState>(VIEWER_STATE_KEY);
15
+
16
+ const menuConfig = $derived(viewerState.config.rightMenu || {});
17
+
18
+ const showSearch = $derived(menuConfig.showSearch !== false);
19
+ const showGallery = $derived(menuConfig.showGallery !== false);
20
+ const showFullscreen = $derived(menuConfig.showFullscreen !== false);
21
+ const showAnnotations = $derived(menuConfig.showAnnotations !== false);
22
+ const showInfo = $derived(menuConfig.showInfo !== false);
23
+
24
+ const activeButtons = $derived(
25
+ [
26
+ showSearch ? 'search' : null,
27
+ showGallery ? 'gallery' : null,
28
+ showFullscreen ? 'fullscreen' : null,
29
+ showAnnotations ? 'annotations' : null,
30
+ showInfo ? 'info' : null,
31
+ ].filter((b): b is string => b !== null),
32
+ );
33
+ </script>
34
+
35
+ {#snippet searchBtn()}
36
+ <button
37
+ aria-label={m.toggle_search()}
38
+ class={[
39
+ 'btn btn-circle btn-lg shadow-lg',
40
+ viewerState.showSearchPanel ? 'btn-primary' : 'btn-neutral',
41
+ ]}
42
+ onclick={() => viewerState.toggleSearchPanel()}
43
+ >
44
+ <MagnifyingGlass size={28} weight="bold" />
45
+ </button>
46
+ {/snippet}
47
+
48
+ {#snippet galleryBtn()}
49
+ <button
50
+ aria-label={viewerState.showThumbnailGallery
51
+ ? m.hide_gallery()
52
+ : m.show_gallery()}
53
+ class="btn btn-lg btn-circle shadow-lg {viewerState.showThumbnailGallery
54
+ ? 'btn-info'
55
+ : 'btn-neutral'}"
56
+ onclick={() => viewerState.toggleThumbnailGallery()}
57
+ >
58
+ <Slideshow size={28} weight="bold" />
59
+ </button>
60
+ {/snippet}
61
+
62
+ {#snippet fullscreenBtn()}
63
+ <button
64
+ class="btn btn-circle btn-lg shadow-lg transition-all duration-300 ease-out {viewerState.isFullScreen
65
+ ? 'btn-warning'
66
+ : 'btn-neutral'}"
67
+ onclick={() => viewerState.toggleFullScreen()}
68
+ >
69
+ {#if viewerState.isFullScreen}
70
+ <CornersIn size={28} weight="bold" />
71
+ {:else}
72
+ <CornersOut size={28} weight="bold" />
73
+ {/if}
74
+ </button>
75
+ {/snippet}
76
+
77
+ {#snippet annotationsBtn()}
78
+ <button
79
+ aria-label={m.toggle_annotations()}
80
+ class="btn btn-lg btn-circle shadow-lg {viewerState.showAnnotations
81
+ ? 'btn-error'
82
+ : 'btn-neutral'}"
83
+ onclick={() => viewerState.toggleAnnotations()}
84
+ >
85
+ <ChatCenteredText size={28} weight="bold" />
86
+ </button>
87
+ {/snippet}
88
+
89
+ {#snippet infoBtn()}
90
+ <button
91
+ aria-label={m.toggle_metadata()}
92
+ class="btn btn-lg btn-circle shadow-lg {viewerState.showMetadataDialog
93
+ ? 'btn-info'
94
+ : 'btn-neutral'}"
95
+ onclick={() => viewerState.toggleMetadataDialog()}
96
+ >
97
+ <Info size={28} weight="bold" />
98
+ </button>
99
+ {/snippet}
100
+
101
+ {#if activeButtons.length === 1}
102
+ <div class="absolute z-600 bottom-6 right-6">
103
+ {#if showSearch}
104
+ <div class="tooltip tooltip-left" data-tip={m.search()}>
105
+ {@render searchBtn()}
106
+ </div>
107
+ {/if}
108
+ {#if showGallery}
109
+ <div
110
+ class="tooltip tooltip-left"
111
+ data-tip={viewerState.showThumbnailGallery
112
+ ? m.hide_gallery()
113
+ : m.show_gallery()}
114
+ >
115
+ {@render galleryBtn()}
116
+ </div>
117
+ {/if}
118
+ {#if showFullscreen}
119
+ <div
120
+ class="tooltip tooltip-left"
121
+ data-tip={viewerState.isFullScreen
122
+ ? m.exit_full_screen()
123
+ : m.enter_full_screen()}
124
+ >
125
+ {@render fullscreenBtn()}
126
+ </div>
127
+ {/if}
128
+ {#if showAnnotations}
129
+ <div
130
+ class="tooltip tooltip-top"
131
+ data-tip={viewerState.showAnnotations
132
+ ? m.hide_annotations()
133
+ : m.show_annotations()}
134
+ >
135
+ {@render annotationsBtn()}
136
+ </div>
137
+ {/if}
138
+ {#if showInfo}
139
+ <div class="tooltip tooltip-top" data-tip={m.metadata()}>
140
+ {@render infoBtn()}
141
+ </div>
142
+ {/if}
143
+ </div>
144
+ {:else if activeButtons.length > 1}
145
+ <div
146
+ class="fab fab-flower fab-top-left absolute z-600 pointer-events-auto bottom-6 right-6"
147
+ >
148
+ <!-- Trigger button: focusable div (Safari bug workaround) - hidden when FAB is open -->
149
+ <div
150
+ tabindex="0"
151
+ role="button"
152
+ class="btn btn-lg btn-primary btn-circle shadow-xl"
153
+ >
154
+ <span class="sr-only">{m.menu()}</span>
155
+ <List size={32} weight="bold" />
156
+ </div>
157
+
158
+ <!-- fab-main-action: replaces the trigger button when FAB is open -->
159
+ <div class="fab-main-action tooltip tooltip-top" data-tip={m.search()}>
160
+ {@render searchBtn()}
161
+ </div>
162
+
163
+ <!-- buttons that show up when FAB is open (max 4 for flower layout) -->
164
+
165
+ <!-- Gallery Toggle -->
166
+ {#if showGallery}
167
+ <div
168
+ class="tooltip tooltip-left"
169
+ data-tip={viewerState.showThumbnailGallery
170
+ ? m.hide_gallery()
171
+ : m.show_gallery()}
172
+ >
173
+ {@render galleryBtn()}
174
+ </div>
175
+ {/if}
176
+
177
+ <!-- Full Screen Toggle -->
178
+ {#if showFullscreen}
179
+ <div
180
+ class="tooltip tooltip-left"
181
+ data-tip={viewerState.isFullScreen
182
+ ? m.exit_full_screen()
183
+ : m.enter_full_screen()}
184
+ >
185
+ {@render fullscreenBtn()}
186
+ </div>
187
+ {/if}
188
+
189
+ <!-- Annotations Toggle -->
190
+ {#if showAnnotations}
191
+ <div
192
+ class="tooltip tooltip-top"
193
+ data-tip={viewerState.showAnnotations
194
+ ? m.hide_annotations()
195
+ : m.show_annotations()}
196
+ >
197
+ {@render annotationsBtn()}
198
+ </div>
199
+ {/if}
200
+
201
+ <!-- Metadata Toggle -->
202
+ {#if showInfo}
203
+ <div class="tooltip tooltip-top" data-tip={m.metadata()}>
204
+ {@render infoBtn()}
205
+ </div>
206
+ {/if}
207
+ </div>
208
+ {/if}
@@ -0,0 +1,3 @@
1
+ declare const FloatingMenu: import("svelte").Component<Record<string, never>, {}, "">;
2
+ type FloatingMenu = ReturnType<typeof FloatingMenu>;
3
+ export default FloatingMenu;
@@ -0,0 +1,69 @@
1
+ <script lang="ts">
2
+ import { getContext } from 'svelte';
3
+ import PuzzlePiece from 'phosphor-svelte/lib/PuzzlePiece';
4
+ import X from 'phosphor-svelte/lib/X';
5
+ import { VIEWER_STATE_KEY, type ViewerState } from '../state/viewer.svelte';
6
+ import { m } from '../state/i18n.svelte';
7
+
8
+ const viewerState = getContext<ViewerState>(VIEWER_STATE_KEY);
9
+
10
+ let sortedPluginButtons = $derived(
11
+ [...viewerState.pluginMenuButtons].sort(
12
+ (a, b) => (a.order ?? 100) - (b.order ?? 100),
13
+ ),
14
+ );
15
+
16
+ let isOpen = $state(false);
17
+
18
+ function toggleOpen() {
19
+ isOpen = !isOpen;
20
+ }
21
+ </script>
22
+
23
+ {#if sortedPluginButtons.length > 0}
24
+ <div
25
+ class="absolute left-6 bottom-6 z-50 pointer-events-auto flex flex-col items-start transition-all duration-300"
26
+ >
27
+ <!-- Plugin Buttons Stack -->
28
+ <div
29
+ class="flex flex-col-reverse gap-3 mb-3 transition-all duration-300 origin-bottom {isOpen
30
+ ? 'opacity-100 translate-y-0 scale-100'
31
+ : 'opacity-0 translate-y-4 scale-90 pointer-events-none'}"
32
+ >
33
+ {#each sortedPluginButtons as button (button.id)}
34
+ {@const Icon = button.icon}
35
+ <div class="tooltip tooltip-right" data-tip={button.tooltip}>
36
+ <button
37
+ aria-label={button.tooltip}
38
+ class="btn btn-lg btn-circle shadow-lg {button.isActive?.()
39
+ ? (button.activeClass ?? 'btn-primary')
40
+ : 'btn-neutral'}"
41
+ onclick={() => {
42
+ button.onClick();
43
+ isOpen = false;
44
+ }}
45
+ >
46
+ <Icon size={28} weight="bold" />
47
+ </button>
48
+ </div>
49
+ {/each}
50
+ </div>
51
+
52
+ <!-- Main Toggle Button -->
53
+ <div class="tooltip tooltip-right" data-tip={m.plugins_tooltip()}>
54
+ <button
55
+ class="btn btn-lg btn-secondary btn-circle shadow-xl transition-transform duration-300 {isOpen
56
+ ? 'rotate-90'
57
+ : ''}"
58
+ aria-label={m.plugins_tooltip()}
59
+ onclick={toggleOpen}
60
+ >
61
+ {#if isOpen}
62
+ <X size={28} weight="bold" />
63
+ {:else}
64
+ <PuzzlePiece size={28} weight="bold" />
65
+ {/if}
66
+ </button>
67
+ </div>
68
+ </div>
69
+ {/if}
@@ -0,0 +1,3 @@
1
+ declare const LeftFab: import("svelte").Component<Record<string, never>, {}, "">;
2
+ type LeftFab = ReturnType<typeof LeftFab>;
3
+ export default LeftFab;
@@ -0,0 +1,151 @@
1
+ <script lang="ts">
2
+ import { getContext } from 'svelte';
3
+ import { VIEWER_STATE_KEY, type ViewerState } from '../state/viewer.svelte';
4
+ import { m, language } from '../state/i18n.svelte';
5
+
6
+ const viewerState = getContext<ViewerState>(VIEWER_STATE_KEY);
7
+
8
+ let manifest = $derived(viewerState.manifest);
9
+
10
+ // Helper to extract metadata
11
+ let metadata = $derived.by(() => {
12
+ const currentLang = language.current;
13
+ if (!manifest) return [];
14
+
15
+ // Manifesto's getMetadata() returns an array of { label: ..., value: ... } objects
16
+ // The values might be strings or arrays of objects (LanguageMap)
17
+ const rawMetadata = manifest.getMetadata();
18
+
19
+ if (!rawMetadata) return [];
20
+
21
+ return rawMetadata.map((item: any) => {
22
+ let label = '';
23
+ let value = '';
24
+
25
+ // Helper to pick best language
26
+ const pickLang = (val: string | any[]) => {
27
+ if (typeof val === 'string') return val;
28
+ if (Array.isArray(val)) {
29
+ // exact match
30
+ let match = val.find(
31
+ (x: any) =>
32
+ x.locale === currentLang ||
33
+ x.language === currentLang,
34
+ );
35
+ // fallback to en
36
+ if (!match)
37
+ match = val.find(
38
+ (x: any) =>
39
+ x.locale === 'en' || x.language === 'en',
40
+ );
41
+ // fallback to none/null
42
+ if (!match)
43
+ match = val.find((x: any) => !x.locale && !x.language);
44
+ // fallback to first
45
+ if (!match) match = val[0];
46
+
47
+ return match ? match.value : '';
48
+ }
49
+ return String(val);
50
+ };
51
+
52
+ // Handle Label
53
+ if (item.getLabel) {
54
+ label = pickLang(item.getLabel());
55
+ } else if (item.label) {
56
+ label = pickLang(item.label);
57
+ }
58
+
59
+ // Handle Value
60
+ if (item.getValue) {
61
+ value = pickLang(item.getValue());
62
+ } else if (item.value) {
63
+ value = pickLang(item.value);
64
+ }
65
+
66
+ return { label, value };
67
+ });
68
+ });
69
+
70
+ // Also get top-level description, attribution, license/rights
71
+ let description = $derived(manifest ? manifest.getDescription() : '');
72
+ let attribution = $derived(
73
+ manifest ? manifest.getRequiredStatement()?.getValue() : '',
74
+ );
75
+ // getRequiredStatement usually returns { label: ..., value: ... } or similar structure that supports getValue()
76
+
77
+ let license = $derived(manifest ? manifest.getLicense() : '');
78
+ </script>
79
+
80
+ <!-- Modal -->
81
+ <dialog class="modal" open={viewerState.showMetadataDialog}>
82
+ <div class="modal-box w-11/12 max-w-5xl">
83
+ <form method="dialog">
84
+ <button
85
+ class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"
86
+ onclick={() => viewerState.toggleMetadataDialog()}>✕</button
87
+ >
88
+ </form>
89
+
90
+ <h3 class="font-bold text-lg mb-4">
91
+ {manifest
92
+ ? manifest.getLabel().length && manifest.getLabel()[0]
93
+ ? manifest.getLabel()[0].value
94
+ : m.metadata_label_fallback()
95
+ : m.loading()}
96
+ </h3>
97
+
98
+ <div class="py-4 overflow-y-auto max-h-[70vh]">
99
+ {#if description}
100
+ <div class="mb-6 prose">
101
+ <p>{@html description}</p>
102
+ </div>
103
+ {/if}
104
+
105
+ <dl class="grid grid-cols-1 md:grid-cols-[200px_1fr]">
106
+ {#if attribution}
107
+ <dt class="font-bold text-lg opacity-70 mt-6">
108
+ {m.attribution()}
109
+ </dt>
110
+ <dd class="text-sm ps-2">{@html attribution}</dd>
111
+ {/if}
112
+
113
+ {#if license}
114
+ <dt class="font-bold text-lg opacity-70 mt-6">
115
+ {m.license()}
116
+ </dt>
117
+ <dd class="text-sm ps-2">
118
+ <a
119
+ href={license}
120
+ target="_blank"
121
+ rel="noreferrer"
122
+ class="link link-primary break-all">{license}</a
123
+ >
124
+ </dd>
125
+ {/if}
126
+
127
+ {#each metadata as item}
128
+ <dt class="font-bold text-lg opacity-70 mt-6">
129
+ {item.label}
130
+ </dt>
131
+ <dd class="text-sm ps-2">{@html item.value}</dd>
132
+ {/each}
133
+ </dl>
134
+ </div>
135
+
136
+ <div class="modal-action">
137
+ <form method="dialog">
138
+ <button
139
+ class="btn"
140
+ onclick={() => viewerState.toggleMetadataDialog()}
141
+ >{m.close()}</button
142
+ >
143
+ </form>
144
+ </div>
145
+ </div>
146
+ <form method="dialog" class="modal-backdrop">
147
+ <button onclick={() => viewerState.toggleMetadataDialog()}
148
+ >{m.close()}</button
149
+ >
150
+ </form>
151
+ </dialog>
@@ -0,0 +1,3 @@
1
+ declare const MetadataDialog: import("svelte").Component<Record<string, never>, {}, "">;
2
+ type MetadataDialog = ReturnType<typeof MetadataDialog>;
3
+ export default MetadataDialog;