@genome-spy/core 0.30.0 → 0.30.3
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/dist/index.es.js +16379 -0
- package/dist/index.js +43 -43
- package/package.json +10 -7
- package/src/data/collector.js +0 -183
- package/src/data/collector.test.js +0 -84
- package/src/data/dataFlow.js +0 -148
- package/src/data/dataFlow.test.js +0 -5
- package/src/data/facetNode.js +0 -17
- package/src/data/flow.test.js +0 -72
- package/src/data/flowBatch.d.ts +0 -40
- package/src/data/flowNode.js +0 -283
- package/src/data/flowNode.test.js +0 -50
- package/src/data/flowOptimizer.js +0 -123
- package/src/data/flowOptimizer.test.js +0 -193
- package/src/data/flowTestUtils.js +0 -63
- package/src/data/formats/fasta.js +0 -32
- package/src/data/formats/fasta.test.js +0 -27
- package/src/data/sources/dataSource.js +0 -22
- package/src/data/sources/dataSourceFactory.js +0 -24
- package/src/data/sources/dataUtils.js +0 -78
- package/src/data/sources/dynamicCallbackSource.js +0 -57
- package/src/data/sources/dynamicSource.js +0 -37
- package/src/data/sources/inlineSource.js +0 -67
- package/src/data/sources/inlineSource.test.js +0 -56
- package/src/data/sources/namedSource.js +0 -79
- package/src/data/sources/sequenceSource.js +0 -46
- package/src/data/sources/sequenceSource.test.js +0 -46
- package/src/data/sources/urlSource.js +0 -74
- package/src/data/transforms/aggregate.js +0 -70
- package/src/data/transforms/clone.js +0 -40
- package/src/data/transforms/clone.test.js +0 -11
- package/src/data/transforms/coverage.js +0 -187
- package/src/data/transforms/coverage.test.js +0 -123
- package/src/data/transforms/filter.js +0 -37
- package/src/data/transforms/filter.test.js +0 -18
- package/src/data/transforms/filterScoredLabels.js +0 -134
- package/src/data/transforms/flattenCompressedExons.js +0 -57
- package/src/data/transforms/flattenDelimited.js +0 -74
- package/src/data/transforms/flattenDelimited.test.js +0 -87
- package/src/data/transforms/flattenSequence.js +0 -39
- package/src/data/transforms/flattenSequence.test.js +0 -34
- package/src/data/transforms/formula.js +0 -39
- package/src/data/transforms/formula.test.js +0 -19
- package/src/data/transforms/identifier.js +0 -108
- package/src/data/transforms/identifier.test.js +0 -83
- package/src/data/transforms/linearizeGenomicCoordinate.js +0 -101
- package/src/data/transforms/measureText.js +0 -44
- package/src/data/transforms/pileup.js +0 -128
- package/src/data/transforms/pileup.test.js +0 -70
- package/src/data/transforms/project.js +0 -41
- package/src/data/transforms/project.test.js +0 -32
- package/src/data/transforms/regexExtract.js +0 -61
- package/src/data/transforms/regexExtract.test.js +0 -67
- package/src/data/transforms/regexFold.js +0 -141
- package/src/data/transforms/regexFold.test.js +0 -160
- package/src/data/transforms/sample.js +0 -101
- package/src/data/transforms/sample.test.js +0 -38
- package/src/data/transforms/stack.js +0 -137
- package/src/data/transforms/stack.test.js +0 -91
- package/src/data/transforms/transformFactory.js +0 -60
- package/src/embedApi.d.ts +0 -67
- package/src/encoder/accessor.js +0 -82
- package/src/encoder/accessor.test.js +0 -47
- package/src/encoder/encoder.js +0 -394
- package/src/encoder/encoder.test.js +0 -98
- package/src/fonts/Lato-Regular.json +0 -1267
- package/src/fonts/Lato-Regular.png +0 -0
- package/src/fonts/OFL.txt +0 -93
- package/src/fonts/README.md +0 -3
- package/src/fonts/bmFont.d.ts +0 -58
- package/src/fonts/bmFontManager.js +0 -357
- package/src/fonts/bmFontMetrics.js +0 -108
- package/src/genome/genome.js +0 -317
- package/src/genome/genome.test.js +0 -188
- package/src/genome/genomeStore.js +0 -54
- package/src/genome/locusFormat.js +0 -31
- package/src/genome/scaleIndex.d.ts +0 -38
- package/src/genome/scaleIndex.js +0 -166
- package/src/genome/scaleIndex.test.js +0 -78
- package/src/genome/scaleLocus.d.ts +0 -11
- package/src/genome/scaleLocus.js +0 -108
- package/src/genome/scaleLocus.test.js +0 -4
- package/src/genomeSpy.js +0 -785
- package/src/gl/arrayBuilder.js +0 -199
- package/src/gl/dataToVertices.js +0 -636
- package/src/gl/includes/common.glsl +0 -63
- package/src/gl/includes/picking.fragment.glsl +0 -1
- package/src/gl/includes/picking.vertex.glsl +0 -27
- package/src/gl/includes/sampleFacet.glsl +0 -107
- package/src/gl/includes/scales.glsl +0 -112
- package/src/gl/link.fragment.glsl +0 -18
- package/src/gl/link.vertex.glsl +0 -111
- package/src/gl/point.fragment.glsl +0 -123
- package/src/gl/point.vertex.glsl +0 -129
- package/src/gl/rect.fragment.glsl +0 -51
- package/src/gl/rect.vertex.glsl +0 -114
- package/src/gl/rule.fragment.glsl +0 -52
- package/src/gl/rule.vertex.glsl +0 -89
- package/src/gl/text.fragment.glsl +0 -31
- package/src/gl/text.vertex.glsl +0 -246
- package/src/gl/webGLHelper.js +0 -504
- package/src/img/bowtie.svg +0 -1
- package/src/img/genomespy-favicon.svg +0 -34
- package/src/index.html +0 -11
- package/src/index.js +0 -128
- package/src/marks/link.js +0 -175
- package/src/marks/mark.js +0 -975
- package/src/marks/markUtils.js +0 -125
- package/src/marks/pointMark.js +0 -251
- package/src/marks/rectMark.js +0 -241
- package/src/marks/rule.js +0 -250
- package/src/marks/text.js +0 -278
- package/src/node_modules/.vitest/results.json +0 -1
- package/src/scale/colorUtils.js +0 -184
- package/src/scale/glslScaleGenerator.js +0 -502
- package/src/scale/scale.js +0 -451
- package/src/scale/scale.test.js +0 -324
- package/src/scale/ticks.js +0 -203
- package/src/scale/ticks.test.js +0 -40
- package/src/singlePageApp.js +0 -13
- package/src/spec/axis.d.ts +0 -296
- package/src/spec/channel.d.ts +0 -430
- package/src/spec/data.d.ts +0 -196
- package/src/spec/font.d.ts +0 -15
- package/src/spec/genome.d.ts +0 -35
- package/src/spec/mark.d.ts +0 -429
- package/src/spec/root.d.ts +0 -17
- package/src/spec/sampleView.d.ts +0 -180
- package/src/spec/scale.d.ts +0 -273
- package/src/spec/title.d.ts +0 -102
- package/src/spec/tooltip.d.ts +0 -9
- package/src/spec/transform.d.ts +0 -479
- package/src/spec/view.d.ts +0 -201
- package/src/styles/genome-spy.scss +0 -153
- package/src/tooltip/dataTooltipHandler.js +0 -64
- package/src/tooltip/refseqGeneTooltipHandler.js +0 -78
- package/src/tooltip/tooltipHandler.ts +0 -12
- package/src/types/filetypes.d.ts +0 -14
- package/src/types/flatqueue.d.ts +0 -53
- package/src/types/glsl.d.ts +0 -4
- package/src/types/internmap.d.ts +0 -22
- package/src/types/object.d.ts +0 -21
- package/src/types/vega-loader.d.ts +0 -1
- package/src/types/vega-scale.d.ts +0 -60
- package/src/utils/addBaseUrl.js +0 -19
- package/src/utils/addBaseUrl.test.js +0 -22
- package/src/utils/animator.js +0 -83
- package/src/utils/arrayUtils.js +0 -61
- package/src/utils/binnedIndex.js +0 -167
- package/src/utils/binnedIndex.test.js +0 -155
- package/src/utils/clamp.js +0 -8
- package/src/utils/cloner.js +0 -34
- package/src/utils/cloner.test.js +0 -24
- package/src/utils/coalesce.js +0 -11
- package/src/utils/coalesce.test.js +0 -16
- package/src/utils/concatIterables.js +0 -26
- package/src/utils/concatIterables.test.js +0 -8
- package/src/utils/debounce.js +0 -37
- package/src/utils/domainArray.js +0 -216
- package/src/utils/domainArray.test.js +0 -130
- package/src/utils/eerp.js +0 -13
- package/src/utils/expression.js +0 -32
- package/src/utils/field.js +0 -28
- package/src/utils/formatObject.js +0 -31
- package/src/utils/indexer.js +0 -43
- package/src/utils/indexer.test.js +0 -47
- package/src/utils/inertia.js +0 -124
- package/src/utils/interactionEvent.js +0 -33
- package/src/utils/iterateNestedMaps.js +0 -21
- package/src/utils/iterateNestedMaps.test.js +0 -33
- package/src/utils/kWayMerge.js +0 -42
- package/src/utils/kWayMerge.test.js +0 -26
- package/src/utils/layout/flexLayout.js +0 -368
- package/src/utils/layout/flexLayout.test.js +0 -311
- package/src/utils/layout/grid.js +0 -95
- package/src/utils/layout/grid.test.js +0 -71
- package/src/utils/layout/padding.js +0 -120
- package/src/utils/layout/point.js +0 -23
- package/src/utils/layout/rectangle.js +0 -288
- package/src/utils/layout/rectangle.test.js +0 -172
- package/src/utils/mergeObjects.js +0 -99
- package/src/utils/mergeObjects.test.js +0 -42
- package/src/utils/numberExtractor.js +0 -24
- package/src/utils/numberExtractor.test.js +0 -6
- package/src/utils/point.js +0 -14
- package/src/utils/propertyCacher.js +0 -70
- package/src/utils/propertyCacher.test.js +0 -85
- package/src/utils/propertyCoalescer.js +0 -42
- package/src/utils/propertyCoalescer.test.js +0 -22
- package/src/utils/reservationMap.js +0 -103
- package/src/utils/reservationMap.test.js +0 -20
- package/src/utils/scaleNull.js +0 -19
- package/src/utils/setOperations.js +0 -75
- package/src/utils/smoothstep.js +0 -10
- package/src/utils/throttle.js +0 -34
- package/src/utils/topK.js +0 -76
- package/src/utils/topK.test.js +0 -64
- package/src/utils/transition.js +0 -74
- package/src/utils/ui/tooltip.js +0 -189
- package/src/utils/url.js +0 -22
- package/src/utils/variableTools.js +0 -24
- package/src/utils/variableTools.test.js +0 -13
- package/src/view/axisResolution.js +0 -140
- package/src/view/axisResolution.test.js +0 -201
- package/src/view/axisView.js +0 -747
- package/src/view/concatView.js +0 -45
- package/src/view/containerView.js +0 -159
- package/src/view/facetView.js +0 -491
- package/src/view/flowBuilder.js +0 -367
- package/src/view/flowBuilder.test.js +0 -125
- package/src/view/gridView.js +0 -786
- package/src/view/implicitRootView.js +0 -14
- package/src/view/importView.js +0 -19
- package/src/view/layerView.js +0 -74
- package/src/view/rendering.d.ts +0 -44
- package/src/view/renderingContext/compositeViewRenderingContext.js +0 -51
- package/src/view/renderingContext/deferredViewRenderingContext.js +0 -176
- package/src/view/renderingContext/layoutRecorderViewRenderingContext.js +0 -128
- package/src/view/renderingContext/simpleViewRenderingContext.js +0 -64
- package/src/view/renderingContext/svgViewRenderingContext.js +0 -125
- package/src/view/renderingContext/viewRenderingContext.js +0 -41
- package/src/view/scaleResolution.js +0 -797
- package/src/view/scaleResolution.test.js +0 -572
- package/src/view/scaleResolutionApi.d.ts +0 -40
- package/src/view/testUtils.js +0 -51
- package/src/view/title.js +0 -165
- package/src/view/unitView.js +0 -382
- package/src/view/view.js +0 -612
- package/src/view/view.test.js +0 -214
- package/src/view/viewContext.d.ts +0 -62
- package/src/view/viewFactory.js +0 -181
- package/src/view/viewFactory.test.js +0 -17
- package/src/view/viewUtils.js +0 -327
- package/src/view/zoom.js +0 -89
package/src/view/title.js
DELETED
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
import { isString } from "vega-util";
|
|
2
|
-
|
|
3
|
-
/** @type {Omit<Required<import("../spec/title").Title>, "text" | "style">} */
|
|
4
|
-
const BASE_TITLE_STYLE = {
|
|
5
|
-
anchor: "middle",
|
|
6
|
-
frame: "group",
|
|
7
|
-
offset: 10,
|
|
8
|
-
orient: "top",
|
|
9
|
-
align: undefined,
|
|
10
|
-
angle: 0,
|
|
11
|
-
baseline: "alphabetic",
|
|
12
|
-
dx: 0,
|
|
13
|
-
dy: 0,
|
|
14
|
-
color: undefined,
|
|
15
|
-
font: undefined,
|
|
16
|
-
fontSize: 12,
|
|
17
|
-
fontStyle: "normal",
|
|
18
|
-
fontWeight: "normal",
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
/** @type {Partial<import("../spec/title").Title>} */
|
|
22
|
-
const TRACK_TITLE_STYLE = {
|
|
23
|
-
orient: "left",
|
|
24
|
-
anchor: "middle",
|
|
25
|
-
align: "right",
|
|
26
|
-
baseline: "middle",
|
|
27
|
-
angle: 0,
|
|
28
|
-
fontSize: 12,
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
/** @type {Partial<import("../spec/title").Title>} */
|
|
32
|
-
const OVERLAY_TITLE_STYLE = {
|
|
33
|
-
orient: "top",
|
|
34
|
-
anchor: "start",
|
|
35
|
-
align: "left",
|
|
36
|
-
baseline: "top",
|
|
37
|
-
offset: -10,
|
|
38
|
-
dx: 10,
|
|
39
|
-
fontSize: 12,
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
/** @type {Record<import("../spec/title").TitleAnchor, number>} */
|
|
43
|
-
const ANCHORS = {
|
|
44
|
-
start: 0,
|
|
45
|
-
middle: 0.5,
|
|
46
|
-
end: 1,
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
/** @type {Record<import("../spec/title").TitleAnchor, import("../spec/font").Align>} */
|
|
50
|
-
const ANCHOR_TO_ALIGN = {
|
|
51
|
-
start: "left",
|
|
52
|
-
middle: "center",
|
|
53
|
-
end: "right",
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* @param {string | import("../spec/title").Title} title
|
|
58
|
-
* @returns {import("../spec/view").UnitSpec}
|
|
59
|
-
*/
|
|
60
|
-
export default function createTitle(title) {
|
|
61
|
-
if (!title) {
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/** @type {import("../spec/title").Title} */
|
|
66
|
-
const titleSpec = isString(title) ? { text: title } : title;
|
|
67
|
-
|
|
68
|
-
if (!titleSpec.text || titleSpec.orient == "none") {
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// TODO: Make these configurable
|
|
73
|
-
/** @type {Partial<import("../spec/title").Title>} */
|
|
74
|
-
const config =
|
|
75
|
-
{
|
|
76
|
-
"track-title": TRACK_TITLE_STYLE,
|
|
77
|
-
overlay: OVERLAY_TITLE_STYLE,
|
|
78
|
-
}[titleSpec.style] ?? {};
|
|
79
|
-
|
|
80
|
-
// TODO: frame prop
|
|
81
|
-
|
|
82
|
-
/** @type {import("../spec/title").Title} */
|
|
83
|
-
const preliminarySpec = {
|
|
84
|
-
...BASE_TITLE_STYLE,
|
|
85
|
-
...config,
|
|
86
|
-
...titleSpec,
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
/** @type {Partial<import("../spec/title").Title>} */
|
|
90
|
-
let orientConfig = {};
|
|
91
|
-
let xy = { x: 0, y: 0 };
|
|
92
|
-
|
|
93
|
-
const anchorPos = ANCHORS[preliminarySpec.anchor ?? "middle"];
|
|
94
|
-
|
|
95
|
-
switch (preliminarySpec.orient) {
|
|
96
|
-
case "top":
|
|
97
|
-
xy = { x: anchorPos, y: 1 };
|
|
98
|
-
orientConfig = { baseline: "alphabetic", angle: 0 };
|
|
99
|
-
break;
|
|
100
|
-
case "right":
|
|
101
|
-
xy = { x: 1, y: 1 - anchorPos };
|
|
102
|
-
orientConfig = { baseline: "alphabetic", angle: 90 };
|
|
103
|
-
break;
|
|
104
|
-
case "bottom":
|
|
105
|
-
xy = { x: anchorPos, y: 0 };
|
|
106
|
-
orientConfig = { baseline: "top", angle: 0 };
|
|
107
|
-
break;
|
|
108
|
-
case "left":
|
|
109
|
-
xy = { x: 0, y: anchorPos };
|
|
110
|
-
orientConfig = { baseline: "alphabetic", angle: -90 };
|
|
111
|
-
break;
|
|
112
|
-
default:
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/** @type {import("../spec/title").Title} */
|
|
116
|
-
const spec = {
|
|
117
|
-
...BASE_TITLE_STYLE,
|
|
118
|
-
...orientConfig,
|
|
119
|
-
...config,
|
|
120
|
-
...titleSpec,
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
const offsets = { xOffset: 0, yOffset: 0 };
|
|
124
|
-
switch (preliminarySpec.orient) {
|
|
125
|
-
case "top":
|
|
126
|
-
offsets.yOffset = -spec.offset;
|
|
127
|
-
break;
|
|
128
|
-
case "right":
|
|
129
|
-
offsets.xOffset = spec.offset;
|
|
130
|
-
break;
|
|
131
|
-
case "bottom":
|
|
132
|
-
offsets.yOffset = spec.offset;
|
|
133
|
-
break;
|
|
134
|
-
case "left":
|
|
135
|
-
offsets.xOffset = -spec.offset;
|
|
136
|
-
break;
|
|
137
|
-
default:
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
return {
|
|
141
|
-
configurableVisibility: false,
|
|
142
|
-
data: { values: [{}] },
|
|
143
|
-
mark: {
|
|
144
|
-
type: "text",
|
|
145
|
-
tooltip: null,
|
|
146
|
-
clip: false,
|
|
147
|
-
|
|
148
|
-
...xy,
|
|
149
|
-
...offsets,
|
|
150
|
-
|
|
151
|
-
text: spec.text,
|
|
152
|
-
|
|
153
|
-
align: spec.align ?? ANCHOR_TO_ALIGN[spec.anchor],
|
|
154
|
-
angle: spec.angle,
|
|
155
|
-
baseline: spec.baseline,
|
|
156
|
-
dx: spec.dx,
|
|
157
|
-
dy: spec.dy,
|
|
158
|
-
color: spec.color,
|
|
159
|
-
font: spec.font,
|
|
160
|
-
size: spec.fontSize,
|
|
161
|
-
fontStyle: spec.fontStyle,
|
|
162
|
-
fontWeight: spec.fontWeight,
|
|
163
|
-
},
|
|
164
|
-
};
|
|
165
|
-
}
|
package/src/view/unitView.js
DELETED
|
@@ -1,382 +0,0 @@
|
|
|
1
|
-
import RectMark from "../marks/rectMark";
|
|
2
|
-
import PointMark from "../marks/pointMark";
|
|
3
|
-
import RuleMark from "../marks/rule";
|
|
4
|
-
import LinkMark from "../marks/link";
|
|
5
|
-
import TextMark from "../marks/text";
|
|
6
|
-
|
|
7
|
-
import ContainerView from "./containerView";
|
|
8
|
-
import ScaleResolution from "./scaleResolution";
|
|
9
|
-
import {
|
|
10
|
-
isSecondaryChannel,
|
|
11
|
-
secondaryChannels,
|
|
12
|
-
isPositionalChannel,
|
|
13
|
-
isChannelDefWithScale,
|
|
14
|
-
primaryPositionalChannels,
|
|
15
|
-
getPrimaryChannel,
|
|
16
|
-
} from "../encoder/encoder";
|
|
17
|
-
import createDomain from "../utils/domainArray";
|
|
18
|
-
import AxisResolution from "./axisResolution";
|
|
19
|
-
import { isAggregateSamplesSpec } from "./viewFactory";
|
|
20
|
-
import { peek } from "../utils/arrayUtils";
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
*
|
|
24
|
-
* @type {Object.<string, typeof import("../marks/mark").default>}
|
|
25
|
-
* TODO: Find a proper place, make extendible
|
|
26
|
-
*/
|
|
27
|
-
export const markTypes = {
|
|
28
|
-
point: PointMark,
|
|
29
|
-
rect: RectMark,
|
|
30
|
-
rule: RuleMark,
|
|
31
|
-
link: LinkMark,
|
|
32
|
-
text: TextMark,
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* @typedef {import("../spec/channel").Channel} Channel
|
|
37
|
-
* @typedef {import("./view").default} View
|
|
38
|
-
* @typedef {import("./layerView").default} LayerView
|
|
39
|
-
* @typedef {import("../utils/domainArray").DomainArray} DomainArray
|
|
40
|
-
* @typedef {import("../encoder/accessor").Accessor} Accessor
|
|
41
|
-
* @typedef {import("../utils/layout/flexLayout").SizeDef} SizeDef
|
|
42
|
-
* @typedef {import("../spec/view").ResolutionTarget} ResolutionTarget
|
|
43
|
-
*
|
|
44
|
-
*/
|
|
45
|
-
export default class UnitView extends ContainerView {
|
|
46
|
-
/**
|
|
47
|
-
*
|
|
48
|
-
* @param {import("../spec/view").UnitSpec} spec
|
|
49
|
-
* @param {import("./viewUtils").ViewContext} context
|
|
50
|
-
* @param {import("./containerView").default} parent
|
|
51
|
-
* @param {string} name
|
|
52
|
-
*/
|
|
53
|
-
constructor(spec, context, parent, name) {
|
|
54
|
-
super(spec, context, parent, name);
|
|
55
|
-
|
|
56
|
-
this.spec = spec; // Set here again to keep types happy
|
|
57
|
-
|
|
58
|
-
const Mark = markTypes[this.getMarkType()];
|
|
59
|
-
if (Mark) {
|
|
60
|
-
/** @type {import("../marks/mark").default} */
|
|
61
|
-
this.mark = new Mark(this);
|
|
62
|
-
} else {
|
|
63
|
-
throw new Error(`No such mark: ${this.getMarkType()}`);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/** @type {(UnitView | LayerView)[]} */
|
|
67
|
-
this.sampleAggregateViews = [];
|
|
68
|
-
this._initializeAggregateViews();
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Not nice! Inconsistent when faceting!
|
|
72
|
-
* TODO: Something. Maybe store only width/height
|
|
73
|
-
* @type {import("../utils/layout/rectangle").default}
|
|
74
|
-
*/
|
|
75
|
-
this.coords = undefined;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* @returns {IterableIterator<View>}
|
|
80
|
-
*/
|
|
81
|
-
*[Symbol.iterator]() {
|
|
82
|
-
for (const child of this.sampleAggregateViews) {
|
|
83
|
-
yield child;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* @param {View} child
|
|
89
|
-
* @param {View} replacement
|
|
90
|
-
*/
|
|
91
|
-
replaceChild(child, replacement) {
|
|
92
|
-
const i = this.sampleAggregateViews.indexOf(child);
|
|
93
|
-
if (i >= 0) {
|
|
94
|
-
this.sampleAggregateViews[i] = replacement;
|
|
95
|
-
} else {
|
|
96
|
-
throw new Error("Not my child view!");
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* @param {import("./renderingContext/viewRenderingContext").default} context
|
|
102
|
-
* @param {import("../utils/layout/rectangle").default} coords
|
|
103
|
-
* @param {import("./view").RenderingOptions} [options]
|
|
104
|
-
*/
|
|
105
|
-
render(context, coords, options = {}) {
|
|
106
|
-
if (!this.isVisible()) {
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
this.coords = coords;
|
|
111
|
-
|
|
112
|
-
context.pushView(this, coords);
|
|
113
|
-
context.renderMark(this.mark, options);
|
|
114
|
-
context.popView(this);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
getMarkType() {
|
|
118
|
-
return typeof this.spec.mark == "object"
|
|
119
|
-
? this.spec.mark.type
|
|
120
|
-
: this.spec.mark;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Pulls scales and axes up in the view hierarcy according to the resolution rules.
|
|
125
|
-
* TODO: legends
|
|
126
|
-
*
|
|
127
|
-
* @param {ResolutionTarget} type
|
|
128
|
-
*/
|
|
129
|
-
resolve(type) {
|
|
130
|
-
// TODO: Complain about nonsensical configuration, e.g. shared parent has independent children.
|
|
131
|
-
|
|
132
|
-
const encoding = this.mark.encoding;
|
|
133
|
-
|
|
134
|
-
for (const [channel, channelDef] of Object.entries(encoding)) {
|
|
135
|
-
if (!isChannelDefWithScale(channelDef)) {
|
|
136
|
-
continue;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
let targetChannel = getPrimaryChannel(
|
|
140
|
-
channelDef.resolutionChannel ?? channel
|
|
141
|
-
);
|
|
142
|
-
|
|
143
|
-
if (type == "axis" && !isPositionalChannel(targetChannel)) {
|
|
144
|
-
continue;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// eslint-disable-next-line consistent-this
|
|
148
|
-
let view = this;
|
|
149
|
-
while (
|
|
150
|
-
view.parent instanceof ContainerView &&
|
|
151
|
-
["shared", "excluded"].includes(
|
|
152
|
-
view.parent.getConfiguredOrDefaultResolution(
|
|
153
|
-
targetChannel,
|
|
154
|
-
type
|
|
155
|
-
)
|
|
156
|
-
) &&
|
|
157
|
-
view.getConfiguredOrDefaultResolution(targetChannel, type) !=
|
|
158
|
-
"excluded"
|
|
159
|
-
) {
|
|
160
|
-
// @ts-ignore
|
|
161
|
-
view = view.parent;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
if (!view.resolutions[type][targetChannel]) {
|
|
165
|
-
view.resolutions[type][targetChannel] =
|
|
166
|
-
type == "scale"
|
|
167
|
-
? new ScaleResolution(targetChannel)
|
|
168
|
-
: new AxisResolution(targetChannel);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// Looks silly, but keeps type checking happy
|
|
172
|
-
if (isPositionalChannel(channel)) {
|
|
173
|
-
view.resolutions[type][targetChannel].pushUnitView(
|
|
174
|
-
this,
|
|
175
|
-
channel
|
|
176
|
-
);
|
|
177
|
-
} else if (type == "scale") {
|
|
178
|
-
view.resolutions[type][targetChannel].pushUnitView(
|
|
179
|
-
this,
|
|
180
|
-
channel
|
|
181
|
-
);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
*
|
|
188
|
-
* @param {import("./view").Channel} channel
|
|
189
|
-
*/
|
|
190
|
-
getAccessor(channel) {
|
|
191
|
-
return this._cache("accessor/" + channel, () => {
|
|
192
|
-
const encoding = this.mark.encoding; // Mark provides encodings with defaults and possible modifications
|
|
193
|
-
if (encoding && encoding[channel]) {
|
|
194
|
-
return this.context.accessorFactory.createAccessor(
|
|
195
|
-
encoding[channel]
|
|
196
|
-
);
|
|
197
|
-
}
|
|
198
|
-
});
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Returns an accessor that returns a (composite) key for partitioning the data
|
|
203
|
-
*
|
|
204
|
-
* @param {View} [whoIsAsking]
|
|
205
|
-
* @returns {function(object):any}
|
|
206
|
-
*/
|
|
207
|
-
getFacetAccessor(whoIsAsking) {
|
|
208
|
-
// TODO: Rewrite, call getFacetFields
|
|
209
|
-
const sampleAccessor = this.getAccessor("sample");
|
|
210
|
-
if (sampleAccessor) {
|
|
211
|
-
return sampleAccessor;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
return super.getFacetAccessor(this);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Returns a collector that is associated with this view.
|
|
219
|
-
*/
|
|
220
|
-
getCollector() {
|
|
221
|
-
return this.context.dataFlow.findCollectorByKey(this);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* @param {Channel} channel A primary channel
|
|
226
|
-
*/
|
|
227
|
-
_validateDomainQuery(channel) {
|
|
228
|
-
if (isSecondaryChannel(channel)) {
|
|
229
|
-
throw new Error(
|
|
230
|
-
`getDomain(${channel}), must only be called for primary channels!`
|
|
231
|
-
);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
const channelDef = this.mark.encoding[channel];
|
|
235
|
-
// TODO: Broken. Fix.
|
|
236
|
-
if (!isChannelDefWithScale(channelDef)) {
|
|
237
|
-
throw new Error("The channel has no scale, cannot get domain!");
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
return channelDef;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
/**
|
|
244
|
-
* Returns the domain of the specified channel of this domain/mark.
|
|
245
|
-
*
|
|
246
|
-
* @param {Channel} channel A primary channel
|
|
247
|
-
* @returns {DomainArray}
|
|
248
|
-
*/
|
|
249
|
-
getConfiguredDomain(channel) {
|
|
250
|
-
const channelDef = this._validateDomainQuery(channel);
|
|
251
|
-
|
|
252
|
-
const specDomain =
|
|
253
|
-
channelDef && channelDef.scale && channelDef.scale.domain;
|
|
254
|
-
if (specDomain) {
|
|
255
|
-
const scaleResolution = this.getScaleResolution(
|
|
256
|
-
channelDef.resolutionChannel ?? channel
|
|
257
|
-
);
|
|
258
|
-
return createDomain(
|
|
259
|
-
channelDef.type ?? "nominal",
|
|
260
|
-
// Chrom/pos must be linearized first
|
|
261
|
-
scaleResolution.fromComplexInterval(specDomain)
|
|
262
|
-
);
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
/**
|
|
267
|
-
* Extracts the domain from the data.
|
|
268
|
-
*
|
|
269
|
-
* TODO: Optimize! Now this performs redundant work if multiple views share the same collector.
|
|
270
|
-
* Also, all relevant fields should be processed in one iteration: https://jsbench.me/y5kkqy52jo/1
|
|
271
|
-
* In fact, domain extraction could be a responsibility of the collector: As it handles data items,
|
|
272
|
-
* it extracts domains for all fields (and data types) that need extracted domains.
|
|
273
|
-
* Alternatively, extractor nodes could be added to the data flow, just like Vega does
|
|
274
|
-
* (with aggregate and extent).
|
|
275
|
-
*
|
|
276
|
-
* @param {Channel} channel
|
|
277
|
-
* @returns {DomainArray}
|
|
278
|
-
*/
|
|
279
|
-
extractDataDomain(channel) {
|
|
280
|
-
const channelDef = this._validateDomainQuery(channel);
|
|
281
|
-
const type = channelDef.type ?? "nominal"; // TODO: Should check that this is a channel without scale
|
|
282
|
-
|
|
283
|
-
/** @param {Channel} channel */
|
|
284
|
-
const extract = (channel) => {
|
|
285
|
-
/** @type {DomainArray} */
|
|
286
|
-
let domain;
|
|
287
|
-
|
|
288
|
-
const encodingSpec = this.mark.encoding[channel];
|
|
289
|
-
|
|
290
|
-
if (encodingSpec) {
|
|
291
|
-
const accessor =
|
|
292
|
-
this.context.accessorFactory.createAccessor(encodingSpec);
|
|
293
|
-
if (accessor) {
|
|
294
|
-
domain = createDomain(type);
|
|
295
|
-
|
|
296
|
-
if (accessor.constant) {
|
|
297
|
-
domain.extend(accessor({}));
|
|
298
|
-
} else {
|
|
299
|
-
const collector = this.getCollector();
|
|
300
|
-
if (collector?.completed) {
|
|
301
|
-
collector.visitData((d) =>
|
|
302
|
-
domain.extend(accessor(d))
|
|
303
|
-
);
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
return domain;
|
|
309
|
-
};
|
|
310
|
-
|
|
311
|
-
let domain = extract(channel);
|
|
312
|
-
|
|
313
|
-
const secondaryChannel = secondaryChannels[channel];
|
|
314
|
-
if (secondaryChannel) {
|
|
315
|
-
const secondaryDomain = extract(secondaryChannel);
|
|
316
|
-
if (secondaryDomain) {
|
|
317
|
-
domain.extendAll(secondaryDomain);
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
return domain;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
getZoomLevel() {
|
|
325
|
-
/** @param {Channel} channel */
|
|
326
|
-
const getZoomLevel = (channel) =>
|
|
327
|
-
this.getScaleResolution(channel)?.getZoomLevel() ?? 1.0;
|
|
328
|
-
|
|
329
|
-
return primaryPositionalChannels
|
|
330
|
-
.map(getZoomLevel)
|
|
331
|
-
.reduce((a, c) => a * c, 1);
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
_initializeAggregateViews() {
|
|
335
|
-
if (isAggregateSamplesSpec(this.spec)) {
|
|
336
|
-
// TODO: Support multiple
|
|
337
|
-
for (const sumSpec of this.spec.aggregateSamples) {
|
|
338
|
-
const transform = sumSpec.transform ?? [];
|
|
339
|
-
if (transform.length && peek(transform).type != "collect") {
|
|
340
|
-
// MergeFacets must be a direct child of Collector
|
|
341
|
-
transform.push({ type: "collect" });
|
|
342
|
-
}
|
|
343
|
-
transform.push({ type: "mergeFacets" });
|
|
344
|
-
sumSpec.transform = transform;
|
|
345
|
-
|
|
346
|
-
sumSpec.encoding = {
|
|
347
|
-
...(sumSpec.encoding ?? {}),
|
|
348
|
-
sample: null,
|
|
349
|
-
};
|
|
350
|
-
|
|
351
|
-
const summaryView =
|
|
352
|
-
/** @type { UnitView | LayerView | DecoratorView } */ (
|
|
353
|
-
this.context.createView(sumSpec, this, "summaryView")
|
|
354
|
-
);
|
|
355
|
-
|
|
356
|
-
/**
|
|
357
|
-
* @param {View} [whoIsAsking]
|
|
358
|
-
*/
|
|
359
|
-
summaryView.getFacetFields = (whoIsAsking) => undefined;
|
|
360
|
-
|
|
361
|
-
this.sampleAggregateViews.push(summaryView);
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
/**
|
|
367
|
-
* @param {import("../utils/interactionEvent").default} event
|
|
368
|
-
*/
|
|
369
|
-
propagateInteractionEvent(event) {
|
|
370
|
-
event.target = this;
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
/**
|
|
374
|
-
* @param {string} channel
|
|
375
|
-
* @param {import("./containerView").ResolutionTarget} resolutionType
|
|
376
|
-
* @returns {import("../spec/view").ResolutionBehavior}
|
|
377
|
-
*/
|
|
378
|
-
getDefaultResolution(channel, resolutionType) {
|
|
379
|
-
// This affects the sample aggregate views.
|
|
380
|
-
return channel == "x" ? "shared" : "independent";
|
|
381
|
-
}
|
|
382
|
-
}
|