@gravity-ui/chartkit 5.10.0 → 5.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -574,5 +574,6 @@ export declare class HighchartsComponent extends React.PureComponent<Props, Stat
574
574
  updateParams: (params: StringParams) => void;
575
575
  private getId;
576
576
  private onLoad;
577
+ private needRenderCallback;
577
578
  }
578
579
  export {};
@@ -103,12 +103,7 @@ export class HighchartsComponent extends React.PureComponent {
103
103
  });
104
104
  }
105
105
  componentDidUpdate() {
106
- var _a, _b;
107
- const needRenderCallback = this.props.onRender && !this.state.isError && !this.props.splitTooltip;
108
- if (needRenderCallback) {
109
- (_b = (_a = this.props).onRender) === null || _b === void 0 ? void 0 : _b.call(_a, {
110
- renderTime: getChartPerformanceDuration(this.getId()),
111
- });
106
+ if (this.needRenderCallback()) {
112
107
  const widget = this.chartComponent.current ? this.chartComponent.current.chart : null;
113
108
  if (this.state.callback && widget) {
114
109
  this.state.callback(widget);
@@ -124,7 +119,7 @@ export class HighchartsComponent extends React.PureComponent {
124
119
  return null;
125
120
  }
126
121
  markChartPerformance(this.getId(true));
127
- return (React.createElement(Component, { key: Math.random(), options: options, highcharts: Highcharts, onSplitPaneMountCallback: this.state.callback || undefined, onSplitPaneOrientationChange: this.props.onSplitPaneOrientationChange, paneSplitOrientation: this.props.paneSplitOrientation, callback: this.extendChartInstance, constructorType: (options === null || options === void 0 ? void 0 : options.useHighStock) ? 'stockChart' : 'chart', containerProps: { className: 'chartkit-graph' }, ref: this.chartComponent }));
122
+ return (React.createElement(Component, { key: Math.random(), options: options, highcharts: Highcharts, onSplitPaneMountCallback: this.state.callback || undefined, onSplitPaneOrientationChange: this.props.onSplitPaneOrientationChange, paneSplitOrientation: this.props.paneSplitOrientation, callback: this.extendChartInstance, constructorType: (options === null || options === void 0 ? void 0 : options.useHighStock) ? 'stockChart' : 'chart', containerProps: { className: 'chartkit-graph' }, ref: this.chartComponent, onRender: this.needRenderCallback() && this.props.onRender }));
128
123
  }
129
124
  getId(refresh = false) {
130
125
  if (refresh) {
@@ -149,6 +144,11 @@ export class HighchartsComponent extends React.PureComponent {
149
144
  window.requestAnimationFrame(this.reflow);
150
145
  }
151
146
  }
147
+ needRenderCallback() {
148
+ const { splitTooltip, onRender } = this.props;
149
+ const { isError } = this.state;
150
+ return !splitTooltip && onRender && !isError;
151
+ }
152
152
  }
153
153
  HighchartsComponent.defaultProps = {
154
154
  hoistConfigError: true,
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  import Highcharts from 'highcharts';
3
+ import type { ChartKitProps } from '../../../../types';
3
4
  interface HighchartsReactRefObject {
4
5
  chart: Highcharts.Chart | null | undefined;
5
6
  container: React.RefObject<HTMLDivElement | undefined>;
@@ -13,6 +14,7 @@ interface HighchartsReactProps {
13
14
  highcharts?: typeof Highcharts;
14
15
  options: Highcharts.Options;
15
16
  callback?: Highcharts.ChartCallbackFunction;
17
+ onRender?: ChartKitProps<any>['onRender'];
16
18
  }
17
19
  export declare const HighchartsReact: React.ForwardRefExoticComponent<React.PropsWithoutRef<HighchartsReactProps> & React.RefAttributes<HighchartsReactRefObject>>;
18
20
  export default HighchartsReact;
@@ -1,9 +1,15 @@
1
1
  /* eslint no-console: ["error", { allow: ["warn", "error"]}] */
2
2
  import React from 'react';
3
+ import afterFrame from 'afterframe';
4
+ import { measurePerformance } from '../../../../utils';
5
+ import { useElementSize } from './useElementSize';
3
6
  const useIsomorphicLayoutEffect = typeof window === 'undefined' ? React.useEffect : React.useLayoutEffect;
4
7
  export const HighchartsReact = React.memo(React.forwardRef(function HighchartsReact(props, ref) {
8
+ const { onRender } = props;
5
9
  const containerRef = React.useRef(null);
6
10
  const chartRef = React.useRef();
11
+ const { width, height } = useElementSize(containerRef);
12
+ const performanceMeasure = React.useRef(measurePerformance());
7
13
  useIsomorphicLayoutEffect(() => {
8
14
  function createChart() {
9
15
  const { highcharts: HighchartsComponent } = props;
@@ -47,6 +53,21 @@ export const HighchartsReact = React.memo(React.forwardRef(function HighchartsRe
47
53
  },
48
54
  container: containerRef,
49
55
  }), []);
56
+ React.useLayoutEffect(() => {
57
+ if (width && height) {
58
+ if (!performanceMeasure.current) {
59
+ performanceMeasure.current = measurePerformance();
60
+ }
61
+ afterFrame(() => {
62
+ var _a;
63
+ const renderTime = (_a = performanceMeasure.current) === null || _a === void 0 ? void 0 : _a.end();
64
+ if (typeof renderTime === 'number') {
65
+ onRender === null || onRender === void 0 ? void 0 : onRender({ renderTime });
66
+ }
67
+ performanceMeasure.current = null;
68
+ });
69
+ }
70
+ }, [width, height, onRender]);
50
71
  return React.createElement("div", Object.assign({}, props.containerProps, { ref: containerRef }));
51
72
  }));
52
73
  HighchartsReact.displayName = 'HighchartsReact';
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ export interface UseElementSizeResult {
3
+ width: number;
4
+ height: number;
5
+ }
6
+ export declare function useElementSize<T extends HTMLElement = HTMLDivElement>(ref: React.MutableRefObject<T | null> | null, key?: string): UseElementSizeResult;
@@ -0,0 +1,50 @@
1
+ import React from 'react';
2
+ import debounce from 'lodash/debounce';
3
+ import round from 'lodash/round';
4
+ const RESIZE_DEBOUNCE = 200;
5
+ const ROUND_PRESICION = 2;
6
+ export function useElementSize(ref,
7
+ // can be used, when it is needed to force reassign observer to element
8
+ // in order to get correct measures. might be related to below
9
+ // https://github.com/WICG/resize-observer/issues/65
10
+ key) {
11
+ const [size, setSize] = React.useState({
12
+ width: 0,
13
+ height: 0,
14
+ });
15
+ React.useLayoutEffect(() => {
16
+ if (!(ref === null || ref === void 0 ? void 0 : ref.current)) {
17
+ return undefined;
18
+ }
19
+ const handleResize = (entries) => {
20
+ if (!Array.isArray(entries)) {
21
+ return;
22
+ }
23
+ const entry = entries[0];
24
+ if (entry && entry.borderBoxSize) {
25
+ const borderBoxSize = entry.borderBoxSize[0]
26
+ ? entry.borderBoxSize[0]
27
+ : entry.borderBoxSize;
28
+ // ...but old versions of Firefox treat it as a single item
29
+ // https://github.com/mdn/dom-examples/blob/main/resize-observer/resize-observer-text.html#L88
30
+ setSize({
31
+ width: round(borderBoxSize.inlineSize, ROUND_PRESICION),
32
+ height: round(borderBoxSize.blockSize, ROUND_PRESICION),
33
+ });
34
+ }
35
+ else if (entry) {
36
+ const target = entry.target;
37
+ setSize({
38
+ width: round(target.offsetWidth, ROUND_PRESICION),
39
+ height: round(target.offsetHeight, ROUND_PRESICION),
40
+ });
41
+ }
42
+ };
43
+ const observer = new ResizeObserver(debounce(handleResize, RESIZE_DEBOUNCE));
44
+ observer.observe(ref.current);
45
+ return () => {
46
+ observer.disconnect();
47
+ };
48
+ }, [ref, key]);
49
+ return size;
50
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/chartkit",
3
- "version": "5.10.0",
3
+ "version": "5.10.1",
4
4
  "description": "React component used to render charts based on any sources you need",
5
5
  "license": "MIT",
6
6
  "repository": "git@github.com:gravity-ui/ChartKit.git",