@fundar/data-chart-telling 0.0.25 → 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.
Files changed (170) hide show
  1. package/dist/charts/bar/Chart.svelte +2 -0
  2. package/dist/charts/heatmap/Chart.svelte +3 -1
  3. package/dist/charts/heatmap/Chart.svelte.d.ts +1 -2
  4. package/dist/charts/line/Chart.svelte +2 -0
  5. package/dist/charts/pyramid/Chart.svelte +3 -1
  6. package/dist/charts/pyramid/Chart.svelte.d.ts +1 -2
  7. package/dist/charts/scatter/Chart.svelte +95 -0
  8. package/dist/charts/scatter/Chart.svelte.d.ts +28 -0
  9. package/dist/configuration/config.svelte.js +2 -0
  10. package/dist/configuration/themes/index.d.ts +48 -0
  11. package/dist/index.d.ts +20 -14
  12. package/dist/index.js +9 -3
  13. package/dist/layout/coordinates/CoordinatesLayout.svelte +95 -0
  14. package/dist/layout/{plot/RuleLayout.svelte.d.ts → coordinates/CoordinatesLayout.svelte.d.ts} +13 -16
  15. package/dist/layout/coordinates/margins.d.ts +16 -0
  16. package/dist/layout/coordinates/margins.js +11 -0
  17. package/dist/{plots/geo → layout/coordinates}/projections/argentina.d.ts +1 -1
  18. package/dist/layout/{geo → coordinates}/resolveProjection.d.ts +1 -1
  19. package/dist/layout/coordinates/resolveProjection.js +24 -0
  20. package/dist/{plots/geo → layout/coordinates}/zoom.svelte.d.ts +1 -1
  21. package/dist/layout/geometry/GeometryLayout.svelte +231 -0
  22. package/dist/layout/geometry/GeometryLayout.svelte.d.ts +62 -0
  23. package/dist/layout/plot/BasePlotLayout.svelte +142 -155
  24. package/dist/layout/plot/BasePlotLayout.svelte.d.ts +61 -51
  25. package/dist/layout/plot/margins.d.ts +0 -16
  26. package/dist/layout/plot/margins.js +0 -11
  27. package/dist/layout/{plot/AxisLayout.svelte → scales/ScalesLayout.svelte} +23 -16
  28. package/dist/layout/{plot/AxisLayout.svelte.d.ts → scales/ScalesLayout.svelte.d.ts} +4 -5
  29. package/dist/layout/scales/buildScale.d.ts +8 -0
  30. package/dist/layout/scales/buildScale.js +43 -0
  31. package/dist/layout/styles/StylesLayout.svelte +75 -0
  32. package/dist/layout/styles/StylesLayout.svelte.d.ts +15 -0
  33. package/dist/{plots/geo → layout/styles}/TileLayer.svelte +2 -2
  34. package/dist/{plots/geo → layout/styles}/TileLayer.svelte.d.ts +1 -1
  35. package/dist/layout/tooltip/Tooltip.svelte +16 -20
  36. package/dist/layout/tooltip/Tooltip.svelte.d.ts +5 -0
  37. package/dist/layout/tooltip/TooltipLayout.svelte +7 -1
  38. package/dist/layout/tooltip/TooltipLayout.svelte.d.ts +4 -0
  39. package/dist/layout/tooltip/controller.svelte.d.ts +4 -5
  40. package/dist/layout/tooltip/controller.svelte.js +28 -16
  41. package/dist/layout/tooltip/resolveTooltipPlacement.d.ts +24 -0
  42. package/dist/layout/tooltip/resolveTooltipPlacement.js +49 -0
  43. package/dist/layout/tooltip/utils.d.ts +27 -19
  44. package/dist/layout/tooltip/utils.js +16 -15
  45. package/dist/markers/BarMarker.svelte +92 -0
  46. package/dist/markers/BarMarker.svelte.d.ts +7 -0
  47. package/dist/markers/CellMarker.svelte +21 -0
  48. package/dist/markers/CellMarker.svelte.d.ts +7 -0
  49. package/dist/markers/ContourMarker.svelte +28 -0
  50. package/dist/markers/ContourMarker.svelte.d.ts +7 -0
  51. package/dist/markers/DeltaMarker.svelte +32 -39
  52. package/dist/markers/DeltaMarker.svelte.d.ts +4 -5
  53. package/dist/markers/DotMarker.svelte +35 -6
  54. package/dist/markers/DotMarker.svelte.d.ts +11 -2
  55. package/dist/markers/GeoFeaturesMarker.svelte +19 -0
  56. package/dist/markers/GeoFeaturesMarker.svelte.d.ts +7 -0
  57. package/dist/markers/GeoHoverMarker.svelte +25 -0
  58. package/dist/markers/GeoHoverMarker.svelte.d.ts +9 -0
  59. package/dist/markers/GraticuleMarker.svelte +18 -0
  60. package/dist/markers/GraticuleMarker.svelte.d.ts +7 -0
  61. package/dist/markers/HoverMarker.svelte +32 -33
  62. package/dist/markers/HoverMarker.svelte.d.ts +15 -9
  63. package/dist/markers/LineMarker.svelte +19 -0
  64. package/dist/markers/LineMarker.svelte.d.ts +7 -0
  65. package/dist/markers/LinkMarker.svelte +42 -0
  66. package/dist/markers/LinkMarker.svelte.d.ts +7 -0
  67. package/dist/markers/RuleMarker.svelte +24 -0
  68. package/dist/markers/RuleMarker.svelte.d.ts +10 -0
  69. package/dist/markers/SphereMarker.svelte +15 -0
  70. package/dist/markers/SphereMarker.svelte.d.ts +7 -0
  71. package/dist/markers/TextMarker.svelte +1 -1
  72. package/dist/markers/TextMarker.svelte.d.ts +1 -1
  73. package/dist/markers/VectorMarker.svelte +20 -0
  74. package/dist/markers/VectorMarker.svelte.d.ts +7 -0
  75. package/dist/markers/inset/InsetMarker.svelte +38 -45
  76. package/dist/markers/inset/InsetMarker.svelte.d.ts +6 -2
  77. package/dist/plots/bar/Plot.svelte +54 -84
  78. package/dist/plots/bar/Plot.svelte.d.ts +4 -5
  79. package/dist/plots/bar/ValueLabels.svelte +1 -1
  80. package/dist/plots/bar/ValueLabels.svelte.d.ts +1 -1
  81. package/dist/plots/bar/buildBarMarkers.d.ts +30 -0
  82. package/dist/plots/bar/buildBarMarkers.js +100 -0
  83. package/dist/plots/bar/layout.svelte.d.ts +1 -2
  84. package/dist/plots/bar/layout.svelte.js +1 -1
  85. package/dist/plots/geo/Plot.svelte +113 -387
  86. package/dist/plots/geo/Plot.svelte.d.ts +5 -4
  87. package/dist/plots/geo/buildGeoMarkers.d.ts +33 -0
  88. package/dist/plots/geo/buildGeoMarkers.js +47 -0
  89. package/dist/plots/heatmap/Plot.svelte +24 -49
  90. package/dist/plots/heatmap/Plot.svelte.d.ts +4 -5
  91. package/dist/plots/heatmap/ValueLabels.svelte +2 -2
  92. package/dist/plots/heatmap/ValueLabels.svelte.d.ts +2 -2
  93. package/dist/plots/heatmap/buildCellMarkers.d.ts +21 -0
  94. package/dist/plots/heatmap/buildCellMarkers.js +25 -0
  95. package/dist/plots/line/Plot.svelte +68 -141
  96. package/dist/plots/line/Plot.svelte.d.ts +4 -4
  97. package/dist/plots/line/ValueLabels.svelte +29 -52
  98. package/dist/plots/line/ValueLabels.svelte.d.ts +6 -1
  99. package/dist/plots/line/buildLineMarkers.d.ts +15 -0
  100. package/dist/plots/line/buildLineMarkers.js +57 -0
  101. package/dist/plots/pyramid/Plot.svelte +41 -117
  102. package/dist/plots/pyramid/Plot.svelte.d.ts +4 -5
  103. package/dist/plots/pyramid/ValueLabels.svelte +1 -1
  104. package/dist/plots/pyramid/ValueLabels.svelte.d.ts +1 -1
  105. package/dist/plots/pyramid/buildPyramidBarMarkers.d.ts +19 -0
  106. package/dist/plots/pyramid/buildPyramidBarMarkers.js +32 -0
  107. package/dist/plots/scatter/Plot.svelte +206 -0
  108. package/dist/plots/{bar/BarSegments.svelte.d.ts → scatter/Plot.svelte.d.ts} +9 -20
  109. package/dist/plots/scatter/ValueLabels.svelte +106 -0
  110. package/dist/{layout/plot/GridLayout.svelte.d.ts → plots/scatter/ValueLabels.svelte.d.ts} +11 -5
  111. package/dist/plots/scatter/buildScatterMarkers.d.ts +11 -0
  112. package/dist/plots/scatter/buildScatterMarkers.js +37 -0
  113. package/dist/plots/scatter/resolveRadiusPaddedDomain.d.ts +10 -0
  114. package/dist/plots/scatter/resolveRadiusPaddedDomain.js +23 -0
  115. package/dist/plots/utils/declutter.d.ts +55 -37
  116. package/dist/plots/utils/declutter.js +79 -64
  117. package/dist/plots/utils/geoAccessors.d.ts +1 -1
  118. package/dist/plots/utils/geoAccessors.js +1 -1
  119. package/dist/plots/utils/segments.d.ts +17 -10
  120. package/dist/plots/utils/segments.js +26 -16
  121. package/dist/types/charts/common.d.ts +1 -1
  122. package/dist/types/charts/props.d.ts +5 -6
  123. package/dist/types/configuration/styling.d.ts +7 -2
  124. package/dist/types/{plots/scales/geo.d.ts → layout/coordinates.d.ts} +33 -1
  125. package/dist/types/layout/geometry.d.ts +17 -0
  126. package/dist/types/{plots/axis.d.ts → layout/scales.d.ts} +11 -0
  127. package/dist/types/layout/styles.d.ts +126 -0
  128. package/dist/types/layout/tooltip.d.ts +20 -1
  129. package/dist/types/markers/all.d.ts +11 -0
  130. package/dist/types/markers/base.d.ts +45 -0
  131. package/dist/types/markers/base.js +1 -0
  132. package/dist/types/markers/common.d.ts +64 -16
  133. package/dist/types/markers/geo.d.ts +75 -100
  134. package/dist/types/markers/line.d.ts +34 -0
  135. package/dist/types/markers/line.js +1 -0
  136. package/dist/types/markers/props.d.ts +1 -1
  137. package/dist/types/plots/data/common.d.ts +1 -1
  138. package/dist/types/plots/data/scatter.d.ts +13 -0
  139. package/dist/types/plots/data/scatter.js +1 -0
  140. package/dist/types/plots/props.d.ts +46 -74
  141. package/dist/types/plots/segments/common.d.ts +6 -12
  142. package/dist/types/plots/segments/config.d.ts +1 -1
  143. package/dist/types/plots/styling.d.ts +10 -0
  144. package/dist/{plots/utils → utils}/delta.d.ts +2 -2
  145. package/dist/{plots/utils → utils}/delta.js +1 -1
  146. package/dist/utils/edgeAwareAnchor.d.ts +37 -0
  147. package/dist/utils/edgeAwareAnchor.js +65 -0
  148. package/dist/utils/grouping.d.ts +1 -1
  149. package/dist/utils/interpolate.d.ts +1 -1
  150. package/package.json +3 -1
  151. package/dist/layout/geo/GeoLayout.svelte +0 -51
  152. package/dist/layout/geo/GeoLayout.svelte.d.ts +0 -24
  153. package/dist/layout/geo/resolveProjection.js +0 -48
  154. package/dist/layout/plot/GridLayout.svelte +0 -30
  155. package/dist/layout/plot/RuleLayout.svelte +0 -111
  156. package/dist/plots/bar/BarSegments.svelte +0 -69
  157. package/dist/types/plots/delta.d.ts +0 -19
  158. package/dist/types/plots/styles/common.d.ts +0 -52
  159. package/dist/types/plots/styles/geo.d.ts +0 -42
  160. /package/dist/{plots/geo → layout/coordinates}/projections/argentina.js +0 -0
  161. /package/dist/{plots/geo → layout/coordinates}/projections/fit.d.ts +0 -0
  162. /package/dist/{plots/geo → layout/coordinates}/projections/fit.js +0 -0
  163. /package/dist/{plots/geo → layout/coordinates}/rotate.svelte.d.ts +0 -0
  164. /package/dist/{plots/geo → layout/coordinates}/rotate.svelte.js +0 -0
  165. /package/dist/{plots/geo → layout/coordinates}/zoom.svelte.js +0 -0
  166. /package/dist/types/{plots/axis.js → layout/coordinates.js} +0 -0
  167. /package/dist/types/{plots/delta.js → layout/geometry.js} +0 -0
  168. /package/dist/types/{plots/scales/geo.js → layout/scales.js} +0 -0
  169. /package/dist/types/{plots/styles/common.js → layout/styles.js} +0 -0
  170. /package/dist/types/{plots/styles/geo.js → markers/all.js} +0 -0
@@ -24,11 +24,11 @@ export function matchByStrategy(points, hover) {
24
24
  (activeSeries == null || p.series == null || p.series === activeSeries));
25
25
  }
26
26
  /** Whether the strategy implies an x crosshair rule by default. */
27
- export function impliesRuleX(strategy) {
27
+ export function impliesCrosshairX(strategy) {
28
28
  return strategy === 'x' || strategy === 'punctual';
29
29
  }
30
30
  /** Whether the strategy implies a y crosshair rule by default. */
31
- export function impliesRuleY(strategy) {
31
+ export function impliesCrosshairY(strategy) {
32
32
  return strategy === 'y' || strategy === 'punctual';
33
33
  }
34
34
  /** Normalize the author-facing prop into a resolved object. */
@@ -44,29 +44,30 @@ export function resolveTooltip(tooltip, defaultStrategy) {
44
44
  format: tooltip.format,
45
45
  series: tooltip.series,
46
46
  content: tooltip.content,
47
+ anchorX: tooltip.anchorX,
48
+ anchorY: tooltip.anchorY,
47
49
  };
48
50
  }
49
51
  /**
50
- * Resolve the strategy that should drive the shared hover store:
51
- * the tooltip's own `strategy` wins when tooltip text is enabled, else the first
52
- * hover marker's `strategy`, else the chart kind's default.
52
+ * Resolve the strategy that should drive the shared hover store: the
53
+ * tooltip's own `strategy` wins, else the first hover marker's `strategy`,
54
+ * else the chart kind's default. Generic over the caller's own marker union,
55
+ * like {@link findHoverMarker}.
53
56
  */
54
57
  export function resolveHoverStrategy(tooltipStrategy, markers, defaultStrategy) {
55
- return tooltipStrategy ?? findHoverMarker(markers)?.strategy ?? defaultStrategy;
58
+ const marker = findHoverMarker(markers);
59
+ return tooltipStrategy ?? marker?.strategy ?? defaultStrategy;
56
60
  }
57
- /**
58
- * Resolve whether the hover should be broadcast across facets:
59
- * the tooltip's own `sync` wins when tooltip text is enabled, else the first
60
- * hover marker's `sync`, else false.
61
- */
61
+ /** Resolve whether the hover should be broadcast across facets. Generic — see {@link resolveHoverStrategy}. */
62
62
  export function resolveHoverSync(tooltipSync, markers) {
63
- return tooltipSync ?? findHoverMarker(markers)?.sync ?? false;
63
+ const marker = findHoverMarker(markers);
64
+ return tooltipSync ?? marker?.sync ?? false;
64
65
  }
65
- /** Whether any marker in the list is a hover marker. */
66
+ /** Whether any marker in the list is a hover marker — axis-based (`'hover'`) or geo (`'geo-hover'`). */
66
67
  export function hasHoverMarker(markers) {
67
- return (markers ?? []).some((m) => m.type === 'hover');
68
+ return (markers ?? []).some((m) => m.type === 'hover' || m.type === 'geo-hover');
68
69
  }
69
- /** First hover marker in the list, if any. */
70
+ /** First hover marker in the list, if any — generic over the caller's own marker union. */
70
71
  export function findHoverMarker(markers) {
71
72
  return (markers ?? []).find((m) => m.type === 'hover');
72
73
  }
@@ -0,0 +1,92 @@
1
+ <script lang="ts">
2
+ import { BarX, BarY, usePlot } from 'svelteplot';
3
+ import type { BarMarkerConfig } from '../types/markers/common';
4
+
5
+ /**
6
+ * Renders one `'bar'` marker — `role: 'segment'` is a visible bar
7
+ * (`<BarX>`/`<BarY>`, per `isHorizontal`); `role: 'hitArea'` is an
8
+ * invisible hit region for one category, resolved against the live scale
9
+ * via `usePlot()`.
10
+ */
11
+ let { marker }: { marker: BarMarkerConfig } = $props();
12
+
13
+ const plot = usePlot();
14
+ function categoryScaleFor(isHorizontal: boolean) {
15
+ return isHorizontal ? plot.scales.y : plot.scales.x;
16
+ }
17
+ function valueScaleFor(isHorizontal: boolean) {
18
+ return isHorizontal ? plot.scales.x : plot.scales.y;
19
+ }
20
+ function valueExtentFor(isHorizontal: boolean): [number, number] {
21
+ const range = valueScaleFor(isHorizontal)?.fn?.range?.();
22
+ if (!range || range.length < 2) return [0, 0];
23
+ const a = Number(range[0]);
24
+ const b = Number(range[range.length - 1]);
25
+ return [Math.min(a, b), Math.max(a, b)];
26
+ }
27
+ </script>
28
+
29
+ {#if marker.role === 'segment'}
30
+ {#if marker.isHorizontal}
31
+ <BarX
32
+ data={marker.data}
33
+ y={marker.y}
34
+ x1={marker.x1}
35
+ x2={marker.x2}
36
+ insetTop={marker.insetTop}
37
+ insetBottom={marker.insetBottom}
38
+ fill={marker.style?.fill}
39
+ fillOpacity={marker.style?.fillOpacity}
40
+ stroke={marker.style?.stroke}
41
+ strokeWidth={marker.style?.strokeWidth}
42
+ strokeOpacity={marker.style?.strokeOpacity}
43
+ strokeDasharray={marker.style?.strokeDasharray}
44
+ borderRadius={marker.style?.borderRadius}
45
+ />
46
+ {:else}
47
+ <BarY
48
+ data={marker.data}
49
+ x={marker.x}
50
+ y1={marker.y1}
51
+ y2={marker.y2}
52
+ insetLeft={marker.insetLeft}
53
+ insetRight={marker.insetRight}
54
+ fill={marker.style?.fill}
55
+ fillOpacity={marker.style?.fillOpacity}
56
+ stroke={marker.style?.stroke}
57
+ strokeWidth={marker.style?.strokeWidth}
58
+ strokeOpacity={marker.style?.strokeOpacity}
59
+ strokeDasharray={marker.style?.strokeDasharray}
60
+ borderRadius={marker.style?.borderRadius}
61
+ />
62
+ {/if}
63
+ {:else}
64
+ {@const categoryScale = categoryScaleFor(marker.isHorizontal)}
65
+ {#if categoryScale?.type === 'band'}
66
+ {@const bandwidth = categoryScale.fn.bandwidth()}
67
+ {@const bandStart = Number(categoryScale.fn(marker.category as never) ?? 0)}
68
+ {@const [valueMin, valueMax] = valueExtentFor(marker.isHorizontal)}
69
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
70
+ {#if marker.isHorizontal}
71
+ <rect
72
+ x={valueMin}
73
+ y={bandStart}
74
+ width={Math.max(0, valueMax - valueMin)}
75
+ height={bandwidth}
76
+ fill="transparent"
77
+ onpointerenter={marker.onpointerenter}
78
+ onpointerleave={marker.onpointerleave}
79
+ />
80
+ {:else}
81
+ <rect
82
+ x={bandStart}
83
+ y={valueMin}
84
+ width={bandwidth}
85
+ height={Math.max(0, valueMax - valueMin)}
86
+ fill="transparent"
87
+ onpointerenter={marker.onpointerenter}
88
+ onpointerleave={marker.onpointerleave}
89
+ />
90
+ {/if}
91
+ {/if}
92
+ {/if}
@@ -0,0 +1,7 @@
1
+ import type { BarMarkerConfig } from '../types/markers/common';
2
+ type $$ComponentProps = {
3
+ marker: BarMarkerConfig;
4
+ };
5
+ declare const BarMarker: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ type BarMarker = ReturnType<typeof BarMarker>;
7
+ export default BarMarker;
@@ -0,0 +1,21 @@
1
+ <script lang="ts">
2
+ import { Cell } from 'svelteplot';
3
+ import type { CellMarkerConfig } from '../types/markers/common';
4
+
5
+ /** Renders one `'cell'` marker as a `<Cell>` call. */
6
+ let { marker }: { marker: CellMarkerConfig } = $props();
7
+ </script>
8
+
9
+ <Cell
10
+ data={marker.data}
11
+ x={marker.x}
12
+ y={marker.y}
13
+ fill={marker.fill}
14
+ fillOpacity={marker.style?.fillOpacity ?? 1}
15
+ stroke={marker.style?.stroke}
16
+ strokeWidth={marker.style?.strokeWidth ?? 0}
17
+ strokeOpacity={marker.style?.strokeOpacity}
18
+ strokeDasharray={marker.style?.strokeDasharray}
19
+ borderRadius={marker.style?.borderRadius}
20
+ inset={marker.inset ?? 0.5}
21
+ />
@@ -0,0 +1,7 @@
1
+ import type { CellMarkerConfig } from '../types/markers/common';
2
+ type $$ComponentProps = {
3
+ marker: CellMarkerConfig;
4
+ };
5
+ declare const CellMarker: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ type CellMarker = ReturnType<typeof CellMarker>;
7
+ export default CellMarker;
@@ -0,0 +1,28 @@
1
+ <script lang="ts">
2
+ import { Contour } from 'svelteplot';
3
+ import type { GeoContourMarkerConfig } from '../types/markers/geo';
4
+
5
+ /**
6
+ * Renders one `'contour'` marker's `<Contour>` mark. `marker.clip` is
7
+ * handled by the caller (`GeometryLayout` wraps this in `ContourClipMarker`)
8
+ * — this component only draws the contour itself.
9
+ */
10
+ let { marker }: { marker: GeoContourMarkerConfig } = $props();
11
+ </script>
12
+
13
+ <!-- No `?? 'none'` fallback: an unset `fill` should leave svelteplot's own default (`fill="none"`) in place, not run the literal string `'none'` through the color scale. -->
14
+ <Contour
15
+ class="contour"
16
+ data={marker.data}
17
+ x={marker.x}
18
+ y={marker.y}
19
+ value={marker.value}
20
+ thresholds={marker.thresholds}
21
+ fill={marker.fill}
22
+ stroke={marker.stroke ?? 'currentColor'}
23
+ strokeWidth={marker.style?.strokeWidth}
24
+ fillOpacity={marker.style?.fillOpacity}
25
+ strokeOpacity={marker.style?.strokeOpacity}
26
+ blur={marker.blur}
27
+ interpolate={marker.interpolate}
28
+ />
@@ -0,0 +1,7 @@
1
+ import type { GeoContourMarkerConfig } from '../types/markers/geo';
2
+ type $$ComponentProps = {
3
+ marker: GeoContourMarkerConfig;
4
+ };
5
+ declare const ContourMarker: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ type ContourMarker = ReturnType<typeof ContourMarker>;
7
+ export default ContourMarker;
@@ -5,38 +5,19 @@
5
5
  import { Line } from 'svelteplot';
6
6
  import DotMarker from './DotMarker.svelte';
7
7
  import TextMarker from './TextMarker.svelte';
8
- import { resolveXDeltas, resolveYDeltas } from '../plots/utils/delta';
9
- import type { MarkerProps } from '../types/markers/props';
8
+ import { resolveXDeltas, resolveYDeltas } from '../utils/delta';
10
9
  import type { Series } from '../types/plots/data/common';
11
- import type { DeltaConfig } from '../types/plots/delta';
10
+ import type { DeltaMarkerConfig } from '../types/markers/line';
12
11
 
13
- interface Props extends MarkerProps<Series<TData>>, DeltaConfig {
14
- xDomain?: (number | string | Date)[];
15
- yDomain?: (number | string | Date)[];
16
- }
17
-
18
- let {
19
- data = [],
20
- axis,
21
- at,
22
- from,
23
- to,
24
- formatDiff,
25
- strokeStyle,
26
- fontStyle,
27
- dotStyle,
28
- xDomain,
29
- yDomain,
30
- }: Props = $props();
12
+ let { marker, data = [] }: { marker: DeltaMarkerConfig; data?: Series<TData>[] } = $props();
31
13
 
32
14
  const resolved = $derived.by(() => {
33
- const cfg: DeltaConfig = { axis, at, from, to, formatDiff, strokeStyle, fontStyle, dotStyle };
34
- const [d] = axis === 'x' ? resolveXDeltas(data, [cfg]) : resolveYDeltas(data, [cfg]);
15
+ const [d] = marker.axis === 'x' ? resolveXDeltas(data, [marker]) : resolveYDeltas(data, [marker]);
35
16
  return d;
36
17
  });
37
18
 
38
19
  const clampRange = $derived.by((): [number, number] | undefined => {
39
- const domain = axis === 'x' ? yDomain : xDomain;
20
+ const domain = marker.axis === 'x' ? marker.yDomain : marker.xDomain;
40
21
  if (!domain || domain.length < 2) return undefined;
41
22
  const lo = Number(domain[0]);
42
23
  const hi = Number(domain[domain.length - 1]);
@@ -48,11 +29,11 @@
48
29
  }
49
30
 
50
31
  function pt(fixed: number, varying: number) {
51
- return axis === 'x' ? { x: fixed, y: varying } : { x: varying, y: fixed };
32
+ return marker.axis === 'x' ? { x: fixed, y: varying } : { x: varying, y: fixed };
52
33
  }
53
34
 
54
35
  function textVaryCoord(fromVis: number, toVis: number) {
55
- const anchor = fontStyle?.lineAnchor ?? 'middle';
36
+ const anchor = marker.fontStyle?.lineAnchor ?? 'middle';
56
37
  return anchor === 'top'
57
38
  ? Math.max(fromVis, toVis)
58
39
  : anchor === 'bottom'
@@ -82,35 +63,47 @@
82
63
  data={coords.lineData}
83
64
  x={(p) => p.x}
84
65
  y={(p) => p.y}
85
- stroke={strokeStyle?.stroke ?? 'currentColor'}
86
- strokeWidth={strokeStyle?.strokeWidth ?? 2}
87
- strokeOpacity={strokeStyle?.strokeOpacity ?? 0.8}
88
- strokeDasharray={strokeStyle?.strokeDasharray ?? '6 6'}
89
- strokeLinecap={strokeStyle?.strokeLinecap ?? 'round'}
66
+ stroke={marker.strokeStyle?.stroke ?? 'currentColor'}
67
+ strokeWidth={marker.strokeStyle?.strokeWidth ?? 2}
68
+ strokeOpacity={marker.strokeStyle?.strokeOpacity ?? 0.8}
69
+ strokeDasharray={marker.strokeStyle?.strokeDasharray ?? '6 6'}
70
+ strokeLinecap={marker.strokeStyle?.strokeLinecap ?? 'round'}
90
71
  />
91
72
  <DotMarker
92
73
  x={coords?.fromPt?.x ?? 0}
93
74
  y={coords?.fromPt?.y ?? 0}
94
- style={{ dotRadius: 4, dotFill: strokeStyle?.stroke, dotStroke: strokeStyle?.stroke, dotStrokeWidth: 2, ...dotStyle }}
75
+ style={{
76
+ dotRadius: 4,
77
+ dotFill: marker.strokeStyle?.stroke,
78
+ dotStroke: marker.strokeStyle?.stroke,
79
+ dotStrokeWidth: 2,
80
+ ...marker.dotStyle,
81
+ }}
95
82
  />
96
83
  <DotMarker
97
84
  x={coords?.toPt?.x ?? 0}
98
85
  y={coords?.toPt?.y ?? 0}
99
- style={{ dotRadius: 4, dotFill: strokeStyle?.stroke, dotStroke: strokeStyle?.stroke, dotStrokeWidth: 2, ...dotStyle }}
86
+ style={{
87
+ dotRadius: 4,
88
+ dotFill: marker.strokeStyle?.stroke,
89
+ dotStroke: marker.strokeStyle?.stroke,
90
+ dotStrokeWidth: 2,
91
+ ...marker.dotStyle,
92
+ }}
100
93
  />
101
94
  <TextMarker
102
95
  x={coords?.textPt?.x ?? 0}
103
96
  y={coords?.textPt?.y ?? 0}
104
- text={(formatDiff ?? ((v: number) => v.toFixed(1)))(coords?.diff ?? 0)}
97
+ text={(marker.formatDiff ?? ((v: number) => v.toFixed(1)))(coords?.diff ?? 0)}
105
98
  style={{
106
99
  fontWeight: 'bold',
107
100
  fontSize: 14,
108
101
  textAnchor: 'middle',
109
- fill: strokeStyle?.stroke ?? 'currentColor',
110
- ...fontStyle,
111
- dx: fontStyle?.dx ?? (axis === 'x' ? 12 : 0),
112
- dy: fontStyle?.dy ?? (axis === 'x' ? 0 : -10),
113
- lineAnchor: axis === 'x' ? (fontStyle?.lineAnchor ?? 'middle') : 'bottom',
102
+ fill: marker.strokeStyle?.stroke ?? 'currentColor',
103
+ ...marker.fontStyle,
104
+ dx: marker.fontStyle?.dx ?? (marker.axis === 'x' ? 12 : 0),
105
+ dy: marker.fontStyle?.dy ?? (marker.axis === 'x' ? 0 : -10),
106
+ lineAnchor: marker.axis === 'x' ? (marker.fontStyle?.lineAnchor ?? 'middle') : 'bottom',
114
107
  }}
115
108
  />
116
109
  {/if}
@@ -1,10 +1,9 @@
1
- import type { MarkerProps } from '../types/markers/props';
2
1
  import type { Series } from '../types/plots/data/common';
3
- import type { DeltaConfig } from '../types/plots/delta';
2
+ import type { DeltaMarkerConfig } from '../types/markers/line';
4
3
  declare function $$render<TData extends Record<string, unknown>>(): {
5
- props: MarkerProps<Series<TData>> & DeltaConfig & {
6
- xDomain?: (number | string | Date)[];
7
- yDomain?: (number | string | Date)[];
4
+ props: {
5
+ marker: DeltaMarkerConfig;
6
+ data?: Series<TData>[];
8
7
  };
9
8
  exports: {};
10
9
  bindings: "";
@@ -1,23 +1,52 @@
1
1
  <script lang="ts" generics="TData = Record<string, unknown>">
2
2
  import { Dot } from 'svelteplot';
3
+ import { makeColorScale } from '../utils/color';
4
+ import { getConfiguration } from '../configuration/config.svelte';
3
5
  import type { MarkerProps } from '../types/markers/props';
4
- import type { AxisValue } from '../types/plots/axis';
6
+ import type { AxisValue } from '../types/layout/scales';
5
7
  import type { DotStyle } from '../types/plots/styling';
8
+ import type { ColorsStyle } from '../types/layout/styles';
6
9
 
7
10
  interface Props extends MarkerProps<TData> {
8
11
  x?: AxisValue | ((d: TData) => AxisValue);
9
12
  y?: AxisValue | ((d: TData) => AxisValue);
10
- style?: DotStyle;
13
+ /** Per-row radius, or a constant — overrides `style.dotRadius` when set. */
14
+ r?: number | ((d: TData) => number);
15
+ /** Per-row fill, overriding `style.dotFill` — ignored when `value` is set. */
16
+ fill?: (d: TData) => string;
17
+ /** Continuous value driving a per-dot color ramp through `style.colors` — takes priority over `fill`/`style.dotFill` when set. */
18
+ value?: (d: TData) => number;
19
+ style?: DotStyle & { colors?: ColorsStyle };
11
20
  }
12
21
 
13
- const { data = [], x, y, style }: Props = $props();
22
+ const { data = [], x, y, r: rProp, fill: fillProp, value, style }: Props = $props();
23
+
24
+ const cfg = $derived(getConfiguration());
14
25
 
15
26
  const xAccessor = $derived(typeof x === 'function' ? x : () => x ?? 0);
16
27
  const yAccessor = $derived(typeof y === 'function' ? y : () => y ?? 0);
17
- const displayData = $derived(data.length > 0 ? data : [{} as TData]);
28
+ /** A literal `x`/`y` draws one dot at a fixed point regardless of `data`; an accessor reads its position per row. */
29
+ const displayData = $derived(
30
+ data.length > 0 || typeof x === 'function' || typeof y === 'function' ? data : [{} as TData],
31
+ );
32
+
33
+ /** Color scale built from `value`'s own data extent — `null` when `value` is unset. */
34
+ const valueColorScale = $derived.by(() => {
35
+ if (!value) return null;
36
+ const vals = displayData.map((d) => Number(value(d))).filter((v) => Number.isFinite(v));
37
+ if (!vals.length) return null;
38
+ return makeColorScale(
39
+ Math.min(...vals),
40
+ Math.max(...vals),
41
+ style?.colors?.min ?? cfg.continuous.min,
42
+ style?.colors?.max ?? cfg.continuous.max,
43
+ );
44
+ });
18
45
 
19
- const r = $derived(style?.dotRadius ?? 5);
20
- const fill = $derived(style?.dotFill ?? 'currentColor');
46
+ const r = $derived(rProp ?? style?.dotRadius ?? 5);
47
+ const fill = $derived(
48
+ valueColorScale && value ? (d: TData) => valueColorScale(Number(value(d))) : (fillProp ?? style?.dotFill ?? 'currentColor'),
49
+ );
21
50
  const fillOpacity = $derived(style?.dotFillOpacity ?? 1);
22
51
  const symbol = $derived(style?.dotSymbol ?? 'circle');
23
52
  const stroke = $derived(style?.dotStroke ?? 'currentColor');
@@ -1,11 +1,20 @@
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 { DotStyle } from '../types/plots/styling';
4
+ import type { ColorsStyle } from '../types/layout/styles';
4
5
  declare function $$render<TData = Record<string, unknown>>(): {
5
6
  props: MarkerProps<TData> & {
6
7
  x?: AxisValue | ((d: TData) => AxisValue);
7
8
  y?: AxisValue | ((d: TData) => AxisValue);
8
- style?: DotStyle;
9
+ /** Per-row radius, or a constant — overrides `style.dotRadius` when set. */
10
+ r?: number | ((d: TData) => number);
11
+ /** Per-row fill, overriding `style.dotFill` — ignored when `value` is set. */
12
+ fill?: (d: TData) => string;
13
+ /** Continuous value driving a per-dot color ramp through `style.colors` — takes priority over `fill`/`style.dotFill` when set. */
14
+ value?: (d: TData) => number;
15
+ style?: DotStyle & {
16
+ colors?: ColorsStyle;
17
+ };
9
18
  };
10
19
  exports: {};
11
20
  bindings: "";
@@ -0,0 +1,19 @@
1
+ <script lang="ts">
2
+ import { Geo } from 'svelteplot';
3
+ import type { GeoFeaturesMarkerConfig } from '../types/markers/geo';
4
+
5
+ /** Renders one `'geo'` marker — one resolved-style bucket of the base map's own features, as a single `<Geo>` call. */
6
+ let { marker }: { marker: GeoFeaturesMarkerConfig } = $props();
7
+ </script>
8
+
9
+ <Geo
10
+ data={marker.data}
11
+ fill={marker.fill}
12
+ fillOpacity={marker.fillOpacity ?? 1}
13
+ stroke={marker.stroke ?? 'currentColor'}
14
+ strokeWidth={marker.strokeWidth ?? 0.5}
15
+ style="vector-effect: non-scaling-stroke"
16
+ onclick={marker.onclick}
17
+ onpointerenter={marker.onpointerenter}
18
+ onpointerleave={marker.onpointerleave}
19
+ />
@@ -0,0 +1,7 @@
1
+ import type { GeoFeaturesMarkerConfig } from '../types/markers/geo';
2
+ type $$ComponentProps = {
3
+ marker: GeoFeaturesMarkerConfig;
4
+ };
5
+ declare const GeoFeaturesMarker: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ type GeoFeaturesMarker = ReturnType<typeof GeoFeaturesMarker>;
7
+ export default GeoFeaturesMarker;
@@ -0,0 +1,25 @@
1
+ <script lang="ts">
2
+ import { Geo } from 'svelteplot';
3
+ import { getConfiguration } from '../configuration/config.svelte';
4
+ import type { GeoHoverMarkerConfig } from '../types/markers/geo';
5
+ import type { HoverPoint } from '../types/layout/tooltip';
6
+
7
+ /** Renders the hovered feature restyled in place — no dot, no label. `pointer-events: none` so it never steals hover from the base map underneath it. */
8
+ let { marker, data }: { marker: GeoHoverMarkerConfig; data: HoverPoint<Record<string, unknown>>[] } = $props();
9
+
10
+ const cfg = $derived(getConfiguration());
11
+ const style = $derived({ ...cfg.hover.area, ...marker.style });
12
+ </script>
13
+
14
+ {#if data.length > 0}
15
+ <Geo
16
+ data={data.map((p) => p.row)}
17
+ fill={style.fill}
18
+ fillOpacity={style.fillOpacity}
19
+ stroke={style.stroke}
20
+ strokeWidth={style.strokeWidth}
21
+ strokeOpacity={style.strokeOpacity}
22
+ strokeDasharray={style.strokeDasharray}
23
+ style="vector-effect: non-scaling-stroke; pointer-events: none;"
24
+ />
25
+ {/if}
@@ -0,0 +1,9 @@
1
+ import type { GeoHoverMarkerConfig } from '../types/markers/geo';
2
+ import type { HoverPoint } from '../types/layout/tooltip';
3
+ type $$ComponentProps = {
4
+ marker: GeoHoverMarkerConfig;
5
+ data: HoverPoint<Record<string, unknown>>[];
6
+ };
7
+ declare const GeoHoverMarker: import("svelte").Component<$$ComponentProps, {}, "">;
8
+ type GeoHoverMarker = ReturnType<typeof GeoHoverMarker>;
9
+ export default GeoHoverMarker;
@@ -0,0 +1,18 @@
1
+ <script lang="ts">
2
+ import { Graticule } from 'svelteplot';
3
+ import type { GeoGraticuleMarkerConfig } from '../types/markers/geo';
4
+
5
+ /** Renders one `'graticule'` marker — longitude/latitude gridlines. */
6
+ let { marker }: { marker: GeoGraticuleMarkerConfig } = $props();
7
+ </script>
8
+
9
+ <Graticule
10
+ step={marker.step}
11
+ stepX={marker.stepX}
12
+ stepY={marker.stepY}
13
+ stroke={marker.style?.stroke ?? 'currentColor'}
14
+ strokeWidth={marker.style?.strokeWidth ?? 0.5}
15
+ strokeOpacity={marker.style?.strokeOpacity ?? 0.3}
16
+ strokeDasharray={marker.style?.strokeDasharray}
17
+ style="vector-effect: non-scaling-stroke"
18
+ />
@@ -0,0 +1,7 @@
1
+ import type { GeoGraticuleMarkerConfig } from '../types/markers/geo';
2
+ type $$ComponentProps = {
3
+ marker: GeoGraticuleMarkerConfig;
4
+ };
5
+ declare const GraticuleMarker: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ type GraticuleMarker = ReturnType<typeof GraticuleMarker>;
7
+ export default GraticuleMarker;
@@ -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,25 +94,11 @@
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}