This repository has been archived on 2022-08-14. You can view files and clone it, but cannot push or open issues or pull requests.
outline/app/components/Editor/components/Toolbar/components/FormattingToolbar.js

113 lines
3.0 KiB
JavaScript

// @flow
import React, { Component } from 'react';
import styled from 'styled-components';
import { Editor } from 'slate-react';
import ToolbarButton from './ToolbarButton';
import BoldIcon from 'components/Icon/BoldIcon';
import CodeIcon from 'components/Icon/CodeIcon';
import Heading1Icon from 'components/Icon/Heading1Icon';
import Heading2Icon from 'components/Icon/Heading2Icon';
import ItalicIcon from 'components/Icon/ItalicIcon';
import LinkIcon from 'components/Icon/LinkIcon';
import StrikethroughIcon from 'components/Icon/StrikethroughIcon';
class FormattingToolbar extends Component {
props: {
editor: Editor,
onCreateLink: Function,
};
/**
* Check if the current selection has a mark with `type` in it.
*
* @param {String} type
* @return {Boolean}
*/
hasMark = (type: string) => {
return this.props.editor.value.marks.some(mark => mark.type === type);
};
isBlock = (type: string) => {
return this.props.editor.value.startBlock.type === type;
};
/**
* When a mark button is clicked, toggle the current mark.
*
* @param {Event} ev
* @param {String} type
*/
onClickMark = (ev: SyntheticEvent, type: string) => {
ev.preventDefault();
this.props.editor.change(change => change.toggleMark(type));
};
onClickBlock = (ev: SyntheticEvent, type: string) => {
ev.preventDefault();
this.props.editor.change(change => change.setBlock(type));
};
onCreateLink = (ev: SyntheticEvent) => {
ev.preventDefault();
ev.stopPropagation();
const data = { href: '' };
this.props.editor.change(change => {
change.wrapInline({ type: 'link', data });
this.props.onCreateLink();
});
};
renderMarkButton = (type: string, IconClass: Function) => {
const isActive = this.hasMark(type);
const onMouseDown = ev => this.onClickMark(ev, type);
return (
<ToolbarButton onMouseDown={onMouseDown} active={isActive}>
<IconClass light />
</ToolbarButton>
);
};
renderBlockButton = (type: string, IconClass: Function) => {
const isActive = this.isBlock(type);
const onMouseDown = ev =>
this.onClickBlock(ev, isActive ? 'paragraph' : type);
return (
<ToolbarButton onMouseDown={onMouseDown} active={isActive}>
<IconClass light />
</ToolbarButton>
);
};
render() {
return (
<span>
{this.renderMarkButton('bold', BoldIcon)}
{this.renderMarkButton('italic', ItalicIcon)}
{this.renderMarkButton('deleted', StrikethroughIcon)}
{this.renderMarkButton('code', CodeIcon)}
<Separator />
{this.renderBlockButton('heading1', Heading1Icon)}
{this.renderBlockButton('heading2', Heading2Icon)}
<Separator />
<ToolbarButton onMouseDown={this.onCreateLink}>
<LinkIcon light />
</ToolbarButton>
</span>
);
}
}
const Separator = styled.div`
height: 100%;
width: 1px;
background: #fff;
opacity: 0.2;
display: inline-block;
margin-left: 10px;
`;
export default FormattingToolbar;