@aics/vole-app 2.13.6 → 2.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1255 @@
1
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
+ var _ViewerChannelSetting, _ViewerChannelSetting2, _ViewerChannelSetting3, _ViewerChannelSetting4, _ViewerChannelSetting5, _ViewerChannelSetting6, _ViewerChannelSetting7, _ViewerChannelSetting8, _ViewerChannelSetting9, _ViewerChannelSetting10, _ViewerChannelSetting11, _ViewerStateKeys$View, _ViewerStateKeys$Mode, _ViewerStateKeys$Mask, _ViewerStateKeys$Imag, _ViewerStateKeys$Axes, _ViewerStateKeys$Boun, _ViewerStateKeys$Boun2, _ViewerStateKeys$Back, _ViewerStateKeys$Auto, _ViewerStateKeys$Brig, _ViewerStateKeys$Dens, _ViewerStateKeys$Leve, _ViewerStateKeys$Inte, _ViewerStateKeys$Regi, _ViewerStateKeys$Slic, _ViewerStateKeys$Time, _ViewerStateKeys$Scen, _ViewerStateKeys$Came;
3
+ function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator["return"] && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, "catch": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
4
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
5
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
6
+ function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
7
+ function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
8
+ function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
9
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
10
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
11
+ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
12
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
13
+ function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
14
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
15
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
16
+ function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
17
+ function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
18
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
19
+ function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
20
+ function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
21
+ function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
22
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
23
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
24
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
25
+ import { isEqual } from "lodash";
26
+ import { getDefaultCameraState, getDefaultChannelState, getDefaultViewerState } from "../constants";
27
+ import { ImageType, RenderMode, ViewMode } from "../enums";
28
+ import { removeMatchingProperties, removeUndefinedProperties } from "./datatypes";
29
+ import FirebaseRequest from "./firebase";
30
+ import { clamp } from "./math";
31
+ export var ENCODED_COMMA_REGEX = /%2C/g;
32
+ export var ENCODED_COLON_REGEX = /%3A/g;
33
+ var DEFAULT_CONTROL_POINT_COLOR = [255, 255, 255];
34
+ var DEFAULT_CONTROL_POINT_COLOR_CODE = "1";
35
+
36
+ /** If the `url` query param equals this, parse image url(s) and metadata from local storage instead of params */
37
+ var URL_FETCH_FROM_STORAGE = "storage";
38
+
39
+ // TODO: refactor regexes to be composed of one another rather than duplicating code
40
+ // const COLOR_CODES: Record<string, ColorArray> = {
41
+ // "0": [0, 0, 0],
42
+ // "1": [255, 255, 255],
43
+ // "-1": [255, 255, 255],
44
+ // w: [255, 255, 255],
45
+ // k: [0, 0, 0],
46
+ // };
47
+ // const COLOR_CODE_REGEX = new RegExp(`(${Object.keys(COLOR_CODES).join("|")})`);
48
+ // const HEX_COLOR_REGEX = new RegExp(`(([0-9a-fA-F]{6})|${COLOR_CODE_REGEX.source})`);
49
+
50
+ var CHANNEL_STATE_KEY_REGEX = /^c[0-9]+$/;
51
+ /** Match colon-separated pairs of alphanumeric strings */
52
+ var LUT_REGEX = /^-?[a-z0-9.]*:[ ]*-?[a-z0-9.]*$/;
53
+ /** Match colon-separated pairs of numeric strings */
54
+ var RAMP_REGEX = /^-?[0-9.]*:-?[0-9.]*$/;
55
+ /**
56
+ * Match comma-separated triplet of numeric strings.
57
+ */
58
+ var SLICE_REGEX = /^[0-9.]*,[0-9.]*,[0-9.]*$/;
59
+ /**
60
+ * Matches a sequence of three comma-separated min:max number pairs, representing
61
+ * the x, y, and z axes.
62
+ */
63
+ var REGION_REGEX = /^([0-9.]*:[0-9.]*)(,[0-9.]*:[0-9.]*){2}$/;
64
+ var HEX_COLOR_REGEX = new RegExp("(([0-9a-fA-F]{6})|".concat(DEFAULT_CONTROL_POINT_COLOR_CODE, ")"));
65
+ var NUMERIC_REGEX = /-?[0-9.]*/;
66
+ var CONTROL_POINT_REGEX = new RegExp("(".concat(NUMERIC_REGEX.source, ":").concat(NUMERIC_REGEX.source, ":").concat(HEX_COLOR_REGEX.source, ")"));
67
+ var HEX_COLOR_STR_REGEX = new RegExp("^".concat(HEX_COLOR_REGEX.source, "$"));
68
+
69
+ /**
70
+ * LEGACY: Matches a COMMA-separated list of control points, where each control point is represented
71
+ * by a triplet of `{x}:{opacity}:{hex color}`.
72
+ * The hex color can be replaced with `w` to represent white (`ffffff`).
73
+ */
74
+ export var LEGACY_CONTROL_POINTS_REGEX = new RegExp("^".concat(CONTROL_POINT_REGEX.source, "(,").concat(CONTROL_POINT_REGEX.source, ")*$"));
75
+ /**
76
+ * Matches a COLON-separated list of control points, where each control point is represented
77
+ * by a triplet of `{x}:{opacity}:{hex color}`.
78
+ * The hex color can be replaced with `w` to represent white (`ffffff`).
79
+ */
80
+ export var CONTROL_POINTS_REGEX = new RegExp("^".concat(CONTROL_POINT_REGEX.source, "(:").concat(CONTROL_POINT_REGEX.source, ")*$"));
81
+
82
+ /**
83
+ * Enum keys for URL parameters. These are stored as enums for better readability,
84
+ * and are mapped to types in `ViewerStateParams`.
85
+ */
86
+ export var ViewerStateKeys = /*#__PURE__*/function (ViewerStateKeys) {
87
+ ViewerStateKeys["View"] = "view";
88
+ ViewerStateKeys["Mode"] = "mode";
89
+ ViewerStateKeys["Mask"] = "mask";
90
+ ViewerStateKeys["Image"] = "image";
91
+ ViewerStateKeys["Axes"] = "axes";
92
+ ViewerStateKeys["BoundingBox"] = "bb";
93
+ ViewerStateKeys["BoundingBoxColor"] = "bbcol";
94
+ ViewerStateKeys["BackgroundColor"] = "bgcol";
95
+ ViewerStateKeys["Autorotate"] = "rot";
96
+ ViewerStateKeys["Brightness"] = "bright";
97
+ ViewerStateKeys["Density"] = "dens";
98
+ ViewerStateKeys["Levels"] = "lvl";
99
+ ViewerStateKeys["Interpolation"] = "interp";
100
+ ViewerStateKeys["Region"] = "reg";
101
+ ViewerStateKeys["Slice"] = "slice";
102
+ ViewerStateKeys["Time"] = "t";
103
+ ViewerStateKeys["Scene"] = "scene";
104
+ ViewerStateKeys["CameraState"] = "cam";
105
+ return ViewerStateKeys;
106
+ }({});
107
+ export var CameraTransformKeys = /*#__PURE__*/function (CameraTransformKeys) {
108
+ CameraTransformKeys["Position"] = "pos";
109
+ CameraTransformKeys["Target"] = "tar";
110
+ CameraTransformKeys["Up"] = "up";
111
+ CameraTransformKeys["OrthoScale"] = "ort";
112
+ CameraTransformKeys["Fov"] = "fov";
113
+ return CameraTransformKeys;
114
+ }({});
115
+
116
+ /**
117
+ * Mapped to types in `ViewerChannelSettingParams`
118
+ */
119
+ export var ViewerChannelSettingKeys = /*#__PURE__*/function (ViewerChannelSettingKeys) {
120
+ ViewerChannelSettingKeys["Color"] = "col";
121
+ ViewerChannelSettingKeys["Colorize"] = "clz";
122
+ ViewerChannelSettingKeys["ColorizeAlpha"] = "cza";
123
+ ViewerChannelSettingKeys["IsosurfaceAlpha"] = "isa";
124
+ ViewerChannelSettingKeys["Lut"] = "lut";
125
+ ViewerChannelSettingKeys["Ramp"] = "rmp";
126
+ ViewerChannelSettingKeys["ControlPoints"] = "cps";
127
+ ViewerChannelSettingKeys["ControlPointsEnabled"] = "cpe";
128
+ ViewerChannelSettingKeys["VolumeEnabled"] = "ven";
129
+ ViewerChannelSettingKeys["SurfaceEnabled"] = "sen";
130
+ ViewerChannelSettingKeys["IsosurfaceValue"] = "isv";
131
+ return ViewerChannelSettingKeys;
132
+ }({});
133
+
134
+ /**
135
+ * The serialized form of a ViewerChannelSetting, as a dictionary object.
136
+ */
137
+ _ViewerChannelSetting = ViewerChannelSettingKeys.Color;
138
+ _ViewerChannelSetting2 = ViewerChannelSettingKeys.Colorize;
139
+ _ViewerChannelSetting3 = ViewerChannelSettingKeys.ColorizeAlpha;
140
+ _ViewerChannelSetting4 = ViewerChannelSettingKeys.IsosurfaceAlpha;
141
+ _ViewerChannelSetting5 = ViewerChannelSettingKeys.Lut;
142
+ _ViewerChannelSetting6 = ViewerChannelSettingKeys.ControlPoints;
143
+ _ViewerChannelSetting7 = ViewerChannelSettingKeys.ControlPointsEnabled;
144
+ _ViewerChannelSetting8 = ViewerChannelSettingKeys.Ramp;
145
+ _ViewerChannelSetting9 = ViewerChannelSettingKeys.VolumeEnabled;
146
+ _ViewerChannelSetting10 = ViewerChannelSettingKeys.SurfaceEnabled;
147
+ _ViewerChannelSetting11 = ViewerChannelSettingKeys.IsosurfaceValue;
148
+ export var ViewerChannelSettingParams = /*#__PURE__*/_createClass(function ViewerChannelSettingParams() {
149
+ _classCallCheck(this, ViewerChannelSettingParams);
150
+ /** Color, as a 6-digit hex color. */
151
+ _defineProperty(this, _ViewerChannelSetting, undefined);
152
+ /** Colorize. "1" is enabled. Disabled by default. */
153
+ _defineProperty(this, _ViewerChannelSetting2, undefined);
154
+ /** Colorize alpha, in the [0, 1] range. Set to `1.0` by default. */
155
+ _defineProperty(this, _ViewerChannelSetting3, undefined);
156
+ /** Isosurface alpha, in the [0, 1 range]. Set to `1.0` by default.*/
157
+ _defineProperty(this, _ViewerChannelSetting4, undefined);
158
+ /**
159
+ * Lookup table (LUT) to map from volume intensity to opacity. Should be two
160
+ * alphanumeric values separated by a colon, where the first value is the
161
+ * minimum and the second is the maximum. Defaults to [0, 255].
162
+ *
163
+ * Min and max values are determined as following:
164
+ * - Plain numbers are indices of histogram bins, typically in the range [0,
165
+ * 255].
166
+ * - `v{n}` represents a raw intensity value, where `n` is a number.
167
+ * - `p{n}` represents a percentile, where `n` is a percentile in the [0, 100]
168
+ * range.
169
+ * - `m{n}` represents the median multiplied by `n / 100`.
170
+ * - `autoij` in either the min or max fields will use the "auto" algorithm
171
+ * from ImageJ to select the min and max.
172
+ *
173
+ * Values will be used to determine the initial control points and ramp if
174
+ * those fields are not provided.
175
+ *
176
+ * @example
177
+ * ```
178
+ * "0:255" // min: intensity 0, max: intensity 255.
179
+ * "p50:p90" // min: 50th percentile, max: 90th percentile.
180
+ * "m1:p75" // min: median, max: 75th percentile.
181
+ * "autoij:0" // use Auto-IJ to calculate min and max.
182
+ * ```
183
+ */
184
+ _defineProperty(this, _ViewerChannelSetting5, undefined);
185
+ /**
186
+ * Control points for the transfer function. If provided, overrides the
187
+ * `lut` field when calculating the control points. Should be a list
188
+ * of `x:opacity:color` triplets, separated by colon.
189
+ * - `x` is a numeric intensity value.
190
+ * - `opacity` is a float in the [0, 1] range.
191
+ * - `color` is a 6-digit hex color, e.g. `ff0000`.
192
+ */
193
+ _defineProperty(this, _ViewerChannelSetting6, undefined);
194
+ /**
195
+ * Whether to show advanced mode, which will show control points instead of
196
+ * ramp values defined by the LUT. "1" is enabled, disabled by default.
197
+ */
198
+ _defineProperty(this, _ViewerChannelSetting7, undefined);
199
+ /**
200
+ * Raw ramp values, which should be two numeric values separated by a colon.
201
+ * If provided, overrides the `lut` field when calculating the ramp values.
202
+ */
203
+ _defineProperty(this, _ViewerChannelSetting8, undefined);
204
+ /** Volume enabled. "1" is enabled. Disabled by default. */
205
+ _defineProperty(this, _ViewerChannelSetting9, undefined);
206
+ /** Isosurface enabled. "1" is enabled. Disabled by default. */
207
+ _defineProperty(this, _ViewerChannelSetting10, undefined);
208
+ /** Isosurface value, in the [0, 255] range. Set to `128` by default. */
209
+ _defineProperty(this, _ViewerChannelSetting11, undefined);
210
+ });
211
+ /**
212
+ * Channels, matching the pattern `c0`, `c1`, etc. corresponding to the index of the channel being configured.
213
+ * The channel parameter should have a value that is a comma-separated list of `key:value` pairs, with keys
214
+ * defined in `ViewerChannelSettingJson`.
215
+ */
216
+ _ViewerStateKeys$View = ViewerStateKeys.View;
217
+ _ViewerStateKeys$Mode = ViewerStateKeys.Mode;
218
+ _ViewerStateKeys$Mask = ViewerStateKeys.Mask;
219
+ _ViewerStateKeys$Imag = ViewerStateKeys.Image;
220
+ _ViewerStateKeys$Axes = ViewerStateKeys.Axes;
221
+ _ViewerStateKeys$Boun = ViewerStateKeys.BoundingBox;
222
+ _ViewerStateKeys$Boun2 = ViewerStateKeys.BoundingBoxColor;
223
+ _ViewerStateKeys$Back = ViewerStateKeys.BackgroundColor;
224
+ _ViewerStateKeys$Auto = ViewerStateKeys.Autorotate;
225
+ _ViewerStateKeys$Brig = ViewerStateKeys.Brightness;
226
+ _ViewerStateKeys$Dens = ViewerStateKeys.Density;
227
+ _ViewerStateKeys$Leve = ViewerStateKeys.Levels;
228
+ _ViewerStateKeys$Inte = ViewerStateKeys.Interpolation;
229
+ _ViewerStateKeys$Regi = ViewerStateKeys.Region;
230
+ _ViewerStateKeys$Slic = ViewerStateKeys.Slice;
231
+ _ViewerStateKeys$Time = ViewerStateKeys.Time;
232
+ _ViewerStateKeys$Scen = ViewerStateKeys.Scene;
233
+ _ViewerStateKeys$Came = ViewerStateKeys.CameraState;
234
+ /** Serialized version of `ViewerState`. */
235
+ export var ViewerStateParams = /*#__PURE__*/_createClass(function ViewerStateParams() {
236
+ _classCallCheck(this, ViewerStateParams);
237
+ /** Axis to view. Valid values are "3D", "X", "Y", and "Z". Defaults to "3D". */
238
+ _defineProperty(this, _ViewerStateKeys$View, undefined);
239
+ /**
240
+ * Render mode. Valid values are "volumetric", "maxproject", and "pathtrace".
241
+ * Defaults to "volumetric".
242
+ */
243
+ _defineProperty(this, _ViewerStateKeys$Mode, undefined);
244
+ /** The opacity of the mask channel, an integer in the range [0, 100]. Defaults to 50. */
245
+ _defineProperty(this, _ViewerStateKeys$Mask, undefined);
246
+ /** The type of image to display. Valid values are "cell" and "fov". Defaults to "cell". */
247
+ _defineProperty(this, _ViewerStateKeys$Imag, undefined);
248
+ /** Whether to show the axes helper. "1" is enabled. Disabled by default. */
249
+ _defineProperty(this, _ViewerStateKeys$Axes, undefined);
250
+ /** Whether to show the bounding box. "1" is enabled. Disabled by default. */
251
+ _defineProperty(this, _ViewerStateKeys$Boun, undefined);
252
+ /** The color of the bounding box, as a 6-digit hex color. */
253
+ _defineProperty(this, _ViewerStateKeys$Boun2, undefined);
254
+ /** The background color, as a 6-digit hex color. */
255
+ _defineProperty(this, _ViewerStateKeys$Back, undefined);
256
+ /** Whether to autorotate the view. "1" is enabled. Disabled by default. */
257
+ _defineProperty(this, _ViewerStateKeys$Auto, undefined);
258
+ /** The brightness of the image, an float in the range [0, 100]. Defaults to 70. */
259
+ _defineProperty(this, _ViewerStateKeys$Brig, undefined);
260
+ /** Density, a float in the range [0, 100]. Defaults to 50. */
261
+ _defineProperty(this, _ViewerStateKeys$Dens, undefined);
262
+ /**
263
+ * Levels for image intensity adjustment. Should be three numeric values separated
264
+ * by commas, representing the low, middle, and high values in a [0, 255] range.
265
+ * Values will be sorted in ascending order; empty values will be parsed as 0.
266
+ */
267
+ _defineProperty(this, _ViewerStateKeys$Leve, undefined);
268
+ /** Whether to enable interpolation. "1" is enabled. Enabled by default. */
269
+ _defineProperty(this, _ViewerStateKeys$Inte, undefined);
270
+ /** Subregions per axis, as min:max pairs separated by commas.
271
+ * Defaults to full range (`0:1`) for each axis.
272
+ */
273
+ _defineProperty(this, _ViewerStateKeys$Regi, undefined);
274
+ /** Slice position per X, Y, and Z axes, as a list of comma-separated floats.
275
+ * 0.5 for all axes by default (e.g. `0.5,0.5,0.5`)
276
+ */
277
+ _defineProperty(this, _ViewerStateKeys$Slic, undefined);
278
+ /** Frame number, for time-series volumes. 0 by default. */
279
+ _defineProperty(this, _ViewerStateKeys$Time, undefined);
280
+ /** Scene number, for multiscene images. 0 by default. */
281
+ _defineProperty(this, _ViewerStateKeys$Scen, undefined);
282
+ /**
283
+ * Camera transform settings, as a list of `key:value` pairs separated by commas.
284
+ * Valid keys are defined in `CameraTransformKeys`:
285
+ * - `pos`: position
286
+ * - `tar`: target
287
+ * - `up`: up
288
+ * - `rot`: rotation
289
+ * - `ort`: orthographic scales
290
+ *
291
+ * All values are an array of three floats, separated by commas and
292
+ * encoded using `encodeURIComponent`.
293
+ */
294
+ _defineProperty(this, _ViewerStateKeys$Came, undefined);
295
+ });
296
+
297
+ /** URL parameters that define data sources when loading volumes. */
298
+ var DataParams = /*#__PURE__*/_createClass(function DataParams() {
299
+ _classCallCheck(this, DataParams);
300
+ /**
301
+ * One or more volume URLs to load. If multiple URLs are provided, they should
302
+ * be separated by commas.
303
+ */
304
+ _defineProperty(this, "url", undefined);
305
+ /**
306
+ * The URL of a JSON manifest. The JSON should contain two properties:
307
+ * - "scenes": A string array of volume URLs.
308
+ * - "meta": An array of metadata dictionary objects.
309
+ *
310
+ * See `ManifestJson` for the type definition.
311
+ */
312
+ _defineProperty(this, "manifest", undefined);
313
+ /**
314
+ * The name of a dataset in the Cell Feature Explorer database. Used with `id`.
315
+ */
316
+ _defineProperty(this, "dataset", undefined);
317
+ /**
318
+ * The ID of a cell within the loaded dataset. Used with `dataset`.
319
+ */
320
+ _defineProperty(this, "id", undefined);
321
+ });
322
+ var DeprecatedParams = /*#__PURE__*/_createClass(function DeprecatedParams() {
323
+ _classCallCheck(this, DeprecatedParams);
324
+ /** Deprecated query parameter for channel settings. */
325
+ _defineProperty(this, "ch", undefined);
326
+ /** Deprecated query parameter for LUT settings. */
327
+ _defineProperty(this, "luts", undefined);
328
+ /** Deprecated query parameter for channel colors. */
329
+ _defineProperty(this, "colors", undefined);
330
+ });
331
+ var allowedParamKeys = [].concat(_toConsumableArray(Object.keys(new ViewerStateParams())), _toConsumableArray(Object.keys(new DataParams())), _toConsumableArray(Object.keys(new DeprecatedParams())));
332
+ var isParamKey = function isParamKey(key) {
333
+ return allowedParamKeys.indexOf(key) !== -1;
334
+ };
335
+ var isChannelKey = function isChannelKey(key) {
336
+ return CHANNEL_STATE_KEY_REGEX.test(key);
337
+ };
338
+
339
+ /**
340
+ * Filters a set of URLSearchParams for only the keys that are valid parameters for the viewer.
341
+ * Non-matching keys are discarded.
342
+ * @param searchParams Input URL search parameters.
343
+ * @returns a dictionary object matching the type of `Params`.
344
+ */
345
+ export function getAllowedParams(searchParams) {
346
+ var result = {};
347
+ var _iterator = _createForOfIteratorHelper(searchParams.entries()),
348
+ _step;
349
+ try {
350
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
351
+ var _step$value = _slicedToArray(_step.value, 2),
352
+ key = _step$value[0],
353
+ value = _step$value[1];
354
+ if (isParamKey(key) || isChannelKey(key)) {
355
+ result[key] = value;
356
+ }
357
+ }
358
+ } catch (err) {
359
+ _iterator.e(err);
360
+ } finally {
361
+ _iterator.f();
362
+ }
363
+ return result;
364
+ }
365
+ var decodeURL = function decodeURL(url) {
366
+ var decodedUrl = decodeURIComponent(url);
367
+ return decodedUrl.endsWith("/") ? decodedUrl.slice(0, -1) : decodedUrl;
368
+ };
369
+
370
+ /** Try to parse a `string` as a list of 2 or more URLs. Returns `undefined` if the string is not a valid URL list. */
371
+ var tryDecodeURLList = function tryDecodeURLList(url) {
372
+ var delim = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ",";
373
+ if (typeof delim === "string" ? !url.includes(delim) : !delim.test(url)) {
374
+ return undefined;
375
+ }
376
+ var urls = url.split(delim).map(function (u) {
377
+ return decodeURL(u);
378
+ });
379
+
380
+ // Verify that all urls are valid
381
+ var _iterator2 = _createForOfIteratorHelper(urls),
382
+ _step2;
383
+ try {
384
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
385
+ var u = _step2.value;
386
+ try {
387
+ new URL(u);
388
+ } catch (_e) {
389
+ return undefined;
390
+ }
391
+ }
392
+ } catch (err) {
393
+ _iterator2.e(err);
394
+ } finally {
395
+ _iterator2.f();
396
+ }
397
+ return urls;
398
+ };
399
+
400
+ //// DATA PARSING //////////////////////
401
+
402
+ /**
403
+ * Parse a string list of comma-separated key:value pairs into
404
+ * a key-value object.
405
+ *
406
+ * @param data The string to parse. Expected to be in the format
407
+ * "key1:value1,key2:value2,...". Commas in keys or values
408
+ * must be encoded using `encodeURIComponent`.
409
+ * @returns An object with the parsed key-value pairs. Key and value strings
410
+ * will be decoded using `decodeURIComponent`.
411
+ */
412
+ export function parseKeyValueList(data) {
413
+ if (data === "") {
414
+ return {};
415
+ }
416
+ var result = {};
417
+ var keyValuePairs = data.split(",");
418
+ var _iterator3 = _createForOfIteratorHelper(keyValuePairs),
419
+ _step3;
420
+ try {
421
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
422
+ var pair = _step3.value;
423
+ var splitIndex = pair.indexOf(":");
424
+ var key = pair.slice(0, splitIndex);
425
+ var value = pair.slice(splitIndex + 1);
426
+ result[decodeURIComponent(key).trim()] = decodeURIComponent(value).trim();
427
+ }
428
+ } catch (err) {
429
+ _iterator3.e(err);
430
+ } finally {
431
+ _iterator3.f();
432
+ }
433
+ return result;
434
+ }
435
+ function decodeColons(str) {
436
+ return str.replace(ENCODED_COLON_REGEX, ":");
437
+ }
438
+ export function objectToKeyValueList(obj) {
439
+ var keyValuePairs = [];
440
+ for (var key in obj) {
441
+ var value = obj[key];
442
+ if (value === undefined) {
443
+ continue;
444
+ }
445
+ // Allow colon separators to remain unencoded to save URL character length.
446
+ var escapedValue = decodeColons(encodeURIComponent(value.trim()));
447
+ keyValuePairs.push("".concat(encodeURIComponent(key.trim()), ":").concat(escapedValue));
448
+ }
449
+ return keyValuePairs.join(",");
450
+ }
451
+
452
+ /**
453
+ * Parses a string to a float and clamps the result to the [min, max] range.
454
+ * Returns `undefined` if the string is undefined or NaN.
455
+ * @param value String to parse as a float. Will be parsed with `Number.parseFloat`.
456
+ * @param min Minimum value, inclusive.
457
+ * @param max Maximum value, inclusive.
458
+ * @returns
459
+ * - The parsed number, clamped to the [min, max] range.
460
+ * - `undefined` if the string is undefined or NaN.
461
+ */
462
+ export function parseStringFloat(value, min, max) {
463
+ if (value === undefined) {
464
+ return undefined;
465
+ }
466
+ var number = Number.parseFloat(value);
467
+ return Number.isNaN(number) ? undefined : clamp(number, min, max);
468
+ }
469
+
470
+ /**
471
+ * Parses a string to an integer and clamps the result to the [min, max] range.
472
+ * @param value String to parse as a float. Assumes base 10, parses with `Number.parseInt(value, 10)`.
473
+ * @param min Minimum value, inclusive.
474
+ * @param max Maximum value, inclusive.
475
+ * @returns
476
+ * - The parsed number, clamped to the [min, max] range.
477
+ * - `undefined` if the string is undefined or NaN.
478
+ */
479
+ export function parseStringInt(value, min, max) {
480
+ if (value === undefined) {
481
+ return undefined;
482
+ }
483
+ var number = Number.parseInt(value, 10);
484
+ if (Number.isNaN(number)) {
485
+ return undefined;
486
+ }
487
+ return clamp(number, min, max);
488
+ }
489
+
490
+ /**
491
+ * Parses a string to an enum value; if the string is not in the enum, returns the default value.
492
+ * @param value String to parse.
493
+ * @param enumValues Enum. Cannot be a `const enum`, as these are removed at compile time.
494
+ * @param defaultValue Default value to return if the string is not in the enum.
495
+ * @returns A value from the enum or the default value. Note that the return type includes `undefined`
496
+ * if the `defaultValue` is `undefined`.
497
+ */
498
+ export function parseStringEnum(value, enumValues) {
499
+ var defaultValue = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined;
500
+ if (value === undefined || !Object.values(enumValues).includes(value)) {
501
+ return defaultValue;
502
+ }
503
+ return value;
504
+ }
505
+
506
+ /**
507
+ * Parses a string boolean value ("1" as true, "0" as false), and returns `undefined` if the value is `undefined`.
508
+ */
509
+ function parseStringBoolean(value) {
510
+ if (value === undefined) {
511
+ return undefined;
512
+ }
513
+ return value === "1";
514
+ }
515
+ export function parseHexColorAsColorArray(hexColor) {
516
+ if (!hexColor || !HEX_COLOR_STR_REGEX.test(hexColor)) {
517
+ return undefined;
518
+ }
519
+ // if (hexColor in COLOR_CODES) {
520
+ // return COLOR_CODES[hexColor];
521
+ // }
522
+ if (hexColor === DEFAULT_CONTROL_POINT_COLOR_CODE) {
523
+ return DEFAULT_CONTROL_POINT_COLOR;
524
+ }
525
+ var r = Number.parseInt(hexColor.slice(0, 2), 16);
526
+ var g = Number.parseInt(hexColor.slice(2, 4), 16);
527
+ var b = Number.parseInt(hexColor.slice(4, 6), 16);
528
+ return [r, g, b];
529
+ }
530
+ function colorArrayToHex(color) {
531
+ return color.map(function (c) {
532
+ return c.toString(16).padStart(2, "0");
533
+ }).join("").toLowerCase();
534
+ }
535
+ function parseStringSlice(region) {
536
+ if (!region || !SLICE_REGEX.test(region)) {
537
+ return undefined;
538
+ }
539
+ var _region$split$map = region.split(",").map(function (val) {
540
+ return parseStringFloat(val, 0, 1);
541
+ }),
542
+ _region$split$map2 = _slicedToArray(_region$split$map, 3),
543
+ x = _region$split$map2[0],
544
+ y = _region$split$map2[1],
545
+ z = _region$split$map2[2];
546
+ if (x === undefined || y === undefined || z === undefined) {
547
+ return undefined;
548
+ }
549
+ return {
550
+ x: x,
551
+ y: y,
552
+ z: z
553
+ };
554
+ }
555
+
556
+ /**
557
+ * Parses an array of three numbers from a string.
558
+ * @param stringArr The string to parse. Should be three numbers separated by a separator.
559
+ * @param options Optional parameters for parsing:
560
+ * - `min`: Minimum value for each number. Default is negative infinity.
561
+ * - `max`: Maximum value for each number. Default is positive infinity.
562
+ * - `separator`: Separator between numbers. Default is `,`.
563
+ * @returns
564
+ * - undefined if the string is undefined or could not be parsed.
565
+ * - An array of three numbers, clamped to the [min, max] range.
566
+ */
567
+ function parseThreeNumberArray(stringArr, options) {
568
+ var _options$min, _options$max, _options$separator;
569
+ if (!stringArr) {
570
+ return undefined;
571
+ }
572
+ var min = (_options$min = options === null || options === void 0 ? void 0 : options.min) !== null && _options$min !== void 0 ? _options$min : Number.NEGATIVE_INFINITY;
573
+ var max = (_options$max = options === null || options === void 0 ? void 0 : options.max) !== null && _options$max !== void 0 ? _options$max : Number.POSITIVE_INFINITY;
574
+ var separator = (_options$separator = options === null || options === void 0 ? void 0 : options.separator) !== null && _options$separator !== void 0 ? _options$separator : ",";
575
+ var _stringArr$split$map = stringArr.split(separator).map(function (val) {
576
+ return parseStringFloat(val, min, max);
577
+ }),
578
+ _stringArr$split$map2 = _slicedToArray(_stringArr$split$map, 3),
579
+ x = _stringArr$split$map2[0],
580
+ y = _stringArr$split$map2[1],
581
+ z = _stringArr$split$map2[2];
582
+ if (x === undefined || y === undefined || z === undefined) {
583
+ return undefined;
584
+ }
585
+ return [x, y, z];
586
+ }
587
+ function parseStringRegion(region) {
588
+ if (!region || !REGION_REGEX.test(region)) {
589
+ return undefined;
590
+ }
591
+ var _region$split$map3 = region.split(",").map(function (axis) {
592
+ // each is a min/max pair
593
+ var _axis$split$map = axis.split(":").map(function (val) {
594
+ return parseStringFloat(val, 0, 1);
595
+ }),
596
+ _axis$split$map2 = _slicedToArray(_axis$split$map, 2),
597
+ min = _axis$split$map2[0],
598
+ max = _axis$split$map2[1];
599
+ if (min === undefined || max === undefined) {
600
+ return undefined;
601
+ }
602
+ // Ensure sorted order
603
+ return min < max ? [min, max] : [max, min];
604
+ }),
605
+ _region$split$map4 = _slicedToArray(_region$split$map3, 3),
606
+ x = _region$split$map4[0],
607
+ y = _region$split$map4[1],
608
+ z = _region$split$map4[2];
609
+ // Check for undefined values
610
+ if (x === undefined || y === undefined || z === undefined) {
611
+ return undefined;
612
+ }
613
+ return {
614
+ x: x,
615
+ y: y,
616
+ z: z
617
+ };
618
+ }
619
+
620
+ /**
621
+ * Formats a float or integer value to a string with a maximum precision for float values.
622
+ * @param value The number to format.
623
+ * @param maxPrecision The maximum number of significant digits to display for float values.
624
+ * Default is 7.
625
+ * @returns
626
+ * - For integers, the integer value as a string.
627
+ * - For floats, the float value as a string with a maximum of `maxPrecision` significant digits
628
+ * and any trailing zeroes removed.
629
+ *
630
+ * @example
631
+ * ```
632
+ * formatFloat(1.23456, 3) // "1.23"
633
+ * formatFloat(123456, 3) // "123456"
634
+ * formatFloat(1.3999999999999999, 3) // "1.4"
635
+ * ```
636
+ */
637
+ function formatFloat(value) {
638
+ var maxPrecision = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 7;
639
+ if (Number.isInteger(value)) {
640
+ return value.toString();
641
+ }
642
+ return Number(value.toPrecision(maxPrecision)).toString();
643
+ }
644
+ function perAxisToArray(perAxis) {
645
+ return [perAxis.x, perAxis.y, perAxis.z];
646
+ }
647
+
648
+ /** Serializes a region into a `x1:x2,y1:y2,z1:z2` string format. */
649
+ function serializeRegion(region) {
650
+ return perAxisToArray(region).map(function (axis) {
651
+ return axis.map(function (val) {
652
+ return formatFloat(val);
653
+ }).join(":");
654
+ }).join(",");
655
+ }
656
+
657
+ /** Serializes a slice parameter into a `x,y,z` string format. */
658
+ function serializeSlice(slice) {
659
+ return perAxisToArray(slice).map(function (val) {
660
+ return formatFloat(val);
661
+ }).join(",");
662
+ }
663
+ function serializeBoolean(value) {
664
+ if (value === undefined) {
665
+ return undefined;
666
+ }
667
+ return value ? "1" : "0";
668
+ }
669
+ function parseCameraState(cameraSettings) {
670
+ if (!cameraSettings) {
671
+ return undefined;
672
+ }
673
+ var parsedCameraSettings = parseKeyValueList(cameraSettings);
674
+ var result = {
675
+ position: parseThreeNumberArray(parsedCameraSettings[CameraTransformKeys.Position], {
676
+ separator: ":"
677
+ }),
678
+ target: parseThreeNumberArray(parsedCameraSettings[CameraTransformKeys.Target], {
679
+ separator: ":"
680
+ }),
681
+ up: parseThreeNumberArray(parsedCameraSettings[CameraTransformKeys.Up], {
682
+ separator: ":"
683
+ }),
684
+ // Orthographic scales cannot be negative
685
+ orthoScale: parseStringFloat(parsedCameraSettings[CameraTransformKeys.OrthoScale], 0, Infinity),
686
+ fov: parseStringFloat(parsedCameraSettings[CameraTransformKeys.Fov], 0, 180)
687
+ };
688
+ return removeUndefinedProperties(result);
689
+ }
690
+ export function serializeCameraState(cameraState, removeDefaults) {
691
+ var viewMode = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ViewMode.threeD;
692
+ if (removeDefaults) {
693
+ // Note that we use the `getDefaultCameraState()` to get the defaults here,
694
+ // instead of `getDefaultViewerState().cameraState`. The latter is undefined, which signals
695
+ // that the camera should not be modified for URLs that don't specify it.
696
+ cameraState = removeMatchingProperties(cameraState, getDefaultCameraState(viewMode));
697
+ if (Object.keys(cameraState).length === 0) {
698
+ return undefined;
699
+ }
700
+ }
701
+ var cameraString = objectToKeyValueList(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty({}, CameraTransformKeys.Position, cameraState.position && cameraState.position.map(function (value) {
702
+ return formatFloat(value);
703
+ }).join(":")), CameraTransformKeys.Target, cameraState.target && cameraState.target.map(function (value) {
704
+ return formatFloat(value);
705
+ }).join(":")), CameraTransformKeys.Up, cameraState.up && cameraState.up.map(function (value) {
706
+ return formatFloat(value);
707
+ }).join(":")), CameraTransformKeys.OrthoScale, cameraState.orthoScale === undefined ? undefined : formatFloat(cameraState.orthoScale)), CameraTransformKeys.Fov, cameraState.fov === undefined ? undefined : formatFloat(cameraState.fov)));
708
+ return cameraString === "" ? undefined : cameraString;
709
+ }
710
+ function serializeControlPoints(controlPoints) {
711
+ return controlPoints.map(function (cp) {
712
+ var x = formatFloat(cp.x);
713
+ var opacity = formatFloat(cp.opacity);
714
+ // Default color is empty string
715
+ // TODO: Substitute
716
+ var color = isEqual(cp.color, DEFAULT_CONTROL_POINT_COLOR) ? DEFAULT_CONTROL_POINT_COLOR_CODE : colorArrayToHex(cp.color);
717
+ return "".concat(x, ":").concat(opacity, ":").concat(color);
718
+ }).join(":");
719
+ }
720
+ function parseControlPoints(controlPoints) {
721
+ if (!(controlPoints && (CONTROL_POINTS_REGEX.test(controlPoints) || LEGACY_CONTROL_POINTS_REGEX.test(controlPoints)))) {
722
+ return undefined;
723
+ }
724
+
725
+ // Parse raw control point data from the string into an array of [x, opacity, color] triplets.
726
+ var rawControlPointData;
727
+ if (LEGACY_CONTROL_POINTS_REGEX.test(controlPoints)) {
728
+ // Legacy format uses commas to separate control points.
729
+ rawControlPointData = controlPoints.split(",").map(function (cp) {
730
+ return cp.split(":");
731
+ });
732
+ } else {
733
+ // New format is all colon-separated, where every three elements represent a control point.
734
+ rawControlPointData = controlPoints.split(":").reduce(function (acc, _val, i, array) {
735
+ if ((i + 1) % 3 === 0) {
736
+ acc.push([array[i - 2], array[i - 1], array[i]]);
737
+ }
738
+ return acc;
739
+ }, []);
740
+ }
741
+ var newControlPoints = rawControlPointData.map(function (cp) {
742
+ var _parseStringFloat, _parseStringFloat2, _parseHexColorAsColor;
743
+ var _cp = _slicedToArray(cp, 3),
744
+ x = _cp[0],
745
+ opacity = _cp[1],
746
+ color = _cp[2];
747
+ return {
748
+ x: (_parseStringFloat = parseStringFloat(x, -Infinity, Infinity)) !== null && _parseStringFloat !== void 0 ? _parseStringFloat : 0,
749
+ opacity: (_parseStringFloat2 = parseStringFloat(opacity, 0, 1)) !== null && _parseStringFloat2 !== void 0 ? _parseStringFloat2 : 1.0,
750
+ color: (_parseHexColorAsColor = parseHexColorAsColorArray(color)) !== null && _parseHexColorAsColor !== void 0 ? _parseHexColorAsColor : DEFAULT_CONTROL_POINT_COLOR
751
+ };
752
+ });
753
+ // Sort control points by x value
754
+ return newControlPoints.sort(function (a, b) {
755
+ return a.x - b.x;
756
+ });
757
+ }
758
+
759
+ //// DATA SERIALIZATION //////////////////////
760
+
761
+ /**
762
+ * Parses a ViewerChannelSetting from a JSON object.
763
+ * @param channelIndex Index of the channel, to be turned into a `match` value.
764
+ * @param jsonState The serialized ViewerChannelSetting to parse, as an object.
765
+ * @returns A ViewerChannelSetting object.
766
+ */
767
+ export function deserializeViewerChannelSetting(channelIndex, jsonState) {
768
+ // Missing/undefined fields should be handled downstream.
769
+ var result = {
770
+ match: channelIndex,
771
+ enabled: parseStringBoolean(jsonState[ViewerChannelSettingKeys.VolumeEnabled]),
772
+ surfaceEnabled: parseStringBoolean(jsonState[ViewerChannelSettingKeys.SurfaceEnabled]),
773
+ isovalue: parseStringFloat(jsonState[ViewerChannelSettingKeys.IsosurfaceValue], 0, 255),
774
+ surfaceOpacity: parseStringFloat(jsonState[ViewerChannelSettingKeys.IsosurfaceAlpha], 0, 1),
775
+ colorizeEnabled: parseStringBoolean(jsonState[ViewerChannelSettingKeys.Colorize]),
776
+ colorizeAlpha: parseStringFloat(jsonState[ViewerChannelSettingKeys.ColorizeAlpha], 0, 1),
777
+ controlPointsEnabled: parseStringBoolean(jsonState[ViewerChannelSettingKeys.ControlPointsEnabled])
778
+ };
779
+ if (jsonState[ViewerChannelSettingKeys.Color] && HEX_COLOR_REGEX.test(jsonState.col)) {
780
+ result.color = jsonState[ViewerChannelSettingKeys.Color];
781
+ }
782
+ if (jsonState[ViewerChannelSettingKeys.Lut] && LUT_REGEX.test(jsonState.lut)) {
783
+ var _jsonState$ViewerChan = jsonState[ViewerChannelSettingKeys.Lut].split(":"),
784
+ _jsonState$ViewerChan2 = _slicedToArray(_jsonState$ViewerChan, 2),
785
+ min = _jsonState$ViewerChan2[0],
786
+ max = _jsonState$ViewerChan2[1];
787
+ result.lut = [min.trim(), max.trim()];
788
+ }
789
+ if (jsonState[ViewerChannelSettingKeys.Ramp] && RAMP_REGEX.test(jsonState.rmp)) {
790
+ var _jsonState$ViewerChan3 = jsonState[ViewerChannelSettingKeys.Ramp].split(":"),
791
+ _jsonState$ViewerChan4 = _slicedToArray(_jsonState$ViewerChan3, 2),
792
+ _min = _jsonState$ViewerChan4[0],
793
+ _max = _jsonState$ViewerChan4[1];
794
+ result.ramp = [Number.parseFloat(_min), Number.parseFloat(_max)];
795
+ }
796
+ if (jsonState[ViewerChannelSettingKeys.ControlPoints]) {
797
+ result.controlPoints = parseControlPoints(jsonState[ViewerChannelSettingKeys.ControlPoints]);
798
+ }
799
+ return result;
800
+ }
801
+
802
+ /**
803
+ * Serializes a single viewer channel setting into a dictionary of URL parameters
804
+ * (`ViewerChannelSettingParams`).
805
+ * @param channelSetting The channel state object to serialize.
806
+ * @param removeDefaults Whether to remove properties that match the output of `GET_DEFAULT_CHANNEL_STATE`.
807
+ * @returns A `ViewerChannelSettingParams` object with the serialized parameters. Undefined values are removed.
808
+ */
809
+ export function serializeViewerChannelSetting(channelSetting, removeDefaults) {
810
+ var _channelSetting$isova, _channelSetting$opaci, _channelSetting$color, _channelSetting$ramp;
811
+ if (removeDefaults) {
812
+ channelSetting = removeMatchingProperties(channelSetting, getDefaultChannelState());
813
+ }
814
+ return removeUndefinedProperties(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty({}, ViewerChannelSettingKeys.VolumeEnabled, serializeBoolean(channelSetting.volumeEnabled)), ViewerChannelSettingKeys.SurfaceEnabled, serializeBoolean(channelSetting.isosurfaceEnabled)), ViewerChannelSettingKeys.IsosurfaceValue, (_channelSetting$isova = channelSetting.isovalue) === null || _channelSetting$isova === void 0 ? void 0 : _channelSetting$isova.toString()), ViewerChannelSettingKeys.IsosurfaceAlpha, (_channelSetting$opaci = channelSetting.opacity) === null || _channelSetting$opaci === void 0 ? void 0 : _channelSetting$opaci.toString()), ViewerChannelSettingKeys.Colorize, serializeBoolean(channelSetting.colorizeEnabled)), ViewerChannelSettingKeys.ColorizeAlpha, (_channelSetting$color = channelSetting.colorizeAlpha) === null || _channelSetting$color === void 0 ? void 0 : _channelSetting$color.toString()), ViewerChannelSettingKeys.Color, channelSetting.color && colorArrayToHex(channelSetting.color)), ViewerChannelSettingKeys.ControlPoints, channelSetting.controlPoints && serializeControlPoints(channelSetting.controlPoints)), ViewerChannelSettingKeys.ControlPointsEnabled, serializeBoolean(channelSetting.useControlPoints)), ViewerChannelSettingKeys.Ramp, (_channelSetting$ramp = channelSetting.ramp) === null || _channelSetting$ramp === void 0 ? void 0 : _channelSetting$ramp.map(function (value) {
815
+ return formatFloat(value);
816
+ }).join(":")));
817
+ }
818
+ export function deserializeViewerState(params) {
819
+ var result = {
820
+ maskAlpha: parseStringInt(params[ViewerStateKeys.Mask], 0, 100),
821
+ imageType: parseStringEnum(params[ViewerStateKeys.Image], ImageType),
822
+ showAxes: parseStringBoolean(params[ViewerStateKeys.Axes]),
823
+ showBoundingBox: parseStringBoolean(params[ViewerStateKeys.BoundingBox]),
824
+ boundingBoxColor: parseHexColorAsColorArray(params[ViewerStateKeys.BoundingBoxColor]),
825
+ backgroundColor: parseHexColorAsColorArray(params[ViewerStateKeys.BackgroundColor]),
826
+ autorotate: parseStringBoolean(params[ViewerStateKeys.Autorotate]),
827
+ brightness: parseStringFloat(params[ViewerStateKeys.Brightness], 0, 100),
828
+ density: parseStringFloat(params[ViewerStateKeys.Density], 0, 100),
829
+ levels: parseThreeNumberArray(params[ViewerStateKeys.Levels], {
830
+ min: 0,
831
+ max: 255
832
+ }),
833
+ interpolationEnabled: parseStringBoolean(params[ViewerStateKeys.Interpolation]),
834
+ region: parseStringRegion(params[ViewerStateKeys.Region]),
835
+ slice: parseStringSlice(params[ViewerStateKeys.Slice]),
836
+ time: parseStringInt(params[ViewerStateKeys.Time], 0, Number.POSITIVE_INFINITY),
837
+ scene: parseStringInt(params[ViewerStateKeys.Scene], 0, Number.POSITIVE_INFINITY),
838
+ renderMode: parseStringEnum(params[ViewerStateKeys.Mode], RenderMode),
839
+ cameraState: parseCameraState(params[ViewerStateKeys.CameraState])
840
+ };
841
+
842
+ // Handle viewmode, since they use different mappings
843
+ // TODO: Allow lowercase
844
+ if (params.view) {
845
+ var viewParamToViewMode = {
846
+ "3D": ViewMode.threeD,
847
+ Z: ViewMode.xy,
848
+ Y: ViewMode.xz,
849
+ X: ViewMode.yz
850
+ };
851
+ var allowedViews = Object.keys(viewParamToViewMode);
852
+ var view;
853
+ if (allowedViews.includes(params.view.toUpperCase())) {
854
+ view = params.view.toUpperCase();
855
+ } else {
856
+ view = "3D";
857
+ }
858
+ result.viewMode = viewParamToViewMode[view];
859
+ }
860
+ return removeUndefinedProperties(result);
861
+ }
862
+
863
+ /**
864
+ * Serializes a ViewerState object into a dictionary of URL parameters.
865
+ * @param state The ViewerState to serialize.
866
+ * @param removeDefaults If true, remove properties that match the output of `GET_DEFAULT_VIEWER_STATE`.
867
+ * @returns A `ViewerStateParams` object with the serialized parameters. Undefined values are removed.
868
+ */
869
+ export function serializeViewerState(state, removeDefaults) {
870
+ var _state$maskAlpha, _state$brightness, _state$density, _state$levels, _state$time, _state$scene, _result;
871
+ if (removeDefaults) {
872
+ state = removeMatchingProperties(state, getDefaultViewerState());
873
+ }
874
+ var result = (_result = {}, _defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_result, ViewerStateKeys.Mode, state.renderMode), ViewerStateKeys.Mask, (_state$maskAlpha = state.maskAlpha) === null || _state$maskAlpha === void 0 ? void 0 : _state$maskAlpha.toString()), ViewerStateKeys.Image, state.imageType), ViewerStateKeys.Axes, serializeBoolean(state.showAxes)), ViewerStateKeys.BoundingBox, serializeBoolean(state.showBoundingBox)), ViewerStateKeys.BoundingBoxColor, state.boundingBoxColor && colorArrayToHex(state.boundingBoxColor)), ViewerStateKeys.BackgroundColor, state.backgroundColor && colorArrayToHex(state.backgroundColor)), ViewerStateKeys.Autorotate, serializeBoolean(state.autorotate)), ViewerStateKeys.Brightness, (_state$brightness = state.brightness) === null || _state$brightness === void 0 ? void 0 : _state$brightness.toString()), ViewerStateKeys.Density, (_state$density = state.density) === null || _state$density === void 0 ? void 0 : _state$density.toString()), _defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_result, ViewerStateKeys.Interpolation, serializeBoolean(state.interpolationEnabled)), ViewerStateKeys.Region, state.region && serializeRegion(state.region)), ViewerStateKeys.Slice, state.slice && serializeSlice(state.slice)), ViewerStateKeys.Levels, (_state$levels = state.levels) === null || _state$levels === void 0 ? void 0 : _state$levels.join(",")), ViewerStateKeys.Time, (_state$time = state.time) === null || _state$time === void 0 ? void 0 : _state$time.toString()), ViewerStateKeys.Scene, (_state$scene = state.scene) === null || _state$scene === void 0 ? void 0 : _state$scene.toString()), ViewerStateKeys.CameraState, state.cameraState && serializeCameraState(state.cameraState, removeDefaults, state.viewMode)));
875
+ var viewModeToViewParam = _defineProperty(_defineProperty(_defineProperty(_defineProperty({}, ViewMode.threeD, "3D"), ViewMode.xy, "Z"), ViewMode.xz, "Y"), ViewMode.yz, "X");
876
+ result[ViewerStateKeys.View] = state.viewMode && viewModeToViewParam[state.viewMode];
877
+ return removeUndefinedProperties(result);
878
+ }
879
+ function parseDeprecatedChannelSettings(params) {
880
+ // old, deprecated channels model
881
+ if (params.ch) {
882
+ // ?ch=1,2
883
+ // ?luts=0,255,0,255
884
+ // ?colors=ff0000,00ff00
885
+ var initialChannelSettings = {
886
+ groups: [{
887
+ name: "Channels",
888
+ channels: []
889
+ }]
890
+ };
891
+ var ch = initialChannelSettings.groups[0].channels;
892
+ var channelsOn = params.ch.split(",").map(function (numstr) {
893
+ return Number.parseInt(numstr, 10);
894
+ });
895
+ for (var i = 0; i < channelsOn.length; ++i) {
896
+ ch.push({
897
+ match: channelsOn[i],
898
+ enabled: true
899
+ });
900
+ }
901
+ // look for luts or color
902
+ if (params.luts) {
903
+ var luts = params.luts.split(",");
904
+ if (luts.length !== ch.length * 2) {
905
+ console.warn("ILL-FORMED QUERYSTRING: luts must have a min/max for each ch");
906
+ } else {
907
+ for (var _i = 0; _i < ch.length; ++_i) {
908
+ ch[_i]["lut"] = [luts[_i * 2], luts[_i * 2 + 1]];
909
+ }
910
+ }
911
+ }
912
+ if (params.colors) {
913
+ var colors = params.colors.split(",");
914
+ if (colors.length !== ch.length) {
915
+ console.warn("ILL-FORMED QUERYSTRING: if colors specified, must have a color for each ch");
916
+ } else {
917
+ for (var _i2 = 0; _i2 < ch.length; ++_i2) {
918
+ ch[_i2]["color"] = colors[_i2];
919
+ }
920
+ }
921
+ }
922
+ return initialChannelSettings;
923
+ }
924
+ return undefined;
925
+ }
926
+ function parseChannelSettings(params) {
927
+ // Channels keys are formatted as `c0`, `c1`, etc., and the value is string containing
928
+ // a comma-separated list of key-value pairs.
929
+ var channelIndexToSettings = new Map();
930
+ Object.keys(params).forEach(function (key) {
931
+ if (isChannelKey(key)) {
932
+ var channelIndex = Number.parseInt(key.slice(1), 10);
933
+ try {
934
+ var channelData = parseKeyValueList(params[key]);
935
+ var channelSetting = deserializeViewerChannelSetting(channelIndex, channelData);
936
+ channelIndexToSettings.set(channelIndex, channelSetting);
937
+ } catch (e) {
938
+ console.warn("url_utils.getArgsFromParams: Failed to parse channel settings for channel ".concat(channelIndex, " from URL parameters."), e);
939
+ }
940
+ }
941
+ });
942
+ if (channelIndexToSettings.size > 0) {
943
+ var groups = [{
944
+ name: "Channels",
945
+ channels: Array.from(channelIndexToSettings.values())
946
+ }];
947
+ return {
948
+ groups: groups
949
+ };
950
+ }
951
+ return undefined;
952
+ }
953
+
954
+ //// FULL URL PARSING //////////////////////
955
+ function loadDataset(_x, _x2, _x3) {
956
+ return _loadDataset.apply(this, arguments);
957
+ }
958
+ function _loadDataset() {
959
+ _loadDataset = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(firestore, dataset, id) {
960
+ var db, args, datasets, datasetMeta, _iterator4, _step4, d, innerDatasets, names, matchingName, datasetData, baseUrl, fileInfo;
961
+ return _regeneratorRuntime().wrap(function _callee$(_context) {
962
+ while (1) switch (_context.prev = _context.next) {
963
+ case 0:
964
+ db = new FirebaseRequest(firestore);
965
+ args = {};
966
+ _context.next = 4;
967
+ return db.getAvailableDatasets();
968
+ case 4:
969
+ datasets = _context.sent;
970
+ datasetMeta = undefined;
971
+ _iterator4 = _createForOfIteratorHelper(datasets);
972
+ _context.prev = 7;
973
+ _iterator4.s();
974
+ case 9:
975
+ if ((_step4 = _iterator4.n()).done) {
976
+ _context.next = 19;
977
+ break;
978
+ }
979
+ d = _step4.value;
980
+ innerDatasets = d.datasets;
981
+ names = Object.keys(innerDatasets);
982
+ matchingName = names.find(function (name) {
983
+ return name === dataset;
984
+ });
985
+ if (!matchingName) {
986
+ _context.next = 17;
987
+ break;
988
+ }
989
+ datasetMeta = innerDatasets[matchingName];
990
+ return _context.abrupt("break", 19);
991
+ case 17:
992
+ _context.next = 9;
993
+ break;
994
+ case 19:
995
+ _context.next = 24;
996
+ break;
997
+ case 21:
998
+ _context.prev = 21;
999
+ _context.t0 = _context["catch"](7);
1000
+ _iterator4.e(_context.t0);
1001
+ case 24:
1002
+ _context.prev = 24;
1003
+ _iterator4.f();
1004
+ return _context.finish(24);
1005
+ case 27:
1006
+ if (!(datasetMeta === undefined)) {
1007
+ _context.next = 30;
1008
+ break;
1009
+ }
1010
+ console.error("No matching dataset: ".concat(dataset));
1011
+ return _context.abrupt("return", {});
1012
+ case 30:
1013
+ _context.next = 32;
1014
+ return db.selectDataset(datasetMeta.manifest);
1015
+ case 32:
1016
+ datasetData = _context.sent;
1017
+ baseUrl = datasetData.volumeViewerDataRoot + "/";
1018
+ args.imageDownloadHref = datasetData.downloadRoot + "/" + id;
1019
+ // args.fovDownloadHref = datasetData.downloadRoot + "/" + id;
1020
+ _context.next = 37;
1021
+ return db.getFileInfoByCellId(id);
1022
+ case 37:
1023
+ fileInfo = _context.sent;
1024
+ args.imageUrl = baseUrl + fileInfo.volumeviewerPath;
1025
+ args.parentImageUrl = baseUrl + fileInfo.fovVolumeviewerPath;
1026
+ return _context.abrupt("return", args);
1027
+ case 41:
1028
+ case "end":
1029
+ return _context.stop();
1030
+ }
1031
+ }, _callee, null, [[7, 21, 24, 27]]);
1032
+ }));
1033
+ return _loadDataset.apply(this, arguments);
1034
+ }
1035
+ function isStringArray(arr) {
1036
+ return Array.isArray(arr) && arr.every(function (item) {
1037
+ return typeof item === "string";
1038
+ });
1039
+ }
1040
+ function isValidScenesArray(arr) {
1041
+ return Array.isArray(arr) && arr.every(function (item) {
1042
+ return typeof item === "string" || isStringArray(item);
1043
+ });
1044
+ }
1045
+ export function loadFromManifest(_x4) {
1046
+ return _loadFromManifest.apply(this, arguments);
1047
+ }
1048
+
1049
+ /**
1050
+ * Parses a set of URL search parameters into props for the viewer.
1051
+ * @param urlSearchParams The URLSearchParams object to parse.
1052
+ * @param firestore Optional Firestore instance. If provided, the function can
1053
+ * load data from a Firestore dataset if the `dataset` and `id` parameters are
1054
+ * provided.
1055
+ * @returns An object containing:
1056
+ * - `args`: Partial AppProps object.
1057
+ * - `viewerSettings`: Partial ViewerState object.
1058
+ *
1059
+ * `args` can be passed as props to the `ImageViewerApp`, and `viewerSettings`
1060
+ * can be passed to `ViewerStateProvider`.
1061
+ */
1062
+ function _loadFromManifest() {
1063
+ _loadFromManifest = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(manifestUrl) {
1064
+ var response, manifestJson, scenes, metadata;
1065
+ return _regeneratorRuntime().wrap(function _callee2$(_context2) {
1066
+ while (1) switch (_context2.prev = _context2.next) {
1067
+ case 0:
1068
+ _context2.prev = 0;
1069
+ _context2.next = 3;
1070
+ return fetch(manifestUrl);
1071
+ case 3:
1072
+ response = _context2.sent;
1073
+ _context2.next = 10;
1074
+ break;
1075
+ case 6:
1076
+ _context2.prev = 6;
1077
+ _context2.t0 = _context2["catch"](0);
1078
+ console.error(_context2.t0);
1079
+ throw new Error("JSON manifest could not be fetched from URL '".concat(manifestUrl, "': ").concat(_context2.t0));
1080
+ case 10:
1081
+ if (response.ok) {
1082
+ _context2.next = 12;
1083
+ break;
1084
+ }
1085
+ throw new Error("JSON manifest could not be fetched from URL '".concat(manifestUrl, "': Received ").concat(response.status, " ").concat(response.statusText));
1086
+ case 12:
1087
+ _context2.prev = 12;
1088
+ _context2.next = 15;
1089
+ return response.json();
1090
+ case 15:
1091
+ manifestJson = _context2.sent;
1092
+ _context2.next = 21;
1093
+ break;
1094
+ case 18:
1095
+ _context2.prev = 18;
1096
+ _context2.t1 = _context2["catch"](12);
1097
+ throw new Error("Could not parse JSON manifest from URL '".concat(manifestUrl, "': ").concat(_context2.t1));
1098
+ case 21:
1099
+ // Parse scenes
1100
+ scenes = manifestJson.scenes;
1101
+ if (!(scenes === undefined)) {
1102
+ _context2.next = 24;
1103
+ break;
1104
+ }
1105
+ throw new Error("No 'scenes' property was found in JSON manifest from URL '".concat(manifestUrl, "'"));
1106
+ case 24:
1107
+ if (typeof scenes === "string") {
1108
+ scenes = [scenes];
1109
+ }
1110
+ if (!(!Array.isArray(scenes) || scenes.length === 0 || !isValidScenesArray(scenes))) {
1111
+ _context2.next = 27;
1112
+ break;
1113
+ }
1114
+ throw new Error("Invalid 'scenes' property found in JSON manifest from URL '".concat(manifestUrl, "'. 'scenes' must be a non-empty array of strings or string arrays."));
1115
+ case 27:
1116
+ // Parse metadata
1117
+ metadata = undefined;
1118
+ if (manifestJson.meta !== undefined && Array.isArray(manifestJson.meta)) {
1119
+ metadata = manifestJson.meta;
1120
+ }
1121
+ return _context2.abrupt("return", {
1122
+ scenes: scenes,
1123
+ metadata: metadata
1124
+ });
1125
+ case 30:
1126
+ case "end":
1127
+ return _context2.stop();
1128
+ }
1129
+ }, _callee2, null, [[0, 6], [12, 18]]);
1130
+ }));
1131
+ return _loadFromManifest.apply(this, arguments);
1132
+ }
1133
+ export function parseViewerUrlParams(_x5, _x6) {
1134
+ return _parseViewerUrlParams.apply(this, arguments);
1135
+ }
1136
+
1137
+ /**
1138
+ * Serializes the ViewerState and ChannelState of a ViewerStateContext into a URLSearchParams object.
1139
+ * @param state ViewerStateContext to serialize.
1140
+ * @param removeDefaults If true, shortens parameters by removing any properties that match the default state.
1141
+ * This includes the output of GET_DEFAULT_VIEWER_STATE and GET_DEFAULT_CHANNEL_STATE.
1142
+ */
1143
+ function _parseViewerUrlParams() {
1144
+ _parseViewerUrlParams = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(urlSearchParams, firestore) {
1145
+ var params, args, viewerSettings, deprecatedChannelSettings, channelSettings, scenes, _yield$loadFromManife, manifestScenes, manifestMetadata, _localStorage$getItem, _tryDecodeURLList, getFromStorage, urlParam, sceneUrls, metadataJson, firstScene, firstUrl, imageUrls, datasetArgs;
1146
+ return _regeneratorRuntime().wrap(function _callee3$(_context3) {
1147
+ while (1) switch (_context3.prev = _context3.next) {
1148
+ case 0:
1149
+ params = getAllowedParams(urlSearchParams);
1150
+ args = {}; // Parse viewer state
1151
+ viewerSettings = deserializeViewerState(params); // Parse channel settings. If per-channel settings are provided, they will override
1152
+ // the old `ch` query parameter.
1153
+ deprecatedChannelSettings = parseDeprecatedChannelSettings(params);
1154
+ channelSettings = parseChannelSettings(params);
1155
+ args.viewerChannelSettings = channelSettings !== null && channelSettings !== void 0 ? channelSettings : deprecatedChannelSettings;
1156
+
1157
+ // Parse data sources (URL or dataset/id pair)
1158
+ if (!(params.manifest !== undefined || params.url !== undefined)) {
1159
+ _context3.next = 33;
1160
+ break;
1161
+ }
1162
+ if (!params.manifest) {
1163
+ _context3.next = 17;
1164
+ break;
1165
+ }
1166
+ _context3.next = 10;
1167
+ return loadFromManifest(params.manifest);
1168
+ case 10:
1169
+ _yield$loadFromManife = _context3.sent;
1170
+ manifestScenes = _yield$loadFromManife.scenes;
1171
+ manifestMetadata = _yield$loadFromManife.metadata;
1172
+ scenes = manifestScenes;
1173
+ args.metadata = manifestMetadata !== null && manifestMetadata !== void 0 ? manifestMetadata : undefined;
1174
+ _context3.next = 22;
1175
+ break;
1176
+ case 17:
1177
+ // Load from URL
1178
+ getFromStorage = params.url === URL_FETCH_FROM_STORAGE;
1179
+ urlParam = getFromStorage ? (_localStorage$getItem = localStorage.getItem("url")) !== null && _localStorage$getItem !== void 0 ? _localStorage$getItem : params.url : params.url; // split encoded url into a list of one or more scenes...
1180
+ sceneUrls = (_tryDecodeURLList = tryDecodeURLList(urlParam, /[+ ]/)) !== null && _tryDecodeURLList !== void 0 ? _tryDecodeURLList : [urlParam]; // ...and each scene into a list of multiple sources, if any.
1181
+ scenes = sceneUrls.map(function (scene) {
1182
+ var _tryDecodeURLList2;
1183
+ return (_tryDecodeURLList2 = tryDecodeURLList(scene)) !== null && _tryDecodeURLList2 !== void 0 ? _tryDecodeURLList2 : decodeURL(scene);
1184
+ });
1185
+ if (getFromStorage) {
1186
+ metadataJson = localStorage.getItem("meta");
1187
+ args.metadata = metadataJson !== null ? JSON.parse(metadataJson) : undefined;
1188
+ }
1189
+ case 22:
1190
+ firstScene = scenes[0]; // Get the very first URL for the download button
1191
+ firstUrl = Array.isArray(firstScene) ? firstScene[0] : firstScene; // If there's only one url, just pass that
1192
+ imageUrls = scenes.length > 1 || firstScene.length > 1 ? {
1193
+ scenes: scenes
1194
+ } : firstScene[0];
1195
+ args.cellId = "1";
1196
+ args.imageUrl = imageUrls;
1197
+ // this is invalid for zarr?
1198
+ args.imageDownloadHref = firstUrl;
1199
+ args.parentImageUrl = "";
1200
+ args.parentImageDownloadHref = "";
1201
+ // Check if channel settings are already provided (through per-channel settings or
1202
+ // old `ch` query param, or included in JSON files). If not, make first three
1203
+ // channels visible by default.
1204
+ if (!firstUrl.endsWith("json") && !args.viewerChannelSettings) {
1205
+ args.viewerChannelSettings = {
1206
+ groups: [
1207
+ // first 3 channels on by default!
1208
+ {
1209
+ name: "Channels",
1210
+ channels: [{
1211
+ match: [0, 1, 2],
1212
+ enabled: true
1213
+ }, {
1214
+ match: "(.+)",
1215
+ enabled: false
1216
+ }]
1217
+ }]
1218
+ };
1219
+ }
1220
+ _context3.next = 38;
1221
+ break;
1222
+ case 33:
1223
+ if (!(params.dataset && params.id && firestore)) {
1224
+ _context3.next = 38;
1225
+ break;
1226
+ }
1227
+ _context3.next = 36;
1228
+ return loadDataset(firestore, params.dataset, params.id);
1229
+ case 36:
1230
+ datasetArgs = _context3.sent;
1231
+ args = _objectSpread(_objectSpread({}, args), datasetArgs);
1232
+ case 38:
1233
+ return _context3.abrupt("return", {
1234
+ args: removeUndefinedProperties(args),
1235
+ viewerSettings: removeUndefinedProperties(viewerSettings)
1236
+ });
1237
+ case 39:
1238
+ case "end":
1239
+ return _context3.stop();
1240
+ }
1241
+ }, _callee3);
1242
+ }));
1243
+ return _parseViewerUrlParams.apply(this, arguments);
1244
+ }
1245
+ export function serializeViewerUrlParams(state) {
1246
+ var _state$channelSetting;
1247
+ var removeDefaults = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
1248
+ var params = serializeViewerState(state, removeDefaults);
1249
+ var channelParams = (_state$channelSetting = state.channelSettings) === null || _state$channelSetting === void 0 ? void 0 : _state$channelSetting.reduce(function (acc, channelSetting, index) {
1250
+ var key = "c".concat(index);
1251
+ acc[key] = objectToKeyValueList(serializeViewerChannelSetting(channelSetting, removeDefaults));
1252
+ return acc;
1253
+ }, {});
1254
+ return _objectSpread(_objectSpread({}, params), channelParams);
1255
+ }