@jbrowse/plugin-circular-view 2.13.0 → 2.14.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 (33) hide show
  1. package/dist/BaseChordDisplay/components/Loading.js +6 -2
  2. package/dist/BaseChordDisplay/models/model.d.ts +4 -5
  3. package/dist/BaseChordDisplay/models/model.js +6 -21
  4. package/dist/BaseChordDisplay/models/renderReaction.js +2 -8
  5. package/dist/CircularView/components/Controls.js +6 -2
  6. package/dist/CircularView/components/ExportSvgDialog.js +13 -5
  7. package/dist/CircularView/components/ImportForm.d.ts +2 -1
  8. package/dist/CircularView/components/ImportForm.js +2 -3
  9. package/dist/CircularView/components/Ruler.js +1 -4
  10. package/dist/CircularView/models/model.d.ts +2 -6
  11. package/dist/CircularView/models/model.js +8 -11
  12. package/dist/CircularView/models/slices.d.ts +1 -1
  13. package/dist/CircularView/models/viewportVisibleRegion.d.ts +1 -1
  14. package/dist/CircularView/models/viewportVisibleRegion.js +5 -5
  15. package/dist/CircularView/svgcomponents/SVGCircularView.js +6 -3
  16. package/dist/LaunchCircularView/index.js +3 -1
  17. package/esm/BaseChordDisplay/components/Loading.js +6 -2
  18. package/esm/BaseChordDisplay/models/model.d.ts +4 -5
  19. package/esm/BaseChordDisplay/models/model.js +6 -21
  20. package/esm/BaseChordDisplay/models/renderReaction.js +2 -8
  21. package/esm/CircularView/components/Controls.js +6 -2
  22. package/esm/CircularView/components/ExportSvgDialog.js +13 -5
  23. package/esm/CircularView/components/ImportForm.d.ts +2 -1
  24. package/esm/CircularView/components/ImportForm.js +2 -3
  25. package/esm/CircularView/components/Ruler.js +1 -4
  26. package/esm/CircularView/models/model.d.ts +2 -6
  27. package/esm/CircularView/models/model.js +9 -12
  28. package/esm/CircularView/models/slices.d.ts +1 -1
  29. package/esm/CircularView/models/viewportVisibleRegion.d.ts +1 -1
  30. package/esm/CircularView/models/viewportVisibleRegion.js +5 -5
  31. package/esm/CircularView/svgcomponents/SVGCircularView.js +6 -3
  32. package/esm/LaunchCircularView/index.js +3 -1
  33. package/package.json +3 -3
@@ -73,8 +73,12 @@ const Loading = (0, mobx_react_1.observer)(function ({ model: { renderProps: { r
73
73
  // only show the loading message after 400ms to prevent excessive flickering
74
74
  const [shown, setShown] = (0, react_1.useState)(false);
75
75
  (0, react_1.useEffect)(() => {
76
- const timeout = setTimeout(() => setShown(true), 400);
77
- return () => clearTimeout(timeout);
76
+ const timeout = setTimeout(() => {
77
+ setShown(true);
78
+ }, 400);
79
+ return () => {
80
+ clearTimeout(timeout);
81
+ };
78
82
  });
79
83
  return !shown ? null : (react_1.default.createElement("g", null,
80
84
  react_1.default.createElement("defs", null,
@@ -42,7 +42,7 @@ export declare const BaseChordDisplayModel: import("mobx-state-tree").IModelType
42
42
  error: unknown;
43
43
  message: string | undefined;
44
44
  }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
45
- onHorizontalScroll?: Function;
45
+ onHorizontalScroll?: () => void;
46
46
  blockState?: Record<string, any>;
47
47
  }>;
48
48
  readonly DisplayBlurb: React.FC<{
@@ -103,10 +103,9 @@ export declare const BaseChordDisplayModel: import("mobx-state-tree").IModelType
103
103
  renderProps(): any;
104
104
  /**
105
105
  * #getter
106
- * the pluggable element type object for this display's
107
- * renderer
106
+ * the pluggable element type object for this display's renderer
108
107
  */
109
- readonly rendererType: RendererType;
108
+ readonly rendererType: RendererType | undefined;
110
109
  /**
111
110
  * #method
112
111
  */
@@ -147,6 +146,6 @@ export declare const BaseChordDisplayModel: import("mobx-state-tree").IModelType
147
146
  * #method
148
147
  */
149
148
  renderSvg(opts: ExportSvgOptions & {
150
- theme: ThemeOptions;
149
+ theme?: ThemeOptions;
151
150
  }): Promise<React.JSX.Element>;
152
151
  }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;
@@ -93,7 +93,6 @@ exports.BaseChordDisplayModel = mobx_state_tree_1.types
93
93
  return {
94
94
  ...(0, tracks_1.getParentRenderProps)(self),
95
95
  rpcDriverName: self.rpcDriverName,
96
- displayModel: self,
97
96
  bezierRadius: view.radiusPx * self.bezierRadiusRatio,
98
97
  radius: view.radiusPx,
99
98
  blockDefinitions: this.blockDefinitions,
@@ -102,20 +101,10 @@ exports.BaseChordDisplayModel = mobx_state_tree_1.types
102
101
  },
103
102
  /**
104
103
  * #getter
105
- * the pluggable element type object for this display's
106
- * renderer
104
+ * the pluggable element type object for this display's renderer
107
105
  */
108
106
  get rendererType() {
109
- const display = self;
110
- const { pluginManager } = (0, util_1.getEnv)(self);
111
- const ThisRendererType = pluginManager.getRendererType(self.rendererTypeName);
112
- if (!ThisRendererType) {
113
- throw new Error(`renderer "${display.rendererTypeName}" not found`);
114
- }
115
- if (!ThisRendererType.ReactComponent) {
116
- throw new Error(`renderer ${display.rendererTypeName} has no ReactComponent, it may not be completely implemented yet`);
117
- }
118
- return ThisRendererType;
107
+ return (0, util_1.getEnv)(self).pluginManager.getRendererType(self.rendererTypeName);
119
108
  },
120
109
  /**
121
110
  * #method
@@ -133,9 +122,6 @@ exports.BaseChordDisplayModel = mobx_state_tree_1.types
133
122
  return undefined;
134
123
  }
135
124
  const session = (0, util_1.getSession)(self);
136
- if (!session) {
137
- return undefined;
138
- }
139
125
  const { selection } = session;
140
126
  // does it quack like a feature?
141
127
  if ((0, util_1.isFeature)(selection)) {
@@ -212,17 +198,16 @@ exports.BaseChordDisplayModel = mobx_state_tree_1.types
212
198
  }, self.renderStarted, self.renderSuccess, self.renderError);
213
199
  (0, util_1.makeAbortableReaction)(self, () => ({
214
200
  assemblyNames: (0, tracks_1.getTrackAssemblyNames)(self.parentTrack),
215
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
216
201
  adapter: (0, configuration_1.getConf)((0, mobx_state_tree_1.getParent)(self, 2), 'adapter'),
217
202
  assemblyManager: (0, util_1.getSession)(self).assemblyManager,
218
- }),
219
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
220
- async ({ assemblyNames, adapter, assemblyManager }, signal) => {
203
+ }), async ({ assemblyNames, adapter, assemblyManager }, signal) => {
221
204
  return assemblyManager.getRefNameMapForAdapter(adapter, assemblyNames[0], { signal, sessionId: (0, tracks_1.getRpcSessionId)(self) });
222
205
  }, {
223
206
  name: `${self.type} ${self.id} getting refNames`,
224
207
  fireImmediately: true,
225
- }, () => { }, refNameMap => self.setRefNameMap(refNameMap), error => {
208
+ }, () => { }, refNameMap => {
209
+ self.setRefNameMap(refNameMap);
210
+ }, error => {
226
211
  console.error(error);
227
212
  self.setError(error);
228
213
  });
@@ -8,9 +8,7 @@ exports.renderReactionEffect = renderReactionEffect;
8
8
  const clone_1 = __importDefault(require("clone"));
9
9
  const tracks_1 = require("@jbrowse/core/util/tracks");
10
10
  const util_1 = require("@jbrowse/core/util");
11
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
12
11
  function renderReactionData(self) {
13
- var _a;
14
12
  const view = (0, util_1.getContainingView)(self);
15
13
  const { rendererType } = self;
16
14
  const { rpcManager } = (0, util_1.getSession)(view);
@@ -19,7 +17,7 @@ function renderReactionData(self) {
19
17
  rpcManager,
20
18
  renderProps: self.renderProps(),
21
19
  renderArgs: {
22
- assemblyName: (_a = view.displayedRegions[0]) === null || _a === void 0 ? void 0 : _a.assemblyName,
20
+ assemblyName: view.displayedRegions[0].assemblyName,
23
21
  adapterConfig: (0, clone_1.default)(self.adapterConfig),
24
22
  rendererType: rendererType.name,
25
23
  regions: (0, clone_1.default)(view.displayedRegions),
@@ -29,11 +27,7 @@ function renderReactionData(self) {
29
27
  },
30
28
  };
31
29
  }
32
- async function renderReactionEffect(
33
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
34
- props, signal,
35
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
36
- self) {
30
+ async function renderReactionEffect(props, signal, self) {
37
31
  var _a;
38
32
  if (!props) {
39
33
  throw new Error('cannot render with no props');
@@ -67,7 +67,9 @@ const Controls = (0, mobx_react_1.observer)(function ({ model }) {
67
67
  react_1.default.createElement(material_1.IconButton, { onClick: model.toggleFitToWindowLock, title: model.lockedFitToWindow
68
68
  ? 'locked model to window size'
69
69
  : 'unlocked model to zoom further', disabled: model.tooSmallToLock }, model.lockedFitToWindow ? react_1.default.createElement(Lock_1.default, null) : react_1.default.createElement(LockOpen_1.default, null)),
70
- react_1.default.createElement(material_1.IconButton, { onClick: event => setAnchorEl(event.currentTarget) },
70
+ react_1.default.createElement(material_1.IconButton, { onClick: event => {
71
+ setAnchorEl(event.currentTarget);
72
+ } },
71
73
  react_1.default.createElement(MoreVert_1.default, null)),
72
74
  model.hideTrackSelectorButton ? null : (react_1.default.createElement(material_1.IconButton, { onClick: model.activateTrackSelector, title: "Open track selector", "data-testid": "circular_track_select" },
73
75
  react_1.default.createElement(Icons_1.TrackSelector, null))),
@@ -85,6 +87,8 @@ const Controls = (0, mobx_react_1.observer)(function ({ model }) {
85
87
  ], onMenuItemClick: (_event, callback) => {
86
88
  callback();
87
89
  setAnchorEl(null);
88
- }, open: Boolean(anchorEl), onClose: () => setAnchorEl(null) })) : null));
90
+ }, open: Boolean(anchorEl), onClose: () => {
91
+ setAnchorEl(null);
92
+ } })) : null));
89
93
  });
90
94
  exports.default = Controls;
@@ -38,7 +38,7 @@ function TextField2({ children, ...rest }) {
38
38
  react_1.default.createElement(material_1.TextField, { ...rest }, children)));
39
39
  }
40
40
  function useSvgLocal(key, val) {
41
- return (0, util_1.useLocalStorage)('svg-' + key, val);
41
+ return (0, util_1.useLocalStorage)(`svg-${key}`, val);
42
42
  }
43
43
  function ExportSvgDialog({ model, handleClose, }) {
44
44
  const session = (0, util_1.getSession)(model);
@@ -51,13 +51,21 @@ function ExportSvgDialog({ model, handleClose, }) {
51
51
  return (react_1.default.createElement(ui_1.Dialog, { open: true, onClose: handleClose, title: "Export SVG" },
52
52
  react_1.default.createElement(material_1.DialogContent, null,
53
53
  error ? (react_1.default.createElement(ui_1.ErrorMessage, { error: error })) : loading ? (react_1.default.createElement(LoadingMessage, null)) : null,
54
- react_1.default.createElement(TextField2, { helperText: "filename", value: filename, onChange: event => setFilename(event.target.value) }),
55
- session.allThemes ? (react_1.default.createElement(TextField2, { select: true, label: "Theme", value: themeName, onChange: event => setThemeName(event.target.value) }, Object.entries(session.allThemes()).map(([key, val]) => (react_1.default.createElement(material_1.MenuItem, { key: key, value: key },
54
+ react_1.default.createElement(TextField2, { helperText: "filename", value: filename, onChange: event => {
55
+ setFilename(event.target.value);
56
+ } }),
57
+ session.allThemes ? (react_1.default.createElement(TextField2, { select: true, label: "Theme", value: themeName, onChange: event => {
58
+ setThemeName(event.target.value);
59
+ } }, Object.entries(session.allThemes()).map(([key, val]) => (react_1.default.createElement(material_1.MenuItem, { key: key, value: key },
56
60
  // @ts-expect-error
57
61
  val.name || '(Unknown name)'))))) : null,
58
- offscreenCanvas ? (react_1.default.createElement(material_1.FormControlLabel, { control: react_1.default.createElement(material_1.Checkbox, { checked: rasterizeLayers, onChange: () => setRasterizeLayers(val => !val) }), label: "Rasterize canvas based tracks? File may be much larger if this is turned off" })) : (react_1.default.createElement(material_1.Typography, null, "Note: rasterizing layers not yet supported in this browser, so SVG size may be large"))),
62
+ offscreenCanvas ? (react_1.default.createElement(material_1.FormControlLabel, { control: react_1.default.createElement(material_1.Checkbox, { checked: rasterizeLayers, onChange: () => {
63
+ setRasterizeLayers(val => !val);
64
+ } }), label: "Rasterize canvas based tracks? File may be much larger if this is turned off" })) : (react_1.default.createElement(material_1.Typography, null, "Note: rasterizing layers not yet supported in this browser, so SVG size may be large"))),
59
65
  react_1.default.createElement(material_1.DialogActions, null,
60
- react_1.default.createElement(material_1.Button, { variant: "contained", color: "secondary", onClick: () => handleClose() }, "Cancel"),
66
+ react_1.default.createElement(material_1.Button, { variant: "contained", color: "secondary", onClick: () => {
67
+ handleClose();
68
+ } }, "Cancel"),
61
69
  react_1.default.createElement(material_1.Button, { variant: "contained", color: "primary", type: "submit", onClick: async () => {
62
70
  setLoading(true);
63
71
  setError(undefined);
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
+ import { CircularViewModel } from '../models/model';
2
3
  declare const ImportForm: ({ model }: {
3
- model: any;
4
+ model: CircularViewModel;
4
5
  }) => React.JSX.Element;
5
6
  export default ImportForm;
@@ -34,8 +34,7 @@ const useStyles = (0, mui_1.makeStyles)()(theme => ({
34
34
  padding: theme.spacing(6),
35
35
  },
36
36
  }));
37
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
38
- const ImportForm = (0, mobx_react_1.observer)(({ model }) => {
37
+ const ImportForm = (0, mobx_react_1.observer)(function ({ model }) {
39
38
  const { classes } = useStyles();
40
39
  const session = (0, util_1.getSession)(model);
41
40
  const { error } = model;
@@ -58,7 +57,7 @@ const ImportForm = (0, mobx_react_1.observer)(({ model }) => {
58
57
  setSelectedAsm(val);
59
58
  }, session: session, selected: selectedAsm })),
60
59
  react_1.default.createElement(material_1.Grid, { item: true },
61
- react_1.default.createElement(material_1.Button, { disabled: !(regions === null || regions === void 0 ? void 0 : regions.length), onClick: () => {
60
+ react_1.default.createElement(material_1.Button, { disabled: !regions.length, onClick: () => {
62
61
  model.setError(undefined);
63
62
  model.setDisplayedRegions(regions);
64
63
  }, variant: "contained", color: "primary" }, regions.length || err ? 'Open' : 'Loading...')))));
@@ -99,11 +99,8 @@ const RegionRulerArc = (0, mobx_react_1.observer)(function ({ model, slice, regi
99
99
  const centerRadians = (endRadians + startRadians) / 2;
100
100
  const widthPx = (endRadians - startRadians) * radiusPx;
101
101
  const session = (0, util_1.getSession)(model);
102
- let color;
103
102
  const assembly = session.assemblyManager.get(region.assemblyName);
104
- if (assembly) {
105
- color = assembly.getRefNameColor(region.refName);
106
- }
103
+ let color = assembly ? assembly.getRefNameColor(region.refName) : undefined;
107
104
  if (color) {
108
105
  try {
109
106
  color = (0, color_1.makeContrasting)(color, theme.palette.background.paper);
@@ -136,8 +136,8 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
136
136
  readonly figureHeight: number;
137
137
  /**
138
138
  * #getter
139
- * this is displayedRegions, post-processed to
140
- * elide regions that are too small to see reasonably
139
+ * this is displayedRegions, post-processed to elide regions that are too
140
+ * small to see reasonably
141
141
  */
142
142
  readonly elidedRegions: SliceRegion[];
143
143
  /**
@@ -207,10 +207,6 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
207
207
  * #action
208
208
  */
209
209
  setModelViewWhenAdjust(secondCondition: boolean): void;
210
- /**
211
- * #action
212
- */
213
- closeView(): void;
214
210
  /**
215
211
  * #action
216
212
  */
@@ -261,8 +261,8 @@ function stateModelFactory(pluginManager) {
261
261
  },
262
262
  /**
263
263
  * #getter
264
- * this is displayedRegions, post-processed to
265
- * elide regions that are too small to see reasonably
264
+ * this is displayedRegions, post-processed to elide regions that are too
265
+ * small to see reasonably
266
266
  */
267
267
  get elidedRegions() {
268
268
  const visible = [];
@@ -418,13 +418,6 @@ function stateModelFactory(pluginManager) {
418
418
  this.setBpPerPx(self.minBpPerPx);
419
419
  }
420
420
  },
421
- /**
422
- * #action
423
- */
424
- closeView() {
425
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
426
- (0, mobx_state_tree_1.getParent)(self, 2).removeView(self);
427
- },
428
421
  /**
429
422
  * #action
430
423
  */
@@ -518,7 +511,9 @@ function stateModelFactory(pluginManager) {
518
511
  const schema = pluginManager.pluggableConfigSchemaType('track');
519
512
  const conf = (0, mobx_state_tree_1.resolveIdentifier)(schema, (0, mobx_state_tree_1.getRoot)(self), trackId);
520
513
  const t = self.tracks.filter(t => t.configuration === conf);
521
- (0, mobx_1.transaction)(() => t.forEach(t => self.tracks.remove(t)));
514
+ (0, mobx_1.transaction)(() => {
515
+ t.forEach(t => self.tracks.remove(t));
516
+ });
522
517
  return t.length;
523
518
  },
524
519
  /**
@@ -551,7 +546,9 @@ function stateModelFactory(pluginManager) {
551
546
  return [
552
547
  {
553
548
  label: 'Return to import form',
554
- onClick: () => self.setDisplayedRegions([]),
549
+ onClick: () => {
550
+ self.setDisplayedRegions([]);
551
+ },
555
552
  icon: FolderOpen_1.default,
556
553
  },
557
554
  {
@@ -31,7 +31,7 @@ export declare class Slice {
31
31
  };
32
32
  }
33
33
  declare function calculateStaticSlices(self: {
34
- elidedRegions: SliceRegion[];
34
+ elidedRegions: readonly SliceRegion[];
35
35
  bpPerRadian: number;
36
36
  spacingPx: number;
37
37
  pxPerRadian: number;
@@ -1,4 +1,4 @@
1
- export declare function cartesianToPolar(x: number, y: number): number[];
1
+ export declare function cartesianToPolar(x: number, y: number): readonly [number, number];
2
2
  export declare function thetaRangesOverlap(r1start: number, r1length: number, r2start: number, r2length: number): boolean;
3
3
  export declare function viewportVisibleSection(viewSides: [number, number, number, number], circleCenter: [number, number], circleRadius: number): {
4
4
  rho: [number, number];
@@ -85,7 +85,7 @@ function viewportVisibleSection(viewSides, circleCenter, circleRadius) {
85
85
  [viewL, viewB],
86
86
  [viewR, viewB],
87
87
  ];
88
- let maxRho = -Infinity;
88
+ let maxRho = Number.NEGATIVE_INFINITY;
89
89
  for (const [x, y] of vertices) {
90
90
  const rho = Math.sqrt(x * x + y * y);
91
91
  if (rho > maxRho) {
@@ -182,10 +182,10 @@ function viewportVisibleSection(viewSides, circleCenter, circleRadius) {
182
182
  // viewportCenterTheta < Math.PI / 2 || viewportCenterTheta > 1.5 * Math.PI
183
183
  // ? -1
184
184
  // : 1
185
- let rhoMin = Infinity;
186
- let rhoMax = -Infinity;
187
- let thetaMin = Infinity;
188
- let thetaMax = -Infinity;
185
+ let rhoMin = Number.POSITIVE_INFINITY;
186
+ let rhoMax = Number.NEGATIVE_INFINITY;
187
+ let thetaMin = Number.POSITIVE_INFINITY;
188
+ let thetaMax = Number.NEGATIVE_INFINITY;
189
189
  for (const [vx, vy] of vertices) {
190
190
  // ignore vertex if outside the viewport
191
191
  if (vx >= viewL && vx <= viewR && vy >= viewT && vy <= viewB) {
@@ -18,7 +18,6 @@ async function renderToSvg(model, opts) {
18
18
  const { themeName = 'default', Wrapper = ({ children }) => children } = opts;
19
19
  const session = (0, util_1.getSession)(model);
20
20
  const theme = (_a = session.allThemes) === null || _a === void 0 ? void 0 : _a.call(session)[themeName];
21
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
21
  const { createRootFn } = (0, mobx_state_tree_1.getRoot)(model);
23
22
  const { width, tracks, height } = model;
24
23
  const shift = 50;
@@ -35,6 +34,10 @@ async function renderToSvg(model, opts) {
35
34
  react_1.default.createElement("svg", { width: width, height: height, xmlns: "http://www.w3.org/2000/svg", xmlnsXlink: "http://www.w3.org/1999/xlink", viewBox: [0, 0, width + shift * 2, height].toString() },
36
35
  react_1.default.createElement(SVGBackground_1.default, { width: width, height: height, shift: shift }),
37
36
  react_1.default.createElement("g", { transform: `translate(${centerXY}) rotate(${deg})` },
38
- staticSlices.map((slice, i) => (react_1.default.createElement(Ruler_1.default, { key: i, model: model, slice: slice }))),
39
- displayResults.map(({ result }, i) => (react_1.default.createElement(react_1.default.Fragment, { key: i }, result))))))), createRootFn);
37
+ staticSlices.map((slice, i) => (
38
+ /* biome-ignore lint/suspicious/noArrayIndexKey: */
39
+ react_1.default.createElement(Ruler_1.default, { key: i, model: model, slice: slice }))),
40
+ displayResults.map(({ result }, i) => (
41
+ /* biome-ignore lint/suspicious/noArrayIndexKey: */
42
+ react_1.default.createElement(react_1.default.Fragment, { key: i }, result))))))), createRootFn);
40
43
  }
@@ -17,6 +17,8 @@ function LaunchCircularViewF(pluginManager) {
17
17
  throw new Error(`Assembly "${assembly}" not found when launching circular genome view`);
18
18
  }
19
19
  view.setDisplayedRegions(asm.regions || []);
20
- tracks.forEach(track => view.showTrack(track));
20
+ tracks.forEach(track => {
21
+ view.showTrack(track);
22
+ });
21
23
  });
22
24
  }
@@ -48,8 +48,12 @@ const Loading = observer(function ({ model: { renderProps: { radius }, }, }) {
48
48
  // only show the loading message after 400ms to prevent excessive flickering
49
49
  const [shown, setShown] = useState(false);
50
50
  useEffect(() => {
51
- const timeout = setTimeout(() => setShown(true), 400);
52
- return () => clearTimeout(timeout);
51
+ const timeout = setTimeout(() => {
52
+ setShown(true);
53
+ }, 400);
54
+ return () => {
55
+ clearTimeout(timeout);
56
+ };
53
57
  });
54
58
  return !shown ? null : (React.createElement("g", null,
55
59
  React.createElement("defs", null,
@@ -42,7 +42,7 @@ export declare const BaseChordDisplayModel: import("mobx-state-tree").IModelType
42
42
  error: unknown;
43
43
  message: string | undefined;
44
44
  }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
45
- onHorizontalScroll?: Function;
45
+ onHorizontalScroll?: () => void;
46
46
  blockState?: Record<string, any>;
47
47
  }>;
48
48
  readonly DisplayBlurb: React.FC<{
@@ -103,10 +103,9 @@ export declare const BaseChordDisplayModel: import("mobx-state-tree").IModelType
103
103
  renderProps(): any;
104
104
  /**
105
105
  * #getter
106
- * the pluggable element type object for this display's
107
- * renderer
106
+ * the pluggable element type object for this display's renderer
108
107
  */
109
- readonly rendererType: RendererType;
108
+ readonly rendererType: RendererType | undefined;
110
109
  /**
111
110
  * #method
112
111
  */
@@ -147,6 +146,6 @@ export declare const BaseChordDisplayModel: import("mobx-state-tree").IModelType
147
146
  * #method
148
147
  */
149
148
  renderSvg(opts: ExportSvgOptions & {
150
- theme: ThemeOptions;
149
+ theme?: ThemeOptions;
151
150
  }): Promise<React.JSX.Element>;
152
151
  }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;
@@ -87,7 +87,6 @@ export const BaseChordDisplayModel = types
87
87
  return {
88
88
  ...getParentRenderProps(self),
89
89
  rpcDriverName: self.rpcDriverName,
90
- displayModel: self,
91
90
  bezierRadius: view.radiusPx * self.bezierRadiusRatio,
92
91
  radius: view.radiusPx,
93
92
  blockDefinitions: this.blockDefinitions,
@@ -96,20 +95,10 @@ export const BaseChordDisplayModel = types
96
95
  },
97
96
  /**
98
97
  * #getter
99
- * the pluggable element type object for this display's
100
- * renderer
98
+ * the pluggable element type object for this display's renderer
101
99
  */
102
100
  get rendererType() {
103
- const display = self;
104
- const { pluginManager } = getEnv(self);
105
- const ThisRendererType = pluginManager.getRendererType(self.rendererTypeName);
106
- if (!ThisRendererType) {
107
- throw new Error(`renderer "${display.rendererTypeName}" not found`);
108
- }
109
- if (!ThisRendererType.ReactComponent) {
110
- throw new Error(`renderer ${display.rendererTypeName} has no ReactComponent, it may not be completely implemented yet`);
111
- }
112
- return ThisRendererType;
101
+ return getEnv(self).pluginManager.getRendererType(self.rendererTypeName);
113
102
  },
114
103
  /**
115
104
  * #method
@@ -127,9 +116,6 @@ export const BaseChordDisplayModel = types
127
116
  return undefined;
128
117
  }
129
118
  const session = getSession(self);
130
- if (!session) {
131
- return undefined;
132
- }
133
119
  const { selection } = session;
134
120
  // does it quack like a feature?
135
121
  if (isFeature(selection)) {
@@ -206,17 +192,16 @@ export const BaseChordDisplayModel = types
206
192
  }, self.renderStarted, self.renderSuccess, self.renderError);
207
193
  makeAbortableReaction(self, () => ({
208
194
  assemblyNames: getTrackAssemblyNames(self.parentTrack),
209
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
210
195
  adapter: getConf(getParent(self, 2), 'adapter'),
211
196
  assemblyManager: getSession(self).assemblyManager,
212
- }),
213
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
214
- async ({ assemblyNames, adapter, assemblyManager }, signal) => {
197
+ }), async ({ assemblyNames, adapter, assemblyManager }, signal) => {
215
198
  return assemblyManager.getRefNameMapForAdapter(adapter, assemblyNames[0], { signal, sessionId: getRpcSessionId(self) });
216
199
  }, {
217
200
  name: `${self.type} ${self.id} getting refNames`,
218
201
  fireImmediately: true,
219
- }, () => { }, refNameMap => self.setRefNameMap(refNameMap), error => {
202
+ }, () => { }, refNameMap => {
203
+ self.setRefNameMap(refNameMap);
204
+ }, error => {
220
205
  console.error(error);
221
206
  self.setError(error);
222
207
  });
@@ -1,9 +1,7 @@
1
1
  import clone from 'clone';
2
2
  import { getRpcSessionId } from '@jbrowse/core/util/tracks';
3
3
  import { getSession, getContainingView } from '@jbrowse/core/util';
4
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
5
4
  export function renderReactionData(self) {
6
- var _a;
7
5
  const view = getContainingView(self);
8
6
  const { rendererType } = self;
9
7
  const { rpcManager } = getSession(view);
@@ -12,7 +10,7 @@ export function renderReactionData(self) {
12
10
  rpcManager,
13
11
  renderProps: self.renderProps(),
14
12
  renderArgs: {
15
- assemblyName: (_a = view.displayedRegions[0]) === null || _a === void 0 ? void 0 : _a.assemblyName,
13
+ assemblyName: view.displayedRegions[0].assemblyName,
16
14
  adapterConfig: clone(self.adapterConfig),
17
15
  rendererType: rendererType.name,
18
16
  regions: clone(view.displayedRegions),
@@ -22,11 +20,7 @@ export function renderReactionData(self) {
22
20
  },
23
21
  };
24
22
  }
25
- export async function renderReactionEffect(
26
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
27
- props, signal,
28
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
29
- self) {
23
+ export async function renderReactionEffect(props, signal, self) {
30
24
  var _a;
31
25
  if (!props) {
32
26
  throw new Error('cannot render with no props');
@@ -39,7 +39,9 @@ const Controls = observer(function ({ model }) {
39
39
  React.createElement(IconButton, { onClick: model.toggleFitToWindowLock, title: model.lockedFitToWindow
40
40
  ? 'locked model to window size'
41
41
  : 'unlocked model to zoom further', disabled: model.tooSmallToLock }, model.lockedFitToWindow ? React.createElement(LockIcon, null) : React.createElement(LockOpenIcon, null)),
42
- React.createElement(IconButton, { onClick: event => setAnchorEl(event.currentTarget) },
42
+ React.createElement(IconButton, { onClick: event => {
43
+ setAnchorEl(event.currentTarget);
44
+ } },
43
45
  React.createElement(MoreVert, null)),
44
46
  model.hideTrackSelectorButton ? null : (React.createElement(IconButton, { onClick: model.activateTrackSelector, title: "Open track selector", "data-testid": "circular_track_select" },
45
47
  React.createElement(TrackSelectorIcon, null))),
@@ -57,6 +59,8 @@ const Controls = observer(function ({ model }) {
57
59
  ], onMenuItemClick: (_event, callback) => {
58
60
  callback();
59
61
  setAnchorEl(null);
60
- }, open: Boolean(anchorEl), onClose: () => setAnchorEl(null) })) : null));
62
+ }, open: Boolean(anchorEl), onClose: () => {
63
+ setAnchorEl(null);
64
+ } })) : null));
61
65
  });
62
66
  export default Controls;
@@ -12,7 +12,7 @@ function TextField2({ children, ...rest }) {
12
12
  React.createElement(TextField, { ...rest }, children)));
13
13
  }
14
14
  function useSvgLocal(key, val) {
15
- return useLocalStorage('svg-' + key, val);
15
+ return useLocalStorage(`svg-${key}`, val);
16
16
  }
17
17
  export default function ExportSvgDialog({ model, handleClose, }) {
18
18
  const session = getSession(model);
@@ -25,13 +25,21 @@ export default function ExportSvgDialog({ model, handleClose, }) {
25
25
  return (React.createElement(Dialog, { open: true, onClose: handleClose, title: "Export SVG" },
26
26
  React.createElement(DialogContent, null,
27
27
  error ? (React.createElement(ErrorMessage, { error: error })) : loading ? (React.createElement(LoadingMessage, null)) : null,
28
- React.createElement(TextField2, { helperText: "filename", value: filename, onChange: event => setFilename(event.target.value) }),
29
- session.allThemes ? (React.createElement(TextField2, { select: true, label: "Theme", value: themeName, onChange: event => setThemeName(event.target.value) }, Object.entries(session.allThemes()).map(([key, val]) => (React.createElement(MenuItem, { key: key, value: key },
28
+ React.createElement(TextField2, { helperText: "filename", value: filename, onChange: event => {
29
+ setFilename(event.target.value);
30
+ } }),
31
+ session.allThemes ? (React.createElement(TextField2, { select: true, label: "Theme", value: themeName, onChange: event => {
32
+ setThemeName(event.target.value);
33
+ } }, Object.entries(session.allThemes()).map(([key, val]) => (React.createElement(MenuItem, { key: key, value: key },
30
34
  // @ts-expect-error
31
35
  val.name || '(Unknown name)'))))) : null,
32
- offscreenCanvas ? (React.createElement(FormControlLabel, { control: React.createElement(Checkbox, { checked: rasterizeLayers, onChange: () => setRasterizeLayers(val => !val) }), label: "Rasterize canvas based tracks? File may be much larger if this is turned off" })) : (React.createElement(Typography, null, "Note: rasterizing layers not yet supported in this browser, so SVG size may be large"))),
36
+ offscreenCanvas ? (React.createElement(FormControlLabel, { control: React.createElement(Checkbox, { checked: rasterizeLayers, onChange: () => {
37
+ setRasterizeLayers(val => !val);
38
+ } }), label: "Rasterize canvas based tracks? File may be much larger if this is turned off" })) : (React.createElement(Typography, null, "Note: rasterizing layers not yet supported in this browser, so SVG size may be large"))),
33
39
  React.createElement(DialogActions, null,
34
- React.createElement(Button, { variant: "contained", color: "secondary", onClick: () => handleClose() }, "Cancel"),
40
+ React.createElement(Button, { variant: "contained", color: "secondary", onClick: () => {
41
+ handleClose();
42
+ } }, "Cancel"),
35
43
  React.createElement(Button, { variant: "contained", color: "primary", type: "submit", onClick: async () => {
36
44
  setLoading(true);
37
45
  setError(undefined);
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
+ import { CircularViewModel } from '../models/model';
2
3
  declare const ImportForm: ({ model }: {
3
- model: any;
4
+ model: CircularViewModel;
4
5
  }) => React.JSX.Element;
5
6
  export default ImportForm;
@@ -9,8 +9,7 @@ const useStyles = makeStyles()(theme => ({
9
9
  padding: theme.spacing(6),
10
10
  },
11
11
  }));
12
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
- const ImportForm = observer(({ model }) => {
12
+ const ImportForm = observer(function ({ model }) {
14
13
  const { classes } = useStyles();
15
14
  const session = getSession(model);
16
15
  const { error } = model;
@@ -33,7 +32,7 @@ const ImportForm = observer(({ model }) => {
33
32
  setSelectedAsm(val);
34
33
  }, session: session, selected: selectedAsm })),
35
34
  React.createElement(Grid, { item: true },
36
- React.createElement(Button, { disabled: !(regions === null || regions === void 0 ? void 0 : regions.length), onClick: () => {
35
+ React.createElement(Button, { disabled: !regions.length, onClick: () => {
37
36
  model.setError(undefined);
38
37
  model.setDisplayedRegions(regions);
39
38
  }, variant: "contained", color: "primary" }, regions.length || err ? 'Open' : 'Loading...')))));
@@ -94,11 +94,8 @@ const RegionRulerArc = observer(function ({ model, slice, region, }) {
94
94
  const centerRadians = (endRadians + startRadians) / 2;
95
95
  const widthPx = (endRadians - startRadians) * radiusPx;
96
96
  const session = getSession(model);
97
- let color;
98
97
  const assembly = session.assemblyManager.get(region.assemblyName);
99
- if (assembly) {
100
- color = assembly.getRefNameColor(region.refName);
101
- }
98
+ let color = assembly ? assembly.getRefNameColor(region.refName) : undefined;
102
99
  if (color) {
103
100
  try {
104
101
  color = makeContrasting(color, theme.palette.background.paper);
@@ -136,8 +136,8 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
136
136
  readonly figureHeight: number;
137
137
  /**
138
138
  * #getter
139
- * this is displayedRegions, post-processed to
140
- * elide regions that are too small to see reasonably
139
+ * this is displayedRegions, post-processed to elide regions that are too
140
+ * small to see reasonably
141
141
  */
142
142
  readonly elidedRegions: SliceRegion[];
143
143
  /**
@@ -207,10 +207,6 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
207
207
  * #action
208
208
  */
209
209
  setModelViewWhenAdjust(secondCondition: boolean): void;
210
- /**
211
- * #action
212
- */
213
- closeView(): void;
214
210
  /**
215
211
  * #action
216
212
  */
@@ -1,5 +1,5 @@
1
1
  import { lazy } from 'react';
2
- import { cast, getParent, getRoot, resolveIdentifier, types, } from 'mobx-state-tree';
2
+ import { cast, getRoot, resolveIdentifier, types, } from 'mobx-state-tree';
3
3
  import { Region } from '@jbrowse/core/util/types/mst';
4
4
  import { transaction } from 'mobx';
5
5
  import { saveAs } from 'file-saver';
@@ -233,8 +233,8 @@ function stateModelFactory(pluginManager) {
233
233
  },
234
234
  /**
235
235
  * #getter
236
- * this is displayedRegions, post-processed to
237
- * elide regions that are too small to see reasonably
236
+ * this is displayedRegions, post-processed to elide regions that are too
237
+ * small to see reasonably
238
238
  */
239
239
  get elidedRegions() {
240
240
  const visible = [];
@@ -390,13 +390,6 @@ function stateModelFactory(pluginManager) {
390
390
  this.setBpPerPx(self.minBpPerPx);
391
391
  }
392
392
  },
393
- /**
394
- * #action
395
- */
396
- closeView() {
397
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
398
- getParent(self, 2).removeView(self);
399
- },
400
393
  /**
401
394
  * #action
402
395
  */
@@ -490,7 +483,9 @@ function stateModelFactory(pluginManager) {
490
483
  const schema = pluginManager.pluggableConfigSchemaType('track');
491
484
  const conf = resolveIdentifier(schema, getRoot(self), trackId);
492
485
  const t = self.tracks.filter(t => t.configuration === conf);
493
- transaction(() => t.forEach(t => self.tracks.remove(t)));
486
+ transaction(() => {
487
+ t.forEach(t => self.tracks.remove(t));
488
+ });
494
489
  return t.length;
495
490
  },
496
491
  /**
@@ -523,7 +518,9 @@ function stateModelFactory(pluginManager) {
523
518
  return [
524
519
  {
525
520
  label: 'Return to import form',
526
- onClick: () => self.setDisplayedRegions([]),
521
+ onClick: () => {
522
+ self.setDisplayedRegions([]);
523
+ },
527
524
  icon: FolderOpenIcon,
528
525
  },
529
526
  {
@@ -31,7 +31,7 @@ export declare class Slice {
31
31
  };
32
32
  }
33
33
  declare function calculateStaticSlices(self: {
34
- elidedRegions: SliceRegion[];
34
+ elidedRegions: readonly SliceRegion[];
35
35
  bpPerRadian: number;
36
36
  spacingPx: number;
37
37
  pxPerRadian: number;
@@ -1,4 +1,4 @@
1
- export declare function cartesianToPolar(x: number, y: number): number[];
1
+ export declare function cartesianToPolar(x: number, y: number): readonly [number, number];
2
2
  export declare function thetaRangesOverlap(r1start: number, r1length: number, r2start: number, r2length: number): boolean;
3
3
  export declare function viewportVisibleSection(viewSides: [number, number, number, number], circleCenter: [number, number], circleRadius: number): {
4
4
  rho: [number, number];
@@ -80,7 +80,7 @@ export function viewportVisibleSection(viewSides, circleCenter, circleRadius) {
80
80
  [viewL, viewB],
81
81
  [viewR, viewB],
82
82
  ];
83
- let maxRho = -Infinity;
83
+ let maxRho = Number.NEGATIVE_INFINITY;
84
84
  for (const [x, y] of vertices) {
85
85
  const rho = Math.sqrt(x * x + y * y);
86
86
  if (rho > maxRho) {
@@ -177,10 +177,10 @@ export function viewportVisibleSection(viewSides, circleCenter, circleRadius) {
177
177
  // viewportCenterTheta < Math.PI / 2 || viewportCenterTheta > 1.5 * Math.PI
178
178
  // ? -1
179
179
  // : 1
180
- let rhoMin = Infinity;
181
- let rhoMax = -Infinity;
182
- let thetaMin = Infinity;
183
- let thetaMax = -Infinity;
180
+ let rhoMin = Number.POSITIVE_INFINITY;
181
+ let rhoMax = Number.NEGATIVE_INFINITY;
182
+ let thetaMin = Number.POSITIVE_INFINITY;
183
+ let thetaMax = Number.NEGATIVE_INFINITY;
184
184
  for (const [vx, vy] of vertices) {
185
185
  // ignore vertex if outside the viewport
186
186
  if (vx >= viewL && vx <= viewR && vy >= viewT && vy <= viewB) {
@@ -12,7 +12,6 @@ export async function renderToSvg(model, opts) {
12
12
  const { themeName = 'default', Wrapper = ({ children }) => children } = opts;
13
13
  const session = getSession(model);
14
14
  const theme = (_a = session.allThemes) === null || _a === void 0 ? void 0 : _a.call(session)[themeName];
15
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
16
15
  const { createRootFn } = getRoot(model);
17
16
  const { width, tracks, height } = model;
18
17
  const shift = 50;
@@ -29,6 +28,10 @@ export async function renderToSvg(model, opts) {
29
28
  React.createElement("svg", { width: width, height: height, xmlns: "http://www.w3.org/2000/svg", xmlnsXlink: "http://www.w3.org/1999/xlink", viewBox: [0, 0, width + shift * 2, height].toString() },
30
29
  React.createElement(SVGBackground, { width: width, height: height, shift: shift }),
31
30
  React.createElement("g", { transform: `translate(${centerXY}) rotate(${deg})` },
32
- staticSlices.map((slice, i) => (React.createElement(Ruler, { key: i, model: model, slice: slice }))),
33
- displayResults.map(({ result }, i) => (React.createElement(React.Fragment, { key: i }, result))))))), createRootFn);
31
+ staticSlices.map((slice, i) => (
32
+ /* biome-ignore lint/suspicious/noArrayIndexKey: */
33
+ React.createElement(Ruler, { key: i, model: model, slice: slice }))),
34
+ displayResults.map(({ result }, i) => (
35
+ /* biome-ignore lint/suspicious/noArrayIndexKey: */
36
+ React.createElement(React.Fragment, { key: i }, result))))))), createRootFn);
34
37
  }
@@ -14,6 +14,8 @@ export default function LaunchCircularViewF(pluginManager) {
14
14
  throw new Error(`Assembly "${assembly}" not found when launching circular genome view`);
15
15
  }
16
16
  view.setDisplayedRegions(asm.regions || []);
17
- tracks.forEach(track => view.showTrack(track));
17
+ tracks.forEach(track => {
18
+ view.showTrack(track);
19
+ });
18
20
  });
19
21
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/plugin-circular-view",
3
- "version": "2.13.0",
3
+ "version": "2.14.0",
4
4
  "description": "JBrowse 2 circular view",
5
5
  "keywords": [
6
6
  "jbrowse",
@@ -24,7 +24,7 @@
24
24
  ],
25
25
  "scripts": {
26
26
  "build": "npm-run-all build:*",
27
- "test": "cd ../..; jest plugins/circular-view",
27
+ "test": "cd ../..; jest --passWithNoTests plugins/circular-view",
28
28
  "prepublishOnly": "yarn test",
29
29
  "prepack": "yarn build && yarn useDist",
30
30
  "postpack": "yarn useSrc",
@@ -57,5 +57,5 @@
57
57
  "distModule": "esm/index.js",
58
58
  "srcModule": "src/index.ts",
59
59
  "module": "esm/index.js",
60
- "gitHead": "efe02fb9616e20e929cceeed46eb96420c1b6923"
60
+ "gitHead": "9fb8231d932db40adf0a283081765431756c66ff"
61
61
  }