dbf-mirador 4.3.0-testing2 → 4.3.0-testing4

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 (28) hide show
  1. package/README.md +35 -13
  2. package/dist/{CommentSharp-DaW0oBJy.js → CommentSharp-BJ6oQAe3.js} +2 -2
  3. package/dist/{CommentSharp-DaW0oBJy.js.map → CommentSharp-BJ6oQAe3.js.map} +1 -1
  4. package/dist/{FailedImageContext-DYZ9cZx9.js → FailedImageContext-BhA0TpVp.js} +22 -1
  5. package/dist/FailedImageContext-BhA0TpVp.js.map +1 -0
  6. package/dist/{GalleryView-DyLH1kk0.js → GalleryView-rCx0Q4f3.js} +3 -3
  7. package/dist/{GalleryView-DyLH1kk0.js.map → GalleryView-rCx0Q4f3.js.map} +1 -1
  8. package/dist/{OpenSeadragonViewer-CBmX5sYE.js → OpenSeadragonViewer-4nw8qaVM.js} +377 -327
  9. package/dist/OpenSeadragonViewer-4nw8qaVM.js.map +1 -0
  10. package/dist/{WindowViewer-BW0_w7wv.js → WindowViewer-uHVYcMsX.js} +2 -2
  11. package/dist/{WindowViewer-BW0_w7wv.js.map → WindowViewer-uHVYcMsX.js.map} +1 -1
  12. package/dist/{WorkspaceArea-C0RjqnIL.js → WorkspaceArea-7bydz9m-.js} +11 -11
  13. package/dist/{WorkspaceArea-C0RjqnIL.js.map → WorkspaceArea-7bydz9m-.js.map} +1 -1
  14. package/dist/mirador.es.js +1310 -1110
  15. package/dist/mirador.es.js.map +1 -1
  16. package/dist/mirador.min.js +65 -65
  17. package/dist/mirador.min.js.map +1 -1
  18. package/package.json +6 -2
  19. package/src/assets/icons/poi-marker.svg +2 -0
  20. package/src/components/AnnotationsOverlay.jsx +50 -28
  21. package/src/components/MapViewer.jsx +80 -0
  22. package/src/components/index.js +1 -0
  23. package/src/lib/AnnotationItem.js +18 -0
  24. package/src/lib/AnnotationResource.js +14 -0
  25. package/src/lib/CanvasAnnotationDisplay.js +104 -0
  26. package/src/plugins/poiPreviewPlugin.tsx +357 -0
  27. package/dist/FailedImageContext-DYZ9cZx9.js.map +0 -1
  28. package/dist/OpenSeadragonViewer-CBmX5sYE.js.map +0 -1
@@ -0,0 +1,357 @@
1
+ import { useState, type ComponentType } from 'react';
2
+ import useMediaQuery from '@mui/material/useMediaQuery';
3
+ import { useTheme } from '@mui/material/styles';
4
+ import {
5
+ ConnectedCompanionWindow as CompanionWindow,
6
+ addCompanionWindow,
7
+ getAnnotations,
8
+ getCompanionWindow,
9
+ getCompanionWindows,
10
+ getVisibleCanvases,
11
+ updateCompanionWindow,
12
+ // Relative, not `from 'dbf-mirador'`: this file lives inside the dbf-mirador package
13
+ // itself (unlike its copy in the Strapi maps plugin, a real external consumer), and
14
+ // there's no self-referencing node_modules link or dist build for the package name to
15
+ // resolve against during local dev.
16
+ } from '../index';
17
+
18
+ // A "dumb" way to preview a POI/journey (issue #375): a Mirador companion window plugin,
19
+ // registered alongside dbf-mirador-annotation-editor's own (see MiradorMaeViewer.tsx) via
20
+ // Mirador's `companionWindowKey` mechanism - no core patch needed, just adding this plugin
21
+ // to the same `plugins` array. The actual "Preview" button lives per-row in
22
+ // dbf-mirador-annotation-editor's own CanvasListItem.jsx, right next to Edit/Delete
23
+ // (see that package's own PR for issue #375) - it opens this companion window passing the
24
+ // specific row's id as `annotationid`, the same convention MAE's own 'annotationCreation'
25
+ // companion window already uses for its own Edit button.
26
+ //
27
+ // Journeys (issue #378) get a richer path here: instead of the "dumb" dual-locale dump
28
+ // below, a Journey renders its ordered stops as numbered cards with a single active
29
+ // locale (toggle EN/AR), closer to how the public site will eventually present it. Two
30
+ // pieces of the Figma design are intentionally NOT built here, per the issue author's own
31
+ // follow-up comment saying they "wait more precision": numbered pins drawn on the map
32
+ // canvas itself, and an SVG line joining those pins in journey order.
33
+
34
+ const POI_PREVIEW_CONTENT_ID = 'mapsPoiPreview';
35
+
36
+ type TextualAnnotationBody = {
37
+ purpose: 'identifying' | 'describing';
38
+ type: 'TextualBody';
39
+ language: string;
40
+ value: string;
41
+ };
42
+
43
+ // Mirrors the maps plugin's `Annotation['dbf:mediaEn']`/`Annotation['dbf:mediaAr']`
44
+ // (issue #377) - one media selection per language, unlike the single, language-agnostic
45
+ // `dbf:media` extension issue #391 briefly introduced.
46
+ type DbfMedia = {
47
+ source: 'upload' | 'iiif-image' | 'media-item';
48
+ id: string;
49
+ title: string | null;
50
+ mediaType?: string | null;
51
+ thumbnailUrl: string | null;
52
+ };
53
+
54
+ type RawAnnotation = {
55
+ id: string;
56
+ 'dbf:kind'?: 'POI' | 'Journey';
57
+ 'dbf:mediaEn'?: DbfMedia | null;
58
+ 'dbf:mediaAr'?: DbfMedia | null;
59
+ // A POI's membership in a journey and its position within it - a Journey never lists
60
+ // its own POIs, membership is always POI -> Journey (see mirador-annotation-editor's
61
+ // annotationListGrouping.js, which this plugin can't import directly since grouping
62
+ // isn't part of that package's public API - so the same filter+sort is redone below).
63
+ 'dbf:journey'?: { id: string; order: number } | null;
64
+ body?: TextualAnnotationBody[];
65
+ };
66
+
67
+ // Both locales, side by side - see the module comment above: the point of a "dumb" preview
68
+ // is to see everything a poi/journey holds, not to render it the way the public site
69
+ // eventually will for one active language.
70
+ const LOCALES = ['en', 'ar'] as const;
71
+
72
+ const textBody = (
73
+ annotation: RawAnnotation,
74
+ language: string,
75
+ purpose: 'identifying' | 'describing'
76
+ ): string =>
77
+ annotation.body?.find(
78
+ (item): item is TextualAnnotationBody =>
79
+ item.type === 'TextualBody' && item.purpose === purpose && item.language === language
80
+ )?.value ?? '';
81
+
82
+ const mediaForLocale = (annotation: RawAnnotation, locale: (typeof LOCALES)[number]): DbfMedia | null | undefined =>
83
+ locale === 'en' ? annotation['dbf:mediaEn'] : annotation['dbf:mediaAr'];
84
+
85
+ // A journey's ordered stops, derived the same way the rest of the codebase does: every
86
+ // POI whose `dbf:journey.id` points at this journey, sorted by `dbf:journey.order`.
87
+ export const getOrderedJourneyPois = (items: RawAnnotation[], journeyId: string): RawAnnotation[] =>
88
+ items
89
+ .filter(
90
+ (item): item is RawAnnotation & { 'dbf:journey': { id: string; order: number } } =>
91
+ item['dbf:kind'] === 'POI' && item['dbf:journey']?.id === journeyId
92
+ )
93
+ .sort((a, b) => a['dbf:journey'].order - b['dbf:journey'].order);
94
+
95
+ const JOURNEY_PREVIEW_LOCALES = ['en', 'ar'] as const;
96
+ type JourneyPreviewLocale = (typeof JOURNEY_PREVIEW_LOCALES)[number];
97
+
98
+ // Arabic is the only RTL locale this project handles today (mirrors the same check in
99
+ // mirador-annotation-editor's POITemplate.jsx/JourneyTemplate.jsx).
100
+ const isRtlLocale = (locale: string) => locale.toLowerCase().startsWith('ar');
101
+
102
+ interface JourneyPreviewContentProps {
103
+ id: string;
104
+ journey: RawAnnotation;
105
+ pois: RawAnnotation[];
106
+ windowId: string;
107
+ }
108
+
109
+ const JourneyPreviewContent = ({ id, journey, pois, windowId }: JourneyPreviewContentProps) => {
110
+ const [locale, setLocale] = useState<JourneyPreviewLocale>('en');
111
+ const journeyTitle = textBody(journey, locale, 'identifying');
112
+
113
+ return (
114
+ <CompanionWindow id={id} title={journeyTitle || 'Journey'} windowId={windowId}>
115
+ <div dir={isRtlLocale(locale) ? 'rtl' : 'ltr'} style={{ padding: 16 }}>
116
+ <div style={{ display: 'flex', justifyContent: 'flex-end', gap: 4, marginBottom: 16 }}>
117
+ {JOURNEY_PREVIEW_LOCALES.map((code) => (
118
+ <button
119
+ aria-pressed={locale === code}
120
+ key={code}
121
+ onClick={() => setLocale(code)}
122
+ style={{
123
+ background: locale === code ? '#333' : 'transparent',
124
+ border: '1px solid #333',
125
+ borderRadius: 4,
126
+ color: locale === code ? '#fff' : '#333',
127
+ cursor: 'pointer',
128
+ padding: '4px 12px',
129
+ }}
130
+ type="button"
131
+ >
132
+ {code.toUpperCase()}
133
+ </button>
134
+ ))}
135
+ </div>
136
+ {pois.length === 0 && <p>This journey has no stops yet.</p>}
137
+ {pois.map((poi, index) => {
138
+ const poiTitle = textBody(poi, locale, 'identifying');
139
+ const description = textBody(poi, locale, 'describing');
140
+ const media = mediaForLocale(poi, locale);
141
+ const isLast = index === pois.length - 1;
142
+ return (
143
+ <div key={poi.id} style={{ display: 'flex' }}>
144
+ <div
145
+ style={{
146
+ alignItems: 'center',
147
+ display: 'flex',
148
+ flexDirection: 'column',
149
+ marginInlineEnd: 16,
150
+ }}
151
+ >
152
+ <span
153
+ style={{
154
+ alignItems: 'center',
155
+ background: '#000',
156
+ borderRadius: '50%',
157
+ color: '#fff',
158
+ display: 'flex',
159
+ flexShrink: 0,
160
+ fontWeight: 'bold',
161
+ height: 28,
162
+ justifyContent: 'center',
163
+ width: 28,
164
+ }}
165
+ >
166
+ {index + 1}
167
+ </span>
168
+ {/* A plain vertical stepper line standing in for the map's own dashed
169
+ connector line, which is out of scope here - see the module comment. */}
170
+ {!isLast && <div style={{ background: '#ccc', flex: 1, margin: '4px 0', width: 2 }} />}
171
+ </div>
172
+ <div style={{ flex: 1, paddingBottom: isLast ? 0 : 24 }}>
173
+ <h3 style={{ margin: '0 0 8px' }}>{poiTitle || '—'}</h3>
174
+ {media?.thumbnailUrl && (
175
+ <img
176
+ alt={media.title ?? ''}
177
+ src={media.thumbnailUrl}
178
+ style={{ borderRadius: 8, marginBottom: 8, maxWidth: '100%' }}
179
+ />
180
+ )}
181
+ {description && (
182
+ // eslint-disable-next-line react/no-danger -- description is CKEditor HTML, the same content the public site will eventually render
183
+ <div dangerouslySetInnerHTML={{ __html: description }} />
184
+ )}
185
+ </div>
186
+ </div>
187
+ );
188
+ })}
189
+ </div>
190
+ </CompanionWindow>
191
+ );
192
+ };
193
+
194
+ interface PoiPreviewContentProps {
195
+ annotation: RawAnnotation | null;
196
+ id: string;
197
+ windowId: string;
198
+ }
199
+
200
+ const PoiPreviewContent = ({ annotation, id, windowId }: PoiPreviewContentProps) => (
201
+ <CompanionWindow id={id} title={annotation?.['dbf:kind'] ?? 'Preview'} windowId={windowId}>
202
+ <div style={{ padding: 16 }}>
203
+ {!annotation && <p>This annotation could not be found - it may have been deleted.</p>}
204
+ {annotation &&
205
+ LOCALES.map((locale) => {
206
+ const title = textBody(annotation, locale, 'identifying');
207
+ const description = textBody(annotation, locale, 'describing');
208
+ const media = mediaForLocale(annotation, locale);
209
+ return (
210
+ <section key={locale} style={{ marginBottom: 24 }}>
211
+ <h3 style={{ textTransform: 'uppercase' }}>{locale}</h3>
212
+ <p>
213
+ <strong>{title || '—'}</strong>
214
+ </p>
215
+ {description && (
216
+ // eslint-disable-next-line react/no-danger -- descriptionEn/Ar is CKEditor HTML, the same content the public site will eventually render
217
+ <div dangerouslySetInnerHTML={{ __html: description }} />
218
+ )}
219
+ {media &&
220
+ (media.thumbnailUrl ? (
221
+ <img alt={media.title ?? ''} src={media.thumbnailUrl} style={{ maxWidth: '100%' }} />
222
+ ) : (
223
+ <p>
224
+ {media.title}
225
+ {media.mediaType ? ` (${media.mediaType})` : ''}
226
+ </p>
227
+ ))}
228
+ </section>
229
+ );
230
+ })}
231
+ </div>
232
+ </CompanionWindow>
233
+ );
234
+
235
+ interface PreviewContentProps {
236
+ annotation: RawAnnotation | null;
237
+ id: string;
238
+ journeyPois: RawAnnotation[];
239
+ windowId: string;
240
+ }
241
+
242
+ const PreviewContent = ({ annotation, id, journeyPois, windowId }: PreviewContentProps) => {
243
+ if (annotation && annotation['dbf:kind'] === 'Journey') {
244
+ return <JourneyPreviewContent id={id} journey={annotation} pois={journeyPois} windowId={windowId} />;
245
+ }
246
+ return <PoiPreviewContent annotation={annotation} id={id} windowId={windowId} />;
247
+ };
248
+
249
+ const poiPreviewCompanionWindowPlugin = {
250
+ component: PreviewContent,
251
+ companionWindowKey: POI_PREVIEW_CONTENT_ID,
252
+ mapStateToProps: (state: unknown, { id, windowId }: { id: string; windowId: string }) => {
253
+ const annotationId = getCompanionWindow(state, { companionWindowId: id })?.annotationid as
254
+ | string
255
+ | undefined;
256
+ const canvasId = getVisibleCanvases(state, { windowId })[0]?.id;
257
+ const pages: Record<string, { json?: { items?: unknown[] } }> | undefined = canvasId
258
+ ? getAnnotations(state)[canvasId]
259
+ : undefined;
260
+ const items = (pages ? Object.values(pages) : []).flatMap(
261
+ (page) => (page.json?.items ?? []) as RawAnnotation[]
262
+ );
263
+ const annotation = items.find((item) => item.id === annotationId) ?? null;
264
+ return {
265
+ annotation,
266
+ journeyPois:
267
+ annotation && annotation['dbf:kind'] === 'Journey' ? getOrderedJourneyPois(items, annotation.id) : [],
268
+ };
269
+ },
270
+ };
271
+
272
+ // A canvas annotation resource, as AnnotationsOverlay's own `annotations`/`searchAnnotations`
273
+ // props carry it (see AnnotationItem#pointSelector/#svgSelector) - a POI marker is any resource
274
+ // with a pointSelector (CanvasAnnotationDisplay#pointContext), a Journey's own canvas target is
275
+ // one with an svgSelector (AnnotationsOverlay#isAnnotationAtPoint's own svgSelector branch).
276
+ type AnnotationResourceLike = { id: string; pointSelector?: unknown; svgSelector?: unknown };
277
+ type AnnotationListItem = { resources?: AnnotationResourceLike[] };
278
+
279
+ interface AnnotationsOverlayTargetProps {
280
+ annotations?: AnnotationListItem[];
281
+ searchAnnotations?: AnnotationListItem[];
282
+ selectAnnotation?: (windowId: string, annotationId: string) => void;
283
+ windowId: string;
284
+ [key: string]: unknown;
285
+ }
286
+
287
+ interface AnnotationsOverlayPoiClickWrapperProps {
288
+ TargetComponent: ComponentType<Record<string, unknown>>;
289
+ targetProps: AnnotationsOverlayTargetProps;
290
+ addCompanionWindow: typeof addCompanionWindow;
291
+ updateCompanionWindow: typeof updateCompanionWindow;
292
+ existingPreviewCompanionWindowId?: string;
293
+ }
294
+
295
+ // Wraps AnnotationsOverlay (the component that owns the OSD canvas-click handler and the
296
+ // select/deselect-annotation dispatch, see AnnotationsOverlay#toggleAnnotation) so that
297
+ // clicking a POI marker OR a Journey's own path on the canvas - not just a row in a list
298
+ // somewhere - opens this same preview companion window a "Preview" button would (issue #375's
299
+ // own follow-up: pins on the map itself; issue #378 extends this to journeys). Re-uses an
300
+ // already-open preview window instead of stacking a new one per click.
301
+ const AnnotationsOverlayPoiClickWrapper = ({
302
+ TargetComponent,
303
+ targetProps,
304
+ addCompanionWindow: dispatchAddCompanionWindow,
305
+ updateCompanionWindow: dispatchUpdateCompanionWindow,
306
+ existingPreviewCompanionWindowId,
307
+ }: AnnotationsOverlayPoiClickWrapperProps) => {
308
+ const { annotations = [], searchAnnotations = [], selectAnnotation } = targetProps;
309
+
310
+ const theme = useTheme();
311
+ // Issue #410: on a phone-width viewport there's no room for a right-hand rail next to
312
+ // the map, so the POI/journey preview opens as a bottom sheet instead.
313
+ const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
314
+ const previewPosition = isMobile ? 'bottom' : 'right';
315
+
316
+ const selectAnnotationAndMaybePreview = (clickedWindowId: string, annotationId: string) => {
317
+ selectAnnotation?.(clickedWindowId, annotationId);
318
+
319
+ const resource = [...annotations, ...searchAnnotations]
320
+ .flatMap((item) => item.resources ?? [])
321
+ .find((item) => item.id === annotationId);
322
+
323
+ // pointSelector => POI pin, svgSelector => a Journey's own canvas target (its path/stops
324
+ // line) - anything else (e.g. a fragmentSelector) has no preview content, skip it.
325
+ if (!resource?.pointSelector && !resource?.svgSelector) return;
326
+
327
+ if (existingPreviewCompanionWindowId) {
328
+ dispatchUpdateCompanionWindow(clickedWindowId, existingPreviewCompanionWindowId, {
329
+ annotationid: annotationId,
330
+ position: previewPosition,
331
+ });
332
+ } else {
333
+ dispatchAddCompanionWindow(clickedWindowId, {
334
+ annotationid: annotationId,
335
+ content: POI_PREVIEW_CONTENT_ID,
336
+ position: previewPosition,
337
+ });
338
+ }
339
+ };
340
+
341
+ return <TargetComponent {...targetProps} selectAnnotation={selectAnnotationAndMaybePreview} />;
342
+ };
343
+
344
+ const poiPreviewClickPlugin = {
345
+ target: 'AnnotationsOverlay',
346
+ mode: 'wrap',
347
+ component: AnnotationsOverlayPoiClickWrapper,
348
+ mapStateToProps: (state: unknown, { windowId }: { windowId: string }) => {
349
+ const existing = Object.values(getCompanionWindows(state) as Record<string, { id: string; windowId: string; content: string | null }>).find(
350
+ (cw) => cw.windowId === windowId && cw.content === POI_PREVIEW_CONTENT_ID,
351
+ );
352
+ return { existingPreviewCompanionWindowId: existing?.id };
353
+ },
354
+ mapDispatchToProps: { addCompanionWindow, updateCompanionWindow },
355
+ };
356
+
357
+ export const poiPreviewPlugins = [poiPreviewCompanionWindowPlugin, poiPreviewClickPlugin];
@@ -1 +0,0 @@
1
- {"version":3,"file":"FailedImageContext-DYZ9cZx9.js","names":[],"sources":["../node_modules/lodash/_baseFilter.js","../node_modules/lodash/filter.js","../node_modules/lodash/compact.js","../src/lib/AnnotationResource.js","../src/lib/AnnotationList.js","../src/lib/AnnotationItem.js","../src/lib/AnnotationPage.js","../src/lib/AnnotationFactory.js","../src/state/selectors/annotations.js","../src/state/selectors/searches.js","../src/state/actions/annotation.js","../src/contexts/FailedImageContext.js"],"sourcesContent":["var baseEach = require('./_baseEach');\n\n/**\n * The base implementation of `_.filter` without support for iteratee shorthands.\n *\n * @private\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {Array} Returns the new filtered array.\n */\nfunction baseFilter(collection, predicate) {\n var result = [];\n baseEach(collection, function(value, index, collection) {\n if (predicate(value, index, collection)) {\n result.push(value);\n }\n });\n return result;\n}\n\nmodule.exports = baseFilter;\n","var arrayFilter = require('./_arrayFilter'),\n baseFilter = require('./_baseFilter'),\n baseIteratee = require('./_baseIteratee'),\n isArray = require('./isArray');\n\n/**\n * Iterates over elements of `collection`, returning an array of all elements\n * `predicate` returns truthy for. The predicate is invoked with three\n * arguments: (value, index|key, collection).\n *\n * **Note:** Unlike `_.remove`, this method returns a new array.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @returns {Array} Returns the new filtered array.\n * @see _.reject\n * @example\n *\n * var users = [\n * { 'user': 'barney', 'age': 36, 'active': true },\n * { 'user': 'fred', 'age': 40, 'active': false }\n * ];\n *\n * _.filter(users, function(o) { return !o.active; });\n * // => objects for ['fred']\n *\n * // The `_.matches` iteratee shorthand.\n * _.filter(users, { 'age': 36, 'active': true });\n * // => objects for ['barney']\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.filter(users, ['active', false]);\n * // => objects for ['fred']\n *\n * // The `_.property` iteratee shorthand.\n * _.filter(users, 'active');\n * // => objects for ['barney']\n *\n * // Combining several predicates using `_.overEvery` or `_.overSome`.\n * _.filter(users, _.overSome([{ 'age': 36 }, ['age', 40]]));\n * // => objects for ['fred', 'barney']\n */\nfunction filter(collection, predicate) {\n var func = isArray(collection) ? arrayFilter : baseFilter;\n return func(collection, baseIteratee(predicate, 3));\n}\n\nmodule.exports = filter;\n","/**\n * Creates an array with all falsey values removed. The values `false`, `null`,\n * `0`, `-0`, `0n`, `\"\"`, `undefined`, and `NaN` are falsy.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to compact.\n * @returns {Array} Returns the new array of filtered values.\n * @example\n *\n * _.compact([0, 1, false, 2, '', 3]);\n * // => [1, 2, 3]\n */\nfunction compact(array) {\n var index = -1,\n length = array == null ? 0 : array.length,\n resIndex = 0,\n result = [];\n\n while (++index < length) {\n var value = array[index];\n if (value) {\n result[resIndex++] = value;\n }\n }\n return result;\n}\n\nmodule.exports = compact;\n","import compact from 'lodash/compact';\nimport { v4 as uuid } from 'uuid';\n\n/** */\nexport default class AnnotationResource {\n /** */\n constructor(resource = {}) {\n this.resource = resource;\n }\n\n /** */\n isOnlyTag() {\n return this.motivations.length === 1 && this.motivations[0] === 'oa:tagging';\n }\n\n /** */\n get id() {\n this._id = this._id || this.resource['@id'] || (this.resources[0] && this.resources[0]['@id']) || uuid();\n return this._id;\n }\n\n /** */\n get targetId() {\n const on = this.on[0];\n switch (typeof on) {\n case 'string':\n return on.replace(/#?xywh=(.*)$/, '');\n case 'object':\n return on.full.replace(/#?xywh=(.*)$/, '');\n default:\n return null;\n }\n }\n\n /**\n * @return {[Array]}\n */\n get motivations() {\n return compact(new Array(this.resource.motivation)).flat();\n }\n\n /** */\n get resources() {\n return compact(new Array(this.resource.resource)).flat();\n }\n\n /** */\n get on() {\n return compact(new Array(this.resource.on)).flat();\n }\n\n /** */\n get tags() {\n if (this.isOnlyTag()) {\n return this.resources.map((r) => r.chars);\n }\n return this.resources.filter((r) => r['@type'] === 'oa:Tag').map((r) => r.chars);\n }\n\n /** */\n get chars() {\n return this.resources\n .filter((r) => r['@type'] !== 'oa:Tag')\n .map((r) => r.chars)\n .join(' ');\n }\n\n /** */\n get selector() {\n const on = this.on[0];\n switch (typeof on) {\n case 'string':\n return on;\n case 'object':\n // For choices, just return the default for now. FIXME: enhance for SVG\n // selectors\n if (on.selector['@type'] === 'oa:Choice') {\n return on.selector.default;\n }\n return on.selector;\n default:\n return null;\n }\n }\n\n /** */\n get svgSelector() {\n const on = this.on[0];\n\n switch (typeof on) {\n case 'string':\n return null;\n case 'object':\n if (on.selector && on.selector.item && on.selector.item['@type'] === 'oa:SvgSelector') {\n return on.selector.item;\n }\n return null;\n default:\n return null;\n }\n }\n\n /** */\n get fragmentSelector() {\n const { selector } = this;\n\n let match;\n\n switch (typeof selector) {\n case 'string':\n match = selector.match(/xywh=(.*)$/);\n break;\n case 'object':\n match = selector.value.match(/xywh=(.*)$/);\n break;\n default:\n return null;\n }\n\n return match && match[1].split(',').map((str) => parseInt(str, 10));\n }\n}\n","import AnnotationResource from './AnnotationResource';\n/** */\nexport default class AnnotationList {\n /** */\n constructor(json, target) {\n this.json = json;\n this.target = target;\n }\n\n /** */\n get id() {\n return this.json['@id'];\n }\n\n /** */\n present() {\n return this.resources && this.resources.length > 0;\n }\n\n /** */\n get resources() {\n this._resources =\n this._resources ||\n (() => {\n if (!this.json || !this.json.resources) return [];\n\n return [this.json.resources].flat().map((resource) => new AnnotationResource(resource));\n })();\n return this._resources;\n }\n}\n","import compact from 'lodash/compact';\nimport { v4 as uuid } from 'uuid';\n\n/**\n * A modeled WebAnnotation item\n */\nexport default class AnnotationItem {\n /** */\n constructor(resource = {}) {\n this.resource = resource;\n }\n\n /** */\n isOnlyTag() {\n return this.motivations.length === 1 && this.motivations[0] === 'tagging';\n }\n\n /** */\n get id() {\n this._id = this._id || this.resource.id || uuid();\n return this._id;\n }\n\n /** */\n get targetId() {\n const target = this.target[0];\n switch (typeof target) {\n case 'string':\n return target.replace(/#?xywh=(.*)$/, '');\n case 'object':\n return (target.source && target.source.id) || target.source || target.id;\n default:\n return null;\n }\n }\n\n /**\n * @return {[Array]}\n */\n get motivations() {\n return compact(new Array(this.resource.motivation)).flat();\n }\n\n /** */\n get body() {\n return compact(new Array(this.resource.body)).flat();\n }\n\n /** */\n get resources() {\n return this.body;\n }\n\n /** */\n get tags() {\n if (this.isOnlyTag()) {\n return this.body.map((r) => r.value);\n }\n return this.body.filter((r) => r.purpose === 'tagging').map((r) => r.value);\n }\n\n /** */\n get target() {\n return compact(new Array(this.resource.target)).flat();\n }\n\n /** */\n get chars() {\n if (this.isOnlyTag()) return null;\n return this.body\n .filter((r) => r.purpose !== 'tagging')\n .map((r) => r.value)\n .join(' ');\n }\n\n /** */\n get selector() {\n const target = this.target[0];\n switch (typeof target) {\n case 'string':\n return target;\n case 'object':\n return compact(new Array(target.selector)).flat();\n default:\n return null;\n }\n }\n\n /** */\n get svgSelector() {\n const { selector } = this;\n switch (typeof selector) {\n case 'string':\n return null;\n case 'object':\n return selector.find((s) => s.type && s.type === 'SvgSelector');\n default:\n return null;\n }\n }\n\n /** */\n get fragmentSelector() {\n const { selector } = this;\n\n let match;\n let fragmentSelector;\n\n switch (typeof selector) {\n case 'string':\n match = selector.match(/xywh=(.*)$/);\n break;\n case 'object':\n fragmentSelector = selector.find((s) => s.type && s.type === 'FragmentSelector');\n match = fragmentSelector && fragmentSelector.value.match(/xywh=(.*)$/);\n break;\n default:\n return null;\n }\n\n return match && match[1].split(',').map((str) => parseInt(str, 10));\n }\n}\n","import AnnotationItem from './AnnotationItem';\n/**\n * Annotation representation for IIIF Presentation v3\n * https://iiif.io/api/presentation/3.0/#55-annotation-page\n */\nexport default class AnnotationPage {\n /** */\n constructor(json, target) {\n this.json = json;\n this.target = target;\n }\n\n /** */\n get id() {\n return this.json.id;\n }\n\n /** */\n present() {\n return this.items && this.items.length > 0;\n }\n\n /** */\n get items() {\n this._items =\n this._items ||\n (() => {\n if (!this.json || !this.json.items) return [];\n\n return [this.json.items].flat().map((resource) => new AnnotationItem(resource));\n })();\n return this._items;\n }\n\n /**\n * Alias to items for compatibility for right now.\n */\n get resources() {\n return this.items;\n }\n}\n","import AnnotationList from './AnnotationList';\nimport AnnotationPage from './AnnotationPage';\n\n/**\n * Used to determine the type of Annotation supported by a version of the IIIF\n * Presentation API.\n */\nexport default class AnnotationFactory {\n /** */\n static determineAnnotation(json, target) {\n if (!json) {\n return null;\n }\n\n // IIIF Presentation API v3. AnnotationPage\n if (json.type === 'AnnotationPage') {\n return new AnnotationPage(json, target);\n }\n\n // IIIF Presentation API v2. OpenAnnotation and SharedCanvas models\n return new AnnotationList(json, target);\n }\n}\n","import { createSelector } from 'reselect';\nimport filter from 'lodash/filter';\nimport AnnotationFactory from '../../lib/AnnotationFactory';\nimport { miradorSlice } from './utils';\nimport { getCanvas, getVisibleCanvasIds } from './canvases';\nimport { getConfig } from './config';\nimport { getWindow } from './getters';\n\n/**\n * Returns the annotation object from the mirador slice.\n * @param {object} state redux state\n * @returns {object} Annotations from the state\n */\nexport const getAnnotations = (state) => miradorSlice(state).annotations;\n\nconst getMotivations = createSelector(\n [getConfig, (state, { motivations }) => motivations],\n (config, motivations) => motivations || config.annotations.filteredMotivations,\n);\n\nconst getAnnotationsOnCanvas = createSelector([getCanvas, getAnnotations], (canvas, annotations) => {\n if (!annotations || !canvas) return [];\n if (!annotations[canvas.id]) return [];\n\n return Object.values(annotations[canvas.id]).flat();\n});\n\nconst getPresentAnnotationsCanvas = createSelector([getAnnotationsOnCanvas], (annotations) =>\n filter(\n Object.values(annotations).map((annotation) => annotation && AnnotationFactory.determineAnnotation(annotation.json)),\n (annotation) => annotation && annotation.present(),\n ),\n);\n\nconst getAnnotationsOnSelectedCanvases = createSelector(\n [(state, { canvasId, ...otherProps }) => (canvasId ? [canvasId] : getVisibleCanvasIds(state, otherProps)), getAnnotations],\n (canvasIds, annotations) => {\n if (!annotations || canvasIds.length === 0) return [];\n return canvasIds.flatMap((targetId) => annotations[targetId] && Object.values(annotations[targetId]));\n },\n);\n\n/**\n * Returns an array of present annotations given a canvasId.\n * @param {object} state redux state\n * @param {string} canvasId canvasId\n * @returns {Array} An array of present annotations\n */\nexport const getPresentAnnotationsOnSelectedCanvases = createSelector([getAnnotationsOnSelectedCanvases], (annotations) =>\n filter(\n Object.values(annotations).map((annotation) => annotation && AnnotationFactory.determineAnnotation(annotation.json)),\n (annotation) => annotation && annotation.present(),\n ),\n);\n\n/**\n * Returns an array of annotation resources filtered by the given motivation for a particular canvas.\n * @param {Array} annotations\n * @param {Array} motivations\n * @returns {Array}\n */\nexport const getAnnotationResourcesByMotivationForCanvas = createSelector(\n [getPresentAnnotationsCanvas, getMotivations],\n (annotations, motivations) => {\n const resources = annotations.flatMap((annotation) => annotation.resources);\n\n // If motivations is empty, null, or undefined, return everything\n if (!motivations || motivations.length === 0) {\n return resources;\n }\n\n // Otherwise filter by motivations\n return resources.filter((resource) => resource.motivations.some((motivation) => motivations.includes(motivation)));\n },\n);\n\n/**\n * Returns annotation resources for a canvas destructured into their id/content/tags/targetId.\n * @param {object} state\n * @param {object} props\n * @param {string} props.canvasId\n * @param {string} props.windowId\n * @returns {Array} [{ id: 'abc123', content: 'Annotation Content' }, ...]\n */\nexport const getAnnotationResourcesDataForCanvas = createSelector([getAnnotationResourcesByMotivationForCanvas], (resources) =>\n resources.map((resource) => ({\n content: resource.chars,\n id: resource.id,\n tags: resource.tags,\n targetId: resource.targetId,\n })),\n);\n\n/**\n * Returns an array of annotation resources filtered by the given motivation.\n * @param {Array} annotations\n * @param {Array} motivations\n * @returns {Array}\n */\nexport const getAnnotationResourcesByMotivation = createSelector(\n [getPresentAnnotationsOnSelectedCanvases, getMotivations],\n (annotations, motivations) => {\n const resources = annotations.flatMap((annotation) => annotation.resources);\n\n // If motivations is empty, null, or undefined, return everything\n if (!motivations || motivations.length === 0) {\n return resources;\n }\n\n // Otherwise filter by motivations\n return resources.filter((resource) => resource.motivations.some((motivation) => motivations.includes(motivation)));\n },\n);\n\n/**\n * Returns the selected annotations IDs.\n * @param {object} state\n * @param {string} windowId\n * @param {Array} targetIds\n * @returns {Array}\n */\nexport const getSelectedAnnotationId = createSelector([getWindow], ({ selectedAnnotationId }) => selectedAnnotationId);\n\n/**\n * Returns annotations on selected canvases.\n * @param {object} state\n * @returns {Array}\n */\nexport const getSelectedAnnotationsOnCanvases = createSelector(\n [getPresentAnnotationsOnSelectedCanvases, getSelectedAnnotationId],\n (canvasAnnotations, selectedAnnotationId) =>\n canvasAnnotations\n .map((annotation) => ({\n id: annotation['@id'] || annotation.id,\n resources: annotation.resources.filter((r) => selectedAnnotationId === r.id),\n }))\n .filter((val) => val.resources.length > 0),\n);\n","import { createSelector } from 'reselect';\nimport { PropertyValue } from 'manifesto.js';\nimport AnnotationList from '../../lib/AnnotationList';\nimport { getCanvas, getCanvases } from './canvases';\nimport { getWindow } from './getters';\nimport { getManifestLocale } from './manifests';\nimport { miradorSlice, EMPTY_ARRAY, EMPTY_OBJECT } from './utils';\n\n/**\n * Get searches from state.\n */\nconst getSearches = (state) => miradorSlice(state).searches;\n\n/**\n * Returns the search result for a specific window.\n * @param {object} state\n * @param {string} windowId\n * @returns {object}\n */\nexport const getSearchForWindow = createSelector([(state, { windowId }) => windowId, getSearches], (windowId, searches) => {\n if (!windowId || !searches) return EMPTY_OBJECT;\n\n return searches[windowId];\n});\n\n/**\n * Returns the search result for a specific companion window.\n * @param {object} state\n * @param {string} companionWindowId\n * @returns {object|undefined}\n */\nconst getSearchForCompanionWindow = createSelector(\n [getSearchForWindow, (state, { companionWindowId }) => companionWindowId],\n (results, companionWindowId) => {\n if (!results || !companionWindowId) return undefined;\n return results[companionWindowId];\n },\n);\n\n/**\n * Returns an array of search responses for a specific companion window.\n * @param {object} state\n * @returns {Array}\n */\nconst getSearchResponsesForCompanionWindow = createSelector([getSearchForCompanionWindow], (results) => {\n if (!results) return EMPTY_ARRAY;\n return Object.values(results.data);\n});\n\n/**\n * Returns the search query for a specific companion window.\n * @param {object} state\n * @param {string} windowId\n * @returns {string|undefined}\n */\nexport const getSearchQuery = createSelector([getSearchForCompanionWindow], (results) => results && results.query);\n\n/**\n * Returns if search response for a companion window is fetching.\n * @param {object} state\n * @returns {boolean}\n */\nexport const getSearchIsFetching = createSelector([getSearchResponsesForCompanionWindow], (results) =>\n results.some((result) => result.isFetching),\n);\n\n/**\n * Returns the total number of search results for a companion window.\n * @param {object} state\n * @param {string} windowId\n * @returns {number|undefined}\n */\nexport const getSearchNumTotal = createSelector([getSearchForCompanionWindow], (results) => {\n if (!results || !results.data) return undefined;\n\n const resultWithWithin = Object.values(results.data).find((result) => !result.isFetching && result.json && result.json.within);\n return resultWithWithin?.json?.within?.total;\n});\n\n/**\n * Returns the Id of the next search.\n * @param {object} state\n * @param {string} windowId\n * @returns {number|undefined}\n */\nexport const getNextSearchId = createSelector([getSearchForCompanionWindow], (results) => {\n if (!results || !results.data) return undefined;\n\n const resultWithAnUnresolvedNext = Object.values(results.data).find(\n (result) => !result.isFetching && result.json && result.json.next && !results.data[result.json.next],\n );\n\n return resultWithAnUnresolvedNext && resultWithAnUnresolvedNext.json && resultWithAnUnresolvedNext.json.next;\n});\n\nconst getSearchHitsForCompanionWindow = createSelector([getSearchResponsesForCompanionWindow], (results) =>\n results.flatMap((result) => {\n if (!result || !result.json || result.isFetching || !result.json.hits) return EMPTY_ARRAY;\n\n return result.json.hits;\n }),\n);\n\nexport const getSearchAnnotationsForCompanionWindow = createSelector(\n [getSearchResponsesForCompanionWindow],\n (results) => results && searchResultsToAnnotation(results),\n);\n\n/**\n * Returns sorted search hits based on canvas order.\n * @param {object} state\n * @param {string} manifestId\n * @returns {Array}\n */\nexport const getSortedSearchHitsForCompanionWindow = createSelector(\n [getSearchHitsForCompanionWindow, getCanvases, getSearchAnnotationsForCompanionWindow],\n (searchHits, canvases, annotation) => {\n if (!canvases || canvases.length === 0) return EMPTY_ARRAY;\n if (!searchHits || searchHits.length === 0) return EMPTY_ARRAY;\n const canvasIds = canvases.map((canvas) => canvas.id);\n\n return [].concat(searchHits).sort((a, b) => {\n const hitA = annotation.resources.find((r) => r.id === a.annotations[0]);\n const hitB = annotation.resources.find((r) => r.id === b.annotations[0]);\n return canvasIds.indexOf(hitA.targetId) - canvasIds.indexOf(hitB.targetId);\n });\n },\n);\n\n/** convert search results to an annotation */\nconst searchResultsToAnnotation = (results) => {\n const annotations = results\n .map((result) => {\n if (!result || !result.json || result.isFetching || !result.json.resources) return undefined;\n const anno = new AnnotationList(result.json);\n return {\n id: anno.id,\n resources: anno.resources,\n };\n })\n .filter(Boolean);\n\n return {\n id: (annotations.find((a) => a.id) || {}).id,\n resources: annotations.flatMap((a) => a.resources),\n };\n};\n\n/**\n * Sorts search annotations based on canvas order.\n * @returns {Array}\n */\nexport function sortSearchAnnotationsByCanvasOrder(searchAnnotations, canvases) {\n if (!searchAnnotations || !searchAnnotations.resources || searchAnnotations.length === 0) return EMPTY_ARRAY;\n if (!canvases || canvases.length === 0) return EMPTY_ARRAY;\n const canvasIds = canvases.map((canvas) => canvas.id);\n\n return []\n .concat(searchAnnotations.resources)\n .sort((annoA, annoB) => canvasIds.indexOf(annoA.targetId) - canvasIds.indexOf(annoB.targetId));\n}\n\n/**\n * Returns sorted search annotations for companion window.\n * @param {object} state\n * @param {string} companionWindowId\n * @returns {Array}\n */\nexport const getSortedSearchAnnotationsForCompanionWindow = createSelector(\n [getSearchAnnotationsForCompanionWindow, getCanvases],\n (searchAnnotations, canvases) => sortSearchAnnotationsByCanvasOrder(searchAnnotations, canvases),\n);\n\n/**\n * Returns sorted search annotations for window.\n * @param {object} state\n * @param {string} windowId\n * @returns {Array}\n */\nexport const getSearchAnnotationsForWindow = createSelector([getSearchForWindow], (results) => {\n if (!results) return EMPTY_ARRAY;\n const data = Object.values(results).map((r) => Object.values(r.data));\n\n return data.map((d) => searchResultsToAnnotation(d)).filter((a) => a.resources.length > 0);\n});\n\n/**\n * Returns ids of selected content search annotations.\n * @param {object} state\n * @param {string} windowId\n * @returns {Array}\n */\nexport const getSelectedContentSearchAnnotationIds = createSelector(\n [getWindow, getSearchForCompanionWindow],\n (window, search) => (search && search.selectedContentSearchAnnotationIds) || [],\n);\n\n/**\n * Returns resource annotations for search hit.\n * @param {object} state\n * @param {string} windowId\n * @returns {Array}\n */\nexport const getResourceAnnotationForSearchHit = createSelector(\n [getSearchAnnotationsForCompanionWindow, (state, { annotationUri }) => annotationUri],\n (annotation, annotationUri) => annotation.resources.find((r) => r.id === annotationUri),\n);\n\n/**\n * Returns annotation label.\n * @param {object} state\n * @param {string} windowId\n * @returns {Array}\n */\nexport const getResourceAnnotationLabel = createSelector(\n [getResourceAnnotationForSearchHit, getManifestLocale],\n (resourceAnnotation, locale) => {\n if (!(resourceAnnotation && resourceAnnotation.resource && resourceAnnotation.resource.label)) return EMPTY_ARRAY;\n\n return PropertyValue.parse(resourceAnnotation.resource.label).getValues(locale);\n },\n);\n\nconst getAnnotationById = createSelector(\n [getSearchAnnotationsForWindow, (state, { annotationId }) => annotationId],\n (annotations, annotationId) => {\n const resourceAnnotations = annotations.flatMap((a) => a.resources);\n return resourceAnnotations.find((r) => r.id === annotationId);\n },\n);\n\n/**\n * Returns annotation label.\n * @param {object} state\n * @param {string} windowId\n * @returns {Array}\n */\nexport const getCanvasForAnnotation = createSelector(\n [\n getAnnotationById,\n (state, { windowId }) =>\n (canvasId) =>\n getCanvas(state, { canvasId, windowId }),\n ],\n (annotation, getCanvasById) => {\n const canvasId = annotation && annotation.targetId;\n return canvasId && getCanvasById(canvasId);\n },\n);\n","import ActionTypes from './action-types';\n\n/**\n * Request annotations on a canvas\n *\n * NOTE: there is no corresponding reducer; the expected API is sagas will\n * pick this action up and act on it accordingly.\n */\nexport function requestCanvasAnnotations(windowId, canvasId) {\n return {\n canvasId,\n type: ActionTypes.REQUEST_CANVAS_ANNOTATIONS,\n windowId,\n };\n}\n\n/**\n * requestAnnotation - action creator\n *\n * @param {String} targetId\n * @param {String} annotationId\n * @memberof ActionCreators\n */\nexport function requestAnnotation(targetId, annotationId) {\n return {\n annotationId,\n targetId,\n type: ActionTypes.REQUEST_ANNOTATION,\n };\n}\n\n/**\n * receiveAnnotation - action creator\n *\n * @param {String} targetId\n * @param {String} annotationId\n * @param {Object} annotationJson\n * @memberof ActionCreators\n */\nexport function receiveAnnotation(targetId, annotationId, annotationJson) {\n return {\n annotationId,\n annotationJson,\n targetId,\n type: ActionTypes.RECEIVE_ANNOTATION,\n };\n}\n\n/**\n * receiveAnnotationFailure - action creator\n *\n * @param {String} targetId\n * @param {String} annotationId\n * @param {String} error\n * @memberof ActionCreators\n */\nexport function receiveAnnotationFailure(targetId, annotationId, error) {\n return {\n annotationId,\n error,\n targetId,\n type: ActionTypes.RECEIVE_ANNOTATION_FAILURE,\n };\n}\n\n/**\n * selectAnnotation - action creator\n *\n * @param {String} windowId\n * @param {String} targetId\n * @param {String} annotationId\n * @memberof ActionCreators\n */\nexport function selectAnnotation(windowId, annotationId) {\n return {\n annotationId,\n type: ActionTypes.SELECT_ANNOTATION,\n windowId,\n };\n}\n\n/**\n * deselectAnnotation - action creator\n *\n * @param {String} windowId\n * @param {String} targetId\n * @param {String} annotationId\n * @memberof ActionCreators\n */\nexport function deselectAnnotation(windowId, annotationId) {\n return {\n annotationId,\n type: ActionTypes.DESELECT_ANNOTATION,\n windowId,\n };\n}\n\n/**\n * toggleAnnotationDisplay - action creator\n *\n * @param {String} windowId\n * @memberof ActionCreators\n */\nexport function toggleAnnotationDisplay(windowId) {\n return {\n type: ActionTypes.TOGGLE_ANNOTATION_DISPLAY,\n windowId,\n };\n}\n\n/**\n * toggleAnnotationDisplay - action creator\n *\n * @param {String} windowId\n * @memberof ActionCreators\n */\nexport function hoverAnnotation(windowId, annotationIds) {\n return {\n annotationIds,\n type: ActionTypes.HOVER_ANNOTATION,\n windowId,\n };\n}\n","import { createContext } from 'react';\n\nconst FailedImageContext = createContext({\n fallbackImage: '',\n hasFailed: false,\n notifyFailure: () => {},\n});\nexport default FailedImageContext;\n"],"x_google_ignoreList":[0,1,2],"mappings":"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"}