sort components into widgets and views
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
import React from 'react';
|
||||
|
||||
import Chip from './chip.jsx';
|
||||
|
||||
/* BEGIN ChipInput: group membership widget */
|
||||
export default class ChipInput extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
placeholder: props.chips ? '' : props.prompt,
|
||||
sortedChips: ChipInput.sortChips(props.chips, props.required),
|
||||
chipIndex: ChipInput.indexChips(props.chips),
|
||||
input: '',
|
||||
focused: false
|
||||
};
|
||||
|
||||
this.handleTextInput = this.handleTextInput.bind(this);
|
||||
this.removeChipAt = this.removeChipAt.bind(this);
|
||||
this.handleChipCancel = this.handleChipCancel.bind(this);
|
||||
this.handleFocusGained = this.handleFocusGained.bind(this);
|
||||
this.handleFocusLost = this.handleFocusLost.bind(this);
|
||||
this.handleKeyDown = this.handleKeyDown.bind(this);
|
||||
}
|
||||
|
||||
UNSAFE_componentWillReceiveProps(nextProps) {
|
||||
this.setState({
|
||||
sortedChips: ChipInput.sortChips(nextProps.chips, nextProps.required),
|
||||
chipIndex: ChipInput.indexChips(nextProps.chips)
|
||||
});
|
||||
if (nextProps.chips.length > this.props.chips.length) {
|
||||
// Chip added: clear input.
|
||||
this.setState({input: ''});
|
||||
}
|
||||
}
|
||||
|
||||
// Map chip index to user name
|
||||
static indexChips(chips) {
|
||||
var index = {};
|
||||
var count = 0;
|
||||
chips.map(function(item) {
|
||||
index[item.user] = count;
|
||||
count ++;
|
||||
});
|
||||
return index;
|
||||
}
|
||||
|
||||
// Have non-removable chips appear before all other chips.
|
||||
static sortChips(chips, keep) {
|
||||
var required = [];
|
||||
var normal = [];
|
||||
chips.map(function(item) {
|
||||
if (item.user === keep) {
|
||||
required.push(item);
|
||||
} else {
|
||||
normal.push(item);
|
||||
}
|
||||
});
|
||||
return required.concat(normal);
|
||||
}
|
||||
|
||||
handleTextInput(e) {
|
||||
this.setState({input: e.target.value});
|
||||
if (this.props.filterFunc) {
|
||||
this.props.filterFunc(e.target.value);
|
||||
}
|
||||
}
|
||||
|
||||
removeChipAt(idx) {
|
||||
var removed = this.state.sortedChips[idx];
|
||||
this.props.onChipRemoved(removed.user, this.state.chipIndex[removed.user]);
|
||||
}
|
||||
|
||||
handleChipCancel(item, idx) {
|
||||
this.removeChipAt(idx);
|
||||
}
|
||||
|
||||
handleFocusGained() {
|
||||
this.setState({focused: true});
|
||||
}
|
||||
|
||||
handleFocusLost() {
|
||||
this.setState({focused: false});
|
||||
if (this.props.onFocusLost) {
|
||||
this.props.onFocusLost(this.state.input);
|
||||
}
|
||||
}
|
||||
|
||||
handleKeyDown(e) {
|
||||
if (e.key === 'Backspace') {
|
||||
if (this.state.input.length == 0 && this.state.sortedChips.length > 0) {
|
||||
var at = this.state.sortedChips.length - 1;
|
||||
if (this.state.sortedChips[at].user !== this.props.required) {
|
||||
this.removeChipAt(at);
|
||||
}
|
||||
}
|
||||
} else if (e.key === 'Enter') {
|
||||
if (this.props.onEnter) {
|
||||
this.props.onEnter(this.state.input);
|
||||
}
|
||||
} else if (e.key === 'Escape') {
|
||||
if (this.props.onCancel) {
|
||||
this.props.onCancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
var chips = [];
|
||||
var count = 0;
|
||||
this.state.sortedChips.map((item) => {
|
||||
chips.push(
|
||||
<Chip
|
||||
onCancel={this.handleChipCancel}
|
||||
avatar={makeImageUrl(item.public ? item.public.photo : null)}
|
||||
title={item.public ? item.public.fn : undefined}
|
||||
noAvatar={this.props.avatarDisabled}
|
||||
topic={item.user}
|
||||
required={item.user === this.props.required}
|
||||
index={count}
|
||||
key={item.user} />
|
||||
);
|
||||
count++;
|
||||
});
|
||||
var className = "chip-input" + (this.state.focused ? ' focused' : '');
|
||||
return (
|
||||
<div className={className}>
|
||||
{chips}
|
||||
<input type="text"
|
||||
placeholder={this.state.placeholder}
|
||||
onChange={this.handleTextInput}
|
||||
onFocus={this.handleFocusGained}
|
||||
onBlur={this.handleFocusLost}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
value={this.state.input}
|
||||
autoFocus />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user