UNPKG

react-data-menu

Version:

Smart data-driven menu rendered in an overlay

186 lines (144 loc) 7.02 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.ITEM_ID_PREFIX = 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 _lodash = require('lodash'); var _lodash2 = _interopRequireDefault(_lodash); var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _reactDom = require('react-dom'); var _reactDom2 = _interopRequireDefault(_reactDom); var _Aligner = require('./../util/Aligner.js'); var _Aligner2 = _interopRequireDefault(_Aligner); var _hoverData = require('./../util/hoverData.js'); var _hoverData2 = _interopRequireDefault(_hoverData); 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 ITEM_ID_PREFIX = exports.ITEM_ID_PREFIX = 'menu-item-'; var DEFAULT_ITEM_RENDERER_TYPE = 'button'; var classnames = require('classnames'); var MenuPopup = function (_Component) { _inherits(MenuPopup, _Component); function MenuPopup(props) { _classCallCheck(this, MenuPopup); var _this = _possibleConstructorReturn(this, (MenuPopup.__proto__ || Object.getPrototypeOf(MenuPopup)).call(this, props)); _this.aligner = _this.props.aligner; _this.state = { showing: false }; return _this; } _createClass(MenuPopup, [{ key: 'render', value: function render() { var index = 0, classPrefix = this.props.classPrefix, selectedIndex = this.props.selectedIndex, popupFactory = this.props.popupFactory, itemFactory = this.props.itemFactory, self = this, key, children, menuItem, styles; children = this.props.items ? this.props.items.map(function (data) { var classes = {}; key = ITEM_ID_PREFIX + index; if (selectedIndex === index) { classes[classPrefix + 'menu-item-selected'] = true; } data = self.expandDescriptor(data); menuItem = itemFactory.createItem(_lodash2.default.assign({}, data, { id: key }), key, classnames(classes), self.props.config); index++; return menuItem; }) : null; styles = { position: 'fixed', left: this.props.x + 'px', top: this.props.y + 'px' }; return popupFactory.createItem(_lodash2.default.assign({}, { popupId: this.props.popupId, styles: styles, children: children, showing: this.state.showing })); } }, { key: 'componentDidMount', value: function componentDidMount() { var classPrefix = this.props.classPrefix, position; // measure DOM if (!this.dom) { this.dom = _reactDom2.default.findDOMNode(this); this.dom.style.position = 'fixed'; } // align position = this.aligner.align(this.dom, this.props.alignTo, this.props.hints, this.props.useOffset ? this.dom.firstChild : null); // bake some of the position information into popups' className if (!position.fitsX) { // if popup doesn't horizontally fit the screen, add this class name // this could be used to introduce scroll etc. this.dom.className += ' ' + classPrefix + 'menu-popup-overflow-x'; } if (!position.fitsY) { // if popup doesn't vertically fit the screen, add this class name this.dom.className += ' ' + classPrefix + 'menu-popup-overflow-y'; } if (position.direction) { // styling different positions ('menu-popup-align-es', 'menu-popup-align-se' etc.) this.dom.className += ' ' + classPrefix + 'menu-popup-align-' + position.direction; } this.setState({ showing: true }); } /** * Expands string descriptor to object descriptor * @param data * @returns {*} */ }, { key: 'expandDescriptor', value: function expandDescriptor(data) { if (typeof data === 'string') { return { type: data }; } if (!data.type) { data.type = DEFAULT_ITEM_RENDERER_TYPE; } return data; } }]); return MenuPopup; }(_react.Component); exports.default = MenuPopup; MenuPopup.propTypes = { config: _react2.default.PropTypes.object, // config object visiting every menu item classPrefix: _react2.default.PropTypes.string, x: _react2.default.PropTypes.number, y: _react2.default.PropTypes.number, items: _react2.default.PropTypes.arrayOf(_react2.default.PropTypes.oneOfType([_react2.default.PropTypes.object, _react2.default.PropTypes.string])), popupId: _react2.default.PropTypes.string.isRequired, useOffset: _react2.default.PropTypes.bool.isRequired, hints: _react2.default.PropTypes.arrayOf(_react2.default.PropTypes.string).isRequired, selectedIndex: _react2.default.PropTypes.number.isRequired }; MenuPopup.defaultProps = { classPrefix: '', x: 0, y: 0, items: [], alignTo: null, useOffset: false, selectedIndex: -1 };