@jbrowse/core 2.10.2 → 2.11.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 (50) hide show
  1. package/BaseFeatureWidget/BaseFeatureDetail/Attributes.js +1 -1
  2. package/BaseFeatureWidget/configSchema.d.ts +2 -0
  3. package/BaseFeatureWidget/configSchema.js +6 -0
  4. package/BaseFeatureWidget/index.d.ts +2 -128
  5. package/BaseFeatureWidget/index.js +4 -168
  6. package/BaseFeatureWidget/stateModelFactory.d.ts +126 -0
  7. package/BaseFeatureWidget/stateModelFactory.js +168 -0
  8. package/Plugin.d.ts +1 -1
  9. package/Plugin.js +0 -3
  10. package/PluginLoader.d.ts +1 -1
  11. package/PluginLoader.js +1 -0
  12. package/PluginManager.d.ts +13 -9
  13. package/PluginManager.js +8 -3
  14. package/ReExports/modules.d.ts +8 -2
  15. package/ReExports/modules.js +16 -5
  16. package/package.json +3 -3
  17. package/pluggableElementTypes/models/BaseTrackModel.d.ts +1 -0
  18. package/pluggableElementTypes/models/BaseTrackModel.js +2 -1
  19. package/pluggableElementTypes/models/InternetAccountModel.d.ts +1 -0
  20. package/pluggableElementTypes/renderers/ServerSideRenderedContent.js +3 -2
  21. package/rpc/BaseRpcDriver.d.ts +3 -3
  22. package/rpc/BaseRpcDriver.js +1 -0
  23. package/rpc/WebWorkerRpcDriver.d.ts +2 -3
  24. package/rpc/WebWorkerRpcDriver.js +1 -1
  25. package/rpc/methods/CoreRender.d.ts +1 -1
  26. package/tsconfig.build.tsbuildinfo +1 -1
  27. package/ui/AssemblySelector.d.ts +5 -5
  28. package/ui/CascadingMenuButton.d.ts +6 -6
  29. package/ui/Dialog.js +1 -1
  30. package/ui/ErrorMessage.d.ts +2 -1
  31. package/ui/ErrorMessage.js +16 -3
  32. package/ui/ErrorMessageStackTraceDialog.d.ts +3 -2
  33. package/ui/ErrorMessageStackTraceDialog.js +61 -31
  34. package/ui/FileSelector/FileSelector.d.ts +5 -5
  35. package/ui/FileSelector/UrlChooser.d.ts +2 -2
  36. package/ui/MenuButton.d.ts +5 -5
  37. package/ui/SnackbarModel.d.ts +21 -30
  38. package/ui/SnackbarModel.js +87 -50
  39. package/ui/Tooltip.d.ts +2 -2
  40. package/ui/theme.d.ts +38 -0
  41. package/ui/theme.js +121 -104
  42. package/util/Base1DViewModel.d.ts +1 -1
  43. package/util/index.d.ts +3 -1
  44. package/util/index.js +16 -5
  45. package/util/io/RemoteFileWithRangeCache.js +14 -31
  46. package/util/jexl.js +1 -0
  47. package/util/offscreenCanvasUtils.js +2 -2
  48. package/util/tracks.js +1 -1
  49. package/util/types/index.d.ts +2 -5
  50. package/util/types/index.js +0 -1
package/ui/theme.js CHANGED
@@ -7,35 +7,57 @@ exports.createJBrowseTheme = exports.createJBrowseBaseTheme = exports.defaultThe
7
7
  const colors_1 = require("@mui/material/colors");
8
8
  const styles_1 = require("@mui/material/styles");
9
9
  const deepmerge_1 = __importDefault(require("deepmerge"));
10
+ const refTheme = (0, styles_1.createTheme)();
10
11
  const midnight = '#0D233F';
11
12
  const grape = '#721E63';
12
- const forest = '#135560';
13
- const mandarin = '#FFB11D';
14
- const refTheme = (0, styles_1.createTheme)();
13
+ const forest = refTheme.palette.augmentColor({ color: { main: '#135560' } });
14
+ const mandarin = refTheme.palette.augmentColor({ color: { main: '#FFB11D' } });
15
+ const bases = {
16
+ A: refTheme.palette.augmentColor({ color: colors_1.green }),
17
+ C: refTheme.palette.augmentColor({ color: colors_1.blue }),
18
+ G: refTheme.palette.augmentColor({ color: colors_1.orange }),
19
+ T: refTheme.palette.augmentColor({ color: colors_1.red }),
20
+ };
21
+ const framesCDS = [
22
+ null,
23
+ refTheme.palette.augmentColor({ color: { main: '#FF8080' } }),
24
+ refTheme.palette.augmentColor({ color: { main: '#80FF80' } }),
25
+ refTheme.palette.augmentColor({ color: { main: '#8080FF' } }),
26
+ refTheme.palette.augmentColor({ color: { main: '#8080FF' } }),
27
+ refTheme.palette.augmentColor({ color: { main: '#80FF80' } }),
28
+ refTheme.palette.augmentColor({ color: { main: '#FF8080' } }),
29
+ ];
30
+ const frames = [
31
+ null,
32
+ refTheme.palette.augmentColor({ color: { main: '#8f8f8f' } }),
33
+ refTheme.palette.augmentColor({ color: { main: '#adadad' } }),
34
+ refTheme.palette.augmentColor({ color: { main: '#d8d8d8' } }),
35
+ refTheme.palette.augmentColor({ color: { main: '#d8d8d8' } }),
36
+ refTheme.palette.augmentColor({ color: { main: '#adadad' } }),
37
+ refTheme.palette.augmentColor({ color: { main: '#8f8f8f' } }),
38
+ ];
39
+ const stopCodon = '#e22';
40
+ const startCodon = '#3e3';
15
41
  function stockTheme() {
16
42
  return {
17
43
  palette: {
18
44
  mode: undefined,
19
45
  primary: { main: midnight },
20
46
  secondary: { main: grape },
21
- tertiary: refTheme.palette.augmentColor({ color: { main: forest } }),
22
- quaternary: refTheme.palette.augmentColor({ color: { main: mandarin } }),
23
- stopCodon: '#e22',
24
- startCodon: '#3e3',
25
- bases: {
26
- A: refTheme.palette.augmentColor({ color: colors_1.green }),
27
- C: refTheme.palette.augmentColor({ color: colors_1.blue }),
28
- G: refTheme.palette.augmentColor({ color: colors_1.orange }),
29
- T: refTheme.palette.augmentColor({ color: colors_1.red }),
30
- },
47
+ tertiary: forest,
48
+ quaternary: mandarin,
49
+ highlight: mandarin,
50
+ stopCodon,
51
+ startCodon,
52
+ bases,
53
+ frames,
54
+ framesCDS,
31
55
  },
32
56
  components: {
33
57
  MuiLink: {
34
58
  styleOverrides: {
35
59
  // the default link color uses theme.palette.primary.main which is
36
60
  // very bad with dark mode+midnight primary
37
- //
38
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
39
61
  root: ({ theme }) => ({
40
62
  color: theme.palette.tertiary.main,
41
63
  }),
@@ -46,14 +68,14 @@ function stockTheme() {
46
68
  }
47
69
  function getDefaultTheme() {
48
70
  return {
49
- name: 'Default (from config)',
50
71
  ...stockTheme(),
72
+ name: 'Default (from config)',
51
73
  };
52
74
  }
53
75
  function getLightStockTheme() {
54
76
  return {
55
- name: 'Light (stock)',
56
77
  ...stockTheme(),
78
+ name: 'Light (stock)',
57
79
  };
58
80
  }
59
81
  function getDarkStockTheme() {
@@ -63,16 +85,14 @@ function getDarkStockTheme() {
63
85
  mode: 'dark',
64
86
  primary: { main: midnight },
65
87
  secondary: { main: grape },
66
- tertiary: refTheme.palette.augmentColor({ color: { main: forest } }),
67
- quaternary: refTheme.palette.augmentColor({ color: { main: mandarin } }),
68
- stopCodon: '#e22',
69
- startCodon: '#3e3',
70
- bases: {
71
- A: refTheme.palette.augmentColor({ color: colors_1.green }),
72
- C: refTheme.palette.augmentColor({ color: colors_1.blue }),
73
- G: refTheme.palette.augmentColor({ color: colors_1.orange }),
74
- T: refTheme.palette.augmentColor({ color: colors_1.red }),
75
- },
88
+ tertiary: forest,
89
+ quaternary: mandarin,
90
+ highlight: mandarin,
91
+ stopCodon,
92
+ startCodon,
93
+ bases,
94
+ frames,
95
+ framesCDS,
76
96
  },
77
97
  components: {
78
98
  MuiAppBar: {
@@ -80,9 +100,8 @@ function getDarkStockTheme() {
80
100
  enableColorOnDark: true,
81
101
  },
82
102
  styleOverrides: {
83
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
84
- primary: (props) => {
85
- return props.theme.palette.primary.main;
103
+ root: ({ theme }) => {
104
+ return theme.palette.primary.main;
86
105
  },
87
106
  },
88
107
  },
@@ -97,15 +116,13 @@ function getDarkMinimalTheme() {
97
116
  primary: { main: colors_1.grey[700] },
98
117
  secondary: { main: colors_1.grey[800] },
99
118
  tertiary: refTheme.palette.augmentColor({ color: { main: colors_1.grey[900] } }),
100
- quaternary: refTheme.palette.augmentColor({ color: { main: mandarin } }),
101
- stopCodon: '#e22',
102
- startCodon: '#3e3',
103
- bases: {
104
- A: refTheme.palette.augmentColor({ color: colors_1.green }),
105
- C: refTheme.palette.augmentColor({ color: colors_1.blue }),
106
- G: refTheme.palette.augmentColor({ color: colors_1.orange }),
107
- T: refTheme.palette.augmentColor({ color: colors_1.red }),
108
- },
119
+ quaternary: mandarin,
120
+ highlight: mandarin,
121
+ stopCodon,
122
+ startCodon,
123
+ bases,
124
+ frames,
125
+ framesCDS,
109
126
  },
110
127
  };
111
128
  }
@@ -116,15 +133,13 @@ function getMinimalTheme() {
116
133
  primary: { main: colors_1.grey[900] },
117
134
  secondary: { main: colors_1.grey[800] },
118
135
  tertiary: refTheme.palette.augmentColor({ color: { main: colors_1.grey[900] } }),
119
- quaternary: refTheme.palette.augmentColor({ color: { main: mandarin } }),
120
- stopCodon: '#e22',
121
- startCodon: '#3e3',
122
- bases: {
123
- A: refTheme.palette.augmentColor({ color: colors_1.green }),
124
- C: refTheme.palette.augmentColor({ color: colors_1.blue }),
125
- G: refTheme.palette.augmentColor({ color: colors_1.orange }),
126
- T: refTheme.palette.augmentColor({ color: colors_1.red }),
127
- },
136
+ quaternary: mandarin,
137
+ highlight: mandarin,
138
+ stopCodon,
139
+ startCodon,
140
+ bases,
141
+ frames,
142
+ framesCDS,
128
143
  },
129
144
  };
130
145
  }
@@ -135,38 +150,43 @@ exports.defaultThemes = {
135
150
  darkMinimal: getDarkMinimalTheme(),
136
151
  darkStock: getDarkStockTheme(),
137
152
  };
138
- function createDefaultProps(theme) {
153
+ function overwriteArrayMerge(_, sourceArray) {
154
+ return sourceArray;
155
+ }
156
+ function createJBrowseBaseTheme(theme) {
139
157
  var _a, _b, _c, _d, _e, _f;
140
- return {
158
+ const themeP = {
159
+ palette: theme === null || theme === void 0 ? void 0 : theme.palette,
160
+ typography: {
161
+ fontSize: 12,
162
+ },
163
+ spacing: 4,
141
164
  components: {
142
165
  MuiButton: {
143
166
  defaultProps: {
144
167
  size: 'small',
145
168
  },
146
169
  styleOverrides: {
147
- // the default button, especially when not using variant=contained, uses
148
- // theme.palette.primary.main for text which is very bad with dark
149
- // mode+midnight primary
170
+ // the default button, especially when not using variant=contained,
171
+ // uses theme.palette.primary.main for text which is very bad with
172
+ // dark mode+midnight primary
150
173
  //
151
174
  // keeps text secondary for darkmode, uses
152
175
  // a text-like coloring to ensure contrast
153
176
  // xref https://stackoverflow.com/a/72546130/2129219
154
- //
155
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
156
- root: (props) => {
157
- const { theme } = props;
158
- return theme.palette.mode === 'dark'
159
- ? {
160
- color: theme.palette.text.primary,
161
- }
162
- : undefined;
163
- },
177
+ root: ({ theme }) => theme.palette.mode === 'dark'
178
+ ? {
179
+ color: theme.palette.text.primary,
180
+ }
181
+ : undefined,
164
182
  },
165
183
  },
166
184
  MuiAccordion: {
167
185
  defaultProps: {
168
186
  disableGutters: true,
169
- TransitionProps: { timeout: 150 },
187
+ TransitionProps: {
188
+ timeout: 150,
189
+ },
170
190
  },
171
191
  },
172
192
  MuiFilledInput: {
@@ -273,18 +293,16 @@ function createDefaultProps(theme) {
273
293
  // mode+midnight primary
274
294
  //
275
295
  // keeps the forest-green checkbox by default but for darkmode, uses
276
- // a text-like coloring to ensure contrast
277
- // xref https://stackoverflow.com/a/72546130/2129219
278
- root: ({ theme }) => {
279
- return theme.palette.mode === 'dark'
280
- ? {
296
+ // a text-like coloring to ensure contrast xref
297
+ // https://stackoverflow.com/a/72546130/2129219
298
+ root: ({ theme }) => theme.palette.mode === 'dark'
299
+ ? {
300
+ color: theme.palette.text.secondary,
301
+ '&.Mui-checked': {
281
302
  color: theme.palette.text.secondary,
282
- '&.Mui-checked': {
283
- color: theme.palette.text.secondary,
284
- },
285
- }
286
- : undefined;
287
- },
303
+ },
304
+ }
305
+ : undefined,
288
306
  },
289
307
  },
290
308
  MuiRadio: {
@@ -296,16 +314,14 @@ function createDefaultProps(theme) {
296
314
  // keeps the forest-green checkbox by default but for darkmode, uses
297
315
  // a text-like coloring to ensure contrast
298
316
  // xref https://stackoverflow.com/a/72546130/2129219
299
- root: ({ theme }) => {
300
- return theme.palette.mode === 'dark'
301
- ? {
317
+ root: ({ theme }) => theme.palette.mode === 'dark'
318
+ ? {
319
+ color: theme.palette.text.secondary,
320
+ '&.Mui-checked': {
302
321
  color: theme.palette.text.secondary,
303
- '&.Mui-checked': {
304
- color: theme.palette.text.secondary,
305
- },
306
- }
307
- : undefined;
308
- },
322
+ },
323
+ }
324
+ : undefined,
309
325
  },
310
326
  },
311
327
  MuiFormLabel: {
@@ -318,16 +334,14 @@ function createDefaultProps(theme) {
318
334
  // a text-like coloring to ensure contrast
319
335
  // xref https://stackoverflow.com/a/72546130/2129219
320
336
  //
321
- root: ({ theme }) => {
322
- return theme.palette.mode === 'dark'
323
- ? {
337
+ root: ({ theme }) => theme.palette.mode === 'dark'
338
+ ? {
339
+ color: theme.palette.text.secondary,
340
+ '&.Mui-focused': {
324
341
  color: theme.palette.text.secondary,
325
- '&.Mui-focused': {
326
- color: theme.palette.text.secondary,
327
- },
328
- }
329
- : undefined;
330
- },
342
+ },
343
+ }
344
+ : undefined,
331
345
  },
332
346
  },
333
347
  MuiAccordionSummary: {
@@ -349,19 +363,14 @@ function createDefaultProps(theme) {
349
363
  },
350
364
  },
351
365
  };
352
- }
353
- function createJBrowseBaseTheme(theme) {
354
- return (0, deepmerge_1.default)({
355
- palette: theme === null || theme === void 0 ? void 0 : theme.palette,
356
- typography: { fontSize: 12 },
357
- spacing: 4,
358
- ...createDefaultProps(theme),
359
- }, theme || {});
366
+ return (0, deepmerge_1.default)(themeP, theme || {}, { arrayMerge: overwriteArrayMerge });
360
367
  }
361
368
  exports.createJBrowseBaseTheme = createJBrowseBaseTheme;
362
369
  function createJBrowseTheme(configTheme = {}, themes = exports.defaultThemes, themeName = 'default') {
363
370
  return (0, styles_1.createTheme)(createJBrowseBaseTheme(themeName === 'default'
364
- ? (0, deepmerge_1.default)(themes.default, augmentTheme(configTheme))
371
+ ? (0, deepmerge_1.default)(themes.default, augmentTheme(configTheme), {
372
+ arrayMerge: overwriteArrayMerge,
373
+ })
365
374
  : augmentThemePlus(themes[themeName]) || themes.default));
366
375
  }
367
376
  exports.createJBrowseTheme = createJBrowseTheme;
@@ -394,14 +403,22 @@ function augmentThemePlus(theme = {}) {
394
403
  if (!((_a = theme === null || theme === void 0 ? void 0 : theme.palette) === null || _a === void 0 ? void 0 : _a.quaternary)) {
395
404
  theme = (0, deepmerge_1.default)(theme, {
396
405
  palette: {
397
- quaternary: refTheme.palette.augmentColor({ color: { main: '#aaa' } }),
406
+ quaternary: refTheme.palette.augmentColor({
407
+ color: {
408
+ main: '#aaa',
409
+ },
410
+ }),
398
411
  },
399
412
  });
400
413
  }
401
414
  if (!((_b = theme === null || theme === void 0 ? void 0 : theme.palette) === null || _b === void 0 ? void 0 : _b.tertiary)) {
402
415
  theme = (0, deepmerge_1.default)(theme, {
403
416
  palette: {
404
- tertiary: refTheme.palette.augmentColor({ color: { main: '#aaa' } }),
417
+ tertiary: refTheme.palette.augmentColor({
418
+ color: {
419
+ main: '#aaa',
420
+ },
421
+ }),
405
422
  },
406
423
  });
407
424
  }
@@ -95,7 +95,7 @@ declare const Base1DView: import("mobx-state-tree").IModelType<{
95
95
  bpToPx({ refName, coord, regionNumber, }: {
96
96
  refName: string;
97
97
  coord: number;
98
- regionNumber?: number | undefined;
98
+ regionNumber?: number;
99
99
  }): number | undefined;
100
100
  } & {
101
101
  /**
package/util/index.d.ts CHANGED
@@ -22,7 +22,7 @@ export declare function useDebouncedCallback<T>(callback: (...args: T[]) => void
22
22
  * find the first node in the hierarchy that matches the given predicate
23
23
  */
24
24
  export declare function findParentThat(node: IAnyStateTreeNode, predicate: (thing: IAnyStateTreeNode) => boolean): IAnyStateTreeNode;
25
- export declare function springAnimate(fromValue: number, toValue: number, setValue: (value: number) => void, onFinish?: () => void, precision?: number, tension?: number, friction?: number): (() => void)[];
25
+ export declare function springAnimate(fromValue: number, toValue: number, setValue: (value: number) => void, onFinish?: () => void, precision?: number, tension?: number, friction?: number, clamp?: boolean): (() => void)[];
26
26
  /**
27
27
  * find the first node in the hierarchy that matches the given 'is' typescript
28
28
  * type guard predicate
@@ -235,6 +235,8 @@ export declare function reverse(seqString: string): string;
235
235
  export declare const complement: (seqString: string) => string;
236
236
  export declare const rIC: (((callback: IdleRequestCallback, options?: IdleRequestOptions | undefined) => number) & typeof requestIdleCallback) | ((cb: Function) => any);
237
237
  export declare function measureText(str: unknown, fontSize?: number): number;
238
+ export type Frame = 1 | 2 | 3 | -1 | -2 | -3;
239
+ export declare function getFrame(start: number, end: number, strand: 1 | -1, phase: 0 | 1 | 2): Frame;
238
240
  export declare const defaultStarts: string[];
239
241
  export declare const defaultStops: string[];
240
242
  export declare const defaultCodonTable: {
package/util/index.js CHANGED
@@ -17,8 +17,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
17
17
  return (mod && mod.__esModule) ? mod : { "default": mod };
18
18
  };
19
19
  Object.defineProperty(exports, "__esModule", { value: true });
20
- exports.toLocale = exports.getBpDisplayStr = exports.isSupportedIndexingAdapter = exports.bytesForRegions = exports.objectHash = exports.hashCode = exports.updateStatus = exports.generateCodonTable = exports.defaultCodonTable = exports.defaultStops = exports.defaultStarts = exports.measureText = exports.rIC = exports.complement = exports.reverse = exports.revcom = exports.isElectron = exports.stringify = exports.shorten = exports.minmax = exports.renameRegionsIfNeeded = exports.renameRegionIfNeeded = exports.makeAbortableReaction = exports.findLast = 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.useWidthSetter = exports.useDebounce = void 0;
21
- exports.blobToDataURL = exports.isFeature = exports.SimpleFeature = exports.renderToStaticMarkup = exports.stripAlpha = exports.gatherOverlaps = exports.mergeIntervals = exports.notEmpty = exports.groupBy = exports.avg = exports.sum = exports.min = exports.max = exports.localStorageSetItem = exports.localStorageGetItem = exports.getEnv = exports.measureGridWidth = exports.linkify = exports.coarseStripHTML = exports.getStr = exports.getUriLink = exports.useLocalStorage = exports.getLayoutId = exports.getViewParams = exports.getTickDisplayStr = void 0;
20
+ exports.getBpDisplayStr = exports.isSupportedIndexingAdapter = exports.bytesForRegions = exports.objectHash = exports.hashCode = exports.updateStatus = exports.generateCodonTable = exports.defaultCodonTable = exports.defaultStops = exports.defaultStarts = exports.getFrame = exports.measureText = exports.rIC = exports.complement = exports.reverse = exports.revcom = exports.isElectron = exports.stringify = exports.shorten = exports.minmax = exports.renameRegionsIfNeeded = exports.renameRegionIfNeeded = exports.makeAbortableReaction = exports.findLast = 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.useWidthSetter = exports.useDebounce = void 0;
21
+ exports.blobToDataURL = exports.isFeature = exports.SimpleFeature = exports.renderToStaticMarkup = exports.stripAlpha = exports.gatherOverlaps = exports.mergeIntervals = exports.notEmpty = exports.groupBy = exports.avg = exports.sum = exports.min = exports.max = exports.localStorageSetItem = exports.localStorageGetItem = exports.getEnv = exports.measureGridWidth = exports.linkify = exports.coarseStripHTML = exports.getStr = exports.getUriLink = exports.useLocalStorage = exports.getLayoutId = exports.getViewParams = exports.getTickDisplayStr = exports.toLocale = void 0;
22
22
  /* eslint-disable @typescript-eslint/no-explicit-any */
23
23
  const react_1 = require("react");
24
24
  const is_object_1 = __importDefault(require("is-object"));
@@ -116,7 +116,7 @@ function findParentThat(node, predicate) {
116
116
  }
117
117
  exports.findParentThat = findParentThat;
118
118
  // based on https://github.com/react-spring/react-spring/blob/cd5548a987383b8023efd620f3726a981f9e18ea/src/animated/FrameLoop.ts
119
- function springAnimate(fromValue, toValue, setValue, onFinish = () => { }, precision = 0, tension = 170, friction = 26) {
119
+ function springAnimate(fromValue, toValue, setValue, onFinish = () => { }, precision = 0, tension = 400, friction = 20, clamp = true) {
120
120
  const mass = 1;
121
121
  if (!precision) {
122
122
  precision = Math.abs(toValue - fromValue) / 1000;
@@ -142,7 +142,12 @@ function springAnimate(fromValue, toValue, setValue, onFinish = () => { }, preci
142
142
  }
143
143
  const isVelocity = Math.abs(velocity) <= precision;
144
144
  const isDisplacement = tension !== 0 ? Math.abs(toValue - position) <= precision : true;
145
- const endOfAnimation = isVelocity && isDisplacement;
145
+ const isOvershooting = clamp && tension !== 0
146
+ ? fromValue < toValue
147
+ ? position > toValue
148
+ : position < toValue
149
+ : false;
150
+ const endOfAnimation = isOvershooting || (isVelocity && isDisplacement);
146
151
  if (endOfAnimation) {
147
152
  setValue(toValue);
148
153
  onFinish();
@@ -776,6 +781,12 @@ function measureText(str, fontSize = 10) {
776
781
  return total * fontSize;
777
782
  }
778
783
  exports.measureText = measureText;
784
+ function getFrame(start, end, strand, phase) {
785
+ return strand === 1
786
+ ? (((start + phase) % 3) + 1)
787
+ : (-1 * ((end - phase) % 3) - 1);
788
+ }
789
+ exports.getFrame = getFrame;
779
790
  exports.defaultStarts = ['ATG'];
780
791
  exports.defaultStops = ['TAA', 'TAG', 'TGA'];
781
792
  exports.defaultCodonTable = {
@@ -1020,7 +1031,7 @@ function coarseStripHTML(s) {
1020
1031
  exports.coarseStripHTML = coarseStripHTML;
1021
1032
  // based on autolink-js, license MIT
1022
1033
  function linkify(s) {
1023
- const pattern = /(^|[\s\n]|<[A-Za-z]*\/?>)((?:https?|ftp):\/\/[\-A-Z0-9+\u0026\u2019@#\/%?=()~_|!:,.;]*[\-A-Z0-9+\u0026@#\/%=~()_|])/gi;
1034
+ const pattern = /(^|[\s\n]|<[A-Za-z]*\/?>)((?:https?|ftp):\/\/[-A-Z0-9+\u0026\u2019@#/%?=()~_|!:,.;]*[-A-Z0-9+\u0026@#/%=~()_|])/gi;
1024
1035
  return s.replaceAll(pattern, '$1<a href=\'$2\' target="_blank">$2</a>');
1025
1036
  }
1026
1037
  exports.linkify = linkify;
@@ -25,55 +25,38 @@ function clearCache() {
25
25
  exports.clearCache = clearCache;
26
26
  class RemoteFileWithRangeCache extends generic_filehandle_1.RemoteFile {
27
27
  async fetch(url, init) {
28
- if (!fetchers[String(url)]) {
29
- fetchers[String(url)] = this.fetchBinaryRange.bind(this);
28
+ var _a;
29
+ const str = String(url);
30
+ if (!fetchers[str]) {
31
+ fetchers[str] = this.fetchBinaryRange.bind(this);
30
32
  }
31
33
  // if it is a range request, route it through the range cache
32
- const requestHeaders = init === null || init === void 0 ? void 0 : init.headers;
33
- let range;
34
- if (requestHeaders) {
35
- if (requestHeaders instanceof Headers) {
36
- range = requestHeaders.get('range');
37
- }
38
- else if (Array.isArray(requestHeaders)) {
39
- ;
40
- [, range] = requestHeaders.find(([key]) => key === 'range') || [
41
- undefined,
42
- undefined,
43
- ];
44
- }
45
- else {
46
- range = requestHeaders.range;
47
- }
48
- }
34
+ const range = (_a = new Headers(init === null || init === void 0 ? void 0 : init.headers)) === null || _a === void 0 ? void 0 : _a.get('range');
49
35
  if (range) {
50
36
  const rangeParse = /bytes=(\d+)-(\d+)/.exec(range);
51
37
  if (rangeParse) {
52
38
  const [, start, end] = rangeParse;
53
39
  const s = Number.parseInt(start, 10);
54
40
  const e = Number.parseInt(end, 10);
55
- const response = (await globalRangeCache.getRange(url, s, e - s + 1, {
56
- signal: init === null || init === void 0 ? void 0 : init.signal,
57
- }));
58
- const { headers } = response;
59
- return new Response(response.buffer, { status: 206, headers });
41
+ const len = e - s;
42
+ const { buffer, headers } = (await globalRangeCache.getRange(url, s, len + 1, { signal: init === null || init === void 0 ? void 0 : init.signal }));
43
+ return new Response(buffer, { status: 206, headers });
60
44
  }
61
45
  }
62
46
  return super.fetch(url, init);
63
47
  }
64
48
  async fetchBinaryRange(url, start, end, options = {}) {
65
49
  const requestDate = new Date();
66
- const requestHeaders = {
67
- ...options.headers,
68
- range: `bytes=${start}-${end}`,
69
- };
70
50
  const res = await super.fetch(url, {
71
51
  ...options,
72
- headers: requestHeaders,
52
+ headers: {
53
+ ...options.headers,
54
+ range: `bytes=${start}-${end}`,
55
+ },
73
56
  });
74
57
  const responseDate = new Date();
75
- if (res.status !== 206) {
76
- const errorMessage = `HTTP ${res.status} (${res.statusText}) when fetching ${url} bytes ${start}-${end}`;
58
+ if (!res.ok) {
59
+ const errorMessage = `HTTP ${res.status} fetching ${url} bytes ${start}-${end}`;
77
60
  const hint = ' (should be 206 for range requests)';
78
61
  throw new Error(`${errorMessage}${res.status === 200 ? hint : ''}`);
79
62
  }
package/util/jexl.js CHANGED
@@ -50,6 +50,7 @@ function default_1( /* config?: any*/) {
50
50
  s.substring(start, end));
51
51
  j.addFunction('toLowerCase', (s) => s.toLowerCase());
52
52
  j.addFunction('toUpperCase', (s) => s.toUpperCase());
53
+ j.addFunction('jsonParse', (s) => JSON.parse(s));
53
54
  j.addFunction('trim', (s) => s.trim());
54
55
  j.addFunction('trimEnd', (s) => s.trimEnd());
55
56
  j.addFunction('trimStart', (s) => s.trimStart());
@@ -91,8 +91,8 @@ async function getSerializedSvg(results) {
91
91
  }
92
92
  exports.getSerializedSvg = getSerializedSvg;
93
93
  function ReactRendering({ rendering, }) {
94
- return (react_1.default.createElement(react_1.default.Fragment, null, react_1.default.isValidElement(rendering.reactElement) ? (rendering.reactElement) : (react_1.default.createElement("g", {
94
+ return react_1.default.isValidElement(rendering.reactElement) ? (rendering.reactElement) : (react_1.default.createElement("g", {
95
95
  /* eslint-disable-next-line react/no-danger */
96
- dangerouslySetInnerHTML: { __html: rendering.html || '' } }))));
96
+ dangerouslySetInnerHTML: { __html: rendering.html || '' } }));
97
97
  }
98
98
  exports.ReactRendering = ReactRendering;
package/util/tracks.js CHANGED
@@ -119,7 +119,7 @@ function getFileName(track) {
119
119
  const blob = 'blobId' in track ? track : undefined;
120
120
  return ((blob === null || blob === void 0 ? void 0 : blob.name) ||
121
121
  (uri === null || uri === void 0 ? void 0 : uri.slice(uri.lastIndexOf('/') + 1)) ||
122
- (localPath === null || localPath === void 0 ? void 0 : localPath.slice(localPath.lastIndexOf('/') + 1)) ||
122
+ (localPath === null || localPath === void 0 ? void 0 : localPath.slice((localPath === null || localPath === void 0 ? void 0 : localPath.replace(/\\/g, '/').lastIndexOf('/')) + 1)) ||
123
123
  '');
124
124
  }
125
125
  exports.getFileName = getFileName;
@@ -19,7 +19,7 @@ export interface AbstractViewContainer extends IStateTreeNode<IType<any, unknown
19
19
  export declare function isViewContainer(thing: unknown): thing is AbstractViewContainer;
20
20
  export type NotificationLevel = 'error' | 'info' | 'warning' | 'success';
21
21
  export interface SnackAction {
22
- name: string;
22
+ name: React.ReactElement;
23
23
  onClick: () => void;
24
24
  }
25
25
  export type AssemblyManager = Instance<ReturnType<typeof assemblyManager>>;
@@ -64,6 +64,7 @@ export interface AbstractSessionModel extends AbstractViewContainer {
64
64
  clearSelection: () => void;
65
65
  duplicateCurrentSession?: () => void;
66
66
  notify: (message: string, level?: NotificationLevel, action?: SnackAction) => void;
67
+ notifyError: (message: string, error?: unknown, extra?: unknown) => void;
67
68
  assemblyManager: AssemblyManager;
68
69
  version: string;
69
70
  getTrackActionMenuItems?: Function;
@@ -203,10 +204,6 @@ export interface AbstractRootModel {
203
204
  }
204
205
  /** root model with more included for the heavier JBrowse web and desktop app */
205
206
  export interface AppRootModel extends AbstractRootModel {
206
- isAssemblyEditing: boolean;
207
- isDefaultSessionEditing: boolean;
208
- setAssemblyEditing: (arg: boolean) => boolean;
209
- setDefaultSessionEditing: (arg: boolean) => boolean;
210
207
  internetAccounts: BaseInternetAccountModel[];
211
208
  findAppropriateInternetAccount(location: UriLocation): BaseInternetAccountModel | undefined;
212
209
  }
@@ -101,7 +101,6 @@ exports.isTrackViewModel = isTrackViewModel;
101
101
  function isAppRootModel(thing) {
102
102
  return (typeof thing === 'object' &&
103
103
  thing !== null &&
104
- 'isAssemblyEditing' in thing &&
105
104
  'findAppropriateInternetAccount' in thing);
106
105
  }
107
106
  exports.isAppRootModel = isAppRootModel;