accounts-frontend/packages/app/components/ui/collapse/Collapse.tsx

81 lines
2.3 KiB
TypeScript
Raw Normal View History

import React, { Component } from 'react';
import { Motion, spring } from 'react-motion';
import MeasureHeight from 'app/components/MeasureHeight';
import styles from './collapse.scss';
2019-12-10 13:17:32 +05:30
interface Props {
2020-05-24 04:38:24 +05:30
isOpened?: boolean;
children: React.ReactNode;
onRest: () => void;
2019-12-10 13:17:32 +05:30
}
2019-12-10 13:17:32 +05:30
interface State {
2020-05-24 04:38:24 +05:30
isOpened?: boolean; // just to track value for derived updates
height: number;
wasInitialized: boolean;
2019-12-10 13:17:32 +05:30
}
export default class Collapse extends Component<Props, State> {
2020-05-24 04:38:24 +05:30
state = {
isOpened: this.props.isOpened,
height: 0,
wasInitialized: false,
};
2020-05-24 04:38:24 +05:30
static defaultProps: Partial<Props> = {
onRest: () => {},
};
2020-05-24 04:38:24 +05:30
static getDerivedStateFromProps(props: Props, state: State) {
if (props.isOpened !== state.isOpened && !state.wasInitialized) {
return {
isOpened: props.isOpened,
wasInitialized: true,
};
}
2019-12-10 13:17:32 +05:30
2020-05-24 04:38:24 +05:30
return null;
}
2020-05-24 04:38:24 +05:30
render() {
const { isOpened, children, onRest } = this.props;
const { height, wasInitialized } = this.state;
2020-05-24 04:38:24 +05:30
return (
<div className={styles.overflow} style={wasInitialized ? {} : { height: 0 }}>
<MeasureHeight state={this.shouldMeasureHeight()} onMeasure={this.onUpdateHeight}>
<Motion
style={{
top: wasInitialized ? spring(isOpened ? 0 : -height) : -height,
}}
onRest={onRest}
>
{({ top }) => (
<div
className={styles.content}
style={{
marginTop: top,
visibility: wasInitialized ? 'inherit' : 'hidden',
}}
>
{children}
</div>
)}
</Motion>
</MeasureHeight>
</div>
);
}
2020-05-24 04:38:24 +05:30
onUpdateHeight = (height: number) => {
this.setState({
height,
});
};
2020-05-24 04:38:24 +05:30
shouldMeasureHeight = () => {
return [this.props.isOpened, this.state.wasInitialized].join('');
};
}