triiiceratops 0.8.1 → 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.
- package/dist/chunks/TriiiceratopsViewer-BGtsfUPF.js +10298 -0
- package/dist/chunks/openseadragon-BTypULhm.js +12427 -0
- package/dist/components/AnnotationOverlay.svelte +288 -0
- package/dist/components/AnnotationOverlay.svelte.d.ts +3 -0
- package/dist/components/CanvasNavigation.svelte +32 -0
- package/dist/components/CanvasNavigation.svelte.d.ts +11 -0
- package/dist/components/DemoHeader.svelte +703 -0
- package/dist/components/DemoHeader.svelte.d.ts +9 -0
- package/dist/components/FloatingMenu.svelte +208 -0
- package/dist/components/FloatingMenu.svelte.d.ts +3 -0
- package/dist/components/LeftFab.svelte +69 -0
- package/dist/components/LeftFab.svelte.d.ts +3 -0
- package/dist/components/MetadataDialog.svelte +151 -0
- package/dist/components/MetadataDialog.svelte.d.ts +3 -0
- package/dist/components/OSDViewer.svelte +260 -0
- package/dist/components/OSDViewer.svelte.d.ts +8 -0
- package/dist/components/SearchPanel.svelte +150 -0
- package/dist/components/SearchPanel.svelte.d.ts +3 -0
- package/dist/components/ThemeToggle.svelte +118 -0
- package/dist/components/ThemeToggle.svelte.d.ts +3 -0
- package/dist/components/ThumbnailGallery.svelte +601 -0
- package/dist/components/ThumbnailGallery.svelte.d.ts +36 -0
- package/dist/components/TriiiceratopsViewer.svelte +434 -0
- package/dist/components/TriiiceratopsViewer.svelte.d.ts +20 -0
- package/dist/components/TriiiceratopsViewerElement.svelte +139 -0
- package/dist/components/TriiiceratopsViewerElement.svelte.d.ts +27 -0
- package/dist/components/TriiiceratopsViewerElementImage.svelte +143 -0
- package/dist/components/TriiiceratopsViewerElementImage.svelte.d.ts +27 -0
- package/dist/custom-element-image.d.ts +1 -0
- package/dist/custom-element-image.js +2 -0
- package/dist/custom-element.d.ts +1 -0
- package/dist/custom-element.js +3 -0
- package/dist/{src/lib/index.d.ts → index.d.ts} +1 -0
- package/dist/index.js +10 -4480
- package/dist/plugins/image-manipulation/ImageManipulationPanel.svelte +134 -0
- package/dist/plugins/image-manipulation/ImageManipulationPanel.svelte.d.ts +10 -0
- package/dist/{src/lib/plugins → plugins}/image-manipulation/ImageManipulationPlugin.svelte.d.ts +2 -2
- package/dist/plugins/image-manipulation/ImageManipulationPlugin.svelte.js +122 -0
- package/dist/{src/lib/plugins → plugins}/image-manipulation/filters.d.ts +1 -1
- package/dist/plugins/image-manipulation/filters.js +48 -0
- package/dist/plugins/image-manipulation/index.js +2 -0
- package/dist/plugins/image-manipulation/types.js +7 -0
- package/dist/state/i18n.svelte.d.ts +4 -0
- package/dist/state/i18n.svelte.js +18 -0
- package/dist/state/manifests.svelte.js +210 -0
- package/dist/state/manifests.test.d.ts +1 -0
- package/dist/state/manifests.test.js +242 -0
- package/dist/{src/lib/state → state}/viewer.svelte.d.ts +4 -4
- package/dist/state/viewer.svelte.js +693 -0
- package/dist/theme/colorUtils.js +196 -0
- package/dist/theme/colorUtils.test.d.ts +1 -0
- package/dist/theme/colorUtils.test.js +90 -0
- package/dist/theme/index.js +52 -0
- package/dist/{src/lib/theme → theme}/themeManager.d.ts +4 -1
- package/dist/theme/themeManager.js +177 -0
- package/dist/theme/types.js +40 -0
- package/dist/triiiceratops-bundle.js +4676 -0
- package/dist/triiiceratops-element-image.js +1 -1
- package/dist/triiiceratops-element.js +1 -1
- package/dist/types/config.js +1 -0
- package/dist/{src/lib/types → types}/plugin.d.ts +3 -3
- package/dist/types/plugin.js +36 -0
- package/dist/utils/annotationAdapter.js +354 -0
- package/dist/utils/annotationAdapter.test.d.ts +1 -0
- package/dist/utils/annotationAdapter.test.js +91 -0
- package/package.json +6 -5
- package/dist/chunks/TriiiceratopsViewer-CyamQrMe.js +0 -22698
- package/dist/plugin-De14WKQl.js +0 -546
- package/dist/plugins/image-manipulation.js +0 -454
- package/dist/src/lib/components/AnnotationOverlay.svelte.d.ts +0 -1
- package/dist/src/lib/components/CanvasNavigation.svelte.d.ts +0 -1
- package/dist/src/lib/components/FloatingMenu.svelte.d.ts +0 -1
- package/dist/src/lib/components/LeftFab.svelte.d.ts +0 -1
- package/dist/src/lib/components/MetadataDialog.svelte.d.ts +0 -1
- package/dist/src/lib/components/OSDViewer.svelte.d.ts +0 -1
- package/dist/src/lib/components/SearchPanel.svelte.d.ts +0 -1
- package/dist/src/lib/components/ThumbnailGallery.svelte.d.ts +0 -1
- package/dist/src/lib/components/TriiiceratopsViewer.svelte.d.ts +0 -1
- package/dist/src/lib/custom-element-image.d.ts +0 -0
- package/dist/src/lib/custom-element.d.ts +0 -0
- package/dist/src/lib/paraglide/messages/de.d.ts +0 -96
- package/dist/src/lib/paraglide/messages/en.d.ts +0 -96
- package/dist/src/lib/paraglide/messages.d.ts +0 -272
- package/dist/src/lib/paraglide/runtime.d.ts +0 -52
- package/dist/src/lib/plugins/image-manipulation/ImageManipulationPanel.svelte.d.ts +0 -1
- package/dist/src/lib/state/i18n.svelte.d.ts +0 -5
- /package/dist/{src/lib/plugins → plugins}/image-manipulation/index.d.ts +0 -0
- /package/dist/{src/lib/plugins → plugins}/image-manipulation/types.d.ts +0 -0
- /package/dist/{src/lib/state → state}/manifests.svelte.d.ts +0 -0
- /package/dist/{src/lib/theme → theme}/colorUtils.d.ts +0 -0
- /package/dist/{src/lib/theme → theme}/index.d.ts +0 -0
- /package/dist/{src/lib/theme → theme}/types.d.ts +0 -0
- /package/dist/{src/lib/types → types}/config.d.ts +0 -0
- /package/dist/{src/lib/utils → utils}/annotationAdapter.d.ts +0 -0
|
@@ -0,0 +1,693 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
11
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
12
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
13
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
14
|
+
function step(op) {
|
|
15
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
16
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
17
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
18
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
19
|
+
switch (op[0]) {
|
|
20
|
+
case 0: case 1: t = op; break;
|
|
21
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
22
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
23
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
24
|
+
default:
|
|
25
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
26
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
27
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
28
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
29
|
+
if (t[2]) _.ops.pop();
|
|
30
|
+
_.trys.pop(); continue;
|
|
31
|
+
}
|
|
32
|
+
op = body.call(thisArg, _);
|
|
33
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
34
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
38
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
39
|
+
if (ar || !(i in from)) {
|
|
40
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
41
|
+
ar[i] = from[i];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
45
|
+
};
|
|
46
|
+
import { manifestsState } from './manifests.svelte.js';
|
|
47
|
+
var ViewerState = /** @class */ (function () {
|
|
48
|
+
function ViewerState(initialManifestId, initialCanvasId, initialPlugins) {
|
|
49
|
+
if (initialManifestId === void 0) { initialManifestId = null; }
|
|
50
|
+
if (initialCanvasId === void 0) { initialCanvasId = null; }
|
|
51
|
+
if (initialPlugins === void 0) { initialPlugins = []; }
|
|
52
|
+
this.manifestId = $state(null);
|
|
53
|
+
this.canvasId = $state(null);
|
|
54
|
+
this.showAnnotations = $state(false);
|
|
55
|
+
this.showThumbnailGallery = $state(false);
|
|
56
|
+
this.isGalleryDockedBottom = $state(false);
|
|
57
|
+
this.isGalleryDockedRight = $state(false);
|
|
58
|
+
this.isFullScreen = $state(false);
|
|
59
|
+
this.showMetadataDialog = $state(false);
|
|
60
|
+
this.dockSide = $state('bottom');
|
|
61
|
+
this.visibleAnnotationIds = $state(new Set());
|
|
62
|
+
// UI Configuration
|
|
63
|
+
this.config = $state({});
|
|
64
|
+
// Gallery State (Lifted for persistence during re-docking)
|
|
65
|
+
this.galleryPosition = $state({ x: 20, y: 100 });
|
|
66
|
+
this.gallerySize = $state({ width: 300, height: 400 });
|
|
67
|
+
this.isGalleryDragging = $state(false);
|
|
68
|
+
this.galleryDragOffset = $state({ x: 0, y: 0 });
|
|
69
|
+
this.dragOverSide = $state(null);
|
|
70
|
+
this.galleryCenterPanelRect = $state(null);
|
|
71
|
+
// ==================== EVENT DISPATCH (Web Component Only) ====================
|
|
72
|
+
/**
|
|
73
|
+
* Event target for dispatching CustomEvents.
|
|
74
|
+
* Only set by TriiiceratopsViewerElement (web component build).
|
|
75
|
+
* Remains null for Svelte component usage → no events dispatched.
|
|
76
|
+
*/
|
|
77
|
+
this.eventTarget = null;
|
|
78
|
+
this.searchQuery = $state('');
|
|
79
|
+
this.searchResults = $state([]);
|
|
80
|
+
this.isSearching = $state(false);
|
|
81
|
+
this.showSearchPanel = $state(false);
|
|
82
|
+
this.searchAnnotations = $state([]);
|
|
83
|
+
// ==================== PLUGIN STATE ====================
|
|
84
|
+
/** Registered plugins */
|
|
85
|
+
this.plugins = $state([]);
|
|
86
|
+
/** Plugin-registered menu buttons */
|
|
87
|
+
this.pluginMenuButtons = $state([]);
|
|
88
|
+
/** Plugin-registered panels */
|
|
89
|
+
this.pluginPanels = $state([]);
|
|
90
|
+
/** OpenSeadragon viewer instance (set by OSDViewer) */
|
|
91
|
+
this.osdViewer = $state(null);
|
|
92
|
+
/** Event handlers for inter-plugin communication */
|
|
93
|
+
this.pluginEventHandlers = new Map();
|
|
94
|
+
this.manifestId = initialManifestId || null;
|
|
95
|
+
this.canvasId = initialCanvasId || null;
|
|
96
|
+
// Fetch manifest immediately
|
|
97
|
+
if (this.manifestId) {
|
|
98
|
+
manifestsState.fetchManifest(this.manifestId);
|
|
99
|
+
}
|
|
100
|
+
// Register initial plugins
|
|
101
|
+
for (var _i = 0, initialPlugins_1 = initialPlugins; _i < initialPlugins_1.length; _i++) {
|
|
102
|
+
var initialPlugin = initialPlugins_1[_i];
|
|
103
|
+
this.registerPlugin(initialPlugin);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
Object.defineProperty(ViewerState.prototype, "showRightMenu", {
|
|
107
|
+
// Derived configuration specific getters
|
|
108
|
+
get: function () {
|
|
109
|
+
var _a;
|
|
110
|
+
return (_a = this.config.showRightMenu) !== null && _a !== void 0 ? _a : true;
|
|
111
|
+
},
|
|
112
|
+
enumerable: false,
|
|
113
|
+
configurable: true
|
|
114
|
+
});
|
|
115
|
+
Object.defineProperty(ViewerState.prototype, "showLeftMenu", {
|
|
116
|
+
get: function () {
|
|
117
|
+
var _a;
|
|
118
|
+
return (_a = this.config.showLeftMenu) !== null && _a !== void 0 ? _a : true;
|
|
119
|
+
},
|
|
120
|
+
enumerable: false,
|
|
121
|
+
configurable: true
|
|
122
|
+
});
|
|
123
|
+
Object.defineProperty(ViewerState.prototype, "showCanvasNav", {
|
|
124
|
+
get: function () {
|
|
125
|
+
var _a;
|
|
126
|
+
return (_a = this.config.showCanvasNav) !== null && _a !== void 0 ? _a : true;
|
|
127
|
+
},
|
|
128
|
+
enumerable: false,
|
|
129
|
+
configurable: true
|
|
130
|
+
});
|
|
131
|
+
/**
|
|
132
|
+
* Set the event target for dispatching state change events.
|
|
133
|
+
* Called by TriiiceratopsViewerElement to enable event-driven API.
|
|
134
|
+
*/
|
|
135
|
+
ViewerState.prototype.setEventTarget = function (target) {
|
|
136
|
+
this.eventTarget = target;
|
|
137
|
+
};
|
|
138
|
+
/**
|
|
139
|
+
* Get current state as a plain object snapshot.
|
|
140
|
+
* Safe to use outside Svelte's reactive system.
|
|
141
|
+
* NOTE: We calculate currentCanvasIndex inline to avoid triggering the canvases getter
|
|
142
|
+
* which can cause infinite loops when it auto-sets canvasId.
|
|
143
|
+
*/
|
|
144
|
+
ViewerState.prototype.getSnapshot = function () {
|
|
145
|
+
var _this = this;
|
|
146
|
+
// Calculate canvas index without triggering reactive side effects
|
|
147
|
+
var canvasIndex = -1;
|
|
148
|
+
if (this.manifestId && this.canvasId) {
|
|
149
|
+
var canvases = manifestsState.getCanvases(this.manifestId);
|
|
150
|
+
canvasIndex = canvases.findIndex(function (c) { return c.id === _this.canvasId; });
|
|
151
|
+
}
|
|
152
|
+
return {
|
|
153
|
+
manifestId: this.manifestId,
|
|
154
|
+
canvasId: this.canvasId,
|
|
155
|
+
currentCanvasIndex: canvasIndex,
|
|
156
|
+
showAnnotations: this.showAnnotations,
|
|
157
|
+
showThumbnailGallery: this.showThumbnailGallery,
|
|
158
|
+
showSearchPanel: this.showSearchPanel,
|
|
159
|
+
searchQuery: this.searchQuery,
|
|
160
|
+
isFullScreen: this.isFullScreen,
|
|
161
|
+
dockSide: this.dockSide,
|
|
162
|
+
};
|
|
163
|
+
};
|
|
164
|
+
/**
|
|
165
|
+
* Dispatch a state change event to the web component.
|
|
166
|
+
* No-op if eventTarget is null (Svelte component usage).
|
|
167
|
+
*
|
|
168
|
+
* Uses queueMicrotask to dispatch asynchronously AFTER the current
|
|
169
|
+
* reactive cycle completes, preventing infinite update loops.
|
|
170
|
+
*/
|
|
171
|
+
ViewerState.prototype.dispatchStateChange = function (eventName) {
|
|
172
|
+
var _this = this;
|
|
173
|
+
if (eventName === void 0) { eventName = 'statechange'; }
|
|
174
|
+
console.log("[ViewerState] Dispatching ".concat(eventName), JSON.stringify(this.getSnapshot()));
|
|
175
|
+
if (!this.eventTarget)
|
|
176
|
+
return;
|
|
177
|
+
// Dispatch asynchronously to break reactive loops
|
|
178
|
+
queueMicrotask(function () {
|
|
179
|
+
var _a;
|
|
180
|
+
(_a = _this.eventTarget) === null || _a === void 0 ? void 0 : _a.dispatchEvent(new CustomEvent(eventName, {
|
|
181
|
+
detail: _this.getSnapshot(),
|
|
182
|
+
bubbles: true,
|
|
183
|
+
composed: true,
|
|
184
|
+
}));
|
|
185
|
+
});
|
|
186
|
+
};
|
|
187
|
+
Object.defineProperty(ViewerState.prototype, "manifest", {
|
|
188
|
+
get: function () {
|
|
189
|
+
if (!this.manifestId)
|
|
190
|
+
return null;
|
|
191
|
+
return manifestsState.getManifest(this.manifestId);
|
|
192
|
+
},
|
|
193
|
+
enumerable: false,
|
|
194
|
+
configurable: true
|
|
195
|
+
});
|
|
196
|
+
Object.defineProperty(ViewerState.prototype, "canvases", {
|
|
197
|
+
get: function () {
|
|
198
|
+
var _this = this;
|
|
199
|
+
if (!this.manifestId)
|
|
200
|
+
return [];
|
|
201
|
+
var canvases = manifestsState.getCanvases(this.manifestId);
|
|
202
|
+
// Auto-initialize canvasId to first canvas if not set
|
|
203
|
+
if (canvases.length > 0 && !this.canvasId) {
|
|
204
|
+
// Use setTimeout to avoid updating state during a derived computation
|
|
205
|
+
setTimeout(function () {
|
|
206
|
+
if (!_this.canvasId && canvases.length > 0) {
|
|
207
|
+
_this.canvasId = canvases[0].id;
|
|
208
|
+
}
|
|
209
|
+
}, 0);
|
|
210
|
+
}
|
|
211
|
+
return canvases;
|
|
212
|
+
},
|
|
213
|
+
enumerable: false,
|
|
214
|
+
configurable: true
|
|
215
|
+
});
|
|
216
|
+
Object.defineProperty(ViewerState.prototype, "currentCanvasIndex", {
|
|
217
|
+
get: function () {
|
|
218
|
+
var _this = this;
|
|
219
|
+
if (!this.canvasId) {
|
|
220
|
+
if (this.canvases.length > 0)
|
|
221
|
+
return 0;
|
|
222
|
+
return -1;
|
|
223
|
+
}
|
|
224
|
+
// Manifesto canvases have an id property
|
|
225
|
+
return this.canvases.findIndex(function (c) { return c.id === _this.canvasId; });
|
|
226
|
+
},
|
|
227
|
+
enumerable: false,
|
|
228
|
+
configurable: true
|
|
229
|
+
});
|
|
230
|
+
Object.defineProperty(ViewerState.prototype, "hasNext", {
|
|
231
|
+
get: function () {
|
|
232
|
+
return this.currentCanvasIndex < this.canvases.length - 1;
|
|
233
|
+
},
|
|
234
|
+
enumerable: false,
|
|
235
|
+
configurable: true
|
|
236
|
+
});
|
|
237
|
+
Object.defineProperty(ViewerState.prototype, "hasPrevious", {
|
|
238
|
+
get: function () {
|
|
239
|
+
return this.currentCanvasIndex > 0;
|
|
240
|
+
},
|
|
241
|
+
enumerable: false,
|
|
242
|
+
configurable: true
|
|
243
|
+
});
|
|
244
|
+
ViewerState.prototype.nextCanvas = function () {
|
|
245
|
+
if (this.hasNext) {
|
|
246
|
+
var nextIndex = this.currentCanvasIndex + 1;
|
|
247
|
+
var canvas = this.canvases[nextIndex];
|
|
248
|
+
this.setCanvas(canvas.id);
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
ViewerState.prototype.previousCanvas = function () {
|
|
252
|
+
if (this.hasPrevious) {
|
|
253
|
+
var prevIndex = this.currentCanvasIndex - 1;
|
|
254
|
+
var canvas = this.canvases[prevIndex];
|
|
255
|
+
this.setCanvas(canvas.id);
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
ViewerState.prototype.setManifest = function (manifestId) {
|
|
259
|
+
this.manifestId = manifestId;
|
|
260
|
+
this.canvasId = null;
|
|
261
|
+
manifestsState.fetchManifest(manifestId);
|
|
262
|
+
this.dispatchStateChange('manifestchange');
|
|
263
|
+
};
|
|
264
|
+
ViewerState.prototype.setCanvas = function (canvasId) {
|
|
265
|
+
this.canvasId = canvasId;
|
|
266
|
+
this.dispatchStateChange('canvaschange');
|
|
267
|
+
};
|
|
268
|
+
ViewerState.prototype.updateConfig = function (newConfig) {
|
|
269
|
+
var _a;
|
|
270
|
+
var oldConfig = this.config;
|
|
271
|
+
this.config = newConfig;
|
|
272
|
+
// Sync state from config
|
|
273
|
+
if (newConfig.gallery) {
|
|
274
|
+
if (newConfig.gallery.open !== undefined) {
|
|
275
|
+
this.showThumbnailGallery = newConfig.gallery.open;
|
|
276
|
+
}
|
|
277
|
+
if (newConfig.gallery.dockPosition !== undefined) {
|
|
278
|
+
this.dockSide = newConfig.gallery.dockPosition;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
if (newConfig.search) {
|
|
282
|
+
if (newConfig.search.open !== undefined) {
|
|
283
|
+
this.showSearchPanel = newConfig.search.open;
|
|
284
|
+
}
|
|
285
|
+
// Only search if the CONFIG has changed its query requirement.
|
|
286
|
+
// This prevents stale config updates (e.g. from other property changes)
|
|
287
|
+
// from overwriting a newer internal search state.
|
|
288
|
+
var newQuery = newConfig.search.query;
|
|
289
|
+
var oldQuery = (_a = oldConfig.search) === null || _a === void 0 ? void 0 : _a.query;
|
|
290
|
+
if (newQuery !== undefined &&
|
|
291
|
+
newQuery !== oldQuery &&
|
|
292
|
+
newQuery !== this.searchQuery) {
|
|
293
|
+
this._performSearch(newQuery);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
if (newConfig.annotations) {
|
|
297
|
+
if (newConfig.annotations.open !== undefined) {
|
|
298
|
+
this.showAnnotations = newConfig.annotations.open;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
// NOTE: We intentionally do NOT dispatch events here.
|
|
302
|
+
// Config updates are external configuration, not user-initiated state changes.
|
|
303
|
+
// Dispatching here would cause infinite loops when the consumer re-renders.
|
|
304
|
+
};
|
|
305
|
+
ViewerState.prototype.toggleAnnotations = function () {
|
|
306
|
+
this.showAnnotations = !this.showAnnotations;
|
|
307
|
+
this.dispatchStateChange();
|
|
308
|
+
};
|
|
309
|
+
ViewerState.prototype.toggleThumbnailGallery = function () {
|
|
310
|
+
this.showThumbnailGallery = !this.showThumbnailGallery;
|
|
311
|
+
this.dispatchStateChange();
|
|
312
|
+
};
|
|
313
|
+
ViewerState.prototype.toggleFullScreen = function () {
|
|
314
|
+
if (!document.fullscreenElement) {
|
|
315
|
+
var el = document.getElementById('triiiceratops-viewer');
|
|
316
|
+
if (el) {
|
|
317
|
+
el.requestFullscreen().catch(function (e) {
|
|
318
|
+
console.warn('Fullscreen request failed', e);
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
document.exitFullscreen();
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
ViewerState.prototype.toggleMetadataDialog = function () {
|
|
327
|
+
this.showMetadataDialog = !this.showMetadataDialog;
|
|
328
|
+
};
|
|
329
|
+
ViewerState.prototype.toggleSearchPanel = function () {
|
|
330
|
+
this.showSearchPanel = !this.showSearchPanel;
|
|
331
|
+
if (!this.showSearchPanel) {
|
|
332
|
+
// Clear ephemeral annotations when closing search
|
|
333
|
+
this.searchAnnotations = [];
|
|
334
|
+
}
|
|
335
|
+
this.dispatchStateChange();
|
|
336
|
+
};
|
|
337
|
+
Object.defineProperty(ViewerState.prototype, "currentCanvasSearchAnnotations", {
|
|
338
|
+
get: function () {
|
|
339
|
+
var _this = this;
|
|
340
|
+
if (!this.canvasId)
|
|
341
|
+
return [];
|
|
342
|
+
return this.searchAnnotations.filter(function (a) { return a.canvasId === _this.canvasId; });
|
|
343
|
+
},
|
|
344
|
+
enumerable: false,
|
|
345
|
+
configurable: true
|
|
346
|
+
});
|
|
347
|
+
ViewerState.prototype.search = function (query) {
|
|
348
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
349
|
+
return __generator(this, function (_a) {
|
|
350
|
+
switch (_a.label) {
|
|
351
|
+
case 0:
|
|
352
|
+
this.dispatchStateChange();
|
|
353
|
+
return [4 /*yield*/, this._performSearch(query)];
|
|
354
|
+
case 1:
|
|
355
|
+
_a.sent();
|
|
356
|
+
this.dispatchStateChange();
|
|
357
|
+
return [2 /*return*/];
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
});
|
|
361
|
+
};
|
|
362
|
+
ViewerState.prototype._performSearch = function (query) {
|
|
363
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
364
|
+
var manifest, service, services, serviceId, searchUrl, response, data, resources, processedResults, parseSelector, _i, _a, hit, annotations, hitBoundsByCanvas, _loop_1, this_1, _b, annotations_1, annoId, _c, hitBoundsByCanvas_1, _d, canvasIndex, data_1, _loop_2, this_2, _e, resources_1, res, annotationIndex_1, e_1;
|
|
365
|
+
var _this = this;
|
|
366
|
+
var _f, _g;
|
|
367
|
+
return __generator(this, function (_h) {
|
|
368
|
+
switch (_h.label) {
|
|
369
|
+
case 0:
|
|
370
|
+
if (!query.trim())
|
|
371
|
+
return [2 /*return*/];
|
|
372
|
+
this.isSearching = true;
|
|
373
|
+
this.searchQuery = query;
|
|
374
|
+
this.searchResults = [];
|
|
375
|
+
_h.label = 1;
|
|
376
|
+
case 1:
|
|
377
|
+
_h.trys.push([1, 4, 5, 6]);
|
|
378
|
+
manifest = this.manifest;
|
|
379
|
+
if (!manifest)
|
|
380
|
+
throw new Error('No manifest loaded');
|
|
381
|
+
service = manifest.getService('http://iiif.io/api/search/1/search') ||
|
|
382
|
+
manifest.getService('http://iiif.io/api/search/0/search');
|
|
383
|
+
if (!service) {
|
|
384
|
+
// Fallback: check json directly if manifesto fails me
|
|
385
|
+
if (manifest.__jsonld && manifest.__jsonld.service) {
|
|
386
|
+
services = Array.isArray(manifest.__jsonld.service)
|
|
387
|
+
? manifest.__jsonld.service
|
|
388
|
+
: [manifest.__jsonld.service];
|
|
389
|
+
service = services.find(function (s) {
|
|
390
|
+
return s.profile ===
|
|
391
|
+
'http://iiif.io/api/search/1/search' ||
|
|
392
|
+
s.profile === 'http://iiif.io/api/search/0/search';
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
if (!service) {
|
|
397
|
+
console.warn('No IIIF search service found in manifest');
|
|
398
|
+
this.isSearching = false;
|
|
399
|
+
return [2 /*return*/];
|
|
400
|
+
}
|
|
401
|
+
serviceId = service.id || service['@id'];
|
|
402
|
+
searchUrl = "".concat(serviceId, "?q=").concat(encodeURIComponent(query));
|
|
403
|
+
return [4 /*yield*/, fetch(searchUrl)];
|
|
404
|
+
case 2:
|
|
405
|
+
response = _h.sent();
|
|
406
|
+
if (!response.ok)
|
|
407
|
+
throw new Error('Search request failed');
|
|
408
|
+
return [4 /*yield*/, response.json()];
|
|
409
|
+
case 3:
|
|
410
|
+
data = _h.sent();
|
|
411
|
+
resources = data.resources || [];
|
|
412
|
+
processedResults = [];
|
|
413
|
+
parseSelector = function (onVal) {
|
|
414
|
+
var val = typeof onVal === 'string'
|
|
415
|
+
? onVal
|
|
416
|
+
: onVal['@id'] || onVal.id;
|
|
417
|
+
if (!val)
|
|
418
|
+
return null;
|
|
419
|
+
var parts = val.split('#xywh=');
|
|
420
|
+
if (parts.length < 2)
|
|
421
|
+
return null;
|
|
422
|
+
var coords = parts[1].split(',').map(Number);
|
|
423
|
+
if (coords.length === 4)
|
|
424
|
+
return coords; // [x, y, w, h]
|
|
425
|
+
return null;
|
|
426
|
+
};
|
|
427
|
+
if (data.hits) {
|
|
428
|
+
for (_i = 0, _a = data.hits; _i < _a.length; _i++) {
|
|
429
|
+
hit = _a[_i];
|
|
430
|
+
annotations = hit.annotations || [];
|
|
431
|
+
hitBoundsByCanvas = new Map();
|
|
432
|
+
_loop_1 = function (annoId) {
|
|
433
|
+
var annotation = resources.find(function (r) { return r['@id'] === annoId || r.id === annoId; });
|
|
434
|
+
if (annotation && annotation.on) {
|
|
435
|
+
// annotation.on can be "canvas-id" or "canvas-id#xywh=..."
|
|
436
|
+
var onVal = typeof annotation.on === 'string'
|
|
437
|
+
? annotation.on
|
|
438
|
+
: annotation.on['@id'] || annotation.on.id;
|
|
439
|
+
var cleanOn_1 = onVal.split('#')[0];
|
|
440
|
+
var bounds = parseSelector(onVal);
|
|
441
|
+
var canvasIndex = this_1.canvases.findIndex(function (c) { return c.id === cleanOn_1; });
|
|
442
|
+
if (canvasIndex >= 0) {
|
|
443
|
+
if (!hitBoundsByCanvas.has(canvasIndex)) {
|
|
444
|
+
var canvas = this_1.canvases[canvasIndex];
|
|
445
|
+
// Try to get a label
|
|
446
|
+
var label = 'Canvas ' + (canvasIndex + 1);
|
|
447
|
+
try {
|
|
448
|
+
if (canvas.getLabel) {
|
|
449
|
+
var l = canvas.getLabel();
|
|
450
|
+
if (Array.isArray(l) &&
|
|
451
|
+
l.length > 0)
|
|
452
|
+
label = l[0].value;
|
|
453
|
+
else if (typeof l === 'string')
|
|
454
|
+
label = l;
|
|
455
|
+
}
|
|
456
|
+
else if (canvas.label) {
|
|
457
|
+
// Fallback if raw object
|
|
458
|
+
if (typeof canvas.label === 'string')
|
|
459
|
+
label = canvas.label;
|
|
460
|
+
else if (Array.isArray(canvas.label))
|
|
461
|
+
label = (_f = canvas.label[0]) === null || _f === void 0 ? void 0 : _f.value;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
catch (e) {
|
|
465
|
+
/* ignore */
|
|
466
|
+
}
|
|
467
|
+
hitBoundsByCanvas.set(canvasIndex, {
|
|
468
|
+
label: String(label),
|
|
469
|
+
bounds: [],
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
if (bounds) {
|
|
473
|
+
hitBoundsByCanvas
|
|
474
|
+
.get(canvasIndex)
|
|
475
|
+
.bounds.push(bounds);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
};
|
|
480
|
+
this_1 = this;
|
|
481
|
+
for (_b = 0, annotations_1 = annotations; _b < annotations_1.length; _b++) {
|
|
482
|
+
annoId = annotations_1[_b];
|
|
483
|
+
_loop_1(annoId);
|
|
484
|
+
}
|
|
485
|
+
// Create one result per canvas for this hit
|
|
486
|
+
for (_c = 0, hitBoundsByCanvas_1 = hitBoundsByCanvas; _c < hitBoundsByCanvas_1.length; _c++) {
|
|
487
|
+
_d = hitBoundsByCanvas_1[_c], canvasIndex = _d[0], data_1 = _d[1];
|
|
488
|
+
processedResults.push({
|
|
489
|
+
type: 'hit',
|
|
490
|
+
before: hit.before,
|
|
491
|
+
match: hit.match,
|
|
492
|
+
after: hit.after,
|
|
493
|
+
canvasIndex: canvasIndex,
|
|
494
|
+
canvasLabel: data_1.label,
|
|
495
|
+
// Store all bounds for this hit on this canvas
|
|
496
|
+
allBounds: data_1.bounds,
|
|
497
|
+
// Keep first bounds for backwards compatibility
|
|
498
|
+
bounds: data_1.bounds.length > 0 ? data_1.bounds[0] : null,
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
else if (resources.length > 0) {
|
|
504
|
+
_loop_2 = function (res) {
|
|
505
|
+
var onVal = typeof res.on === 'string'
|
|
506
|
+
? res.on
|
|
507
|
+
: res.on['@id'] || res.on.id;
|
|
508
|
+
var cleanOn = onVal.split('#')[0];
|
|
509
|
+
var bounds = parseSelector(onVal);
|
|
510
|
+
var canvasIndex = this_2.canvases.findIndex(function (c) { return c.id === cleanOn; });
|
|
511
|
+
if (canvasIndex >= 0) {
|
|
512
|
+
var canvas = this_2.canvases[canvasIndex];
|
|
513
|
+
var label = 'Canvas ' + (canvasIndex + 1);
|
|
514
|
+
try {
|
|
515
|
+
if (canvas.getLabel) {
|
|
516
|
+
var l = canvas.getLabel();
|
|
517
|
+
if (Array.isArray(l) && l.length > 0)
|
|
518
|
+
label = l[0].value;
|
|
519
|
+
else if (typeof l === 'string')
|
|
520
|
+
label = l;
|
|
521
|
+
}
|
|
522
|
+
else if (canvas.label) {
|
|
523
|
+
// Fallback if raw object
|
|
524
|
+
if (typeof canvas.label === 'string')
|
|
525
|
+
label = canvas.label;
|
|
526
|
+
else if (Array.isArray(canvas.label))
|
|
527
|
+
label = (_g = canvas.label[0]) === null || _g === void 0 ? void 0 : _g.value;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
catch (e) {
|
|
531
|
+
/* ignore */
|
|
532
|
+
}
|
|
533
|
+
processedResults.push({
|
|
534
|
+
type: 'resource',
|
|
535
|
+
match: res.resource && res.resource.chars
|
|
536
|
+
? res.resource.chars
|
|
537
|
+
: res.chars || '',
|
|
538
|
+
canvasIndex: canvasIndex,
|
|
539
|
+
canvasLabel: String(label),
|
|
540
|
+
bounds: bounds,
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
};
|
|
544
|
+
this_2 = this;
|
|
545
|
+
// No hits (Basic level?), just annotations
|
|
546
|
+
for (_e = 0, resources_1 = resources; _e < resources_1.length; _e++) {
|
|
547
|
+
res = resources_1[_e];
|
|
548
|
+
_loop_2(res);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
this.searchResults = processedResults;
|
|
552
|
+
annotationIndex_1 = 0;
|
|
553
|
+
this.searchAnnotations = processedResults.flatMap(function (r) {
|
|
554
|
+
var canvas = _this.canvases[r.canvasIndex];
|
|
555
|
+
// Use allBounds if available, otherwise fall back to single bounds
|
|
556
|
+
var boundsArray = r.allBounds && r.allBounds.length > 0
|
|
557
|
+
? r.allBounds
|
|
558
|
+
: r.bounds
|
|
559
|
+
? [r.bounds]
|
|
560
|
+
: [];
|
|
561
|
+
return boundsArray.map(function (bounds) {
|
|
562
|
+
var on = "".concat(canvas.id, "#xywh=").concat(bounds.join(','));
|
|
563
|
+
return {
|
|
564
|
+
'@id': "urn:search-hit:".concat(annotationIndex_1++),
|
|
565
|
+
'@type': 'oa:Annotation',
|
|
566
|
+
motivation: 'sc:painting',
|
|
567
|
+
on: on,
|
|
568
|
+
canvasId: canvas.id,
|
|
569
|
+
resource: {
|
|
570
|
+
'@type': 'cnt:ContentAsText',
|
|
571
|
+
chars: r.match,
|
|
572
|
+
},
|
|
573
|
+
// Flag to identify styling in Overlay?
|
|
574
|
+
// Or just standard rendering.
|
|
575
|
+
isSearchHit: true,
|
|
576
|
+
};
|
|
577
|
+
});
|
|
578
|
+
});
|
|
579
|
+
return [3 /*break*/, 6];
|
|
580
|
+
case 4:
|
|
581
|
+
e_1 = _h.sent();
|
|
582
|
+
console.error('Search error:', e_1);
|
|
583
|
+
return [3 /*break*/, 6];
|
|
584
|
+
case 5:
|
|
585
|
+
this.isSearching = false;
|
|
586
|
+
return [7 /*endfinally*/];
|
|
587
|
+
case 6: return [2 /*return*/];
|
|
588
|
+
}
|
|
589
|
+
});
|
|
590
|
+
});
|
|
591
|
+
};
|
|
592
|
+
// ==================== PLUGIN METHODS ====================
|
|
593
|
+
/**
|
|
594
|
+
* Create plugin context - the stable API surface for plugins.
|
|
595
|
+
*/
|
|
596
|
+
ViewerState.prototype.createPluginContext = function () {
|
|
597
|
+
var self = this;
|
|
598
|
+
return {
|
|
599
|
+
viewerState: self,
|
|
600
|
+
getOSDViewer: function () { return self.osdViewer; },
|
|
601
|
+
registerMenuButton: function (button) {
|
|
602
|
+
if (!self.pluginMenuButtons.find(function (b) { return b.id === button.id; })) {
|
|
603
|
+
self.pluginMenuButtons = __spreadArray(__spreadArray([], self.pluginMenuButtons, true), [
|
|
604
|
+
button,
|
|
605
|
+
], false);
|
|
606
|
+
}
|
|
607
|
+
},
|
|
608
|
+
unregisterMenuButton: function (buttonId) {
|
|
609
|
+
self.pluginMenuButtons = self.pluginMenuButtons.filter(function (b) { return b.id !== buttonId; });
|
|
610
|
+
},
|
|
611
|
+
registerPanel: function (panel) {
|
|
612
|
+
if (!self.pluginPanels.find(function (p) { return p.id === panel.id; })) {
|
|
613
|
+
self.pluginPanels = __spreadArray(__spreadArray([], self.pluginPanels, true), [panel], false);
|
|
614
|
+
}
|
|
615
|
+
},
|
|
616
|
+
unregisterPanel: function (panelId) {
|
|
617
|
+
self.pluginPanels = self.pluginPanels.filter(function (p) { return p.id !== panelId; });
|
|
618
|
+
},
|
|
619
|
+
emit: function (eventName, data) {
|
|
620
|
+
var handlers = self.pluginEventHandlers.get(eventName);
|
|
621
|
+
handlers === null || handlers === void 0 ? void 0 : handlers.forEach(function (handler) { return handler(data); });
|
|
622
|
+
},
|
|
623
|
+
on: function (eventName, handler) {
|
|
624
|
+
if (!self.pluginEventHandlers.has(eventName)) {
|
|
625
|
+
self.pluginEventHandlers.set(eventName, new Set());
|
|
626
|
+
}
|
|
627
|
+
self.pluginEventHandlers.get(eventName).add(handler);
|
|
628
|
+
return function () {
|
|
629
|
+
var _a;
|
|
630
|
+
(_a = self.pluginEventHandlers.get(eventName)) === null || _a === void 0 ? void 0 : _a.delete(handler);
|
|
631
|
+
};
|
|
632
|
+
},
|
|
633
|
+
};
|
|
634
|
+
};
|
|
635
|
+
/**
|
|
636
|
+
* Register a plugin with this viewer instance.
|
|
637
|
+
*/
|
|
638
|
+
ViewerState.prototype.registerPlugin = function (plugin) {
|
|
639
|
+
if (this.plugins.find(function (p) { return p.id === plugin.id; })) {
|
|
640
|
+
console.warn("[Triiiceratops] Plugin \"".concat(plugin.id, "\" already registered"));
|
|
641
|
+
return;
|
|
642
|
+
}
|
|
643
|
+
this.plugins = __spreadArray(__spreadArray([], this.plugins, true), [plugin], false);
|
|
644
|
+
plugin.onRegister(this.createPluginContext());
|
|
645
|
+
// If OSD already ready, notify immediately
|
|
646
|
+
if (this.osdViewer && plugin.onViewerReady) {
|
|
647
|
+
plugin.onViewerReady(this.osdViewer);
|
|
648
|
+
}
|
|
649
|
+
};
|
|
650
|
+
/**
|
|
651
|
+
* Unregister a plugin by ID.
|
|
652
|
+
*/
|
|
653
|
+
ViewerState.prototype.unregisterPlugin = function (pluginId) {
|
|
654
|
+
var _a;
|
|
655
|
+
var plugin = this.plugins.find(function (p) { return p.id === pluginId; });
|
|
656
|
+
if (plugin) {
|
|
657
|
+
(_a = plugin.onDestroy) === null || _a === void 0 ? void 0 : _a.call(plugin);
|
|
658
|
+
this.plugins = this.plugins.filter(function (p) { return p.id !== pluginId; });
|
|
659
|
+
// Remove plugin's UI registrations
|
|
660
|
+
this.pluginMenuButtons = this.pluginMenuButtons.filter(function (b) { return !b.id.startsWith("".concat(pluginId, ":")); });
|
|
661
|
+
this.pluginPanels = this.pluginPanels.filter(function (p) { return !p.id.startsWith("".concat(pluginId, ":")); });
|
|
662
|
+
}
|
|
663
|
+
};
|
|
664
|
+
/**
|
|
665
|
+
* Called by OSDViewer when OpenSeadragon is ready.
|
|
666
|
+
*/
|
|
667
|
+
ViewerState.prototype.notifyOSDReady = function (viewer) {
|
|
668
|
+
var _a;
|
|
669
|
+
this.osdViewer = viewer;
|
|
670
|
+
for (var _i = 0, _b = this.plugins; _i < _b.length; _i++) {
|
|
671
|
+
var plugin = _b[_i];
|
|
672
|
+
(_a = plugin.onViewerReady) === null || _a === void 0 ? void 0 : _a.call(plugin, viewer);
|
|
673
|
+
}
|
|
674
|
+
};
|
|
675
|
+
/**
|
|
676
|
+
* Destroy all plugins (called on viewer unmount).
|
|
677
|
+
*/
|
|
678
|
+
ViewerState.prototype.destroyAllPlugins = function () {
|
|
679
|
+
var _a;
|
|
680
|
+
for (var _i = 0, _b = this.plugins; _i < _b.length; _i++) {
|
|
681
|
+
var plugin = _b[_i];
|
|
682
|
+
(_a = plugin.onDestroy) === null || _a === void 0 ? void 0 : _a.call(plugin);
|
|
683
|
+
}
|
|
684
|
+
this.plugins = [];
|
|
685
|
+
this.pluginMenuButtons = [];
|
|
686
|
+
this.pluginPanels = [];
|
|
687
|
+
this.pluginEventHandlers.clear();
|
|
688
|
+
};
|
|
689
|
+
return ViewerState;
|
|
690
|
+
}());
|
|
691
|
+
export { ViewerState };
|
|
692
|
+
// Context key for providing/injecting ViewerState in components
|
|
693
|
+
export var VIEWER_STATE_KEY = 'triiiceratops:viewerState';
|