@solidports/recharts 0.1.0 → 0.1.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.
- package/dist/index.d.ts +40 -2
- package/dist/index.js +14238 -7174
- package/dist/{dev.js → index.jsx} +18367 -15900
- package/dist/server.js +48178 -0
- package/package.json +36 -19
- package/src/animation/AnimatedItems.tsx +0 -183
- package/src/animation/AnimationController.ts +0 -33
- package/src/animation/AnimationControllerImpl.ts +0 -36
- package/src/animation/AnimationHandle.ts +0 -307
- package/src/animation/CSSTransitionAnimate.tsx +0 -170
- package/src/animation/JavascriptAnimate.tsx +0 -119
- package/src/animation/easing.ts +0 -221
- package/src/animation/matchBy.ts +0 -164
- package/src/animation/timeoutController.ts +0 -70
- package/src/animation/useAnimationController.tsx +0 -34
- package/src/animation/useAnimationStartSnapshot.ts +0 -118
- package/src/animation/util.ts +0 -41
- package/src/cartesian/Area.tsx +0 -915
- package/src/cartesian/AreaRevealShape.tsx +0 -190
- package/src/cartesian/Bar.tsx +0 -1369
- package/src/cartesian/BarStack.tsx +0 -152
- package/src/cartesian/Brush.tsx +0 -951
- package/src/cartesian/CartesianAxis.tsx +0 -722
- package/src/cartesian/CartesianGrid.tsx +0 -711
- package/src/cartesian/ErrorBar.tsx +0 -361
- package/src/cartesian/Funnel.tsx +0 -803
- package/src/cartesian/GraphicalItemClipPath.tsx +0 -67
- package/src/cartesian/Line.tsx +0 -863
- package/src/cartesian/LineDrawShape.tsx +0 -89
- package/src/cartesian/ReferenceArea.tsx +0 -331
- package/src/cartesian/ReferenceDot.tsx +0 -304
- package/src/cartesian/ReferenceLine.tsx +0 -474
- package/src/cartesian/Scatter.tsx +0 -888
- package/src/cartesian/XAxis.tsx +0 -433
- package/src/cartesian/YAxis.tsx +0 -443
- package/src/cartesian/ZAxis.tsx +0 -155
- package/src/cartesian/cartesianPositionToCSSTranslate.tsx +0 -29
- package/src/cartesian/cartesianViewBoxToTrapezoid.tsx +0 -21
- package/src/cartesian/getCartesianPosition.tsx +0 -267
- package/src/cartesian/getEquidistantTicks.ts +0 -144
- package/src/cartesian/getTicks.ts +0 -225
- package/src/cartesian/isOutsidePosition.ts +0 -15
- package/src/cartesian/useAnimatedLineLength.ts +0 -54
- package/src/chart/AreaChart.tsx +0 -29
- package/src/chart/BarChart.tsx +0 -29
- package/src/chart/CartesianChart.tsx +0 -131
- package/src/chart/CategoricalChart.tsx +0 -94
- package/src/chart/ComposedChart.tsx +0 -29
- package/src/chart/FunnelChart.tsx +0 -29
- package/src/chart/LineChart.tsx +0 -29
- package/src/chart/PieChart.tsx +0 -50
- package/src/chart/PolarChart.tsx +0 -164
- package/src/chart/RadarChart.tsx +0 -70
- package/src/chart/RadialBarChart.tsx +0 -46
- package/src/chart/RechartsWrapper.tsx +0 -551
- package/src/chart/Sankey.tsx +0 -1534
- package/src/chart/ScatterChart.tsx +0 -29
- package/src/chart/SunburstChart.tsx +0 -504
- package/src/chart/Treemap.tsx +0 -1223
- package/src/chart/createInitialRootProps.ts +0 -24
- package/src/chart/types.ts +0 -53
- package/src/component/ActivePoints.tsx +0 -144
- package/src/component/Cell.tsx +0 -37
- package/src/component/Cursor.tsx +0 -185
- package/src/component/Customized.tsx +0 -50
- package/src/component/DefaultLegendContent.tsx +0 -348
- package/src/component/DefaultTooltipContent.tsx +0 -224
- package/src/component/Dots.tsx +0 -157
- package/src/component/Label.tsx +0 -636
- package/src/component/LabelList.tsx +0 -375
- package/src/component/Legend.tsx +0 -512
- package/src/component/ResponsiveContainer.tsx +0 -348
- package/src/component/Text.tsx +0 -541
- package/src/component/Tooltip.tsx +0 -470
- package/src/component/TooltipBoundingBox.tsx +0 -146
- package/src/component/responsiveContainerUtils.ts +0 -134
- package/src/container/ClipPathProvider.tsx +0 -51
- package/src/container/Layer.tsx +0 -38
- package/src/container/RootSurface.tsx +0 -120
- package/src/container/Surface.tsx +0 -61
- package/src/context/CellsContext.tsx +0 -54
- package/src/context/ErrorBarContext.tsx +0 -146
- package/src/context/GraphicalItemChildrenScope.tsx +0 -18
- package/src/context/PanoramaContext.tsx +0 -9
- package/src/context/RegisterGraphicalItemId.tsx +0 -30
- package/src/context/accessibilityContext.tsx +0 -6
- package/src/context/brushUpdateContext.tsx +0 -9
- package/src/context/chartDataContext.tsx +0 -97
- package/src/context/chartLayoutContext.tsx +0 -201
- package/src/context/legendPayloadContext.tsx +0 -20
- package/src/context/legendPortalContext.tsx +0 -12
- package/src/context/tooltipContext.tsx +0 -89
- package/src/context/tooltipPortalContext.tsx +0 -12
- package/src/context/useTooltipAxis.ts +0 -22
- package/src/hooks.ts +0 -476
- package/src/index.ts +0 -280
- package/src/polar/Pie.tsx +0 -1360
- package/src/polar/PolarAngleAxis.tsx +0 -616
- package/src/polar/PolarGrid.tsx +0 -312
- package/src/polar/PolarRadiusAxis.tsx +0 -547
- package/src/polar/Radar.tsx +0 -734
- package/src/polar/RadialBar.tsx +0 -917
- package/src/polar/defaultPolarAngleAxisProps.tsx +0 -27
- package/src/polar/defaultPolarRadiusAxisProps.tsx +0 -25
- package/src/shape/Cross.tsx +0 -89
- package/src/shape/Curve.tsx +0 -343
- package/src/shape/Dot.tsx +0 -70
- package/src/shape/Polygon.tsx +0 -195
- package/src/shape/Rectangle.tsx +0 -470
- package/src/shape/Sector.tsx +0 -347
- package/src/shape/Symbols.tsx +0 -139
- package/src/shape/Trapezoid.tsx +0 -280
- package/src/state/RechartsStateContext.tsx +0 -12
- package/src/state/RechartsStateProvider.tsx +0 -87
- package/src/state/RechartsStoreContext.tsx +0 -25
- package/src/state/RechartsStoreProvider.tsx +0 -35
- package/src/state/ReportChartProps.tsx +0 -40
- package/src/state/ReportEventSettings.tsx +0 -30
- package/src/state/ReportMainChartProps.tsx +0 -61
- package/src/state/ReportPolarOptions.tsx +0 -35
- package/src/state/SetGraphicalItem.ts +0 -79
- package/src/state/SetLegendPayload.ts +0 -134
- package/src/state/SetTooltipEntrySettings.tsx +0 -72
- package/src/state/actions.ts +0 -464
- package/src/state/brushSlice.ts +0 -13
- package/src/state/cartesianAxisSlice.ts +0 -141
- package/src/state/chartDataSlice.ts +0 -50
- package/src/state/chartState.ts +0 -297
- package/src/state/errorBarSlice.ts +0 -29
- package/src/state/eventSettingsSlice.ts +0 -8
- package/src/state/events.ts +0 -76
- package/src/state/externalEventsMiddleware.ts +0 -255
- package/src/state/graphicalItemsSlice.ts +0 -74
- package/src/state/hooks/useChartSelectors.tsx +0 -45
- package/src/state/keyboardEventsMiddleware.ts +0 -228
- package/src/state/layoutSlice.ts +0 -21
- package/src/state/legendSlice.ts +0 -57
- package/src/state/mouseEventsMiddleware.ts +0 -185
- package/src/state/optionsSlice.ts +0 -47
- package/src/state/polarAxisSlice.ts +0 -10
- package/src/state/polarOptionsSlice.ts +0 -12
- package/src/state/rawData.ts +0 -26
- package/src/state/referenceElementsSlice.ts +0 -40
- package/src/state/renderedTicksSlice.ts +0 -15
- package/src/state/rootPropsSlice.ts +0 -47
- package/src/state/selectors/areaSelectors.ts +0 -240
- package/src/state/selectors/arrayEqualityCheck.ts +0 -29
- package/src/state/selectors/axisSelectors.ts +0 -2157
- package/src/state/selectors/barSelectors.ts +0 -310
- package/src/state/selectors/barStackSelectors.ts +0 -77
- package/src/state/selectors/brushSelectors.ts +0 -33
- package/src/state/selectors/chartSelector.ts +0 -185
- package/src/state/selectors/combiners/combineActiveLabel.ts +0 -16
- package/src/state/selectors/combiners/combineActiveTooltipIndex.ts +0 -95
- package/src/state/selectors/combiners/combineAllBarPositions.ts +0 -122
- package/src/state/selectors/combiners/combineAxisRangeWithReverse.ts +0 -16
- package/src/state/selectors/combiners/combineBarPosition.ts +0 -23
- package/src/state/selectors/combiners/combineBarSizeList.ts +0 -80
- package/src/state/selectors/combiners/combineCheckedDomain.ts +0 -48
- package/src/state/selectors/combiners/combineConfiguredScale.ts +0 -111
- package/src/state/selectors/combiners/combineCoordinateForDefaultIndex.ts +0 -45
- package/src/state/selectors/combiners/combineDisplayedStackedData.ts +0 -50
- package/src/state/selectors/combiners/combineInverseScaleFunction.ts +0 -16
- package/src/state/selectors/combiners/combineRealScaleType.ts +0 -44
- package/src/state/selectors/combiners/combineStackedData.ts +0 -27
- package/src/state/selectors/combiners/combineTooltipInteractionState.ts +0 -86
- package/src/state/selectors/combiners/combineTooltipPayload.ts +0 -205
- package/src/state/selectors/combiners/combineTooltipPayloadConfigurations.ts +0 -58
- package/src/state/selectors/containerSelectors.ts +0 -12
- package/src/state/selectors/dataSelectors.ts +0 -88
- package/src/state/selectors/funnelSelectors.ts +0 -75
- package/src/state/selectors/graphicalItemSelectors.ts +0 -30
- package/src/state/selectors/legendSelectors.ts +0 -29
- package/src/state/selectors/lineSelectors.ts +0 -134
- package/src/state/selectors/numberDomainEqualityCheck.ts +0 -14
- package/src/state/selectors/pickAxisId.ts +0 -5
- package/src/state/selectors/pickAxisType.ts +0 -3
- package/src/state/selectors/pieSelectors.ts +0 -97
- package/src/state/selectors/polarAxisSelectors.ts +0 -201
- package/src/state/selectors/polarGridSelectors.ts +0 -28
- package/src/state/selectors/polarScaleSelectors.ts +0 -133
- package/src/state/selectors/polarSelectors.ts +0 -219
- package/src/state/selectors/radarSelectors.ts +0 -191
- package/src/state/selectors/radialBarSelectors.ts +0 -435
- package/src/state/selectors/rootPropsSelectors.ts +0 -25
- package/src/state/selectors/scatterSelectors.ts +0 -96
- package/src/state/selectors/selectActivePropsFromChartPointer.ts +0 -26
- package/src/state/selectors/selectAllAxes.ts +0 -17
- package/src/state/selectors/selectChartOffset.ts +0 -16
- package/src/state/selectors/selectChartOffsetInternal.ts +0 -136
- package/src/state/selectors/selectLegendArea.ts +0 -20
- package/src/state/selectors/selectPlotArea.ts +0 -22
- package/src/state/selectors/selectTooltipAxisId.ts +0 -7
- package/src/state/selectors/selectTooltipAxisType.ts +0 -32
- package/src/state/selectors/selectTooltipEventType.ts +0 -48
- package/src/state/selectors/selectTooltipPayloadSearcher.ts +0 -6
- package/src/state/selectors/selectTooltipSettings.ts +0 -39
- package/src/state/selectors/selectTooltipState.ts +0 -8
- package/src/state/selectors/selectors.ts +0 -271
- package/src/state/selectors/tooltipSelectors.ts +0 -578
- package/src/state/selectors/touchSelectors.ts +0 -31
- package/src/state/store.ts +0 -29
- package/src/state/storeIdentity.ts +0 -9
- package/src/state/teardownWrite.ts +0 -10
- package/src/state/tooltipInteraction.ts +0 -23
- package/src/state/tooltipSlice.ts +0 -334
- package/src/state/touchEventsMiddleware.ts +0 -214
- package/src/state/types/AnimationSettings.ts +0 -20
- package/src/state/types/AreaSettings.ts +0 -14
- package/src/state/types/BarSettings.ts +0 -15
- package/src/state/types/LineSettings.ts +0 -9
- package/src/state/types/PieSettings.ts +0 -34
- package/src/state/types/RadarSettings.ts +0 -5
- package/src/state/types/RadialBarSettings.ts +0 -10
- package/src/state/types/ScatterSettings.ts +0 -12
- package/src/state/types/StackedGraphicalItem.ts +0 -34
- package/src/state/useChartState.ts +0 -17
- package/src/state/zIndexSlice.ts +0 -39
- package/src/synchronisation/syncSelectors.ts +0 -7
- package/src/synchronisation/types.ts +0 -44
- package/src/synchronisation/useChartSynchronisation.tsx +0 -404
- package/src/theme/RechartsTheme.ts +0 -16
- package/src/theme/RechartsThemeContext.ts +0 -19
- package/src/theme/darkTheme.ts +0 -13
- package/src/theme/graphicalItemIdentity.ts +0 -70
- package/src/theme/legacyTheme.ts +0 -17
- package/src/theme/lightTheme.ts +0 -13
- package/src/types.ts +0 -54
- package/src/util/ActiveShapeUtils.tsx +0 -162
- package/src/util/BarUtils.tsx +0 -62
- package/src/util/BarePortal.tsx +0 -50
- package/src/util/CamelCaseSVGAttrs.ts +0 -34
- package/src/util/CartesianUtils.ts +0 -48
- package/src/util/ChartUtils.ts +0 -802
- package/src/util/Constants.ts +0 -42
- package/src/util/CssPrefixUtils.ts +0 -20
- package/src/util/DOMUtils.ts +0 -129
- package/src/util/DataUtils.ts +0 -216
- package/src/util/Events.ts +0 -16
- package/src/util/FunnelUtils.tsx +0 -15
- package/src/util/Global.ts +0 -12
- package/src/util/IfOverflow.ts +0 -15
- package/src/util/LRUCache.ts +0 -41
- package/src/util/LogUtils.ts +0 -22
- package/src/util/PolarUtils.ts +0 -132
- package/src/util/RadialBarUtils.tsx +0 -24
- package/src/util/ReactUtils.ts +0 -95
- package/src/util/ReduceCSSCalc.ts +0 -187
- package/src/util/ScatterUtils.tsx +0 -52
- package/src/util/ShapeElementProps.tsx +0 -87
- package/src/util/TickUtils.ts +0 -60
- package/src/util/XAxisUtils.ts +0 -48
- package/src/util/YAxisUtils.ts +0 -48
- package/src/util/axisPropsAreEqual.ts +0 -48
- package/src/util/createCartesianCharts.tsx +0 -150
- package/src/util/createEventProxy.ts +0 -20
- package/src/util/createPolarCharts.tsx +0 -112
- package/src/util/cursor/getCursorPoints.ts +0 -46
- package/src/util/cursor/getCursorRectangle.ts +0 -28
- package/src/util/cursor/getRadialCursorPoints.ts +0 -32
- package/src/util/excludeEventProps.ts +0 -171
- package/src/util/getActiveCoordinate.ts +0 -213
- package/src/util/getAxisTypeBasedOnLayout.ts +0 -21
- package/src/util/getClassNameFromUnknown.ts +0 -6
- package/src/util/getEveryNth.ts +0 -27
- package/src/util/getRadiusAndStrokeWidthFromDot.ts +0 -35
- package/src/util/getRelativeCoordinate.ts +0 -80
- package/src/util/getSliced.ts +0 -13
- package/src/util/hoverDedupe.ts +0 -41
- package/src/util/isDomainSpecifiedByUser.ts +0 -219
- package/src/util/isWellBehavedNumber.ts +0 -7
- package/src/util/pathTotalLength.ts +0 -25
- package/src/util/payload/getUniqPayload.ts +0 -28
- package/src/util/propsAreEqual.ts +0 -121
- package/src/util/resolveDefaultProps.ts +0 -161
- package/src/util/round.ts +0 -32
- package/src/util/scale/CartesianScaleHelper.ts +0 -72
- package/src/util/scale/CustomScaleDefinition.ts +0 -81
- package/src/util/scale/RechartsScale.ts +0 -130
- package/src/util/scale/createCategoricalInverse.ts +0 -72
- package/src/util/scale/getNiceTickValues.ts +0 -311
- package/src/util/scale/index.ts +0 -2
- package/src/util/scale/util/arithmetic.ts +0 -54
- package/src/util/solid-1-compat.ts +0 -310
- package/src/util/solidJsxCamelAugment.d.ts +0 -84
- package/src/util/stacks/getStackSeriesIdentifier.ts +0 -21
- package/src/util/stacks/stackTypes.ts +0 -60
- package/src/util/structurallyEqual.ts +0 -31
- package/src/util/svgPropertiesAndEvents.ts +0 -53
- package/src/util/svgPropertiesNoEvents.ts +0 -571
- package/src/util/tooltip/translate.ts +0 -171
- package/src/util/typedDataKey.ts +0 -48
- package/src/util/types.ts +0 -1560
- package/src/util/useAnimationId.ts +0 -31
- package/src/util/useElementOffset.ts +0 -110
- package/src/util/useId.ts +0 -8
- package/src/util/usePrefersReducedMotion.ts +0 -48
- package/src/util/useReportScale.ts +0 -24
- package/src/util/useUniqueId.ts +0 -30
- package/src/zIndex/DefaultZIndexes.ts +0 -84
- package/src/zIndex/ZIndexLayer.tsx +0 -121
- package/src/zIndex/ZIndexPortal.tsx +0 -79
- package/src/zIndex/getZIndexFromUnknown.ts +0 -14
- package/src/zIndex/zIndexSelectors.ts +0 -48
package/src/chart/Sankey.tsx
DELETED
|
@@ -1,1534 +0,0 @@
|
|
|
1
|
-
/* eslint-disable import/no-cycle, sort-keys */
|
|
2
|
-
import { createMemo, For, Show, untrack } from 'solid-js';
|
|
3
|
-
import type { WithoutRemoveFalse } from "../util/types"
|
|
4
|
-
import type { JSX } from '@solidjs/web';
|
|
5
|
-
import maxBy from "es-toolkit/compat/maxBy"
|
|
6
|
-
import sumBy from "es-toolkit/compat/sumBy"
|
|
7
|
-
import get from "es-toolkit/compat/get"
|
|
8
|
-
import { Surface } from "../container/Surface"
|
|
9
|
-
import { Layer } from "../container/Layer"
|
|
10
|
-
import type { Props as RectangleProps } from "../shape/Rectangle"
|
|
11
|
-
import { Rectangle } from "../shape/Rectangle"
|
|
12
|
-
import { getValueByDataKey } from "../util/ChartUtils"
|
|
13
|
-
import type {
|
|
14
|
-
Coordinate,
|
|
15
|
-
DataKey,
|
|
16
|
-
EventThrottlingProps,
|
|
17
|
-
Margin,
|
|
18
|
-
Percent,
|
|
19
|
-
SankeyLink,
|
|
20
|
-
SankeyNode,
|
|
21
|
-
} from "../util/types"
|
|
22
|
-
import {
|
|
23
|
-
ReportChartMargin,
|
|
24
|
-
ReportChartSize,
|
|
25
|
-
useChartHeight,
|
|
26
|
-
useChartWidth,
|
|
27
|
-
} from "../context/chartLayoutContext"
|
|
28
|
-
import { RechartsWrapper } from "./RechartsWrapper"
|
|
29
|
-
import { RechartsStateProvider } from "../state/RechartsStateProvider"
|
|
30
|
-
import { createInitialLayoutState } from "../state/chartState"
|
|
31
|
-
import { useChartStore } from "../state/RechartsStoreContext"
|
|
32
|
-
import { useOptionalChartState } from "../state/useChartState"
|
|
33
|
-
import type {
|
|
34
|
-
TooltipIndex,
|
|
35
|
-
TooltipPayloadConfiguration,
|
|
36
|
-
TooltipPayloadSearcher,
|
|
37
|
-
} from "../state/tooltipSlice"
|
|
38
|
-
import { SetTooltipEntrySettings } from "../state/SetTooltipEntrySettings"
|
|
39
|
-
import type { ChartOptions } from "../state/optionsSlice"
|
|
40
|
-
import { ReportEventSettings } from "../state/ReportEventSettings"
|
|
41
|
-
import { SetComputedData } from "../context/chartDataContext"
|
|
42
|
-
import {
|
|
43
|
-
svgPropertiesNoEvents,
|
|
44
|
-
svgPropertiesNoEventsFromUnknown,
|
|
45
|
-
} from "../util/svgPropertiesNoEvents"
|
|
46
|
-
import type { RequiresDefaultProps } from "../util/resolveDefaultProps"
|
|
47
|
-
import { resolveDefaultProps } from "../util/resolveDefaultProps"
|
|
48
|
-
import { isPositiveNumber } from "../util/isWellBehavedNumber"
|
|
49
|
-
import { isNotNil, noop } from "../util/DataUtils"
|
|
50
|
-
import type { WithIdRequired } from "../util/useUniqueId"
|
|
51
|
-
import { RegisterGraphicalItemId } from "../context/RegisterGraphicalItemId"
|
|
52
|
-
import type { GraphicalItemId } from "../state/graphicalItemsSlice"
|
|
53
|
-
import { initialEventSettingsState } from "../state/eventSettingsSlice"
|
|
54
|
-
|
|
55
|
-
import { splitProps } from '../util/solid-1-compat';
|
|
56
|
-
import { setTooltipInteraction } from "../state/tooltipInteraction"
|
|
57
|
-
const interpolationGenerator = (a: number, b: number) => {
|
|
58
|
-
const ka = +a
|
|
59
|
-
const kb = b - ka
|
|
60
|
-
return (t: number) => ka + kb * t
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const centerY = (node: SankeyNode) => node.y + node.dy / 2
|
|
64
|
-
|
|
65
|
-
const cubicValue = (start: number, control1: number, control2: number, end: number, t: number): number => {
|
|
66
|
-
const inverseT = 1 - t
|
|
67
|
-
return inverseT ** 3 * start + 3 * inverseT ** 2 * t * control1 + 3 * inverseT * t ** 2 * control2 + t ** 3 * end
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/* TODO why is this not reading dataKey? */
|
|
71
|
-
const getValue = (entry: LinkDataItem | SankeyNode | undefined): number =>
|
|
72
|
-
(entry && entry.value) || 0
|
|
73
|
-
|
|
74
|
-
const getSumOfIds = (links: ReadonlyArray<LinkDataItem>, ids: number[]): number =>
|
|
75
|
-
ids.reduce((result, id) => result + getValue(links[id]), 0)
|
|
76
|
-
|
|
77
|
-
const getSumWithWeightedSource = (
|
|
78
|
-
tree: ReadonlyArray<SankeyNode>,
|
|
79
|
-
links: ReadonlyArray<LinkDataItemDy>,
|
|
80
|
-
ids: number[],
|
|
81
|
-
) =>
|
|
82
|
-
ids.reduce((result, id) => {
|
|
83
|
-
const link = links[id]
|
|
84
|
-
if (link == null) {
|
|
85
|
-
return result
|
|
86
|
-
}
|
|
87
|
-
const sourceNode = tree[link.source]
|
|
88
|
-
if (sourceNode == null) {
|
|
89
|
-
return result
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return result + centerY(sourceNode) * getValue(links[id])
|
|
93
|
-
}, 0)
|
|
94
|
-
|
|
95
|
-
const getSumWithWeightedTarget = (
|
|
96
|
-
tree: ReadonlyArray<SankeyNode>,
|
|
97
|
-
links: ReadonlyArray<LinkDataItemDy>,
|
|
98
|
-
ids: ReadonlyArray<number>,
|
|
99
|
-
): number =>
|
|
100
|
-
ids.reduce((result: number, id: number) => {
|
|
101
|
-
const link = links[id]
|
|
102
|
-
if (link == null) {
|
|
103
|
-
return result
|
|
104
|
-
}
|
|
105
|
-
const targetNode = tree[link.target]
|
|
106
|
-
if (targetNode == null) {
|
|
107
|
-
return result
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return result + centerY(targetNode) * getValue(links[id])
|
|
111
|
-
}, 0)
|
|
112
|
-
|
|
113
|
-
const ascendingY = (a: { y: number }, b: { y: number }) => a.y - b.y
|
|
114
|
-
|
|
115
|
-
const searchTargetsAndSources = (links: LinkDataItem[], id: number) => {
|
|
116
|
-
const sourceNodes: number[] = []
|
|
117
|
-
const sourceLinks: number[] = []
|
|
118
|
-
const targetNodes: number[] = []
|
|
119
|
-
const targetLinks: number[] = []
|
|
120
|
-
|
|
121
|
-
for (let i = 0, len = links.length; i < len; i++) {
|
|
122
|
-
const link = links[i]
|
|
123
|
-
|
|
124
|
-
if (link?.source === id) {
|
|
125
|
-
targetNodes.push(link.target)
|
|
126
|
-
targetLinks.push(i)
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
if (link?.target === id) {
|
|
130
|
-
sourceNodes.push(link.source)
|
|
131
|
-
sourceLinks.push(i)
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
return { sourceLinks, sourceNodes, targetLinks, targetNodes }
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
const updateDepthOfTargets = (tree: SankeyNode[], curNode: SankeyNode) => {
|
|
139
|
-
const { targetNodes } = curNode
|
|
140
|
-
|
|
141
|
-
for (let i = 0, len = targetNodes.length; i < len; i++) {
|
|
142
|
-
const targetNode = targetNodes[i]
|
|
143
|
-
if (targetNode == null) {
|
|
144
|
-
continue
|
|
145
|
-
}
|
|
146
|
-
const target = tree[targetNode]
|
|
147
|
-
|
|
148
|
-
if (target) {
|
|
149
|
-
const newDepth = curNode.depth + 1
|
|
150
|
-
/*
|
|
151
|
-
* Only recurse when the depth grows. Depth is the longest path to a node, so once it stops increasing
|
|
152
|
-
* the subtree is already up to date; without this guard every path through the graph is walked
|
|
153
|
-
* separately, which explodes combinatorially on dense graphs.
|
|
154
|
-
*/
|
|
155
|
-
if (newDepth > target.depth) {
|
|
156
|
-
target.depth = newDepth
|
|
157
|
-
updateDepthOfTargets(tree, target)
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
const getNodesTree = (
|
|
164
|
-
{ nodes, links }: SankeyData,
|
|
165
|
-
width: number,
|
|
166
|
-
nodeWidth: number,
|
|
167
|
-
align: "left" | "justify",
|
|
168
|
-
): { tree: SankeyNode[]; maxDepth: number } => {
|
|
169
|
-
const tree: SankeyNode[] = nodes.map((entry: Record<string, unknown>, index: number) => {
|
|
170
|
-
const result = searchTargetsAndSources(links, index)
|
|
171
|
-
|
|
172
|
-
return {
|
|
173
|
-
...entry,
|
|
174
|
-
...result,
|
|
175
|
-
depth: 0,
|
|
176
|
-
value: Math.max(
|
|
177
|
-
getSumOfIds(links, result.sourceLinks),
|
|
178
|
-
getSumOfIds(links, result.targetLinks),
|
|
179
|
-
),
|
|
180
|
-
} as SankeyNode
|
|
181
|
-
})
|
|
182
|
-
|
|
183
|
-
for (let i = 0, len = tree.length; i < len; i++) {
|
|
184
|
-
const node = tree[i]
|
|
185
|
-
|
|
186
|
-
if (node != null && node.sourceNodes.length === 0) {
|
|
187
|
-
updateDepthOfTargets(tree, node)
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
const maxDepth = maxBy(tree, (entry: SankeyNode) => entry.depth)?.depth ?? 0
|
|
191
|
-
|
|
192
|
-
if (maxDepth >= 1) {
|
|
193
|
-
const childWidth = (width - nodeWidth) / maxDepth
|
|
194
|
-
for (let i = 0, len = tree.length; i < len; i++) {
|
|
195
|
-
const node = tree[i]
|
|
196
|
-
if (node == null) {
|
|
197
|
-
continue
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
if (node.targetNodes.length === 0) {
|
|
201
|
-
if (align === "justify") {
|
|
202
|
-
node.depth = maxDepth
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
node.x = node.depth * childWidth
|
|
206
|
-
node.dx = nodeWidth
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
return { maxDepth, tree }
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
const getDepthTree = (tree: SankeyNode[]): SankeyNode[][] => {
|
|
214
|
-
const result: SankeyNode[][] = []
|
|
215
|
-
|
|
216
|
-
for (let i = 0, len = tree.length; i < len; i++) {
|
|
217
|
-
const node = tree[i]
|
|
218
|
-
if (node == null) {
|
|
219
|
-
continue
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
if (result[node.depth] == null) {
|
|
223
|
-
result[node.depth] = []
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
result[node.depth]?.push(node)
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
return result
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
type LinkDataItemDy = LinkDataItem & { dy: number; sy?: number; ty?: number }
|
|
233
|
-
|
|
234
|
-
type SankeyVerticalAlign = "justify" | "top"
|
|
235
|
-
|
|
236
|
-
const updateYOfTree = (
|
|
237
|
-
depthTree: SankeyNode[][],
|
|
238
|
-
height: number,
|
|
239
|
-
nodePadding: number,
|
|
240
|
-
links: ReadonlyArray<LinkDataItem>,
|
|
241
|
-
verticalAlign: SankeyVerticalAlign,
|
|
242
|
-
): Array<LinkDataItemDy> => {
|
|
243
|
-
let yRatio: number = Math.min(
|
|
244
|
-
...depthTree.map((nodes) => {
|
|
245
|
-
const value = sumBy(nodes, getValue)
|
|
246
|
-
return value === 0 ? Infinity : (height - (nodes.length - 1) * nodePadding) / value
|
|
247
|
-
}),
|
|
248
|
-
)
|
|
249
|
-
if (yRatio === Infinity) {
|
|
250
|
-
yRatio = 0
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
for (let d = 0, maxDepth = depthTree.length; d < maxDepth; d++) {
|
|
254
|
-
const nodes = depthTree[d]
|
|
255
|
-
if (nodes == null) {
|
|
256
|
-
continue
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
if (verticalAlign === "top") {
|
|
260
|
-
let currentY = 0
|
|
261
|
-
for (let i = 0, len = nodes.length; i < len; i++) {
|
|
262
|
-
const node = nodes[i]
|
|
263
|
-
if (node == null) {
|
|
264
|
-
continue
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
node.dy = node.value * yRatio
|
|
268
|
-
node.y = currentY
|
|
269
|
-
currentY += node.dy + nodePadding
|
|
270
|
-
}
|
|
271
|
-
} else {
|
|
272
|
-
for (let i = 0, len = nodes.length; i < len; i++) {
|
|
273
|
-
const node = nodes[i]
|
|
274
|
-
if (node == null) {
|
|
275
|
-
continue
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
node.y = i
|
|
279
|
-
node.dy = node.value * yRatio
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
return links.map(
|
|
285
|
-
(link: LinkDataItem): LinkDataItemDy => ({ ...link, dy: getValue(link) * yRatio }),
|
|
286
|
-
)
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
const resolveCollisions = (
|
|
290
|
-
depthTree: SankeyNode[][],
|
|
291
|
-
height: number,
|
|
292
|
-
nodePadding: number,
|
|
293
|
-
sort = true,
|
|
294
|
-
) => {
|
|
295
|
-
for (let i = 0, len = depthTree.length; i < len; i++) {
|
|
296
|
-
const nodes = depthTree[i]
|
|
297
|
-
if (nodes == null) {
|
|
298
|
-
continue
|
|
299
|
-
}
|
|
300
|
-
const n = nodes.length
|
|
301
|
-
|
|
302
|
-
/* Sort by the value of y */
|
|
303
|
-
if (sort) {
|
|
304
|
-
nodes.sort(ascendingY)
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
let y0 = 0
|
|
308
|
-
for (let j = 0; j < n; j++) {
|
|
309
|
-
const node = nodes[j]
|
|
310
|
-
if (node == null) {
|
|
311
|
-
continue
|
|
312
|
-
}
|
|
313
|
-
const dy = y0 - node.y
|
|
314
|
-
|
|
315
|
-
if (dy > 0) {
|
|
316
|
-
node.y += dy
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
y0 = node.y + node.dy + nodePadding
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
y0 = height + nodePadding
|
|
323
|
-
for (let j = n - 1; j >= 0; j--) {
|
|
324
|
-
const node = nodes[j]
|
|
325
|
-
if (node == null) {
|
|
326
|
-
continue
|
|
327
|
-
}
|
|
328
|
-
const dy = node.y + node.dy + nodePadding - y0
|
|
329
|
-
|
|
330
|
-
if (dy > 0) {
|
|
331
|
-
node.y -= dy
|
|
332
|
-
y0 = node.y
|
|
333
|
-
} else {
|
|
334
|
-
break
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
const relaxLeftToRight = (
|
|
341
|
-
tree: ReadonlyArray<SankeyNode>,
|
|
342
|
-
depthTree: SankeyNode[][],
|
|
343
|
-
links: ReadonlyArray<LinkDataItemDy>,
|
|
344
|
-
alpha: number,
|
|
345
|
-
) => {
|
|
346
|
-
for (let i = 0, maxDepth = depthTree.length; i < maxDepth; i++) {
|
|
347
|
-
const nodes = depthTree[i]
|
|
348
|
-
if (nodes == null) {
|
|
349
|
-
continue
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
for (let j = 0, len = nodes.length; j < len; j++) {
|
|
353
|
-
const node = nodes[j]
|
|
354
|
-
if (node == null) {
|
|
355
|
-
continue
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
if (node.sourceLinks.length) {
|
|
359
|
-
const sourceSum = getSumOfIds(links, node.sourceLinks)
|
|
360
|
-
const weightedSum = getSumWithWeightedSource(tree, links, node.sourceLinks)
|
|
361
|
-
const y = sourceSum === 0 ? centerY(node) : weightedSum / sourceSum
|
|
362
|
-
|
|
363
|
-
node.y += (y - centerY(node)) * alpha
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
const relaxRightToLeft = (
|
|
370
|
-
tree: ReadonlyArray<SankeyNode>,
|
|
371
|
-
/*
|
|
372
|
-
* depthTree array is modified by this method!
|
|
373
|
-
*/
|
|
374
|
-
depthTree: SankeyNode[][],
|
|
375
|
-
links: ReadonlyArray<LinkDataItemDy>,
|
|
376
|
-
alpha: number,
|
|
377
|
-
) => {
|
|
378
|
-
for (let i = depthTree.length - 1; i >= 0; i--) {
|
|
379
|
-
const nodes = depthTree[i]
|
|
380
|
-
if (nodes == null) {
|
|
381
|
-
continue
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
for (let j = 0, len = nodes.length; j < len; j++) {
|
|
385
|
-
const node = nodes[j]
|
|
386
|
-
if (node == null) {
|
|
387
|
-
continue
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
if (node.targetLinks.length) {
|
|
391
|
-
const targetSum = getSumOfIds(links, node.targetLinks)
|
|
392
|
-
const weightedSum = getSumWithWeightedTarget(tree, links, node.targetLinks)
|
|
393
|
-
const y = targetSum === 0 ? centerY(node) : weightedSum / targetSum
|
|
394
|
-
|
|
395
|
-
node.y += (y - centerY(node)) * alpha
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
const updateYOfLinks = (tree: SankeyNode[], links: LinkDataItemDy[]): void => {
|
|
402
|
-
for (let i = 0, len = tree.length; i < len; i++) {
|
|
403
|
-
const node = tree[i]
|
|
404
|
-
if (node == null) {
|
|
405
|
-
continue
|
|
406
|
-
}
|
|
407
|
-
let sy = 0
|
|
408
|
-
let ty = 0
|
|
409
|
-
|
|
410
|
-
node.targetLinks.sort((a, b) => {
|
|
411
|
-
const targetA = links[a]?.target
|
|
412
|
-
const targetB = links[b]?.target
|
|
413
|
-
if (targetA == null || targetB == null) {
|
|
414
|
-
return 0
|
|
415
|
-
}
|
|
416
|
-
const yA = tree[targetA]?.y
|
|
417
|
-
const yB = tree[targetB]?.y
|
|
418
|
-
if (yA == null || yB == null) {
|
|
419
|
-
return 0
|
|
420
|
-
}
|
|
421
|
-
return yA - yB
|
|
422
|
-
})
|
|
423
|
-
node.sourceLinks.sort((a, b) => {
|
|
424
|
-
const sourceA = links[a]?.source
|
|
425
|
-
const sourceB = links[b]?.source
|
|
426
|
-
if (sourceA == null || sourceB == null) {
|
|
427
|
-
return 0
|
|
428
|
-
}
|
|
429
|
-
const yA = tree[sourceA]?.y
|
|
430
|
-
const yB = tree[sourceB]?.y
|
|
431
|
-
if (yA == null || yB == null) {
|
|
432
|
-
return 0
|
|
433
|
-
}
|
|
434
|
-
return yA - yB
|
|
435
|
-
})
|
|
436
|
-
|
|
437
|
-
for (let j = 0, tLen = node.targetLinks.length; j < tLen; j++) {
|
|
438
|
-
const targetLink = node.targetLinks[j]
|
|
439
|
-
if (targetLink == null) {
|
|
440
|
-
continue
|
|
441
|
-
}
|
|
442
|
-
const link = links[targetLink]
|
|
443
|
-
|
|
444
|
-
if (link) {
|
|
445
|
-
link.sy = sy
|
|
446
|
-
sy += link.dy
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
for (let j = 0, sLen = node.sourceLinks.length; j < sLen; j++) {
|
|
451
|
-
const sourceLink = node.sourceLinks[j]
|
|
452
|
-
if (sourceLink == null) {
|
|
453
|
-
continue
|
|
454
|
-
}
|
|
455
|
-
const link = links[sourceLink]
|
|
456
|
-
|
|
457
|
-
if (link) {
|
|
458
|
-
link.ty = ty
|
|
459
|
-
ty += link.dy
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
const getLinkYAtX = (sourceNode: SankeyNode, targetNode: SankeyNode, link: LinkDataItemDy, x: number): number => {
|
|
466
|
-
const sourceX = sourceNode.x + sourceNode.dx
|
|
467
|
-
const targetX = targetNode.x
|
|
468
|
-
const progress = targetX === sourceX ? 0 : (x - sourceX) / (targetX - sourceX)
|
|
469
|
-
const boundedProgress = Math.min(Math.max(progress, 0), 1)
|
|
470
|
-
const sourceY = sourceNode.y + (link.sy ?? 0) + link.dy / 2
|
|
471
|
-
const targetY = targetNode.y + (link.ty ?? 0) + link.dy / 2
|
|
472
|
-
|
|
473
|
-
return cubicValue(sourceY, sourceY, targetY, targetY, boundedProgress)
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
const resolveNodeLinkCollisions = (
|
|
477
|
-
tree: SankeyNode[],
|
|
478
|
-
depthTree: SankeyNode[][],
|
|
479
|
-
links: LinkDataItemDy[],
|
|
480
|
-
height: number,
|
|
481
|
-
nodePadding: number,
|
|
482
|
-
) => {
|
|
483
|
-
const depthByNode = new Map<SankeyNode, number>()
|
|
484
|
-
|
|
485
|
-
for (let depth = 0; depth < depthTree.length; depth++) {
|
|
486
|
-
const nodes = depthTree[depth]
|
|
487
|
-
if (nodes == null) {
|
|
488
|
-
continue
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
for (const node of nodes) {
|
|
492
|
-
depthByNode.set(node, depth)
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
for (let depth = 0; depth < depthTree.length; depth++) {
|
|
497
|
-
const nodes = depthTree[depth]
|
|
498
|
-
if (nodes == null || nodes.length === 0) {
|
|
499
|
-
continue
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
const depthX = nodes[0] == null ? undefined : nodes[0].x + nodes[0].dx / 2
|
|
503
|
-
if (depthX == null) {
|
|
504
|
-
continue
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
const fixedObstacles = links.flatMap(link => {
|
|
508
|
-
const sourceNode = tree[link.source]
|
|
509
|
-
const targetNode = tree[link.target]
|
|
510
|
-
if (sourceNode == null || targetNode == null) {
|
|
511
|
-
return []
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
const sourceDepth = depthByNode.get(sourceNode)
|
|
515
|
-
const targetDepth = depthByNode.get(targetNode)
|
|
516
|
-
if (sourceDepth == null || targetDepth == null) {
|
|
517
|
-
return []
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
if (depth <= Math.min(sourceDepth, targetDepth) || depth >= Math.max(sourceDepth, targetDepth)) {
|
|
521
|
-
return []
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
const y = getLinkYAtX(sourceNode, targetNode, link, depthX) - link.dy / 2
|
|
525
|
-
return [{ y, dy: link.dy, fixed: true as const }]
|
|
526
|
-
})
|
|
527
|
-
|
|
528
|
-
const containedNodeObstacles = fixedObstacles.filter(obstacle =>
|
|
529
|
-
nodes.some(node => node.y >= obstacle.y && node.y + node.dy <= obstacle.y + obstacle.dy),
|
|
530
|
-
)
|
|
531
|
-
|
|
532
|
-
if (containedNodeObstacles.length === 0) {
|
|
533
|
-
continue
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
type CollisionItem = { node: SankeyNode; fixed: false } | { y: number; dy: number; fixed: true }
|
|
537
|
-
const getItemY = (item: CollisionItem): number => (item.fixed ? item.y : item.node.y)
|
|
538
|
-
const getItemHeight = (item: CollisionItem): number => (item.fixed ? item.dy : item.node.dy)
|
|
539
|
-
let items: CollisionItem[] = [
|
|
540
|
-
...nodes.map(node => ({ node, fixed: false as const })),
|
|
541
|
-
...containedNodeObstacles,
|
|
542
|
-
].sort((a, b) => getItemY(a) - getItemY(b))
|
|
543
|
-
|
|
544
|
-
let nextY = 0
|
|
545
|
-
for (const item of items) {
|
|
546
|
-
if (item.fixed) {
|
|
547
|
-
nextY = Math.max(nextY, item.y + item.dy + nodePadding)
|
|
548
|
-
continue
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
if (item.node.y < nextY) {
|
|
552
|
-
item.node.y = nextY
|
|
553
|
-
}
|
|
554
|
-
nextY = item.node.y + item.node.dy + nodePadding
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
items = items.sort((a, b) => getItemY(a) - getItemY(b))
|
|
558
|
-
|
|
559
|
-
let previousY = height + nodePadding
|
|
560
|
-
for (let i = items.length - 1; i >= 0; i--) {
|
|
561
|
-
const item = items[i]
|
|
562
|
-
if (item == null) {
|
|
563
|
-
continue
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
if (item.fixed) {
|
|
567
|
-
previousY = Math.min(previousY, item.y - nodePadding)
|
|
568
|
-
continue
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
/* This backward pass only keeps moved nodes within the chart bounds.
|
|
572
|
-
It intentionally does not iterate again against fixed obstacles above,
|
|
573
|
-
because this fix is scoped to the fully-contained skipped-depth case. */
|
|
574
|
-
const dy = item.node.y + getItemHeight(item) + nodePadding - previousY
|
|
575
|
-
if (dy > 0) {
|
|
576
|
-
item.node.y -= dy
|
|
577
|
-
}
|
|
578
|
-
previousY = item.node.y
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
export const computeData = ({
|
|
584
|
-
data,
|
|
585
|
-
width,
|
|
586
|
-
height,
|
|
587
|
-
iterations,
|
|
588
|
-
nodeWidth,
|
|
589
|
-
nodePadding,
|
|
590
|
-
sort,
|
|
591
|
-
verticalAlign,
|
|
592
|
-
align,
|
|
593
|
-
}: {
|
|
594
|
-
data: SankeyData
|
|
595
|
-
width: number
|
|
596
|
-
height: number
|
|
597
|
-
iterations: number
|
|
598
|
-
nodeWidth: number
|
|
599
|
-
nodePadding: number
|
|
600
|
-
sort: boolean
|
|
601
|
-
verticalAlign: SankeyVerticalAlign
|
|
602
|
-
align: "left" | "justify"
|
|
603
|
-
}): {
|
|
604
|
-
nodes: ReadonlyArray<SankeyNode>
|
|
605
|
-
links: ReadonlyArray<SankeyLink>
|
|
606
|
-
} => {
|
|
607
|
-
const { links } = data
|
|
608
|
-
const { tree } = getNodesTree(data, width, nodeWidth, align)
|
|
609
|
-
const depthTree = getDepthTree(tree)
|
|
610
|
-
const linksWithDy: Array<LinkDataItemDy> = updateYOfTree(
|
|
611
|
-
depthTree,
|
|
612
|
-
height,
|
|
613
|
-
nodePadding,
|
|
614
|
-
links,
|
|
615
|
-
verticalAlign,
|
|
616
|
-
)
|
|
617
|
-
|
|
618
|
-
resolveCollisions(depthTree, height, nodePadding, sort)
|
|
619
|
-
|
|
620
|
-
if (verticalAlign === "justify") {
|
|
621
|
-
let alpha = 1
|
|
622
|
-
for (let i = 1; i <= iterations; i++) {
|
|
623
|
-
relaxRightToLeft(tree, depthTree, linksWithDy, (alpha *= 0.99))
|
|
624
|
-
|
|
625
|
-
resolveCollisions(depthTree, height, nodePadding, sort)
|
|
626
|
-
|
|
627
|
-
relaxLeftToRight(tree, depthTree, linksWithDy, alpha)
|
|
628
|
-
|
|
629
|
-
resolveCollisions(depthTree, height, nodePadding, sort)
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
updateYOfLinks(tree, linksWithDy)
|
|
634
|
-
resolveNodeLinkCollisions(tree, depthTree, linksWithDy, height, nodePadding)
|
|
635
|
-
updateYOfLinks(tree, linksWithDy)
|
|
636
|
-
|
|
637
|
-
/* updateYOfLinks modifies the links array to add sy and ty in place */
|
|
638
|
-
const newLinks: ReadonlyArray<SankeyLink> = linksWithDy as unknown as ReadonlyArray<SankeyLink>
|
|
639
|
-
|
|
640
|
-
return { links: newLinks, nodes: tree }
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
const getNodeCoordinateOfTooltip = (item: NodeProps) => {
|
|
644
|
-
return { x: +item.x + +item.width / 2, y: +item.y + +item.height / 2 }
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
const getLinkCoordinateOfTooltip = (item: LinkProps): Coordinate | undefined => {
|
|
648
|
-
return "sourceX" in item
|
|
649
|
-
? {
|
|
650
|
-
x: (item.sourceX + item.targetX) / 2,
|
|
651
|
-
y: (item.sourceY + item.targetY) / 2,
|
|
652
|
-
}
|
|
653
|
-
: undefined
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
type SankeyTooltipPayload = { payload: SankeyNode | SankeyLink; name: unknown; value: unknown }
|
|
657
|
-
|
|
658
|
-
const getPayloadOfTooltip = (
|
|
659
|
-
item: { payload: SankeyNode | SankeyLink },
|
|
660
|
-
type: SankeyElementType,
|
|
661
|
-
nameKey: DataKey<SankeyLink | SankeyNode, string> | undefined,
|
|
662
|
-
): SankeyTooltipPayload | undefined => {
|
|
663
|
-
const { payload } = item
|
|
664
|
-
if (type === "node") {
|
|
665
|
-
return {
|
|
666
|
-
name: getValueByDataKey(payload, nameKey, ""),
|
|
667
|
-
payload,
|
|
668
|
-
value: getValueByDataKey(payload, "value"),
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
if ("source" in payload && payload.source && payload.target) {
|
|
672
|
-
const sourceObj = typeof payload.source === "object" ? (payload.source as SankeyNode) : null
|
|
673
|
-
const targetObj = typeof payload.target === "object" ? (payload.target as SankeyNode) : null
|
|
674
|
-
const sourceName = sourceObj ? getValueByDataKey(sourceObj, nameKey, "") : ""
|
|
675
|
-
const targetName = targetObj ? getValueByDataKey(targetObj, nameKey, "") : ""
|
|
676
|
-
|
|
677
|
-
return {
|
|
678
|
-
name: `${sourceName} - ${targetName}`,
|
|
679
|
-
payload,
|
|
680
|
-
value: getValueByDataKey(payload, "value"),
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
|
|
684
|
-
return undefined
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
export const sankeyPayloadSearcher: TooltipPayloadSearcher = (
|
|
688
|
-
_: unknown,
|
|
689
|
-
activeIndex: TooltipIndex,
|
|
690
|
-
computedData?: unknown,
|
|
691
|
-
nameKey?,
|
|
692
|
-
): SankeyTooltipPayload | undefined => {
|
|
693
|
-
if (activeIndex == null || typeof activeIndex !== "string") {
|
|
694
|
-
return undefined
|
|
695
|
-
}
|
|
696
|
-
if (computedData == null || typeof computedData !== "object") {
|
|
697
|
-
return undefined
|
|
698
|
-
}
|
|
699
|
-
const splitIndex = activeIndex.split("-")
|
|
700
|
-
const [targetType, index] = splitIndex
|
|
701
|
-
const item = get(computedData, `${targetType}s[${index}]`)
|
|
702
|
-
if (item) {
|
|
703
|
-
const payload = getPayloadOfTooltip(
|
|
704
|
-
item as { payload: SankeyNode | SankeyLink },
|
|
705
|
-
targetType as SankeyElementType,
|
|
706
|
-
nameKey as DataKey<SankeyLink | SankeyNode, string> | undefined,
|
|
707
|
-
)
|
|
708
|
-
return payload
|
|
709
|
-
}
|
|
710
|
-
return undefined
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
const options: ChartOptions = {
|
|
714
|
-
chartName: "Sankey",
|
|
715
|
-
defaultTooltipEventType: "item",
|
|
716
|
-
eventEmitter: undefined,
|
|
717
|
-
tooltipPayloadSearcher: sankeyPayloadSearcher,
|
|
718
|
-
validateTooltipEventTypes: ["item"],
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
function SetSankeyTooltipEntrySettings(props: {
|
|
722
|
-
dataKey: DataKey<unknown> | undefined
|
|
723
|
-
nameKey: DataKey<unknown> | undefined
|
|
724
|
-
stroke: string | undefined
|
|
725
|
-
strokeWidth: number | string | undefined
|
|
726
|
-
fill: string | undefined
|
|
727
|
-
name: string | number | undefined
|
|
728
|
-
data: SankeyData
|
|
729
|
-
id: GraphicalItemId
|
|
730
|
-
}): JSX.Element {
|
|
731
|
-
/* GOTCHA-005: createMemo so reactive props flow into the settings object. */
|
|
732
|
-
const tooltipEntrySettings = createMemo<TooltipPayloadConfiguration>(() => ({
|
|
733
|
-
dataDefinedOnItem: props.data,
|
|
734
|
-
getPosition: noop,
|
|
735
|
-
settings: {
|
|
736
|
-
color: props.fill,
|
|
737
|
-
dataKey: props.dataKey,
|
|
738
|
-
fill: props.fill,
|
|
739
|
-
graphicalItemId: props.id,
|
|
740
|
-
hide: false,
|
|
741
|
-
name: props.name,
|
|
742
|
-
nameKey: props.nameKey,
|
|
743
|
-
stroke: props.stroke,
|
|
744
|
-
strokeWidth: props.strokeWidth,
|
|
745
|
-
type: undefined,
|
|
746
|
-
unit: "",
|
|
747
|
-
},
|
|
748
|
-
}))
|
|
749
|
-
return <SetTooltipEntrySettings tooltipEntrySettings={tooltipEntrySettings()} />
|
|
750
|
-
}
|
|
751
|
-
|
|
752
|
-
interface LinkDataItem {
|
|
753
|
-
source: number
|
|
754
|
-
target: number
|
|
755
|
-
value: number
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
export interface NodeProps {
|
|
759
|
-
height: number
|
|
760
|
-
width: number
|
|
761
|
-
payload: SankeyNode
|
|
762
|
-
index: number
|
|
763
|
-
x: number
|
|
764
|
-
y: number
|
|
765
|
-
[key: string]: unknown
|
|
766
|
-
}
|
|
767
|
-
|
|
768
|
-
export interface LinkProps {
|
|
769
|
-
sourceX: number
|
|
770
|
-
targetX: number
|
|
771
|
-
sourceY: number
|
|
772
|
-
targetY: number
|
|
773
|
-
sourceControlX: number
|
|
774
|
-
targetControlX: number
|
|
775
|
-
sourceRelativeY: number
|
|
776
|
-
targetRelativeY: number
|
|
777
|
-
linkWidth: number
|
|
778
|
-
index: number
|
|
779
|
-
/** payload is SankeyLink except source and target are now Node objects instead of numbers */
|
|
780
|
-
payload: Omit<SankeyLink, "source" | "target"> & { source: SankeyNode; target: SankeyNode }
|
|
781
|
-
[key: string]: unknown
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
export interface SankeyData {
|
|
785
|
-
nodes: Record<string, unknown>[]
|
|
786
|
-
links: LinkDataItem[]
|
|
787
|
-
}
|
|
788
|
-
|
|
789
|
-
export type SankeyNodeOptions = ((props: NodeProps) => JSX.Element) | RectangleProps
|
|
790
|
-
|
|
791
|
-
type SankeyLinkOptions = ((props: LinkProps) => JSX.Element) | JSX.PathSVGAttributes<SVGPathElement>
|
|
792
|
-
|
|
793
|
-
interface SankeyProps extends EventThrottlingProps {
|
|
794
|
-
/**
|
|
795
|
-
* Tab order of the chart surface. Upstream's React `tabIndex`; the native `tabindex`
|
|
796
|
-
* attribute is accepted too. Defaults to 0 when `accessibilityLayer` is on.
|
|
797
|
-
*/
|
|
798
|
-
tabIndex?: number
|
|
799
|
-
/**
|
|
800
|
-
* Name represents each sector in the tooltip.
|
|
801
|
-
* This allows you to extract the name from the data:
|
|
802
|
-
*
|
|
803
|
-
* - `string`: the name of the field in the data object;
|
|
804
|
-
* - `number`: the index of the field in the data;
|
|
805
|
-
* - `function`: a function that receives the data object and returns the name.
|
|
806
|
-
*
|
|
807
|
-
* @defaultValue name
|
|
808
|
-
*/
|
|
809
|
-
nameKey?: DataKey<unknown>
|
|
810
|
-
/**
|
|
811
|
-
* dataKey prop in Sankey defines which key in the link objects represents the value of the link _in Tooltip only_.
|
|
812
|
-
*
|
|
813
|
-
* Unlike other charts where dataKey is used to extract values from the data array, in Sankey charts,
|
|
814
|
-
* the value of each link is directly taken from the 'value' property of the link objects.
|
|
815
|
-
*
|
|
816
|
-
* @default 'value'
|
|
817
|
-
*/
|
|
818
|
-
dataKey?: DataKey<unknown>
|
|
819
|
-
/**
|
|
820
|
-
* The width of chart container.
|
|
821
|
-
* Can be a number or a percent string like "100%".
|
|
822
|
-
*
|
|
823
|
-
* @see {@link https://recharts.github.io/en-US/guide/sizes/ Chart sizing guide}
|
|
824
|
-
*/
|
|
825
|
-
width?: number | Percent
|
|
826
|
-
/**
|
|
827
|
-
* The height of chart container.
|
|
828
|
-
* Can be a number or a percent string like "100%".
|
|
829
|
-
*
|
|
830
|
-
* @see {@link https://recharts.github.io/en-US/guide/sizes/ Chart sizing guide}
|
|
831
|
-
*/
|
|
832
|
-
height?: number | Percent
|
|
833
|
-
/**
|
|
834
|
-
* The source data, including the array of nodes, and the relationships, represented by links.
|
|
835
|
-
*
|
|
836
|
-
* Note that Sankey requires a specific data structure.
|
|
837
|
-
* Each node should have a unique index in the nodes array, and each link should reference these nodes by their indices.
|
|
838
|
-
* This is different from other chart types in Recharts, which accept arbitrary data.
|
|
839
|
-
*
|
|
840
|
-
* @example
|
|
841
|
-
* nodes: [
|
|
842
|
-
* { name: 'Visit' },
|
|
843
|
-
* { name: 'Direct-Favourite' },
|
|
844
|
-
* { name: 'Page-Click' },
|
|
845
|
-
* { name: 'Detail-Favourite' },
|
|
846
|
-
* { name: 'Lost' },
|
|
847
|
-
* ],
|
|
848
|
-
* links: [
|
|
849
|
-
* { source: 0, target: 1, value: 3728.3 },
|
|
850
|
-
* { source: 0, target: 2, value: 354170 },
|
|
851
|
-
* { source: 2, target: 3, value: 62429 },
|
|
852
|
-
* { source: 2, target: 4, value: 291741 },
|
|
853
|
-
* ],
|
|
854
|
-
*/
|
|
855
|
-
data: SankeyData
|
|
856
|
-
/**
|
|
857
|
-
* The padding between the nodes
|
|
858
|
-
* @default 10
|
|
859
|
-
*/
|
|
860
|
-
nodePadding?: number
|
|
861
|
-
/**
|
|
862
|
-
* The width of node
|
|
863
|
-
* @default 10
|
|
864
|
-
*/
|
|
865
|
-
nodeWidth?: number
|
|
866
|
-
/**
|
|
867
|
-
* The curvature of width
|
|
868
|
-
* @default 0.5
|
|
869
|
-
*/
|
|
870
|
-
linkCurvature?: number
|
|
871
|
-
/**
|
|
872
|
-
* The number of the iterations between the links
|
|
873
|
-
* @default 32
|
|
874
|
-
*/
|
|
875
|
-
iterations?: number
|
|
876
|
-
/**
|
|
877
|
-
* If set an object, the option is the configuration of nodes.
|
|
878
|
-
* If set a React element, the option is the custom react element of drawing the nodes.
|
|
879
|
-
*
|
|
880
|
-
* @example <Sankey node={MyCustomComponent} />
|
|
881
|
-
* @example <Sankey node={{stroke: #77c878, strokeWidth: 2}} />
|
|
882
|
-
*/
|
|
883
|
-
node?: SankeyNodeOptions
|
|
884
|
-
/**
|
|
885
|
-
* If set an object, the option is the configuration of links.
|
|
886
|
-
* If set a React element, the option is the custom react element of drawing the links.
|
|
887
|
-
*
|
|
888
|
-
* @example <Sankey link={MyCustomComponent} />
|
|
889
|
-
* @example <Sankey link={{ fill: #77c878 }} />
|
|
890
|
-
*/
|
|
891
|
-
link?: SankeyLinkOptions
|
|
892
|
-
style?: JSX.CSSProperties
|
|
893
|
-
class?: string
|
|
894
|
-
children?: JSX.Element
|
|
895
|
-
/**
|
|
896
|
-
* Turn on accessibility support for keyboard-only and screen reader users.
|
|
897
|
-
*
|
|
898
|
-
* @defaultValue true
|
|
899
|
-
*/
|
|
900
|
-
accessibilityLayer?: boolean
|
|
901
|
-
title?: string
|
|
902
|
-
desc?: string
|
|
903
|
-
/**
|
|
904
|
-
* Empty space around the container.
|
|
905
|
-
*
|
|
906
|
-
* @defaultValue {"top":5,"right":5,"bottom":5,"left":5}
|
|
907
|
-
*/
|
|
908
|
-
margin?: Partial<Margin>
|
|
909
|
-
/**
|
|
910
|
-
* The customized event handler of click on the area in this group
|
|
911
|
-
*/
|
|
912
|
-
onClick?: (item: NodeProps | LinkProps, type: SankeyElementType, e: MouseEvent & { currentTarget: SVGGraphicsElement }) => void
|
|
913
|
-
/**
|
|
914
|
-
* The customized event handler of mouseenter on the area in this group
|
|
915
|
-
*/
|
|
916
|
-
onMouseEnter?: (item: NodeProps | LinkProps, type: SankeyElementType, e: MouseEvent & { currentTarget: SVGGraphicsElement }) => void
|
|
917
|
-
/**
|
|
918
|
-
* The customized event handler of mouseleave on the area in this group
|
|
919
|
-
*/
|
|
920
|
-
onMouseLeave?: (item: NodeProps | LinkProps, type: SankeyElementType, e: MouseEvent & { currentTarget: SVGGraphicsElement }) => void
|
|
921
|
-
/**
|
|
922
|
-
* Whether to sort the nodes on the y axis, or to display them as user-defined.
|
|
923
|
-
* @default true
|
|
924
|
-
*/
|
|
925
|
-
sort?: boolean
|
|
926
|
-
/**
|
|
927
|
-
* Controls the vertical spacing of nodes within a depth. 'justify' distributes nodes evenly and balances link paths, while 'top' positions the group starting from the top edge of the chart.
|
|
928
|
-
* @default 'justify'
|
|
929
|
-
*/
|
|
930
|
-
verticalAlign?: SankeyVerticalAlign
|
|
931
|
-
/**
|
|
932
|
-
* If set to 'justify', the start nodes will be aligned to the left edge of the chart and the end nodes will be aligned to the right edge of the chart. If set to 'left', the start nodes will be aligned to the left edge of the chart.
|
|
933
|
-
* @default 'justify'
|
|
934
|
-
*/
|
|
935
|
-
align?: "left" | "justify"
|
|
936
|
-
stroke?: string
|
|
937
|
-
strokeWidth?: number | string
|
|
938
|
-
fill?: string
|
|
939
|
-
name?: string | number
|
|
940
|
-
id?: string
|
|
941
|
-
}
|
|
942
|
-
|
|
943
|
-
export type Props = WithoutRemoveFalse<Omit<JSX.SvgSVGAttributes<SVGSVGElement>, keyof SankeyProps | "ref">> & SankeyProps
|
|
944
|
-
|
|
945
|
-
export type SankeyElementType = "node" | "link"
|
|
946
|
-
|
|
947
|
-
function renderLinkItem(
|
|
948
|
-
option: SankeyLinkOptions | undefined,
|
|
949
|
-
linkProps: LinkProps,
|
|
950
|
-
events?: Record<string, ((e: Event) => void) | undefined>,
|
|
951
|
-
): JSX.Element {
|
|
952
|
-
if (typeof option === "function") {
|
|
953
|
-
return option(linkProps)
|
|
954
|
-
}
|
|
955
|
-
|
|
956
|
-
const {
|
|
957
|
-
sourceX,
|
|
958
|
-
sourceY,
|
|
959
|
-
sourceControlX,
|
|
960
|
-
targetX,
|
|
961
|
-
targetY,
|
|
962
|
-
targetControlX,
|
|
963
|
-
linkWidth,
|
|
964
|
-
...others
|
|
965
|
-
} = linkProps
|
|
966
|
-
|
|
967
|
-
return (
|
|
968
|
-
<path
|
|
969
|
-
class="recharts-sankey-link"
|
|
970
|
-
d={`
|
|
971
|
-
M${sourceX},${sourceY}
|
|
972
|
-
C${sourceControlX},${sourceY} ${targetControlX},${targetY} ${targetX},${targetY}
|
|
973
|
-
`}
|
|
974
|
-
fill="none"
|
|
975
|
-
stroke="#333"
|
|
976
|
-
stroke-width={linkWidth}
|
|
977
|
-
stroke-opacity="0.2"
|
|
978
|
-
{...svgPropertiesNoEvents(others)}
|
|
979
|
-
{...(events ?? {})}
|
|
980
|
-
/>
|
|
981
|
-
)
|
|
982
|
-
}
|
|
983
|
-
|
|
984
|
-
const buildLinkProps = ({
|
|
985
|
-
link,
|
|
986
|
-
nodes,
|
|
987
|
-
left,
|
|
988
|
-
top,
|
|
989
|
-
i,
|
|
990
|
-
linkContent,
|
|
991
|
-
linkCurvature,
|
|
992
|
-
}: {
|
|
993
|
-
link: SankeyLink
|
|
994
|
-
nodes: ReadonlyArray<SankeyNode>
|
|
995
|
-
top: number
|
|
996
|
-
left: number
|
|
997
|
-
linkContent: SankeyLinkOptions | undefined
|
|
998
|
-
i: number
|
|
999
|
-
linkCurvature: number
|
|
1000
|
-
}): LinkProps | undefined => {
|
|
1001
|
-
const { sy: sourceRelativeY, ty: targetRelativeY, dy: linkWidth } = link
|
|
1002
|
-
const sourceNode = nodes[link.source]
|
|
1003
|
-
const targetNode = nodes[link.target]
|
|
1004
|
-
if (sourceNode == null || targetNode == null) {
|
|
1005
|
-
return undefined
|
|
1006
|
-
}
|
|
1007
|
-
const sourceX = sourceNode.x + sourceNode.dx + left
|
|
1008
|
-
const targetX = targetNode.x + left
|
|
1009
|
-
const interpolationFunc = interpolationGenerator(sourceX, targetX)
|
|
1010
|
-
const sourceControlX = interpolationFunc(linkCurvature)
|
|
1011
|
-
const targetControlX = interpolationFunc(1 - linkCurvature)
|
|
1012
|
-
const sourceY = sourceNode.y + sourceRelativeY + linkWidth / 2 + top
|
|
1013
|
-
const targetY = targetNode.y + targetRelativeY + linkWidth / 2 + top
|
|
1014
|
-
|
|
1015
|
-
const linkProps: LinkProps = {
|
|
1016
|
-
...svgPropertiesNoEventsFromUnknown(linkContent),
|
|
1017
|
-
index: i,
|
|
1018
|
-
linkWidth,
|
|
1019
|
-
payload: { ...link, source: sourceNode, target: targetNode },
|
|
1020
|
-
sourceControlX,
|
|
1021
|
-
sourceRelativeY,
|
|
1022
|
-
sourceX,
|
|
1023
|
-
sourceY,
|
|
1024
|
-
targetControlX,
|
|
1025
|
-
targetRelativeY,
|
|
1026
|
-
targetX,
|
|
1027
|
-
targetY,
|
|
1028
|
-
}
|
|
1029
|
-
|
|
1030
|
-
return linkProps
|
|
1031
|
-
}
|
|
1032
|
-
|
|
1033
|
-
function SankeyLinkElement(props: {
|
|
1034
|
-
graphicalItemId: GraphicalItemId
|
|
1035
|
-
props: LinkProps
|
|
1036
|
-
i: number
|
|
1037
|
-
linkContent: SankeyLinkOptions | undefined
|
|
1038
|
-
onMouseEnter: (linkProps: LinkProps, e: MouseEvent & { currentTarget: SVGGraphicsElement }) => void
|
|
1039
|
-
onMouseLeave: (linkProps: LinkProps, e: MouseEvent & { currentTarget: SVGGraphicsElement }) => void
|
|
1040
|
-
onClick: (linkProps: LinkProps, e: MouseEvent & { currentTarget: SVGGraphicsElement }) => void
|
|
1041
|
-
dataKey: DataKey<unknown>
|
|
1042
|
-
}): JSX.Element {
|
|
1043
|
-
/* eslint-disable solid/reactivity -- props.props and props.i are stable identifiers captured once at mount */
|
|
1044
|
-
const linkProps = untrack(() => props.props)
|
|
1045
|
-
const linkIndex = untrack(() => props.i)
|
|
1046
|
-
const activeCoordinate = getLinkCoordinateOfTooltip(linkProps)
|
|
1047
|
-
const activeIndex = `link-${linkIndex}`
|
|
1048
|
-
/* eslint-enable solid/reactivity */
|
|
1049
|
-
|
|
1050
|
-
const ctx = useChartStore()
|
|
1051
|
-
const newCtx = useOptionalChartState()
|
|
1052
|
-
|
|
1053
|
-
/* GOTCHA-016-C: bind both enter/leave AND over/out so fireEvent.mouseEnter, fireEvent.mouseOver, and user.hover all dispatch. Track per-instance entry state — `user.hover` fires mouseenter then mouseover; we dedupe by toggling once per real entry. */
|
|
1054
|
-
let entered = false
|
|
1055
|
-
const fireEnter = (e: MouseEvent & { currentTarget: SVGGraphicsElement }) => {
|
|
1056
|
-
if (entered) return
|
|
1057
|
-
entered = true
|
|
1058
|
-
const hoverPayload = {
|
|
1059
|
-
active: true,
|
|
1060
|
-
coordinate: activeCoordinate,
|
|
1061
|
-
dataKey: props.dataKey,
|
|
1062
|
-
graphicalItemId: props.graphicalItemId,
|
|
1063
|
-
index: activeIndex,
|
|
1064
|
-
}
|
|
1065
|
-
if (newCtx != null) setTooltipInteraction(newCtx.setState, "itemInteraction", "hover", hoverPayload)
|
|
1066
|
-
props.onMouseEnter(linkProps, e)
|
|
1067
|
-
}
|
|
1068
|
-
const fireLeave = (e: MouseEvent & { currentTarget: SVGGraphicsElement }) => {
|
|
1069
|
-
if (!entered) return
|
|
1070
|
-
entered = false
|
|
1071
|
-
newCtx?.setState("tooltip", "itemInteraction", "hover", "active", false)
|
|
1072
|
-
props.onMouseLeave(linkProps, e)
|
|
1073
|
-
}
|
|
1074
|
-
const events = {
|
|
1075
|
-
onClick: (e: MouseEvent & { currentTarget: SVGGraphicsElement }) => {
|
|
1076
|
-
const clickPayload = {
|
|
1077
|
-
active: true,
|
|
1078
|
-
coordinate: activeCoordinate,
|
|
1079
|
-
dataKey: props.dataKey,
|
|
1080
|
-
graphicalItemId: props.graphicalItemId,
|
|
1081
|
-
index: activeIndex,
|
|
1082
|
-
}
|
|
1083
|
-
if (newCtx != null) setTooltipInteraction(newCtx.setState, "itemInteraction", "click", clickPayload)
|
|
1084
|
-
props.onClick(linkProps, e)
|
|
1085
|
-
},
|
|
1086
|
-
onMouseEnter: fireEnter,
|
|
1087
|
-
onMouseOver: fireEnter,
|
|
1088
|
-
onMouseLeave: fireLeave,
|
|
1089
|
-
onMouseOut: fireLeave,
|
|
1090
|
-
}
|
|
1091
|
-
|
|
1092
|
-
return (
|
|
1093
|
-
<Layer>
|
|
1094
|
-
{renderLinkItem(
|
|
1095
|
-
props.linkContent,
|
|
1096
|
-
linkProps,
|
|
1097
|
-
events as unknown as Record<string, ((e: Event) => void) | undefined>,
|
|
1098
|
-
)}
|
|
1099
|
-
</Layer>
|
|
1100
|
-
)
|
|
1101
|
-
}
|
|
1102
|
-
|
|
1103
|
-
function AllSankeyLinkElements(props: {
|
|
1104
|
-
graphicalItemId: GraphicalItemId
|
|
1105
|
-
modifiedLinks: ReadonlyArray<LinkProps>
|
|
1106
|
-
links: ReadonlyArray<SankeyLink>
|
|
1107
|
-
linkContent: SankeyLinkOptions | undefined
|
|
1108
|
-
onMouseEnter: (linkProps: LinkProps, e: MouseEvent & { currentTarget: SVGGraphicsElement }) => void
|
|
1109
|
-
onMouseLeave: (linkProps: LinkProps, e: MouseEvent & { currentTarget: SVGGraphicsElement }) => void
|
|
1110
|
-
onClick: (linkProps: LinkProps, e: MouseEvent & { currentTarget: SVGGraphicsElement }) => void
|
|
1111
|
-
dataKey: DataKey<unknown>
|
|
1112
|
-
}): JSX.Element {
|
|
1113
|
-
return (
|
|
1114
|
-
<Layer class="recharts-sankey-links">
|
|
1115
|
-
<For each={props.links as SankeyLink[]}>
|
|
1116
|
-
{(link: SankeyLink, i) => {
|
|
1117
|
-
const linkPropsItem = () => props.modifiedLinks[i()]
|
|
1118
|
-
return (
|
|
1119
|
-
<Show when={linkPropsItem()}>
|
|
1120
|
-
{(lp) => (
|
|
1121
|
-
<SankeyLinkElement
|
|
1122
|
-
graphicalItemId={props.graphicalItemId}
|
|
1123
|
-
props={lp()}
|
|
1124
|
-
linkContent={props.linkContent}
|
|
1125
|
-
i={i()}
|
|
1126
|
-
onMouseEnter={props.onMouseEnter}
|
|
1127
|
-
onMouseLeave={props.onMouseLeave}
|
|
1128
|
-
onClick={props.onClick}
|
|
1129
|
-
dataKey={props.dataKey}
|
|
1130
|
-
/>
|
|
1131
|
-
)}
|
|
1132
|
-
</Show>
|
|
1133
|
-
)
|
|
1134
|
-
}}
|
|
1135
|
-
</For>
|
|
1136
|
-
</Layer>
|
|
1137
|
-
)
|
|
1138
|
-
}
|
|
1139
|
-
|
|
1140
|
-
function renderNodeItem(
|
|
1141
|
-
option: SankeyNodeOptions | undefined,
|
|
1142
|
-
nodeProps: NodeProps,
|
|
1143
|
-
events?: Record<string, ((e: Event) => void) | undefined>,
|
|
1144
|
-
): JSX.Element {
|
|
1145
|
-
if (typeof option === "function") {
|
|
1146
|
-
return option(nodeProps)
|
|
1147
|
-
}
|
|
1148
|
-
|
|
1149
|
-
return (
|
|
1150
|
-
<Rectangle
|
|
1151
|
-
class="recharts-sankey-node"
|
|
1152
|
-
fill="#0088fe"
|
|
1153
|
-
fill-opacity="0.8"
|
|
1154
|
-
{...svgPropertiesNoEvents(nodeProps)}
|
|
1155
|
-
{...(events ?? {})}
|
|
1156
|
-
/>
|
|
1157
|
-
)
|
|
1158
|
-
}
|
|
1159
|
-
|
|
1160
|
-
const buildNodeProps = ({
|
|
1161
|
-
node,
|
|
1162
|
-
nodeContent,
|
|
1163
|
-
top,
|
|
1164
|
-
left,
|
|
1165
|
-
i,
|
|
1166
|
-
}: {
|
|
1167
|
-
node: SankeyNode
|
|
1168
|
-
nodeContent: SankeyNodeOptions | undefined
|
|
1169
|
-
top: number
|
|
1170
|
-
left: number
|
|
1171
|
-
i: number
|
|
1172
|
-
}): NodeProps => {
|
|
1173
|
-
const { x, y, dx, dy } = node
|
|
1174
|
-
const nodeProps: NodeProps = {
|
|
1175
|
-
...svgPropertiesNoEventsFromUnknown(nodeContent),
|
|
1176
|
-
height: dy,
|
|
1177
|
-
index: i,
|
|
1178
|
-
payload: node,
|
|
1179
|
-
width: dx,
|
|
1180
|
-
x: x + left,
|
|
1181
|
-
y: y + top,
|
|
1182
|
-
}
|
|
1183
|
-
return nodeProps
|
|
1184
|
-
}
|
|
1185
|
-
|
|
1186
|
-
function NodeElement(props: {
|
|
1187
|
-
graphicalItemId: GraphicalItemId
|
|
1188
|
-
props: NodeProps
|
|
1189
|
-
nodeContent: SankeyNodeOptions | undefined
|
|
1190
|
-
i: number
|
|
1191
|
-
onMouseEnter: (nodeProps: NodeProps, e: MouseEvent & { currentTarget: SVGGraphicsElement }) => void
|
|
1192
|
-
onMouseLeave: (nodeProps: NodeProps, e: MouseEvent & { currentTarget: SVGGraphicsElement }) => void
|
|
1193
|
-
onClick: (nodeProps: NodeProps, e: MouseEvent & { currentTarget: SVGGraphicsElement }) => void
|
|
1194
|
-
dataKey: DataKey<unknown>
|
|
1195
|
-
}): JSX.Element {
|
|
1196
|
-
const ctx = useChartStore()
|
|
1197
|
-
const newCtx = useOptionalChartState()
|
|
1198
|
-
|
|
1199
|
-
/* eslint-disable solid/reactivity -- props.props and props.i are stable identifiers captured once at mount */
|
|
1200
|
-
const nodeProps = untrack(() => props.props)
|
|
1201
|
-
const nodeIndex = untrack(() => props.i)
|
|
1202
|
-
const activeCoordinate = getNodeCoordinateOfTooltip(nodeProps)
|
|
1203
|
-
const activeIndex = `node-${nodeIndex}`
|
|
1204
|
-
/* eslint-enable solid/reactivity */
|
|
1205
|
-
|
|
1206
|
-
/* GOTCHA-016-C: same pattern as SankeyLinkElement — bind both enter/leave AND over/out, dedupe via per-instance entry flag. */
|
|
1207
|
-
let entered = false
|
|
1208
|
-
const fireEnter = (e: MouseEvent & { currentTarget: SVGGraphicsElement }) => {
|
|
1209
|
-
if (entered) return
|
|
1210
|
-
entered = true
|
|
1211
|
-
const hoverPayload = {
|
|
1212
|
-
active: true,
|
|
1213
|
-
coordinate: activeCoordinate,
|
|
1214
|
-
dataKey: props.dataKey,
|
|
1215
|
-
graphicalItemId: props.graphicalItemId,
|
|
1216
|
-
index: activeIndex,
|
|
1217
|
-
}
|
|
1218
|
-
if (newCtx != null) setTooltipInteraction(newCtx.setState, "itemInteraction", "hover", hoverPayload)
|
|
1219
|
-
props.onMouseEnter(nodeProps, e)
|
|
1220
|
-
}
|
|
1221
|
-
const fireLeave = (e: MouseEvent & { currentTarget: SVGGraphicsElement }) => {
|
|
1222
|
-
if (!entered) return
|
|
1223
|
-
entered = false
|
|
1224
|
-
newCtx?.setState("tooltip", "itemInteraction", "hover", "active", false)
|
|
1225
|
-
props.onMouseLeave(nodeProps, e)
|
|
1226
|
-
}
|
|
1227
|
-
const events = {
|
|
1228
|
-
onClick: (e: MouseEvent & { currentTarget: SVGGraphicsElement }) => {
|
|
1229
|
-
const clickPayload = {
|
|
1230
|
-
active: true,
|
|
1231
|
-
coordinate: activeCoordinate,
|
|
1232
|
-
dataKey: props.dataKey,
|
|
1233
|
-
graphicalItemId: props.graphicalItemId,
|
|
1234
|
-
index: activeIndex,
|
|
1235
|
-
}
|
|
1236
|
-
if (newCtx != null) setTooltipInteraction(newCtx.setState, "itemInteraction", "click", clickPayload)
|
|
1237
|
-
props.onClick(nodeProps, e)
|
|
1238
|
-
},
|
|
1239
|
-
onMouseEnter: fireEnter,
|
|
1240
|
-
onMouseOver: fireEnter,
|
|
1241
|
-
onMouseLeave: fireLeave,
|
|
1242
|
-
onMouseOut: fireLeave,
|
|
1243
|
-
}
|
|
1244
|
-
|
|
1245
|
-
return (
|
|
1246
|
-
<Layer>
|
|
1247
|
-
{renderNodeItem(
|
|
1248
|
-
props.nodeContent,
|
|
1249
|
-
nodeProps,
|
|
1250
|
-
events as unknown as Record<string, ((e: Event) => void) | undefined>,
|
|
1251
|
-
)}
|
|
1252
|
-
</Layer>
|
|
1253
|
-
)
|
|
1254
|
-
}
|
|
1255
|
-
|
|
1256
|
-
function AllNodeElements(props: {
|
|
1257
|
-
graphicalItemId: GraphicalItemId
|
|
1258
|
-
modifiedNodes: ReadonlyArray<NodeProps>
|
|
1259
|
-
nodeContent: SankeyNodeOptions | undefined
|
|
1260
|
-
onMouseEnter: (nodeProps: NodeProps, e: MouseEvent & { currentTarget: SVGGraphicsElement }) => void
|
|
1261
|
-
onMouseLeave: (nodeProps: NodeProps, e: MouseEvent & { currentTarget: SVGGraphicsElement }) => void
|
|
1262
|
-
onClick: (nodeProps: NodeProps, e: MouseEvent & { currentTarget: SVGGraphicsElement }) => void
|
|
1263
|
-
dataKey: DataKey<unknown>
|
|
1264
|
-
}): JSX.Element {
|
|
1265
|
-
return (
|
|
1266
|
-
<Layer class="recharts-sankey-nodes">
|
|
1267
|
-
<For each={props.modifiedNodes as NodeProps[]}>
|
|
1268
|
-
{(modifiedNode, i) => (
|
|
1269
|
-
<NodeElement
|
|
1270
|
-
graphicalItemId={props.graphicalItemId}
|
|
1271
|
-
props={modifiedNode}
|
|
1272
|
-
nodeContent={props.nodeContent}
|
|
1273
|
-
i={i()}
|
|
1274
|
-
onMouseEnter={props.onMouseEnter}
|
|
1275
|
-
onMouseLeave={props.onMouseLeave}
|
|
1276
|
-
onClick={props.onClick}
|
|
1277
|
-
dataKey={props.dataKey}
|
|
1278
|
-
/>
|
|
1279
|
-
)}
|
|
1280
|
-
</For>
|
|
1281
|
-
</Layer>
|
|
1282
|
-
)
|
|
1283
|
-
}
|
|
1284
|
-
|
|
1285
|
-
export const sankeyDefaultProps = {
|
|
1286
|
-
accessibilityLayer: true,
|
|
1287
|
-
align: "justify",
|
|
1288
|
-
dataKey: "value",
|
|
1289
|
-
iterations: 32,
|
|
1290
|
-
linkCurvature: 0.5,
|
|
1291
|
-
margin: { bottom: 5, left: 5, right: 5, top: 5 },
|
|
1292
|
-
nameKey: "name",
|
|
1293
|
-
nodePadding: 10,
|
|
1294
|
-
nodeWidth: 10,
|
|
1295
|
-
sort: true,
|
|
1296
|
-
verticalAlign: "justify",
|
|
1297
|
-
...initialEventSettingsState,
|
|
1298
|
-
} as const satisfies Partial<Props>
|
|
1299
|
-
|
|
1300
|
-
type PropsWithResolvedDefaults = RequiresDefaultProps<Props, typeof sankeyDefaultProps>
|
|
1301
|
-
|
|
1302
|
-
type InternalSankeyProps = WithIdRequired<PropsWithResolvedDefaults>
|
|
1303
|
-
|
|
1304
|
-
function SankeyImpl(props: InternalSankeyProps): JSX.Element {
|
|
1305
|
-
const width = createMemo(() => useChartWidth())
|
|
1306
|
-
const height = createMemo(() => useChartHeight())
|
|
1307
|
-
|
|
1308
|
-
const computed = createMemo(() => {
|
|
1309
|
-
const w = width()
|
|
1310
|
-
const h = height()
|
|
1311
|
-
if (w == null || h == null || w <= 0 || h <= 0 || props.data == null) {
|
|
1312
|
-
return {
|
|
1313
|
-
links: [] as SankeyLink[],
|
|
1314
|
-
modifiedLinks: [] as LinkProps[],
|
|
1315
|
-
modifiedNodes: [] as NodeProps[],
|
|
1316
|
-
nodes: [] as SankeyNode[],
|
|
1317
|
-
}
|
|
1318
|
-
}
|
|
1319
|
-
const contentWidth = w - (props.margin.left ?? 0) - (props.margin.right ?? 0)
|
|
1320
|
-
const contentHeight = h - (props.margin.top ?? 0) - (props.margin.bottom ?? 0)
|
|
1321
|
-
const result = computeData({
|
|
1322
|
-
align: props.align,
|
|
1323
|
-
data: props.data,
|
|
1324
|
-
height: contentHeight,
|
|
1325
|
-
iterations: props.iterations,
|
|
1326
|
-
nodePadding: props.nodePadding,
|
|
1327
|
-
nodeWidth: props.nodeWidth,
|
|
1328
|
-
sort: props.sort,
|
|
1329
|
-
verticalAlign: props.verticalAlign,
|
|
1330
|
-
width: contentWidth,
|
|
1331
|
-
})
|
|
1332
|
-
|
|
1333
|
-
const top = props.margin.top || 0
|
|
1334
|
-
const left = props.margin.left || 0
|
|
1335
|
-
const newModifiedLinks = result.links
|
|
1336
|
-
.map((l, i) => {
|
|
1337
|
-
return buildLinkProps({
|
|
1338
|
-
i,
|
|
1339
|
-
left,
|
|
1340
|
-
link: l,
|
|
1341
|
-
linkContent: props.link,
|
|
1342
|
-
linkCurvature: props.linkCurvature,
|
|
1343
|
-
nodes: result.nodes,
|
|
1344
|
-
top,
|
|
1345
|
-
})
|
|
1346
|
-
})
|
|
1347
|
-
.filter(isNotNil)
|
|
1348
|
-
|
|
1349
|
-
const newModifiedNodes = result.nodes.map((n, i) => {
|
|
1350
|
-
return buildNodeProps({
|
|
1351
|
-
i,
|
|
1352
|
-
left,
|
|
1353
|
-
node: n,
|
|
1354
|
-
nodeContent: props.node,
|
|
1355
|
-
top,
|
|
1356
|
-
})
|
|
1357
|
-
})
|
|
1358
|
-
|
|
1359
|
-
return {
|
|
1360
|
-
links: result.links,
|
|
1361
|
-
modifiedLinks: newModifiedLinks,
|
|
1362
|
-
modifiedNodes: newModifiedNodes,
|
|
1363
|
-
nodes: result.nodes,
|
|
1364
|
-
}
|
|
1365
|
-
})
|
|
1366
|
-
|
|
1367
|
-
function handleMouseEnter(item: NodeProps | LinkProps, type: SankeyElementType, e: MouseEvent & { currentTarget: SVGGraphicsElement }) {
|
|
1368
|
-
if (props.onMouseEnter) {
|
|
1369
|
-
props.onMouseEnter(item, type, e)
|
|
1370
|
-
}
|
|
1371
|
-
}
|
|
1372
|
-
|
|
1373
|
-
function handleMouseLeave(item: NodeProps | LinkProps, type: SankeyElementType, e: MouseEvent & { currentTarget: SVGGraphicsElement }) {
|
|
1374
|
-
if (props.onMouseLeave) {
|
|
1375
|
-
props.onMouseLeave(item, type, e)
|
|
1376
|
-
}
|
|
1377
|
-
}
|
|
1378
|
-
|
|
1379
|
-
function handleClick(item: NodeProps | LinkProps, type: SankeyElementType, e: MouseEvent & { currentTarget: SVGGraphicsElement }) {
|
|
1380
|
-
if (props.onClick) {
|
|
1381
|
-
props.onClick(item, type, e)
|
|
1382
|
-
}
|
|
1383
|
-
}
|
|
1384
|
-
|
|
1385
|
-
const attrs = () => svgPropertiesNoEvents(props)
|
|
1386
|
-
|
|
1387
|
-
const tabIndex = () => {
|
|
1388
|
-
const explicit = props.tabIndex ?? props.tabindex
|
|
1389
|
-
if (typeof explicit === "number") {
|
|
1390
|
-
return explicit
|
|
1391
|
-
}
|
|
1392
|
-
return props.accessibilityLayer ? 0 : undefined
|
|
1393
|
-
}
|
|
1394
|
-
|
|
1395
|
-
const role = () => {
|
|
1396
|
-
if (typeof props.role === "string") {
|
|
1397
|
-
return props.role
|
|
1398
|
-
}
|
|
1399
|
-
return props.accessibilityLayer ? "application" : undefined
|
|
1400
|
-
}
|
|
1401
|
-
|
|
1402
|
-
return (
|
|
1403
|
-
<Show
|
|
1404
|
-
when={
|
|
1405
|
-
isPositiveNumber(width()) &&
|
|
1406
|
-
isPositiveNumber(height()) &&
|
|
1407
|
-
props.data?.links &&
|
|
1408
|
-
props.data?.nodes
|
|
1409
|
-
}
|
|
1410
|
-
>
|
|
1411
|
-
<SetComputedData
|
|
1412
|
-
computedData={{ links: computed().modifiedLinks, nodes: computed().modifiedNodes }}
|
|
1413
|
-
/>
|
|
1414
|
-
<Surface
|
|
1415
|
-
{...attrs()}
|
|
1416
|
-
title={props.title}
|
|
1417
|
-
desc={props.desc}
|
|
1418
|
-
role={role()}
|
|
1419
|
-
tabindex={tabIndex()}
|
|
1420
|
-
width={width() ?? 0}
|
|
1421
|
-
height={height() ?? 0}
|
|
1422
|
-
>
|
|
1423
|
-
{props.children}
|
|
1424
|
-
<AllSankeyLinkElements
|
|
1425
|
-
graphicalItemId={props.id}
|
|
1426
|
-
links={computed().links}
|
|
1427
|
-
modifiedLinks={computed().modifiedLinks}
|
|
1428
|
-
linkContent={props.link}
|
|
1429
|
-
dataKey={props.dataKey}
|
|
1430
|
-
onMouseEnter={(linkProps: LinkProps, e: MouseEvent & { currentTarget: SVGGraphicsElement }) =>
|
|
1431
|
-
handleMouseEnter(linkProps, "link", e)
|
|
1432
|
-
}
|
|
1433
|
-
onMouseLeave={(linkProps: LinkProps, e: MouseEvent & { currentTarget: SVGGraphicsElement }) =>
|
|
1434
|
-
handleMouseLeave(linkProps, "link", e)
|
|
1435
|
-
}
|
|
1436
|
-
onClick={(linkProps: LinkProps, e: MouseEvent & { currentTarget: SVGGraphicsElement }) => handleClick(linkProps, "link", e)}
|
|
1437
|
-
/>
|
|
1438
|
-
<AllNodeElements
|
|
1439
|
-
graphicalItemId={props.id}
|
|
1440
|
-
modifiedNodes={computed().modifiedNodes}
|
|
1441
|
-
nodeContent={props.node}
|
|
1442
|
-
dataKey={props.dataKey}
|
|
1443
|
-
onMouseEnter={(nodeProps: NodeProps, e: MouseEvent & { currentTarget: SVGGraphicsElement }) =>
|
|
1444
|
-
handleMouseEnter(nodeProps, "node", e)
|
|
1445
|
-
}
|
|
1446
|
-
onMouseLeave={(nodeProps: NodeProps, e: MouseEvent & { currentTarget: SVGGraphicsElement }) =>
|
|
1447
|
-
handleMouseLeave(nodeProps, "node", e)
|
|
1448
|
-
}
|
|
1449
|
-
onClick={(nodeProps: NodeProps, e: MouseEvent & { currentTarget: SVGGraphicsElement }) => handleClick(nodeProps, "node", e)}
|
|
1450
|
-
/>
|
|
1451
|
-
</Surface>
|
|
1452
|
-
</Show>
|
|
1453
|
-
)
|
|
1454
|
-
}
|
|
1455
|
-
|
|
1456
|
-
/**
|
|
1457
|
-
* Flow diagram in which the width of the arrows is proportional to the flow rate.
|
|
1458
|
-
* It is typically used to visualize energy or material or cost transfers between processes.
|
|
1459
|
-
*
|
|
1460
|
-
* @consumes ResponsiveContainerContext
|
|
1461
|
-
* @provides TooltipEntrySettings
|
|
1462
|
-
*/
|
|
1463
|
-
export function Sankey(outsideProps: Props): JSX.Element {
|
|
1464
|
-
/* GOTCHA-005-B: do not spread {...props} into a deep child — that enumerates the
|
|
1465
|
-
Solid props proxy and triggers `children` getter, which instantiates user JSX
|
|
1466
|
-
(Tooltip, Customized, etc.) under the OUTER owner (no RechartsWrapper Provider
|
|
1467
|
-
in scope). Strip children via splitProps and pass them as JSX so they're created
|
|
1468
|
-
inside RechartsWrapper where TooltipPortalContext / LegendPortalContext live. */
|
|
1469
|
-
const [childrenSplit, restProps] = splitProps(outsideProps, ["children"])
|
|
1470
|
-
const props: PropsWithResolvedDefaults = resolveDefaultProps(restProps, sankeyDefaultProps)
|
|
1471
|
-
|
|
1472
|
-
return (
|
|
1473
|
-
<RechartsStateProvider
|
|
1474
|
-
preloadedState={{
|
|
1475
|
-
layout: untrack(() =>
|
|
1476
|
-
createInitialLayoutState({ height: props.height, margin: props.margin, width: props.width }),
|
|
1477
|
-
),
|
|
1478
|
-
options,
|
|
1479
|
-
}}
|
|
1480
|
-
>
|
|
1481
|
-
<ReportChartSize width={props.width} height={props.height} />
|
|
1482
|
-
<ReportChartMargin margin={props.margin} />
|
|
1483
|
-
<ReportEventSettings
|
|
1484
|
-
throttleDelay={props.throttleDelay}
|
|
1485
|
-
throttledEvents={props.throttledEvents}
|
|
1486
|
-
/>
|
|
1487
|
-
|
|
1488
|
-
<RechartsWrapper
|
|
1489
|
-
class={props.class}
|
|
1490
|
-
style={props.style}
|
|
1491
|
-
width={props.width}
|
|
1492
|
-
height={props.height}
|
|
1493
|
-
/*
|
|
1494
|
-
* Sankey, same as Treemap, suffers from overfilling the container
|
|
1495
|
-
* and causing infinite render loops where the chart keeps growing.
|
|
1496
|
-
*/
|
|
1497
|
-
responsive={false}
|
|
1498
|
-
onMouseEnter={undefined}
|
|
1499
|
-
onMouseLeave={undefined}
|
|
1500
|
-
onClick={undefined}
|
|
1501
|
-
onMouseMove={undefined}
|
|
1502
|
-
onMouseDown={undefined}
|
|
1503
|
-
onMouseUp={undefined}
|
|
1504
|
-
onContextMenu={undefined}
|
|
1505
|
-
onDoubleClick={undefined}
|
|
1506
|
-
onTouchStart={undefined}
|
|
1507
|
-
onTouchMove={undefined}
|
|
1508
|
-
onTouchEnd={undefined}
|
|
1509
|
-
>
|
|
1510
|
-
<RegisterGraphicalItemId id={props.id} type="sankey">
|
|
1511
|
-
{(id) => (
|
|
1512
|
-
<>
|
|
1513
|
-
<SetSankeyTooltipEntrySettings
|
|
1514
|
-
dataKey={props.dataKey}
|
|
1515
|
-
nameKey={props.nameKey}
|
|
1516
|
-
stroke={props.stroke}
|
|
1517
|
-
strokeWidth={props.strokeWidth}
|
|
1518
|
-
fill={props.fill}
|
|
1519
|
-
name={props.name}
|
|
1520
|
-
data={props.data}
|
|
1521
|
-
id={id}
|
|
1522
|
-
/>
|
|
1523
|
-
<SankeyImpl {...props} id={id}>
|
|
1524
|
-
{childrenSplit.children}
|
|
1525
|
-
</SankeyImpl>
|
|
1526
|
-
</>
|
|
1527
|
-
)}
|
|
1528
|
-
</RegisterGraphicalItemId>
|
|
1529
|
-
</RechartsWrapper>
|
|
1530
|
-
</RechartsStateProvider>
|
|
1531
|
-
)
|
|
1532
|
-
}
|
|
1533
|
-
|
|
1534
|
-
Sankey.displayName = "Sankey"
|