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.

124 lines (119 loc) 3.8 kB
import * as React from "react"; import styled, { css } from "styled-components"; import Heading from "../Heading"; import Stack from "../Stack"; import ButtonLink from "../ButtonLink"; import ChevronDown from "../icons/ChevronDown"; import Slide from "../utils/Slide"; import defaultTheme from "../defaultTheme"; import randomID from "../utils/randomID"; const AnimatedIcon = styled(ChevronDown).withConfig({ displayName: "Collapse__AnimatedIcon", componentId: "x5d7nf-0" })(["transition:transform ", " ease-in-out;", ";"], ({ theme }) => theme.orbit.durationFast, ({ expanded }) => expanded && css(["transform:rotate(180deg);"])); AnimatedIcon.defaultProps = { theme: defaultTheme }; const StyledCollapse = styled.div.withConfig({ displayName: "Collapse__StyledCollapse", componentId: "x5d7nf-1" })(["width:100%;display:block;border-bottom:1px solid ", ";padding-bottom:", ";margin-bottom:", ";:last-child,:only-child{border:0;margin:0;}"], ({ theme }) => theme.orbit.paletteCloudNormal, ({ theme }) => theme.orbit.spaceXLarge, ({ theme }) => theme.orbit.spaceXLarge); StyledCollapse.defaultProps = { theme: defaultTheme }; const StyledCollapseLabel = styled.div.withConfig({ displayName: "Collapse__StyledCollapseLabel", componentId: "x5d7nf-2" })(["width:100%;display:block;cursor:pointer;"]); const StyledCollapseChildren = styled.div.withConfig({ displayName: "Collapse__StyledCollapseChildren", componentId: "x5d7nf-3" })(["margin-top:", ";"], ({ theme }) => theme.orbit.spaceXSmall); StyledCollapseChildren.defaultProps = { theme: defaultTheme }; const Collapse = ({ initialExpanded = false, expanded: expandedProp, label, children, dataTest, onClick }) => { const isControlledComponent = React.useMemo(() => expandedProp != null, [expandedProp]); const [expandedState, setExpandedState] = React.useState(isControlledComponent ? expandedProp : initialExpanded); const expanded = isControlledComponent ? expandedProp : expandedState; const [contentHeight, setContentHeight] = React.useState(expanded ? null : 0); const node = React.useRef(null); React.useEffect(() => { const calculateHeight = () => { if (node && node.current) { const { height } = node.current.getBoundingClientRect(); setContentHeight(height); } }; calculateHeight(); window.addEventListener("resize", calculateHeight); return () => { window.removeEventListener("resize", calculateHeight); }; }, []); const slideID = React.useMemo(() => randomID("slideID"), []); const labelID = React.useMemo(() => randomID("labelID"), []); const handleClick = React.useCallback(event => { if (!isControlledComponent) { if (onClick) { onClick(event, !expanded); } setExpandedState(!expanded); } if (onClick) { onClick(event, !expanded); } }, [expanded, isControlledComponent, onClick]); return React.createElement(StyledCollapse, { "data-test": dataTest }, React.createElement(StyledCollapseLabel, { onClick: handleClick, role: "button", "aria-expanded": expanded, "aria-controls": slideID, id: labelID }, React.createElement(Stack, { direction: "row", justify: "between", align: "center" }, React.createElement(Heading, { type: "title4", element: "div" }, label), React.createElement(ButtonLink, { iconLeft: React.createElement(AnimatedIcon, { expanded: expanded }), transparent: true, size: "small", type: "secondary" }))), React.createElement(Slide, { maxHeight: contentHeight, expanded: expanded, id: slideID, ariaLabelledBy: labelID }, React.createElement(StyledCollapseChildren, { ref: node }, children))); }; export default Collapse;