UNPKG

@douyinfe/semi-ui

Version:

A modern, comprehensive, flexible design system and UI library. Connect DesignOps & DevOps. Quickly build beautiful React apps. Maintained by Douyin-fe team.

185 lines (184 loc) 6.97 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _pick2 = _interopRequireDefault(require("lodash/pick")); var _isEqual2 = _interopRequireDefault(require("lodash/isEqual")); var _react = _interopRequireDefault(require("react")); var _foundation = _interopRequireDefault(require("@douyinfe/semi-foundation/lib/cjs/collapsible/foundation")); var _baseComponent = _interopRequireDefault(require("../_base/baseComponent")); var _propTypes = _interopRequireDefault(require("prop-types")); var _classnames = _interopRequireDefault(require("classnames")); var _constants = require("@douyinfe/semi-foundation/lib/cjs/collapsible/constants"); require("@douyinfe/semi-foundation/lib/cjs/collapsible/collapsible.css"); var _utils = require("../_utils"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } class Collapsible extends _baseComponent.default { constructor(props) { super(props); this.domRef = /*#__PURE__*/_react.default.createRef(); this.hasBeenRendered = false; this.handleResize = entryList => { const entry = entryList[0]; if (entry) { const entryInfo = Collapsible.getEntryInfo(entry); this.foundation.updateDOMHeight(entryInfo.height); this.foundation.updateDOMInRenderTree(entryInfo.isShown); } }; this.isChildrenInRenderTree = () => { if (this.domRef.current) { return this.domRef.current.offsetHeight > 0; } return false; }; this.state = { domInRenderTree: false, domHeight: 0, visible: this.props.isOpen, isTransitioning: false }; this.foundation = new _foundation.default(this.adapter); } get adapter() { return Object.assign(Object.assign({}, super.adapter), { setDOMInRenderTree: domInRenderTree => { if (this.state.domInRenderTree !== domInRenderTree) { this.setState({ domInRenderTree }); } }, setDOMHeight: domHeight => { if (this.state.domHeight !== domHeight) { this.setState({ domHeight }); } }, setVisible: visible => { if (this.state.visible !== visible) { this.setState({ visible }); } }, setIsTransitioning: isTransitioning => { if (this.state.isTransitioning !== isTransitioning) { this.setState({ isTransitioning }); } } }); } componentDidMount() { super.componentDidMount(); this.resizeObserver = new ResizeObserver(this.handleResize); this.resizeObserver.observe(this.domRef.current); const domInRenderTree = this.isChildrenInRenderTree(); this.foundation.updateDOMInRenderTree(domInRenderTree); if (domInRenderTree) { this.foundation.updateDOMHeight(this.domRef.current.scrollHeight); } } componentDidUpdate(prevProps, prevState, snapshot) { const changedPropKeys = Object.keys((0, _pick2.default)(this.props, ['reCalcKey', "isOpen"])).filter(key => !(0, _isEqual2.default)(this.props[key], prevProps[key])); const changedStateKeys = Object.keys((0, _pick2.default)(this.state, ['domInRenderTree'])).filter(key => !(0, _isEqual2.default)(this.state[key], prevState[key])); if (changedPropKeys.includes("reCalcKey")) { this.foundation.updateDOMHeight(this.domRef.current.scrollHeight); } if (changedStateKeys.includes("domInRenderTree") && this.state.domInRenderTree) { this.foundation.updateDOMHeight(this.domRef.current.scrollHeight); } if (changedPropKeys.includes("isOpen")) { if (this.props.isOpen || !this.props.motion) { this.foundation.updateVisible(this.props.isOpen); } } if (this.props.motion && prevProps.isOpen !== this.props.isOpen) { this.foundation.updateIsTransitioning(true); } } componentWillUnmount() { super.componentWillUnmount(); this.resizeObserver.disconnect(); } render() { const wrapperStyle = Object.assign({ overflow: 'hidden', height: this.props.isOpen ? this.state.domHeight : this.props.collapseHeight, opacity: this.props.isOpen || !this.props.fade || this.props.collapseHeight !== 0 ? 1 : 0, transitionDuration: `${this.props.motion && this.state.isTransitioning ? this.props.duration : 0}ms` }, this.props.style); const wrapperCls = (0, _classnames.default)(`${_constants.cssClasses.PREFIX}-wrapper`, { [`${_constants.cssClasses.PREFIX}-transition`]: this.props.motion && this.state.isTransitioning }, this.props.className); const shouldRender = this.props.keepDOM && (this.props.lazyRender ? this.hasBeenRendered : true) || this.props.collapseHeight !== 0 || this.state.visible || this.props.isOpen; if (shouldRender && !this.hasBeenRendered) { this.hasBeenRendered = true; } return /*#__PURE__*/_react.default.createElement("div", Object.assign({ className: wrapperCls, style: wrapperStyle, onTransitionEnd: () => { var _a, _b; if (!this.props.isOpen) { this.foundation.updateVisible(false); } this.foundation.updateIsTransitioning(false); (_b = (_a = this.props).onMotionEnd) === null || _b === void 0 ? void 0 : _b.call(_a); } }, this.getDataAttr(this.props)), /*#__PURE__*/_react.default.createElement("div", { "x-semi-prop": "children", ref: this.domRef, style: { overflow: 'hidden' }, id: this.props.id }, shouldRender && this.props.children)); } } Collapsible.__SemiComponentName__ = "Collapsible"; Collapsible.defaultProps = (0, _utils.getDefaultPropsFromGlobalConfig)(Collapsible.__SemiComponentName__, { isOpen: false, duration: 250, motion: true, keepDOM: false, lazyRender: false, collapseHeight: 0, fade: false }); Collapsible.getEntryInfo = entry => { //judge whether parent or self display none let inRenderTree; if (entry.borderBoxSize) { inRenderTree = !(entry.borderBoxSize[0].blockSize === 0 && entry.borderBoxSize[0].inlineSize === 0); } else { inRenderTree = !(entry.contentRect.height === 0 && entry.contentRect.width === 0); } let height = 0; if (entry.borderBoxSize) { height = Math.ceil(entry.borderBoxSize[0].blockSize); } else { const target = entry.target; height = target.clientHeight; } return { isShown: inRenderTree, height }; }; Collapsible.propTypes = { motion: _propTypes.default.bool, children: _propTypes.default.node, isOpen: _propTypes.default.bool, duration: _propTypes.default.number, keepDOM: _propTypes.default.bool, collapseHeight: _propTypes.default.number, style: _propTypes.default.object, className: _propTypes.default.string, reCalcKey: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]) }; var _default = exports.default = Collapsible;