diff --git a/docs/reference-guides/data/data-core-customize-widgets.md b/docs/reference-guides/data/data-core-customize-widgets.md index 8796f4cfea5ddf..b0c0fc8818f327 100644 --- a/docs/reference-guides/data/data-core-customize-widgets.md +++ b/docs/reference-guides/data/data-core-customize-widgets.md @@ -78,6 +78,7 @@ _Parameters_ - _value_ `boolean|Object`: Whether the inserter should be opened (true) or closed (false). To specify an insertion point, use an object. - _value.rootClientId_ `string`: The root client ID to insert at. - _value.insertionIndex_ `number`: The index to insert at. +- _value.initialTab_ `string`: The id of the tab to display first when the block editor inserter is opened. A category corresponds to one of the tab ids defined in packages/block-editor/src/components/inserter/tabs.js. _Returns_ diff --git a/docs/reference-guides/data/data-core-edit-widgets.md b/docs/reference-guides/data/data-core-edit-widgets.md index 2dde89bf69ad73..f5268963882bab 100644 --- a/docs/reference-guides/data/data-core-edit-widgets.md +++ b/docs/reference-guides/data/data-core-edit-widgets.md @@ -215,6 +215,7 @@ _Parameters_ - _value_ `boolean|Object`: Whether the inserter should be opened (true) or closed (false). To specify an insertion point, use an object. - _value.rootClientId_ `string`: The root client ID to insert at. - _value.insertionIndex_ `number`: The index to insert at. +- _value.initialTab_ `string`: The id of the tab to display first when the block editor inserter is opened. A category corresponds to one of the tab ids defined in packages/block-editor/src/components/inserter/tabs.js. _Returns_ diff --git a/docs/reference-guides/data/data-core-editor.md b/docs/reference-guides/data/data-core-editor.md index be2276bbf03641..51126696942fad 100644 --- a/docs/reference-guides/data/data-core-editor.md +++ b/docs/reference-guides/data/data-core-editor.md @@ -1382,6 +1382,7 @@ _Parameters_ - _value_ `boolean|Object`: Whether the inserter should be opened (true) or closed (false). To specify an insertion point, use an object. - _value.rootClientId_ `string`: The root client ID to insert at. - _value.insertionIndex_ `number`: The index to insert at. +- _value.initialTab_ `string`: The id of the tab to display first when the block editor inserter is opened. A category corresponds to one of the tab ids defined in packages/block-editor/src/components/inserter/tabs.js. _Returns_ diff --git a/packages/block-editor/src/components/block-list/block.js b/packages/block-editor/src/components/block-list/block.js index 7690386764f6cc..f3cefd4741e9c4 100644 --- a/packages/block-editor/src/components/block-list/block.js +++ b/packages/block-editor/src/components/block-list/block.js @@ -616,6 +616,10 @@ function BlockListBlockProvider( props ) { ), isEditingDisabled: getBlockEditingMode( clientId ) === 'disabled', + hasEditableOutline: + getBlockEditingMode( clientId ) !== 'disabled' && + getBlockEditingMode( getBlockRootClientId( clientId ) ) === + 'disabled', className: hasLightBlockWrapper ? attributes.className : undefined, @@ -660,6 +664,7 @@ function BlockListBlockProvider( props ) { isBlockMovingMode, canInsertMovingBlock, isEditingDisabled, + hasEditableOutline, className, defaultClassName, } = selectedProps; @@ -695,6 +700,7 @@ function BlockListBlockProvider( props ) { isBlockMovingMode, canInsertMovingBlock, isEditingDisabled, + hasEditableOutline, isTemporarilyEditingAsBlocks, defaultClassName, mayDisplayControls, diff --git a/packages/block-editor/src/components/block-list/content.scss b/packages/block-editor/src/components/block-list/content.scss index a650710bfb119a..d309340ecca30e 100644 --- a/packages/block-editor/src/components/block-list/content.scss +++ b/packages/block-editor/src/components/block-list/content.scss @@ -300,35 +300,30 @@ _::-webkit-full-page-media, _:future, :root .has-multi-selection .block-editor-b } } -// Indicate which blocks are editable within a locked context. -// 1. User must be hovering an editor with renderingMode = 'template-lock'; or... -.is-template-locked:hover, -// ...a container block. -.block-editor-block-list__block:hover { - // 2. Look for locked blocks; or... - .block-editor-block-list__block.is-editing-disabled, - // ...container blocks that have locked children. - &:has(> .block-editor-block-list__block.is-editing-disabled) { - // 3. Highlight any unlocked children of that locked block. - & > .block-editor-block-list__block:not(.is-editing-disabled):not(.is-selected):not(.has-child-selected) { - &::after { - content: ""; - border-style: dotted; - position: absolute; - pointer-events: none; - top: $border-width; - left: $border-width; - right: $border-width; - bottom: $border-width; - border: 1px dotted var(--wp-admin-theme-color); - border-radius: $radius-block-ui - $border-width; - } +@keyframes block-editor-has-editable-outline__fade-out-animation { + from { + border-color: rgba(var(--wp-admin-theme-color--rgb), 1); + } + to { + border-color: rgba(var(--wp-admin-theme-color--rgb), 0); + } +} - &.is-hovered::after { - background: rgba(var(--wp-admin-theme-color--rgb), 0.1); - border: none; - } - } +.is-root-container:not([inert]) .block-editor-block-list__block.has-editable-outline { + &::after { + content: ""; + position: absolute; + pointer-events: none; + top: 0; + left: 0; + right: 0; + bottom: 0; + border: 1px dotted rgba(var(--wp-admin-theme-color--rgb), 1); + border-radius: $radius-block-ui; + animation: block-editor-has-editable-outline__fade-out-animation 0.3s ease-out; + animation-delay: 3s; + animation-fill-mode: forwards; + @include reduce-motion("animation"); } } diff --git a/packages/block-editor/src/components/block-list/use-block-props/index.js b/packages/block-editor/src/components/block-list/use-block-props/index.js index 9c7ae30b5997a5..7f3b9f1bb05e24 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/index.js +++ b/packages/block-editor/src/components/block-list/use-block-props/index.js @@ -95,6 +95,7 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) { isBlockMovingMode, canInsertMovingBlock, isEditingDisabled, + hasEditableOutline, isTemporarilyEditingAsBlocks, defaultClassName, } = useContext( PrivateBlockContext ); @@ -152,6 +153,7 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) { 'is-block-moving-mode': isBlockMovingMode, 'can-insert-moving-block': canInsertMovingBlock, 'is-editing-disabled': isEditingDisabled, + 'has-editable-outline': hasEditableOutline, 'is-content-locked-temporarily-editing-as-blocks': isTemporarilyEditingAsBlocks, }, diff --git a/packages/block-editor/src/components/inserter/library.js b/packages/block-editor/src/components/inserter/library.js index 7d462b343c310d..870bb7b91b29c3 100644 --- a/packages/block-editor/src/components/inserter/library.js +++ b/packages/block-editor/src/components/inserter/library.js @@ -21,6 +21,7 @@ function InserterLibrary( showMostUsedBlocks = false, __experimentalInsertionIndex, __experimentalFilterValue, + initialInserterTab, onSelect = noop, shouldFocusBlock = false, }, @@ -46,6 +47,7 @@ function InserterLibrary( isAppender={ isAppender } showInserterHelpPanel={ showInserterHelpPanel } showMostUsedBlocks={ showMostUsedBlocks } + initialInserterTab={ initialInserterTab } __experimentalInsertionIndex={ __experimentalInsertionIndex } __experimentalFilterValue={ __experimentalFilterValue } shouldFocusBlock={ shouldFocusBlock } diff --git a/packages/block-editor/src/components/inserter/menu.js b/packages/block-editor/src/components/inserter/menu.js index 6a38e52cbffba1..4527318813a3da 100644 --- a/packages/block-editor/src/components/inserter/menu.js +++ b/packages/block-editor/src/components/inserter/menu.js @@ -45,6 +45,7 @@ function InserterMenu( showMostUsedBlocks, __experimentalFilterValue = '', shouldFocusBlock = true, + initialInserterTab, }, ref ) { @@ -56,8 +57,9 @@ function InserterMenu( const [ patternFilter, setPatternFilter ] = useState( 'all' ); const [ selectedMediaCategory, setSelectedMediaCategory ] = useState( null ); - const [ selectedTab, setSelectedTab ] = useState( null ); - + const [ selectedTab, setSelectedTab ] = useState( + initialInserterTab || null + ); const [ destinationRootClientId, onInsertBlocks, onToggleInsertionPoint ] = useInsertionPoint( { rootClientId, @@ -259,6 +261,7 @@ function InserterMenu( showMedia={ showMedia } onSelect={ handleSetSelectedTab } tabsContents={ inserterTabsContents } + initialTabId={ initialInserterTab } /> ) } { ! delayedFilterValue && ! showAsTabs && ( diff --git a/packages/block-editor/src/components/inserter/tabs.js b/packages/block-editor/src/components/inserter/tabs.js index 4795c3ce4fdc24..1ea917596711ac 100644 --- a/packages/block-editor/src/components/inserter/tabs.js +++ b/packages/block-editor/src/components/inserter/tabs.js @@ -33,6 +33,7 @@ function InserterTabs( { showMedia = false, onSelect, tabsContents, + initialTabId, } ) { const tabs = [ blocksTab, @@ -40,9 +41,13 @@ function InserterTabs( { showMedia && mediaTab, ].filter( Boolean ); + initialTabId = !! tabs.find( ( { name } ) => initialTabId === name ) + ? initialTabId + : 'blocks'; + return (
- + { tabs.map( ( tab ) => ( diff --git a/packages/block-editor/src/components/use-flash-editable-blocks/index.js b/packages/block-editor/src/components/use-flash-editable-blocks/index.js new file mode 100644 index 00000000000000..56e4e64a17ec86 --- /dev/null +++ b/packages/block-editor/src/components/use-flash-editable-blocks/index.js @@ -0,0 +1,54 @@ +/** + * WordPress dependencies + */ +import { useRefEffect } from '@wordpress/compose'; +import { useSelect } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import { store as blockEditorStore } from '../../store'; +import { unlock } from '../../lock-unlock'; + +export default function useFlashEditableBlocks( rootClientId = '' ) { + const { getEnabledClientIdsTree } = unlock( useSelect( blockEditorStore ) ); + + return useRefEffect( ( element ) => { + const flashEditableBlocks = () => { + getEnabledClientIdsTree( rootClientId ).forEach( + ( { clientId } ) => { + const blockElement = element.querySelector( + `[data-block="${ clientId }"]` + ); + if ( ! blockElement ) { + return; + } + blockElement.classList.remove( 'has-editable-outline' ); + // Force reflow to trigger the animation. + // eslint-disable-next-line no-unused-expressions + blockElement.offsetWidth; + blockElement.classList.add( 'has-editable-outline' ); + } + ); + }; + + const handleClick = ( event ) => { + const shouldFlash = + event.target === element || + event.target.classList.contains( 'is-root-container' ); + if ( ! shouldFlash ) { + return; + } + if ( event.defaultPrevented ) { + return; + } + event.preventDefault(); + flashEditableBlocks(); + }; + + element.addEventListener( 'click', handleClick ); + return () => { + element.removeEventListener( 'click', handleClick ); + }; + } ); +} diff --git a/packages/block-editor/src/private-apis.js b/packages/block-editor/src/private-apis.js index 74bf4af421dfbb..555d0dd574fef7 100644 --- a/packages/block-editor/src/private-apis.js +++ b/packages/block-editor/src/private-apis.js @@ -24,6 +24,7 @@ import { import { usesContextKey } from './components/rich-text/format-edit'; import { ExperimentalBlockCanvas } from './components/block-canvas'; import { getDuotoneFilter } from './components/duotone/utils'; +import useFlashEditableBlocks from './components/use-flash-editable-blocks'; /** * Private @wordpress/block-editor APIs. @@ -52,4 +53,5 @@ lock( privateApis, { ReusableBlocksRenameHint, useReusableBlocksRenameHint, usesContextKey, + useFlashEditableBlocks, } ); diff --git a/packages/block-library/src/block/edit.js b/packages/block-library/src/block/edit.js index cd04e09605ff40..8c2b70624ccf8f 100644 --- a/packages/block-library/src/block/edit.js +++ b/packages/block-library/src/block/edit.js @@ -35,7 +35,9 @@ import { parse, cloneBlock } from '@wordpress/blocks'; */ import { unlock } from '../lock-unlock'; -const { useLayoutClasses } = unlock( blockEditorPrivateApis ); +const { useLayoutClasses, useFlashEditableBlocks } = unlock( + blockEditorPrivateApis +); const { PARTIAL_SYNCING_SUPPORTED_BLOCKS } = unlock( patternsPrivateApis ); function isPartiallySynced( block ) { @@ -273,6 +275,7 @@ export default function ReusableBlockEdit( { const layoutClasses = useLayoutClasses( { layout }, name ); const blockProps = useBlockProps( { + ref: useFlashEditableBlocks( patternClientId ), className: classnames( 'block-library-block__reusable-block-container', layout && layoutClasses, diff --git a/packages/block-library/src/editor.scss b/packages/block-library/src/editor.scss index e3642868034a5a..7151051f545441 100644 --- a/packages/block-library/src/editor.scss +++ b/packages/block-library/src/editor.scss @@ -54,6 +54,7 @@ @import "./query-pagination-numbers/editor.scss"; @import "./post-featured-image/editor.scss"; @import "./post-comments-form/editor.scss"; +@import "./post-content/editor.scss"; @import "./editor-elements.scss"; diff --git a/packages/block-library/src/post-content/edit.js b/packages/block-library/src/post-content/edit.js index 041a3b4fa02f61..ba3e8241c0cf57 100644 --- a/packages/block-library/src/post-content/edit.js +++ b/packages/block-library/src/post-content/edit.js @@ -8,13 +8,15 @@ import { RecursionProvider, useHasRecursion, Warning, + InnerBlocks, + store as blockEditorStore, } from '@wordpress/block-editor'; -import { - useEntityProp, - useEntityBlockEditor, - store as coreStore, -} from '@wordpress/core-data'; +import { useEntityProp, useEntityBlockEditor } from '@wordpress/core-data'; +import { Button } from '@wordpress/components'; +import { isUnmodifiedDefaultBlock } from '@wordpress/blocks'; +import { useMemo } from '@wordpress/element'; import { useSelect } from '@wordpress/data'; + /** * Internal dependencies */ @@ -45,7 +47,31 @@ function ReadOnlyContent( { ); } -function EditableContent( { context = {} } ) { +function InsertPatternButton( { rootClientId } ) { + const setIsInserterOpened = useSelect( + ( select ) => + select( blockEditorStore ).getSettings() + .__experimentalSetIsInserterOpened, + [] + ); + return ( + + ); +} + +function EditableContent( { context = {}, clientId } ) { const { postType, postId } = context; const [ blocks, onInput, onChange ] = useEntityBlockEditor( @@ -54,20 +80,20 @@ function EditableContent( { context = {} } ) { { id: postId } ); - const entityRecord = useSelect( - ( select ) => { - return select( coreStore ).getEntityRecord( - 'postType', - postType, - postId - ); - }, - [ postType, postId ] - ); + const hasBlocks = !! blocks?.length; + const isDefaultBlock = + blocks?.length === 1 && isUnmodifiedDefaultBlock( blocks[ 0 ] ); + const hasContent = hasBlocks && ! isDefaultBlock; - const hasInnerBlocks = !! entityRecord?.content?.raw || blocks?.length; - - const initialInnerBlocks = [ [ 'core/paragraph' ] ]; + const Appender = useMemo( + () => () => ( + <> + { ! isDefaultBlock && } + + + ), + [ isDefaultBlock, clientId ] + ); const props = useInnerBlocksProps( useBlockProps( { className: 'entry-content' } ), @@ -75,7 +101,7 @@ function EditableContent( { context = {} } ) { value: blocks, onInput, onChange, - template: ! hasInnerBlocks ? initialInnerBlocks : undefined, + renderAppender: hasContent ? undefined : Appender, } ); return
; @@ -141,6 +167,7 @@ function RecursionError() { export default function PostContentEdit( { context, __unstableLayoutClassNames: layoutClassNames, + clientId, } ) { const { postId: contextPostId, postType: contextPostType } = context; const hasAlreadyRendered = useHasRecursion( contextPostId ); @@ -155,6 +182,7 @@ export default function PostContentEdit( { ) : ( diff --git a/packages/block-library/src/post-content/editor.scss b/packages/block-library/src/post-content/editor.scss new file mode 100644 index 00000000000000..98dc51093c9f49 --- /dev/null +++ b/packages/block-library/src/post-content/editor.scss @@ -0,0 +1,13 @@ +.wp-block-post-content { + .block-list-appender { + position: relative; + } + + .block-editor-default-block-appender:not(.is-selected):not(.has-child-selected) { + display: block; + } +} + +.wp-block-post-content__insert-pattern { + font-size: $editor-font-size; +} diff --git a/packages/customize-widgets/src/store/actions.js b/packages/customize-widgets/src/store/actions.js index 8656ef8854c9f5..528f2c395d57e6 100644 --- a/packages/customize-widgets/src/store/actions.js +++ b/packages/customize-widgets/src/store/actions.js @@ -7,6 +7,8 @@ * use an object. * @param {string} value.rootClientId The root client ID to insert at. * @param {number} value.insertionIndex The index to insert at. + * @param {string} value.initialTab The id of the tab to display first when the block editor inserter is opened. + * A category corresponds to one of the tab ids defined in packages/block-editor/src/components/inserter/tabs.js. * * @example * ```js diff --git a/packages/edit-widgets/src/store/actions.js b/packages/edit-widgets/src/store/actions.js index 8124ace66bdb3a..40d48bd85fab25 100644 --- a/packages/edit-widgets/src/store/actions.js +++ b/packages/edit-widgets/src/store/actions.js @@ -348,6 +348,8 @@ export function setIsWidgetAreaOpen( clientId, isOpen ) { * use an object. * @param {string} value.rootClientId The root client ID to insert at. * @param {number} value.insertionIndex The index to insert at. + * @param {string} value.initialTab The id of the tab to display first when the block editor inserter is opened. + * A category corresponds to one of the tab ids defined in packages/block-editor/src/components/inserter/tabs.js. * * @return {Object} Action object. */ diff --git a/packages/editor/src/components/editor-canvas/edit-template-blocks-notification.js b/packages/editor/src/components/editor-canvas/edit-template-blocks-notification.js index 566311e20cadc2..c4ac494ba3dbda 100644 --- a/packages/editor/src/components/editor-canvas/edit-template-blocks-notification.js +++ b/packages/editor/src/components/editor-canvas/edit-template-blocks-notification.js @@ -27,10 +27,6 @@ import { store as editorStore } from '../../store'; * editor iframe canvas. */ export default function EditTemplateBlocksNotification( { contentRef } ) { - const renderingMode = useSelect( - ( select ) => select( editorStore ).getRenderingMode(), - [] - ); const { getNotices } = useSelect( noticesStore ); const { createInfoNotice, removeNotice } = useDispatch( noticesStore ); @@ -42,18 +38,17 @@ export default function EditTemplateBlocksNotification( { contentRef } ) { useEffect( () => { const handleClick = async ( event ) => { - if ( renderingMode !== 'template-locked' ) { - return; - } if ( ! event.target.classList.contains( 'is-root-container' ) ) { return; } + const isNoticeAlreadyShowing = getNotices().some( ( notice ) => notice.id === lastNoticeId.current ); if ( isNoticeAlreadyShowing ) { return; } + const { notice } = await createInfoNotice( __( 'Edit your template to edit this block.' ), { @@ -71,9 +66,6 @@ export default function EditTemplateBlocksNotification( { contentRef } ) { }; const handleDblClick = ( event ) => { - if ( renderingMode !== 'template-locked' ) { - return; - } if ( ! event.target.classList.contains( 'is-root-container' ) ) { return; } @@ -90,7 +82,7 @@ export default function EditTemplateBlocksNotification( { contentRef } ) { canvas?.removeEventListener( 'click', handleClick ); canvas?.removeEventListener( 'dblclick', handleDblClick ); }; - }, [ lastNoticeId, renderingMode, contentRef.current ] ); + }, [ lastNoticeId, contentRef.current ] ); return ( {}; @@ -287,9 +288,11 @@ function EditorCanvas( { const localRef = useRef(); const typewriterRef = useTypewriter(); + const flashEditableBlocksRef = useFlashEditableBlocks(); const contentRef = useMergeRefs( [ localRef, renderingMode === 'post-only' ? typewriterRef : noop, + renderingMode === 'template-locked' ? flashEditableBlocksRef : noop, ] ); return ( @@ -364,8 +367,7 @@ function EditorCanvas( { 'is-' + deviceType.toLowerCase() + '-preview', renderingMode !== 'post-only' ? 'wp-site-blocks' - : `${ blockListLayoutClass } wp-block-post-content`, // Ensure root level blocks receive default/flow blockGap styling rules. - renderingMode !== 'all' && 'is-' + renderingMode + : `${ blockListLayoutClass } wp-block-post-content` // Ensure root level blocks receive default/flow blockGap styling rules. ) } layout={ blockListLayout } dropZoneElement={ @@ -377,7 +379,9 @@ function EditorCanvas( { } renderAppender={ renderAppender } /> - + { renderingMode === 'template-locked' && ( + + ) } { children } diff --git a/packages/editor/src/components/inserter-sidebar/index.js b/packages/editor/src/components/inserter-sidebar/index.js index 7db4335309935a..783294dddee7d1 100644 --- a/packages/editor/src/components/inserter-sidebar/index.js +++ b/packages/editor/src/components/inserter-sidebar/index.js @@ -20,14 +20,18 @@ import { unlock } from '../../lock-unlock'; import { store as editorStore } from '../../store'; export default function InserterSidebar() { - const { insertionPoint, showMostUsedBlocks } = useSelect( ( select ) => { - const { getInsertionPoint } = unlock( select( editorStore ) ); - const { get } = select( preferencesStore ); - return { - insertionPoint: getInsertionPoint(), - showMostUsedBlocks: get( 'core', 'mostUsedBlocks' ), - }; - }, [] ); + const { insertionPoint, initialInserterTab, showMostUsedBlocks } = + useSelect( ( select ) => { + const { getInsertionPoint, getInserterInitialTab } = unlock( + select( editorStore ) + ); + const { get } = select( preferencesStore ); + return { + insertionPoint: getInsertionPoint(), + initialInserterTab: getInserterInitialTab(), + showMostUsedBlocks: get( 'core', 'mostUsedBlocks' ), + }; + }, [] ); const { setIsInserterOpened } = useDispatch( editorStore ); const isMobileViewport = useViewportMatch( 'medium', '<' ); @@ -64,6 +68,7 @@ export default function InserterSidebar() { __experimentalInsertionIndex={ insertionPoint.insertionIndex } + initialInserterTab={ initialInserterTab } __experimentalFilterValue={ insertionPoint.filterValue } ref={ libraryRef } /> diff --git a/packages/editor/src/store/actions.js b/packages/editor/src/store/actions.js index a0330321bac8f7..9f0bf4700c4715 100644 --- a/packages/editor/src/store/actions.js +++ b/packages/editor/src/store/actions.js @@ -697,6 +697,8 @@ export function removeEditorPanel( panelName ) { * use an object. * @param {string} value.rootClientId The root client ID to insert at. * @param {number} value.insertionIndex The index to insert at. + * @param {string} value.initialTab The id of the tab to display first when the block editor inserter is opened. + * A category corresponds to one of the tab ids defined in packages/block-editor/src/components/inserter/tabs.js. * * @return {Object} Action object. */ diff --git a/packages/editor/src/store/private-selectors.js b/packages/editor/src/store/private-selectors.js index e276859f884038..f3dd3f4404e24e 100644 --- a/packages/editor/src/store/private-selectors.js +++ b/packages/editor/src/store/private-selectors.js @@ -25,7 +25,11 @@ const EMPTY_INSERTION_POINT = { export const getInsertionPoint = createRegistrySelector( ( select ) => ( state ) => { if ( typeof state.blockInserterPanel === 'object' ) { - return state.blockInserterPanel; + return { + rootClientId: state.blockInserterPanel?.rootClientId, + insertionIndex: state.blockInserterPanel?.insertionIndex, + filterValue: state.blockInserterPanel?.filterValue, + }; } if ( getRenderingMode( state ) === 'template-locked' ) { @@ -46,6 +50,21 @@ export const getInsertionPoint = createRegistrySelector( } ); +/** + * Get the initial tab id for the inserter. + * A category corresponds to one of the tab ids defined in packages/block-editor/src/components/inserter/tabs.js. + * + * @param {Object} state Global application state. + * + * @return {string} The initial tab category to open when the inserter is opened. + */ +export const getInserterInitialTab = createRegistrySelector( + () => ( state ) => + typeof state.blockInserterPanel === 'object' + ? state.blockInserterPanel?.initialTab + : null +); + export function getListViewToggleRef( state ) { return state.listViewToggleRef; }