react-msaview 5.0.6 → 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 (190) hide show
  1. package/bundle/index.js +106 -106
  2. package/bundle/index.js.LICENSE.txt +1 -1
  3. package/bundle/index.js.map +1 -1
  4. package/dist/components/Checkbox2.js +3 -6
  5. package/dist/components/Checkbox2.js.map +1 -1
  6. package/dist/components/MSAViewer.d.ts +14 -0
  7. package/dist/components/MSAViewer.js +34 -0
  8. package/dist/components/MSAViewer.js.map +1 -0
  9. package/dist/components/Track.d.ts +0 -4
  10. package/dist/components/Track.js +6 -26
  11. package/dist/components/Track.js.map +1 -1
  12. package/dist/components/dialogs/DomainDialog.js +2 -5
  13. package/dist/components/dialogs/DomainDialog.js.map +1 -1
  14. package/dist/components/dialogs/InterProScanDialog.js +7 -7
  15. package/dist/components/dialogs/InterProScanDialog.js.map +1 -1
  16. package/dist/components/dialogs/SettingsDialog.js +3 -19
  17. package/dist/components/dialogs/SettingsDialog.js.map +1 -1
  18. package/dist/components/header/ColorSchemeMenu.d.ts +6 -0
  19. package/dist/components/header/ColorSchemeMenu.js +19 -0
  20. package/dist/components/header/ColorSchemeMenu.js.map +1 -0
  21. package/dist/components/header/{ZoomStar.d.ts → FileMenu.d.ts} +2 -2
  22. package/dist/components/header/FileMenu.js +71 -0
  23. package/dist/components/header/FileMenu.js.map +1 -0
  24. package/dist/components/header/Header.js +8 -6
  25. package/dist/components/header/Header.js.map +1 -1
  26. package/dist/components/header/HeaderMenu.js +3 -145
  27. package/dist/components/header/HeaderMenu.js.map +1 -1
  28. package/dist/components/header/MSASettingsMenu.d.ts +6 -0
  29. package/dist/components/header/MSASettingsMenu.js +36 -0
  30. package/dist/components/header/MSASettingsMenu.js.map +1 -0
  31. package/dist/components/header/SettingsMenu.js +1 -21
  32. package/dist/components/header/SettingsMenu.js.map +1 -1
  33. package/dist/components/header/TreeSettingsMenu.d.ts +6 -0
  34. package/dist/components/header/TreeSettingsMenu.js +74 -0
  35. package/dist/components/header/TreeSettingsMenu.js.map +1 -0
  36. package/dist/components/header/ZoomMenu.js +0 -8
  37. package/dist/components/header/ZoomMenu.js.map +1 -1
  38. package/dist/components/header/getDomainsMenu.d.ts +31 -0
  39. package/dist/components/header/getDomainsMenu.js +75 -0
  40. package/dist/components/header/getDomainsMenu.js.map +1 -0
  41. package/dist/components/import/ImportFormExamples.js +21 -19
  42. package/dist/components/import/ImportFormExamples.js.map +1 -1
  43. package/dist/components/msa/MSACanvas.js +13 -89
  44. package/dist/components/msa/MSACanvas.js.map +1 -1
  45. package/dist/components/msa/MSACanvasBlock.js +1 -3
  46. package/dist/components/msa/MSACanvasBlock.js.map +1 -1
  47. package/dist/components/msa/renderMSABlock.js +2 -4
  48. package/dist/components/msa/renderMSABlock.js.map +1 -1
  49. package/dist/components/msa/renderMSAMouseover.js +1 -7
  50. package/dist/components/msa/renderMSAMouseover.js.map +1 -1
  51. package/dist/components/tree/TreeCanvas.js +18 -101
  52. package/dist/components/tree/TreeCanvas.js.map +1 -1
  53. package/dist/components/tree/TreeCanvasBlock.js +33 -1
  54. package/dist/components/tree/TreeCanvasBlock.js.map +1 -1
  55. package/dist/components/tree/TreeNodeMenu.js +5 -16
  56. package/dist/components/tree/TreeNodeMenu.js.map +1 -1
  57. package/dist/components/tree/renderTreeCanvas.js +4 -12
  58. package/dist/components/tree/renderTreeCanvas.js.map +1 -1
  59. package/dist/constants.d.ts +0 -2
  60. package/dist/constants.js +0 -2
  61. package/dist/constants.js.map +1 -1
  62. package/dist/fetchUtils.d.ts +0 -1
  63. package/dist/fetchUtils.js +0 -4
  64. package/dist/fetchUtils.js.map +1 -1
  65. package/dist/flatToTree.d.ts +0 -5
  66. package/dist/flatToTree.js +13 -30
  67. package/dist/flatToTree.js.map +1 -1
  68. package/dist/hierarchy.d.ts +28 -0
  69. package/dist/hierarchy.js +164 -0
  70. package/dist/hierarchy.js.map +1 -0
  71. package/dist/index.d.ts +2 -0
  72. package/dist/index.js +1 -0
  73. package/dist/index.js.map +1 -1
  74. package/dist/launchInterProScan.d.ts +0 -5
  75. package/dist/launchInterProScan.js +5 -3
  76. package/dist/launchInterProScan.js.map +1 -1
  77. package/dist/model/DataModel.d.ts +9 -0
  78. package/dist/model/DataModel.js +12 -1
  79. package/dist/model/DataModel.js.map +1 -1
  80. package/dist/model/msaModel.d.ts +3 -0
  81. package/dist/model/msaModel.js +0 -1
  82. package/dist/model/msaModel.js.map +1 -1
  83. package/dist/model/treeModel.d.ts +3 -6
  84. package/dist/model/treeModel.js +3 -15
  85. package/dist/model/treeModel.js.map +1 -1
  86. package/dist/model.d.ts +34 -77
  87. package/dist/model.js +140 -239
  88. package/dist/model.js.map +1 -1
  89. package/dist/neighborJoining.js +40 -633
  90. package/dist/neighborJoining.js.map +1 -1
  91. package/dist/parseAsn1.d.ts +0 -12
  92. package/dist/parseAsn1.js +125 -332
  93. package/dist/parseAsn1.js.map +1 -1
  94. package/dist/useWheelScroll.d.ts +8 -0
  95. package/dist/useWheelScroll.js +93 -0
  96. package/dist/useWheelScroll.js.map +1 -0
  97. package/dist/util.d.ts +1 -6
  98. package/dist/util.js +5 -34
  99. package/dist/util.js.map +1 -1
  100. package/dist/vendor/copyToClipboard.d.ts +1 -10
  101. package/dist/vendor/copyToClipboard.js +14 -109
  102. package/dist/vendor/copyToClipboard.js.map +1 -1
  103. package/dist/vendor/fileSaver.d.ts +1 -11
  104. package/dist/vendor/fileSaver.js +7 -76
  105. package/dist/vendor/fileSaver.js.map +1 -1
  106. package/dist/version.d.ts +1 -1
  107. package/dist/version.js +1 -1
  108. package/dist/version.js.map +1 -1
  109. package/package.json +14 -14
  110. package/src/collapseLogic.test.ts +115 -0
  111. package/src/components/Checkbox2.tsx +9 -18
  112. package/src/components/MSAViewer.tsx +67 -0
  113. package/src/components/Track.tsx +11 -30
  114. package/src/components/dialogs/DomainDialog.tsx +4 -5
  115. package/src/components/dialogs/InterProScanDialog.tsx +7 -7
  116. package/src/components/dialogs/SettingsDialog.tsx +0 -37
  117. package/src/components/header/ColorSchemeMenu.tsx +35 -0
  118. package/src/components/header/FileMenu.tsx +84 -0
  119. package/src/components/header/Header.tsx +8 -6
  120. package/src/components/header/HeaderMenu.tsx +4 -155
  121. package/src/components/header/MSASettingsMenu.tsx +48 -0
  122. package/src/components/header/SettingsMenu.tsx +0 -23
  123. package/src/components/header/TreeSettingsMenu.tsx +96 -0
  124. package/src/components/header/ZoomMenu.tsx +0 -8
  125. package/src/components/header/getDomainsMenu.ts +83 -0
  126. package/src/components/import/ImportFormExamples.tsx +37 -34
  127. package/src/components/msa/MSACanvas.tsx +21 -97
  128. package/src/components/msa/MSACanvasBlock.tsx +1 -3
  129. package/src/components/msa/renderBoxFeatureCanvasBlock.ts +1 -1
  130. package/src/components/msa/renderMSABlock.ts +2 -5
  131. package/src/components/msa/renderMSAMouseover.ts +0 -6
  132. package/src/components/tree/TreeCanvas.tsx +48 -111
  133. package/src/components/tree/TreeCanvasBlock.tsx +44 -0
  134. package/src/components/tree/TreeNodeMenu.tsx +5 -14
  135. package/src/components/tree/renderTreeCanvas.ts +8 -21
  136. package/src/constants.ts +0 -2
  137. package/src/fetchUtils.ts +0 -5
  138. package/src/flatToTree.ts +20 -38
  139. package/src/hierarchy.test.ts +120 -0
  140. package/src/hierarchy.ts +220 -0
  141. package/src/index.ts +2 -0
  142. package/src/launchInterProScan.ts +4 -3
  143. package/src/model/DataModel.ts +12 -1
  144. package/src/model/msaModel.ts +0 -2
  145. package/src/model/treeModel.ts +2 -18
  146. package/src/model.ts +203 -278
  147. package/src/neighborJoining.test.ts +15 -7
  148. package/src/neighborJoining.ts +40 -632
  149. package/src/parseAsn1.test.ts +5 -2
  150. package/src/parseAsn1.ts +135 -405
  151. package/src/useWheelScroll.ts +109 -0
  152. package/src/util.ts +5 -50
  153. package/src/vendor/copyToClipboard.ts +14 -122
  154. package/src/vendor/fileSaver.ts +8 -105
  155. package/src/version.ts +1 -1
  156. package/dist/components/dialogs/AddTrackDialog.d.ts +0 -8
  157. package/dist/components/dialogs/AddTrackDialog.js +0 -30
  158. package/dist/components/dialogs/AddTrackDialog.js.map +0 -1
  159. package/dist/components/dialogs/TabPanel.d.ts +0 -6
  160. package/dist/components/dialogs/TabPanel.js +0 -6
  161. package/dist/components/dialogs/TabPanel.js.map +0 -1
  162. package/dist/components/header/ZoomStar.js +0 -40
  163. package/dist/components/header/ZoomStar.js.map +0 -1
  164. package/dist/createPaletteMap.test.d.ts +0 -1
  165. package/dist/createPaletteMap.test.js +0 -49
  166. package/dist/createPaletteMap.test.js.map +0 -1
  167. package/dist/layout.d.ts +0 -26
  168. package/dist/layout.js +0 -74
  169. package/dist/layout.js.map +0 -1
  170. package/dist/neighborJoining.test.d.ts +0 -1
  171. package/dist/neighborJoining.test.js +0 -110
  172. package/dist/neighborJoining.test.js.map +0 -1
  173. package/dist/parseAsn1.test.d.ts +0 -1
  174. package/dist/parseAsn1.test.js +0 -8
  175. package/dist/parseAsn1.test.js.map +0 -1
  176. package/dist/reparseTree.d.ts +0 -2
  177. package/dist/reparseTree.js +0 -15
  178. package/dist/reparseTree.js.map +0 -1
  179. package/dist/rowCoordinateCalculations.test.d.ts +0 -1
  180. package/dist/rowCoordinateCalculations.test.js +0 -224
  181. package/dist/rowCoordinateCalculations.test.js.map +0 -1
  182. package/dist/seqPosToGlobalCol.test.d.ts +0 -1
  183. package/dist/seqPosToGlobalCol.test.js +0 -60
  184. package/dist/seqPosToGlobalCol.test.js.map +0 -1
  185. package/src/components/dialogs/AddTrackDialog.tsx +0 -85
  186. package/src/components/dialogs/TabPanel.tsx +0 -19
  187. package/src/components/header/ZoomStar.tsx +0 -74
  188. package/src/createPaletteMap.test.ts +0 -57
  189. package/src/layout.ts +0 -118
  190. 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.6'
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"}
@@ -1 +0,0 @@
1
- export {};
@@ -1,49 +0,0 @@
1
- import { expect, test } from 'vitest';
2
- import { createPaletteMap } from "./createPaletteMap.js";
3
- import palettes from "./ggplotPalettes.js";
4
- // Original implementation for comparison
5
- function originalFillPalette(keys) {
6
- let i = 0;
7
- const map = {};
8
- for (const key of keys) {
9
- const k = Math.min(keys.length - 1, palettes.length - 1);
10
- map[key] = palettes[k][i];
11
- i++;
12
- }
13
- return map;
14
- }
15
- test('createPaletteMap matches original implementation with 1 key', () => {
16
- const keys = ['IPR001234'];
17
- expect(createPaletteMap(keys)).toEqual(originalFillPalette(keys));
18
- });
19
- test('createPaletteMap matches original implementation with 3 keys', () => {
20
- const keys = ['IPR001234', 'IPR005678', 'IPR009012'];
21
- expect(createPaletteMap(keys)).toEqual(originalFillPalette(keys));
22
- });
23
- test('createPaletteMap matches original implementation with 8 keys (max palette size)', () => {
24
- const keys = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'];
25
- expect(createPaletteMap(keys)).toEqual(originalFillPalette(keys));
26
- });
27
- test('createPaletteMap matches original implementation with more keys than palette colors', () => {
28
- const keys = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'];
29
- expect(createPaletteMap(keys)).toEqual(originalFillPalette(keys));
30
- });
31
- test('createPaletteMap returns correct colors for 3 keys', () => {
32
- const keys = ['X', 'Y', 'Z'];
33
- const result = createPaletteMap(keys);
34
- // With 3 keys, uses palette index 2 (0-indexed)
35
- expect(result).toEqual({
36
- X: '#F8766D',
37
- Y: '#00BA38',
38
- Z: '#619CFF',
39
- });
40
- });
41
- test('createPaletteMap returns empty object for empty keys', () => {
42
- expect(createPaletteMap([])).toEqual({});
43
- });
44
- test('createPaletteMap preserves key order', () => {
45
- const keys = ['Z', 'A', 'M'];
46
- const result = createPaletteMap(keys);
47
- expect(Object.keys(result)).toEqual(['Z', 'A', 'M']);
48
- });
49
- //# sourceMappingURL=createPaletteMap.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"createPaletteMap.test.js","sourceRoot":"","sources":["../src/createPaletteMap.test.ts"],"names":[],"mappings":"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"}
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
- }