@fundar/data-chart-telling 0.0.24 → 0.0.26
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/charts/bar/Chart.svelte +2 -0
- package/dist/charts/heatmap/Chart.svelte +3 -1
- package/dist/charts/heatmap/Chart.svelte.d.ts +1 -2
- package/dist/charts/line/Chart.svelte +2 -0
- package/dist/charts/pyramid/Chart.svelte +3 -1
- package/dist/charts/pyramid/Chart.svelte.d.ts +1 -2
- package/dist/charts/scatter/Chart.svelte +95 -0
- package/dist/charts/scatter/Chart.svelte.d.ts +28 -0
- package/dist/configuration/config.svelte.js +13 -1
- package/dist/configuration/themes/index.d.ts +76 -0
- package/dist/index.d.ts +20 -14
- package/dist/index.js +9 -3
- package/dist/layout/coordinates/CoordinatesLayout.svelte +95 -0
- package/dist/layout/{plot/RuleLayout.svelte.d.ts → coordinates/CoordinatesLayout.svelte.d.ts} +13 -16
- package/dist/layout/coordinates/margins.d.ts +16 -0
- package/dist/layout/coordinates/margins.js +11 -0
- package/dist/{plots/geo → layout/coordinates}/projections/argentina.d.ts +1 -1
- package/dist/layout/{geo → coordinates}/resolveProjection.d.ts +1 -1
- package/dist/layout/coordinates/resolveProjection.js +24 -0
- package/dist/{plots/geo → layout/coordinates}/zoom.svelte.d.ts +1 -1
- package/dist/layout/geometry/GeometryLayout.svelte +231 -0
- package/dist/layout/geometry/GeometryLayout.svelte.d.ts +62 -0
- package/dist/layout/plot/BasePlotLayout.svelte +142 -155
- package/dist/layout/plot/BasePlotLayout.svelte.d.ts +61 -51
- package/dist/layout/plot/margins.d.ts +0 -16
- package/dist/layout/plot/margins.js +0 -11
- package/dist/layout/{plot/AxisLayout.svelte → scales/ScalesLayout.svelte} +23 -16
- package/dist/layout/{plot/AxisLayout.svelte.d.ts → scales/ScalesLayout.svelte.d.ts} +4 -5
- package/dist/layout/scales/buildScale.d.ts +8 -0
- package/dist/layout/scales/buildScale.js +43 -0
- package/dist/layout/styles/StylesLayout.svelte +75 -0
- package/dist/layout/styles/StylesLayout.svelte.d.ts +15 -0
- package/dist/{plots/geo → layout/styles}/TileLayer.svelte +2 -2
- package/dist/{plots/geo → layout/styles}/TileLayer.svelte.d.ts +1 -1
- package/dist/layout/tooltip/Tooltip.svelte +16 -20
- package/dist/layout/tooltip/Tooltip.svelte.d.ts +5 -0
- package/dist/layout/tooltip/TooltipLayout.svelte +7 -1
- package/dist/layout/tooltip/TooltipLayout.svelte.d.ts +4 -0
- package/dist/layout/tooltip/controller.svelte.d.ts +4 -5
- package/dist/layout/tooltip/controller.svelte.js +28 -16
- package/dist/layout/tooltip/resolveTooltipPlacement.d.ts +24 -0
- package/dist/layout/tooltip/resolveTooltipPlacement.js +49 -0
- package/dist/layout/tooltip/utils.d.ts +27 -19
- package/dist/layout/tooltip/utils.js +16 -15
- package/dist/markers/BarMarker.svelte +92 -0
- package/dist/markers/BarMarker.svelte.d.ts +7 -0
- package/dist/markers/CellMarker.svelte +21 -0
- package/dist/markers/CellMarker.svelte.d.ts +7 -0
- package/dist/markers/ContourMarker.svelte +28 -0
- package/dist/markers/ContourMarker.svelte.d.ts +7 -0
- package/dist/markers/DeltaMarker.svelte +32 -39
- package/dist/markers/DeltaMarker.svelte.d.ts +4 -5
- package/dist/markers/DotMarker.svelte +35 -6
- package/dist/markers/DotMarker.svelte.d.ts +11 -2
- package/dist/markers/GeoFeaturesMarker.svelte +19 -0
- package/dist/markers/GeoFeaturesMarker.svelte.d.ts +7 -0
- package/dist/markers/GeoHoverMarker.svelte +25 -0
- package/dist/markers/GeoHoverMarker.svelte.d.ts +9 -0
- package/dist/markers/GraticuleMarker.svelte +18 -0
- package/dist/markers/GraticuleMarker.svelte.d.ts +7 -0
- package/dist/markers/HoverMarker.svelte +32 -33
- package/dist/markers/HoverMarker.svelte.d.ts +15 -9
- package/dist/markers/LineMarker.svelte +19 -0
- package/dist/markers/LineMarker.svelte.d.ts +7 -0
- package/dist/markers/LinkMarker.svelte +42 -0
- package/dist/markers/LinkMarker.svelte.d.ts +7 -0
- package/dist/markers/RuleMarker.svelte +24 -0
- package/dist/markers/RuleMarker.svelte.d.ts +10 -0
- package/dist/markers/SphereMarker.svelte +15 -0
- package/dist/markers/SphereMarker.svelte.d.ts +7 -0
- package/dist/markers/TextMarker.svelte +1 -1
- package/dist/markers/TextMarker.svelte.d.ts +1 -1
- package/dist/markers/VectorMarker.svelte +20 -0
- package/dist/markers/VectorMarker.svelte.d.ts +7 -0
- package/dist/markers/inset/InsetMarker.svelte +38 -45
- package/dist/markers/inset/InsetMarker.svelte.d.ts +6 -2
- package/dist/plots/bar/Plot.svelte +54 -84
- package/dist/plots/bar/Plot.svelte.d.ts +4 -5
- package/dist/plots/bar/ValueLabels.svelte +1 -1
- package/dist/plots/bar/ValueLabels.svelte.d.ts +1 -1
- package/dist/plots/bar/buildBarMarkers.d.ts +30 -0
- package/dist/plots/bar/buildBarMarkers.js +100 -0
- package/dist/plots/bar/layout.svelte.d.ts +1 -2
- package/dist/plots/bar/layout.svelte.js +1 -1
- package/dist/plots/geo/Plot.svelte +113 -387
- package/dist/plots/geo/Plot.svelte.d.ts +5 -4
- package/dist/plots/geo/buildGeoMarkers.d.ts +33 -0
- package/dist/plots/geo/buildGeoMarkers.js +47 -0
- package/dist/plots/heatmap/Plot.svelte +24 -49
- package/dist/plots/heatmap/Plot.svelte.d.ts +4 -5
- package/dist/plots/heatmap/ValueLabels.svelte +2 -2
- package/dist/plots/heatmap/ValueLabels.svelte.d.ts +2 -2
- package/dist/plots/heatmap/buildCellMarkers.d.ts +21 -0
- package/dist/plots/heatmap/buildCellMarkers.js +25 -0
- package/dist/plots/line/Plot.svelte +68 -141
- package/dist/plots/line/Plot.svelte.d.ts +4 -4
- package/dist/plots/line/ValueLabels.svelte +94 -49
- package/dist/plots/line/ValueLabels.svelte.d.ts +6 -1
- package/dist/plots/line/buildLineMarkers.d.ts +15 -0
- package/dist/plots/line/buildLineMarkers.js +57 -0
- package/dist/plots/pyramid/Plot.svelte +41 -117
- package/dist/plots/pyramid/Plot.svelte.d.ts +4 -5
- package/dist/plots/pyramid/ValueLabels.svelte +1 -1
- package/dist/plots/pyramid/ValueLabels.svelte.d.ts +1 -1
- package/dist/plots/pyramid/buildPyramidBarMarkers.d.ts +19 -0
- package/dist/plots/pyramid/buildPyramidBarMarkers.js +32 -0
- package/dist/plots/scatter/Plot.svelte +206 -0
- package/dist/plots/{bar/BarSegments.svelte.d.ts → scatter/Plot.svelte.d.ts} +9 -20
- package/dist/plots/scatter/ValueLabels.svelte +106 -0
- package/dist/{layout/plot/GridLayout.svelte.d.ts → plots/scatter/ValueLabels.svelte.d.ts} +11 -5
- package/dist/plots/scatter/buildScatterMarkers.d.ts +11 -0
- package/dist/plots/scatter/buildScatterMarkers.js +37 -0
- package/dist/plots/scatter/resolveRadiusPaddedDomain.d.ts +10 -0
- package/dist/plots/scatter/resolveRadiusPaddedDomain.js +23 -0
- package/dist/plots/utils/declutter.d.ts +82 -33
- package/dist/plots/utils/declutter.js +182 -40
- package/dist/plots/utils/geoAccessors.d.ts +1 -1
- package/dist/plots/utils/geoAccessors.js +1 -1
- package/dist/plots/utils/segments.d.ts +17 -10
- package/dist/plots/utils/segments.js +26 -16
- package/dist/types/charts/common.d.ts +1 -1
- package/dist/types/charts/props.d.ts +5 -6
- package/dist/types/configuration/styling.d.ts +24 -2
- package/dist/types/{plots/scales/geo.d.ts → layout/coordinates.d.ts} +33 -1
- package/dist/types/layout/geometry.d.ts +17 -0
- package/dist/types/{plots/axis.d.ts → layout/scales.d.ts} +11 -0
- package/dist/types/layout/styles.d.ts +126 -0
- package/dist/types/layout/tooltip.d.ts +20 -1
- package/dist/types/markers/all.d.ts +11 -0
- package/dist/types/markers/base.d.ts +45 -0
- package/dist/types/markers/base.js +1 -0
- package/dist/types/markers/common.d.ts +64 -16
- package/dist/types/markers/geo.d.ts +75 -100
- package/dist/types/markers/line.d.ts +34 -0
- package/dist/types/markers/line.js +1 -0
- package/dist/types/markers/props.d.ts +1 -1
- package/dist/types/plots/data/common.d.ts +1 -1
- package/dist/types/plots/data/scatter.d.ts +13 -0
- package/dist/types/plots/data/scatter.js +1 -0
- package/dist/types/plots/props.d.ts +46 -74
- package/dist/types/plots/segments/common.d.ts +6 -12
- package/dist/types/plots/segments/config.d.ts +1 -1
- package/dist/types/plots/styling.d.ts +10 -0
- package/dist/{plots/utils → utils}/delta.d.ts +2 -2
- package/dist/{plots/utils → utils}/delta.js +1 -1
- package/dist/utils/edgeAwareAnchor.d.ts +37 -0
- package/dist/utils/edgeAwareAnchor.js +65 -0
- package/dist/utils/grouping.d.ts +1 -1
- package/dist/utils/interpolate.d.ts +1 -1
- package/package.json +3 -1
- package/dist/layout/geo/GeoLayout.svelte +0 -51
- package/dist/layout/geo/GeoLayout.svelte.d.ts +0 -24
- package/dist/layout/geo/resolveProjection.js +0 -48
- package/dist/layout/plot/GridLayout.svelte +0 -30
- package/dist/layout/plot/RuleLayout.svelte +0 -111
- package/dist/plots/bar/BarSegments.svelte +0 -69
- package/dist/types/plots/delta.d.ts +0 -19
- package/dist/types/plots/styles/common.d.ts +0 -52
- package/dist/types/plots/styles/geo.d.ts +0 -42
- /package/dist/{plots/geo → layout/coordinates}/projections/argentina.js +0 -0
- /package/dist/{plots/geo → layout/coordinates}/projections/fit.d.ts +0 -0
- /package/dist/{plots/geo → layout/coordinates}/projections/fit.js +0 -0
- /package/dist/{plots/geo → layout/coordinates}/rotate.svelte.d.ts +0 -0
- /package/dist/{plots/geo → layout/coordinates}/rotate.svelte.js +0 -0
- /package/dist/{plots/geo → layout/coordinates}/zoom.svelte.js +0 -0
- /package/dist/types/{plots/axis.js → layout/coordinates.js} +0 -0
- /package/dist/types/{plots/delta.js → layout/geometry.js} +0 -0
- /package/dist/types/{plots/scales/geo.js → layout/scales.js} +0 -0
- /package/dist/types/{plots/styles/common.js → layout/styles.js} +0 -0
- /package/dist/types/{plots/styles/geo.js → markers/all.js} +0 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `graticule`/`sphere`/`contour` opt into drawing underneath the base map's
|
|
3
|
+
* own fill/stroke instead of on top of it — see each config's own `behind`
|
|
4
|
+
* doc comment.
|
|
5
|
+
*/
|
|
6
|
+
function isBehindMarker(marker) {
|
|
7
|
+
return ((marker.type === 'graticule' || marker.type === 'sphere' || marker.type === 'contour') &&
|
|
8
|
+
marker.behind === true);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Every marker for one `GeoPlot` render, in final draw order: any authored
|
|
12
|
+
* marker with `behind: true`, then the base map itself (one `'geo'` marker
|
|
13
|
+
* per resolved feature style), then the rest of the authored markers in
|
|
14
|
+
* order, with any `hover` marker moved last.
|
|
15
|
+
*/
|
|
16
|
+
export function buildGeoMarkers(args) {
|
|
17
|
+
const { styleGroups, resolveBaseFill, fillOpacity, stroke, strokeWidth, axisColor, onFeatureClick, markers, hoverActive, hoverPointById, isOverInset, setHoverMatch, clearHoverMatch, } = args;
|
|
18
|
+
const featureMarkers = styleGroups.map((group) => ({
|
|
19
|
+
type: 'geo',
|
|
20
|
+
data: group.data,
|
|
21
|
+
fill: (d) => group.style.fill ?? resolveBaseFill(d),
|
|
22
|
+
fillOpacity: group.style.fillOpacity ?? fillOpacity ?? 1,
|
|
23
|
+
stroke: group.style.stroke ?? stroke ?? axisColor,
|
|
24
|
+
strokeWidth: group.style.strokeWidth ?? strokeWidth ?? 0.5,
|
|
25
|
+
onclick: onFeatureClick ? (e, d) => onFeatureClick(d, e) : undefined,
|
|
26
|
+
onpointerenter: hoverActive
|
|
27
|
+
? (e, d) => {
|
|
28
|
+
if (isOverInset(e))
|
|
29
|
+
return;
|
|
30
|
+
const hp = hoverPointById.get(d.__id);
|
|
31
|
+
if (hp)
|
|
32
|
+
setHoverMatch([hp.row]);
|
|
33
|
+
}
|
|
34
|
+
: undefined,
|
|
35
|
+
onpointerleave: hoverActive
|
|
36
|
+
? (e) => {
|
|
37
|
+
if (isOverInset(e))
|
|
38
|
+
return;
|
|
39
|
+
clearHoverMatch();
|
|
40
|
+
}
|
|
41
|
+
: undefined,
|
|
42
|
+
}));
|
|
43
|
+
const behindMarkers = markers.filter(isBehindMarker);
|
|
44
|
+
const frontMarkers = markers.filter((m) => !isBehindMarker(m) && m.type !== 'geo-hover');
|
|
45
|
+
const hoverMarker = markers.find((m) => m.type === 'geo-hover');
|
|
46
|
+
return [...behindMarkers, ...featureMarkers, ...frontMarkers, ...(hoverMarker ? [hoverMarker] : [])];
|
|
47
|
+
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
<script lang="ts" generics="TData extends Record<string, unknown>">
|
|
2
|
-
import { Cell } from 'svelteplot';
|
|
3
2
|
import { resolveAccessor } from '../utils/accessors';
|
|
4
3
|
import { validateSegments } from '../utils/segments';
|
|
5
4
|
import { buildSeries } from '../../utils/grouping';
|
|
@@ -7,19 +6,16 @@
|
|
|
7
6
|
import { getConfiguration } from '../../configuration/config.svelte';
|
|
8
7
|
import { getLegendInteraction } from '../../layout/legend/interaction.svelte';
|
|
9
8
|
import { disabledFillOverride } from '../utils/legendDisabled';
|
|
9
|
+
import { buildCellMarkers } from './buildCellMarkers';
|
|
10
10
|
import BasePlotLayout from '../../layout/plot/BasePlotLayout.svelte';
|
|
11
|
-
import AxisLayout from '../../layout/plot/AxisLayout.svelte';
|
|
12
|
-
import GridLayout from '../../layout/plot/GridLayout.svelte';
|
|
13
|
-
import RuleLayout from '../../layout/plot/RuleLayout.svelte';
|
|
14
11
|
import ValueLabels from './ValueLabels.svelte';
|
|
15
12
|
import { hasHoverMarker, resolveHoverStrategy, resolveHoverSync } from '../../layout/tooltip/utils';
|
|
16
13
|
import type { BasePlotProps } from '../../types/plots/props';
|
|
17
|
-
import type { AxisValue } from '../../types/
|
|
14
|
+
import type { AxisValue, AxisBasedScalesConfig } from '../../types/layout/scales';
|
|
18
15
|
import type { SeriesProps, DataProps } from '../../types/plots/data/common';
|
|
19
|
-
import type {
|
|
20
|
-
import type { BasePlotStyles } from '../../types/plots/styles/common';
|
|
16
|
+
import type { BasePlotStylesConfig } from '../../types/layout/styles';
|
|
21
17
|
import type { CellSegmentStyle } from '../../types/plots/segments/common';
|
|
22
|
-
import type {
|
|
18
|
+
import type { AxisBasedMarkersConfig } from '../../types/markers/common';
|
|
23
19
|
|
|
24
20
|
/**
|
|
25
21
|
* A categorical grid of value-coloured cells. Accepts either a pre-built
|
|
@@ -33,9 +29,9 @@
|
|
|
33
29
|
type Props = BasePlotProps<
|
|
34
30
|
SeriesProps<TData> | DataProps<TData>,
|
|
35
31
|
TData,
|
|
36
|
-
|
|
32
|
+
BasePlotStylesConfig,
|
|
37
33
|
CellSegmentStyle,
|
|
38
|
-
|
|
34
|
+
AxisBasedMarkersConfig,
|
|
39
35
|
AxisBasedScalesConfig<TData>
|
|
40
36
|
>;
|
|
41
37
|
|
|
@@ -185,17 +181,10 @@
|
|
|
185
181
|
);
|
|
186
182
|
|
|
187
183
|
/**
|
|
188
|
-
* One
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
*
|
|
192
|
-
* scale collapses every row to the same (wrong) value instead of the
|
|
193
|
-
* literal numbers set on each segment. A literal, per-call constant (one
|
|
194
|
-
* call per style bucket) bypasses that entirely, which is exactly how
|
|
195
|
-
* bar/line avoid the same trap (one mark per visual segment). `fill`
|
|
196
|
-
* stays a per-cell accessor within each group — unlike fillOpacity, it
|
|
197
|
-
* must keep varying continuously with the underlying value wherever a
|
|
198
|
-
* segment doesn't explicitly override it.
|
|
184
|
+
* One marker per *distinct resolved style*, not one for the whole
|
|
185
|
+
* dataset — svelteplot's opacity/numeric scale machinery requires
|
|
186
|
+
* `fillOpacity`/`strokeWidth` to be constant per mark instance, unlike
|
|
187
|
+
* `fill`, which stays a per-row accessor.
|
|
199
188
|
*/
|
|
200
189
|
type StyleGroup = { style: CellSegmentStyle; data: TData[] };
|
|
201
190
|
const styleGroups = $derived.by((): StyleGroup[] => {
|
|
@@ -224,43 +213,31 @@
|
|
|
224
213
|
y: { type: 'band', domain: yDomain, ...(scales.y ?? {}) },
|
|
225
214
|
});
|
|
226
215
|
|
|
227
|
-
const
|
|
228
|
-
|
|
229
|
-
|
|
216
|
+
const hover = $derived({
|
|
217
|
+
active: tooltip != null || hasHoverMarker(markers),
|
|
218
|
+
points: hoverPoints,
|
|
219
|
+
label: (d: TData) => fmtVal(Number(getZ(d)), ''),
|
|
220
|
+
strategy: resolveHoverStrategy(tooltip?.strategy, markers, 'punctual'),
|
|
221
|
+
sync: resolveHoverSync(tooltip?.sync, markers),
|
|
222
|
+
tooltip,
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
const cellMarkers = $derived(buildCellMarkers({ styleGroups, getX, getY, getZ, colorScale }));
|
|
230
226
|
</script>
|
|
231
227
|
|
|
232
228
|
<BasePlotLayout
|
|
233
229
|
{width}
|
|
234
230
|
{height}
|
|
231
|
+
{styles}
|
|
235
232
|
data={flat}
|
|
236
233
|
{getX}
|
|
237
234
|
{getY}
|
|
238
|
-
{
|
|
239
|
-
label={(d) => fmtVal(Number(getZ(d)), '')}
|
|
240
|
-
{tooltip}
|
|
241
|
-
{hoverActive}
|
|
242
|
-
{hoverStrategy}
|
|
243
|
-
{hoverSync}
|
|
235
|
+
{hover}
|
|
244
236
|
scales={resolvedScales}
|
|
245
237
|
{margins}
|
|
238
|
+
markers={[...cellMarkers, ...markers]}
|
|
239
|
+
seriesData={resolvedSeries}
|
|
246
240
|
>
|
|
247
|
-
{#snippet children({ matchedPoints, ruleX, ruleY, impliesRuleX, impliesRuleY, numericMargins })}
|
|
248
|
-
<AxisLayout data={flat} {getX} {getY} {width} {height} {numericMargins} scales={resolvedScales} />
|
|
249
|
-
<GridLayout scales={resolvedScales} />
|
|
250
|
-
<RuleLayout {markers} seriesData={resolvedSeries} {matchedPoints} {ruleX} {ruleY} {impliesRuleX} {impliesRuleY} showHoverLabels={false}>
|
|
251
|
-
{#each styleGroups as group, i (i)}
|
|
252
|
-
<Cell
|
|
253
|
-
data={group.data as unknown as Record<string | symbol, never>[]}
|
|
254
|
-
x={getX}
|
|
255
|
-
y={getY}
|
|
256
|
-
fill={(d) => group.style.fill ?? colorScale(Number(getZ(d as TData)))}
|
|
257
|
-
fillOpacity={group.style.fillOpacity ?? 1}
|
|
258
|
-
stroke={group.style.stroke}
|
|
259
|
-
strokeWidth={group.style.strokeWidth ?? 0}
|
|
260
|
-
inset={0.5}
|
|
261
|
-
/>
|
|
262
|
-
{/each}
|
|
263
|
-
|
|
264
241
|
{#if showVals}
|
|
265
242
|
<ValueLabels
|
|
266
243
|
data={flat}
|
|
@@ -272,6 +249,4 @@
|
|
|
272
249
|
defaultColor={cfg.continuous.labelColor}
|
|
273
250
|
/>
|
|
274
251
|
{/if}
|
|
275
|
-
</RuleLayout>
|
|
276
|
-
{/snippet}
|
|
277
252
|
</BasePlotLayout>
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import type { BasePlotProps } from '../../types/plots/props';
|
|
2
|
+
import type { AxisBasedScalesConfig } from '../../types/layout/scales';
|
|
2
3
|
import type { SeriesProps, DataProps } from '../../types/plots/data/common';
|
|
3
|
-
import type {
|
|
4
|
-
import type {
|
|
5
|
-
import type { CellSegmentStyle } from '../../types/plots/segments/common';
|
|
6
|
-
import type { Marker } from '../../types/markers/common';
|
|
4
|
+
import type { BasePlotStylesConfig } from '../../types/layout/styles';
|
|
5
|
+
import type { AxisBasedMarkersConfig } from '../../types/markers/common';
|
|
7
6
|
declare function $$render<TData extends Record<string, unknown>>(): {
|
|
8
|
-
props: BasePlotProps<SeriesProps<TData> | DataProps<TData>, TData,
|
|
7
|
+
props: BasePlotProps<SeriesProps<TData> | DataProps<TData>, TData, BasePlotStylesConfig, import("../..").AreaStyle, AxisBasedMarkersConfig, AxisBasedScalesConfig<TData>>;
|
|
9
8
|
exports: {};
|
|
10
9
|
bindings: "";
|
|
11
10
|
slots: {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts" generics="TData extends Record<string, unknown>">
|
|
2
2
|
import { Text } from 'svelteplot';
|
|
3
|
-
import type { AxisValue } from '../../types/
|
|
4
|
-
import type { ValuesStyle } from '../../types/
|
|
3
|
+
import type { AxisValue } from '../../types/layout/scales';
|
|
4
|
+
import type { ValuesStyle } from '../../types/layout/styles';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Renders every cell's value label in one mark — heatmaps have no
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { AxisValue } from '../../types/
|
|
2
|
-
import type { ValuesStyle } from '../../types/
|
|
1
|
+
import type { AxisValue } from '../../types/layout/scales';
|
|
2
|
+
import type { ValuesStyle } from '../../types/layout/styles';
|
|
3
3
|
declare function $$render<TData extends Record<string, unknown>>(): {
|
|
4
4
|
props: {
|
|
5
5
|
data: TData[];
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { AxisValue } from '../../types/layout/scales';
|
|
2
|
+
import type { CellSegmentStyle } from '../../types/plots/segments/common';
|
|
3
|
+
import type { CellMarkerConfig } from '../../types/markers/common';
|
|
4
|
+
/** One resolved-style bucket of cells, as grouped by `HeatmapPlot`'s own `styleGroups`. */
|
|
5
|
+
export type CellStyleGroup<TData> = {
|
|
6
|
+
style: CellSegmentStyle;
|
|
7
|
+
data: TData[];
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Every `'cell'` marker for one HeatmapPlot render: one marker per
|
|
11
|
+
* resolved-style bucket in `styleGroups`. `fill` stays a per-row accessor,
|
|
12
|
+
* falling back to `colorScale` wherever a segment doesn't set a literal
|
|
13
|
+
* `fill`.
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildCellMarkers<TData extends Record<string, unknown>>(args: {
|
|
16
|
+
styleGroups: CellStyleGroup<TData>[];
|
|
17
|
+
getX: (d: TData) => AxisValue;
|
|
18
|
+
getY: (d: TData) => AxisValue;
|
|
19
|
+
getZ: (d: TData) => AxisValue;
|
|
20
|
+
colorScale: (value: number) => string;
|
|
21
|
+
}): CellMarkerConfig[];
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every `'cell'` marker for one HeatmapPlot render: one marker per
|
|
3
|
+
* resolved-style bucket in `styleGroups`. `fill` stays a per-row accessor,
|
|
4
|
+
* falling back to `colorScale` wherever a segment doesn't set a literal
|
|
5
|
+
* `fill`.
|
|
6
|
+
*/
|
|
7
|
+
export function buildCellMarkers(args) {
|
|
8
|
+
const { styleGroups, getX, getY, getZ, colorScale } = args;
|
|
9
|
+
return styleGroups.map((group) => ({
|
|
10
|
+
type: 'cell',
|
|
11
|
+
data: group.data,
|
|
12
|
+
x: getX,
|
|
13
|
+
y: getY,
|
|
14
|
+
fill: (d) => group.style.fill ?? colorScale(Number(getZ(d))),
|
|
15
|
+
style: {
|
|
16
|
+
fillOpacity: group.style.fillOpacity ?? 1,
|
|
17
|
+
stroke: group.style.stroke,
|
|
18
|
+
strokeWidth: group.style.strokeWidth ?? 0,
|
|
19
|
+
strokeOpacity: group.style.strokeOpacity,
|
|
20
|
+
strokeDasharray: group.style.strokeDasharray,
|
|
21
|
+
borderRadius: group.style.borderRadius,
|
|
22
|
+
},
|
|
23
|
+
inset: 0.5,
|
|
24
|
+
}));
|
|
25
|
+
}
|
|
@@ -2,36 +2,30 @@
|
|
|
2
2
|
lang="ts"
|
|
3
3
|
generics="TData extends Record<string, unknown>"
|
|
4
4
|
>
|
|
5
|
-
import { SvelteMap } from 'svelte/reactivity';
|
|
6
|
-
import { Line, Dot } from 'svelteplot';
|
|
7
5
|
import { resolveAccessor } from '../utils/accessors';
|
|
8
6
|
import { getConfiguration } from '../../configuration/config.svelte';
|
|
9
7
|
import { paletteColor } from '../../utils/color';
|
|
10
8
|
import { buildSeries } from '../../utils/grouping';
|
|
11
9
|
import { getLegendInteraction } from '../../layout/legend/interaction.svelte';
|
|
12
10
|
import { disabledStrokeOverride, disabledDotsOverride } from '../utils/legendDisabled';
|
|
11
|
+
import { buildLineMarkers } from './buildLineMarkers';
|
|
13
12
|
import BasePlotLayout from '../../layout/plot/BasePlotLayout.svelte';
|
|
14
|
-
import AxisLayout from '../../layout/plot/AxisLayout.svelte';
|
|
15
|
-
import GridLayout from '../../layout/plot/GridLayout.svelte';
|
|
16
|
-
import RuleLayout from '../../layout/plot/RuleLayout.svelte';
|
|
17
|
-
import HoverMarker from '../../markers/HoverMarker.svelte';
|
|
18
13
|
import ValueLabels from './ValueLabels.svelte';
|
|
19
14
|
import { hasHoverMarker, resolveHoverStrategy, resolveHoverSync } from '../../layout/tooltip/utils';
|
|
20
|
-
import { buildGroupedSeries, validateSegments,
|
|
15
|
+
import { buildGroupedSeries, validateSegments, buildScopedMarkerGroups } from '../utils/segments';
|
|
21
16
|
import type { BasePlotProps } from '../../types/plots/props';
|
|
22
|
-
import type { AxisValue } from '../../types/
|
|
17
|
+
import type { AxisValue, AxisBasedScalesConfig } from '../../types/layout/scales';
|
|
23
18
|
import type { Series, SeriesProps, DataProps } from '../../types/plots/data/common';
|
|
24
|
-
import type {
|
|
25
|
-
import type { BasePlotStyles } from '../../types/plots/styles/common';
|
|
19
|
+
import type { BasePlotStylesConfig } from '../../types/layout/styles';
|
|
26
20
|
import type { LineSegmentStyle } from '../../types/plots/segments/common';
|
|
27
|
-
import type {
|
|
21
|
+
import type { LineMarkersConfig } from '../../types/markers/line';
|
|
28
22
|
|
|
29
23
|
type Props = BasePlotProps<
|
|
30
24
|
SeriesProps<TData> | DataProps<TData>,
|
|
31
25
|
TData,
|
|
32
|
-
|
|
26
|
+
BasePlotStylesConfig,
|
|
33
27
|
LineSegmentStyle,
|
|
34
|
-
|
|
28
|
+
LineMarkersConfig,
|
|
35
29
|
AxisBasedScalesConfig<TData>
|
|
36
30
|
>;
|
|
37
31
|
|
|
@@ -60,17 +54,6 @@
|
|
|
60
54
|
buildGroupedSeries<Series<TData>, LineSegmentStyle>(resolvedSeries, segments),
|
|
61
55
|
);
|
|
62
56
|
|
|
63
|
-
const seriesMarkers = $derived.by(() => {
|
|
64
|
-
const map = new SvelteMap<string, Marker[]>();
|
|
65
|
-
for (const marker of markers) {
|
|
66
|
-
if ((marker.type === 'component' || marker.type === 'hover') && marker.series) {
|
|
67
|
-
if (!map.has(marker.series)) map.set(marker.series, []);
|
|
68
|
-
map.get(marker.series)!.push(marker);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
return map;
|
|
72
|
-
});
|
|
73
|
-
|
|
74
57
|
const cfg = $derived(getConfiguration());
|
|
75
58
|
const showVals = $derived(styles.values?.show ?? false);
|
|
76
59
|
|
|
@@ -102,134 +85,78 @@
|
|
|
102
85
|
.filter(({ lastRow }) => lastRow !== undefined),
|
|
103
86
|
);
|
|
104
87
|
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
88
|
+
const hover = $derived({
|
|
89
|
+
active: tooltip != null || hasHoverMarker(markers),
|
|
90
|
+
points: hoverPoints,
|
|
91
|
+
label: (r: TData) => String(yAcc(r)),
|
|
92
|
+
strategy: resolveHoverStrategy(tooltip?.strategy, markers, 'x'),
|
|
93
|
+
sync: resolveHoverSync(tooltip?.sync, markers),
|
|
94
|
+
tooltip,
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
const lineMarkers = $derived(
|
|
98
|
+
buildLineMarkers({
|
|
99
|
+
groupedSeries,
|
|
100
|
+
disabledStrokeFor: (name) => disabledStrokeOverride(legendInteraction?.disabledSeries.get(name)),
|
|
101
|
+
disabledDotsFor: (name) => disabledDotsOverride(legendInteraction?.disabledSeries.get(name)),
|
|
102
|
+
}),
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
const scopedGroups = $derived(
|
|
106
|
+
buildScopedMarkerGroups<TData, Series<TData>, LineSegmentStyle>({
|
|
107
|
+
groupedSeries,
|
|
108
|
+
segments,
|
|
109
|
+
colorFor: (_series, seriesIndex) => paletteColor(seriesIndex, cfg.palette),
|
|
110
|
+
segmentColorFor: (style, defaultColor) => style?.stroke?.stroke ?? defaultColor,
|
|
111
|
+
}),
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
// End-of-line labels can grow past the plot's own content box, into its
|
|
115
|
+
// margin — reserving real space there (rather than padding the domain,
|
|
116
|
+
// which would falsely imply data exists past the last real point) is
|
|
117
|
+
// what ValueLabels's own overflow measurement feeds into here. Grown
|
|
118
|
+
// monotonically (never shrunk) from that real `getBBox()` measurement:
|
|
119
|
+
// once the real overflow reaches ~0 (the margin now fits it), reporting
|
|
120
|
+
// that same value again is a no-op (`Math.max` of an unchanged value),
|
|
121
|
+
// which is what keeps this converging instead of oscillating between
|
|
122
|
+
// "shrink margin → overflow reappears → grow margin → …". Local to this
|
|
123
|
+
// one `<Plot>` instance — see ValueLabels.svelte's own doc comment for
|
|
124
|
+
// why that locality (vs. svelteplot's shared margin context) matters.
|
|
125
|
+
let measuredLabelMargin = $state({ left: 0, right: 0 });
|
|
126
|
+
|
|
127
|
+
function handleLabelOverflow(overflow: { left: number; right: number }) {
|
|
128
|
+
const left = Math.max(measuredLabelMargin.left, overflow.left);
|
|
129
|
+
const right = Math.max(measuredLabelMargin.right, overflow.right);
|
|
130
|
+
if (left !== measuredLabelMargin.left || right !== measuredLabelMargin.right) {
|
|
131
|
+
measuredLabelMargin = { left, right };
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const resolvedMargins = $derived.by(() => {
|
|
136
|
+
if (measuredLabelMargin.left <= 0 && measuredLabelMargin.right <= 0) return margins;
|
|
137
|
+
const out = { ...margins };
|
|
138
|
+
if (measuredLabelMargin.right > 0 && margins?.right === undefined) out.right = measuredLabelMargin.right;
|
|
139
|
+
if (measuredLabelMargin.left > 0 && margins?.left === undefined) out.left = measuredLabelMargin.left;
|
|
140
|
+
return out;
|
|
141
|
+
});
|
|
108
142
|
</script>
|
|
109
143
|
|
|
110
144
|
<BasePlotLayout
|
|
111
145
|
{width}
|
|
112
146
|
{height}
|
|
147
|
+
{styles}
|
|
113
148
|
data={flat}
|
|
114
149
|
getX={xAcc}
|
|
115
150
|
getY={(d) => Number(yAcc(d))}
|
|
116
|
-
{
|
|
117
|
-
label={(r) => String(yAcc(r))}
|
|
118
|
-
{tooltip}
|
|
119
|
-
{hoverActive}
|
|
120
|
-
{hoverStrategy}
|
|
121
|
-
{hoverSync}
|
|
151
|
+
{hover}
|
|
122
152
|
{scales}
|
|
123
|
-
{
|
|
153
|
+
margins={resolvedMargins}
|
|
124
154
|
xTickRotate={scales?.x?.tickRotate}
|
|
155
|
+
markers={[...lineMarkers, ...markers]}
|
|
156
|
+
seriesData={resolvedSeries}
|
|
157
|
+
{scopedGroups}
|
|
125
158
|
>
|
|
126
|
-
{#snippet children({ matchedPoints, ruleX, ruleY, impliesRuleX, impliesRuleY, numericMargins })}
|
|
127
|
-
<AxisLayout data={flat} getX={xAcc} getY={(d) => Number(yAcc(d))} {width} {height} {numericMargins} {scales} />
|
|
128
|
-
<GridLayout {scales} />
|
|
129
|
-
<RuleLayout {markers} seriesData={resolvedSeries} {matchedPoints} {ruleX} {ruleY} {impliesRuleX} {impliesRuleY}>
|
|
130
|
-
{#each groupedSeries as group, seriesIndex (group.series.name)}
|
|
131
|
-
{@const defaultColor = paletteColor(seriesIndex, cfg.palette)}
|
|
132
|
-
{@const disabledOverride = legendInteraction?.disabledSeries.get(group.series.name)}
|
|
133
|
-
{@const disabledStroke = disabledStrokeOverride(disabledOverride)}
|
|
134
|
-
{@const disabledDots = disabledDotsOverride(disabledOverride)}
|
|
135
|
-
{#each group.visualSegments as seg, i (`${group.series.name}-${i}`)}
|
|
136
|
-
{@const strokeStyle = seg.style.stroke}
|
|
137
|
-
{@const lineData = seg.data as unknown as Record<string | symbol, never>[]}
|
|
138
|
-
<Line
|
|
139
|
-
data={lineData}
|
|
140
|
-
x={resolveAccessor(group.series.x)}
|
|
141
|
-
y={resolveAccessor(group.series.y)}
|
|
142
|
-
stroke={disabledStroke?.stroke ?? strokeStyle?.stroke ?? defaultColor}
|
|
143
|
-
strokeWidth={disabledStroke?.strokeWidth ?? strokeStyle?.strokeWidth ?? cfg.line.strokeWidth}
|
|
144
|
-
strokeOpacity={disabledStroke?.strokeOpacity ?? strokeStyle?.strokeOpacity ?? 1}
|
|
145
|
-
strokeDasharray={disabledStroke?.strokeDasharray ?? strokeStyle?.strokeDasharray}
|
|
146
|
-
strokeLinejoin={disabledStroke?.strokeLinejoin ?? strokeStyle?.strokeLinejoin}
|
|
147
|
-
strokeLinecap={disabledStroke?.strokeLinecap ?? strokeStyle?.strokeLinecap}
|
|
148
|
-
/>
|
|
149
|
-
{#if seg.style.dots}
|
|
150
|
-
{@const dotStyle = seg.style.dots}
|
|
151
|
-
<Dot
|
|
152
|
-
data={seg.data}
|
|
153
|
-
x={resolveAccessor(group.series.x)}
|
|
154
|
-
y={resolveAccessor(group.series.y)}
|
|
155
|
-
r={disabledDots?.dotRadius ?? dotStyle.dotRadius ?? cfg.line.dotRadius}
|
|
156
|
-
fill={disabledDots?.dotFill ?? dotStyle.dotFill ?? strokeStyle?.stroke ?? defaultColor}
|
|
157
|
-
symbol={disabledDots?.dotSymbol ?? dotStyle.dotSymbol ?? 'circle'}
|
|
158
|
-
stroke={disabledDots?.dotStroke ?? dotStyle.dotStroke ?? strokeStyle?.stroke ?? defaultColor}
|
|
159
|
-
strokeWidth={disabledDots?.dotStrokeWidth ?? dotStyle.dotStrokeWidth ?? 1}
|
|
160
|
-
fillOpacity={disabledDots?.dotFillOpacity ?? dotStyle.dotFillOpacity ?? strokeStyle?.strokeOpacity ?? 1}
|
|
161
|
-
strokeOpacity={disabledDots?.dotStrokeOpacity ?? dotStyle.dotStrokeOpacity ?? strokeStyle?.strokeOpacity ?? 1}
|
|
162
|
-
strokeDasharray={disabledDots?.dotStrokeDasharray ?? dotStyle.dotStrokeDasharray}
|
|
163
|
-
/>
|
|
164
|
-
{/if}
|
|
165
|
-
{/each}
|
|
166
|
-
|
|
167
|
-
{#each seriesMarkers.get(group.series.name) ?? [] as marker, i (`series-${group.series.name}-${marker.type}-${i}`)}
|
|
168
|
-
{#if marker.type === 'component'}
|
|
169
|
-
{#if marker.scope === 'segment'}
|
|
170
|
-
{@const segs = resolveSegmentsForSeries(segments, group.series.name)}
|
|
171
|
-
{@const xAccessor = resolveAccessor(group.series.x)}
|
|
172
|
-
{@const segmentDataArrays = getDataForSegments(group.series.data, xAccessor, segs)}
|
|
173
|
-
{#each segmentDataArrays as segmentData, segIdx (`${group.series.name}-marker-segment-${segIdx}`)}
|
|
174
|
-
{#if segmentData.length > 0}
|
|
175
|
-
{@const segmentColor = segs[segIdx]?.style?.stroke?.stroke ?? defaultColor}
|
|
176
|
-
<marker.component
|
|
177
|
-
{...marker.props}
|
|
178
|
-
series={group.series.name}
|
|
179
|
-
data={segmentData}
|
|
180
|
-
seriesColor={segmentColor}
|
|
181
|
-
/>
|
|
182
|
-
{/if}
|
|
183
|
-
{/each}
|
|
184
|
-
{:else}
|
|
185
|
-
{@const segs = resolveSegmentsForSeries(segments, group.series.name)}
|
|
186
|
-
{@const seriesColor = segs[0]?.style?.stroke?.stroke ?? defaultColor}
|
|
187
|
-
<marker.component
|
|
188
|
-
{...marker.props}
|
|
189
|
-
series={group.series.name}
|
|
190
|
-
data={group.series.data}
|
|
191
|
-
seriesColor={seriesColor}
|
|
192
|
-
/>
|
|
193
|
-
{/if}
|
|
194
|
-
{:else if marker.type === 'hover'}
|
|
195
|
-
{@const seriesPoints = matchedPoints.filter((p) => p.series === group.series.name)}
|
|
196
|
-
{#if marker.scope === 'segment'}
|
|
197
|
-
{@const segs = resolveSegmentsForSeries(segments, group.series.name)}
|
|
198
|
-
{#each segs as seg, segIdx (`${group.series.name}-hover-segment-${segIdx}`)}
|
|
199
|
-
{@const segPoints = seriesPoints.filter((p) => matchesSegmentX(p.x, seg))}
|
|
200
|
-
{#if segPoints.length > 0}
|
|
201
|
-
<HoverMarker
|
|
202
|
-
data={segPoints}
|
|
203
|
-
ruleX={marker.ruleX !== false && (impliesRuleX || marker.ruleX === true) ? ruleX : null}
|
|
204
|
-
ruleY={marker.ruleY !== false && (impliesRuleY || marker.ruleY === true) ? ruleY : null}
|
|
205
|
-
showLabels={marker.showLabels}
|
|
206
|
-
ruleStyle={marker.ruleStyle}
|
|
207
|
-
dotStyle={marker.dotStyle}
|
|
208
|
-
fontStyle={marker.fontStyle}
|
|
209
|
-
seriesColor={seg.style?.stroke?.stroke ?? defaultColor}
|
|
210
|
-
/>
|
|
211
|
-
{/if}
|
|
212
|
-
{/each}
|
|
213
|
-
{:else}
|
|
214
|
-
{@const segs = resolveSegmentsForSeries(segments, group.series.name)}
|
|
215
|
-
<HoverMarker
|
|
216
|
-
data={seriesPoints}
|
|
217
|
-
ruleX={marker.ruleX !== false && (impliesRuleX || marker.ruleX === true) ? ruleX : null}
|
|
218
|
-
ruleY={marker.ruleY !== false && (impliesRuleY || marker.ruleY === true) ? ruleY : null}
|
|
219
|
-
showLabels={marker.showLabels}
|
|
220
|
-
ruleStyle={marker.ruleStyle}
|
|
221
|
-
dotStyle={marker.dotStyle}
|
|
222
|
-
fontStyle={marker.fontStyle}
|
|
223
|
-
seriesColor={segs[0]?.style?.stroke?.stroke ?? defaultColor}
|
|
224
|
-
/>
|
|
225
|
-
{/if}
|
|
226
|
-
{/if}
|
|
227
|
-
{/each}
|
|
228
|
-
{/each}
|
|
229
|
-
|
|
230
159
|
{#if showVals}
|
|
231
|
-
<ValueLabels {lastPoints} values={styles.values} />
|
|
160
|
+
<ValueLabels {lastPoints} values={styles.values} onOverflow={handleLabelOverflow} />
|
|
232
161
|
{/if}
|
|
233
|
-
</RuleLayout>
|
|
234
|
-
{/snippet}
|
|
235
162
|
</BasePlotLayout>
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { BasePlotProps } from '../../types/plots/props';
|
|
2
|
+
import type { AxisBasedScalesConfig } from '../../types/layout/scales';
|
|
2
3
|
import type { SeriesProps, DataProps } from '../../types/plots/data/common';
|
|
3
|
-
import type {
|
|
4
|
-
import type { BasePlotStyles } from '../../types/plots/styles/common';
|
|
4
|
+
import type { BasePlotStylesConfig } from '../../types/layout/styles';
|
|
5
5
|
import type { LineSegmentStyle } from '../../types/plots/segments/common';
|
|
6
|
-
import type {
|
|
6
|
+
import type { LineMarkersConfig } from '../../types/markers/line';
|
|
7
7
|
declare function $$render<TData extends Record<string, unknown>>(): {
|
|
8
|
-
props: BasePlotProps<SeriesProps<TData> | DataProps<TData>, TData,
|
|
8
|
+
props: BasePlotProps<SeriesProps<TData> | DataProps<TData>, TData, BasePlotStylesConfig, LineSegmentStyle, LineMarkersConfig, AxisBasedScalesConfig<TData>>;
|
|
9
9
|
exports: {};
|
|
10
10
|
bindings: "";
|
|
11
11
|
slots: {};
|