@fjader/svelte 0.2.2 → 0.2.4

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 (148) hide show
  1. package/README.md +2 -0
  2. package/dist/components/axes/AxisBottom.svelte +23 -6
  3. package/dist/components/axes/AxisBottom.svelte.d.ts +10 -0
  4. package/dist/components/axes/AxisLeft.svelte +77 -8
  5. package/dist/components/axes/AxisLeft.svelte.d.ts +17 -0
  6. package/dist/components/axes/BandAxisTicks.svelte +64 -25
  7. package/dist/components/axes/BandAxisTicks.svelte.d.ts +5 -5
  8. package/dist/components/axes/axis-title.d.ts +30 -0
  9. package/dist/components/axes/axis-title.js +77 -0
  10. package/dist/components/charts/ChartCell.svelte +1 -1
  11. package/dist/components/charts/ChartContainer.svelte +12 -3
  12. package/dist/components/charts/ChartContainer.svelte.d.ts +7 -0
  13. package/dist/components/guides/legend/ContinuousColorLegend.svelte +9 -2
  14. package/dist/components/guides/legend/OrdinalColorLegend.svelte +96 -35
  15. package/dist/components/marks/AreaMarkX.svelte +21 -6
  16. package/dist/components/marks/AreaMarkY.svelte +21 -6
  17. package/dist/components/marks/BarMarkX.svelte +16 -1
  18. package/dist/components/marks/BarMarkY.svelte +16 -1
  19. package/dist/components/marks/DotsMark.svelte +5 -0
  20. package/dist/components/marks/LineMark.svelte +8 -1
  21. package/dist/components/marks/ParallelCoordinatesMark.svelte +10 -0
  22. package/dist/components/marks/ParallelCoordinatesMark.svelte.d.ts +5 -0
  23. package/dist/components/marks/RectMark.svelte +5 -0
  24. package/dist/components/marks/RectXMark.svelte +5 -0
  25. package/dist/components/marks/RectYMark.svelte +5 -0
  26. package/dist/components/marks/RuleMarkX.svelte +12 -2
  27. package/dist/components/marks/RuleMarkY.svelte +12 -2
  28. package/dist/components/marks/TextMark.svelte +76 -13
  29. package/dist/components/marks/lifecycle/MarkLifecycleV2.svelte.d.ts +21 -2
  30. package/dist/components/marks/lifecycle/MarkLifecycleV2.svelte.js +300 -42
  31. package/dist/components/marks/lifecycle/domain-queries.d.ts +3 -1
  32. package/dist/components/marks/lifecycle/domain-queries.js +22 -15
  33. package/dist/components/marks/lifecycle/domain-registration.js +2 -6
  34. package/dist/components/marks/lifecycle/other-rows.svelte.d.ts +104 -0
  35. package/dist/components/marks/lifecycle/other-rows.svelte.js +193 -0
  36. package/dist/components/marks/lifecycle/other-split.d.ts +80 -0
  37. package/dist/components/marks/lifecycle/other-split.js +112 -0
  38. package/dist/components/marks/lifecycle/query-builder.d.ts +26 -1
  39. package/dist/components/marks/lifecycle/query-builder.js +25 -5
  40. package/dist/components/marks/lifecycle/transform-scale-key.d.ts +16 -0
  41. package/dist/components/marks/lifecycle/transform-scale-key.js +27 -0
  42. package/dist/components/marks/utils/area-outline.d.ts +24 -0
  43. package/dist/components/marks/utils/area-outline.js +10 -0
  44. package/dist/components/marks/utils/reactive-config.d.ts +1 -1
  45. package/dist/components/marks/utils/reactive-config.js +9 -0
  46. package/dist/components/marks/utils/tooltip-helpers.d.ts +4 -1
  47. package/dist/components/marks/utils/tooltip-helpers.js +2 -1
  48. package/dist/components/rendering/Areas.svelte +30 -6
  49. package/dist/components/rendering/Areas.svelte.d.ts +2 -0
  50. package/dist/components/rendering/BaseGPURenderer.svelte.d.ts +3 -1
  51. package/dist/components/rendering/BaseGPURenderer.svelte.js +8 -3
  52. package/dist/components/rendering/Dots.svelte +24 -3
  53. package/dist/components/rendering/Dots.svelte.d.ts +2 -0
  54. package/dist/components/rendering/GridLine.svelte +2 -1
  55. package/dist/components/rendering/Lines.svelte +49 -7
  56. package/dist/components/rendering/Lines.svelte.d.ts +9 -0
  57. package/dist/components/rendering/ParallelLines.svelte +26 -7
  58. package/dist/components/rendering/ParallelLines.svelte.d.ts +2 -0
  59. package/dist/components/rendering/Rects.svelte +129 -20
  60. package/dist/components/rendering/Rects.svelte.d.ts +9 -0
  61. package/dist/components/rendering/RuleX.svelte +20 -5
  62. package/dist/components/rendering/RuleX.svelte.d.ts +2 -0
  63. package/dist/components/rendering/RuleY.svelte +20 -5
  64. package/dist/components/rendering/RuleY.svelte.d.ts +2 -0
  65. package/dist/components/rendering/activity-reads.d.ts +111 -0
  66. package/dist/components/rendering/activity-reads.js +154 -0
  67. package/dist/components/rendering/uniform-sizes.d.ts +26 -0
  68. package/dist/components/rendering/uniform-sizes.js +28 -0
  69. package/dist/config/ChartConfig.svelte.d.ts +5 -1
  70. package/dist/gpu/ColorScaleShaderLib.d.ts +13 -1
  71. package/dist/gpu/ColorScaleShaderLib.js +56 -5
  72. package/dist/gpu/GPUCoordinator.svelte.d.ts +8 -0
  73. package/dist/gpu/GPUCoordinator.svelte.js +68 -32
  74. package/dist/gpu/MorphedChannels.d.ts +6 -32
  75. package/dist/gpu/MorphedChannels.js +45 -3
  76. package/dist/gpu/ResolveShader.d.ts +2 -2
  77. package/dist/gpu/ResolveShader.js +2 -2
  78. package/dist/gpu/ScaleTemplateSystem.d.ts +19 -0
  79. package/dist/gpu/ScaleTemplateSystem.js +111 -11
  80. package/dist/gpu/SizeScaleShaderLib.d.ts +4 -4
  81. package/dist/gpu/SizeScaleShaderLib.js +4 -4
  82. package/dist/gpu/identity-slot-packing.d.ts +157 -40
  83. package/dist/gpu/identity-slot-packing.js +262 -62
  84. package/dist/gpu/tracked-scales.d.ts +14 -0
  85. package/dist/gpu/tracked-scales.js +18 -0
  86. package/dist/index.d.ts +2 -0
  87. package/dist/index.js +4 -0
  88. package/dist/interactors/BandLabelToggle.svelte +5 -9
  89. package/dist/interactors/BandLabelToggle.svelte.d.ts +3 -3
  90. package/dist/interactors/DerivedInterval1D.svelte +26 -54
  91. package/dist/interactors/Interval1D.svelte +8 -2
  92. package/dist/interactors/Interval2D.svelte +8 -2
  93. package/dist/interactors/ParallelAxisSource.svelte +14 -5
  94. package/dist/interactors/ParallelAxisSource.svelte.d.ts +2 -1
  95. package/dist/interactors/ParallelBrushes.svelte +8 -9
  96. package/dist/interactors/ParallelBrushes.svelte.d.ts +3 -3
  97. package/dist/interactors/Toggle.svelte +48 -38
  98. package/dist/interactors/Toggle.svelte.d.ts +4 -3
  99. package/dist/interactors/Tooltip.svelte +140 -42
  100. package/dist/interactors/TooltipManager.svelte.d.ts +20 -5
  101. package/dist/interactors/TooltipManager.svelte.js +40 -10
  102. package/dist/interactors/other-tooltip.d.ts +16 -0
  103. package/dist/interactors/other-tooltip.js +22 -0
  104. package/dist/interactors/relay-clauses.d.ts +23 -0
  105. package/dist/interactors/relay-clauses.js +60 -0
  106. package/dist/query-engine/CrossfilterSelection.svelte.d.ts +88 -15
  107. package/dist/query-engine/CrossfilterSelection.svelte.js +94 -20
  108. package/dist/query-engine/FieldActivity.svelte.d.ts +128 -0
  109. package/dist/query-engine/FieldActivity.svelte.js +378 -0
  110. package/dist/query-engine/FilterGroup.svelte.d.ts +76 -30
  111. package/dist/query-engine/FilterGroup.svelte.js +223 -124
  112. package/dist/query-engine/FilterGroupRegistry.svelte.d.ts +73 -3
  113. package/dist/query-engine/FilterGroupRegistry.svelte.js +161 -12
  114. package/dist/query-engine/MarkHandle.svelte.d.ts +9 -1
  115. package/dist/query-engine/MarkHandle.svelte.js +12 -2
  116. package/dist/query-engine/QueryEngine.d.ts +52 -16
  117. package/dist/query-engine/QueryEngine.js +116 -34
  118. package/dist/query-engine/categorical-identity.d.ts +114 -27
  119. package/dist/query-engine/categorical-identity.js +225 -51
  120. package/dist/query-engine/index.d.ts +2 -1
  121. package/dist/query-engine/index.js +1 -0
  122. package/dist/query-engine/preagg/Preagg.d.ts +1 -1
  123. package/dist/query-engine/preagg/Preagg.js +11 -9
  124. package/dist/query-engine/preagg/plan.d.ts +14 -5
  125. package/dist/query-engine/preagg/plan.js +44 -18
  126. package/dist/query-engine/toggle-predicate.d.ts +21 -0
  127. package/dist/query-engine/toggle-predicate.js +41 -2
  128. package/dist/scales/ActivityTable.d.ts +103 -0
  129. package/dist/scales/ActivityTable.js +220 -0
  130. package/dist/scales/BandScaleState.svelte.d.ts +41 -15
  131. package/dist/scales/BandScaleState.svelte.js +78 -36
  132. package/dist/scales/ChartScales.svelte.d.ts +2 -2
  133. package/dist/scales/ColorScaleState.svelte.d.ts +36 -8
  134. package/dist/scales/ColorScaleState.svelte.js +118 -24
  135. package/dist/scales/DomainResolver.d.ts +2 -0
  136. package/dist/scales/DomainResolver.js +15 -8
  137. package/dist/scales/ScaleRegistry.svelte.d.ts +9 -0
  138. package/dist/scales/ScaleRegistry.svelte.js +22 -1
  139. package/dist/scales/TimeScaleState.svelte.js +7 -1
  140. package/dist/spec/index.js +1 -0
  141. package/dist/spec/types.d.ts +4 -0
  142. package/dist/theme.css +5 -4
  143. package/dist/transforms/TransformCompiler.d.ts +37 -2
  144. package/dist/transforms/TransformCompiler.js +44 -1
  145. package/dist/transforms/index.d.ts +27 -0
  146. package/dist/transforms/index.js +127 -19
  147. package/dist/types.d.ts +71 -0
  148. package/package.json +3 -2
@@ -1,9 +1,11 @@
1
1
  <script lang="ts">
2
2
  import { getContext, onDestroy } from 'svelte';
3
- import type { ScaleRegistry } from '../../../scales/ScaleRegistry.svelte';
4
3
  import type { ColorScaleState } from '../../../scales/ColorScaleState.svelte';
5
- import type { ActiveValueScale } from '../../../query-engine/FilterGroup.svelte';
6
4
  import type { FilterGroupRegistry } from '../../../query-engine/FilterGroupRegistry.svelte';
5
+ import type { ChartContext } from '../../../types';
6
+ import type { BandScaleState } from '../../../scales/BandScaleState.svelte';
7
+ import type { DimValue } from '../../../query-engine/categorical-identity';
8
+ import { categoryLabel } from '../../../query-engine/categorical-identity';
7
9
 
8
10
  interface Props {
9
11
  scaleState: ColorScaleState;
@@ -31,43 +33,106 @@
31
33
 
32
34
  const filterGroups = getContext<FilterGroupRegistry | undefined>('filter-groups');
33
35
  const filterGroup = filterGroups?.get(selection);
34
- const scaleRegistry = getContext<ScaleRegistry>('scale-registry');
35
36
 
36
- // Reactive: re-renders when domain or scheme changes
37
- const items = $derived(
38
- scaleState.domain.map((value) => ({
37
+ const chartContext = getContext<ChartContext | undefined>('chart');
38
+
39
+ /**
40
+ * The chart's band axis on this legend's field, if it has one. The legend then
41
+ * lists what that axis shows (a top N and its Other, a table's own categories)
42
+ * rather than every category of the field, which is what the colour scale's
43
+ * domain holds: it is shared per field across charts.
44
+ */
45
+ const bandOnField = $derived.by(() => {
46
+ // Neither identityKey is reactive state, and both are null until identity
47
+ // lands, which is after this first runs: read the signals that change
48
+ // with them, or this stays null for good.
49
+ void scaleState.ranksRevision;
50
+ const key = scaleState.identityKey;
51
+ if (!chartContext || !key) return null;
52
+ for (const axis of ['x', 'y'] as const) {
53
+ const type = chartContext.scaleTypes?.[axis];
54
+ if (type !== 'band' && type !== 'point') continue;
55
+ const band = chartContext[`${axis}ScaleState`] as BandScaleState | null;
56
+ if (!band) continue;
57
+ void band._version;
58
+ if (band.identityKey === key) return band;
59
+ }
60
+ return null;
61
+ });
62
+
63
+ interface Item {
64
+ /** The category's dim id, when the legend follows a band axis. */
65
+ id: number | null;
66
+ value: DimValue;
67
+ color: string;
68
+ /** An Other bucket: a click selects what it holds (see toggleOther). */
69
+ bucket: boolean;
70
+ }
71
+
72
+ // Reactive: re-renders when the domain, the axis or the palette ranks change.
73
+ const items = $derived.by((): Item[] => {
74
+ const band = bandOnField;
75
+ if (band) {
76
+ void band._version;
77
+ const ids = band.displayOrder;
78
+ const values = band.effectiveDomain;
79
+ const identity = scaleState.identity;
80
+ return Array.from(ids, (id, i) => ({
81
+ id,
82
+ value: values[i],
83
+ color: scaleState.getColor(values[i] as string | number | null),
84
+ bucket: identity?.synthetic.has(id) ?? false
85
+ }));
86
+ }
87
+ return scaleState.domain.map((value) => ({
88
+ id: null,
39
89
  value,
40
- color: scaleState.getColor(value)
41
- }))
42
- );
90
+ color: scaleState.getColor(value),
91
+ bucket: false
92
+ }));
93
+ });
43
94
 
44
95
  // --- Toggle interaction ---
45
96
  const isInteractive = $derived(filterGroup != null && field != null);
46
97
 
47
- // Scales to dim: this color scale + any band scale for the same field.
48
- // Projection itself is handled by FilterGroup, shared with Toggle/brushes.
49
- function getLegendScaleStates(): ActiveValueScale[] {
50
- const band = scaleRegistry?.getScaleByField(field!, 'band');
51
- return [scaleState, band].filter(Boolean) as unknown as ActiveValueScale[];
98
+ /**
99
+ * The field's identity key: what its selection is kept under. The scale's
100
+ * own once it has identity; the field before, as the toggle keys it. For a
101
+ * plain column the two are the same. For a computed field (an expression)
102
+ * they differ, so while a reload empties the identity the legend reads the
103
+ * selection under the field's name and its highlight is briefly lost.
104
+ */
105
+ const key = $derived(scaleState.identityKey ?? field ?? scaleState.field);
106
+ const groups = $derived(filterGroup ? [filterGroup.index] : []);
107
+
108
+ /**
109
+ * How visible an entry is now: its group's selection fade on the field, on
110
+ * the same clock and with the same floor as the marks.
111
+ */
112
+ function opacityOf(item: Item): number {
113
+ if (!filterGroups) return 1;
114
+ // By id where there is one: the only way to reach an Other bucket.
115
+ return item.id !== null
116
+ ? filterGroups.opacityOfId(key, groups, item.id)
117
+ : filterGroups.opacityOfValue(key, groups, item.value);
52
118
  }
53
119
 
54
120
  // The selection is shared with any Toggle on the same field through its clause.
55
- // A legend is not a chart, so it excludes no marks: every chart filters.
121
+ // A legend inside a chart skips that chart, as a Toggle there does: its marks
122
+ // keyed by the field dim, the rest keep their data. A standalone legend is in
123
+ // no chart, so every chart in its group is routed by its marks alone.
56
124
  const toggle =
57
125
  filterGroup && field
58
- ? filterGroup.registerToggle(field, {
59
- excludeMarkIds: () => new Set<string>(),
60
- scales: getLegendScaleStates
61
- })
126
+ ? filterGroup.registerToggle(field, { chart: chartContext?.config ?? null })
62
127
  : null;
63
128
  onDestroy(() => toggle?.destroy());
64
129
 
65
- // Derive visual state from the toggle's selection
66
- const selectedSet = $derived(toggle?.active ? toggle.values : null);
67
-
68
130
  // Shift/meta-click adds or removes; selecting every value clears instead.
69
- function handleClick(value: string | number, event: MouseEvent) {
70
- toggle?.toggle([value], event.shiftKey || event.metaKey, scaleState.domain.length);
131
+ function handleClick(item: Item, event: MouseEvent) {
132
+ const multi = event.shiftKey || event.metaKey;
133
+ // An Other bucket names no value: the click selects what it holds.
134
+ if (item.bucket && item.id !== null) toggle?.toggleOther(item.id, null, multi);
135
+ else toggle?.toggle([item.value], multi, scaleState.domain.length);
71
136
  }
72
137
  </script>
73
138
 
@@ -85,12 +150,13 @@
85
150
  class:legend-columns={columns}
86
151
  class:legend-vertical={orientation === 'vertical'}
87
152
  >
88
- {#each items as { value, color } (value)}
153
+ {#each items as item (item.id ?? item.value)}
154
+ {@const { value, color } = item}
89
155
  {#if isInteractive}
90
156
  <button
91
157
  class="legend-item legend-item-interactive"
92
- class:legend-item-dimmed={selectedSet != null && !selectedSet.has(value)}
93
- onclick={(e) => handleClick(value, e)}
158
+ style:opacity={opacityOf(item)}
159
+ onclick={(e) => handleClick(item, e)}
94
160
  >
95
161
  <span
96
162
  class="legend-swatch"
@@ -99,10 +165,10 @@
99
165
  style:height="{swatchSize}px"
100
166
  style:border-radius="{swatchRadius}px"
101
167
  ></span>
102
- <span class="legend-label">{value}</span>
168
+ <span class="legend-label">{categoryLabel(value)}</span>
103
169
  </button>
104
170
  {:else}
105
- <span class="legend-item">
171
+ <span class="legend-item" style:opacity={opacityOf(item)}>
106
172
  <span
107
173
  class="legend-swatch"
108
174
  style:background={color}
@@ -110,7 +176,7 @@
110
176
  style:height="{swatchSize}px"
111
177
  style:border-radius="{swatchRadius}px"
112
178
  ></span>
113
- <span class="legend-label">{value}</span>
179
+ <span class="legend-label">{categoryLabel(value)}</span>
114
180
  </span>
115
181
  {/if}
116
182
  {/each}
@@ -157,7 +223,6 @@
157
223
  align-items: center;
158
224
  gap: 4px;
159
225
  white-space: nowrap;
160
- transition: opacity 0.15s ease;
161
226
  }
162
227
 
163
228
  .legend-item-interactive {
@@ -170,10 +235,6 @@
170
235
  color: inherit;
171
236
  }
172
237
 
173
- .legend-item-dimmed {
174
- opacity: 0.2;
175
- }
176
-
177
238
  .legend-swatch {
178
239
  display: inline-block;
179
240
  flex-shrink: 0;
@@ -1,4 +1,5 @@
1
1
  <script lang="ts">
2
+ import { outlineColor } from './utils/area-outline';
2
3
  import { getContext, onDestroy, untrack } from 'svelte';
3
4
  import { MarkLifecycleV2 } from './lifecycle/MarkLifecycleV2.svelte';
4
5
  import { Areas, Lines } from '../rendering';
@@ -46,6 +47,8 @@
46
47
  let {
47
48
  table,
48
49
  selection = undefined,
50
+ selectionResponse = undefined,
51
+ nulls = undefined,
49
52
  y,
50
53
  x,
51
54
  x1: x1Prop,
@@ -98,6 +101,8 @@
98
101
  strokeWidth: () => strokeWidth,
99
102
  transforms: () => transforms,
100
103
  selection: () => selection,
104
+ selectionResponse: () => selectionResponse,
105
+ nulls: () => nulls,
101
106
  limit: () => limit,
102
107
  preferredXScaleType: () => preferredXScaleType,
103
108
  preferredYScaleType: () => preferredYScaleType,
@@ -157,6 +162,9 @@
157
162
  chartContext
158
163
  );
159
164
 
165
+ /** The outline's colour, and the fill's activity it dims by (see area-outline.ts). */
166
+ const outline = $derived(outlineColor(entry.stroke, markColor));
167
+
160
168
  // Detect if x2 is an aggregate expression
161
169
  const hasAggregateX = $derived.by(() => {
162
170
  return (
@@ -366,6 +374,7 @@
366
374
  colorValueData={markColor.data}
367
375
  colorMode={markColor.colorMode}
368
376
  colorScaleIndex={markColor.colorScaleIndex}
377
+ groupIndex={setup?.groupIndex ?? 0}
369
378
  constantColor={markColor.constantColor}
370
379
  fillOpacity={entry.fillOpacity ?? 0.5}
371
380
  dotRadius={effectiveDotRadius}
@@ -381,9 +390,12 @@
381
390
  {yData}
382
391
  {seriesData}
383
392
  curve={effectiveCurve}
384
- colorValueData={entry.stroke ? null : markColor.data}
385
- colorMode={entry.stroke ? 0 : markColor.colorMode}
386
- colorScaleIndex={entry.stroke ? 0 : markColor.colorScaleIndex}
393
+ colorValueData={outline.colorValueData}
394
+ colorMode={outline.colorMode}
395
+ colorScaleIndex={outline.colorScaleIndex}
396
+ activityColorMode={outline.activityColorMode}
397
+ activityColorScaleIndex={outline.activityColorScaleIndex}
398
+ groupIndex={setup?.groupIndex ?? 0}
387
399
  constantColor={strokeConstantColor}
388
400
  strokeWidth={entry.strokeWidth ?? 0}
389
401
  zIndex={1}
@@ -396,9 +408,12 @@
396
408
  {yData}
397
409
  {seriesData}
398
410
  curve={effectiveCurve}
399
- colorValueData={entry.stroke ? null : markColor.data}
400
- colorMode={entry.stroke ? 0 : markColor.colorMode}
401
- colorScaleIndex={entry.stroke ? 0 : markColor.colorScaleIndex}
411
+ colorValueData={outline.colorValueData}
412
+ colorMode={outline.colorMode}
413
+ colorScaleIndex={outline.colorScaleIndex}
414
+ activityColorMode={outline.activityColorMode}
415
+ activityColorScaleIndex={outline.activityColorScaleIndex}
416
+ groupIndex={setup?.groupIndex ?? 0}
402
417
  constantColor={strokeConstantColor}
403
418
  strokeWidth={entry.strokeWidth ?? 0}
404
419
  zIndex={1}
@@ -1,4 +1,5 @@
1
1
  <script lang="ts">
2
+ import { outlineColor } from './utils/area-outline';
2
3
  import { getContext, onDestroy, untrack } from 'svelte';
3
4
  import { MarkLifecycleV2 } from './lifecycle/MarkLifecycleV2.svelte';
4
5
  import { Areas, Lines } from '../rendering';
@@ -46,6 +47,8 @@
46
47
  let {
47
48
  table,
48
49
  selection = undefined,
50
+ selectionResponse = undefined,
51
+ nulls = undefined,
49
52
  x,
50
53
  y,
51
54
  y1: y1Prop,
@@ -98,6 +101,8 @@
98
101
  strokeWidth: () => strokeWidth,
99
102
  transforms: () => transforms,
100
103
  selection: () => selection,
104
+ selectionResponse: () => selectionResponse,
105
+ nulls: () => nulls,
101
106
  limit: () => limit,
102
107
  preferredXScaleType: () => preferredXScaleType,
103
108
  preferredYScaleType: () => preferredYScaleType,
@@ -157,6 +162,9 @@
157
162
  chartContext
158
163
  );
159
164
 
165
+ /** The outline's colour, and the fill's activity it dims by (see area-outline.ts). */
166
+ const outline = $derived(outlineColor(entry.stroke, markColor));
167
+
160
168
  // Detect if y2 is an aggregate expression (count, sum, mean, etc.)
161
169
  const hasAggregateY = $derived.by(() => {
162
170
  return (
@@ -366,6 +374,7 @@
366
374
  colorValueData={markColor.data}
367
375
  colorMode={markColor.colorMode}
368
376
  colorScaleIndex={markColor.colorScaleIndex}
377
+ groupIndex={setup?.groupIndex ?? 0}
369
378
  constantColor={markColor.constantColor}
370
379
  fillOpacity={entry.fillOpacity ?? 0.5}
371
380
  dotRadius={effectiveDotRadius}
@@ -381,9 +390,12 @@
381
390
  yData={yTopData}
382
391
  {seriesData}
383
392
  curve={effectiveCurve}
384
- colorValueData={entry.stroke ? null : markColor.data}
385
- colorMode={entry.stroke ? 0 : markColor.colorMode}
386
- colorScaleIndex={entry.stroke ? 0 : markColor.colorScaleIndex}
393
+ colorValueData={outline.colorValueData}
394
+ colorMode={outline.colorMode}
395
+ colorScaleIndex={outline.colorScaleIndex}
396
+ activityColorMode={outline.activityColorMode}
397
+ activityColorScaleIndex={outline.activityColorScaleIndex}
398
+ groupIndex={setup?.groupIndex ?? 0}
387
399
  constantColor={strokeConstantColor}
388
400
  strokeWidth={entry.strokeWidth ?? 0}
389
401
  zIndex={1}
@@ -396,9 +408,12 @@
396
408
  yData={yBottomData}
397
409
  {seriesData}
398
410
  curve={effectiveCurve}
399
- colorValueData={entry.stroke ? null : markColor.data}
400
- colorMode={entry.stroke ? 0 : markColor.colorMode}
401
- colorScaleIndex={entry.stroke ? 0 : markColor.colorScaleIndex}
411
+ colorValueData={outline.colorValueData}
412
+ colorMode={outline.colorMode}
413
+ colorScaleIndex={outline.colorScaleIndex}
414
+ activityColorMode={outline.activityColorMode}
415
+ activityColorScaleIndex={outline.activityColorScaleIndex}
416
+ groupIndex={setup?.groupIndex ?? 0}
402
417
  constantColor={strokeConstantColor}
403
418
  strokeWidth={entry.strokeWidth ?? 0}
404
419
  zIndex={1}
@@ -40,6 +40,9 @@
40
40
  let {
41
41
  table,
42
42
  selection = undefined,
43
+ selectionResponse = undefined,
44
+ nulls = undefined,
45
+ contributeDomain = undefined,
43
46
  x,
44
47
  x1: x1Prop,
45
48
  x2: x2Prop,
@@ -81,6 +84,9 @@
81
84
  opacity: () => opacity,
82
85
  transforms: () => transforms,
83
86
  selection: () => selection,
87
+ selectionResponse: () => selectionResponse,
88
+ nulls: () => nulls,
89
+ contributeDomain: () => contributeDomain,
84
90
  limit: () => limit,
85
91
  padding: () => padding,
86
92
  paddingInner: () => paddingInner,
@@ -278,7 +284,14 @@
278
284
  colorColumn: 'fill',
279
285
  bandAxes: { y: true },
280
286
  markColor,
281
- displayFields: resolvedTip.displayFields
287
+ displayFields: resolvedTip.displayFields,
288
+ otherStats: (point) => {
289
+ const id = point.__bandIdY;
290
+ const facet = point.__facetId;
291
+ return typeof id === 'number'
292
+ ? setup!.otherRows.statsAt(id, typeof facet === 'number' ? facet : null)
293
+ : null;
294
+ }
282
295
  })
283
296
  );
284
297
  });
@@ -301,8 +314,10 @@
301
314
  {y1Data}
302
315
  colorValueData={markColor.data}
303
316
  alphaData={opacityData}
317
+ share={setup?.otherRows.split ?? null}
304
318
  colorMode={markColor.colorMode}
305
319
  colorScaleIndex={markColor.colorScaleIndex}
320
+ groupIndex={setup?.groupIndex ?? 0}
306
321
  constantColor={markColor.constantColor}
307
322
  facetData={setup?.facetData}
308
323
  dataVersion={setup?.dataVersion || 0}
@@ -39,6 +39,9 @@
39
39
  let {
40
40
  table,
41
41
  selection = undefined,
42
+ selectionResponse = undefined,
43
+ nulls = undefined,
44
+ contributeDomain = undefined,
42
45
  x,
43
46
  y,
44
47
  y1: y1Prop,
@@ -80,6 +83,9 @@
80
83
  opacity: () => opacity,
81
84
  transforms: () => transforms,
82
85
  selection: () => selection,
86
+ selectionResponse: () => selectionResponse,
87
+ nulls: () => nulls,
88
+ contributeDomain: () => contributeDomain,
83
89
  limit: () => limit,
84
90
  padding: () => padding,
85
91
  paddingInner: () => paddingInner,
@@ -279,7 +285,14 @@
279
285
  colorColumn: 'fill',
280
286
  bandAxes: { x: true },
281
287
  markColor,
282
- displayFields: resolvedTip.displayFields
288
+ displayFields: resolvedTip.displayFields,
289
+ otherStats: (point) => {
290
+ const id = point.__bandIdX;
291
+ const facet = point.__facetId;
292
+ return typeof id === 'number'
293
+ ? setup!.otherRows.statsAt(id, typeof facet === 'number' ? facet : null)
294
+ : null;
295
+ }
283
296
  })
284
297
  );
285
298
  });
@@ -302,8 +315,10 @@
302
315
  {y1Data}
303
316
  colorValueData={markColor.data}
304
317
  alphaData={opacityData}
318
+ share={setup?.otherRows.split ?? null}
305
319
  colorMode={markColor.colorMode}
306
320
  colorScaleIndex={markColor.colorScaleIndex}
321
+ groupIndex={setup?.groupIndex ?? 0}
307
322
  constantColor={markColor.constantColor}
308
323
  facetData={setup?.facetData}
309
324
  dataVersion={setup?.dataVersion || 0}
@@ -42,6 +42,8 @@
42
42
  let {
43
43
  table,
44
44
  selection = undefined,
45
+ selectionResponse = undefined,
46
+ nulls = undefined,
45
47
  x,
46
48
  y,
47
49
  fill = null,
@@ -80,6 +82,8 @@
80
82
  radiusRange: () => radiusRange,
81
83
  transforms: () => transforms,
82
84
  selection: () => selection,
85
+ selectionResponse: () => selectionResponse,
86
+ nulls: () => nulls,
83
87
  limit: () => limit,
84
88
  preferredXScaleType: () => preferredXScaleType,
85
89
  preferredYScaleType: () => preferredYScaleType,
@@ -306,6 +310,7 @@
306
310
  colorValueData={markColor.data}
307
311
  colorMode={markColor.colorMode}
308
312
  colorScaleIndex={markColor.colorScaleIndex}
313
+ groupIndex={setup?.groupIndex ?? 0}
309
314
  constantColor={markColor.constantColor}
310
315
  sizeMode={markSize.sizeMode}
311
316
  sizeScaleIndex={markSize.sizeScaleIndex}
@@ -70,6 +70,8 @@
70
70
  let {
71
71
  table,
72
72
  selection = undefined,
73
+ selectionResponse = undefined,
74
+ nulls = undefined,
73
75
  x,
74
76
  y,
75
77
  stroke = null,
@@ -122,6 +124,8 @@
122
124
  dotRadius: () => dotRadius,
123
125
  transforms: () => transforms,
124
126
  selection: () => selection,
127
+ selectionResponse: () => selectionResponse,
128
+ nulls: () => nulls,
125
129
  limit: () => limit,
126
130
  preferredXScaleType: () => preferredXScaleType,
127
131
  preferredYScaleType: () => preferredYScaleType,
@@ -144,7 +148,9 @@
144
148
  inferMarkScaleType(entry.y, entry.table, entry.preferredYScaleType)
145
149
  );
146
150
 
147
- // Series grouping: z overrides stroke for grouping
151
+ // Series grouping: z overrides stroke for grouping. A selection dims a line
152
+ // by its stroke colour only; dimming by a separate z field is not supported
153
+ // yet (see activityReads in activity-reads.ts).
148
154
  const seriesChannelKey = entry.z != null ? 'z' : 'stroke';
149
155
  const markSeries = new MarkSeries(
150
156
  () => entry.z ?? entry.stroke,
@@ -570,6 +576,7 @@
570
576
  colorValueData={markColor.data}
571
577
  colorMode={markColor.colorMode}
572
578
  colorScaleIndex={markColor.colorScaleIndex}
579
+ groupIndex={setup?.groupIndex ?? 0}
573
580
  constantColor={markColor.constantColor}
574
581
  strokeWidth={entry.strokeWidth ?? 2}
575
582
  dotRadius={effectiveDotRadius}
@@ -11,6 +11,8 @@
11
11
  </script>
12
12
 
13
13
  <script lang="ts">
14
+ import type { SelectionResponse } from '../rendering/activity-reads';
15
+ import type { NullsResponse } from '../../types';
14
16
  import { getContext, onDestroy, untrack } from 'svelte';
15
17
  import { MarkLifecycleV2 } from './lifecycle/MarkLifecycleV2.svelte';
16
18
  import { ParallelLines } from '../rendering';
@@ -31,6 +33,9 @@
31
33
  strokeWidth?: number;
32
34
  curve?: CurveType;
33
35
  selection?: string;
36
+ /** How this mark responds to selections in its group (see BaseMarkProps). */
37
+ selectionResponse?: SelectionResponse;
38
+ nulls?: NullsResponse;
34
39
  transforms?: Transform[];
35
40
  }
36
41
 
@@ -43,6 +48,8 @@
43
48
  strokeWidth = 2,
44
49
  curve = 'linear',
45
50
  selection = undefined,
51
+ selectionResponse = undefined,
52
+ nulls = undefined,
46
53
  transforms = []
47
54
  }: Props = $props();
48
55
 
@@ -59,6 +66,8 @@
59
66
  stroke: () => stroke,
60
67
  scheme: () => scheme,
61
68
  selection: () => selection,
69
+ selectionResponse: () => selectionResponse,
70
+ nulls: () => nulls,
62
71
  transforms: () => transforms
63
72
  });
64
73
 
@@ -188,6 +197,7 @@
188
197
  colorValueData={markColor.data}
189
198
  colorMode={markColor.colorMode}
190
199
  colorScaleIndex={markColor.colorScaleIndex}
200
+ groupIndex={setup?.groupIndex ?? 0}
191
201
  constantColor={markColor.constantColor}
192
202
  axisOrder={currentAxisOrder}
193
203
  axisScaleIds={currentScaleIds}
@@ -9,6 +9,8 @@
9
9
  export declare const parallelParity: {
10
10
  reverseScales: boolean;
11
11
  };
12
+ import type { SelectionResponse } from '../rendering/activity-reads';
13
+ import type { NullsResponse } from '../../types';
12
14
  import type { FieldRef, ColorScheme, CurveType, Transform } from '../../types';
13
15
  interface Props {
14
16
  table: string;
@@ -19,6 +21,9 @@ interface Props {
19
21
  strokeWidth?: number;
20
22
  curve?: CurveType;
21
23
  selection?: string;
24
+ /** How this mark responds to selections in its group (see BaseMarkProps). */
25
+ selectionResponse?: SelectionResponse;
26
+ nulls?: NullsResponse;
22
27
  transforms?: Transform[];
23
28
  }
24
29
  declare const ParallelCoordinatesMark: import("svelte").Component<Props, {}, "">;
@@ -47,6 +47,8 @@
47
47
  let {
48
48
  table,
49
49
  selection = undefined,
50
+ selectionResponse = undefined,
51
+ nulls = undefined,
50
52
  x = null,
51
53
  x1: x1Prop = null,
52
54
  x2: x2Prop = null,
@@ -95,6 +97,8 @@
95
97
  opacity: () => opacity,
96
98
  transforms: () => transforms,
97
99
  selection: () => selection,
100
+ selectionResponse: () => selectionResponse,
101
+ nulls: () => nulls,
98
102
  limit: () => limit,
99
103
  preferredXScaleType: () => preferredXScaleType,
100
104
  preferredYScaleType: () => preferredYScaleType,
@@ -360,6 +364,7 @@
360
364
  alphaData={opacityData}
361
365
  colorMode={markColor.colorMode}
362
366
  colorScaleIndex={markColor.colorScaleIndex}
367
+ groupIndex={setup?.groupIndex ?? 0}
363
368
  constantColor={markColor.constantColor}
364
369
  facetData={setup?.facetData}
365
370
  dataVersion={setup?.dataVersion || 0}
@@ -47,6 +47,8 @@
47
47
  let {
48
48
  table,
49
49
  selection = undefined,
50
+ selectionResponse = undefined,
51
+ nulls = undefined,
50
52
  x,
51
53
  x1: x1Prop,
52
54
  x2: x2Prop,
@@ -90,6 +92,8 @@
90
92
  opacity: () => opacity,
91
93
  transforms: () => transforms,
92
94
  selection: () => selection,
95
+ selectionResponse: () => selectionResponse,
96
+ nulls: () => nulls,
93
97
  limit: () => limit,
94
98
  preferredYScaleType: () => preferredYScaleType,
95
99
  fitDomain: () => fitDomain,
@@ -351,6 +355,7 @@
351
355
  alphaData={opacityData}
352
356
  colorMode={markColor.colorMode}
353
357
  colorScaleIndex={markColor.colorScaleIndex}
358
+ groupIndex={setup?.groupIndex ?? 0}
354
359
  constantColor={markColor.constantColor}
355
360
  facetData={setup?.facetData}
356
361
  dataVersion={setup?.dataVersion || 0}
@@ -48,6 +48,8 @@
48
48
  let {
49
49
  table,
50
50
  selection = undefined,
51
+ selectionResponse = undefined,
52
+ nulls = undefined,
51
53
  x = null,
52
54
  x1: x1Prop = null,
53
55
  x2: x2Prop = null,
@@ -92,6 +94,8 @@
92
94
  opacity: () => opacity,
93
95
  transforms: () => transforms,
94
96
  selection: () => selection,
97
+ selectionResponse: () => selectionResponse,
98
+ nulls: () => nulls,
95
99
  limit: () => limit,
96
100
  preferredXScaleType: () => preferredXScaleType,
97
101
  fitDomain: () => fitDomain,
@@ -358,6 +362,7 @@
358
362
  alphaData={opacityData}
359
363
  colorMode={markColor.colorMode}
360
364
  colorScaleIndex={markColor.colorScaleIndex}
365
+ groupIndex={setup?.groupIndex ?? 0}
361
366
  constantColor={markColor.constantColor}
362
367
  facetData={setup?.facetData}
363
368
  dataVersion={setup?.dataVersion || 0}