Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 159 additions & 0 deletions components/autocomplete.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
import React, { Component, Fragment } from "react";
import PropTypes from "prop-types";

class Autocomplete extends Component {
static propTypes = {
suggestions: PropTypes.instanceOf(Array)
};

static defaultProps = {
suggestions: []
};

constructor(props) {
super(props);

this.state = {
// The active selection's index
activeSuggestion: 0,
// The suggestions that match the user's input
filteredSuggestions: [],
// Whether or not the suggestion list is shown
showSuggestions: false,
// What the user has entered
userInput: ""
};
}

// Event fired when the input value is changed
onChange = e => {
const { suggestions } = this.props;
const userInput = e.currentTarget.value;

// Filter our suggestions that don't contain the user's input
const filteredSuggestions = suggestions.filter(
suggestion =>
suggestion.toLowerCase().indexOf(userInput.toLowerCase()) > -1
);

// Update the user input and filtered suggestions, reset the active
// suggestion and make sure the suggestions are shown
this.setState({
activeSuggestion: 0,
filteredSuggestions,
showSuggestions: true,
userInput: e.currentTarget.value
});
};

// Event fired when the user clicks on a suggestion
onClick = e => {
// Update the user input and reset the rest of the state
this.setState({
activeSuggestion: 0,
filteredSuggestions: [],
showSuggestions: false,
userInput: e.currentTarget.innerText
});
};

// Event fired when the user presses a key down
onKeyDown = e => {
const { activeSuggestion, filteredSuggestions } = this.state;

// User pressed the enter key, update the input and close the
// suggestions
if (e.keyCode === 13) {
this.setState({
activeSuggestion: 0,
showSuggestions: false,
userInput: filteredSuggestions[activeSuggestion]
});
}
// User pressed the up arrow, decrement the index
else if (e.keyCode === 38) {
if (activeSuggestion === 0) {
return;
}

this.setState({ activeSuggestion: activeSuggestion - 1 });
}
// User pressed the down arrow, increment the index
else if (e.keyCode === 40) {
if (activeSuggestion - 1 === filteredSuggestions.length) {
return;
}

this.setState({ activeSuggestion: activeSuggestion + 1 });
}
};

render() {
const {
onChange,
onClick,
onKeyDown,
state: {
activeSuggestion,
filteredSuggestions,
showSuggestions,
userInput
}
} = this;

let suggestionsListComponent;

if (showSuggestions && userInput) {
if (filteredSuggestions.length) {
suggestionsListComponent = (
<ul class="suggestions menu">
{filteredSuggestions.map((suggestion, index) => {
let className;

// Flag the active suggestion with a class
if (index === activeSuggestion) {
className = "suggestion-active";
}

return (
<li
className={className}
class="menu-item"
key={suggestion}
onClick={onClick}
>
<div class="tile">
<div class="tile-content">
{suggestion}
</div>
</div>
</li>
);
})}
</ul>
);
} else {
suggestionsListComponent = (
<div class="no-suggestions">
<em>No such category! A new category will be created</em>
</div>
);
}
}

return (
<Fragment>
<input
class="form-input"
type="text"
onChange={onChange}
onKeyDown={onKeyDown}
value={userInput}
/>
{suggestionsListComponent}
</Fragment>
);
}
}

export default Autocomplete;
37 changes: 37 additions & 0 deletions components/editor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Component } from 'react';
const isBrowser = typeof window !== 'undefined';
let RichTextEditor;
if (isBrowser) {
RichTextEditor = require('react-rte').default;
}

export default class Home extends Component {
state = {
value: RichTextEditor ? RichTextEditor.createEmptyValue() : ""
}

onChange = (value) => {
this.setState({ value });
if (this.props.onChange) {
// Send the changes up to the parent component as an HTML string.
// This is here to demonstrate using `.toString()` but in a real app it
// would be better to avoid generating a string on each change.
this.props.onChange(
value.toString('html')
);
}
};

render() {
return (
<div>
{RichTextEditor &&
<RichTextEditor
value={this.state.value}
onChange={this.onChange}
/>}
</div>

)
}
}
Loading