react-msaview 5.0.7 → 5.0.13

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 (169) hide show
  1. package/bundle/index.js +25 -25
  2. package/bundle/index.js.map +1 -1
  3. package/dist/components/Checkbox2.js +3 -6
  4. package/dist/components/Checkbox2.js.map +1 -1
  5. package/dist/components/MSAViewer.d.ts +14 -0
  6. package/dist/components/MSAViewer.js +34 -0
  7. package/dist/components/MSAViewer.js.map +1 -0
  8. package/dist/components/Track.js +5 -24
  9. package/dist/components/Track.js.map +1 -1
  10. package/dist/components/dialogs/DomainDialog.js +2 -5
  11. package/dist/components/dialogs/DomainDialog.js.map +1 -1
  12. package/dist/components/dialogs/InterProScanDialog.js +7 -7
  13. package/dist/components/dialogs/InterProScanDialog.js.map +1 -1
  14. package/dist/components/dialogs/SettingsDialog.js +3 -19
  15. package/dist/components/dialogs/SettingsDialog.js.map +1 -1
  16. package/dist/components/header/ColorSchemeMenu.d.ts +6 -0
  17. package/dist/components/header/ColorSchemeMenu.js +19 -0
  18. package/dist/components/header/ColorSchemeMenu.js.map +1 -0
  19. package/dist/components/header/{ZoomStar.d.ts → FileMenu.d.ts} +2 -2
  20. package/dist/components/header/FileMenu.js +71 -0
  21. package/dist/components/header/FileMenu.js.map +1 -0
  22. package/dist/components/header/Header.js +8 -6
  23. package/dist/components/header/Header.js.map +1 -1
  24. package/dist/components/header/HeaderMenu.js +3 -145
  25. package/dist/components/header/HeaderMenu.js.map +1 -1
  26. package/dist/components/header/MSASettingsMenu.d.ts +6 -0
  27. package/dist/components/header/MSASettingsMenu.js +36 -0
  28. package/dist/components/header/MSASettingsMenu.js.map +1 -0
  29. package/dist/components/header/SettingsMenu.js +1 -21
  30. package/dist/components/header/SettingsMenu.js.map +1 -1
  31. package/dist/components/header/TreeSettingsMenu.d.ts +6 -0
  32. package/dist/components/header/TreeSettingsMenu.js +74 -0
  33. package/dist/components/header/TreeSettingsMenu.js.map +1 -0
  34. package/dist/components/header/ZoomMenu.js +0 -8
  35. package/dist/components/header/ZoomMenu.js.map +1 -1
  36. package/dist/components/header/getDomainsMenu.d.ts +31 -0
  37. package/dist/components/header/getDomainsMenu.js +75 -0
  38. package/dist/components/header/getDomainsMenu.js.map +1 -0
  39. package/dist/components/import/ImportFormExamples.js +21 -19
  40. package/dist/components/import/ImportFormExamples.js.map +1 -1
  41. package/dist/components/msa/MSACanvas.js +13 -84
  42. package/dist/components/msa/MSACanvas.js.map +1 -1
  43. package/dist/components/msa/MSACanvasBlock.js +1 -3
  44. package/dist/components/msa/MSACanvasBlock.js.map +1 -1
  45. package/dist/components/msa/renderMSABlock.js +2 -4
  46. package/dist/components/msa/renderMSABlock.js.map +1 -1
  47. package/dist/components/msa/renderMSAMouseover.js +1 -7
  48. package/dist/components/msa/renderMSAMouseover.js.map +1 -1
  49. package/dist/components/tree/TreeCanvas.js +14 -91
  50. package/dist/components/tree/TreeCanvas.js.map +1 -1
  51. package/dist/components/tree/TreeNodeMenu.js +5 -16
  52. package/dist/components/tree/TreeNodeMenu.js.map +1 -1
  53. package/dist/components/tree/renderTreeCanvas.js +4 -12
  54. package/dist/components/tree/renderTreeCanvas.js.map +1 -1
  55. package/dist/constants.d.ts +0 -2
  56. package/dist/constants.js +0 -2
  57. package/dist/constants.js.map +1 -1
  58. package/dist/fetchUtils.d.ts +0 -1
  59. package/dist/fetchUtils.js +0 -4
  60. package/dist/fetchUtils.js.map +1 -1
  61. package/dist/flatToTree.d.ts +0 -5
  62. package/dist/flatToTree.js +13 -30
  63. package/dist/flatToTree.js.map +1 -1
  64. package/dist/hierarchy.d.ts +28 -0
  65. package/dist/hierarchy.js +164 -0
  66. package/dist/hierarchy.js.map +1 -0
  67. package/dist/index.d.ts +2 -0
  68. package/dist/index.js +1 -0
  69. package/dist/index.js.map +1 -1
  70. package/dist/launchInterProScan.d.ts +0 -5
  71. package/dist/launchInterProScan.js +5 -3
  72. package/dist/launchInterProScan.js.map +1 -1
  73. package/dist/model/DataModel.d.ts +9 -0
  74. package/dist/model/DataModel.js +12 -1
  75. package/dist/model/DataModel.js.map +1 -1
  76. package/dist/model/msaModel.d.ts +3 -0
  77. package/dist/model/msaModel.js +0 -1
  78. package/dist/model/msaModel.js.map +1 -1
  79. package/dist/model/treeModel.d.ts +3 -6
  80. package/dist/model/treeModel.js +3 -15
  81. package/dist/model/treeModel.js.map +1 -1
  82. package/dist/model.d.ts +24 -77
  83. package/dist/model.js +117 -239
  84. package/dist/model.js.map +1 -1
  85. package/dist/neighborJoining.js +38 -629
  86. package/dist/neighborJoining.js.map +1 -1
  87. package/dist/parseAsn1.d.ts +0 -12
  88. package/dist/parseAsn1.js +125 -332
  89. package/dist/parseAsn1.js.map +1 -1
  90. package/dist/useWheelScroll.d.ts +8 -0
  91. package/dist/useWheelScroll.js +93 -0
  92. package/dist/useWheelScroll.js.map +1 -0
  93. package/dist/util.d.ts +1 -6
  94. package/dist/util.js +5 -34
  95. package/dist/util.js.map +1 -1
  96. package/dist/vendor/copyToClipboard.d.ts +1 -10
  97. package/dist/vendor/copyToClipboard.js +14 -109
  98. package/dist/vendor/copyToClipboard.js.map +1 -1
  99. package/dist/vendor/fileSaver.d.ts +1 -11
  100. package/dist/vendor/fileSaver.js +7 -76
  101. package/dist/vendor/fileSaver.js.map +1 -1
  102. package/dist/version.d.ts +1 -1
  103. package/dist/version.js +1 -1
  104. package/dist/version.js.map +1 -1
  105. package/package.json +10 -13
  106. package/src/collapseLogic.test.ts +115 -0
  107. package/src/components/Checkbox2.tsx +9 -18
  108. package/src/components/MSAViewer.tsx +67 -0
  109. package/src/components/Track.tsx +10 -26
  110. package/src/components/dialogs/DomainDialog.tsx +4 -5
  111. package/src/components/dialogs/InterProScanDialog.tsx +7 -7
  112. package/src/components/dialogs/SettingsDialog.tsx +0 -37
  113. package/src/components/header/ColorSchemeMenu.tsx +35 -0
  114. package/src/components/header/FileMenu.tsx +84 -0
  115. package/src/components/header/Header.tsx +8 -6
  116. package/src/components/header/HeaderMenu.tsx +4 -155
  117. package/src/components/header/MSASettingsMenu.tsx +48 -0
  118. package/src/components/header/SettingsMenu.tsx +0 -23
  119. package/src/components/header/TreeSettingsMenu.tsx +96 -0
  120. package/src/components/header/ZoomMenu.tsx +0 -8
  121. package/src/components/header/getDomainsMenu.ts +83 -0
  122. package/src/components/import/ImportFormExamples.tsx +37 -34
  123. package/src/components/msa/MSACanvas.tsx +21 -91
  124. package/src/components/msa/MSACanvasBlock.tsx +1 -3
  125. package/src/components/msa/renderBoxFeatureCanvasBlock.ts +1 -1
  126. package/src/components/msa/renderMSABlock.ts +2 -5
  127. package/src/components/msa/renderMSAMouseover.ts +0 -6
  128. package/src/components/tree/TreeCanvas.tsx +35 -100
  129. package/src/components/tree/TreeNodeMenu.tsx +5 -14
  130. package/src/components/tree/renderTreeCanvas.ts +8 -21
  131. package/src/constants.ts +0 -2
  132. package/src/fetchUtils.ts +0 -5
  133. package/src/flatToTree.ts +20 -38
  134. package/src/hierarchy.test.ts +120 -0
  135. package/src/hierarchy.ts +220 -0
  136. package/src/index.ts +2 -0
  137. package/src/launchInterProScan.ts +4 -3
  138. package/src/model/DataModel.ts +12 -1
  139. package/src/model/msaModel.ts +0 -2
  140. package/src/model/treeModel.ts +2 -18
  141. package/src/model.ts +179 -278
  142. package/src/neighborJoining.ts +38 -628
  143. package/src/parseAsn1.test.ts +4 -1
  144. package/src/parseAsn1.ts +135 -405
  145. package/src/useWheelScroll.ts +109 -0
  146. package/src/util.ts +5 -50
  147. package/src/vendor/copyToClipboard.ts +14 -122
  148. package/src/vendor/fileSaver.ts +8 -105
  149. package/src/version.ts +1 -1
  150. package/dist/components/dialogs/AddTrackDialog.d.ts +0 -8
  151. package/dist/components/dialogs/AddTrackDialog.js +0 -30
  152. package/dist/components/dialogs/AddTrackDialog.js.map +0 -1
  153. package/dist/components/dialogs/TabPanel.d.ts +0 -6
  154. package/dist/components/dialogs/TabPanel.js +0 -6
  155. package/dist/components/dialogs/TabPanel.js.map +0 -1
  156. package/dist/components/header/ZoomStar.js +0 -40
  157. package/dist/components/header/ZoomStar.js.map +0 -1
  158. package/dist/layout.d.ts +0 -26
  159. package/dist/layout.js +0 -74
  160. package/dist/layout.js.map +0 -1
  161. package/dist/reparseTree.d.ts +0 -2
  162. package/dist/reparseTree.js +0 -15
  163. package/dist/reparseTree.js.map +0 -1
  164. package/src/components/dialogs/AddTrackDialog.tsx +0 -85
  165. package/src/components/dialogs/TabPanel.tsx +0 -19
  166. package/src/components/header/ZoomStar.tsx +0 -74
  167. package/src/createPaletteMap.test.ts +0 -57
  168. package/src/layout.ts +0 -118
  169. package/src/reparseTree.ts +0 -18
@@ -0,0 +1,109 @@
1
+ import { useEffect, useRef, useState } from 'react'
2
+
3
+ export function useWheelScroll({
4
+ ref,
5
+ onScrollX,
6
+ onScrollY,
7
+ }: {
8
+ ref: React.RefObject<HTMLDivElement | null>
9
+ onScrollX?: (delta: number) => void
10
+ onScrollY?: (delta: number) => void
11
+ }) {
12
+ const scheduled = useRef(false)
13
+ const deltaX = useRef(0)
14
+ const deltaY = useRef(0)
15
+ const prevX = useRef(0)
16
+ const prevY = useRef(0)
17
+ const [mouseDragging, setMouseDragging] = useState(false)
18
+
19
+ useEffect(() => {
20
+ const curr = ref.current
21
+ if (!curr) {
22
+ return
23
+ }
24
+ function onWheel(event: WheelEvent) {
25
+ if (onScrollX) {
26
+ deltaX.current += event.deltaX
27
+ }
28
+ if (onScrollY) {
29
+ deltaY.current += event.deltaY
30
+ }
31
+
32
+ if (!scheduled.current) {
33
+ scheduled.current = true
34
+ requestAnimationFrame(() => {
35
+ if (onScrollX) {
36
+ onScrollX(-deltaX.current)
37
+ deltaX.current = 0
38
+ }
39
+ if (onScrollY) {
40
+ onScrollY(-deltaY.current)
41
+ deltaY.current = 0
42
+ }
43
+ scheduled.current = false
44
+ })
45
+ }
46
+ event.preventDefault()
47
+ event.stopPropagation()
48
+ }
49
+ curr.addEventListener('wheel', onWheel, { passive: false })
50
+ return () => {
51
+ curr.removeEventListener('wheel', onWheel)
52
+ }
53
+ }, [ref, onScrollX, onScrollY])
54
+
55
+ useEffect(() => {
56
+ if (!mouseDragging) {
57
+ return
58
+ }
59
+ function globalMouseMove(event: MouseEvent) {
60
+ event.preventDefault()
61
+ const distanceX = event.clientX - prevX.current
62
+ const distanceY = event.clientY - prevY.current
63
+ if ((distanceX && onScrollX) || (distanceY && onScrollY)) {
64
+ if (!scheduled.current) {
65
+ scheduled.current = true
66
+ requestAnimationFrame(() => {
67
+ onScrollX?.(distanceX)
68
+ onScrollY?.(distanceY)
69
+ scheduled.current = false
70
+ prevX.current = event.clientX
71
+ prevY.current = event.clientY
72
+ })
73
+ }
74
+ }
75
+ }
76
+
77
+ function globalMouseUp() {
78
+ prevX.current = 0
79
+ prevY.current = 0
80
+ setMouseDragging(false)
81
+ }
82
+
83
+ window.addEventListener('mousemove', globalMouseMove, true)
84
+ window.addEventListener('mouseup', globalMouseUp, true)
85
+ return () => {
86
+ window.removeEventListener('mousemove', globalMouseMove, true)
87
+ window.removeEventListener('mouseup', globalMouseUp, true)
88
+ }
89
+ }, [mouseDragging, onScrollX, onScrollY])
90
+
91
+ function onMouseDown(event: React.MouseEvent) {
92
+ const target = event.target as HTMLElement
93
+ if (target.draggable || target.dataset.resizer) {
94
+ return
95
+ }
96
+ if (event.button === 0) {
97
+ prevX.current = event.clientX
98
+ prevY.current = event.clientY
99
+ setMouseDragging(true)
100
+ }
101
+ }
102
+
103
+ function onMouseUp(event: React.MouseEvent) {
104
+ event.preventDefault()
105
+ setMouseDragging(false)
106
+ }
107
+
108
+ return { onMouseDown, onMouseUp }
109
+ }
package/src/util.ts CHANGED
@@ -1,10 +1,7 @@
1
1
  import { colord, extend } from 'colord'
2
2
  import namesPlugin from 'colord/plugins/names'
3
- import { max } from 'd3-array'
4
3
 
5
- import type { NodeWithIds } from './types.ts'
6
4
  import type { Theme } from '@mui/material'
7
- import type { HierarchyNode } from 'd3-hierarchy'
8
5
 
9
6
  extend([namesPlugin])
10
7
 
@@ -25,66 +22,24 @@ export function colorContrast(
25
22
  ])
26
23
  }
27
24
 
28
- export function skipBlanks(blanks: number[], arg: string | string[]) {
25
+ export function skipBlanks(blanks: number[], str: string) {
29
26
  if (blanks.length === 0) {
30
- return typeof arg === 'string' ? arg : arg.join('')
27
+ return str
31
28
  }
32
29
  const chunks = []
33
30
  let lastEnd = 0
34
31
  for (const blankIdx of blanks) {
35
32
  if (blankIdx > lastEnd) {
36
- chunks.push(
37
- typeof arg === 'string'
38
- ? arg.slice(lastEnd, blankIdx)
39
- : arg.slice(lastEnd, blankIdx).join(''),
40
- )
33
+ chunks.push(str.slice(lastEnd, blankIdx))
41
34
  }
42
35
  lastEnd = blankIdx + 1
43
36
  }
44
- if (lastEnd < arg.length) {
45
- chunks.push(
46
- typeof arg === 'string'
47
- ? arg.slice(lastEnd)
48
- : arg.slice(lastEnd).join(''),
49
- )
37
+ if (lastEnd < str.length) {
38
+ chunks.push(str.slice(lastEnd))
50
39
  }
51
40
  return chunks.join('')
52
41
  }
53
42
 
54
- // basically same as setRadius from https://observablehq.com/@d3/tree-of-life
55
- export function setBrLength(
56
- d: HierarchyNode<NodeWithIds>,
57
- y0: number,
58
- k: number,
59
- ) {
60
- // @ts-expect-error
61
- d.len = (y0 += Math.max(d.data.length || 0, 0)) * k
62
-
63
- if (d.children) {
64
- d.children.forEach(d => {
65
- setBrLength(d, y0, k)
66
- })
67
- }
68
- }
69
-
70
- // basically same as maxLength from https://observablehq.com/@d3/tree-of-life
71
- export function maxLength(d: HierarchyNode<NodeWithIds>): number {
72
- return (
73
- (d.data.length || 0) + (d.children ? max(d.children, maxLength) || 0 : 0)
74
- )
75
- }
76
-
77
- // Collapse the node and all it's children, from
78
- // https://bl.ocks.org/d3noob/43a860bc0024792f8803bba8ca0d5ecd
79
- export function collapse(d: HierarchyNode<NodeWithIds>) {
80
- if (d.children) {
81
- // @ts-expect-error
82
- d._children = d.children
83
- // @ts-expect-error
84
- d.children = null
85
- }
86
- }
87
-
88
43
  export function len(a: { end: number; start: number }) {
89
44
  return a.end - a.start
90
45
  }
@@ -1,125 +1,17 @@
1
- /**
2
- * Copy text to clipboard utility.
3
- * Uses modern Clipboard API with fallback to execCommand.
4
- */
5
-
6
- function deselectCurrent() {
7
- const selection = document.getSelection()
8
- if (!selection?.rangeCount) {
9
- return () => {}
10
- }
11
- const active = document.activeElement as HTMLElement | null
12
-
13
- const ranges: Range[] = []
14
- for (let i = 0; i < selection.rangeCount; i++) {
15
- ranges.push(selection.getRangeAt(i))
16
- }
17
-
18
- const tagName = active?.tagName.toUpperCase()
19
- if (tagName === 'INPUT' || tagName === 'TEXTAREA') {
20
- active?.blur()
21
- }
22
-
23
- selection.removeAllRanges()
24
- return () => {
25
- if (selection.type === 'Caret') {
26
- selection.removeAllRanges()
27
- }
28
- if (!selection.rangeCount) {
29
- for (const range of ranges) {
30
- selection.addRange(range)
31
- }
32
- }
33
- active?.focus()
34
- }
35
- }
36
-
37
- export interface CopyOptions {
38
- debug?: boolean
39
- format?: string
40
- onCopy?: (clipboardData: DataTransfer) => void
41
- }
42
-
43
- export default function copy(text: string, options?: CopyOptions): boolean {
44
- const debug = options?.debug || false
45
- let success = false
46
- let reselectPrevious: (() => void) | undefined
47
- let range: Range | undefined
48
- let selection: Selection | null = null
49
- let mark: HTMLSpanElement | undefined
50
-
51
- try {
52
- reselectPrevious = deselectCurrent()
53
- range = document.createRange()
54
- selection = document.getSelection()
55
-
56
- mark = document.createElement('span')
57
- mark.textContent = text
58
- mark.ariaHidden = 'true'
59
- mark.style.all = 'unset'
60
- mark.style.position = 'fixed'
61
- mark.style.top = '0'
62
- mark.style.clip = 'rect(0, 0, 0, 0)'
63
- mark.style.whiteSpace = 'pre'
64
- mark.style.webkitUserSelect = 'text'
65
- ;(mark.style as unknown as Record<string, string>).MozUserSelect = 'text'
66
- ;(mark.style as unknown as Record<string, string>).msUserSelect = 'text'
67
- mark.style.userSelect = 'text'
68
-
69
- mark.addEventListener('copy', e => {
70
- e.stopPropagation()
71
- if (options?.format) {
72
- e.preventDefault()
73
- if (e.clipboardData) {
74
- e.clipboardData.clearData()
75
- e.clipboardData.setData(options.format, text)
76
- }
77
- }
78
- if (options?.onCopy && e.clipboardData) {
79
- e.preventDefault()
80
- options.onCopy(e.clipboardData)
81
- }
1
+ export default function copy(text: string) {
2
+ const clip = navigator.clipboard as Clipboard | undefined
3
+ if (clip?.writeText) {
4
+ clip.writeText(text).catch((e: unknown) => {
5
+ console.error('Failed to copy to clipboard:', e)
82
6
  })
83
-
84
- document.body.append(mark)
85
- range.selectNodeContents(mark)
86
- selection?.addRange(range)
87
-
88
- const successful = document.execCommand('copy')
89
- if (!successful) {
90
- throw new Error('copy command was unsuccessful')
91
- }
92
- success = true
93
- } catch (err) {
94
- if (debug) {
95
- console.error('unable to copy using execCommand:', err)
96
- }
97
- try {
98
- const clipboardData = (window as unknown as Record<string, DataTransfer>)
99
- .clipboardData
100
- if (clipboardData) {
101
- clipboardData.setData(options?.format || 'text', text)
102
- options?.onCopy?.(clipboardData)
103
- success = true
104
- }
105
- } catch (err2) {
106
- if (debug) {
107
- console.error('unable to copy using clipboardData:', err2)
108
- }
109
- }
110
- } finally {
111
- if (selection) {
112
- if (typeof selection.removeRange === 'function' && range) {
113
- selection.removeRange(range)
114
- } else {
115
- selection.removeAllRanges()
116
- }
117
- }
118
- if (mark) {
119
- mark.remove()
120
- }
121
- reselectPrevious?.()
7
+ return
122
8
  }
123
-
124
- return success
9
+ const textarea = document.createElement('textarea')
10
+ textarea.value = text
11
+ textarea.style.position = 'fixed'
12
+ textarea.style.opacity = '0'
13
+ document.body.append(textarea)
14
+ textarea.select()
15
+ document.execCommand('copy')
16
+ textarea.remove()
125
17
  }
@@ -1,107 +1,10 @@
1
- /**
2
- * FileSaver.js
3
- * A saveAs() FileSaver implementation.
4
- *
5
- * By Eli Grey, http://eligrey.com
6
- * License: MIT
7
- * source: http://purl.eligrey.com/github/FileSaver.js
8
- *
9
- * Vendored and converted to ESM/TypeScript for pure ESM compatibility.
10
- */
11
-
12
- function click(node: HTMLAnchorElement) {
13
- try {
14
- node.dispatchEvent(new MouseEvent('click'))
15
- } catch {
16
- const evt = document.createEvent('MouseEvents')
17
- evt.initMouseEvent(
18
- 'click',
19
- true,
20
- true,
21
- window,
22
- 0,
23
- 0,
24
- 0,
25
- 80,
26
- 20,
27
- false,
28
- false,
29
- false,
30
- false,
31
- 0,
32
- null,
33
- )
34
- node.dispatchEvent(evt)
35
- }
36
- }
37
-
38
- // Detect WebView inside a native macOS app by ruling out all browsers
39
- const isMacOSWebView =
40
- typeof navigator !== 'undefined' &&
41
- navigator.userAgent.includes('Macintosh') &&
42
- navigator.userAgent.includes('AppleWebKit') &&
43
- !navigator.userAgent.includes('Safari')
44
-
45
- export function saveAs(blob: Blob | string, name?: string) {
46
- if (typeof window === 'undefined') {
47
- return
48
- }
49
-
50
- const URL = window.URL
1
+ export function saveAs(blob: Blob, name: string) {
2
+ const url = URL.createObjectURL(blob)
51
3
  const a = document.createElement('a')
52
- name = name || (blob instanceof Blob ? 'download' : 'download')
53
-
54
- // Use download attribute if available and not macOS WebView
55
- if ('download' in HTMLAnchorElement.prototype && !isMacOSWebView) {
56
- a.download = name
57
- a.rel = 'noopener'
58
-
59
- if (typeof blob === 'string') {
60
- a.href = blob
61
- click(a)
62
- } else {
63
- a.href = URL.createObjectURL(blob)
64
- setTimeout(() => {
65
- URL.revokeObjectURL(a.href)
66
- }, 40000)
67
- setTimeout(() => {
68
- click(a)
69
- }, 0)
70
- }
71
- return
72
- }
73
-
74
- // Fallback for browsers without download attribute support
75
- if (typeof blob === 'string') {
76
- window.open(blob, '_blank')
77
- return
78
- }
79
-
80
- const isSafari =
81
- /constructor/i.test(
82
- (window as unknown as { HTMLElement: unknown }).HTMLElement?.toString() ??
83
- '',
84
- ) || !!(window as unknown as { safari?: unknown }).safari
85
- const isChromeIOS = /CriOS\/[\d]+/.test(navigator.userAgent)
86
-
87
- if (
88
- (isChromeIOS || isSafari || isMacOSWebView) &&
89
- typeof FileReader !== 'undefined'
90
- ) {
91
- const reader = new FileReader()
92
- reader.onloadend = () => {
93
- let url = reader.result as string
94
- url = isChromeIOS
95
- ? url
96
- : url.replace(/^data:[^;]*;/, 'data:attachment/file;')
97
- window.open(url, '_blank')
98
- }
99
- reader.readAsDataURL(blob)
100
- } else {
101
- const url = URL.createObjectURL(blob)
102
- window.open(url, '_blank')
103
- setTimeout(() => {
104
- URL.revokeObjectURL(url)
105
- }, 40000)
106
- }
4
+ a.href = url
5
+ a.download = name
6
+ a.click()
7
+ setTimeout(() => {
8
+ URL.revokeObjectURL(url)
9
+ }, 40_000)
107
10
  }
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = '5.0.7'
1
+ export const version = '5.0.13'
@@ -1,8 +0,0 @@
1
- import React from 'react';
2
- import type { MsaViewModel } from '../../model.ts';
3
- declare const AddTrackDialog: ({ model, onClose, open, }: {
4
- model: MsaViewModel;
5
- onClose: () => void;
6
- open: boolean;
7
- }) => React.JSX.Element;
8
- export default AddTrackDialog;
@@ -1,30 +0,0 @@
1
- import React, { useState } from 'react';
2
- import { Dialog, FileSelector } from '@jbrowse/core/ui';
3
- import { Button, DialogActions, DialogContent, MenuItem, TextField, Typography, } from '@mui/material';
4
- import { observer } from 'mobx-react';
5
- const AddTrackDialog = observer(function ({ model, onClose, open, }) {
6
- const options = model.rows.map(r => r[0]);
7
- const [trackFile, setTrackFile] = useState();
8
- const [currentOption, setCurrentOption] = useState('');
9
- return (React.createElement(Dialog, { onClose: () => {
10
- onClose();
11
- }, open: open, title: "Add track" },
12
- React.createElement(DialogContent, null,
13
- React.createElement(Typography, null, "Open relevant per-alignment tracks e.g. protein domains"),
14
- React.createElement(TextField, { select: true, helperText: "Which row does this track apply to?", value: currentOption, onChange: event => {
15
- setCurrentOption(event.target.value);
16
- } }, options.map((option, index) => (React.createElement(MenuItem, { key: `${option}-${index}`, value: option }, option)))),
17
- React.createElement(FileSelector, { location: trackFile, setLocation: setTrackFile }),
18
- React.createElement(DialogActions, null,
19
- React.createElement(Button, { onClick: () => {
20
- model.setError(undefined);
21
- if (trackFile) {
22
- model.setMSAFilehandle(trackFile);
23
- }
24
- }, variant: "contained", color: "primary" }, "Open"),
25
- React.createElement(Button, { color: "secondary", variant: "contained", onClick: () => {
26
- onClose();
27
- } }, "Cancel")))));
28
- });
29
- export default AddTrackDialog;
30
- //# sourceMappingURL=AddTrackDialog.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AddTrackDialog.js","sourceRoot":"","sources":["../../../src/components/dialogs/AddTrackDialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAEvC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,EACL,MAAM,EACN,aAAa,EACb,aAAa,EACb,QAAQ,EACR,SAAS,EACT,UAAU,GACX,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAKrC,MAAM,cAAc,GAAG,QAAQ,CAAC,UAAU,EACxC,KAAK,EACL,OAAO,EACP,IAAI,GAKL;IACC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IACzC,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,EAAgB,CAAA;IAC1D,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAA;IAEtD,OAAO,CACL,oBAAC,MAAM,IACL,OAAO,EAAE,GAAG,EAAE;YACZ,OAAO,EAAE,CAAA;QACX,CAAC,EACD,IAAI,EAAE,IAAI,EACV,KAAK,EAAC,WAAW;QAEjB,oBAAC,aAAa;YACZ,oBAAC,UAAU,kEAEE;YACb,oBAAC,SAAS,IACR,MAAM,QACN,UAAU,EAAC,qCAAqC,EAChD,KAAK,EAAE,aAAa,EACpB,QAAQ,EAAE,KAAK,CAAC,EAAE;oBAChB,gBAAgB,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;gBACtC,CAAC,IAEA,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAC9B,oBAAC,QAAQ,IAAC,GAAG,EAAE,GAAG,MAAM,IAAI,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,IAC/C,MAAM,CACE,CACZ,CAAC,CACQ;YACZ,oBAAC,YAAY,IAAC,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,GAAI;YAChE,oBAAC,aAAa;gBACZ,oBAAC,MAAM,IACL,OAAO,EAAE,GAAG,EAAE;wBACZ,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAA;wBACzB,IAAI,SAAS,EAAE,CAAC;4BACd,KAAK,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAA;wBACnC,CAAC;oBACH,CAAC,EACD,OAAO,EAAC,WAAW,EACnB,KAAK,EAAC,SAAS,WAGR;gBACT,oBAAC,MAAM,IACL,KAAK,EAAC,WAAW,EACjB,OAAO,EAAC,WAAW,EACnB,OAAO,EAAE,GAAG,EAAE;wBACZ,OAAO,EAAE,CAAA;oBACX,CAAC,aAGM,CACK,CACF,CACT,CACV,CAAA;AACH,CAAC,CAAC,CAAA;AAEF,eAAe,cAAc,CAAA"}
@@ -1,6 +0,0 @@
1
- import React from 'react';
2
- export default function TabPanel({ children, value, index, ...other }: {
3
- children?: React.ReactNode;
4
- index: number;
5
- value: number;
6
- }): React.JSX.Element;
@@ -1,6 +0,0 @@
1
- import React from 'react';
2
- // this is from MUI example
3
- export default function TabPanel({ children, value, index, ...other }) {
4
- return (React.createElement("div", { role: "tabpanel", hidden: value !== index, ...other }, value === index && React.createElement("div", null, children)));
5
- }
6
- //# sourceMappingURL=TabPanel.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"TabPanel.js","sourceRoot":"","sources":["../../../src/components/dialogs/TabPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,2BAA2B;AAC3B,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,EAC/B,QAAQ,EACR,KAAK,EACL,KAAK,EACL,GAAG,KAAK,EAKT;IACC,OAAO,CACL,6BAAK,IAAI,EAAC,UAAU,EAAC,MAAM,EAAE,KAAK,KAAK,KAAK,KAAM,KAAK,IACpD,KAAK,KAAK,KAAK,IAAI,iCAAM,QAAQ,CAAO,CACrC,CACP,CAAA;AACH,CAAC"}
@@ -1,40 +0,0 @@
1
- import React from 'react';
2
- import RestartAlt from '@mui/icons-material/RestartAlt';
3
- import { IconButton } from '@mui/material';
4
- import { observer } from 'mobx-react';
5
- import { makeStyles } from 'tss-react/mui';
6
- const useStyles = makeStyles()(theme => ({
7
- dpad: {
8
- display: 'grid',
9
- gridTemplateColumns: 'repeat(3, 1fr)',
10
- },
11
- icon: {
12
- padding: theme.spacing(0.5),
13
- },
14
- }));
15
- const ZoomStar = observer(function ({ model }) {
16
- const { classes } = useStyles();
17
- return (React.createElement("div", { className: classes.dpad },
18
- React.createElement("div", null),
19
- React.createElement(IconButton, { className: classes.icon, onClick: () => {
20
- model.zoomInVertical();
21
- } }, "Y+"),
22
- React.createElement("div", null),
23
- React.createElement(IconButton, { className: classes.icon, onClick: () => {
24
- model.zoomOutHorizontal();
25
- } }, "X-"),
26
- React.createElement(IconButton, { className: classes.icon, onClick: () => {
27
- model.resetZoom();
28
- } },
29
- React.createElement(RestartAlt, null)),
30
- React.createElement(IconButton, { className: classes.icon, onClick: () => {
31
- model.zoomInHorizontal();
32
- } }, "X+"),
33
- React.createElement("div", null),
34
- React.createElement(IconButton, { className: classes.icon, onClick: () => {
35
- model.zoomOutVertical();
36
- } }, "Y-"),
37
- React.createElement("div", null)));
38
- });
39
- export default ZoomStar;
40
- //# sourceMappingURL=ZoomStar.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ZoomStar.js","sourceRoot":"","sources":["../../../src/components/header/ZoomStar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,UAAU,MAAM,gCAAgC,CAAA;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAI1C,MAAM,SAAS,GAAG,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACvC,IAAI,EAAE;QACJ,OAAO,EAAE,MAAM;QACf,mBAAmB,EAAE,gBAAgB;KACtC;IACD,IAAI,EAAE;QACJ,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;KAC5B;CACF,CAAC,CAAC,CAAA;AAEH,MAAM,QAAQ,GAAG,QAAQ,CAAC,UAAU,EAAE,KAAK,EAA2B;IACpE,MAAM,EAAE,OAAO,EAAE,GAAG,SAAS,EAAE,CAAA;IAC/B,OAAO,CACL,6BAAK,SAAS,EAAE,OAAO,CAAC,IAAI;QAC1B,gCAAO;QACP,oBAAC,UAAU,IACT,SAAS,EAAE,OAAO,CAAC,IAAI,EACvB,OAAO,EAAE,GAAG,EAAE;gBACZ,KAAK,CAAC,cAAc,EAAE,CAAA;YACxB,CAAC,SAGU;QACb,gCAAO;QAEP,oBAAC,UAAU,IACT,SAAS,EAAE,OAAO,CAAC,IAAI,EACvB,OAAO,EAAE,GAAG,EAAE;gBACZ,KAAK,CAAC,iBAAiB,EAAE,CAAA;YAC3B,CAAC,SAGU;QACb,oBAAC,UAAU,IACT,SAAS,EAAE,OAAO,CAAC,IAAI,EACvB,OAAO,EAAE,GAAG,EAAE;gBACZ,KAAK,CAAC,SAAS,EAAE,CAAA;YACnB,CAAC;YAED,oBAAC,UAAU,OAAG,CACH;QACb,oBAAC,UAAU,IACT,SAAS,EAAE,OAAO,CAAC,IAAI,EACvB,OAAO,EAAE,GAAG,EAAE;gBACZ,KAAK,CAAC,gBAAgB,EAAE,CAAA;YAC1B,CAAC,SAGU;QAEb,gCAAO;QACP,oBAAC,UAAU,IACT,SAAS,EAAE,OAAO,CAAC,IAAI,EACvB,OAAO,EAAE,GAAG,EAAE;gBACZ,KAAK,CAAC,eAAe,EAAE,CAAA;YACzB,CAAC,SAGU;QACb,gCAAO,CACH,CACP,CAAA;AACH,CAAC,CAAC,CAAA;AAEF,eAAe,QAAQ,CAAA"}
package/dist/layout.d.ts DELETED
@@ -1,26 +0,0 @@
1
- export default class Layout {
2
- rectangles: Map<string, {
3
- minY: number;
4
- maxY: number;
5
- minX: number;
6
- maxX: number;
7
- id: string;
8
- data: unknown;
9
- }>;
10
- maxHeightReached: boolean;
11
- private maxHeight;
12
- private flatbush;
13
- private indexToId;
14
- private pTotalHeight;
15
- constructor({ maxHeight, }?: {
16
- maxHeight?: number;
17
- });
18
- private rebuildIndex;
19
- private collides;
20
- /**
21
- * @returns top position for the rect, or Null if laying
22
- * out the rect would exceed maxHeighe
23
- */
24
- addRect(id: string, left: number, right: number, height: number, data: unknown): number | null;
25
- get totalHeight(): number;
26
- }
package/dist/layout.js DELETED
@@ -1,74 +0,0 @@
1
- import Flatbush from 'flatbush';
2
- export default class Layout {
3
- rectangles;
4
- maxHeightReached = false;
5
- maxHeight;
6
- flatbush = null;
7
- indexToId = [];
8
- pTotalHeight;
9
- constructor({ maxHeight = 10000, } = {}) {
10
- this.rectangles = new Map();
11
- this.maxHeight = Math.ceil(maxHeight);
12
- this.pTotalHeight = 0; // total height, in units of bitmap squares (px/pitchY)
13
- }
14
- rebuildIndex() {
15
- // Rebuild the spatial index with current rectangles
16
- const rects = Array.from(this.rectangles.values());
17
- if (rects.length === 0) {
18
- this.flatbush = null;
19
- this.indexToId = [];
20
- return;
21
- }
22
- this.flatbush = new Flatbush(rects.length);
23
- this.indexToId = [];
24
- for (const rect of rects) {
25
- this.flatbush.add(rect.minX, rect.minY, rect.maxX, rect.maxY);
26
- this.indexToId.push(rect.id);
27
- }
28
- this.flatbush.finish();
29
- }
30
- collides(box) {
31
- if (!this.flatbush) {
32
- return false;
33
- }
34
- const results = this.flatbush.search(box.minX, box.minY, box.maxX, box.maxY);
35
- return results.length > 0;
36
- }
37
- /**
38
- * @returns top position for the rect, or Null if laying
39
- * out the rect would exceed maxHeighe
40
- */
41
- addRect(id, left, right, height, data) {
42
- // add to flatbush
43
- const existingRecord = this.rectangles.get(id);
44
- if (existingRecord) {
45
- return existingRecord.minY;
46
- }
47
- let currHeight = 0;
48
- while (this.collides({
49
- minX: left,
50
- minY: currHeight,
51
- maxX: right,
52
- maxY: currHeight + height,
53
- }) &&
54
- currHeight <= this.maxHeight) {
55
- currHeight += 1;
56
- }
57
- const record = {
58
- minX: left,
59
- minY: currHeight,
60
- maxX: right,
61
- maxY: currHeight + height,
62
- id,
63
- data,
64
- };
65
- this.rectangles.set(id, record);
66
- this.rebuildIndex();
67
- this.pTotalHeight = Math.max(this.pTotalHeight, currHeight);
68
- return currHeight;
69
- }
70
- get totalHeight() {
71
- return this.pTotalHeight;
72
- }
73
- }
74
- //# sourceMappingURL=layout.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"layout.js","sourceRoot":"","sources":["../src/layout.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import type { NodeWithIds } from './types.ts';
2
- export declare function reparseTree(tree: NodeWithIds): NodeWithIds;