jbrowse-plugin-msaview 2.5.1 → 2.5.2

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.
@@ -73,7 +73,9 @@ function parseFeature(featureXml) {
73
73
  : noteName || quals.site_type || 'site';
74
74
  const accession = isDomain ? cddId : `${cddId}:${name}`;
75
75
  return {
76
- signature: { entry: { name, description: quals.note ?? name, accession } },
76
+ signature: {
77
+ entry: { name, description: quals.note ?? name, accession },
78
+ },
77
79
  locations: [span],
78
80
  };
79
81
  }
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "2.5.1";
1
+ export declare const version = "2.5.2";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '2.5.1';
1
+ export const version = '2.5.2';
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.5.1",
2
+ "version": "2.5.2",
3
3
  "license": "MIT",
4
4
  "name": "jbrowse-plugin-msaview",
5
5
  "repository": {
@@ -21,37 +21,37 @@
21
21
  "idb": "^8.0.3",
22
22
  "pako-esm2": "^2.0.2",
23
23
  "react-msaview": "^5.4.1",
24
- "swr": "^2.4.1"
24
+ "swr": "^2.4.2"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@emotion/react": "^11.14.0",
28
28
  "@eslint/js": "^10.0.1",
29
29
  "@fal-works/esbuild-plugin-global-externals": "^2.1.2",
30
30
  "@jbrowse/core": "^4.3.0",
31
- "@jbrowse/mobx-state-tree": "^5.10.8",
31
+ "@jbrowse/mobx-state-tree": "^5.11.1",
32
32
  "@jbrowse/plugin-linear-genome-view": "^4.3.0",
33
33
  "@mui/icons-material": "^7.3.11",
34
34
  "@mui/material": "^7.3.11",
35
35
  "@mui/system": "^7.3.11",
36
- "@mui/x-data-grid": "^8.28.7",
37
- "@types/node": "^25.9.1",
38
- "@types/react": "^19.2.16",
39
- "@typescript-eslint/eslint-plugin": "^8.60.1",
40
- "@typescript-eslint/parser": "^8.60.1",
41
- "esbuild": "^0.28.0",
42
- "eslint": "^10.4.1",
43
- "eslint-plugin-import-x": "^4.16.2",
36
+ "@mui/x-data-grid": "^8.29.1",
37
+ "@types/node": "^25.9.4",
38
+ "@types/react": "^19.2.17",
39
+ "@typescript-eslint/eslint-plugin": "^8.62.0",
40
+ "@typescript-eslint/parser": "^8.62.0",
41
+ "esbuild": "^0.28.1",
42
+ "eslint": "^10.5.0",
43
+ "eslint-plugin-import-x": "^4.17.0",
44
44
  "eslint-plugin-react": "^7.37.5",
45
45
  "eslint-plugin-react-hooks": "^7.1.1",
46
46
  "eslint-plugin-unicorn": "^64.0.0",
47
- "mobx": "^6.15.4",
47
+ "mobx": "^6.16.1",
48
48
  "mobx-react": "^9.2.2",
49
49
  "msa-parsers": "5.4.1",
50
50
  "pixelmatch": "^7.2.0",
51
51
  "pngjs": "^7.0.0",
52
- "prettier": "^3.8.3",
52
+ "prettier": "^3.8.4",
53
53
  "pretty-bytes": "^7.1.0",
54
- "puppeteer": "^25.1.0",
54
+ "puppeteer": "^25.2.1",
55
55
  "react": "^19.2.7",
56
56
  "react-dom": "^19.2.7",
57
57
  "rimraf": "^6.1.3",
@@ -59,8 +59,8 @@
59
59
  "serve": "^14.2.6",
60
60
  "tss-react": "^4.9.21",
61
61
  "typescript": "^6.0.3",
62
- "typescript-eslint": "^8.60.1",
63
- "vitest": "^4.1.8"
62
+ "typescript-eslint": "^8.62.0",
63
+ "vitest": "^4.1.9"
64
64
  },
65
65
  "scripts": {
66
66
  "clean": "rimraf dist",
@@ -282,46 +282,71 @@ export function autoConnectStructures(self: JBrowsePluginMsaViewModel) {
282
282
  }
283
283
  }
284
284
 
285
+ /**
286
+ * Mirror a connected 3D protein view's hovered residue onto the MSA's
287
+ * highlighted columns. Returns the autorun body and keeps a flag tracking
288
+ * whether the current highlight was set by THIS sync: when a protein hover ends
289
+ * we restore the declarative highlightColumns seed (or clear) rather than
290
+ * blindly wiping it.
291
+ *
292
+ * Without the flag this autorun fires once on creation — with the view connected
293
+ * to a *genome* LGV but no 3D protein structure attached — computes zero columns,
294
+ * and calls setHighlightedColumns(undefined), clobbering the seed that
295
+ * MSAModelF.afterCreate just set from the declarative `highlightColumns`. That is
296
+ * the bug that made the BRAF/TP53 genome-browser links open with no V600/R248
297
+ * column lit (SRC has no highlightColumns, so nothing was there to wipe).
298
+ */
285
299
  export function observeProteinHighlights(self: JBrowsePluginMsaViewModel) {
286
- const { connectedViewId, transcriptToMsaMap, querySeqName } = self
300
+ let proteinDriven = false
301
+ return () => {
302
+ const { connectedViewId, transcriptToMsaMap, querySeqName } = self
287
303
 
288
- if (!connectedViewId || !transcriptToMsaMap) {
289
- return
290
- }
304
+ if (!connectedViewId || !transcriptToMsaMap) {
305
+ return
306
+ }
291
307
 
292
- const columns = new Set<number>()
308
+ const columns = new Set<number>()
293
309
 
294
- for (const view of getProteinViews(getSession(self).views)) {
295
- for (const structure of view.structures) {
296
- if (structure.connectedViewId !== connectedViewId) {
297
- continue
298
- }
310
+ for (const view of getProteinViews(getSession(self).views)) {
311
+ for (const structure of view.structures) {
312
+ if (structure.connectedViewId !== connectedViewId) {
313
+ continue
314
+ }
299
315
 
300
- const highlights = structure.hoverGenomeHighlights
301
- if (!highlights || highlights.length === 0) {
302
- continue
303
- }
316
+ const highlights = structure.hoverGenomeHighlights
317
+ if (!highlights || highlights.length === 0) {
318
+ continue
319
+ }
304
320
 
305
- const { g2p } = transcriptToMsaMap
306
- for (const highlight of highlights) {
307
- for (let coord = highlight.start; coord < highlight.end; coord++) {
308
- const proteinPos = g2p[coord]
309
- if (proteinPos !== undefined) {
310
- const col = self.seqPosToGlobalCol(querySeqName, proteinPos)
311
- columns.add(col)
321
+ const { g2p } = transcriptToMsaMap
322
+ for (const highlight of highlights) {
323
+ for (let coord = highlight.start; coord < highlight.end; coord++) {
324
+ const proteinPos = g2p[coord]
325
+ if (proteinPos !== undefined) {
326
+ const col = self.seqPosToGlobalCol(querySeqName, proteinPos)
327
+ columns.add(col)
328
+ }
312
329
  }
313
330
  }
314
331
  }
315
332
  }
316
- }
317
-
318
- const visibleColumns = Array.from(columns)
319
- .map(col => self.globalColToVisibleCol(col))
320
- .filter((col): col is number => col !== undefined)
321
333
 
322
- self.setHighlightedColumns(
323
- visibleColumns.length > 0 ? visibleColumns : undefined,
324
- )
334
+ const visibleColumns = Array.from(columns)
335
+ .map(col => self.globalColToVisibleCol(col))
336
+ .filter((col): col is number => col !== undefined)
337
+
338
+ if (visibleColumns.length > 0) {
339
+ self.setHighlightedColumns(visibleColumns)
340
+ proteinDriven = true
341
+ } else if (proteinDriven) {
342
+ // our protein-hover highlight ended — fall back to the declarative seed
343
+ // instead of wiping a column the URL/user asked to keep lit
344
+ self.setHighlightedColumns(
345
+ self.highlightColumns?.length ? self.highlightColumns : undefined,
346
+ )
347
+ proteinDriven = false
348
+ }
349
+ }
325
350
  }
326
351
 
327
352
  export function runCleanup() {
@@ -471,7 +471,6 @@ export default function stateModelFactory() {
471
471
  highlightConnectedStructures,
472
472
  autoConnectStructures,
473
473
  autoLoadProteinDomains,
474
- observeProteinHighlights,
475
474
  ]) {
476
475
  addDisposer(
477
476
  self,
@@ -480,7 +479,10 @@ export default function stateModelFactory() {
480
479
  }),
481
480
  )
482
481
  }
482
+ // these two keep per-reaction state across runs (a "did I set it?" flag),
483
+ // so they're factories returning the autorun body rather than plain fns
483
484
  addDisposer(self, autorun(syncGenomeHoverToMsaColumn(self)))
485
+ addDisposer(self, autorun(observeProteinHighlights(self)))
484
486
  },
485
487
  }))
486
488
  }
@@ -26,8 +26,7 @@ export async function getCachedDomains(accessions: string[]) {
26
26
  const tx = db.transaction(STORE_NAME, 'readonly')
27
27
  const results = await Promise.all(
28
28
  accessions.map(
29
- accession =>
30
- tx.store.get(accession) as Promise<CachedDomain | undefined>,
29
+ accession => tx.store.get(accession) as Promise<CachedDomain | undefined>,
31
30
  ),
32
31
  )
33
32
  await tx.done
@@ -83,7 +83,9 @@ function parseFeature(featureXml: string): DomainMatch | undefined {
83
83
  : noteName || quals.site_type || 'site'
84
84
  const accession = isDomain ? cddId : `${cddId}:${name}`
85
85
  return {
86
- signature: { entry: { name, description: quals.note ?? name, accession } },
86
+ signature: {
87
+ entry: { name, description: quals.note ?? name, accession },
88
+ },
87
89
  locations: [span],
88
90
  }
89
91
  }
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = '2.5.1'
1
+ export const version = '2.5.2'