@fundar/data-chart-telling 0.0.25 → 0.0.27

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 (198) hide show
  1. package/dist/charts/BaseChart.svelte +18 -10
  2. package/dist/charts/BaseChart.svelte.d.ts +4 -2
  3. package/dist/charts/bar/Chart.svelte +2 -0
  4. package/dist/charts/heatmap/Chart.svelte +5 -3
  5. package/dist/charts/heatmap/Chart.svelte.d.ts +1 -2
  6. package/dist/charts/line/Chart.svelte +2 -0
  7. package/dist/charts/pyramid/Chart.svelte +5 -3
  8. package/dist/charts/pyramid/Chart.svelte.d.ts +1 -2
  9. package/dist/charts/scatter/Chart.svelte +95 -0
  10. package/dist/charts/scatter/Chart.svelte.d.ts +28 -0
  11. package/dist/configuration/config.svelte.js +28 -0
  12. package/dist/configuration/themes/dark.js +4 -0
  13. package/dist/configuration/themes/index.d.ts +112 -0
  14. package/dist/index.d.ts +26 -16
  15. package/dist/index.js +11 -3
  16. package/dist/layout/coordinates/CoordinatesLayout.svelte +93 -0
  17. package/dist/layout/{plot/RuleLayout.svelte.d.ts → coordinates/CoordinatesLayout.svelte.d.ts} +13 -16
  18. package/dist/layout/coordinates/margins.d.ts +16 -0
  19. package/dist/layout/coordinates/margins.js +11 -0
  20. package/dist/{plots/geo → layout/coordinates}/projections/argentina.d.ts +1 -1
  21. package/dist/layout/{geo → coordinates}/resolveProjection.d.ts +1 -1
  22. package/dist/layout/coordinates/resolveProjection.js +24 -0
  23. package/dist/{plots/geo → layout/coordinates}/zoom.svelte.d.ts +1 -1
  24. package/dist/layout/facet/FacetIndicator.svelte +31 -0
  25. package/dist/layout/facet/FacetIndicator.svelte.d.ts +8 -0
  26. package/dist/layout/facet/FacetLayout.svelte +249 -24
  27. package/dist/layout/facet/FacetLayout.svelte.d.ts +7 -1
  28. package/dist/layout/geometry/GeometryLayout.svelte +231 -0
  29. package/dist/layout/geometry/GeometryLayout.svelte.d.ts +62 -0
  30. package/dist/layout/legend/ContinuousSection.svelte +1 -1
  31. package/dist/layout/legend/ContinuousSection.svelte.d.ts +1 -1
  32. package/dist/layout/legend/DiscreteSection.svelte +1 -1
  33. package/dist/layout/legend/DiscreteSection.svelte.d.ts +1 -1
  34. package/dist/layout/legend/LegendLayout.svelte +1 -1
  35. package/dist/layout/legend/LegendLayout.svelte.d.ts +1 -1
  36. package/dist/layout/legend/interaction.svelte.d.ts +9 -1
  37. package/dist/layout/legend/interaction.svelte.js +9 -1
  38. package/dist/layout/plot/BasePlotLayout.svelte +142 -155
  39. package/dist/layout/plot/BasePlotLayout.svelte.d.ts +61 -51
  40. package/dist/layout/plot/margins.d.ts +0 -16
  41. package/dist/layout/plot/margins.js +0 -11
  42. package/dist/layout/{plot/AxisLayout.svelte → scales/ScalesLayout.svelte} +23 -16
  43. package/dist/layout/{plot/AxisLayout.svelte.d.ts → scales/ScalesLayout.svelte.d.ts} +4 -5
  44. package/dist/layout/scales/buildScale.d.ts +8 -0
  45. package/dist/layout/scales/buildScale.js +43 -0
  46. package/dist/layout/styles/StylesLayout.svelte +75 -0
  47. package/dist/layout/styles/StylesLayout.svelte.d.ts +15 -0
  48. package/dist/{plots/geo → layout/styles}/TileLayer.svelte +2 -2
  49. package/dist/{plots/geo → layout/styles}/TileLayer.svelte.d.ts +1 -1
  50. package/dist/layout/timeline/Timeline.svelte +1 -1
  51. package/dist/layout/timeline/Timeline.svelte.d.ts +1 -1
  52. package/dist/layout/timeline/TimelineLayout.svelte +1 -1
  53. package/dist/layout/timeline/TimelineLayout.svelte.d.ts +1 -1
  54. package/dist/layout/tooltip/Tooltip.svelte +16 -20
  55. package/dist/layout/tooltip/Tooltip.svelte.d.ts +5 -0
  56. package/dist/layout/tooltip/TooltipLayout.svelte +7 -1
  57. package/dist/layout/tooltip/TooltipLayout.svelte.d.ts +4 -0
  58. package/dist/layout/tooltip/controller.svelte.d.ts +4 -5
  59. package/dist/layout/tooltip/controller.svelte.js +42 -16
  60. package/dist/layout/tooltip/resolveTooltipPlacement.d.ts +24 -0
  61. package/dist/layout/tooltip/resolveTooltipPlacement.js +49 -0
  62. package/dist/layout/tooltip/utils.d.ts +27 -19
  63. package/dist/layout/tooltip/utils.js +16 -15
  64. package/dist/markers/BarMarker.svelte +92 -0
  65. package/dist/markers/BarMarker.svelte.d.ts +7 -0
  66. package/dist/markers/CellMarker.svelte +21 -0
  67. package/dist/markers/CellMarker.svelte.d.ts +7 -0
  68. package/dist/markers/ContourMarker.svelte +28 -0
  69. package/dist/markers/ContourMarker.svelte.d.ts +7 -0
  70. package/dist/markers/DeltaMarker.svelte +32 -39
  71. package/dist/markers/DeltaMarker.svelte.d.ts +4 -5
  72. package/dist/markers/DotMarker.svelte +35 -6
  73. package/dist/markers/DotMarker.svelte.d.ts +11 -2
  74. package/dist/markers/GeoFeaturesMarker.svelte +19 -0
  75. package/dist/markers/GeoFeaturesMarker.svelte.d.ts +7 -0
  76. package/dist/markers/GeoHoverMarker.svelte +25 -0
  77. package/dist/markers/GeoHoverMarker.svelte.d.ts +9 -0
  78. package/dist/markers/GraticuleMarker.svelte +18 -0
  79. package/dist/markers/GraticuleMarker.svelte.d.ts +7 -0
  80. package/dist/markers/HoverMarker.svelte +34 -35
  81. package/dist/markers/HoverMarker.svelte.d.ts +15 -9
  82. package/dist/markers/LineMarker.svelte +19 -0
  83. package/dist/markers/LineMarker.svelte.d.ts +7 -0
  84. package/dist/markers/LinkMarker.svelte +42 -0
  85. package/dist/markers/LinkMarker.svelte.d.ts +7 -0
  86. package/dist/markers/RuleMarker.svelte +24 -0
  87. package/dist/markers/RuleMarker.svelte.d.ts +10 -0
  88. package/dist/markers/SphereMarker.svelte +15 -0
  89. package/dist/markers/SphereMarker.svelte.d.ts +7 -0
  90. package/dist/markers/TextMarker.svelte +1 -1
  91. package/dist/markers/TextMarker.svelte.d.ts +1 -1
  92. package/dist/markers/VectorMarker.svelte +20 -0
  93. package/dist/markers/VectorMarker.svelte.d.ts +7 -0
  94. package/dist/markers/inset/InsetMarker.svelte +38 -45
  95. package/dist/markers/inset/InsetMarker.svelte.d.ts +6 -2
  96. package/dist/plots/bar/Plot.svelte +96 -87
  97. package/dist/plots/bar/Plot.svelte.d.ts +4 -5
  98. package/dist/plots/bar/ValueLabels.svelte +70 -24
  99. package/dist/plots/bar/ValueLabels.svelte.d.ts +11 -2
  100. package/dist/plots/bar/buildBarMarkers.d.ts +30 -0
  101. package/dist/plots/bar/buildBarMarkers.js +100 -0
  102. package/dist/plots/bar/layout.svelte.d.ts +1 -2
  103. package/dist/plots/bar/layout.svelte.js +1 -1
  104. package/dist/plots/geo/Plot.svelte +113 -387
  105. package/dist/plots/geo/Plot.svelte.d.ts +5 -4
  106. package/dist/plots/geo/buildGeoMarkers.d.ts +33 -0
  107. package/dist/plots/geo/buildGeoMarkers.js +47 -0
  108. package/dist/plots/heatmap/Plot.svelte +27 -52
  109. package/dist/plots/heatmap/Plot.svelte.d.ts +4 -5
  110. package/dist/plots/heatmap/ValueLabels.svelte +5 -5
  111. package/dist/plots/heatmap/ValueLabels.svelte.d.ts +3 -3
  112. package/dist/plots/heatmap/buildCellMarkers.d.ts +21 -0
  113. package/dist/plots/heatmap/buildCellMarkers.js +25 -0
  114. package/dist/plots/line/Plot.svelte +73 -141
  115. package/dist/plots/line/Plot.svelte.d.ts +4 -4
  116. package/dist/plots/line/ValueLabels.svelte +84 -85
  117. package/dist/plots/line/ValueLabels.svelte.d.ts +10 -1
  118. package/dist/plots/line/buildLineMarkers.d.ts +15 -0
  119. package/dist/plots/line/buildLineMarkers.js +57 -0
  120. package/dist/plots/pyramid/Plot.svelte +80 -121
  121. package/dist/plots/pyramid/Plot.svelte.d.ts +4 -5
  122. package/dist/plots/pyramid/ValueLabels.svelte +71 -25
  123. package/dist/plots/pyramid/ValueLabels.svelte.d.ts +11 -2
  124. package/dist/plots/pyramid/buildPyramidBarMarkers.d.ts +19 -0
  125. package/dist/plots/pyramid/buildPyramidBarMarkers.js +32 -0
  126. package/dist/plots/scatter/Plot.svelte +242 -0
  127. package/dist/{layout/plot/GridLayout.svelte.d.ts → plots/scatter/Plot.svelte.d.ts} +9 -7
  128. package/dist/plots/scatter/ValueLabels.svelte +149 -0
  129. package/dist/plots/{bar/BarSegments.svelte.d.ts → scatter/ValueLabels.svelte.d.ts} +17 -15
  130. package/dist/plots/scatter/buildScatterMarkers.d.ts +11 -0
  131. package/dist/plots/scatter/buildScatterMarkers.js +37 -0
  132. package/dist/plots/scatter/resolveRadiusPaddedDomain.d.ts +10 -0
  133. package/dist/plots/scatter/resolveRadiusPaddedDomain.js +23 -0
  134. package/dist/plots/utils/declutter.d.ts +55 -37
  135. package/dist/plots/utils/declutter.js +79 -64
  136. package/dist/plots/utils/geoAccessors.d.ts +1 -1
  137. package/dist/plots/utils/geoAccessors.js +1 -1
  138. package/dist/plots/utils/labelOverflow.svelte.d.ts +51 -0
  139. package/dist/plots/utils/labelOverflow.svelte.js +116 -0
  140. package/dist/plots/utils/legendDisabled.d.ts +1 -1
  141. package/dist/plots/utils/segments.d.ts +17 -10
  142. package/dist/plots/utils/segments.js +26 -16
  143. package/dist/types/charts/common.d.ts +3 -50
  144. package/dist/types/charts/props.d.ts +8 -8
  145. package/dist/types/configuration/styling.d.ts +26 -2
  146. package/dist/types/{plots/scales/geo.d.ts → layout/coordinates.d.ts} +33 -1
  147. package/dist/types/layout/facet.d.ts +41 -0
  148. package/dist/types/layout/geometry.d.ts +17 -0
  149. package/dist/types/layout/legend.d.ts +65 -1
  150. package/dist/types/{plots/axis.d.ts → layout/scales.d.ts} +11 -0
  151. package/dist/types/layout/styles.d.ts +115 -0
  152. package/dist/types/layout/timeline.d.ts +32 -0
  153. package/dist/types/layout/tooltip.d.ts +20 -1
  154. package/dist/types/markers/all.d.ts +11 -0
  155. package/dist/types/markers/all.js +1 -0
  156. package/dist/types/markers/base.d.ts +45 -0
  157. package/dist/types/markers/base.js +1 -0
  158. package/dist/types/markers/common.d.ts +64 -16
  159. package/dist/types/markers/geo.d.ts +75 -100
  160. package/dist/types/markers/line.d.ts +34 -0
  161. package/dist/types/markers/line.js +1 -0
  162. package/dist/types/markers/props.d.ts +1 -1
  163. package/dist/types/plots/data/common.d.ts +1 -1
  164. package/dist/types/plots/data/scatter.d.ts +13 -0
  165. package/dist/types/plots/data/scatter.js +1 -0
  166. package/dist/types/plots/props.d.ts +46 -74
  167. package/dist/types/plots/segments/common.d.ts +6 -12
  168. package/dist/types/plots/segments/config.d.ts +1 -1
  169. package/dist/types/plots/styling.d.ts +10 -0
  170. package/dist/{plots/utils → utils}/delta.d.ts +2 -2
  171. package/dist/{plots/utils → utils}/delta.js +1 -1
  172. package/dist/utils/edgeAwareAnchor.d.ts +37 -0
  173. package/dist/utils/edgeAwareAnchor.js +65 -0
  174. package/dist/utils/grouping.d.ts +1 -1
  175. package/dist/utils/interpolate.d.ts +2 -2
  176. package/package.json +3 -1
  177. package/dist/layout/geo/GeoLayout.svelte +0 -51
  178. package/dist/layout/geo/GeoLayout.svelte.d.ts +0 -24
  179. package/dist/layout/geo/resolveProjection.js +0 -48
  180. package/dist/layout/plot/GridLayout.svelte +0 -30
  181. package/dist/layout/plot/RuleLayout.svelte +0 -111
  182. package/dist/plots/bar/BarSegments.svelte +0 -69
  183. package/dist/types/charts/legend.d.ts +0 -60
  184. package/dist/types/plots/delta.d.ts +0 -19
  185. package/dist/types/plots/styles/common.d.ts +0 -52
  186. package/dist/types/plots/styles/geo.d.ts +0 -42
  187. /package/dist/{plots/geo → layout/coordinates}/projections/argentina.js +0 -0
  188. /package/dist/{plots/geo → layout/coordinates}/projections/fit.d.ts +0 -0
  189. /package/dist/{plots/geo → layout/coordinates}/projections/fit.js +0 -0
  190. /package/dist/{plots/geo → layout/coordinates}/rotate.svelte.d.ts +0 -0
  191. /package/dist/{plots/geo → layout/coordinates}/rotate.svelte.js +0 -0
  192. /package/dist/{plots/geo → layout/coordinates}/zoom.svelte.js +0 -0
  193. /package/dist/types/{charts/legend.js → layout/coordinates.js} +0 -0
  194. /package/dist/types/{plots/axis.js → layout/facet.js} +0 -0
  195. /package/dist/types/{plots/delta.js → layout/geometry.js} +0 -0
  196. /package/dist/types/{plots/scales/geo.js → layout/scales.js} +0 -0
  197. /package/dist/types/{plots/styles/common.js → layout/styles.js} +0 -0
  198. /package/dist/types/{plots/styles/geo.js → layout/timeline.js} +0 -0
@@ -1,11 +1,10 @@
1
1
  <script lang="ts">
2
- import { RuleX, RuleY } from 'svelteplot';
3
2
  import DotMarker from './DotMarker.svelte';
4
3
  import TextMarker from './TextMarker.svelte';
4
+ import RuleMarker from './RuleMarker.svelte';
5
5
  import { getConfiguration } from '../configuration/config.svelte';
6
6
  import type { MarkerProps } from '../types/markers/props';
7
- import type { AxisValue } from '../types/plots/axis';
8
- import type { DotStyle, FontStyle, StrokeStyle } from '../types/plots/styling';
7
+ import type { HoverMarkerConfig } from '../types/markers/common';
9
8
  import type { HoverDisplayPoint } from '../types/layout/tooltip';
10
9
 
11
10
  /**
@@ -14,31 +13,45 @@
14
13
  * correctly in every facet — that is what makes cross-facet sync work without
15
14
  * any pixel math. Draws optional x/y crosshair rules plus a dot + value label
16
15
  * for each matched point.
16
+ *
17
+ * Takes the raw `marker` config plus the couple of things it can't know on
18
+ * its own — `activePoint` (the specific matched point actually under the
19
+ * cursor, for the crosshair position; see `controller.svelte.ts`'s own doc
20
+ * comment) and whether the active hover strategy implies a crosshair on
21
+ * each axis by default — the same "component owns its own rendering"
22
+ * pattern `BarMarker`/`RuleMarker` follow. `activePoint`/
23
+ * `impliesCrosshairX`/`impliesCrosshairY` are all optional and default to
24
+ * "no crosshair".
17
25
  */
18
26
  interface Props extends MarkerProps<HoverDisplayPoint> {
19
- ruleX?: AxisValue | null;
20
- ruleY?: AxisValue | null;
21
- showLabels?: boolean;
22
- format?: (point: HoverDisplayPoint) => string;
23
- ruleStyle?: StrokeStyle;
24
- dotStyle?: DotStyle;
25
- fontStyle?: FontStyle;
27
+ /** Narrowed to just the fields this component reads — `HoverMarkerConfig` also carries routing/scoping fields (`series`/`scope`/`strategy`/`sync`) it has no use for. */
28
+ marker: Pick<HoverMarkerConfig, 'ruleX' | 'ruleY' | 'showLabels' | 'format' | 'ruleStyle' | 'dotStyle' | 'fontStyle'>;
29
+ activePoint?: HoverDisplayPoint | null;
30
+ impliesCrosshairX?: boolean;
31
+ impliesCrosshairY?: boolean;
26
32
  }
27
33
 
28
34
  let {
29
35
  data = [],
30
- ruleX = null,
31
- ruleY = null,
32
- showLabels = true,
33
- format,
34
- ruleStyle,
35
- dotStyle,
36
- fontStyle,
36
+ marker,
37
+ activePoint = null,
38
+ impliesCrosshairX = false,
39
+ impliesCrosshairY = false,
37
40
  seriesColor,
38
41
  }: Props = $props();
39
42
 
40
43
  const cfg = $derived(getConfiguration());
41
44
 
45
+ const showCrosshairX = $derived(marker.ruleX !== false && (impliesCrosshairX || marker.ruleX === true));
46
+ const showCrosshairY = $derived(marker.ruleY !== false && (impliesCrosshairY || marker.ruleY === true));
47
+ const ruleX = $derived(showCrosshairX ? (activePoint?.x ?? null) : null);
48
+ const ruleY = $derived(showCrosshairY ? (activePoint?.y ?? null) : null);
49
+ const showLabels = $derived(marker.showLabels ?? true);
50
+ const format = $derived(marker.format);
51
+ const ruleStyle = $derived(marker.ruleStyle);
52
+ const dotStyle = $derived(marker.dotStyle);
53
+ const fontStyle = $derived(marker.fontStyle);
54
+
42
55
  /** Explicit style wins; otherwise fall back to the series color, then the point's own resolved color. */
43
56
  const resolveColor = (explicit: string | undefined, point: HoverDisplayPoint) =>
44
57
  explicit ?? seriesColor ?? point.color;
@@ -81,29 +94,15 @@
81
94
  </script>
82
95
 
83
96
  {#if ruleX != null}
84
- <RuleX
85
- data={[{ v: ruleX }]}
86
- x={(d) => d.v}
87
- stroke={ruleStyle?.stroke ?? cfg.hover.rule.stroke}
88
- strokeOpacity={ruleStyle?.strokeOpacity ?? cfg.hover.rule.strokeOpacity}
89
- strokeWidth={ruleStyle?.strokeWidth ?? cfg.hover.rule.strokeWidth}
90
- strokeDasharray={ruleStyle?.strokeDasharray ?? cfg.hover.rule.strokeDasharray}
91
- />
97
+ <RuleMarker axis="x" value={ruleX} style={{ ...cfg.hover.rule, ...ruleStyle }} />
92
98
  {/if}
93
99
 
94
100
  {#if ruleY != null}
95
- <RuleY
96
- data={[{ v: ruleY }]}
97
- y={(d) => d.v}
98
- stroke={ruleStyle?.stroke ?? cfg.hover.rule.stroke}
99
- strokeOpacity={ruleStyle?.strokeOpacity ?? cfg.hover.rule.strokeOpacity}
100
- strokeWidth={ruleStyle?.strokeWidth ?? cfg.hover.rule.strokeWidth}
101
- strokeDasharray={ruleStyle?.strokeDasharray ?? cfg.hover.rule.strokeDasharray}
102
- />
101
+ <RuleMarker axis="y" value={ruleY} style={{ ...cfg.hover.rule, ...ruleStyle }} />
103
102
  {/if}
104
103
 
105
104
  {#if data.length > 0}
106
- {#each data as point (point.series ?? `${point.x}_${point.y}`)}
105
+ {#each data as point (`${point.series ?? ''}_${point.x}_${point.y}`)}
107
106
  <!-- Pixel nudge for plot kinds whose series position isn't fully captured
108
107
  by x/y alone (e.g. BarPlot's 'grouped' layout) — see HoverDisplayPoint.dx/dy. -->
109
108
  <g transform="translate({point.dx ?? 0}, {point.dy ?? 0})">
@@ -121,7 +120,7 @@
121
120
  </g>
122
121
  {/each}
123
122
  {#if showLabels}
124
- {#each data as point (point.series ?? `${point.x}_${point.y}`)}
123
+ {#each data as point (`${point.series ?? ''}_${point.x}_${point.y}`)}
125
124
  <g transform="translate({point.dx ?? 0}, {point.dy ?? 0})">
126
125
  <TextMarker
127
126
  data={[point]}
@@ -1,6 +1,5 @@
1
1
  import type { MarkerProps } from '../types/markers/props';
2
- import type { AxisValue } from '../types/plots/axis';
3
- import type { DotStyle, FontStyle, StrokeStyle } from '../types/plots/styling';
2
+ import type { HoverMarkerConfig } from '../types/markers/common';
4
3
  import type { HoverDisplayPoint } from '../types/layout/tooltip';
5
4
  /**
6
5
  * In-SVG hover highlight, rendered *inside* a `<Plot>`. Because it positions
@@ -8,15 +7,22 @@ import type { HoverDisplayPoint } from '../types/layout/tooltip';
8
7
  * correctly in every facet — that is what makes cross-facet sync work without
9
8
  * any pixel math. Draws optional x/y crosshair rules plus a dot + value label
10
9
  * for each matched point.
10
+ *
11
+ * Takes the raw `marker` config plus the couple of things it can't know on
12
+ * its own — `activePoint` (the specific matched point actually under the
13
+ * cursor, for the crosshair position; see `controller.svelte.ts`'s own doc
14
+ * comment) and whether the active hover strategy implies a crosshair on
15
+ * each axis by default — the same "component owns its own rendering"
16
+ * pattern `BarMarker`/`RuleMarker` follow. `activePoint`/
17
+ * `impliesCrosshairX`/`impliesCrosshairY` are all optional and default to
18
+ * "no crosshair".
11
19
  */
12
20
  interface Props extends MarkerProps<HoverDisplayPoint> {
13
- ruleX?: AxisValue | null;
14
- ruleY?: AxisValue | null;
15
- showLabels?: boolean;
16
- format?: (point: HoverDisplayPoint) => string;
17
- ruleStyle?: StrokeStyle;
18
- dotStyle?: DotStyle;
19
- fontStyle?: FontStyle;
21
+ /** Narrowed to just the fields this component reads — `HoverMarkerConfig` also carries routing/scoping fields (`series`/`scope`/`strategy`/`sync`) it has no use for. */
22
+ marker: Pick<HoverMarkerConfig, 'ruleX' | 'ruleY' | 'showLabels' | 'format' | 'ruleStyle' | 'dotStyle' | 'fontStyle'>;
23
+ activePoint?: HoverDisplayPoint | null;
24
+ impliesCrosshairX?: boolean;
25
+ impliesCrosshairY?: boolean;
20
26
  }
21
27
  declare const HoverMarker: import("svelte").Component<Props, {}, "">;
22
28
  type HoverMarker = ReturnType<typeof HoverMarker>;
@@ -0,0 +1,19 @@
1
+ <script lang="ts">
2
+ import { Line } from 'svelteplot';
3
+ import type { LineMarkerConfig } from '../types/markers/common';
4
+
5
+ /** Renders one `'line'` marker as a `<Line>` call — just the stroke. Endpoint dots are a separate `'dot'` marker. */
6
+ let { marker }: { marker: LineMarkerConfig } = $props();
7
+ </script>
8
+
9
+ <Line
10
+ data={marker.data}
11
+ x={marker.x}
12
+ y={marker.y}
13
+ stroke={marker.style?.stroke}
14
+ strokeWidth={marker.style?.strokeWidth}
15
+ strokeOpacity={marker.style?.strokeOpacity}
16
+ strokeDasharray={marker.style?.strokeDasharray}
17
+ strokeLinejoin={marker.style?.strokeLinejoin}
18
+ strokeLinecap={marker.style?.strokeLinecap}
19
+ />
@@ -0,0 +1,7 @@
1
+ import type { LineMarkerConfig } from '../types/markers/common';
2
+ type $$ComponentProps = {
3
+ marker: LineMarkerConfig;
4
+ };
5
+ declare const LineMarker: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ type LineMarker = ReturnType<typeof LineMarker>;
7
+ export default LineMarker;
@@ -0,0 +1,42 @@
1
+ <script lang="ts">
2
+ import { Geo } from 'svelteplot';
3
+ import { resolveAccessor } from '../plots/utils/accessors';
4
+ import { greatCircleInterpolate } from '../plots/utils/geoAccessors';
5
+ import type { GeoLinkMarkerConfig } from '../types/markers/geo';
6
+
7
+ /** Renders one `'link'` marker — geodesic-aware lines between point pairs, as a synthetic `LineString` fed through `<Geo>`. */
8
+ let { marker }: { marker: GeoLinkMarkerConfig } = $props();
9
+
10
+ const getX1 = $derived(resolveAccessor(marker.x1));
11
+ const getY1 = $derived(resolveAccessor(marker.y1));
12
+ const getX2 = $derived(resolveAccessor(marker.x2));
13
+ const getY2 = $derived(resolveAccessor(marker.y2));
14
+
15
+ const linkFeatures = $derived(
16
+ marker.data.map((d) => ({
17
+ type: 'Feature' as const,
18
+ properties: {},
19
+ geometry: {
20
+ type: 'LineString' as const,
21
+ coordinates:
22
+ marker.curve === 'linear'
23
+ ? [
24
+ [Number(getX1(d)), Number(getY1(d))],
25
+ [Number(getX2(d)), Number(getY2(d))],
26
+ ]
27
+ : greatCircleInterpolate(Number(getX1(d)), Number(getY1(d)), Number(getX2(d)), Number(getY2(d))),
28
+ },
29
+ })),
30
+ );
31
+ </script>
32
+
33
+ <!-- No `fill` prop: svelteplot treats any string as scale-worthy unless it's a real CSS color, so a literal `'none'` would run through the color scale instead of staying unfilled. Omitting it leaves svelteplot's own unfilled default in place. -->
34
+ <Geo
35
+ class="link"
36
+ data={linkFeatures}
37
+ stroke={marker.style?.stroke ?? 'currentColor'}
38
+ strokeWidth={marker.style?.strokeWidth ?? 1}
39
+ strokeOpacity={marker.style?.strokeOpacity}
40
+ strokeDasharray={marker.style?.strokeDasharray}
41
+ style="vector-effect: non-scaling-stroke"
42
+ />
@@ -0,0 +1,7 @@
1
+ import type { GeoLinkMarkerConfig } from '../types/markers/geo';
2
+ type $$ComponentProps = {
3
+ marker: GeoLinkMarkerConfig;
4
+ };
5
+ declare const LinkMarker: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ type LinkMarker = ReturnType<typeof LinkMarker>;
7
+ export default LinkMarker;
@@ -0,0 +1,24 @@
1
+ <script lang="ts">
2
+ import { RuleX, RuleY } from 'svelteplot';
3
+ import type { AxisValue } from '../types/layout/scales';
4
+ import type { StrokeStyle } from '../types/plots/styling';
5
+
6
+ /**
7
+ * A single vertical (`axis: 'x'`) or horizontal (`axis: 'y'`) reference
8
+ * line at `value` — shared by author-configured `'rule'` markers and
9
+ * `HoverMarker`'s crosshair. Falls back to `'currentColor'`/`1` when the
10
+ * caller supplies no style.
11
+ */
12
+ let { axis, value, style }: { axis: 'x' | 'y'; value: AxisValue; style?: StrokeStyle } = $props();
13
+
14
+ const RuleMark = $derived(axis === 'x' ? RuleX : RuleY);
15
+ </script>
16
+
17
+ <RuleMark
18
+ data={[{ v: value }]}
19
+ {...axis === 'x' ? { x: (d: { v: AxisValue }) => d.v } : { y: (d: { v: AxisValue }) => d.v }}
20
+ stroke={style?.stroke ?? 'currentColor'}
21
+ strokeWidth={style?.strokeWidth ?? 1}
22
+ strokeOpacity={style?.strokeOpacity ?? 1}
23
+ strokeDasharray={style?.strokeDasharray}
24
+ />
@@ -0,0 +1,10 @@
1
+ import type { AxisValue } from '../types/layout/scales';
2
+ import type { StrokeStyle } from '../types/plots/styling';
3
+ type $$ComponentProps = {
4
+ axis: 'x' | 'y';
5
+ value: AxisValue;
6
+ style?: StrokeStyle;
7
+ };
8
+ declare const RuleMarker: import("svelte").Component<$$ComponentProps, {}, "">;
9
+ type RuleMarker = ReturnType<typeof RuleMarker>;
10
+ export default RuleMarker;
@@ -0,0 +1,15 @@
1
+ <script lang="ts">
2
+ import { Sphere } from 'svelteplot';
3
+ import type { GeoSphereMarkerConfig } from '../types/markers/geo';
4
+
5
+ /** Renders one `'sphere'` marker — the outer globe outline. */
6
+ let { marker }: { marker: GeoSphereMarkerConfig } = $props();
7
+ </script>
8
+
9
+ <Sphere
10
+ fill={marker.style?.fill}
11
+ fillOpacity={marker.style?.fillOpacity}
12
+ stroke={marker.style?.stroke ?? 'currentColor'}
13
+ strokeWidth={marker.style?.strokeWidth ?? 1}
14
+ style="vector-effect: non-scaling-stroke"
15
+ />
@@ -0,0 +1,7 @@
1
+ import type { GeoSphereMarkerConfig } from '../types/markers/geo';
2
+ type $$ComponentProps = {
3
+ marker: GeoSphereMarkerConfig;
4
+ };
5
+ declare const SphereMarker: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ type SphereMarker = ReturnType<typeof SphereMarker>;
7
+ export default SphereMarker;
@@ -1,7 +1,7 @@
1
1
  <script lang="ts" generics="TData = Record<string, unknown>">
2
2
  import { Text } from 'svelteplot';
3
3
  import type { MarkerProps } from '../types/markers/props';
4
- import type { AxisValue } from '../types/plots/axis';
4
+ import type { AxisValue } from '../types/layout/scales';
5
5
  import type { FontStyle } from '../types/plots/styling';
6
6
 
7
7
  interface Props extends MarkerProps<TData> {
@@ -1,5 +1,5 @@
1
1
  import type { MarkerProps } from '../types/markers/props';
2
- import type { AxisValue } from '../types/plots/axis';
2
+ import type { AxisValue } from '../types/layout/scales';
3
3
  import type { FontStyle } from '../types/plots/styling';
4
4
  declare function $$render<TData = Record<string, unknown>>(): {
5
5
  props: MarkerProps<TData> & {
@@ -0,0 +1,20 @@
1
+ <script lang="ts">
2
+ import { Vector } from 'svelteplot';
3
+ import type { GeoVectorMarkerConfig } from '../types/markers/geo';
4
+
5
+ /** Renders one `'vector'` marker — arrows/spikes at points. */
6
+ let { marker }: { marker: GeoVectorMarkerConfig } = $props();
7
+ </script>
8
+
9
+ <Vector
10
+ data={marker.data}
11
+ x={marker.x}
12
+ y={marker.y}
13
+ length={marker.length}
14
+ rotate={marker.rotate}
15
+ shape={marker.shape ?? 'arrow'}
16
+ anchor={marker.anchor}
17
+ fill={marker.style?.fill ?? 'currentColor'}
18
+ stroke={marker.style?.stroke}
19
+ strokeWidth={marker.style?.strokeWidth}
20
+ />
@@ -0,0 +1,7 @@
1
+ import type { GeoVectorMarkerConfig } from '../types/markers/geo';
2
+ type $$ComponentProps = {
3
+ marker: GeoVectorMarkerConfig;
4
+ };
5
+ declare const VectorMarker: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ type VectorMarker = ReturnType<typeof VectorMarker>;
7
+ export default VectorMarker;
@@ -4,12 +4,13 @@
4
4
  import { insetBox } from './insetLayout';
5
5
  import { filterGeometryParts } from '../../plots/utils/geoAccessors';
6
6
  import TooltipLayout from '../../layout/tooltip/TooltipLayout.svelte';
7
- import type { GeoInsetMarker } from '../../types/markers/geo';
7
+ import type { GeoInsetMarkerConfig } from '../../types/markers/geo';
8
8
  import type { GeoFeature } from '../../types/plots/data/geo';
9
+ import type { TooltipAnchorX, TooltipAnchorY } from '../../types/layout/tooltip';
9
10
 
10
11
  /**
11
12
  * A small, independently-projected map panel anchored to a corner/edge of
12
- * the plot — see `GeoInsetMarker`'s doc comment. Renders raw `<path>`s via
13
+ * the plot — see `GeoInsetMarkerConfig`'s doc comment. Renders raw `<path>`s via
13
14
  * its own `d3-geo` `geoPath`, deliberately not svelteplot's `<Geo>` mark:
14
15
  * that mark is bound to the plot's *shared* projection scale, but an inset
15
16
  * needs its own, independently fit to just what it's showing.
@@ -22,8 +23,10 @@
22
23
  left = 0,
23
24
  top = 0,
24
25
  defaultFill,
26
+ tooltipAnchorX,
27
+ tooltipAnchorY,
25
28
  }: {
26
- marker: GeoInsetMarker<TProps>;
29
+ marker: GeoInsetMarkerConfig<TProps>;
27
30
  /**
28
31
  * The plot's own already-tagged features (`__id` set), with full,
29
32
  * unreduced geometry regardless of the plot's own `excludeParts` — used
@@ -45,6 +48,9 @@
45
48
  left?: number;
46
49
  top?: number;
47
50
  defaultFill: string;
51
+ /** The plot's own top-level `tooltip.anchorX`/`anchorY` — the fallback this inset's own tooltip inherits when its own is unset, before the system default. */
52
+ tooltipAnchorX?: TooltipAnchorX;
53
+ tooltipAnchorY?: TooltipAnchorY;
48
54
  } = $props();
49
55
 
50
56
  const insetFeatures = $derived.by((): GeoFeature<Record<string, unknown>>[] => {
@@ -84,44 +90,33 @@
84
90
  return geoPath(projection);
85
91
  });
86
92
 
87
- /**
88
- * Nearest-feature hover, local to this inset only — mirrors the main
89
- * map's own "always nearest feature centroid" behaviour (see `Plot.svelte`),
90
- * but computed against this inset's own fitted `path`/projection instead
91
- * of the plot's shared one, since svelteplot's `<Pointer>` (which drives
92
- * the main map's hover) only ever matches the main projection's own
93
- * feature positions — it has no way to reach content an inset draws at a
94
- * wholly different scale/location.
95
- */
96
- const centroids = $derived.by(() => {
97
- if (!path) return [];
98
- return insetFeatures.map((f) => ({ feature: f, centroid: path.centroid(f as GeoJSON.Feature) }));
99
- });
100
-
101
93
  let hovered = $state<{ feature: GeoFeature<Record<string, unknown>>; x: number; y: number } | null>(null);
102
94
 
103
- // Any point within the inset box always matches its nearest feature —
104
- // there's no reason for a hover inside a small, self-contained panel to
105
- // ever come up empty, so the threshold is just the box's own diagonal.
106
- const maxDistance = $derived(Math.hypot(box.width, box.height));
95
+ /**
96
+ * Purely a coordinate reference (`pointer-events: none` never itself a
97
+ * hover target) sized exactly to the inset's own box, so `onInsetPointer*`
98
+ * below can convert a screen-space pointer event into the same box-local
99
+ * `x`/`y` space `TooltipLayout`'s `bounds` expects, the same way
100
+ * `BasePlotLayout`'s own cursor tracking does for the main map.
101
+ */
102
+ let boxRectEl = $state<SVGRectElement>();
107
103
 
108
- function onInsetPointerMove(e: PointerEvent) {
109
- const rect = (e.currentTarget as SVGRectElement).getBoundingClientRect();
110
- const x = e.clientX - rect.left;
111
- const y = e.clientY - rect.top;
112
- let nearest: (typeof centroids)[number] | null = null;
113
- let nearestDist = Infinity;
114
- for (const c of centroids) {
115
- const d = Math.hypot(c.centroid[0] - x, c.centroid[1] - y);
116
- if (d < nearestDist) {
117
- nearestDist = d;
118
- nearest = c;
119
- }
120
- }
121
- hovered = nearest && nearestDist <= maxDistance ? { feature: nearest.feature, x, y } : null;
104
+ /**
105
+ * Which exact feature `<path>` the browser's own SVG hit-testing resolved
106
+ * the event to mirrors the main map's own `<Geo onpointerenter>` (see
107
+ * `Plot.svelte`) rather than approximating it by nearest centroid
108
+ * distance, which used to make hover pick the wrong (if geometrically
109
+ * nearer-by-centroid) neighboring feature, exactly the bug that fix
110
+ * addressed for the main map.
111
+ */
112
+ function onInsetFeaturePointer(e: PointerEvent, f: GeoFeature<Record<string, unknown>>) {
113
+ const rect = boxRectEl?.getBoundingClientRect();
114
+ const x = e.clientX - (rect?.left ?? 0);
115
+ const y = e.clientY - (rect?.top ?? 0);
116
+ hovered = { feature: f, x, y };
122
117
  }
123
118
 
124
- function onInsetPointerLeave() {
119
+ function onInsetFeatureLeave() {
125
120
  hovered = null;
126
121
  }
127
122
  </script>
@@ -129,6 +124,7 @@
129
124
  {#if path}
130
125
  <g class="dct-geo-inset" transform="translate({box.left + left}, {box.top + top})">
131
126
  {#each insetFeatures as f, i (i)}
127
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
132
128
  <path
133
129
  d={path(f as GeoJSON.Feature) ?? undefined}
134
130
  fill={marker.style?.fill ?? defaultFill}
@@ -136,19 +132,14 @@
136
132
  stroke={marker.style?.stroke ?? 'currentColor'}
137
133
  stroke-width={marker.style?.strokeWidth ?? 0.5}
138
134
  style="vector-effect: non-scaling-stroke"
135
+ onpointerenter={marker.tooltip ? (e: PointerEvent) => onInsetFeaturePointer(e, f) : undefined}
136
+ onpointermove={marker.tooltip ? (e: PointerEvent) => onInsetFeaturePointer(e, f) : undefined}
137
+ onpointerleave={marker.tooltip ? onInsetFeatureLeave : undefined}
139
138
  />
140
139
  {/each}
141
140
  {#if marker.tooltip}
142
141
  <!-- svelte-ignore a11y_no_static_element_interactions -->
143
- <rect
144
- x={0}
145
- y={0}
146
- width={box.width}
147
- height={box.height}
148
- fill="transparent"
149
- onpointermove={onInsetPointerMove}
150
- onpointerleave={onInsetPointerLeave}
151
- />
142
+ <rect x={0} y={0} width={box.width} height={box.height} fill="transparent" pointer-events="none" bind:this={boxRectEl} />
152
143
  {/if}
153
144
  {#if marker.tooltip}
154
145
  {@const tooltip = marker.tooltip}
@@ -162,6 +153,8 @@
162
153
  rows={hovered ? [hovered.feature] : []}
163
154
  format={tooltip.format}
164
155
  content={tooltip.content}
156
+ anchorX={tooltip.anchorX ?? tooltipAnchorX}
157
+ anchorY={tooltip.anchorY ?? tooltipAnchorY}
165
158
  />
166
159
  </div>
167
160
  </foreignObject>
@@ -1,8 +1,9 @@
1
- import type { GeoInsetMarker } from '../../types/markers/geo';
1
+ import type { GeoInsetMarkerConfig } from '../../types/markers/geo';
2
2
  import type { GeoFeature } from '../../types/plots/data/geo';
3
+ import type { TooltipAnchorX, TooltipAnchorY } from '../../types/layout/tooltip';
3
4
  declare function $$render<TProps extends Record<string, unknown>>(): {
4
5
  props: {
5
- marker: GeoInsetMarker<TProps>;
6
+ marker: GeoInsetMarkerConfig<TProps>;
6
7
  /**
7
8
  * The plot's own already-tagged features (`__id` set), with full,
8
9
  * unreduced geometry regardless of the plot's own `excludeParts` — used
@@ -26,6 +27,9 @@ declare function $$render<TProps extends Record<string, unknown>>(): {
26
27
  left?: number;
27
28
  top?: number;
28
29
  defaultFill: string;
30
+ /** The plot's own top-level `tooltip.anchorX`/`anchorY` — the fallback this inset's own tooltip inherits when its own is unset, before the system default. */
31
+ tooltipAnchorX?: TooltipAnchorX;
32
+ tooltipAnchorY?: TooltipAnchorY;
29
33
  };
30
34
  exports: {};
31
35
  bindings: "";