@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
|
@@ -1,294 +0,0 @@
|
|
|
1
|
-
<script lang="ts" generics="TData extends Record<string, unknown>">
|
|
2
|
-
import type { ComponentProps, Snippet } from 'svelte';
|
|
3
|
-
import { Plot, Pointer, RuleX, RuleY, AxisX, AxisY } from 'svelteplot';
|
|
4
|
-
import { getConfiguration } from '../../configuration/config.svelte';
|
|
5
|
-
import { getHover, createHover } from '../tooltip/hover.svelte';
|
|
6
|
-
import { createHoverController } from '../tooltip/controller.svelte';
|
|
7
|
-
import { hasHoverMarker, findHoverMarker } from '../tooltip/utils';
|
|
8
|
-
import HoverMarker from '../../plots/markers/HoverMarker.svelte';
|
|
9
|
-
import Tooltip from '../tooltip/Tooltip.svelte';
|
|
10
|
-
import type { AxisValue, AxisScale, Series, ScalesConfig, MarginConfig } from '../../types/plots/common';
|
|
11
|
-
import type { Marker } from '../../types/plots/markers';
|
|
12
|
-
import type { HoverStrategy, HoverDisplayPoint, HoverPoint, TooltipRuntime } from '../../types/layout/tooltip';
|
|
13
|
-
|
|
14
|
-
type SveltePlotProps = ComponentProps<typeof Plot>;
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Shared chrome around every plot kind's svelteplot markup: the pointer-event
|
|
18
|
-
* wrapper, the hover/tooltip state machine, the `<Plot>` element itself plus
|
|
19
|
-
* standalone markers (`ruleX`/`ruleY`/un-scoped `component`) and the floating
|
|
20
|
-
* tooltip. A plot kind only supplies its data/accessors and its marks
|
|
21
|
-
* (`<Line>`/`<BarY>`/`<Cell>`, …) through `children`.
|
|
22
|
-
*/
|
|
23
|
-
let {
|
|
24
|
-
width,
|
|
25
|
-
height,
|
|
26
|
-
x,
|
|
27
|
-
y,
|
|
28
|
-
data,
|
|
29
|
-
getX,
|
|
30
|
-
getY,
|
|
31
|
-
matchY,
|
|
32
|
-
hoverPoints,
|
|
33
|
-
label,
|
|
34
|
-
tooltip = undefined,
|
|
35
|
-
markers = [],
|
|
36
|
-
seriesData = [],
|
|
37
|
-
showHoverLabels = true,
|
|
38
|
-
scales,
|
|
39
|
-
margins,
|
|
40
|
-
defaultStrategy = 'x',
|
|
41
|
-
children,
|
|
42
|
-
}: {
|
|
43
|
-
width: number;
|
|
44
|
-
height: number;
|
|
45
|
-
x?: SveltePlotProps['x'];
|
|
46
|
-
y?: SveltePlotProps['y'];
|
|
47
|
-
/** Flat rows fed to svelteplot's `<Pointer>` for nearest-point matching. */
|
|
48
|
-
data: TData[];
|
|
49
|
-
getX: (d: TData) => AxisValue;
|
|
50
|
-
getY: (d: TData) => AxisValue;
|
|
51
|
-
/** Pointer's `y` channel — only needed when matching must be 2D (e.g. a heatmap grid). */
|
|
52
|
-
matchY?: (d: TData) => AxisValue;
|
|
53
|
-
hoverPoints: HoverPoint<TData>[];
|
|
54
|
-
label: (row: TData) => string;
|
|
55
|
-
tooltip?: TooltipRuntime<TData>;
|
|
56
|
-
markers?: Marker[];
|
|
57
|
-
/** All resolved series, forwarded to unscoped component markers (e.g. DeltaMarker). */
|
|
58
|
-
seriesData?: Series<TData>[];
|
|
59
|
-
/** Scale config forwarded from the plot. */
|
|
60
|
-
scales?: ScalesConfig;
|
|
61
|
-
/** Partial margin override — merged on top of the theme before tickRotate adjustment. */
|
|
62
|
-
margins?: MarginConfig;
|
|
63
|
-
showHoverLabels?: boolean;
|
|
64
|
-
/**
|
|
65
|
-
* The plot kind's default hover strategy when none is set on the tooltip or
|
|
66
|
-
* hover marker. Line/bar → `'x'`, pyramid → `'y'`, heatmap → `'punctual'`.
|
|
67
|
-
*/
|
|
68
|
-
defaultStrategy?: HoverStrategy;
|
|
69
|
-
/**
|
|
70
|
-
* `matchedPoints` carries only display info (+ `series`), not `row` — a
|
|
71
|
-
* per-series-scoped `HoverMarker` never needs the source row, just enough
|
|
72
|
-
* to filter and place dots/labels, which sidesteps forcing a concrete
|
|
73
|
-
* `TData` resolution through this snippet's type for every plot kind.
|
|
74
|
-
* `impliesRuleX`/`impliesRuleY` tell the plot kind whether the active
|
|
75
|
-
* strategy implies a crosshair rule on each axis by default.
|
|
76
|
-
*/
|
|
77
|
-
children: Snippet<
|
|
78
|
-
[{
|
|
79
|
-
matchedPoints: HoverDisplayPoint[];
|
|
80
|
-
ruleX: AxisValue | null;
|
|
81
|
-
ruleY: AxisValue | null;
|
|
82
|
-
impliesRuleX: boolean;
|
|
83
|
-
impliesRuleY: boolean;
|
|
84
|
-
}]
|
|
85
|
-
>;
|
|
86
|
-
} = $props();
|
|
87
|
-
|
|
88
|
-
const cfg = $derived(getConfiguration());
|
|
89
|
-
|
|
90
|
-
const computedMargins = $derived.by(() => {
|
|
91
|
-
const base = { ...cfg.margins, ...margins };
|
|
92
|
-
const xRotate = scales?.x?.tickRotate;
|
|
93
|
-
if (!xRotate) return base;
|
|
94
|
-
const rad = Math.abs(xRotate) * Math.PI / 180;
|
|
95
|
-
return {
|
|
96
|
-
...base,
|
|
97
|
-
bottom: base.bottom + Math.ceil(Math.sin(rad) * 20),
|
|
98
|
-
};
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
// ── Axis ticks / domain ──────────────────────────────────────────────────
|
|
102
|
-
|
|
103
|
-
const xValues = $derived(data.map(getX));
|
|
104
|
-
const yValues = $derived(data.map(getY));
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Caps the requested tick count to the axis's own number of distinct
|
|
108
|
-
* values, but never above what the pixel width would naturally request —
|
|
109
|
-
* so a narrow domain (e.g. 5 whole years) never gets subdivided into
|
|
110
|
-
* fractional ticks (2020, 2020.5, 2021, …) just to fill the space. Skipped
|
|
111
|
-
* whenever the caller already controls tick density directly.
|
|
112
|
-
*/
|
|
113
|
-
function autoTickCount(scale: AxisScale | undefined, values: AxisValue[], span: number, spacing: number, min: number): number | undefined {
|
|
114
|
-
if (scale?.ticks != null || scale?.tickSpacing != null || scale?.interval != null) return undefined;
|
|
115
|
-
const uniqueCount = new Set(values.map(String)).size;
|
|
116
|
-
const natural = Math.max(min, Math.round(span / spacing));
|
|
117
|
-
return uniqueCount >= 2 && uniqueCount < natural ? uniqueCount : undefined;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const xTickCount = $derived(
|
|
121
|
-
autoTickCount(scales?.x, xValues, Math.max(0, width - computedMargins.left - computedMargins.right), 80, 3),
|
|
122
|
-
);
|
|
123
|
-
const yTickCount = $derived(
|
|
124
|
-
autoTickCount(scales?.y, yValues, Math.max(0, height - computedMargins.top - computedMargins.bottom), 50, 2),
|
|
125
|
-
);
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* svelteplot's own `sort` scale option only toggles a fixed ascending sort
|
|
129
|
-
* (lexicographic for strings) — it can't take a custom comparator. When the
|
|
130
|
-
* caller supplies one via `scales.x.sort`/`scales.y.sort` for a string-valued
|
|
131
|
-
* axis (e.g. dates formatted as text), compute the ordered domain ourselves
|
|
132
|
-
* and hand it to the scale as an explicit `domain`, which svelteplot does
|
|
133
|
-
* respect as-is for ordinal scales.
|
|
134
|
-
*/
|
|
135
|
-
function sortedScale<T>(scale: T, scaleConfig: AxisScale | undefined, values: AxisValue[]): T {
|
|
136
|
-
const sort = scaleConfig?.sort;
|
|
137
|
-
if (!sort || scaleConfig?.domain || values.length === 0) return scale;
|
|
138
|
-
if (!values.every((v) => typeof v === 'string')) return scale;
|
|
139
|
-
const domain = [...new Set(values)].sort(sort);
|
|
140
|
-
return { ...(scale as object), domain } as T;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
const resolvedX = $derived(sortedScale(x, scales?.x, xValues));
|
|
144
|
-
const resolvedY = $derived(sortedScale(y, scales?.y, yValues));
|
|
145
|
-
|
|
146
|
-
// ── Hover / tooltip ───────────────────────────────────────────────────────
|
|
147
|
-
const hoverActive = $derived(tooltip != null || hasHoverMarker(markers));
|
|
148
|
-
|
|
149
|
-
const sharedHover = getHover();
|
|
150
|
-
const localHover = createHover();
|
|
151
|
-
const hover = $derived(sharedHover ?? localHover);
|
|
152
|
-
|
|
153
|
-
$effect(() => {
|
|
154
|
-
if (sharedHover) return;
|
|
155
|
-
const hoverMarker = findHoverMarker(markers);
|
|
156
|
-
localHover.strategy = tooltip?.strategy ?? hoverMarker?.strategy ?? defaultStrategy;
|
|
157
|
-
localHover.sync = tooltip?.sync ?? hoverMarker?.sync ?? false;
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
const ctrl = createHoverController<TData>({
|
|
161
|
-
hover: () => hover,
|
|
162
|
-
facetId: () => tooltip?.facetId ?? '',
|
|
163
|
-
points: () => hoverPoints,
|
|
164
|
-
getX: () => getX,
|
|
165
|
-
getY: () => getY,
|
|
166
|
-
label: () => label,
|
|
167
|
-
format: () => tooltip?.format ?? label,
|
|
168
|
-
seriesFilter: () => tooltip?.series,
|
|
169
|
-
width: () => width,
|
|
170
|
-
height: () => height,
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
const topLevelMarkers = $derived(
|
|
174
|
-
markers.filter(
|
|
175
|
-
(marker) =>
|
|
176
|
-
marker.type === 'ruleX' ||
|
|
177
|
-
marker.type === 'ruleY' ||
|
|
178
|
-
(marker.type === 'component' && !marker.series),
|
|
179
|
-
),
|
|
180
|
-
);
|
|
181
|
-
|
|
182
|
-
/** The unscoped (no `series`) hover marker, if any. */
|
|
183
|
-
const unscopedHoverMarker = $derived(
|
|
184
|
-
markers.find((m) => m.type === 'hover' && !m.series) as
|
|
185
|
-
| Extract<Marker, { type: 'hover' }>
|
|
186
|
-
| undefined,
|
|
187
|
-
);
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* Gate ruleX display: shows when the strategy implies it (default) or the
|
|
191
|
-
* marker explicitly requests it (`ruleX: true`), and is never suppressed
|
|
192
|
-
* unless the marker explicitly disables it (`ruleX: false`).
|
|
193
|
-
*/
|
|
194
|
-
const showRuleX = $derived(
|
|
195
|
-
unscopedHoverMarker != null &&
|
|
196
|
-
unscopedHoverMarker.ruleX !== false &&
|
|
197
|
-
(ctrl.impliesRuleX || unscopedHoverMarker.ruleX === true),
|
|
198
|
-
);
|
|
199
|
-
const showRuleY = $derived(
|
|
200
|
-
unscopedHoverMarker != null &&
|
|
201
|
-
unscopedHoverMarker.ruleY !== false &&
|
|
202
|
-
(ctrl.impliesRuleY || unscopedHoverMarker.ruleY === true),
|
|
203
|
-
);
|
|
204
|
-
</script>
|
|
205
|
-
|
|
206
|
-
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
207
|
-
<div
|
|
208
|
-
class="dct-plot"
|
|
209
|
-
style:color={cfg.axis.color}
|
|
210
|
-
onpointermove={hoverActive ? ctrl.onMove : undefined}
|
|
211
|
-
onpointerleave={hoverActive ? ctrl.onLeave : undefined}
|
|
212
|
-
>
|
|
213
|
-
<Plot {width} {height} margin={computedMargins} x={resolvedX} y={resolvedY}>
|
|
214
|
-
<AxisX
|
|
215
|
-
tickCount={xTickCount}
|
|
216
|
-
tickSize={scales?.x?.tickSize ?? cfg.axis.xTickSize}
|
|
217
|
-
tickPadding={scales?.x?.tickPadding ?? cfg.axis.xTickPadding}
|
|
218
|
-
tickFontSize={cfg.axis.fontSize}
|
|
219
|
-
titleFontSize={scales?.x?.titleFontSize ?? cfg.axis.titleFontSize}
|
|
220
|
-
/>
|
|
221
|
-
<AxisY
|
|
222
|
-
tickCount={yTickCount}
|
|
223
|
-
tickSize={scales?.y?.tickSize ?? cfg.axis.yTickSize}
|
|
224
|
-
tickPadding={scales?.y?.tickPadding ?? cfg.axis.yTickPadding}
|
|
225
|
-
tickFontSize={cfg.axis.fontSize}
|
|
226
|
-
titleFontSize={scales?.y?.titleFontSize ?? cfg.axis.titleFontSize}
|
|
227
|
-
/>
|
|
228
|
-
{@render children({
|
|
229
|
-
matchedPoints: ctrl.points,
|
|
230
|
-
ruleX: ctrl.ruleX,
|
|
231
|
-
ruleY: ctrl.ruleY,
|
|
232
|
-
impliesRuleX: ctrl.impliesRuleX,
|
|
233
|
-
impliesRuleY: ctrl.impliesRuleY,
|
|
234
|
-
})}
|
|
235
|
-
|
|
236
|
-
{#each topLevelMarkers as marker, i (marker.type === 'ruleX' ? `${marker.type}-${marker.x}` : marker.type === 'ruleY' ? `${marker.type}-${marker.y}` : `${marker.type}-${i}`)}
|
|
237
|
-
{#if marker.type === 'ruleX'}
|
|
238
|
-
<RuleX
|
|
239
|
-
data={[{ xValue: marker.x }]}
|
|
240
|
-
x={(d) => d.xValue}
|
|
241
|
-
stroke={marker.style?.stroke ?? 'currentColor'}
|
|
242
|
-
strokeWidth={marker.style?.strokeWidth ?? 1}
|
|
243
|
-
strokeOpacity={marker.style?.strokeOpacity ?? 1}
|
|
244
|
-
strokeDasharray={marker.style?.strokeDasharray}
|
|
245
|
-
/>
|
|
246
|
-
{:else if marker.type === 'ruleY'}
|
|
247
|
-
<RuleY
|
|
248
|
-
data={[{ yValue: marker.y }]}
|
|
249
|
-
y={(d) => d.yValue}
|
|
250
|
-
stroke={marker.style?.stroke ?? 'currentColor'}
|
|
251
|
-
strokeWidth={marker.style?.strokeWidth ?? 1}
|
|
252
|
-
strokeOpacity={marker.style?.strokeOpacity ?? 1}
|
|
253
|
-
strokeDasharray={marker.style?.strokeDasharray}
|
|
254
|
-
/>
|
|
255
|
-
{:else if marker.type === 'component'}
|
|
256
|
-
<marker.component {...marker.props} data={marker.data ?? seriesData} />
|
|
257
|
-
{/if}
|
|
258
|
-
{/each}
|
|
259
|
-
|
|
260
|
-
{#if hoverActive}
|
|
261
|
-
<Pointer {data} x={getX} y={matchY} maxDistance={400} onupdate={ctrl.onPointer} />
|
|
262
|
-
{/if}
|
|
263
|
-
|
|
264
|
-
{#if unscopedHoverMarker}
|
|
265
|
-
<HoverMarker
|
|
266
|
-
data={ctrl.points}
|
|
267
|
-
ruleX={showRuleX ? ctrl.ruleX : null}
|
|
268
|
-
ruleY={showRuleY ? ctrl.ruleY : null}
|
|
269
|
-
showLabels={unscopedHoverMarker.showLabels ?? showHoverLabels}
|
|
270
|
-
format={unscopedHoverMarker.format}
|
|
271
|
-
ruleStyle={unscopedHoverMarker.ruleStyle}
|
|
272
|
-
dotStyle={unscopedHoverMarker.dotStyle}
|
|
273
|
-
fontStyle={unscopedHoverMarker.fontStyle}
|
|
274
|
-
/>
|
|
275
|
-
{/if}
|
|
276
|
-
</Plot>
|
|
277
|
-
|
|
278
|
-
{#if tooltip && ctrl.showTooltip && ctrl.tooltipPosition}
|
|
279
|
-
<Tooltip x={ctrl.tooltipPosition?.x ?? 0} y={ctrl.tooltipPosition?.y ?? 0} bounds={{ width, height }}>
|
|
280
|
-
{#if tooltip.content}
|
|
281
|
-
{@render tooltip.content({ rows: ctrl.matchedRows.map((p) => p.row) })}
|
|
282
|
-
{:else}
|
|
283
|
-
{ctrl.tooltipText}
|
|
284
|
-
{/if}
|
|
285
|
-
</Tooltip>
|
|
286
|
-
{/if}
|
|
287
|
-
</div>
|
|
288
|
-
|
|
289
|
-
<style>
|
|
290
|
-
.dct-plot {
|
|
291
|
-
position: relative;
|
|
292
|
-
line-height: 0;
|
|
293
|
-
}
|
|
294
|
-
</style>
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import type { Snippet } from 'svelte';
|
|
2
|
-
import type { AxisValue, Series, ScalesConfig, MarginConfig } from '../../types/plots/common';
|
|
3
|
-
import type { Marker } from '../../types/plots/markers';
|
|
4
|
-
import type { HoverStrategy, HoverDisplayPoint, HoverPoint, TooltipRuntime } from '../../types/layout/tooltip';
|
|
5
|
-
declare function $$render<TData extends Record<string, unknown>>(): {
|
|
6
|
-
props: {
|
|
7
|
-
width: number;
|
|
8
|
-
height: number;
|
|
9
|
-
x?: false | Partial<import("svelteplot/types/scale.js").XScaleOptions> | import("svelteplot/types/data.js").RawValue[] | undefined;
|
|
10
|
-
y?: false | import("svelteplot/types/data.js").RawValue[] | Partial<import("svelteplot/types/scale.js").YScaleOptions> | undefined;
|
|
11
|
-
/** Flat rows fed to svelteplot's `<Pointer>` for nearest-point matching. */
|
|
12
|
-
data: TData[];
|
|
13
|
-
getX: (d: TData) => AxisValue;
|
|
14
|
-
getY: (d: TData) => AxisValue;
|
|
15
|
-
/** Pointer's `y` channel — only needed when matching must be 2D (e.g. a heatmap grid). */
|
|
16
|
-
matchY?: (d: TData) => AxisValue;
|
|
17
|
-
hoverPoints: HoverPoint<TData>[];
|
|
18
|
-
label: (row: TData) => string;
|
|
19
|
-
tooltip?: TooltipRuntime<TData>;
|
|
20
|
-
markers?: Marker[];
|
|
21
|
-
/** All resolved series, forwarded to unscoped component markers (e.g. DeltaMarker). */
|
|
22
|
-
seriesData?: Series<TData>[];
|
|
23
|
-
/** Scale config forwarded from the plot. */
|
|
24
|
-
scales?: ScalesConfig;
|
|
25
|
-
/** Partial margin override — merged on top of the theme before tickRotate adjustment. */
|
|
26
|
-
margins?: MarginConfig;
|
|
27
|
-
showHoverLabels?: boolean;
|
|
28
|
-
/**
|
|
29
|
-
* The plot kind's default hover strategy when none is set on the tooltip or
|
|
30
|
-
* hover marker. Line/bar → `'x'`, pyramid → `'y'`, heatmap → `'punctual'`.
|
|
31
|
-
*/
|
|
32
|
-
defaultStrategy?: HoverStrategy;
|
|
33
|
-
/**
|
|
34
|
-
* `matchedPoints` carries only display info (+ `series`), not `row` — a
|
|
35
|
-
* per-series-scoped `HoverMarker` never needs the source row, just enough
|
|
36
|
-
* to filter and place dots/labels, which sidesteps forcing a concrete
|
|
37
|
-
* `TData` resolution through this snippet's type for every plot kind.
|
|
38
|
-
* `impliesRuleX`/`impliesRuleY` tell the plot kind whether the active
|
|
39
|
-
* strategy implies a crosshair rule on each axis by default.
|
|
40
|
-
*/
|
|
41
|
-
children: Snippet<[{
|
|
42
|
-
matchedPoints: HoverDisplayPoint[];
|
|
43
|
-
ruleX: AxisValue | null;
|
|
44
|
-
ruleY: AxisValue | null;
|
|
45
|
-
impliesRuleX: boolean;
|
|
46
|
-
impliesRuleY: boolean;
|
|
47
|
-
}]>;
|
|
48
|
-
};
|
|
49
|
-
exports: {};
|
|
50
|
-
bindings: "";
|
|
51
|
-
slots: {};
|
|
52
|
-
events: {};
|
|
53
|
-
};
|
|
54
|
-
declare class __sveltets_Render<TData extends Record<string, unknown>> {
|
|
55
|
-
props(): ReturnType<typeof $$render<TData>>['props'];
|
|
56
|
-
events(): ReturnType<typeof $$render<TData>>['events'];
|
|
57
|
-
slots(): ReturnType<typeof $$render<TData>>['slots'];
|
|
58
|
-
bindings(): "";
|
|
59
|
-
exports(): {};
|
|
60
|
-
}
|
|
61
|
-
interface $$IsomorphicComponent {
|
|
62
|
-
new <TData extends Record<string, unknown>>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<TData>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<TData>['props']>, ReturnType<__sveltets_Render<TData>['events']>, ReturnType<__sveltets_Render<TData>['slots']>> & {
|
|
63
|
-
$$bindings?: ReturnType<__sveltets_Render<TData>['bindings']>;
|
|
64
|
-
} & ReturnType<__sveltets_Render<TData>['exports']>;
|
|
65
|
-
<TData extends Record<string, unknown>>(internal: unknown, props: ReturnType<__sveltets_Render<TData>['props']> & {}): ReturnType<__sveltets_Render<TData>['exports']>;
|
|
66
|
-
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
67
|
-
}
|
|
68
|
-
declare const PlotLayout: $$IsomorphicComponent;
|
|
69
|
-
type PlotLayout<TData extends Record<string, unknown>> = InstanceType<typeof PlotLayout<TData>>;
|
|
70
|
-
export default PlotLayout;
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { RuleX, RuleY } from 'svelteplot';
|
|
3
|
-
import DotMarker from './DotMarker.svelte';
|
|
4
|
-
import TextMarker from './TextMarker.svelte';
|
|
5
|
-
import { getConfiguration } from '../../configuration/config.svelte';
|
|
6
|
-
import type { MarkerProps } from '../../types/plots/markers';
|
|
7
|
-
import type { AxisValue } from '../../types/plots/common';
|
|
8
|
-
import type { DotStyle, FontStyle, StrokeStyle } from '../../types/plots/styles';
|
|
9
|
-
import type { HoverDisplayPoint } from '../../types/layout/tooltip';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* In-SVG hover highlight, rendered *inside* a `<Plot>`. Because it positions
|
|
13
|
-
* itself through the host plot's scales, it places the same coordinate
|
|
14
|
-
* correctly in every facet — that is what makes cross-facet sync work without
|
|
15
|
-
* any pixel math. Draws optional x/y crosshair rules plus a dot + value label
|
|
16
|
-
* for each matched point.
|
|
17
|
-
*/
|
|
18
|
-
interface Props extends MarkerProps<HoverDisplayPoint> {
|
|
19
|
-
ruleX?: AxisValue | null;
|
|
20
|
-
ruleY?: AxisValue | null;
|
|
21
|
-
showLabels?: boolean;
|
|
22
|
-
format?: (point: HoverDisplayPoint) => string;
|
|
23
|
-
ruleStyle?: StrokeStyle;
|
|
24
|
-
dotStyle?: DotStyle;
|
|
25
|
-
fontStyle?: FontStyle;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
let {
|
|
29
|
-
data = [],
|
|
30
|
-
ruleX = null,
|
|
31
|
-
ruleY = null,
|
|
32
|
-
showLabels = true,
|
|
33
|
-
format,
|
|
34
|
-
ruleStyle,
|
|
35
|
-
dotStyle,
|
|
36
|
-
fontStyle,
|
|
37
|
-
seriesColor,
|
|
38
|
-
}: Props = $props();
|
|
39
|
-
|
|
40
|
-
const cfg = $derived(getConfiguration());
|
|
41
|
-
|
|
42
|
-
/** Explicit style wins; otherwise fall back to the series color, then the point's own resolved color. */
|
|
43
|
-
const resolveColor = (explicit: string | undefined, point: HoverDisplayPoint) =>
|
|
44
|
-
explicit ?? seriesColor ?? point.color;
|
|
45
|
-
</script>
|
|
46
|
-
|
|
47
|
-
{#if ruleX != null}
|
|
48
|
-
<RuleX
|
|
49
|
-
data={[{ v: ruleX }]}
|
|
50
|
-
x={(d) => d.v}
|
|
51
|
-
stroke={ruleStyle?.stroke ?? cfg.hover.rule.stroke}
|
|
52
|
-
strokeOpacity={ruleStyle?.strokeOpacity ?? cfg.hover.rule.strokeOpacity}
|
|
53
|
-
strokeWidth={ruleStyle?.strokeWidth ?? cfg.hover.rule.strokeWidth}
|
|
54
|
-
strokeDasharray={ruleStyle?.strokeDasharray ?? cfg.hover.rule.strokeDasharray}
|
|
55
|
-
/>
|
|
56
|
-
{/if}
|
|
57
|
-
|
|
58
|
-
{#if ruleY != null}
|
|
59
|
-
<RuleY
|
|
60
|
-
data={[{ v: ruleY }]}
|
|
61
|
-
y={(d) => d.v}
|
|
62
|
-
stroke={ruleStyle?.stroke ?? cfg.hover.rule.stroke}
|
|
63
|
-
strokeOpacity={ruleStyle?.strokeOpacity ?? cfg.hover.rule.strokeOpacity}
|
|
64
|
-
strokeWidth={ruleStyle?.strokeWidth ?? cfg.hover.rule.strokeWidth}
|
|
65
|
-
strokeDasharray={ruleStyle?.strokeDasharray ?? cfg.hover.rule.strokeDasharray}
|
|
66
|
-
/>
|
|
67
|
-
{/if}
|
|
68
|
-
|
|
69
|
-
{#if data.length > 0}
|
|
70
|
-
{#each data as point (point.series ?? `${point.x}_${point.y}`)}
|
|
71
|
-
<DotMarker
|
|
72
|
-
data={[point]}
|
|
73
|
-
x={(d) => d.x}
|
|
74
|
-
y={(d) => d.y}
|
|
75
|
-
style={{
|
|
76
|
-
...cfg.hover.dot,
|
|
77
|
-
...dotStyle,
|
|
78
|
-
dotFill: resolveColor(dotStyle?.dotFill, point),
|
|
79
|
-
dotStroke: resolveColor(dotStyle?.dotStroke, point),
|
|
80
|
-
}}
|
|
81
|
-
/>
|
|
82
|
-
{/each}
|
|
83
|
-
{#if showLabels}
|
|
84
|
-
{#each data as point (point.series ?? `${point.x}_${point.y}`)}
|
|
85
|
-
<TextMarker
|
|
86
|
-
data={[point]}
|
|
87
|
-
x={(d) => d.x}
|
|
88
|
-
y={(d) => d.y}
|
|
89
|
-
text={(d) => format ? format(d) : (d.label ?? '')}
|
|
90
|
-
style={{
|
|
91
|
-
...cfg.hover.font,
|
|
92
|
-
...fontStyle,
|
|
93
|
-
fill: resolveColor(fontStyle?.fill, point),
|
|
94
|
-
}}
|
|
95
|
-
/>
|
|
96
|
-
{/each}
|
|
97
|
-
{/if}
|
|
98
|
-
{/if}
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
export type AxisValue = number | string | Date;
|
|
2
|
-
/** Partial margin override — only the sides you specify are overridden; the rest come from the theme. */
|
|
3
|
-
export type MarginConfig = Partial<{
|
|
4
|
-
top: number;
|
|
5
|
-
right: number;
|
|
6
|
-
bottom: number;
|
|
7
|
-
left: number;
|
|
8
|
-
}>;
|
|
9
|
-
/**
|
|
10
|
-
* Author-facing scale overrides for a plot axis. Mirrors svelteplot's
|
|
11
|
-
* `ScaleOptions` + `XScaleOptions` in full — `type`, `padding`, `domain`,
|
|
12
|
-
* `nice`, `reverse`, `label`, `tickFormat`, `labelAnchor`, etc.
|
|
13
|
-
*
|
|
14
|
-
* Used for both `x` and `y` entries in {@link ScalesConfig}. X-specific
|
|
15
|
-
* fields (`labelAnchor`, `tickRotate`) are accepted on `y` too; svelteplot
|
|
16
|
-
* silently ignores any inapplicable options.
|
|
17
|
-
*/
|
|
18
|
-
export type AxisScale = {
|
|
19
|
-
type?: 'auto' | 'linear' | 'pow' | 'sqrt' | 'log' | 'symlog' | 'time' | 'utc' | 'point' | 'ordinal' | 'sequential' | 'band' | 'categorical' | 'cyclical' | 'threshold' | 'quantile-cont' | 'quantile' | 'quantize' | 'diverging' | 'diverging-log' | 'diverging-pow' | 'diverging-sqrt' | 'diverging-symlog';
|
|
20
|
-
domain?: (number | string | boolean | Date | null)[];
|
|
21
|
-
range?: (number | string | boolean | Date | null)[];
|
|
22
|
-
reverse?: boolean;
|
|
23
|
-
label?: string | false;
|
|
24
|
-
interval?: string | number;
|
|
25
|
-
clamp?: boolean;
|
|
26
|
-
nice?: boolean;
|
|
27
|
-
zero?: boolean;
|
|
28
|
-
round?: boolean;
|
|
29
|
-
percent?: boolean;
|
|
30
|
-
padding?: number;
|
|
31
|
-
align?: number;
|
|
32
|
-
paddingInner?: number;
|
|
33
|
-
paddingOuter?: number;
|
|
34
|
-
insetLeft?: number;
|
|
35
|
-
insetRight?: number;
|
|
36
|
-
insetTop?: number;
|
|
37
|
-
insetBottom?: number;
|
|
38
|
-
ticks?: (number | string | boolean | Date | null)[];
|
|
39
|
-
tickSpacing?: number;
|
|
40
|
-
tickSize?: number;
|
|
41
|
-
tickPadding?: number;
|
|
42
|
-
titleFontSize?: number;
|
|
43
|
-
base?: number;
|
|
44
|
-
constant?: number;
|
|
45
|
-
sort?: (a: AxisValue, b: AxisValue) => number;
|
|
46
|
-
grid?: boolean;
|
|
47
|
-
tickRotate?: number;
|
|
48
|
-
tickFormat?: false | Intl.NumberFormatOptions | Intl.DateTimeFormatOptions | ((d: unknown, index: number, ticks: unknown[]) => string | string[]);
|
|
49
|
-
};
|
|
50
|
-
/**
|
|
51
|
-
* Per-axis scale overrides, passed as a single `scales` prop to every plot
|
|
52
|
-
* kind.
|
|
53
|
-
*/
|
|
54
|
-
export type ScalesConfig = {
|
|
55
|
-
x?: AxisScale;
|
|
56
|
-
y?: AxisScale;
|
|
57
|
-
z?: AxisScale;
|
|
58
|
-
};
|
|
59
|
-
/**
|
|
60
|
-
* A field key or accessor function. Mirrors the shorthand used across plots
|
|
61
|
-
* so chart-level encodings (`x`, `y`, `z`, facet, timeline) feel consistent
|
|
62
|
-
* with the plot-level series definitions.
|
|
63
|
-
*/
|
|
64
|
-
export type Accessor<TRow extends Record<string, unknown>, V> = keyof TRow | ((d: TRow) => V);
|
|
65
|
-
/**
|
|
66
|
-
* A plot series: a name, x/y accessors and the rows it draws. Shared as-is by
|
|
67
|
-
* every mark (line, bar, …) — none of them need anything beyond this shape;
|
|
68
|
-
* visual styling lives separately in `segments`.
|
|
69
|
-
*/
|
|
70
|
-
export type Series<T extends Record<string, unknown> = Record<string, unknown>> = {
|
|
71
|
-
name: string;
|
|
72
|
-
x: Accessor<T, AxisValue>;
|
|
73
|
-
y: Accessor<T, AxisValue>;
|
|
74
|
-
z?: Accessor<T, unknown>;
|
|
75
|
-
data: T[];
|
|
76
|
-
};
|
|
77
|
-
/**
|
|
78
|
-
* Pre-built series. Mutually exclusive with {@link DataProps} — takes
|
|
79
|
-
* precedence when both could apply.
|
|
80
|
-
*/
|
|
81
|
-
export type SeriesProps<T extends Record<string, unknown>> = {
|
|
82
|
-
series: Series<T>[];
|
|
83
|
-
data?: never;
|
|
84
|
-
x?: never;
|
|
85
|
-
y?: never;
|
|
86
|
-
z?: never;
|
|
87
|
-
};
|
|
88
|
-
/**
|
|
89
|
-
* Flat rows to group into series, as an alternative to {@link SeriesProps}.
|
|
90
|
-
*/
|
|
91
|
-
export type DataProps<T extends Record<string, unknown>> = {
|
|
92
|
-
series?: never;
|
|
93
|
-
data: T[];
|
|
94
|
-
x: Accessor<T, AxisValue>;
|
|
95
|
-
y: Accessor<T, AxisValue>;
|
|
96
|
-
z?: Accessor<T, unknown>;
|
|
97
|
-
};
|