@vitessce/all 3.9.7 → 3.9.8

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.
@@ -9398,6 +9398,7 @@ const CoordinationType$1 = {
9398
9398
  SPATIAL_LAYER_MODEL_MATRIX: "spatialLayerModelMatrix",
9399
9399
  SPATIAL_SEGMENTATION_FILLED: "spatialSegmentationFilled",
9400
9400
  SPATIAL_SEGMENTATION_STROKE_WIDTH: "spatialSegmentationStrokeWidth",
9401
+ SPATIAL_POINT_STROKE_WIDTH: "spatialPointStrokeWidth",
9401
9402
  SPATIAL_CHANNEL_COLOR: "spatialChannelColor",
9402
9403
  SPATIAL_CHANNEL_VISIBLE: "spatialChannelVisible",
9403
9404
  SPATIAL_CHANNEL_OPACITY: "spatialChannelOpacity",
@@ -9793,7 +9794,8 @@ const COMPONENT_COORDINATION_TYPES = {
9793
9794
  CoordinationType$1.SPATIAL_CHANNEL_COLOR,
9794
9795
  CoordinationType$1.SPATIAL_CHANNEL_OPACITY,
9795
9796
  CoordinationType$1.SPATIAL_CHANNEL_VISIBLE,
9796
- CoordinationType$1.LEGEND_VISIBLE
9797
+ CoordinationType$1.LEGEND_VISIBLE,
9798
+ CoordinationType$1.SPATIAL_POINT_STROKE_WIDTH
9797
9799
  ],
9798
9800
  [ViewType$1.SCATTERPLOT]: [
9799
9801
  CoordinationType$1.DATASET,
@@ -10177,6 +10179,7 @@ const COMPONENT_COORDINATION_TYPES = {
10177
10179
  CoordinationType$1.SPATIAL_CHANNEL_COLOR,
10178
10180
  CoordinationType$1.SPATIAL_SEGMENTATION_FILLED,
10179
10181
  CoordinationType$1.SPATIAL_SEGMENTATION_STROKE_WIDTH,
10182
+ CoordinationType$1.SPATIAL_POINT_STROKE_WIDTH,
10180
10183
  CoordinationType$1.IMAGE_CHANNEL,
10181
10184
  CoordinationType$1.IMAGE_LAYER,
10182
10185
  CoordinationType$1.SEGMENTATION_CHANNEL,
@@ -10915,6 +10918,8 @@ const ngPrecomputedMeshSchema = z.object({
10915
10918
  // projectionScale: z.number(),
10916
10919
  // position: z.array(z.number()).length(3),
10917
10920
  // projectionOrientation: z.array(z.number()).length(4),
10921
+ subsources: z.record(z.boolean()).describe("Subsources are the individual data components of a source (e.g. meshes, skeletons, etc.). Each entry explicitly enables or disables a subsource.").optional(),
10922
+ enableDefaultSubsources: z.boolean().describe("When true (default), automatically loads all subsources (defined in mesh metadata), when false loads what is explicitly enabled in `subsources`.").optional()
10918
10923
  }).partial().nullable();
10919
10924
  const ngPointAnnotationSchema = z.object({
10920
10925
  projectionAnnotationSpacing: z.number(),
@@ -19229,7 +19234,7 @@ const { tss } = createTss({
19229
19234
  },
19230
19235
  "usePlugin": useMuiThemeStyleOverridesPlugin
19231
19236
  });
19232
- const useStyles$w = tss.create({});
19237
+ const useStyles$x = tss.create({});
19233
19238
  function createChainedFunction$1(...funcs) {
19234
19239
  return funcs.reduce((acc, func) => {
19235
19240
  if (func == null) {
@@ -23342,7 +23347,7 @@ IconButton$1.propTypes = {
23342
23347
  */
23343
23348
  sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])
23344
23349
  };
23345
- const ClearIcon = createSvgIcon(/* @__PURE__ */ jsxRuntimeExports.jsx("path", {
23350
+ const ClearIcon$1 = createSvgIcon(/* @__PURE__ */ jsxRuntimeExports.jsx("path", {
23346
23351
  d: "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"
23347
23352
  }), "Close");
23348
23353
  const usePreviousProps = (value2) => {
@@ -28351,7 +28356,7 @@ const Autocomplete = /* @__PURE__ */ React.forwardRef(function Autocomplete2(inP
28351
28356
  blurOnSelect = false,
28352
28357
  ChipProps: ChipPropsProp,
28353
28358
  className,
28354
- clearIcon = _ClearIcon || (_ClearIcon = /* @__PURE__ */ jsxRuntimeExports.jsx(ClearIcon, {
28359
+ clearIcon = _ClearIcon || (_ClearIcon = /* @__PURE__ */ jsxRuntimeExports.jsx(ClearIcon$1, {
28355
28360
  fontSize: "small"
28356
28361
  })),
28357
28362
  clearOnBlur = !props.freeSolo,
@@ -46666,6 +46671,9 @@ const VisibilityIcon = createSvgIcon(/* @__PURE__ */ jsxRuntimeExports.jsx("path
46666
46671
  const VisibilityOffIcon = createSvgIcon(/* @__PURE__ */ jsxRuntimeExports.jsx("path", {
46667
46672
  d: "M12 7c2.76 0 5 2.24 5 5 0 .65-.13 1.26-.36 1.83l2.92 2.92c1.51-1.26 2.7-2.89 3.43-4.75-1.73-4.39-6-7.5-11-7.5-1.4 0-2.74.25-3.98.7l2.16 2.16C10.74 7.13 11.35 7 12 7M2 4.27l2.28 2.28.46.46C3.08 8.3 1.78 10.02 1 12c1.73 4.39 6 7.5 11 7.5 1.55 0 3.03-.3 4.38-.84l.42.42L19.73 22 21 20.73 3.27 3zM7.53 9.8l1.55 1.55c-.05.21-.08.43-.08.65 0 1.66 1.34 3 3 3 .22 0 .44-.03.65-.08l1.55 1.55c-.67.33-1.41.53-2.2.53-2.76 0-5-2.24-5-5 0-.79.2-1.53.53-2.2m4.31-.78 3.15 3.15.02-.16c0-1.66-1.34-3-3-3z"
46668
46673
  }), "VisibilityOff");
46674
+ const ClearIcon = createSvgIcon(/* @__PURE__ */ jsxRuntimeExports.jsx("path", {
46675
+ d: "M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"
46676
+ }), "Clear");
46669
46677
  const reactMajor = parseInt(React.version, 10);
46670
46678
  const forwardRef = (render2) => {
46671
46679
  if (reactMajor >= 19) {
@@ -73523,7 +73531,7 @@ const Popper = React.forwardRef((props, ref2) => {
73523
73531
  }, [handlePopperRef]);
73524
73532
  React.useImperativeHandle(popperRefProp, () => popperRef.current, []);
73525
73533
  const [exited, setExited] = React.useState(true);
73526
- const { theme } = useStyles$w();
73534
+ const { theme } = useStyles$x();
73527
73535
  const rtlPlacement = flipPlacement(initialPlacement, theme);
73528
73536
  const [placement, setPlacement] = React.useState(rtlPlacement);
73529
73537
  React.useEffect(() => {
@@ -74257,7 +74265,7 @@ var VariableSizeList$1 = /* @__PURE__ */ createListComponent({
74257
74265
  });
74258
74266
  const VariableSizeList = VariableSizeList$1;
74259
74267
  const LIST_ROW_HEIGHT$1 = 48;
74260
- const useStyles$v = makeStyles()(() => ({
74268
+ const useStyles$w = makeStyles()(() => ({
74261
74269
  searchInput: {
74262
74270
  lineHeight: "initial",
74263
74271
  height: "auto !important"
@@ -74297,7 +74305,7 @@ const ListboxComponent$1 = React__default.forwardRef((props, ref2) => {
74297
74305
  });
74298
74306
  function SimpleAutocomplete(props) {
74299
74307
  const { getMatches, onChange, textInputLabel = "Enter a gene", getItemLabel = (option) => option.label } = props;
74300
- const { classes: classes2 } = useStyles$v();
74308
+ const { classes: classes2 } = useStyles$w();
74301
74309
  const [potentialItems, setPotentialItems] = useState([]);
74302
74310
  const handleInputChange = async (_event, value2) => {
74303
74311
  if (!value2) {
@@ -83847,7 +83855,7 @@ function defaultUrlTransform(value2) {
83847
83855
  }
83848
83856
  return "";
83849
83857
  }
83850
- const useStyles$u = makeStyles()((theme) => ({
83858
+ const useStyles$v = makeStyles()((theme) => ({
83851
83859
  description: {
83852
83860
  "& p, details, table": {
83853
83861
  fontSize: "80%",
@@ -83884,7 +83892,7 @@ const useStyles$u = makeStyles()((theme) => ({
83884
83892
  }));
83885
83893
  function Description(props) {
83886
83894
  const { description: description2, metadata: metadata2, descriptionType } = props;
83887
- const { classes: classes2 } = useStyles$u();
83895
+ const { classes: classes2 } = useStyles$v();
83888
83896
  return jsxRuntimeExports.jsxs("div", { className: classes2.description, children: [descriptionType && descriptionType === DescriptionType.MARKDOWN ? jsxRuntimeExports.jsx(Markdown, { children: description2 }) : jsxRuntimeExports.jsx("p", { children: description2 }), metadata2 && Array.from(metadata2.entries()).map(([layerIndex, { name: layerName, metadata: metadataRecord }]) => metadataRecord && Object.entries(metadataRecord).length > 0 ? jsxRuntimeExports.jsxs("details", { children: [jsxRuntimeExports.jsx("summary", { children: layerName }), jsxRuntimeExports.jsx("div", { className: classes2.metadataContainer, children: jsxRuntimeExports.jsx("table", { children: jsxRuntimeExports.jsx("tbody", { children: Object.entries(metadataRecord).map(([key2, value2]) => jsxRuntimeExports.jsxs("tr", { children: [jsxRuntimeExports.jsx("th", { title: key2, children: key2 }), jsxRuntimeExports.jsx("td", { title: value2, children: value2 })] }, key2)) }) }) })] }, layerIndex) : null)] });
83889
83897
  }
83890
83898
  function DescriptionSubscriber(props) {
@@ -98955,7 +98963,7 @@ const Tooltip$2 = /* @__PURE__ */ React.forwardRef((props, ref2) => {
98955
98963
  }, extraProps), getChildren());
98956
98964
  });
98957
98965
  const nodeHeight = 32;
98958
- const useStyles$t = makeStyles()((theme) => ({
98966
+ const useStyles$u = makeStyles()((theme) => ({
98959
98967
  setsManager: {
98960
98968
  position: "relative",
98961
98969
  width: "100%",
@@ -99122,7 +99130,7 @@ const useStyles$t = makeStyles()((theme) => ({
99122
99130
  }));
99123
99131
  function SetsManagerTreeGlobalStyles(props) {
99124
99132
  const { classes: classes2 } = props;
99125
- const { theme } = useStyles$w();
99133
+ const { theme } = useStyles$x();
99126
99134
  return jsxRuntimeExports.jsx(ScopedGlobalStyles, { parentClassName: classes2.setsManagerTree, styles: {
99127
99135
  ".rc-tree": {
99128
99136
  paddingLeft: "0",
@@ -99463,7 +99471,7 @@ function HelpTooltipGlobalStyles(props) {
99463
99471
  }
99464
99472
  function PopoverGlobalStyles(props) {
99465
99473
  const { classes: classes2 } = props;
99466
- const { theme } = useStyles$w();
99474
+ const { theme } = useStyles$x();
99467
99475
  return jsxRuntimeExports.jsx(ScopedGlobalStyles, { parentClassName: classes2.popover, styles: {
99468
99476
  ".rc-tooltip-inner": {
99469
99477
  boxSizing: "border-box",
@@ -104147,7 +104155,7 @@ function NamedSetNodeStatic(props) {
104147
104155
  const onClick = level === 0 && !expanded ? () => onCheckLevel(nodeKey, nextLevelToCheck) : () => onNodeView(path2);
104148
104156
  const tooltipProps = disableTooltip ? { visible: false } : {};
104149
104157
  const popoverMenuConfig = makeNodeViewMenuConfig(props);
104150
- const { classes: classes2 } = useStyles$t();
104158
+ const { classes: classes2 } = useStyles$u();
104151
104159
  return jsxRuntimeExports.jsxs("span", { children: [jsxRuntimeExports.jsx(HelpTooltip, { title: tooltipText, ...tooltipProps, children: jsxRuntimeExports.jsx("button", { type: "button", onClick, onKeyPress: (e3) => callbackOnKeyPress(e3, "v", () => onNodeView(path2)), className: classes2.titleButton, children: title2 }) }), popoverMenuConfig.length > 0 ? jsxRuntimeExports.jsx(PopoverMenu, { menuConfig: makeNodeViewMenuConfig(props), color: level > 0 && editable ? color2 || getDefaultColor(theme) : null, setColor: (c2) => onNodeSetColor(path2, c2), children: jsxRuntimeExports.jsx("span", { children: jsxRuntimeExports.jsx(SvgMenu, { className: classes2.nodeMenuIcon, "aria-label": "Open Node View Menu" }) }) }) : null, level > 0 && isChecking ? checkbox2 : null, level > 0 && jsxRuntimeExports.jsx("span", { className: classes2.nodeSizeLabel, children: niceSize })] });
104152
104160
  }
104153
104161
  function NamedSetNodeEditing(props) {
@@ -104159,7 +104167,7 @@ function NamedSetNodeEditing(props) {
104159
104167
  onNodeSetName(path2, currentTitle, true);
104160
104168
  }
104161
104169
  }
104162
- const { classes: classes2 } = useStyles$t();
104170
+ const { classes: classes2 } = useStyles$u();
104163
104171
  return jsxRuntimeExports.jsxs("span", { className: classes2.titleButtonWithInput, children: [jsxRuntimeExports.jsx("input", {
104164
104172
  // eslint-disable-next-line jsx-a11y/no-autofocus
104165
104173
  autoFocus: true,
@@ -104185,7 +104193,7 @@ function LevelsButtons(props) {
104185
104193
  onCheckLevel(nodeKey, newLevel);
104186
104194
  }
104187
104195
  }
104188
- const { classes: classes2 } = useStyles$t();
104196
+ const { classes: classes2 } = useStyles$u();
104189
104197
  return jsxRuntimeExports.jsx("div", { className: classes2.levelButtonsContainer, children: range$e(1, height2 + 1).map((i2) => {
104190
104198
  const isChecked = isEqual$3(path2, checkedLevelPath) && i2 === checkedLevelIndex;
104191
104199
  return jsxRuntimeExports.jsx("div", { children: jsxRuntimeExports.jsx(HelpTooltip, { title: getLevelTooltipText(i2), children: jsxRuntimeExports.jsx("input", { className: clsx(classes2.levelRadioButton, { [classes2.levelRadioButtonChecked]: isChecked && !hasColorEncoding }), type: "checkbox", value: i2, checked: isChecked && hasColorEncoding, onChange: onCheck }) }) }, i2);
@@ -104269,7 +104277,7 @@ let TreeNode$1 = class TreeNode extends TreeNode$2 {
104269
104277
  };
104270
104278
  function PlusButton(props) {
104271
104279
  const { datatype, onError, onImportTree, onCreateLevelZeroNode, importable, editable } = props;
104272
- const { classes: classes2 } = useStyles$t();
104280
+ const { classes: classes2 } = useStyles$u();
104273
104281
  const onImport = useCallback((importHandler, mimeType) => () => {
104274
104282
  const uploadInputNode = document.createElement("input");
104275
104283
  uploadInputNode.setAttribute("type", "file");
@@ -104386,7 +104394,7 @@ function SetsManager(props) {
104386
104394
  }, onNodeCheckNewName, onNodeSetIsEditing: setIsEditingNodeName, onNodeRemove, onExportLevelZeroNodeJSON, onExportLevelZeroNodeTabular, onExportSetJSON, disableTooltip: isDragging, onDragStart: () => setIsDragging(true), onDragEnd: () => setIsDragging(false), children: renderTreeNodes(node2.children, readOnly, newPath) }, pathToKey(newPath));
104387
104395
  });
104388
104396
  }
104389
- const { classes: classes2 } = useStyles$t();
104397
+ const { classes: classes2 } = useStyles$u();
104390
104398
  return jsxRuntimeExports.jsxs("div", { className: classes2.setsManager, children: [jsxRuntimeExports.jsx(SetsManagerTreeGlobalStyles, { classes: classes2 }), jsxRuntimeExports.jsxs("div", { className: classes2.setsManagerTree, children: [jsxRuntimeExports.jsx(Tree$1, { draggable: false, checkable, checkedKeys: setSelectionKeys, expandedKeys: setExpansionKeys, autoExpandParent, onCheck: (checkedKeys, info2) => onCheckNode(info2.node.props.nodeKey, info2.checked), onExpand: (expandedKeys, info2) => onExpandNode(expandedKeys, info2.node.props.nodeKey, info2.expanded), children: renderTreeNodes(processedSets.tree, true, []) }), jsxRuntimeExports.jsx(Tree$1, { draggable: true, checkable, checkedKeys: additionalSetSelectionKeys, expandedKeys: additionalSetExpansionKeys, autoExpandParent, onCheck: (checkedKeys, info2) => onCheckNode(info2.node.props.nodeKey, info2.checked), onExpand: (expandedKeys, info2) => onExpandNode(expandedKeys, info2.node.props.nodeKey, info2.expanded), onDrop: (info2) => {
104391
104399
  const { eventKey: dropKey } = info2.node.props;
104392
104400
  const { eventKey: dragKey } = info2.dragNode.props;
@@ -210351,22 +210359,22 @@ async function getDecoder(fileDirectory) {
210351
210359
  const Decoder = await importFn();
210352
210360
  return new Decoder(fileDirectory);
210353
210361
  }
210354
- addDecoder([void 0, 1], () => import("./raw-BHe10UqL.js").then((m2) => m2.default));
210355
- addDecoder(5, () => import("./lzw-xRmfciyv.js").then((m2) => m2.default));
210362
+ addDecoder([void 0, 1], () => import("./raw-BDQB9cuz.js").then((m2) => m2.default));
210363
+ addDecoder(5, () => import("./lzw-oMC0dlgC.js").then((m2) => m2.default));
210356
210364
  addDecoder(6, () => {
210357
210365
  throw new Error("old style JPEG compression is not supported.");
210358
210366
  });
210359
- addDecoder(7, () => import("./jpeg-Bx2qADwx.js").then((m2) => m2.default));
210360
- addDecoder([8, 32946], () => import("./deflate-BVXiBwpd.js").then((m2) => m2.default));
210361
- addDecoder(32773, () => import("./packbits-DymgLbq7.js").then((m2) => m2.default));
210367
+ addDecoder(7, () => import("./jpeg-C7Mxa_R_.js").then((m2) => m2.default));
210368
+ addDecoder([8, 32946], () => import("./deflate-CsmxXIPT.js").then((m2) => m2.default));
210369
+ addDecoder(32773, () => import("./packbits-C-3XoOot.js").then((m2) => m2.default));
210362
210370
  addDecoder(
210363
210371
  34887,
210364
- () => import("./lerc-BVprPTmk.js").then(async (m2) => {
210372
+ () => import("./lerc-DbIzGgSj.js").then(async (m2) => {
210365
210373
  await m2.zstd.init();
210366
210374
  return m2;
210367
210375
  }).then((m2) => m2.default)
210368
210376
  );
210369
- addDecoder(50001, () => import("./webimage-DBDXmZdm.js").then((m2) => m2.default));
210377
+ addDecoder(50001, () => import("./webimage-DhNmlhtK.js").then((m2) => m2.default));
210370
210378
  function copyNewSize(array2, width2, height2, samplesPerPixel = 1) {
210371
210379
  return new (Object.getPrototypeOf(array2)).constructor(width2 * height2 * samplesPerPixel);
210372
210380
  }
@@ -227135,7 +227143,7 @@ class ContourLayerWithText extends ContourLayer {
227135
227143
  }
227136
227144
  ContourLayerWithText.layerName = "ContourLayerWithText";
227137
227145
  ContourLayerWithText.defaultProps = defaultProps;
227138
- const useStyles$s = makeStyles()(() => ({
227146
+ const useStyles$t = makeStyles()(() => ({
227139
227147
  toolButton: {
227140
227148
  display: "inline-flex",
227141
227149
  "&:active": {
@@ -227197,12 +227205,12 @@ const useStyles$s = makeStyles()(() => ({
227197
227205
  }));
227198
227206
  function IconTool(props) {
227199
227207
  const { alt, onClick, isActive: isActive2, children: children3 } = props;
227200
- const { classes: classes2 } = useStyles$s();
227208
+ const { classes: classes2 } = useStyles$t();
227201
227209
  return jsxRuntimeExports.jsx("button", { className: clsx(classes2.toolIcon, { [classes2.toolActive]: isActive2 }), onClick, type: "button", title: alt, children: children3 });
227202
227210
  }
227203
227211
  function IconButton(props) {
227204
227212
  const { alt, onClick, children: children3 } = props;
227205
- const { classes: classes2 } = useStyles$s();
227213
+ const { classes: classes2 } = useStyles$t();
227206
227214
  return jsxRuntimeExports.jsx("button", { className: clsx(classes2.toolIcon, classes2.toolButton), onClick, type: "button", title: alt, children: children3 });
227207
227215
  }
227208
227216
  function ToolMenu(props) {
@@ -227210,7 +227218,7 @@ function ToolMenu(props) {
227210
227218
  const lassoIconAltText = "Select lasso";
227211
227219
  const { setActiveTool, activeTool, visibleTools = { pan: true, selectLasso: true, recenter: true }, recenterOnClick = () => {
227212
227220
  } } = props;
227213
- const { classes: classes2 } = useStyles$s();
227221
+ const { classes: classes2 } = useStyles$t();
227214
227222
  const onRecenterButtonCLick = () => {
227215
227223
  recenterOnClick();
227216
227224
  };
@@ -228399,7 +228407,7 @@ function ScatterplotOptions(props) {
228399
228407
  id: `feature-aggregation-strategy-${scatterplotOptionsId}`
228400
228408
  }, children: FEATURE_AGGREGATION_STRATEGIES$1.map((opt) => jsxRuntimeExports.jsx("option", { value: opt, children: capitalize$3(opt) }, opt)) }) })] }) : null] });
228401
228409
  }
228402
- const useStyles$r = makeStyles()((theme) => ({
228410
+ const useStyles$s = makeStyles()((theme) => ({
228403
228411
  tooltipAnchor: {
228404
228412
  position: "relative",
228405
228413
  width: "0px",
@@ -228430,7 +228438,7 @@ const useStyles$r = makeStyles()((theme) => ({
228430
228438
  function Tooltip3(props) {
228431
228439
  const { x: x2, y: y2, parentWidth, parentHeight, children: children3 } = props;
228432
228440
  const ref2 = useRef();
228433
- const { classes: classes2 } = useStyles$r();
228441
+ const { classes: classes2 } = useStyles$s();
228434
228442
  const [placementX, setPlacementX] = useState("start");
228435
228443
  const [placementY, setPlacementY] = useState("bottom");
228436
228444
  const getTooltipContainer = useVitessceContainer(ref2);
@@ -228446,7 +228454,7 @@ function Tooltip3(props) {
228446
228454
  }, [x2, y2, parentWidth, parentHeight]);
228447
228455
  return jsxRuntimeExports.jsx("div", { ref: ref2, className: classes2.tooltipAnchor, children: ref2 && ref2.current ? jsxRuntimeExports.jsx(Popper, { open: true, anchorEl: ref2.current, container: getTooltipContainer, transition: true, placement: `${placementY}-${placementX}`, children: jsxRuntimeExports.jsx(Paper, { elevation: 8, className: classes2.tooltipContent, children: children3 }) }) : null });
228448
228456
  }
228449
- const useStyles$q = makeStyles()((theme) => ({
228457
+ const useStyles$r = makeStyles()((theme) => ({
228450
228458
  cellEmphasisCrosshair: {
228451
228459
  zIndex: 50,
228452
228460
  position: "absolute",
@@ -228457,7 +228465,7 @@ const useStyles$q = makeStyles()((theme) => ({
228457
228465
  }));
228458
228466
  function Tooltip2D(props) {
228459
228467
  const { parentUuid, sourceUuid, x: x2, y: y2, parentWidth, parentHeight, children: children3 } = props;
228460
- const { classes: classes2 } = useStyles$q();
228468
+ const { classes: classes2 } = useStyles$r();
228461
228469
  if (x2 < 0 || x2 > parentWidth || y2 < 0 || y2 > parentHeight) {
228462
228470
  return null;
228463
228471
  }
@@ -232362,7 +232370,7 @@ function getXlinkHref(cmap) {
232362
232370
  const xlinkHref = ramp(color2.copy().domain(quantize$3(interpolate$1$1(0, 1), n3))).toDataURL();
232363
232371
  return xlinkHref;
232364
232372
  }
232365
- const useStyles$p = makeStyles()(() => ({
232373
+ const useStyles$q = makeStyles()(() => ({
232366
232374
  legend: {
232367
232375
  position: "relative",
232368
232376
  // Needed for absolute positioning of slider overlay
@@ -232559,7 +232567,7 @@ function Legend(props) {
232559
232567
  contourThresholds
232560
232568
  } = props;
232561
232569
  const svgRef = useRef(null);
232562
- const { classes: classes2 } = useStyles$p();
232570
+ const { classes: classes2 } = useStyles$q();
232563
232571
  const [localRange, setLocalRange] = useState(featureValueColormapRange);
232564
232572
  useEffect(() => {
232565
232573
  setLocalRange(featureValueColormapRange);
@@ -232840,7 +232848,9 @@ function Legend(props) {
232840
232848
  isStaticColor,
232841
232849
  missing,
232842
232850
  showObsLabel,
232843
- staticColor
232851
+ staticColor,
232852
+ featureColor,
232853
+ pointsLegendElements
232844
232854
  ]);
232845
232855
  const showInteractiveSlider = !isPointsLayer && setFeatureValueColormapRange && ["geneSelection", "geneExpression"].includes(obsColorEncoding ?? "") && pointsVisible && featureValueColormap;
232846
232856
  const globalExtent = useMemo$1(() => {
@@ -232891,7 +232901,7 @@ function Legend(props) {
232891
232901
  }
232892
232902
  } })] })] });
232893
232903
  }
232894
- const useStyles$o = makeStyles()(() => ({
232904
+ const useStyles$p = makeStyles()(() => ({
232895
232905
  multiLegend: {
232896
232906
  position: "absolute",
232897
232907
  top: "0px",
@@ -232918,7 +232928,7 @@ function MultiLegend(props) {
232918
232928
  pointLayerCoordination,
232919
232929
  pointMultiIndicesData
232920
232930
  } = props;
232921
- const { classes: classes2 } = useStyles$o();
232931
+ const { classes: classes2 } = useStyles$p();
232922
232932
  const reversedSegmentationLayerScopes = useMemo$1(() => [...segmentationLayerScopes || []].reverse(), [segmentationLayerScopes]);
232923
232933
  const reversedSpotLayerScopes = useMemo$1(() => [...spotLayerScopes || []].reverse(), [spotLayerScopes]);
232924
232934
  const reversedPointLayerScopes = useMemo$1(() => [...pointLayerScopes || []].reverse(), [pointLayerScopes]);
@@ -233011,7 +233021,7 @@ function MultiLegend(props) {
233011
233021
  }) : null;
233012
233022
  }) : null] });
233013
233023
  }
233014
- const useStyles$n = makeStyles()(() => ({
233024
+ const useStyles$o = makeStyles()(() => ({
233015
233025
  channelNamesLegendContainer: {
233016
233026
  position: "absolute",
233017
233027
  bottom: "0px",
@@ -233034,7 +233044,7 @@ const useStyles$n = makeStyles()(() => ({
233034
233044
  }));
233035
233045
  function ChannelNamesLegend(props) {
233036
233046
  const { images, imageLayerScopes, imageLayerCoordination, imageChannelScopesByLayer, imageChannelCoordination } = props;
233037
- const { classes: classes2 } = useStyles$n();
233047
+ const { classes: classes2 } = useStyles$o();
233038
233048
  const reversedImageLayerScopes = useMemo$1(() => [...imageLayerScopes || []].reverse(), [imageLayerScopes]);
233039
233049
  return jsxRuntimeExports.jsx("div", { className: classes2.channelNamesLegendContainer, children: imageLayerScopes ? reversedImageLayerScopes.map((layerScope) => {
233040
233050
  const layerCoordination = imageLayerCoordination[0][layerScope];
@@ -251919,6 +251929,12 @@ function createGetRange(store) {
251919
251929
  throw new Error("Invalid rangeQuery value.");
251920
251930
  };
251921
251931
  }
251932
+ function flattenOmeAttrs(rootAttrs) {
251933
+ if (rootAttrs && typeof rootAttrs.ome === "object" && rootAttrs.ome !== null) {
251934
+ return { ...rootAttrs.ome, ...rootAttrs };
251935
+ }
251936
+ return rootAttrs;
251937
+ }
251922
251938
  class VitessceError extends Error {
251923
251939
  constructor(message) {
251924
251940
  super(message);
@@ -251981,10 +251997,12 @@ async function loadMultiscales(root2) {
251981
251997
  }
251982
251998
  throw e3;
251983
251999
  }
252000
+ rootAttrs = flattenOmeAttrs(rootAttrs);
251984
252001
  let paths = ["0"];
251985
252002
  let labels2 = ["t", "c", "z", "y", "x"];
251986
252003
  if ("multiscales" in rootAttrs) {
251987
- const { datasets, axes } = rootAttrs.multiscales[0];
252004
+ const { multiscales } = rootAttrs;
252005
+ const { datasets, axes } = multiscales[0];
251988
252006
  paths = datasets.map((d) => d.path);
251989
252007
  if (axes) {
251990
252008
  if (isAxis(axes)) {
@@ -254855,12 +254873,12 @@ class ErrorBoundary extends React__default.Component {
254855
254873
  }
254856
254874
  }
254857
254875
  const LazySpatialThree = React__default.lazy(async () => {
254858
- const { SpatialWrapper: SpatialWrapper2 } = await import("./index-CC-2MyaG.js");
254876
+ const { SpatialWrapper: SpatialWrapper2 } = await import("./index-BstOXuv0.js");
254859
254877
  return { default: SpatialWrapper2 };
254860
254878
  });
254861
254879
  const SpatialThreeAdapter = React__default.forwardRef((props, ref2) => jsxRuntimeExports.jsx("div", { ref: ref2, style: { width: "100%", height: "100%" }, children: jsxRuntimeExports.jsx(ErrorBoundary, { children: jsxRuntimeExports.jsx(Suspense, { fallback: jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: jsxRuntimeExports.jsx(LazySpatialThree, { ...props }) }) }) }));
254862
254880
  const LazySpatialAccelerated = React__default.lazy(async () => {
254863
- const { SpatialWrapper: SpatialWrapper2 } = await import("./index-BA1bwFuv.js");
254881
+ const { SpatialWrapper: SpatialWrapper2 } = await import("./index-BPsHPaJT.js");
254864
254882
  return { default: SpatialWrapper2 };
254865
254883
  });
254866
254884
  const SpatialAcceleratedAdapter = React__default.forwardRef((props, ref2) => jsxRuntimeExports.jsx("div", { ref: ref2, style: { width: "100%", height: "100%" }, children: jsxRuntimeExports.jsx(ErrorBoundary, { children: jsxRuntimeExports.jsx(Suspense, { fallback: jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: jsxRuntimeExports.jsx(LazySpatialAccelerated, { ...props }) }) }) }));
@@ -262980,7 +262998,7 @@ _defineProperty$3(WindowScroller, "defaultProps", {
262980
262998
  serverHeight: 0,
262981
262999
  serverWidth: 0
262982
263000
  });
262983
- const useStyles$m = makeStyles()((theme) => ({
263001
+ const useStyles$n = makeStyles()((theme) => ({
262984
263002
  selectableTable: {
262985
263003
  flex: "1 1 auto",
262986
263004
  outline: "none"
@@ -263129,7 +263147,7 @@ function SelectableTable(props) {
263129
263147
  onChange(null);
263130
263148
  }
263131
263149
  }, [selectedRows, allowMultiple]);
263132
- const { classes: classes2 } = useStyles$m();
263150
+ const { classes: classes2 } = useStyles$n();
263133
263151
  const inputUuid = v4$1();
263134
263152
  const rowRenderer = ({ index: index2, style: style2 }) => (
263135
263153
  // eslint-disable-next-line jsx-a11y/interactive-supports-focus
@@ -263154,7 +263172,7 @@ const FEATURELIST_SORT_OPTIONS = [
263154
263172
  "original"
263155
263173
  ];
263156
263174
  const ALT_COLNAME = "Alternate ID";
263157
- const useStyles$l = makeStyles()(() => ({
263175
+ const useStyles$m = makeStyles()(() => ({
263158
263176
  searchBar: {
263159
263177
  marginTop: "10px",
263160
263178
  marginLeft: "10px",
@@ -263167,7 +263185,7 @@ const useStyles$l = makeStyles()(() => ({
263167
263185
  }));
263168
263186
  function FeatureList(props) {
263169
263187
  const { width: width2, height: height2, hasColorEncoding, geneList = [], featureLabelsMap, geneSelection = [], geneFilter = null, setGeneSelection, enableMultiSelect, showFeatureTable, featureListSort, featureListSortKey, hasFeatureLabels, primaryColumnName } = props;
263170
- const { classes: classes2 } = useStyles$l();
263188
+ const { classes: classes2 } = useStyles$m();
263171
263189
  const [searchTerm, setSearchTerm] = useState("");
263172
263190
  const selectableTableSortKey = featureListSortKey === "featureIndex" ? "key" : "name";
263173
263191
  const searchResults = useMemo$1(() => geneList.filter((gene) => gene.toLowerCase().includes(searchTerm.toLowerCase()) || featureLabelsMap?.get(gene)?.toLowerCase().includes(searchTerm.toLowerCase()) || featureLabelsMap?.get(cleanFeatureId(gene))?.toLowerCase().includes(searchTerm.toLowerCase())), [geneList, searchTerm, featureLabelsMap]);
@@ -263242,7 +263260,7 @@ function FeatureListOptions(props) {
263242
263260
  id: `feature-list-show-alternative-ids-${featureListId}`
263243
263261
  } } }) })] })] }) : null] });
263244
263262
  }
263245
- const useStyles$k = makeStyles()((theme) => ({
263263
+ const useStyles$l = makeStyles()((theme) => ({
263246
263264
  featureListContainer: {
263247
263265
  width: "100%",
263248
263266
  height: "100%",
@@ -263257,7 +263275,7 @@ function FeatureListSubscriber(props) {
263257
263275
  const loaders = useLoaders();
263258
263276
  const coordinationScopes = useCoordinationScopes(coordinationScopesRaw);
263259
263277
  const [width2, height2, containerRef] = useGridItemSize();
263260
- const { classes: classes2 } = useStyles$k();
263278
+ const { classes: classes2 } = useStyles$l();
263261
263279
  const [{ dataset, obsType, featureType, featureSelection: geneSelection, featureFilter: geneFilter, obsColorEncoding: cellColorEncoding }, { setFeatureSelection: setGeneSelection, setFeatureFilter: setGeneFilter, setFeatureHighlight: setGeneHighlight, setObsColorEncoding: setCellColorEncoding }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType$1.FEATURE_LIST], coordinationScopes);
263262
263280
  const variablesLabel = variablesLabelOverride || featureType;
263263
263281
  const title2 = titleOverride || `${capitalize$3(variablesLabel)} List`;
@@ -263325,6 +263343,12 @@ const useControllerSectionStyles = makeStyles()((theme) => ({
263325
263343
  },
263326
263344
  layerControllerGrid: {
263327
263345
  marginTop: "10px"
263346
+ },
263347
+ layerControllerSubRow: {
263348
+ flexDirection: "column",
263349
+ marginLeft: "40px",
263350
+ padding: "0px 8px",
263351
+ backgroundColor: theme.palette.paperBackground
263328
263352
  }
263329
263353
  }));
263330
263354
  const useAccordionStyles = makeStyles()((theme) => ({
@@ -263386,7 +263410,7 @@ const useSelectionSliderStyles = makeStyles()(() => ({
263386
263410
  backgroundColor: "rgba(128, 128, 128, 0.7)"
263387
263411
  }
263388
263412
  }));
263389
- const useStyles$j = makeStyles()((theme) => ({
263413
+ const useStyles$k = makeStyles()((theme) => ({
263390
263414
  paletteContainer: {
263391
263415
  width: "70px",
263392
263416
  height: "40px",
@@ -263407,10 +263431,10 @@ const useStyles$j = makeStyles()((theme) => ({
263407
263431
  }
263408
263432
  }));
263409
263433
  const ColorPalette = ({ handleChange }) => {
263410
- const { classes: classes2 } = useStyles$j();
263434
+ const { classes: classes2 } = useStyles$k();
263411
263435
  return jsxRuntimeExports.jsx("div", { className: classes2.paletteContainer, "aria-label": "Color swatch", children: VIEWER_PALETTE.map((color2) => jsxRuntimeExports.jsx(IconButton$1, { className: classes2.button, onClick: () => handleChange(color2), "aria-label": `Change color to ${color2}`, children: jsxRuntimeExports.jsx(LensIcon, { fontSize: "small", style: { color: `rgb(${color2})` }, className: classes2.icon }) }, color2)) });
263412
263436
  };
263413
- const useStyles$i = makeStyles()(() => ({
263437
+ const useStyles$j = makeStyles()(() => ({
263414
263438
  menuButton: {
263415
263439
  backgroundColor: "transparent"
263416
263440
  },
@@ -263429,7 +263453,7 @@ function MuiSpan(props) {
263429
263453
  }
263430
263454
  function ChannelOptions$1({ handlePropertyChange, handleChannelRemove, handleIQRUpdate }) {
263431
263455
  const [open2, setOpen] = useState(false);
263432
- const { classes: classes2 } = useStyles$i();
263456
+ const { classes: classes2 } = useStyles$j();
263433
263457
  const handleColorSelect = (color2) => {
263434
263458
  handlePropertyChange("color", color2);
263435
263459
  };
@@ -264046,7 +264070,7 @@ function LayerController$1(props) {
264046
264070
  minWidth: "50%"
264047
264071
  } })] }), jsxRuntimeExports.jsx(TabPanel, { value: tab2, index: 0, children: FullController }), jsxRuntimeExports.jsx(TabPanel, { value: tab2, index: 1, style: { marginTop: 4 }, children: jsxRuntimeExports.jsx(VolumeOptions, { loader: loader2, handleSlicerSetting, handleRenderingModeChange: setRenderingMode, renderingMode, xSlice, ySlice, zSlice, use3d, setViewState, spatialHeight, spatialWidth, modelMatrix: modelMatrix2 }) })] }) : FullController, shouldShowRemoveLayerButton ? jsxRuntimeExports.jsx(Button, { onClick: handleLayerRemove, fullWidth: true, variant: "outlined", style: buttonStyles, size: "small", children: "Remove Image Layer" }) : null] })] });
264048
264072
  }
264049
- const useStyles$h = makeStyles()(() => ({
264073
+ const useStyles$i = makeStyles()(() => ({
264050
264074
  addButton: {
264051
264075
  marginTop: "10px",
264052
264076
  marginBottom: "10px",
@@ -264058,7 +264082,7 @@ function ImageAddIcon() {
264058
264082
  }
264059
264083
  function ImageAddButton({ imageOptions, handleImageAdd }) {
264060
264084
  const [open2, setOpen] = useState(false);
264061
- const { classes: classes2 } = useStyles$h();
264085
+ const { classes: classes2 } = useStyles$i();
264062
264086
  const handleAdd = (imgData) => {
264063
264087
  setOpen((prev2) => !prev2);
264064
264088
  handleImageAdd(imgData);
@@ -264390,7 +264414,7 @@ const useEllipsisMenuStyles = makeStyles()(() => ({
264390
264414
  padding: "4px"
264391
264415
  }
264392
264416
  }));
264393
- const useStyles$g = makeStyles()(() => ({
264417
+ const useStyles$h = makeStyles()(() => ({
264394
264418
  colorPickerPaper: {
264395
264419
  overflow: "hidden",
264396
264420
  "& > ul": {
@@ -264448,13 +264472,15 @@ function ChannelColorPickerMenu(props) {
264448
264472
  setColor2([rgb2.r, rgb2.g, rgb2.b]);
264449
264473
  }
264450
264474
  }
264451
- const { classes: classes2 } = useStyles$g();
264475
+ const { classes: classes2 } = useStyles$h();
264452
264476
  const currentColor = color2 ? colorArrayToString(color2) : colorArrayToString(getDefaultColor(theme));
264453
- return jsxRuntimeExports.jsx(PopperMenu, { open: isStaticColor && visible ? open2 : false, setOpen, buttonIcon: isStaticColor && visible ? jsxRuntimeExports.jsx("div", { className: clsx(classes2.colorIcon, {
264477
+ const isWritable = typeof setColor2 === "function";
264478
+ const derivedOpen = isWritable ? isStaticColor && visible ? open2 : false : false;
264479
+ return jsxRuntimeExports.jsx(PopperMenu, { open: derivedOpen, setOpen, buttonIcon: isStaticColor && visible ? jsxRuntimeExports.jsx("div", { className: clsx(classes2.colorIcon, {
264454
264480
  [classes2.colorIconOutline]: theme !== "dark" && isEqual$3(color2, [255, 255, 255])
264455
264481
  }), style: { backgroundColor: currentColor } }) : isColormap && visible && featureValueColormap ? jsxRuntimeExports.jsx("div", { className: classes2.colorIcon, children: jsxRuntimeExports.jsx("svg", { width: "18", height: "18", children: jsxRuntimeExports.jsx("image", { x: 0, y: 0, width: 18, height: 18, preserveAspectRatio: "none", href: getXlinkHref(featureValueColormap), clipPath: "inset(0% round 4px)" }) }) }) : jsxRuntimeExports.jsx("div", { className: classes2.colorIcon }), buttonClassName: classes2.colorIconButton, withPaper: true, paperClassName: classes2.colorPickerPaper, "aria-label": "Open color picker menu", children: jsxRuntimeExports.jsx(Twitter$1, { className: classes2.colorPicker, disableAlpha: true, width: 108, triangle: "hide", colors: defaultPalette, color: currentColor, onChangeComplete: handleColorChange }) });
264456
264482
  }
264457
- const useStyles$f = makeStyles()(() => ({
264483
+ const useStyles$g = makeStyles()(() => ({
264458
264484
  layerTypeSpotIcon: {
264459
264485
  height: "100%",
264460
264486
  marginLeft: "1px",
@@ -264467,7 +264493,7 @@ const useStyles$f = makeStyles()(() => ({
264467
264493
  function SpotLayerEllipsisMenu(props) {
264468
264494
  const { strokeWidth, setStrokeWidth, filled, setFilled, featureSelection, obsColorEncoding, setObsColorEncoding, featureValueColormap, setFeatureValueColormap, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible } = props;
264469
264495
  const [open2, setOpen] = useState(false);
264470
- const { classes: classes2 } = useStyles$f();
264496
+ const { classes: classes2 } = useStyles$g();
264471
264497
  const { classes: selectClasses2 } = useSelectStyles();
264472
264498
  const { classes: menuClasses } = useEllipsisMenuStyles();
264473
264499
  const filledId = $bdb11010cef70236$export$f680877a34711e37();
@@ -264489,7 +264515,7 @@ function SpotLayerController(props) {
264489
264515
  const Visibility = useMemo$1(() => visibleSetting ? VisibilityIcon : VisibilityOffIcon, [visibleSetting]);
264490
264516
  const isStaticColor = obsColorEncoding === "spatialLayerColor";
264491
264517
  const isColormap = obsColorEncoding === "geneSelection";
264492
- const { classes: classes2 } = useStyles$f();
264518
+ const { classes: classes2 } = useStyles$g();
264493
264519
  const { classes: lcClasses } = useControllerSectionStyles();
264494
264520
  const { classes: menuClasses } = useEllipsisMenuStyles();
264495
264521
  const handleVisibleChange = useCallback(() => {
@@ -264499,6 +264525,104 @@ function SpotLayerController(props) {
264499
264525
  const handleOpacityChange = useCallback((e3, v) => setOpacity2(v), [setOpacity2]);
264500
264526
  return jsxRuntimeExports.jsx(Grid$1, { className: lcClasses.layerControllerGrid, children: jsxRuntimeExports.jsx(Paper, { elevation: 4, className: lcClasses.layerControllerRoot, children: jsxRuntimeExports.jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsxRuntimeExports.jsx(Grid$1, { size: 1, children: jsxRuntimeExports.jsx(Button, { onClick: handleVisibleChange, className: menuClasses.imageLayerVisibleButton, "aria-label": "Toggle spot layer visibility", children: jsxRuntimeExports.jsx(Visibility, {}) }) }), jsxRuntimeExports.jsx(Grid$1, { size: 1, children: jsxRuntimeExports.jsx(ChannelColorPickerMenu, { theme, color: color2, setColor: setColor2, palette, isStaticColor, isColormap, featureValueColormap, visible }) }), jsxRuntimeExports.jsx(Grid$1, { size: 6, children: jsxRuntimeExports.jsx(Typography, { className: menuClasses.imageLayerName, children: label2 }) }), jsxRuntimeExports.jsx(Grid$1, { size: 2, children: jsxRuntimeExports.jsx(Slider, { value: opacity2, min: 0, max: 1, step: 1e-3, onChange: handleOpacityChange, className: menuClasses.imageLayerOpacitySlider, orientation: "horizontal", "aria-label": `Adjust opacity for layer ${label2}` }) }), jsxRuntimeExports.jsx(Grid$1, { size: 1, children: jsxRuntimeExports.jsx(SpotLayerEllipsisMenu, { filled, setFilled, strokeWidth, setStrokeWidth, featureSelection, obsColorEncoding, setObsColorEncoding, featureValueColormap, setFeatureValueColormap, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible }) }), jsxRuntimeExports.jsx(Grid$1, { size: 1, children: jsxRuntimeExports.jsx(SvgSpots, { className: classes2.layerTypeSpotIcon }) })] }) }) });
264501
264527
  }
264528
+ const useStyles$f = makeStyles()(() => ({
264529
+ layerFeatureControllerGrid: {
264530
+ padding: "0",
264531
+ flexWrap: "nowrap"
264532
+ },
264533
+ layerFeatureExpansionButton: {
264534
+ display: "inline-block",
264535
+ margin: 0,
264536
+ padding: 0,
264537
+ minWidth: 0,
264538
+ lineHeight: 1,
264539
+ width: "50%"
264540
+ },
264541
+ layerTypeFeatureIcon: {
264542
+ height: "100%",
264543
+ paddingLeft: "2px",
264544
+ fill: "currentColor",
264545
+ fontSize: "14px",
264546
+ width: "50%",
264547
+ maxWidth: "16px"
264548
+ }
264549
+ }));
264550
+ function LayerPerFeatureController(props) {
264551
+ const { theme, palette = null, featureName, featureColor, setFeatureColor, featureValueColormap, featureSelection, setFeatureSelection, spatialLayerColor, featureIndex, obsColorEncoding, loadingDoneFraction, opacity: opacity2, handleOpacityChange } = props;
264552
+ const featureColorIndex = useMemo$1(() => featureColor?.findIndex((fc) => fc.name === featureName) ?? -1, [featureColor, featureName]);
264553
+ const varIndex = useMemo$1(() => featureIndex?.indexOf(featureName) ?? -1, [featureIndex, featureName]);
264554
+ const randomByFeatureColor = useMemo$1(() => varIndex >= 0 ? PALETTE[varIndex % PALETTE.length] : [255, 255, 255], [varIndex]);
264555
+ const handleRemoveFeature = useCallback(() => {
264556
+ setFeatureSelection(featureSelection.filter((f2) => f2 !== featureName));
264557
+ }, [featureName, featureSelection, setFeatureSelection]);
264558
+ const handleColorChange = useCallback((newColor) => {
264559
+ if (featureColorIndex >= 0) {
264560
+ const nextFeatureColor = [...featureColor];
264561
+ nextFeatureColor[featureColorIndex] = {
264562
+ ...nextFeatureColor[featureColorIndex],
264563
+ color: newColor
264564
+ };
264565
+ setFeatureColor(nextFeatureColor);
264566
+ } else {
264567
+ setFeatureColor([
264568
+ ...featureColor ?? [],
264569
+ { name: featureName, color: newColor }
264570
+ ]);
264571
+ }
264572
+ }, [featureName, featureColor, setFeatureColor, featureColorIndex]);
264573
+ const { classes: classes2 } = useStyles$f();
264574
+ const { classes: lcClasses } = useControllerSectionStyles();
264575
+ const { classes: menuClasses } = useEllipsisMenuStyles();
264576
+ const [open2, setOpen] = useState(false);
264577
+ const { colorPickerColor, colorPickerReadable, colorPickerWritable, colorPickerTooltip } = useMemo$1(() => {
264578
+ if (obsColorEncoding === "geneSelection") {
264579
+ return {
264580
+ colorPickerColor: featureColor?.[featureColorIndex]?.color ?? spatialLayerColor,
264581
+ colorPickerReadable: true,
264582
+ colorPickerWritable: true,
264583
+ colorPickerTooltip: null
264584
+ };
264585
+ }
264586
+ if (obsColorEncoding === "spatialLayerColor") {
264587
+ return {
264588
+ colorPickerColor: spatialLayerColor,
264589
+ colorPickerReadable: true,
264590
+ colorPickerWritable: false,
264591
+ colorPickerTooltip: 'Currently using the color value from the parent point layer. Per-feature colors can be modified when the Color Encoding mode of the parent layer is "Feature Color".'
264592
+ };
264593
+ }
264594
+ if (obsColorEncoding === "randomByFeature") {
264595
+ return {
264596
+ colorPickerColor: randomByFeatureColor,
264597
+ colorPickerReadable: true,
264598
+ colorPickerWritable: false,
264599
+ colorPickerTooltip: 'Currently using the assigned random color. Per-feature colors can be modified when the Color Encoding mode of the parent layer is "Feature Color".'
264600
+ };
264601
+ }
264602
+ if (obsColorEncoding === "random") {
264603
+ return {
264604
+ colorPickerColor: null,
264605
+ colorPickerReadable: false,
264606
+ colorPickerWritable: false,
264607
+ colorPickerTooltip: 'Currently using a random color per point. Per-feature colors can be modified when the Color Encoding mode of the parent layer is "Feature Color".'
264608
+ };
264609
+ }
264610
+ return {
264611
+ colorPickerColor: null,
264612
+ colorPickerReadable: false,
264613
+ colorPickerWritable: false,
264614
+ colorPickerTooltip: null
264615
+ };
264616
+ }, [
264617
+ obsColorEncoding,
264618
+ spatialLayerColor,
264619
+ featureName,
264620
+ featureColor,
264621
+ featureColorIndex,
264622
+ randomByFeatureColor
264623
+ ]);
264624
+ return jsxRuntimeExports.jsx(Grid$1, { className: lcClasses.layerControllerGrid, children: jsxRuntimeExports.jsxs(Paper, { elevation: 2, className: lcClasses.layerControllerSubRow, children: [jsxRuntimeExports.jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsxRuntimeExports.jsx(Grid$1, { size: 1, children: jsxRuntimeExports.jsx(Button, { onClick: handleRemoveFeature, className: menuClasses.imageLayerVisibleButton, "aria-label": "Remove feature", children: jsxRuntimeExports.jsx(ClearIcon, {}) }) }), jsxRuntimeExports.jsx(Grid$1, { size: 1, children: jsxRuntimeExports.jsx(Tooltip$3, { title: colorPickerTooltip ?? "", disableHoverListener: !colorPickerTooltip, placement: "top", children: jsxRuntimeExports.jsx("span", { children: jsxRuntimeExports.jsx(ChannelColorPickerMenu, { theme, color: colorPickerColor, setColor: colorPickerWritable ? handleColorChange : null, palette, isStaticColor: colorPickerReadable, isColormap: false, featureValueColormap, visible: true }) }) }) }), jsxRuntimeExports.jsx(Grid$1, { size: 6, children: jsxRuntimeExports.jsx(Typography, { className: menuClasses.imageLayerName, children: featureName }) }), jsxRuntimeExports.jsx(Grid$1, { size: 2, sx: { paddingRight: "12px", overflow: "visible" }, children: jsxRuntimeExports.jsx(Slider, { value: opacity2, min: 0, max: 1, step: 1e-3, onChange: handleOpacityChange, className: menuClasses.imageLayerOpacitySlider, orientation: "horizontal", "aria-label": `Adjust opacity for layer ${featureName}` }) }), jsxRuntimeExports.jsxs(Grid$1, { size: 1, container: true, direction: "row", children: [jsxRuntimeExports.jsx(SvgPoints, { className: classes2.layerTypeFeatureIcon }), null] })] }), loadingDoneFraction < 1 ? jsxRuntimeExports.jsx(Grid$1, { size: 12, container: true, direction: "column", justifyContent: "space-between", className: classes2.layerFeatureControllerGrid, children: jsxRuntimeExports.jsx(LinearProgress, { variant: loadingDoneFraction === 0 ? "indeterminate" : "determinate", value: loadingDoneFraction * 100 }) }) : null] }) }, featureName);
264625
+ }
264502
264626
  const useStyles$e = makeStyles()(() => ({
264503
264627
  pointLayerButton: {
264504
264628
  borderStyle: "dashed",
@@ -264541,7 +264665,7 @@ function PointLayerEllipsisMenu(props) {
264541
264665
  return jsxRuntimeExports.jsxs(PopperMenu, { open: open2, setOpen, buttonIcon: jsxRuntimeExports.jsx(MoreVertIcon, {}), buttonClassName: menuClasses.imageLayerMenuButton, containerClassName: menuClasses.imageLayerPopperContainer, withPaper: true, "aria-label": "Open point layer options menu", children: [jsxRuntimeExports.jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsxRuntimeExports.jsx("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: quantitativeColormapId, children: "Color Encoding: " }), jsxRuntimeExports.jsxs(NativeSelect, { onChange: (e3) => setObsColorEncoding(e3.target.value), value: obsColorEncoding, inputProps: { id: quantitativeColormapId, "aria-label": "Color encoding selector" }, classes: { root: selectClasses2.selectRoot }, children: [jsxRuntimeExports.jsx("option", { value: "spatialLayerColor", children: "Static Color" }), jsxRuntimeExports.jsx("option", { value: "geneSelection", children: "Feature Color" }), jsxRuntimeExports.jsx("option", { value: "randomByFeature", children: "Random Color per Feature" }), jsxRuntimeExports.jsx("option", { value: "random", children: "Random Color per Point" })] })] }), jsxRuntimeExports.jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsxRuntimeExports.jsx("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: featureFilterModeId, children: "Filter to Feature Selection: " }), jsxRuntimeExports.jsx(Checkbox$1, { color: "primary", className: menuClasses.menuItemCheckbox, checked: featureFilterMode === "featureSelection", onChange: (e3, v) => setFeatureFilterMode(v ? "featureSelection" : null), slotProps: { input: { id: featureFilterModeId, "aria-label": "Toggle feature filter mode" } } })] }), jsxRuntimeExports.jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsxRuntimeExports.jsx("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: colormapRangeId, children: "Colormap Range: " }), jsxRuntimeExports.jsx(Slider, { disabled: obsColorEncoding !== "geneSelection", value: featureValueColormapRange, min: 0, max: 1, step: 0.01, onChange: (e3, v) => setFeatureValueColormapRange(v), className: menuClasses.menuItemSlider, orientation: "horizontal", id: colormapRangeId, getAriaLabel: (index2) => index2 === 0 ? "Low value colormap range slider" : "High value colormap range slider" })] }), jsxRuntimeExports.jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsxRuntimeExports.jsx("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: tooltipsVisibleId, children: "Tooltips Visible: " }), jsxRuntimeExports.jsx(Checkbox$1, { color: "primary", className: menuClasses.menuItemCheckbox, checked: tooltipsVisible, onChange: (e3, v) => setTooltipsVisible(v), slotProps: { input: { id: tooltipsVisibleId, "aria-label": "Toggle tooltip visibility" } } })] }), jsxRuntimeExports.jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsxRuntimeExports.jsx("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: crosshairsVisibleId, children: "Tooltip Crosshairs Visible: " }), jsxRuntimeExports.jsx(Checkbox$1, { color: "primary", className: menuClasses.menuItemCheckbox, checked: tooltipCrosshairsVisible, onChange: (e3, v) => setTooltipCrosshairsVisible(v), slotProps: { input: { id: crosshairsVisibleId, "aria-label": "Toggle tooltip crosshair visibility" } } })] }), jsxRuntimeExports.jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsxRuntimeExports.jsx("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: legendVisibleId, children: "Legend Visible: " }), jsxRuntimeExports.jsx(Checkbox$1, { color: "primary", className: menuClasses.menuItemCheckbox, checked: legendVisible, onChange: (e3, v) => setLegendVisible(v), slotProps: { input: { id: legendVisibleId, "aria-label": "Toggle legend visibility" } } })] })] });
264542
264666
  }
264543
264667
  function PointLayerController(props) {
264544
- const { theme, layerScope, layerCoordination, setLayerCoordination, palette = null, pointMatrixIndicesData, tiledPointsLoadingProgress } = props;
264668
+ const { theme, layerScope, layerCoordination, setLayerCoordination, palette = null, pointMatrixIndicesData, tiledPointsLoadingProgress, layerPerFeatureForPoints } = props;
264545
264669
  const [open2, setOpen] = useState(false);
264546
264670
  const loadingDoneFraction = useMemo$1(() => {
264547
264671
  if (tiledPointsLoadingProgress && typeof tiledPointsLoadingProgress === "object") {
@@ -264626,7 +264750,8 @@ function PointLayerController(props) {
264626
264750
  useCallback(() => setOpen((prev2) => !prev2), []);
264627
264751
  const [coloringTabIndex, setColoringTabIndex] = useState(0);
264628
264752
  const { featureIndex } = pointMatrixIndicesData || {};
264629
- return jsxRuntimeExports.jsx(Grid$1, { className: lcClasses.layerControllerGrid, children: jsxRuntimeExports.jsxs(Paper, { elevation: 4, className: lcClasses.layerControllerRoot, children: [jsxRuntimeExports.jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsxRuntimeExports.jsx(Grid$1, { size: 1, children: jsxRuntimeExports.jsx(Button, { onClick: handleVisibleChange, className: menuClasses.imageLayerVisibleButton, "aria-label": "Toggle layer visibility", children: jsxRuntimeExports.jsx(Visibility, {}) }) }), jsxRuntimeExports.jsx(Grid$1, { size: 1, children: jsxRuntimeExports.jsx(ChannelColorPickerMenu, { theme, color: color2, setColor: setColor2, palette, isStaticColor, isColormap, featureValueColormap, visible }) }), jsxRuntimeExports.jsx(Grid$1, { size: 6, children: jsxRuntimeExports.jsx(Typography, { className: menuClasses.imageLayerName, children: label2 }) }), jsxRuntimeExports.jsx(Grid$1, { size: 2, children: jsxRuntimeExports.jsx(Slider, { value: opacity2, min: 0, max: 1, step: 1e-3, onChange: handleOpacityChange, className: menuClasses.imageLayerOpacitySlider, orientation: "horizontal", "aria-label": `Adjust opacity for layer ${label2}` }) }), jsxRuntimeExports.jsx(Grid$1, { size: 1, children: jsxRuntimeExports.jsx(PointLayerEllipsisMenu, { featureSelection, obsColorEncoding, setObsColorEncoding, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible, featureFilterMode, setFeatureFilterMode }) }), jsxRuntimeExports.jsxs(Grid$1, { size: 1, container: true, direction: "row", children: [jsxRuntimeExports.jsx(SvgPoints, { className: classes2.layerTypePointIcon }), null] })] }), loadingDoneFraction < 1 ? jsxRuntimeExports.jsx(Grid$1, { size: 12, container: true, direction: "column", justifyContent: "space-between", className: classes2.pointFeatureControllerGrid, children: jsxRuntimeExports.jsx(LinearProgress, { variant: loadingDoneFraction === 0 ? "indeterminate" : "determinate", value: loadingDoneFraction * 100 }) }) : null, null] }) });
264753
+ const hasSelectedFeatures = Array.isArray(featureSelection) && featureSelection.length > 0;
264754
+ return jsxRuntimeExports.jsxs(Grid$1, { className: lcClasses.layerControllerGrid, children: [jsxRuntimeExports.jsxs(Paper, { elevation: 4, className: lcClasses.layerControllerRoot, children: [jsxRuntimeExports.jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsxRuntimeExports.jsx(Grid$1, { size: 1, children: jsxRuntimeExports.jsx(Button, { onClick: handleVisibleChange, className: menuClasses.imageLayerVisibleButton, "aria-label": "Toggle layer visibility", children: jsxRuntimeExports.jsx(Visibility, {}) }) }), jsxRuntimeExports.jsx(Grid$1, { size: 1, children: jsxRuntimeExports.jsx(ChannelColorPickerMenu, { theme, color: color2, setColor: setColor2, palette, isStaticColor, isColormap, featureValueColormap, visible }) }), jsxRuntimeExports.jsx(Grid$1, { size: 6, children: jsxRuntimeExports.jsx(Typography, { className: menuClasses.imageLayerName, children: label2 }) }), jsxRuntimeExports.jsx(Grid$1, { size: 2, children: jsxRuntimeExports.jsx(Slider, { value: opacity2, min: 0, max: 1, step: 1e-3, onChange: handleOpacityChange, className: menuClasses.imageLayerOpacitySlider, orientation: "horizontal", "aria-label": `Adjust opacity for layer ${label2}` }) }), jsxRuntimeExports.jsx(Grid$1, { size: 1, children: jsxRuntimeExports.jsx(PointLayerEllipsisMenu, { featureSelection, obsColorEncoding, setObsColorEncoding, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible, featureFilterMode, setFeatureFilterMode }) }), jsxRuntimeExports.jsxs(Grid$1, { size: 1, container: true, direction: "row", children: [jsxRuntimeExports.jsx(SvgPoints, { className: classes2.layerTypePointIcon }), null] })] }), loadingDoneFraction < 1 ? jsxRuntimeExports.jsx(Grid$1, { size: 12, container: true, direction: "column", justifyContent: "space-between", className: classes2.pointFeatureControllerGrid, children: jsxRuntimeExports.jsx(LinearProgress, { variant: loadingDoneFraction === 0 ? "indeterminate" : "determinate", value: loadingDoneFraction * 100 }) }) : null, null] }), hasSelectedFeatures ? jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [featureSelection.map((featureName) => jsxRuntimeExports.jsx(LayerPerFeatureController, { theme, featureName, featureColor, setFeatureColor, spatialLayerColor, featureIndex, featureValueColormap, featureSelection, setFeatureSelection, obsColorEncoding, loadingDoneFraction, opacity: opacity2, handleOpacityChange }, featureName)), jsxRuntimeExports.jsx(Grid$1, { className: lcClasses.layerControllerGrid, children: jsxRuntimeExports.jsx(Paper, { elevation: 2, className: lcClasses.layerControllerSubRow, children: jsxRuntimeExports.jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsxRuntimeExports.jsx(Grid$1, { size: 1, children: jsxRuntimeExports.jsx(Button, { onClick: () => setFeatureFilterMode(featureFilterMode === "featureSelection" ? null : "featureSelection"), className: menuClasses.imageLayerVisibleButton, "aria-label": "Toggle visibility of unselected points", children: featureFilterMode === "featureSelection" ? jsxRuntimeExports.jsx(VisibilityOffIcon, {}) : jsxRuntimeExports.jsx(VisibilityIcon, {}) }) }), jsxRuntimeExports.jsx(Grid$1, { size: 1, children: jsxRuntimeExports.jsx(ChannelColorPickerMenu, { theme, color: getDefaultColor("dark"), setColor: null, isStaticColor: true, isColormap: false, visible: true }) }), jsxRuntimeExports.jsx(Grid$1, { size: 6, children: jsxRuntimeExports.jsx(Typography, { className: menuClasses.imageLayerName, children: "Unselected" }) }), jsxRuntimeExports.jsx(Grid$1, { size: 2, sx: { paddingRight: "12px", overflow: "visible" }, children: jsxRuntimeExports.jsx(Slider, { value: opacity2, min: 0, max: 1, step: 1e-3, onChange: handleOpacityChange, className: menuClasses.imageLayerOpacitySlider, orientation: "horizontal", "aria-label": "Adjust opacity for unselected layer" }) }), jsxRuntimeExports.jsx(Grid$1, { size: 1, children: jsxRuntimeExports.jsx(SvgPoints, { className: classes2.layerTypePointIcon }) })] }) }) })] }) : null] });
264630
264755
  }
264631
264756
  const useStyles$d = makeStyles()(() => ({
264632
264757
  layerTypeSegmentationIcon: {
@@ -266284,16 +266409,17 @@ function GlobalDimensionSlider(props) {
266284
266409
  const { classes: lcClasses } = useControllerSectionStyles();
266285
266410
  const { classes: classes2 } = useStyles$7();
266286
266411
  const isForZ = spatialRenderingMode !== null;
266412
+ const is3dMode = spatialRenderingMode === "3D";
266287
266413
  function handleRenderingModeChange(event2) {
266288
266414
  setSpatialRenderingMode(event2.target.checked ? "3D" : "2D");
266289
266415
  if (!event2.target.checked) {
266290
266416
  setTargetValue(Math.floor(targetValue));
266291
266417
  }
266292
266418
  }
266293
- return jsxRuntimeExports.jsx(Grid$1, { className: lcClasses.layerControllerGrid, children: jsxRuntimeExports.jsx(Paper, { elevation: 4, className: lcClasses.layerControllerRoot, children: jsxRuntimeExports.jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsxRuntimeExports.jsx(Grid$1, { size: 1, children: jsxRuntimeExports.jsx(SvgDimensions, { className: classes2.dimensionsIcon }) }), jsxRuntimeExports.jsx(Grid$1, { size: 1, children: jsxRuntimeExports.jsx(Typography, { className: classes2.dimensionLabel, children: label2 }) }), jsxRuntimeExports.jsx(Grid$1, { size: 8, children: jsxRuntimeExports.jsx(Slider, { value: targetValue, min: min2, max: max2, step: 1, onChange: (e3, v) => setTargetValue(v), className: classes2.dimensionSlider, valueLabelDisplay: "auto", orientation: "horizontal", disabled: spatialRenderingMode === "3D", "aria-label": `${label2}-slice slider` }) }), jsxRuntimeExports.jsx(Grid$1, { size: 2, children: isForZ ? jsxRuntimeExports.jsx(FormGroup, { row: true, className: classes2.switchFormGroup, children: jsxRuntimeExports.jsx(FormControlLabel$1, { control: jsxRuntimeExports.jsx(Switch, { color: "primary", checked: spatialRenderingMode === "3D", onChange: handleRenderingModeChange, name: "is3dMode" }), label: "3D" }) }) : null })] }) }) });
266419
+ return jsxRuntimeExports.jsx(Grid$1, { className: lcClasses.layerControllerGrid, children: jsxRuntimeExports.jsx(Paper, { elevation: 4, className: lcClasses.layerControllerRoot, children: jsxRuntimeExports.jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsxRuntimeExports.jsx(Grid$1, { size: 1, children: jsxRuntimeExports.jsx(SvgDimensions, { className: classes2.dimensionsIcon }) }), jsxRuntimeExports.jsx(Grid$1, { size: 1, children: jsxRuntimeExports.jsx(Typography, { className: classes2.dimensionLabel, children: label2 }) }), jsxRuntimeExports.jsx(Grid$1, { size: 8, children: !is3dMode ? jsxRuntimeExports.jsx(Slider, { value: targetValue, min: min2, max: max2, step: 1, onChange: (e3, v) => setTargetValue(v), className: classes2.dimensionSlider, valueLabelDisplay: "auto", orientation: "horizontal", disabled: spatialRenderingMode === "3D", "aria-label": `${label2}-slice slider` }) : null }), jsxRuntimeExports.jsx(Grid$1, { size: 2, children: isForZ ? jsxRuntimeExports.jsx(FormGroup, { row: true, className: classes2.switchFormGroup, children: jsxRuntimeExports.jsx(FormControlLabel$1, { control: jsxRuntimeExports.jsx(Switch, { color: "primary", checked: spatialRenderingMode === "3D", onChange: handleRenderingModeChange, name: "is3dMode" }), label: "3D" }) }) : null })] }) }) });
266294
266420
  }
266295
266421
  function LayerController(props) {
266296
- const { theme, coordinationScopesRaw, segmentationLayerScopes, segmentationLayerCoordination, segmentationChannelScopesByLayer, segmentationChannelCoordination, images, imageLayerScopes, imageLayerCoordination, targetT, targetZ, setTargetT, setTargetZ, spatialRenderingMode, setSpatialRenderingMode, imageChannelScopesByLayer, imageChannelCoordination, spotLayerScopes, spotLayerCoordination, pointLayerScopes, pointLayerCoordination, pointMultiIndicesData, volumeLoadingStatus, tiledPointsLoadingProgress } = props;
266422
+ const { theme, coordinationScopesRaw, segmentationLayerScopes, segmentationLayerCoordination, segmentationChannelScopesByLayer, segmentationChannelCoordination, images, imageLayerScopes, imageLayerCoordination, targetT, targetZ, setTargetT, setTargetZ, spatialRenderingMode, setSpatialRenderingMode, imageChannelScopesByLayer, imageChannelCoordination, spotLayerScopes, spotLayerCoordination, pointLayerScopes, pointLayerCoordination, pointMultiIndicesData, volumeLoadingStatus, tiledPointsLoadingProgress, layerPerFeatureForPoints } = props;
266297
266423
  const anyLayerHasT = Object.values(images || {}).some((image2) => image2?.image?.instance.hasTStack());
266298
266424
  const anyLayerHasZ = Object.values(images || {}).some((image2) => image2?.image?.instance.hasZStack());
266299
266425
  const maxT = Object.values(images || {}).reduce((a2, h2) => Math.max(a2, h2?.image?.instance.getNumT()), 1) - 1;
@@ -266302,10 +266428,10 @@ function LayerController(props) {
266302
266428
  const reversedSegmentationLayerScopes = useMemo$1(() => [...segmentationLayerScopes || []].reverse(), [segmentationLayerScopes]);
266303
266429
  const reversedSpotLayerScopes = useMemo$1(() => [...spotLayerScopes || []].reverse(), [spotLayerScopes]);
266304
266430
  const reversedPointLayerScopes = useMemo$1(() => [...pointLayerScopes || []].reverse(), [pointLayerScopes]);
266305
- return jsxRuntimeExports.jsxs("div", { children: [anyLayerHasZ ? jsxRuntimeExports.jsx(GlobalDimensionSlider, { label: "Z", targetValue: targetZ, setTargetValue: setTargetZ, max: maxZ, spatialRenderingMode, setSpatialRenderingMode }) : null, anyLayerHasT ? jsxRuntimeExports.jsx(GlobalDimensionSlider, { label: "T", targetValue: targetT, setTargetValue: setTargetT, max: maxT }) : null, pointLayerScopes && reversedPointLayerScopes.map((layerScope) => jsxRuntimeExports.jsx(PointLayerController, { theme, layerScope, layerCoordination: pointLayerCoordination[0][layerScope], setLayerCoordination: pointLayerCoordination[1][layerScope], pointMatrixIndicesData: pointMultiIndicesData?.[layerScope], tiledPointsLoadingProgress }, layerScope)), spotLayerScopes && reversedSpotLayerScopes.map((layerScope) => jsxRuntimeExports.jsx(SpotLayerController, { theme, layerScope, layerCoordination: spotLayerCoordination[0][layerScope], setLayerCoordination: spotLayerCoordination[1][layerScope] }, layerScope)), segmentationLayerScopes && reversedSegmentationLayerScopes.map((layerScope) => jsxRuntimeExports.jsx(SegmentationLayerController, { theme, layerScope, layerCoordination: segmentationLayerCoordination[0][layerScope], setLayerCoordination: segmentationLayerCoordination[1][layerScope], channelScopes: segmentationChannelScopesByLayer[layerScope], channelCoordination: segmentationChannelCoordination[0][layerScope], setChannelCoordination: segmentationChannelCoordination[1][layerScope] }, layerScope)), imageLayerScopes && reversedImageLayerScopes.map((layerScope) => jsxRuntimeExports.jsx(ImageLayerController, { theme, coordinationScopesRaw, layerScope, layerCoordination: imageLayerCoordination[0][layerScope], setLayerCoordination: imageLayerCoordination[1][layerScope], channelScopes: imageChannelScopesByLayer[layerScope], channelCoordination: imageChannelCoordination[0][layerScope], setChannelCoordination: imageChannelCoordination[1][layerScope], image: images[layerScope]?.image?.instance, featureIndex: images[layerScope]?.featureIndex, targetT, targetZ, spatialRenderingMode, volumeLoadingProgress: volumeLoadingStatus?.loadingProgress, onStopVolumeLoading: volumeLoadingStatus?.onStopLoading, onRestartVolumeLoading: volumeLoadingStatus?.onRestartLoading, volumeStillRef: volumeLoadingStatus?.stillRef }, layerScope))] });
266431
+ return jsxRuntimeExports.jsxs("div", { children: [anyLayerHasZ ? jsxRuntimeExports.jsx(GlobalDimensionSlider, { label: "Z", targetValue: targetZ, setTargetValue: setTargetZ, max: maxZ, spatialRenderingMode, setSpatialRenderingMode }) : null, anyLayerHasT ? jsxRuntimeExports.jsx(GlobalDimensionSlider, { label: "T", targetValue: targetT, setTargetValue: setTargetT, max: maxT }) : null, pointLayerScopes && reversedPointLayerScopes.map((layerScope) => jsxRuntimeExports.jsx(PointLayerController, { theme, layerScope, layerCoordination: pointLayerCoordination[0][layerScope], setLayerCoordination: pointLayerCoordination[1][layerScope], pointMatrixIndicesData: pointMultiIndicesData?.[layerScope], tiledPointsLoadingProgress, layerPerFeatureForPoints }, layerScope)), spotLayerScopes && reversedSpotLayerScopes.map((layerScope) => jsxRuntimeExports.jsx(SpotLayerController, { theme, layerScope, layerCoordination: spotLayerCoordination[0][layerScope], setLayerCoordination: spotLayerCoordination[1][layerScope] }, layerScope)), segmentationLayerScopes && reversedSegmentationLayerScopes.map((layerScope) => jsxRuntimeExports.jsx(SegmentationLayerController, { theme, layerScope, layerCoordination: segmentationLayerCoordination[0][layerScope], setLayerCoordination: segmentationLayerCoordination[1][layerScope], channelScopes: segmentationChannelScopesByLayer[layerScope], channelCoordination: segmentationChannelCoordination[0][layerScope], setChannelCoordination: segmentationChannelCoordination[1][layerScope] }, layerScope)), imageLayerScopes && reversedImageLayerScopes.map((layerScope) => jsxRuntimeExports.jsx(ImageLayerController, { theme, coordinationScopesRaw, layerScope, layerCoordination: imageLayerCoordination[0][layerScope], setLayerCoordination: imageLayerCoordination[1][layerScope], channelScopes: imageChannelScopesByLayer[layerScope], channelCoordination: imageChannelCoordination[0][layerScope], setChannelCoordination: imageChannelCoordination[1][layerScope], image: images[layerScope]?.image?.instance, featureIndex: images[layerScope]?.featureIndex, targetT, targetZ, spatialRenderingMode, volumeLoadingProgress: volumeLoadingStatus?.loadingProgress, onStopVolumeLoading: volumeLoadingStatus?.onStopLoading, onRestartVolumeLoading: volumeLoadingStatus?.onRestartLoading, volumeStillRef: volumeLoadingStatus?.stillRef }, layerScope))] });
266306
266432
  }
266307
266433
  function LayerControllerSubscriber(props) {
266308
- const { coordinationScopes: coordinationScopesRaw, coordinationScopesBy: coordinationScopesByRaw, closeButtonVisible, downloadButtonVisible, removeGridComponent, theme, title: title2 = "Spatial Layers", uuid: uuid2, cameraPresets } = props;
266434
+ const { coordinationScopes: coordinationScopesRaw, coordinationScopesBy: coordinationScopesByRaw, closeButtonVisible, downloadButtonVisible, removeGridComponent, theme, title: title2 = "Spatial Layers", uuid: uuid2, layerPerFeatureForPoints = false, cameraPresets } = props;
266309
266435
  const loaders = useLoaders();
266310
266436
  const mergeCoordination = useMergeCoordination();
266311
266437
  const coordinationScopes = useCoordinationScopes(coordinationScopesRaw);
@@ -266461,7 +266587,7 @@ function LayerControllerSubscriber(props) {
266461
266587
  imageDataStatus,
266462
266588
  pointMultiIndicesDataStatus
266463
266589
  ]);
266464
- return jsxRuntimeExports.jsx(TitleInfo, { title: title2, isScroll: true, closeButtonVisible, downloadButtonVisible, removeGridComponent, theme, isReady, errors, children: jsxRuntimeExports.jsx(LayerController, { theme, coordinationScopesRaw, segmentationLayerScopes, segmentationLayerCoordination, segmentationChannelScopesByLayer, segmentationChannelCoordination, images: imageData, imageLayerScopes, imageLayerCoordination, targetT, targetZ, setTargetT, setTargetZ, spatialRenderingMode, setSpatialRenderingMode, imageChannelScopesByLayer, imageChannelCoordination, spotLayerScopes, spotLayerCoordination, pointLayerScopes, pointLayerCoordination, pointMultiIndicesData, volumeLoadingStatus, tiledPointsLoadingProgress }) });
266590
+ return jsxRuntimeExports.jsx(TitleInfo, { title: title2, isScroll: true, closeButtonVisible, downloadButtonVisible, removeGridComponent, theme, isReady, errors, children: jsxRuntimeExports.jsx(LayerController, { theme, coordinationScopesRaw, segmentationLayerScopes, segmentationLayerCoordination, segmentationChannelScopesByLayer, segmentationChannelCoordination, images: imageData, imageLayerScopes, imageLayerCoordination, targetT, targetZ, setTargetT, setTargetZ, spatialRenderingMode, setSpatialRenderingMode, imageChannelScopesByLayer, imageChannelCoordination, spotLayerScopes, spotLayerCoordination, pointLayerScopes, pointLayerCoordination, pointMultiIndicesData, layerPerFeatureForPoints, volumeLoadingStatus, tiledPointsLoadingProgress }) });
266465
266591
  }
266466
266592
  const isIterable$2 = (obj) => Symbol.iterator in obj;
266467
266593
  const hasIterableEntries = (value2) => (
@@ -268459,7 +268585,7 @@ function HiglassGlobalStyles(props) {
268459
268585
  }
268460
268586
  register({ dataFetcher: ZarrMultivecDataFetcher_default, config: ZarrMultivecDataFetcher_default.config }, { pluginType: "dataFetcher" });
268461
268587
  const LazyHiGlassComponent = React__default.lazy(async () => {
268462
- const { HiGlassComponent } = await import("./higlass-BABKAqJw.js");
268588
+ const { HiGlassComponent } = await import("./higlass-wSBrpMhX.js");
268463
268589
  return { default: HiGlassComponent };
268464
268590
  });
268465
268591
  const HG_SIZE = 800;
@@ -271407,7 +271533,7 @@ function NeuroglancerGlobalStyles(props) {
271407
271533
  const { classes: classes2 } = props;
271408
271534
  return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(GlobalStyles$3, { styles: globalNeuroglancerCss }), jsxRuntimeExports.jsx(ScopedGlobalStyles, { styles: globalNeuroglancerStyles, parentClassName: classes2.neuroglancerWrapper })] });
271409
271535
  }
271410
- const LazyReactNeuroglancer = React__default.lazy(() => import("./ReactNeuroglancer-DC-9NQV1.js"));
271536
+ const LazyReactNeuroglancer = React__default.lazy(() => import("./ReactNeuroglancer-x4EMSEcX.js"));
271411
271537
  function createWorker() {
271412
271538
  const worker = new WorkerFactory$1();
271413
271539
  worker.AsyncComputationWorker = WorkerFactory;
@@ -271478,8 +271604,8 @@ class NeuroglancerComp extends PureComponent {
271478
271604
  }
271479
271605
  }
271480
271606
  render() {
271481
- const { classes: classes2, viewerState, cellColorMapping } = this.props;
271482
- return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(NeuroglancerGlobalStyles, { classes: classes2 }), jsxRuntimeExports.jsx("div", { className: classes2.neuroglancerWrapper, children: jsxRuntimeExports.jsx(Suspense, { fallback: jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: jsxRuntimeExports.jsx(LazyReactNeuroglancer, { brainMapsClientId: "NOT_A_VALID_ID", viewerState, onViewerStateChanged: this.onViewerStateChanged, bundleRoot: this.bundleRoot, cellColorMapping, ref: this.onRef }) }) })] });
271607
+ const { classes: classes2, viewerState, cellColorMapping, onLayerLoadingChange } = this.props;
271608
+ return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(NeuroglancerGlobalStyles, { classes: classes2 }), jsxRuntimeExports.jsx("div", { className: classes2.neuroglancerWrapper, children: jsxRuntimeExports.jsx(Suspense, { fallback: jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: jsxRuntimeExports.jsx(LazyReactNeuroglancer, { brainMapsClientId: "NOT_A_VALID_ID", viewerState, onViewerStateChanged: this.onViewerStateChanged, onLayerLoadingChange, bundleRoot: this.bundleRoot, cellColorMapping, ref: this.onRef }) }) })] });
271483
271609
  }
271484
271610
  }
271485
271611
  function useMemoCustomComparison(factory2, dependencies2, customIsEqual) {
@@ -271518,7 +271644,8 @@ function customIsEqualForCellColors(prevDeps, nextDeps) {
271518
271644
  "obsColorEncoding",
271519
271645
  "obsSetSelection",
271520
271646
  "additionalObsSets",
271521
- "spatialChannelColor"
271647
+ "spatialChannelColor",
271648
+ "spatialChannelOpacity"
271522
271649
  ])) {
271523
271650
  forceUpdate = true;
271524
271651
  }
@@ -271533,6 +271660,9 @@ function customIsEqualForInitialViewerState(prevDeps, nextDeps) {
271533
271660
  const curriedShallowDiffByLayer = (depName, scopeName) => shallowDiffByLayer(prevDeps, nextDeps, depName, scopeName);
271534
271661
  const curriedShallowDiffByLayerCoordinationWithKeys = (depName, layerScope, keys2) => shallowDiffByLayerCoordinationWithKeys(prevDeps, nextDeps, depName, layerScope, keys2);
271535
271662
  const curriedShallowDiffByChannelCoordinationWithKeys = (depName, layerScope, channelScope, keys2) => shallowDiffByChannelCoordinationWithKeys(prevDeps, nextDeps, depName, layerScope, channelScope, keys2);
271663
+ if (["theme", "showAxisLines"].some(curriedShallowDiff)) {
271664
+ forceUpdate = true;
271665
+ }
271536
271666
  if (["segmentationLayerScopes", "segmentationChannelScopesByLayer"].some(curriedShallowDiff)) {
271537
271667
  forceUpdate = true;
271538
271668
  } else {
@@ -271561,7 +271691,8 @@ function customIsEqualForInitialViewerState(prevDeps, nextDeps) {
271561
271691
  "spatialLayerColor",
271562
271692
  "featureSelection",
271563
271693
  "featureFilterMode",
271564
- "featureColor"
271694
+ "featureColor",
271695
+ "spatialPointStrokeWidth"
271565
271696
  ]) || Math.abs(prevDeps?.pointLayerCoordination?.[0]?.[layerScope]?.spatialLayerOpacity - nextDeps?.pointLayerCoordination?.[0]?.[layerScope]?.spatialLayerOpacity) >= 0.05) {
271566
271697
  forceUpdate = true;
271567
271698
  }
@@ -271572,21 +271703,25 @@ function customIsEqualForInitialViewerState(prevDeps, nextDeps) {
271572
271703
  function normalizeColor(rgbColor) {
271573
271704
  return rgbColor.map((c2) => c2 / 255);
271574
271705
  }
271706
+ function borderWidthGlsl(borderWidth = 0) {
271707
+ return `setPointMarkerBorderWidth(${borderWidth.toFixed(1)});`;
271708
+ }
271575
271709
  function toVec3(normalizedColor) {
271576
271710
  return `vec3(${normalizedColor.join(", ")})`;
271577
271711
  }
271578
271712
  function toVec4(normalizedColor, alpha2) {
271579
271713
  return `vec4(${normalizedColor.join(", ")}, ${alpha2})`;
271580
271714
  }
271581
- function getSpatialLayerColorShader(staticColor, opacity2) {
271715
+ function getSpatialLayerColorShader(staticColor, opacity2, borderWidth = 0) {
271582
271716
  const norm2 = normalizeColor(staticColor);
271583
271717
  return `
271584
271718
  void main() {
271585
271719
  setColor(${toVec4(norm2, opacity2)});
271720
+ ${borderWidthGlsl(borderWidth)}
271586
271721
  }
271587
271722
  `;
271588
271723
  }
271589
- function getSpatialLayerColorWithSelectionShader(staticColor, opacity2, featureIndices, defaultColor, featureIndexProp) {
271724
+ function getSpatialLayerColorWithSelectionShader(staticColor, opacity2, featureIndices, defaultColor, featureIndexProp, borderWidth = 0) {
271590
271725
  const normStatic = normalizeColor(staticColor);
271591
271726
  const normDefault = normalizeColor(defaultColor);
271592
271727
  const numFeatures = featureIndices.length;
@@ -271603,13 +271738,15 @@ function getSpatialLayerColorWithSelectionShader(staticColor, opacity2, featureI
271603
271738
  }
271604
271739
  if (isSelected) {
271605
271740
  setColor(${toVec4(normStatic, opacity2)});
271741
+ ${borderWidthGlsl(borderWidth)}
271606
271742
  } else {
271607
271743
  setColor(${toVec4(normDefault, opacity2)});
271744
+ ${borderWidthGlsl(borderWidth)}
271608
271745
  }
271609
271746
  }
271610
271747
  `;
271611
271748
  }
271612
- function getSpatialLayerColorFilteredShader(staticColor, opacity2, featureIndices, featureIndexProp) {
271749
+ function getSpatialLayerColorFilteredShader(staticColor, opacity2, featureIndices, featureIndexProp, borderWidth = 0) {
271613
271750
  const normStatic = normalizeColor(staticColor);
271614
271751
  const numFeatures = featureIndices.length;
271615
271752
  const indicesArr = `int selectedIndices[${numFeatures}] = int[${numFeatures}](${featureIndices.join(", ")});`;
@@ -271627,18 +271764,20 @@ function getSpatialLayerColorFilteredShader(staticColor, opacity2, featureIndice
271627
271764
  discard;
271628
271765
  }
271629
271766
  setColor(${toVec4(normStatic, opacity2)});
271767
+ ${borderWidthGlsl(borderWidth)}
271630
271768
  }
271631
271769
  `;
271632
271770
  }
271633
- function getGeneSelectionNoSelectionShader(staticColor, opacity2) {
271771
+ function getGeneSelectionNoSelectionShader(staticColor, opacity2, borderWidth = 0) {
271634
271772
  const norm2 = normalizeColor(staticColor);
271635
271773
  return `
271636
271774
  void main() {
271637
271775
  setColor(${toVec4(norm2, opacity2)});
271776
+ ${borderWidthGlsl(borderWidth)}
271638
271777
  }
271639
271778
  `;
271640
271779
  }
271641
- function getGeneSelectionWithSelectionShader(featureIndices, featureColors, staticColor, defaultColor, opacity2, featureIndexProp) {
271780
+ function getGeneSelectionWithSelectionShader(featureIndices, featureColors, staticColor, defaultColor, opacity2, featureIndexProp, borderWidth = 0) {
271642
271781
  const numFeatures = featureIndices.length;
271643
271782
  const normDefault = normalizeColor(defaultColor);
271644
271783
  const normColors = featureColors.map((c2) => normalizeColor(c2));
@@ -271658,10 +271797,11 @@ function getGeneSelectionWithSelectionShader(featureIndices, featureColors, stat
271658
271797
  }
271659
271798
  }
271660
271799
  setColor(color);
271800
+ ${borderWidthGlsl(borderWidth)}
271661
271801
  }
271662
271802
  `;
271663
271803
  }
271664
- function getGeneSelectionFilteredShader(featureIndices, featureColors, staticColor, opacity2, featureIndexProp) {
271804
+ function getGeneSelectionFilteredShader(featureIndices, featureColors, staticColor, opacity2, featureIndexProp, borderWidth = 0) {
271665
271805
  const numFeatures = featureIndices.length;
271666
271806
  const normColors = featureColors.map((c2) => normalizeColor(c2));
271667
271807
  const normStatic = normalizeColor(staticColor);
@@ -271685,10 +271825,11 @@ function getGeneSelectionFilteredShader(featureIndices, featureColors, staticCol
271685
271825
  discard;
271686
271826
  }
271687
271827
  setColor(vec4(matchedColor, ${opacity2}));
271828
+ ${borderWidthGlsl(borderWidth)}
271688
271829
  }
271689
271830
  `;
271690
271831
  }
271691
- function getRandomByFeatureShader(opacity2, featureIndexProp) {
271832
+ function getRandomByFeatureShader(opacity2, featureIndexProp, borderWidth = 0) {
271692
271833
  const paletteSize = PALETTE.length;
271693
271834
  const normPalette = PALETTE.map((c2) => normalizeColor(c2));
271694
271835
  const paletteDecl = `vec3 palette[${paletteSize}] = vec3[${paletteSize}](${normPalette.map((c2) => toVec3(c2)).join(", ")});`;
@@ -271700,10 +271841,11 @@ function getRandomByFeatureShader(opacity2, featureIndexProp) {
271700
271841
  if (colorIdx < 0) { colorIdx = -colorIdx; }
271701
271842
  vec3 color = palette[colorIdx];
271702
271843
  setColor(vec4(color, ${opacity2}));
271844
+ ${borderWidthGlsl(borderWidth)}
271703
271845
  }
271704
271846
  `;
271705
271847
  }
271706
- function getRandomByFeatureWithSelectionShader(featureIndices, defaultColor, opacity2, featureIndexProp) {
271848
+ function getRandomByFeatureWithSelectionShader(featureIndices, defaultColor, opacity2, featureIndexProp, borderWidth = 0) {
271707
271849
  const paletteSize = PALETTE.length;
271708
271850
  const normPalette = PALETTE.map((c2) => normalizeColor(c2));
271709
271851
  const normDefault = normalizeColor(defaultColor);
@@ -271725,13 +271867,15 @@ function getRandomByFeatureWithSelectionShader(featureIndices, defaultColor, opa
271725
271867
  int colorIdx = geneIndex - (geneIndex / ${paletteSize}) * ${paletteSize};
271726
271868
  if (colorIdx < 0) { colorIdx = -colorIdx; }
271727
271869
  setColor(vec4(palette[colorIdx], ${opacity2}));
271870
+ ${borderWidthGlsl(borderWidth)}
271728
271871
  } else {
271729
271872
  setColor(${toVec4(normDefault, opacity2)});
271873
+ ${borderWidthGlsl(borderWidth)}
271730
271874
  }
271731
271875
  }
271732
271876
  `;
271733
271877
  }
271734
- function getRandomByFeatureFilteredShader(featureIndices, opacity2, featureIndexProp) {
271878
+ function getRandomByFeatureFilteredShader(featureIndices, opacity2, featureIndexProp, borderWidth = 0) {
271735
271879
  const paletteSize = PALETTE.length;
271736
271880
  const normPalette = PALETTE.map((c2) => normalizeColor(c2));
271737
271881
  const numFeatures = featureIndices.length;
@@ -271754,6 +271898,7 @@ function getRandomByFeatureFilteredShader(featureIndices, opacity2, featureIndex
271754
271898
  int colorIdx = geneIndex - (geneIndex / ${paletteSize}) * ${paletteSize};
271755
271899
  if (colorIdx < 0) { colorIdx = -colorIdx; }
271756
271900
  setColor(vec4(palette[colorIdx], ${opacity2}));
271901
+ ${borderWidthGlsl(borderWidth)}
271757
271902
  }
271758
271903
  `;
271759
271904
  }
@@ -271768,7 +271913,7 @@ function hashToFloatGlsl() {
271768
271913
  }
271769
271914
  `;
271770
271915
  }
271771
- function getRandomPerPointShader(opacity2, featureIndexProp, pointIndexProp) {
271916
+ function getRandomPerPointShader(opacity2, featureIndexProp, pointIndexProp, borderWidth = 0) {
271772
271917
  return `
271773
271918
  ${hashToFloatGlsl()}
271774
271919
  void main() {
@@ -271778,10 +271923,11 @@ function getRandomPerPointShader(opacity2, featureIndexProp, pointIndexProp) {
271778
271923
  float g = hashToFloat(pointIndex, 1);
271779
271924
  float b = hashToFloat(pointIndex, 2);
271780
271925
  setColor(vec4(r, g, b, ${opacity2}));
271926
+ ${borderWidthGlsl(borderWidth)}
271781
271927
  }
271782
271928
  `;
271783
271929
  }
271784
- function getRandomPerPointWithSelectionShader(featureIndices, defaultColor, opacity2, featureIndexProp, pointIndexProp) {
271930
+ function getRandomPerPointWithSelectionShader(featureIndices, defaultColor, opacity2, featureIndexProp, pointIndexProp, borderWidth = 0) {
271785
271931
  const normDefault = normalizeColor(defaultColor);
271786
271932
  const numFeatures = featureIndices.length;
271787
271933
  const indicesDecl = `int selectedIndices[${numFeatures}] = int[${numFeatures}](${featureIndices.join(", ")});`;
@@ -271802,13 +271948,15 @@ function getRandomPerPointWithSelectionShader(featureIndices, defaultColor, opac
271802
271948
  float g = hashToFloat(pointIndex, 1);
271803
271949
  float b = hashToFloat(pointIndex, 2);
271804
271950
  setColor(vec4(r, g, b, ${opacity2}));
271951
+ ${borderWidthGlsl(borderWidth)}
271805
271952
  } else {
271806
271953
  setColor(${toVec4(normDefault, opacity2)});
271954
+ ${borderWidthGlsl(borderWidth)}
271807
271955
  }
271808
271956
  }
271809
271957
  `;
271810
271958
  }
271811
- function getRandomPerPointFilteredShader(featureIndices, opacity2, featureIndexProp, pointIndexProp) {
271959
+ function getRandomPerPointFilteredShader(featureIndices, opacity2, featureIndexProp, pointIndexProp, borderWidth = 0) {
271812
271960
  const numFeatures = featureIndices.length;
271813
271961
  const indicesDecl = `int selectedIndices[${numFeatures}] = int[${numFeatures}](${featureIndices.join(", ")});`;
271814
271962
  return `
@@ -271830,11 +271978,12 @@ function getRandomPerPointFilteredShader(featureIndices, opacity2, featureIndexP
271830
271978
  float g = hashToFloat(pointIndex, 1);
271831
271979
  float b = hashToFloat(pointIndex, 2);
271832
271980
  setColor(vec4(r, g, b, ${opacity2}));
271981
+ ${borderWidthGlsl(borderWidth)}
271833
271982
  }
271834
271983
  `;
271835
271984
  }
271836
271985
  function getPointsShader(layerCoordination) {
271837
- const { theme, featureIndex, spatialLayerOpacity, obsColorEncoding, spatialLayerColor, featureSelection, featureFilterMode, featureColor, featureIndexProp, pointIndexProp } = layerCoordination;
271986
+ const { theme, featureIndex, spatialLayerOpacity, obsColorEncoding, spatialLayerColor, featureSelection, featureFilterMode, featureColor, pointMarkerBorderWidth = 0, featureIndexProp, pointIndexProp } = layerCoordination;
271838
271987
  const defaultColor = getDefaultColor(theme);
271839
271988
  const opacity2 = spatialLayerOpacity ?? 1;
271840
271989
  const staticColor = Array.isArray(spatialLayerColor) && spatialLayerColor.length === 3 ? spatialLayerColor : defaultColor;
@@ -271851,50 +272000,50 @@ function getPointsShader(layerCoordination) {
271851
272000
  }) : [];
271852
272001
  if (obsColorEncoding === "spatialLayerColor") {
271853
272002
  if (!hasFeatureSelection || !hasResolvedIndices) {
271854
- return getSpatialLayerColorShader(staticColor, opacity2);
272003
+ return getSpatialLayerColorShader(staticColor, opacity2, pointMarkerBorderWidth);
271855
272004
  }
271856
272005
  if (isFiltered) {
271857
- return getSpatialLayerColorFilteredShader(staticColor, opacity2, featureIndices, featureIndexProp);
272006
+ return getSpatialLayerColorFilteredShader(staticColor, opacity2, featureIndices, featureIndexProp, pointMarkerBorderWidth);
271858
272007
  }
271859
- return getSpatialLayerColorWithSelectionShader(staticColor, opacity2, featureIndices, defaultColor, featureIndexProp);
272008
+ return getSpatialLayerColorWithSelectionShader(staticColor, opacity2, featureIndices, defaultColor, featureIndexProp, pointMarkerBorderWidth);
271860
272009
  }
271861
272010
  if (obsColorEncoding === "geneSelection") {
271862
272011
  if (!featureIndexProp) {
271863
272012
  throw new Error("In order to use gene-based color encoding for Neuroglancer Points, options.featureIndexProp must be specified for the obsPoints.ng-annotations fileType in the Vitessce configuration.");
271864
272013
  }
271865
272014
  if (!hasFeatureSelection || !hasResolvedIndices) {
271866
- return getGeneSelectionNoSelectionShader(staticColor, opacity2);
272015
+ return getGeneSelectionNoSelectionShader(staticColor, opacity2, pointMarkerBorderWidth);
271867
272016
  }
271868
272017
  if (isFiltered) {
271869
- return getGeneSelectionFilteredShader(featureIndices, resolvedFeatureColors, staticColor, opacity2, featureIndexProp);
272018
+ return getGeneSelectionFilteredShader(featureIndices, resolvedFeatureColors, staticColor, opacity2, featureIndexProp, pointMarkerBorderWidth);
271870
272019
  }
271871
- return getGeneSelectionWithSelectionShader(featureIndices, resolvedFeatureColors, staticColor, defaultColor, opacity2, featureIndexProp);
272020
+ return getGeneSelectionWithSelectionShader(featureIndices, resolvedFeatureColors, staticColor, defaultColor, opacity2, featureIndexProp, pointMarkerBorderWidth);
271872
272021
  }
271873
272022
  if (obsColorEncoding === "randomByFeature") {
271874
272023
  if (!featureIndexProp) {
271875
272024
  throw new Error("In order to use gene-based color encoding for Neuroglancer Points, options.featureIndexProp must be specified for the obsPoints.ng-annotations fileType in the Vitessce configuration.");
271876
272025
  }
271877
272026
  if (!hasFeatureSelection || !hasResolvedIndices) {
271878
- return getRandomByFeatureShader(opacity2, featureIndexProp);
272027
+ return getRandomByFeatureShader(opacity2, featureIndexProp, pointMarkerBorderWidth);
271879
272028
  }
271880
272029
  if (isFiltered) {
271881
- return getRandomByFeatureFilteredShader(featureIndices, opacity2, featureIndexProp);
272030
+ return getRandomByFeatureFilteredShader(featureIndices, opacity2, featureIndexProp, pointMarkerBorderWidth);
271882
272031
  }
271883
- return getRandomByFeatureWithSelectionShader(featureIndices, defaultColor, opacity2, featureIndexProp);
272032
+ return getRandomByFeatureWithSelectionShader(featureIndices, defaultColor, opacity2, featureIndexProp, pointMarkerBorderWidth);
271884
272033
  }
271885
272034
  if (obsColorEncoding === "random") {
271886
272035
  if (!pointIndexProp) {
271887
272036
  throw new Error("In order to use per-point color encoding for Neuroglancer Points, options.pointIndexProp must be specified for the obsPoints.ng-annotations fileType in the Vitessce configuration.");
271888
272037
  }
271889
272038
  if (!hasFeatureSelection || !hasResolvedIndices) {
271890
- return getRandomPerPointShader(opacity2, featureIndexProp, pointIndexProp);
272039
+ return getRandomPerPointShader(opacity2, featureIndexProp, pointIndexProp, pointMarkerBorderWidth);
271891
272040
  }
271892
272041
  if (isFiltered) {
271893
- return getRandomPerPointFilteredShader(featureIndices, opacity2, featureIndexProp, pointIndexProp);
272042
+ return getRandomPerPointFilteredShader(featureIndices, opacity2, featureIndexProp, pointIndexProp, pointMarkerBorderWidth);
271894
272043
  }
271895
- return getRandomPerPointWithSelectionShader(featureIndices, defaultColor, opacity2, featureIndexProp, pointIndexProp);
272044
+ return getRandomPerPointWithSelectionShader(featureIndices, defaultColor, opacity2, featureIndexProp, pointIndexProp, pointMarkerBorderWidth);
271896
272045
  }
271897
- return getSpatialLayerColorShader(staticColor, opacity2);
272046
+ return getSpatialLayerColorShader(staticColor, opacity2, pointMarkerBorderWidth);
271898
272047
  }
271899
272048
  const DEFAULT_NG_PROPS = {
271900
272049
  layout: "3d",
@@ -271924,7 +272073,7 @@ function toNgLayerName(dataType, layerScope, channelScope = null) {
271924
272073
  }
271925
272074
  throw new Error(`Unsupported data type: ${dataType}`);
271926
272075
  }
271927
- function useNeuroglancerViewerState(theme, segmentationLayerScopes, segmentationChannelScopesByLayer, segmentationLayerCoordination, segmentationChannelCoordination, obsSegmentationsUrls, obsSegmentationsData, pointLayerScopes, pointLayerCoordination, obsPointsUrls, obsPointsData, pointMultiIndicesData) {
272076
+ function useNeuroglancerViewerState(theme, showAxisLines, segmentationLayerScopes, segmentationChannelScopesByLayer, segmentationLayerCoordination, segmentationChannelCoordination, obsSegmentationsUrls, obsSegmentationsData, pointLayerScopes, pointLayerCoordination, obsPointsUrls, obsPointsData, pointMultiIndicesData) {
271928
272077
  const viewerState = useMemoCustomComparison(() => {
271929
272078
  let result = cloneDeep$1(DEFAULT_NG_PROPS);
271930
272079
  segmentationLayerScopes.forEach((layerScope) => {
@@ -271937,13 +272086,20 @@ function useNeuroglancerViewerState(theme, segmentationLayerScopes, segmentation
271937
272086
  channelScopes.forEach((channelScope) => {
271938
272087
  const channelCoordination = segmentationChannelCoordination[0]?.[layerScope]?.[channelScope];
271939
272088
  const { spatialChannelVisible } = channelCoordination || {};
272089
+ const { source: ngSource, ...otherNgOptions } = layerData.neuroglancerOptions ?? {};
272090
+ const hasNgSourceOptions = layerData.neuroglancerOptions?.subsources || layerData.neuroglancerOptions?.enableDefaultSubsources !== void 0;
272091
+ const source2 = hasNgSourceOptions ? {
272092
+ url: toPrecomputedSource(layerUrl),
272093
+ subsources: layerData.neuroglancerOptions.subsources,
272094
+ enableDefaultSubsources: layerData.neuroglancerOptions.enableDefaultSubsources ?? false
272095
+ } : toPrecomputedSource(layerUrl);
271940
272096
  result = {
271941
272097
  ...result,
271942
272098
  layers: [
271943
272099
  ...result.layers,
271944
272100
  {
271945
272101
  type: "segmentation",
271946
- source: toPrecomputedSource(layerUrl),
272102
+ source: source2,
271947
272103
  segments: [],
271948
272104
  name: toNgLayerName(DataType$3.OBS_SEGMENTATIONS, layerScope, channelScope),
271949
272105
  visible: spatialLayerVisible && spatialChannelVisible,
@@ -271951,7 +272107,7 @@ function useNeuroglancerViewerState(theme, segmentationLayerScopes, segmentation
271951
272107
  // visibility must be true for the layer to be visible.
271952
272108
  // TODO: update this to extract specific properties from
271953
272109
  // neuroglancerOptions as needed.
271954
- ...layerData.neuroglancerOptions ?? {}
272110
+ ...otherNgOptions
271955
272111
  }
271956
272112
  ]
271957
272113
  };
@@ -271964,7 +272120,7 @@ function useNeuroglancerViewerState(theme, segmentationLayerScopes, segmentation
271964
272120
  const layerUrl = obsPointsUrls[layerScope]?.[0]?.url;
271965
272121
  const featureIndex = pointMultiIndicesData[layerScope]?.featureIndex;
271966
272122
  if (layerUrl && layerData) {
271967
- const { spatialLayerVisible, spatialLayerOpacity, obsColorEncoding, spatialLayerColor, featureSelection, featureFilterMode, featureColor } = layerCoordination || {};
272123
+ const { spatialLayerVisible, spatialLayerOpacity, obsColorEncoding, spatialLayerColor, featureSelection, featureFilterMode, featureColor, spatialPointStrokeWidth } = layerCoordination || {};
271968
272124
  const shader = getPointsShader({
271969
272125
  theme,
271970
272126
  featureIndex,
@@ -271975,7 +272131,8 @@ function useNeuroglancerViewerState(theme, segmentationLayerScopes, segmentation
271975
272131
  featureFilterMode,
271976
272132
  featureColor,
271977
272133
  featureIndexProp: layerData.neuroglancerOptions?.featureIndexProp,
271978
- pointIndexProp: layerData.neuroglancerOptions?.pointIndexProp
272134
+ pointIndexProp: layerData.neuroglancerOptions?.pointIndexProp,
272135
+ pointMarkerBorderWidth: spatialPointStrokeWidth ?? 0
271979
272136
  });
271980
272137
  result = {
271981
272138
  ...result,
@@ -272012,6 +272169,7 @@ function useNeuroglancerViewerState(theme, segmentationLayerScopes, segmentation
272012
272169
  return result;
272013
272170
  }, {
272014
272171
  theme,
272172
+ showAxisLines,
272015
272173
  segmentationLayerScopes,
272016
272174
  segmentationChannelScopesByLayer,
272017
272175
  segmentationLayerCoordination,
@@ -301707,6 +301865,7 @@ function NeuroglancerSubscriber(props) {
301707
301865
  downloadButtonVisible,
301708
301866
  removeGridComponent,
301709
301867
  theme,
301868
+ showAxisLines = false,
301710
301869
  title: title2 = "Spatial",
301711
301870
  subtitle = "Powered by Neuroglancer",
301712
301871
  helpText = ViewHelpMapping.NEUROGLANCER,
@@ -301795,7 +301954,8 @@ function NeuroglancerSubscriber(props) {
301795
301954
  CoordinationType$1.OBS_HIGHLIGHT,
301796
301955
  CoordinationType$1.TOOLTIPS_VISIBLE,
301797
301956
  CoordinationType$1.TOOLTIP_CROSSHAIRS_VISIBLE,
301798
- CoordinationType$1.LEGEND_VISIBLE
301957
+ CoordinationType$1.LEGEND_VISIBLE,
301958
+ CoordinationType$1.SPATIAL_POINT_STROKE_WIDTH
301799
301959
  ], coordinationScopes, coordinationScopesBy, CoordinationType$1.POINT_LAYER);
301800
301960
  const [obsPointsData, obsPointsDataStatus, obsPointsUrls, obsPointsErrors] = useMultiObsPoints(coordinationScopes, coordinationScopesBy, loaders, dataset, mergeCoordination, uuid2);
301801
301961
  const [pointMultiIndicesData, pointMultiIndicesDataStatus, pointMultiIndicesDataErrors] = usePointMultiObsFeatureMatrixIndices(coordinationScopes, coordinationScopesBy, loaders, dataset);
@@ -301828,7 +301988,7 @@ function NeuroglancerSubscriber(props) {
301828
301988
  result[layerScope] = {};
301829
301989
  segmentationChannelScopesByLayer?.[layerScope]?.forEach((channelScope) => {
301830
301990
  const { obsSets: layerSets, obsIndex: layerIndex } = obsSegmentationsSetsData?.[layerScope]?.[channelScope] || {};
301831
- const { obsSetColor, obsColorEncoding, obsSetSelection, additionalObsSets, spatialChannelColor } = segmentationChannelCoordination[0][layerScope][channelScope];
301991
+ const { obsSetColor, obsColorEncoding, obsSetSelection, additionalObsSets, spatialChannelColor, spatialChannelOpacity } = segmentationChannelCoordination[0][layerScope][channelScope];
301832
301992
  if (obsColorEncoding === "spatialChannelColor") {
301833
301993
  if (layerIndex && spatialChannelColor) {
301834
301994
  const hex2 = rgbToHex$1(spatialChannelColor);
@@ -301848,6 +302008,7 @@ function NeuroglancerSubscriber(props) {
301848
302008
  });
301849
302009
  }
301850
302010
  result[layerScope][channelScope] = ngCellColors;
302011
+ result[layerScope].opacity = spatialChannelOpacity ?? 1;
301851
302012
  }
301852
302013
  } else if (layerSets && layerIndex) {
301853
302014
  const mergedCellSets = mergeObsSets(layerSets, additionalObsSets);
@@ -301863,6 +302024,7 @@ function NeuroglancerSubscriber(props) {
301863
302024
  ngCellColors[i2] = rgbToHex$1(color2);
301864
302025
  });
301865
302026
  result[layerScope][channelScope] = ngCellColors;
302027
+ result[layerScope].opacity = spatialChannelOpacity ?? 1;
301866
302028
  }
301867
302029
  });
301868
302030
  });
@@ -301876,7 +302038,7 @@ function NeuroglancerSubscriber(props) {
301876
302038
  segmentationChannelCoordination,
301877
302039
  theme
301878
302040
  }, customIsEqualForCellColors);
301879
- const initalViewerState = useNeuroglancerViewerState(theme, segmentationLayerScopes, segmentationChannelScopesByLayer, segmentationLayerCoordination, segmentationChannelCoordination, obsSegmentationsUrls, obsSegmentationsData, pointLayerScopes, pointLayerCoordination, obsPointsUrls, obsPointsData, pointMultiIndicesData);
302041
+ const initalViewerState = useNeuroglancerViewerState(theme, showAxisLines, segmentationLayerScopes, segmentationChannelScopesByLayer, segmentationLayerCoordination, segmentationChannelCoordination, obsSegmentationsUrls, obsSegmentationsData, pointLayerScopes, pointLayerCoordination, obsPointsUrls, obsPointsData, pointMultiIndicesData);
301880
302042
  const [latestViewerStateIteration, incrementLatestViewerStateIteration] = useReducer((x2) => x2 + 1, 0);
301881
302043
  const latestViewerStateRef = useRef({
301882
302044
  ...initalViewerState,
@@ -301910,6 +302072,7 @@ function NeuroglancerSubscriber(props) {
301910
302072
  z: spatialRotationZ,
301911
302073
  orbit: spatialRotationOrbit
301912
302074
  });
302075
+ const [isLayersLoaded, setIsLayersLoaded] = useState(false);
301913
302076
  const prevCoordsRef = useRef({
301914
302077
  zoom: spatialZoom,
301915
302078
  rx: spatialRotationX,
@@ -302014,7 +302177,10 @@ function NeuroglancerSubscriber(props) {
302014
302177
  const result = {};
302015
302178
  segmentationLayerScopes?.forEach((layerScope) => {
302016
302179
  const channelScope = segmentationChannelScopesByLayer?.[layerScope]?.[0];
302017
- result[layerScope] = segmentationColorMapping?.[layerScope]?.[channelScope] ?? {};
302180
+ result[layerScope] = {
302181
+ colors: segmentationColorMapping?.[layerScope]?.[channelScope] ?? {},
302182
+ opacity: segmentationColorMapping?.[layerScope]?.opacity ?? 1
302183
+ };
302018
302184
  });
302019
302185
  return result;
302020
302186
  }, [segmentationColorMapping, segmentationLayerScopes, segmentationChannelScopesByLayer]);
@@ -302077,12 +302243,13 @@ function NeuroglancerSubscriber(props) {
302077
302243
  }
302078
302244
  const updatedLayers = current2?.layers?.map((layer, idx) => {
302079
302245
  const layerScope = segmentationLayerScopes?.[idx];
302080
- const layerColorMapping = cellColorMappingByLayer?.[layerScope] ?? {};
302246
+ const layerColorMapping = cellColorMappingByLayer?.[layerScope]?.colors ?? {};
302081
302247
  const layerSegments = Object.keys(layerColorMapping);
302082
302248
  return {
302083
302249
  ...layer,
302084
302250
  segments: layerSegments,
302085
- segmentColors: layerColorMapping
302251
+ segmentColors: layerColorMapping,
302252
+ objectAlpha: cellColorMappingByLayer?.[layerScope]?.opacity ?? 1
302086
302253
  };
302087
302254
  }) ?? [];
302088
302255
  const updated = {
@@ -302117,8 +302284,23 @@ function NeuroglancerSubscriber(props) {
302117
302284
  const onSegmentHighlight = useCallback((obsId) => {
302118
302285
  setCellHighlight(String(obsId));
302119
302286
  }, [setCellHighlight]);
302287
+ const handleLayerLoadingChange = useCallback((isLoaded) => {
302288
+ setIsLayersLoaded(isLoaded);
302289
+ }, []);
302120
302290
  const hasLayers = derivedViewerState?.layers?.length > 0;
302121
- return jsxRuntimeExports.jsx(TitleInfo, { title: title2, info: subtitle, helpText, isSpatial: true, theme, closeButtonVisible, downloadButtonVisible, removeGridComponent, isReady, errors, withPadding: false, guideUrl: GUIDE_URL, children: hasLayers ? jsxRuntimeExports.jsxs("div", { style: { position: "relative", width: "100%", height: "100%" }, ref: containerRef, children: [jsxRuntimeExports.jsx("div", { style: { position: "absolute", top: 0, right: 0, zIndex: 50 }, children: jsxRuntimeExports.jsx(MultiLegend, { theme: "dark", maxHeight: ngHeight, segmentationLayerScopes, segmentationLayerCoordination, segmentationChannelScopesByLayer, segmentationChannelCoordination }) }), jsxRuntimeExports.jsx(NeuroglancerComp, { classes: classes2, onSegmentClick, onSelectHoveredCoords: onSegmentHighlight, viewerState: derivedViewerState, cellColorMapping: cellColorMappingByLayer, setViewerState: handleStateUpdate })] }) : null });
302291
+ return jsxRuntimeExports.jsx(TitleInfo, { title: title2, info: subtitle, helpText, isSpatial: true, theme, closeButtonVisible, downloadButtonVisible, removeGridComponent, isReady: isReady && isLayersLoaded, errors, withPadding: false, guideUrl: GUIDE_URL, children: hasLayers ? jsxRuntimeExports.jsxs("div", { style: { position: "relative", width: "100%", height: "100%" }, ref: containerRef, children: [jsxRuntimeExports.jsx("div", { style: { position: "absolute", top: 0, right: 0, zIndex: 50 }, children: jsxRuntimeExports.jsx(MultiLegend, {
302292
+ theme: "dark",
302293
+ maxHeight: ngHeight,
302294
+ // Segmentations
302295
+ segmentationLayerScopes,
302296
+ segmentationLayerCoordination,
302297
+ segmentationChannelScopesByLayer,
302298
+ segmentationChannelCoordination,
302299
+ // Points
302300
+ pointLayerScopes,
302301
+ pointLayerCoordination,
302302
+ pointMultiIndicesData
302303
+ }) }), jsxRuntimeExports.jsx(NeuroglancerComp, { classes: classes2, onSegmentClick, onSelectHoveredCoords: onSegmentHighlight, viewerState: derivedViewerState, cellColorMapping: cellColorMappingByLayer, setViewerState: handleStateUpdate, onLayerLoadingChange: handleLayerLoadingChange })] }) : null });
302122
302304
  }
302123
302305
  const FEATURE_AGGREGATION_STRATEGIES = ["first", "last", "sum", "mean"];
302124
302306
  function CellSetExpressionPlotOptions(props) {
@@ -304077,10 +304259,9 @@ function CellSetExpressionPlot(props) {
304077
304259
  if (!obsSetSelection) {
304078
304260
  return 0;
304079
304261
  }
304080
- const cellSetNames = obsSetSelection.map((d) => d.at(-1));
304081
- return cellSetNames.reduce((acc, name2) => {
304082
- acc = acc === void 0 || name2.length > acc ? name2.length : acc;
304083
- return acc;
304262
+ return obsSetSelection.reduce((acc, path2) => {
304263
+ const nameLength = path2?.at(-1)?.length ?? 0;
304264
+ return nameLength > acc ? nameLength : acc;
304084
304265
  }, 0);
304085
304266
  }, [obsSetSelection]);
304086
304267
  const isStratified = Array.isArray(sampleSetSelection) && sampleSetSelection.length === 2;
@@ -304159,7 +304340,7 @@ function CellSetExpressionPlot(props) {
304159
304340
  }
304160
304341
  g2.append("g").attr("transform", `translate(${marginLeft},0)`).call(axisLeft(y2)).selectAll("text").style("font-size", "11px");
304161
304342
  const xTickG = g2.append("g").attr("transform", `translate(0,${innerHeight})`).style("font-size", "14px");
304162
- xTickG.call(axisBottom(xGroup).tickFormat((d) => d.at(-1))).selectAll("text").style("font-size", "11px").attr("dx", "-6px").attr("dy", "6px").attr("transform", "rotate(-45)").style("text-anchor", "end");
304343
+ xTickG.call(axisBottom(xGroup).tickFormat((d) => d?.at(-1) ?? "")).selectAll("text").style("font-size", "11px").attr("dx", "-6px").attr("dy", "6px").attr("transform", "rotate(-45)").style("text-anchor", "end");
304163
304344
  if (isStratified) {
304164
304345
  const tickWidth = xGroup.bandwidth();
304165
304346
  xTickG.selectAll(".tick").append("rect").attr("x", -tickWidth / 2).attr("width", tickWidth).attr("height", 4).style("fill", (d) => obsSetColorScale(d));
@@ -354943,7 +355124,7 @@ const VEGA_THEMES = {
354943
355124
  };
354944
355125
  const DATASET_NAME = "table";
354945
355126
  function VegaGlobalStyles() {
354946
- const { theme } = useStyles$w();
355127
+ const { theme } = useStyles$x();
354947
355128
  return jsxRuntimeExports.jsx(GlobalStyles$3, { styles: {
354948
355129
  "#vg-tooltip-element.vg-tooltip.custom-theme": {
354949
355130
  boxShadow: "0px 2px 4px -1px rgba(0,0,0,0.2),0px 4px 5px 0px rgba(0,0,0,0.14),0px 1px 10px 0px rgba(0,0,0,0.12)",
@@ -354977,7 +355158,7 @@ function renderTooltipContents(tooltipText) {
354977
355158
  }
354978
355159
  function VegaPlot(props) {
354979
355160
  const { spec: partialSpec, data: data2, getTooltipText, signalListeners, renderer = "svg", onNewView } = props;
354980
- const { classes: tooltipClasses2 } = useStyles$r();
355161
+ const { classes: tooltipClasses2 } = useStyles$s();
354981
355162
  const tooltipHandler = useMemo$1(() => {
354982
355163
  if (typeof getTooltipText === "function") {
354983
355164
  const tooltipConfig = {
@@ -356989,7 +357170,8 @@ class SpatialDataAutoConfig extends AbstractAutoConfig {
356989
357170
  });
356990
357171
  availableElements.forEach(({ path: path2, attrs }) => {
356991
357172
  const relPath = path2.substring(1);
356992
- const firstCoordinateSystem = attrs?.multiscales?.[0]?.coordinateTransformations?.[0]?.output?.name;
357173
+ const omeAttrs = flattenOmeAttrs(attrs);
357174
+ const firstCoordinateSystem = omeAttrs?.multiscales?.[0]?.coordinateTransformations?.[0]?.output?.name;
356993
357175
  if (relPath.match(/^(images)\/([^/]*)$/)) {
356994
357176
  options.image = {
356995
357177
  path: relPath,
@@ -359916,10 +360098,10 @@ class OmeZarrLoader extends AbstractTwoStepLoader {
359916
360098
  const loader2 = await loadOmeZarr(this.storeRoot);
359917
360099
  const imageWrapper = new ImageWrapper(loader2, this.options);
359918
360100
  const { metadata: metadata2, data: data2 } = loader2;
359919
- const { omero, multiscales, channels_metadata: spatialDataChannels, "image-label": imageLabel } = metadata2;
359920
- const isSpatialData = !!spatialDataChannels || !!imageLabel;
359921
- const isLabels = !!imageLabel;
359922
- if (!isSpatialData && !omero) {
360101
+ const { omero, multiscales, channels_metadata: spatialDataChannels, "image-label": imageLabel, spatialdata_attrs: spatialDataAttrs } = metadata2;
360102
+ const isSpatialDataElement = !!spatialDataChannels || !!imageLabel || !!spatialDataAttrs;
360103
+ const isLabels = !!imageLabel || isSpatialDataElement && !omero && !spatialDataChannels;
360104
+ if (!isSpatialDataElement && !omero) {
359923
360105
  throw new Error("image.ome-zarr must have omero metadata in attributes.");
359924
360106
  }
359925
360107
  if (!Array.isArray(multiscales) || multiscales.length === 0) {
@@ -359948,23 +360130,21 @@ class OmeZarrLoader extends AbstractTwoStepLoader {
359948
360130
  let channelLabels = [];
359949
360131
  let initialTargetT = 0;
359950
360132
  let initialTargetZ = 0;
359951
- if (isSpatialData) {
359952
- if (isLabels) {
359953
- channelObjects = [{
359954
- selection: filterSelection2({ z: initialTargetZ, t: initialTargetT, c: 0 }),
359955
- slider: [0, 255],
359956
- color: [255, 255, 255]
359957
- }];
359958
- channelLabels = ["labels"];
359959
- } else {
359960
- const { channels: channels2 } = spatialDataChannels;
359961
- channelObjects = channels2.map((channel, i2) => ({
359962
- selection: filterSelection2({ z: initialTargetZ, t: initialTargetT, c: i2 }),
359963
- slider: [0, 255],
359964
- color: [255, 255, 255]
359965
- }));
359966
- channelLabels = channels2.map((c2) => c2.label);
359967
- }
360133
+ if (isLabels) {
360134
+ channelObjects = [{
360135
+ selection: filterSelection2({ z: initialTargetZ, t: initialTargetT, c: 0 }),
360136
+ slider: [0, 255],
360137
+ color: [255, 255, 255]
360138
+ }];
360139
+ channelLabels = ["labels"];
360140
+ } else if (spatialDataChannels) {
360141
+ const { channels: channels2 } = spatialDataChannels;
360142
+ channelObjects = channels2.map((channel, i2) => ({
360143
+ selection: filterSelection2({ z: initialTargetZ, t: initialTargetT, c: i2 }),
360144
+ slider: [0, 255],
360145
+ color: [255, 255, 255]
360146
+ }));
360147
+ channelLabels = channels2.map((c2) => c2.label);
359968
360148
  } else {
359969
360149
  const { rdefs = {}, channels: channels2 } = omero;
359970
360150
  if (typeof rdefs.defaultT === "number") {
@@ -382773,6 +382953,7 @@ const baseCoordinationTypes = [
382773
382953
  new PluginCoordinationType(CoordinationType$1.SPATIAL_CHANNEL_COLOR, [255, 255, 255], z.array(z.number()).length(3).nullable()),
382774
382954
  new PluginCoordinationType(CoordinationType$1.SPATIAL_SEGMENTATION_FILLED, true, z.boolean()),
382775
382955
  new PluginCoordinationType(CoordinationType$1.SPATIAL_SEGMENTATION_STROKE_WIDTH, 1, z.number()),
382956
+ new PluginCoordinationType(CoordinationType$1.SPATIAL_POINT_STROKE_WIDTH, 0, z.number()),
382776
382957
  new PluginCoordinationType(CoordinationType$1.SPATIAL_LOD_FACTOR, 1, z.number()),
382777
382958
  // Reference: https://www.awaresystems.be/imaging/tiff/tifftags/photometricinterpretation.html
382778
382959
  new PluginCoordinationType(CoordinationType$1.PHOTOMETRIC_INTERPRETATION, null, z.enum(["BlackIsZero", "RGB"]).nullable()),