diff --git a/components/clipboard-button/index.js b/components/clipboard-button/index.js
index e52ef576afc4bb..80a96920e5cbd1 100644
--- a/components/clipboard-button/index.js
+++ b/components/clipboard-button/index.js
@@ -3,12 +3,11 @@
*/
import Clipboard from 'clipboard';
import classnames from 'classnames';
-import { noop } from 'lodash';
/**
* WordPress dependencies
*/
-import { findDOMNode, Component } from '@wordpress/element';
+import { Component } from '@wordpress/element';
/**
* Internal dependencies
@@ -16,12 +15,23 @@ import { findDOMNode, Component } from '@wordpress/element';
import { Button } from '../';
class ClipboardButton extends Component {
+ constructor() {
+ super( ...arguments );
+
+ this.bindContainer = this.bindContainer.bind( this );
+ this.onCopy = this.onCopy.bind( this );
+ this.getText = this.getText.bind( this );
+ }
+
componentDidMount() {
- const { text, onCopy = noop } = this.props;
- const button = findDOMNode( this.button );
- this.clipboard = new Clipboard( button, {
- text: () => text,
+ const { container, getText, onCopy } = this;
+ const button = container.firstChild;
+
+ this.clipboard = new Clipboard( button, {
+ text: getText,
+ container,
} );
+
this.clipboard.on( 'success', onCopy );
}
@@ -30,17 +40,36 @@ class ClipboardButton extends Component {
delete this.clipboard;
}
+ bindContainer( container ) {
+ this.container = container;
+ }
+
+ onCopy( args ) {
+ // Clearing selection will move focus back to the triggering button,
+ // ensuring that it is not reset to the body, and further that it is
+ // kept within the rendered node.
+ args.clearSelection();
+
+ const { onCopy } = this.props;
+ if ( onCopy ) {
+ onCopy();
+ }
+ }
+
+ getText() {
+ return this.props.text;
+ }
+
render() {
const { className, children } = this.props;
const classes = classnames( 'components-clipboard-button', className );
return (
-
+
+
+
);
}
}
diff --git a/editor/post-permalink/index.js b/editor/post-permalink/index.js
index 2f7fc86277e431..a53295c6399696 100644
--- a/editor/post-permalink/index.js
+++ b/editor/post-permalink/index.js
@@ -25,7 +25,7 @@ class PostPermalink extends Component {
this.onCopy = this.onCopy.bind( this );
}
- componentWillUnmout() {
+ componentWillUnmount() {
clearTimeout( this.dismissCopyConfirmation );
}
diff --git a/editor/post-title/index.js b/editor/post-title/index.js
index bdbb042f47ba39..4c01f36bd5e687 100644
--- a/editor/post-title/index.js
+++ b/editor/post-title/index.js
@@ -3,7 +3,6 @@
*/
import { connect } from 'react-redux';
import Textarea from 'react-autosize-textarea';
-import clickOutside from 'react-click-outside';
import classnames from 'classnames';
/**
@@ -32,12 +31,16 @@ class PostTitle extends Component {
constructor() {
super( ...arguments );
- this.bindTextarea = this.bindTextarea.bind( this );
+ this.bindContainer = this.bindNode.bind( this, 'container' );
+ this.bindTextarea = this.bindNode.bind( this, 'textarea' );
this.onChange = this.onChange.bind( this );
this.onSelect = this.onSelect.bind( this );
this.onUnselect = this.onUnselect.bind( this );
this.onSelectionChange = this.onSelectionChange.bind( this );
this.onKeyDown = this.onKeyDown.bind( this );
+ this.blurIfOutside = this.blurIfOutside.bind( this );
+
+ this.nodes = {};
this.state = {
isSelected: false,
@@ -52,12 +55,12 @@ class PostTitle extends Component {
document.removeEventListener( 'selectionchange', this.onSelectionChange );
}
- bindTextarea( ref ) {
- this.textareaContainer = ref;
+ bindNode( name, node ) {
+ this.nodes[ name ] = node;
}
onSelectionChange() {
- const textarea = this.textareaContainer.textarea;
+ const textarea = this.nodes.textarea.textarea;
if (
document.activeElement === textarea &&
textarea.selectionStart !== textarea.selectionEnd
@@ -80,8 +83,10 @@ class PostTitle extends Component {
this.setState( { isSelected: false } );
}
- handleClickOutside() {
- this.setState( { isSelected: false } );
+ blurIfOutside( event ) {
+ if ( ! this.nodes.container.contains( event.relatedTarget ) ) {
+ this.onUnselect();
+ }
}
onKeyDown( event ) {
@@ -97,7 +102,13 @@ class PostTitle extends Component {
const className = classnames( 'editor-post-title', { 'is-selected': isSelected } );
return (
-