triiiceratops 0.12.3 → 0.12.5
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/dist/{ArrowCounterClockwise-CM9mGGcp.js → ArrowCounterClockwise-Bcse6skq.js} +1 -1
- package/dist/Check-D3d2XX_P.js +423 -0
- package/dist/{X-Bn7S7vUL.js → X-BsrpnzCK.js} +169 -156
- package/dist/components/DemoHeader.svelte +5 -548
- package/dist/components/SettingsMenu.svelte +507 -0
- package/dist/components/SettingsMenu.svelte.d.ts +6 -0
- package/dist/components/Toolbar.svelte +13 -2
- package/dist/components/TriiiceratopsViewer.svelte +37 -11
- package/dist/{image_filters_reset-CmWuQiOc.js → image_filters_reset-Dw23NgOZ.js} +1 -1
- package/dist/paraglide/messages/_index.d.ts +3 -0
- package/dist/paraglide/messages/_index.js +3 -0
- package/dist/paraglide/messages/demo_title.d.ts +4 -0
- package/dist/paraglide/messages/demo_title.js +34 -0
- package/dist/paraglide/messages/settings_thumbnail_height.d.ts +4 -0
- package/dist/paraglide/messages/settings_thumbnail_height.js +34 -0
- package/dist/paraglide/messages/settings_toggle_show_viewing_mode.js +3 -2
- package/dist/paraglide/messages/settings_view_configuration.d.ts +4 -0
- package/dist/paraglide/messages/settings_view_configuration.js +34 -0
- package/dist/plugins/annotation-editor.js +493 -623
- package/dist/plugins/image-manipulation.js +3 -3
- package/dist/state/viewer.svelte.d.ts +1 -0
- package/dist/state/viewer.svelte.js +6 -1
- package/dist/triiiceratops-bundle.js +1780 -1711
- package/dist/triiiceratops-element.iife.js +15 -15
- package/dist/triiiceratops.css +1 -1
- package/package.json +1 -1
- package/dist/annotation_tool_point-LoRp_nrI.js +0 -290
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { m } from '../state/i18n.svelte';
|
|
3
|
+
import Check from 'phosphor-svelte/lib/Check';
|
|
4
|
+
import Copy from 'phosphor-svelte/lib/Copy';
|
|
5
|
+
|
|
6
|
+
let { config = $bindable(), class: className = '' } = $props();
|
|
7
|
+
|
|
8
|
+
let copied = $state(false);
|
|
9
|
+
|
|
10
|
+
function copyConfig() {
|
|
11
|
+
navigator.clipboard.writeText(JSON.stringify(config, null, 2));
|
|
12
|
+
copied = true;
|
|
13
|
+
setTimeout(() => {
|
|
14
|
+
copied = false;
|
|
15
|
+
}, 2000);
|
|
16
|
+
}
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<ul class={className}>
|
|
20
|
+
<li class="menu-title px-4 py-2">
|
|
21
|
+
{m.settings_category_general()}
|
|
22
|
+
</li>
|
|
23
|
+
<li>
|
|
24
|
+
<label class="label cursor-pointer py-1">
|
|
25
|
+
<span class="label-text">{m.settings_transparent_background()}</span
|
|
26
|
+
>
|
|
27
|
+
<input
|
|
28
|
+
type="checkbox"
|
|
29
|
+
class="toggle toggle-sm"
|
|
30
|
+
bind:checked={config.transparentBackground}
|
|
31
|
+
/>
|
|
32
|
+
</label>
|
|
33
|
+
</li>
|
|
34
|
+
<li>
|
|
35
|
+
<label class="label cursor-pointer py-1">
|
|
36
|
+
<span class="label-text">{m.settings_toggle_canvas_nav()}</span>
|
|
37
|
+
<input
|
|
38
|
+
type="checkbox"
|
|
39
|
+
class="toggle toggle-sm"
|
|
40
|
+
bind:checked={config.showCanvasNav}
|
|
41
|
+
/>
|
|
42
|
+
</label>
|
|
43
|
+
</li>
|
|
44
|
+
<li>
|
|
45
|
+
<label class="label cursor-pointer py-1">
|
|
46
|
+
<span class="label-text">{m.settings_toggle_zoom_controls()}</span>
|
|
47
|
+
<input
|
|
48
|
+
type="checkbox"
|
|
49
|
+
class="toggle toggle-sm"
|
|
50
|
+
bind:checked={config.showZoomControls}
|
|
51
|
+
/>
|
|
52
|
+
</label>
|
|
53
|
+
</li>
|
|
54
|
+
|
|
55
|
+
<div class="divider my-1"></div>
|
|
56
|
+
|
|
57
|
+
<li class="menu-title px-4 py-2">
|
|
58
|
+
{m.settings_category_configuration()}
|
|
59
|
+
</li>
|
|
60
|
+
|
|
61
|
+
<li>
|
|
62
|
+
<details>
|
|
63
|
+
<summary>{m.settings_submenu_toolbar()}</summary>
|
|
64
|
+
<ul>
|
|
65
|
+
<li>
|
|
66
|
+
<label class="label cursor-pointer py-1">
|
|
67
|
+
<span class="label-text"
|
|
68
|
+
>{m.settings_toggle_show_toggle()}</span
|
|
69
|
+
>
|
|
70
|
+
<input
|
|
71
|
+
type="checkbox"
|
|
72
|
+
class="toggle toggle-sm"
|
|
73
|
+
checked={config.showToggle !== false}
|
|
74
|
+
onchange={(e) => {
|
|
75
|
+
config.showToggle = e.currentTarget.checked;
|
|
76
|
+
}}
|
|
77
|
+
/>
|
|
78
|
+
</label>
|
|
79
|
+
</li>
|
|
80
|
+
<li>
|
|
81
|
+
<label class="label cursor-pointer py-1">
|
|
82
|
+
<span class="label-text"
|
|
83
|
+
>{m.settings_toolbar_open()}</span
|
|
84
|
+
>
|
|
85
|
+
<input
|
|
86
|
+
type="checkbox"
|
|
87
|
+
class="toggle toggle-sm"
|
|
88
|
+
bind:checked={config.toolbarOpen}
|
|
89
|
+
/>
|
|
90
|
+
</label>
|
|
91
|
+
</li>
|
|
92
|
+
<li>
|
|
93
|
+
<label class="label cursor-pointer py-1">
|
|
94
|
+
<span class="label-text"
|
|
95
|
+
>{m.settings_toolbar_position()}</span
|
|
96
|
+
>
|
|
97
|
+
<select
|
|
98
|
+
class="select select-bordered select-xs w-24"
|
|
99
|
+
value={config.toolbarPosition ?? 'left'}
|
|
100
|
+
onchange={(e) => {
|
|
101
|
+
config.toolbarPosition = (
|
|
102
|
+
e.currentTarget as HTMLSelectElement
|
|
103
|
+
).value as 'left' | 'right' | 'top';
|
|
104
|
+
}}
|
|
105
|
+
>
|
|
106
|
+
<option value="left"
|
|
107
|
+
>{m.settings_position_left()}</option
|
|
108
|
+
>
|
|
109
|
+
<option value="right"
|
|
110
|
+
>{m.settings_position_right()}</option
|
|
111
|
+
>
|
|
112
|
+
<option value="top"
|
|
113
|
+
>{m.settings_position_top()}</option
|
|
114
|
+
>
|
|
115
|
+
</select>
|
|
116
|
+
</label>
|
|
117
|
+
</li>
|
|
118
|
+
<div class="divider my-1"></div>
|
|
119
|
+
<li>
|
|
120
|
+
<label class="label cursor-pointer py-1">
|
|
121
|
+
<span class="label-text"
|
|
122
|
+
>{m.settings_toggle_show_search()}</span
|
|
123
|
+
>
|
|
124
|
+
<input
|
|
125
|
+
type="checkbox"
|
|
126
|
+
class="checkbox checkbox-xs"
|
|
127
|
+
checked={config.toolbar?.showSearch ?? true}
|
|
128
|
+
onchange={(e) => {
|
|
129
|
+
if (!config.toolbar) config.toolbar = {};
|
|
130
|
+
config.toolbar.showSearch =
|
|
131
|
+
e.currentTarget.checked;
|
|
132
|
+
}}
|
|
133
|
+
/>
|
|
134
|
+
</label>
|
|
135
|
+
</li>
|
|
136
|
+
<li>
|
|
137
|
+
<label class="label cursor-pointer py-1">
|
|
138
|
+
<span class="label-text"
|
|
139
|
+
>{m.settings_toggle_show_gallery()}</span
|
|
140
|
+
>
|
|
141
|
+
<input
|
|
142
|
+
type="checkbox"
|
|
143
|
+
class="checkbox checkbox-xs"
|
|
144
|
+
checked={config.toolbar?.showGallery ?? true}
|
|
145
|
+
onchange={(e) => {
|
|
146
|
+
if (!config.toolbar) config.toolbar = {};
|
|
147
|
+
config.toolbar.showGallery =
|
|
148
|
+
e.currentTarget.checked;
|
|
149
|
+
}}
|
|
150
|
+
/>
|
|
151
|
+
</label>
|
|
152
|
+
</li>
|
|
153
|
+
<li>
|
|
154
|
+
<label class="label cursor-pointer py-1">
|
|
155
|
+
<span class="label-text"
|
|
156
|
+
>{m.settings_toggle_show_annotations()}</span
|
|
157
|
+
>
|
|
158
|
+
<input
|
|
159
|
+
type="checkbox"
|
|
160
|
+
class="checkbox checkbox-xs"
|
|
161
|
+
checked={config.toolbar?.showAnnotations ?? true}
|
|
162
|
+
onchange={(e) => {
|
|
163
|
+
if (!config.toolbar) config.toolbar = {};
|
|
164
|
+
config.toolbar.showAnnotations =
|
|
165
|
+
e.currentTarget.checked;
|
|
166
|
+
}}
|
|
167
|
+
/>
|
|
168
|
+
</label>
|
|
169
|
+
</li>
|
|
170
|
+
<li>
|
|
171
|
+
<label class="label cursor-pointer py-1">
|
|
172
|
+
<span class="label-text"
|
|
173
|
+
>{m.settings_toggle_show_fullscreen()}</span
|
|
174
|
+
>
|
|
175
|
+
<input
|
|
176
|
+
type="checkbox"
|
|
177
|
+
class="checkbox checkbox-xs"
|
|
178
|
+
checked={config.toolbar?.showFullscreen ?? true}
|
|
179
|
+
onchange={(e) => {
|
|
180
|
+
if (!config.toolbar) config.toolbar = {};
|
|
181
|
+
config.toolbar.showFullscreen =
|
|
182
|
+
e.currentTarget.checked;
|
|
183
|
+
}}
|
|
184
|
+
/>
|
|
185
|
+
</label>
|
|
186
|
+
</li>
|
|
187
|
+
<li>
|
|
188
|
+
<label class="label cursor-pointer py-1">
|
|
189
|
+
<span class="label-text"
|
|
190
|
+
>{m.settings_toggle_show_info()}</span
|
|
191
|
+
>
|
|
192
|
+
<input
|
|
193
|
+
type="checkbox"
|
|
194
|
+
class="checkbox checkbox-xs"
|
|
195
|
+
checked={config.toolbar?.showInfo ?? true}
|
|
196
|
+
onchange={(e) => {
|
|
197
|
+
if (!config.toolbar) config.toolbar = {};
|
|
198
|
+
config.toolbar.showInfo =
|
|
199
|
+
e.currentTarget.checked;
|
|
200
|
+
}}
|
|
201
|
+
/>
|
|
202
|
+
</label>
|
|
203
|
+
</li>
|
|
204
|
+
<li>
|
|
205
|
+
<label class="label cursor-pointer py-1">
|
|
206
|
+
<span class="label-text"
|
|
207
|
+
>{m.settings_toggle_show_viewing_mode()}</span
|
|
208
|
+
>
|
|
209
|
+
<input
|
|
210
|
+
type="checkbox"
|
|
211
|
+
class="checkbox checkbox-xs"
|
|
212
|
+
checked={config.toolbar?.showViewingMode ?? true}
|
|
213
|
+
onchange={(e) => {
|
|
214
|
+
if (!config.toolbar) config.toolbar = {};
|
|
215
|
+
config.toolbar.showViewingMode =
|
|
216
|
+
e.currentTarget.checked;
|
|
217
|
+
}}
|
|
218
|
+
/>
|
|
219
|
+
</label>
|
|
220
|
+
</li>
|
|
221
|
+
<li>
|
|
222
|
+
<label class="label cursor-pointer py-1">
|
|
223
|
+
<span class="label-text">{m.viewing_mode_label()}</span>
|
|
224
|
+
<select
|
|
225
|
+
class="select select-bordered select-xs"
|
|
226
|
+
value={config.viewingMode ?? 'individuals'}
|
|
227
|
+
onchange={(e) => {
|
|
228
|
+
config.viewingMode = (
|
|
229
|
+
e.currentTarget as HTMLSelectElement
|
|
230
|
+
).value as 'individuals' | 'paged';
|
|
231
|
+
}}
|
|
232
|
+
>
|
|
233
|
+
<option value="individuals"
|
|
234
|
+
>{m.viewing_mode_individuals()}</option
|
|
235
|
+
>
|
|
236
|
+
<option value="paged"
|
|
237
|
+
>{m.viewing_mode_paged()}</option
|
|
238
|
+
>
|
|
239
|
+
</select>
|
|
240
|
+
</label>
|
|
241
|
+
</li>
|
|
242
|
+
</ul>
|
|
243
|
+
</details>
|
|
244
|
+
</li>
|
|
245
|
+
|
|
246
|
+
<li>
|
|
247
|
+
<details>
|
|
248
|
+
<summary>{m.settings_submenu_gallery()}</summary>
|
|
249
|
+
<ul>
|
|
250
|
+
<li>
|
|
251
|
+
<label class="label cursor-pointer py-1">
|
|
252
|
+
<span class="label-text"
|
|
253
|
+
>{m.settings_toggle_open()}</span
|
|
254
|
+
>
|
|
255
|
+
<input
|
|
256
|
+
type="checkbox"
|
|
257
|
+
class="toggle toggle-xs"
|
|
258
|
+
checked={config.gallery?.open ?? false}
|
|
259
|
+
onchange={(e) => {
|
|
260
|
+
if (!config.gallery) config.gallery = {};
|
|
261
|
+
config.gallery.open = e.currentTarget.checked;
|
|
262
|
+
}}
|
|
263
|
+
/>
|
|
264
|
+
</label>
|
|
265
|
+
</li>
|
|
266
|
+
<li>
|
|
267
|
+
<label class="label cursor-pointer py-1">
|
|
268
|
+
<span class="label-text"
|
|
269
|
+
>{m.settings_toggle_draggable()}</span
|
|
270
|
+
>
|
|
271
|
+
<input
|
|
272
|
+
type="checkbox"
|
|
273
|
+
class="checkbox checkbox-xs"
|
|
274
|
+
checked={config.gallery?.draggable ?? true}
|
|
275
|
+
onchange={(e) => {
|
|
276
|
+
if (!config.gallery) config.gallery = {};
|
|
277
|
+
config.gallery.draggable =
|
|
278
|
+
e.currentTarget.checked;
|
|
279
|
+
}}
|
|
280
|
+
/>
|
|
281
|
+
</label>
|
|
282
|
+
</li>
|
|
283
|
+
<li>
|
|
284
|
+
<label class="label cursor-pointer py-1">
|
|
285
|
+
<span class="label-text"
|
|
286
|
+
>{m.settings_toggle_close_button()}</span
|
|
287
|
+
>
|
|
288
|
+
<input
|
|
289
|
+
type="checkbox"
|
|
290
|
+
class="checkbox checkbox-xs"
|
|
291
|
+
checked={config.gallery?.showCloseButton ?? true}
|
|
292
|
+
onchange={(e) => {
|
|
293
|
+
if (!config.gallery) config.gallery = {};
|
|
294
|
+
config.gallery.showCloseButton =
|
|
295
|
+
e.currentTarget.checked;
|
|
296
|
+
}}
|
|
297
|
+
/>
|
|
298
|
+
</label>
|
|
299
|
+
</li>
|
|
300
|
+
<li>
|
|
301
|
+
<label class="label cursor-pointer py-1 gap-2">
|
|
302
|
+
<span class="label-text"
|
|
303
|
+
>{m.settings_select_dock_position()}</span
|
|
304
|
+
>
|
|
305
|
+
<select
|
|
306
|
+
class="select select-bordered select-xs w-24"
|
|
307
|
+
value={config.gallery?.dockPosition ?? 'bottom'}
|
|
308
|
+
onchange={(e) => {
|
|
309
|
+
if (!config.gallery) config.gallery = {};
|
|
310
|
+
config.gallery.dockPosition = (
|
|
311
|
+
e.currentTarget as HTMLSelectElement
|
|
312
|
+
).value;
|
|
313
|
+
}}
|
|
314
|
+
onclick={(e) => e.stopPropagation()}
|
|
315
|
+
>
|
|
316
|
+
<option value="bottom"
|
|
317
|
+
>{m.settings_position_bottom()}</option
|
|
318
|
+
>
|
|
319
|
+
<option value="top"
|
|
320
|
+
>{m.settings_position_top()}</option
|
|
321
|
+
>
|
|
322
|
+
<option value="left"
|
|
323
|
+
>{m.settings_position_left()}</option
|
|
324
|
+
>
|
|
325
|
+
<option value="right"
|
|
326
|
+
>{m.settings_position_right()}</option
|
|
327
|
+
>
|
|
328
|
+
<option value="none"
|
|
329
|
+
>{m.settings_position_floating()}</option
|
|
330
|
+
>
|
|
331
|
+
</select>
|
|
332
|
+
</label>
|
|
333
|
+
</li>
|
|
334
|
+
<li>
|
|
335
|
+
<label class="label cursor-pointer py-1 gap-2">
|
|
336
|
+
<span class="label-text"
|
|
337
|
+
>{m.settings_thumbnail_height()}</span
|
|
338
|
+
>
|
|
339
|
+
<input
|
|
340
|
+
type="range"
|
|
341
|
+
min="50"
|
|
342
|
+
max="300"
|
|
343
|
+
value={config.gallery?.fixedHeight ?? 120}
|
|
344
|
+
class="range range-xs range-primary w-24"
|
|
345
|
+
oninput={(e) => {
|
|
346
|
+
if (!config.gallery) config.gallery = {};
|
|
347
|
+
config.gallery.fixedHeight = parseInt(
|
|
348
|
+
e.currentTarget.value,
|
|
349
|
+
);
|
|
350
|
+
}}
|
|
351
|
+
/>
|
|
352
|
+
<span class="text-xs opacity-50 w-8 text-right"
|
|
353
|
+
>{config.gallery?.fixedHeight ?? 120}px</span
|
|
354
|
+
>
|
|
355
|
+
</label>
|
|
356
|
+
</li>
|
|
357
|
+
</ul>
|
|
358
|
+
</details>
|
|
359
|
+
</li>
|
|
360
|
+
|
|
361
|
+
<li>
|
|
362
|
+
<details>
|
|
363
|
+
<summary>{m.settings_submenu_search()}</summary>
|
|
364
|
+
<ul>
|
|
365
|
+
<li>
|
|
366
|
+
<label class="label cursor-pointer py-1">
|
|
367
|
+
<span class="label-text"
|
|
368
|
+
>{m.settings_toggle_open()}</span
|
|
369
|
+
>
|
|
370
|
+
<input
|
|
371
|
+
type="checkbox"
|
|
372
|
+
class="toggle toggle-xs"
|
|
373
|
+
checked={config.search?.open ?? false}
|
|
374
|
+
onchange={(e) => {
|
|
375
|
+
if (!config.search) config.search = {};
|
|
376
|
+
config.search.open = e.currentTarget.checked;
|
|
377
|
+
}}
|
|
378
|
+
/>
|
|
379
|
+
</label>
|
|
380
|
+
</li>
|
|
381
|
+
<li>
|
|
382
|
+
<label class="label cursor-pointer py-1">
|
|
383
|
+
<span class="label-text"
|
|
384
|
+
>{m.settings_toggle_close_button()}</span
|
|
385
|
+
>
|
|
386
|
+
<input
|
|
387
|
+
type="checkbox"
|
|
388
|
+
class="checkbox checkbox-xs"
|
|
389
|
+
checked={config.search?.showCloseButton ?? true}
|
|
390
|
+
onchange={(e) => {
|
|
391
|
+
if (!config.search) config.search = {};
|
|
392
|
+
config.search.showCloseButton =
|
|
393
|
+
e.currentTarget.checked;
|
|
394
|
+
}}
|
|
395
|
+
/>
|
|
396
|
+
</label>
|
|
397
|
+
</li>
|
|
398
|
+
<li>
|
|
399
|
+
<label class="label cursor-pointer py-1 gap-2">
|
|
400
|
+
<span class="label-text"
|
|
401
|
+
>{m.settings_select_dock_position()}</span
|
|
402
|
+
>
|
|
403
|
+
<select
|
|
404
|
+
class="select select-bordered select-xs w-24"
|
|
405
|
+
value={config.search?.position ?? 'right'}
|
|
406
|
+
onchange={(e) => {
|
|
407
|
+
if (!config.search) config.search = {};
|
|
408
|
+
config.search.position = (
|
|
409
|
+
e.currentTarget as HTMLSelectElement
|
|
410
|
+
).value;
|
|
411
|
+
}}
|
|
412
|
+
onclick={(e) => e.stopPropagation()}
|
|
413
|
+
>
|
|
414
|
+
<option value="right"
|
|
415
|
+
>{m.settings_position_right()}</option
|
|
416
|
+
>
|
|
417
|
+
<option value="left"
|
|
418
|
+
>{m.settings_position_left()}</option
|
|
419
|
+
>
|
|
420
|
+
</select>
|
|
421
|
+
</label>
|
|
422
|
+
</li>
|
|
423
|
+
<li>
|
|
424
|
+
<label class="label cursor-pointer py-1 gap-2">
|
|
425
|
+
<span class="label-text"
|
|
426
|
+
>{m.settings_panel_width()}</span
|
|
427
|
+
>
|
|
428
|
+
<input
|
|
429
|
+
type="range"
|
|
430
|
+
min="200"
|
|
431
|
+
max="800"
|
|
432
|
+
value={parseInt(config.search?.width ?? '320')}
|
|
433
|
+
class="range range-xs range-primary w-32"
|
|
434
|
+
oninput={(e) => {
|
|
435
|
+
if (!config.search) config.search = {};
|
|
436
|
+
config.search.width = `${e.currentTarget.value}px`;
|
|
437
|
+
}}
|
|
438
|
+
/>
|
|
439
|
+
<span class="text-xs opacity-50 w-8 text-right"
|
|
440
|
+
>{config.search?.width ?? '320px'}</span
|
|
441
|
+
>
|
|
442
|
+
</label>
|
|
443
|
+
</li>
|
|
444
|
+
</ul>
|
|
445
|
+
</details>
|
|
446
|
+
</li>
|
|
447
|
+
|
|
448
|
+
<li>
|
|
449
|
+
<details>
|
|
450
|
+
<summary>{m.settings_submenu_annotations()}</summary>
|
|
451
|
+
<ul>
|
|
452
|
+
<li>
|
|
453
|
+
<label class="label cursor-pointer py-1">
|
|
454
|
+
<span class="label-text"
|
|
455
|
+
>{m.settings_toggle_panel_open()}</span
|
|
456
|
+
>
|
|
457
|
+
<input
|
|
458
|
+
type="checkbox"
|
|
459
|
+
class="toggle toggle-xs"
|
|
460
|
+
checked={config.annotations?.open ?? false}
|
|
461
|
+
onchange={(e) => {
|
|
462
|
+
if (!config.annotations)
|
|
463
|
+
config.annotations = {};
|
|
464
|
+
config.annotations.open =
|
|
465
|
+
e.currentTarget.checked;
|
|
466
|
+
}}
|
|
467
|
+
/>
|
|
468
|
+
</label>
|
|
469
|
+
</li>
|
|
470
|
+
<li>
|
|
471
|
+
<label class="label cursor-pointer py-1">
|
|
472
|
+
<span class="label-text"
|
|
473
|
+
>{m.settings_toggle_visible_by_default()}</span
|
|
474
|
+
>
|
|
475
|
+
<input
|
|
476
|
+
type="checkbox"
|
|
477
|
+
class="checkbox checkbox-xs"
|
|
478
|
+
checked={config.annotations?.visible ?? true}
|
|
479
|
+
onchange={(e) => {
|
|
480
|
+
if (!config.annotations)
|
|
481
|
+
config.annotations = {};
|
|
482
|
+
config.annotations.visible =
|
|
483
|
+
e.currentTarget.checked;
|
|
484
|
+
}}
|
|
485
|
+
/>
|
|
486
|
+
</label>
|
|
487
|
+
</li>
|
|
488
|
+
</ul>
|
|
489
|
+
</details>
|
|
490
|
+
</li>
|
|
491
|
+
<div class="divider my-1"></div>
|
|
492
|
+
<li>
|
|
493
|
+
<button
|
|
494
|
+
class="btn btn-sm btn-ghost w-full justify-start gap-2"
|
|
495
|
+
class:text-success={copied}
|
|
496
|
+
onclick={copyConfig}
|
|
497
|
+
>
|
|
498
|
+
{#if copied}
|
|
499
|
+
<Check size={16} />
|
|
500
|
+
{m.copied()}
|
|
501
|
+
{:else}
|
|
502
|
+
<Copy size={16} />
|
|
503
|
+
{m.copy_config()}
|
|
504
|
+
{/if}
|
|
505
|
+
</button>
|
|
506
|
+
</li>
|
|
507
|
+
</ul>
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import List from 'phosphor-svelte/lib/List';
|
|
10
10
|
import BookOpen from 'phosphor-svelte/lib/BookOpen';
|
|
11
11
|
import Scroll from 'phosphor-svelte/lib/Scroll';
|
|
12
|
+
import Check from 'phosphor-svelte/lib/Check';
|
|
12
13
|
import X from 'phosphor-svelte/lib/X';
|
|
13
14
|
import { VIEWER_STATE_KEY, type ViewerState } from '../state/viewer.svelte';
|
|
14
15
|
import { m, language } from '../state/i18n.svelte';
|
|
@@ -220,7 +221,12 @@
|
|
|
220
221
|
viewerState.setViewingMode('individuals')}
|
|
221
222
|
>
|
|
222
223
|
<Scroll size={16} />
|
|
223
|
-
|
|
224
|
+
<span class="flex-1"
|
|
225
|
+
>{m.viewing_mode_individuals()}</span
|
|
226
|
+
>
|
|
227
|
+
{#if viewerState.viewingMode === 'individuals'}
|
|
228
|
+
<Check size={16} weight="bold" />
|
|
229
|
+
{/if}
|
|
224
230
|
</button>
|
|
225
231
|
</li>
|
|
226
232
|
<li>
|
|
@@ -232,7 +238,12 @@
|
|
|
232
238
|
viewerState.setViewingMode('paged')}
|
|
233
239
|
>
|
|
234
240
|
<BookOpen size={16} />
|
|
235
|
-
|
|
241
|
+
<span class="flex-1"
|
|
242
|
+
>{m.viewing_mode_paged()}</span
|
|
243
|
+
>
|
|
244
|
+
{#if viewerState.viewingMode === 'paged'}
|
|
245
|
+
<Check size={16} weight="bold" />
|
|
246
|
+
{/if}
|
|
236
247
|
</button>
|
|
237
248
|
</li>
|
|
238
249
|
{#if viewerState.viewingMode === 'paged'}
|
|
@@ -232,8 +232,17 @@
|
|
|
232
232
|
|
|
233
233
|
const canvas = canvases[currentCanvasIndex];
|
|
234
234
|
|
|
235
|
-
//
|
|
236
|
-
|
|
235
|
+
// Helper to get images from a canvas, with v3 fallback
|
|
236
|
+
// v2 uses getImages(), v3 uses getContent() for painting annotations
|
|
237
|
+
const getCanvasImages = (c: any): any[] => {
|
|
238
|
+
let imgs = c.getImages?.() || [];
|
|
239
|
+
if ((!imgs || !imgs.length) && c.getContent) {
|
|
240
|
+
imgs = c.getContent();
|
|
241
|
+
}
|
|
242
|
+
return imgs || [];
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
let images = getCanvasImages(canvas);
|
|
237
246
|
if (internalViewerState.viewingMode === 'paged') {
|
|
238
247
|
// Single pages at the start: pagedOffset (default 0, shifted = 1)
|
|
239
248
|
const singlePages = internalViewerState.pagedOffset;
|
|
@@ -242,17 +251,12 @@
|
|
|
242
251
|
const nextIndex = currentCanvasIndex + 1;
|
|
243
252
|
if (nextIndex < canvases.length) {
|
|
244
253
|
const nextCanvas = canvases[nextIndex];
|
|
245
|
-
const nextImages = nextCanvas
|
|
254
|
+
const nextImages = getCanvasImages(nextCanvas);
|
|
246
255
|
images = images.concat(nextImages);
|
|
247
256
|
}
|
|
248
257
|
}
|
|
249
258
|
}
|
|
250
259
|
|
|
251
|
-
// Fallback for IIIF v3: iterate content if images is empty
|
|
252
|
-
if ((!images || !images.length) && canvas.getContent) {
|
|
253
|
-
images = canvas.getContent();
|
|
254
|
-
}
|
|
255
|
-
|
|
256
260
|
if (!images || !images.length) {
|
|
257
261
|
// Check for raw v3 items
|
|
258
262
|
if (canvas.__jsonld && canvas.__jsonld.items) {
|
|
@@ -330,6 +334,30 @@
|
|
|
330
334
|
}
|
|
331
335
|
|
|
332
336
|
if (services.length > 0) {
|
|
337
|
+
// Matches IIIF Image API profile URIs with http or https scheme
|
|
338
|
+
const iiifImageApiPattern = /^https?:\/\/iiif\.io\/api\/image\//;
|
|
339
|
+
|
|
340
|
+
// IIIF allows profile as a string, array, or containing objects
|
|
341
|
+
// Shorthand levels (level0, level1, level2) are valid per spec
|
|
342
|
+
const isIiifImageProfile = (p: unknown): boolean => {
|
|
343
|
+
if (typeof p === 'string') {
|
|
344
|
+
return (
|
|
345
|
+
iiifImageApiPattern.test(p) ||
|
|
346
|
+
p === 'level0' ||
|
|
347
|
+
p === 'level1' ||
|
|
348
|
+
p === 'level2'
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
if (Array.isArray(p)) {
|
|
352
|
+
return p.some(
|
|
353
|
+
(item) =>
|
|
354
|
+
typeof item === 'string' &&
|
|
355
|
+
isIiifImageProfile(item),
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
return false;
|
|
359
|
+
};
|
|
360
|
+
|
|
333
361
|
// Find a valid image service
|
|
334
362
|
const service = services.find((s: any) => {
|
|
335
363
|
const type = s.getType
|
|
@@ -340,9 +368,7 @@
|
|
|
340
368
|
type === 'ImageService1' ||
|
|
341
369
|
type === 'ImageService2' ||
|
|
342
370
|
type === 'ImageService3' ||
|
|
343
|
-
(
|
|
344
|
-
profile.includes('http://iiif.io/api/image')) ||
|
|
345
|
-
(typeof profile === 'string' && profile === 'level0')
|
|
371
|
+
isIiifImageProfile(profile)
|
|
346
372
|
);
|
|
347
373
|
});
|
|
348
374
|
|
|
@@ -126,6 +126,9 @@ export * from "./viewing_mode_individuals.js";
|
|
|
126
126
|
export * from "./viewing_mode_paged.js";
|
|
127
127
|
export * from "./viewing_mode_shift_pairing.js";
|
|
128
128
|
export * from "./settings_toggle_show_viewing_mode.js";
|
|
129
|
+
export * from "./demo_title.js";
|
|
130
|
+
export * from "./settings_view_configuration.js";
|
|
131
|
+
export * from "./settings_thumbnail_height.js";
|
|
129
132
|
export * from "./toggle_two_page_mode.js";
|
|
130
133
|
export * from "./toggle_single_page_mode.js";
|
|
131
134
|
export * from "./show_mode_toggle.js";
|
|
@@ -128,6 +128,9 @@ export * from './viewing_mode_individuals.js'
|
|
|
128
128
|
export * from './viewing_mode_paged.js'
|
|
129
129
|
export * from './viewing_mode_shift_pairing.js'
|
|
130
130
|
export * from './settings_toggle_show_viewing_mode.js'
|
|
131
|
+
export * from './demo_title.js'
|
|
132
|
+
export * from './settings_view_configuration.js'
|
|
133
|
+
export * from './settings_thumbnail_height.js'
|
|
131
134
|
export * from './toggle_two_page_mode.js'
|
|
132
135
|
export * from './toggle_single_page_mode.js'
|
|
133
136
|
export * from './show_mode_toggle.js'
|