triiiceratops 0.9.12 → 0.10.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 (136) hide show
  1. package/dist/ArrowCounterClockwise-aFffCOKw.js +136 -0
  2. package/dist/X-DZEgXrJ8.js +877 -0
  3. package/dist/annotation_tool_point-CZKsj4Nk.js +290 -0
  4. package/dist/components/AnnotationOverlay.svelte +179 -86
  5. package/dist/components/DemoHeader.svelte +12 -0
  6. package/dist/components/LeftFab.svelte +21 -9
  7. package/dist/components/OSDViewer.svelte +24 -4
  8. package/dist/components/SearchPanel.svelte +4 -1
  9. package/dist/components/TriiiceratopsViewer.svelte +114 -47
  10. package/dist/components/TriiiceratopsViewer.svelte.d.ts +5 -5
  11. package/dist/components/TriiiceratopsViewerElement.svelte +2 -2
  12. package/dist/components/TriiiceratopsViewerElement.svelte.d.ts +2 -2
  13. package/dist/custom-element.d.ts +10 -0
  14. package/dist/custom-element.js +13 -0
  15. package/dist/image_filters_reset-BEIf-_QA.js +108 -0
  16. package/dist/index.d.ts +1 -2
  17. package/dist/index.js +0 -1
  18. package/dist/paraglide/messages/_index.d.ts +31 -0
  19. package/dist/paraglide/messages/_index.js +32 -1
  20. package/dist/paraglide/messages/annotation_editor_add_content.d.ts +4 -0
  21. package/dist/paraglide/messages/annotation_editor_add_content.js +34 -0
  22. package/dist/paraglide/messages/annotation_editor_cancel.d.ts +4 -0
  23. package/dist/paraglide/messages/annotation_editor_cancel.js +34 -0
  24. package/dist/paraglide/messages/annotation_editor_create_mode.d.ts +4 -0
  25. package/dist/paraglide/messages/annotation_editor_create_mode.js +34 -0
  26. package/dist/paraglide/messages/annotation_editor_delete.d.ts +4 -0
  27. package/dist/paraglide/messages/annotation_editor_delete.js +34 -0
  28. package/dist/paraglide/messages/annotation_editor_delete_message.d.ts +4 -0
  29. package/dist/paraglide/messages/annotation_editor_delete_message.js +34 -0
  30. package/dist/paraglide/messages/annotation_editor_delete_title.d.ts +4 -0
  31. package/dist/paraglide/messages/annotation_editor_delete_title.js +34 -0
  32. package/dist/paraglide/messages/annotation_editor_delete_tooltip.d.ts +4 -0
  33. package/dist/paraglide/messages/annotation_editor_delete_tooltip.js +34 -0
  34. package/dist/paraglide/messages/annotation_editor_edit_mode.d.ts +4 -0
  35. package/dist/paraglide/messages/annotation_editor_edit_mode.js +34 -0
  36. package/dist/paraglide/messages/annotation_editor_edit_section.d.ts +4 -0
  37. package/dist/paraglide/messages/annotation_editor_edit_section.js +34 -0
  38. package/dist/paraglide/messages/annotation_editor_instruction_create.d.ts +4 -0
  39. package/dist/paraglide/messages/annotation_editor_instruction_create.js +34 -0
  40. package/dist/paraglide/messages/annotation_editor_instruction_edit.d.ts +4 -0
  41. package/dist/paraglide/messages/annotation_editor_instruction_edit.js +34 -0
  42. package/dist/paraglide/messages/annotation_editor_link_placeholder.d.ts +4 -0
  43. package/dist/paraglide/messages/annotation_editor_link_placeholder.js +34 -0
  44. package/dist/paraglide/messages/annotation_editor_redo.d.ts +4 -0
  45. package/dist/paraglide/messages/annotation_editor_redo.js +34 -0
  46. package/dist/paraglide/messages/annotation_editor_save.d.ts +4 -0
  47. package/dist/paraglide/messages/annotation_editor_save.js +34 -0
  48. package/dist/paraglide/messages/annotation_editor_tag_placeholder.d.ts +4 -0
  49. package/dist/paraglide/messages/annotation_editor_tag_placeholder.js +34 -0
  50. package/dist/paraglide/messages/annotation_editor_text_placeholder.d.ts +4 -0
  51. package/dist/paraglide/messages/annotation_editor_text_placeholder.js +34 -0
  52. package/dist/paraglide/messages/annotation_editor_title.d.ts +4 -0
  53. package/dist/paraglide/messages/annotation_editor_title.js +34 -0
  54. package/dist/paraglide/messages/annotation_editor_tool_label.d.ts +4 -0
  55. package/dist/paraglide/messages/annotation_editor_tool_label.js +34 -0
  56. package/dist/paraglide/messages/annotation_editor_undo.d.ts +4 -0
  57. package/dist/paraglide/messages/annotation_editor_undo.js +34 -0
  58. package/dist/paraglide/messages/annotation_tool_point.d.ts +4 -0
  59. package/dist/paraglide/messages/annotation_tool_point.js +34 -0
  60. package/dist/paraglide/messages/annotation_tool_polygon.d.ts +4 -0
  61. package/dist/paraglide/messages/annotation_tool_polygon.js +34 -0
  62. package/dist/paraglide/messages/annotation_tool_rectangle.d.ts +4 -0
  63. package/dist/paraglide/messages/annotation_tool_rectangle.js +34 -0
  64. package/dist/paraglide/messages/image_adjustments_title.d.ts +4 -0
  65. package/dist/paraglide/messages/image_adjustments_title.js +34 -0
  66. package/dist/paraglide/messages/image_filters_brightness.d.ts +4 -0
  67. package/dist/paraglide/messages/image_filters_brightness.js +34 -0
  68. package/dist/paraglide/messages/image_filters_contrast.d.ts +4 -0
  69. package/dist/paraglide/messages/image_filters_contrast.js +34 -0
  70. package/dist/paraglide/messages/image_filters_effects.d.ts +4 -0
  71. package/dist/paraglide/messages/image_filters_effects.js +34 -0
  72. package/dist/paraglide/messages/image_filters_grayscale.d.ts +4 -0
  73. package/dist/paraglide/messages/image_filters_grayscale.js +34 -0
  74. package/dist/paraglide/messages/image_filters_invert.d.ts +4 -0
  75. package/dist/paraglide/messages/image_filters_invert.js +34 -0
  76. package/dist/paraglide/messages/image_filters_reset.d.ts +4 -0
  77. package/dist/paraglide/messages/image_filters_reset.js +34 -0
  78. package/dist/paraglide/messages/image_filters_saturation.d.ts +4 -0
  79. package/dist/paraglide/messages/image_filters_saturation.js +34 -0
  80. package/dist/paraglide/messages/plugins_tooltip.js +1 -1
  81. package/dist/paraglide/messages/settings_transparent_background.d.ts +4 -0
  82. package/dist/paraglide/messages/settings_transparent_background.js +34 -0
  83. package/dist/plugins/annotation-editor/AnnotationEditorController.svelte +166 -0
  84. package/dist/plugins/annotation-editor/AnnotationEditorController.svelte.d.ts +9 -0
  85. package/dist/plugins/annotation-editor/AnnotationEditorPanel.svelte +315 -0
  86. package/dist/plugins/annotation-editor/AnnotationEditorPanel.svelte.d.ts +24 -0
  87. package/dist/plugins/annotation-editor/AnnotationManager.svelte.d.ts +39 -0
  88. package/dist/plugins/annotation-editor/AnnotationManager.svelte.js +433 -0
  89. package/dist/plugins/annotation-editor/adapters/LocalStorageAdapter.d.ts +20 -0
  90. package/dist/plugins/annotation-editor/adapters/LocalStorageAdapter.js +67 -0
  91. package/dist/plugins/annotation-editor/adapters/index.d.ts +2 -0
  92. package/dist/plugins/annotation-editor/adapters/index.js +1 -0
  93. package/dist/plugins/annotation-editor/adapters/types.d.ts +23 -0
  94. package/dist/plugins/annotation-editor/adapters/types.js +1 -0
  95. package/dist/plugins/annotation-editor/iife-entry.d.ts +15 -0
  96. package/dist/plugins/annotation-editor/iife-entry.js +35 -0
  97. package/dist/plugins/annotation-editor/index.d.ts +41 -0
  98. package/dist/plugins/annotation-editor/index.js +57 -0
  99. package/dist/plugins/annotation-editor/loader.svelte.d.ts +7 -0
  100. package/dist/plugins/annotation-editor/loader.svelte.js +32 -0
  101. package/dist/plugins/annotation-editor/types.d.ts +41 -0
  102. package/dist/plugins/annotation-editor/types.js +13 -0
  103. package/dist/plugins/annotation-editor.js +32824 -0
  104. package/dist/plugins/image-manipulation/ImageManipulationController.svelte +54 -0
  105. package/dist/plugins/image-manipulation/ImageManipulationController.svelte.d.ts +6 -0
  106. package/dist/plugins/image-manipulation/ImageManipulationPanel.svelte +19 -9
  107. package/dist/plugins/image-manipulation/ImageManipulationPanel.svelte.d.ts +1 -0
  108. package/dist/plugins/image-manipulation/iife-entry.d.ts +13 -0
  109. package/dist/plugins/image-manipulation/iife-entry.js +17 -0
  110. package/dist/plugins/image-manipulation/index.d.ts +15 -1
  111. package/dist/plugins/image-manipulation/index.js +21 -1
  112. package/dist/plugins/image-manipulation.js +265 -0
  113. package/dist/state/i18n.svelte.js +4 -2
  114. package/dist/state/manifests.svelte.d.ts +5 -0
  115. package/dist/state/manifests.svelte.js +42 -13
  116. package/dist/state/viewer.svelte.d.ts +14 -13
  117. package/dist/state/viewer.svelte.js +63 -74
  118. package/dist/triiiceratops-bundle.js +3208 -3124
  119. package/dist/triiiceratops-element.iife.js +99 -0
  120. package/dist/triiiceratops.css +1 -1
  121. package/dist/types/config.d.ts +5 -0
  122. package/dist/types/plugin.d.ts +21 -62
  123. package/dist/types/plugin.js +1 -23
  124. package/dist/utils/annotationAdapter.d.ts +12 -1
  125. package/dist/utils/annotationAdapter.js +98 -39
  126. package/package.json +13 -6
  127. package/dist/chunks/TriiiceratopsViewer-DpZQA17w.js +0 -10435
  128. package/dist/chunks/openseadragon-5MHeYuQz.js +0 -12427
  129. package/dist/components/TriiiceratopsViewerElementImage.svelte +0 -143
  130. package/dist/components/TriiiceratopsViewerElementImage.svelte.d.ts +0 -27
  131. package/dist/custom-element-image.d.ts +0 -1
  132. package/dist/custom-element-image.js +0 -2
  133. package/dist/plugins/image-manipulation/ImageManipulationPlugin.svelte.d.ts +0 -19
  134. package/dist/plugins/image-manipulation/ImageManipulationPlugin.svelte.js +0 -87
  135. package/dist/triiiceratops-element-image.js +0 -555
  136. package/dist/triiiceratops-element.js +0 -114
@@ -0,0 +1,34 @@
1
+ /* eslint-disable */
2
+ import { getLocale, trackMessageCall, experimentalMiddlewareLocaleSplitting, isServer } from '../runtime.js';
3
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
4
+
5
+ const en_image_filters_reset = /** @type {(inputs: {}) => LocalizedString} */ () => {
6
+ return /** @type {LocalizedString} */ (`Reset to Default`)
7
+ };
8
+
9
+ const de_image_filters_reset = /** @type {(inputs: {}) => LocalizedString} */ () => {
10
+ return /** @type {LocalizedString} */ (`Zurücksetzen`)
11
+ };
12
+
13
+ /**
14
+ * This function has been compiled by [Paraglide JS](https://inlang.com/m/gerre34r).
15
+ *
16
+ * - Changing this function will be over-written by the next build.
17
+ *
18
+ * - If you want to change the translations, you can either edit the source files e.g. `en.json`, or
19
+ * use another inlang app like [Fink](https://inlang.com/m/tdozzpar) or the [VSCode extension Sherlock](https://inlang.com/m/r7kp499g).
20
+ *
21
+ * @param {{}} inputs
22
+ * @param {{ locale?: "en" | "de" }} options
23
+ * @returns {LocalizedString}
24
+ */
25
+ /* @__NO_SIDE_EFFECTS__ */
26
+ export const image_filters_reset = (inputs = {}, options = {}) => {
27
+ if (experimentalMiddlewareLocaleSplitting && isServer === false) {
28
+ return /** @type {any} */ (globalThis).__paraglide_ssr.image_filters_reset(inputs)
29
+ }
30
+ const locale = options.locale ?? getLocale()
31
+ trackMessageCall("image_filters_reset", locale)
32
+ if (locale === "en") return en_image_filters_reset(inputs)
33
+ return de_image_filters_reset(inputs)
34
+ };
@@ -0,0 +1,4 @@
1
+ export function image_filters_saturation(inputs?: {}, options?: {
2
+ locale?: "en" | "de";
3
+ }): LocalizedString;
4
+ export type LocalizedString = import("../runtime.js").LocalizedString;
@@ -0,0 +1,34 @@
1
+ /* eslint-disable */
2
+ import { getLocale, trackMessageCall, experimentalMiddlewareLocaleSplitting, isServer } from '../runtime.js';
3
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
4
+
5
+ const en_image_filters_saturation = /** @type {(inputs: {}) => LocalizedString} */ () => {
6
+ return /** @type {LocalizedString} */ (`Saturation`)
7
+ };
8
+
9
+ const de_image_filters_saturation = /** @type {(inputs: {}) => LocalizedString} */ () => {
10
+ return /** @type {LocalizedString} */ (`Sättigung`)
11
+ };
12
+
13
+ /**
14
+ * This function has been compiled by [Paraglide JS](https://inlang.com/m/gerre34r).
15
+ *
16
+ * - Changing this function will be over-written by the next build.
17
+ *
18
+ * - If you want to change the translations, you can either edit the source files e.g. `en.json`, or
19
+ * use another inlang app like [Fink](https://inlang.com/m/tdozzpar) or the [VSCode extension Sherlock](https://inlang.com/m/r7kp499g).
20
+ *
21
+ * @param {{}} inputs
22
+ * @param {{ locale?: "en" | "de" }} options
23
+ * @returns {LocalizedString}
24
+ */
25
+ /* @__NO_SIDE_EFFECTS__ */
26
+ export const image_filters_saturation = (inputs = {}, options = {}) => {
27
+ if (experimentalMiddlewareLocaleSplitting && isServer === false) {
28
+ return /** @type {any} */ (globalThis).__paraglide_ssr.image_filters_saturation(inputs)
29
+ }
30
+ const locale = options.locale ?? getLocale()
31
+ trackMessageCall("image_filters_saturation", locale)
32
+ if (locale === "en") return en_image_filters_saturation(inputs)
33
+ return de_image_filters_saturation(inputs)
34
+ };
@@ -7,7 +7,7 @@ const en_plugins_tooltip = /** @type {(inputs: {}) => LocalizedString} */ () =>
7
7
  };
8
8
 
9
9
  const de_plugins_tooltip = /** @type {(inputs: {}) => LocalizedString} */ () => {
10
- return /** @type {LocalizedString} */ (`Plugins`)
10
+ return /** @type {LocalizedString} */ (`Erweiterungen`)
11
11
  };
12
12
 
13
13
  /**
@@ -0,0 +1,4 @@
1
+ export function settings_transparent_background(inputs?: {}, options?: {
2
+ locale?: "en" | "de";
3
+ }): LocalizedString;
4
+ export type LocalizedString = import("../runtime.js").LocalizedString;
@@ -0,0 +1,34 @@
1
+ /* eslint-disable */
2
+ import { getLocale, trackMessageCall, experimentalMiddlewareLocaleSplitting, isServer } from '../runtime.js';
3
+ /** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
4
+
5
+ const en_settings_transparent_background = /** @type {(inputs: {}) => LocalizedString} */ () => {
6
+ return /** @type {LocalizedString} */ (`Transparent Background`)
7
+ };
8
+
9
+ const de_settings_transparent_background = /** @type {(inputs: {}) => LocalizedString} */ () => {
10
+ return /** @type {LocalizedString} */ (`Transparenter Hintergrund`)
11
+ };
12
+
13
+ /**
14
+ * This function has been compiled by [Paraglide JS](https://inlang.com/m/gerre34r).
15
+ *
16
+ * - Changing this function will be over-written by the next build.
17
+ *
18
+ * - If you want to change the translations, you can either edit the source files e.g. `en.json`, or
19
+ * use another inlang app like [Fink](https://inlang.com/m/tdozzpar) or the [VSCode extension Sherlock](https://inlang.com/m/r7kp499g).
20
+ *
21
+ * @param {{}} inputs
22
+ * @param {{ locale?: "en" | "de" }} options
23
+ * @returns {LocalizedString}
24
+ */
25
+ /* @__NO_SIDE_EFFECTS__ */
26
+ export const settings_transparent_background = (inputs = {}, options = {}) => {
27
+ if (experimentalMiddlewareLocaleSplitting && isServer === false) {
28
+ return /** @type {any} */ (globalThis).__paraglide_ssr.settings_transparent_background(inputs)
29
+ }
30
+ const locale = options.locale ?? getLocale()
31
+ trackMessageCall("settings_transparent_background", locale)
32
+ if (locale === "en") return en_settings_transparent_background(inputs)
33
+ return de_settings_transparent_background(inputs)
34
+ };
@@ -0,0 +1,166 @@
1
+ <script lang="ts">
2
+ import { getContext, onMount, onDestroy } from 'svelte';
3
+ import {
4
+ VIEWER_STATE_KEY,
5
+ type ViewerState,
6
+ } from '../../state/viewer.svelte';
7
+ import { AnnotationManager } from './AnnotationManager.svelte';
8
+ import AnnotationEditorPanel from './AnnotationEditorPanel.svelte';
9
+ import type {
10
+ AnnotationEditorConfig,
11
+ DrawingTool,
12
+ W3CAnnotationBody,
13
+ } from './types';
14
+
15
+ // Props from the plugin system
16
+ let {
17
+ isOpen = false,
18
+ close,
19
+ config,
20
+ }: {
21
+ isOpen: boolean;
22
+ close: () => void;
23
+ config: AnnotationEditorConfig;
24
+ } = $props();
25
+
26
+ const viewerState = getContext<ViewerState>(VIEWER_STATE_KEY);
27
+
28
+ // UI state
29
+ let isEditing = $state(false);
30
+ let activeTool = $state<DrawingTool>(config.defaultTool ?? 'rectangle');
31
+ let selectedAnnotation = $state<any>(null);
32
+ let showDeleteConfirm = $state(false);
33
+ let pendingDeleteId = $state<string | null>(null);
34
+ let canUndo = $state(false);
35
+ let canRedo = $state(false);
36
+
37
+ // Create the annotation manager
38
+ let manager: AnnotationManager | null = $state.raw(null);
39
+
40
+ onMount(() => {
41
+ if (viewerState?.osdViewer) {
42
+ const mgr = new AnnotationManager(config);
43
+
44
+ // Set up callbacks
45
+ mgr.onSelectionChange = (annotation) => {
46
+ selectedAnnotation = annotation;
47
+ };
48
+
49
+ mgr.onUndoRedoChange = (undo, redo) => {
50
+ canUndo = undo;
51
+ canRedo = redo;
52
+ };
53
+
54
+ mgr.onAnnotationCreated = (annotation) => {
55
+ selectedAnnotation = annotation;
56
+ };
57
+
58
+ mgr.init(viewerState.osdViewer, viewerState.canvasId);
59
+
60
+ // Load initial annotations
61
+ if (viewerState.manifestId && viewerState.canvasId) {
62
+ mgr.handleCanvasChange(
63
+ viewerState.manifestId,
64
+ viewerState.canvasId,
65
+ );
66
+ }
67
+
68
+ manager = mgr;
69
+ } else {
70
+ console.warn(
71
+ '[AnnotationEditor] No OSD viewer available at mount time',
72
+ );
73
+ }
74
+ });
75
+
76
+ onDestroy(() => {
77
+ manager?.destroy();
78
+ });
79
+
80
+ // Watch for canvas changes
81
+ $effect(() => {
82
+ const manifestId = viewerState?.manifestId;
83
+ const canvasId = viewerState?.canvasId;
84
+ manager?.handleCanvasChange(manifestId ?? null, canvasId ?? null);
85
+ });
86
+
87
+ // Handlers
88
+ function handleToggleEditing() {
89
+ isEditing = !isEditing;
90
+ manager?.setEditing(isEditing);
91
+ }
92
+
93
+ function handleSetTool(tool: DrawingTool) {
94
+ activeTool = tool;
95
+ manager?.setTool(tool);
96
+ }
97
+
98
+ async function handleSaveBodies(bodies: W3CAnnotationBody[]) {
99
+ if (selectedAnnotation && manager) {
100
+ await manager.updateAnnotationBodies(selectedAnnotation.id, bodies);
101
+ selectedAnnotation = null;
102
+ manager.cancelSelection();
103
+ }
104
+ }
105
+
106
+ function handleRequestDelete() {
107
+ if (selectedAnnotation) {
108
+ pendingDeleteId = selectedAnnotation.id;
109
+ showDeleteConfirm = true;
110
+ }
111
+ }
112
+
113
+ async function handleConfirmDelete() {
114
+ if (pendingDeleteId && manager) {
115
+ await manager.deleteAnnotation(pendingDeleteId);
116
+ }
117
+ showDeleteConfirm = false;
118
+ pendingDeleteId = null;
119
+ selectedAnnotation = null;
120
+ }
121
+
122
+ function handleCancelDelete() {
123
+ showDeleteConfirm = false;
124
+ pendingDeleteId = null;
125
+ manager?.cancelSelection();
126
+ }
127
+
128
+ function handleUndo() {
129
+ manager?.undo();
130
+ }
131
+
132
+ function handleRedo() {
133
+ manager?.redo();
134
+ }
135
+
136
+ function handleClose() {
137
+ if (isEditing) {
138
+ isEditing = false;
139
+ manager?.setEditing(false);
140
+ }
141
+ close();
142
+ }
143
+ </script>
144
+
145
+ <AnnotationEditorPanel
146
+ {isEditing}
147
+ {activeTool}
148
+ {selectedAnnotation}
149
+ {showDeleteConfirm}
150
+ {canUndo}
151
+ {canRedo}
152
+ availableTools={manager?.availableTools ?? [
153
+ 'rectangle',
154
+ 'polygon',
155
+ 'point',
156
+ ]}
157
+ onToggleEditing={handleToggleEditing}
158
+ onSetTool={handleSetTool}
159
+ onSaveBodies={handleSaveBodies}
160
+ onRequestDelete={handleRequestDelete}
161
+ onConfirmDelete={handleConfirmDelete}
162
+ onCancelDelete={handleCancelDelete}
163
+ onUndo={handleUndo}
164
+ onRedo={handleRedo}
165
+ onClose={handleClose}
166
+ />
@@ -0,0 +1,9 @@
1
+ import type { AnnotationEditorConfig } from './types';
2
+ type $$ComponentProps = {
3
+ isOpen: boolean;
4
+ close: () => void;
5
+ config: AnnotationEditorConfig;
6
+ };
7
+ declare const AnnotationEditorController: import("svelte").Component<$$ComponentProps, {}, "">;
8
+ type AnnotationEditorController = ReturnType<typeof AnnotationEditorController>;
9
+ export default AnnotationEditorController;
@@ -0,0 +1,315 @@
1
+ <script lang="ts">
2
+ import X from 'phosphor-svelte/lib/X';
3
+ import PencilSimple from 'phosphor-svelte/lib/PencilSimple';
4
+ import Rectangle from 'phosphor-svelte/lib/Rectangle';
5
+ import Polygon from 'phosphor-svelte/lib/Polygon';
6
+ import Trash from 'phosphor-svelte/lib/Trash';
7
+ import ArrowCounterClockwise from 'phosphor-svelte/lib/ArrowCounterClockwise';
8
+ import ArrowClockwise from 'phosphor-svelte/lib/ArrowClockwise';
9
+ import Plus from 'phosphor-svelte/lib/Plus';
10
+ import Warning from 'phosphor-svelte/lib/Warning';
11
+ import Target from 'phosphor-svelte/lib/Target';
12
+ import Check from 'phosphor-svelte/lib/Check';
13
+ import type { DrawingTool, W3CAnnotationBody } from './types';
14
+ import { W3C_PURPOSES } from './types';
15
+ import { setLocale, locales } from '../../paraglide/runtime';
16
+ import { m } from '../../paraglide/messages';
17
+
18
+ // Import Annotorious CSS for the drawing overlay to ensure it's loaded by Vite
19
+ import '@annotorious/openseadragon/annotorious-openseadragon.css';
20
+
21
+ // Props
22
+ let {
23
+ isEditing = false,
24
+ activeTool = 'rectangle' as DrawingTool,
25
+ selectedAnnotation = null as any,
26
+ showDeleteConfirm = false,
27
+ canUndo = false,
28
+ canRedo = false,
29
+ availableTools = ['rectangle', 'polygon', 'point'] as DrawingTool[],
30
+ onToggleEditing,
31
+ onSetTool,
32
+ onSaveBodies,
33
+ onRequestDelete,
34
+ onConfirmDelete,
35
+ onCancelDelete,
36
+ onUndo,
37
+ onRedo,
38
+ onClose,
39
+ locale,
40
+ }: {
41
+ isEditing: boolean;
42
+ activeTool: DrawingTool;
43
+ selectedAnnotation: any;
44
+ showDeleteConfirm: boolean;
45
+ canUndo: boolean;
46
+ canRedo: boolean;
47
+ availableTools: DrawingTool[];
48
+ onToggleEditing: () => void;
49
+ onSetTool: (tool: DrawingTool) => void;
50
+ onSaveBodies: (bodies: W3CAnnotationBody[]) => void;
51
+ onRequestDelete: () => void;
52
+ onConfirmDelete: () => void;
53
+ onCancelDelete: () => void;
54
+ onUndo: () => void;
55
+ onRedo: () => void;
56
+ onClose: () => void;
57
+ locale?: string;
58
+ } = $props();
59
+
60
+ // Tool icons
61
+ const toolIcons: Record<string, any> = {
62
+ rectangle: Rectangle,
63
+ polygon: Polygon,
64
+ point: Target,
65
+ };
66
+
67
+ // Body editor state (local copy for editing)
68
+ let editableBodies = $state<W3CAnnotationBody[]>([]);
69
+
70
+ // Sync when a new annotation is selected
71
+ $effect(() => {
72
+ if (selectedAnnotation) {
73
+ const body = selectedAnnotation.body;
74
+ if (Array.isArray(body)) {
75
+ editableBodies = body.map((b: any) => ({ ...b }));
76
+ } else if (body) {
77
+ editableBodies = [{ ...body }];
78
+ } else {
79
+ editableBodies = [];
80
+ }
81
+ }
82
+ });
83
+
84
+ $effect(() => {
85
+ if (locale && locales.includes(locale as any)) {
86
+ setLocale(locale as any);
87
+ }
88
+ });
89
+
90
+ function addBody() {
91
+ editableBodies = [
92
+ ...editableBodies,
93
+ { purpose: 'commenting', value: '' },
94
+ ];
95
+ }
96
+
97
+ function removeBody(index: number) {
98
+ editableBodies = editableBodies.filter((_, i) => i !== index);
99
+ }
100
+
101
+ function handleSaveBodies() {
102
+ // Filter empty bodies
103
+ const valid = editableBodies.filter((b) => b.value?.trim());
104
+ onSaveBodies(valid);
105
+ }
106
+ </script>
107
+
108
+ <div
109
+ class="w-80 h-full bg-base-200 border-r border-base-300 shadow-xl flex flex-col"
110
+ >
111
+ <!-- Header -->
112
+ <div class="flex items-center justify-between p-4 border-b border-base-300">
113
+ <h2 class="text-lg font-semibold flex items-center gap-2">
114
+ <PencilSimple size={20} />
115
+ {m.annotation_editor_title()}
116
+ </h2>
117
+ <button
118
+ class="btn btn-sm btn-ghost btn-circle"
119
+ onclick={onClose}
120
+ aria-label={m.close()}
121
+ >
122
+ <X size={20} />
123
+ </button>
124
+ </div>
125
+
126
+ <div class="flex-1 overflow-y-auto p-4 space-y-6">
127
+ <!-- Drawing Mode Toggle -->
128
+ <div class="flex flex-col gap-2">
129
+ <div class="join grid grid-cols-2 w-full">
130
+ <button
131
+ class="join-item btn btn-sm {!isEditing
132
+ ? 'btn-secondary'
133
+ : ''}"
134
+ onclick={() => isEditing && onToggleEditing()}
135
+ >
136
+ {m.annotation_editor_edit_mode()}
137
+ </button>
138
+ <button
139
+ class="join-item btn btn-sm {isEditing
140
+ ? 'btn-primary'
141
+ : ''}"
142
+ onclick={() => !isEditing && onToggleEditing()}
143
+ >
144
+ {m.annotation_editor_create_mode()}
145
+ </button>
146
+ </div>
147
+ <p class="text-xs opacity-60 text-center">
148
+ {isEditing
149
+ ? m.annotation_editor_instruction_create()
150
+ : m.annotation_editor_instruction_edit()}
151
+ </p>
152
+ </div>
153
+
154
+ <!-- Tool Selection -->
155
+ {#if isEditing}
156
+ <div class="space-y-2">
157
+ <p class="text-sm font-medium">
158
+ {m.annotation_editor_tool_label()}
159
+ </p>
160
+ <div class="join">
161
+ {#each availableTools as tool}
162
+ {@const Icon = toolIcons[tool] ?? Rectangle}
163
+ {@const toolName =
164
+ {
165
+ rectangle: m.annotation_tool_rectangle(),
166
+ polygon: m.annotation_tool_polygon(),
167
+ point: m.annotation_tool_point(),
168
+ }[tool] ?? tool}
169
+ <button
170
+ class="join-item btn btn-sm tooltip tooltip-bottom {activeTool ===
171
+ tool
172
+ ? 'btn-primary'
173
+ : ''}"
174
+ data-tip={toolName}
175
+ onclick={() => onSetTool(tool)}
176
+ aria-label={toolName}
177
+ >
178
+ <Icon size={18} />
179
+ </button>
180
+ {/each}
181
+ </div>
182
+ </div>
183
+
184
+ <!-- Undo/Redo -->
185
+ <div class="flex gap-2">
186
+ <button
187
+ class="btn btn-sm btn-outline flex-1"
188
+ disabled={!canUndo}
189
+ onclick={onUndo}
190
+ >
191
+ <ArrowCounterClockwise size={16} />
192
+ {m.annotation_editor_undo()}
193
+ </button>
194
+ <button
195
+ class="btn btn-sm btn-outline flex-1"
196
+ disabled={!canRedo}
197
+ onclick={onRedo}
198
+ >
199
+ <ArrowClockwise size={16} />
200
+ {m.annotation_editor_redo()}
201
+ </button>
202
+ </div>
203
+ {/if}
204
+
205
+ <!-- Selected Annotation Editor (Inline) -->
206
+ {#if selectedAnnotation}
207
+ <div class="card bg-base-100 p-4 space-y-3">
208
+ <div class="flex items-center justify-between mb-2">
209
+ <h3 class="font-medium text-sm">
210
+ {m.annotation_editor_edit_section()}
211
+ </h3>
212
+ <div class="flex gap-1">
213
+ <button
214
+ class="btn btn-sm btn-error btn-ghost btn-circle"
215
+ onclick={onRequestDelete}
216
+ aria-label={m.annotation_editor_delete_tooltip()}
217
+ >
218
+ <Trash size={16} />
219
+ </button>
220
+ </div>
221
+ </div>
222
+
223
+ <div class="space-y-3 max-h-[40vh] overflow-y-auto pr-1">
224
+ {#each editableBodies as body, i}
225
+ <div class="card bg-base-200 p-2 space-y-2">
226
+ <div class="flex items-center gap-2">
227
+ <select
228
+ class="select select-xs select-bordered flex-1"
229
+ bind:value={body.purpose}
230
+ >
231
+ {#each W3C_PURPOSES as purpose}
232
+ <option
233
+ value={purpose}
234
+ class="capitalize">{purpose}</option
235
+ >
236
+ {/each}
237
+ </select>
238
+ <button
239
+ class="btn btn-xs btn-ghost btn-circle text-error"
240
+ onclick={() => removeBody(i)}
241
+ >
242
+ <X size={14} />
243
+ </button>
244
+ </div>
245
+
246
+ {#if body.purpose === 'tagging'}
247
+ <input
248
+ type="text"
249
+ class="input input-xs input-bordered w-full"
250
+ placeholder={m.annotation_editor_tag_placeholder()}
251
+ bind:value={body.value}
252
+ />
253
+ {:else if body.purpose === 'linking'}
254
+ <input
255
+ type="url"
256
+ class="input input-xs input-bordered w-full"
257
+ placeholder={m.annotation_editor_link_placeholder()}
258
+ bind:value={body.value}
259
+ />
260
+ {:else}
261
+ <textarea
262
+ class="textarea textarea-xs textarea-bordered w-full"
263
+ rows="2"
264
+ placeholder={m.annotation_editor_text_placeholder()}
265
+ bind:value={body.value}
266
+ ></textarea>
267
+ {/if}
268
+ </div>
269
+ {/each}
270
+ </div>
271
+
272
+ <button class="btn btn-xs btn-ghost w-full" onclick={addBody}>
273
+ <Plus size={14} />
274
+ {m.annotation_editor_add_content()}
275
+ </button>
276
+
277
+ <div class="pt-2">
278
+ <button
279
+ class="btn btn-sm btn-primary w-full"
280
+ onclick={handleSaveBodies}
281
+ >
282
+ <Check size={16} />
283
+ {m.annotation_editor_save()}
284
+ </button>
285
+ </div>
286
+ </div>
287
+ {/if}
288
+ </div>
289
+ </div>
290
+
291
+ <!-- Delete Confirmation Modal (Keep as modal for safety) -->
292
+ {#if showDeleteConfirm}
293
+ <dialog class="modal modal-open">
294
+ <div class="modal-box">
295
+ <h3 class="font-bold text-lg flex items-center gap-2">
296
+ <Warning size={24} class="text-warning" />
297
+ {m.annotation_editor_delete_title()}
298
+ </h3>
299
+ <p class="py-4">
300
+ {m.annotation_editor_delete_message()}
301
+ </p>
302
+ <div class="modal-action">
303
+ <button class="btn btn-ghost" onclick={onCancelDelete}>
304
+ {m.annotation_editor_cancel()}
305
+ </button>
306
+ <button class="btn btn-error" onclick={onConfirmDelete}>
307
+ {m.annotation_editor_delete()}
308
+ </button>
309
+ </div>
310
+ </div>
311
+ <form method="dialog" class="modal-backdrop">
312
+ <button onclick={onCancelDelete}>close</button>
313
+ </form>
314
+ </dialog>
315
+ {/if}
@@ -0,0 +1,24 @@
1
+ import type { DrawingTool, W3CAnnotationBody } from './types';
2
+ import '@annotorious/openseadragon/annotorious-openseadragon.css';
3
+ type $$ComponentProps = {
4
+ isEditing: boolean;
5
+ activeTool: DrawingTool;
6
+ selectedAnnotation: any;
7
+ showDeleteConfirm: boolean;
8
+ canUndo: boolean;
9
+ canRedo: boolean;
10
+ availableTools: DrawingTool[];
11
+ onToggleEditing: () => void;
12
+ onSetTool: (tool: DrawingTool) => void;
13
+ onSaveBodies: (bodies: W3CAnnotationBody[]) => void;
14
+ onRequestDelete: () => void;
15
+ onConfirmDelete: () => void;
16
+ onCancelDelete: () => void;
17
+ onUndo: () => void;
18
+ onRedo: () => void;
19
+ onClose: () => void;
20
+ locale?: string;
21
+ };
22
+ declare const AnnotationEditorPanel: import("svelte").Component<$$ComponentProps, {}, "">;
23
+ type AnnotationEditorPanel = ReturnType<typeof AnnotationEditorPanel>;
24
+ export default AnnotationEditorPanel;
@@ -0,0 +1,39 @@
1
+ import type { AnnotationEditorConfig, DrawingTool, W3CAnnotationBody } from './types';
2
+ /**
3
+ * Manages the Annotorious instance and annotation CRUD operations.
4
+ * Instantiated within the controller component.
5
+ */
6
+ export declare class AnnotationManager {
7
+ private config;
8
+ private adapter;
9
+ private annotorious;
10
+ private osdViewer;
11
+ private currentManifestId;
12
+ private currentCanvasId;
13
+ private isDrawingEnabled;
14
+ private activeTool;
15
+ onSelectionChange?: (annotation: any | null) => void;
16
+ onUndoRedoChange?: (canUndo: boolean, canRedo: boolean) => void;
17
+ onAnnotationCreated?: (annotation: any) => void;
18
+ constructor(config: AnnotationEditorConfig);
19
+ init(viewer: any, canvasId: string | null): void;
20
+ private initAnnotorious;
21
+ private handlePointClick;
22
+ setEditing(enabled: boolean): void;
23
+ private updateDrawingMode;
24
+ setTool(tool: DrawingTool): void;
25
+ get availableTools(): DrawingTool[];
26
+ private injectStyles;
27
+ private setupEvents;
28
+ private updateUndoRedoState;
29
+ handleCanvasChange(manifestId: string | null, canvasId: string | null): Promise<void>;
30
+ private loadAnnotations;
31
+ saveAnnotation(annotation: any): Promise<void>;
32
+ private ensureTargetSource;
33
+ deleteAnnotation(annotationId: string): Promise<void>;
34
+ updateAnnotationBodies(annotationId: string, bodies: W3CAnnotationBody[]): Promise<void>;
35
+ cancelSelection(): void;
36
+ undo(): void;
37
+ redo(): void;
38
+ destroy(): void;
39
+ }