mirror of
https://github.com/wu736139669/Monkey-Test.git
synced 2026-08-05 05:55:46 +00:00
536 lines
14 KiB
JavaScript
536 lines
14 KiB
JavaScript
'use strict'
|
|
|
|
var React = require('react')
|
|
var assign = require('object-assign')
|
|
var normalize = require('react-style-normalizer')
|
|
|
|
function emptyFn(){}
|
|
|
|
function toUpperFirst(s){
|
|
return s?
|
|
s.charAt(0).toUpperCase() + s.substring(1):
|
|
''
|
|
}
|
|
|
|
var ALIGN = (function(){
|
|
var MAP = {
|
|
left : 'flex-start',
|
|
start : 'flex-start',
|
|
center: 'center',
|
|
right : 'flex-end',
|
|
end : 'flex-end'
|
|
}
|
|
|
|
return function(value){
|
|
return MAP[value] || value
|
|
}
|
|
})()
|
|
|
|
var PropTypes = React.PropTypes
|
|
var DISPLAY_NAME = 'ReactButton'
|
|
|
|
var THEME = {
|
|
'default': {
|
|
//default type
|
|
style: {
|
|
border : '1px solid rgb(46, 153, 235)',
|
|
color : 'rgb(84, 84, 84)',
|
|
},
|
|
overStyle: {
|
|
background: 'linear-gradient(to bottom, rgb(125, 191, 242) 0%, rgb(110, 184, 241) 50%, rgb(117, 188, 242) 100%)',
|
|
color: 'white'
|
|
},
|
|
|
|
activeStyle: {
|
|
//-6 lightness from overStyle
|
|
background: ' linear-gradient(to bottom, rgb(106,182,240) 0%,rgb(91,175,239) 50%,rgb(96,178,240) 100%)',
|
|
color: 'white'
|
|
},
|
|
|
|
//disabled
|
|
disabledStyle: {
|
|
//theme properties
|
|
background: 'rgb(221, 221, 221)',
|
|
border: '1px solid rgb(147, 147, 147)',
|
|
color: 'rgb(128, 128, 128)'
|
|
},
|
|
|
|
//pressed
|
|
pressedStyle: {
|
|
background: 'linear-gradient(to bottom, rgb(22,135,222) 0%,rgb(20,129,212) 50%,rgb(20,132,218) 100%)',
|
|
color: 'white'
|
|
},
|
|
|
|
overPressedStyle: {
|
|
// +14 lightness from pressed style
|
|
background: 'linear-gradient(to bottom, rgb(48,153,234) 0%,rgb(36,148,234) 50%,rgb(41,151,235) 100%)',
|
|
},
|
|
|
|
activePressedStyle: {
|
|
background: 'linear-gradient(to bottom, rgb(58,159,236) 0%,rgb(45,153,235) 50%,rgb(50,155,236) 100%)'
|
|
},
|
|
|
|
//focused
|
|
focusedStyle: {}
|
|
//---NONE ----
|
|
},
|
|
'primary': {
|
|
style: {
|
|
background: 'linear-gradient(to bottom, #4ea9ee 0%,#41a2ed 50%,#46a5ee 100%)',
|
|
color: 'white'
|
|
},
|
|
|
|
overStyle: {
|
|
// + 10 lightness from primary
|
|
background: 'linear-gradient(to bottom, rgb(96,178,240) 0%,rgb(83,171,239) 50%,rgb(88,174,240) 100%)'
|
|
},
|
|
|
|
activeStyle: {
|
|
// -5 lightness from primary
|
|
background: 'linear-gradient(to bottom, rgb(64,162,236) 0%,rgb(50,155,236) 50%,rgb(55,158,237) 100%)'
|
|
},
|
|
|
|
//disabled
|
|
disabledStyle: {
|
|
//theme properties
|
|
background: 'rgb(116, 144, 166)',
|
|
color: 'rgb(190, 190, 190)'
|
|
}
|
|
|
|
//pressed
|
|
//---NONE---
|
|
|
|
//focused
|
|
//---NONE---
|
|
}
|
|
}
|
|
|
|
var ReactButton = React.createClass({
|
|
|
|
displayName: DISPLAY_NAME,
|
|
|
|
propTypes: {
|
|
fn: PropTypes.func,
|
|
onClick: PropTypes.func,
|
|
|
|
primary: PropTypes.bool,
|
|
disabled: PropTypes.bool,
|
|
pressed: PropTypes.bool,
|
|
defaultPressed: PropTypes.bool,
|
|
|
|
href: PropTypes.string,
|
|
align: PropTypes.string,
|
|
|
|
style: PropTypes.object,
|
|
|
|
className : PropTypes.string,
|
|
activeClassName : PropTypes.string,
|
|
overClassName : PropTypes.string,
|
|
focusedClassName: PropTypes.string,
|
|
disabledClassName: PropTypes.string
|
|
},
|
|
|
|
getDefaultProps: function() {
|
|
return {
|
|
isReactButton: true,
|
|
applyDefaultTheme: true,
|
|
buttonStates: ['focused', 'pressed'],
|
|
|
|
'data-display-name': DISPLAY_NAME,
|
|
|
|
align: 'center',
|
|
|
|
defaultStyle: {
|
|
boxSizing : 'border-box',
|
|
|
|
display : 'inline-flex',
|
|
alignItems : 'center',
|
|
justifyContent: 'center',
|
|
|
|
userSelect : 'none',
|
|
textDecoration: 'none',
|
|
cursor : 'pointer',
|
|
overflow : 'hidden',
|
|
|
|
//theme properties
|
|
//fontFamily: 'Arial',
|
|
// fontSize : '0.9em',
|
|
whiteSpace: 'nowrap',
|
|
padding : 5,
|
|
margin : 2
|
|
},
|
|
|
|
defaultDisabledStyle: {
|
|
cursor: 'default',
|
|
},
|
|
|
|
defaultLabelStyle: {
|
|
display: 'inline-block'
|
|
},
|
|
|
|
ellipsisLabelStyle: {
|
|
textOverflow: 'ellipsis',
|
|
overflow: 'hidden',
|
|
whiteSpace: 'nowrap'
|
|
},
|
|
|
|
ellipsis: true,
|
|
|
|
href: ''
|
|
}
|
|
},
|
|
|
|
getInitialState: function() {
|
|
return {
|
|
mouseOver: false,
|
|
active: false,
|
|
defaultPressed: this.props.defaultPressed
|
|
}
|
|
},
|
|
|
|
isFocused: function() {
|
|
return this.state.focused
|
|
},
|
|
|
|
isActive: function() {
|
|
return !!this.state.active
|
|
},
|
|
|
|
render: function(){
|
|
var props = this.prepareProps(this.props, this.state)
|
|
|
|
return (props.factory || React.DOM.a)(props)
|
|
},
|
|
|
|
prepareProps: function(thisProps, state) {
|
|
|
|
var props = {}
|
|
|
|
assign(props, thisProps)
|
|
|
|
props.theme = this.prepareTheme(props)
|
|
|
|
var pressed = props.pressed != null? props.pressed: state.defaultPressed
|
|
|
|
if (pressed != null){
|
|
props.pressed = pressed
|
|
}
|
|
|
|
props.active = props.activeState == null? !!state.active: props.activeState
|
|
props.over = props.overState == null? !!state.mouseOver: props.overState
|
|
props.focused = props.focusedState == null? !!state.focused: props.focusedState
|
|
|
|
props['data-active'] = props.active
|
|
props['data-over'] = props.over
|
|
props['data-focused'] = props.focused
|
|
props['data-pressed'] = props.pressed
|
|
props['data-disabled'] = props.disabled
|
|
|
|
props.style = this.prepareStyle(props, state)
|
|
props.className = this.prepareClassName(props, state)
|
|
props.children = this.prepareChildren(props)
|
|
|
|
var handleClick = this.handleClick.bind(this, props)
|
|
|
|
props.onClick = typeof props.interceptClick == 'function'?
|
|
props.interceptClick.bind(this, handleClick):
|
|
handleClick
|
|
|
|
props.onFocus = this.handleFocus.bind(this, props)
|
|
props.onBlur = this.handleBlur.bind(this, props)
|
|
props.onMouseEnter = this.handleMouseEnter.bind(this, props)
|
|
props.onMouseLeave = this.handleMouseLeave.bind(this, props)
|
|
props.onMouseDown = this.handleMouseDown.bind(this, props)
|
|
props.onMouseUp = this.handleMouseUp.bind(this, props)
|
|
|
|
return props
|
|
},
|
|
|
|
handleFocus: function(props, event) {
|
|
if (props.disabled){
|
|
return
|
|
}
|
|
|
|
this.setState({
|
|
focused: true
|
|
})
|
|
|
|
;(this.props.onFocus || emptyFn)(event)
|
|
},
|
|
|
|
handleBlur: function(props, event) {
|
|
if (props.disabled){
|
|
return
|
|
}
|
|
|
|
this.setState({
|
|
focused: false
|
|
})
|
|
|
|
;(this.props.onBlur || emptyFn)(event)
|
|
},
|
|
|
|
handleClick: function(props, event) {
|
|
if (!props.href || props.disabled){
|
|
event.preventDefault()
|
|
}
|
|
|
|
if (props.disabled){
|
|
return
|
|
}
|
|
|
|
if (props.pressed != null){
|
|
var newPressed = !props.pressed
|
|
|
|
if (this.props.pressed == null){
|
|
this.setState({
|
|
defaultPressed: newPressed
|
|
})
|
|
}
|
|
|
|
;(this.props.onToggle || emptyFn)(newPressed, event)
|
|
}
|
|
|
|
;(this.props.onClick || emptyFn)(event)
|
|
;(this.props.fn || emptyFn)(props, event)
|
|
},
|
|
|
|
handleMouseEnter: function(props, event) {
|
|
if (props.disabled){
|
|
return
|
|
}
|
|
|
|
this.setState({
|
|
mouseOver: true
|
|
})
|
|
|
|
;(this.props.onMouseEnter || emptyFn)(event)
|
|
},
|
|
|
|
handleMouseLeave: function(props, event) {
|
|
if (props.disabled){
|
|
return
|
|
}
|
|
|
|
this.setState({
|
|
mouseOver: false
|
|
})
|
|
|
|
;(this.props.onMouseLeave || emptyFn)(event)
|
|
},
|
|
|
|
handleMouseUp: function(props, event) {
|
|
if (props.disabled){
|
|
return
|
|
}
|
|
|
|
this.setState({
|
|
active: false
|
|
})
|
|
|
|
window.removeEventListener('mouseup', this.handleMouseUp)
|
|
|
|
;(this.props.onMouseUp || emptyFn)(event)
|
|
;(this.props.onDeactivate || emptyFn)(event)
|
|
},
|
|
|
|
handleMouseDown: function(props, event) {
|
|
|
|
if (props.disabled){
|
|
return
|
|
}
|
|
|
|
this.setState({
|
|
active: true
|
|
})
|
|
|
|
window.addEventListener('mouseup', this.handleMouseUp)
|
|
|
|
;(this.props.onMouseDown || emptyFn)(event)
|
|
;(this.props.onActivate || emptyFn)(event)
|
|
},
|
|
|
|
prepareTheme: function(props){
|
|
var theme = props.theme
|
|
var THEMES = props.themes = props.themes || this.constructor.theme || THEME
|
|
|
|
if (typeof theme == 'string'){
|
|
theme = THEMES[theme]?
|
|
THEMES[theme]:
|
|
null
|
|
}
|
|
|
|
return theme == null?
|
|
THEMES.default:
|
|
theme
|
|
},
|
|
|
|
prepareChildren: function(props) {
|
|
var children = props.children
|
|
|
|
if (props.label){
|
|
|
|
var labelProps = assign({}, props.defaultLabelProps, props.labelProps)
|
|
var defaultLabelStyle = assign({}, props.defaultLabelStyle)
|
|
|
|
if (props.ellipsis){
|
|
assign(defaultLabelStyle, props.ellipsisLabelStyle)
|
|
}
|
|
|
|
var labelStyle = assign({}, defaultLabelStyle, labelProps.style, props.labelStyle)
|
|
|
|
labelProps.style = labelStyle
|
|
|
|
children = React.createElement("span", React.__spread({}, labelProps),
|
|
props.label
|
|
)
|
|
}
|
|
|
|
if (typeof this.props.renderChildren === 'function'){
|
|
return this.props.renderChildren(children)
|
|
}
|
|
|
|
return children
|
|
},
|
|
|
|
prepareClassName: function(props) {
|
|
|
|
var className = props.className || ''
|
|
|
|
if (props.disabled){
|
|
if (props.disabledClassName){
|
|
className += ' ' + props.disabledClassName
|
|
}
|
|
} else {
|
|
if (props.active && props.activeClassName){
|
|
className += ' ' + props.activeClassName
|
|
}
|
|
|
|
if (props.pressed && props.pressedClassName){
|
|
className += ' ' + props.pressedClassName
|
|
}
|
|
|
|
if (props.over && props.overClassName){
|
|
className += ' ' + props.overClassName
|
|
}
|
|
|
|
if (props.focused && props.focusedClassName){
|
|
className += ' ' + props.focusedClassName
|
|
}
|
|
}
|
|
|
|
return className
|
|
},
|
|
|
|
prepareComputedStyleNames: function(props){
|
|
|
|
if (typeof props.computeStyleNames == 'function'){
|
|
return props.computeStyleNames(props)
|
|
}
|
|
|
|
var names = ['style']
|
|
|
|
if (props.disabled){
|
|
names.push('disabledStyle')
|
|
|
|
return names
|
|
}
|
|
|
|
if (props.focused){
|
|
names.push('focusedStyle')
|
|
}
|
|
if (props.pressed){
|
|
names.push('pressedStyle')
|
|
}
|
|
|
|
if (typeof props.addStateStyle == 'function'){
|
|
props.addStateStyle(names)
|
|
}
|
|
|
|
if (props.focused && props.pressed){
|
|
names.push('focusedPressedStyle')
|
|
}
|
|
|
|
if (typeof props.addCombinedStateStyle == 'function'){
|
|
props.addCombinedStateStyle(names)
|
|
}
|
|
|
|
//names is something like ['style','focusedStyle','pressedStyle', 'focusedPressedStyle']
|
|
//
|
|
//now we add over and active styles
|
|
|
|
var overNames
|
|
if (props.over){
|
|
overNames = names.map(function(name){
|
|
return 'over' + toUpperFirst(name)
|
|
})
|
|
}
|
|
|
|
var activeNames
|
|
if (props.active){
|
|
activeNames = names.map(function(name){
|
|
return 'active' + toUpperFirst(name)
|
|
})
|
|
}
|
|
|
|
overNames && names.push.apply(names, overNames)
|
|
activeNames && names.push.apply(names, activeNames)
|
|
|
|
return names
|
|
},
|
|
|
|
prepareStyle: function(props) {
|
|
|
|
var style = assign({}, this.prepareDefaultStyle(props))
|
|
|
|
var styleNames = this.prepareComputedStyleNames(props)
|
|
var theme = props.theme
|
|
var THEMES = props.themes
|
|
|
|
if (theme){
|
|
//apply default theme first
|
|
if (props.applyDefaultTheme && THEMES.default && theme != THEMES.default){
|
|
styleNames.forEach(function(styleName){
|
|
assign(style, THEMES.default[styleName])
|
|
})
|
|
}
|
|
|
|
//then apply theme
|
|
styleNames.forEach(function(styleName){
|
|
assign(style, theme[styleName])
|
|
})
|
|
}
|
|
|
|
;(props.onThemeStyleReady || emptyFn)(style, props)
|
|
|
|
//TODO apply default non-theme first to typed buttons
|
|
//then non-theme
|
|
styleNames.forEach(function(styleName){
|
|
assign(style, props[styleName])
|
|
})
|
|
|
|
;(props.onStyleReady || emptyFn)(style, props)
|
|
|
|
return normalize(style)
|
|
},
|
|
|
|
prepareDefaultStyle: function(props){
|
|
var defaultStyle = assign({}, props.defaultStyle)
|
|
|
|
if (props.block){
|
|
defaultStyle.display = 'flex'
|
|
}
|
|
|
|
defaultStyle.justifyContent = ALIGN(props.align)
|
|
|
|
if (props.disabled){
|
|
assign(defaultStyle, props.defaultDisabledStyle)
|
|
}
|
|
|
|
return defaultStyle
|
|
}
|
|
})
|
|
|
|
ReactButton.themes = THEME
|
|
|
|
module.exports = ReactButton |