diff --git a/components/clipboard-button/index.js b/components/clipboard-button/index.js index 3c4a78f30783a0..79f550acc60cb6 100644 --- a/components/clipboard-button/index.js +++ b/components/clipboard-button/index.js @@ -38,6 +38,7 @@ class ClipboardButton extends Component { componentWillUnmount() { this.clipboard.destroy(); delete this.clipboard; + clearTimeout( this.onCopyTimeout ); } bindContainer( container ) { @@ -50,9 +51,17 @@ class ClipboardButton extends Component { // kept within the rendered node. args.clearSelection(); - const { onCopy } = this.props; + const { onCopy, onFinishCopy } = this.props; if ( onCopy ) { onCopy(); + // For convenience and consistency, ClipboardButton offers to call + // a secondary callback with delay. This is useful to reset + // consumers' state, e.g. to revert a label from "Copied" to + // "Copy". + if ( onFinishCopy ) { + clearTimeout( this.onCopyTimeout ); + this.onCopyTimeout = setTimeout( onFinishCopy, 4000 ); + } } } @@ -68,7 +77,7 @@ class ClipboardButton extends Component { render() { // Disable reason: Exclude from spread props passed to Button // eslint-disable-next-line no-unused-vars - const { className, children, onCopy, text, ...buttonProps } = this.props; + const { className, children, onCopy, onFinishCopy, text, ...buttonProps } = this.props; const classes = classnames( 'components-clipboard-button', className ); return ( diff --git a/components/menu-items/menu-items-group.js b/components/menu-items/menu-items-group.js index d59f9785b2b097..27a8af4533361d 100644 --- a/components/menu-items/menu-items-group.js +++ b/components/menu-items/menu-items-group.js @@ -1,3 +1,8 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + /** * Internal dependencies */ @@ -6,11 +11,23 @@ import { NavigableMenu } from '../navigable-container'; import withInstanceId from '../higher-order/with-instance-id'; import MenuItemsToggle from './menu-items-toggle'; -function MenuItemsGroup( { label, value, choices = [], onSelect, children, instanceId } ) { +function MenuItemsGroup( { + label, + value, + choices = [], + onSelect, + children, + instanceId, + className = '', +} ) { const labelId = `components-choice-menu-label-${ instanceId }`; + const classNames = classnames( className, 'components-choice-menu' ); + return ( -
-
{ label }
+
+ { label && +
{ label }
+ } { choices.map( ( item ) => { const isSelected = value === item.value; diff --git a/components/menu-items/menu-items-toggle.js b/components/menu-items/menu-items-toggle.js index 3d70f4316e4efc..e7b4e97a22f51f 100644 --- a/components/menu-items/menu-items-toggle.js +++ b/components/menu-items/menu-items-toggle.js @@ -10,7 +10,7 @@ function MenuItemsToggle( { label, isSelected, onClick, shortcut } ) { if ( isSelected ) { return ( @@ -22,7 +22,7 @@ function MenuItemsToggle( { label, isSelected, onClick, shortcut } ) { return ( - + { this.state.showCopyConfirmation ? __( 'Copied!' ) : __( 'Copy' ) }
diff --git a/editor/edit-post/header/copy-content-button/index.js b/editor/edit-post/header/copy-content-button/index.js new file mode 100644 index 00000000000000..ed8045165bf038 --- /dev/null +++ b/editor/edit-post/header/copy-content-button/index.js @@ -0,0 +1,51 @@ +/** + * External dependencies + */ +import { connect } from 'react-redux'; + +/** + * WordPress dependencies + */ +import { ClipboardButton } from '@wordpress/components'; +import { Component } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import { getEditedPostContent } from '../../../store/selectors'; + +class CopyContentButton extends Component { + constructor() { + super( ...arguments ); + this.state = { hasCopied: false }; + this.onCopy = this.onCopy.bind( this ); + this.onFinishCopy = this.onFinishCopy.bind( this ); + } + onCopy() { + this.setState( { hasCopied: true } ); + } + onFinishCopy() { + this.setState( { hasCopied: false } ); + } + render() { + return ( + + { this.state.hasCopied ? + __( 'Copied!' ) : + __( 'Copy All Content' ) } + + ); + } +} + +export default connect( + ( state ) => ( { + editedPostContent: getEditedPostContent( state ), + } ) +)( CopyContentButton ); diff --git a/editor/edit-post/header/editor-actions/index.js b/editor/edit-post/header/editor-actions/index.js new file mode 100644 index 00000000000000..43127de4faf22b --- /dev/null +++ b/editor/edit-post/header/editor-actions/index.js @@ -0,0 +1,20 @@ +/** + * WordPress dependencies + */ +import { MenuItemsGroup } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import CopyContentButton from '../copy-content-button'; + +export default function EditorActions() { + return ( + + + + ); +} diff --git a/editor/edit-post/header/ellipsis-menu/index.js b/editor/edit-post/header/ellipsis-menu/index.js index d78f028d0feb61..be3d8d6ba3e8ed 100644 --- a/editor/edit-post/header/ellipsis-menu/index.js +++ b/editor/edit-post/header/ellipsis-menu/index.js @@ -10,6 +10,7 @@ import { IconButton, Dropdown } from '@wordpress/components'; import './style.scss'; import ModeSwitcher from '../mode-switcher'; import FixedToolbarToggle from '../fixed-toolbar-toggle'; +import EditorActions from '../editor-actions'; const element = (
+
+
) } /> diff --git a/editor/edit-post/header/fixed-toolbar-toggle/index.js b/editor/edit-post/header/fixed-toolbar-toggle/index.js index dcc620dab7432e..d9f2d2af3c118c 100644 --- a/editor/edit-post/header/fixed-toolbar-toggle/index.js +++ b/editor/edit-post/header/fixed-toolbar-toggle/index.js @@ -21,7 +21,7 @@ function FeatureToggle( { onToggle, active, onMobile } ) { } return (