@vitessce/launcher 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.
@@ -11241,6 +11241,7 @@ const CoordinationType$1 = {
11241
11241
  SPATIAL_LAYER_MODEL_MATRIX: "spatialLayerModelMatrix",
11242
11242
  SPATIAL_SEGMENTATION_FILLED: "spatialSegmentationFilled",
11243
11243
  SPATIAL_SEGMENTATION_STROKE_WIDTH: "spatialSegmentationStrokeWidth",
11244
+ SPATIAL_POINT_STROKE_WIDTH: "spatialPointStrokeWidth",
11244
11245
  SPATIAL_CHANNEL_COLOR: "spatialChannelColor",
11245
11246
  SPATIAL_CHANNEL_VISIBLE: "spatialChannelVisible",
11246
11247
  SPATIAL_CHANNEL_OPACITY: "spatialChannelOpacity",
@@ -11636,7 +11637,8 @@ const COMPONENT_COORDINATION_TYPES = {
11636
11637
  CoordinationType$1.SPATIAL_CHANNEL_COLOR,
11637
11638
  CoordinationType$1.SPATIAL_CHANNEL_OPACITY,
11638
11639
  CoordinationType$1.SPATIAL_CHANNEL_VISIBLE,
11639
- CoordinationType$1.LEGEND_VISIBLE
11640
+ CoordinationType$1.LEGEND_VISIBLE,
11641
+ CoordinationType$1.SPATIAL_POINT_STROKE_WIDTH
11640
11642
  ],
11641
11643
  [ViewType$1.SCATTERPLOT]: [
11642
11644
  CoordinationType$1.DATASET,
@@ -12020,6 +12022,7 @@ const COMPONENT_COORDINATION_TYPES = {
12020
12022
  CoordinationType$1.SPATIAL_CHANNEL_COLOR,
12021
12023
  CoordinationType$1.SPATIAL_SEGMENTATION_FILLED,
12022
12024
  CoordinationType$1.SPATIAL_SEGMENTATION_STROKE_WIDTH,
12025
+ CoordinationType$1.SPATIAL_POINT_STROKE_WIDTH,
12023
12026
  CoordinationType$1.IMAGE_CHANNEL,
12024
12027
  CoordinationType$1.IMAGE_LAYER,
12025
12028
  CoordinationType$1.SEGMENTATION_CHANNEL,
@@ -12758,6 +12761,8 @@ const ngPrecomputedMeshSchema = z.object({
12758
12761
  // projectionScale: z.number(),
12759
12762
  // position: z.array(z.number()).length(3),
12760
12763
  // projectionOrientation: z.array(z.number()).length(4),
12764
+ 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(),
12765
+ 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()
12761
12766
  }).partial().nullable();
12762
12767
  const ngPointAnnotationSchema = z.object({
12763
12768
  projectionAnnotationSpacing: z.number(),
@@ -20175,7 +20180,7 @@ const { tss } = createTss({
20175
20180
  },
20176
20181
  "usePlugin": useMuiThemeStyleOverridesPlugin
20177
20182
  });
20178
- const useStyles$x = tss.create({});
20183
+ const useStyles$y = tss.create({});
20179
20184
  function createChainedFunction$1(...funcs) {
20180
20185
  return funcs.reduce((acc, func) => {
20181
20186
  if (func == null) {
@@ -24304,7 +24309,7 @@ const ErrorOutlineIcon = createSvgIcon(/* @__PURE__ */ jsxRuntimeExports.jsx("pa
24304
24309
  const InfoOutlinedIcon = createSvgIcon(/* @__PURE__ */ jsxRuntimeExports.jsx("path", {
24305
24310
  d: "M11,9H13V7H11M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20, 12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10, 10 0 0,0 12,2M11,17H13V11H11V17Z"
24306
24311
  }), "InfoOutlined");
24307
- const ClearIcon = createSvgIcon(/* @__PURE__ */ jsxRuntimeExports.jsx("path", {
24312
+ const ClearIcon$1 = createSvgIcon(/* @__PURE__ */ jsxRuntimeExports.jsx("path", {
24308
24313
  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"
24309
24314
  }), "Close");
24310
24315
  const useUtilityClasses$1y = (ownerState) => {
@@ -24510,7 +24515,7 @@ const Alert = /* @__PURE__ */ React.forwardRef(function Alert2(inProps, ref2) {
24510
24515
  ownerState
24511
24516
  });
24512
24517
  const [CloseIconSlot, closeIconProps] = useSlot("closeIcon", {
24513
- elementType: ClearIcon,
24518
+ elementType: ClearIcon$1,
24514
24519
  externalForwardedProps,
24515
24520
  ownerState
24516
24521
  });
@@ -29673,7 +29678,7 @@ const Autocomplete = /* @__PURE__ */ React.forwardRef(function Autocomplete2(inP
29673
29678
  blurOnSelect = false,
29674
29679
  ChipProps: ChipPropsProp,
29675
29680
  className,
29676
- clearIcon = _ClearIcon || (_ClearIcon = /* @__PURE__ */ jsxRuntimeExports.jsx(ClearIcon, {
29681
+ clearIcon = _ClearIcon || (_ClearIcon = /* @__PURE__ */ jsxRuntimeExports.jsx(ClearIcon$1, {
29677
29682
  fontSize: "small"
29678
29683
  })),
29679
29684
  clearOnBlur = !props.freeSolo,
@@ -48134,6 +48139,9 @@ const VisibilityIcon = createSvgIcon(/* @__PURE__ */ jsxRuntimeExports.jsx("path
48134
48139
  const VisibilityOffIcon = createSvgIcon(/* @__PURE__ */ jsxRuntimeExports.jsx("path", {
48135
48140
  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"
48136
48141
  }), "VisibilityOff");
48142
+ const ClearIcon = createSvgIcon(/* @__PURE__ */ jsxRuntimeExports.jsx("path", {
48143
+ 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"
48144
+ }), "Clear");
48137
48145
  const reactMajor = parseInt(React.version, 10);
48138
48146
  const forwardRef = (render2) => {
48139
48147
  if (reactMajor >= 19) {
@@ -74991,7 +74999,7 @@ const Popper = React.forwardRef((props, ref2) => {
74991
74999
  }, [handlePopperRef]);
74992
75000
  React.useImperativeHandle(popperRefProp, () => popperRef.current, []);
74993
75001
  const [exited, setExited] = React.useState(true);
74994
- const { theme } = useStyles$x();
75002
+ const { theme } = useStyles$y();
74995
75003
  const rtlPlacement = flipPlacement(initialPlacement, theme);
74996
75004
  const [placement, setPlacement] = React.useState(rtlPlacement);
74997
75005
  React.useEffect(() => {
@@ -75725,7 +75733,7 @@ var VariableSizeList$1 = /* @__PURE__ */ createListComponent({
75725
75733
  });
75726
75734
  const VariableSizeList = VariableSizeList$1;
75727
75735
  const LIST_ROW_HEIGHT$1 = 48;
75728
- const useStyles$w = makeStyles()(() => ({
75736
+ const useStyles$x = makeStyles()(() => ({
75729
75737
  searchInput: {
75730
75738
  lineHeight: "initial",
75731
75739
  height: "auto !important"
@@ -75765,7 +75773,7 @@ const ListboxComponent$1 = React__default.forwardRef((props, ref2) => {
75765
75773
  });
75766
75774
  function SimpleAutocomplete(props) {
75767
75775
  const { getMatches, onChange, textInputLabel = "Enter a gene", getItemLabel = (option) => option.label } = props;
75768
- const { classes: classes2 } = useStyles$w();
75776
+ const { classes: classes2 } = useStyles$x();
75769
75777
  const [potentialItems, setPotentialItems] = useState([]);
75770
75778
  const handleInputChange = async (_event, value2) => {
75771
75779
  if (!value2) {
@@ -85315,7 +85323,7 @@ function defaultUrlTransform(value2) {
85315
85323
  }
85316
85324
  return "";
85317
85325
  }
85318
- const useStyles$v = makeStyles()((theme) => ({
85326
+ const useStyles$w = makeStyles()((theme) => ({
85319
85327
  description: {
85320
85328
  "& p, details, table": {
85321
85329
  fontSize: "80%",
@@ -85352,7 +85360,7 @@ const useStyles$v = makeStyles()((theme) => ({
85352
85360
  }));
85353
85361
  function Description(props) {
85354
85362
  const { description: description2, metadata: metadata2, descriptionType } = props;
85355
- const { classes: classes2 } = useStyles$v();
85363
+ const { classes: classes2 } = useStyles$w();
85356
85364
  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)] });
85357
85365
  }
85358
85366
  function DescriptionSubscriber(props) {
@@ -100423,7 +100431,7 @@ const Tooltip$2 = /* @__PURE__ */ React.forwardRef((props, ref2) => {
100423
100431
  }, extraProps), getChildren());
100424
100432
  });
100425
100433
  const nodeHeight = 32;
100426
- const useStyles$u = makeStyles()((theme) => ({
100434
+ const useStyles$v = makeStyles()((theme) => ({
100427
100435
  setsManager: {
100428
100436
  position: "relative",
100429
100437
  width: "100%",
@@ -100590,7 +100598,7 @@ const useStyles$u = makeStyles()((theme) => ({
100590
100598
  }));
100591
100599
  function SetsManagerTreeGlobalStyles(props) {
100592
100600
  const { classes: classes2 } = props;
100593
- const { theme } = useStyles$x();
100601
+ const { theme } = useStyles$y();
100594
100602
  return jsxRuntimeExports.jsx(ScopedGlobalStyles, { parentClassName: classes2.setsManagerTree, styles: {
100595
100603
  ".rc-tree": {
100596
100604
  paddingLeft: "0",
@@ -100931,7 +100939,7 @@ function HelpTooltipGlobalStyles(props) {
100931
100939
  }
100932
100940
  function PopoverGlobalStyles(props) {
100933
100941
  const { classes: classes2 } = props;
100934
- const { theme } = useStyles$x();
100942
+ const { theme } = useStyles$y();
100935
100943
  return jsxRuntimeExports.jsx(ScopedGlobalStyles, { parentClassName: classes2.popover, styles: {
100936
100944
  ".rc-tooltip-inner": {
100937
100945
  boxSizing: "border-box",
@@ -105615,7 +105623,7 @@ function NamedSetNodeStatic(props) {
105615
105623
  const onClick = level === 0 && !expanded ? () => onCheckLevel(nodeKey, nextLevelToCheck) : () => onNodeView(path2);
105616
105624
  const tooltipProps = disableTooltip ? { visible: false } : {};
105617
105625
  const popoverMenuConfig = makeNodeViewMenuConfig(props);
105618
- const { classes: classes2 } = useStyles$u();
105626
+ const { classes: classes2 } = useStyles$v();
105619
105627
  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 })] });
105620
105628
  }
105621
105629
  function NamedSetNodeEditing(props) {
@@ -105627,7 +105635,7 @@ function NamedSetNodeEditing(props) {
105627
105635
  onNodeSetName(path2, currentTitle, true);
105628
105636
  }
105629
105637
  }
105630
- const { classes: classes2 } = useStyles$u();
105638
+ const { classes: classes2 } = useStyles$v();
105631
105639
  return jsxRuntimeExports.jsxs("span", { className: classes2.titleButtonWithInput, children: [jsxRuntimeExports.jsx("input", {
105632
105640
  // eslint-disable-next-line jsx-a11y/no-autofocus
105633
105641
  autoFocus: true,
@@ -105653,7 +105661,7 @@ function LevelsButtons(props) {
105653
105661
  onCheckLevel(nodeKey, newLevel);
105654
105662
  }
105655
105663
  }
105656
- const { classes: classes2 } = useStyles$u();
105664
+ const { classes: classes2 } = useStyles$v();
105657
105665
  return jsxRuntimeExports.jsx("div", { className: classes2.levelButtonsContainer, children: range$e(1, height2 + 1).map((i2) => {
105658
105666
  const isChecked = isEqual$3(path2, checkedLevelPath) && i2 === checkedLevelIndex;
105659
105667
  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);
@@ -105737,7 +105745,7 @@ let TreeNode$1 = class TreeNode extends TreeNode$2 {
105737
105745
  };
105738
105746
  function PlusButton(props) {
105739
105747
  const { datatype, onError, onImportTree, onCreateLevelZeroNode, importable, editable } = props;
105740
- const { classes: classes2 } = useStyles$u();
105748
+ const { classes: classes2 } = useStyles$v();
105741
105749
  const onImport = useCallback((importHandler, mimeType) => () => {
105742
105750
  const uploadInputNode = document.createElement("input");
105743
105751
  uploadInputNode.setAttribute("type", "file");
@@ -105854,7 +105862,7 @@ function SetsManager(props) {
105854
105862
  }, onNodeCheckNewName, onNodeSetIsEditing: setIsEditingNodeName, onNodeRemove, onExportLevelZeroNodeJSON, onExportLevelZeroNodeTabular, onExportSetJSON, disableTooltip: isDragging, onDragStart: () => setIsDragging(true), onDragEnd: () => setIsDragging(false), children: renderTreeNodes(node2.children, readOnly, newPath) }, pathToKey(newPath));
105855
105863
  });
105856
105864
  }
105857
- const { classes: classes2 } = useStyles$u();
105865
+ const { classes: classes2 } = useStyles$v();
105858
105866
  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) => {
105859
105867
  const { eventKey: dropKey } = info2.node.props;
105860
105868
  const { eventKey: dragKey } = info2.dragNode.props;
@@ -211819,22 +211827,22 @@ async function getDecoder(fileDirectory) {
211819
211827
  const Decoder = await importFn();
211820
211828
  return new Decoder(fileDirectory);
211821
211829
  }
211822
- addDecoder([void 0, 1], () => import("./raw-DUp-QtrM.js").then((m2) => m2.default));
211823
- addDecoder(5, () => import("./lzw-D2V8xY3D.js").then((m2) => m2.default));
211830
+ addDecoder([void 0, 1], () => import("./raw-BChW8Bv2.js").then((m2) => m2.default));
211831
+ addDecoder(5, () => import("./lzw-GyLKEjHd.js").then((m2) => m2.default));
211824
211832
  addDecoder(6, () => {
211825
211833
  throw new Error("old style JPEG compression is not supported.");
211826
211834
  });
211827
- addDecoder(7, () => import("./jpeg-9fUrQn3q.js").then((m2) => m2.default));
211828
- addDecoder([8, 32946], () => import("./deflate-Dbe9OGOc.js").then((m2) => m2.default));
211829
- addDecoder(32773, () => import("./packbits-DgS6vwfA.js").then((m2) => m2.default));
211835
+ addDecoder(7, () => import("./jpeg-BztqQwoS.js").then((m2) => m2.default));
211836
+ addDecoder([8, 32946], () => import("./deflate-D0JH4rkz.js").then((m2) => m2.default));
211837
+ addDecoder(32773, () => import("./packbits-DJsZJlYo.js").then((m2) => m2.default));
211830
211838
  addDecoder(
211831
211839
  34887,
211832
- () => import("./lerc-BinCJj-X.js").then(async (m2) => {
211840
+ () => import("./lerc-9qrJ4PEa.js").then(async (m2) => {
211833
211841
  await m2.zstd.init();
211834
211842
  return m2;
211835
211843
  }).then((m2) => m2.default)
211836
211844
  );
211837
- addDecoder(50001, () => import("./webimage-CH0Nfeyo.js").then((m2) => m2.default));
211845
+ addDecoder(50001, () => import("./webimage-BlgQb3bb.js").then((m2) => m2.default));
211838
211846
  function copyNewSize(array2, width2, height2, samplesPerPixel = 1) {
211839
211847
  return new (Object.getPrototypeOf(array2)).constructor(width2 * height2 * samplesPerPixel);
211840
211848
  }
@@ -228603,7 +228611,7 @@ class ContourLayerWithText extends ContourLayer {
228603
228611
  }
228604
228612
  ContourLayerWithText.layerName = "ContourLayerWithText";
228605
228613
  ContourLayerWithText.defaultProps = defaultProps;
228606
- const useStyles$t = makeStyles()(() => ({
228614
+ const useStyles$u = makeStyles()(() => ({
228607
228615
  toolButton: {
228608
228616
  display: "inline-flex",
228609
228617
  "&:active": {
@@ -228665,12 +228673,12 @@ const useStyles$t = makeStyles()(() => ({
228665
228673
  }));
228666
228674
  function IconTool(props) {
228667
228675
  const { alt, onClick, isActive: isActive2, children: children3 } = props;
228668
- const { classes: classes2 } = useStyles$t();
228676
+ const { classes: classes2 } = useStyles$u();
228669
228677
  return jsxRuntimeExports.jsx("button", { className: clsx(classes2.toolIcon, { [classes2.toolActive]: isActive2 }), onClick, type: "button", title: alt, children: children3 });
228670
228678
  }
228671
228679
  function IconButton(props) {
228672
228680
  const { alt, onClick, children: children3 } = props;
228673
- const { classes: classes2 } = useStyles$t();
228681
+ const { classes: classes2 } = useStyles$u();
228674
228682
  return jsxRuntimeExports.jsx("button", { className: clsx(classes2.toolIcon, classes2.toolButton), onClick, type: "button", title: alt, children: children3 });
228675
228683
  }
228676
228684
  function ToolMenu(props) {
@@ -228678,7 +228686,7 @@ function ToolMenu(props) {
228678
228686
  const lassoIconAltText = "Select lasso";
228679
228687
  const { setActiveTool, activeTool, visibleTools = { pan: true, selectLasso: true, recenter: true }, recenterOnClick = () => {
228680
228688
  } } = props;
228681
- const { classes: classes2 } = useStyles$t();
228689
+ const { classes: classes2 } = useStyles$u();
228682
228690
  const onRecenterButtonCLick = () => {
228683
228691
  recenterOnClick();
228684
228692
  };
@@ -229867,7 +229875,7 @@ function ScatterplotOptions(props) {
229867
229875
  id: `feature-aggregation-strategy-${scatterplotOptionsId}`
229868
229876
  }, children: FEATURE_AGGREGATION_STRATEGIES$1.map((opt) => jsxRuntimeExports.jsx("option", { value: opt, children: capitalize$3(opt) }, opt)) }) })] }) : null] });
229869
229877
  }
229870
- const useStyles$s = makeStyles()((theme) => ({
229878
+ const useStyles$t = makeStyles()((theme) => ({
229871
229879
  tooltipAnchor: {
229872
229880
  position: "relative",
229873
229881
  width: "0px",
@@ -229898,7 +229906,7 @@ const useStyles$s = makeStyles()((theme) => ({
229898
229906
  function Tooltip3(props) {
229899
229907
  const { x: x2, y: y2, parentWidth, parentHeight, children: children3 } = props;
229900
229908
  const ref2 = useRef();
229901
- const { classes: classes2 } = useStyles$s();
229909
+ const { classes: classes2 } = useStyles$t();
229902
229910
  const [placementX, setPlacementX] = useState("start");
229903
229911
  const [placementY, setPlacementY] = useState("bottom");
229904
229912
  const getTooltipContainer = useVitessceContainer(ref2);
@@ -229914,7 +229922,7 @@ function Tooltip3(props) {
229914
229922
  }, [x2, y2, parentWidth, parentHeight]);
229915
229923
  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 });
229916
229924
  }
229917
- const useStyles$r = makeStyles()((theme) => ({
229925
+ const useStyles$s = makeStyles()((theme) => ({
229918
229926
  cellEmphasisCrosshair: {
229919
229927
  zIndex: 50,
229920
229928
  position: "absolute",
@@ -229925,7 +229933,7 @@ const useStyles$r = makeStyles()((theme) => ({
229925
229933
  }));
229926
229934
  function Tooltip2D(props) {
229927
229935
  const { parentUuid, sourceUuid, x: x2, y: y2, parentWidth, parentHeight, children: children3 } = props;
229928
- const { classes: classes2 } = useStyles$r();
229936
+ const { classes: classes2 } = useStyles$s();
229929
229937
  if (x2 < 0 || x2 > parentWidth || y2 < 0 || y2 > parentHeight) {
229930
229938
  return null;
229931
229939
  }
@@ -233830,7 +233838,7 @@ function getXlinkHref(cmap) {
233830
233838
  const xlinkHref = ramp(color2.copy().domain(quantize$3(interpolate$1$1(0, 1), n3))).toDataURL();
233831
233839
  return xlinkHref;
233832
233840
  }
233833
- const useStyles$q = makeStyles()(() => ({
233841
+ const useStyles$r = makeStyles()(() => ({
233834
233842
  legend: {
233835
233843
  position: "relative",
233836
233844
  // Needed for absolute positioning of slider overlay
@@ -234027,7 +234035,7 @@ function Legend(props) {
234027
234035
  contourThresholds
234028
234036
  } = props;
234029
234037
  const svgRef = useRef(null);
234030
- const { classes: classes2 } = useStyles$q();
234038
+ const { classes: classes2 } = useStyles$r();
234031
234039
  const [localRange, setLocalRange] = useState(featureValueColormapRange);
234032
234040
  useEffect(() => {
234033
234041
  setLocalRange(featureValueColormapRange);
@@ -234308,7 +234316,9 @@ function Legend(props) {
234308
234316
  isStaticColor,
234309
234317
  missing,
234310
234318
  showObsLabel,
234311
- staticColor
234319
+ staticColor,
234320
+ featureColor,
234321
+ pointsLegendElements
234312
234322
  ]);
234313
234323
  const showInteractiveSlider = !isPointsLayer && setFeatureValueColormapRange && ["geneSelection", "geneExpression"].includes(obsColorEncoding ?? "") && pointsVisible && featureValueColormap;
234314
234324
  const globalExtent = useMemo$1(() => {
@@ -234359,7 +234369,7 @@ function Legend(props) {
234359
234369
  }
234360
234370
  } })] })] });
234361
234371
  }
234362
- const useStyles$p = makeStyles()(() => ({
234372
+ const useStyles$q = makeStyles()(() => ({
234363
234373
  multiLegend: {
234364
234374
  position: "absolute",
234365
234375
  top: "0px",
@@ -234386,7 +234396,7 @@ function MultiLegend(props) {
234386
234396
  pointLayerCoordination,
234387
234397
  pointMultiIndicesData
234388
234398
  } = props;
234389
- const { classes: classes2 } = useStyles$p();
234399
+ const { classes: classes2 } = useStyles$q();
234390
234400
  const reversedSegmentationLayerScopes = useMemo$1(() => [...segmentationLayerScopes || []].reverse(), [segmentationLayerScopes]);
234391
234401
  const reversedSpotLayerScopes = useMemo$1(() => [...spotLayerScopes || []].reverse(), [spotLayerScopes]);
234392
234402
  const reversedPointLayerScopes = useMemo$1(() => [...pointLayerScopes || []].reverse(), [pointLayerScopes]);
@@ -234479,7 +234489,7 @@ function MultiLegend(props) {
234479
234489
  }) : null;
234480
234490
  }) : null] });
234481
234491
  }
234482
- const useStyles$o = makeStyles()(() => ({
234492
+ const useStyles$p = makeStyles()(() => ({
234483
234493
  channelNamesLegendContainer: {
234484
234494
  position: "absolute",
234485
234495
  bottom: "0px",
@@ -234502,7 +234512,7 @@ const useStyles$o = makeStyles()(() => ({
234502
234512
  }));
234503
234513
  function ChannelNamesLegend(props) {
234504
234514
  const { images, imageLayerScopes, imageLayerCoordination, imageChannelScopesByLayer, imageChannelCoordination } = props;
234505
- const { classes: classes2 } = useStyles$o();
234515
+ const { classes: classes2 } = useStyles$p();
234506
234516
  const reversedImageLayerScopes = useMemo$1(() => [...imageLayerScopes || []].reverse(), [imageLayerScopes]);
234507
234517
  return jsxRuntimeExports.jsx("div", { className: classes2.channelNamesLegendContainer, children: imageLayerScopes ? reversedImageLayerScopes.map((layerScope) => {
234508
234518
  const layerCoordination = imageLayerCoordination[0][layerScope];
@@ -253450,6 +253460,12 @@ function createGetRange(store) {
253450
253460
  throw new Error("Invalid rangeQuery value.");
253451
253461
  };
253452
253462
  }
253463
+ function flattenOmeAttrs(rootAttrs) {
253464
+ if (rootAttrs && typeof rootAttrs.ome === "object" && rootAttrs.ome !== null) {
253465
+ return { ...rootAttrs.ome, ...rootAttrs };
253466
+ }
253467
+ return rootAttrs;
253468
+ }
253453
253469
  class VitessceError extends Error {
253454
253470
  constructor(message) {
253455
253471
  super(message);
@@ -253512,10 +253528,12 @@ async function loadMultiscales(root2) {
253512
253528
  }
253513
253529
  throw e3;
253514
253530
  }
253531
+ rootAttrs = flattenOmeAttrs(rootAttrs);
253515
253532
  let paths = ["0"];
253516
253533
  let labels2 = ["t", "c", "z", "y", "x"];
253517
253534
  if ("multiscales" in rootAttrs) {
253518
- const { datasets, axes } = rootAttrs.multiscales[0];
253535
+ const { multiscales } = rootAttrs;
253536
+ const { datasets, axes } = multiscales[0];
253519
253537
  paths = datasets.map((d) => d.path);
253520
253538
  if (axes) {
253521
253539
  if (isAxis(axes)) {
@@ -256386,12 +256404,12 @@ class ErrorBoundary extends React__default.Component {
256386
256404
  }
256387
256405
  }
256388
256406
  const LazySpatialThree = React__default.lazy(async () => {
256389
- const { SpatialWrapper: SpatialWrapper2 } = await import("./index-DlwYKAh1.js");
256407
+ const { SpatialWrapper: SpatialWrapper2 } = await import("./index-1U4gELip.js");
256390
256408
  return { default: SpatialWrapper2 };
256391
256409
  });
256392
256410
  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 }) }) }) }));
256393
256411
  const LazySpatialAccelerated = React__default.lazy(async () => {
256394
- const { SpatialWrapper: SpatialWrapper2 } = await import("./index-_s9jmws5.js");
256412
+ const { SpatialWrapper: SpatialWrapper2 } = await import("./index-D2vPxKer.js");
256395
256413
  return { default: SpatialWrapper2 };
256396
256414
  });
256397
256415
  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 }) }) }) }));
@@ -264511,7 +264529,7 @@ _defineProperty$3(WindowScroller, "defaultProps", {
264511
264529
  serverHeight: 0,
264512
264530
  serverWidth: 0
264513
264531
  });
264514
- const useStyles$n = makeStyles()((theme) => ({
264532
+ const useStyles$o = makeStyles()((theme) => ({
264515
264533
  selectableTable: {
264516
264534
  flex: "1 1 auto",
264517
264535
  outline: "none"
@@ -264660,7 +264678,7 @@ function SelectableTable(props) {
264660
264678
  onChange(null);
264661
264679
  }
264662
264680
  }, [selectedRows, allowMultiple]);
264663
- const { classes: classes2 } = useStyles$n();
264681
+ const { classes: classes2 } = useStyles$o();
264664
264682
  const inputUuid = v4$1();
264665
264683
  const rowRenderer = ({ index: index2, style: style2 }) => (
264666
264684
  // eslint-disable-next-line jsx-a11y/interactive-supports-focus
@@ -264685,7 +264703,7 @@ const FEATURELIST_SORT_OPTIONS = [
264685
264703
  "original"
264686
264704
  ];
264687
264705
  const ALT_COLNAME = "Alternate ID";
264688
- const useStyles$m = makeStyles()(() => ({
264706
+ const useStyles$n = makeStyles()(() => ({
264689
264707
  searchBar: {
264690
264708
  marginTop: "10px",
264691
264709
  marginLeft: "10px",
@@ -264698,7 +264716,7 @@ const useStyles$m = makeStyles()(() => ({
264698
264716
  }));
264699
264717
  function FeatureList(props) {
264700
264718
  const { width: width2, height: height2, hasColorEncoding, geneList = [], featureLabelsMap, geneSelection = [], geneFilter = null, setGeneSelection, enableMultiSelect, showFeatureTable, featureListSort, featureListSortKey, hasFeatureLabels, primaryColumnName } = props;
264701
- const { classes: classes2 } = useStyles$m();
264719
+ const { classes: classes2 } = useStyles$n();
264702
264720
  const [searchTerm, setSearchTerm] = useState("");
264703
264721
  const selectableTableSortKey = featureListSortKey === "featureIndex" ? "key" : "name";
264704
264722
  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]);
@@ -264773,7 +264791,7 @@ function FeatureListOptions(props) {
264773
264791
  id: `feature-list-show-alternative-ids-${featureListId}`
264774
264792
  } } }) })] })] }) : null] });
264775
264793
  }
264776
- const useStyles$l = makeStyles()((theme) => ({
264794
+ const useStyles$m = makeStyles()((theme) => ({
264777
264795
  featureListContainer: {
264778
264796
  width: "100%",
264779
264797
  height: "100%",
@@ -264788,7 +264806,7 @@ function FeatureListSubscriber(props) {
264788
264806
  const loaders = useLoaders();
264789
264807
  const coordinationScopes = useCoordinationScopes(coordinationScopesRaw);
264790
264808
  const [width2, height2, containerRef] = useGridItemSize();
264791
- const { classes: classes2 } = useStyles$l();
264809
+ const { classes: classes2 } = useStyles$m();
264792
264810
  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);
264793
264811
  const variablesLabel = variablesLabelOverride || featureType;
264794
264812
  const title2 = titleOverride || `${capitalize$3(variablesLabel)} List`;
@@ -264856,6 +264874,12 @@ const useControllerSectionStyles = makeStyles()((theme) => ({
264856
264874
  },
264857
264875
  layerControllerGrid: {
264858
264876
  marginTop: "10px"
264877
+ },
264878
+ layerControllerSubRow: {
264879
+ flexDirection: "column",
264880
+ marginLeft: "40px",
264881
+ padding: "0px 8px",
264882
+ backgroundColor: theme.palette.paperBackground
264859
264883
  }
264860
264884
  }));
264861
264885
  const useAccordionStyles = makeStyles()((theme) => ({
@@ -264917,7 +264941,7 @@ const useSelectionSliderStyles = makeStyles()(() => ({
264917
264941
  backgroundColor: "rgba(128, 128, 128, 0.7)"
264918
264942
  }
264919
264943
  }));
264920
- const useStyles$k = makeStyles()((theme) => ({
264944
+ const useStyles$l = makeStyles()((theme) => ({
264921
264945
  paletteContainer: {
264922
264946
  width: "70px",
264923
264947
  height: "40px",
@@ -264938,10 +264962,10 @@ const useStyles$k = makeStyles()((theme) => ({
264938
264962
  }
264939
264963
  }));
264940
264964
  const ColorPalette = ({ handleChange }) => {
264941
- const { classes: classes2 } = useStyles$k();
264965
+ const { classes: classes2 } = useStyles$l();
264942
264966
  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)) });
264943
264967
  };
264944
- const useStyles$j = makeStyles()(() => ({
264968
+ const useStyles$k = makeStyles()(() => ({
264945
264969
  menuButton: {
264946
264970
  backgroundColor: "transparent"
264947
264971
  },
@@ -264960,7 +264984,7 @@ function MuiSpan(props) {
264960
264984
  }
264961
264985
  function ChannelOptions$1({ handlePropertyChange, handleChannelRemove, handleIQRUpdate }) {
264962
264986
  const [open2, setOpen] = useState(false);
264963
- const { classes: classes2 } = useStyles$j();
264987
+ const { classes: classes2 } = useStyles$k();
264964
264988
  const handleColorSelect = (color2) => {
264965
264989
  handlePropertyChange("color", color2);
264966
264990
  };
@@ -265577,7 +265601,7 @@ function LayerController$1(props) {
265577
265601
  minWidth: "50%"
265578
265602
  } })] }), 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] })] });
265579
265603
  }
265580
- const useStyles$i = makeStyles()(() => ({
265604
+ const useStyles$j = makeStyles()(() => ({
265581
265605
  addButton: {
265582
265606
  marginTop: "10px",
265583
265607
  marginBottom: "10px",
@@ -265589,7 +265613,7 @@ function ImageAddIcon() {
265589
265613
  }
265590
265614
  function ImageAddButton({ imageOptions, handleImageAdd }) {
265591
265615
  const [open2, setOpen] = useState(false);
265592
- const { classes: classes2 } = useStyles$i();
265616
+ const { classes: classes2 } = useStyles$j();
265593
265617
  const handleAdd = (imgData) => {
265594
265618
  setOpen((prev2) => !prev2);
265595
265619
  handleImageAdd(imgData);
@@ -265921,7 +265945,7 @@ const useEllipsisMenuStyles = makeStyles()(() => ({
265921
265945
  padding: "4px"
265922
265946
  }
265923
265947
  }));
265924
- const useStyles$h = makeStyles()(() => ({
265948
+ const useStyles$i = makeStyles()(() => ({
265925
265949
  colorPickerPaper: {
265926
265950
  overflow: "hidden",
265927
265951
  "& > ul": {
@@ -265979,13 +266003,15 @@ function ChannelColorPickerMenu(props) {
265979
266003
  setColor2([rgb2.r, rgb2.g, rgb2.b]);
265980
266004
  }
265981
266005
  }
265982
- const { classes: classes2 } = useStyles$h();
266006
+ const { classes: classes2 } = useStyles$i();
265983
266007
  const currentColor = color2 ? colorArrayToString(color2) : colorArrayToString(getDefaultColor(theme));
265984
- return jsxRuntimeExports.jsx(PopperMenu, { open: isStaticColor && visible ? open2 : false, setOpen, buttonIcon: isStaticColor && visible ? jsxRuntimeExports.jsx("div", { className: clsx(classes2.colorIcon, {
266008
+ const isWritable = typeof setColor2 === "function";
266009
+ const derivedOpen = isWritable ? isStaticColor && visible ? open2 : false : false;
266010
+ return jsxRuntimeExports.jsx(PopperMenu, { open: derivedOpen, setOpen, buttonIcon: isStaticColor && visible ? jsxRuntimeExports.jsx("div", { className: clsx(classes2.colorIcon, {
265985
266011
  [classes2.colorIconOutline]: theme !== "dark" && isEqual$3(color2, [255, 255, 255])
265986
266012
  }), 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 }) });
265987
266013
  }
265988
- const useStyles$g = makeStyles()(() => ({
266014
+ const useStyles$h = makeStyles()(() => ({
265989
266015
  layerTypeSpotIcon: {
265990
266016
  height: "100%",
265991
266017
  marginLeft: "1px",
@@ -265998,7 +266024,7 @@ const useStyles$g = makeStyles()(() => ({
265998
266024
  function SpotLayerEllipsisMenu(props) {
265999
266025
  const { strokeWidth, setStrokeWidth, filled, setFilled, featureSelection, obsColorEncoding, setObsColorEncoding, featureValueColormap, setFeatureValueColormap, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible } = props;
266000
266026
  const [open2, setOpen] = useState(false);
266001
- const { classes: classes2 } = useStyles$g();
266027
+ const { classes: classes2 } = useStyles$h();
266002
266028
  const { classes: selectClasses2 } = useSelectStyles();
266003
266029
  const { classes: menuClasses } = useEllipsisMenuStyles();
266004
266030
  const filledId = $bdb11010cef70236$export$f680877a34711e37();
@@ -266020,7 +266046,7 @@ function SpotLayerController(props) {
266020
266046
  const Visibility = useMemo$1(() => visibleSetting ? VisibilityIcon : VisibilityOffIcon, [visibleSetting]);
266021
266047
  const isStaticColor = obsColorEncoding === "spatialLayerColor";
266022
266048
  const isColormap = obsColorEncoding === "geneSelection";
266023
- const { classes: classes2 } = useStyles$g();
266049
+ const { classes: classes2 } = useStyles$h();
266024
266050
  const { classes: lcClasses } = useControllerSectionStyles();
266025
266051
  const { classes: menuClasses } = useEllipsisMenuStyles();
266026
266052
  const handleVisibleChange = useCallback(() => {
@@ -266030,6 +266056,104 @@ function SpotLayerController(props) {
266030
266056
  const handleOpacityChange = useCallback((e3, v) => setOpacity2(v), [setOpacity2]);
266031
266057
  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 }) })] }) }) });
266032
266058
  }
266059
+ const useStyles$g = makeStyles()(() => ({
266060
+ layerFeatureControllerGrid: {
266061
+ padding: "0",
266062
+ flexWrap: "nowrap"
266063
+ },
266064
+ layerFeatureExpansionButton: {
266065
+ display: "inline-block",
266066
+ margin: 0,
266067
+ padding: 0,
266068
+ minWidth: 0,
266069
+ lineHeight: 1,
266070
+ width: "50%"
266071
+ },
266072
+ layerTypeFeatureIcon: {
266073
+ height: "100%",
266074
+ paddingLeft: "2px",
266075
+ fill: "currentColor",
266076
+ fontSize: "14px",
266077
+ width: "50%",
266078
+ maxWidth: "16px"
266079
+ }
266080
+ }));
266081
+ function LayerPerFeatureController(props) {
266082
+ const { theme, palette = null, featureName, featureColor, setFeatureColor, featureValueColormap, featureSelection, setFeatureSelection, spatialLayerColor, featureIndex, obsColorEncoding, loadingDoneFraction, opacity: opacity2, handleOpacityChange } = props;
266083
+ const featureColorIndex = useMemo$1(() => featureColor?.findIndex((fc) => fc.name === featureName) ?? -1, [featureColor, featureName]);
266084
+ const varIndex = useMemo$1(() => featureIndex?.indexOf(featureName) ?? -1, [featureIndex, featureName]);
266085
+ const randomByFeatureColor = useMemo$1(() => varIndex >= 0 ? PALETTE[varIndex % PALETTE.length] : [255, 255, 255], [varIndex]);
266086
+ const handleRemoveFeature = useCallback(() => {
266087
+ setFeatureSelection(featureSelection.filter((f2) => f2 !== featureName));
266088
+ }, [featureName, featureSelection, setFeatureSelection]);
266089
+ const handleColorChange = useCallback((newColor) => {
266090
+ if (featureColorIndex >= 0) {
266091
+ const nextFeatureColor = [...featureColor];
266092
+ nextFeatureColor[featureColorIndex] = {
266093
+ ...nextFeatureColor[featureColorIndex],
266094
+ color: newColor
266095
+ };
266096
+ setFeatureColor(nextFeatureColor);
266097
+ } else {
266098
+ setFeatureColor([
266099
+ ...featureColor ?? [],
266100
+ { name: featureName, color: newColor }
266101
+ ]);
266102
+ }
266103
+ }, [featureName, featureColor, setFeatureColor, featureColorIndex]);
266104
+ const { classes: classes2 } = useStyles$g();
266105
+ const { classes: lcClasses } = useControllerSectionStyles();
266106
+ const { classes: menuClasses } = useEllipsisMenuStyles();
266107
+ const [open2, setOpen] = useState(false);
266108
+ const { colorPickerColor, colorPickerReadable, colorPickerWritable, colorPickerTooltip } = useMemo$1(() => {
266109
+ if (obsColorEncoding === "geneSelection") {
266110
+ return {
266111
+ colorPickerColor: featureColor?.[featureColorIndex]?.color ?? spatialLayerColor,
266112
+ colorPickerReadable: true,
266113
+ colorPickerWritable: true,
266114
+ colorPickerTooltip: null
266115
+ };
266116
+ }
266117
+ if (obsColorEncoding === "spatialLayerColor") {
266118
+ return {
266119
+ colorPickerColor: spatialLayerColor,
266120
+ colorPickerReadable: true,
266121
+ colorPickerWritable: false,
266122
+ 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".'
266123
+ };
266124
+ }
266125
+ if (obsColorEncoding === "randomByFeature") {
266126
+ return {
266127
+ colorPickerColor: randomByFeatureColor,
266128
+ colorPickerReadable: true,
266129
+ colorPickerWritable: false,
266130
+ 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".'
266131
+ };
266132
+ }
266133
+ if (obsColorEncoding === "random") {
266134
+ return {
266135
+ colorPickerColor: null,
266136
+ colorPickerReadable: false,
266137
+ colorPickerWritable: false,
266138
+ 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".'
266139
+ };
266140
+ }
266141
+ return {
266142
+ colorPickerColor: null,
266143
+ colorPickerReadable: false,
266144
+ colorPickerWritable: false,
266145
+ colorPickerTooltip: null
266146
+ };
266147
+ }, [
266148
+ obsColorEncoding,
266149
+ spatialLayerColor,
266150
+ featureName,
266151
+ featureColor,
266152
+ featureColorIndex,
266153
+ randomByFeatureColor
266154
+ ]);
266155
+ 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);
266156
+ }
266033
266157
  const useStyles$f = makeStyles()(() => ({
266034
266158
  pointLayerButton: {
266035
266159
  borderStyle: "dashed",
@@ -266072,7 +266196,7 @@ function PointLayerEllipsisMenu(props) {
266072
266196
  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" } } })] })] });
266073
266197
  }
266074
266198
  function PointLayerController(props) {
266075
- const { theme, layerScope, layerCoordination, setLayerCoordination, palette = null, pointMatrixIndicesData, tiledPointsLoadingProgress } = props;
266199
+ const { theme, layerScope, layerCoordination, setLayerCoordination, palette = null, pointMatrixIndicesData, tiledPointsLoadingProgress, layerPerFeatureForPoints } = props;
266076
266200
  const [open2, setOpen] = useState(false);
266077
266201
  const loadingDoneFraction = useMemo$1(() => {
266078
266202
  if (tiledPointsLoadingProgress && typeof tiledPointsLoadingProgress === "object") {
@@ -266157,7 +266281,8 @@ function PointLayerController(props) {
266157
266281
  useCallback(() => setOpen((prev2) => !prev2), []);
266158
266282
  const [coloringTabIndex, setColoringTabIndex] = useState(0);
266159
266283
  const { featureIndex } = pointMatrixIndicesData || {};
266160
- 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] }) });
266284
+ const hasSelectedFeatures = Array.isArray(featureSelection) && featureSelection.length > 0;
266285
+ 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] });
266161
266286
  }
266162
266287
  const useStyles$e = makeStyles()(() => ({
266163
266288
  layerTypeSegmentationIcon: {
@@ -269292,16 +269417,17 @@ function GlobalDimensionSlider(props) {
269292
269417
  const { classes: lcClasses } = useControllerSectionStyles();
269293
269418
  const { classes: classes2 } = useStyles$8();
269294
269419
  const isForZ = spatialRenderingMode !== null;
269420
+ const is3dMode = spatialRenderingMode === "3D";
269295
269421
  function handleRenderingModeChange(event2) {
269296
269422
  setSpatialRenderingMode(event2.target.checked ? "3D" : "2D");
269297
269423
  if (!event2.target.checked) {
269298
269424
  setTargetValue(Math.floor(targetValue));
269299
269425
  }
269300
269426
  }
269301
- 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 })] }) }) });
269427
+ 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 })] }) }) });
269302
269428
  }
269303
269429
  function LayerController(props) {
269304
- 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;
269430
+ 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;
269305
269431
  const anyLayerHasT = Object.values(images || {}).some((image2) => image2?.image?.instance.hasTStack());
269306
269432
  const anyLayerHasZ = Object.values(images || {}).some((image2) => image2?.image?.instance.hasZStack());
269307
269433
  const maxT = Object.values(images || {}).reduce((a2, h2) => Math.max(a2, h2?.image?.instance.getNumT()), 1) - 1;
@@ -269310,10 +269436,10 @@ function LayerController(props) {
269310
269436
  const reversedSegmentationLayerScopes = useMemo$1(() => [...segmentationLayerScopes || []].reverse(), [segmentationLayerScopes]);
269311
269437
  const reversedSpotLayerScopes = useMemo$1(() => [...spotLayerScopes || []].reverse(), [spotLayerScopes]);
269312
269438
  const reversedPointLayerScopes = useMemo$1(() => [...pointLayerScopes || []].reverse(), [pointLayerScopes]);
269313
- 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))] });
269439
+ 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))] });
269314
269440
  }
269315
269441
  function LayerControllerSubscriber(props) {
269316
- const { coordinationScopes: coordinationScopesRaw, coordinationScopesBy: coordinationScopesByRaw, closeButtonVisible, downloadButtonVisible, removeGridComponent, theme, title: title2 = "Spatial Layers", uuid: uuid2, cameraPresets } = props;
269442
+ const { coordinationScopes: coordinationScopesRaw, coordinationScopesBy: coordinationScopesByRaw, closeButtonVisible, downloadButtonVisible, removeGridComponent, theme, title: title2 = "Spatial Layers", uuid: uuid2, layerPerFeatureForPoints = false, cameraPresets } = props;
269317
269443
  const loaders = useLoaders();
269318
269444
  const mergeCoordination = useMergeCoordination();
269319
269445
  const coordinationScopes = useCoordinationScopes(coordinationScopesRaw);
@@ -269469,7 +269595,7 @@ function LayerControllerSubscriber(props) {
269469
269595
  imageDataStatus,
269470
269596
  pointMultiIndicesDataStatus
269471
269597
  ]);
269472
- 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 }) });
269598
+ 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 }) });
269473
269599
  }
269474
269600
  const isIterable$2 = (obj) => Symbol.iterator in obj;
269475
269601
  const hasIterableEntries = (value2) => (
@@ -271467,7 +271593,7 @@ function HiglassGlobalStyles(props) {
271467
271593
  }
271468
271594
  register({ dataFetcher: ZarrMultivecDataFetcher_default, config: ZarrMultivecDataFetcher_default.config }, { pluginType: "dataFetcher" });
271469
271595
  const LazyHiGlassComponent = React__default.lazy(async () => {
271470
- const { HiGlassComponent } = await import("./higlass-DBQ7M7Iv.js");
271596
+ const { HiGlassComponent } = await import("./higlass-PHabY4jK.js");
271471
271597
  return { default: HiGlassComponent };
271472
271598
  });
271473
271599
  const HG_SIZE = 800;
@@ -274415,7 +274541,7 @@ function NeuroglancerGlobalStyles(props) {
274415
274541
  const { classes: classes2 } = props;
274416
274542
  return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(GlobalStyles$3, { styles: globalNeuroglancerCss }), jsxRuntimeExports.jsx(ScopedGlobalStyles, { styles: globalNeuroglancerStyles, parentClassName: classes2.neuroglancerWrapper })] });
274417
274543
  }
274418
- const LazyReactNeuroglancer = React__default.lazy(() => import("./ReactNeuroglancer-DCZQdt01.js"));
274544
+ const LazyReactNeuroglancer = React__default.lazy(() => import("./ReactNeuroglancer-DJRTUBG7.js"));
274419
274545
  function createWorker() {
274420
274546
  const worker = new WorkerFactory$1();
274421
274547
  worker.AsyncComputationWorker = WorkerFactory;
@@ -274486,8 +274612,8 @@ class NeuroglancerComp extends PureComponent {
274486
274612
  }
274487
274613
  }
274488
274614
  render() {
274489
- const { classes: classes2, viewerState, cellColorMapping } = this.props;
274490
- 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 }) }) })] });
274615
+ const { classes: classes2, viewerState, cellColorMapping, onLayerLoadingChange } = this.props;
274616
+ 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 }) }) })] });
274491
274617
  }
274492
274618
  }
274493
274619
  function useMemoCustomComparison(factory2, dependencies2, customIsEqual) {
@@ -274526,7 +274652,8 @@ function customIsEqualForCellColors(prevDeps, nextDeps) {
274526
274652
  "obsColorEncoding",
274527
274653
  "obsSetSelection",
274528
274654
  "additionalObsSets",
274529
- "spatialChannelColor"
274655
+ "spatialChannelColor",
274656
+ "spatialChannelOpacity"
274530
274657
  ])) {
274531
274658
  forceUpdate = true;
274532
274659
  }
@@ -274541,6 +274668,9 @@ function customIsEqualForInitialViewerState(prevDeps, nextDeps) {
274541
274668
  const curriedShallowDiffByLayer = (depName, scopeName) => shallowDiffByLayer(prevDeps, nextDeps, depName, scopeName);
274542
274669
  const curriedShallowDiffByLayerCoordinationWithKeys = (depName, layerScope, keys2) => shallowDiffByLayerCoordinationWithKeys(prevDeps, nextDeps, depName, layerScope, keys2);
274543
274670
  const curriedShallowDiffByChannelCoordinationWithKeys = (depName, layerScope, channelScope, keys2) => shallowDiffByChannelCoordinationWithKeys(prevDeps, nextDeps, depName, layerScope, channelScope, keys2);
274671
+ if (["theme", "showAxisLines"].some(curriedShallowDiff)) {
274672
+ forceUpdate = true;
274673
+ }
274544
274674
  if (["segmentationLayerScopes", "segmentationChannelScopesByLayer"].some(curriedShallowDiff)) {
274545
274675
  forceUpdate = true;
274546
274676
  } else {
@@ -274569,7 +274699,8 @@ function customIsEqualForInitialViewerState(prevDeps, nextDeps) {
274569
274699
  "spatialLayerColor",
274570
274700
  "featureSelection",
274571
274701
  "featureFilterMode",
274572
- "featureColor"
274702
+ "featureColor",
274703
+ "spatialPointStrokeWidth"
274573
274704
  ]) || Math.abs(prevDeps?.pointLayerCoordination?.[0]?.[layerScope]?.spatialLayerOpacity - nextDeps?.pointLayerCoordination?.[0]?.[layerScope]?.spatialLayerOpacity) >= 0.05) {
274574
274705
  forceUpdate = true;
274575
274706
  }
@@ -274580,21 +274711,25 @@ function customIsEqualForInitialViewerState(prevDeps, nextDeps) {
274580
274711
  function normalizeColor(rgbColor) {
274581
274712
  return rgbColor.map((c2) => c2 / 255);
274582
274713
  }
274714
+ function borderWidthGlsl(borderWidth = 0) {
274715
+ return `setPointMarkerBorderWidth(${borderWidth.toFixed(1)});`;
274716
+ }
274583
274717
  function toVec3(normalizedColor) {
274584
274718
  return `vec3(${normalizedColor.join(", ")})`;
274585
274719
  }
274586
274720
  function toVec4(normalizedColor, alpha2) {
274587
274721
  return `vec4(${normalizedColor.join(", ")}, ${alpha2})`;
274588
274722
  }
274589
- function getSpatialLayerColorShader(staticColor, opacity2) {
274723
+ function getSpatialLayerColorShader(staticColor, opacity2, borderWidth = 0) {
274590
274724
  const norm2 = normalizeColor(staticColor);
274591
274725
  return `
274592
274726
  void main() {
274593
274727
  setColor(${toVec4(norm2, opacity2)});
274728
+ ${borderWidthGlsl(borderWidth)}
274594
274729
  }
274595
274730
  `;
274596
274731
  }
274597
- function getSpatialLayerColorWithSelectionShader(staticColor, opacity2, featureIndices, defaultColor, featureIndexProp) {
274732
+ function getSpatialLayerColorWithSelectionShader(staticColor, opacity2, featureIndices, defaultColor, featureIndexProp, borderWidth = 0) {
274598
274733
  const normStatic = normalizeColor(staticColor);
274599
274734
  const normDefault = normalizeColor(defaultColor);
274600
274735
  const numFeatures = featureIndices.length;
@@ -274611,13 +274746,15 @@ function getSpatialLayerColorWithSelectionShader(staticColor, opacity2, featureI
274611
274746
  }
274612
274747
  if (isSelected) {
274613
274748
  setColor(${toVec4(normStatic, opacity2)});
274749
+ ${borderWidthGlsl(borderWidth)}
274614
274750
  } else {
274615
274751
  setColor(${toVec4(normDefault, opacity2)});
274752
+ ${borderWidthGlsl(borderWidth)}
274616
274753
  }
274617
274754
  }
274618
274755
  `;
274619
274756
  }
274620
- function getSpatialLayerColorFilteredShader(staticColor, opacity2, featureIndices, featureIndexProp) {
274757
+ function getSpatialLayerColorFilteredShader(staticColor, opacity2, featureIndices, featureIndexProp, borderWidth = 0) {
274621
274758
  const normStatic = normalizeColor(staticColor);
274622
274759
  const numFeatures = featureIndices.length;
274623
274760
  const indicesArr = `int selectedIndices[${numFeatures}] = int[${numFeatures}](${featureIndices.join(", ")});`;
@@ -274635,18 +274772,20 @@ function getSpatialLayerColorFilteredShader(staticColor, opacity2, featureIndice
274635
274772
  discard;
274636
274773
  }
274637
274774
  setColor(${toVec4(normStatic, opacity2)});
274775
+ ${borderWidthGlsl(borderWidth)}
274638
274776
  }
274639
274777
  `;
274640
274778
  }
274641
- function getGeneSelectionNoSelectionShader(staticColor, opacity2) {
274779
+ function getGeneSelectionNoSelectionShader(staticColor, opacity2, borderWidth = 0) {
274642
274780
  const norm2 = normalizeColor(staticColor);
274643
274781
  return `
274644
274782
  void main() {
274645
274783
  setColor(${toVec4(norm2, opacity2)});
274784
+ ${borderWidthGlsl(borderWidth)}
274646
274785
  }
274647
274786
  `;
274648
274787
  }
274649
- function getGeneSelectionWithSelectionShader(featureIndices, featureColors, staticColor, defaultColor, opacity2, featureIndexProp) {
274788
+ function getGeneSelectionWithSelectionShader(featureIndices, featureColors, staticColor, defaultColor, opacity2, featureIndexProp, borderWidth = 0) {
274650
274789
  const numFeatures = featureIndices.length;
274651
274790
  const normDefault = normalizeColor(defaultColor);
274652
274791
  const normColors = featureColors.map((c2) => normalizeColor(c2));
@@ -274666,10 +274805,11 @@ function getGeneSelectionWithSelectionShader(featureIndices, featureColors, stat
274666
274805
  }
274667
274806
  }
274668
274807
  setColor(color);
274808
+ ${borderWidthGlsl(borderWidth)}
274669
274809
  }
274670
274810
  `;
274671
274811
  }
274672
- function getGeneSelectionFilteredShader(featureIndices, featureColors, staticColor, opacity2, featureIndexProp) {
274812
+ function getGeneSelectionFilteredShader(featureIndices, featureColors, staticColor, opacity2, featureIndexProp, borderWidth = 0) {
274673
274813
  const numFeatures = featureIndices.length;
274674
274814
  const normColors = featureColors.map((c2) => normalizeColor(c2));
274675
274815
  const normStatic = normalizeColor(staticColor);
@@ -274693,10 +274833,11 @@ function getGeneSelectionFilteredShader(featureIndices, featureColors, staticCol
274693
274833
  discard;
274694
274834
  }
274695
274835
  setColor(vec4(matchedColor, ${opacity2}));
274836
+ ${borderWidthGlsl(borderWidth)}
274696
274837
  }
274697
274838
  `;
274698
274839
  }
274699
- function getRandomByFeatureShader(opacity2, featureIndexProp) {
274840
+ function getRandomByFeatureShader(opacity2, featureIndexProp, borderWidth = 0) {
274700
274841
  const paletteSize = PALETTE.length;
274701
274842
  const normPalette = PALETTE.map((c2) => normalizeColor(c2));
274702
274843
  const paletteDecl = `vec3 palette[${paletteSize}] = vec3[${paletteSize}](${normPalette.map((c2) => toVec3(c2)).join(", ")});`;
@@ -274708,10 +274849,11 @@ function getRandomByFeatureShader(opacity2, featureIndexProp) {
274708
274849
  if (colorIdx < 0) { colorIdx = -colorIdx; }
274709
274850
  vec3 color = palette[colorIdx];
274710
274851
  setColor(vec4(color, ${opacity2}));
274852
+ ${borderWidthGlsl(borderWidth)}
274711
274853
  }
274712
274854
  `;
274713
274855
  }
274714
- function getRandomByFeatureWithSelectionShader(featureIndices, defaultColor, opacity2, featureIndexProp) {
274856
+ function getRandomByFeatureWithSelectionShader(featureIndices, defaultColor, opacity2, featureIndexProp, borderWidth = 0) {
274715
274857
  const paletteSize = PALETTE.length;
274716
274858
  const normPalette = PALETTE.map((c2) => normalizeColor(c2));
274717
274859
  const normDefault = normalizeColor(defaultColor);
@@ -274733,13 +274875,15 @@ function getRandomByFeatureWithSelectionShader(featureIndices, defaultColor, opa
274733
274875
  int colorIdx = geneIndex - (geneIndex / ${paletteSize}) * ${paletteSize};
274734
274876
  if (colorIdx < 0) { colorIdx = -colorIdx; }
274735
274877
  setColor(vec4(palette[colorIdx], ${opacity2}));
274878
+ ${borderWidthGlsl(borderWidth)}
274736
274879
  } else {
274737
274880
  setColor(${toVec4(normDefault, opacity2)});
274881
+ ${borderWidthGlsl(borderWidth)}
274738
274882
  }
274739
274883
  }
274740
274884
  `;
274741
274885
  }
274742
- function getRandomByFeatureFilteredShader(featureIndices, opacity2, featureIndexProp) {
274886
+ function getRandomByFeatureFilteredShader(featureIndices, opacity2, featureIndexProp, borderWidth = 0) {
274743
274887
  const paletteSize = PALETTE.length;
274744
274888
  const normPalette = PALETTE.map((c2) => normalizeColor(c2));
274745
274889
  const numFeatures = featureIndices.length;
@@ -274762,6 +274906,7 @@ function getRandomByFeatureFilteredShader(featureIndices, opacity2, featureIndex
274762
274906
  int colorIdx = geneIndex - (geneIndex / ${paletteSize}) * ${paletteSize};
274763
274907
  if (colorIdx < 0) { colorIdx = -colorIdx; }
274764
274908
  setColor(vec4(palette[colorIdx], ${opacity2}));
274909
+ ${borderWidthGlsl(borderWidth)}
274765
274910
  }
274766
274911
  `;
274767
274912
  }
@@ -274776,7 +274921,7 @@ function hashToFloatGlsl() {
274776
274921
  }
274777
274922
  `;
274778
274923
  }
274779
- function getRandomPerPointShader(opacity2, featureIndexProp, pointIndexProp) {
274924
+ function getRandomPerPointShader(opacity2, featureIndexProp, pointIndexProp, borderWidth = 0) {
274780
274925
  return `
274781
274926
  ${hashToFloatGlsl()}
274782
274927
  void main() {
@@ -274786,10 +274931,11 @@ function getRandomPerPointShader(opacity2, featureIndexProp, pointIndexProp) {
274786
274931
  float g = hashToFloat(pointIndex, 1);
274787
274932
  float b = hashToFloat(pointIndex, 2);
274788
274933
  setColor(vec4(r, g, b, ${opacity2}));
274934
+ ${borderWidthGlsl(borderWidth)}
274789
274935
  }
274790
274936
  `;
274791
274937
  }
274792
- function getRandomPerPointWithSelectionShader(featureIndices, defaultColor, opacity2, featureIndexProp, pointIndexProp) {
274938
+ function getRandomPerPointWithSelectionShader(featureIndices, defaultColor, opacity2, featureIndexProp, pointIndexProp, borderWidth = 0) {
274793
274939
  const normDefault = normalizeColor(defaultColor);
274794
274940
  const numFeatures = featureIndices.length;
274795
274941
  const indicesDecl = `int selectedIndices[${numFeatures}] = int[${numFeatures}](${featureIndices.join(", ")});`;
@@ -274810,13 +274956,15 @@ function getRandomPerPointWithSelectionShader(featureIndices, defaultColor, opac
274810
274956
  float g = hashToFloat(pointIndex, 1);
274811
274957
  float b = hashToFloat(pointIndex, 2);
274812
274958
  setColor(vec4(r, g, b, ${opacity2}));
274959
+ ${borderWidthGlsl(borderWidth)}
274813
274960
  } else {
274814
274961
  setColor(${toVec4(normDefault, opacity2)});
274962
+ ${borderWidthGlsl(borderWidth)}
274815
274963
  }
274816
274964
  }
274817
274965
  `;
274818
274966
  }
274819
- function getRandomPerPointFilteredShader(featureIndices, opacity2, featureIndexProp, pointIndexProp) {
274967
+ function getRandomPerPointFilteredShader(featureIndices, opacity2, featureIndexProp, pointIndexProp, borderWidth = 0) {
274820
274968
  const numFeatures = featureIndices.length;
274821
274969
  const indicesDecl = `int selectedIndices[${numFeatures}] = int[${numFeatures}](${featureIndices.join(", ")});`;
274822
274970
  return `
@@ -274838,11 +274986,12 @@ function getRandomPerPointFilteredShader(featureIndices, opacity2, featureIndexP
274838
274986
  float g = hashToFloat(pointIndex, 1);
274839
274987
  float b = hashToFloat(pointIndex, 2);
274840
274988
  setColor(vec4(r, g, b, ${opacity2}));
274989
+ ${borderWidthGlsl(borderWidth)}
274841
274990
  }
274842
274991
  `;
274843
274992
  }
274844
274993
  function getPointsShader(layerCoordination) {
274845
- const { theme, featureIndex, spatialLayerOpacity, obsColorEncoding, spatialLayerColor, featureSelection, featureFilterMode, featureColor, featureIndexProp, pointIndexProp } = layerCoordination;
274994
+ const { theme, featureIndex, spatialLayerOpacity, obsColorEncoding, spatialLayerColor, featureSelection, featureFilterMode, featureColor, pointMarkerBorderWidth = 0, featureIndexProp, pointIndexProp } = layerCoordination;
274846
274995
  const defaultColor = getDefaultColor(theme);
274847
274996
  const opacity2 = spatialLayerOpacity ?? 1;
274848
274997
  const staticColor = Array.isArray(spatialLayerColor) && spatialLayerColor.length === 3 ? spatialLayerColor : defaultColor;
@@ -274859,50 +275008,50 @@ function getPointsShader(layerCoordination) {
274859
275008
  }) : [];
274860
275009
  if (obsColorEncoding === "spatialLayerColor") {
274861
275010
  if (!hasFeatureSelection || !hasResolvedIndices) {
274862
- return getSpatialLayerColorShader(staticColor, opacity2);
275011
+ return getSpatialLayerColorShader(staticColor, opacity2, pointMarkerBorderWidth);
274863
275012
  }
274864
275013
  if (isFiltered) {
274865
- return getSpatialLayerColorFilteredShader(staticColor, opacity2, featureIndices, featureIndexProp);
275014
+ return getSpatialLayerColorFilteredShader(staticColor, opacity2, featureIndices, featureIndexProp, pointMarkerBorderWidth);
274866
275015
  }
274867
- return getSpatialLayerColorWithSelectionShader(staticColor, opacity2, featureIndices, defaultColor, featureIndexProp);
275016
+ return getSpatialLayerColorWithSelectionShader(staticColor, opacity2, featureIndices, defaultColor, featureIndexProp, pointMarkerBorderWidth);
274868
275017
  }
274869
275018
  if (obsColorEncoding === "geneSelection") {
274870
275019
  if (!featureIndexProp) {
274871
275020
  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.");
274872
275021
  }
274873
275022
  if (!hasFeatureSelection || !hasResolvedIndices) {
274874
- return getGeneSelectionNoSelectionShader(staticColor, opacity2);
275023
+ return getGeneSelectionNoSelectionShader(staticColor, opacity2, pointMarkerBorderWidth);
274875
275024
  }
274876
275025
  if (isFiltered) {
274877
- return getGeneSelectionFilteredShader(featureIndices, resolvedFeatureColors, staticColor, opacity2, featureIndexProp);
275026
+ return getGeneSelectionFilteredShader(featureIndices, resolvedFeatureColors, staticColor, opacity2, featureIndexProp, pointMarkerBorderWidth);
274878
275027
  }
274879
- return getGeneSelectionWithSelectionShader(featureIndices, resolvedFeatureColors, staticColor, defaultColor, opacity2, featureIndexProp);
275028
+ return getGeneSelectionWithSelectionShader(featureIndices, resolvedFeatureColors, staticColor, defaultColor, opacity2, featureIndexProp, pointMarkerBorderWidth);
274880
275029
  }
274881
275030
  if (obsColorEncoding === "randomByFeature") {
274882
275031
  if (!featureIndexProp) {
274883
275032
  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.");
274884
275033
  }
274885
275034
  if (!hasFeatureSelection || !hasResolvedIndices) {
274886
- return getRandomByFeatureShader(opacity2, featureIndexProp);
275035
+ return getRandomByFeatureShader(opacity2, featureIndexProp, pointMarkerBorderWidth);
274887
275036
  }
274888
275037
  if (isFiltered) {
274889
- return getRandomByFeatureFilteredShader(featureIndices, opacity2, featureIndexProp);
275038
+ return getRandomByFeatureFilteredShader(featureIndices, opacity2, featureIndexProp, pointMarkerBorderWidth);
274890
275039
  }
274891
- return getRandomByFeatureWithSelectionShader(featureIndices, defaultColor, opacity2, featureIndexProp);
275040
+ return getRandomByFeatureWithSelectionShader(featureIndices, defaultColor, opacity2, featureIndexProp, pointMarkerBorderWidth);
274892
275041
  }
274893
275042
  if (obsColorEncoding === "random") {
274894
275043
  if (!pointIndexProp) {
274895
275044
  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.");
274896
275045
  }
274897
275046
  if (!hasFeatureSelection || !hasResolvedIndices) {
274898
- return getRandomPerPointShader(opacity2, featureIndexProp, pointIndexProp);
275047
+ return getRandomPerPointShader(opacity2, featureIndexProp, pointIndexProp, pointMarkerBorderWidth);
274899
275048
  }
274900
275049
  if (isFiltered) {
274901
- return getRandomPerPointFilteredShader(featureIndices, opacity2, featureIndexProp, pointIndexProp);
275050
+ return getRandomPerPointFilteredShader(featureIndices, opacity2, featureIndexProp, pointIndexProp, pointMarkerBorderWidth);
274902
275051
  }
274903
- return getRandomPerPointWithSelectionShader(featureIndices, defaultColor, opacity2, featureIndexProp, pointIndexProp);
275052
+ return getRandomPerPointWithSelectionShader(featureIndices, defaultColor, opacity2, featureIndexProp, pointIndexProp, pointMarkerBorderWidth);
274904
275053
  }
274905
- return getSpatialLayerColorShader(staticColor, opacity2);
275054
+ return getSpatialLayerColorShader(staticColor, opacity2, pointMarkerBorderWidth);
274906
275055
  }
274907
275056
  const DEFAULT_NG_PROPS = {
274908
275057
  layout: "3d",
@@ -274932,7 +275081,7 @@ function toNgLayerName(dataType, layerScope, channelScope = null) {
274932
275081
  }
274933
275082
  throw new Error(`Unsupported data type: ${dataType}`);
274934
275083
  }
274935
- function useNeuroglancerViewerState(theme, segmentationLayerScopes, segmentationChannelScopesByLayer, segmentationLayerCoordination, segmentationChannelCoordination, obsSegmentationsUrls, obsSegmentationsData, pointLayerScopes, pointLayerCoordination, obsPointsUrls, obsPointsData, pointMultiIndicesData) {
275084
+ function useNeuroglancerViewerState(theme, showAxisLines, segmentationLayerScopes, segmentationChannelScopesByLayer, segmentationLayerCoordination, segmentationChannelCoordination, obsSegmentationsUrls, obsSegmentationsData, pointLayerScopes, pointLayerCoordination, obsPointsUrls, obsPointsData, pointMultiIndicesData) {
274936
275085
  const viewerState = useMemoCustomComparison(() => {
274937
275086
  let result = cloneDeep$1(DEFAULT_NG_PROPS);
274938
275087
  segmentationLayerScopes.forEach((layerScope) => {
@@ -274945,13 +275094,20 @@ function useNeuroglancerViewerState(theme, segmentationLayerScopes, segmentation
274945
275094
  channelScopes.forEach((channelScope) => {
274946
275095
  const channelCoordination = segmentationChannelCoordination[0]?.[layerScope]?.[channelScope];
274947
275096
  const { spatialChannelVisible } = channelCoordination || {};
275097
+ const { source: ngSource, ...otherNgOptions } = layerData.neuroglancerOptions ?? {};
275098
+ const hasNgSourceOptions = layerData.neuroglancerOptions?.subsources || layerData.neuroglancerOptions?.enableDefaultSubsources !== void 0;
275099
+ const source2 = hasNgSourceOptions ? {
275100
+ url: toPrecomputedSource(layerUrl),
275101
+ subsources: layerData.neuroglancerOptions.subsources,
275102
+ enableDefaultSubsources: layerData.neuroglancerOptions.enableDefaultSubsources ?? false
275103
+ } : toPrecomputedSource(layerUrl);
274948
275104
  result = {
274949
275105
  ...result,
274950
275106
  layers: [
274951
275107
  ...result.layers,
274952
275108
  {
274953
275109
  type: "segmentation",
274954
- source: toPrecomputedSource(layerUrl),
275110
+ source: source2,
274955
275111
  segments: [],
274956
275112
  name: toNgLayerName(DataType$3.OBS_SEGMENTATIONS, layerScope, channelScope),
274957
275113
  visible: spatialLayerVisible && spatialChannelVisible,
@@ -274959,7 +275115,7 @@ function useNeuroglancerViewerState(theme, segmentationLayerScopes, segmentation
274959
275115
  // visibility must be true for the layer to be visible.
274960
275116
  // TODO: update this to extract specific properties from
274961
275117
  // neuroglancerOptions as needed.
274962
- ...layerData.neuroglancerOptions ?? {}
275118
+ ...otherNgOptions
274963
275119
  }
274964
275120
  ]
274965
275121
  };
@@ -274972,7 +275128,7 @@ function useNeuroglancerViewerState(theme, segmentationLayerScopes, segmentation
274972
275128
  const layerUrl = obsPointsUrls[layerScope]?.[0]?.url;
274973
275129
  const featureIndex = pointMultiIndicesData[layerScope]?.featureIndex;
274974
275130
  if (layerUrl && layerData) {
274975
- const { spatialLayerVisible, spatialLayerOpacity, obsColorEncoding, spatialLayerColor, featureSelection, featureFilterMode, featureColor } = layerCoordination || {};
275131
+ const { spatialLayerVisible, spatialLayerOpacity, obsColorEncoding, spatialLayerColor, featureSelection, featureFilterMode, featureColor, spatialPointStrokeWidth } = layerCoordination || {};
274976
275132
  const shader = getPointsShader({
274977
275133
  theme,
274978
275134
  featureIndex,
@@ -274983,7 +275139,8 @@ function useNeuroglancerViewerState(theme, segmentationLayerScopes, segmentation
274983
275139
  featureFilterMode,
274984
275140
  featureColor,
274985
275141
  featureIndexProp: layerData.neuroglancerOptions?.featureIndexProp,
274986
- pointIndexProp: layerData.neuroglancerOptions?.pointIndexProp
275142
+ pointIndexProp: layerData.neuroglancerOptions?.pointIndexProp,
275143
+ pointMarkerBorderWidth: spatialPointStrokeWidth ?? 0
274987
275144
  });
274988
275145
  result = {
274989
275146
  ...result,
@@ -275020,6 +275177,7 @@ function useNeuroglancerViewerState(theme, segmentationLayerScopes, segmentation
275020
275177
  return result;
275021
275178
  }, {
275022
275179
  theme,
275180
+ showAxisLines,
275023
275181
  segmentationLayerScopes,
275024
275182
  segmentationChannelScopesByLayer,
275025
275183
  segmentationLayerCoordination,
@@ -304715,6 +304873,7 @@ function NeuroglancerSubscriber(props) {
304715
304873
  downloadButtonVisible,
304716
304874
  removeGridComponent,
304717
304875
  theme,
304876
+ showAxisLines = false,
304718
304877
  title: title2 = "Spatial",
304719
304878
  subtitle = "Powered by Neuroglancer",
304720
304879
  helpText = ViewHelpMapping.NEUROGLANCER,
@@ -304803,7 +304962,8 @@ function NeuroglancerSubscriber(props) {
304803
304962
  CoordinationType$1.OBS_HIGHLIGHT,
304804
304963
  CoordinationType$1.TOOLTIPS_VISIBLE,
304805
304964
  CoordinationType$1.TOOLTIP_CROSSHAIRS_VISIBLE,
304806
- CoordinationType$1.LEGEND_VISIBLE
304965
+ CoordinationType$1.LEGEND_VISIBLE,
304966
+ CoordinationType$1.SPATIAL_POINT_STROKE_WIDTH
304807
304967
  ], coordinationScopes, coordinationScopesBy, CoordinationType$1.POINT_LAYER);
304808
304968
  const [obsPointsData, obsPointsDataStatus, obsPointsUrls, obsPointsErrors] = useMultiObsPoints(coordinationScopes, coordinationScopesBy, loaders, dataset, mergeCoordination, uuid2);
304809
304969
  const [pointMultiIndicesData, pointMultiIndicesDataStatus, pointMultiIndicesDataErrors] = usePointMultiObsFeatureMatrixIndices(coordinationScopes, coordinationScopesBy, loaders, dataset);
@@ -304836,7 +304996,7 @@ function NeuroglancerSubscriber(props) {
304836
304996
  result[layerScope] = {};
304837
304997
  segmentationChannelScopesByLayer?.[layerScope]?.forEach((channelScope) => {
304838
304998
  const { obsSets: layerSets, obsIndex: layerIndex } = obsSegmentationsSetsData?.[layerScope]?.[channelScope] || {};
304839
- const { obsSetColor, obsColorEncoding, obsSetSelection, additionalObsSets, spatialChannelColor } = segmentationChannelCoordination[0][layerScope][channelScope];
304999
+ const { obsSetColor, obsColorEncoding, obsSetSelection, additionalObsSets, spatialChannelColor, spatialChannelOpacity } = segmentationChannelCoordination[0][layerScope][channelScope];
304840
305000
  if (obsColorEncoding === "spatialChannelColor") {
304841
305001
  if (layerIndex && spatialChannelColor) {
304842
305002
  const hex2 = rgbToHex$1(spatialChannelColor);
@@ -304856,6 +305016,7 @@ function NeuroglancerSubscriber(props) {
304856
305016
  });
304857
305017
  }
304858
305018
  result[layerScope][channelScope] = ngCellColors;
305019
+ result[layerScope].opacity = spatialChannelOpacity ?? 1;
304859
305020
  }
304860
305021
  } else if (layerSets && layerIndex) {
304861
305022
  const mergedCellSets = mergeObsSets(layerSets, additionalObsSets);
@@ -304871,6 +305032,7 @@ function NeuroglancerSubscriber(props) {
304871
305032
  ngCellColors[i2] = rgbToHex$1(color2);
304872
305033
  });
304873
305034
  result[layerScope][channelScope] = ngCellColors;
305035
+ result[layerScope].opacity = spatialChannelOpacity ?? 1;
304874
305036
  }
304875
305037
  });
304876
305038
  });
@@ -304884,7 +305046,7 @@ function NeuroglancerSubscriber(props) {
304884
305046
  segmentationChannelCoordination,
304885
305047
  theme
304886
305048
  }, customIsEqualForCellColors);
304887
- const initalViewerState = useNeuroglancerViewerState(theme, segmentationLayerScopes, segmentationChannelScopesByLayer, segmentationLayerCoordination, segmentationChannelCoordination, obsSegmentationsUrls, obsSegmentationsData, pointLayerScopes, pointLayerCoordination, obsPointsUrls, obsPointsData, pointMultiIndicesData);
305049
+ const initalViewerState = useNeuroglancerViewerState(theme, showAxisLines, segmentationLayerScopes, segmentationChannelScopesByLayer, segmentationLayerCoordination, segmentationChannelCoordination, obsSegmentationsUrls, obsSegmentationsData, pointLayerScopes, pointLayerCoordination, obsPointsUrls, obsPointsData, pointMultiIndicesData);
304888
305050
  const [latestViewerStateIteration, incrementLatestViewerStateIteration] = useReducer((x2) => x2 + 1, 0);
304889
305051
  const latestViewerStateRef = useRef({
304890
305052
  ...initalViewerState,
@@ -304918,6 +305080,7 @@ function NeuroglancerSubscriber(props) {
304918
305080
  z: spatialRotationZ,
304919
305081
  orbit: spatialRotationOrbit
304920
305082
  });
305083
+ const [isLayersLoaded, setIsLayersLoaded] = useState(false);
304921
305084
  const prevCoordsRef = useRef({
304922
305085
  zoom: spatialZoom,
304923
305086
  rx: spatialRotationX,
@@ -305022,7 +305185,10 @@ function NeuroglancerSubscriber(props) {
305022
305185
  const result = {};
305023
305186
  segmentationLayerScopes?.forEach((layerScope) => {
305024
305187
  const channelScope = segmentationChannelScopesByLayer?.[layerScope]?.[0];
305025
- result[layerScope] = segmentationColorMapping?.[layerScope]?.[channelScope] ?? {};
305188
+ result[layerScope] = {
305189
+ colors: segmentationColorMapping?.[layerScope]?.[channelScope] ?? {},
305190
+ opacity: segmentationColorMapping?.[layerScope]?.opacity ?? 1
305191
+ };
305026
305192
  });
305027
305193
  return result;
305028
305194
  }, [segmentationColorMapping, segmentationLayerScopes, segmentationChannelScopesByLayer]);
@@ -305085,12 +305251,13 @@ function NeuroglancerSubscriber(props) {
305085
305251
  }
305086
305252
  const updatedLayers = current2?.layers?.map((layer, idx) => {
305087
305253
  const layerScope = segmentationLayerScopes?.[idx];
305088
- const layerColorMapping = cellColorMappingByLayer?.[layerScope] ?? {};
305254
+ const layerColorMapping = cellColorMappingByLayer?.[layerScope]?.colors ?? {};
305089
305255
  const layerSegments = Object.keys(layerColorMapping);
305090
305256
  return {
305091
305257
  ...layer,
305092
305258
  segments: layerSegments,
305093
- segmentColors: layerColorMapping
305259
+ segmentColors: layerColorMapping,
305260
+ objectAlpha: cellColorMappingByLayer?.[layerScope]?.opacity ?? 1
305094
305261
  };
305095
305262
  }) ?? [];
305096
305263
  const updated = {
@@ -305125,8 +305292,23 @@ function NeuroglancerSubscriber(props) {
305125
305292
  const onSegmentHighlight = useCallback((obsId) => {
305126
305293
  setCellHighlight(String(obsId));
305127
305294
  }, [setCellHighlight]);
305295
+ const handleLayerLoadingChange = useCallback((isLoaded) => {
305296
+ setIsLayersLoaded(isLoaded);
305297
+ }, []);
305128
305298
  const hasLayers = derivedViewerState?.layers?.length > 0;
305129
- 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 });
305299
+ 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, {
305300
+ theme: "dark",
305301
+ maxHeight: ngHeight,
305302
+ // Segmentations
305303
+ segmentationLayerScopes,
305304
+ segmentationLayerCoordination,
305305
+ segmentationChannelScopesByLayer,
305306
+ segmentationChannelCoordination,
305307
+ // Points
305308
+ pointLayerScopes,
305309
+ pointLayerCoordination,
305310
+ pointMultiIndicesData
305311
+ }) }), jsxRuntimeExports.jsx(NeuroglancerComp, { classes: classes2, onSegmentClick, onSelectHoveredCoords: onSegmentHighlight, viewerState: derivedViewerState, cellColorMapping: cellColorMappingByLayer, setViewerState: handleStateUpdate, onLayerLoadingChange: handleLayerLoadingChange })] }) : null });
305130
305312
  }
305131
305313
  const FEATURE_AGGREGATION_STRATEGIES = ["first", "last", "sum", "mean"];
305132
305314
  function CellSetExpressionPlotOptions(props) {
@@ -307085,10 +307267,9 @@ function CellSetExpressionPlot(props) {
307085
307267
  if (!obsSetSelection) {
307086
307268
  return 0;
307087
307269
  }
307088
- const cellSetNames = obsSetSelection.map((d) => d.at(-1));
307089
- return cellSetNames.reduce((acc, name2) => {
307090
- acc = acc === void 0 || name2.length > acc ? name2.length : acc;
307091
- return acc;
307270
+ return obsSetSelection.reduce((acc, path2) => {
307271
+ const nameLength = path2?.at(-1)?.length ?? 0;
307272
+ return nameLength > acc ? nameLength : acc;
307092
307273
  }, 0);
307093
307274
  }, [obsSetSelection]);
307094
307275
  const isStratified = Array.isArray(sampleSetSelection) && sampleSetSelection.length === 2;
@@ -307167,7 +307348,7 @@ function CellSetExpressionPlot(props) {
307167
307348
  }
307168
307349
  g2.append("g").attr("transform", `translate(${marginLeft},0)`).call(axisLeft(y2)).selectAll("text").style("font-size", "11px");
307169
307350
  const xTickG = g2.append("g").attr("transform", `translate(0,${innerHeight})`).style("font-size", "14px");
307170
- 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");
307351
+ 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");
307171
307352
  if (isStratified) {
307172
307353
  const tickWidth = xGroup.bandwidth();
307173
307354
  xTickG.selectAll(".tick").append("rect").attr("x", -tickWidth / 2).attr("width", tickWidth).attr("height", 4).style("fill", (d) => obsSetColorScale(d));
@@ -357951,7 +358132,7 @@ const VEGA_THEMES = {
357951
358132
  };
357952
358133
  const DATASET_NAME = "table";
357953
358134
  function VegaGlobalStyles() {
357954
- const { theme } = useStyles$x();
358135
+ const { theme } = useStyles$y();
357955
358136
  return jsxRuntimeExports.jsx(GlobalStyles$3, { styles: {
357956
358137
  "#vg-tooltip-element.vg-tooltip.custom-theme": {
357957
358138
  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)",
@@ -357985,7 +358166,7 @@ function renderTooltipContents(tooltipText) {
357985
358166
  }
357986
358167
  function VegaPlot(props) {
357987
358168
  const { spec: partialSpec, data: data2, getTooltipText, signalListeners, renderer = "svg", onNewView } = props;
357988
- const { classes: tooltipClasses2 } = useStyles$s();
358169
+ const { classes: tooltipClasses2 } = useStyles$t();
357989
358170
  const tooltipHandler = useMemo$1(() => {
357990
358171
  if (typeof getTooltipText === "function") {
357991
358172
  const tooltipConfig = {
@@ -360683,7 +360864,8 @@ class SpatialDataAutoConfig extends AbstractAutoConfig {
360683
360864
  });
360684
360865
  availableElements.forEach(({ path: path2, attrs }) => {
360685
360866
  const relPath = path2.substring(1);
360686
- const firstCoordinateSystem = attrs?.multiscales?.[0]?.coordinateTransformations?.[0]?.output?.name;
360867
+ const omeAttrs = flattenOmeAttrs(attrs);
360868
+ const firstCoordinateSystem = omeAttrs?.multiscales?.[0]?.coordinateTransformations?.[0]?.output?.name;
360687
360869
  if (relPath.match(/^(images)\/([^/]*)$/)) {
360688
360870
  options.image = {
360689
360871
  path: relPath,
@@ -363765,10 +363947,10 @@ class OmeZarrLoader extends AbstractTwoStepLoader {
363765
363947
  const loader2 = await loadOmeZarr(this.storeRoot);
363766
363948
  const imageWrapper = new ImageWrapper(loader2, this.options);
363767
363949
  const { metadata: metadata2, data: data2 } = loader2;
363768
- const { omero, multiscales, channels_metadata: spatialDataChannels, "image-label": imageLabel } = metadata2;
363769
- const isSpatialData = !!spatialDataChannels || !!imageLabel;
363770
- const isLabels = !!imageLabel;
363771
- if (!isSpatialData && !omero) {
363950
+ const { omero, multiscales, channels_metadata: spatialDataChannels, "image-label": imageLabel, spatialdata_attrs: spatialDataAttrs } = metadata2;
363951
+ const isSpatialDataElement = !!spatialDataChannels || !!imageLabel || !!spatialDataAttrs;
363952
+ const isLabels = !!imageLabel || isSpatialDataElement && !omero && !spatialDataChannels;
363953
+ if (!isSpatialDataElement && !omero) {
363772
363954
  throw new Error("image.ome-zarr must have omero metadata in attributes.");
363773
363955
  }
363774
363956
  if (!Array.isArray(multiscales) || multiscales.length === 0) {
@@ -363797,23 +363979,21 @@ class OmeZarrLoader extends AbstractTwoStepLoader {
363797
363979
  let channelLabels = [];
363798
363980
  let initialTargetT = 0;
363799
363981
  let initialTargetZ = 0;
363800
- if (isSpatialData) {
363801
- if (isLabels) {
363802
- channelObjects = [{
363803
- selection: filterSelection2({ z: initialTargetZ, t: initialTargetT, c: 0 }),
363804
- slider: [0, 255],
363805
- color: [255, 255, 255]
363806
- }];
363807
- channelLabels = ["labels"];
363808
- } else {
363809
- const { channels: channels2 } = spatialDataChannels;
363810
- channelObjects = channels2.map((channel, i2) => ({
363811
- selection: filterSelection2({ z: initialTargetZ, t: initialTargetT, c: i2 }),
363812
- slider: [0, 255],
363813
- color: [255, 255, 255]
363814
- }));
363815
- channelLabels = channels2.map((c2) => c2.label);
363816
- }
363982
+ if (isLabels) {
363983
+ channelObjects = [{
363984
+ selection: filterSelection2({ z: initialTargetZ, t: initialTargetT, c: 0 }),
363985
+ slider: [0, 255],
363986
+ color: [255, 255, 255]
363987
+ }];
363988
+ channelLabels = ["labels"];
363989
+ } else if (spatialDataChannels) {
363990
+ const { channels: channels2 } = spatialDataChannels;
363991
+ channelObjects = channels2.map((channel, i2) => ({
363992
+ selection: filterSelection2({ z: initialTargetZ, t: initialTargetT, c: i2 }),
363993
+ slider: [0, 255],
363994
+ color: [255, 255, 255]
363995
+ }));
363996
+ channelLabels = channels2.map((c2) => c2.label);
363817
363997
  } else {
363818
363998
  const { rdefs = {}, channels: channels2 } = omero;
363819
363999
  if (typeof rdefs.defaultT === "number") {
@@ -386530,6 +386710,7 @@ const baseCoordinationTypes = [
386530
386710
  new PluginCoordinationType(CoordinationType$1.SPATIAL_CHANNEL_COLOR, [255, 255, 255], z.array(z.number()).length(3).nullable()),
386531
386711
  new PluginCoordinationType(CoordinationType$1.SPATIAL_SEGMENTATION_FILLED, true, z.boolean()),
386532
386712
  new PluginCoordinationType(CoordinationType$1.SPATIAL_SEGMENTATION_STROKE_WIDTH, 1, z.number()),
386713
+ new PluginCoordinationType(CoordinationType$1.SPATIAL_POINT_STROKE_WIDTH, 0, z.number()),
386533
386714
  new PluginCoordinationType(CoordinationType$1.SPATIAL_LOD_FACTOR, 1, z.number()),
386534
386715
  // Reference: https://www.awaresystems.be/imaging/tiff/tifftags/photometricinterpretation.html
386535
386716
  new PluginCoordinationType(CoordinationType$1.PHOTOMETRIC_INTERPRETATION, null, z.enum(["BlackIsZero", "RGB"]).nullable()),