UNPKG

20.6 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6
7var _extends2 = require('babel-runtime/helpers/extends');
8
9var _extends3 = _interopRequireDefault(_extends2);
10
11var _objectWithoutProperties2 = require('babel-runtime/helpers/objectWithoutProperties');
12
13var _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2);
14
15var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
16
17var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
18
19var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
20
21var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
22
23var _createClass2 = require('babel-runtime/helpers/createClass');
24
25var _createClass3 = _interopRequireDefault(_createClass2);
26
27var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
28
29var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
30
31var _inherits2 = require('babel-runtime/helpers/inherits');
32
33var _inherits3 = _interopRequireDefault(_inherits2);
34
35var _simpleAssign = require('simple-assign');
36
37var _simpleAssign2 = _interopRequireDefault(_simpleAssign);
38
39var _react = require('react');
40
41var _react2 = _interopRequireDefault(_react);
42
43var _propTypes = require('prop-types');
44
45var _propTypes2 = _interopRequireDefault(_propTypes);
46
47var _reactDom = require('react-dom');
48
49var _reactDom2 = _interopRequireDefault(_reactDom);
50
51var _reactEventListener = require('react-event-listener');
52
53var _reactEventListener2 = _interopRequireDefault(_reactEventListener);
54
55var _keycode = require('keycode');
56
57var _keycode2 = _interopRequireDefault(_keycode);
58
59var _transitions = require('../styles/transitions');
60
61var _transitions2 = _interopRequireDefault(_transitions);
62
63var _Overlay = require('../internal/Overlay');
64
65var _Overlay2 = _interopRequireDefault(_Overlay);
66
67var _RenderToLayer = require('../internal/RenderToLayer');
68
69var _RenderToLayer2 = _interopRequireDefault(_RenderToLayer);
70
71var _Paper = require('../Paper');
72
73var _Paper2 = _interopRequireDefault(_Paper);
74
75var _TransitionGroup = require('react-transition-group/TransitionGroup');
76
77var _TransitionGroup2 = _interopRequireDefault(_TransitionGroup);
78
79function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
80
81var TransitionItem = function (_Component) {
82 (0, _inherits3.default)(TransitionItem, _Component);
83
84 function TransitionItem() {
85 var _ref;
86
87 var _temp, _this, _ret;
88
89 (0, _classCallCheck3.default)(this, TransitionItem);
90
91 for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
92 args[_key] = arguments[_key];
93 }
94
95 return _ret = (_temp = (_this = (0, _possibleConstructorReturn3.default)(this, (_ref = TransitionItem.__proto__ || (0, _getPrototypeOf2.default)(TransitionItem)).call.apply(_ref, [this].concat(args))), _this), _this.state = {
96 style: {}
97 }, _temp), (0, _possibleConstructorReturn3.default)(_this, _ret);
98 }
99
100 (0, _createClass3.default)(TransitionItem, [{
101 key: 'componentWillUnmount',
102 value: function componentWillUnmount() {
103 clearTimeout(this.enterTimeout);
104 clearTimeout(this.leaveTimeout);
105 }
106 }, {
107 key: 'componentWillEnter',
108 value: function componentWillEnter(callback) {
109 this.componentWillAppear(callback);
110 }
111 }, {
112 key: 'componentWillAppear',
113 value: function componentWillAppear(callback) {
114 var spacing = this.context.muiTheme.baseTheme.spacing;
115
116 this.setState({
117 style: {
118 opacity: 1,
119 transform: 'translate(0, ' + spacing.desktopKeylineIncrement + 'px)'
120 }
121 });
122
123 this.enterTimeout = setTimeout(callback, 450); // matches transition duration
124 }
125 }, {
126 key: 'componentWillLeave',
127 value: function componentWillLeave(callback) {
128 this.setState({
129 style: {
130 opacity: 0,
131 transform: 'translate(0, 0)'
132 }
133 });
134
135 this.leaveTimeout = setTimeout(callback, 450); // matches transition duration
136 }
137 }, {
138 key: 'render',
139 value: function render() {
140 var _props = this.props,
141 style = _props.style,
142 children = _props.children,
143 other = (0, _objectWithoutProperties3.default)(_props, ['style', 'children']);
144 var prepareStyles = this.context.muiTheme.prepareStyles;
145
146
147 return _react2.default.createElement(
148 'div',
149 (0, _extends3.default)({}, other, { style: prepareStyles((0, _simpleAssign2.default)({}, this.state.style, style)) }),
150 children
151 );
152 }
153 }]);
154 return TransitionItem;
155}(_react.Component);
156
157TransitionItem.contextTypes = {
158 muiTheme: _propTypes2.default.object.isRequired
159};
160TransitionItem.propTypes = process.env.NODE_ENV !== "production" ? {
161 children: _propTypes2.default.node,
162 style: _propTypes2.default.object
163} : {};
164
165
166function getStyles(props, context) {
167 var autoScrollBodyContent = props.autoScrollBodyContent,
168 open = props.open;
169 var _context$muiTheme = context.muiTheme,
170 _context$muiTheme$bas = _context$muiTheme.baseTheme,
171 spacing = _context$muiTheme$bas.spacing,
172 palette = _context$muiTheme$bas.palette,
173 dialog = _context$muiTheme.dialog,
174 zIndex = _context$muiTheme.zIndex;
175
176
177 var gutter = spacing.desktopGutter;
178 var borderScroll = '1px solid ' + palette.borderColor;
179
180 return {
181 root: {
182 position: 'fixed',
183 boxSizing: 'border-box',
184 WebkitTapHighlightColor: 'rgba(0,0,0,0)', // Remove mobile color flashing (deprecated)
185 zIndex: zIndex.dialog,
186 top: 0,
187 left: open ? 0 : -10000,
188 width: '100%',
189 height: '100%',
190 transition: open ? _transitions2.default.easeOut('0ms', 'left', '0ms') : _transitions2.default.easeOut('0ms', 'left', '450ms')
191 },
192 content: {
193 boxSizing: 'border-box',
194 WebkitTapHighlightColor: 'rgba(0,0,0,0)', // Remove mobile color flashing (deprecated)
195 transition: _transitions2.default.easeOut(),
196 position: 'relative',
197 width: '75%',
198 maxWidth: spacing.desktopKeylineIncrement * 12,
199 margin: '0 auto',
200 zIndex: zIndex.dialog
201 },
202 actionsContainer: {
203 boxSizing: 'border-box',
204 WebkitTapHighlightColor: 'rgba(0,0,0,0)', // Remove mobile color flashing (deprecated)
205 padding: 8,
206 width: '100%',
207 textAlign: 'right',
208 marginTop: autoScrollBodyContent ? -1 : 0
209 },
210 overlay: {
211 zIndex: zIndex.dialogOverlay
212 },
213 title: {
214 margin: 0,
215 padding: gutter + 'px ' + gutter + 'px 20px ' + gutter + 'px',
216 color: palette.textColor,
217 fontSize: dialog.titleFontSize,
218 lineHeight: '32px',
219 fontWeight: 400,
220 marginBottom: autoScrollBodyContent ? -1 : 0
221 },
222 body: {
223 fontSize: dialog.bodyFontSize,
224 color: dialog.bodyColor,
225 padding: (props.title ? 0 : gutter) + 'px ' + gutter + 'px ' + gutter + 'px',
226 boxSizing: 'border-box',
227 overflowY: autoScrollBodyContent ? 'auto' : 'hidden',
228 borderTop: autoScrollBodyContent ? borderScroll : 'none',
229 borderBottom: autoScrollBodyContent ? borderScroll : 'none'
230 }
231 };
232}
233
234var DialogInline = function (_Component2) {
235 (0, _inherits3.default)(DialogInline, _Component2);
236
237 function DialogInline() {
238 var _ref2;
239
240 var _temp2, _this2, _ret2;
241
242 (0, _classCallCheck3.default)(this, DialogInline);
243
244 for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
245 args[_key2] = arguments[_key2];
246 }
247
248 return _ret2 = (_temp2 = (_this2 = (0, _possibleConstructorReturn3.default)(this, (_ref2 = DialogInline.__proto__ || (0, _getPrototypeOf2.default)(DialogInline)).call.apply(_ref2, [this].concat(args))), _this2), _this2.handleClickOverlay = function () {
249 _this2.requestClose(false);
250 }, _this2.handleKeyUp = function (event) {
251 if ((0, _keycode2.default)(event) === 'esc') {
252 _this2.requestClose(false);
253 }
254 }, _this2.handleResize = function () {
255 _this2.positionDialog();
256 }, _temp2), (0, _possibleConstructorReturn3.default)(_this2, _ret2);
257 }
258
259 (0, _createClass3.default)(DialogInline, [{
260 key: 'componentDidMount',
261 value: function componentDidMount() {
262 this.positionDialog();
263 }
264 }, {
265 key: 'componentDidUpdate',
266 value: function componentDidUpdate() {
267 this.positionDialog();
268 }
269 }, {
270 key: 'positionDialog',
271 value: function positionDialog() {
272 var _props2 = this.props,
273 actions = _props2.actions,
274 autoDetectWindowHeight = _props2.autoDetectWindowHeight,
275 autoScrollBodyContent = _props2.autoScrollBodyContent,
276 bodyStyle = _props2.bodyStyle,
277 open = _props2.open,
278 repositionOnUpdate = _props2.repositionOnUpdate,
279 title = _props2.title;
280
281
282 if (!open) {
283 return;
284 }
285
286 var clientHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
287 var container = _reactDom2.default.findDOMNode(this);
288 var dialogWindow = _reactDom2.default.findDOMNode(this.refs.dialogWindow);
289 var dialogContent = _reactDom2.default.findDOMNode(this.refs.dialogContent);
290 var minPaddingTop = 16;
291
292 // Reset the height in case the window was resized.
293 dialogWindow.style.height = '';
294 dialogContent.style.height = '';
295
296 var dialogWindowHeight = dialogWindow.offsetHeight;
297 var paddingTop = (clientHeight - dialogWindowHeight) / 2 - 64;
298 if (paddingTop < minPaddingTop) paddingTop = minPaddingTop;
299
300 // Vertically center the dialog window, but make sure it doesn't
301 // transition to that position.
302 if (repositionOnUpdate || !container.style.paddingTop) {
303 container.style.paddingTop = paddingTop + 'px';
304 }
305
306 // Force a height if the dialog is taller than clientHeight
307 if (autoDetectWindowHeight || autoScrollBodyContent) {
308 var styles = getStyles(this.props, this.context);
309 styles.body = (0, _simpleAssign2.default)(styles.body, bodyStyle);
310 var maxDialogContentHeight = clientHeight - 2 * 64;
311
312 if (title) maxDialogContentHeight -= dialogContent.previousSibling.offsetHeight;
313
314 if (_react2.default.Children.count(actions)) {
315 maxDialogContentHeight -= dialogContent.nextSibling.offsetHeight;
316 }
317
318 dialogContent.style.maxHeight = maxDialogContentHeight + 'px';
319 if (maxDialogContentHeight > dialogWindowHeight) {
320 dialogContent.style.borderBottom = 'none';
321 dialogContent.style.borderTop = 'none';
322 }
323 }
324 }
325 }, {
326 key: 'requestClose',
327 value: function requestClose(buttonClicked) {
328 if (!buttonClicked && this.props.modal) {
329 return;
330 }
331
332 if (this.props.onRequestClose) {
333 this.props.onRequestClose(!!buttonClicked);
334 }
335 }
336 }, {
337 key: 'render',
338 value: function render() {
339 var _props3 = this.props,
340 actions = _props3.actions,
341 actionsContainerClassName = _props3.actionsContainerClassName,
342 actionsContainerStyle = _props3.actionsContainerStyle,
343 bodyClassName = _props3.bodyClassName,
344 bodyStyle = _props3.bodyStyle,
345 children = _props3.children,
346 className = _props3.className,
347 contentClassName = _props3.contentClassName,
348 contentStyle = _props3.contentStyle,
349 overlayClassName = _props3.overlayClassName,
350 overlayStyle = _props3.overlayStyle,
351 open = _props3.open,
352 paperClassName = _props3.paperClassName,
353 paperProps = _props3.paperProps,
354 style = _props3.style,
355 titleClassName = _props3.titleClassName,
356 titleStyle = _props3.titleStyle,
357 title = _props3.title;
358 var prepareStyles = this.context.muiTheme.prepareStyles;
359
360 var styles = getStyles(this.props, this.context);
361
362 styles.root = (0, _simpleAssign2.default)(styles.root, style);
363 styles.content = (0, _simpleAssign2.default)(styles.content, contentStyle);
364 styles.body = (0, _simpleAssign2.default)(styles.body, bodyStyle);
365 styles.actionsContainer = (0, _simpleAssign2.default)(styles.actionsContainer, actionsContainerStyle);
366 styles.overlay = (0, _simpleAssign2.default)(styles.overlay, overlayStyle);
367 styles.title = (0, _simpleAssign2.default)(styles.title, titleStyle);
368
369 var actionsContainer = _react2.default.Children.count(actions) > 0 && _react2.default.createElement(
370 'div',
371 { className: actionsContainerClassName, style: prepareStyles(styles.actionsContainer) },
372 _react2.default.Children.toArray(actions)
373 );
374
375 var titleElement = title;
376 if (_react2.default.isValidElement(title)) {
377 titleElement = _react2.default.cloneElement(title, {
378 className: title.props.className || titleClassName,
379 style: prepareStyles((0, _simpleAssign2.default)(styles.title, title.props.style))
380 });
381 } else if (typeof title === 'string') {
382 titleElement = _react2.default.createElement(
383 'h3',
384 { className: titleClassName, style: prepareStyles(styles.title) },
385 title
386 );
387 }
388
389 return _react2.default.createElement(
390 'div',
391 { className: className, style: prepareStyles(styles.root) },
392 open && _react2.default.createElement(_reactEventListener2.default, {
393 target: 'window',
394 onKeyUp: this.handleKeyUp,
395 onResize: this.handleResize
396 }),
397 _react2.default.createElement(
398 _TransitionGroup2.default,
399 {
400 component: 'div',
401 ref: 'dialogWindow',
402 transitionAppear: true,
403 transitionAppearTimeout: 450,
404 transitionEnter: true,
405 transitionEnterTimeout: 450
406 },
407 open && _react2.default.createElement(
408 TransitionItem,
409 {
410 className: contentClassName,
411 style: styles.content
412 },
413 _react2.default.createElement(
414 _Paper2.default,
415 (0, _extends3.default)({ className: paperClassName, zDepth: 4 }, paperProps),
416 titleElement,
417 _react2.default.createElement(
418 'div',
419 {
420 ref: 'dialogContent',
421 className: bodyClassName,
422 style: prepareStyles(styles.body)
423 },
424 children
425 ),
426 actionsContainer
427 )
428 )
429 ),
430 _react2.default.createElement(_Overlay2.default, {
431 show: open,
432 className: overlayClassName,
433 style: styles.overlay,
434 onClick: this.handleClickOverlay
435 })
436 );
437 }
438 }]);
439 return DialogInline;
440}(_react.Component);
441
442DialogInline.contextTypes = {
443 muiTheme: _propTypes2.default.object.isRequired
444};
445DialogInline.propTypes = process.env.NODE_ENV !== "production" ? {
446 actions: _propTypes2.default.node,
447 actionsContainerClassName: _propTypes2.default.string,
448 actionsContainerStyle: _propTypes2.default.object,
449 autoDetectWindowHeight: _propTypes2.default.bool,
450 autoScrollBodyContent: _propTypes2.default.bool,
451 bodyClassName: _propTypes2.default.string,
452 bodyStyle: _propTypes2.default.object,
453 children: _propTypes2.default.node,
454 className: _propTypes2.default.string,
455 contentClassName: _propTypes2.default.string,
456 contentStyle: _propTypes2.default.object,
457 modal: _propTypes2.default.bool,
458 onRequestClose: _propTypes2.default.func,
459 open: _propTypes2.default.bool.isRequired,
460 overlayClassName: _propTypes2.default.string,
461 overlayStyle: _propTypes2.default.object,
462 paperClassName: _propTypes2.default.string,
463 paperProps: _propTypes2.default.object,
464 repositionOnUpdate: _propTypes2.default.bool,
465 style: _propTypes2.default.object,
466 title: _propTypes2.default.node,
467 titleClassName: _propTypes2.default.string,
468 titleStyle: _propTypes2.default.object
469} : {};
470
471var Dialog = function (_Component3) {
472 (0, _inherits3.default)(Dialog, _Component3);
473
474 function Dialog() {
475 var _ref3;
476
477 var _temp3, _this3, _ret3;
478
479 (0, _classCallCheck3.default)(this, Dialog);
480
481 for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
482 args[_key3] = arguments[_key3];
483 }
484
485 return _ret3 = (_temp3 = (_this3 = (0, _possibleConstructorReturn3.default)(this, (_ref3 = Dialog.__proto__ || (0, _getPrototypeOf2.default)(Dialog)).call.apply(_ref3, [this].concat(args))), _this3), _this3.renderLayer = function () {
486 return _react2.default.createElement(DialogInline, _this3.props);
487 }, _temp3), (0, _possibleConstructorReturn3.default)(_this3, _ret3);
488 }
489
490 (0, _createClass3.default)(Dialog, [{
491 key: 'render',
492 value: function render() {
493 return _react2.default.createElement(_RenderToLayer2.default, { render: this.renderLayer, open: true, useLayerForClickAway: false });
494 }
495 }]);
496 return Dialog;
497}(_react.Component);
498
499Dialog.contextTypes = {
500 muiTheme: _propTypes2.default.object.isRequired
501};
502Dialog.defaultProps = {
503 autoDetectWindowHeight: true,
504 autoScrollBodyContent: false,
505 modal: false,
506 repositionOnUpdate: true
507};
508Dialog.propTypes = process.env.NODE_ENV !== "production" ? {
509 /**
510 * Action buttons to display below the Dialog content (`children`).
511 * This property accepts either a React element, or an array of React elements.
512 */
513 actions: _propTypes2.default.node,
514 /**
515 * The `className` to add to the actions container's root element.
516 */
517 actionsContainerClassName: _propTypes2.default.string,
518 /**
519 * Overrides the inline-styles of the actions container's root element.
520 */
521 actionsContainerStyle: _propTypes2.default.object,
522 /**
523 * If set to true, the height of the `Dialog` will be auto detected. A max height
524 * will be enforced so that the content does not extend beyond the viewport.
525 */
526 autoDetectWindowHeight: _propTypes2.default.bool,
527 /**
528 * If set to true, the body content of the `Dialog` will be scrollable.
529 */
530 autoScrollBodyContent: _propTypes2.default.bool,
531 /**
532 * The `className` to add to the content's root element under the title.
533 */
534 bodyClassName: _propTypes2.default.string,
535 /**
536 * Overrides the inline-styles of the content's root element under the title.
537 */
538 bodyStyle: _propTypes2.default.object,
539 /**
540 * The contents of the `Dialog`.
541 */
542 children: _propTypes2.default.node,
543 /**
544 * @ignore
545 */
546 className: _propTypes2.default.string,
547 /**
548 * The `className` to add to the content container.
549 */
550 contentClassName: _propTypes2.default.string,
551 /**
552 * Overrides the inline-styles of the content container.
553 */
554 contentStyle: _propTypes2.default.object,
555 /**
556 * Force the user to use one of the actions in the `Dialog`.
557 * Clicking outside the `Dialog` will not trigger the `onRequestClose`.
558 */
559 modal: _propTypes2.default.bool,
560 /**
561 * Fired when the `Dialog` is requested to be closed by a click outside the `Dialog` or on the buttons.
562 *
563 * @param {bool} buttonClicked Determines whether a button click triggered this request.
564 */
565 onRequestClose: _propTypes2.default.func,
566 /**
567 * Controls whether the Dialog is opened or not.
568 */
569 open: _propTypes2.default.bool.isRequired,
570 /**
571 * The `className` to add to the `Overlay` component that is rendered behind the `Dialog`.
572 */
573 overlayClassName: _propTypes2.default.string,
574 /**
575 * Overrides the inline-styles of the `Overlay` component that is rendered behind the `Dialog`.
576 */
577 overlayStyle: _propTypes2.default.object,
578 /**
579 * The CSS class name of the `Paper` element.
580 */
581 paperClassName: _propTypes2.default.string,
582 /**
583 * Properties applied to the `Paper` element.
584 */
585 paperProps: _propTypes2.default.object,
586 /**
587 * Determines whether the `Dialog` should be repositioned when it's contents are updated.
588 */
589 repositionOnUpdate: _propTypes2.default.bool,
590 /**
591 * Override the inline-styles of the root element.
592 */
593 style: _propTypes2.default.object,
594 /**
595 * The title to display on the `Dialog`. Could be number, string, element or an array containing these types.
596 */
597 title: _propTypes2.default.node,
598 /**
599 * The `className` to add to the title's root container element.
600 */
601 titleClassName: _propTypes2.default.string,
602 /**
603 * Overrides the inline-styles of the title's root container element.
604 */
605 titleStyle: _propTypes2.default.object
606} : {};
607exports.default = Dialog;
\No newline at end of file