react-msaview 5.1.1 → 5.2.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 (100) hide show
  1. package/bundle/index.js +2 -2
  2. package/bundle/index.js.map +1 -1
  3. package/dist/calculateBlocks.d.ts +4 -10
  4. package/dist/calculateBlocks.js +12 -20
  5. package/dist/calculateBlocks.js.map +1 -1
  6. package/dist/components/ConservationTrack.js +18 -24
  7. package/dist/components/ConservationTrack.js.map +1 -1
  8. package/dist/components/TextTrack.js +24 -34
  9. package/dist/components/TextTrack.js.map +1 -1
  10. package/dist/components/dialogs/ExportSVGDialog.js +20 -20
  11. package/dist/components/dialogs/ExportSVGDialog.js.map +1 -1
  12. package/dist/components/dialogs/InterProScanDialog.js +6 -1
  13. package/dist/components/dialogs/InterProScanDialog.js.map +1 -1
  14. package/dist/components/header/FileMenu.js +2 -1
  15. package/dist/components/header/FileMenu.js.map +1 -1
  16. package/dist/components/header/Header.js +1 -1
  17. package/dist/components/header/settingsMenuItems.js +24 -8
  18. package/dist/components/header/settingsMenuItems.js.map +1 -1
  19. package/dist/components/minimap/Minimap.js +1 -6
  20. package/dist/components/minimap/Minimap.js.map +1 -1
  21. package/dist/components/minimap/MinimapSVG.js +4 -8
  22. package/dist/components/minimap/MinimapSVG.js.map +1 -1
  23. package/dist/components/msa/getVisibleLeaves.d.ts +6 -0
  24. package/dist/components/msa/getVisibleLeaves.js +9 -0
  25. package/dist/components/msa/getVisibleLeaves.js.map +1 -0
  26. package/dist/components/msa/renderBoxFeatureCanvasBlock.d.ts +2 -1
  27. package/dist/components/msa/renderBoxFeatureCanvasBlock.js +5 -6
  28. package/dist/components/msa/renderBoxFeatureCanvasBlock.js.map +1 -1
  29. package/dist/components/msa/renderMSABlock.d.ts +2 -1
  30. package/dist/components/msa/renderMSABlock.js +98 -84
  31. package/dist/components/msa/renderMSABlock.js.map +1 -1
  32. package/dist/components/msa/renderMSAMouseover.js +3 -3
  33. package/dist/components/msa/renderMSAMouseover.js.map +1 -1
  34. package/dist/components/msa/visibleColRange.d.ts +8 -0
  35. package/dist/components/msa/visibleColRange.js +10 -0
  36. package/dist/components/msa/visibleColRange.js.map +1 -0
  37. package/dist/components/renderCtx.d.ts +7 -0
  38. package/dist/components/renderCtx.js +2 -0
  39. package/dist/components/renderCtx.js.map +1 -0
  40. package/dist/components/tracks/renderTracksSvg.d.ts +6 -5
  41. package/dist/components/tracks/renderTracksSvg.js +11 -4
  42. package/dist/components/tracks/renderTracksSvg.js.map +1 -1
  43. package/dist/components/tree/TreeCanvas.js.map +1 -1
  44. package/dist/components/tree/TreeCanvasBlock.js +2 -10
  45. package/dist/components/tree/TreeCanvasBlock.js.map +1 -1
  46. package/dist/components/tree/renderTreeCanvas.d.ts +5 -4
  47. package/dist/components/tree/renderTreeCanvas.js +16 -24
  48. package/dist/components/tree/renderTreeCanvas.js.map +1 -1
  49. package/dist/components/util.d.ts +0 -14
  50. package/dist/components/util.js +0 -58
  51. package/dist/components/util.js.map +1 -1
  52. package/dist/hierarchy.d.ts +2 -0
  53. package/dist/hierarchy.js +19 -0
  54. package/dist/hierarchy.js.map +1 -1
  55. package/dist/index.js +7 -0
  56. package/dist/index.js.map +1 -1
  57. package/dist/model.d.ts +26 -30
  58. package/dist/model.js +74 -82
  59. package/dist/model.js.map +1 -1
  60. package/dist/renderToSvg.d.ts +1 -1
  61. package/dist/renderToSvg.js +20 -26
  62. package/dist/renderToSvg.js.map +1 -1
  63. package/dist/rowCoordinateCalculations.d.ts +0 -9
  64. package/dist/rowCoordinateCalculations.js +0 -20
  65. package/dist/rowCoordinateCalculations.js.map +1 -1
  66. package/dist/util.d.ts +1 -0
  67. package/dist/util.js +23 -1
  68. package/dist/util.js.map +1 -1
  69. package/dist/version.d.ts +1 -1
  70. package/dist/version.js +1 -1
  71. package/package.json +3 -3
  72. package/src/calculateBlocks.ts +18 -51
  73. package/src/components/ConservationTrack.tsx +18 -27
  74. package/src/components/TextTrack.tsx +30 -38
  75. package/src/components/dialogs/ExportSVGDialog.tsx +27 -17
  76. package/src/components/dialogs/InterProScanDialog.tsx +6 -1
  77. package/src/components/header/FileMenu.tsx +2 -1
  78. package/src/components/header/Header.tsx +1 -1
  79. package/src/components/header/settingsMenuItems.ts +24 -8
  80. package/src/components/minimap/Minimap.tsx +1 -6
  81. package/src/components/minimap/MinimapSVG.tsx +4 -8
  82. package/src/components/msa/getVisibleLeaves.ts +21 -0
  83. package/src/components/msa/renderBoxFeatureCanvasBlock.ts +9 -9
  84. package/src/components/msa/renderMSABlock.ts +119 -118
  85. package/src/components/msa/renderMSAMouseover.ts +2 -3
  86. package/src/components/msa/visibleColRange.ts +17 -0
  87. package/src/components/renderCtx.ts +29 -0
  88. package/src/components/tracks/renderTracksSvg.ts +18 -9
  89. package/src/components/tree/TreeCanvas.tsx +3 -1
  90. package/src/components/tree/TreeCanvasBlock.tsx +2 -12
  91. package/src/components/tree/renderTreeCanvas.ts +25 -28
  92. package/src/components/util.ts +0 -81
  93. package/src/hierarchy.ts +27 -0
  94. package/src/index.ts +7 -0
  95. package/src/model.ts +81 -98
  96. package/src/renderToSvg.tsx +23 -31
  97. package/src/rowCoordinateCalculations.test.ts +0 -51
  98. package/src/rowCoordinateCalculations.ts +0 -23
  99. package/src/util.ts +25 -1
  100. package/src/version.ts +1 -1
@@ -19,7 +19,7 @@ export interface ExportSvgOptions {
19
19
  theme: Theme
20
20
  includeMinimap?: boolean
21
21
  includeTracks?: boolean
22
- exportType: string
22
+ exportType: 'entire' | 'viewport'
23
23
  }
24
24
  export async function renderToSvg(model: MsaViewModel, opts: ExportSvgOptions) {
25
25
  await when(() => !!model.dataInitialized)
@@ -41,21 +41,18 @@ export async function renderToSvg(model: MsaViewModel, opts: ExportSvgOptions) {
41
41
  includeTracks,
42
42
  })
43
43
  }
44
- if (exportType === 'viewport') {
45
- return render({
46
- width,
47
- height: height + (includeMinimap ? model.minimapHeight : 0) + trackHeight,
48
- contentHeight: height,
49
- trackHeight,
50
- theme,
51
- model,
52
- offsetY: -scrollY,
53
- offsetX: -scrollX,
54
- includeMinimap,
55
- includeTracks,
56
- })
57
- }
58
- throw new Error('unknown export type')
44
+ return render({
45
+ width,
46
+ height: height + (includeMinimap ? model.minimapHeight : 0) + trackHeight,
47
+ contentHeight: height,
48
+ trackHeight,
49
+ theme,
50
+ model,
51
+ offsetY: -scrollY,
52
+ offsetX: -scrollX,
53
+ includeMinimap,
54
+ includeTracks,
55
+ })
59
56
  }
60
57
 
61
58
  async function render({
@@ -93,7 +90,7 @@ async function render({
93
90
  model={model}
94
91
  theme={theme}
95
92
  offsetX={offsetX}
96
- width={width}
93
+ msaAreaWidth={width - model.treeAreaWidth}
97
94
  trackHeight={trackHeight}
98
95
  />
99
96
  ) : null}
@@ -108,7 +105,7 @@ async function render({
108
105
  theme={theme}
109
106
  offsetX={offsetX}
110
107
  offsetY={offsetY}
111
- width={width}
108
+ msaAreaWidth={width - model.treeAreaWidth}
112
109
  contentHeight={contentHeight}
113
110
  />
114
111
  </g>
@@ -120,7 +117,7 @@ async function render({
120
117
  function CoreRendering({
121
118
  model,
122
119
  theme,
123
- width,
120
+ msaAreaWidth,
124
121
  contentHeight,
125
122
  offsetX,
126
123
  offsetY,
@@ -128,7 +125,7 @@ function CoreRendering({
128
125
  }: {
129
126
  model: MsaViewModel
130
127
  theme: Theme
131
- width: number
128
+ msaAreaWidth: number
132
129
  contentHeight: number
133
130
  offsetX: number
134
131
  offsetY: number
@@ -139,9 +136,8 @@ function CoreRendering({
139
136
  const clipId2 = `msa-${id}`
140
137
  const contrastScheme = colorContrast(colorScheme, theme)
141
138
 
142
- const ctx1 = new Context(width, contentHeight) as any
143
-
144
- const ctx2 = new Context(width, contentHeight) as any
139
+ const ctx1 = new Context(treeAreaWidth, contentHeight)
140
+ const ctx2 = new Context(msaAreaWidth, contentHeight)
145
141
  renderBoxFeatureCanvasBlock({
146
142
  ctx: ctx2,
147
143
  offsetX,
@@ -150,7 +146,6 @@ function CoreRendering({
150
146
  blockSizeYOverride: contentHeight,
151
147
  highResScaleFactorOverride: 1,
152
148
  })
153
- const msaAreaWidth = width - treeAreaWidth
154
149
  renderTreeCanvas({
155
150
  model,
156
151
  offsetY,
@@ -176,8 +171,6 @@ function CoreRendering({
176
171
  <clipPath id={clipId1}>
177
172
  <rect x={0} y={0} width={treeAreaWidth} height={contentHeight} />
178
173
  </clipPath>
179
- </defs>
180
- <defs>
181
174
  <clipPath id={clipId2}>
182
175
  <rect x={0} y={0} width={msaAreaWidth} height={contentHeight} />
183
176
  </clipPath>
@@ -199,14 +192,14 @@ function CoreRendering({
199
192
  function TrackRendering({
200
193
  model,
201
194
  theme,
202
- width,
195
+ msaAreaWidth,
203
196
  trackHeight,
204
197
  offsetX,
205
198
  Context,
206
199
  }: {
207
200
  model: MsaViewModel
208
201
  theme: Theme
209
- width: number
202
+ msaAreaWidth: number
210
203
  trackHeight: number
211
204
  offsetX: number
212
205
  Context: typeof ContextType
@@ -214,9 +207,8 @@ function TrackRendering({
214
207
  const { treeAreaWidth, colorScheme, id } = model
215
208
  const clipId = `tracks-${id}`
216
209
  const contrastScheme = colorContrast(colorScheme, theme)
217
- const msaAreaWidth = width - treeAreaWidth
218
210
 
219
- const ctx = new Context(msaAreaWidth, trackHeight) as any
211
+ const ctx = new Context(msaAreaWidth, trackHeight)
220
212
 
221
213
  renderAllTracks({
222
214
  model,
@@ -277,7 +269,7 @@ function SvgWrapper({
277
269
  height={height}
278
270
  xmlns="http://www.w3.org/2000/svg"
279
271
  xmlnsXlink="http://www.w3.org/1999/xlink"
280
- viewBox={[0, 0, width, height].toString()}
272
+ viewBox={`0 0 ${width} ${height}`}
281
273
  >
282
274
  {children}
283
275
  </svg>
@@ -1,7 +1,6 @@
1
1
  import { expect, test } from 'vitest'
2
2
 
3
3
  import {
4
- globalColToSeqPos,
5
4
  globalColToVisibleCol,
6
5
  visibleColToGlobalCol,
7
6
  visibleColToSeqPos,
@@ -126,56 +125,6 @@ test('globalColToVisibleCol with consecutive blanks', () => {
126
125
  expect(globalColToVisibleCol(blanks, 10)).toBe(5)
127
126
  })
128
127
 
129
- // Tests for globalColToSeqPos (global column → sequence position)
130
- test('globalColToSeqPos with gaps in sequence', () => {
131
- const sequence = 'AC-GT-A'
132
- expect(globalColToSeqPos(sequence, 0)).toBe(0)
133
- expect(globalColToSeqPos(sequence, 1)).toBe(1)
134
- expect(globalColToSeqPos(sequence, 2)).toBe(2)
135
- // Position 2 is a gap, so count before it is 2
136
- expect(globalColToSeqPos(sequence, 3)).toBe(2)
137
- expect(globalColToSeqPos(sequence, 4)).toBe(3)
138
- expect(globalColToSeqPos(sequence, 5)).toBe(4)
139
- // Position 5 is a gap, so count before it is 4
140
- expect(globalColToSeqPos(sequence, 6)).toBe(4)
141
- })
142
-
143
- test('globalColToSeqPos with mixed gap characters (- and .)', () => {
144
- const sequence = 'AC.GT-A'
145
- expect(globalColToSeqPos(sequence, 0)).toBe(0)
146
- expect(globalColToSeqPos(sequence, 1)).toBe(1)
147
- // Position 2 is a gap (.), so count before it is 2
148
- expect(globalColToSeqPos(sequence, 2)).toBe(2)
149
- expect(globalColToSeqPos(sequence, 3)).toBe(2)
150
- expect(globalColToSeqPos(sequence, 4)).toBe(3)
151
- // Position 5 is a gap (-), so count before it is 4
152
- expect(globalColToSeqPos(sequence, 5)).toBe(4)
153
- expect(globalColToSeqPos(sequence, 6)).toBe(4)
154
- })
155
-
156
- test('globalColToSeqPos with no gaps in sequence', () => {
157
- const sequence = 'ACGTA'
158
- expect(globalColToSeqPos(sequence, 0)).toBe(0)
159
- expect(globalColToSeqPos(sequence, 1)).toBe(1)
160
- expect(globalColToSeqPos(sequence, 2)).toBe(2)
161
- expect(globalColToSeqPos(sequence, 3)).toBe(3)
162
- expect(globalColToSeqPos(sequence, 4)).toBe(4)
163
- })
164
-
165
- test('globalColToSeqPos with all gaps in sequence', () => {
166
- const sequence = '-----'
167
- expect(globalColToSeqPos(sequence, 0)).toBe(0)
168
- expect(globalColToSeqPos(sequence, 1)).toBe(0)
169
- expect(globalColToSeqPos(sequence, 2)).toBe(0)
170
- expect(globalColToSeqPos(sequence, 3)).toBe(0)
171
- expect(globalColToSeqPos(sequence, 4)).toBe(0)
172
- })
173
-
174
- test('globalColToSeqPos with position exceeding sequence length', () => {
175
- const sequence = 'AC-GT'
176
- expect(globalColToSeqPos(sequence, 10)).toBe(4)
177
- })
178
-
179
128
  // Tests for visibleColToSeqPos (visible column → sequence position)
180
129
  test('visibleColToSeqPos returns sequence position or undefined for gaps', () => {
181
130
  const seq = 'AC--GT--CT'
@@ -88,29 +88,6 @@ export function globalColToVisibleCol(
88
88
  return globalCol - blanksBefore
89
89
  }
90
90
 
91
- /**
92
- * Convert a global column index to a row-specific sequence position.
93
- * This counts non-gap characters up to the given global column.
94
- *
95
- * @param seq - The row's sequence string (including gaps)
96
- * @param globalCol - The global column index
97
- * @returns The sequence position (count of non-gap characters before this column)
98
- */
99
- export function globalColToSeqPos(seq: string, globalCol: number) {
100
- let seqPos = 0
101
- let currentCol = 0
102
- const seqLen = seq.length
103
-
104
- while (currentCol < globalCol && currentCol < seqLen) {
105
- if (!isBlank(seq[currentCol])) {
106
- seqPos++
107
- }
108
- currentCol++
109
- }
110
-
111
- return seqPos
112
- }
113
-
114
91
  /**
115
92
  * Convert a visible column to a row-specific sequence position.
116
93
  * Returns undefined if the position is a gap in the sequence.
package/src/util.ts CHANGED
@@ -1,9 +1,33 @@
1
1
  import { colord, extend } from 'colord'
2
+ import a11yPlugin from 'colord/plugins/a11y'
2
3
  import namesPlugin from 'colord/plugins/names'
3
4
 
4
5
  import type { Theme } from '@mui/material'
5
6
 
6
- extend([namesPlugin])
7
+ extend([namesPlugin, a11yPlugin])
8
+
9
+ const contrastAdjustCache = new Map<string, string>()
10
+
11
+ // Adjusts a background-tile color until it meets WCAG AA (4.5:1) contrast
12
+ // against `bg`, so it can be used as letter text in letter-color mode.
13
+ // Darkens on light backgrounds, lightens on dark backgrounds.
14
+ export function adjustColorForContrast(color: string, bg: string): string {
15
+ const cacheKey = `${color}|${bg}`
16
+ const cached = contrastAdjustCache.get(cacheKey)
17
+ if (cached !== undefined) {
18
+ return cached
19
+ }
20
+ let c = colord(color)
21
+ if (!c.isReadable(bg)) {
22
+ const bgIsDark = colord(bg).luminance() < 0.5
23
+ for (let i = 0; i < 40 && !c.isReadable(bg); i++) {
24
+ c = bgIsDark ? c.lighten(0.05) : c.darken(0.05)
25
+ }
26
+ }
27
+ const result = c.toHex()
28
+ contrastAdjustCache.set(cacheKey, result)
29
+ return result
30
+ }
7
31
 
8
32
  export function transform<T>(
9
33
  obj: Record<string, T>,
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = '5.1.1'
1
+ export const version = '5.2.0'