@jbrowse/plugin-linear-comparative-view 2.16.0 → 2.17.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 (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 +30 -34
  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 +21 -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 +30 -34
  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 +21 -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;
@@ -106,20 +114,8 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
106
114
  noSpacing: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<boolean>>;
107
115
  fadeLikelihood: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<boolean>>;
108
116
  trackMaxHeight: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<number>>;
109
- colorBy: import("mobx-state-tree").IMaybe<import("mobx-state-tree").IModelType<{
110
- type: import("mobx-state-tree").ISimpleType<string>;
111
- tag: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
112
- extra: import("mobx-state-tree").IType<any, any, any>;
113
- }, {}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
114
- filterBy: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").IModelType<{
115
- flagInclude: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<number>, [undefined]>;
116
- flagExclude: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<number>, [undefined]>;
117
- readName: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
118
- tagFilter: import("mobx-state-tree").IMaybe<import("mobx-state-tree").IModelType<{
119
- tag: import("mobx-state-tree").ISimpleType<string>;
120
- value: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
121
- }, {}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
122
- }, {}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>, [undefined]>;
117
+ colorBy: import("mobx-state-tree").IType<import("@jbrowse/plugin-alignments/src/shared/types").ColorBy | undefined, import("@jbrowse/plugin-alignments/src/shared/types").ColorBy | undefined, import("@jbrowse/plugin-alignments/src/shared/types").ColorBy | undefined>;
118
+ filterBy: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").IType<import("@jbrowse/plugin-alignments/src/shared/types").FilterBy, import("@jbrowse/plugin-alignments/src/shared/types").FilterBy, import("@jbrowse/plugin-alignments/src/shared/types").FilterBy>, [undefined]>;
123
119
  jexlFilters: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").IArrayType<import("mobx-state-tree").ISimpleType<string>>, [undefined]>;
124
120
  } & {
125
121
  /**
@@ -223,7 +219,7 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
223
219
  regionCannotBeRendered(_region: import("@jbrowse/core/util").Region): import("react").JSX.Element | null;
224
220
  } & {
225
221
  featureIdUnderMouse: undefined | string;
226
- contextMenuFeature: undefined | import("@jbrowse/core/util").Feature;
222
+ contextMenuFeature: undefined | Feature;
227
223
  } & {
228
224
  readonly DisplayMessageComponent: import("react").FC<any> | undefined;
229
225
  readonly blockType: "dynamicBlocks" | "staticBlocks";
@@ -233,19 +229,19 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
233
229
  readonly TooltipComponent: import("@jbrowse/core/util").AnyReactComponentType;
234
230
  readonly selectedFeatureId: string | undefined;
235
231
  } & {
236
- readonly features: import("@jbrowse/core/util/compositeMap").default<string, import("@jbrowse/core/util").Feature>;
237
- readonly featureUnderMouse: import("@jbrowse/core/util").Feature | undefined;
232
+ readonly features: import("@jbrowse/core/util/compositeMap").default<string, Feature>;
233
+ readonly featureUnderMouse: Feature | undefined;
238
234
  getFeatureOverlapping(blockKey: string, x: number, y: number): string | undefined;
239
235
  getFeatureByID(blockKey: string, id: string): [number, number, number, number] | undefined;
240
236
  searchFeatureByID(id: string): [number, number, number, number] | undefined;
241
237
  } & {
242
238
  addBlock(key: string, block: import("@jbrowse/core/util/blockTypes").BaseBlock): void;
243
239
  deleteBlock(key: string): void;
244
- selectFeature(feature: import("@jbrowse/core/util").Feature): void;
245
- navToFeature(feature: import("@jbrowse/core/util").Feature): void;
240
+ selectFeature(feature: Feature): void;
241
+ navToFeature(feature: Feature): void;
246
242
  clearFeatureSelection(): void;
247
243
  setFeatureIdUnderMouse(feature?: string): void;
248
- setContextMenuFeature(feature?: import("@jbrowse/core/util").Feature): void;
244
+ setContextMenuFeature(feature?: Feature): void;
249
245
  } & {
250
246
  reload(): Promise<void>;
251
247
  } & {
@@ -257,7 +253,7 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
257
253
  afterAttach(): void;
258
254
  } & {
259
255
  colorTagMap: import("mobx").ObservableMap<string, string>;
260
- featureUnderMouseVolatile: undefined | import("@jbrowse/core/util").Feature;
256
+ featureUnderMouseVolatile: undefined | Feature;
261
257
  tagsReady: boolean;
262
258
  } & {
263
259
  readonly autorunReady: boolean;
@@ -266,17 +262,13 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
266
262
  setMaxHeight(n?: number): void;
267
263
  setFeatureHeight(n?: number): void;
268
264
  setNoSpacing(flag?: boolean): void;
269
- setColorScheme(colorScheme: {
270
- type: string;
271
- tag?: string;
272
- extra?: import("@jbrowse/plugin-alignments/src/shared/color").ExtraColorBy;
273
- }): void;
265
+ setColorScheme(colorScheme: import("@jbrowse/plugin-alignments/src/shared/types").ColorBy): void;
274
266
  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;
267
+ setFeatureUnderMouse(feat?: Feature): void;
268
+ selectFeature(feature: Feature): void;
269
+ copyFeatureToClipboard(feature: Feature): void;
278
270
  setConfig(conf: import("@jbrowse/core/configuration").AnyConfigurationModel): void;
279
- setFilterBy(filter: import("@jbrowse/plugin-alignments/src/shared").IFilter): void;
271
+ setFilterBy(filter: import("@jbrowse/plugin-alignments/src/shared/types").FilterBy): void;
280
272
  setJexlFilters(filters: string[]): void;
281
273
  } & {
282
274
  readonly rendererConfig: {
@@ -293,7 +285,7 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
293
285
  } & {
294
286
  readonly maxHeight: any;
295
287
  readonly featureHeightSetting: any;
296
- readonly featureUnderMouse: import("@jbrowse/core/util").Feature | undefined;
288
+ readonly featureUnderMouse: Feature | undefined;
297
289
  renderReady(): boolean;
298
290
  readonly filters: import("@jbrowse/core/pluggableElementTypes/renderers/util/serializableFilterChain").default;
299
291
  } & {
@@ -352,6 +344,10 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
352
344
  }[];
353
345
  })[];
354
346
  } & {
347
+ /**
348
+ * #action
349
+ */
350
+ selectFeature(feature: Feature): void;
355
351
  afterCreate(): void;
356
352
  }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;
357
353
  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,
@@ -27,6 +27,7 @@ const useStyles = makeStyles()({
27
27
  });
28
28
  const LinearSyntenyRendering = observer(function ({ model, }) {
29
29
  const { classes } = useStyles();
30
+ const { mouseoverId, height } = model;
30
31
  const xOffset = useRef(0);
31
32
  const view = getContainingView(model);
32
33
  const width = view.width;
@@ -39,20 +40,19 @@ const LinearSyntenyRendering = observer(function ({ model, }) {
39
40
  const [mouseCurrDownX, setMouseCurrDownX] = useState();
40
41
  const [mouseInitialDownX, setMouseInitialDownX] = useState();
41
42
  const [currY, setCurrY] = useState();
42
- const { mouseoverId, height } = model;
43
- const k2p = useRef();
43
+ const mainSyntenyCanvasRefp = useRef();
44
44
  // these useCallbacks avoid new refs from being created on any mouseover,
45
45
  // etc.
46
46
  // biome-ignore lint/correctness/useExhaustiveDependencies:
47
- const k1 = useCallback((ref) => {
47
+ const mouseoverDetectionCanvasRef = useCallback((ref) => {
48
48
  model.setMouseoverCanvasRef(ref);
49
49
  },
50
50
  // eslint-disable-next-line react-hooks/exhaustive-deps
51
51
  [model, height, width]);
52
52
  // biome-ignore lint/correctness/useExhaustiveDependencies:
53
- const k2 = useCallback((ref) => {
53
+ const mainSyntenyCanvasRef = useCallback((ref) => {
54
54
  model.setMainCanvasRef(ref);
55
- k2p.current = ref; // this ref is additionally used in useEffect below
55
+ mainSyntenyCanvasRefp.current = ref; // this ref is additionally used in useEffect below
56
56
  },
57
57
  // eslint-disable-next-line react-hooks/exhaustive-deps
58
58
  [model, height, width]);
@@ -75,7 +75,9 @@ const LinearSyntenyRendering = observer(function ({ model, }) {
75
75
  v.setScaleFactor(1);
76
76
  v.zoomTo(delta.current > 0
77
77
  ? 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));
78
+ : v.bpPerPx / (1 - delta.current), event.clientX -
79
+ (((_a = mainSyntenyCanvasRefp.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect().left) ||
80
+ 0));
79
81
  }
80
82
  delta.current = 0;
81
83
  }, 300);
@@ -98,28 +100,28 @@ const LinearSyntenyRendering = observer(function ({ model, }) {
98
100
  }
99
101
  }
100
102
  }
101
- (_a = k2p.current) === null || _a === void 0 ? void 0 : _a.addEventListener('wheel', onWheel);
103
+ (_a = mainSyntenyCanvasRefp.current) === null || _a === void 0 ? void 0 : _a.addEventListener('wheel', onWheel);
102
104
  return () => {
103
105
  var _a;
104
- (_a = k2p.current) === null || _a === void 0 ? void 0 : _a.removeEventListener('wheel', onWheel);
106
+ (_a = mainSyntenyCanvasRefp.current) === null || _a === void 0 ? void 0 : _a.removeEventListener('wheel', onWheel);
105
107
  };
106
108
  // eslint-disable-next-line react-hooks/exhaustive-deps
107
109
  }, [model, height, width]);
108
110
  // biome-ignore lint/correctness/useExhaustiveDependencies:
109
- const k3 = useCallback((ref) => {
111
+ const clickMapCanvasRef = useCallback((ref) => {
110
112
  model.setClickMapCanvasRef(ref);
111
113
  },
112
114
  // eslint-disable-next-line react-hooks/exhaustive-deps
113
115
  [model, height, width]);
114
116
  // biome-ignore lint/correctness/useExhaustiveDependencies:
115
- const k4 = useCallback((ref) => {
117
+ const cigarClickMapCanvasRef = useCallback((ref) => {
116
118
  model.setCigarClickMapCanvasRef(ref);
117
119
  },
118
120
  // eslint-disable-next-line react-hooks/exhaustive-deps
119
121
  [model, height, width]);
120
122
  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 => {
123
+ React.createElement("canvas", { ref: mouseoverDetectionCanvasRef, width: width, height: height, className: classes.mouseoverCanvas }),
124
+ React.createElement("canvas", { ref: mainSyntenyCanvasRef, onMouseMove: event => {
123
125
  var _a;
124
126
  if (mouseCurrDownX !== undefined) {
125
127
  xOffset.current += mouseCurrDownX - event.clientX;
@@ -166,7 +168,11 @@ const LinearSyntenyRendering = observer(function ({ model, }) {
166
168
  const { f, cigar } = model.featPositions[id];
167
169
  const unitMultiplier2 = Math.floor(MAX_COLOR_RANGE / cigar.length);
168
170
  const cigarIdx = getId(r2, g2, b2, unitMultiplier2);
169
- setTooltip(getTooltip(f, cigar[cigarIdx], cigar[cigarIdx + 1]));
171
+ setTooltip(getTooltip({
172
+ feature: f,
173
+ cigarOp: cigar[cigarIdx],
174
+ cigarOpLen: cigar[cigarIdx + 1],
175
+ }));
170
176
  }
171
177
  }
172
178
  }, onMouseLeave: () => {
@@ -185,8 +191,8 @@ const LinearSyntenyRendering = observer(function ({ model, }) {
185
191
  }, onContextMenu: evt => {
186
192
  onSynContextClick(evt, model, setAnchorEl);
187
193
  }, "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 }),
194
+ React.createElement("canvas", { ref: clickMapCanvasRef, className: classes.pix, width: width, height: height }),
195
+ React.createElement("canvas", { ref: cigarClickMapCanvasRef, className: classes.pix, width: width, height: height }),
190
196
  mouseoverId && tooltip && currX && currY ? (React.createElement(SyntenyTooltip, { title: tooltip })) : null,
191
197
  anchorEl ? (React.createElement(SyntenyContextMenu, { model: model, anchorEl: anchorEl, onClose: () => {
192
198
  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();