@jbrowse/plugin-linear-comparative-view 2.16.0 → 2.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/LGVSyntenyDisplay/components/LaunchSyntenyViewDialog.d.ts +2 -1
  2. package/dist/LGVSyntenyDisplay/components/LaunchSyntenyViewDialog.js +4 -2
  3. package/dist/LGVSyntenyDisplay/components/util.d.ts +4 -1
  4. package/dist/LGVSyntenyDisplay/components/util.js +7 -15
  5. package/dist/LGVSyntenyDisplay/model.d.ts +26 -14
  6. package/dist/LGVSyntenyDisplay/model.js +23 -1
  7. package/dist/LinearComparativeDisplay/stateModelFactory.d.ts +28 -5
  8. package/dist/LinearComparativeDisplay/stateModelFactory.js +14 -3
  9. package/dist/LinearSyntenyDisplay/afterAttach.js +2 -3
  10. package/dist/LinearSyntenyDisplay/components/LinearSyntenyRendering.js +22 -15
  11. package/dist/LinearSyntenyDisplay/components/SyntenyContextMenu.js +2 -4
  12. package/dist/LinearSyntenyDisplay/components/util.d.ts +5 -1
  13. package/dist/LinearSyntenyDisplay/components/util.js +7 -9
  14. package/dist/LinearSyntenyDisplay/drawSynteny.js +7 -9
  15. package/dist/LinearSyntenyDisplay/model.d.ts +48 -11
  16. package/dist/LinearSyntenyDisplay/model.js +38 -22
  17. package/dist/SyntenyFeatureDetail/SyntenyFeatureDetail.d.ts +14 -0
  18. package/dist/SyntenyFeatureDetail/SyntenyFeatureDetail.js +100 -0
  19. package/dist/SyntenyFeatureDetail/index.d.ts +2 -0
  20. package/dist/SyntenyFeatureDetail/index.js +56 -0
  21. package/dist/index.js +2 -0
  22. package/esm/LGVSyntenyDisplay/components/LaunchSyntenyViewDialog.d.ts +2 -1
  23. package/esm/LGVSyntenyDisplay/components/LaunchSyntenyViewDialog.js +4 -2
  24. package/esm/LGVSyntenyDisplay/components/util.d.ts +4 -1
  25. package/esm/LGVSyntenyDisplay/components/util.js +8 -16
  26. package/esm/LGVSyntenyDisplay/model.d.ts +26 -14
  27. package/esm/LGVSyntenyDisplay/model.js +25 -3
  28. package/esm/LinearComparativeDisplay/stateModelFactory.d.ts +28 -5
  29. package/esm/LinearComparativeDisplay/stateModelFactory.js +14 -3
  30. package/esm/LinearSyntenyDisplay/afterAttach.js +3 -4
  31. package/esm/LinearSyntenyDisplay/components/LinearSyntenyRendering.js +22 -15
  32. package/esm/LinearSyntenyDisplay/components/SyntenyContextMenu.js +2 -4
  33. package/esm/LinearSyntenyDisplay/components/util.d.ts +5 -1
  34. package/esm/LinearSyntenyDisplay/components/util.js +7 -9
  35. package/esm/LinearSyntenyDisplay/drawSynteny.js +7 -9
  36. package/esm/LinearSyntenyDisplay/model.d.ts +48 -11
  37. package/esm/LinearSyntenyDisplay/model.js +39 -23
  38. package/esm/SyntenyFeatureDetail/SyntenyFeatureDetail.d.ts +14 -0
  39. package/esm/SyntenyFeatureDetail/SyntenyFeatureDetail.js +72 -0
  40. package/esm/SyntenyFeatureDetail/index.d.ts +2 -0
  41. package/esm/SyntenyFeatureDetail/index.js +27 -0
  42. package/esm/index.js +2 -0
  43. package/package.json +3 -3
@@ -1,4 +1,5 @@
1
1
  import { AnyConfigurationSchemaType } from '@jbrowse/core/configuration';
2
+ import { Feature } from '@jbrowse/core/util';
2
3
  /**
3
4
  * #stateModel LGVSyntenyDisplay
4
5
  * displays location of "synteny" feature in a plain LGV, allowing linking out
@@ -10,7 +11,14 @@ import { AnyConfigurationSchemaType } from '@jbrowse/core/configuration';
10
11
  declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("mobx-state-tree").IModelType<{
11
12
  id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
12
13
  type: import("mobx-state-tree").ISimpleType<string>;
13
- rpcDriverName: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
14
+ rpcDriverName: import("mobx-state-tree" /**
15
+ * #stateModel LGVSyntenyDisplay
16
+ * displays location of "synteny" feature in a plain LGV, allowing linking out
17
+ * to external synteny views
18
+ *
19
+ * extends
20
+ * - [SharedLinearPileupDisplayMixin](../sharedlinearpileupdisplaymixin)
21
+ */).IMaybe<import("mobx-state-tree").ISimpleType<string>>;
14
22
  } & {
15
23
  heightPreConfig: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<number>>;
16
24
  } & {
@@ -38,7 +46,7 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
38
46
  renderInProgress: AbortController | undefined;
39
47
  filled: boolean;
40
48
  reactElement: React.ReactElement | undefined;
41
- features: Map<string, import("@jbrowse/core/util").Feature> | undefined;
49
+ features: Map<string, Feature> | undefined;
42
50
  layout: any;
43
51
  status: string;
44
52
  error: unknown;
@@ -63,7 +71,7 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
63
71
  setMessage(messageText: string): void;
64
72
  setRendered(props: {
65
73
  reactElement: React.ReactElement;
66
- features: Map<string, import("@jbrowse/core/util").Feature>;
74
+ features: Map<string, Feature>;
67
75
  layout: any;
68
76
  maxHeightReached: boolean;
69
77
  renderProps: any;
@@ -223,7 +231,7 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
223
231
  regionCannotBeRendered(_region: import("@jbrowse/core/util").Region): import("react").JSX.Element | null;
224
232
  } & {
225
233
  featureIdUnderMouse: undefined | string;
226
- contextMenuFeature: undefined | import("@jbrowse/core/util").Feature;
234
+ contextMenuFeature: undefined | Feature;
227
235
  } & {
228
236
  readonly DisplayMessageComponent: import("react").FC<any> | undefined;
229
237
  readonly blockType: "dynamicBlocks" | "staticBlocks";
@@ -233,19 +241,19 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
233
241
  readonly TooltipComponent: import("@jbrowse/core/util").AnyReactComponentType;
234
242
  readonly selectedFeatureId: string | undefined;
235
243
  } & {
236
- readonly features: import("@jbrowse/core/util/compositeMap").default<string, import("@jbrowse/core/util").Feature>;
237
- readonly featureUnderMouse: import("@jbrowse/core/util").Feature | undefined;
244
+ readonly features: import("@jbrowse/core/util/compositeMap").default<string, Feature>;
245
+ readonly featureUnderMouse: Feature | undefined;
238
246
  getFeatureOverlapping(blockKey: string, x: number, y: number): string | undefined;
239
247
  getFeatureByID(blockKey: string, id: string): [number, number, number, number] | undefined;
240
248
  searchFeatureByID(id: string): [number, number, number, number] | undefined;
241
249
  } & {
242
250
  addBlock(key: string, block: import("@jbrowse/core/util/blockTypes").BaseBlock): void;
243
251
  deleteBlock(key: string): void;
244
- selectFeature(feature: import("@jbrowse/core/util").Feature): void;
245
- navToFeature(feature: import("@jbrowse/core/util").Feature): void;
252
+ selectFeature(feature: Feature): void;
253
+ navToFeature(feature: Feature): void;
246
254
  clearFeatureSelection(): void;
247
255
  setFeatureIdUnderMouse(feature?: string): void;
248
- setContextMenuFeature(feature?: import("@jbrowse/core/util").Feature): void;
256
+ setContextMenuFeature(feature?: Feature): void;
249
257
  } & {
250
258
  reload(): Promise<void>;
251
259
  } & {
@@ -257,7 +265,7 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
257
265
  afterAttach(): void;
258
266
  } & {
259
267
  colorTagMap: import("mobx").ObservableMap<string, string>;
260
- featureUnderMouseVolatile: undefined | import("@jbrowse/core/util").Feature;
268
+ featureUnderMouseVolatile: undefined | Feature;
261
269
  tagsReady: boolean;
262
270
  } & {
263
271
  readonly autorunReady: boolean;
@@ -272,9 +280,9 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
272
280
  extra?: import("@jbrowse/plugin-alignments/src/shared/color").ExtraColorBy;
273
281
  }): void;
274
282
  updateColorTagMap(uniqueTag: string[]): void;
275
- setFeatureUnderMouse(feat?: import("@jbrowse/core/util").Feature): void;
276
- selectFeature(feature: import("@jbrowse/core/util").Feature): void;
277
- copyFeatureToClipboard(feature: import("@jbrowse/core/util").Feature): void;
283
+ setFeatureUnderMouse(feat?: Feature): void;
284
+ selectFeature(feature: Feature): void;
285
+ copyFeatureToClipboard(feature: Feature): void;
278
286
  setConfig(conf: import("@jbrowse/core/configuration").AnyConfigurationModel): void;
279
287
  setFilterBy(filter: import("@jbrowse/plugin-alignments/src/shared").IFilter): void;
280
288
  setJexlFilters(filters: string[]): void;
@@ -293,7 +301,7 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
293
301
  } & {
294
302
  readonly maxHeight: any;
295
303
  readonly featureHeightSetting: any;
296
- readonly featureUnderMouse: import("@jbrowse/core/util").Feature | undefined;
304
+ readonly featureUnderMouse: Feature | undefined;
297
305
  renderReady(): boolean;
298
306
  readonly filters: import("@jbrowse/core/pluggableElementTypes/renderers/util/serializableFilterChain").default;
299
307
  } & {
@@ -352,6 +360,10 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
352
360
  }[];
353
361
  })[];
354
362
  } & {
363
+ /**
364
+ * #action
365
+ */
366
+ selectFeature(feature: Feature): void;
355
367
  afterCreate(): void;
356
368
  }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;
357
369
  export default stateModelFactory;
@@ -1,6 +1,6 @@
1
1
  import { lazy } from 'react';
2
- import { ConfigurationReference, } from '@jbrowse/core/configuration';
3
- import { getSession } from '@jbrowse/core/util';
2
+ import { ConfigurationReference, getConf, } from '@jbrowse/core/configuration';
3
+ import { getContainingTrack, getContainingView, getSession, isSessionModelWithWidgets, } from '@jbrowse/core/util';
4
4
  import { SharedLinearPileupDisplayMixin } from '@jbrowse/plugin-alignments';
5
5
  import { types } from 'mobx-state-tree';
6
6
  const LaunchSyntenyViewDialog = lazy(() => import('./components/LaunchSyntenyViewDialog'));
@@ -37,12 +37,13 @@ function stateModelFactory(schema) {
37
37
  ...(feature
38
38
  ? [
39
39
  {
40
- label: 'Open synteny view for this position',
40
+ label: 'Launch synteny view for this position',
41
41
  onClick: () => {
42
42
  getSession(self).queueDialog(handleClose => [
43
43
  LaunchSyntenyViewDialog,
44
44
  {
45
45
  model: self,
46
+ trackId: getConf(getContainingTrack(self), 'trackId'),
46
47
  handleClose,
47
48
  feature,
48
49
  },
@@ -73,6 +74,27 @@ function stateModelFactory(schema) {
73
74
  };
74
75
  })
75
76
  .actions(self => ({
77
+ /**
78
+ * #action
79
+ */
80
+ selectFeature(feature) {
81
+ const session = getSession(self);
82
+ if (isSessionModelWithWidgets(session)) {
83
+ const r2 = getContainingView(self);
84
+ let r3 = r2;
85
+ try {
86
+ r3 = getContainingView(r3);
87
+ }
88
+ catch (e) { }
89
+ const featureWidget = session.addWidget('SyntenyFeatureWidget', 'syntenyFeature', {
90
+ featureData: feature.toJSON(),
91
+ view: r3,
92
+ track: getContainingTrack(self),
93
+ });
94
+ session.showWidget(featureWidget);
95
+ }
96
+ session.setSelection(feature);
97
+ },
76
98
  afterCreate() {
77
99
  // use color by stand to help indicate inversions better on first load,
78
100
  // otherwise use selected orientation
@@ -43,7 +43,10 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
43
43
  message: string | undefined;
44
44
  }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
45
45
  onHorizontalScroll?: () => void;
46
- blockState?: Record<string, any>;
46
+ blockState? /**
47
+ * #action
48
+ * controlled by a reaction
49
+ */: Record<string, any>;
47
50
  }>;
48
51
  readonly DisplayBlurb: React.FC<{
49
52
  model: {
@@ -55,7 +58,10 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
55
58
  error: unknown;
56
59
  message: string | undefined;
57
60
  } & import("mobx-state-tree").IStateTreeNode<import("mobx-state-tree").IModelType<{
58
- id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
61
+ id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree" /**
62
+ * #action
63
+ * controlled by a reaction
64
+ */).ISimpleType<string>, [undefined]>;
59
65
  type: import("mobx-state-tree").ISimpleType<string>;
60
66
  rpcDriverName: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
61
67
  }, {
@@ -82,6 +88,14 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
82
88
  features: Feature[] | undefined;
83
89
  message: string | undefined;
84
90
  } & {
91
+ /**
92
+ * #getter
93
+ */
94
+ readonly level: number;
95
+ /**
96
+ * #getter
97
+ */
98
+ readonly height: number;
85
99
  /**
86
100
  * #getter
87
101
  */
@@ -126,7 +140,10 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
126
140
  message: string | undefined;
127
141
  }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
128
142
  onHorizontalScroll?: () => void;
129
- blockState?: Record<string, any>;
143
+ blockState? /**
144
+ * #action
145
+ * controlled by a reaction
146
+ */: Record<string, any>;
130
147
  }>;
131
148
  readonly DisplayBlurb: React.FC<{
132
149
  model: {
@@ -138,7 +155,10 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
138
155
  error: unknown;
139
156
  message: string | undefined;
140
157
  } & import("mobx-state-tree").IStateTreeNode<import("mobx-state-tree").IModelType<{
141
- id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
158
+ id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree" /**
159
+ * #action
160
+ * controlled by a reaction
161
+ */).ISimpleType<string>, [undefined]>;
142
162
  type: import("mobx-state-tree").ISimpleType<string>;
143
163
  rpcDriverName: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
144
164
  }, {
@@ -201,7 +221,10 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
201
221
  message: string | undefined;
202
222
  }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
203
223
  onHorizontalScroll?: () => void;
204
- blockState?: Record<string, any>;
224
+ blockState? /**
225
+ * #action
226
+ * controlled by a reaction
227
+ */: Record<string, any>;
205
228
  }>;
206
229
  readonly DisplayBlurb: React.FC<{
207
230
  model: {
@@ -26,6 +26,18 @@ function stateModelFactory(configSchema) {
26
26
  message: undefined,
27
27
  }))
28
28
  .views(self => ({
29
+ /**
30
+ * #getter
31
+ */
32
+ get level() {
33
+ return getParent(self, 4).level;
34
+ },
35
+ /**
36
+ * #getter
37
+ */
38
+ get height() {
39
+ return getParent(self, 4).height;
40
+ },
29
41
  /**
30
42
  * #getter
31
43
  */
@@ -131,7 +143,7 @@ function renderBlockData(self) {
131
143
  // renderProps is something under our control. Compare to
132
144
  // serverSideRenderedBlock
133
145
  readConfObject(self.configuration);
134
- const { adapterConfig } = self;
146
+ const { level, adapterConfig } = self;
135
147
  const parent = getContainingView(self);
136
148
  const sessionId = getRpcSessionId(self);
137
149
  getSnapshot(parent);
@@ -140,8 +152,7 @@ function renderBlockData(self) {
140
152
  rpcManager,
141
153
  renderProps: {
142
154
  ...display.renderProps(),
143
- // @ts-expect-error
144
- level: getParent(self, 4).level,
155
+ level,
145
156
  view: parent,
146
157
  adapterConfig,
147
158
  sessionId,
@@ -1,8 +1,8 @@
1
- import { addDisposer, getParent, getSnapshot } from 'mobx-state-tree';
1
+ import { reaction, autorun } from 'mobx';
2
+ import { addDisposer, getSnapshot } from 'mobx-state-tree';
2
3
  import { getContainingView, getSession } from '@jbrowse/core/util';
3
4
  import { bpToPx } from '@jbrowse/core/util/Base1DUtils';
4
5
  import { MismatchParser } from '@jbrowse/plugin-alignments';
5
- import { reaction, autorun } from 'mobx';
6
6
  import { drawMouseoverSynteny, drawRef } from './drawSynteny';
7
7
  export function doAfterAttach(self) {
8
8
  addDisposer(self, autorun(() => {
@@ -48,10 +48,9 @@ export function doAfterAttach(self) {
48
48
  if (!initialized) {
49
49
  return;
50
50
  }
51
+ const { level } = self;
51
52
  const { assemblyManager } = getSession(self);
52
53
  const view = getContainingView(self);
53
- // @ts-expect-error
54
- const level = getParent(self, 4).level;
55
54
  const viewSnaps = view.views.map(view => ({
56
55
  ...getSnapshot(view),
57
56
  width: view.width,
@@ -18,6 +18,7 @@ const useStyles = makeStyles()({
18
18
  position: 'relative',
19
19
  },
20
20
  mouseoverCanvas: {
21
+ imageRendering: 'pixelated',
21
22
  position: 'absolute',
22
23
  pointEvents: 'none',
23
24
  },
@@ -27,6 +28,7 @@ const useStyles = makeStyles()({
27
28
  });
28
29
  const LinearSyntenyRendering = observer(function ({ model, }) {
29
30
  const { classes } = useStyles();
31
+ const { mouseoverId, height } = model;
30
32
  const xOffset = useRef(0);
31
33
  const view = getContainingView(model);
32
34
  const width = view.width;
@@ -39,20 +41,19 @@ const LinearSyntenyRendering = observer(function ({ model, }) {
39
41
  const [mouseCurrDownX, setMouseCurrDownX] = useState();
40
42
  const [mouseInitialDownX, setMouseInitialDownX] = useState();
41
43
  const [currY, setCurrY] = useState();
42
- const { mouseoverId, height } = model;
43
- const k2p = useRef();
44
+ const mainSyntenyCanvasRefp = useRef();
44
45
  // these useCallbacks avoid new refs from being created on any mouseover,
45
46
  // etc.
46
47
  // biome-ignore lint/correctness/useExhaustiveDependencies:
47
- const k1 = useCallback((ref) => {
48
+ const mouseoverDetectionCanvasRef = useCallback((ref) => {
48
49
  model.setMouseoverCanvasRef(ref);
49
50
  },
50
51
  // eslint-disable-next-line react-hooks/exhaustive-deps
51
52
  [model, height, width]);
52
53
  // biome-ignore lint/correctness/useExhaustiveDependencies:
53
- const k2 = useCallback((ref) => {
54
+ const mainSyntenyCanvasRef = useCallback((ref) => {
54
55
  model.setMainCanvasRef(ref);
55
- k2p.current = ref; // this ref is additionally used in useEffect below
56
+ mainSyntenyCanvasRefp.current = ref; // this ref is additionally used in useEffect below
56
57
  },
57
58
  // eslint-disable-next-line react-hooks/exhaustive-deps
58
59
  [model, height, width]);
@@ -75,7 +76,9 @@ const LinearSyntenyRendering = observer(function ({ model, }) {
75
76
  v.setScaleFactor(1);
76
77
  v.zoomTo(delta.current > 0
77
78
  ? v.bpPerPx * (1 + delta.current)
78
- : v.bpPerPx / (1 - delta.current), event.clientX - (((_a = k2p.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect().left) || 0));
79
+ : v.bpPerPx / (1 - delta.current), event.clientX -
80
+ (((_a = mainSyntenyCanvasRefp.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect().left) ||
81
+ 0));
79
82
  }
80
83
  delta.current = 0;
81
84
  }, 300);
@@ -98,28 +101,28 @@ const LinearSyntenyRendering = observer(function ({ model, }) {
98
101
  }
99
102
  }
100
103
  }
101
- (_a = k2p.current) === null || _a === void 0 ? void 0 : _a.addEventListener('wheel', onWheel);
104
+ (_a = mainSyntenyCanvasRefp.current) === null || _a === void 0 ? void 0 : _a.addEventListener('wheel', onWheel);
102
105
  return () => {
103
106
  var _a;
104
- (_a = k2p.current) === null || _a === void 0 ? void 0 : _a.removeEventListener('wheel', onWheel);
107
+ (_a = mainSyntenyCanvasRefp.current) === null || _a === void 0 ? void 0 : _a.removeEventListener('wheel', onWheel);
105
108
  };
106
109
  // eslint-disable-next-line react-hooks/exhaustive-deps
107
110
  }, [model, height, width]);
108
111
  // biome-ignore lint/correctness/useExhaustiveDependencies:
109
- const k3 = useCallback((ref) => {
112
+ const clickMapCanvasRef = useCallback((ref) => {
110
113
  model.setClickMapCanvasRef(ref);
111
114
  },
112
115
  // eslint-disable-next-line react-hooks/exhaustive-deps
113
116
  [model, height, width]);
114
117
  // biome-ignore lint/correctness/useExhaustiveDependencies:
115
- const k4 = useCallback((ref) => {
118
+ const cigarClickMapCanvasRef = useCallback((ref) => {
116
119
  model.setCigarClickMapCanvasRef(ref);
117
120
  },
118
121
  // eslint-disable-next-line react-hooks/exhaustive-deps
119
122
  [model, height, width]);
120
123
  return (React.createElement("div", { className: classes.rel },
121
- React.createElement("canvas", { ref: k1, width: width, height: height, className: classes.mouseoverCanvas }),
122
- React.createElement("canvas", { ref: k2, onMouseMove: event => {
124
+ React.createElement("canvas", { ref: mouseoverDetectionCanvasRef, width: width, height: height, className: classes.mouseoverCanvas }),
125
+ React.createElement("canvas", { ref: mainSyntenyCanvasRef, onMouseMove: event => {
123
126
  var _a;
124
127
  if (mouseCurrDownX !== undefined) {
125
128
  xOffset.current += mouseCurrDownX - event.clientX;
@@ -166,7 +169,11 @@ const LinearSyntenyRendering = observer(function ({ model, }) {
166
169
  const { f, cigar } = model.featPositions[id];
167
170
  const unitMultiplier2 = Math.floor(MAX_COLOR_RANGE / cigar.length);
168
171
  const cigarIdx = getId(r2, g2, b2, unitMultiplier2);
169
- setTooltip(getTooltip(f, cigar[cigarIdx], cigar[cigarIdx + 1]));
172
+ setTooltip(getTooltip({
173
+ feature: f,
174
+ cigarOp: cigar[cigarIdx],
175
+ cigarOpLen: cigar[cigarIdx + 1],
176
+ }));
170
177
  }
171
178
  }
172
179
  }, onMouseLeave: () => {
@@ -185,8 +192,8 @@ const LinearSyntenyRendering = observer(function ({ model, }) {
185
192
  }, onContextMenu: evt => {
186
193
  onSynContextClick(evt, model, setAnchorEl);
187
194
  }, "data-testid": "synteny_canvas", className: classes.mainCanvas, width: width, height: height }),
188
- React.createElement("canvas", { ref: k3, className: classes.pix, width: width, height: height }),
189
- React.createElement("canvas", { ref: k4, className: classes.pix, width: width, height: height }),
195
+ React.createElement("canvas", { ref: clickMapCanvasRef, className: classes.pix, width: width, height: height }),
196
+ React.createElement("canvas", { ref: cigarClickMapCanvasRef, className: classes.pix, width: width, height: height }),
190
197
  mouseoverId && tooltip && currX && currY ? (React.createElement(SyntenyTooltip, { title: tooltip })) : null,
191
198
  anchorEl ? (React.createElement(SyntenyContextMenu, { model: model, anchorEl: anchorEl, onClose: () => {
192
199
  setAnchorEl(undefined);
@@ -1,7 +1,6 @@
1
1
  import React from 'react';
2
2
  import { getContainingView, getSession } from '@jbrowse/core/util';
3
3
  import { Menu } from '@jbrowse/core/ui';
4
- import { getParent } from 'mobx-state-tree';
5
4
  export default function SyntenyContextMenu({ model, onClose, anchorEl, }) {
6
5
  const view = getContainingView(model);
7
6
  const { clientX, clientY, feature } = anchorEl;
@@ -30,13 +29,12 @@ export default function SyntenyContextMenu({ model, onClose, anchorEl, }) {
30
29
  label: 'Center on feature',
31
30
  onClick: () => {
32
31
  const { f } = feature;
33
- const track = getParent(model, 4);
34
32
  const start = f.get('start');
35
33
  const end = f.get('end');
36
34
  const refName = f.get('refName');
37
35
  const mate = f.get('mate');
38
- const l1 = view.views[track.level];
39
- const l2 = view.views[track.level + 1];
36
+ const l1 = view.views[model.level];
37
+ const l2 = view.views[model.level + 1];
40
38
  l1.navToLocString(`${refName}:${start}-${end}`).catch((e) => {
41
39
  const err = `${l1.assemblyNames[0]}:${e}`;
42
40
  console.error(err);
@@ -36,5 +36,9 @@ export declare function drawBox(ctx: CanvasRenderingContext2D, x1: number, x2: n
36
36
  export declare function drawBezierBox(ctx: CanvasRenderingContext2D, x1: number, x2: number, y1: number, x3: number, x4: number, y2: number, mid: number): void;
37
37
  export declare function onSynClick(event: React.MouseEvent, model: LinearSyntenyDisplayModel): import("../model").FeatPos | undefined;
38
38
  export declare function onSynContextClick(event: React.MouseEvent, model: LinearSyntenyDisplayModel, setAnchorEl: (arg: ClickCoord) => void): void;
39
- export declare function getTooltip(f: Feature, cigarOp?: string, cigarOpLen?: string): string;
39
+ export declare function getTooltip({ feature, cigarOp, cigarOpLen, }: {
40
+ feature: Feature;
41
+ cigarOp?: string;
42
+ cigarOpLen?: string;
43
+ }): string;
40
44
  export {};
@@ -54,7 +54,6 @@ export function drawBox(ctx, x1, x2, y1, x3, x4, y2) {
54
54
  ctx.lineTo(x3, y2);
55
55
  ctx.lineTo(x4, y2);
56
56
  ctx.closePath();
57
- ctx.fill();
58
57
  }
59
58
  export function drawBezierBox(ctx, x1, x2, y1, x3, x4, y2, mid) {
60
59
  const len1 = Math.abs(x1 - x2);
@@ -74,13 +73,11 @@ export function drawBezierBox(ctx, x1, x2, y1, x3, x4, y2, mid) {
74
73
  ctx.lineTo(x4, y2);
75
74
  ctx.bezierCurveTo(x4, mid, x1, mid, x1, y1);
76
75
  ctx.closePath();
77
- ctx.fill();
78
76
  }
79
77
  export function onSynClick(event, model) {
80
78
  const view = getContainingView(model);
81
79
  const track = getContainingTrack(model);
82
- const ref1 = model.clickMapCanvas;
83
- const ref2 = model.cigarClickMapCanvas;
80
+ const { featPositions, numFeats, clickMapCanvas: ref1, cigarClickMapCanvas: ref2, level, } = model;
84
81
  if (!ref1 || !ref2) {
85
82
  return;
86
83
  }
@@ -93,18 +90,19 @@ export function onSynClick(event, model) {
93
90
  const x = event.clientX - rect.left;
94
91
  const y = event.clientY - rect.top;
95
92
  const [r1, g1, b1] = ctx1.getImageData(x, y, 1, 1).data;
96
- const unitMultiplier = Math.floor(MAX_COLOR_RANGE / model.numFeats);
93
+ const unitMultiplier = Math.floor(MAX_COLOR_RANGE / numFeats);
97
94
  const id = getId(r1, g1, b1, unitMultiplier);
98
- const feat = model.featPositions[id];
95
+ const feat = featPositions[id];
99
96
  if (feat) {
100
97
  const { f } = feat;
101
98
  model.setClickId(f.id());
102
99
  const session = getSession(model);
103
100
  if (isSessionModelWithWidgets(session)) {
104
- session.showWidget(session.addWidget('BaseFeatureWidget', 'baseFeature', {
101
+ session.showWidget(session.addWidget('SyntenyFeatureWidget', 'syntenyFeature', {
105
102
  view,
106
103
  track,
107
104
  featureData: f.toJSON(),
105
+ level,
108
106
  }));
109
107
  }
110
108
  }
@@ -135,9 +133,9 @@ export function onSynContextClick(event, model, setAnchorEl) {
135
133
  setAnchorEl({ clientX, clientY, feature: f });
136
134
  }
137
135
  }
138
- export function getTooltip(f, cigarOp, cigarOpLen) {
136
+ export function getTooltip({ feature, cigarOp, cigarOpLen, }) {
139
137
  // @ts-expect-error
140
- const f1 = f.toJSON();
138
+ const f1 = feature.toJSON();
141
139
  const f2 = f1.mate;
142
140
  const l1 = f1.end - f1.start;
143
141
  const l2 = f2.end - f2.start;
@@ -1,6 +1,5 @@
1
1
  import { doesIntersect2, getContainingView } from '@jbrowse/core/util';
2
2
  import { draw, drawMatchSimple } from './components/util';
3
- import { getParent } from 'mobx-state-tree';
4
3
  export const MAX_COLOR_RANGE = 255 * 255 * 255; // max color range
5
4
  function makeColor(idx) {
6
5
  const r = Math.floor(idx / (255 * 255)) % 255;
@@ -24,11 +23,9 @@ export function getId(r, g, b, unitMultiplier) {
24
23
  export function drawRef(model, ctx1, ctx3) {
25
24
  var _a;
26
25
  const view = getContainingView(model);
27
- // @ts-expect-error
28
- const level = getParent(model, 4).level;
29
26
  const drawCurves = view.drawCurves;
30
27
  const drawCIGAR = view.drawCIGAR;
31
- const { height, featPositions } = model;
28
+ const { level, height, featPositions } = model;
32
29
  const width = view.width;
33
30
  const bpPerPxs = view.views.map(v => v.bpPerPx);
34
31
  if (ctx3) {
@@ -144,9 +141,11 @@ export function drawRef(model, ctx1, ctx3) {
144
141
  colorMap[(continuingFlag && d1 > 1) || d2 > 1 ? op : 'M'];
145
142
  continuingFlag = false;
146
143
  draw(ctx1, px1, cx1, y1, cx2, px2, y2, mid, drawCurves);
144
+ ctx1.fill();
147
145
  if (ctx3) {
148
146
  ctx3.fillStyle = makeColor(idx);
149
147
  draw(ctx3, px1, cx1, y1, cx2, px2, y2, mid, drawCurves);
148
+ ctx3.fill();
150
149
  }
151
150
  }
152
151
  }
@@ -154,6 +153,7 @@ export function drawRef(model, ctx1, ctx3) {
154
153
  }
155
154
  else {
156
155
  draw(ctx1, x11, x12, y1, x22, x21, y2, mid, drawCurves);
156
+ ctx1.fill();
157
157
  }
158
158
  }
159
159
  }
@@ -187,7 +187,7 @@ export function drawRef(model, ctx1, ctx3) {
187
187
  }
188
188
  export function drawMouseoverSynteny(model) {
189
189
  var _a;
190
- const { clickId, mouseoverId } = model;
190
+ const { level, clickId, mouseoverId } = model;
191
191
  const highResolutionScaling = 1;
192
192
  const view = getContainingView(model);
193
193
  const drawCurves = view.drawCurves;
@@ -195,17 +195,16 @@ export function drawMouseoverSynteny(model) {
195
195
  const width = view.width;
196
196
  const ctx = (_a = model.mouseoverCanvas) === null || _a === void 0 ? void 0 : _a.getContext('2d');
197
197
  const offsets = view.views.map(v => v.offsetPx);
198
- // @ts-expect-error
199
- const level = getParent(model, 4).level;
200
198
  if (!ctx) {
201
199
  return;
202
200
  }
203
201
  ctx.resetTransform();
204
202
  ctx.scale(highResolutionScaling, highResolutionScaling);
205
203
  ctx.clearRect(0, 0, width, height);
204
+ ctx.strokeStyle = 'rgba(0, 0, 0, 0.9)';
205
+ ctx.fillStyle = 'rgba(0, 0, 0, 0.1)';
206
206
  const feature1 = model.featMap[mouseoverId || ''];
207
207
  if (feature1) {
208
- ctx.fillStyle = 'rgb(0,0,0,0.1)';
209
208
  drawMatchSimple({
210
209
  cb: ctx => {
211
210
  ctx.fill();
@@ -222,7 +221,6 @@ export function drawMouseoverSynteny(model) {
222
221
  }
223
222
  const feature2 = model.featMap[clickId || ''];
224
223
  if (feature2) {
225
- ctx.strokeStyle = 'rgb(0, 0, 0, 0.9)';
226
224
  drawMatchSimple({
227
225
  cb: ctx => {
228
226
  ctx.stroke();