jbrowse-plugin-msaview 3.10.0 → 5.0.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 (150) hide show
  1. package/dist/AddHighlightModel/GenomeMouseoverHighlight.js +1 -1
  2. package/dist/AddHighlightModel/index.js +3 -12
  3. package/dist/LaunchMsaView/codingFeature.d.ts +0 -12
  4. package/dist/LaunchMsaView/codingFeature.js +0 -30
  5. package/dist/LaunchMsaView/codingFeature.test.js +1 -48
  6. package/dist/LaunchMsaView/components/BlastQuery/BlastAutomaticPanel.js +8 -10
  7. package/dist/LaunchMsaView/components/BlastQuery/BlastManualPanel.js +9 -11
  8. package/dist/LaunchMsaView/components/BlastQuery/CachedBlastResults.js +3 -1
  9. package/dist/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.js +14 -16
  10. package/dist/LaunchMsaView/components/OrthologQuery/OrthologPanel.js +16 -18
  11. package/dist/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.js +17 -19
  12. package/dist/LaunchMsaView/components/fetchSeq.d.ts +1 -1
  13. package/dist/LaunchMsaView/components/fetchSeq.js +3 -10
  14. package/dist/LaunchMsaView/components/launchConnectedView.d.ts +2 -2
  15. package/dist/LaunchMsaView/components/launchConnectedView.js +4 -8
  16. package/dist/LaunchMsaView/components/useFeatureSequence.d.ts +1 -1
  17. package/dist/LaunchMsaView/index.js +4 -13
  18. package/dist/LaunchMsaView/launchTarget.d.ts +7 -30
  19. package/dist/LaunchMsaView/launchTarget.js +10 -49
  20. package/dist/LaunchMsaView/launchTarget.test.js +17 -109
  21. package/dist/LaunchMsaViewExtensionPoint/index.js +3 -3
  22. package/dist/LaunchMsaViewExtensionPoint/index.test.js +24 -21
  23. package/dist/MsaViewPanel/index.js +3 -3
  24. package/dist/MsaViewPanel/isMsaView.d.ts +4 -0
  25. package/dist/MsaViewPanel/isMsaView.js +3 -0
  26. package/dist/MsaViewPanel/model.d.ts +8 -11
  27. package/dist/MsaViewPanel/model.js +3 -13
  28. package/dist/MsaViewPanel/resolveConnectedTranscript.js +1 -7
  29. package/dist/chunks/AboutDialog-WT6GXMXU.js +2 -0
  30. package/dist/chunks/AboutDialog-WT6GXMXU.js.map +7 -0
  31. package/dist/chunks/AnnotationFileDialog-34R7LFHB.js +2 -0
  32. package/dist/chunks/AnnotationFileDialog-34R7LFHB.js.map +7 -0
  33. package/dist/chunks/BgzipFastaMsaAdapter-ZMUARSUQ.js +4 -0
  34. package/dist/chunks/BgzipFastaMsaAdapter-ZMUARSUQ.js.map +7 -0
  35. package/dist/chunks/ExportSVGDialog-NMVUHFGY.js +2 -0
  36. package/dist/chunks/ExportSVGDialog-NMVUHFGY.js.map +7 -0
  37. package/dist/chunks/FeatureDialog-XNHIA5PS.js +2 -0
  38. package/dist/chunks/FeatureDialog-XNHIA5PS.js.map +7 -0
  39. package/dist/chunks/HelpDialog-DF4Y536X.js +2 -0
  40. package/dist/chunks/HelpDialog-DF4Y536X.js.map +7 -0
  41. package/dist/chunks/LaunchMsaViewDialog-LMZOJ7T6.js +5 -0
  42. package/dist/chunks/LaunchMsaViewDialog-LMZOJ7T6.js.map +7 -0
  43. package/dist/chunks/MetadataDialog-2WT6EX4M.js +2 -0
  44. package/dist/chunks/MetadataDialog-2WT6EX4M.js.map +7 -0
  45. package/dist/chunks/MsaViewPanel-YYP4CYYO.js +2 -0
  46. package/dist/chunks/MsaViewPanel-YYP4CYYO.js.map +7 -0
  47. package/dist/chunks/TrackInfoDialog-TYCMLUKG.js +2 -0
  48. package/dist/chunks/TrackInfoDialog-TYCMLUKG.js.map +7 -0
  49. package/dist/chunks/TreeNodeInfoDialog-BFF6JRCO.js +2 -0
  50. package/dist/chunks/TreeNodeInfoDialog-BFF6JRCO.js.map +7 -0
  51. package/dist/chunks/chunk-2IWD4OO4.js +2 -0
  52. package/dist/chunks/chunk-2IWD4OO4.js.map +7 -0
  53. package/dist/chunks/chunk-5ORPTTMR.js +2 -0
  54. package/dist/chunks/chunk-5ORPTTMR.js.map +7 -0
  55. package/dist/chunks/chunk-6YFCSBEE.js +2 -0
  56. package/dist/chunks/chunk-6YFCSBEE.js.map +7 -0
  57. package/dist/chunks/chunk-73KAPCJ2.js +2 -0
  58. package/dist/chunks/chunk-73KAPCJ2.js.map +7 -0
  59. package/dist/chunks/chunk-BX4Z274Q.js +2 -0
  60. package/dist/chunks/chunk-BX4Z274Q.js.map +7 -0
  61. package/dist/chunks/chunk-CVLB4VFP.js +2 -0
  62. package/dist/chunks/chunk-CVLB4VFP.js.map +7 -0
  63. package/dist/chunks/chunk-DNFD5II2.js +2 -0
  64. package/dist/chunks/chunk-DNFD5II2.js.map +7 -0
  65. package/dist/chunks/chunk-ENTWPX2K.js +6 -0
  66. package/dist/chunks/chunk-ENTWPX2K.js.map +7 -0
  67. package/dist/chunks/chunk-FCNT6B47.js +2 -0
  68. package/dist/chunks/chunk-FCNT6B47.js.map +7 -0
  69. package/dist/chunks/chunk-FCWXYIFC.js +2 -0
  70. package/dist/chunks/chunk-FCWXYIFC.js.map +7 -0
  71. package/dist/chunks/chunk-FY3BTKY4.js +2 -0
  72. package/dist/chunks/chunk-FY3BTKY4.js.map +7 -0
  73. package/dist/chunks/chunk-IBBQUV2I.js +2 -0
  74. package/dist/chunks/chunk-IBBQUV2I.js.map +7 -0
  75. package/dist/chunks/chunk-J6KYLXRD.js +2 -0
  76. package/dist/chunks/chunk-J6KYLXRD.js.map +7 -0
  77. package/dist/chunks/chunk-MBI4TMKR.js +2 -0
  78. package/dist/chunks/chunk-MBI4TMKR.js.map +7 -0
  79. package/dist/chunks/chunk-MHBTV7BZ.js +3 -0
  80. package/dist/chunks/chunk-MHBTV7BZ.js.map +7 -0
  81. package/dist/chunks/chunk-NSASZ5FM.js +2 -0
  82. package/dist/chunks/chunk-NSASZ5FM.js.map +7 -0
  83. package/dist/chunks/chunk-O7JNDIKD.js +2 -0
  84. package/dist/chunks/chunk-O7JNDIKD.js.map +7 -0
  85. package/dist/chunks/chunk-P77DPK6B.js +2 -0
  86. package/dist/chunks/chunk-P77DPK6B.js.map +7 -0
  87. package/dist/chunks/chunk-PJZ3XTMG.js +6 -0
  88. package/dist/chunks/chunk-PJZ3XTMG.js.map +7 -0
  89. package/dist/chunks/chunk-QAC6JSDZ.js +5 -0
  90. package/dist/chunks/chunk-QAC6JSDZ.js.map +7 -0
  91. package/dist/chunks/chunk-QMLPITS4.js +18 -0
  92. package/dist/chunks/chunk-QMLPITS4.js.map +7 -0
  93. package/dist/chunks/chunk-RTKNCGDF.js +8 -0
  94. package/dist/chunks/chunk-RTKNCGDF.js.map +7 -0
  95. package/dist/chunks/chunk-TITP6LCV.js +2 -0
  96. package/dist/chunks/chunk-TITP6LCV.js.map +7 -0
  97. package/dist/chunks/chunk-VOBS7IVV.js +2 -0
  98. package/dist/chunks/chunk-VOBS7IVV.js.map +7 -0
  99. package/dist/chunks/chunk-YUKJI2AH.js +2 -0
  100. package/dist/chunks/chunk-YUKJI2AH.js.map +7 -0
  101. package/dist/chunks/chunk-ZTQYZDWK.js +2 -0
  102. package/dist/chunks/chunk-ZTQYZDWK.js.map +7 -0
  103. package/dist/chunks/dist-2T65ZS4E.js +2 -0
  104. package/dist/chunks/dist-2T65ZS4E.js.map +7 -0
  105. package/dist/chunks/dist-UX5CKLQJ.js +2 -0
  106. package/dist/chunks/dist-UX5CKLQJ.js.map +7 -0
  107. package/dist/chunks/model-7VBTOIJX.js +12 -0
  108. package/dist/chunks/model-7VBTOIJX.js.map +7 -0
  109. package/dist/chunks/renderToSvg-B7RCHRO3.js +2 -0
  110. package/dist/chunks/renderToSvg-B7RCHRO3.js.map +7 -0
  111. package/dist/config.json +1 -1
  112. package/dist/index.js +5 -2
  113. package/dist/jbrowse-plugin-msaview.esm.js +3 -0
  114. package/dist/jbrowse-plugin-msaview.esm.js.map +7 -0
  115. package/dist/utils/launchMsaView.d.ts +1 -1
  116. package/dist/utils/launchMsaView.js +5 -2
  117. package/dist/utils/workspaces.js +6 -25
  118. package/dist/utils/workspaces.test.js +5 -5
  119. package/dist/version.d.ts +1 -1
  120. package/dist/version.js +1 -1
  121. package/package.json +3 -5
  122. package/src/AddHighlightModel/GenomeMouseoverHighlight.tsx +1 -1
  123. package/src/AddHighlightModel/index.tsx +6 -16
  124. package/src/LaunchMsaView/codingFeature.test.ts +1 -64
  125. package/src/LaunchMsaView/codingFeature.ts +0 -38
  126. package/src/LaunchMsaView/components/BlastQuery/BlastAutomaticPanel.tsx +3 -3
  127. package/src/LaunchMsaView/components/BlastQuery/BlastManualPanel.tsx +3 -3
  128. package/src/LaunchMsaView/components/BlastQuery/CachedBlastResults.tsx +3 -1
  129. package/src/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.tsx +3 -3
  130. package/src/LaunchMsaView/components/OrthologQuery/OrthologPanel.tsx +3 -3
  131. package/src/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.tsx +3 -3
  132. package/src/LaunchMsaView/components/fetchSeq.ts +3 -20
  133. package/src/LaunchMsaView/components/launchConnectedView.ts +5 -8
  134. package/src/LaunchMsaView/index.ts +8 -13
  135. package/src/LaunchMsaView/launchTarget.test.ts +20 -133
  136. package/src/LaunchMsaView/launchTarget.ts +18 -70
  137. package/src/LaunchMsaViewExtensionPoint/index.test.ts +26 -21
  138. package/src/LaunchMsaViewExtensionPoint/index.ts +3 -4
  139. package/src/MsaViewPanel/index.ts +3 -4
  140. package/src/MsaViewPanel/isMsaView.ts +7 -0
  141. package/src/MsaViewPanel/model.ts +3 -16
  142. package/src/MsaViewPanel/resolveConnectedTranscript.ts +1 -7
  143. package/src/index.ts +5 -2
  144. package/src/utils/launchMsaView.ts +5 -2
  145. package/src/utils/useFetch.ts +1 -1
  146. package/src/utils/workspaces.test.ts +5 -5
  147. package/src/utils/workspaces.ts +6 -25
  148. package/src/version.ts +1 -1
  149. package/dist/jbrowse-plugin-msaview.umd.production.min.js +0 -137
  150. package/dist/jbrowse-plugin-msaview.umd.production.min.js.map +0 -7
@@ -1,132 +1,40 @@
1
1
  import { SimpleFeature } from '@jbrowse/core/util';
2
2
  import { describe, expect, test } from 'vitest';
3
- import { isGeneLikeType, launchTarget } from './launchTarget';
4
- function feature(type, subfeatures = ['CDS']) {
5
- return new SimpleFeature({
6
- uniqueId: type,
3
+ import { launchTarget } from './launchTarget';
4
+ const host = (type) => ({
5
+ contextMenuItems: () => [],
6
+ contextMenuInfo: { item: { featureId: 'f1', type }, displayedRegionIndex: 0 },
7
+ fetchFullFeature: (featureId) => Promise.resolve(new SimpleFeature({
8
+ uniqueId: featureId,
7
9
  refName: 'chr1',
8
10
  start: 0,
9
11
  end: 100,
10
- type,
11
- subfeatures: subfeatures.map((t, i) => ({
12
- uniqueId: `${type}-${i}`,
13
- refName: 'chr1',
14
- start: 0,
15
- end: 100,
16
- type: t,
17
- })),
18
- });
19
- }
20
- const modernHost = (type) => ({
21
- contextMenuItems: () => [],
22
- contextMenuInfo: { item: { featureId: 'f1', type }, displayedRegionIndex: 0 },
23
- fetchFullFeature: (featureId) => Promise.resolve(feature(`fetched:${featureId}`)),
24
- });
25
- const legacyHost = (feat) => ({
26
- contextMenuItems: () => [],
27
- contextMenuFeature: feat,
28
- });
29
- async function fetched(target) {
30
- return target && 'fetchFeature' in target
31
- ? await target.fetchFeature()
32
- : undefined;
33
- }
34
- describe('isGeneLikeType', () => {
35
- test.each(['gene', 'mRNA', 'transcript', 'lnc_RNA', 'protein_coding_gene'])('accepts %s', type => {
36
- expect(isGeneLikeType(type)).toBe(true);
37
- });
38
- test.each(['CDS', 'exon', 'match', 'SNV', undefined, null, 42])('rejects %s', type => {
39
- expect(isGeneLikeType(type)).toBe(false);
40
- });
12
+ type: `fetched:${featureId}`,
13
+ })),
41
14
  });
42
15
  describe('launchTarget', () => {
43
16
  test('resolves the clicked feature through fetchFullFeature', async () => {
44
- const target = launchTarget(modernHost('mRNA'));
45
- expect(await fetched(target)).toBeDefined();
46
- expect((await fetched(target))?.get('type')).toBe('fetched:f1');
17
+ const feature = await launchTarget(host('mRNA'))?.fetchFeature();
18
+ expect(feature?.get('type')).toBe('fetched:f1');
47
19
  });
48
20
  test('offers nothing for a non-gene click', () => {
49
- expect(launchTarget(modernHost('CDS'))).toBeUndefined();
50
- expect(launchTarget(modernHost(undefined))).toBeUndefined();
21
+ expect(launchTarget(host('CDS'))).toBeUndefined();
22
+ expect(launchTarget(host(undefined))).toBeUndefined();
51
23
  });
52
24
  test('offers nothing when nothing was clicked', () => {
53
- expect(launchTarget({ contextMenuItems: () => [] })).toBeUndefined();
54
- });
55
- // v4.3.0 and earlier have contextMenuFeature and nothing else; dropping this
56
- // fallback once took "Launch MSA view" off every host in the wild.
57
- test('falls back to a synchronous contextMenuFeature', () => {
58
- const target = launchTarget(legacyHost(feature('mRNA')));
59
- expect(target && 'feature' in target && target.feature.get('type')).toBe('mRNA');
60
- });
61
- test('applies the same gene test on both host shapes', () => {
62
- expect(launchTarget(legacyHost(feature('lnc_RNA')))).toBeDefined();
63
- expect(launchTarget(legacyHost(feature('exon')))).toBeUndefined();
64
- });
65
- // gene-like is not enough: an lncRNA translates to nothing, and offering the
66
- // item opened a dialog whose Submit never left grey
67
- test('declines a gene-like feature with no CDS below it', () => {
68
- expect(launchTarget(legacyHost(feature('lnc_RNA', ['exon'])))).toBeUndefined();
69
- });
70
- // a legacy host can hand over a bare record whose children are a separate
71
- // query, and declining it takes the item off an ordinary gene with no word
72
- test('offers the item for a gene that arrived with no subfeatures', () => {
73
- expect(launchTarget(legacyHost(feature('gene', [])))).toBeDefined();
74
- });
75
- // a click on an isoform should open the dialog on the gene, so every
76
- // transcript is there to pick from
77
- test('climbs to the gene from a clicked isoform', () => {
78
- const gene = new SimpleFeature({
79
- uniqueId: 'gene',
80
- refName: 'chr1',
81
- start: 0,
82
- end: 100,
83
- type: 'gene',
84
- subfeatures: [
85
- {
86
- uniqueId: 'mrna',
87
- refName: 'chr1',
88
- start: 0,
89
- end: 100,
90
- type: 'mRNA',
91
- subfeatures: [
92
- {
93
- uniqueId: 'cds',
94
- refName: 'chr1',
95
- start: 0,
96
- end: 100,
97
- type: 'CDS',
98
- },
99
- ],
100
- },
101
- ],
102
- });
103
- const mrna = gene.get('subfeatures')[0];
104
- const target = launchTarget(legacyHost(mrna));
105
- expect(target && 'feature' in target && target.feature).toBe(gene);
106
- // the gene is what the dialog opens on, but the picker still opens on the
107
- // isoform the click landed on -- on a v4 host that click is the only place
108
- // the choice is ever stated
109
- expect(target?.preferredTranscriptId).toBe(mrna.id());
25
+ expect(launchTarget({ ...host('mRNA'), contextMenuInfo: undefined })).toBeUndefined();
110
26
  });
111
27
  // the canvas host names the clicked isoform beside the gene it fetches, as
112
28
  // its own Collapse introns dialog reads it
113
- test('carries the isoform a canvas click landed on', () => {
114
- const host = modernHost('gene');
29
+ test('carries the isoform a click landed on', () => {
30
+ const h = host('gene');
115
31
  const target = launchTarget({
116
- ...host,
32
+ ...h,
117
33
  contextMenuInfo: {
118
- ...host.contextMenuInfo,
34
+ ...h.contextMenuInfo,
119
35
  subfeature: { featureId: 'mrna-2' },
120
36
  },
121
37
  });
122
38
  expect(target?.preferredTranscriptId).toBe('mrna-2');
123
39
  });
124
- // a host that has both shapes must not fall through to the legacy branch and
125
- // launch on a stale feature when the click was not on a gene
126
- test('a non-gene click on a host carrying both shapes offers nothing', () => {
127
- expect(launchTarget({
128
- ...modernHost('CDS'),
129
- ...legacyHost(feature('mRNA')),
130
- })).toBeUndefined();
131
- });
132
40
  });
@@ -1,4 +1,3 @@
1
- import { expandSpec } from 'react-msaview';
2
1
  import { launchMsaView } from '../utils/launchMsaView';
3
2
  /**
4
3
  * `msa` and `tree` onto the plugin's own sources, so a url still goes through
@@ -23,7 +22,7 @@ function withLongSources({ msa, tree, ...args }) {
23
22
  };
24
23
  }
25
24
  export default function LaunchMsaViewExtensionPointF(pluginManager) {
26
- pluginManager.addToExtensionPoint('LaunchView-MsaView', (args) => {
25
+ pluginManager.addToExtensionPoint('LaunchView-MsaView', async (args) => {
27
26
  const { session, query, data, msaFileLocation, msaIndexedLocation, msaName, treeFileLocation, querySeqName, searchParams, ...rest } = withLongSources(args);
28
27
  // `orthologParams` and `searchParams` name no alignment at all — the
29
28
  // view builds one at launch, which is the dialog's Orthologs and BLAST
@@ -49,7 +48,8 @@ export default function LaunchMsaViewExtensionPointF(pluginManager) {
49
48
  msaName,
50
49
  querySeqName,
51
50
  };
52
- launchMsaView(session, {
51
+ const { expandSpec } = await import('react-msaview');
52
+ await launchMsaView(session, {
53
53
  ...expandSpec({ ...rest, query }),
54
54
  ...(searchParams ? { blastParams: searchParams } : {}),
55
55
  data,
@@ -1,6 +1,6 @@
1
1
  import { expect, test } from 'vitest';
2
2
  import LaunchMsaViewExtensionPointF from './index';
3
- function launch(args) {
3
+ async function launch(args) {
4
4
  let run;
5
5
  LaunchMsaViewExtensionPointF({
6
6
  addToExtensionPoint(_name, cb) {
@@ -9,20 +9,20 @@ function launch(args) {
9
9
  });
10
10
  const added = [];
11
11
  const session = {
12
- addView(_type, snapshot) {
12
+ async launchView(_type, snapshot) {
13
13
  added.push(snapshot);
14
14
  return { id: 'view-1' };
15
15
  },
16
16
  };
17
- run({ session, ...args });
17
+ await run({ session, ...args });
18
18
  return added[0];
19
19
  }
20
- test('inline data carries no init, which the panel would read as a launch in flight', () => {
21
- const snapshot = launch({ data: { msa: '>a\nMEEP' } });
20
+ test('inline data carries no init, which the panel would read as a launch in flight', async () => {
21
+ const snapshot = await launch({ data: { msa: '>a\nMEEP' } });
22
22
  expect('init' in snapshot).toBe(false);
23
23
  });
24
- test('a file location travels through init', () => {
25
- const snapshot = launch({
24
+ test('a file location travels through init', async () => {
25
+ const snapshot = await launch({
26
26
  msaFileLocation: { uri: 'http://example.com/a.fa' },
27
27
  });
28
28
  expect(snapshot.init).toEqual({
@@ -32,8 +32,8 @@ test('a file location travels through init', () => {
32
32
  querySeqName: undefined,
33
33
  });
34
34
  });
35
- test('searchParams is a source, stored under the name the dialog uses', () => {
36
- const snapshot = launch({
35
+ test('searchParams is a source, stored under the name the dialog uses', async () => {
36
+ const snapshot = await launch({
37
37
  searchParams: {
38
38
  searchProgram: 'phmmer',
39
39
  blastDatabase: 'rp15',
@@ -50,13 +50,13 @@ test('searchParams is a source, stored under the name the dialog uses', () => {
50
50
  expect('searchParams' in snapshot).toBe(false);
51
51
  expect(snapshot.connectedTranscript).toBe('NM_000546.6');
52
52
  });
53
- test('a launch naming no source at all is refused', () => {
54
- expect(() => launch({ connectedViewId: 'lgv1' })).toThrow(/searchParams/);
53
+ test('a launch naming no source at all is refused', async () => {
54
+ await expect(launch({ connectedViewId: 'lgv1' })).rejects.toThrow(/searchParams/);
55
55
  });
56
- test('region and the data-layer keys reach the view as snapshot properties', () => {
56
+ test('region and the data-layer keys reach the view as snapshot properties', async () => {
57
57
  const region = { row: 'Human', start: 245, end: 249 };
58
58
  const clades = [{ mrca: ['Human', 'Mouse'], tips: 2, mark: 'bracket' }];
59
- const snapshot = launch({
59
+ const snapshot = await launch({
60
60
  data: { msa: '>Human\nMEEP' },
61
61
  region,
62
62
  clades,
@@ -68,8 +68,11 @@ test('region and the data-layer keys reach the view as snapshot properties', ()
68
68
  expect(snapshot.relativeTo).toBe('Human');
69
69
  expect(snapshot.gffFilehandle).toEqual({ uri: 'http://example.com/a.gff' });
70
70
  });
71
- test('one field set is enough to need init', () => {
72
- const snapshot = launch({ data: { msa: '>a\nMEEP' }, querySeqName: 'QUERY' });
71
+ test('one field set is enough to need init', async () => {
72
+ const snapshot = await launch({
73
+ data: { msa: '>a\nMEEP' },
74
+ querySeqName: 'QUERY',
75
+ });
73
76
  expect(snapshot.init).toEqual({
74
77
  msaUrl: undefined,
75
78
  msaIndexedLocation: undefined,
@@ -77,8 +80,8 @@ test('one field set is enough to need init', () => {
77
80
  querySeqName: 'QUERY',
78
81
  });
79
82
  });
80
- test('msa and tree urls reach the plugin sources, query the query row', () => {
81
- const snapshot = launch({
83
+ test('msa and tree urls reach the plugin sources, query the query row', async () => {
84
+ const snapshot = await launch({
82
85
  msa: 'https://example.com/p53.afa',
83
86
  tree: 'https://example.com/p53.nh',
84
87
  query: 'Human',
@@ -94,13 +97,13 @@ test('msa and tree urls reach the plugin sources, query the query row', () => {
94
97
  expect(snapshot.relativeTo).toBe('Human');
95
98
  expect('msa' in snapshot || 'query' in snapshot).toBe(false);
96
99
  });
97
- test('inline msa and newick text become inline data', () => {
98
- const snapshot = launch({ msa: '>a\nMEEP\n>b\nMEEP', tree: '(a,b);' });
100
+ test('inline msa and newick text become inline data', async () => {
101
+ const snapshot = await launch({ msa: '>a\nMEEP\n>b\nMEEP', tree: '(a,b);' });
99
102
  expect(snapshot.data).toEqual({ msa: '>a\nMEEP\n>b\nMEEP', tree: '(a,b);' });
100
103
  expect('init' in snapshot).toBe(false);
101
104
  });
102
- test('highlights, region and column tracks expand onto the query row', () => {
103
- const snapshot = launch({
105
+ test('highlights, region and column tracks expand onto the query row', async () => {
106
+ const snapshot = await launch({
104
107
  msa: 'https://example.com/p53.afa',
105
108
  query: 'Human',
106
109
  highlights: ['102-292 DNA-binding', 175],
@@ -1,13 +1,13 @@
1
1
  import { lazy } from 'react';
2
2
  import ViewType from '@jbrowse/core/pluggableElementTypes/ViewType';
3
- import stateModelFactory from './model';
4
- // lazies
5
3
  const MsaViewPanel = lazy(() => import('./components/MsaViewPanel'));
6
4
  export default function MsaViewF(pluginManager) {
7
5
  pluginManager.addViewType(() => {
8
6
  return new ViewType({
9
7
  name: 'MsaView',
10
- stateModel: stateModelFactory(),
8
+ // a thunk, so react-msaview loads with the first view rather than with
9
+ // the plugin; addView refuses the type until then, hence launchView
10
+ stateModel: () => import('./model').then(m => m.default()),
11
11
  ReactComponent: MsaViewPanel,
12
12
  });
13
13
  });
@@ -0,0 +1,4 @@
1
+ import type { JBrowsePluginMsaViewModel } from './model';
2
+ export declare function isMsaView(view: {
3
+ type: string;
4
+ }): view is JBrowsePluginMsaViewModel;
@@ -0,0 +1,3 @@
1
+ export function isMsaView(view) {
2
+ return view.type === 'MsaView';
3
+ }
@@ -498,16 +498,16 @@ export default function stateModelFactory(): import("@jbrowse/mobx-state-tree").
498
498
  clades: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").IArrayType<import("@jbrowse/mobx-state-tree").IType<import("react-msaview").Clade, import("react-msaview").Clade, import("react-msaview").Clade>>, [undefined]>;
499
499
  encodings: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").IArrayType<import("@jbrowse/mobx-state-tree").IType<import("react-msaview").Encoding, import("react-msaview").Encoding, import("react-msaview").Encoding>>, [undefined]>;
500
500
  rowPanels: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").IArrayType<import("@jbrowse/mobx-state-tree").IType<import("react-msaview").RowPanelSpec, import("react-msaview").RowPanelSpec, import("react-msaview").RowPanelSpec>>, [undefined]>;
501
- }, "init" | "querySeqName" | "querySeqOffset" | "zoomToBaseLevel" | "launchCompleted" | "connectedViewId" | "connectedFeature" | "connectedTranscript" | "blastParams" | "orthologParams" | "uniprotId" | "dataStoreId" | "mafRegion"> & {
501
+ }, "init" | "querySeqName" | "launchCompleted" | "connectedViewId" | "connectedFeature" | "connectedTranscript" | "blastParams" | "orthologParams" | "querySeqOffset" | "uniprotId" | "zoomToBaseLevel" | "dataStoreId" | "mafRegion"> & {
502
502
  connectedViewId: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<string>>;
503
503
  connectedFeature: import("@jbrowse/mobx-state-tree").IType<any, any, any>;
504
504
  connectedTranscript: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<string>>;
505
505
  blastParams: import("@jbrowse/mobx-state-tree").IType<BlastParams | undefined, BlastParams | undefined, BlastParams | undefined>;
506
506
  orthologParams: import("@jbrowse/mobx-state-tree").IType<OrthologParams | undefined, OrthologParams | undefined, OrthologParams | undefined>;
507
- querySeqName: import("@jbrowse/mobx-state-tree").IType<string | undefined, string, string>;
508
- querySeqOffset: import("@jbrowse/mobx-state-tree").IType<number | undefined, number, number>;
507
+ querySeqName: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<string>, [undefined]>;
508
+ querySeqOffset: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<number>, [undefined]>;
509
509
  uniprotId: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<string>>;
510
- zoomToBaseLevel: import("@jbrowse/mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
510
+ zoomToBaseLevel: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
511
511
  init: import("@jbrowse/mobx-state-tree").IType<MsaViewInitState | undefined, MsaViewInitState | undefined, MsaViewInitState | undefined>;
512
512
  dataStoreId: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<string>>;
513
513
  launchCompleted: import("@jbrowse/mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
@@ -1509,16 +1509,16 @@ export default function stateModelFactory(): import("@jbrowse/mobx-state-tree").
1509
1509
  clades: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").IArrayType<import("@jbrowse/mobx-state-tree").IType<import("react-msaview").Clade, import("react-msaview").Clade, import("react-msaview").Clade>>, [undefined]>;
1510
1510
  encodings: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").IArrayType<import("@jbrowse/mobx-state-tree").IType<import("react-msaview").Encoding, import("react-msaview").Encoding, import("react-msaview").Encoding>>, [undefined]>;
1511
1511
  rowPanels: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").IArrayType<import("@jbrowse/mobx-state-tree").IType<import("react-msaview").RowPanelSpec, import("react-msaview").RowPanelSpec, import("react-msaview").RowPanelSpec>>, [undefined]>;
1512
- }, "init" | "querySeqName" | "querySeqOffset" | "zoomToBaseLevel" | "launchCompleted" | "connectedViewId" | "connectedFeature" | "connectedTranscript" | "blastParams" | "orthologParams" | "uniprotId" | "dataStoreId" | "mafRegion"> & {
1512
+ }, "init" | "querySeqName" | "launchCompleted" | "connectedViewId" | "connectedFeature" | "connectedTranscript" | "blastParams" | "orthologParams" | "querySeqOffset" | "uniprotId" | "zoomToBaseLevel" | "dataStoreId" | "mafRegion"> & {
1513
1513
  connectedViewId: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<string>>;
1514
1514
  connectedFeature: import("@jbrowse/mobx-state-tree").IType<any, any, any>;
1515
1515
  connectedTranscript: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<string>>;
1516
1516
  blastParams: import("@jbrowse/mobx-state-tree").IType<BlastParams | undefined, BlastParams | undefined, BlastParams | undefined>;
1517
1517
  orthologParams: import("@jbrowse/mobx-state-tree").IType<OrthologParams | undefined, OrthologParams | undefined, OrthologParams | undefined>;
1518
- querySeqName: import("@jbrowse/mobx-state-tree").IType<string | undefined, string, string>;
1519
- querySeqOffset: import("@jbrowse/mobx-state-tree").IType<number | undefined, number, number>;
1518
+ querySeqName: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<string>, [undefined]>;
1519
+ querySeqOffset: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<number>, [undefined]>;
1520
1520
  uniprotId: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<string>>;
1521
- zoomToBaseLevel: import("@jbrowse/mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
1521
+ zoomToBaseLevel: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
1522
1522
  init: import("@jbrowse/mobx-state-tree").IType<MsaViewInitState | undefined, MsaViewInitState | undefined, MsaViewInitState | undefined>;
1523
1523
  dataStoreId: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<string>>;
1524
1524
  launchCompleted: import("@jbrowse/mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
@@ -1803,6 +1803,3 @@ export default function stateModelFactory(): import("@jbrowse/mobx-state-tree").
1803
1803
  export type JBrowsePluginMsaViewStateModel = ReturnType<typeof stateModelFactory>;
1804
1804
  export type JBrowsePluginMsaViewModel = Instance<JBrowsePluginMsaViewStateModel>;
1805
1805
  export { type MafRegion, type MsaViewInitState } from './types';
1806
- export declare function isMsaView(view: {
1807
- type: string;
1808
- }): view is JBrowsePluginMsaViewModel;
@@ -51,12 +51,7 @@ export default function stateModelFactory() {
51
51
  /**
52
52
  * #property
53
53
  */
54
- // Plain defaults, not types.stripDefault: that postdates the
55
- // mobx-state-tree every released core exposes (present only on main), and
56
- // the missing function throws while this model is being built, which
57
- // error-pages the whole app rather than just this view. Restore
58
- // stripDefault once a release ships it.
59
- querySeqName: 'QUERY',
54
+ querySeqName: types.stripDefault(types.string, 'QUERY'),
60
55
  /**
61
56
  * #property
62
57
  * transcript residues before the query row's first residue, so a
@@ -66,8 +61,7 @@ export default function stateModelFactory() {
66
61
  * transcript's first residue put every click off by the trimmed
67
62
  * amount. Negative when the row runs past the transcript's start.
68
63
  */
69
- // see querySeqName above re: types.stripDefault
70
- querySeqOffset: 0,
64
+ querySeqOffset: types.stripDefault(types.number, 0),
71
65
  /**
72
66
  * #property
73
67
  */
@@ -75,8 +69,7 @@ export default function stateModelFactory() {
75
69
  /**
76
70
  * #property
77
71
  */
78
- // see querySeqName above re: types.stripDefault
79
- zoomToBaseLevel: false,
72
+ zoomToBaseLevel: types.stripDefault(types.boolean, false),
80
73
  /**
81
74
  * #property
82
75
  */
@@ -513,6 +506,3 @@ export default function stateModelFactory() {
513
506
  },
514
507
  }));
515
508
  }
516
- export function isMsaView(view) {
517
- return view.type === 'MsaView';
518
- }
@@ -50,13 +50,7 @@ async function findTranscript(self, transcriptId) {
50
50
  const tracks = transcriptTracks(view.tracks);
51
51
  for (const regions of searchWindows(view)) {
52
52
  for (const track of tracks) {
53
- // a named object keeps sessionId, which v4 hosts read from the args
54
- const args = {
55
- adapterConfig: getConf(track, 'adapter'),
56
- sessionId,
57
- regions,
58
- };
59
- const feats = await session.rpcManager.call(sessionId, 'CoreGetFeatures', args);
53
+ const feats = await session.rpcManager.call(sessionId, 'CoreGetFeatures', { adapterConfig: getConf(track, 'adapter'), regions });
60
54
  for (const feat of feats) {
61
55
  const hit = getTranscriptFeatures(feat).find(t => transcriptMatches(t, transcriptId));
62
56
  if (hit) {
@@ -0,0 +1,2 @@
1
+ import{a as i}from"./chunk-DNFD5II2.js";import{a as m}from"./chunk-BX4Z274Q.js";import{a}from"./chunk-J6KYLXRD.js";import{b as r}from"./chunk-FY3BTKY4.js";var e=r(a(),1),o=r(i(),1),t=r(m(),1);var l="8.4.1";function c({onClose:n}){return e.default.createElement(o.Dialog,{open:!0,title:"About",onClose:()=>{n()}},e.default.createElement(t.DialogContent,null,e.default.createElement(t.Typography,null,"MSAView ",l," (",e.default.createElement(t.Link,{target:"_blank",rel:"noopener",href:"https://github.com/gmod/react-msaview"},"Github"),")"),e.default.createElement("ul",null,e.default.createElement("li",null,e.default.createElement(t.Typography,null,"We use some color schemes from the"," ",e.default.createElement(t.Link,{target:"_blank",rel:"noopener",href:"https://github.com/biotite-dev/biotite"},"biotite")," ","project, and their license is reproduced"," ",e.default.createElement(t.Link,{target:"_blank",rel:"noopener",href:"https://github.com/biotite-dev/biotite/blob/master/LICENSE.rst"},"here"))),e.default.createElement("li",null,e.default.createElement(t.Typography,null,"See this page for some information on jalview colorings"," ",e.default.createElement(t.Link,{target:"_blank",rel:"noopener",href:"https://www.jalview.org/help/html/colourSchemes/"},"here"))),e.default.createElement("li",null,e.default.createElement(t.Typography,null,"See this page for some info on the clustal, cinema, maeditor, and lesk color schemes"," ",e.default.createElement(t.Link,{target:"_blank",rel:"noopener",href:"http://www.bioinformatics.nl/~berndb/aacolour.html"},"here"))),e.default.createElement("li",null,e.default.createElement(t.Typography,null,"See this paper about the flower color scheme"," ",e.default.createElement(t.Link,{target:"_blank",rel:"noopener",href:"https://www.ncbi.nlm.nih.gov/pmc/articles/PMC7245768/"},"here"))))))}export{c as default};
2
+ //# sourceMappingURL=AboutDialog-WT6GXMXU.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../node_modules/.pnpm/react-msaview@8.4.1_35cd7d1fa06820f3dff395dec9803110/node_modules/react-msaview/src/components/dialogs/AboutDialog.tsx", "../../node_modules/.pnpm/react-msaview@8.4.1_35cd7d1fa06820f3dff395dec9803110/node_modules/react-msaview/src/version.ts"],
4
+ "sourcesContent": ["import React from 'react'\n\nimport { Dialog } from '@jbrowse/core/ui'\nimport { DialogContent, Link, Typography } from '@mui/material'\n\nimport { version } from '../../version.ts'\n\nexport default function AboutDialog({ onClose }: { onClose: () => void }) {\n return (\n <Dialog\n open\n title=\"About\"\n onClose={() => {\n onClose()\n }}\n >\n <DialogContent>\n <Typography>\n MSAView {version} (\n <Link\n target=\"_blank\"\n rel=\"noopener\"\n href=\"https://github.com/gmod/react-msaview\"\n >\n Github\n </Link>\n )\n </Typography>\n\n <ul>\n <li>\n <Typography>\n We use some color schemes from the{' '}\n <Link\n target=\"_blank\"\n rel=\"noopener\"\n href=\"https://github.com/biotite-dev/biotite\"\n >\n biotite\n </Link>{' '}\n project, and their license is reproduced{' '}\n <Link\n target=\"_blank\"\n rel=\"noopener\"\n href=\"https://github.com/biotite-dev/biotite/blob/master/LICENSE.rst\"\n >\n here\n </Link>\n </Typography>\n </li>\n <li>\n <Typography>\n See this page for some information on jalview colorings{' '}\n <Link\n target=\"_blank\"\n rel=\"noopener\"\n href=\"https://www.jalview.org/help/html/colourSchemes/\"\n >\n here\n </Link>\n </Typography>\n </li>\n <li>\n <Typography>\n See this page for some info on the clustal, cinema, maeditor, and\n lesk color schemes{' '}\n <Link\n target=\"_blank\"\n rel=\"noopener\"\n href=\"http://www.bioinformatics.nl/~berndb/aacolour.html\"\n >\n here\n </Link>\n </Typography>\n </li>\n <li>\n <Typography>\n See this paper about the flower color scheme{' '}\n <Link\n target=\"_blank\"\n rel=\"noopener\"\n href=\"https://www.ncbi.nlm.nih.gov/pmc/articles/PMC7245768/\"\n >\n here\n </Link>\n </Typography>\n </li>\n </ul>\n </DialogContent>\n </Dialog>\n )\n}\n", "export const version = '8.4.1'\n"],
5
+ "mappings": "2JAAA,IAAAA,EAAkB,SAElBC,EAAuB,SACvBC,EAAgD,SCHzC,IAAMC,EAAU,QDOT,SAAPC,EAA6B,CAAE,QAAAC,CAAO,EAA2B,CACtE,OACE,EAAAC,QAAA,cAAC,SAAM,CACL,KAAI,GACJ,MAAM,QACN,QAAS,IAAK,CACZD,EAAO,CACT,CAAC,EAED,EAAAC,QAAA,cAAC,gBAAa,KACZ,EAAAA,QAAA,cAAC,aAAU,gBACAC,OACT,EAAAD,QAAA,cAAC,OAAI,CACH,OAAO,SACP,IAAI,WACJ,KAAK,uCAAuC,EAAA,QAAA,OAOhD,EAAAA,QAAA,cAAA,KAAA,KACE,EAAAA,QAAA,cAAA,KAAA,KACE,EAAAA,QAAA,cAAC,aAAU,0CAC0B,IACnC,EAAAA,QAAA,cAAC,OAAI,CACH,OAAO,SACP,IAAI,WACJ,KAAK,wCAAwC,EAAA,SAAA,EAGvC,+CACiC,IACzC,EAAAA,QAAA,cAAC,OAAI,CACH,OAAO,SACP,IAAI,WACJ,KAAK,gEAAgE,EAAA,MAAA,CAGhE,CACI,EAEf,EAAAA,QAAA,cAAA,KAAA,KACE,EAAAA,QAAA,cAAC,aAAU,+DAC+C,IACxD,EAAAA,QAAA,cAAC,OAAI,CACH,OAAO,SACP,IAAI,WACJ,KAAK,kDAAkD,EAAA,MAAA,CAGlD,CACI,EAEf,EAAAA,QAAA,cAAA,KAAA,KACE,EAAAA,QAAA,cAAC,aAAU,4FAEU,IACnB,EAAAA,QAAA,cAAC,OAAI,CACH,OAAO,SACP,IAAI,WACJ,KAAK,oDAAoD,EAAA,MAAA,CAGpD,CACI,EAEf,EAAAA,QAAA,cAAA,KAAA,KACE,EAAAA,QAAA,cAAC,aAAU,oDACoC,IAC7C,EAAAA,QAAA,cAAC,OAAI,CACH,OAAO,SACP,IAAI,WACJ,KAAK,uDAAuD,EAAA,MAAA,CAGvD,CACI,CACV,CACF,CACS,CAGtB",
6
+ "names": ["import_react", "import_ui", "import_material", "version", "AboutDialog", "onClose", "React", "version"]
7
+ }
@@ -0,0 +1,2 @@
1
+ import{f as E,i as d}from"./chunk-RTKNCGDF.js";import"./chunk-QAC6JSDZ.js";import"./chunk-73KAPCJ2.js";import{a as x}from"./chunk-CVLB4VFP.js";import{a as w}from"./chunk-DNFD5II2.js";import{a as T}from"./chunk-BX4Z274Q.js";import{a as C}from"./chunk-J6KYLXRD.js";import{b as i}from"./chunk-FY3BTKY4.js";var e=i(C(),1),c=i(w(),1),t=i(T(),1),h=i(x(),1);function b(r){let n=r.trimStart();if(!n.startsWith("{"))return r;let a=JSON.parse(n);return d(E(a))}async function O(r){let n=await fetch(r);if(!n.ok)throw new Error(`HTTP ${n.status} fetching ${r} ${await n.text()}`);return n.text()}var R=(0,h.observer)(function({handleClose:r,model:n}){let[a,g]=(0,e.useState)(),[l,v]=(0,e.useState)("file"),[s,F]=(0,e.useState)(""),[m,u]=(0,e.useState)(),[y,f]=(0,e.useState)(!1);return e.default.createElement(c.Dialog,{maxWidth:"xl",title:"Open annotation file",onClose:()=>{r()},open:!0},e.default.createElement(t.DialogContent,null,m?e.default.createElement(c.ErrorMessage,{error:m}):null,e.default.createElement(t.Typography,null,"Open a GFF3 file of annotations, such as the one `react-msaview-cli interpro` writes, or the JSON an InterProScan run returns."),e.default.createElement("div",{style:{display:"flex",margin:30}},e.default.createElement(t.FormControl,{component:"fieldset"},e.default.createElement(t.RadioGroup,{value:l,onChange:o=>{v(o.target.value)}},e.default.createElement(t.FormControlLabel,{value:"url",control:e.default.createElement(t.Radio,null),label:"URL"}),e.default.createElement(t.FormControlLabel,{value:"file",control:e.default.createElement(t.Radio,null),label:"File"}))),l==="url"?e.default.createElement("div",null,e.default.createElement(t.Typography,null,"Open an annotation file from a URL"),e.default.createElement(t.TextField,{label:"URL",value:s,onChange:o=>{F(o.target.value)}})):e.default.createElement("div",{style:{paddingTop:20}},e.default.createElement(t.Typography,null,"Open an annotation file from your local drive"),e.default.createElement(t.Button,{variant:"outlined",component:"label"},"Choose File",e.default.createElement("input",{type:"file",hidden:!0,onChange:({target:o})=>{let p=o.files?.[0];p&&g(p)}})),a?e.default.createElement(t.Typography,null,a.name):null))),e.default.createElement(t.DialogActions,null,e.default.createElement(t.Button,{variant:"contained",color:"primary",disabled:y||(l==="file"?!a:!s.trim()),onClick:()=>{(async()=>{f(!0),u(void 0);try{let o=await(l==="file"&&a?a.text():O(s));n.setGFF(b(o)),n.setShowDomains(!0),r()}catch(o){console.error(o),u(o)}finally{f(!1)}})()}},"Open annotations"),e.default.createElement(t.Button,{variant:"contained",color:"secondary",onClick:()=>{r()}},"Cancel")))}),D=R;export{D as default};
2
+ //# sourceMappingURL=AnnotationFileDialog-34R7LFHB.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../node_modules/.pnpm/react-msaview@8.4.1_35cd7d1fa06820f3dff395dec9803110/node_modules/react-msaview/src/components/dialogs/AnnotationFileDialog.tsx"],
4
+ "sourcesContent": ["import React, { useState } from 'react'\n\nimport { Dialog, ErrorMessage } from '@jbrowse/core/ui'\nimport {\n Button,\n DialogActions,\n DialogContent,\n FormControl,\n FormControlLabel,\n Radio,\n RadioGroup,\n TextField,\n Typography,\n} from '@mui/material'\nimport { observer } from 'mobx-react'\nimport {\n annotationsToGFF,\n interProScanResponseToAnnotations,\n} from 'msa-parsers'\n\nimport type { MsaViewModel } from '../../model.ts'\nimport type { InterProScanResponse } from 'msa-parsers'\n\n// GFF3 as the CLI writes it, or the JSON an InterProScan run returns. Both\n// arrive as text and the model keeps GFF, so the JSON is converted on the way\n// in rather than given a second path through the model\nfunction toGFF(text: string) {\n const trimmed = text.trimStart()\n if (!trimmed.startsWith('{')) {\n return text\n }\n const response: InterProScanResponse = JSON.parse(trimmed)\n return annotationsToGFF(interProScanResponseToAnnotations(response))\n}\n\nasync function fetchText(url: string) {\n const response = await fetch(url)\n if (!response.ok) {\n throw new Error(\n `HTTP ${response.status} fetching ${url} ${await response.text()}`,\n )\n }\n return response.text()\n}\n\nconst AnnotationFileDialog = observer(function ({\n handleClose,\n model,\n}: {\n handleClose: () => void\n model: MsaViewModel\n}) {\n const [file, setFile] = useState<File>()\n const [choice, setChoice] = useState('file')\n const [url, setUrl] = useState('')\n const [error, setError] = useState<unknown>()\n const [loading, setLoading] = useState(false)\n\n // the error is shown here rather than notified: the standalone app and the\n // MSAViewer component have no jbrowse session to notify, and asking one for\n // its notify() threw out of the success path into the catch, which threw\n // again on the same missing session\n return (\n <Dialog\n maxWidth=\"xl\"\n title=\"Open annotation file\"\n onClose={() => {\n handleClose()\n }}\n open\n >\n <DialogContent>\n {error ? <ErrorMessage error={error} /> : null}\n <Typography>\n Open a GFF3 file of annotations, such as the one `react-msaview-cli\n interpro` writes, or the JSON an InterProScan run returns.\n </Typography>\n\n <div style={{ display: 'flex', margin: 30 }}>\n <FormControl component=\"fieldset\">\n <RadioGroup\n value={choice}\n onChange={event => {\n setChoice(event.target.value)\n }}\n >\n <FormControlLabel value=\"url\" control={<Radio />} label=\"URL\" />\n <FormControlLabel value=\"file\" control={<Radio />} label=\"File\" />\n </RadioGroup>\n </FormControl>\n {choice === 'url' ? (\n <div>\n <Typography>Open an annotation file from a URL</Typography>\n <TextField\n label=\"URL\"\n value={url}\n onChange={event => {\n setUrl(event.target.value)\n }}\n />\n </div>\n ) : (\n <div style={{ paddingTop: 20 }}>\n <Typography>\n Open an annotation file from your local drive\n </Typography>\n <Button variant=\"outlined\" component=\"label\">\n Choose File\n <input\n type=\"file\"\n hidden\n onChange={({ target }) => {\n const chosen = target.files?.[0]\n if (chosen) {\n setFile(chosen)\n }\n }}\n />\n </Button>\n {file ? <Typography>{file.name}</Typography> : null}\n </div>\n )}\n </div>\n </DialogContent>\n <DialogActions>\n <Button\n variant=\"contained\"\n color=\"primary\"\n disabled={loading || (choice === 'file' ? !file : !url.trim())}\n onClick={() => {\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n ;(async () => {\n setLoading(true)\n setError(undefined)\n try {\n const text = await (choice === 'file' && file\n ? file.text()\n : fetchText(url))\n // through the model's own GFF text, so the annotations travel\n // in the snapshot and the shared URL like every other layer.\n // Setting them straight onto the volatile left a view whose\n // link opened without them\n model.setGFF(toGFF(text))\n model.setShowDomains(true)\n handleClose()\n } catch (e) {\n console.error(e)\n setError(e)\n } finally {\n setLoading(false)\n }\n })()\n }}\n >\n Open annotations\n </Button>\n <Button\n variant=\"contained\"\n color=\"secondary\"\n onClick={() => {\n handleClose()\n }}\n >\n Cancel\n </Button>\n </DialogActions>\n </Dialog>\n )\n})\n\nexport default AnnotationFileDialog\n"],
5
+ "mappings": "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",
6
+ "names": ["import_react", "import_ui", "import_material", "import_mobx_react", "toGFF", "text", "trimmed", "response", "annotationsToGFF", "interProScanResponseToAnnotations", "fetchText", "url", "AnnotationFileDialog", "handleClose", "model", "file", "setFile", "choice", "setChoice", "setUrl", "error", "setError", "loading", "setLoading", "React", "event", "target", "chosen", "e", "AnnotationFileDialog_default"]
7
+ }
@@ -0,0 +1,4 @@
1
+ import{a as or}from"./chunk-2IWD4OO4.js";import{a as tr,b as B}from"./chunk-FY3BTKY4.js";var V=tr((cr,L)=>{L.exports=JBrowseExports["@jbrowse/core/data_adapters/BaseAdapter"]});var Z=B(or()),rr=B(V());var P=function(t,r){return P=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,o){e.__proto__=o}||function(e,o){for(var n in o)Object.prototype.hasOwnProperty.call(o,n)&&(e[n]=o[n])},P(t,r)};function b(t,r){if(typeof r!="function"&&r!==null)throw new TypeError("Class extends value "+String(r)+" is not a constructor or null");P(t,r);function e(){this.constructor=t}t.prototype=r===null?Object.create(r):(e.prototype=r.prototype,new e)}function T(t){var r=typeof Symbol=="function"&&Symbol.iterator,e=r&&t[r],o=0;if(e)return e.call(t);if(t&&typeof t.length=="number")return{next:function(){return t&&o>=t.length&&(t=void 0),{value:t&&t[o++],done:!t}}};throw new TypeError(r?"Object is not iterable.":"Symbol.iterator is not defined.")}function h(t,r){var e=typeof Symbol=="function"&&t[Symbol.iterator];if(!e)return t;var o=e.call(t),n,i=[],f;try{for(;(r===void 0||r-- >0)&&!(n=o.next()).done;)i.push(n.value)}catch(a){f={error:a}}finally{try{n&&!n.done&&(e=o.return)&&e.call(o)}finally{if(f)throw f.error}}return i}function d(t,r,e){if(e||arguments.length===2)for(var o=0,n=r.length,i;o<n;o++)(i||!(o in r))&&(i||(i=Array.prototype.slice.call(r,0,o)),i[o]=r[o]);return t.concat(i||Array.prototype.slice.call(r))}function u(t){return typeof t=="function"}function g(t){var r=function(o){Error.call(o),o.stack=new Error().stack},e=t(r);return e.prototype=Object.create(Error.prototype),e.prototype.constructor=e,e}var _=g(function(t){return function(e){t(this),this.message=e?e.length+` errors occurred during unsubscription:
2
+ `+e.map(function(o,n){return n+1+") "+o.toString()}).join(`
3
+ `):"",this.name="UnsubscriptionError",this.errors=e}});function j(t,r){if(t){var e=t.indexOf(r);0<=e&&t.splice(e,1)}}var E=(function(){function t(r){this.initialTeardown=r,this.closed=!1,this._parentage=null,this._finalizers=null}return t.prototype.unsubscribe=function(){var r,e,o,n,i;if(!this.closed){this.closed=!0;var f=this._parentage;if(f)if(this._parentage=null,Array.isArray(f))try{for(var a=T(f),p=a.next();!p.done;p=a.next()){var c=p.value;c.remove(this)}}catch(s){r={error:s}}finally{try{p&&!p.done&&(e=a.return)&&e.call(a)}finally{if(r)throw r.error}}else f.remove(this);var l=this.initialTeardown;if(u(l))try{l()}catch(s){i=s instanceof _?s.errors:[s]}var v=this._finalizers;if(v){this._finalizers=null;try{for(var w=T(v),y=w.next();!y.done;y=w.next()){var er=y.value;try{k(er)}catch(s){i=i??[],s instanceof _?i=d(d([],h(i)),h(s.errors)):i.push(s)}}}catch(s){o={error:s}}finally{try{y&&!y.done&&(n=w.return)&&n.call(w)}finally{if(o)throw o.error}}}if(i)throw new _(i)}},t.prototype.add=function(r){var e;if(r&&r!==this)if(this.closed)k(r);else{if(r instanceof t){if(r.closed||r._hasParent(this))return;r._addParent(this)}(this._finalizers=(e=this._finalizers)!==null&&e!==void 0?e:[]).push(r)}},t.prototype._hasParent=function(r){var e=this._parentage;return e===r||Array.isArray(e)&&e.includes(r)},t.prototype._addParent=function(r){var e=this._parentage;this._parentage=Array.isArray(e)?(e.push(r),e):e?[e,r]:r},t.prototype._removeParent=function(r){var e=this._parentage;e===r?this._parentage=null:Array.isArray(e)&&j(e,r)},t.prototype.remove=function(r){var e=this._finalizers;e&&j(e,r),r instanceof t&&r._removeParent(this)},t.EMPTY=(function(){var r=new t;return r.closed=!0,r})(),t})();var _r=E.EMPTY;function q(t){return t instanceof E||t&&"closed"in t&&u(t.remove)&&u(t.add)&&u(t.unsubscribe)}function k(t){u(t)?t():t.unsubscribe()}var m={onUnhandledError:null,onStoppedNotification:null,Promise:void 0,useDeprecatedSynchronousErrorHandling:!1,useDeprecatedNextContext:!1};var x={setTimeout:function(t,r){for(var e=[],o=2;o<arguments.length;o++)e[o-2]=arguments[o];var n=x.delegate;return n?.setTimeout?n.setTimeout.apply(n,d([t,r],h(e))):setTimeout.apply(void 0,d([t,r],h(e)))},clearTimeout:function(t){var r=x.delegate;return(r?.clearTimeout||clearTimeout)(t)},delegate:void 0};function z(t){x.setTimeout(function(){var r=m.onUnhandledError;if(r)r(t);else throw t})}function A(){}var H=(function(){return R("C",void 0,void 0)})();function Y(t){return R("E",void 0,t)}function K(t){return R("N",t,void 0)}function R(t,r,e){return{kind:t,value:r,error:e}}var C=null;function G(t){m.useDeprecatedSynchronousErrorHandling&&C&&(C.errorThrown=!0,C.error=t)}var I=(function(t){b(r,t);function r(e){var o=t.call(this)||this;return o.isStopped=!1,e?(o.destination=e,q(e)&&e.add(o)):o.destination=ar,o}return r.create=function(e,o,n){return new N(e,o,n)},r.prototype.next=function(e){this.isStopped?F(K(e),this):this._next(e)},r.prototype.error=function(e){this.isStopped?F(Y(e),this):(this.isStopped=!0,this._error(e))},r.prototype.complete=function(){this.isStopped?F(H,this):(this.isStopped=!0,this._complete())},r.prototype.unsubscribe=function(){this.closed||(this.isStopped=!0,t.prototype.unsubscribe.call(this),this.destination=null)},r.prototype._next=function(e){this.destination.next(e)},r.prototype._error=function(e){try{this.destination.error(e)}finally{this.unsubscribe()}},r.prototype._complete=function(){try{this.destination.complete()}finally{this.unsubscribe()}},r})(E);var nr=Function.prototype.bind;function M(t,r){return nr.call(t,r)}var ir=(function(){function t(r){this.partialObserver=r}return t.prototype.next=function(r){var e=this.partialObserver;if(e.next)try{e.next(r)}catch(o){S(o)}},t.prototype.error=function(r){var e=this.partialObserver;if(e.error)try{e.error(r)}catch(o){S(o)}else S(r)},t.prototype.complete=function(){var r=this.partialObserver;if(r.complete)try{r.complete()}catch(e){S(e)}},t})(),N=(function(t){b(r,t);function r(e,o,n){var i=t.call(this)||this,f;if(u(e)||!e)f={next:e??void 0,error:o??void 0,complete:n??void 0};else{var a;i&&m.useDeprecatedNextContext?(a=Object.create(e),a.unsubscribe=function(){return i.unsubscribe()},f={next:e.next&&M(e.next,a),error:e.error&&M(e.error,a),complete:e.complete&&M(e.complete,a)}):f=e}return i.destination=new ir(f),i}return r})(I);function S(t){m.useDeprecatedSynchronousErrorHandling?G(t):z(t)}function fr(t){throw t}function F(t,r){var e=m.onStoppedNotification;e&&x.setTimeout(function(){return e(t,r)})}var ar={closed:!0,next:A,error:fr,complete:A};function pr(t){return u(t?.lift)}function O(t){return function(r){if(pr(r))return r.lift(function(e){try{return t(e,this)}catch(o){this.error(o)}});throw new TypeError("Unable to lift unknown Observable type")}}function J(t,r,e,o,n){return new sr(t,r,e,o,n)}var sr=(function(t){b(r,t);function r(e,o,n,i,f,a){var p=t.call(this,e)||this;return p.onFinalize=f,p.shouldUnsubscribe=a,p._next=o?function(c){try{o(c)}catch(l){e.error(l)}}:t.prototype._next,p._error=i?function(c){try{i(c)}catch(l){e.error(l)}finally{this.unsubscribe()}}:t.prototype._error,p._complete=n?function(){try{n()}catch(c){e.error(c)}finally{this.unsubscribe()}}:t.prototype._complete,p}return r.prototype.unsubscribe=function(){var e;if(!this.shouldUnsubscribe||this.shouldUnsubscribe()){var o=this.closed;t.prototype.unsubscribe.call(this),!o&&((e=this.onFinalize)===null||e===void 0||e.call(this))}},r})(I);var $=g(function(t){return function(){t(this),this.name="EmptyError",this.message="no elements in sequence"}});function U(t,r){var e=typeof r=="object";return new Promise(function(o,n){var i=new N({next:function(f){o(f),i.unsubscribe()},error:n,complete:function(){e?o(r.defaultValue):n(new $)}});t.subscribe(i)})}function Q(t,r,e,o,n){return function(i,f){var a=e,p=r,c=0;i.subscribe(J(f,function(l){var v=c++;p=a?t(p,l,v):(a=!0,l),o&&f.next(p)},n&&(function(){a&&f.next(p),f.complete()})))}}function X(t,r){return O(Q(t,r,arguments.length>=2,!1,!0))}var ur=function(t,r){return t.push(r),t};function D(){return O(function(t,r){X(ur,[])(t).subscribe(r)})}var W=class extends rr.BaseAdapter{async configurePre(){let r=this.getSubAdapter;if(r)return(await r({...(0,Z.readConfObject)(this.config),type:"BgzipFastaAdapter"})).dataAdapter;throw new Error("no get subadapter")}configure(){return this.configureP??=this.configurePre().catch(r=>{throw this.configureP=void 0,r}),this.configureP}async getMSARefs(){return this.refNamesP??=this.configure().then(r=>r.getRefNames()).catch(r=>{throw this.refNamesP=void 0,r}),this.refNamesP}getMsaRegex(){return new RegExp(this.getConf("msaRegex"))}refNameToMsaId(r){return r.split(this.getMsaRegex())[0]}async getMSAList(){let r=await this.getMSARefs();return[...new Set(r.map(o=>this.refNameToMsaId(o)))]}async getMSA(r){let e=await this.configure(),n=(await this.getMSARefs()).filter(i=>this.refNameToMsaId(i)===r);return U(e.getFeaturesInMultipleRegions(n.map(i=>({refName:i,start:0,end:1e9,assemblyName:""}))).pipe(D()))}};export{W as default};
4
+ //# sourceMappingURL=BgzipFastaMsaAdapter-ZMUARSUQ.js.map