@aics/vole-app 2.11.0 → 2.13.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.
- package/es/aics-image-viewer/components/App/ChannelUpdater.js +11 -12
- package/es/aics-image-viewer/components/App/index.js +62 -30
- package/es/aics-image-viewer/components/AxisClipSliders/index.js +34 -25
- package/es/aics-image-viewer/components/BottomPanel/index.js +12 -28
- package/es/aics-image-viewer/components/CellViewerCanvasWrapper/index.js +3 -12
- package/es/aics-image-viewer/components/ChannelsWidgetRow/index.js +6 -2
- package/es/aics-image-viewer/components/ChannelsWidgetRow/styles.css +5 -1
- package/es/aics-image-viewer/components/ErrorAlert/index.js +1 -1
- package/es/aics-image-viewer/components/ErrorAlert/styles.css +3 -0
- package/es/aics-image-viewer/components/StyleProvider/index.js +1 -1
- package/es/aics-image-viewer/components/TfEditor/index.js +229 -41
- package/es/aics-image-viewer/components/TfEditor/styles.css +19 -7
- package/es/aics-image-viewer/components/Toolbar/ViewModeRadioButtons.js +1 -1
- package/es/aics-image-viewer/components/Toolbar/index.js +34 -30
- package/es/aics-image-viewer/components/ViewerStateProvider/index.js +11 -13
- package/es/aics-image-viewer/shared/constants.js +41 -1
- package/es/aics-image-viewer/shared/utils/hooks.js +3 -3
- package/es/aics-image-viewer/shared/utils/viewerState.js +3 -1
- package/package.json +4 -3
- package/type-declarations/aics-image-viewer/components/App/types.d.ts +1 -1
- package/type-declarations/aics-image-viewer/components/BottomPanel/index.d.ts +2 -2
- package/type-declarations/aics-image-viewer/components/CellViewerCanvasWrapper/index.d.ts +2 -2
- package/type-declarations/aics-image-viewer/components/TfEditor/index.d.ts +2 -0
- package/type-declarations/aics-image-viewer/components/Toolbar/index.d.ts +1 -1
- package/type-declarations/aics-image-viewer/components/ViewerStateProvider/types.d.ts +2 -0
- package/type-declarations/aics-image-viewer/shared/constants.d.ts +8 -1
- package/type-declarations/aics-image-viewer/shared/types.d.ts +2 -2
|
@@ -31,6 +31,8 @@ var ChannelUpdater = function ChannelUpdater(_ref) {
|
|
|
31
31
|
if (image && version > 0) {
|
|
32
32
|
return effect(image);
|
|
33
33
|
}
|
|
34
|
+
// react-hooks will check that `deps` match `effect`'s dependencies, so we can safely exclude `effect` here
|
|
35
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
34
36
|
}, [].concat(_toConsumableArray(deps), [image, version]));
|
|
35
37
|
};
|
|
36
38
|
|
|
@@ -40,30 +42,30 @@ var ChannelUpdater = function ChannelUpdater(_ref) {
|
|
|
40
42
|
view3d.setVolumeChannelEnabled(image, index, volumeEnabled);
|
|
41
43
|
view3d.updateLuts(image);
|
|
42
44
|
}
|
|
43
|
-
}, [image, volumeEnabled]);
|
|
45
|
+
}, [image, volumeEnabled, index, view3d]);
|
|
44
46
|
useEffect(function () {
|
|
45
47
|
if (image) {
|
|
46
48
|
view3d.setVolumeChannelOptions(image, index, {
|
|
47
49
|
isosurfaceEnabled: isosurfaceEnabled
|
|
48
50
|
});
|
|
49
51
|
}
|
|
50
|
-
}, [image, isosurfaceEnabled]);
|
|
52
|
+
}, [image, isosurfaceEnabled, index, view3d]);
|
|
51
53
|
useImageEffect(function (currentImage) {
|
|
52
54
|
return view3d.setVolumeChannelOptions(currentImage, index, {
|
|
53
55
|
isovalue: isovalue
|
|
54
56
|
});
|
|
55
|
-
}, [isovalue]);
|
|
57
|
+
}, [isovalue, index, view3d]);
|
|
56
58
|
useImageEffect(function (currentImage) {
|
|
57
59
|
return view3d.setVolumeChannelOptions(currentImage, index, {
|
|
58
60
|
isosurfaceOpacity: opacity
|
|
59
61
|
});
|
|
60
|
-
}, [opacity]);
|
|
62
|
+
}, [opacity, index, view3d]);
|
|
61
63
|
useImageEffect(function (currentImage) {
|
|
62
64
|
view3d.setVolumeChannelOptions(currentImage, index, {
|
|
63
65
|
color: color
|
|
64
66
|
});
|
|
65
67
|
view3d.updateLuts(currentImage);
|
|
66
|
-
}, [color]);
|
|
68
|
+
}, [color, index, view3d]);
|
|
67
69
|
var controlPoints = channelState.controlPoints,
|
|
68
70
|
ramp = channelState.ramp,
|
|
69
71
|
useControlPoints = channelState.useControlPoints;
|
|
@@ -75,22 +77,19 @@ var ChannelUpdater = function ChannelUpdater(_ref) {
|
|
|
75
77
|
var gradient = controlPointsToLut(controlPointsToUse);
|
|
76
78
|
currentImage.setLut(index, gradient);
|
|
77
79
|
view3d.updateLuts(currentImage);
|
|
78
|
-
}, [controlPoints, ramp, useControlPoints]);
|
|
80
|
+
}, [controlPoints, ramp, useControlPoints, index, view3d]);
|
|
79
81
|
useImageEffect(function (currentImage) {
|
|
80
82
|
if (colorizeEnabled) {
|
|
81
83
|
// TODO get the labelColors from the tf editor component
|
|
82
84
|
var lut = new Lut().createLabelColors(currentImage.getHistogram(index));
|
|
83
85
|
currentImage.setColorPalette(index, lut.lut);
|
|
84
|
-
|
|
85
|
-
} else {
|
|
86
|
-
currentImage.setColorPaletteAlpha(index, 0);
|
|
86
|
+
// following effect will also run and call `updateLuts`
|
|
87
87
|
}
|
|
88
|
-
|
|
89
|
-
}, [colorizeEnabled]);
|
|
88
|
+
}, [colorizeEnabled, index, view3d]);
|
|
90
89
|
useImageEffect(function (currentImage) {
|
|
91
90
|
currentImage.setColorPaletteAlpha(index, colorizeEnabled ? colorizeAlpha : 0);
|
|
92
91
|
view3d.updateLuts(currentImage);
|
|
93
|
-
}, [colorizeAlpha]);
|
|
92
|
+
}, [colorizeEnabled, colorizeAlpha, index, view3d]);
|
|
94
93
|
return null;
|
|
95
94
|
};
|
|
96
95
|
export default ChannelUpdater;
|
|
@@ -23,7 +23,7 @@ import { Layout } from "antd";
|
|
|
23
23
|
import { debounce, isEqual } from "lodash";
|
|
24
24
|
import React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
|
|
25
25
|
import { Box3, Vector3 } from "three";
|
|
26
|
-
import { AXIS_MARGIN_DEFAULT, CACHE_MAX_SIZE, CLIPPING_PANEL_HEIGHT_DEFAULT, CLIPPING_PANEL_HEIGHT_TALL, CONTROL_PANEL_CLOSE_WIDTH, getDefaultChannelColor, getDefaultViewerState, QUEUE_MAX_LOW_PRIORITY_SIZE, QUEUE_MAX_SIZE, SCALE_BAR_MARGIN_DEFAULT } from "../../shared/constants";
|
|
26
|
+
import { AXIS_MARGIN_DEFAULT, CACHE_MAX_SIZE, CLIPPING_PANEL_HEIGHT_DEFAULT, CLIPPING_PANEL_HEIGHT_TALL, CONTROL_PANEL_CLOSE_WIDTH, DTYPE_RANGE, getDefaultChannelColor, getDefaultViewerState, QUEUE_MAX_LOW_PRIORITY_SIZE, QUEUE_MAX_SIZE, SCALE_BAR_MARGIN_DEFAULT } from "../../shared/constants";
|
|
27
27
|
import { ImageType, RenderMode, ViewMode } from "../../shared/enums";
|
|
28
28
|
import { activeAxisMap } from "../../shared/types";
|
|
29
29
|
import { colorArrayToFloats } from "../../shared/utils/colorRepresentations";
|
|
@@ -87,6 +87,7 @@ var axisToLoaderPriority = {
|
|
|
87
87
|
y: PrefetchDirection.Y_PLUS,
|
|
88
88
|
x: PrefetchDirection.X_PLUS
|
|
89
89
|
};
|
|
90
|
+
var CLIPPING_PANEL_ANIMATION_DURATION_MS = 300;
|
|
90
91
|
var setIndicatorPositions = function setIndicatorPositions(view3d, panelOpen, hasTime, hasScenes, isMode3d) {
|
|
91
92
|
// The height of the clipping panel includes the button, but we're trying to put these elements next to the button
|
|
92
93
|
var CLIPPING_PANEL_BUTTON_HEIGHT = 40;
|
|
@@ -115,6 +116,11 @@ var setIndicatorPositions = function setIndicatorPositions(view3d, panelOpen, ha
|
|
|
115
116
|
view3d.setTimestepIndicatorPosition(SCALE_BAR_MARGIN_DEFAULT[0], scaleBarY);
|
|
116
117
|
view3d.setScaleBarPosition(scaleBarX, scaleBarY);
|
|
117
118
|
};
|
|
119
|
+
|
|
120
|
+
// TODO this component, specifically its volume loading behavior, is way out of compliance with react-hooks lints
|
|
121
|
+
// and will need a larger refactoring pass to fix that.
|
|
122
|
+
/* eslint-disable react-hooks/exhaustive-deps */
|
|
123
|
+
/* eslint-disable react-hooks/rules-of-hooks */
|
|
118
124
|
var App = function App(props) {
|
|
119
125
|
var _scenes$length, _scenes, _image$imageInfo$volu, _image$imageInfo$subr, _image$imageInfo$time, _props$transform2, _props$transform4;
|
|
120
126
|
props = _objectSpread(_objectSpread({}, defaultProps), props);
|
|
@@ -223,19 +229,21 @@ var App = function App(props) {
|
|
|
223
229
|
_useState12 = _slicedToArray(_useState11, 2),
|
|
224
230
|
hasAutoClosedControlPanel = _useState12[0],
|
|
225
231
|
setHasAutoClosedControlPanel = _useState12[1];
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
232
|
+
var _useState13 = useState(true),
|
|
233
|
+
_useState14 = _slicedToArray(_useState13, 2),
|
|
234
|
+
clippingPanelOpen = _useState14[0],
|
|
235
|
+
setClippingPanelOpen = _useState14[1];
|
|
236
|
+
var clippingPanelOpenTimeout = useRef(0);
|
|
229
237
|
|
|
230
238
|
// `PlayControls` manages playing through time and spatial axes, which isn't practical with "pure" React
|
|
231
239
|
// Playback state goes here, but the play/pause buttons that mainly control this class are down in `AxisClipSliders`
|
|
232
240
|
var playControls = useConstructor(function () {
|
|
233
241
|
return new PlayControls();
|
|
234
242
|
});
|
|
235
|
-
var
|
|
236
|
-
|
|
237
|
-
playingAxis =
|
|
238
|
-
setPlayingAxis =
|
|
243
|
+
var _useState15 = useState(null),
|
|
244
|
+
_useState16 = _slicedToArray(_useState15, 2),
|
|
245
|
+
playingAxis = _useState16[0],
|
|
246
|
+
setPlayingAxis = _useState16[1];
|
|
239
247
|
playControls.onPlayingAxisChanged = function (axis) {
|
|
240
248
|
var _loader$current, _loader$current2;
|
|
241
249
|
(_loader$current = loader.current) === null || _loader$current === void 0 || _loader$current.setPrefetchPriority(axis ? [axisToLoaderPriority[axis]] : []);
|
|
@@ -288,7 +296,10 @@ var App = function App(props) {
|
|
|
288
296
|
controlPoints = _initializeLut.controlPoints;
|
|
289
297
|
changeChannelSetting(channelIndex, {
|
|
290
298
|
controlPoints: controlPoints,
|
|
291
|
-
ramp: controlPointsToRamp(ramp)
|
|
299
|
+
ramp: controlPointsToRamp(ramp),
|
|
300
|
+
// set the default range of the transfer function editor to cover the full range of the data type
|
|
301
|
+
plotMin: DTYPE_RANGE[thisChannel.dtype].min,
|
|
302
|
+
plotMax: DTYPE_RANGE[thisChannel.dtype].max
|
|
292
303
|
});
|
|
293
304
|
onResetChannel(channelIndex);
|
|
294
305
|
} else {
|
|
@@ -301,8 +312,8 @@ var App = function App(props) {
|
|
|
301
312
|
var oldRange = channelRangesRef.current[channelIndex];
|
|
302
313
|
if (thisChannelsSettings.useControlPoints) {
|
|
303
314
|
// control points were just automatically remapped - update in state
|
|
304
|
-
// now manually remap ramp using the channel's old range
|
|
305
315
|
var rampControlPoints = rampToControlPoints(thisChannelsSettings.ramp);
|
|
316
|
+
// now manually remap ramp using the channel's old range
|
|
306
317
|
var remappedRampControlPoints = remapControlPointsForChannel(rampControlPoints, oldRange, thisChannel);
|
|
307
318
|
changeChannelSetting(channelIndex, {
|
|
308
319
|
ramp: controlPointsToRamp(remappedRampControlPoints),
|
|
@@ -393,7 +404,7 @@ var App = function App(props) {
|
|
|
393
404
|
})
|
|
394
405
|
});
|
|
395
406
|
var mode3d = viewerSettings.viewMode === ViewMode.threeD;
|
|
396
|
-
setIndicatorPositions(view3d,
|
|
407
|
+
setIndicatorPositions(view3d, clippingPanelOpen, aimg.imageInfo.times > 1, numScenes > 1, mode3d);
|
|
397
408
|
imageLoadHandlers.current.forEach(function (effect) {
|
|
398
409
|
return effect(aimg);
|
|
399
410
|
});
|
|
@@ -545,25 +556,31 @@ var App = function App(props) {
|
|
|
545
556
|
anchor.click();
|
|
546
557
|
});
|
|
547
558
|
}, []);
|
|
548
|
-
var
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
559
|
+
var onClippingPanelOpenChange = useCallback(function (panelOpen) {
|
|
560
|
+
if (panelOpen === clippingPanelOpen) {
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
var hasTime = numTimesteps > 1;
|
|
564
|
+
var hasScenes = numScenes > 1;
|
|
565
|
+
var mode3d = viewerSettings.viewMode === ViewMode.threeD;
|
|
566
|
+
setClippingPanelOpen(panelOpen);
|
|
553
567
|
setIndicatorPositions(view3d, panelOpen, hasTime, hasScenes, mode3d);
|
|
554
568
|
|
|
555
569
|
// Hide indicators while clipping panel is in motion - otherwise they pop to the right place prematurely
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
570
|
+
if (panelOpen) {
|
|
571
|
+
view3d.setShowScaleBar(false);
|
|
572
|
+
view3d.setShowTimestepIndicator(false);
|
|
573
|
+
view3d.setShowAxis(false);
|
|
574
|
+
window.clearTimeout(clippingPanelOpenTimeout.current);
|
|
575
|
+
clippingPanelOpenTimeout.current = window.setTimeout(function () {
|
|
576
|
+
view3d.setShowScaleBar(true);
|
|
577
|
+
view3d.setShowTimestepIndicator(true);
|
|
578
|
+
if (viewerSettings.showAxes) {
|
|
579
|
+
view3d.setShowAxis(true);
|
|
580
|
+
}
|
|
581
|
+
}, CLIPPING_PANEL_ANIMATION_DURATION_MS);
|
|
565
582
|
}
|
|
566
|
-
}, [viewerSettings.showAxes]);
|
|
583
|
+
}, [view3d, numTimesteps, numScenes, viewerSettings.viewMode, viewerSettings.showAxes, clippingPanelOpen]);
|
|
567
584
|
var getMetadata = useCallback(function () {
|
|
568
585
|
var _props2 = props,
|
|
569
586
|
metadata = _props2.metadata,
|
|
@@ -572,12 +589,24 @@ var App = function App(props) {
|
|
|
572
589
|
if (imageMetadata && metadataFormatter) {
|
|
573
590
|
imageMetadata = metadataFormatter(imageMetadata);
|
|
574
591
|
}
|
|
592
|
+
var sceneMeta;
|
|
593
|
+
if (Array.isArray(metadata)) {
|
|
594
|
+
// If metadata is an array, try to index it by scene
|
|
595
|
+
if (metadata.length >= numScenes) {
|
|
596
|
+
sceneMeta = metadata[viewerState.current.scene];
|
|
597
|
+
} else {
|
|
598
|
+
sceneMeta = metadata[0];
|
|
599
|
+
}
|
|
600
|
+
} else {
|
|
601
|
+
sceneMeta = metadata;
|
|
602
|
+
}
|
|
575
603
|
if (imageMetadata && Object.keys(imageMetadata).length > 0) {
|
|
576
604
|
return _objectSpread({
|
|
577
605
|
Image: imageMetadata
|
|
578
|
-
},
|
|
606
|
+
}, sceneMeta);
|
|
579
607
|
} else {
|
|
580
|
-
|
|
608
|
+
var _sceneMeta;
|
|
609
|
+
return (_sceneMeta = sceneMeta) !== null && _sceneMeta !== void 0 ? _sceneMeta : {};
|
|
581
610
|
}
|
|
582
611
|
}, [props.metadata, props.metadataFormatter, image]);
|
|
583
612
|
|
|
@@ -777,6 +806,9 @@ var App = function App(props) {
|
|
|
777
806
|
var pixelSize = useMemo(function () {
|
|
778
807
|
return image ? image.imageInfo.physicalPixelSize.toArray() : [1, 1, 1];
|
|
779
808
|
}, [image === null || image === void 0 ? void 0 : image.imageInfo.physicalPixelSize]);
|
|
809
|
+
var resetCamera = useMemo(function () {
|
|
810
|
+
return view3d.resetCamera.bind(view3d);
|
|
811
|
+
}, [view3d]);
|
|
780
812
|
return /*#__PURE__*/React.createElement(StyleProvider, null, errorAlert, /*#__PURE__*/React.createElement(Layout, {
|
|
781
813
|
className: "cell-viewer-app",
|
|
782
814
|
style: {
|
|
@@ -842,8 +874,8 @@ var App = function App(props) {
|
|
|
842
874
|
playingAxis: playingAxis,
|
|
843
875
|
appHeight: props.appHeight,
|
|
844
876
|
visibleControls: visibleControls,
|
|
845
|
-
|
|
846
|
-
|
|
877
|
+
clippingPanelOpen: clippingPanelOpen,
|
|
878
|
+
onClippingPanelOpenChange: onClippingPanelOpenChange
|
|
847
879
|
})))));
|
|
848
880
|
};
|
|
849
881
|
export default App;
|
|
@@ -29,23 +29,30 @@ var SliderRow = function SliderRow(_ref) {
|
|
|
29
29
|
onStart = _ref.onStart,
|
|
30
30
|
onEnd = _ref.onEnd;
|
|
31
31
|
var isRange = vals.length > 1;
|
|
32
|
-
// If slider is a range, handles represent slice *edges*: the range around only the
|
|
33
|
-
//
|
|
34
|
-
|
|
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
|
+
};
|
|
35
42
|
return /*#__PURE__*/React.createElement("span", {
|
|
36
43
|
className: "axis-slider-container"
|
|
37
44
|
}, /*#__PURE__*/React.createElement("span", {
|
|
38
45
|
className: "slider-name"
|
|
39
|
-
}, label),
|
|
46
|
+
}, label), max === 0 ? /*#__PURE__*/React.createElement("i", null, "No values to adjust") : /*#__PURE__*/React.createElement("span", {
|
|
40
47
|
className: "axis-slider"
|
|
41
48
|
}, /*#__PURE__*/React.createElement(SmarterSlider, {
|
|
42
49
|
className: isRange ? "" : "slider-single-handle",
|
|
43
50
|
connect: true,
|
|
44
51
|
range: {
|
|
45
|
-
min:
|
|
46
|
-
max:
|
|
52
|
+
min: min,
|
|
53
|
+
max: max
|
|
47
54
|
},
|
|
48
|
-
start: vals,
|
|
55
|
+
start: isRange ? vals : [vals[0] + 1],
|
|
49
56
|
step: 1,
|
|
50
57
|
margin: 1,
|
|
51
58
|
behaviour: "drag",
|
|
@@ -66,28 +73,33 @@ var SliderRow = function SliderRow(_ref) {
|
|
|
66
73
|
to: Math.round,
|
|
67
74
|
from: parseInt
|
|
68
75
|
},
|
|
69
|
-
onSlide:
|
|
70
|
-
onChange:
|
|
76
|
+
onSlide: wrappedOnSlide,
|
|
77
|
+
onChange: wrappedOnChange,
|
|
71
78
|
onStart: onStart,
|
|
72
79
|
onEnd: onEnd
|
|
73
|
-
})),
|
|
80
|
+
})), max > 0 && /*#__PURE__*/React.createElement("span", {
|
|
74
81
|
className: "slider-values"
|
|
75
82
|
}, /*#__PURE__*/React.createElement(NumericInput, {
|
|
76
|
-
|
|
77
|
-
|
|
83
|
+
min: min,
|
|
84
|
+
max: max,
|
|
85
|
+
value: valsReadout[0] + (isRange ? 0 : 1),
|
|
78
86
|
onChange: function onChange(value) {
|
|
79
|
-
return _onChange === null || _onChange === void 0 ? void 0 : _onChange(isRange ? [value, vals[1]] : [value]);
|
|
87
|
+
return _onChange === null || _onChange === void 0 ? void 0 : _onChange(isRange ? [value, vals[1]] : [value - 1]);
|
|
80
88
|
}
|
|
81
89
|
}), isRange && /*#__PURE__*/React.createElement(React.Fragment, null, " , ", /*#__PURE__*/React.createElement(NumericInput, {
|
|
82
|
-
|
|
90
|
+
min: min,
|
|
91
|
+
max: max,
|
|
83
92
|
value: valsReadout[1],
|
|
84
93
|
onChange: function onChange(value) {
|
|
85
94
|
return _onChange === null || _onChange === void 0 ? void 0 : _onChange([vals[0], value]);
|
|
86
95
|
}
|
|
87
|
-
})), " / ", max
|
|
96
|
+
})), " / ", max));
|
|
88
97
|
};
|
|
89
98
|
/** Wrapper around `SliderRow` that adds a play button and accounts for the case where not all of an axis is loaded */
|
|
90
99
|
var PlaySliderRow = function PlaySliderRow(props) {
|
|
100
|
+
var onChange = props.onChange,
|
|
101
|
+
onStart = props.onStart,
|
|
102
|
+
onEnd = props.onEnd;
|
|
91
103
|
// In partially-loaded axes, stores the displayed value of the slider while the user is sliding it
|
|
92
104
|
var _useState = useState(props.val),
|
|
93
105
|
_useState2 = _slicedToArray(_useState, 2),
|
|
@@ -99,27 +111,24 @@ var PlaySliderRow = function PlaySliderRow(props) {
|
|
|
99
111
|
sliderHeld = _useState4[0],
|
|
100
112
|
setSliderHeld = _useState4[1];
|
|
101
113
|
var wrappedOnChange = useCallback(function (_ref2) {
|
|
102
|
-
var _props$onChange;
|
|
103
114
|
var _ref3 = _slicedToArray(_ref2, 1),
|
|
104
115
|
val = _ref3[0];
|
|
105
|
-
return
|
|
106
|
-
}, [
|
|
116
|
+
return onChange === null || onChange === void 0 ? void 0 : onChange(val);
|
|
117
|
+
}, [onChange]);
|
|
107
118
|
var wrappedSetValReadout = useCallback(function (_ref4) {
|
|
108
119
|
var _ref5 = _slicedToArray(_ref4, 1),
|
|
109
120
|
val = _ref5[0];
|
|
110
121
|
return setValReadout(val);
|
|
111
122
|
}, []);
|
|
112
123
|
var wrappedOnStart = useCallback(function () {
|
|
113
|
-
var _props$onStart;
|
|
114
124
|
setValReadout(props.val);
|
|
115
125
|
setSliderHeld(true);
|
|
116
|
-
|
|
117
|
-
}, [props.
|
|
126
|
+
onStart === null || onStart === void 0 || onStart();
|
|
127
|
+
}, [onStart, props.val]);
|
|
118
128
|
var wrappedOnEnd = useCallback(function () {
|
|
119
|
-
var _props$onEnd;
|
|
120
129
|
setSliderHeld(false);
|
|
121
|
-
|
|
122
|
-
}, [
|
|
130
|
+
onEnd === null || onEnd === void 0 || onEnd();
|
|
131
|
+
}, [onEnd]);
|
|
123
132
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(SliderRow, {
|
|
124
133
|
label: props.label,
|
|
125
134
|
vals: [props.val],
|
|
@@ -172,7 +181,7 @@ var AxisClipSliders = function AxisClipSliders(props) {
|
|
|
172
181
|
// Pause when view mode or volume size has changed
|
|
173
182
|
useEffect(function () {
|
|
174
183
|
return props.playControls.pause();
|
|
175
|
-
}, [props.mode, props.image]);
|
|
184
|
+
}, [props.mode, props.image, props.playControls]);
|
|
176
185
|
var handlePlayPause = function handlePlayPause(axis, willPlay) {
|
|
177
186
|
if (willPlay) {
|
|
178
187
|
props.playControls.play(axis);
|
|
@@ -5,41 +5,26 @@ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length)
|
|
|
5
5
|
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; } }
|
|
6
6
|
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
|
7
7
|
import { Button, Drawer } from "antd";
|
|
8
|
-
import React, {
|
|
8
|
+
import React, { useCallback, useState } from "react";
|
|
9
9
|
import ViewerIcon from "../shared/ViewerIcon";
|
|
10
10
|
import "./styles.css";
|
|
11
11
|
var BottomPanel = function BottomPanel(_ref) {
|
|
12
12
|
var children = _ref.children,
|
|
13
|
+
openProp = _ref.open,
|
|
13
14
|
title = _ref.title,
|
|
14
15
|
height = _ref.height,
|
|
15
|
-
|
|
16
|
-
onVisibleChangeEnd = _ref.onVisibleChangeEnd;
|
|
16
|
+
onOpenChange = _ref.onOpenChange;
|
|
17
17
|
var _useState = useState(true),
|
|
18
18
|
_useState2 = _slicedToArray(_useState, 2),
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if (!isVisible) {
|
|
26
|
-
onVisibleChangeEnd === null || onVisibleChangeEnd === void 0 || onVisibleChangeEnd(isVisible);
|
|
19
|
+
openState = _useState2[0],
|
|
20
|
+
setOpenState = _useState2[1];
|
|
21
|
+
var open = openProp !== null && openProp !== void 0 ? openProp : openState;
|
|
22
|
+
var toggleDrawer = useCallback(function () {
|
|
23
|
+
if (openProp === undefined) {
|
|
24
|
+
setOpenState(!open);
|
|
27
25
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
// Treat changes in height as a change in visibility if the panel is open
|
|
31
|
-
useEffect(function () {
|
|
32
|
-
onVisibleChange === null || onVisibleChange === void 0 || onVisibleChange(isVisible);
|
|
33
|
-
window.setTimeout(function () {
|
|
34
|
-
return onVisibleChangeEnd === null || onVisibleChangeEnd === void 0 ? void 0 : onVisibleChangeEnd(isVisible);
|
|
35
|
-
}, 300);
|
|
36
|
-
}, [height]);
|
|
37
|
-
var toggleDrawer = function toggleDrawer() {
|
|
38
|
-
setIsVisible(!isVisible);
|
|
39
|
-
if (onVisibleChange) {
|
|
40
|
-
onVisibleChange(!isVisible);
|
|
41
|
-
}
|
|
42
|
-
};
|
|
26
|
+
onOpenChange === null || onOpenChange === void 0 || onOpenChange(!open);
|
|
27
|
+
}, [open, openProp, onOpenChange]);
|
|
43
28
|
var optionsButton = /*#__PURE__*/React.createElement(Button, {
|
|
44
29
|
className: "options-button",
|
|
45
30
|
size: "small",
|
|
@@ -58,10 +43,9 @@ var BottomPanel = function BottomPanel(_ref) {
|
|
|
58
43
|
placement: "bottom",
|
|
59
44
|
closable: false,
|
|
60
45
|
getContainer: false,
|
|
61
|
-
open:
|
|
46
|
+
open: open,
|
|
62
47
|
mask: false,
|
|
63
48
|
title: optionsButton,
|
|
64
|
-
afterOpenChange: onVisibleChangeEnd,
|
|
65
49
|
height: height !== null && height !== void 0 ? height : 190
|
|
66
50
|
}, /*#__PURE__*/React.createElement("div", {
|
|
67
51
|
className: "drawer-body-wrapper"
|
|
@@ -16,13 +16,7 @@ var ViewerWrapper = function ViewerWrapper(props) {
|
|
|
16
16
|
var view3dviewerRef = /*#__PURE__*/React.createRef();
|
|
17
17
|
React.useEffect(function () {
|
|
18
18
|
view3dviewerRef.current.appendChild(props.view3d.getDOMElement());
|
|
19
|
-
|
|
20
|
-
}, []);
|
|
21
|
-
|
|
22
|
-
// TODO necessary?
|
|
23
|
-
React.useEffect(function () {
|
|
24
|
-
props.view3d.resize(null);
|
|
25
|
-
});
|
|
19
|
+
}, [props.view3d, view3dviewerRef]);
|
|
26
20
|
var renderOverlay = function renderOverlay() {
|
|
27
21
|
// Don't show spinner during playback - we may be constantly loading new data, it'll block the view!
|
|
28
22
|
var showSpinner = props.loadingImage && !props.playingAxis;
|
|
@@ -62,11 +56,8 @@ var ViewerWrapper = function ViewerWrapper(props) {
|
|
|
62
56
|
style: STYLES.view3d
|
|
63
57
|
}), /*#__PURE__*/React.createElement(BottomPanel, {
|
|
64
58
|
title: "Clipping",
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
(_props$onClippingPane = props.onClippingPanelVisibleChange) === null || _props$onClippingPane === void 0 || _props$onClippingPane.call(props, visible, numTimesteps > 1, numScenes > 1, viewMode === ViewMode.threeD);
|
|
68
|
-
},
|
|
69
|
-
onVisibleChangeEnd: props.onClippingPanelVisibleChangeEnd,
|
|
59
|
+
open: props.clippingPanelOpen,
|
|
60
|
+
onOpenChange: props.onClippingPanelOpenChange,
|
|
70
61
|
height: clippingPanelTall ? CLIPPING_PANEL_HEIGHT_TALL : CLIPPING_PANEL_HEIGHT_DEFAULT
|
|
71
62
|
}, visibleControls.axisClipSliders && !!props.image && /*#__PURE__*/React.createElement(AxisClipSliders, {
|
|
72
63
|
mode: viewMode,
|
|
@@ -93,7 +93,9 @@ var ChannelsWidgetRow = function ChannelsWidgetRow(props) {
|
|
|
93
93
|
colorizeEnabled = channelState.colorizeEnabled,
|
|
94
94
|
colorizeAlpha = channelState.colorizeAlpha,
|
|
95
95
|
useControlPoints = channelState.useControlPoints,
|
|
96
|
-
ramp = channelState.ramp
|
|
96
|
+
ramp = channelState.ramp,
|
|
97
|
+
plotMin = channelState.plotMin,
|
|
98
|
+
plotMax = channelState.plotMax;
|
|
97
99
|
return /*#__PURE__*/React.createElement(TfEditor, {
|
|
98
100
|
id: "TFEditor" + index,
|
|
99
101
|
width: 418,
|
|
@@ -104,7 +106,9 @@ var ChannelsWidgetRow = function ChannelsWidgetRow(props) {
|
|
|
104
106
|
colorizeEnabled: colorizeEnabled,
|
|
105
107
|
colorizeAlpha: colorizeAlpha,
|
|
106
108
|
useControlPoints: useControlPoints,
|
|
107
|
-
ramp: ramp
|
|
109
|
+
ramp: ramp,
|
|
110
|
+
plotMin: plotMin,
|
|
111
|
+
plotMax: plotMax
|
|
108
112
|
});
|
|
109
113
|
};
|
|
110
114
|
var renderSurfaceControls = function renderSurfaceControls() {
|
|
@@ -30,9 +30,13 @@
|
|
|
30
30
|
display:flex;
|
|
31
31
|
justify-content:start;
|
|
32
32
|
align-items:end;
|
|
33
|
-
gap:
|
|
33
|
+
gap:5px;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
.channel-rows-list .ant-list-item.channel-row .button-row .ant-btn.ant-btn-sm{
|
|
37
|
+
padding:12px 8px;
|
|
38
|
+
}
|
|
39
|
+
|
|
36
40
|
.channel-rows-list .ant-list-item.channel-row.controls-closed .ant-btn-text:not(:focus-visible){
|
|
37
41
|
color:var(--color-controlpanel-text);
|
|
38
42
|
}
|
|
@@ -119,7 +119,7 @@ export var useErrorAlert = function useErrorAlert() {
|
|
|
119
119
|
return [].concat(_toConsumableArray(prev), [errorSeenCount]);
|
|
120
120
|
});
|
|
121
121
|
seenErrors.set(errorTitle, errorSeenCount);
|
|
122
|
-
}, []);
|
|
122
|
+
}, [seenErrors]);
|
|
123
123
|
var onSkipError = React.useCallback(function () {
|
|
124
124
|
setErrorList(function (prev) {
|
|
125
125
|
return prev.slice(1);
|
|
@@ -16,6 +16,9 @@
|
|
|
16
16
|
.load-error-alert .ant-btn-text{
|
|
17
17
|
color:var(--color-text-link);
|
|
18
18
|
}
|
|
19
|
+
.load-error-alert .ant-btn-text:hover{
|
|
20
|
+
color:#25affe !important;
|
|
21
|
+
}
|
|
19
22
|
.load-error-alert .ant-alert-message div:first-child{
|
|
20
23
|
color:var(--color-text-section);
|
|
21
24
|
font-weight:600;
|
|
@@ -134,7 +134,7 @@ var theme = {
|
|
|
134
134
|
}
|
|
135
135
|
};
|
|
136
136
|
/** Makes theme styling available to child components via CSS variables. */
|
|
137
|
-
var CssProvider = styled.div(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n width: 100%;\n height: 100%;\n\n ", "\n\n h1, h2, h3, h4, p {\n font-family: var(--font-family);\n }\n\n h1 {\n color: var(--color-text-header);\n font-size: 28px;\n font-weight: 400;\n }\n\n h2 {\n color: var(--color-text-section);\n font-size: 19px;\n font-weight: 400;\n }\n\n h3 {\n color: var(--color-text-header);\n font-size: 16px;\n font-weight: 600;\n }\n\n h4 {\n color: var(--color-text-header);\n font-size: 14px;\n font-weight: 400;\n }\n\n p {\n color: var(--color-text-body);\n font-size: 14px;\n font-weight: 400;\n }\n\n a {\n color: var(--color-text-link);\n
|
|
137
|
+
var CssProvider = styled.div(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n width: 100%;\n height: 100%;\n\n ", "\n\n h1, h2, h3, h4, p {\n font-family: var(--font-family);\n }\n\n h1 {\n color: var(--color-text-header);\n font-size: 28px;\n font-weight: 400;\n }\n\n h2 {\n color: var(--color-text-section);\n font-size: 19px;\n font-weight: 400;\n }\n\n h3 {\n color: var(--color-text-header);\n font-size: 16px;\n font-weight: 600;\n }\n\n h4 {\n color: var(--color-text-header);\n font-size: 14px;\n font-weight: 400;\n }\n\n p {\n color: var(--color-text-body);\n font-size: 14px;\n font-weight: 400;\n }\n\n a {\n color: var(--color-text-link);\n }\n\n & *::selection {\n background-color: var(--color-text-selection-bg);\n color: var(--color-text-selection-text);\n }\n\n /** TODO: Go through these styles and see if we can use Ant ConfigProvider for them instead. */\n .ant-btn-link,\n .ant-btn-text,\n .ant-btn-primary,\n .ant-btn-icon-only {\n box-shadow: none;\n\n &:hover:not(:disabled),\n &:focus-visible:not(:disabled) {\n background-color: var(--color-button-primary-hover-bg);\n border-color: var(--color-button-primary-hover-bg);\n color: var(--color-button-primary-text);\n }\n\n &:active:not(:disabled) {\n background-color: var(--color-button-primary-hover-bg);\n border: 1px solid var(--color-button-primary-active-outline);\n color: var(--color-button-primary-text);\n }\n }\n\n /* Let us use buttons with type=\"text\" as purely semantic containers - don't bring any styling! */\n .ant-btn-text {\n width: unset;\n height: unset;\n padding: unset;\n\n &:hover:not(:disabled),\n &:focus-visible:not(:disabled) {\n background-color: unset;\n border-color: transparent;\n }\n }\n\n .ant-btn-icon-only:disabled {\n color: var(--color-button-icon-disabled-text);\n }\n\n .ant-btn-link:not(:disabled) {\n // Change from default blue link text\n color: var(--color-button-link-text);\n }\n\n /**\n * Tertiary style buttons. Grey outline by default, turns to light\n * purple outline on hover.\n */\n .ant-btn-default:not(.ant-btn-icon-only) {\n background-color: var(--color-button-tertiary-bg);\n color: var(--color-button-tertiary-text);\n border-color: var(--color-button-tertiary-outline);\n\n &:hover:not(:disabled),\n &:focus-visible:not(:disabled) {\n background-color: transparent;\n border-color: var(--color-button-tertiary-hover-bg);\n color: var(--color-button-tertiary-hover-text);\n }\n\n &:active:not(:disabled) {\n background-color: transparent;\n border-color: var(--color-button-tertiary-active-outline);\n color: var(--color-button-tertiary-active-text);\n }\n }\n\n // Overrides for checkbox styling\n & .ant-checkbox-input {\n &:hover,\n &:focus-visible {\n border: 1px solid white;\n }\n }\n\n & .ant-checkbox.ant-checkbox-checked {\n background-color: var(--color-checkbox-bg);\n }\n\n .ant-checkbox-inner {\n background-color: transparent !important;\n }\n\n // Add outlines to modals and dropdowns\n & .ant-select-dropdown,\n & .ant-dropdown-menu,\n & .ant-modal-content {\n border: 1px solid var(--color-modal-border);\n }\n\n // Force active/hovered text to be white instead of grey for better contrast\n & .ant-dropdown-menu-item-active {\n color: var(--color-menu-hover-text);\n }\n\n // Remove padding in dropdown menus and make items reactangular + flush with the edge\n & .ant-dropdown-menu,\n & .ant-select-dropdown {\n padding: 0;\n overflow: hidden;\n\n & .ant-dropdown-menu-item,\n & .ant-select-item {\n border-radius: 0;\n }\n }\n"])), function (_ref) {
|
|
138
138
|
var $theme = _ref.$theme;
|
|
139
139
|
return css(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n /* Component and color variables. */\n // TODO: Fix inconsistent use of border vs. outline\n // TODO: Remove variables that aren't used in other CSS files. These should be set directly\n // from the $theme object to reduce unnecessary variables.\n --color-text-link: ", ";\n --color-text-header: ", ";\n --color-text-section: ", ";\n --color-text-body: ", ";\n --color-text-error: ", ";\n\n --color-text-selection-bg: ", ";\n --color-text-selection-text: ", ";\n\n --color-header-title: ", ";\n --color-header-hover-title: ", ";\n --color-header-bg: ", ";\n --color-header-border: ", ";\n\n --color-button-primary-bg: ", ";\n --color-button-primary-text: ", ";\n --color-button-primary-hover-bg: ", ";\n --color-button-primary-active-bg: ", ";\n --color-button-primary-active-outline: ", ";\n --color-button-primary-disabled-bg: ", ";\n\n --color-button-link-text: ", ";\n\n --color-button-secondary-bg: ", ";\n --color-button-secondary-text: ", ";\n --color-button-secondary-outline: ", ";\n\n --color-button-tertiary-bg: transparent;\n --color-button-tertiary-text: ", ";\n --color-button-tertiary-outline: ", ";\n --color-button-tertiary-hover-outline: ", ";\n --color-button-tertiary-hover-text: ", ";\n --color-button-tertiary-active-outline: ", ";\n --color-button-tertiary-active-text: ", ";\n\n --color-button-icon-disabled-text: ", ";\n --color-button-icon-disabled-text: ", ";\n --color-button-icon-activated-text: ", ";\n --color-button-icon-activated-bg: ", ";\n --color-button-icon-activated-outline: ", ";\n\n --color-toolbar-button-bg: ", ";\n\n --color-controlpanel-bg: ", ";\n --color-controlpanel-border: ", ";\n --color-controlpanel-section-text: ", ";\n --color-controlpanel-text: ", ";\n --color-controlpanel-section-bg: ", ";\n --color-controlpanel-drawer-bg: ", ";\n --color-controlpanel-ramp-slider: ", ";\n\n --color-landingpage-bg: ", ";\n --color-landingpage-bg-alt: ", ";\n --color-landingpage-text: ", ";\n --color-landingpage-banner-highlight-bg: ", ";\n\n --color-statusflag-border: ", ";\n --color-statusflag-text: ", ";\n\n --color-layout-dividers: ", ";\n\n --color-modal-border: ", ";\n\n --color-menu-hover-text: ", ";\n --color-menu-selected-text: ", ";\n\n --color-checkbox-bg: ", ";\n\n --font-family: ", ";\n "])), $theme.colors.text.link, $theme.colors.text.header, $theme.colors.text.section, $theme.colors.text.body, $theme.colors.text.error, $theme.colors.text.selectionBg, $theme.colors.text.selectionText, $theme.colors.header.title, $theme.colors.header.hoverTitle, $theme.colors.header.bg, $theme.colors.header.border, $theme.colors.button.primary.bg, $theme.colors.button.primary.text, $theme.colors.button.primary.hoverBg, $theme.colors.button.primary.hoverBg, $theme.colors.button.primary.activeOutline, $theme.colors.button.primary.disabledBg, $theme.colors.button.link.text, $theme.colors.button.secondary.bg, $theme.colors.button.secondary.text, $theme.colors.button.secondary.outline, $theme.colors.button.tertiary.text, $theme.colors.button.tertiary.outline, $theme.colors.button.tertiary.hoverOutline, $theme.colors.button.tertiary.hoverText, $theme.colors.button.tertiary.activeOutline, $theme.colors.button.tertiary.hoverText, $theme.colors.button.tertiary.disabledText, $theme.colors.button.tertiary.disabledText, $theme.colors.button.tertiary.activatedText, $theme.colors.button.tertiary.activatedBg, $theme.colors.button.tertiary.activatedOutline, $theme.colors.toolbar.buttonBg, $theme.colors.controlPanel.bg, $theme.colors.controlPanel.border, $theme.colors.controlPanel.sectionText, $theme.colors.controlPanel.text, $theme.colors.controlPanel.sectionBg, $theme.colors.controlPanel.drawerBg, $theme.colors.controlPanel.rampSlider, $theme.colors.landingPage.bg, $theme.colors.landingPage.bgAlt, $theme.colors.landingPage.text, $theme.colors.landingPage.bannerBg, $theme.colors.statusFlag.border, $theme.colors.statusFlag.text, $theme.colors.layout.dividers, $theme.colors.modal.border, $theme.colors.menu.hoverText, $theme.colors.menu.selectedText, $theme.colors.checkbox.bg, $theme.fonts.family);
|
|
140
140
|
});
|