262 lines
7.4 KiB
JavaScript
262 lines
7.4 KiB
JavaScript
import React from 'react';
|
|
import PropTypes from 'prop-types';
|
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
|
import styled from '@emotion/styled';
|
|
import { css } from '@emotion/core';
|
|
import { List } from 'immutable';
|
|
import {
|
|
Toggle,
|
|
Dropdown,
|
|
DropdownItem,
|
|
DropdownButton,
|
|
colors,
|
|
transitions,
|
|
lengths,
|
|
} from 'netlify-cms-ui-default';
|
|
import ToolbarButton from './ToolbarButton';
|
|
|
|
const ToolbarContainer = styled.div`
|
|
background-color: ${colors.textFieldBorder};
|
|
border-top-right-radius: ${lengths.borderRadius};
|
|
position: relative;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 11px 14px;
|
|
min-height: 58px;
|
|
transition: background-color ${transitions.main}, color ${transitions.main};
|
|
color: ${colors.text};
|
|
`;
|
|
|
|
const ToolbarDropdownWrapper = styled.div`
|
|
display: inline-block;
|
|
position: relative;
|
|
`;
|
|
|
|
const ToolbarToggle = styled.div`
|
|
flex-shrink: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
font-size: 14px;
|
|
margin: 0 10px;
|
|
`;
|
|
|
|
const StyledToggle = ToolbarToggle.withComponent(Toggle);
|
|
|
|
const ToolbarToggleLabel = styled.span`
|
|
display: inline-block;
|
|
text-align: center;
|
|
white-space: nowrap;
|
|
line-height: 20px;
|
|
width: ${props => (props.offPosition ? '62px' : '70px')};
|
|
|
|
${props =>
|
|
props.isActive &&
|
|
css`
|
|
font-weight: 600;
|
|
color: ${colors.active};
|
|
`};
|
|
`;
|
|
|
|
const headingOptions = {
|
|
'heading-one': 'Heading 1',
|
|
'heading-two': 'Heading 2',
|
|
'heading-three': 'Heading 3',
|
|
'heading-four': 'Heading 4',
|
|
'heading-five': 'Heading 5',
|
|
'heading-six': 'Heading 6',
|
|
};
|
|
|
|
export default class Toolbar extends React.Component {
|
|
static propTypes = {
|
|
buttons: ImmutablePropTypes.list,
|
|
onToggleMode: PropTypes.func.isRequired,
|
|
rawMode: PropTypes.bool,
|
|
plugins: ImmutablePropTypes.map,
|
|
onSubmit: PropTypes.func,
|
|
onAddAsset: PropTypes.func,
|
|
getAsset: PropTypes.func,
|
|
disabled: PropTypes.bool,
|
|
onMarkClick: PropTypes.func,
|
|
onBlockClick: PropTypes.func,
|
|
onLinkClick: PropTypes.func,
|
|
hasMark: PropTypes.func,
|
|
hasInline: PropTypes.func,
|
|
hasBlock: PropTypes.func,
|
|
t: PropTypes.func.isRequired,
|
|
};
|
|
|
|
isHidden = button => {
|
|
const { buttons } = this.props;
|
|
return List.isList(buttons) ? !buttons.includes(button) : false;
|
|
};
|
|
|
|
handleBlockClick = (event, type) => {
|
|
if (event) {
|
|
event.preventDefault();
|
|
}
|
|
this.props.onBlockClick(type);
|
|
};
|
|
|
|
handleMarkClick = (event, type) => {
|
|
event.preventDefault();
|
|
this.props.onMarkClick(type);
|
|
};
|
|
|
|
render() {
|
|
const {
|
|
onLinkClick,
|
|
onToggleMode,
|
|
rawMode,
|
|
plugins,
|
|
disabled,
|
|
onSubmit,
|
|
hasMark = () => {},
|
|
hasInline = () => {},
|
|
hasBlock = () => {},
|
|
t,
|
|
} = this.props;
|
|
|
|
return (
|
|
<ToolbarContainer>
|
|
<div>
|
|
<ToolbarButton
|
|
type="bold"
|
|
label="Bold"
|
|
icon="bold"
|
|
onClick={this.handleMarkClick}
|
|
isActive={hasMark('bold')}
|
|
isHidden={this.isHidden('bold')}
|
|
disabled={disabled}
|
|
/>
|
|
<ToolbarButton
|
|
type="italic"
|
|
label="Italic"
|
|
icon="italic"
|
|
onClick={this.handleMarkClick}
|
|
isActive={hasMark('italic')}
|
|
isHidden={this.isHidden('italic')}
|
|
disabled={disabled}
|
|
/>
|
|
<ToolbarButton
|
|
type="code"
|
|
label="Code"
|
|
icon="code"
|
|
onClick={this.handleMarkClick}
|
|
isActive={hasMark('code')}
|
|
isHidden={this.isHidden('code')}
|
|
disabled={disabled}
|
|
/>
|
|
<ToolbarButton
|
|
type="link"
|
|
label="Link"
|
|
icon="link"
|
|
onClick={onLinkClick}
|
|
isActive={hasInline('link')}
|
|
isHidden={this.isHidden('link')}
|
|
disabled={disabled}
|
|
/>
|
|
{/* Show dropdown if at least one heading is not hidden */}
|
|
{Object.keys(headingOptions).some(optionKey => {
|
|
return !this.isHidden(optionKey);
|
|
}) && (
|
|
<ToolbarDropdownWrapper>
|
|
<Dropdown
|
|
dropdownTopOverlap="36px"
|
|
renderButton={() => (
|
|
<DropdownButton>
|
|
<ToolbarButton
|
|
type="headings"
|
|
label="Headings"
|
|
icon="hOptions"
|
|
disabled={disabled}
|
|
isActive={
|
|
!disabled &&
|
|
Object.keys(headingOptions).some(optionKey => {
|
|
return hasBlock(optionKey);
|
|
})
|
|
}
|
|
/>
|
|
</DropdownButton>
|
|
)}
|
|
>
|
|
{!disabled &&
|
|
Object.keys(headingOptions).map(
|
|
(optionKey, idx) =>
|
|
!this.isHidden(optionKey) && (
|
|
<DropdownItem
|
|
key={idx}
|
|
label={headingOptions[optionKey]}
|
|
className={hasBlock(optionKey) ? 'active' : ''}
|
|
onClick={() => this.handleBlockClick(null, optionKey)}
|
|
/>
|
|
),
|
|
)}
|
|
</Dropdown>
|
|
</ToolbarDropdownWrapper>
|
|
)}
|
|
<ToolbarButton
|
|
type="quote"
|
|
label="Quote"
|
|
icon="quote"
|
|
onClick={this.handleBlockClick}
|
|
isActive={hasBlock('quote')}
|
|
isHidden={this.isHidden('quote')}
|
|
disabled={disabled}
|
|
/>
|
|
<ToolbarButton
|
|
type="bulleted-list"
|
|
label="Bulleted List"
|
|
icon="list-bulleted"
|
|
onClick={this.handleBlockClick}
|
|
isActive={hasBlock('bulleted-list')}
|
|
isHidden={this.isHidden('bulleted-list')}
|
|
disabled={disabled}
|
|
/>
|
|
<ToolbarButton
|
|
type="numbered-list"
|
|
label="Numbered List"
|
|
icon="list-numbered"
|
|
onClick={this.handleBlockClick}
|
|
isActive={hasBlock('numbered-list')}
|
|
isHidden={this.isHidden('numbered-list')}
|
|
disabled={disabled}
|
|
/>
|
|
<ToolbarDropdownWrapper>
|
|
<Dropdown
|
|
dropdownTopOverlap="36px"
|
|
dropdownWidth="110px"
|
|
renderButton={() => (
|
|
<DropdownButton>
|
|
<ToolbarButton
|
|
label="Add Component"
|
|
icon="add-with"
|
|
onClick={this.handleComponentsMenuToggle}
|
|
disabled={disabled}
|
|
/>
|
|
</DropdownButton>
|
|
)}
|
|
>
|
|
{plugins &&
|
|
plugins
|
|
.toList()
|
|
.map((plugin, idx) => (
|
|
<DropdownItem key={idx} label={plugin.label} onClick={() => onSubmit(plugin)} />
|
|
))}
|
|
</Dropdown>
|
|
</ToolbarDropdownWrapper>
|
|
</div>
|
|
<ToolbarToggle>
|
|
<ToolbarToggleLabel isActive={!rawMode} offPosition>
|
|
{t('editor.editorWidgets.markdown.richText')}
|
|
</ToolbarToggleLabel>
|
|
<StyledToggle active={rawMode} onChange={onToggleMode} />
|
|
<ToolbarToggleLabel isActive={rawMode}>
|
|
{t('editor.editorWidgets.markdown.markdown')}
|
|
</ToolbarToggleLabel>
|
|
</ToolbarToggle>
|
|
</ToolbarContainer>
|
|
);
|
|
}
|
|
}
|