triiiceratops 0.9.13 → 0.10.1

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 (133) hide show
  1. package/dist/ArrowCounterClockwise-C6n_F9YZ.js +136 -0
  2. package/dist/X-BUzsFa3u.js +886 -0
  3. package/dist/annotation_tool_point-CCJi2I8J.js +290 -0
  4. package/dist/components/AnnotationOverlay.svelte +179 -86
  5. package/dist/components/LeftFab.svelte +21 -9
  6. package/dist/components/OSDViewer.svelte +20 -3
  7. package/dist/components/ThumbnailGallery.svelte +4 -4
  8. package/dist/components/TriiiceratopsViewer.svelte +167 -49
  9. package/dist/components/TriiiceratopsViewer.svelte.d.ts +5 -5
  10. package/dist/components/TriiiceratopsViewerElement.svelte +2 -2
  11. package/dist/components/TriiiceratopsViewerElement.svelte.d.ts +2 -2
  12. package/dist/custom-element.d.ts +10 -0
  13. package/dist/custom-element.js +13 -0
  14. package/dist/image_filters_reset-CWe7vTJU.js +108 -0
  15. package/dist/index.d.ts +1 -2
  16. package/dist/index.js +0 -1
  17. package/dist/paraglide/messages/_index.d.ts +30 -0
  18. package/dist/paraglide/messages/_index.js +31 -1
  19. package/dist/paraglide/messages/annotation_editor_add_content.d.ts +4 -0
  20. package/dist/paraglide/messages/annotation_editor_add_content.js +34 -0
  21. package/dist/paraglide/messages/annotation_editor_cancel.d.ts +4 -0
  22. package/dist/paraglide/messages/annotation_editor_cancel.js +34 -0
  23. package/dist/paraglide/messages/annotation_editor_create_mode.d.ts +4 -0
  24. package/dist/paraglide/messages/annotation_editor_create_mode.js +34 -0
  25. package/dist/paraglide/messages/annotation_editor_delete.d.ts +4 -0
  26. package/dist/paraglide/messages/annotation_editor_delete.js +34 -0
  27. package/dist/paraglide/messages/annotation_editor_delete_message.d.ts +4 -0
  28. package/dist/paraglide/messages/annotation_editor_delete_message.js +34 -0
  29. package/dist/paraglide/messages/annotation_editor_delete_title.d.ts +4 -0
  30. package/dist/paraglide/messages/annotation_editor_delete_title.js +34 -0
  31. package/dist/paraglide/messages/annotation_editor_delete_tooltip.d.ts +4 -0
  32. package/dist/paraglide/messages/annotation_editor_delete_tooltip.js +34 -0
  33. package/dist/paraglide/messages/annotation_editor_edit_mode.d.ts +4 -0
  34. package/dist/paraglide/messages/annotation_editor_edit_mode.js +34 -0
  35. package/dist/paraglide/messages/annotation_editor_edit_section.d.ts +4 -0
  36. package/dist/paraglide/messages/annotation_editor_edit_section.js +34 -0
  37. package/dist/paraglide/messages/annotation_editor_instruction_create.d.ts +4 -0
  38. package/dist/paraglide/messages/annotation_editor_instruction_create.js +34 -0
  39. package/dist/paraglide/messages/annotation_editor_instruction_edit.d.ts +4 -0
  40. package/dist/paraglide/messages/annotation_editor_instruction_edit.js +34 -0
  41. package/dist/paraglide/messages/annotation_editor_link_placeholder.d.ts +4 -0
  42. package/dist/paraglide/messages/annotation_editor_link_placeholder.js +34 -0
  43. package/dist/paraglide/messages/annotation_editor_redo.d.ts +4 -0
  44. package/dist/paraglide/messages/annotation_editor_redo.js +34 -0
  45. package/dist/paraglide/messages/annotation_editor_save.d.ts +4 -0
  46. package/dist/paraglide/messages/annotation_editor_save.js +34 -0
  47. package/dist/paraglide/messages/annotation_editor_tag_placeholder.d.ts +4 -0
  48. package/dist/paraglide/messages/annotation_editor_tag_placeholder.js +34 -0
  49. package/dist/paraglide/messages/annotation_editor_text_placeholder.d.ts +4 -0
  50. package/dist/paraglide/messages/annotation_editor_text_placeholder.js +34 -0
  51. package/dist/paraglide/messages/annotation_editor_title.d.ts +4 -0
  52. package/dist/paraglide/messages/annotation_editor_title.js +34 -0
  53. package/dist/paraglide/messages/annotation_editor_tool_label.d.ts +4 -0
  54. package/dist/paraglide/messages/annotation_editor_tool_label.js +34 -0
  55. package/dist/paraglide/messages/annotation_editor_undo.d.ts +4 -0
  56. package/dist/paraglide/messages/annotation_editor_undo.js +34 -0
  57. package/dist/paraglide/messages/annotation_tool_point.d.ts +4 -0
  58. package/dist/paraglide/messages/annotation_tool_point.js +34 -0
  59. package/dist/paraglide/messages/annotation_tool_polygon.d.ts +4 -0
  60. package/dist/paraglide/messages/annotation_tool_polygon.js +34 -0
  61. package/dist/paraglide/messages/annotation_tool_rectangle.d.ts +4 -0
  62. package/dist/paraglide/messages/annotation_tool_rectangle.js +34 -0
  63. package/dist/paraglide/messages/image_adjustments_title.d.ts +4 -0
  64. package/dist/paraglide/messages/image_adjustments_title.js +34 -0
  65. package/dist/paraglide/messages/image_filters_brightness.d.ts +4 -0
  66. package/dist/paraglide/messages/image_filters_brightness.js +34 -0
  67. package/dist/paraglide/messages/image_filters_contrast.d.ts +4 -0
  68. package/dist/paraglide/messages/image_filters_contrast.js +34 -0
  69. package/dist/paraglide/messages/image_filters_effects.d.ts +4 -0
  70. package/dist/paraglide/messages/image_filters_effects.js +34 -0
  71. package/dist/paraglide/messages/image_filters_grayscale.d.ts +4 -0
  72. package/dist/paraglide/messages/image_filters_grayscale.js +34 -0
  73. package/dist/paraglide/messages/image_filters_invert.d.ts +4 -0
  74. package/dist/paraglide/messages/image_filters_invert.js +34 -0
  75. package/dist/paraglide/messages/image_filters_reset.d.ts +4 -0
  76. package/dist/paraglide/messages/image_filters_reset.js +34 -0
  77. package/dist/paraglide/messages/image_filters_saturation.d.ts +4 -0
  78. package/dist/paraglide/messages/image_filters_saturation.js +34 -0
  79. package/dist/paraglide/messages/plugins_tooltip.js +1 -1
  80. package/dist/plugins/annotation-editor/AnnotationEditorController.svelte +166 -0
  81. package/dist/plugins/annotation-editor/AnnotationEditorController.svelte.d.ts +9 -0
  82. package/dist/plugins/annotation-editor/AnnotationEditorPanel.svelte +315 -0
  83. package/dist/plugins/annotation-editor/AnnotationEditorPanel.svelte.d.ts +24 -0
  84. package/dist/plugins/annotation-editor/AnnotationManager.svelte.d.ts +39 -0
  85. package/dist/plugins/annotation-editor/AnnotationManager.svelte.js +433 -0
  86. package/dist/plugins/annotation-editor/adapters/LocalStorageAdapter.d.ts +20 -0
  87. package/dist/plugins/annotation-editor/adapters/LocalStorageAdapter.js +67 -0
  88. package/dist/plugins/annotation-editor/adapters/index.d.ts +2 -0
  89. package/dist/plugins/annotation-editor/adapters/index.js +1 -0
  90. package/dist/plugins/annotation-editor/adapters/types.d.ts +23 -0
  91. package/dist/plugins/annotation-editor/adapters/types.js +1 -0
  92. package/dist/plugins/annotation-editor/iife-entry.d.ts +15 -0
  93. package/dist/plugins/annotation-editor/iife-entry.js +35 -0
  94. package/dist/plugins/annotation-editor/index.d.ts +41 -0
  95. package/dist/plugins/annotation-editor/index.js +57 -0
  96. package/dist/plugins/annotation-editor/loader.svelte.d.ts +7 -0
  97. package/dist/plugins/annotation-editor/loader.svelte.js +32 -0
  98. package/dist/plugins/annotation-editor/types.d.ts +41 -0
  99. package/dist/plugins/annotation-editor/types.js +13 -0
  100. package/dist/plugins/annotation-editor.js +32824 -0
  101. package/dist/plugins/image-manipulation/ImageManipulationController.svelte +54 -0
  102. package/dist/plugins/image-manipulation/ImageManipulationController.svelte.d.ts +6 -0
  103. package/dist/plugins/image-manipulation/ImageManipulationPanel.svelte +19 -9
  104. package/dist/plugins/image-manipulation/ImageManipulationPanel.svelte.d.ts +1 -0
  105. package/dist/plugins/image-manipulation/iife-entry.d.ts +13 -0
  106. package/dist/plugins/image-manipulation/iife-entry.js +17 -0
  107. package/dist/plugins/image-manipulation/index.d.ts +15 -1
  108. package/dist/plugins/image-manipulation/index.js +21 -1
  109. package/dist/plugins/image-manipulation.js +265 -0
  110. package/dist/state/i18n.svelte.js +4 -2
  111. package/dist/state/manifests.svelte.d.ts +7 -2
  112. package/dist/state/manifests.svelte.js +45 -13
  113. package/dist/state/viewer.svelte.d.ts +16 -13
  114. package/dist/state/viewer.svelte.js +75 -84
  115. package/dist/triiiceratops-bundle.js +3260 -3155
  116. package/dist/triiiceratops-element.css +1 -0
  117. package/dist/triiiceratops-element.iife.js +99 -0
  118. package/dist/triiiceratops.css +1 -1
  119. package/dist/types/plugin.d.ts +21 -62
  120. package/dist/types/plugin.js +1 -23
  121. package/dist/utils/annotationAdapter.d.ts +12 -1
  122. package/dist/utils/annotationAdapter.js +98 -39
  123. package/package.json +13 -6
  124. package/dist/chunks/TriiiceratopsViewer-EViTQO_n.js +0 -10437
  125. package/dist/chunks/openseadragon-CHvATAD9.js +0 -12427
  126. package/dist/components/TriiiceratopsViewerElementImage.svelte +0 -143
  127. package/dist/components/TriiiceratopsViewerElementImage.svelte.d.ts +0 -27
  128. package/dist/custom-element-image.d.ts +0 -1
  129. package/dist/custom-element-image.js +0 -2
  130. package/dist/plugins/image-manipulation/ImageManipulationPlugin.svelte.d.ts +0 -19
  131. package/dist/plugins/image-manipulation/ImageManipulationPlugin.svelte.js +0 -87
  132. package/dist/triiiceratops-element-image.js +0 -555
  133. package/dist/triiiceratops-element.js +0 -114
@@ -1,5 +1,5 @@
1
1
  import type { ViewerConfig } from '../types/config';
2
- import type { TriiiceratopsPlugin, PluginMenuButton, PluginPanel } from '../types/plugin';
2
+ import type { PluginMenuButton, PluginPanel, PluginDef } from '../types/plugin';
3
3
  /**
4
4
  * Snapshot of viewer state for external consumers.
5
5
  * Used by web component events to expose state without Svelte reactivity.
@@ -71,8 +71,9 @@ export declare class ViewerState {
71
71
  * reactive cycle completes, preventing infinite update loops.
72
72
  */
73
73
  private dispatchStateChange;
74
- constructor(initialManifestId?: string | null, initialCanvasId?: string | null, initialPlugins?: TriiiceratopsPlugin[]);
74
+ constructor(initialManifestId?: string | null, initialCanvasId?: string | null, initialPlugins?: PluginDef[]);
75
75
  get manifest(): any;
76
+ get manifestEntry(): import("./manifests.svelte.js").ManifestEntry | null | undefined;
76
77
  get canvases(): any;
77
78
  get currentCanvasIndex(): any;
78
79
  get hasNext(): boolean;
@@ -87,6 +88,7 @@ export declare class ViewerState {
87
88
  toggleFullScreen(): void;
88
89
  toggleMetadataDialog(): void;
89
90
  searchQuery: string;
91
+ pendingSearchQuery: string | null;
90
92
  searchResults: any[];
91
93
  isSearching: boolean;
92
94
  showSearchPanel: boolean;
@@ -95,8 +97,6 @@ export declare class ViewerState {
95
97
  get currentCanvasSearchAnnotations(): any[];
96
98
  search(query: string): Promise<void>;
97
99
  private _performSearch;
98
- /** Registered plugins */
99
- plugins: TriiiceratopsPlugin[];
100
100
  /** Plugin-registered menu buttons */
101
101
  pluginMenuButtons: PluginMenuButton[];
102
102
  /** Plugin-registered panels */
@@ -105,24 +105,27 @@ export declare class ViewerState {
105
105
  osdViewer: any | null;
106
106
  /** Event handlers for inter-plugin communication */
107
107
  private pluginEventHandlers;
108
- /**
109
- * Create plugin context - the stable API surface for plugins.
110
- */
111
- private createPluginContext;
112
108
  /**
113
109
  * Register a plugin with this viewer instance.
110
+ * Accepts a simple PluginDef object.
114
111
  */
115
- registerPlugin(plugin: TriiiceratopsPlugin): void;
112
+ registerPlugin(def: PluginDef): void;
116
113
  /**
117
- * Unregister a plugin by ID.
114
+ * Unregister a plugin's UI components by ID prefix.
115
+ * Note: This cleans up the menu button and panel, but doesn't remove listeners attached by the plugin itself
116
+ * since we don't have a handle on the plugin instance or its cleanup function anymore.
117
+ * Plugins should manage their own cleanup via component lifecycle (onDestroy) if possible.
118
118
  */
119
119
  unregisterPlugin(pluginId: string): void;
120
120
  /**
121
- * Called by OSDViewer when OpenSeadragon is ready.
121
+ * Notify that OSD viewer is ready.
122
+ * With the component-based system, we don't notify plugins individually.
123
+ * Instead, plugins should use the OSDViewer instance from context or listen for 'osd-ready' event (if we emitted one).
124
+ * But since we have direct access to osdViewer in this state, components can just react to it.
122
125
  */
123
- notifyOSDReady(viewer: any): void;
126
+ notifyOSDReady(viewer: OpenSeadragon.Viewer): void;
124
127
  /**
125
- * Destroy all plugins (called on viewer unmount).
128
+ * Cleanup everything.
126
129
  */
127
130
  destroyAllPlugins(): void;
128
131
  }
@@ -54,7 +54,13 @@ export class ViewerState {
54
54
  let canvasIndex = -1;
55
55
  if (this.manifestId && this.canvasId) {
56
56
  const canvases = manifestsState.getCanvases(this.manifestId);
57
- canvasIndex = canvases.findIndex((c) => c.id === this.canvasId);
57
+ canvasIndex = canvases.findIndex((c) => {
58
+ const id = c.id ||
59
+ c['@id'] ||
60
+ (c.getCanvasId ? c.getCanvasId() : null) ||
61
+ (c.getId ? c.getId() : null);
62
+ return id === this.canvasId;
63
+ });
58
64
  }
59
65
  return {
60
66
  manifestId: this.manifestId,
@@ -105,19 +111,16 @@ export class ViewerState {
105
111
  return null;
106
112
  return manifestsState.getManifest(this.manifestId);
107
113
  }
114
+ get manifestEntry() {
115
+ if (!this.manifestId)
116
+ return null;
117
+ return manifestsState.getManifestEntry(this.manifestId);
118
+ }
108
119
  get canvases() {
109
120
  if (!this.manifestId)
110
121
  return [];
111
122
  const canvases = manifestsState.getCanvases(this.manifestId);
112
123
  // Auto-initialize canvasId to first canvas if not set
113
- if (canvases.length > 0 && !this.canvasId) {
114
- // Use setTimeout to avoid updating state during a derived computation
115
- setTimeout(() => {
116
- if (!this.canvasId && canvases.length > 0) {
117
- this.canvasId = canvases[0].id;
118
- }
119
- }, 0);
120
- }
121
124
  return canvases;
122
125
  }
123
126
  get currentCanvasIndex() {
@@ -126,8 +129,14 @@ export class ViewerState {
126
129
  return 0;
127
130
  return -1;
128
131
  }
129
- // Manifesto canvases have an id property
130
- return this.canvases.findIndex((c) => c.id === this.canvasId);
132
+ // Manifesto canvases have an id property, but let's be robust and check multiple possibilities
133
+ return this.canvases.findIndex((c) => {
134
+ const id = c.id ||
135
+ c['@id'] ||
136
+ (c.getCanvasId ? c.getCanvasId() : null) ||
137
+ (c.getId ? c.getId() : null);
138
+ return id === this.canvasId;
139
+ });
131
140
  }
132
141
  get hasNext() {
133
142
  return this.currentCanvasIndex < this.canvases.length - 1;
@@ -220,6 +229,7 @@ export class ViewerState {
220
229
  this.showMetadataDialog = !this.showMetadataDialog;
221
230
  }
222
231
  searchQuery = $state('');
232
+ pendingSearchQuery = $state(null);
223
233
  searchResults = $state([]);
224
234
  isSearching = $state(false);
225
235
  showSearchPanel = $state(false);
@@ -250,8 +260,12 @@ export class ViewerState {
250
260
  this.searchResults = [];
251
261
  try {
252
262
  const manifest = this.manifest;
253
- if (!manifest)
254
- throw new Error('No manifest loaded');
263
+ if (!manifest) {
264
+ // Defer search until manifest is loaded
265
+ console.log('[ViewerState] Manifest not loaded, deferring search:', query);
266
+ this.pendingSearchQuery = query;
267
+ return;
268
+ }
255
269
  let service = manifest.getService('http://iiif.io/api/search/1/search') ||
256
270
  manifest.getService('http://iiif.io/api/search/0/search');
257
271
  if (!service) {
@@ -447,104 +461,81 @@ export class ViewerState {
447
461
  }
448
462
  }
449
463
  // ==================== PLUGIN STATE ====================
450
- /** Registered plugins */
451
- plugins = $state([]);
452
464
  /** Plugin-registered menu buttons */
453
465
  pluginMenuButtons = $state([]);
454
466
  /** Plugin-registered panels */
455
467
  pluginPanels = $state([]);
456
468
  /** OpenSeadragon viewer instance (set by OSDViewer) */
457
- osdViewer = $state(null);
469
+ osdViewer = $state.raw(null);
458
470
  /** Event handlers for inter-plugin communication */
459
471
  pluginEventHandlers = new Map();
460
472
  // ==================== PLUGIN METHODS ====================
461
473
  /**
462
- * Create plugin context - the stable API surface for plugins.
474
+ * Register a plugin with this viewer instance.
475
+ * Accepts a simple PluginDef object.
463
476
  */
464
- createPluginContext() {
465
- const self = this;
466
- return {
467
- viewerState: self,
468
- getOSDViewer: () => self.osdViewer,
469
- registerMenuButton(button) {
470
- if (!self.pluginMenuButtons.find((b) => b.id === button.id)) {
471
- self.pluginMenuButtons = [
472
- ...self.pluginMenuButtons,
473
- button,
474
- ];
475
- }
476
- },
477
- unregisterMenuButton(buttonId) {
478
- self.pluginMenuButtons = self.pluginMenuButtons.filter((b) => b.id !== buttonId);
479
- },
480
- registerPanel(panel) {
481
- if (!self.pluginPanels.find((p) => p.id === panel.id)) {
482
- self.pluginPanels = [...self.pluginPanels, panel];
483
- }
484
- },
485
- unregisterPanel(panelId) {
486
- self.pluginPanels = self.pluginPanels.filter((p) => p.id !== panelId);
477
+ registerPlugin(def) {
478
+ const id = def.id || `plugin-${Math.random().toString(36).substr(2, 9)}`;
479
+ // Create reactive state for this plugin's panel
480
+ // Svelte 5's $state works fine in closures if consumed in reactive context
481
+ let isOpen = $state(false);
482
+ // Register Menu Button
483
+ const button = {
484
+ id: `${id}:toggle`,
485
+ icon: def.icon,
486
+ tooltip: def.name,
487
+ onClick: () => {
488
+ isOpen = !isOpen;
487
489
  },
488
- emit(eventName, data) {
489
- const handlers = self.pluginEventHandlers.get(eventName);
490
- handlers?.forEach((handler) => handler(data));
491
- },
492
- on(eventName, handler) {
493
- if (!self.pluginEventHandlers.has(eventName)) {
494
- self.pluginEventHandlers.set(eventName, new Set());
495
- }
496
- self.pluginEventHandlers.get(eventName).add(handler);
497
- return () => {
498
- self.pluginEventHandlers.get(eventName)?.delete(handler);
499
- };
490
+ isActive: () => isOpen,
491
+ order: 200, // Default order for simple plugins
492
+ };
493
+ // Register Panel
494
+ const panel = {
495
+ id: `${id}:panel`,
496
+ component: def.panel,
497
+ position: def.position || 'left',
498
+ isVisible: () => isOpen,
499
+ props: {
500
+ ...def.props,
501
+ // Pass isOpen state and closer to component
502
+ isOpen: isOpen,
503
+ close: () => {
504
+ isOpen = false;
505
+ },
500
506
  },
501
507
  };
502
- }
503
- /**
504
- * Register a plugin with this viewer instance.
505
- */
506
- registerPlugin(plugin) {
507
- if (this.plugins.find((p) => p.id === plugin.id)) {
508
- console.warn(`[Triiiceratops] Plugin "${plugin.id}" already registered`);
509
- return;
510
- }
511
- this.plugins = [...this.plugins, plugin];
512
- plugin.onRegister(this.createPluginContext());
513
- // If OSD already ready, notify immediately
514
- if (this.osdViewer && plugin.onViewerReady) {
515
- plugin.onViewerReady(this.osdViewer);
508
+ // Add directly to lists
509
+ this.pluginMenuButtons = [...this.pluginMenuButtons, button];
510
+ this.pluginPanels = [...this.pluginPanels, panel];
511
+ // Execute lifecycle hook if present
512
+ if (def.onInit) {
513
+ def.onInit(this);
516
514
  }
517
515
  }
518
516
  /**
519
- * Unregister a plugin by ID.
517
+ * Unregister a plugin's UI components by ID prefix.
518
+ * Note: This cleans up the menu button and panel, but doesn't remove listeners attached by the plugin itself
519
+ * since we don't have a handle on the plugin instance or its cleanup function anymore.
520
+ * Plugins should manage their own cleanup via component lifecycle (onDestroy) if possible.
520
521
  */
521
522
  unregisterPlugin(pluginId) {
522
- const plugin = this.plugins.find((p) => p.id === pluginId);
523
- if (plugin) {
524
- plugin.onDestroy?.();
525
- this.plugins = this.plugins.filter((p) => p.id !== pluginId);
526
- // Remove plugin's UI registrations
527
- this.pluginMenuButtons = this.pluginMenuButtons.filter((b) => !b.id.startsWith(`${pluginId}:`));
528
- this.pluginPanels = this.pluginPanels.filter((p) => !p.id.startsWith(`${pluginId}:`));
529
- }
523
+ this.pluginMenuButtons = this.pluginMenuButtons.filter((b) => !b.id.startsWith(`${pluginId}:`));
524
+ this.pluginPanels = this.pluginPanels.filter((p) => !p.id.startsWith(`${pluginId}:`));
530
525
  }
531
526
  /**
532
- * Called by OSDViewer when OpenSeadragon is ready.
527
+ * Notify that OSD viewer is ready.
528
+ * With the component-based system, we don't notify plugins individually.
529
+ * Instead, plugins should use the OSDViewer instance from context or listen for 'osd-ready' event (if we emitted one).
530
+ * But since we have direct access to osdViewer in this state, components can just react to it.
533
531
  */
534
532
  notifyOSDReady(viewer) {
535
533
  this.osdViewer = viewer;
536
- for (const plugin of this.plugins) {
537
- plugin.onViewerReady?.(viewer);
538
- }
539
534
  }
540
535
  /**
541
- * Destroy all plugins (called on viewer unmount).
536
+ * Cleanup everything.
542
537
  */
543
538
  destroyAllPlugins() {
544
- for (const plugin of this.plugins) {
545
- plugin.onDestroy?.();
546
- }
547
- this.plugins = [];
548
539
  this.pluginMenuButtons = [];
549
540
  this.pluginPanels = [];
550
541
  this.pluginEventHandlers.clear();