@jbrowse/plugin-linear-genome-view 4.1.1 → 4.1.4

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 (47) hide show
  1. package/esm/BaseLinearDisplay/components/FloatingLabels.js +3 -4
  2. package/esm/BaseLinearDisplay/components/LinearBlocks.js +3 -1
  3. package/esm/BaseLinearDisplay/components/LoadingOverlay.d.ts +2 -1
  4. package/esm/BaseLinearDisplay/components/LoadingOverlay.js +2 -2
  5. package/esm/BaseLinearDisplay/components/NonBlockCanvasDisplayComponent.d.ts +1 -0
  6. package/esm/BaseLinearDisplay/components/NonBlockCanvasDisplayComponent.js +2 -2
  7. package/esm/BaseLinearDisplay/components/ServerSideRenderedBlockContent.d.ts +1 -0
  8. package/esm/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js +1 -1
  9. package/esm/BaseLinearDisplay/components/util.d.ts +8 -8
  10. package/esm/BaseLinearDisplay/components/util.js +25 -35
  11. package/esm/BaseLinearDisplay/model.d.ts +19 -9
  12. package/esm/BaseLinearDisplay/models/SvgFloatingLabels.d.ts +8 -0
  13. package/esm/BaseLinearDisplay/models/SvgFloatingLabels.js +19 -0
  14. package/esm/BaseLinearDisplay/models/configSchema.d.ts +2 -2
  15. package/esm/BaseLinearDisplay/models/serverSideRenderedBlock.d.ts +2 -0
  16. package/esm/BaseLinearDisplay/models/serverSideRenderedBlock.js +3 -0
  17. package/esm/BaseLinearDisplay/models/util.d.ts +0 -13
  18. package/esm/BaseLinearDisplay/renderSvg.js +8 -4
  19. package/esm/BaseLinearDisplay/types.d.ts +0 -4
  20. package/esm/BasicTrack/configSchema.d.ts +8 -8
  21. package/esm/FeatureTrack/configSchema.d.ts +8 -8
  22. package/esm/LinearBareDisplay/configSchema.d.ts +3 -3
  23. package/esm/LinearBareDisplay/model.d.ts +19 -9
  24. package/esm/LinearBasicDisplay/configSchema.d.ts +3 -3
  25. package/esm/LinearBasicDisplay/model.d.ts +18 -8
  26. package/esm/LinearFeatureDisplay/configSchema.d.ts +3 -3
  27. package/esm/LinearFeatureDisplay/model.d.ts +22 -10
  28. package/esm/LinearGenomeView/components/ExportSvgDialog.js +18 -6
  29. package/esm/LinearGenomeView/components/Gridlines.js +3 -2
  30. package/esm/LinearGenomeView/components/Scalebar.js +3 -2
  31. package/esm/LinearGenomeView/components/ScalebarRefNameLabels.js +2 -2
  32. package/esm/LinearGenomeView/components/SearchResultsTable.js +2 -7
  33. package/esm/LinearGenomeView/components/TracksContainer.js +1 -1
  34. package/esm/LinearGenomeView/lazyDialogs.d.ts +23 -0
  35. package/esm/LinearGenomeView/lazyDialogs.js +5 -0
  36. package/esm/LinearGenomeView/menuItems.js +1 -5
  37. package/esm/LinearGenomeView/model.d.ts +2 -1
  38. package/esm/LinearGenomeView/model.js +64 -13
  39. package/esm/LinearGenomeView/types.d.ts +1 -0
  40. package/esm/index.d.ts +24 -13
  41. package/esm/index.js +1 -0
  42. package/esm/searchUtils.js +4 -1
  43. package/package.json +5 -5
  44. package/esm/BaseLinearDisplay/models/calculateLabelPositions.d.ts +0 -24
  45. package/esm/BaseLinearDisplay/models/calculateLabelPositions.js +0 -60
  46. package/esm/BaseLinearDisplay/models/renderSvg.d.ts +0 -3
  47. package/esm/BaseLinearDisplay/models/renderSvg.js +0 -55
@@ -31,8 +31,8 @@ const FixedLabel = memo(function FixedLabel({ text, color, isOverlay, featureLef
31
31
  transform: `translate(calc(${featureLeftPx}px - var(--offset-px)), ${y}px)`,
32
32
  }, children: text }));
33
33
  });
34
- function FloatingLabel({ text, color, isOverlay, featureLeftPx, featureRightPx, featureId, subfeatureId, labelWidth, y, offsetPx, viewportLeft, tooltip, labelClass, overlayClass, }) {
35
- const x = calculateFloatingLabelPosition(featureLeftPx, featureRightPx, labelWidth, offsetPx, viewportLeft);
34
+ function FloatingLabel({ text, color, isOverlay, featureLeftPx, featureRightPx, featureId, subfeatureId, labelWidth, y, offsetPx, tooltip, labelClass, overlayClass, }) {
35
+ const x = calculateFloatingLabelPosition(featureLeftPx, featureRightPx, labelWidth, offsetPx);
36
36
  return (_jsx("div", { "data-feature-id": featureId, "data-subfeature-id": subfeatureId, "data-tooltip": tooltip, className: isOverlay ? `${labelClass} ${overlayClass}` : labelClass, style: { color, transform: `translate(${x}px,${y}px)` }, children: text }));
37
37
  }
38
38
  const FloatingLabels = observer(function FloatingLabels({ model, }) {
@@ -43,7 +43,6 @@ const FloatingLabels = observer(function FloatingLabels({ model, }) {
43
43
  const { onFeatureClick, onFeatureContextMenu, onMouseMove } = model.renderingProps();
44
44
  const fixedLabels = [];
45
45
  const floatingLabels = [];
46
- const viewportLeft = Math.max(0, offsetPx);
47
46
  for (const [key, { leftPx, topPx, totalFeatureHeight, floatingLabels: labelData, featureWidth, },] of featureLabels.entries()) {
48
47
  const featureVisualBottom = topPx + totalFeatureHeight;
49
48
  const featureRightPx = leftPx + featureWidth;
@@ -57,7 +56,7 @@ const FloatingLabels = observer(function FloatingLabels({ model, }) {
57
56
  fixedLabels.push(_jsx(FixedLabel, { text: text, color: color, isOverlay: isOverlay ?? false, featureLeftPx: leftPx, featureId: featureId, subfeatureId: subfeatureId, y: y, tooltip: tooltip, labelClass: classes.label, overlayClass: classes.overlay }, labelKey));
58
57
  }
59
58
  else {
60
- floatingLabels.push(_jsx(FloatingLabel, { text: text, color: color, isOverlay: isOverlay ?? false, featureLeftPx: leftPx, featureRightPx: featureRightPx, featureId: featureId, subfeatureId: subfeatureId, labelWidth: labelWidth, y: y, offsetPx: offsetPx, viewportLeft: viewportLeft, tooltip: tooltip, labelClass: classes.label, overlayClass: classes.overlay }, labelKey));
59
+ floatingLabels.push(_jsx(FloatingLabel, { text: text, color: color, isOverlay: isOverlay ?? false, featureLeftPx: leftPx, featureRightPx: featureRightPx, featureId: featureId, subfeatureId: subfeatureId, labelWidth: labelWidth, y: y, offsetPx: offsetPx, tooltip: tooltip, labelClass: classes.label, overlayClass: classes.overlay }, labelKey));
61
60
  }
62
61
  }
63
62
  }
@@ -1,4 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { getContainingView } from '@jbrowse/core/util';
2
3
  import { makeStyles } from '@jbrowse/core/util/tss-react';
3
4
  import { observer } from 'mobx-react';
4
5
  import RenderedBlocks from "./RenderedBlocks.js";
@@ -14,8 +15,9 @@ const useStyles = makeStyles()({
14
15
  const LinearBlocks = observer(function LinearBlocks({ model, }) {
15
16
  const { classes } = useStyles();
16
17
  const { blockDefinitions } = model;
18
+ const viewModel = getContainingView(model);
17
19
  return (_jsx("div", { className: classes.linearBlocks, style: {
18
- left: `calc(${blockDefinitions.offsetPx}px - var(--offset-px))`,
20
+ left: blockDefinitions.offsetPx - viewModel.offsetPx,
19
21
  }, children: _jsx(RenderedBlocks, { model: model }) }));
20
22
  });
21
23
  export default LinearBlocks;
@@ -1,4 +1,5 @@
1
- export default function LoadingOverlay({ statusMessage, children, }: {
1
+ export default function LoadingOverlay({ statusMessage, children, height, }: {
2
2
  statusMessage?: string;
3
3
  children?: React.ReactNode;
4
+ height?: number;
4
5
  }): import("react/jsx-runtime").JSX.Element;
@@ -42,8 +42,8 @@ const useStyles = makeStyles()({
42
42
  },
43
43
  },
44
44
  });
45
- export default function LoadingOverlay({ statusMessage, children, }) {
45
+ export default function LoadingOverlay({ statusMessage, children, height, }) {
46
46
  const { classes } = useStyles();
47
47
  const isLoading = !!statusMessage;
48
- return (_jsxs("div", { className: classes.container, children: [children, _jsx("span", { className: cx(classes.overlay, isLoading && classes.visible), "data-testid": isLoading ? 'loading-overlay' : undefined, children: _jsx("span", { className: classes.dots, children: statusMessage || 'Loading' }) })] }));
48
+ return (_jsxs("div", { className: classes.container, style: height ? { height } : undefined, children: [children, _jsx("span", { className: cx(classes.overlay, isLoading && classes.visible), "data-testid": isLoading ? 'loading-overlay' : undefined, children: _jsx("span", { className: classes.dots, children: statusMessage || 'Loading' }) })] }));
49
49
  }
@@ -12,6 +12,7 @@ export interface NonBlockCanvasDisplayModel {
12
12
  statusMessage?: string;
13
13
  showLegend?: boolean;
14
14
  legendItems?: () => LegendItem[];
15
+ height: number;
15
16
  }
16
17
  declare const NonBlockCanvasDisplayComponent: ({ model, children, }: {
17
18
  model: NonBlockCanvasDisplayModel;
@@ -31,14 +31,14 @@ const NonBlockCanvasDisplayComponent = observer(function NonBlockCanvasDisplayCo
31
31
  return error ? (_jsx(BlockErrorMessage, { model: model })) : regionTooLarge ? (model.regionCannotBeRendered()) : (_jsx(DataDisplay, { model: model, children: children }));
32
32
  });
33
33
  const DataDisplay = observer(function DataDisplay({ model, children, }) {
34
- const { drawn, loading, showLegend, legendItems, lastDrawnBpPerPx } = model;
34
+ const { drawn, loading, showLegend, legendItems, lastDrawnBpPerPx, height } = model;
35
35
  const view = getContainingView(model);
36
36
  const items = legendItems?.() ?? [];
37
37
  const hasZoomed = lastDrawnBpPerPx !== undefined && lastDrawnBpPerPx !== view.bpPerPx;
38
38
  const calculatedLeft = hasZoomed
39
39
  ? 0
40
40
  : (model.lastDrawnOffsetPx ?? 0) - view.offsetPx;
41
- return (_jsxs("div", { "data-testid": `drawn-${drawn}`, children: [_jsx("div", { style: {
41
+ return (_jsxs("div", { "data-testid": `drawn-${drawn}`, style: { position: 'relative', height }, children: [_jsx("div", { style: {
42
42
  position: 'absolute',
43
43
  left: calculatedLeft,
44
44
  visibility: hasZoomed ? 'hidden' : undefined,
@@ -6,6 +6,7 @@ declare const ServerSideRenderedBlockContent: ({ model, }: {
6
6
  statusMessage?: string;
7
7
  reactElement?: React.ReactElement;
8
8
  isRenderingPending?: boolean;
9
+ displayHeight?: number;
9
10
  };
10
11
  }) => import("react/jsx-runtime").JSX.Element;
11
12
  export default ServerSideRenderedBlockContent;
@@ -12,7 +12,7 @@ const ServerSideRenderedBlockContent = observer(function ServerSideRenderedBlock
12
12
  return isValidElement(model.message) ? (model.message) : (_jsx(BlockMsg, { message: `${model.message}`, severity: "info" }));
13
13
  }
14
14
  else {
15
- return (_jsx(LoadingOverlay, { statusMessage: model.statusMessage, children: model.reactElement }));
15
+ return (_jsx(LoadingOverlay, { statusMessage: model.statusMessage, height: model.displayHeight, children: model.reactElement }));
16
16
  }
17
17
  });
18
18
  export default ServerSideRenderedBlockContent;
@@ -3,19 +3,19 @@ import type { FloatingLabelData, LayoutRecord } from '../types.ts';
3
3
  import type { Assembly } from '@jbrowse/core/assemblyManager/assembly';
4
4
  export interface FeatureLabelData {
5
5
  leftPx: number;
6
- rightPx: number;
7
6
  topPx: number;
8
7
  totalFeatureHeight: number;
9
8
  floatingLabels: FloatingLabelData[];
10
9
  featureWidth: number;
11
- totalLayoutWidth: number;
12
10
  }
11
+ interface RenderingWithLayout {
12
+ layout?: {
13
+ getRectangles?: () => Map<string, LayoutRecord>;
14
+ };
15
+ }
16
+ export declare function collectLayoutsFromRenderings(renderings: readonly (readonly [unknown, RenderingWithLayout])[]): Map<string, LayoutRecord>[];
13
17
  export declare function deduplicateFeatureLabels(layoutFeatures: {
14
18
  entries(): IterableIterator<readonly [string, LayoutRecord | undefined]>;
15
19
  }, view: LinearGenomeViewModel, assembly: Assembly | undefined, bpPerPx: number): Map<string, FeatureLabelData>;
16
- export declare function getViewportLeftEdge(offsetPx: number): number;
17
- export declare function clampToViewport(featureLeftPx: number, featureRightPx: number, offsetPx: number): {
18
- leftPx: number;
19
- rightPx: number;
20
- };
21
- export declare function calculateFloatingLabelPosition(featureLeftPx: number, featureRightPx: number, labelWidth: number, offsetPx: number, viewportLeft: number): number;
20
+ export declare function calculateFloatingLabelPosition(featureLeftPx: number, featureRightPx: number, labelWidth: number, offsetPx: number): number;
21
+ export {};
@@ -1,5 +1,14 @@
1
1
  import { clamp } from '@jbrowse/core/util';
2
- function calculateFeaturePixelPositions(view, assembly, refName, left, right, bpPerPx) {
2
+ export function collectLayoutsFromRenderings(renderings) {
3
+ const layoutMaps = [];
4
+ for (const [, rendering] of renderings) {
5
+ if (rendering.layout?.getRectangles) {
6
+ layoutMaps.push(rendering.layout.getRectangles());
7
+ }
8
+ }
9
+ return layoutMaps;
10
+ }
11
+ function calculateFeatureLeftPx(view, assembly, refName, left, right, bpPerPx) {
3
12
  const canonicalRefName = assembly?.getCanonicalRefName(refName) || refName;
4
13
  const leftBpPx = view.bpToPx({
5
14
  refName: canonicalRefName,
@@ -11,28 +20,21 @@ function calculateFeaturePixelPositions(view, assembly, refName, left, right, bp
11
20
  })?.offsetPx;
12
21
  if (leftBpPx !== undefined) {
13
22
  const rightEstimate = rightBpPx !== undefined ? rightBpPx : leftBpPx + (right - left) / bpPerPx;
14
- return {
15
- leftPx: Math.min(leftBpPx, rightEstimate),
16
- rightPx: Math.max(leftBpPx, rightEstimate),
17
- };
23
+ return Math.min(leftBpPx, rightEstimate);
18
24
  }
19
25
  else if (rightBpPx !== undefined) {
20
26
  const leftEstimate = rightBpPx - (right - left) / bpPerPx;
21
- return {
22
- leftPx: Math.min(leftEstimate, rightBpPx),
23
- rightPx: Math.max(leftEstimate, rightBpPx),
24
- };
27
+ return Math.min(leftEstimate, rightBpPx);
25
28
  }
26
29
  return undefined;
27
30
  }
28
- function calculateMultiRegionPositions(view, assembly, refName, left, right) {
31
+ function calculateMultiRegionLeftPx(view, assembly, refName, left, right) {
29
32
  const canonicalRefName = assembly?.getCanonicalRefName(refName) || refName;
30
33
  const visibleRegions = view.displayedRegions.filter(r => r.refName === canonicalRefName && r.start < right && r.end > left);
31
34
  if (visibleRegions.length === 0) {
32
35
  return undefined;
33
36
  }
34
37
  let minLeftPx = Infinity;
35
- let maxRightPx = -Infinity;
36
38
  for (const region of visibleRegions) {
37
39
  const regionStart = Math.max(left, region.start);
38
40
  const regionEnd = Math.min(right, region.end);
@@ -46,16 +48,16 @@ function calculateMultiRegionPositions(view, assembly, refName, left, right) {
46
48
  })?.offsetPx;
47
49
  if (startPx !== undefined && endPx !== undefined) {
48
50
  minLeftPx = Math.min(minLeftPx, startPx, endPx);
49
- maxRightPx = Math.max(maxRightPx, startPx, endPx);
50
51
  }
51
52
  }
52
- if (minLeftPx === Infinity || maxRightPx === -Infinity) {
53
+ if (minLeftPx === Infinity) {
53
54
  return undefined;
54
55
  }
55
- return { leftPx: minLeftPx, rightPx: maxRightPx };
56
+ return minLeftPx;
56
57
  }
57
- function getFeaturePositions(view, assembly, refName, left, right, bpPerPx) {
58
- return (calculateFeaturePixelPositions(view, assembly, refName, left, right, bpPerPx) || calculateMultiRegionPositions(view, assembly, refName, left, right));
58
+ function getFeatureLeftPx(view, assembly, refName, left, right, bpPerPx) {
59
+ return (calculateFeatureLeftPx(view, assembly, refName, left, right, bpPerPx) ??
60
+ calculateMultiRegionLeftPx(view, assembly, refName, left, right));
59
61
  }
60
62
  export function deduplicateFeatureLabels(layoutFeatures, view, assembly, bpPerPx) {
61
63
  const featureLabels = new Map();
@@ -64,51 +66,39 @@ export function deduplicateFeatureLabels(layoutFeatures, view, assembly, bpPerPx
64
66
  continue;
65
67
  }
66
68
  const [, topPx, , , feature] = val;
67
- const { refName, floatingLabels, totalFeatureHeight, actualTopPx, featureWidth, totalLayoutWidth, featureStartBp, featureEndBp, } = feature;
69
+ const { refName, floatingLabels, totalFeatureHeight, actualTopPx, featureWidth, featureStartBp, featureEndBp, } = feature;
68
70
  const effectiveTopPx = actualTopPx ?? topPx;
69
71
  if (!floatingLabels ||
70
72
  floatingLabels.length === 0 ||
71
73
  !totalFeatureHeight ||
72
74
  featureWidth === undefined ||
73
- totalLayoutWidth === undefined ||
74
75
  featureStartBp === undefined ||
75
76
  featureEndBp === undefined) {
76
77
  continue;
77
78
  }
78
- const positions = getFeaturePositions(view, assembly, refName, featureStartBp, featureEndBp, bpPerPx);
79
- if (!positions) {
79
+ const leftPx = getFeatureLeftPx(view, assembly, refName, featureStartBp, featureEndBp, bpPerPx);
80
+ if (leftPx === undefined) {
80
81
  continue;
81
82
  }
82
83
  const existing = featureLabels.get(key);
83
- if (!existing || positions.leftPx < existing.leftPx) {
84
+ if (!existing || leftPx < existing.leftPx) {
84
85
  featureLabels.set(key, {
85
- leftPx: positions.leftPx,
86
- rightPx: positions.rightPx,
86
+ leftPx,
87
87
  topPx: effectiveTopPx,
88
88
  totalFeatureHeight,
89
89
  floatingLabels,
90
90
  featureWidth,
91
- totalLayoutWidth,
92
91
  });
93
92
  }
94
93
  }
95
94
  return featureLabels;
96
95
  }
97
- export function getViewportLeftEdge(offsetPx) {
98
- return Math.max(0, offsetPx);
99
- }
100
- export function clampToViewport(featureLeftPx, featureRightPx, offsetPx) {
101
- const viewportLeft = getViewportLeftEdge(offsetPx);
102
- return {
103
- leftPx: Math.max(featureLeftPx, viewportLeft),
104
- rightPx: Math.max(featureRightPx, viewportLeft),
105
- };
106
- }
107
- export function calculateFloatingLabelPosition(featureLeftPx, featureRightPx, labelWidth, offsetPx, viewportLeft) {
96
+ export function calculateFloatingLabelPosition(featureLeftPx, featureRightPx, labelWidth, offsetPx) {
108
97
  const featureWidth = featureRightPx - featureLeftPx;
109
98
  if (labelWidth > featureWidth) {
110
99
  return featureLeftPx - offsetPx;
111
100
  }
101
+ const viewportLeft = Math.max(0, offsetPx);
112
102
  const leftPx = Math.max(featureLeftPx, viewportLeft);
113
103
  const naturalX = leftPx - offsetPx;
114
104
  const maxX = featureRightPx - offsetPx - labelWidth;
@@ -41,6 +41,7 @@ export declare const BaseLinearDisplay: import("@jbrowse/mobx-state-tree").IMode
41
41
  statusMessage?: string;
42
42
  reactElement?: React.ReactElement;
43
43
  isRenderingPending?: boolean;
44
+ displayHeight?: number;
44
45
  };
45
46
  }) => import("react/jsx-runtime").JSX.Element;
46
47
  renderProps: any;
@@ -59,10 +60,11 @@ export declare const BaseLinearDisplay: import("@jbrowse/mobx-state-tree").IMode
59
60
  beforeDestroy(): void;
60
61
  } & {
61
62
  readonly statusMessage: any;
63
+ readonly displayHeight: number | undefined;
62
64
  } & {
63
65
  afterAttach(): void;
64
66
  }, import("@jbrowse/mobx-state-tree")._NotCustomized, import("@jbrowse/mobx-state-tree")._NotCustomized>>;
65
- configuration: import("node_modules/@jbrowse/core/src/configuration/configurationSchema.ts").ConfigurationSchemaType<{
67
+ configuration: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
66
68
  maxFeatureScreenDensity: {
67
69
  type: string;
68
70
  description: string;
@@ -89,7 +91,7 @@ export declare const BaseLinearDisplay: import("@jbrowse/mobx-state-tree").IMode
89
91
  description: string;
90
92
  defaultValue: never[];
91
93
  };
92
- }, import("node_modules/@jbrowse/core/src/configuration/configurationSchema.ts").ConfigurationSchemaOptions<undefined, "displayId">>;
94
+ }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "displayId">>;
93
95
  showLegend: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>>;
94
96
  showTooltips: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>>;
95
97
  }, {
@@ -380,6 +382,7 @@ export declare const BaseLinearDisplay: import("@jbrowse/mobx-state-tree").IMode
380
382
  statusMessage?: string;
381
383
  reactElement?: React.ReactElement;
382
384
  isRenderingPending?: boolean;
385
+ displayHeight?: number;
383
386
  };
384
387
  }) => import("react/jsx-runtime").JSX.Element;
385
388
  renderProps: any;
@@ -398,6 +401,7 @@ export declare const BaseLinearDisplay: import("@jbrowse/mobx-state-tree").IMode
398
401
  beforeDestroy(): void;
399
402
  } & {
400
403
  readonly statusMessage: any;
404
+ readonly displayHeight: number | undefined;
401
405
  } & {
402
406
  afterAttach(): void;
403
407
  }, import("@jbrowse/mobx-state-tree")._NotCustomized, import("@jbrowse/mobx-state-tree")._NotCustomized>> & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("@jbrowse/mobx-state-tree").IMapType<import("@jbrowse/mobx-state-tree").IModelType<{
@@ -424,6 +428,7 @@ export declare const BaseLinearDisplay: import("@jbrowse/mobx-state-tree").IMode
424
428
  statusMessage?: string;
425
429
  reactElement?: React.ReactElement;
426
430
  isRenderingPending?: boolean;
431
+ displayHeight?: number;
427
432
  };
428
433
  }) => import("react/jsx-runtime").JSX.Element;
429
434
  renderProps: any;
@@ -442,6 +447,7 @@ export declare const BaseLinearDisplay: import("@jbrowse/mobx-state-tree").IMode
442
447
  beforeDestroy(): void;
443
448
  } & {
444
449
  readonly statusMessage: any;
450
+ readonly displayHeight: number | undefined;
445
451
  } & {
446
452
  afterAttach(): void;
447
453
  }, import("@jbrowse/mobx-state-tree")._NotCustomized, import("@jbrowse/mobx-state-tree")._NotCustomized>>>;
@@ -455,7 +461,7 @@ export declare const BaseLinearDisplay: import("@jbrowse/mobx-state-tree").IMode
455
461
  [x: string]: any;
456
462
  } & import("@jbrowse/mobx-state-tree/dist/internal").NonEmptyObject & any & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>);
457
463
  } & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>);
458
- } & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("node_modules/@jbrowse/core/src/configuration/configurationSchema.ts").ConfigurationSchemaType<{
464
+ } & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
459
465
  maxFeatureScreenDensity: {
460
466
  type: string;
461
467
  description: string;
@@ -482,7 +488,7 @@ export declare const BaseLinearDisplay: import("@jbrowse/mobx-state-tree").IMode
482
488
  description: string;
483
489
  defaultValue: never[];
484
490
  };
485
- }, import("node_modules/@jbrowse/core/src/configuration/configurationSchema.ts").ConfigurationSchemaOptions<undefined, "displayId">>>;
491
+ }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "displayId">>>;
486
492
  showLegend: boolean | undefined;
487
493
  showTooltips: boolean | undefined;
488
494
  } & import("@jbrowse/mobx-state-tree/dist/internal").NonEmptyObject & {
@@ -772,6 +778,7 @@ export declare const BaseLinearDisplay: import("@jbrowse/mobx-state-tree").IMode
772
778
  statusMessage?: string;
773
779
  reactElement?: React.ReactElement;
774
780
  isRenderingPending?: boolean;
781
+ displayHeight?: number;
775
782
  };
776
783
  }) => import("react/jsx-runtime").JSX.Element;
777
784
  renderProps: any;
@@ -790,10 +797,11 @@ export declare const BaseLinearDisplay: import("@jbrowse/mobx-state-tree").IMode
790
797
  beforeDestroy(): void;
791
798
  } & {
792
799
  readonly statusMessage: any;
800
+ readonly displayHeight: number | undefined;
793
801
  } & {
794
802
  afterAttach(): void;
795
803
  }, import("@jbrowse/mobx-state-tree")._NotCustomized, import("@jbrowse/mobx-state-tree")._NotCustomized>>;
796
- configuration: import("node_modules/@jbrowse/core/src/configuration/configurationSchema.ts").ConfigurationSchemaType<{
804
+ configuration: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
797
805
  maxFeatureScreenDensity: {
798
806
  type: string;
799
807
  description: string;
@@ -820,7 +828,7 @@ export declare const BaseLinearDisplay: import("@jbrowse/mobx-state-tree").IMode
820
828
  description: string;
821
829
  defaultValue: never[];
822
830
  };
823
- }, import("node_modules/@jbrowse/core/src/configuration/configurationSchema.ts").ConfigurationSchemaOptions<undefined, "displayId">>;
831
+ }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "displayId">>;
824
832
  showLegend: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>>;
825
833
  showTooltips: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>>;
826
834
  }, {
@@ -1119,6 +1127,7 @@ export declare const BaseLinearDisplay: import("@jbrowse/mobx-state-tree").IMode
1119
1127
  statusMessage?: string;
1120
1128
  reactElement?: React.ReactElement;
1121
1129
  isRenderingPending?: boolean;
1130
+ displayHeight?: number;
1122
1131
  };
1123
1132
  }) => import("react/jsx-runtime").JSX.Element;
1124
1133
  renderProps: any;
@@ -1137,10 +1146,11 @@ export declare const BaseLinearDisplay: import("@jbrowse/mobx-state-tree").IMode
1137
1146
  beforeDestroy(): void;
1138
1147
  } & {
1139
1148
  readonly statusMessage: any;
1149
+ readonly displayHeight: number | undefined;
1140
1150
  } & {
1141
1151
  afterAttach(): void;
1142
1152
  }, import("@jbrowse/mobx-state-tree")._NotCustomized, import("@jbrowse/mobx-state-tree")._NotCustomized>>;
1143
- configuration: import("node_modules/@jbrowse/core/src/configuration/configurationSchema.ts").ConfigurationSchemaType<{
1153
+ configuration: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
1144
1154
  maxFeatureScreenDensity: {
1145
1155
  type: string;
1146
1156
  description: string;
@@ -1167,12 +1177,12 @@ export declare const BaseLinearDisplay: import("@jbrowse/mobx-state-tree").IMode
1167
1177
  description: string;
1168
1178
  defaultValue: never[];
1169
1179
  };
1170
- }, import("node_modules/@jbrowse/core/src/configuration/configurationSchema.ts").ConfigurationSchemaOptions<undefined, "displayId">>;
1180
+ }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "displayId">>;
1171
1181
  showLegend: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>>;
1172
1182
  showTooltips: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>>;
1173
1183
  }>>, {
1174
- id: string;
1175
1184
  type: string;
1185
+ id: string;
1176
1186
  configuration: import("@jbrowse/mobx-state-tree").ModelSnapshotType<Record<string, any>>;
1177
1187
  rpcDriverName: string | undefined;
1178
1188
  heightPreConfig: number | undefined;
@@ -0,0 +1,8 @@
1
+ import { type FeatureLabelData } from '../components/util.ts';
2
+ interface Props {
3
+ featureLabels: Map<string, FeatureLabelData>;
4
+ offsetPx: number;
5
+ viewWidth: number;
6
+ }
7
+ export declare function SvgFloatingLabels({ featureLabels, offsetPx, viewWidth, }: Props): import("react/jsx-runtime").JSX.Element;
8
+ export {};
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { calculateFloatingLabelPosition, } from "../components/util.js";
3
+ export function SvgFloatingLabels({ featureLabels, offsetPx, viewWidth, }) {
4
+ const elements = [];
5
+ for (const [key, { leftPx, topPx, totalFeatureHeight, floatingLabels, featureWidth },] of featureLabels.entries()) {
6
+ const featureVisualBottom = topPx + totalFeatureHeight;
7
+ const featureRightPx = leftPx + featureWidth;
8
+ for (const [i, { text, relativeY, color, textWidth, isOverlay },] of floatingLabels.entries()) {
9
+ const y = featureVisualBottom + relativeY;
10
+ const x = calculateFloatingLabelPosition(leftPx, featureRightPx, textWidth, offsetPx);
11
+ if (x < 0 || x > viewWidth) {
12
+ continue;
13
+ }
14
+ const fontSize = 11;
15
+ elements.push(_jsxs("g", { transform: `translate(${x}, ${y})`, children: [isOverlay ? (_jsx("rect", { x: -1, y: 0, width: textWidth + 2, height: fontSize + 1, fill: "rgba(255, 255, 255, 0.8)" })) : null, _jsx("text", { x: 0, y: fontSize, fontSize: fontSize, fill: color, style: { pointerEvents: 'none' }, children: text })] }, `${key}-${i}`));
16
+ }
17
+ }
18
+ return _jsx(_Fragment, { children: elements });
19
+ }
@@ -1,4 +1,4 @@
1
- declare const baseLinearDisplayConfigSchema: import("node_modules/@jbrowse/core/src/configuration/configurationSchema").ConfigurationSchemaType<{
1
+ declare const baseLinearDisplayConfigSchema: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
2
2
  maxFeatureScreenDensity: {
3
3
  type: string;
4
4
  description: string;
@@ -25,5 +25,5 @@ declare const baseLinearDisplayConfigSchema: import("node_modules/@jbrowse/core/
25
25
  description: string;
26
26
  defaultValue: never[];
27
27
  };
28
- }, import("node_modules/@jbrowse/core/src/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "displayId">>;
28
+ }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "displayId">>;
29
29
  export default baseLinearDisplayConfigSchema;
@@ -35,6 +35,7 @@ declare const blockState: import("@jbrowse/mobx-state-tree").IModelType<{
35
35
  statusMessage?: string;
36
36
  reactElement?: React.ReactElement;
37
37
  isRenderingPending?: boolean;
38
+ displayHeight?: number;
38
39
  };
39
40
  }) => import("react/jsx-runtime").JSX.Element;
40
41
  renderProps: any;
@@ -53,6 +54,7 @@ declare const blockState: import("@jbrowse/mobx-state-tree").IModelType<{
53
54
  beforeDestroy(): void;
54
55
  } & {
55
56
  readonly statusMessage: any;
57
+ readonly displayHeight: number | undefined;
56
58
  } & {
57
59
  afterAttach(): void;
58
60
  }, import("@jbrowse/mobx-state-tree")._NotCustomized, import("@jbrowse/mobx-state-tree")._NotCustomized>;
@@ -132,6 +132,9 @@ const blockState = types
132
132
  'Loading'
133
133
  : undefined;
134
134
  },
135
+ get displayHeight() {
136
+ return self.cachedDisplay?.height;
137
+ },
135
138
  }))
136
139
  .actions(self => ({
137
140
  afterAttach() {
@@ -1,18 +1,5 @@
1
1
  import type { AnyConfigurationModel } from '@jbrowse/core/configuration';
2
2
  import type { FeatureDensityStats } from '@jbrowse/core/data_adapters/BaseAdapter';
3
- export interface RenderProps {
4
- rendererType: any;
5
- renderArgs: Record<string, any>;
6
- renderProps: Record<string, any>;
7
- displayError: unknown;
8
- rpcManager: {
9
- call: (...args: unknown[]) => void;
10
- };
11
- cannotBeRenderedReason: string;
12
- }
13
- export interface ErrorProps {
14
- displayError: string;
15
- }
16
3
  export declare function getDisplayStr(totalBytes: number): string;
17
4
  export declare function getId(id: string, index: string | number): string;
18
5
  export declare function getFeatureDensityStatsPre(self: {
@@ -2,11 +2,13 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
2
2
  import { Fragment } from 'react';
3
3
  import { createJBrowseTheme } from '@jbrowse/core/ui';
4
4
  import { ReactRendering, getContainingView, getSession, } from '@jbrowse/core/util';
5
+ import CompositeMap from '@jbrowse/core/util/compositeMap';
5
6
  import SVGLegend from "./SVGLegend.js";
7
+ import { collectLayoutsFromRenderings, deduplicateFeatureLabels, } from "./components/util.js";
8
+ import { SvgFloatingLabels } from "./models/SvgFloatingLabels.js";
6
9
  import BlockState, { renderBlockData, } from "./models/serverSideRenderedBlock.js";
7
10
  import { getId } from "./models/util.js";
8
11
  import { ErrorBox } from "../LinearGenomeView/SVGErrorBox.js";
9
- import { calculateLabelPositions } from "./models/calculateLabelPositions.js";
10
12
  export async function renderBaseLinearDisplaySvg(self, opts) {
11
13
  const { height, id } = self;
12
14
  const { overrideHeight } = opts;
@@ -42,11 +44,13 @@ export async function renderBaseLinearDisplaySvg(self, opts) {
42
44
  }),
43
45
  ];
44
46
  }));
47
+ const layoutMaps = collectLayoutsFromRenderings(renderings);
48
+ const layoutFeatures = new CompositeMap(layoutMaps);
45
49
  const { assemblyManager } = getSession(self);
46
- const { offsetPx } = view;
50
+ const { offsetPx, bpPerPx } = view;
47
51
  const assemblyName = view.assemblyNames[0];
48
52
  const assembly = assemblyName ? assemblyManager.get(assemblyName) : undefined;
49
- const labelData = calculateLabelPositions(self, view, assembly, offsetPx);
53
+ const featureLabels = deduplicateFeatureLabels(layoutFeatures, view, assembly, bpPerPx);
50
54
  const labelsClipId = getId(id, 'labels');
51
55
  const theme = createJBrowseTheme(opts.theme);
52
56
  const legendItems = self.showLegend ? self.legendItems(theme) : [];
@@ -55,5 +59,5 @@ export async function renderBaseLinearDisplaySvg(self, opts) {
55
59
  const offset = offsetPx - viewOffsetPx;
56
60
  const clipid = getId(id, index);
57
61
  return (_jsxs(Fragment, { children: [_jsx("defs", { children: _jsx("clipPath", { id: clipid, children: _jsx("rect", { x: 0, y: 0, width: widthPx, height: overrideHeight || height }) }) }), _jsx("g", { transform: `translate(${offset} 0)`, children: _jsx("g", { clipPath: `url(#${clipid})`, children: _jsx(ReactRendering, { rendering: rendering }) }) })] }, `frag-${index}`));
58
- }), _jsx("defs", { children: _jsx("clipPath", { id: labelsClipId, children: _jsx("rect", { x: 0, y: 0, width: width, height: overrideHeight || height }) }) }), _jsx("g", { clipPath: `url(#${labelsClipId})`, children: labelData.map(({ key, label, description, leftPos, topPos }) => (_jsxs("g", { transform: `translate(${leftPos}, ${topPos})`, children: [_jsx("text", { x: 0, y: 11, fontSize: 11, fill: "currentColor", children: label }), description ? (_jsx("text", { x: 0, y: 25, fontSize: 11, fill: "blue", children: description })) : null] }, `label-${key}`))) }), legendItems.length > 0 ? (_jsx(SVGLegend, { items: legendItems, width: width, legendAreaWidth: opts.legendWidth })) : null] }));
62
+ }), _jsx("defs", { children: _jsx("clipPath", { id: labelsClipId, children: _jsx("rect", { x: 0, y: 0, width: width, height: overrideHeight || height }) }) }), _jsx("g", { clipPath: `url(#${labelsClipId})`, children: _jsx(SvgFloatingLabels, { featureLabels: featureLabels, offsetPx: offsetPx, viewWidth: width }) }), legendItems.length > 0 ? (_jsx(SVGLegend, { items: legendItems, width: width, legendAreaWidth: opts.legendWidth })) : null] }));
59
63
  }
@@ -18,12 +18,9 @@ export interface FloatingLabelData {
18
18
  tooltip?: string;
19
19
  }
20
20
  export interface LayoutFeatureMetadata {
21
- label?: string;
22
- description?: string;
23
21
  refName: string;
24
22
  floatingLabels?: FloatingLabelData[];
25
23
  totalFeatureHeight?: number;
26
- totalLayoutWidth?: number;
27
24
  featureWidth?: number;
28
25
  actualTopPx?: number;
29
26
  featureStartBp?: number;
@@ -33,7 +30,6 @@ export declare function createSubfeatureLabelMetadata(args: {
33
30
  refName: string;
34
31
  floatingLabels: FloatingLabelData[];
35
32
  totalFeatureHeight: number;
36
- totalLayoutWidth: number;
37
33
  featureWidth: number;
38
34
  actualTopPx: number;
39
35
  featureStartBp: number;
@@ -1,5 +1,5 @@
1
1
  import type PluginManager from '@jbrowse/core/PluginManager';
2
- declare const configSchema: (pluginManager: PluginManager) => import("node_modules/@jbrowse/core/src/configuration/configurationSchema").ConfigurationSchemaType<{}, import("node_modules/@jbrowse/core/src/configuration/configurationSchema").ConfigurationSchemaOptions<import("node_modules/@jbrowse/core/src/configuration/configurationSchema").ConfigurationSchemaType<{
2
+ declare const configSchema: (pluginManager: PluginManager) => import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
3
3
  name: {
4
4
  description: string;
5
5
  type: string;
@@ -31,7 +31,7 @@ declare const configSchema: (pluginManager: PluginManager) => import("node_modul
31
31
  defaultValue: string;
32
32
  };
33
33
  adapter: import("@jbrowse/mobx-state-tree").IAnyModelType;
34
- textSearching: import("node_modules/@jbrowse/core/src/configuration/configurationSchema").ConfigurationSchemaType<{
34
+ textSearching: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
35
35
  indexingAttributes: {
36
36
  type: string;
37
37
  description: string;
@@ -43,9 +43,9 @@ declare const configSchema: (pluginManager: PluginManager) => import("node_modul
43
43
  defaultValue: string[];
44
44
  };
45
45
  textSearchAdapter: import("@jbrowse/mobx-state-tree").IAnyModelType;
46
- }, import("node_modules/@jbrowse/core/src/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined>>;
46
+ }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined>>;
47
47
  displays: import("@jbrowse/mobx-state-tree").IArrayType<import("@jbrowse/mobx-state-tree").IAnyModelType>;
48
- formatDetails: import("node_modules/@jbrowse/core/src/configuration/configurationSchema").ConfigurationSchemaType<{
48
+ formatDetails: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
49
49
  feature: {
50
50
  type: string;
51
51
  description: string;
@@ -68,8 +68,8 @@ declare const configSchema: (pluginManager: PluginManager) => import("node_modul
68
68
  defaultValue: number;
69
69
  description: string;
70
70
  };
71
- }, import("node_modules/@jbrowse/core/src/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined>>;
72
- formatAbout: import("node_modules/@jbrowse/core/src/configuration/configurationSchema").ConfigurationSchemaType<{
71
+ }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined>>;
72
+ formatAbout: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
73
73
  config: {
74
74
  type: string;
75
75
  description: string;
@@ -80,6 +80,6 @@ declare const configSchema: (pluginManager: PluginManager) => import("node_modul
80
80
  type: string;
81
81
  defaultValue: boolean;
82
82
  };
83
- }, import("node_modules/@jbrowse/core/src/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined>>;
84
- }, import("node_modules/@jbrowse/core/src/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "trackId">>, "trackId">>;
83
+ }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined>>;
84
+ }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "trackId">>, "trackId">>;
85
85
  export default configSchema;