react-msaview 9.1.1 → 9.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.
- package/bundle/index.js +79 -79
- package/bundle/index.js.map +4 -4
- package/dist/components/DragHandle.js +2 -1
- package/dist/components/DragHandle.js.map +1 -1
- package/dist/components/MSAViewer.d.ts +31 -19
- package/dist/components/MSAViewer.js +2 -1
- package/dist/components/MSAViewer.js.map +1 -1
- package/dist/components/Track.js +2 -5
- package/dist/components/Track.js.map +1 -1
- package/dist/components/VerticalScrollbar.js +1 -1
- package/dist/components/VerticalScrollbar.js.map +1 -1
- package/dist/components/header/Header.js +2 -1
- package/dist/components/header/Header.js.map +1 -1
- package/dist/components/minimap/Minimap.js +1 -1
- package/dist/components/minimap/Minimap.js.map +1 -1
- package/dist/components/msa/MSACanvas.js +16 -27
- package/dist/components/msa/MSACanvas.js.map +1 -1
- package/dist/components/rowpanels/RowPanels.js +8 -6
- package/dist/components/rowpanels/RowPanels.js.map +1 -1
- package/dist/components/settings/SettingsPanel.js +2 -1
- package/dist/components/settings/SettingsPanel.js.map +1 -1
- package/dist/components/settings/TrackList.js +8 -5
- package/dist/components/settings/TrackList.js.map +1 -1
- package/dist/components/tracks/TrackTooltipContent.js +2 -1
- package/dist/components/tracks/TrackTooltipContent.js.map +1 -1
- package/dist/components/tracks/drawTracks.js +13 -6
- package/dist/components/tracks/drawTracks.js.map +1 -1
- package/dist/components/tree/TreeCanvas.js +8 -6
- package/dist/components/tree/TreeCanvas.js.map +1 -1
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +2 -0
- package/dist/constants.js.map +1 -1
- package/dist/element.d.ts +11 -7
- package/dist/element.js +46 -8
- package/dist/element.js.map +1 -1
- package/dist/featurePanels.d.ts +0 -7
- package/dist/featurePanels.js +1 -16
- package/dist/featurePanels.js.map +1 -1
- package/dist/ggplotPalettes.js +12 -1
- package/dist/ggplotPalettes.js.map +1 -1
- package/dist/groupKeys.d.ts +6 -0
- package/dist/groupKeys.js +52 -0
- package/dist/groupKeys.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/model.d.ts +40 -17
- package/dist/model.js +123 -54
- package/dist/model.js.map +1 -1
- package/dist/scales.d.ts +114 -13
- package/dist/scales.js +154 -19
- package/dist/scales.js.map +1 -1
- package/dist/svgTestUtil.d.ts +22 -12
- package/dist/types.d.ts +30 -28
- package/dist/useDragScroll.d.ts +4 -3
- package/dist/useDragScroll.js +9 -6
- package/dist/useDragScroll.js.map +1 -1
- package/dist/useWheelScroll.d.ts +26 -8
- package/dist/useWheelScroll.js +108 -71
- package/dist/useWheelScroll.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/viewerSnapshot.js +2 -1
- package/dist/viewerSnapshot.js.map +1 -1
- package/package.json +3 -3
- package/src/components/DragHandle.tsx +2 -1
- package/src/components/MSAViewer.tsx +11 -8
- package/src/components/Track.tsx +2 -8
- package/src/components/VerticalScrollbar.tsx +1 -1
- package/src/components/header/Header.tsx +2 -1
- package/src/components/minimap/Minimap.tsx +1 -1
- package/src/components/msa/MSACanvas.tsx +14 -35
- package/src/components/rowpanels/RowPanels.tsx +8 -10
- package/src/components/settings/SettingsPanel.tsx +2 -1
- package/src/components/settings/TrackList.tsx +9 -4
- package/src/components/tracks/TrackTooltipContent.tsx +2 -1
- package/src/components/tracks/drawTracks.ts +15 -7
- package/src/components/tree/TreeCanvas.tsx +8 -10
- package/src/constants.ts +2 -0
- package/src/element.ts +53 -8
- package/src/featurePanels.ts +1 -25
- package/src/ggplotPalettes.ts +13 -1
- package/src/groupKeys.ts +54 -0
- package/src/index.ts +13 -2
- package/src/model.ts +174 -72
- package/src/scales.ts +268 -25
- package/src/types.ts +29 -26
- package/src/useDragScroll.ts +11 -8
- package/src/useWheelScroll.ts +124 -84
- package/src/version.ts +1 -1
- package/src/viewerSnapshot.ts +3 -1
package/src/scales.ts
CHANGED
|
@@ -1,12 +1,42 @@
|
|
|
1
|
+
import { colord } from 'colord'
|
|
2
|
+
|
|
1
3
|
import { createPaletteMap } from './createPaletteMap.ts'
|
|
2
4
|
import { paletteNamed } from './ggplotPalettes.ts'
|
|
5
|
+
import { compareGroupKeys } from './groupKeys.ts'
|
|
3
6
|
|
|
4
|
-
import type {
|
|
7
|
+
import type {
|
|
8
|
+
ColorScheme,
|
|
9
|
+
ColumnTrackSpec,
|
|
10
|
+
Encoding,
|
|
11
|
+
LegendEntry,
|
|
12
|
+
RowPanelSpec,
|
|
13
|
+
} from './types.ts'
|
|
5
14
|
|
|
6
|
-
/**
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
15
|
+
/**
|
|
16
|
+
* The color object: the scale a channel reads its field through, the members
|
|
17
|
+
* jbrowse-components' displays declare (its ADR-151). The values the field
|
|
18
|
+
* takes are the scale's domain, `range` holds the colors they map onto, and
|
|
19
|
+
* the legend is the guide listing each value with its color.
|
|
20
|
+
*
|
|
21
|
+
* - `scale`: the kind, `categorical` when unset and the only kind so far
|
|
22
|
+
* - `domain`: values in legend order, each taking the `range` color at its own
|
|
23
|
+
* index; the field's other values follow in natural order
|
|
24
|
+
* - `range`: a palette name (`ggplot`, `set1`, `dark2`, `okabeito`, `tableau`)
|
|
25
|
+
* or a list of colors, which colors as many values as it holds
|
|
26
|
+
* - `title`: the legend's title, the field when unset
|
|
27
|
+
*
|
|
28
|
+
* Records declaring the same members, `title` included, share one scale.
|
|
29
|
+
*/
|
|
30
|
+
export interface ColorSpec {
|
|
31
|
+
scale?: 'categorical'
|
|
32
|
+
domain?: string[]
|
|
33
|
+
range?: string | string[]
|
|
34
|
+
title?: string
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** a channel record: a field read through a color object */
|
|
38
|
+
export interface ColorChannel extends ColorSpec {
|
|
39
|
+
field: string
|
|
10
40
|
}
|
|
11
41
|
|
|
12
42
|
export interface ResolvedScale {
|
|
@@ -16,32 +46,245 @@ export interface ResolvedScale {
|
|
|
16
46
|
}
|
|
17
47
|
|
|
18
48
|
/**
|
|
19
|
-
* The
|
|
20
|
-
*
|
|
21
|
-
*
|
|
49
|
+
* The colors a `range` lists, read the way jbrowse-components'
|
|
50
|
+
* `paletteFromSpec` reads a string: a palette name gives undefined here, and a
|
|
51
|
+
* comma-separated list of colors gives the list
|
|
52
|
+
*/
|
|
53
|
+
function rangeList(range: ColorSpec['range']) {
|
|
54
|
+
if (typeof range !== 'string') {
|
|
55
|
+
return range
|
|
56
|
+
}
|
|
57
|
+
if (paletteNamed(range)) {
|
|
58
|
+
return undefined
|
|
59
|
+
}
|
|
60
|
+
const colors = range.split(/,(?![^(]*\))/).map(c => c.trim())
|
|
61
|
+
return colors.every(c => colord(c).isValid()) ? colors : undefined
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function rangeColors(range: ColorSpec['range'], order: string[]) {
|
|
65
|
+
const list = rangeList(range)
|
|
66
|
+
return list
|
|
67
|
+
? new Map(order.slice(0, list.length).map((value, i) => [value, list[i]!]))
|
|
68
|
+
: new Map(
|
|
69
|
+
Object.entries(
|
|
70
|
+
createPaletteMap(
|
|
71
|
+
order,
|
|
72
|
+
paletteNamed(typeof range === 'string' ? range : undefined),
|
|
73
|
+
),
|
|
74
|
+
),
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* The scale a channel reads its field through. `values` are the field's
|
|
80
|
+
* values, in any order and with repeats. The domain lists the values `domain`
|
|
81
|
+
* names first, then the rest in natural order, so a value keeps its color when
|
|
82
|
+
* rows are re-ordered, collapsed or filtered.
|
|
22
83
|
*
|
|
23
|
-
* `
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
84
|
+
* A palette name, or no `range` at all, colors every value: past the end of
|
|
85
|
+
* the palette each takes an evenly spaced hue. A list of colors leaves the
|
|
86
|
+
* values past its end uncolored, so `{domain, range}` colors the values it
|
|
87
|
+
* names and no others.
|
|
27
88
|
*/
|
|
28
89
|
export function resolveScale(
|
|
29
|
-
spec:
|
|
90
|
+
spec: ColorSpec | undefined,
|
|
30
91
|
values: Iterable<string>,
|
|
31
92
|
): ResolvedScale {
|
|
32
|
-
const
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
93
|
+
const present = new Set(values)
|
|
94
|
+
const listed = new Set(spec?.domain)
|
|
95
|
+
const order = [
|
|
96
|
+
...listed,
|
|
97
|
+
...[...present].filter(v => !listed.has(v)).sort(compareGroupKeys),
|
|
98
|
+
]
|
|
99
|
+
const colors = rangeColors(spec?.range, order)
|
|
37
100
|
return {
|
|
38
101
|
kind: 'categorical',
|
|
39
|
-
colorOf: (value: string) => colors
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
id: value,
|
|
43
|
-
label: value,
|
|
44
|
-
color: colors[value]!,
|
|
45
|
-
})),
|
|
102
|
+
colorOf: (value: string) => colors.get(value),
|
|
103
|
+
legend: order
|
|
104
|
+
.filter(value => present.has(value) && colors.has(value))
|
|
105
|
+
.map(value => ({ id: value, label: value, color: colors.get(value)! })),
|
|
46
106
|
}
|
|
47
107
|
}
|
|
108
|
+
|
|
109
|
+
/** which table a record's field is read from */
|
|
110
|
+
export type ScaleTable = 'rows' | 'features'
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* One record's use of a color object: the values its field takes in its
|
|
114
|
+
* table, and for the feature table the values the drawn features carry, which
|
|
115
|
+
* the legend lists
|
|
116
|
+
*/
|
|
117
|
+
export interface ScaleUse {
|
|
118
|
+
spec: ColorSpec
|
|
119
|
+
field: string
|
|
120
|
+
table: ScaleTable
|
|
121
|
+
values: string[]
|
|
122
|
+
shown?: string[]
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export interface SharedScale extends ResolvedScale {
|
|
126
|
+
key: string
|
|
127
|
+
title: string
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* The key records share a scale under: the table and the members as declared,
|
|
132
|
+
* with `title` standing in for the field. Two strips over one palette with no
|
|
133
|
+
* title read two fields and list two legends; naming one title gives them one
|
|
134
|
+
* scale and one legend.
|
|
135
|
+
*/
|
|
136
|
+
export function declarationKey({
|
|
137
|
+
spec,
|
|
138
|
+
field,
|
|
139
|
+
table,
|
|
140
|
+
}: Pick<ScaleUse, 'spec' | 'field' | 'table'>) {
|
|
141
|
+
const { scale = 'categorical', domain, range, title = field } = spec
|
|
142
|
+
return JSON.stringify([table, scale, domain, range, title])
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Resolves each declaration once over the union of its records' values, so a
|
|
147
|
+
* value two fields share takes one color in both
|
|
148
|
+
*/
|
|
149
|
+
export function resolveShared(uses: ScaleUse[]) {
|
|
150
|
+
const groups = new Map<string, ScaleUse[]>()
|
|
151
|
+
for (const use of uses) {
|
|
152
|
+
const key = declarationKey(use)
|
|
153
|
+
groups.set(key, [...(groups.get(key) ?? []), use])
|
|
154
|
+
}
|
|
155
|
+
return new Map(
|
|
156
|
+
[...groups].map(([key, group]) => {
|
|
157
|
+
const { spec, field } = group[0]!
|
|
158
|
+
const resolved = resolveScale(
|
|
159
|
+
spec,
|
|
160
|
+
group.flatMap(u => u.values),
|
|
161
|
+
)
|
|
162
|
+
const shown = group[0]!.shown
|
|
163
|
+
? new Set(group.flatMap(u => u.shown ?? []))
|
|
164
|
+
: undefined
|
|
165
|
+
const scale: SharedScale = {
|
|
166
|
+
...resolved,
|
|
167
|
+
key,
|
|
168
|
+
title: spec.title ?? field,
|
|
169
|
+
legend: shown
|
|
170
|
+
? resolved.legend.filter(entry => shown.has(entry.id))
|
|
171
|
+
: resolved.legend,
|
|
172
|
+
}
|
|
173
|
+
return [key, scale] as const
|
|
174
|
+
}),
|
|
175
|
+
)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/** the spelling a color object had before ADR-151's: `{palette}` or `{map}` */
|
|
179
|
+
export interface LegacyScale {
|
|
180
|
+
palette?: string
|
|
181
|
+
map?: Record<string, string>
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/** a record as an older snapshot, R or Python may write it */
|
|
185
|
+
export type LegacyColor<T extends ColorSpec> = Omit<T, 'scale'> & {
|
|
186
|
+
scale?: ColorSpec['scale'] | LegacyScale
|
|
187
|
+
legend?: string
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Lifts the earlier spelling onto the color object: `{palette: p}` reads as
|
|
192
|
+
* `{range: p}`, `{map: m}` as `{domain: keys(m), range: values(m)}`, and a
|
|
193
|
+
* strip's `legend` as `title`. A member written in the new spelling wins.
|
|
194
|
+
*/
|
|
195
|
+
export function readColor<T extends ColorSpec>(record: LegacyColor<T>): T {
|
|
196
|
+
const { scale, legend, ...rest } = record
|
|
197
|
+
if (typeof scale !== 'object' && legend === undefined) {
|
|
198
|
+
return record as T
|
|
199
|
+
}
|
|
200
|
+
const lifted: ColorSpec =
|
|
201
|
+
typeof scale !== 'object'
|
|
202
|
+
? scale === undefined
|
|
203
|
+
? {}
|
|
204
|
+
: { scale }
|
|
205
|
+
: scale.map
|
|
206
|
+
? { domain: Object.keys(scale.map), range: Object.values(scale.map) }
|
|
207
|
+
: scale.palette === undefined
|
|
208
|
+
? {}
|
|
209
|
+
: { range: scale.palette }
|
|
210
|
+
return {
|
|
211
|
+
...(legend === undefined ? {} : { title: legend }),
|
|
212
|
+
...lifted,
|
|
213
|
+
...rest,
|
|
214
|
+
} as unknown as T
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export type LegacyEncoding = LegacyColor<Encoding>
|
|
218
|
+
|
|
219
|
+
export function readEncoding(encoding: Encoding | LegacyEncoding) {
|
|
220
|
+
return readColor<Encoding>(encoding)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export type LegacyRowPanel =
|
|
224
|
+
| LegacyColor<Extract<RowPanelSpec, { kind: 'strip' }>>
|
|
225
|
+
| (Omit<Extract<RowPanelSpec, { kind: 'features' }>, 'encoding'> & {
|
|
226
|
+
encoding?: {
|
|
227
|
+
color?: LegacyColor<ColorChannel>
|
|
228
|
+
label?: string
|
|
229
|
+
}
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
export function readRowPanel(panel: RowPanelSpec | LegacyRowPanel) {
|
|
233
|
+
if (panel.kind === 'strip') {
|
|
234
|
+
return readColor<Extract<RowPanelSpec, { kind: 'strip' }>>(panel)
|
|
235
|
+
}
|
|
236
|
+
const color = panel.encoding?.color
|
|
237
|
+
return (
|
|
238
|
+
color
|
|
239
|
+
? { ...panel, encoding: { ...panel.encoding, color: readColor(color) } }
|
|
240
|
+
: panel
|
|
241
|
+
) as RowPanelSpec
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export type LegacyColumnTrack = ColumnTrackSpec & {
|
|
245
|
+
max?: number
|
|
246
|
+
colors?: Record<string, string>
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Lifts a column track's `colors` onto `encoding.color` and its `max` onto
|
|
251
|
+
* `scales.y.domainMax`
|
|
252
|
+
*/
|
|
253
|
+
export function readColumnTrack(track: LegacyColumnTrack): ColumnTrackSpec {
|
|
254
|
+
const { max, colors, ...rest } = track
|
|
255
|
+
if (max === undefined && colors === undefined) {
|
|
256
|
+
return track
|
|
257
|
+
}
|
|
258
|
+
return {
|
|
259
|
+
...(colors
|
|
260
|
+
? {
|
|
261
|
+
encoding: {
|
|
262
|
+
color: {
|
|
263
|
+
domain: Object.keys(colors),
|
|
264
|
+
range: Object.values(colors),
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
}
|
|
268
|
+
: {}),
|
|
269
|
+
...(max === undefined ? {} : { scales: { y: { domainMax: max } } }),
|
|
270
|
+
...rest,
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* The color a color object gives each value listed, for a reader that keys
|
|
276
|
+
* colors by value, such as the residue letters of a scheme or a text track
|
|
277
|
+
*/
|
|
278
|
+
export function colorTable(spec: ColorSpec, values: Iterable<string>) {
|
|
279
|
+
return Object.fromEntries(
|
|
280
|
+
resolveScale(spec, values).legend.map(e => [e.id, e.color]),
|
|
281
|
+
)
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* The letter-to-color table an object `colorScheme` gives, `{domain, range}`
|
|
286
|
+
* or the earlier `{map}`
|
|
287
|
+
*/
|
|
288
|
+
export function letterColors(scheme: Exclude<ColorScheme, string>) {
|
|
289
|
+
return 'map' in scheme ? scheme.map : colorTable(scheme, scheme.domain ?? [])
|
|
290
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ColorChannel, ColorSpec, SharedScale } from './scales.ts'
|
|
2
2
|
import type { Annotation } from 'msa-parsers'
|
|
3
3
|
|
|
4
4
|
export interface Accession {
|
|
@@ -8,7 +8,7 @@ export interface Accession {
|
|
|
8
8
|
}
|
|
9
9
|
// every kind draws into the same per-column space; drawTracks.ts dispatches on
|
|
10
10
|
// it to pick the draw function
|
|
11
|
-
export type TrackKind = 'text' | 'bar' | 'logo' | 'arc' | 'ruler'
|
|
11
|
+
export type TrackKind = 'text' | 'bar' | 'logo' | 'arc' | 'ruler' | 'reference'
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Which channel the color scheme paints. `fill` colors the cell a residue sits
|
|
@@ -18,11 +18,17 @@ export type TrackKind = 'text' | 'bar' | 'logo' | 'arc' | 'ruler'
|
|
|
18
18
|
export type ResidueEncoding = 'fill' | 'color'
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
|
-
* The residue colors: a scheme name from the built-in table, or a
|
|
22
|
-
*
|
|
23
|
-
* uncolored
|
|
21
|
+
* The residue colors: a scheme name from the built-in table, or a color object
|
|
22
|
+
* over residue letters, `{domain: ['K', 'R'], range: ['#1f77b4', '#1f77b4']}`,
|
|
23
|
+
* which leaves every letter it does not list uncolored
|
|
24
24
|
*/
|
|
25
|
-
export type ColorScheme =
|
|
25
|
+
export type ColorScheme =
|
|
26
|
+
| string
|
|
27
|
+
| Pick<ColorSpec, 'domain' | 'range'>
|
|
28
|
+
| {
|
|
29
|
+
/** @deprecated the earlier spelling of `{domain, range}` */
|
|
30
|
+
map: Record<string, string>
|
|
31
|
+
}
|
|
26
32
|
|
|
27
33
|
export interface BasicTrackModel {
|
|
28
34
|
id: string
|
|
@@ -75,7 +81,8 @@ export interface ArcSpec {
|
|
|
75
81
|
// a track supplied as data in the snapshot rather than computed from the
|
|
76
82
|
// alignment. `values` (bar) or `data` (text) index alignment columns, or the
|
|
77
83
|
// 1-based residues of `row` when it names one; `arcs` (arc) name two such
|
|
78
|
-
// positions each
|
|
84
|
+
// positions each. `scales.y.domainMax` is the bar value drawn at full height,
|
|
85
|
+
// and a text track's `encoding.color` colors its characters
|
|
79
86
|
export interface ColumnTrackSpec {
|
|
80
87
|
id: string
|
|
81
88
|
name: string
|
|
@@ -83,32 +90,29 @@ export interface ColumnTrackSpec {
|
|
|
83
90
|
values?: number[]
|
|
84
91
|
data?: string
|
|
85
92
|
arcs?: ArcSpec[]
|
|
86
|
-
max?: number
|
|
87
93
|
color?: string
|
|
88
|
-
|
|
94
|
+
encoding?: { color?: ColorSpec }
|
|
95
|
+
scales?: { y?: { domainMax?: number } }
|
|
89
96
|
row?: string
|
|
90
97
|
height?: number
|
|
91
98
|
}
|
|
92
99
|
|
|
93
100
|
/**
|
|
94
|
-
* A strip panel: one cell per row, colored from a `rowData` field through
|
|
95
|
-
*
|
|
96
|
-
* the row height, and `header` labels the column and defaults
|
|
97
|
-
*
|
|
98
|
-
*
|
|
101
|
+
* A strip panel: one cell per row, colored from a `rowData` field through the
|
|
102
|
+
* color object's members, which is ggtree's `gheatmap`. `width` is in pixels
|
|
103
|
+
* and defaults to the row height, and `header` labels the column and defaults
|
|
104
|
+
* to the field. Strips declaring the same members and `title` share one scale
|
|
105
|
+
* and one legend.
|
|
99
106
|
*/
|
|
100
|
-
export interface RowStripSpec {
|
|
107
|
+
export interface RowStripSpec extends ColorChannel {
|
|
101
108
|
kind: 'strip'
|
|
102
|
-
field: string
|
|
103
|
-
scale?: ScaleSpec
|
|
104
109
|
width?: number
|
|
105
110
|
header?: string
|
|
106
|
-
legend?: string
|
|
107
111
|
}
|
|
108
112
|
|
|
109
113
|
/** the channels a `features` panel reads off the feature table */
|
|
110
114
|
export interface FeatureEncodingSpec {
|
|
111
|
-
color?:
|
|
115
|
+
color?: ColorChannel
|
|
112
116
|
label?: string
|
|
113
117
|
}
|
|
114
118
|
|
|
@@ -150,7 +154,8 @@ interface ResolvedPanelBase {
|
|
|
150
154
|
width: number
|
|
151
155
|
offsetX: number
|
|
152
156
|
legend: LegendEntry[]
|
|
153
|
-
/** the
|
|
157
|
+
/** the scale this panel's entries list under; absent means the domain key */
|
|
158
|
+
legendKey?: string
|
|
154
159
|
legendTitle?: string
|
|
155
160
|
}
|
|
156
161
|
|
|
@@ -497,17 +502,15 @@ export type EncodingChannel =
|
|
|
497
502
|
| 'featureLabel'
|
|
498
503
|
|
|
499
504
|
/**
|
|
500
|
-
* A channel, the field feeding it, and the
|
|
501
|
-
* See docs/layers.md
|
|
505
|
+
* A channel, the field feeding it, and the color object's members it reads
|
|
506
|
+
* that field through. See docs/layers.md
|
|
502
507
|
*/
|
|
503
|
-
export interface Encoding {
|
|
508
|
+
export interface Encoding extends ColorChannel {
|
|
504
509
|
channel: EncodingChannel
|
|
505
|
-
field: string
|
|
506
|
-
scale?: ScaleSpec
|
|
507
510
|
}
|
|
508
511
|
|
|
509
512
|
/** an Encoding with its scale resolved against the values in the table */
|
|
510
|
-
export type ResolvedEncoding = Encoding &
|
|
513
|
+
export type ResolvedEncoding = Encoding & SharedScale
|
|
511
514
|
|
|
512
515
|
/** a Highlight resolved to visible column indices and row indices */
|
|
513
516
|
export interface ResolvedHighlight {
|
package/src/useDragScroll.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { useEffect, useRef, useState } from 'react'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Tracks a
|
|
5
|
-
* animation frame. Shared by the horizontal Minimap
|
|
4
|
+
* Tracks a pointer drag along a single axis and reports the scroll delta on
|
|
5
|
+
* each animation frame. Shared by the horizontal Minimap, the VerticalScrollbar
|
|
6
|
+
* and the dividers.
|
|
6
7
|
*
|
|
7
8
|
* `onScroll` is invoked with the pixel delta since drag start and the scroll
|
|
8
9
|
* offset captured when the drag began. Memoize it (useCallback) so the document
|
|
@@ -21,7 +22,7 @@ export function useDragScroll(
|
|
|
21
22
|
useEffect(() => {
|
|
22
23
|
if (mouseDown !== undefined) {
|
|
23
24
|
const { client: startClient, startScroll } = mouseDown
|
|
24
|
-
function onMove(event:
|
|
25
|
+
function onMove(event: PointerEvent) {
|
|
25
26
|
if (!scheduled.current) {
|
|
26
27
|
scheduled.current = true
|
|
27
28
|
requestAnimationFrame(() => {
|
|
@@ -34,18 +35,20 @@ export function useDragScroll(
|
|
|
34
35
|
function onUp() {
|
|
35
36
|
setMouseDown(undefined)
|
|
36
37
|
}
|
|
37
|
-
document.addEventListener('
|
|
38
|
-
document.addEventListener('
|
|
38
|
+
document.addEventListener('pointermove', onMove)
|
|
39
|
+
document.addEventListener('pointerup', onUp)
|
|
40
|
+
document.addEventListener('pointercancel', onUp)
|
|
39
41
|
return () => {
|
|
40
|
-
document.removeEventListener('
|
|
41
|
-
document.removeEventListener('
|
|
42
|
+
document.removeEventListener('pointermove', onMove)
|
|
43
|
+
document.removeEventListener('pointerup', onUp)
|
|
44
|
+
document.removeEventListener('pointercancel', onUp)
|
|
42
45
|
}
|
|
43
46
|
}
|
|
44
47
|
}, [axis, onScroll, mouseDown])
|
|
45
48
|
|
|
46
49
|
return {
|
|
47
50
|
dragging: mouseDown !== undefined,
|
|
48
|
-
startDrag: (event: React.
|
|
51
|
+
startDrag: (event: React.PointerEvent, startScroll: number) => {
|
|
49
52
|
setMouseDown({
|
|
50
53
|
client: axis === 'x' ? event.clientX : event.clientY,
|
|
51
54
|
startScroll,
|