mirror of
https://github.com/actualbudget/actual.git
synced 2026-03-21 15:36:50 -05:00
* react-spring (10.0.0 -> ^10.0.3) * note * fix VRT * fix more animations * fix budget month colouring
114 lines
2.7 KiB
TypeScript
114 lines
2.7 KiB
TypeScript
import React, {
|
|
useCallback,
|
|
useContext,
|
|
useLayoutEffect,
|
|
useMemo,
|
|
useRef,
|
|
useState,
|
|
} from 'react';
|
|
import { animated, useSpring } from 'react-spring';
|
|
|
|
import { View } from '@actual-app/components/view';
|
|
import { css } from '@emotion/css';
|
|
|
|
import { addMonths, subMonths } from 'loot-core/shared/months';
|
|
|
|
import { MonthsContext } from './MonthsContext';
|
|
|
|
import { useBudgetComponents } from '.';
|
|
|
|
import { useResizeObserver } from '@desktop-client/hooks/useResizeObserver';
|
|
|
|
export function BudgetSummaries() {
|
|
const { months } = useContext(MonthsContext);
|
|
const [firstMonth] = months;
|
|
|
|
const [widthState, setWidthState] = useState(0);
|
|
const [styles, spring] = useSpring(
|
|
() => ({
|
|
from: { x: 0 },
|
|
config: { mass: 3, tension: 600, friction: 80 },
|
|
}),
|
|
[],
|
|
);
|
|
|
|
const containerRef = useResizeObserver<HTMLDivElement>(
|
|
useCallback(rect => {
|
|
setWidthState(rect.width);
|
|
}, []),
|
|
);
|
|
|
|
const prevMonth0 = useRef(firstMonth);
|
|
const allMonths = useMemo(() => {
|
|
const all = [...months];
|
|
all.unshift(subMonths(firstMonth, 1));
|
|
all.push(addMonths(months[months.length - 1], 1));
|
|
return all;
|
|
}, [months, firstMonth]);
|
|
const monthWidth = widthState / months.length;
|
|
|
|
useLayoutEffect(() => {
|
|
const prevMonth = prevMonth0.current;
|
|
const reversed = prevMonth > firstMonth;
|
|
const offsetX = monthWidth;
|
|
let from = reversed ? -offsetX * 2 : 0;
|
|
|
|
if (prevMonth !== allMonths[0] && prevMonth !== allMonths[2]) {
|
|
from = -offsetX;
|
|
}
|
|
|
|
const to = -offsetX;
|
|
if (from !== to) {
|
|
void spring.start({ from: { x: from }, to: { x: to } });
|
|
}
|
|
}, [spring, firstMonth, monthWidth, allMonths]);
|
|
|
|
useLayoutEffect(() => {
|
|
prevMonth0.current = firstMonth;
|
|
}, [firstMonth]);
|
|
|
|
useLayoutEffect(() => {
|
|
void spring.start({ to: { x: -monthWidth }, immediate: true });
|
|
}, [spring, monthWidth]);
|
|
|
|
const { SummaryComponent } = useBudgetComponents();
|
|
|
|
return (
|
|
<div
|
|
className={css([
|
|
{ flex: 1, overflow: 'hidden' },
|
|
months.length === 1 && {
|
|
marginLeft: -4,
|
|
marginRight: -4,
|
|
},
|
|
])}
|
|
ref={containerRef}
|
|
>
|
|
<animated.div
|
|
className="view"
|
|
style={{
|
|
flexDirection: 'row',
|
|
width: widthState,
|
|
willChange: 'transform',
|
|
transform: styles.x.to(x => `translateX(${x}px)`),
|
|
}}
|
|
>
|
|
{allMonths.map(month => {
|
|
return (
|
|
<View
|
|
key={month}
|
|
style={{
|
|
flex: `0 0 ${monthWidth}px`,
|
|
paddingLeft: 4,
|
|
paddingRight: 4,
|
|
}}
|
|
>
|
|
<SummaryComponent month={month} />
|
|
</View>
|
|
);
|
|
})}
|
|
</animated.div>
|
|
</div>
|
|
);
|
|
}
|