react-iiif-vault 0.9.10 → 0.9.13
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/.build/types/canvas-panel/Viewer.d.ts +13 -0
- package/.build/types/canvas-panel/index.d.ts +18 -0
- package/.build/types/canvas-panel/render/Annotation.d.ts +8 -0
- package/.build/types/canvas-panel/render/AnnotationPage.d.ts +6 -0
- package/.build/types/canvas-panel/render/Audio.d.ts +6 -0
- package/.build/types/canvas-panel/render/Canvas.d.ts +23 -0
- package/.build/types/canvas-panel/render/DefaultCanvasFallback.d.ts +5 -0
- package/.build/types/canvas-panel/render/Image.d.ts +13 -0
- package/.build/types/canvas-panel/render/Model.d.ts +3 -0
- package/.build/types/canvas-panel/render/Video.d.ts +6 -0
- package/.build/types/context/AnnotationContext.d.ts +5 -0
- package/.build/types/context/CanvasContext.d.ts +5 -0
- package/.build/types/context/CollectionContext.d.ts +5 -0
- package/.build/types/context/ContextBridge.d.ts +22 -0
- package/.build/types/context/ImageServiceLoaderContext.d.ts +4 -0
- package/.build/types/context/ManifestContext.d.ts +5 -0
- package/.build/types/context/MediaContext.d.ts +17 -0
- package/.build/types/context/PortalContext.d.ts +7 -0
- package/.build/types/context/RangeContext.d.ts +5 -0
- package/.build/types/context/ResourceContext.d.ts +14 -0
- package/.build/types/context/VaultContext.d.ts +14 -0
- package/.build/types/context/ViewerPresetContext.d.ts +3 -0
- package/.build/types/context/VisibleCanvasContext.d.ts +4 -0
- package/.build/types/demo/demo.d.ts +1 -0
- package/.build/types/demo/media-controls.d.ts +1 -0
- package/.build/types/demo/viewer-controls.d.ts +1 -0
- package/.build/types/features/rendering-strategy/3d-strategy.d.ts +13 -0
- package/.build/types/features/rendering-strategy/audio-strategy.d.ts +3 -0
- package/.build/types/features/rendering-strategy/choice-types.d.ts +15 -0
- package/.build/types/features/rendering-strategy/image-strategy.d.ts +13 -0
- package/.build/types/features/rendering-strategy/rendering-utils.d.ts +21 -0
- package/.build/types/features/rendering-strategy/resource-types.d.ts +42 -0
- package/.build/types/features/rendering-strategy/strategies.d.ts +22 -0
- package/.build/types/features/rendering-strategy/video-strategy.d.ts +3 -0
- package/.build/types/hooks/useAnnotation.d.ts +8 -0
- package/.build/types/hooks/useAnnotationPageManager.d.ts +10 -0
- package/.build/types/hooks/useAnnotationsAtTime.d.ts +4 -0
- package/.build/types/hooks/useCanvas.d.ts +8 -0
- package/.build/types/hooks/useCanvasClock.d.ts +1 -0
- package/.build/types/hooks/useCanvasSelector.d.ts +0 -0
- package/.build/types/hooks/useCanvasTimeline.d.ts +0 -0
- package/.build/types/hooks/useCollection.d.ts +8 -0
- package/.build/types/hooks/useDispatch.d.ts +2 -0
- package/.build/types/hooks/useEnabledAnnotationPageIds.d.ts +1 -0
- package/.build/types/hooks/useEventListener.d.ts +4 -0
- package/.build/types/hooks/useExistingVault.d.ts +1 -0
- package/.build/types/hooks/useExternalCollection.d.ts +13 -0
- package/.build/types/hooks/useExternalManifest.d.ts +13 -0
- package/.build/types/hooks/useExternalResource.d.ts +16 -0
- package/.build/types/hooks/useImageService.d.ts +9 -0
- package/.build/types/hooks/useImageTile.d.ts +11 -0
- package/.build/types/hooks/useLoadImageService.d.ts +6 -0
- package/.build/types/hooks/useManifest.d.ts +8 -0
- package/.build/types/hooks/usePaintables.d.ts +8 -0
- package/.build/types/hooks/usePaintingAnnotations.d.ts +4 -0
- package/.build/types/hooks/useRange.d.ts +8 -0
- package/.build/types/hooks/useRenderingStrategy.d.ts +14 -0
- package/.build/types/hooks/useResourceEvents.d.ts +3 -0
- package/.build/types/hooks/useResources.d.ts +1 -0
- package/.build/types/hooks/useSearchService.d.ts +2 -0
- package/.build/types/hooks/useSimpleMediaPlayer.d.ts +32 -0
- package/.build/types/hooks/useStyleHelper.d.ts +1 -0
- package/.build/types/hooks/useStyles.d.ts +3 -0
- package/.build/types/hooks/useThumbnail.d.ts +5 -0
- package/.build/types/hooks/useVault.d.ts +2 -0
- package/.build/types/hooks/useVaultEffect.d.ts +2 -0
- package/.build/types/hooks/useVaultSelector.d.ts +2 -0
- package/.build/types/hooks/useVirtualAnnotationPage.d.ts +13 -0
- package/.build/types/hooks/useVirtualAnnotationPageContext.d.ts +9 -0
- package/.build/types/hooks/useVirtualCanvas.d.ts +0 -0
- package/.build/types/index.d.ts +54 -0
- package/.build/types/utility/flatten-annotation-page-ids.d.ts +7 -0
- package/.build/types/viewers/SimpleViewerContext.d.ts +18 -0
- package/.build/types/viewers/SingleCanvasContext.d.ts +1 -0
- package/dist/bundle/cjs/index.js +36 -0
- package/dist/bundle/cjs/index.js.map +1 -0
- package/dist/{esm → bundle/esm}/index.mjs +740 -791
- package/dist/bundle/esm/index.mjs.map +1 -0
- package/dist/canvas-panel/cjs/canvas-panel.js +36 -0
- package/dist/canvas-panel/cjs/canvas-panel.js.map +1 -0
- package/dist/canvas-panel/esm/canvas-panel.mjs +2043 -0
- package/dist/canvas-panel/esm/canvas-panel.mjs.map +1 -0
- package/dist/index.umd.js +121 -31742
- package/dist/index.umd.js.map +1 -0
- package/package.json +38 -28
- package/dist/cjs/index.js +0 -2536
- package/dist/index.d.ts +0 -615
|
@@ -0,0 +1,2043 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
var __objRest = (source, exclude) => {
|
|
21
|
+
var target = {};
|
|
22
|
+
for (var prop in source)
|
|
23
|
+
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
24
|
+
target[prop] = source[prop];
|
|
25
|
+
if (source != null && __getOwnPropSymbols)
|
|
26
|
+
for (var prop of __getOwnPropSymbols(source)) {
|
|
27
|
+
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
28
|
+
target[prop] = source[prop];
|
|
29
|
+
}
|
|
30
|
+
return target;
|
|
31
|
+
};
|
|
32
|
+
import * as React from "react";
|
|
33
|
+
import React__default, { useContext, useMemo, useState, useEffect, createContext, useRef, useLayoutEffect, useCallback, Fragment as Fragment$1, useReducer } from "react";
|
|
34
|
+
import { AtlasAuto, mergeStyles, RegionHighlight, TileSet } from "@atlas-viewer/atlas";
|
|
35
|
+
import { globalVault, Vault } from "@iiif/vault";
|
|
36
|
+
import { createAction } from "typesafe-actions";
|
|
37
|
+
import require$$0 from "react-dom";
|
|
38
|
+
import { ImageServiceLoader, getImageServices, getFixedSizeFromImage } from "@atlas-viewer/iiif-image-api";
|
|
39
|
+
function _setPrototypeOf(o, p2) {
|
|
40
|
+
_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf2(o2, p3) {
|
|
41
|
+
o2.__proto__ = p3;
|
|
42
|
+
return o2;
|
|
43
|
+
};
|
|
44
|
+
return _setPrototypeOf(o, p2);
|
|
45
|
+
}
|
|
46
|
+
function _inheritsLoose(subClass, superClass) {
|
|
47
|
+
subClass.prototype = Object.create(superClass.prototype);
|
|
48
|
+
subClass.prototype.constructor = subClass;
|
|
49
|
+
_setPrototypeOf(subClass, superClass);
|
|
50
|
+
}
|
|
51
|
+
var changedArray = function changedArray2(a, b) {
|
|
52
|
+
if (a === void 0) {
|
|
53
|
+
a = [];
|
|
54
|
+
}
|
|
55
|
+
if (b === void 0) {
|
|
56
|
+
b = [];
|
|
57
|
+
}
|
|
58
|
+
return a.length !== b.length || a.some(function(item, index) {
|
|
59
|
+
return !Object.is(item, b[index]);
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
var initialState = {
|
|
63
|
+
error: null
|
|
64
|
+
};
|
|
65
|
+
var ErrorBoundary = /* @__PURE__ */ function(_React$Component) {
|
|
66
|
+
_inheritsLoose(ErrorBoundary2, _React$Component);
|
|
67
|
+
function ErrorBoundary2() {
|
|
68
|
+
var _this;
|
|
69
|
+
for (var _len = arguments.length, _args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
70
|
+
_args[_key] = arguments[_key];
|
|
71
|
+
}
|
|
72
|
+
_this = _React$Component.call.apply(_React$Component, [this].concat(_args)) || this;
|
|
73
|
+
_this.state = initialState;
|
|
74
|
+
_this.resetErrorBoundary = function() {
|
|
75
|
+
var _this$props;
|
|
76
|
+
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
|
77
|
+
args[_key2] = arguments[_key2];
|
|
78
|
+
}
|
|
79
|
+
_this.props.onReset == null ? void 0 : (_this$props = _this.props).onReset.apply(_this$props, args);
|
|
80
|
+
_this.reset();
|
|
81
|
+
};
|
|
82
|
+
return _this;
|
|
83
|
+
}
|
|
84
|
+
ErrorBoundary2.getDerivedStateFromError = function getDerivedStateFromError(error) {
|
|
85
|
+
return {
|
|
86
|
+
error
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
var _proto = ErrorBoundary2.prototype;
|
|
90
|
+
_proto.reset = function reset() {
|
|
91
|
+
this.setState(initialState);
|
|
92
|
+
};
|
|
93
|
+
_proto.componentDidCatch = function componentDidCatch(error, info) {
|
|
94
|
+
var _this$props$onError, _this$props2;
|
|
95
|
+
(_this$props$onError = (_this$props2 = this.props).onError) == null ? void 0 : _this$props$onError.call(_this$props2, error, info);
|
|
96
|
+
};
|
|
97
|
+
_proto.componentDidUpdate = function componentDidUpdate(prevProps, prevState) {
|
|
98
|
+
var error = this.state.error;
|
|
99
|
+
var resetKeys = this.props.resetKeys;
|
|
100
|
+
if (error !== null && prevState.error !== null && changedArray(prevProps.resetKeys, resetKeys)) {
|
|
101
|
+
var _this$props$onResetKe, _this$props3;
|
|
102
|
+
(_this$props$onResetKe = (_this$props3 = this.props).onResetKeysChange) == null ? void 0 : _this$props$onResetKe.call(_this$props3, prevProps.resetKeys, resetKeys);
|
|
103
|
+
this.reset();
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
_proto.render = function render() {
|
|
107
|
+
var error = this.state.error;
|
|
108
|
+
var _this$props4 = this.props, fallbackRender = _this$props4.fallbackRender, FallbackComponent = _this$props4.FallbackComponent, fallback = _this$props4.fallback;
|
|
109
|
+
if (error !== null) {
|
|
110
|
+
var _props = {
|
|
111
|
+
error,
|
|
112
|
+
resetErrorBoundary: this.resetErrorBoundary
|
|
113
|
+
};
|
|
114
|
+
if (/* @__PURE__ */ React.isValidElement(fallback)) {
|
|
115
|
+
return fallback;
|
|
116
|
+
} else if (typeof fallbackRender === "function") {
|
|
117
|
+
return fallbackRender(_props);
|
|
118
|
+
} else if (FallbackComponent) {
|
|
119
|
+
return /* @__PURE__ */ React.createElement(FallbackComponent, _props);
|
|
120
|
+
} else {
|
|
121
|
+
throw new Error("react-error-boundary requires either a fallback, fallbackRender, or FallbackComponent prop");
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return this.props.children;
|
|
125
|
+
};
|
|
126
|
+
return ErrorBoundary2;
|
|
127
|
+
}(React.Component);
|
|
128
|
+
var jsxRuntime = { exports: {} };
|
|
129
|
+
var reactJsxRuntime_production_min = {};
|
|
130
|
+
/**
|
|
131
|
+
* @license React
|
|
132
|
+
* react-jsx-runtime.production.min.js
|
|
133
|
+
*
|
|
134
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
135
|
+
*
|
|
136
|
+
* This source code is licensed under the MIT license found in the
|
|
137
|
+
* LICENSE file in the root directory of this source tree.
|
|
138
|
+
*/
|
|
139
|
+
var f = React__default, k = Symbol.for("react.element"), l = Symbol.for("react.fragment"), m$1 = Object.prototype.hasOwnProperty, n = f.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner, p = { key: true, ref: true, __self: true, __source: true };
|
|
140
|
+
function q(c, a, g) {
|
|
141
|
+
var b, d = {}, e = null, h = null;
|
|
142
|
+
g !== void 0 && (e = "" + g);
|
|
143
|
+
a.key !== void 0 && (e = "" + a.key);
|
|
144
|
+
a.ref !== void 0 && (h = a.ref);
|
|
145
|
+
for (b in a)
|
|
146
|
+
m$1.call(a, b) && !p.hasOwnProperty(b) && (d[b] = a[b]);
|
|
147
|
+
if (c && c.defaultProps)
|
|
148
|
+
for (b in a = c.defaultProps, a)
|
|
149
|
+
d[b] === void 0 && (d[b] = a[b]);
|
|
150
|
+
return { $$typeof: k, type: c, key: e, ref: h, props: d, _owner: n.current };
|
|
151
|
+
}
|
|
152
|
+
reactJsxRuntime_production_min.Fragment = l;
|
|
153
|
+
reactJsxRuntime_production_min.jsx = q;
|
|
154
|
+
reactJsxRuntime_production_min.jsxs = q;
|
|
155
|
+
{
|
|
156
|
+
jsxRuntime.exports = reactJsxRuntime_production_min;
|
|
157
|
+
}
|
|
158
|
+
const jsx = jsxRuntime.exports.jsx;
|
|
159
|
+
const jsxs = jsxRuntime.exports.jsxs;
|
|
160
|
+
const Fragment = jsxRuntime.exports.Fragment;
|
|
161
|
+
const defaultResourceContext = {
|
|
162
|
+
collection: void 0,
|
|
163
|
+
manifest: void 0,
|
|
164
|
+
range: void 0,
|
|
165
|
+
canvas: void 0,
|
|
166
|
+
annotation: void 0
|
|
167
|
+
};
|
|
168
|
+
const ResourceReactContext = React__default.createContext(defaultResourceContext);
|
|
169
|
+
const useResourceContext = () => {
|
|
170
|
+
return useContext(ResourceReactContext);
|
|
171
|
+
};
|
|
172
|
+
function ResourceProvider({
|
|
173
|
+
value,
|
|
174
|
+
children
|
|
175
|
+
}) {
|
|
176
|
+
const parentContext = useResourceContext();
|
|
177
|
+
const newContext = useMemo(() => {
|
|
178
|
+
return __spreadValues(__spreadValues({}, parentContext), value);
|
|
179
|
+
}, [value, parentContext]);
|
|
180
|
+
return /* @__PURE__ */ jsx(ResourceReactContext.Provider, {
|
|
181
|
+
value: newContext,
|
|
182
|
+
children
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
const ReactVaultContext = React__default.createContext({
|
|
186
|
+
vault: null,
|
|
187
|
+
setVaultInstance: (vault) => {
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
function VaultProvider({
|
|
191
|
+
vault,
|
|
192
|
+
vaultOptions,
|
|
193
|
+
useGlobal,
|
|
194
|
+
resources,
|
|
195
|
+
children
|
|
196
|
+
}) {
|
|
197
|
+
const [vaultInstance, setVaultInstance] = useState(() => {
|
|
198
|
+
if (vault) {
|
|
199
|
+
return vault;
|
|
200
|
+
}
|
|
201
|
+
if (useGlobal) {
|
|
202
|
+
return globalVault(vaultOptions);
|
|
203
|
+
}
|
|
204
|
+
if (vaultOptions) {
|
|
205
|
+
return new Vault(vaultOptions);
|
|
206
|
+
}
|
|
207
|
+
return new Vault();
|
|
208
|
+
});
|
|
209
|
+
return /* @__PURE__ */ jsx(ReactVaultContext.Provider, {
|
|
210
|
+
value: {
|
|
211
|
+
vault: vaultInstance,
|
|
212
|
+
setVaultInstance
|
|
213
|
+
},
|
|
214
|
+
children: /* @__PURE__ */ jsx(ResourceProvider, {
|
|
215
|
+
value: resources || {},
|
|
216
|
+
children
|
|
217
|
+
})
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
const useVault = () => {
|
|
221
|
+
const { vault } = useContext(ReactVaultContext);
|
|
222
|
+
if (vault === null) {
|
|
223
|
+
throw new Error("Vault not found. Ensure you have your provider set up correctly.");
|
|
224
|
+
}
|
|
225
|
+
return vault;
|
|
226
|
+
};
|
|
227
|
+
function CanvasContext({
|
|
228
|
+
canvas,
|
|
229
|
+
children
|
|
230
|
+
}) {
|
|
231
|
+
return /* @__PURE__ */ jsx(ResourceProvider, {
|
|
232
|
+
value: {
|
|
233
|
+
canvas
|
|
234
|
+
},
|
|
235
|
+
children
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
function useVaultSelector(selector, deps = []) {
|
|
239
|
+
const vault = useVault();
|
|
240
|
+
const [selectedState, setSelectedState] = useState(() => selector(vault.getState(), vault));
|
|
241
|
+
useEffect(() => {
|
|
242
|
+
return vault.subscribe((s) => selector(s, vault), (s) => {
|
|
243
|
+
setSelectedState(s);
|
|
244
|
+
}, false);
|
|
245
|
+
}, deps);
|
|
246
|
+
return selectedState;
|
|
247
|
+
}
|
|
248
|
+
const VisibleCanvasReactContext = React__default.createContext([]);
|
|
249
|
+
function useVisibleCanvases() {
|
|
250
|
+
const ids = useContext(VisibleCanvasReactContext);
|
|
251
|
+
return useVaultSelector((state) => {
|
|
252
|
+
return ids.map((id) => state.iiif.entities.Canvas[id]).filter(Boolean);
|
|
253
|
+
}, [ids]);
|
|
254
|
+
}
|
|
255
|
+
const noop = () => {
|
|
256
|
+
};
|
|
257
|
+
const SimpleViewerReactContext = createContext({
|
|
258
|
+
setCurrentCanvasId: noop,
|
|
259
|
+
setCurrentCanvasIndex: noop,
|
|
260
|
+
nextCanvas: noop,
|
|
261
|
+
previousCanvas: noop,
|
|
262
|
+
currentCanvasIndex: -1,
|
|
263
|
+
totalCanvases: 0,
|
|
264
|
+
pagingView: true
|
|
265
|
+
});
|
|
266
|
+
function useContextBridge() {
|
|
267
|
+
return {
|
|
268
|
+
VaultContext: useContext(ReactVaultContext),
|
|
269
|
+
ResourceContext: useContext(ResourceReactContext),
|
|
270
|
+
SimpleViewerReactContext: useContext(SimpleViewerReactContext),
|
|
271
|
+
VisibleCanvasReactContext: useContext(VisibleCanvasReactContext)
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
function ContextBridge(props) {
|
|
275
|
+
return /* @__PURE__ */ jsx(VaultProvider, {
|
|
276
|
+
vault: props.bridge.VaultContext.vault || void 0,
|
|
277
|
+
resources: props.bridge.ResourceContext,
|
|
278
|
+
children: /* @__PURE__ */ jsx(VisibleCanvasReactContext.Provider, {
|
|
279
|
+
value: props.bridge.VisibleCanvasReactContext,
|
|
280
|
+
children: /* @__PURE__ */ jsx(SimpleViewerReactContext.Provider, {
|
|
281
|
+
value: props.bridge.SimpleViewerReactContext,
|
|
282
|
+
children: props.children
|
|
283
|
+
})
|
|
284
|
+
})
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
const IMPORT_ENTITIES = "@iiif/IMPORT_ENTITIES";
|
|
288
|
+
const MODIFY_ENTITY_FIELD = "@iiif/MODIFY_ENTITY_FIELD";
|
|
289
|
+
const REORDER_ENTITY_FIELD = "@iiif/REORDER_ENTITY_FIELD";
|
|
290
|
+
const ADD_REFERENCE = "@iiif/ADD_REFERENCE";
|
|
291
|
+
const REMOVE_REFERENCE = "@iiif/REMOVE_REFERENCE";
|
|
292
|
+
const importEntities = createAction(IMPORT_ENTITIES)();
|
|
293
|
+
const modifyEntityField = createAction(MODIFY_ENTITY_FIELD)();
|
|
294
|
+
const reorderEntityField = createAction(REORDER_ENTITY_FIELD)();
|
|
295
|
+
const addReference = createAction(ADD_REFERENCE)();
|
|
296
|
+
const removeReference = createAction(REMOVE_REFERENCE)();
|
|
297
|
+
const entityActions = { importEntities, modifyEntityField, reorderEntityField, addReference, removeReference };
|
|
298
|
+
const ADD_MAPPING = "@iiif/ADD_MAPPING";
|
|
299
|
+
const ADD_MAPPINGS = "@iiif/ADD_MAPPINGS";
|
|
300
|
+
createAction(ADD_MAPPING)();
|
|
301
|
+
createAction(ADD_MAPPINGS)();
|
|
302
|
+
const SET_META_VALUE = "@iiif/SET_META_VALUE";
|
|
303
|
+
const SET_META_VALUE_DYNAMIC = "@iiif/SET_META_VALUE_DYNAMIC";
|
|
304
|
+
const UNSET_META_VALUE = "@iiif/UNSET_META_VALUE";
|
|
305
|
+
createAction(SET_META_VALUE)();
|
|
306
|
+
createAction(SET_META_VALUE_DYNAMIC)();
|
|
307
|
+
createAction(UNSET_META_VALUE)();
|
|
308
|
+
const REQUEST_RESOURCE = "@iiif/REQUEST_RESOURCE";
|
|
309
|
+
const REQUEST_ERROR = "@iiif/REQUEST_ERROR";
|
|
310
|
+
const REQUEST_MISMATCH = "@iiif/REQUEST_MISMATCH";
|
|
311
|
+
const REQUEST_COMPLETE = "@iiif/REQUEST_COMPLETE";
|
|
312
|
+
const REQUEST_OFFLINE_RESOURCE = "@iiif/REQUEST_OFFLINE_RESOURCE";
|
|
313
|
+
createAction(REQUEST_RESOURCE)();
|
|
314
|
+
createAction(REQUEST_ERROR)();
|
|
315
|
+
createAction(REQUEST_MISMATCH)();
|
|
316
|
+
createAction(REQUEST_COMPLETE)();
|
|
317
|
+
createAction(REQUEST_OFFLINE_RESOURCE)();
|
|
318
|
+
const BATCH_ACTIONS = "@iiif/BATCH";
|
|
319
|
+
const BATCH_IMPORT = "@iiif/BATCH_IMPORT";
|
|
320
|
+
createAction(BATCH_ACTIONS)();
|
|
321
|
+
createAction(BATCH_IMPORT)();
|
|
322
|
+
function useDispatch() {
|
|
323
|
+
const vault = useVault();
|
|
324
|
+
const store = vault.getStore();
|
|
325
|
+
return useMemo(() => {
|
|
326
|
+
return (action) => store.dispatch(action);
|
|
327
|
+
}, [store]);
|
|
328
|
+
}
|
|
329
|
+
function isVaultActivated(obj) {
|
|
330
|
+
return typeof obj !== "string" && obj && obj.bindToVault;
|
|
331
|
+
}
|
|
332
|
+
function useVirtualAnnotationPage() {
|
|
333
|
+
const vault = useVault();
|
|
334
|
+
const sources = useRef([]);
|
|
335
|
+
const dispatch = useDispatch();
|
|
336
|
+
const virtualId = useMemo(() => {
|
|
337
|
+
return `vault://annotation-page/${new Date().getTime()}/${Math.round(Math.random() * 1e9).toString(16)}`;
|
|
338
|
+
}, []);
|
|
339
|
+
useLayoutEffect(() => {
|
|
340
|
+
const page = {
|
|
341
|
+
id: virtualId,
|
|
342
|
+
type: "AnnotationPage",
|
|
343
|
+
behavior: [],
|
|
344
|
+
motivation: null,
|
|
345
|
+
label: null,
|
|
346
|
+
thumbnail: [],
|
|
347
|
+
summary: null,
|
|
348
|
+
requiredStatement: null,
|
|
349
|
+
metadata: [],
|
|
350
|
+
rights: null,
|
|
351
|
+
provider: [],
|
|
352
|
+
items: [],
|
|
353
|
+
seeAlso: [],
|
|
354
|
+
homepage: [],
|
|
355
|
+
logo: [],
|
|
356
|
+
rendering: [],
|
|
357
|
+
service: []
|
|
358
|
+
};
|
|
359
|
+
dispatch(entityActions.importEntities({
|
|
360
|
+
entities: {
|
|
361
|
+
AnnotationPage: {
|
|
362
|
+
[page.id]: page
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}));
|
|
366
|
+
}, [virtualId]);
|
|
367
|
+
const fullPage = useVaultSelector((state) => virtualId ? state.iiif.entities.AnnotationPage[virtualId] : null, [virtualId]);
|
|
368
|
+
const addAnnotation = useCallback((id, atIndex) => {
|
|
369
|
+
if (virtualId) {
|
|
370
|
+
if (isVaultActivated(id)) {
|
|
371
|
+
const display = id;
|
|
372
|
+
if (!display.__vault) {
|
|
373
|
+
display.bindToVault(vault);
|
|
374
|
+
}
|
|
375
|
+
id = typeof display.source === "string" ? display.source : display.source.id;
|
|
376
|
+
sources.current[id] = display;
|
|
377
|
+
} else if (typeof id !== "string") {
|
|
378
|
+
id = id.id;
|
|
379
|
+
}
|
|
380
|
+
const full = vault.get({ id: virtualId, type: "AnnotationPage" });
|
|
381
|
+
const annotation = vault.get({ id, type: "Annotation" });
|
|
382
|
+
if (full && annotation) {
|
|
383
|
+
if (!full.items.find((r) => r.id === annotation.id)) {
|
|
384
|
+
dispatch(entityActions.addReference({
|
|
385
|
+
id: virtualId,
|
|
386
|
+
type: "AnnotationPage",
|
|
387
|
+
key: "items",
|
|
388
|
+
reference: {
|
|
389
|
+
id,
|
|
390
|
+
type: "Annotation"
|
|
391
|
+
},
|
|
392
|
+
index: atIndex
|
|
393
|
+
}));
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}, [virtualId]);
|
|
398
|
+
const removeAnnotation = useCallback((id) => {
|
|
399
|
+
if (virtualId) {
|
|
400
|
+
if (isVaultActivated(id)) {
|
|
401
|
+
id = typeof id.source === "string" ? id.source : id.source.id;
|
|
402
|
+
} else if (typeof id !== "string") {
|
|
403
|
+
id = id.id;
|
|
404
|
+
}
|
|
405
|
+
if (sources.current[id]) {
|
|
406
|
+
sources.current[id].beforeRemove();
|
|
407
|
+
}
|
|
408
|
+
const full = vault.get({ id: virtualId, type: "AnnotationPage" });
|
|
409
|
+
if (full) {
|
|
410
|
+
dispatch(entityActions.removeReference({
|
|
411
|
+
id: virtualId,
|
|
412
|
+
type: "AnnotationPage",
|
|
413
|
+
key: "items",
|
|
414
|
+
reference: {
|
|
415
|
+
id,
|
|
416
|
+
type: "Annotation"
|
|
417
|
+
}
|
|
418
|
+
}));
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}, [virtualId]);
|
|
422
|
+
return [
|
|
423
|
+
fullPage,
|
|
424
|
+
{
|
|
425
|
+
addAnnotation,
|
|
426
|
+
removeAnnotation
|
|
427
|
+
}
|
|
428
|
+
];
|
|
429
|
+
}
|
|
430
|
+
const VirtualAnnotationPageContext = createContext(null);
|
|
431
|
+
function useVirtualAnnotationPageContext() {
|
|
432
|
+
const ctx = useContext(VirtualAnnotationPageContext);
|
|
433
|
+
return [ctx.fullPage, {
|
|
434
|
+
addAnnotation: ctx.addAnnotation,
|
|
435
|
+
removeAnnotation: ctx.removeAnnotation
|
|
436
|
+
}];
|
|
437
|
+
}
|
|
438
|
+
function VirtualAnnotationProvider({
|
|
439
|
+
children
|
|
440
|
+
}) {
|
|
441
|
+
const [fullPage, {
|
|
442
|
+
addAnnotation,
|
|
443
|
+
removeAnnotation
|
|
444
|
+
}] = useVirtualAnnotationPage();
|
|
445
|
+
return /* @__PURE__ */ jsx(VirtualAnnotationPageContext.Provider, {
|
|
446
|
+
value: useMemo(() => ({
|
|
447
|
+
fullPage,
|
|
448
|
+
addAnnotation,
|
|
449
|
+
removeAnnotation
|
|
450
|
+
}), [fullPage]),
|
|
451
|
+
children
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
function DefaultCanvasFallback({
|
|
455
|
+
width,
|
|
456
|
+
style,
|
|
457
|
+
height
|
|
458
|
+
}) {
|
|
459
|
+
return /* @__PURE__ */ jsx("div", {
|
|
460
|
+
style: __spreadProps(__spreadValues({
|
|
461
|
+
width,
|
|
462
|
+
height,
|
|
463
|
+
minHeight: 500
|
|
464
|
+
}, style || {}), {
|
|
465
|
+
background: "#f9f9f9"
|
|
466
|
+
}),
|
|
467
|
+
children: "Unknown error"
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
var createRoot;
|
|
471
|
+
var m = require$$0;
|
|
472
|
+
{
|
|
473
|
+
createRoot = m.createRoot;
|
|
474
|
+
}
|
|
475
|
+
const ViewerPresetContext = createContext(null);
|
|
476
|
+
function useViewerPreset() {
|
|
477
|
+
return useContext(ViewerPresetContext);
|
|
478
|
+
}
|
|
479
|
+
const PortalContext = React__default.createContext(null);
|
|
480
|
+
const OverlayPortalContext = React__default.createContext(null);
|
|
481
|
+
function CanvasPortal({
|
|
482
|
+
children,
|
|
483
|
+
overlay
|
|
484
|
+
}) {
|
|
485
|
+
const htmlElement = useContext(overlay ? OverlayPortalContext : PortalContext);
|
|
486
|
+
const rootRef = useRef(null);
|
|
487
|
+
const preset = useViewerPreset();
|
|
488
|
+
useLayoutEffect(() => {
|
|
489
|
+
if (!rootRef.current) {
|
|
490
|
+
rootRef.current = htmlElement ? createRoot(htmlElement) : null;
|
|
491
|
+
}
|
|
492
|
+
}, []);
|
|
493
|
+
useLayoutEffect(() => {
|
|
494
|
+
return () => {
|
|
495
|
+
var _a;
|
|
496
|
+
(_a = rootRef.current) == null ? void 0 : _a.unmount();
|
|
497
|
+
rootRef.current = null;
|
|
498
|
+
};
|
|
499
|
+
}, []);
|
|
500
|
+
useLayoutEffect(() => {
|
|
501
|
+
if (rootRef.current) {
|
|
502
|
+
rootRef.current.render(/* @__PURE__ */ jsx(ViewerPresetContext.Provider, {
|
|
503
|
+
value: preset,
|
|
504
|
+
children
|
|
505
|
+
}));
|
|
506
|
+
}
|
|
507
|
+
}, [children, preset]);
|
|
508
|
+
return null;
|
|
509
|
+
}
|
|
510
|
+
function Viewer(_a) {
|
|
511
|
+
var _b = _a, {
|
|
512
|
+
children,
|
|
513
|
+
errorFallback,
|
|
514
|
+
outerContainerProps = {}
|
|
515
|
+
} = _b, props = __objRest(_b, [
|
|
516
|
+
"children",
|
|
517
|
+
"errorFallback",
|
|
518
|
+
"outerContainerProps"
|
|
519
|
+
]);
|
|
520
|
+
const portal = useRef(null);
|
|
521
|
+
const [portalElement, setPortalElement] = useState();
|
|
522
|
+
const [viewerPreset, setViewerPreset] = useState();
|
|
523
|
+
const overlayPortal = useRef(null);
|
|
524
|
+
const [overlayPortalElement, setOverlayPortalElement] = useState();
|
|
525
|
+
const bridge = useContextBridge();
|
|
526
|
+
const ErrorFallback = errorFallback || DefaultCanvasFallback;
|
|
527
|
+
useLayoutEffect(() => {
|
|
528
|
+
setPortalElement(portal.current);
|
|
529
|
+
setOverlayPortalElement(overlayPortal.current);
|
|
530
|
+
}, []);
|
|
531
|
+
return /* @__PURE__ */ jsxs(ErrorBoundary, {
|
|
532
|
+
fallbackRender: () => /* @__PURE__ */ jsx(ErrorFallback, __spreadValues({}, props)),
|
|
533
|
+
children: [/* @__PURE__ */ jsx(AtlasAuto, __spreadProps(__spreadValues({}, props), {
|
|
534
|
+
containerProps: __spreadValues({
|
|
535
|
+
style: {
|
|
536
|
+
position: "relative"
|
|
537
|
+
}
|
|
538
|
+
}, props.containerProps || {}),
|
|
539
|
+
htmlChildren: /* @__PURE__ */ jsx("div", {
|
|
540
|
+
ref: overlayPortal
|
|
541
|
+
}),
|
|
542
|
+
onCreated: (preset) => {
|
|
543
|
+
setViewerPreset(preset);
|
|
544
|
+
if (props.onCreated) {
|
|
545
|
+
props.onCreated(preset);
|
|
546
|
+
}
|
|
547
|
+
},
|
|
548
|
+
children: /* @__PURE__ */ jsx(ViewerPresetContext.Provider, {
|
|
549
|
+
value: viewerPreset,
|
|
550
|
+
children: /* @__PURE__ */ jsx(PortalContext.Provider, {
|
|
551
|
+
value: portalElement,
|
|
552
|
+
children: /* @__PURE__ */ jsx(OverlayPortalContext.Provider, {
|
|
553
|
+
value: overlayPortalElement,
|
|
554
|
+
children: /* @__PURE__ */ jsx(ContextBridge, {
|
|
555
|
+
bridge,
|
|
556
|
+
children: /* @__PURE__ */ jsx(VirtualAnnotationProvider, {
|
|
557
|
+
children
|
|
558
|
+
})
|
|
559
|
+
})
|
|
560
|
+
})
|
|
561
|
+
})
|
|
562
|
+
})
|
|
563
|
+
})), /* @__PURE__ */ jsx("div", {
|
|
564
|
+
ref: portal
|
|
565
|
+
})]
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
function createEventsHelper(vault) {
|
|
569
|
+
return {
|
|
570
|
+
addEventListener(resource, event, listener, scope) {
|
|
571
|
+
if (!resource) {
|
|
572
|
+
return;
|
|
573
|
+
}
|
|
574
|
+
vault.setMetaValue([resource.id, "eventManager", event], (registeredCallbacks) => {
|
|
575
|
+
const callbacks = registeredCallbacks || [];
|
|
576
|
+
for (const registered of callbacks) {
|
|
577
|
+
if (registered.callback === listener) {
|
|
578
|
+
return callbacks;
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
return [...callbacks, { callback: listener, scope }];
|
|
582
|
+
});
|
|
583
|
+
return listener;
|
|
584
|
+
},
|
|
585
|
+
removeEventListener(resource, event, listener) {
|
|
586
|
+
if (!resource) {
|
|
587
|
+
return;
|
|
588
|
+
}
|
|
589
|
+
vault.setMetaValue([resource.id, "eventManager", event], (registeredCallbacks) => {
|
|
590
|
+
return (registeredCallbacks || []).filter((registeredCallback) => registeredCallback.callback !== listener);
|
|
591
|
+
});
|
|
592
|
+
},
|
|
593
|
+
getListenersAsProps(resourceOrId, scope) {
|
|
594
|
+
const resource = typeof resourceOrId === "string" ? { id: resourceOrId } : resourceOrId;
|
|
595
|
+
if (!resource || !resource.id) {
|
|
596
|
+
return {};
|
|
597
|
+
}
|
|
598
|
+
const hooks = vault.getResourceMeta(resource.id, "eventManager");
|
|
599
|
+
const props = {};
|
|
600
|
+
if (hooks && resource) {
|
|
601
|
+
for (const hook of Object.keys(hooks)) {
|
|
602
|
+
props[hook] = (e) => {
|
|
603
|
+
const fullResource = vault.get(resource);
|
|
604
|
+
for (const { callback, scope: _scope } of hooks[hook] || []) {
|
|
605
|
+
if (!_scope || scope && _scope.indexOf(scope) !== -1) {
|
|
606
|
+
callback(e, fullResource);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
};
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
return props;
|
|
613
|
+
}
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
function useResourceEvents(resource, scope) {
|
|
617
|
+
const vault = useVault();
|
|
618
|
+
const helper = useMemo(() => createEventsHelper(vault), [vault]);
|
|
619
|
+
const hooks = useVaultSelector(() => {
|
|
620
|
+
if (resource && resource.id) {
|
|
621
|
+
return vault.getResourceMeta(resource.id, "eventManager");
|
|
622
|
+
}
|
|
623
|
+
return null;
|
|
624
|
+
}, [resource]);
|
|
625
|
+
return useMemo(() => {
|
|
626
|
+
return resource ? helper.getListenersAsProps(resource, scope) : {};
|
|
627
|
+
}, [hooks, resource, vault, scope]);
|
|
628
|
+
}
|
|
629
|
+
function createStylesHelper(vault) {
|
|
630
|
+
return {
|
|
631
|
+
applyStyles(resource, scope, styles) {
|
|
632
|
+
const id = typeof resource === "string" ? resource : resource.id;
|
|
633
|
+
return vault.setMetaValue([id, "styles", scope], styles);
|
|
634
|
+
},
|
|
635
|
+
getAppliedStyles(resource) {
|
|
636
|
+
const id = typeof resource === "string" ? resource : resource.id;
|
|
637
|
+
return vault.getResourceMeta(id, "styles");
|
|
638
|
+
}
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
function useStyles(resource, scope) {
|
|
642
|
+
const vault = useVault();
|
|
643
|
+
const helper = useMemo(() => createStylesHelper(vault), [vault]);
|
|
644
|
+
return useVaultSelector(() => {
|
|
645
|
+
if (!resource) {
|
|
646
|
+
return null;
|
|
647
|
+
}
|
|
648
|
+
const styles = helper.getAppliedStyles(resource.id);
|
|
649
|
+
return styles ? scope ? styles[scope] : styles : void 0;
|
|
650
|
+
}, [resource, scope]);
|
|
651
|
+
}
|
|
652
|
+
var __defProp2 = Object.defineProperty;
|
|
653
|
+
var __defProps2 = Object.defineProperties;
|
|
654
|
+
var __getOwnPropDescs2 = Object.getOwnPropertyDescriptors;
|
|
655
|
+
var __getOwnPropSymbols2 = Object.getOwnPropertySymbols;
|
|
656
|
+
var __hasOwnProp2 = Object.prototype.hasOwnProperty;
|
|
657
|
+
var __propIsEnum2 = Object.prototype.propertyIsEnumerable;
|
|
658
|
+
var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
659
|
+
var __spreadValues2 = (a, b) => {
|
|
660
|
+
for (var prop in b || (b = {}))
|
|
661
|
+
if (__hasOwnProp2.call(b, prop))
|
|
662
|
+
__defNormalProp2(a, prop, b[prop]);
|
|
663
|
+
if (__getOwnPropSymbols2)
|
|
664
|
+
for (var prop of __getOwnPropSymbols2(b)) {
|
|
665
|
+
if (__propIsEnum2.call(b, prop))
|
|
666
|
+
__defNormalProp2(a, prop, b[prop]);
|
|
667
|
+
}
|
|
668
|
+
return a;
|
|
669
|
+
};
|
|
670
|
+
var __spreadProps2 = (a, b) => __defProps2(a, __getOwnPropDescs2(b));
|
|
671
|
+
const BOX_SELECTOR = /&?(xywh=)?(pixel:|percent:|pct:)?([0-9]+(?:\.[0-9]+)?),([0-9]+(?:\.[0-9]+)?),([0-9]+(?:\.[0-9]+)?),([0-9]+(?:\.[0-9]+)?)/;
|
|
672
|
+
const TEMPORAL_SELECTOR = /&?(t=)(npt:)?([0-9]+(.[0-9]+)?)?(,([0-9]+(.[0-9]+)?))?/;
|
|
673
|
+
function parseSelector(source) {
|
|
674
|
+
if (Array.isArray(source)) {
|
|
675
|
+
return source.reduce((data, nextSource) => {
|
|
676
|
+
const { selector, selectors } = parseSelector(nextSource);
|
|
677
|
+
if (selector) {
|
|
678
|
+
if (!data.selector) {
|
|
679
|
+
data.selector = selector;
|
|
680
|
+
}
|
|
681
|
+
data.selectors.push(...selectors);
|
|
682
|
+
}
|
|
683
|
+
return data;
|
|
684
|
+
}, {
|
|
685
|
+
selector: null,
|
|
686
|
+
selectors: []
|
|
687
|
+
});
|
|
688
|
+
}
|
|
689
|
+
if (!source) {
|
|
690
|
+
return {
|
|
691
|
+
selector: null,
|
|
692
|
+
selectors: []
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
if (typeof source === "string") {
|
|
696
|
+
const [id, fragment] = source.split("#");
|
|
697
|
+
if (!fragment) {
|
|
698
|
+
return {
|
|
699
|
+
selector: null,
|
|
700
|
+
selectors: []
|
|
701
|
+
};
|
|
702
|
+
}
|
|
703
|
+
return parseSelector({ type: "FragmentSelector", value: fragment });
|
|
704
|
+
}
|
|
705
|
+
if (source.type === "PointSelector" && (source.t || source.t === 0)) {
|
|
706
|
+
const selector = {
|
|
707
|
+
type: "TemporalSelector",
|
|
708
|
+
temporal: {
|
|
709
|
+
startTime: source.t
|
|
710
|
+
}
|
|
711
|
+
};
|
|
712
|
+
return {
|
|
713
|
+
selector,
|
|
714
|
+
selectors: [selector]
|
|
715
|
+
};
|
|
716
|
+
}
|
|
717
|
+
if (source.type === "FragmentSelector") {
|
|
718
|
+
const matchBoxSelector = BOX_SELECTOR.exec(source.value);
|
|
719
|
+
if (matchBoxSelector) {
|
|
720
|
+
const selector = {
|
|
721
|
+
type: "BoxSelector",
|
|
722
|
+
spatial: {
|
|
723
|
+
unit: matchBoxSelector[2] === "percent:" || matchBoxSelector[2] === "pct:" ? "percent" : "pixel",
|
|
724
|
+
x: parseFloat(matchBoxSelector[3]),
|
|
725
|
+
y: parseFloat(matchBoxSelector[4]),
|
|
726
|
+
width: parseFloat(matchBoxSelector[5]),
|
|
727
|
+
height: parseFloat(matchBoxSelector[6])
|
|
728
|
+
}
|
|
729
|
+
};
|
|
730
|
+
return {
|
|
731
|
+
selector,
|
|
732
|
+
selectors: [selector]
|
|
733
|
+
};
|
|
734
|
+
}
|
|
735
|
+
const matchTimeSelector = source.value.match(TEMPORAL_SELECTOR);
|
|
736
|
+
if (matchTimeSelector) {
|
|
737
|
+
const selector = {
|
|
738
|
+
type: "TemporalSelector",
|
|
739
|
+
temporal: {
|
|
740
|
+
startTime: matchTimeSelector[4] ? parseFloat(matchTimeSelector[4]) : 0,
|
|
741
|
+
endTime: matchTimeSelector[7] ? parseFloat(matchTimeSelector[7]) : void 0
|
|
742
|
+
}
|
|
743
|
+
};
|
|
744
|
+
return {
|
|
745
|
+
selector,
|
|
746
|
+
selectors: [selector]
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
return {
|
|
750
|
+
selector: null,
|
|
751
|
+
selectors: []
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
return {
|
|
755
|
+
selector: null,
|
|
756
|
+
selectors: []
|
|
757
|
+
};
|
|
758
|
+
}
|
|
759
|
+
function expandTarget(target, options = {}) {
|
|
760
|
+
if (Array.isArray(target)) {
|
|
761
|
+
return expandTarget(target[0]);
|
|
762
|
+
}
|
|
763
|
+
if (typeof target === "string") {
|
|
764
|
+
const [id, fragment] = target.split("#");
|
|
765
|
+
if (!fragment) {
|
|
766
|
+
return {
|
|
767
|
+
type: "SpecificResource",
|
|
768
|
+
source: { id, type: options.typeMap && options.typeMap[id] || "Unknown" },
|
|
769
|
+
selector: null,
|
|
770
|
+
selectors: []
|
|
771
|
+
};
|
|
772
|
+
}
|
|
773
|
+
return expandTarget({
|
|
774
|
+
type: "SpecificResource",
|
|
775
|
+
source: { id, type: "Unknown" },
|
|
776
|
+
selector: {
|
|
777
|
+
type: "FragmentSelector",
|
|
778
|
+
value: fragment
|
|
779
|
+
}
|
|
780
|
+
});
|
|
781
|
+
}
|
|
782
|
+
if (target.type === "Choice" || target.type === "List" || target.type === "Composite" || target.type === "Independents") {
|
|
783
|
+
return expandTarget(target.items[0]);
|
|
784
|
+
}
|
|
785
|
+
if (target.type === "SpecificResource") {
|
|
786
|
+
if (target.source.type === "Canvas" && target.source.partOf && typeof target.source.partOf === "string") {
|
|
787
|
+
target.source.partOf = [
|
|
788
|
+
{
|
|
789
|
+
id: target.source.partOf,
|
|
790
|
+
type: "Manifest"
|
|
791
|
+
}
|
|
792
|
+
];
|
|
793
|
+
}
|
|
794
|
+
const { selector, selectors } = target.selector ? parseSelector(target.selector) : { selector: null, selectors: [] };
|
|
795
|
+
return {
|
|
796
|
+
type: "SpecificResource",
|
|
797
|
+
source: target.source,
|
|
798
|
+
selector,
|
|
799
|
+
selectors
|
|
800
|
+
};
|
|
801
|
+
}
|
|
802
|
+
if (target.id) {
|
|
803
|
+
if (target.type === "Canvas" && target.partOf && typeof target.partOf === "string") {
|
|
804
|
+
target.partOf = [
|
|
805
|
+
{
|
|
806
|
+
id: target.partOf,
|
|
807
|
+
type: "Manifest"
|
|
808
|
+
}
|
|
809
|
+
];
|
|
810
|
+
}
|
|
811
|
+
const [id, fragment] = target.id.split("#");
|
|
812
|
+
if (!fragment) {
|
|
813
|
+
return {
|
|
814
|
+
type: "SpecificResource",
|
|
815
|
+
source: __spreadProps2(__spreadValues2({}, target), {
|
|
816
|
+
id
|
|
817
|
+
}),
|
|
818
|
+
selector: null,
|
|
819
|
+
selectors: []
|
|
820
|
+
};
|
|
821
|
+
}
|
|
822
|
+
return expandTarget({
|
|
823
|
+
type: "SpecificResource",
|
|
824
|
+
source: __spreadProps2(__spreadValues2({}, target), {
|
|
825
|
+
id
|
|
826
|
+
}),
|
|
827
|
+
selector: {
|
|
828
|
+
type: "FragmentSelector",
|
|
829
|
+
value: fragment
|
|
830
|
+
}
|
|
831
|
+
});
|
|
832
|
+
}
|
|
833
|
+
return {
|
|
834
|
+
type: "SpecificResource",
|
|
835
|
+
source: target,
|
|
836
|
+
selector: null,
|
|
837
|
+
selectors: []
|
|
838
|
+
};
|
|
839
|
+
}
|
|
840
|
+
function useAnnotation(options = {}, deps = []) {
|
|
841
|
+
const { id, selector } = options;
|
|
842
|
+
const ctx = useResourceContext();
|
|
843
|
+
const vault = useVault();
|
|
844
|
+
const annotationId = id ? id : ctx.annotation;
|
|
845
|
+
const annotation = useVaultSelector((s) => annotationId ? s.iiif.entities.Annotation[annotationId] : void 0, [annotationId]);
|
|
846
|
+
const body = useVaultSelector((s) => annotation && annotation.body ? annotation.body.map((singleBody) => singleBody ? s.iiif.entities[singleBody.type][singleBody.id] : null).filter(Boolean) : [], [annotation]);
|
|
847
|
+
return useMemo(() => {
|
|
848
|
+
if (!annotation) {
|
|
849
|
+
return void 0;
|
|
850
|
+
}
|
|
851
|
+
const newAnnotation = __spreadProps(__spreadValues({}, annotation), {
|
|
852
|
+
body,
|
|
853
|
+
target: expandTarget(annotation.target, { typeMap: vault.getState().iiif.mapping })
|
|
854
|
+
});
|
|
855
|
+
if (selector) {
|
|
856
|
+
return selector(newAnnotation);
|
|
857
|
+
}
|
|
858
|
+
return newAnnotation;
|
|
859
|
+
}, [annotation, selector, body, ...deps]);
|
|
860
|
+
}
|
|
861
|
+
function useCanvas(options = {}, deps = []) {
|
|
862
|
+
const { id, selector } = options;
|
|
863
|
+
const ctx = useResourceContext();
|
|
864
|
+
const canvasId = id ? id : ctx.canvas;
|
|
865
|
+
const canvas = useVaultSelector((s) => canvasId ? s.iiif.entities.Canvas[canvasId] : void 0, [canvasId]);
|
|
866
|
+
return useMemo(() => {
|
|
867
|
+
if (!canvas) {
|
|
868
|
+
return void 0;
|
|
869
|
+
}
|
|
870
|
+
if (selector) {
|
|
871
|
+
return selector(canvas);
|
|
872
|
+
}
|
|
873
|
+
return canvas;
|
|
874
|
+
}, [canvas, selector, ...deps]);
|
|
875
|
+
}
|
|
876
|
+
const RenderAnnotation = ({
|
|
877
|
+
id,
|
|
878
|
+
style: defaultStyle,
|
|
879
|
+
className,
|
|
880
|
+
interactive
|
|
881
|
+
}) => {
|
|
882
|
+
const annotation = useAnnotation({
|
|
883
|
+
id
|
|
884
|
+
});
|
|
885
|
+
const style = useStyles(annotation, "atlas");
|
|
886
|
+
const html = useStyles(annotation, "html");
|
|
887
|
+
const events = useResourceEvents(annotation, ["atlas"]);
|
|
888
|
+
const canvas = useCanvas();
|
|
889
|
+
const allStyles = useMemo(() => {
|
|
890
|
+
return mergeStyles(defaultStyle, style);
|
|
891
|
+
}, [defaultStyle, style]);
|
|
892
|
+
const isValid = canvas && annotation && annotation.target && annotation.target.selector && annotation.target.selector.type === "BoxSelector" && annotation.target.source && annotation.target.source.id === canvas.id;
|
|
893
|
+
if (!isValid) {
|
|
894
|
+
return null;
|
|
895
|
+
}
|
|
896
|
+
return /* @__PURE__ */ jsx(RegionHighlight, __spreadValues({
|
|
897
|
+
id: annotation.id,
|
|
898
|
+
isEditing: true,
|
|
899
|
+
region: annotation.target.selector.spatial,
|
|
900
|
+
style: allStyles,
|
|
901
|
+
className: (html == null ? void 0 : html.className) || className,
|
|
902
|
+
interactive: !!((html == null ? void 0 : html.href) || interactive),
|
|
903
|
+
href: (html == null ? void 0 : html.href) || null,
|
|
904
|
+
title: (html == null ? void 0 : html.title) || null,
|
|
905
|
+
hrefTarget: (html == null ? void 0 : html.target) || null
|
|
906
|
+
}, events));
|
|
907
|
+
};
|
|
908
|
+
const RenderAnnotationPage = ({
|
|
909
|
+
className,
|
|
910
|
+
page
|
|
911
|
+
}) => {
|
|
912
|
+
var _a;
|
|
913
|
+
const style = useStyles(page, "atlas");
|
|
914
|
+
const html = useStyles(page, "html");
|
|
915
|
+
useVaultSelector((state) => page.id ? state.iiif.entities.AnnotationPage[page.id] : null, []);
|
|
916
|
+
return /* @__PURE__ */ jsx(Fragment$1, {
|
|
917
|
+
children: (_a = page.items) == null ? void 0 : _a.map((annotation) => {
|
|
918
|
+
return /* @__PURE__ */ jsx(RenderAnnotation, {
|
|
919
|
+
id: annotation.id,
|
|
920
|
+
style,
|
|
921
|
+
className: (html == null ? void 0 : html.className) || className
|
|
922
|
+
}, annotation.id);
|
|
923
|
+
})
|
|
924
|
+
});
|
|
925
|
+
};
|
|
926
|
+
function RenderImage({
|
|
927
|
+
id,
|
|
928
|
+
image,
|
|
929
|
+
thumbnail,
|
|
930
|
+
isStatic,
|
|
931
|
+
x = 0,
|
|
932
|
+
y = 0,
|
|
933
|
+
annotations,
|
|
934
|
+
children
|
|
935
|
+
}) {
|
|
936
|
+
var _a, _b, _c, _d;
|
|
937
|
+
return /* @__PURE__ */ jsx(Fragment$1, {
|
|
938
|
+
children: !image.service ? /* @__PURE__ */ jsxs(Fragment$1, {
|
|
939
|
+
children: [/* @__PURE__ */ jsx("world-image", {
|
|
940
|
+
uri: image.id,
|
|
941
|
+
target: image.target.spatial,
|
|
942
|
+
display: image.width && image.height ? {
|
|
943
|
+
width: image.width,
|
|
944
|
+
height: image.height
|
|
945
|
+
} : void 0
|
|
946
|
+
}), annotations, children]
|
|
947
|
+
}, "no-service") : /* @__PURE__ */ jsxs(Fragment$1, {
|
|
948
|
+
children: [/* @__PURE__ */ jsx(TileSet, {
|
|
949
|
+
tiles: {
|
|
950
|
+
id: image.service.id || image.service["@id"] || "unknown",
|
|
951
|
+
height: image.height,
|
|
952
|
+
width: image.width,
|
|
953
|
+
imageService: image.service,
|
|
954
|
+
thumbnail: thumbnail && thumbnail.type === "fixed" ? thumbnail : void 0
|
|
955
|
+
},
|
|
956
|
+
x: ((_a = image.target) == null ? void 0 : _a.spatial.x) + x,
|
|
957
|
+
y: ((_b = image.target) == null ? void 0 : _b.spatial.y) + y,
|
|
958
|
+
width: (_c = image.target) == null ? void 0 : _c.spatial.width,
|
|
959
|
+
height: (_d = image.target) == null ? void 0 : _d.spatial.height
|
|
960
|
+
}), annotations, children]
|
|
961
|
+
}, "service")
|
|
962
|
+
}, id);
|
|
963
|
+
}
|
|
964
|
+
function parseSpecificResource(resource) {
|
|
965
|
+
if (resource.type === "SpecificResource") {
|
|
966
|
+
return [resource.source, { selector: resource.selector }];
|
|
967
|
+
}
|
|
968
|
+
return [resource, { selector: null }];
|
|
969
|
+
}
|
|
970
|
+
function getPaintables(vault, paintingAnnotations, enabledChoices) {
|
|
971
|
+
const types = [];
|
|
972
|
+
let choice = null;
|
|
973
|
+
const items = [];
|
|
974
|
+
for (const annotation of paintingAnnotations) {
|
|
975
|
+
const bodies = vault.get(annotation.body);
|
|
976
|
+
for (const unknownBody of bodies) {
|
|
977
|
+
const [body, { selector }] = parseSpecificResource(unknownBody);
|
|
978
|
+
const type = (body.type || "unknown").toLowerCase();
|
|
979
|
+
if (type === "choice") {
|
|
980
|
+
const nestedBodies = vault.get(body.items);
|
|
981
|
+
const selected = enabledChoices.length ? enabledChoices.map((cid) => nestedBodies.find((b) => b.id === cid)).filter(Boolean) : [nestedBodies[0]];
|
|
982
|
+
if (selected.length === 0) {
|
|
983
|
+
selected.push(nestedBodies[0]);
|
|
984
|
+
}
|
|
985
|
+
choice = {
|
|
986
|
+
type: "single-choice",
|
|
987
|
+
items: nestedBodies.map((b) => ({
|
|
988
|
+
id: b.id,
|
|
989
|
+
label: b.label,
|
|
990
|
+
selected: selected.indexOf(b) !== -1
|
|
991
|
+
})),
|
|
992
|
+
label: unknownBody.label
|
|
993
|
+
};
|
|
994
|
+
bodies.push(...selected);
|
|
995
|
+
continue;
|
|
996
|
+
}
|
|
997
|
+
if (types.indexOf(type) === -1) {
|
|
998
|
+
types.push(type);
|
|
999
|
+
}
|
|
1000
|
+
items.push({
|
|
1001
|
+
type,
|
|
1002
|
+
resource: body,
|
|
1003
|
+
target: annotation.target,
|
|
1004
|
+
selector
|
|
1005
|
+
});
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
return {
|
|
1009
|
+
types,
|
|
1010
|
+
items,
|
|
1011
|
+
choice
|
|
1012
|
+
};
|
|
1013
|
+
}
|
|
1014
|
+
const emptyActions = {
|
|
1015
|
+
makeChoice: () => {
|
|
1016
|
+
}
|
|
1017
|
+
};
|
|
1018
|
+
const unknownResponse = { type: "unknown" };
|
|
1019
|
+
const unsupportedStrategy = (reason) => {
|
|
1020
|
+
return { type: "unknown", reason, annotations: { pages: [] } };
|
|
1021
|
+
};
|
|
1022
|
+
function useManifest(options = {}, deps = []) {
|
|
1023
|
+
const { id, selector } = options;
|
|
1024
|
+
const ctx = useResourceContext();
|
|
1025
|
+
useVault();
|
|
1026
|
+
const manifestId = id ? id : ctx.manifest;
|
|
1027
|
+
const manifest = useVaultSelector((s) => manifestId ? s.iiif.entities.Manifest[manifestId] : void 0, [manifestId]);
|
|
1028
|
+
return useMemo(() => {
|
|
1029
|
+
if (!manifest) {
|
|
1030
|
+
return void 0;
|
|
1031
|
+
}
|
|
1032
|
+
if (selector) {
|
|
1033
|
+
return selector(manifest);
|
|
1034
|
+
}
|
|
1035
|
+
return manifest;
|
|
1036
|
+
}, [manifest, selector, ...deps]);
|
|
1037
|
+
}
|
|
1038
|
+
function getMeta$1(state, resourceId) {
|
|
1039
|
+
var _a;
|
|
1040
|
+
const resourceMeta = (_a = state == null ? void 0 : state.iiif) == null ? void 0 : _a.meta[resourceId];
|
|
1041
|
+
if (!resourceMeta) {
|
|
1042
|
+
return null;
|
|
1043
|
+
}
|
|
1044
|
+
return resourceMeta.annotationPageManager;
|
|
1045
|
+
}
|
|
1046
|
+
function useEnabledAnnotationPageIds(resourceId, availablePageIds) {
|
|
1047
|
+
return useVaultSelector((state) => {
|
|
1048
|
+
const pageIds = [];
|
|
1049
|
+
if (!resourceId) {
|
|
1050
|
+
return pageIds;
|
|
1051
|
+
}
|
|
1052
|
+
const allAnnotationListIds = Object.keys(state.iiif.entities.AnnotationPage);
|
|
1053
|
+
for (const annotationListId of allAnnotationListIds) {
|
|
1054
|
+
if (!availablePageIds || availablePageIds.indexOf(annotationListId) !== -1) {
|
|
1055
|
+
const annotationListMeta = getMeta$1(state, annotationListId);
|
|
1056
|
+
if (annotationListMeta && annotationListMeta.views && annotationListMeta.views[resourceId]) {
|
|
1057
|
+
pageIds.push(annotationListId);
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
return pageIds;
|
|
1062
|
+
}, [resourceId, availablePageIds]);
|
|
1063
|
+
}
|
|
1064
|
+
function flattenAnnotationPageIds({
|
|
1065
|
+
canvas,
|
|
1066
|
+
manifest,
|
|
1067
|
+
all,
|
|
1068
|
+
canvases
|
|
1069
|
+
}) {
|
|
1070
|
+
const foundIds = [];
|
|
1071
|
+
if (manifest) {
|
|
1072
|
+
for (const page of manifest.annotations) {
|
|
1073
|
+
if (foundIds.indexOf(page.id) === -1) {
|
|
1074
|
+
foundIds.push(page.id);
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
if (all) {
|
|
1079
|
+
if (canvases && canvases.length) {
|
|
1080
|
+
for (const canvas_ of canvases) {
|
|
1081
|
+
for (const page of canvas_.annotations) {
|
|
1082
|
+
if (foundIds.indexOf(page.id) === -1) {
|
|
1083
|
+
foundIds.push(page.id);
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
} else if (canvas) {
|
|
1089
|
+
for (const page of canvas.annotations) {
|
|
1090
|
+
if (foundIds.indexOf(page.id) === -1) {
|
|
1091
|
+
foundIds.push(page.id);
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
return foundIds;
|
|
1096
|
+
}
|
|
1097
|
+
function getMeta(state, resourceId) {
|
|
1098
|
+
var _a;
|
|
1099
|
+
const resourceMeta = (_a = state == null ? void 0 : state.iiif) == null ? void 0 : _a.meta[resourceId];
|
|
1100
|
+
if (!resourceMeta) {
|
|
1101
|
+
return null;
|
|
1102
|
+
}
|
|
1103
|
+
return resourceMeta.annotationPageManager;
|
|
1104
|
+
}
|
|
1105
|
+
function useAnnotationPageManager(resourceId, options = {}) {
|
|
1106
|
+
const vault = useVault();
|
|
1107
|
+
const manifest = useManifest();
|
|
1108
|
+
const canvas = useCanvas();
|
|
1109
|
+
const canvases = useVisibleCanvases();
|
|
1110
|
+
const availablePageIds = useMemo(() => {
|
|
1111
|
+
return flattenAnnotationPageIds({
|
|
1112
|
+
all: options.all,
|
|
1113
|
+
manifest,
|
|
1114
|
+
canvas,
|
|
1115
|
+
canvases
|
|
1116
|
+
});
|
|
1117
|
+
}, [options.all, canvas, canvases, manifest]);
|
|
1118
|
+
const enabledPageIds = useEnabledAnnotationPageIds(resourceId, options.all ? void 0 : availablePageIds);
|
|
1119
|
+
const setPageDisabled = useCallback((deselectId) => {
|
|
1120
|
+
if (!resourceId) {
|
|
1121
|
+
return;
|
|
1122
|
+
}
|
|
1123
|
+
vault.setMetaValue([deselectId, "annotationPageManager", "views"], (existingResources) => {
|
|
1124
|
+
if (existingResources && !existingResources[resourceId]) {
|
|
1125
|
+
return existingResources;
|
|
1126
|
+
}
|
|
1127
|
+
return __spreadProps(__spreadValues({}, existingResources || {}), {
|
|
1128
|
+
[resourceId]: false
|
|
1129
|
+
});
|
|
1130
|
+
});
|
|
1131
|
+
}, [resourceId, vault]);
|
|
1132
|
+
const setPageEnabled = useCallback((id, opt = {}) => {
|
|
1133
|
+
if (!resourceId) {
|
|
1134
|
+
return;
|
|
1135
|
+
}
|
|
1136
|
+
const state = vault.getState();
|
|
1137
|
+
const toDeselect = [];
|
|
1138
|
+
if (opt == null ? void 0 : opt.deselectOthers) {
|
|
1139
|
+
const allAnnotationListIds = Object.keys(state.iiif.entities.AnnotationPage);
|
|
1140
|
+
for (const annotationPageId of allAnnotationListIds) {
|
|
1141
|
+
const annotationListMeta = getMeta(state, annotationPageId);
|
|
1142
|
+
if (annotationListMeta && annotationListMeta.views && annotationListMeta.views[resourceId]) {
|
|
1143
|
+
toDeselect.push(annotationPageId);
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
for (const deselectId of toDeselect) {
|
|
1148
|
+
setPageDisabled(deselectId);
|
|
1149
|
+
}
|
|
1150
|
+
vault.setMetaValue([id, "annotationPageManager", "views"], (existingResources) => {
|
|
1151
|
+
if (existingResources && existingResources[resourceId]) {
|
|
1152
|
+
return existingResources;
|
|
1153
|
+
}
|
|
1154
|
+
return __spreadProps(__spreadValues({}, existingResources || {}), {
|
|
1155
|
+
[resourceId]: true
|
|
1156
|
+
});
|
|
1157
|
+
});
|
|
1158
|
+
}, [resourceId, setPageDisabled, vault]);
|
|
1159
|
+
return {
|
|
1160
|
+
availablePageIds,
|
|
1161
|
+
enabledPageIds,
|
|
1162
|
+
setPageEnabled,
|
|
1163
|
+
setPageDisabled
|
|
1164
|
+
};
|
|
1165
|
+
}
|
|
1166
|
+
function useResources(ids, type) {
|
|
1167
|
+
return useVaultSelector((state, vault) => vault.get(ids.map((id) => ({ id, type }))), [ids, type]);
|
|
1168
|
+
}
|
|
1169
|
+
const ImageServiceLoaderContext = React__default.createContext(new ImageServiceLoader());
|
|
1170
|
+
function useImageServiceLoader() {
|
|
1171
|
+
return useContext(ImageServiceLoaderContext);
|
|
1172
|
+
}
|
|
1173
|
+
function useLoadImageService() {
|
|
1174
|
+
const loader = useImageServiceLoader();
|
|
1175
|
+
const [imageServiceStatus, setImageServiceStatus] = useState({});
|
|
1176
|
+
const didUnmount = useRef(false);
|
|
1177
|
+
useEffect(() => {
|
|
1178
|
+
return () => {
|
|
1179
|
+
didUnmount.current = true;
|
|
1180
|
+
};
|
|
1181
|
+
}, []);
|
|
1182
|
+
const loadImageService = useCallback((imageService, { height, width }) => {
|
|
1183
|
+
if (imageService) {
|
|
1184
|
+
const imageServiceId = imageService.id || imageService["@id"];
|
|
1185
|
+
const syncLoaded = loader.loadServiceSync({
|
|
1186
|
+
id: imageServiceId,
|
|
1187
|
+
width: imageService.width || width,
|
|
1188
|
+
height: imageService.height || height,
|
|
1189
|
+
source: imageService
|
|
1190
|
+
});
|
|
1191
|
+
if (syncLoaded) {
|
|
1192
|
+
imageService = syncLoaded;
|
|
1193
|
+
} else if (!imageServiceStatus[imageServiceId]) {
|
|
1194
|
+
if (!didUnmount.current) {
|
|
1195
|
+
setImageServiceStatus((r) => {
|
|
1196
|
+
return __spreadProps(__spreadValues({}, r), {
|
|
1197
|
+
[imageServiceId]: "loading"
|
|
1198
|
+
});
|
|
1199
|
+
});
|
|
1200
|
+
}
|
|
1201
|
+
loader.loadService({
|
|
1202
|
+
id: imageServiceId,
|
|
1203
|
+
width: imageService.width || width,
|
|
1204
|
+
height: imageService.height || height
|
|
1205
|
+
}).then(() => {
|
|
1206
|
+
if (!didUnmount.current) {
|
|
1207
|
+
setImageServiceStatus((r) => {
|
|
1208
|
+
return __spreadProps(__spreadValues({}, r), {
|
|
1209
|
+
[imageServiceId]: "done"
|
|
1210
|
+
});
|
|
1211
|
+
});
|
|
1212
|
+
}
|
|
1213
|
+
});
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
return imageService;
|
|
1217
|
+
}, [loader, imageServiceStatus]);
|
|
1218
|
+
return [loadImageService, imageServiceStatus];
|
|
1219
|
+
}
|
|
1220
|
+
function usePaintingAnnotations(options = {}) {
|
|
1221
|
+
const canvas = useCanvas(options.canvasId ? { id: options.canvasId } : void 0);
|
|
1222
|
+
return useVaultSelector((state, vault) => {
|
|
1223
|
+
if (!canvas) {
|
|
1224
|
+
return [];
|
|
1225
|
+
}
|
|
1226
|
+
const annotationPages = vault.get(canvas.items);
|
|
1227
|
+
const flatAnnotations = [];
|
|
1228
|
+
for (const page of annotationPages) {
|
|
1229
|
+
flatAnnotations.push(...vault.get(page.items));
|
|
1230
|
+
}
|
|
1231
|
+
return flatAnnotations;
|
|
1232
|
+
}, [canvas]);
|
|
1233
|
+
}
|
|
1234
|
+
function usePaintables(options, deps = []) {
|
|
1235
|
+
const vault = useVault();
|
|
1236
|
+
const paintingAnnotations = usePaintingAnnotations();
|
|
1237
|
+
const [enabledChoices, setEnabledChoices] = useState((options == null ? void 0 : options.defaultChoices) || []);
|
|
1238
|
+
const paintables = useMemo(() => getPaintables(vault, paintingAnnotations, enabledChoices), [vault, paintingAnnotations, enabledChoices, ...deps]);
|
|
1239
|
+
const makeChoice = useCallback((id, { deselectOthers = true, deselect = false } = {}) => {
|
|
1240
|
+
if (paintables.choice) {
|
|
1241
|
+
if (paintables.choice.type !== "single-choice") {
|
|
1242
|
+
throw new Error("Complex choice not supported yet");
|
|
1243
|
+
}
|
|
1244
|
+
setEnabledChoices((prevChoices) => {
|
|
1245
|
+
if (deselect) {
|
|
1246
|
+
const without = prevChoices.filter((e) => e !== id);
|
|
1247
|
+
if (without.length === 0) {
|
|
1248
|
+
const defaultId = paintables.items[0].resource.id;
|
|
1249
|
+
if (defaultId) {
|
|
1250
|
+
return [defaultId];
|
|
1251
|
+
} else {
|
|
1252
|
+
return [];
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
return without;
|
|
1256
|
+
}
|
|
1257
|
+
if (deselectOthers) {
|
|
1258
|
+
return [id];
|
|
1259
|
+
}
|
|
1260
|
+
const newChoices = [...prevChoices];
|
|
1261
|
+
if (newChoices.length === 0 && paintables.items.length) {
|
|
1262
|
+
const defaultId = paintables.items[0].resource.id;
|
|
1263
|
+
if (defaultId) {
|
|
1264
|
+
newChoices.push(defaultId);
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
if (prevChoices.indexOf(id) !== -1) {
|
|
1268
|
+
return prevChoices;
|
|
1269
|
+
}
|
|
1270
|
+
return [...prevChoices, id];
|
|
1271
|
+
});
|
|
1272
|
+
}
|
|
1273
|
+
}, [paintables.choice]);
|
|
1274
|
+
const actions = { makeChoice };
|
|
1275
|
+
return [paintables, actions];
|
|
1276
|
+
}
|
|
1277
|
+
function getImageStrategy(canvas, paintables, loadImageService) {
|
|
1278
|
+
const imageTypes = [];
|
|
1279
|
+
for (const singleImage of paintables.items) {
|
|
1280
|
+
const resource = singleImage.resource && singleImage.resource.type === "SpecificResource" ? singleImage.resource.source : singleImage.resource;
|
|
1281
|
+
if (!resource.id) {
|
|
1282
|
+
return unsupportedStrategy("No resource Identifier");
|
|
1283
|
+
}
|
|
1284
|
+
let imageService = void 0;
|
|
1285
|
+
if (resource.service) {
|
|
1286
|
+
const imageServices = getImageServices(resource);
|
|
1287
|
+
if (imageServices[0]) {
|
|
1288
|
+
imageService = loadImageService(imageServices[0], canvas);
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
const { selector: imageTarget, source } = expandTarget(singleImage.target);
|
|
1292
|
+
if (source.id !== canvas.id) {
|
|
1293
|
+
continue;
|
|
1294
|
+
}
|
|
1295
|
+
const defaultTarget = {
|
|
1296
|
+
type: "BoxSelector",
|
|
1297
|
+
spatial: {
|
|
1298
|
+
x: 0,
|
|
1299
|
+
y: 0,
|
|
1300
|
+
width: canvas.width,
|
|
1301
|
+
height: canvas.height
|
|
1302
|
+
}
|
|
1303
|
+
};
|
|
1304
|
+
const target = imageTarget ? imageTarget.type === "TemporalSelector" ? {
|
|
1305
|
+
type: "TemporalBoxSelector",
|
|
1306
|
+
temporal: imageTarget.temporal,
|
|
1307
|
+
spatial: defaultTarget.spatial
|
|
1308
|
+
} : imageTarget : null;
|
|
1309
|
+
const defaultImageSelector = {
|
|
1310
|
+
type: "BoxSelector",
|
|
1311
|
+
spatial: {
|
|
1312
|
+
x: 0,
|
|
1313
|
+
y: 0,
|
|
1314
|
+
width: canvas.width,
|
|
1315
|
+
height: canvas.height
|
|
1316
|
+
}
|
|
1317
|
+
};
|
|
1318
|
+
const imageSelector = singleImage.resource.type === "SpecificResource" ? expandTarget(singleImage.resource) : null;
|
|
1319
|
+
const selector = imageSelector && imageSelector.selector && (imageSelector.selector.type === "BoxSelector" || imageSelector.selector.type === "TemporalBoxSelector") ? {
|
|
1320
|
+
type: "BoxSelector",
|
|
1321
|
+
spatial: {
|
|
1322
|
+
x: imageSelector.selector.spatial.x,
|
|
1323
|
+
y: imageSelector.selector.spatial.y,
|
|
1324
|
+
width: imageSelector.selector.spatial.width,
|
|
1325
|
+
height: imageSelector.selector.spatial.height
|
|
1326
|
+
}
|
|
1327
|
+
} : defaultImageSelector;
|
|
1328
|
+
if (imageService && !imageService.id) {
|
|
1329
|
+
imageService.id = imageService["@id"];
|
|
1330
|
+
}
|
|
1331
|
+
const imageType = {
|
|
1332
|
+
id: resource.id,
|
|
1333
|
+
type: "Image",
|
|
1334
|
+
width: target ? resource.width : canvas.width,
|
|
1335
|
+
height: target ? resource.height : canvas.height,
|
|
1336
|
+
service: imageService,
|
|
1337
|
+
sizes: imageService && imageService.sizes ? imageService.sizes : resource.width && resource.height ? [{ width: resource.width, height: resource.height }] : [],
|
|
1338
|
+
target: target && target.type !== "PointSelector" ? target : defaultTarget,
|
|
1339
|
+
selector
|
|
1340
|
+
};
|
|
1341
|
+
imageTypes.push(imageType);
|
|
1342
|
+
}
|
|
1343
|
+
return {
|
|
1344
|
+
type: "images",
|
|
1345
|
+
image: imageTypes[0],
|
|
1346
|
+
images: imageTypes,
|
|
1347
|
+
choice: paintables.choice
|
|
1348
|
+
};
|
|
1349
|
+
}
|
|
1350
|
+
const supportedFormats = ["model/gltf-binary"];
|
|
1351
|
+
function get3dStrategy(canvas, paintables) {
|
|
1352
|
+
const first = paintables.items[0];
|
|
1353
|
+
const resource = first.resource;
|
|
1354
|
+
if (!resource.format) {
|
|
1355
|
+
return unsupportedStrategy("Unknown format");
|
|
1356
|
+
}
|
|
1357
|
+
if (supportedFormats.indexOf(resource.format) === -1) {
|
|
1358
|
+
return unsupportedStrategy(`3D format: ${resource.format} is unsupported`);
|
|
1359
|
+
}
|
|
1360
|
+
return {
|
|
1361
|
+
type: "3d-model",
|
|
1362
|
+
model: resource
|
|
1363
|
+
};
|
|
1364
|
+
}
|
|
1365
|
+
function getAudioStrategy(canvas, paintables) {
|
|
1366
|
+
var _a;
|
|
1367
|
+
if (!canvas.duration) {
|
|
1368
|
+
return unsupportedStrategy("No duration on canvas");
|
|
1369
|
+
}
|
|
1370
|
+
if (paintables.items.length > 1) {
|
|
1371
|
+
return unsupportedStrategy("Only one audio source supported");
|
|
1372
|
+
}
|
|
1373
|
+
const audioResource = (_a = paintables.items[0]) == null ? void 0 : _a.resource;
|
|
1374
|
+
if (!audioResource) {
|
|
1375
|
+
return unsupportedStrategy("Unknown audio");
|
|
1376
|
+
}
|
|
1377
|
+
if (!audioResource.format) {
|
|
1378
|
+
return unsupportedStrategy("Audio does not have format");
|
|
1379
|
+
}
|
|
1380
|
+
return {
|
|
1381
|
+
type: "media",
|
|
1382
|
+
media: {
|
|
1383
|
+
duration: canvas.duration,
|
|
1384
|
+
url: audioResource.id,
|
|
1385
|
+
type: "Sound",
|
|
1386
|
+
target: {
|
|
1387
|
+
type: "TemporalSelector",
|
|
1388
|
+
temporal: {
|
|
1389
|
+
startTime: 0,
|
|
1390
|
+
endTime: canvas.duration
|
|
1391
|
+
}
|
|
1392
|
+
},
|
|
1393
|
+
format: audioResource.format,
|
|
1394
|
+
selector: {
|
|
1395
|
+
type: "TemporalSelector",
|
|
1396
|
+
temporal: {
|
|
1397
|
+
startTime: 0,
|
|
1398
|
+
endTime: canvas.duration
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
},
|
|
1402
|
+
annotations: {
|
|
1403
|
+
pages: []
|
|
1404
|
+
}
|
|
1405
|
+
};
|
|
1406
|
+
}
|
|
1407
|
+
function getVideoStrategy(canvas, paintables) {
|
|
1408
|
+
var _a;
|
|
1409
|
+
const videoPaintables = paintables.items.filter((t) => t.type === "video");
|
|
1410
|
+
if (!canvas.duration) {
|
|
1411
|
+
return unsupportedStrategy("No duration on canvas");
|
|
1412
|
+
}
|
|
1413
|
+
if (videoPaintables.length > 1) {
|
|
1414
|
+
return unsupportedStrategy("Only one video source supported");
|
|
1415
|
+
}
|
|
1416
|
+
const audioResource = (_a = videoPaintables[0]) == null ? void 0 : _a.resource;
|
|
1417
|
+
if (!audioResource) {
|
|
1418
|
+
return unsupportedStrategy("Unknown video");
|
|
1419
|
+
}
|
|
1420
|
+
if (!audioResource.format) {
|
|
1421
|
+
return unsupportedStrategy("Video does not have format");
|
|
1422
|
+
}
|
|
1423
|
+
return {
|
|
1424
|
+
type: "media",
|
|
1425
|
+
media: {
|
|
1426
|
+
duration: canvas.duration,
|
|
1427
|
+
url: audioResource.id,
|
|
1428
|
+
type: "Video",
|
|
1429
|
+
items: [],
|
|
1430
|
+
target: {
|
|
1431
|
+
type: "TemporalSelector",
|
|
1432
|
+
temporal: {
|
|
1433
|
+
startTime: 0,
|
|
1434
|
+
endTime: canvas.duration
|
|
1435
|
+
}
|
|
1436
|
+
},
|
|
1437
|
+
format: audioResource.format,
|
|
1438
|
+
selector: {
|
|
1439
|
+
type: "TemporalSelector",
|
|
1440
|
+
temporal: {
|
|
1441
|
+
startTime: 0,
|
|
1442
|
+
endTime: canvas.duration
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
},
|
|
1446
|
+
annotations: {
|
|
1447
|
+
pages: []
|
|
1448
|
+
}
|
|
1449
|
+
};
|
|
1450
|
+
}
|
|
1451
|
+
function useRenderingStrategy(options) {
|
|
1452
|
+
const manifest = useManifest();
|
|
1453
|
+
const canvas = useCanvas();
|
|
1454
|
+
const vault = useVault();
|
|
1455
|
+
const [loadImageService, imageServiceStatus] = useLoadImageService();
|
|
1456
|
+
const { enabledPageIds } = useAnnotationPageManager((options == null ? void 0 : options.annotationPageManagerId) || (manifest == null ? void 0 : manifest.id) || (canvas == null ? void 0 : canvas.id), {
|
|
1457
|
+
all: false
|
|
1458
|
+
});
|
|
1459
|
+
const enabledPages = useResources(enabledPageIds, "AnnotationPage");
|
|
1460
|
+
const supports = (options == null ? void 0 : options.strategies) || ["images", "media", "complex-timeline"];
|
|
1461
|
+
const [paintables, actions] = usePaintables(options, [imageServiceStatus]);
|
|
1462
|
+
const strategy = useMemo(() => {
|
|
1463
|
+
if (!canvas || paintables.types.length === 0) {
|
|
1464
|
+
return unknownResponse;
|
|
1465
|
+
}
|
|
1466
|
+
if (paintables.types.length !== 1) {
|
|
1467
|
+
if (paintables.types.length === 2 && paintables.types.indexOf("text") !== -1) {
|
|
1468
|
+
paintables.types = paintables.types.filter((t) => t !== "text");
|
|
1469
|
+
} else {
|
|
1470
|
+
if (supports.indexOf("complex-timeline") === -1) {
|
|
1471
|
+
return unsupportedStrategy("Complex timeline not supported");
|
|
1472
|
+
}
|
|
1473
|
+
return unsupportedStrategy("ComplexTimelineStrategy not yet supported");
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
const mainType = paintables.types[0];
|
|
1477
|
+
if (mainType === "image") {
|
|
1478
|
+
if (supports.indexOf("images") === -1) {
|
|
1479
|
+
return unsupportedStrategy("Image not supported");
|
|
1480
|
+
}
|
|
1481
|
+
return getImageStrategy(canvas, paintables, loadImageService);
|
|
1482
|
+
}
|
|
1483
|
+
if (mainType === "Model" || mainType === "model") {
|
|
1484
|
+
if (supports.indexOf("3d-model") === -1) {
|
|
1485
|
+
return unsupportedStrategy("3D not supported");
|
|
1486
|
+
}
|
|
1487
|
+
return get3dStrategy(canvas, paintables);
|
|
1488
|
+
}
|
|
1489
|
+
if (mainType === "sound" || mainType === "audio") {
|
|
1490
|
+
if (supports.indexOf("media") === -1) {
|
|
1491
|
+
return unsupportedStrategy("Media not supported");
|
|
1492
|
+
}
|
|
1493
|
+
return getAudioStrategy(canvas, paintables);
|
|
1494
|
+
}
|
|
1495
|
+
if (mainType === "video") {
|
|
1496
|
+
if (supports.indexOf("media") === -1) {
|
|
1497
|
+
return unsupportedStrategy("Media not supported");
|
|
1498
|
+
}
|
|
1499
|
+
return getVideoStrategy(canvas, paintables);
|
|
1500
|
+
}
|
|
1501
|
+
return unknownResponse;
|
|
1502
|
+
}, [canvas, paintables, vault, actions.makeChoice]);
|
|
1503
|
+
return useMemo(() => {
|
|
1504
|
+
if (strategy.type === "unknown") {
|
|
1505
|
+
return [strategy, emptyActions];
|
|
1506
|
+
}
|
|
1507
|
+
return [
|
|
1508
|
+
__spreadProps(__spreadValues({}, strategy), {
|
|
1509
|
+
annotations: { pages: enabledPages }
|
|
1510
|
+
}),
|
|
1511
|
+
actions
|
|
1512
|
+
];
|
|
1513
|
+
}, [strategy, enabledPages]);
|
|
1514
|
+
}
|
|
1515
|
+
const useVaultEffect = (callback, deps = []) => {
|
|
1516
|
+
const vault = useVault();
|
|
1517
|
+
useEffect(() => {
|
|
1518
|
+
callback(vault);
|
|
1519
|
+
}, [vault, ...deps]);
|
|
1520
|
+
};
|
|
1521
|
+
function createThumbnailHelper(vault, dependencies = {}) {
|
|
1522
|
+
const imageServiceLoader = dependencies.imageServiceLoader || new ImageServiceLoader();
|
|
1523
|
+
async function getBestThumbnailAtSize(input, request, dereference, candidates = [], dimensions) {
|
|
1524
|
+
if (typeof input === "string") {
|
|
1525
|
+
return { best: getFixedSizeFromImage(input), fallback: [], log: [] };
|
|
1526
|
+
}
|
|
1527
|
+
const fullInput = vault.get(input);
|
|
1528
|
+
if (typeof fullInput === "string") {
|
|
1529
|
+
return { best: getFixedSizeFromImage(fullInput), fallback: [], log: [] };
|
|
1530
|
+
}
|
|
1531
|
+
switch (fullInput.type) {
|
|
1532
|
+
case "Annotation": {
|
|
1533
|
+
const contentResources = fullInput.body;
|
|
1534
|
+
const firstContentResources = vault.get(contentResources[0]);
|
|
1535
|
+
if (dimensions && !firstContentResources.width) {
|
|
1536
|
+
firstContentResources.width = dimensions.width;
|
|
1537
|
+
firstContentResources.height = dimensions.height;
|
|
1538
|
+
}
|
|
1539
|
+
return await imageServiceLoader.getThumbnailFromResource(firstContentResources, request, dereference, candidates);
|
|
1540
|
+
}
|
|
1541
|
+
case "Canvas": {
|
|
1542
|
+
const canvas = fullInput;
|
|
1543
|
+
if (canvas.thumbnail && canvas.thumbnail.length) {
|
|
1544
|
+
const thumbnail = vault.get(canvas.thumbnail[0]);
|
|
1545
|
+
const potentialThumbnails = await imageServiceLoader.getImageCandidates(thumbnail, dereference);
|
|
1546
|
+
if (potentialThumbnails && potentialThumbnails.length) {
|
|
1547
|
+
candidates.push(...potentialThumbnails);
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
return getBestThumbnailAtSize(canvas.items[0], request, dereference, candidates, {
|
|
1551
|
+
width: canvas.width,
|
|
1552
|
+
height: canvas.height
|
|
1553
|
+
});
|
|
1554
|
+
}
|
|
1555
|
+
case "AnnotationPage": {
|
|
1556
|
+
const annotationPage = fullInput;
|
|
1557
|
+
return getBestThumbnailAtSize(annotationPage.items[0], request, dereference, candidates, dimensions);
|
|
1558
|
+
}
|
|
1559
|
+
case "Choice": {
|
|
1560
|
+
const choice = fullInput;
|
|
1561
|
+
return getBestThumbnailAtSize(choice.items[0], request, dereference, candidates, dimensions);
|
|
1562
|
+
}
|
|
1563
|
+
case "Collection": {
|
|
1564
|
+
const collection = fullInput;
|
|
1565
|
+
const firstManifest = collection.items[0];
|
|
1566
|
+
return getBestThumbnailAtSize(firstManifest, request, dereference, candidates, dimensions);
|
|
1567
|
+
}
|
|
1568
|
+
case "Manifest": {
|
|
1569
|
+
const manifest = fullInput;
|
|
1570
|
+
const firstCanvas = manifest.items[0];
|
|
1571
|
+
return getBestThumbnailAtSize(firstCanvas, request, dereference, candidates, dimensions);
|
|
1572
|
+
}
|
|
1573
|
+
case "SpecificResource":
|
|
1574
|
+
case "Image":
|
|
1575
|
+
case "Dataset":
|
|
1576
|
+
case "Sound":
|
|
1577
|
+
case "Text":
|
|
1578
|
+
case "TextualBody":
|
|
1579
|
+
case "Video":
|
|
1580
|
+
if (dimensions && !fullInput.width) {
|
|
1581
|
+
fullInput.width = dimensions.width;
|
|
1582
|
+
fullInput.height = dimensions.height;
|
|
1583
|
+
}
|
|
1584
|
+
return imageServiceLoader.getThumbnailFromResource(fullInput, request, dereference, candidates);
|
|
1585
|
+
case "Service":
|
|
1586
|
+
case "Range":
|
|
1587
|
+
case "AnnotationCollection":
|
|
1588
|
+
case "CanvasReference":
|
|
1589
|
+
case "ContentResource":
|
|
1590
|
+
return { best: void 0, fallback: [], log: [] };
|
|
1591
|
+
}
|
|
1592
|
+
return { best: void 0, fallback: [], log: [] };
|
|
1593
|
+
}
|
|
1594
|
+
return {
|
|
1595
|
+
getBestThumbnailAtSize
|
|
1596
|
+
};
|
|
1597
|
+
}
|
|
1598
|
+
function useThumbnail(request, dereference, { canvasId, manifestId } = {}) {
|
|
1599
|
+
const vault = useVault();
|
|
1600
|
+
const loader = useImageServiceLoader();
|
|
1601
|
+
const helper = useMemo(() => createThumbnailHelper(vault, { imageServiceLoader: loader }), [vault, loader]);
|
|
1602
|
+
const [thumbnail, setThumbnail] = useState();
|
|
1603
|
+
const manifest = useManifest(manifestId ? { id: manifestId } : void 0);
|
|
1604
|
+
const canvas = useCanvas(canvasId ? { id: canvasId } : void 0);
|
|
1605
|
+
const subject = canvas ? canvas : manifest;
|
|
1606
|
+
const didUnmount = useRef(false);
|
|
1607
|
+
useEffect(() => {
|
|
1608
|
+
return () => {
|
|
1609
|
+
didUnmount.current = true;
|
|
1610
|
+
};
|
|
1611
|
+
}, []);
|
|
1612
|
+
if (!subject) {
|
|
1613
|
+
throw new Error("Must be called under a manifest or canvas context.");
|
|
1614
|
+
}
|
|
1615
|
+
useVaultEffect((v) => {
|
|
1616
|
+
helper.getBestThumbnailAtSize(subject, request, dereference).then((thumb) => {
|
|
1617
|
+
if (thumb.best && !didUnmount.current) {
|
|
1618
|
+
setThumbnail(thumb.best);
|
|
1619
|
+
}
|
|
1620
|
+
});
|
|
1621
|
+
}, [subject]);
|
|
1622
|
+
return thumbnail;
|
|
1623
|
+
}
|
|
1624
|
+
function getDefaultState(duration) {
|
|
1625
|
+
return { isMuted: false, playRequested: false, isPlaying: false, isFinished: false, volume: 100, duration };
|
|
1626
|
+
}
|
|
1627
|
+
function reducer(state, action) {
|
|
1628
|
+
switch (action.type) {
|
|
1629
|
+
case "FINISHED":
|
|
1630
|
+
return __spreadProps(__spreadValues({}, state), { isFinished: true, isPlaying: false, playRequested: false });
|
|
1631
|
+
case "PLAY_PAUSE":
|
|
1632
|
+
return __spreadProps(__spreadValues({}, state), { isFinished: false, isPlaying: !state.isPlaying });
|
|
1633
|
+
case "PLAY_REQUESTED":
|
|
1634
|
+
return __spreadProps(__spreadValues({}, state), { isFinished: false, playRequested: true });
|
|
1635
|
+
case "PAUSE":
|
|
1636
|
+
return __spreadProps(__spreadValues({}, state), { isPlaying: false });
|
|
1637
|
+
case "PLAY":
|
|
1638
|
+
return __spreadProps(__spreadValues({}, state), { isFinished: false, playRequested: false, isPlaying: true });
|
|
1639
|
+
case "MUTE":
|
|
1640
|
+
return __spreadProps(__spreadValues({}, state), { isMuted: true });
|
|
1641
|
+
case "SET_VOLUME":
|
|
1642
|
+
return __spreadProps(__spreadValues({}, state), { volume: action.volume, isMuted: action.volume === 0 });
|
|
1643
|
+
case "TOGGLE_MUTE":
|
|
1644
|
+
return __spreadProps(__spreadValues({}, state), { isMuted: !state.isMuted });
|
|
1645
|
+
case "UNMUTE":
|
|
1646
|
+
return __spreadProps(__spreadValues({}, state), { isMuted: false });
|
|
1647
|
+
}
|
|
1648
|
+
return state;
|
|
1649
|
+
}
|
|
1650
|
+
function formatTime(time) {
|
|
1651
|
+
const seconds = Math.round(time);
|
|
1652
|
+
return `${Math.floor(seconds / 60)}:${`${seconds % 60}`.padStart(2, "0")}`;
|
|
1653
|
+
}
|
|
1654
|
+
function useSimpleMediaPlayer(props) {
|
|
1655
|
+
const [state, dispatch] = useReducer(reducer, getDefaultState(props.duration));
|
|
1656
|
+
const media = useRef(null);
|
|
1657
|
+
const currentTime = useRef(null);
|
|
1658
|
+
const progress = useRef(null);
|
|
1659
|
+
const _isMuted = useRef(false);
|
|
1660
|
+
const _updateCurrentTime = useCallback(() => {
|
|
1661
|
+
if (currentTime.current && media.current) {
|
|
1662
|
+
currentTime.current.innerHTML = formatTime(media.current.currentTime);
|
|
1663
|
+
if (progress.current) {
|
|
1664
|
+
progress.current.style.width = `${media.current.currentTime / props.duration * 100}%`;
|
|
1665
|
+
}
|
|
1666
|
+
if (_isMuted.current !== media.current.muted) {
|
|
1667
|
+
_isMuted.current = media.current.muted;
|
|
1668
|
+
dispatch(media.current.muted ? { type: "MUTE" } : { type: "UNMUTE" });
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1671
|
+
}, [props.duration]);
|
|
1672
|
+
const play = useCallback(() => {
|
|
1673
|
+
if (media.current) {
|
|
1674
|
+
dispatch({ type: "PLAY_REQUESTED" });
|
|
1675
|
+
media.current.play().then(() => {
|
|
1676
|
+
dispatch({ type: "PLAY" });
|
|
1677
|
+
});
|
|
1678
|
+
_updateCurrentTime();
|
|
1679
|
+
}
|
|
1680
|
+
}, [_updateCurrentTime]);
|
|
1681
|
+
const playPause = useCallback(() => {
|
|
1682
|
+
if (media.current) {
|
|
1683
|
+
if (media.current.duration > 0 && media.current.paused) {
|
|
1684
|
+
play();
|
|
1685
|
+
} else {
|
|
1686
|
+
pause();
|
|
1687
|
+
}
|
|
1688
|
+
}
|
|
1689
|
+
}, [_updateCurrentTime]);
|
|
1690
|
+
const pause = useCallback(() => {
|
|
1691
|
+
if (media.current) {
|
|
1692
|
+
media.current.pause();
|
|
1693
|
+
dispatch({ type: "PAUSE" });
|
|
1694
|
+
_updateCurrentTime();
|
|
1695
|
+
}
|
|
1696
|
+
}, [_updateCurrentTime]);
|
|
1697
|
+
const toggleMute = useCallback(() => {
|
|
1698
|
+
if (media.current) {
|
|
1699
|
+
media.current.muted = !media.current.muted;
|
|
1700
|
+
dispatch(media.current.muted ? { type: "MUTE" } : { type: "UNMUTE" });
|
|
1701
|
+
}
|
|
1702
|
+
}, []);
|
|
1703
|
+
const mute = useCallback(() => {
|
|
1704
|
+
if (media.current) {
|
|
1705
|
+
media.current.muted = true;
|
|
1706
|
+
dispatch({ type: "MUTE" });
|
|
1707
|
+
}
|
|
1708
|
+
}, []);
|
|
1709
|
+
const unmute = useCallback(() => {
|
|
1710
|
+
if (media.current) {
|
|
1711
|
+
media.current.muted = false;
|
|
1712
|
+
dispatch({ type: "UNMUTE" });
|
|
1713
|
+
}
|
|
1714
|
+
}, []);
|
|
1715
|
+
const setVolume = useCallback((newVolume) => {
|
|
1716
|
+
if (media.current) {
|
|
1717
|
+
media.current.muted = false;
|
|
1718
|
+
media.current.volume = newVolume / 100;
|
|
1719
|
+
dispatch({ type: "SET_VOLUME", volume: newVolume });
|
|
1720
|
+
}
|
|
1721
|
+
}, []);
|
|
1722
|
+
const setDurationPercent = useCallback((percent) => {
|
|
1723
|
+
if (media.current) {
|
|
1724
|
+
media.current.currentTime = Math.max(0, Math.min(percent * props.duration, props.duration));
|
|
1725
|
+
_updateCurrentTime();
|
|
1726
|
+
}
|
|
1727
|
+
}, []);
|
|
1728
|
+
const setTime = useCallback((time) => {
|
|
1729
|
+
if (media.current) {
|
|
1730
|
+
media.current.currentTime = Math.max(0, Math.min(time, props.duration));
|
|
1731
|
+
_updateCurrentTime();
|
|
1732
|
+
}
|
|
1733
|
+
}, []);
|
|
1734
|
+
useEffect(() => {
|
|
1735
|
+
const interval = setInterval(() => {
|
|
1736
|
+
_updateCurrentTime();
|
|
1737
|
+
}, 350);
|
|
1738
|
+
return () => clearInterval(interval);
|
|
1739
|
+
}, [_updateCurrentTime, props.duration]);
|
|
1740
|
+
useEffect(() => {
|
|
1741
|
+
const ended = () => {
|
|
1742
|
+
dispatch({ type: "FINISHED" });
|
|
1743
|
+
};
|
|
1744
|
+
const _media = media.current;
|
|
1745
|
+
_media == null ? void 0 : _media.addEventListener("ended", ended);
|
|
1746
|
+
return () => _media == null ? void 0 : _media.removeEventListener("ended", ended);
|
|
1747
|
+
}, []);
|
|
1748
|
+
return [
|
|
1749
|
+
{ element: media, currentTime, progress },
|
|
1750
|
+
state,
|
|
1751
|
+
{
|
|
1752
|
+
play,
|
|
1753
|
+
pause,
|
|
1754
|
+
playPause,
|
|
1755
|
+
mute,
|
|
1756
|
+
unmute,
|
|
1757
|
+
toggleMute,
|
|
1758
|
+
setVolume,
|
|
1759
|
+
setDurationPercent,
|
|
1760
|
+
setTime
|
|
1761
|
+
}
|
|
1762
|
+
];
|
|
1763
|
+
}
|
|
1764
|
+
const MediaReactContextState = createContext(null);
|
|
1765
|
+
const MediaReactContextActions = createContext(null);
|
|
1766
|
+
const MediaReactContextElements = createContext(null);
|
|
1767
|
+
function MediaPlayerProvider({
|
|
1768
|
+
actions,
|
|
1769
|
+
state,
|
|
1770
|
+
children,
|
|
1771
|
+
currentTime,
|
|
1772
|
+
progress,
|
|
1773
|
+
element
|
|
1774
|
+
}) {
|
|
1775
|
+
return /* @__PURE__ */ jsx(MediaReactContextElements.Provider, {
|
|
1776
|
+
value: {
|
|
1777
|
+
currentTime,
|
|
1778
|
+
progress,
|
|
1779
|
+
element
|
|
1780
|
+
},
|
|
1781
|
+
children: /* @__PURE__ */ jsx(MediaReactContextActions.Provider, {
|
|
1782
|
+
value: actions,
|
|
1783
|
+
children: /* @__PURE__ */ jsx(MediaReactContextState.Provider, {
|
|
1784
|
+
value: state,
|
|
1785
|
+
children
|
|
1786
|
+
})
|
|
1787
|
+
})
|
|
1788
|
+
});
|
|
1789
|
+
}
|
|
1790
|
+
function Audio({
|
|
1791
|
+
media,
|
|
1792
|
+
children
|
|
1793
|
+
}) {
|
|
1794
|
+
const [{
|
|
1795
|
+
element,
|
|
1796
|
+
currentTime,
|
|
1797
|
+
progress
|
|
1798
|
+
}, state, actions] = useSimpleMediaPlayer({
|
|
1799
|
+
duration: media.duration
|
|
1800
|
+
});
|
|
1801
|
+
return /* @__PURE__ */ jsx(Fragment, {
|
|
1802
|
+
children: /* @__PURE__ */ jsx(CanvasPortal, {
|
|
1803
|
+
children: /* @__PURE__ */ jsxs(MediaPlayerProvider, {
|
|
1804
|
+
state,
|
|
1805
|
+
actions,
|
|
1806
|
+
currentTime,
|
|
1807
|
+
progress,
|
|
1808
|
+
element,
|
|
1809
|
+
children: [/* @__PURE__ */ jsx("audio", {
|
|
1810
|
+
ref: element,
|
|
1811
|
+
src: media.url
|
|
1812
|
+
}), children]
|
|
1813
|
+
})
|
|
1814
|
+
})
|
|
1815
|
+
});
|
|
1816
|
+
}
|
|
1817
|
+
function Video({
|
|
1818
|
+
media,
|
|
1819
|
+
children
|
|
1820
|
+
}) {
|
|
1821
|
+
const [{
|
|
1822
|
+
element,
|
|
1823
|
+
currentTime,
|
|
1824
|
+
progress
|
|
1825
|
+
}, state, actions] = useSimpleMediaPlayer({
|
|
1826
|
+
duration: media.duration
|
|
1827
|
+
});
|
|
1828
|
+
const Component = "div";
|
|
1829
|
+
return /* @__PURE__ */ jsxs(Fragment, {
|
|
1830
|
+
children: [/* @__PURE__ */ jsxs(CanvasPortal, {
|
|
1831
|
+
overlay: true,
|
|
1832
|
+
children: [/* @__PURE__ */ jsx("style", {
|
|
1833
|
+
children: `
|
|
1834
|
+
.video-container {
|
|
1835
|
+
position: absolute;
|
|
1836
|
+
top: 0;
|
|
1837
|
+
bottom: 0;
|
|
1838
|
+
left: 0;
|
|
1839
|
+
right: 0;
|
|
1840
|
+
background: #000;
|
|
1841
|
+
z-index: 13;
|
|
1842
|
+
display: flex;
|
|
1843
|
+
justify-content: center;
|
|
1844
|
+
pointer-events: visible;
|
|
1845
|
+
}
|
|
1846
|
+
`
|
|
1847
|
+
}), /* @__PURE__ */ jsx(Component, {
|
|
1848
|
+
className: "video-container",
|
|
1849
|
+
part: "video-container",
|
|
1850
|
+
onClick: () => actions.playPause(),
|
|
1851
|
+
children: /* @__PURE__ */ jsx("video", {
|
|
1852
|
+
ref: element,
|
|
1853
|
+
src: media.url,
|
|
1854
|
+
style: {
|
|
1855
|
+
width: "100%",
|
|
1856
|
+
objectFit: "contain"
|
|
1857
|
+
}
|
|
1858
|
+
})
|
|
1859
|
+
})]
|
|
1860
|
+
}), /* @__PURE__ */ jsx(CanvasPortal, {
|
|
1861
|
+
children: /* @__PURE__ */ jsx(MediaPlayerProvider, {
|
|
1862
|
+
state,
|
|
1863
|
+
actions,
|
|
1864
|
+
currentTime,
|
|
1865
|
+
progress,
|
|
1866
|
+
element,
|
|
1867
|
+
children
|
|
1868
|
+
})
|
|
1869
|
+
})]
|
|
1870
|
+
});
|
|
1871
|
+
}
|
|
1872
|
+
function Model({
|
|
1873
|
+
model
|
|
1874
|
+
}) {
|
|
1875
|
+
return /* @__PURE__ */ jsxs(CanvasPortal, {
|
|
1876
|
+
overlay: true,
|
|
1877
|
+
children: [/* @__PURE__ */ jsx("style", {
|
|
1878
|
+
children: `
|
|
1879
|
+
.model-container {
|
|
1880
|
+
position: absolute;
|
|
1881
|
+
top: 0;
|
|
1882
|
+
bottom: 0;
|
|
1883
|
+
left: 0;
|
|
1884
|
+
right: 0;
|
|
1885
|
+
background: #000;
|
|
1886
|
+
z-index: 13;
|
|
1887
|
+
display: flex;
|
|
1888
|
+
justify-content: center;
|
|
1889
|
+
pointer-events: visible;
|
|
1890
|
+
}
|
|
1891
|
+
`
|
|
1892
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
1893
|
+
className: "model-container",
|
|
1894
|
+
children: /* @__PURE__ */ jsx("model-viewer", {
|
|
1895
|
+
"interaction-prompt": "none",
|
|
1896
|
+
style: {
|
|
1897
|
+
width: "100%",
|
|
1898
|
+
height: "100%"
|
|
1899
|
+
},
|
|
1900
|
+
"camera-controls": "",
|
|
1901
|
+
"ar-status": "not-presenting",
|
|
1902
|
+
src: model.id
|
|
1903
|
+
})
|
|
1904
|
+
})]
|
|
1905
|
+
});
|
|
1906
|
+
}
|
|
1907
|
+
function RenderCanvas({
|
|
1908
|
+
x,
|
|
1909
|
+
y,
|
|
1910
|
+
onChoiceChange,
|
|
1911
|
+
registerActions,
|
|
1912
|
+
defaultChoices,
|
|
1913
|
+
isStatic,
|
|
1914
|
+
renderViewerControls,
|
|
1915
|
+
renderMediaControls,
|
|
1916
|
+
strategies,
|
|
1917
|
+
children
|
|
1918
|
+
}) {
|
|
1919
|
+
const canvas = useCanvas();
|
|
1920
|
+
const elementProps = useResourceEvents(canvas, ["deep-zoom"]);
|
|
1921
|
+
const [virtualPage] = useVirtualAnnotationPageContext();
|
|
1922
|
+
const vault = useVault();
|
|
1923
|
+
const helper = useMemo(() => createStylesHelper(vault), [vault]);
|
|
1924
|
+
const [strategy, actions] = useRenderingStrategy({
|
|
1925
|
+
strategies: strategies || ["images"],
|
|
1926
|
+
defaultChoices: defaultChoices == null ? void 0 : defaultChoices.map(({
|
|
1927
|
+
id
|
|
1928
|
+
}) => id)
|
|
1929
|
+
});
|
|
1930
|
+
const choice = strategy.type === "images" ? strategy.choice : void 0;
|
|
1931
|
+
useEffect(() => {
|
|
1932
|
+
if (registerActions) {
|
|
1933
|
+
registerActions(actions);
|
|
1934
|
+
}
|
|
1935
|
+
}, [strategy.annotations]);
|
|
1936
|
+
useEffect(() => {
|
|
1937
|
+
if (defaultChoices) {
|
|
1938
|
+
for (const choice2 of defaultChoices) {
|
|
1939
|
+
if (typeof choice2.opacity !== "undefined") {
|
|
1940
|
+
helper.applyStyles({
|
|
1941
|
+
id: choice2.id
|
|
1942
|
+
}, "atlas", {
|
|
1943
|
+
opacity: choice2.opacity
|
|
1944
|
+
});
|
|
1945
|
+
}
|
|
1946
|
+
}
|
|
1947
|
+
}
|
|
1948
|
+
}, [defaultChoices]);
|
|
1949
|
+
useLayoutEffect(() => {
|
|
1950
|
+
if (onChoiceChange) {
|
|
1951
|
+
onChoiceChange(choice);
|
|
1952
|
+
}
|
|
1953
|
+
}, [choice]);
|
|
1954
|
+
const thumbnail = useThumbnail({
|
|
1955
|
+
maxWidth: 256,
|
|
1956
|
+
maxHeight: 256
|
|
1957
|
+
});
|
|
1958
|
+
if (!canvas) {
|
|
1959
|
+
return null;
|
|
1960
|
+
}
|
|
1961
|
+
const accompanyingCanvas = canvas.accompanyingCanvas;
|
|
1962
|
+
const thumbnailFallbackImage = thumbnail && thumbnail.type === "fixed" ? /* @__PURE__ */ jsx("world-object", {
|
|
1963
|
+
height: canvas.height,
|
|
1964
|
+
width: canvas.width,
|
|
1965
|
+
x,
|
|
1966
|
+
y,
|
|
1967
|
+
children: /* @__PURE__ */ jsx("world-image", {
|
|
1968
|
+
uri: thumbnail.id,
|
|
1969
|
+
target: {
|
|
1970
|
+
x: 0,
|
|
1971
|
+
y: 0,
|
|
1972
|
+
width: canvas.width,
|
|
1973
|
+
height: canvas.height
|
|
1974
|
+
},
|
|
1975
|
+
display: thumbnail.width && thumbnail.height ? {
|
|
1976
|
+
width: thumbnail.width,
|
|
1977
|
+
height: thumbnail.height
|
|
1978
|
+
} : void 0
|
|
1979
|
+
})
|
|
1980
|
+
}) : null;
|
|
1981
|
+
if (strategy.type === "unknown") {
|
|
1982
|
+
if (thumbnailFallbackImage) {
|
|
1983
|
+
return thumbnailFallbackImage;
|
|
1984
|
+
}
|
|
1985
|
+
throw new Error(strategy.reason || "Unknown image strategy");
|
|
1986
|
+
}
|
|
1987
|
+
const annotations = /* @__PURE__ */ jsxs(Fragment$1, {
|
|
1988
|
+
children: [virtualPage ? /* @__PURE__ */ jsx(RenderAnnotationPage, {
|
|
1989
|
+
page: virtualPage
|
|
1990
|
+
}) : null, strategy.annotations && strategy.annotations.pages ? strategy.annotations.pages.map((page) => {
|
|
1991
|
+
return /* @__PURE__ */ jsx(RenderAnnotationPage, {
|
|
1992
|
+
page
|
|
1993
|
+
}, page.id);
|
|
1994
|
+
}) : null, children]
|
|
1995
|
+
});
|
|
1996
|
+
return /* @__PURE__ */ jsxs(Fragment, {
|
|
1997
|
+
children: [/* @__PURE__ */ jsxs("world-object", __spreadProps(__spreadValues({
|
|
1998
|
+
height: canvas.height,
|
|
1999
|
+
width: canvas.width,
|
|
2000
|
+
x,
|
|
2001
|
+
y
|
|
2002
|
+
}, elementProps), {
|
|
2003
|
+
children: [strategy.type === "images" ? /* @__PURE__ */ jsxs(Fragment, {
|
|
2004
|
+
children: [strategy.images.map((image, idx) => {
|
|
2005
|
+
return /* @__PURE__ */ jsx(RenderImage, {
|
|
2006
|
+
isStatic,
|
|
2007
|
+
image,
|
|
2008
|
+
id: image.id,
|
|
2009
|
+
thumbnail: idx === 0 ? thumbnail : void 0,
|
|
2010
|
+
annotations
|
|
2011
|
+
}, image.id);
|
|
2012
|
+
}), renderViewerControls ? /* @__PURE__ */ jsx(CanvasPortal, {
|
|
2013
|
+
overlay: true,
|
|
2014
|
+
children: renderViewerControls(strategy)
|
|
2015
|
+
}) : null]
|
|
2016
|
+
}) : null, strategy.type === "3d-model" ? /* @__PURE__ */ jsx(Model, {
|
|
2017
|
+
model: strategy.model
|
|
2018
|
+
}) : null, strategy.type === "media" ? /* @__PURE__ */ jsx(Fragment, {
|
|
2019
|
+
children: strategy.media.type === "Sound" ? /* @__PURE__ */ jsxs(Audio, {
|
|
2020
|
+
media: strategy.media,
|
|
2021
|
+
children: [thumbnailFallbackImage, renderMediaControls ? renderMediaControls(strategy) : null]
|
|
2022
|
+
}) : strategy.media.type === "Video" ? /* @__PURE__ */ jsxs(Video, {
|
|
2023
|
+
media: strategy.media,
|
|
2024
|
+
children: [thumbnailFallbackImage, renderMediaControls ? renderMediaControls(strategy) : null]
|
|
2025
|
+
}) : null
|
|
2026
|
+
}) : null]
|
|
2027
|
+
}), strategy.type), strategy.type === "media" && strategy.media.type === "Sound" && accompanyingCanvas ? /* @__PURE__ */ jsx(CanvasContext, {
|
|
2028
|
+
canvas: accompanyingCanvas.id,
|
|
2029
|
+
children: /* @__PURE__ */ jsx(RenderCanvas, {
|
|
2030
|
+
renderViewerControls
|
|
2031
|
+
})
|
|
2032
|
+
}) : null]
|
|
2033
|
+
});
|
|
2034
|
+
}
|
|
2035
|
+
const CanvasPanel = {
|
|
2036
|
+
RenderImage,
|
|
2037
|
+
RenderCanvas,
|
|
2038
|
+
RenderAnnotationPage,
|
|
2039
|
+
RenderAnnotation,
|
|
2040
|
+
Viewer
|
|
2041
|
+
};
|
|
2042
|
+
export { CanvasPanel };
|
|
2043
|
+
//# sourceMappingURL=canvas-panel.mjs.map
|