@fjader/svelte 0.2.2 → 0.2.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/components/axes/BandAxisTicks.svelte +63 -24
- package/dist/components/axes/BandAxisTicks.svelte.d.ts +5 -5
- package/dist/components/charts/ChartContainer.svelte +2 -1
- package/dist/components/guides/legend/ContinuousColorLegend.svelte +2 -1
- package/dist/components/guides/legend/OrdinalColorLegend.svelte +92 -34
- package/dist/components/marks/AreaMarkX.svelte +19 -6
- package/dist/components/marks/AreaMarkY.svelte +19 -6
- package/dist/components/marks/BarMarkX.svelte +3 -0
- package/dist/components/marks/BarMarkY.svelte +3 -0
- package/dist/components/marks/DotsMark.svelte +3 -0
- package/dist/components/marks/LineMark.svelte +3 -0
- package/dist/components/marks/ParallelCoordinatesMark.svelte +6 -0
- package/dist/components/marks/ParallelCoordinatesMark.svelte.d.ts +3 -0
- package/dist/components/marks/RectMark.svelte +3 -0
- package/dist/components/marks/RectXMark.svelte +3 -0
- package/dist/components/marks/RectYMark.svelte +3 -0
- package/dist/components/marks/RuleMarkX.svelte +10 -2
- package/dist/components/marks/RuleMarkY.svelte +10 -2
- package/dist/components/marks/TextMark.svelte +68 -4
- package/dist/components/marks/lifecycle/MarkLifecycleV2.svelte.d.ts +15 -1
- package/dist/components/marks/lifecycle/MarkLifecycleV2.svelte.js +116 -27
- package/dist/components/marks/lifecycle/domain-queries.js +13 -11
- package/dist/components/marks/lifecycle/transform-scale-key.d.ts +16 -0
- package/dist/components/marks/lifecycle/transform-scale-key.js +27 -0
- package/dist/components/marks/utils/area-outline.d.ts +24 -0
- package/dist/components/marks/utils/area-outline.js +10 -0
- package/dist/components/marks/utils/reactive-config.d.ts +1 -1
- package/dist/components/marks/utils/reactive-config.js +3 -0
- package/dist/components/rendering/Areas.svelte +30 -6
- package/dist/components/rendering/Areas.svelte.d.ts +2 -0
- package/dist/components/rendering/BaseGPURenderer.svelte.js +4 -1
- package/dist/components/rendering/Dots.svelte +24 -3
- package/dist/components/rendering/Dots.svelte.d.ts +2 -0
- package/dist/components/rendering/GridLine.svelte +2 -1
- package/dist/components/rendering/Lines.svelte +49 -7
- package/dist/components/rendering/Lines.svelte.d.ts +9 -0
- package/dist/components/rendering/ParallelLines.svelte +26 -7
- package/dist/components/rendering/ParallelLines.svelte.d.ts +2 -0
- package/dist/components/rendering/Rects.svelte +20 -5
- package/dist/components/rendering/Rects.svelte.d.ts +2 -0
- package/dist/components/rendering/RuleX.svelte +20 -5
- package/dist/components/rendering/RuleX.svelte.d.ts +2 -0
- package/dist/components/rendering/RuleY.svelte +20 -5
- package/dist/components/rendering/RuleY.svelte.d.ts +2 -0
- package/dist/components/rendering/activity-reads.d.ts +93 -0
- package/dist/components/rendering/activity-reads.js +135 -0
- package/dist/components/rendering/uniform-sizes.d.ts +26 -0
- package/dist/components/rendering/uniform-sizes.js +28 -0
- package/dist/config/ChartConfig.svelte.d.ts +2 -0
- package/dist/gpu/ColorScaleShaderLib.d.ts +13 -1
- package/dist/gpu/ColorScaleShaderLib.js +56 -5
- package/dist/gpu/GPUCoordinator.svelte.d.ts +8 -0
- package/dist/gpu/GPUCoordinator.svelte.js +68 -32
- package/dist/gpu/ResolveShader.d.ts +2 -2
- package/dist/gpu/ResolveShader.js +2 -2
- package/dist/gpu/ScaleTemplateSystem.d.ts +19 -0
- package/dist/gpu/ScaleTemplateSystem.js +86 -7
- package/dist/gpu/SizeScaleShaderLib.d.ts +4 -4
- package/dist/gpu/SizeScaleShaderLib.js +4 -4
- package/dist/gpu/identity-slot-packing.d.ts +157 -40
- package/dist/gpu/identity-slot-packing.js +262 -62
- package/dist/gpu/tracked-scales.d.ts +14 -0
- package/dist/gpu/tracked-scales.js +18 -0
- package/dist/index.js +1 -0
- package/dist/interactors/BandLabelToggle.svelte +5 -9
- package/dist/interactors/BandLabelToggle.svelte.d.ts +3 -3
- package/dist/interactors/DerivedInterval1D.svelte +26 -54
- package/dist/interactors/Interval1D.svelte +2 -1
- package/dist/interactors/Interval2D.svelte +2 -1
- package/dist/interactors/ParallelAxisSource.svelte +4 -4
- package/dist/interactors/ParallelAxisSource.svelte.d.ts +2 -1
- package/dist/interactors/ParallelBrushes.svelte +8 -9
- package/dist/interactors/ParallelBrushes.svelte.d.ts +3 -3
- package/dist/interactors/Toggle.svelte +17 -36
- package/dist/interactors/Toggle.svelte.d.ts +4 -3
- package/dist/interactors/Tooltip.svelte +2 -1
- package/dist/interactors/TooltipManager.svelte.js +8 -3
- package/dist/interactors/relay-clauses.d.ts +23 -0
- package/dist/interactors/relay-clauses.js +60 -0
- package/dist/query-engine/CrossfilterSelection.svelte.d.ts +88 -15
- package/dist/query-engine/CrossfilterSelection.svelte.js +94 -20
- package/dist/query-engine/FieldActivity.svelte.d.ts +79 -0
- package/dist/query-engine/FieldActivity.svelte.js +207 -0
- package/dist/query-engine/FilterGroup.svelte.d.ts +53 -29
- package/dist/query-engine/FilterGroup.svelte.js +181 -122
- package/dist/query-engine/FilterGroupRegistry.svelte.d.ts +42 -0
- package/dist/query-engine/FilterGroupRegistry.svelte.js +103 -1
- package/dist/query-engine/MarkHandle.svelte.d.ts +9 -1
- package/dist/query-engine/MarkHandle.svelte.js +12 -2
- package/dist/query-engine/QueryEngine.d.ts +52 -16
- package/dist/query-engine/QueryEngine.js +90 -28
- package/dist/query-engine/categorical-identity.d.ts +99 -27
- package/dist/query-engine/categorical-identity.js +210 -51
- package/dist/query-engine/index.d.ts +2 -1
- package/dist/query-engine/index.js +1 -0
- package/dist/query-engine/preagg/Preagg.d.ts +1 -1
- package/dist/query-engine/preagg/Preagg.js +11 -9
- package/dist/query-engine/preagg/plan.d.ts +9 -5
- package/dist/query-engine/preagg/plan.js +13 -11
- package/dist/query-engine/toggle-predicate.js +12 -1
- package/dist/scales/ActivityTable.d.ts +99 -0
- package/dist/scales/ActivityTable.js +211 -0
- package/dist/scales/BandScaleState.svelte.d.ts +28 -7
- package/dist/scales/BandScaleState.svelte.js +55 -20
- package/dist/scales/ChartScales.svelte.d.ts +2 -2
- package/dist/scales/ColorScaleState.svelte.d.ts +36 -8
- package/dist/scales/ColorScaleState.svelte.js +118 -24
- package/dist/scales/DomainResolver.d.ts +2 -0
- package/dist/scales/DomainResolver.js +15 -8
- package/dist/scales/ScaleRegistry.svelte.d.ts +9 -0
- package/dist/scales/ScaleRegistry.svelte.js +22 -1
- package/dist/scales/TimeScaleState.svelte.js +7 -1
- package/dist/spec/index.js +1 -0
- package/dist/spec/types.d.ts +2 -0
- package/dist/transforms/index.d.ts +27 -0
- package/dist/transforms/index.js +97 -3
- package/dist/types.d.ts +30 -0
- package/package.json +1 -1
|
@@ -42,10 +42,11 @@ export async function fetchCategoricalDomains(coordinator, table, select, actual
|
|
|
42
42
|
//
|
|
43
43
|
// - Order. DISTINCT has no ORDER BY, so today's domain is whatever DuckDB
|
|
44
44
|
// returned, then "first-appearance order" in updateDomainFromExtents.
|
|
45
|
-
// Arbitrary. Dim
|
|
46
|
-
// deterministic
|
|
47
|
-
//
|
|
48
|
-
//
|
|
45
|
+
// Arbitrary. Dim values are listed in id order, so the domain is
|
|
46
|
+
// deterministic. It is the real categories only (`categoryValues`
|
|
47
|
+
// leaves out Other buckets), so position-in-domain equals the dim id
|
|
48
|
+
// only until a bucket's row: the scale encodes each value to its id
|
|
49
|
+
// rather than relying on position.
|
|
49
50
|
// - Multi-table. The dim spans every table registering the field, so two
|
|
50
51
|
// marks on one shared scale agree on the category set by construction.
|
|
51
52
|
//
|
|
@@ -63,10 +64,11 @@ export async function fetchCategoricalDomains(coordinator, table, select, actual
|
|
|
63
64
|
fetches.push((async () => {
|
|
64
65
|
// Idempotent and coalesced — the mark's own setup calls this too.
|
|
65
66
|
await coordinator.ensureColumns(table, { categorical: [identityField] });
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
//
|
|
69
|
-
//
|
|
67
|
+
// This table's categories: the dim spans every table on the field.
|
|
68
|
+
const categories = coordinator.categoryValues(identityField.key, table);
|
|
69
|
+
// A snapshot of the real categories. The scale adopts the live
|
|
70
|
+
// identity itself in MarkLifecycleV2's #ensureIdentityColumns, which
|
|
71
|
+
// also covers the explicit-domain axes that never reach this branch.
|
|
70
72
|
if (categories.length > 0)
|
|
71
73
|
scaleState.addMark(categories, markId);
|
|
72
74
|
})());
|
|
@@ -121,7 +123,7 @@ export async function fetchCategoricalDomains(coordinator, table, select, actual
|
|
|
121
123
|
fetches.push((async () => {
|
|
122
124
|
// Idempotent and coalesced — the mark's own setup calls this too.
|
|
123
125
|
await coordinator.ensureColumns(table, { categorical: [facetKey] });
|
|
124
|
-
const categories = coordinator.
|
|
126
|
+
const categories = coordinator.categoryValues(facetKey.key, table);
|
|
125
127
|
if (categories.length > 0)
|
|
126
128
|
facetBandScale.addMark(categories, markId);
|
|
127
129
|
})());
|
|
@@ -185,7 +187,7 @@ export async function fetchCategoricalDomains(coordinator, table, select, actual
|
|
|
185
187
|
fetches.push((async () => {
|
|
186
188
|
// Idempotent and coalesced — the mark's own setup calls this too.
|
|
187
189
|
await coordinator.ensureColumns(table, { categorical: [colorIdentity] });
|
|
188
|
-
const categories = coordinator.
|
|
190
|
+
const categories = coordinator.categoryValues(colorIdentity.key);
|
|
189
191
|
if (categories.length > 0) {
|
|
190
192
|
colorScaleState.setDomain(categories);
|
|
191
193
|
}
|
|
@@ -234,7 +236,7 @@ export async function fetchCategoricalDomains(coordinator, table, select, actual
|
|
|
234
236
|
if (seriesIdentity) {
|
|
235
237
|
fetches.push((async () => {
|
|
236
238
|
await coordinator.ensureColumns(table, { categorical: [seriesIdentity] });
|
|
237
|
-
const categories = coordinator.
|
|
239
|
+
const categories = coordinator.categoryValues(seriesIdentity.key);
|
|
238
240
|
if (categories.length > 0) {
|
|
239
241
|
seriesScaleState.setDomain(categories);
|
|
240
242
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `transformKey` a mark with a category-reducing transform (topN) adds to
|
|
3
|
+
* its band scale's config, which is part of the scale's registry key.
|
|
4
|
+
*
|
|
5
|
+
* It names the table, the transform (N included) and the chart. A topN axis
|
|
6
|
+
* shows the categories its own query returned, and a band scale resolves the
|
|
7
|
+
* union of every mark registered on it, so two charts may share one only if
|
|
8
|
+
* they always return the same categories. Two charts with the identical topN
|
|
9
|
+
* do not: they receive different filters (a brush skips its own chart), and a
|
|
10
|
+
* shared scale would show each the other's top N as empty slots, and share one
|
|
11
|
+
* Other bucket between two different sets of members.
|
|
12
|
+
*
|
|
13
|
+
* The chart is its ChartConfig object, which a faceted chart's cells share, so
|
|
14
|
+
* facets keep one axis; a bar and its value labels in one chart share one too.
|
|
15
|
+
*/
|
|
16
|
+
export declare function transformScaleKey(table: string, transformKey: string, chart: object | null | undefined): string;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `transformKey` a mark with a category-reducing transform (topN) adds to
|
|
3
|
+
* its band scale's config, which is part of the scale's registry key.
|
|
4
|
+
*
|
|
5
|
+
* It names the table, the transform (N included) and the chart. A topN axis
|
|
6
|
+
* shows the categories its own query returned, and a band scale resolves the
|
|
7
|
+
* union of every mark registered on it, so two charts may share one only if
|
|
8
|
+
* they always return the same categories. Two charts with the identical topN
|
|
9
|
+
* do not: they receive different filters (a brush skips its own chart), and a
|
|
10
|
+
* shared scale would show each the other's top N as empty slots, and share one
|
|
11
|
+
* Other bucket between two different sets of members.
|
|
12
|
+
*
|
|
13
|
+
* The chart is its ChartConfig object, which a faceted chart's cells share, so
|
|
14
|
+
* facets keep one axis; a bar and its value labels in one chart share one too.
|
|
15
|
+
*/
|
|
16
|
+
const chartKeys = new WeakMap();
|
|
17
|
+
let nextChartKey = 0;
|
|
18
|
+
/** A name for a chart, stable while its ChartConfig lives, shared by its cells. */
|
|
19
|
+
function chartKeyOf(chart) {
|
|
20
|
+
let key = chartKeys.get(chart);
|
|
21
|
+
if (!key)
|
|
22
|
+
chartKeys.set(chart, (key = `chart${nextChartKey++}`));
|
|
23
|
+
return key;
|
|
24
|
+
}
|
|
25
|
+
export function transformScaleKey(table, transformKey, chart) {
|
|
26
|
+
return chart ? `${table}:${transformKey}@${chartKeyOf(chart)}` : `${table}:${transformKey}`;
|
|
27
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How an area's outline is coloured, and which colour its selection activity
|
|
3
|
+
* is read through.
|
|
4
|
+
*
|
|
5
|
+
* The outline is drawn in the fill's colour, or in a constant `stroke`. Either
|
|
6
|
+
* way its activity is the fill's: the area dims as one shape when a selection
|
|
7
|
+
* on its colour field dims the fill, outline included. Before activity was per
|
|
8
|
+
* field the unselected areas were filtered away, outlines with them; drawn in a
|
|
9
|
+
* constant colour, an outline reading its own colour would read no activity and
|
|
10
|
+
* stay opaque over its dimmed fill.
|
|
11
|
+
*/
|
|
12
|
+
export interface OutlineColor {
|
|
13
|
+
/** The values the outline's colour buffer holds: the fill's, always. */
|
|
14
|
+
colorValueData: Float32Array | null;
|
|
15
|
+
colorMode: number;
|
|
16
|
+
colorScaleIndex: number;
|
|
17
|
+
activityColorMode: number;
|
|
18
|
+
activityColorScaleIndex: number;
|
|
19
|
+
}
|
|
20
|
+
export declare function outlineColor(stroke: unknown, fill: {
|
|
21
|
+
data: Float32Array | null;
|
|
22
|
+
colorMode: number;
|
|
23
|
+
colorScaleIndex: number;
|
|
24
|
+
}): OutlineColor;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function outlineColor(stroke, fill) {
|
|
2
|
+
const constant = !!stroke;
|
|
3
|
+
return {
|
|
4
|
+
colorValueData: fill.data,
|
|
5
|
+
colorMode: constant ? 0 : fill.colorMode,
|
|
6
|
+
colorScaleIndex: constant ? 0 : fill.colorScaleIndex,
|
|
7
|
+
activityColorMode: fill.colorMode,
|
|
8
|
+
activityColorScaleIndex: fill.colorScaleIndex
|
|
9
|
+
};
|
|
10
|
+
}
|
|
@@ -12,6 +12,6 @@ import type { MarkEntry } from '../../../config/ChartConfig.svelte';
|
|
|
12
12
|
* @param entry - The mark entry (reactive props from ChartConfig)
|
|
13
13
|
* @param opts.resolveFitDomain - Getter for resolved fitDomain (deferred read)
|
|
14
14
|
*/
|
|
15
|
-
export declare function buildReactiveConfig(entry: Partial<Pick<MarkEntry, 'sort' | 'limit' | 'domain' | 'tooltip' | 'tip' | 'fitDomain'>>, opts?: {
|
|
15
|
+
export declare function buildReactiveConfig(entry: Partial<Pick<MarkEntry, 'sort' | 'limit' | 'domain' | 'tooltip' | 'tip' | 'fitDomain' | 'selectionResponse'>>, opts?: {
|
|
16
16
|
resolveFitDomain?: () => 'x' | 'y' | boolean | undefined;
|
|
17
17
|
}): ReactiveConfig;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { activityReads, colorActivityWGSL } from './activity-reads';
|
|
3
|
+
import { UNIFORM_BYTES } from './uniform-sizes';
|
|
2
4
|
import { getContext, onMount, onDestroy } from 'svelte';
|
|
3
5
|
import { RendererHost } from './RendererHost.svelte';
|
|
4
6
|
import { getGPUContext } from '../../gpu';
|
|
@@ -25,7 +27,7 @@
|
|
|
25
27
|
FACET: 6
|
|
26
28
|
};
|
|
27
29
|
|
|
28
|
-
// Uniform struct offsets (matching WGSL MarkConstants
|
|
30
|
+
// Uniform struct offsets (matching WGSL MarkConstants; size in uniform-sizes.ts)
|
|
29
31
|
const UNIFORM_OFFSETS = {
|
|
30
32
|
POINT_COUNT: 0, // u32
|
|
31
33
|
COLOR_MODE: 4, // u32
|
|
@@ -35,7 +37,8 @@
|
|
|
35
37
|
FILL_OPACITY: 32, // f32
|
|
36
38
|
DOT_RADIUS: 36, // f32
|
|
37
39
|
SHOW_BOTTOM_DOTS: 40, // u32 (0 or 1)
|
|
38
|
-
FULL_DOMAIN_SPAN: 44 // f32
|
|
40
|
+
FULL_DOMAIN_SPAN: 44, // f32
|
|
41
|
+
GROUP_INDEX: 48 // u32
|
|
39
42
|
};
|
|
40
43
|
|
|
41
44
|
interface Props {
|
|
@@ -55,6 +58,8 @@
|
|
|
55
58
|
orientation?: 'vertical' | 'horizontal';
|
|
56
59
|
colorMode?: number;
|
|
57
60
|
colorScaleIndex?: number;
|
|
61
|
+
/** The page-wide index of this mark's filter group: which run of a field's activity block it reads. */
|
|
62
|
+
groupIndex?: number;
|
|
58
63
|
constantColor?: [number, number, number, number];
|
|
59
64
|
markId?: string;
|
|
60
65
|
}
|
|
@@ -76,6 +81,7 @@
|
|
|
76
81
|
orientation = 'vertical',
|
|
77
82
|
colorMode = 0,
|
|
78
83
|
colorScaleIndex = 0,
|
|
84
|
+
groupIndex = 0,
|
|
79
85
|
constantColor = DEFAULT_FILL_COLOR,
|
|
80
86
|
markId = ''
|
|
81
87
|
}: Props = $props();
|
|
@@ -87,6 +93,9 @@
|
|
|
87
93
|
const baseMarkType = curve === 'linear' ? 'areas' : `areas-${curve}`;
|
|
88
94
|
const effectiveMarkType = faceted ? `${baseMarkType}-faceted` : baseMarkType;
|
|
89
95
|
|
|
96
|
+
/** The selection activity this shader reads; routing reads the same table. */
|
|
97
|
+
const ACTIVITY_READS = activityReads('areas');
|
|
98
|
+
|
|
90
99
|
// --- Facet compile-time specialization ---
|
|
91
100
|
// Areas uses a storage buffer (not a vertex attribute) for facet indices because
|
|
92
101
|
// the boundary check needs random access: facetIndices[nextIdx] to detect when
|
|
@@ -141,7 +150,11 @@
|
|
|
141
150
|
fillOpacity: f32,
|
|
142
151
|
dotRadius: f32,
|
|
143
152
|
showBottomDots: u32,
|
|
144
|
-
fullDomainSpan: f32
|
|
153
|
+
fullDomainSpan: f32,
|
|
154
|
+
groupIndex: u32, // Page-wide filter group index, for activity reads
|
|
155
|
+
_pad0: u32,
|
|
156
|
+
_pad1: u32,
|
|
157
|
+
_pad2: u32
|
|
145
158
|
};
|
|
146
159
|
@group(1) @binding(5) var<uniform> markConstants: MarkConstants;
|
|
147
160
|
|
|
@@ -241,7 +254,12 @@
|
|
|
241
254
|
var output: VertexOutput;
|
|
242
255
|
output.position = pixelsToClip(pos);
|
|
243
256
|
output.colorValue = colorValues[instanceIdx];
|
|
244
|
-
output.alpha =
|
|
257
|
+
output.alpha = selectionDim(
|
|
258
|
+
${colorActivityWGSL(ACTIVITY_READS, {
|
|
259
|
+
color: 'markConstants.colorMode, markConstants.colorScaleIndex, colorValues[instanceIdx]',
|
|
260
|
+
group: 'markConstants.groupIndex'
|
|
261
|
+
})}
|
|
262
|
+
);
|
|
245
263
|
output.circleUV = quadCorner;
|
|
246
264
|
output.circleRadius = circleR;
|
|
247
265
|
return output;
|
|
@@ -341,7 +359,12 @@
|
|
|
341
359
|
var output: VertexOutput;
|
|
342
360
|
output.position = pixelsToClip(finalPos);
|
|
343
361
|
output.colorValue = colorValues[currIdx];
|
|
344
|
-
output.alpha = markConstants.fillOpacity
|
|
362
|
+
output.alpha = markConstants.fillOpacity * selectionDim(
|
|
363
|
+
${colorActivityWGSL(ACTIVITY_READS, {
|
|
364
|
+
color: 'markConstants.colorMode, markConstants.colorScaleIndex, colorValues[currIdx]',
|
|
365
|
+
group: 'markConstants.groupIndex'
|
|
366
|
+
})}
|
|
367
|
+
);
|
|
345
368
|
output.circleUV = vec2<f32>(-2.0, -2.0);
|
|
346
369
|
output.circleRadius = 0.0;
|
|
347
370
|
return output;
|
|
@@ -440,13 +463,14 @@
|
|
|
440
463
|
// re-fires once data loads.
|
|
441
464
|
if (colorMode === 1 && !colorValueData) return;
|
|
442
465
|
|
|
443
|
-
const buffer = new ArrayBuffer(
|
|
466
|
+
const buffer = new ArrayBuffer(UNIFORM_BYTES.areasMarkConstants);
|
|
444
467
|
const view = new DataView(buffer);
|
|
445
468
|
const LE = true;
|
|
446
469
|
|
|
447
470
|
view.setUint32(UNIFORM_OFFSETS.POINT_COUNT, dimData ? dimData.length : 0, LE);
|
|
448
471
|
view.setUint32(UNIFORM_OFFSETS.COLOR_MODE, colorMode, LE);
|
|
449
472
|
view.setUint32(UNIFORM_OFFSETS.COLOR_SCALE_INDEX, colorScaleIndex, LE);
|
|
473
|
+
view.setUint32(UNIFORM_OFFSETS.GROUP_INDEX, groupIndex, LE);
|
|
450
474
|
view.setUint32(UNIFORM_OFFSETS.ORIENTATION, orientation === 'horizontal' ? 1 : 0, LE);
|
|
451
475
|
view.setFloat32(UNIFORM_OFFSETS.CONSTANT_COLOR + 0, constantColor[0], LE);
|
|
452
476
|
view.setFloat32(UNIFORM_OFFSETS.CONSTANT_COLOR + 4, constantColor[1], LE);
|
|
@@ -16,6 +16,8 @@ interface Props {
|
|
|
16
16
|
orientation?: 'vertical' | 'horizontal';
|
|
17
17
|
colorMode?: number;
|
|
18
18
|
colorScaleIndex?: number;
|
|
19
|
+
/** The page-wide index of this mark's filter group: which run of a field's activity block it reads. */
|
|
20
|
+
groupIndex?: number;
|
|
19
21
|
constantColor?: [number, number, number, number];
|
|
20
22
|
markId?: string;
|
|
21
23
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { UNIFORM_STAND_IN_BYTES } from './uniform-sizes';
|
|
1
2
|
import { MorphedChannels } from '../../gpu/MorphedChannels';
|
|
2
3
|
/** Warned once per page, not per mark. */
|
|
3
4
|
let warnedMorphUnsupported = false;
|
|
@@ -385,7 +386,9 @@ export class BaseGPURenderer {
|
|
|
385
386
|
get #sharedDummyBuffer() {
|
|
386
387
|
if (!this.#dummyBuffer) {
|
|
387
388
|
this.#dummyBuffer = this.#device.createBuffer({
|
|
388
|
-
|
|
389
|
+
// Bound to any binding not written yet, uniforms included: as large as
|
|
390
|
+
// the largest uniform struct, or a draw before the first write fails.
|
|
391
|
+
size: UNIFORM_STAND_IN_BYTES,
|
|
389
392
|
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
|
|
390
393
|
label: `${this.#markType}-dummy`
|
|
391
394
|
});
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { UNIFORM_BYTES } from './uniform-sizes';
|
|
2
3
|
import { getContext, onMount, onDestroy } from 'svelte';
|
|
3
4
|
import { RendererHost } from './RendererHost.svelte';
|
|
4
5
|
import { getGPUContext } from '../../gpu';
|
|
5
6
|
import { DEFAULT_STROKE_COLOR } from '../../scales/color-utils';
|
|
6
7
|
import type { ChartContext, WebGPUCanvasContext } from '../../types';
|
|
8
|
+
import { activityReads, markActivityWGSL } from './activity-reads';
|
|
7
9
|
|
|
8
10
|
const dotRendererDefinition = {
|
|
9
11
|
x: { concept: 'position', channels: ['x'] },
|
|
@@ -29,7 +31,8 @@
|
|
|
29
31
|
COLOR_SCALE_INDEX: 4,
|
|
30
32
|
SIZE_MODE: 8,
|
|
31
33
|
SIZE_SCALE_INDEX: 12,
|
|
32
|
-
CONSTANT_COLOR: 16
|
|
34
|
+
CONSTANT_COLOR: 16,
|
|
35
|
+
GROUP_INDEX: 32
|
|
33
36
|
};
|
|
34
37
|
|
|
35
38
|
interface Props {
|
|
@@ -43,6 +46,8 @@
|
|
|
43
46
|
zIndex?: number;
|
|
44
47
|
colorMode?: number;
|
|
45
48
|
colorScaleIndex?: number;
|
|
49
|
+
/** The page-wide index of this mark's filter group: which run of a field's activity block it reads. */
|
|
50
|
+
groupIndex?: number;
|
|
46
51
|
constantColor?: [number, number, number, number];
|
|
47
52
|
sizeMode?: number;
|
|
48
53
|
sizeScaleIndex?: number;
|
|
@@ -72,6 +77,7 @@
|
|
|
72
77
|
zIndex = 0,
|
|
73
78
|
colorMode = 0,
|
|
74
79
|
colorScaleIndex = 0,
|
|
80
|
+
groupIndex = 0,
|
|
75
81
|
constantColor = DEFAULT_STROKE_COLOR,
|
|
76
82
|
sizeMode = 0,
|
|
77
83
|
sizeScaleIndex = 0,
|
|
@@ -112,6 +118,9 @@
|
|
|
112
118
|
return degen;
|
|
113
119
|
}`;
|
|
114
120
|
|
|
121
|
+
/** The selection activities this shader reads; routing reads the same table. */
|
|
122
|
+
const ACTIVITY_READS = activityReads('dots');
|
|
123
|
+
|
|
115
124
|
const dotsShaderCode = `
|
|
116
125
|
// MarkConstants uniform for per-mark configuration
|
|
117
126
|
struct MarkConstants {
|
|
@@ -120,6 +129,10 @@
|
|
|
120
129
|
sizeMode: u32, // 0 = raw value, 1 = scale
|
|
121
130
|
sizeScaleIndex: u32, // Index into sizeConfigs
|
|
122
131
|
constantColor: vec4<f32>, // Used when colorMode = 0
|
|
132
|
+
groupIndex: u32, // Page-wide filter group index, for activity reads
|
|
133
|
+
_pad0: u32,
|
|
134
|
+
_pad1: u32,
|
|
135
|
+
_pad2: u32,
|
|
123
136
|
};
|
|
124
137
|
@group(1) @binding(5) var<uniform> markConstants: MarkConstants;
|
|
125
138
|
|
|
@@ -175,7 +188,14 @@
|
|
|
175
188
|
output.colorValue = colorValue;
|
|
176
189
|
output.uv = quadPosition;
|
|
177
190
|
output.radius = displayRadius;
|
|
178
|
-
output.alpha = alpha
|
|
191
|
+
output.alpha = alpha * selectionDim(
|
|
192
|
+
${markActivityWGSL(ACTIVITY_READS, {
|
|
193
|
+
color: 'markConstants.colorMode, markConstants.colorScaleIndex, colorValue',
|
|
194
|
+
x: 'x',
|
|
195
|
+
y: 'y',
|
|
196
|
+
group: 'markConstants.groupIndex'
|
|
197
|
+
})}
|
|
198
|
+
);
|
|
179
199
|
return output;
|
|
180
200
|
}
|
|
181
201
|
|
|
@@ -283,12 +303,13 @@
|
|
|
283
303
|
// which re-triggers the guard and avoids stale-buffer flashes.
|
|
284
304
|
if (colorMode === 1 && !colorValueData) return;
|
|
285
305
|
|
|
286
|
-
const buffer = new ArrayBuffer(
|
|
306
|
+
const buffer = new ArrayBuffer(UNIFORM_BYTES.dotsMarkConstants);
|
|
287
307
|
const view = new DataView(buffer);
|
|
288
308
|
const LE = true;
|
|
289
309
|
|
|
290
310
|
view.setUint32(UNIFORM_OFFSETS.COLOR_MODE, colorMode, LE);
|
|
291
311
|
view.setUint32(UNIFORM_OFFSETS.COLOR_SCALE_INDEX, colorScaleIndex, LE);
|
|
312
|
+
view.setUint32(UNIFORM_OFFSETS.GROUP_INDEX, groupIndex, LE);
|
|
292
313
|
view.setUint32(UNIFORM_OFFSETS.SIZE_MODE, sizeMode, LE);
|
|
293
314
|
view.setUint32(UNIFORM_OFFSETS.SIZE_SCALE_INDEX, sizeScaleIndex, LE);
|
|
294
315
|
view.setFloat32(UNIFORM_OFFSETS.CONSTANT_COLOR + 0, constantColor[0], LE);
|
|
@@ -9,6 +9,8 @@ interface Props {
|
|
|
9
9
|
zIndex?: number;
|
|
10
10
|
colorMode?: number;
|
|
11
11
|
colorScaleIndex?: number;
|
|
12
|
+
/** The page-wide index of this mark's filter group: which run of a field's activity block it reads. */
|
|
13
|
+
groupIndex?: number;
|
|
12
14
|
constantColor?: [number, number, number, number];
|
|
13
15
|
sizeMode?: number;
|
|
14
16
|
sizeScaleIndex?: number;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { UNIFORM_BYTES } from './uniform-sizes';
|
|
2
3
|
import { getContext, onMount, onDestroy } from 'svelte';
|
|
3
4
|
import { RendererHost } from './RendererHost.svelte';
|
|
4
5
|
import { getGPUContext } from '../../gpu';
|
|
@@ -194,7 +195,7 @@ ${placement}
|
|
|
194
195
|
// Update uniform constants
|
|
195
196
|
$effect(() => {
|
|
196
197
|
if (renderer?.resourcesCreated) {
|
|
197
|
-
const buffer = new ArrayBuffer(
|
|
198
|
+
const buffer = new ArrayBuffer(UNIFORM_BYTES.gridLineRuleConstants);
|
|
198
199
|
const view = new DataView(buffer);
|
|
199
200
|
const LE = true;
|
|
200
201
|
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { activityReads, colorActivityWGSL } from './activity-reads';
|
|
3
|
+
import { UNIFORM_BYTES } from './uniform-sizes';
|
|
2
4
|
import { getContext, onMount, onDestroy } from 'svelte';
|
|
3
5
|
import { RendererHost } from './RendererHost.svelte';
|
|
4
6
|
import { getGPUContext } from '../../gpu';
|
|
@@ -25,7 +27,7 @@
|
|
|
25
27
|
FACET: 5
|
|
26
28
|
};
|
|
27
29
|
|
|
28
|
-
// Uniform struct offsets (matching WGSL MarkConstants
|
|
30
|
+
// Uniform struct offsets (matching WGSL MarkConstants; size in uniform-sizes.ts)
|
|
29
31
|
const UNIFORM_OFFSETS = {
|
|
30
32
|
STROKE_WIDTH: 0, // f32
|
|
31
33
|
POINT_COUNT: 4, // u32
|
|
@@ -33,7 +35,10 @@
|
|
|
33
35
|
COLOR_SCALE_INDEX: 12, // u32
|
|
34
36
|
CONSTANT_COLOR: 16, // vec4<f32>
|
|
35
37
|
DOT_RADIUS: 32, // f32
|
|
36
|
-
GLOBAL_ALPHA: 36 // f32
|
|
38
|
+
GLOBAL_ALPHA: 36, // f32
|
|
39
|
+
GROUP_INDEX: 40, // u32
|
|
40
|
+
ACTIVITY_COLOR_MODE: 44, // u32
|
|
41
|
+
ACTIVITY_COLOR_SCALE_INDEX: 48 // u32
|
|
37
42
|
};
|
|
38
43
|
|
|
39
44
|
interface Props {
|
|
@@ -49,6 +54,15 @@
|
|
|
49
54
|
dotRadius?: number;
|
|
50
55
|
colorMode?: number;
|
|
51
56
|
colorScaleIndex?: number;
|
|
57
|
+
/** The page-wide index of this mark's filter group: which run of a field's activity block it reads. */
|
|
58
|
+
groupIndex?: number;
|
|
59
|
+
/**
|
|
60
|
+
* The colour mode and scale index selection activity is read through,
|
|
61
|
+
* from `colorValueData`; null for the line's own colour. An area's
|
|
62
|
+
* outline in a constant stroke passes its fill's, with the fill's values.
|
|
63
|
+
*/
|
|
64
|
+
activityColorMode?: number | null;
|
|
65
|
+
activityColorScaleIndex?: number | null;
|
|
52
66
|
constantColor?: [number, number, number, number];
|
|
53
67
|
m4Decimator?: M4Decimator | null;
|
|
54
68
|
dotsRung?: import('../../lod/DotsRung.svelte').DotsRung | null;
|
|
@@ -69,6 +83,9 @@
|
|
|
69
83
|
dotRadius = 0,
|
|
70
84
|
colorMode = 0,
|
|
71
85
|
colorScaleIndex = 0,
|
|
86
|
+
groupIndex = 0,
|
|
87
|
+
activityColorMode = null,
|
|
88
|
+
activityColorScaleIndex = null,
|
|
72
89
|
constantColor = DEFAULT_STROKE_COLOR,
|
|
73
90
|
m4Decimator = null,
|
|
74
91
|
dotsRung = null,
|
|
@@ -83,6 +100,9 @@
|
|
|
83
100
|
const baseMarkType = curve === 'linear' ? 'lines' : `lines-${curve}`;
|
|
84
101
|
const effectiveMarkType = faceted ? `${baseMarkType}-faceted` : baseMarkType;
|
|
85
102
|
|
|
103
|
+
/** The selection activity this shader reads; routing reads the same table. */
|
|
104
|
+
const ACTIVITY_READS = activityReads('lines');
|
|
105
|
+
|
|
86
106
|
// --- Facet compile-time specialization ---
|
|
87
107
|
// Lines uses a storage buffer (not a vertex attribute) for facet indices because
|
|
88
108
|
// the boundary check needs random access: facetIndices[nextIdx] to detect when
|
|
@@ -139,7 +159,12 @@
|
|
|
139
159
|
constantColor: vec4<f32>,
|
|
140
160
|
dotRadius: f32,
|
|
141
161
|
globalAlpha: f32,
|
|
142
|
-
|
|
162
|
+
groupIndex: u32, // Page-wide filter group index, for activity reads
|
|
163
|
+
// Which colour scale this line's selection activity is read through. Its
|
|
164
|
+
// own colour by default; an area's outline, drawn in a constant stroke,
|
|
165
|
+
// reads its fill's so it dims with the fill.
|
|
166
|
+
activityColorMode: u32,
|
|
167
|
+
activityColorScaleIndex: u32
|
|
143
168
|
};
|
|
144
169
|
@group(1) @binding(4) var<uniform> markConstants: MarkConstants;
|
|
145
170
|
|
|
@@ -196,7 +221,13 @@
|
|
|
196
221
|
var output: VertexOutput;
|
|
197
222
|
output.position = pixelsToClip(pos);
|
|
198
223
|
output.colorValue = colorValues[instanceIdx];
|
|
199
|
-
output.alpha = markConstants.globalAlpha
|
|
224
|
+
output.alpha = markConstants.globalAlpha * selectionDim(
|
|
225
|
+
${colorActivityWGSL(ACTIVITY_READS, {
|
|
226
|
+
color:
|
|
227
|
+
'markConstants.activityColorMode, markConstants.activityColorScaleIndex, colorValues[instanceIdx]',
|
|
228
|
+
group: 'markConstants.groupIndex'
|
|
229
|
+
})}
|
|
230
|
+
);
|
|
200
231
|
output.circleUV = quadPosition;
|
|
201
232
|
output.circleRadius = circleR;
|
|
202
233
|
return output;
|
|
@@ -291,7 +322,13 @@
|
|
|
291
322
|
var output: VertexOutput;
|
|
292
323
|
output.position = pixelsToClip(finalPos);
|
|
293
324
|
output.colorValue = colorValues[currIdx];
|
|
294
|
-
output.alpha = markConstants.globalAlpha
|
|
325
|
+
output.alpha = markConstants.globalAlpha * selectionDim(
|
|
326
|
+
${colorActivityWGSL(ACTIVITY_READS, {
|
|
327
|
+
color:
|
|
328
|
+
'markConstants.activityColorMode, markConstants.activityColorScaleIndex, colorValues[currIdx]',
|
|
329
|
+
group: 'markConstants.groupIndex'
|
|
330
|
+
})}
|
|
331
|
+
);
|
|
295
332
|
output.circleUV = vec2<f32>(-2.0, -2.0);
|
|
296
333
|
output.circleRadius = 0.0;
|
|
297
334
|
return output;
|
|
@@ -385,9 +422,11 @@
|
|
|
385
422
|
// Guard: skip uniform write when colorMode=1 but color data hasn't
|
|
386
423
|
// arrived yet. colorValueData is tracked reactively so the effect
|
|
387
424
|
// re-fires once data loads.
|
|
388
|
-
|
|
425
|
+
const activityMode = activityColorMode ?? colorMode;
|
|
426
|
+
const activityScale = activityColorScaleIndex ?? colorScaleIndex;
|
|
427
|
+
if ((colorMode === 1 || activityMode === 1) && !colorValueData) return;
|
|
389
428
|
|
|
390
|
-
const buffer = new ArrayBuffer(
|
|
429
|
+
const buffer = new ArrayBuffer(UNIFORM_BYTES.linesMarkConstants);
|
|
391
430
|
const view = new DataView(buffer);
|
|
392
431
|
const LE = true;
|
|
393
432
|
|
|
@@ -401,6 +440,9 @@
|
|
|
401
440
|
view.setUint32(UNIFORM_OFFSETS.POINT_COUNT, pointCount, LE);
|
|
402
441
|
view.setUint32(UNIFORM_OFFSETS.COLOR_MODE, colorMode, LE);
|
|
403
442
|
view.setUint32(UNIFORM_OFFSETS.COLOR_SCALE_INDEX, colorScaleIndex, LE);
|
|
443
|
+
view.setUint32(UNIFORM_OFFSETS.GROUP_INDEX, groupIndex, LE);
|
|
444
|
+
view.setUint32(UNIFORM_OFFSETS.ACTIVITY_COLOR_MODE, activityMode, LE);
|
|
445
|
+
view.setUint32(UNIFORM_OFFSETS.ACTIVITY_COLOR_SCALE_INDEX, activityScale, LE);
|
|
404
446
|
view.setFloat32(UNIFORM_OFFSETS.CONSTANT_COLOR + 0, constantColor[0], LE);
|
|
405
447
|
view.setFloat32(UNIFORM_OFFSETS.CONSTANT_COLOR + 4, constantColor[1], LE);
|
|
406
448
|
view.setFloat32(UNIFORM_OFFSETS.CONSTANT_COLOR + 8, constantColor[2], LE);
|
|
@@ -13,6 +13,15 @@ interface Props {
|
|
|
13
13
|
dotRadius?: number;
|
|
14
14
|
colorMode?: number;
|
|
15
15
|
colorScaleIndex?: number;
|
|
16
|
+
/** The page-wide index of this mark's filter group: which run of a field's activity block it reads. */
|
|
17
|
+
groupIndex?: number;
|
|
18
|
+
/**
|
|
19
|
+
* The colour mode and scale index selection activity is read through,
|
|
20
|
+
* from `colorValueData`; null for the line's own colour. An area's
|
|
21
|
+
* outline in a constant stroke passes its fill's, with the fill's values.
|
|
22
|
+
*/
|
|
23
|
+
activityColorMode?: number | null;
|
|
24
|
+
activityColorScaleIndex?: number | null;
|
|
16
25
|
constantColor?: [number, number, number, number];
|
|
17
26
|
m4Decimator?: M4Decimator | null;
|
|
18
27
|
dotsRung?: import('../../lod/DotsRung.svelte').DotsRung | null;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { activityReads, colorActivityWGSL } from './activity-reads';
|
|
3
|
+
import { PARALLEL_MAX_AXES, UNIFORM_BYTES } from './uniform-sizes';
|
|
2
4
|
import { getContext, onMount, onDestroy } from 'svelte';
|
|
3
5
|
import { RendererHost } from './RendererHost.svelte';
|
|
4
6
|
import { getGPUContext } from '../../gpu';
|
|
@@ -7,10 +9,10 @@
|
|
|
7
9
|
import { DEFAULT_STROKE_COLOR } from '../../scales/color-utils';
|
|
8
10
|
import type { ChartContext, CurveType, WebGPUCanvasContext } from '../../types';
|
|
9
11
|
|
|
10
|
-
const MAX_AXES =
|
|
11
|
-
const UNIFORM_SIZE =
|
|
12
|
+
const MAX_AXES = PARALLEL_MAX_AXES;
|
|
13
|
+
const UNIFORM_SIZE = UNIFORM_BYTES.parallelConfig;
|
|
12
14
|
// One ScaleParam (16 bytes) per axis, filled by the coordinator.
|
|
13
|
-
const AXIS_SCALES_SIZE =
|
|
15
|
+
const AXIS_SCALES_SIZE = UNIFORM_BYTES.parallelAxisScales;
|
|
14
16
|
|
|
15
17
|
// Both x and y so ScaleTemplateSystem generates scaleX(), scaleLinearY(), pixelsToClip()
|
|
16
18
|
const rendererDefinition = {
|
|
@@ -32,6 +34,8 @@
|
|
|
32
34
|
colorValueData?: Float32Array | null;
|
|
33
35
|
colorMode?: number;
|
|
34
36
|
colorScaleIndex?: number;
|
|
37
|
+
/** The page-wide index of this mark's filter group: which run of a field's activity block it reads. */
|
|
38
|
+
groupIndex?: number;
|
|
35
39
|
constantColor?: [number, number, number, number];
|
|
36
40
|
axisOrder: number[];
|
|
37
41
|
/** Each axis's scale id, in data (not visual) order. */
|
|
@@ -51,6 +55,7 @@
|
|
|
51
55
|
colorValueData = null,
|
|
52
56
|
colorMode = 0,
|
|
53
57
|
colorScaleIndex = 0,
|
|
58
|
+
groupIndex = 0,
|
|
54
59
|
constantColor = DEFAULT_STROKE_COLOR,
|
|
55
60
|
axisOrder,
|
|
56
61
|
axisScaleIds,
|
|
@@ -87,6 +92,9 @@
|
|
|
87
92
|
// (N-1) segments × resolution sub-quads × 6 verts + N circles × 6 verts
|
|
88
93
|
const vertexCount = $derived((axisCount - 1) * 6 * resolution + axisCount * 6);
|
|
89
94
|
|
|
95
|
+
/** The selection activity this shader reads; routing reads the same table. */
|
|
96
|
+
const ACTIVITY_READS = activityReads('parallel');
|
|
97
|
+
|
|
90
98
|
// evaluateCurve() and CURVE_RESOLUTION are prepended from CurveShaderLib.
|
|
91
99
|
// With linear (resolution=1): single quad per segment, identical to original.
|
|
92
100
|
// With bump-x (resolution=128): smooth S-curves between axes, adaptive.
|
|
@@ -101,7 +109,7 @@
|
|
|
101
109
|
opacity: f32,
|
|
102
110
|
colorMode: u32,
|
|
103
111
|
colorScaleIndex: u32,
|
|
104
|
-
|
|
112
|
+
groupIndex: u32,
|
|
105
113
|
_pad1: u32,
|
|
106
114
|
constantColor: vec4<f32>,
|
|
107
115
|
axisOrder: array<vec4<u32>, 4>,
|
|
@@ -191,7 +199,12 @@
|
|
|
191
199
|
var output: VertexOutput;
|
|
192
200
|
output.position = pixelsToClip(pos);
|
|
193
201
|
output.colorValue = colorValues[rowIdx];
|
|
194
|
-
output.alpha = config.opacity
|
|
202
|
+
output.alpha = config.opacity * selectionDim(
|
|
203
|
+
${colorActivityWGSL(ACTIVITY_READS, {
|
|
204
|
+
color: 'config.colorMode, config.colorScaleIndex, colorValues[rowIdx]',
|
|
205
|
+
group: 'config.groupIndex'
|
|
206
|
+
})}
|
|
207
|
+
);
|
|
195
208
|
output.circleUV = quadPosition;
|
|
196
209
|
output.circleRadius = halfWidth;
|
|
197
210
|
return output;
|
|
@@ -270,7 +283,12 @@
|
|
|
270
283
|
var output: VertexOutput;
|
|
271
284
|
output.position = pixelsToClip(finalPos);
|
|
272
285
|
output.colorValue = colorValues[rowIdx];
|
|
273
|
-
output.alpha = config.opacity
|
|
286
|
+
output.alpha = config.opacity * selectionDim(
|
|
287
|
+
${colorActivityWGSL(ACTIVITY_READS, {
|
|
288
|
+
color: 'config.colorMode, config.colorScaleIndex, colorValues[rowIdx]',
|
|
289
|
+
group: 'config.groupIndex'
|
|
290
|
+
})}
|
|
291
|
+
);
|
|
274
292
|
output.circleUV = vec2<f32>(-2.0, -2.0);
|
|
275
293
|
output.circleRadius = 0.0;
|
|
276
294
|
return output;
|
|
@@ -361,7 +379,8 @@
|
|
|
361
379
|
f32[3] = opacity;
|
|
362
380
|
u32[4] = colorMode;
|
|
363
381
|
u32[5] = colorScaleIndex;
|
|
364
|
-
|
|
382
|
+
u32[6] = groupIndex;
|
|
383
|
+
// u32[7] = padding
|
|
365
384
|
f32[8] = constantColor[0];
|
|
366
385
|
f32[9] = constantColor[1];
|
|
367
386
|
f32[10] = constantColor[2];
|
|
@@ -6,6 +6,8 @@ interface Props {
|
|
|
6
6
|
colorValueData?: Float32Array | null;
|
|
7
7
|
colorMode?: number;
|
|
8
8
|
colorScaleIndex?: number;
|
|
9
|
+
/** The page-wide index of this mark's filter group: which run of a field's activity block it reads. */
|
|
10
|
+
groupIndex?: number;
|
|
9
11
|
constantColor?: [number, number, number, number];
|
|
10
12
|
axisOrder: number[];
|
|
11
13
|
/** Each axis's scale id, in data (not visual) order. */
|