@fundar/data-chart-telling 0.0.24 → 0.0.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/charts/bar/Chart.svelte +2 -0
- package/dist/charts/heatmap/Chart.svelte +3 -1
- package/dist/charts/heatmap/Chart.svelte.d.ts +1 -2
- package/dist/charts/line/Chart.svelte +2 -0
- package/dist/charts/pyramid/Chart.svelte +3 -1
- package/dist/charts/pyramid/Chart.svelte.d.ts +1 -2
- package/dist/charts/scatter/Chart.svelte +95 -0
- package/dist/charts/scatter/Chart.svelte.d.ts +28 -0
- package/dist/configuration/config.svelte.js +13 -1
- package/dist/configuration/themes/index.d.ts +76 -0
- package/dist/index.d.ts +20 -14
- package/dist/index.js +9 -3
- package/dist/layout/coordinates/CoordinatesLayout.svelte +95 -0
- package/dist/layout/{plot/RuleLayout.svelte.d.ts → coordinates/CoordinatesLayout.svelte.d.ts} +13 -16
- package/dist/layout/coordinates/margins.d.ts +16 -0
- package/dist/layout/coordinates/margins.js +11 -0
- package/dist/{plots/geo → layout/coordinates}/projections/argentina.d.ts +1 -1
- package/dist/layout/{geo → coordinates}/resolveProjection.d.ts +1 -1
- package/dist/layout/coordinates/resolveProjection.js +24 -0
- package/dist/{plots/geo → layout/coordinates}/zoom.svelte.d.ts +1 -1
- package/dist/layout/geometry/GeometryLayout.svelte +231 -0
- package/dist/layout/geometry/GeometryLayout.svelte.d.ts +62 -0
- package/dist/layout/plot/BasePlotLayout.svelte +142 -155
- package/dist/layout/plot/BasePlotLayout.svelte.d.ts +61 -51
- package/dist/layout/plot/margins.d.ts +0 -16
- package/dist/layout/plot/margins.js +0 -11
- package/dist/layout/{plot/AxisLayout.svelte → scales/ScalesLayout.svelte} +23 -16
- package/dist/layout/{plot/AxisLayout.svelte.d.ts → scales/ScalesLayout.svelte.d.ts} +4 -5
- package/dist/layout/scales/buildScale.d.ts +8 -0
- package/dist/layout/scales/buildScale.js +43 -0
- package/dist/layout/styles/StylesLayout.svelte +75 -0
- package/dist/layout/styles/StylesLayout.svelte.d.ts +15 -0
- package/dist/{plots/geo → layout/styles}/TileLayer.svelte +2 -2
- package/dist/{plots/geo → layout/styles}/TileLayer.svelte.d.ts +1 -1
- package/dist/layout/tooltip/Tooltip.svelte +16 -20
- package/dist/layout/tooltip/Tooltip.svelte.d.ts +5 -0
- package/dist/layout/tooltip/TooltipLayout.svelte +7 -1
- package/dist/layout/tooltip/TooltipLayout.svelte.d.ts +4 -0
- package/dist/layout/tooltip/controller.svelte.d.ts +4 -5
- package/dist/layout/tooltip/controller.svelte.js +28 -16
- package/dist/layout/tooltip/resolveTooltipPlacement.d.ts +24 -0
- package/dist/layout/tooltip/resolveTooltipPlacement.js +49 -0
- package/dist/layout/tooltip/utils.d.ts +27 -19
- package/dist/layout/tooltip/utils.js +16 -15
- package/dist/markers/BarMarker.svelte +92 -0
- package/dist/markers/BarMarker.svelte.d.ts +7 -0
- package/dist/markers/CellMarker.svelte +21 -0
- package/dist/markers/CellMarker.svelte.d.ts +7 -0
- package/dist/markers/ContourMarker.svelte +28 -0
- package/dist/markers/ContourMarker.svelte.d.ts +7 -0
- package/dist/markers/DeltaMarker.svelte +32 -39
- package/dist/markers/DeltaMarker.svelte.d.ts +4 -5
- package/dist/markers/DotMarker.svelte +35 -6
- package/dist/markers/DotMarker.svelte.d.ts +11 -2
- package/dist/markers/GeoFeaturesMarker.svelte +19 -0
- package/dist/markers/GeoFeaturesMarker.svelte.d.ts +7 -0
- package/dist/markers/GeoHoverMarker.svelte +25 -0
- package/dist/markers/GeoHoverMarker.svelte.d.ts +9 -0
- package/dist/markers/GraticuleMarker.svelte +18 -0
- package/dist/markers/GraticuleMarker.svelte.d.ts +7 -0
- package/dist/markers/HoverMarker.svelte +32 -33
- package/dist/markers/HoverMarker.svelte.d.ts +15 -9
- package/dist/markers/LineMarker.svelte +19 -0
- package/dist/markers/LineMarker.svelte.d.ts +7 -0
- package/dist/markers/LinkMarker.svelte +42 -0
- package/dist/markers/LinkMarker.svelte.d.ts +7 -0
- package/dist/markers/RuleMarker.svelte +24 -0
- package/dist/markers/RuleMarker.svelte.d.ts +10 -0
- package/dist/markers/SphereMarker.svelte +15 -0
- package/dist/markers/SphereMarker.svelte.d.ts +7 -0
- package/dist/markers/TextMarker.svelte +1 -1
- package/dist/markers/TextMarker.svelte.d.ts +1 -1
- package/dist/markers/VectorMarker.svelte +20 -0
- package/dist/markers/VectorMarker.svelte.d.ts +7 -0
- package/dist/markers/inset/InsetMarker.svelte +38 -45
- package/dist/markers/inset/InsetMarker.svelte.d.ts +6 -2
- package/dist/plots/bar/Plot.svelte +54 -84
- package/dist/plots/bar/Plot.svelte.d.ts +4 -5
- package/dist/plots/bar/ValueLabels.svelte +1 -1
- package/dist/plots/bar/ValueLabels.svelte.d.ts +1 -1
- package/dist/plots/bar/buildBarMarkers.d.ts +30 -0
- package/dist/plots/bar/buildBarMarkers.js +100 -0
- package/dist/plots/bar/layout.svelte.d.ts +1 -2
- package/dist/plots/bar/layout.svelte.js +1 -1
- package/dist/plots/geo/Plot.svelte +113 -387
- package/dist/plots/geo/Plot.svelte.d.ts +5 -4
- package/dist/plots/geo/buildGeoMarkers.d.ts +33 -0
- package/dist/plots/geo/buildGeoMarkers.js +47 -0
- package/dist/plots/heatmap/Plot.svelte +24 -49
- package/dist/plots/heatmap/Plot.svelte.d.ts +4 -5
- package/dist/plots/heatmap/ValueLabels.svelte +2 -2
- package/dist/plots/heatmap/ValueLabels.svelte.d.ts +2 -2
- package/dist/plots/heatmap/buildCellMarkers.d.ts +21 -0
- package/dist/plots/heatmap/buildCellMarkers.js +25 -0
- package/dist/plots/line/Plot.svelte +68 -141
- package/dist/plots/line/Plot.svelte.d.ts +4 -4
- package/dist/plots/line/ValueLabels.svelte +94 -49
- package/dist/plots/line/ValueLabels.svelte.d.ts +6 -1
- package/dist/plots/line/buildLineMarkers.d.ts +15 -0
- package/dist/plots/line/buildLineMarkers.js +57 -0
- package/dist/plots/pyramid/Plot.svelte +41 -117
- package/dist/plots/pyramid/Plot.svelte.d.ts +4 -5
- package/dist/plots/pyramid/ValueLabels.svelte +1 -1
- package/dist/plots/pyramid/ValueLabels.svelte.d.ts +1 -1
- package/dist/plots/pyramid/buildPyramidBarMarkers.d.ts +19 -0
- package/dist/plots/pyramid/buildPyramidBarMarkers.js +32 -0
- package/dist/plots/scatter/Plot.svelte +206 -0
- package/dist/plots/{bar/BarSegments.svelte.d.ts → scatter/Plot.svelte.d.ts} +9 -20
- package/dist/plots/scatter/ValueLabels.svelte +106 -0
- package/dist/{layout/plot/GridLayout.svelte.d.ts → plots/scatter/ValueLabels.svelte.d.ts} +11 -5
- package/dist/plots/scatter/buildScatterMarkers.d.ts +11 -0
- package/dist/plots/scatter/buildScatterMarkers.js +37 -0
- package/dist/plots/scatter/resolveRadiusPaddedDomain.d.ts +10 -0
- package/dist/plots/scatter/resolveRadiusPaddedDomain.js +23 -0
- package/dist/plots/utils/declutter.d.ts +82 -33
- package/dist/plots/utils/declutter.js +182 -40
- package/dist/plots/utils/geoAccessors.d.ts +1 -1
- package/dist/plots/utils/geoAccessors.js +1 -1
- package/dist/plots/utils/segments.d.ts +17 -10
- package/dist/plots/utils/segments.js +26 -16
- package/dist/types/charts/common.d.ts +1 -1
- package/dist/types/charts/props.d.ts +5 -6
- package/dist/types/configuration/styling.d.ts +24 -2
- package/dist/types/{plots/scales/geo.d.ts → layout/coordinates.d.ts} +33 -1
- package/dist/types/layout/geometry.d.ts +17 -0
- package/dist/types/{plots/axis.d.ts → layout/scales.d.ts} +11 -0
- package/dist/types/layout/styles.d.ts +126 -0
- package/dist/types/layout/tooltip.d.ts +20 -1
- package/dist/types/markers/all.d.ts +11 -0
- package/dist/types/markers/base.d.ts +45 -0
- package/dist/types/markers/base.js +1 -0
- package/dist/types/markers/common.d.ts +64 -16
- package/dist/types/markers/geo.d.ts +75 -100
- package/dist/types/markers/line.d.ts +34 -0
- package/dist/types/markers/line.js +1 -0
- package/dist/types/markers/props.d.ts +1 -1
- package/dist/types/plots/data/common.d.ts +1 -1
- package/dist/types/plots/data/scatter.d.ts +13 -0
- package/dist/types/plots/data/scatter.js +1 -0
- package/dist/types/plots/props.d.ts +46 -74
- package/dist/types/plots/segments/common.d.ts +6 -12
- package/dist/types/plots/segments/config.d.ts +1 -1
- package/dist/types/plots/styling.d.ts +10 -0
- package/dist/{plots/utils → utils}/delta.d.ts +2 -2
- package/dist/{plots/utils → utils}/delta.js +1 -1
- package/dist/utils/edgeAwareAnchor.d.ts +37 -0
- package/dist/utils/edgeAwareAnchor.js +65 -0
- package/dist/utils/grouping.d.ts +1 -1
- package/dist/utils/interpolate.d.ts +1 -1
- package/package.json +3 -1
- package/dist/layout/geo/GeoLayout.svelte +0 -51
- package/dist/layout/geo/GeoLayout.svelte.d.ts +0 -24
- package/dist/layout/geo/resolveProjection.js +0 -48
- package/dist/layout/plot/GridLayout.svelte +0 -30
- package/dist/layout/plot/RuleLayout.svelte +0 -111
- package/dist/plots/bar/BarSegments.svelte +0 -69
- package/dist/types/plots/delta.d.ts +0 -19
- package/dist/types/plots/styles/common.d.ts +0 -52
- package/dist/types/plots/styles/geo.d.ts +0 -42
- /package/dist/{plots/geo → layout/coordinates}/projections/argentina.js +0 -0
- /package/dist/{plots/geo → layout/coordinates}/projections/fit.d.ts +0 -0
- /package/dist/{plots/geo → layout/coordinates}/projections/fit.js +0 -0
- /package/dist/{plots/geo → layout/coordinates}/rotate.svelte.d.ts +0 -0
- /package/dist/{plots/geo → layout/coordinates}/rotate.svelte.js +0 -0
- /package/dist/{plots/geo → layout/coordinates}/zoom.svelte.js +0 -0
- /package/dist/types/{plots/axis.js → layout/coordinates.js} +0 -0
- /package/dist/types/{plots/delta.js → layout/geometry.js} +0 -0
- /package/dist/types/{plots/scales/geo.js → layout/scales.js} +0 -0
- /package/dist/types/{plots/styles/common.js → layout/styles.js} +0 -0
- /package/dist/types/{plots/styles/geo.js → markers/all.js} +0 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Accessor, SeriesProps, DataProps } from './common';
|
|
2
|
+
/**
|
|
3
|
+
* `SeriesProps`/`DataProps`, plus an optional per-row bubble radius —
|
|
4
|
+
* ScatterPlot's own data contract. A field key or accessor function is
|
|
5
|
+
* bound to svelteplot's own auto sqrt scale (mirroring how `x`/`y` are
|
|
6
|
+
* bound to their own scales), so bubble *area* — not radius — ends up
|
|
7
|
+
* proportional to the raw values with no manual scaling needed; feeding it
|
|
8
|
+
* an already-scaled value double-scales it. A literal number bypasses
|
|
9
|
+
* scaling entirely (a fixed pixel radius, same as the default dot size).
|
|
10
|
+
*/
|
|
11
|
+
export type ScatterDataProps<T extends Record<string, unknown>> = (SeriesProps<T> | DataProps<T>) & {
|
|
12
|
+
r?: Accessor<T, number> | number;
|
|
13
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,41 +1,23 @@
|
|
|
1
|
-
import type { TooltipOptions } from '../layout/tooltip';
|
|
1
|
+
import type { HoverPoint, HoverStrategy, TooltipOptions } from '../layout/tooltip';
|
|
2
2
|
import type { Segment } from './segments/config';
|
|
3
|
-
import type {
|
|
4
|
-
import type {
|
|
3
|
+
import type { AxisBasedScalesConfig } from '../layout/scales';
|
|
4
|
+
import type { GeoScalesConfig } from '../layout/coordinates';
|
|
5
5
|
/** The `styles` prop accepted by every plot kind — its own
|
|
6
|
-
* styles shape ({@link
|
|
6
|
+
* styles shape ({@link BasePlotStylesConfig}, `GeoStylesConfig`, …). */
|
|
7
7
|
export type StylesConfig<TStyles extends object> = TStyles;
|
|
8
|
-
/** The `markers` prop accepted by every plot kind — a list of that
|
|
9
|
-
* kind's own marker union ({@link Marker}, `GeoMarker`, …). */
|
|
8
|
+
/** The `markers` prop accepted by every plot kind — a list of that kind's own marker union. */
|
|
10
9
|
export type MarkersConfig<TMarker> = TMarker[];
|
|
11
10
|
/**
|
|
12
|
-
* The `segments` prop accepted by every plot kind
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* segments under `'default'` apply to every series.
|
|
17
|
-
*
|
|
18
|
-
* ```ts
|
|
19
|
-
* segments: {
|
|
20
|
-
* female: [{ style: { stroke: { stroke: 'tomato' } } }], // catch-all for female
|
|
21
|
-
* male: [{ style: { stroke: { stroke: 'steelblue' } } }], // catch-all for male
|
|
22
|
-
* default: [{ areas: [{ x: { from: 2012, to: 2014 } }], style: { dots: { dotSymbol: 'circle' } } }],
|
|
23
|
-
* }
|
|
24
|
-
* ```
|
|
25
|
-
*
|
|
26
|
-
* Within each resolved series list, catch-alls (no `areas`) are evaluated last
|
|
27
|
-
* so that area-specific segments always override them, regardless of position.
|
|
28
|
-
* Area-specific segments also inherit any style key absent from their own style
|
|
29
|
-
* by merging the catch-all as a baseline — the area's own style wins on conflict.
|
|
30
|
-
* This lets you set a series colour once in a catch-all and add per-range dots
|
|
31
|
-
* or dash patterns without repeating the colour on every area segment.
|
|
11
|
+
* The `segments` prop accepted by every plot kind — series name (or
|
|
12
|
+
* `'default'` for all series) to a list of {@link Segment}s. Within a
|
|
13
|
+
* series, catch-all segments (no `areas`) evaluate first as a baseline;
|
|
14
|
+
* area-specific segments merge on top and win on conflict.
|
|
32
15
|
*/
|
|
33
16
|
export type SegmentsConfig<TStyle> = Record<string, Segment<TStyle>[]>;
|
|
34
17
|
/**
|
|
35
|
-
* Partial margin override —
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* title, rotated ticks); a number pins it exactly.
|
|
18
|
+
* Partial margin override — unset sides fall back to the theme (itself
|
|
19
|
+
* `'auto'` by default). `'auto'` fits the side to its rendered content; a
|
|
20
|
+
* number pins it exactly.
|
|
39
21
|
*/
|
|
40
22
|
export type MarginConfig = Partial<{
|
|
41
23
|
top: number | 'auto';
|
|
@@ -44,69 +26,59 @@ export type MarginConfig = Partial<{
|
|
|
44
26
|
left: number | 'auto';
|
|
45
27
|
}>;
|
|
46
28
|
/**
|
|
47
|
-
* The `tooltip` prop a plot actually receives — the
|
|
48
|
-
*
|
|
49
|
-
* `
|
|
50
|
-
*
|
|
51
|
-
* (`''` when not faceted). Presence of this object on a plot is what turns
|
|
52
|
-
* hovering on.
|
|
29
|
+
* The `tooltip` prop a plot actually receives — the resolved form of the
|
|
30
|
+
* author-facing {@link TooltipOptions}. `format`/`sync` become required;
|
|
31
|
+
* `facetId` identifies the originating facet (`''` when not faceted).
|
|
32
|
+
* Presence of this object is what turns hovering on.
|
|
53
33
|
*/
|
|
54
34
|
export type TooltipConfig<TRow extends Record<string, unknown>> = Omit<TooltipOptions<TRow>, 'format' | 'sync'> & {
|
|
55
35
|
format: (row: TRow) => string;
|
|
56
36
|
sync: boolean;
|
|
57
37
|
facetId: string;
|
|
58
38
|
};
|
|
59
|
-
/**
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
*/
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
|
|
80
|
-
domain?: [number, number];
|
|
81
|
-
};
|
|
39
|
+
/** How a pointer event resolves to a candidate point: `'nearest'` (closest within a distance threshold) or `'contains'` (whichever candidate's own rendered shape contains the cursor). */
|
|
40
|
+
export type PointMatchingStrategy = 'nearest' | 'contains';
|
|
41
|
+
/** `BasePlotLayout`'s single `hover` prop — every plot kind's own resolved hover/tooltip wiring. */
|
|
42
|
+
export type HoverConfig<TRow extends Record<string, unknown>> = {
|
|
43
|
+
/** Whether the pointer/hover/tooltip machinery should mount at all. */
|
|
44
|
+
active: boolean;
|
|
45
|
+
/** Candidate points hover matching searches against. */
|
|
46
|
+
points: HoverPoint<TRow>[];
|
|
47
|
+
/** Short label drawn next to the highlight dot (e.g. the value). */
|
|
48
|
+
label: (row: TRow) => string;
|
|
49
|
+
/** Resolved hover strategy for the *local* hover store (ignored once a shared store is in scope). */
|
|
50
|
+
strategy?: HoverStrategy;
|
|
51
|
+
/** Resolved sync flag for the *local* hover store (ignored once a shared store is in scope). */
|
|
52
|
+
sync?: boolean;
|
|
53
|
+
tooltip?: TooltipConfig<TRow>;
|
|
54
|
+
/** When it returns `true`, that pointer event is treated as a leave instead of a move — lets a nested layout opt part of the plot out of hover matching. */
|
|
55
|
+
exclude?: (e: PointerEvent) => boolean;
|
|
56
|
+
/** How to resolve a pointer event to a candidate point — see {@link PointMatchingStrategy}. Defaults to `'nearest'`. */
|
|
57
|
+
pointMatching?: PointMatchingStrategy;
|
|
58
|
+
/** Forces the crosshair rule(s) a `hover` marker draws off entirely, overriding whatever `strategy` implies. */
|
|
59
|
+
crosshair?: boolean;
|
|
82
60
|
};
|
|
83
61
|
/**
|
|
84
62
|
* The `scales` prop accepted by every plot kind — either flavor of scale
|
|
85
|
-
* config a plot kind can have
|
|
86
|
-
*
|
|
87
|
-
* `Plot.svelte` narrows `BasePlotProps`'s `TScales` to exactly the one
|
|
88
|
-
* that applies to it, rather than accepting this whole union.
|
|
63
|
+
* config a plot kind can have. Each concrete `Plot.svelte` narrows
|
|
64
|
+
* `BasePlotProps`'s `TScales` to exactly the one that applies to it.
|
|
89
65
|
*/
|
|
90
66
|
export type ScalesConfig<TData = Record<string, unknown>> = AxisBasedScalesConfig<TData> | GeoScalesConfig;
|
|
91
67
|
/**
|
|
92
|
-
* The shared
|
|
93
|
-
* everything that varies by plot kind: `TDataContract` is
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
* own segment/style/marker/scale shapes. Each `Plot.svelte` instantiates
|
|
98
|
-
* this directly with its own concrete arguments rather than going through a
|
|
99
|
-
* shared per-kind alias — segments/styles/markers already diverge in shape
|
|
100
|
-
* across kinds today (or will soon), so a shared alias would just be an
|
|
101
|
-
* extra layer to keep in sync.
|
|
68
|
+
* The shared prop bag every plot component accepts, parameterized over
|
|
69
|
+
* everything that varies by plot kind: `TDataContract` is its own data
|
|
70
|
+
* shape, `TRow` is what `tooltip` resolves against, and the rest are its
|
|
71
|
+
* own segment/style/marker/scale/coordinate-system shapes. `TCoordinates`
|
|
72
|
+
* defaults to `undefined` — only `GeoPlot` instantiates it.
|
|
102
73
|
*/
|
|
103
|
-
export type BasePlotProps<TDataContract, TRow extends Record<string, unknown>, TStyles extends object, TSegmentStyle extends object, TMarker, TScales extends ScalesConfig<TRow
|
|
74
|
+
export type BasePlotProps<TDataContract, TRow extends Record<string, unknown>, TStyles extends object, TSegmentStyle extends object, TMarker, TScales extends ScalesConfig<TRow>, TCoordinates = undefined> = TDataContract & {
|
|
104
75
|
width: number;
|
|
105
76
|
height: number;
|
|
106
77
|
styles?: StylesConfig<TStyles>;
|
|
107
78
|
segments?: SegmentsConfig<TSegmentStyle>;
|
|
108
79
|
markers?: MarkersConfig<TMarker>;
|
|
109
80
|
scales?: TScales;
|
|
81
|
+
coordinates?: TCoordinates;
|
|
110
82
|
margins?: MarginConfig;
|
|
111
83
|
tooltip?: TooltipConfig<TRow>;
|
|
112
84
|
};
|
|
@@ -1,21 +1,15 @@
|
|
|
1
|
-
import type { StrokeStyle, DotStyle } from '../styling';
|
|
1
|
+
import type { StrokeStyle, DotStyle, AreaStyle } from '../styling';
|
|
2
2
|
/** Per-segment styling for a line: its stroke and/or its endpoint dots. */
|
|
3
3
|
export type LineSegmentStyle = {
|
|
4
4
|
stroke?: StrokeStyle;
|
|
5
5
|
dots?: DotStyle;
|
|
6
6
|
};
|
|
7
|
-
/** Per-segment styling for a bar-shaped mark
|
|
8
|
-
export type BarSegmentStyle =
|
|
9
|
-
fill?: string;
|
|
10
|
-
fillOpacity?: number;
|
|
11
|
-
};
|
|
7
|
+
/** Per-segment styling for a bar-shaped mark. Shared by `BarPlot` and `PyramidPlot`. */
|
|
8
|
+
export type BarSegmentStyle = AreaStyle;
|
|
12
9
|
/** Per-cell styling override for a heatmap cell. */
|
|
13
|
-
export type CellSegmentStyle =
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
stroke?: string;
|
|
17
|
-
strokeWidth?: number;
|
|
18
|
-
};
|
|
10
|
+
export type CellSegmentStyle = AreaStyle;
|
|
11
|
+
/** Per-segment styling for a scatter point cloud. */
|
|
12
|
+
export type ScatterSegmentStyle = DotStyle;
|
|
19
13
|
/** Per-feature styling override for `GeoPlot` — the geo analog of `CellSegmentStyle`. */
|
|
20
14
|
export type GeoSegmentStyle = {
|
|
21
15
|
fill?: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AxisValue } from '
|
|
1
|
+
import type { AxisValue } from '../../layout/scales';
|
|
2
2
|
import type { Series } from '../data/common';
|
|
3
3
|
import type { LineSegmentStyle } from './common';
|
|
4
4
|
/** A half-open interval on one axis. Both bounds are inclusive; omit either to leave that end open. */
|
|
@@ -43,3 +43,13 @@ export type DotStyle = {
|
|
|
43
43
|
dotStrokeOpacity?: number;
|
|
44
44
|
dotStrokeDasharray?: string | LineStyle;
|
|
45
45
|
};
|
|
46
|
+
/** Styling for a 2D area mark — a bar segment, a heatmap cell, a geo feature highlight. */
|
|
47
|
+
export type AreaStyle = {
|
|
48
|
+
fill?: string;
|
|
49
|
+
fillOpacity?: number;
|
|
50
|
+
stroke?: string;
|
|
51
|
+
strokeWidth?: number;
|
|
52
|
+
strokeOpacity?: number;
|
|
53
|
+
strokeDasharray?: string | LineStyle;
|
|
54
|
+
borderRadius?: number;
|
|
55
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Series } from '
|
|
2
|
-
import type { DeltaConfig } from '
|
|
1
|
+
import type { Series } from '../types/plots/data/common';
|
|
2
|
+
import type { DeltaConfig } from '../types/markers/line';
|
|
3
3
|
export type ResolvedDelta = {
|
|
4
4
|
cfg: DeltaConfig;
|
|
5
5
|
at: number;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { resolveAccessor } from '
|
|
1
|
+
import { resolveAccessor } from '../plots/utils/accessors';
|
|
2
2
|
/**
|
|
3
3
|
* Sorts `data` by `sortBy`, then finds the first adjacent pair where `scanBy`
|
|
4
4
|
* brackets `target` and linearly interpolates `measureBy` at that crossing.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export type HorizontalAnchor = 'start' | 'middle' | 'end';
|
|
2
|
+
export type VerticalAnchor = 'top' | 'middle' | 'bottom';
|
|
3
|
+
/** Rough estimate of rendered text width in pixels — character count × font size, not a real DOM measurement. Shared so a pre-render space reservation (e.g. domain padding) and this file's own overflow check agree on the same number. */
|
|
4
|
+
export declare function estimateTextWidth(text: string, fontSize: number): number;
|
|
5
|
+
export type AnchorPlacement = {
|
|
6
|
+
textAnchor: HorizontalAnchor;
|
|
7
|
+
lineAnchor: VerticalAnchor;
|
|
8
|
+
dx: number;
|
|
9
|
+
dy: number;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Flips (or nudges) a label's anchor/offset when its default placement
|
|
13
|
+
* would push it past a pixel box — e.g. the plot's own inner content box.
|
|
14
|
+
* `extent` estimates the rendered label size (character count × font size,
|
|
15
|
+
* not a real DOM measurement) deliberately: measuring via `getBBox()` and
|
|
16
|
+
* feeding the result back into anything reactive to the plot's own layout
|
|
17
|
+
* (like svelteplot's shared margin-auto-sizing context) risks a feedback
|
|
18
|
+
* loop between this component's own effect and svelteplot's — this stays
|
|
19
|
+
* self-contained and read-only against the live scale instead.
|
|
20
|
+
*/
|
|
21
|
+
export declare function resolveEdgeAwareAnchor(args: {
|
|
22
|
+
/** Pixel position of the anchored point. */
|
|
23
|
+
px: number;
|
|
24
|
+
py: number;
|
|
25
|
+
/** Size of the box the label must stay within — typically the plot's own inner content box. */
|
|
26
|
+
width: number;
|
|
27
|
+
height: number;
|
|
28
|
+
textAnchor: HorizontalAnchor;
|
|
29
|
+
lineAnchor: VerticalAnchor;
|
|
30
|
+
/** Desired distance from the point, in pixels — sign is resolved from the (possibly flipped) anchor. */
|
|
31
|
+
gapX: number;
|
|
32
|
+
gapY: number;
|
|
33
|
+
extent: {
|
|
34
|
+
width: number;
|
|
35
|
+
height: number;
|
|
36
|
+
};
|
|
37
|
+
}): AnchorPlacement;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/** Rough estimate of rendered text width in pixels — character count × font size, not a real DOM measurement. Shared so a pre-render space reservation (e.g. domain padding) and this file's own overflow check agree on the same number. */
|
|
2
|
+
export function estimateTextWidth(text, fontSize) {
|
|
3
|
+
return text.length * fontSize * 0.62;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Flips (or nudges) a label's anchor/offset when its default placement
|
|
7
|
+
* would push it past a pixel box — e.g. the plot's own inner content box.
|
|
8
|
+
* `extent` estimates the rendered label size (character count × font size,
|
|
9
|
+
* not a real DOM measurement) deliberately: measuring via `getBBox()` and
|
|
10
|
+
* feeding the result back into anything reactive to the plot's own layout
|
|
11
|
+
* (like svelteplot's shared margin-auto-sizing context) risks a feedback
|
|
12
|
+
* loop between this component's own effect and svelteplot's — this stays
|
|
13
|
+
* self-contained and read-only against the live scale instead.
|
|
14
|
+
*/
|
|
15
|
+
export function resolveEdgeAwareAnchor(args) {
|
|
16
|
+
const { px, py, width, height, gapX, gapY, extent } = args;
|
|
17
|
+
let { textAnchor, lineAnchor } = args;
|
|
18
|
+
let dx;
|
|
19
|
+
let dy;
|
|
20
|
+
if (textAnchor === 'start') {
|
|
21
|
+
dx = gapX;
|
|
22
|
+
if (px + dx + extent.width > width) {
|
|
23
|
+
textAnchor = 'end';
|
|
24
|
+
dx = -gapX;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
else if (textAnchor === 'end') {
|
|
28
|
+
dx = -gapX;
|
|
29
|
+
if (px + dx - extent.width < 0) {
|
|
30
|
+
textAnchor = 'start';
|
|
31
|
+
dx = gapX;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
const half = extent.width / 2;
|
|
36
|
+
dx = 0;
|
|
37
|
+
if (px - half < 0)
|
|
38
|
+
dx = half - px;
|
|
39
|
+
else if (px + half > width)
|
|
40
|
+
dx = width - (px + half);
|
|
41
|
+
}
|
|
42
|
+
if (lineAnchor === 'top') {
|
|
43
|
+
dy = gapY;
|
|
44
|
+
if (py + dy + extent.height > height) {
|
|
45
|
+
lineAnchor = 'bottom';
|
|
46
|
+
dy = -gapY;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
else if (lineAnchor === 'bottom') {
|
|
50
|
+
dy = -gapY;
|
|
51
|
+
if (py + dy - extent.height < 0) {
|
|
52
|
+
lineAnchor = 'top';
|
|
53
|
+
dy = gapY;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
const half = extent.height / 2;
|
|
58
|
+
dy = 0;
|
|
59
|
+
if (py - half < 0)
|
|
60
|
+
dy = half - py;
|
|
61
|
+
else if (py + half > height)
|
|
62
|
+
dy = height - (py + half);
|
|
63
|
+
}
|
|
64
|
+
return { textAnchor, lineAnchor, dx, dy };
|
|
65
|
+
}
|
package/dist/utils/grouping.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { EasingName, EasingFn } from '../types/charts/interpolate';
|
|
2
2
|
import type { TimeValue, TimelineInterpolation } from '../types/charts/common';
|
|
3
|
-
import type { AxisValue } from '../types/
|
|
3
|
+
import type { AxisValue } from '../types/layout/scales';
|
|
4
4
|
import type { Accessor } from '../types/plots/data/common';
|
|
5
5
|
export declare function resolveEasing(easing?: EasingName | EasingFn): EasingFn;
|
|
6
6
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fundar/data-chart-telling",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.26",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist"
|
|
@@ -58,6 +58,7 @@
|
|
|
58
58
|
"eslint-plugin-storybook": "^10.4.1",
|
|
59
59
|
"eslint-plugin-svelte": "^3.17.0",
|
|
60
60
|
"globals": "^17.4.0",
|
|
61
|
+
"knip": "^6.32.1",
|
|
61
62
|
"playwright": "^1.60.0",
|
|
62
63
|
"prettier": "^3.8.1",
|
|
63
64
|
"prettier-plugin-svelte": "^3.5.1",
|
|
@@ -80,6 +81,7 @@
|
|
|
80
81
|
"build": "svelte-package",
|
|
81
82
|
"check": "svelte-check --tsconfig ./tsconfig.json",
|
|
82
83
|
"check:watch": "svelte-check --tsconfig ./tsconfig.json --watch",
|
|
84
|
+
"check:unused-types": "knip --include types",
|
|
83
85
|
"lint": "prettier --check . && eslint .",
|
|
84
86
|
"format": "prettier --write .",
|
|
85
87
|
"test": "vitest run --project=unit --project=browser",
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { Snippet } from 'svelte';
|
|
3
|
-
import TileLayer from '../../plots/geo/TileLayer.svelte';
|
|
4
|
-
import type { GeoTileLayerConfig } from '../../types/plots/styles/geo';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Geo-only chrome nested inside `BasePlotLayout` (the `GeoPlot` analog of
|
|
8
|
-
* `AxisLayout`/`GridLayout`/`RuleLayout`) — just the pan/zoom transform
|
|
9
|
-
* group and the raster tile layer underneath the map's own marks.
|
|
10
|
-
* Everything else GeoPlot used to duplicate from `BasePlotLayout` (the hover
|
|
11
|
-
* state machine, `<Plot>` itself, `<Pointer>`, the tooltip) now lives
|
|
12
|
-
* exclusively in `BasePlotLayout`; the zoom/rotate *gesture* state itself lives
|
|
13
|
-
* in `GeoPlot`'s own `Plot.svelte` (it also feeds the projection's
|
|
14
|
-
* `rotate`, which has to reach `BasePlotLayout`'s `<Plot projection>` prop —
|
|
15
|
-
* something a component nested *inside* that same `<Plot>` has no way to
|
|
16
|
-
* reach back out to), and is only handed down here as an already-resolved
|
|
17
|
-
* `zoomTransform` to apply.
|
|
18
|
-
*/
|
|
19
|
-
let {
|
|
20
|
-
width,
|
|
21
|
-
height,
|
|
22
|
-
numericMargins,
|
|
23
|
-
zoomTransform,
|
|
24
|
-
tileLayer,
|
|
25
|
-
dataLonLatBounds,
|
|
26
|
-
children,
|
|
27
|
-
}: {
|
|
28
|
-
width: number;
|
|
29
|
-
height: number;
|
|
30
|
-
numericMargins: { top: number; right: number; bottom: number; left: number };
|
|
31
|
-
zoomTransform: { x: number; y: number; k: number };
|
|
32
|
-
tileLayer?: GeoTileLayerConfig;
|
|
33
|
-
/** Forwarded to `TileLayer` — see `Plot.svelte`'s `dataLonLatBounds`. */
|
|
34
|
-
dataLonLatBounds?: [number, number, number, number] | null;
|
|
35
|
-
children: Snippet;
|
|
36
|
-
} = $props();
|
|
37
|
-
</script>
|
|
38
|
-
|
|
39
|
-
<g transform="translate({zoomTransform.x}, {zoomTransform.y}) scale({zoomTransform.k})">
|
|
40
|
-
{#if tileLayer}
|
|
41
|
-
<TileLayer
|
|
42
|
-
config={tileLayer}
|
|
43
|
-
left={numericMargins.left}
|
|
44
|
-
top={numericMargins.top}
|
|
45
|
-
width={Math.max(0, width - numericMargins.left - numericMargins.right)}
|
|
46
|
-
height={Math.max(0, height - numericMargins.top - numericMargins.bottom)}
|
|
47
|
-
{dataLonLatBounds}
|
|
48
|
-
/>
|
|
49
|
-
{/if}
|
|
50
|
-
{@render children()}
|
|
51
|
-
</g>
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import type { Snippet } from 'svelte';
|
|
2
|
-
import type { GeoTileLayerConfig } from '../../types/plots/styles/geo';
|
|
3
|
-
type $$ComponentProps = {
|
|
4
|
-
width: number;
|
|
5
|
-
height: number;
|
|
6
|
-
numericMargins: {
|
|
7
|
-
top: number;
|
|
8
|
-
right: number;
|
|
9
|
-
bottom: number;
|
|
10
|
-
left: number;
|
|
11
|
-
};
|
|
12
|
-
zoomTransform: {
|
|
13
|
-
x: number;
|
|
14
|
-
y: number;
|
|
15
|
-
k: number;
|
|
16
|
-
};
|
|
17
|
-
tileLayer?: GeoTileLayerConfig;
|
|
18
|
-
/** Forwarded to `TileLayer` — see `Plot.svelte`'s `dataLonLatBounds`. */
|
|
19
|
-
dataLonLatBounds?: [number, number, number, number] | null;
|
|
20
|
-
children: Snippet;
|
|
21
|
-
};
|
|
22
|
-
declare const GeoLayout: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
23
|
-
type GeoLayout = ReturnType<typeof GeoLayout>;
|
|
24
|
-
export default GeoLayout;
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `data` (see `resolveProjection`) is one row per disjoint geometry *part*
|
|
3
|
-
* (see `Plot.svelte`'s `hoverCandidates` — needed so hover-matching finds
|
|
4
|
-
* every part of a multi-part feature, not just whichever one its combined
|
|
5
|
-
* centroid happens to land near), not one row per feature. Several rows
|
|
6
|
-
* therefore share the exact same `geometry` object by reference — spread
|
|
7
|
-
* from the same tagged feature, only `__cx`/`__cy` differ. Deduping by that
|
|
8
|
-
* reference before handing rows to d3-geo's bounds/fit computation matters:
|
|
9
|
-
* a feature with many parts (e.g. a province whose `MultiPolygon` has
|
|
10
|
-
* hundreds of small islands) would otherwise have its *entire* geometry
|
|
11
|
-
* re-traversed once per part it contributed, an accidental O(parts²) cost
|
|
12
|
-
* that got severe enough to be visible (multi-second) on real IGN data.
|
|
13
|
-
*/
|
|
14
|
-
function dedupeByGeometry(data) {
|
|
15
|
-
const seen = new Set();
|
|
16
|
-
const result = [];
|
|
17
|
-
for (const row of data) {
|
|
18
|
-
if (seen.has(row.geometry))
|
|
19
|
-
continue;
|
|
20
|
-
seen.add(row.geometry);
|
|
21
|
-
result.push(row);
|
|
22
|
-
}
|
|
23
|
-
return result;
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Resolves a `GeoScalesConfig['projection']` into what svelteplot's own
|
|
27
|
-
* `<Plot projection>` expects — kept separate from `GeoPlot`'s own
|
|
28
|
-
* `Plot.svelte` so adding more projection-level behavior (like the
|
|
29
|
-
* `domain: 'data'` sentinel below) doesn't grow that component itself.
|
|
30
|
-
*/
|
|
31
|
-
export function resolveProjection(projection, data) {
|
|
32
|
-
if (!projection)
|
|
33
|
-
return 'equal-earth';
|
|
34
|
-
if (typeof projection === 'string')
|
|
35
|
-
return projection;
|
|
36
|
-
const domain = projection.domain === 'data'
|
|
37
|
-
? { type: 'FeatureCollection', features: dedupeByGeometry(data) }
|
|
38
|
-
: projection.domain;
|
|
39
|
-
return {
|
|
40
|
-
type: projection.type,
|
|
41
|
-
rotate: projection.rotate,
|
|
42
|
-
center: projection.center,
|
|
43
|
-
parallels: projection.parallels,
|
|
44
|
-
inset: projection.inset,
|
|
45
|
-
clip: projection.clip,
|
|
46
|
-
domain,
|
|
47
|
-
};
|
|
48
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
<script lang="ts" generics="TData extends Record<string, unknown>">
|
|
2
|
-
import { GridX, GridY } from 'svelteplot';
|
|
3
|
-
import type { AxisBasedScalesConfig } from '../../types/plots/props';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Grid lines for the plot kinds that have an x/y axis pair — opt-in via
|
|
7
|
-
* `scales.x.grid`/`scales.y.grid` (svelteplot's own implicit grid is a
|
|
8
|
-
* fixed, unstyled default, so this is drawn instead of that, not on top of
|
|
9
|
-
* it — see `BasePlotLayout`'s `finalizeScale`, which strips `grid` from what
|
|
10
|
-
* actually reaches `<Plot x y>`).
|
|
11
|
-
*/
|
|
12
|
-
let { scales }: { scales?: AxisBasedScalesConfig<TData> } = $props();
|
|
13
|
-
</script>
|
|
14
|
-
|
|
15
|
-
{#if scales?.x?.grid}
|
|
16
|
-
<GridX
|
|
17
|
-
stroke={typeof scales.x.grid === 'object' ? scales.x.grid.stroke : undefined}
|
|
18
|
-
strokeWidth={typeof scales.x.grid === 'object' ? scales.x.grid.strokeWidth : undefined}
|
|
19
|
-
strokeOpacity={typeof scales.x.grid === 'object' ? scales.x.grid.strokeOpacity : undefined}
|
|
20
|
-
strokeDasharray={typeof scales.x.grid === 'object' ? scales.x.grid.strokeDasharray : undefined}
|
|
21
|
-
/>
|
|
22
|
-
{/if}
|
|
23
|
-
{#if scales?.y?.grid}
|
|
24
|
-
<GridY
|
|
25
|
-
stroke={typeof scales.y.grid === 'object' ? scales.y.grid.stroke : undefined}
|
|
26
|
-
strokeWidth={typeof scales.y.grid === 'object' ? scales.y.grid.strokeWidth : undefined}
|
|
27
|
-
strokeOpacity={typeof scales.y.grid === 'object' ? scales.y.grid.strokeOpacity : undefined}
|
|
28
|
-
strokeDasharray={typeof scales.y.grid === 'object' ? scales.y.grid.strokeDasharray : undefined}
|
|
29
|
-
/>
|
|
30
|
-
{/if}
|