fix menu
							parent
							
								
									fb4a9970ef
								
							
						
					
					
						commit
						e918a45e03
					
				|  | @ -0,0 +1,521 @@ | |||
| /** | ||||
|  * @ignore | ||||
|  * some key-codes definition and utils from closure-library | ||||
|  * @author yiminghe@gmail.com | ||||
|  */ | ||||
| 
 | ||||
| const KeyCode = { | ||||
|   /** | ||||
|    * MAC_ENTER | ||||
|    */ | ||||
|   MAC_ENTER: 3, | ||||
|   /** | ||||
|    * BACKSPACE | ||||
|    */ | ||||
|   BACKSPACE: 8, | ||||
|   /** | ||||
|    * TAB | ||||
|    */ | ||||
|   TAB: 9, | ||||
|   /** | ||||
|    * NUMLOCK on FF/Safari Mac | ||||
|    */ | ||||
|   NUM_CENTER: 12, // NUMLOCK on FF/Safari Mac
 | ||||
|   /** | ||||
|    * ENTER | ||||
|    */ | ||||
|   ENTER: 13, | ||||
|   /** | ||||
|    * SHIFT | ||||
|    */ | ||||
|   SHIFT: 16, | ||||
|   /** | ||||
|    * CTRL | ||||
|    */ | ||||
|   CTRL: 17, | ||||
|   /** | ||||
|    * ALT | ||||
|    */ | ||||
|   ALT: 18, | ||||
|   /** | ||||
|    * PAUSE | ||||
|    */ | ||||
|   PAUSE: 19, | ||||
|   /** | ||||
|    * CAPS_LOCK | ||||
|    */ | ||||
|   CAPS_LOCK: 20, | ||||
|   /** | ||||
|    * ESC | ||||
|    */ | ||||
|   ESC: 27, | ||||
|   /** | ||||
|    * SPACE | ||||
|    */ | ||||
|   SPACE: 32, | ||||
|   /** | ||||
|    * PAGE_UP | ||||
|    */ | ||||
|   PAGE_UP: 33, // also NUM_NORTH_EAST
 | ||||
|   /** | ||||
|    * PAGE_DOWN | ||||
|    */ | ||||
|   PAGE_DOWN: 34, // also NUM_SOUTH_EAST
 | ||||
|   /** | ||||
|    * END | ||||
|    */ | ||||
|   END: 35, // also NUM_SOUTH_WEST
 | ||||
|   /** | ||||
|    * HOME | ||||
|    */ | ||||
|   HOME: 36, // also NUM_NORTH_WEST
 | ||||
|   /** | ||||
|    * LEFT | ||||
|    */ | ||||
|   LEFT: 37, // also NUM_WEST
 | ||||
|   /** | ||||
|    * UP | ||||
|    */ | ||||
|   UP: 38, // also NUM_NORTH
 | ||||
|   /** | ||||
|    * RIGHT | ||||
|    */ | ||||
|   RIGHT: 39, // also NUM_EAST
 | ||||
|   /** | ||||
|    * DOWN | ||||
|    */ | ||||
|   DOWN: 40, // also NUM_SOUTH
 | ||||
|   /** | ||||
|    * PRINT_SCREEN | ||||
|    */ | ||||
|   PRINT_SCREEN: 44, | ||||
|   /** | ||||
|    * INSERT | ||||
|    */ | ||||
|   INSERT: 45, // also NUM_INSERT
 | ||||
|   /** | ||||
|    * DELETE | ||||
|    */ | ||||
|   DELETE: 46, // also NUM_DELETE
 | ||||
|   /** | ||||
|    * ZERO | ||||
|    */ | ||||
|   ZERO: 48, | ||||
|   /** | ||||
|    * ONE | ||||
|    */ | ||||
|   ONE: 49, | ||||
|   /** | ||||
|    * TWO | ||||
|    */ | ||||
|   TWO: 50, | ||||
|   /** | ||||
|    * THREE | ||||
|    */ | ||||
|   THREE: 51, | ||||
|   /** | ||||
|    * FOUR | ||||
|    */ | ||||
|   FOUR: 52, | ||||
|   /** | ||||
|    * FIVE | ||||
|    */ | ||||
|   FIVE: 53, | ||||
|   /** | ||||
|    * SIX | ||||
|    */ | ||||
|   SIX: 54, | ||||
|   /** | ||||
|    * SEVEN | ||||
|    */ | ||||
|   SEVEN: 55, | ||||
|   /** | ||||
|    * EIGHT | ||||
|    */ | ||||
|   EIGHT: 56, | ||||
|   /** | ||||
|    * NINE | ||||
|    */ | ||||
|   NINE: 57, | ||||
|   /** | ||||
|    * QUESTION_MARK | ||||
|    */ | ||||
|   QUESTION_MARK: 63, // needs localization
 | ||||
|   /** | ||||
|    * A | ||||
|    */ | ||||
|   A: 65, | ||||
|   /** | ||||
|    * B | ||||
|    */ | ||||
|   B: 66, | ||||
|   /** | ||||
|    * C | ||||
|    */ | ||||
|   C: 67, | ||||
|   /** | ||||
|    * D | ||||
|    */ | ||||
|   D: 68, | ||||
|   /** | ||||
|    * E | ||||
|    */ | ||||
|   E: 69, | ||||
|   /** | ||||
|    * F | ||||
|    */ | ||||
|   F: 70, | ||||
|   /** | ||||
|    * G | ||||
|    */ | ||||
|   G: 71, | ||||
|   /** | ||||
|    * H | ||||
|    */ | ||||
|   H: 72, | ||||
|   /** | ||||
|    * I | ||||
|    */ | ||||
|   I: 73, | ||||
|   /** | ||||
|    * J | ||||
|    */ | ||||
|   J: 74, | ||||
|   /** | ||||
|    * K | ||||
|    */ | ||||
|   K: 75, | ||||
|   /** | ||||
|    * L | ||||
|    */ | ||||
|   L: 76, | ||||
|   /** | ||||
|    * M | ||||
|    */ | ||||
|   M: 77, | ||||
|   /** | ||||
|    * N | ||||
|    */ | ||||
|   N: 78, | ||||
|   /** | ||||
|    * O | ||||
|    */ | ||||
|   O: 79, | ||||
|   /** | ||||
|    * P | ||||
|    */ | ||||
|   P: 80, | ||||
|   /** | ||||
|    * Q | ||||
|    */ | ||||
|   Q: 81, | ||||
|   /** | ||||
|    * R | ||||
|    */ | ||||
|   R: 82, | ||||
|   /** | ||||
|    * S | ||||
|    */ | ||||
|   S: 83, | ||||
|   /** | ||||
|    * T | ||||
|    */ | ||||
|   T: 84, | ||||
|   /** | ||||
|    * U | ||||
|    */ | ||||
|   U: 85, | ||||
|   /** | ||||
|    * V | ||||
|    */ | ||||
|   V: 86, | ||||
|   /** | ||||
|    * W | ||||
|    */ | ||||
|   W: 87, | ||||
|   /** | ||||
|    * X | ||||
|    */ | ||||
|   X: 88, | ||||
|   /** | ||||
|    * Y | ||||
|    */ | ||||
|   Y: 89, | ||||
|   /** | ||||
|    * Z | ||||
|    */ | ||||
|   Z: 90, | ||||
|   /** | ||||
|    * META | ||||
|    */ | ||||
|   META: 91, // WIN_KEY_LEFT
 | ||||
|   /** | ||||
|    * WIN_KEY_RIGHT | ||||
|    */ | ||||
|   WIN_KEY_RIGHT: 92, | ||||
|   /** | ||||
|    * CONTEXT_MENU | ||||
|    */ | ||||
|   CONTEXT_MENU: 93, | ||||
|   /** | ||||
|    * NUM_ZERO | ||||
|    */ | ||||
|   NUM_ZERO: 96, | ||||
|   /** | ||||
|    * NUM_ONE | ||||
|    */ | ||||
|   NUM_ONE: 97, | ||||
|   /** | ||||
|    * NUM_TWO | ||||
|    */ | ||||
|   NUM_TWO: 98, | ||||
|   /** | ||||
|    * NUM_THREE | ||||
|    */ | ||||
|   NUM_THREE: 99, | ||||
|   /** | ||||
|    * NUM_FOUR | ||||
|    */ | ||||
|   NUM_FOUR: 100, | ||||
|   /** | ||||
|    * NUM_FIVE | ||||
|    */ | ||||
|   NUM_FIVE: 101, | ||||
|   /** | ||||
|    * NUM_SIX | ||||
|    */ | ||||
|   NUM_SIX: 102, | ||||
|   /** | ||||
|    * NUM_SEVEN | ||||
|    */ | ||||
|   NUM_SEVEN: 103, | ||||
|   /** | ||||
|    * NUM_EIGHT | ||||
|    */ | ||||
|   NUM_EIGHT: 104, | ||||
|   /** | ||||
|    * NUM_NINE | ||||
|    */ | ||||
|   NUM_NINE: 105, | ||||
|   /** | ||||
|    * NUM_MULTIPLY | ||||
|    */ | ||||
|   NUM_MULTIPLY: 106, | ||||
|   /** | ||||
|    * NUM_PLUS | ||||
|    */ | ||||
|   NUM_PLUS: 107, | ||||
|   /** | ||||
|    * NUM_MINUS | ||||
|    */ | ||||
|   NUM_MINUS: 109, | ||||
|   /** | ||||
|    * NUM_PERIOD | ||||
|    */ | ||||
|   NUM_PERIOD: 110, | ||||
|   /** | ||||
|    * NUM_DIVISION | ||||
|    */ | ||||
|   NUM_DIVISION: 111, | ||||
|   /** | ||||
|    * F1 | ||||
|    */ | ||||
|   F1: 112, | ||||
|   /** | ||||
|    * F2 | ||||
|    */ | ||||
|   F2: 113, | ||||
|   /** | ||||
|    * F3 | ||||
|    */ | ||||
|   F3: 114, | ||||
|   /** | ||||
|    * F4 | ||||
|    */ | ||||
|   F4: 115, | ||||
|   /** | ||||
|    * F5 | ||||
|    */ | ||||
|   F5: 116, | ||||
|   /** | ||||
|    * F6 | ||||
|    */ | ||||
|   F6: 117, | ||||
|   /** | ||||
|    * F7 | ||||
|    */ | ||||
|   F7: 118, | ||||
|   /** | ||||
|    * F8 | ||||
|    */ | ||||
|   F8: 119, | ||||
|   /** | ||||
|    * F9 | ||||
|    */ | ||||
|   F9: 120, | ||||
|   /** | ||||
|    * F10 | ||||
|    */ | ||||
|   F10: 121, | ||||
|   /** | ||||
|    * F11 | ||||
|    */ | ||||
|   F11: 122, | ||||
|   /** | ||||
|    * F12 | ||||
|    */ | ||||
|   F12: 123, | ||||
|   /** | ||||
|    * NUMLOCK | ||||
|    */ | ||||
|   NUMLOCK: 144, | ||||
|   /** | ||||
|    * SEMICOLON | ||||
|    */ | ||||
|   SEMICOLON: 186, // needs localization
 | ||||
|   /** | ||||
|    * DASH | ||||
|    */ | ||||
|   DASH: 189, // needs localization
 | ||||
|   /** | ||||
|    * EQUALS | ||||
|    */ | ||||
|   EQUALS: 187, // needs localization
 | ||||
|   /** | ||||
|    * COMMA | ||||
|    */ | ||||
|   COMMA: 188, // needs localization
 | ||||
|   /** | ||||
|    * PERIOD | ||||
|    */ | ||||
|   PERIOD: 190, // needs localization
 | ||||
|   /** | ||||
|    * SLASH | ||||
|    */ | ||||
|   SLASH: 191, // needs localization
 | ||||
|   /** | ||||
|    * APOSTROPHE | ||||
|    */ | ||||
|   APOSTROPHE: 192, // needs localization
 | ||||
|   /** | ||||
|    * SINGLE_QUOTE | ||||
|    */ | ||||
|   SINGLE_QUOTE: 222, // needs localization
 | ||||
|   /** | ||||
|    * OPEN_SQUARE_BRACKET | ||||
|    */ | ||||
|   OPEN_SQUARE_BRACKET: 219, // needs localization
 | ||||
|   /** | ||||
|    * BACKSLASH | ||||
|    */ | ||||
|   BACKSLASH: 220, // needs localization
 | ||||
|   /** | ||||
|    * CLOSE_SQUARE_BRACKET | ||||
|    */ | ||||
|   CLOSE_SQUARE_BRACKET: 221, // needs localization
 | ||||
|   /** | ||||
|    * WIN_KEY | ||||
|    */ | ||||
|   WIN_KEY: 224, | ||||
|   /** | ||||
|    * MAC_FF_META | ||||
|    */ | ||||
|   MAC_FF_META: 224, // Firefox (Gecko) fires this for the meta key instead of 91
 | ||||
|   /** | ||||
|    * WIN_IME | ||||
|    */ | ||||
|   WIN_IME: 229, | ||||
| } | ||||
| 
 | ||||
| /* | ||||
|  whether text and modified key is entered at the same time. | ||||
|  */ | ||||
| KeyCode.isTextModifyingKeyEvent = function isTextModifyingKeyEvent (e) { | ||||
|   const keyCode = e.keyCode | ||||
|   if (e.altKey && !e.ctrlKey || e.metaKey || | ||||
|   // Function keys don't generate text
 | ||||
|     keyCode >= KeyCode.F1 && keyCode <= KeyCode.F12) { | ||||
|     return false | ||||
|   } | ||||
| 
 | ||||
|   // The following keys are quite harmless, even in combination with
 | ||||
|   // CTRL, ALT or SHIFT.
 | ||||
|   switch (keyCode) { | ||||
|     case KeyCode.ALT: | ||||
|     case KeyCode.CAPS_LOCK: | ||||
|     case KeyCode.CONTEXT_MENU: | ||||
|     case KeyCode.CTRL: | ||||
|     case KeyCode.DOWN: | ||||
|     case KeyCode.END: | ||||
|     case KeyCode.ESC: | ||||
|     case KeyCode.HOME: | ||||
|     case KeyCode.INSERT: | ||||
|     case KeyCode.LEFT: | ||||
|     case KeyCode.MAC_FF_META: | ||||
|     case KeyCode.META: | ||||
|     case KeyCode.NUMLOCK: | ||||
|     case KeyCode.NUM_CENTER: | ||||
|     case KeyCode.PAGE_DOWN: | ||||
|     case KeyCode.PAGE_UP: | ||||
|     case KeyCode.PAUSE: | ||||
|     case KeyCode.PRINT_SCREEN: | ||||
|     case KeyCode.RIGHT: | ||||
|     case KeyCode.SHIFT: | ||||
|     case KeyCode.UP: | ||||
|     case KeyCode.WIN_KEY: | ||||
|     case KeyCode.WIN_KEY_RIGHT: | ||||
|       return false | ||||
|     default: | ||||
|       return true | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /* | ||||
|  whether character is entered. | ||||
|  */ | ||||
| KeyCode.isCharacterKey = function isCharacterKey (keyCode) { | ||||
|   if (keyCode >= KeyCode.ZERO && | ||||
|     keyCode <= KeyCode.NINE) { | ||||
|     return true | ||||
|   } | ||||
| 
 | ||||
|   if (keyCode >= KeyCode.NUM_ZERO && | ||||
|     keyCode <= KeyCode.NUM_MULTIPLY) { | ||||
|     return true | ||||
|   } | ||||
| 
 | ||||
|   if (keyCode >= KeyCode.A && | ||||
|     keyCode <= KeyCode.Z) { | ||||
|     return true | ||||
|   } | ||||
| 
 | ||||
|   // Safari sends zero key code for non-latin characters.
 | ||||
|   if (window.navigation.userAgent.indexOf('WebKit') !== -1 && keyCode === 0) { | ||||
|     return true | ||||
|   } | ||||
| 
 | ||||
|   switch (keyCode) { | ||||
|     case KeyCode.SPACE: | ||||
|     case KeyCode.QUESTION_MARK: | ||||
|     case KeyCode.NUM_PLUS: | ||||
|     case KeyCode.NUM_MINUS: | ||||
|     case KeyCode.NUM_PERIOD: | ||||
|     case KeyCode.NUM_DIVISION: | ||||
|     case KeyCode.SEMICOLON: | ||||
|     case KeyCode.DASH: | ||||
|     case KeyCode.EQUALS: | ||||
|     case KeyCode.COMMA: | ||||
|     case KeyCode.PERIOD: | ||||
|     case KeyCode.SLASH: | ||||
|     case KeyCode.APOSTROPHE: | ||||
|     case KeyCode.SINGLE_QUOTE: | ||||
|     case KeyCode.OPEN_SQUARE_BRACKET: | ||||
|     case KeyCode.BACKSLASH: | ||||
|     case KeyCode.CLOSE_SQUARE_BRACKET: | ||||
|       return true | ||||
|     default: | ||||
|       return false | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| export default KeyCode | ||||
|  | @ -1,221 +0,0 @@ | |||
| // import React from 'react'; | ||||
| import PropTypes from 'prop-types' | ||||
| import createReactClass from 'create-react-class' | ||||
| import MenuMixin from './MenuMixin' | ||||
| import { noop } from './util' | ||||
| 
 | ||||
| const Menu = createReactClass({ | ||||
|   displayName: 'Menu', | ||||
| 
 | ||||
|   propTypes: { | ||||
|     defaultSelectedKeys: PropTypes.arrayOf(PropTypes.string), | ||||
|     selectedKeys: PropTypes.arrayOf(PropTypes.string), | ||||
|     defaultOpenKeys: PropTypes.arrayOf(PropTypes.string), | ||||
|     openKeys: PropTypes.arrayOf(PropTypes.string), | ||||
|     mode: PropTypes.oneOf(['horizontal', 'vertical', 'vertical-left', 'vertical-right', 'inline']), | ||||
|     getPopupContainer: PropTypes.func, | ||||
|     onClick: PropTypes.func, | ||||
|     onSelect: PropTypes.func, | ||||
|     onDeselect: PropTypes.func, | ||||
|     onDestroy: PropTypes.func, | ||||
|     openTransitionName: PropTypes.string, | ||||
|     openAnimation: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), | ||||
|     subMenuOpenDelay: PropTypes.number, | ||||
|     subMenuCloseDelay: PropTypes.number, | ||||
|     forceSubMenuRender: PropTypes.bool, | ||||
|     triggerSubMenuAction: PropTypes.string, | ||||
|     level: PropTypes.number, | ||||
|     selectable: PropTypes.bool, | ||||
|     multiple: PropTypes.bool, | ||||
|     children: PropTypes.any, | ||||
|   }, | ||||
| 
 | ||||
|   mixins: [MenuMixin], | ||||
| 
 | ||||
|   isRootMenu: true, | ||||
| 
 | ||||
|   getDefaultProps () { | ||||
|     return { | ||||
|       selectable: true, | ||||
|       onClick: noop, | ||||
|       onSelect: noop, | ||||
|       onOpenChange: noop, | ||||
|       onDeselect: noop, | ||||
|       defaultSelectedKeys: [], | ||||
|       defaultOpenKeys: [], | ||||
|       subMenuOpenDelay: 0, | ||||
|       subMenuCloseDelay: 0.1, | ||||
|       triggerSubMenuAction: 'hover', | ||||
|     } | ||||
|   }, | ||||
| 
 | ||||
|   getInitialState () { | ||||
|     const props = this.props | ||||
|     let selectedKeys = props.defaultSelectedKeys | ||||
|     let openKeys = props.defaultOpenKeys | ||||
|     if ('selectedKeys' in props) { | ||||
|       selectedKeys = props.selectedKeys || [] | ||||
|     } | ||||
|     if ('openKeys' in props) { | ||||
|       openKeys = props.openKeys || [] | ||||
|     } | ||||
|     return { | ||||
|       selectedKeys, | ||||
|       openKeys, | ||||
|     } | ||||
|   }, | ||||
| 
 | ||||
|   componentWillReceiveProps (nextProps) { | ||||
|     const props = {} | ||||
|     if ('selectedKeys' in nextProps) { | ||||
|       props.selectedKeys = nextProps.selectedKeys || [] | ||||
|     } | ||||
|     if ('openKeys' in nextProps) { | ||||
|       props.openKeys = nextProps.openKeys || [] | ||||
|     } | ||||
|     this.setState(props) | ||||
|   }, | ||||
| 
 | ||||
|   onDestroy (key) { | ||||
|     const state = this.state | ||||
|     const props = this.props | ||||
|     const selectedKeys = state.selectedKeys | ||||
|     const openKeys = state.openKeys | ||||
|     let index = selectedKeys.indexOf(key) | ||||
|     if (!('selectedKeys' in props) && index !== -1) { | ||||
|       selectedKeys.splice(index, 1) | ||||
|     } | ||||
|     index = openKeys.indexOf(key) | ||||
|     if (!('openKeys' in props) && index !== -1) { | ||||
|       openKeys.splice(index, 1) | ||||
|     } | ||||
|   }, | ||||
| 
 | ||||
|   onSelect (selectInfo) { | ||||
|     const props = this.props | ||||
|     if (props.selectable) { | ||||
|       // root menu | ||||
|       let selectedKeys = this.state.selectedKeys | ||||
|       const selectedKey = selectInfo.key | ||||
|       if (props.multiple) { | ||||
|         selectedKeys = selectedKeys.concat([selectedKey]) | ||||
|       } else { | ||||
|         selectedKeys = [selectedKey] | ||||
|       } | ||||
|       if (!('selectedKeys' in props)) { | ||||
|         this.setState({ | ||||
|           selectedKeys, | ||||
|         }) | ||||
|       } | ||||
|       props.onSelect({ | ||||
|         ...selectInfo, | ||||
|         selectedKeys, | ||||
|       }) | ||||
|     } | ||||
|   }, | ||||
| 
 | ||||
|   onClick (e) { | ||||
|     this.props.onClick(e) | ||||
|   }, | ||||
| 
 | ||||
|   onOpenChange (e_) { | ||||
|     const props = this.props | ||||
|     const openKeys = this.state.openKeys.concat() | ||||
|     let changed = false | ||||
|     const processSingle = (e) => { | ||||
|       let oneChanged = false | ||||
|       if (e.open) { | ||||
|         oneChanged = openKeys.indexOf(e.key) === -1 | ||||
|         if (oneChanged) { | ||||
|           openKeys.push(e.key) | ||||
|         } | ||||
|       } else { | ||||
|         const index = openKeys.indexOf(e.key) | ||||
|         oneChanged = index !== -1 | ||||
|         if (oneChanged) { | ||||
|           openKeys.splice(index, 1) | ||||
|         } | ||||
|       } | ||||
|       changed = changed || oneChanged | ||||
|     } | ||||
|     if (Array.isArray(e_)) { | ||||
|       // batch change call | ||||
|       e_.forEach(processSingle) | ||||
|     } else { | ||||
|       processSingle(e_) | ||||
|     } | ||||
|     if (changed) { | ||||
|       if (!('openKeys' in this.props)) { | ||||
|         this.setState({ openKeys }) | ||||
|       } | ||||
|       props.onOpenChange(openKeys) | ||||
|     } | ||||
|   }, | ||||
| 
 | ||||
|   onDeselect (selectInfo) { | ||||
|     const props = this.props | ||||
|     if (props.selectable) { | ||||
|       const selectedKeys = this.state.selectedKeys.concat() | ||||
|       const selectedKey = selectInfo.key | ||||
|       const index = selectedKeys.indexOf(selectedKey) | ||||
|       if (index !== -1) { | ||||
|         selectedKeys.splice(index, 1) | ||||
|       } | ||||
|       if (!('selectedKeys' in props)) { | ||||
|         this.setState({ | ||||
|           selectedKeys, | ||||
|         }) | ||||
|       } | ||||
|       props.onDeselect({ | ||||
|         ...selectInfo, | ||||
|         selectedKeys, | ||||
|       }) | ||||
|     } | ||||
|   }, | ||||
| 
 | ||||
|   getOpenTransitionName () { | ||||
|     const props = this.props | ||||
|     let transitionName = props.openTransitionName | ||||
|     const animationName = props.openAnimation | ||||
|     if (!transitionName && typeof animationName === 'string') { | ||||
|       transitionName = `${props.prefixCls}-open-${animationName}` | ||||
|     } | ||||
|     return transitionName | ||||
|   }, | ||||
| 
 | ||||
|   isInlineMode () { | ||||
|     return this.props.mode === 'inline' | ||||
|   }, | ||||
| 
 | ||||
|   lastOpenSubMenu () { | ||||
|     let lastOpen = [] | ||||
|     const { openKeys } = this.state | ||||
|     if (openKeys.length) { | ||||
|       lastOpen = this.getFlatInstanceArray().filter((c) => { | ||||
|         return c && openKeys.indexOf(c.props.eventKey) !== -1 | ||||
|       }) | ||||
|     } | ||||
|     return lastOpen[0] | ||||
|   }, | ||||
| 
 | ||||
|   renderMenuItem (c, i, subIndex) { | ||||
|     if (!c) { | ||||
|       return null | ||||
|     } | ||||
|     const state = this.state | ||||
|     const extraProps = { | ||||
|       openKeys: state.openKeys, | ||||
|       selectedKeys: state.selectedKeys, | ||||
|       triggerSubMenuAction: this.props.triggerSubMenuAction, | ||||
|     } | ||||
|     return this.renderCommonMenuItem(c, i, subIndex, extraProps) | ||||
|   }, | ||||
| 
 | ||||
|   render () { | ||||
|     const props = { ...this.props } | ||||
|     props.className += ` ${props.prefixCls}-root` | ||||
|     return this.renderRoot(props) | ||||
|   }, | ||||
| }) | ||||
| 
 | ||||
| export default Menu | ||||
|  | @ -0,0 +1,195 @@ | |||
| <script> | ||||
| import PropTypes from 'vue-types' | ||||
| import MenuMixin from './MenuMixin' | ||||
| import StateMixin from '../../_util/StateMixin' | ||||
| 
 | ||||
| const Menu = { | ||||
|   name: 'Menu', | ||||
| 
 | ||||
|   props: { | ||||
|     defaultSelectedKeys: PropTypes.arrayOf(PropTypes.string).def([]), | ||||
|     selectedKeys: PropTypes.arrayOf(PropTypes.string), | ||||
|     defaultOpenKeys: PropTypes.arrayOf(PropTypes.string).def([]), | ||||
|     openKeys: PropTypes.arrayOf(PropTypes.string), | ||||
|     mode: PropTypes.oneOf(['horizontal', 'vertical', 'vertical-left', 'vertical-right', 'inline']).def('vertical'), | ||||
|     getPopupContainer: PropTypes.func, | ||||
|     openTransitionName: PropTypes.string, | ||||
|     openAnimation: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), | ||||
|     subMenuOpenDelay: PropTypes.number.def(0), | ||||
|     subMenuCloseDelay: PropTypes.number.def(0.1), | ||||
|     forceSubMenuRender: PropTypes.bool, | ||||
|     triggerSubMenuAction: PropTypes.string.def('hover'), | ||||
|     level: PropTypes.number.def(1), | ||||
|     selectable: PropTypes.bool.def(true), | ||||
|     multiple: PropTypes.bool, | ||||
|     children: PropTypes.any, | ||||
|   }, | ||||
|   mixins: [StateMixin, MenuMixin], | ||||
| 
 | ||||
|   data () { | ||||
|     const props = this.$props | ||||
|     let selectedKeys = props.defaultSelectedKeys | ||||
|     let openKeys = props.defaultOpenKeys | ||||
|     selectedKeys = props.selectedKeys || [] | ||||
|     openKeys = props.openKeys || [] | ||||
|     return { | ||||
|       selectedKeys, | ||||
|       openKeys, | ||||
|       isRootMenu: true, | ||||
|     } | ||||
|   }, | ||||
| 
 | ||||
|   componentWillReceiveProps (nextProps) { | ||||
|     const props = {} | ||||
|     if ('selectedKeys' in nextProps) { | ||||
|       props.selectedKeys = nextProps.selectedKeys || [] | ||||
|     } | ||||
|     if ('openKeys' in nextProps) { | ||||
|       props.openKeys = nextProps.openKeys || [] | ||||
|     } | ||||
|     this.setState(props) | ||||
|   }, | ||||
|   methods: { | ||||
|     onDestroy (key) { | ||||
|       const state = this.$data | ||||
|       const props = this.$props | ||||
|       const selectedKeys = state.selectedKeys | ||||
|       const openKeys = state.openKeys | ||||
|       let index = selectedKeys.indexOf(key) | ||||
|       if (!('selectedKeys' in props) && index !== -1) { | ||||
|         selectedKeys.splice(index, 1) | ||||
|       } | ||||
|       index = openKeys.indexOf(key) | ||||
|       if (!('openKeys' in props) && index !== -1) { | ||||
|         openKeys.splice(index, 1) | ||||
|       } | ||||
|     }, | ||||
| 
 | ||||
|     onSelect (selectInfo) { | ||||
|       const props = this.$props | ||||
|       if (props.selectable) { | ||||
|       // root menu | ||||
|         let selectedKeys = this.$data.selectedKeys | ||||
|         const selectedKey = selectInfo.key | ||||
|         if (props.multiple) { | ||||
|           selectedKeys = selectedKeys.concat([selectedKey]) | ||||
|         } else { | ||||
|           selectedKeys = [selectedKey] | ||||
|         } | ||||
|         if (!('selectedKeys' in props)) { | ||||
|           this.setState({ | ||||
|             selectedKeys, | ||||
|           }) | ||||
|         } | ||||
|         this.$emit('select', { | ||||
|           ...selectInfo, | ||||
|           selectedKeys, | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
| 
 | ||||
|     onClick (e) { | ||||
|       this.$emit('click', e) | ||||
|     }, | ||||
| 
 | ||||
|     onOpenChange (e_) { | ||||
|       const openKeys = this.$data.openKeys.concat() | ||||
|       let changed = false | ||||
|       const processSingle = (e) => { | ||||
|         let oneChanged = false | ||||
|         if (e.open) { | ||||
|           oneChanged = openKeys.indexOf(e.key) === -1 | ||||
|           if (oneChanged) { | ||||
|             openKeys.push(e.key) | ||||
|           } | ||||
|         } else { | ||||
|           const index = openKeys.indexOf(e.key) | ||||
|           oneChanged = index !== -1 | ||||
|           if (oneChanged) { | ||||
|             openKeys.splice(index, 1) | ||||
|           } | ||||
|         } | ||||
|         changed = changed || oneChanged | ||||
|       } | ||||
|       if (Array.isArray(e_)) { | ||||
|       // batch change call | ||||
|         e_.forEach(processSingle) | ||||
|       } else { | ||||
|         processSingle(e_) | ||||
|       } | ||||
|       if (changed) { | ||||
|         if (this.$props.openKeys === undefined) { | ||||
|           this.setState({ openKeys }) | ||||
|         } | ||||
|         this.$emit('openChange', openKeys) | ||||
|       } | ||||
|     }, | ||||
| 
 | ||||
|     onDeselect (selectInfo) { | ||||
|       const props = this.$props | ||||
|       if (props.selectable) { | ||||
|         const selectedKeys = this.$data.selectedKeys.concat() | ||||
|         const selectedKey = selectInfo.key | ||||
|         const index = selectedKeys.indexOf(selectedKey) | ||||
|         if (index !== -1) { | ||||
|           selectedKeys.splice(index, 1) | ||||
|         } | ||||
|         if (!('selectedKeys' in props)) { | ||||
|           this.setState({ | ||||
|             selectedKeys, | ||||
|           }) | ||||
|         } | ||||
|         this.$emit('deselect', { | ||||
|           ...selectInfo, | ||||
|           selectedKeys, | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
| 
 | ||||
|     getOpenTransitionName () { | ||||
|       const props = this.$props | ||||
|       let transitionName = props.openTransitionName | ||||
|       const animationName = props.openAnimation | ||||
|       if (!transitionName && typeof animationName === 'string') { | ||||
|         transitionName = `${props.prefixCls}-open-${animationName}` | ||||
|       } | ||||
|       return transitionName | ||||
|     }, | ||||
| 
 | ||||
|     isInlineMode () { | ||||
|       return this.$props.mode === 'inline' | ||||
|     }, | ||||
| 
 | ||||
|     lastOpenSubMenu () { | ||||
|       let lastOpen = [] | ||||
|       const { openKeys } = this.$data | ||||
|       if (openKeys.length) { | ||||
|         lastOpen = this.getFlatInstanceArray().filter((c) => { | ||||
|           return c && openKeys.indexOf(c.props.eventKey) !== -1 | ||||
|         }) | ||||
|       } | ||||
|       return lastOpen[0] | ||||
|     }, | ||||
| 
 | ||||
|     renderMenuItem (c, i, subIndex) { | ||||
|       if (!c) { | ||||
|         return null | ||||
|       } | ||||
|       const state = this.$data | ||||
|       const extraProps = { | ||||
|         openKeys: state.openKeys, | ||||
|         selectedKeys: state.selectedKeys, | ||||
|         triggerSubMenuAction: this.$props.triggerSubMenuAction, | ||||
|       } | ||||
|       return this.renderCommonMenuItem(c, i, subIndex, extraProps) | ||||
|     }, | ||||
|   }, | ||||
| 
 | ||||
|   render () { | ||||
|     const props = { ...this.$props } | ||||
|     props.className += ` ${props.prefixCls}-root` | ||||
|     return this.renderRoot(props) | ||||
|   }, | ||||
| } | ||||
| export default Menu | ||||
| </script> | ||||
|  | @ -1,165 +0,0 @@ | |||
| import React from 'react' | ||||
| import PropTypes from 'prop-types' | ||||
| import createReactClass from 'create-react-class' | ||||
| import KeyCode from 'rc-util/lib/KeyCode' | ||||
| import classNames from 'classnames' | ||||
| import { noop } from './util' | ||||
| 
 | ||||
| /* eslint react/no-is-mounted:0 */ | ||||
| 
 | ||||
| const MenuItem = createReactClass({ | ||||
|   displayName: 'MenuItem', | ||||
| 
 | ||||
|   propTypes: { | ||||
|     rootPrefixCls: PropTypes.string, | ||||
|     eventKey: PropTypes.string, | ||||
|     active: PropTypes.bool, | ||||
|     children: PropTypes.any, | ||||
|     selectedKeys: PropTypes.array, | ||||
|     disabled: PropTypes.bool, | ||||
|     title: PropTypes.string, | ||||
|     onItemHover: PropTypes.func, | ||||
|     onSelect: PropTypes.func, | ||||
|     onClick: PropTypes.func, | ||||
|     onDeselect: PropTypes.func, | ||||
|     parentMenu: PropTypes.object, | ||||
|     onDestroy: PropTypes.func, | ||||
|     onMouseEnter: PropTypes.func, | ||||
|     onMouseLeave: PropTypes.func, | ||||
|   }, | ||||
| 
 | ||||
|   getDefaultProps () { | ||||
|     return { | ||||
|       onSelect: noop, | ||||
|       onMouseEnter: noop, | ||||
|       onMouseLeave: noop, | ||||
|     } | ||||
|   }, | ||||
| 
 | ||||
|   componentWillUnmount () { | ||||
|     const props = this.props | ||||
|     if (props.onDestroy) { | ||||
|       props.onDestroy(props.eventKey) | ||||
|     } | ||||
|   }, | ||||
|   onKeyDown (e) { | ||||
|     const keyCode = e.keyCode | ||||
|     if (keyCode === KeyCode.ENTER) { | ||||
|       this.onClick(e) | ||||
|       return true | ||||
|     } | ||||
|   }, | ||||
| 
 | ||||
|   onMouseLeave (e) { | ||||
|     const { eventKey, onItemHover, onMouseLeave } = this.props | ||||
|     onItemHover({ | ||||
|       key: eventKey, | ||||
|       hover: false, | ||||
|     }) | ||||
|     onMouseLeave({ | ||||
|       key: eventKey, | ||||
|       domEvent: e, | ||||
|     }) | ||||
|   }, | ||||
| 
 | ||||
|   onMouseEnter (e) { | ||||
|     const { eventKey, parentMenu, onItemHover, onMouseEnter } = this.props | ||||
|     if (parentMenu.subMenuInstance) { | ||||
|       parentMenu.subMenuInstance.clearSubMenuTimers() | ||||
|     } | ||||
|     onItemHover({ | ||||
|       key: eventKey, | ||||
|       hover: true, | ||||
|     }) | ||||
|     onMouseEnter({ | ||||
|       key: eventKey, | ||||
|       domEvent: e, | ||||
|     }) | ||||
|   }, | ||||
| 
 | ||||
|   onClick (e) { | ||||
|     const { eventKey, multiple, onClick, onSelect, onDeselect } = this.props | ||||
|     const selected = this.isSelected() | ||||
|     const info = { | ||||
|       key: eventKey, | ||||
|       keyPath: [eventKey], | ||||
|       item: this, | ||||
|       domEvent: e, | ||||
|     } | ||||
|     onClick(info) | ||||
|     if (multiple) { | ||||
|       if (selected) { | ||||
|         onDeselect(info) | ||||
|       } else { | ||||
|         onSelect(info) | ||||
|       } | ||||
|     } else if (!selected) { | ||||
|       onSelect(info) | ||||
|     } | ||||
|   }, | ||||
| 
 | ||||
|   getPrefixCls () { | ||||
|     return `${this.props.rootPrefixCls}-item` | ||||
|   }, | ||||
| 
 | ||||
|   getActiveClassName () { | ||||
|     return `${this.getPrefixCls()}-active` | ||||
|   }, | ||||
| 
 | ||||
|   getSelectedClassName () { | ||||
|     return `${this.getPrefixCls()}-selected` | ||||
|   }, | ||||
| 
 | ||||
|   getDisabledClassName () { | ||||
|     return `${this.getPrefixCls()}-disabled` | ||||
|   }, | ||||
| 
 | ||||
|   isSelected () { | ||||
|     return this.props.selectedKeys.indexOf(this.props.eventKey) !== -1 | ||||
|   }, | ||||
| 
 | ||||
|   render () { | ||||
|     const props = this.props | ||||
|     const selected = this.isSelected() | ||||
|     const className = classNames(this.getPrefixCls(), props.className, { | ||||
|       [this.getActiveClassName()]: !props.disabled && props.active, | ||||
|       [this.getSelectedClassName()]: selected, | ||||
|       [this.getDisabledClassName()]: props.disabled, | ||||
|     }) | ||||
|     const attrs = { | ||||
|       ...props.attribute, | ||||
|       title: props.title, | ||||
|       className, | ||||
|       role: 'menuitem', | ||||
|       'aria-selected': selected, | ||||
|       'aria-disabled': props.disabled, | ||||
|     } | ||||
|     let mouseEvent = {} | ||||
|     if (!props.disabled) { | ||||
|       mouseEvent = { | ||||
|         onClick: this.onClick, | ||||
|         onMouseLeave: this.onMouseLeave, | ||||
|         onMouseEnter: this.onMouseEnter, | ||||
|       } | ||||
|     } | ||||
|     const style = { | ||||
|       ...props.style, | ||||
|     } | ||||
|     if (props.mode === 'inline') { | ||||
|       style.paddingLeft = props.inlineIndent * props.level | ||||
|     } | ||||
|     return ( | ||||
|       <li | ||||
|         {...attrs} | ||||
|         {...mouseEvent} | ||||
|         style={style} | ||||
|       > | ||||
|         {props.children} | ||||
|       </li> | ||||
|     ) | ||||
|   }, | ||||
| }) | ||||
| 
 | ||||
| MenuItem.isMenuItem = 1 | ||||
| 
 | ||||
| export default MenuItem | ||||
|  | @ -0,0 +1,157 @@ | |||
| <script> | ||||
| import PropTypes from 'vue-types' | ||||
| import KeyCode from '../../_util/KeyCode' | ||||
| 
 | ||||
| const MenuItem = { | ||||
|   name: 'MenuItem', | ||||
| 
 | ||||
|   props: { | ||||
|     rootPrefixCls: PropTypes.string, | ||||
|     eventKey: PropTypes.string, | ||||
|     active: PropTypes.bool, | ||||
|     children: PropTypes.any, | ||||
|     selectedKeys: PropTypes.array, | ||||
|     disabled: PropTypes.bool, | ||||
|     title: PropTypes.string, | ||||
|     // onItemHover: PropTypes.func, | ||||
|     // onSelect: PropTypes.func, | ||||
|     // onClick: PropTypes.func, | ||||
|     // onDeselect: PropTypes.func, | ||||
|     parentMenu: PropTypes.object, | ||||
|     // onDestroy: PropTypes.func, | ||||
|     // onMouseEnter: PropTypes.func, | ||||
|     // onMouseLeave: PropTypes.func, | ||||
|   }, | ||||
| 
 | ||||
|   beforeDestroy () { | ||||
|     const props = this.$props | ||||
|     this.$emit('destroy', props.eventKey) | ||||
|   }, | ||||
|   methods: { | ||||
|     onKeyDown (e) { | ||||
|       const keyCode = e.keyCode | ||||
|       if (keyCode === KeyCode.ENTER) { | ||||
|         this.$emit('click', e) | ||||
|         return true | ||||
|       } | ||||
|     }, | ||||
| 
 | ||||
|     onMouseLeave (e) { | ||||
|       const { eventKey } = this.$props | ||||
|       this.$emit('itemHover', { | ||||
|         key: eventKey, | ||||
|         hover: false, | ||||
|       }) | ||||
|       this.$emit('mouseLeave', { | ||||
|         key: eventKey, | ||||
|         domEvent: e, | ||||
|       }) | ||||
|     }, | ||||
| 
 | ||||
|     onMouseEnter (e) { | ||||
|       const { eventKey, parentMenu } = this.$props | ||||
|       if (parentMenu.subMenuInstance) { | ||||
|         parentMenu.subMenuInstance.clearSubMenuTimers() | ||||
|       } | ||||
|       this.$emit('itemHover', { | ||||
|         key: eventKey, | ||||
|         hover: true, | ||||
|       }) | ||||
|       this.$emit('mouseEnter', { | ||||
|         key: eventKey, | ||||
|         domEvent: e, | ||||
|       }) | ||||
|     }, | ||||
| 
 | ||||
|     onClick (e) { | ||||
|       const { eventKey, multiple } = this.$props | ||||
|       const selected = this.isSelected() | ||||
|       const info = { | ||||
|         key: eventKey, | ||||
|         keyPath: [eventKey], | ||||
|         item: this, | ||||
|         domEvent: e, | ||||
|       } | ||||
|       this.$emit('click', info) | ||||
|       if (multiple) { | ||||
|         if (selected) { | ||||
|           this.$emit('deselect', info) | ||||
|         } else { | ||||
|           this.$emit('select', info) | ||||
|         } | ||||
|       } else if (!selected) { | ||||
|         this.$emit('select', info) | ||||
|       } | ||||
|     }, | ||||
| 
 | ||||
|     getPrefixCls () { | ||||
|       return `${this.$props.rootPrefixCls}-item` | ||||
|     }, | ||||
| 
 | ||||
|     getActiveClassName () { | ||||
|       return `${this.getPrefixCls()}-active` | ||||
|     }, | ||||
| 
 | ||||
|     getSelectedClassName () { | ||||
|       return `${this.getPrefixCls()}-selected` | ||||
|     }, | ||||
| 
 | ||||
|     getDisabledClassName () { | ||||
|       return `${this.getPrefixCls()}-disabled` | ||||
|     }, | ||||
| 
 | ||||
|     isSelected () { | ||||
|       return this.$props.selectedKeys.indexOf(this.$props.eventKey) !== -1 | ||||
|     }, | ||||
|   }, | ||||
| 
 | ||||
|   render () { | ||||
|     const props = this.$props | ||||
|     const selected = this.isSelected() | ||||
|     const className = { | ||||
|       [this.getPrefixCls()]: true, | ||||
|       [this.getActiveClassName()]: !props.disabled && props.active, | ||||
|       [this.getSelectedClassName()]: selected, | ||||
|       [this.getDisabledClassName()]: props.disabled, | ||||
|     } | ||||
|     const attrs = { | ||||
|       ...props.attribute, | ||||
|       title: props.title, | ||||
|       role: 'menuitem', | ||||
|       'aria-selected': selected, | ||||
|       'aria-disabled': props.disabled, | ||||
|     } | ||||
|     let mouseEvent = {} | ||||
|     if (!props.disabled) { | ||||
|       mouseEvent = { | ||||
|         click: this.onClick, | ||||
|         mouseleave: this.onMouseLeave, | ||||
|         mouseenter: this.onMouseEnter, | ||||
|       } | ||||
|     } | ||||
|     const style = {} | ||||
|     if (props.mode === 'inline') { | ||||
|       style.paddingLeft = `${props.inlineIndent * props.level}px` | ||||
|     } | ||||
|     const liProps = { | ||||
|       attrs, | ||||
|       on: { | ||||
|         mouseEvent, | ||||
|       }, | ||||
|     } | ||||
|     return ( | ||||
|       <li | ||||
|         {...liProps} | ||||
|         style={style} | ||||
|         class={className} | ||||
|       > | ||||
|         {this.$slots.default} | ||||
|       </li> | ||||
|     ) | ||||
|   }, | ||||
| } | ||||
| 
 | ||||
| MenuItem.isMenuItem = 1 | ||||
| 
 | ||||
| export default MenuItem | ||||
| </script> | ||||
|  | @ -1,48 +0,0 @@ | |||
| import React from 'react' | ||||
| import PropTypes from 'prop-types' | ||||
| import createReactClass from 'create-react-class' | ||||
| 
 | ||||
| const MenuItemGroup = createReactClass({ | ||||
|   displayName: 'MenuItemGroup', | ||||
| 
 | ||||
|   propTypes: { | ||||
|     renderMenuItem: PropTypes.func, | ||||
|     index: PropTypes.number, | ||||
|     className: PropTypes.string, | ||||
|     rootPrefixCls: PropTypes.string, | ||||
|   }, | ||||
| 
 | ||||
|   getDefaultProps () { | ||||
|     // To fix keyboard UX. | ||||
|     return { disabled: true } | ||||
|   }, | ||||
| 
 | ||||
|   renderInnerMenuItem (item, subIndex) { | ||||
|     const { renderMenuItem, index } = this.props | ||||
|     return renderMenuItem(item, index, subIndex) | ||||
|   }, | ||||
| 
 | ||||
|   render () { | ||||
|     const props = this.props | ||||
|     const { className = '', rootPrefixCls } = props | ||||
|     const titleClassName = `${rootPrefixCls}-item-group-title` | ||||
|     const listClassName = `${rootPrefixCls}-item-group-list` | ||||
|     return ( | ||||
|       <li className={`${className} ${rootPrefixCls}-item-group`}> | ||||
|         <div | ||||
|           className={titleClassName} | ||||
|           title={typeof props.title === 'string' ? props.title : undefined} | ||||
|         > | ||||
|           {props.title} | ||||
|         </div> | ||||
|         <ul className={listClassName}> | ||||
|           {React.Children.map(props.children, this.renderInnerMenuItem)} | ||||
|         </ul> | ||||
|       </li> | ||||
|     ) | ||||
|   }, | ||||
| }) | ||||
| 
 | ||||
| MenuItemGroup.isMenuItemGroup = true | ||||
| 
 | ||||
| export default MenuItemGroup | ||||
|  | @ -0,0 +1,45 @@ | |||
| <script> | ||||
| import PropTypes from 'vue-types' | ||||
| 
 | ||||
| const MenuItemGroup = { | ||||
|   name: 'MenuItemGroup', | ||||
| 
 | ||||
|   props: { | ||||
|     renderMenuItem: PropTypes.func, | ||||
|     index: PropTypes.number, | ||||
|     className: PropTypes.string, | ||||
|     rootPrefixCls: PropTypes.string, | ||||
|     disabled: PropTypes.bool.def(true), | ||||
|   }, | ||||
| 
 | ||||
|   methods: { | ||||
|     renderInnerMenuItem (item, subIndex) { | ||||
|       const { renderMenuItem, index } = this.$props | ||||
|       return renderMenuItem(item, index, subIndex) | ||||
|     }, | ||||
|   }, | ||||
|   render () { | ||||
|     const props = this.$props | ||||
|     const { rootPrefixCls } = props | ||||
|     const titleClassName = `${rootPrefixCls}-item-group-title` | ||||
|     const listClassName = `${rootPrefixCls}-item-group-list` | ||||
|     return ( | ||||
|       <li class={`${rootPrefixCls}-item-group`}> | ||||
|         <div | ||||
|           class={titleClassName} | ||||
|           title={typeof props.title === 'string' ? props.title : undefined} | ||||
|         > | ||||
|           {props.title} | ||||
|         </div> | ||||
|         <ul class={listClassName}> | ||||
|           {this.$slots.default.map(this.renderInnerMenuItem)} | ||||
|         </ul> | ||||
|       </li> | ||||
|     ) | ||||
|   }, | ||||
| } | ||||
| 
 | ||||
| MenuItemGroup.isMenuItemGroup = true | ||||
| 
 | ||||
| export default MenuItemGroup | ||||
| </script> | ||||
|  | @ -1,9 +1,5 @@ | |||
| import React from 'react' | ||||
| import PropTypes from 'prop-types' | ||||
| import ReactDOM from 'react-dom' | ||||
| import KeyCode from 'rc-util/lib/KeyCode' | ||||
| import createChainedFunction from 'rc-util/lib/createChainedFunction' | ||||
| import classNames from 'classnames' | ||||
| import PropTypes from 'vue-types' | ||||
| import KeyCode from '../../_util/KeyCode' | ||||
| import scrollIntoView from 'dom-scroll-into-view' | ||||
| import { getKeyFromChildrenIndex, loopMenuItem } from './util' | ||||
| import DOMWrap from './DOMWrap' | ||||
|  | @ -53,35 +49,22 @@ function saveRef (index, subIndex, c) { | |||
| } | ||||
| 
 | ||||
| const MenuMixin = { | ||||
|   propTypes: { | ||||
|     focusable: PropTypes.bool, | ||||
|   props: { | ||||
|     prefixCls: PropTypes.string.def('ant-menu'), | ||||
|     inlineIndent: PropTypes.number.def(24), | ||||
|     focusable: PropTypes.bool.def(true), | ||||
|     multiple: PropTypes.bool, | ||||
|     style: PropTypes.object, | ||||
|     defaultActiveFirst: PropTypes.bool, | ||||
|     visible: PropTypes.bool, | ||||
|     visible: PropTypes.bool.def(true), | ||||
|     activeKey: PropTypes.string, | ||||
|     selectedKeys: PropTypes.arrayOf(PropTypes.string), | ||||
|     defaultSelectedKeys: PropTypes.arrayOf(PropTypes.string), | ||||
|     defaultOpenKeys: PropTypes.arrayOf(PropTypes.string), | ||||
|     openKeys: PropTypes.arrayOf(PropTypes.string), | ||||
|     children: PropTypes.any, | ||||
|   }, | ||||
| 
 | ||||
|   getDefaultProps () { | ||||
|     return { | ||||
|       prefixCls: 'rc-menu', | ||||
|       className: '', | ||||
|       mode: 'vertical', | ||||
|       level: 1, | ||||
|       inlineIndent: 24, | ||||
|       visible: true, | ||||
|       focusable: true, | ||||
|       style: {}, | ||||
|     } | ||||
|   }, | ||||
| 
 | ||||
|   getInitialState () { | ||||
|     const props = this.props | ||||
|   data () { | ||||
|     const props = this.$props | ||||
|     return { | ||||
|       activeKey: getActiveKey(props, props.activeKey), | ||||
|     } | ||||
|  | @ -108,190 +91,189 @@ const MenuMixin = { | |||
|     } | ||||
|   }, | ||||
| 
 | ||||
|   shouldComponentUpdate (nextProps) { | ||||
|     return this.props.visible || nextProps.visible | ||||
|   }, | ||||
| 
 | ||||
|   componentWillMount () { | ||||
|   created () { | ||||
|     this.instanceArray = [] | ||||
|   }, | ||||
| 
 | ||||
|   // all keyboard events callbacks run from here at first
 | ||||
|   onKeyDown (e, callback) { | ||||
|     const keyCode = e.keyCode | ||||
|     let handled | ||||
|     this.getFlatInstanceArray().forEach((obj) => { | ||||
|       if (obj && obj.props.active && obj.onKeyDown) { | ||||
|         handled = obj.onKeyDown(e) | ||||
|   methods: { | ||||
|     // all keyboard events callbacks run from here at first
 | ||||
|     onKeyDown (e, callback) { | ||||
|       const keyCode = e.keyCode | ||||
|       let handled | ||||
|       this.getFlatInstanceArray().forEach((obj) => { | ||||
|         if (obj && obj.props.active && obj.onKeyDown) { | ||||
|           handled = obj.onKeyDown(e) | ||||
|         } | ||||
|       }) | ||||
|       if (handled) { | ||||
|         return 1 | ||||
|       } | ||||
|     }) | ||||
|     if (handled) { | ||||
|       return 1 | ||||
|     } | ||||
|     let activeItem = null | ||||
|     if (keyCode === KeyCode.UP || keyCode === KeyCode.DOWN) { | ||||
|       activeItem = this.step(keyCode === KeyCode.UP ? -1 : 1) | ||||
|     } | ||||
|     if (activeItem) { | ||||
|       e.preventDefault() | ||||
|       this.setState({ | ||||
|         activeKey: activeItem.props.eventKey, | ||||
|       }, () => { | ||||
|         scrollIntoView(ReactDOM.findDOMNode(activeItem), ReactDOM.findDOMNode(this), { | ||||
|           onlyScrollIfNeeded: true, | ||||
|       let activeItem = null | ||||
|       if (keyCode === KeyCode.UP || keyCode === KeyCode.DOWN) { | ||||
|         activeItem = this.step(keyCode === KeyCode.UP ? -1 : 1) | ||||
|       } | ||||
|       if (activeItem) { | ||||
|         e.preventDefault() | ||||
|         this.setState({ | ||||
|           activeKey: activeItem.$props.eventKey, | ||||
|         }, () => { | ||||
|           scrollIntoView(activeItem.$el, this.$el, { | ||||
|             onlyScrollIfNeeded: true, | ||||
|           }) | ||||
|           // https://github.com/react-component/menu/commit/9899a9672f6f028ec3cdf773f1ecea5badd2d33e
 | ||||
|           if (typeof callback === 'function') { | ||||
|             callback(activeItem) | ||||
|           } | ||||
|         }) | ||||
|         // https://github.com/react-component/menu/commit/9899a9672f6f028ec3cdf773f1ecea5badd2d33e
 | ||||
|         if (typeof callback === 'function') { | ||||
|           callback(activeItem) | ||||
|         } | ||||
|       }) | ||||
|       return 1 | ||||
|     } else if (activeItem === undefined) { | ||||
|       e.preventDefault() | ||||
|         return 1 | ||||
|       } else if (activeItem === undefined) { | ||||
|         e.preventDefault() | ||||
|         this.setState({ | ||||
|           activeKey: null, | ||||
|         }) | ||||
|         return 1 | ||||
|       } | ||||
|     }, | ||||
| 
 | ||||
|     onItemHover (e) { | ||||
|       const { key, hover } = e | ||||
|       this.setState({ | ||||
|         activeKey: null, | ||||
|         activeKey: hover ? key : null, | ||||
|       }) | ||||
|       return 1 | ||||
|     } | ||||
|   }, | ||||
|     }, | ||||
| 
 | ||||
|   onItemHover (e) { | ||||
|     const { key, hover } = e | ||||
|     this.setState({ | ||||
|       activeKey: hover ? key : null, | ||||
|     }) | ||||
|   }, | ||||
| 
 | ||||
|   getFlatInstanceArray () { | ||||
|     let instanceArray = this.instanceArray | ||||
|     const hasInnerArray = instanceArray.some((a) => { | ||||
|       return Array.isArray(a) | ||||
|     }) | ||||
|     if (hasInnerArray) { | ||||
|       instanceArray = [] | ||||
|       this.instanceArray.forEach((a) => { | ||||
|         if (Array.isArray(a)) { | ||||
|           instanceArray.push.apply(instanceArray, a) | ||||
|         } else { | ||||
|           instanceArray.push(a) | ||||
|         } | ||||
|     getFlatInstanceArray () { | ||||
|       let instanceArray = this.instanceArray | ||||
|       const hasInnerArray = instanceArray.some((a) => { | ||||
|         return Array.isArray(a) | ||||
|       }) | ||||
|       this.instanceArray = instanceArray | ||||
|     } | ||||
|     return instanceArray | ||||
|   }, | ||||
|       if (hasInnerArray) { | ||||
|         instanceArray = [] | ||||
|         this.instanceArray.forEach((a) => { | ||||
|           if (Array.isArray(a)) { | ||||
|             instanceArray.push.apply(instanceArray, a) | ||||
|           } else { | ||||
|             instanceArray.push(a) | ||||
|           } | ||||
|         }) | ||||
|         this.instanceArray = instanceArray | ||||
|       } | ||||
|       return instanceArray | ||||
|     }, | ||||
| 
 | ||||
|   renderCommonMenuItem (child, i, subIndex, extraProps) { | ||||
|     const state = this.state | ||||
|     const props = this.props | ||||
|     const key = getKeyFromChildrenIndex(child, props.eventKey, i) | ||||
|     const childProps = child.props | ||||
|     const isActive = key === state.activeKey | ||||
|     const newChildProps = { | ||||
|       mode: props.mode, | ||||
|       level: props.level, | ||||
|       inlineIndent: props.inlineIndent, | ||||
|       renderMenuItem: this.renderMenuItem, | ||||
|       rootPrefixCls: props.prefixCls, | ||||
|       index: i, | ||||
|       parentMenu: this, | ||||
|       ref: childProps.disabled ? undefined | ||||
|         : createChainedFunction(child.ref, saveRef.bind(this, i, subIndex)), | ||||
|       eventKey: key, | ||||
|       active: !childProps.disabled && isActive, | ||||
|       multiple: props.multiple, | ||||
|       onClick: this.onClick, | ||||
|       onItemHover: this.onItemHover, | ||||
|       openTransitionName: this.getOpenTransitionName(), | ||||
|       openAnimation: props.openAnimation, | ||||
|       subMenuOpenDelay: props.subMenuOpenDelay, | ||||
|       subMenuCloseDelay: props.subMenuCloseDelay, | ||||
|       forceSubMenuRender: props.forceSubMenuRender, | ||||
|       onOpenChange: this.onOpenChange, | ||||
|       onDeselect: this.onDeselect, | ||||
|       onDestroy: this.onDestroy, | ||||
|       onSelect: this.onSelect, | ||||
|       ...extraProps, | ||||
|     } | ||||
|     if (props.mode === 'inline') { | ||||
|       newChildProps.triggerSubMenuAction = 'click' | ||||
|     } | ||||
|     return React.cloneElement(child, newChildProps) | ||||
|   }, | ||||
|     renderCommonMenuItem (child, i, subIndex, extraProps) { | ||||
|       const state = this.state | ||||
|       const props = this.props | ||||
|       const key = getKeyFromChildrenIndex(child, props.eventKey, i) | ||||
|       const childProps = child.props | ||||
|       const isActive = key === state.activeKey | ||||
|       const newChildProps = { | ||||
|         mode: props.mode, | ||||
|         level: props.level, | ||||
|         inlineIndent: props.inlineIndent, | ||||
|         renderMenuItem: this.renderMenuItem, | ||||
|         rootPrefixCls: props.prefixCls, | ||||
|         index: i, | ||||
|         parentMenu: this, | ||||
|         ref: child.ref, | ||||
|         // ref: childProps.disabled ? undefined
 | ||||
|         //  : createChainedFunction(child.ref, saveRef.bind(this, i, subIndex)),
 | ||||
|         eventKey: key, | ||||
|         active: !childProps.disabled && isActive, | ||||
|         multiple: props.multiple, | ||||
|         onClick: this.onClick, | ||||
|         onItemHover: this.onItemHover, | ||||
|         openTransitionName: this.getOpenTransitionName(), | ||||
|         openAnimation: props.openAnimation, | ||||
|         subMenuOpenDelay: props.subMenuOpenDelay, | ||||
|         subMenuCloseDelay: props.subMenuCloseDelay, | ||||
|         forceSubMenuRender: props.forceSubMenuRender, | ||||
|         onOpenChange: this.onOpenChange, | ||||
|         onDeselect: this.onDeselect, | ||||
|         onDestroy: this.onDestroy, | ||||
|         onSelect: this.onSelect, | ||||
|         ...extraProps, | ||||
|       } | ||||
|       if (props.mode === 'inline') { | ||||
|         newChildProps.triggerSubMenuAction = 'click' | ||||
|       } | ||||
|       return child | ||||
|       // return React.cloneElement(child, newChildProps)
 | ||||
|     }, | ||||
| 
 | ||||
|   renderRoot (props) { | ||||
|     this.instanceArray = [] | ||||
|     const className = classNames( | ||||
|       props.prefixCls, | ||||
|       props.className, | ||||
|       `${props.prefixCls}-${props.mode}`, | ||||
|     ) | ||||
|     const domProps = { | ||||
|       className, | ||||
|       role: 'menu', | ||||
|       'aria-activedescendant': '', | ||||
|     } | ||||
|     if (props.id) { | ||||
|       domProps.id = props.id | ||||
|     } | ||||
|     if (props.focusable) { | ||||
|       domProps.tabIndex = '0' | ||||
|       domProps.onKeyDown = this.onKeyDown | ||||
|     } | ||||
|     return ( | ||||
|     renderRoot (props) { | ||||
|       this.instanceArray = [] | ||||
|       const className = { | ||||
|         [props.prefixCls]: true, | ||||
|         [props.className]: true, | ||||
|         [`${props.prefixCls}-${props.mode}`]: true, | ||||
|       } | ||||
|       const domProps = { | ||||
|         className, | ||||
|         role: 'menu', | ||||
|         'aria-activedescendant': '', | ||||
|       } | ||||
|       if (props.id) { | ||||
|         domProps.id = props.id | ||||
|       } | ||||
|       if (props.focusable) { | ||||
|         domProps.tabIndex = '0' | ||||
|         domProps.onKeyDown = this.onKeyDown | ||||
|       } | ||||
|       return ( | ||||
|       // ESLint is not smart enough to know that the type of `children` was checked.
 | ||||
|       /* eslint-disable */ | ||||
|       <DOMWrap | ||||
|         style={props.style} | ||||
|         tag="ul" | ||||
|         hiddenClassName={`${props.prefixCls}-hidden`} | ||||
|         visible={props.visible} | ||||
|         {...domProps} | ||||
|       > | ||||
|         {React.Children.map(props.children, this.renderMenuItem)} | ||||
|       </DOMWrap> | ||||
|       /*eslint -enable */ | ||||
|     ) | ||||
|   }, | ||||
|         <DOMWrap | ||||
|           style={props.style} | ||||
|           tag="ul" | ||||
|           hiddenClassName={`${props.prefixCls}-hidden`} | ||||
|           visible={props.visible} | ||||
|           {...domProps} | ||||
|         > | ||||
|           {this.$slots.default.map(this.renderMenuItem)} | ||||
|         </DOMWrap> | ||||
|         /*eslint -enable */ | ||||
|       ) | ||||
|     }, | ||||
| 
 | ||||
|   step (direction) { | ||||
|     let children = this.getFlatInstanceArray() | ||||
|     const activeKey = this.state.activeKey | ||||
|     const len = children.length | ||||
|     if (!len) { | ||||
|       return null | ||||
|     } | ||||
|     if (direction < 0) { | ||||
|       children = children.concat().reverse() | ||||
|     } | ||||
|     // find current activeIndex
 | ||||
|     let activeIndex = -1 | ||||
|     children.every((c, ci) => { | ||||
|       if (c && c.props.eventKey === activeKey) { | ||||
|         activeIndex = ci | ||||
|         return false | ||||
|     step (direction) { | ||||
|       let children = this.getFlatInstanceArray() | ||||
|       const activeKey = this.state.activeKey | ||||
|       const len = children.length | ||||
|       if (!len) { | ||||
|         return null | ||||
|       } | ||||
|       return true | ||||
|     }) | ||||
|     if (!this.props.defaultActiveFirst && activeIndex !== -1) { | ||||
|       if (allDisabled(children.slice(activeIndex, len - 1))) { | ||||
|         return undefined | ||||
|       if (direction < 0) { | ||||
|         children = children.concat().reverse() | ||||
|       } | ||||
|     } | ||||
|     const start = (activeIndex + 1) % len | ||||
|     let i = start | ||||
|     for (; ;) { | ||||
|       const child = children[i] | ||||
|       if (!child || child.props.disabled) { | ||||
|         i = (i + 1 + len) % len | ||||
|         // complete a loop
 | ||||
|         if (i === start) { | ||||
|           return null | ||||
|       // find current activeIndex
 | ||||
|       let activeIndex = -1 | ||||
|       children.every((c, ci) => { | ||||
|         if (c && c.props.eventKey === activeKey) { | ||||
|           activeIndex = ci | ||||
|           return false | ||||
|         } | ||||
|         return true | ||||
|       }) | ||||
|       if (!this.props.defaultActiveFirst && activeIndex !== -1) { | ||||
|         if (allDisabled(children.slice(activeIndex, len - 1))) { | ||||
|           return undefined | ||||
|         } | ||||
|       } else { | ||||
|         return child | ||||
|       } | ||||
|     } | ||||
|       const start = (activeIndex + 1) % len | ||||
|       let i = start | ||||
|       for (; ;) { | ||||
|         const child = children[i] | ||||
|         if (!child || child.props.disabled) { | ||||
|           i = (i + 1 + len) % len | ||||
|           // complete a loop
 | ||||
|           if (i === start) { | ||||
|             return null | ||||
|           } | ||||
|         } else { | ||||
|           return child | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,5 +1,4 @@ | |||
| import React from 'react' | ||||
| import PropTypes from 'prop-types' | ||||
| import PropTypes from 'vue-types' | ||||
| import createReactClass from 'create-react-class' | ||||
| import Animate from 'rc-animate' | ||||
| import MenuMixin from './MenuMixin' | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 tangjinzhou
						tangjinzhou