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 'vue-types'
|
||||||
import PropTypes from 'prop-types'
|
import KeyCode from '../../_util/KeyCode'
|
||||||
import ReactDOM from 'react-dom'
|
|
||||||
import KeyCode from 'rc-util/lib/KeyCode'
|
|
||||||
import createChainedFunction from 'rc-util/lib/createChainedFunction'
|
|
||||||
import classNames from 'classnames'
|
|
||||||
import scrollIntoView from 'dom-scroll-into-view'
|
import scrollIntoView from 'dom-scroll-into-view'
|
||||||
import { getKeyFromChildrenIndex, loopMenuItem } from './util'
|
import { getKeyFromChildrenIndex, loopMenuItem } from './util'
|
||||||
import DOMWrap from './DOMWrap'
|
import DOMWrap from './DOMWrap'
|
||||||
|
@ -53,35 +49,22 @@ function saveRef (index, subIndex, c) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const MenuMixin = {
|
const MenuMixin = {
|
||||||
propTypes: {
|
props: {
|
||||||
focusable: PropTypes.bool,
|
prefixCls: PropTypes.string.def('ant-menu'),
|
||||||
|
inlineIndent: PropTypes.number.def(24),
|
||||||
|
focusable: PropTypes.bool.def(true),
|
||||||
multiple: PropTypes.bool,
|
multiple: PropTypes.bool,
|
||||||
style: PropTypes.object,
|
style: PropTypes.object,
|
||||||
defaultActiveFirst: PropTypes.bool,
|
defaultActiveFirst: PropTypes.bool,
|
||||||
visible: PropTypes.bool,
|
visible: PropTypes.bool.def(true),
|
||||||
activeKey: PropTypes.string,
|
activeKey: PropTypes.string,
|
||||||
selectedKeys: PropTypes.arrayOf(PropTypes.string),
|
selectedKeys: PropTypes.arrayOf(PropTypes.string),
|
||||||
defaultSelectedKeys: PropTypes.arrayOf(PropTypes.string),
|
defaultSelectedKeys: PropTypes.arrayOf(PropTypes.string),
|
||||||
defaultOpenKeys: PropTypes.arrayOf(PropTypes.string),
|
defaultOpenKeys: PropTypes.arrayOf(PropTypes.string),
|
||||||
openKeys: PropTypes.arrayOf(PropTypes.string),
|
openKeys: PropTypes.arrayOf(PropTypes.string),
|
||||||
children: PropTypes.any,
|
|
||||||
},
|
},
|
||||||
|
data () {
|
||||||
getDefaultProps () {
|
const props = this.$props
|
||||||
return {
|
|
||||||
prefixCls: 'rc-menu',
|
|
||||||
className: '',
|
|
||||||
mode: 'vertical',
|
|
||||||
level: 1,
|
|
||||||
inlineIndent: 24,
|
|
||||||
visible: true,
|
|
||||||
focusable: true,
|
|
||||||
style: {},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
getInitialState () {
|
|
||||||
const props = this.props
|
|
||||||
return {
|
return {
|
||||||
activeKey: getActiveKey(props, props.activeKey),
|
activeKey: getActiveKey(props, props.activeKey),
|
||||||
}
|
}
|
||||||
|
@ -108,14 +91,10 @@ const MenuMixin = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
shouldComponentUpdate (nextProps) {
|
created () {
|
||||||
return this.props.visible || nextProps.visible
|
|
||||||
},
|
|
||||||
|
|
||||||
componentWillMount () {
|
|
||||||
this.instanceArray = []
|
this.instanceArray = []
|
||||||
},
|
},
|
||||||
|
methods: {
|
||||||
// all keyboard events callbacks run from here at first
|
// all keyboard events callbacks run from here at first
|
||||||
onKeyDown (e, callback) {
|
onKeyDown (e, callback) {
|
||||||
const keyCode = e.keyCode
|
const keyCode = e.keyCode
|
||||||
|
@ -135,9 +114,9 @@ const MenuMixin = {
|
||||||
if (activeItem) {
|
if (activeItem) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
this.setState({
|
this.setState({
|
||||||
activeKey: activeItem.props.eventKey,
|
activeKey: activeItem.$props.eventKey,
|
||||||
}, () => {
|
}, () => {
|
||||||
scrollIntoView(ReactDOM.findDOMNode(activeItem), ReactDOM.findDOMNode(this), {
|
scrollIntoView(activeItem.$el, this.$el, {
|
||||||
onlyScrollIfNeeded: true,
|
onlyScrollIfNeeded: true,
|
||||||
})
|
})
|
||||||
// https://github.com/react-component/menu/commit/9899a9672f6f028ec3cdf773f1ecea5badd2d33e
|
// https://github.com/react-component/menu/commit/9899a9672f6f028ec3cdf773f1ecea5badd2d33e
|
||||||
|
@ -195,8 +174,9 @@ const MenuMixin = {
|
||||||
rootPrefixCls: props.prefixCls,
|
rootPrefixCls: props.prefixCls,
|
||||||
index: i,
|
index: i,
|
||||||
parentMenu: this,
|
parentMenu: this,
|
||||||
ref: childProps.disabled ? undefined
|
ref: child.ref,
|
||||||
: createChainedFunction(child.ref, saveRef.bind(this, i, subIndex)),
|
// ref: childProps.disabled ? undefined
|
||||||
|
// : createChainedFunction(child.ref, saveRef.bind(this, i, subIndex)),
|
||||||
eventKey: key,
|
eventKey: key,
|
||||||
active: !childProps.disabled && isActive,
|
active: !childProps.disabled && isActive,
|
||||||
multiple: props.multiple,
|
multiple: props.multiple,
|
||||||
|
@ -216,16 +196,17 @@ const MenuMixin = {
|
||||||
if (props.mode === 'inline') {
|
if (props.mode === 'inline') {
|
||||||
newChildProps.triggerSubMenuAction = 'click'
|
newChildProps.triggerSubMenuAction = 'click'
|
||||||
}
|
}
|
||||||
return React.cloneElement(child, newChildProps)
|
return child
|
||||||
|
// return React.cloneElement(child, newChildProps)
|
||||||
},
|
},
|
||||||
|
|
||||||
renderRoot (props) {
|
renderRoot (props) {
|
||||||
this.instanceArray = []
|
this.instanceArray = []
|
||||||
const className = classNames(
|
const className = {
|
||||||
props.prefixCls,
|
[props.prefixCls]: true,
|
||||||
props.className,
|
[props.className]: true,
|
||||||
`${props.prefixCls}-${props.mode}`,
|
[`${props.prefixCls}-${props.mode}`]: true,
|
||||||
)
|
}
|
||||||
const domProps = {
|
const domProps = {
|
||||||
className,
|
className,
|
||||||
role: 'menu',
|
role: 'menu',
|
||||||
|
@ -248,7 +229,7 @@ const MenuMixin = {
|
||||||
visible={props.visible}
|
visible={props.visible}
|
||||||
{...domProps}
|
{...domProps}
|
||||||
>
|
>
|
||||||
{React.Children.map(props.children, this.renderMenuItem)}
|
{this.$slots.default.map(this.renderMenuItem)}
|
||||||
</DOMWrap>
|
</DOMWrap>
|
||||||
/*eslint -enable */
|
/*eslint -enable */
|
||||||
)
|
)
|
||||||
|
@ -293,6 +274,7 @@ const MenuMixin = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export default MenuMixin
|
export default MenuMixin
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import React from 'react'
|
import PropTypes from 'vue-types'
|
||||||
import PropTypes from 'prop-types'
|
|
||||||
import createReactClass from 'create-react-class'
|
import createReactClass from 'create-react-class'
|
||||||
import Animate from 'rc-animate'
|
import Animate from 'rc-animate'
|
||||||
import MenuMixin from './MenuMixin'
|
import MenuMixin from './MenuMixin'
|
||||||
|
|
Loading…
Reference in New Issue