Add/Remove link
This commit is contained in:
parent
72b8e14f07
commit
5fa551dcb2
@ -78,6 +78,6 @@
|
|||||||
"react-portal": "^2.2.1",
|
"react-portal": "^2.2.1",
|
||||||
"selection-position": "^1.0.0",
|
"selection-position": "^1.0.0",
|
||||||
"slate": "^0.11.0",
|
"slate": "^0.11.0",
|
||||||
"slate-markdown-serializer": "^0.1.3"
|
"slate-markdown-serializer": "^0.1.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@ class MarkdownControl extends React.Component {
|
|||||||
this.handleDocumentChange = this.handleDocumentChange.bind(this);
|
this.handleDocumentChange = this.handleDocumentChange.bind(this);
|
||||||
this.handleMarkStyleClick = this.handleMarkStyleClick.bind(this);
|
this.handleMarkStyleClick = this.handleMarkStyleClick.bind(this);
|
||||||
this.handleBlockStyleClick = this.handleBlockStyleClick.bind(this);
|
this.handleBlockStyleClick = this.handleBlockStyleClick.bind(this);
|
||||||
|
this.handleInlineClick = this.handleInlineClick.bind(this);
|
||||||
this.handleBlockTypeClick = this.handleBlockTypeClick.bind(this);
|
this.handleBlockTypeClick = this.handleBlockTypeClick.bind(this);
|
||||||
this.handleKeyDown = this.handleKeyDown.bind(this);
|
this.handleKeyDown = this.handleKeyDown.bind(this);
|
||||||
this.calculateMenuPositions = this.calculateMenuPositions.bind(this);
|
this.calculateMenuPositions = this.calculateMenuPositions.bind(this);
|
||||||
@ -150,6 +151,42 @@ class MarkdownControl extends React.Component {
|
|||||||
this.setState({ state });
|
this.setState({ state });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When clicking a link, if the selection has a link in it, remove the link.
|
||||||
|
* Otherwise, add a new link with an href and text.
|
||||||
|
*
|
||||||
|
* @param {Event} e
|
||||||
|
*/
|
||||||
|
|
||||||
|
handleInlineClick(type, isActive) {
|
||||||
|
let { state } = this.state;
|
||||||
|
|
||||||
|
if (type === 'link') {
|
||||||
|
if (!state.isExpanded) return;
|
||||||
|
|
||||||
|
if (isActive) {
|
||||||
|
state = state
|
||||||
|
.transform()
|
||||||
|
.unwrapInline('link')
|
||||||
|
.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
const href = window.prompt('Enter the URL of the link:', 'http://www.');
|
||||||
|
state = state
|
||||||
|
.transform()
|
||||||
|
.wrapInline({
|
||||||
|
type: 'link',
|
||||||
|
data: { href }
|
||||||
|
})
|
||||||
|
.collapseToEnd()
|
||||||
|
.apply();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.setState({ state });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
handleBlockTypeClick(type) {
|
handleBlockTypeClick(type) {
|
||||||
let { state } = this.state;
|
let { state } = this.state;
|
||||||
|
|
||||||
@ -208,7 +245,9 @@ class MarkdownControl extends React.Component {
|
|||||||
position={this.menuPositions.stylesMenu}
|
position={this.menuPositions.stylesMenu}
|
||||||
marks={this.state.state.marks}
|
marks={this.state.state.marks}
|
||||||
blocks={this.state.state.blocks}
|
blocks={this.state.state.blocks}
|
||||||
|
inlines={this.state.state.inlines}
|
||||||
onClickMark={this.handleMarkStyleClick}
|
onClickMark={this.handleMarkStyleClick}
|
||||||
|
onClickInline={this.handleInlineClick}
|
||||||
onClickBlock={this.handleBlockStyleClick}
|
onClickBlock={this.handleBlockStyleClick}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -16,8 +16,10 @@ export default class StylesMenu extends Component {
|
|||||||
this.hasBlock = this.hasBlock.bind(this);
|
this.hasBlock = this.hasBlock.bind(this);
|
||||||
this.renderMarkButton = this.renderMarkButton.bind(this);
|
this.renderMarkButton = this.renderMarkButton.bind(this);
|
||||||
this.renderBlockButton = this.renderBlockButton.bind(this);
|
this.renderBlockButton = this.renderBlockButton.bind(this);
|
||||||
|
this.renderLinkButton = this.renderLinkButton.bind(this);
|
||||||
this.updateMenuPosition = this.updateMenuPosition.bind(this);
|
this.updateMenuPosition = this.updateMenuPosition.bind(this);
|
||||||
this.handleMarkClick = this.handleMarkClick.bind(this);
|
this.handleMarkClick = this.handleMarkClick.bind(this);
|
||||||
|
this.handleInlineClick = this.handleInlineClick.bind(this);
|
||||||
this.handleBlockClick = this.handleBlockClick.bind(this);
|
this.handleBlockClick = this.handleBlockClick.bind(this);
|
||||||
this.handleOpen = this.handleOpen.bind(this);
|
this.handleOpen = this.handleOpen.bind(this);
|
||||||
}
|
}
|
||||||
@ -54,6 +56,10 @@ export default class StylesMenu extends Component {
|
|||||||
const { blocks } = this.props;
|
const { blocks } = this.props;
|
||||||
return blocks.some(node => node.type == type);
|
return blocks.some(node => node.type == type);
|
||||||
}
|
}
|
||||||
|
hasLinks(type) {
|
||||||
|
const { inlines } = this.props;
|
||||||
|
return inlines.some(inline => inline.type == 'link');
|
||||||
|
}
|
||||||
|
|
||||||
handleMarkClick(e, type) {
|
handleMarkClick(e, type) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@ -70,6 +76,21 @@ export default class StylesMenu extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleInlineClick(e, type, isActive) {
|
||||||
|
e.preventDefault();
|
||||||
|
this.props.onClickInline(type, isActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderLinkButton() {
|
||||||
|
const isActive = this.hasLinks();
|
||||||
|
const onMouseDown = e => this.handleInlineClick(e, 'link', isActive);
|
||||||
|
return (
|
||||||
|
<span className={styles.button} onMouseDown={onMouseDown} data-active={isActive}>
|
||||||
|
<Icon type="link"/>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
handleBlockClick(e, type) {
|
handleBlockClick(e, type) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const isActive = this.hasBlock(type);
|
const isActive = this.hasBlock(type);
|
||||||
@ -103,6 +124,7 @@ export default class StylesMenu extends Component {
|
|||||||
{this.renderMarkButton('bold', 'bold')}
|
{this.renderMarkButton('bold', 'bold')}
|
||||||
{this.renderMarkButton('italic', 'italic')}
|
{this.renderMarkButton('italic', 'italic')}
|
||||||
{this.renderMarkButton('code', 'code')}
|
{this.renderMarkButton('code', 'code')}
|
||||||
|
{this.renderLinkButton()}
|
||||||
{this.renderBlockButton('heading1', 'h1')}
|
{this.renderBlockButton('heading1', 'h1')}
|
||||||
{this.renderBlockButton('heading2', 'h2')}
|
{this.renderBlockButton('heading2', 'h2')}
|
||||||
{this.renderBlockButton('block-quote', 'quote-left')}
|
{this.renderBlockButton('block-quote', 'quote-left')}
|
||||||
@ -122,6 +144,8 @@ StylesMenu.propTypes = {
|
|||||||
}),
|
}),
|
||||||
marks: PropTypes.object.isRequired,
|
marks: PropTypes.object.isRequired,
|
||||||
blocks: PropTypes.object.isRequired,
|
blocks: PropTypes.object.isRequired,
|
||||||
|
inlines: PropTypes.object.isRequired,
|
||||||
onClickBlock: PropTypes.func.isRequired,
|
onClickBlock: PropTypes.func.isRequired,
|
||||||
onClickMark: PropTypes.func.isRequired
|
onClickMark: PropTypes.func.isRequired,
|
||||||
|
onClickInline: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Block from './Block';
|
import Block from './Block';
|
||||||
import BlockStatic from './BlockStatic';
|
import BlockStatic from './BlockStatic';
|
||||||
import { Icon } from '../../UI';
|
|
||||||
|
|
||||||
/* eslint react/prop-types: 0, react/no-multi-comp: 0 */
|
/* eslint react/prop-types: 0, react/no-multi-comp: 0 */
|
||||||
|
|
||||||
@ -24,7 +23,7 @@ export const NODES = {
|
|||||||
'link': (props) => {
|
'link': (props) => {
|
||||||
const { data } = props.node;
|
const { data } = props.node;
|
||||||
const href = data.get('href');
|
const href = data.get('href');
|
||||||
return <span><a {...props.attributes} href={href}>{props.children}</a><Icon type="link"/></span>;
|
return <a {...props.attributes} href={href}>{props.children}</a>;
|
||||||
},
|
},
|
||||||
'image': (props) => {
|
'image': (props) => {
|
||||||
const { node } = props;
|
const { node } = props;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user