@octanejs/recharts 0.1.62 → 0.1.64
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.
- package/package.json +5 -5
- package/src/animation/AnimatedItems.tsrx +36 -31
- package/src/animation/CSSTransitionAnimate.tsrx +1 -2
- package/src/animation/JavascriptAnimate.tsrx +1 -2
- package/src/cartesian/Area.tsrx +414 -386
- package/src/cartesian/AreaRevealShape.tsrx +103 -84
- package/src/cartesian/Bar.tsrx +343 -317
- package/src/cartesian/BarStack.tsrx +33 -28
- package/src/cartesian/CartesianAxis.tsrx +168 -165
- package/src/cartesian/CartesianGrid.tsrx +256 -272
- package/src/cartesian/ErrorBar.tsrx +108 -104
- package/src/cartesian/Funnel.tsrx +405 -382
- package/src/cartesian/GraphicalItemClipPath.tsrx +4 -8
- package/src/cartesian/Line.tsrx +190 -177
- package/src/cartesian/LineDrawShape.tsrx +14 -15
- package/src/cartesian/ReferenceLine.tsrx +119 -105
- package/src/cartesian/Scatter.tsrx +416 -398
- package/src/cartesian/XAxis.tsrx +39 -32
- package/src/cartesian/YAxis.tsrx +47 -37
- package/src/cartesian/ZAxis.tsrx +76 -73
- package/src/chart/AreaChart.tsrx +15 -11
- package/src/chart/BarChart.tsrx +15 -11
- package/src/chart/CategoricalChart.tsrx +32 -26
- package/src/chart/ComposedChart.tsrx +15 -11
- package/src/chart/FunnelChart.tsrx +15 -11
- package/src/chart/LineChart.tsrx +15 -11
- package/src/chart/PieChart.tsrx +15 -11
- package/src/chart/PolarChart.tsrx +45 -48
- package/src/chart/RadarChart.tsrx +38 -32
- package/src/chart/RadialBarChart.tsrx +15 -11
- package/src/chart/RechartsWrapper.tsrx +214 -162
- package/src/chart/Sankey.tsrx +412 -378
- package/src/chart/ScatterChart.tsrx +15 -11
- package/src/chart/SunburstChart.tsrx +162 -155
- package/src/component/ActivePoints.tsrx +19 -13
- package/src/component/Cursor.tsrx +25 -18
- package/src/component/DefaultLegendContent.tsrx +131 -127
- package/src/component/DefaultTooltipContent.tsrx +46 -42
- package/src/component/Dots.tsrx +11 -5
- package/src/component/Label.tsrx +69 -55
- package/src/component/LabelList.tsrx +32 -27
- package/src/component/Legend.tsrx +120 -123
- package/src/component/ResponsiveContainer.tsrx +18 -11
- package/src/component/Text.tsrx +50 -43
- package/src/component/Tooltip.tsrx +234 -223
- package/src/component/TooltipBoundingBox.tsrx +34 -34
- package/src/container/ClipPathProvider.tsrx +1 -3
- package/src/container/Layer.tsrx +5 -1
- package/src/container/RootSurface.tsrx +31 -21
- package/src/container/Surface.tsrx +15 -13
- package/src/context/ErrorBarContext.tsrx +5 -5
- package/src/polar/Pie.tsrx +541 -487
- package/src/polar/PolarAngleAxis.tsrx +245 -227
- package/src/polar/PolarGrid.tsrx +139 -127
- package/src/polar/PolarRadiusAxis.tsrx +204 -185
- package/src/polar/Radar.tsrx +274 -264
- package/src/polar/RadialBar.tsrx +408 -361
- package/src/shape/Cross.tsrx +13 -7
- package/src/shape/Curve.tsrx +54 -44
- package/src/shape/Dot.tsrx +10 -8
- package/src/shape/Polygon.tsrx +38 -29
- package/src/shape/Rectangle.tsrx +73 -28
- package/src/shape/Sector.tsrx +30 -18
- package/src/shape/Symbols.tsrx +13 -11
- package/src/shape/Trapezoid.tsrx +16 -11
- package/src/state/RechartsStoreProvider.tsrx +5 -1
- package/src/synchronisation/useChartSynchronisation.tsrx +8 -7
- package/src/util/BarUtils.tsrx +43 -40
- package/src/util/FunnelUtils.tsrx +5 -5
- package/src/util/RadialBarUtils.tsrx +3 -4
- package/src/util/ScatterUtils.tsrx +13 -8
- package/src/zIndex/ZIndexLayer.tsrx +2 -2
- package/src/zIndex/ZIndexPortal.tsrx +2 -8
package/src/component/Label.tsrx
CHANGED
|
@@ -32,10 +32,9 @@ interface LabelProps extends ZIndexable {
|
|
|
32
32
|
id?: string;
|
|
33
33
|
}
|
|
34
34
|
export type Props = Omit<SVGProps<SVGTextElement>, 'viewBox'> & LabelProps;
|
|
35
|
-
type PropsWithDefaults =
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
};
|
|
35
|
+
type PropsWithDefaults = Props & {
|
|
36
|
+
offset: number;
|
|
37
|
+
};
|
|
39
38
|
export type ImplicitLabelType =
|
|
40
39
|
| boolean
|
|
41
40
|
| string
|
|
@@ -80,33 +79,34 @@ import { getCartesianPosition } from '../cartesian/getCartesianPosition';
|
|
|
80
79
|
|
|
81
80
|
const CartesianLabelContext = createContext<TrapezoidViewBox | null>(null);
|
|
82
81
|
|
|
83
|
-
export function CartesianLabelContextProvider(
|
|
84
|
-
|
|
85
|
-
|
|
82
|
+
export function CartesianLabelContextProvider(
|
|
83
|
+
props: TrapezoidViewBox & {
|
|
84
|
+
children: OctaneNode;
|
|
85
|
+
},
|
|
86
|
+
) @{
|
|
86
87
|
const { x, y, upperWidth, lowerWidth, width, height, children } = props;
|
|
87
|
-
const viewBox = useMemo(
|
|
88
|
-
x,
|
|
89
|
-
y,
|
|
90
|
-
|
|
91
|
-
lowerWidth,
|
|
92
|
-
width,
|
|
93
|
-
height,
|
|
94
|
-
]);
|
|
88
|
+
const viewBox = useMemo(
|
|
89
|
+
() => ({ x, y, upperWidth, lowerWidth, width, height }),
|
|
90
|
+
[x, y, upperWidth, lowerWidth, width, height],
|
|
91
|
+
);
|
|
95
92
|
<CartesianLabelContext value={viewBox}>{children}</CartesianLabelContext>
|
|
96
93
|
}
|
|
97
94
|
|
|
98
95
|
function useCartesianLabelContext() {
|
|
99
96
|
const labelChildContext = useContext(CartesianLabelContext);
|
|
100
97
|
const chartContext = useViewBox();
|
|
101
|
-
return
|
|
102
|
-
(chartContext ? cartesianViewBoxToTrapezoid(chartContext) : undefined)
|
|
98
|
+
return (
|
|
99
|
+
labelChildContext || (chartContext ? cartesianViewBoxToTrapezoid(chartContext) : undefined)
|
|
100
|
+
);
|
|
103
101
|
}
|
|
104
102
|
|
|
105
103
|
const PolarLabelContext = createContext<PolarViewBoxRequired | null>(null);
|
|
106
104
|
|
|
107
|
-
export function PolarLabelContextProvider(
|
|
108
|
-
|
|
109
|
-
|
|
105
|
+
export function PolarLabelContextProvider(
|
|
106
|
+
props: PolarViewBoxRequired & {
|
|
107
|
+
children: OctaneNode;
|
|
108
|
+
},
|
|
109
|
+
) @{
|
|
110
110
|
const { cx, cy, innerRadius, outerRadius, startAngle, endAngle, clockWise, children } = props;
|
|
111
111
|
const viewBox = useMemo(
|
|
112
112
|
() => ({ cx, cy, innerRadius, outerRadius, startAngle, endAngle, clockWise }),
|
|
@@ -151,8 +151,7 @@ function renderRadialLabel(
|
|
|
151
151
|
const { cx, cy, innerRadius, outerRadius, startAngle, endAngle, clockWise } = viewBox;
|
|
152
152
|
const radius = (innerRadius + outerRadius) / 2;
|
|
153
153
|
const deltaAngle = getDeltaAngle(startAngle, endAngle);
|
|
154
|
-
const sign =
|
|
155
|
-
deltaAngle >= 0 ? 1 : -1;
|
|
154
|
+
const sign = deltaAngle >= 0 ? 1 : -1;
|
|
156
155
|
let labelAngle, direction;
|
|
157
156
|
switch (position) {
|
|
158
157
|
case 'insideStart':
|
|
@@ -174,24 +173,33 @@ function renderRadialLabel(
|
|
|
174
173
|
const startPoint = polarToCartesian(cx, cy, radius, labelAngle);
|
|
175
174
|
const endPoint = polarToCartesian(cx, cy, radius, labelAngle + (direction ? 1 : -1) * 359);
|
|
176
175
|
const path =
|
|
177
|
-
'M' +
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
176
|
+
'M' +
|
|
177
|
+
startPoint.x +
|
|
178
|
+
',' +
|
|
179
|
+
startPoint.y +
|
|
180
|
+
'\n A' +
|
|
181
|
+
radius +
|
|
182
|
+
',' +
|
|
183
|
+
radius +
|
|
184
|
+
',0,1,' +
|
|
185
|
+
(direction ? 0 : 1) +
|
|
186
|
+
',\n ' +
|
|
187
|
+
endPoint.x +
|
|
188
|
+
',' +
|
|
182
189
|
endPoint.y;
|
|
183
|
-
const id =
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
190
|
+
const id = isNullish(labelProps.id) ? uniqueId('recharts-radial-line-') : labelProps.id;
|
|
191
|
+
return (
|
|
192
|
+
<text
|
|
193
|
+
{...attrs}
|
|
194
|
+
dominantBaseline="central"
|
|
195
|
+
class={clsx('recharts-radial-bar-label', className)}
|
|
196
|
+
>
|
|
197
|
+
<defs>
|
|
198
|
+
<path id={id} d={path} />
|
|
199
|
+
</defs>
|
|
200
|
+
<textPath xlinkHref={'#' + id}>{label}</textPath>
|
|
201
|
+
</text>
|
|
202
|
+
);
|
|
195
203
|
}
|
|
196
204
|
|
|
197
205
|
const getAttrsOfPolarLabel = (
|
|
@@ -270,7 +278,7 @@ export function Label(outerProps: Props) {
|
|
|
270
278
|
|
|
271
279
|
// position 'center' prefers the cartesian box (recharts#6030 quick fix).
|
|
272
280
|
const resolvedViewBox =
|
|
273
|
-
position === 'center' ? cartesianViewBox : polarViewBox ?? cartesianViewBox;
|
|
281
|
+
position === 'center' ? cartesianViewBox : (polarViewBox ?? cartesianViewBox);
|
|
274
282
|
let viewBox, label, positionAttrs: LabelPositionAttributes;
|
|
275
283
|
if (viewBoxFromProps == null) {
|
|
276
284
|
viewBox = resolvedViewBox;
|
|
@@ -282,8 +290,10 @@ export function Label(outerProps: Props) {
|
|
|
282
290
|
const cartesianBox = polarViewBoxToTrapezoid(viewBox);
|
|
283
291
|
if (
|
|
284
292
|
!viewBox ||
|
|
285
|
-
|
|
286
|
-
|
|
293
|
+
(isNullish(value) &&
|
|
294
|
+
isNullish(children) &&
|
|
295
|
+
!isValidElement(content) &&
|
|
296
|
+
typeof content !== 'function')
|
|
287
297
|
) {
|
|
288
298
|
return null;
|
|
289
299
|
}
|
|
@@ -327,16 +337,22 @@ export function Label(outerProps: Props) {
|
|
|
327
337
|
...(cartesianResult.height !== undefined ? { height: cartesianResult.height } : {}),
|
|
328
338
|
};
|
|
329
339
|
}
|
|
330
|
-
return
|
|
331
|
-
<
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
+
return (
|
|
341
|
+
<ZIndexLayer zIndex={props.zIndex}>
|
|
342
|
+
<Text
|
|
343
|
+
ref={labelRef}
|
|
344
|
+
className={clsx('recharts-label', className)}
|
|
345
|
+
{...attrs}
|
|
346
|
+
{...positionAttrs}
|
|
347
|
+
textAnchor={
|
|
348
|
+
isValidTextAnchor(attrs.textAnchor) ? attrs.textAnchor : positionAttrs.textAnchor
|
|
349
|
+
}
|
|
350
|
+
breakAll={textBreakAll}
|
|
351
|
+
>
|
|
352
|
+
{label}
|
|
353
|
+
</Text>
|
|
354
|
+
</ZIndexLayer>
|
|
355
|
+
);
|
|
340
356
|
}
|
|
341
357
|
|
|
342
358
|
Label.displayName = 'Label';
|
|
@@ -380,9 +396,7 @@ export function CartesianLabelFromLabelProp(props: {
|
|
|
380
396
|
return parseLabel(label, viewBox, labelRef) || null;
|
|
381
397
|
}
|
|
382
398
|
|
|
383
|
-
export function PolarLabelFromLabelProp(props: {
|
|
384
|
-
label: ImplicitLabelType | undefined;
|
|
385
|
-
}) {
|
|
399
|
+
export function PolarLabelFromLabelProp(props: { label: ImplicitLabelType | undefined }) {
|
|
386
400
|
const { label } = props;
|
|
387
401
|
const viewBox = usePolarLabelContext();
|
|
388
402
|
return parseLabel(label, viewBox) || null;
|
|
@@ -26,8 +26,10 @@ export interface PolarLabelListEntry extends LabelListEntry {
|
|
|
26
26
|
}
|
|
27
27
|
interface LabelListProps extends ZIndexable {
|
|
28
28
|
id?: string;
|
|
29
|
-
valueAccessor?: (
|
|
30
|
-
|
|
29
|
+
valueAccessor?: (
|
|
30
|
+
entry: CartesianLabelListEntry | PolarLabelListEntry,
|
|
31
|
+
index: number,
|
|
32
|
+
) => RenderableText;
|
|
31
33
|
clockWise?: boolean;
|
|
32
34
|
dataKey?: DataKey<any>;
|
|
33
35
|
content?: LabelContentType;
|
|
@@ -86,35 +88,38 @@ export function LabelList(labelListProps: Props) {
|
|
|
86
88
|
if (!data || !data.length) {
|
|
87
89
|
return null;
|
|
88
90
|
}
|
|
89
|
-
return
|
|
90
|
-
<
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
91
|
+
return (
|
|
92
|
+
<ZIndexLayer zIndex={zIndex ?? DefaultZIndexes.label}>
|
|
93
|
+
<Layer className="recharts-label-list">
|
|
94
|
+
{data.map((entry, index) => {
|
|
95
|
+
const value = isNullish(dataKey)
|
|
96
|
+
? valueAccessor(entry, index)
|
|
97
|
+
: getValueByDataKey(entry.payload, dataKey);
|
|
98
|
+
const idProps = isNullish(id) ? {} : { id: id + '-' + index };
|
|
99
|
+
return (
|
|
100
|
+
<Label
|
|
101
|
+
key={'label-' + index}
|
|
102
|
+
{...svgPropertiesAndEvents(entry)}
|
|
103
|
+
{...others}
|
|
104
|
+
{...idProps}
|
|
105
|
+
fill={restProps.fill ?? entry.fill}
|
|
106
|
+
parentViewBox={entry.parentViewBox}
|
|
107
|
+
value={value}
|
|
108
|
+
textBreakAll={textBreakAll}
|
|
109
|
+
viewBox={entry.viewBox}
|
|
110
|
+
index={index}
|
|
111
|
+
zIndex={0}
|
|
112
|
+
/>
|
|
113
|
+
);
|
|
114
|
+
})}
|
|
115
|
+
</Layer>
|
|
116
|
+
</ZIndexLayer>
|
|
117
|
+
);
|
|
111
118
|
}
|
|
112
119
|
|
|
113
120
|
LabelList.displayName = 'LabelList';
|
|
114
121
|
|
|
115
|
-
export function LabelListFromLabelProp(props: {
|
|
116
|
-
label?: ImplicitLabelListType;
|
|
117
|
-
}) {
|
|
122
|
+
export function LabelListFromLabelProp(props: { label?: ImplicitLabelListType }) {
|
|
118
123
|
const { label } = props;
|
|
119
124
|
if (!label) {
|
|
120
125
|
return null;
|
|
@@ -25,13 +25,12 @@ function defaultUniqBy(entry: LegendPayload) {
|
|
|
25
25
|
return entry.value;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
type ContentProps =
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
};
|
|
28
|
+
type ContentProps = Props & {
|
|
29
|
+
margin: Margin | undefined;
|
|
30
|
+
chartWidth: number;
|
|
31
|
+
chartHeight: number;
|
|
32
|
+
contextPayload: ReadonlyArray<LegendPayload>;
|
|
33
|
+
};
|
|
35
34
|
|
|
36
35
|
function LegendContent(props: ContentProps) {
|
|
37
36
|
const { contextPayload, ...otherProps } = props;
|
|
@@ -70,29 +69,31 @@ function getDefaultPosition(
|
|
|
70
69
|
|
|
71
70
|
if (
|
|
72
71
|
!style ||
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
((style.left === undefined || style.left === null) &&
|
|
73
|
+
(style.right === undefined || style.right === null))
|
|
75
74
|
) {
|
|
76
75
|
if (align === 'center' && layout === 'vertical') {
|
|
77
76
|
hPos = { left: ((chartWidth || 0) - box.width) / 2 };
|
|
78
77
|
} else {
|
|
79
|
-
hPos =
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
hPos =
|
|
79
|
+
align === 'right'
|
|
80
|
+
? { right: (margin && margin.right) || 0 }
|
|
81
|
+
: { left: (margin && margin.left) || 0 };
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
if (
|
|
86
86
|
!style ||
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
((style.top === undefined || style.top === null) &&
|
|
88
|
+
(style.bottom === undefined || style.bottom === null))
|
|
89
89
|
) {
|
|
90
90
|
if (verticalAlign === 'middle') {
|
|
91
91
|
vPos = { top: ((chartHeight || 0) - box.height) / 2 };
|
|
92
92
|
} else {
|
|
93
|
-
vPos =
|
|
94
|
-
|
|
95
|
-
|
|
93
|
+
vPos =
|
|
94
|
+
verticalAlign === 'bottom'
|
|
95
|
+
? { bottom: (margin && margin.bottom) || 0 }
|
|
96
|
+
: { top: (margin && margin.top) || 0 };
|
|
96
97
|
}
|
|
97
98
|
}
|
|
98
99
|
|
|
@@ -101,68 +102,67 @@ function getDefaultPosition(
|
|
|
101
102
|
|
|
102
103
|
export type LegendItemSorter = 'value' | 'dataKey' | ((item: LegendPayload) => number | string);
|
|
103
104
|
|
|
104
|
-
export type Props =
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
};
|
|
105
|
+
export type Props = Omit<DefaultLegendContentProps, 'payload' | 'ref' | 'verticalAlign'> & {
|
|
106
|
+
/**
|
|
107
|
+
* Renders the content of the legend.
|
|
108
|
+
*
|
|
109
|
+
* This should return HTML elements, not SVG elements.
|
|
110
|
+
*
|
|
111
|
+
* - If not set, the {@link DefaultLegendContent} component is used.
|
|
112
|
+
* - If set to a React element, this element will be cloned and extra props will be passed in.
|
|
113
|
+
* - If set to a function, the function will be called and should return HTML elements.
|
|
114
|
+
*
|
|
115
|
+
* @example <Legend content={CustomizedLegend} />
|
|
116
|
+
* @example <Legend content={renderLegend} />
|
|
117
|
+
*/
|
|
118
|
+
content?: ContentType;
|
|
119
|
+
/**
|
|
120
|
+
* CSS styles to be applied to the wrapper `div` element.
|
|
121
|
+
*/
|
|
122
|
+
wrapperStyle?: CSSProperties;
|
|
123
|
+
/**
|
|
124
|
+
* Width of the legend.
|
|
125
|
+
* Accept CSS style string values like `100%` or `fit-content`, or number values like `400`.
|
|
126
|
+
*/
|
|
127
|
+
width?: number | string;
|
|
128
|
+
/**
|
|
129
|
+
* Height of the legend.
|
|
130
|
+
* Accept CSS style string values like `100%` or `fit-content`, or number values like `400`.
|
|
131
|
+
*/
|
|
132
|
+
height?: number | string;
|
|
133
|
+
payloadUniqBy?: UniqueOption<LegendPayload>;
|
|
134
|
+
onBBoxUpdate?: (box: ElementOffset | null) => void;
|
|
135
|
+
/**
|
|
136
|
+
* If portal is defined, then Legend will use this element as a target
|
|
137
|
+
* for rendering using React Portal.
|
|
138
|
+
*
|
|
139
|
+
* If this is undefined then Legend renders inside the recharts-wrapper element.
|
|
140
|
+
*
|
|
141
|
+
* @see {@link https://react.dev/reference/react-dom/createPortal}
|
|
142
|
+
*/
|
|
143
|
+
portal?: HTMLElement | null;
|
|
144
|
+
/**
|
|
145
|
+
* Sorts Legend items. Defaults to `value` which means it will sort alphabetically
|
|
146
|
+
* by the label.
|
|
147
|
+
*
|
|
148
|
+
* If `null` is provided then the payload is not sorted. Be aware that without sort,
|
|
149
|
+
* the order of items may change between renders!
|
|
150
|
+
*
|
|
151
|
+
* @defaultValue value
|
|
152
|
+
*/
|
|
153
|
+
itemSorter?: LegendItemSorter | null;
|
|
154
|
+
/**
|
|
155
|
+
* The alignment of the whole Legend container:
|
|
156
|
+
*
|
|
157
|
+
* - `bottom`: shows the Legend below chart, and chart height reduces automatically to make space for it.
|
|
158
|
+
* - `top`: shows the Legend above chart, and chart height reduces automatically.
|
|
159
|
+
* - `middle`: shows the Legend in the middle of chart, covering other content, and chart height remains unchanged.
|
|
160
|
+
* The exact behavior changes depending on `align` prop.
|
|
161
|
+
*
|
|
162
|
+
* @defaultValue bottom
|
|
163
|
+
*/
|
|
164
|
+
verticalAlign?: VerticalAlignmentType;
|
|
165
|
+
};
|
|
166
166
|
|
|
167
167
|
function LegendSettingsDispatcher({
|
|
168
168
|
align,
|
|
@@ -247,23 +247,22 @@ function LegendImpl(outsideProps: Props) {
|
|
|
247
247
|
const maxWidth = chartWidth - (margin?.left || 0) - (margin?.right || 0);
|
|
248
248
|
const widthOrHeight = getWidthOrHeight(props.layout, heightFromProps, widthFromProps, maxWidth);
|
|
249
249
|
// if the user supplies their own portal, only use their defined wrapper styles
|
|
250
|
-
const outerStyle: CSSProperties | undefined =
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
};
|
|
250
|
+
const outerStyle: CSSProperties | undefined = portalFromProps
|
|
251
|
+
? wrapperStyle
|
|
252
|
+
: {
|
|
253
|
+
position: 'absolute',
|
|
254
|
+
width: widthOrHeight?.width || widthFromProps || 'auto',
|
|
255
|
+
height: widthOrHeight?.height || heightFromProps || 'auto',
|
|
256
|
+
...getDefaultPosition(
|
|
257
|
+
wrapperStyle,
|
|
258
|
+
props,
|
|
259
|
+
margin,
|
|
260
|
+
chartWidth,
|
|
261
|
+
chartHeight,
|
|
262
|
+
lastBoundingBox,
|
|
263
|
+
),
|
|
264
|
+
...wrapperStyle,
|
|
265
|
+
};
|
|
267
266
|
|
|
268
267
|
const legendPortal = portalFromProps ?? legendPortalFromContext;
|
|
269
268
|
|
|
@@ -271,36 +270,34 @@ function LegendImpl(outsideProps: Props) {
|
|
|
271
270
|
return null;
|
|
272
271
|
}
|
|
273
272
|
|
|
274
|
-
const legendElement =
|
|
275
|
-
className="recharts-legend-wrapper"
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
</div>;
|
|
273
|
+
const legendElement = (
|
|
274
|
+
<div className="recharts-legend-wrapper" style={outerStyle} ref={updateBoundingBox}>
|
|
275
|
+
<LegendSettingsDispatcher
|
|
276
|
+
layout={props.layout}
|
|
277
|
+
align={props.align}
|
|
278
|
+
verticalAlign={props.verticalAlign}
|
|
279
|
+
itemSorter={props.itemSorter}
|
|
280
|
+
/>
|
|
281
|
+
{/* if we have a portal from props nothing should need the size of the legend */}
|
|
282
|
+
{!portalFromProps && (
|
|
283
|
+
<LegendSizeDispatcher width={lastBoundingBox.width} height={lastBoundingBox.height} />
|
|
284
|
+
)}
|
|
285
|
+
<LegendContent
|
|
286
|
+
{...props}
|
|
287
|
+
{...widthOrHeight}
|
|
288
|
+
margin={margin}
|
|
289
|
+
chartWidth={chartWidth}
|
|
290
|
+
chartHeight={chartHeight}
|
|
291
|
+
contextPayload={contextPayload}
|
|
292
|
+
/>
|
|
293
|
+
</div>
|
|
294
|
+
);
|
|
297
295
|
|
|
298
296
|
return createPortal(legendElement, legendPortal);
|
|
299
297
|
}
|
|
300
298
|
|
|
301
|
-
export const Legend = React.memo(LegendImpl, propsAreEqual) as
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
};
|
|
299
|
+
export const Legend = React.memo(LegendImpl, propsAreEqual) as typeof LegendImpl & {
|
|
300
|
+
displayName?: string;
|
|
301
|
+
};
|
|
305
302
|
|
|
306
303
|
Legend.displayName = 'Legend';
|
|
@@ -66,9 +66,11 @@ function ResponsiveContainerContextProvider({
|
|
|
66
66
|
if (!isPositiveNumber(size.width) || !isPositiveNumber(size.height)) {
|
|
67
67
|
return null;
|
|
68
68
|
}
|
|
69
|
-
return
|
|
70
|
-
value={size as ResponsiveContainerDimensions}
|
|
71
|
-
|
|
69
|
+
return (
|
|
70
|
+
<ResponsiveContainerContext value={size as ResponsiveContainerDimensions}>
|
|
71
|
+
{children}
|
|
72
|
+
</ResponsiveContainerContext>
|
|
73
|
+
);
|
|
72
74
|
}
|
|
73
75
|
|
|
74
76
|
function SizeDetectorContainer(props: Props) @{
|
|
@@ -100,9 +102,8 @@ function SizeDetectorContainer(props: Props) @{
|
|
|
100
102
|
const setContainerSize = useCallback((newWidth: number, newHeight: number) => {
|
|
101
103
|
const containerWidth = Math.round(newWidth);
|
|
102
104
|
const containerHeight = Math.round(newHeight);
|
|
103
|
-
setSizes(
|
|
104
|
-
|
|
105
|
-
previous.containerHeight === containerHeight
|
|
105
|
+
setSizes((previous) =>
|
|
106
|
+
previous.containerWidth === containerWidth && previous.containerHeight === containerHeight
|
|
106
107
|
? previous
|
|
107
108
|
: { containerWidth, containerHeight },
|
|
108
109
|
);
|
|
@@ -147,7 +148,9 @@ function SizeDetectorContainer(props: Props) @{
|
|
|
147
148
|
<ResponsiveContainerContextProvider
|
|
148
149
|
width={calculated.calculatedWidth}
|
|
149
150
|
height={calculated.calculatedHeight}
|
|
150
|
-
>
|
|
151
|
+
>
|
|
152
|
+
{children}
|
|
153
|
+
</ResponsiveContainerContextProvider>
|
|
151
154
|
</div>
|
|
152
155
|
</div>
|
|
153
156
|
}
|
|
@@ -165,10 +168,14 @@ export function ResponsiveContainer(props: Props) {
|
|
|
165
168
|
maxHeight: props.maxHeight,
|
|
166
169
|
});
|
|
167
170
|
if (isNumber(calculated.calculatedWidth) && isNumber(calculated.calculatedHeight)) {
|
|
168
|
-
return
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
171
|
+
return (
|
|
172
|
+
<ResponsiveContainerContextProvider
|
|
173
|
+
width={calculated.calculatedWidth}
|
|
174
|
+
height={calculated.calculatedHeight}
|
|
175
|
+
>
|
|
176
|
+
{props.children}
|
|
177
|
+
</ResponsiveContainerContextProvider>
|
|
178
|
+
);
|
|
172
179
|
}
|
|
173
180
|
return <SizeDetectorContainer {...props} width={defaults.width} height={defaults.height} />;
|
|
174
181
|
}
|