@fundar/data-chart-telling 0.0.13 → 0.0.15

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.
Files changed (141) hide show
  1. package/README.md +121 -17
  2. package/dist/charts/{Chart.svelte.d.ts → BaseChart.svelte.d.ts} +3 -3
  3. package/dist/charts/bar/Chart.svelte +5 -5
  4. package/dist/charts/bar/Chart.svelte.d.ts +1 -2
  5. package/dist/charts/heatmap/Chart.svelte +8 -7
  6. package/dist/charts/heatmap/Chart.svelte.d.ts +2 -3
  7. package/dist/charts/line/Chart.svelte +5 -5
  8. package/dist/charts/line/Chart.svelte.d.ts +1 -2
  9. package/dist/charts/pyramid/Chart.svelte +7 -6
  10. package/dist/charts/pyramid/Chart.svelte.d.ts +2 -3
  11. package/dist/configuration/config.svelte.js +1 -1
  12. package/dist/configuration/themes/index.d.ts +56 -40
  13. package/dist/index.d.ts +26 -12
  14. package/dist/index.js +12 -7
  15. package/dist/layout/facet/FacetLayout.svelte +1 -1
  16. package/dist/layout/facet/FacetLayout.svelte.d.ts +1 -1
  17. package/dist/layout/geo/GeoLayout.svelte +47 -0
  18. package/dist/layout/geo/GeoLayout.svelte.d.ts +22 -0
  19. package/dist/layout/geo/resolveProjection.d.ts +10 -0
  20. package/dist/layout/geo/resolveProjection.js +48 -0
  21. package/dist/layout/legend/DiscreteSection.svelte +1 -1
  22. package/dist/layout/plot/AxisLayout.svelte +95 -0
  23. package/dist/layout/plot/AxisLayout.svelte.d.ts +39 -0
  24. package/dist/layout/plot/BasePlotLayout.svelte +302 -0
  25. package/dist/layout/plot/BasePlotLayout.svelte.d.ts +95 -0
  26. package/dist/layout/plot/GridLayout.svelte +30 -0
  27. package/dist/layout/plot/GridLayout.svelte.d.ts +27 -0
  28. package/dist/layout/plot/RuleLayout.svelte +111 -0
  29. package/dist/layout/plot/RuleLayout.svelte.d.ts +40 -0
  30. package/dist/layout/plot/margins.d.ts +34 -0
  31. package/dist/layout/plot/margins.js +26 -0
  32. package/dist/layout/timeline/TimelineLayout.svelte +1 -1
  33. package/dist/layout/timeline/TimelineLayout.svelte.d.ts +1 -1
  34. package/dist/layout/tooltip/Tooltip.svelte +15 -0
  35. package/dist/layout/tooltip/Tooltip.svelte.d.ts +7 -0
  36. package/dist/layout/tooltip/TooltipLayout.svelte +45 -0
  37. package/dist/layout/tooltip/TooltipLayout.svelte.d.ts +41 -0
  38. package/dist/layout/tooltip/controller.svelte.d.ts +4 -3
  39. package/dist/layout/tooltip/controller.svelte.js +5 -6
  40. package/dist/layout/tooltip/hover.svelte.d.ts +1 -1
  41. package/dist/layout/tooltip/hover.svelte.js +1 -1
  42. package/dist/layout/tooltip/utils.d.ts +2 -2
  43. package/dist/markers/ContourClipMarker.svelte +77 -0
  44. package/dist/markers/ContourClipMarker.svelte.d.ts +10 -0
  45. package/dist/{plots/markers → markers}/DeltaMarker.svelte +4 -4
  46. package/dist/{plots/markers → markers}/DeltaMarker.svelte.d.ts +3 -3
  47. package/dist/{plots/markers → markers}/DotMarker.svelte +3 -3
  48. package/dist/{plots/markers → markers}/DotMarker.svelte.d.ts +3 -3
  49. package/dist/markers/HoverMarker.svelte +136 -0
  50. package/dist/{plots/markers → markers}/HoverMarker.svelte.d.ts +4 -4
  51. package/dist/{plots/markers → markers}/PeakMarker.svelte +2 -2
  52. package/dist/{plots/markers → markers}/PeakMarker.svelte.d.ts +2 -2
  53. package/dist/{plots/markers → markers}/TextMarker.svelte +11 -4
  54. package/dist/{plots/markers → markers}/TextMarker.svelte.d.ts +3 -3
  55. package/dist/markers/inset/InsetMarker.svelte +170 -0
  56. package/dist/markers/inset/InsetMarker.svelte.d.ts +51 -0
  57. package/dist/markers/inset/insetLayout.d.ts +25 -0
  58. package/dist/markers/inset/insetLayout.js +39 -0
  59. package/dist/markers/inset/insetProjection.d.ts +8 -0
  60. package/dist/markers/inset/insetProjection.js +39 -0
  61. package/dist/plots/bar/BarSegments.svelte +66 -0
  62. package/dist/plots/bar/BarSegments.svelte.d.ts +36 -0
  63. package/dist/plots/bar/Plot.svelte +132 -76
  64. package/dist/plots/bar/Plot.svelte.d.ts +7 -3
  65. package/dist/plots/bar/ValueLabels.svelte +89 -0
  66. package/dist/plots/bar/ValueLabels.svelte.d.ts +39 -0
  67. package/dist/plots/bar/hoverPoints.d.ts +15 -0
  68. package/dist/plots/bar/hoverPoints.js +35 -0
  69. package/dist/plots/bar/layout.svelte.d.ts +37 -0
  70. package/dist/plots/bar/layout.svelte.js +132 -0
  71. package/dist/plots/geo/Plot.svelte +548 -0
  72. package/dist/plots/geo/Plot.svelte.d.ts +29 -0
  73. package/dist/plots/geo/TileLayer.svelte +77 -0
  74. package/dist/plots/geo/TileLayer.svelte.d.ts +11 -0
  75. package/dist/plots/geo/projections/argentina.d.ts +8 -0
  76. package/dist/plots/geo/projections/argentina.js +35 -0
  77. package/dist/plots/geo/projections/fit.d.ts +8 -0
  78. package/dist/plots/geo/projections/fit.js +14 -0
  79. package/dist/plots/geo/rotate.svelte.d.ts +26 -0
  80. package/dist/plots/geo/rotate.svelte.js +79 -0
  81. package/dist/plots/geo/zoom.svelte.d.ts +32 -0
  82. package/dist/plots/geo/zoom.svelte.js +50 -0
  83. package/dist/plots/heatmap/Plot.svelte +129 -47
  84. package/dist/plots/heatmap/Plot.svelte.d.ts +7 -3
  85. package/dist/plots/line/Plot.svelte +44 -16
  86. package/dist/plots/line/Plot.svelte.d.ts +7 -3
  87. package/dist/plots/pyramid/Plot.svelte +70 -25
  88. package/dist/plots/pyramid/Plot.svelte.d.ts +7 -3
  89. package/dist/plots/utils/delta.d.ts +1 -1
  90. package/dist/plots/utils/geoAccessors.d.ts +64 -0
  91. package/dist/plots/utils/geoAccessors.js +188 -0
  92. package/dist/plots/utils/geoSegments.d.ts +14 -0
  93. package/dist/plots/utils/geoSegments.js +17 -0
  94. package/dist/plots/utils/segments.d.ts +14 -5
  95. package/dist/plots/utils/segments.js +25 -13
  96. package/dist/plots/utils/tiles.d.ts +89 -0
  97. package/dist/plots/utils/tiles.js +159 -0
  98. package/dist/plots/utils/topojson.d.ts +9 -0
  99. package/dist/plots/utils/topojson.js +30 -0
  100. package/dist/types/charts/common.d.ts +2 -1
  101. package/dist/types/charts/legend.d.ts +1 -1
  102. package/dist/types/charts/props.d.ts +9 -6
  103. package/dist/types/configuration/styling.d.ts +11 -5
  104. package/dist/types/layout/tooltip.d.ts +14 -21
  105. package/dist/types/{plots/markers.d.ts → markers/common.d.ts} +2 -18
  106. package/dist/types/markers/geo.d.ts +237 -0
  107. package/dist/types/markers/props.d.ts +11 -0
  108. package/dist/types/plots/axis.d.ts +55 -0
  109. package/dist/types/plots/axis.js +1 -0
  110. package/dist/types/plots/constants.d.ts +30 -0
  111. package/dist/types/plots/constants.js +1 -0
  112. package/dist/types/plots/data/common.d.ts +40 -0
  113. package/dist/types/plots/data/common.js +1 -0
  114. package/dist/types/plots/data/geo.d.ts +74 -0
  115. package/dist/types/plots/data/geo.js +1 -0
  116. package/dist/types/plots/delta.d.ts +2 -2
  117. package/dist/types/plots/props.d.ts +105 -16
  118. package/dist/types/plots/scales/geo.d.ts +44 -0
  119. package/dist/types/plots/scales/geo.js +1 -0
  120. package/dist/types/plots/segments/common.d.ts +25 -0
  121. package/dist/types/plots/segments/common.js +1 -0
  122. package/dist/types/plots/segments/config.d.ts +51 -0
  123. package/dist/types/plots/segments/config.js +1 -0
  124. package/dist/types/plots/styles/common.d.ts +37 -0
  125. package/dist/types/plots/styles/common.js +1 -0
  126. package/dist/types/plots/styles/geo.d.ts +42 -0
  127. package/dist/types/plots/styles/geo.js +1 -0
  128. package/dist/types/plots/styling.d.ts +45 -0
  129. package/dist/types/plots/styling.js +1 -0
  130. package/dist/utils/grouping.d.ts +2 -1
  131. package/dist/utils/interpolate.d.ts +2 -1
  132. package/package.json +27 -13
  133. package/dist/layout/plot/PlotLayout.svelte +0 -237
  134. package/dist/layout/plot/PlotLayout.svelte.d.ts +0 -70
  135. package/dist/plots/markers/HoverMarker.svelte +0 -98
  136. package/dist/types/plots/common.d.ts +0 -100
  137. package/dist/types/plots/styles.d.ts +0 -187
  138. /package/dist/charts/{Chart.svelte → BaseChart.svelte} +0 -0
  139. /package/dist/types/{plots → markers}/common.js +0 -0
  140. /package/dist/types/{plots/markers.js → markers/geo.js} +0 -0
  141. /package/dist/types/{plots/styles.js → markers/props.js} +0 -0
@@ -0,0 +1,89 @@
1
+ export type TileCoord = {
2
+ x: number;
3
+ y: number;
4
+ z: number;
5
+ };
6
+ export type ScreenBounds = {
7
+ left: number;
8
+ top: number;
9
+ width: number;
10
+ height: number;
11
+ };
12
+ /** The subset of a `d3-geo`-style projection this module needs. */
13
+ export type ProjectionLike = {
14
+ (point: [number, number]): [number, number] | null;
15
+ invert?(point: [number, number]): [number, number] | null;
16
+ };
17
+ /** The minimal geometry-stream shape a projection's `.stream()` accepts — kept local instead of importing `d3-geo`'s own `GeoStream` type, so this module stays dependency-free. */
18
+ type MinimalStream = {
19
+ point: (x: number, y: number, z?: number) => void;
20
+ lineStart: () => void;
21
+ lineEnd: () => void;
22
+ polygonStart: () => void;
23
+ polygonEnd: () => void;
24
+ sphere?: () => void;
25
+ };
26
+ /** What `toProjectionLike` needs from a svelteplot-resolved projection. */
27
+ export type StreamingProjection = {
28
+ stream: (s: MinimalStream) => MinimalStream;
29
+ invert?: (point: [number, number]) => [number, number] | null;
30
+ };
31
+ /**
32
+ * Adapts a svelteplot-resolved projection (which exposes `.stream()`/
33
+ * `.invert()`, but — unlike a raw `d3-geo` projection instance — isn't
34
+ * itself callable as `(point) => [x, y]`) into a `ProjectionLike`, by
35
+ * feeding a single point through its stream pipeline and capturing the
36
+ * projected output.
37
+ */
38
+ export declare function toProjectionLike(projection: StreamingProjection): ProjectionLike;
39
+ /**
40
+ * Derives the visible XYZ tile grid from svelteplot's own already-fitted
41
+ * projection (rather than this package computing/duplicating a `d3-geo` fit
42
+ * itself) — see `TileLayer.svelte`. Only correct for Mercator-family
43
+ * projections, where a screen-space rectangle maps back to a lon/lat bbox
44
+ * whose tile coverage is well-defined; callers are responsible for the
45
+ * projection-compatibility check (see `Plot.svelte`'s validation effect).
46
+ */
47
+ export declare function visibleTiles(projection: ProjectionLike, bounds: ScreenBounds, tileSize?: number, minZoom?: number, maxZoom?: number): TileCoord[];
48
+ /** An affine tile-space → screen-space mapping (see `buildMercatorFit`), reused across every tile in a grid instead of forward-projecting each one individually. */
49
+ export type MercatorFit = {
50
+ z: number;
51
+ screenLeft: number;
52
+ screenTop: number;
53
+ tileXAtLeft: number;
54
+ tileYAtTop: number;
55
+ pxPerTileX: number;
56
+ pxPerTileY: number;
57
+ };
58
+ /**
59
+ * Builds an affine tile-space → screen-space mapping from two reliable
60
+ * anchor points — `bounds`' own top-left/bottom-right corners, inverted
61
+ * back to lon/lat — rather than forward-projecting each tile's own corners
62
+ * individually (what this replaced). That per-tile approach broke under a
63
+ * projection whose scale/translate were fit to a *custom* domain rather
64
+ * than set via its own `.scale()`/`.translate()`: `d3-geo`'s cylindrical
65
+ * projections (mercator included) auto-install an internal `clipExtent`
66
+ * sized to whatever scale/translate they were constructed or last
67
+ * `.scale()`/`.translate()`-called with (guarding against the y → ±Infinity
68
+ * blowup near the poles); svelteplot's own domain-fitting wraps the
69
+ * *unmodified* projection instance in an external transform instead of
70
+ * calling those setters, so that internal clip keeps silently rejecting
71
+ * forward-projected points outside its stale bounds — nulling out most of
72
+ * a tile grid even for tiles nowhere near a pole. `.invert()` isn't routed
73
+ * through that clip, so anchoring to two known-good inverted corners
74
+ * sidesteps it entirely — sound because Mercator's tile space (longitude,
75
+ * and the standard log-tan latitude transform used by `latToTileY`) is
76
+ * affine in screen space by construction, so one linear fit applies
77
+ * uniformly to every tile in the grid.
78
+ */
79
+ export declare function buildMercatorFit(projection: ProjectionLike, bounds: ScreenBounds, z: number): MercatorFit | null;
80
+ /** Places a tile on screen via a `MercatorFit` — `null` only if `tile` is from a different zoom level than the fit was built for. */
81
+ export declare function tileScreenBounds(fit: MercatorFit, tile: TileCoord): ScreenBounds | null;
82
+ /**
83
+ * Fills `{z}/{x}/{y}` placeholders in a tile URL template. Also supports
84
+ * `{-y}` for TMS-scheme sources (e.g. IGN's tile services), whose row index
85
+ * counts from the south instead of the north — the standard XYZ-to-TMS
86
+ * conversion `2^z - 1 - y`.
87
+ */
88
+ export declare function tileUrl(template: string, tile: TileCoord): string;
89
+ export {};
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Adapts a svelteplot-resolved projection (which exposes `.stream()`/
3
+ * `.invert()`, but — unlike a raw `d3-geo` projection instance — isn't
4
+ * itself callable as `(point) => [x, y]`) into a `ProjectionLike`, by
5
+ * feeding a single point through its stream pipeline and capturing the
6
+ * projected output.
7
+ */
8
+ export function toProjectionLike(projection) {
9
+ const fn = ((point) => {
10
+ let result = null;
11
+ const sink = {
12
+ point: (x, y) => {
13
+ result = [x, y];
14
+ },
15
+ lineStart() { },
16
+ lineEnd() { },
17
+ polygonStart() { },
18
+ polygonEnd() { },
19
+ };
20
+ projection.stream(sink).point(point[0], point[1]);
21
+ return result;
22
+ });
23
+ if (projection.invert)
24
+ fn.invert = (point) => projection.invert(point);
25
+ return fn;
26
+ }
27
+ function lonToTileX(lon, z) {
28
+ return ((lon + 180) / 360) * 2 ** z;
29
+ }
30
+ function latToTileY(lat, z) {
31
+ const rad = (lat * Math.PI) / 180;
32
+ return ((1 - Math.log(Math.tan(rad) + 1 / Math.cos(rad)) / Math.PI) / 2) * 2 ** z;
33
+ }
34
+ /**
35
+ * Picks an integer XYZ zoom level whose tile pixel density roughly matches
36
+ * the projection's *current* pixels-per-degree at the map center — so tiles
37
+ * neither look blurry (too coarse) nor waste bandwidth (too fine).
38
+ */
39
+ function estimateZoomLevel(projection, centerLon, centerLat, tileSize) {
40
+ const eps = 0.01;
41
+ const p0 = projection([centerLon, centerLat]);
42
+ const p1 = projection([centerLon + eps, centerLat]);
43
+ if (!p0 || !p1)
44
+ return null;
45
+ const pixelsPerDegree = Math.abs(p1[0] - p0[0]) / eps;
46
+ const worldPixelsAtZ0 = tileSize / 360;
47
+ const ratio = pixelsPerDegree / worldPixelsAtZ0;
48
+ if (!Number.isFinite(ratio) || ratio <= 0)
49
+ return null;
50
+ return Math.round(Math.log2(ratio));
51
+ }
52
+ /**
53
+ * Derives the visible XYZ tile grid from svelteplot's own already-fitted
54
+ * projection (rather than this package computing/duplicating a `d3-geo` fit
55
+ * itself) — see `TileLayer.svelte`. Only correct for Mercator-family
56
+ * projections, where a screen-space rectangle maps back to a lon/lat bbox
57
+ * whose tile coverage is well-defined; callers are responsible for the
58
+ * projection-compatibility check (see `Plot.svelte`'s validation effect).
59
+ */
60
+ export function visibleTiles(projection, bounds, tileSize = 256, minZoom = 0, maxZoom = 19) {
61
+ if (!projection.invert)
62
+ return [];
63
+ const corners = [
64
+ [bounds.left, bounds.top],
65
+ [bounds.left + bounds.width, bounds.top],
66
+ [bounds.left, bounds.top + bounds.height],
67
+ [bounds.left + bounds.width, bounds.top + bounds.height],
68
+ ];
69
+ const lonLats = corners.map((c) => projection.invert(c)).filter((p) => p != null);
70
+ if (lonLats.length === 0)
71
+ return [];
72
+ const centerScreen = [bounds.left + bounds.width / 2, bounds.top + bounds.height / 2];
73
+ const center = projection.invert(centerScreen);
74
+ const z = center
75
+ ? Math.max(minZoom, Math.min(maxZoom, estimateZoomLevel(projection, center[0], center[1], tileSize) ?? minZoom))
76
+ : minZoom;
77
+ const lons = lonLats.map((p) => p[0]);
78
+ const lats = lonLats.map((p) => p[1]);
79
+ const minTileX = Math.floor(lonToTileX(Math.min(...lons), z));
80
+ const maxTileX = Math.floor(lonToTileX(Math.max(...lons), z));
81
+ const minTileY = Math.floor(latToTileY(Math.max(...lats), z));
82
+ const maxTileY = Math.floor(latToTileY(Math.min(...lats), z));
83
+ const maxTile = 2 ** z - 1;
84
+ const tiles = [];
85
+ for (let x = Math.max(0, minTileX); x <= Math.min(maxTile, maxTileX); x++) {
86
+ for (let y = Math.max(0, minTileY); y <= Math.min(maxTile, maxTileY); y++) {
87
+ tiles.push({ x, y, z });
88
+ }
89
+ }
90
+ return tiles;
91
+ }
92
+ /**
93
+ * Builds an affine tile-space → screen-space mapping from two reliable
94
+ * anchor points — `bounds`' own top-left/bottom-right corners, inverted
95
+ * back to lon/lat — rather than forward-projecting each tile's own corners
96
+ * individually (what this replaced). That per-tile approach broke under a
97
+ * projection whose scale/translate were fit to a *custom* domain rather
98
+ * than set via its own `.scale()`/`.translate()`: `d3-geo`'s cylindrical
99
+ * projections (mercator included) auto-install an internal `clipExtent`
100
+ * sized to whatever scale/translate they were constructed or last
101
+ * `.scale()`/`.translate()`-called with (guarding against the y → ±Infinity
102
+ * blowup near the poles); svelteplot's own domain-fitting wraps the
103
+ * *unmodified* projection instance in an external transform instead of
104
+ * calling those setters, so that internal clip keeps silently rejecting
105
+ * forward-projected points outside its stale bounds — nulling out most of
106
+ * a tile grid even for tiles nowhere near a pole. `.invert()` isn't routed
107
+ * through that clip, so anchoring to two known-good inverted corners
108
+ * sidesteps it entirely — sound because Mercator's tile space (longitude,
109
+ * and the standard log-tan latitude transform used by `latToTileY`) is
110
+ * affine in screen space by construction, so one linear fit applies
111
+ * uniformly to every tile in the grid.
112
+ */
113
+ export function buildMercatorFit(projection, bounds, z) {
114
+ if (!projection.invert)
115
+ return null;
116
+ const topLeft = projection.invert([bounds.left, bounds.top]);
117
+ const bottomRight = projection.invert([bounds.left + bounds.width, bounds.top + bounds.height]);
118
+ if (!topLeft || !bottomRight)
119
+ return null;
120
+ const tileXAtLeft = lonToTileX(topLeft[0], z);
121
+ const tileXAtRight = lonToTileX(bottomRight[0], z);
122
+ const tileYAtTop = latToTileY(topLeft[1], z);
123
+ const tileYAtBottom = latToTileY(bottomRight[1], z);
124
+ if (tileXAtRight === tileXAtLeft || tileYAtBottom === tileYAtTop)
125
+ return null;
126
+ return {
127
+ z,
128
+ screenLeft: bounds.left,
129
+ screenTop: bounds.top,
130
+ tileXAtLeft,
131
+ tileYAtTop,
132
+ pxPerTileX: bounds.width / (tileXAtRight - tileXAtLeft),
133
+ pxPerTileY: bounds.height / (tileYAtBottom - tileYAtTop),
134
+ };
135
+ }
136
+ /** Places a tile on screen via a `MercatorFit` — `null` only if `tile` is from a different zoom level than the fit was built for. */
137
+ export function tileScreenBounds(fit, tile) {
138
+ if (tile.z !== fit.z)
139
+ return null;
140
+ return {
141
+ left: fit.screenLeft + (tile.x - fit.tileXAtLeft) * fit.pxPerTileX,
142
+ top: fit.screenTop + (tile.y - fit.tileYAtTop) * fit.pxPerTileY,
143
+ width: fit.pxPerTileX,
144
+ height: fit.pxPerTileY,
145
+ };
146
+ }
147
+ /**
148
+ * Fills `{z}/{x}/{y}` placeholders in a tile URL template. Also supports
149
+ * `{-y}` for TMS-scheme sources (e.g. IGN's tile services), whose row index
150
+ * counts from the south instead of the north — the standard XYZ-to-TMS
151
+ * conversion `2^z - 1 - y`.
152
+ */
153
+ export function tileUrl(template, tile) {
154
+ return template
155
+ .replace('{z}', String(tile.z))
156
+ .replace('{x}', String(tile.x))
157
+ .replace('{-y}', String(2 ** tile.z - 1 - tile.y))
158
+ .replace('{y}', String(tile.y));
159
+ }
@@ -0,0 +1,9 @@
1
+ import type { GeoFeature, Topology } from '../../types/plots/data/geo';
2
+ export declare function isTopology(data: unknown): data is Topology;
3
+ /**
4
+ * Converts a TopoJSON `Topology` to GeoJSON via `topojson-client`'s
5
+ * `feature()`, loaded with a dynamic import so the package works perfectly
6
+ * for consumers who never install `topojson-client` — it's an optional peer
7
+ * dependency (see package.json), never statically imported.
8
+ */
9
+ export declare function topologyToGeoJson<TProps extends Record<string, unknown>>(topology: Topology, object: string): Promise<GeoFeature<TProps>[]>;
@@ -0,0 +1,30 @@
1
+ export function isTopology(data) {
2
+ return !!data && typeof data === 'object' && data.type === 'Topology';
3
+ }
4
+ /**
5
+ * Converts a TopoJSON `Topology` to GeoJSON via `topojson-client`'s
6
+ * `feature()`, loaded with a dynamic import so the package works perfectly
7
+ * for consumers who never install `topojson-client` — it's an optional peer
8
+ * dependency (see package.json), never statically imported.
9
+ */
10
+ export async function topologyToGeoJson(topology, object) {
11
+ const obj = topology.objects[object];
12
+ if (!obj) {
13
+ throw new Error(`GeoPlot: topology.objects has no key "${object}".`);
14
+ }
15
+ let mod;
16
+ try {
17
+ // @ts-expect-error — topojson-client is an optional peer dependency; its
18
+ // type declarations are intentionally not resolved by our own build
19
+ // (`Topology` above is typed structurally instead), so this import is
20
+ // resolved purely at runtime.
21
+ mod = await import('topojson-client');
22
+ }
23
+ catch {
24
+ throw new Error("GeoPlot: `data` is a TopoJSON Topology, but 'topojson-client' isn't installed. " +
25
+ 'Run `npm install topojson-client` (it\'s an optional peer dependency) or pass GeoJSON directly.');
26
+ }
27
+ const { feature } = mod;
28
+ const collection = feature(topology, obj);
29
+ return (collection.type === 'FeatureCollection' ? collection.features : [collection]);
30
+ }
@@ -1,5 +1,6 @@
1
1
  import type { Snippet } from 'svelte';
2
- import type { Accessor, AxisValue } from '../plots/common';
2
+ import type { AxisValue } from '../plots/axis';
3
+ import type { Accessor } from '../plots/data/common';
3
4
  import type { EasingName, EasingFn } from './interpolate';
4
5
  export type TimeValue = number;
5
6
  export type Orientation = 'horizontal' | 'vertical';
@@ -1,4 +1,4 @@
1
- import type { SymbolType, LineStyle } from '../plots/styles';
1
+ import type { SymbolType, LineStyle } from '../plots/constants';
2
2
  export type LegendSectionType = 'discrete' | 'continuous';
3
3
  export type LegendItem = {
4
4
  name: string;
@@ -1,7 +1,10 @@
1
1
  import type { Snippet } from 'svelte';
2
- import type { Accessor, AxisValue, ScalesConfig, MarginConfig } from '../plots/common';
3
- import type { PlotStyles, Segments } from '../plots/styles';
4
- import type { Marker } from '../plots/markers';
2
+ import type { AxisValue } from '../plots/axis';
3
+ import type { Accessor } from '../plots/data/common';
4
+ import type { AxisBasedScalesConfig } from '../plots/props';
5
+ import type { BasePlotStyles } from '../plots/styles/common';
6
+ import type { SegmentsConfig, MarginConfig } from '../plots/props';
7
+ import type { Marker } from '../markers/common';
5
8
  import type { TooltipProp } from '../layout/tooltip';
6
9
  import type { LegendSection } from './legend';
7
10
  import type { FacetConfig, TimelineConfig } from './common';
@@ -27,10 +30,10 @@ export type ChartProps<TRow extends Record<string, unknown>, TSegmentStyle exten
27
30
  x: Accessor<TRow, AxisValue>;
28
31
  y: Accessor<TRow, AxisValue>;
29
32
  z?: Accessor<TRow, unknown>;
30
- styles?: PlotStyles;
31
- segments?: Segments<TSegmentStyle>;
33
+ styles?: BasePlotStyles;
34
+ segments?: SegmentsConfig<TSegmentStyle>;
32
35
  markers?: Marker[];
33
- scales?: ScalesConfig;
36
+ scales?: AxisBasedScalesConfig<TRow>;
34
37
  margins?: MarginConfig;
35
38
  facet?: FacetConfig<TRow>;
36
39
  timeline?: TimelineConfig<TRow>;
@@ -1,4 +1,4 @@
1
- import type { StrokeStyle, DotStyle, FontStyle } from '../plots/styles';
1
+ import type { StrokeStyle, DotStyle, FontStyle } from '../plots/styling';
2
2
  export type TextStyle = {
3
3
  /** font-family */
4
4
  font: string;
@@ -57,11 +57,17 @@ export type ChartConfig = {
57
57
  radius: string;
58
58
  border: string;
59
59
  };
60
+ /**
61
+ * Per-side plot margin. `'auto'` (the default) lets svelteplot size that
62
+ * side to fit whatever it actually renders there — tick labels, an axis
63
+ * title, rotated ticks — instead of clipping content or leaving unused
64
+ * space. A number pins that side exactly, opting out of auto-sizing.
65
+ */
60
66
  margins: {
61
- top: number;
62
- right: number;
63
- bottom: number;
64
- left: number;
67
+ top: number | 'auto';
68
+ right: number | 'auto';
69
+ bottom: number | 'auto';
70
+ left: number | 'auto';
65
71
  };
66
72
  /** Discrete categorical palette (grouped series). */
67
73
  palette: string[];
@@ -1,9 +1,9 @@
1
1
  import type { Snippet } from 'svelte';
2
- import type { AxisValue } from '../plots/common';
2
+ import type { AxisValue } from '../plots/axis';
3
3
  /**
4
4
  * How the hover highlight finds related points within a facet.
5
- * - `'x'` all points sharing the hovered x (default for line / bar).
6
- * - `'y'` all points sharing the hovered y (default for pyramid).
5
+ * - `'x'` all points sharing the hovered x (default for line / bar).
6
+ * - `'y'` all points sharing the hovered y (default for pyramid).
7
7
  * - `'punctual'` exact XY match — one cell at a time (default for heatmap).
8
8
  */
9
9
  export type HoverStrategy = 'x' | 'y' | 'punctual';
@@ -27,27 +27,10 @@ export type TooltipOptions<TRow extends Record<string, unknown>> = {
27
27
  };
28
28
  /** Either a bare on/off flag or the full option object. */
29
29
  export type TooltipProp<TRow extends Record<string, unknown>> = boolean | TooltipOptions<TRow>;
30
- /**
31
- * Resolved tooltip config handed from a chart kind down to a plot. Presence of
32
- * this object on a plot is what turns hovering on.
33
- */
34
- export type TooltipRuntime<TRow extends Record<string, unknown>> = {
35
- format: (row: TRow) => string;
36
- /** Identifies the originating facet (`''` when not faceted). */
37
- facetId: string;
38
- /** Strategy resolved by the chart; omitted → PlotLayout falls back to its own default. */
39
- strategy?: HoverStrategy;
40
- /** Whether to broadcast to other facets. */
41
- sync: boolean;
42
- series?: string[];
43
- content?: Snippet<[{
44
- rows: TRow[];
45
- }]>;
46
- };
47
30
  /**
48
31
  * Shared hover state for cross-facet tooltip syncing.
49
32
  *
50
- * {@link Chart} provides one store via context; every faceted plot reads the
33
+ * {@link BaseChart} provides one store via context; every faceted plot reads the
51
34
  * same instance, so a hover detected in one facet (which writes `activeX/Y` and
52
35
  * stamps itself as `source`) is visible to the others. A standalone plot with no
53
36
  * provider falls back to its own {@link createHover} store.
@@ -83,6 +66,16 @@ export type HoverDisplayPoint = {
83
66
  series?: string;
84
67
  /** Resolved series color — used by HoverMarker when dotFill/fill is `'currentColor'`. */
85
68
  color?: string;
69
+ /**
70
+ * Pixel nudge applied on top of the scaled `x`/`y` position — for plot kinds
71
+ * where a series' visual position isn't fully captured by its data value
72
+ * (e.g. BarPlot's 'grouped' layout, where every series shares the same `x`
73
+ * category but is drawn at its own pixel slice within that category's band).
74
+ * Matching (`matchByStrategy`) still compares raw `x`/`y`, so this is
75
+ * display-only and never affects which points highlight together.
76
+ */
77
+ dx?: number;
78
+ dy?: number;
86
79
  };
87
80
  /** A candidate point for hover matching/highlighting — also carries its source row. */
88
81
  export type HoverPoint<T> = HoverDisplayPoint & {
@@ -1,17 +1,6 @@
1
- import type { AxisValue } from './common';
2
- import type { DotStyle, FontStyle, StrokeStyle } from './styles';
1
+ import type { AxisValue } from '../plots/axis';
2
+ import type { DotStyle, FontStyle, StrokeStyle } from '../plots/styling';
3
3
  import type { HoverStrategy, HoverDisplayPoint } from '../layout/tooltip';
4
- /**
5
- * Baseline props every marker component receives when mounted by a plot:
6
- * `data` for the points/values it draws, plus `series`/`seriesColor` when
7
- * mounted per-series via a `CustomComponentMarker`. Marker components extend
8
- * this with whatever else they need (e.g. PeakMarker's `mode`, `label`).
9
- */
10
- export interface MarkerProps<TData = Record<string, unknown>> {
11
- data?: TData[];
12
- series?: string;
13
- seriesColor?: string;
14
- }
15
4
  export type RuleXMarker = {
16
5
  type: 'ruleX';
17
6
  x: AxisValue;
@@ -31,16 +20,12 @@ export type RuleYMarker = {
31
20
  export type HoverMarkerConfig = {
32
21
  type: 'hover';
33
22
  series?: string;
34
- /** Whether to render per segment or for the full series. Defaults to `'series'`. */
35
23
  scope?: 'series' | 'segment';
36
- /** Matching strategy — how related points are found. Defaults to the plot kind's own default. */
37
24
  strategy?: HoverStrategy;
38
- /** Broadcast the hover to other facets. Defaults to `false`. */
39
25
  sync?: boolean;
40
26
  ruleX?: boolean;
41
27
  ruleY?: boolean;
42
28
  showLabels?: boolean;
43
- /** Custom label formatter. Receives the matched point; return the string to display. */
44
29
  format?: (point: HoverDisplayPoint) => string;
45
30
  ruleStyle?: StrokeStyle;
46
31
  dotStyle?: DotStyle;
@@ -52,7 +37,6 @@ export type CustomComponentMarker = {
52
37
  component: any;
53
38
  props?: Record<string, unknown>;
54
39
  data?: any[];
55
- /** Whether to render per segment or for the full series. Defaults to `'series'`. */
56
40
  scope?: 'series' | 'segment';
57
41
  };
58
42
  export type Marker = RuleXMarker | RuleYMarker | HoverMarkerConfig | CustomComponentMarker;