Skip to content

Commit

Permalink
TinyMCE per block: Adding a custom Link control to TinyMCE instances (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
youknowriad authored Mar 6, 2017
1 parent 4106a8a commit defa286
Show file tree
Hide file tree
Showing 9 changed files with 188 additions and 73 deletions.
26 changes: 13 additions & 13 deletions tinymce-per-block/build/app.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions tinymce-per-block/src/assets/stylesheets/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
@import '~external/dashicons/style';
@import '~renderers/block/block-list/style';
@import '~renderers/html/html-editor/style';
@import '~controls/editable-format-toolbar/style';

* {
box-sizing: border-box;
Expand Down
57 changes: 0 additions & 57 deletions tinymce-per-block/src/controls/editable-format-toolbar.js

This file was deleted.

117 changes: 117 additions & 0 deletions tinymce-per-block/src/controls/editable-format-toolbar/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/**
* External dependencies
*/
import { createElement, Component } from 'wp-elements';
import classNames from 'classnames';
import {
EditorBoldIcon,
EditorItalicIcon,
EditorStrikethroughIcon,
AdminLinksIcon
} from 'dashicons';

export default class EditableFormatToolbar extends Component {
state = {
controls: {
bold: false,
italic: false,
strikethrough: false,
link: ''
},
linkModal: {
open: false,
value: ''
}
};

clickToolbarControl = ( control ) => ( event ) => {
if ( ! this.props.editable ) {
return;
}
event.preventDefault();
this.props.editable.executeCommand( control, true, ! this.state[ control ] );
};

setToolbarState( control, value ) {
if ( this.state.controls[ control ] === value ) {
return;
}
if ( control === 'link' && this.state.controls.link !== value ) {
this.setState( {
linkModal: {
open: this.state.linkModal.open,
value
}
} );
}
this.setState( {
controls: Object.assign( {}, this.state.controls, {
[ control ]: value
} )
} );
}

toggleLinkModal = () => {
this.setState( {
linkModal: {
open: ! this.state.linkModal.open,
value: this.state.controls.link
}
} );
};

submitLinkModal = ( event ) => {
event.preventDefault();
this.props.editable && this.props.editable.executeCommand( 'mceInsertLink', true, this.state.linkModal.value );
this.setState( {
linkModal: {
open: false,
value: this.state.controls.link
}
} );
};

updateLinkValue = ( event ) => {
this.setState( {
linkModal: {
open: true,
value: event.target.value
}
} );
}

render() {
const formats = [
{ id: 'bold', icon: EditorBoldIcon, onClick: this.clickToolbarControl( 'bold' ) },
{ id: 'italic', icon: EditorItalicIcon, onClick: this.clickToolbarControl( 'italic' ) },
{ id: 'strikethrough', icon: EditorStrikethroughIcon,
onClick: this.clickToolbarControl( 'strikethrough' )
},
{ id: 'link', icon: AdminLinksIcon, onClick: this.toggleLinkModal }
];

return (
<div className="editable-format-toolbar block-list__block-toolbar">
{ formats.map( ( { id, icon: Icon, onClick } ) =>
<button
key={ id }
className={ classNames( 'block-list__block-control', {
'is-selected': !! this.state.controls[ id ]
} ) }
onClick={ onClick }
>
<Icon />
</button>
) }
{ this.state.linkModal.open &&
<div className="controls__link-modal">
<form onSubmit={ this.submitLinkModal }>
<input type="url" value={ this.state.linkModal.value } onChange={ this.updateLinkValue } />
<button>Add Link</button>
</form>
</div>
}
</div>
);
}
}
33 changes: 33 additions & 0 deletions tinymce-per-block/src/controls/editable-format-toolbar/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
.editable-format-toolbar {
position: relative;
}

.controls__link-modal {
position: absolute;
top: 50px;
box-shadow: 0px 3px 20px rgba( 18, 24, 30, .1 ), 0px 1px 3px rgba( 18, 24, 30, .1 );
border: 1px solid #e0e5e9;
background: #fff;
z-index: 1;
padding: 10px;

input {
font-size: 13px;
}

&:before {
content: '';
border: 10px dashed #e0e5e9;
height: 0;
line-height: 0;
position: absolute;
width: 0;
top: -10px;
left: 50%;
margin-left: -10px;
border-bottom-style: solid;
border-top: none;
border-left-color: transparent;
border-right-color: transparent;
}
}
13 changes: 13 additions & 0 deletions tinymce-per-block/src/external/dashicons/icons/admin-links.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* External dependencies
*/
import { createElement } from 'wp-elements';

/**
* Internal dependencies
*/
import createDashicon from '../create-dashicon';

export default createDashicon(
<path d="M17.74 2.76c1.68 1.69 1.68 4.41 0 6.1l-1.53 1.52c-1.12 1.12-2.7 1.47-4.14 1.090l2.62-2.61 0.76-0.77 0.76-0.76c0.84-0.84 0.84-2.2 0-3.040-0.84-0.85-2.2-0.85-3.040 0l-0.77 0.76-3.38 3.38c-0.37-1.44-0.020-3.020 1.1-4.14l1.52-1.53c1.69-1.68 4.42-1.68 6.1 0zM8.59 13.43l5.34-5.34c0.42-0.42 0.42-1.1 0-1.52-0.44-0.43-1.13-0.39-1.53 0l-5.33 5.34c-0.42 0.42-0.42 1.1 0 1.52 0.44 0.43 1.13 0.39 1.52 0zM7.83 15.72l4.14-4.15c0.38 1.44 0.030 3.020-1.090 4.14l-1.52 1.53c-1.69 1.68-4.41 1.68-6.1 0-1.68-1.68-1.68-4.42 0-6.1l1.53-1.52c1.12-1.12 2.7-1.47 4.14-1.1l-4.14 4.15c-0.85 0.84-0.85 2.2 0 3.050 0.84 0.84 2.2 0.84 3.040 0z"></path>
);
1 change: 1 addition & 0 deletions tinymce-per-block/src/external/dashicons/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ export { default as ImageAlignLeftIcon } from './icons/image-align-left';
export { default as ImageAlignRightIcon } from './icons/image-align-right';
export { default as ImageFullWidthIcon } from './icons/image-full-width';
export { default as VideoAlt3Icon } from './icons/video-alt3';
export { default as AdminLinksIcon } from './icons/admin-links';
9 changes: 8 additions & 1 deletion tinymce-per-block/src/external/wp-blocks/editable/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ function initialize( node, inline, onSetup ) {
};

if ( inline ) {
config.valid_elements = '#p,br,b,i,strong,em,del';
config.valid_elements = '#p,br,b,i,strong,em,del,a[href|target]';
}

tinymce.init( config );
Expand Down Expand Up @@ -169,6 +169,13 @@ export default class EditableComponent extends Component {
!! event.parents.find( parent => format.nodes.indexOf( parent.nodeName ) !== -1 );
this.props.setToolbarState( format.id, formatValue );
} );

// Link format
const link = event.element.nodeName === 'A'
? event.element
: event.parents.find( parent => parent.nodeName === 'A' );
const linkValue = link ? link.getAttribute( 'href' ) : '';
this.props.setToolbarState( 'link', linkValue );
};

onFocus = () => {
Expand Down
4 changes: 2 additions & 2 deletions tinymce-per-block/src/renderers/block/block-list/_style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
position: absolute;
left: 0;
top: -36px;
z-index: 1;
}

.block-list__block-controls-group {
Expand All @@ -39,7 +40,6 @@
box-shadow: 0px 3px 20px rgba( 18, 24, 30, .1 ), 0px 1px 3px rgba( 18, 24, 30, .1 );
color: #12181e;
display: inline-block;
overflow: hidden;
margin-left: 20px;
}

Expand All @@ -58,7 +58,7 @@
display: block;
float: left;

&.is-selected {
&.is-selected, &:hover {
background: #f0f2f4;
}

Expand Down

0 comments on commit defa286

Please sign in to comment.