@aics/vole-app 3.3.0 → 3.4.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.
Files changed (60) hide show
  1. package/LICENSE +21 -25
  2. package/es/aics-image-viewer/components/App/index.js +11 -9
  3. package/es/aics-image-viewer/components/BottomPanel/index.js +48 -19
  4. package/es/aics-image-viewer/components/BottomPanel/styles.css +16 -7
  5. package/es/aics-image-viewer/components/CellViewerCanvasWrapper/index.js +39 -19
  6. package/es/aics-image-viewer/components/ChannelsWidget.js +2 -2
  7. package/es/aics-image-viewer/components/ControlPanel/index.js +17 -11
  8. package/es/aics-image-viewer/components/ControlPanel/styles.css +5 -5
  9. package/es/aics-image-viewer/components/ErrorAlert/index.js +91 -64
  10. package/es/aics-image-viewer/components/ErrorAlert/styles.css +33 -4
  11. package/es/aics-image-viewer/components/StyleProvider/index.js +42 -22
  12. package/es/aics-image-viewer/components/TfEditor/index.js +8 -1
  13. package/es/aics-image-viewer/components/Toolbar/index.js +33 -12
  14. package/es/aics-image-viewer/components/Toolbar/styles.css +21 -130
  15. package/es/aics-image-viewer/components/dimension_sliders/AxisClipSliders.js +148 -0
  16. package/es/aics-image-viewer/components/dimension_sliders/RotationSliders.js +165 -0
  17. package/es/aics-image-viewer/components/dimension_sliders/SliderRows.js +167 -0
  18. package/es/aics-image-viewer/components/{AxisClipSliders → dimension_sliders}/styles.css +7 -1
  19. package/es/aics-image-viewer/components/shared/ControlPanelRow/styles.css +1 -1
  20. package/es/aics-image-viewer/components/shared/NumericInput/index.js +4 -2
  21. package/es/aics-image-viewer/components/shared/SliderRow/index.js +2 -0
  22. package/es/aics-image-viewer/components/shared/SliderRow/styles.css +2 -1
  23. package/es/aics-image-viewer/components/useVolume.js +3 -0
  24. package/es/aics-image-viewer/shared/constants.js +2 -2
  25. package/es/aics-image-viewer/shared/utils/camera.js +122 -0
  26. package/es/aics-image-viewer/shared/utils/playControls.js +12 -1
  27. package/es/aics-image-viewer/shared/utils/sceneStore.js +8 -0
  28. package/es/aics-image-viewer/shared/utils/test/camera.test.js +127 -0
  29. package/es/aics-image-viewer/shared/utils/test/urlParsing.test.js +23 -702
  30. package/es/aics-image-viewer/shared/utils/urlParsing.js +14 -828
  31. package/es/aics-image-viewer/shared/utils/viewerChannelSettings.js +3 -4
  32. package/es/aics-image-viewer/state/deserialize.js +437 -0
  33. package/es/aics-image-viewer/state/serialize.js +145 -0
  34. package/es/aics-image-viewer/state/test/deserialize.test.js +432 -0
  35. package/es/aics-image-viewer/state/test/serialize.test.js +97 -0
  36. package/es/aics-image-viewer/state/test/test_data.js +168 -0
  37. package/es/aics-image-viewer/state/types.js +265 -1
  38. package/package.json +6 -5
  39. package/type-declarations/aics-image-viewer/components/App/types.d.ts +2 -2
  40. package/type-declarations/aics-image-viewer/components/BottomPanel/index.d.ts +6 -3
  41. package/type-declarations/aics-image-viewer/components/CellViewerCanvasWrapper/index.d.ts +1 -0
  42. package/type-declarations/aics-image-viewer/components/ControlPanel/index.d.ts +4 -5
  43. package/type-declarations/aics-image-viewer/components/ErrorAlert/index.d.ts +8 -5
  44. package/type-declarations/aics-image-viewer/components/Toolbar/index.d.ts +2 -1
  45. package/type-declarations/aics-image-viewer/components/{AxisClipSliders/index.d.ts → dimension_sliders/AxisClipSliders.d.ts} +2 -3
  46. package/type-declarations/aics-image-viewer/components/dimension_sliders/RotationSliders.d.ts +6 -0
  47. package/type-declarations/aics-image-viewer/components/dimension_sliders/SliderRows.d.ts +31 -0
  48. package/type-declarations/aics-image-viewer/components/shared/NumericInput/index.d.ts +1 -0
  49. package/type-declarations/aics-image-viewer/components/shared/SliderRow/index.d.ts +3 -1
  50. package/type-declarations/aics-image-viewer/components/useVolume.d.ts +1 -1
  51. package/type-declarations/aics-image-viewer/shared/constants.d.ts +1 -1
  52. package/type-declarations/aics-image-viewer/shared/utils/camera.d.ts +19 -0
  53. package/type-declarations/aics-image-viewer/shared/utils/playControls.d.ts +1 -0
  54. package/type-declarations/aics-image-viewer/shared/utils/sceneStore.d.ts +2 -1
  55. package/type-declarations/aics-image-viewer/shared/utils/urlParsing.d.ts +1 -307
  56. package/type-declarations/aics-image-viewer/state/deserialize.d.ts +70 -0
  57. package/type-declarations/aics-image-viewer/state/serialize.d.ts +20 -0
  58. package/type-declarations/aics-image-viewer/state/types.d.ts +216 -0
  59. package/LICENSE.txt +0 -26
  60. package/es/aics-image-viewer/components/AxisClipSliders/index.js +0 -295
@@ -48,3 +48,219 @@ export type ChannelState = {
48
48
  */
49
49
  keepIntensityRange: boolean;
50
50
  };
51
+ /**
52
+ * Enum keys for serialized viewer settings. These are stored as enums for
53
+ * better readability, and are mapped to types in `ViewerStateParams`.
54
+ */
55
+ export declare enum ViewerStateKeys {
56
+ View = "view",
57
+ Mode = "mode",
58
+ Mask = "mask",
59
+ Image = "image",
60
+ Axes = "axes",
61
+ BoundingBox = "bb",
62
+ BoundingBoxColor = "bbcol",
63
+ BackgroundColor = "bgcol",
64
+ Autorotate = "rot",
65
+ Brightness = "bright",
66
+ Density = "dens",
67
+ Levels = "lvl",
68
+ Interpolation = "interp",
69
+ Region = "reg",
70
+ Slice = "slice",
71
+ Time = "t",
72
+ Scene = "scene",
73
+ CameraState = "cam",
74
+ SingleChannelMode = "scm",
75
+ SingleChannelIndex = "sci",
76
+ UseExactScaleLevel = "esl",
77
+ ScaleLevelIndex = "scl"
78
+ }
79
+ export declare enum CameraTransformKeys {
80
+ /** Camera position in 3D coordinates. */
81
+ Position = "pos",
82
+ /** Target position of the trackball controls in 3D coordinates. */
83
+ Target = "tar",
84
+ /** The up vector of the camera. Will be normalized to magnitude of 1. */
85
+ Up = "up",
86
+ /** Scale factor for orthographic cameras. */
87
+ OrthoScale = "ort",
88
+ /** Vertical FOV of the camera view frustum, from top to bottom, in degrees. */
89
+ Fov = "fov"
90
+ }
91
+ /** Serialized version of `ViewerState`. */
92
+ export declare class ViewerStateParams {
93
+ /** Axis to view. Valid values are "3D", "X", "Y", and "Z". Defaults to "3D". */
94
+ [ViewerStateKeys.View]?: string;
95
+ /**
96
+ * Render mode. Valid values are "volumetric", "maxproject", and "pathtrace".
97
+ * Defaults to "volumetric".
98
+ */
99
+ [ViewerStateKeys.Mode]?: string;
100
+ /** The opacity of the mask channel, an integer in the range [0, 100]. Defaults to 50. */
101
+ [ViewerStateKeys.Mask]?: string;
102
+ /** The type of image to display. Valid values are "cell" and "fov". Defaults to "cell". */
103
+ [ViewerStateKeys.Image]?: string;
104
+ /** Whether to show the axes helper. "1" is enabled. Disabled by default. */
105
+ [ViewerStateKeys.Axes]?: string;
106
+ /** Whether to show the bounding box. "1" is enabled. Disabled by default. */
107
+ [ViewerStateKeys.BoundingBox]?: string;
108
+ /** Whether single-channel mode is active. "1" is active. Inactive by default. */
109
+ [ViewerStateKeys.SingleChannelMode]?: string;
110
+ /** If single-channel mode is active, which channel index is shown. Defaults to 0. */
111
+ [ViewerStateKeys.SingleChannelIndex]?: string;
112
+ /** The color of the bounding box, as a 6-digit hex color. */
113
+ [ViewerStateKeys.BoundingBoxColor]?: string;
114
+ /** The background color, as a 6-digit hex color. */
115
+ [ViewerStateKeys.BackgroundColor]?: string;
116
+ /** Whether to autorotate the view. "1" is enabled. Disabled by default. */
117
+ [ViewerStateKeys.Autorotate]?: string;
118
+ /** The brightness of the image, an float in the range [0, 100]. Defaults to 70. */
119
+ [ViewerStateKeys.Brightness]?: string;
120
+ /** Density, a float in the range [0, 100]. Defaults to 50. */
121
+ [ViewerStateKeys.Density]?: string;
122
+ /**
123
+ * Levels for image intensity adjustment. Should be three numeric values separated
124
+ * by commas, representing the low, middle, and high values in a [0, 255] range.
125
+ * Values will be sorted in ascending order; empty values will be parsed as 0.
126
+ */
127
+ [ViewerStateKeys.Levels]?: string;
128
+ /** Whether to enable interpolation. "1" is enabled. Enabled by default. */
129
+ [ViewerStateKeys.Interpolation]?: string;
130
+ /** Subregions per axis, as min:max pairs separated by commas.
131
+ * Defaults to full range (`0:1`) for each axis.
132
+ */
133
+ [ViewerStateKeys.Region]?: string;
134
+ /** Slice position per X, Y, and Z axes, as a list of comma-separated floats.
135
+ * 0.5 for all axes by default (e.g. `0.5,0.5,0.5`)
136
+ */
137
+ [ViewerStateKeys.Slice]?: string;
138
+ /** Frame number, for time-series volumes. 0 by default. */
139
+ [ViewerStateKeys.Time]?: string;
140
+ /** Scene number, for multiscene images. 0 by default. */
141
+ [ViewerStateKeys.Scene]?: string;
142
+ /** Whether to use an exact scale level index. 0 by default. */
143
+ [ViewerStateKeys.UseExactScaleLevel]?: string;
144
+ /** The exact scale level index to use, if `UseExactScaleLevel` is 1. 0 by default. */
145
+ [ViewerStateKeys.ScaleLevelIndex]?: string;
146
+ /**
147
+ * Camera transform settings, as a list of `key:value` pairs separated by commas.
148
+ * Valid keys are defined in `CameraTransformKeys`:
149
+ * - `pos`: position
150
+ * - `tar`: target
151
+ * - `up`: up
152
+ * - `ort`: orthographic scale
153
+ * - `fov`: field of view
154
+ *
155
+ * Vector values are encoded as three floats separated by colons (e.g. `1:2:3`) and
156
+ * encoded using `encodeURIComponent`.
157
+ */
158
+ [ViewerStateKeys.CameraState]?: string;
159
+ }
160
+ /**
161
+ * Mapped to types in `ViewerChannelStateParams`.
162
+ */
163
+ export declare enum ViewerChannelSettingKeys {
164
+ Color = "col",
165
+ Colorize = "clz",
166
+ ColorizeAlpha = "cza",
167
+ IsosurfaceAlpha = "isa",
168
+ Lut = "lut",
169
+ ControlPoints = "cpt",
170
+ ControlPointsLegacy = "cps",
171
+ Ramp = "ram",
172
+ RampLegacy = "rmp",
173
+ ControlPointsEnabled = "cpe",
174
+ VolumeEnabled = "ven",
175
+ SurfaceEnabled = "sen",
176
+ IsosurfaceValue = "isv",
177
+ KeepRange = "pin"
178
+ }
179
+ /**
180
+ * The serialized form of a ViewerChannelSetting, as a dictionary object.
181
+ */
182
+ export declare class ViewerChannelStateParams {
183
+ /** Color, as a 6-digit hex color. */
184
+ [ViewerChannelSettingKeys.Color]?: string;
185
+ /** Colorize. "1" is enabled. Disabled by default. */
186
+ [ViewerChannelSettingKeys.Colorize]?: "1" | "0";
187
+ /** Colorize alpha, in the [0, 1] range. Set to `1.0` by default. */
188
+ [ViewerChannelSettingKeys.ColorizeAlpha]?: string;
189
+ /** Isosurface alpha, in the [0, 1 range]. Set to `1.0` by default.*/
190
+ [ViewerChannelSettingKeys.IsosurfaceAlpha]?: string;
191
+ /**
192
+ * Lookup table (LUT) to map from volume intensity to opacity. Should be two
193
+ * alphanumeric values separated by a colon, where the first value is the
194
+ * minimum and the second is the maximum. Defaults to [0, 255].
195
+ *
196
+ * Min and max values are determined as following:
197
+ * - Plain numbers are indices of histogram bins, typically in the range [0,
198
+ * 255].
199
+ * - `v{n}` represents a raw intensity value, where `n` is a number.
200
+ * - `p{n}` represents a percentile, where `n` is a percentile in the [0, 100]
201
+ * range.
202
+ * - `m{n}` represents the median multiplied by `n / 100`.
203
+ * - `autoij` in either the min or max fields will use the "auto" algorithm
204
+ * from ImageJ to select the min AND max.
205
+ *
206
+ * Values will be used to determine the initial control points and ramp if
207
+ * those fields are not provided.
208
+ *
209
+ * @example
210
+ * ```
211
+ * "0:255" // min: intensity 0, max: intensity 255.
212
+ * "p50:p90" // min: 50th percentile, max: 90th percentile.
213
+ * "m1:p75" // min: median, max: 75th percentile.
214
+ * "autoij:0" // use Auto-IJ to calculate min and max.
215
+ * ```
216
+ */
217
+ [ViewerChannelSettingKeys.Lut]?: string;
218
+ /**
219
+ * Legacy specifier for control points for the transfer function as a list of
220
+ * `x:opacity:color` triplets, separated by colon. Uses histogram bin indices
221
+ * instead of intensity values.
222
+ * - `x` is a histogram bin index in the [0, 255] range.
223
+ * - `opacity` is a float in the [0, 1] range.
224
+ * - `color` is a 6-digit hex color, e.g. `ff0000`.
225
+ *
226
+ * Will be overridden by the ControlPoints field (`cpt`) if provided.
227
+ */
228
+ [ViewerChannelSettingKeys.ControlPointsLegacy]?: string;
229
+ /**
230
+ * Control points for the transfer function, formatted as a list of
231
+ * `x:opacity:color` triplets, separated by colons.
232
+ * - `x` is a numeric intensity value.
233
+ * - `opacity` is a float in the [0, 1] range.
234
+ * - `color` is a 6-digit hex color, e.g. `ff0000`.
235
+ *
236
+ * If provided, overrides the `lut` field when calculating the control points.
237
+ */
238
+ [ViewerChannelSettingKeys.ControlPoints]?: string;
239
+ /**
240
+ * Whether to show advanced mode, which will show control points instead of
241
+ * ramp values defined by the LUT. "1" is enabled, disabled by default.
242
+ */
243
+ [ViewerChannelSettingKeys.ControlPointsEnabled]?: "1" | "0";
244
+ /**
245
+ * Legacy specifier for the transfer function ramp which uses histogram bin
246
+ * indices instead of intensity values, formatted as `min:max`. Will be
247
+ * overridden by the Ramp field (`ram`) if provided.
248
+ */
249
+ [ViewerChannelSettingKeys.RampLegacy]?: string;
250
+ /**
251
+ * Ramp min and max intensity values (`min:max`). If provided, overrides the
252
+ * `lut` field when calculating the ramp.
253
+ */
254
+ [ViewerChannelSettingKeys.Ramp]?: string;
255
+ /** Volume enabled. "1" is enabled. Disabled by default. */
256
+ [ViewerChannelSettingKeys.VolumeEnabled]?: "1" | "0";
257
+ /** Isosurface enabled. "1" is enabled. Disabled by default. */
258
+ [ViewerChannelSettingKeys.SurfaceEnabled]?: "1" | "0";
259
+ /** Isosurface value, in the [0, 255] range. Set to `128` by default. */
260
+ [ViewerChannelSettingKeys.IsosurfaceValue]?: string;
261
+ /**
262
+ * Whether to keep the current contrast settings when loading a new volume.
263
+ * "1" is enabled. Disabled by default.
264
+ */
265
+ [ViewerChannelSettingKeys.KeepRange]?: "1" | "0";
266
+ }
package/LICENSE.txt DELETED
@@ -1,26 +0,0 @@
1
- Allen Institute Software License – This software license is the 2-clause BSD license
2
- plus clause a third clause that prohibits redistribution for commercial purposes without further permission.
3
-
4
- Copyright © 2017. Allen Institute. All rights reserved.
5
-
6
- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
7
- following conditions are met:
8
-
9
- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
10
- following disclaimer.
11
-
12
- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
13
- following disclaimer in the documentation and/or other materials provided with the distribution.
14
-
15
- 3. Redistributions for commercial purposes are not permitted without the Allen Institute’s written permission.
16
- For purposes of this license, commercial purposes is the incorporation of the Allen Institute's software into
17
- anything for which you will charge fees or other compensation. Contact terms@alleninstitute.org for commercial
18
- licensing opportunities.
19
-
20
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
21
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
26
- USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -1,295 +0,0 @@
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
- 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; }
3
- function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
4
- 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); }
5
- function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
6
- 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."); }
7
- 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; } }
8
- 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; }
9
- 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; } }
10
- function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
11
- import { CaretRightOutlined, PauseOutlined } from "@ant-design/icons";
12
- import { Button, Tooltip } from "antd";
13
- import React, { useCallback, useEffect, useState } from "react";
14
- import { activeAxisMap } from "../../shared/types";
15
- import NumericInput from "../shared/NumericInput";
16
- import SmarterSlider from "../shared/SmarterSlider";
17
- import "./styles.css";
18
- var AXES = ["x", "y", "z"];
19
- /** A single slider row, with a slider, one or two spinbox inputs, and a max value */
20
- var SliderRow = function SliderRow(_ref) {
21
- var label = _ref.label,
22
- vals = _ref.vals,
23
- _ref$valsReadout = _ref.valsReadout,
24
- valsReadout = _ref$valsReadout === void 0 ? vals : _ref$valsReadout,
25
- max = _ref.max,
26
- onSlide = _ref.onSlide,
27
- _ref$onChange = _ref.onChange,
28
- _onChange = _ref$onChange === void 0 ? onSlide : _ref$onChange,
29
- onStart = _ref.onStart,
30
- onEnd = _ref.onEnd;
31
- var isRange = vals.length > 1;
32
- // If slider is a range, handles represent slice *edges*: the range around only the 1st slice is [0, 1]; the range
33
- // around only the last is [max-1, max].
34
- // If slider is not a range, just work with slices, but don't 0-index: 1st slice is 1, last is max
35
- var min = isRange ? 0 : 1;
36
- var wrappedOnSlide = isRange ? onSlide : function (values) {
37
- return onSlide === null || onSlide === void 0 ? void 0 : onSlide([values[0] - 1]);
38
- };
39
- var wrappedOnChange = isRange ? _onChange : function (values) {
40
- return _onChange === null || _onChange === void 0 ? void 0 : _onChange([values[0] - 1]);
41
- };
42
- return /*#__PURE__*/React.createElement("span", {
43
- className: "axis-slider-container"
44
- }, /*#__PURE__*/React.createElement("span", {
45
- className: "slider-name"
46
- }, label), max <= min ? /*#__PURE__*/React.createElement("i", null, "No values to adjust") : /*#__PURE__*/React.createElement("span", {
47
- className: "axis-slider"
48
- }, /*#__PURE__*/React.createElement(SmarterSlider, {
49
- className: isRange ? "" : "slider-single-handle",
50
- connect: true,
51
- range: {
52
- min: min,
53
- max: max
54
- },
55
- start: isRange ? vals : [vals[0] + 1],
56
- step: 1,
57
- margin: 1,
58
- behaviour: "drag",
59
- pips: {
60
- mode: "positions",
61
- values: [25, 50, 75],
62
- density: 25,
63
- format: {
64
- // remove labels from pips
65
- to: function to() {
66
- return "";
67
- }
68
- }
69
- }
70
- // round slider output to nearest slice; assume any string inputs represent ints
71
- ,
72
- format: {
73
- to: Math.round,
74
- from: parseInt
75
- },
76
- onSlide: wrappedOnSlide,
77
- onChange: wrappedOnChange,
78
- onStart: onStart,
79
- onEnd: onEnd
80
- })), max > min && /*#__PURE__*/React.createElement("span", {
81
- className: "slider-values"
82
- }, /*#__PURE__*/React.createElement(NumericInput, {
83
- min: min,
84
- max: max,
85
- value: valsReadout[0] + (isRange ? 0 : 1),
86
- onChange: function onChange(value) {
87
- return _onChange === null || _onChange === void 0 ? void 0 : _onChange(isRange ? [value, vals[1]] : [value - 1]);
88
- }
89
- }), isRange && /*#__PURE__*/React.createElement(React.Fragment, null, " , ", /*#__PURE__*/React.createElement(NumericInput, {
90
- min: min,
91
- max: max,
92
- value: valsReadout[1],
93
- onChange: function onChange(value) {
94
- return _onChange === null || _onChange === void 0 ? void 0 : _onChange([vals[0], value]);
95
- }
96
- })), " / ", max));
97
- };
98
- /** Wrapper around `SliderRow` that adds a play button and accounts for the case where not all of an axis is loaded */
99
- var PlaySliderRow = function PlaySliderRow(props) {
100
- var onChange = props.onChange,
101
- onStart = props.onStart,
102
- onEnd = props.onEnd;
103
- // In partially-loaded axes, stores the displayed value of the slider while the user is sliding it
104
- var _useState = useState(props.val),
105
- _useState2 = _slicedToArray(_useState, 2),
106
- valReadout = _useState2[0],
107
- setValReadout = _useState2[1];
108
- // Tracks when the user is sliding the slider and `valReadout` may have to sub in for props
109
- var _useState3 = useState(false),
110
- _useState4 = _slicedToArray(_useState3, 2),
111
- sliderHeld = _useState4[0],
112
- setSliderHeld = _useState4[1];
113
- var wrappedOnChange = useCallback(function (_ref2) {
114
- var _ref3 = _slicedToArray(_ref2, 1),
115
- val = _ref3[0];
116
- return onChange === null || onChange === void 0 ? void 0 : onChange(val);
117
- }, [onChange]);
118
- var wrappedSetValReadout = useCallback(function (_ref4) {
119
- var _ref5 = _slicedToArray(_ref4, 1),
120
- val = _ref5[0];
121
- return setValReadout(val);
122
- }, []);
123
- var wrappedOnStart = useCallback(function () {
124
- setValReadout(props.val);
125
- setSliderHeld(true);
126
- onStart === null || onStart === void 0 || onStart();
127
- }, [onStart, props.val]);
128
- var wrappedOnEnd = useCallback(function () {
129
- setSliderHeld(false);
130
- onEnd === null || onEnd === void 0 || onEnd();
131
- }, [onEnd]);
132
- return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(SliderRow, {
133
- label: props.label,
134
- vals: [props.val],
135
- valsReadout: props.updateWhileSliding || !sliderHeld ? undefined : [valReadout],
136
- max: props.max,
137
- onSlide: props.updateWhileSliding ? wrappedOnChange : wrappedSetValReadout,
138
- onChange: props.updateWhileSliding ? undefined : wrappedOnChange,
139
- onStart: wrappedOnStart,
140
- onEnd: wrappedOnEnd
141
- }), props.max > 1 && /*#__PURE__*/React.createElement(Tooltip, {
142
- placement: "top",
143
- title: "Play through sequence",
144
- trigger: ["hover", "focus"]
145
- }, /*#__PURE__*/React.createElement(Button, {
146
- className: "slider-play-button",
147
- onClick: function onClick() {
148
- return props.onTogglePlayback(!props.playing);
149
- },
150
- icon: props.playing ? /*#__PURE__*/React.createElement(PauseOutlined, null) : /*#__PURE__*/React.createElement(CaretRightOutlined, null),
151
- "aria-label": (props.playing ? "Pause " : "Play ") + props.label
152
- })));
153
- };
154
- var AxisClipSliders = function AxisClipSliders(props) {
155
- var activeAxis = activeAxisMap[props.mode];
156
- var pauseOnInput = function pauseOnInput(axis) {
157
- // Pause on slider input unless user is scrubbing along the playing axis (playback is held while this is happening)
158
- if (!props.playControls.playHolding || props.playingAxis !== axis) {
159
- props.playControls.pause();
160
- }
161
- };
162
- var updateRegion = function updateRegion(axis, minval, maxval) {
163
- pauseOnInput(axis);
164
- var changeViewerSetting = props.changeViewerSetting,
165
- numSlices = props.numSlices;
166
- // get a value from 0-1
167
- var max = numSlices[axis];
168
- var start = minval / max;
169
- var end = maxval / max;
170
- changeViewerSetting("region", _defineProperty({}, axis, [start, end]));
171
- };
172
- var updateSlice = function updateSlice(axis, slice) {
173
- pauseOnInput(axis);
174
- props.changeViewerSetting("slice", _defineProperty({}, axis, slice / props.numSlices[axis]));
175
- };
176
- var updateTime = function updateTime(time) {
177
- pauseOnInput("t");
178
- props.changeViewerSetting("time", time);
179
- };
180
-
181
- // Pause when view mode or volume size has changed
182
- useEffect(function () {
183
- return props.playControls.pause();
184
- }, [props.mode, props.image, props.playControls]);
185
- var handlePlayPause = function handlePlayPause(axis, willPlay) {
186
- if (willPlay) {
187
- props.playControls.play(axis);
188
- } else {
189
- props.playControls.pause();
190
- }
191
- };
192
- var create2dAxisSlider = function create2dAxisSlider(axis) {
193
- var numSlices = props.numSlices[axis];
194
- var numSlicesLoaded = props.numSlicesLoaded[axis];
195
- return /*#__PURE__*/React.createElement("div", {
196
- key: axis + numSlices + numSlicesLoaded,
197
- className: "slider-row slider-".concat(axis)
198
- }, /*#__PURE__*/React.createElement(PlaySliderRow, {
199
- label: axis.toUpperCase(),
200
- val: Math.round(props.slices[axis] * numSlices),
201
- max: numSlices,
202
- onChange: function onChange(val) {
203
- return updateSlice(axis, val);
204
- },
205
- onStart: function onStart() {
206
- return props.playControls.startHold(axis);
207
- },
208
- onEnd: function onEnd() {
209
- return props.playControls.endHold();
210
- },
211
- playing: props.playingAxis === axis,
212
- onTogglePlayback: function onTogglePlayback(willPlay) {
213
- return handlePlayPause(axis, willPlay);
214
- },
215
- updateWhileSliding: numSlices === numSlicesLoaded
216
- }));
217
- };
218
- var create3dAxisSlider = function create3dAxisSlider(axis) {
219
- var numSlices = props.numSlices[axis];
220
- if (numSlices === 1) {
221
- return null;
222
- }
223
- var region = props.region[axis];
224
- return /*#__PURE__*/React.createElement("div", {
225
- key: axis + numSlices + "3d",
226
- className: "slider-row slider-".concat(axis)
227
- }, /*#__PURE__*/React.createElement(SliderRow, {
228
- label: axis.toUpperCase(),
229
- vals: [Math.round(region[0] * numSlices), Math.round(region[1] * numSlices)],
230
- max: numSlices,
231
- onSlide: function onSlide(values) {
232
- return updateRegion(axis, values[0], values[1]);
233
- },
234
- onStart: function onStart() {
235
- return props.playControls.startHold(axis);
236
- },
237
- onEnd: function onEnd() {
238
- return props.playControls.endHold();
239
- }
240
- }));
241
- };
242
- return /*#__PURE__*/React.createElement("div", {
243
- className: activeAxis ? "clip-sliders clip-sliders-2d" : "clip-sliders"
244
- }, /*#__PURE__*/React.createElement("span", {
245
- className: "slider-group"
246
- }, /*#__PURE__*/React.createElement("h4", {
247
- className: "slider-group-title"
248
- }, "ROI"), /*#__PURE__*/React.createElement("span", {
249
- className: "slider-group-rows"
250
- }, activeAxis ? create2dAxisSlider(activeAxis) : AXES.map(create3dAxisSlider))), props.numTimesteps > 1 && /*#__PURE__*/React.createElement("span", {
251
- className: "slider-group"
252
- }, /*#__PURE__*/React.createElement("h4", {
253
- className: "slider-group-title"
254
- }, "Time"), /*#__PURE__*/React.createElement("span", {
255
- className: "slider-group-rows"
256
- }, /*#__PURE__*/React.createElement("div", {
257
- className: "slider-row slider-t"
258
- }, /*#__PURE__*/React.createElement(PlaySliderRow, {
259
- label: "",
260
- val: props.time,
261
- max: props.numTimesteps,
262
- playing: props.playingAxis === "t",
263
- onTogglePlayback: function onTogglePlayback(willPlay) {
264
- return handlePlayPause("t", willPlay);
265
- },
266
- onChange: function onChange(time) {
267
- return updateTime(time);
268
- },
269
- onStart: function onStart() {
270
- return props.playControls.startHold("t");
271
- },
272
- onEnd: function onEnd() {
273
- return props.playControls.endHold();
274
- }
275
- })))), props.numScenes > 1 && /*#__PURE__*/React.createElement("span", {
276
- className: "slider-group"
277
- }, /*#__PURE__*/React.createElement("h4", {
278
- className: "slider-group-title"
279
- }, "Scene"), /*#__PURE__*/React.createElement("span", {
280
- className: "slider-group-rows"
281
- }, /*#__PURE__*/React.createElement("div", {
282
- className: "slider-row slider-scene"
283
- }, /*#__PURE__*/React.createElement(SliderRow, {
284
- label: "",
285
- vals: [props.scene],
286
- max: props.numScenes,
287
- onChange: function onChange(_ref6) {
288
- var _ref7 = _slicedToArray(_ref6, 1),
289
- scene = _ref7[0];
290
- props.changeViewerSetting("scene", scene);
291
- props.changeViewerSetting("useExactScaleLevel", false);
292
- }
293
- })))));
294
- };
295
- export default AxisClipSliders;