@jbrowse/core 2.3.2 → 2.3.4

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.
package/ui/Dialog.js CHANGED
@@ -7,8 +7,11 @@ const react_1 = __importDefault(require("react"));
7
7
  const material_1 = require("@mui/material");
8
8
  const mobx_react_1 = require("mobx-react");
9
9
  const mui_1 = require("tss-react/mui");
10
+ const react_error_boundary_1 = require("react-error-boundary");
10
11
  // icons
11
12
  const Close_1 = __importDefault(require("@mui/icons-material/Close"));
13
+ // locals
14
+ const ErrorMessage_1 = __importDefault(require("./ErrorMessage"));
12
15
  const useStyles = (0, mui_1.makeStyles)()(theme => ({
13
16
  closeButton: {
14
17
  position: 'absolute',
@@ -17,6 +20,10 @@ const useStyles = (0, mui_1.makeStyles)()(theme => ({
17
20
  color: theme.palette.grey[500],
18
21
  },
19
22
  }));
23
+ function DialogError({ error }) {
24
+ return (react_1.default.createElement("div", { style: { width: 800, margin: 40 } },
25
+ react_1.default.createElement(ErrorMessage_1.default, { error: error })));
26
+ }
20
27
  function JBrowseDialog(props) {
21
28
  const { classes } = useStyles();
22
29
  const { title, children, onClose } = props;
@@ -30,6 +37,6 @@ function JBrowseDialog(props) {
30
37
  } },
31
38
  react_1.default.createElement(Close_1.default, null))) : null),
32
39
  react_1.default.createElement(material_1.Divider, null),
33
- children)));
40
+ react_1.default.createElement(react_error_boundary_1.ErrorBoundary, { FallbackComponent: DialogError }, children))));
34
41
  }
35
42
  exports.default = (0, mobx_react_1.observer)(JBrowseDialog);
@@ -33,9 +33,6 @@ const mobx_react_1 = require("mobx-react");
33
33
  const ArrowDropDown_1 = __importDefault(require("@mui/icons-material/ArrowDropDown"));
34
34
  const Menu_1 = __importDefault(require("./Menu"));
35
35
  const useStyles = (0, mui_1.makeStyles)()(theme => ({
36
- root: {
37
- display: 'flex',
38
- },
39
36
  buttonRoot: {
40
37
  '&:hover': {
41
38
  backgroundColor: (0, material_1.alpha)(theme.palette.primary.contrastText, theme.palette.action.hoverOpacity),
@@ -59,7 +56,7 @@ function DropDownMenu({ menuTitle, session, menuItems, }) {
59
56
  function handleClose() {
60
57
  setOpen(false);
61
58
  }
62
- return (react_1.default.createElement("div", { className: classes.root },
59
+ return (react_1.default.createElement(react_1.default.Fragment, null,
63
60
  react_1.default.createElement(material_1.Button, { ref: anchorEl, onClick: handleToggle, color: "inherit", "data-testid": "dropDownMenuButton", classes: { root: classes.buttonRoot } },
64
61
  menuTitle,
65
62
  react_1.default.createElement(ArrowDropDown_1.default, null)),
@@ -88,7 +88,7 @@ const EditableTypography = react_1.default.forwardRef((props, ref) => {
88
88
  setBlur(true);
89
89
  }
90
90
  }, onBlur: () => {
91
- setValue(editedValue || '');
91
+ setValue(editedValue || value || '');
92
92
  setEditedValue(undefined);
93
93
  } })));
94
94
  });
@@ -36,7 +36,6 @@ const ResetComponent = ({ onFactoryReset, resetButtonText, }) => {
36
36
  react_1.default.createElement(FactoryResetDialog_1.default, { onClose: () => setDialogOpen(false), open: dialogOpen, onFactoryReset: onFactoryReset })));
37
37
  };
38
38
  const FatalErrorDialog = ({ componentStack, error = 'No error message provided', onFactoryReset, resetButtonText = 'Factory Reset', }) => {
39
- console.error(error);
40
39
  return (react_1.default.createElement(material_1.Dialog, { open: true },
41
40
  react_1.default.createElement(material_1.DialogTitle, { style: { background: '#e88' } }, "Fatal error"),
42
41
  react_1.default.createElement(material_1.DialogContent, null,
package/ui/Menu.js CHANGED
@@ -245,7 +245,15 @@ const MenuPage = react_1.default.forwardRef((props, ref) => {
245
245
  });
246
246
  function Menu(props) {
247
247
  const { open, onClose, menuItems, onMenuItemClick, ...other } = props;
248
- return (react_1.default.createElement(material_1.Popover, { transitionDuration: 0, open: open, onClose: onClose, BackdropProps: { invisible: true }, ...other },
248
+ return (react_1.default.createElement(material_1.Popover, { open: open, onClose: onClose, BackdropProps: { invisible: true }, anchorOrigin: {
249
+ vertical: 'bottom',
250
+ horizontal: 'right',
251
+ ...other.anchorOrigin,
252
+ }, transformOrigin: {
253
+ vertical: 'top',
254
+ horizontal: 'left',
255
+ ...other.transformOrigin,
256
+ }, ...other },
249
257
  react_1.default.createElement(MenuPage, { open: open, onClose: onClose, menuItems: menuItems, onMenuItemClick: onMenuItemClick, top: true })));
250
258
  }
251
259
  exports.default = Menu;
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ export declare function useResizeBar(): {
3
+ ref: React.RefObject<HTMLDivElement>;
4
+ scrollLeft: number;
5
+ };
6
+ export default function ResizeBar({ widths, setWidths, checkbox, scrollLeft, }: {
7
+ widths: number[];
8
+ setWidths: (arg: number[]) => void;
9
+ checkbox?: boolean;
10
+ scrollLeft?: number;
11
+ }): JSX.Element;
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.useResizeBar = void 0;
30
+ const react_1 = __importStar(require("react"));
31
+ const mui_1 = require("tss-react/mui");
32
+ // locals
33
+ const ResizeHandle_1 = __importDefault(require("./ResizeHandle"));
34
+ const useStyles = (0, mui_1.makeStyles)()({
35
+ resizeBar: {
36
+ background: 'lightgrey',
37
+ height: 12,
38
+ position: 'relative',
39
+ overflow: 'hidden',
40
+ },
41
+ tick: {
42
+ position: 'absolute',
43
+ height: '100%',
44
+ pointerEvents: 'none',
45
+ background: 'black',
46
+ width: 1,
47
+ },
48
+ hiddenTick: {
49
+ position: 'absolute',
50
+ height: '100%',
51
+ background: 'lightgrey',
52
+ width: 5,
53
+ },
54
+ });
55
+ function useResizeBar() {
56
+ const ref = (0, react_1.useRef)(null);
57
+ const [scrollLeft, setScrollLeft] = (0, react_1.useState)(0);
58
+ (0, react_1.useEffect)(() => {
59
+ const timer = setInterval(() => {
60
+ var _a;
61
+ const elt = (_a = ref.current) === null || _a === void 0 ? void 0 : _a.querySelector('.MuiDataGrid-virtualScroller');
62
+ if (elt) {
63
+ setScrollLeft(elt.scrollLeft);
64
+ }
65
+ }, 100);
66
+ return () => {
67
+ clearInterval(timer);
68
+ };
69
+ }, []);
70
+ return { ref, scrollLeft };
71
+ }
72
+ exports.useResizeBar = useResizeBar;
73
+ function Tick({ left, scrollLeft, idx, onDrag, }) {
74
+ const { classes } = useStyles();
75
+ const cb = (0, react_1.useCallback)((d) => {
76
+ onDrag(d, idx);
77
+ }, [idx, onDrag]);
78
+ // has an invisible wider than tick mark (1px) clickable area (5px)
79
+ return (react_1.default.createElement(react_1.default.Fragment, null,
80
+ react_1.default.createElement(ResizeHandle_1.default, { onDrag: cb, vertical: true, className: classes.hiddenTick, style: { left: left - scrollLeft - 2.5 } }),
81
+ react_1.default.createElement("div", { style: { left: left - scrollLeft }, className: classes.tick })));
82
+ }
83
+ function ResizeBar({ widths, setWidths, checkbox, scrollLeft = 0, }) {
84
+ const { classes } = useStyles();
85
+ const offsets = [];
86
+ widths.reduce((a, b, i) => (offsets[i] = a + b), checkbox ? 52 : 0);
87
+ const onDrag = (0, react_1.useCallback)((distance, idx) => {
88
+ const newWidths = [...widths];
89
+ // mui doesn't allow columns smaller than 50
90
+ newWidths[idx] = Math.max(newWidths[idx] + distance, 50);
91
+ setWidths(newWidths);
92
+ }, [widths, setWidths]);
93
+ return (react_1.default.createElement("div", { className: classes.resizeBar }, offsets.map((left, i) => (react_1.default.createElement(Tick, { key: i, left: i === offsets.length - 1 ? left - 3 : left, onDrag: onDrag, idx: i, scrollLeft: scrollLeft })))));
94
+ }
95
+ exports.default = ResizeBar;
@@ -1,6 +1,6 @@
1
1
  /// <reference types="react" />
2
2
  declare function ResizeHandle({ onDrag, vertical, flexbox, className: originalClassName, ...props }: {
3
- onDrag: (arg: number) => number;
3
+ onDrag: (arg: number) => number | void;
4
4
  vertical?: boolean;
5
5
  flexbox?: boolean;
6
6
  className?: string;
@@ -89,6 +89,6 @@ function ResizeHandle({ onDrag, vertical = false, flexbox = false, className: or
89
89
  event.preventDefault();
90
90
  prevPos.current = vertical ? event.clientX : event.clientY;
91
91
  setMouseDragging(true);
92
- }, role: "presentation", className: cx(className, originalClassName), ...props }));
92
+ }, className: cx(className, originalClassName), ...props }));
93
93
  }
94
94
  exports.default = ResizeHandle;
@@ -65,7 +65,7 @@ function SanitizedHTML({ html }) {
65
65
  }
66
66
  });
67
67
  }
68
- return (react_1.default.createElement("div", {
68
+ return (react_1.default.createElement("span", {
69
69
  // eslint-disable-next-line react/no-danger
70
70
  dangerouslySetInnerHTML: {
71
71
  __html: dompurify_1.default.sanitize(value),
package/ui/theme.d.ts CHANGED
@@ -116,6 +116,16 @@ export declare function createJBrowseDefaultProps(): {
116
116
  size: "small";
117
117
  };
118
118
  };
119
+ MuiPopover: {
120
+ defaultProps: {
121
+ transitionDuration: number;
122
+ };
123
+ };
124
+ MuiMenu: {
125
+ defaultProps: {
126
+ transitionDuration: number;
127
+ };
128
+ };
119
129
  MuiMenuList: {
120
130
  defaultProps: {
121
131
  dense: boolean;
package/ui/theme.js CHANGED
@@ -102,6 +102,16 @@ function createJBrowseDefaultProps( /* palette: PaletteOptions = {} */) {
102
102
  size: 'small',
103
103
  },
104
104
  },
105
+ MuiPopover: {
106
+ defaultProps: {
107
+ transitionDuration: 0,
108
+ },
109
+ },
110
+ MuiMenu: {
111
+ defaultProps: {
112
+ transitionDuration: 0,
113
+ },
114
+ },
105
115
  MuiMenuList: {
106
116
  defaultProps: {
107
117
  dense: true,
@@ -30,3 +30,9 @@ export declare function bpToPx({ refName, coord, regionNumber, self, }: {
30
30
  index: number;
31
31
  offsetPx: number;
32
32
  } | undefined;
33
+ export declare function bpToPxMap({ refName, coord, regionNumber, self, }: {
34
+ refName: string;
35
+ coord: number;
36
+ regionNumber?: number;
37
+ self: ViewSnap;
38
+ }): {};
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.bpToPx = exports.pxToBp = exports.moveTo = void 0;
3
+ exports.bpToPxMap = exports.bpToPx = exports.pxToBp = exports.moveTo = void 0;
4
4
  const mobx_state_tree_1 = require("mobx-state-tree");
5
5
  function lengthBetween(self, start, end) {
6
6
  let bpSoFar = 0;
@@ -57,6 +57,9 @@ function moveTo(self, start, end) {
57
57
  self.scrollTo(Math.round(bpToStart / self.bpPerPx));
58
58
  }
59
59
  exports.moveTo = moveTo;
60
+ function coord(r, bp) {
61
+ return Math.floor(r.reversed ? r.end - bp : r.start + bp) + 1;
62
+ }
60
63
  // manual return type since getSnapshot hard to infer here
61
64
  function pxToBp(self, px) {
62
65
  var _a;
@@ -65,16 +68,14 @@ function pxToBp(self, px) {
65
68
  const blocks = staticBlocks.contentBlocks;
66
69
  const bp = (offsetPx + px) * bpPerPx;
67
70
  if (bp < 0) {
68
- const region = displayedRegions[0];
69
- const snap = (0, mobx_state_tree_1.getSnapshot)(region);
71
+ const r = displayedRegions[0];
72
+ const snap = (0, mobx_state_tree_1.getSnapshot)(r);
70
73
  // @ts-ignore
71
74
  return {
72
75
  // xref https://github.com/mobxjs/mobx-state-tree/issues/1524 for Omit
73
76
  ...snap,
74
77
  oob: true,
75
- coord: region.reversed
76
- ? Math.floor(region.end - bp) + 1
77
- : Math.floor(region.start + bp) + 1,
78
+ coord: coord(r, bp),
78
79
  offset: bp,
79
80
  index: 0,
80
81
  };
@@ -82,20 +83,18 @@ function pxToBp(self, px) {
82
83
  const interRegionPaddingBp = interRegionPaddingWidth * bpPerPx;
83
84
  let currBlock = 0;
84
85
  for (let i = 0; i < displayedRegions.length; i++) {
85
- const region = displayedRegions[i];
86
- const len = region.end - region.start;
86
+ const r = displayedRegions[i];
87
+ const len = r.end - r.start;
87
88
  const offset = bp - bpSoFar;
88
89
  if (len + bpSoFar > bp && bpSoFar <= bp) {
89
- const snap = (0, mobx_state_tree_1.getSnapshot)(region);
90
+ const snap = (0, mobx_state_tree_1.getSnapshot)(r);
90
91
  // @ts-ignore
91
92
  return {
92
93
  // xref https://github.com/mobxjs/mobx-state-tree/issues/1524 for Omit
93
94
  ...snap,
94
95
  oob: false,
95
96
  offset,
96
- coord: region.reversed
97
- ? Math.floor(region.end - offset) + 1
98
- : Math.floor(region.start + offset) + 1,
97
+ coord: coord(r, offset),
99
98
  index: i,
100
99
  };
101
100
  }
@@ -110,19 +109,17 @@ function pxToBp(self, px) {
110
109
  }
111
110
  }
112
111
  if (bp >= bpSoFar && displayedRegions.length) {
113
- const region = displayedRegions[displayedRegions.length - 1];
114
- const len = region.end - region.start;
112
+ const r = displayedRegions[displayedRegions.length - 1];
113
+ const len = r.end - r.start;
115
114
  const offset = bp - bpSoFar + len;
116
- const snap = (0, mobx_state_tree_1.getSnapshot)(region);
115
+ const snap = (0, mobx_state_tree_1.getSnapshot)(r);
117
116
  // @ts-ignore
118
117
  return {
119
118
  // xref https://github.com/mobxjs/mobx-state-tree/issues/1524 for Omit
120
119
  ...snap,
121
120
  oob: true,
122
121
  offset,
123
- coord: region.reversed
124
- ? Math.floor(region.end - offset) + 1
125
- : Math.floor(region.start + offset) + 1,
122
+ coord: coord(r, offset),
126
123
  index: displayedRegions.length - 1,
127
124
  };
128
125
  }
@@ -148,13 +145,11 @@ function bpToPx({ refName, coord, regionNumber, self, }) {
148
145
  let currBlock = 0;
149
146
  let i = 0;
150
147
  for (; i < displayedRegions.length; i++) {
151
- const region = displayedRegions[i];
152
- const len = region.end - region.start;
153
- if (refName === region.refName &&
154
- coord >= region.start &&
155
- coord <= region.end) {
148
+ const r = displayedRegions[i];
149
+ const len = r.end - r.start;
150
+ if (refName === r.refName && coord >= r.start && coord <= r.end) {
156
151
  if (regionNumber ? regionNumber === i : true) {
157
- bpSoFar += region.reversed ? region.end - coord : coord - region.start;
152
+ bpSoFar += r.reversed ? r.end - coord : coord - r.start;
158
153
  break;
159
154
  }
160
155
  }
@@ -178,3 +173,41 @@ function bpToPx({ refName, coord, regionNumber, self, }) {
178
173
  return undefined;
179
174
  }
180
175
  exports.bpToPx = bpToPx;
176
+ function bpToPxMap({ refName, coord, regionNumber, self, }) {
177
+ var _a;
178
+ let bpSoFar = 0;
179
+ const { interRegionPaddingWidth, bpPerPx, displayedRegions, staticBlocks } = self;
180
+ const blocks = staticBlocks.contentBlocks;
181
+ const interRegionPaddingBp = interRegionPaddingWidth * bpPerPx;
182
+ const map = {};
183
+ let currBlock = 0;
184
+ let i = 0;
185
+ for (; i < displayedRegions.length; i++) {
186
+ const r = displayedRegions[i];
187
+ const len = r.end - r.start;
188
+ if (refName === r.refName && coord >= r.start && coord <= r.end) {
189
+ if (regionNumber !== undefined ? regionNumber === i : true) {
190
+ bpSoFar += r.reversed ? r.end - coord : coord - r.start;
191
+ break;
192
+ }
193
+ }
194
+ // add the interRegionPaddingWidth if the boundary is in the screen e.g. in
195
+ // a static block
196
+ if (((_a = blocks[currBlock]) === null || _a === void 0 ? void 0 : _a.regionNumber) === i) {
197
+ bpSoFar += len + interRegionPaddingBp;
198
+ currBlock++;
199
+ }
200
+ else {
201
+ bpSoFar += len;
202
+ }
203
+ }
204
+ const found = displayedRegions[i];
205
+ if (found) {
206
+ return {
207
+ index: i,
208
+ offsetPx: Math.round(bpSoFar / bpPerPx),
209
+ };
210
+ }
211
+ return map;
212
+ }
213
+ exports.bpToPxMap = bpToPxMap;
@@ -78,7 +78,9 @@ declare const Base1DView: import("mobx-state-tree").IModelType<{
78
78
  */
79
79
  pxToBp(px: number): {
80
80
  coord: number;
81
- index: number;
81
+ index: number; /**
82
+ * #getter
83
+ */
82
84
  refName: string;
83
85
  oob: boolean;
84
86
  assemblyName: string;
package/util/index.d.ts CHANGED
@@ -1,22 +1,22 @@
1
1
  import PluginManager from '../PluginManager';
2
2
  import { IAnyStateTreeNode, IStateTreeNode } from 'mobx-state-tree';
3
3
  import { IReactionPublic, IReactionOptions } from 'mobx';
4
- import SimpleFeature, { Feature, isFeature } from './simpleFeature';
4
+ import SimpleFeature, { Feature, SimpleFeatureSerialized, isFeature } from './simpleFeature';
5
5
  import { AssemblyManager, Region, TypeTestedByPredicate } from './types';
6
6
  import { BaseBlock } from './blockTypes';
7
- export type { Feature };
8
7
  export * from './types';
9
8
  export * from './aborting';
10
9
  export * from './when';
11
10
  export * from './range';
12
11
  export * from './dedupe';
13
12
  export { SimpleFeature, isFeature };
13
+ export type { Feature, SimpleFeatureSerialized };
14
14
  export * from './offscreenCanvasPonyfill';
15
15
  export * from './offscreenCanvasUtils';
16
16
  export declare const inDevelopment: boolean;
17
17
  export declare const inProduction: boolean;
18
18
  export declare function useDebounce<T>(value: T, delay: number): T;
19
- export declare function useDebouncedCallback<A extends any[]>(callback: (...args: A) => void, wait?: number): (...args: A) => void;
19
+ export declare function useDebouncedCallback<T>(callback: (...args: T[]) => void, wait?: number): (...args: T[]) => void;
20
20
  /** find the first node in the hierarchy that matches the given predicate */
21
21
  export declare function findParentThat(node: IAnyStateTreeNode, predicate: (thing: IAnyStateTreeNode) => boolean): IAnyStateTreeNode;
22
22
  export declare function springAnimate(fromValue: number, toValue: number, setValue: (value: number) => void, onFinish?: () => void, precision?: number, tension?: number, friction?: number): (() => void)[];
@@ -153,7 +153,7 @@ export declare function bpSpanPx(leftBp: number, rightBp: number, region: {
153
153
  end: number;
154
154
  reversed?: boolean;
155
155
  }, bpPerPx: number): [number, number];
156
- export declare function iterMap<T, U>(iterable: Iterable<T>, func: (item: T) => U, sizeHint?: number): U[];
156
+ export declare function iterMap<T, U>(iter: Iterable<T>, func: (arg: T) => U, sizeHint?: number): U[];
157
157
  /**
158
158
  * Returns the index of the last element in the array where predicate is true,
159
159
  * and -1 otherwise.
@@ -280,8 +280,8 @@ export declare const defaultCodonTable: {
280
280
  GGT: string;
281
281
  };
282
282
  /**
283
- * take CodonTable above and generate larger codon table that includes
284
- * all permutations of upper and lower case nucleotides
283
+ * take CodonTable above and generate larger codon table that includes all
284
+ * permutations of upper and lower case nucleotides
285
285
  */
286
286
  export declare function generateCodonTable(table: any): {
287
287
  [key: string]: string;
@@ -337,8 +337,18 @@ export declare function getUriLink(value: {
337
337
  baseUri?: string;
338
338
  }): string;
339
339
  export declare function getStr(obj: unknown): string;
340
- export declare function measureGridWidth(elements: string[]): number;
340
+ export declare function measureGridWidth(elements: string[], args?: {
341
+ minWidth?: number;
342
+ fontSize?: number;
343
+ maxWidth?: number;
344
+ padding?: number;
345
+ stripHTML?: boolean;
346
+ }): number;
341
347
  export declare function getEnv(obj: any): {
342
348
  pluginManager: PluginManager;
343
349
  };
344
350
  export declare function localStorageGetItem(item: string): string | null | undefined;
351
+ export declare function max(arr: number[]): number;
352
+ export declare function min(arr: number[]): number;
353
+ export declare function sum(arr: number[]): number;
354
+ export declare function avg(arr: number[]): number;
package/util/index.js CHANGED
@@ -30,7 +30,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
30
30
  };
31
31
  Object.defineProperty(exports, "__esModule", { value: true });
32
32
  exports.bytesForRegions = exports.objectHash = exports.hashCode = exports.updateStatus = exports.generateCodonTable = exports.defaultCodonTable = exports.defaultStops = exports.defaultStarts = exports.measureText = exports.rIC = exports.blobToDataURL = exports.complement = exports.reverse = exports.revcom = exports.isElectron = exports.stringify = exports.shorten = exports.minmax = exports.renameRegionsIfNeeded = exports.renameRegionIfNeeded = exports.makeAbortableReaction = exports.findLastIndex = exports.iterMap = exports.bpSpanPx = exports.featureSpanPx = exports.cartesianToPolar = exports.polarToCartesian = exports.degToRad = exports.radToDeg = exports.bpToPx = exports.clamp = exports.compareLocStrings = exports.compareLocs = exports.parseLocString = exports.parseLocStringOneBased = exports.assembleLocStringFast = exports.assembleLocString = exports.getContainingDisplay = exports.getContainingTrack = exports.getContainingView = exports.getSession = exports.findParentThatIs = exports.springAnimate = exports.findParentThat = exports.useDebouncedCallback = exports.useDebounce = exports.inProduction = exports.inDevelopment = exports.isFeature = exports.SimpleFeature = void 0;
33
- exports.localStorageGetItem = exports.getEnv = exports.measureGridWidth = exports.getStr = exports.getUriLink = exports.useLocalStorage = exports.getLayoutId = exports.getViewParams = exports.getTickDisplayStr = exports.toLocale = exports.getBpDisplayStr = exports.supportedIndexingAdapters = void 0;
33
+ exports.avg = exports.sum = exports.min = exports.max = exports.localStorageGetItem = exports.getEnv = exports.measureGridWidth = exports.getStr = exports.getUriLink = exports.useLocalStorage = exports.getLayoutId = exports.getViewParams = exports.getTickDisplayStr = exports.toLocale = exports.getBpDisplayStr = exports.supportedIndexingAdapters = void 0;
34
34
  /* eslint-disable @typescript-eslint/no-explicit-any */
35
35
  const react_1 = require("react");
36
36
  const is_object_1 = __importDefault(require("is-object"));
@@ -66,7 +66,7 @@ function useDebounce(value, delay) {
66
66
  return debouncedValue;
67
67
  }
68
68
  exports.useDebounce = useDebounce;
69
- // https://stackoverflow.com/questions/56283920/how-to-debounce-a-callback-in-functional-component-using-hooks
69
+ // https://stackoverflow.com/questions/56283920/
70
70
  function useDebouncedCallback(callback, wait = 400) {
71
71
  // track args & timeout handle between calls
72
72
  const argsRef = (0, react_1.useRef)();
@@ -504,10 +504,10 @@ function bpSpanPx(leftBp, rightBp, region, bpPerPx) {
504
504
  }
505
505
  exports.bpSpanPx = bpSpanPx;
506
506
  // do an array map of an iterable
507
- function iterMap(iterable, func, sizeHint) {
507
+ function iterMap(iter, func, sizeHint) {
508
508
  const results = sizeHint ? new Array(sizeHint) : [];
509
509
  let counter = 0;
510
- for (const item of iterable) {
510
+ for (const item of iter) {
511
511
  results[counter] = func(item);
512
512
  counter += 1;
513
513
  }
@@ -664,8 +664,10 @@ function stringify({ refName, coord, oob, }) {
664
664
  : '';
665
665
  }
666
666
  exports.stringify = stringify;
667
- // this is recommended in a later comment in https://github.com/electron/electron/issues/2288
668
- // for detecting electron in a renderer process, which is the one that has node enabled for us
667
+ // this is recommended in a later comment in
668
+ // https://github.com/electron/electron/issues/2288 for detecting electron in a
669
+ // renderer process, which is the one that has node enabled for us
670
+ //
669
671
  // const isElectron = process.versions.electron
670
672
  // const i2 = process.versions.hasOwnProperty('electron')
671
673
  exports.isElectron = /electron/i.test(typeof navigator !== 'undefined' ? navigator.userAgent : '');
@@ -829,8 +831,8 @@ exports.defaultCodonTable = {
829
831
  GGT: 'G',
830
832
  };
831
833
  /**
832
- * take CodonTable above and generate larger codon table that includes
833
- * all permutations of upper and lower case nucleotides
834
+ * take CodonTable above and generate larger codon table that includes all
835
+ * permutations of upper and lower case nucleotides
834
836
  */
835
837
  function generateCodonTable(table) {
836
838
  const tempCodonTable = {};
@@ -1002,9 +1004,18 @@ function getStr(obj) {
1002
1004
  : String(obj);
1003
1005
  }
1004
1006
  exports.getStr = getStr;
1007
+ // tries to measure grid width without HTML tags included
1008
+ function coarseStripHTML(s) {
1009
+ return s.replace(/(<([^>]+)>)/gi, '');
1010
+ }
1005
1011
  // heuristic measurement for a column of a @mui/x-data-grid, pass in values from a column
1006
- function measureGridWidth(elements) {
1007
- return Math.max(...elements.map(element => Math.min(Math.max(measureText(getStr(element), 14) + 50, 80), 1000)));
1012
+ function measureGridWidth(elements, args) {
1013
+ const { padding = 30, minWidth = 80, fontSize = 12, maxWidth = 1000, stripHTML = false, } = args || {};
1014
+ return max(elements
1015
+ .map(element => getStr(element))
1016
+ .map(str => (stripHTML ? coarseStripHTML(str) : str))
1017
+ .map(str => measureText(str, fontSize))
1018
+ .map(n => Math.min(Math.max(n + padding, minWidth), maxWidth)));
1008
1019
  }
1009
1020
  exports.measureGridWidth = measureGridWidth;
1010
1021
  function getEnv(obj) {
@@ -1017,3 +1028,31 @@ function localStorageGetItem(item) {
1017
1028
  : undefined;
1018
1029
  }
1019
1030
  exports.localStorageGetItem = localStorageGetItem;
1031
+ function max(arr) {
1032
+ let max = -Infinity;
1033
+ for (let i = 0; i < arr.length; i++) {
1034
+ max = arr[i] > max ? arr[i] : max;
1035
+ }
1036
+ return max;
1037
+ }
1038
+ exports.max = max;
1039
+ function min(arr) {
1040
+ let min = Infinity;
1041
+ for (let i = 0; i < arr.length; i++) {
1042
+ min = arr[i] < min ? arr[i] : min;
1043
+ }
1044
+ return min;
1045
+ }
1046
+ exports.min = min;
1047
+ function sum(arr) {
1048
+ let sum = 0;
1049
+ for (let i = 0; i < arr.length; i++) {
1050
+ sum += arr[i];
1051
+ }
1052
+ return sum;
1053
+ }
1054
+ exports.sum = sum;
1055
+ function avg(arr) {
1056
+ return sum(arr) / arr.length;
1057
+ }
1058
+ exports.avg = avg;
package/util/stats.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.blankStats = exports.scoresToStats = exports.calcPerBaseStats = exports.rectifyStats = exports.calcStdFromSums = void 0;
4
+ const rxjs_1 = require("rxjs");
4
5
  const operators_1 = require("rxjs/operators");
5
6
  /**
6
7
  * calculate standard deviation using the 'shortcut method' that accepts
@@ -96,8 +97,7 @@ async function scoresToStats(region, feats) {
96
97
  featureCount: 0,
97
98
  };
98
99
  let found = false;
99
- const { scoreMin, scoreMax, scoreSum, scoreSumSquares, featureCount } = await feats
100
- .pipe((0, operators_1.reduce)((acc, f) => {
100
+ const { scoreMin, scoreMax, scoreSum, scoreSumSquares, featureCount } = await (0, rxjs_1.firstValueFrom)(feats.pipe((0, operators_1.reduce)((acc, f) => {
101
101
  const s = f.get('score');
102
102
  const summary = f.get('summary');
103
103
  const { scoreMax, scoreMin } = acc;
@@ -108,8 +108,7 @@ async function scoresToStats(region, feats) {
108
108
  acc.featureCount += 1;
109
109
  found = true;
110
110
  return acc;
111
- }, seed))
112
- .toPromise();
111
+ }, seed)));
113
112
  return found
114
113
  ? rectifyStats({
115
114
  scoreMax,