react-msaview-cli 9.2.0 → 9.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +477 -239
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -4694,7 +4694,7 @@ var init_identifier = __esm({
4694
4694
  }
4695
4695
  });
4696
4696
 
4697
- // ../../node_modules/.pnpm/@babel+runtime@7.29.7/node_modules/@babel/runtime/helpers/esm/extends.js
4697
+ // ../../node_modules/.pnpm/@babel+runtime@7.29.10/node_modules/@babel/runtime/helpers/esm/extends.js
4698
4698
  function _extends() {
4699
4699
  return _extends = Object.assign ? Object.assign.bind() : function(n2) {
4700
4700
  for (var e3 = 1; e3 < arguments.length; e3++) {
@@ -4705,7 +4705,7 @@ function _extends() {
4705
4705
  }, _extends.apply(null, arguments);
4706
4706
  }
4707
4707
  var init_extends = __esm({
4708
- "../../node_modules/.pnpm/@babel+runtime@7.29.7/node_modules/@babel/runtime/helpers/esm/extends.js"() {
4708
+ "../../node_modules/.pnpm/@babel+runtime@7.29.10/node_modules/@babel/runtime/helpers/esm/extends.js"() {
4709
4709
  }
4710
4710
  });
4711
4711
 
@@ -5641,6 +5641,12 @@ var init_emotion_cache_esm = __esm({
5641
5641
  }
5642
5642
  });
5643
5643
 
5644
+ // ../../node_modules/.pnpm/@babel+runtime@7.29.7/node_modules/@babel/runtime/helpers/esm/extends.js
5645
+ var init_extends2 = __esm({
5646
+ "../../node_modules/.pnpm/@babel+runtime@7.29.7/node_modules/@babel/runtime/helpers/esm/extends.js"() {
5647
+ }
5648
+ });
5649
+
5644
5650
  // ../../node_modules/.pnpm/react-is@16.13.1/node_modules/react-is/cjs/react-is.production.min.js
5645
5651
  var require_react_is_production_min = __commonJS({
5646
5652
  "../../node_modules/.pnpm/react-is@16.13.1/node_modules/react-is/cjs/react-is.production.min.js"(exports) {
@@ -6202,7 +6208,7 @@ var init_emotion_element_d59e098f_esm = __esm({
6202
6208
  React2 = __toESM(require_react());
6203
6209
  import_react = __toESM(require_react());
6204
6210
  init_emotion_cache_esm();
6205
- init_extends();
6211
+ init_extends2();
6206
6212
  init_emotion_weak_memoize_esm();
6207
6213
  init_emotion_utils_esm();
6208
6214
  init_emotion_serialize_esm();
@@ -6318,16 +6324,16 @@ var init_emotion_element_d59e098f_esm = __esm({
6318
6324
  // ../../node_modules/.pnpm/@babel+runtime@7.29.7/node_modules/@babel/runtime/helpers/extends.js
6319
6325
  var require_extends = __commonJS({
6320
6326
  "../../node_modules/.pnpm/@babel+runtime@7.29.7/node_modules/@babel/runtime/helpers/extends.js"(exports, module) {
6321
- function _extends2() {
6322
- return module.exports = _extends2 = Object.assign ? Object.assign.bind() : function(n2) {
6327
+ function _extends3() {
6328
+ return module.exports = _extends3 = Object.assign ? Object.assign.bind() : function(n2) {
6323
6329
  for (var e3 = 1; e3 < arguments.length; e3++) {
6324
6330
  var t3 = arguments[e3];
6325
6331
  for (var r4 in t3) ({}).hasOwnProperty.call(t3, r4) && (n2[r4] = t3[r4]);
6326
6332
  }
6327
6333
  return n2;
6328
- }, module.exports.__esModule = true, module.exports["default"] = module.exports, _extends2.apply(null, arguments);
6334
+ }, module.exports.__esModule = true, module.exports["default"] = module.exports, _extends3.apply(null, arguments);
6329
6335
  }
6330
- module.exports = _extends2, module.exports.__esModule = true, module.exports["default"] = module.exports;
6336
+ module.exports = _extends3, module.exports.__esModule = true, module.exports["default"] = module.exports;
6331
6337
  }
6332
6338
  });
6333
6339
 
@@ -6619,12 +6625,28 @@ var init_emotion_styled_base_esm = __esm({
6619
6625
  }
6620
6626
  });
6621
6627
 
6628
+ // ../../node_modules/.pnpm/@babel+runtime@7.29.10/node_modules/@babel/runtime/helpers/extends.js
6629
+ var require_extends2 = __commonJS({
6630
+ "../../node_modules/.pnpm/@babel+runtime@7.29.10/node_modules/@babel/runtime/helpers/extends.js"(exports, module) {
6631
+ function _extends3() {
6632
+ return module.exports = _extends3 = Object.assign ? Object.assign.bind() : function(n2) {
6633
+ for (var e3 = 1; e3 < arguments.length; e3++) {
6634
+ var t3 = arguments[e3];
6635
+ for (var r4 in t3) ({}).hasOwnProperty.call(t3, r4) && (n2[r4] = t3[r4]);
6636
+ }
6637
+ return n2;
6638
+ }, module.exports.__esModule = true, module.exports["default"] = module.exports, _extends3.apply(null, arguments);
6639
+ }
6640
+ module.exports = _extends3, module.exports.__esModule = true, module.exports["default"] = module.exports;
6641
+ }
6642
+ });
6643
+
6622
6644
  // ../../node_modules/.pnpm/@emotion+styled@11.14.1_@emotion+react@11.14.0_@types+react@19.3.0_react@19.3.1_support_96e6059dc34d61fb5723d6878bab7582/node_modules/@emotion/styled/dist/emotion-styled.esm.js
6623
6645
  var import_extends4, import_react3, tags, styled;
6624
6646
  var init_emotion_styled_esm = __esm({
6625
6647
  "../../node_modules/.pnpm/@emotion+styled@11.14.1_@emotion+react@11.14.0_@types+react@19.3.0_react@19.3.1_support_96e6059dc34d61fb5723d6878bab7582/node_modules/@emotion/styled/dist/emotion-styled.esm.js"() {
6626
6648
  init_emotion_styled_base_esm();
6627
- import_extends4 = __toESM(require_extends());
6649
+ import_extends4 = __toESM(require_extends2());
6628
6650
  init_emotion_serialize_esm();
6629
6651
  init_emotion_use_insertion_effect_with_fallbacks_esm();
6630
6652
  init_emotion_utils_esm();
@@ -44846,7 +44868,6 @@ var init_material = __esm({
44846
44868
  init_Alert2();
44847
44869
  init_AlertTitle();
44848
44870
  init_AppBar2();
44849
- init_AppBar2();
44850
44871
  init_Autocomplete2();
44851
44872
  init_Autocomplete2();
44852
44873
  init_Avatar();
@@ -44861,7 +44882,6 @@ var init_material = __esm({
44861
44882
  init_Button2();
44862
44883
  init_Button2();
44863
44884
  init_ButtonBase2();
44864
- init_ButtonBase2();
44865
44885
  init_ButtonGroup();
44866
44886
  init_Card();
44867
44887
  init_CardActionArea();
@@ -45038,11 +45058,13 @@ function useDragScroll(axis, onScroll) {
45038
45058
  };
45039
45059
  var onMove = onMove2, onUp = onUp2;
45040
45060
  const { client: startClient, startScroll } = mouseDown;
45041
- document.addEventListener("mousemove", onMove2);
45042
- document.addEventListener("mouseup", onUp2);
45061
+ document.addEventListener("pointermove", onMove2);
45062
+ document.addEventListener("pointerup", onUp2);
45063
+ document.addEventListener("pointercancel", onUp2);
45043
45064
  return () => {
45044
- document.removeEventListener("mousemove", onMove2);
45045
- document.removeEventListener("mouseup", onUp2);
45065
+ document.removeEventListener("pointermove", onMove2);
45066
+ document.removeEventListener("pointerup", onUp2);
45067
+ document.removeEventListener("pointercancel", onUp2);
45046
45068
  };
45047
45069
  }
45048
45070
  }, [axis, onScroll, mouseDown]);
@@ -45077,10 +45099,11 @@ function DragHandle({ axis, variant, getStart, onDrag, style: style3 }) {
45077
45099
  setHovered(true);
45078
45100
  }, onMouseLeave: () => {
45079
45101
  setHovered(false);
45080
- }, onMouseDown: (event) => {
45102
+ }, onPointerDown: (event) => {
45081
45103
  startDrag(event, getStart());
45082
45104
  }, style: {
45083
45105
  position: position3,
45106
+ touchAction: "none",
45084
45107
  zIndex: zIndex3,
45085
45108
  cursor: cursor2(axis),
45086
45109
  background: hovered ? fillHovered(theme) : fill(theme),
@@ -45763,13 +45786,14 @@ var init_renderHighlights = __esm({
45763
45786
  function fontSizeFor(rowHeight) {
45764
45787
  return Math.min(Math.max(6, rowHeight - 3), 18);
45765
45788
  }
45766
- var defaultRowHeight, defaultColWidth, defaultHeight, defaultScrollX, defaultScrollY, defaultCurrentAlignment, defaultShowDomains, defaultShowDomainLegend, defaultHideGaps, defaultAllowedGappyness, defaultSubFeatureRows, subFeatureRowHeight, domainUnderlineHeight, segmentFeatureTypes, segmentShades, defaultDrawMsaLetters, defaultScrollZoom, scrollZoomAxes, defaultScrollZoomAxis, minLetterRowHeight, minLetterColWidth, zoomFrameMaxLetters, minFeatureLabelHeight, labelFitFontSize, minColWidth, minRowHeight, maxCellSize, settingsPanelWidth, defaultBgColor, defaultColorSchemeName, defaultShowColumnStats, defaultDrawLabels, defaultLabelsAlignRight, minTreeWidth, maxFitTreeWidth, pxPerTreeDepth, maxTreeAreaShare, defaultShowBranchLen, treeOrders, defaultTreeOrder, defaultDrawTree, defaultDrawNodeBubbles, defaultDrawNodeLabels, defaultShowTreeOverview, defaultShowTreeScaleBar, defaultOverviewHeight, maxNeighborJoiningRows, rowTintAlpha, cladeHighlightColor, cladeHighlightAlpha, maxInlineSnapshotBytes, rowPanelHeaderHeight, treeScaleBarHeight, defaultFeaturePanelWidth, msaOverlayZIndex, legendZIndex;
45789
+ var defaultRowHeight, defaultColWidth, defaultHeight, resizeHandleWidth, defaultScrollX, defaultScrollY, defaultCurrentAlignment, defaultShowDomains, defaultShowDomainLegend, defaultHideGaps, defaultAllowedGappyness, defaultSubFeatureRows, subFeatureRowHeight, domainUnderlineHeight, segmentFeatureTypes, segmentShades, defaultDrawMsaLetters, defaultScrollZoom, scrollZoomAxes, defaultScrollZoomAxis, minLetterRowHeight, minLetterColWidth, zoomFrameMaxLetters, minFeatureLabelHeight, labelFitFontSize, minColWidth, minRowHeight, maxCellSize, settingsPanelWidth, defaultBgColor, defaultColorSchemeName, defaultShowColumnStats, defaultDrawLabels, defaultLabelsAlignRight, minTreeWidth, maxFitTreeWidth, pxPerTreeDepth, maxTreeAreaShare, defaultShowBranchLen, treeOrders, defaultTreeOrder, defaultDrawTree, defaultDrawNodeBubbles, defaultDrawNodeLabels, defaultShowTreeOverview, defaultShowTreeScaleBar, defaultOverviewHeight, maxNeighborJoiningRows, rowTintAlpha, cladeHighlightColor, cladeHighlightAlpha, maxInlineSnapshotBytes, rowPanelHeaderHeight, treeScaleBarHeight, defaultFeaturePanelWidth, msaOverlayZIndex, legendZIndex;
45767
45790
  var init_constants = __esm({
45768
45791
  "../lib/dist/constants.js"() {
45769
45792
  "use strict";
45770
45793
  defaultRowHeight = 16;
45771
45794
  defaultColWidth = 12;
45772
45795
  defaultHeight = 550;
45796
+ resizeHandleWidth = 5;
45773
45797
  defaultScrollX = 0;
45774
45798
  defaultScrollY = 0;
45775
45799
  defaultCurrentAlignment = 0;
@@ -49534,7 +49558,7 @@ var require_react_dom_client_production = __commonJS({
49534
49558
  return true;
49535
49559
  }
49536
49560
  }
49537
- var aliases2 = /* @__PURE__ */ new Map([
49561
+ var aliases3 = /* @__PURE__ */ new Map([
49538
49562
  ["acceptCharset", "accept-charset"],
49539
49563
  ["htmlFor", "for"],
49540
49564
  ["httpEquiv", "http-equiv"],
@@ -59119,7 +59143,7 @@ var require_react_dom_client_production = __commonJS({
59119
59143
  return;
59120
59144
  default:
59121
59145
  if (!(2 < key.length) || "o" !== key[0] && "O" !== key[0] || "n" !== key[1] && "N" !== key[1])
59122
- key = aliases2.get(key) || key, setValueForAttribute(domElement, key, value);
59146
+ key = aliases3.get(key) || key, setValueForAttribute(domElement, key, value);
59123
59147
  else return;
59124
59148
  }
59125
59149
  viewTransitionMutationContext = true;
@@ -84844,19 +84868,35 @@ var init_wheelZoom = __esm({
84844
84868
  });
84845
84869
 
84846
84870
  // ../lib/dist/useWheelScroll.js
84847
- function useWheelScroll({ ref, onScrollX, onScrollY, onZoom, onZoomSettle, onWheelScroll, scrollZoom }) {
84871
+ function canScrollY(model2, delta) {
84872
+ const { scrollY, maxScrollY } = model2;
84873
+ return delta > 0 ? scrollY > maxScrollY : delta < 0 && scrollY < 0;
84874
+ }
84875
+ function withPinch(pan) {
84876
+ return pinchZoom ? `${pan} ${pinchZoom}` : pan;
84877
+ }
84878
+ function panTouchAction(model2, axes) {
84879
+ const x2 = axes.includes("x") && model2.maxScrollX < 0;
84880
+ const y2 = axes.includes("y") && model2.maxScrollY < 0;
84881
+ return x2 && y2 ? pinchZoom ?? "none" : x2 ? withPinch("pan-y") : y2 ? withPinch("pan-x") : "auto";
84882
+ }
84883
+ function useWheelScroll({ ref, model: model2, axes, zoom, onWheelScroll }) {
84848
84884
  const scheduled = (0, import_react39.useRef)(false);
84849
84885
  const zoomFrame = (0, import_react39.useRef)(void 0);
84850
84886
  const zoomSettle = (0, import_react39.useRef)(void 0);
84851
84887
  const deltaX = (0, import_react39.useRef)(0);
84852
84888
  const deltaY = (0, import_react39.useRef)(0);
84889
+ const lastTaken = (0, import_react39.useRef)(Number.NEGATIVE_INFINITY);
84853
84890
  const zoomSmoother = (0, import_react39.useRef)(new WheelZoomSmoother());
84854
84891
  const zoomX = (0, import_react39.useRef)(0);
84855
84892
  const zoomY = (0, import_react39.useRef)(0);
84856
84893
  const lastZoomTime = (0, import_react39.useRef)(null);
84857
- const prevX = (0, import_react39.useRef)(0);
84858
- const prevY = (0, import_react39.useRef)(0);
84859
- const [mouseDragging, setMouseDragging] = (0, import_react39.useState)(false);
84894
+ const prev2 = (0, import_react39.useRef)({ x: 0, y: 0 });
84895
+ const latest = (0, import_react39.useRef)({ x: 0, y: 0 });
84896
+ const panFrame = (0, import_react39.useRef)(false);
84897
+ const [panPointer, setPanPointer] = (0, import_react39.useState)();
84898
+ const x2 = axes.includes("x");
84899
+ const y2 = axes.includes("y");
84860
84900
  (0, import_react39.useEffect)(() => {
84861
84901
  const curr = ref.current;
84862
84902
  if (!curr) {
@@ -84864,9 +84904,8 @@ function useWheelScroll({ ref, onScrollX, onScrollY, onZoom, onZoomSettle, onWhe
84864
84904
  }
84865
84905
  function onWheel(event) {
84866
84906
  const isCtrlZoom = event.ctrlKey || event.metaKey;
84867
- const isScrollZoom = scrollZoom && !event.shiftKey && Math.abs(event.deltaY) >= Math.abs(event.deltaX);
84868
- if (onZoom && (isCtrlZoom || isScrollZoom)) {
84869
- const zoom = onZoom;
84907
+ const isScrollZoom = model2.scrollZoom && !event.shiftKey && Math.abs(event.deltaY) >= Math.abs(event.deltaX);
84908
+ if (zoom && (isCtrlZoom || isScrollZoom)) {
84870
84909
  const rect = curr.getBoundingClientRect();
84871
84910
  zoomSmoother.current.add(event.deltaY, event.deltaMode, isCtrlZoom);
84872
84911
  zoomX.current = event.clientX - rect.left;
@@ -84876,10 +84915,10 @@ function useWheelScroll({ ref, onScrollX, onScrollY, onZoom, onZoomSettle, onWhe
84876
84915
  const frame = (now) => {
84877
84916
  const elapsed = lastZoomTime.current === null ? 16.67 : now - lastZoomTime.current;
84878
84917
  lastZoomTime.current = now;
84879
- zoom(zoomSmoother.current.step(Math.min(100, elapsed)), zoomX.current, zoomY.current);
84918
+ model2.wheelZoomToPos(zoomSmoother.current.step(Math.min(100, elapsed)), zoomX.current, zoomY.current);
84880
84919
  clearTimeout(zoomSettle.current);
84881
84920
  zoomSettle.current = setTimeout(() => {
84882
- onZoomSettle?.();
84921
+ model2.endWheelZoom();
84883
84922
  }, zoomSettleMs);
84884
84923
  zoomFrame.current = zoomSmoother.current.idle ? void 0 : requestAnimationFrame(frame);
84885
84924
  };
@@ -84889,27 +84928,25 @@ function useWheelScroll({ ref, onScrollX, onScrollY, onZoom, onZoomSettle, onWhe
84889
84928
  event.stopPropagation();
84890
84929
  return;
84891
84930
  }
84892
- const consumeX = !!onScrollX && event.deltaX !== 0;
84893
- const consumeY = !!onScrollY && event.deltaY !== 0;
84894
- if (consumeX || consumeY) {
84895
- onWheelScroll?.(event);
84896
- if (onScrollX) {
84897
- deltaX.current += event.deltaX;
84898
- }
84899
- if (onScrollY) {
84900
- deltaY.current += event.deltaY;
84931
+ const { deltaX: dx, deltaY: dy } = event;
84932
+ const vertical = Math.abs(dy) >= Math.abs(dx);
84933
+ const latched = event.timeStamp - lastTaken.current < wheelLatchMs;
84934
+ const takeY = y2 && dy !== 0 && (latched || canScrollY(model2, dy) || !vertical);
84935
+ const takeX = x2 && dx !== 0 && (!vertical || takeY);
84936
+ if (takeX || takeY) {
84937
+ if (takeY && vertical) {
84938
+ lastTaken.current = event.timeStamp;
84901
84939
  }
84940
+ onWheelScroll?.(event);
84941
+ deltaX.current += takeX ? event.deltaX : 0;
84942
+ deltaY.current += takeY ? event.deltaY : 0;
84902
84943
  if (!scheduled.current) {
84903
84944
  scheduled.current = true;
84904
84945
  requestAnimationFrame(() => {
84905
- if (onScrollX) {
84906
- onScrollX(-deltaX.current);
84907
- deltaX.current = 0;
84908
- }
84909
- if (onScrollY) {
84910
- onScrollY(-deltaY.current);
84911
- deltaY.current = 0;
84912
- }
84946
+ model2.doScrollX(-deltaX.current);
84947
+ model2.doScrollY(-deltaY.current);
84948
+ deltaX.current = 0;
84949
+ deltaY.current = 0;
84913
84950
  scheduled.current = false;
84914
84951
  });
84915
84952
  }
@@ -84926,68 +84963,60 @@ function useWheelScroll({ ref, onScrollX, onScrollY, onZoom, onZoomSettle, onWhe
84926
84963
  }
84927
84964
  clearTimeout(zoomSettle.current);
84928
84965
  };
84929
- }, [
84930
- ref,
84931
- onScrollX,
84932
- onScrollY,
84933
- onZoom,
84934
- onZoomSettle,
84935
- onWheelScroll,
84936
- scrollZoom
84937
- ]);
84966
+ }, [ref, model2, x2, y2, zoom, onWheelScroll]);
84938
84967
  (0, import_react39.useEffect)(() => {
84939
- if (!mouseDragging) {
84968
+ if (panPointer === void 0) {
84940
84969
  return;
84941
84970
  }
84942
- function globalMouseMove(event) {
84971
+ function onMove(event) {
84972
+ if (event.pointerId !== panPointer) {
84973
+ return;
84974
+ }
84943
84975
  event.preventDefault();
84944
- const distanceX = event.clientX - prevX.current;
84945
- const distanceY = event.clientY - prevY.current;
84946
- if (distanceX && onScrollX || distanceY && onScrollY) {
84947
- if (!scheduled.current) {
84948
- scheduled.current = true;
84949
- requestAnimationFrame(() => {
84950
- onScrollX?.(distanceX);
84951
- onScrollY?.(distanceY);
84952
- scheduled.current = false;
84953
- prevX.current = event.clientX;
84954
- prevY.current = event.clientY;
84955
- });
84956
- }
84976
+ latest.current = { x: event.clientX, y: event.clientY };
84977
+ if (!panFrame.current) {
84978
+ panFrame.current = true;
84979
+ requestAnimationFrame(() => {
84980
+ const to = latest.current;
84981
+ model2.doScrollX(x2 ? to.x - prev2.current.x : 0);
84982
+ model2.doScrollY(y2 ? to.y - prev2.current.y : 0);
84983
+ prev2.current = to;
84984
+ panFrame.current = false;
84985
+ });
84957
84986
  }
84958
84987
  }
84959
- function globalMouseUp() {
84960
- prevX.current = 0;
84961
- prevY.current = 0;
84962
- setMouseDragging(false);
84988
+ function onUp(event) {
84989
+ if (event.pointerId === panPointer) {
84990
+ setPanPointer(void 0);
84991
+ }
84963
84992
  }
84964
- window.addEventListener("mousemove", globalMouseMove, true);
84965
- window.addEventListener("mouseup", globalMouseUp, true);
84993
+ window.addEventListener("pointermove", onMove, true);
84994
+ window.addEventListener("pointerup", onUp, true);
84995
+ window.addEventListener("pointercancel", onUp, true);
84966
84996
  return () => {
84967
- window.removeEventListener("mousemove", globalMouseMove, true);
84968
- window.removeEventListener("mouseup", globalMouseUp, true);
84997
+ window.removeEventListener("pointermove", onMove, true);
84998
+ window.removeEventListener("pointerup", onUp, true);
84999
+ window.removeEventListener("pointercancel", onUp, true);
84969
85000
  };
84970
- }, [mouseDragging, onScrollX, onScrollY]);
84971
- function onMouseDown(event) {
84972
- if (event.button === 0) {
84973
- prevX.current = event.clientX;
84974
- prevY.current = event.clientY;
84975
- setMouseDragging(true);
85001
+ }, [panPointer, model2, x2, y2]);
85002
+ function onPointerDown(event) {
85003
+ if (event.button === 0 && event.isPrimary && panPointer === void 0) {
85004
+ prev2.current = { x: event.clientX, y: event.clientY };
85005
+ latest.current = prev2.current;
85006
+ setPanPointer(event.pointerId);
84976
85007
  }
84977
85008
  }
84978
- function onMouseUp(event) {
84979
- event.preventDefault();
84980
- setMouseDragging(false);
84981
- }
84982
- return { onMouseDown, onMouseUp };
85009
+ return { onPointerDown, touchAction: panTouchAction(model2, axes) };
84983
85010
  }
84984
- var import_react39, zoomSettleMs;
85011
+ var import_react39, zoomSettleMs, wheelLatchMs, pinchZoom;
84985
85012
  var init_useWheelScroll = __esm({
84986
85013
  "../lib/dist/useWheelScroll.js"() {
84987
85014
  "use strict";
84988
85015
  import_react39 = __toESM(require_react(), 1);
84989
85016
  init_wheelZoom();
84990
85017
  zoomSettleMs = 150;
85018
+ wheelLatchMs = 150;
85019
+ pinchZoom = typeof CSS !== "undefined" && CSS.supports("touch-action", "pinch-zoom") ? "pinch-zoom" : void 0;
84991
85020
  }
84992
85021
  });
84993
85022
 
@@ -85573,13 +85602,10 @@ var init_Track = __esm({
85573
85602
  );
85574
85603
  });
85575
85604
  Track = (0, import_mobx_react35.observer)(function({ model: model2, track }) {
85576
- const { resizeHandleWidth, rowPanelsWidth, showColumnStats } = model2;
85605
+ const { resizeHandleWidth: resizeHandleWidth2, rowPanelsWidth, showColumnStats } = model2;
85577
85606
  const { model: { height: height2 } } = track;
85578
85607
  const ref = (0, import_react47.useRef)(null);
85579
- const onScrollX = (0, import_react47.useCallback)((d3) => {
85580
- model2.doScrollX(d3);
85581
- }, [model2]);
85582
- useWheelScroll({ ref, onScrollX });
85608
+ useWheelScroll({ ref, model: model2, axes: "x" });
85583
85609
  const { classes } = useStyles10();
85584
85610
  const { anchor, onMouseMove, onMouseDown, onMouseLeave } = useTrackHover({
85585
85611
  model: model2,
@@ -85589,7 +85615,7 @@ var init_Track = __esm({
85589
85615
  "div",
85590
85616
  { className: classes.row, style: { height: height2 } },
85591
85617
  import_react47.default.createElement(TrackLabel, { model: model2, track }),
85592
- import_react47.default.createElement("div", { style: { width: rowPanelsWidth + resizeHandleWidth, flexShrink: 0 } }),
85618
+ import_react47.default.createElement("div", { style: { width: rowPanelsWidth + resizeHandleWidth2, flexShrink: 0 } }),
85593
85619
  import_react47.default.createElement(
85594
85620
  "div",
85595
85621
  { ref, "data-testid": `track_${track.model.id}`, tabIndex: -1, style: { outline: "none" }, onKeyDown: (event) => {
@@ -85639,7 +85665,7 @@ var init_VerticalScrollbar = __esm({
85639
85665
  }, [model2, unit]);
85640
85666
  return import_react48.default.createElement(
85641
85667
  "div",
85642
- { onMouseDown: (event) => {
85668
+ { onPointerDown: (event) => {
85643
85669
  if (event.button === 0 && event.target === event.currentTarget) {
85644
85670
  const y2 = event.clientY - event.currentTarget.getBoundingClientRect().top;
85645
85671
  model2.setScrollY(-y2 / unit + msaAreaHeight / 2);
@@ -86502,7 +86528,7 @@ var version2;
86502
86528
  var init_version3 = __esm({
86503
86529
  "../lib/dist/version.js"() {
86504
86530
  "use strict";
86505
- version2 = "9.2.0";
86531
+ version2 = "9.4.0";
86506
86532
  }
86507
86533
  });
86508
86534
 
@@ -87821,6 +87847,7 @@ var init_Header = __esm({
87821
87847
  init_useMeasure();
87822
87848
  init_Tune();
87823
87849
  init_material();
87850
+ init_AppBar2();
87824
87851
  import_mobx_react54 = __toESM(require_dist3(), 1);
87825
87852
  init_StatusMessage();
87826
87853
  init_HeaderInfoArea();
@@ -87937,7 +87964,7 @@ var init_Minimap = __esm({
87937
87964
  width: msaCanvasWidth,
87938
87965
  flexShrink: 0
87939
87966
  } },
87940
- import_react76.default.createElement("canvas", { ref, width: barWidth, height: barHeight, onMouseDown: (event) => {
87967
+ import_react76.default.createElement("canvas", { ref, width: barWidth, height: barHeight, onPointerDown: (event) => {
87941
87968
  if (event.button === 0 && unit > 0) {
87942
87969
  const x2 = event.clientX - event.currentTarget.getBoundingClientRect().left;
87943
87970
  model2.setScrollX(-x2 / unit + msaCanvasWidth / 2);
@@ -88368,51 +88395,52 @@ var init_MSACanvas = __esm({
88368
88395
  init_WheelZoomHint();
88369
88396
  init_msaKeys();
88370
88397
  MSACanvas = (0, import_mobx_react58.observer)(function({ model: model2 }) {
88371
- const { MSA, msaFilehandle, height: height2, msaCanvasWidth, blocks2d, scrollZoom, scrollX, scrollY, zoomSnapshot } = model2;
88398
+ const { MSA, msaFilehandle, height: height2, msaCanvasWidth, blocks2d, scrollX, scrollY, zoomSnapshot } = model2;
88372
88399
  const blocks = zoomSnapshot ? zoomSnapshot.blocksY.flatMap((by) => zoomSnapshot.blocksX.map((bx) => [bx, by])) : blocks2d;
88373
88400
  const scale = zoomSnapshot ? zoomSnapshotScale(model2, zoomSnapshot) : void 0;
88374
88401
  const ref = (0, import_react82.useRef)(null);
88375
- const onScrollX = (0, import_react82.useCallback)((d3) => {
88376
- model2.doScrollX(d3);
88377
- }, [model2]);
88378
- const onScrollY = (0, import_react82.useCallback)((d3) => {
88379
- model2.doScrollY(d3);
88380
- }, [model2]);
88381
- const onZoom = (0, import_react82.useCallback)((scaleFactor, offsetX, offsetY) => {
88382
- model2.wheelZoomToPos(scaleFactor, offsetX, offsetY);
88383
- }, [model2]);
88384
- const onZoomSettle = (0, import_react82.useCallback)(() => {
88385
- model2.endWheelZoom();
88386
- }, [model2]);
88387
88402
  const hint = useWheelZoomHint(model2);
88388
- const { onMouseDown, onMouseUp } = useWheelScroll({
88403
+ const { onPointerDown, touchAction } = useWheelScroll({
88389
88404
  ref,
88390
- onScrollX,
88391
- onScrollY,
88392
- onZoom,
88393
- onZoomSettle,
88394
- onWheelScroll: hint.onWheelScroll,
88395
- scrollZoom
88405
+ model: model2,
88406
+ axes: "xy",
88407
+ zoom: true,
88408
+ onWheelScroll: hint.onWheelScroll
88396
88409
  });
88397
88410
  return import_react82.default.createElement(
88398
88411
  "div",
88399
- { ref, "data-testid": "msa_canvas", tabIndex: 0, "aria-label": alignmentAriaLabel, onKeyDown: (event) => {
88400
- if (onMsaKey(model2, event)) {
88401
- event.preventDefault();
88402
- }
88403
- }, onMouseDown: (event) => {
88404
- if (event.shiftKey) {
88405
- event.preventDefault();
88406
- ref.current?.focus({ preventScroll: true });
88407
- } else {
88408
- onMouseDown(event);
88412
+ {
88413
+ ref,
88414
+ "data-testid": "msa_canvas",
88415
+ tabIndex: 0,
88416
+ "aria-label": alignmentAriaLabel,
88417
+ onKeyDown: (event) => {
88418
+ if (onMsaKey(model2, event)) {
88419
+ event.preventDefault();
88420
+ }
88421
+ },
88422
+ // a shifted press selects cells (useMsaBlockMouse), so it takes the
88423
+ // focus Escape clears from, and leaves out the pan and the page's own
88424
+ // text selection
88425
+ onMouseDown: (event) => {
88426
+ if (event.shiftKey) {
88427
+ event.preventDefault();
88428
+ ref.current?.focus({ preventScroll: true });
88429
+ }
88430
+ },
88431
+ onPointerDown: (event) => {
88432
+ if (!event.shiftKey) {
88433
+ onPointerDown(event);
88434
+ }
88435
+ },
88436
+ style: {
88437
+ position: "relative",
88438
+ touchAction,
88439
+ height: height2,
88440
+ width: msaCanvasWidth,
88441
+ overflow: "hidden"
88409
88442
  }
88410
- }, onMouseUp, style: {
88411
- position: "relative",
88412
- height: height2,
88413
- width: msaCanvasWidth,
88414
- overflow: "hidden"
88415
- } },
88443
+ },
88416
88444
  !MSA && !msaFilehandle ? null : MSA ? import_react82.default.createElement("div", { style: {
88417
88445
  position: "absolute",
88418
88446
  top: 0,
@@ -88686,13 +88714,15 @@ var init_RowPanels = __esm({
88686
88714
  RowPanel = (0, import_mobx_react63.observer)(function({ model: model2, panel }) {
88687
88715
  const ref = (0, import_react87.useRef)(null);
88688
88716
  const { height: height2, blocksY, scrollY } = model2;
88689
- const onScrollY = (0, import_react87.useCallback)((d3) => {
88690
- model2.doScrollY(d3);
88691
- }, [model2]);
88692
- const { onMouseDown, onMouseUp } = useWheelScroll({ ref, onScrollY });
88717
+ const { onPointerDown, touchAction } = useWheelScroll({
88718
+ ref,
88719
+ model: model2,
88720
+ axes: "y"
88721
+ });
88693
88722
  return import_react87.default.createElement(
88694
88723
  "div",
88695
- { ref, "data-testid": `rowpanel_${panel.id}`, onMouseDown, onMouseUp, style: {
88724
+ { ref, "data-testid": `rowpanel_${panel.id}`, onPointerDown, style: {
88725
+ touchAction,
88696
88726
  height: height2,
88697
88727
  width: panel.width,
88698
88728
  flexShrink: 0,
@@ -88934,6 +88964,7 @@ var init_SettingsPanel = __esm({
88934
88964
  init_ArrowRight();
88935
88965
  init_Close2();
88936
88966
  init_material();
88967
+ init_ButtonBase2();
88937
88968
  import_mobx_react65 = __toESM(require_dist3(), 1);
88938
88969
  init_constants();
88939
88970
  init_getAnnotationsMenu();
@@ -89953,10 +89984,11 @@ var init_TreeCanvas = __esm({
89953
89984
  TreeCanvas = (0, import_mobx_react71.observer)(function({ model: model2 }) {
89954
89985
  const ref = (0, import_react97.useRef)(null);
89955
89986
  const { height: height2, blocksY, effectiveTreeAreaWidth, scrollY, highResScaleFactor } = model2;
89956
- const onScrollY = (0, import_react97.useCallback)((d3) => {
89957
- model2.doScrollY(d3);
89958
- }, [model2]);
89959
- const { onMouseDown, onMouseUp } = useWheelScroll({ ref, onScrollY });
89987
+ const { onPointerDown, touchAction } = useWheelScroll({
89988
+ ref,
89989
+ model: model2,
89990
+ axes: "y"
89991
+ });
89960
89992
  const canvasWidth = effectiveTreeAreaWidth * highResScaleFactor;
89961
89993
  const canvasHeight = height2 * highResScaleFactor;
89962
89994
  const mouseoverRef = useCanvasAutorun({
@@ -89971,7 +90003,8 @@ var init_TreeCanvas = __esm({
89971
90003
  });
89972
90004
  return import_react97.default.createElement(
89973
90005
  "div",
89974
- { ref, onMouseDown, onMouseUp, style: {
90006
+ { ref, onPointerDown, style: {
90007
+ touchAction,
89975
90008
  height: height2,
89976
90009
  position: "relative",
89977
90010
  width: effectiveTreeAreaWidth
@@ -90071,7 +90104,7 @@ var init_MSAView = __esm({
90071
90104
  init_TreePanel();
90072
90105
  init_TreeRuler();
90073
90106
  TopArea = (0, import_mobx_react74.observer)(function({ model: model2 }) {
90074
- const { showHorizontalScrollbar, showTreeOverview, resizeHandleWidth } = model2;
90107
+ const { showHorizontalScrollbar, showTreeOverview, resizeHandleWidth: resizeHandleWidth2 } = model2;
90075
90108
  return import_react100.default.createElement(
90076
90109
  "div",
90077
90110
  { style: { display: "flex" } },
@@ -90082,12 +90115,12 @@ var init_MSAView = __esm({
90082
90115
  import_react100.default.createElement(TreeRuler_default, { model: model2 })
90083
90116
  ),
90084
90117
  import_react100.default.createElement(RowPanelHeaders_default, { model: model2 }),
90085
- import_react100.default.createElement("div", { style: { width: resizeHandleWidth, flexShrink: 0 } }),
90118
+ import_react100.default.createElement("div", { style: { width: resizeHandleWidth2, flexShrink: 0 } }),
90086
90119
  showHorizontalScrollbar ? import_react100.default.createElement(Minimap_default, { model: model2 }) : null
90087
90120
  );
90088
90121
  });
90089
90122
  TrackColumnIndicator = (0, import_mobx_react74.observer)(function({ model: model2 }) {
90090
- const { mouseCol, mouseClickCol, colWidth, scrollX, effectiveTreeAreaWidth, rowPanelsWidth, resizeHandleWidth, totalTrackAreaHeight, msaCanvasWidth, resolvedSelection } = model2;
90123
+ const { mouseCol, mouseClickCol, colWidth, scrollX, effectiveTreeAreaWidth, rowPanelsWidth, resizeHandleWidth: resizeHandleWidth2, totalTrackAreaHeight, msaCanvasWidth, resolvedSelection } = model2;
90091
90124
  const bands = [
90092
90125
  {
90093
90126
  start: resolvedSelection?.startCol,
@@ -90099,7 +90132,7 @@ var init_MSAView = __esm({
90099
90132
  ];
90100
90133
  return import_react100.default.createElement("div", { style: {
90101
90134
  position: "absolute",
90102
- left: effectiveTreeAreaWidth + rowPanelsWidth + resizeHandleWidth,
90135
+ left: effectiveTreeAreaWidth + rowPanelsWidth + resizeHandleWidth2,
90103
90136
  top: 0,
90104
90137
  width: msaCanvasWidth,
90105
90138
  height: totalTrackAreaHeight,
@@ -90971,9 +91004,9 @@ var init_scaleBar = __esm({
90971
91004
 
90972
91005
  // ../lib/dist/ggplotPalettes.js
90973
91006
  function paletteNamed(name) {
90974
- return name === void 0 ? void 0 : namedPalettes[name];
91007
+ return name === void 0 ? void 0 : Object.hasOwn(namedPalettes, name) ? namedPalettes[name] : Object.hasOwn(aliases2, name) ? namedPalettes[aliases2[name]] : void 0;
90975
91008
  }
90976
- var palettes, ggplotPalettes_default, namedPalettes;
91009
+ var palettes, ggplotPalettes_default, namedPalettes, aliases2;
90977
91010
  var init_ggplotPalettes = __esm({
90978
91011
  "../lib/dist/ggplotPalettes.js"() {
90979
91012
  "use strict";
@@ -91044,6 +91077,10 @@ var init_ggplotPalettes = __esm({
91044
91077
  "#bab0ac"
91045
91078
  ]
91046
91079
  };
91080
+ aliases2 = {
91081
+ okabeIto: "okabeito",
91082
+ tableau10: "tableau"
91083
+ };
91047
91084
  }
91048
91085
  });
91049
91086
 
@@ -91080,32 +91117,6 @@ var init_exportFileName = __esm({
91080
91117
  }
91081
91118
  });
91082
91119
 
91083
- // ../lib/dist/scales.js
91084
- function resolveScale(spec, values3) {
91085
- const domain = [...new Set(values3)].sort((a3, b2) => a3.localeCompare(b2));
91086
- const { map: map2, palette: palette2 } = spec ?? {};
91087
- const colors2 = map2 ?? createPaletteMap(domain, paletteNamed(palette2));
91088
- const present = new Set(domain);
91089
- const labels = map2 ? Object.keys(map2).filter((v2) => present.has(v2)) : domain;
91090
- return {
91091
- kind: "categorical",
91092
- colorOf: (value) => colors2[value],
91093
- // a categorical value is its own label, and the id a legend keys on
91094
- legend: labels.map((value) => ({
91095
- id: value,
91096
- label: value,
91097
- color: colors2[value]
91098
- }))
91099
- };
91100
- }
91101
- var init_scales = __esm({
91102
- "../lib/dist/scales.js"() {
91103
- "use strict";
91104
- init_createPaletteMap();
91105
- init_ggplotPalettes();
91106
- }
91107
- });
91108
-
91109
91120
  // ../lib/dist/featurePanels.js
91110
91121
  function rowPanelWidth(panel, view) {
91111
91122
  return panel.width ?? (panel.kind === "features" ? defaultFeaturePanelWidth : view.rowHeight);
@@ -91226,25 +91237,13 @@ function featurePanelSpans({ panel, width: width3, colWidth, domainBands, annota
91226
91237
  }))
91227
91238
  ]));
91228
91239
  }
91229
- function resolveFeatureScale(field, scale, annotations, drawn) {
91230
- const valuesOf = (list) => list.map((a3) => featureField(a3, field)).filter(notEmpty);
91231
- const resolved = resolveScale(scale, valuesOf(annotations));
91232
- const shown = new Set(valuesOf(drawn));
91233
- return {
91234
- field,
91235
- ...resolved,
91236
- legend: resolved.legend.filter((entry) => shown.has(entry.id))
91237
- };
91238
- }
91239
91240
  var UNSCALED_FEATURE, laneOverlap;
91240
91241
  var init_featurePanels = __esm({
91241
91242
  "../lib/dist/featurePanels.js"() {
91242
91243
  "use strict";
91243
- init_util5();
91244
91244
  init_packDomainLanes();
91245
91245
  init_constants();
91246
91246
  init_featureFields();
91247
- init_scales();
91248
91247
  init_util3();
91249
91248
  UNSCALED_FEATURE = "#d9d9d9";
91250
91249
  laneOverlap = 0.1;
@@ -92236,6 +92235,166 @@ var init_rowCoordinateCalculations = __esm({
92236
92235
  }
92237
92236
  });
92238
92237
 
92238
+ // ../lib/dist/groupKeys.js
92239
+ function compareRuns(a3, b2) {
92240
+ const runsA = a3.match(DIGIT_RUNS) ?? [];
92241
+ const runsB = b2.match(DIGIT_RUNS) ?? [];
92242
+ const shared = Math.min(runsA.length, runsB.length);
92243
+ for (let i2 = 0; i2 < shared; i2++) {
92244
+ const x2 = runsA[i2];
92245
+ const y2 = runsB[i2];
92246
+ if (x2 === y2) {
92247
+ continue;
92248
+ }
92249
+ if (/^\d/.test(x2) && /^\d/.test(y2)) {
92250
+ const nx = Number(x2);
92251
+ const ny = Number(y2);
92252
+ if (nx !== ny) {
92253
+ return nx < ny ? -1 : 1;
92254
+ }
92255
+ return x2.length < y2.length ? -1 : 1;
92256
+ }
92257
+ return x2 < y2 ? -1 : 1;
92258
+ }
92259
+ return runsA.length - runsB.length;
92260
+ }
92261
+ function compareGroupKeys(a3, b2) {
92262
+ if (a3 === b2) {
92263
+ return 0;
92264
+ }
92265
+ if (a3 === "" || b2 === "") {
92266
+ return a3 === "" ? 1 : -1;
92267
+ }
92268
+ const numA = NUMERIC.test(a3);
92269
+ const numB = NUMERIC.test(b2);
92270
+ if (numA !== numB) {
92271
+ return numA ? -1 : 1;
92272
+ }
92273
+ if (numA) {
92274
+ const diff = Number(a3) - Number(b2);
92275
+ if (diff !== 0) {
92276
+ return diff < 0 ? -1 : 1;
92277
+ }
92278
+ }
92279
+ return compareRuns(a3, b2);
92280
+ }
92281
+ var NUMERIC, DIGIT_RUNS;
92282
+ var init_groupKeys = __esm({
92283
+ "../lib/dist/groupKeys.js"() {
92284
+ "use strict";
92285
+ NUMERIC = /^-?\d+(\.\d+)?$/;
92286
+ DIGIT_RUNS = /\d+|\D+/g;
92287
+ }
92288
+ });
92289
+
92290
+ // ../lib/dist/scales.js
92291
+ function rangeList(range) {
92292
+ if (typeof range !== "string") {
92293
+ return range;
92294
+ }
92295
+ if (paletteNamed(range)) {
92296
+ return void 0;
92297
+ }
92298
+ const colors2 = range.split(/,(?![^(]*\))/).map((c2) => c2.trim());
92299
+ return colors2.every((c2) => A(c2).isValid()) ? colors2 : void 0;
92300
+ }
92301
+ function rangeColors(range, order2) {
92302
+ const list = rangeList(range);
92303
+ return list ? new Map(order2.slice(0, list.length).map((value, i2) => [value, list[i2]])) : new Map(Object.entries(createPaletteMap(order2, paletteNamed(typeof range === "string" ? range : void 0))));
92304
+ }
92305
+ function resolveScale(spec, values3) {
92306
+ const present = new Set(values3);
92307
+ const listed = new Set(spec?.domain);
92308
+ const order2 = [
92309
+ ...listed,
92310
+ ...[...present].filter((v2) => !listed.has(v2)).sort(compareGroupKeys)
92311
+ ];
92312
+ const colors2 = rangeColors(spec?.range, order2);
92313
+ return {
92314
+ kind: "categorical",
92315
+ colorOf: (value) => colors2.get(value),
92316
+ legend: order2.filter((value) => present.has(value) && colors2.has(value)).map((value) => ({ id: value, label: value, color: colors2.get(value) }))
92317
+ };
92318
+ }
92319
+ function declarationKey({ spec, field, table }) {
92320
+ const { scale = "categorical", domain, range, title = field } = spec;
92321
+ return JSON.stringify([table, scale, domain, range, title]);
92322
+ }
92323
+ function resolveShared(uses) {
92324
+ const groups = /* @__PURE__ */ new Map();
92325
+ for (const use4 of uses) {
92326
+ const key = declarationKey(use4);
92327
+ groups.set(key, [...groups.get(key) ?? [], use4]);
92328
+ }
92329
+ return new Map([...groups].map(([key, group]) => {
92330
+ const { spec, field } = group[0];
92331
+ const resolved = resolveScale(spec, group.flatMap((u2) => u2.values));
92332
+ const shown = group[0].shown ? new Set(group.flatMap((u2) => u2.shown ?? [])) : void 0;
92333
+ const scale = {
92334
+ ...resolved,
92335
+ key,
92336
+ title: spec.title ?? field,
92337
+ legend: shown ? resolved.legend.filter((entry) => shown.has(entry.id)) : resolved.legend
92338
+ };
92339
+ return [key, scale];
92340
+ }));
92341
+ }
92342
+ function readColor(record) {
92343
+ const { scale, legend, ...rest } = record;
92344
+ if (typeof scale !== "object" && legend === void 0) {
92345
+ return record;
92346
+ }
92347
+ const lifted = typeof scale !== "object" ? scale === void 0 ? {} : { scale } : scale.map ? { domain: Object.keys(scale.map), range: Object.values(scale.map) } : scale.palette === void 0 ? {} : { range: scale.palette };
92348
+ return {
92349
+ ...legend === void 0 ? {} : { title: legend },
92350
+ ...lifted,
92351
+ ...rest
92352
+ };
92353
+ }
92354
+ function readEncoding(encoding) {
92355
+ return readColor(encoding);
92356
+ }
92357
+ function readRowPanel(panel) {
92358
+ if (panel.kind === "strip") {
92359
+ return readColor(panel);
92360
+ }
92361
+ const color2 = panel.encoding?.color;
92362
+ return color2 ? { ...panel, encoding: { ...panel.encoding, color: readColor(color2) } } : panel;
92363
+ }
92364
+ function readColumnTrack(track) {
92365
+ const { max: max3, colors: colors2, ...rest } = track;
92366
+ if (max3 === void 0 && colors2 === void 0) {
92367
+ return track;
92368
+ }
92369
+ return {
92370
+ ...colors2 ? {
92371
+ encoding: {
92372
+ color: {
92373
+ domain: Object.keys(colors2),
92374
+ range: Object.values(colors2)
92375
+ }
92376
+ }
92377
+ } : {},
92378
+ ...max3 === void 0 ? {} : { scales: { y: { domainMax: max3 } } },
92379
+ ...rest
92380
+ };
92381
+ }
92382
+ function colorTable(spec, values3) {
92383
+ return Object.fromEntries(resolveScale(spec, values3).legend.map((e3) => [e3.id, e3.color]));
92384
+ }
92385
+ function letterColors(scheme) {
92386
+ return "map" in scheme ? scheme.map : colorTable(scheme, scheme.domain ?? []);
92387
+ }
92388
+ var init_scales = __esm({
92389
+ "../lib/dist/scales.js"() {
92390
+ "use strict";
92391
+ init_colord();
92392
+ init_createPaletteMap();
92393
+ init_ggplotPalettes();
92394
+ init_groupKeys();
92395
+ }
92396
+ });
92397
+
92239
92398
  // ../lib/dist/seqPosToGlobalCol.js
92240
92399
  function buildSeqPosIndex(row) {
92241
92400
  const index3 = new Int32Array(row.length);
@@ -93043,7 +93202,9 @@ function stateModelFactory({ maxInlineSnapshotBytes: maxInlineSnapshotBytes2 = m
93043
93202
  * tracks supplied as data: per-column values drawn as bars, or a
93044
93203
  * per-column string drawn as a text track. See docs/layers.md
93045
93204
  */
93046
- columnTracks: stripDefault2(types.array(types.frozen()), []),
93205
+ columnTracks: stripDefault2(types.array(types.snapshotProcessor(types.frozen(), {
93206
+ preProcessor: readColumnTrack
93207
+ })), []),
93047
93208
  /**
93048
93209
  * #property
93049
93210
  * row-to-structure residue correspondence, computed outside the viewer
@@ -93123,20 +93284,25 @@ function stateModelFactory({ maxInlineSnapshotBytes: maxInlineSnapshotBytes2 = m
93123
93284
  clades: stripDefault2(types.array(types.frozen()), []),
93124
93285
  /**
93125
93286
  * #property
93126
- * what the viewer's own marks read from `rowData`:
93127
- * `{channel, field, scale?}` per channel, where `channel` is
93128
- * `tipLabel` or `rowTint`. See docs/layers.md
93287
+ * what the viewer's own marks read from `rowData` or the feature
93288
+ * table: `{channel, field, range?, domain?, title?}` per channel. The
93289
+ * earlier `scale: {palette}` and `scale: {map}` read as `range` and
93290
+ * `domain`. See docs/layers.md
93129
93291
  */
93130
- encodings: stripDefault2(types.array(types.frozen()), []),
93292
+ encodings: stripDefault2(types.array(types.snapshotProcessor(types.frozen(), {
93293
+ preProcessor: readEncoding
93294
+ })), []),
93131
93295
  /**
93132
93296
  * #property
93133
93297
  * panels drawn between the tree and the alignment:
93134
- * `{kind: "strip", field, scale?, width?, header?}` colors one cell
93135
- * per row from a `rowData` field, and
93298
+ * `{kind: "strip", field, range?, domain?, title?, width?, header?}`
93299
+ * colors one cell per row from a `rowData` field, and
93136
93300
  * `{kind: "features", x, encoding?, transform?, width?, header?}`
93137
93301
  * draws the spans the GFF carries. See docs/layers.md
93138
93302
  */
93139
- rowPanels: stripDefault2(types.array(types.frozen()), [])
93303
+ rowPanels: stripDefault2(types.array(types.snapshotProcessor(types.frozen(), {
93304
+ preProcessor: readRowPanel
93305
+ })), [])
93140
93306
  })).volatile(() => ({
93141
93307
  /**
93142
93308
  * #volatile
@@ -93196,9 +93362,10 @@ function stateModelFactory({ maxInlineSnapshotBytes: maxInlineSnapshotBytes2 = m
93196
93362
  volatileWidth: void 0,
93197
93363
  /**
93198
93364
  * #volatile
93199
- * resize handle width between tree and msa area, px
93365
+ * thickness of the dividers, between the tree and the alignment and under
93366
+ * the view, px
93200
93367
  */
93201
- resizeHandleWidth: 5,
93368
+ resizeHandleWidth,
93202
93369
  /**
93203
93370
  * #volatile
93204
93371
  * size of blocks of content to be drawn, px
@@ -94491,7 +94658,7 @@ function stateModelFactory({ maxInlineSnapshotBytes: maxInlineSnapshotBytes2 = m
94491
94658
  return [track.id, { arcs }];
94492
94659
  }
94493
94660
  if (track.kind === "bar") {
94494
- const max3 = track.max ?? 1;
94661
+ const max3 = track.scales?.y?.domainMax ?? 1;
94495
94662
  const values3 = skip2(project(track, track.values ?? [], 0)).map((v2) => Math.min(1, Math.max(0, v2 / max3)));
94496
94663
  return [track.id, { values: values3 }];
94497
94664
  }
@@ -94530,7 +94697,10 @@ function stateModelFactory({ maxInlineSnapshotBytes: maxInlineSnapshotBytes2 = m
94530
94697
  height: this.trackHeight(track.kind, heightKey, track.height),
94531
94698
  barColor: track.color,
94532
94699
  arcColor: track.color,
94533
- customColorScheme: track.colors,
94700
+ customColorScheme: track.encoding?.color ? colorTable(track.encoding.color, [
94701
+ ...track.encoding.color.domain ?? [],
94702
+ ...new Set(track.data)
94703
+ ]) : void 0,
94534
94704
  data: content?.data,
94535
94705
  arcs: content?.arcs
94536
94706
  }
@@ -95391,7 +95561,7 @@ function stateModelFactory({ maxInlineSnapshotBytes: maxInlineSnapshotBytes2 = m
95391
95561
  * #action
95392
95562
  */
95393
95563
  setColumnTracks(tracks) {
95394
- self.columnTracks.replace(tracks);
95564
+ self.columnTracks.replace(tracks.map(readColumnTrack));
95395
95565
  },
95396
95566
  /**
95397
95567
  * #action
@@ -95406,14 +95576,14 @@ function stateModelFactory({ maxInlineSnapshotBytes: maxInlineSnapshotBytes2 = m
95406
95576
  * replace what the viewer's marks read from the row table
95407
95577
  */
95408
95578
  setEncodings(encodings) {
95409
- self.encodings.replace(encodings);
95579
+ self.encodings.replace(encodings.map(readEncoding));
95410
95580
  },
95411
95581
  /**
95412
95582
  * #action
95413
95583
  * replace the panels drawn between the tree and the alignment
95414
95584
  */
95415
95585
  setRowPanels(panels) {
95416
- self.rowPanels.replace(panels);
95586
+ self.rowPanels.replace(panels.map(readRowPanel));
95417
95587
  },
95418
95588
  /**
95419
95589
  * #action
@@ -95516,10 +95686,15 @@ function stateModelFactory({ maxInlineSnapshotBytes: maxInlineSnapshotBytes2 = m
95516
95686
  /**
95517
95687
  * #getter
95518
95688
  * categorical feature types (InterPro domains and the like) that each get
95519
- * their own color and a legend entry
95689
+ * their own color and a legend entry, in palette order: grouped by
95690
+ * feature type, types in the order they first appear. A GenPept
95691
+ * record's CDD Sites follow every Region, so the palette spends the
95692
+ * colors after the domains' on the sites inside them
95520
95693
  */
95521
95694
  get categoricalDomainTypes() {
95522
- return [...self.annotationTypes.values()].filter((d3) => !segmentFeatureTypes.has(d3.featureType ?? ""));
95695
+ const types2 = [...self.annotationTypes.values()].filter((d3) => !segmentFeatureTypes.has(d3.featureType ?? ""));
95696
+ const typeOrder = [...new Set(types2.map((d3) => d3.featureType))];
95697
+ return types2.toSorted((a3, b2) => typeOrder.indexOf(a3.featureType) - typeOrder.indexOf(b2.featureType));
95523
95698
  },
95524
95699
  get fillPalette() {
95525
95700
  const segments = Object.fromEntries(this.segmentDomainTypes.map((d3, i2) => [
@@ -95582,46 +95757,42 @@ function stateModelFactory({ maxInlineSnapshotBytes: maxInlineSnapshotBytes2 = m
95582
95757
  * the categorical color keys drawn for this view, shared by the on-screen
95583
95758
  * legend overlay and the SVG export's reserved column. The domain overlay
95584
95759
  * produces the first, listing the `featureFill` scale where an encoding
95585
- * names one. Every field a row-table encoding or a row panel reads
95586
- * produces one more, so two channels over one field, or two strips over
95587
- * it, list that field once. A strip's `legend` names the title it lists
95588
- * under, so strips over eight fields with one set of colors list one
95589
- * legend between them
95760
+ * names one. Every scale a row-table encoding or a row panel reads
95761
+ * produces one more, keyed by its declaration, so two channels or two
95762
+ * strips declaring one scale list it once, and strips over eight fields
95763
+ * naming one `title` list one legend between them
95590
95764
  */
95591
95765
  get legends() {
95592
95766
  const { featureFillEncoding, fillPalette, visibleDomainTypes } = this;
95593
95767
  const byKey = /* @__PURE__ */ new Map();
95594
- const add = (field, entries3, id) => {
95595
- if (entries3.length === 0) {
95768
+ const ids = /* @__PURE__ */ new Set();
95769
+ const add = (key, title, entries3, overlay = false) => {
95770
+ const k2 = key ?? "domains";
95771
+ if (entries3.length === 0 || byKey.has(k2)) {
95596
95772
  return;
95597
95773
  }
95598
- const key = field === void 0 ? "domains" : `field:${field}`;
95599
- const legend = byKey.get(key);
95600
- if (legend) {
95601
- const seen = new Set(legend.entries.map((e3) => e3.id));
95602
- legend.entries.push(...entries3.filter((e3) => !seen.has(e3.id)));
95603
- } else {
95604
- byKey.set(key, {
95605
- id: id ?? (field === void 0 ? "domains" : `rowData-${field}`),
95606
- title: field ?? "Domains",
95607
- entries: [...entries3]
95608
- });
95774
+ const base = overlay || key === void 0 ? "domains" : `rowData-${title}`;
95775
+ let id = base;
95776
+ for (let n2 = 2; ids.has(id); n2++) {
95777
+ id = `${base}-${n2}`;
95609
95778
  }
95779
+ ids.add(id);
95780
+ byKey.set(k2, { id, title: title ?? "Domains", entries: entries3 });
95610
95781
  };
95611
95782
  if (self.actuallyShowDomains && self.numColumns > 0) {
95612
- add(featureFillEncoding?.field, featureFillEncoding ? featureFillEncoding.legend : visibleDomainTypes.map((d3) => ({
95783
+ add(featureFillEncoding?.key, featureFillEncoding?.title, featureFillEncoding ? featureFillEncoding.legend : visibleDomainTypes.map((d3) => ({
95613
95784
  id: d3.accession,
95614
95785
  label: d3.name,
95615
95786
  color: d3.color ?? fillPalette[d3.accession]
95616
- })), "domains");
95787
+ })), true);
95617
95788
  }
95618
- for (const { channel, field, legend } of this.resolvedEncodings) {
95789
+ for (const { channel, key, title, legend } of this.resolvedEncodings) {
95619
95790
  if (!featureChannels.has(channel)) {
95620
- add(field, legend);
95791
+ add(key, title, legend);
95621
95792
  }
95622
95793
  }
95623
- for (const { legendTitle, legend } of this.rowPanelScales) {
95624
- add(legendTitle, legend);
95794
+ for (const { legendKey, legendTitle, legend } of this.rowPanelScales) {
95795
+ add(legendKey, legendTitle, legend);
95625
95796
  }
95626
95797
  return [...byKey.values()];
95627
95798
  },
@@ -95853,12 +96024,46 @@ function stateModelFactory({ maxInlineSnapshotBytes: maxInlineSnapshotBytes2 = m
95853
96024
  * table or the encodings, never per row per frame.
95854
96025
  */
95855
96026
  get resolvedEncodings() {
95856
- const rows = Object.values(self.rowData);
95857
96027
  return self.encodings.map((encoding) => ({
95858
96028
  ...encoding,
95859
- ...featureChannels.has(encoding.channel) ? resolveFeatureScale(encoding.field, encoding.scale, self.allAnnotations, self.filteredAnnotations) : resolveScale(encoding.scale, rows.map((row) => row?.[encoding.field]).filter(notEmpty))
96029
+ ...this.scaleOf(encoding, featureChannels.has(encoding.channel) ? "features" : "rows")
95860
96030
  }));
95861
96031
  },
96032
+ /**
96033
+ * #getter
96034
+ * every color object the encodings and the row panels declare, keyed
96035
+ * by declaration (`declarationKey`) and resolved once over the union
96036
+ * of the values its records' fields take, so a value two strips share
96037
+ * takes one color in both. A feature field reads every feature loaded,
96038
+ * so hiding a type in the filter dialog leaves the rest in their
96039
+ * colors, and its legend lists the values of the drawn features.
96040
+ */
96041
+ get resolvedScales() {
96042
+ const rows = Object.values(self.rowData);
96043
+ const featureValues = (list, field) => list.map((a3) => featureField(a3, field)).filter(notEmpty);
96044
+ const use4 = (channel, table) => ({
96045
+ spec: channel,
96046
+ field: channel.field,
96047
+ table,
96048
+ ...table === "rows" ? {
96049
+ values: rows.map((row) => row?.[channel.field]).filter(notEmpty)
96050
+ } : {
96051
+ values: featureValues(self.allAnnotations, channel.field),
96052
+ shown: featureValues(self.filteredAnnotations, channel.field)
96053
+ }
96054
+ });
96055
+ return resolveShared([
96056
+ ...self.encodings.map((encoding) => use4(encoding, featureChannels.has(encoding.channel) ? "features" : "rows")),
96057
+ ...self.rowPanels.flatMap((panel) => panel.kind === "strip" ? [use4(panel, "rows")] : panel.encoding?.color ? [use4(panel.encoding.color, "features")] : [])
96058
+ ]);
96059
+ },
96060
+ /**
96061
+ * #method
96062
+ * the shared scale a record's color object resolves to
96063
+ */
96064
+ scaleOf(channel, table) {
96065
+ return this.resolvedScales.get(declarationKey({ spec: channel, field: channel.field, table }));
96066
+ },
95862
96067
  /**
95863
96068
  * #getter
95864
96069
  * each row panel's scale resolved against the values its field takes,
@@ -95872,14 +96077,15 @@ function stateModelFactory({ maxInlineSnapshotBytes: maxInlineSnapshotBytes2 = m
95872
96077
  return self.rowPanels.map((panel) => {
95873
96078
  if (panel.kind === "features") {
95874
96079
  const color2 = panel.encoding?.color;
95875
- const encoding = color2 ? resolveFeatureScale(color2.field, color2.scale, self.allAnnotations, annotations) : featureFillEncoding;
96080
+ const encoding = color2 ? { field: color2.field, ...this.scaleOf(color2, "features") } : featureFillEncoding;
95876
96081
  const label2 = panel.encoding?.label;
95877
96082
  return {
95878
96083
  kind: panel.kind,
95879
96084
  x: panel.x,
95880
96085
  header: panel.header ?? "",
95881
96086
  field: encoding?.field,
95882
- legendTitle: encoding?.field,
96087
+ legendKey: encoding?.key,
96088
+ legendTitle: encoding?.title,
95883
96089
  colors: color2 ? featureColorMap(annotations, encoding, fillPalette) : this.featureColors,
95884
96090
  labels: label2 ? featureLabelMap(annotations, label2) : featureLabels,
95885
96091
  legend: encoding?.legend ?? this.visibleDomainTypes.map((d3) => ({
@@ -95889,12 +96095,13 @@ function stateModelFactory({ maxInlineSnapshotBytes: maxInlineSnapshotBytes2 = m
95889
96095
  }))
95890
96096
  };
95891
96097
  }
95892
- const { colorOf, legend } = resolveScale(panel.scale, Object.values(rowData).map((row) => row?.[panel.field]).filter(notEmpty));
96098
+ const { colorOf, legend, key, title } = this.scaleOf(panel, "rows");
95893
96099
  return {
95894
96100
  kind: panel.kind,
95895
96101
  field: panel.field,
95896
96102
  header: panel.header ?? panel.field,
95897
- legendTitle: panel.legend ?? panel.field,
96103
+ legendKey: key,
96104
+ legendTitle: title,
95898
96105
  colors: colorByRow(rowData, panel.field, colorOf),
95899
96106
  legend
95900
96107
  };
@@ -96438,7 +96645,7 @@ var init_model = __esm({
96438
96645
 
96439
96646
  // ../lib/dist/viewerSnapshot.js
96440
96647
  function colorSchemeSnapshot(scheme) {
96441
- return typeof scheme === "string" ? { colorSchemeName: scheme } : scheme ? { customColorScheme: scheme.map } : {};
96648
+ return typeof scheme === "string" ? { colorSchemeName: scheme } : scheme ? { customColorScheme: letterColors(scheme) } : {};
96442
96649
  }
96443
96650
  function columnHighlights(columns = []) {
96444
96651
  const sorted = [...new Set(columns)].sort((a3, b2) => a3 - b2);
@@ -96514,6 +96721,7 @@ var init_viewerSnapshot = __esm({
96514
96721
  "../lib/dist/viewerSnapshot.js"() {
96515
96722
  "use strict";
96516
96723
  init_theme();
96724
+ init_scales();
96517
96725
  }
96518
96726
  });
96519
96727
 
@@ -96628,6 +96836,7 @@ var init_MSAViewer = __esm({
96628
96836
  init_styles();
96629
96837
  import_mobx7 = __toESM(require_dist(), 1);
96630
96838
  init_model();
96839
+ init_scales();
96631
96840
  init_viewerSnapshot();
96632
96841
  init_Loading2();
96633
96842
  MSAViewer = (0, import_react104.forwardRef)(function MSAViewer2(props, ref) {
@@ -96689,7 +96898,7 @@ var init_MSAViewer = __esm({
96689
96898
  if (typeof scheme === "string") {
96690
96899
  m2.setColorSchemeName(scheme);
96691
96900
  } else if (scheme) {
96692
- m2.setCustomColorScheme(scheme.map);
96901
+ m2.setCustomColorScheme(letterColors(scheme));
96693
96902
  }
96694
96903
  }),
96695
96904
  synced(viewerHighlights, (m2, v2) => {
@@ -96814,6 +97023,7 @@ function defineMsaElement(tagName = "jbrowse-msa") {
96814
97023
  class MsaElement extends HTMLElement {
96815
97024
  static observedAttributes = [...ownAttributes, ...nightingaleAttributes];
96816
97025
  #viewer;
97026
+ #nearby;
96817
97027
  #model;
96818
97028
  #manager;
96819
97029
  #cancelRange;
@@ -96947,7 +97157,18 @@ function defineMsaElement(tagName = "jbrowse-msa") {
96947
97157
  if (!this.style.display) {
96948
97158
  this.style.display = "block";
96949
97159
  }
96950
- this.#viewer = mount(this, this.#props());
97160
+ if (this.#lazy) {
97161
+ const height2 = numberAttribute(this.getAttribute("height")) ?? defaultHeight;
97162
+ this.style.minHeight = `${height2 + resizeHandleWidth}px`;
97163
+ this.#nearby = new IntersectionObserver((entries3) => {
97164
+ if (entries3.some((entry) => entry.isIntersecting)) {
97165
+ this.#mount();
97166
+ }
97167
+ }, { rootMargin: lazyMargin });
97168
+ this.#nearby.observe(this);
97169
+ } else {
97170
+ this.#mount();
97171
+ }
96951
97172
  const manager2 = this.closest("nightingale-manager");
96952
97173
  if (manager2) {
96953
97174
  void customElements.whenDefined("nightingale-manager").then(() => {
@@ -96958,7 +97179,17 @@ function defineMsaElement(tagName = "jbrowse-msa") {
96958
97179
  });
96959
97180
  }
96960
97181
  }
97182
+ get #lazy() {
97183
+ return this.getAttribute("loading") === "lazy" && typeof IntersectionObserver !== "undefined";
97184
+ }
97185
+ #mount() {
97186
+ this.#nearby?.disconnect();
97187
+ this.#nearby = void 0;
97188
+ this.#viewer ??= mount(this, this.#props());
97189
+ }
96961
97190
  disconnectedCallback() {
97191
+ this.#nearby?.disconnect();
97192
+ this.#nearby = void 0;
96962
97193
  this.#manager?.unregister(this);
96963
97194
  this.#manager = void 0;
96964
97195
  this.#cancelRange?.();
@@ -96977,6 +97208,10 @@ function defineMsaElement(tagName = "jbrowse-msa") {
96977
97208
  }
96978
97209
  } else if (name === "highlight") {
96979
97210
  this.#followHighlight();
97211
+ } else if (name === "loading") {
97212
+ if (this.#nearby && !this.#lazy) {
97213
+ this.#mount();
97214
+ }
96980
97215
  } else {
96981
97216
  this.#viewer?.update(this.#props());
96982
97217
  }
@@ -96985,11 +97220,12 @@ function defineMsaElement(tagName = "jbrowse-msa") {
96985
97220
  customElements.define(tagName, MsaElement);
96986
97221
  return MsaElement;
96987
97222
  }
96988
- var import_mobx8, dataProperties, ownAttributes, nightingaleAttributes;
97223
+ var import_mobx8, dataProperties, ownAttributes, lazyMargin, nightingaleAttributes;
96989
97224
  var init_element = __esm({
96990
97225
  "../lib/dist/element.js"() {
96991
97226
  "use strict";
96992
97227
  import_mobx8 = __toESM(require_dist(), 1);
97228
+ init_constants();
96993
97229
  init_mount();
96994
97230
  dataProperties = [
96995
97231
  "msa",
@@ -97010,8 +97246,10 @@ var init_element = __esm({
97010
97246
  "hide-header",
97011
97247
  "theme",
97012
97248
  "reference-row",
97013
- "tree-area-width"
97249
+ "tree-area-width",
97250
+ "loading"
97014
97251
  ];
97252
+ lazyMargin = "200px";
97015
97253
  nightingaleAttributes = ["display-start", "display-end", "highlight"];
97016
97254
  }
97017
97255
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-msaview-cli",
3
- "version": "9.2.0",
3
+ "version": "9.4.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "repository": {
@@ -20,8 +20,8 @@
20
20
  "@types/node": "^26.6.5",
21
21
  "esbuild": "^0.28.2",
22
22
  "mobx-react": "^10.0.2",
23
- "msa-parsers": "9.2.0",
24
- "react-msaview": "9.2.0"
23
+ "msa-parsers": "9.4.0",
24
+ "react-msaview": "9.4.0"
25
25
  },
26
26
  "dependencies": {
27
27
  "jsdom": "^30.1.3"