Add markdown editor toolbar customization
This commit is contained in:
parent
9975c7e914
commit
106968990d
@ -1,4 +1,5 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import React from 'react';
|
||||
import { Editor as Slate } from 'slate-react';
|
||||
import Plain from 'slate-plain-serializer';
|
||||
@ -50,12 +51,13 @@ export default class RawEditor extends React.Component {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { className } = this.props;
|
||||
const { className, field } = this.props;
|
||||
return (
|
||||
<div className="nc-rawEditor-rawWrapper">
|
||||
<div className="nc-visualEditor-editorControlBar">
|
||||
<Toolbar
|
||||
onToggleMode={this.handleToggleMode}
|
||||
buttons={field.get('buttons')}
|
||||
className="nc-markdownWidget-toolbarRaw"
|
||||
disabled
|
||||
rawMode
|
||||
@ -77,4 +79,5 @@ RawEditor.propTypes = {
|
||||
onMode: PropTypes.func.isRequired,
|
||||
className: PropTypes.string.isRequired,
|
||||
value: PropTypes.string,
|
||||
field: ImmutablePropTypes.map
|
||||
};
|
||||
|
@ -17,6 +17,7 @@ export default class Toolbar extends React.Component {
|
||||
getAsset: PropTypes.func,
|
||||
disabled: PropTypes.bool,
|
||||
className: PropTypes.string,
|
||||
buttons: ImmutablePropTypes.list
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
@ -26,7 +27,7 @@ export default class Toolbar extends React.Component {
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
getToolbarButtonsList() {
|
||||
const {
|
||||
onMarkClick,
|
||||
onBlockClick,
|
||||
@ -34,18 +35,64 @@ export default class Toolbar extends React.Component {
|
||||
selectionHasMark,
|
||||
selectionHasBlock,
|
||||
selectionHasLink,
|
||||
disabled,
|
||||
buttons
|
||||
} = this.props;
|
||||
|
||||
const toolbarButtons = [
|
||||
{ type: 'bold', label: 'Bold', icon: 'bold', onClick: onMarkClick, isActive: selectionHasMark, disabled },
|
||||
{ type: 'italic', label: 'Italic', icon: 'italic', onClick: onMarkClick, isActive: selectionHasMark, disabled },
|
||||
{ type: 'code', label: 'Code', icon: 'code', onClick: onMarkClick, isActive: selectionHasMark, disabled },
|
||||
{ type: 'link', label: 'Link', icon: 'link', onClick: onLinkClick, isActive: selectionHasLink, disabled },
|
||||
{ type: 'heading-one', label: 'Header 1', icon: 'h1', onClick: onBlockClick, isActive: selectionHasBlock, disabled },
|
||||
{ type: 'heading-two', label: 'Header 2', icon: 'h2', onClick: onBlockClick, isActive: selectionHasBlock, disabled },
|
||||
{ type: 'quote', label: 'Quote', icon: 'quote', onClick: onBlockClick, isActive: selectionHasBlock, disabled },
|
||||
{ type: 'code', label: 'Code Block', icon: 'code-block', onClick: onBlockClick, isActive: selectionHasBlock, disabled },
|
||||
{ type: 'bulleted-list', label: 'Bulleted List', icon: 'list-bulleted', onClick: onBlockClick, isActive: selectionHasBlock, disabled },
|
||||
{ type: 'numbered-list', label: 'Numbered List', icon: 'list-numbered', onClick: onBlockClick, isActive: selectionHasBlock, disabled }
|
||||
];
|
||||
|
||||
return buttons === undefined ? toolbarButtons : toolbarButtons.filter(button => buttons.includes(button.type));
|
||||
}
|
||||
|
||||
renderToolbarButton(button) {
|
||||
const { type, label, icon, onClick, isActive, disabled } = button;
|
||||
return <ToolbarButton key={label} type={type} label={label} icon={icon} onClick={onClick} isActive={isActive} disabled={disabled}/>;
|
||||
}
|
||||
|
||||
renderToolbarDropdown() {
|
||||
const { plugins, disabled, onSubmit } = this.props;
|
||||
|
||||
return (
|
||||
<div className="nc-toolbar-dropdown">
|
||||
<Dropdown
|
||||
dropdownTopOverlap="36px"
|
||||
button={
|
||||
<ToolbarButton
|
||||
label="Add Component"
|
||||
icon="add-with"
|
||||
onClick={this.handleComponentsMenuToggle}
|
||||
disabled={disabled}
|
||||
/>
|
||||
}
|
||||
>
|
||||
{plugins && plugins.toList().map((plugin, idx) => (
|
||||
<DropdownItem key={idx} label={plugin.get('label')} onClick={() => onSubmit(plugin.get('id'))} />
|
||||
))}
|
||||
</Dropdown>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderToolbarToggle() {
|
||||
const {
|
||||
onToggleMode,
|
||||
rawMode,
|
||||
plugins,
|
||||
onAddAsset,
|
||||
getAsset,
|
||||
disabled,
|
||||
onSubmit,
|
||||
className,
|
||||
className
|
||||
} = this.props;
|
||||
|
||||
const { activePlugin } = this.state;
|
||||
|
||||
/**
|
||||
* Because the toggle labels change font weight for active/inactive state,
|
||||
* we need to set estimated widths for them to maintain position without
|
||||
@ -57,132 +104,43 @@ export default class Toolbar extends React.Component {
|
||||
const toggleOnLabelWidth = '70px';
|
||||
|
||||
return (
|
||||
<div className={c(className, 'nc-toolbar-Toolbar')}>
|
||||
<div className="nc-markdownWidget-toolbar-toggle">
|
||||
<span
|
||||
style={{ width: toggleOffLabelWidth }}
|
||||
className={c(
|
||||
'nc-markdownWidget-toolbar-toggle-label',
|
||||
{ 'nc-markdownWidget-toolbar-toggle-label-active': !rawMode },
|
||||
)}
|
||||
>
|
||||
{toggleOffLabel}
|
||||
</span>
|
||||
<Toggle
|
||||
active={rawMode}
|
||||
onChange={onToggleMode}
|
||||
className="nc-markdownWidget-toolbar-toggle"
|
||||
classNameBackground="nc-markdownWidget-toolbar-toggle-background"
|
||||
/>
|
||||
<span
|
||||
style={{ width: toggleOnLabelWidth }}
|
||||
className={c(
|
||||
'nc-markdownWidget-toolbar-toggle-label',
|
||||
{ 'nc-markdownWidget-toolbar-toggle-label-active': rawMode },
|
||||
)}
|
||||
>
|
||||
{toggleOnLabel}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className={c(this.props.className, 'nc-toolbar-Toolbar')}>
|
||||
<div>
|
||||
<ToolbarButton
|
||||
type="bold"
|
||||
label="Bold"
|
||||
icon="bold"
|
||||
onClick={onMarkClick}
|
||||
isActive={selectionHasMark}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<ToolbarButton
|
||||
type="italic"
|
||||
label="Italic"
|
||||
icon="italic"
|
||||
onClick={onMarkClick}
|
||||
isActive={selectionHasMark}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<ToolbarButton
|
||||
type="code"
|
||||
label="Code"
|
||||
icon="code"
|
||||
onClick={onMarkClick}
|
||||
isActive={selectionHasMark}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<ToolbarButton
|
||||
type="link"
|
||||
label="Link"
|
||||
icon="link"
|
||||
onClick={onLinkClick}
|
||||
isActive={selectionHasLink}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<ToolbarButton
|
||||
type="heading-one"
|
||||
label="Header 1"
|
||||
icon="h1"
|
||||
onClick={onBlockClick}
|
||||
isActive={selectionHasBlock}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<ToolbarButton
|
||||
type="heading-two"
|
||||
label="Header 2"
|
||||
icon="h2"
|
||||
onClick={onBlockClick}
|
||||
isActive={selectionHasBlock}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<ToolbarButton
|
||||
type="quote"
|
||||
label="Quote"
|
||||
icon="quote"
|
||||
onClick={onBlockClick}
|
||||
isActive={selectionHasBlock}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<ToolbarButton
|
||||
type="code"
|
||||
label="Code Block"
|
||||
icon="code-block"
|
||||
onClick={onBlockClick}
|
||||
isActive={selectionHasBlock}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<ToolbarButton
|
||||
type="bulleted-list"
|
||||
label="Bulleted List"
|
||||
icon="list-bulleted"
|
||||
onClick={onBlockClick}
|
||||
isActive={selectionHasBlock}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<ToolbarButton
|
||||
type="numbered-list"
|
||||
label="Numbered List"
|
||||
icon="list-numbered"
|
||||
onClick={onBlockClick}
|
||||
isActive={selectionHasBlock}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<div className="nc-toolbar-dropdown">
|
||||
<Dropdown
|
||||
dropdownTopOverlap="36px"
|
||||
button={
|
||||
<ToolbarButton
|
||||
label="Add Component"
|
||||
icon="add-with"
|
||||
onClick={this.handleComponentsMenuToggle}
|
||||
disabled={disabled}
|
||||
/>
|
||||
}
|
||||
>
|
||||
{plugins && plugins.toList().map((plugin, idx) => (
|
||||
<DropdownItem key={idx} label={plugin.get('label')} onClick={() => onSubmit(plugin.get('id'))} />
|
||||
))}
|
||||
</Dropdown>
|
||||
</div>
|
||||
</div>
|
||||
<div className="nc-markdownWidget-toolbar-toggle">
|
||||
<span
|
||||
style={{ width: toggleOffLabelWidth }}
|
||||
className={c(
|
||||
'nc-markdownWidget-toolbar-toggle-label',
|
||||
{ 'nc-markdownWidget-toolbar-toggle-label-active': !rawMode },
|
||||
)}
|
||||
>
|
||||
{toggleOffLabel}
|
||||
</span>
|
||||
<Toggle
|
||||
active={rawMode}
|
||||
onChange={onToggleMode}
|
||||
className="nc-markdownWidget-toolbar-toggle"
|
||||
classNameBackground="nc-markdownWidget-toolbar-toggle-background"
|
||||
/>
|
||||
<span
|
||||
style={{ width: toggleOnLabelWidth }}
|
||||
className={c(
|
||||
'nc-markdownWidget-toolbar-toggle-label',
|
||||
{ 'nc-markdownWidget-toolbar-toggle-label-active': rawMode },
|
||||
)}
|
||||
>
|
||||
{toggleOnLabel}
|
||||
</span>
|
||||
{this.getToolbarButtonsList().map((toolbarButton) => this.renderToolbarButton(toolbarButton))}
|
||||
{this.renderToolbarDropdown()}
|
||||
</div>
|
||||
{this.renderToolbarToggle()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import React, { Component } from 'react';
|
||||
import { get, isEmpty, debounce } from 'lodash';
|
||||
import { Map } from 'immutable';
|
||||
@ -33,6 +34,7 @@ export default class Editor extends Component {
|
||||
onMode: PropTypes.func.isRequired,
|
||||
className: PropTypes.string.isRequired,
|
||||
value: PropTypes.string,
|
||||
field: ImmutablePropTypes.map
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
@ -189,7 +191,7 @@ export default class Editor extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { onAddAsset, getAsset, className } = this.props;
|
||||
const { onAddAsset, getAsset, className, field } = this.props;
|
||||
|
||||
return (
|
||||
<div className="nc-visualEditor-wrapper">
|
||||
@ -206,6 +208,7 @@ export default class Editor extends Component {
|
||||
onSubmit={this.handlePluginAdd}
|
||||
onAddAsset={onAddAsset}
|
||||
getAsset={getAsset}
|
||||
buttons={field.get('buttons')}
|
||||
/>
|
||||
</div>
|
||||
<Slate
|
||||
|
@ -45,6 +45,7 @@ export default class MarkdownControl extends React.Component {
|
||||
getAsset,
|
||||
value,
|
||||
classNameWrapper,
|
||||
field
|
||||
} = this.props;
|
||||
|
||||
const { mode } = this.state;
|
||||
@ -57,6 +58,7 @@ export default class MarkdownControl extends React.Component {
|
||||
getAsset={getAsset}
|
||||
className={classNameWrapper}
|
||||
value={value}
|
||||
field={field}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
@ -69,6 +71,7 @@ export default class MarkdownControl extends React.Component {
|
||||
getAsset={getAsset}
|
||||
className={classNameWrapper}
|
||||
value={value}
|
||||
field={field}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user