@gravity-ui/charts 1.46.1 → 1.48.0

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 (195) hide show
  1. package/dist/cjs/components/AxisX/prepare-axis-data.js +9 -6
  2. package/dist/cjs/components/AxisY/prepare-axis-data.js +11 -4
  3. package/dist/cjs/components/ChartInner/index.js +1 -0
  4. package/dist/cjs/components/ChartInner/useChartInnerProps.d.ts +1 -0
  5. package/dist/cjs/components/ChartInner/useChartInnerProps.js +12 -5
  6. package/dist/cjs/core/axes/types.d.ts +4 -2
  7. package/dist/cjs/core/axes/x-axis.js +2 -0
  8. package/dist/cjs/core/axes/y-axis.js +2 -0
  9. package/dist/cjs/core/brush/index.d.ts +2 -0
  10. package/dist/cjs/core/brush/index.js +2 -0
  11. package/dist/cjs/{hooks/useBrush → core/brush}/types.d.ts +2 -2
  12. package/dist/{esm/hooks/useBrush → cjs/core/brush}/utils.d.ts +1 -1
  13. package/dist/cjs/core/chart/index.d.ts +1 -0
  14. package/dist/cjs/core/chart/index.js +1 -0
  15. package/dist/cjs/core/chart/types.d.ts +8 -0
  16. package/dist/cjs/core/index.d.ts +3 -0
  17. package/dist/cjs/core/index.js +3 -0
  18. package/dist/cjs/core/layout/chart-dimensions.d.ts +1 -1
  19. package/dist/cjs/core/range-slider/index.d.ts +2 -0
  20. package/dist/cjs/core/range-slider/index.js +2 -0
  21. package/dist/cjs/core/range-slider/types.d.ts +4 -0
  22. package/dist/cjs/{hooks/useRangeSlider → core/range-slider}/utils.d.ts +5 -5
  23. package/dist/cjs/{hooks/useRangeSlider → core/range-slider}/utils.js +1 -1
  24. package/dist/cjs/core/scales/x-scale.d.ts +2 -2
  25. package/dist/cjs/core/scales/y-scale.js +21 -0
  26. package/dist/cjs/core/series/prepare-legend.d.ts +1 -1
  27. package/dist/cjs/core/series/prepare-scatter.js +11 -3
  28. package/dist/cjs/core/series/types.d.ts +8 -0
  29. package/dist/cjs/core/shapes/area/prepare-data.js +8 -50
  30. package/dist/cjs/core/shapes/area/renderer.js +8 -14
  31. package/dist/cjs/core/shapes/area/types.d.ts +6 -5
  32. package/dist/cjs/core/shapes/bar-x/prepare-data.js +49 -35
  33. package/dist/cjs/core/shapes/bar-x/renderer.js +6 -12
  34. package/dist/cjs/core/shapes/bar-y/renderer.js +6 -12
  35. package/dist/cjs/core/shapes/data-labels.d.ts +15 -0
  36. package/dist/cjs/core/shapes/data-labels.js +15 -0
  37. package/dist/cjs/core/shapes/funnel/renderer.js +6 -11
  38. package/dist/cjs/core/shapes/heatmap/prepare-data.js +1 -0
  39. package/dist/cjs/core/shapes/heatmap/renderer.js +6 -11
  40. package/dist/cjs/core/shapes/heatmap/types.d.ts +1 -0
  41. package/dist/cjs/core/shapes/line/prepare-data.js +22 -59
  42. package/dist/cjs/core/shapes/line/renderer.js +7 -13
  43. package/dist/cjs/core/shapes/line/types.d.ts +5 -4
  44. package/dist/cjs/core/shapes/radar/renderer.js +8 -12
  45. package/dist/cjs/core/shapes/sankey/renderer.js +6 -12
  46. package/dist/cjs/core/shapes/scatter/prepare-data.d.ts +5 -2
  47. package/dist/cjs/core/shapes/scatter/prepare-data.js +43 -4
  48. package/dist/cjs/core/shapes/scatter/renderer.d.ts +2 -2
  49. package/dist/cjs/core/shapes/scatter/renderer.js +9 -1
  50. package/dist/cjs/core/shapes/scatter/types.d.ts +6 -1
  51. package/dist/cjs/core/shapes/utils.d.ts +24 -0
  52. package/dist/cjs/core/shapes/utils.js +48 -0
  53. package/dist/cjs/core/shapes/waterfall/renderer.js +6 -12
  54. package/dist/cjs/core/shapes/x-range/renderer.js +7 -13
  55. package/dist/cjs/core/types/chart/axis.d.ts +20 -0
  56. package/dist/cjs/core/types/chart/base.d.ts +17 -3
  57. package/dist/cjs/core/types/chart/scatter.d.ts +2 -0
  58. package/dist/cjs/core/types/chart/tooltip.d.ts +3 -3
  59. package/dist/cjs/core/types/formatter.d.ts +1 -40
  60. package/dist/cjs/core/utils/data-labels.d.ts +46 -0
  61. package/dist/cjs/core/utils/data-labels.js +64 -0
  62. package/dist/cjs/core/utils/format.d.ts +2 -2
  63. package/dist/cjs/core/utils/get-closest-data.js +13 -8
  64. package/dist/cjs/core/utils/index.d.ts +1 -0
  65. package/dist/cjs/core/utils/index.js +1 -0
  66. package/dist/cjs/core/zoom/index.d.ts +2 -0
  67. package/dist/cjs/core/zoom/index.js +2 -0
  68. package/dist/{esm/hooks/useZoom → cjs/core/zoom}/utils.d.ts +3 -3
  69. package/dist/{esm/hooks/useZoom → cjs/core/zoom}/utils.js +1 -1
  70. package/dist/cjs/core/zoom/zoom.d.ts +3 -3
  71. package/dist/cjs/hooks/index.d.ts +2 -2
  72. package/dist/cjs/hooks/index.js +2 -2
  73. package/dist/cjs/hooks/types.d.ts +2 -8
  74. package/dist/cjs/hooks/useBrush/index.d.ts +1 -1
  75. package/dist/cjs/hooks/useBrush/index.js +1 -1
  76. package/dist/cjs/hooks/useRangeSlider/index.js +3 -3
  77. package/dist/cjs/hooks/useRangeSlider/types.d.ts +5 -7
  78. package/dist/cjs/hooks/useShapes/index.d.ts +1 -1
  79. package/dist/cjs/hooks/useShapes/index.js +5 -3
  80. package/dist/cjs/hooks/useShapes/scatter/index.d.ts +2 -2
  81. package/dist/cjs/hooks/useShapes/scatter/index.js +4 -1
  82. package/dist/cjs/hooks/useShapes/styles.css +8 -25
  83. package/dist/cjs/hooks/useShapes/utils.d.ts +1 -1
  84. package/dist/cjs/hooks/useZoom/index.d.ts +1 -1
  85. package/dist/cjs/hooks/useZoom/index.js +1 -1
  86. package/dist/cjs/index.d.ts +1 -0
  87. package/dist/cjs/index.js +1 -0
  88. package/dist/cjs/libs/format-number/index.js +82 -14
  89. package/dist/cjs/libs/format-number/presets.d.ts +40 -0
  90. package/dist/cjs/libs/format-number/presets.js +66 -0
  91. package/dist/cjs/libs/format-number/types.d.ts +82 -3
  92. package/dist/esm/components/AxisX/prepare-axis-data.js +9 -6
  93. package/dist/esm/components/AxisY/prepare-axis-data.js +11 -4
  94. package/dist/esm/components/ChartInner/index.js +1 -0
  95. package/dist/esm/components/ChartInner/useChartInnerProps.d.ts +1 -0
  96. package/dist/esm/components/ChartInner/useChartInnerProps.js +12 -5
  97. package/dist/esm/core/axes/types.d.ts +4 -2
  98. package/dist/esm/core/axes/x-axis.js +2 -0
  99. package/dist/esm/core/axes/y-axis.js +2 -0
  100. package/dist/esm/core/brush/index.d.ts +2 -0
  101. package/dist/esm/core/brush/index.js +2 -0
  102. package/dist/esm/{hooks/useBrush → core/brush}/types.d.ts +2 -2
  103. package/dist/esm/core/brush/types.js +1 -0
  104. package/dist/{cjs/hooks/useBrush → esm/core/brush}/utils.d.ts +1 -1
  105. package/dist/esm/core/chart/index.d.ts +1 -0
  106. package/dist/esm/core/chart/index.js +1 -0
  107. package/dist/esm/core/chart/types.d.ts +8 -0
  108. package/dist/esm/core/chart/types.js +1 -0
  109. package/dist/esm/core/index.d.ts +3 -0
  110. package/dist/esm/core/index.js +3 -0
  111. package/dist/esm/core/layout/chart-dimensions.d.ts +1 -1
  112. package/dist/esm/core/range-slider/index.d.ts +2 -0
  113. package/dist/esm/core/range-slider/index.js +2 -0
  114. package/dist/esm/core/range-slider/types.d.ts +4 -0
  115. package/dist/esm/core/range-slider/types.js +1 -0
  116. package/dist/esm/{hooks/useRangeSlider → core/range-slider}/utils.d.ts +5 -5
  117. package/dist/esm/{hooks/useRangeSlider → core/range-slider}/utils.js +1 -1
  118. package/dist/esm/core/scales/x-scale.d.ts +2 -2
  119. package/dist/esm/core/scales/y-scale.js +21 -0
  120. package/dist/esm/core/series/prepare-legend.d.ts +1 -1
  121. package/dist/esm/core/series/prepare-scatter.js +11 -3
  122. package/dist/esm/core/series/types.d.ts +8 -0
  123. package/dist/esm/core/shapes/area/prepare-data.js +8 -50
  124. package/dist/esm/core/shapes/area/renderer.js +8 -14
  125. package/dist/esm/core/shapes/area/types.d.ts +6 -5
  126. package/dist/esm/core/shapes/bar-x/prepare-data.js +49 -35
  127. package/dist/esm/core/shapes/bar-x/renderer.js +6 -12
  128. package/dist/esm/core/shapes/bar-y/renderer.js +6 -12
  129. package/dist/esm/core/shapes/data-labels.d.ts +15 -0
  130. package/dist/esm/core/shapes/data-labels.js +15 -0
  131. package/dist/esm/core/shapes/funnel/renderer.js +6 -11
  132. package/dist/esm/core/shapes/heatmap/prepare-data.js +1 -0
  133. package/dist/esm/core/shapes/heatmap/renderer.js +6 -11
  134. package/dist/esm/core/shapes/heatmap/types.d.ts +1 -0
  135. package/dist/esm/core/shapes/line/prepare-data.js +22 -59
  136. package/dist/esm/core/shapes/line/renderer.js +7 -13
  137. package/dist/esm/core/shapes/line/types.d.ts +5 -4
  138. package/dist/esm/core/shapes/radar/renderer.js +8 -12
  139. package/dist/esm/core/shapes/sankey/renderer.js +6 -12
  140. package/dist/esm/core/shapes/scatter/prepare-data.d.ts +5 -2
  141. package/dist/esm/core/shapes/scatter/prepare-data.js +43 -4
  142. package/dist/esm/core/shapes/scatter/renderer.d.ts +2 -2
  143. package/dist/esm/core/shapes/scatter/renderer.js +9 -1
  144. package/dist/esm/core/shapes/scatter/types.d.ts +6 -1
  145. package/dist/esm/core/shapes/utils.d.ts +24 -0
  146. package/dist/esm/core/shapes/utils.js +48 -0
  147. package/dist/esm/core/shapes/waterfall/renderer.js +6 -12
  148. package/dist/esm/core/shapes/x-range/renderer.js +7 -13
  149. package/dist/esm/core/types/chart/axis.d.ts +20 -0
  150. package/dist/esm/core/types/chart/base.d.ts +17 -3
  151. package/dist/esm/core/types/chart/scatter.d.ts +2 -0
  152. package/dist/esm/core/types/chart/tooltip.d.ts +3 -3
  153. package/dist/esm/core/types/formatter.d.ts +1 -40
  154. package/dist/esm/core/utils/data-labels.d.ts +46 -0
  155. package/dist/esm/core/utils/data-labels.js +64 -0
  156. package/dist/esm/core/utils/format.d.ts +2 -2
  157. package/dist/esm/core/utils/get-closest-data.js +13 -8
  158. package/dist/esm/core/utils/index.d.ts +1 -0
  159. package/dist/esm/core/utils/index.js +1 -0
  160. package/dist/esm/core/zoom/index.d.ts +2 -0
  161. package/dist/esm/core/zoom/index.js +2 -0
  162. package/dist/esm/core/zoom/types.js +1 -0
  163. package/dist/{cjs/hooks/useZoom → esm/core/zoom}/utils.d.ts +3 -3
  164. package/dist/{cjs/hooks/useZoom → esm/core/zoom}/utils.js +1 -1
  165. package/dist/esm/core/zoom/zoom.d.ts +3 -3
  166. package/dist/esm/hooks/index.d.ts +2 -2
  167. package/dist/esm/hooks/index.js +2 -2
  168. package/dist/esm/hooks/types.d.ts +2 -8
  169. package/dist/esm/hooks/useBrush/index.d.ts +1 -1
  170. package/dist/esm/hooks/useBrush/index.js +1 -1
  171. package/dist/esm/hooks/useRangeSlider/index.js +3 -3
  172. package/dist/esm/hooks/useRangeSlider/types.d.ts +5 -7
  173. package/dist/esm/hooks/useShapes/index.d.ts +1 -1
  174. package/dist/esm/hooks/useShapes/index.js +5 -3
  175. package/dist/esm/hooks/useShapes/scatter/index.d.ts +2 -2
  176. package/dist/esm/hooks/useShapes/scatter/index.js +4 -1
  177. package/dist/esm/hooks/useShapes/styles.css +8 -25
  178. package/dist/esm/hooks/useShapes/utils.d.ts +1 -1
  179. package/dist/esm/hooks/useZoom/index.d.ts +1 -1
  180. package/dist/esm/hooks/useZoom/index.js +1 -1
  181. package/dist/esm/index.d.ts +1 -0
  182. package/dist/esm/index.js +1 -0
  183. package/dist/esm/libs/format-number/index.js +82 -14
  184. package/dist/esm/libs/format-number/presets.d.ts +40 -0
  185. package/dist/esm/libs/format-number/presets.js +66 -0
  186. package/dist/esm/libs/format-number/types.d.ts +82 -3
  187. package/package.json +1 -1
  188. /package/dist/cjs/{hooks/useBrush → core/brush}/types.js +0 -0
  189. /package/dist/cjs/{hooks/useBrush → core/brush}/utils.js +0 -0
  190. /package/dist/cjs/{hooks/useZoom → core/chart}/types.js +0 -0
  191. /package/dist/{esm/hooks/useBrush → cjs/core/range-slider}/types.js +0 -0
  192. /package/dist/cjs/{hooks/useZoom → core/zoom}/types.d.ts +0 -0
  193. /package/dist/{esm/hooks/useZoom → cjs/core/zoom}/types.js +0 -0
  194. /package/dist/esm/{hooks/useBrush → core/brush}/utils.js +0 -0
  195. /package/dist/esm/{hooks/useZoom → core/zoom}/types.d.ts +0 -0
@@ -12,7 +12,6 @@ export type CustomFormat = {
12
12
  type: 'custom';
13
13
  formatter: (args: {
14
14
  value: unknown;
15
- formattedValue?: string;
16
15
  }) => string;
17
16
  };
18
17
  /**
@@ -20,7 +19,10 @@ export type CustomFormat = {
20
19
  *
21
20
  * - `{ type: 'number' }` — numeric formatting with optional precision, units, percent display, etc.
22
21
  * See [FormatNumberOptions](https://gravity-ui.github.io/charts/pages/api/Utilities/interfaces/FormatNumberOptions.html) for all available options.
23
- * - `{ type: 'date' }` — date/time formatting
22
+ * - `{ type: 'date' }` — date/time formatting.
23
+ * - `{ type: 'custom' }` — user-defined formatter function. Receives the raw `value`
24
+ * and returns the display string. Use it when the built-in number/date formatters
25
+ * are not enough (e.g. bytes → KB/MB/GB, currency with locale, etc.).
24
26
  * @example
25
27
  * // Two decimal places, shown as percent
26
28
  * { type: 'number', precision: 2, format: 'percent' }
@@ -30,8 +32,20 @@ export type CustomFormat = {
30
32
  * @example
31
33
  * // Date value (Unix ms) formatted as "17 October 2025"
32
34
  * { type: 'date', format: 'DD MMMM YYYY' }
35
+ * @example
36
+ * // Bytes → human-readable size
37
+ * {
38
+ * type: 'custom',
39
+ * formatter: ({value}) => {
40
+ * const bytes = Number(value);
41
+ * if (!Number.isFinite(bytes)) return String(value);
42
+ * const units = ['B', 'KB', 'MB', 'GB', 'TB'];
43
+ * const i = Math.min(units.length - 1, Math.floor(Math.log(Math.abs(bytes) || 1) / Math.log(1024)));
44
+ * return `${(bytes / 1024 ** i).toFixed(1)} ${units[i]}`;
45
+ * },
46
+ * }
33
47
  */
34
- export type ValueFormat = NumberFormat | DateFormat;
48
+ export type ValueFormat = NumberFormat | DateFormat | CustomFormat;
35
49
  export interface BaseDataLabels {
36
50
  /**
37
51
  * Enable or disable the data labels
@@ -23,6 +23,8 @@ export interface ScatterSeriesData<T = MeaningfulAny> extends BaseSeriesData<T>
23
23
  * @deprecated use `x` or `y` instead
24
24
  */
25
25
  category?: string;
26
+ /** Data label value of the point. If not specified, the y value is used. */
27
+ label?: string | number;
26
28
  /** Individual radius for the point. */
27
29
  radius?: number;
28
30
  /** Individual opacity for the point. */
@@ -5,7 +5,7 @@ import type { AreaSeries, AreaSeriesData } from './area';
5
5
  import type { AxisPlotBand, AxisPlotLine, AxisPlotShape, ChartXAxis, ChartYAxis } from './axis';
6
6
  import type { BarXSeries, BarXSeriesData } from './bar-x';
7
7
  import type { BarYSeries, BarYSeriesData } from './bar-y';
8
- import type { CustomFormat, ValueFormat } from './base';
8
+ import type { ValueFormat } from './base';
9
9
  import type { FunnelSeries, FunnelSeriesData } from './funnel';
10
10
  import type { HeatmapSeries, HeatmapSeriesData } from './heatmap';
11
11
  import type { LineSeries, LineSeriesData } from './line';
@@ -107,7 +107,7 @@ export interface ChartTooltipRendererArgs<T = MeaningfulAny> {
107
107
  xAxis?: ChartXAxis | null;
108
108
  yAxis?: ChartYAxis;
109
109
  /** Formatting settings for tooltip header row (includes computed default). */
110
- headerFormat?: ValueFormat | CustomFormat;
110
+ headerFormat?: ValueFormat;
111
111
  }
112
112
  export interface ChartTooltipTotalsAggregationArgs<T = MeaningfulAny> extends ChartTooltipRendererArgs<T> {
113
113
  }
@@ -167,7 +167,7 @@ export interface ChartTooltip<T = MeaningfulAny> {
167
167
  /** Formatting settings for tooltip value. */
168
168
  valueFormat?: ValueFormat;
169
169
  /** Formatting settings for tooltip header row. */
170
- headerFormat?: ValueFormat | CustomFormat;
170
+ headerFormat?: ValueFormat;
171
171
  /** Settings for totals block in tooltip */
172
172
  totals?: {
173
173
  /**
@@ -1,40 +1 @@
1
- export interface FormatOptions {
2
- /**
3
- * Number of decimal places to display.
4
- * Use `'auto'` to determine precision automatically based on the value magnitude.
5
- */
6
- precision?: number | 'auto';
7
- /** When `true`, inserts a thousands separator (e.g. `1 500 000`). */
8
- showRankDelimiter?: boolean;
9
- /**
10
- * BCP 47 language tag used for locale-aware formatting (e.g. `'en'`, `'ru'`).
11
- * Defaults to the application locale when omitted.
12
- */
13
- lang?: string;
14
- /** Internal rendering hint for axis label layout. Not intended for public use. */
15
- labelMode?: string;
16
- }
17
- export interface FormatNumberOptions extends FormatOptions {
18
- /**
19
- * Display mode for the numeric value.
20
- * - `'number'` — plain number (default).
21
- * - `'percent'` — value is multiplied by 100 and rendered with a `%` suffix.
22
- */
23
- format?: 'number' | 'percent';
24
- /** Factor applied to the value before formatting. For example, `multiplier: 1000` converts seconds to milliseconds. */
25
- multiplier?: number;
26
- /** String prepended to the formatted value (e.g. `'$'`). */
27
- prefix?: string;
28
- /** String appended to the formatted value (e.g. `' USD'`). */
29
- postfix?: string;
30
- /**
31
- * Compact unit suffix applied to large numbers.
32
- * - `'auto'` — picks the most appropriate unit automatically (`k`, `m`, `b`, `t`).
33
- * - `'k'` — thousands (÷ 1 000).
34
- * - `'m'` — millions (÷ 1 000 000).
35
- * - `'b'` — billions (÷ 1 000 000 000).
36
- * - `'t'` — trillions (÷ 1 000 000 000 000).
37
- * - `null` — no unit suffix.
38
- */
39
- unit?: 'auto' | 'k' | 'm' | 'b' | 't' | null;
40
- }
1
+ export type { FormatNumberOptions, FormatOptions, FormatUnitScale, FormatUnitScaleEntry, } from '../../libs/format-number/types';
@@ -0,0 +1,46 @@
1
+ import type { HtmlItem, LabelData } from '../../types';
2
+ import type { BaseTextStyle, ValueFormat } from '../types/chart/base';
3
+ type PointLabelSeries = {
4
+ id: string;
5
+ dataLabels: {
6
+ style: BaseTextStyle;
7
+ html: boolean;
8
+ padding: number;
9
+ format?: ValueFormat;
10
+ };
11
+ };
12
+ type LabelPoint = {
13
+ x: number | null;
14
+ y: number | null;
15
+ data: {
16
+ label?: string | number | null;
17
+ y?: string | number | null;
18
+ };
19
+ };
20
+ /**
21
+ * Shared "above-point" dataLabels algorithm used by line, area, and scatter series.
22
+ *
23
+ * For each visible point it:
24
+ * 1. Formats the value via getFormattedValue
25
+ * 2. Measures the label size (HTML → getLabelsSize, SVG → getTextSizeFn)
26
+ * 3. Positions the label centered above the point, clamped to chart bounds
27
+ *
28
+ * `anchorYOffset` shifts the vertical anchor from the point center upward by the given
29
+ * number of pixels (e.g. marker radius for scatter), so padding is measured from the
30
+ * marker edge rather than its center. The top-boundary clamp also respects this offset
31
+ * so the label never drops below the anchor.
32
+ *
33
+ * Overlap filtering is intentionally left to the caller.
34
+ */
35
+ export declare function preparePointDataLabels<S extends PointLabelSeries, P extends LabelPoint>({ series, points, xMax, yAxisTop, isOutsideBounds, anchorYOffset, }: {
36
+ series: S;
37
+ points: P[];
38
+ xMax: number;
39
+ yAxisTop: number;
40
+ isOutsideBounds: (x: number, y: number) => boolean;
41
+ anchorYOffset?: number;
42
+ }): Promise<{
43
+ svgLabels: LabelData[];
44
+ htmlLabels: HtmlItem[];
45
+ }>;
46
+ export {};
@@ -0,0 +1,64 @@
1
+ import { getFormattedValue } from './format';
2
+ import { getLabelsSize, getTextSizeFn } from './text';
3
+ /**
4
+ * Shared "above-point" dataLabels algorithm used by line, area, and scatter series.
5
+ *
6
+ * For each visible point it:
7
+ * 1. Formats the value via getFormattedValue
8
+ * 2. Measures the label size (HTML → getLabelsSize, SVG → getTextSizeFn)
9
+ * 3. Positions the label centered above the point, clamped to chart bounds
10
+ *
11
+ * `anchorYOffset` shifts the vertical anchor from the point center upward by the given
12
+ * number of pixels (e.g. marker radius for scatter), so padding is measured from the
13
+ * marker edge rather than its center. The top-boundary clamp also respects this offset
14
+ * so the label never drops below the anchor.
15
+ *
16
+ * Overlap filtering is intentionally left to the caller.
17
+ */
18
+ export async function preparePointDataLabels({ series, points, xMax, yAxisTop, isOutsideBounds, anchorYOffset = 0, }) {
19
+ var _a;
20
+ const svgLabels = [];
21
+ const htmlLabels = [];
22
+ const getTextSize = getTextSizeFn({ style: series.dataLabels.style });
23
+ for (let i = 0; i < points.length; i++) {
24
+ const point = points[i];
25
+ if (point.y === null || point.x === null || isOutsideBounds(point.x, point.y)) {
26
+ continue;
27
+ }
28
+ const text = getFormattedValue(Object.assign({ value: (_a = point.data.label) !== null && _a !== void 0 ? _a : point.data.y }, series.dataLabels));
29
+ const anchorY = point.y - anchorYOffset;
30
+ if (series.dataLabels.html) {
31
+ const size = await getLabelsSize({
32
+ labels: [text],
33
+ style: series.dataLabels.style,
34
+ html: true,
35
+ });
36
+ const width = size.maxWidth;
37
+ const height = size.maxHeight;
38
+ htmlLabels.push({
39
+ x: Math.min(xMax - width, Math.max(0, point.x - width / 2)),
40
+ y: Math.max(yAxisTop, anchorY - series.dataLabels.padding - height),
41
+ content: text,
42
+ size: { width, height },
43
+ style: series.dataLabels.style,
44
+ });
45
+ }
46
+ else {
47
+ const labelSize = await getTextSize(text);
48
+ svgLabels.push({
49
+ text,
50
+ x: Math.min(xMax - labelSize.width, Math.max(0, point.x - labelSize.width / 2)),
51
+ y: Math.max(yAxisTop, anchorY -
52
+ series.dataLabels.padding -
53
+ labelSize.height +
54
+ labelSize.hangingOffset),
55
+ style: series.dataLabels.style,
56
+ size: labelSize,
57
+ textAnchor: 'start',
58
+ series,
59
+ active: true,
60
+ });
61
+ }
62
+ }
63
+ return { svgLabels, htmlLabels };
64
+ }
@@ -1,9 +1,9 @@
1
1
  import type { AxisDomain } from 'd3-axis';
2
- import type { CustomFormat, ValueFormat } from '../../types';
2
+ import type { ValueFormat } from '../../types';
3
3
  import type { PreparedAxis } from '../axes/types';
4
4
  export declare function getFormattedValue(args: {
5
5
  value: string | number | undefined | null;
6
- format?: ValueFormat | CustomFormat;
6
+ format?: ValueFormat;
7
7
  }): string;
8
8
  export declare function formatAxisTickLabel(args: {
9
9
  axis: PreparedAxis;
@@ -68,7 +68,7 @@ export function getClosestPoints(args) {
68
68
  case 'line': {
69
69
  const linePoints = list.reduce((acc, d) => {
70
70
  acc.push(...d.points.reduce((accPoints, p) => {
71
- if (p.y !== null && p.x !== null) {
71
+ if (p.y !== null && p.x !== null && !p.hiddenInLine) {
72
72
  accPoints.push({
73
73
  data: p.data,
74
74
  series: p.series,
@@ -86,13 +86,18 @@ export function getClosestPoints(args) {
86
86
  }
87
87
  case 'area': {
88
88
  const areaPoints = list.reduce((acc, d) => {
89
- Array.prototype.push.apply(acc, d.points.map((p) => ({
90
- data: p.data,
91
- series: p.series,
92
- x: p.x,
93
- y0: p.y0,
94
- y1: p.y,
95
- })));
89
+ for (const p of d.points) {
90
+ if (p.y === null || p.hiddenInLine) {
91
+ continue;
92
+ }
93
+ acc.push({
94
+ data: p.data,
95
+ series: p.series,
96
+ x: p.x,
97
+ y0: p.y0,
98
+ y1: p.y,
99
+ });
100
+ }
96
101
  return acc;
97
102
  }, []);
98
103
  closestPointsByXValue.push(...areaPoints);
@@ -15,3 +15,4 @@ export * from '../layout/chart-dimensions';
15
15
  export * from './common';
16
16
  export * from './misc';
17
17
  export * from './dispatcher';
18
+ export * from './data-labels';
@@ -15,3 +15,4 @@ export * from '../layout/chart-dimensions';
15
15
  export * from './common';
16
16
  export * from './misc';
17
17
  export * from './dispatcher';
18
+ export * from './data-labels';
@@ -1 +1,3 @@
1
+ export * from './types';
2
+ export * from './utils';
1
3
  export * from './zoom';
@@ -1 +1,3 @@
1
+ export * from './types';
2
+ export * from './utils';
1
3
  export * from './zoom';
@@ -0,0 +1 @@
1
+ export {};
@@ -1,7 +1,7 @@
1
1
  import type { BrushSelection } from 'd3-brush';
2
- import type { ZoomType } from '../../core/constants';
3
- import type { ChartScale } from '../../core/scales/types';
4
- import type { PreparedXAxis, PreparedYAxis } from '../useAxis/types';
2
+ import type { PreparedXAxis, PreparedYAxis } from '../axes/types';
3
+ import type { ZoomType } from '../constants';
4
+ import type { ChartScale } from '../scales/types';
5
5
  import type { ZoomState } from './types';
6
6
  export declare function selectionToZoomBounds(args: {
7
7
  selection: BrushSelection;
@@ -1,4 +1,4 @@
1
- import { ZOOM_TYPE } from '../../core/constants';
1
+ import { ZOOM_TYPE } from '../constants';
2
2
  export function selectionToZoomBounds(args) {
3
3
  const { selection, xAxis, xScale, yAxes, yScales, zoomType } = args;
4
4
  const zoomState = {};
@@ -1,8 +1,8 @@
1
- import type { RangeSliderState } from '../../hooks';
2
- import type { ZoomState } from '../../hooks/useZoom/types';
3
- import type { ChartXAxis, ChartYAxis } from '../../types';
4
1
  import type { PreparedXAxis, PreparedYAxis } from '../axes/types';
2
+ import type { RangeSliderState } from '../range-slider/types';
5
3
  import type { PreparedSeries } from '../series';
4
+ import type { ChartXAxis, ChartYAxis } from '../types';
5
+ import type { ZoomState } from './types';
6
6
  export declare function getZoomedSeriesData(args: {
7
7
  seriesData: PreparedSeries[];
8
8
  zoomState: Partial<ZoomState>;
@@ -3,7 +3,7 @@ export * from '../core/axes/types';
3
3
  export * from './useAxisScales';
4
4
  export * from '../core/scales/types';
5
5
  export * from './useBrush';
6
- export * from './useBrush/types';
6
+ export * from '../core/brush/types';
7
7
  export * from './useCrosshair';
8
8
  export * from './usePrevious';
9
9
  export * from './useRangeSlider';
@@ -15,5 +15,5 @@ export * from '../core/layout/split';
15
15
  export * from '../core/layout/split-types';
16
16
  export * from './useTooltip';
17
17
  export * from './useZoom';
18
- export * from './useZoom/types';
18
+ export * from '../core/zoom/types';
19
19
  export * from './types';
@@ -3,7 +3,7 @@ export * from '../core/axes/types';
3
3
  export * from './useAxisScales';
4
4
  export * from '../core/scales/types';
5
5
  export * from './useBrush';
6
- export * from './useBrush/types';
6
+ export * from '../core/brush/types';
7
7
  export * from './useCrosshair';
8
8
  export * from './usePrevious';
9
9
  export * from './useRangeSlider';
@@ -15,5 +15,5 @@ export * from '../core/layout/split';
15
15
  export * from '../core/layout/split-types';
16
16
  export * from './useTooltip';
17
17
  export * from './useZoom';
18
- export * from './useZoom/types';
18
+ export * from '../core/zoom/types';
19
19
  export * from './types';
@@ -1,13 +1,7 @@
1
1
  import type { TextRowData } from '../components/types';
2
- import type { BaseTextStyle, ChartBrush, ChartData, ChartMargin, ChartTitle, ChartZoom, DeepRequired } from '../types';
2
+ import type { BaseTextStyle, ChartData, ChartTitle } from '../types';
3
3
  import type { HtmlItem } from '../types/chart-ui';
4
- export type PreparedZoom = DeepRequired<Omit<ChartZoom, 'enabled' | 'brush'>> & DeepRequired<{
5
- brush: ChartBrush;
6
- }>;
7
- export type PreparedChart = {
8
- margin: ChartMargin;
9
- zoom: PreparedZoom | null;
10
- };
4
+ export type { PreparedChart, PreparedZoom } from '../core/chart/types';
11
5
  export type PreparedTitle = Omit<ChartTitle, 'margin' | 'style'> & {
12
6
  height: number;
13
7
  margin: number;
@@ -1,3 +1,3 @@
1
- import type { UseBrushProps } from './types';
1
+ import type { UseBrushProps } from '../../core/brush/types';
2
2
  import './styles.css';
3
3
  export declare function useBrush(props: UseBrushProps): void;
@@ -1,8 +1,8 @@
1
1
  import React from 'react';
2
2
  import { brush, brushX, brushY } from 'd3-brush';
3
3
  import { pointer, select } from 'd3-selection';
4
+ import { getDefaultSelection, getNormalizedSelection, setBrushBorder, setBrushHandles, } from '../../core/brush/utils';
4
5
  import { block } from '../../utils';
5
- import { getDefaultSelection, getNormalizedSelection, setBrushBorder, setBrushHandles, } from './utils';
6
6
  import './styles.css';
7
7
  const b = block('brush');
8
8
  export function useBrush(props) {
@@ -1,14 +1,14 @@
1
1
  import React from 'react';
2
2
  import { pointer } from 'd3-selection';
3
3
  import { isEqual } from 'lodash';
4
+ import { getNormalizedSelection, isOneDimensionalSelection } from '../../core/brush/utils';
4
5
  import { SERIES_TYPE } from '../../core/constants';
6
+ import { getRangeSliderOffsetTop, getRangeSliderSelection } from '../../core/range-slider/utils';
5
7
  import { isBandScale } from '../../core/utils';
8
+ import { selectionToZoomBounds } from '../../core/zoom/utils';
6
9
  import { useAxis } from '../useAxis';
7
10
  import { useAxisScales } from '../useAxisScales';
8
- import { getNormalizedSelection, isOneDimensionalSelection } from '../useBrush/utils';
9
11
  import { useShapes } from '../useShapes';
10
- import { selectionToZoomBounds } from '../useZoom/utils';
11
- import { getRangeSliderOffsetTop, getRangeSliderSelection } from './utils';
12
12
  export const EMPTY_PREPARED_SPLIT = {
13
13
  plots: [],
14
14
  gap: 0,
@@ -1,13 +1,11 @@
1
+ import type { PreparedRangeSlider, PreparedXAxis, PreparedYAxis } from '../../core/axes/types';
2
+ import type { BrushSelection, UseBrushProps } from '../../core/brush/types';
3
+ import type { PreparedChart } from '../../core/chart/types';
4
+ import type { RangeSliderState } from '../../core/range-slider/types';
1
5
  import type { ChartScale } from '../../core/scales/types';
2
6
  import type { PreparedLegend, PreparedSeries, PreparedSeriesOptions } from '../../core/series/types';
3
7
  import type { ChartXAxis, ChartYAxis, LegendConfig } from '../../types';
4
- import type { PreparedChart } from '../types';
5
- import type { PreparedRangeSlider, PreparedXAxis, PreparedYAxis } from '../useAxis/types';
6
- import type { BrushSelection, UseBrushProps } from '../useBrush/types';
7
- export type RangeSliderState = {
8
- max: number;
9
- min: number;
10
- };
8
+ export type { RangeSliderState };
11
9
  export interface RangeSliderProps {
12
10
  activeLegendItems: string[];
13
11
  boundsOffsetLeft: number;
@@ -16,8 +16,8 @@ import type { PreparedSankeyData } from '../../core/shapes/sankey/types';
16
16
  import type { PreparedScatterData } from '../../core/shapes/scatter/types';
17
17
  import type { PreparedWaterfallData } from '../../core/shapes/waterfall/types';
18
18
  import type { PreparedXRangeData } from '../../core/shapes/x-range/types';
19
+ import type { ZoomState } from '../../core/zoom/types';
19
20
  import type { PreparedXAxis, PreparedYAxis } from '../useAxis/types';
20
- import type { ZoomState } from '../useZoom/types';
21
21
  import './styles.css';
22
22
  export type ShapeData = PreparedBarXData | PreparedBarYData | PreparedScatterData | PreparedLineData | PreparedPieData | PreparedAreaData | PreparedWaterfallData | PreparedSankeyData | PreparedRadarData | PreparedHeatmapData | PreparedFunnelData | PreparedXRangeData;
23
23
  export type ClipPathBySeriesType = Partial<Record<SeriesType, boolean>>;
@@ -146,18 +146,20 @@ export async function getShapes(args) {
146
146
  }
147
147
  case SERIES_TYPE.Scatter: {
148
148
  if (xAxis && xScale && (yScale === null || yScale === void 0 ? void 0 : yScale.length)) {
149
- const preparedData = prepareScatterData({
149
+ const scatterShapeData = await prepareScatterData({
150
150
  series: chartSeries,
151
151
  xAxis,
152
152
  xScale,
153
153
  yAxis,
154
154
  yScale,
155
+ split,
155
156
  isOutsideBounds,
157
+ isRangeSlider,
156
158
  });
157
159
  shapes[index] = (React.createElement(ScatterSeriesShape, { key: SERIES_TYPE.Scatter, clipPathId: shouldUseClipPathId(SERIES_TYPE.Scatter, clipPathBySeriesType)
158
160
  ? clipPathId
159
- : undefined, dispatcher: dispatcher, preparedData: preparedData, seriesOptions: seriesOptions, htmlLayout: htmlLayout }));
160
- shapesData.splice(index, 0, ...preparedData);
161
+ : undefined, dispatcher: dispatcher, preparedData: scatterShapeData, seriesOptions: seriesOptions, htmlLayout: htmlLayout }));
162
+ shapesData.splice(index, 0, ...scatterShapeData.markers);
161
163
  }
162
164
  break;
163
165
  }
@@ -1,11 +1,11 @@
1
1
  import React from 'react';
2
2
  import type { Dispatch } from 'd3-dispatch';
3
3
  import type { PreparedSeriesOptions } from '../../../core/series/types';
4
- import type { PreparedScatterData } from '../../../core/shapes/scatter/types';
4
+ import type { PreparedScatterShapeData } from '../../../core/shapes/scatter/types';
5
5
  export { prepareScatterData } from '../../../core/shapes/scatter/prepare-data';
6
6
  type ScatterSeriesShapeProps = {
7
7
  htmlLayout: HTMLElement | null;
8
- preparedData: PreparedScatterData[];
8
+ preparedData: PreparedScatterShapeData;
9
9
  seriesOptions: PreparedSeriesOptions;
10
10
  clipPathId?: string;
11
11
  dispatcher?: Dispatch<object>;
@@ -13,7 +13,10 @@ export function ScatterSeriesShape(props) {
13
13
  }
14
14
  return renderScatter({ plot: ref.current }, preparedData, seriesOptions, dispatcher);
15
15
  }, [dispatcher, preparedData, seriesOptions]);
16
+ const htmlLayerData = React.useMemo(() => {
17
+ return { htmlElements: preparedData.htmlLabels };
18
+ }, [preparedData]);
16
19
  return (React.createElement(React.Fragment, null,
17
20
  React.createElement("g", { ref: ref, className: b(), clipPath: clipPathId ? `url(#${clipPathId})` : undefined }),
18
- React.createElement(HtmlLayer, { preparedData: preparedData, htmlLayout: htmlLayout })));
21
+ React.createElement(HtmlLayer, { preparedData: htmlLayerData, htmlLayout: htmlLayout })));
19
22
  }
@@ -1,8 +1,15 @@
1
1
  .gcharts-line__label,
2
2
  .gcharts-area__label,
3
3
  .gcharts-radar__label,
4
+ .gcharts-bar-x__label,
5
+ .gcharts-bar-y__label,
4
6
  .gcharts-heatmap__label,
5
- .gcharts-funnel__label {
7
+ .gcharts-funnel__label,
8
+ .gcharts-treemap__label,
9
+ .gcharts-pie__label,
10
+ .gcharts-scatter__label {
11
+ user-select: none;
12
+ pointer-events: none;
6
13
  dominant-baseline: hanging;
7
14
  }
8
15
 
@@ -13,30 +20,6 @@
13
20
  .gcharts-pie__segment {
14
21
  stroke: var(--g-color-base-background);
15
22
  }
16
- .gcharts-pie__label {
17
- font-size: 11px;
18
- font-weight: bold;
19
- fill: var(--g-color-text-complementary);
20
- dominant-baseline: hanging;
21
- }
22
-
23
- .gcharts-bar-x__label {
24
- user-select: none;
25
- fill: var(--g-color-text-complementary);
26
- }
27
-
28
- .gcharts-bar-y__label {
29
- user-select: none;
30
- fill: var(--g-color-text-complementary);
31
- dominant-baseline: hanging;
32
- }
33
-
34
- .gcharts-treemap__label {
35
- user-select: none;
36
- pointer-events: none;
37
- fill: var(--g-color-text-complementary);
38
- dominant-baseline: hanging;
39
- }
40
23
 
41
24
  .gcharts-waterfall__connector {
42
25
  stroke: var(--g-color-line-generic-active);
@@ -1,5 +1,5 @@
1
+ import type { ZoomState } from '../../core/zoom/types';
1
2
  import type { PreparedYAxis } from '../useAxis/types';
2
- import type { ZoomState } from '../useZoom/types';
3
3
  export * from '../../core/shapes/utils';
4
4
  export declare function getSeriesClipPathId(args: {
5
5
  clipPathId: string;
@@ -1,8 +1,8 @@
1
1
  import type { PreparedSplit } from '../../core/layout/split-types';
2
2
  import type { ChartScale } from '../../core/scales/types';
3
+ import type { ZoomState } from '../../core/zoom/types';
3
4
  import type { PreparedZoom } from '../types';
4
5
  import type { PreparedXAxis, PreparedYAxis } from '../useAxis/types';
5
- import type { ZoomState } from './types';
6
6
  interface UseZoomProps {
7
7
  node: SVGGElement | null;
8
8
  onUpdate: (zoomState: Partial<ZoomState>) => void;
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import { select } from 'd3-selection';
3
+ import { selectionToZoomBounds } from '../../core/zoom/utils';
3
4
  import { useBrush } from '../useBrush';
4
- import { selectionToZoomBounds } from './utils';
5
5
  export function useZoom(props) {
6
6
  const { node, onUpdate, plotContainerHeight, plotContainerWidth, preparedSplit, preparedZoom, rangeSliderDomain, xAxis, xScale, yAxis, yScale, } = props;
7
7
  const isBrushDisabled = Boolean(!xAxis || !yAxis || !xScale || !yScale);
@@ -1,5 +1,6 @@
1
1
  export { CustomShapeRenderer } from './utils';
2
2
  export { getFormattedValue } from './core/utils';
3
3
  export { getDefaultTooltipHeaderFormat } from './core/utils/tooltip';
4
+ export { FORMAT_UNITS_BITS, FORMAT_UNITS_BYTES, FORMAT_UNITS_NUMBERS, } from './libs/format-number/presets';
4
5
  export * from './components';
5
6
  export * from './types';
package/dist/esm/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export { CustomShapeRenderer } from './utils';
2
2
  export { getFormattedValue } from './core/utils';
3
3
  export { getDefaultTooltipHeaderFormat } from './core/utils/tooltip';
4
+ export { FORMAT_UNITS_BITS, FORMAT_UNITS_BYTES, FORMAT_UNITS_NUMBERS, } from './libs/format-number/presets';
4
5
  export * from './components';
5
6
  export * from './types';