layerchart 2.0.0-next.1 → 2.0.0-next.3

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 (266) hide show
  1. package/dist/actions/movable.d.ts +28 -0
  2. package/dist/actions/movable.js +91 -0
  3. package/dist/components/AnnotationLine.svelte +143 -0
  4. package/dist/components/AnnotationLine.svelte.d.ts +30 -0
  5. package/dist/components/AnnotationPoint.svelte +119 -0
  6. package/dist/components/AnnotationPoint.svelte.d.ts +34 -0
  7. package/dist/components/AnnotationRange.svelte +147 -0
  8. package/dist/components/AnnotationRange.svelte.d.ts +40 -0
  9. package/dist/components/Arc.svelte +344 -151
  10. package/dist/components/Arc.svelte.d.ts +138 -0
  11. package/dist/components/Area.svelte +165 -149
  12. package/dist/components/Area.svelte.d.ts +45 -0
  13. package/dist/components/Axis.svelte +283 -180
  14. package/dist/components/Axis.svelte.d.ts +117 -0
  15. package/dist/components/Bar.svelte +166 -107
  16. package/dist/components/Bar.svelte.d.ts +51 -0
  17. package/dist/components/Bars.svelte +56 -67
  18. package/dist/components/Bars.svelte.d.ts +27 -0
  19. package/dist/components/Blur.svelte +42 -12
  20. package/dist/components/Blur.svelte.d.ts +23 -21
  21. package/dist/components/Bounds.svelte +49 -19
  22. package/dist/components/Bounds.svelte.d.ts +24 -50
  23. package/dist/components/BrushContext.svelte +296 -168
  24. package/dist/components/BrushContext.svelte.d.ts +97 -65
  25. package/dist/components/Calendar.svelte +116 -59
  26. package/dist/components/Calendar.svelte.d.ts +50 -31
  27. package/dist/components/Chart.svelte +1289 -398
  28. package/dist/components/Chart.svelte.d.ts +535 -410
  29. package/dist/components/ChartClipPath.svelte +37 -15
  30. package/dist/components/ChartClipPath.svelte.d.ts +21 -19
  31. package/dist/components/Circle.svelte +124 -85
  32. package/dist/components/Circle.svelte.d.ts +52 -0
  33. package/dist/components/CircleClipPath.svelte +76 -16
  34. package/dist/components/CircleClipPath.svelte.d.ts +46 -0
  35. package/dist/components/ClipPath.svelte +71 -21
  36. package/dist/components/ClipPath.svelte.d.ts +40 -27
  37. package/dist/components/ColorRamp.svelte +75 -9
  38. package/dist/components/ColorRamp.svelte.d.ts +37 -19
  39. package/dist/components/ComputedStyles.svelte +17 -5
  40. package/dist/components/ComputedStyles.svelte.d.ts +11 -19
  41. package/dist/components/Connector.svelte +149 -0
  42. package/dist/components/Connector.svelte.d.ts +51 -0
  43. package/dist/components/Dagre.svelte +211 -122
  44. package/dist/components/Dagre.svelte.d.ts +119 -56
  45. package/dist/components/ForceSimulation.svelte +215 -90
  46. package/dist/components/ForceSimulation.svelte.d.ts +82 -35
  47. package/dist/components/Frame.svelte +33 -13
  48. package/dist/components/Frame.svelte.d.ts +13 -17
  49. package/dist/components/GeoCircle.svelte +29 -16
  50. package/dist/components/GeoCircle.svelte.d.ts +22 -24
  51. package/dist/components/GeoContext.svelte +113 -72
  52. package/dist/components/GeoContext.svelte.d.ts +49 -41
  53. package/dist/components/GeoEdgeFade.svelte +49 -13
  54. package/dist/components/GeoEdgeFade.svelte.d.ts +17 -19
  55. package/dist/components/GeoPath.svelte +157 -127
  56. package/dist/components/GeoPath.svelte.d.ts +48 -36
  57. package/dist/components/GeoPoint.svelte +52 -20
  58. package/dist/components/GeoPoint.svelte.d.ts +25 -22
  59. package/dist/components/GeoSpline.svelte +75 -26
  60. package/dist/components/GeoSpline.svelte.d.ts +29 -20
  61. package/dist/components/GeoTile.svelte +100 -49
  62. package/dist/components/GeoTile.svelte.d.ts +38 -23
  63. package/dist/components/GeoVisible.svelte +17 -9
  64. package/dist/components/GeoVisible.svelte.d.ts +10 -18
  65. package/dist/components/Graticule.svelte +30 -14
  66. package/dist/components/Graticule.svelte.d.ts +11 -52
  67. package/dist/components/Grid.svelte +230 -117
  68. package/dist/components/Grid.svelte.d.ts +71 -0
  69. package/dist/components/Group.svelte +173 -106
  70. package/dist/components/Group.svelte.d.ts +81 -0
  71. package/dist/components/Highlight.svelte +410 -308
  72. package/dist/components/Highlight.svelte.d.ts +107 -0
  73. package/dist/components/Hull.svelte +97 -46
  74. package/dist/components/Hull.svelte.d.ts +40 -30
  75. package/dist/components/Labels.svelte +127 -47
  76. package/dist/components/Labels.svelte.d.ts +70 -27
  77. package/dist/components/Legend.svelte +374 -190
  78. package/dist/components/Legend.svelte.d.ts +95 -44
  79. package/dist/components/Line.svelte +163 -125
  80. package/dist/components/Line.svelte.d.ts +75 -0
  81. package/dist/components/LinearGradient.svelte +153 -78
  82. package/dist/components/LinearGradient.svelte.d.ts +66 -31
  83. package/dist/components/Link.svelte +160 -104
  84. package/dist/components/Link.svelte.d.ts +54 -0
  85. package/dist/components/Marker.svelte +100 -39
  86. package/dist/components/Marker.svelte.d.ts +59 -27
  87. package/dist/components/MarkerWrapper.svelte +35 -0
  88. package/dist/components/MarkerWrapper.svelte.d.ts +18 -0
  89. package/dist/components/MonthPath.svelte +65 -20
  90. package/dist/components/MonthPath.svelte.d.ts +23 -17
  91. package/dist/components/MotionPath.svelte +80 -24
  92. package/dist/components/MotionPath.svelte.d.ts +46 -27
  93. package/dist/components/Pack.svelte +53 -17
  94. package/dist/components/Pack.svelte.d.ts +42 -21
  95. package/dist/components/Partition.svelte +64 -22
  96. package/dist/components/Partition.svelte.d.ts +49 -26
  97. package/dist/components/Pattern.svelte +297 -11
  98. package/dist/components/Pattern.svelte.d.ts +103 -19
  99. package/dist/components/Pie.svelte +122 -76
  100. package/dist/components/Pie.svelte.d.ts +65 -51
  101. package/dist/components/Point.svelte +20 -9
  102. package/dist/components/Point.svelte.d.ts +16 -20
  103. package/dist/components/Points.svelte +148 -137
  104. package/dist/components/Points.svelte.d.ts +45 -34
  105. package/dist/components/RadialGradient.svelte +143 -70
  106. package/dist/components/RadialGradient.svelte.d.ts +69 -31
  107. package/dist/components/Rect.svelte +121 -102
  108. package/dist/components/Rect.svelte.d.ts +36 -0
  109. package/dist/components/RectClipPath.svelte +82 -18
  110. package/dist/components/RectClipPath.svelte.d.ts +55 -0
  111. package/dist/components/Rule.svelte +107 -63
  112. package/dist/components/Rule.svelte.d.ts +40 -19
  113. package/dist/components/Sankey.svelte +132 -55
  114. package/dist/components/Sankey.svelte.d.ts +61 -31
  115. package/dist/components/Spline.svelte +281 -218
  116. package/dist/components/Spline.svelte.d.ts +95 -0
  117. package/dist/components/Text.svelte +437 -176
  118. package/dist/components/Text.svelte.d.ts +130 -0
  119. package/dist/components/Threshold.svelte +48 -16
  120. package/dist/components/Threshold.svelte.d.ts +29 -31
  121. package/dist/components/TileImage.svelte +103 -30
  122. package/dist/components/TileImage.svelte.d.ts +48 -23
  123. package/dist/components/TransformContext.svelte +365 -171
  124. package/dist/components/TransformControls.svelte +50 -26
  125. package/dist/components/TransformControls.svelte.d.ts +27 -19
  126. package/dist/components/Tree.svelte +74 -33
  127. package/dist/components/Tree.svelte.d.ts +42 -30
  128. package/dist/components/Treemap.svelte +119 -42
  129. package/dist/components/Treemap.svelte.d.ts +75 -27
  130. package/dist/components/Voronoi.svelte +108 -76
  131. package/dist/components/Voronoi.svelte.d.ts +40 -41
  132. package/dist/components/charts/ArcChart.svelte +464 -0
  133. package/dist/components/charts/ArcChart.svelte.d.ts +90 -0
  134. package/dist/components/charts/AreaChart.svelte +450 -393
  135. package/dist/components/charts/AreaChart.svelte.d.ts +61 -0
  136. package/dist/components/charts/BarChart.svelte +454 -389
  137. package/dist/components/charts/BarChart.svelte.d.ts +76 -0
  138. package/dist/components/charts/ChartAnnotations.svelte +37 -0
  139. package/dist/components/charts/ChartAnnotations.svelte.d.ts +10 -0
  140. package/dist/components/charts/DefaultTooltip.svelte +60 -0
  141. package/dist/components/charts/DefaultTooltip.svelte.d.ts +10 -0
  142. package/dist/components/charts/LineChart.svelte +369 -314
  143. package/dist/components/charts/LineChart.svelte.d.ts +53 -0
  144. package/dist/components/charts/PieChart.svelte +458 -316
  145. package/dist/components/charts/PieChart.svelte.d.ts +137 -353
  146. package/dist/components/charts/ScatterChart.svelte +334 -296
  147. package/dist/components/charts/ScatterChart.svelte.d.ts +39 -0
  148. package/dist/components/charts/index.d.ts +8 -0
  149. package/dist/components/charts/index.js +7 -0
  150. package/dist/components/charts/types.d.ts +253 -0
  151. package/dist/components/charts/utils.svelte.d.ts +30 -0
  152. package/dist/components/charts/utils.svelte.js +55 -0
  153. package/dist/components/index.d.ts +76 -4
  154. package/dist/components/index.js +76 -5
  155. package/dist/components/layout/Canvas.svelte +321 -155
  156. package/dist/components/layout/Canvas.svelte.d.ts +104 -55
  157. package/dist/components/layout/Html.svelte +82 -42
  158. package/dist/components/layout/Html.svelte.d.ts +39 -28
  159. package/dist/components/layout/Layer.svelte +39 -0
  160. package/dist/components/layout/Layer.svelte.d.ts +17 -0
  161. package/dist/components/layout/Svg.svelte +122 -70
  162. package/dist/components/layout/Svg.svelte.d.ts +53 -34
  163. package/dist/components/layout/WebGL.svelte +135 -0
  164. package/dist/components/layout/WebGL.svelte.d.ts +50 -0
  165. package/dist/components/tooltip/Tooltip.svelte +246 -78
  166. package/dist/components/tooltip/Tooltip.svelte.d.ts +149 -31
  167. package/dist/components/tooltip/TooltipContext.svelte +409 -271
  168. package/dist/components/tooltip/TooltipContext.svelte.d.ts +86 -55
  169. package/dist/components/tooltip/TooltipHeader.svelte +100 -11
  170. package/dist/components/tooltip/TooltipHeader.svelte.d.ts +43 -23
  171. package/dist/components/tooltip/TooltipItem.svelte +167 -27
  172. package/dist/components/tooltip/TooltipItem.svelte.d.ts +63 -31
  173. package/dist/components/tooltip/TooltipList.svelte +22 -3
  174. package/dist/components/tooltip/TooltipList.svelte.d.ts +6 -17
  175. package/dist/components/tooltip/TooltipSeparator.svelte +27 -1
  176. package/dist/components/tooltip/TooltipSeparator.svelte.d.ts +6 -15
  177. package/dist/components/tooltip/index.d.ts +6 -0
  178. package/dist/components/tooltip/index.js +6 -0
  179. package/dist/components/tooltip/tooltipMetaContext.d.ts +79 -0
  180. package/dist/components/tooltip/tooltipMetaContext.js +139 -0
  181. package/dist/components/types.d.ts +1 -0
  182. package/dist/components/types.js +1 -0
  183. package/dist/docs/Blockquote.svelte.d.ts +18 -14
  184. package/dist/docs/Code.svelte.d.ts +26 -22
  185. package/dist/docs/ConnectorSweepMenuField.svelte +17 -0
  186. package/dist/docs/ConnectorSweepMenuField.svelte.d.ts +7 -0
  187. package/dist/docs/ConnectorTypeMenuField.svelte +17 -0
  188. package/dist/docs/ConnectorTypeMenuField.svelte.d.ts +7 -0
  189. package/dist/docs/CurveMenuField.svelte +14 -3
  190. package/dist/docs/CurveMenuField.svelte.d.ts +9 -18
  191. package/dist/docs/GeoDebug.svelte +47 -42
  192. package/dist/docs/GeoDebug.svelte.d.ts +4 -16
  193. package/dist/docs/Header1.svelte.d.ts +27 -16
  194. package/dist/docs/Json.svelte.d.ts +20 -16
  195. package/dist/docs/Layout.svelte.d.ts +18 -13
  196. package/dist/docs/Link.svelte.d.ts +33 -21
  197. package/dist/docs/PathDataMenuField.svelte +14 -10
  198. package/dist/docs/PathDataMenuField.svelte.d.ts +8 -18
  199. package/dist/docs/Preview.svelte +20 -7
  200. package/dist/docs/Preview.svelte.d.ts +12 -22
  201. package/dist/docs/TilesetField.svelte.d.ts +21 -17
  202. package/dist/docs/TransformDebug.svelte +5 -6
  203. package/dist/docs/TransformDebug.svelte.d.ts +18 -14
  204. package/dist/docs/ViewSourceButton.svelte.d.ts +21 -17
  205. package/dist/types/d3-shape-extentions.d.ts +7 -0
  206. package/dist/utils/afterTick.d.ts +5 -0
  207. package/dist/utils/afterTick.js +8 -0
  208. package/dist/utils/arcText.svelte.d.ts +57 -0
  209. package/dist/utils/arcText.svelte.js +262 -0
  210. package/dist/utils/array.d.ts +9 -1
  211. package/dist/utils/array.js +13 -0
  212. package/dist/utils/attributes.d.ts +29 -0
  213. package/dist/utils/attributes.js +40 -0
  214. package/dist/utils/canvas.js +47 -10
  215. package/dist/utils/chart.d.ts +78 -0
  216. package/dist/utils/chart.js +512 -0
  217. package/dist/utils/color.d.ts +1 -0
  218. package/dist/utils/color.js +8 -0
  219. package/dist/utils/common.d.ts +3 -5
  220. package/dist/utils/common.js +3 -2
  221. package/dist/utils/connectorUtils.d.ts +21 -0
  222. package/dist/utils/connectorUtils.js +111 -0
  223. package/dist/utils/createId.d.ts +7 -0
  224. package/dist/utils/createId.js +9 -0
  225. package/dist/utils/debug.d.ts +1 -0
  226. package/dist/utils/debug.js +84 -0
  227. package/dist/utils/filterObject.d.ts +9 -0
  228. package/dist/utils/filterObject.js +12 -0
  229. package/dist/utils/graph/dagre.d.ts +34 -0
  230. package/dist/utils/graph/dagre.js +78 -0
  231. package/dist/utils/graph/dagre.test.d.ts +1 -0
  232. package/dist/utils/{graph.test.js → graph/dagre.test.js} +19 -33
  233. package/dist/utils/graph/sankey.d.ts +28 -0
  234. package/dist/utils/{graph.js → graph/sankey.js} +13 -41
  235. package/dist/utils/index.d.ts +3 -1
  236. package/dist/utils/index.js +3 -1
  237. package/dist/utils/key.svelte.d.ts +3 -0
  238. package/dist/utils/key.svelte.js +11 -0
  239. package/dist/utils/legendPayload.d.ts +7 -0
  240. package/dist/utils/legendPayload.js +8 -0
  241. package/dist/utils/motion.svelte.d.ts +140 -0
  242. package/dist/utils/motion.svelte.js +180 -0
  243. package/dist/utils/motion.test.d.ts +1 -0
  244. package/dist/utils/motion.test.js +213 -0
  245. package/dist/utils/{rect.d.ts → rect.svelte.d.ts} +7 -4
  246. package/dist/utils/rect.svelte.js +105 -0
  247. package/dist/utils/scales.svelte.d.ts +90 -0
  248. package/dist/utils/{scales.js → scales.svelte.js} +100 -39
  249. package/dist/utils/stack.d.ts +2 -3
  250. package/dist/utils/stack.js +1 -1
  251. package/dist/utils/string.js +87 -0
  252. package/dist/utils/ticks.d.ts +8 -2
  253. package/dist/utils/ticks.js +28 -0
  254. package/dist/utils/ticks.test.d.ts +1 -0
  255. package/dist/utils/ticks.test.js +67 -0
  256. package/dist/utils/types.d.ts +81 -0
  257. package/package.json +21 -19
  258. package/dist/components/ChartContext.svelte +0 -295
  259. package/dist/components/ChartContext.svelte.d.ts +0 -139
  260. package/dist/components/TransformContext.svelte.d.ts +0 -158
  261. package/dist/stores/motionStore.d.ts +0 -30
  262. package/dist/stores/motionStore.js +0 -62
  263. package/dist/utils/graph.d.ts +0 -37
  264. package/dist/utils/rect.js +0 -107
  265. package/dist/utils/scales.d.ts +0 -66
  266. /package/dist/{utils/graph.test.d.ts → components/charts/types.js} +0 -0
@@ -1,144 +1,302 @@
1
+ <script lang="ts" module>
2
+ import type { Snippet } from 'svelte';
3
+ import type { Placement } from './types.js';
4
+ import type { Without } from '../utils/types.js';
5
+
6
+ export type LegendItem = {
7
+ value: any;
8
+ color: string;
9
+ };
10
+
11
+ export type LegendPropsWithoutHTML = {
12
+ scale?: AnyScale;
13
+
14
+ /**
15
+ * The title of the legend.
16
+ *
17
+ * @default ''
18
+ */
19
+ title?: string;
20
+
21
+ /**
22
+ * The width of the legend.
23
+ *
24
+ * @default 320
25
+ */
26
+ width?: number;
27
+
28
+ /**
29
+ * The height of the legend.
30
+ *
31
+ * @default 10
32
+ */
33
+ height?: number;
34
+
35
+ /**
36
+ * The number of ticks to show on the scale.
37
+ * @default width / 64
38
+ */
39
+ ticks?: number;
40
+ tickFormat?: FormatType;
41
+ tickValues?: any[];
42
+ /**
43
+ * The font size of the tick labels.
44
+ *
45
+ * @default 10
46
+ */
47
+ tickFontSize?: number;
48
+
49
+ /**
50
+ * The length of the tick marks.
51
+ *
52
+ * @default 4
53
+ */
54
+ tickLength?: number;
55
+
56
+ /**
57
+ * The placement of the legend.
58
+ */
59
+ placement?: Placement;
60
+
61
+ /**
62
+ * The orientation of the legend.
63
+ *
64
+ * @default 'horizontal'
65
+ */
66
+ orientation?: 'horizontal' | 'vertical';
67
+
68
+ onclick?: (e: MouseEvent, detail: LegendItem) => any;
69
+ onpointerenter?: (e: MouseEvent, detail: LegendItem) => any;
70
+ onpointerleave?: (e: MouseEvent, detail: LegendItem) => any;
71
+
72
+ /**
73
+ * Determine display ramp (individual color swatches or continuous ramp)
74
+ *
75
+ * @default 'ramp'
76
+ */
77
+ variant?: 'ramp' | 'swatches';
78
+
79
+ /**
80
+ * Classes to apply to the elements.
81
+ *
82
+ * @default {}
83
+ */
84
+ classes?: {
85
+ root?: string;
86
+ title?: string;
87
+ label?: string;
88
+ tick?: string;
89
+ swatches?: string;
90
+ swatch?: string;
91
+ item?: (item: LegendItem) => string;
92
+ };
93
+
94
+ /**
95
+ * A bindable reference to the wrapping `<div>` element.
96
+ *
97
+ * @bindable
98
+ */
99
+ ref?: HTMLElement;
100
+
101
+ children?: Snippet<[{ values: any[]; scale: AnyScale | null }]>;
102
+ };
103
+
104
+ export type LegendProps = LegendPropsWithoutHTML &
105
+ Without<HTMLAttributes<HTMLElement>, LegendPropsWithoutHTML>;
106
+ </script>
107
+
1
108
  <script lang="ts">
2
- import type { SVGAttributes } from 'svelte/elements';
109
+ import type { HTMLAttributes, SVGAttributes } from 'svelte/elements';
3
110
  import { scaleBand, scaleLinear } from 'd3-scale';
4
111
  import { quantize, interpolate, interpolateRound } from 'd3-interpolate';
5
112
  import { quantile, range } from 'd3-array';
6
113
  import { format, type FormatType } from '@layerstack/utils';
7
114
 
8
- import { chartContext } from './ChartContext.svelte';
9
115
  import ColorRamp from './ColorRamp.svelte';
10
116
  import { cls } from '@layerstack/tailwind';
117
+ import type { AnyScale } from '../utils/scales.svelte.js';
118
+ import { getChartContext } from './Chart.svelte';
119
+ import { extractLayerProps, layerClass } from '../utils/attributes.js';
11
120
 
12
- const { cScale } = chartContext() ?? {};
13
-
14
- type AnyScale = any;
15
- type Placement =
16
- | 'top-left'
17
- | 'top'
18
- | 'top-right'
19
- | 'left'
20
- | 'center'
21
- | 'right'
22
- | 'bottom-left'
23
- | 'bottom'
24
- | 'bottom-right';
25
-
26
- export let scale: AnyScale = undefined;
27
- export let title = '';
28
- export let width = 320;
29
- export let height = 10;
30
- export let ticks = width / 64;
31
- export let tickFormat: FormatType | undefined = undefined;
32
- export let tickValues: any[] | undefined = undefined;
33
- export let tickFontSize = 10;
34
- export let tickLength = 4;
35
- export let placement: Placement | undefined = undefined;
36
- export let orientation: 'horizontal' | 'vertical' = 'horizontal';
37
-
38
- export let onclick: ((e: MouseEvent, detail: any) => any) | undefined = undefined;
39
- export let onpointerenter: ((e: MouseEvent, detail: any) => any) | undefined = undefined;
40
- export let onpointerleave: ((e: MouseEvent, detail: any) => any) | undefined = undefined;
41
-
42
- /** Determine display ramp (individual color swatches or continuous ramp)*/
43
- export let variant: 'ramp' | 'swatches' = 'ramp';
44
-
45
- export let classes: {
46
- root?: string;
47
- title?: string;
48
- label?: string;
49
- tick?: string;
50
- swatches?: string;
51
- swatch?: string;
52
- item?: (item: any) => string;
53
- } = {};
54
-
55
- $: _scale = scale ?? (cScale ? $cScale : null);
56
-
57
- let xScale: AnyScale;
58
- let interpolator: ((t: number) => string) | undefined;
59
- let swatches: SVGAttributes<SVGRectElement>[];
60
- let tickLabelOffset = 0;
61
- let tickLine = true;
62
-
63
- $: if (!_scale) {
64
- // do nothing
65
- } else if (_scale.interpolate) {
66
- // Continuous
67
- const n = Math.min(_scale.domain().length, _scale.range().length);
68
- xScale = _scale.copy().rangeRound(quantize(interpolate(0, width), n));
69
- interpolator = _scale.copy().domain(quantize(interpolate(0, 1), n));
70
- tickFormat = tickFormat ?? xScale.tickFormat?.();
71
- } else if (_scale.interpolator) {
72
- // Sequential
73
- xScale = Object.assign(_scale.copy().interpolator(interpolateRound(0, width)), {
74
- range() {
75
- return [0, width];
76
- },
77
- });
78
- interpolator = _scale.interpolator();
79
-
80
- // scaleSequentialQuantile doesn’t implement ticks or tickFormat.
81
- if (!xScale.ticks) {
82
- if (tickValues === undefined) {
83
- const n = Math.round(ticks + 1);
84
- tickValues = range(n).map((i) => quantile(_scale.domain(), i / (n - 1)));
121
+ let {
122
+ scale: scaleProp,
123
+ title = '',
124
+ width = 320,
125
+ height = 10,
126
+ ticks = width / 64,
127
+ tickFormat: tickFormatProp,
128
+ tickValues: tickValuesProp,
129
+ tickFontSize = 10,
130
+ tickLength: tickLengthProp = 4,
131
+ placement,
132
+ orientation = 'horizontal',
133
+ onclick,
134
+ onpointerenter,
135
+ onpointerleave,
136
+ variant = 'ramp',
137
+ classes = {},
138
+ ref: refProp = $bindable(),
139
+ class: className,
140
+ children,
141
+ ...restProps
142
+ }: LegendProps = $props();
143
+
144
+ let ref = $state<HTMLElement>();
145
+ $effect.pre(() => {
146
+ refProp = ref;
147
+ });
148
+
149
+ const ctx = getChartContext();
150
+
151
+ const scale = $derived(scaleProp ?? ctx.cScale);
152
+
153
+ type ScaleConfig = {
154
+ xScale: AnyScale | undefined;
155
+ interpolator: ((t: number) => string) | undefined;
156
+ swatches: SVGAttributes<SVGRectElement>[] | undefined;
157
+ tickLabelOffset: number;
158
+ tickLine: boolean;
159
+ tickValues: any[] | undefined;
160
+ tickLength: number;
161
+ };
162
+
163
+ const scaleConfig: ScaleConfig = $derived.by(() => {
164
+ if (!scale) {
165
+ return {
166
+ xScale: undefined,
167
+ interpolator: undefined,
168
+ swatches: undefined,
169
+ tickLabelOffset: 0,
170
+ tickLine: true,
171
+ tickLength: tickLengthProp,
172
+ tickFormat: tickFormatProp,
173
+ tickValues: tickValuesProp,
174
+ };
175
+ } else if (scale.interpolate) {
176
+ // Continuous
177
+ const n = Math.min(scale.domain().length, scale.range().length);
178
+ const xScale = scale.copy().rangeRound?.(quantize(interpolate(0, width), n));
179
+ const interpolator = scale.copy().domain(quantize(interpolate(0, 1), n));
180
+ const _tickFormat = tickFormatProp ?? xScale?.tickFormat?.();
181
+
182
+ return {
183
+ xScale,
184
+ interpolator,
185
+ tickFormat: _tickFormat,
186
+ tickLabelOffset: 0,
187
+ tickLine: true,
188
+ tickValues: tickValuesProp,
189
+ tickLength: tickLengthProp,
190
+ swatches: undefined,
191
+ };
192
+ } else if (scale.interpolator) {
193
+ // Sequential
194
+ const xScale = Object.assign(scale.copy().interpolator!(interpolateRound(0, width)), {
195
+ range() {
196
+ return [0, width];
197
+ },
198
+ });
199
+ const interpolator = scale.interpolator();
200
+ let tickValues: any[] | undefined = tickValuesProp;
201
+
202
+ if (!xScale.ticks) {
203
+ if (tickValues === undefined) {
204
+ const n = Math.round(ticks + 1);
205
+ tickValues = range(n).map((i) => quantile(scale.domain(), i / (n - 1)));
206
+ }
207
+
208
+ // if (typeof tickFormat !== "function") {
209
+ // tickFormat = d3.format(tickFormat === undefined ? ",f" : tickFormat);
210
+ // }
85
211
  }
86
- // if (typeof tickFormat !== "function") {
87
- // tickFormat = d3.format(tickFormat === undefined ? ",f" : tickFormat);
88
- // }
89
- }
90
- tickFormat = tickFormat ?? xScale.tickFormat?.();
91
- } else if (_scale.invertExtent) {
92
- // Threshold
93
- const thresholds = _scale.thresholds
94
- ? _scale.thresholds() // scaleQuantize
95
- : _scale.quantiles
96
- ? _scale.quantiles() // scaleQuantile
97
- : _scale.domain(); // scaleThreshold
98
-
99
- xScale = scaleLinear()
100
- .domain([-1, _scale.range().length - 1])
101
- .rangeRound([0, width]);
102
-
103
- swatches = _scale.range().map((d: any, i: number) => {
212
+
213
+ const tickFormat = tickFormatProp ?? xScale.tickFormat?.();
214
+
104
215
  return {
105
- x: xScale(i - 1),
106
- y: 0,
107
- width: xScale(i) - xScale(i - 1),
108
- height,
109
- fill: d,
216
+ interpolator,
217
+ tickValues: tickValues,
218
+ tickFormat: tickFormat,
219
+ swatches: undefined,
220
+ tickLabelOffset: 0,
221
+ tickLine: true,
222
+ tickLength: tickLengthProp,
223
+ xScale: xScale,
110
224
  };
111
- });
225
+ } else if (scale.invertExtent) {
226
+ // Threshold
227
+ const thresholds = scale.thresholds
228
+ ? scale.thresholds() // scaleQuantize
229
+ : scale.quantiles
230
+ ? scale.quantiles() // scaleQuantile
231
+ : scale.domain(); // scaleThreshold
112
232
 
113
- tickValues = range(thresholds.length);
114
- tickFormat = (i) => {
115
- const value = thresholds[i];
116
- return $$props.tickFormat ? format(value, $$props.tickFormat) : value;
117
- };
118
- } else {
119
- // Ordinal
120
- xScale = scaleBand().domain(_scale.domain()).rangeRound([0, width]);
233
+ const xScale = scaleLinear()
234
+ .domain([-1, scale.range().length - 1])
235
+ .rangeRound([0, width]);
236
+ const swatches = scale.range().map((d: any, i: number) => {
237
+ return {
238
+ x: xScale(i - 1),
239
+ y: 0,
240
+ width: xScale(i) - xScale(i - 1),
241
+ height,
242
+ fill: d,
243
+ };
244
+ });
245
+ const tickValues = range(thresholds.length);
246
+ const tickFormat = (i: number) => {
247
+ const value = thresholds[i];
248
+ return tickFormatProp ? format(value, tickFormatProp) : value;
249
+ };
121
250
 
122
- swatches = _scale.domain().map((d: any) => {
123
251
  return {
124
- x: xScale(d),
125
- y: 0,
126
- width: Math.max(0, xScale.bandwidth() - 1),
127
- height,
128
- fill: _scale(d),
252
+ xScale,
253
+ swatches,
254
+ tickValues: tickValues,
255
+ tickFormat: tickFormat,
256
+ tickLabelOffset: 0,
257
+ tickLine: true,
258
+ tickLength: tickLengthProp,
259
+ interpolator: undefined,
129
260
  };
130
- });
261
+ } else {
262
+ // Ordinal
263
+
264
+ const xScale = scaleBand().domain(scale.domain()).rangeRound([0, width]);
265
+
266
+ const swatches = scale.domain().map((d: any) => {
267
+ return {
268
+ x: xScale(d),
269
+ y: 0,
270
+ width: Math.max(0, xScale.bandwidth() - 1),
271
+ height,
272
+ fill: scale(d),
273
+ };
274
+ });
131
275
 
132
- tickValues = _scale.domain();
133
- tickLabelOffset = xScale.bandwidth() / 2;
134
- tickLine = false;
135
- tickLength = 0;
136
- }
276
+ const tickValues = scale.domain();
277
+ const tickLabelOffset = xScale.bandwidth() / 2;
278
+ const tickLine = false;
279
+ const tickLength = 0;
280
+ return {
281
+ xScale,
282
+ tickFormat: tickFormatProp,
283
+ tickLabelOffset,
284
+ tickLine,
285
+ tickLength,
286
+ tickValues,
287
+ swatches,
288
+ interpolator: undefined,
289
+ };
290
+ }
291
+ });
137
292
  </script>
138
293
 
139
294
  <div
140
- {...$$restProps}
295
+ bind:this={ref}
296
+ {...restProps}
297
+ data-placement={placement}
141
298
  class={cls(
299
+ layerClass('legend-container'),
142
300
  'inline-block',
143
301
  'z-1', // stack above tooltip context layers (band rects, voronoi, ...)
144
302
  placement && [
@@ -155,80 +313,106 @@
155
313
  'bottom-right': 'bottom-0 right-0',
156
314
  }[placement],
157
315
  ],
158
- $$restProps.class,
316
+ className,
159
317
  classes.root
160
318
  )}
161
319
  >
162
- <div class={cls('text-[10px] font-semibold', classes.title)}>{title}</div>
163
- <slot values={tickValues ?? []} scale={_scale}>
164
- {#if variant === 'ramp'}
165
- <svg
166
- {width}
167
- height={height + tickLength + tickFontSize}
168
- viewBox="0 0 {width} {height + tickLength + tickFontSize}"
169
- class="overflow-visible"
170
- >
171
- <g>
172
- {#if interpolator}
173
- <ColorRamp {width} {height} {interpolator} />
174
- {:else if swatches}
175
- {#each swatches as swatch, i}
176
- <rect {...swatch} />
177
- {/each}
178
- {/if}
179
- </g>
180
-
181
- <g>
182
- {#each tickValues ?? xScale?.ticks?.(ticks) ?? [] as tick, i}
183
- <text
184
- text-anchor="middle"
185
- x={xScale(tick) + tickLabelOffset}
186
- y={height + tickLength + tickFontSize}
187
- style:font-size={tickFontSize}
188
- class={cls('text-[10px] fill-surface-content', classes.label)}
189
- >
190
- {tickFormat ? format(tick, tickFormat) : tick}
191
- </text>
192
-
193
- {#if tickLine}
194
- <line
195
- x1={xScale(tick)}
196
- y1={0}
197
- x2={xScale(tick)}
198
- y2={height + tickLength}
199
- class={cls('stroke-surface-content', classes.tick)}
200
- />
201
- {/if}
320
+ <div class={cls(layerClass('legend-title'), 'text-[10px] font-semibold', classes.title)}>
321
+ {title}
322
+ </div>
323
+ {#if children}
324
+ {@render children({
325
+ values: scaleConfig.tickValues ?? scaleConfig.xScale?.ticks?.(ticks) ?? [],
326
+ scale,
327
+ })}
328
+ {:else if variant === 'ramp'}
329
+ <svg
330
+ {width}
331
+ height={height + tickLengthProp + tickFontSize}
332
+ viewBox="0 0 {width} {height + tickLengthProp + tickFontSize}"
333
+ class={cls(layerClass('legend-ramp-svg'), 'overflow-visible')}
334
+ >
335
+ <g class={layerClass('legend-ramp-g')}>
336
+ {#if scaleConfig.interpolator}
337
+ <ColorRamp
338
+ {width}
339
+ {height}
340
+ interpolator={scaleConfig.interpolator}
341
+ class={layerClass('legend-color-ramp')}
342
+ />
343
+ {:else if scaleConfig.swatches}
344
+ {#each scaleConfig.swatches as swatch, i}
345
+ <rect {...extractLayerProps(swatch, 'legend-swatch')} />
202
346
  {/each}
203
- </g>
204
- </svg>
205
- {:else if variant === 'swatches'}
206
- <div
207
- class={cls(
208
- 'flex gap-x-4 gap-y-1',
209
- orientation === 'vertical' && 'flex-col',
210
- classes.swatches
211
- )}
212
- >
213
- {#each tickValues ?? xScale?.ticks?.(ticks) ?? [] as tick}
214
- {@const color = _scale(tick)}
215
- {@const item = { value: tick, color }}
216
- <button
217
- class={cls('flex gap-1', !onclick && 'cursor-auto', classes.item?.(item))}
218
- on:click={(e) => onclick?.(e, item)}
219
- on:pointerenter={(e) => onpointerenter?.(e, item)}
220
- on:pointerleave={(e) => onpointerleave?.(e, item)}
347
+ {/if}
348
+ </g>
349
+
350
+ <g class={layerClass('legend-tick-group')}>
351
+ {#each tickValuesProp ?? scaleConfig.xScale?.ticks?.(ticks) ?? [] as tick, i}
352
+ <text
353
+ text-anchor="middle"
354
+ x={scaleConfig.xScale?.(tick) + scaleConfig.tickLabelOffset}
355
+ y={height + tickLengthProp + tickFontSize}
356
+ style:font-size={tickFontSize}
357
+ class={cls(
358
+ layerClass('legend-tick-text'),
359
+ 'text-[10px] fill-surface-content',
360
+ classes.label
361
+ )}
221
362
  >
222
- <div
223
- class={cls('h-4 w-4 rounded-full', classes.swatch)}
224
- style:background-color={color}
225
- ></div>
226
- <div class={cls('text-xs text-surface-content whitespace-nowrap', classes.label)}>
227
- {tickFormat ? format(tick, tickFormat) : tick}
228
- </div>
229
- </button>
363
+ {tickFormatProp ? format(tick, tickFormatProp) : tick}
364
+ </text>
365
+
366
+ {#if scaleConfig.tickLine}
367
+ <line
368
+ x1={scaleConfig.xScale?.(tick)}
369
+ y1={0}
370
+ x2={scaleConfig.xScale?.(tick)}
371
+ y2={height + tickLengthProp}
372
+ class={cls(layerClass('legend-tick-line'), 'stroke-surface-content', classes.tick)}
373
+ />
374
+ {/if}
230
375
  {/each}
231
- </div>
232
- {/if}
233
- </slot>
376
+ </g>
377
+ </svg>
378
+ {:else if variant === 'swatches'}
379
+ <div
380
+ class={cls(
381
+ layerClass('legend-swatch-group'),
382
+ 'flex gap-x-4 gap-y-1',
383
+ orientation === 'vertical' && 'flex-col',
384
+ classes.swatches
385
+ )}
386
+ >
387
+ {#each scaleConfig.tickValues ?? scaleConfig.xScale?.ticks?.(ticks) ?? [] as tick}
388
+ {@const color = scale?.(tick) ?? ''}
389
+ {@const item = { value: tick, color }}
390
+ <button
391
+ class={cls(
392
+ layerClass('legend-swatch-button'),
393
+ 'flex gap-1',
394
+ !onclick && 'cursor-auto',
395
+ classes.item?.(item)
396
+ )}
397
+ onclick={(e) => onclick?.(e, item)}
398
+ onpointerenter={(e) => onpointerenter?.(e, item)}
399
+ onpointerleave={(e) => onpointerleave?.(e, item)}
400
+ >
401
+ <div
402
+ class={cls(layerClass('legend-swatch'), 'h-4 w-4 rounded-full', classes.swatch)}
403
+ style:background-color={color}
404
+ ></div>
405
+ <div
406
+ class={cls(
407
+ layerClass('legend-swatch-label'),
408
+ 'text-xs text-surface-content whitespace-nowrap',
409
+ classes.label
410
+ )}
411
+ >
412
+ {tickFormatProp ? format(tick, tickFormatProp) : tick}
413
+ </div>
414
+ </button>
415
+ {/each}
416
+ </div>
417
+ {/if}
234
418
  </div>