@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
|
@@ -1,54 +1,42 @@
|
|
|
1
1
|
<script lang="ts" generics="TProps extends Record<string, unknown>">
|
|
2
2
|
import { SvelteMap } from 'svelte/reactivity';
|
|
3
|
-
import { Geo, Graticule, Sphere, Dot, Vector, Contour } from 'svelteplot';
|
|
4
3
|
import { resolveAccessor } from '../utils/accessors';
|
|
5
4
|
import { resolveFeatureStyle } from '../utils/geoSegments';
|
|
6
|
-
import {
|
|
7
|
-
geometryCentroid,
|
|
8
|
-
geometryLonLatBounds,
|
|
9
|
-
geometryPartCentroids,
|
|
10
|
-
filterGeometryParts,
|
|
11
|
-
defaultFeatureId,
|
|
12
|
-
greatCircleInterpolate,
|
|
13
|
-
} from '../utils/geoAccessors';
|
|
5
|
+
import { geometryCentroid, filterGeometryParts, defaultFeatureId } from '../utils/geoAccessors';
|
|
14
6
|
import { isTopology, topologyToGeoJson } from '../utils/topojson';
|
|
15
7
|
import { makeColorScale } from '../../utils/color';
|
|
16
8
|
import { getConfiguration } from '../../configuration/config.svelte';
|
|
17
9
|
import { getLegendInteraction } from '../../layout/legend/interaction.svelte';
|
|
18
10
|
import { disabledFillOverride } from '../utils/legendDisabled';
|
|
19
|
-
import { GEO_MARGIN_ESTIMATE } from '../../layout/
|
|
11
|
+
import { GEO_MARGIN_ESTIMATE } from '../../layout/coordinates/margins';
|
|
12
|
+
import { buildGeoMarkers } from './buildGeoMarkers';
|
|
13
|
+
import { hasHoverMarker } from '../../layout/tooltip/utils';
|
|
20
14
|
import BasePlotLayout from '../../layout/plot/BasePlotLayout.svelte';
|
|
21
|
-
import
|
|
22
|
-
import {
|
|
23
|
-
import HoverMarker from '../../markers/HoverMarker.svelte';
|
|
24
|
-
import { createGeoZoom } from './zoom.svelte';
|
|
25
|
-
import { createGeoRotate, type GeoRotate } from './rotate.svelte';
|
|
26
|
-
import InsetMarker from '../../markers/inset/InsetMarker.svelte';
|
|
27
|
-
import ContourClipMarker from '../../markers/ContourClipMarker.svelte';
|
|
28
|
-
import type { BasePlotProps, GeoScalesConfig } from '../../types/plots/props';
|
|
15
|
+
import type { BasePlotProps } from '../../types/plots/props';
|
|
16
|
+
import type { GeoScalesConfig, CoordinatesConfig } from '../../types/layout/coordinates';
|
|
29
17
|
import type { GeoFeature, GeoDataProps } from '../../types/plots/data/geo';
|
|
30
|
-
import type {
|
|
18
|
+
import type { GeoStylesConfig } from '../../types/layout/styles';
|
|
31
19
|
import type { GeoSegmentStyle } from '../../types/plots/segments/common';
|
|
32
|
-
import type {
|
|
20
|
+
import type { GeoMarkersConfig } from '../../types/markers/geo';
|
|
33
21
|
|
|
34
22
|
/**
|
|
35
|
-
* A map, rendered from GeoJSON
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* graticule/sphere — is a `markers` entry.
|
|
23
|
+
* A map, rendered from GeoJSON or TopoJSON. Unlike the other plot kinds
|
|
24
|
+
* there's no x/y/z axis pair: `data` IS the map. `segments` styles
|
|
25
|
+
* features by id; `value` + `scales.color`/`styles.colors` drive a
|
|
26
|
+
* continuous choropleth ramp. Everything drawn on top — points, arrows,
|
|
27
|
+
* links, contours, graticule/sphere — is a `markers` entry, assembled by
|
|
28
|
+
* `buildGeoMarkers` and routed through `GeometryLayout`.
|
|
42
29
|
*/
|
|
43
30
|
type TaggedFeature = GeoFeature<TProps> & { __id: string; __cx: number; __cy: number };
|
|
44
31
|
|
|
45
32
|
type Props = BasePlotProps<
|
|
46
33
|
GeoDataProps<TProps>,
|
|
47
34
|
GeoFeature<TProps>,
|
|
48
|
-
|
|
35
|
+
GeoStylesConfig<TProps>,
|
|
49
36
|
GeoSegmentStyle,
|
|
50
|
-
|
|
51
|
-
GeoScalesConfig
|
|
37
|
+
GeoMarkersConfig,
|
|
38
|
+
GeoScalesConfig,
|
|
39
|
+
CoordinatesConfig
|
|
52
40
|
>;
|
|
53
41
|
|
|
54
42
|
let {
|
|
@@ -63,6 +51,7 @@
|
|
|
63
51
|
segments = {},
|
|
64
52
|
markers = [],
|
|
65
53
|
scales = {},
|
|
54
|
+
coordinates = {},
|
|
66
55
|
margins,
|
|
67
56
|
tooltip = undefined,
|
|
68
57
|
}: Props = $props();
|
|
@@ -110,18 +99,12 @@
|
|
|
110
99
|
);
|
|
111
100
|
|
|
112
101
|
/**
|
|
113
|
-
* Tags each feature with a plain enumerable `__id`/`__cx`/`__cy
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
* side `Map` keyed by identity.
|
|
120
|
-
*
|
|
121
|
-
* Untouched by `excludeParts` — this is the full geometry, passed to
|
|
122
|
-
* `InsetMarker` as-is, so an inset can show a part regardless of whether
|
|
123
|
-
* `excludeParts` also hides that same part from the main map's own
|
|
124
|
-
* rendering below (see `features`).
|
|
102
|
+
* Tags each feature with a plain enumerable `__id`/`__cx`/`__cy`, so
|
|
103
|
+
* per-row metadata (feature id for style/hover lookups, centroid for
|
|
104
|
+
* positioning) lives as an own property on the object itself rather than a
|
|
105
|
+
* side lookup. Untouched by `excludeParts`: passed to `InsetMarker` as-is,
|
|
106
|
+
* so an inset can show a part the main map's own rendering (`features`,
|
|
107
|
+
* below) excludes.
|
|
125
108
|
*/
|
|
126
109
|
const allFeatures = $derived.by((): TaggedFeature[] =>
|
|
127
110
|
rawFeatures.map((f) => {
|
|
@@ -132,8 +115,9 @@
|
|
|
132
115
|
|
|
133
116
|
/**
|
|
134
117
|
* `allFeatures`, reduced per `excludeParts` — this is what actually
|
|
135
|
-
* renders (`styleGroups
|
|
136
|
-
* from. A feature reduced to no parts at all is
|
|
118
|
+
* renders (`styleGroups`/the base `'geo'` marker below) and what
|
|
119
|
+
* `hoverPoints` derives from. A feature reduced to no parts at all is
|
|
120
|
+
* dropped entirely.
|
|
137
121
|
*/
|
|
138
122
|
const features = $derived.by((): TaggedFeature[] => {
|
|
139
123
|
if (!excludeParts) return allFeatures;
|
|
@@ -148,7 +132,7 @@
|
|
|
148
132
|
// ── Tile-layer / projection compatibility ────────────────────────────────
|
|
149
133
|
$effect(() => {
|
|
150
134
|
if (!styles.tileLayer) return;
|
|
151
|
-
const proj =
|
|
135
|
+
const proj = coordinates.projection;
|
|
152
136
|
const name = typeof proj === 'string' ? proj : proj?.type;
|
|
153
137
|
if (name && name !== 'mercator' && name !== 'transverse-mercator') {
|
|
154
138
|
console.warn(
|
|
@@ -157,22 +141,28 @@
|
|
|
157
141
|
}
|
|
158
142
|
});
|
|
159
143
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
144
|
+
/**
|
|
145
|
+
* `coordinates.projection`, defaulted to `'mercator'` when unset and
|
|
146
|
+
* `styles.tileLayer` is active (the only projection family `TileLayer`
|
|
147
|
+
* renders correctly under) — folded in here, before `coordinates` reaches
|
|
148
|
+
* `BasePlotLayout`/`CoordinatesLayout`, since neither knows about
|
|
149
|
+
* `styles.tileLayer`.
|
|
150
|
+
*/
|
|
151
|
+
const resolvedCoordinates = $derived.by((): CoordinatesConfig => ({
|
|
152
|
+
...coordinates,
|
|
153
|
+
projection: coordinates.projection ?? (styles.tileLayer ? 'mercator' : undefined),
|
|
154
|
+
}));
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* `styles`, with `features` tacked onto `tileLayer` (never author-facing —
|
|
158
|
+
* `GeoTileLayerConfig` doesn't declare it) so `StylesLayout` can compute
|
|
159
|
+
* the tile layer's auto-fit bounds without raw geometry threaded through
|
|
160
|
+
* as a separate prop. `excludeParts`-reduced `features`, matching what
|
|
161
|
+
* actually renders.
|
|
162
|
+
*/
|
|
163
|
+
const resolvedStyles = $derived.by(() =>
|
|
164
|
+
styles.tileLayer ? { ...styles, tileLayer: { ...styles.tileLayer, features } } : styles,
|
|
165
|
+
);
|
|
176
166
|
|
|
177
167
|
// ── Choropleth color scale (mirrors heatmap's styles.colors/scales.z) ────
|
|
178
168
|
const minColor = $derived(styles.colors?.min ?? cfg.continuous.min);
|
|
@@ -213,23 +203,8 @@
|
|
|
213
203
|
return { ...base, ...disabledFillOverride(r.disabledStyle) };
|
|
214
204
|
}
|
|
215
205
|
|
|
216
|
-
/** Per-marker color ramp for a `dot` marker's `value` channel — independent of the base map's own choropleth ramp. */
|
|
217
|
-
function makeDotColorScale(marker: GeoDotMarker): ((v: number) => string) | null {
|
|
218
|
-
if (!marker.value) return null;
|
|
219
|
-
const getValue = resolveAccessor(marker.value);
|
|
220
|
-
const vals = marker.data.map((d) => Number(getValue(d))).filter((v) => Number.isFinite(v));
|
|
221
|
-
if (!vals.length) return null;
|
|
222
|
-
const domain: [number, number] = [Math.min(...vals), Math.max(...vals)];
|
|
223
|
-
return makeColorScale(
|
|
224
|
-
domain[0],
|
|
225
|
-
domain[1],
|
|
226
|
-
marker.style?.colors?.min ?? cfg.continuous.min,
|
|
227
|
-
marker.style?.colors?.max ?? cfg.continuous.max,
|
|
228
|
-
);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
206
|
// ── Per-feature style resolution, grouped by distinct resolved style ─────
|
|
232
|
-
// (one
|
|
207
|
+
// (one `'geo'` marker per group — mirrors heatmap's styleGroups: svelteplot's
|
|
233
208
|
// shared numeric-scale machinery collapses a per-row fillOpacity/strokeWidth
|
|
234
209
|
// *accessor* to a single value, so literal per-call constants are required.)
|
|
235
210
|
function getFeatureStyle(f: TaggedFeature): GeoSegmentStyle {
|
|
@@ -252,22 +227,10 @@
|
|
|
252
227
|
return [...groups.values()];
|
|
253
228
|
});
|
|
254
229
|
|
|
255
|
-
/**
|
|
256
|
-
* Hover/click candidates — like `features`, but one row per disjoint
|
|
257
|
-
* geometry part instead of per feature, so a multi-part feature's hover
|
|
258
|
-
* point isn't stranded somewhere between its parts (see
|
|
259
|
-
* `geometryPartCentroids`). Only used for hover matching (`BasePlotLayout`'s
|
|
260
|
-
* `data`/`hoverPoints`) — `<Geo>` itself still renders from
|
|
261
|
-
* `features`/`styleGroups`, one entry per feature, unaffected by this.
|
|
262
|
-
*/
|
|
263
|
-
const hoverCandidates = $derived.by((): TaggedFeature[] =>
|
|
264
|
-
features.flatMap((f) => geometryPartCentroids(f.geometry).map(([cx, cy]) => ({ ...f, __cx: cx, __cy: cy }))),
|
|
265
|
-
);
|
|
266
|
-
|
|
267
230
|
// A feature outside the active range is dimmed in place, but never
|
|
268
231
|
// surfaces in hover/tooltip — it's simply absent from the candidate list.
|
|
269
232
|
const hoverPoints = $derived(
|
|
270
|
-
|
|
233
|
+
features
|
|
271
234
|
.filter((f) => {
|
|
272
235
|
const r = range;
|
|
273
236
|
if (r == null || !value) return true;
|
|
@@ -280,323 +243,86 @@
|
|
|
280
243
|
const hoverGetY = (f: TaggedFeature) => f.__cy;
|
|
281
244
|
|
|
282
245
|
/**
|
|
283
|
-
* `
|
|
284
|
-
*
|
|
285
|
-
*
|
|
286
|
-
* `
|
|
287
|
-
|
|
288
|
-
function isBehindMarker(marker: GeoMarker): boolean {
|
|
289
|
-
return (
|
|
290
|
-
(marker.type === 'graticule' || marker.type === 'sphere' || marker.type === 'contour') &&
|
|
291
|
-
marker.behind === true
|
|
292
|
-
);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
const hoverMarkerConfig = $derived(markers.find((m): m is GeoHoverMarkerConfig => m.type === 'hover'));
|
|
296
|
-
|
|
297
|
-
$effect(() => {
|
|
298
|
-
if (hoverMarkerConfig?.strategy === 'nearest-point') {
|
|
299
|
-
console.warn(
|
|
300
|
-
"GeoPlot: the hover marker's strategy 'nearest-point' isn't implemented yet — falling back to 'nearest-feature'.",
|
|
301
|
-
);
|
|
302
|
-
}
|
|
303
|
-
});
|
|
304
|
-
|
|
305
|
-
const hoverActive = $derived(tooltip != null || hoverMarkerConfig != null);
|
|
306
|
-
|
|
307
|
-
// ── Projection ────────────────────────────────────────────────────────────
|
|
308
|
-
const resolvedProjection = $derived(
|
|
309
|
-
resolveProjection(scales.projection ?? (styles.tileLayer ? 'mercator' : undefined), hoverCandidates),
|
|
310
|
-
);
|
|
311
|
-
|
|
312
|
-
// ── Pan / zoom / rotate — owned here (not GeoLayout) since the resulting
|
|
313
|
-
// rotated projection must reach `BasePlotLayout`'s own `<Plot projection>`
|
|
314
|
-
// prop, and a component nested *inside* that `<Plot>` (as GeoLayout is)
|
|
315
|
-
// has no way to reach back out to a prop on its own ancestor. GeoLayout
|
|
316
|
-
// only renders the *result* (`zoomTransform`) as its `<g transform>`. ────
|
|
317
|
-
let containerEl = $state<HTMLDivElement>();
|
|
318
|
-
const zoomEnabled = $derived(styles.zoom !== false && styles.zoom != null);
|
|
319
|
-
const zoomConfig = $derived(typeof styles.zoom === 'object' ? styles.zoom : undefined);
|
|
320
|
-
|
|
321
|
-
/**
|
|
322
|
-
* Orthographic (and other azimuthal, hemisphere-style) projections don't
|
|
323
|
-
* gain anything from drag-to-*pan* — panning just slides the same globe a
|
|
324
|
-
* few pixels within the frame — so when `zoom` is enabled on one, drag
|
|
325
|
-
* instead rotates the globe (`createGeoRotate`) and wheel/pinch keeps
|
|
326
|
-
* scaling it (`createGeoZoom`, with its own drag disabled below so the two
|
|
327
|
-
* gestures don't fight over the same pointer events).
|
|
246
|
+
* `hoverPoints` keyed by feature `__id`, looked up from the exact feature
|
|
247
|
+
* the browser's own SVG hit-testing resolved a pointer event to (see the
|
|
248
|
+
* base `'geo'` marker's `onpointerenter`, built by `buildGeoMarkers`). A
|
|
249
|
+
* feature absent here was filtered out of `hoverPoints` and correctly
|
|
250
|
+
* produces no match.
|
|
328
251
|
*/
|
|
329
|
-
const
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
const baseRotate = $derived.by((): GeoRotate => {
|
|
334
|
-
const configured = typeof resolvedProjection === 'object' ? resolvedProjection?.rotate : undefined;
|
|
335
|
-
return [configured?.[0] ?? 0, configured?.[1] ?? 0, configured?.[2] ?? 0];
|
|
336
|
-
});
|
|
337
|
-
|
|
338
|
-
const geoZoom = createGeoZoom({
|
|
339
|
-
enabled: () => zoomEnabled,
|
|
340
|
-
config: () => zoomConfig,
|
|
341
|
-
node: () => containerEl ?? null,
|
|
342
|
-
disableDrag: () => rotateEnabled,
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
const geoRotate = createGeoRotate({
|
|
346
|
-
enabled: () => rotateEnabled,
|
|
347
|
-
baseRotate: () => baseRotate,
|
|
348
|
-
scale: () => geoZoom.transform.k,
|
|
349
|
-
node: () => containerEl ?? null,
|
|
252
|
+
const hoverPointById = $derived.by(() => {
|
|
253
|
+
const map = new SvelteMap<string, (typeof hoverPoints)[number]>();
|
|
254
|
+
for (const p of hoverPoints) map.set(p.row.__id, p);
|
|
255
|
+
return map;
|
|
350
256
|
});
|
|
351
257
|
|
|
352
|
-
const
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
258
|
+
const hoverActive = $derived(tooltip != null || hasHoverMarker(markers));
|
|
259
|
+
|
|
260
|
+
const hover = $derived({
|
|
261
|
+
active: hoverActive,
|
|
262
|
+
points: hoverPoints,
|
|
263
|
+
label: (f: TaggedFeature) => f.__id,
|
|
264
|
+
strategy: 'punctual' as const,
|
|
265
|
+
// A map has no axis to draw a crosshair rule against — 'punctual' here
|
|
266
|
+
// only means "exact XY hover match", unlike heatmap's own use of it.
|
|
267
|
+
crosshair: false,
|
|
268
|
+
sync: tooltip?.sync ?? false,
|
|
269
|
+
tooltip,
|
|
270
|
+
exclude: isOverInset,
|
|
271
|
+
// A feature's true visual center can sit far from where the cursor
|
|
272
|
+
// actually is on a large/irregular shape (e.g. an elongated province) —
|
|
273
|
+
// 'contains' matches the feature the cursor is really over, via the
|
|
274
|
+
// browser's own SVG hit-testing on each rendered feature path, rather
|
|
275
|
+
// than 'nearest' centroid distance.
|
|
276
|
+
pointMatching: 'contains' as const,
|
|
358
277
|
});
|
|
359
278
|
|
|
360
279
|
/**
|
|
361
|
-
*
|
|
362
|
-
*
|
|
363
|
-
*
|
|
364
|
-
*
|
|
365
|
-
*
|
|
366
|
-
*
|
|
367
|
-
* Checked via `e.target` (which `InsetMarker`'s own hit-test `<rect>`, or
|
|
368
|
-
* one of its feature `<path>`s, tags with the `dct-geo-inset` ancestor —
|
|
369
|
-
* see `InsetMarker.svelte`) rather than by comparing pixel coordinates against a
|
|
370
|
-
* precomputed inset box: svelteplot's `<Plot>` doesn't necessarily render
|
|
371
|
-
* at a 1:1 scale between its `width`/`height` props and actual client
|
|
372
|
-
* pixels (its internal `viewBox` can differ), which would silently desync
|
|
373
|
-
* any independently-computed pixel math from what's really on screen. The
|
|
374
|
-
* browser's own hit-testing has no such problem — it already resolves
|
|
375
|
-
* `e.target` against whatever is actually painted, accounting for any such
|
|
376
|
-
* scaling automatically.
|
|
280
|
+
* The main map's own hover must never fire while the cursor is over an
|
|
281
|
+
* `inset` marker's panel, which draws at its own scale/projection.
|
|
282
|
+
* Checked via `e.target` (tagged with the `dct-geo-inset` ancestor class
|
|
283
|
+
* by `InsetMarker`'s own hit-test elements) rather than precomputed pixel
|
|
284
|
+
* bounds, since the browser's own hit-testing already accounts for any
|
|
285
|
+
* scale mismatch between `<Plot>`'s props and its rendered viewBox.
|
|
377
286
|
*/
|
|
378
287
|
function isOverInset(e: PointerEvent): boolean {
|
|
379
288
|
return (e.target as Element | null)?.closest?.('.dct-geo-inset') != null;
|
|
380
289
|
}
|
|
381
290
|
</script>
|
|
382
291
|
|
|
383
|
-
{#snippet marker_(marker: GeoMarker, numericMargins: { top: number; right: number; bottom: number; left: number })}
|
|
384
|
-
{#if marker.type === 'graticule'}
|
|
385
|
-
<Graticule
|
|
386
|
-
step={marker.step}
|
|
387
|
-
stepX={marker.stepX}
|
|
388
|
-
stepY={marker.stepY}
|
|
389
|
-
stroke={marker.style?.stroke ?? 'currentColor'}
|
|
390
|
-
strokeWidth={marker.style?.strokeWidth ?? 0.5}
|
|
391
|
-
strokeOpacity={marker.style?.strokeOpacity ?? 0.3}
|
|
392
|
-
strokeDasharray={marker.style?.strokeDasharray}
|
|
393
|
-
style="vector-effect: non-scaling-stroke"
|
|
394
|
-
/>
|
|
395
|
-
{:else if marker.type === 'sphere'}
|
|
396
|
-
<Sphere
|
|
397
|
-
fill={marker.style?.fill}
|
|
398
|
-
fillOpacity={marker.style?.fillOpacity}
|
|
399
|
-
stroke={marker.style?.stroke ?? 'currentColor'}
|
|
400
|
-
strokeWidth={marker.style?.strokeWidth ?? 1}
|
|
401
|
-
style="vector-effect: non-scaling-stroke"
|
|
402
|
-
/>
|
|
403
|
-
{:else if marker.type === 'dot'}
|
|
404
|
-
{@const getDotValue = marker.value ? resolveAccessor(marker.value) : null}
|
|
405
|
-
{@const dotColorScale = getDotValue ? makeDotColorScale(marker) : null}
|
|
406
|
-
<Dot
|
|
407
|
-
data={marker.data}
|
|
408
|
-
x={marker.x}
|
|
409
|
-
y={marker.y}
|
|
410
|
-
r={marker.r ?? marker.style?.dotRadius ?? 4}
|
|
411
|
-
fill={dotColorScale && getDotValue
|
|
412
|
-
? (d: Record<string, unknown>) => dotColorScale(Number(getDotValue(d)))
|
|
413
|
-
: (marker.style?.dotFill ?? cfg.palette[0])}
|
|
414
|
-
fillOpacity={marker.style?.dotFillOpacity ?? 1}
|
|
415
|
-
stroke={marker.style?.dotStroke}
|
|
416
|
-
strokeWidth={marker.style?.dotStrokeWidth}
|
|
417
|
-
/>
|
|
418
|
-
{:else if marker.type === 'vector'}
|
|
419
|
-
<Vector
|
|
420
|
-
data={marker.data}
|
|
421
|
-
x={marker.x}
|
|
422
|
-
y={marker.y}
|
|
423
|
-
length={marker.length}
|
|
424
|
-
rotate={marker.rotate}
|
|
425
|
-
shape={marker.shape ?? 'arrow'}
|
|
426
|
-
anchor={marker.anchor}
|
|
427
|
-
fill={marker.style?.fill ?? 'currentColor'}
|
|
428
|
-
stroke={marker.style?.stroke}
|
|
429
|
-
strokeWidth={marker.style?.strokeWidth}
|
|
430
|
-
/>
|
|
431
|
-
{:else if marker.type === 'link'}
|
|
432
|
-
{@const getX1 = resolveAccessor(marker.x1)}
|
|
433
|
-
{@const getY1 = resolveAccessor(marker.y1)}
|
|
434
|
-
{@const getX2 = resolveAccessor(marker.x2)}
|
|
435
|
-
{@const getY2 = resolveAccessor(marker.y2)}
|
|
436
|
-
{@const linkFeatures = marker.data.map((d) => ({
|
|
437
|
-
type: 'Feature' as const,
|
|
438
|
-
properties: {},
|
|
439
|
-
geometry: {
|
|
440
|
-
type: 'LineString' as const,
|
|
441
|
-
coordinates:
|
|
442
|
-
marker.curve === 'linear'
|
|
443
|
-
? [
|
|
444
|
-
[Number(getX1(d)), Number(getY1(d))],
|
|
445
|
-
[Number(getX2(d)), Number(getY2(d))],
|
|
446
|
-
]
|
|
447
|
-
: greatCircleInterpolate(Number(getX1(d)), Number(getY1(d)), Number(getX2(d)), Number(getY2(d))),
|
|
448
|
-
},
|
|
449
|
-
}))}
|
|
450
|
-
<!--
|
|
451
|
-
No `fill` prop here, deliberately: svelteplot's channel resolution
|
|
452
|
-
(`toChannelOption`) treats *any* string value — including the
|
|
453
|
-
literal `'none'` this used to pass — as scale-worthy unless it
|
|
454
|
-
parses as a real CSS color, so `fill="none"` was getting run
|
|
455
|
-
through the plot's color scale and painted an arbitrary category
|
|
456
|
-
color instead of staying unfilled (confirmed by inspecting the
|
|
457
|
-
rendered DOM). Omitting the prop entirely leaves svelteplot's own
|
|
458
|
-
per-mark default in place, which is `fill: none` for an unfilled
|
|
459
|
-
channel — the outcome this mark actually wants, without the buggy
|
|
460
|
-
detour through the color scale.
|
|
461
|
-
-->
|
|
462
|
-
<Geo
|
|
463
|
-
class="link"
|
|
464
|
-
data={linkFeatures}
|
|
465
|
-
stroke={marker.style?.stroke ?? 'currentColor'}
|
|
466
|
-
strokeWidth={marker.style?.strokeWidth ?? 1}
|
|
467
|
-
strokeOpacity={marker.style?.strokeOpacity}
|
|
468
|
-
strokeDasharray={marker.style?.strokeDasharray}
|
|
469
|
-
style="vector-effect: non-scaling-stroke"
|
|
470
|
-
/>
|
|
471
|
-
{:else if marker.type === 'contour'}
|
|
472
|
-
<!--
|
|
473
|
-
`fill`/`stroke`: no `?? 'none'` fallback here, deliberately — same
|
|
474
|
-
bug as the `link` marker above. Omitting the prop when
|
|
475
|
-
`marker.fill` is unset leaves svelteplot's own per-mark default in
|
|
476
|
-
place (`fill="none"`, per Contour's own doc comment), instead of
|
|
477
|
-
running the literal string `'none'` through the plot's color scale
|
|
478
|
-
(`'none'` isn't a recognized CSS color, so svelteplot doesn't treat
|
|
479
|
-
it as a literal output value the way it does e.g. `'currentColor'`).
|
|
480
|
-
-->
|
|
481
|
-
<ContourClipMarker mode={marker.clip} {features}>
|
|
482
|
-
<Contour
|
|
483
|
-
class="contour"
|
|
484
|
-
data={marker.data}
|
|
485
|
-
x={marker.x}
|
|
486
|
-
y={marker.y}
|
|
487
|
-
value={marker.value}
|
|
488
|
-
thresholds={marker.thresholds}
|
|
489
|
-
fill={marker.fill}
|
|
490
|
-
stroke={marker.stroke ?? 'currentColor'}
|
|
491
|
-
strokeWidth={marker.style?.strokeWidth}
|
|
492
|
-
fillOpacity={marker.style?.fillOpacity}
|
|
493
|
-
strokeOpacity={marker.style?.strokeOpacity}
|
|
494
|
-
blur={marker.blur}
|
|
495
|
-
interpolate={marker.interpolate}
|
|
496
|
-
/>
|
|
497
|
-
</ContourClipMarker>
|
|
498
|
-
{:else if marker.type === 'component'}
|
|
499
|
-
<marker.component {...marker.props} data={marker.data ?? features} />
|
|
500
|
-
{:else if marker.type === 'inset'}
|
|
501
|
-
{@const insetContentBox = {
|
|
502
|
-
left: numericMargins.left,
|
|
503
|
-
top: numericMargins.top,
|
|
504
|
-
width: Math.max(0, width - numericMargins.left - numericMargins.right),
|
|
505
|
-
height: Math.max(0, height - numericMargins.top - numericMargins.bottom),
|
|
506
|
-
}}
|
|
507
|
-
<InsetMarker
|
|
508
|
-
marker={marker as GeoInsetMarker<TProps>}
|
|
509
|
-
features={allFeatures}
|
|
510
|
-
width={insetContentBox.width}
|
|
511
|
-
height={insetContentBox.height}
|
|
512
|
-
left={insetContentBox.left}
|
|
513
|
-
top={insetContentBox.top}
|
|
514
|
-
defaultFill={cfg.palette[0]}
|
|
515
|
-
/>
|
|
516
|
-
{/if}
|
|
517
|
-
{/snippet}
|
|
518
|
-
|
|
519
292
|
<!--
|
|
520
|
-
`x`/`y`: pins the plot's generic linear
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
hardcoded to read `plot.scales.x`/`y` (see `Contour.svelte`) regardless of
|
|
525
|
-
any active projection. Left unset, that scale would auto-fit to just the
|
|
526
|
-
contour data's own point extent — a different frame than the projection's
|
|
527
|
-
own (typically whole-world) fit, so the contour would sit at the wrong
|
|
528
|
-
scale/position relative to the map under it. Pinning both to the world
|
|
529
|
-
range only helps `contour` markers align (best exactly under an
|
|
530
|
-
`equirectangular` projection, whose x/y truly are linear in lon/lat) and
|
|
531
|
-
is a no-op for every other mark type.
|
|
293
|
+
`x`/`y`: pins the plot's generic linear scales to the full lon/lat range.
|
|
294
|
+
Every geo-aware mark routes through the active projection instead, except
|
|
295
|
+
svelteplot's `Contour`, whose grid reads `plot.scales.x`/`y` directly —
|
|
296
|
+
this keeps a `contour` marker aligned with the map under it.
|
|
532
297
|
-->
|
|
533
298
|
<BasePlotLayout
|
|
534
299
|
{width}
|
|
535
300
|
{height}
|
|
536
|
-
data={
|
|
301
|
+
data={features}
|
|
537
302
|
getX={hoverGetX}
|
|
538
303
|
getY={hoverGetY}
|
|
539
|
-
{
|
|
540
|
-
label={(f) => f.__id}
|
|
541
|
-
{tooltip}
|
|
542
|
-
{hoverActive}
|
|
543
|
-
hoverStrategy="punctual"
|
|
544
|
-
hoverSync={tooltip?.sync ?? false}
|
|
304
|
+
{hover}
|
|
545
305
|
x={{ domain: [-180, 180] }}
|
|
546
306
|
y={{ domain: [90, -90] }}
|
|
547
|
-
|
|
307
|
+
coordinates={resolvedCoordinates}
|
|
548
308
|
{margins}
|
|
549
309
|
marginEstimate={GEO_MARGIN_ESTIMATE}
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
{#each styleGroups as group (JSON.stringify(group.style))}
|
|
570
|
-
<Geo
|
|
571
|
-
data={group.data}
|
|
572
|
-
fill={(d: TaggedFeature) => group.style.fill ?? resolveBaseFill(d)}
|
|
573
|
-
fillOpacity={group.style.fillOpacity ?? styles.fillOpacity ?? 1}
|
|
574
|
-
stroke={group.style.stroke ?? styles.stroke ?? cfg.axis.color}
|
|
575
|
-
strokeWidth={group.style.strokeWidth ?? styles.strokeWidth ?? 0.5}
|
|
576
|
-
style="vector-effect: non-scaling-stroke"
|
|
577
|
-
onclick={styles.onFeatureClick
|
|
578
|
-
? (e: Event, d: TaggedFeature) => styles.onFeatureClick?.(d, e)
|
|
579
|
-
: undefined}
|
|
580
|
-
/>
|
|
581
|
-
{/each}
|
|
582
|
-
|
|
583
|
-
{#each markers as marker, i (marker.type + '-' + i)}
|
|
584
|
-
{#if !isBehindMarker(marker)}
|
|
585
|
-
{@render marker_(marker, numericMargins)}
|
|
586
|
-
{/if}
|
|
587
|
-
{/each}
|
|
588
|
-
</GeoLayout>
|
|
589
|
-
|
|
590
|
-
{#if hoverMarkerConfig}
|
|
591
|
-
<HoverMarker
|
|
592
|
-
data={matchedPoints}
|
|
593
|
-
ruleX={null}
|
|
594
|
-
ruleY={null}
|
|
595
|
-
showLabels={hoverMarkerConfig.showLabels ?? true}
|
|
596
|
-
format={hoverMarkerConfig.format}
|
|
597
|
-
dotStyle={hoverMarkerConfig.dotStyle}
|
|
598
|
-
fontStyle={hoverMarkerConfig.fontStyle}
|
|
599
|
-
/>
|
|
600
|
-
{/if}
|
|
601
|
-
{/snippet}
|
|
602
|
-
</BasePlotLayout>
|
|
310
|
+
styles={resolvedStyles}
|
|
311
|
+
markers={({ setHoverMatch, clearHoverMatch }) =>
|
|
312
|
+
buildGeoMarkers({
|
|
313
|
+
styleGroups,
|
|
314
|
+
resolveBaseFill,
|
|
315
|
+
fillOpacity: styles.fillOpacity,
|
|
316
|
+
stroke: styles.stroke,
|
|
317
|
+
strokeWidth: styles.strokeWidth,
|
|
318
|
+
axisColor: cfg.axis.color,
|
|
319
|
+
onFeatureClick: styles.onFeatureClick,
|
|
320
|
+
markers,
|
|
321
|
+
hoverActive,
|
|
322
|
+
hoverPointById,
|
|
323
|
+
isOverInset,
|
|
324
|
+
setHoverMatch,
|
|
325
|
+
clearHoverMatch,
|
|
326
|
+
})}
|
|
327
|
+
geoAllFeatures={allFeatures}
|
|
328
|
+
/>
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import type { BasePlotProps
|
|
1
|
+
import type { BasePlotProps } from '../../types/plots/props';
|
|
2
|
+
import type { GeoScalesConfig, CoordinatesConfig } from '../../types/layout/coordinates';
|
|
2
3
|
import type { GeoFeature, GeoDataProps } from '../../types/plots/data/geo';
|
|
3
|
-
import type {
|
|
4
|
+
import type { GeoStylesConfig } from '../../types/layout/styles';
|
|
4
5
|
import type { GeoSegmentStyle } from '../../types/plots/segments/common';
|
|
5
|
-
import type {
|
|
6
|
+
import type { GeoMarkersConfig } from '../../types/markers/geo';
|
|
6
7
|
declare function $$render<TProps extends Record<string, unknown>>(): {
|
|
7
|
-
props: BasePlotProps<GeoDataProps<TProps>, GeoFeature<TProps>,
|
|
8
|
+
props: BasePlotProps<GeoDataProps<TProps>, GeoFeature<TProps>, GeoStylesConfig<TProps>, GeoSegmentStyle, GeoMarkersConfig, GeoScalesConfig, CoordinatesConfig>;
|
|
8
9
|
exports: {};
|
|
9
10
|
bindings: "";
|
|
10
11
|
slots: {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { MarkerConfig } from '../../types/markers/all';
|
|
2
|
+
import type { GeoMarkersConfig } from '../../types/markers/geo';
|
|
3
|
+
import type { GeoSegmentStyle } from '../../types/plots/segments/common';
|
|
4
|
+
/** One resolved-style bucket of features, as grouped by `GeoPlot`'s own `styleGroups`. */
|
|
5
|
+
export type GeoStyleGroup<TRow> = {
|
|
6
|
+
style: GeoSegmentStyle;
|
|
7
|
+
data: TRow[];
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Every marker for one `GeoPlot` render, in final draw order: any authored
|
|
11
|
+
* marker with `behind: true`, then the base map itself (one `'geo'` marker
|
|
12
|
+
* per resolved feature style), then the rest of the authored markers in
|
|
13
|
+
* order, with any `hover` marker moved last.
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildGeoMarkers<TRow extends Record<string, unknown> & {
|
|
16
|
+
__id: string;
|
|
17
|
+
}>(args: {
|
|
18
|
+
styleGroups: GeoStyleGroup<TRow>[];
|
|
19
|
+
resolveBaseFill: (d: TRow) => string;
|
|
20
|
+
fillOpacity?: number;
|
|
21
|
+
stroke?: string;
|
|
22
|
+
strokeWidth?: number;
|
|
23
|
+
axisColor: string;
|
|
24
|
+
onFeatureClick?: (d: TRow, e: Event) => void;
|
|
25
|
+
markers: GeoMarkersConfig[];
|
|
26
|
+
hoverActive: boolean;
|
|
27
|
+
hoverPointById: Map<string, {
|
|
28
|
+
row: TRow;
|
|
29
|
+
}>;
|
|
30
|
+
isOverInset: (e: PointerEvent) => boolean;
|
|
31
|
+
setHoverMatch: (rows: TRow[]) => void;
|
|
32
|
+
clearHoverMatch: () => void;
|
|
33
|
+
}): MarkerConfig[];
|