@gravity-ui/charts 1.51.1 → 1.51.5

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 (197) hide show
  1. package/dist/cjs/components/index.js +25 -17
  2. package/dist/cjs/core/series/plugin.d.ts +14 -0
  3. package/dist/cjs/core/series/plugin.js +1 -0
  4. package/dist/cjs/core/series/prepareSeries.d.ts +3 -10
  5. package/dist/cjs/core/series/prepareSeries.js +3 -126
  6. package/dist/cjs/core/series/seriesRegistry.d.ts +3 -0
  7. package/dist/cjs/core/series/seriesRegistry.js +12 -0
  8. package/dist/cjs/core/shapes/area/get-tooltip-data.d.ts +3 -0
  9. package/dist/cjs/core/shapes/area/get-tooltip-data.js +19 -0
  10. package/dist/cjs/core/shapes/bar-x/get-tooltip-data.d.ts +3 -0
  11. package/dist/cjs/core/shapes/bar-x/get-tooltip-data.js +20 -0
  12. package/dist/cjs/core/shapes/bar-y/get-tooltip-data.d.ts +3 -0
  13. package/dist/cjs/core/shapes/bar-y/get-tooltip-data.js +32 -0
  14. package/dist/cjs/core/shapes/funnel/get-tooltip-data.d.ts +3 -0
  15. package/dist/cjs/core/shapes/funnel/get-tooltip-data.js +21 -0
  16. package/dist/cjs/core/shapes/funnel/prepare-data.js +6 -4
  17. package/dist/cjs/core/shapes/heatmap/get-tooltip-data.d.ts +3 -0
  18. package/dist/cjs/core/shapes/heatmap/get-tooltip-data.js +21 -0
  19. package/dist/cjs/core/shapes/line/get-tooltip-data.d.ts +3 -0
  20. package/dist/cjs/core/shapes/line/get-tooltip-data.js +18 -0
  21. package/dist/cjs/core/shapes/pie/get-tooltip-data.d.ts +3 -0
  22. package/dist/cjs/core/shapes/pie/get-tooltip-data.js +27 -0
  23. package/dist/cjs/core/shapes/radar/get-tooltip-data.d.ts +3 -0
  24. package/dist/cjs/core/shapes/radar/get-tooltip-data.js +35 -0
  25. package/dist/cjs/core/shapes/sankey/get-tooltip-data.d.ts +3 -0
  26. package/dist/cjs/core/shapes/sankey/get-tooltip-data.js +32 -0
  27. package/dist/cjs/core/shapes/scatter/get-tooltip-data.d.ts +3 -0
  28. package/dist/cjs/core/shapes/scatter/get-tooltip-data.js +19 -0
  29. package/dist/cjs/core/shapes/treemap/get-tooltip-data.d.ts +3 -0
  30. package/dist/cjs/core/shapes/treemap/get-tooltip-data.js +18 -0
  31. package/dist/cjs/core/shapes/waterfall/get-tooltip-data.d.ts +3 -0
  32. package/dist/cjs/core/shapes/waterfall/get-tooltip-data.js +15 -0
  33. package/dist/cjs/core/shapes/x-range/get-tooltip-data.d.ts +3 -0
  34. package/dist/cjs/core/shapes/x-range/get-tooltip-data.js +22 -0
  35. package/dist/cjs/core/types/chart/funnel.d.ts +9 -4
  36. package/dist/cjs/core/utils/get-closest-data.d.ts +2 -11
  37. package/dist/cjs/core/utils/get-closest-data.js +47 -326
  38. package/dist/cjs/core/utils/tooltip-helpers.d.ts +43 -0
  39. package/dist/cjs/core/utils/tooltip-helpers.js +72 -0
  40. package/dist/cjs/index.d.ts +1 -0
  41. package/dist/cjs/index.js +1 -0
  42. package/dist/cjs/plugins/area/index.d.ts +3 -0
  43. package/dist/cjs/plugins/area/index.js +5 -0
  44. package/dist/cjs/{core/series/prepare-area.d.ts → plugins/area/prepare.d.ts} +2 -2
  45. package/dist/cjs/{core/series/prepare-area.js → plugins/area/prepare.js} +4 -4
  46. package/dist/cjs/plugins/bar-x/index.d.ts +3 -0
  47. package/dist/cjs/plugins/bar-x/index.js +5 -0
  48. package/dist/{esm/core/series/prepare-bar-x.d.ts → cjs/plugins/bar-x/prepare.d.ts} +1 -1
  49. package/dist/{esm/core/series/prepare-bar-x.js → cjs/plugins/bar-x/prepare.js} +4 -4
  50. package/dist/cjs/plugins/bar-y/index.d.ts +3 -0
  51. package/dist/cjs/plugins/bar-y/index.js +5 -0
  52. package/dist/cjs/{core/series/prepare-bar-y.d.ts → plugins/bar-y/prepare.d.ts} +2 -2
  53. package/dist/cjs/{core/series/prepare-bar-y.js → plugins/bar-y/prepare.js} +4 -4
  54. package/dist/cjs/plugins/funnel/index.d.ts +3 -0
  55. package/dist/cjs/plugins/funnel/index.js +5 -0
  56. package/dist/cjs/{core/series/prepare-funnel.d.ts → plugins/funnel/prepare.d.ts} +2 -2
  57. package/dist/{esm/core/series/prepare-funnel.js → cjs/plugins/funnel/prepare.js} +15 -9
  58. package/dist/cjs/plugins/heatmap/index.d.ts +3 -0
  59. package/dist/cjs/plugins/heatmap/index.js +10 -0
  60. package/dist/{esm/core/series/prepare-heatmap.d.ts → cjs/plugins/heatmap/prepare.d.ts} +1 -1
  61. package/dist/{esm/core/series/prepare-heatmap.js → cjs/plugins/heatmap/prepare.js} +4 -4
  62. package/dist/cjs/plugins/index.d.ts +1 -0
  63. package/dist/cjs/plugins/index.js +27 -0
  64. package/dist/cjs/plugins/line/index.d.ts +3 -0
  65. package/dist/cjs/plugins/line/index.js +5 -0
  66. package/dist/cjs/{core/series/prepare-line.d.ts → plugins/line/prepare.d.ts} +2 -2
  67. package/dist/cjs/{core/series/prepare-line.js → plugins/line/prepare.js} +3 -3
  68. package/dist/cjs/plugins/pie/index.d.ts +3 -0
  69. package/dist/cjs/plugins/pie/index.js +5 -0
  70. package/dist/cjs/{core/series/prepare-pie.d.ts → plugins/pie/prepare.d.ts} +2 -2
  71. package/dist/cjs/plugins/pie/prepare.js +84 -0
  72. package/dist/cjs/plugins/radar/index.d.ts +3 -0
  73. package/dist/cjs/plugins/radar/index.js +5 -0
  74. package/dist/cjs/{core/series/prepare-radar.d.ts → plugins/radar/prepare.d.ts} +2 -2
  75. package/dist/cjs/{core/series/prepare-radar.js → plugins/radar/prepare.js} +4 -4
  76. package/dist/cjs/plugins/sankey/index.d.ts +3 -0
  77. package/dist/cjs/plugins/sankey/index.js +5 -0
  78. package/dist/cjs/{core/series/prepare-sankey.d.ts → plugins/sankey/prepare.d.ts} +1 -1
  79. package/dist/cjs/{core/series/prepare-sankey.js → plugins/sankey/prepare.js} +3 -3
  80. package/dist/cjs/plugins/scatter/index.d.ts +3 -0
  81. package/dist/cjs/plugins/scatter/index.js +10 -0
  82. package/dist/cjs/{core/series/prepare-scatter.d.ts → plugins/scatter/prepare.d.ts} +1 -1
  83. package/dist/{esm/core/series/prepare-scatter.js → cjs/plugins/scatter/prepare.js} +4 -4
  84. package/dist/cjs/plugins/treemap/index.d.ts +3 -0
  85. package/dist/cjs/plugins/treemap/index.js +5 -0
  86. package/dist/{esm/core/series/prepare-treemap.d.ts → cjs/plugins/treemap/prepare.d.ts} +1 -1
  87. package/dist/cjs/{core/series/prepare-treemap.js → plugins/treemap/prepare.js} +4 -4
  88. package/dist/cjs/plugins/waterfall/index.d.ts +3 -0
  89. package/dist/cjs/plugins/waterfall/index.js +5 -0
  90. package/dist/cjs/{core/series/prepare-waterfall.d.ts → plugins/waterfall/prepare.d.ts} +1 -1
  91. package/dist/{esm/core/series/prepare-waterfall.js → cjs/plugins/waterfall/prepare.js} +4 -4
  92. package/dist/cjs/plugins/x-range/index.d.ts +3 -0
  93. package/dist/cjs/plugins/x-range/index.js +5 -0
  94. package/dist/cjs/{core/series/prepare-x-range.d.ts → plugins/x-range/prepare.d.ts} +1 -1
  95. package/dist/cjs/{core/series/prepare-x-range.js → plugins/x-range/prepare.js} +4 -4
  96. package/dist/cjs/setup-jsdom.d.ts +1 -0
  97. package/dist/cjs/setup-jsdom.js +30 -4
  98. package/dist/esm/components/index.js +25 -17
  99. package/dist/esm/core/series/plugin.d.ts +14 -0
  100. package/dist/esm/core/series/plugin.js +1 -0
  101. package/dist/esm/core/series/prepareSeries.d.ts +3 -10
  102. package/dist/esm/core/series/prepareSeries.js +3 -126
  103. package/dist/esm/core/series/seriesRegistry.d.ts +3 -0
  104. package/dist/esm/core/series/seriesRegistry.js +12 -0
  105. package/dist/esm/core/shapes/area/get-tooltip-data.d.ts +3 -0
  106. package/dist/esm/core/shapes/area/get-tooltip-data.js +19 -0
  107. package/dist/esm/core/shapes/bar-x/get-tooltip-data.d.ts +3 -0
  108. package/dist/esm/core/shapes/bar-x/get-tooltip-data.js +20 -0
  109. package/dist/esm/core/shapes/bar-y/get-tooltip-data.d.ts +3 -0
  110. package/dist/esm/core/shapes/bar-y/get-tooltip-data.js +32 -0
  111. package/dist/esm/core/shapes/funnel/get-tooltip-data.d.ts +3 -0
  112. package/dist/esm/core/shapes/funnel/get-tooltip-data.js +21 -0
  113. package/dist/esm/core/shapes/funnel/prepare-data.js +6 -4
  114. package/dist/esm/core/shapes/heatmap/get-tooltip-data.d.ts +3 -0
  115. package/dist/esm/core/shapes/heatmap/get-tooltip-data.js +21 -0
  116. package/dist/esm/core/shapes/line/get-tooltip-data.d.ts +3 -0
  117. package/dist/esm/core/shapes/line/get-tooltip-data.js +18 -0
  118. package/dist/esm/core/shapes/pie/get-tooltip-data.d.ts +3 -0
  119. package/dist/esm/core/shapes/pie/get-tooltip-data.js +27 -0
  120. package/dist/esm/core/shapes/radar/get-tooltip-data.d.ts +3 -0
  121. package/dist/esm/core/shapes/radar/get-tooltip-data.js +35 -0
  122. package/dist/esm/core/shapes/sankey/get-tooltip-data.d.ts +3 -0
  123. package/dist/esm/core/shapes/sankey/get-tooltip-data.js +32 -0
  124. package/dist/esm/core/shapes/scatter/get-tooltip-data.d.ts +3 -0
  125. package/dist/esm/core/shapes/scatter/get-tooltip-data.js +19 -0
  126. package/dist/esm/core/shapes/treemap/get-tooltip-data.d.ts +3 -0
  127. package/dist/esm/core/shapes/treemap/get-tooltip-data.js +18 -0
  128. package/dist/esm/core/shapes/waterfall/get-tooltip-data.d.ts +3 -0
  129. package/dist/esm/core/shapes/waterfall/get-tooltip-data.js +15 -0
  130. package/dist/esm/core/shapes/x-range/get-tooltip-data.d.ts +3 -0
  131. package/dist/esm/core/shapes/x-range/get-tooltip-data.js +22 -0
  132. package/dist/esm/core/types/chart/funnel.d.ts +9 -4
  133. package/dist/esm/core/utils/get-closest-data.d.ts +2 -11
  134. package/dist/esm/core/utils/get-closest-data.js +47 -326
  135. package/dist/esm/core/utils/tooltip-helpers.d.ts +43 -0
  136. package/dist/esm/core/utils/tooltip-helpers.js +72 -0
  137. package/dist/esm/index.d.ts +1 -0
  138. package/dist/esm/index.js +1 -0
  139. package/dist/esm/plugins/area/index.d.ts +3 -0
  140. package/dist/esm/plugins/area/index.js +5 -0
  141. package/dist/esm/{core/series/prepare-area.d.ts → plugins/area/prepare.d.ts} +2 -2
  142. package/dist/esm/{core/series/prepare-area.js → plugins/area/prepare.js} +4 -4
  143. package/dist/esm/plugins/bar-x/index.d.ts +3 -0
  144. package/dist/esm/plugins/bar-x/index.js +5 -0
  145. package/dist/{cjs/core/series/prepare-bar-x.d.ts → esm/plugins/bar-x/prepare.d.ts} +1 -1
  146. package/dist/{cjs/core/series/prepare-bar-x.js → esm/plugins/bar-x/prepare.js} +4 -4
  147. package/dist/esm/plugins/bar-y/index.d.ts +3 -0
  148. package/dist/esm/plugins/bar-y/index.js +5 -0
  149. package/dist/esm/{core/series/prepare-bar-y.d.ts → plugins/bar-y/prepare.d.ts} +5 -5
  150. package/dist/esm/{core/series/prepare-bar-y.js → plugins/bar-y/prepare.js} +4 -4
  151. package/dist/esm/plugins/funnel/index.d.ts +3 -0
  152. package/dist/esm/plugins/funnel/index.js +5 -0
  153. package/dist/esm/{core/series/prepare-funnel.d.ts → plugins/funnel/prepare.d.ts} +2 -2
  154. package/dist/{cjs/core/series/prepare-funnel.js → esm/plugins/funnel/prepare.js} +15 -9
  155. package/dist/esm/plugins/heatmap/index.d.ts +3 -0
  156. package/dist/esm/plugins/heatmap/index.js +10 -0
  157. package/dist/{cjs/core/series/prepare-heatmap.d.ts → esm/plugins/heatmap/prepare.d.ts} +1 -1
  158. package/dist/{cjs/core/series/prepare-heatmap.js → esm/plugins/heatmap/prepare.js} +4 -4
  159. package/dist/esm/plugins/index.d.ts +1 -0
  160. package/dist/esm/plugins/index.js +27 -0
  161. package/dist/esm/plugins/line/index.d.ts +3 -0
  162. package/dist/esm/plugins/line/index.js +5 -0
  163. package/dist/esm/{core/series/prepare-line.d.ts → plugins/line/prepare.d.ts} +2 -2
  164. package/dist/esm/{core/series/prepare-line.js → plugins/line/prepare.js} +3 -3
  165. package/dist/esm/plugins/pie/index.d.ts +3 -0
  166. package/dist/esm/plugins/pie/index.js +5 -0
  167. package/dist/esm/{core/series/prepare-pie.d.ts → plugins/pie/prepare.d.ts} +2 -2
  168. package/dist/esm/plugins/pie/prepare.js +84 -0
  169. package/dist/esm/plugins/radar/index.d.ts +3 -0
  170. package/dist/esm/plugins/radar/index.js +5 -0
  171. package/dist/esm/{core/series/prepare-radar.d.ts → plugins/radar/prepare.d.ts} +2 -2
  172. package/dist/esm/{core/series/prepare-radar.js → plugins/radar/prepare.js} +4 -4
  173. package/dist/esm/plugins/sankey/index.d.ts +3 -0
  174. package/dist/esm/plugins/sankey/index.js +5 -0
  175. package/dist/esm/{core/series/prepare-sankey.d.ts → plugins/sankey/prepare.d.ts} +1 -1
  176. package/dist/esm/{core/series/prepare-sankey.js → plugins/sankey/prepare.js} +3 -3
  177. package/dist/esm/plugins/scatter/index.d.ts +3 -0
  178. package/dist/esm/plugins/scatter/index.js +10 -0
  179. package/dist/esm/{core/series/prepare-scatter.d.ts → plugins/scatter/prepare.d.ts} +1 -1
  180. package/dist/{cjs/core/series/prepare-scatter.js → esm/plugins/scatter/prepare.js} +4 -4
  181. package/dist/esm/plugins/treemap/index.d.ts +3 -0
  182. package/dist/esm/plugins/treemap/index.js +5 -0
  183. package/dist/{cjs/core/series/prepare-treemap.d.ts → esm/plugins/treemap/prepare.d.ts} +1 -1
  184. package/dist/esm/{core/series/prepare-treemap.js → plugins/treemap/prepare.js} +4 -4
  185. package/dist/esm/plugins/waterfall/index.d.ts +3 -0
  186. package/dist/esm/plugins/waterfall/index.js +5 -0
  187. package/dist/esm/{core/series/prepare-waterfall.d.ts → plugins/waterfall/prepare.d.ts} +1 -1
  188. package/dist/{cjs/core/series/prepare-waterfall.js → esm/plugins/waterfall/prepare.js} +4 -4
  189. package/dist/esm/plugins/x-range/index.d.ts +3 -0
  190. package/dist/esm/plugins/x-range/index.js +5 -0
  191. package/dist/esm/{core/series/prepare-x-range.d.ts → plugins/x-range/prepare.d.ts} +1 -1
  192. package/dist/esm/{core/series/prepare-x-range.js → plugins/x-range/prepare.js} +4 -4
  193. package/dist/esm/setup-jsdom.d.ts +1 -0
  194. package/dist/esm/setup-jsdom.js +30 -4
  195. package/package.json +4 -2
  196. package/dist/cjs/core/series/prepare-pie.js +0 -83
  197. package/dist/esm/core/series/prepare-pie.js +0 -83
@@ -1,4 +1,4 @@
1
- "use strict";
1
+ import './plugins';
2
2
  // Global mocks for jsdom environment.
3
3
  // Guarded by typeof checks so this file is safe to run in the `node` environment too.
4
4
  if (typeof document !== 'undefined') {
@@ -11,10 +11,36 @@ if (typeof document !== 'undefined') {
11
11
  }
12
12
  }
13
13
  if (typeof ResizeObserver === 'undefined') {
14
+ const resizeObserverCallbacks = new Map();
14
15
  global.ResizeObserver = class ResizeObserver {
15
- observe() { }
16
- unobserve() { }
17
- disconnect() { }
16
+ constructor(callback) {
17
+ this.callback = callback;
18
+ }
19
+ observe(target) {
20
+ if (!resizeObserverCallbacks.has(target)) {
21
+ resizeObserverCallbacks.set(target, new Set());
22
+ }
23
+ resizeObserverCallbacks.get(target).add(this.callback);
24
+ }
25
+ unobserve(target) {
26
+ var _a;
27
+ (_a = resizeObserverCallbacks.get(target)) === null || _a === void 0 ? void 0 : _a.delete(this.callback);
28
+ }
29
+ disconnect() {
30
+ resizeObserverCallbacks.forEach((callbacks) => {
31
+ callbacks.delete(this.callback);
32
+ });
33
+ }
34
+ };
35
+ /**
36
+ * Test helper: simulate a ResizeObserver notification for the given element.
37
+ */
38
+ global.__triggerResizeObserver = (target) => {
39
+ const callbacks = resizeObserverCallbacks.get(target);
40
+ if (callbacks) {
41
+ const entry = [{ target, contentRect: target.getBoundingClientRect() }];
42
+ callbacks.forEach((cb) => cb(entry, {}));
43
+ }
18
44
  };
19
45
  }
20
46
  if (typeof HTMLCanvasElement !== 'undefined') {
@@ -1,8 +1,6 @@
1
1
  import React from 'react';
2
- import { select } from 'd3-selection';
3
2
  import debounce from 'lodash/debounce';
4
3
  import { i18nFactory } from '../core/i18n';
5
- import { getUniqId } from '../core/utils';
6
4
  import { validateData } from '../core/validation';
7
5
  import { ChartInner } from './ChartInner';
8
6
  export * from './Tooltip/ChartTooltipContent';
@@ -17,11 +15,22 @@ export const Chart = React.forwardRef(function Chart(props, forwardedRef) {
17
15
  validateData(data);
18
16
  validatedData.current = data;
19
17
  }
20
- const handleResize = React.useCallback(() => {
18
+ const handleResize = React.useCallback((options) => {
21
19
  var _a;
22
20
  const parentElement = (_a = ref.current) === null || _a === void 0 ? void 0 : _a.parentElement;
23
21
  if (parentElement) {
24
- setDimensions({ width: parentElement.clientWidth, height: parentElement.clientHeight });
22
+ const nextDimensions = {
23
+ width: parentElement.clientWidth,
24
+ height: parentElement.clientHeight,
25
+ };
26
+ setDimensions((currentDimensions) => {
27
+ if (!(options === null || options === void 0 ? void 0 : options.force) &&
28
+ (currentDimensions === null || currentDimensions === void 0 ? void 0 : currentDimensions.width) === nextDimensions.width &&
29
+ currentDimensions.height === nextDimensions.height) {
30
+ return currentDimensions;
31
+ }
32
+ return nextDimensions;
33
+ });
25
34
  }
26
35
  }, []);
27
36
  const debuncedHandleResize = React.useMemo(() => {
@@ -33,10 +42,10 @@ export const Chart = React.forwardRef(function Chart(props, forwardedRef) {
33
42
  React.useImperativeHandle(forwardedRef, () => ({
34
43
  reflow(options) {
35
44
  if (options === null || options === void 0 ? void 0 : options.immediate) {
36
- handleResize();
45
+ handleResize({ force: true });
37
46
  }
38
47
  else {
39
- debuncedHandleResize();
48
+ debuncedHandleResize({ force: true });
40
49
  }
41
50
  },
42
51
  }), [debuncedHandleResize, handleResize]);
@@ -45,19 +54,18 @@ export const Chart = React.forwardRef(function Chart(props, forwardedRef) {
45
54
  handleResize();
46
55
  }, [handleResize]);
47
56
  React.useEffect(() => {
48
- const selection = select(window);
49
- // https://github.com/d3/d3-selection/blob/main/README.md#handling-events
50
- const eventName = `resize.${getUniqId()}`;
51
- selection.on(eventName, debuncedHandleResize);
52
- window.addEventListener('transitionend', handleResize, { capture: true });
53
- window.addEventListener('animationend', handleResize, { capture: true });
57
+ var _a;
58
+ const parentElement = (_a = ref.current) === null || _a === void 0 ? void 0 : _a.parentElement;
59
+ if (!parentElement) {
60
+ return undefined;
61
+ }
62
+ const observer = new ResizeObserver(() => debuncedHandleResize());
63
+ observer.observe(parentElement);
54
64
  return () => {
55
- // https://d3js.org/d3-selection/events#selection_on
56
- selection.on(eventName, null);
57
- window.removeEventListener('transitionend', handleResize, { capture: true });
58
- window.removeEventListener('animationend', handleResize, { capture: true });
65
+ observer.disconnect();
66
+ debuncedHandleResize.cancel();
59
67
  };
60
- }, [debuncedHandleResize, handleResize]);
68
+ }, [debuncedHandleResize]);
61
69
  React.useEffect(() => {
62
70
  if (typeof onResize === 'function') {
63
71
  onResize({ dimensions });
@@ -0,0 +1,14 @@
1
+ import type { ScaleOrdinal } from 'd3-scale';
2
+ import type { ChartSeries, ChartSeriesOptions } from '../../types';
3
+ import type { PreparedLegend, PreparedSeries } from './types';
4
+ export interface PrepareSeriesArgs {
5
+ series: ChartSeries[];
6
+ seriesOptions?: ChartSeriesOptions;
7
+ legend: PreparedLegend;
8
+ colorScale: ScaleOrdinal<string, string>;
9
+ colors: string[];
10
+ }
11
+ export interface SeriesPlugin<T extends ChartSeries = ChartSeries> {
12
+ type: T['type'];
13
+ prepareSeries(args: PrepareSeriesArgs): PreparedSeries[] | Promise<PreparedSeries[]>;
14
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,5 +1,5 @@
1
- import type { ScaleOrdinal } from 'd3-scale';
2
- import type { ChartData, ChartSeries, ChartSeriesOptions } from '../../types';
1
+ import type { ChartData } from '../../types';
2
+ import type { PrepareSeriesArgs } from './plugin';
3
3
  import type { PreparedLegend, PreparedSeries } from './types';
4
4
  export declare const getPreparedSeries: ({ seriesData, seriesOptions, colors, preparedLegend, }: {
5
5
  seriesData: ChartData["series"]["data"];
@@ -7,11 +7,4 @@ export declare const getPreparedSeries: ({ seriesData, seriesOptions, colors, pr
7
7
  colors: string[];
8
8
  preparedLegend?: PreparedLegend | null;
9
9
  }) => Promise<PreparedSeries[]>;
10
- export declare function prepareSeries(args: {
11
- type: ChartSeries['type'];
12
- series: ChartSeries[];
13
- seriesOptions?: ChartSeriesOptions;
14
- legend: PreparedLegend;
15
- colors: string[];
16
- colorScale: ScaleOrdinal<string, string>;
17
- }): Promise<PreparedSeries[]>;
10
+ export declare function prepareSeries(args: PrepareSeriesArgs): Promise<PreparedSeries[]>;
@@ -1,20 +1,7 @@
1
1
  import { group } from 'd3-array';
2
2
  import { scaleOrdinal } from 'd3-scale';
3
- import { ChartError } from '../../libs';
4
3
  import { getSeriesNames } from '../utils';
5
- import { prepareArea } from './prepare-area';
6
- import { prepareBarXSeries } from './prepare-bar-x';
7
- import { prepareBarYSeries } from './prepare-bar-y';
8
- import { prepareFunnelSeries } from './prepare-funnel';
9
- import { prepareHeatmapSeries } from './prepare-heatmap';
10
- import { prepareLineSeries } from './prepare-line';
11
- import { preparePieSeries } from './prepare-pie';
12
- import { prepareRadarSeries } from './prepare-radar';
13
- import { prepareSankeySeries } from './prepare-sankey';
14
- import { prepareScatterSeries } from './prepare-scatter';
15
- import { prepareTreemap } from './prepare-treemap';
16
- import { prepareWaterfallSeries } from './prepare-waterfall';
17
- import { prepareXRangeSeries } from './prepare-x-range';
4
+ import { getSeriesPlugin } from './seriesRegistry';
18
5
  export const getPreparedSeries = async ({ seriesData, seriesOptions, colors, preparedLegend, }) => {
19
6
  const seriesNames = getSeriesNames(seriesData);
20
7
  const colorScale = scaleOrdinal(seriesNames, colors);
@@ -31,9 +18,7 @@ export const getPreparedSeries = async ({ seriesData, seriesOptions, colors, pre
31
18
  const list = Array.from(groupedSeries);
32
19
  for (let i = 0; i < list.length; i++) {
33
20
  const [_groupId, seriesList] = list[i];
34
- const seriesType = seriesList[0].type;
35
21
  acc.push(...(await prepareSeries({
36
- type: seriesType,
37
22
  series: seriesList,
38
23
  seriesOptions,
39
24
  legend: preparedLegend,
@@ -44,114 +29,6 @@ export const getPreparedSeries = async ({ seriesData, seriesOptions, colors, pre
44
29
  return acc;
45
30
  };
46
31
  export async function prepareSeries(args) {
47
- const { type, series, seriesOptions, legend, colors, colorScale } = args;
48
- switch (type) {
49
- case 'pie': {
50
- return series.reduce((acc, singleSeries) => {
51
- acc.push(...preparePieSeries({
52
- series: singleSeries,
53
- seriesOptions,
54
- legend,
55
- colors,
56
- }));
57
- return acc;
58
- }, []);
59
- }
60
- case 'bar-x': {
61
- return prepareBarXSeries({
62
- series: series,
63
- legend,
64
- colorScale,
65
- seriesOptions,
66
- });
67
- }
68
- case 'bar-y': {
69
- return await prepareBarYSeries({
70
- series: series,
71
- legend,
72
- colorScale,
73
- seriesOptions,
74
- });
75
- }
76
- case 'scatter': {
77
- return prepareScatterSeries({ series: series, legend, colorScale });
78
- }
79
- case 'line': {
80
- return prepareLineSeries({
81
- series: series,
82
- seriesOptions,
83
- legend,
84
- colorScale,
85
- });
86
- }
87
- case 'area': {
88
- return prepareArea({
89
- series: series,
90
- seriesOptions,
91
- legend,
92
- colorScale,
93
- });
94
- }
95
- case 'treemap': {
96
- return prepareTreemap({
97
- series: series,
98
- seriesOptions,
99
- legend,
100
- colorScale,
101
- });
102
- }
103
- case 'waterfall': {
104
- return prepareWaterfallSeries({
105
- series: series,
106
- legend,
107
- colorScale,
108
- colors,
109
- });
110
- }
111
- case 'sankey': {
112
- return prepareSankeySeries({
113
- series: series,
114
- seriesOptions,
115
- colorScale,
116
- legend,
117
- });
118
- }
119
- case 'radar': {
120
- return prepareRadarSeries({
121
- series: series,
122
- seriesOptions,
123
- legend,
124
- colors,
125
- });
126
- }
127
- case 'heatmap': {
128
- return await prepareHeatmapSeries({
129
- series: series,
130
- legend,
131
- colorScale,
132
- seriesOptions,
133
- });
134
- }
135
- case 'funnel': {
136
- return prepareFunnelSeries({
137
- series: series[0],
138
- seriesOptions,
139
- legend,
140
- colors,
141
- });
142
- }
143
- case 'x-range': {
144
- return prepareXRangeSeries({
145
- series: series,
146
- seriesOptions,
147
- legend,
148
- colorScale,
149
- });
150
- }
151
- default: {
152
- throw new ChartError({
153
- message: `Series type "${type}" does not support data preparation for series that do not support the presence of axes`,
154
- });
155
- }
156
- }
32
+ const plugin = getSeriesPlugin(args.series[0].type);
33
+ return plugin.prepareSeries(args);
157
34
  }
@@ -0,0 +1,3 @@
1
+ import type { SeriesPlugin } from './plugin';
2
+ export declare function registerSeriesPlugin(plugin: SeriesPlugin): void;
3
+ export declare function getSeriesPlugin(type: string): SeriesPlugin;
@@ -0,0 +1,12 @@
1
+ import { ChartError } from '../../libs';
2
+ const registry = new Map();
3
+ export function registerSeriesPlugin(plugin) {
4
+ registry.set(plugin.type, plugin);
5
+ }
6
+ export function getSeriesPlugin(type) {
7
+ const plugin = registry.get(type);
8
+ if (!plugin) {
9
+ throw new ChartError({ message: `Unknown series type: "${type}"` });
10
+ }
11
+ return plugin;
12
+ }
@@ -0,0 +1,3 @@
1
+ import type { GetTooltipDataArgs, GetTooltipDataResult } from '../../utils/tooltip-helpers';
2
+ import type { PreparedAreaData } from './types';
3
+ export declare function getTooltipData(args: GetTooltipDataArgs<PreparedAreaData>): GetTooltipDataResult;
@@ -0,0 +1,19 @@
1
+ export function getTooltipData(args) {
2
+ const { data } = args;
3
+ const xLookupPoints = data.reduce((acc, d) => {
4
+ for (const p of d.points) {
5
+ if (p.y === null || p.hiddenInLine) {
6
+ continue;
7
+ }
8
+ acc.push({
9
+ data: p.data,
10
+ series: p.series,
11
+ x: p.x,
12
+ y0: p.y0,
13
+ y1: p.y,
14
+ });
15
+ }
16
+ return acc;
17
+ }, []);
18
+ return { chunks: [], xLookupPoints };
19
+ }
@@ -0,0 +1,3 @@
1
+ import type { GetTooltipDataArgs, GetTooltipDataResult } from '../../utils/tooltip-helpers';
2
+ import type { PreparedBarXData } from './types';
3
+ export declare function getTooltipData(args: GetTooltipDataArgs<PreparedBarXData>): GetTooltipDataResult;
@@ -0,0 +1,20 @@
1
+ import groupBy from 'lodash/groupBy';
2
+ export function getTooltipData(args) {
3
+ const { data } = args;
4
+ const barXGroups = groupBy(data, (d) => String(d.data.x));
5
+ const xLookupPoints = [];
6
+ for (const group of Object.values(barXGroups)) {
7
+ const groupCenterX = group.reduce((sum, d) => sum + d.x + d.width / 2, 0) / group.length;
8
+ for (const d of group) {
9
+ xLookupPoints.push({
10
+ data: d.data,
11
+ series: d.series,
12
+ x: groupCenterX,
13
+ y0: d.y,
14
+ y1: d.y + d.height,
15
+ sourceX: d.x + d.width / 2,
16
+ });
17
+ }
18
+ }
19
+ return { chunks: [], xLookupPoints };
20
+ }
@@ -0,0 +1,3 @@
1
+ import type { GetTooltipDataArgs, GetTooltipDataResult } from '../../utils/tooltip-helpers';
2
+ import type { PreparedBarYData } from './types';
3
+ export declare function getTooltipData(args: GetTooltipDataArgs<PreparedBarYData>): GetTooltipDataResult;
@@ -0,0 +1,32 @@
1
+ import { bisector, sort } from 'd3-array';
2
+ export function getTooltipData(args) {
3
+ var _a, _b;
4
+ const { data, position } = args;
5
+ const [pointerX, pointerY] = position;
6
+ const sorted = sort(data, (p) => p.y);
7
+ const closestYIndex = bisector((p) => p.y + p.height / 2).center(sorted, pointerY);
8
+ const closestYPoint = sorted[closestYIndex];
9
+ if (!closestYPoint) {
10
+ return { chunks: [] };
11
+ }
12
+ const selectedPoints = data.filter((p) => p.data.y === closestYPoint.data.y);
13
+ const closestPoints = sort(selectedPoints.filter((p) => p.y === closestYPoint.y), (p) => p.x);
14
+ let closestPointXValue;
15
+ const lastPoint = closestPoints[closestPoints.length - 1];
16
+ if (pointerX < ((_a = closestPoints[0]) === null || _a === void 0 ? void 0 : _a.x)) {
17
+ closestPointXValue = closestPoints[0].x;
18
+ }
19
+ else if (lastPoint && pointerX > lastPoint.x + lastPoint.width) {
20
+ closestPointXValue = lastPoint.x;
21
+ }
22
+ else {
23
+ closestPointXValue = (_b = closestPoints.find((p) => pointerX > p.x && pointerX < p.x + p.width)) === null || _b === void 0 ? void 0 : _b.x;
24
+ }
25
+ return {
26
+ chunks: selectedPoints.map((p) => ({
27
+ data: p.data,
28
+ series: p.series,
29
+ closest: p.x === closestPointXValue && p.y === closestYPoint.y,
30
+ })),
31
+ };
32
+ }
@@ -0,0 +1,3 @@
1
+ import type { GetTooltipDataArgs, GetTooltipDataResult } from '../../utils/tooltip-helpers';
2
+ import type { PreparedFunnelData } from './types';
3
+ export declare function getTooltipData(args: GetTooltipDataArgs<PreparedFunnelData>): GetTooltipDataResult;
@@ -0,0 +1,21 @@
1
+ export function getTooltipData(args) {
2
+ var _a;
3
+ const { data, position } = args;
4
+ const [pointerX, pointerY] = position;
5
+ const closestPoint = (_a = data[0]) === null || _a === void 0 ? void 0 : _a.items.find((item) => pointerX >= item.x &&
6
+ pointerX <= item.x + item.width &&
7
+ pointerY >= item.y &&
8
+ pointerY <= item.y + item.height);
9
+ if (!closestPoint) {
10
+ return { chunks: [] };
11
+ }
12
+ return {
13
+ chunks: [
14
+ {
15
+ data: closestPoint.data,
16
+ series: closestPoint.series,
17
+ closest: true,
18
+ },
19
+ ],
20
+ };
21
+ }
@@ -128,11 +128,13 @@ export async function prepareFunnelData(args) {
128
128
  const prevSeries = series[index - 1];
129
129
  const prevItem = items[index - 1];
130
130
  if (prevSeries && prevItem && ((_e = prevSeries.connectors) === null || _e === void 0 ? void 0 : _e.enabled)) {
131
+ // Use the actual bottom corners of the previous segment (points[3]/[2]) so that
132
+ // trapezoid segments (whose bottom edge differs from the top edge) are handled correctly.
131
133
  const connectorPoints = [
132
- [prevItem.x, prevItem.y + prevItem.height],
133
- [prevItem.x + prevItem.width, prevItem.y + prevItem.height],
134
- [funnelSegment.x + funnelSegment.width, funnelSegment.y],
135
- [funnelSegment.x, funnelSegment.y],
134
+ prevItem.points[3],
135
+ prevItem.points[2],
136
+ funnelSegment.points[1],
137
+ funnelSegment.points[0],
136
138
  ];
137
139
  connectors.push({
138
140
  linePath: getLineConnectorPaths({ points: connectorPoints }),
@@ -0,0 +1,3 @@
1
+ import type { GetTooltipDataArgs, GetTooltipDataResult } from '../../utils/tooltip-helpers';
2
+ import type { PreparedHeatmapData } from './types';
3
+ export declare function getTooltipData(args: GetTooltipDataArgs<PreparedHeatmapData>): GetTooltipDataResult;
@@ -0,0 +1,21 @@
1
+ export function getTooltipData(args) {
2
+ var _a;
3
+ const { data, position } = args;
4
+ const [pointerX, pointerY] = position;
5
+ const closestPoint = (_a = data[0]) === null || _a === void 0 ? void 0 : _a.items.find((cell) => pointerX >= cell.x &&
6
+ pointerX <= cell.x + cell.width &&
7
+ pointerY >= cell.y &&
8
+ pointerY <= cell.y + cell.height);
9
+ if (!closestPoint) {
10
+ return { chunks: [] };
11
+ }
12
+ return {
13
+ chunks: [
14
+ {
15
+ data: closestPoint.data,
16
+ series: data[0].series,
17
+ closest: true,
18
+ },
19
+ ],
20
+ };
21
+ }
@@ -0,0 +1,3 @@
1
+ import type { GetTooltipDataArgs, GetTooltipDataResult } from '../../utils/tooltip-helpers';
2
+ import type { PreparedLineData } from './types';
3
+ export declare function getTooltipData(args: GetTooltipDataArgs<PreparedLineData>): GetTooltipDataResult;
@@ -0,0 +1,18 @@
1
+ export function getTooltipData(args) {
2
+ const { data } = args;
3
+ const xLookupPoints = data.reduce((acc, d) => {
4
+ for (const p of d.points) {
5
+ if (p.y !== null && p.x !== null && !p.hiddenInLine) {
6
+ acc.push({
7
+ data: p.data,
8
+ series: p.series,
9
+ x: p.x,
10
+ y0: p.y,
11
+ y1: p.y,
12
+ });
13
+ }
14
+ }
15
+ return acc;
16
+ }, []);
17
+ return { chunks: [], xLookupPoints };
18
+ }
@@ -0,0 +1,3 @@
1
+ import type { GetTooltipDataArgs, GetTooltipDataResult } from '../../utils/tooltip-helpers';
2
+ import type { PreparedPieData } from './types';
3
+ export declare function getTooltipData(args: GetTooltipDataArgs<PreparedPieData>): GetTooltipDataResult;
@@ -0,0 +1,27 @@
1
+ import { getRadius } from '../../utils/tooltip-helpers';
2
+ export function getTooltipData(args) {
3
+ const { data, position } = args;
4
+ const [pointerX, pointerY] = position;
5
+ const points = data.flatMap((d) => d.segments);
6
+ const closestPoint = points.find((p) => {
7
+ const { center } = p.data.pie;
8
+ const x = pointerX - center[0];
9
+ const y = pointerY - center[1];
10
+ let angle = Math.atan2(y, x) + 0.5 * Math.PI;
11
+ angle = angle < 0 ? Math.PI * 2 + angle : angle;
12
+ const polarRadius = getRadius({ center, pointer: [pointerX, pointerY] });
13
+ return angle >= p.startAngle && angle <= p.endAngle && polarRadius < p.data.radius;
14
+ });
15
+ if (!closestPoint) {
16
+ return { chunks: [] };
17
+ }
18
+ return {
19
+ chunks: [
20
+ {
21
+ data: closestPoint.data.series.data,
22
+ series: closestPoint.data.series,
23
+ closest: true,
24
+ },
25
+ ],
26
+ };
27
+ }
@@ -0,0 +1,3 @@
1
+ import type { GetTooltipDataArgs, GetTooltipDataResult } from '../../utils/tooltip-helpers';
2
+ import type { PreparedRadarData } from './types';
3
+ export declare function getTooltipData(args: GetTooltipDataArgs<PreparedRadarData>): GetTooltipDataResult;
@@ -0,0 +1,35 @@
1
+ import { Delaunay } from 'd3-delaunay';
2
+ import { getRadius, isInsidePath } from '../../utils/tooltip-helpers';
3
+ export function getTooltipData(args) {
4
+ const { data, position, boundsWidth, boundsHeight } = args;
5
+ const [pointerX, pointerY] = position;
6
+ const [radarData] = data;
7
+ if (!radarData) {
8
+ return { chunks: [] };
9
+ }
10
+ const radius = getRadius({ center: radarData.center, pointer: [pointerX, pointerY] });
11
+ if (radius > radarData.radius) {
12
+ return { chunks: [] };
13
+ }
14
+ const radarShapes = radarData.shapes.filter((shape) => isInsidePath({
15
+ path: shape.path,
16
+ point: [pointerX, pointerY],
17
+ width: boundsWidth,
18
+ height: boundsHeight,
19
+ strokeWidth: shape.borderWidth,
20
+ }));
21
+ const points = radarShapes.flatMap((shape) => shape.points);
22
+ const delaunay = Delaunay.from(points, (d) => d.position[0], (d) => d.position[1]);
23
+ const closestPoint = points[delaunay.find(pointerX, pointerY)];
24
+ if (!closestPoint) {
25
+ return { chunks: [] };
26
+ }
27
+ return {
28
+ chunks: radarData.shapes.map((shape) => ({
29
+ data: shape.points[closestPoint.index].data,
30
+ series: shape.series,
31
+ category: shape.series.categories[closestPoint.index],
32
+ closest: shape.series === closestPoint.series,
33
+ })),
34
+ };
35
+ }
@@ -0,0 +1,3 @@
1
+ import type { GetTooltipDataArgs, GetTooltipDataResult } from '../../utils/tooltip-helpers';
2
+ import type { PreparedSankeyData } from './types';
3
+ export declare function getTooltipData(args: GetTooltipDataArgs<PreparedSankeyData>): GetTooltipDataResult;
@@ -0,0 +1,32 @@
1
+ import { isInsidePath } from '../../utils/tooltip-helpers';
2
+ export function getTooltipData(args) {
3
+ const { data, position, boundsWidth, boundsHeight } = args;
4
+ const [pointerX, pointerY] = position;
5
+ const [sankeyData] = data;
6
+ if (!sankeyData) {
7
+ return { chunks: [] };
8
+ }
9
+ const closestLink = sankeyData.links.find((d) => {
10
+ var _a;
11
+ return isInsidePath({
12
+ path: (_a = d.path) !== null && _a !== void 0 ? _a : '',
13
+ strokeWidth: d.strokeWidth,
14
+ point: [pointerX, pointerY],
15
+ width: boundsWidth,
16
+ height: boundsHeight,
17
+ });
18
+ });
19
+ if (!closestLink) {
20
+ return { chunks: [] };
21
+ }
22
+ return {
23
+ chunks: [
24
+ {
25
+ data: closestLink.source,
26
+ target: closestLink.target,
27
+ series: sankeyData.series,
28
+ closest: true,
29
+ },
30
+ ],
31
+ };
32
+ }
@@ -0,0 +1,3 @@
1
+ import type { GetTooltipDataArgs, GetTooltipDataResult } from '../../utils/tooltip-helpers';
2
+ import type { PreparedScatterData } from './types';
3
+ export declare function getTooltipData(args: GetTooltipDataArgs<PreparedScatterData>): GetTooltipDataResult;
@@ -0,0 +1,19 @@
1
+ import { Delaunay } from 'd3-delaunay';
2
+ export function getTooltipData(args) {
3
+ const { data, position } = args;
4
+ const [pointerX, pointerY] = position;
5
+ const delaunay = Delaunay.from(data, (d) => d.point.x, (d) => d.point.y);
6
+ const closestPoint = data[delaunay.find(pointerX, pointerY)];
7
+ if (!closestPoint) {
8
+ return { chunks: [] };
9
+ }
10
+ return {
11
+ chunks: [
12
+ {
13
+ data: closestPoint.point.data,
14
+ series: closestPoint.point.series,
15
+ closest: true,
16
+ },
17
+ ],
18
+ };
19
+ }