@jbrowse/core 5.0.0-beta.10 → 5.0.0-beta.11

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 (67) hide show
  1. package/README.md +113 -5
  2. package/esm/BaseFeatureWidget/BaseFeatureDetail/ArrayValue.js +0 -2
  3. package/esm/BaseFeatureWidget/BaseFeatureDetail/BasicValue.js +22 -6
  4. package/esm/BaseFeatureWidget/BaseFeatureDetail/jexlFilterActions.js +3 -4
  5. package/esm/BaseFeatureWidget/SequenceFeatureDetails/useSequenceData.js +8 -5
  6. package/esm/CorePlugin.js +32 -1
  7. package/esm/ReExports/coreModules.generated.js +248 -246
  8. package/esm/ReExports/coreWorkerModules.generated.js +246 -244
  9. package/esm/ReExports/list.js +3 -2
  10. package/esm/configuration/index.d.ts +2 -0
  11. package/esm/configuration/index.js +1 -0
  12. package/esm/configuration/plot.d.ts +61 -0
  13. package/esm/configuration/plot.js +142 -0
  14. package/esm/pluggableElementTypes/DisplayType.d.ts +7 -0
  15. package/esm/pluggableElementTypes/DisplayType.js +6 -0
  16. package/esm/pluggableElementTypes/WidgetType.d.ts +6 -0
  17. package/esm/pluggableElementTypes/WidgetType.js +6 -0
  18. package/esm/pluggableElementTypes/index.js +1 -8
  19. package/esm/pluggableElementTypes/models/BaseDisplayModel.d.ts +57 -1
  20. package/esm/pluggableElementTypes/models/BaseDisplayModel.js +84 -2
  21. package/esm/pluggableElementTypes/models/BaseViewModel.d.ts +2 -2
  22. package/esm/pluggableElementTypes/models/BaseViewModel.js +1 -1
  23. package/esm/ui/JexlFilterDialog.d.ts +1 -1
  24. package/esm/ui/JexlFilterDialog.js +2 -3
  25. package/esm/util/TimeTraveller.d.ts +3 -0
  26. package/esm/util/TimeTraveller.js +34 -2
  27. package/esm/util/baseDisplayConfig.d.ts +8 -0
  28. package/esm/util/baseDisplayConfig.js +27 -0
  29. package/esm/util/cachedSetup.d.ts +16 -6
  30. package/esm/util/cachedSetup.js +108 -38
  31. package/esm/util/cellMatches.d.ts +23 -0
  32. package/esm/util/cellMatches.js +264 -0
  33. package/esm/util/cellsStep.d.ts +29 -0
  34. package/esm/util/cellsStep.js +437 -0
  35. package/esm/util/copyToClipboard.js +8 -1
  36. package/esm/util/createAbortRotation.js +3 -3
  37. package/esm/util/featureTransforms.d.ts +7 -6
  38. package/esm/util/featureTransforms.js +131 -479
  39. package/esm/util/fetchPhases.d.ts +1 -1
  40. package/esm/util/formatBytes.js +1 -1
  41. package/esm/util/formatGuessers.d.ts +25 -14
  42. package/esm/util/formatGuessers.js +42 -27
  43. package/esm/util/formatRelativeTime.js +1 -1
  44. package/esm/util/getLocationUri.d.ts +2 -1
  45. package/esm/util/getLocationUri.js +8 -2
  46. package/esm/util/groupKeys.d.ts +4 -5
  47. package/esm/util/groupKeys.js +7 -6
  48. package/esm/util/intervals.js +9 -4
  49. package/esm/util/io/index.js +3 -1
  50. package/esm/util/jexlFilters.d.ts +31 -49
  51. package/esm/util/jexlFilters.js +29 -39
  52. package/esm/util/locString.js +5 -2
  53. package/esm/util/markEncoding.js +48 -8
  54. package/esm/util/markEncodingTypes.d.ts +8 -1
  55. package/esm/util/springAnimate.js +1 -1
  56. package/esm/util/stepTables.d.ts +14 -0
  57. package/esm/util/stepTables.js +38 -4
  58. package/esm/util/tabix.d.ts +6 -2
  59. package/esm/util/tabix.js +2 -2
  60. package/esm/util/tracks.d.ts +3 -30
  61. package/esm/util/tracks.js +4 -39
  62. package/esm/util/unknownSnapshotKeys.d.ts +3 -1
  63. package/esm/util/unknownSnapshotKeys.js +5 -11
  64. package/esm/util/usePanZoom.js +10 -3
  65. package/esm/util/useRafCommit.js +1 -0
  66. package/esm/util/withFeatureDetails.js +4 -0
  67. package/package.json +9 -8
package/README.md CHANGED
@@ -99,6 +99,19 @@ historically drifted.
99
99
 
100
100
  [Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/core/src/util/bandLayout.ts)
101
101
 
102
+ ### baseDisplayConfig
103
+
104
+ The base's entry for this display, hydrated, which a reset returns to and "is
105
+ this the reader's" compares against: the config.json's, or the one a track the
106
+ session owns was added with; empty in a session that keeps no base.
107
+
108
+ ```js
109
+ // type signature
110
+ (self: object) => Record<string, unknown>
111
+ ```
112
+
113
+ [Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/core/src/util/baseDisplayConfig.ts)
114
+
102
115
  ### BinStep
103
116
 
104
117
  Place every feature in a genome-aligned bin of `step` bp, writing the bin's
@@ -1057,6 +1070,22 @@ steps that follow it read the rows already in section order.
1057
1070
 
1058
1071
  [Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/core/src/util/featureTransforms.ts)
1059
1072
 
1073
+ ### liftPlot
1074
+
1075
+ A draft as the display's config would hold it, through the schema's own lift and
1076
+ checks: a shorthand becomes its object, a default falls off, and what a config
1077
+ file is refused for throws, a key outside the plot included. The node is never
1078
+ attached, so nothing on the display is touched; a display reads its typed
1079
+ members off it. The draft is copied first, since MST freezes what it creates
1080
+ from.
1081
+
1082
+ ```js
1083
+ // type signature
1084
+ (conf: AnyConfigurationModel, draft: Plot) => AnyConfigurationModel
1085
+ ```
1086
+
1087
+ [Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/core/src/configuration/plot.ts)
1088
+
1060
1089
  ### ListColumn
1061
1090
 
1062
1091
  A list of rows per row: row `i`'s entries are the rows of `entries` from
@@ -1123,14 +1152,15 @@ the worker.
1123
1152
  ### matedBy
1124
1153
 
1125
1154
  How a record states its other end, or undefined where it states none: the `mate`
1126
- a paired adapter fills (BEDPE, STAR-Fusion), or an `ALT` the breakend and
1127
- symbolic-SV readers resolve. The `mate` step admits exactly the features this
1128
- names one for, so a caller deciding whether links are the picture a track wants
1129
- asks here rather than re-reading the fields.
1155
+ a paired adapter fills (BEDPE, STAR-Fusion), an `ALT` the breakend and
1156
+ symbolic-SV readers resolve, or a read's `next_ref` and `next_pos`. The `mate`
1157
+ step admits exactly the features this names one for, so a caller deciding
1158
+ whether links are the picture a track wants asks here rather than re-reading the
1159
+ fields.
1130
1160
 
1131
1161
  ```js
1132
1162
  // type signature
1133
- (f: Feature) => "alt" | "mate" | undefined
1163
+ (f: Feature) => "alt" | "mate" | "pair" | undefined
1134
1164
  ```
1135
1165
 
1136
1166
  [Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/core/src/util/featureTransforms.ts)
@@ -1228,6 +1258,18 @@ every comparison against it declines.
1228
1258
 
1229
1259
  [Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/core/src/util/thresholdScale.ts)
1230
1260
 
1261
+ ### parsePlot
1262
+
1263
+ The text as a plot, refusing a key the display's plot does not hold. The schema
1264
+ is the parser past this point.
1265
+
1266
+ ```js
1267
+ // type signature
1268
+ (text: string, keys: readonly string[]) => Plot
1269
+ ```
1270
+
1271
+ [Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/core/src/configuration/plot.ts)
1272
+
1231
1273
  ### parseSvAlt
1232
1274
 
1233
1275
  Parse raw (non-assembly-resolved) mate coordinates from a VCF SV feature+alt.
@@ -1253,6 +1295,72 @@ packs each section on its own.
1253
1295
 
1254
1296
  [Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/core/src/util/markEncodingTypes.ts)
1255
1297
 
1298
+ ### Plot
1299
+
1300
+ A display's plot settings as written: a key left out is left alone, and `null`
1301
+ resets that setting. Untyped, since a value may be a shorthand the schema lifts,
1302
+ and the schema is what judges it.
1303
+
1304
+ [Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/core/src/configuration/plot.ts)
1305
+
1306
+ ### PLOT_VOCABULARY
1307
+
1308
+ The grammar's settings, by the slot name every display that has one gives it,
1309
+ and what each holds: what "Edit plot..." shows and an agent reads as a display's
1310
+ `plot`. A display's plot is the ones its config declares (`plotKeysOf`).
1311
+
1312
+ ```js
1313
+ // type signature
1314
+ Readonly<Record<string, string>>
1315
+ ```
1316
+
1317
+ [Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/core/src/configuration/plot.ts)
1318
+
1319
+ ### PlotExample
1320
+
1321
+ A worked example of a display's plot: the text it fills the editor with, and
1322
+ what it does.
1323
+
1324
+ [Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/core/src/configuration/plot.ts)
1325
+
1326
+ ### plotKeysOf
1327
+
1328
+ The plot keys a display config declares.
1329
+
1330
+ ```js
1331
+ // type signature
1332
+ (conf: AnyConfigurationModel) => string[]
1333
+ ```
1334
+
1335
+ [Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/core/src/configuration/plot.ts)
1336
+
1337
+ ### plotOf
1338
+
1339
+ A display's plot as declared, defaults left off. A list sitting at a default it
1340
+ shares with no other display, a default plot's marks, shows its entries, since
1341
+ they are what is drawn.
1342
+
1343
+ ```js
1344
+ // type signature
1345
+ (conf: AnyConfigurationModel) => Plot
1346
+ ```
1347
+
1348
+ [Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/core/src/configuration/plot.ts)
1349
+
1350
+ ### plotWrites
1351
+
1352
+ What applying a draft writes: each setting whose lifted value differs from the
1353
+ plot, as the lifted value, and `null` for one it resets. A value spelled another
1354
+ way but lifting to the same setting writes nothing. Throws a refusal before
1355
+ anything is written.
1356
+
1357
+ ```js
1358
+ // type signature
1359
+ (conf: AnyConfigurationModel, draft: Plot) => Record<string, unknown>
1360
+ ```
1361
+
1362
+ [Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/core/src/configuration/plot.ts)
1363
+
1256
1364
  ### preProcessConfigSnapshot
1257
1365
 
1258
1366
  A snapshot as `type` admits it: the same lift and checks `type.create` applies,
@@ -18,11 +18,9 @@ const useStyles = makeStyles()(theme => ({
18
18
  },
19
19
  fieldSubvalue: {
20
20
  wordBreak: 'break-word',
21
- maxHeight: 300,
22
21
  padding: theme.spacing(0.5),
23
22
  border: `1px solid ${theme.palette.action.selected}`,
24
23
  boxSizing: 'border-box',
25
- overflow: 'auto',
26
24
  },
27
25
  }));
28
26
  /**
@@ -1,16 +1,27 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { isValidElement } from 'react';
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { isValidElement, useState } from 'react';
3
3
  import { Link } from '@mui/material';
4
4
  import { SanitizedHTML } from '../../ui/index.js';
5
5
  import { isObject } from '../../util/index.js';
6
6
  import { makeStyles } from '../../util/tss-react/index.js';
7
+ import useMeasure from '../../util/useMeasure.js';
8
+ const CLAMP_HEIGHT = 300;
7
9
  const useStyles = makeStyles()(theme => ({
8
10
  fieldValue: {
9
11
  wordBreak: 'break-word',
10
- maxHeight: 300,
11
12
  fontSize: 12,
12
13
  padding: theme.spacing(0.5),
13
- overflow: 'auto',
14
+ minWidth: 0,
15
+ },
16
+ clip: {
17
+ overflowX: 'auto',
18
+ overflowY: 'hidden',
19
+ },
20
+ clamped: {
21
+ maxHeight: CLAMP_HEIGHT,
22
+ },
23
+ faded: {
24
+ maskImage: 'linear-gradient(to bottom, black 75%, transparent)',
14
25
  },
15
26
  }));
16
27
  export function isBareUrl(text) {
@@ -29,6 +40,11 @@ export function ValueText({ text }) {
29
40
  return isBareUrl(text) ? (_jsx(Link, { href: text, target: "_blank", rel: "noopener noreferrer", children: text })) : (_jsx(SanitizedHTML, { html: text }));
30
41
  }
31
42
  export default function BasicValue({ value }) {
32
- const { classes } = useStyles();
33
- return (_jsx("div", { className: classes.fieldValue, children: isValidElement(value) ? value : _jsx(ValueText, { text: valueText(value) }) }));
43
+ const { classes, cx } = useStyles();
44
+ const [expanded, setExpanded] = useState(false);
45
+ const [ref, { height }] = useMeasure('height');
46
+ const overflows = height !== undefined && height > CLAMP_HEIGHT;
47
+ return (_jsxs("div", { className: classes.fieldValue, children: [_jsx("div", { className: cx(classes.clip, !expanded && classes.clamped, !expanded && overflows && classes.faded), children: _jsx("div", { ref: ref, children: isValidElement(value) ? (value) : (_jsx(ValueText, { text: valueText(value) })) }) }), overflows ? (_jsx(Link, { component: "button", variant: "caption", onClick: () => {
48
+ setExpanded(v => !v);
49
+ }, children: expanded ? 'Show less' : 'Show more' })) : null] }));
34
50
  }
@@ -1,5 +1,4 @@
1
1
  import { pathSubject, printCondition } from '@jbrowse/jexl';
2
- import { activeJexlFilters } from '../../util/jexlFilters.js';
3
2
  import { ensureJexlPrefix } from '../../util/jexlStrings.js';
4
3
  import { getNotificationSink } from '../../util/sessionServices.js';
5
4
  const MAX_LABEL_VALUE = 30;
@@ -26,17 +25,17 @@ export function filterByValueItems(display, path, value) {
26
25
  const text = String(value);
27
26
  const shown = text.length > MAX_LABEL_VALUE ? `${text.slice(0, MAX_LABEL_VALUE)}…` : text;
28
27
  const add = (op) => () => {
29
- const previous = display.filterSetting;
28
+ const previous = display.configuredFilters();
30
29
  const line = printCondition({
31
30
  subject: pathSubject('feature', path),
32
31
  op,
33
32
  value,
34
33
  });
35
- display.setFilter([...activeJexlFilters(display), ensureJexlPrefix(line)]);
34
+ display.setFilter([...previous, ensureJexlPrefix(line)]);
36
35
  getNotificationSink(display).notify('Filter added', 'info', {
37
36
  name: 'Undo',
38
37
  onClick: () => {
39
- display.setFilter(previous && [...previous]);
38
+ display.setFilter(previous);
40
39
  },
41
40
  });
42
41
  };
@@ -18,13 +18,16 @@ function processFeatureData(children, feature) {
18
18
  // translations if included)
19
19
  const featureType = feature.type?.toLowerCase();
20
20
  const isMatureProteinRegion = featureType === 'mature_protein_region_of_cds';
21
+ const ofType = (type) => children.filter(sub => sub.type?.toLowerCase() === type);
22
+ // A frameshift polyprotein's CDS carries its reading frames as CDS rows beside
23
+ // its cleavage products; a single-frame one has only the products.
24
+ const codingRows = ofType('cds');
21
25
  const cds = isMatureProteinRegion
22
26
  ? [{ start: 0, end: feature.end - feature.start, type: 'CDS' }]
23
- : filterSuccessiveElementsWithSameStartAndEndCoord(children.filter(sub => {
24
- const type = sub.type?.toLowerCase();
25
- return type === 'cds' || type === 'mature_protein_region_of_cds';
26
- }));
27
- const exons = filterSuccessiveElementsWithSameStartAndEndCoord(children.filter(sub => sub.type?.toLowerCase() === 'exon'));
27
+ : filterSuccessiveElementsWithSameStartAndEndCoord(codingRows.length > 0
28
+ ? codingRows
29
+ : ofType('mature_protein_region_of_cds'));
30
+ const exons = filterSuccessiveElementsWithSameStartAndEndCoord(ofType('exon'));
28
31
  // annotated UTRs are deliberately not read: a UTR is just the exonic sequence
29
32
  // outside the CDS, so the renderer derives the split from cds+exons. Trusting
30
33
  // the annotation meant a transcript that named only one of its UTRs lost the
package/esm/CorePlugin.js CHANGED
@@ -1,10 +1,40 @@
1
+ import { trackTypeForAdapter } from '@jbrowse/add-track-core';
1
2
  import { configSchema, stateModelFactory } from './BaseFeatureWidget/index.js';
2
3
  import Plugin from './Plugin.js';
3
4
  import CytobandAdapterF from './data_adapters/CytobandAdapter/index.js';
4
5
  import WidgetType from './pluggableElementTypes/WidgetType.js';
5
6
  import * as coreRpcMethods from './rpc/coreRpcMethods.js';
6
- import { installFormatGuessers } from './util/formatGuessers.js';
7
+ import { guessTrackConfFromTable } from './util/formatGuessers.js';
8
+ import { getFileName } from './util/getFileName.js';
7
9
  import { lazyWithPreload } from './util/lazyWithPreload.js';
10
+ import { addAdapterGuesser, addTrackTypeGuesser } from './util/tracks.js';
11
+ /**
12
+ * Guess every format `@jbrowse/add-track-core`'s table describes — the same
13
+ * table `@jbrowse/cli`'s `add-track` reads, so a file resolves to the same
14
+ * adapter config in the app and on the command line.
15
+ *
16
+ * Whether a build can open a format is decided by `hasAdapterType`, not by the
17
+ * table: guessing `BamAdapter` in a build with no alignments plugin writes a
18
+ * track config that fails at render. A plugin therefore registers its adapters
19
+ * and nothing else — there is no format list to keep in step. ADR-077.
20
+ *
21
+ * `CorePlugin` installs this first, so any `addAdapterGuesser` a plugin
22
+ * registers is later in the chain and wins over the table. That is how a format
23
+ * the table cannot express is added, and how a third-party plugin claims one.
24
+ */
25
+ // #region installFormatGuessers
26
+ function installFormatGuessers(pluginManager) {
27
+ addAdapterGuesser(pluginManager, (file, index, adapterHint) => {
28
+ const adapter = guessTrackConfFromTable(file, index, adapterHint)?.adapter;
29
+ return adapter && pluginManager.hasAdapterType(adapter.type)
30
+ ? adapter
31
+ : undefined;
32
+ });
33
+ addTrackTypeGuesser(pluginManager, (adapterName, file) => pluginManager.hasAdapterType(adapterName)
34
+ ? trackTypeForAdapter(adapterName, file && getFileName(file))
35
+ : undefined);
36
+ }
37
+ // #endregion
8
38
  // the core plugin, which registers types that ALL JBrowse applications are
9
39
  // expected to need.
10
40
  export default class CorePlugin extends Plugin {
@@ -19,6 +49,7 @@ export default class CorePlugin extends Plugin {
19
49
  pluginManager.addWidgetType(() => {
20
50
  return new WidgetType({
21
51
  name: 'BaseFeatureWidget',
52
+ discardOnClose: true,
22
53
  heading: 'Feature details',
23
54
  configSchema,
24
55
  stateModel: stateModelFactory(pluginManager),