| [a762898] | 1 | import { useEffect } from 'react';
|
|---|
| 2 | import { useAppDispatch, useAppSelector } from '../state/hooks';
|
|---|
| 3 | import { setChartSize, setMargin } from '../state/layoutSlice';
|
|---|
| 4 | import { selectChartOffsetInternal, selectChartViewBox } from '../state/selectors/selectChartOffsetInternal';
|
|---|
| 5 | import { selectChartHeight, selectChartWidth } from '../state/selectors/containerSelectors';
|
|---|
| 6 | import { useIsPanorama } from './PanoramaContext';
|
|---|
| 7 | import { selectBrushDimensions, selectBrushSettings } from '../state/selectors/brushSelectors';
|
|---|
| 8 | import { useResponsiveContainerContext } from '../component/ResponsiveContainer';
|
|---|
| 9 | import { isPositiveNumber } from '../util/isWellBehavedNumber';
|
|---|
| 10 | export function cartesianViewBoxToTrapezoid(box) {
|
|---|
| 11 | if (!box) {
|
|---|
| 12 | return undefined;
|
|---|
| 13 | }
|
|---|
| 14 | return {
|
|---|
| 15 | x: box.x,
|
|---|
| 16 | y: box.y,
|
|---|
| 17 | upperWidth: 'upperWidth' in box ? box.upperWidth : box.width,
|
|---|
| 18 | lowerWidth: 'lowerWidth' in box ? box.lowerWidth : box.width,
|
|---|
| 19 | width: box.width,
|
|---|
| 20 | height: box.height
|
|---|
| 21 | };
|
|---|
| 22 | }
|
|---|
| 23 | export var useViewBox = () => {
|
|---|
| 24 | var _useAppSelector;
|
|---|
| 25 | var panorama = useIsPanorama();
|
|---|
| 26 | var rootViewBox = useAppSelector(selectChartViewBox);
|
|---|
| 27 | var brushDimensions = useAppSelector(selectBrushDimensions);
|
|---|
| 28 | var brushPadding = (_useAppSelector = useAppSelector(selectBrushSettings)) === null || _useAppSelector === void 0 ? void 0 : _useAppSelector.padding;
|
|---|
| 29 | if (!panorama || !brushDimensions || !brushPadding) {
|
|---|
| 30 | return rootViewBox;
|
|---|
| 31 | }
|
|---|
| 32 | return {
|
|---|
| 33 | width: brushDimensions.width - brushPadding.left - brushPadding.right,
|
|---|
| 34 | height: brushDimensions.height - brushPadding.top - brushPadding.bottom,
|
|---|
| 35 | x: brushPadding.left,
|
|---|
| 36 | y: brushPadding.top
|
|---|
| 37 | };
|
|---|
| 38 | };
|
|---|
| 39 | var manyComponentsThrowErrorsIfOffsetIsUndefined = {
|
|---|
| 40 | top: 0,
|
|---|
| 41 | bottom: 0,
|
|---|
| 42 | left: 0,
|
|---|
| 43 | right: 0,
|
|---|
| 44 | width: 0,
|
|---|
| 45 | height: 0,
|
|---|
| 46 | brushBottom: 0
|
|---|
| 47 | };
|
|---|
| 48 | /**
|
|---|
| 49 | * For internal use only. If you want this information, `import { useOffset } from 'recharts'` instead.
|
|---|
| 50 | *
|
|---|
| 51 | * Returns the offset of the chart in pixels.
|
|---|
| 52 | *
|
|---|
| 53 | * @returns {ChartOffsetInternal} The offset of the chart in pixels, or a default value if not in a chart context.
|
|---|
| 54 | */
|
|---|
| 55 | export var useOffsetInternal = () => {
|
|---|
| 56 | var _useAppSelector2;
|
|---|
| 57 | return (_useAppSelector2 = useAppSelector(selectChartOffsetInternal)) !== null && _useAppSelector2 !== void 0 ? _useAppSelector2 : manyComponentsThrowErrorsIfOffsetIsUndefined;
|
|---|
| 58 | };
|
|---|
| 59 |
|
|---|
| 60 | /**
|
|---|
| 61 | * Returns the width of the chart in pixels.
|
|---|
| 62 | *
|
|---|
| 63 | * If you are using chart with hardcoded `width` prop, then the width returned will be the same
|
|---|
| 64 | * as the `width` prop on the main chart element.
|
|---|
| 65 | *
|
|---|
| 66 | * If you are using a chart with a `ResponsiveContainer`, the width will be the size of the chart
|
|---|
| 67 | * as the ResponsiveContainer has decided it would be.
|
|---|
| 68 | *
|
|---|
| 69 | * If the chart has any axes or legend, the `width` will be the size of the chart
|
|---|
| 70 | * including the axes and legend. Meaning: adding axes and legend will not change the width.
|
|---|
| 71 | *
|
|---|
| 72 | * The dimensions do not scale, meaning as user zoom in and out, the width number will not change
|
|---|
| 73 | * as the chart gets visually larger or smaller.
|
|---|
| 74 | *
|
|---|
| 75 | * Returns `undefined` if used outside a chart context.
|
|---|
| 76 | *
|
|---|
| 77 | * @returns {number | undefined} The width of the chart in pixels, or `undefined` if not in a chart context.
|
|---|
| 78 | */
|
|---|
| 79 | export var useChartWidth = () => {
|
|---|
| 80 | return useAppSelector(selectChartWidth);
|
|---|
| 81 | };
|
|---|
| 82 |
|
|---|
| 83 | /**
|
|---|
| 84 | * Returns the height of the chart in pixels.
|
|---|
| 85 | *
|
|---|
| 86 | * If you are using chart with hardcoded `height` props, then the height returned will be the same
|
|---|
| 87 | * as the `height` prop on the main chart element.
|
|---|
| 88 | *
|
|---|
| 89 | * If you are using a chart with a `ResponsiveContainer`, the height will be the size of the chart
|
|---|
| 90 | * as the ResponsiveContainer has decided it would be.
|
|---|
| 91 | *
|
|---|
| 92 | * If the chart has any axes or legend, the `height` will be the size of the chart
|
|---|
| 93 | * including the axes and legend. Meaning: adding axes and legend will not change the height.
|
|---|
| 94 | *
|
|---|
| 95 | * The dimensions do not scale, meaning as user zoom in and out, the height number will not change
|
|---|
| 96 | * as the chart gets visually larger or smaller.
|
|---|
| 97 | *
|
|---|
| 98 | * Returns `undefined` if used outside a chart context.
|
|---|
| 99 | *
|
|---|
| 100 | * @returns {number | undefined} The height of the chart in pixels, or `undefined` if not in a chart context.
|
|---|
| 101 | */
|
|---|
| 102 | export var useChartHeight = () => {
|
|---|
| 103 | return useAppSelector(selectChartHeight);
|
|---|
| 104 | };
|
|---|
| 105 |
|
|---|
| 106 | /**
|
|---|
| 107 | * Margin is the empty space around the chart. Excludes axes and legend and brushes and the like.
|
|---|
| 108 | * This is declared by the user in the chart props.
|
|---|
| 109 | * If you are interested in the space occupied by axes, legend, or brushes,
|
|---|
| 110 | * use {@link useOffset} instead, which also includes calculated widths and heights of axes and legends.
|
|---|
| 111 | *
|
|---|
| 112 | * Returns `undefined` if used outside a chart context.
|
|---|
| 113 | *
|
|---|
| 114 | * @returns {Margin | undefined} The margin of the chart in pixels, or `undefined` if not in a chart context.
|
|---|
| 115 | */
|
|---|
| 116 | export var useMargin = () => {
|
|---|
| 117 | return useAppSelector(state => state.layout.margin);
|
|---|
| 118 | };
|
|---|
| 119 | export var selectChartLayout = state => state.layout.layoutType;
|
|---|
| 120 | export var useChartLayout = () => useAppSelector(selectChartLayout);
|
|---|
| 121 | export var useCartesianChartLayout = () => {
|
|---|
| 122 | var layout = useChartLayout();
|
|---|
| 123 | if (layout === 'horizontal' || layout === 'vertical') {
|
|---|
| 124 | return layout;
|
|---|
| 125 | }
|
|---|
| 126 | return undefined;
|
|---|
| 127 | };
|
|---|
| 128 | export var selectPolarChartLayout = state => {
|
|---|
| 129 | var layout = state.layout.layoutType;
|
|---|
| 130 | if (layout === 'centric' || layout === 'radial') {
|
|---|
| 131 | return layout;
|
|---|
| 132 | }
|
|---|
| 133 | return undefined;
|
|---|
| 134 | };
|
|---|
| 135 | export var usePolarChartLayout = () => {
|
|---|
| 136 | return useAppSelector(selectPolarChartLayout);
|
|---|
| 137 | };
|
|---|
| 138 |
|
|---|
| 139 | /**
|
|---|
| 140 | * Returns true if the component is rendered inside a chart context.
|
|---|
| 141 | * Some components may be used both inside and outside of charts,
|
|---|
| 142 | * and this hook allows them to determine if they are in a chart context or not.
|
|---|
| 143 | *
|
|---|
| 144 | * Other selectors may return undefined when used outside a chart context,
|
|---|
| 145 | * or undefined when inside a chart, but without relevant data.
|
|---|
| 146 | * This hook provides a more explicit way to check for chart context.
|
|---|
| 147 | *
|
|---|
| 148 | * @returns {boolean} True if in chart context, false otherwise.
|
|---|
| 149 | */
|
|---|
| 150 | export var useIsInChartContext = () => {
|
|---|
| 151 | /*
|
|---|
| 152 | * All charts provide a layout type in the chart context.
|
|---|
| 153 | * If we have a layout type, we are in a chart context.
|
|---|
| 154 | */
|
|---|
| 155 | var layout = useChartLayout();
|
|---|
| 156 | return layout !== undefined;
|
|---|
| 157 | };
|
|---|
| 158 | export var ReportChartSize = props => {
|
|---|
| 159 | var dispatch = useAppDispatch();
|
|---|
| 160 |
|
|---|
| 161 | /*
|
|---|
| 162 | * Skip dispatching properties in panorama chart for two reasons:
|
|---|
| 163 | * 1. The root chart should be deciding on these properties, and
|
|---|
| 164 | * 2. Brush reads these properties from redux store, and so they must remain stable
|
|---|
| 165 | * to avoid circular dependency and infinite re-rendering.
|
|---|
| 166 | */
|
|---|
| 167 | var isPanorama = useIsPanorama();
|
|---|
| 168 | var {
|
|---|
| 169 | width: widthFromProps,
|
|---|
| 170 | height: heightFromProps
|
|---|
| 171 | } = props;
|
|---|
| 172 | var responsiveContainerCalculations = useResponsiveContainerContext();
|
|---|
| 173 | var width = widthFromProps;
|
|---|
| 174 | var height = heightFromProps;
|
|---|
| 175 | if (responsiveContainerCalculations) {
|
|---|
| 176 | /*
|
|---|
| 177 | * In case we receive width and height from ResponsiveContainer,
|
|---|
| 178 | * we will always prefer those.
|
|---|
| 179 | * Only in case ResponsiveContainer does not provide width or height,
|
|---|
| 180 | * we will fall back to the explicitly provided width and height.
|
|---|
| 181 | *
|
|---|
| 182 | * This to me feels backwards - we should allow override by the more specific props on individual charts, right?
|
|---|
| 183 | * But this is 3.x behaviour, so let's keep it for backwards compatibility.
|
|---|
| 184 | *
|
|---|
| 185 | * We can change this in 4.x if we want to.
|
|---|
| 186 | */
|
|---|
| 187 | width = responsiveContainerCalculations.width > 0 ? responsiveContainerCalculations.width : widthFromProps;
|
|---|
| 188 | height = responsiveContainerCalculations.height > 0 ? responsiveContainerCalculations.height : heightFromProps;
|
|---|
| 189 | }
|
|---|
| 190 | useEffect(() => {
|
|---|
| 191 | if (!isPanorama && isPositiveNumber(width) && isPositiveNumber(height)) {
|
|---|
| 192 | dispatch(setChartSize({
|
|---|
| 193 | width,
|
|---|
| 194 | height
|
|---|
| 195 | }));
|
|---|
| 196 | }
|
|---|
| 197 | }, [dispatch, isPanorama, width, height]);
|
|---|
| 198 | return null;
|
|---|
| 199 | };
|
|---|
| 200 | export var ReportChartMargin = _ref => {
|
|---|
| 201 | var {
|
|---|
| 202 | margin
|
|---|
| 203 | } = _ref;
|
|---|
| 204 | var dispatch = useAppDispatch();
|
|---|
| 205 | useEffect(() => {
|
|---|
| 206 | dispatch(setMargin(margin));
|
|---|
| 207 | }, [dispatch, margin]);
|
|---|
| 208 | return null;
|
|---|
| 209 | }; |
|---|