@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
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
import { createMemo, createSignal, untrack, createEffect } from "solid-js"
|
|
2
|
-
import type { Accessor } from "solid-js"
|
|
3
|
-
import type { JSX } from "@solidjs/web"
|
|
4
|
-
import { useAnimationController } from "./useAnimationController"
|
|
5
|
-
import { getTransitionVal } from "./util"
|
|
6
|
-
import { resolveIsAnimationActive, usePrefersReducedMotion } from "../util/usePrefersReducedMotion"
|
|
7
|
-
import { CSSTransitionAnimation } from "./AnimationHandle"
|
|
8
|
-
import { RequestAnimationFrameTimeoutController } from "./timeoutController"
|
|
9
|
-
import type { EasingInput, NamedBezier } from "./easing"
|
|
10
|
-
import type { AnimationController } from "./AnimationController"
|
|
11
|
-
|
|
12
|
-
type CSSTransitionAnimateProps = {
|
|
13
|
-
animationController?: AnimationController
|
|
14
|
-
animationId: string
|
|
15
|
-
attributeName: string
|
|
16
|
-
begin?: number
|
|
17
|
-
canBegin?: boolean
|
|
18
|
-
/* Children receive an accessor and are invoked once, like JavascriptAnimate. A CSS
|
|
19
|
-
transition only runs when the SAME element changes its style: re-invoking children
|
|
20
|
-
per style change would mount a new element already at `to`, and nothing animates. */
|
|
21
|
-
children: (style: Accessor<Record<string, string | number>>) => JSX.Element
|
|
22
|
-
duration?: number
|
|
23
|
-
easing?: NamedBezier
|
|
24
|
-
from: string
|
|
25
|
-
isActive?: boolean | "auto"
|
|
26
|
-
onAnimationEnd?: () => void
|
|
27
|
-
onAnimationStart?: () => void
|
|
28
|
-
to: string
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const defaultProps = {
|
|
32
|
-
begin: 0,
|
|
33
|
-
canBegin: true,
|
|
34
|
-
duration: 1000,
|
|
35
|
-
easing: "ease",
|
|
36
|
-
isActive: true,
|
|
37
|
-
onAnimationEnd: () => {},
|
|
38
|
-
onAnimationStart: () => {},
|
|
39
|
-
} as const satisfies Partial<CSSTransitionAnimateProps>
|
|
40
|
-
|
|
41
|
-
export function extractCssEasing(easingInput: EasingInput): NamedBezier | undefined {
|
|
42
|
-
if (easingInput === "spring" || typeof easingInput !== "string") {
|
|
43
|
-
return undefined
|
|
44
|
-
}
|
|
45
|
-
return easingInput
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export function CSSTransitionAnimate(outsideProps: CSSTransitionAnimateProps) {
|
|
49
|
-
/* Live getters with defaults (resolveDefaultProps would freeze them at setup — see
|
|
50
|
-
* GOTCHA-005-C). A literal view skips mergeProps' per-key defineProperty and key scan;
|
|
51
|
-
* this runs once per animated shape. `??` matches mergeProps: no prop here admits null. */
|
|
52
|
-
const props = {
|
|
53
|
-
get animationController() {
|
|
54
|
-
return outsideProps.animationController
|
|
55
|
-
},
|
|
56
|
-
get animationId() {
|
|
57
|
-
return outsideProps.animationId
|
|
58
|
-
},
|
|
59
|
-
get attributeName() {
|
|
60
|
-
return outsideProps.attributeName
|
|
61
|
-
},
|
|
62
|
-
get begin() {
|
|
63
|
-
return outsideProps.begin ?? defaultProps.begin
|
|
64
|
-
},
|
|
65
|
-
get canBegin() {
|
|
66
|
-
return outsideProps.canBegin ?? defaultProps.canBegin
|
|
67
|
-
},
|
|
68
|
-
get children() {
|
|
69
|
-
return outsideProps.children
|
|
70
|
-
},
|
|
71
|
-
get duration() {
|
|
72
|
-
return outsideProps.duration ?? defaultProps.duration
|
|
73
|
-
},
|
|
74
|
-
get easing() {
|
|
75
|
-
return outsideProps.easing ?? defaultProps.easing
|
|
76
|
-
},
|
|
77
|
-
get from() {
|
|
78
|
-
return outsideProps.from
|
|
79
|
-
},
|
|
80
|
-
get isActive() {
|
|
81
|
-
return outsideProps.isActive ?? defaultProps.isActive
|
|
82
|
-
},
|
|
83
|
-
get onAnimationEnd() {
|
|
84
|
-
return outsideProps.onAnimationEnd ?? defaultProps.onAnimationEnd
|
|
85
|
-
},
|
|
86
|
-
get onAnimationStart() {
|
|
87
|
-
return outsideProps.onAnimationStart ?? defaultProps.onAnimationStart
|
|
88
|
-
},
|
|
89
|
-
get to() {
|
|
90
|
-
return outsideProps.to
|
|
91
|
-
},
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const prefersReducedMotion = usePrefersReducedMotion()
|
|
95
|
-
const isActive = createMemo(() => resolveIsAnimationActive(props.isActive, prefersReducedMotion))
|
|
96
|
-
|
|
97
|
-
const animationController = useAnimationController(() => props.animationController)
|
|
98
|
-
const [style, setStyle] = createSignal<string | number>(
|
|
99
|
-
untrack(() => (isActive() === false ? props.to : props.from)),
|
|
100
|
-
)
|
|
101
|
-
/* Plain mutable mirrors React's useRef — flipping it must NOT trigger a
|
|
102
|
-
* re-render. Re-renders happen only when `style` changes (signal) or
|
|
103
|
-
* canBegin/isActive flip. The post-start render then reads the flag and
|
|
104
|
-
* adds `transition`. */
|
|
105
|
-
let initialized = false
|
|
106
|
-
|
|
107
|
-
createEffect(
|
|
108
|
-
() =>
|
|
109
|
-
isActive() === false || !props.canBegin
|
|
110
|
-
? null
|
|
111
|
-
: {
|
|
112
|
-
animationId: props.animationId + props.attributeName,
|
|
113
|
-
begin: props.begin,
|
|
114
|
-
controller: animationController(),
|
|
115
|
-
duration: props.duration,
|
|
116
|
-
easing: props.easing,
|
|
117
|
-
from: props.from,
|
|
118
|
-
onAnimationEnd: props.onAnimationEnd,
|
|
119
|
-
onAnimationStart: props.onAnimationStart,
|
|
120
|
-
to: props.to,
|
|
121
|
-
},
|
|
122
|
-
(run) => {
|
|
123
|
-
if (run == null) {
|
|
124
|
-
return undefined
|
|
125
|
-
}
|
|
126
|
-
initialized = true
|
|
127
|
-
|
|
128
|
-
const animation = new CSSTransitionAnimation({
|
|
129
|
-
animationBegin: run.begin,
|
|
130
|
-
animationDuration: run.duration,
|
|
131
|
-
animationId: run.animationId,
|
|
132
|
-
easing: run.easing,
|
|
133
|
-
from: run.from,
|
|
134
|
-
onAnimationEnd: run.onAnimationEnd,
|
|
135
|
-
onAnimationStart: () => {
|
|
136
|
-
setStyle(run.from)
|
|
137
|
-
run.onAnimationStart()
|
|
138
|
-
},
|
|
139
|
-
to: run.to,
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
return run.controller(new RequestAnimationFrameTimeoutController(), animation, setStyle)
|
|
143
|
-
},
|
|
144
|
-
)
|
|
145
|
-
|
|
146
|
-
const childStyle = createMemo<Record<string, string | number>>(() => {
|
|
147
|
-
/* Always read `style()` so the memo tracks it regardless of which
|
|
148
|
-
* branch we currently take. Otherwise: memo first evaluates with
|
|
149
|
-
* initialized=false, never reads style, never subscribes — when the
|
|
150
|
-
* start-effect later flips initialized and setStyle fires, the memo
|
|
151
|
-
* has no dependency on style and doesn't re-evaluate. */
|
|
152
|
-
const styleNow = style()
|
|
153
|
-
if (isActive() === false) {
|
|
154
|
-
return { [props.attributeName]: props.to }
|
|
155
|
-
}
|
|
156
|
-
if (!props.canBegin) {
|
|
157
|
-
return { [props.attributeName]: props.from }
|
|
158
|
-
}
|
|
159
|
-
if (initialized) {
|
|
160
|
-
return {
|
|
161
|
-
transition: getTransitionVal([props.attributeName], props.duration, props.easing),
|
|
162
|
-
[props.attributeName]: styleNow,
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
return { [props.attributeName]: props.from }
|
|
166
|
-
})
|
|
167
|
-
|
|
168
|
-
/* eslint-disable-next-line solid/reactivity -- one-time children() call keeps element identity; childStyle is reactive */
|
|
169
|
-
return untrack(() => props.children(childStyle))
|
|
170
|
-
}
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import { createMemo, createSignal, untrack, createEffect } from "solid-js"
|
|
2
|
-
import type { JSX } from "@solidjs/web"
|
|
3
|
-
import { createEasingFunction } from "./easing"
|
|
4
|
-
import type { EasingInput } from "./easing"
|
|
5
|
-
import { useAnimationController } from "./useAnimationController"
|
|
6
|
-
import { resolveIsAnimationActive, usePrefersReducedMotion } from "../util/usePrefersReducedMotion"
|
|
7
|
-
import { JavascriptAnimation } from "./AnimationHandle"
|
|
8
|
-
import { RequestAnimationFrameTimeoutController } from "./timeoutController"
|
|
9
|
-
import type { AnimationController } from "./AnimationController"
|
|
10
|
-
|
|
11
|
-
import { mergeProps } from "../util/solid-1-compat"
|
|
12
|
-
type JavascriptAnimateProps = {
|
|
13
|
-
animationController?: AnimationController
|
|
14
|
-
animationId: string
|
|
15
|
-
begin?: number
|
|
16
|
-
canBegin?: boolean
|
|
17
|
-
/* Children receives an Accessor<number> instead of a plain number. Solid
|
|
18
|
-
evaluates the children fn ONCE at setup and the returned JSX is mounted
|
|
19
|
-
stable across animation ticks; reading `t()` inside reactive attribute
|
|
20
|
-
slots (e.g. `<path d={getD(t())}/>`) updates only the attribute, not the
|
|
21
|
-
element identity. Plain-value children gets re-instantiated every tick,
|
|
22
|
-
replacing the DOM node on each render — tests holding a captured DOM ref
|
|
23
|
-
see stale attributes. */
|
|
24
|
-
children: (time: () => number) => JSX.Element
|
|
25
|
-
duration?: number
|
|
26
|
-
easing?: EasingInput
|
|
27
|
-
isActive?: boolean | "auto"
|
|
28
|
-
onAnimationEnd?: () => void
|
|
29
|
-
onAnimationStart?: () => void
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const defaultJavascriptAnimateProps = {
|
|
33
|
-
begin: 0,
|
|
34
|
-
canBegin: true,
|
|
35
|
-
duration: 1000,
|
|
36
|
-
easing: "ease",
|
|
37
|
-
isActive: true,
|
|
38
|
-
onAnimationEnd: () => {},
|
|
39
|
-
onAnimationStart: () => {},
|
|
40
|
-
} as const satisfies Partial<JavascriptAnimateProps>
|
|
41
|
-
|
|
42
|
-
const from = 0
|
|
43
|
-
const to = 1
|
|
44
|
-
|
|
45
|
-
export function JavascriptAnimate(outsideProps: JavascriptAnimateProps) {
|
|
46
|
-
/* mergeProps preserves the props proxy lazily so child callbacks and
|
|
47
|
-
* downstream toggles (isActive, canBegin) stay reactive. resolveDefaultProps
|
|
48
|
-
* would freeze them at setup — see GOTCHA-005-C. */
|
|
49
|
-
const props = mergeProps(defaultJavascriptAnimateProps, outsideProps)
|
|
50
|
-
|
|
51
|
-
const prefersReducedMotion = usePrefersReducedMotion()
|
|
52
|
-
const isActive = createMemo(() => resolveIsAnimationActive(props.isActive, prefersReducedMotion))
|
|
53
|
-
|
|
54
|
-
const animationController = useAnimationController(() => props.animationController)
|
|
55
|
-
|
|
56
|
-
/* Each committed frame is tagged with the animation that produced it. When
|
|
57
|
-
animationId flips, the previous animation's frame no longer applies and
|
|
58
|
-
time reads `from` immediately, the same as upstream remounting
|
|
59
|
-
JavascriptAnimate via `key={animationId}`; no stale `t=1` frame leaks into
|
|
60
|
-
the new animation's first render (GOTCHA-014-G). */
|
|
61
|
-
const [frame, setFrame] = createSignal<{ animationId: string; t: number }>(
|
|
62
|
-
untrack(() => ({ animationId: props.animationId, t: isActive() ? from : to })),
|
|
63
|
-
)
|
|
64
|
-
const time = createMemo(() => {
|
|
65
|
-
if (!isActive()) {
|
|
66
|
-
return to
|
|
67
|
-
}
|
|
68
|
-
const current = frame()
|
|
69
|
-
return current.animationId === props.animationId ? current.t : from
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
createEffect(
|
|
73
|
-
() =>
|
|
74
|
-
isActive() === false || !props.canBegin
|
|
75
|
-
? null
|
|
76
|
-
: {
|
|
77
|
-
animationId: props.animationId,
|
|
78
|
-
begin: props.begin,
|
|
79
|
-
controller: animationController(),
|
|
80
|
-
duration: props.duration,
|
|
81
|
-
easing: props.easing,
|
|
82
|
-
onAnimationEnd: props.onAnimationEnd,
|
|
83
|
-
onAnimationStart: props.onAnimationStart,
|
|
84
|
-
},
|
|
85
|
-
(run) => {
|
|
86
|
-
if (run == null) {
|
|
87
|
-
return undefined
|
|
88
|
-
}
|
|
89
|
-
const easingFunction = createEasingFunction(run.easing)
|
|
90
|
-
if (easingFunction == null) {
|
|
91
|
-
return undefined
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const animation = new JavascriptAnimation({
|
|
95
|
-
animationBegin: run.begin,
|
|
96
|
-
animationDuration: run.duration,
|
|
97
|
-
animationId: run.animationId,
|
|
98
|
-
easing: easingFunction,
|
|
99
|
-
from,
|
|
100
|
-
onAnimationEnd: run.onAnimationEnd,
|
|
101
|
-
onAnimationStart: run.onAnimationStart,
|
|
102
|
-
to,
|
|
103
|
-
})
|
|
104
|
-
|
|
105
|
-
return run.controller(new RequestAnimationFrameTimeoutController(), animation, (value) =>
|
|
106
|
-
setFrame({ animationId: run.animationId, t: Number(value) }),
|
|
107
|
-
)
|
|
108
|
-
},
|
|
109
|
-
)
|
|
110
|
-
|
|
111
|
-
/* perf: invoke children ONCE at setup. The `time` accessor is
|
|
112
|
-
reactive on its own, so consumers reading `t()` inside their createMemo
|
|
113
|
-
subscribe to the frame signal directly. Building the subtree at setup and
|
|
114
|
-
returning it directly lets attribute bindings update in place instead of
|
|
115
|
-
re-creating every computation inside the children thunk per tick. */
|
|
116
|
-
/* eslint-disable-next-line solid/reactivity -- intentional one-time children() call at setup for perf (see comment above); time is a reactive accessor */
|
|
117
|
-
const subtree = props.children(time)
|
|
118
|
-
return subtree
|
|
119
|
-
}
|
package/src/animation/easing.ts
DELETED
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
export const ACCURACY = 1e-4
|
|
2
|
-
|
|
3
|
-
const cubicBezierFactor = (c1: number, c2: number) => [0, 3 * c1, 3 * c2 - 6 * c1, 3 * c1 - 3 * c2 + 1]
|
|
4
|
-
|
|
5
|
-
const evaluatePolynomial = (params: ReadonlyArray<number>, animationElapsedTime: number) =>
|
|
6
|
-
params.map((param, i) => param * animationElapsedTime ** i).reduce((pre, curr) => pre + curr)
|
|
7
|
-
|
|
8
|
-
const cubicBezier = (c1: number, c2: number) => (animationElapsedTime: number) => {
|
|
9
|
-
const params = cubicBezierFactor(c1, c2)
|
|
10
|
-
|
|
11
|
-
return evaluatePolynomial(params, animationElapsedTime)
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const derivativeCubicBezier = (c1: number, c2: number) => (animationElapsedTime: number) => {
|
|
15
|
-
const params = cubicBezierFactor(c1, c2)
|
|
16
|
-
const newParams = [...params.map((param, i) => param * i).slice(1), 0]
|
|
17
|
-
|
|
18
|
-
return evaluatePolynomial(newParams, animationElapsedTime)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
type CubicBezierTemplate = `cubic-bezier(${number},${number},${number},${number})`
|
|
22
|
-
|
|
23
|
-
export type NamedBezier = "linear" | "ease" | "ease-in" | "ease-out" | "ease-in-out" | CubicBezierTemplate
|
|
24
|
-
|
|
25
|
-
type BezierInput = [NamedBezier] | [number, number, number, number]
|
|
26
|
-
|
|
27
|
-
export type BezierEasingFunction = {
|
|
28
|
-
isStepper: false
|
|
29
|
-
(animationElapsedTime: number): number
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const parseCubicBezier = (easing: string): [number, number, number, number] | null => {
|
|
33
|
-
const easingParts = easing.split("(")
|
|
34
|
-
if (easingParts.length !== 2 || easingParts[0] !== "cubic-bezier") {
|
|
35
|
-
return null
|
|
36
|
-
}
|
|
37
|
-
const numbers = easingParts[1]?.split(")")[0]?.split(",")
|
|
38
|
-
if (numbers == null || numbers.length !== 4) {
|
|
39
|
-
return null
|
|
40
|
-
}
|
|
41
|
-
const coords = numbers.map((x: string) => parseFloat(x))
|
|
42
|
-
return [coords[0] as number, coords[1] as number, coords[2] as number, coords[3] as number]
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const getBezierCoordinates = (...args: BezierInput): [number, number, number, number] => {
|
|
46
|
-
if (args.length === 1) {
|
|
47
|
-
switch (args[0]) {
|
|
48
|
-
case "linear":
|
|
49
|
-
return [0.0, 0.0, 1.0, 1.0]
|
|
50
|
-
case "ease":
|
|
51
|
-
return [0.25, 0.1, 0.25, 1.0]
|
|
52
|
-
case "ease-in":
|
|
53
|
-
return [0.42, 0.0, 1.0, 1.0]
|
|
54
|
-
case "ease-out":
|
|
55
|
-
return [0.42, 0.0, 0.58, 1.0]
|
|
56
|
-
case "ease-in-out":
|
|
57
|
-
return [0.0, 0.0, 0.58, 1.0]
|
|
58
|
-
default: {
|
|
59
|
-
const easing = parseCubicBezier(args[0])
|
|
60
|
-
if (easing) {
|
|
61
|
-
return easing
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (args.length === 4) {
|
|
68
|
-
return args
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Fallback for invalid inputs. The previous implementation was buggy and would lead to NaN.
|
|
72
|
-
// Returning linear easing is a safe default.
|
|
73
|
-
return [0.0, 0.0, 1.0, 1.0]
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const createBezierEasing = (x1: number, y1: number, x2: number, y2: number): BezierEasingFunction => {
|
|
77
|
-
const curveX = cubicBezier(x1, x2)
|
|
78
|
-
const curveY = cubicBezier(y1, y2)
|
|
79
|
-
const derCurveX = derivativeCubicBezier(x1, x2)
|
|
80
|
-
const rangeValue = (value: number): number => {
|
|
81
|
-
if (value > 1) {
|
|
82
|
-
return 1
|
|
83
|
-
}
|
|
84
|
-
if (value < 0) {
|
|
85
|
-
return 0
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
return value
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const bezier = (_animationElapsedTime: number) => {
|
|
92
|
-
const animationElapsedTime = _animationElapsedTime > 1 ? 1 : _animationElapsedTime
|
|
93
|
-
let x = animationElapsedTime
|
|
94
|
-
|
|
95
|
-
for (let i = 0; i < 8; ++i) {
|
|
96
|
-
const evalT = curveX(x) - animationElapsedTime
|
|
97
|
-
const derVal = derCurveX(x)
|
|
98
|
-
|
|
99
|
-
if (Math.abs(evalT - animationElapsedTime) < ACCURACY || derVal < ACCURACY) {
|
|
100
|
-
return curveY(x)
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
x = rangeValue(x - evalT / derVal)
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return curveY(x)
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
bezier.isStepper = false as const
|
|
110
|
-
|
|
111
|
-
return bezier
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// calculate cubic-bezier using Newton's method
|
|
115
|
-
export const configBezier = (...args: BezierInput): BezierEasingFunction => {
|
|
116
|
-
return createBezierEasing(...getBezierCoordinates(...args))
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
type SpringInput = {
|
|
120
|
-
/**
|
|
121
|
-
* The stiffness coefficient of the spring.
|
|
122
|
-
* Higher values create a more forceful, faster pull towards the target.
|
|
123
|
-
*/
|
|
124
|
-
stiff?: number
|
|
125
|
-
/**
|
|
126
|
-
* The damping coefficient (friction/resistance).
|
|
127
|
-
* Higher values reduce bounciness and stop oscillation sooner. Lower values create more bounce.
|
|
128
|
-
*/
|
|
129
|
-
damping?: number
|
|
130
|
-
/**
|
|
131
|
-
* The physics simulation time step in milliseconds.
|
|
132
|
-
* Determines the granularity of the baked frames. 16.67ms roughly equals a 60fps frame delta.
|
|
133
|
-
*/
|
|
134
|
-
dt?: number
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Creates a performance-optimized, progress-based spring easing function.
|
|
139
|
-
* It pre-calculates ("bakes") spring physics frames upfront based on a fixed duration,
|
|
140
|
-
* then returns a pure, lightweight function mapping progress (0 to 1) to the animated position.
|
|
141
|
-
* This approach is ideal for low-power devices because it removes heavy physics math from the frame loop.
|
|
142
|
-
*/
|
|
143
|
-
export const createSpringEasing = (config: SpringInput = {}): EasingFunction => {
|
|
144
|
-
const { stiff = 100, damping = 8, dt = 16.67 } = config
|
|
145
|
-
const destX = 1
|
|
146
|
-
|
|
147
|
-
const positions: number[] = [0]
|
|
148
|
-
let currX = 0
|
|
149
|
-
let currV = 0
|
|
150
|
-
|
|
151
|
-
// Safety valve to prevent accidental infinite loops if physics config is extreme
|
|
152
|
-
const maxIterations = 10000
|
|
153
|
-
let iterations = 0
|
|
154
|
-
|
|
155
|
-
// 1. Run the simulation until the spring completely stops moving
|
|
156
|
-
while (iterations < maxIterations) {
|
|
157
|
-
const FSpring = -(currX - destX) * stiff
|
|
158
|
-
const FDamping = currV * damping
|
|
159
|
-
|
|
160
|
-
currV += ((FSpring - FDamping) * dt) / 1000
|
|
161
|
-
currX += (currV * dt) / 1000
|
|
162
|
-
|
|
163
|
-
positions.push(currX)
|
|
164
|
-
|
|
165
|
-
// Stop only when position is essentially at 1.0 AND bounce velocity has died down
|
|
166
|
-
if (Math.abs(currX - destX) < ACCURACY && Math.abs(currV) < ACCURACY) {
|
|
167
|
-
break
|
|
168
|
-
}
|
|
169
|
-
iterations++
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// Force the absolute final element to be exactly 1.0 for a perfect finish
|
|
173
|
-
positions[positions.length - 1] = destX
|
|
174
|
-
const maxIndex = positions.length - 1
|
|
175
|
-
|
|
176
|
-
// 2. The ultra-smooth runtime function mapping your 0..1 progress
|
|
177
|
-
return (t: number): number => {
|
|
178
|
-
if (t <= 0) return 0
|
|
179
|
-
if (t >= 1) return destX
|
|
180
|
-
|
|
181
|
-
// Scale t (0..1) proportionally across our entire pre-calculated array
|
|
182
|
-
const exactFrame = t * maxIndex
|
|
183
|
-
const index = Math.floor(exactFrame)
|
|
184
|
-
const fraction = exactFrame - index
|
|
185
|
-
|
|
186
|
-
// Blend between the two closest frames
|
|
187
|
-
return (positions[index] ?? 0) + ((positions[index + 1] ?? 0) - (positions[index] ?? 0)) * fraction
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
export type EasingFunction = (t: number) => number
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* @inline
|
|
195
|
-
*/
|
|
196
|
-
export type EasingInput = NamedBezier | "spring" | EasingFunction
|
|
197
|
-
|
|
198
|
-
export const createEasingFunction = (easing: EasingInput): EasingFunction | null => {
|
|
199
|
-
if (typeof easing === "string") {
|
|
200
|
-
switch (easing) {
|
|
201
|
-
case "ease":
|
|
202
|
-
case "ease-in-out":
|
|
203
|
-
case "ease-out":
|
|
204
|
-
case "ease-in":
|
|
205
|
-
case "linear":
|
|
206
|
-
return configBezier(easing)
|
|
207
|
-
case "spring":
|
|
208
|
-
return createSpringEasing()
|
|
209
|
-
default:
|
|
210
|
-
if (easing.split("(")[0] === "cubic-bezier") {
|
|
211
|
-
return configBezier(easing)
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
if (typeof easing === "function") {
|
|
217
|
-
return easing
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
return null
|
|
221
|
-
}
|
package/src/animation/matchBy.ts
DELETED
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
import { getValueByDataKey } from "../util/ChartUtils"
|
|
2
|
-
import type { DataKey } from "../util/types"
|
|
3
|
-
import type {
|
|
4
|
-
AnimationItem,
|
|
5
|
-
AnimationMatchBy,
|
|
6
|
-
AnimationMatchByProp,
|
|
7
|
-
} from "../state/types/AnimationSettings"
|
|
8
|
-
|
|
9
|
-
export type { AnimationItem, AnimationMatchBy, AnimationMatchByProp }
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Match animation items by their array index (the default behavior).
|
|
13
|
-
*
|
|
14
|
-
* Previous items are paired with next items based on their position
|
|
15
|
-
* in the array, with proportional stretching when array lengths differ.
|
|
16
|
-
*
|
|
17
|
-
* @since 3.9
|
|
18
|
-
*/
|
|
19
|
-
export const matchByIndex = "index" as const
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Match animation items sequentially: previous item 0 pairs with next item 0,
|
|
23
|
-
* previous item 1 pairs with next item 1, and so on. Extra next items animate in;
|
|
24
|
-
* extra previous items are dropped.
|
|
25
|
-
*
|
|
26
|
-
* @since 3.9
|
|
27
|
-
*/
|
|
28
|
-
export const matchAppend = "append" as const
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Create a matching function that pairs items by a data key from their payload.
|
|
32
|
-
*
|
|
33
|
-
* @since 3.9
|
|
34
|
-
*/
|
|
35
|
-
export function matchByDataKey(
|
|
36
|
-
dataKey: DataKey<Record<string, unknown>>,
|
|
37
|
-
): AnimationMatchBy<{ payload?: unknown }> {
|
|
38
|
-
return (item: { payload?: unknown }): string | number | null => {
|
|
39
|
-
if (item.payload == null || typeof item.payload !== "object") {
|
|
40
|
-
return null
|
|
41
|
-
}
|
|
42
|
-
const value = getValueByDataKey(item.payload as Record<string, unknown>, dataKey)
|
|
43
|
-
if (value == null) {
|
|
44
|
-
return null
|
|
45
|
-
}
|
|
46
|
-
if (typeof value === "string" || typeof value === "number") {
|
|
47
|
-
return value
|
|
48
|
-
}
|
|
49
|
-
return JSON.stringify(value)
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function tagAlignedItems<T>(
|
|
54
|
-
alignedPrevItems: ReadonlyArray<T | undefined>,
|
|
55
|
-
nextItems: ReadonlyArray<T>,
|
|
56
|
-
removedPrevItems: ReadonlyArray<T> = [],
|
|
57
|
-
): ReadonlyArray<AnimationItem<T>> {
|
|
58
|
-
const tagged: Array<AnimationItem<T>> = []
|
|
59
|
-
for (const prev of removedPrevItems) {
|
|
60
|
-
tagged.push({ status: "removed", prev })
|
|
61
|
-
}
|
|
62
|
-
for (let i = 0; i < nextItems.length; i++) {
|
|
63
|
-
const prev = alignedPrevItems[i]
|
|
64
|
-
/* i is within bounds; noUncheckedIndexedAccess cannot see that */
|
|
65
|
-
const next = nextItems[i] as T
|
|
66
|
-
if (prev != null) {
|
|
67
|
-
tagged.push({ status: "matched", prev, next })
|
|
68
|
-
} else {
|
|
69
|
-
tagged.push({ status: "added", next })
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
return tagged
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function matchByIndexImpl<T>(
|
|
76
|
-
prevItems: ReadonlyArray<T>,
|
|
77
|
-
nextItems: ReadonlyArray<T>,
|
|
78
|
-
): ReadonlyArray<AnimationItem<T>> {
|
|
79
|
-
const factor = prevItems.length / nextItems.length
|
|
80
|
-
const alignedPrevItems = nextItems.map((_, i) => prevItems[Math.floor(i * factor)])
|
|
81
|
-
return tagAlignedItems(alignedPrevItems, nextItems)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
function matchAppendImpl<T>(
|
|
85
|
-
prevItems: ReadonlyArray<T>,
|
|
86
|
-
nextItems: ReadonlyArray<T>,
|
|
87
|
-
): ReadonlyArray<AnimationItem<T>> {
|
|
88
|
-
const alignedPrevItems = nextItems.map((_, i) => prevItems[i])
|
|
89
|
-
return tagAlignedItems(alignedPrevItems, nextItems)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function buildPrevKeyMap<T>(
|
|
93
|
-
prevItems: ReadonlyArray<T>,
|
|
94
|
-
matchBy: AnimationMatchBy<T>,
|
|
95
|
-
): ReadonlyMap<string | number, T> {
|
|
96
|
-
const prevMap = new Map<string | number, T>()
|
|
97
|
-
for (let i = 0; i < prevItems.length; i++) {
|
|
98
|
-
const item = prevItems[i]
|
|
99
|
-
if (item == null) {
|
|
100
|
-
continue
|
|
101
|
-
}
|
|
102
|
-
const key = matchBy(item, i)
|
|
103
|
-
if (key != null && !prevMap.has(key)) {
|
|
104
|
-
prevMap.set(key, item)
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
return prevMap
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
function matchByKey<T>(
|
|
111
|
-
prevItems: ReadonlyArray<T>,
|
|
112
|
-
nextItems: ReadonlyArray<T>,
|
|
113
|
-
matchBy: AnimationMatchBy<T>,
|
|
114
|
-
): ReadonlyArray<AnimationItem<T>> {
|
|
115
|
-
const prevMap = buildPrevKeyMap(prevItems, matchBy)
|
|
116
|
-
const matchedKeys = new Set<string | number>()
|
|
117
|
-
|
|
118
|
-
const alignedPrevItems = nextItems.map((next, i) => {
|
|
119
|
-
const key = matchBy(next, i)
|
|
120
|
-
if (key != null) {
|
|
121
|
-
const prev = prevMap.get(key)
|
|
122
|
-
if (prev !== undefined) {
|
|
123
|
-
matchedKeys.add(key)
|
|
124
|
-
return prev
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
return undefined
|
|
128
|
-
})
|
|
129
|
-
|
|
130
|
-
const removedPrevItems: Array<T> = []
|
|
131
|
-
for (const [key, item] of prevMap) {
|
|
132
|
-
if (!matchedKeys.has(key)) {
|
|
133
|
-
removedPrevItems.push(item)
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
return tagAlignedItems(alignedPrevItems, nextItems, removedPrevItems)
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Match previous items to next items using the given matching strategy.
|
|
142
|
-
*
|
|
143
|
-
* On first render, all next items are returned as `{ status: 'added' }`.
|
|
144
|
-
* For key-based matching, unmatched previous items are `{ status: 'removed' }`.
|
|
145
|
-
*/
|
|
146
|
-
export function matchAnimationItems<T>(
|
|
147
|
-
prevItems: ReadonlyArray<T> | null,
|
|
148
|
-
nextItems: ReadonlyArray<T> | undefined,
|
|
149
|
-
matchBy: AnimationMatchByProp<T>,
|
|
150
|
-
): ReadonlyArray<AnimationItem<T>> | null {
|
|
151
|
-
if (nextItems == null) {
|
|
152
|
-
return null
|
|
153
|
-
}
|
|
154
|
-
if (prevItems == null) {
|
|
155
|
-
return nextItems.map((next) => ({ status: "added" as const, next }))
|
|
156
|
-
}
|
|
157
|
-
if (matchBy === matchByIndex) {
|
|
158
|
-
return matchByIndexImpl(prevItems, nextItems)
|
|
159
|
-
}
|
|
160
|
-
if (matchBy === matchAppend) {
|
|
161
|
-
return matchAppendImpl(prevItems, nextItems)
|
|
162
|
-
}
|
|
163
|
-
return matchByKey(prevItems, nextItems, matchBy)
|
|
164
|
-
}
|