diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index 311c5d7fae495a..cd89b9461d07e8 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -429,6 +429,16 @@ Add custom HTML code and preview it as you edit. ([Source](https://github.com/Wo - **Supports:** interactivity (clientNavigation), ~~className~~, ~~customCSS~~, ~~customClassName~~, ~~html~~ - **Attributes:** content +## Icon + +Insert an SVG icon. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/icon)) + +- **Name:** core/icon +- **Experimental:** true +- **Category:** media +- **Supports:** align (center, left, right), anchor, ariaLabel, color (background, text), dimensions (width), interactivity (clientNavigation), spacing (margin, padding), ~~html~~ +- **Attributes:** icon, style + ## Image Insert an image to make a visual statement. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/image)) @@ -528,7 +538,7 @@ A collection of blocks that allow visitors to get around your site. ([Source](ht - **Name:** core/navigation - **Category:** theme -- **Allowed Blocks:** core/navigation-link, core/search, core/social-links, core/page-list, core/spacer, core/home-link, core/site-title, core/site-logo, core/navigation-submenu, core/loginout, core/buttons +- **Allowed Blocks:** core/navigation-link, core/search, core/social-links, core/page-list, core/spacer, core/home-link, core/icon, core/site-title, core/site-logo, core/navigation-submenu, core/loginout, core/buttons - **Supports:** align (full, wide), anchor, ariaLabel, contentRole, inserter, interactivity, layout (allowSizingOnChildren, default, ~~allowInheriting~~, ~~allowSwitching~~, ~~allowVerticalAlignment~~), spacing (blockGap, units), typography (fontSize, lineHeight), ~~html~~, ~~renaming~~ - **Attributes:** __unstableLocation, backgroundColor, customBackgroundColor, customOverlayBackgroundColor, customOverlayTextColor, customTextColor, hasIcon, icon, maxNestingLevel, overlay, overlayBackgroundColor, overlayMenu, overlayTextColor, ref, rgbBackgroundColor, rgbTextColor, showSubmenuIcon, submenuVisibility, templateLock, textColor diff --git a/lib/experimental/editor-settings.php b/lib/experimental/editor-settings.php index 9c90acc005c81d..6be9aab1925a98 100644 --- a/lib/experimental/editor-settings.php +++ b/lib/experimental/editor-settings.php @@ -69,6 +69,11 @@ function gutenberg_enable_block_experiments() { if ( $gutenberg_experiments && array_key_exists( 'gutenberg-block-experiments', $gutenberg_experiments ) ) { wp_add_inline_script( 'wp-block-editor', 'window.__experimentalEnableBlockExperiments = true', 'before' ); } + + // Adding explicit support for the Icon block if the SVG icon registry is active. + if ( $gutenberg_experiments && array_key_exists( 'gutenberg-svg-icon-registry', $gutenberg_experiments ) ) { + wp_add_inline_script( 'wp-block-editor', 'window.__experimentalEnableIconBlock = true', 'before' ); + } } add_action( 'admin_init', 'gutenberg_enable_block_experiments' ); diff --git a/lib/experiments-page.php b/lib/experiments-page.php index 2d4149014e627f..1fee6ded0e5389 100644 --- a/lib/experiments-page.php +++ b/lib/experiments-page.php @@ -228,7 +228,7 @@ function gutenberg_initialize_experiments_settings() { 'gutenberg-experiments', 'gutenberg_experiments_section', array( - 'label' => __( 'Enables a REST API endpoint for accessing SVG icons.', 'gutenberg' ), + 'label' => __( 'Enables a REST API endpoint for accessing SVG icons as well as the associated Icon block.', 'gutenberg' ), 'id' => 'gutenberg-svg-icon-registry', ) ); diff --git a/packages/block-library/src/editor.scss b/packages/block-library/src/editor.scss index 88ad6c2943167e..fd2f4b4859d3f9 100644 --- a/packages/block-library/src/editor.scss +++ b/packages/block-library/src/editor.scss @@ -22,6 +22,7 @@ @use "./gallery/editor.scss" as *; @use "./group/editor.scss" as *; @use "./html/editor.scss" as *; +@use "./icon/editor.scss" as *; @use "./image/editor.scss" as *; @use "./latest-posts/editor.scss" as *; @use "./math/editor.scss" as *; diff --git a/packages/block-library/src/icon/block.json b/packages/block-library/src/icon/block.json new file mode 100644 index 00000000000000..2916fd653987ee --- /dev/null +++ b/packages/block-library/src/icon/block.json @@ -0,0 +1,65 @@ +{ + "apiVersion": 3, + "$schema": "https://schemas.wp.org/trunk/block.json", + "name": "core/icon", + "title": "Icon", + "__experimental": true, + "category": "media", + "description": "Insert an SVG icon.", + "keywords": [ "icon", "svg" ], + "textdomain": "default", + "attributes": { + "icon": { + "type": "string", + "role": "content" + }, + "style": { + "type": "object", + "default": { + "dimensions": { + "width": "24px" + } + } + } + }, + "supports": { + "anchor": true, + "ariaLabel": { + "__experimentalSkipSerialization": true + }, + "align": [ "left", "center", "right" ], + "html": false, + "color": { + "background": true, + "text": true + }, + "interactivity": { + "clientNavigation": true + }, + "__experimentalBorder": { + "color": true, + "radius": true, + "style": true, + "width": true, + "__experimentalDefaultControls": { + "color": false, + "radius": false, + "style": false, + "width": false + } + }, + "spacing": { + "padding": true, + "margin": true, + "__experimentalDefaultControls": { + "margin": false, + "padding": false + } + }, + "dimensions": { + "width": true + } + }, + "style": "wp-block-icon", + "editorStyle": "wp-block-icon-editor" +} diff --git a/packages/block-library/src/icon/components/custom-inserter/icon-grid.js b/packages/block-library/src/icon/components/custom-inserter/icon-grid.js new file mode 100644 index 00000000000000..b5e51c247a428f --- /dev/null +++ b/packages/block-library/src/icon/components/custom-inserter/icon-grid.js @@ -0,0 +1,55 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { Button } from '@wordpress/components'; + +/** + * Internal dependencies + */ +import HtmlRenderer from '../../../utils/html-renderer'; + +export default function IconGrid( { icons, onChange, attributes } ) { + return ( +
+ { icons.length === 0 ? ( +
+

{ __( 'No results found.' ) }

+
+ ) : ( +
+ { icons.map( ( icon ) => { + return ( + + ); + } ) } +
+ ) } +
+ ); +} diff --git a/packages/block-library/src/icon/components/custom-inserter/index.js b/packages/block-library/src/icon/components/custom-inserter/index.js new file mode 100644 index 00000000000000..95473de42aee2b --- /dev/null +++ b/packages/block-library/src/icon/components/custom-inserter/index.js @@ -0,0 +1,73 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { Modal, SearchControl } from '@wordpress/components'; +import { useState, useMemo, useCallback } from '@wordpress/element'; +import { useDebounce } from '@wordpress/compose'; + +/** + * Internal dependencies + */ +import IconGrid from './icon-grid'; +import { normalizeSearchInput } from '../../../utils/search-patterns'; + +export default function CustomInserterModal( { + icons, + setInserterOpen, + attributes, + setAttributes, +} ) { + const [ searchInput, setSearchInput ] = useState( '' ); + + const debouncedSetSearchInput = useDebounce( setSearchInput, 300 ); + + const setIcon = useCallback( + ( name ) => { + setAttributes( { + icon: name, + } ); + setInserterOpen( false ); + }, + [ setAttributes, setInserterOpen ] + ); + + const filteredIcons = useMemo( () => { + if ( searchInput ) { + const input = normalizeSearchInput( searchInput ); + return icons.filter( ( icon ) => { + const iconName = normalizeSearchInput( icon.name ); + const iconLabel = normalizeSearchInput( icon.label ); + + return ( + iconName.includes( input ) || iconLabel.includes( input ) + ); + } ); + } + + return icons; + }, [ searchInput, icons ] ); + + return ( + setInserterOpen( false ) } + isFullScreen + > +
+
+ +
+ +
+
+ ); +} diff --git a/packages/block-library/src/icon/components/index.js b/packages/block-library/src/icon/components/index.js new file mode 100644 index 00000000000000..2a53f2d299b798 --- /dev/null +++ b/packages/block-library/src/icon/components/index.js @@ -0,0 +1 @@ +export { default as CustomInserterModal } from './custom-inserter'; diff --git a/packages/block-library/src/icon/edit.js b/packages/block-library/src/icon/edit.js new file mode 100644 index 00000000000000..03e39c8ddd7380 --- /dev/null +++ b/packages/block-library/src/icon/edit.js @@ -0,0 +1,187 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { + DropdownMenu, + TextControl, + ToolbarButton, + ToolbarGroup, + __experimentalToolsPanel as ToolsPanel, + __experimentalToolsPanelItem as ToolsPanelItem, + Placeholder, +} from '@wordpress/components'; +import { + BlockControls, + InspectorControls, + useBlockProps, + useBlockEditingMode, + store as blockEditorStore, +} from '@wordpress/block-editor'; +import { useDispatch, useSelect } from '@wordpress/data'; +import { store as coreDataStore } from '@wordpress/core-data'; +import { useState, useEffect } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import { useToolsPanelDropdownMenuProps } from '../utils/hooks'; +import HtmlRenderer from '../utils/html-renderer'; +import { CustomInserterModal } from './components'; +import { unlock } from '../lock-unlock'; + +export function Edit( { attributes, setAttributes } ) { + const { icon, ariaLabel, style } = attributes; + + const [ isInserterOpen, setInserterOpen ] = useState( false ); + + const { __unstableMarkNextChangeAsNotPersistent } = + useDispatch( blockEditorStore ); + + const isContentOnlyMode = useBlockEditingMode() === 'contentOnly'; + + const allIcons = useSelect( ( select ) => { + return unlock( select( coreDataStore ) ).getIcons(); + }, [] ); + + // Is the width value is 0, reset it to the default value. + useEffect( () => { + if ( + ! style?.dimensions?.width || + parseFloat( style?.dimensions?.width ) === 0 + ) { + // To avoid interfering with undo/redo operations any changes in this + // effect must not make history and should be preceded by + // `__unstableMarkNextChangeAsNotPersistent()`. + __unstableMarkNextChangeAsNotPersistent(); + setAttributes( { + style: { + ...style, + dimensions: { ...style?.dimensions, width: '12px' }, + }, + } ); + } + }, [ + icon, + style, + setAttributes, + __unstableMarkNextChangeAsNotPersistent, + ] ); + + const iconToDisplay = + allIcons?.length > 0 + ? allIcons?.find( ( { name } ) => name === icon )?.content + : ''; + + const blockControls = ( + <> + + { + setInserterOpen( true ); + } } + > + { icon ? __( 'Replace' ) : __( 'Choose icon' ) } + + + { isContentOnlyMode && icon && ( + // Add some extra controls for content attributes when content only mode is active. + // With content only mode active, the inspector is hidden, so users need another way + // to edit these attributes. + + + + { () => ( + + setAttributes( { ariaLabel: value } ) + } + help={ __( + 'Briefly describe the icon to help screen reader users. Leave blank for decorative icons.' + ) } + __next40pxDefaultSize + /> + ) } + + + + ) } + + ); + const dropdownMenuProps = useToolsPanelDropdownMenuProps(); + const inspectorControls = icon && ( + <> + + + setAttributes( { + ariaLabel: undefined, + } ) + } + dropdownMenuProps={ dropdownMenuProps } + > + !! ariaLabel } + onDeselect={ () => + setAttributes( { ariaLabel: undefined } ) + } + > + + setAttributes( { ariaLabel: value } ) + } + __next40pxDefaultSize + /> + + + + + ); + + return ( + <> + { blockControls } + { inspectorControls } +
+ { icon ? ( + + ) : ( + + ) } +
+ { isInserterOpen && ( + + ) } + + ); +} + +export default Edit; diff --git a/packages/block-library/src/icon/editor.scss b/packages/block-library/src/icon/editor.scss new file mode 100644 index 00000000000000..1ca78c6a46d6bd --- /dev/null +++ b/packages/block-library/src/icon/editor.scss @@ -0,0 +1,57 @@ +@use "@wordpress/base-styles/variables" as *; +@use "@wordpress/base-styles/colors" as *; + +// Style for the icon library modal. +.wp-block-icon__inserter { + padding: 0 $grid-unit-30; + margin: 0 (-1 * $grid-unit-30); +} + +.wp-block-icon__inserter-header { + align-items: center; + display: flex; + justify-content: space-between; + margin-bottom: $grid-unit-20; +} + +.wp-block-icon__inserter-grid-icons-list { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); +} + +.wp-block-icon__inserter-grid-no-results { + display: flex; + justify-content: center; +} + +.wp-block-icon__inserter-grid-icons-list-item { + display: flex; + flex-direction: column; + height: auto !important; +} + +.wp-block-icon__inserter-grid-icons-list-item-icon { + padding: $grid-unit-15; +} + +.wp-block-icon__inserter-grid-icons-list-item-title { + font-size: $font-size-small; + padding: $grid-unit-05 $grid-unit-05 $grid-unit-10; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.wp-block-icon__toolbar-content { + width: 250px; +} + +// Provide special styling for the placeholder. +// @todo this particular minimal style of placeholder could be componentized further. +.wp-block-icon .components-placeholder { + padding: 0; + min-height: $grid-unit-30; + min-width: $grid-unit-30; + height: 100%; + width: 100%; +} diff --git a/packages/block-library/src/icon/icon.js b/packages/block-library/src/icon/icon.js new file mode 100644 index 00000000000000..019de4281a5294 --- /dev/null +++ b/packages/block-library/src/icon/icon.js @@ -0,0 +1,14 @@ +/** + * WordPress dependencies + */ +import { SVG, Path } from '@wordpress/components'; + +/** + * SVG to represent the block. + */ +export const icon = ( + + + +); +export default icon; diff --git a/packages/block-library/src/icon/index.js b/packages/block-library/src/icon/index.js new file mode 100644 index 00000000000000..d83f59c00670b5 --- /dev/null +++ b/packages/block-library/src/icon/index.js @@ -0,0 +1,26 @@ +/** + * Internal dependencies + */ +import initBlock from '../utils/init-block'; +import edit from './edit'; +import metadata from './block.json'; +import icon from './icon'; + +const { name } = metadata; +export { metadata, name }; +export const settings = { + icon, + example: { + attributes: { + icon: 'core/audio', + style: { + dimensions: { + width: '48px', + }, + }, + }, + }, + edit, +}; + +export const init = () => initBlock( { name, metadata, settings } ); diff --git a/packages/block-library/src/icon/index.php b/packages/block-library/src/icon/index.php new file mode 100644 index 00000000000000..e1cf2815ef8656 --- /dev/null +++ b/packages/block-library/src/icon/index.php @@ -0,0 +1,65 @@ +get_registered_icon( $attributes['icon'] ); + + if ( is_null( $icon ) ) { + return; + } + + $aria_label = ! empty( $attributes['ariaLabel'] ) ? $attributes['ariaLabel'] : ''; + + // Process the markup. + $processor = new WP_HTML_Tag_Processor( $icon['content'] ); + $processor->next_tag( 'svg' ); + if ( ! $aria_label ) { + // Icon is decorative, hide it from screen readers. + $processor->set_attribute( 'aria-hidden', 'true' ); + $processor->set_attribute( 'focusable', 'false' ); + } else { + $processor->set_attribute( 'role', 'img' ); + $processor->set_attribute( 'aria-label', $aria_label ); + } + + // Return the updated SVG markup. + $svg = $processor->get_updated_html(); + $attributes = get_block_wrapper_attributes(); + return sprintf( '
%s
', $attributes, $svg ); +} + + +/** + * Registers the `core/icon` block on server. + * + * @since 7.0.0 + */ +function register_block_core_icon() { + register_block_type_from_metadata( + __DIR__ . '/icon', + array( + 'render_callback' => 'render_block_core_icon', + ) + ); +} +add_action( 'init', 'register_block_core_icon' ); diff --git a/packages/block-library/src/icon/style.scss b/packages/block-library/src/icon/style.scss new file mode 100644 index 00000000000000..200b5b479277ef --- /dev/null +++ b/packages/block-library/src/icon/style.scss @@ -0,0 +1,13 @@ +/** + * Editor and frontend styles for the Icon Block. + */ + +/* Icon Block styles. */ +.wp-block-icon { + line-height: 0; + svg { + width: 100%; + height: 100%; + fill: currentColor; + } +} diff --git a/packages/block-library/src/index.js b/packages/block-library/src/index.js index f891ec38c0aa2d..65e685cd6059d4 100644 --- a/packages/block-library/src/index.js +++ b/packages/block-library/src/index.js @@ -74,6 +74,7 @@ import * as group from './group'; import * as heading from './heading'; import * as homeLink from './home-link'; import * as html from './html'; +import * as icon from './icon'; import * as image from './image'; import * as latestComments from './latest-comments'; import * as latestPosts from './latest-posts'; @@ -297,6 +298,10 @@ const getAllBlocks = () => { blocks.push( playlistTrack ); } + if ( window?.__experimentalEnableIconBlock ) { + blocks.push( icon ); + } + // When in a WordPress context, conditionally // add the classic block and TinyMCE editor // under any of the following conditions: diff --git a/packages/block-library/src/navigation/block.json b/packages/block-library/src/navigation/block.json index 78941f9c3b575f..c13ac0000f34df 100644 --- a/packages/block-library/src/navigation/block.json +++ b/packages/block-library/src/navigation/block.json @@ -11,6 +11,7 @@ "core/page-list", "core/spacer", "core/home-link", + "core/icon", "core/site-title", "core/site-logo", "core/navigation-submenu", diff --git a/packages/block-library/src/style.scss b/packages/block-library/src/style.scss index 1aac2fc64e05ca..f1c652d56b2dce 100644 --- a/packages/block-library/src/style.scss +++ b/packages/block-library/src/style.scss @@ -28,6 +28,7 @@ @use "./gallery/style.scss" as *; @use "./group/style.scss" as *; @use "./heading/style.scss" as *; +@use "./icon/style.scss" as *; @use "./image/style.scss" as *; @use "./latest-comments/style.scss" as *; @use "./latest-posts/style.scss" as *; diff --git a/packages/core-data/src/private-actions.js b/packages/core-data/src/private-actions.js index 856062b46fd92e..27ceda015da374 100644 --- a/packages/core-data/src/private-actions.js +++ b/packages/core-data/src/private-actions.js @@ -160,3 +160,17 @@ export function receiveEditorAssets( assets ) { assets, }; } + +/** + * Returns an action object used to receive icons. + * + * @param {Array} icons List of icons. + * + * @return {Object} Action object. + */ +export function receiveIcons( icons ) { + return { + type: 'RECEIVE_ICONS', + icons, + }; +} diff --git a/packages/core-data/src/private-selectors.ts b/packages/core-data/src/private-selectors.ts index 3c2a5446dda7c2..36517505274e42 100644 --- a/packages/core-data/src/private-selectors.ts +++ b/packages/core-data/src/private-selectors.ts @@ -6,7 +6,12 @@ import { createSelector, createRegistrySelector } from '@wordpress/data'; /** * Internal dependencies */ -import { getDefaultTemplateId, getEntityRecord, type State } from './selectors'; +import { + getDefaultTemplateId, + getEntityRecord, + type State, + type Icon, +} from './selectors'; import { STORE_NAME } from './name'; import { unlock } from './lock-unlock'; import { getSyncManager } from './sync'; @@ -308,3 +313,13 @@ export function getEditorSettings( export function getEditorAssets( state: State ): Record< string, any > | null { return state.editorAssets; } + +/** + * Returns the list of available icons. + * + * @param state Data state. + * @return The list of icons or empty array if not loaded. + */ +export function getIcons( state: State ): Icon[] { + return state.icons ?? []; +} diff --git a/packages/core-data/src/reducer.js b/packages/core-data/src/reducer.js index f2acaa34fb8c60..dd6ffc177b07be 100644 --- a/packages/core-data/src/reducer.js +++ b/packages/core-data/src/reducer.js @@ -660,6 +660,22 @@ export function editorAssets( state = null, action ) { return state; } +/** + * Reducer managing icons. + * + * @param {Array} state Current state. + * @param {Object} action Action object. + * + * @return {Array} Updated state. + */ +export function icons( state = [], action ) { + switch ( action.type ) { + case 'RECEIVE_ICONS': + return action.icons; + } + return state; +} + export default combineReducers( { users, currentTheme, @@ -682,4 +698,5 @@ export default combineReducers( { registeredPostMeta, editorSettings, editorAssets, + icons, } ); diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index bf77698208eda1..e7bc0f5173323b 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -1254,3 +1254,15 @@ export const getEditorAssets = } ); dispatch.receiveEditorAssets( assets ); }; + +/** + * Requests icons from the REST API. + */ +export const getIcons = + () => + async ( { dispatch } ) => { + const icons = await apiFetch( { + path: '/wp/v2/icons', + } ); + dispatch.receiveIcons( icons ); + }; diff --git a/packages/core-data/src/selectors.ts b/packages/core-data/src/selectors.ts index f322e85326f73a..84ee439d995058 100644 --- a/packages/core-data/src/selectors.ts +++ b/packages/core-data/src/selectors.ts @@ -52,10 +52,17 @@ export interface State { registeredPostMeta: Record< string, Object >; editorSettings: Record< string, any > | null; editorAssets: Record< string, any > | null; + icons: Icon[]; } type EntityRecordKey = string | number; +export interface Icon { + name: string; + content: string; + label: string; +} + interface EntitiesState { config: EntityConfig[]; records: Record< string, Record< string, EntityState< ET.EntityRecord > > >; diff --git a/test/integration/fixtures/blocks/core__icon.html b/test/integration/fixtures/blocks/core__icon.html new file mode 100644 index 00000000000000..c6c2c59ef044b4 --- /dev/null +++ b/test/integration/fixtures/blocks/core__icon.html @@ -0,0 +1 @@ + diff --git a/test/integration/fixtures/blocks/core__icon.json b/test/integration/fixtures/blocks/core__icon.json new file mode 100644 index 00000000000000..bf6d3621208325 --- /dev/null +++ b/test/integration/fixtures/blocks/core__icon.json @@ -0,0 +1,14 @@ +[ + { + "name": "core/icon", + "isValid": true, + "attributes": { + "style": { + "dimensions": { + "width": "24px" + } + } + }, + "innerBlocks": [] + } +] diff --git a/test/integration/fixtures/blocks/core__icon.parsed.json b/test/integration/fixtures/blocks/core__icon.parsed.json new file mode 100644 index 00000000000000..e02039a280361a --- /dev/null +++ b/test/integration/fixtures/blocks/core__icon.parsed.json @@ -0,0 +1,9 @@ +[ + { + "blockName": "core/icon", + "attrs": {}, + "innerBlocks": [], + "innerHTML": "", + "innerContent": [] + } +] diff --git a/test/integration/fixtures/blocks/core__icon.serialized.html b/test/integration/fixtures/blocks/core__icon.serialized.html new file mode 100644 index 00000000000000..c6c2c59ef044b4 --- /dev/null +++ b/test/integration/fixtures/blocks/core__icon.serialized.html @@ -0,0 +1 @@ + diff --git a/test/integration/full-content/full-content.test.js b/test/integration/full-content/full-content.test.js index 471b8797bf9a21..7177b7048743e0 100644 --- a/test/integration/full-content/full-content.test.js +++ b/test/integration/full-content/full-content.test.js @@ -1,12 +1,13 @@ /** * External dependencies */ -import glob from 'fast-glob'; import { format } from 'util'; +import glob from 'fast-glob'; /** * WordPress dependencies */ +import prettierConfig from '@wordpress/prettier-config'; import { getBlockTypes, parse, @@ -18,7 +19,6 @@ import { registerCoreBlocks, __experimentalRegisterExperimentalCoreBlocks, } from '@wordpress/block-library'; -import prettierConfig from '@wordpress/prettier-config'; /** * Internal dependencies @@ -66,6 +66,9 @@ describe( 'full post content fixture', () => { // Form-related blocks will not be registered unless they are opted // in on the experimental settings page. window.__experimentalEnableFormBlocks = true; + // Icon block will not be registered unless are opted into on the + // experimental settings page. + window.__experimentalEnableIconBlock = true; registerCoreBlocks(); if ( globalThis.IS_GUTENBERG_PLUGIN ) {