Add search bar and test entry item
This commit is contained in:
parent
b497ec46f2
commit
6912567122
5 changed files with 804 additions and 52 deletions
|
|
@ -5,21 +5,22 @@ import getMuiTheme from 'material-ui/lib/styles/getMuiTheme'
|
||||||
|
|
||||||
import List from 'material-ui/lib/lists/list'
|
import List from 'material-ui/lib/lists/list'
|
||||||
import ListItem from 'material-ui/lib/lists/list-item'
|
import ListItem from 'material-ui/lib/lists/list-item'
|
||||||
import ActionGrade from 'material-ui/lib/svg-icons/action/grade'
|
import Description from 'material-ui/lib/svg-icons/action/description'
|
||||||
import History from 'material-ui/lib/svg-icons/action/history'
|
import Add from 'material-ui/lib/svg-icons/content/add'
|
||||||
import AddCircleOutline from 'material-ui/lib/svg-icons/content/add-circle-outline'
|
import Search from 'material-ui/lib/svg-icons/action/search'
|
||||||
import Folder from 'material-ui/lib/svg-icons/file/folder'
|
import SelectableList from 'SelectableList'
|
||||||
import Delete from 'material-ui/lib/svg-icons/action/delete'
|
|
||||||
import Divider from 'material-ui/lib/divider'
|
|
||||||
|
|
||||||
|
import Item from 'Item'
|
||||||
|
|
||||||
const {AppBar,
|
const {AppBar,
|
||||||
AppCanvas,
|
AppCanvas,
|
||||||
FontIcon,
|
FontIcon,
|
||||||
IconButton,
|
IconButton,
|
||||||
EnhancedButton,
|
EnhancedButton,
|
||||||
|
AutoComplete,
|
||||||
NavigationClose,
|
NavigationClose,
|
||||||
Menu,
|
Menu,
|
||||||
|
MenuItem,
|
||||||
Mixins,
|
Mixins,
|
||||||
RaisedButton,
|
RaisedButton,
|
||||||
FlatButton,
|
FlatButton,
|
||||||
|
|
@ -27,6 +28,7 @@ const {AppBar,
|
||||||
Styles,
|
Styles,
|
||||||
Tab,
|
Tab,
|
||||||
Tabs,
|
Tabs,
|
||||||
|
TextField,
|
||||||
Paper} = mui
|
Paper} = mui
|
||||||
|
|
||||||
const colors = Styles.Colors
|
const colors = Styles.Colors
|
||||||
|
|
@ -56,9 +58,41 @@ export default class EntrySelector extends React.Component {
|
||||||
|
|
||||||
render(){
|
render(){
|
||||||
return (
|
return (
|
||||||
<div id={this.props.id} className={this.props.className}></div>
|
<Paper id={this.props.id} className={this.props.className} zDepth={0}>
|
||||||
|
<Paper zDepth={0}>
|
||||||
|
<Item
|
||||||
|
id="search-bar"
|
||||||
|
active={false}
|
||||||
|
selected={false}
|
||||||
|
leftIcon={<Search color={colors.grey600}/>}
|
||||||
|
rightIconButton={<IconButton tooltip="Add New Note">
|
||||||
|
<Add color={colors.grey600}/>
|
||||||
|
</IconButton>}>
|
||||||
|
<TextField
|
||||||
|
hintText="Filter by keyword, title or tag."
|
||||||
|
onKeyDown={()=>{}}
|
||||||
|
onEnterKeyDown={()=>{}}
|
||||||
|
/>
|
||||||
|
</Item>
|
||||||
|
</Paper>
|
||||||
|
<SelectableList
|
||||||
|
id="entry-list"
|
||||||
|
ref="entryList"
|
||||||
|
selectedItemStyle={{backgroundColor: colors.grey300}}>
|
||||||
|
<ListItem
|
||||||
|
leftAvatar={<Description color={colors.grey700}/>}
|
||||||
|
primaryText="Today's Notes"
|
||||||
|
secondaryText={
|
||||||
|
<p>
|
||||||
|
<span style={{color: colors.darkBlack}}>I did things</span> --
|
||||||
|
I did so many things today, it's not even funny. You think it's funny?
|
||||||
|
Well it's not!
|
||||||
|
</p>
|
||||||
|
}
|
||||||
|
secondaryTextLines={2}
|
||||||
|
/>
|
||||||
|
</SelectableList>
|
||||||
|
</Paper>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
691
app/components/Item.jsx
Normal file
691
app/components/Item.jsx
Normal file
|
|
@ -0,0 +1,691 @@
|
||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
|
import ColorManipulator from 'material-ui/lib/utils/color-manipulator';
|
||||||
|
import StylePropable from 'material-ui/lib/mixins/style-propable';
|
||||||
|
import Colors from 'material-ui/lib/styles/colors';
|
||||||
|
import Transitions from 'material-ui/lib/styles/transitions';
|
||||||
|
import Typography from 'material-ui/lib/styles/typography';
|
||||||
|
import EnhancedButton from 'material-ui/lib/enhanced-button';
|
||||||
|
import IconButton from 'material-ui/lib/icon-button';
|
||||||
|
import OpenIcon from 'material-ui/lib/svg-icons/navigation/arrow-drop-up';
|
||||||
|
import CloseIcon from 'material-ui/lib/svg-icons/navigation/arrow-drop-down';
|
||||||
|
import NestedList from 'material-ui/lib/lists/nested-list';
|
||||||
|
import getMuiTheme from 'material-ui/lib/styles/getMuiTheme';
|
||||||
|
|
||||||
|
const Item = React.createClass({
|
||||||
|
|
||||||
|
propTypes: {
|
||||||
|
/**
|
||||||
|
* Generate a nested list indicator icon when
|
||||||
|
* nested list items are detected. Set to false
|
||||||
|
* if you do not want an indicator auto-generated.
|
||||||
|
* Note that an indicator will not be created if a
|
||||||
|
* rightIcon/Button has been specified.
|
||||||
|
*/
|
||||||
|
autoGenerateNestedIndicator: React.PropTypes.bool,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Children passed into the ListItem.
|
||||||
|
*/
|
||||||
|
children: React.PropTypes.node,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does not allow the element to be focused by the keyboard.
|
||||||
|
*/
|
||||||
|
disableKeyboardFocus: React.PropTypes.bool,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If true, the list-item will not be clickable
|
||||||
|
* and will not display hover affects.
|
||||||
|
* This is automatically disabled if leftCheckbox
|
||||||
|
* or rightToggle is set.
|
||||||
|
*/
|
||||||
|
disabled: React.PropTypes.bool,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controls whether or not the child ListItems are initially displayed.
|
||||||
|
*/
|
||||||
|
initiallyOpen: React.PropTypes.bool,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Style prop for the innder div element.
|
||||||
|
*/
|
||||||
|
innerDivStyle: React.PropTypes.object,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If true, the children will be indented by 72px.
|
||||||
|
* Only needed if there is no left avatar or left icon.
|
||||||
|
*/
|
||||||
|
insetChildren: React.PropTypes.bool,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the Avatar element to be displayed on the left side.
|
||||||
|
*/
|
||||||
|
leftAvatar: React.PropTypes.element,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the Checkbox element to be displayed on the left side.
|
||||||
|
*/
|
||||||
|
leftCheckbox: React.PropTypes.element,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the SvgIcon or FontIcon to be displayed on the left side.
|
||||||
|
*/
|
||||||
|
leftIcon: React.PropTypes.element,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array of ListItems to nest underneath the current ListItem.
|
||||||
|
*/
|
||||||
|
nestedItems: React.PropTypes.arrayOf(React.PropTypes.element),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controls how deep a ListItem appears.
|
||||||
|
* This property is automatically managed so modify at your own risk.
|
||||||
|
*/
|
||||||
|
nestedLevel: React.PropTypes.number,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override the inline-styles of the nestedItems NestedList.
|
||||||
|
*/
|
||||||
|
nestedListStyle: React.PropTypes.object,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the ListItem has keyboard focus.
|
||||||
|
*/
|
||||||
|
onKeyboardFocus: React.PropTypes.func,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the mouse is over the ListItem.
|
||||||
|
*/
|
||||||
|
onMouseEnter: React.PropTypes.func,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the mouse is no longer over the ListItem.
|
||||||
|
*/
|
||||||
|
onMouseLeave: React.PropTypes.func,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the ListItem toggles its nested ListItems.
|
||||||
|
*/
|
||||||
|
onNestedListToggle: React.PropTypes.func,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when touches start.
|
||||||
|
*/
|
||||||
|
onTouchStart: React.PropTypes.func,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a touch tap event occures on the component.
|
||||||
|
*/
|
||||||
|
onTouchTap: React.PropTypes.func,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the block element that contains the primary text.
|
||||||
|
* If a string is passed in, a div tag will be rendered.
|
||||||
|
*/
|
||||||
|
primaryText: React.PropTypes.node,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If provided, tapping on the primary text
|
||||||
|
* of the item toggles the nested list.
|
||||||
|
*/
|
||||||
|
primaryTogglesNestedList: React.PropTypes.bool,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the avatar element to be displayed on the right side.
|
||||||
|
*/
|
||||||
|
rightAvatar: React.PropTypes.element,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the SvgIcon or FontIcon to be displayed on the right side.
|
||||||
|
*/
|
||||||
|
rightIcon: React.PropTypes.element,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the IconButton to be displayed on the right side.
|
||||||
|
* Hovering over this button will remove the ListItem hover.
|
||||||
|
* Also, clicking on this button will not trigger a
|
||||||
|
* ListItem ripple. The event will be stopped and prevented
|
||||||
|
* from bubbling up to cause a ListItem click.
|
||||||
|
*/
|
||||||
|
rightIconButton: React.PropTypes.element,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the Toggle element to display on the right side.
|
||||||
|
*/
|
||||||
|
rightToggle: React.PropTypes.element,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the block element that contains the secondary text.
|
||||||
|
* If a string is passed in, a div tag will be rendered.
|
||||||
|
*/
|
||||||
|
secondaryText: React.PropTypes.node,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can be 1 or 2. This is the number of secondary
|
||||||
|
* text lines before ellipsis will show.
|
||||||
|
*/
|
||||||
|
secondaryTextLines: React.PropTypes.oneOf([1, 2]),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override the inline-styles of the root element.
|
||||||
|
*/
|
||||||
|
style: React.PropTypes.object,
|
||||||
|
},
|
||||||
|
|
||||||
|
contextTypes: {
|
||||||
|
muiTheme: React.PropTypes.object,
|
||||||
|
},
|
||||||
|
|
||||||
|
//for passing default theme context to children
|
||||||
|
childContextTypes: {
|
||||||
|
muiTheme: React.PropTypes.object,
|
||||||
|
},
|
||||||
|
|
||||||
|
mixins: [
|
||||||
|
PureRenderMixin,
|
||||||
|
StylePropable,
|
||||||
|
],
|
||||||
|
|
||||||
|
getDefaultProps() {
|
||||||
|
return {
|
||||||
|
autoGenerateNestedIndicator: true,
|
||||||
|
disableKeyboardFocus: false,
|
||||||
|
disabled: false,
|
||||||
|
initiallyOpen: false,
|
||||||
|
insetChildren: false,
|
||||||
|
nestedItems: [],
|
||||||
|
nestedLevel: 0,
|
||||||
|
onKeyboardFocus: () => {},
|
||||||
|
onMouseEnter: () => {},
|
||||||
|
onMouseLeave: () => {},
|
||||||
|
onNestedListToggle: () => {},
|
||||||
|
onTouchStart: () => {},
|
||||||
|
primaryTogglesNestedList: false,
|
||||||
|
secondaryTextLines: 1,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
getInitialState() {
|
||||||
|
return {
|
||||||
|
hovered: false,
|
||||||
|
isKeyboardFocused: false,
|
||||||
|
open: this.props.initiallyOpen,
|
||||||
|
rightIconButtonHovered: false,
|
||||||
|
rightIconButtonKeyboardFocused: false,
|
||||||
|
touch: false,
|
||||||
|
muiTheme: this.context.muiTheme || getMuiTheme(),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
getChildContext() {
|
||||||
|
return {
|
||||||
|
muiTheme: this.state.muiTheme,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
//to update theme inside state whenever a new theme is passed down
|
||||||
|
//from the parent / owner using context
|
||||||
|
componentWillReceiveProps(nextProps, nextContext) {
|
||||||
|
let newMuiTheme = nextContext.muiTheme ? nextContext.muiTheme : this.state.muiTheme;
|
||||||
|
this.setState({muiTheme: newMuiTheme});
|
||||||
|
},
|
||||||
|
|
||||||
|
applyFocusState(focusState) {
|
||||||
|
const button = this.refs.enhancedButton;
|
||||||
|
const buttonEl = ReactDOM.findDOMNode(button);
|
||||||
|
|
||||||
|
if (button) {
|
||||||
|
switch (focusState) {
|
||||||
|
case 'none':
|
||||||
|
buttonEl.blur();
|
||||||
|
break;
|
||||||
|
case 'focused':
|
||||||
|
buttonEl.focus();
|
||||||
|
break;
|
||||||
|
case 'keyboard-focused':
|
||||||
|
button.setKeyboardFocus();
|
||||||
|
buttonEl.focus();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_createDisabledElement(styles, contentChildren, additionalProps) {
|
||||||
|
const {
|
||||||
|
innerDivStyle,
|
||||||
|
style,
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
const mergedDivStyles = this.mergeStyles(
|
||||||
|
styles.root,
|
||||||
|
styles.innerDiv,
|
||||||
|
innerDivStyle,
|
||||||
|
style
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
{...additionalProps}
|
||||||
|
style={this.prepareStyles(mergedDivStyles)}
|
||||||
|
>
|
||||||
|
{contentChildren}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
_createLabelElement(styles, contentChildren, additionalProps) {
|
||||||
|
const {
|
||||||
|
innerDivStyle,
|
||||||
|
style,
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
const mergedLabelStyles = this.mergeStyles(
|
||||||
|
styles.root,
|
||||||
|
styles.innerDiv,
|
||||||
|
innerDivStyle,
|
||||||
|
styles.label,
|
||||||
|
style
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<label
|
||||||
|
{...additionalProps}
|
||||||
|
style={this.prepareStyles(mergedLabelStyles)}
|
||||||
|
>
|
||||||
|
{contentChildren}
|
||||||
|
</label>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
_createTextElement(styles, data, key) {
|
||||||
|
const isAnElement = React.isValidElement(data);
|
||||||
|
const mergedStyles = isAnElement ?
|
||||||
|
this.mergeStyles(styles, data.props.style) : null;
|
||||||
|
|
||||||
|
return isAnElement ? (
|
||||||
|
React.cloneElement(data, {
|
||||||
|
key: key,
|
||||||
|
style: this.prepareStyles(mergedStyles),
|
||||||
|
})
|
||||||
|
) : (
|
||||||
|
<div key={key} style={this.prepareStyles(styles)}>
|
||||||
|
{data}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
_handleKeyboardFocus(e, isKeyboardFocused) {
|
||||||
|
this.setState({isKeyboardFocused: isKeyboardFocused});
|
||||||
|
this.props.onKeyboardFocus(e, isKeyboardFocused);
|
||||||
|
},
|
||||||
|
|
||||||
|
_handleMouseEnter(e) {
|
||||||
|
this.props.onMouseEnter(e);
|
||||||
|
},
|
||||||
|
|
||||||
|
_handleMouseLeave(e) {
|
||||||
|
this.props.onMouseLeave(e);
|
||||||
|
},
|
||||||
|
|
||||||
|
_handleNestedListToggle(e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
this.setState({open: !this.state.open});
|
||||||
|
this.props.onNestedListToggle(this);
|
||||||
|
},
|
||||||
|
|
||||||
|
_handleRightIconButtonKeyboardFocus(e, isKeyboardFocused) {
|
||||||
|
const iconButton = this.props.rightIconButton;
|
||||||
|
let newState = {};
|
||||||
|
|
||||||
|
newState.rightIconButtonKeyboardFocused = isKeyboardFocused;
|
||||||
|
if (isKeyboardFocused) newState.isKeyboardFocused = false;
|
||||||
|
this.setState(newState);
|
||||||
|
|
||||||
|
if (iconButton && iconButton.props.onKeyboardFocus) iconButton.props.onKeyboardFocus(e, isKeyboardFocused);
|
||||||
|
},
|
||||||
|
|
||||||
|
_handleRightIconButtonMouseDown(e) {
|
||||||
|
const iconButton = this.props.rightIconButton;
|
||||||
|
e.stopPropagation();
|
||||||
|
if (iconButton && iconButton.props.onMouseDown) iconButton.props.onMouseDown(e);
|
||||||
|
},
|
||||||
|
|
||||||
|
_handleRightIconButtonMouseLeave(e) {
|
||||||
|
const iconButton = this.props.rightIconButton;
|
||||||
|
this.setState({rightIconButtonHovered: false});
|
||||||
|
if (iconButton && iconButton.props.onMouseLeave) iconButton.props.onMouseLeave(e);
|
||||||
|
},
|
||||||
|
|
||||||
|
_handleRightIconButtonMouseEnter(e) {
|
||||||
|
const iconButton = this.props.rightIconButton;
|
||||||
|
this.setState({rightIconButtonHovered: true});
|
||||||
|
if (iconButton && iconButton.props.onMouseEnter) iconButton.props.onMouseEnter(e);
|
||||||
|
},
|
||||||
|
|
||||||
|
_handleRightIconButtonMouseUp(e) {
|
||||||
|
const iconButton = this.props.rightIconButton;
|
||||||
|
e.stopPropagation();
|
||||||
|
if (iconButton && iconButton.props.onMouseUp) iconButton.props.onMouseUp(e);
|
||||||
|
},
|
||||||
|
|
||||||
|
_handleRightIconButtonTouchTap(e) {
|
||||||
|
const iconButton = this.props.rightIconButton;
|
||||||
|
|
||||||
|
//Stop the event from bubbling up to the list-item
|
||||||
|
e.stopPropagation();
|
||||||
|
if (iconButton && iconButton.props.onTouchTap) iconButton.props.onTouchTap(e);
|
||||||
|
},
|
||||||
|
|
||||||
|
_handleTouchStart(e) {
|
||||||
|
this.setState({touch: true});
|
||||||
|
this.props.onTouchStart(e);
|
||||||
|
},
|
||||||
|
|
||||||
|
_pushElement(children, element, baseStyles, additionalProps) {
|
||||||
|
if (element) {
|
||||||
|
const styles = this.mergeStyles(baseStyles, element.props.style);
|
||||||
|
children.push(
|
||||||
|
React.cloneElement(element, {
|
||||||
|
key: children.length,
|
||||||
|
style: styles,
|
||||||
|
...additionalProps,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
autoGenerateNestedIndicator,
|
||||||
|
children,
|
||||||
|
disabled,
|
||||||
|
disableKeyboardFocus,
|
||||||
|
innerDivStyle,
|
||||||
|
insetChildren,
|
||||||
|
leftAvatar,
|
||||||
|
leftCheckbox,
|
||||||
|
leftIcon,
|
||||||
|
nestedItems,
|
||||||
|
nestedLevel,
|
||||||
|
nestedListStyle,
|
||||||
|
onKeyboardFocus,
|
||||||
|
onMouseLeave,
|
||||||
|
onMouseEnter,
|
||||||
|
onTouchStart,
|
||||||
|
onTouchTap,
|
||||||
|
rightAvatar,
|
||||||
|
rightIcon,
|
||||||
|
rightIconButton,
|
||||||
|
leftIconButton,
|
||||||
|
rightToggle,
|
||||||
|
primaryText,
|
||||||
|
primaryTogglesNestedList,
|
||||||
|
secondaryText,
|
||||||
|
secondaryTextLines,
|
||||||
|
style,
|
||||||
|
...other,
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
const textColor = this.state.muiTheme.rawTheme.palette.textColor;
|
||||||
|
const hoverColor = ColorManipulator.fade(textColor, 0.1);
|
||||||
|
const singleAvatar = !secondaryText && (leftAvatar || rightAvatar);
|
||||||
|
const singleNoAvatar = !secondaryText && !(leftAvatar || rightAvatar);
|
||||||
|
const twoLine = secondaryText && secondaryTextLines === 1;
|
||||||
|
const threeLine = secondaryText && secondaryTextLines > 1;
|
||||||
|
const hasCheckbox = true;
|
||||||
|
|
||||||
|
const styles = {
|
||||||
|
root: {
|
||||||
|
backgroundColor: (this.state.isKeyboardFocused || this.state.hovered) &&
|
||||||
|
!this.state.leftIconButtonHovered &&
|
||||||
|
!this.state.leftIconButtonHovered ? hoverColor : null &&
|
||||||
|
!this.state.rightIconButtonHovered &&
|
||||||
|
!this.state.rightIconButtonKeyboardFocused ? hoverColor : null,
|
||||||
|
color: textColor,
|
||||||
|
display: 'block',
|
||||||
|
fontSize: 16,
|
||||||
|
lineHeight: '16px',
|
||||||
|
position: 'relative',
|
||||||
|
transition: Transitions.easeOut(),
|
||||||
|
},
|
||||||
|
|
||||||
|
//This inner div is needed so that ripples will span the entire container
|
||||||
|
innerDiv: {
|
||||||
|
marginLeft: nestedLevel * this.state.muiTheme.listItem.nestedLevelDepth,
|
||||||
|
paddingLeft: leftIcon || leftAvatar || leftIconButton || leftCheckbox || insetChildren ? 72 : 16,
|
||||||
|
paddingRight: rightIcon || rightAvatar || rightIconButton ? 56 : rightToggle ? 72 : 16,
|
||||||
|
paddingBottom: singleAvatar ? 20 : 16,
|
||||||
|
paddingTop: singleNoAvatar || threeLine ? 16 : 20,
|
||||||
|
position: 'relative',
|
||||||
|
},
|
||||||
|
|
||||||
|
icons: {
|
||||||
|
height: 24,
|
||||||
|
width: 24,
|
||||||
|
display: 'block',
|
||||||
|
position: 'absolute',
|
||||||
|
top: twoLine ? 12 : singleAvatar ? 4 : 0,
|
||||||
|
margin: 12,
|
||||||
|
},
|
||||||
|
|
||||||
|
leftIcon: {
|
||||||
|
color: Colors.grey600,
|
||||||
|
fill: Colors.grey600,
|
||||||
|
left: 4,
|
||||||
|
},
|
||||||
|
|
||||||
|
rightIcon: {
|
||||||
|
color: Colors.grey400,
|
||||||
|
fill: Colors.grey400,
|
||||||
|
right: 4,
|
||||||
|
},
|
||||||
|
|
||||||
|
avatars: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: singleAvatar ? 8 : 16,
|
||||||
|
},
|
||||||
|
|
||||||
|
label: {
|
||||||
|
cursor: 'pointer',
|
||||||
|
},
|
||||||
|
|
||||||
|
leftAvatar: {
|
||||||
|
left: 16,
|
||||||
|
},
|
||||||
|
|
||||||
|
rightAvatar: {
|
||||||
|
right: 16,
|
||||||
|
},
|
||||||
|
|
||||||
|
leftCheckbox: {
|
||||||
|
position: 'absolute',
|
||||||
|
display: 'block',
|
||||||
|
width: 24,
|
||||||
|
top: twoLine ? 24 : singleAvatar ? 16 : 12,
|
||||||
|
left: 16,
|
||||||
|
},
|
||||||
|
|
||||||
|
primaryText: {
|
||||||
|
},
|
||||||
|
|
||||||
|
rightIconButton: {
|
||||||
|
position: 'absolute',
|
||||||
|
display: 'block',
|
||||||
|
top: twoLine ? 12 : singleAvatar ? 4 : 0,
|
||||||
|
right: 4,
|
||||||
|
},
|
||||||
|
|
||||||
|
leftIconButton: {
|
||||||
|
position: 'absolute',
|
||||||
|
display: 'block',
|
||||||
|
top: twoLine ? 12 : singleAvatar ? 4 : 0,
|
||||||
|
right: 4,
|
||||||
|
},
|
||||||
|
|
||||||
|
rightToggle: {
|
||||||
|
position: 'absolute',
|
||||||
|
display: 'block',
|
||||||
|
width: 54,
|
||||||
|
top: twoLine ? 25 : singleAvatar ? 17 : 13,
|
||||||
|
right: 8,
|
||||||
|
},
|
||||||
|
|
||||||
|
secondaryText: {
|
||||||
|
fontSize: 14,
|
||||||
|
lineHeight: threeLine ? '18px' : '16px',
|
||||||
|
height: threeLine ? 36 : 16,
|
||||||
|
margin: 0,
|
||||||
|
marginTop: 4,
|
||||||
|
color: Typography.textLightBlack,
|
||||||
|
|
||||||
|
//needed for 2 and 3 line ellipsis
|
||||||
|
overflow: 'hidden',
|
||||||
|
textOverflow: 'ellipsis',
|
||||||
|
whiteSpace: threeLine ? null : 'nowrap',
|
||||||
|
display: threeLine ? '-webkit-box' : null,
|
||||||
|
WebkitLineClamp: threeLine ? 2 : null,
|
||||||
|
WebkitBoxOrient: threeLine ? 'vertical' : null,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let contentChildren = [children];
|
||||||
|
|
||||||
|
if (leftIcon) {
|
||||||
|
this._pushElement(
|
||||||
|
contentChildren,
|
||||||
|
leftIcon,
|
||||||
|
this.mergeStyles(styles.icons, styles.leftIcon)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rightIcon) {
|
||||||
|
this._pushElement(
|
||||||
|
contentChildren,
|
||||||
|
rightIcon,
|
||||||
|
this.mergeStyles(styles.icons, styles.rightIcon)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (leftAvatar) {
|
||||||
|
this._pushElement(
|
||||||
|
contentChildren,
|
||||||
|
leftAvatar,
|
||||||
|
this.mergeStyles(styles.avatars, styles.leftAvatar)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rightAvatar) {
|
||||||
|
this._pushElement(
|
||||||
|
contentChildren,
|
||||||
|
rightAvatar,
|
||||||
|
this.mergeStyles(styles.avatars, styles.rightAvatar)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (leftCheckbox) {
|
||||||
|
this._pushElement(
|
||||||
|
contentChildren,
|
||||||
|
leftCheckbox,
|
||||||
|
this.mergeStyles(styles.leftCheckbox)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//RightIconButtonElement
|
||||||
|
const hasNestListItems = nestedItems.length;
|
||||||
|
const hasRightElement = rightAvatar || rightIcon || rightIconButton || rightToggle;
|
||||||
|
const needsNestedIndicator = hasNestListItems && autoGenerateNestedIndicator && !hasRightElement;
|
||||||
|
|
||||||
|
if (rightIconButton || needsNestedIndicator) {
|
||||||
|
let rightIconButtonElement = rightIconButton;
|
||||||
|
let rightIconButtonHandlers = {
|
||||||
|
onKeyboardFocus: this._handleRightIconButtonKeyboardFocus,
|
||||||
|
onMouseEnter: this._handleRightIconButtonMouseEnter,
|
||||||
|
onMouseLeave: this._handleRightIconButtonMouseLeave,
|
||||||
|
onTouchTap: this._handleRightIconButtonTouchTap,
|
||||||
|
onMouseDown: this._handleRightIconButtonMouseUp,
|
||||||
|
onMouseUp: this._handleRightIconButtonMouseUp,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create a nested list indicator icon if we don't have an icon on the right
|
||||||
|
if (needsNestedIndicator) {
|
||||||
|
rightIconButtonElement = this.state.open ?
|
||||||
|
<IconButton><OpenIcon /></IconButton> :
|
||||||
|
<IconButton><CloseIcon /></IconButton>;
|
||||||
|
rightIconButtonHandlers.onTouchTap = this._handleNestedListToggle;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._pushElement(
|
||||||
|
contentChildren,
|
||||||
|
rightIconButtonElement,
|
||||||
|
this.mergeStyles(styles.rightIconButton),
|
||||||
|
rightIconButtonHandlers
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rightToggle) {
|
||||||
|
this._pushElement(
|
||||||
|
contentChildren,
|
||||||
|
rightToggle,
|
||||||
|
this.mergeStyles(styles.rightToggle)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (primaryText) {
|
||||||
|
const secondaryTextElement = this._createTextElement(
|
||||||
|
styles.primaryText,
|
||||||
|
primaryText,
|
||||||
|
'primaryText'
|
||||||
|
);
|
||||||
|
contentChildren.push(secondaryTextElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (secondaryText) {
|
||||||
|
const secondaryTextElement = this._createTextElement(
|
||||||
|
styles.secondaryText,
|
||||||
|
secondaryText,
|
||||||
|
'secondaryText'
|
||||||
|
);
|
||||||
|
contentChildren.push(secondaryTextElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
const nestedList = nestedItems.length ? (
|
||||||
|
<NestedList nestedLevel={nestedLevel + 1} open={this.state.open} style={nestedListStyle}>
|
||||||
|
{nestedItems}
|
||||||
|
</NestedList>
|
||||||
|
) : undefined;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{
|
||||||
|
hasCheckbox ? this._createLabelElement(styles, contentChildren, other) :
|
||||||
|
disabled ? this._createDisabledElement(styles, contentChildren, other) : (
|
||||||
|
<EnhancedButton
|
||||||
|
{...other}
|
||||||
|
disabled={disabled}
|
||||||
|
disableKeyboardFocus={disableKeyboardFocus || this.state.rightIconButtonKeyboardFocused}
|
||||||
|
linkButton={true}
|
||||||
|
onKeyboardFocus={this._handleKeyboardFocus}
|
||||||
|
onMouseLeave={this._handleMouseLeave}
|
||||||
|
onMouseEnter={this._handleMouseEnter}
|
||||||
|
onTouchStart={this._handleTouchStart}
|
||||||
|
onTouchTap={primaryTogglesNestedList ? this._handleNestedListToggle : onTouchTap}
|
||||||
|
ref="enhancedButton"
|
||||||
|
style={this.mergeStyles(styles.root, style)}
|
||||||
|
>
|
||||||
|
<div style={this.prepareStyles(styles.innerDiv, innerDivStyle)}>
|
||||||
|
{contentChildren}
|
||||||
|
</div>
|
||||||
|
</EnhancedButton>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
{nestedList}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
export default Item;
|
||||||
|
|
||||||
|
|
@ -15,7 +15,7 @@ import Folder from 'material-ui/lib/svg-icons/file/folder'
|
||||||
import Edit from 'material-ui/lib/svg-icons/editor/mode-edit'
|
import Edit from 'material-ui/lib/svg-icons/editor/mode-edit'
|
||||||
import Delete from 'material-ui/lib/svg-icons/action/delete'
|
import Delete from 'material-ui/lib/svg-icons/action/delete'
|
||||||
import Divider from 'material-ui/lib/divider'
|
import Divider from 'material-ui/lib/divider'
|
||||||
import { SelectableContainerEnhance } from '../enhance/SelectableEnhance'
|
import SelectableList from 'SelectableList'
|
||||||
|
|
||||||
import uuid from 'node-uuid'
|
import uuid from 'node-uuid'
|
||||||
import path from 'path-extra'
|
import path from 'path-extra'
|
||||||
|
|
@ -64,36 +64,6 @@ const {
|
||||||
LeftNav,
|
LeftNav,
|
||||||
Paper} = mui
|
Paper} = mui
|
||||||
|
|
||||||
let SelectableList = SelectableContainerEnhance(List)
|
|
||||||
|
|
||||||
function wrapState(ComposedComponent) {
|
|
||||||
const StateWrapper = React.createClass({
|
|
||||||
getInitialState() {
|
|
||||||
return {selectedIndex: -1};
|
|
||||||
},
|
|
||||||
setIndex(i, func){
|
|
||||||
this.setState({
|
|
||||||
selectedIndex: i,
|
|
||||||
}, func);
|
|
||||||
},
|
|
||||||
handleUpdateSelectedIndex(e, index) {
|
|
||||||
this.setIndex(index);
|
|
||||||
},
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<ComposedComponent
|
|
||||||
{...this.props}
|
|
||||||
{...this.state}
|
|
||||||
valueLink={{value: this.state.selectedIndex, requestChange: this.handleUpdateSelectedIndex}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return StateWrapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
SelectableList = wrapState(SelectableList)
|
|
||||||
|
|
||||||
const DefaultRawTheme = Styles.LightRawTheme
|
const DefaultRawTheme = Styles.LightRawTheme
|
||||||
|
|
||||||
export default class LibraryNav extends React.Component {
|
export default class LibraryNav extends React.Component {
|
||||||
|
|
@ -432,7 +402,12 @@ export default class LibraryNav extends React.Component {
|
||||||
render(){
|
render(){
|
||||||
return (
|
return (
|
||||||
<div id={this.props.id} className={this.props.className+" leftnav"} open={this.state.open}>
|
<div id={this.props.id} className={this.props.className+" leftnav"} open={this.state.open}>
|
||||||
<SelectableList ref='mainList' className="list" id="main-nav" subheader="Library">
|
<SelectableList
|
||||||
|
ref='mainList'
|
||||||
|
className="list"
|
||||||
|
id="main-nav"
|
||||||
|
selectedItemStyle={{backgroundColor: "#C8C8C8"}}
|
||||||
|
subheader="Library">
|
||||||
{this.state.navItems.map((item, i) => {
|
{this.state.navItems.map((item, i) => {
|
||||||
return <ListItem
|
return <ListItem
|
||||||
primaryText={item.name}
|
primaryText={item.name}
|
||||||
|
|
@ -445,7 +420,12 @@ export default class LibraryNav extends React.Component {
|
||||||
})}
|
})}
|
||||||
</SelectableList>
|
</SelectableList>
|
||||||
<Divider />
|
<Divider />
|
||||||
<SelectableList id="nblist" className="list" ref='notebookList' subheader={<div>
|
<SelectableList
|
||||||
|
id="nblist"
|
||||||
|
className="list"
|
||||||
|
ref='notebookList'
|
||||||
|
selectedItemStyle={{backgroundColor: "#C8C8C8"}}
|
||||||
|
subheader={<div>
|
||||||
<div className="inline">NoteBooks</div>
|
<div className="inline">NoteBooks</div>
|
||||||
<IconButton
|
<IconButton
|
||||||
onTouchTap={this.addNotebookTapped}
|
onTouchTap={this.addNotebookTapped}
|
||||||
|
|
|
||||||
35
app/components/SelectableList.jsx
Normal file
35
app/components/SelectableList.jsx
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
import styles from 'material-ui/lib/styles'
|
||||||
|
import List from 'material-ui/lib/lists/list'
|
||||||
|
import { SelectableContainerEnhance } from '../enhance/SelectableEnhance'
|
||||||
|
|
||||||
|
let SelectableList = SelectableContainerEnhance(List)
|
||||||
|
|
||||||
|
function wrapState(ComposedComponent) {
|
||||||
|
const StateWrapper = React.createClass({
|
||||||
|
getInitialState() {
|
||||||
|
return {selectedIndex: -1};
|
||||||
|
},
|
||||||
|
setIndex(i, func){
|
||||||
|
this.setState({
|
||||||
|
selectedIndex: i,
|
||||||
|
}, func);
|
||||||
|
},
|
||||||
|
handleUpdateSelectedIndex(e, index) {
|
||||||
|
this.setIndex(index);
|
||||||
|
},
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<ComposedComponent
|
||||||
|
{...this.props}
|
||||||
|
{...this.state}
|
||||||
|
valueLink={{value: this.state.selectedIndex, requestChange: this.handleUpdateSelectedIndex}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return StateWrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SelectableList = wrapState(SelectableList)
|
||||||
12
style.css
12
style.css
|
|
@ -12,6 +12,14 @@ body, html{
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#search-bar {
|
||||||
|
padding-top: 0px !important;
|
||||||
|
padding-bottom: 0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list {
|
||||||
|
background-color: #EFEFEF !important;
|
||||||
|
}
|
||||||
.list > div:first-child{
|
.list > div:first-child{
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
}
|
}
|
||||||
|
|
@ -25,9 +33,13 @@ body, html{
|
||||||
.right{
|
.right{
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
#entry-list{
|
||||||
|
padding-top: 0px !important;
|
||||||
|
}
|
||||||
#entry-selector{
|
#entry-selector{
|
||||||
border-right: solid 1px #d9d9d9;
|
border-right: solid 1px #d9d9d9;
|
||||||
min-width: 250px;
|
min-width: 250px;
|
||||||
|
max-width: 390px !important;
|
||||||
}
|
}
|
||||||
#library-nav{
|
#library-nav{
|
||||||
border-right: solid 1px #d9d9d9;
|
border-right: solid 1px #d9d9d9;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue