gosling.js 2.0.0-alpha.1 → 2.0.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"gosling-component.d.ts","sourceRoot":"","sources":["../../demo/gosling-component.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAuB,KAAK,SAAS,EAAuB,MAAM,OAAO,CAAC;AACxF,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAW,KAAK,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAI1E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAErD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,MAAM,MAAM,UAAU,GAAG;IAAE,GAAG,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAA;CAAE,CAAC;AAIjE,UAAU,qBAAqB;IAC3B,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,GAAG,CAAC,EAAE,SAAS,CAAC,UAAU,CAAC,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,eAoD5D;AACD;;GAEG;AACH,wBAAgB,aAAa,CACzB,EAAE,EAAE,WAAW,EACf,SAAS,EAAE,cAAc,EACzB,WAAW,EAAE,WAAW,EACxB,KAAK,EAAE,KAAK,EACZ,iBAAiB,CAAC,EAAE,iBAAiB;;;;;;;;EAiDxC"}
1
+ {"version":3,"file":"gosling-component.d.ts","sourceRoot":"","sources":["../../demo/gosling-component.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAuB,KAAK,SAAS,EAAuB,MAAM,OAAO,CAAC;AACxF,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAW,KAAK,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAI1E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAErD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,MAAM,MAAM,UAAU,GAAG;IAAE,GAAG,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAA;CAAE,CAAC;AAIjE,UAAU,qBAAqB;IAC3B,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,GAAG,CAAC,EAAE,SAAS,CAAC,UAAU,CAAC,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,eAuD5D;AACD;;GAEG;AACH,wBAAgB,aAAa,CACzB,EAAE,EAAE,WAAW,EACf,SAAS,EAAE,cAAc,EACzB,WAAW,EAAE,WAAW,EACxB,KAAK,EAAE,KAAK,EACZ,iBAAiB,CAAC,EAAE,iBAAiB;;;;;;;;EAiDxC"}
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../demo/renderer/main.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,SAAS,EAAa,MAAM,mBAAmB,CAAC;AAE9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAGhE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAK9D;;;;GAIG;AACH,wBAAgB,eAAe,CAC3B,SAAS,EAAE,SAAS,EAAE,EACtB,eAAe,EAAE,cAAc,EAAE,EACjC,WAAW,EAAE,WAAW,EACxB,iBAAiB,CAAC,EAAE,iBAAiB,2BAiHxC"}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../demo/renderer/main.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,SAAS,EAAa,MAAM,mBAAmB,CAAC;AAE9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAGhE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAK9D;;;;GAIG;AACH,wBAAgB,eAAe,CAC3B,SAAS,EAAE,SAAS,EAAE,EACtB,eAAe,EAAE,cAAc,EAAE,EACjC,WAAW,EAAE,WAAW,EACxB,iBAAiB,CAAC,EAAE,iBAAiB,2BA0HxC"}
package/dist/gosling.js CHANGED
@@ -55,7 +55,7 @@ import { createNanoEvents } from "nanoevents";
55
55
  import PubSub$1 from "pubsub-js";
56
56
  import { zoom, ZoomTransform } from "d3-zoom";
57
57
  const name = "gosling.js";
58
- const version = "2.0.0-alpha.1";
58
+ const version = "2.0.0-alpha.2";
59
59
  const $ref$1 = "#/definitions/GoslingSpec";
60
60
  const $schema$1 = "http://json-schema.org/draft-07/schema#";
61
61
  const definitions$1 = {
@@ -11766,7 +11766,7 @@ function compile(spec, templates, theme, containerStatus) {
11766
11766
  return compileResult;
11767
11767
  }
11768
11768
  class PixiManager {
11769
- constructor(width, height, container, fps, options) {
11769
+ constructor(width, height, container, fps, options = {}) {
11770
11770
  __publicField(this, "app");
11771
11771
  /** Contains the canvas and the overlayContainer */
11772
11772
  __publicField(this, "rootDiv");
@@ -11774,6 +11774,7 @@ class PixiManager {
11774
11774
  __publicField(this, "overlayContainer");
11775
11775
  /** Mapping between the position and the overlay div */
11776
11776
  __publicField(this, "createdContainers", /* @__PURE__ */ new Map());
11777
+ var _a, _b;
11777
11778
  this.app = new PIXI.Application({
11778
11779
  width,
11779
11780
  height,
@@ -11784,7 +11785,8 @@ class PixiManager {
11784
11785
  autoDensity: true,
11785
11786
  // When resolution is set, this should be true so things are scaled correctly
11786
11787
  view: document.createElement("canvas"),
11787
- backgroundColor: 16777215,
11788
+ backgroundColor: (_a = options.background) != null ? _a : 16777215,
11789
+ backgroundAlpha: options.background === "transparent" ? 0 : 1,
11788
11790
  eventMode: "static",
11789
11791
  eventFeatures: {
11790
11792
  move: true,
@@ -11796,7 +11798,7 @@ class PixiManager {
11796
11798
  const wrapper = document.createElement("div");
11797
11799
  const padding = options.padding || 50;
11798
11800
  wrapper.style.padding = `${padding}px`;
11799
- wrapper.style.backgroundColor = "white";
11801
+ wrapper.style.backgroundColor = options.background === "transparent" ? "#ffffff00" : (_b = options.background) != null ? _b : "#ffffff";
11800
11802
  container.appendChild(wrapper);
11801
11803
  const rootDiv = document.createElement("div");
11802
11804
  rootDiv.style.position = "relative";
@@ -29316,8 +29318,7 @@ isTooStretched_fn = function(stretchFactor) {
29316
29318
  */
29317
29319
  __privateAdd(_GoslingTrackClass, _tilesToId);
29318
29320
  let GoslingTrackClass = _GoslingTrackClass;
29319
- function zoomWheelBehavior(event) {
29320
- const defaultMultiplier = 1;
29321
+ function zoomWheelBehavior(event, defaultMultiplier = 1) {
29321
29322
  return -event.deltaY * (event.deltaMode === 1 ? 0.05 : event.deltaMode ? 1 : 2e-3) * (event.ctrlKey ? 10 : defaultMultiplier);
29322
29323
  }
29323
29324
  class GoslingTrack extends GoslingTrackClass {
@@ -29468,14 +29469,17 @@ function cursor(plot, cursorPos) {
29468
29469
  const newScale = baseScale.domain(plot.xDomain.value);
29469
29470
  const genomicPos = newScale.invert(event.offsetX);
29470
29471
  cursorPos.value = genomicPos;
29472
+ cursor2.visible = true;
29471
29473
  };
29472
29474
  plot.domOverlay.addEventListener("mousemove", moveCursor);
29473
29475
  plot.domOverlay.addEventListener("mouseleave", () => {
29474
- cursorPos.value = -10;
29476
+ cursorPos.value = Number.NEGATIVE_INFINITY;
29477
+ cursor2.visible = false;
29475
29478
  });
29476
29479
  effect(() => {
29477
29480
  const newScale = baseScale.domain(plot.xDomain.value);
29478
29481
  cursor2.position.x = newScale(cursorPos.value);
29482
+ cursor2.visible = true;
29479
29483
  });
29480
29484
  }
29481
29485
  function cursor2D(plot, cursorPosX, cursorPosY) {
@@ -29608,6 +29612,116 @@ function panZoomHeatmap(plot, xDomain, yDomain) {
29608
29612
  }
29609
29613
  });
29610
29614
  }
29615
+ function cursorCircular(plot, cursorPos) {
29616
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
29617
+ const xDomain = plot.xDomain.value;
29618
+ const cx = plot.domOverlay.clientWidth / 2;
29619
+ const cy = plot.domOverlay.clientHeight / 2;
29620
+ const innerRadius = (_c = (_b = (_a = plot.options) == null ? void 0 : _a.spec) == null ? void 0 : _b.innerRadius) != null ? _c : 40;
29621
+ const isAxis = IsXAxis(plot.options.spec);
29622
+ const outerRadius = ((_f = (_e = (_d = plot.options) == null ? void 0 : _d.spec) == null ? void 0 : _e.outerRadius) != null ? _f : Math.min(cx, cy)) - (isAxis ? DEFAULT_AXIS_SIZE : 0);
29623
+ const startAngle = (_i = (_h = (_g = plot.options) == null ? void 0 : _g.spec) == null ? void 0 : _h.startAngle) != null ? _i : 0;
29624
+ const endAngle = (_l = (_k = (_j = plot.options) == null ? void 0 : _j.spec) == null ? void 0 : _k.endAngle) != null ? _l : 360;
29625
+ const baseScaleAngle = scaleLinear().domain(xDomain).range([0, 2 * Math.PI]);
29626
+ const cursor2 = new PIXI.Graphics();
29627
+ plot.pMasked.addChild(cursor2);
29628
+ const moveCursor = (event) => {
29629
+ const degree = pointsToDegree(event.offsetX, event.offsetY, cx, cy);
29630
+ const angleRange = endAngle - startAngle;
29631
+ const normalizedDegree = (degree - startAngle + 360) % 360 / angleRange;
29632
+ const newScaleAngle = baseScaleAngle.domain(plot.xDomain.value);
29633
+ const genomicPos = newScaleAngle.invert(normalizedDegree * 2 * Math.PI);
29634
+ cursorPos.value = genomicPos;
29635
+ const radian = valueToRadian(
29636
+ genomicPos - plot.xDomain.value[0],
29637
+ plot.xDomain.value[1] - plot.xDomain.value[0],
29638
+ startAngle,
29639
+ endAngle
29640
+ );
29641
+ cursor2.clear();
29642
+ cursor2.lineStyle(1, "black", 1);
29643
+ cursor2.moveTo(cx + Math.cos(radian) * innerRadius, cy + Math.sin(radian) * innerRadius);
29644
+ cursor2.lineTo(cx + Math.cos(radian) * outerRadius, cy + Math.sin(radian) * outerRadius);
29645
+ };
29646
+ plot.domOverlay.addEventListener("mousemove", moveCursor);
29647
+ plot.domOverlay.addEventListener("mouseleave", () => {
29648
+ cursorPos.value = Number.NEGATIVE_INFINITY;
29649
+ cursor2.clear();
29650
+ });
29651
+ effect(() => {
29652
+ if (plot.xDomain.value[0] < cursorPos.value && cursorPos.value < plot.xDomain.value[1]) {
29653
+ const radian = valueToRadian(
29654
+ cursorPos.value - plot.xDomain.value[0],
29655
+ plot.xDomain.value[1] - plot.xDomain.value[0],
29656
+ startAngle,
29657
+ endAngle
29658
+ );
29659
+ cursor2.clear();
29660
+ cursor2.lineStyle(1, "black", 1);
29661
+ cursor2.moveTo(cx + Math.cos(radian) * innerRadius, cy + Math.sin(radian) * innerRadius);
29662
+ cursor2.lineTo(cx + Math.cos(radian) * outerRadius, cy + Math.sin(radian) * outerRadius);
29663
+ } else {
29664
+ cursor2.clear();
29665
+ }
29666
+ });
29667
+ }
29668
+ function panZoomCircular(plot, cursorPos, xDomain) {
29669
+ var _a, _b, _c, _d, _e, _f;
29670
+ plot.xDomain = xDomain;
29671
+ const zoomStartScaleX = scaleLinear();
29672
+ const centerX = plot.domOverlay.clientWidth / 2;
29673
+ const centerY = plot.domOverlay.clientHeight / 2;
29674
+ const startAngle = (_c = (_b = (_a = plot.options) == null ? void 0 : _a.spec) == null ? void 0 : _b.startAngle) != null ? _c : 0;
29675
+ const endAngle = (_f = (_e = (_d = plot.options) == null ? void 0 : _d.spec) == null ? void 0 : _e.endAngle) != null ? _f : 360;
29676
+ let panStartAngle = 0;
29677
+ let zoomStartPos = 0;
29678
+ let panStartDomain = [0, 0];
29679
+ const zoomed = (event) => {
29680
+ const { transform, sourceEvent } = event;
29681
+ if (sourceEvent && sourceEvent.type === "wheel") {
29682
+ const newXDomain = transform.rescaleX(zoomStartScaleX).domain();
29683
+ const newDomain = newXDomain[1] - newXDomain[0];
29684
+ const originalDomain = zoomStartScaleX.domain()[1] - zoomStartScaleX.domain()[0];
29685
+ const mouseRelativePos = (zoomStartPos - zoomStartScaleX.domain()[0]) / originalDomain;
29686
+ const adjustedStart = zoomStartPos - newDomain * mouseRelativePos;
29687
+ const centeredDomain = [adjustedStart, adjustedStart + newDomain];
29688
+ batch(() => {
29689
+ xDomain.value = centeredDomain;
29690
+ });
29691
+ } else if (sourceEvent && (sourceEvent.type === "mousemove" || sourceEvent.type === "mousedown")) {
29692
+ const mouseX = sourceEvent.offsetX || sourceEvent.layerX;
29693
+ const mouseY = sourceEvent.offsetY || sourceEvent.layerY;
29694
+ const currentAngleDegrees = pointsToDegree(mouseX, mouseY, centerX, centerY);
29695
+ const angleDiff = currentAngleDegrees - panStartAngle;
29696
+ const angleRange = endAngle - startAngle;
29697
+ const domainRange = panStartDomain[1] - panStartDomain[0];
29698
+ const domainDiff = angleDiff / angleRange * domainRange;
29699
+ const newXDomain = [panStartDomain[0] - domainDiff, panStartDomain[1] - domainDiff];
29700
+ batch(() => {
29701
+ xDomain.value = newXDomain;
29702
+ });
29703
+ }
29704
+ };
29705
+ const zoomBehavior = zoom().wheelDelta(zoomWheelBehavior).filter((event) => {
29706
+ const isRect = event.target.tagName === "rect";
29707
+ const isMousedown = event.type === "mousedown";
29708
+ const isDraggingBrush = isRect && isMousedown;
29709
+ const isAltPressed = event.altKey;
29710
+ const defaultFilter = (!event.ctrlKey || event.type === "wheel") && !event.button;
29711
+ return defaultFilter && !isDraggingBrush && !isAltPressed;
29712
+ }).on("end", () => plot.domOverlay.__zoom = new ZoomTransform(1, 0, 0)).on("start", (event) => {
29713
+ zoomStartPos = cursorPos.value;
29714
+ zoomStartScaleX.domain(xDomain.value).range([0, plot.width]);
29715
+ const { sourceEvent } = event;
29716
+ if (sourceEvent && sourceEvent.type === "mousedown") {
29717
+ const mouseX = sourceEvent.offsetX || sourceEvent.layerX;
29718
+ const mouseY = sourceEvent.offsetY || sourceEvent.layerY;
29719
+ panStartAngle = pointsToDegree(mouseX, mouseY, centerX, centerY);
29720
+ panStartDomain = [...xDomain.value];
29721
+ }
29722
+ }).on("zoom", zoomed);
29723
+ select(plot.domOverlay).call(zoomBehavior);
29724
+ }
29611
29725
  function getDataFetcher(spec, urlToFetchOptions) {
29612
29726
  const { data, assembly = "hg38" } = spec;
29613
29727
  if (typeof data === "undefined") {
@@ -29665,8 +29779,8 @@ function getFields(spec) {
29665
29779
  }
29666
29780
  function renderTrackDefs(trackDefs, linkedEncodings, pixiManager, urlToFetchOptions) {
29667
29781
  const plotDict = {};
29668
- const cursorPosX = signal(0);
29669
- const cursorPosY = signal(0);
29782
+ const cursorPosX = signal(Number.NEGATIVE_INFINITY);
29783
+ const cursorPosY = signal(Number.NEGATIVE_INFINITY);
29670
29784
  trackDefs.forEach((trackDef) => {
29671
29785
  const { boundingBox, type, options, trackId } = trackDef;
29672
29786
  if (type === TrackType.Text) {
@@ -29693,10 +29807,18 @@ function renderTrackDefs(trackDefs, linkedEncodings, pixiManager, urlToFetchOpti
29693
29807
  gosOptions.spec.orientation
29694
29808
  );
29695
29809
  const isOverlayedOnPrevious = "overlayOnPreviousTrack" in spec && spec.overlayOnPreviousTrack;
29696
- if (!spec.static && !isOverlayedOnPrevious) {
29697
- gosPlot.addInteractor((plot) => panZoom(plot, xDomain, yDomain));
29810
+ if (!spec.static && !(spec.layout === "linear" && isOverlayedOnPrevious)) {
29811
+ if (spec.layout === "circular") {
29812
+ gosPlot.addInteractor((plot) => panZoomCircular(plot, cursorPosX, xDomain));
29813
+ } else {
29814
+ gosPlot.addInteractor((plot) => panZoom(plot, xDomain, yDomain));
29815
+ }
29816
+ }
29817
+ if (spec.layout === "circular") {
29818
+ gosPlot.addInteractor((plot) => cursorCircular(plot, cursorPosX));
29819
+ } else {
29820
+ gosPlot.addInteractor((plot) => cursor(plot, cursorPosX));
29698
29821
  }
29699
- gosPlot.addInteractor((plot) => cursor(plot, cursorPosX));
29700
29822
  plotDict[trackId] = gosPlot;
29701
29823
  }
29702
29824
  if (type === TrackType.Heatmap) {
@@ -30259,7 +30381,10 @@ function GoslingComponent(props) {
30259
30381
  if (!pixiManager) {
30260
30382
  const canvasWidth = 1e3, canvasHeight = 1e3;
30261
30383
  const pixiManager2 = new PixiManager(canvasWidth, canvasHeight, plotElement, () => {
30262
- }, { padding });
30384
+ }, {
30385
+ padding,
30386
+ background: getTheme(theme).root.background
30387
+ });
30263
30388
  const compileResult = renderGosling(spec, plotElement, pixiManager2, theme, urlToFetchOptions);
30264
30389
  setCompiledResults(compileResult);
30265
30390
  setPixiManager(pixiManager2);