diff --git a/blocks/components/editable/index.js b/blocks/components/editable/index.js index bc524c53205250..97c88482295244 100644 --- a/blocks/components/editable/index.js +++ b/blocks/components/editable/index.js @@ -131,7 +131,7 @@ export default class Editable extends wp.element.Component { } onNodeChange( { parents } ) { - this.formats = parents.reduce( ( result, node ) => { + const formats = parents.reduce( ( result, node ) => { const tag = node.nodeName.toLowerCase(); if ( formatMap.hasOwnProperty( tag ) ) { @@ -141,6 +141,14 @@ export default class Editable extends wp.element.Component { return result; }, {} ); + // Link format + const link = parents.find( parent => parent.nodeName === 'A' ); + if ( link ) { + formats.link = link.getAttribute( 'href' ); + } + + this.formats = formats; + this.props.onFormatChange( this.formats ); } @@ -215,7 +223,9 @@ export default class Editable extends wp.element.Component { if ( state !== currentState ) { this.editor.focus(); - if ( state ) { + if ( format === 'link' ) { + this.editor.execCommand( 'mceInsertLink', true, state ); + } else if ( state ) { this.editor.formatter.apply( format ); } else { this.editor.formatter.remove( format ); diff --git a/editor/components/format-toolbar/index.js b/editor/components/format-toolbar/index.js new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/editor/components/toolbar/index.js b/editor/components/toolbar/index.js index 2a63d1cb38d9d4..da53845fc75f0e 100644 --- a/editor/components/toolbar/index.js +++ b/editor/components/toolbar/index.js @@ -9,27 +9,34 @@ import classNames from 'classnames'; import './style.scss'; import IconButton from 'components/icon-button'; -function Toolbar( { controls } ) { +function Toolbar( { attributes, setAttributes, controls } ) { if ( ! controls || ! controls.length ) { return null; } return ( ); } diff --git a/editor/modes/visual-editor/block.js b/editor/modes/visual-editor/block.js index 6f7c705a697b13..fe9692977b2973 100644 --- a/editor/modes/visual-editor/block.js +++ b/editor/modes/visual-editor/block.js @@ -10,24 +10,7 @@ import classnames from 'classnames'; import Toolbar from 'components/toolbar'; import BlockMover from 'components/block-mover'; import BlockSwitcher from 'components/block-switcher'; - -const formattingControls = [ - { - icon: 'editor-bold', - title: wp.i18n.__( 'Bold' ), - format: 'bold' - }, - { - icon: 'editor-italic', - title: wp.i18n.__( 'Italic' ), - format: 'italic' - }, - { - icon: 'editor-strikethrough', - title: wp.i18n.__( 'Strikethrough' ), - format: 'strikethrough' - } -]; +import formattingControls from './format-controls'; class VisualEditorBlock extends wp.element.Component { constructor() { @@ -37,7 +20,7 @@ class VisualEditorBlock extends wp.element.Component { this.maybeDeselect = this.maybeDeselect.bind( this ); this.maybeHover = this.maybeHover.bind( this ); this.onFormatChange = this.onFormatChange.bind( this ); - this.toggleFormat = this.toggleFormat.bind( this ); + this.setFormats = this.setFormats.bind( this ); this.previousOffset = null; this.state = { formats: {} @@ -56,13 +39,13 @@ class VisualEditorBlock extends wp.element.Component { this.setState( { formats } ); } - toggleFormat( format ) { + setFormats( newFormats ) { const { formats } = this.state; this.setState( { formats: { ...formats, - [ format ]: ! formats[ format ] + ...newFormats } } ); } @@ -143,7 +126,6 @@ class VisualEditorBlock extends wp.element.Component { tabIndex="0" onFocus={ onSelect } onBlur={ this.maybeDeselect } - onKeyDown={ onStartTyping } onMouseEnter={ onHover } onMouseMove={ this.maybeHover } onMouseLeave={ onMouseLeave } @@ -155,31 +137,31 @@ class VisualEditorBlock extends wp.element.Component { { !! settings.controls && ( ( { - ...control, - onClick: () => control.onClick( block.attributes, this.setAttributes ), - isActive: () => control.isActive( block.attributes ) - } ) ) } /> + controls={ settings.controls } + attributes={ block.attributes } + setAttributes={ this.setAttributes } + /> ) } { this.state.hasEditable && ( ( { - ...control, - onClick: () => this.toggleFormat( control.format ), - isActive: () => !! this.state.formats[ control.format ] - } ) ) } /> + controls={ formattingControls } + attributes={ this.state.formats } + setAttributes={ this.setFormats } + /> ) } } - +
+ +
); /* eslint-enable jsx-a11y/no-static-element-interactions */ diff --git a/editor/modes/visual-editor/format-controls.js b/editor/modes/visual-editor/format-controls.js new file mode 100644 index 00000000000000..21121f08bbfc24 --- /dev/null +++ b/editor/modes/visual-editor/format-controls.js @@ -0,0 +1,105 @@ +/** + * External dependencies + */ +import classNames from 'classnames'; + +/** + * Internal dependencies + */ +import './style.scss'; +import IconButton from 'components/icon-button'; + +class LinkControl extends wp.element.Component { + constructor() { + super( ...arguments ); + this.state = { + opened: false + }; + this.toggleLinkModal = this.toggleLinkModal.bind( this ); + this.submitLinkModal = this.submitLinkModal.bind( this ); + this.updateLinkValue = this.updateLinkValue.bind( this ); + } + + componentWillMount() { + this.setState( { value: this.props.attributes.link } ); + } + + componentWillReceiveProps( nextProps ) { + this.setState( { value: nextProps.attributes.link } ); + } + + toggleLinkModal() { + this.setState( { + opened: ! this.state.opened + } ); + } + + submitLinkModal( event ) { + event.preventDefault(); + this.props.setAttributes( { link: this.state.value } ); + this.setState( { + opened: false + } ); + } + + updateLinkValue( event ) { + this.setState( { + value: event.target.value + } ); + } + + render() { + return ( +
+ + { this.state.opened && +
+
+ + +
+
+ } +
+ ); + } +} + +const formattingControls = [ + { + icon: 'editor-bold', + title: wp.i18n.__( 'Bold' ), + isActive: ( { bold } ) => !! bold, + onClick( attributes, setAttributes ) { + setAttributes( { bold: ! attributes.bold } ); + }, + }, + { + icon: 'editor-italic', + title: wp.i18n.__( 'Italic' ), + isActive: ( { italic } ) => !! italic, + onClick( attributes, setAttributes ) { + setAttributes( { italic: ! attributes.italic } ); + }, + }, + { + icon: 'editor-strikethrough', + title: wp.i18n.__( 'Strikethrough' ), + isActive: ( { strikethrough } ) => !! strikethrough, + onClick( attributes, setAttributes ) { + setAttributes( { strikethrough: ! attributes.strikethrough } ); + }, + }, + { + edit: LinkControl + } +]; + +export default formattingControls; diff --git a/editor/modes/visual-editor/style.scss b/editor/modes/visual-editor/style.scss index e5815cd9c3108f..e95ab016362887 100644 --- a/editor/modes/visual-editor/style.scss +++ b/editor/modes/visual-editor/style.scss @@ -60,3 +60,22 @@ .editor-visual-editor .editor-inserter { margin: $item-spacing; } + + +// joen make me pretty +.editable-visual-editor__link-control { + position: relative; +} + +.editable-visual-editor__link-modal { + position: absolute; + top: 42px; + box-shadow: 0px 3px 20px rgba( 18, 24, 30, .1 ), 0px 1px 3px rgba( 18, 24, 30, .1 ); + border: 1px solid #e0e5e9; + background: #fff; + padding: 10px; + + input { + font-size: 13px; + } +} diff --git a/languages/gutenberg.pot b/languages/gutenberg.pot index a26b05009d732f..37da5a4d2e188b 100644 --- a/languages/gutenberg.pot +++ b/languages/gutenberg.pot @@ -95,15 +95,23 @@ msgstr "" msgid "Publish" msgstr "" -#: editor/modes/visual-editor/block.js:17 +#: editor/modes/visual-editor/format-controls.js:56 +msgid "Link" +msgstr "" + +#: editor/modes/visual-editor/format-controls.js:66 +msgid "Add Link" +msgstr "" + +#: editor/modes/visual-editor/format-controls.js:78 msgid "Bold" msgstr "" -#: editor/modes/visual-editor/block.js:22 +#: editor/modes/visual-editor/format-controls.js:86 msgid "Italic" msgstr "" -#: editor/modes/visual-editor/block.js:27 +#: editor/modes/visual-editor/format-controls.js:94 msgid "Strikethrough" msgstr ""