diff --git a/packages/base-styles/_z-index.scss b/packages/base-styles/_z-index.scss index b028f3d3023b58..8baf03c3fa61bb 100644 --- a/packages/base-styles/_z-index.scss +++ b/packages/base-styles/_z-index.scss @@ -76,6 +76,11 @@ $z-layers: ( // should overlap most block content. ".block-editor-block-list__block.is-{selected,hovered} .block-editor-block-mover": 61, + // Query block setup state. + ".block-editor-block-pattern-setup .pattern-slide": 100, + ".block-editor-block-pattern-setup .{next,previous}-slide": 101, + ".block-editor-block-pattern-setup .active-slide": 102, + // Show sidebar above wp-admin navigation bar for mobile viewports: // #wpadminbar { z-index: 99999 } ".interface-interface-skeleton__sidebar": 100000, diff --git a/packages/block-editor/src/components/block-pattern-setup/constants.js b/packages/block-editor/src/components/block-pattern-setup/constants.js new file mode 100644 index 00000000000000..07e03528f1d257 --- /dev/null +++ b/packages/block-editor/src/components/block-pattern-setup/constants.js @@ -0,0 +1,4 @@ +export const VIEWMODES = { + carousel: 'carousel', + grid: 'grid', +}; diff --git a/packages/block-editor/src/components/block-pattern-setup/index.js b/packages/block-editor/src/components/block-pattern-setup/index.js new file mode 100644 index 00000000000000..26c5533be8c840 --- /dev/null +++ b/packages/block-editor/src/components/block-pattern-setup/index.js @@ -0,0 +1,184 @@ +/** + * WordPress dependencies + */ +import { useDispatch } from '@wordpress/data'; +import { cloneBlock } from '@wordpress/blocks'; +import { + VisuallyHidden, + __unstableComposite as Composite, + __unstableUseCompositeState as useCompositeState, + __unstableCompositeItem as CompositeItem, +} from '@wordpress/components'; + +import { useState } from '@wordpress/element'; +import { useInstanceId } from '@wordpress/compose'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import { store as blockEditorStore } from '../../store'; +import BlockPreview from '../block-preview'; +import SetupToolbar from './setup-toolbar'; +import usePatternsSetup from './use-patterns-setup'; +import { VIEWMODES } from './constants'; + +const SetupContent = ( { + viewMode, + activeSlide, + patterns, + onBlockPatternSelect, +} ) => { + const composite = useCompositeState(); + const containerClass = 'block-editor-block-pattern-setup__container'; + if ( viewMode === VIEWMODES.carousel ) { + const slideClass = new Map( [ + [ activeSlide, 'active-slide' ], + [ activeSlide - 1, 'previous-slide' ], + [ activeSlide + 1, 'next-slide' ], + ] ); + return ( +
+ +
+ ); + } + return ( + + { patterns.map( ( pattern ) => ( + + ) ) } + + ); +}; + +function BlockPattern( { pattern, onSelect, composite } ) { + const baseClassName = 'block-editor-block-pattern-setup-list'; + const { blocks, title, description, viewportWidth = 700 } = pattern; + const descriptionId = useInstanceId( + BlockPattern, + `${ baseClassName }__item-description` + ); + return ( +
+ onSelect( blocks ) } + > + +
+ { title } +
+
+ { !! description && ( + + { description } + + ) } +
+ ); +} + +function BlockPatternSlide( { className, pattern } ) { + const { blocks, title, description } = pattern; + const descriptionId = useInstanceId( + BlockPatternSlide, + 'block-editor-block-pattern-setup-list__item-description' + ); + return ( +
  • + + { !! description && ( + + { description } + + ) } +
  • + ); +} + +const BlockPatternSetup = ( { + clientId, + blockName, + filterPatternsFn, + startBlankComponent, +} ) => { + const [ viewMode, setViewMode ] = useState( VIEWMODES.carousel ); + const [ activeSlide, setActiveSlide ] = useState( 0 ); + const [ showBlank, setShowBlank ] = useState( false ); + const { replaceBlock } = useDispatch( blockEditorStore ); + const patterns = usePatternsSetup( clientId, blockName, filterPatternsFn ); + + if ( ! patterns?.length || showBlank ) { + return startBlankComponent; + } + + const onBlockPatternSelect = ( blocks ) => { + const clonedBlocks = blocks.map( ( block ) => cloneBlock( block ) ); + replaceBlock( clientId, clonedBlocks ); + }; + return ( +
    + { + setActiveSlide( ( active ) => active + 1 ); + } } + handlePrevious={ () => { + setActiveSlide( ( active ) => active - 1 ); + } } + onBlockPatternSelect={ () => { + onBlockPatternSelect( patterns[ activeSlide ].blocks ); + } } + onStartBlank={ () => { + setShowBlank( true ); + } } + /> + +
    + ); +}; + +export default BlockPatternSetup; diff --git a/packages/block-editor/src/components/block-pattern-setup/setup-toolbar.js b/packages/block-editor/src/components/block-pattern-setup/setup-toolbar.js new file mode 100644 index 00000000000000..7eba89edb25793 --- /dev/null +++ b/packages/block-editor/src/components/block-pattern-setup/setup-toolbar.js @@ -0,0 +1,97 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { Button } from '@wordpress/components'; +import { + chevronRight, + chevronLeft, + grid, + stretchFullWidth, +} from '@wordpress/icons'; + +/** + * Internal dependencies + */ +import { VIEWMODES } from './constants'; + +const Actions = ( { onStartBlank, onBlockPatternSelect } ) => ( +
    + + +
    +); + +const CarouselNavigation = ( { + handlePrevious, + handleNext, + activeSlide, + totalSlides, +} ) => ( +
    +
    +); + +const SetupToolbar = ( { + viewMode, + setViewMode, + handlePrevious, + handleNext, + activeSlide, + totalSlides, + onBlockPatternSelect, + onStartBlank, +} ) => { + const isCarouselView = viewMode === VIEWMODES.carousel; + const displayControls = ( +
    +
    + ); + return ( +
    + { isCarouselView && ( + + ) } + { displayControls } + { isCarouselView && ( + + ) } +
    + ); +}; + +export default SetupToolbar; diff --git a/packages/block-editor/src/components/block-pattern-setup/style.scss b/packages/block-editor/src/components/block-pattern-setup/style.scss new file mode 100644 index 00000000000000..a1876fd5c6022e --- /dev/null +++ b/packages/block-editor/src/components/block-pattern-setup/style.scss @@ -0,0 +1,128 @@ +.block-editor-block-pattern-setup { + display: flex; + flex-direction: column; + justify-content: center; + align-items: flex-start; + width: 100%; + border-radius: $radius-block-ui; + box-shadow: inset 0 0 0 $border-width $gray-900; + outline: 1px solid transparent; // Shown for Windows 10 High Contrast mode. + + // TODO change to check parent. + &.view-mode-grid { + .block-editor-block-pattern-setup__toolbar { + justify-content: center; + } + + .block-editor-block-pattern-setup__container { + display: grid; + grid-template-columns: 1fr 1fr; + grid-gap: $grid-unit-20; + padding: $grid-unit-20; + max-height: 550px; + overflow: auto; + margin: 0 $border-width $border-width $border-width; + width: calc(100% - #{ $border-width * 2 }); + background: $white; + + .block-editor-block-preview__container, + div[role="button"] { + cursor: pointer; + } + + .block-editor-block-pattern-setup-list__item-title { + padding: $grid-unit-05; + font-size: $helptext-font-size; + text-align: center; + } + + .block-editor-block-preview__container { + border-radius: $radius-block-ui; + border: $border-width solid $gray-300; + } + } + } + + .block-editor-block-pattern-setup__toolbar { + box-sizing: border-box; + position: relative; + padding: $grid-unit-20; + width: 100%; + text-align: left; + margin: 0; + color: $gray-900; + // Block UI appearance. + border-radius: $radius-block-ui $radius-block-ui 0 0; + background-color: $white; + box-shadow: inset 0 0 0 $border-width $gray-900; + outline: 1px solid transparent; // Shown for Windows 10 High Contrast mode. + + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + + .block-editor-block-pattern-setup__display-controls { + display: flex; + } + + .block-editor-block-pattern-setup__navigation, + .block-editor-block-pattern-setup__actions { + width: calc(50% - 36px); // This ensures the grid / list toggle is centrally aligned. + display: flex; + } + + .block-editor-block-pattern-setup__actions { + justify-content: flex-end; + } + } + .block-editor-block-pattern-setup__container { + display: flex; + flex-direction: column; + width: 100%; + box-sizing: border-box; + + .carousel-container { + overflow: hidden; + text-align: center; + position: relative; + padding: 0; + margin: 0; + list-style: none; + transform-style: preserve-3d; + * { + box-sizing: border-box; + } + .pattern-slide { + opacity: 0; + position: absolute; + top: 0; + width: 100%; + margin: auto; + padding: $grid-unit-20; + transition: transform 0.5s, opacity 0.5s, z-index 0.5s; + z-index: z-index(".block-editor-block-pattern-setup .pattern-slide"); + + &.active-slide { + opacity: 1; + position: relative; + z-index: z-index(".block-editor-block-pattern-setup .active-slide"); + } + + &.previous-slide { + transform: translateX(-100%); + z-index: z-index(".block-editor-block-pattern-setup .{next,previous}-slide"); + } + + &.next-slide { + transform: translateX(100%); + z-index: z-index(".block-editor-block-pattern-setup .{next,previous}-slide"); + } + } + } + + .block-list-appender { + display: none; + } + } +} diff --git a/packages/block-editor/src/components/block-pattern-setup/use-patterns-setup.js b/packages/block-editor/src/components/block-pattern-setup/use-patterns-setup.js new file mode 100644 index 00000000000000..1b6a90b87457a0 --- /dev/null +++ b/packages/block-editor/src/components/block-pattern-setup/use-patterns-setup.js @@ -0,0 +1,34 @@ +/** + * WordPress dependencies + */ +import { useSelect } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import { store as blockEditorStore } from '../../store'; + +function usePatternsSetup( clientId, blockName, filterPatternsFn ) { + return useSelect( + ( select ) => { + const { + getBlockRootClientId, + __experimentalGetPatternsByBlockTypes, + __experimentalGetAllowedPatterns, + } = select( blockEditorStore ); + const rootClientId = getBlockRootClientId( clientId ); + if ( filterPatternsFn ) { + return __experimentalGetAllowedPatterns( rootClientId ).filter( + filterPatternsFn + ); + } + return __experimentalGetPatternsByBlockTypes( + blockName, + rootClientId + ); + }, + [ clientId, blockName, filterPatternsFn ] + ); +} + +export default usePatternsSetup; diff --git a/packages/block-editor/src/components/index.js b/packages/block-editor/src/components/index.js index dc88ae5a36deb3..64c5b34a8b4d16 100644 --- a/packages/block-editor/src/components/index.js +++ b/packages/block-editor/src/components/index.js @@ -27,6 +27,7 @@ export { BlockNavigationBlockFill as __experimentalBlockNavigationBlockFill } fr export { default as __experimentalBlockNavigationEditor } from './block-navigation/editor'; export { default as __experimentalBlockNavigationTree } from './block-navigation/tree'; export { default as __experimentalBlockVariationPicker } from './block-variation-picker'; +export { default as __experimentalBlockPatternSetup } from './block-pattern-setup'; export { default as __experimentalBlockVariationTransforms } from './block-variation-transforms'; export { BlockVerticalAlignmentToolbar, diff --git a/packages/block-editor/src/style.scss b/packages/block-editor/src/style.scss index 745e64a980d2a9..515f4195850007 100644 --- a/packages/block-editor/src/style.scss +++ b/packages/block-editor/src/style.scss @@ -26,6 +26,7 @@ @import "./components/block-switcher/style.scss"; @import "./components/block-types-list/style.scss"; @import "./components/block-variation-picker/style.scss"; +@import "./components/block-pattern-setup/style.scss"; @import "./components/block-variation-transforms/style.scss"; @import "./components/border-style-control/style.scss"; @import "./components/button-block-appender/style.scss"; diff --git a/packages/block-library/src/query/edit/block-setup/index.js b/packages/block-library/src/query/edit/block-setup/index.js deleted file mode 100644 index 37008b6010ff7e..00000000000000 --- a/packages/block-library/src/query/edit/block-setup/index.js +++ /dev/null @@ -1,49 +0,0 @@ -/** - * WordPress dependencies - */ -import { useSelect } from '@wordpress/data'; -import { useBlockProps } from '@wordpress/block-editor'; -import { store as blocksStore } from '@wordpress/blocks'; -import { Placeholder } from '@wordpress/components'; - -/** - * Internal dependencies - */ -import LayoutSetupStep from './layout-step'; - -const BlockSetup = ( { - blockName, - useLayoutSetup, - onVariationSelect = () => {}, - onBlockPatternSelect = () => {}, - children, -} ) => { - const { blockType } = useSelect( - ( select ) => { - const { getBlockType } = select( blocksStore ); - return { blockType: getBlockType( blockName ) }; - }, - [ blockName ] - ); - const blockProps = useBlockProps(); - return ( -
    - - { useLayoutSetup && ( - - ) } - { children } - -
    - ); -}; - -export default BlockSetup; diff --git a/packages/block-library/src/query/edit/block-setup/layout-step.js b/packages/block-library/src/query/edit/block-setup/layout-step.js deleted file mode 100644 index 9df6893856722f..00000000000000 --- a/packages/block-library/src/query/edit/block-setup/layout-step.js +++ /dev/null @@ -1,200 +0,0 @@ -/** - * WordPress dependencies - */ -import { useSelect } from '@wordpress/data'; -import { useState } from '@wordpress/element'; -import { store as blocksStore } from '@wordpress/blocks'; -import { useInstanceId } from '@wordpress/compose'; -import { - BlockPreview, - store as blockEditorStore, -} from '@wordpress/block-editor'; -import { __, isRTL } from '@wordpress/i18n'; -import { - Button, - Icon, - VisuallyHidden, - __unstableComposite as Composite, - __unstableUseCompositeState as useCompositeState, - __unstableCompositeItem as CompositeItem, -} from '@wordpress/components'; -import { chevronRight, chevronLeft } from '@wordpress/icons'; - -const LayoutSetupStep = ( { - blockType, - onVariationSelect, - onBlockPatternSelect, -} ) => { - const [ showBack, setShowBack ] = useState( false ); - const { - defaultVariation, - blockVariations, - patterns, - hasBlockVariations, - } = useSelect( - ( select ) => { - const { getBlockVariations, getDefaultBlockVariation } = select( - blocksStore - ); - const { __experimentalGetPatternsByBlockTypes } = select( - blockEditorStore - ); - const { name } = blockType; - const _patterns = __experimentalGetPatternsByBlockTypes( name ); - const _blockVariations = getBlockVariations( name, 'block' ); - return { - defaultVariation: getDefaultBlockVariation( name, 'block' ), - blockVariations: _blockVariations, - patterns: _patterns, - hasBlockVariations: !! _blockVariations?.length, - }; - }, - [ blockType ] - ); - const [ showBlockVariations, setShowBlockVariations ] = useState( - ! patterns?.length && hasBlockVariations - ); - const composite = useCompositeState(); - // Show nothing if block variations and block pattterns do not exist. - if ( ! hasBlockVariations && ! patterns?.length ) return null; - - const showPatternsList = ! showBlockVariations && !! patterns.length; - return ( - <> - { showBack && ( - - ) } - - { showBlockVariations && ( - <> - { blockVariations.map( ( variation ) => ( - onVariationSelect( nextVariation ) } - composite={ composite } - /> - ) ) } - - ) } - { showPatternsList && ( - <> - { patterns.map( ( pattern ) => ( - - ) ) } - - ) } - { ! showBlockVariations && hasBlockVariations && ( - { - setShowBack( true ); - setShowBlockVariations( true ); - } } - composite={ composite } - /> - ) } - - - ); -}; - -function BlockPattern( { pattern, onSelect, composite } ) { - const { viewportWidth, blocks } = pattern; - const descriptionId = useInstanceId( - BlockPattern, - 'block-setup-block-layout-list__item-description' - ); - return ( -
    - onSelect( blocks ) } - > - - -
    - { pattern.title } -
    - { !! pattern.description && ( - - { pattern.description } - - ) } -
    - ); -} - -function BlockVariation( { variation, onSelect, composite } ) { - const descriptionId = useInstanceId( - BlockVariation, - 'block-setup-block-layout-list__item-description' - ); - return ( -
    - onSelect( variation ) } - label={ variation.description || variation.title } - > - { variation.icon && ( -
    - -
    - ) } -
    -
    - { variation.title } -
    - { !! variation.description && ( - - { variation.description } - - ) } -
    - ); -} - -export default LayoutSetupStep; diff --git a/packages/block-library/src/query/edit/index.js b/packages/block-library/src/query/edit/index.js index ce83e54e6c97ad..c64acc48b2f41c 100644 --- a/packages/block-library/src/query/edit/index.js +++ b/packages/block-library/src/query/edit/index.js @@ -9,6 +9,7 @@ import { useBlockProps, store as blockEditorStore, __experimentalUseInnerBlocksProps as useInnerBlocksProps, + __experimentalBlockPatternSetup as BlockPatternSetup, } from '@wordpress/block-editor'; /** @@ -16,7 +17,7 @@ import { */ import QueryToolbar from './query-toolbar'; import QueryInspectorControls from './query-inspector-controls'; -import QueryBlockSetup from './query-block-setup'; +import QueryPlaceholder from './query-placeholder'; import { DEFAULTS_POSTS_PER_PAGE } from '../constants'; const TEMPLATE = [ [ 'core/query-loop' ] ]; @@ -87,6 +88,22 @@ export function QueryContent( { attributes, setAttributes } ) { ); } +function QueryPatternSetup( props ) { + const { clientId, name: blockName } = props; + const blockProps = useBlockProps(); + // `startBlankComponent` is what to render when clicking `Start blank` + // or if no matched patterns are found. + return ( +
    + } + /> +
    + ); +} + const QueryEdit = ( props ) => { const { clientId } = props; const hasInnerBlocks = useSelect( @@ -94,7 +111,7 @@ const QueryEdit = ( props ) => { !! select( blockEditorStore ).getBlocks( clientId ).length, [ clientId ] ); - const Component = hasInnerBlocks ? QueryContent : QueryBlockSetup; + const Component = hasInnerBlocks ? QueryContent : QueryPatternSetup; return ; }; diff --git a/packages/block-library/src/query/edit/query-block-setup.js b/packages/block-library/src/query/edit/query-block-setup.js deleted file mode 100644 index f7837da313fc37..00000000000000 --- a/packages/block-library/src/query/edit/query-block-setup.js +++ /dev/null @@ -1,120 +0,0 @@ -/** - * External dependencies - */ -import { cloneDeep } from 'lodash'; -/** - * WordPress dependencies - */ -import { useDispatch } from '@wordpress/data'; -import { __, _x } from '@wordpress/i18n'; -import { SelectControl, ToggleControl } from '@wordpress/components'; -import { - cloneBlock, - createBlocksFromInnerBlocksTemplate, -} from '@wordpress/blocks'; -import { store as blockEditorStore } from '@wordpress/block-editor'; - -/** - * Internal dependencies - */ -import BlockSetup from './block-setup'; -import { usePostTypes } from '../utils'; - -const QueryBlockSetup = ( { - clientId, - attributes: { query }, - setAttributes, - name: blockName, -} ) => { - const { postType, inherit } = query; - const { replaceBlocks, replaceInnerBlocks } = useDispatch( - blockEditorStore - ); - const { postTypesSelectOptions } = usePostTypes(); - const updateQuery = ( newQuery ) => - setAttributes( { query: { ...query, ...newQuery } } ); - const onVariationSelect = ( nextVariation ) => { - if ( nextVariation.attributes ) { - setAttributes( nextVariation.attributes ); - } - if ( nextVariation.innerBlocks ) { - replaceInnerBlocks( - clientId, - createBlocksFromInnerBlocksTemplate( - nextVariation.innerBlocks - ), - false - ); - } - }; - const onBlockPatternSelect = ( blocks ) => { - const clonedBlocks = blocks.map( ( block ) => { - const clone = cloneBlock( block ); - /** - * TODO: this check will be revised with the ongoing work on block patterns. - * For now we keep the value of posts per page (`query.perPage`) from Query patterns - * so as to preview the pattern as intended, without possible big previews. - * During insertion, we need to override the Query's attributes that can be set in - * the Placeholder and we unset the `perPage` value to be set appropriately by Query block. - */ - if ( block.name === 'core/query' ) { - /** - * We need to `cloneDeep` the Query's attributes, as `cloneBlock` does a swallow - * copy of the block. - */ - const queryAttributes = cloneDeep( clone.attributes ); - Object.assign( queryAttributes.query, { - inherit: query.inherit, - postType: query.postType, - perPage: null, - } ); - return { - ...clone, - attributes: queryAttributes, - }; - } - return clone; - } ); - replaceBlocks( clientId, clonedBlocks ); - }; - const inheritToggleHelp = !! inherit - ? _x( - 'Inherit the global query depending on the URL.', - 'Query block `inherit` option helping text' - ) - : _x( - 'Customize the query arguments.', - 'Query block `inherit` option helping text' - ); - return ( - -
    - - updateQuery( { inherit: !! value } ) - } - help={ inheritToggleHelp } - /> - { ! inherit && ( - - updateQuery( { postType: newValue } ) - } - /> - ) } -
    -
    - ); -}; - -export default QueryBlockSetup; diff --git a/packages/block-library/src/query/editor.scss b/packages/block-library/src/query/editor.scss index 164d1f6f00bbc1..27d4ce00c4939a 100644 --- a/packages/block-library/src/query/editor.scss +++ b/packages/block-library/src/query/editor.scss @@ -5,123 +5,3 @@ .wp-block-query__create-new-link { padding: 0 $grid-unit-20 $grid-unit-20 56px; } - -.wp-block-query { - .components-placeholder { - .block-setup-navigation { - padding: $grid-unit-15 0 0; - } - - .block-attributes-setup-container { - padding-top: $grid-unit-30; - - .components-base-control__help { - margin: $grid-unit-15 auto; - } - } - } -} - -.block-setup-block-layout-list__container { - display: flex; - flex-direction: row; - flex-wrap: wrap; - - .block-setup-block-layout-list__list-item { - cursor: pointer; - margin: 0 $grid-unit-15 $grid-unit-15 0; - width: 200px; - text-align: center; - display: flex; - flex-direction: column; - - &.is-block-variation { - width: 90px; - - button { - display: inline-flex; - margin-right: 0; - height: auto; - } - } - - .block-setup-block-layout-list__item-title { - padding: $grid-unit-05 0; - font-size: $helptext-font-size; - } - - .block-setup-block-layout-list__item { - height: 100%; - max-height: 140px; - display: flex; - flex-direction: column; - padding: 2px; - transition: all 0.05s ease-in-out; - @include reduce-motion("transition"); - border-radius: $radius-block-ui; - border: $border-width solid $gray-300; - - &:hover { - border: $border-width solid var(--wp-admin-theme-color); - } - - &:focus { - box-shadow: inset 0 0 0 1px $white, 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); - // Windows High Contrast mode will show this outline, but not the box-shadow. - outline: 2px solid transparent; - } - - .block-editor-block-preview__container { - margin: auto 0; - cursor: pointer; // This is for the BlockPreview. - } - - .block-setup-block-layout-list__item-variation-icon { - color: var(--wp-admin-theme-color); - padding: $grid-unit-05 * 1.5; - border-radius: $radius-block-ui; - box-shadow: inset 0 0 0 1px var(--wp-admin-theme-color); - display: inline-flex; - margin: $grid-unit-15 auto auto auto; - - svg { - fill: currentColor; - outline: none; - } - } - } - } - - // Size consecutive block variation icons the same. - .block-setup-block-layout-list__list-item.is-block-variation .block-setup-block-layout-list__item { - height: 90px; - min-height: 90px; - } - - // Size the block variation icon same as the thumbnail on step 1. - .block-setup-block-layout-list__list-item:not(.is-block-variation) + .block-setup-block-layout-list__list-item.is-block-variation .block-setup-block-layout-list__item { - height: 100%; - } -} - -.components-button.block-setup-block-layout-back-button.is-tertiary.has-icon { - color: inherit; - padding-left: 0; - display: inline-flex; - margin-right: auto; - margin-top: -$grid-unit-15; - - &:hover:not(:disabled) { - box-shadow: none; - color: var(--wp-admin-theme-color); - } - - &:active:not(:disabled) { - background: transparent; - color: $gray-300; - } - - svg { - margin-right: 0; - } -} diff --git a/packages/e2e-tests/plugins/query-block.php b/packages/e2e-tests/plugins/query-block.php new file mode 100644 index 00000000000000..f985c0d772224f --- /dev/null +++ b/packages/e2e-tests/plugins/query-block.php @@ -0,0 +1,38 @@ + __( 'Query Test 1', 'gutenberg' ), + 'blockTypes' => array( 'core/query' ), + 'content' => ' + + + + ', + ) +); +register_block_pattern( + 'query/test-2', + array( + 'title' => __( 'Query Test 2', 'gutenberg' ), + 'blockTypes' => array( 'core/query' ), + 'content' => ' + + + + + ', + ) +); diff --git a/packages/e2e-tests/specs/experiments/blocks/query.test.js b/packages/e2e-tests/specs/experiments/blocks/query.test.js new file mode 100644 index 00000000000000..254acdd009b2dd --- /dev/null +++ b/packages/e2e-tests/specs/experiments/blocks/query.test.js @@ -0,0 +1,103 @@ +/** + * WordPress dependencies + */ +import { + activatePlugin, + deactivatePlugin, + activateTheme, + createNewPost, + insertBlock, + publishPost, + trashAllPosts, +} from '@wordpress/e2e-test-utils'; + +const createDemoPosts = async () => { + await createNewPost( { postType: 'post', title: `Post 1` } ); + await publishPost(); +}; + +describe( 'Query block', () => { + beforeAll( async () => { + await activatePlugin( 'gutenberg-test-query-block' ); + await activateTheme( 'tt1-blocks' ); + await createDemoPosts(); + } ); + afterAll( async () => { + await activateTheme( 'twentytwentyone' ); + await trashAllPosts(); + await deactivatePlugin( 'gutenberg-test-query-block' ); + } ); + beforeEach( async () => { + await createNewPost( { postType: 'page', title: `Query Page` } ); + } ); + afterEach( async () => { + await trashAllPosts( 'page' ); + } ); + describe( 'Query block insertion', () => { + it( 'Carousel', async () => { + await insertBlock( 'Query' ); + // Wait for pattern blocks to be loaded. + await page.waitForSelector( + '.block-editor-block-pattern-setup__container .wp-block-post-title' + ); + /** + * Ensure that carousel is working by checking slider css classes + * and navigating to the next pattern. + */ + await page.waitForSelector( + 'li.pattern-slide.active-slide[aria-label="Query Test 1"]' + ); + const nextPatternButton = await page.waitForSelector( + '.block-editor-block-pattern-setup__navigation button[aria-label="Next pattern"]' + ); + await nextPatternButton.click(); + await page.waitForSelector( + 'li.pattern-slide.active-slide[aria-label="Query Test 2"]' + ); + // Choose the selected pattern. + const chooseButton = await page.waitForXPath( + '//div[contains(@class, "block-editor-block-pattern-setup__actions")]//button[text()="Choose"]' + ); + chooseButton.click(); + // Wait for pattern setup to go away. + await page.waitForSelector( '.block-editor-block-pattern-setup', { + hidden: true, + } ); + /** + * We can't use `getEditedPostContent` easily for now because + * `query` makes used of `instanceId` so it's not very reliable. + * This should be revisited. + */ + await page.waitForSelector( '.wp-block-post-date' ); + await page.waitForSelector( '.wp-block-post-title' ); + } ); + it( 'Grid view', async () => { + await insertBlock( 'Query' ); + // Wait for patterns setup to be loaded. + await page.waitForSelector( + '.block-editor-block-pattern-setup__display-controls' + ); + // Click the Grid view button. + const gridViewButton = await page.waitForSelector( + '.block-editor-block-pattern-setup__display-controls button[aria-label="Grid view"]' + ); + await gridViewButton.click(); + // Wait for patterns to be loaded and click the wanted pattern. + const gridPattern = await page.waitForXPath( + '//div[@class="block-editor-block-pattern-setup-list__item-title" and contains(text(), "Query Test 2")]' + ); + await gridPattern.click(); + // Wait for pattern setup to go away. + await page.waitForSelector( '.block-editor-block-pattern-setup', { + hidden: true, + } ); + /** + * We can't use `getEditedPostContent` easily for now because + * `query` makes used of `instanceId` so it's not very reliable. + * This should be revisited. + */ + await page.waitForSelector( '.wp-block-post-date' ); + await page.waitForSelector( '.wp-block-post-title' ); + } ); + } ); +} );