UNPKG

kitten-components

Version:
339 lines (269 loc) 10.9 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.Dropdown = undefined; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _propTypes = require('prop-types'); var _propTypes2 = _interopRequireDefault(_propTypes); var _classnames = require('classnames'); var _classnames2 = _interopRequireDefault(_classnames); var _emitter = require('kitten/helpers/utils/emitter'); var _emitter2 = _interopRequireDefault(_emitter); var _dropdownButton = require('kitten/components/dropdowns/dropdown-button'); var _elementHelper = require('kitten/helpers/dom/element-helper'); var _elementHelper2 = _interopRequireDefault(_elementHelper); var _assign = require('core-js/library/fn/object/assign'); var _assign2 = _interopRequireDefault(_assign); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var Dropdown = exports.Dropdown = function (_React$Component) { _inherits(Dropdown, _React$Component); function Dropdown(props) { _classCallCheck(this, Dropdown); var _this = _possibleConstructorReturn(this, (Dropdown.__proto__ || Object.getPrototypeOf(Dropdown)).call(this, props)); _this.state = { isExpanded: false, referenceElementHeight: 0 }; _this.handleDropdownPosition = _this.handleDropdownPosition.bind(_this); _this.revertHandleClickOnLinks = _this.revertHandleClickOnLinks.bind(_this); _this.close = _this.close.bind(_this); return _this; } _createClass(Dropdown, [{ key: 'componentDidMount', value: function componentDidMount() { var _this2 = this; var dropdown = this; if (_elementHelper2.default.canUseDom()) { // Update dropdown content position after DOM is build. var referenceElementHeight = this.getReferenceElementHeight(); this.setState({ referenceElementHeight: referenceElementHeight }); } // Handle events. this.handleClickOnLinks(); _emitter2.default.on('dropdown:opening:trigger', this.close); if (this.props.refreshEvents) { this.props.refreshEvents.forEach(function (ev) { window.addEventListener(ev, _this2.handleDropdownPosition); }); } if (this.props.closeEvents) { this.props.closeEvents.forEach(function (ev) { window.addEventListener(ev, _this2.close); }); } } }, { key: 'componentWillUnmount', value: function componentWillUnmount() { var _this3 = this; this.revertHandleClickOnLinks(); if (this.props.refreshEvents) { this.props.refreshEvents.forEach(function (ev) { window.removeEventListener(ev, _this3.handleDropdownPosition); }); } if (this.props.closeEvents) { this.props.closeEvents.forEach(function (ev) { window.removeEventListener(ev, _this3.close); }); } _emitter2.default.off('dropdown:opening:trigger', this.close); } }, { key: 'componentWillReceiveProps', value: function componentWillReceiveProps(nextProps) { // Enable wrapper component to expand the dropdown. if (nextProps.isExpanded != this.state.isExpanded) { this.toggle(nextProps.isExpanded); } } // Component methods }, { key: 'close', value: function close() { this.setState({ isExpanded: false }); } }, { key: 'toggle', value: function toggle(nextExpandedState) { if (nextExpandedState) { _emitter2.default.emit('dropdown:opening:trigger', this); } this.props.onToggle(); this.setState({ isExpanded: nextExpandedState }); } }, { key: 'hasDefaultHorizontalPosition', value: function hasDefaultHorizontalPosition() { return this.props.positionedOn == 'left'; } }, { key: 'isSelfReference', value: function isSelfReference() { return typeof this.props.positionedWith == 'undefined'; } }, { key: 'getReferenceElement', value: function getReferenceElement() { if (!this.isSelfReference()) return this.props.positionedWith(); return this.refs.dropdown; } }, { key: 'getReferenceElementHeight', value: function getReferenceElementHeight() { var referenceElement = this.getReferenceElement(); return _elementHelper2.default.getComputedHeight(referenceElement, this.props.positionedWithBorder); } }, { key: 'getArrowPosition', value: function getArrowPosition() { var defaultPosition = { position: 'absolute', top: 0 }; var arrowHorizontalPosition = this.props.arrowHorizontalPosition; return (0, _assign2.default)(defaultPosition, arrowHorizontalPosition); } }, { key: 'getContentPosition', value: function getContentPosition() { var defaultPosition = { top: this.state.referenceElementHeight }; var horizontalPosition = this.props.contentHorizontalPosition; return (0, _assign2.default)(defaultPosition, horizontalPosition); } // Component listener callbacks }, { key: 'revertHandleClickOnLinks', value: function revertHandleClickOnLinks() { var _this4 = this; var links = this.refs.dropdownContent.getElementsByTagName('a'); Array.prototype.forEach.call(links, function (link) { link.removeEventListener('click', _this4.close); }); } }, { key: 'handleClickOnLinks', value: function handleClickOnLinks() { var _this5 = this; var links = this.refs.dropdownContent.getElementsByTagName('a'); Array.prototype.forEach.call(links, function (link) { link.removeEventListener('click', _this5.close); }); } }, { key: 'handleDropdownPosition', value: function handleDropdownPosition() { if (_elementHelper2.default.canUseDom()) { this.props.onPositionUpdate(); } } }, { key: 'handleButtonClick', value: function handleButtonClick(event) { event.stopPropagation(); event.preventDefault(); this.toggle(!this.state.isExpanded); } // Rendering }, { key: 'renderButtonContentElement', value: function renderButtonContentElement() { if (this.state.isExpanded) { return this.props.buttonContentOnExpanded; } return this.props.buttonContentOnCollapsed; } }, { key: 'renderButton', value: function renderButton() { if (this.props.button) return this.props.button; return _react2.default.createElement( _dropdownButton.DropdownButton, { ref: 'dropdownButton', className: this.props.buttonClassName, id: this.props.buttonId, isExpanded: this.state.isExpanded, onClick: this.handleButtonClick.bind(this) }, this.renderButtonContentElement() ); } }, { key: 'renderArrow', value: function renderArrow() { if (!this.props.dropdownListArrow) return; var style = this.getArrowPosition(); return _react2.default.createElement( 'span', { ref: 'arrow', style: style }, this.props.dropdownListArrow ); } }, { key: 'render', value: function render() { var button = this.renderButton(); var dropdownClassName = (0, _classnames2.default)('k-Dropdown', { 'is-expanded': this.state.isExpanded, 'k-Dropdown--asReference': this.isSelfReference() }, this.props.className); return _react2.default.createElement( 'div', { ref: 'dropdown', className: dropdownClassName }, button, _react2.default.createElement( 'div', { ref: 'dropdownContent', className: 'k-Dropdown__content', style: this.getContentPosition(), 'aria-hidden': 'true', 'aria-labelledby': this.props.buttonId }, this.props.dropdownContent, this.renderArrow() ) ); } }]); return Dropdown; }(_react2.default.Component); Dropdown.propTypes = { isExpanded: _propTypes2.default.bool, positionedWith: _propTypes2.default.func, positionedWithBorder: _propTypes2.default.bool, positionedOn: _propTypes2.default.string, notifications: _propTypes2.default.number, refreshEvents: _propTypes2.default.array, closeEvents: _propTypes2.default.array, onPositionUpdate: _propTypes2.default.func }; Dropdown.defaultProps = { // Take border into account to compute reference element height. positionedWithBorder: true, // Fix the dropdown on the left or on the right. positionedOn: 'left', // 'left' | 'right' // Custom horizontal position for content and content arrow. contentHorizontalPosition: { left: '0' }, arrowHorizontalPosition: { left: '50%' }, // Button settings buttonContentOnExpanded: 'Close me', buttonContentOnCollapsed: 'Expand me', // List of events that will trigger the update of the reference element // height. refreshEvents: [], // eg. ['resize'] // List of events that will trigger the closure. closeEvents: [], // Called when one of the `refreshEvents` is triggered. onPositionUpdate: function onPositionUpdate() {}, // Called when the dropdown is opened or closed onToggle: function onToggle() {} // DEPRECATED: do not use default export. };exports.default = Dropdown;