Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 

592 строки
18 KiB

  1. 'use strict';
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. var _extends2 = require('babel-runtime/helpers/extends');
  6. var _extends3 = _interopRequireDefault(_extends2);
  7. var _objectWithoutProperties2 = require('babel-runtime/helpers/objectWithoutProperties');
  8. var _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2);
  9. var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
  10. var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
  11. var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
  12. var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
  13. var _createClass2 = require('babel-runtime/helpers/createClass');
  14. var _createClass3 = _interopRequireDefault(_createClass2);
  15. var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
  16. var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
  17. var _inherits2 = require('babel-runtime/helpers/inherits');
  18. var _inherits3 = _interopRequireDefault(_inherits2);
  19. var _simpleAssign = require('simple-assign');
  20. var _simpleAssign2 = _interopRequireDefault(_simpleAssign);
  21. var _react = require('react');
  22. var _react2 = _interopRequireDefault(_react);
  23. var _propTypes = require('prop-types');
  24. var _propTypes2 = _interopRequireDefault(_propTypes);
  25. var _reactDom = require('react-dom');
  26. var _reactDom2 = _interopRequireDefault(_reactDom);
  27. var _transitions = require('../styles/transitions');
  28. var _transitions2 = _interopRequireDefault(_transitions);
  29. var _arrowDropDown = require('../svg-icons/navigation/arrow-drop-down');
  30. var _arrowDropDown2 = _interopRequireDefault(_arrowDropDown);
  31. var _Menu = require('../Menu/Menu');
  32. var _Menu2 = _interopRequireDefault(_Menu);
  33. var _ClearFix = require('../internal/ClearFix');
  34. var _ClearFix2 = _interopRequireDefault(_ClearFix);
  35. var _Popover = require('../Popover/Popover');
  36. var _Popover2 = _interopRequireDefault(_Popover);
  37. var _PopoverAnimationVertical = require('../Popover/PopoverAnimationVertical');
  38. var _PopoverAnimationVertical2 = _interopRequireDefault(_PopoverAnimationVertical);
  39. var _keycode = require('keycode');
  40. var _keycode2 = _interopRequireDefault(_keycode);
  41. var _events = require('../utils/events');
  42. var _events2 = _interopRequireDefault(_events);
  43. var _IconButton = require('../IconButton');
  44. var _IconButton2 = _interopRequireDefault(_IconButton);
  45. var _propTypes3 = require('../utils/propTypes');
  46. var _propTypes4 = _interopRequireDefault(_propTypes3);
  47. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  48. function getStyles(props, context) {
  49. var disabled = props.disabled;
  50. var spacing = context.muiTheme.baseTheme.spacing;
  51. var palette = context.muiTheme.baseTheme.palette;
  52. var accentColor = context.muiTheme.dropDownMenu.accentColor;
  53. return {
  54. control: {
  55. cursor: disabled ? 'not-allowed' : 'pointer',
  56. height: '100%',
  57. position: 'relative',
  58. width: '100%'
  59. },
  60. icon: {
  61. fill: accentColor,
  62. position: 'absolute',
  63. right: spacing.desktopGutterLess,
  64. top: (spacing.iconSize - 24) / 2 + spacing.desktopGutterMini / 2
  65. },
  66. iconChildren: {
  67. fill: 'inherit'
  68. },
  69. label: {
  70. color: disabled ? palette.disabledColor : palette.textColor,
  71. height: spacing.desktopToolbarHeight + 'px',
  72. lineHeight: spacing.desktopToolbarHeight + 'px',
  73. overflow: 'hidden',
  74. opacity: 1,
  75. position: 'relative',
  76. paddingLeft: spacing.desktopGutter,
  77. paddingRight: spacing.iconSize * 2 + spacing.desktopGutterMini,
  78. textOverflow: 'ellipsis',
  79. top: 0,
  80. whiteSpace: 'nowrap'
  81. },
  82. labelWhenOpen: {
  83. opacity: 0,
  84. top: spacing.desktopToolbarHeight / 8
  85. },
  86. root: {
  87. display: 'inline-block',
  88. fontSize: spacing.desktopDropDownMenuFontSize,
  89. height: spacing.desktopSubheaderHeight,
  90. fontFamily: context.muiTheme.baseTheme.fontFamily,
  91. outline: 'none',
  92. position: 'relative',
  93. transition: _transitions2.default.easeOut()
  94. },
  95. rootWhenOpen: {
  96. opacity: 1
  97. },
  98. underline: {
  99. borderTop: 'solid 1px ' + accentColor,
  100. bottom: 1,
  101. left: 0,
  102. margin: '-1px ' + spacing.desktopGutter + 'px',
  103. right: 0,
  104. position: 'absolute'
  105. }
  106. };
  107. }
  108. var DropDownMenu = function (_Component) {
  109. (0, _inherits3.default)(DropDownMenu, _Component);
  110. function DropDownMenu() {
  111. var _ref;
  112. var _temp, _this, _ret;
  113. (0, _classCallCheck3.default)(this, DropDownMenu);
  114. for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
  115. args[_key] = arguments[_key];
  116. }
  117. return _ret = (_temp = (_this = (0, _possibleConstructorReturn3.default)(this, (_ref = DropDownMenu.__proto__ || (0, _getPrototypeOf2.default)(DropDownMenu)).call.apply(_ref, [this].concat(args))), _this), _this.state = {
  118. open: false
  119. }, _this.rootNode = undefined, _this.arrowNode = undefined, _this.handleClickControl = function (event) {
  120. event.preventDefault();
  121. if (!_this.props.disabled) {
  122. _this.setState({
  123. open: !_this.state.open,
  124. anchorEl: _this.rootNode
  125. });
  126. }
  127. }, _this.handleRequestCloseMenu = function () {
  128. _this.close(false);
  129. }, _this.handleEscKeyDownMenu = function () {
  130. _this.close(true);
  131. }, _this.handleKeyDown = function (event) {
  132. switch ((0, _keycode2.default)(event)) {
  133. case 'up':
  134. case 'down':
  135. case 'space':
  136. case 'enter':
  137. event.preventDefault();
  138. _this.setState({
  139. open: true,
  140. anchorEl: _this.rootNode
  141. });
  142. break;
  143. }
  144. }, _this.handleItemClick = function (event, child, index) {
  145. if (_this.props.multiple) {
  146. if (!_this.state.open) {
  147. _this.setState({ open: true });
  148. }
  149. } else {
  150. event.persist();
  151. _this.setState({
  152. open: false
  153. }, function () {
  154. if (_this.props.onChange) {
  155. _this.props.onChange(event, index, child.props.value);
  156. }
  157. _this.close(_events2.default.isKeyboard(event));
  158. });
  159. }
  160. }, _this.handleChange = function (event, value) {
  161. if (_this.props.multiple && _this.props.onChange) {
  162. _this.props.onChange(event, undefined, value);
  163. }
  164. }, _this.close = function (isKeyboard) {
  165. _this.setState({
  166. open: false
  167. }, function () {
  168. if (_this.props.onClose) {
  169. _this.props.onClose();
  170. }
  171. if (isKeyboard) {
  172. var dropArrow = _this.arrowNode;
  173. var dropNode = _reactDom2.default.findDOMNode(dropArrow);
  174. dropNode.focus();
  175. dropArrow.setKeyboardFocus(true);
  176. }
  177. });
  178. }, _temp), (0, _possibleConstructorReturn3.default)(_this, _ret);
  179. }
  180. // The nested styles for drop-down-menu are modified by toolbar and possibly
  181. // other user components, so it will give full access to its js styles rather
  182. // than just the parent.
  183. (0, _createClass3.default)(DropDownMenu, [{
  184. key: 'componentDidMount',
  185. value: function componentDidMount() {
  186. var _this2 = this;
  187. if (this.props.autoWidth) {
  188. this.setWidth();
  189. }
  190. if (this.props.openImmediately) {
  191. // TODO: Temporary fix to make openImmediately work with popover.
  192. /* eslint-disable react/no-did-mount-set-state */
  193. setTimeout(function () {
  194. return _this2.setState({
  195. open: true,
  196. anchorEl: _this2.rootNode
  197. });
  198. }, 0);
  199. /* eslint-enable react/no-did-mount-set-state */
  200. }
  201. }
  202. }, {
  203. key: 'componentWillReceiveProps',
  204. value: function componentWillReceiveProps() {
  205. if (this.props.autoWidth) {
  206. this.setWidth();
  207. }
  208. }
  209. }, {
  210. key: 'getInputNode',
  211. /**
  212. * This method is deprecated but still here because the TextField
  213. * need it in order to work. TODO: That will be addressed later.
  214. */
  215. value: function getInputNode() {
  216. var _this3 = this;
  217. var rootNode = this.rootNode;
  218. rootNode.focus = function () {
  219. if (!_this3.props.disabled) {
  220. _this3.setState({
  221. open: !_this3.state.open,
  222. anchorEl: _this3.rootNode
  223. });
  224. }
  225. };
  226. return rootNode;
  227. }
  228. }, {
  229. key: 'setWidth',
  230. value: function setWidth() {
  231. var el = this.rootNode;
  232. if (!this.props.style || !this.props.style.hasOwnProperty('width')) {
  233. el.style.width = 'auto';
  234. }
  235. }
  236. }, {
  237. key: 'render',
  238. value: function render() {
  239. var _this4 = this;
  240. var _props = this.props,
  241. animated = _props.animated,
  242. animation = _props.animation,
  243. autoWidth = _props.autoWidth,
  244. multiple = _props.multiple,
  245. children = _props.children,
  246. className = _props.className,
  247. disabled = _props.disabled,
  248. iconStyle = _props.iconStyle,
  249. labelStyle = _props.labelStyle,
  250. listStyle = _props.listStyle,
  251. maxHeight = _props.maxHeight,
  252. menuStyleProp = _props.menuStyle,
  253. selectionRenderer = _props.selectionRenderer,
  254. onClose = _props.onClose,
  255. openImmediately = _props.openImmediately,
  256. menuItemStyle = _props.menuItemStyle,
  257. selectedMenuItemStyle = _props.selectedMenuItemStyle,
  258. style = _props.style,
  259. underlineStyle = _props.underlineStyle,
  260. value = _props.value,
  261. iconButton = _props.iconButton,
  262. anchorOrigin = _props.anchorOrigin,
  263. targetOrigin = _props.targetOrigin,
  264. other = (0, _objectWithoutProperties3.default)(_props, ['animated', 'animation', 'autoWidth', 'multiple', 'children', 'className', 'disabled', 'iconStyle', 'labelStyle', 'listStyle', 'maxHeight', 'menuStyle', 'selectionRenderer', 'onClose', 'openImmediately', 'menuItemStyle', 'selectedMenuItemStyle', 'style', 'underlineStyle', 'value', 'iconButton', 'anchorOrigin', 'targetOrigin']);
  265. var _state = this.state,
  266. anchorEl = _state.anchorEl,
  267. open = _state.open;
  268. var prepareStyles = this.context.muiTheme.prepareStyles;
  269. var styles = getStyles(this.props, this.context);
  270. var displayValue = '';
  271. if (!multiple) {
  272. _react2.default.Children.forEach(children, function (child) {
  273. if (child && value === child.props.value) {
  274. if (selectionRenderer) {
  275. displayValue = selectionRenderer(value, child);
  276. } else {
  277. // This will need to be improved (in case primaryText is a node)
  278. displayValue = child.props.label || child.props.primaryText;
  279. }
  280. }
  281. });
  282. } else {
  283. var values = [];
  284. var selectionRendererChildren = [];
  285. _react2.default.Children.forEach(children, function (child) {
  286. if (child && value && value.indexOf(child.props.value) > -1) {
  287. if (selectionRenderer) {
  288. values.push(child.props.value);
  289. selectionRendererChildren.push(child);
  290. } else {
  291. values.push(child.props.label || child.props.primaryText);
  292. }
  293. }
  294. });
  295. displayValue = [];
  296. if (selectionRenderer) {
  297. displayValue = selectionRenderer(values, selectionRendererChildren);
  298. } else {
  299. displayValue = values.join(', ');
  300. }
  301. }
  302. var menuStyle = void 0;
  303. if (anchorEl && !autoWidth) {
  304. menuStyle = (0, _simpleAssign2.default)({
  305. width: anchorEl.clientWidth
  306. }, menuStyleProp);
  307. } else {
  308. menuStyle = menuStyleProp;
  309. }
  310. return _react2.default.createElement(
  311. 'div',
  312. (0, _extends3.default)({}, other, {
  313. ref: function ref(node) {
  314. _this4.rootNode = node;
  315. },
  316. className: className,
  317. style: prepareStyles((0, _simpleAssign2.default)({}, styles.root, open && styles.rootWhenOpen, style))
  318. }),
  319. _react2.default.createElement(
  320. _ClearFix2.default,
  321. { style: styles.control, onClick: this.handleClickControl },
  322. _react2.default.createElement(
  323. 'div',
  324. { style: prepareStyles((0, _simpleAssign2.default)({}, styles.label, open && styles.labelWhenOpen, labelStyle)) },
  325. displayValue
  326. ),
  327. _react2.default.createElement(
  328. _IconButton2.default,
  329. {
  330. disabled: disabled,
  331. onKeyDown: this.handleKeyDown,
  332. ref: function ref(node) {
  333. _this4.arrowNode = node;
  334. },
  335. style: (0, _simpleAssign2.default)({}, styles.icon, iconStyle),
  336. iconStyle: styles.iconChildren
  337. },
  338. iconButton
  339. ),
  340. _react2.default.createElement('div', { style: prepareStyles((0, _simpleAssign2.default)({}, styles.underline, underlineStyle)) })
  341. ),
  342. _react2.default.createElement(
  343. _Popover2.default,
  344. {
  345. anchorOrigin: anchorOrigin,
  346. targetOrigin: targetOrigin,
  347. anchorEl: anchorEl,
  348. animation: animation || _PopoverAnimationVertical2.default,
  349. open: open,
  350. animated: animated,
  351. onRequestClose: this.handleRequestCloseMenu
  352. },
  353. _react2.default.createElement(
  354. _Menu2.default,
  355. {
  356. multiple: multiple,
  357. maxHeight: maxHeight,
  358. desktop: true,
  359. value: value,
  360. onEscKeyDown: this.handleEscKeyDownMenu,
  361. style: menuStyle,
  362. listStyle: listStyle,
  363. onItemClick: this.handleItemClick,
  364. onChange: this.handleChange,
  365. menuItemStyle: menuItemStyle,
  366. selectedMenuItemStyle: selectedMenuItemStyle,
  367. autoWidth: autoWidth,
  368. width: !autoWidth && menuStyle ? menuStyle.width : null
  369. },
  370. children
  371. )
  372. )
  373. );
  374. }
  375. }]);
  376. return DropDownMenu;
  377. }(_react.Component);
  378. DropDownMenu.muiName = 'DropDownMenu';
  379. DropDownMenu.defaultProps = {
  380. animated: true,
  381. autoWidth: true,
  382. disabled: false,
  383. iconButton: _react2.default.createElement(_arrowDropDown2.default, null),
  384. openImmediately: false,
  385. maxHeight: 500,
  386. multiple: false,
  387. anchorOrigin: {
  388. vertical: 'top',
  389. horizontal: 'left'
  390. }
  391. };
  392. DropDownMenu.contextTypes = {
  393. muiTheme: _propTypes2.default.object.isRequired
  394. };
  395. DropDownMenu.propTypes = process.env.NODE_ENV !== "production" ? {
  396. /**
  397. * This is the point on the anchor that the popover's
  398. * `targetOrigin` will attach to.
  399. * Options:
  400. * vertical: [top, center, bottom]
  401. * horizontal: [left, middle, right].
  402. */
  403. anchorOrigin: _propTypes4.default.origin,
  404. /**
  405. * If true, the popover will apply transitions when
  406. * it gets added to the DOM.
  407. */
  408. animated: _propTypes2.default.bool,
  409. /**
  410. * Override the default animation component used.
  411. */
  412. animation: _propTypes2.default.func,
  413. /**
  414. * The width will automatically be set according to the items inside the menu.
  415. * To control this width in css instead, set this prop to `false`.
  416. */
  417. autoWidth: _propTypes2.default.bool,
  418. /**
  419. * The `MenuItem`s to populate the `Menu` with. If the `MenuItems` have the
  420. * prop `label` that value will be used to render the representation of that
  421. * item within the field.
  422. */
  423. children: _propTypes2.default.node,
  424. /**
  425. * The css class name of the root element.
  426. */
  427. className: _propTypes2.default.string,
  428. /**
  429. * Disables the menu.
  430. */
  431. disabled: _propTypes2.default.bool,
  432. /**
  433. * Overrides default `SvgIcon` dropdown arrow component.
  434. */
  435. iconButton: _propTypes2.default.node,
  436. /**
  437. * Overrides the styles of icon element.
  438. */
  439. iconStyle: _propTypes2.default.object,
  440. /**
  441. * Overrides the styles of label when the `DropDownMenu` is inactive.
  442. */
  443. labelStyle: _propTypes2.default.object,
  444. /**
  445. * The style object to use to override underlying list style.
  446. */
  447. listStyle: _propTypes2.default.object,
  448. /**
  449. * The maximum height of the `Menu` when it is displayed.
  450. */
  451. maxHeight: _propTypes2.default.number,
  452. /**
  453. * Override the inline-styles of menu items.
  454. */
  455. menuItemStyle: _propTypes2.default.object,
  456. /**
  457. * Overrides the styles of `Menu` when the `DropDownMenu` is displayed.
  458. */
  459. menuStyle: _propTypes2.default.object,
  460. /**
  461. * If true, `value` must be an array and the menu will support
  462. * multiple selections.
  463. */
  464. multiple: _propTypes2.default.bool,
  465. /**
  466. * Callback function fired when a menu item is clicked, other than the one currently selected.
  467. *
  468. * @param {object} event Click event targeting the menu item that was clicked.
  469. * @param {number} key The index of the clicked menu item in the `children` collection.
  470. * @param {any} value If `multiple` is true, the menu's `value`
  471. * array with either the menu item's `value` added (if
  472. * it wasn't already selected) or omitted (if it was already selected).
  473. * Otherwise, the `value` of the menu item.
  474. */
  475. onChange: _propTypes2.default.func,
  476. /**
  477. * Callback function fired when the menu is closed.
  478. */
  479. onClose: _propTypes2.default.func,
  480. /**
  481. * Set to true to have the `DropDownMenu` automatically open on mount.
  482. */
  483. openImmediately: _propTypes2.default.bool,
  484. /**
  485. * Override the inline-styles of selected menu items.
  486. */
  487. selectedMenuItemStyle: _propTypes2.default.object,
  488. /**
  489. * Callback function fired when a menu item is clicked, other than the one currently selected.
  490. *
  491. * @param {any} value If `multiple` is true, the menu's `value`
  492. * array with either the menu item's `value` added (if
  493. * it wasn't already selected) or omitted (if it was already selected).
  494. * Otherwise, the `value` of the menu item.
  495. * @param {any} menuItem The selected `MenuItem`.
  496. * If `multiple` is true, this will be an array with the `MenuItem`s matching the `value`s parameter.
  497. */
  498. selectionRenderer: _propTypes2.default.func,
  499. /**
  500. * Override the inline-styles of the root element.
  501. */
  502. style: _propTypes2.default.object,
  503. /**
  504. * This is the point on the popover which will attach to
  505. * the anchor's origin.
  506. * Options:
  507. * vertical: [top, center, bottom]
  508. * horizontal: [left, middle, right].
  509. */
  510. targetOrigin: _propTypes4.default.origin,
  511. /**
  512. * Overrides the inline-styles of the underline.
  513. */
  514. underlineStyle: _propTypes2.default.object,
  515. /**
  516. * If `multiple` is true, an array of the `value`s of the selected
  517. * menu items. Otherwise, the `value` of the selected menu item.
  518. * If provided, the menu will be a controlled component.
  519. */
  520. value: _propTypes2.default.any
  521. } : {};
  522. exports.default = DropDownMenu;