@jbrowse/plugin-circular-view 2.2.1 → 2.3.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 (66) hide show
  1. package/README.md +13 -4
  2. package/dist/BaseChordDisplay/components/BaseChordDisplay.d.ts +11 -3
  3. package/dist/BaseChordDisplay/components/BaseChordDisplay.js +4 -6
  4. package/dist/BaseChordDisplay/components/BaseChordDisplay.js.map +1 -1
  5. package/dist/BaseChordDisplay/components/DisplayError.js +1 -1
  6. package/dist/BaseChordDisplay/components/DisplayError.js.map +1 -1
  7. package/dist/BaseChordDisplay/components/Loading.js +1 -2
  8. package/dist/BaseChordDisplay/components/Loading.js.map +1 -1
  9. package/dist/BaseChordDisplay/models/BaseChordDisplayModel.d.ts +6 -5
  10. package/dist/BaseChordDisplay/models/BaseChordDisplayModel.js +198 -194
  11. package/dist/BaseChordDisplay/models/BaseChordDisplayModel.js.map +1 -1
  12. package/dist/BaseChordDisplay/models/renderReaction.d.ts +2 -0
  13. package/dist/BaseChordDisplay/models/renderReaction.js +12 -3
  14. package/dist/BaseChordDisplay/models/renderReaction.js.map +1 -1
  15. package/dist/CircularView/components/CircularView.js +2 -2
  16. package/dist/CircularView/components/CircularView.js.map +1 -1
  17. package/dist/CircularView/index.d.ts +3 -0
  18. package/dist/CircularView/index.js +40 -0
  19. package/dist/CircularView/index.js.map +1 -0
  20. package/dist/LaunchCircularView/index.d.ts +3 -0
  21. package/dist/LaunchCircularView/index.js +22 -0
  22. package/dist/LaunchCircularView/index.js.map +1 -0
  23. package/dist/index.d.ts +1 -1
  24. package/dist/index.js +7 -50
  25. package/dist/index.js.map +1 -1
  26. package/esm/BaseChordDisplay/components/BaseChordDisplay.d.ts +11 -3
  27. package/esm/BaseChordDisplay/components/BaseChordDisplay.js +4 -6
  28. package/esm/BaseChordDisplay/components/BaseChordDisplay.js.map +1 -1
  29. package/esm/BaseChordDisplay/components/DisplayError.js +1 -1
  30. package/esm/BaseChordDisplay/components/DisplayError.js.map +1 -1
  31. package/esm/BaseChordDisplay/components/Loading.js +1 -2
  32. package/esm/BaseChordDisplay/components/Loading.js.map +1 -1
  33. package/esm/BaseChordDisplay/models/BaseChordDisplayModel.d.ts +6 -5
  34. package/esm/BaseChordDisplay/models/BaseChordDisplayModel.js +199 -195
  35. package/esm/BaseChordDisplay/models/BaseChordDisplayModel.js.map +1 -1
  36. package/esm/BaseChordDisplay/models/renderReaction.d.ts +2 -0
  37. package/esm/BaseChordDisplay/models/renderReaction.js +9 -3
  38. package/esm/BaseChordDisplay/models/renderReaction.js.map +1 -1
  39. package/esm/CircularView/components/CircularView.js +2 -2
  40. package/esm/CircularView/components/CircularView.js.map +1 -1
  41. package/esm/CircularView/index.d.ts +3 -0
  42. package/esm/CircularView/index.js +12 -0
  43. package/esm/CircularView/index.js.map +1 -0
  44. package/esm/LaunchCircularView/index.d.ts +3 -0
  45. package/esm/LaunchCircularView/index.js +20 -0
  46. package/esm/LaunchCircularView/index.js.map +1 -0
  47. package/esm/index.d.ts +1 -1
  48. package/esm/index.js +6 -26
  49. package/esm/index.js.map +1 -1
  50. package/package.json +6 -5
  51. package/src/BaseChordDisplay/components/BaseChordDisplay.tsx +16 -6
  52. package/src/BaseChordDisplay/components/DisplayError.tsx +41 -43
  53. package/src/BaseChordDisplay/components/Loading.tsx +55 -58
  54. package/src/BaseChordDisplay/models/BaseChordDisplayModel.ts +241 -232
  55. package/src/BaseChordDisplay/models/renderReaction.ts +9 -3
  56. package/src/CircularView/components/CircularView.tsx +73 -75
  57. package/src/CircularView/index.ts +16 -0
  58. package/src/LaunchCircularView/index.ts +48 -0
  59. package/src/index.ts +10 -55
  60. package/dist/BaseChordDisplay/components/RpcRenderedSvgGroup.d.ts +0 -12
  61. package/dist/BaseChordDisplay/components/RpcRenderedSvgGroup.js +0 -73
  62. package/dist/BaseChordDisplay/components/RpcRenderedSvgGroup.js.map +0 -1
  63. package/esm/BaseChordDisplay/components/RpcRenderedSvgGroup.d.ts +0 -12
  64. package/esm/BaseChordDisplay/components/RpcRenderedSvgGroup.js +0 -48
  65. package/esm/BaseChordDisplay/components/RpcRenderedSvgGroup.js.map +0 -1
  66. package/src/BaseChordDisplay/components/RpcRenderedSvgGroup.tsx +0 -69
@@ -1,4 +1,8 @@
1
1
  import React from 'react'
2
+ import clone from 'clone'
3
+ import { getParent, isAlive, types } from 'mobx-state-tree'
4
+
5
+ // jbrowse
2
6
  import { getConf } from '@jbrowse/core/configuration'
3
7
  import { BaseDisplay } from '@jbrowse/core/pluggableElementTypes/models'
4
8
  import CircularChordRendererType from '@jbrowse/core/pluggableElementTypes/renderers/CircularChordRendererType'
@@ -7,17 +11,17 @@ import {
7
11
  getContainingView,
8
12
  getSession,
9
13
  getEnv,
14
+ isFeature,
10
15
  makeAbortableReaction,
11
16
  AnyReactComponentType,
17
+ Feature,
18
+ Region,
12
19
  } from '@jbrowse/core/util'
13
- import { Feature, isFeature } from '@jbrowse/core/util/simpleFeature'
14
20
  import {
15
21
  getParentRenderProps,
16
22
  getRpcSessionId,
17
23
  getTrackAssemblyNames,
18
24
  } from '@jbrowse/core/util/tracks'
19
- import { Region } from '@jbrowse/core/util/types'
20
- import { getParent, isAlive, types } from 'mobx-state-tree'
21
25
 
22
26
  // locals
23
27
  import { renderReactionData, renderReactionEffect } from './renderReaction'
@@ -27,252 +31,257 @@ import { CircularViewModel } from '../../CircularView/models/CircularView'
27
31
  * #stateModel BaseChordDisplay
28
32
  * extends `BaseDisplay`
29
33
  */
30
- function stateModelFactory() {
31
- return types
32
- .compose(
33
- 'BaseChordDisplay',
34
- BaseDisplay,
35
- types.model({
36
- /**
37
- * #property
38
- */
39
- bezierRadiusRatio: 0.1,
40
- /**
41
- * #property
42
- */
43
- assemblyName: types.maybe(types.string),
44
- }),
45
- )
46
- .volatile(() => {
47
- return {
48
- // NOTE: all this volatile stuff has to be filled in at once
49
- // so that it stays consistent
50
- filled: false,
51
- reactElement: undefined as React.ReactElement | undefined,
52
- data: undefined,
53
- message: '',
54
- renderingComponent: undefined as undefined | AnyReactComponentType,
55
- refNameMap: undefined as Record<string, string> | undefined,
56
- }
57
- })
58
- .actions(self => {
59
- const { pluginManager } = getEnv(self)
60
- const track = self
61
- return {
62
- /**
63
- * #action
64
- */
65
- onChordClick(feature: Feature) {
66
- getConf(self, 'onChordClick', { feature, track, pluginManager })
67
- },
68
- }
69
- })
70
- .views(self => ({
34
+ function x() {} // eslint-disable-line @typescript-eslint/no-unused-vars
35
+
36
+ export const BaseChordDisplayModel = types
37
+ .compose(
38
+ 'BaseChordDisplay',
39
+ BaseDisplay,
40
+ types.model({
71
41
  /**
72
- * #getter
42
+ * #property
73
43
  */
74
- get blockDefinitions() {
75
- const origSlices = (getContainingView(self) as CircularViewModel)
76
- .staticSlices
77
- if (!self.refNameMap) {
78
- return origSlices
79
- }
44
+ bezierRadiusRatio: 0.1,
45
+ /**
46
+ * #property
47
+ */
48
+ assemblyName: types.maybe(types.string),
49
+ }),
50
+ )
51
+ .volatile(() => {
52
+ return {
53
+ // NOTE: all this volatile stuff has to be filled in at once
54
+ // so that it stays consistent
55
+ filled: false,
56
+ reactElement: undefined as React.ReactElement | undefined,
57
+ data: undefined,
58
+ html: undefined as string | undefined,
59
+ message: '',
60
+ renderingComponent: undefined as undefined | AnyReactComponentType,
61
+ refNameMap: undefined as Record<string, string> | undefined,
62
+ }
63
+ })
64
+ .actions(self => {
65
+ const { pluginManager } = getEnv(self)
66
+ const track = self
67
+ return {
68
+ /**
69
+ * #action
70
+ */
71
+ onChordClick(feature: Feature) {
72
+ getConf(self, 'onChordClick', { feature, track, pluginManager })
73
+ },
74
+ }
75
+ })
76
+ .views(self => ({
77
+ /**
78
+ * #getter
79
+ */
80
+ get blockDefinitions() {
81
+ const origSlices = (getContainingView(self) as CircularViewModel)
82
+ .staticSlices
83
+ if (!self.refNameMap) {
84
+ return origSlices
85
+ }
80
86
 
81
- const slices = JSON.parse(JSON.stringify(origSlices))
87
+ const slices = clone(origSlices)
82
88
 
83
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
84
- slices.forEach((slice: any) => {
85
- const regions = slice.region.elided
86
- ? slice.region.regions
87
- : [slice.region]
88
- regions.forEach((region: Region) => {
89
- const renamed = self.refNameMap?.[region.refName]
90
- if (renamed && region.refName !== renamed) {
91
- region.refName = renamed
92
- }
93
- })
89
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
90
+ slices.forEach((slice: any) => {
91
+ const regions = slice.region.elided
92
+ ? slice.region.regions
93
+ : [slice.region]
94
+ regions.forEach((region: Region) => {
95
+ const renamed = self.refNameMap?.[region.refName]
96
+ if (renamed && region.refName !== renamed) {
97
+ region.refName = renamed
98
+ }
94
99
  })
95
- return slices
96
- },
100
+ })
101
+ return slices
102
+ },
97
103
 
98
- /**
99
- * #method
100
- */
101
- renderProps() {
102
- const view = getContainingView(self) as CircularViewModel
103
- return {
104
- ...getParentRenderProps(self),
105
- rpcDriverName: self.rpcDriverName,
106
- displayModel: self,
107
- bezierRadius: view.radiusPx * self.bezierRadiusRatio,
108
- radius: view.radiusPx,
109
- blockDefinitions: this.blockDefinitions,
110
- onChordClick: self.onChordClick,
111
- }
112
- },
104
+ /**
105
+ * #method
106
+ */
107
+ renderProps() {
108
+ const view = getContainingView(self) as CircularViewModel
109
+ return {
110
+ ...getParentRenderProps(self),
111
+ rpcDriverName: self.rpcDriverName,
112
+ displayModel: self,
113
+ bezierRadius: view.radiusPx * self.bezierRadiusRatio,
114
+ radius: view.radiusPx,
115
+ blockDefinitions: this.blockDefinitions,
116
+ onChordClick: self.onChordClick,
117
+ }
118
+ },
113
119
 
114
- /**
115
- * #getter
116
- * the pluggable element type object for this diplay's
117
- * renderer
118
- */
119
- get rendererType() {
120
- const display = self
121
- const { pluginManager } = getEnv(self)
122
- const ThisRendererType = pluginManager.getRendererType(
123
- self.rendererTypeName,
120
+ /**
121
+ * #getter
122
+ * the pluggable element type object for this display's
123
+ * renderer
124
+ */
125
+ get rendererType() {
126
+ const display = self
127
+ const { pluginManager } = getEnv(self)
128
+ const ThisRendererType = pluginManager.getRendererType(
129
+ self.rendererTypeName,
130
+ )
131
+ if (!ThisRendererType) {
132
+ throw new Error(`renderer "${display.rendererTypeName}" not found`)
133
+ }
134
+ if (!ThisRendererType.ReactComponent) {
135
+ throw new Error(
136
+ `renderer ${display.rendererTypeName} has no ReactComponent, it may not be completely implemented yet`,
124
137
  )
125
- if (!ThisRendererType) {
126
- throw new Error(`renderer "${display.rendererTypeName}" not found`)
127
- }
128
- if (!ThisRendererType.ReactComponent) {
129
- throw new Error(
130
- `renderer ${display.rendererTypeName} has no ReactComponent, it may not be completely implemented yet`,
131
- )
132
- }
133
- return ThisRendererType
134
- },
138
+ }
139
+ return ThisRendererType
140
+ },
135
141
 
136
- /**
137
- * #method
138
- */
139
- isCompatibleWithRenderer(renderer: RendererType) {
140
- return !!(renderer instanceof CircularChordRendererType)
141
- },
142
+ /**
143
+ * #method
144
+ */
145
+ isCompatibleWithRenderer(renderer: RendererType) {
146
+ return !!(renderer instanceof CircularChordRendererType)
147
+ },
142
148
 
143
- /**
144
- * #getter
145
- * returns a string feature ID if the globally-selected object
146
- * is probably a feature
147
- */
148
- get selectedFeatureId() {
149
- if (!isAlive(self)) {
150
- return undefined
151
- }
152
- const session = getSession(self)
153
- if (!session) {
154
- return undefined
155
- }
156
- const { selection } = session
157
- // does it quack like a feature?
158
- if (isFeature(selection)) {
159
- return selection.id()
160
- }
149
+ /**
150
+ * #getter
151
+ * returns a string feature ID if the globally-selected object
152
+ * is probably a feature
153
+ */
154
+ get selectedFeatureId() {
155
+ if (!isAlive(self)) {
161
156
  return undefined
162
- },
163
- }))
164
- .actions(self => ({
165
- /**
166
- * #action
167
- */
168
- renderStarted() {
157
+ }
158
+ const session = getSession(self)
159
+ if (!session) {
160
+ return undefined
161
+ }
162
+ const { selection } = session
163
+ // does it quack like a feature?
164
+ if (isFeature(selection)) {
165
+ return selection.id()
166
+ }
167
+ return undefined
168
+ },
169
+ }))
170
+ .actions(self => ({
171
+ /**
172
+ * #action
173
+ */
174
+ renderStarted() {
175
+ self.filled = false
176
+ self.message = ''
177
+ self.reactElement = undefined
178
+ self.data = undefined
179
+ self.html = undefined
180
+ self.error = undefined
181
+ self.renderingComponent = undefined
182
+ },
183
+ /**
184
+ * #action
185
+ */
186
+ renderSuccess({
187
+ message,
188
+ data,
189
+ reactElement,
190
+ html,
191
+ renderingComponent,
192
+ }: {
193
+ message: string
194
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
195
+ data: any
196
+ html: string
197
+ reactElement: React.ReactElement
198
+ renderingComponent: AnyReactComponentType
199
+ }) {
200
+ if (message) {
169
201
  self.filled = false
170
- self.message = ''
202
+ self.message = message
171
203
  self.reactElement = undefined
172
204
  self.data = undefined
205
+ self.html = undefined
173
206
  self.error = undefined
174
207
  self.renderingComponent = undefined
175
- },
176
- /**
177
- * #action
178
- */
179
- renderSuccess({
180
- message,
181
- data,
182
- reactElement,
183
- renderingComponent,
184
- }: {
185
- message: string
186
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
187
- data: any
188
- reactElement: React.ReactElement
189
- renderingComponent: AnyReactComponentType
190
- }) {
191
- if (message) {
192
- self.filled = false
193
- self.message = message
194
- self.reactElement = undefined
195
- self.data = undefined
196
- self.error = undefined
197
- self.renderingComponent = undefined
198
- } else {
199
- self.filled = true
200
- self.message = ''
201
- self.reactElement = reactElement
202
- self.data = data
203
- self.error = undefined
204
- self.renderingComponent = renderingComponent
205
- }
206
- },
207
- /**
208
- * #action
209
- */
210
- renderError(error: unknown) {
211
- console.error(error)
212
- // the rendering failed for some reason
213
- self.filled = false
208
+ } else {
209
+ self.filled = true
214
210
  self.message = ''
215
- self.reactElement = undefined
216
- self.data = undefined
217
- self.error = error
218
- self.renderingComponent = undefined
219
- },
211
+ self.reactElement = reactElement
212
+ self.data = data
213
+ self.html = html
214
+ self.error = undefined
215
+ self.renderingComponent = renderingComponent
216
+ }
217
+ },
218
+ /**
219
+ * #action
220
+ */
221
+ renderError(error: unknown) {
222
+ console.error(error)
223
+ // the rendering failed for some reason
224
+ self.filled = false
225
+ self.message = ''
226
+ self.reactElement = undefined
227
+ self.html = undefined
228
+ self.data = undefined
229
+ self.error = error
230
+ self.renderingComponent = undefined
231
+ },
220
232
 
221
- /**
222
- * #action
223
- */
224
- setRefNameMap(refNameMap: Record<string, string>) {
225
- self.refNameMap = refNameMap
226
- },
227
- }))
228
- .actions(self => ({
229
- afterAttach() {
230
- makeAbortableReaction(
231
- self,
232
- renderReactionData,
233
+ /**
234
+ * #action
235
+ */
236
+ setRefNameMap(refNameMap: Record<string, string>) {
237
+ self.refNameMap = refNameMap
238
+ },
239
+ }))
240
+ .actions(self => ({
241
+ afterAttach() {
242
+ makeAbortableReaction(
243
+ self,
244
+ renderReactionData,
233
245
 
234
- // @ts-ignore
235
- renderReactionEffect,
236
- {
237
- name: `${self.type} ${self.id} rendering`,
238
- // delay: self.renderDelay || 300,
239
- fireImmediately: true,
240
- },
241
- self.renderStarted,
242
- self.renderSuccess,
243
- self.renderError,
244
- )
245
- makeAbortableReaction(
246
- self,
247
- () => ({
248
- assemblyNames: getTrackAssemblyNames(self.parentTrack) as string[],
249
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
250
- adapter: getConf(getParent<any>(self, 2), 'adapter'),
251
- assemblyManager: getSession(self).assemblyManager,
252
- }),
246
+ // @ts-ignore
247
+ renderReactionEffect,
248
+ {
249
+ name: `${self.type} ${self.id} rendering`,
250
+ // delay: self.renderDelay || 300,
251
+ fireImmediately: true,
252
+ },
253
+ self.renderStarted,
254
+ self.renderSuccess,
255
+ self.renderError,
256
+ )
257
+ makeAbortableReaction(
258
+ self,
259
+ () => ({
260
+ assemblyNames: getTrackAssemblyNames(self.parentTrack) as string[],
253
261
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
254
- async ({ assemblyNames, adapter, assemblyManager }: any, signal) => {
255
- return assemblyManager.getRefNameMapForAdapter(
256
- adapter,
257
- assemblyNames[0],
258
- { signal, sessionId: getRpcSessionId(self) },
259
- )
260
- },
261
- {
262
- name: `${self.type} ${self.id} getting refNames`,
263
- fireImmediately: true,
264
- },
265
- () => {},
266
- refNameMap => {
267
- self.setRefNameMap(refNameMap)
268
- },
269
- error => {
270
- console.error(error)
271
- self.setError(error)
272
- },
273
- )
274
- },
275
- }))
276
- }
277
-
278
- export const BaseChordDisplayModel = stateModelFactory()
262
+ adapter: getConf(getParent<any>(self, 2), 'adapter'),
263
+ assemblyManager: getSession(self).assemblyManager,
264
+ }),
265
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
266
+ async ({ assemblyNames, adapter, assemblyManager }: any, signal) => {
267
+ return assemblyManager.getRefNameMapForAdapter(
268
+ adapter,
269
+ assemblyNames[0],
270
+ { signal, sessionId: getRpcSessionId(self) },
271
+ )
272
+ },
273
+ {
274
+ name: `${self.type} ${self.id} getting refNames`,
275
+ fireImmediately: true,
276
+ },
277
+ () => {},
278
+ refNameMap => {
279
+ self.setRefNameMap(refNameMap)
280
+ },
281
+ error => {
282
+ console.error(error)
283
+ self.setError(error)
284
+ },
285
+ )
286
+ },
287
+ }))
@@ -1,3 +1,4 @@
1
+ import clone from 'clone'
1
2
  import { getRpcSessionId } from '@jbrowse/core/util/tracks'
2
3
  import { getSession, getContainingView } from '@jbrowse/core/util'
3
4
 
@@ -13,9 +14,9 @@ export function renderReactionData(self: any) {
13
14
  renderProps: self.renderProps(),
14
15
  renderArgs: {
15
16
  assemblyName: view.displayedRegions[0]?.assemblyName,
16
- adapterConfig: JSON.parse(JSON.stringify(self.adapterConfig)),
17
+ adapterConfig: clone(self.adapterConfig),
17
18
  rendererType: rendererType.name,
18
- regions: JSON.parse(JSON.stringify(view.displayedRegions)),
19
+ regions: clone(view.displayedRegions),
19
20
  blockDefinitions: self.blockDefinitions,
20
21
  sessionId: getRpcSessionId(self),
21
22
  timeout: 1000000,
@@ -68,5 +69,10 @@ export async function renderReactionEffect(
68
69
  signal,
69
70
  })
70
71
 
71
- return { html, data, renderingComponent: rendererType.ReactComponent }
72
+ return {
73
+ html,
74
+ data,
75
+ reactElement: data.reactElement,
76
+ renderingComponent: rendererType.ReactComponent,
77
+ }
72
78
  }