diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index bb4dc1725bc3f..ecd6db1713a6a 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -173,6 +173,10 @@ _Related_ Undocumented declaration. +### BlockLockToolbar + +Undocumented declaration. + ### BlockMover _Related_ diff --git a/packages/block-editor/src/components/block-preview/README.md b/packages/block-editor/src/components/block-preview/README.md index 6df2cb6773878..f04053b1e5df6 100644 --- a/packages/block-editor/src/components/block-preview/README.md +++ b/packages/block-editor/src/components/block-preview/README.md @@ -35,16 +35,9 @@ Width of the preview container in pixels. Controls at what size the blocks will Padding for the preview container body. -### `__experimentalLive` +### `__experimentalScale` - **Type** `Boolean` -- **Default:** `false` +- **Default:** `true` -Enables displaying previews without an iframe container. - -### `__experimentalOnClick` - -- **Type** `Function` -- **Default:** `undefined` - -Use this callback in combination with `__experimentalLive`. The callback is attached to the preview container element. +Enables displaying previews without an iframe container. \ No newline at end of file diff --git a/packages/block-editor/src/components/block-preview/auto.js b/packages/block-editor/src/components/block-preview/auto.js index d2eca43010a7c..c004bb9f8d4c9 100644 --- a/packages/block-editor/src/components/block-preview/auto.js +++ b/packages/block-editor/src/components/block-preview/auto.js @@ -23,6 +23,7 @@ function AutoBlockPreview( { viewportWidth, __experimentalPadding, __experimentalMinHeight, + __experimentalScale = true, } ) { const [ containerResizeListener, @@ -58,7 +59,10 @@ function AutoBlockPreview( { // Initialize on render instead of module top level, to avoid circular dependency issues. MemoizedBlockList = MemoizedBlockList || pure( BlockList ); - const scale = containerWidth / viewportWidth; + const scale = + __experimentalScale === true + ? containerWidth / viewportWidth + : __experimentalScale; return (
@@ -97,7 +101,10 @@ function AutoBlockPreview( { tabIndex={ -1 } style={ { position: 'absolute', - width: viewportWidth, + width: + __experimentalScale === true + ? viewportWidth + : 'calc( 100% / ' + __experimentalScale + ' )', height: contentHeight, pointerEvents: 'none', // This is a catch-all max-height for patterns. diff --git a/packages/block-editor/src/components/block-preview/index.js b/packages/block-editor/src/components/block-preview/index.js index d27f6235a658c..37b4fd4ef280b 100644 --- a/packages/block-editor/src/components/block-preview/index.js +++ b/packages/block-editor/src/components/block-preview/index.js @@ -18,7 +18,6 @@ import { memo, useMemo } from '@wordpress/element'; * Internal dependencies */ import BlockEditorProvider from '../provider'; -import LiveBlockPreview from './live'; import AutoHeightBlockPreview from './auto'; import { store as blockEditorStore } from '../../store'; import { BlockListItems } from '../block-list'; @@ -27,8 +26,7 @@ export function BlockPreview( { blocks, __experimentalPadding = 0, viewportWidth = 1200, - __experimentalLive = false, - __experimentalOnClick, + __experimentalScale = true, __experimentalMinHeight, } ) { const originalSettings = useSelect( @@ -46,15 +44,12 @@ export function BlockPreview( { } return ( - { __experimentalLive ? ( - - ) : ( - - ) } + ); } diff --git a/packages/block-editor/src/components/block-preview/live.js b/packages/block-editor/src/components/block-preview/live.js deleted file mode 100644 index 792740bb2c02b..0000000000000 --- a/packages/block-editor/src/components/block-preview/live.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * WordPress dependencies - */ -import { Disabled } from '@wordpress/components'; - -/** - * Internal dependencies - */ -import BlockList from '../block-list'; - -export default function LiveBlockPreview( { onClick } ) { - return ( -
- - - -
- ); -} diff --git a/packages/block-editor/src/components/block-tools/style.scss b/packages/block-editor/src/components/block-tools/style.scss index 32abd4aafb2c5..c4643421514b6 100644 --- a/packages/block-editor/src/components/block-tools/style.scss +++ b/packages/block-editor/src/components/block-tools/style.scss @@ -52,7 +52,8 @@ .block-editor-block-list__empty-block-inserter, .block-editor-default-block-appender, .block-editor-block-list__insertion-point-inserter, -.block-editor-block-list__block-popover-inserter { +.block-editor-block-list__block-popover-inserter, +.edit-site-block-list-exploded__inserter { .block-editor-inserter__toggle.components-button.has-icon { // Basic look background: $gray-900; @@ -70,11 +71,13 @@ } } } - -.block-editor-block-list__insertion-point-inserter .block-editor-inserter__toggle.components-button.has-icon { - background: var(--wp-admin-theme-color); - &:hover { - background: $gray-900; +.edit-site-block-list-exploded__inserter, +.block-editor-block-list__insertion-point-inserter { + .block-editor-inserter__toggle.components-button.has-icon { + background: var(--wp-admin-theme-color); + &:hover { + background: $gray-900; + } } } diff --git a/packages/block-editor/src/components/index.js b/packages/block-editor/src/components/index.js index 8e6395f5b5d70..034874145ae08 100644 --- a/packages/block-editor/src/components/index.js +++ b/packages/block-editor/src/components/index.js @@ -108,6 +108,7 @@ export { default as BlockInspector } from './block-inspector'; export { default as BlockList } from './block-list'; export { useBlockProps } from './block-list/use-block-props'; export { LayoutStyle as __experimentalLayoutStyle } from './block-list/layout'; +export { default as BlockLockToolbar } from './block-lock/toolbar'; export { default as BlockMover } from './block-mover'; export { default as BlockPreview, diff --git a/packages/block-editor/src/components/inserter/quick-inserter.js b/packages/block-editor/src/components/inserter/quick-inserter.js index e3973cba6ac1c..bef05b2ae924e 100644 --- a/packages/block-editor/src/components/inserter/quick-inserter.js +++ b/packages/block-editor/src/components/inserter/quick-inserter.js @@ -65,9 +65,7 @@ export default function QuickInserter( { setInserterIsOpened: settings.__experimentalSetIsInserterOpened, prioritizePatterns: settings.__experimentalPreferPatternsOnRoot && - ! rootClientId && - index > 0 && - ( index < blockCount || blockCount === 0 ), + ! rootClientId, insertionIndex: index === -1 ? blockCount : index, }; }, diff --git a/packages/edit-site/src/components/block-editor/index.js b/packages/edit-site/src/components/block-editor/index.js index d90747db4ad10..8146b4b71ef88 100644 --- a/packages/edit-site/src/components/block-editor/index.js +++ b/packages/edit-site/src/components/block-editor/index.js @@ -40,6 +40,7 @@ import BlockInspectorButton from './block-inspector-button'; import EditTemplatePartMenuButton from '../edit-template-part-menu-button'; import BackButton from './back-button'; import ResizableEditor from './resizable-editor'; +import BlockListExploded from '../block-list-exploded'; const LAYOUT = { type: 'default', @@ -48,7 +49,7 @@ const LAYOUT = { }; export default function BlockEditor( { setIsInserterOpen } ) { - const { settings } = useSelect( + const { settings, editorMode } = useSelect( ( select ) => { let storedSettings = select( editSiteStore ).getSettings( setIsInserterOpen @@ -74,6 +75,7 @@ export default function BlockEditor( { setIsInserterOpen } ) { return { settings: storedSettings, + editorMode: select( editSiteStore ).getEditorMode(), }; }, [ setIsInserterOpen ] @@ -158,52 +160,58 @@ export default function BlockEditor( { setIsInserterOpen } ) { - { - // Clear selected block when clicking on the gray background. - if ( event.target === event.currentTarget ) { - clearSelectedBlock(); - } - } } - > - - - } + + { editorMode === 'visual' && ( + { + // Clear selected block when clicking on the gray background. + if ( event.target === event.currentTarget ) { + clearSelectedBlock(); + } + } } > - - - <__unstableBlockSettingsMenuFirstItem> - { ( { onClose } ) => ( - - ) } - - <__unstableBlockToolbarLastItem> - <__unstableBlockNameContext.Consumer> - { ( blockName ) => - blockName === 'core/navigation' && ( - - ) + + + - - + settings={ settings } + contentRef={ mergedRefs } + > + + + <__unstableBlockSettingsMenuFirstItem> + { ( { onClose } ) => ( + + ) } + + <__unstableBlockToolbarLastItem> + <__unstableBlockNameContext.Consumer> + { ( blockName ) => + blockName === 'core/navigation' && ( + + ) + } + + + + ) } ); diff --git a/packages/edit-site/src/components/block-list-exploded/README.md b/packages/edit-site/src/components/block-list-exploded/README.md new file mode 100644 index 0000000000000..8ec4ddda30e90 --- /dev/null +++ b/packages/edit-site/src/components/block-list-exploded/README.md @@ -0,0 +1,4 @@ +## BlockListExploded Component + +This is an experimental component being built to implement the exploded view in the site editor. +The potential goal for this component is to be a component that can be used by any block editor, so it's important to keep its dependencies minimal. (block-editor dependencies). Eventually, it should be moved to the `@wordpress/block-editor` package. \ No newline at end of file diff --git a/packages/edit-site/src/components/block-list-exploded/index.js b/packages/edit-site/src/components/block-list-exploded/index.js new file mode 100644 index 0000000000000..444ef0e17cd1b --- /dev/null +++ b/packages/edit-site/src/components/block-list-exploded/index.js @@ -0,0 +1,37 @@ +/** + * WordPress dependencies + */ +import { store as blockEditorStore, Inserter } from '@wordpress/block-editor'; +import { useSelect } from '@wordpress/data'; +import { pure } from '@wordpress/compose'; + +/** + * Internal dependencies + */ +import BlockListExplodedItem from './item'; + +const InserterBeforeBlock = pure( ( { clientId } ) => ( +
+ +
+) ); + +function BlockListExploded() { + const blockOrder = useSelect( ( select ) => { + return select( blockEditorStore ).getBlockOrder(); + }, [] ); + + return ( +
+ { blockOrder.map( ( clientId ) => ( +
+ + +
+ ) ) } + +
+ ); +} + +export default BlockListExploded; diff --git a/packages/edit-site/src/components/block-list-exploded/item.js b/packages/edit-site/src/components/block-list-exploded/item.js new file mode 100644 index 0000000000000..d7278da38171d --- /dev/null +++ b/packages/edit-site/src/components/block-list-exploded/item.js @@ -0,0 +1,89 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + +/** + * WordPress dependencies + */ +import { + store as blockEditorStore, + BlockPreview, + useBlockDisplayInformation, +} from '@wordpress/block-editor'; +import { useSelect, useDispatch } from '@wordpress/data'; +import { pure } from '@wordpress/compose'; +import { sprintf, __ } from '@wordpress/i18n'; +import { useMemo, useRef, useEffect } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import BlockListExplodedTopToolbar from './top-toolbar'; +import { store as editSiteStore } from '../../store'; + +function BlockListExplodedItem( { clientId } ) { + const blockWrapper = useRef(); + const { block, isSelected } = useSelect( + ( select ) => { + const { getBlock, isBlockSelected } = select( blockEditorStore ); + return { + block: getBlock( clientId ), + isSelected: isBlockSelected( clientId ), + }; + }, + [ clientId ] + ); + const { title } = useBlockDisplayInformation( clientId ); + const { selectBlock } = useDispatch( blockEditorStore ); + // If the exploded list becomes part of block-editor + // This mode also need to move into the block-editor store. + const { switchEditorMode } = useDispatch( editSiteStore ); + + // translators: %s: Type of block (i.e. Text, Image etc) + const blockLabel = sprintf( __( 'Block: %s' ), title ); + const blocksToPreview = useMemo( () => [ block ], [ block ] ); + + useEffect( () => { + if ( isSelected ) { + blockWrapper.current.focus(); + } + }, [ isSelected ] ); + + return ( +
+ { isSelected && ( + + ) } +
{ + const isFirstClick = event.detail === 1; + const isDoubleClick = event.detail === 2; + if ( isFirstClick ) { + selectBlock( clientId ); + } else if ( isDoubleClick ) { + switchEditorMode( 'visual' ); + } + } } + onKeyPress={ () => selectBlock( clientId ) } + onFocus={ () => selectBlock( clientId ) } + aria-label={ blockLabel } + tabIndex={ 0 } + > + +
+
+ ); +} + +export default pure( BlockListExplodedItem ); diff --git a/packages/edit-site/src/components/block-list-exploded/style.scss b/packages/edit-site/src/components/block-list-exploded/style.scss new file mode 100644 index 0000000000000..9f604c763b163 --- /dev/null +++ b/packages/edit-site/src/components/block-list-exploded/style.scss @@ -0,0 +1,66 @@ +.edit-site-block-list-exploded { + display: flex; + flex-direction: column; + width: min(#{$content-width}, calc(100% - #{$grid-unit-40})); + margin: auto; +} + +.edit-site-block-list-exploded__inserter > div { + display: flex; + margin: 30px auto; + width: fit-content; +} + +.edit-site-block-list-exploded__item-container { + position: relative; + + &::after { + content: ""; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + pointer-events: none; + } + + &:hover::after { + border: 1px solid var(--wp-admin-theme-color); + } + + &.is-selected::after { + border: 2px solid var(--wp-admin-theme-color); + } +} + +.edit-site-block-list-exploded__item-top-toolbar { + position: absolute; + top: -$block-toolbar-height - $grid-unit-15; + height: $block-toolbar-height; + background: var(--wp-admin-theme-color); + color: $white; + display: flex; + align-items: center; + gap: $grid-unit-20; + padding-left: $grid-unit-20; + border-radius: $radius-block-ui; + + .block-editor-block-lock-toolbar, + .block-editor-block-mover__move-button-container { + background: transparent; + color: inherit; + border: none; + + .components-button { + color: $white; + } + } + + // TODO: Absorb these in the BlockMover component (outside of mobile). + .block-editor-block-mover-button.is-down-button svg { + bottom: 5px; + } + .block-editor-block-mover-button.is-up-button svg { + top: 5px; + } +} diff --git a/packages/edit-site/src/components/block-list-exploded/top-toolbar.js b/packages/edit-site/src/components/block-list-exploded/top-toolbar.js new file mode 100644 index 0000000000000..cd2ffe42d22d9 --- /dev/null +++ b/packages/edit-site/src/components/block-list-exploded/top-toolbar.js @@ -0,0 +1,27 @@ +/** + * WordPress dependencies + */ +import { + BlockTitle, + BlockMover, + BlockLockToolbar, + BlockIcon, + useBlockDisplayInformation, +} from '@wordpress/block-editor'; + +function BlockListExplodedTopToolbar( { clientId } ) { + const { icon } = useBlockDisplayInformation( clientId ); + + return ( +
+ + + + + + +
+ ); +} + +export default BlockListExplodedTopToolbar; diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index 5564cf454a4c7..7f032185a3ce9 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -241,7 +241,10 @@ function Editor( { onError } ) { <> - { editorMode === 'visual' && + { ( editorMode === + 'visual' || + editorMode === + 'exploded' ) && template && ( { const { __experimentalGetPreviewDeviceType, @@ -61,6 +63,7 @@ export default function Header( { editorStore ); const { getShortcutRepresentation } = select( keyboardShortcutsStore ); + const { getBlockCount } = select( blockEditorStore ); const postType = getEditedPostType(); const postId = getEditedPostId(); @@ -78,7 +81,8 @@ export default function Header( { listViewShortcut: getShortcutRepresentation( 'core/edit-site/toggle-list-view' ), - isVisualMode: getEditorMode() === 'visual', + mode: getEditorMode(), + hasMoreThanOneBlock: getBlockCount() > 1, }; }, [] ); @@ -86,6 +90,7 @@ export default function Header( { __experimentalSetPreviewDeviceType: setPreviewDeviceType, setIsInserterOpened, setIsListViewOpened, + switchEditorMode, } = useDispatch( editSiteStore ); const isLargeViewport = useViewportMatch( 'medium' ); @@ -105,6 +110,8 @@ export default function Header( { ); const isFocusMode = templateType === 'wp_template_part'; + const shouldEnableExplodedViewButton = + mode === 'exploded' || ( hasMoreThanOneBlock && mode === 'visual' ); return (
@@ -115,7 +122,7 @@ export default function Header( { variant="primary" isPressed={ isInserterOpen } className="edit-site-header-toolbar__inserter-toggle" - disabled={ ! isVisualMode } + disabled={ mode !== 'visual' } onMouseDown={ preventDefault } onClick={ openInserter } icon={ plus } @@ -131,13 +138,13 @@ export default function Header( { <>
diff --git a/packages/edit-site/src/store/actions.js b/packages/edit-site/src/store/actions.js index 1185865861c5f..5535f13dcd4b5 100644 --- a/packages/edit-site/src/store/actions.js +++ b/packages/edit-site/src/store/actions.js @@ -468,7 +468,7 @@ export const switchEditorMode = ( mode ) => ( { registry } ) => { if ( mode === 'visual' ) { speak( __( 'Visual editor selected' ), 'assertive' ); - } else if ( mode === 'mosaic' ) { - speak( __( 'Mosaic view selected' ), 'assertive' ); + } else if ( mode === 'exploded' ) { + speak( __( 'Exploded view selected' ), 'assertive' ); } }; diff --git a/packages/edit-site/src/style.scss b/packages/edit-site/src/style.scss index b61d06574c7aa..ac1daf0924901 100644 --- a/packages/edit-site/src/style.scss +++ b/packages/edit-site/src/style.scss @@ -1,6 +1,7 @@ @import "../../interface/src/style.scss"; @import "./components/block-editor/style.scss"; +@import "./components/block-list-exploded/style.scss"; @import "./components/code-editor/style.scss"; @import "./components/global-styles/style.scss"; @import "./components/header/style.scss";