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

86 lines
1.8 KiB
TypeScript

import React, { Component } from 'react';
import { Motion, spring } from 'react-motion';
import MeasureHeight from 'app/components/MeasureHeight';
import styles from './collapse.scss';
type Props = {
isOpened?: boolean;
children: React.ReactNode;
onRest: () => void;
};
export default class Collapse extends Component<
Props,
{
height: number;
wasInitialized: boolean;
}
> {
state = {
height: 0,
wasInitialized: false,
};
static defaultProps = {
onRest: () => {},
};
componentWillReceiveProps(nextProps: Props) {
if (
this.props.isOpened !== nextProps.isOpened &&
!this.state.wasInitialized
) {
this.setState({
wasInitialized: true,
});
}
}
render() {
const { isOpened, children, onRest } = this.props;
const { height, wasInitialized } = this.state;
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>
);
}
onUpdateHeight = (height: number) => {
this.setState({
height,
});
};
shouldMeasureHeight = () => {
return [this.props.isOpened, this.state.wasInitialized].join('');
};
}