layerchart 0.53.0 → 0.54.1

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 (107) hide show
  1. package/dist/components/Arc.svelte +170 -144
  2. package/dist/components/Area.svelte +96 -67
  3. package/dist/components/Area.svelte.d.ts +1 -0
  4. package/dist/components/Axis.svelte +241 -234
  5. package/dist/components/Axis.svelte.d.ts +2 -1
  6. package/dist/components/Bar.svelte +72 -45
  7. package/dist/components/Bars.svelte +46 -34
  8. package/dist/components/Bars.svelte.d.ts +1 -0
  9. package/dist/components/Blur.svelte +5 -3
  10. package/dist/components/Bounds.svelte +37 -21
  11. package/dist/components/Brush.svelte +181 -110
  12. package/dist/components/Calendar.svelte +51 -38
  13. package/dist/components/Chart.svelte +296 -73
  14. package/dist/components/Chart.svelte.d.ts +42 -25
  15. package/dist/components/ChartClipPath.svelte +8 -5
  16. package/dist/components/ChartContext.svelte +243 -93
  17. package/dist/components/ChartContext.svelte.d.ts +15 -23
  18. package/dist/components/Circle.svelte +25 -16
  19. package/dist/components/CircleClipPath.svelte +16 -10
  20. package/dist/components/ClipPath.svelte +11 -7
  21. package/dist/components/ColorRamp.svelte +12 -10
  22. package/dist/components/ForceSimulation.svelte +185 -116
  23. package/dist/components/Frame.svelte +10 -6
  24. package/dist/components/GeoCircle.svelte +15 -9
  25. package/dist/components/GeoContext.svelte +109 -62
  26. package/dist/components/GeoEdgeFade.svelte +20 -14
  27. package/dist/components/GeoPath.svelte +107 -69
  28. package/dist/components/GeoPoint.svelte +32 -18
  29. package/dist/components/GeoSpline.svelte +30 -22
  30. package/dist/components/GeoTile.svelte +40 -30
  31. package/dist/components/GeoVisible.svelte +10 -7
  32. package/dist/components/Graticule.svelte +14 -8
  33. package/dist/components/Grid.svelte +178 -0
  34. package/dist/components/Grid.svelte.d.ts +35 -0
  35. package/dist/components/Group.svelte +43 -31
  36. package/dist/components/Highlight.svelte +284 -243
  37. package/dist/components/HitCanvas.svelte +75 -42
  38. package/dist/components/Hull.svelte +40 -20
  39. package/dist/components/Labels.svelte +84 -63
  40. package/dist/components/Labels.svelte.d.ts +2 -0
  41. package/dist/components/Legend.svelte +106 -75
  42. package/dist/components/Legend.svelte.d.ts +1 -1
  43. package/dist/components/Line.svelte +29 -19
  44. package/dist/components/LinearGradient.svelte +21 -15
  45. package/dist/components/Link.svelte +44 -22
  46. package/dist/components/MonthPath.svelte +23 -16
  47. package/dist/components/MotionPath.svelte +34 -25
  48. package/dist/components/Pack.svelte +21 -14
  49. package/dist/components/Partition.svelte +35 -20
  50. package/dist/components/Pattern.svelte +8 -6
  51. package/dist/components/Pie.svelte +76 -57
  52. package/dist/components/Point.svelte +11 -7
  53. package/dist/components/Points.svelte +178 -143
  54. package/dist/components/RadialGradient.svelte +25 -18
  55. package/dist/components/Rect.svelte +33 -19
  56. package/dist/components/RectClipPath.svelte +16 -11
  57. package/dist/components/Rule.svelte +66 -42
  58. package/dist/components/Rule.svelte.d.ts +2 -0
  59. package/dist/components/Sankey.svelte +55 -30
  60. package/dist/components/Spline.svelte +118 -96
  61. package/dist/components/Text.svelte +137 -104
  62. package/dist/components/Threshold.svelte +18 -7
  63. package/dist/components/TileImage.svelte +56 -50
  64. package/dist/components/TransformContext.svelte +238 -136
  65. package/dist/components/TransformControls.svelte +57 -29
  66. package/dist/components/TransformControls.svelte.d.ts +1 -1
  67. package/dist/components/Tree.svelte +33 -23
  68. package/dist/components/Treemap.svelte +69 -41
  69. package/dist/components/Voronoi.svelte +55 -28
  70. package/dist/components/charts/AreaChart.svelte +162 -87
  71. package/dist/components/charts/AreaChart.svelte.d.ts +41 -3
  72. package/dist/components/charts/BarChart.svelte +207 -108
  73. package/dist/components/charts/BarChart.svelte.d.ts +41 -3
  74. package/dist/components/charts/LineChart.svelte +119 -47
  75. package/dist/components/charts/LineChart.svelte.d.ts +41 -3
  76. package/dist/components/charts/PieChart.svelte +117 -53
  77. package/dist/components/charts/PieChart.svelte.d.ts +17 -2
  78. package/dist/components/charts/ScatterChart.svelte +92 -42
  79. package/dist/components/charts/ScatterChart.svelte.d.ts +39 -3
  80. package/dist/components/index.d.ts +1 -0
  81. package/dist/components/index.js +1 -0
  82. package/dist/components/layout/Canvas.svelte +63 -43
  83. package/dist/components/layout/Html.svelte +28 -18
  84. package/dist/components/layout/Svg.svelte +47 -32
  85. package/dist/components/tooltip/Tooltip.svelte +143 -82
  86. package/dist/components/tooltip/Tooltip.svelte.d.ts +1 -1
  87. package/dist/components/tooltip/TooltipContext.svelte +315 -248
  88. package/dist/components/tooltip/TooltipContext.svelte.d.ts +7 -0
  89. package/dist/components/tooltip/TooltipHeader.svelte +9 -3
  90. package/dist/components/tooltip/TooltipItem.svelte +17 -9
  91. package/dist/components/tooltip/TooltipList.svelte +2 -1
  92. package/dist/components/tooltip/TooltipSeparator.svelte +3 -2
  93. package/dist/docs/Blockquote.svelte +4 -3
  94. package/dist/docs/Code.svelte +15 -8
  95. package/dist/docs/CurveMenuField.svelte +17 -12
  96. package/dist/docs/GeoDebug.svelte +13 -9
  97. package/dist/docs/Header1.svelte +2 -1
  98. package/dist/docs/Json.svelte +6 -4
  99. package/dist/docs/Layout.svelte +6 -6
  100. package/dist/docs/PathDataMenuField.svelte +52 -44
  101. package/dist/docs/Preview.svelte +48 -29
  102. package/dist/docs/TilesetField.svelte +80 -62
  103. package/dist/docs/TransformDebug.svelte +8 -5
  104. package/dist/docs/ViewSourceButton.svelte +13 -9
  105. package/dist/stores/motionStore.d.ts +1 -1
  106. package/dist/utils/scales.d.ts +4 -4
  107. package/package.json +29 -30
@@ -1,308 +1,375 @@
1
- <script context="module">import { getContext, setContext } from 'svelte';
2
- export const tooltipContextKey = Symbol();
3
- const defaultContext = writable({
1
+ <script lang="ts" context="module">
2
+ import { getContext, setContext } from 'svelte';
3
+ import type { Readable } from 'svelte/store';
4
+
5
+ export const tooltipContextKey = Symbol();
6
+
7
+ export type TooltipContextValue = {
8
+ x: number;
9
+ y: number;
10
+ data: any;
11
+ show(e: PointerEvent, tooltipData?: any): void;
12
+ hide(e?: PointerEvent): void;
13
+ };
14
+
15
+ export type TooltipContext = Readable<TooltipContextValue>;
16
+
17
+ const defaultContext: TooltipContext = writable({
4
18
  x: 0,
5
19
  y: 0,
6
- data: null,
7
- show: () => { },
8
- hide: () => { },
9
- });
10
- export function tooltipContext() {
11
- return getContext(tooltipContextKey) ?? defaultContext;
12
- }
13
- function setTooltipContext(tooltip) {
20
+ data: null as any,
21
+ show: () => {},
22
+ hide: () => {},
23
+ });
24
+ export function tooltipContext() {
25
+ return getContext<TooltipContext>(tooltipContextKey) ?? defaultContext;
26
+ }
27
+
28
+ function setTooltipContext(tooltip: TooltipContext) {
14
29
  setContext(tooltipContextKey, tooltip);
15
- }
30
+ }
16
31
  </script>
17
32
 
18
- <script>import { raise } from 'layercake';
19
- import { writable } from 'svelte/store';
20
- import { bisector, max, min } from 'd3-array';
21
- import { quadtree as d3Quadtree } from 'd3-quadtree';
22
- import { sortFunc } from '@layerstack/utils';
23
- import { cls } from '@layerstack/tailwind';
24
- import Svg from './../layout/Svg.svelte';
25
- import { chartContext } from './../ChartContext.svelte';
26
- import ChartClipPath from './../ChartClipPath.svelte';
27
- import Voronoi from './../Voronoi.svelte';
28
- import { localPoint } from '../../utils/event.js';
29
- import { isScaleBand, scaleInvert } from '../../utils/scales.js';
30
- import { cartesianToPolar } from '../../utils/math.js';
31
- import { quadtreeRects } from '../../utils/quadtree.js';
32
- const { flatData, x, xScale, xGet, xRange, y, yScale, yGet, yRange, width, height, containerWidth, containerHeight, padding, radial, } = chartContext();
33
- /*
34
- TODO: Defaults to consider (if possible to detect scale type, which might not be possible)
35
- - scaleTime / scaleLinear: bisect
36
- - scaleTime / scaleLinear (multi/stack): bisect
37
- - scaleTime / scaleBand: bisect (or band)
38
- - scaleTime (multi) / scaleBand: bounds (or possible band if not overlapping)
39
- - scaleBand, scaleLinear: band (or bounds)
40
- - scaleBand, scaleLinear: band (or bounds) - multiple (overlapping) bars
41
- - scaleLinear, scaleLinear: voronoi (or quadtree)
42
- */
43
- /**
44
- * @type {'bisect-x' | 'bisect-y' | 'band' | 'bisect-band' | 'bounds' | 'voronoi' | 'quadtree' | 'manual'}
45
- */
46
- export let mode = 'manual';
47
- /**
48
- * @type {'closest' | 'left' | 'right'}
49
- */
50
- export let findTooltipData = 'closest';
51
- /** Similar to d3-selection's raise, re-insert the e.target as the last child of its parent, so to be the top-most element */
52
- export let raiseTarget = false;
53
- /** quadtree search radius
54
- * @type {number}
55
- */
56
- export let radius = Infinity;
57
- /** Enable debug view (show hit targets, etc) */
58
- export let debug = false;
59
- export let onClick = () => { };
60
- const tooltip = writable({
33
+ <script lang="ts">
34
+ import { raise } from 'layercake';
35
+ import { writable } from 'svelte/store';
36
+ import { bisector, max, min } from 'd3-array';
37
+ import { quadtree as d3Quadtree, type Quadtree } from 'd3-quadtree';
38
+ import { sortFunc } from '@layerstack/utils';
39
+ import { cls } from '@layerstack/tailwind';
40
+
41
+ import Svg from './../layout/Svg.svelte';
42
+ import { chartContext } from './../ChartContext.svelte';
43
+ import ChartClipPath from './../ChartClipPath.svelte';
44
+ import Voronoi from './../Voronoi.svelte';
45
+
46
+ import { localPoint } from '../../utils/event.js';
47
+ import { isScaleBand, scaleInvert } from '../../utils/scales.js';
48
+ import { cartesianToPolar } from '../../utils/math.js';
49
+ import { quadtreeRects } from '../../utils/quadtree.js';
50
+
51
+ const {
52
+ flatData,
53
+ x,
54
+ xScale,
55
+ xGet,
56
+ xRange,
57
+ y,
58
+ yScale,
59
+ yGet,
60
+ yRange,
61
+ width,
62
+ height,
63
+ containerWidth,
64
+ containerHeight,
65
+ padding,
66
+ radial,
67
+ } = chartContext<any>();
68
+
69
+ /*
70
+ TODO: Defaults to consider (if possible to detect scale type, which might not be possible)
71
+ - scaleTime / scaleLinear: bisect
72
+ - scaleTime / scaleLinear (multi/stack): bisect
73
+ - scaleTime / scaleBand: bisect (or band)
74
+ - scaleTime (multi) / scaleBand: bounds (or possible band if not overlapping)
75
+ - scaleBand, scaleLinear: band (or bounds)
76
+ - scaleBand, scaleLinear: band (or bounds) - multiple (overlapping) bars
77
+ - scaleLinear, scaleLinear: voronoi (or quadtree)
78
+ */
79
+
80
+ /**
81
+ * @type {'bisect-x' | 'bisect-y' | 'band' | 'bisect-band' | 'bounds' | 'voronoi' | 'quadtree' | 'manual'}
82
+ */
83
+ export let mode:
84
+ | 'bisect-x'
85
+ | 'bisect-y'
86
+ | 'band'
87
+ | 'bisect-band'
88
+ | 'bounds'
89
+ | 'voronoi'
90
+ | 'quadtree'
91
+ | 'manual' = 'manual';
92
+ /**
93
+ * @type {'closest' | 'left' | 'right'}
94
+ */
95
+ export let findTooltipData: 'closest' | 'left' | 'right' = 'closest';
96
+
97
+ /** Similar to d3-selection's raise, re-insert the e.target as the last child of its parent, so to be the top-most element */
98
+ export let raiseTarget = false;
99
+
100
+ /** quadtree search radius
101
+ * @type {number}
102
+ */
103
+ export let radius: number = Infinity;
104
+ /** Enable debug view (show hit targets, etc) */
105
+ export let debug = false;
106
+
107
+ export let onClick: ({ data }: { data: any }) => any = () => {};
108
+
109
+ /** Exposed to allow binding in Chart */
110
+ export let tooltip = writable({
61
111
  y: 0,
62
112
  x: 0,
63
- data: null,
113
+ data: null as any,
64
114
  show: showTooltip,
65
115
  hide: hideTooltip,
66
- });
67
- setTooltipContext(tooltip);
68
- let hideTimeoutId;
69
- $: bisectX = bisector((d) => {
116
+ });
117
+ setTooltipContext(tooltip);
118
+
119
+ let hideTimeoutId: NodeJS.Timeout;
120
+
121
+ $: bisectX = bisector((d: any) => {
70
122
  const value = $x(d);
71
123
  if (Array.isArray(value)) {
72
- // `x` accessor with multiple properties (ex. `x={['start', 'end']})`)
73
- // Using first value. Consider using average, max, etc
74
- // const midpoint = new Date((value[1].valueOf() + value[0].getTime()) / 2);
75
- // return midpoint;
76
- return value[0];
77
- }
78
- else {
79
- return value;
124
+ // `x` accessor with multiple properties (ex. `x={['start', 'end']})`)
125
+ // Using first value. Consider using average, max, etc
126
+ // const midpoint = new Date((value[1].valueOf() + value[0].getTime()) / 2);
127
+ // return midpoint;
128
+ return value[0];
129
+ } else {
130
+ return value;
80
131
  }
81
- }).left;
82
- $: bisectY = bisector((d) => {
132
+ }).left;
133
+
134
+ $: bisectY = bisector((d: any) => {
83
135
  const value = $y(d);
84
136
  if (Array.isArray(value)) {
85
- // `x` accessor with multiple properties (ex. `x={['start', 'end']})`)
86
- // Using first value. Consider using average, max, etc
87
- // const midpoint = new Date((value[1].valueOf() + value[0].getTime()) / 2);
88
- // return midpoint;
89
- return value[0];
90
- }
91
- else {
92
- return value;
137
+ // `x` accessor with multiple properties (ex. `x={['start', 'end']})`)
138
+ // Using first value. Consider using average, max, etc
139
+ // const midpoint = new Date((value[1].valueOf() + value[0].getTime()) / 2);
140
+ // return midpoint;
141
+ return value[0];
142
+ } else {
143
+ return value;
93
144
  }
94
- }).left;
95
- function findData(previousValue, currentValue, valueAtPoint, accessor) {
145
+ }).left;
146
+
147
+ function findData(previousValue: any, currentValue: any, valueAtPoint: any, accessor: Function) {
96
148
  switch (findTooltipData) {
97
- case 'closest':
98
- if (currentValue === undefined) {
99
- return previousValue;
100
- }
101
- else if (previousValue === undefined) {
102
- return currentValue;
103
- }
104
- else {
105
- return Number(valueAtPoint) - Number(accessor(previousValue)) >
106
- Number(accessor(currentValue)) - Number(valueAtPoint)
107
- ? currentValue
108
- : previousValue;
109
- }
110
- case 'left':
111
- return previousValue;
112
- case 'right':
113
- default:
114
- return currentValue;
149
+ case 'closest':
150
+ if (currentValue === undefined) {
151
+ return previousValue;
152
+ } else if (previousValue === undefined) {
153
+ return currentValue;
154
+ } else {
155
+ return Number(valueAtPoint) - Number(accessor(previousValue)) >
156
+ Number(accessor(currentValue)) - Number(valueAtPoint)
157
+ ? currentValue
158
+ : previousValue;
159
+ }
160
+ case 'left':
161
+ return previousValue;
162
+ case 'right':
163
+ default:
164
+ return currentValue;
115
165
  }
116
- }
117
- function showTooltip(e, tooltipData) {
166
+ }
167
+
168
+ function showTooltip(e: PointerEvent, tooltipData?: any) {
118
169
  // Cancel hiding tooltip if from previous event loop
119
170
  clearTimeout(hideTimeoutId);
120
- const referenceNode = e.target.closest('.layercake-container');
171
+
172
+ const referenceNode = (e.target as Element).closest('.layercake-container')!;
121
173
  const point = localPoint(referenceNode, e);
122
174
  const localX = point?.x ?? 0;
123
175
  const localY = point?.y ?? 0;
176
+
124
177
  if (
125
- // @ts-expect-error
126
- e.offsetX < e.currentTarget?.offsetLeft ||
127
- // @ts-expect-error
128
- e.offsetX > e.currentTarget?.offsetLeft + e.currentTarget?.offsetWidth ||
129
- // @ts-expect-error
130
- e.offsetY < e.currentTarget?.offsetTop ||
131
- // @ts-expect-error
132
- e.offsetY > e.currentTarget?.offsetTop + e.currentTarget?.offsetHeight) {
133
- // Ignore if within padding of chart
134
- hideTooltip();
135
- return;
178
+ // @ts-expect-error
179
+ e.offsetX < e.currentTarget?.offsetLeft ||
180
+ // @ts-expect-error
181
+ e.offsetX > e.currentTarget?.offsetLeft + e.currentTarget?.offsetWidth ||
182
+ // @ts-expect-error
183
+ e.offsetY < e.currentTarget?.offsetTop ||
184
+ // @ts-expect-error
185
+ e.offsetY > e.currentTarget?.offsetTop + e.currentTarget?.offsetHeight
186
+ ) {
187
+ // Ignore if within padding of chart
188
+ hideTooltip();
189
+ return;
136
190
  }
191
+
137
192
  // If tooltipData not provided already (voronoi, etc), attempt to find it
138
193
  // TODO: When using bisect-x/y/band, values should be sorted. Typically they are for `x`, but not `y` (and band depends on if x or y scale)
139
194
  if (tooltipData == null) {
140
- switch (mode) {
141
- case 'bisect-x': {
142
- let xValueAtPoint;
143
- if ($radial) {
144
- // Assume radial is always centered
145
- const { radians } = cartesianToPolar(localX - $width / 2, localY - $height / 2);
146
- xValueAtPoint = scaleInvert($xScale, radians);
147
- }
148
- else {
149
- xValueAtPoint = scaleInvert($xScale, localX - $padding.left);
150
- }
151
- const index = bisectX($flatData, xValueAtPoint, 1);
152
- const previousValue = $flatData[index - 1];
153
- const currentValue = $flatData[index];
154
- tooltipData = findData(previousValue, currentValue, xValueAtPoint, $x);
155
- break;
156
- }
157
- case 'bisect-y': {
158
- // `y` value at pointer coordinate
159
- const yValueAtPoint = scaleInvert($yScale, localY - $padding.top);
160
- const index = bisectY($flatData, yValueAtPoint, 1);
161
- const previousValue = $flatData[index - 1];
162
- const currentValue = $flatData[index];
163
- tooltipData = findData(previousValue, currentValue, yValueAtPoint, $y);
164
- break;
165
- }
166
- case 'bisect-band': {
167
- // `x` and `y` values at pointer coordinate
168
- const xValueAtPoint = scaleInvert($xScale, localX);
169
- const yValueAtPoint = scaleInvert($yScale, localY);
170
- if (isScaleBand($xScale)) {
171
- // Find point closest to pointer within the x band
172
- const bandData = $flatData
173
- .filter((d) => $x(d) === xValueAtPoint)
174
- .sort(sortFunc($y)); // sort for bisect
175
- const index = bisectY(bandData, yValueAtPoint, 1);
176
- const previousValue = bandData[index - 1];
177
- const currentValue = bandData[index];
178
- tooltipData = findData(previousValue, currentValue, yValueAtPoint, $y);
179
- }
180
- else if (isScaleBand($yScale)) {
181
- // Find point closest to pointer within the y band
182
- const bandData = $flatData
183
- .filter((d) => $y(d) === yValueAtPoint)
184
- .sort(sortFunc($x)); // sort for bisect
185
- const index = bisectX(bandData, xValueAtPoint, 1);
186
- const previousValue = bandData[index - 1];
187
- const currentValue = bandData[index];
188
- tooltipData = findData(previousValue, currentValue, xValueAtPoint, $x);
189
- }
190
- else {
191
- // TODO: Support `bisect-band` without band? Fallback to bisect?
192
- }
193
- break;
194
- }
195
- case 'quadtree': {
196
- tooltipData = quadtree.find(localX, localY, radius);
197
- break;
198
- }
195
+ switch (mode) {
196
+ case 'bisect-x': {
197
+ let xValueAtPoint: any;
198
+ if ($radial) {
199
+ // Assume radial is always centered
200
+ const { radians } = cartesianToPolar(localX - $width / 2, localY - $height / 2);
201
+ xValueAtPoint = scaleInvert($xScale, radians);
202
+ } else {
203
+ xValueAtPoint = scaleInvert($xScale, localX - $padding.left);
204
+ }
205
+
206
+ const index = bisectX($flatData, xValueAtPoint, 1);
207
+ const previousValue = $flatData[index - 1];
208
+ const currentValue = $flatData[index];
209
+ tooltipData = findData(previousValue, currentValue, xValueAtPoint, $x);
210
+ break;
199
211
  }
200
- }
201
- if (tooltipData) {
202
- if (raiseTarget) {
203
- raise(e.target);
212
+
213
+ case 'bisect-y': {
214
+ // `y` value at pointer coordinate
215
+ const yValueAtPoint = scaleInvert($yScale, localY - $padding.top);
216
+
217
+ const index = bisectY($flatData, yValueAtPoint, 1);
218
+ const previousValue = $flatData[index - 1];
219
+ const currentValue = $flatData[index];
220
+ tooltipData = findData(previousValue, currentValue, yValueAtPoint, $y);
221
+ break;
222
+ }
223
+
224
+ case 'bisect-band': {
225
+ // `x` and `y` values at pointer coordinate
226
+ const xValueAtPoint = scaleInvert($xScale, localX);
227
+ const yValueAtPoint = scaleInvert($yScale, localY);
228
+
229
+ if (isScaleBand($xScale)) {
230
+ // Find point closest to pointer within the x band
231
+ const bandData = $flatData
232
+ .filter((d) => $x(d) === xValueAtPoint)
233
+ .sort(sortFunc($y as () => any)); // sort for bisect
234
+ const index = bisectY(bandData, yValueAtPoint, 1);
235
+ const previousValue = bandData[index - 1];
236
+ const currentValue = bandData[index];
237
+ tooltipData = findData(previousValue, currentValue, yValueAtPoint, $y);
238
+ } else if (isScaleBand($yScale)) {
239
+ // Find point closest to pointer within the y band
240
+ const bandData = $flatData
241
+ .filter((d) => $y(d) === yValueAtPoint)
242
+ .sort(sortFunc($x as () => any)); // sort for bisect
243
+ const index = bisectX(bandData, xValueAtPoint, 1);
244
+ const previousValue = bandData[index - 1];
245
+ const currentValue = bandData[index];
246
+ tooltipData = findData(previousValue, currentValue, xValueAtPoint, $x);
247
+ } else {
248
+ // TODO: Support `bisect-band` without band? Fallback to bisect?
249
+ }
250
+ break;
251
+ }
252
+
253
+ case 'quadtree': {
254
+ tooltipData = quadtree.find(localX, localY, radius);
255
+ break;
204
256
  }
205
- $tooltip = {
206
- ...$tooltip,
207
- x: localX,
208
- y: localY,
209
- data: tooltipData,
210
- };
257
+ }
211
258
  }
212
- else {
213
- // Hide tooltip if unable to locate
214
- hideTooltip();
259
+
260
+ if (tooltipData) {
261
+ if (raiseTarget) {
262
+ raise(e.target as Element);
263
+ }
264
+
265
+ $tooltip = {
266
+ ...$tooltip,
267
+ x: localX,
268
+ y: localY,
269
+ data: tooltipData,
270
+ };
271
+ } else {
272
+ // Hide tooltip if unable to locate
273
+ hideTooltip();
215
274
  }
216
- }
217
- function hideTooltip() {
275
+ }
276
+
277
+ function hideTooltip() {
218
278
  // Wait an event loop tick in case `showTooltip` is called immediately on another element, to allow tweeneing (ex. moving between bands/bars)
219
279
  hideTimeoutId = setTimeout(() => {
220
- $tooltip = { ...$tooltip, data: null };
280
+ $tooltip = { ...$tooltip, data: null };
221
281
  });
222
- }
223
- let quadtree;
224
- $: if (mode === 'quadtree') {
282
+ }
283
+
284
+ let quadtree: Quadtree<[number, number]>;
285
+ $: if (mode === 'quadtree') {
225
286
  quadtree = d3Quadtree()
226
- .extent([
287
+ .extent([
227
288
  [0, 0],
228
289
  [$width, $height],
229
- ])
230
- .x((d) => {
290
+ ])
291
+ .x((d) => {
231
292
  const value = $xGet(d);
293
+
232
294
  if (Array.isArray(value)) {
233
- // `x` accessor with multiple properties (ex. `x={['start', 'end']})`)
234
- // Using first value. Consider using average, max, etc
235
- // const midpoint = new Date((value[1].valueOf() + value[0].getTime()) / 2);
236
- // return midpoint;
237
- return min(value);
238
- }
239
- else {
240
- return value;
295
+ // `x` accessor with multiple properties (ex. `x={['start', 'end']})`)
296
+ // Using first value. Consider using average, max, etc
297
+ // const midpoint = new Date((value[1].valueOf() + value[0].getTime()) / 2);
298
+ // return midpoint;
299
+ return min(value);
300
+ } else {
301
+ return value;
241
302
  }
242
- })
243
- .y((d) => {
303
+ })
304
+ .y((d) => {
244
305
  const value = $yGet(d);
306
+
245
307
  if (Array.isArray(value)) {
246
- // `x` accessor with multiple properties (ex. `x={['start', 'end']})`)
247
- // Using first value. Consider using average, max, etc
248
- // const midpoint = new Date((value[1].valueOf() + value[0].getTime()) / 2);
249
- // return midpoint;
250
- return min(value);
251
- }
252
- else {
253
- return value;
308
+ // `x` accessor with multiple properties (ex. `x={['start', 'end']})`)
309
+ // Using first value. Consider using average, max, etc
310
+ // const midpoint = new Date((value[1].valueOf() + value[0].getTime()) / 2);
311
+ // return midpoint;
312
+ return min(value);
313
+ } else {
314
+ return value;
254
315
  }
255
- })
256
- .addAll($flatData);
257
- }
258
- let rects = [];
259
- $: if (mode === 'bounds' || mode === 'band') {
316
+ })
317
+ .addAll($flatData as [number, number][]);
318
+ }
319
+
320
+ let rects: Array<{ x: number; y: number; width: number; height: number; data: any }> = [];
321
+ $: if (mode === 'bounds' || mode === 'band') {
260
322
  // @ts-expect-error
261
323
  rects = $flatData
262
- .map((d) => {
324
+ .map((d) => {
263
325
  const xValue = $xGet(d);
264
326
  const yValue = $yGet(d);
327
+
265
328
  const x = Array.isArray(xValue) ? xValue[0] : xValue;
266
329
  const y = Array.isArray(yValue) ? yValue[0] : yValue;
330
+
267
331
  const xOffset = isScaleBand($xScale) ? ($xScale.padding() * $xScale.step()) / 2 : 0;
268
332
  const yOffset = isScaleBand($yScale) ? ($yScale.padding() * $yScale.step()) / 2 : 0;
333
+
269
334
  // @ts-expect-error
270
335
  const fullWidth = max($xRange) - min($xRange);
271
336
  // @ts-expect-error
272
337
  const fullHeight = max($yRange) - min($yRange);
338
+
273
339
  if (mode === 'band') {
274
- // full band width/height regardless of value
275
- return {
276
- x: isScaleBand($xScale) ? x - xOffset : min($xRange),
277
- y: isScaleBand($yScale) ? y - yOffset : min($yRange),
278
- width: isScaleBand($xScale) ? $xScale.step() : fullWidth,
279
- height: isScaleBand($yScale) ? $yScale.step() : fullHeight,
280
- data: d,
281
- };
282
- }
283
- else if (mode === 'bounds') {
284
- return {
285
- x: isScaleBand($xScale) || Array.isArray(xValue) ? x - xOffset : min($xRange),
286
- // y: isScaleBand($yScale) || Array.isArray(yValue) ? y - yOffset : min($yRange),
287
- y: y - yOffset,
288
- width: Array.isArray(xValue)
289
- ? xValue[1] - xValue[0]
290
- : isScaleBand($xScale)
291
- ? $xScale.step()
292
- : min($xRange) + x,
293
- height: Array.isArray(yValue)
294
- ? yValue[1] - yValue[0]
295
- : isScaleBand($yScale)
296
- ? $yScale.step()
297
- : // @ts-expect-error
298
- max($yRange) - y,
299
- data: d,
300
- };
340
+ // full band width/height regardless of value
341
+ return {
342
+ x: isScaleBand($xScale) ? x - xOffset : min($xRange),
343
+ y: isScaleBand($yScale) ? y - yOffset : min($yRange),
344
+ width: isScaleBand($xScale) ? $xScale.step() : fullWidth,
345
+ height: isScaleBand($yScale) ? $yScale.step() : fullHeight,
346
+ data: d,
347
+ };
348
+ } else if (mode === 'bounds') {
349
+ return {
350
+ x: isScaleBand($xScale) || Array.isArray(xValue) ? x - xOffset : min($xRange),
351
+ // y: isScaleBand($yScale) || Array.isArray(yValue) ? y - yOffset : min($yRange),
352
+ y: y - yOffset,
353
+
354
+ width: Array.isArray(xValue)
355
+ ? xValue[1] - xValue[0]
356
+ : isScaleBand($xScale)
357
+ ? $xScale.step()
358
+ : min($xRange) + x,
359
+ height: Array.isArray(yValue)
360
+ ? yValue[1] - yValue[0]
361
+ : isScaleBand($yScale)
362
+ ? $yScale.step()
363
+ : // @ts-expect-error
364
+ max($yRange) - y,
365
+ data: d,
366
+ };
301
367
  }
302
- })
303
- .sort(sortFunc('x'));
304
- }
305
- $: triggerPointEvents = ['bisect-x', 'bisect-y', 'bisect-band', 'quadtree'].includes(mode);
368
+ })
369
+ .sort(sortFunc('x'));
370
+ }
371
+
372
+ $: triggerPointEvents = ['bisect-x', 'bisect-y', 'bisect-band', 'quadtree'].includes(mode);
306
373
  </script>
307
374
 
308
375
  <!-- svelte-ignore a11y-click-events-have-key-events -->
@@ -26,6 +26,13 @@ declare const __propDef: {
26
26
  onClick?: ({ data }: {
27
27
  data: any;
28
28
  }) => any;
29
+ /** Exposed to allow binding in Chart */ tooltip?: import("svelte/store").Writable<{
30
+ y: number;
31
+ x: number;
32
+ data: any;
33
+ show: (e: PointerEvent, tooltipData?: any) => void;
34
+ hide: () => void;
35
+ }>;
29
36
  };
30
37
  events: {
31
38
  [evt: string]: CustomEvent<any>;
@@ -1,6 +1,12 @@
1
- <script>import { cls } from '@layerstack/tailwind';
2
- export let color = undefined;
3
- export let classes = {};
1
+ <script lang="ts">
2
+ import { cls } from '@layerstack/tailwind';
3
+
4
+ export let color: string | undefined = undefined;
5
+
6
+ export let classes: {
7
+ root?: string;
8
+ color?: string;
9
+ } = {};
4
10
  </script>
5
11
 
6
12
  <div