UNPKG

@vtex/styleguide

Version:

> VTEX Styleguide React components ([Docs](https://vtex.github.io/styleguide))

227 lines (183 loc) 7.06 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _react = require("react"); var _react2 = _interopRequireDefault(_react); var _propTypes = require("prop-types"); var _propTypes2 = _interopRequireDefault(_propTypes); var _CaretDown = require("../icon/CaretDown"); var _CaretDown2 = _interopRequireDefault(_CaretDown); var _CaretUp = require("../icon/CaretUp"); var _CaretUp2 = _interopRequireDefault(_CaretUp); var _styles = require("./styles.css"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } var colorMap = { base: 'c-on-base', primary: 'c-action-primary', muted: 'c-muted-3' }; function handleClick(callback, isOpen) { callback && callback({ target: { isOpen: isOpen } }); } function mapToCSSClass(color) { return colorMap[color]; } var Collapsible = /*#__PURE__*/ function (_Component) { _inheritsLoose(Collapsible, _Component); function Collapsible(props) { var _this; _this = _Component.call(this, props) || this; _this.handleTransitionEnd = function () { var _this$props = _this.props, isOpen = _this$props.isOpen, isOverflowHidden = _this$props.isOverflowHidden; _this.setState({ height: isOpen ? 'auto' : 0 }); if (isOpen && !isOverflowHidden) { _this.childrenRef.current.style.removeProperty('overflow'); } }; _this.openCard = function () { _this.childrenRef.current.style.height = 'auto'; var childrenHeight = _this.childrenRef.current.offsetHeight; _this.childrenRef.current.style.height = 0; /** after force setting element height like the line above * you have to force layout / reflow so the height value * may actually apply. You can do this by requesting * element offsetHeight again, like the line below */ _this.childrenRef.current.offsetHeight; _this.setState({ height: childrenHeight }); }; _this.closeCard = function () { var childrenHeight = _this.childrenRef.current.offsetHeight; _this.childrenRef.current.style.setProperty('overflow', 'hidden'); _this.setState({ height: childrenHeight }, function () { window.requestAnimationFrame(function () { return _this.setState({ height: 0 }); }); }); }; _this.childrenRef = _react2.default.createRef(); _this.openTimeout = null; _this.closeTimeout = null; _this.state = { height: 0 }; return _this; } var _proto = Collapsible.prototype; _proto.componentDidMount = function componentDidMount() { if (this.props.isOpen) { this.setState({ height: 'auto' }); } }; _proto.componentDidUpdate = function componentDidUpdate(prevProps) { if (prevProps.isOpen !== this.props.isOpen) { if (this.props.isOpen) { this.openCard(); } else { this.closeCard(); } } }; _proto.render = function render() { var _this$props2 = this.props, align = _this$props2.align, children = _this$props2.children, header = _this$props2.header, muted = _this$props2.muted, callback = _this$props2.onClick, isOpen = _this$props2.isOpen, arrowAlign = _this$props2.arrowAlign, isOverflowHidden = _this$props2.isOverflowHidden; var caretColor = this.props.caretColor; var height = this.state.height; var childrenContainerStyle = { height: height, overflow: !isOverflowHidden && isOpen ? 'none' : 'hidden', transition: 'height 250ms ease-in-out' }; if (muted) { caretColor = caretColor || 'muted'; console.warn("The \"muted\" prop on the \"Collapsible\" component is depreacted and will be removed in a future version. Use \"caretColor='muted'\" instead."); } var color = caretColor ? mapToCSSClass(caretColor) : 'c-action-primary'; return _react2.default.createElement("div", { className: _styles.jsFocusVisible }, _react2.default.createElement("div", { className: "flex flex-row items-center pointer", tabIndex: 0, role: "button", onClick: function onClick() { return handleClick(callback, !isOpen); }, onKeyDown: function onKeyDown(e) { return e.key === 'Enter' && handleClick(callback, !isOpen); }, "aria-expanded": isOpen }, align === 'left' ? _react2.default.createElement(_react.Fragment, null, _react2.default.createElement("div", { className: color + " mr3 self-" + arrowAlign }, isOpen ? _react2.default.createElement(_CaretUp2.default, null) : _react2.default.createElement(_CaretDown2.default, null)), _react2.default.createElement("div", { className: "flex-grow-1" }, header)) : _react2.default.createElement(_react.Fragment, null, _react2.default.createElement("div", { className: "flex-grow-1" }, header), _react2.default.createElement("div", { className: color + " ml3 self-" + arrowAlign }, isOpen ? _react2.default.createElement(_CaretUp2.default, null) : _react2.default.createElement(_CaretDown2.default, null)))), _react2.default.createElement("div", { ref: this.childrenRef, style: childrenContainerStyle, role: "region", onTransitionEnd: this.handleTransitionEnd }, children)); }; return Collapsible; }(_react.Component); Collapsible.defaultProps = { align: 'left', isOpen: false, muted: false, arrowAlign: 'center', isOverflowHidden: true }; Collapsible.propTypes = { /** Caret alignment. * Use _right_ alignment only in small width scenarios. */ align: _propTypes2.default.oneOf(['right', 'left']), /** Content of the collapsible */ children: _propTypes2.default.node.isRequired, /** Component to be used as the header of the collapsible. */ header: _propTypes2.default.node.isRequired, /** @deprecated Use the 'muted' option in the caretColor prop instead. * To be used only in dense scenarios, or when the affordance is clearly * conveyed by the context. */ muted: _propTypes2.default.bool, /** Controls whether the collapsible is open or not. */ isOpen: _propTypes2.default.bool, /** _onClick_ event. */ onClick: _propTypes2.default.func, /** Color or semantic to be applied to the Caret Icon in the Collapsible header.*/ caretColor: _propTypes2.default.oneOf(Object.keys(colorMap)), /** Vertical position of arrow icon.*/ arrowAlign: _propTypes2.default.oneOf(['start', 'center', 'end', 'baseline', 'stretch']), /** Controls whether the collapsible should hide overflowing components. (e.g. Turn the overflow off to avoid popup menus in the childen component to be cropped.)*/ isOverflowHidden: _propTypes2.default.bool }; exports.default = Collapsible;