Summary: My benchmarks have shown react-emotion to be faster than the current implementation of `styled`. For this reason, I am converting all styling to [emotion](https://emotion.sh). Benchmark results: {F136839093} The syntax is very similar between the two libraries. The main difference is that emotion only allows a single function for the whole style attribute, whereas the old implementation had functions for every style-attirbute. Before: ``` { color: props => props.color, fontSize: props => props.size, } ``` After: ``` props => ({ color: props.color, fontSize: props.size, }) ``` Reviewed By: jknoxville Differential Revision: D9479893 fbshipit-source-id: 2c39e4618f7e52ceacb67bbec8ae26114025723f
126 lines
2.8 KiB
JavaScript
126 lines
2.8 KiB
JavaScript
/**
|
|
* Copyright 2018-present Facebook.
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
* @format
|
|
*/
|
|
|
|
import styled from '../styled/index.js';
|
|
import {colors, darkColors} from './colors.js';
|
|
|
|
const React = require('react');
|
|
|
|
const DesktopDropdownContainer = styled('div')({
|
|
borderBottom: `1px solid ${darkColors.dividers}`,
|
|
lineHeight: '25px',
|
|
marginTop: 5,
|
|
maxHeight: 600,
|
|
minWidth: 180,
|
|
overflow: 'auto',
|
|
padding: 0,
|
|
paddingBottom: 5,
|
|
textAlign: 'left',
|
|
width: 'auto',
|
|
|
|
'&:last-child': {
|
|
borderBottom: 'none',
|
|
},
|
|
});
|
|
|
|
export function DesktopDropdown(props: {|
|
|
deactivate?: () => void,
|
|
children?: any,
|
|
|}) {
|
|
return (
|
|
<DesktopDropdownContainer>
|
|
{React.Children.map(props.children, child => {
|
|
return (
|
|
child &&
|
|
React.cloneElement(child, {
|
|
deactivate: props.deactivate,
|
|
})
|
|
);
|
|
})}
|
|
</DesktopDropdownContainer>
|
|
);
|
|
}
|
|
|
|
const DesktopDropdownItemContainer = styled('div')(props => ({
|
|
listStyle: 'none',
|
|
opacity: props.onClick || props.onHover ? 1 : 0.5,
|
|
padding: '0 20px',
|
|
'&:hover': {
|
|
backgroundColor: props.onClick || props.onHover ? colors.highlight : '',
|
|
color: props.onClick || props.onHover ? '#fff' : 'inherit',
|
|
},
|
|
}));
|
|
|
|
type DesktopDropdownItemState = {|hovered: boolean|};
|
|
|
|
type DesktopDropdownItemProps = {
|
|
onClick?: false | ?((event: SyntheticMouseEvent<>) => void),
|
|
onHover?: false | ?(() => React$Node),
|
|
children?: React$Node,
|
|
deactivate?: () => void,
|
|
};
|
|
|
|
export class DesktopDropdownItem extends React.Component<
|
|
DesktopDropdownItemProps,
|
|
DesktopDropdownItemState,
|
|
> {
|
|
constructor(props: DesktopDropdownItemProps, context: Object) {
|
|
super(props, context);
|
|
this.state = {hovered: false};
|
|
}
|
|
|
|
onMouseEnter = () => {
|
|
this.setState({hovered: true});
|
|
};
|
|
|
|
onMouseLeave = () => {
|
|
this.setState({hovered: false});
|
|
};
|
|
|
|
onClick = (event: SyntheticMouseEvent<>) => {
|
|
const {deactivate, onClick} = this.props;
|
|
if (typeof onClick === 'function') {
|
|
if (deactivate) {
|
|
deactivate();
|
|
}
|
|
onClick(event);
|
|
}
|
|
};
|
|
|
|
render() {
|
|
const {hovered} = this.state;
|
|
const {
|
|
children,
|
|
deactivate: _deactivate,
|
|
onClick,
|
|
onHover,
|
|
...props
|
|
} = this.props;
|
|
|
|
return (
|
|
<DesktopDropdownItemContainer
|
|
{...props}
|
|
onMouseEnter={this.onMouseEnter}
|
|
onMouseLeave={this.onMouseLeave}
|
|
onClick={typeof onClick === 'function' && this.onClick}>
|
|
{children}
|
|
{hovered && typeof onHover === 'function' && onHover()}
|
|
</DesktopDropdownItemContainer>
|
|
);
|
|
}
|
|
}
|
|
|
|
export const DesktopDropdownSelectedItem = styled(DesktopDropdownItem)({
|
|
position: 'relative',
|
|
|
|
'&::before': {
|
|
content: "'✔'",
|
|
marginLeft: '-15px',
|
|
position: 'absolute',
|
|
},
|
|
});
|