diff --git a/packages/edit-widgets/src/components/header/document-tools/index.js b/packages/edit-widgets/src/components/header/document-tools/index.js new file mode 100644 index 0000000000000..8cac7590be5e8 --- /dev/null +++ b/packages/edit-widgets/src/components/header/document-tools/index.js @@ -0,0 +1,130 @@ +/** + * WordPress dependencies + */ +import { useSelect, useDispatch } from '@wordpress/data'; +import { __, _x } from '@wordpress/i18n'; +import { Button, ToolbarItem } from '@wordpress/components'; +import { + NavigableToolbar, + store as blockEditorStore, + privateApis as blockEditorPrivateApis, +} from '@wordpress/block-editor'; +import { listView, plus } from '@wordpress/icons'; +import { useCallback, useRef } from '@wordpress/element'; +import { useViewportMatch } from '@wordpress/compose'; + +/** + * Internal dependencies + */ +import UndoButton from '../undo-redo/undo'; +import RedoButton from '../undo-redo/redo'; +import useLastSelectedWidgetArea from '../../../hooks/use-last-selected-widget-area'; +import { store as editWidgetsStore } from '../../../store'; +import { unlock } from '../../../lock-unlock'; + +const { useShouldContextualToolbarShow } = unlock( blockEditorPrivateApis ); + +function DocumentTools( { setListViewToggleElement } ) { + const isMediumViewport = useViewportMatch( 'medium' ); + const inserterButton = useRef(); + const widgetAreaClientId = useLastSelectedWidgetArea(); + const isLastSelectedWidgetAreaOpen = useSelect( + ( select ) => + select( editWidgetsStore ).getIsWidgetAreaOpen( + widgetAreaClientId + ), + [ widgetAreaClientId ] + ); + const { isInserterOpen, isListViewOpen } = useSelect( ( select ) => { + const { isInserterOpened, isListViewOpened } = + select( editWidgetsStore ); + return { + isInserterOpen: isInserterOpened(), + isListViewOpen: isListViewOpened(), + }; + }, [] ); + const { setIsWidgetAreaOpen, setIsInserterOpened, setIsListViewOpened } = + useDispatch( editWidgetsStore ); + const { selectBlock } = useDispatch( blockEditorStore ); + const handleClick = () => { + if ( isInserterOpen ) { + // Focusing the inserter button closes the inserter popover. + setIsInserterOpened( false ); + } else { + if ( ! isLastSelectedWidgetAreaOpen ) { + // Select the last selected block if hasn't already. + selectBlock( widgetAreaClientId ); + // Open the last selected widget area when opening the inserter. + setIsWidgetAreaOpen( widgetAreaClientId, true ); + } + // The DOM updates resulting from selectBlock() and setIsInserterOpened() calls are applied the + // same tick and pretty much in a random order. The inserter is closed if any other part of the + // app receives focus. If selectBlock() happens to take effect after setIsInserterOpened() then + // the inserter is visible for a brief moment and then gets auto-closed due to focus moving to + // the selected block. + window.requestAnimationFrame( () => setIsInserterOpened( true ) ); + } + }; + + const toggleListView = useCallback( + () => setIsListViewOpened( ! isListViewOpen ), + [ setIsListViewOpened, isListViewOpen ] + ); + + const { + shouldShowContextualToolbar, + canFocusHiddenToolbar, + fixedToolbarCanBeFocused, + } = useShouldContextualToolbarShow(); + // If there's a block toolbar to be focused, disable the focus shortcut for the document toolbar. + // There's a fixed block toolbar when the fixed toolbar option is enabled or when the browser width is less than the large viewport. + const blockToolbarCanBeFocused = + shouldShowContextualToolbar || + canFocusHiddenToolbar || + fixedToolbarCanBeFocused; + + return ( + + { + event.preventDefault(); + } } + onClick={ handleClick } + icon={ plus } + /* translators: button label text should, if possible, be under 16 + characters. */ + label={ _x( + 'Toggle block inserter', + 'Generic label for block inserter button' + ) } + /> + { isMediumViewport && ( + <> + + + + + ) } + + ); +} + +export default DocumentTools; diff --git a/packages/edit-widgets/src/components/header/index.js b/packages/edit-widgets/src/components/header/index.js index 0308c2c2171e2..29afc1eba59b8 100644 --- a/packages/edit-widgets/src/components/header/index.js +++ b/packages/edit-widgets/src/components/header/index.js @@ -1,90 +1,20 @@ /** * WordPress dependencies */ -import { useSelect, useDispatch } from '@wordpress/data'; -import { __, _x } from '@wordpress/i18n'; -import { Button, ToolbarItem, VisuallyHidden } from '@wordpress/components'; -import { - NavigableToolbar, - store as blockEditorStore, - privateApis as blockEditorPrivateApis, -} from '@wordpress/block-editor'; +import { __ } from '@wordpress/i18n'; +import { VisuallyHidden } from '@wordpress/components'; import { PinnedItems } from '@wordpress/interface'; -import { listView, plus } from '@wordpress/icons'; -import { useCallback, useRef } from '@wordpress/element'; import { useViewportMatch } from '@wordpress/compose'; /** * Internal dependencies */ +import DocumentTools from './document-tools'; import SaveButton from '../save-button'; -import UndoButton from './undo-redo/undo'; -import RedoButton from './undo-redo/redo'; import MoreMenu from '../more-menu'; -import useLastSelectedWidgetArea from '../../hooks/use-last-selected-widget-area'; -import { store as editWidgetsStore } from '../../store'; -import { unlock } from '../../lock-unlock'; - -const { useShouldContextualToolbarShow } = unlock( blockEditorPrivateApis ); function Header( { setListViewToggleElement } ) { const isMediumViewport = useViewportMatch( 'medium' ); - const inserterButton = useRef(); - const widgetAreaClientId = useLastSelectedWidgetArea(); - const isLastSelectedWidgetAreaOpen = useSelect( - ( select ) => - select( editWidgetsStore ).getIsWidgetAreaOpen( - widgetAreaClientId - ), - [ widgetAreaClientId ] - ); - const { isInserterOpen, isListViewOpen } = useSelect( ( select ) => { - const { isInserterOpened, isListViewOpened } = - select( editWidgetsStore ); - return { - isInserterOpen: isInserterOpened(), - isListViewOpen: isListViewOpened(), - }; - }, [] ); - const { setIsWidgetAreaOpen, setIsInserterOpened, setIsListViewOpened } = - useDispatch( editWidgetsStore ); - const { selectBlock } = useDispatch( blockEditorStore ); - const handleClick = () => { - if ( isInserterOpen ) { - // Focusing the inserter button closes the inserter popover. - setIsInserterOpened( false ); - } else { - if ( ! isLastSelectedWidgetAreaOpen ) { - // Select the last selected block if hasn't already. - selectBlock( widgetAreaClientId ); - // Open the last selected widget area when opening the inserter. - setIsWidgetAreaOpen( widgetAreaClientId, true ); - } - // The DOM updates resulting from selectBlock() and setIsInserterOpened() calls are applied the - // same tick and pretty much in a random order. The inserter is closed if any other part of the - // app receives focus. If selectBlock() happens to take effect after setIsInserterOpened() then - // the inserter is visible for a brief moment and then gets auto-closed due to focus moving to - // the selected block. - window.requestAnimationFrame( () => setIsInserterOpened( true ) ); - } - }; - - const toggleListView = useCallback( - () => setIsListViewOpened( ! isListViewOpen ), - [ setIsListViewOpened, isListViewOpen ] - ); - - const { - shouldShowContextualToolbar, - canFocusHiddenToolbar, - fixedToolbarCanBeFocused, - } = useShouldContextualToolbarShow(); - // If there's a block toolbar to be focused, disable the focus shortcut for the document toolbar. - // There's a fixed block toolbar when the fixed toolbar option is enabled or when the browser width is less than the large viewport. - const blockToolbarCanBeFocused = - shouldShowContextualToolbar || - canFocusHiddenToolbar || - fixedToolbarCanBeFocused; return ( <> @@ -103,48 +33,9 @@ function Header( { setListViewToggleElement } ) { { __( 'Widgets' ) } ) } - - { - event.preventDefault(); - } } - onClick={ handleClick } - icon={ plus } - /* translators: button label text should, if possible, be under 16 - characters. */ - label={ _x( - 'Toggle block inserter', - 'Generic label for block inserter button' - ) } - /> - { isMediumViewport && ( - <> - - - - - ) } - +