@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
@@ -1,6 +1,6 @@
1
1
  import { getUniqId } from '@gravity-ui/uikit';
2
2
  import { select } from 'd3-selection';
3
- import { calculateCos, calculateSin, formatAxisTickLabel, getBandsPosition, getLabelsSize, getMinSpaceBetween, getTextSizeFn, getTextWithElipsis, } from '../../core/utils';
3
+ import { calculateCos, calculateNumericProperty, calculateSin, formatAxisTickLabel, getBandsPosition, getLabelsSize, getMinSpaceBetween, getTextSizeFn, getTextWithElipsis, } from '../../core/utils';
4
4
  import { getXAxisTickValues } from '../../core/utils/axis/x-axis';
5
5
  import { getMultilineTitleContentRows } from '../utils/axis-title';
6
6
  async function getSvgAxisLabel({ getTextSize, text, axis, top, left, labelMaxWidth, axisWidth, boundsOffsetLeft, boundsOffsetRight, }) {
@@ -72,7 +72,7 @@ async function getSvgAxisLabel({ getTextSize, text, axis, top, left, labelMaxWid
72
72
  return svgLabel;
73
73
  }
74
74
  export async function prepareXAxisData({ axis, boundsOffsetLeft, boundsOffsetRight, boundsWidth, height, scale, series, split, yAxis, }) {
75
- var _a, _b, _c, _d, _e, _f, _g, _h;
75
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
76
76
  const xAxisItems = [];
77
77
  const splitPlots = (_a = split === null || split === void 0 ? void 0 : split.plots) !== null && _a !== void 0 ? _a : [];
78
78
  for (let plotIndex = 0; plotIndex < splitPlots.length; plotIndex++) {
@@ -267,6 +267,9 @@ export async function prepareXAxisData({ axis, boundsOffsetLeft, boundsOffsetRig
267
267
  if (plotBandWidth < 0) {
268
268
  continue;
269
269
  }
270
+ const perpExtent = (_g = calculateNumericProperty({ value: plotBand.size, base: axisHeight })) !== null && _g !== void 0 ? _g : axisHeight;
271
+ // X axis is positioned at the bottom of the plot area, so 'start' = bottom edge.
272
+ const bandY = plotBand.align === 'end' ? axisTop : axisTop + axisHeight - perpExtent;
270
273
  const getPlotLabelSize = getTextSizeFn({ style: plotBand.label.style });
271
274
  const labelSize = plotBand.label.text
272
275
  ? await getPlotLabelSize(plotBand.label.text)
@@ -274,17 +277,17 @@ export async function prepareXAxisData({ axis, boundsOffsetLeft, boundsOffsetRig
274
277
  plotBands.push({
275
278
  layerPlacement: plotBand.layerPlacement,
276
279
  x: Math.max(0, startPos),
277
- y: axisTop,
280
+ y: bandY,
278
281
  width: plotBandWidth,
279
- height: axisHeight,
282
+ height: perpExtent,
280
283
  color: plotBand.color,
281
284
  opacity: plotBand.opacity,
282
285
  label: plotBand.label.text
283
286
  ? {
284
287
  text: plotBand.label.text,
285
288
  style: plotBand.label.style,
286
- x: plotBand.label.padding + ((_g = labelSize === null || labelSize === void 0 ? void 0 : labelSize.hangingOffset) !== null && _g !== void 0 ? _g : 0),
287
- y: plotBand.label.padding + ((_h = labelSize === null || labelSize === void 0 ? void 0 : labelSize.width) !== null && _h !== void 0 ? _h : 0),
289
+ x: plotBand.label.padding + ((_h = labelSize === null || labelSize === void 0 ? void 0 : labelSize.hangingOffset) !== null && _h !== void 0 ? _h : 0),
290
+ y: plotBand.label.padding + ((_j = labelSize === null || labelSize === void 0 ? void 0 : labelSize.width) !== null && _j !== void 0 ? _j : 0),
288
291
  rotate: -90,
289
292
  qa: plotBand.label.qa,
290
293
  }
@@ -1,6 +1,6 @@
1
1
  import { getUniqId } from '@gravity-ui/uikit';
2
2
  import { select } from 'd3-selection';
3
- import { calculateCos, calculateSin, formatAxisTickLabel, getBandsPosition, getLabelsSize, getMinSpaceBetween, getTextSizeFn, getTextWithElipsis, wrapText, } from '../../core/utils';
3
+ import { calculateCos, calculateNumericProperty, calculateSin, formatAxisTickLabel, getBandsPosition, getLabelsSize, getMinSpaceBetween, getTextSizeFn, getTextWithElipsis, wrapText, } from '../../core/utils';
4
4
  import { prepareHtmlYAxisTitle, prepareSvgYAxisTitle } from './prepare-axis-title';
5
5
  import { getTickValues } from './utils';
6
6
  async function getSvgAxisLabel({ getTextSize, text, axis, top, left, labelMaxHeight, topOffset, }) {
@@ -113,7 +113,7 @@ async function getSvgAxisLabel({ getTextSize, text, axis, top, left, labelMaxHei
113
113
  return svgLabel;
114
114
  }
115
115
  export async function prepareYAxisData({ axis, split, scale, top: topOffset, width, height, series, }) {
116
- var _a, _b, _c, _d, _e;
116
+ var _a, _b, _c, _d, _e, _f;
117
117
  const axisPlotTopPosition = ((_a = split === null || split === void 0 ? void 0 : split.plots[axis.plotIndex]) === null || _a === void 0 ? void 0 : _a.top) || 0;
118
118
  const axisHeight = ((_b = split === null || split === void 0 ? void 0 : split.plots[axis.plotIndex]) === null || _b === void 0 ? void 0 : _b.height) || height;
119
119
  const domainX = axis.position === 'left' ? 0 : width;
@@ -231,11 +231,18 @@ export async function prepareYAxisData({ axis, split, scale, top: topOffset, wid
231
231
  if (plotBandHeight < 0) {
232
232
  continue;
233
233
  }
234
+ const perpExtent = (_f = calculateNumericProperty({ value: plotBand.size, base: width })) !== null && _f !== void 0 ? _f : width;
235
+ // 'start' = at the main Y axis line. For a left axis that's x=0;
236
+ // for a right axis that's x = width - perpExtent. 'end' is mirrored.
237
+ const isLeftAxis = axis.position === 'left';
238
+ const atMainAxis = isLeftAxis ? 0 : width - perpExtent;
239
+ const atOpposite = isLeftAxis ? width - perpExtent : 0;
240
+ const bandX = plotBand.align === 'end' ? atOpposite : atMainAxis;
234
241
  const plotBandItem = {
235
242
  layerPlacement: plotBand.layerPlacement,
236
- x: 0,
243
+ x: bandX,
237
244
  y: axisPlotTopPosition + top,
238
- width,
245
+ width: perpExtent,
239
246
  height: plotBandHeight,
240
247
  color: plotBand.color,
241
248
  opacity: plotBand.opacity,
@@ -55,6 +55,7 @@ export const ChartInner = (props) => {
55
55
  const { activeLegendItems, allPreparedSeries, boundsHeight, boundsOffsetLeft, boundsOffsetTop, boundsWidth, handleLegendItemClick, legendConfig, legendItems, preparedLegend, preparedSeries, preparedSeriesOptions, preparedSplit, shapes, shapesData, shapesReady, xAxis, xScale, yAxis, yScale, preparedTitle, preparedChart, } = useChartInnerProps(Object.assign(Object.assign({}, props), { clipPathId,
56
56
  dispatcher,
57
57
  htmlLayout, plotNode: plotRef.current, rangeSliderState,
58
+ updateRangeSliderState,
58
59
  updateZoomState,
59
60
  zoomState }));
60
61
  const prevWidth = usePrevious(width);
@@ -9,6 +9,7 @@ type Props = ChartInnerProps & {
9
9
  dispatcher: Dispatch<object>;
10
10
  htmlLayout: HTMLElement | null;
11
11
  plotNode: SVGGElement | null;
12
+ updateRangeSliderState: (nextState?: RangeSliderState) => void;
12
13
  updateZoomState: (nextZoomState: Partial<ZoomState>) => void;
13
14
  zoomState: Partial<ZoomState>;
14
15
  rangeSliderState?: RangeSliderState;
@@ -38,7 +38,7 @@ function getBoundsOffsetLeft(args) {
38
38
  }
39
39
  export function useChartInnerProps(props) {
40
40
  var _a, _b, _c, _d, _e, _f, _g, _h;
41
- const { clipPathId, data, dispatcher, height, htmlLayout, plotNode, rangeSliderState, width, updateZoomState, zoomState, } = props;
41
+ const { clipPathId, data, dispatcher, height, htmlLayout, plotNode, rangeSliderState, width, updateRangeSliderState, updateZoomState, zoomState, } = props;
42
42
  const [selectedLegendItems, setSelectedLegendItems] = React.useState(null);
43
43
  const [chartState, setState] = React.useState(null);
44
44
  const prevStateValue = React.useRef(chartState);
@@ -48,20 +48,26 @@ export function useChartInnerProps(props) {
48
48
  currentRunRef.current++;
49
49
  const currentRun = currentRunRef.current;
50
50
  (async function () {
51
- var _a, _b, _c, _d;
51
+ var _a, _b, _c, _d, _e, _f, _g;
52
52
  const chartDataChanged = !(previousChartData.current && isEqual(previousChartData.current, data));
53
+ const axisTypeChanged = ((_b = (_a = previousChartData.current) === null || _a === void 0 ? void 0 : _a.xAxis) === null || _b === void 0 ? void 0 : _b.type) !== undefined &&
54
+ previousChartData.current.xAxis.type !== ((_c = data.xAxis) === null || _c === void 0 ? void 0 : _c.type);
55
+ if (axisTypeChanged && rangeSliderState !== undefined) {
56
+ updateRangeSliderState(undefined);
57
+ return;
58
+ }
53
59
  const preparedTitle = await getPreparedTitle({
54
60
  title: data.title,
55
61
  chartWidth: width,
56
62
  chartHeight: height,
57
- chartMargin: (_a = data.chart) === null || _a === void 0 ? void 0 : _a.margin,
63
+ chartMargin: (_d = data.chart) === null || _d === void 0 ? void 0 : _d.margin,
58
64
  });
59
65
  const preparedChart = getPreparedChart({
60
66
  chart: data.chart,
61
67
  seriesData: data.series.data,
62
68
  preparedTitle,
63
69
  });
64
- const colors = (_b = data.colors) !== null && _b !== void 0 ? _b : DEFAULT_PALETTE;
70
+ const colors = (_e = data.colors) !== null && _e !== void 0 ? _e : DEFAULT_PALETTE;
65
71
  const normalizedSeriesData = getSortedSeriesData({
66
72
  seriesData: data.series.data,
67
73
  xAxis: data.xAxis,
@@ -84,7 +90,7 @@ export function useChartInnerProps(props) {
84
90
  });
85
91
  }
86
92
  else {
87
- allPreparedSeries = (_d = (_c = prevStateValue.current) === null || _c === void 0 ? void 0 : _c.allPreparedSeries) !== null && _d !== void 0 ? _d : [];
93
+ allPreparedSeries = (_g = (_f = prevStateValue.current) === null || _f === void 0 ? void 0 : _f.allPreparedSeries) !== null && _g !== void 0 ? _g : [];
88
94
  }
89
95
  const activeLegendItems = selectedLegendItems !== null && selectedLegendItems !== void 0 ? selectedLegendItems : getActiveLegendItems(allPreparedSeries);
90
96
  const visiblePreparedSeries = getVisibleSeries({
@@ -243,6 +249,7 @@ export function useChartInnerProps(props) {
243
249
  rangeSliderState,
244
250
  dispatcher,
245
251
  htmlLayout,
252
+ updateRangeSliderState,
246
253
  clipPathId,
247
254
  ]);
248
255
  // additional start
@@ -1,4 +1,4 @@
1
- import type { AxisCrosshair, AxisPlotBand, AxisPlotShape, BaseTextStyle, ChartAxis, ChartAxisLabels, ChartAxisRangeSlider, ChartAxisTitleAlignment, ChartAxisTitleRotation, ChartAxisType, DeepRequired, MeaningfulAny, PlotLayerPlacement } from '../../types';
1
+ import type { AxisCrosshair, AxisPlotBand, AxisPlotShape, BaseTextStyle, ChartAxis, ChartAxisLabels, ChartAxisRangeSlider, ChartAxisTitleAlignment, ChartAxisTitleRotation, ChartAxisType, DeepRequired, MeaningfulAny, PlotBandAlign, PlotLayerPlacement } from '../../types';
2
2
  import type { DashStyle } from '../constants';
3
3
  type PreparedAxisLabels = Omit<ChartAxisLabels, 'enabled' | 'padding' | 'style' | 'autoRotation'> & Required<Pick<ChartAxisLabels, 'enabled' | 'padding' | 'margin' | 'rotation' | 'html'>> & {
4
4
  style: BaseTextStyle;
@@ -8,7 +8,8 @@ type PreparedAxisLabels = Omit<ChartAxisLabels, 'enabled' | 'padding' | 'style'
8
8
  lineHeight: number;
9
9
  maxWidth: number;
10
10
  };
11
- export type PreparedAxisPlotBand = Required<AxisPlotBand> & {
11
+ export type PreparedAxisPlotBand = Required<Omit<AxisPlotBand, 'size' | 'align'>> & {
12
+ align: PlotBandAlign;
12
13
  custom?: MeaningfulAny;
13
14
  label: {
14
15
  text: string;
@@ -16,6 +17,7 @@ export type PreparedAxisPlotBand = Required<AxisPlotBand> & {
16
17
  padding: number;
17
18
  qa?: string;
18
19
  };
20
+ size?: number | string;
19
21
  };
20
22
  type PreparedAxisCrosshair = Required<AxisCrosshair>;
21
23
  export type PreparedAxisPlotLine = {
@@ -166,6 +166,8 @@ export const getPreparedXAxis = async ({ xAxis, seriesData, width, boundsWidth,
166
166
  opacity: get(d, 'opacity', 1),
167
167
  from: get(d, 'from', 0),
168
168
  to: get(d, 'to', 0),
169
+ align: get(d, 'align', 'start'),
170
+ size: d.size,
169
171
  layerPlacement: get(d, 'layerPlacement', 'before'),
170
172
  custom: d.custom,
171
173
  label: prepareAxisPlotLabel(d),
@@ -181,6 +181,8 @@ export const getPreparedYAxis = ({ height, boundsHeight, width, seriesData, yAxi
181
181
  opacity: get(d, 'opacity', 1),
182
182
  from: get(d, 'from', 0),
183
183
  to: get(d, 'to', 0),
184
+ align: get(d, 'align', 'start'),
185
+ size: d.size,
184
186
  layerPlacement: get(d, 'layerPlacement', 'before'),
185
187
  custom: d.custom,
186
188
  label: prepareAxisPlotLabel(d),
@@ -0,0 +1,2 @@
1
+ export * from './types';
2
+ export * from './utils';
@@ -0,0 +1,2 @@
1
+ export * from './types';
2
+ export * from './utils';
@@ -1,6 +1,6 @@
1
1
  import type { BrushBehavior } from 'd3-brush';
2
- import type { ZoomType } from '../../core/constants';
3
- import type { ChartBrush, DeepRequired } from '../../types';
2
+ import type { ZoomType } from '../constants';
3
+ import type { ChartBrush, DeepRequired } from '../types';
4
4
  export type BrushSelection = [number, number] | [[number, number], [number, number]];
5
5
  export interface BrushArea {
6
6
  /**
@@ -1,5 +1,5 @@
1
1
  import type { BrushBehavior } from 'd3-brush';
2
- import type { ChartBrush, DeepRequired } from '../../types';
2
+ import type { ChartBrush, DeepRequired } from '../types';
3
3
  import type { BrushSelection } from './types';
4
4
  export declare function isOneDimensionalSelection(selection?: BrushSelection | null): selection is [number, number];
5
5
  export declare function setBrushBorder(this: SVGGElement, _brushInstance: BrushBehavior<unknown>, selection: BrushSelection | null, options: {
@@ -0,0 +1 @@
1
+ export * from './types';
@@ -0,0 +1 @@
1
+ export * from './types';
@@ -0,0 +1,8 @@
1
+ import type { ChartBrush, ChartMargin, ChartZoom, DeepRequired } from '../types';
2
+ export type PreparedZoom = DeepRequired<Omit<ChartZoom, 'enabled' | 'brush'>> & DeepRequired<{
3
+ brush: ChartBrush;
4
+ }>;
5
+ export type PreparedChart = {
6
+ margin: ChartMargin;
7
+ zoom: PreparedZoom | null;
8
+ };
@@ -8,3 +8,6 @@ export * from './scales';
8
8
  export * from './axes';
9
9
  export * from './layout';
10
10
  export * from './zoom';
11
+ export * from './brush';
12
+ export * from './range-slider';
13
+ export * from './chart';
@@ -8,3 +8,6 @@ export * from './scales';
8
8
  export * from './axes';
9
9
  export * from './layout';
10
10
  export * from './zoom';
11
+ export * from './brush';
12
+ export * from './range-slider';
13
+ export * from './chart';
@@ -1,6 +1,6 @@
1
- import type { PreparedChart } from '../../hooks/types';
2
1
  import type { ChartMargin, LegendConfig } from '../../types';
3
2
  import type { PreparedXAxis, PreparedYAxis } from '../axes/types';
3
+ import type { PreparedChart } from '../chart/types';
4
4
  import type { PreparedLegend, PreparedSeries } from '../series';
5
5
  export declare const getBoundsWidth: (args: {
6
6
  chartWidth: number;
@@ -0,0 +1,2 @@
1
+ export * from './types';
2
+ export * from './utils';
@@ -0,0 +1,2 @@
1
+ export * from './types';
2
+ export * from './utils';
@@ -0,0 +1,4 @@
1
+ export type RangeSliderState = {
2
+ max: number;
3
+ min: number;
4
+ };
@@ -1,8 +1,8 @@
1
- import type { ChartScale } from '../../core/scales/types';
2
- import type { PreparedLegend } from '../../core/series/types';
3
- import type { PreparedChart } from '../types';
4
- import type { PreparedRangeSlider } from '../useAxis/types';
5
- import type { BrushSelection } from '../useBrush/types';
1
+ import type { PreparedRangeSlider } from '../axes/types';
2
+ import type { BrushSelection } from '../brush/types';
3
+ import type { PreparedChart } from '../chart/types';
4
+ import type { ChartScale } from '../scales/types';
5
+ import type { PreparedLegend } from '../series/types';
6
6
  import type { RangeSliderState } from './types';
7
7
  export declare function getRangeSliderOffsetTop(args: {
8
8
  height: number;
@@ -1,4 +1,4 @@
1
- import { isBandScale } from '../../core/utils';
1
+ import { isBandScale } from '../utils';
2
2
  export function getRangeSliderOffsetTop(args) {
3
3
  var _a, _b;
4
4
  const { height, preparedChart, preparedLegend, preparedRangeSlider } = args;
@@ -1,7 +1,7 @@
1
- import type { RangeSliderState } from '../../hooks';
2
- import type { ChartAxis, ChartSeries } from '../../types';
3
1
  import type { PreparedAxis } from '../axes/types';
2
+ import type { RangeSliderState } from '../range-slider/types';
4
3
  import type { PreparedSeries } from '../series';
4
+ import type { ChartAxis, ChartSeries } from '../types';
5
5
  export declare function createXScale(args: {
6
6
  axis: PreparedAxis | ChartAxis;
7
7
  boundsWidth: number;
@@ -218,6 +218,27 @@ export function createYScale(args) {
218
218
  else {
219
219
  yMax = hasSeriesWithVolumeOnYAxis ? Math.max(yMaxDomain, 0) : yMaxDomain;
220
220
  }
221
+ // When the user pins only one of min/max on the wrong side of all data,
222
+ // d3 produces either an inverted scale (yMax<yMin, silently flips the
223
+ // axis) or a degenerate one (yMax===yMin, maps everything to the range
224
+ // midpoint); both leave phantom hover targets inside an empty plot.
225
+ // Expand the auto-computed side so the scale stays sane. Only applies
226
+ // when the opposite bound is auto-derived — if the user supplied both
227
+ // bounds, trust the explicit range and let point filtering hide the
228
+ // rest. Comparison uses the raw data extent because upstream coercions
229
+ // like volume-series `yMax = Math.max(yMaxDomain, 0)` can make the
230
+ // post-coerced yMin/yMax lie about where data actually sits.
231
+ // Logarithmic has its own guard.
232
+ if (axis.type === 'linear') {
233
+ const minIsUserSet = typeof yMinPropsOrState === 'number';
234
+ const maxIsUserSet = typeof yMaxPropsOrState === 'number';
235
+ if (minIsUserSet && !maxIsUserSet && yMaxDomain < yMin) {
236
+ yMax = yMin + Math.max(Math.abs(yMin), 1);
237
+ }
238
+ else if (maxIsUserSet && !minIsUserSet && yMinDomain > yMax) {
239
+ yMin = yMax - Math.max(Math.abs(yMax), 1);
240
+ }
241
+ }
221
242
  const scaleFn = axis.type === 'logarithmic' ? scaleLog : scaleLinear;
222
243
  let scale = scaleFn().domain([yMin, yMax]).range(range);
223
244
  let offsetMin = 0;
@@ -1,5 +1,5 @@
1
- import type { PreparedChart } from '../../hooks/types';
2
1
  import type { ChartData } from '../../types';
2
+ import type { PreparedChart } from '../chart/types';
3
3
  import type { LegendItem, PreparedLegend, PreparedSeries } from './types';
4
4
  export declare function getPreparedLegend(args: {
5
5
  legend: ChartData['legend'];
@@ -1,8 +1,8 @@
1
1
  import get from 'lodash/get';
2
2
  import merge from 'lodash/merge';
3
- import { seriesRangeSliderOptionsDefaults } from '../constants';
3
+ import { DEFAULT_DATALABELS_STYLE, seriesRangeSliderOptionsDefaults } from '../constants';
4
4
  import { getSymbolType, getUniqId } from '../utils';
5
- import { DEFAULT_HALO_OPTIONS, DEFAULT_POINT_MARKER_OPTIONS } from './constants';
5
+ import { DEFAULT_DATALABELS_PADDING, DEFAULT_HALO_OPTIONS, DEFAULT_POINT_MARKER_OPTIONS, } from './constants';
6
6
  import { prepareLegendSymbol } from './utils';
7
7
  function prepareMarker(series, seriesOptions, index) {
8
8
  const seriesHoverState = get(seriesOptions, 'scatter.states.hover');
@@ -39,7 +39,7 @@ function prepareSeriesData(series) {
39
39
  export function prepareScatterSeries(args) {
40
40
  const { colorScale, series, seriesOptions, legend } = args;
41
41
  return series.map((s, index) => {
42
- var _a, _b, _c, _d, _e, _f;
42
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
43
43
  const id = getUniqId();
44
44
  const name = 'name' in s && s.name ? s.name : '';
45
45
  const symbolType = s.symbolType || getSymbolType(index);
@@ -56,6 +56,14 @@ export function prepareScatterSeries(args) {
56
56
  itemText: (_f = (_e = s.legend) === null || _e === void 0 ? void 0 : _e.itemText) !== null && _f !== void 0 ? _f : name,
57
57
  },
58
58
  data: prepareSeriesData(s),
59
+ dataLabels: {
60
+ enabled: ((_g = s.dataLabels) === null || _g === void 0 ? void 0 : _g.enabled) || false,
61
+ style: Object.assign({}, DEFAULT_DATALABELS_STYLE, (_h = s.dataLabels) === null || _h === void 0 ? void 0 : _h.style),
62
+ padding: get(s, 'dataLabels.padding', DEFAULT_DATALABELS_PADDING),
63
+ allowOverlap: get(s, 'dataLabels.allowOverlap', false),
64
+ html: get(s, 'dataLabels.html', false),
65
+ format: (_j = s.dataLabels) === null || _j === void 0 ? void 0 : _j.format,
66
+ },
59
67
  marker: prepareMarker(s, seriesOptions, index),
60
68
  cursor: get(s, 'cursor', null),
61
69
  yAxis: get(s, 'yAxis', 0),
@@ -101,6 +101,14 @@ type BasePreparedAxisRelatedSeries = {
101
101
  export type PreparedScatterSeries = {
102
102
  type: ScatterSeries['type'];
103
103
  data: ScatterSeriesData[];
104
+ dataLabels: {
105
+ enabled: boolean;
106
+ style: BaseTextStyle;
107
+ padding: number;
108
+ allowOverlap: boolean;
109
+ html: boolean;
110
+ format?: ValueFormat;
111
+ };
104
112
  marker: {
105
113
  states: {
106
114
  normal: {
@@ -2,9 +2,8 @@ import { group, min, sort } from 'd3-array';
2
2
  import isNil from 'lodash/isNil';
3
3
  import round from 'lodash/round';
4
4
  import { prepareAnnotation } from '../../series/prepare-annotation';
5
- import { getXValue, getYValue } from '../../shapes/utils';
6
- import { getDataCategoryValue, getLabelsSize, getTextSizeFn } from '../../utils';
7
- import { getFormattedValue } from '../../utils/format';
5
+ import { getXValue, getYValue, markHiddenPointsOutOfYRange } from '../../shapes/utils';
6
+ import { getDataCategoryValue, preparePointDataLabels } from '../../utils';
8
7
  function getXValues(series, xAxis, xScale) {
9
8
  const categories = xAxis.categories || [];
10
9
  const xValues = series.reduce((acc, s) => {
@@ -30,52 +29,6 @@ function getXValues(series, xAxis, xScale) {
30
29
  }
31
30
  return sort(Array.from(xValues), (d) => d[1]);
32
31
  }
33
- async function prepareDataLabels({ series, points, xMax, yAxisTop, isOutsideBounds, }) {
34
- var _a;
35
- const svgLabels = [];
36
- const htmlLabels = [];
37
- const getTextSize = getTextSizeFn({ style: series.dataLabels.style });
38
- for (let pointsIndex = 0; pointsIndex < points.length; pointsIndex++) {
39
- const point = points[pointsIndex];
40
- if (point.y === null || isOutsideBounds(point.x, point.y)) {
41
- continue;
42
- }
43
- const text = getFormattedValue(Object.assign({ value: (_a = point.data.label) !== null && _a !== void 0 ? _a : point.data.y }, series.dataLabels));
44
- if (series.dataLabels.html) {
45
- const size = await getLabelsSize({
46
- labels: [text],
47
- style: series.dataLabels.style,
48
- html: series.dataLabels.html,
49
- });
50
- const labelSize = { width: size.maxWidth, height: size.maxHeight };
51
- const x = Math.min(xMax - labelSize.width, Math.max(0, point.x - labelSize.width / 2));
52
- const y = Math.max(yAxisTop, point.y - series.dataLabels.padding - labelSize.height);
53
- htmlLabels.push({
54
- x,
55
- y,
56
- content: text,
57
- size: labelSize,
58
- style: series.dataLabels.style,
59
- });
60
- }
61
- else {
62
- const labelSize = await getTextSize(text);
63
- const x = Math.min(xMax - labelSize.width, Math.max(0, point.x - labelSize.width / 2));
64
- const y = Math.max(yAxisTop, point.y - series.dataLabels.padding - labelSize.height + labelSize.hangingOffset);
65
- svgLabels.push({
66
- text,
67
- x,
68
- y,
69
- style: series.dataLabels.style,
70
- size: labelSize,
71
- textAnchor: 'start',
72
- series,
73
- active: true,
74
- });
75
- }
76
- }
77
- return { svgLabels, htmlLabels };
78
- }
79
32
  export const prepareAreaData = async (args) => {
80
33
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
81
34
  const { series, seriesOptions, xAxis, xScale, yAxis, yScale, split, isOutsideBounds, isRangeSlider, } = args;
@@ -315,6 +268,11 @@ export const prepareAreaData = async (args) => {
315
268
  }
316
269
  return result;
317
270
  }, []);
271
+ markHiddenPointsOutOfYRange({
272
+ points,
273
+ yScale: seriesYScale,
274
+ yAxisTop,
275
+ });
318
276
  seriesStackData.push({
319
277
  annotations,
320
278
  points,
@@ -335,7 +293,7 @@ export const prepareAreaData = async (args) => {
335
293
  const currentYAxis = yAxis[item.series.yAxis];
336
294
  const itemYAxisTop = ((_p = split.plots[currentYAxis.plotIndex]) === null || _p === void 0 ? void 0 : _p.top) || 0;
337
295
  if (item.series.dataLabels.enabled && !isRangeSlider) {
338
- const labelsData = await prepareDataLabels({
296
+ const labelsData = await preparePointDataLabels({
339
297
  series: item.series,
340
298
  points: item.points,
341
299
  xMax,
@@ -5,6 +5,7 @@ import get from 'lodash/get';
5
5
  import { block } from '../../../utils';
6
6
  import { filterOverlappingLabels } from '../../utils';
7
7
  import { renderAnnotations } from '../annotation';
8
+ import { renderDataLabels } from '../data-labels';
8
9
  import { getMarkerHaloVisibility, getMarkerVisibility, renderMarker, selectMarkerHalo, selectMarkerSymbol, setMarker, } from '../marker';
9
10
  import { setActiveState } from '../utils';
10
11
  const b = block('area');
@@ -17,7 +18,7 @@ export function renderArea(elements, preparedData, seriesOptions, allowOverlapDa
17
18
  const inactiveOptions = get(seriesOptions, 'area.states.inactive');
18
19
  const line = lineGenerator()
19
20
  .x((d) => d.x)
20
- .defined((d) => d.y !== null)
21
+ .defined((d) => d.y !== null && !d.hiddenInLine)
21
22
  .y((d) => d.y);
22
23
  plotSvgElement.selectAll('*').remove();
23
24
  markersSvgElement.selectAll('*').remove();
@@ -37,7 +38,7 @@ export function renderArea(elements, preparedData, seriesOptions, allowOverlapDa
37
38
  .attr('stroke-linejoin', 'round')
38
39
  .attr('stroke-linecap', 'round');
39
40
  const area = areaGenerator()
40
- .defined((d) => d.y !== null)
41
+ .defined((d) => d.y !== null && !d.hiddenInLine)
41
42
  .x((d) => d.x)
42
43
  .y0((d) => d.y0)
43
44
  .y1((d) => d.y);
@@ -53,18 +54,11 @@ export function renderArea(elements, preparedData, seriesOptions, allowOverlapDa
53
54
  if (!allowOverlapDataLabels) {
54
55
  dataLabels = filterOverlappingLabels(dataLabels);
55
56
  }
56
- const labelsSelection = plotSvgElement
57
- .selectAll('text')
58
- .data(dataLabels)
59
- .join('text')
60
- .html((d) => d.text)
61
- .attr('class', b('label'))
62
- .attr('x', (d) => d.x)
63
- .attr('y', (d) => d.y)
64
- .attr('text-anchor', (d) => d.textAnchor)
65
- .style('font-size', (d) => d.style.fontSize)
66
- .style('font-weight', (d) => d.style.fontWeight || null)
67
- .style('fill', (d) => d.style.fontColor || null);
57
+ const labelsSelection = renderDataLabels({
58
+ container: plotSvgElement,
59
+ data: dataLabels,
60
+ className: b('label'),
61
+ });
68
62
  const markers = preparedData.reduce((acc, d) => acc.concat(d.markers), []);
69
63
  const markerSelection = markersSvgElement
70
64
  .selectAll('marker')
@@ -1,13 +1,14 @@
1
1
  import type { AreaSeriesData, HtmlItem, LabelData } from '../../../types';
2
2
  import type { AnnotationAnchor, PreparedAnnotation, PreparedAreaSeries } from '../../series/types';
3
3
  export type PointData = {
4
- y0: number;
5
- x: number;
6
- y: number | null;
7
- data: AreaSeriesData;
8
- series: PreparedAreaSeries;
9
4
  annotation?: PreparedAnnotation;
10
5
  color?: string;
6
+ data: AreaSeriesData;
7
+ hiddenInLine?: boolean;
8
+ series: PreparedAreaSeries;
9
+ x: number;
10
+ y: number | null;
11
+ y0: number;
11
12
  };
12
13
  export type MarkerPointData = PointData & {
13
14
  y: number;