@fundar/data-chart-telling 0.0.14 → 0.0.16
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/README.md +121 -17
- package/dist/charts/{Chart.svelte → BaseChart.svelte} +2 -0
- package/dist/charts/{Chart.svelte.d.ts → BaseChart.svelte.d.ts} +3 -3
- package/dist/charts/bar/Chart.svelte +5 -5
- package/dist/charts/bar/Chart.svelte.d.ts +1 -2
- package/dist/charts/heatmap/Chart.svelte +8 -7
- package/dist/charts/heatmap/Chart.svelte.d.ts +2 -3
- package/dist/charts/line/Chart.svelte +5 -5
- package/dist/charts/line/Chart.svelte.d.ts +1 -2
- package/dist/charts/pyramid/Chart.svelte +7 -6
- package/dist/charts/pyramid/Chart.svelte.d.ts +2 -3
- package/dist/configuration/config.svelte.js +2 -1
- package/dist/configuration/themes/index.d.ts +60 -40
- package/dist/index.d.ts +27 -13
- package/dist/index.js +12 -7
- package/dist/layout/facet/FacetLayout.svelte +1 -1
- package/dist/layout/facet/FacetLayout.svelte.d.ts +1 -1
- package/dist/layout/geo/GeoLayout.svelte +47 -0
- package/dist/layout/geo/GeoLayout.svelte.d.ts +22 -0
- package/dist/layout/geo/resolveProjection.d.ts +10 -0
- package/dist/layout/geo/resolveProjection.js +48 -0
- package/dist/layout/legend/ContinuousSection.svelte +158 -17
- package/dist/layout/legend/DiscreteSection.svelte +56 -4
- package/dist/layout/legend/interaction.svelte.d.ts +7 -0
- package/dist/layout/legend/interaction.svelte.js +24 -0
- package/dist/layout/plot/AxisLayout.svelte +95 -0
- package/dist/layout/plot/AxisLayout.svelte.d.ts +39 -0
- package/dist/layout/plot/BasePlotLayout.svelte +302 -0
- package/dist/layout/plot/BasePlotLayout.svelte.d.ts +95 -0
- package/dist/layout/plot/GridLayout.svelte +30 -0
- package/dist/layout/plot/GridLayout.svelte.d.ts +27 -0
- package/dist/layout/plot/RuleLayout.svelte +111 -0
- package/dist/layout/plot/RuleLayout.svelte.d.ts +40 -0
- package/dist/layout/plot/margins.d.ts +34 -0
- package/dist/layout/plot/margins.js +26 -0
- package/dist/layout/timeline/TimelineLayout.svelte +1 -1
- package/dist/layout/timeline/TimelineLayout.svelte.d.ts +1 -1
- package/dist/layout/tooltip/Tooltip.svelte +15 -0
- package/dist/layout/tooltip/Tooltip.svelte.d.ts +7 -0
- package/dist/layout/tooltip/TooltipLayout.svelte +45 -0
- package/dist/layout/tooltip/TooltipLayout.svelte.d.ts +41 -0
- package/dist/layout/tooltip/controller.svelte.d.ts +4 -3
- package/dist/layout/tooltip/controller.svelte.js +5 -6
- package/dist/layout/tooltip/hover.svelte.d.ts +1 -1
- package/dist/layout/tooltip/hover.svelte.js +1 -1
- package/dist/layout/tooltip/utils.d.ts +2 -2
- package/dist/markers/ContourClipMarker.svelte +77 -0
- package/dist/markers/ContourClipMarker.svelte.d.ts +10 -0
- package/dist/{plots/markers → markers}/DeltaMarker.svelte +4 -4
- package/dist/{plots/markers → markers}/DeltaMarker.svelte.d.ts +3 -3
- package/dist/{plots/markers → markers}/DotMarker.svelte +3 -3
- package/dist/{plots/markers → markers}/DotMarker.svelte.d.ts +3 -3
- package/dist/markers/HoverMarker.svelte +136 -0
- package/dist/{plots/markers → markers}/HoverMarker.svelte.d.ts +4 -4
- package/dist/{plots/markers → markers}/PeakMarker.svelte +2 -2
- package/dist/{plots/markers → markers}/PeakMarker.svelte.d.ts +2 -2
- package/dist/{plots/markers → markers}/TextMarker.svelte +11 -4
- package/dist/{plots/markers → markers}/TextMarker.svelte.d.ts +3 -3
- package/dist/markers/inset/InsetMarker.svelte +170 -0
- package/dist/markers/inset/InsetMarker.svelte.d.ts +51 -0
- package/dist/markers/inset/insetLayout.d.ts +25 -0
- package/dist/markers/inset/insetLayout.js +39 -0
- package/dist/markers/inset/insetProjection.d.ts +8 -0
- package/dist/markers/inset/insetProjection.js +39 -0
- package/dist/plots/bar/BarSegments.svelte +69 -0
- package/dist/plots/bar/BarSegments.svelte.d.ts +40 -0
- package/dist/plots/bar/Plot.svelte +140 -74
- package/dist/plots/bar/Plot.svelte.d.ts +7 -3
- package/dist/plots/bar/ValueLabels.svelte +89 -0
- package/dist/plots/bar/ValueLabels.svelte.d.ts +39 -0
- package/dist/plots/bar/hoverPoints.d.ts +15 -0
- package/dist/plots/bar/hoverPoints.js +35 -0
- package/dist/plots/bar/layout.svelte.d.ts +37 -0
- package/dist/plots/bar/layout.svelte.js +132 -0
- package/dist/plots/geo/Plot.svelte +577 -0
- package/dist/plots/geo/Plot.svelte.d.ts +29 -0
- package/dist/plots/geo/TileLayer.svelte +77 -0
- package/dist/plots/geo/TileLayer.svelte.d.ts +11 -0
- package/dist/plots/geo/projections/argentina.d.ts +8 -0
- package/dist/plots/geo/projections/argentina.js +35 -0
- package/dist/plots/geo/projections/fit.d.ts +8 -0
- package/dist/plots/geo/projections/fit.js +14 -0
- package/dist/plots/geo/rotate.svelte.d.ts +26 -0
- package/dist/plots/geo/rotate.svelte.js +79 -0
- package/dist/plots/geo/zoom.svelte.d.ts +32 -0
- package/dist/plots/geo/zoom.svelte.js +50 -0
- package/dist/plots/heatmap/Plot.svelte +171 -58
- package/dist/plots/heatmap/Plot.svelte.d.ts +7 -3
- package/dist/plots/line/Plot.svelte +67 -30
- package/dist/plots/line/Plot.svelte.d.ts +7 -3
- package/dist/plots/pyramid/Plot.svelte +88 -35
- package/dist/plots/pyramid/Plot.svelte.d.ts +7 -3
- package/dist/plots/utils/delta.d.ts +1 -1
- package/dist/plots/utils/geoAccessors.d.ts +64 -0
- package/dist/plots/utils/geoAccessors.js +188 -0
- package/dist/plots/utils/geoSegments.d.ts +14 -0
- package/dist/plots/utils/geoSegments.js +17 -0
- package/dist/plots/utils/legendDisabled.d.ts +15 -0
- package/dist/plots/utils/legendDisabled.js +41 -0
- package/dist/plots/utils/segments.d.ts +14 -5
- package/dist/plots/utils/segments.js +25 -13
- package/dist/plots/utils/tiles.d.ts +89 -0
- package/dist/plots/utils/tiles.js +159 -0
- package/dist/plots/utils/topojson.d.ts +9 -0
- package/dist/plots/utils/topojson.js +30 -0
- package/dist/types/charts/common.d.ts +2 -1
- package/dist/types/charts/legend.d.ts +32 -1
- package/dist/types/charts/props.d.ts +9 -6
- package/dist/types/configuration/styling.d.ts +13 -5
- package/dist/types/layout/legend.d.ts +26 -0
- package/dist/types/layout/tooltip.d.ts +14 -21
- package/dist/types/{plots/markers.d.ts → markers/common.d.ts} +2 -18
- package/dist/types/markers/geo.d.ts +237 -0
- package/dist/types/markers/props.d.ts +11 -0
- package/dist/types/markers/props.js +1 -0
- package/dist/types/plots/axis.d.ts +55 -0
- package/dist/types/plots/axis.js +1 -0
- package/dist/types/plots/constants.d.ts +30 -0
- package/dist/types/plots/constants.js +1 -0
- package/dist/types/plots/data/common.d.ts +40 -0
- package/dist/types/plots/data/common.js +1 -0
- package/dist/types/plots/data/geo.d.ts +74 -0
- package/dist/types/plots/data/geo.js +1 -0
- package/dist/types/plots/delta.d.ts +2 -2
- package/dist/types/plots/props.d.ts +105 -16
- package/dist/types/plots/scales/geo.d.ts +44 -0
- package/dist/types/plots/scales/geo.js +1 -0
- package/dist/types/plots/segments/common.d.ts +25 -0
- package/dist/types/plots/segments/common.js +1 -0
- package/dist/types/plots/segments/config.d.ts +51 -0
- package/dist/types/plots/segments/config.js +1 -0
- package/dist/types/plots/styles/common.d.ts +37 -0
- package/dist/types/plots/styles/common.js +1 -0
- package/dist/types/plots/styles/geo.d.ts +42 -0
- package/dist/types/plots/styles/geo.js +1 -0
- package/dist/types/plots/styling.d.ts +45 -0
- package/dist/types/plots/styling.js +1 -0
- package/dist/utils/grouping.d.ts +2 -1
- package/dist/utils/interpolate.d.ts +2 -1
- package/package.json +27 -13
- package/dist/layout/plot/PlotLayout.svelte +0 -294
- package/dist/layout/plot/PlotLayout.svelte.d.ts +0 -70
- package/dist/plots/markers/HoverMarker.svelte +0 -98
- package/dist/types/plots/common.d.ts +0 -97
- package/dist/types/plots/styles.d.ts +0 -187
- /package/dist/types/{plots/common.js → layout/legend.js} +0 -0
- /package/dist/types/{plots/markers.js → markers/common.js} +0 -0
- /package/dist/types/{plots/styles.js → markers/geo.js} +0 -0
|
@@ -8,13 +8,32 @@
|
|
|
8
8
|
import { getConfiguration } from '../../configuration/config.svelte';
|
|
9
9
|
import { paletteColor } from '../../utils/color';
|
|
10
10
|
import { buildSeries } from '../../utils/grouping';
|
|
11
|
-
import
|
|
12
|
-
import
|
|
11
|
+
import { getLegendInteraction } from '../../layout/legend/interaction.svelte';
|
|
12
|
+
import { disabledStrokeOverride, disabledDotsOverride } from '../utils/legendDisabled';
|
|
13
|
+
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
|
+
import { hasHoverMarker, resolveHoverStrategy, resolveHoverSync } from '../../layout/tooltip/utils';
|
|
13
19
|
import { buildGroupedSeries, validateSegments, resolveSegmentsForSeries, matchesSegmentX, getDataForSegments } from '../utils/segments';
|
|
14
|
-
import type {
|
|
15
|
-
import type {
|
|
16
|
-
import type {
|
|
17
|
-
import type {
|
|
20
|
+
import type { BasePlotProps } from '../../types/plots/props';
|
|
21
|
+
import type { AxisValue } from '../../types/plots/axis';
|
|
22
|
+
import type { Series, SeriesProps, DataProps } from '../../types/plots/data/common';
|
|
23
|
+
import type { AxisBasedScalesConfig } from '../../types/plots/props';
|
|
24
|
+
import type { BasePlotStyles } from '../../types/plots/styles/common';
|
|
25
|
+
import type { ValueAnchor } from '../../types/plots/constants';
|
|
26
|
+
import type { LineSegmentStyle } from '../../types/plots/segments/common';
|
|
27
|
+
import type { Marker } from '../../types/markers/common';
|
|
28
|
+
|
|
29
|
+
type Props = BasePlotProps<
|
|
30
|
+
SeriesProps<TData> | DataProps<TData>,
|
|
31
|
+
TData,
|
|
32
|
+
BasePlotStyles,
|
|
33
|
+
LineSegmentStyle,
|
|
34
|
+
Marker,
|
|
35
|
+
AxisBasedScalesConfig<TData>
|
|
36
|
+
>;
|
|
18
37
|
|
|
19
38
|
let {
|
|
20
39
|
width,
|
|
@@ -30,9 +49,10 @@
|
|
|
30
49
|
scales = {},
|
|
31
50
|
margins,
|
|
32
51
|
tooltip = undefined,
|
|
33
|
-
}:
|
|
52
|
+
}: Props = $props();
|
|
34
53
|
|
|
35
54
|
const resolvedSeries = $derived(series ?? buildSeries(data!, x!, y!, z));
|
|
55
|
+
const legendInteraction = $derived(getLegendInteraction());
|
|
36
56
|
|
|
37
57
|
$effect(() => { validateSegments(segments); });
|
|
38
58
|
|
|
@@ -57,12 +77,19 @@
|
|
|
57
77
|
styles.values?.format ?? ((v: number, name: string) => `${name} - ${v}`),
|
|
58
78
|
);
|
|
59
79
|
const valAnchor = $derived<ValueAnchor>(styles.values?.anchor ?? 'start');
|
|
80
|
+
// 'outside' is a per-point escape hatch resolved by HoverMarker; line's own
|
|
81
|
+
// value labels already have their own `anchor: 'outside'` concept above,
|
|
82
|
+
// so treat it as unset here.
|
|
83
|
+
const resolvedTextAnchor = $derived(styles.values?.textAnchor === 'outside' ? undefined : styles.values?.textAnchor);
|
|
60
84
|
|
|
61
85
|
const xAcc = $derived(resolveAccessor(resolvedSeries[0]?.x ?? ((d: TData) => d)));
|
|
62
86
|
const yAcc = $derived(resolveAccessor(resolvedSeries[0]?.y ?? ((d: TData) => d)));
|
|
63
87
|
const flat = $derived(resolvedSeries.flatMap((s) => s.data));
|
|
88
|
+
// A legend-disabled series is dimmed on the mark itself, but never surfaces
|
|
89
|
+
// in hover/tooltip — its points are simply absent from the candidate list.
|
|
64
90
|
const hoverPoints = $derived(
|
|
65
91
|
resolvedSeries.flatMap((s, idx) => {
|
|
92
|
+
if (legendInteraction?.disabledSeries.has(s.name)) return [];
|
|
66
93
|
const sx = resolveAccessor(s.x);
|
|
67
94
|
const sy = resolveAccessor(s.y);
|
|
68
95
|
return s.data.map((d) => ({
|
|
@@ -82,28 +109,37 @@
|
|
|
82
109
|
.map((s, idx) => ({ series: s, lastRow: s.data[s.data.length - 1], seriesIndex: idx }))
|
|
83
110
|
.filter(({ lastRow }) => lastRow !== undefined),
|
|
84
111
|
);
|
|
112
|
+
|
|
113
|
+
const hoverActive = $derived(tooltip != null || hasHoverMarker(markers));
|
|
114
|
+
const hoverStrategy = $derived(resolveHoverStrategy(tooltip?.strategy, markers, 'x'));
|
|
115
|
+
const hoverSync = $derived(resolveHoverSync(tooltip?.sync, markers));
|
|
85
116
|
</script>
|
|
86
117
|
|
|
87
|
-
<
|
|
118
|
+
<BasePlotLayout
|
|
88
119
|
{width}
|
|
89
120
|
{height}
|
|
90
|
-
x={scales.x}
|
|
91
|
-
y={scales.y}
|
|
92
121
|
data={flat}
|
|
93
122
|
getX={xAcc}
|
|
94
123
|
getY={(d) => Number(yAcc(d))}
|
|
95
124
|
{hoverPoints}
|
|
96
125
|
label={(r) => String(yAcc(r))}
|
|
97
126
|
{tooltip}
|
|
98
|
-
{
|
|
99
|
-
|
|
127
|
+
{hoverActive}
|
|
128
|
+
{hoverStrategy}
|
|
129
|
+
{hoverSync}
|
|
100
130
|
{scales}
|
|
101
131
|
{margins}
|
|
102
|
-
|
|
132
|
+
xTickRotate={scales?.x?.tickRotate}
|
|
103
133
|
>
|
|
104
|
-
{#snippet children({ matchedPoints, ruleX, ruleY, impliesRuleX, impliesRuleY })}
|
|
134
|
+
{#snippet children({ matchedPoints, ruleX, ruleY, impliesRuleX, impliesRuleY, numericMargins })}
|
|
135
|
+
<AxisLayout data={flat} getX={xAcc} getY={(d) => Number(yAcc(d))} {width} {height} {numericMargins} {scales} />
|
|
136
|
+
<GridLayout {scales} />
|
|
137
|
+
<RuleLayout {markers} seriesData={resolvedSeries} {matchedPoints} {ruleX} {ruleY} {impliesRuleX} {impliesRuleY}>
|
|
105
138
|
{#each groupedSeries as group, seriesIndex (group.series.name)}
|
|
106
139
|
{@const defaultColor = paletteColor(seriesIndex, cfg.palette)}
|
|
140
|
+
{@const disabledOverride = legendInteraction?.disabledSeries.get(group.series.name)}
|
|
141
|
+
{@const disabledStroke = disabledStrokeOverride(disabledOverride)}
|
|
142
|
+
{@const disabledDots = disabledDotsOverride(disabledOverride)}
|
|
107
143
|
{#each group.visualSegments as seg, i (`${group.series.name}-${i}`)}
|
|
108
144
|
{@const strokeStyle = seg.style.stroke}
|
|
109
145
|
{@const lineData = seg.data as unknown as Record<string | symbol, never>[]}
|
|
@@ -111,12 +147,12 @@
|
|
|
111
147
|
data={lineData}
|
|
112
148
|
x={resolveAccessor(group.series.x)}
|
|
113
149
|
y={resolveAccessor(group.series.y)}
|
|
114
|
-
stroke={strokeStyle?.stroke ?? defaultColor}
|
|
115
|
-
strokeWidth={strokeStyle?.strokeWidth ?? cfg.line.strokeWidth}
|
|
116
|
-
strokeOpacity={strokeStyle?.strokeOpacity ?? 1}
|
|
117
|
-
strokeDasharray={strokeStyle?.strokeDasharray}
|
|
118
|
-
strokeLinejoin={strokeStyle?.strokeLinejoin}
|
|
119
|
-
strokeLinecap={strokeStyle?.strokeLinecap}
|
|
150
|
+
stroke={disabledStroke?.stroke ?? strokeStyle?.stroke ?? defaultColor}
|
|
151
|
+
strokeWidth={disabledStroke?.strokeWidth ?? strokeStyle?.strokeWidth ?? cfg.line.strokeWidth}
|
|
152
|
+
strokeOpacity={disabledStroke?.strokeOpacity ?? strokeStyle?.strokeOpacity ?? 1}
|
|
153
|
+
strokeDasharray={disabledStroke?.strokeDasharray ?? strokeStyle?.strokeDasharray}
|
|
154
|
+
strokeLinejoin={disabledStroke?.strokeLinejoin ?? strokeStyle?.strokeLinejoin}
|
|
155
|
+
strokeLinecap={disabledStroke?.strokeLinecap ?? strokeStyle?.strokeLinecap}
|
|
120
156
|
/>
|
|
121
157
|
{#if seg.style.dots}
|
|
122
158
|
{@const dotStyle = seg.style.dots}
|
|
@@ -124,14 +160,14 @@
|
|
|
124
160
|
data={seg.data}
|
|
125
161
|
x={resolveAccessor(group.series.x)}
|
|
126
162
|
y={resolveAccessor(group.series.y)}
|
|
127
|
-
r={dotStyle.dotRadius ?? cfg.line.dotRadius}
|
|
128
|
-
fill={dotStyle.dotFill ?? strokeStyle?.stroke ?? defaultColor}
|
|
129
|
-
symbol={dotStyle.dotSymbol ?? 'circle'}
|
|
130
|
-
stroke={dotStyle.dotStroke ?? strokeStyle?.stroke ?? defaultColor}
|
|
131
|
-
strokeWidth={dotStyle.dotStrokeWidth ?? 1}
|
|
132
|
-
fillOpacity={dotStyle.dotFillOpacity ?? strokeStyle?.strokeOpacity ?? 1}
|
|
133
|
-
strokeOpacity={dotStyle.dotStrokeOpacity ?? strokeStyle?.strokeOpacity ?? 1}
|
|
134
|
-
strokeDasharray={dotStyle.dotStrokeDasharray}
|
|
163
|
+
r={disabledDots?.dotRadius ?? dotStyle.dotRadius ?? cfg.line.dotRadius}
|
|
164
|
+
fill={disabledDots?.dotFill ?? dotStyle.dotFill ?? strokeStyle?.stroke ?? defaultColor}
|
|
165
|
+
symbol={disabledDots?.dotSymbol ?? dotStyle.dotSymbol ?? 'circle'}
|
|
166
|
+
stroke={disabledDots?.dotStroke ?? dotStyle.dotStroke ?? strokeStyle?.stroke ?? defaultColor}
|
|
167
|
+
strokeWidth={disabledDots?.dotStrokeWidth ?? dotStyle.dotStrokeWidth ?? 1}
|
|
168
|
+
fillOpacity={disabledDots?.dotFillOpacity ?? dotStyle.dotFillOpacity ?? strokeStyle?.strokeOpacity ?? 1}
|
|
169
|
+
strokeOpacity={disabledDots?.dotStrokeOpacity ?? dotStyle.dotStrokeOpacity ?? strokeStyle?.strokeOpacity ?? 1}
|
|
170
|
+
strokeDasharray={disabledDots?.dotStrokeDasharray ?? dotStyle.dotStrokeDasharray}
|
|
135
171
|
/>
|
|
136
172
|
{/if}
|
|
137
173
|
{/each}
|
|
@@ -221,7 +257,7 @@
|
|
|
221
257
|
text={() => fmtVal(Number(yFn(lastRow)), s.name)}
|
|
222
258
|
dx={styles.values?.dx ?? defaultDx}
|
|
223
259
|
dy={styles.values?.dy ?? defaultDy}
|
|
224
|
-
textAnchor={
|
|
260
|
+
textAnchor={resolvedTextAnchor ?? defaultTA}
|
|
225
261
|
lineAnchor={styles.values?.lineAnchor ?? defaultLA}
|
|
226
262
|
lineHeight={styles.values?.lineHeight}
|
|
227
263
|
rotate={styles.values?.rotate}
|
|
@@ -232,5 +268,6 @@
|
|
|
232
268
|
/>
|
|
233
269
|
{/each}
|
|
234
270
|
{/if}
|
|
271
|
+
</RuleLayout>
|
|
235
272
|
{/snippet}
|
|
236
|
-
</
|
|
273
|
+
</BasePlotLayout>
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
1
|
+
import type { BasePlotProps } from '../../types/plots/props';
|
|
2
|
+
import type { SeriesProps, DataProps } from '../../types/plots/data/common';
|
|
3
|
+
import type { AxisBasedScalesConfig } from '../../types/plots/props';
|
|
4
|
+
import type { BasePlotStyles } from '../../types/plots/styles/common';
|
|
5
|
+
import type { LineSegmentStyle } from '../../types/plots/segments/common';
|
|
6
|
+
import type { Marker } from '../../types/markers/common';
|
|
3
7
|
declare function $$render<TData extends Record<string, unknown>>(): {
|
|
4
|
-
props:
|
|
8
|
+
props: BasePlotProps<SeriesProps<TData> | DataProps<TData>, TData, BasePlotStyles, LineSegmentStyle, Marker, AxisBasedScalesConfig<TData>>;
|
|
5
9
|
exports: {};
|
|
6
10
|
bindings: "";
|
|
7
11
|
slots: {};
|
|
@@ -5,13 +5,23 @@
|
|
|
5
5
|
import { getConfiguration } from '../../configuration/config.svelte';
|
|
6
6
|
import { paletteColor } from '../../utils/color';
|
|
7
7
|
import { buildSeries } from '../../utils/grouping';
|
|
8
|
+
import { getLegendInteraction } from '../../layout/legend/interaction.svelte';
|
|
9
|
+
import { disabledFillOverride } from '../utils/legendDisabled';
|
|
8
10
|
import { buildGroupedSeries, validateSegments, resolveSegmentsForSeries, matchesSegmentX, getDataForSegments } from '../utils/segments';
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
import
|
|
11
|
+
import BasePlotLayout from '../../layout/plot/BasePlotLayout.svelte';
|
|
12
|
+
import AxisLayout from '../../layout/plot/AxisLayout.svelte';
|
|
13
|
+
import GridLayout from '../../layout/plot/GridLayout.svelte';
|
|
14
|
+
import RuleLayout from '../../layout/plot/RuleLayout.svelte';
|
|
15
|
+
import HoverMarker from '../../markers/HoverMarker.svelte';
|
|
16
|
+
import { hasHoverMarker, resolveHoverStrategy, resolveHoverSync } from '../../layout/tooltip/utils';
|
|
17
|
+
import type { BasePlotProps } from '../../types/plots/props';
|
|
18
|
+
import type { AxisValue } from '../../types/plots/axis';
|
|
19
|
+
import type { Series, SeriesProps, DataProps } from '../../types/plots/data/common';
|
|
20
|
+
import type { AxisBasedScalesConfig } from '../../types/plots/props';
|
|
21
|
+
import type { BasePlotStyles } from '../../types/plots/styles/common';
|
|
22
|
+
import type { ValueAnchor } from '../../types/plots/constants';
|
|
23
|
+
import type { BarSegmentStyle } from '../../types/plots/segments/common';
|
|
24
|
+
import type { Marker } from '../../types/markers/common';
|
|
15
25
|
|
|
16
26
|
/**
|
|
17
27
|
* A population-pyramid-style diverging bar chart: each series is mirrored
|
|
@@ -29,6 +39,15 @@
|
|
|
29
39
|
type PyramidSide = 'left' | 'right';
|
|
30
40
|
type InternalSeries = Series<TData> & { side: PyramidSide };
|
|
31
41
|
|
|
42
|
+
type Props = BasePlotProps<
|
|
43
|
+
SeriesProps<TData> | DataProps<TData>,
|
|
44
|
+
TData,
|
|
45
|
+
BasePlotStyles,
|
|
46
|
+
BarSegmentStyle,
|
|
47
|
+
Marker,
|
|
48
|
+
AxisBasedScalesConfig<TData>
|
|
49
|
+
>;
|
|
50
|
+
|
|
32
51
|
let {
|
|
33
52
|
width,
|
|
34
53
|
height,
|
|
@@ -43,16 +62,21 @@
|
|
|
43
62
|
segments = {},
|
|
44
63
|
markers = [],
|
|
45
64
|
tooltip = undefined,
|
|
46
|
-
}:
|
|
65
|
+
}: Props = $props();
|
|
47
66
|
|
|
48
67
|
$effect(() => { validateSegments(segments); });
|
|
49
68
|
|
|
50
69
|
const cfg = $derived(getConfiguration());
|
|
70
|
+
const legendInteraction = $derived(getLegendInteraction());
|
|
51
71
|
const leftColor = $derived(styles.colors?.left ?? paletteColor(0, cfg.palette));
|
|
52
72
|
const rightColor = $derived(styles.colors?.right ?? paletteColor(1, cfg.palette));
|
|
53
73
|
const showVals = $derived(styles.values?.show ?? false);
|
|
54
74
|
const fmtVal = $derived(styles.values?.format ?? ((v: number) => `${v}`));
|
|
55
75
|
const valAnchor = $derived<ValueAnchor>(styles.values?.anchor ?? 'outside');
|
|
76
|
+
// 'outside' is a per-point escape hatch resolved by HoverMarker; pyramid's
|
|
77
|
+
// own value labels already have their own `anchor: 'outside'` concept
|
|
78
|
+
// above, so treat it as unset here.
|
|
79
|
+
const resolvedTextAnchor = $derived(styles.values?.textAnchor === 'outside' ? undefined : styles.values?.textAnchor);
|
|
56
80
|
|
|
57
81
|
// Sort series names alphabetically; even index → left, odd → right.
|
|
58
82
|
// scales.z.reverse flips the assignment so the second name goes left.
|
|
@@ -68,7 +92,9 @@
|
|
|
68
92
|
});
|
|
69
93
|
|
|
70
94
|
const groupedSeries = $derived(
|
|
71
|
-
|
|
95
|
+
// connect: false — bars are discrete; there's no visual gap between
|
|
96
|
+
// adjacent categories to bridge (see buildGroupedSeries's own doc).
|
|
97
|
+
buildGroupedSeries<InternalSeries, BarSegmentStyle>(resolvedSeries, segments, false),
|
|
72
98
|
);
|
|
73
99
|
|
|
74
100
|
function signedValue(s: InternalSeries, d: TData): number {
|
|
@@ -111,15 +137,19 @@
|
|
|
111
137
|
const getY = (d: TaggedRow) => d.__y;
|
|
112
138
|
const labelFor = (d: TaggedRow) => d.__label;
|
|
113
139
|
|
|
140
|
+
// A legend-disabled series is dimmed on the bar itself, but never surfaces
|
|
141
|
+
// in hover/tooltip — its points are simply absent from the candidate list.
|
|
114
142
|
const hoverPoints = $derived(
|
|
115
|
-
flat
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
143
|
+
flat
|
|
144
|
+
.filter((d) => !legendInteraction?.disabledSeries.has(d.__series))
|
|
145
|
+
.map((d) => ({
|
|
146
|
+
x: d.__x,
|
|
147
|
+
y: d.__y,
|
|
148
|
+
row: d,
|
|
149
|
+
label: d.__label,
|
|
150
|
+
series: d.__series,
|
|
151
|
+
color: d.__side === 'left' ? leftColor : rightColor,
|
|
152
|
+
})),
|
|
123
153
|
);
|
|
124
154
|
|
|
125
155
|
const yDomain = $derived([
|
|
@@ -149,42 +179,59 @@
|
|
|
149
179
|
}
|
|
150
180
|
return map;
|
|
151
181
|
});
|
|
182
|
+
|
|
183
|
+
// The single, fully-resolved scales object BasePlotLayout reads for
|
|
184
|
+
// everything (ticks, grid, sort, and the real svelteplot scale) — avoids
|
|
185
|
+
// keeping a second, separately-defaulted copy of `scales.x`/`scales.y`
|
|
186
|
+
// (our own diverging-domain + band-scale defaults) out of sync with the
|
|
187
|
+
// one actually forwarded.
|
|
188
|
+
const resolvedScales = $derived<AxisBasedScalesConfig<TData>>({
|
|
189
|
+
...scales,
|
|
190
|
+
x: {
|
|
191
|
+
domain: [-maxMagnitude, maxMagnitude],
|
|
192
|
+
tickFormat: (v: unknown) => fmtVal(Math.abs(Number(v)), ''),
|
|
193
|
+
...(scales.x ?? {}),
|
|
194
|
+
},
|
|
195
|
+
y: { type: 'band', padding: 0.2, domain: yDomain, ...(scales.y ?? {}) },
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
const hoverActive = $derived(tooltip != null || hasHoverMarker(markers));
|
|
199
|
+
const hoverStrategy = $derived(resolveHoverStrategy(tooltip?.strategy, markers, 'y'));
|
|
200
|
+
const hoverSync = $derived(resolveHoverSync(tooltip?.sync, markers));
|
|
152
201
|
</script>
|
|
153
202
|
|
|
154
|
-
<
|
|
203
|
+
<BasePlotLayout
|
|
155
204
|
{width}
|
|
156
205
|
{height}
|
|
157
|
-
x={{
|
|
158
|
-
domain: [-maxMagnitude, maxMagnitude],
|
|
159
|
-
tickFormat: (v: unknown) => fmtVal(Math.abs(Number(v)), ''),
|
|
160
|
-
...(scales.x ?? {}),
|
|
161
|
-
}}
|
|
162
|
-
y={{ type: 'band', padding: 0.2, domain: yDomain, ...(scales.y ?? {}) }}
|
|
163
206
|
data={flat}
|
|
164
207
|
{getX}
|
|
165
208
|
{getY}
|
|
166
|
-
matchY={getY}
|
|
167
209
|
{hoverPoints}
|
|
168
210
|
label={labelFor}
|
|
169
211
|
{tooltip}
|
|
170
|
-
{
|
|
171
|
-
|
|
172
|
-
{
|
|
212
|
+
{hoverActive}
|
|
213
|
+
{hoverStrategy}
|
|
214
|
+
{hoverSync}
|
|
215
|
+
scales={resolvedScales}
|
|
173
216
|
{margins}
|
|
174
|
-
|
|
217
|
+
xTickRotate={resolvedScales?.x?.tickRotate}
|
|
175
218
|
>
|
|
176
|
-
{#snippet children({ matchedPoints, ruleX, ruleY, impliesRuleX, impliesRuleY })}
|
|
219
|
+
{#snippet children({ matchedPoints, ruleX, ruleY, impliesRuleX, impliesRuleY, numericMargins })}
|
|
220
|
+
<AxisLayout data={flat} {getX} {getY} {width} {height} {numericMargins} scales={resolvedScales} />
|
|
221
|
+
<GridLayout scales={resolvedScales} />
|
|
222
|
+
<RuleLayout {markers} seriesData={resolvedSeries} {matchedPoints} {ruleX} {ruleY} {impliesRuleX} {impliesRuleY}>
|
|
177
223
|
{#each groupedSeries as group (group.series.name)}
|
|
178
224
|
{@const defaultColor = group.series.side === 'left' ? leftColor : rightColor}
|
|
179
225
|
{@const getCategory = resolveAccessor(group.series.x)}
|
|
226
|
+
{@const disabledFill = disabledFillOverride(legendInteraction?.disabledSeries.get(group.series.name))}
|
|
180
227
|
{#each group.visualSegments as seg, i (`${group.series.name}-${i}`)}
|
|
181
228
|
<BarX
|
|
182
229
|
data={seg.data}
|
|
183
230
|
x1={0}
|
|
184
231
|
x2={(d: TData) => signedValue(group.series, d)}
|
|
185
232
|
y={getCategory}
|
|
186
|
-
fill={seg.style.fill ?? defaultColor}
|
|
187
|
-
fillOpacity={seg.style.fillOpacity ?? 1}
|
|
233
|
+
fill={disabledFill?.fill ?? seg.style.fill ?? defaultColor}
|
|
234
|
+
fillOpacity={disabledFill?.fillOpacity ?? seg.style.fillOpacity ?? 1}
|
|
188
235
|
/>
|
|
189
236
|
{/each}
|
|
190
237
|
|
|
@@ -210,14 +257,19 @@
|
|
|
210
257
|
text={(d: TData) => fmtVal(Math.abs(Number(resolveAccessor(group.series.y)(d))), group.series.name)}
|
|
211
258
|
dx={styles.values?.dx ?? defaultDx}
|
|
212
259
|
dy={styles.values?.dy ?? 0}
|
|
213
|
-
textAnchor={
|
|
260
|
+
textAnchor={resolvedTextAnchor ?? defaultTextAnchor}
|
|
214
261
|
lineAnchor={styles.values?.lineAnchor ?? 'middle'}
|
|
215
262
|
lineHeight={styles.values?.lineHeight}
|
|
216
263
|
rotate={styles.values?.rotate}
|
|
217
264
|
class={styles.values?.class}
|
|
218
265
|
textClass={styles.values?.textClass}
|
|
219
|
-
fill={cfg.axis.color}
|
|
220
|
-
fontSize={12}
|
|
266
|
+
fill={styles.values?.fill ?? cfg.axis.color}
|
|
267
|
+
fontSize={styles.values?.fontSize ?? 12}
|
|
268
|
+
fontWeight={styles.values?.fontWeight}
|
|
269
|
+
fontStyle={styles.values?.fontStyle}
|
|
270
|
+
stroke={styles.values?.stroke}
|
|
271
|
+
strokeWidth={styles.values?.strokeWidth}
|
|
272
|
+
paintOrder={styles.values?.paintOrder}
|
|
221
273
|
/>
|
|
222
274
|
{/if}
|
|
223
275
|
|
|
@@ -282,5 +334,6 @@
|
|
|
282
334
|
{/if}
|
|
283
335
|
{/each}
|
|
284
336
|
{/each}
|
|
337
|
+
</RuleLayout>
|
|
285
338
|
{/snippet}
|
|
286
|
-
</
|
|
339
|
+
</BasePlotLayout>
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
1
|
+
import type { BasePlotProps } from '../../types/plots/props';
|
|
2
|
+
import type { SeriesProps, DataProps } from '../../types/plots/data/common';
|
|
3
|
+
import type { AxisBasedScalesConfig } from '../../types/plots/props';
|
|
4
|
+
import type { BasePlotStyles } from '../../types/plots/styles/common';
|
|
5
|
+
import type { BarSegmentStyle } from '../../types/plots/segments/common';
|
|
6
|
+
import type { Marker } from '../../types/markers/common';
|
|
3
7
|
declare function $$render<TData extends Record<string, unknown>>(): {
|
|
4
|
-
props:
|
|
8
|
+
props: BasePlotProps<SeriesProps<TData> | DataProps<TData>, TData, BasePlotStyles, BarSegmentStyle, Marker, AxisBasedScalesConfig<TData>>;
|
|
5
9
|
exports: {};
|
|
6
10
|
bindings: "";
|
|
7
11
|
slots: {};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { GeoFeature } from '../../types/plots/data/geo';
|
|
2
|
+
/**
|
|
3
|
+
* Bounding-box center of a geometry's flattened coordinates — a cheap
|
|
4
|
+
* approximation used for default label placement, not a true
|
|
5
|
+
* geographic/area centroid (no polygon-hole or geodesic-area weighting).
|
|
6
|
+
* For hover-matching specifically, see `geometryPartCentroids` instead —
|
|
7
|
+
* this single combined point can land far from every actual part of a
|
|
8
|
+
* multi-part geometry whose pieces are geographically spread out.
|
|
9
|
+
*/
|
|
10
|
+
export declare function geometryCentroid(geometry: GeoJSON.Geometry): [number, number];
|
|
11
|
+
/**
|
|
12
|
+
* Splits a geometry into its disjoint parts: one `Polygon` per element of a
|
|
13
|
+
* `MultiPolygon`'s `coordinates`, one `LineString` per element of a
|
|
14
|
+
* `MultiLineString`'s, `GeometryCollection` recursed and flattened, and any
|
|
15
|
+
* other geometry type returned unchanged as its own single-element array.
|
|
16
|
+
* The shared building block behind `geometryPartCentroids` (one centroid per
|
|
17
|
+
* part) and `filterGeometryParts` (keep/drop whole parts).
|
|
18
|
+
*/
|
|
19
|
+
export declare function splitGeometryParts(geometry: GeoJSON.Geometry): GeoJSON.Geometry[];
|
|
20
|
+
/**
|
|
21
|
+
* Like `geometryCentroid`, but returns one point per disjoint part instead
|
|
22
|
+
* of a single bounding-box center across all of them. A `MultiPolygon`
|
|
23
|
+
* whose parts are geographically far apart — e.g. Argentina's "Tierra del
|
|
24
|
+
* Fuego, Antártida e Islas del Atlántico Sur" province, whose `MultiPolygon`
|
|
25
|
+
* spans the mainland island, the Antarctic sector, and the South Atlantic
|
|
26
|
+
* islands in one feature — would otherwise get a single hover point
|
|
27
|
+
* stranded somewhere between all of them, matching hovers over *none* of
|
|
28
|
+
* the actually-rendered shapes. Multiple points attributed to the same
|
|
29
|
+
* feature is fine for hover-matching (nearest point wins, whichever part
|
|
30
|
+
* that is); it's only label placement (`geometryCentroid`) that needs a
|
|
31
|
+
* single point.
|
|
32
|
+
*/
|
|
33
|
+
export declare function geometryPartCentroids(geometry: GeoJSON.Geometry): [number, number][];
|
|
34
|
+
/**
|
|
35
|
+
* Keeps or drops each disjoint part of a geometry (see `splitGeometryParts`)
|
|
36
|
+
* based on a per-part predicate, reassembling a geometry of the same type
|
|
37
|
+
* from whatever survives — `null` if nothing does. Used to let a single
|
|
38
|
+
* feature's geometry be split between the main map and an `inset` marker
|
|
39
|
+
* (see `GeoDataProps.excludeParts`/`GeoInsetMarker.featurePartsFilter`)
|
|
40
|
+
* without preprocessing the source data: e.g. a province whose `MultiPolygon`
|
|
41
|
+
* spans both a mainland part and a far-flung part can have the main map
|
|
42
|
+
* exclude the latter while an inset shows only it.
|
|
43
|
+
*/
|
|
44
|
+
export declare function filterGeometryParts(geometry: GeoJSON.Geometry, keep: (part: {
|
|
45
|
+
centroid: [number, number];
|
|
46
|
+
geometry: GeoJSON.Geometry;
|
|
47
|
+
}) => boolean): GeoJSON.Geometry | null;
|
|
48
|
+
/** Default `featureId`: `feature.id`, else `properties.id`, else `properties.name`. */
|
|
49
|
+
export declare function defaultFeatureId<TProps extends Record<string, unknown>>(f: GeoFeature<TProps>): string;
|
|
50
|
+
/**
|
|
51
|
+
* Densifies a great-circle arc between two lon/lat points into `steps + 1`
|
|
52
|
+
* points via spherical linear interpolation (slerp) — used to draw a `link`
|
|
53
|
+
* marker's geodesic curve through the `Geo` mark (see `Plot.svelte`).
|
|
54
|
+
*
|
|
55
|
+
* Not delegated to svelteplot's own `Link` mark: its 0.14.2 projection
|
|
56
|
+
* integration (`Mark.svelte`'s paired-channel handling) reads a single
|
|
57
|
+
* `row.x`/`row.y` pair regardless of channel suffix, so a mark bound to
|
|
58
|
+
* `x1`/`y1`/`x2`/`y2` (never plain `x`/`y`) resolves every point as invalid
|
|
59
|
+
* whenever the plot has an active `projection` scale — which GeoPlot always
|
|
60
|
+
* does. `Geo` has no such limitation (geo marks are explicitly excluded from
|
|
61
|
+
* that code path), so a manually-interpolated `LineString` feature sidesteps
|
|
62
|
+
* the bug entirely while still producing the same geodesic visual.
|
|
63
|
+
*/
|
|
64
|
+
export declare function greatCircleInterpolate(lon1: number, lat1: number, lon2: number, lat2: number, steps?: number): [number, number][];
|