Small refactor

This commit is contained in:
Cássio Zen 2016-08-03 10:30:42 -03:00
parent 08d5110d3a
commit a16a8ff20d
2 changed files with 68 additions and 68 deletions

View File

@ -1,62 +1,16 @@
import React, { PropTypes } from 'react'; import React, { PropTypes } from 'react';
import { Editor, Plain } from 'slate'; import { Editor, Plain } from 'slate';
import Markdown from 'slate-markdown-serializer';
import Block from './MarkdownControlElements/Block';
import Portal from 'react-portal'; import Portal from 'react-portal';
import position from 'selection-position'; import position from 'selection-position';
import { Icon } from '../UI'; import Markdown from 'slate-markdown-serializer';
import { DEFAULT_NODE, NODES, MARKS } from './MarkdownControlElements/localRenderers';
import styles from './MarkdownControl.css'; import styles from './MarkdownControl.css';
const markdown = new Markdown(); const markdown = new Markdown();
/*
/**
* Slate Render Configuration * Slate Render Configuration
*/ */
// Define the default node type.
const DEFAULT_NODE = 'paragraph';
// Local node renderers.
const NODES = {
'block-quote': (props) => <Block type='blockquote' {...props.attributes}>{props.children}</Block>,
'bulleted-list': props => <Block type='Unordered List'><ul {...props.attributes}>{props.children}</ul></Block>,
'heading1': props => <Block type='Heading1' {...props.attributes}>{props.children}</Block>,
'heading2': props => <Block type='Heading2' {...props.attributes}>{props.children}</Block>,
'heading3': props => <Block type='Heading2' {...props.attributes}>{props.children}</Block>,
'heading4': props => <Block type='Heading2' {...props.attributes}>{props.children}</Block>,
'heading5': props => <Block type='Heading2' {...props.attributes}>{props.children}</Block>,
'heading6': props => <Block type='Heading2' {...props.attributes}>{props.children}</Block>,
'list-item': props => <li {...props.attributes}>{props.children}</li>,
'paragraph': props => <Block type='Paragraph' {...props.attributes}>{props.children}</Block>,
'link': (props) => {
const { data } = props.node;
const href = data.get('href');
return <span><a {...props.attributes} href={href}>{props.children}</a><Icon type="link"/></span>;
},
'image': (props) => {
const { node, state } = props;
const src = node.data.get('src');
return (
<img {...props.attributes} src={src} />
);
}
};
// Local mark renderers.
const MARKS = {
bold: {
fontWeight: 'bold'
},
italic: {
fontStyle: 'italic'
},
code: {
fontFamily: 'monospace',
backgroundColor: '#eee',
padding: '3px',
borderRadius: '4px'
}
};
class MarkdownControl extends React.Component { class MarkdownControl extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
@ -77,22 +31,22 @@ class MarkdownControl extends React.Component {
this.renderBlockButton = this.renderBlockButton.bind(this); this.renderBlockButton = this.renderBlockButton.bind(this);
this.renderNode = this.renderNode.bind(this); this.renderNode = this.renderNode.bind(this);
this.renderMark = this.renderMark.bind(this); this.renderMark = this.renderMark.bind(this);
this.onOpen = this.onOpen.bind(this); this.handleOpen = this.handleOpen.bind(this);
this.updateMenu = this.updateMenu.bind(this); this.updateMenu = this.updateMenu.bind(this);
} }
/* /**
* On update, update the menu. * On update, update the menu.
*/ */
componentDidMount() { componentDidMount() {
this.updateMenu(); this.updateMenu();
} }
componentDidUpdate() { componentDidUpdate() {
this.updateMenu(); this.updateMenu();
} }
/**
/*
* Used to set toolbar buttons to active state * Used to set toolbar buttons to active state
*/ */
hasMark(type) { hasMark(type) {
@ -104,7 +58,7 @@ class MarkdownControl extends React.Component {
return state.blocks.some(node => node.type == type); return state.blocks.some(node => node.type == type);
} }
/* /**
* Slate keeps track of selections, scroll position etc. * Slate keeps track of selections, scroll position etc.
* So, onChange gets dispatched on every interaction (click, arrows, everything...) * So, onChange gets dispatched on every interaction (click, arrows, everything...)
* It also have an onDocumentChange, that get's dispached only when the actual * It also have an onDocumentChange, that get's dispached only when the actual
@ -122,8 +76,7 @@ class MarkdownControl extends React.Component {
this.props.onChange(markdown.serialize(state)); this.props.onChange(markdown.serialize(state));
} }
/**
/*
* Toggle marks / blocks when button is clicked * Toggle marks / blocks when button is clicked
*/ */
onClickMark(e, type) { onClickMark(e, type) {
@ -200,22 +153,21 @@ class MarkdownControl extends React.Component {
this.setState({ state }); this.setState({ state });
} }
/* /**
* When the portal opens, cache the menu element. * When the portal opens, cache the menu element.
*/ */
onOpen(portal) { handleOpen(portal) {
this.setState({ menu: portal.firstChild }); this.setState({ menu: portal.firstChild });
} }
renderMenu() { renderMenu() {
const { state } = this.state const { state } = this.state;
const isOpen = state.isExpanded && state.isFocused const isOpen = state.isExpanded && state.isFocused;
return ( return (
<Portal isOpened onOpen={this.onOpen}> <Portal isOpened={isOpen} onOpen={this.handleOpen}>
<div className={`${styles.menu} ${styles.hoverMenu}`}> <div className={`${styles.menu} ${styles.hoverMenu}`}>
{this.renderMarkButton('bold', 'b')} {this.renderMarkButton('bold', 'b')}
{this.renderMarkButton('italic', 'i')} {this.renderMarkButton('italic', 'i')}
{this.renderMarkButton('underlined', 'u')}
{this.renderMarkButton('code', 'code')} {this.renderMarkButton('code', 'code')}
{this.renderBlockButton('heading1', 'h1')} {this.renderBlockButton('heading1', 'h1')}
{this.renderBlockButton('heading2', 'h2')} {this.renderBlockButton('heading2', 'h2')}
@ -223,7 +175,7 @@ class MarkdownControl extends React.Component {
{this.renderBlockButton('bulleted-list', 'ul')} {this.renderBlockButton('bulleted-list', 'ul')}
</div> </div>
</Portal> </Portal>
) );
} }
renderMarkButton(type, icon) { renderMarkButton(type, icon) {
@ -248,7 +200,7 @@ class MarkdownControl extends React.Component {
); );
} }
/* /**
* Return renderers for Slate * Return renderers for Slate
*/ */
renderNode(node) { renderNode(node) {
@ -258,10 +210,9 @@ class MarkdownControl extends React.Component {
return MARKS[mark.type]; return MARKS[mark.type];
} }
/* /**
* Update the menu's absolute position. * Update the menu's absolute position.
*/ */
updateMenu() { updateMenu() {
const { menu, state } = this.state; const { menu, state } = this.state;
if (!menu) return; if (!menu) return;
@ -277,7 +228,6 @@ class MarkdownControl extends React.Component {
menu.style.left = `${rect.left + window.scrollX - menu.offsetWidth / 2 + rect.width / 2}px`; menu.style.left = `${rect.left + window.scrollX - menu.offsetWidth / 2 + rect.width / 2}px`;
} }
render() { render() {
return ( return (
<div> <div>

View File

@ -0,0 +1,50 @@
import React from 'react';
import Block from './Block';
import { Icon } from '../../UI';
/* eslint react/prop-types: 0, react/no-multi-comp: 0 */
// Define the default node type.
export const DEFAULT_NODE = 'paragraph';
// Local node renderers.
export const NODES = {
'block-quote': (props) => <Block type='blockquote' {...props.attributes}>{props.children}</Block>,
'bulleted-list': props => <Block type='Unordered List'><ul {...props.attributes}>{props.children}</ul></Block>,
'heading1': props => <Block type='Heading1' {...props.attributes}>{props.children}</Block>,
'heading2': props => <Block type='Heading2' {...props.attributes}>{props.children}</Block>,
'heading3': props => <Block type='Heading2' {...props.attributes}>{props.children}</Block>,
'heading4': props => <Block type='Heading2' {...props.attributes}>{props.children}</Block>,
'heading5': props => <Block type='Heading2' {...props.attributes}>{props.children}</Block>,
'heading6': props => <Block type='Heading2' {...props.attributes}>{props.children}</Block>,
'list-item': props => <li {...props.attributes}>{props.children}</li>,
'paragraph': props => <Block type='Paragraph' {...props.attributes}>{props.children}</Block>,
'link': (props) => {
const { data } = props.node;
const href = data.get('href');
return <span><a {...props.attributes} href={href}>{props.children}</a><Icon type="link"/></span>;
},
'image': (props) => {
const { node } = props;
const src = node.data.get('src');
return (
<img {...props.attributes} src={src} />
);
}
};
// Local mark renderers.
export const MARKS = {
bold: {
fontWeight: 'bold'
},
italic: {
fontStyle: 'italic'
},
code: {
fontFamily: 'monospace',
backgroundColor: '#eee',
padding: '3px',
borderRadius: '4px'
}
};