@jbrowse/plugin-linear-comparative-view 2.11.1 → 2.12.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 (27) hide show
  1. package/dist/LGVSyntenyDisplay/components/util.js +1 -1
  2. package/dist/LGVSyntenyDisplay/configSchemaF.d.ts +5 -0
  3. package/dist/LGVSyntenyDisplay/model.d.ts +7 -3
  4. package/dist/LinearComparativeView/model.d.ts +11 -36
  5. package/dist/LinearComparativeView/model.js +0 -23
  6. package/dist/LinearSyntenyDisplay/components/LinearSyntenyRendering.js +54 -101
  7. package/dist/LinearSyntenyDisplay/components/util.d.ts +10 -0
  8. package/dist/LinearSyntenyDisplay/components/util.js +87 -1
  9. package/dist/LinearSyntenyView/components/ImportForm/index.js +1 -0
  10. package/dist/LinearSyntenyView/model.d.ts +39 -139
  11. package/dist/LinearSyntenyView/model.js +0 -8
  12. package/dist/SyntenyFeatureDetail/SyntenyFeatureDetail.d.ts +5 -3
  13. package/dist/SyntenyFeatureDetail/SyntenyFeatureDetail.js +2 -4
  14. package/esm/LGVSyntenyDisplay/components/util.js +1 -1
  15. package/esm/LGVSyntenyDisplay/configSchemaF.d.ts +5 -0
  16. package/esm/LGVSyntenyDisplay/model.d.ts +7 -3
  17. package/esm/LinearComparativeView/model.d.ts +11 -36
  18. package/esm/LinearComparativeView/model.js +1 -24
  19. package/esm/LinearSyntenyDisplay/components/LinearSyntenyRendering.js +54 -101
  20. package/esm/LinearSyntenyDisplay/components/util.d.ts +10 -0
  21. package/esm/LinearSyntenyDisplay/components/util.js +84 -1
  22. package/esm/LinearSyntenyView/components/ImportForm/index.js +1 -0
  23. package/esm/LinearSyntenyView/model.d.ts +39 -139
  24. package/esm/LinearSyntenyView/model.js +0 -8
  25. package/esm/SyntenyFeatureDetail/SyntenyFeatureDetail.d.ts +5 -3
  26. package/esm/SyntenyFeatureDetail/SyntenyFeatureDetail.js +2 -4
  27. package/package.json +2 -2
@@ -24,7 +24,7 @@ function findPosInCigar(cigar, startX) {
24
24
  else if (op === 'D') {
25
25
  featX += min;
26
26
  }
27
- else if (op === 'M') {
27
+ else if (op === 'M' || op === '=' || op === 'X') {
28
28
  mateX += min;
29
29
  featX += min;
30
30
  }
@@ -48,5 +48,10 @@ declare function configSchemaF(pluginManager: PluginManager): import("@jbrowse/c
48
48
  defaultValue: string;
49
49
  contextVariable: string[];
50
50
  };
51
+ jexlFilters: {
52
+ type: string;
53
+ description: string;
54
+ defaultValue: never[];
55
+ };
51
56
  }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "displayId">>, undefined>>, undefined>>, undefined>>;
52
57
  export default configSchemaF;
@@ -85,9 +85,7 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
85
85
  height: {
86
86
  type: string;
87
87
  defaultValue: number;
88
- description: string; /**
89
- * #method
90
- */
88
+ description: string;
91
89
  };
92
90
  mouseover: {
93
91
  type: string;
@@ -95,6 +93,11 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
95
93
  defaultValue: string;
96
94
  contextVariable: string[];
97
95
  };
96
+ jexlFilters: {
97
+ type: string;
98
+ description: string;
99
+ defaultValue: never[];
100
+ };
98
101
  }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "displayId">>;
99
102
  } & {
100
103
  configuration: AnyConfigurationSchemaType;
@@ -240,6 +243,7 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
240
243
  addBlock(key: string, block: import("@jbrowse/core/util/blockTypes").BaseBlock): void;
241
244
  deleteBlock(key: string): void;
242
245
  selectFeature(feature: import("@jbrowse/core/util").Feature): void;
246
+ navToFeature(feature: import("@jbrowse/core/util").Feature): void;
243
247
  clearFeatureSelection(): void;
244
248
  setFeatureIdUnderMouse(feature?: string | undefined): void;
245
249
  setContextMenuFeature(feature?: import("@jbrowse/core/util").Feature | undefined): void;
@@ -17,7 +17,6 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
17
17
  type: import("mobx-state-tree").ISimpleType<"LinearComparativeView">;
18
18
  trackSelectorType: import("mobx-state-tree").IType<string | undefined, string, string>;
19
19
  showIntraviewLinks: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
20
- linkViews: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
21
20
  interactToggled: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
22
21
  middleComparativeHeight: import("mobx-state-tree").IType<number | undefined, number, number>;
23
22
  tracks: import("mobx-state-tree").IArrayType<import("mobx-state-tree").IAnyType>;
@@ -30,16 +29,7 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
30
29
  type: import("mobx-state-tree").IType<string | undefined, string, string>;
31
30
  offsetPx: import("mobx-state-tree").IType<number | undefined, number, number>;
32
31
  bpPerPx: import("mobx-state-tree").IType<number | undefined, number, number>;
33
- displayedRegions: import("mobx-state-tree").IArrayType<import("mobx-state-tree").IModelType<{
34
- refName: import("mobx-state-tree").ISimpleType<string>;
35
- start: import("mobx-state-tree").ISimpleType<number>;
36
- end: import("mobx-state-tree").ISimpleType<number>;
37
- reversed: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<boolean>, [undefined]>;
38
- } & {
39
- assemblyName: import("mobx-state-tree").ISimpleType<string>;
40
- }, {
41
- setRefName(newRefName: string): void;
42
- }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
32
+ displayedRegions: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").IType<import("@jbrowse/core/util").Region[], import("@jbrowse/core/util").Region[], import("@jbrowse/core/util").Region[]>, [undefined]>;
43
33
  tracks: import("mobx-state-tree").IArrayType<import("mobx-state-tree").IAnyType>;
44
34
  hideHeader: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
45
35
  hideHeaderOverview: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
@@ -140,6 +130,7 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
140
130
  getSelectedRegions(leftOffset?: import("@jbrowse/plugin-linear-genome-view/src/LinearGenomeView").BpOffset | undefined, rightOffset?: import("@jbrowse/plugin-linear-genome-view/src/LinearGenomeView").BpOffset | undefined): {
141
131
  start: number;
142
132
  end: number;
133
+ type: string;
143
134
  regionNumber?: number | undefined;
144
135
  reversed?: boolean | undefined;
145
136
  refName: string;
@@ -197,14 +188,13 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
197
188
  lowerCaseRefNameAliases: {
198
189
  [x: string]: string | undefined;
199
190
  } | undefined;
200
- cytobands: import("@jbrowse/core/util").Feature[] | undefined;
191
+ cytobands: import("@jbrowse/core/util").Feature[] | undefined; /**
192
+ * #property
193
+ */
201
194
  } & {
202
195
  getConf(arg: string): any;
203
196
  } & {
204
197
  readonly initialized: boolean;
205
- /**
206
- * #property
207
- */
208
198
  readonly name: string;
209
199
  readonly regions: import("@jbrowse/core/assemblyManager/assembly").BasicRegion[] | undefined;
210
200
  readonly aliases: string[];
@@ -262,14 +252,13 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
262
252
  lowerCaseRefNameAliases: {
263
253
  [x: string]: string | undefined;
264
254
  } | undefined;
265
- cytobands: import("@jbrowse/core/util").Feature[] | undefined;
255
+ cytobands: import("@jbrowse/core/util").Feature[] | undefined; /**
256
+ * #property
257
+ */
266
258
  } & {
267
259
  getConf(arg: string): any;
268
260
  } & {
269
261
  readonly initialized: boolean;
270
- /**
271
- * #property
272
- */
273
262
  readonly name: string;
274
263
  readonly regions: import("@jbrowse/core/assemblyManager/assembly").BasicRegion[] | undefined;
275
264
  readonly aliases: string[];
@@ -339,7 +328,7 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
339
328
  offset: number;
340
329
  start: number;
341
330
  end: number;
342
- reversed: boolean;
331
+ reversed?: boolean | undefined;
343
332
  };
344
333
  readonly centerLineInfo: {
345
334
  coord: number;
@@ -350,7 +339,7 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
350
339
  offset: number;
351
340
  start: number;
352
341
  end: number;
353
- reversed: boolean;
342
+ reversed?: boolean | undefined;
354
343
  } | undefined;
355
344
  } & {
356
345
  afterCreate(): void;
@@ -363,16 +352,7 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
363
352
  type: import("mobx-state-tree").IType<string | undefined, string, string>;
364
353
  offsetPx: import("mobx-state-tree").IType<number | undefined, number, number>;
365
354
  bpPerPx: import("mobx-state-tree").IType<number | undefined, number, number>;
366
- displayedRegions: import("mobx-state-tree").IArrayType<import("mobx-state-tree").IModelType<{
367
- refName: import("mobx-state-tree").ISimpleType<string>;
368
- start: import("mobx-state-tree").ISimpleType<number>;
369
- end: import("mobx-state-tree").ISimpleType<number>;
370
- reversed: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<boolean>, [undefined]>;
371
- } & {
372
- assemblyName: import("mobx-state-tree").ISimpleType<string>;
373
- }, {
374
- setRefName(newRefName: string): void;
375
- }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
355
+ displayedRegions: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").IType<import("@jbrowse/core/util").Region[], import("@jbrowse/core/util").Region[], import("@jbrowse/core/util").Region[]>, [undefined]>;
376
356
  tracks: import("mobx-state-tree").IArrayType<import("mobx-state-tree").IAnyType>;
377
357
  hideHeader: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
378
358
  hideHeaderOverview: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
@@ -414,7 +394,6 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
414
394
  */
415
395
  readonly assemblyNames: string[];
416
396
  } & {
417
- afterAttach(): void;
418
397
  beforeDestroy(): void;
419
398
  onSubviewAction(actionName: string, path: string, args?: unknown[]): void;
420
399
  /**
@@ -439,10 +418,6 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
439
418
  * #action
440
419
  */
441
420
  setMiddleComparativeHeight(n: number): number;
442
- /**
443
- * #action
444
- */
445
- toggleLinkViews(): void;
446
421
  /**
447
422
  * #action
448
423
  */
@@ -62,10 +62,6 @@ function stateModelFactory(pluginManager) {
62
62
  * #property
63
63
  */
64
64
  showIntraviewLinks: true,
65
- /**
66
- * #property
67
- */
68
- linkViews: false,
69
65
  /**
70
66
  * #property
71
67
  */
@@ -126,19 +122,6 @@ function stateModelFactory(pluginManager) {
126
122
  },
127
123
  }))
128
124
  .actions(self => ({
129
- afterAttach() {
130
- (0, mobx_state_tree_1.addDisposer)(self, (0, mobx_state_tree_1.onAction)(self, param => {
131
- if (self.linkViews) {
132
- const { name, path, args } = param;
133
- // doesn't link showTrack/hideTrack, doesn't make sense in
134
- // synteny views most time
135
- const actions = ['horizontalScroll', 'zoomTo', 'setScaleFactor'];
136
- if (actions.includes(name) && path) {
137
- this.onSubviewAction(name, path, args);
138
- }
139
- }
140
- }));
141
- },
142
125
  // automatically removes session assemblies associated with this view
143
126
  // e.g. read vs ref
144
127
  beforeDestroy() {
@@ -191,12 +174,6 @@ function stateModelFactory(pluginManager) {
191
174
  self.middleComparativeHeight = n;
192
175
  return self.middleComparativeHeight;
193
176
  },
194
- /**
195
- * #action
196
- */
197
- toggleLinkViews() {
198
- self.linkViews = !self.linkViews;
199
- },
200
177
  /**
201
178
  * #action
202
179
  */
@@ -35,6 +35,7 @@ const mui_1 = require("tss-react/mui");
35
35
  const SyntenyTooltip_1 = __importDefault(require("./SyntenyTooltip"));
36
36
  const drawSynteny_1 = require("../drawSynteny");
37
37
  const SyntenyContextMenu_1 = __importDefault(require("./SyntenyContextMenu"));
38
+ const util_2 = require("./util");
38
39
  const useStyles = (0, mui_1.makeStyles)()({
39
40
  pix: {
40
41
  imageRendering: 'pixelated',
@@ -59,30 +60,44 @@ const LinearSyntenyRendering = (0, mobx_react_1.observer)(function ({ model, })
59
60
  const view = (0, util_1.getContainingView)(model);
60
61
  const height = view.middleComparativeHeight;
61
62
  const width = view.width;
63
+ const delta = (0, react_1.useRef)(0);
64
+ const timeout = (0, react_1.useRef)();
62
65
  const [anchorEl, setAnchorEl] = (0, react_1.useState)();
63
66
  const [tooltip, setTooltip] = (0, react_1.useState)('');
64
67
  const [currX, setCurrX] = (0, react_1.useState)();
65
68
  const [mouseCurrDownX, setMouseCurrDownX] = (0, react_1.useState)();
66
69
  const [mouseInitialDownX, setMouseInitialDownX] = (0, react_1.useState)();
67
70
  const [currY, setCurrY] = (0, react_1.useState)();
71
+ const { mouseoverId } = model;
68
72
  // these useCallbacks avoid new refs from being created on any mouseover, etc.
69
73
  const k1 = (0, react_1.useCallback)((ref) => model.setMouseoverCanvasRef(ref),
70
74
  // eslint-disable-next-line react-hooks/exhaustive-deps
71
75
  [model, height, width]);
72
- const k2 = (0, react_1.useCallback)((ref) => model.setMainCanvasRef(ref),
73
- // eslint-disable-next-line react-hooks/exhaustive-deps
74
- [model, height, width]);
75
- const k3 = (0, react_1.useCallback)((ref) => model.setClickMapCanvasRef(ref),
76
- // eslint-disable-next-line react-hooks/exhaustive-deps
77
- [model, height, width]);
78
- const k4 = (0, react_1.useCallback)((ref) => model.setCigarClickMapCanvasRef(ref),
79
- // eslint-disable-next-line react-hooks/exhaustive-deps
80
- [model, height, width]);
81
- return (react_1.default.createElement("div", { className: classes.rel },
82
- react_1.default.createElement("canvas", { ref: k1, width: width, height: height, className: cx(classes.abs, classes.none) }),
83
- react_1.default.createElement("canvas", { ref: k2, onWheel: event => {
76
+ const k2 = (0, react_1.useCallback)((ref) => {
77
+ model.setMainCanvasRef(ref);
78
+ function onWheel(event) {
79
+ event.preventDefault();
80
+ if (event.ctrlKey === true) {
81
+ delta.current += event.deltaY / 500;
82
+ for (const v of view.views) {
83
+ v.setScaleFactor(delta.current < 0 ? 1 - delta.current : 1 / (1 + delta.current));
84
+ }
85
+ if (timeout.current) {
86
+ clearTimeout(timeout.current);
87
+ }
88
+ timeout.current = setTimeout(() => {
89
+ for (const v of view.views) {
90
+ v.setScaleFactor(1);
91
+ v.zoomTo(delta.current > 0
92
+ ? v.bpPerPx * (1 + delta.current)
93
+ : v.bpPerPx / (1 - delta.current), event.clientX - ((ref === null || ref === void 0 ? void 0 : ref.getBoundingClientRect().left) || 0));
94
+ }
95
+ delta.current = 0;
96
+ }, 300);
97
+ }
98
+ else {
84
99
  if (Math.abs(event.deltaY) < Math.abs(event.deltaX)) {
85
- xOffset.current += event.deltaX;
100
+ xOffset.current += event.deltaX / 2;
86
101
  }
87
102
  if (currScrollFrame.current === undefined) {
88
103
  currScrollFrame.current = requestAnimationFrame(() => {
@@ -95,7 +110,28 @@ const LinearSyntenyRendering = (0, mobx_react_1.observer)(function ({ model, })
95
110
  });
96
111
  });
97
112
  }
98
- }, onMouseMove: event => {
113
+ }
114
+ }
115
+ if (ref) {
116
+ ref.addEventListener('wheel', onWheel);
117
+ // this is a react 19-ism to have a cleanup in the ref callback
118
+ // https://react.dev/blog/2024/04/25/react-19#cleanup-functions-for-refs
119
+ // note: it warns in earlier versions of react
120
+ return () => ref.removeEventListener('wheel', onWheel);
121
+ }
122
+ return () => { };
123
+ },
124
+ // eslint-disable-next-line react-hooks/exhaustive-deps
125
+ [model, height, width]);
126
+ const k3 = (0, react_1.useCallback)((ref) => model.setClickMapCanvasRef(ref),
127
+ // eslint-disable-next-line react-hooks/exhaustive-deps
128
+ [model, height, width]);
129
+ const k4 = (0, react_1.useCallback)((ref) => model.setCigarClickMapCanvasRef(ref),
130
+ // eslint-disable-next-line react-hooks/exhaustive-deps
131
+ [model, height, width]);
132
+ return (react_1.default.createElement("div", { className: classes.rel },
133
+ react_1.default.createElement("canvas", { ref: k1, width: width, height: height, className: cx(classes.abs, classes.none) }),
134
+ react_1.default.createElement("canvas", { ref: k2, onMouseMove: event => {
99
135
  var _a;
100
136
  if (mouseCurrDownX !== undefined) {
101
137
  xOffset.current += mouseCurrDownX - event.clientX;
@@ -141,7 +177,7 @@ const LinearSyntenyRendering = (0, mobx_react_1.observer)(function ({ model, })
141
177
  const { f, cigar } = model.featPositions[id];
142
178
  const unitMultiplier2 = Math.floor(drawSynteny_1.MAX_COLOR_RANGE / cigar.length);
143
179
  const cigarIdx = (0, drawSynteny_1.getId)(r2, g2, b2, unitMultiplier2);
144
- setTooltip(getTooltip(f, cigar[cigarIdx], cigar[cigarIdx + 1]));
180
+ setTooltip((0, util_2.getTooltip)(f, cigar[cigarIdx], cigar[cigarIdx + 1]));
145
181
  }
146
182
  }
147
183
  }, onMouseLeave: () => {
@@ -155,95 +191,12 @@ const LinearSyntenyRendering = (0, mobx_react_1.observer)(function ({ model, })
155
191
  setMouseCurrDownX(undefined);
156
192
  if (mouseInitialDownX !== undefined &&
157
193
  Math.abs(evt.clientX - mouseInitialDownX) < 5) {
158
- onSyntenyClick(evt, model);
194
+ (0, util_2.onSynClick)(evt, model);
159
195
  }
160
- }, onContextMenu: evt => {
161
- onSyntenyContextClick(evt, model, setAnchorEl);
162
- }, "data-testid": "synteny_canvas", className: classes.abs, width: width, height: height }),
196
+ }, onContextMenu: evt => (0, util_2.onSynContextClick)(evt, model, setAnchorEl), "data-testid": "synteny_canvas", className: classes.abs, width: width, height: height }),
163
197
  react_1.default.createElement("canvas", { ref: k3, className: classes.pix, width: width, height: height }),
164
198
  react_1.default.createElement("canvas", { ref: k4, className: classes.pix, width: width, height: height }),
165
- model.mouseoverId && tooltip && currX && currY ? (react_1.default.createElement(SyntenyTooltip_1.default, { title: tooltip })) : null,
199
+ mouseoverId && tooltip && currX && currY ? (react_1.default.createElement(SyntenyTooltip_1.default, { title: tooltip })) : null,
166
200
  anchorEl ? (react_1.default.createElement(SyntenyContextMenu_1.default, { model: model, anchorEl: anchorEl, onClose: () => setAnchorEl(undefined) })) : null));
167
201
  });
168
- function onSyntenyClick(event, model) {
169
- const ref1 = model.clickMapCanvas;
170
- const ref2 = model.cigarClickMapCanvas;
171
- if (!ref1 || !ref2) {
172
- return;
173
- }
174
- const rect = ref1.getBoundingClientRect();
175
- const ctx1 = ref1.getContext('2d');
176
- const ctx2 = ref2.getContext('2d');
177
- if (!ctx1 || !ctx2) {
178
- return;
179
- }
180
- const x = event.clientX - rect.left;
181
- const y = event.clientY - rect.top;
182
- const [r1, g1, b1] = ctx1.getImageData(x, y, 1, 1).data;
183
- const unitMultiplier = Math.floor(drawSynteny_1.MAX_COLOR_RANGE / model.numFeats);
184
- const id = (0, drawSynteny_1.getId)(r1, g1, b1, unitMultiplier);
185
- const feat = model.featPositions[id];
186
- if (feat) {
187
- const { f } = feat;
188
- model.setClickId(f.id());
189
- const session = (0, util_1.getSession)(model);
190
- if ((0, util_1.isSessionModelWithWidgets)(session)) {
191
- session.showWidget(session.addWidget('SyntenyFeatureWidget', 'syntenyFeature', {
192
- featureData: {
193
- feature1: f.toJSON(),
194
- feature2: f.get('mate'),
195
- },
196
- }));
197
- }
198
- }
199
- return feat;
200
- }
201
- function onSyntenyContextClick(event, model, setAnchorEl) {
202
- event.preventDefault();
203
- const ref1 = model.clickMapCanvas;
204
- const ref2 = model.cigarClickMapCanvas;
205
- if (!ref1 || !ref2) {
206
- return;
207
- }
208
- const rect = ref1.getBoundingClientRect();
209
- const ctx1 = ref1.getContext('2d');
210
- const ctx2 = ref2.getContext('2d');
211
- if (!ctx1 || !ctx2) {
212
- return;
213
- }
214
- const { clientX, clientY } = event;
215
- const x = clientX - rect.left;
216
- const y = clientY - rect.top;
217
- const [r1, g1, b1] = ctx1.getImageData(x, y, 1, 1).data;
218
- const unitMultiplier = Math.floor(drawSynteny_1.MAX_COLOR_RANGE / model.numFeats);
219
- const id = (0, drawSynteny_1.getId)(r1, g1, b1, unitMultiplier);
220
- const f = model.featPositions[id];
221
- if (f) {
222
- model.setClickId(f.f.id());
223
- setAnchorEl({ clientX, clientY, feature: f });
224
- }
225
- }
226
- function getTooltip(f, cigarOp, cigarOpLen) {
227
- // @ts-expect-error
228
- const f1 = f.toJSON();
229
- const f2 = f1.mate;
230
- const l1 = f1.end - f1.start;
231
- const l2 = f2.end - f2.start;
232
- const identity = f1.identity;
233
- const n1 = f1.name;
234
- const n2 = f2.name;
235
- return [
236
- `Loc1: ${(0, util_1.assembleLocString)(f1)}`,
237
- `Loc2: ${(0, util_1.assembleLocString)(f2)}`,
238
- `Inverted: ${f1.strand === -1}`,
239
- `Query len: ${l1.toLocaleString('en-US')}`,
240
- `Target len: ${l2.toLocaleString('en-US')}`,
241
- identity ? `Identity: ${identity.toPrecision(2)}` : '',
242
- cigarOp ? `CIGAR operator: ${cigarOp}${cigarOpLen}` : '',
243
- n1 ? `Name 1: ${n1}` : '',
244
- n2 ? `Name 1: ${n2}` : '',
245
- ]
246
- .filter(f => !!f)
247
- .join('<br/>');
248
- }
249
202
  exports.default = LinearSyntenyRendering;
@@ -1,7 +1,14 @@
1
+ import React from 'react';
1
2
  import { Feature } from '@jbrowse/core/util';
3
+ import { LinearSyntenyDisplayModel } from '../model';
2
4
  interface Pos {
3
5
  offsetPx: number;
4
6
  }
7
+ export interface ClickCoord {
8
+ clientX: number;
9
+ clientY: number;
10
+ feature: any;
11
+ }
5
12
  interface FeatPos {
6
13
  p11: Pos;
7
14
  p12: Pos;
@@ -24,4 +31,7 @@ export declare function drawMatchSimple({ feature, ctx, offsets, cb, height, dra
24
31
  export declare function draw(ctx: CanvasRenderingContext2D, x1: number, x2: number, y1: number, x3: number, x4: number, y2: number, mid: number, drawCurves?: boolean): void;
25
32
  export declare function drawBox(ctx: CanvasRenderingContext2D, x1: number, x2: number, y1: number, x3: number, x4: number, y2: number): void;
26
33
  export declare function drawBezierBox(ctx: CanvasRenderingContext2D, x1: number, x2: number, y1: number, x3: number, x4: number, y2: number, mid: number): void;
34
+ export declare function onSynClick(event: React.MouseEvent, model: LinearSyntenyDisplayModel): import("../model").FeatPos | undefined;
35
+ export declare function onSynContextClick(event: React.MouseEvent, model: LinearSyntenyDisplayModel, setAnchorEl: (arg: ClickCoord) => void): void;
36
+ export declare function getTooltip(f: Feature, cigarOp?: string, cigarOpLen?: string): string;
27
37
  export {};
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.drawBezierBox = exports.drawBox = exports.draw = exports.drawMatchSimple = void 0;
3
+ exports.getTooltip = exports.onSynContextClick = exports.onSynClick = exports.drawBezierBox = exports.drawBox = exports.draw = exports.drawMatchSimple = void 0;
4
4
  const util_1 = require("@jbrowse/core/util");
5
+ // locals
6
+ const drawSynteny_1 = require("../drawSynteny");
5
7
  function drawMatchSimple({ feature, ctx, offsets, cb, height, drawCurves, oobLimit, viewWidth, hideTiny, }) {
6
8
  const { p11, p12, p21, p22 } = feature;
7
9
  const x11 = p11.offsetPx - offsets[0];
@@ -81,3 +83,87 @@ function drawBezierBox(ctx, x1, x2, y1, x3, x4, y2, mid) {
81
83
  ctx.fill();
82
84
  }
83
85
  exports.drawBezierBox = drawBezierBox;
86
+ function onSynClick(event, model) {
87
+ const ref1 = model.clickMapCanvas;
88
+ const ref2 = model.cigarClickMapCanvas;
89
+ if (!ref1 || !ref2) {
90
+ return;
91
+ }
92
+ const rect = ref1.getBoundingClientRect();
93
+ const ctx1 = ref1.getContext('2d');
94
+ const ctx2 = ref2.getContext('2d');
95
+ if (!ctx1 || !ctx2) {
96
+ return;
97
+ }
98
+ const x = event.clientX - rect.left;
99
+ const y = event.clientY - rect.top;
100
+ const [r1, g1, b1] = ctx1.getImageData(x, y, 1, 1).data;
101
+ const unitMultiplier = Math.floor(drawSynteny_1.MAX_COLOR_RANGE / model.numFeats);
102
+ const id = (0, drawSynteny_1.getId)(r1, g1, b1, unitMultiplier);
103
+ const feat = model.featPositions[id];
104
+ if (feat) {
105
+ const { f } = feat;
106
+ model.setClickId(f.id());
107
+ const session = (0, util_1.getSession)(model);
108
+ if ((0, util_1.isSessionModelWithWidgets)(session)) {
109
+ session.showWidget(session.addWidget('SyntenyFeatureWidget', 'syntenyFeature', {
110
+ featureData: {
111
+ feature1: f.toJSON(),
112
+ feature2: f.get('mate'),
113
+ },
114
+ }));
115
+ }
116
+ }
117
+ return feat;
118
+ }
119
+ exports.onSynClick = onSynClick;
120
+ function onSynContextClick(event, model, setAnchorEl) {
121
+ event.preventDefault();
122
+ const ref1 = model.clickMapCanvas;
123
+ const ref2 = model.cigarClickMapCanvas;
124
+ if (!ref1 || !ref2) {
125
+ return;
126
+ }
127
+ const rect = ref1.getBoundingClientRect();
128
+ const ctx1 = ref1.getContext('2d');
129
+ const ctx2 = ref2.getContext('2d');
130
+ if (!ctx1 || !ctx2) {
131
+ return;
132
+ }
133
+ const { clientX, clientY } = event;
134
+ const x = clientX - rect.left;
135
+ const y = clientY - rect.top;
136
+ const [r1, g1, b1] = ctx1.getImageData(x, y, 1, 1).data;
137
+ const unitMultiplier = Math.floor(drawSynteny_1.MAX_COLOR_RANGE / model.numFeats);
138
+ const id = (0, drawSynteny_1.getId)(r1, g1, b1, unitMultiplier);
139
+ const f = model.featPositions[id];
140
+ if (f) {
141
+ model.setClickId(f.f.id());
142
+ setAnchorEl({ clientX, clientY, feature: f });
143
+ }
144
+ }
145
+ exports.onSynContextClick = onSynContextClick;
146
+ function getTooltip(f, cigarOp, cigarOpLen) {
147
+ // @ts-expect-error
148
+ const f1 = f.toJSON();
149
+ const f2 = f1.mate;
150
+ const l1 = f1.end - f1.start;
151
+ const l2 = f2.end - f2.start;
152
+ const identity = f1.identity;
153
+ const n1 = f1.name;
154
+ const n2 = f2.name;
155
+ return [
156
+ `Loc1: ${(0, util_1.assembleLocString)(f1)}`,
157
+ `Loc2: ${(0, util_1.assembleLocString)(f2)}`,
158
+ `Inverted: ${f1.strand === -1}`,
159
+ `Query len: ${l1.toLocaleString('en-US')}`,
160
+ `Target len: ${l2.toLocaleString('en-US')}`,
161
+ identity ? `Identity: ${identity.toPrecision(2)}` : '',
162
+ cigarOp ? `CIGAR operator: ${cigarOp}${cigarOpLen}` : '',
163
+ n1 ? `Name 1: ${n1}` : '',
164
+ n2 ? `Name 1: ${n2}` : '',
165
+ ]
166
+ .filter(f => !!f)
167
+ .join('<br/>');
168
+ }
169
+ exports.getTooltip = getTooltip;
@@ -93,6 +93,7 @@ const LinearSyntenyViewImportForm = (0, mobx_react_1.observer)(function ({ model
93
93
  };
94
94
  })));
95
95
  model.views.forEach(view => view.setWidth(model.width));
96
+ model.views.forEach(view => view.showAllRegions());
96
97
  if (sessionTrackData) {
97
98
  session.addTrackConf(sessionTrackData);
98
99
  model.toggleTrack(sessionTrackData.trackId);