UNPKG

@kiwicom/orbit-components

Version:

Orbit-components is a React component library which provides developers with the easiest possible way of building Kiwi.com’s products.

182 lines (158 loc) 4.58 kB
import * as React from "react"; import styled from "styled-components"; import transition from "../transition"; import defaultTheme from "../../defaultTheme"; const getMaxHeight = ({ maxHeight }) => { if (maxHeight === 0) return `0px`; if (!maxHeight) return undefined; return `${maxHeight}px`; }; export const StyledSlide = styled.div.withConfig({ displayName: "Slide__StyledSlide", componentId: "sc-jio51l-0" })(["position:relative;width:100%;transition:", ";max-height:", ";overflow:", ";visibility:", ";"], ({ transitionDuration }) => transition(["max-height"], transitionDuration, "linear"), getMaxHeight, ({ transitionFinished }) => !transitionFinished && "hidden", ({ visible }) => !visible && "hidden"); // $FlowFixMe: https://github.com/flow-typed/flow-typed/issues/3653#issuecomment-568539198 StyledSlide.defaultProps = { theme: defaultTheme }; class Slide extends React.Component { constructor(...args) { super(...args); this.state = { maxHeight: typeof this.props.maxHeight !== "undefined" ? this.props.maxHeight : 0, transitionFinished: false, visible: false }; this.expandTimeout = null; this.collapseTimeout = null; this.transitionFinishedTimeout = null; this.visibleTimeout = null; this.setVisible = visible => () => { this.setState({ visible }); }; this.setMaxHeight = () => { const { maxHeight } = this.props; this.setState({ maxHeight }); }; this.expandCallback = () => { this.setState({ maxHeight: null }); this.transitionFinishedTimeout = setTimeout(this.transitionFinishedCallback(true), 100); }; this.collapseCallback = () => { this.setState({ maxHeight: 0, transitionFinished: false }); this.visibleTimeout = setTimeout(this.setVisible(false), 150); if (this.transitionFinishedTimeout && typeof clearTimeout === "function") { clearTimeout(this.transitionFinishedTimeout); this.transitionFinishedTimeout = null; } }; this.transitionFinishedCallback = transitionFinished => () => { this.setState({ transitionFinished }); }; } componentDidMount() { if (this.props.expanded) { this.setState({ transitionFinished: true, visible: true }); } } componentDidUpdate(prevProps, prevState, snapshot) { if (snapshot) { if (this.props.expanded) { this.setMaxHeight(); if (typeof setTimeout === "function") { if (this.visibleTimeout && typeof clearTimeout === "function") { clearTimeout(this.visibleTimeout); this.visibleTimeout = null; } this.setVisible(true)(); this.expandTimeout = setTimeout(this.expandCallback, 150); } } else { if (this.state.maxHeight !== this.props.maxHeight) { this.setMaxHeight(); } if (typeof setTimeout === "function") { if (this.expandTimeout && typeof clearTimeout === "function") { clearTimeout(this.expandTimeout); this.expandTimeout = null; } this.collapseTimeout = setTimeout(this.collapseCallback, 1); } } } } componentWillUnmount() { if (typeof clearTimeout === "function") { if (this.expandTimeout) { clearTimeout(this.expandTimeout); } if (this.collapseTimeout) { clearTimeout(this.collapseTimeout); } if (this.transitionFinishedTimeout) { clearTimeout(this.transitionFinishedTimeout); } if (this.visibleTimeout) { clearTimeout(this.visibleTimeout); } } } getSnapshotBeforeUpdate(prevProps) { if (this.props.expanded === prevProps.expanded) return null; return true; } render() { const { children, expanded = false, id, ariaLabelledBy, transitionDuration } = this.props; const { transitionFinished, maxHeight, visible } = this.state; return /*#__PURE__*/React.createElement(StyledSlide, { maxHeight: maxHeight, expanded: expanded, transitionFinished: transitionFinished, transitionDuration: transitionDuration, "aria-hidden": !expanded, id: id, "aria-labelledby": ariaLabelledBy, visible: visible, onClick: ev => { ev.stopPropagation(); } }, children); } } Slide.defaultProps = { transitionDuration: "fast" }; export default Slide;