diff --git a/conf/specs.js b/conf/specs.js
index e930720..cceb8c0 100644
--- a/conf/specs.js
+++ b/conf/specs.js
@@ -1 +1,8 @@
-global.STORYSHOP_API_URI = 'http://nonexistent';
\ No newline at end of file
+global.STORYSHOP_API_URI = 'http://nonexistent';
+global.window = {
+ navigator: {
+ userAgent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36',
+ }
+};
+
+require.extensions['.css'] = function() {};
diff --git a/conf/storybook/webpack.config.js b/conf/storybook/webpack.config.js
index 370d4ab..7dde8c8 100644
--- a/conf/storybook/webpack.config.js
+++ b/conf/storybook/webpack.config.js
@@ -6,5 +6,15 @@ module.exports = {
path.resolve( './src' ),
],
},
+ module: {
+ loaders: [
+ {
+ test: /plugin\.css$/,
+ loaders: [
+ 'style', 'css',
+ ],
+ },
+ ],
+ }
};
diff --git a/package.json b/package.json
index eb950ae..b80f875 100644
--- a/package.json
+++ b/package.json
@@ -60,9 +60,11 @@
"babel-runtime": "^6.5.0",
"css-loader": "^0.23.1",
"debug": "^2.2.0",
- "draft-js": "0.9.0",
- "draft-js-mention-plugin": "1.1.0",
- "draft-js-plugins-editor": "1.1.0",
+ "draft-js": "0.9.1",
+ "draft-js-linkify-plugin": "^2.0.0-beta5",
+ "draft-js-mention-plugin": "2.0.0-beta5",
+ "draft-js-plugins-editor": "2.0.0-beta5",
+ "draft-js-undo-plugin": "^2.0.0-beta5",
"enzyme": "^2.4.1",
"express": "^4.13.4",
"falcor": "^0.1.16",
diff --git a/src/components/reference-editor/index.js b/src/components/reference-editor/index.js
new file mode 100644
index 0000000..dccfcc8
--- /dev/null
+++ b/src/components/reference-editor/index.js
@@ -0,0 +1,54 @@
+import { PropTypes } from 'react';
+import reactStamp from 'react-stamp';
+
+import EditorFactory from 'components/editor';
+
+import createMentionPlugin, { defaultSuggestionsFilter } from 'draft-js-mention-plugin';
+import createUndoPlugin from 'draft-js-undo-plugin';
+import createLinkifyPlugin from 'draft-js-linkify-plugin';
+
+import 'draft-js-mention-plugin/lib/plugin.css';
+import 'draft-js-undo-plugin/lib/plugin.css';
+import 'draft-js-linkify-plugin/lib/plugin.css';
+
+import MentionComponent from './mention-text';
+import SuggestionsFactory from './suggestions';
+
+export const mentionPlugin = createMentionPlugin({ mentionComponent: MentionComponent });
+export const undoPlugin = createUndoPlugin();
+export const linkifyPlugin = createLinkifyPlugin();
+
+const { MentionSuggestions } = mentionPlugin;
+const Suggestions = SuggestionsFactory(MentionSuggestions);
+
+export default (React, ...behaviours) => {
+ const Editor = EditorFactory(React);
+ return reactStamp(React).compose({
+ propTypes: {
+ onSearchChange: PropTypes.func,
+ searchSuggestions: PropTypes.arrayOf(PropTypes.shape({
+ type: PropTypes.oneOf(['character', 'element']).isRequired,
+ _id: PropTypes.string.isRequired,
+ name: PropTypes.string.isRequired,
+ link: PropTypes.string.isRequired,
+ avatar: PropTypes.string.isRequired,
+ })).isRequired,
+ },
+
+ render() {
+ const { onSearchChange, searchSuggestions, plugins = [], ...rest } = this.props;
+ return (
+
+
+
+
+ );
+ },
+ });
+};
diff --git a/src/components/reference-editor/mention-text.js b/src/components/reference-editor/mention-text.js
new file mode 100644
index 0000000..bdfa5c9
--- /dev/null
+++ b/src/components/reference-editor/mention-text.js
@@ -0,0 +1,18 @@
+import React from 'react';
+import { Link } from 'react-router';
+import { cyan700, green700 } from 'material-ui/lib/styles/colors';
+
+const MentionComponent = ({ mention, className, mentionPrefix, children }) => (
+
+ {mentionPrefix}{children}
+
+);
+
+export default MentionComponent;
diff --git a/src/components/reference-editor/spec.js b/src/components/reference-editor/spec.js
new file mode 100644
index 0000000..1021a4c
--- /dev/null
+++ b/src/components/reference-editor/spec.js
@@ -0,0 +1,41 @@
+import React from 'react';
+import test from 'tape';
+import { shallow } from 'enzyme';
+import spy, { createSpy } from '../../utils/spy';
+
+import EditorFactory, { mentionPlugin, linkifyPlugin, undoPlugin } from './';
+import UpstreamEditorFactory from 'components/editor';
+
+const Editor = EditorFactory(React);
+const UpstreamEditor = UpstreamEditorFactory(React);
+
+test('ReferenceEditor', t => {
+ let instance, actual, expected;
+
+ const content = {};
+
+ instance = shallow();
+
+ {
+ const upstream = instance.children().at(0);
+ t.ok(upstream, 'should render the editor');
+
+ const plugins = upstream.props().plugins;
+ t.notEquals(plugins.indexOf(mentionPlugin), -1, 'should manage mention plugin');
+ t.notEquals(plugins.indexOf(undoPlugin), -1, 'should manage undo plugin');
+ t.notEquals(plugins.indexOf(linkifyPlugin), -1, 'should manage linkify plugin');
+ }
+
+ {
+ const onSearchChange = () => {};
+ const searchSuggestions = [];
+ instance = shallow();
+ const suggestions = instance.children().at(1);
+
+ t.ok(suggestions, 'renders suggestion list');
+ t.equals(suggestions.props().onSearchChange, onSearchChange, 'passed search callback down');
+ t.equals(suggestions.props().suggestions, searchSuggestions, 'passes suggestion list down');
+ }
+
+ t.end();
+});
diff --git a/src/components/reference-editor/story.js b/src/components/reference-editor/story.js
new file mode 100644
index 0000000..75627e1
--- /dev/null
+++ b/src/components/reference-editor/story.js
@@ -0,0 +1,41 @@
+import React from 'react';
+import { storiesOf, action } from '@kadira/storybook';
+
+import EditorFactory from './';
+
+const Editor = EditorFactory(React);
+
+import {
+ ContentState,
+ ContentBlock,
+ CharacterMetadata,
+ convertToRaw,
+} from 'draft-js';
+import { is, fromJS, List, Repeat } from 'immutable';
+
+const genContent = (text) => {
+ const contentState = ContentState.createFromBlockArray([
+ new ContentBlock({
+ key: 'abc',
+ type: 'unstyled',
+ text,
+ characterList: List(Repeat(CharacterMetadata.EMPTY, text.length))
+ }),
+ ]);
+ return convertToRaw(contentState);
+};
+
+storiesOf('Reference Editor', module)
+ .add('default', () => {
+ const initialContent = genContent('Here we go');
+ return (
+
+ );
+ });
diff --git a/src/components/reference-editor/suggestions/entry.js b/src/components/reference-editor/suggestions/entry.js
new file mode 100644
index 0000000..e40d522
--- /dev/null
+++ b/src/components/reference-editor/suggestions/entry.js
@@ -0,0 +1,14 @@
+import React from 'react';
+import ListItem from 'material-ui/lib/lists/list-item';
+import Avatar from 'material-ui/lib/avatar';
+
+const EntryComponent = ({ mention, className, ...props }) => (
+ }
+ {...props}
+ >
+ {mention.get('name')}
+
+);
+
+export default EntryComponent;
diff --git a/src/components/reference-editor/suggestions/index.js b/src/components/reference-editor/suggestions/index.js
new file mode 100644
index 0000000..b07a28a
--- /dev/null
+++ b/src/components/reference-editor/suggestions/index.js
@@ -0,0 +1,14 @@
+import React from 'react';
+import { fromJS } from 'immutable';
+import EntryComponent from './entry';
+
+export default function (MentionSuggestions) {
+ return ({ suggestions, ...rest }) => (
+
+ );
+}