@aics/vole-app 3.2.0 → 3.2.2

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/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Vol-E App
2
2
 
3
+ <p>
4
+ <a href="https://www.npmjs.com/package/@aics/vole-app"><img src="https://img.shields.io/npm/v/%40aics%2Fvole-app" alt="npm package"></a>
5
+ </p>
6
+
3
7
  Volume Explorer (Vol-E) is a browser based volume viewer built with React and WebGL (Three.js). This package wraps the [vole-core](https://github.com/allen-cell-animated/vole-core) library.
4
8
 
5
9
  For the latest stable release, please visit [https://vole.allencell.org](https://vole.allencell.org)
@@ -4,14 +4,13 @@ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r)
4
4
  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; }
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
- import { Button, Checkbox, List } from "antd";
7
+ import { Button, Checkbox } from "antd";
8
8
  import React, { useCallback, useState } from "react";
9
- import { colorArrayToObject, colorObjectToArray } from "../../shared/utils/colorRepresentations";
10
- import { select, useViewerState } from "../../state/store";
11
- import ColorPicker from "../ColorPicker";
12
- import ViewerIcon from "../shared/ViewerIcon";
13
- import TfEditor from "../TfEditor";
14
- import "./styles.css";
9
+ import { colorArrayToObject, colorObjectToArray } from "../shared/utils/colorRepresentations";
10
+ import { select, useViewerState } from "../state/store";
11
+ import ControlPanelRow from "./shared/ControlPanelRow";
12
+ import ViewerIcon from "./shared/ViewerIcon";
13
+ import TfEditor from "./TfEditor";
15
14
  var ChannelsWidgetRow = function ChannelsWidgetRow(props) {
16
15
  var index = props.index,
17
16
  saveIsosurface = props.saveIsosurface;
@@ -52,22 +51,12 @@ var ChannelsWidgetRow = function ChannelsWidgetRow(props) {
52
51
  isosurfaceEnabled: target.checked
53
52
  });
54
53
  };
55
- var onColorChange = function onColorChange(newRGB, _oldRGB, index) {
54
+ var onColorChange = useCallback(function (newRGB) {
56
55
  var color = colorObjectToArray(newRGB);
57
56
  changeChannelSetting(index, {
58
57
  color: color
59
58
  });
60
- };
61
- var createColorPicker = function createColorPicker() {
62
- return /*#__PURE__*/React.createElement(ColorPicker, {
63
- color: colorArrayToObject(channelState.color),
64
- onColorChange: onColorChange,
65
- onColorChangeComplete: props.onColorChangeComplete,
66
- disableAlpha: true,
67
- idx: index,
68
- width: 18
69
- });
70
- };
59
+ }, [index, changeChannelSetting]);
71
60
  var thisChannelOnly = singleChannelMode && singleChannelIndex === index;
72
61
  var visibilityControls = singleChannelMode ? /*#__PURE__*/React.createElement("div", {
73
62
  className: "channel-visibility-controls".concat(thisChannelOnly ? " single-channel" : "")
@@ -134,15 +123,17 @@ var ChannelsWidgetRow = function ChannelsWidgetRow(props) {
134
123
  saveIsosurface: saveThisIsosurface
135
124
  });
136
125
  };
137
- var rowClass = "channel-row".concat(controlsOpen ? "" : " controls-closed").concat(thisChannelOnly ? " single-channel" : "");
138
- return /*#__PURE__*/React.createElement(List.Item, {
126
+ var rowClass = controlsOpen ? "" : " controls-closed";
127
+ return /*#__PURE__*/React.createElement(ControlPanelRow, {
139
128
  key: index,
140
- className: rowClass,
141
- onClick: onClickChannel
142
- }, /*#__PURE__*/React.createElement(List.Item.Meta, {
143
129
  title: props.name,
144
- avatar: createColorPicker()
145
- }), visibilityControls, controlsOpen && /*#__PURE__*/React.createElement("div", {
130
+ color: colorArrayToObject(channelState.color),
131
+ onColorChange: onColorChange,
132
+ onColorChangeComplete: props.onColorChangeComplete,
133
+ onClick: onClickChannel,
134
+ className: rowClass,
135
+ highlight: thisChannelOnly
136
+ }, visibilityControls, controlsOpen && /*#__PURE__*/React.createElement("div", {
146
137
  style: {
147
138
  width: "100%"
148
139
  }
@@ -44,13 +44,13 @@ var ColorPicker = function ColorPicker(props) {
44
44
  var _props$onColorChange;
45
45
  setCurrentColor(color.rgb);
46
46
  // supply onColorChange callback in props.
47
- (_props$onColorChange = props.onColorChange) === null || _props$onColorChange === void 0 || _props$onColorChange.call(props, color.rgb, currentColor, props.idx);
47
+ (_props$onColorChange = props.onColorChange) === null || _props$onColorChange === void 0 || _props$onColorChange.call(props, color.rgb, currentColor);
48
48
  };
49
49
  var handleChangeComplete = function handleChangeComplete(color) {
50
50
  var _props$onColorChangeC;
51
51
  setCurrentColor(color.rgb);
52
52
  // supply onColorChange callback in props.
53
- (_props$onColorChangeC = props.onColorChangeComplete) === null || _props$onColorChangeC === void 0 || _props$onColorChangeC.call(props, color.rgb, currentColor, props.idx);
53
+ (_props$onColorChangeC = props.onColorChangeComplete) === null || _props$onColorChangeC === void 0 || _props$onColorChangeC.call(props, color.rgb, currentColor);
54
54
  };
55
55
  React.useEffect(function () {
56
56
  return setCurrentColor(props.color);
@@ -8,10 +8,6 @@
8
8
  border-right:1px solid var(--color-controlpanel-border);
9
9
  }
10
10
 
11
- .control-panel-col-container .ant-checkbox-wrapper{
12
- align-items:center;
13
- }
14
-
15
11
  .control-panel-col-container .control-panel-tab-col{
16
12
  text-align:center;
17
13
  }
@@ -52,7 +48,6 @@
52
48
  }
53
49
 
54
50
  .control-panel-col-container .control-panel-col{
55
- flex:1 auto;
56
51
  max-width:540px;
57
52
  overflow-y:scroll;
58
53
  scrollbar-width:none;
@@ -86,20 +81,14 @@
86
81
  border-top:1px solid var(--color-controlpanel-border);
87
82
  }
88
83
 
89
- .control-panel-col-container .control-panel-col .control-panel-content .ant-list-item-meta .ant-list-item-meta-title{
90
- margin:0;
91
- }
92
-
93
84
  .control-panel-col-container .control-panel-col .control-panel-content .channel-visibility-controls,
94
85
  .control-panel-col-container .control-panel-col .control-panel-content .ant-collapse-extra{
86
+ align-self:end;
95
87
  width:40%;
96
88
  display:flex;
97
89
  }
98
90
 
99
- .control-panel-col-container .control-panel-col .control-panel-content .channel-visibility-controls .ant-checkbox-wrapper,
100
- .control-panel-col-container .control-panel-col .control-panel-content .channel-visibility-controls .single-channel-text,
101
- .control-panel-col-container .control-panel-col .control-panel-content .ant-collapse-extra .ant-checkbox-wrapper,
102
- .control-panel-col-container .control-panel-col .control-panel-content .ant-collapse-extra .single-channel-text{
91
+ .control-panel-col-container .control-panel-col .control-panel-content .channel-visibility-controls .ant-checkbox-wrapper, .control-panel-col-container .control-panel-col .control-panel-content .ant-collapse-extra .ant-checkbox-wrapper{
103
92
  flex:4;
104
93
  }
105
94
 
@@ -128,38 +117,6 @@
128
117
  border-bottom:1px solid var(--color-controlpanel-border);
129
118
  }
130
119
 
131
- .control-panel-col-container .control-panel-col .ant-list-item,
132
- .control-panel-col-container .control-panel-col .color-picker-row{
133
- padding:0 16px;
134
- border-bottom:none;
135
- display:flex;
136
- flex-flow:row wrap;
137
- color:var(--color-controlpanel-text);
138
- }
139
-
140
- .control-panel-col-container .control-panel-col .ant-list-item::after, .control-panel-col-container .control-panel-col .color-picker-row::after{
141
- content:"";
142
- margin-top:22px;
143
- width:100%;
144
- border-bottom:1px solid var(--color-controlpanel-border);
145
- }
146
-
147
- .control-panel-col-container .control-panel-col .ant-list-item{
148
- padding-top:22px;
149
- }
150
-
151
- .control-panel-col-container .control-panel-col .ant-list-item::after{
152
- margin-top:22px;
153
- }
154
-
155
- .control-panel-col-container .control-panel-col .color-picker-row{
156
- padding-top:16px;
157
- }
158
-
159
- .control-panel-col-container .control-panel-col .color-picker-row::after{
160
- margin-top:16px;
161
- }
162
-
163
120
  .control-panel-col-container .control-panel-col .noUi-horizontal .noUi-handle{
164
121
  box-shadow:none;
165
122
  cursor:pointer;
@@ -1,43 +1,26 @@
1
1
  import React from "react";
2
2
  import { colorArrayToObject, colorObjectToArray } from "../shared/utils/colorRepresentations";
3
3
  import { select, useViewerState } from "../state/store";
4
- import ColorPicker from "./ColorPicker";
5
- var ColorPickerRow = function ColorPickerRow(_ref) {
6
- var color = _ref.color,
7
- _onColorChange = _ref.onColorChange,
8
- children = _ref.children;
9
- return /*#__PURE__*/React.createElement("div", {
10
- className: "color-picker-row"
11
- }, /*#__PURE__*/React.createElement("span", {
12
- style: {
13
- marginRight: "16px",
14
- display: "flex",
15
- alignItems: "center"
16
- }
17
- }, /*#__PURE__*/React.createElement(ColorPicker, {
18
- color: colorArrayToObject(color),
19
- onColorChange: function onColorChange(color) {
20
- return _onColorChange(colorObjectToArray(color));
21
- },
22
- width: 18,
23
- disableAlpha: true
24
- })), /*#__PURE__*/React.createElement("span", null, children));
25
- };
4
+ import ControlPanelRow from "./shared/ControlPanelRow";
26
5
  var CustomizeWidget = function CustomizeWidget(props) {
27
6
  var showBoundingBox = useViewerState(select("showBoundingBox"));
28
7
  var backgroundColor = useViewerState(select("backgroundColor"));
29
8
  var boundingBoxColor = useViewerState(select("boundingBoxColor"));
30
9
  var changeViewerSetting = useViewerState(select("changeViewerSetting"));
31
- return /*#__PURE__*/React.createElement(React.Fragment, null, props.visibleControls.backgroundColorPicker && /*#__PURE__*/React.createElement(ColorPickerRow, {
32
- color: backgroundColor,
10
+ return /*#__PURE__*/React.createElement(React.Fragment, null, props.visibleControls.backgroundColorPicker && /*#__PURE__*/React.createElement(ControlPanelRow, {
11
+ color: colorArrayToObject(backgroundColor),
33
12
  onColorChange: function onColorChange(color) {
34
- return changeViewerSetting("backgroundColor", color);
35
- }
36
- }, "Background color"), props.visibleControls.boundingBoxColorPicker && /*#__PURE__*/React.createElement(ColorPickerRow, {
37
- color: boundingBoxColor,
13
+ return changeViewerSetting("backgroundColor", colorObjectToArray(color));
14
+ },
15
+ title: "Background color",
16
+ verticalMargin: 16
17
+ }), props.visibleControls.boundingBoxColorPicker && /*#__PURE__*/React.createElement(ControlPanelRow, {
18
+ color: colorArrayToObject(boundingBoxColor),
38
19
  onColorChange: function onColorChange(color) {
39
- return changeViewerSetting("boundingBoxColor", color);
40
- }
41
- }, "Bounding box color", !showBoundingBox && /*#__PURE__*/React.createElement("i", null, " - bounding box turned off")));
20
+ return changeViewerSetting("boundingBoxColor", colorObjectToArray(color));
21
+ },
22
+ title: /*#__PURE__*/React.createElement(React.Fragment, null, "Bounding box color", !showBoundingBox && /*#__PURE__*/React.createElement("i", null, " - bounding box turned off")),
23
+ verticalMargin: 16
24
+ }));
42
25
  };
43
26
  export default CustomizeWidget;
@@ -613,7 +613,7 @@ var TfEditor = function TfEditor(props) {
613
613
  rawMin = _props$channelData.rawMin,
614
614
  rawMax = _props$channelData.rawMax;
615
615
  return /*#__PURE__*/React.createElement("div", {
616
- className: "tf-editor"
616
+ className: "aics-tf-editor"
617
617
  }, /*#__PURE__*/React.createElement("div", {
618
618
  className: "tf-editor-control-row"
619
619
  }, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Button, {
@@ -1,22 +1,22 @@
1
- .channel-row .tf-editor{
1
+ .aics-tf-editor{
2
2
  margin-top:27px;
3
3
  }
4
4
 
5
- .channel-row .tf-editor .tf-editor-svg.dragging-slider{
5
+ .aics-tf-editor .tf-editor-svg.dragging-slider{
6
6
  cursor:ew-resize;
7
7
  }
8
8
 
9
- .channel-row .tf-editor .tf-editor-svg.dragging-point{
9
+ .aics-tf-editor .tf-editor-svg.dragging-point{
10
10
  cursor:move;
11
11
  }
12
12
 
13
- .channel-row .tf-editor .tf-editor-popover{
13
+ .aics-tf-editor .tf-editor-popover{
14
14
  position:absolute;
15
15
  z-index:9999;
16
16
  width:100%;
17
17
  }
18
18
 
19
- .channel-row .tf-editor .tf-editor-cover{
19
+ .aics-tf-editor .tf-editor-cover{
20
20
  position:fixed;
21
21
  top:0;
22
22
  left:0;
@@ -24,7 +24,7 @@
24
24
  bottom:0;
25
25
  }
26
26
 
27
- .channel-row .tf-editor .tf-editor-control-row{
27
+ .aics-tf-editor .tf-editor-control-row{
28
28
  display:flex;
29
29
  color:var(--color-controlpanel-text);
30
30
  justify-content:space-between;
@@ -32,31 +32,31 @@
32
32
  min-height:24px;
33
33
  }
34
34
 
35
- .channel-row .tf-editor .tf-editor-control-row:not(:first-child){
35
+ .aics-tf-editor .tf-editor-control-row:not(:first-child){
36
36
  margin-bottom:12px;
37
37
  }
38
38
 
39
- .channel-row .tf-editor .tf-editor-control-row > div{
39
+ .aics-tf-editor .tf-editor-control-row > div{
40
40
  display:flex;
41
41
  gap:5px;
42
42
  }
43
43
 
44
- .channel-row .tf-editor .tf-editor-control-row .ant-input-number{
44
+ .aics-tf-editor .tf-editor-control-row .ant-input-number{
45
45
  border-color:var(--color-button-tertiary-outline);
46
46
  width:64px;
47
47
  }
48
48
 
49
- .channel-row .tf-editor .tf-editor-control-row .ant-input-number input{
49
+ .aics-tf-editor .tf-editor-control-row .ant-input-number input{
50
50
  text-align:right;
51
51
  }
52
52
 
53
- .channel-row .tf-editor h4{
53
+ .aics-tf-editor h4{
54
54
  font-size:16px;
55
55
  margin-top:0;
56
56
  margin-bottom:12px;
57
57
  }
58
58
 
59
- .channel-row .tf-editor .tick text{
59
+ .aics-tf-editor .tick text{
60
60
  fill:var(--color-controlpanel-text);
61
61
  user-select:none;
62
62
  -o-user-select:none;
@@ -65,58 +65,58 @@
65
65
  -webkit-user-select:none;
66
66
  }
67
67
 
68
- .channel-row .tf-editor rect.bar{
68
+ .aics-tf-editor rect.bar{
69
69
  fill:var(--color-controlpanel-border);
70
70
  }
71
71
 
72
- .channel-row .tf-editor .axis path,
73
- .channel-row .tf-editor .axis line{
72
+ .aics-tf-editor .axis path,
73
+ .aics-tf-editor .axis line{
74
74
  stroke:var(--color-controlpanel-border);
75
75
  }
76
76
 
77
- .channel-row .tf-editor rect{
77
+ .aics-tf-editor rect{
78
78
  fill:none;
79
79
  pointer-events:all;
80
80
  }
81
81
 
82
- .channel-row .tf-editor .line{
82
+ .aics-tf-editor .line{
83
83
  stroke:#aeacae;
84
84
  stroke-width:1px;
85
85
  }
86
86
 
87
- .channel-row .tf-editor .sliders path,
88
- .channel-row .tf-editor .sliders line{
87
+ .aics-tf-editor .sliders path,
88
+ .aics-tf-editor .sliders line{
89
89
  cursor:ew-resize;
90
90
  }
91
91
 
92
- .channel-row .tf-editor .sliders line.slider-click-target{
92
+ .aics-tf-editor .sliders line.slider-click-target{
93
93
  stroke:transparent;
94
94
  }
95
95
 
96
- .channel-row .tf-editor .sliders.sliders-ramp path{
96
+ .aics-tf-editor .sliders.sliders-ramp path{
97
97
  fill:var(--color-controlpanel-ramp-slider);
98
98
  }
99
99
 
100
- .channel-row .tf-editor .sliders.sliders-ramp line:not(.slider-click-target){
100
+ .aics-tf-editor .sliders.sliders-ramp line:not(.slider-click-target){
101
101
  stroke:var(--color-controlpanel-ramp-slider);
102
102
  }
103
103
 
104
- .channel-row .tf-editor .sliders.sliders-isovalue path{
104
+ .aics-tf-editor .sliders.sliders-isovalue path{
105
105
  fill:var(--color-controlpanel-isovalue-slider);
106
106
  }
107
107
 
108
- .channel-row .tf-editor .sliders.sliders-isovalue line:not(.slider-click-target){
108
+ .aics-tf-editor .sliders.sliders-isovalue line:not(.slider-click-target){
109
109
  stroke:var(--color-controlpanel-isovalue-slider);
110
110
  }
111
111
 
112
- .channel-row .tf-editor circle{
112
+ .aics-tf-editor circle{
113
113
  fill-opacity:0.6;
114
114
  cursor:move;
115
115
  stroke:#aeacae;
116
116
  stroke-width:1.5px;
117
117
  }
118
118
 
119
- .channel-row .tf-editor circle.selected{
119
+ .aics-tf-editor circle.selected{
120
120
  fill:white;
121
121
  stroke:white;
122
122
  }
@@ -0,0 +1,48 @@
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 _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
3
+ 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; }
4
+ 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; }
5
+ 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; }
6
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
7
+ 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); }
8
+ import React from "react";
9
+ import ColorPicker from "../../ColorPicker";
10
+ import "./styles.css";
11
+ var defaultProps = {
12
+ verticalMargin: 22,
13
+ showColorPicker: true,
14
+ color: {
15
+ r: 255,
16
+ g: 255,
17
+ b: 255
18
+ },
19
+ highlight: false
20
+ };
21
+ var ControlPanelRow = function ControlPanelRow(inputProps) {
22
+ var props = _objectSpread(_objectSpread({}, defaultProps), inputProps);
23
+ var color = props.color,
24
+ onColorChange = props.onColorChange,
25
+ onColorChangeComplete = props.onColorChangeComplete;
26
+ var colorPickerProps = {
27
+ color: color,
28
+ onColorChange: onColorChange,
29
+ onColorChangeComplete: onColorChangeComplete
30
+ };
31
+ var style = {
32
+ "--control-panel-row-vertical-margin": props.verticalMargin + "px"
33
+ };
34
+ var createTitle = props.title !== undefined || props.showColorPicker;
35
+ var baseClass = "control-panel-row".concat(props.highlight ? " control-panel-row-highlight" : "");
36
+ var className = props.className ? "".concat(baseClass, " ").concat(props.className) : baseClass;
37
+ return /*#__PURE__*/React.createElement("div", {
38
+ className: className,
39
+ style: style,
40
+ onClick: props.onClick
41
+ }, createTitle && /*#__PURE__*/React.createElement("div", {
42
+ className: "control-panel-row-title"
43
+ }, props.showColorPicker && /*#__PURE__*/React.createElement(ColorPicker, _extends({
44
+ disableAlpha: true,
45
+ width: 18
46
+ }, colorPickerProps)), props.title && /*#__PURE__*/React.createElement("h4", null, props.title)), props.children);
47
+ };
48
+ export default ControlPanelRow;
@@ -0,0 +1,64 @@
1
+ .control-panel-col .control-panel-row{
2
+ padding:var(--control-panel-row-vertical-margin) 16px 0;
3
+ display:flex;
4
+ flex-flow:row wrap;
5
+ justify-content:space-between;
6
+ color:var(--color-controlpanel-text);
7
+ }
8
+
9
+ .control-panel-col .control-panel-row .ant-checkbox-wrapper{
10
+ color:var(--color-controlpanel-text);
11
+ }
12
+
13
+ .control-panel-col .control-panel-row .control-panel-row-title{
14
+ display:flex;
15
+ align-items:center;
16
+ flex-grow:1;
17
+ }
18
+
19
+ .control-panel-col .control-panel-row .control-panel-row-title .color-picker{
20
+ margin-right:16px;
21
+ }
22
+
23
+ .control-panel-col .control-panel-row .control-panel-row-title h4{
24
+ margin:0;
25
+ }
26
+
27
+ .control-panel-col .control-panel-row .ant-btn-text{
28
+ color:var(--color-button-icon-activated-text);
29
+ transition:color 0.3s;
30
+ }
31
+
32
+ .control-panel-col .control-panel-row .ant-btn-text:hover,
33
+ .control-panel-col .control-panel-row .ant-btn-text:focus-visible{
34
+ color:var(--color-button-tertiary-hover-text) !important;
35
+ }
36
+
37
+ .control-panel-col .control-panel-row.controls-closed .ant-btn-text:not(:focus-visible){
38
+ color:var(--color-controlpanel-text);
39
+ }
40
+
41
+ .control-panel-col .control-panel-row.control-panel-row-highlight{
42
+ background-color:var(--color-button-primary-bg);
43
+ }
44
+
45
+ .control-panel-col .control-panel-row.control-panel-row-highlight,
46
+ .control-panel-col .control-panel-row.control-panel-row-highlight h4{
47
+ color:var(--color-button-primary-text);
48
+ font-weight:600;
49
+ }
50
+
51
+ .control-panel-col .control-panel-row.control-panel-row-highlight .color-picker .color-picker-swatch{
52
+ border-color:var(--color-button-primary-text);
53
+ }
54
+
55
+ .control-panel-col .control-panel-row::after{
56
+ content:"";
57
+ margin-top:var(--control-panel-row-vertical-margin);
58
+ width:100%;
59
+ border-bottom:1px solid var(--color-controlpanel-border);
60
+ }
61
+
62
+ .control-panel-col .ant-collapse-item:not(:last-child) .control-panel-row:last-child::after{
63
+ border-bottom:none;
64
+ }
@@ -196,11 +196,12 @@ export function readStoredMetadata(scenes) {
196
196
  var skipCacheUpdate = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
197
197
  var keySet = new Set();
198
198
  var result = scenes.map(function (scene) {
199
- if (Array.isArray(scene)) {
200
- // can't handle multi-source scenes (yet)
199
+ // can't handle multi-source scenes (yet)
200
+ var firstScene = Array.isArray(scene) ? scene[0] : scene;
201
+ if (firstScene === undefined) {
201
202
  return undefined;
202
203
  }
203
- var globalKey = "".concat(StorageEntryType.Meta, "@").concat(sanitizeStorageKey(scene));
204
+ var globalKey = "".concat(StorageEntryType.Meta, "@").concat(sanitizeStorageKey(firstScene));
204
205
  var meta = window.localStorage.getItem(globalKey);
205
206
  if (meta === null) {
206
207
  return undefined;
@@ -151,7 +151,7 @@ describe("writeMetadata/readStoredMetadata", function () {
151
151
  });
152
152
  expect(tooMany).toBe(false);
153
153
  });
154
- it("returns `undefined` on an attempt to get an array key", function () {
154
+ it("returns metadata for only the first URL when it receives an array key", function () {
155
155
  writeMetadata({
156
156
  one: {
157
157
  digits: 1
@@ -164,7 +164,9 @@ describe("writeMetadata/readStoredMetadata", function () {
164
164
  digits: 1
165
165
  }, {
166
166
  digits: 12
167
- }, undefined]);
167
+ }, {
168
+ digits: 1
169
+ }]);
168
170
  });
169
171
  });
170
172
  describe("writeScenes/readStoredScenes", function () {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aics/vole-app",
3
- "version": "3.2.0",
3
+ "version": "3.2.2",
4
4
  "description": "web view of cell volume images",
5
5
  "main": "es/index.js",
6
6
  "module": "es/index.js",
@@ -1,8 +1,7 @@
1
1
  import type { Channel } from "@aics/vole-core";
2
2
  import React from "react";
3
- import type { IsosurfaceFormat } from "../../shared/types";
4
- import { type ColorObject } from "../../shared/utils/colorRepresentations";
5
- import "./styles.css";
3
+ import type { IsosurfaceFormat } from "../shared/types";
4
+ import { type ColorObject } from "../shared/utils/colorRepresentations";
6
5
  interface ChannelsWidgetRowProps {
7
6
  index: number;
8
7
  name: string;
@@ -1,13 +1,12 @@
1
1
  import React from "react";
2
2
  import type { ColorObject } from "../../shared/utils/colorRepresentations";
3
3
  import "./styles.css";
4
- type ColorChangeHandler = (currentColor: ColorObject, prevColor?: ColorObject, idx?: number) => void;
5
- interface ColorPickerProps {
4
+ type ColorChangeHandler = (currentColor: ColorObject, prevColor: ColorObject) => void;
5
+ export interface ColorPickerProps {
6
6
  color: ColorObject;
7
7
  width: number;
8
8
  onColorChange?: ColorChangeHandler;
9
9
  onColorChangeComplete?: ColorChangeHandler;
10
- idx?: any;
11
10
  disableAlpha?: boolean;
12
11
  }
13
12
  declare const ColorPicker: React.FC<ColorPickerProps>;
@@ -0,0 +1,14 @@
1
+ import React from "react";
2
+ import { type ColorPickerProps } from "../../ColorPicker";
3
+ import "./styles.css";
4
+ type ColorPickerPropPassthru = Partial<Pick<ColorPickerProps, "color" | "onColorChange" | "onColorChangeComplete">>;
5
+ export type ControlPanelRowProps = React.PropsWithChildren<ColorPickerPropPassthru & {
6
+ verticalMargin?: number;
7
+ showColorPicker?: boolean;
8
+ title?: React.ReactNode;
9
+ onClick?: React.MouseEventHandler;
10
+ className?: string;
11
+ highlight?: boolean;
12
+ }>;
13
+ declare const ControlPanelRow: React.FC<ControlPanelRowProps>;
14
+ export default ControlPanelRow;
@@ -1,48 +0,0 @@
1
- .control-panel-content .ant-list-item.channel-row .ant-list-item-meta-title,
2
- .control-panel-content .ant-list-item.channel-row .ant-checkbox-wrapper{
3
- color:var(--color-controlpanel-text);
4
- }
5
-
6
- .control-panel-content .ant-list-item.channel-row .ant-list-item-meta{
7
- align-items:center;
8
- }
9
-
10
- .control-panel-content .ant-list-item.channel-row .ant-btn-text{
11
- color:var(--color-button-icon-activated-text);
12
- transition:color 0.3s;
13
- }
14
-
15
- .control-panel-content .ant-list-item.channel-row .ant-btn-text:hover,
16
- .control-panel-content .ant-list-item.channel-row .ant-btn-text:focus-visible{
17
- color:var(--color-button-tertiary-hover-text) !important;
18
- }
19
-
20
- .control-panel-content .ant-list-item.channel-row .button-row{
21
- margin-top:16px;
22
- display:flex;
23
- justify-content:start;
24
- align-items:end;
25
- gap:5px;
26
- }
27
-
28
- .control-panel-content .ant-list-item.channel-row .button-row .ant-btn.ant-btn-sm{
29
- padding:12px 8px;
30
- }
31
-
32
- .control-panel-content .ant-list-item.channel-row.controls-closed .ant-btn-text:not(:focus-visible){
33
- color:var(--color-controlpanel-text);
34
- }
35
-
36
- .control-panel-content .ant-list-item.channel-row.single-channel{
37
- background-color:var(--color-button-primary-bg);
38
- }
39
-
40
- .control-panel-content .ant-list-item.channel-row.single-channel .channel-visibility-controls,
41
- .control-panel-content .ant-list-item.channel-row.single-channel .ant-list-item-meta-title{
42
- color:var(--color-button-primary-text);
43
- font-weight:600;
44
- }
45
-
46
- .control-panel-content .ant-list-item.channel-row.single-channel .color-picker .color-picker-swatch{
47
- border-color:var(--color-button-primary-text);
48
- }