dbf-mirador 4.3.0-testing2 → 4.3.0-testing3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dbf-mirador",
3
- "version": "4.3.0-testing2",
3
+ "version": "4.3.0-testing3",
4
4
  "description": "An open-source, web-based 'multi-up' viewer that supports zoom-pan-rotate functionality, ability to display/compare simple images, and images with annotations.",
5
5
  "type": "module",
6
6
  "main": "./dist/mirador.min.js",
@@ -6,11 +6,11 @@ import sortBy from 'lodash/sortBy';
6
6
  import xor from 'lodash/xor';
7
7
  import OpenSeadragonCanvasOverlay from '../lib/OpenSeadragonCanvasOverlay';
8
8
  import CanvasWorld from '../lib/CanvasWorld';
9
- import CanvasAnnotationDisplay from '../lib/CanvasAnnotationDisplay';
9
+ import CanvasAnnotationDisplay, { POI_ICON_HEIGHT_PX } from '../lib/CanvasAnnotationDisplay';
10
10
  import { buildPath2D } from '../lib/svgShapesToPath';
11
11
 
12
12
  /** @private */
13
- function isAnnotationAtPoint(canvasWorld, osdCanvasOverlay, resource, canvas, point) {
13
+ function isAnnotationAtPoint({ canvasWorld, osdCanvasOverlay, viewer }, resource, canvas, point) {
14
14
  const [canvasX, canvasY] = canvasWorld.canvasToWorldCoordinates(canvas.id);
15
15
  const relativeX = point.x - canvasX;
16
16
  const relativeY = point.y - canvasY;
@@ -21,6 +21,21 @@ function isAnnotationAtPoint(canvasWorld, osdCanvasOverlay, resource, canvas, po
21
21
  return [...svgPaths].some((path) => context.isPointInPath(buildPath2D(path), relativeX, relativeY));
22
22
  }
23
23
 
24
+ if (resource.pointSelector) {
25
+ const { x, y } = resource.pointSelector;
26
+ const osdCanvasIndex = canvasWorld.canvases.findIndex((c) => c.id === canvas.id);
27
+ const viewportCanvas = viewer.world.getItemAt(osdCanvasIndex);
28
+ if (!viewportCanvas) return false;
29
+ // The icon renders at a constant on-screen size regardless of zoom (see
30
+ // CanvasAnnotationDisplay#pointContext), so its clickable footprint must counter-scale the
31
+ // same way, or the hit region would shrink/grow with the image instead of the icon.
32
+ const zoomRatio = viewportCanvas.viewportToImageZoom(viewer.viewport.getZoom(true));
33
+ const hitRadius = POI_ICON_HEIGHT_PX / 2 / zoomRatio;
34
+ const dx = relativeX - x;
35
+ const dy = relativeY - y;
36
+ return dx * dx + dy * dy <= hitRadius * hitRadius;
37
+ }
38
+
24
39
  if (resource.fragmentSelector) {
25
40
  const [x, y, w, h] = resource.fragmentSelector;
26
41
  return x <= relativeX && relativeX <= x + w && y <= relativeY && relativeY <= y + h;
@@ -137,12 +152,12 @@ export function AnnotationsOverlay({
137
152
  .filter((resource) => {
138
153
  if (canvas.id !== resource.targetId) return false;
139
154
 
140
- return isAnnotationAtPoint(canvasWorld, osdCanvasOverlay, resource, canvas, point);
155
+ return isAnnotationAtPoint({ canvasWorld, osdCanvasOverlay, viewer }, resource, canvas, point);
141
156
  });
142
157
 
143
158
  return annos;
144
159
  },
145
- [annotations, canvasWorld, osdCanvasOverlay, searchAnnotations],
160
+ [annotations, canvasWorld, osdCanvasOverlay, searchAnnotations, viewer],
146
161
  );
147
162
 
148
163
  const onCanvasClick = useCallback(
@@ -188,7 +203,7 @@ export function AnnotationsOverlay({
188
203
  const x = Math.cos(degrees * degreesToRadians) * radius + point.x;
189
204
  const y = Math.sin(degrees * degreesToRadians) * radius + point.y;
190
205
 
191
- if (isAnnotationAtPoint(canvasWorld, osdCanvasOverlay, anno, canvas, { x, y })) score += 1;
206
+ if (isAnnotationAtPoint({ canvasWorld, osdCanvasOverlay, viewer }, anno, canvas, { x, y })) score += 1;
192
207
  }
193
208
 
194
209
  return { anno, score };
@@ -206,7 +221,7 @@ export function AnnotationsOverlay({
206
221
  toggleAnnotation(annosWithScore[0].anno.id);
207
222
  }
208
223
  },
209
- [annotationsAtPoint, canvasWorld, osdCanvasOverlay, toggleAnnotation],
224
+ [annotationsAtPoint, canvasWorld, osdCanvasOverlay, toggleAnnotation, viewer],
210
225
  );
211
226
 
212
227
  const onCanvasMouseMove = useDebouncedCallback(
@@ -120,4 +120,22 @@ export default class AnnotationItem {
120
120
 
121
121
  return match && match[1].split(',').map((str) => parseInt(str, 10));
122
122
  }
123
+
124
+ /** */
125
+ get pointSelector() {
126
+ const { selector } = this;
127
+ switch (typeof selector) {
128
+ case 'string':
129
+ return null;
130
+ case 'object':
131
+ return selector.find((s) => s.type && s.type === 'PointSelector');
132
+ default:
133
+ return null;
134
+ }
135
+ }
136
+
137
+ /** the POI's position within its journey (see mirador-annotation-editor's `dbf:journey`), or null when the POI is not part of a journey */
138
+ get journeyOrder() {
139
+ return this.resource['dbf:journey']?.order ?? null;
140
+ }
123
141
  }
@@ -119,4 +119,18 @@ export default class AnnotationResource {
119
119
 
120
120
  return match && match[1].split(',').map((str) => parseInt(str, 10));
121
121
  }
122
+
123
+ /** */
124
+ get pointSelector() {
125
+ const { selector } = this;
126
+ if (selector && typeof selector === 'object' && selector['@type'] === 'oa:PointSelector') {
127
+ return { x: selector.x, y: selector.y };
128
+ }
129
+ return null;
130
+ }
131
+
132
+ /** the POI's position within its journey (see mirador-annotation-editor's `dbf:journey`), or null when the POI is not part of a journey */
133
+ get journeyOrder() {
134
+ return this.resource['dbf:journey']?.order ?? null;
135
+ }
122
136
  }
@@ -4,6 +4,23 @@
4
4
  */
5
5
  import { buildPath2D } from '../lib/svgShapesToPath';
6
6
 
7
+ /**
8
+ * The POI marker icon's path data and viewBox, copied from src/assets/icons/poi-marker.svg -
9
+ * inlined as a Path2D (rather than loaded as an image via drawImage) so it renders as a crisp
10
+ * vector at any zoom with no async image-load step to coordinate with the render loop. Update
11
+ * this constant (and the asset file, for reference) together if the icon changes.
12
+ */
13
+ const POI_ICON_PATH_D =
14
+ 'M50.002 0C30.763 0 15 15.718 15 34.902c0 7.432 2.374 14.34 6.392 20.019L45.73 96.994c3.409 4.453 5.675 3.607 8.51-.235l26.843-45.683c.542-.981.967-2.026 1.338-3.092A34.446 34.446 0 0 0 85 34.902C85 15.718 69.24 0 50.002 0zm0 16.354c10.359 0 18.597 8.218 18.597 18.548c0 10.33-8.238 18.544-18.597 18.544c-10.36 0-18.601-8.215-18.601-18.544c0-10.33 8.241-18.548 18.6-18.548z';
15
+ const POI_ICON_VIEWBOX_SIZE = 100;
16
+ /** The icon's own point (its pin tip), in viewBox units - this is what gets placed exactly on the annotated coordinate, not the icon's bounding-box center. */
17
+ const POI_ICON_TIP = { x: 50, y: 97 };
18
+ /** Center/radius of the icon's circular head, in viewBox units - where a journey-order badge is drawn, overlapping the icon like a numbered pin. */
19
+ const POI_ICON_HEAD = { x: 50, y: 34.9, radius: 18.6 };
20
+ const POI_ICON_DEFAULT_FILL = '#1e88e5';
21
+ /** Constant on-screen height (CSS px) for the POI icon, regardless of zoom - counter-scaled the same way this class already counter-scales stroke width (see `lineWidth /= zoomRatio` in svgContext). */
22
+ export const POI_ICON_HEIGHT_PX = 32;
23
+
7
24
  export default class CanvasAnnotationDisplay {
8
25
  /** */
9
26
  constructor({ resource, palette, zoomRatio, offset, selected, hovered }) {
@@ -20,11 +37,70 @@ export default class CanvasAnnotationDisplay {
20
37
  this.context = context;
21
38
  if (this.resource.svgSelector) {
22
39
  this.svgContext();
40
+ } else if (this.resource.pointSelector) {
41
+ this.pointContext();
23
42
  } else if (this.resource.fragmentSelector) {
24
43
  this.fragmentContext();
25
44
  }
26
45
  }
27
46
 
47
+ /** */
48
+ currentPalette() {
49
+ if (this.hovered) return this.palette.hovered;
50
+ if (this.selected) return this.palette.selected;
51
+ return this.palette.default;
52
+ }
53
+
54
+ /**
55
+ * Draws a POI marker (IIIF PointSelector) as the SVG pin icon, at a constant on-screen size,
56
+ * with the icon's own tip placed exactly on the annotated point. When the annotation carries
57
+ * journey-order metadata (`dbf:journey.order`), also draws a numbered badge over the icon's
58
+ * head, so a POI's position within its journey is visible directly on the map.
59
+ */
60
+ pointContext() {
61
+ const { x, y } = this.resource.pointSelector;
62
+ const currentPalette = this.currentPalette();
63
+ if (currentPalette.globalAlpha === 0) return;
64
+
65
+ const iconHeight = POI_ICON_HEIGHT_PX / this.zoomRatio;
66
+ const iconScale = iconHeight / POI_ICON_VIEWBOX_SIZE;
67
+
68
+ this.context.save();
69
+ this.context.translate(this.offset.x + x, this.offset.y + y);
70
+ this.context.scale(iconScale, iconScale);
71
+ this.context.translate(-POI_ICON_TIP.x, -POI_ICON_TIP.y);
72
+
73
+ this.context.globalAlpha = currentPalette.globalAlpha ?? 1;
74
+ this.context.fillStyle = currentPalette.fillStyle || POI_ICON_DEFAULT_FILL;
75
+ this.context.fill(new Path2D(POI_ICON_PATH_D));
76
+
77
+ const { journeyOrder } = this.resource;
78
+ if (journeyOrder != null) {
79
+ this.journeyOrderBadgeContext(journeyOrder);
80
+ }
81
+
82
+ this.context.restore();
83
+ }
84
+
85
+ /**
86
+ * Draws a small numbered circle over the POI icon's head, in the icon's own (viewBox-unit,
87
+ * already-scaled/translated) coordinate space - called from within pointContext's transform,
88
+ * before it restores the context.
89
+ * @param {number} order
90
+ */
91
+ journeyOrderBadgeContext(order) {
92
+ this.context.beginPath();
93
+ this.context.arc(POI_ICON_HEAD.x, POI_ICON_HEAD.y, POI_ICON_HEAD.radius, 0, Math.PI * 2);
94
+ this.context.fillStyle = '#ffffff';
95
+ this.context.fill();
96
+
97
+ this.context.fillStyle = this.currentPalette().fillStyle || POI_ICON_DEFAULT_FILL;
98
+ this.context.font = `bold ${POI_ICON_HEAD.radius}px sans-serif`;
99
+ this.context.textAlign = 'center';
100
+ this.context.textBaseline = 'middle';
101
+ this.context.fillText(String(order), POI_ICON_HEAD.x, POI_ICON_HEAD.y);
102
+ }
103
+
28
104
  /** */
29
105
  get svgString() {
30
106
  return this.resource.svgSelector.value;
@@ -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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"}