@jbrowse/plugin-linear-genome-view 2.8.0 → 2.10.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 (59) hide show
  1. package/dist/BaseLinearDisplay/components/Tooltip.js +18 -50
  2. package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +4 -16
  3. package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.js +8 -1
  4. package/dist/BasicTrack/configSchema.d.ts +5 -0
  5. package/dist/FeatureTrack/configSchema.d.ts +5 -0
  6. package/dist/LaunchLinearGenomeView/index.js +16 -14
  7. package/dist/LinearBareDisplay/model.d.ts +8 -11
  8. package/dist/LinearBareDisplay/model.js +2 -1
  9. package/dist/LinearBasicDisplay/model.d.ts +30 -33
  10. package/dist/LinearBasicDisplay/model.js +3 -0
  11. package/dist/LinearGenomeView/components/CenterLine.js +1 -1
  12. package/dist/LinearGenomeView/components/Cytobands.d.ts +18 -6
  13. package/dist/LinearGenomeView/components/Cytobands.js +8 -2
  14. package/dist/LinearGenomeView/components/ImportForm.js +26 -74
  15. package/dist/LinearGenomeView/components/ImportFormRefNameAutocomplete.d.ts +12 -0
  16. package/dist/LinearGenomeView/components/ImportFormRefNameAutocomplete.js +29 -0
  17. package/dist/LinearGenomeView/components/OverviewScalebar.js +1 -1
  18. package/dist/LinearGenomeView/components/SearchBox.js +19 -56
  19. package/dist/LinearGenomeView/components/TracksContainer.js +1 -1
  20. package/dist/LinearGenomeView/model.d.ts +18 -2
  21. package/dist/LinearGenomeView/model.js +19 -0
  22. package/dist/LinearGenomeView/svgcomponents/SVGLinearGenomeView.d.ts +0 -7
  23. package/dist/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js +11 -13
  24. package/dist/LinearGenomeView/svgcomponents/util.d.ts +8 -0
  25. package/dist/LinearGenomeView/svgcomponents/util.js +9 -0
  26. package/dist/index.d.ts +776 -7
  27. package/dist/index.js +5 -4
  28. package/dist/searchUtils.d.ts +26 -0
  29. package/dist/searchUtils.js +90 -0
  30. package/esm/BaseLinearDisplay/components/Tooltip.js +16 -28
  31. package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +4 -16
  32. package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.js +8 -1
  33. package/esm/BasicTrack/configSchema.d.ts +5 -0
  34. package/esm/FeatureTrack/configSchema.d.ts +5 -0
  35. package/esm/LaunchLinearGenomeView/index.js +16 -14
  36. package/esm/LinearBareDisplay/model.d.ts +8 -11
  37. package/esm/LinearBareDisplay/model.js +2 -1
  38. package/esm/LinearBasicDisplay/model.d.ts +30 -33
  39. package/esm/LinearBasicDisplay/model.js +3 -0
  40. package/esm/LinearGenomeView/components/CenterLine.js +1 -1
  41. package/esm/LinearGenomeView/components/Cytobands.d.ts +18 -6
  42. package/esm/LinearGenomeView/components/Cytobands.js +8 -2
  43. package/esm/LinearGenomeView/components/ImportForm.js +26 -74
  44. package/esm/LinearGenomeView/components/ImportFormRefNameAutocomplete.d.ts +12 -0
  45. package/esm/LinearGenomeView/components/ImportFormRefNameAutocomplete.js +24 -0
  46. package/esm/LinearGenomeView/components/OverviewScalebar.js +1 -1
  47. package/esm/LinearGenomeView/components/SearchBox.js +20 -57
  48. package/esm/LinearGenomeView/components/TracksContainer.js +1 -1
  49. package/esm/LinearGenomeView/model.d.ts +18 -2
  50. package/esm/LinearGenomeView/model.js +19 -0
  51. package/esm/LinearGenomeView/svgcomponents/SVGLinearGenomeView.d.ts +0 -7
  52. package/esm/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js +9 -10
  53. package/esm/LinearGenomeView/svgcomponents/util.d.ts +8 -0
  54. package/esm/LinearGenomeView/svgcomponents/util.js +5 -0
  55. package/esm/index.d.ts +776 -7
  56. package/esm/index.js +4 -3
  57. package/esm/searchUtils.d.ts +26 -0
  58. package/esm/searchUtils.js +79 -0
  59. package/package.json +4 -6
@@ -66,10 +66,16 @@ const Cytobands = observer(function ({ overview, block, assembly, }) {
66
66
  const c = colorMap[type];
67
67
  if (type === 'acen' && !centromereSeen) {
68
68
  centromereSeen = true; // the next acen entry is drawn with different right triangle
69
- return React.createElement("polygon", { key: k, points: leftTriangle(s, 0, w, h), fill: c });
69
+ const tri = reversed
70
+ ? rightTriangle(s - w, 0, w, h)
71
+ : leftTriangle(s, 0, w, h);
72
+ return React.createElement("polygon", { key: k, points: tri, fill: c });
70
73
  }
71
74
  else if (type === 'acen' && centromereSeen) {
72
- return React.createElement("polygon", { key: k, points: rightTriangle(s, 0, w, h), fill: c });
75
+ const tri = reversed
76
+ ? leftTriangle(s - w, 0, w, h)
77
+ : rightTriangle(s, 0, w, h);
78
+ return React.createElement("polygon", { key: k, points: tri, fill: c });
73
79
  }
74
80
  else if (lcap === index) {
75
81
  return React.createElement("path", { key: k, d: leftRoundedRect(l, 0, w, h, 8), fill: c });
@@ -6,9 +6,8 @@ import { Button, FormControl, Container, Grid, CircularProgress, } from '@mui/ma
6
6
  import { ErrorMessage, AssemblySelector } from '@jbrowse/core/ui';
7
7
  // icons
8
8
  import CloseIcon from '@mui/icons-material/Close';
9
- // locals
10
- import RefNameAutocomplete from './RefNameAutocomplete';
11
- import { fetchResults, splitLast } from './util';
9
+ import { handleSelectedRegion, navToOption } from '../../searchUtils';
10
+ import ImportFormRefNameAutocomplete from './ImportFormRefNameAutocomplete';
12
11
  const useStyles = makeStyles()(theme => ({
13
12
  importFormContainer: {
14
13
  padding: theme.spacing(2),
@@ -24,11 +23,10 @@ const LinearGenomeViewImportForm = observer(function ({ model, }) {
24
23
  var _a;
25
24
  const { classes } = useStyles();
26
25
  const session = getSession(model);
27
- const { assemblyNames, assemblyManager, textSearchManager } = session;
28
- const { rankSearchResults, error } = model;
26
+ const { assemblyNames, assemblyManager } = session;
27
+ const { error } = model;
29
28
  const [selectedAsm, setSelectedAsm] = useState(assemblyNames[0]);
30
29
  const [option, setOption] = useState();
31
- const searchScope = model.searchScope(selectedAsm);
32
30
  const assembly = assemblyManager.get(selectedAsm);
33
31
  const assemblyError = assemblyNames.length
34
32
  ? assembly === null || assembly === void 0 ? void 0 : assembly.error
@@ -46,74 +44,37 @@ const LinearGenomeViewImportForm = observer(function ({ model, }) {
46
44
  useEffect(() => {
47
45
  setValue(r0);
48
46
  }, [r0, selectedAsm]);
49
- async function navToOption(option) {
50
- const location = option.getLocation();
51
- const trackId = option.getTrackId();
52
- if (location) {
53
- await model.navToLocString(location, selectedAsm);
54
- if (trackId) {
55
- model.showTrack(trackId);
56
- }
57
- }
58
- }
59
- // gets a string as input, or use stored option results from previous query,
60
- // then re-query and
61
- // 1) if it has multiple results: pop a dialog
62
- // 2) if it's a single result navigate to it
63
- // 3) else assume it's a locstring and navigate to it
64
- async function handleSelectedRegion(input) {
65
- var _a;
66
- try {
67
- if ((option === null || option === void 0 ? void 0 : option.getDisplayString()) === input && option.hasLocation()) {
68
- await navToOption(option);
69
- }
70
- else if ((_a = option === null || option === void 0 ? void 0 : option.results) === null || _a === void 0 ? void 0 : _a.length) {
71
- model.setSearchResults(option.results, option.getLabel(), selectedAsm);
72
- }
73
- else {
74
- const [ref, rest] = splitLast(input, ':');
75
- const allRefs = (assembly === null || assembly === void 0 ? void 0 : assembly.allRefNamesWithLowerCase) || [];
76
- if (allRefs.includes(input) ||
77
- (allRefs.includes(ref) && !Number.isNaN(Number.parseInt(rest, 10)))) {
78
- await model.navToLocString(input, selectedAsm);
79
- }
80
- else {
81
- const results = await fetchResults({
82
- queryString: input,
83
- searchType: 'exact',
84
- searchScope,
85
- rankSearchResults,
86
- textSearchManager,
87
- assembly,
88
- });
89
- if (results.length > 1) {
90
- model.setSearchResults(results, input.toLowerCase(), selectedAsm);
91
- }
92
- else if (results.length === 1) {
93
- await navToOption(results[0]);
94
- }
95
- else {
96
- await model.navToLocString(input, selectedAsm);
97
- }
98
- }
99
- }
100
- }
101
- catch (e) {
102
- console.error(e);
103
- session.notify(`${e}`, 'warning');
104
- }
105
- }
106
47
  // implementation notes:
107
48
  // having this wrapped in a form allows intuitive use of enter key to submit
108
49
  return (React.createElement("div", { className: classes.container },
109
50
  displayError ? React.createElement(ErrorMessage, { error: displayError }) : null,
110
51
  React.createElement(Container, { className: classes.importFormContainer },
111
52
  React.createElement("form", { onSubmit: async (event) => {
53
+ var _a;
112
54
  event.preventDefault();
113
55
  model.setError(undefined);
114
56
  if (value) {
115
57
  // has it's own error handling
116
- await handleSelectedRegion(value);
58
+ try {
59
+ if ((option === null || option === void 0 ? void 0 : option.getDisplayString()) === value &&
60
+ option.hasLocation()) {
61
+ await navToOption({
62
+ option,
63
+ model,
64
+ assemblyName: selectedAsm,
65
+ });
66
+ }
67
+ else if ((_a = option === null || option === void 0 ? void 0 : option.results) === null || _a === void 0 ? void 0 : _a.length) {
68
+ model.setSearchResults(option.results, option.getLabel(), selectedAsm);
69
+ }
70
+ else if (assembly) {
71
+ await handleSelectedRegion({ input: value, assembly, model });
72
+ }
73
+ }
74
+ catch (e) {
75
+ console.error(e);
76
+ session.notify(`${e}`, 'warning');
77
+ }
117
78
  }
118
79
  } },
119
80
  React.createElement(Grid, { container: true, spacing: 1, justifyContent: "center", alignItems: "center" },
@@ -121,16 +82,7 @@ const LinearGenomeViewImportForm = observer(function ({ model, }) {
121
82
  React.createElement(FormControl, null,
122
83
  React.createElement(AssemblySelector, { onChange: val => setSelectedAsm(val), localStorageKey: "lgv", session: session, selected: selectedAsm }))),
123
84
  React.createElement(Grid, { item: true }, selectedAsm ? (assemblyError ? (React.createElement(CloseIcon, { style: { color: 'red' } })) : assemblyLoaded ? (React.createElement(FormControl, null,
124
- React.createElement(RefNameAutocomplete, { fetchResults: queryString => fetchResults({
125
- queryString,
126
- assembly,
127
- textSearchManager,
128
- rankSearchResults,
129
- searchScope,
130
- }), model: model, assemblyName: selectedAsm, value: value, minWidth: 270, onChange: str => setValue(str), onSelect: val => setOption(val), TextFieldProps: {
131
- variant: 'outlined',
132
- helperText: 'Enter sequence name, feature name, or location',
133
- } }))) : (React.createElement(CircularProgress, { size: 20, disableShrink: true }))) : null),
85
+ React.createElement(ImportFormRefNameAutocomplete, { value: value, setValue: setValue, selectedAsm: selectedAsm, setOption: setOption, model: model }))) : (React.createElement(CircularProgress, { size: 20, disableShrink: true }))) : null),
134
86
  React.createElement(Grid, { item: true },
135
87
  React.createElement(FormControl, null,
136
88
  React.createElement(Button, { type: "submit", disabled: !value, className: classes.button, variant: "contained", color: "primary" }, "Open")),
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import BaseResult from '@jbrowse/core/TextSearch/BaseResults';
3
+ import { LinearGenomeViewModel } from '..';
4
+ type LGV = LinearGenomeViewModel;
5
+ declare const ImportFormRefNameAutocomplete: ({ model, selectedAsm, value, setValue, setOption, }: {
6
+ value: string;
7
+ setValue: (arg: string) => void;
8
+ model: LGV;
9
+ selectedAsm: string;
10
+ setOption: (arg: BaseResult) => void;
11
+ }) => React.JSX.Element;
12
+ export default ImportFormRefNameAutocomplete;
@@ -0,0 +1,24 @@
1
+ import React from 'react';
2
+ import { observer } from 'mobx-react';
3
+ import { getSession } from '@jbrowse/core/util';
4
+ // locals
5
+ import RefNameAutocomplete from './RefNameAutocomplete';
6
+ import { fetchResults } from './util';
7
+ const ImportFormRefNameAutocomplete = observer(function ({ model, selectedAsm, value, setValue, setOption, }) {
8
+ const session = getSession(model);
9
+ const { assemblyManager, textSearchManager } = session;
10
+ const { rankSearchResults } = model;
11
+ const searchScope = model.searchScope(selectedAsm);
12
+ const assembly = assemblyManager.get(selectedAsm);
13
+ return (React.createElement(RefNameAutocomplete, { fetchResults: queryString => fetchResults({
14
+ queryString,
15
+ assembly,
16
+ textSearchManager,
17
+ rankSearchResults,
18
+ searchScope,
19
+ }), model: model, assemblyName: selectedAsm, value: value, minWidth: 270, onChange: str => setValue(str), onSelect: val => setOption(val), TextFieldProps: {
20
+ variant: 'outlined',
21
+ helperText: 'Enter sequence name, feature name, or location',
22
+ } }));
23
+ });
24
+ export default ImportFormRefNameAutocomplete;
@@ -195,7 +195,7 @@ const OverviewScalebar = observer(function ({ model, children, }) {
195
195
  overview.showAllRegions();
196
196
  return overview;
197
197
  }, [
198
- JSON.stringify(displayedRegions),
198
+ JSON.stringify(displayedRegions), // eslint-disable-line react-hooks/exhaustive-deps
199
199
  model.minimumBlockWidth,
200
200
  modWidth,
201
201
  displayedRegions,
@@ -5,18 +5,14 @@ import { makeStyles } from 'tss-react/mui';
5
5
  import { getSession } from '@jbrowse/core/util';
6
6
  // locals
7
7
  import RefNameAutocomplete from './RefNameAutocomplete';
8
- import { fetchResults, splitLast } from './util';
8
+ import { fetchResults } from './util';
9
9
  import { SPACING, WIDGET_HEIGHT } from '..';
10
+ import { handleSelectedRegion, navToOption } from '../../searchUtils';
10
11
  const useStyles = makeStyles()(() => ({
11
12
  headerRefName: {
12
13
  minWidth: 100,
13
14
  },
14
15
  }));
15
- function checkRef(str, allRefs) {
16
- const [ref, rest] = splitLast(str, ':');
17
- return (allRefs.includes(str) ||
18
- (allRefs.includes(ref) && !Number.isNaN(Number.parseInt(rest, 10))));
19
- }
20
16
  const SearchBox = observer(function ({ model, showHelp, }) {
21
17
  const { classes } = useStyles();
22
18
  const theme = useTheme();
@@ -26,61 +22,28 @@ const SearchBox = observer(function ({ model, showHelp, }) {
26
22
  const assemblyName = assemblyNames[0];
27
23
  const assembly = assemblyManager.get(assemblyName);
28
24
  const searchScope = model.searchScope(assemblyName);
29
- async function navToOption(option) {
30
- const location = option.getLocation();
31
- const trackId = option.getTrackId();
32
- if (location) {
33
- await model.navToLocString(location, assemblyName);
34
- if (trackId) {
35
- model.showTrack(trackId);
36
- }
37
- }
38
- }
39
- // gets a string as input, or use stored option results from previous query,
40
- // then re-query and
41
- // 1) if it has multiple results: pop a dialog
42
- // 2) if it's a single result navigate to it
43
- // 3) else assume it's a locstring and navigate to it
44
- async function handleSelectedRegion(option) {
45
- var _a;
46
- try {
47
- const input = option.getLabel();
48
- const allRefs = (assembly === null || assembly === void 0 ? void 0 : assembly.allRefNamesWithLowerCase) || [];
49
- if (option.hasLocation()) {
50
- await navToOption(option);
51
- }
52
- else if ((_a = option.results) === null || _a === void 0 ? void 0 : _a.length) {
53
- model.setSearchResults(option.results, option.getLabel());
54
- }
55
- else if (input.split(' ').every(entry => checkRef(entry, allRefs))) {
56
- await model.navToLocString(input, assemblyName);
57
- }
58
- else {
59
- const results = await fetchResults({
60
- queryString: input,
61
- searchType: 'exact',
62
- searchScope,
63
- rankSearchResults,
64
- textSearchManager,
65
- assembly,
66
- });
67
- if (results.length > 1) {
68
- model.setSearchResults(results, input.toLowerCase());
25
+ return (React.createElement(RefNameAutocomplete, { showHelp: showHelp, onSelect: async (option) => {
26
+ var _a;
27
+ try {
28
+ if (option.hasLocation()) {
29
+ await navToOption({ option, model, assemblyName });
69
30
  }
70
- else if (results.length === 1) {
71
- await navToOption(results[0]);
31
+ else if ((_a = option.results) === null || _a === void 0 ? void 0 : _a.length) {
32
+ model.setSearchResults(option.results, option.getLabel());
72
33
  }
73
- else {
74
- await model.navToLocString(input, assemblyName);
34
+ else if (assembly) {
35
+ await handleSelectedRegion({
36
+ input: option.getLabel(),
37
+ assembly,
38
+ model,
39
+ });
75
40
  }
76
41
  }
77
- }
78
- catch (e) {
79
- console.error(e);
80
- session.notify(`${e}`, 'warning');
81
- }
82
- }
83
- return (React.createElement(RefNameAutocomplete, { showHelp: showHelp, onSelect: handleSelectedRegion, assemblyName: assemblyName, fetchResults: queryString => fetchResults({
42
+ catch (e) {
43
+ console.error(e);
44
+ getSession(model).notify(`${e}`, 'warning');
45
+ }
46
+ }, assemblyName: assemblyName, fetchResults: queryString => fetchResults({
84
47
  queryString,
85
48
  searchScope,
86
49
  rankSearchResults,
@@ -2,6 +2,7 @@ import React, { useRef } from 'react';
2
2
  import { makeStyles } from 'tss-react/mui';
3
3
  import { observer } from 'mobx-react';
4
4
  import { Menu } from '@jbrowse/core/ui';
5
+ import { getEnv } from '@jbrowse/core/util';
5
6
  // local utils
6
7
  import { SCALE_BAR_HEIGHT } from '..';
7
8
  import { useSideScroll, useRangeSelect, useWheelScroll } from './hooks';
@@ -12,7 +13,6 @@ import Gridlines from './Gridlines';
12
13
  import CenterLine from './CenterLine';
13
14
  import VerticalGuide from './VerticalGuide';
14
15
  import RubberbandSpan from './RubberbandSpan';
15
- import { getEnv } from '@jbrowse/core/util';
16
16
  const useStyles = makeStyles()({
17
17
  tracksContainer: {
18
18
  position: 'relative',
@@ -6,6 +6,7 @@ import BaseResult from '@jbrowse/core/TextSearch/BaseResults';
6
6
  import { BlockSet, BaseBlock } from '@jbrowse/core/util/blockTypes';
7
7
  import { Instance } from 'mobx-state-tree';
8
8
  import PluginManager from '@jbrowse/core/PluginManager';
9
+ import { Assembly } from '@jbrowse/core/assemblyManager/assembly';
9
10
  export interface BpOffset {
10
11
  refName?: string;
11
12
  index: number;
@@ -20,7 +21,9 @@ export interface BpOffset {
20
21
  export interface ExportSvgOptions {
21
22
  rasterizeLayers?: boolean;
22
23
  filename?: string;
23
- Wrapper?: React.FC<any>;
24
+ Wrapper?: React.FC<{
25
+ children: React.ReactNode;
26
+ }>;
24
27
  fontSize?: number;
25
28
  rulerHeight?: number;
26
29
  textHeight?: number;
@@ -46,6 +49,9 @@ export declare const WIDGET_HEIGHT = 32;
46
49
  /**
47
50
  * #stateModel LinearGenomeView
48
51
  * #category view
52
+ *
53
+ * extends
54
+ * - [BaseViewModel](../baseviewmodel)
49
55
  */
50
56
  export declare function stateModelFactory(pluginManager: PluginManager): import("mobx-state-tree").IModelType<{
51
57
  id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
@@ -292,7 +298,7 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
292
298
  /**
293
299
  * #action
294
300
  */
295
- toggleTrack(trackId: string): void;
301
+ toggleTrack(trackId: string): boolean;
296
302
  /**
297
303
  * #action
298
304
  */
@@ -463,6 +469,16 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
463
469
  * navigating to the locstring
464
470
  */
465
471
  navToLocString(input: string, optAssemblyName?: string): Promise<void>;
472
+ /**
473
+ * #action
474
+ * Performs a text index search, and navigates to it immediately if a
475
+ * single result is returned. Will pop up a search dialog if multiple
476
+ * results are returned
477
+ */
478
+ navToSearchString({ input, assembly, }: {
479
+ input: string;
480
+ assembly: Assembly;
481
+ }): Promise<void>;
466
482
  /**
467
483
  * #action
468
484
  * Similar to `navToLocString`, but accepts parsed location objects
@@ -24,6 +24,7 @@ import MenuOpenIcon from '@mui/icons-material/MenuOpen';
24
24
  import MiniControls from './components/MiniControls';
25
25
  import Header from './components/Header';
26
26
  import { generateLocations, parseLocStrings } from './util';
27
+ import { handleSelectedRegion } from '../searchUtils';
27
28
  // lazies
28
29
  const ReturnToImportFormDialog = lazy(() => import('@jbrowse/core/ui/ReturnToImportFormDialog'));
29
30
  const SequenceSearchDialog = lazy(() => import('./components/SequenceSearchDialog'));
@@ -53,6 +54,9 @@ export const WIDGET_HEIGHT = 32;
53
54
  /**
54
55
  * #stateModel LinearGenomeView
55
56
  * #category view
57
+ *
58
+ * extends
59
+ * - [BaseViewModel](../baseviewmodel)
56
60
  */
57
61
  export function stateModelFactory(pluginManager) {
58
62
  return types
@@ -595,7 +599,9 @@ export function stateModelFactory(pluginManager) {
595
599
  // if none had that configuration, turn one on
596
600
  if (!hiddenCount) {
597
601
  self.showTrack(trackId);
602
+ return true;
598
603
  }
604
+ return false;
599
605
  },
600
606
  /**
601
607
  * #action
@@ -1077,6 +1083,19 @@ export function stateModelFactory(pluginManager) {
1077
1083
  }
1078
1084
  return this.navToLocations(parseLocStrings(input, assemblyName, isValidRefName), assemblyName);
1079
1085
  },
1086
+ /**
1087
+ * #action
1088
+ * Performs a text index search, and navigates to it immediately if a
1089
+ * single result is returned. Will pop up a search dialog if multiple
1090
+ * results are returned
1091
+ */
1092
+ async navToSearchString({ input, assembly, }) {
1093
+ await handleSelectedRegion({
1094
+ input,
1095
+ assembly,
1096
+ model: self,
1097
+ });
1098
+ },
1080
1099
  /**
1081
1100
  * #action
1082
1101
  * Similar to `navToLocString`, but accepts parsed location objects
@@ -1,12 +1,5 @@
1
1
  import { LinearGenomeViewModel, ExportSvgOptions } from '..';
2
2
  type LGV = LinearGenomeViewModel;
3
- interface Display {
4
- height: number;
5
- }
6
- interface Track {
7
- displays: Display[];
8
- }
9
- export declare function totalHeight(tracks: Track[], textHeight: number, trackLabels: string): number;
10
3
  export declare function renderToSvg(model: LGV, opts: ExportSvgOptions): Promise<string>;
11
4
  export { default as SVGRuler } from './SVGRuler';
12
5
  export { default as SVGTracks } from './SVGTracks';
@@ -1,25 +1,24 @@
1
1
  /* eslint-disable react-refresh/only-export-components */
2
2
  import React from 'react';
3
- import { renderToStaticMarkup } from 'react-dom/server';
4
3
  import { when } from 'mobx';
5
- import { getSession, max, measureText, sum } from '@jbrowse/core/util';
4
+ import { getSession, max, measureText, renderToStaticMarkup, } from '@jbrowse/core/util';
6
5
  import { ThemeProvider } from '@mui/material';
7
6
  import { createJBrowseTheme } from '@jbrowse/core/ui';
7
+ import { getTrackName } from '@jbrowse/core/util/tracks';
8
+ import { getRoot } from 'mobx-state-tree';
8
9
  import SVGBackground from './SVGBackground';
9
10
  import SVGTracks from './SVGTracks';
10
11
  import SVGHeader from './SVGHeader';
11
- import { getTrackName } from '@jbrowse/core/util/tracks';
12
- export function totalHeight(tracks, textHeight, trackLabels) {
13
- return sum(tracks.map(t => t.displays[0].height +
14
- (['none', 'left'].includes(trackLabels) ? 0 : textHeight)));
15
- }
12
+ import { totalHeight } from './util';
16
13
  // render LGV to SVG
17
14
  export async function renderToSvg(model, opts) {
18
- var _a;
19
15
  await when(() => model.initialized);
20
16
  const { textHeight = 18, headerHeight = 40, rulerHeight = 50, fontSize = 13, cytobandHeight = 100, trackLabels = 'offset', themeName = 'default', Wrapper = ({ children }) => React.createElement(React.Fragment, null, children), } = opts;
21
17
  const session = getSession(model);
22
- const theme = (_a = session.allThemes) === null || _a === void 0 ? void 0 : _a.call(session)[themeName];
18
+ const { allThemes } = session;
19
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
20
+ const { createRootFn } = getRoot(model);
21
+ const theme = allThemes === null || allThemes === void 0 ? void 0 : allThemes()[themeName];
23
22
  const { width, tracks, showCytobands } = model;
24
23
  const shift = 50;
25
24
  const c = +showCytobands * cytobandHeight;
@@ -41,7 +40,7 @@ export async function renderToSvg(model, opts) {
41
40
  React.createElement("g", { transform: `translate(${shift} 0)` },
42
41
  React.createElement("g", { transform: `translate(${trackLabelOffset})` },
43
42
  React.createElement(SVGHeader, { model: model, fontSize: fontSize, rulerHeight: rulerHeight, cytobandHeight: cytobandHeight })),
44
- React.createElement(SVGTracks, { textHeight: textHeight, fontSize: fontSize, model: model, displayResults: displayResults, offset: offset, trackLabels: trackLabels, trackLabelOffset: trackLabelOffset }))))));
43
+ React.createElement(SVGTracks, { textHeight: textHeight, fontSize: fontSize, model: model, displayResults: displayResults, offset: offset, trackLabels: trackLabels, trackLabelOffset: trackLabelOffset }))))), createRootFn);
45
44
  }
46
45
  export { default as SVGRuler } from './SVGRuler';
47
46
  export { default as SVGTracks } from './SVGTracks';
@@ -0,0 +1,8 @@
1
+ interface Display {
2
+ height: number;
3
+ }
4
+ interface Track {
5
+ displays: Display[];
6
+ }
7
+ export declare function totalHeight(tracks: Track[], textHeight: number, trackLabels: string): number;
8
+ export {};
@@ -0,0 +1,5 @@
1
+ import { sum } from '@jbrowse/core/util';
2
+ export function totalHeight(tracks, textHeight, trackLabels) {
3
+ return sum(tracks.map(t => t.displays[0].height +
4
+ (['none', 'left'].includes(trackLabels) ? 0 : textHeight)));
5
+ }