@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,7 +8,7 @@
|
|
|
8
8
|
TimelineChildSnippet,
|
|
9
9
|
TimelineInterpolation,
|
|
10
10
|
} from '../../types/charts/common';
|
|
11
|
-
import type { Accessor } from '../../types/plots/common';
|
|
11
|
+
import type { Accessor } from '../../types/plots/data/common';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Couples a scrubber `progress` to a discrete sequence of time steps. It picks
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Orientation, TimeValue, TimelineChildSnippet, TimelineInterpolation } from '../../types/charts/common';
|
|
2
|
-
import type { Accessor } from '../../types/plots/common';
|
|
2
|
+
import type { Accessor } from '../../types/plots/data/common';
|
|
3
3
|
declare function $$render<TRow extends Record<string, unknown>>(): {
|
|
4
4
|
props: {
|
|
5
5
|
data: TRow[];
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
background,
|
|
20
20
|
color,
|
|
21
21
|
bounds,
|
|
22
|
+
plain = false,
|
|
22
23
|
children,
|
|
23
24
|
}: {
|
|
24
25
|
x: number;
|
|
@@ -28,6 +29,13 @@
|
|
|
28
29
|
color?: string;
|
|
29
30
|
/** Box the tooltip must stay within — usually the hosting plot's width/height. */
|
|
30
31
|
bounds?: { width: number; height: number };
|
|
32
|
+
/**
|
|
33
|
+
* Drops the default dark box (background/padding/border) so a custom
|
|
34
|
+
* `content` snippet fully owns its own look. Set whenever the caller
|
|
35
|
+
* supplies `content` — the drop shadow and border radius still apply,
|
|
36
|
+
* so a custom card can match its own corners via `--dct-tooltip-radius`.
|
|
37
|
+
*/
|
|
38
|
+
plain?: boolean;
|
|
31
39
|
children: Snippet;
|
|
32
40
|
} = $props();
|
|
33
41
|
|
|
@@ -55,6 +63,7 @@
|
|
|
55
63
|
{#if visible}
|
|
56
64
|
<div
|
|
57
65
|
class="dct-tooltip"
|
|
66
|
+
class:dct-tooltip--plain={plain}
|
|
58
67
|
bind:clientWidth={boxWidth}
|
|
59
68
|
bind:clientHeight={boxHeight}
|
|
60
69
|
style:left="{placement.left}px"
|
|
@@ -81,4 +90,10 @@
|
|
|
81
90
|
white-space: pre-line;
|
|
82
91
|
line-height: 1.35;
|
|
83
92
|
}
|
|
93
|
+
|
|
94
|
+
.dct-tooltip--plain {
|
|
95
|
+
background: transparent;
|
|
96
|
+
padding: 0;
|
|
97
|
+
border: none;
|
|
98
|
+
}
|
|
84
99
|
</style>
|
|
@@ -10,6 +10,13 @@ type $$ComponentProps = {
|
|
|
10
10
|
width: number;
|
|
11
11
|
height: number;
|
|
12
12
|
};
|
|
13
|
+
/**
|
|
14
|
+
* Drops the default dark box (background/padding/border) so a custom
|
|
15
|
+
* `content` snippet fully owns its own look. Set whenever the caller
|
|
16
|
+
* supplies `content` — the drop shadow and border radius still apply,
|
|
17
|
+
* so a custom card can match its own corners via `--dct-tooltip-radius`.
|
|
18
|
+
*/
|
|
19
|
+
plain?: boolean;
|
|
13
20
|
children: Snippet;
|
|
14
21
|
};
|
|
15
22
|
declare const Tooltip: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<script lang="ts" generics="TRow extends Record<string, unknown>">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import Tooltip from './Tooltip.svelte';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The "resolve + render" step every hoverable plot repeats verbatim:
|
|
7
|
+
* given the matched row(s) for the current hover and the author's
|
|
8
|
+
* `format`/`content` config, decide what goes inside the floating
|
|
9
|
+
* `Tooltip` — its own custom snippet (`content`, given every matched row)
|
|
10
|
+
* or the newline-joined `format` text (the default). Shared by
|
|
11
|
+
* `BasePlotLayout` (fed by the shared hover controller, used by every plot
|
|
12
|
+
* kind including `GeoPlot`) and `InsetMarker` (which matches hover locally,
|
|
13
|
+
* independent of that controller) so neither re-implements this branch.
|
|
14
|
+
*/
|
|
15
|
+
let {
|
|
16
|
+
visible,
|
|
17
|
+
x,
|
|
18
|
+
y,
|
|
19
|
+
bounds,
|
|
20
|
+
rows,
|
|
21
|
+
format,
|
|
22
|
+
content,
|
|
23
|
+
}: {
|
|
24
|
+
visible: boolean;
|
|
25
|
+
x: number;
|
|
26
|
+
y: number;
|
|
27
|
+
/** Box the tooltip must stay within — see `Tooltip`'s own `bounds` doc. */
|
|
28
|
+
bounds: { width: number; height: number };
|
|
29
|
+
/** Every row the current hover matched — passed to `content` as-is; joined via `format` otherwise. */
|
|
30
|
+
rows: TRow[];
|
|
31
|
+
format: (row: TRow) => string;
|
|
32
|
+
/** Custom tooltip body; replaces the joined `format` text when given. */
|
|
33
|
+
content?: Snippet<[{ rows: TRow[] }]>;
|
|
34
|
+
} = $props();
|
|
35
|
+
</script>
|
|
36
|
+
|
|
37
|
+
{#if visible}
|
|
38
|
+
<Tooltip {x} {y} {bounds} plain={!!content}>
|
|
39
|
+
{#if content}
|
|
40
|
+
{@render content({ rows })}
|
|
41
|
+
{:else}
|
|
42
|
+
{rows.map(format).join('\n')}
|
|
43
|
+
{/if}
|
|
44
|
+
</Tooltip>
|
|
45
|
+
{/if}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
declare function $$render<TRow extends Record<string, unknown>>(): {
|
|
3
|
+
props: {
|
|
4
|
+
visible: boolean;
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
/** Box the tooltip must stay within — see `Tooltip`'s own `bounds` doc. */
|
|
8
|
+
bounds: {
|
|
9
|
+
width: number;
|
|
10
|
+
height: number;
|
|
11
|
+
};
|
|
12
|
+
/** Every row the current hover matched — passed to `content` as-is; joined via `format` otherwise. */
|
|
13
|
+
rows: TRow[];
|
|
14
|
+
format: (row: TRow) => string;
|
|
15
|
+
/** Custom tooltip body; replaces the joined `format` text when given. */
|
|
16
|
+
content?: Snippet<[{
|
|
17
|
+
rows: TRow[];
|
|
18
|
+
}]>;
|
|
19
|
+
};
|
|
20
|
+
exports: {};
|
|
21
|
+
bindings: "";
|
|
22
|
+
slots: {};
|
|
23
|
+
events: {};
|
|
24
|
+
};
|
|
25
|
+
declare class __sveltets_Render<TRow extends Record<string, unknown>> {
|
|
26
|
+
props(): ReturnType<typeof $$render<TRow>>['props'];
|
|
27
|
+
events(): ReturnType<typeof $$render<TRow>>['events'];
|
|
28
|
+
slots(): ReturnType<typeof $$render<TRow>>['slots'];
|
|
29
|
+
bindings(): "";
|
|
30
|
+
exports(): {};
|
|
31
|
+
}
|
|
32
|
+
interface $$IsomorphicComponent {
|
|
33
|
+
new <TRow extends Record<string, unknown>>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<TRow>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<TRow>['props']>, ReturnType<__sveltets_Render<TRow>['events']>, ReturnType<__sveltets_Render<TRow>['slots']>> & {
|
|
34
|
+
$$bindings?: ReturnType<__sveltets_Render<TRow>['bindings']>;
|
|
35
|
+
} & ReturnType<__sveltets_Render<TRow>['exports']>;
|
|
36
|
+
<TRow extends Record<string, unknown>>(internal: unknown, props: ReturnType<__sveltets_Render<TRow>['props']> & {}): ReturnType<__sveltets_Render<TRow>['exports']>;
|
|
37
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
38
|
+
}
|
|
39
|
+
declare const TooltipLayout: $$IsomorphicComponent;
|
|
40
|
+
type TooltipLayout<TRow extends Record<string, unknown>> = InstanceType<typeof TooltipLayout<TRow>>;
|
|
41
|
+
export default TooltipLayout;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { HoverStore, HoverPoint } from '../../types/layout/tooltip';
|
|
2
|
-
import type { AxisValue } from '../../types/plots/
|
|
2
|
+
import type { AxisValue } from '../../types/plots/axis';
|
|
3
3
|
/**
|
|
4
4
|
* The plot-agnostic hover state machine shared by every plot. Given reactive
|
|
5
5
|
* accessors for the current hover store, this facet's id, and the local points,
|
|
@@ -18,7 +18,6 @@ export declare function createHoverController<T extends Record<string, unknown>>
|
|
|
18
18
|
getY: () => (d: T) => AxisValue;
|
|
19
19
|
/** Short label drawn next to the highlight dot (e.g. the value). */
|
|
20
20
|
label: () => (row: T) => string;
|
|
21
|
-
format: () => (row: T) => string;
|
|
22
21
|
/** Named subset of series the tooltip text/content should be limited to. */
|
|
23
22
|
seriesFilter?: () => string[] | undefined;
|
|
24
23
|
/** This facet's own box, used to convert the cursor to/from a sync-broadcast fraction. */
|
|
@@ -34,6 +33,9 @@ export declare function createHoverController<T extends Record<string, unknown>>
|
|
|
34
33
|
label: string;
|
|
35
34
|
series: string | undefined;
|
|
36
35
|
color: string | undefined;
|
|
36
|
+
dx: number | undefined;
|
|
37
|
+
dy: number | undefined;
|
|
38
|
+
row: T;
|
|
37
39
|
}[];
|
|
38
40
|
readonly matchedRows: HoverPoint<T>[];
|
|
39
41
|
readonly ruleX: AxisValue | null;
|
|
@@ -41,7 +43,6 @@ export declare function createHoverController<T extends Record<string, unknown>>
|
|
|
41
43
|
readonly impliesRuleX: boolean;
|
|
42
44
|
readonly impliesRuleY: boolean;
|
|
43
45
|
readonly showTooltip: boolean;
|
|
44
|
-
readonly tooltipText: string;
|
|
45
46
|
readonly tooltipPosition: {
|
|
46
47
|
x: number;
|
|
47
48
|
y: number;
|
|
@@ -31,9 +31,12 @@ export function createHoverController(args) {
|
|
|
31
31
|
const matchedRows = $derived(filterBySeries(matched, args.seriesFilter?.()));
|
|
32
32
|
// Points highlighted in THIS facet for the in-SVG marker — no series
|
|
33
33
|
// filtering, since that's the tooltip text's concern, not the marker's.
|
|
34
|
-
|
|
34
|
+
// Keeps `row` (not just the display fields) so plot-kind templates can
|
|
35
|
+
// resolve a semantic value off the source row directly — e.g. a bar
|
|
36
|
+
// plot's category, regardless of which visual axis it's drawn on.
|
|
37
|
+
const highlight = $derived(matched.map(({ x, y, label, series, color, dx, dy, row }) => ({ x, y, label, series, color, dx, dy, row })));
|
|
35
38
|
// Raw hover position — available whenever there are matched points.
|
|
36
|
-
//
|
|
39
|
+
// BasePlotLayout gates actual display with impliesRuleX/Y + the marker's ruleX/Y props.
|
|
37
40
|
const ruleX = $derived(matched.length > 0 ? args.hover().activeX : null);
|
|
38
41
|
const ruleY = $derived(matched.length > 0 ? args.hover().activeY : null);
|
|
39
42
|
// Whether the current strategy implies a crosshair rule on each axis by default.
|
|
@@ -47,7 +50,6 @@ export function createHoverController(args) {
|
|
|
47
50
|
return cursor != null;
|
|
48
51
|
return h.sync;
|
|
49
52
|
});
|
|
50
|
-
const tooltipText = $derived(matchedRows.length ? matchedRows.map((p) => args.format()(p.row)).join('\n') : '');
|
|
51
53
|
function onPointer(data) {
|
|
52
54
|
const h = args.hover();
|
|
53
55
|
if (data.length) {
|
|
@@ -115,9 +117,6 @@ export function createHoverController(args) {
|
|
|
115
117
|
get showTooltip() {
|
|
116
118
|
return showTooltip;
|
|
117
119
|
},
|
|
118
|
-
get tooltipText() {
|
|
119
|
-
return tooltipText;
|
|
120
|
-
},
|
|
121
120
|
get tooltipPosition() {
|
|
122
121
|
return tooltipPosition;
|
|
123
122
|
},
|
|
@@ -3,5 +3,5 @@ import type { HoverStore } from '../../types/layout/tooltip';
|
|
|
3
3
|
export declare function provideHover(): HoverStore;
|
|
4
4
|
/** Read the shared hover store, or `null` when there is no provider. */
|
|
5
5
|
export declare function getHover(): HoverStore | null;
|
|
6
|
-
/** A private hover store for a plot used outside of a {@link
|
|
6
|
+
/** A private hover store for a plot used outside of a {@link BaseChart}. */
|
|
7
7
|
export declare function createHover(): HoverStore;
|
|
@@ -21,7 +21,7 @@ export function provideHover() {
|
|
|
21
21
|
export function getHover() {
|
|
22
22
|
return getContext(HOVER_KEY) ?? null;
|
|
23
23
|
}
|
|
24
|
-
/** A private hover store for a plot used outside of a {@link
|
|
24
|
+
/** A private hover store for a plot used outside of a {@link BaseChart}. */
|
|
25
25
|
export function createHover() {
|
|
26
26
|
const store = $state(blank());
|
|
27
27
|
return store;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { AxisValue } from '../../types/plots/
|
|
2
|
-
import type { Marker, HoverMarkerConfig } from '../../types/
|
|
1
|
+
import type { AxisValue } from '../../types/plots/axis';
|
|
2
|
+
import type { Marker, HoverMarkerConfig } from '../../types/markers/common';
|
|
3
3
|
import type { HoverStore, HoverStrategy, HoverPoint, TooltipProp, TooltipOptions } from '../../types/layout/tooltip';
|
|
4
4
|
/** Value equality that also handles `Date` (compared by timestamp). */
|
|
5
5
|
export declare function eq(a: AxisValue, b: AxisValue): boolean;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { geoPath, type GeoPath } from 'd3-geo';
|
|
3
|
+
import { usePlot } from 'svelteplot';
|
|
4
|
+
import type { Snippet } from 'svelte';
|
|
5
|
+
import type { GeoFeature } from '../types/plots/data/geo';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Masks a `contour` marker to just the landmass (`'land'`) or just the
|
|
9
|
+
* water (`'ocean'`) of the plot's own base map, via an SVG `clipPath` —
|
|
10
|
+
* lets a filled contour read as "temperature over land" without also
|
|
11
|
+
* painting straight across the ocean, or vice versa. A no-op passthrough
|
|
12
|
+
* when `mode` is unset, so this can unconditionally wrap every `contour`
|
|
13
|
+
* marker without an extra branch at each call site.
|
|
14
|
+
*
|
|
15
|
+
* Builds the clip path from the plot's own shared, already-fitted
|
|
16
|
+
* projection (`usePlot()` — the same hook `TileLayer.svelte` uses) rather
|
|
17
|
+
* than an independent one, so it lines up with the rest of the map
|
|
18
|
+
* regardless of projection/zoom. `'ocean'` unions the sphere and land
|
|
19
|
+
* paths into one `clip-rule: evenodd` shape — the sphere covers
|
|
20
|
+
* everything, then every land ring toggles back out, leaving only water.
|
|
21
|
+
*/
|
|
22
|
+
let {
|
|
23
|
+
mode,
|
|
24
|
+
features,
|
|
25
|
+
children,
|
|
26
|
+
}: {
|
|
27
|
+
mode: 'land' | 'ocean' | undefined;
|
|
28
|
+
features: GeoFeature<Record<string, unknown>>[];
|
|
29
|
+
children: Snippet;
|
|
30
|
+
} = $props();
|
|
31
|
+
|
|
32
|
+
const plot = usePlot();
|
|
33
|
+
const clipId = `geo-contour-clip-${Math.random().toString(36).slice(2, 9)}`;
|
|
34
|
+
|
|
35
|
+
// Same runtime shape TileLayer.svelte relies on — svelteplot's own
|
|
36
|
+
// `PlotScale` type doesn't reflect it, but `plot.scales.projection` is a
|
|
37
|
+
// real `d3-geo`-compatible stream source at runtime.
|
|
38
|
+
const path: GeoPath = $derived(geoPath(plot.scales.projection as unknown as Parameters<typeof geoPath>[0]));
|
|
39
|
+
// Some real-world datasets carry exact-duplicate features for the same
|
|
40
|
+
// territory (seen in this repo's own `WORLD_COUNTRIES` fixture, for every
|
|
41
|
+
// South American country) — harmless for an ordinary filled `<Geo>` (the
|
|
42
|
+
// duplicate just redraws the same shape), but fatal here: two identical,
|
|
43
|
+
// oppositely-would-be-redundant copies of the same ring toggle each other
|
|
44
|
+
// back out under `clip-rule: evenodd`, silently punching a hole exactly
|
|
45
|
+
// where the duplicated territory is. Deduping by geometry keeps this
|
|
46
|
+
// correct regardless of whether the caller's data happens to be clean.
|
|
47
|
+
const uniqueGeometries = $derived(
|
|
48
|
+
Array.from(new Map(features.map((f) => [JSON.stringify(f.geometry), f as unknown as GeoJSON.Feature])).values()),
|
|
49
|
+
);
|
|
50
|
+
const landPath = $derived(
|
|
51
|
+
uniqueGeometries
|
|
52
|
+
.map((f) => path(f))
|
|
53
|
+
.filter((d): d is string => !!d)
|
|
54
|
+
.join(' '),
|
|
55
|
+
);
|
|
56
|
+
// `{type: 'Sphere'}` is d3-geo's own pseudo-geometry for "the whole
|
|
57
|
+
// globe" — not part of the GeoJSON spec, so `@types/geojson` has no type
|
|
58
|
+
// for it either.
|
|
59
|
+
const spherePath = $derived(path({ type: 'Sphere' } as unknown as GeoJSON.Feature) ?? '');
|
|
60
|
+
</script>
|
|
61
|
+
|
|
62
|
+
{#if mode}
|
|
63
|
+
<defs>
|
|
64
|
+
<clipPath id={clipId}>
|
|
65
|
+
{#if mode === 'land'}
|
|
66
|
+
<path d={landPath} clip-rule="evenodd" />
|
|
67
|
+
{:else}
|
|
68
|
+
<path d="{spherePath} {landPath}" clip-rule="evenodd" />
|
|
69
|
+
{/if}
|
|
70
|
+
</clipPath>
|
|
71
|
+
</defs>
|
|
72
|
+
<g clip-path="url(#{clipId})">
|
|
73
|
+
{@render children()}
|
|
74
|
+
</g>
|
|
75
|
+
{:else}
|
|
76
|
+
{@render children()}
|
|
77
|
+
{/if}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { GeoFeature } from '../types/plots/data/geo';
|
|
3
|
+
type $$ComponentProps = {
|
|
4
|
+
mode: 'land' | 'ocean' | undefined;
|
|
5
|
+
features: GeoFeature<Record<string, unknown>>[];
|
|
6
|
+
children: Snippet;
|
|
7
|
+
};
|
|
8
|
+
declare const ContourClipMarker: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
9
|
+
type ContourClipMarker = ReturnType<typeof ContourClipMarker>;
|
|
10
|
+
export default ContourClipMarker;
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
import { Line } from 'svelteplot';
|
|
6
6
|
import DotMarker from './DotMarker.svelte';
|
|
7
7
|
import TextMarker from './TextMarker.svelte';
|
|
8
|
-
import { resolveXDeltas, resolveYDeltas } from '../utils/delta';
|
|
9
|
-
import type { MarkerProps } from '
|
|
10
|
-
import type { Series } from '
|
|
11
|
-
import type { DeltaConfig } from '
|
|
8
|
+
import { resolveXDeltas, resolveYDeltas } from '../plots/utils/delta';
|
|
9
|
+
import type { MarkerProps } from '../types/markers/props';
|
|
10
|
+
import type { Series } from '../types/plots/data/common';
|
|
11
|
+
import type { DeltaConfig } from '../types/plots/delta';
|
|
12
12
|
|
|
13
13
|
interface Props extends MarkerProps<Series<TData>>, DeltaConfig {
|
|
14
14
|
xDomain?: (number | string | Date)[];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { MarkerProps } from '
|
|
2
|
-
import type { Series } from '
|
|
3
|
-
import type { DeltaConfig } from '
|
|
1
|
+
import type { MarkerProps } from '../types/markers/props';
|
|
2
|
+
import type { Series } from '../types/plots/data/common';
|
|
3
|
+
import type { DeltaConfig } from '../types/plots/delta';
|
|
4
4
|
declare function $$render<TData extends Record<string, unknown>>(): {
|
|
5
5
|
props: MarkerProps<Series<TData>> & DeltaConfig & {
|
|
6
6
|
xDomain?: (number | string | Date)[];
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script lang="ts" generics="TData = Record<string, unknown>">
|
|
2
2
|
import { Dot } from 'svelteplot';
|
|
3
|
-
import type { MarkerProps } from '
|
|
4
|
-
import type { AxisValue } from '
|
|
5
|
-
import type { DotStyle } from '
|
|
3
|
+
import type { MarkerProps } from '../types/markers/props';
|
|
4
|
+
import type { AxisValue } from '../types/plots/axis';
|
|
5
|
+
import type { DotStyle } from '../types/plots/styling';
|
|
6
6
|
|
|
7
7
|
interface Props extends MarkerProps<TData> {
|
|
8
8
|
x?: AxisValue | ((d: TData) => AxisValue);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { MarkerProps } from '
|
|
2
|
-
import type { AxisValue } from '
|
|
3
|
-
import type { DotStyle } from '
|
|
1
|
+
import type { MarkerProps } from '../types/markers/props';
|
|
2
|
+
import type { AxisValue } from '../types/plots/axis';
|
|
3
|
+
import type { DotStyle } from '../types/plots/styling';
|
|
4
4
|
declare function $$render<TData = Record<string, unknown>>(): {
|
|
5
5
|
props: MarkerProps<TData> & {
|
|
6
6
|
x?: AxisValue | ((d: TData) => AxisValue);
|
|
@@ -0,0 +1,136 @@
|
|
|
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/markers/props';
|
|
7
|
+
import type { AxisValue } from '../types/plots/axis';
|
|
8
|
+
import type { DotStyle, FontStyle, StrokeStyle } from '../types/plots/styling';
|
|
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
|
+
|
|
46
|
+
// Horizontal gap between the dot's edge and an 'outside'-anchored label —
|
|
47
|
+
// scales with the dot's own resolved radius so the label clears it.
|
|
48
|
+
const dotRadius = $derived(dotStyle?.dotRadius ?? cfg.hover.dot.dotRadius ?? 5);
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Resolves `fontStyle.textAnchor: 'outside'` into a per-point anchor +
|
|
52
|
+
* offset, mirroring the value-label `'outside'` anchor's own left/right
|
|
53
|
+
* split (see pyramid/bar's own `ValueAnchor` handling): a positive `x`
|
|
54
|
+
* anchors `'start'` and nudges right, a negative `x` anchors `'end'` and
|
|
55
|
+
* nudges left — so a diverging mark's label sits on the side of the dot
|
|
56
|
+
* away from zero, on whichever side that dot itself landed. Only
|
|
57
|
+
* meaningful when the point's `x` is numeric (e.g. pyramid's magnitude
|
|
58
|
+
* axis); anything else falls through to the plain `fontStyle` unchanged.
|
|
59
|
+
*
|
|
60
|
+
* Also overrides `cfg.hover.font`'s default `dy: -18` (meant for a label
|
|
61
|
+
* floating *above* the dot) back to vertically centered, and clears the
|
|
62
|
+
* dot's own radius horizontally instead of the flat default nudge, so the
|
|
63
|
+
* label doesn't collide with the dot it's labeling.
|
|
64
|
+
*/
|
|
65
|
+
function resolveFontStyle(point: HoverDisplayPoint) {
|
|
66
|
+
if (fontStyle?.textAnchor !== 'outside' || typeof point.x !== 'number') {
|
|
67
|
+
return { ...cfg.hover.font, ...fontStyle, fill: resolveColor(fontStyle?.fill, point) };
|
|
68
|
+
}
|
|
69
|
+
const outward = point.x >= 0;
|
|
70
|
+
const gap = dotRadius + 5;
|
|
71
|
+
return {
|
|
72
|
+
...cfg.hover.font,
|
|
73
|
+
...fontStyle,
|
|
74
|
+
fill: resolveColor(fontStyle?.fill, point),
|
|
75
|
+
textAnchor: outward ? ('start' as const) : ('end' as const),
|
|
76
|
+
lineAnchor: fontStyle?.lineAnchor ?? ('middle' as const),
|
|
77
|
+
dx: fontStyle?.dx ?? (outward ? gap : -gap),
|
|
78
|
+
dy: fontStyle?.dy ?? 0,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
</script>
|
|
82
|
+
|
|
83
|
+
{#if ruleX != null}
|
|
84
|
+
<RuleX
|
|
85
|
+
data={[{ v: ruleX }]}
|
|
86
|
+
x={(d) => d.v}
|
|
87
|
+
stroke={ruleStyle?.stroke ?? cfg.hover.rule.stroke}
|
|
88
|
+
strokeOpacity={ruleStyle?.strokeOpacity ?? cfg.hover.rule.strokeOpacity}
|
|
89
|
+
strokeWidth={ruleStyle?.strokeWidth ?? cfg.hover.rule.strokeWidth}
|
|
90
|
+
strokeDasharray={ruleStyle?.strokeDasharray ?? cfg.hover.rule.strokeDasharray}
|
|
91
|
+
/>
|
|
92
|
+
{/if}
|
|
93
|
+
|
|
94
|
+
{#if ruleY != null}
|
|
95
|
+
<RuleY
|
|
96
|
+
data={[{ v: ruleY }]}
|
|
97
|
+
y={(d) => d.v}
|
|
98
|
+
stroke={ruleStyle?.stroke ?? cfg.hover.rule.stroke}
|
|
99
|
+
strokeOpacity={ruleStyle?.strokeOpacity ?? cfg.hover.rule.strokeOpacity}
|
|
100
|
+
strokeWidth={ruleStyle?.strokeWidth ?? cfg.hover.rule.strokeWidth}
|
|
101
|
+
strokeDasharray={ruleStyle?.strokeDasharray ?? cfg.hover.rule.strokeDasharray}
|
|
102
|
+
/>
|
|
103
|
+
{/if}
|
|
104
|
+
|
|
105
|
+
{#if data.length > 0}
|
|
106
|
+
{#each data as point (point.series ?? `${point.x}_${point.y}`)}
|
|
107
|
+
<!-- Pixel nudge for plot kinds whose series position isn't fully captured
|
|
108
|
+
by x/y alone (e.g. BarPlot's 'grouped' layout) — see HoverDisplayPoint.dx/dy. -->
|
|
109
|
+
<g transform="translate({point.dx ?? 0}, {point.dy ?? 0})">
|
|
110
|
+
<DotMarker
|
|
111
|
+
data={[point]}
|
|
112
|
+
x={(d) => d.x}
|
|
113
|
+
y={(d) => d.y}
|
|
114
|
+
style={{
|
|
115
|
+
...cfg.hover.dot,
|
|
116
|
+
...dotStyle,
|
|
117
|
+
dotFill: resolveColor(dotStyle?.dotFill, point),
|
|
118
|
+
dotStroke: resolveColor(dotStyle?.dotStroke, point),
|
|
119
|
+
}}
|
|
120
|
+
/>
|
|
121
|
+
</g>
|
|
122
|
+
{/each}
|
|
123
|
+
{#if showLabels}
|
|
124
|
+
{#each data as point (point.series ?? `${point.x}_${point.y}`)}
|
|
125
|
+
<g transform="translate({point.dx ?? 0}, {point.dy ?? 0})">
|
|
126
|
+
<TextMarker
|
|
127
|
+
data={[point]}
|
|
128
|
+
x={(d) => d.x}
|
|
129
|
+
y={(d) => d.y}
|
|
130
|
+
text={(d) => format ? format(d) : (d.label ?? '')}
|
|
131
|
+
style={resolveFontStyle(point)}
|
|
132
|
+
/>
|
|
133
|
+
</g>
|
|
134
|
+
{/each}
|
|
135
|
+
{/if}
|
|
136
|
+
{/if}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { MarkerProps } from '
|
|
2
|
-
import type { AxisValue } from '
|
|
3
|
-
import type { DotStyle, FontStyle, StrokeStyle } from '
|
|
4
|
-
import type { HoverDisplayPoint } from '
|
|
1
|
+
import type { MarkerProps } from '../types/markers/props';
|
|
2
|
+
import type { AxisValue } from '../types/plots/axis';
|
|
3
|
+
import type { DotStyle, FontStyle, StrokeStyle } from '../types/plots/styling';
|
|
4
|
+
import type { HoverDisplayPoint } from '../types/layout/tooltip';
|
|
5
5
|
/**
|
|
6
6
|
* In-SVG hover highlight, rendered *inside* a `<Plot>`. Because it positions
|
|
7
7
|
* itself through the host plot's scales, it places the same coordinate
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import DotMarker from './DotMarker.svelte';
|
|
3
3
|
import TextMarker from './TextMarker.svelte';
|
|
4
|
-
import type { MarkerProps } from '
|
|
5
|
-
import type { DotStyle, FontStyle } from '
|
|
4
|
+
import type { MarkerProps } from '../types/markers/props';
|
|
5
|
+
import type { DotStyle, FontStyle } from '../types/plots/styling';
|
|
6
6
|
|
|
7
7
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
8
8
|
interface Props extends MarkerProps<Record<string, any>> {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { MarkerProps } from '
|
|
2
|
-
import type { DotStyle, FontStyle } from '
|
|
1
|
+
import type { MarkerProps } from '../types/markers/props';
|
|
2
|
+
import type { DotStyle, FontStyle } from '../types/plots/styling';
|
|
3
3
|
interface Props extends MarkerProps<Record<string, any>> {
|
|
4
4
|
yProp?: string;
|
|
5
5
|
xProp?: string;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script lang="ts" generics="TData = Record<string, unknown>">
|
|
2
2
|
import { Text } from 'svelteplot';
|
|
3
|
-
import type { MarkerProps } from '
|
|
4
|
-
import type { AxisValue } from '
|
|
5
|
-
import type { FontStyle } from '
|
|
3
|
+
import type { MarkerProps } from '../types/markers/props';
|
|
4
|
+
import type { AxisValue } from '../types/plots/axis';
|
|
5
|
+
import type { FontStyle } from '../types/plots/styling';
|
|
6
6
|
|
|
7
7
|
interface Props extends MarkerProps<TData> {
|
|
8
8
|
x?: AxisValue | ((d: TData) => AxisValue);
|
|
@@ -28,7 +28,10 @@
|
|
|
28
28
|
const fontSize = $derived(style?.fontSize ?? 12);
|
|
29
29
|
const fontWeight = $derived(style?.fontWeight ?? 'normal');
|
|
30
30
|
const fontStyleProp = $derived(style?.fontStyle ?? 'normal');
|
|
31
|
-
|
|
31
|
+
// 'outside' is meant to be resolved per-point by the caller (see
|
|
32
|
+
// HoverMarker, which knows each point's signed x); a caller that passes it
|
|
33
|
+
// through unresolved falls back to 'start' rather than an invalid svelteplot value.
|
|
34
|
+
const textAnchor = $derived(style?.textAnchor === 'outside' ? 'start' : (style?.textAnchor ?? 'middle'));
|
|
32
35
|
const lineAnchor = $derived(style?.lineAnchor ?? 'middle');
|
|
33
36
|
const dx = $derived(style?.dx ?? 0);
|
|
34
37
|
const dy = $derived(style?.dy ?? 0);
|
|
@@ -46,10 +49,14 @@
|
|
|
46
49
|
fontStyle={fontStyleProp}
|
|
47
50
|
{textAnchor}
|
|
48
51
|
{lineAnchor}
|
|
52
|
+
lineHeight={style?.lineHeight}
|
|
53
|
+
rotate={style?.rotate}
|
|
49
54
|
stroke={style?.stroke}
|
|
50
55
|
strokeWidth={style?.strokeWidth}
|
|
51
56
|
paintOrder={style?.paintOrder}
|
|
52
57
|
{dx}
|
|
53
58
|
{dy}
|
|
59
|
+
class={style?.class}
|
|
60
|
+
textClass={style?.textClass}
|
|
54
61
|
/>
|
|
55
62
|
{/if}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { MarkerProps } from '
|
|
2
|
-
import type { AxisValue } from '
|
|
3
|
-
import type { FontStyle } from '
|
|
1
|
+
import type { MarkerProps } from '../types/markers/props';
|
|
2
|
+
import type { AxisValue } from '../types/plots/axis';
|
|
3
|
+
import type { FontStyle } from '../types/plots/styling';
|
|
4
4
|
declare function $$render<TData = Record<string, unknown>>(): {
|
|
5
5
|
props: MarkerProps<TData> & {
|
|
6
6
|
x?: AxisValue | ((d: TData) => AxisValue);
|