UNPKG

6.78 kBJavaScriptView Raw
1import _extends from "@babel/runtime-corejs2/helpers/esm/extends";
2import _objectWithoutPropertiesLoose from "@babel/runtime-corejs2/helpers/esm/objectWithoutPropertiesLoose";
3import _inheritsLoose from "@babel/runtime-corejs2/helpers/esm/inheritsLoose";
4import _parseInt from "@babel/runtime-corejs2/core-js/parse-int";
5
6var _collapseStyles;
7
8import classNames from 'classnames';
9import css from 'dom-helpers/style';
10import React from 'react';
11import PropTypes from 'prop-types';
12import Transition, { EXITED, ENTERED, ENTERING, EXITING } from 'react-transition-group/Transition';
13import capitalize from './utils/capitalize';
14import createChainedFunction from './utils/createChainedFunction';
15var MARGINS = {
16 height: ['marginTop', 'marginBottom'],
17 width: ['marginLeft', 'marginRight']
18}; // reading a dimension prop will cause the browser to recalculate,
19// which will let our animations work
20
21function triggerBrowserReflow(node) {
22 node.offsetHeight; // eslint-disable-line no-unused-expressions
23}
24
25function getDimensionValue(dimension, elem) {
26 var value = elem["offset" + capitalize(dimension)];
27 var margins = MARGINS[dimension];
28 return value + _parseInt(css(elem, margins[0]), 10) + _parseInt(css(elem, margins[1]), 10);
29}
30
31var collapseStyles = (_collapseStyles = {}, _collapseStyles[EXITED] = 'collapse', _collapseStyles[EXITING] = 'collapsing', _collapseStyles[ENTERING] = 'collapsing', _collapseStyles[ENTERED] = 'collapse in', _collapseStyles);
32var propTypes = {
33 /**
34 * Show the component; triggers the expand or collapse animation
35 */
36 in: PropTypes.bool,
37
38 /**
39 * Wait until the first "enter" transition to mount the component (add it to the DOM)
40 */
41 mountOnEnter: PropTypes.bool,
42
43 /**
44 * Unmount the component (remove it from the DOM) when it is collapsed
45 */
46 unmountOnExit: PropTypes.bool,
47
48 /**
49 * Run the expand animation when the component mounts, if it is initially
50 * shown
51 */
52 appear: PropTypes.bool,
53
54 /**
55 * Duration of the collapse animation in milliseconds, to ensure that
56 * finishing callbacks are fired even if the original browser transition end
57 * events are canceled
58 */
59 timeout: PropTypes.number,
60
61 /**
62 * Callback fired before the component expands
63 */
64 onEnter: PropTypes.func,
65
66 /**
67 * Callback fired after the component starts to expand
68 */
69 onEntering: PropTypes.func,
70
71 /**
72 * Callback fired after the component has expanded
73 */
74 onEntered: PropTypes.func,
75
76 /**
77 * Callback fired before the component collapses
78 */
79 onExit: PropTypes.func,
80
81 /**
82 * Callback fired after the component starts to collapse
83 */
84 onExiting: PropTypes.func,
85
86 /**
87 * Callback fired after the component has collapsed
88 */
89 onExited: PropTypes.func,
90
91 /**
92 * The dimension used when collapsing, or a function that returns the
93 * dimension
94 *
95 * _Note: Bootstrap only partially supports 'width'!
96 * You will need to supply your own CSS animation for the `.width` CSS class._
97 */
98 dimension: PropTypes.oneOfType([PropTypes.oneOf(['height', 'width']), PropTypes.func]),
99
100 /**
101 * Function that returns the height or width of the animating DOM node
102 *
103 * Allows for providing some custom logic for how much the Collapse component
104 * should animate in its specified dimension. Called with the current
105 * dimension prop value and the DOM node.
106 */
107 getDimensionValue: PropTypes.func,
108
109 /**
110 * ARIA role of collapsible element
111 */
112 role: PropTypes.string
113};
114var defaultProps = {
115 in: false,
116 timeout: 300,
117 mountOnEnter: false,
118 unmountOnExit: false,
119 appear: false,
120 dimension: 'height',
121 getDimensionValue: getDimensionValue
122};
123
124var Collapse =
125/*#__PURE__*/
126function (_React$Component) {
127 _inheritsLoose(Collapse, _React$Component);
128
129 function Collapse() {
130 var _this;
131
132 for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
133 args[_key] = arguments[_key];
134 }
135
136 _this = _React$Component.call.apply(_React$Component, [this].concat(args)) || this;
137
138 _this.handleEnter = function (elem) {
139 elem.style[_this.getDimension()] = '0';
140 };
141
142 _this.handleEntering = function (elem) {
143 var dimension = _this.getDimension();
144
145 elem.style[dimension] = _this._getScrollDimensionValue(elem, dimension);
146 };
147
148 _this.handleEntered = function (elem) {
149 elem.style[_this.getDimension()] = null;
150 };
151
152 _this.handleExit = function (elem) {
153 var dimension = _this.getDimension();
154
155 elem.style[dimension] = _this.props.getDimensionValue(dimension, elem) + "px";
156 triggerBrowserReflow(elem);
157 };
158
159 _this.handleExiting = function (elem) {
160 elem.style[_this.getDimension()] = '0';
161 };
162
163 return _this;
164 }
165
166 var _proto = Collapse.prototype;
167
168 _proto.getDimension = function getDimension() {
169 return typeof this.props.dimension === 'function' ? this.props.dimension() : this.props.dimension;
170 }; // for testing
171
172
173 _proto._getScrollDimensionValue = function _getScrollDimensionValue(elem, dimension) {
174 return elem["scroll" + capitalize(dimension)] + "px";
175 };
176 /* -- Expanding -- */
177
178
179 _proto.render = function render() {
180 var _this2 = this;
181
182 var _this$props = this.props,
183 onEnter = _this$props.onEnter,
184 onEntering = _this$props.onEntering,
185 onEntered = _this$props.onEntered,
186 onExit = _this$props.onExit,
187 onExiting = _this$props.onExiting,
188 className = _this$props.className,
189 children = _this$props.children,
190 props = _objectWithoutPropertiesLoose(_this$props, ["onEnter", "onEntering", "onEntered", "onExit", "onExiting", "className", "children"]);
191
192 delete props.dimension;
193 delete props.getDimensionValue;
194 var handleEnter = createChainedFunction(this.handleEnter, onEnter);
195 var handleEntering = createChainedFunction(this.handleEntering, onEntering);
196 var handleEntered = createChainedFunction(this.handleEntered, onEntered);
197 var handleExit = createChainedFunction(this.handleExit, onExit);
198 var handleExiting = createChainedFunction(this.handleExiting, onExiting);
199 return React.createElement(Transition, _extends({}, props, {
200 "aria-expanded": props.role ? props.in : null,
201 onEnter: handleEnter,
202 onEntering: handleEntering,
203 onEntered: handleEntered,
204 onExit: handleExit,
205 onExiting: handleExiting
206 }), function (state, innerProps) {
207 return React.cloneElement(children, _extends({}, innerProps, {
208 className: classNames(className, children.props.className, collapseStyles[state], _this2.getDimension() === 'width' && 'width')
209 }));
210 });
211 };
212
213 return Collapse;
214}(React.Component);
215
216Collapse.propTypes = propTypes;
217Collapse.defaultProps = defaultProps;
218export default Collapse;
\No newline at end of file