@vitessce/all 4.0.0-test.3 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/{GeometryAndMeshXR-BRP24ura.js → GeometryAndMeshXR-o1KV1S6m.js} +2 -2
  2. package/dist/{ReactNeuroglancer-VYcAJw_c.js → ReactNeuroglancer-BuXB_Emb.js} +1 -1
  3. package/dist/{XREnterButton-vmEhdF4L.js → XREnterButton-DZUdn-IL.js} +1 -1
  4. package/dist/{XRSceneComponents-DnZLSAJz.js → XRSceneComponents-Cgrg-9p2.js} +3 -1
  5. package/dist/{XRWrapper-C94X82Mb.js → XRWrapper-BB28re-M.js} +3 -2
  6. package/dist/{deflate-B35gUGrI.js → deflate-E8TfyvM7.js} +1 -1
  7. package/dist/{higlass-DIGh19X3.js → higlass-CGhpbMxK.js} +1 -1
  8. package/dist/{index-CIJWVuYa.js → index-0nuepTVk.js} +18 -6
  9. package/dist/{index-BRdVNpUK.js → index-BHE3zASA.js} +7 -6
  10. package/dist/{index-DLzCt39t.js → index-moreUHDf.js} +447 -220
  11. package/dist/index.js +1 -1
  12. package/dist/{jpeg-pIveo5qm.js → jpeg-_87xUwY6.js} +1 -1
  13. package/dist/{lerc-DEzmYyQ_.js → lerc-DFl9HcRa.js} +1 -1
  14. package/dist/{lzw-lK2xDQPh.js → lzw-hla-j59h.js} +1 -1
  15. package/dist/{packbits-Ds8BMewq.js → packbits-C8umOnfG.js} +1 -1
  16. package/dist/{raw-BKulPvK3.js → raw-BLQKlp_4.js} +1 -1
  17. package/dist/{webimage-BnK9oxcF.js → webimage-nk5eMN68.js} +1 -1
  18. package/dist/xrStore-gGt4Wkvz.js +8 -0
  19. package/dist-tsc/Vitessce.js +1 -0
  20. package/dist-tsc/Vitessce.js.map +1 -0
  21. package/dist-tsc/base-plugins.d.ts +1 -1
  22. package/dist-tsc/base-plugins.d.ts.map +1 -1
  23. package/dist-tsc/base-plugins.js +3 -0
  24. package/dist-tsc/base-plugins.js.map +1 -0
  25. package/dist-tsc/index.js +1 -0
  26. package/dist-tsc/index.js.map +1 -0
  27. package/dist-tsc/joint-file-types-legacy.js +1 -0
  28. package/dist-tsc/joint-file-types-legacy.js.map +1 -0
  29. package/dist-tsc/joint-file-types-legacy.test.js +1 -0
  30. package/dist-tsc/joint-file-types-legacy.test.js.map +1 -0
  31. package/dist-tsc/joint-file-types.js +1 -0
  32. package/dist-tsc/joint-file-types.js.map +1 -0
  33. package/dist-tsc/joint-file-types.test.js +1 -0
  34. package/dist-tsc/joint-file-types.test.js.map +1 -0
  35. package/dist-tsc/latest-config-schema.test.js +1 -0
  36. package/dist-tsc/latest-config-schema.test.js.map +1 -0
  37. package/package.json +34 -34
  38. package/src/base-plugins.ts +2 -0
  39. package/dist/xrStore-BymedRtx.js +0 -8
@@ -4,9 +4,6 @@ import { useLoaders, useCoordinationScopes, useCoordination, useDescription, use
4
4
  import { jsx as jsx$1, jsxs, Fragment } from "react/jsx-runtime";
5
5
  import * as ReactDOM from "react-dom";
6
6
  import ReactDOM__default, { createPortal } from "react-dom";
7
- import { Quaternion as Quaternion$1, Euler as Euler$1 } from "three";
8
- import { GLTFLoader as GLTFLoader$1 } from "three/addons/loaders/GLTFLoader.js";
9
- import { DRACOLoader } from "three/addons/loaders/DRACOLoader.js";
10
7
  function _mergeNamespaces(n3, m2) {
11
8
  for (var i2 = 0; i2 < m2.length; i2++) {
12
9
  const e3 = m2[i2];
@@ -4946,7 +4943,7 @@ function baseClamp(number2, lower2, upper) {
4946
4943
  }
4947
4944
  return number2;
4948
4945
  }
4949
- function clamp$7(number2, lower2, upper) {
4946
+ function clamp$8(number2, lower2, upper) {
4950
4947
  if (upper === void 0) {
4951
4948
  upper = lower2;
4952
4949
  lower2 = void 0;
@@ -9267,6 +9264,7 @@ const FileType$1 = {
9267
9264
  OBS_LABELS_MUDATA_ZARR: "obsLabels.mudata.zarr",
9268
9265
  FEATURE_LABELS_MUDATA_ZARR: "featureLabels.mudata.zarr",
9269
9266
  GENOMIC_PROFILES_ZARR: "genomic-profiles.zarr",
9267
+ GENOMIC_PROFILES_ZARR_ZIP: "genomic-profiles.zarr.zip",
9270
9268
  NEIGHBORHOODS_JSON: "neighborhoods.json",
9271
9269
  // OME-TIFF
9272
9270
  IMAGE_OME_TIFF: "image.ome-tiff",
@@ -9438,6 +9436,7 @@ const CoordinationType$1 = {
9438
9436
  SPATIAL_CHANNEL_LABELS_VISIBLE: "spatialChannelLabelsVisible",
9439
9437
  SPATIAL_CHANNEL_LABELS_ORIENTATION: "spatialChannelLabelsOrientation",
9440
9438
  SPATIAL_CHANNEL_LABEL_SIZE: "spatialChannelLabelSize",
9439
+ SPATIAL_CHANNELS_SORT_ORDER: "spatialChannelsSortOrder",
9441
9440
  // Multi-sample / comparative
9442
9441
  SAMPLE_TYPE: "sampleType",
9443
9442
  SAMPLE_SELECTION: "sampleSelection",
@@ -9490,7 +9489,9 @@ const ViewHelpMapping = {
9490
9489
  OBS_SET_COMPOSITION_BAR_PLOT: "The set composition bar plot displays the results of a compositional analysis conducted using the scCODA method (Büttner et al. 2021 Nature Communications).",
9491
9490
  FEATURE_SET_ENRICHMENT_BAR_PLOT: "The feature set enrichment bar plot displays the results of a hypergeometric test applied to the differential expression test results to identify enriched pathway gene sets.",
9492
9491
  SAMPLE_SET_PAIR_MANAGER: "Select pairs of sample groups.",
9493
- FEATURE_STATS_TABLE: "This table displays per-feature statistics, for example, from a differential expression test."
9492
+ FEATURE_STATS_TABLE: "This table displays per-feature statistics, for example, from a differential expression test.",
9493
+ LAYER_CONTROLLER_BETA: "The spatial layer controller provides an interface for manipulating the visualization layers displayed in the spatial view.",
9494
+ SPATIAL_BETA: "The spatial view displays (potentially layered) spatially-resolved data including RGB or multiplexed images, segmentations of observations (bitmask- or polygon-based), and/or points (e.g., representing FISH transcripts)."
9494
9495
  };
9495
9496
  ({
9496
9497
  // For new file types
@@ -9561,6 +9562,7 @@ const ViewHelpMapping = {
9561
9562
  [FileType$1.OBS_LABELS_MOLECULES_JSON]: DataType$3.OBS_LABELS,
9562
9563
  // For old file types
9563
9564
  [FileType$1.GENOMIC_PROFILES_ZARR]: DataType$3.GENOMIC_PROFILES,
9565
+ [FileType$1.GENOMIC_PROFILES_ZARR_ZIP]: DataType$3.GENOMIC_PROFILES,
9564
9566
  [FileType$1.NEIGHBORHOODS_JSON]: DataType$3.NEIGHBORHOODS
9565
9567
  });
9566
9568
  ({
@@ -9725,6 +9727,10 @@ const ALT_ZARR_STORE_TYPES = {
9725
9727
  },
9726
9728
  [FileType$1.OBS_EMBEDDING_SPATIALDATA_ZARR]: {
9727
9729
  zip: FileType$1.OBS_EMBEDDING_SPATIALDATA_ZARR_ZIP
9730
+ },
9731
+ // For genomic profiles:
9732
+ [FileType$1.GENOMIC_PROFILES_ZARR]: {
9733
+ zip: FileType$1.GENOMIC_PROFILES_ZARR_ZIP
9728
9734
  }
9729
9735
  };
9730
9736
  [
@@ -10036,6 +10042,7 @@ const COMPONENT_COORDINATION_TYPES = {
10036
10042
  CoordinationType$1.SPATIAL_CHANNEL_LABELS_VISIBLE,
10037
10043
  CoordinationType$1.SPATIAL_CHANNEL_LABELS_ORIENTATION,
10038
10044
  CoordinationType$1.SPATIAL_CHANNEL_LABEL_SIZE,
10045
+ CoordinationType$1.SPATIAL_CHANNELS_SORT_ORDER,
10039
10046
  CoordinationType$1.PHOTOMETRIC_INTERPRETATION
10040
10047
  ],
10041
10048
  [ViewType$1.HEATMAP]: [
@@ -10217,7 +10224,8 @@ const COMPONENT_COORDINATION_TYPES = {
10217
10224
  CoordinationType$1.LEGEND_VISIBLE,
10218
10225
  CoordinationType$1.SPATIAL_CHANNEL_LABELS_VISIBLE,
10219
10226
  CoordinationType$1.SPATIAL_CHANNEL_LABELS_ORIENTATION,
10220
- CoordinationType$1.SPATIAL_CHANNEL_LABEL_SIZE
10227
+ CoordinationType$1.SPATIAL_CHANNEL_LABEL_SIZE,
10228
+ CoordinationType$1.SPATIAL_CHANNELS_SORT_ORDER
10221
10229
  ],
10222
10230
  [ViewType$1.GENOMIC_PROFILES]: [
10223
10231
  CoordinationType$1.DATASET,
@@ -16101,7 +16109,7 @@ function useThemeProps$1({
16101
16109
  });
16102
16110
  }
16103
16111
  const useEnhancedEffect$1 = typeof window !== "undefined" ? React.useLayoutEffect : React.useEffect;
16104
- function clamp$6(val, min2 = Number.MIN_SAFE_INTEGER, max2 = Number.MAX_SAFE_INTEGER) {
16112
+ function clamp$7(val, min2 = Number.MIN_SAFE_INTEGER, max2 = Number.MAX_SAFE_INTEGER) {
16105
16113
  return Math.max(min2, Math.min(val, max2));
16106
16114
  }
16107
16115
  function clampWrapper(value2, min2 = 0, max2 = 1) {
@@ -16110,7 +16118,7 @@ function clampWrapper(value2, min2 = 0, max2 = 1) {
16110
16118
  console.error(`MUI: The value provided ${value2} is out of range [${min2}, ${max2}].`);
16111
16119
  }
16112
16120
  }
16113
- return clamp$6(value2, min2, max2);
16121
+ return clamp$7(value2, min2, max2);
16114
16122
  }
16115
16123
  function hexToRgb$1(color2) {
16116
16124
  color2 = color2.slice(1);
@@ -39601,7 +39609,7 @@ function useSlider(parameters2) {
39601
39609
  });
39602
39610
  const range2 = Array.isArray(valueDerived);
39603
39611
  let values3 = range2 ? valueDerived.slice().sort(asc) : [valueDerived];
39604
- values3 = values3.map((value2) => value2 == null ? min2 : clamp$6(value2, min2, max2));
39612
+ values3 = values3.map((value2) => value2 == null ? min2 : clamp$7(value2, min2, max2));
39605
39613
  const marks = marksProp === true && step !== null ? [...Array(Math.floor((max2 - min2) / step) + 1)].map((_, index2) => ({
39606
39614
  value: min2 + step * index2
39607
39615
  })) : marksProp || [];
@@ -39639,10 +39647,10 @@ function useSlider(parameters2) {
39639
39647
  newValue = newValue < value2 ? marksValues[marksIndex - 1] : marksValues[marksIndex + 1];
39640
39648
  }
39641
39649
  }
39642
- newValue = clamp$6(newValue, min2, max2);
39650
+ newValue = clamp$7(newValue, min2, max2);
39643
39651
  if (range2) {
39644
39652
  if (disableSwap) {
39645
- newValue = clamp$6(newValue, values3[index2 - 1] || -Infinity, values3[index2 + 1] || Infinity);
39653
+ newValue = clamp$7(newValue, values3[index2 - 1] || -Infinity, values3[index2 + 1] || Infinity);
39646
39654
  }
39647
39655
  const previousValue = newValue;
39648
39656
  newValue = setValueIndex({
@@ -39777,7 +39785,7 @@ function useSlider(parameters2) {
39777
39785
  const closestIndex = findClosest(marksValues, newValue);
39778
39786
  newValue = marksValues[closestIndex];
39779
39787
  }
39780
- newValue = clamp$6(newValue, min2, max2);
39788
+ newValue = clamp$7(newValue, min2, max2);
39781
39789
  let activeIndex = 0;
39782
39790
  if (range2) {
39783
39791
  if (!move2) {
@@ -39786,7 +39794,7 @@ function useSlider(parameters2) {
39786
39794
  activeIndex = previousIndex.current;
39787
39795
  }
39788
39796
  if (disableSwap) {
39789
- newValue = clamp$6(newValue, values3[activeIndex - 1] || -Infinity, values3[activeIndex + 1] || Infinity);
39797
+ newValue = clamp$7(newValue, values3[activeIndex - 1] || -Infinity, values3[activeIndex + 1] || Infinity);
39790
39798
  }
39791
39799
  const previousValue = newValue;
39792
39800
  newValue = setValueIndex({
@@ -47547,7 +47555,7 @@ function localStorageAvailable() {
47547
47555
  function escapeRegExp(value2) {
47548
47556
  return value2.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
47549
47557
  }
47550
- const clamp$5 = (value2, min2, max2) => Math.max(min2, Math.min(max2, value2));
47558
+ const clamp$6 = (value2, min2, max2) => Math.max(min2, Math.min(max2, value2));
47551
47559
  function range$c(from2, to) {
47552
47560
  return Array.from({
47553
47561
  length: to - from2
@@ -51253,7 +51261,7 @@ const hydrateColumnsWidth = (rawState, dimensions) => {
51253
51261
  totalFlexUnits += column2.flex;
51254
51262
  isFlex = true;
51255
51263
  } else {
51256
- computedWidth = clamp$5(column2.width || GRID_STRING_COL_DEF.width, column2.minWidth || GRID_STRING_COL_DEF.minWidth, column2.maxWidth || GRID_STRING_COL_DEF.maxWidth);
51264
+ computedWidth = clamp$6(column2.width || GRID_STRING_COL_DEF.width, column2.minWidth || GRID_STRING_COL_DEF.minWidth, column2.maxWidth || GRID_STRING_COL_DEF.maxWidth);
51257
51265
  }
51258
51266
  widthAllocatedBeforeFlex += computedWidth;
51259
51267
  }
@@ -51853,8 +51861,8 @@ const useGridVirtualScroller = () => {
51853
51861
  const maxScrollTop = Math.ceil(dimensions.minimumSize.height - dimensions.viewportOuterSize.height);
51854
51862
  const maxScrollLeft = Math.ceil(dimensions.minimumSize.width - dimensions.viewportInnerSize.width);
51855
51863
  const newScroll = {
51856
- top: clamp$5(scroller.scrollTop, 0, maxScrollTop),
51857
- left: isRtl ? clamp$5(scroller.scrollLeft, -maxScrollLeft, 0) : clamp$5(scroller.scrollLeft, 0, maxScrollLeft)
51864
+ top: clamp$6(scroller.scrollTop, 0, maxScrollTop),
51865
+ left: isRtl ? clamp$6(scroller.scrollLeft, -maxScrollLeft, 0) : clamp$6(scroller.scrollLeft, 0, maxScrollLeft)
51858
51866
  };
51859
51867
  const dx = newScroll.left - scrollPosition.current.left;
51860
51868
  const dy = newScroll.top - scrollPosition.current.top;
@@ -52292,7 +52300,7 @@ function getNearestIndexToRender(inputs, offset2, options) {
52292
52300
  if (inputs.range?.lastRowIndex && !allRowsMeasured) {
52293
52301
  allRowsMeasured = lastMeasuredIndexRelativeToAllRows >= inputs.range.lastRowIndex;
52294
52302
  }
52295
- const lastMeasuredIndexRelativeToCurrentPage = clamp$5(lastMeasuredIndexRelativeToAllRows - (inputs.range?.firstRowIndex || 0), 0, inputs.rowsMeta.positions.length);
52303
+ const lastMeasuredIndexRelativeToCurrentPage = clamp$6(lastMeasuredIndexRelativeToAllRows - (inputs.range?.firstRowIndex || 0), 0, inputs.rowsMeta.positions.length);
52296
52304
  if (allRowsMeasured || inputs.rowsMeta.positions[lastMeasuredIndexRelativeToCurrentPage] >= offset2) {
52297
52305
  return binarySearch$2(offset2, inputs.rowsMeta.positions, options);
52298
52306
  }
@@ -52376,7 +52384,7 @@ function getIndexesToRender({
52376
52384
  lastPosition: positions[positions.length - 1] + lastSize
52377
52385
  });
52378
52386
  const lastIndexPadded = binarySearch$2(lastPosition, positions);
52379
- return [clamp$5(firstIndexPadded, minFirstIndex, maxLastIndex), clamp$5(lastIndexPadded, minFirstIndex, maxLastIndex)];
52387
+ return [clamp$6(firstIndexPadded, minFirstIndex, maxLastIndex), clamp$6(lastIndexPadded, minFirstIndex, maxLastIndex)];
52380
52388
  }
52381
52389
  function areRenderContextsEqual(context1, context2) {
52382
52390
  if (context1 === context2) {
@@ -61955,7 +61963,7 @@ const useGridFocus = (apiRef, props) => {
61955
61963
  columnIndexToFocus = visibleColumns.length - 1;
61956
61964
  }
61957
61965
  }
61958
- rowIndexToFocus = clamp$5(rowIndexToFocus, 0, currentPageRows.length - 1);
61966
+ rowIndexToFocus = clamp$6(rowIndexToFocus, 0, currentPageRows.length - 1);
61959
61967
  const rowToFocus = currentPageRows[rowIndexToFocus];
61960
61968
  if (!rowToFocus) {
61961
61969
  return;
@@ -61968,7 +61976,7 @@ const useGridFocus = (apiRef, props) => {
61968
61976
  columnIndexToFocus = colSpanInfo.rightVisibleCellIndex;
61969
61977
  }
61970
61978
  }
61971
- columnIndexToFocus = clamp$5(columnIndexToFocus, 0, visibleColumns.length - 1);
61979
+ columnIndexToFocus = clamp$6(columnIndexToFocus, 0, visibleColumns.length - 1);
61972
61980
  const columnToFocus = visibleColumns[columnIndexToFocus];
61973
61981
  apiRef.current.setCellFocus(rowToFocus.id, columnToFocus.field);
61974
61982
  }, [apiRef, props.pagination, props.paginationMode]);
@@ -62081,7 +62089,7 @@ const useGridFocus = (apiRef, props) => {
62081
62089
  pagination: props.pagination,
62082
62090
  paginationMode: props.paginationMode
62083
62091
  });
62084
- const nextRow = currentPage.rows[clamp$5(lastFocusedRowIndex, 0, currentPage.rows.length - 1)];
62092
+ const nextRow = currentPage.rows[clamp$6(lastFocusedRowIndex, 0, currentPage.rows.length - 1)];
62085
62093
  nextRowId = nextRow?.id ?? null;
62086
62094
  }
62087
62095
  apiRef.current.setState((state) => _extends$c({}, state, {
@@ -66434,7 +66442,7 @@ function extractColumnWidths(apiRef, options, columns2) {
66434
66442
  const min2 = hasColumnMin ? column2.minWidth : 0;
66435
66443
  const max2 = hasColumnMax ? column2.maxWidth : Infinity;
66436
66444
  const maxContent = filteredWidths.length === 0 ? 0 : Math.max(...filteredWidths);
66437
- widthByField[column2.field] = clamp$5(maxContent, min2, max2);
66445
+ widthByField[column2.field] = clamp$6(maxContent, min2, max2);
66438
66446
  });
66439
66447
  root2.classList.remove(gridClasses.autosizing);
66440
66448
  return widthByField;
@@ -66590,7 +66598,7 @@ const useGridColumnResize = (apiRef, props) => {
66590
66598
  return;
66591
66599
  }
66592
66600
  let newWidth = computeNewWidth(initialOffsetToSeparator.current, nativeEvent.clientX, refs.columnHeaderElement.getBoundingClientRect(), resizeDirection.current);
66593
- newWidth = clamp$5(newWidth, refs.colDef.minWidth, refs.colDef.maxWidth);
66601
+ newWidth = clamp$6(newWidth, refs.colDef.minWidth, refs.colDef.maxWidth);
66594
66602
  updateWidth(newWidth);
66595
66603
  const params2 = {
66596
66604
  element: refs.columnHeaderElement,
@@ -66616,7 +66624,7 @@ const useGridColumnResize = (apiRef, props) => {
66616
66624
  return;
66617
66625
  }
66618
66626
  let newWidth = computeNewWidth(initialOffsetToSeparator.current, finger.x, refs.columnHeaderElement.getBoundingClientRect(), resizeDirection.current);
66619
- newWidth = clamp$5(newWidth, refs.colDef.minWidth, refs.colDef.maxWidth);
66627
+ newWidth = clamp$6(newWidth, refs.colDef.minWidth, refs.colDef.maxWidth);
66620
66628
  updateWidth(newWidth);
66621
66629
  const params2 = {
66622
66630
  element: refs.columnHeaderElement,
@@ -115185,7 +115193,7 @@ function acos$4(radians2, result) {
115185
115193
  function atan$3(radians2, result) {
115186
115194
  return map$3(radians2, (angle2) => Math.atan(angle2), result);
115187
115195
  }
115188
- function clamp$4(value2, min2, max2) {
115196
+ function clamp$5(value2, min2, max2) {
115189
115197
  return map$3(value2, (value3) => Math.max(min2, Math.min(max2, value3)));
115190
115198
  }
115191
115199
  function lerp$8(a2, b2, t4) {
@@ -118155,7 +118163,7 @@ class SphericalCoordinates {
118155
118163
  this.radius = length$5(v);
118156
118164
  if (this.radius > 0) {
118157
118165
  this.theta = Math.atan2(v[0], v[1]);
118158
- this.phi = Math.acos(clamp$4(v[2] / this.radius, -1, 1));
118166
+ this.phi = Math.acos(clamp$5(v[2] / this.radius, -1, 1));
118159
118167
  }
118160
118168
  return this.check();
118161
118169
  }
@@ -118410,7 +118418,7 @@ class Euler extends MathArray {
118410
118418
  order2 = order2 || this[3];
118411
118419
  switch (order2) {
118412
118420
  case Euler.XYZ:
118413
- this[1] = Math.asin(clamp$4(m13, -1, 1));
118421
+ this[1] = Math.asin(clamp$5(m13, -1, 1));
118414
118422
  if (Math.abs(m13) < ALMOST_ONE) {
118415
118423
  this[0] = Math.atan2(-m23, m33);
118416
118424
  this[2] = Math.atan2(-m12, m11);
@@ -118420,7 +118428,7 @@ class Euler extends MathArray {
118420
118428
  }
118421
118429
  break;
118422
118430
  case Euler.YXZ:
118423
- this[0] = Math.asin(-clamp$4(m23, -1, 1));
118431
+ this[0] = Math.asin(-clamp$5(m23, -1, 1));
118424
118432
  if (Math.abs(m23) < ALMOST_ONE) {
118425
118433
  this[1] = Math.atan2(m13, m33);
118426
118434
  this[2] = Math.atan2(m21, m22);
@@ -118430,7 +118438,7 @@ class Euler extends MathArray {
118430
118438
  }
118431
118439
  break;
118432
118440
  case Euler.ZXY:
118433
- this[0] = Math.asin(clamp$4(m32, -1, 1));
118441
+ this[0] = Math.asin(clamp$5(m32, -1, 1));
118434
118442
  if (Math.abs(m32) < ALMOST_ONE) {
118435
118443
  this[1] = Math.atan2(-m31, m33);
118436
118444
  this[2] = Math.atan2(-m12, m22);
@@ -118440,7 +118448,7 @@ class Euler extends MathArray {
118440
118448
  }
118441
118449
  break;
118442
118450
  case Euler.ZYX:
118443
- this[1] = Math.asin(-clamp$4(m31, -1, 1));
118451
+ this[1] = Math.asin(-clamp$5(m31, -1, 1));
118444
118452
  if (Math.abs(m31) < ALMOST_ONE) {
118445
118453
  this[0] = Math.atan2(m32, m33);
118446
118454
  this[2] = Math.atan2(m21, m11);
@@ -118450,7 +118458,7 @@ class Euler extends MathArray {
118450
118458
  }
118451
118459
  break;
118452
118460
  case Euler.YZX:
118453
- this[2] = Math.asin(clamp$4(m21, -1, 1));
118461
+ this[2] = Math.asin(clamp$5(m21, -1, 1));
118454
118462
  if (Math.abs(m21) < ALMOST_ONE) {
118455
118463
  this[0] = Math.atan2(-m23, m22);
118456
118464
  this[1] = Math.atan2(-m31, m11);
@@ -118460,7 +118468,7 @@ class Euler extends MathArray {
118460
118468
  }
118461
118469
  break;
118462
118470
  case Euler.XZY:
118463
- this[2] = Math.asin(-clamp$4(m12, -1, 1));
118471
+ this[2] = Math.asin(-clamp$5(m12, -1, 1));
118464
118472
  if (Math.abs(m12) < ALMOST_ONE) {
118465
118473
  this[0] = Math.atan2(m32, m22);
118466
118474
  this[1] = Math.atan2(m13, m11);
@@ -121604,7 +121612,7 @@ function mod$2(value2, divisor) {
121604
121612
  function lerp$3(start2, end2, step) {
121605
121613
  return step * end2 + (1 - step) * start2;
121606
121614
  }
121607
- function clamp$3(x2, min2, max2) {
121615
+ function clamp$4(x2, min2, max2) {
121608
121616
  return x2 < min2 ? min2 : x2 > max2 ? max2 : x2;
121609
121617
  }
121610
121618
  function ieLog2(x2) {
@@ -121750,7 +121758,7 @@ function getProjectionParameters(options) {
121750
121758
  cameraToSeaLevelDistance += center2[2] * scale2 / Math.cos(pitchRadians) / height2;
121751
121759
  }
121752
121760
  const fovAboveCenter = fovRadians * (0.5 + (offset2 ? offset2[1] : 0) / height2);
121753
- const topHalfSurfaceDistance = Math.sin(fovAboveCenter) * cameraToSeaLevelDistance / Math.sin(clamp$3(Math.PI / 2 - pitchRadians - fovAboveCenter, 0.01, Math.PI - 0.01));
121761
+ const topHalfSurfaceDistance = Math.sin(fovAboveCenter) * cameraToSeaLevelDistance / Math.sin(clamp$4(Math.PI / 2 - pitchRadians - fovAboveCenter, 0.01, Math.PI - 0.01));
121754
121762
  const furthestDistance = Math.sin(pitchRadians) * topHalfSurfaceDistance + cameraToSeaLevelDistance;
121755
121763
  const horizonDistance = cameraToSeaLevelDistance * 10;
121756
121764
  const farZ = Math.min(furthestDistance * farZMultiplier, horizonDistance);
@@ -121808,8 +121816,8 @@ function fitBounds(options) {
121808
121816
  } = options;
121809
121817
  const [[west, south], [east, north]] = bounds2;
121810
121818
  const padding2 = getPaddingObject(options.padding);
121811
- const nw = lngLatToWorld([west, clamp$3(north, -MAX_LATITUDE, MAX_LATITUDE)]);
121812
- const se = lngLatToWorld([east, clamp$3(south, -MAX_LATITUDE, MAX_LATITUDE)]);
121819
+ const nw = lngLatToWorld([west, clamp$4(north, -MAX_LATITUDE, MAX_LATITUDE)]);
121820
+ const se = lngLatToWorld([east, clamp$4(south, -MAX_LATITUDE, MAX_LATITUDE)]);
121813
121821
  const size2 = [Math.max(Math.abs(se[0] - nw[0]), minExtent), Math.max(Math.abs(se[1] - nw[1]), minExtent)];
121814
121822
  const targetSize = [width2 - padding2.left - padding2.right - Math.abs(offset2[0]) * 2, height2 - padding2.top - padding2.bottom - Math.abs(offset2[1]) * 2];
121815
121823
  assert$b(targetSize[0] > 0 && targetSize[1] > 0);
@@ -123099,8 +123107,8 @@ function createProjectionMatrix({
123099
123107
  top: top2 = 0,
123100
123108
  bottom: bottom2 = 0
123101
123109
  } = padding2;
123102
- const offsetX = clamp$4((left2 + width2 - right2) / 2, 0, width2) - width2 / 2;
123103
- const offsetY = clamp$4((top2 + height2 - bottom2) / 2, 0, height2) - height2 / 2;
123110
+ const offsetX = clamp$5((left2 + width2 - right2) / 2, 0, width2) - width2 / 2;
123111
+ const offsetY = clamp$5((top2 + height2 - bottom2) / 2, 0, height2) - height2 / 2;
123104
123112
  matrix2[8] -= offsetX * 2 / width2;
123105
123113
  matrix2[9] += offsetY * 2 / height2;
123106
123114
  }
@@ -123215,7 +123223,7 @@ class Viewport {
123215
123223
  projectFlat(xyz) {
123216
123224
  if (this.isGeospatial) {
123217
123225
  const result = lngLatToWorld(xyz);
123218
- result[1] = clamp$4(result[1], -318, 830);
123226
+ result[1] = clamp$5(result[1], -318, 830);
123219
123227
  return result;
123220
123228
  }
123221
123229
  return xyz;
@@ -125932,7 +125940,7 @@ class MapState extends ViewState {
125932
125940
  minZoom
125933
125941
  } = this.getViewportProps();
125934
125942
  let zoom2 = startZoom + Math.log2(scale2);
125935
- zoom2 = clamp$4(zoom2, minZoom, maxZoom);
125943
+ zoom2 = clamp$5(zoom2, minZoom, maxZoom);
125936
125944
  const zoomedViewport = this.makeViewport({
125937
125945
  ...this.getViewportProps(),
125938
125946
  zoom: zoom2
@@ -126009,13 +126017,13 @@ class MapState extends ViewState {
126009
126017
  minZoom,
126010
126018
  zoom: zoom2
126011
126019
  } = props;
126012
- props.zoom = clamp$4(zoom2, minZoom, maxZoom);
126020
+ props.zoom = clamp$5(zoom2, minZoom, maxZoom);
126013
126021
  const {
126014
126022
  maxPitch,
126015
126023
  minPitch,
126016
126024
  pitch
126017
126025
  } = props;
126018
- props.pitch = clamp$4(pitch, minPitch, maxPitch);
126026
+ props.pitch = clamp$5(pitch, minPitch, maxPitch);
126019
126027
  const {
126020
126028
  normalize: normalize2 = true
126021
126029
  } = props;
@@ -126076,7 +126084,7 @@ class MapState extends ViewState {
126076
126084
  deltaScaleY = 1 - centerY / startY;
126077
126085
  }
126078
126086
  }
126079
- deltaScaleY = clamp$4(deltaScaleY, -1, 1);
126087
+ deltaScaleY = clamp$5(deltaScaleY, -1, 1);
126080
126088
  const {
126081
126089
  minPitch,
126082
126090
  maxPitch
@@ -126205,8 +126213,8 @@ function getProjectionMatrix({
126205
126213
  top: t4 = 0,
126206
126214
  bottom: b2 = 0
126207
126215
  } = padding2;
126208
- const offsetX = clamp$4((l2 + width2 - r3) / 2, 0, width2) - width2 / 2;
126209
- const offsetY = clamp$4((t4 + height2 - b2) / 2, 0, height2) - height2 / 2;
126216
+ const offsetX = clamp$5((l2 + width2 - r3) / 2, 0, width2) - width2 / 2;
126217
+ const offsetY = clamp$5((t4 + height2 - b2) / 2, 0, height2) - height2 / 2;
126210
126218
  left2 -= offsetX;
126211
126219
  right2 -= offsetX;
126212
126220
  bottom2 += offsetY;
@@ -126519,7 +126527,7 @@ class OrbitState extends ViewState {
126519
126527
  startZoom = this.getViewportProps().zoom;
126520
126528
  }
126521
126529
  const zoom2 = startZoom + Math.log2(scale2);
126522
- return clamp$4(zoom2, minZoom, maxZoom);
126530
+ return clamp$5(zoom2, minZoom, maxZoom);
126523
126531
  }
126524
126532
  _panFromCenter(offset2) {
126525
126533
  const {
@@ -126549,8 +126557,8 @@ class OrbitState extends ViewState {
126549
126557
  minRotationX,
126550
126558
  rotationOrbit
126551
126559
  } = props;
126552
- props.zoom = Array.isArray(zoom2) ? [clamp$4(zoom2[0], minZoom, maxZoom), clamp$4(zoom2[1], minZoom, maxZoom)] : clamp$4(zoom2, minZoom, maxZoom);
126553
- props.rotationX = clamp$4(props.rotationX, minRotationX, maxRotationX);
126560
+ props.zoom = Array.isArray(zoom2) ? [clamp$5(zoom2[0], minZoom, maxZoom), clamp$5(zoom2[1], minZoom, maxZoom)] : clamp$5(zoom2, minZoom, maxZoom);
126561
+ props.rotationX = clamp$5(props.rotationX, minRotationX, maxRotationX);
126554
126562
  if (rotationOrbit < -180 || rotationOrbit > 180) {
126555
126563
  props.rotationOrbit = mod$1(rotationOrbit + 180, 360) - 180;
126556
126564
  }
@@ -126594,10 +126602,10 @@ class OrthographicState extends OrbitState {
126594
126602
  let [newZoomX, newZoomY] = startZoom;
126595
126603
  switch (this.zoomAxis) {
126596
126604
  case "X":
126597
- newZoomX = clamp$4(newZoomX + deltaZoom, minZoom, maxZoom);
126605
+ newZoomX = clamp$5(newZoomX + deltaZoom, minZoom, maxZoom);
126598
126606
  break;
126599
126607
  case "Y":
126600
- newZoomY = clamp$4(newZoomY + deltaZoom, minZoom, maxZoom);
126608
+ newZoomY = clamp$5(newZoomY + deltaZoom, minZoom, maxZoom);
126601
126609
  break;
126602
126610
  default:
126603
126611
  let z2 = Math.min(newZoomX + deltaZoom, newZoomY + deltaZoom);
@@ -126613,7 +126621,7 @@ class OrthographicState extends OrbitState {
126613
126621
  }
126614
126622
  return [newZoomX, newZoomY];
126615
126623
  }
126616
- return clamp$4(startZoom + deltaZoom, minZoom, maxZoom);
126624
+ return clamp$5(startZoom + deltaZoom, minZoom, maxZoom);
126617
126625
  }
126618
126626
  }
126619
126627
  class OrthographicController extends Controller {
@@ -135352,7 +135360,7 @@ class FirstPersonState extends ViewState {
135352
135360
  longitude: longitude2,
135353
135361
  bearing
135354
135362
  } = props;
135355
- props.pitch = clamp$4(pitch, minPitch, maxPitch);
135363
+ props.pitch = clamp$5(pitch, minPitch, maxPitch);
135356
135364
  if (longitude2 !== null && (longitude2 < -180 || longitude2 > 180)) {
135357
135365
  props.longitude = mod$1(longitude2 + 180, 360) - 180;
135358
135366
  }
@@ -135401,7 +135409,7 @@ class GlobeState extends MapState {
135401
135409
  minZoom,
135402
135410
  zoom: zoom2
135403
135411
  } = props;
135404
- props.zoom = clamp$4(zoom2, minZoom, maxZoom);
135412
+ props.zoom = clamp$5(zoom2, minZoom, maxZoom);
135405
135413
  const {
135406
135414
  longitude: longitude2,
135407
135415
  latitude
@@ -135409,7 +135417,7 @@ class GlobeState extends MapState {
135409
135417
  if (longitude2 < -180 || longitude2 > 180) {
135410
135418
  props.longitude = mod$1(longitude2 + 180, 360) - 180;
135411
135419
  }
135412
- props.latitude = clamp$4(latitude, -89, 89);
135420
+ props.latitude = clamp$5(latitude, -89, 89);
135413
135421
  return props;
135414
135422
  }
135415
135423
  }
@@ -143056,7 +143064,7 @@ function getQuantileDomain(data2, valueAccessor) {
143056
143064
  function getOrdinalDomain(data2, valueAccessor) {
143057
143065
  return unique$1(getTruthyValues(data2, valueAccessor));
143058
143066
  }
143059
- function clamp$2(value2, min2, max2) {
143067
+ function clamp$3(value2, min2, max2) {
143060
143068
  return Math.max(min2, Math.min(max2, value2));
143061
143069
  }
143062
143070
  const defaultGetValue = (points2) => points2.length;
@@ -143117,7 +143125,7 @@ class BinSorter {
143117
143125
  if (len2 < 2) {
143118
143126
  return [0, 0];
143119
143127
  }
143120
- const [lower2, upper] = percentileRange.map((n3) => clamp$2(n3, 0, 100));
143128
+ const [lower2, upper] = percentileRange.map((n3) => clamp$3(n3, 0, 100));
143121
143129
  const lowerIdx = Math.ceil(lower2 / 100 * (len2 - 1));
143122
143130
  const upperIdx = Math.floor(upper / 100 * (len2 - 1));
143123
143131
  return [lowerIdx, upperIdx];
@@ -165911,7 +165919,7 @@ new Vector3();
165911
165919
  new Vector2();
165912
165920
  new Vector2();
165913
165921
  function fromSNorm(value2, rangeMaximum = 255) {
165914
- return clamp$4(value2, 0, rangeMaximum) / rangeMaximum * 2 - 1;
165922
+ return clamp$5(value2, 0, rangeMaximum) / rangeMaximum * 2 - 1;
165915
165923
  }
165916
165924
  function signNotZero(value2) {
165917
165925
  return value2 < 0 ? -1 : 1;
@@ -205028,7 +205036,7 @@ const esm = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty(
205028
205036
  asin: asin$5,
205029
205037
  assert: assert$c,
205030
205038
  atan: atan$3,
205031
- clamp: clamp$4,
205039
+ clamp: clamp$5,
205032
205040
  clone: clone$5,
205033
205041
  config: config$3,
205034
205042
  configure,
@@ -209457,22 +209465,22 @@ async function getDecoder(fileDirectory) {
209457
209465
  const Decoder = await importFn();
209458
209466
  return new Decoder(fileDirectory);
209459
209467
  }
209460
- addDecoder([void 0, 1], () => import("./raw-BKulPvK3.js").then((m2) => m2.default));
209461
- addDecoder(5, () => import("./lzw-lK2xDQPh.js").then((m2) => m2.default));
209468
+ addDecoder([void 0, 1], () => import("./raw-BLQKlp_4.js").then((m2) => m2.default));
209469
+ addDecoder(5, () => import("./lzw-hla-j59h.js").then((m2) => m2.default));
209462
209470
  addDecoder(6, () => {
209463
209471
  throw new Error("old style JPEG compression is not supported.");
209464
209472
  });
209465
- addDecoder(7, () => import("./jpeg-pIveo5qm.js").then((m2) => m2.default));
209466
- addDecoder([8, 32946], () => import("./deflate-B35gUGrI.js").then((m2) => m2.default));
209467
- addDecoder(32773, () => import("./packbits-Ds8BMewq.js").then((m2) => m2.default));
209473
+ addDecoder(7, () => import("./jpeg-_87xUwY6.js").then((m2) => m2.default));
209474
+ addDecoder([8, 32946], () => import("./deflate-E8TfyvM7.js").then((m2) => m2.default));
209475
+ addDecoder(32773, () => import("./packbits-C8umOnfG.js").then((m2) => m2.default));
209468
209476
  addDecoder(
209469
209477
  34887,
209470
- () => import("./lerc-DEzmYyQ_.js").then(async (m2) => {
209478
+ () => import("./lerc-DFl9HcRa.js").then(async (m2) => {
209471
209479
  await m2.zstd.init();
209472
209480
  return m2;
209473
209481
  }).then((m2) => m2.default)
209474
209482
  );
209475
- addDecoder(50001, () => import("./webimage-BnK9oxcF.js").then((m2) => m2.default));
209483
+ addDecoder(50001, () => import("./webimage-nk5eMN68.js").then((m2) => m2.default));
209476
209484
  function copyNewSize(array2, width2, height2, samplesPerPixel = 1) {
209477
209485
  return new (Object.getPrototypeOf(array2)).constructor(width2 * height2 * samplesPerPixel);
209478
209486
  }
@@ -226328,7 +226336,7 @@ function ToolMenu(props) {
226328
226336
  return jsxs("div", { className: classes2.tool, children: [visibleTools.pan && jsx$1(IconTool, { alt: pointerIconAltText, onClick: () => setActiveTool(null), isActive: activeTool === null, children: jsx$1(SvgNearMe, {}) }), visibleTools.selectLasso ? jsx$1(IconTool, { alt: lassoIconAltText, onClick: () => setActiveTool(distEs6Exports$2.SELECTION_TYPE.POLYGON), isActive: activeTool === distEs6Exports$2.SELECTION_TYPE.POLYGON, children: jsx$1(SvgSelectionLasso, {}) }) : null, visibleTools.recenter ? jsx$1(IconButton, { alt: "click to recenter", onClick: () => onRecenterButtonCLick(), "aria-label": "Recenter scatterplot view", children: jsx$1(CenterFocusStrong, {}) }) : null] });
226329
226337
  }
226330
226338
  const getCursorWithTool = () => "crosshair";
226331
- const getCursor = (interactionState) => interactionState.isDragging ? "grabbing" : "default";
226339
+ const getCursor = (interactionState) => interactionState.isDragging ? "grabbing" : "grab";
226332
226340
  function getOnHoverCallback(obsIndex, setObsHighlight, setComponentHover) {
226333
226341
  return (info2) => {
226334
226342
  if (setComponentHover) {
@@ -226693,7 +226701,7 @@ const BASE_POINT_SIZE = 5;
226693
226701
  const LARGE_DATASET_CELL_COUNT = 1e4;
226694
226702
  const SMALL_DATASET_CELL_COUNT = 100;
226695
226703
  function getInitialPointSize(numCells = LARGE_DATASET_CELL_COUNT) {
226696
- return BASE_POINT_SIZE / clamp$7(numCells, SMALL_DATASET_CELL_COUNT, LARGE_DATASET_CELL_COUNT);
226704
+ return BASE_POINT_SIZE / clamp$8(numCells, SMALL_DATASET_CELL_COUNT, LARGE_DATASET_CELL_COUNT);
226697
226705
  }
226698
226706
  function getPointSizeDevicePixels(devicePixelRatio2, zoom2, xRange, yRange, width2, height2, numCells) {
226699
226707
  const pointSize = getInitialPointSize(numCells);
@@ -226706,7 +226714,7 @@ function getPointSizeDevicePixels(devicePixelRatio2, zoom2, xRange, yRange, widt
226706
226714
  const diagonalAxisRange = Math.sqrt(xAxisRange ** 2 + yAxisRange ** 2);
226707
226715
  const diagonalFraction = pointSize / diagonalAxisRange;
226708
226716
  const deviceSize = diagonalFraction * diagonalScreenSize;
226709
- const pointSizeDevicePixels = clamp$7(deviceSize, pointScreenSizeMin, pointScreenSizeMax);
226717
+ const pointSizeDevicePixels = clamp$8(deviceSize, pointScreenSizeMin, pointScreenSizeMax);
226710
226718
  return pointSizeDevicePixels;
226711
226719
  }
226712
226720
  function getPointOpacity(zoom2, xRange, yRange, width2, height2, numCells, avgFillDensity) {
@@ -226735,7 +226743,7 @@ function getPointOpacity(zoom2, xRange, yRange, width2, height2, numCells, avgFi
226735
226743
  rho = Math.min(1, 1 / 10 ** (Math.log10(N2) - 3));
226736
226744
  }
226737
226745
  const alpha2 = rho * W * H / N2 * (Y02 / Y3) * (X02 / X3);
226738
- const pointOpacity = clamp$7(alpha2, 1.01 / 255, 1);
226746
+ const pointOpacity = clamp$8(alpha2, 1.01 / 255, 1);
226739
226747
  return pointOpacity;
226740
226748
  }
226741
226749
  const CELLS_LAYER_ID$1 = "scatterplot";
@@ -227351,7 +227359,7 @@ typeof SuppressedError === "function" ? SuppressedError : function(error2, suppr
227351
227359
  var e3 = new Error(message);
227352
227360
  return e3.name = "SuppressedError", e3.error = error2, e3.suppressed = suppressed, e3;
227353
227361
  };
227354
- const FEATURE_AGGREGATION_STRATEGIES$1 = ["first", "last", "sum", "mean"];
227362
+ const FEATURE_AGGREGATION_STRATEGIES$2 = ["first", "last", "sum", "mean"];
227355
227363
  function ScatterplotOptions(props) {
227356
227364
  const { children: children3, observationsLabel, cellRadius, setCellRadius, cellRadiusMode, setCellRadiusMode, cellOpacity, setCellOpacity, cellOpacityMode, setCellOpacityMode, cellSetLabelsVisible, setCellSetLabelsVisible, tooltipsVisible, setTooltipsVisible, cellSetLabelSize, setCellSetLabelSize, cellSetPolygonsVisible, setCellSetPolygonsVisible, cellColorEncoding, setCellColorEncoding, geneExpressionColormap, setGeneExpressionColormap, geneExpressionColormapRange, setGeneExpressionColormapRange, embeddingPointsVisible, setEmbeddingPointsVisible, embeddingContoursVisible, setEmbeddingContoursVisible, embeddingContoursFilled, setEmbeddingContoursFilled, contourPercentiles, setContourPercentiles, defaultContourPercentiles, contourColorEncoding, setContourColorEncoding, featureAggregationStrategy, setFeatureAggregationStrategy } = props;
227357
227365
  const scatterplotOptionsId = $bdb11010cef70236$export$f680877a34711e37();
@@ -227476,7 +227484,7 @@ function ScatterplotOptions(props) {
227476
227484
  return "Scatterplot sliders for contour percentile thresholds";
227477
227485
  }, id: `scatterplot-contour-percentiles-${scatterplotOptionsId}`, valueLabelDisplay: "auto", step: 5e-3, min: 9e-3, max: 0.999 }) })] }), setFeatureAggregationStrategy ? jsxs(TableRow, { children: [jsx$1(TableCell, { className: classes2.labelCell, variant: "head", scope: "row", children: jsx$1("label", { htmlFor: `feature-aggregation-strategy-${scatterplotOptionsId}`, children: "Feature Aggregation Strategy" }) }), jsx$1(TableCell, { className: classes2.inputCell, variant: "body", children: jsx$1(OptionSelect, { className: classes2.select, value: featureAggregationStrategy ?? "first", onChange: handleFeatureAggregationStrategyChange, inputProps: {
227478
227486
  id: `feature-aggregation-strategy-${scatterplotOptionsId}`
227479
- }, children: FEATURE_AGGREGATION_STRATEGIES$1.map((opt) => jsx$1("option", { value: opt, children: capitalize$3(opt) }, opt)) }) })] }) : null] });
227487
+ }, children: FEATURE_AGGREGATION_STRATEGIES$2.map((opt) => jsx$1("option", { value: opt, children: capitalize$3(opt) }, opt)) }) })] }) : null] });
227480
227488
  }
227481
227489
  const useStyles$s = makeStyles()((theme) => ({
227482
227490
  tooltipAnchor: {
@@ -232148,7 +232156,7 @@ function ChannelNamesLegend(props) {
232148
232156
  }) : null });
232149
232157
  }
232150
232158
  const DEFAULT_CONTOUR_PERCENTILES = [0.09, 0.9, 0.99];
232151
- const DEFAULT_FEATURE_AGGREGATION_STRATEGY$2 = "first";
232159
+ const DEFAULT_FEATURE_AGGREGATION_STRATEGY$3 = "first";
232152
232160
  function EmbeddingScatterplotSubscriber(props) {
232153
232161
  const {
232154
232162
  uuid: uuid2,
@@ -232175,7 +232183,7 @@ function EmbeddingScatterplotSubscriber(props) {
232175
232183
  const { embeddingZoom: initialZoom, embeddingTargetX: initialTargetX, embeddingTargetY: initialTargetY } = useInitialCoordination(COMPONENT_COORDINATION_TYPES[ViewType$1.SCATTERPLOT], coordinationScopes);
232176
232184
  const observationsLabel = observationsLabelOverride || obsType;
232177
232185
  const sampleSetSelection = sampleSetSelectionFromProps || sampleSetSelectionFromCoordination;
232178
- const featureAggregationStrategyToUse = featureAggregationStrategy ?? DEFAULT_FEATURE_AGGREGATION_STRATEGY$2;
232186
+ const featureAggregationStrategyToUse = featureAggregationStrategy ?? DEFAULT_FEATURE_AGGREGATION_STRATEGY$3;
232179
232187
  const [width2, height2, deckRef] = useDeckCanvasSize();
232180
232188
  const title2 = titleOverride || `Scatterplot (${mapping})`;
232181
232189
  const [
@@ -236847,7 +236855,7 @@ function cbrt(x2) {
236847
236855
  function ceil$2(x2) {
236848
236856
  return finalise(x2 = new this(x2), x2.e + 1, 2);
236849
236857
  }
236850
- function clamp$1(x2, min2, max2) {
236858
+ function clamp$2(x2, min2, max2) {
236851
236859
  return new this(x2).clamp(min2, max2);
236852
236860
  }
236853
236861
  function config$1(obj) {
@@ -237018,7 +237026,7 @@ function clone$1(obj) {
237018
237026
  Decimal3.atan2 = atan2$2;
237019
237027
  Decimal3.cbrt = cbrt;
237020
237028
  Decimal3.ceil = ceil$2;
237021
- Decimal3.clamp = clamp$1;
237029
+ Decimal3.clamp = clamp$2;
237022
237030
  Decimal3.cos = cos$3;
237023
237031
  Decimal3.cosh = cosh;
237024
237032
  Decimal3.div = div;
@@ -250939,6 +250947,16 @@ class RelaxedFetchStore extends FetchStore {
250939
250947
  throw e3;
250940
250948
  }
250941
250949
  }
250950
+ async getRange(key2, range2, options = {}) {
250951
+ try {
250952
+ return await super.getRange(key2, range2, options);
250953
+ } catch (e3) {
250954
+ if (e3?.message?.startsWith("Unexpected response status 403") && true) {
250955
+ return void 0;
250956
+ }
250957
+ throw e3;
250958
+ }
250959
+ }
250942
250960
  }
250943
250961
  function transformEntriesForZipFileStore(entries2) {
250944
250962
  const topLevelZarrDirectories = new Set(Object.keys(entries2).map((k) => k.split("/")[0]).filter((firstPathItem) => firstPathItem?.endsWith(".zarr")));
@@ -251848,7 +251866,8 @@ let Spatial$1 = class Spatial extends AbstractSpatialOrScatterplot {
251848
251866
  "expressionData",
251849
251867
  "cellColorEncoding",
251850
251868
  "geneExpressionColormap",
251851
- "segmentationLayerCallbacks"
251869
+ "segmentationLayerCallbacks",
251870
+ "getExpressionValue"
251852
251871
  ].some(shallowDiff2)) {
251853
251872
  this.onUpdateCellsLayer();
251854
251873
  forceUpdate = true;
@@ -251908,6 +251927,7 @@ const useToggleStyles = makeStyles()(() => ({
251908
251927
  padding: "0px"
251909
251928
  }
251910
251929
  }));
251930
+ const FEATURE_AGGREGATION_STRATEGIES$1 = ["first", "last", "sum", "mean"];
251911
251931
  const ToggleFixedAxisButton = ({ setSpatialAxisFixed, spatialAxisFixed, use3d }) => {
251912
251932
  const toggleAxisId = $bdb11010cef70236$export$f680877a34711e37();
251913
251933
  const { classes: classes2 } = useToggleStyles();
@@ -251917,7 +251937,7 @@ const ToggleFixedAxisButton = ({ setSpatialAxisFixed, spatialAxisFixed, use3d })
251917
251937
  } } }) })] });
251918
251938
  };
251919
251939
  function SpatialOptions(props) {
251920
- const { observationsLabel, cellColorEncoding, setCellColorEncoding, setSpatialAxisFixed, spatialAxisFixed, use3d, tooltipsVisible, setTooltipsVisible, geneExpressionColormap, setGeneExpressionColormap, geneExpressionColormapRange, setGeneExpressionColormapRange, canShowExpressionOptions, canShowColorEncodingOption, canShow3DOptions } = props;
251940
+ const { observationsLabel, cellColorEncoding, setCellColorEncoding, setSpatialAxisFixed, spatialAxisFixed, use3d, tooltipsVisible, setTooltipsVisible, geneExpressionColormap, setGeneExpressionColormap, geneExpressionColormapRange, setGeneExpressionColormapRange, canShowExpressionOptions, canShowColorEncodingOption, canShow3DOptions, featureAggregationStrategy, setFeatureAggregationStrategy } = props;
251921
251941
  const spatialOptionsId = $bdb11010cef70236$export$f680877a34711e37();
251922
251942
  function handleGeneExpressionColormapChange(event2) {
251923
251943
  setGeneExpressionColormap(event2.target.value);
@@ -251953,7 +251973,7 @@ function SpatialOptions(props) {
251953
251973
  }, value: geneExpressionColormapRange, onChange: handleColormapRangeChangeDebounced, getAriaLabel: (index2) => {
251954
251974
  const labelPrefix = index2 === 0 ? "Low value slider" : "High value slider";
251955
251975
  return `${labelPrefix} for spatial gene expression colormap range`;
251956
- }, id: `gene-expression-colormap-range-${spatialOptionsId}`, valueLabelDisplay: "auto", step: 5e-3, min: 0, max: 1 }) })] })] }) : null] });
251976
+ }, id: `gene-expression-colormap-range-${spatialOptionsId}`, valueLabelDisplay: "auto", step: 5e-3, min: 0, max: 1 }) })] }), setFeatureAggregationStrategy ? jsxs(TableRow, { children: [jsx$1(TableCell, { className: classes2.labelCell, variant: "head", scope: "row", children: jsx$1("label", { htmlFor: `feature-aggregation-strategy-${spatialOptionsId}`, children: "Feature Aggregation Strategy" }) }), jsx$1(TableCell, { className: classes2.inputCell, variant: "body", children: jsx$1(OptionSelect, { className: classes2.select, value: featureAggregationStrategy ?? "first", onChange: (e3) => setFeatureAggregationStrategy(e3.target.value), inputProps: { id: `feature-aggregation-strategy-${spatialOptionsId}` }, children: FEATURE_AGGREGATION_STRATEGIES$1.map((opt) => jsx$1("option", { value: opt, children: capitalize$3(opt) }, opt)) }) })] }) : null] }) : null] });
251957
251977
  }
251958
251978
  function SpatialTooltipSubscriber$1(props) {
251959
251979
  const { parentUuid, obsHighlight, width: width2, height: height2, getObsInfo: getObsInfo2, hoverData, hoverCoord, hoverMode, useHoverInfoForTooltip, getObsIdFromHoverData, featureType, featureLabelsMap } = props;
@@ -251985,12 +252005,13 @@ function SpatialTooltipSubscriber$1(props) {
251985
252005
  }
251986
252006
  return cellInfo ? jsx$1(Tooltip2D, { x: x2, y: y2, parentUuid, sourceUuid, parentWidth: width2, parentHeight: height2, children: jsx$1(TooltipContent, { info: cellInfo, featureType, featureLabelsMap }) }) : null;
251987
252007
  }
252008
+ const DEFAULT_FEATURE_AGGREGATION_STRATEGY$2 = "first";
251988
252009
  function SpatialSubscriber$1(props) {
251989
252010
  const { uuid: uuid2, coordinationScopes, closeButtonVisible, downloadButtonVisible, removeGridComponent, observationsLabelOverride, subobservationsLabelOverride: subobservationsLabel = "molecule", theme, title: title2 = "Spatial", disable3d, globalDisable3d, useFullResolutionImage = {}, channelNamesVisible = false, helpText = ViewHelpMapping.SPATIAL } = props;
251990
252011
  const loaders = useLoaders();
251991
252012
  const setComponentHover = useSetComponentHover();
251992
252013
  const setComponentViewInfo = useSetComponentViewInfo(uuid2);
251993
- const [{ dataset, obsType, featureType, featureValueType, spatialZoom: zoom2, spatialTargetX: targetX2, spatialTargetY: targetY2, spatialTargetZ: targetZ, spatialRotationX: rotationX, spatialRotationY: rotationY, spatialRotationZ: rotationZ, spatialRotationOrbit: rotationOrbit, spatialOrbitAxis: orbitAxis, spatialImageLayer: imageLayers, spatialSegmentationLayer: cellsLayer, spatialPointLayer: moleculesLayer, spatialNeighborhoodLayer: neighborhoodsLayer, obsFilter: cellFilter, obsHighlight: cellHighlight, moleculeHighlight, featureSelection: geneSelection, obsSetSelection: cellSetSelection, obsSetColor: cellSetColor, obsColorEncoding: cellColorEncoding, additionalObsSets: additionalCellSets, spatialAxisFixed, featureValueColormap: geneExpressionColormap, featureValueColormapRange: geneExpressionColormapRange, tooltipsVisible, photometricInterpretation: photometricInterpretationFromCoordination }, { setSpatialZoom: setZoom, setSpatialTargetX: setTargetX, setSpatialTargetY: setTargetY, setSpatialTargetZ: setTargetZ, setSpatialRotationX: setRotationX, setSpatialRotationOrbit: setRotationOrbit, setSpatialOrbitAxis: setOrbitAxis, setSpatialImageLayer: setRasterLayers, setSpatialSegmentationLayer: setCellsLayer, setSpatialPointLayer: setMoleculesLayer, setSpatialNeighborhoodLayer: setNeighborhoodsLayer, setObsFilter: setCellFilter, setObsSetSelection: setCellSetSelection, setObsHighlight: setCellHighlight, setObsSetColor: setCellSetColor, setObsColorEncoding: setCellColorEncoding, setAdditionalObsSets: setAdditionalCellSets, setMoleculeHighlight, setSpatialAxisFixed, setFeatureValueColormap: setGeneExpressionColormap, setFeatureValueColormapRange: setGeneExpressionColormapRange, setTooltipsVisible }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType$1.SPATIAL], coordinationScopes);
252014
+ const [{ dataset, obsType, featureType, featureValueType, spatialZoom: zoom2, spatialTargetX: targetX2, spatialTargetY: targetY2, spatialTargetZ: targetZ, spatialRotationX: rotationX, spatialRotationY: rotationY, spatialRotationZ: rotationZ, spatialRotationOrbit: rotationOrbit, spatialOrbitAxis: orbitAxis, spatialImageLayer: imageLayers, spatialSegmentationLayer: cellsLayer, spatialPointLayer: moleculesLayer, spatialNeighborhoodLayer: neighborhoodsLayer, obsFilter: cellFilter, obsHighlight: cellHighlight, moleculeHighlight, featureSelection: geneSelection, obsSetSelection: cellSetSelection, obsSetColor: cellSetColor, obsColorEncoding: cellColorEncoding, additionalObsSets: additionalCellSets, spatialAxisFixed, featureValueColormap: geneExpressionColormap, featureValueColormapRange: geneExpressionColormapRange, tooltipsVisible, photometricInterpretation: photometricInterpretationFromCoordination, featureAggregationStrategy }, { setSpatialZoom: setZoom, setSpatialTargetX: setTargetX, setSpatialTargetY: setTargetY, setSpatialTargetZ: setTargetZ, setSpatialRotationX: setRotationX, setSpatialRotationOrbit: setRotationOrbit, setSpatialOrbitAxis: setOrbitAxis, setSpatialImageLayer: setRasterLayers, setSpatialSegmentationLayer: setCellsLayer, setSpatialPointLayer: setMoleculesLayer, setSpatialNeighborhoodLayer: setNeighborhoodsLayer, setObsFilter: setCellFilter, setObsSetSelection: setCellSetSelection, setObsHighlight: setCellHighlight, setObsSetColor: setCellSetColor, setObsColorEncoding: setCellColorEncoding, setAdditionalObsSets: setAdditionalCellSets, setMoleculeHighlight, setSpatialAxisFixed, setFeatureValueColormap: setGeneExpressionColormap, setFeatureValueColormapRange: setGeneExpressionColormapRange, setTooltipsVisible, setFeatureAggregationStrategy }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType$1.SPATIAL], coordinationScopes);
251994
252015
  const { spatialZoom: initialZoom, spatialTargetX: initialTargetX, spatialTargetY: initialTargetY, spatialTargetZ: initialTargetZ } = useInitialCoordination(COMPONENT_COORDINATION_TYPES[ViewType$1.SPATIAL], coordinationScopes);
251995
252016
  const observationsLabel = observationsLabelOverride || obsType;
251996
252017
  const [{ imageLayerCallbacks, segmentationLayerCallbacks }] = useAuxiliaryCoordination(COMPONENT_COORDINATION_TYPES.layerController, coordinationScopes);
@@ -252196,7 +252217,15 @@ function SpatialSubscriber$1(props) {
252196
252217
  subobservationsLabel,
252197
252218
  locationsCount
252198
252219
  });
252199
- const { normData: uint8ExpressionData, extents: expressionExtents } = useUint8FeatureSelection(expressionData);
252220
+ const featureAggregationStrategyToUse = featureAggregationStrategy ?? DEFAULT_FEATURE_AGGREGATION_STRATEGY$2;
252221
+ const aggregatedExpressionData = useMemo$1(() => {
252222
+ if (featureAggregationStrategyToUse != null && expressionData && expressionData.length > 1) {
252223
+ const aggregated = aggregateFeatureArrays(expressionData, featureAggregationStrategyToUse);
252224
+ return [aggregated];
252225
+ }
252226
+ return expressionData;
252227
+ }, [expressionData, featureAggregationStrategyToUse]);
252228
+ const { normData: uint8ExpressionData, extents: expressionExtents } = useUint8FeatureSelection(aggregatedExpressionData);
252200
252229
  const shiftedExpressionDataForBitmask = useMemo$1(() => {
252201
252230
  if (matrixObsIndex && uint8ExpressionData && obsSegmentationsType === "bitmask") {
252202
252231
  const maxId = matrixObsIndex.reduce((max2, curr) => Math.max(max2, Number(curr)));
@@ -252221,7 +252250,7 @@ function SpatialSubscriber$1(props) {
252221
252250
  const canShow3DOptions = canLoad3DLayers && !(disable3d?.length === imageLayerLoaders.length) && !globalDisable3d;
252222
252251
  const options = useMemo$1(() => {
252223
252252
  if (canShow3DOptions || hasExpressionData) {
252224
- return jsx$1(SpatialOptions, { observationsLabel, cellColorEncoding, setCellColorEncoding, setSpatialAxisFixed, spatialAxisFixed, use3d, tooltipsVisible, setTooltipsVisible, geneExpressionColormap, setGeneExpressionColormap, geneExpressionColormapRange, setGeneExpressionColormapRange, canShowExpressionOptions: hasExpressionData, canShowColorEncodingOption: (hasLocationsData || hasSegmentationsData) && hasExpressionData, canShow3DOptions });
252253
+ return jsx$1(SpatialOptions, { observationsLabel, cellColorEncoding, setCellColorEncoding, setSpatialAxisFixed, spatialAxisFixed, use3d, tooltipsVisible, setTooltipsVisible, geneExpressionColormap, setGeneExpressionColormap, geneExpressionColormapRange, setGeneExpressionColormapRange, canShowExpressionOptions: hasExpressionData, canShowColorEncodingOption: (hasLocationsData || hasSegmentationsData) && hasExpressionData, canShow3DOptions, featureSelection: geneSelection, featureAggregationStrategy, setFeatureAggregationStrategy });
252225
252254
  }
252226
252255
  return null;
252227
252256
  }, [
@@ -252240,7 +252269,10 @@ function SpatialSubscriber$1(props) {
252240
252269
  spatialAxisFixed,
252241
252270
  use3d,
252242
252271
  tooltipsVisible,
252243
- setTooltipsVisible
252272
+ setTooltipsVisible,
252273
+ geneSelection,
252274
+ featureAggregationStrategy,
252275
+ setFeatureAggregationStrategy
252244
252276
  ]);
252245
252277
  useEffect(() => {
252246
252278
  if (!hasSegmentationsData && cellsLayer && !obsSegmentations && !obsSegmentationsIndex && obsCentroids && obsCentroidsIndex) {
@@ -252303,7 +252335,8 @@ function SpatialSubscriber$1(props) {
252303
252335
  featureValueColormap: geneExpressionColormap,
252304
252336
  featureValueColormapRange: geneExpressionColormapRange,
252305
252337
  setFeatureValueColormapRange: setGeneExpressionColormapRange,
252306
- extent: expressionExtents?.[0]
252338
+ extent: expressionExtents?.[0],
252339
+ featureAggregationStrategy: featureAggregationStrategyToUse
252307
252340
  })] });
252308
252341
  }
252309
252342
  function getInitialSpatialTargets({ width: width2, height: height2, obsPoints, obsSpots, obsSegmentations, obsSegmentationsLocations, segmentationChannelScopesByLayer, images, is3dMode: use3d, isReady }) {
@@ -253955,12 +253988,12 @@ class ErrorBoundary extends React__default.Component {
253955
253988
  }
253956
253989
  }
253957
253990
  const LazySpatialThree = React__default.lazy(async () => {
253958
- const { SpatialWrapper: SpatialWrapper2 } = await import("./index-CIJWVuYa.js").then((n3) => n3.a);
253991
+ const { SpatialWrapper: SpatialWrapper2 } = await import("./index-0nuepTVk.js").then((n3) => n3.a);
253959
253992
  return { default: SpatialWrapper2 };
253960
253993
  });
253961
253994
  const SpatialThreeAdapter = React__default.forwardRef((props, ref2) => jsx$1("div", { ref: ref2, style: { width: "100%", height: "100%" }, children: jsx$1(ErrorBoundary, { fallback: jsx$1("div", { children: "3D spatial view is not available in this environment." }), children: jsx$1(Suspense, { fallback: jsx$1("div", { children: "Loading..." }), children: jsx$1(LazySpatialThree, { ...props }) }) }) }));
253962
253995
  const LazySpatialAccelerated = React__default.lazy(async () => {
253963
- const { SpatialWrapper: SpatialWrapper2 } = await import("./index-BRdVNpUK.js");
253996
+ const { SpatialWrapper: SpatialWrapper2 } = await import("./index-BHE3zASA.js");
253964
253997
  return { default: SpatialWrapper2 };
253965
253998
  });
253966
253999
  const SpatialAcceleratedAdapter = React__default.forwardRef((props, ref2) => jsx$1("div", { ref: ref2, style: { width: "100%", height: "100%" }, children: jsx$1(ErrorBoundary, { fallback: jsx$1("div", { children: "3D spatial view is not available in this environment." }), children: jsx$1(Suspense, { fallback: jsx$1("div", { children: "Loading..." }), children: jsx$1(LazySpatialAccelerated, { ...props }) }) }) }));
@@ -254137,7 +254170,8 @@ function SpatialSubscriber(props) {
254137
254170
  bitmaskValueIsIndex = false,
254138
254171
  // TODO: move to coordination type
254139
254172
  three: threeFor3d = false,
254140
- accelerated: acceleratedFor3d = false
254173
+ accelerated: acceleratedFor3d = false,
254174
+ helpText = ViewHelpMapping.SPATIAL_BETA
254141
254175
  } = props;
254142
254176
  const loaders = useLoaders();
254143
254177
  const setComponentHover = useSetComponentHover();
@@ -254581,7 +254615,7 @@ function SpatialSubscriber(props) {
254581
254615
  }
254582
254616
  }
254583
254617
  };
254584
- return jsxs(TitleInfo, { title: title2, info: subtitle, isSpatial: true, urls: urls2, theme, closeButtonVisible, downloadButtonVisible, removeGridComponent, isReady, errors, children: [shouldUseThree ? acceleratedFor3d ? jsx$1(SpatialAcceleratedAdapter, { ref: threeRef, uuid: uuid2, width: width2, height: height2, theme, hideTools: !isSelectable, rotation: [rotationX, rotationY, rotationZ], setRotationX, setRotationY, setRotationZ, targetT, targetZ, viewState: isValidViewState ? {
254618
+ return jsxs(TitleInfo, { title: title2, info: subtitle, isSpatial: true, urls: urls2, theme, closeButtonVisible, downloadButtonVisible, removeGridComponent, isReady, errors, helpText, children: [shouldUseThree ? acceleratedFor3d ? jsx$1(SpatialAcceleratedAdapter, { ref: threeRef, uuid: uuid2, width: width2, height: height2, theme, hideTools: !isSelectable, rotation: [rotationX, rotationY, rotationZ], setRotationX, setRotationY, setRotationZ, targetT, targetZ, viewState: isValidViewState ? {
254585
254619
  zoom: zoom2,
254586
254620
  target: [targetX2, targetY2, targetZ],
254587
254621
  rotationX,
@@ -254688,8 +254722,8 @@ function getAxisSizes(transpose2, longestGeneLabel, longestCellLabel, hideObserv
254688
254722
  const font2 = `${AXIS_LABEL_TEXT_SIZE}pt ${AXIS_FONT_FAMILY}`;
254689
254723
  const geneLabelMaxWidth = hideVariableLabels ? 0 : getTextWidth(longestGeneLabel, font2) + AXIS_PADDING;
254690
254724
  const cellLabelMaxWidth = hideObservationLabels ? 0 : getTextWidth(longestCellLabel, font2) + AXIS_PADDING;
254691
- const axisOffsetLeft = clamp$7(transpose2 ? geneLabelMaxWidth : cellLabelMaxWidth, AXIS_MIN_SIZE, AXIS_MAX_SIZE);
254692
- const axisOffsetTop = clamp$7(transpose2 ? cellLabelMaxWidth : geneLabelMaxWidth, AXIS_MIN_SIZE, AXIS_MAX_SIZE);
254725
+ const axisOffsetLeft = clamp$8(transpose2 ? geneLabelMaxWidth : cellLabelMaxWidth, AXIS_MIN_SIZE, AXIS_MAX_SIZE);
254726
+ const axisOffsetTop = clamp$8(transpose2 ? cellLabelMaxWidth : geneLabelMaxWidth, AXIS_MIN_SIZE, AXIS_MAX_SIZE);
254693
254727
  return [axisOffsetLeft, axisOffsetTop];
254694
254728
  }
254695
254729
  function mouseToHeatmapPosition(mouseX, mouseY, { offsetLeft, offsetTop, targetX: targetX2, targetY: targetY2, scaleFactor, matrixWidth, matrixHeight, numRows, numCols }) {
@@ -254919,8 +254953,8 @@ const Heatmap$1 = forwardRef$1((props, deckRef) => {
254919
254953
  const scaleFactor = 2 ** viewState.zoom;
254920
254954
  const cellHeight = matrixHeight * scaleFactor / height2;
254921
254955
  const cellWidth = matrixWidth * scaleFactor / width2;
254922
- const aggSizeX = clamp$7(2 ** Math.ceil(Math.log2(1 / cellWidth)), MIN_ROW_AGG, MAX_ROW_AGG);
254923
- const aggSizeY = clamp$7(2 ** Math.ceil(Math.log2(1 / cellHeight)), MIN_ROW_AGG, MAX_ROW_AGG);
254956
+ const aggSizeX = clamp$8(2 ** Math.ceil(Math.log2(1 / cellWidth)), MIN_ROW_AGG, MAX_ROW_AGG);
254957
+ const aggSizeY = clamp$8(2 ** Math.ceil(Math.log2(1 / cellHeight)), MIN_ROW_AGG, MAX_ROW_AGG);
254924
254958
  const [targetX2, targetY2] = viewState.target;
254925
254959
  useEffect(() => {
254926
254960
  updateViewInfo({
@@ -254964,8 +254998,8 @@ const Heatmap$1 = forwardRef$1((props, deckRef) => {
254964
254998
  const minTargetY = nextZoom === 0 ? 0 : -(matrixBottom - matrixBottom / nextScaleFactor);
254965
254999
  const maxTargetY = -1 * minTargetY;
254966
255000
  const nextTarget = [
254967
- clamp$7(nextViewState.target[0], minTargetX, maxTargetX),
254968
- clamp$7(nextViewState.target[1], minTargetY, maxTargetY)
255001
+ clamp$8(nextViewState.target[0], minTargetX, maxTargetX),
255002
+ clamp$8(nextViewState.target[1], minTargetY, maxTargetY)
254969
255003
  ];
254970
255004
  setViewState({
254971
255005
  zoom: nextZoom,
@@ -262110,7 +262144,7 @@ const useStyles$n = makeStyles()((theme) => ({
262110
262144
  }));
262111
262145
  const SHIFT_KEYCODE = 16;
262112
262146
  function SelectableTable(props) {
262113
- const { hasColorEncoding, columns: columns2, columnLabels, data: data2, onChange, idKey = "id", valueKey = "value", allowMultiple = false, allowUncheck = false, showTableHead = true, showTableInputs = false, testHeight = void 0, testWidth = void 0, width: width2, height: height2 } = props;
262147
+ const { hasColorEncoding, columns: columns2, columnLabels, data: data2, onChange, idKey = "id", selectedIds, allowMultiple = false, allowUncheck = false, showTableHead = true, showTableInputs = false, testHeight = void 0, testWidth = void 0, width: width2, height: height2 } = props;
262114
262148
  const [selectedRows, setSelectedRows] = useState(null);
262115
262149
  const [isCheckingMultiple, setIsCheckingMultiple] = useState(false);
262116
262150
  useEffect(() => {
@@ -262154,20 +262188,20 @@ function SelectableTable(props) {
262154
262188
  })), [data2, idKey]);
262155
262189
  const isSelected = useCallback((id2) => Array.isArray(selectedRows) && selectedRows.includes(id2), [selectedRows]);
262156
262190
  useEffect(() => {
262157
- const initialSelectedRows = data2.map((d) => {
262158
- if (d[valueKey]) {
262159
- return d[idKey];
262160
- }
262161
- return null;
262162
- }).filter(Boolean);
262163
- if (!isEqual$3(initialSelectedRows, selectedRows)) {
262164
- if (initialSelectedRows.length > 0) {
262165
- setSelectedRows(initialSelectedRows);
262166
- } else {
262167
- setSelectedRows(null);
262191
+ if (selectedIds === void 0)
262192
+ return;
262193
+ setSelectedRows((prev2) => {
262194
+ const prevList = prev2 || [];
262195
+ const nextList = selectedIds || [];
262196
+ const sharedList = prevList.filter((id2) => nextList.includes(id2));
262197
+ const nextUnique = nextList.filter((id2) => !prevList.includes(id2));
262198
+ const merged = [...sharedList, ...nextUnique];
262199
+ if (isEqual$3(merged, prevList)) {
262200
+ return prev2;
262168
262201
  }
262169
- }
262170
- }, [data2, idKey, valueKey]);
262202
+ return merged.length > 0 ? merged : null;
262203
+ });
262204
+ }, [selectedIds]);
262171
262205
  useEffect(() => {
262172
262206
  if (!onChange || !selectedRows) {
262173
262207
  return;
@@ -262239,8 +262273,7 @@ function FeatureList(props) {
262239
262273
  const data2 = useMemo$1(() => {
262240
262274
  const preSortedData = searchResults.filter((gene) => geneFilter ? geneFilter.includes(gene) : true).map((gene) => ({
262241
262275
  key: gene,
262242
- name: featureLabelsMap?.get(gene) || featureLabelsMap?.get(cleanFeatureId(gene)) || gene,
262243
- value: geneSelection ? geneSelection.includes(gene) : false
262276
+ name: featureLabelsMap?.get(gene) || featureLabelsMap?.get(cleanFeatureId(gene)) || gene
262244
262277
  }));
262245
262278
  if (preSortedData && featureListSort === "alphabetical" && preSortedData.length > 0) {
262246
262279
  return preSortedData.sort((a2, b2) => a2[selectableTableSortKey].localeCompare(b2[selectableTableSortKey]));
@@ -262251,8 +262284,7 @@ function FeatureList(props) {
262251
262284
  selectableTableSortKey,
262252
262285
  searchResults,
262253
262286
  geneFilter,
262254
- featureLabelsMap,
262255
- geneSelection
262287
+ featureLabelsMap
262256
262288
  ]);
262257
262289
  const handleChange = (event2) => {
262258
262290
  setSearchTerm(event2.target.value);
@@ -262269,7 +262301,7 @@ function FeatureList(props) {
262269
262301
  [primaryColumnName]
262270
262302
  ];
262271
262303
  }, [showFeatureTable, primaryColumnName, hasFeatureLabels]);
262272
- return width2 > 0 && height2 > 0 ? jsxs(Fragment, { children: [jsx$1("input", { className: classes2.searchBar, type: "text", placeholder: "Search", value: searchTerm, onChange: handleChange }), jsx$1(SelectableTable, { columns: columns2, columnLabels, data: data2, hasColorEncoding, idKey: "key", valueKey: "value", onChange, allowMultiple: enableMultiSelect, allowUncheck: enableMultiSelect, showTableHead: columnLabels.length > 1, width: width2, height: height2 - 34 })] }) : null;
262304
+ return width2 > 0 && height2 > 0 ? jsxs(Fragment, { children: [jsx$1("input", { className: classes2.searchBar, type: "text", placeholder: "Search", value: searchTerm, onChange: handleChange }), jsx$1(SelectableTable, { columns: columns2, columnLabels, data: data2, hasColorEncoding, idKey: "key", selectedIds: geneSelection, onChange, allowMultiple: enableMultiSelect, allowUncheck: enableMultiSelect, showTableHead: columnLabels.length > 1, width: width2, height: height2 - 34 })] }) : null;
262273
262305
  }
262274
262306
  function FeatureListOptions(props) {
262275
262307
  const { children: children3, featureListSort, setFeatureListSort, featureListSortKey, setFeatureListSortKey, showFeatureTable, setShowFeatureTable, hasFeatureLabels, primaryColumnName } = props;
@@ -262286,7 +262318,7 @@ function FeatureListOptions(props) {
262286
262318
  const { classes: classes2 } = usePlotOptionsStyles();
262287
262319
  return jsxs(OptionsContainer, { children: [children3, jsxs(TableRow, { children: [jsx$1(TableCell, { className: classes2.labelCell, variant: "head", scope: "row", children: jsx$1("label", { htmlFor: `feature-list-sort-option-${featureListId}`, children: "Sort Ordering" }) }), jsx$1(TableCell, { variant: "body", children: jsx$1(OptionSelect, { className: classes2.select, value: featureListSort, onChange: handleFeatureListSortChange, inputProps: {
262288
262320
  id: `feature-list-sort-option-${featureListId}`
262289
- }, children: FEATURELIST_SORT_OPTIONS.map((option) => jsx$1("option", { value: option, children: option }, option)) }) })] }), hasFeatureLabels ? jsxs(Fragment, { children: [jsxs(TableRow, { children: [jsx$1(TableCell, { className: classes2.labelCell, variant: "head", scope: "row", children: jsx$1("label", { htmlFor: `feature-list-sort-key-${featureListId}`, children: "Sort Key" }) }), jsx$1(TableCell, { variant: "body", children: jsx$1(OptionSelect, { className: classes2.select, disabled: featureListSort === "original", value: featureListSortKey, onChange: handleFeatureListSortKeyChange, inputProps: {
262321
+ }, children: FEATURELIST_SORT_OPTIONS.map((option) => jsx$1("option", { value: option, children: capitalize$3(option) }, option)) }) })] }), hasFeatureLabels ? jsxs(Fragment, { children: [jsxs(TableRow, { children: [jsx$1(TableCell, { className: classes2.labelCell, variant: "head", scope: "row", children: jsx$1("label", { htmlFor: `feature-list-sort-key-${featureListId}`, children: "Sort Key" }) }), jsx$1(TableCell, { variant: "body", children: jsx$1(OptionSelect, { className: classes2.select, disabled: featureListSort === "original", value: featureListSortKey, onChange: handleFeatureListSortKeyChange, inputProps: {
262290
262322
  "aria-label": "Select the feature list sort key",
262291
262323
  id: `feature-list-sort-key-${featureListId}`
262292
262324
  }, children: hasFeatureLabels ? jsxs(Fragment, { children: [jsx$1("option", { value: "featureLabels", children: primaryColumnName }), jsx$1("option", { value: "featureIndex", children: ALT_COLNAME })] }) : jsx$1("option", { value: "featureIndex", children: primaryColumnName }) }) })] }), jsxs(TableRow, { children: [jsx$1(TableCell, { className: classes2.labelCell, variant: "head", scope: "row", children: jsx$1("label", { htmlFor: `feature-list-show-alternative-ids-${featureListId}`, children: "Show Alternate IDs" }) }), jsx$1(TableCell, { className: classes2.inputCell, variant: "body", children: jsx$1(Checkbox$1, { className: classes2.tableCheckbox, checked: showFeatureTable, onChange: handleShowTableChange, name: "feature-list-show-table", color: "default", slotProps: { input: {
@@ -263785,7 +263817,7 @@ function PointLayerController(props) {
263785
263817
  const [coloringTabIndex, setColoringTabIndex] = useState(0);
263786
263818
  const { featureIndex } = pointMatrixIndicesData || {};
263787
263819
  const hasSelectedFeatures = Array.isArray(featureSelection) && featureSelection.length > 0;
263788
- return jsxs(Grid$1, { className: lcClasses.layerControllerGrid, children: [jsxs(Paper, { elevation: 4, className: lcClasses.layerControllerRoot, children: [jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsx$1(Grid$1, { size: 1, children: jsx$1(Button, { onClick: handleVisibleChange, className: menuClasses.imageLayerVisibleButton, "aria-label": "Toggle layer visibility", children: jsx$1(Visibility, {}) }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(ChannelColorPickerMenu, { theme, color: color2, setColor: setColor2, palette, isStaticColor, isColormap, featureValueColormap, visible }) }), jsx$1(Grid$1, { size: 6, children: jsx$1(Typography, { className: menuClasses.imageLayerName, children: label2 }) }), jsx$1(Grid$1, { size: 2, children: jsx$1(Slider, { value: opacity2, min: 0, max: 1, step: 1e-3, onChange: handleOpacityChange, className: menuClasses.imageLayerOpacitySlider, orientation: "horizontal", "aria-label": `Adjust opacity for layer ${label2}` }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(PointLayerEllipsisMenu, { featureSelection, obsColorEncoding, setObsColorEncoding, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible, featureFilterMode, setFeatureFilterMode }) }), jsxs(Grid$1, { size: 1, container: true, direction: "row", children: [jsx$1(SvgPoints, { className: classes2.layerTypePointIcon }), null] })] }), loadingDoneFraction < 1 ? jsx$1(Grid$1, { size: 12, container: true, direction: "column", justifyContent: "space-between", className: classes2.pointFeatureControllerGrid, children: jsx$1(LinearProgress, { variant: loadingDoneFraction === 0 ? "indeterminate" : "determinate", value: loadingDoneFraction * 100 }) }) : null, null] }), hasSelectedFeatures ? jsxs(Fragment, { children: [featureSelection.map((featureName) => jsx$1(LayerPerFeatureController, { theme, featureName, featureColor, setFeatureColor, spatialLayerColor, featureIndex, featureValueColormap, featureSelection, setFeatureSelection, obsColorEncoding, loadingDoneFraction, opacity: opacity2, handleOpacityChange }, featureName)), jsx$1(Grid$1, { className: lcClasses.layerControllerGrid, children: jsx$1(Paper, { elevation: 2, className: lcClasses.layerControllerSubRow, children: jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsx$1(Grid$1, { size: 1, children: jsx$1(Button, { onClick: () => setFeatureFilterMode(featureFilterMode === "featureSelection" ? null : "featureSelection"), className: menuClasses.imageLayerVisibleButton, "aria-label": "Toggle visibility of unselected points", children: featureFilterMode === "featureSelection" ? jsx$1(VisibilityOffIcon, {}) : jsx$1(VisibilityIcon, {}) }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(ChannelColorPickerMenu, { theme, color: getDefaultColor("dark"), setColor: null, isStaticColor: true, isColormap: false, visible: true }) }), jsx$1(Grid$1, { size: 6, children: jsx$1(Typography, { className: menuClasses.imageLayerName, children: "Unselected" }) }), jsx$1(Grid$1, { size: 2, sx: { paddingRight: "12px", overflow: "visible" }, children: jsx$1(Slider, { value: opacity2, min: 0, max: 1, step: 1e-3, onChange: handleOpacityChange, className: menuClasses.imageLayerOpacitySlider, orientation: "horizontal", "aria-label": "Adjust opacity for unselected layer" }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(SvgPoints, { className: classes2.layerTypePointIcon }) })] }) }) })] }) : null] });
263820
+ return jsxs(Grid$1, { className: lcClasses.layerControllerGrid, children: [jsxs(Paper, { elevation: 4, className: lcClasses.layerControllerRoot, children: [jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsx$1(Grid$1, { size: 1, children: jsx$1(Button, { onClick: handleVisibleChange, className: menuClasses.imageLayerVisibleButton, "aria-label": "Toggle layer visibility", children: jsx$1(Visibility, {}) }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(ChannelColorPickerMenu, { theme, color: color2, setColor: setColor2, palette, isStaticColor, isColormap, featureValueColormap, visible }) }), jsx$1(Grid$1, { size: 6, children: jsx$1(Typography, { className: menuClasses.imageLayerName, children: label2 }) }), jsx$1(Grid$1, { size: 2, children: jsx$1(Slider, { value: opacity2, min: 0, max: 1, step: 1e-3, onChange: handleOpacityChange, className: menuClasses.imageLayerOpacitySlider, orientation: "horizontal", "aria-label": `Adjust opacity for layer ${label2}` }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(PointLayerEllipsisMenu, { featureSelection, obsColorEncoding, setObsColorEncoding, featureValueColormapRange, setFeatureValueColormapRange, tooltipsVisible, setTooltipsVisible, tooltipCrosshairsVisible, setTooltipCrosshairsVisible, legendVisible, setLegendVisible, featureFilterMode, setFeatureFilterMode }) }), jsxs(Grid$1, { size: 1, container: true, direction: "row", children: [jsx$1(SvgPoints, { className: classes2.layerTypePointIcon }), null] })] }), loadingDoneFraction < 1 ? jsx$1(Grid$1, { size: 12, container: true, direction: "column", justifyContent: "space-between", className: classes2.pointFeatureControllerGrid, children: jsx$1(LinearProgress, { variant: loadingDoneFraction === 0 ? "indeterminate" : "determinate", value: loadingDoneFraction * 100 }) }) : null, null] }), layerPerFeatureForPoints && hasSelectedFeatures ? jsxs(Fragment, { children: [featureSelection.map((featureName) => jsx$1(LayerPerFeatureController, { theme, featureName, featureColor, setFeatureColor, spatialLayerColor, featureIndex, featureValueColormap, featureSelection, setFeatureSelection, obsColorEncoding, loadingDoneFraction, opacity: opacity2, handleOpacityChange }, featureName)), jsx$1(Grid$1, { className: lcClasses.layerControllerGrid, children: jsx$1(Paper, { elevation: 2, className: lcClasses.layerControllerSubRow, children: jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsx$1(Grid$1, { size: 1, children: jsx$1(Button, { onClick: () => setFeatureFilterMode(featureFilterMode === "featureSelection" ? null : "featureSelection"), className: menuClasses.imageLayerVisibleButton, "aria-label": "Toggle visibility of unselected points", children: featureFilterMode === "featureSelection" ? jsx$1(VisibilityOffIcon, {}) : jsx$1(VisibilityIcon, {}) }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(ChannelColorPickerMenu, { theme, color: getDefaultColor("dark"), setColor: null, isStaticColor: true, isColormap: false, visible: true }) }), jsx$1(Grid$1, { size: 6, children: jsx$1(Typography, { className: menuClasses.imageLayerName, children: "Unselected" }) }), jsx$1(Grid$1, { size: 2, sx: { paddingRight: "12px", overflow: "visible" }, children: jsx$1(Slider, { value: opacity2, min: 0, max: 1, step: 1e-3, onChange: handleOpacityChange, className: menuClasses.imageLayerOpacitySlider, orientation: "horizontal", "aria-label": "Adjust opacity for unselected layer" }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(SvgPoints, { className: classes2.layerTypePointIcon }) })] }) }) })] }) : null] });
263789
263821
  }
263790
263822
  const useStyles$d = makeStyles()(() => ({
263791
263823
  layerTypeSegmentationIcon: {
@@ -265137,17 +265169,23 @@ const useStyles$9 = makeStyles()(() => ({
265137
265169
  }
265138
265170
  }));
265139
265171
  function ChannelSelectionDropdown(props) {
265140
- const { featureIndex, targetC, setTargetC, setWindow: setWindow2, disabled } = props;
265172
+ const { featureIndex, channelsSortOrder, targetC, setTargetC, setWindow: setWindow2, disabled } = props;
265141
265173
  const { classes: classes2 } = useStyles$9();
265142
265174
  const { classes: selectClasses2 } = useSelectStyles();
265143
265175
  function handleChange(event2) {
265144
265176
  setTargetC(event2.target.value === "" ? null : Number(event2.target.value));
265145
265177
  setWindow2(null);
265146
265178
  }
265147
- return Array.isArray(featureIndex) ? jsx$1(NativeSelect, { classes: { root: selectClasses2.selectRoot }, className: classes2.oneLineChannelSelect, value: targetC === null ? "" : targetC, onChange: handleChange, inputProps: { "aria-label": "Channel selector" }, children: featureIndex.map((channelName, channelIndex) => (
265148
- // eslint-disable-next-line react/no-array-index-key
265149
- jsx$1("option", { disabled, value: channelIndex, children: channelName }, `${channelName}-${channelIndex}`)
265150
- )) }) : null;
265179
+ const sortedOptions = useMemo$1(() => {
265180
+ if (!Array.isArray(featureIndex))
265181
+ return [];
265182
+ const options = featureIndex.map((channelName, channelIndex) => ({ channelName, channelIndex }));
265183
+ if (channelsSortOrder === "alphabetical") {
265184
+ return options.sort((a2, b2) => a2.channelName.localeCompare(b2.channelName, void 0, { numeric: true, sensitivity: "base" }));
265185
+ }
265186
+ return options;
265187
+ }, [featureIndex, channelsSortOrder]);
265188
+ return Array.isArray(featureIndex) ? jsx$1(NativeSelect, { classes: { root: selectClasses2.selectRoot }, className: classes2.oneLineChannelSelect, value: targetC === null ? "" : targetC, onChange: handleChange, inputProps: { "aria-label": "Channel selector" }, children: sortedOptions.map(({ channelName, channelIndex }) => jsx$1("option", { disabled, value: channelIndex, children: channelName }, `${channelName}-${channelIndex}`)) }) : null;
265151
265189
  }
265152
265190
  function ImageChannelController(props) {
265153
265191
  const {
@@ -265175,7 +265213,8 @@ function ImageChannelController(props) {
265175
265213
  spatialRenderingMode,
265176
265214
  numResolutions,
265177
265215
  spatialMaxResolution,
265178
- setSpatialMaxResolution
265216
+ setSpatialMaxResolution,
265217
+ channelsSortOrder
265179
265218
  } = props;
265180
265219
  const removeChannel = useRemoveImageChannelInMetaCoordinationScopes();
265181
265220
  const [showValueExtent, setShowValueExtent] = useState(true);
@@ -265212,7 +265251,7 @@ function ImageChannelController(props) {
265212
265251
  setWindow2(minMaxDomain);
265213
265252
  }
265214
265253
  }
265215
- return jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsx$1(Grid$1, { size: 1, children: jsx$1(ChannelVisibilityCheckbox, { color: color2, setColor: setColor2, visible, setVisible, disabled: isLoading, theme, colormapOn }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(ChannelColorPickerMenu, { color: color2, setColor: setColor2, visible, setVisible, disabled: isLoading, theme, isStaticColor: !colormapOn, palette: VIEWER_PALETTE }) }), jsx$1(Grid$1, { size: 6, children: jsx$1(ChannelSelectionDropdown, { featureIndex, targetC, setTargetC, setWindow: setWindow2, disabled: isLoading }) }), jsx$1(Grid$1, { size: 3, children: jsx$1(ChannelSlider, { image: image2, targetT, targetZ, targetC, window: window2, setWindow: setWindow2, disabled, color: color2, theme, colormapOn, showValueExtent, minMaxDomain }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(ChannelOptions, { onRemove: onRemove2, showValueExtent, setShowValueExtent, onResetWindowUsingIQR: handleResetWindowUsingIQR, numResolutions, spatialMaxResolution, setSpatialMaxResolution }) })] });
265254
+ return jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsx$1(Grid$1, { size: 1, children: jsx$1(ChannelVisibilityCheckbox, { color: color2, setColor: setColor2, visible, setVisible, disabled: isLoading, theme, colormapOn }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(ChannelColorPickerMenu, { color: color2, setColor: setColor2, visible, setVisible, disabled: isLoading, theme, isStaticColor: !colormapOn, palette: VIEWER_PALETTE }) }), jsx$1(Grid$1, { size: 6, children: jsx$1(ChannelSelectionDropdown, { featureIndex, targetC, setTargetC, setWindow: setWindow2, disabled: isLoading, channelsSortOrder }) }), jsx$1(Grid$1, { size: 3, children: jsx$1(ChannelSlider, { image: image2, targetT, targetZ, targetC, window: window2, setWindow: setWindow2, disabled, color: color2, theme, colormapOn, showValueExtent, minMaxDomain }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(ChannelOptions, { onRemove: onRemove2, showValueExtent, setShowValueExtent, onResetWindowUsingIQR: handleResetWindowUsingIQR, numResolutions, spatialMaxResolution, setSpatialMaxResolution }) })] });
265216
265255
  }
265217
265256
  function DimensionSlider(props) {
265218
265257
  const { boundingSlice, sliceValue, setSliceValue, label: label2 } = props;
@@ -265311,7 +265350,7 @@ const lodSliderRangeConfig = {
265311
265350
  step: 1
265312
265351
  };
265313
265352
  function ImageLayerEllipsisMenu(props) {
265314
- const { colormap, setColormap, photometricInterpretation, setPhotometricInterpretation, spatialTargetResolution, setSpatialTargetResolution, spatialLodFactor, setSpatialLodFactor, volumetricRenderingAlgorithm, setVolumetricRenderingAlgorithm, spatialLayerTransparentColor, setSpatialLayerTransparentColor, spatialRenderingMode, image: image2, channelScopes, tooltipsVisible, setTooltipsVisible, channelLabelsVisible, setChannelLabelsVisible, channelLabelsOrientation, setChannelLabelsOrientation, channelLabelSize, setChannelLabelSize } = props;
265353
+ const { colormap, setColormap, photometricInterpretation, setPhotometricInterpretation, spatialTargetResolution, setSpatialTargetResolution, spatialLodFactor, setSpatialLodFactor, volumetricRenderingAlgorithm, setVolumetricRenderingAlgorithm, spatialLayerTransparentColor, setSpatialLayerTransparentColor, spatialRenderingMode, image: image2, channelScopes, tooltipsVisible, setTooltipsVisible, channelLabelsVisible, setChannelLabelsVisible, channelLabelsOrientation, setChannelLabelsOrientation, channelLabelSize, setChannelLabelSize, channelsSortOrder, setChannelsSortOrder } = props;
265315
265354
  const [open2, setOpen] = useState(false);
265316
265355
  const { classes: selectClasses2 } = useSelectStyles();
265317
265356
  const { classes: menuClasses } = useEllipsisMenuStyles();
@@ -265337,6 +265376,9 @@ function ImageLayerEllipsisMenu(props) {
265337
265376
  function handleChannelLabelsOrientationChange(event2) {
265338
265377
  setChannelLabelsOrientation(event2.target.value);
265339
265378
  }
265379
+ function handleChannelsSortOrderChange(event2) {
265380
+ setChannelsSortOrder(event2.target.value);
265381
+ }
265340
265382
  function handleLodFactorChange(event2, value2) {
265341
265383
  setLocalLodSliderValue(value2);
265342
265384
  }
@@ -265358,11 +265400,12 @@ function ImageLayerEllipsisMenu(props) {
265358
265400
  const channelLabelsOrientationId = $bdb11010cef70236$export$f680877a34711e37();
265359
265401
  const channelLabelSizeId = $bdb11010cef70236$export$f680877a34711e37();
265360
265402
  const lodFactorId = $bdb11010cef70236$export$f680877a34711e37();
265403
+ const channelsSortOrderId = $bdb11010cef70236$export$f680877a34711e37();
265361
265404
  return jsxs(PopperMenu, { open: open2, setOpen, buttonIcon: jsx$1(MoreVertIcon, {}), buttonClassName: menuClasses.imageLayerMenuButton, containerClassName: menuClasses.imageLayerPopperContainer, withPaper: true, "aria-label": "Open image layer options menu", children: [is3dMode && jsxs(MenuItem, { dense: true, disableGutters: true, className: menuClasses.menuItem, children: [jsx$1("label", { id: `${lodFactorId}-label`, className: menuClasses.imageLayerMenuLabel, htmlFor: lodFactorId, children: "LOD Factor: " }), jsx$1(Slider, { disabled: !is3dMode, value: localLodSliderValue, onChange: handleLodFactorChange, onChangeCommitted: handleLodFactorChangeCommitted, className: menuClasses.menuItemSlider, orientation: "horizontal", id: lodFactorId, "aria-label": "Level of detail factor slider", valueLabelDisplay: "off", ...lodSliderRangeConfig }), jsx$1(Box, { px: 1 }), jsx$1(Input$1, { value: localLodSliderValue, onChange: handleLodFactorInputChange, onBlur: handleLodFactorInputChange, "aria-labelledby": `${lodFactorId}-label`, size: "small", sx: { width: "6ch", flexShrink: 0, fontVariantNumeric: "tabular-nums" }, endAdornment: jsx$1(InputAdornment$1, { position: "end", variant: "standard", sx: { "& > p": { marginBottom: 0 } }, children: "%" }), inputProps: {
265362
265405
  ...lodSliderRangeConfig,
265363
265406
  inputMode: "numeric",
265364
265407
  pattern: "[0-9]*"
265365
- } })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: colormapId, children: "Colormap: " }), jsxs(NativeSelect, { disabled: photometricInterpretation === "RGB", onChange: handleColormapChange, value: colormap === null ? "" : colormap, inputProps: { id: colormapId, "aria-label": "Colormap selector" }, classes: { root: selectClasses2.selectRoot }, children: [jsx$1("option", { "aria-label": "None", value: "", children: "None" }), COLORMAP_OPTIONS.map((name2) => jsx$1("option", { value: name2, children: name2 }, name2))] })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: interpretationId, children: "Photometric Interpretation: " }), jsxs(NativeSelect, { onChange: handleInterpretationChange, value: photometricInterpretation, inputProps: { id: interpretationId, "aria-label": "Photometric interpretation selector" }, classes: { root: selectClasses2.selectRoot }, children: [jsx$1("option", { "aria-label": "RGB", value: "RGB", children: "RGB" }), channelScopes.length > 0 ? jsx$1("option", { "aria-label": "BlackIsZero", value: "BlackIsZero", children: "BlackIsZero" }) : null] })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: transparentId, children: "Zero Transparent: " }), jsx$1(Checkbox$1, { color: "primary", checked: spatialLayerTransparentColor !== null, onChange: (e3, v) => setSpatialLayerTransparentColor(v ? [0, 0, 0] : null), slotProps: { input: { id: transparentId, "aria-label": "Render zero-value pixels as transparent" } } })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: volumetricId, children: "Volumetric Rendering: " }), jsxs(NativeSelect, { onChange: handleVolumetricChange, value: volumetricRenderingAlgorithm, inputProps: { id: volumetricId, "aria-label": "Volumetric rendering algorithm selector" }, classes: { root: selectClasses2.selectRoot }, disabled: !is3dMode, children: [jsx$1("option", { "aria-label": "Additive", value: "additive", children: "Additive" }), jsx$1("option", { "aria-label": "Maximum Intensity Projection", value: "maximumIntensityProjection", children: "Maximum Intensity Projection" })] })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: resolutionId, children: "Volume Resolution: " }), jsxs(NativeSelect, { disabled: !is3dMode || !isMultiResolution, onChange: handleResolutionChange, value: spatialTargetResolution === null ? "auto" : spatialTargetResolution, inputProps: { id: resolutionId, "aria-label": "Volumetric resolution selector" }, classes: { root: selectClasses2.selectRoot }, children: [jsx$1("option", { value: "auto", children: "Auto" }), Array.isArray(multiResolutionStats) ? multiResolutionStats.map((stats, resolution) => stats.canLoad ? jsx$1("option", { value: resolution, children: `3D: ${resolution}x Downsampled, ~${formatBytes(stats.totalBytes)} per channel, (${stats.height}, ${stats.width}, ${stats.depthDownsampled})` }, `(${stats.height}, ${stats.width}, ${stats.depthDownsampled})`) : null) : null] })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: tooltipsVisibleId, children: "Tooltips Visible: " }), jsx$1(Checkbox$1, { color: "primary", checked: tooltipsVisible, onChange: (e3, v) => setTooltipsVisible(v), slotProps: { input: { id: tooltipsVisibleId, "aria-label": "Render pixel value tooltips" } } })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: channelLabelsVisibleId, children: "Channel Labels Visible: " }), jsx$1(Checkbox$1, { disabled: photometricInterpretation === "RGB", color: "primary", checked: channelLabelsVisible, onChange: (e3, v) => setChannelLabelsVisible(v), slotProps: { input: { id: channelLabelsVisibleId, "aria-label": "Render channel labels" } } })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: channelLabelsOrientationId, children: "Channel Labels Orientation: " }), jsxs(NativeSelect, { disabled: photometricInterpretation === "RGB", onChange: handleChannelLabelsOrientationChange, value: channelLabelsOrientation, inputProps: { id: channelLabelsOrientationId, "aria-label": "Channel labels orientation selector" }, classes: { root: selectClasses2.selectRoot }, children: [jsx$1("option", { "aria-label": "Vertical", value: "vertical", children: "Vertical" }), jsx$1("option", { "aria-label": "Horizontal", value: "horizontal", children: "Horizontal" })] })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: channelLabelSizeId, children: "Channel Labels Size: " }), jsx$1(Slider, { disabled: photometricInterpretation === "RGB", value: channelLabelSize, min: 8, max: 36, step: 1, onChange: (e3, v) => setChannelLabelSize(v), className: menuClasses.menuItemSlider, orientation: "horizontal", id: channelLabelSizeId, "aria-label": "Channel labels text size slider" })] })] });
265408
+ } })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: colormapId, children: "Colormap: " }), jsxs(NativeSelect, { disabled: photometricInterpretation === "RGB", onChange: handleColormapChange, value: colormap === null ? "" : colormap, inputProps: { id: colormapId, "aria-label": "Colormap selector" }, classes: { root: selectClasses2.selectRoot }, children: [jsx$1("option", { "aria-label": "None", value: "", children: "None" }), COLORMAP_OPTIONS.map((name2) => jsx$1("option", { value: name2, children: name2 }, name2))] })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: interpretationId, children: "Photometric Interpretation: " }), jsxs(NativeSelect, { onChange: handleInterpretationChange, value: photometricInterpretation, inputProps: { id: interpretationId, "aria-label": "Photometric interpretation selector" }, classes: { root: selectClasses2.selectRoot }, children: [jsx$1("option", { "aria-label": "RGB", value: "RGB", children: "RGB" }), channelScopes.length > 0 ? jsx$1("option", { "aria-label": "BlackIsZero", value: "BlackIsZero", children: "BlackIsZero" }) : null] })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: transparentId, children: "Zero Transparent: " }), jsx$1(Checkbox$1, { color: "primary", checked: spatialLayerTransparentColor !== null, onChange: (e3, v) => setSpatialLayerTransparentColor(v ? [0, 0, 0] : null), slotProps: { input: { id: transparentId, "aria-label": "Render zero-value pixels as transparent" } } })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: volumetricId, children: "Volumetric Rendering: " }), jsxs(NativeSelect, { onChange: handleVolumetricChange, value: volumetricRenderingAlgorithm, inputProps: { id: volumetricId, "aria-label": "Volumetric rendering algorithm selector" }, classes: { root: selectClasses2.selectRoot }, disabled: !is3dMode, children: [jsx$1("option", { "aria-label": "Additive", value: "additive", children: "Additive" }), jsx$1("option", { "aria-label": "Maximum Intensity Projection", value: "maximumIntensityProjection", children: "Maximum Intensity Projection" })] })] }), jsxs(MenuItem, { dense: true, disableGutters: true, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: resolutionId, children: "Volume Resolution: " }), jsxs(NativeSelect, { disabled: !is3dMode || !isMultiResolution, onChange: handleResolutionChange, value: spatialTargetResolution === null ? "auto" : spatialTargetResolution, inputProps: { id: resolutionId, "aria-label": "Volumetric resolution selector" }, classes: { root: selectClasses2.selectRoot }, children: [jsx$1("option", { value: "auto", children: "Auto" }), Array.isArray(multiResolutionStats) ? multiResolutionStats.map((stats, resolution) => stats.canLoad ? jsx$1("option", { value: resolution, children: `3D: ${resolution}x Downsampled, ~${formatBytes(stats.totalBytes)} per channel, (${stats.height}, ${stats.width}, ${stats.depthDownsampled})` }, `(${stats.height}, ${stats.width}, ${stats.depthDownsampled})`) : null) : null] })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: tooltipsVisibleId, children: "Tooltips Visible: " }), jsx$1(Checkbox$1, { color: "primary", checked: tooltipsVisible, onChange: (e3, v) => setTooltipsVisible(v), slotProps: { input: { id: tooltipsVisibleId, "aria-label": "Render pixel value tooltips" } } })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: channelLabelsVisibleId, children: "Channel Labels Visible: " }), jsx$1(Checkbox$1, { disabled: photometricInterpretation === "RGB", color: "primary", checked: channelLabelsVisible, onChange: (e3, v) => setChannelLabelsVisible(v), slotProps: { input: { id: channelLabelsVisibleId, "aria-label": "Render channel labels" } } })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: channelLabelsOrientationId, children: "Channel Labels Orientation: " }), jsxs(NativeSelect, { disabled: photometricInterpretation === "RGB", onChange: handleChannelLabelsOrientationChange, value: channelLabelsOrientation, inputProps: { id: channelLabelsOrientationId, "aria-label": "Channel labels orientation selector" }, classes: { root: selectClasses2.selectRoot }, children: [jsx$1("option", { "aria-label": "Vertical", value: "vertical", children: "Vertical" }), jsx$1("option", { "aria-label": "Horizontal", value: "horizontal", children: "Horizontal" })] })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: channelLabelSizeId, children: "Channel Labels Size: " }), jsx$1(Slider, { disabled: photometricInterpretation === "RGB", value: channelLabelSize, min: 8, max: 36, step: 1, onChange: (e3, v) => setChannelLabelSize(v), className: menuClasses.menuItemSlider, orientation: "horizontal", id: channelLabelSizeId, "aria-label": "Channel labels text size slider" })] }), jsxs(MenuItem, { dense: true, disableGutters: true, classes: menuClasses.menuItem, children: [jsx$1("label", { className: menuClasses.imageLayerMenuLabel, htmlFor: channelsSortOrderId, children: "Channel Ordering: " }), jsxs(NativeSelect, { onChange: handleChannelsSortOrderChange, value: channelsSortOrder, inputProps: { id: channelsSortOrderId, "aria-label": "Channel sort order selector" }, classes: { root: selectClasses2.selectRoot }, children: [jsx$1("option", { "aria-label": "Original", value: "original", children: "Original" }), jsx$1("option", { "aria-label": "Alphabetical", value: "alphabetical", children: "Alphabetical" })] })] })] });
265366
265409
  }
265367
265410
  function ImageLayerController(props) {
265368
265411
  const {
@@ -265388,8 +265431,8 @@ function ImageLayerController(props) {
265388
265431
  volumeStillRef = null
265389
265432
  } = props;
265390
265433
  const [open2, setOpen] = useState(true);
265391
- const { spatialLayerVisible: visible, spatialLayerOpacity: opacity2, spatialLayerColormap: colormap, photometricInterpretation, spatialTargetResolution, spatialLodFactor, volumetricRenderingAlgorithm, spatialLayerTransparentColor, spatialSliceX, spatialSliceY, spatialSliceZ, tooltipsVisible, spatialChannelLabelsVisible: channelLabelsVisible, spatialChannelLabelsOrientation: channelLabelsOrientation, spatialChannelLabelSize: channelLabelSize } = layerCoordination;
265392
- const { setSpatialLayerVisible: setVisible, setSpatialLayerOpacity: setOpacity2, setSpatialLayerColormap: setColormap, setPhotometricInterpretation, setSpatialTargetResolution, setSpatialLodFactor, setVolumetricRenderingAlgorithm, setSpatialLayerTransparentColor, setSpatialSliceX, setSpatialSliceY, setSpatialSliceZ, setTooltipsVisible, setSpatialChannelLabelsVisible: setChannelLabelsVisible, setSpatialChannelLabelsOrientation: setChannelLabelsOrientation, setSpatialChannelLabelSize: setChannelLabelSize } = setLayerCoordination;
265434
+ const { spatialLayerVisible: visible, spatialLayerOpacity: opacity2, spatialLayerColormap: colormap, photometricInterpretation, spatialTargetResolution, spatialLodFactor, volumetricRenderingAlgorithm, spatialLayerTransparentColor, spatialSliceX, spatialSliceY, spatialSliceZ, tooltipsVisible, spatialChannelLabelsVisible: channelLabelsVisible, spatialChannelLabelsOrientation: channelLabelsOrientation, spatialChannelLabelSize: channelLabelSize, spatialChannelsSortOrder: channelsSortOrder } = layerCoordination;
265435
+ const { setSpatialLayerVisible: setVisible, setSpatialLayerOpacity: setOpacity2, setSpatialLayerColormap: setColormap, setPhotometricInterpretation, setSpatialTargetResolution, setSpatialLodFactor, setVolumetricRenderingAlgorithm, setSpatialLayerTransparentColor, setSpatialSliceX, setSpatialSliceY, setSpatialSliceZ, setTooltipsVisible, setSpatialChannelLabelsVisible: setChannelLabelsVisible, setSpatialChannelLabelsOrientation: setChannelLabelsOrientation, setSpatialChannelLabelSize: setChannelLabelSize, setSpatialChannelsSortOrder: setChannelsSortOrder } = setLayerCoordination;
265393
265436
  const addChannel = useAddImageChannelInMetaCoordinationScopes();
265394
265437
  const visibleSetting = typeof visible === "boolean" ? visible : true;
265395
265438
  const Visibility = useMemo$1(() => visibleSetting ? VisibilityIcon : VisibilityOffIcon, [visibleSetting]);
@@ -265409,12 +265452,12 @@ function ImageLayerController(props) {
265409
265452
  const { classes: menuClasses } = useEllipsisMenuStyles();
265410
265453
  const { classes: controllerSectionClasses } = useControllerSectionStyles();
265411
265454
  const isMultiChannel = photometricInterpretation !== "RGB";
265412
- return jsx$1(Grid$1, { className: controllerSectionClasses.layerControllerGrid, children: jsxs(Paper, { elevation: 4, className: controllerSectionClasses.layerControllerRoot, children: [jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsx$1(Grid$1, { size: 1, children: jsx$1(Button, { className: menuClasses.imageLayerVisibleButton, onClick: handleVisibleChange, "aria-label": "Toggle layer visibility", children: jsx$1(Visibility, {}) }) }), jsx$1(Grid$1, { size: 1 }), jsx$1(Grid$1, { size: 6, children: jsx$1(Typography, { className: menuClasses.imageLayerName, children: label2 }) }), jsx$1(Grid$1, { size: 2, children: jsx$1(Slider, { value: opacity2, min: 0, max: 1, step: 1e-3, onChange: handleOpacityChange, className: menuClasses.imageLayerOpacitySlider, orientation: "horizontal", "aria-label": `Adjust opacity for layer ${label2}` }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(ImageLayerEllipsisMenu, { colormap, setColormap, photometricInterpretation, setPhotometricInterpretation, spatialTargetResolution, setSpatialTargetResolution, spatialLodFactor, setSpatialLodFactor, volumetricRenderingAlgorithm, setVolumetricRenderingAlgorithm, spatialLayerTransparentColor, setSpatialLayerTransparentColor, spatialRenderingMode, image: image2, channelScopes, tooltipsVisible, setTooltipsVisible, channelLabelsVisible, setChannelLabelsVisible, channelLabelsOrientation, setChannelLabelsOrientation, channelLabelSize, setChannelLabelSize }) }), jsxs(Grid$1, { size: 1, container: true, direction: "row", children: [jsx$1(ImageIcon, { className: classes2.layerTypeImageIcon }), isMultiChannel ? jsx$1(Button, { onClick: handleOpenChange, className: classes2.channelExpansionButton, "aria-label": "Expand or collapse channel controls", children: open2 ? jsx$1(ExpandLess, {}) : jsx$1(ExpandMoreIcon, {}) }) : null] })] }), isMultiChannel && open2 ? jsxs(Grid$1, { container: true, direction: "column", justifyContent: "space-between", className: classes2.imageChannelControllerGrid, children: [channelScopes.map((cScope) => {
265455
+ return jsx$1(Grid$1, { className: controllerSectionClasses.layerControllerGrid, children: jsxs(Paper, { elevation: 4, className: controllerSectionClasses.layerControllerRoot, children: [jsxs(Grid$1, { container: true, direction: "row", justifyContent: "space-between", children: [jsx$1(Grid$1, { size: 1, children: jsx$1(Button, { className: menuClasses.imageLayerVisibleButton, onClick: handleVisibleChange, "aria-label": "Toggle layer visibility", children: jsx$1(Visibility, {}) }) }), jsx$1(Grid$1, { size: 1 }), jsx$1(Grid$1, { size: 6, children: jsx$1(Typography, { className: menuClasses.imageLayerName, children: label2 }) }), jsx$1(Grid$1, { size: 2, children: jsx$1(Slider, { value: opacity2, min: 0, max: 1, step: 1e-3, onChange: handleOpacityChange, className: menuClasses.imageLayerOpacitySlider, orientation: "horizontal", "aria-label": `Adjust opacity for layer ${label2}` }) }), jsx$1(Grid$1, { size: 1, children: jsx$1(ImageLayerEllipsisMenu, { colormap, setColormap, photometricInterpretation, setPhotometricInterpretation, spatialTargetResolution, setSpatialTargetResolution, spatialLodFactor, setSpatialLodFactor, volumetricRenderingAlgorithm, setVolumetricRenderingAlgorithm, spatialLayerTransparentColor, setSpatialLayerTransparentColor, spatialRenderingMode, image: image2, channelScopes, tooltipsVisible, setTooltipsVisible, channelLabelsVisible, setChannelLabelsVisible, channelLabelsOrientation, setChannelLabelsOrientation, channelLabelSize, setChannelLabelSize, channelsSortOrder, setChannelsSortOrder }) }), jsxs(Grid$1, { size: 1, container: true, direction: "row", children: [jsx$1(ImageIcon, { className: classes2.layerTypeImageIcon }), isMultiChannel ? jsx$1(Button, { onClick: handleOpenChange, className: classes2.channelExpansionButton, "aria-label": "Expand or collapse channel controls", children: open2 ? jsx$1(ExpandLess, {}) : jsx$1(ExpandMoreIcon, {}) }) : null] })] }), isMultiChannel && open2 ? jsxs(Grid$1, { container: true, direction: "column", justifyContent: "space-between", className: classes2.imageChannelControllerGrid, children: [channelScopes.map((cScope) => {
265413
265456
  const { spatialTargetC, spatialChannelVisible, spatialChannelOpacity, spatialChannelColor, spatialChannelWindow, spatialMaxResolution } = channelCoordination[cScope];
265414
265457
  const { setSpatialTargetC, setSpatialChannelVisible, setSpatialChannelOpacity, setSpatialChannelColor, setSpatialChannelWindow, setSpatialMaxResolution } = setChannelCoordination[cScope];
265415
265458
  const channelIndex = image2?.getChannelIndex(spatialTargetC);
265416
265459
  const numResolutions = image2?.getNumResolutions();
265417
- return jsx$1(ImageChannelController, { theme, coordinationScopesRaw, layerScope, channelScope: cScope, targetT, targetZ, targetC: channelIndex, setTargetC: setSpatialTargetC, visible: spatialChannelVisible, setVisible: setSpatialChannelVisible, opacity: spatialChannelOpacity, setOpacity: setSpatialChannelOpacity, color: spatialChannelColor, setColor: setSpatialChannelColor, window: spatialChannelWindow, setWindow: setSpatialChannelWindow, colormapOn: colormap !== null, featureIndex, image: image2, spatialRenderingMode, numResolutions, spatialMaxResolution, setSpatialMaxResolution }, cScope);
265460
+ return jsx$1(ImageChannelController, { theme, coordinationScopesRaw, layerScope, channelScope: cScope, targetT, targetZ, targetC: channelIndex, setTargetC: setSpatialTargetC, visible: spatialChannelVisible, setVisible: setSpatialChannelVisible, opacity: spatialChannelOpacity, setOpacity: setSpatialChannelOpacity, color: spatialChannelColor, setColor: setSpatialChannelColor, window: spatialChannelWindow, setWindow: setSpatialChannelWindow, colormapOn: colormap !== null, featureIndex, image: image2, channelsSortOrder, spatialRenderingMode, numResolutions, spatialMaxResolution, setSpatialMaxResolution }, cScope);
265418
265461
  }), jsx$1(Button, { disabled: channelScopes.length === MAX_CHANNELS$1 || channelScopes.length === imageNumChannels, onClick: handleChannelAdd, fullWidth: true, variant: "outlined", className: classes2.imageLayerButton, startIcon: jsx$1(AddIcon, {}), size: "small", "aria-label": "Add a channel to this layer", children: "Add Channel" })] }) : null, is3dMode && image2 ? jsxs(Grid$1, { container: true, direction: "column", justifyContent: "space-between", className: classes2.imageChannelControllerGrid, children: [jsx$1(Typography, { className: classes2.clippingPanesLabel, children: "Clipping planes:" }), jsx$1(Grid$1, { size: 12, className: classes2.clippingSliders, children: jsx$1(ClippingSliders, { image: image2, spatialSliceX, spatialSliceY, spatialSliceZ, setSpatialSliceX, setSpatialSliceY, setSpatialSliceZ }) }), jsx$1(LoadingStatusIndicator, { loadingProgress: volumeLoadingProgress, onStopLoading: onStopVolumeLoading, onRestartLoading: onRestartVolumeLoading, stillRef: volumeStillRef, spatialRenderingMode })] }) : null] }) });
265419
265462
  }
265420
265463
  const useStyles$7 = makeStyles()((theme) => ({
@@ -265465,7 +265508,7 @@ function LayerController(props) {
265465
265508
  return jsxs("div", { children: [anyLayerHasZ ? jsx$1(GlobalDimensionSlider, { label: "Z", targetValue: targetZ, setTargetValue: setTargetZ, max: maxZ, spatialRenderingMode, setSpatialRenderingMode }) : null, anyLayerHasT ? jsx$1(GlobalDimensionSlider, { label: "T", targetValue: targetT, setTargetValue: setTargetT, max: maxT }) : null, pointLayerScopes && reversedPointLayerScopes.map((layerScope) => jsx$1(PointLayerController, { theme, layerScope, layerCoordination: pointLayerCoordination[0][layerScope], setLayerCoordination: pointLayerCoordination[1][layerScope], pointMatrixIndicesData: pointMultiIndicesData?.[layerScope], tiledPointsLoadingProgress, layerPerFeatureForPoints }, layerScope)), spotLayerScopes && reversedSpotLayerScopes.map((layerScope) => jsx$1(SpotLayerController, { theme, layerScope, layerCoordination: spotLayerCoordination[0][layerScope], setLayerCoordination: spotLayerCoordination[1][layerScope] }, layerScope)), segmentationLayerScopes && reversedSegmentationLayerScopes.map((layerScope) => jsx$1(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) => jsx$1(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))] });
265466
265509
  }
265467
265510
  function LayerControllerSubscriber(props) {
265468
- const { coordinationScopes: coordinationScopesRaw, coordinationScopesBy: coordinationScopesByRaw, closeButtonVisible, downloadButtonVisible, removeGridComponent, theme, title: title2 = "Spatial Layers", uuid: uuid2, layerPerFeatureForPoints = false, cameraPresets } = props;
265511
+ const { coordinationScopes: coordinationScopesRaw, coordinationScopesBy: coordinationScopesByRaw, closeButtonVisible, downloadButtonVisible, removeGridComponent, theme, title: title2 = "Spatial Layers", uuid: uuid2, layerPerFeatureForPoints = false, cameraPresets, helpText = ViewHelpMapping.LAYER_CONTROLLER_BETA } = props;
265469
265512
  const loaders = useLoaders();
265470
265513
  const mergeCoordination = useMergeCoordination();
265471
265514
  const coordinationScopes = useCoordinationScopes(coordinationScopesRaw);
@@ -265553,7 +265596,8 @@ function LayerControllerSubscriber(props) {
265553
265596
  CoordinationType$1.TOOLTIPS_VISIBLE,
265554
265597
  CoordinationType$1.SPATIAL_CHANNEL_LABELS_VISIBLE,
265555
265598
  CoordinationType$1.SPATIAL_CHANNEL_LABELS_ORIENTATION,
265556
- CoordinationType$1.SPATIAL_CHANNEL_LABEL_SIZE
265599
+ CoordinationType$1.SPATIAL_CHANNEL_LABEL_SIZE,
265600
+ CoordinationType$1.SPATIAL_CHANNELS_SORT_ORDER
265557
265601
  ], coordinationScopes, coordinationScopesBy, CoordinationType$1.IMAGE_LAYER);
265558
265602
  const imageChannelCoordination = useComplexCoordinationSecondary([
265559
265603
  CoordinationType$1.SPATIAL_TARGET_C,
@@ -265621,7 +265665,7 @@ function LayerControllerSubscriber(props) {
265621
265665
  imageDataStatus,
265622
265666
  pointMultiIndicesDataStatus
265623
265667
  ]);
265624
- return jsx$1(TitleInfo, { title: title2, isScroll: true, closeButtonVisible, downloadButtonVisible, removeGridComponent, theme, isReady, errors, children: jsx$1(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 }) });
265668
+ return jsx$1(TitleInfo, { title: title2, isScroll: true, closeButtonVisible, downloadButtonVisible, removeGridComponent, theme, isReady, errors, helpText, children: jsx$1(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 }) });
265625
265669
  }
265626
265670
  const isIterable$2 = (obj) => Symbol.iterator in obj;
265627
265671
  const hasIterableEntries = (value2) => (
@@ -267536,7 +267580,7 @@ function HiglassGlobalStyles(props) {
267536
267580
  }
267537
267581
  register({ dataFetcher: ZarrMultivecDataFetcher_default, config: ZarrMultivecDataFetcher_default.config }, { pluginType: "dataFetcher" });
267538
267582
  const LazyHiGlassComponent = React__default.lazy(async () => {
267539
- const { HiGlassComponent } = await import("./higlass-DIGh19X3.js");
267583
+ const { HiGlassComponent } = await import("./higlass-CGhpbMxK.js");
267540
267584
  return { default: HiGlassComponent };
267541
267585
  });
267542
267586
  const HG_SIZE = 800;
@@ -269125,13 +269169,16 @@ const globalNeuroglancerStyles = {
269125
269169
  },
269126
269170
  "input.perspective-panel-show-slice-views": { pointerEvents: "all" },
269127
269171
  ".neuroglancer-rendered-data-panel": {
269128
- cursor: "crosshair",
269172
+ cursor: "grab",
269129
269173
  position: "relative",
269130
269174
  outline: "0",
269131
269175
  touchAction: "none",
269132
269176
  color: "#fff",
269133
269177
  textAlign: "left"
269134
269178
  },
269179
+ ".neuroglancer-rendered-data-panel:active": {
269180
+ cursor: "grabbing"
269181
+ },
269135
269182
  ".neuroglancer-display-dimensions-widget": {
269136
269183
  position: "absolute",
269137
269184
  cursor: "default",
@@ -270484,7 +270531,7 @@ function NeuroglancerGlobalStyles(props) {
270484
270531
  const { classes: classes2 } = props;
270485
270532
  return jsxs(Fragment, { children: [jsx$1(GlobalStyles$3, { styles: globalNeuroglancerCss }), jsx$1(ScopedGlobalStyles, { styles: globalNeuroglancerStyles, parentClassName: classes2.neuroglancerWrapper })] });
270486
270533
  }
270487
- const LazyReactNeuroglancer = React__default.lazy(() => import("./ReactNeuroglancer-VYcAJw_c.js"));
270534
+ const LazyReactNeuroglancer = React__default.lazy(() => import("./ReactNeuroglancer-BuXB_Emb.js"));
270488
270535
  function createWorker() {
270489
270536
  const worker = new WorkerFactory$1();
270490
270537
  worker.AsyncComputationWorker = WorkerFactory;
@@ -271174,17 +271221,40 @@ function diffCameraState(prev2, next4) {
271174
271221
  const pos = posHard || posSoft;
271175
271222
  return { changed: scale2 || pos || rot2, scale: scale2, pos, rot: rot2 };
271176
271223
  }
271224
+ const clamp$1 = (value2, min2, max2) => Math.max(min2, Math.min(max2, value2));
271177
271225
  function quaternionToEuler([x2, y2, z2, w2]) {
271178
- const quaternion2 = new Quaternion$1(x2, y2, z2, w2);
271179
- const euler = new Euler$1().setFromQuaternion(quaternion2, "YXZ");
271180
- const pitch = euler.x;
271181
- const yaw = euler.y;
271226
+ const x22 = x2 + x2;
271227
+ const y22 = y2 + y2;
271228
+ const z22 = z2 + z2;
271229
+ const xx = x2 * x22;
271230
+ const yy = y2 * y22;
271231
+ const zz = z2 * z22;
271232
+ const xz = x2 * z22;
271233
+ const yz = y2 * z22;
271234
+ const wx = w2 * x22;
271235
+ const wy = w2 * y22;
271236
+ const m11 = 1 - (yy + zz);
271237
+ const m13 = xz + wy;
271238
+ const m23 = yz - wx;
271239
+ const m31 = xz - wy;
271240
+ const m33 = 1 - (xx + yy);
271241
+ const pitch = Math.asin(-clamp$1(m23, -1, 1));
271242
+ const yaw = Math.abs(m23) < 0.9999999 ? Math.atan2(m13, m33) : Math.atan2(-m31, m11);
271182
271243
  return [pitch, yaw];
271183
271244
  }
271184
271245
  function eulerToQuaternion(pitch, yaw, roll = 0) {
271185
- const euler = new Euler$1(pitch, yaw, roll, "YXZ");
271186
- const quaternion2 = new Quaternion$1().setFromEuler(euler);
271187
- return [quaternion2.x, quaternion2.y, quaternion2.z, quaternion2.w];
271246
+ const c1 = Math.cos(pitch / 2);
271247
+ const c2 = Math.cos(yaw / 2);
271248
+ const c3 = Math.cos(roll / 2);
271249
+ const s1 = Math.sin(pitch / 2);
271250
+ const s2 = Math.sin(yaw / 2);
271251
+ const s3 = Math.sin(roll / 2);
271252
+ return [
271253
+ s1 * c2 * c3 + c1 * s2 * s3,
271254
+ c1 * s2 * c3 - s1 * c2 * s3,
271255
+ c1 * c2 * s3 - s1 * s2 * c3,
271256
+ c1 * c2 * c3 + s1 * s2 * s3
271257
+ ];
271188
271258
  }
271189
271259
  function makeVitNgZoomCalibrator(initialNgProjectionScale, initialDeckZoom = 0) {
271190
271260
  const base2 = initialNgProjectionScale / 2 ** -initialDeckZoom;
@@ -273495,7 +273565,7 @@ function useFilteredVolcanoData(props) {
273495
273565
  const rawSampleSetPathB = coordinationValues.sampleSetFilter[1];
273496
273566
  const sampleSetPathB = [...rawSampleSetPathB];
273497
273567
  sampleSetPathB[0] = sampleSetsColumnNameMappingReversed[rawSampleSetPathB[0]];
273498
- if (isEqual$3(sampleSetPathA, sampleSetSelection[1]) && isEqual$3(sampleSetPathB, sampleSetSelection[0])) {
273568
+ if (isEqual$3(sampleSetPathA, sampleSetSelection[0]) && isEqual$3(sampleSetPathB, sampleSetSelection[1])) {
273499
273569
  shouldSwapFoldChangeDirection = true;
273500
273570
  }
273501
273571
  }
@@ -324325,8 +324395,8 @@ function CellSetSizesPlot(props) {
324325
324395
  value: 0
324326
324396
  }
324327
324397
  },
324328
- width: clamp$7(width2 - marginRight, 10, Infinity),
324329
- height: clamp$7(height2 - marginBottom, 10, Infinity),
324398
+ width: clamp$8(width2 - marginRight, 10, Infinity),
324399
+ height: clamp$8(height2 - marginBottom, 10, Infinity),
324330
324400
  config: VEGA_THEMES[theme]
324331
324401
  };
324332
324402
  const handleSignal = (name2, value2) => {
@@ -324439,8 +324509,8 @@ function ExpressionHistogram(props) {
324439
324509
  select: { type: "interval", encodings: ["x"] }
324440
324510
  }
324441
324511
  ],
324442
- width: clamp$7(width2 - marginRight, 10, Infinity),
324443
- height: clamp$7(height2 - marginBottom, 10, Infinity),
324512
+ width: clamp$8(width2 - marginRight, 10, Infinity),
324513
+ height: clamp$8(height2 - marginBottom, 10, Infinity),
324444
324514
  config: VEGA_THEMES[theme]
324445
324515
  };
324446
324516
  const handleSignal = (name2, value2) => {
@@ -324575,8 +324645,8 @@ function DotPlot(props) {
324575
324645
  const autoMarginForFeature = marginBottom || 30 + Math.sqrt(maxCharactersForFeature / 2) * 30;
324576
324646
  const autoMarginForGroup = marginRight || 30 + Math.sqrt(maxCharactersForGroup / 2) * 30;
324577
324647
  const autoMarginForSampleSet = marginRight || 30 + Math.sqrt(maxCharactersForSampleSet / 2) * 30;
324578
- const plotWidth = transpose2 ? clamp$7(width2 - autoMarginForFeature - 180, 10, Infinity) / (obsSetSelection?.length || 1) : clamp$7(width2 - autoMarginForGroup - autoMarginForSampleSet - 200, 10, Infinity);
324579
- const plotHeight = transpose2 ? clamp$7(height2 - autoMarginForGroup - autoMarginForSampleSet - 50, 10, Infinity) : clamp$7(height2 - autoMarginForFeature - 80, 10, Infinity) / (obsSetSelection?.length || 1);
324648
+ const plotWidth = transpose2 ? clamp$8(width2 - autoMarginForFeature - 180, 10, Infinity) / (obsSetSelection?.length || 1) : clamp$8(width2 - autoMarginForGroup - autoMarginForSampleSet - 200, 10, Infinity);
324649
+ const plotHeight = transpose2 ? clamp$8(height2 - autoMarginForGroup - autoMarginForSampleSet - 50, 10, Infinity) : clamp$8(height2 - autoMarginForFeature - 80, 10, Infinity) / (obsSetSelection?.length || 1);
324580
324650
  const groupKeys = data2.map((d) => d.keyGroup);
324581
324651
  const featureKeys = data2.map((d) => d.keyFeature);
324582
324652
  const groupSecondaryKeys = data2.map((d) => d.keyGroupSecondary);
@@ -325249,6 +325319,10 @@ function TreemapSubscriber(props) {
325249
325319
  }, [setObsSetSelection]);
325250
325320
  return jsxs(TitleInfo, { title: `Treemap of ${capitalize$3(pluralize(obsType, 2))}`, info: `${commaNumber(selectedObsCount)} ${pluralize(obsType, selectedObsCount)} from ${commaNumber(selectedSampleCount)} ${pluralize(sampleType, selectedSampleCount)}`, removeGridComponent, urls: urls2, theme, isReady, helpText, errors, withPadding: false, options: jsx$1(TreemapOptions, { obsType, sampleType, obsColorEncoding, setObsColorEncoding, hierarchyLevels: hierarchyLevels || DEFAULT_HIERARCHY_LEVELS, setHierarchyLevels }), children: [jsx$1("div", { ref: containerRef, className: classes2.vegaContainer, children: jsx$1(Treemap, { obsCounts, sampleCounts, obsColorEncoding, hierarchyLevels: hierarchyLevels || DEFAULT_HIERARCHY_LEVELS, theme, width: width2, height: Math.max(height2 * (selectedObsCount / totalObsCount), 40), obsType, sampleType, obsSetColor, sampleSetColor, obsSetSelection, sampleSetSelection, onNodeClick }) }), jsx$1("div", { style: { position: "absolute", right: "2px", bottom: "2px", fontSize: "10px" }, children: unselectedObsCount > 0 ? jsx$1("span", { children: `${commaNumber(unselectedObsCount)} ${pluralize(obsType, unselectedObsCount)} from ${commaNumber(unselectedSampleCount)} ${pluralize(sampleType, unselectedSampleCount)} currently omitted` }) : null })] });
325251
325321
  }
325322
+ const GOLDEN_RATIO = 0.6180339887498948;
325323
+ function topJitter(index2, rangePixels) {
325324
+ return index2 * GOLDEN_RATIO % 1 * rangePixels;
325325
+ }
325252
325326
  function VolcanoPlot(props) {
325253
325327
  const { theme, width: width2, height: height2, obsType, featureType, obsSetsColumnNameMappingReversed, sampleSetsColumnNameMappingReversed, sampleSetSelection, obsSetSelection, obsSetColor, sampleSetColor, data: data2, marginTop = 5, marginRight = 5, marginLeft = 50, marginBottom = 50, onFeatureClick, featurePointSignificanceThreshold, featurePointFoldChangeThreshold, featureLabelSignificanceThreshold, featureLabelFoldChangeThreshold } = props;
325254
325328
  const svgRef = useRef();
@@ -325310,10 +325384,10 @@ function VolcanoPlot(props) {
325310
325384
  const obsSetPath2 = [...rawObsSetPath];
325311
325385
  obsSetPath2[0] = obsSetsColumnNameMappingReversed[rawObsSetPath[0]];
325312
325386
  const color2 = obsSetColorScale(obsSetPath2);
325313
- obsSetG.append("g").selectAll("circle").data(filteredDf).join("circle").attr("cx", (d) => xScale(d.logFoldChange)).attr("cy", (d) => yScale(d.minusLog10p)).attr("r", 3).attr("opacity", 0.5).attr("fill", color2).on("click", (event2, d) => {
325387
+ obsSetG.append("g").selectAll("circle").data(filteredDf).join("circle").attr("cx", (d) => xScale(d.logFoldChange)).attr("cy", (d, i2) => yScale(d.minusLog10p) + (!Number.isFinite(d.minusLog10p) ? topJitter(i2, 20) : 0)).attr("r", 3).attr("opacity", 0.5).attr("fill", color2).on("click", (event2, d) => {
325314
325388
  onFeatureClick(d.featureId);
325315
325389
  });
325316
- const textElements = obsSetG.append("g").selectAll("text").data(filteredDf).join("text").text((d) => d.featureId).attr("text-anchor", (d) => d.logFoldChange < 0 ? "end" : "start").attr("x", (d) => xScale(d.logFoldChange)).attr("y", (d) => yScale(d.minusLog10p)).style("display", (d) => Math.abs(d.logFoldChange) < (featureLabelFoldChangeThreshold ?? 5) || d.featureSignificance >= (featureLabelSignificanceThreshold ?? 0.01) ? "none" : void 0).attr("fill", color2).on("click", (event2, d) => {
325390
+ const textElements = obsSetG.append("g").selectAll("text").data(filteredDf).join("text").text((d) => d.featureId).attr("text-anchor", (d) => d.logFoldChange < 0 ? "end" : "start").attr("x", (d) => xScale(d.logFoldChange)).attr("y", (d, i2) => yScale(d.minusLog10p) + (!Number.isFinite(d.minusLog10p) ? topJitter(i2, 20) : 0)).style("display", (d) => Math.abs(d.logFoldChange) < (featureLabelFoldChangeThreshold ?? 5) || d.featureSignificance >= (featureLabelSignificanceThreshold ?? 0.01) ? "none" : void 0).attr("fill", color2).on("click", (event2, d) => {
325317
325391
  onFeatureClick(d.featureId);
325318
325392
  });
325319
325393
  textElements.append("title").text((d) => `${featureType}: ${d.featureId}
@@ -325572,8 +325646,8 @@ function CellSetCompositionBarPlot(props) {
325572
325646
  }
325573
325647
  },
325574
325648
  // TODO: for width, also subtract length of longest y-axis set name label.
325575
- width: clamp$7(width2 - marginRight, 10, Infinity),
325576
- height: clamp$7(height2 - marginBottom, 10, Infinity),
325649
+ width: clamp$8(width2 - marginRight, 10, Infinity),
325650
+ height: clamp$8(height2 - marginBottom, 10, Infinity),
325577
325651
  config: VEGA_THEMES[theme]
325578
325652
  };
325579
325653
  const handleSignal = (name2, value2) => {
@@ -325754,8 +325828,8 @@ function FeatureSetEnrichmentBarPlot(props) {
325754
325828
  }
325755
325829
  },
325756
325830
  // TODO: for width, also subtract length of longest y-axis set name label.
325757
- width: clamp$7(width2 - marginRight, 10, Infinity),
325758
- height: clamp$7(height2 - marginBottom, 10, Infinity),
325831
+ width: clamp$8(width2 - marginRight, 10, Infinity),
325832
+ height: clamp$8(height2 - marginBottom, 10, Infinity),
325759
325833
  config: VEGA_THEMES[theme]
325760
325834
  };
325761
325835
  const handleSignal = (name2, value2) => {
@@ -326287,7 +326361,9 @@ class OmeAutoConfig extends AbstractAutoConfig {
326287
326361
  // TODO: how to handle h5ad-based AnnData (since needs reference JSON file).
326288
326362
  // Perhaps just assume one H5AD+one JSON (or .ref.json) file correspond to each other?
326289
326363
  [FileType$1.SPATIALDATA_ZARR]: [".sd.zarr", ".sdata.zarr", ".spatialdata.zarr"],
326290
- [FileType$1.SPATIALDATA_ZARR_ZIP]: [".sd.zarr.zip", ".sdata.zarr.zip", ".spatialdata.zarr.zip"]
326364
+ [FileType$1.SPATIALDATA_ZARR_ZIP]: [".sd.zarr.zip", ".sdata.zarr.zip", ".spatialdata.zarr.zip"],
326365
+ [FileType$1.GENOMIC_PROFILES_ZARR]: [".multivec.zarr"],
326366
+ [FileType$1.GENOMIC_PROFILES_ZARR_ZIP]: [".multivec.zarr.zip"]
326291
326367
  });
326292
326368
  ({
326293
326369
  // OME-TIFF
@@ -326313,8 +326389,106 @@ class OmeAutoConfig extends AbstractAutoConfig {
326313
326389
  FileType$1.IMAGE_OME_ZARR,
326314
326390
  FileType$1.IMAGE_OME_ZARR_ZIP,
326315
326391
  FileType$1.OBS_SEGMENTATIONS_OME_ZARR,
326316
- FileType$1.OBS_SEGMENTATIONS_OME_ZARR_ZIP
326392
+ FileType$1.OBS_SEGMENTATIONS_OME_ZARR_ZIP,
326393
+ FileType$1.GENOMIC_PROFILES_ZARR,
326394
+ FileType$1.GENOMIC_PROFILES_ZARR_ZIP
326317
326395
  ];
326396
+ var fetchJsonp$1 = { exports: {} };
326397
+ var fetchJsonp = fetchJsonp$1.exports;
326398
+ var hasRequiredFetchJsonp;
326399
+ function requireFetchJsonp() {
326400
+ if (hasRequiredFetchJsonp) return fetchJsonp$1.exports;
326401
+ hasRequiredFetchJsonp = 1;
326402
+ (function(module2, exports2) {
326403
+ (function(global2, factory2) {
326404
+ {
326405
+ factory2(exports2, module2);
326406
+ }
326407
+ })(fetchJsonp, function(exports3, module3) {
326408
+ var defaultOptions = {
326409
+ timeout: 5e3,
326410
+ jsonpCallback: "callback"
326411
+ };
326412
+ function generateCallbackFunction() {
326413
+ return "jsonp_" + Date.now() + "_" + Math.ceil(Math.random() * 1e5);
326414
+ }
326415
+ function clearFunction(functionName) {
326416
+ try {
326417
+ delete window[functionName];
326418
+ } catch (e3) {
326419
+ window[functionName] = void 0;
326420
+ }
326421
+ }
326422
+ function removeScript(scriptId) {
326423
+ var script = document.getElementById(scriptId);
326424
+ if (script) {
326425
+ document.getElementsByTagName("head")[0].removeChild(script);
326426
+ }
326427
+ }
326428
+ function fetchJsonp2(_url) {
326429
+ var options = arguments.length <= 1 || arguments[1] === void 0 ? {} : arguments[1];
326430
+ var url = _url;
326431
+ var timeout3 = options.timeout || defaultOptions.timeout;
326432
+ var jsonpCallback = options.jsonpCallback || defaultOptions.jsonpCallback;
326433
+ var timeoutId = void 0;
326434
+ return new Promise(function(resolve2, reject) {
326435
+ var callbackFunction = options.jsonpCallbackFunction || generateCallbackFunction();
326436
+ var scriptId = jsonpCallback + "_" + callbackFunction;
326437
+ window[callbackFunction] = function(response) {
326438
+ resolve2({
326439
+ ok: true,
326440
+ // keep consistent with fetch API
326441
+ json: function json2() {
326442
+ return Promise.resolve(response);
326443
+ }
326444
+ });
326445
+ if (timeoutId) clearTimeout(timeoutId);
326446
+ removeScript(scriptId);
326447
+ clearFunction(callbackFunction);
326448
+ };
326449
+ url += url.indexOf("?") === -1 ? "?" : "&";
326450
+ var jsonpScript = document.createElement("script");
326451
+ jsonpScript.setAttribute("src", "" + url + jsonpCallback + "=" + callbackFunction);
326452
+ if (options.charset) {
326453
+ jsonpScript.setAttribute("charset", options.charset);
326454
+ }
326455
+ if (options.nonce) {
326456
+ jsonpScript.setAttribute("nonce", options.nonce);
326457
+ }
326458
+ if (options.referrerPolicy) {
326459
+ jsonpScript.setAttribute("referrerPolicy", options.referrerPolicy);
326460
+ }
326461
+ if (options.crossorigin) {
326462
+ jsonpScript.setAttribute("crossorigin", typeof options.crossorigin === "string" ? options.crossorigin : "anonymous");
326463
+ }
326464
+ var fp = options.fetchPriority;
326465
+ if (fp === "high" || fp === "low" || fp === "auto") {
326466
+ jsonpScript.setAttribute("fetchPriority", fp);
326467
+ }
326468
+ jsonpScript.id = scriptId;
326469
+ document.getElementsByTagName("head")[0].appendChild(jsonpScript);
326470
+ timeoutId = setTimeout(function() {
326471
+ reject(new Error("JSONP request to " + _url + " timed out"));
326472
+ clearFunction(callbackFunction);
326473
+ removeScript(scriptId);
326474
+ window[callbackFunction] = function() {
326475
+ clearFunction(callbackFunction);
326476
+ };
326477
+ }, timeout3);
326478
+ jsonpScript.onerror = function() {
326479
+ reject(new Error("JSONP request to " + _url + " failed"));
326480
+ clearFunction(callbackFunction);
326481
+ removeScript(scriptId);
326482
+ if (timeoutId) clearTimeout(timeoutId);
326483
+ };
326484
+ });
326485
+ }
326486
+ module3.exports = fetchJsonp2;
326487
+ });
326488
+ })(fetchJsonp$1, fetchJsonp$1.exports);
326489
+ return fetchJsonp$1.exports;
326490
+ }
326491
+ requireFetchJsonp();
326318
326492
  class ObsSpotsCsvLoader extends CsvLoader {
326319
326493
  loadFromCache(data2) {
326320
326494
  if (this.cachedResult) {
@@ -327229,11 +327403,21 @@ class AnnDataSource extends ZarrDataSource {
327229
327403
  categoriesValues = await this.getFlatArrDecompressed(`${prefix2}/${categories}`);
327230
327404
  }
327231
327405
  } else if (encodingType === "categorical") {
327232
- const { dtype } = await open$1(storeRoot.resolve(`${path2}/categories`), { kind: "array" });
327233
- if (dtype === "v2:object" || dtype === "|O") {
327406
+ const categoriesZattrs = await this.getJson(`${path2}/categories/.zattrs`);
327407
+ const categoriesEncodingType = categoriesZattrs?.["encoding-type"];
327408
+ if (categoriesEncodingType === "nullable-string-array") {
327409
+ categoriesValues = await this.getFlatArrDecompressed(`${path2}/categories/values`);
327410
+ } else if (categoriesEncodingType === "string-array") {
327234
327411
  categoriesValues = await this.getFlatArrDecompressed(`${path2}/categories`);
327412
+ } else {
327413
+ const { dtype } = await open$1(storeRoot.resolve(`${path2}/categories`), { kind: "array" });
327414
+ if (dtype === "v2:object" || dtype === "|O") {
327415
+ categoriesValues = await this.getFlatArrDecompressed(`${path2}/categories`);
327416
+ }
327235
327417
  }
327236
327418
  codesPath = `${path2}/codes`;
327419
+ } else if (encodingType === "nullable-string-array") {
327420
+ return this.getFlatArrDecompressed(`${path2}/values`);
327237
327421
  } else if (encodingType === "string-array") {
327238
327422
  return this.getFlatArrDecompressed(path2);
327239
327423
  } else {
@@ -328397,16 +328581,25 @@ let FeatureStatsAnndataLoader$1 = class FeatureStatsAnndataLoader extends Abstra
328397
328581
  return this.dataSource.loadDataFrameIndex(dfPath);
328398
328582
  }
328399
328583
  async loadDataFrame(dfPath) {
328400
- const [featureId2, featureFoldChange, featureSignificance] = await Promise.all([
328401
- this.loadFeatureNames(dfPath),
328402
- this.loadFoldChanges(dfPath),
328403
- this.loadSignificances(dfPath)
328404
- ]);
328405
- return {
328406
- featureId: featureId2,
328407
- featureFoldChange,
328408
- featureSignificance
328409
- };
328584
+ try {
328585
+ const [featureId2, featureFoldChange, featureSignificance] = await Promise.all([
328586
+ this.loadFeatureNames(dfPath),
328587
+ this.loadFoldChanges(dfPath),
328588
+ this.loadSignificances(dfPath)
328589
+ ]);
328590
+ return {
328591
+ featureId: featureId2,
328592
+ featureFoldChange,
328593
+ featureSignificance
328594
+ };
328595
+ } catch (e3) {
328596
+ log$b.warn("Dataframe not found at", dfPath);
328597
+ return {
328598
+ featureId: [],
328599
+ featureFoldChange: [],
328600
+ featureSignificance: []
328601
+ };
328602
+ }
328410
328603
  }
328411
328604
  /**
328412
328605
  *
@@ -328433,7 +328626,7 @@ let FeatureStatsAnndataLoader$1 = class FeatureStatsAnndataLoader extends Abstra
328433
328626
  * @returns {Promise<LoaderResult<FeatureStatsData>>}
328434
328627
  */
328435
328628
  async loadMulti(volcanoOptions) {
328436
- const { analysisType: targetAnalysisType = "rank_genes_groups" } = this.options;
328629
+ const { analysisType: targetAnalysisType = "pydeseq2" } = this.options;
328437
328630
  const { sampleSetSelection, obsSetSelection } = volcanoOptions || {};
328438
328631
  const rawObsSetSelection = obsSetSelection;
328439
328632
  const rawSampleSetSelection = sampleSetSelection;
@@ -329411,7 +329604,7 @@ class SpatialDataObsSpotsLoader extends AbstractTwoStepLoader {
329411
329604
  const formatVersion = await this.dataSource.getShapesFormatVersion(path2);
329412
329605
  if (formatVersion === "0.1") {
329413
329606
  locations = await this.dataSource.loadNumericForDims(getCoordsPath(path2), [0, 1]);
329414
- } else if (formatVersion === "0.2") {
329607
+ } else if (formatVersion === "0.2" || formatVersion === "0.3") {
329415
329608
  locations = await this.dataSource.loadCircleShapes(getGeometryPath$1(path2));
329416
329609
  }
329417
329610
  this.locations = locations;
@@ -329610,7 +329803,7 @@ class SpatialDataObsPointsLoader extends AbstractTwoStepLoader {
329610
329803
  }
329611
329804
  let locations;
329612
329805
  const formatVersion = await this.dataSource.getPointsFormatVersion(path2);
329613
- if (formatVersion === "0.1") {
329806
+ if (formatVersion === "0.1" || formatVersion === "0.2") {
329614
329807
  locations = await this.dataSource.loadPoints(path2);
329615
329808
  } else {
329616
329809
  throw new UnknownSpatialDataFormatError("Only points format version 0.1 is supported.");
@@ -329629,7 +329822,7 @@ class SpatialDataObsPointsLoader extends AbstractTwoStepLoader {
329629
329822
  }
329630
329823
  let locationsFeatureIndex;
329631
329824
  const formatVersion = await this.dataSource.getPointsFormatVersion(path2);
329632
- if (formatVersion === "0.1") {
329825
+ if (formatVersion === "0.1" || formatVersion === "0.2") {
329633
329826
  locationsFeatureIndex = await this.dataSource.loadPointsFeatureIds(path2);
329634
329827
  } else {
329635
329828
  throw new UnknownSpatialDataFormatError("Only points format version 0.1 is supported.");
@@ -329641,7 +329834,7 @@ class SpatialDataObsPointsLoader extends AbstractTwoStepLoader {
329641
329834
  const { path: path2, featureIndexColumn, mortonCodeColumn } = this.options;
329642
329835
  let locations;
329643
329836
  const formatVersion = await this.dataSource.getPointsFormatVersion(path2);
329644
- if (formatVersion === "0.1") {
329837
+ if (formatVersion === "0.1" || formatVersion === "0.2") {
329645
329838
  locations = await this.dataSource.loadPointsInRect(path2, bounds2, signal, featureIndexColumn, mortonCodeColumn);
329646
329839
  } else {
329647
329840
  throw new UnknownSpatialDataFormatError("Only points format version 0.1 is supported.");
@@ -329673,10 +329866,8 @@ class SpatialDataObsPointsLoader extends AbstractTwoStepLoader {
329673
329866
  // and for the presence of morton_code_2d and feature_index columns.
329674
329867
  this.dataSource.supportsLoadPointsInRect(path2, featureIndexColumnName, mortonCodeColumn)
329675
329868
  ]);
329676
- const isSupportedVersion = formatVersion === "0.1";
329677
- const boundingBox = zattrs?.bounding_box;
329678
- const hasBoundingBox2D = typeof boundingBox?.x_max === "number" && typeof boundingBox?.x_min === "number" && typeof boundingBox?.y_max === "number" && typeof boundingBox?.y_min === "number";
329679
- return isSupportedVersion && hasBoundingBox2D && hasRequiredColumnsAndRowGroupSize;
329869
+ const isSupportedVersion = formatVersion === "0.1" || formatVersion === "0.2";
329870
+ return isSupportedVersion && hasRequiredColumnsAndRowGroupSize;
329680
329871
  }
329681
329872
  async load() {
329682
329873
  const [modelMatrix2, supportsTiling] = await Promise.all([
@@ -329714,7 +329905,7 @@ class SpatialDataObsPointsLoader extends AbstractTwoStepLoader {
329714
329905
  featureIds,
329715
329906
  obsPointsModelMatrix: modelMatrix2,
329716
329907
  // Return 'tiled' if the morton_code_2d column
329717
- // and bounding_box metadata are present,
329908
+ // is present,
329718
329909
  // and the row group size is small enough.
329719
329910
  // Otherwise, return 'full'.
329720
329911
  obsPointsTilingType: supportsTiling ? "tiled" : "full",
@@ -339223,6 +339414,7 @@ function sdataMortonQueryRectAux(boundingBox, origRect) {
339223
339414
  const mortonIntervals = zcoverRectangle(normRect[0][0], normRect[0][1], normRect[1][0], normRect[1][1], 16, null, true);
339224
339415
  return mortonIntervals;
339225
339416
  }
339417
+ const MORTON_CODE_EXTREME_VALUE_INDICATOR = 0;
339226
339418
  async function getParquetModule() {
339227
339419
  const module2 = await import(
339228
339420
  /* webpackIgnore: true */
@@ -339301,7 +339493,7 @@ async function _loadParquetSchemaBytes({ queryClient, store }, parquetPath, part
339301
339493
  if (!tailBytes || tailBytes.length < TAIL_LENGTH) {
339302
339494
  throw new Error(`Failed to load parquet footerLength for ${partZeroPath}`);
339303
339495
  }
339304
- const footerLength = new DataView(tailBytes.buffer).getInt32(0, true);
339496
+ const footerLength = new DataView(tailBytes.buffer, tailBytes.byteOffset, tailBytes.byteLength).getInt32(0, true);
339305
339497
  const magic = new TextDecoder().decode(tailBytes.slice(4, 8));
339306
339498
  if (magic !== "PAR1") {
339307
339499
  throw new Error("Invalid Parquet file: missing PAR1 magic number");
@@ -339348,22 +339540,22 @@ async function _loadParquetMetadataByPart({ queryClient, store }, parquetPath) {
339348
339540
  } catch (error2) {
339349
339541
  if (error2.message.includes("Failed to load parquet footerLength")) {
339350
339542
  numParts = partIndex;
339543
+ log$b.info(`Found ${numParts} parts for parquet path ${parquetPath}; An above "Failed to load parquet footerLength" error is expected for the subsequent part.`);
339351
339544
  }
339352
339545
  }
339353
339546
  } while (numParts === void 0);
339547
+ const numRows = allMetadata.map((part) => part.metadata.fileMetadata().numRows());
339548
+ const numRowGroups = allMetadata.map((part) => part.metadata.numRowGroups());
339549
+ const numRowsPerGroup = allMetadata.map((part) => part.metadata.rowGroup(0).numRows());
339354
339550
  const metadata2 = {
339355
- numRows: 0,
339356
- numRowGroups: 0,
339357
- numRowsPerGroup: 0,
339358
- schema: null
339359
- };
339360
- if (allMetadata.length > 0) {
339361
- const firstPart = allMetadata[0];
339362
- metadata2.numRows = allMetadata.reduce((sum2, part) => sum2 + part.metadata.fileMetadata().numRows(), 0);
339363
- metadata2.numRowGroups = allMetadata.reduce((sum2, part) => sum2 + part.metadata.numRowGroups(), 0);
339364
- metadata2.numRowsPerGroup = firstPart.metadata.rowGroup(0).numRows();
339365
- metadata2.schema = firstPart.schema.schema;
339366
- }
339551
+ totalNumRows: numRows.reduce((a2, b2) => a2 + b2, 0),
339552
+ totalNumRowGroups: numRowGroups.reduce((a2, b2) => a2 + b2, 0),
339553
+ // Array of count per part (length equal to numParts).
339554
+ numRowsByPart: numRows,
339555
+ numRowGroupsByPart: numRowGroups,
339556
+ numRowsPerGroupByPart: numRowsPerGroup,
339557
+ schema: allMetadata?.[0]?.schema?.schema
339558
+ };
339367
339559
  const result = {
339368
339560
  ...metadata2,
339369
339561
  // TODO: extract metadata per part and rowGroup into plain objects that match the hyparquet parquetMetadata() return value?
@@ -339387,8 +339579,8 @@ async function _loadParquetRowGroupByGroupIndex({ queryClient, store }, parquetP
339387
339579
  const store2 = ctx.meta?.store;
339388
339580
  const { readParquetRowGroup } = await _getParquetModule({ queryClient: queryClient2 });
339389
339581
  const allMetadata = await _loadParquetMetadataByPart({ queryClient: queryClient2, store: store2 }, parquetPath);
339390
- if (rowGroupIndex < 0 || rowGroupIndex >= allMetadata.numRowGroups) {
339391
- throw new Error(`Row group index ${rowGroupIndex} is out of bounds for parquet table with ${allMetadata.numRowGroups} row groups.`);
339582
+ if (rowGroupIndex < 0 || rowGroupIndex >= allMetadata.totalNumRowGroups) {
339583
+ throw new Error(`Row group index ${rowGroupIndex} is out of bounds for parquet table with ${allMetadata.totalNumRowGroups} row groups.`);
339392
339584
  }
339393
339585
  let partIndex;
339394
339586
  let cumulativeRowGroups = 0;
@@ -339498,9 +339690,9 @@ async function _bisectRowGroupsRight({ queryClient, store }, parquetPath, column
339498
339690
  );
339499
339691
  const store2 = ctx.meta?.store;
339500
339692
  const allMetadata = await _loadParquetMetadataByPart({ queryClient: queryClient2, store: store2 }, parquetPath);
339501
- const { numRowGroups } = allMetadata;
339693
+ const { totalNumRowGroups } = allMetadata;
339502
339694
  let lo = 0;
339503
- let hi = numRowGroups;
339695
+ let hi = totalNumRowGroups;
339504
339696
  while (lo < hi) {
339505
339697
  const cachedInRange = await getCachedInRange(queryClient2, parquetPath, columnName, lo, hi);
339506
339698
  const betterLo = cachedInRange.slice().reverse().find((c2) => c2.index > lo && targetValue >= c2.max);
@@ -339903,11 +340095,12 @@ class SpatialDataTableSource extends AnnDataSource {
339903
340095
  const { queryClient } = this;
339904
340096
  const { store } = this.storeRoot;
339905
340097
  const allMetadata = await _loadParquetMetadataByPart({ queryClient, store }, parquetPath);
339906
- const { numRowsPerGroup } = allMetadata;
339907
- const numRowsTotal = allMetadata.numRows;
339908
- if (numRowsPerGroup >= 1e5) {
340098
+ const { numRowsPerGroupByPart } = allMetadata;
340099
+ const numRowsTotal = allMetadata.totalNumRows;
340100
+ const maxNumRowsPerGroup = Math.max(...numRowsPerGroupByPart);
340101
+ if (maxNumRowsPerGroup >= 1e5) {
339909
340102
  if (numRowsTotal > 5e6) {
339910
- throw new Error(`The Parquet table at ${parquetPath} has ${numRowsTotal} total rows, which necessitates tiled loading, but it was not possible because the row group size is too large (${numRowsPerGroup}). See the Vitessce documentation at Data Troubleshooting -> Points for more details.`);
340103
+ throw new Error(`The Parquet table at ${parquetPath} has ${numRowsTotal} total rows, which necessitates tiled loading, but it was not possible because the row group size is too large (${maxNumRowsPerGroup}). See the Vitessce documentation at Data Troubleshooting -> Points for more details.`);
339911
340104
  }
339912
340105
  return false;
339913
340106
  }
@@ -339931,7 +340124,7 @@ class SpatialDataTableSource extends AnnDataSource {
339931
340124
  * @param {string[]|undefined} columns An optional list of column names to load.
339932
340125
  * @returns
339933
340126
  */
339934
- async loadParquetTableInRect(parquetPath, tileBbox, allPointsBbox, signal, featureIndexColumnName, mortonCodeColumn) {
340127
+ async loadParquetTableInRect(parquetPath, tileBbox, signal, featureIndexColumnName, mortonCodeColumn) {
339935
340128
  const { queryClient } = this;
339936
340129
  const { store } = this.storeRoot;
339937
340130
  const mortonCodeColumnName = mortonCodeColumn ?? "morton_code_2d";
@@ -339956,15 +340149,46 @@ class SpatialDataTableSource extends AnnDataSource {
339956
340149
  } else {
339957
340150
  tileBboxes = [tileBbox];
339958
340151
  }
340152
+ const firstRowGroupTable = await _loadParquetRowGroupByGroupIndex({ queryClient, store }, parquetPath, 0);
340153
+ const xColumnForBoundingBox = firstRowGroupTable.getChild("x");
340154
+ const yColumnForBoundingBox = firstRowGroupTable.getChild("y");
340155
+ const mortonCodeColumnForBoundingBox = firstRowGroupTable.getChild(mortonCodeColumnName);
340156
+ const boundingBoxMaxNumRows = Math.min(4, firstRowGroupTable.numRows);
340157
+ const firstMortonCodes = range$e(boundingBoxMaxNumRows).map((i2) => mortonCodeColumnForBoundingBox.get(i2));
340158
+ const boundingBoxNumRows = firstMortonCodes.filter((code2) => code2 === MORTON_CODE_EXTREME_VALUE_INDICATOR).length;
340159
+ const boundingBoxXValues = range$e(boundingBoxNumRows).map((i2) => xColumnForBoundingBox.get(i2));
340160
+ const boundingBoxYValues = range$e(boundingBoxNumRows).map((i2) => yColumnForBoundingBox.get(i2));
340161
+ const xMin = Math.min(...boundingBoxXValues);
340162
+ const xMax = Math.max(...boundingBoxXValues);
340163
+ const yMin = Math.min(...boundingBoxYValues);
340164
+ const yMax = Math.max(...boundingBoxYValues);
340165
+ const allPointsBbox = {
340166
+ x_min: xMin,
340167
+ x_max: xMax,
340168
+ y_min: yMin,
340169
+ y_max: yMax
340170
+ };
339959
340171
  const rowGroupIndicesPerTile = await Promise.all(tileBboxes.map(async (subTileBbox) => _rectToRowGroupIndices({ queryClient, store }, parquetPath, subTileBbox, allPointsBbox, mortonCodeColumnName)));
339960
340172
  const uniqueCoveredRowGroupIndices = Array.from(new Set(rowGroupIndicesPerTile.flat())).toSorted((a2, b2) => a2 - b2);
339961
340173
  const allMetadata = await _loadParquetMetadataByPart({ queryClient, store }, parquetPath);
339962
- const { numRowsPerGroup } = allMetadata;
339963
- const numRowGroups = uniqueCoveredRowGroupIndices.length;
339964
- const totalNumRows = numRowsPerGroup * numRowGroups;
339965
- const xArr = new Float32Array(totalNumRows);
339966
- const yArr = new Float32Array(totalNumRows);
339967
- const featureIndexArr = new Uint32Array(totalNumRows);
340174
+ const { numRowsPerGroupByPart, numRowGroupsByPart } = allMetadata;
340175
+ const rowGroupIToNumRows = (rowGroupI) => {
340176
+ let currPartIndex = 0;
340177
+ let prevTotalRowGroupCount = 0;
340178
+ for (let partIndex = 0; partIndex < numRowGroupsByPart.length; partIndex++) {
340179
+ const numRowGroupsInPart = numRowGroupsByPart[partIndex];
340180
+ if (prevTotalRowGroupCount <= rowGroupI && rowGroupI < prevTotalRowGroupCount + numRowGroupsInPart) {
340181
+ currPartIndex = partIndex;
340182
+ break;
340183
+ }
340184
+ prevTotalRowGroupCount += numRowGroupsInPart;
340185
+ }
340186
+ return numRowsPerGroupByPart[currPartIndex];
340187
+ };
340188
+ const totalNumRowsToLoad = uniqueCoveredRowGroupIndices.reduce((acc, rowGroupI) => acc + rowGroupIToNumRows(rowGroupI), 0);
340189
+ const xArr = new Float32Array(totalNumRowsToLoad);
340190
+ const yArr = new Float32Array(totalNumRowsToLoad);
340191
+ const featureIndexArr = new Uint32Array(totalNumRowsToLoad);
339968
340192
  const rowGroupTables = await Promise.all(uniqueCoveredRowGroupIndices.map(async (rowGroupIndex) => _loadParquetRowGroupByGroupIndex({ queryClient, store }, parquetPath, rowGroupIndex)));
339969
340193
  let rowOffset = 0;
339970
340194
  rowGroupTables.forEach((table2) => {
@@ -339977,7 +340201,7 @@ class SpatialDataTableSource extends AnnDataSource {
339977
340201
  xArr.set(xColumn.toArray(), rowOffset);
339978
340202
  yArr.set(yColumn.toArray(), rowOffset);
339979
340203
  featureIndexArr.set(featureIndexColumn.toArray(), rowOffset);
339980
- rowOffset += numRowsPerGroup;
340204
+ rowOffset += table2.numRows;
339981
340205
  });
339982
340206
  return {
339983
340207
  data: {
@@ -339985,7 +340209,7 @@ class SpatialDataTableSource extends AnnDataSource {
339985
340209
  y: yArr,
339986
340210
  featureIndices: featureIndexArr
339987
340211
  },
339988
- shape: [3, totalNumRows]
340212
+ shape: [3, totalNumRowsToLoad]
339989
340213
  };
339990
340214
  }
339991
340215
  }
@@ -345861,14 +346085,14 @@ class SpatialDataShapesSource extends SpatialDataTableSource {
345861
346085
  /**
345862
346086
  *
345863
346087
  * @param {string} path A path to within shapes.
345864
- * @returns {Promise<"0.1"|"0.2">} The format version.
346088
+ * @returns {Promise<"0.1"|"0.2"|"0.3">} The format version.
345865
346089
  */
345866
346090
  async getShapesFormatVersion(path2) {
345867
346091
  const zattrs = await this.loadSpatialDataElementAttrs(path2);
345868
346092
  const formatVersion = zattrs.spatialdata_attrs.version;
345869
346093
  const geos = zattrs.spatialdata_attrs.geos || {};
345870
346094
  const encodingType = zattrs["encoding-type"];
345871
- if (encodingType !== "ngff:shapes" || !(formatVersion === "0.1" && (geos.name === "POINT" && geos.type === 0) || formatVersion === "0.2")) {
346095
+ if (encodingType !== "ngff:shapes" || !(formatVersion === "0.1" && (geos.name === "POINT" && geos.type === 0) || formatVersion === "0.2" || formatVersion === "0.3")) {
345872
346096
  throw new Error(`Unexpected encoding type or version for shapes spatialdata_attrs: ${encodingType} ${formatVersion}`);
345873
346097
  }
345874
346098
  return formatVersion;
@@ -346077,7 +346301,7 @@ class SpatialDataPointsSource extends SpatialDataTableSource {
346077
346301
  const zattrs = await this.loadSpatialDataElementAttrs(path2);
346078
346302
  const formatVersion = zattrs.spatialdata_attrs.version;
346079
346303
  const encodingType = zattrs["encoding-type"];
346080
- if (encodingType === "ngff:points" && !(formatVersion === "0.1")) {
346304
+ if (encodingType === "ngff:points" && !(formatVersion === "0.1" || formatVersion === "0.2")) {
346081
346305
  throw new Error(`Unexpected version for points spatialdata_attrs: ${formatVersion}`);
346082
346306
  }
346083
346307
  return formatVersion;
@@ -346180,16 +346404,11 @@ class SpatialDataPointsSource extends SpatialDataTableSource {
346180
346404
  const zattrs = await this.loadSpatialDataElementAttrs(elementPath);
346181
346405
  const {
346182
346406
  // axes,
346183
- spatialdata_attrs: spatialDataAttrs,
346184
- // The bounding box (extent) of all points.
346185
- // Required for un-normalization from uints back to floats.
346186
- // TODO: decide whether these will be stored here or somewhere else.
346187
- // Reference: https://github.com/vitessce/vitessce-python/pull/476#issuecomment-3362656956
346188
- bounding_box: allPointsBbox
346407
+ spatialdata_attrs: spatialDataAttrs
346189
346408
  } = zattrs;
346190
346409
  const { feature_key: featureKey } = spatialDataAttrs;
346191
346410
  const featureIndexColumnName = featureIndexColumnNameFromOptions ?? `${featureKey}_codes`;
346192
- return this.loadParquetTableInRect(parquetPath, tileBbox, allPointsBbox, signal, featureIndexColumnName, mortonCodeColumn);
346411
+ return this.loadParquetTableInRect(parquetPath, tileBbox, signal, featureIndexColumnName, mortonCodeColumn);
346193
346412
  }
346194
346413
  async supportsLoadPointsInRect(elementPath, featureIndexColumnName, mortonCodeColumn) {
346195
346414
  const parquetPath = getParquetPath(elementPath);
@@ -346397,7 +346616,13 @@ class GlbSource {
346397
346616
  class GlbDataLoader extends AbstractTwoStepLoader {
346398
346617
  async load() {
346399
346618
  const { url, options } = this;
346400
- const loader2 = new GLTFLoader$1();
346619
+ const [{ GLTFLoader: GLTFLoader2 }, { DRACOLoader }] = await Promise.all([
346620
+ // eslint-disable-next-line import/no-unresolved
346621
+ import("three/addons/loaders/GLTFLoader.js"),
346622
+ // eslint-disable-next-line import/no-unresolved
346623
+ import("three/addons/loaders/DRACOLoader.js")
346624
+ ]);
346625
+ const loader2 = new GLTFLoader2();
346401
346626
  const dracoLoader = new DRACOLoader();
346402
346627
  dracoLoader.setDecoderPath("https://www.gstatic.com/draco/versioned/decoders/1.5.6/");
346403
346628
  loader2.setDRACOLoader(dracoLoader);
@@ -348963,7 +349188,8 @@ const baseFileTypes = [
348963
349188
  makeFileType(FileType$1.OBS_LOCATIONS_MOLECULES_JSON, DataType$3.OBS_LOCATIONS, MoleculesJsonAsObsLocationsLoader, JsonSource, z.null()),
348964
349189
  makeFileType(FileType$1.OBS_LABELS_MOLECULES_JSON, DataType$3.OBS_LABELS, MoleculesJsonAsObsLabelsLoader, JsonSource, z.null()),
348965
349190
  makeFileType(FileType$1.NEIGHBORHOODS_JSON, DataType$3.NEIGHBORHOODS, JsonLoader, JsonSource, z.null()),
348966
- makeFileType(FileType$1.GENOMIC_PROFILES_ZARR, DataType$3.GENOMIC_PROFILES, GenomicProfilesZarrLoader, ZarrDataSource, z.null())
349191
+ makeFileType(FileType$1.GENOMIC_PROFILES_ZARR, DataType$3.GENOMIC_PROFILES, GenomicProfilesZarrLoader, ZarrDataSource, z.null()),
349192
+ makeFileType(FileType$1.GENOMIC_PROFILES_ZARR_ZIP, DataType$3.GENOMIC_PROFILES, GenomicProfilesZarrLoader, ZarrDataSource, z.null())
348967
349193
  ];
348968
349194
  const baseJointFileTypes = [
348969
349195
  new PluginJointFileType(FileType$1.ANNDATA_ZARR, expandAnndataZarr, anndataZarrSchema),
@@ -349222,6 +349448,7 @@ const baseCoordinationTypes = [
349222
349448
  new PluginCoordinationType(CoordinationType$1.SPATIAL_CHANNEL_LABELS_VISIBLE, true, z.boolean()),
349223
349449
  new PluginCoordinationType(CoordinationType$1.SPATIAL_CHANNEL_LABELS_ORIENTATION, "vertical", z.enum(["vertical", "horizontal"])),
349224
349450
  new PluginCoordinationType(CoordinationType$1.SPATIAL_CHANNEL_LABEL_SIZE, 14, z.number()),
349451
+ new PluginCoordinationType(CoordinationType$1.SPATIAL_CHANNELS_SORT_ORDER, "original", z.enum(["original", "alphabetical"])),
349225
349452
  new PluginCoordinationType(CoordinationType$1.SAMPLE_TYPE, "sample", z.string().nullable()),
349226
349453
  // TODO: remove one array level and use multi-coordination for sampleSetSelection?
349227
349454
  new PluginCoordinationType(CoordinationType$1.SAMPLE_FILTER, null, z.array(z.string()).nullable()),