From a8d2475a6e9b3cc17c18c38061da870650dcca87 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Thu, 10 Jun 2021 10:03:27 +0800 Subject: [PATCH 01/20] Fix block multi selection in nested blocks (#32536) * Only allow multi selections for blocks with the same parent * Update unit tests * Update e2e test --- packages/block-editor/src/store/actions.js | 16 ++++++ .../block-editor/src/store/test/actions.js | 50 +++++++++++++++++-- .../various/multi-block-selection.test.js | 14 ++++++ 3 files changed, 77 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index 69da6c75860edf..ec1bb964de3c0a 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -277,6 +277,22 @@ export function stopMultiSelect() { * @param {string} end Last block of the multiselection. */ export function* multiSelect( start, end ) { + const startBlockRootClientId = yield controls.select( + blockEditorStoreName, + 'getBlockRootClientId', + start + ); + const endBlockRootClientId = yield controls.select( + blockEditorStoreName, + 'getBlockRootClientId', + end + ); + + // Only allow block multi-selections at the same level. + if ( startBlockRootClientId !== endBlockRootClientId ) { + return; + } + yield { type: 'MULTI_SELECT', start, diff --git a/packages/block-editor/src/store/test/actions.js b/packages/block-editor/src/store/test/actions.js index 6433f15e6523e7..c651122f77ad72 100644 --- a/packages/block-editor/src/store/test/actions.js +++ b/packages/block-editor/src/store/test/actions.js @@ -147,16 +147,60 @@ describe( 'actions', () => { } ); } ); describe( 'multiSelect', () => { - it( 'should return MULTI_SELECT action', () => { + it( 'should return MULTI_SELECT action if blocks have the same root client id', () => { const start = 'start'; const end = 'end'; - const fulfillment = multiSelect( start, end ); - expect( fulfillment.next().value ).toEqual( { + const multiSelectGenerator = multiSelect( start, end ); + + expect( multiSelectGenerator.next().value ).toEqual( + controls.select( + blockEditorStoreName, + 'getBlockRootClientId', + start + ) + ); + + expect( multiSelectGenerator.next( 'parent' ).value ).toEqual( + controls.select( + blockEditorStoreName, + 'getBlockRootClientId', + end + ) + ); + + expect( multiSelectGenerator.next( 'parent' ).value ).toEqual( { type: 'MULTI_SELECT', start, end, } ); } ); + + it( 'should return undefined if blocks have different root client ids', () => { + const start = 'start'; + const end = 'end'; + const multiSelectGenerator = multiSelect( start, end ); + + expect( multiSelectGenerator.next().value ).toEqual( + controls.select( + blockEditorStoreName, + 'getBlockRootClientId', + start + ) + ); + + expect( multiSelectGenerator.next( 'parent' ).value ).toEqual( + controls.select( + blockEditorStoreName, + 'getBlockRootClientId', + end + ) + ); + + expect( multiSelectGenerator.next( 'another parent' ) ).toEqual( { + done: true, + value: undefined, + } ); + } ); } ); describe( 'clearSelectedBlock', () => { diff --git a/packages/e2e-tests/specs/editor/various/multi-block-selection.test.js b/packages/e2e-tests/specs/editor/various/multi-block-selection.test.js index eba80dd658a89b..f8d748eaa285ca 100644 --- a/packages/e2e-tests/specs/editor/various/multi-block-selection.test.js +++ b/packages/e2e-tests/specs/editor/various/multi-block-selection.test.js @@ -9,6 +9,7 @@ import { getEditedPostContent, clickBlockToolbarButton, clickButton, + clickMenuItem, } from '@wordpress/e2e-test-utils'; async function getSelectedFlatIndices() { @@ -272,6 +273,19 @@ describe( 'Multi-block selection', () => { await testNativeSelection(); expect( await getSelectedFlatIndices() ).toEqual( [ 1, 2 ] ); + + // Group the blocks and test that multiselection also works for nested + // blocks. Checks for regressions of + // https://github.com/WordPress/gutenberg/issues/32056 + + await clickBlockToolbarButton( 'Options' ); + await clickMenuItem( 'Group' ); + await page.click( '[data-type="core/paragraph"]' ); + await page.keyboard.down( 'Shift' ); + await page.click( '[data-type="core/paragraph"]:nth-child(2)' ); + await page.keyboard.up( 'Shift' ); + await testNativeSelection(); + expect( await getSelectedFlatIndices() ).toEqual( [ 2, 3 ] ); } ); it( 'should select by dragging', async () => { From 11e57ea5ca4df4e7d1347dab495d7781c3ea1127 Mon Sep 17 00:00:00 2001 From: tellthemachines Date: Thu, 10 Jun 2021 12:10:57 +1000 Subject: [PATCH 02/20] Save deleted and restored widgets. (#32534) --- packages/edit-widgets/src/store/actions.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/edit-widgets/src/store/actions.js b/packages/edit-widgets/src/store/actions.js index 7ae0bb06d65324..d31280c0a0133b 100644 --- a/packages/edit-widgets/src/store/actions.js +++ b/packages/edit-widgets/src/store/actions.js @@ -140,7 +140,9 @@ export function* saveWidgetArea( widgetAreaId ) { // since order is important. sidebarWidgetsIds.push( widgetId ); - if ( widgetId ) { + // We need to check for the id in the widget object here, because a deleted + // and restored widget won't have this id. + if ( widget.id ) { yield dispatch( 'core', 'editEntityRecord', From 862918690970d51acb51d818cfd020bdfe4fcfc9 Mon Sep 17 00:00:00 2001 From: Ramon Date: Thu, 10 Jun 2021 14:37:57 +1000 Subject: [PATCH 03/20] Widgets editor: Add Breadcrumbs Block (#32498) --- .../src/components/layout/interface.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/edit-widgets/src/components/layout/interface.js b/packages/edit-widgets/src/components/layout/interface.js index 22320cac6b1f0e..cf69328dd414a5 100644 --- a/packages/edit-widgets/src/components/layout/interface.js +++ b/packages/edit-widgets/src/components/layout/interface.js @@ -7,7 +7,10 @@ import { useViewportMatch, } from '@wordpress/compose'; import { close } from '@wordpress/icons'; -import { __experimentalLibrary as Library } from '@wordpress/block-editor'; +import { + __experimentalLibrary as Library, + BlockBreadcrumb, +} from '@wordpress/block-editor'; import { useEffect } from '@wordpress/element'; import { useDispatch, useSelect } from '@wordpress/data'; import { @@ -32,6 +35,8 @@ const interfaceLabels = { body: __( 'Widgets and blocks' ), /* translators: accessibility text for the widgets screen settings landmark region. */ sidebar: __( 'Widgets settings' ), + /* translators: accessibility text for the widgets screen footer landmark region. */ + footer: __( 'Widgets footer' ), }; function Interface( { blockEditorSettings } ) { @@ -107,6 +112,13 @@ function Interface( { blockEditorSettings } ) { blockEditorSettings={ blockEditorSettings } /> } + footer={ + ! isMobileViewport && ( +
+ +
+ ) + } /> ); } From beaaf606618d9269a52c2ced06f8b8d0912d3467 Mon Sep 17 00:00:00 2001 From: Jorge Costa Date: Thu, 10 Jun 2021 10:40:53 +0100 Subject: [PATCH 04/20] Enqueue core and theme colors by using separate structures per origin. (#32358) --- lib/class-wp-theme-json-gutenberg.php | 146 +++---- ...class-wp-theme-json-resolver-gutenberg.php | 8 +- lib/experimental-default-theme.json | 72 ++-- lib/global-styles.php | 35 +- .../src/components/use-setting/index.js | 34 +- .../editor/global-styles-provider.js | 64 +-- .../editor/global-styles-renderer.js | 51 ++- .../editor/test/global-styles-renderer.js | 62 ++- .../edit-site/src/components/editor/utils.js | 24 +- .../components/sidebar/color-palette-panel.js | 41 +- .../class-wp-theme-json-schema-v0-test.php | 207 +++++----- phpunit/class-wp-theme-json-test.php | 390 +++++++++--------- 12 files changed, 590 insertions(+), 544 deletions(-) diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 16c41bb15b160a..5e44f1a9ba82b2 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -641,6 +641,34 @@ private static function append_to_selector( $selector, $to_append ) { return implode( ',', $new_selectors ); } + /** + * Function that given an array of presets keyed by origin + * and the value key of the preset returns an array where each key is + * the a preset slug and each value is the preset value. + * + * @param array $preset_per_origin Array of presets keyed by origin. + * @param string $value_key The property of the preset that contains its value. + * + * @return array Array of presets where each key is a slug and each value is the preset value. + */ + private static function get_merged_preset_by_slug( $preset_per_origin, $value_key ) { + $origins = array( 'core', 'theme', 'user' ); + $result = array(); + foreach ( $origins as $origin ) { + if ( ! isset( $preset_per_origin[ $origin ] ) ) { + continue; + } + foreach ( $preset_per_origin[ $origin ] as $preset ) { + // We don't want to use kebabCase here, + // see https://github.com/WordPress/gutenberg/issues/32347 + // However, we need to make sure the generated class or css variable + // doesn't contain spaces. + $result[ preg_replace( '/\s+/', '-', $preset['slug'] ) ] = $preset[ $value_key ]; + } + } + return $result; + } + /** * Given a settings array, it returns the generated rulesets * for the preset classes. @@ -659,19 +687,16 @@ private static function compute_preset_classes( $settings, $selector ) { $stylesheet = ''; foreach ( self::PRESETS_METADATA as $preset ) { - $values = _wp_array_get( $settings, $preset['path'], array() ); - foreach ( $values as $value ) { - foreach ( $preset['classes'] as $class ) { + $preset_per_origin = _wp_array_get( $settings, $preset['path'], array() ); + $preset_by_slug = self::get_merged_preset_by_slug( $preset_per_origin, $preset['value_key'] ); + foreach ( $preset['classes'] as $class ) { + foreach ( $preset_by_slug as $slug => $value ) { $stylesheet .= self::to_ruleset( - // We don't want to use kebabCase here, - // see https://github.com/WordPress/gutenberg/issues/32347 - // However, we need to make sure the generated class - // doesn't contain spaces. - self::append_to_selector( $selector, '.has-' . preg_replace( '/\s+/', '-', $value['slug'] ) . '-' . $class['class_suffix'] ), + self::append_to_selector( $selector, '.has-' . $slug . '-' . $class['class_suffix'] ), array( array( 'name' => $class['property_name'], - 'value' => $value[ $preset['value_key'] ] . ' !important', + 'value' => $value . ' !important', ), ) ); @@ -701,11 +726,12 @@ private static function compute_preset_classes( $settings, $selector ) { private static function compute_preset_vars( $settings ) { $declarations = array(); foreach ( self::PRESETS_METADATA as $preset ) { - $values = _wp_array_get( $settings, $preset['path'], array() ); - foreach ( $values as $value ) { + $preset_per_origin = _wp_array_get( $settings, $preset['path'], array() ); + $preset_by_slug = self::get_merged_preset_by_slug( $preset_per_origin, $preset['value_key'] ); + foreach ( $preset_by_slug as $slug => $value ) { $declarations[] = array( - 'name' => '--wp--preset--' . $preset['css_var_infix'] . '--' . $value['slug'], - 'value' => $value[ $preset['value_key'] ], + 'name' => '--wp--preset--' . $preset['css_var_infix'] . '--' . $slug, + 'value' => $value, ); } } @@ -1101,85 +1127,59 @@ public function get_stylesheet( $type = 'all' ) { /** * Merge new incoming data. * - * @param WP_Theme_JSON_Gutenberg $incoming Data to merge. - * @param string $update_or_remove Whether update or remove existing colors - * for which the incoming data has a duplicated slug. + * @param WP_Theme_JSON $incoming Data to merge. + * @param string $origin origin of the incoming data (e.g: core, theme, or user). */ - public function merge( $incoming, $update_or_remove = 'remove' ) { - $incoming_data = $incoming->get_raw_data(); - $existing_data = $this->theme_json; + public function merge( $incoming, $origin ) { + + $incoming_data = $incoming->get_raw_data(); + $this->theme_json = array_replace_recursive( $this->theme_json, $incoming_data ); // The array_replace_recursive algorithm merges at the leaf level. // For leaf values that are arrays it will use the numeric indexes for replacement. - $this->theme_json = array_replace_recursive( $this->theme_json, $incoming_data ); + // In those cases, what we want is to use the incoming value, if it exists. + // + // These are the cases that have array values at the leaf levels. + $properties = array(); + $properties[] = array( 'custom' ); + $properties[] = array( 'spacing', 'units' ); + $properties[] = array( 'color', 'duotone' ); - // There are a few cases in which we want to merge things differently - // from what array_replace_recursive does. - - // Some incoming properties should replace the existing. - $to_replace = array(); - $to_replace[] = array( 'custom' ); - $to_replace[] = array( 'spacing', 'units' ); - $to_replace[] = array( 'typography', 'fontSizes' ); - $to_replace[] = array( 'typography', 'fontFamilies' ); - - // Some others should be appended to the existing. - // If the slug is the same than an existing element, - // the $update_or_remove param is used to decide - // what to do with the existing element: - // either remove it and append the incoming, - // or update it with the incoming. $to_append = array(); - $to_append[] = array( 'color', 'duotone' ); - $to_append[] = array( 'color', 'gradients' ); $to_append[] = array( 'color', 'palette' ); + $to_append[] = array( 'color', 'gradients' ); + $to_append[] = array( 'typography', 'fontSizes' ); + $to_append[] = array( 'typography', 'fontFamilies' ); $nodes = self::get_setting_nodes( $this->theme_json ); foreach ( $nodes as $metadata ) { - foreach ( $to_replace as $path_to_replace ) { - $path = array_merge( $metadata['path'], $path_to_replace ); + foreach ( $properties as $property_path ) { + $path = array_merge( $metadata['path'], $property_path ); $node = _wp_array_get( $incoming_data, $path, array() ); if ( ! empty( $node ) ) { gutenberg_experimental_set( $this->theme_json, $path, $node ); } } - foreach ( $to_append as $path_to_append ) { - $path = array_merge( $metadata['path'], $path_to_append ); - $incoming_node = _wp_array_get( $incoming_data, $path, array() ); - $existing_node = _wp_array_get( $existing_data, $path, array() ); - - if ( empty( $incoming_node ) && empty( $existing_node ) ) { - continue; - } - $index_table = array(); - $existing_slugs = array(); - $merged = array(); - foreach ( $existing_node as $key => $value ) { - $index_table[ $value['slug'] ] = $key; - $existing_slugs[] = $value['slug']; - $merged[ $key ] = $value; - } - - $to_remove = array(); - foreach ( $incoming_node as $value ) { - if ( ! in_array( $value['slug'], $existing_slugs, true ) ) { - $merged[] = $value; - } elseif ( 'update' === $update_or_remove ) { - $merged[ $index_table[ $value['slug'] ] ] = $value; + foreach ( $to_append as $property_path ) { + $path = array_merge( $metadata['path'], $property_path ); + $node = _wp_array_get( $incoming_data, $path, null ); + if ( null !== $node ) { + $existing_node = _wp_array_get( $this->theme_json, $path, null ); + $new_node = array_filter( + $existing_node, + function ( $key ) { + return in_array( $key, array( 'core', 'theme', 'user ' ), true ); + }, + ARRAY_FILTER_USE_KEY + ); + if ( isset( $node[ $origin ] ) ) { + $new_node[ $origin ] = $node[ $origin ]; } else { - $merged[] = $value; - $to_remove[] = $index_table[ $value['slug'] ]; + $new_node[ $origin ] = $node; } + gutenberg_experimental_set( $this->theme_json, $path, $new_node ); } - - // Remove the duplicated values and pack the sparsed array. - foreach ( $to_remove as $index ) { - unset( $merged[ $index ] ); - } - $merged = array_values( $merged ); - - gutenberg_experimental_set( $this->theme_json, $path, $merged ); } } diff --git a/lib/class-wp-theme-json-resolver-gutenberg.php b/lib/class-wp-theme-json-resolver-gutenberg.php index bcdedda86f30b7..e37264d25319b2 100644 --- a/lib/class-wp-theme-json-resolver-gutenberg.php +++ b/lib/class-wp-theme-json-resolver-gutenberg.php @@ -290,7 +290,7 @@ public static function get_theme_data( $theme_support_data = array() ) { * to override the ones declared via add_theme_support. */ $with_theme_supports = new WP_Theme_JSON_Gutenberg( $theme_support_data ); - $with_theme_supports->merge( self::$theme ); + $with_theme_supports->merge( self::$theme, 'theme' ); return $with_theme_supports; } @@ -415,11 +415,11 @@ public static function get_merged_data( $settings = array(), $origin = 'user' ) $theme_support_data = WP_Theme_JSON_Gutenberg::get_from_editor_settings( $settings ); $result = new WP_Theme_JSON_Gutenberg(); - $result->merge( self::get_core_data() ); - $result->merge( self::get_theme_data( $theme_support_data ) ); + $result->merge( self::get_core_data(), 'core' ); + $result->merge( self::get_theme_data( $theme_support_data ), 'theme' ); if ( 'user' === $origin ) { - $result->merge( self::get_user_data(), 'update' ); + $result->merge( self::get_user_data(), 'user' ); } return $result; diff --git a/lib/experimental-default-theme.json b/lib/experimental-default-theme.json index dc4dbbaf058529..d92547a1468952 100644 --- a/lib/experimental-default-theme.json +++ b/lib/experimental-default-theme.json @@ -6,148 +6,124 @@ { "name": "Black", "slug": "black", - "color": "#000000", - "origin": "core" + "color": "#000000" }, { "name": "Cyan bluish gray", "slug": "cyan-bluish-gray", - "color": "#abb8c3", - "origin": "core" + "color": "#abb8c3" }, { "name": "White", "slug": "white", - "color": "#ffffff", - "origin": "core" + "color": "#ffffff" }, { "name": "Pale pink", "slug": "pale-pink", - "color": "#f78da7", - "origin": "core" + "color": "#f78da7" }, { "name": "Vivid red", "slug": "vivid-red", - "color": "#cf2e2e", - "origin": "core" + "color": "#cf2e2e" }, { "name": "Luminous vivid orange", "slug": "luminous-vivid-orange", - "color": "#ff6900", - "origin": "core" + "color": "#ff6900" }, { "name": "Luminous vivid amber", "slug": "luminous-vivid-amber", - "color": "#fcb900", - "origin": "core" + "color": "#fcb900" }, { "name": "Light green cyan", "slug": "light-green-cyan", - "color": "#7bdcb5", - "origin": "core" + "color": "#7bdcb5" }, { "name": "Vivid green cyan", "slug": "vivid-green-cyan", - "color": "#00d084", - "origin": "core" + "color": "#00d084" }, { "name": "Pale cyan blue", "slug": "pale-cyan-blue", - "color": "#8ed1fc", - "origin": "core" + "color": "#8ed1fc" }, { "name": "Vivid cyan blue", "slug": "vivid-cyan-blue", - "color": "#0693e3", - "origin": "core" + "color": "#0693e3" }, { "name": "Vivid purple", "slug": "vivid-purple", - "color": "#9b51e0", - "origin": "core" + "color": "#9b51e0" } ], "gradients": [ { "name": "Vivid cyan blue to vivid purple", "gradient": "linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)", - "slug": "vivid-cyan-blue-to-vivid-purple", - "origin": "core" + "slug": "vivid-cyan-blue-to-vivid-purple" }, { "name": "Light green cyan to vivid green cyan", "gradient": "linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%)", - "slug": "light-green-cyan-to-vivid-green-cyan", - "origin": "core" + "slug": "light-green-cyan-to-vivid-green-cyan" }, { "name": "Luminous vivid amber to luminous vivid orange", "gradient": "linear-gradient(135deg,rgba(252,185,0,1) 0%,rgba(255,105,0,1) 100%)", - "slug": "luminous-vivid-amber-to-luminous-vivid-orange", - "origin": "core" + "slug": "luminous-vivid-amber-to-luminous-vivid-orange" }, { "name": "Luminous vivid orange to vivid red", "gradient": "linear-gradient(135deg,rgba(255,105,0,1) 0%,rgb(207,46,46) 100%)", - "slug": "luminous-vivid-orange-to-vivid-red", - "origin": "core" + "slug": "luminous-vivid-orange-to-vivid-red" }, { "name": "Very light gray to cyan bluish gray", "gradient": "linear-gradient(135deg,rgb(238,238,238) 0%,rgb(169,184,195) 100%)", - "slug": "very-light-gray-to-cyan-bluish-gray", - "origin": "core" + "slug": "very-light-gray-to-cyan-bluish-gray" }, { "name": "Cool to warm spectrum", "gradient": "linear-gradient(135deg,rgb(74,234,220) 0%,rgb(151,120,209) 20%,rgb(207,42,186) 40%,rgb(238,44,130) 60%,rgb(251,105,98) 80%,rgb(254,248,76) 100%)", - "slug": "cool-to-warm-spectrum", - "origin": "core" + "slug": "cool-to-warm-spectrum" }, { "name": "Blush light purple", "gradient": "linear-gradient(135deg,rgb(255,206,236) 0%,rgb(152,150,240) 100%)", - "slug": "blush-light-purple", - "origin": "core" + "slug": "blush-light-purple" }, { "name": "Blush bordeaux", "gradient": "linear-gradient(135deg,rgb(254,205,165) 0%,rgb(254,45,45) 50%,rgb(107,0,62) 100%)", - "slug": "blush-bordeaux", - "origin": "core" + "slug": "blush-bordeaux" }, { "name": "Luminous dusk", "gradient": "linear-gradient(135deg,rgb(255,203,112) 0%,rgb(199,81,192) 50%,rgb(65,88,208) 100%)", - "slug": "luminous-dusk", - "origin": "core" + "slug": "luminous-dusk" }, { "name": "Pale ocean", "gradient": "linear-gradient(135deg,rgb(255,245,203) 0%,rgb(182,227,212) 50%,rgb(51,167,181) 100%)", - "slug": "pale-ocean", - "origin": "core" + "slug": "pale-ocean" }, { "name": "Electric grass", "gradient": "linear-gradient(135deg,rgb(202,248,128) 0%,rgb(113,206,126) 100%)", - "slug": "electric-grass", - "origin": "core" + "slug": "electric-grass" }, { "name": "Midnight", "gradient": "linear-gradient(135deg,rgb(2,3,129) 0%,rgb(40,116,252) 100%)", - "slug": "midnight", - "origin": "core" + "slug": "midnight" } ], "duotone": [ diff --git a/lib/global-styles.php b/lib/global-styles.php index 2aa5c1b104538c..17462579fd6c85 100644 --- a/lib/global-styles.php +++ b/lib/global-styles.php @@ -136,14 +136,37 @@ function_exists( 'gutenberg_is_edit_site_page' ) && // Copied from get_block_editor_settings() at wordpress-develop/block-editor.php. $settings['__experimentalFeatures'] = $consolidated->get_settings(); + if ( isset( $settings['__experimentalFeatures']['color']['palette'] ) ) { - $settings['colors'] = $settings['__experimentalFeatures']['color']['palette']; - unset( $settings['__experimentalFeatures']['color']['palette'] ); + $colors_by_origin = $settings['__experimentalFeatures']['color']['palette']; + $settings['colors'] = isset( $colors_by_origin['user'] ) ? + $colors_by_origin['user'] : ( + isset( $colors_by_origin['theme'] ) ? + $colors_by_origin['theme'] : + $colors_by_origin['core'] + ); } + if ( isset( $settings['__experimentalFeatures']['color']['gradients'] ) ) { - $settings['gradients'] = $settings['__experimentalFeatures']['color']['gradients']; - unset( $settings['__experimentalFeatures']['color']['gradients'] ); + $gradients_by_origin = $settings['__experimentalFeatures']['color']['gradients']; + $settings['gradients'] = isset( $gradients_by_origin['user'] ) ? + $gradients_by_origin['user'] : ( + isset( $gradients_by_origin['theme'] ) ? + $gradients_by_origin['theme'] : + $gradients_by_origin['core'] + ); + } + + if ( isset( $settings['__experimentalFeatures']['typography']['fontSizes'] ) ) { + $font_sizes_by_origin = $settings['__experimentalFeatures']['typography']['fontSizes']; + $settings['fontSizes'] = isset( $font_sizes_by_origin['user'] ) ? + $font_sizes_by_origin['user'] : ( + isset( $font_sizes_by_origin['theme'] ) ? + $font_sizes_by_origin['theme'] : + $font_sizes_by_origin['core'] + ); } + if ( isset( $settings['__experimentalFeatures']['color']['custom'] ) ) { $settings['disableCustomColors'] = ! $settings['__experimentalFeatures']['color']['custom']; unset( $settings['__experimentalFeatures']['color']['custom'] ); @@ -152,10 +175,6 @@ function_exists( 'gutenberg_is_edit_site_page' ) && $settings['disableCustomGradients'] = ! $settings['__experimentalFeatures']['color']['customGradient']; unset( $settings['__experimentalFeatures']['color']['customGradient'] ); } - if ( isset( $settings['__experimentalFeatures']['typography']['fontSizes'] ) ) { - $settings['fontSizes'] = $settings['__experimentalFeatures']['typography']['fontSizes']; - unset( $settings['__experimentalFeatures']['typography']['fontSizes'] ); - } if ( isset( $settings['__experimentalFeatures']['typography']['customFontSize'] ) ) { $settings['disableCustomFontSizes'] = ! $settings['__experimentalFeatures']['typography']['customFontSize']; unset( $settings['__experimentalFeatures']['typography']['customFontSize'] ); diff --git a/packages/block-editor/src/components/use-setting/index.js b/packages/block-editor/src/components/use-setting/index.js index 43ee185c396617..d302ceb277425f 100644 --- a/packages/block-editor/src/components/use-setting/index.js +++ b/packages/block-editor/src/components/use-setting/index.js @@ -49,18 +49,11 @@ const deprecatedFlags = { 'spacing.customPadding': ( settings ) => settings.enableCustomSpacing, }; -const filterColorsFromCoreOrigin = ( path, setting ) => { - if ( path !== 'color.palette' && path !== 'color.gradients' ) { - return setting; - } - - if ( ! Array.isArray( setting ) ) { - return setting; - } - - const colors = setting.filter( ( color ) => color?.origin !== 'core' ); - - return colors.length > 0 ? colors : setting; +const PATHS_WITH_MERGE = { + 'color.gradients': true, + 'color.palette': true, + 'typography.fontFamilies': true, + 'typography.fontSizes': true, }; /** @@ -90,10 +83,14 @@ export default function useSetting( path ) { const experimentalFeaturesResult = get( settings, blockPath ) ?? get( settings, defaultsPath ); if ( experimentalFeaturesResult !== undefined ) { - return filterColorsFromCoreOrigin( - path, - experimentalFeaturesResult - ); + if ( PATHS_WITH_MERGE[ path ] ) { + return ( + experimentalFeaturesResult.user ?? + experimentalFeaturesResult.theme ?? + experimentalFeaturesResult.core + ); + } + return experimentalFeaturesResult; } // 2 - Use deprecated settings, otherwise. @@ -101,10 +98,7 @@ export default function useSetting( path ) { ? deprecatedFlags[ path ]( settings ) : undefined; if ( deprecatedSettingsValue !== undefined ) { - return filterColorsFromCoreOrigin( - path, - deprecatedSettingsValue - ); + return deprecatedSettingsValue; } // 3 - Fall back for typography.dropCap: diff --git a/packages/edit-site/src/components/editor/global-styles-provider.js b/packages/edit-site/src/components/editor/global-styles-provider.js index 6d173773a18499..05e672dfa05f17 100644 --- a/packages/edit-site/src/components/editor/global-styles-provider.js +++ b/packages/edit-site/src/components/editor/global-styles-provider.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { set, get, mergeWith } from 'lodash'; +import { set, get, mergeWith, mapValues, setWith, clone } from 'lodash'; /** * WordPress dependencies @@ -30,6 +30,7 @@ import { ROOT_BLOCK_SUPPORTS, getValueFromVariable, getPresetVariable, + PRESET_METADATA, } from './utils'; import { toCustomProperties, toStyles } from './global-styles-renderer'; import { store as editSiteStore } from '../../store'; @@ -47,31 +48,7 @@ const GlobalStylesContext = createContext( { /* eslint-enable no-unused-vars */ } ); -const mergeTreesCustomizer = ( objValue, srcValue, key ) => { - // Users can add their own colors. - // We want to append them when they don't - // have the same slug as an existing color, - // otherwise we want to update the existing color instead. - if ( 'palette' === key ) { - const indexTable = {}; - const existingSlugs = []; - const result = [ ...( objValue ?? [] ) ]; - result.forEach( ( { slug }, index ) => { - indexTable[ slug ] = index; - existingSlugs.push( slug ); - } ); - - ( srcValue ?? [] ).forEach( ( element ) => { - if ( existingSlugs.includes( element?.slug ) ) { - result[ indexTable[ element?.slug ] ] = element; - } else { - result.push( element ); - } - } ); - - return result; - } - +const mergeTreesCustomizer = ( objValue, srcValue ) => { // We only pass as arrays the presets, // in which case we want the new array of values // to override the old array (no merging). @@ -135,6 +112,10 @@ const getBlockMetadata = ( blockTypes ) => { return result; }; +function immutableSet( object, path, value ) { + return setWith( object ? clone( object ) : {}, path, value, clone ); +} + export default function GlobalStylesProvider( { children, baseStyles } ) { const [ content, setContent ] = useGlobalStylesEntityContent(); const { blockTypes, settings } = useSelect( ( select ) => { @@ -174,12 +155,41 @@ export default function GlobalStylesProvider( { children, baseStyles } ) { newUserStyles = EMPTY_CONTENT; } + const addUserToSettings = ( settingsToAdd ) => { + PRESET_METADATA.forEach( ( { path } ) => { + const presetData = get( settingsToAdd, path ); + if ( presetData ) { + settingsToAdd = immutableSet( settingsToAdd, path, { + user: presetData, + } ); + } + } ); + return settingsToAdd; + }; + + let userStylesWithOrigin = newUserStyles; + if ( userStylesWithOrigin.settings ) { + userStylesWithOrigin = { + ...userStylesWithOrigin, + settings: addUserToSettings( userStylesWithOrigin.settings ), + }; + if ( userStylesWithOrigin.settings.blocks ) { + userStylesWithOrigin.settings = { + ...userStylesWithOrigin.settings, + blocks: mapValues( + userStylesWithOrigin.settings.blocks, + addUserToSettings + ), + }; + } + } + // At this point, the version schema of the theme & user // is the same, so we can merge them. const newMergedStyles = mergeWith( {}, baseStyles, - newUserStyles, + userStylesWithOrigin, mergeTreesCustomizer ); diff --git a/packages/edit-site/src/components/editor/global-styles-renderer.js b/packages/edit-site/src/components/editor/global-styles-renderer.js index 45241512c0e7dc..5d3f9da5cc079b 100644 --- a/packages/edit-site/src/components/editor/global-styles-renderer.js +++ b/packages/edit-site/src/components/editor/global-styles-renderer.js @@ -52,12 +52,17 @@ function getPresetsDeclarations( blockPresets = {} ) { return reduce( PRESET_METADATA, ( declarations, { path, valueKey, cssVarInfix } ) => { - const preset = get( blockPresets, path, [] ); - preset.forEach( ( value ) => { - declarations.push( - `--wp--preset--${ cssVarInfix }--${ value.slug }: ${ value[ valueKey ] }` - ); + const presetByOrigin = get( blockPresets, path, [] ); + [ 'core', 'theme', 'user' ].forEach( ( origin ) => { + if ( presetByOrigin[ origin ] ) { + presetByOrigin[ origin ].forEach( ( value ) => { + declarations.push( + `--wp--preset--${ cssVarInfix }--${ value.slug }: ${ value[ valueKey ] }` + ); + } ); + } } ); + return declarations; }, [] @@ -78,22 +83,26 @@ function getPresetsClasses( blockSelector, blockPresets = {} ) { if ( ! classes ) { return declarations; } - const presets = get( blockPresets, path, [] ); - presets.forEach( ( preset ) => { - classes.forEach( ( { classSuffix, propertyName } ) => { - const slug = preset.slug; - const value = preset[ valueKey ]; - // We don't want to use kebabCase from lodash here - // see https://github.com/WordPress/gutenberg/issues/32347 - // However, we need to make sure the generated class - // doesn't contain spaces. - const classSelectorToUse = `.has-${ slug.replace( - /\s+/g, - '-' - ) }-${ classSuffix }`; - const selectorToUse = `${ blockSelector }${ classSelectorToUse }`; - declarations += `${ selectorToUse }{${ propertyName }: ${ value } !important;}`; - } ); + const presetByOrigin = get( blockPresets, path, [] ); + [ 'core', 'theme', 'user' ].forEach( ( origin ) => { + if ( presetByOrigin[ origin ] ) { + presetByOrigin[ origin ].forEach( ( preset ) => { + classes.forEach( ( { classSuffix, propertyName } ) => { + const slug = preset.slug; + const value = preset[ valueKey ]; + // We don't want to use kebabCase from lodash here + // see https://github.com/WordPress/gutenberg/issues/32347 + // However, we need to make sure the generated class + // doesn't contain spaces. + const classSelectorToUse = `.has-${ slug.replace( + /\s+/g, + '-' + ) }-${ classSuffix }`; + const selectorToUse = `${ blockSelector }${ classSelectorToUse }`; + declarations += `${ selectorToUse }{${ propertyName }: ${ value } !important;}`; + } ); + } ); + } } ); return declarations; }, diff --git a/packages/edit-site/src/components/editor/test/global-styles-renderer.js b/packages/edit-site/src/components/editor/test/global-styles-renderer.js index 9d0f510c4be592..37798630dcd8e1 100644 --- a/packages/edit-site/src/components/editor/test/global-styles-renderer.js +++ b/packages/edit-site/src/components/editor/test/global-styles-renderer.js @@ -214,10 +214,20 @@ describe( 'global styles renderer', () => { const tree = { settings: { color: { - palette: [ - { name: 'White', slug: 'white', color: 'white' }, - { name: 'Black', slug: 'black', color: 'black' }, - ], + palette: { + user: [ + { + name: 'White', + slug: 'white', + color: 'white', + }, + { + name: 'Black', + slug: 'black', + color: 'black', + }, + ], + }, }, custom: { 'font-primary': 'value', @@ -229,18 +239,20 @@ describe( 'global styles renderer', () => { blocks: { 'core/heading': { typography: { - fontSizes: [ - { - name: 'small', - slug: 'small', - size: '12px', - }, - { - name: 'medium', - slug: 'medium', - size: '23px', - }, - ], + fontSizes: { + theme: [ + { + name: 'small', + slug: 'small', + size: '12px', + }, + { + name: 'medium', + slug: 'medium', + size: '23px', + }, + ], + }, }, }, }, @@ -264,10 +276,20 @@ describe( 'global styles renderer', () => { const tree = { settings: { color: { - palette: [ - { name: 'White', slug: 'white', color: 'white' }, - { name: 'Black', slug: 'black', color: 'black' }, - ], + palette: { + core: [ + { + name: 'White', + slug: 'white', + color: 'white', + }, + { + name: 'Black', + slug: 'black', + color: 'black', + }, + ], + }, }, }, styles: { diff --git a/packages/edit-site/src/components/editor/utils.js b/packages/edit-site/src/components/editor/utils.js index 7d5d55884feeeb..05218ea42ad108 100644 --- a/packages/edit-site/src/components/editor/utils.js +++ b/packages/edit-site/src/components/editor/utils.js @@ -90,18 +90,11 @@ function getPresetMetadataFromStyleProperty( styleProperty ) { return getPresetMetadataFromStyleProperty.MAP[ styleProperty ]; } -const filterColorsFromCoreOrigin = ( path, setting ) => { - if ( path !== 'color.palette' && path !== 'color.gradients' ) { - return setting; - } - - if ( ! Array.isArray( setting ) ) { - return setting; - } - - const colors = setting.filter( ( color ) => color?.origin !== 'core' ); - - return colors.length > 0 ? colors : setting; +const PATHS_WITH_MERGE = { + 'color.gradients': true, + 'color.palette': true, + 'typography.fontFamilies': true, + 'typography.fontSizes': true, }; export function useSetting( path, blockName = '' ) { @@ -110,8 +103,11 @@ export function useSetting( path, blockName = '' ) { } ); const topLevelPath = `__experimentalFeatures.${ path }`; const blockPath = `__experimentalFeatures.blocks.${ blockName }.${ path }`; - const setting = get( settings, blockPath ) ?? get( settings, topLevelPath ); - return filterColorsFromCoreOrigin( path, setting ); + const result = get( settings, blockPath ) ?? get( settings, topLevelPath ); + if ( PATHS_WITH_MERGE[ path ] ) { + return result.user ?? result.theme ?? result.core; + } + return result; } export function getPresetVariable( styles, context, propertyName, value ) { diff --git a/packages/edit-site/src/components/sidebar/color-palette-panel.js b/packages/edit-site/src/components/sidebar/color-palette-panel.js index 49e7c964fc29c8..fbae0697b9c811 100644 --- a/packages/edit-site/src/components/sidebar/color-palette-panel.js +++ b/packages/edit-site/src/components/sidebar/color-palette-panel.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { difference, get } from 'lodash'; +import { get } from 'lodash'; /** * WordPress dependencies @@ -38,14 +38,23 @@ export default function ColorPalettePanel( { ( select ) => { const baseStyles = select( editSiteStore ).getSettings() .__experimentalGlobalStylesBaseStyles; + const contextualBasePalette = get( baseStyles, [ + 'settings', + 'blocks', + contextName, + 'color', + 'palette', + ] ); + const globalPalette = get( baseStyles, [ + 'settings', + 'color', + 'palette', + ] ); const basePalette = - get( baseStyles, [ - 'settings', - 'blocks', - contextName, - 'color', - 'palette', - ] ) ?? get( baseStyles, [ 'settings', 'color', 'palette' ] ); + contextualBasePalette?.theme ?? + contextualBasePalette?.core ?? + globalPalette?.theme ?? + globalPalette?.core; if ( ! basePalette ) { return EMPTY_ARRAY; } @@ -58,21 +67,7 @@ export default function ColorPalettePanel( { immutableColorSlugs={ immutableColorSlugs } colors={ colors } onChange={ ( newColors ) => { - const existingUserColors = ( newColors ?? [] ).filter( - ( color ) => color.origin === 'user' - ); - const differentUserColors = difference( newColors, colors ); - if ( differentUserColors.length === 1 ) { - differentUserColors[ 0 ] = { - ...differentUserColors[ 0 ], - origin: 'user', - }; - } - - setSetting( contextName, 'color.palette', [ - ...existingUserColors, - ...differentUserColors, - ] ); + setSetting( contextName, 'color.palette', newColors ); } } emptyUI={ __( 'Colors are empty! Add some colors to create your own color palette.' diff --git a/phpunit/class-wp-theme-json-schema-v0-test.php b/phpunit/class-wp-theme-json-schema-v0-test.php index aad503dc7c1616..d2fd23e04edf49 100644 --- a/phpunit/class-wp-theme-json-schema-v0-test.php +++ b/phpunit/class-wp-theme-json-schema-v0-test.php @@ -335,129 +335,132 @@ function test_get_settings() { function test_get_stylesheet() { $root_name = WP_Theme_JSON_Schema_V0::ROOT_BLOCK_NAME; $all_blocks_name = WP_Theme_JSON_Schema_V0::ALL_BLOCKS_NAME; - - $theme_json = new WP_Theme_JSON_Gutenberg( - array( - 'settings' => array( - $all_blocks_name => array( - 'color' => array( - 'text' => 'value', - 'palette' => array( - array( - 'slug' => 'white', - 'color' => 'white', - ), - array( - 'slug' => 'black', - 'color' => 'black', + $theme_json = new WP_Theme_JSON_Gutenberg( array() ); + $theme_json->merge( + new WP_Theme_JSON_Gutenberg( + array( + 'settings' => array( + $all_blocks_name => array( + 'color' => array( + 'text' => 'value', + 'palette' => array( + array( + 'slug' => 'white', + 'color' => 'white', + ), + array( + 'slug' => 'black', + 'color' => 'black', + ), ), ), - ), - 'typography' => array( - 'fontFamilies' => array( - array( - 'slug' => 'small', - 'fontFamily' => '14px', + 'typography' => array( + 'fontFamilies' => array( + array( + 'slug' => 'small', + 'fontFamily' => '14px', + ), + array( + 'slug' => 'big', + 'fontFamily' => '41px', + ), ), - array( - 'slug' => 'big', - 'fontFamily' => '41px', + ), + 'misc' => 'value', + ), + $root_name => array( + 'color' => array( + 'palette' => array( + array( + 'slug' => 'grey', + 'color' => 'grey', + ), ), ), ), - 'misc' => 'value', - ), - $root_name => array( - 'color' => array( - 'palette' => array( - array( - 'slug' => 'grey', - 'color' => 'grey', + 'core/group' => array( + 'custom' => array( + 'base-font' => 16, + 'line-height' => array( + 'small' => 1.2, + 'medium' => 1.4, + 'large' => 1.8, ), ), ), ), - 'core/group' => array( - 'custom' => array( - 'base-font' => 16, - 'line-height' => array( - 'small' => 1.2, - 'medium' => 1.4, - 'large' => 1.8, + 'styles' => array( + $root_name => array( + 'color' => array( + 'link' => '#111', + 'text' => 'var:preset|color|grey', ), + 'misc' => 'value', ), - ), - ), - 'styles' => array( - $root_name => array( - 'color' => array( - 'link' => '#111', - 'text' => 'var:preset|color|grey', - ), - 'misc' => 'value', - ), - 'core/group' => array( - 'color' => array( - 'link' => '#333', - ), - 'spacing' => array( - 'padding' => array( - 'top' => '12px', - 'bottom' => '24px', + 'core/group' => array( + 'color' => array( + 'link' => '#333', + ), + 'spacing' => array( + 'padding' => array( + 'top' => '12px', + 'bottom' => '24px', + ), ), ), - ), - 'core/heading/h1' => array( - 'color' => array( - 'link' => '#111', - ), - 'typography' => array( - 'fontSize' => '1em', - ), - ), - 'core/heading/h2' => array( - 'color' => array( - 'link' => '#222', - ), - 'typography' => array( - 'fontSize' => '2em', - ), - ), - 'core/post-title/h2' => array( - 'color' => array( - 'link' => '#222', - ), - 'typography' => array( - 'fontSize' => '2em', - ), - ), - 'core/post-title/h5' => array( - 'color' => array( - 'link' => '#555', + 'core/heading/h1' => array( + 'color' => array( + 'link' => '#111', + ), + 'typography' => array( + 'fontSize' => '1em', + ), ), - 'typography' => array( - 'fontSize' => '5em', + 'core/heading/h2' => array( + 'color' => array( + 'link' => '#222', + ), + 'typography' => array( + 'fontSize' => '2em', + ), ), - ), - 'core/query-title/h4' => array( - 'color' => array( - 'link' => '#444', + 'core/post-title/h2' => array( + 'color' => array( + 'link' => '#222', + ), + 'typography' => array( + 'fontSize' => '2em', + ), ), - 'typography' => array( - 'fontSize' => '4em', + 'core/post-title/h5' => array( + 'color' => array( + 'link' => '#555', + ), + 'typography' => array( + 'fontSize' => '5em', + ), ), - ), - 'core/query-title/h5' => array( - 'color' => array( - 'link' => '#555', + 'core/query-title/h4' => array( + 'color' => array( + 'link' => '#444', + ), + 'typography' => array( + 'fontSize' => '4em', + ), ), - 'typography' => array( - 'fontSize' => '5em', + 'core/query-title/h5' => array( + 'color' => array( + 'link' => '#555', + ), + 'typography' => array( + 'fontSize' => '5em', + ), ), ), - ), - 'misc' => 'value', - ) + 'misc' => 'value', + ) + ), + 'core' ); $this->assertEquals( diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index fa3a4931a561b2..c38aa1d9ae768c 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -57,107 +57,111 @@ function test_get_settings() { } function test_get_stylesheet() { - $theme_json = new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'text' => 'value', - 'palette' => array( - array( - 'slug' => 'grey', - 'color' => 'grey', + $theme_json = new WP_Theme_JSON_Gutenberg( array() ); + $theme_json->merge( + new WP_Theme_JSON_Gutenberg( + array( + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, + 'settings' => array( + 'color' => array( + 'text' => 'value', + 'palette' => array( + array( + 'slug' => 'grey', + 'color' => 'grey', + ), ), ), - ), - 'typography' => array( - 'fontFamilies' => array( - array( - 'slug' => 'small', - 'fontFamily' => '14px', - ), - array( - 'slug' => 'big', - 'fontFamily' => '41px', + 'typography' => array( + 'fontFamilies' => array( + array( + 'slug' => 'small', + 'fontFamily' => '14px', + ), + array( + 'slug' => 'big', + 'fontFamily' => '41px', + ), ), ), - ), - 'misc' => 'value', - 'blocks' => array( - 'core/group' => array( - 'custom' => array( - 'base-font' => 16, - 'line-height' => array( - 'small' => 1.2, - 'medium' => 1.4, - 'large' => 1.8, + 'misc' => 'value', + 'blocks' => array( + 'core/group' => array( + 'custom' => array( + 'base-font' => 16, + 'line-height' => array( + 'small' => 1.2, + 'medium' => 1.4, + 'large' => 1.8, + ), ), ), ), ), - ), - 'styles' => array( - 'color' => array( - 'text' => 'var:preset|color|grey', - ), - 'misc' => 'value', - 'elements' => array( - 'link' => array( - 'color' => array( - 'text' => '#111', - 'background' => '#333', - ), + 'styles' => array( + 'color' => array( + 'text' => 'var:preset|color|grey', ), - ), - 'blocks' => array( - 'core/group' => array( - 'elements' => array( - 'link' => array( - 'color' => array( - 'text' => '#111', - ), - ), - ), - 'spacing' => array( - 'padding' => array( - 'top' => '12px', - 'bottom' => '24px', + 'misc' => 'value', + 'elements' => array( + 'link' => array( + 'color' => array( + 'text' => '#111', + 'background' => '#333', ), ), ), - 'core/heading' => array( - 'color' => array( - 'text' => '#123456', - ), - 'elements' => array( - 'link' => array( - 'color' => array( - 'text' => '#111', - 'background' => '#333', + 'blocks' => array( + 'core/group' => array( + 'elements' => array( + 'link' => array( + 'color' => array( + 'text' => '#111', + ), ), - 'typography' => array( - 'fontSize' => '60px', + ), + 'spacing' => array( + 'padding' => array( + 'top' => '12px', + 'bottom' => '24px', ), ), ), - ), - 'core/post-date' => array( - 'color' => array( - 'text' => '#123456', + 'core/heading' => array( + 'color' => array( + 'text' => '#123456', + ), + 'elements' => array( + 'link' => array( + 'color' => array( + 'text' => '#111', + 'background' => '#333', + ), + 'typography' => array( + 'fontSize' => '60px', + ), + ), + ), ), - 'elements' => array( - 'link' => array( - 'color' => array( - 'background' => '#777', - 'text' => '#555', + 'core/post-date' => array( + 'color' => array( + 'text' => '#123456', + ), + 'elements' => array( + 'link' => array( + 'color' => array( + 'background' => '#777', + 'text' => '#555', + ), ), ), ), ), ), - ), - 'misc' => 'value', - ) + 'misc' => 'value', + ) + ), + 'core' ); $this->assertEquals( @@ -175,24 +179,28 @@ function test_get_stylesheet() { } function test_get_stylesheet_preset_classes_work_with_compounded_selectors() { - $theme_json = new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'blocks' => array( - 'core/heading' => array( - 'color' => array( - 'palette' => array( - array( - 'slug' => 'white', - 'color' => '#fff', + $theme_json = new WP_Theme_JSON_Gutenberg( array() ); + $theme_json->merge( + new WP_Theme_JSON_Gutenberg( + array( + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, + 'settings' => array( + 'blocks' => array( + 'core/heading' => array( + 'color' => array( + 'palette' => array( + array( + 'slug' => 'white', + 'color' => '#fff', + ), ), ), ), ), ), - ), - ) + ) + ), + 'theme' ); $this->assertEquals( @@ -202,33 +210,37 @@ function test_get_stylesheet_preset_classes_work_with_compounded_selectors() { } function test_get_stylesheet_preset_rules_come_after_block_rules() { - $theme_json = new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'blocks' => array( - 'core/group' => array( - 'color' => array( - 'palette' => array( - array( - 'slug' => 'grey', - 'color' => 'grey', + $theme_json = new WP_Theme_JSON_Gutenberg( array() ); + $theme_json->merge( + new WP_Theme_JSON_Gutenberg( + array( + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, + 'settings' => array( + 'blocks' => array( + 'core/group' => array( + 'color' => array( + 'palette' => array( + array( + 'slug' => 'grey', + 'color' => 'grey', + ), ), ), ), ), ), - ), - 'styles' => array( - 'blocks' => array( - 'core/group' => array( - 'color' => array( - 'text' => 'red', + 'styles' => array( + 'blocks' => array( + 'core/group' => array( + 'color' => array( + 'text' => 'red', + ), ), ), ), - ), - ) + ) + ), + 'theme' ); $this->assertEquals( @@ -242,34 +254,38 @@ function test_get_stylesheet_preset_rules_come_after_block_rules() { } public function test_get_stylesheet_preset_values_are_marked_as_important() { - $theme_json = new WP_Theme_JSON_Gutenberg( - array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'palette' => array( - array( - 'slug' => 'grey', - 'color' => 'grey', + $theme_json = new WP_Theme_JSON_Gutenberg( array() ); + $theme_json->merge( + new WP_Theme_JSON_Gutenberg( + array( + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, + 'settings' => array( + 'color' => array( + 'palette' => array( + array( + 'slug' => 'grey', + 'color' => 'grey', + ), ), ), ), - ), - 'styles' => array( - 'blocks' => array( - 'core/paragraph' => array( - 'color' => array( - 'text' => 'red', - 'background' => 'blue', - ), - 'typography' => array( - 'fontSize' => '12px', - 'lineHeight' => '1.3', + 'styles' => array( + 'blocks' => array( + 'core/paragraph' => array( + 'color' => array( + 'text' => 'red', + 'background' => 'blue', + ), + 'typography' => array( + 'fontSize' => '12px', + 'lineHeight' => '1.3', + ), ), ), ), - ), - ) + ) + ), + 'core' ); $this->assertEquals( @@ -279,35 +295,42 @@ public function test_get_stylesheet_preset_values_are_marked_as_important() { } public function test_merge_incoming_data() { - $initial = array( - 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, - 'settings' => array( - 'color' => array( - 'custom' => false, - 'palette' => array( - array( - 'slug' => 'red', - 'color' => 'red', + $theme_json = new WP_Theme_JSON_Gutenberg( array() ); + $theme_json->merge( + new WP_Theme_JSON_Gutenberg( + array( + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, + 'settings' => array( + 'color' => array( + 'custom' => false, + 'palette' => array( + array( + 'slug' => 'red', + 'color' => 'red', + ), + array( + 'slug' => 'green', + 'color' => 'green', + ), + ), ), - array( - 'slug' => 'green', - 'color' => 'green', + 'blocks' => array( + 'core/paragraph' => array( + 'color' => array( + 'custom' => false, + ), + ), ), ), - ), - 'blocks' => array( - 'core/paragraph' => array( - 'color' => array( - 'custom' => false, + 'styles' => array( + 'typography' => array( + 'fontSize' => '12', ), ), - ), - ), - 'styles' => array( - 'typography' => array( - 'fontSize' => '12', - ), + + ) ), + 'core' ); $add_new_block = array( @@ -437,37 +460,37 @@ public function test_merge_incoming_data() { 'custom' => true, 'customGradient' => true, 'palette' => array( - array( - 'slug' => 'red', - 'color' => 'red', - ), - array( - 'slug' => 'green', - 'color' => 'green', - ), - array( - 'slug' => 'blue', - 'color' => 'blue', + 'core' => array( + array( + 'slug' => 'blue', + 'color' => 'blue', + ), ), ), 'gradients' => array( - array( - 'slug' => 'gradient', - 'gradient' => 'gradient', + 'core' => array( + array( + 'slug' => 'gradient', + 'gradient' => 'gradient', + ), ), ), ), 'typography' => array( 'fontSizes' => array( - array( - 'slug' => 'fontSize', - 'size' => 'fontSize', + 'core' => array( + array( + 'slug' => 'fontSize', + 'size' => 'fontSize', + ), ), ), 'fontFamilies' => array( - array( - 'slug' => 'fontFamily', - 'fontFamily' => 'fontFamily', + 'core' => array( + array( + 'slug' => 'fontFamily', + 'fontFamily' => 'fontFamily', + ), ), ), ), @@ -509,14 +532,13 @@ public function test_merge_incoming_data() { ), ); - $theme_json = new WP_Theme_JSON_Gutenberg( $initial ); - $theme_json->merge( new WP_Theme_JSON_Gutenberg( $add_new_block ) ); - $theme_json->merge( new WP_Theme_JSON_Gutenberg( $add_key_in_settings ) ); - $theme_json->merge( new WP_Theme_JSON_Gutenberg( $update_key_in_settings ) ); - $theme_json->merge( new WP_Theme_JSON_Gutenberg( $add_styles ) ); - $theme_json->merge( new WP_Theme_JSON_Gutenberg( $add_key_in_styles ) ); - $theme_json->merge( new WP_Theme_JSON_Gutenberg( $add_invalid_context ) ); - $theme_json->merge( new WP_Theme_JSON_Gutenberg( $update_presets ) ); + $theme_json->merge( new WP_Theme_JSON_Gutenberg( $add_new_block ), 'core' ); + $theme_json->merge( new WP_Theme_JSON_Gutenberg( $add_key_in_settings ), 'core' ); + $theme_json->merge( new WP_Theme_JSON_Gutenberg( $update_key_in_settings ), 'core' ); + $theme_json->merge( new WP_Theme_JSON_Gutenberg( $add_styles ), 'core' ); + $theme_json->merge( new WP_Theme_JSON_Gutenberg( $add_key_in_styles ), 'core' ); + $theme_json->merge( new WP_Theme_JSON_Gutenberg( $add_invalid_context ), 'core' ); + $theme_json->merge( new WP_Theme_JSON_Gutenberg( $update_presets ), 'core' ); $actual = $theme_json->get_raw_data(); $this->assertEqualSetsWithIndex( $expected, $actual ); From 3436129e14e4845bc7beb5e2c469521f5960aed1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ella=20van=C2=A0Durpe?= <4710635+ellatrix@users.noreply.github.com> Date: Thu, 10 Jun 2021 17:04:37 +0300 Subject: [PATCH 05/20] Drop indicator: show around dragged block and show above selected block for file drop (#31896) --- .../block-list/use-in-between-inserter.js | 16 ++++ .../components/block-tools/block-popover.js | 22 +++++- .../components/block-tools/insertion-point.js | 75 +++++++------------ .../src/components/block-tools/style.scss | 5 ++ .../components/use-block-drop-zone/index.js | 16 ++-- .../use-block-drop-zone/test/index.js | 42 ----------- .../compose/src/hooks/use-drop-zone/index.js | 47 +++++++++--- 7 files changed, 111 insertions(+), 112 deletions(-) diff --git a/packages/block-editor/src/components/block-list/use-in-between-inserter.js b/packages/block-editor/src/components/block-list/use-in-between-inserter.js index 0dfdab359d7a77..618811ec91ba64 100644 --- a/packages/block-editor/src/components/block-list/use-in-between-inserter.js +++ b/packages/block-editor/src/components/block-list/use-in-between-inserter.js @@ -14,12 +14,17 @@ import { InsertionPointOpenRef } from '../block-tools/insertion-point'; export function useInBetweenInserter() { const openRef = useContext( InsertionPointOpenRef ); + const hasReducedUI = useSelect( + ( select ) => select( blockEditorStore ).getSettings().hasReducedUI, + [] + ); const { getBlockListSettings, getBlockRootClientId, getBlockIndex, isBlockInsertionPointVisible, isMultiSelecting, + getSelectedBlockClientIds, } = useSelect( blockEditorStore ); const { showInsertionPoint, hideInsertionPoint } = useDispatch( blockEditorStore @@ -27,6 +32,10 @@ export function useInBetweenInserter() { return useRefEffect( ( node ) => { + if ( hasReducedUI ) { + return; + } + function onMouseMove( event ) { if ( openRef.current ) { return; @@ -98,6 +107,12 @@ export function useInBetweenInserter() { return; } + // Don't show the inserter when hovering above (conflicts with + // block toolbar) or inside selected block(s). + if ( getSelectedBlockClientIds().includes( clientId ) ) { + return; + } + const elementRect = element.getBoundingClientRect(); if ( @@ -145,6 +160,7 @@ export function useInBetweenInserter() { isMultiSelecting, showInsertionPoint, hideInsertionPoint, + getSelectedBlockClientIds, ] ); } diff --git a/packages/block-editor/src/components/block-tools/block-popover.js b/packages/block-editor/src/components/block-tools/block-popover.js index dc803f7670aba6..8371cfff9bbba8 100644 --- a/packages/block-editor/src/components/block-tools/block-popover.js +++ b/packages/block-editor/src/components/block-tools/block-popover.js @@ -64,6 +64,24 @@ function BlockPopover( { hasFixedToolbar, lastClientId, } = useSelect( selector, [] ); + const isInsertionPointVisible = useSelect( + ( select ) => { + const { + isBlockInsertionPointVisible, + getBlockInsertionPoint, + getBlockOrder, + } = select( blockEditorStore ); + + if ( ! isBlockInsertionPointVisible() ) { + return false; + } + + const insertionPoint = getBlockInsertionPoint(); + const order = getBlockOrder( insertionPoint.rootClientId ); + return order[ insertionPoint.index ] === clientId; + }, + [ clientId ] + ); const isLargeViewport = useViewportMatch( 'medium' ); const [ isToolbarForced, setIsToolbarForced ] = useState( false ); const [ isInserterShown, setIsInserterShown ] = useState( false ); @@ -184,7 +202,9 @@ function BlockPopover( { position={ popoverPosition } focusOnMount={ false } anchorRef={ anchorRef } - className="block-editor-block-list__block-popover" + className={ classnames( 'block-editor-block-list__block-popover', { + 'is-insertion-point-visible': isInsertionPointVisible, + } ) } __unstableStickyBoundaryElement={ stickyBoundaryElement } // Render in the old slot if needed for backward compatibility, // otherwise render in place (not in the the default popover slot). diff --git a/packages/block-editor/src/components/block-tools/insertion-point.js b/packages/block-editor/src/components/block-tools/insertion-point.js index 134430c301a61e..b836beba7d3ae0 100644 --- a/packages/block-editor/src/components/block-tools/insertion-point.js +++ b/packages/block-editor/src/components/block-tools/insertion-point.js @@ -36,7 +36,6 @@ function InsertionPointPopover( { const ref = useRef(); const { orientation, - isHidden, previousClientId, nextClientId, rootClientId, @@ -45,47 +44,36 @@ function InsertionPointPopover( { const { getBlockOrder, getBlockListSettings, - getMultiSelectedBlockClientIds, - getSelectedBlockClientId, - hasMultiSelection, - getSettings, getBlockInsertionPoint, + isBlockBeingDragged, + getPreviousBlockClientId, + getNextBlockClientId, } = select( blockEditorStore ); const insertionPoint = getBlockInsertionPoint(); const order = getBlockOrder( insertionPoint.rootClientId ); - const targetClientId = order[ insertionPoint.index - 1 ]; - const targetRootClientId = insertionPoint.rootClientId; - const blockOrder = getBlockOrder( targetRootClientId ); - if ( ! blockOrder.length ) { + + if ( ! order.length ) { return {}; } - const previous = targetClientId - ? targetClientId - : blockOrder[ blockOrder.length - 1 ]; - const isLast = previous === blockOrder[ blockOrder.length - 1 ]; - const next = isLast - ? null - : blockOrder[ blockOrder.indexOf( previous ) + 1 ]; - const { hasReducedUI } = getSettings(); - const multiSelectedBlockClientIds = getMultiSelectedBlockClientIds(); - const selectedBlockClientId = getSelectedBlockClientId(); - const blockOrientation = - getBlockListSettings( targetRootClientId )?.orientation || - 'vertical'; + + let _previousClientId = order[ insertionPoint.index - 1 ]; + let _nextClientId = order[ insertionPoint.index ]; + + while ( isBlockBeingDragged( _previousClientId ) ) { + _previousClientId = getPreviousBlockClientId( _previousClientId ); + } + + while ( isBlockBeingDragged( _nextClientId ) ) { + _nextClientId = getNextBlockClientId( _nextClientId ); + } return { - previousClientId: previous, - nextClientId: next, - isHidden: - hasReducedUI || - ( hasMultiSelection() - ? next && multiSelectedBlockClientIds.includes( next ) - : next && - blockOrientation === 'vertical' && - next === selectedBlockClientId ), - orientation: blockOrientation, - clientId: targetClientId, - rootClientId: targetRootClientId, + previousClientId: _previousClientId, + nextClientId: _nextClientId, + orientation: + getBlockListSettings( insertionPoint.rootClientId ) + ?.orientation || 'vertical', + rootClientId: insertionPoint.rootClientId, isInserterShown: insertionPoint?.__unstableWithInserter, }; }, [] ); @@ -193,14 +181,7 @@ function InsertionPointPopover( { // Only show the inserter when there's a `nextElement` (a block after the // insertion point). At the end of the block list the trailing appender // should serve the purpose of inserting blocks. - const showInsertionPointInserter = - ! isHidden && nextElement && isInserterShown; - - // Show the indicator if the insertion point inserter is visible, or if - // the `showInsertionPoint` state is `true`. The latter is generally true - // when hovering blocks for insertion in the block library. - const showInsertionPointIndicator = - showInsertionPointInserter || ! isHidden; + const showInsertionPointInserter = nextElement && isInserterShown; /* eslint-disable jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events */ // While ideally it would be enough to capture the @@ -231,9 +212,7 @@ function InsertionPointPopover( { } ) } style={ style } > - { showInsertionPointIndicator && ( -
- ) } +
{ showInsertionPointInserter && (
{ - const { isMultiSelecting, isBlockInsertionPointVisible } = select( - blockEditorStore - ); - - return isBlockInsertionPointVisible() && ! isMultiSelecting(); + return select( blockEditorStore ).isBlockInsertionPointVisible(); }, [] ); return ( diff --git a/packages/block-editor/src/components/block-tools/style.scss b/packages/block-editor/src/components/block-tools/style.scss index e511a41fabe92c..072b085f387bc1 100644 --- a/packages/block-editor/src/components/block-tools/style.scss +++ b/packages/block-editor/src/components/block-tools/style.scss @@ -321,6 +321,11 @@ } } + // Hide the block toolbar if the insertion point is shown. + &.is-insertion-point-visible { + visibility: hidden; + } + .is-dragging-components-draggable & { opacity: 0; // Use a minimal duration to delay hiding the element, see hide-during-dragging animation for more details. diff --git a/packages/block-editor/src/components/use-block-drop-zone/index.js b/packages/block-editor/src/components/use-block-drop-zone/index.js index 391f78ac97aa3c..019f80af6d59da 100644 --- a/packages/block-editor/src/components/use-block-drop-zone/index.js +++ b/packages/block-editor/src/components/use-block-drop-zone/index.js @@ -59,16 +59,7 @@ export function getNearestBlockIndex( elements, position, orientation ) { // If the user is dropping to the trailing edge of the block // add 1 to the index to represent dragging after. const isTrailingEdge = edge === 'bottom' || edge === 'right'; - let offset = isTrailingEdge ? 1 : 0; - - // If the target is the dragged block itself and another 1 to - // index as the dragged block is set to `display: none` and - // should be skipped in the calculation. - const isTargetDraggedBlock = - isTrailingEdge && - elements[ index + 1 ] && - elements[ index + 1 ].classList.contains( 'is-dragging' ); - offset += isTargetDraggedBlock ? 1 : 0; + const offset = isTrailingEdge ? 1 : 0; // Update the currently known best candidate. candidateDistance = distance; @@ -144,6 +135,11 @@ export default function useBlockDropZone( { // https://developer.mozilla.org/en-US/docs/Web/API/Event/currentTarget throttled( event, event.currentTarget ); }, + onDragLeave() { + throttled.cancel(); + hideInsertionPoint(); + setTargetBlockIndex( null ); + }, onDragEnd() { throttled.cancel(); hideInsertionPoint(); diff --git a/packages/block-editor/src/components/use-block-drop-zone/test/index.js b/packages/block-editor/src/components/use-block-drop-zone/test/index.js index c0aac7b5827d92..42a9476be0cd41 100644 --- a/packages/block-editor/src/components/use-block-drop-zone/test/index.js +++ b/packages/block-editor/src/components/use-block-drop-zone/test/index.js @@ -209,27 +209,6 @@ describe( 'getNearestBlockIndex', () => { expect( result ).toBe( 4 ); } ); - - it( 'skips the block being dragged by checking for the `is-dragging` classname', () => { - const position = { x: 0, y: 450 }; - - const verticalElementsWithDraggedBlock = [ - ...verticalElements.slice( 0, 2 ), - { - ...verticalElements[ 2 ], - classList: createMockClassList( 'wp-block is-dragging' ), - }, - ...verticalElements.slice( 3, 4 ), - ]; - - const result = getNearestBlockIndex( - verticalElementsWithDraggedBlock, - position, - orientation - ); - - expect( result ).toBe( 3 ); - } ); } ); describe( 'Horizontal block lists', () => { @@ -342,26 +321,5 @@ describe( 'getNearestBlockIndex', () => { expect( result ).toBe( 4 ); } ); - - it( 'skips the block being dragged by checking for the `is-dragging` classname', () => { - const position = { x: 450, y: 0 }; - - const horizontalElementsWithDraggedBlock = [ - ...horizontalElements.slice( 0, 2 ), - { - ...horizontalElements[ 2 ], - classList: createMockClassList( 'wp-block is-dragging' ), - }, - ...horizontalElements.slice( 3, 4 ), - ]; - - const result = getNearestBlockIndex( - horizontalElementsWithDraggedBlock, - position, - orientation - ); - - expect( result ).toBe( 3 ); - } ); } ); } ); diff --git a/packages/compose/src/hooks/use-drop-zone/index.js b/packages/compose/src/hooks/use-drop-zone/index.js index bbfc0ba461a89c..f2af24c549bf6a 100644 --- a/packages/compose/src/hooks/use-drop-zone/index.js +++ b/packages/compose/src/hooks/use-drop-zone/index.js @@ -56,7 +56,31 @@ export default function useDropZone( { const { ownerDocument } = element; - function maybeDragStart( event ) { + /** + * Checks if an element is in the drop zone. + * + * @param {HTMLElement|null} elementToCheck + * + * @return {boolean} True if in drop zone, false if not. + */ + function isElementInZone( elementToCheck ) { + if ( + ! elementToCheck || + ! element.contains( elementToCheck ) + ) { + return false; + } + + do { + if ( elementToCheck.dataset.isDropZone ) { + return elementToCheck === element; + } + } while ( ( elementToCheck = elementToCheck.parentElement ) ); + + return false; + } + + function maybeDragStart( /** @type {DragEvent} */ event ) { if ( isDragging ) { return; } @@ -68,6 +92,13 @@ export default function useDropZone( { maybeDragStart ); + // Note that `dragend` doesn't fire consistently for file and + // HTML drag events where the drag origin is outside the browser + // window. In Firefox it may also not fire if the originating + // node is removed. + ownerDocument.addEventListener( 'dragend', maybeDragEnd ); + ownerDocument.addEventListener( 'mousemove', maybeDragEnd ); + if ( onDragStartRef.current ) { onDragStartRef.current( event ); } @@ -106,7 +137,7 @@ export default function useDropZone( { // leaving the drop zone, which means the `relatedTarget` // (element that has been entered) should be outside the drop // zone. - if ( element.contains( event.relatedTarget ) ) { + if ( isElementInZone( event.relatedTarget ) ) { return; } @@ -146,33 +177,31 @@ export default function useDropZone( { isDragging = false; ownerDocument.addEventListener( 'dragenter', maybeDragStart ); + ownerDocument.removeEventListener( 'dragend', maybeDragEnd ); + ownerDocument.removeEventListener( 'mousemove', maybeDragEnd ); if ( onDragEndRef.current ) { onDragEndRef.current( event ); } } + element.dataset.isDropZone = 'true'; element.addEventListener( 'drop', onDrop ); element.addEventListener( 'dragenter', onDragEnter ); element.addEventListener( 'dragover', onDragOver ); element.addEventListener( 'dragleave', onDragLeave ); - // Note that `dragend` doesn't fire consistently for file and HTML - // drag events where the drag origin is outside the browser window. - // In Firefox it may also not fire if the originating node is - // removed. - ownerDocument.addEventListener( 'dragend', maybeDragEnd ); - ownerDocument.addEventListener( 'mouseup', maybeDragEnd ); // The `dragstart` event doesn't fire if the drag started outside // the document. ownerDocument.addEventListener( 'dragenter', maybeDragStart ); return () => { + delete element.dataset.isDropZone; element.removeEventListener( 'drop', onDrop ); element.removeEventListener( 'dragenter', onDragEnter ); element.removeEventListener( 'dragover', onDragOver ); element.removeEventListener( 'dragleave', onDragLeave ); ownerDocument.removeEventListener( 'dragend', maybeDragEnd ); - ownerDocument.removeEventListener( 'mouseup', maybeDragEnd ); + ownerDocument.removeEventListener( 'mousemove', maybeDragEnd ); ownerDocument.addEventListener( 'dragenter', maybeDragStart ); }; }, From ab5043f92d79f67b5f4fe43e053b5d99fdf0fcb3 Mon Sep 17 00:00:00 2001 From: Robert Anderson Date: Fri, 11 Jun 2021 10:51:18 +1000 Subject: [PATCH 06/20] Widgets editor: Fix dirty state after adding new block (#32573) --- .../specs/widgets/editing-widgets.test.js | 21 +++++++++++++++++++ packages/edit-widgets/src/store/actions.js | 9 +++----- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/packages/e2e-tests/specs/widgets/editing-widgets.test.js b/packages/e2e-tests/specs/widgets/editing-widgets.test.js index 4c0088d4ea4f2f..9eab5544c04097 100644 --- a/packages/e2e-tests/specs/widgets/editing-widgets.test.js +++ b/packages/e2e-tests/specs/widgets/editing-widgets.test.js @@ -130,6 +130,16 @@ describe( 'Widgets screen', () => { } it( 'Should insert content using the global inserter', async () => { + const updateButton = await find( { + role: 'button', + name: 'Update', + } ); + + // Update button should start out disabled. + expect( + await updateButton.evaluate( ( button ) => button.disabled ) + ).toBe( true ); + const widgetAreas = await findAll( { role: 'group', name: 'Block: Widget Area', @@ -146,6 +156,11 @@ describe( 'Widgets screen', () => { await addParagraphBlock.click(); + // Adding content should enable the Update button. + expect( + await updateButton.evaluate( ( button ) => button.disabled ) + ).toBe( false ); + let addedParagraphBlockInFirstWidgetArea = await find( { name: /^Empty block/, @@ -215,6 +230,12 @@ describe( 'Widgets screen', () => { // await page.keyboard.type( 'Third Paragraph' ); await saveWidgets(); + + // The Update button should be disabled again after saving. + expect( + await updateButton.evaluate( ( button ) => button.disabled ) + ).toBe( true ); + const serializedWidgetAreas = await getSerializedWidgetAreas(); expect( serializedWidgetAreas ).toMatchInlineSnapshot( ` Object { diff --git a/packages/edit-widgets/src/store/actions.js b/packages/edit-widgets/src/store/actions.js index d31280c0a0133b..c3ae54eb619aeb 100644 --- a/packages/edit-widgets/src/store/actions.js +++ b/packages/edit-widgets/src/store/actions.js @@ -204,12 +204,9 @@ export function* saveWidgetArea( widgetAreaId ) { const widget = preservedRecords[ i ]; const { block, position } = batchMeta[ i ]; - yield dispatch( - 'core/block-editor', - 'updateBlockAttributes', - block.clientId, - { __internalWidgetId: widget.id } - ); + // Set __internalWidgetId on the block. This will be persisted to the + // store when we dispatch receiveEntityRecords( post ) below. + post.blocks[ position ].attributes.__internalWidgetId = widget.id; const error = yield select( 'core', From d26692be9c4096866b778013c6aa5fb82900b62e Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Fri, 11 Jun 2021 05:02:29 +0400 Subject: [PATCH 07/20] Widget Editor: Fix button spacing in header (#32585) --- .../edit-widgets/src/components/header/style.scss | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/packages/edit-widgets/src/components/header/style.scss b/packages/edit-widgets/src/components/header/style.scss index 3b64974e54afb5..16a2c33be2ddc0 100644 --- a/packages/edit-widgets/src/components/header/style.scss +++ b/packages/edit-widgets/src/components/header/style.scss @@ -25,6 +25,19 @@ .edit-widgets-header__actions { display: flex; + + .components-button { + margin-right: $grid-unit-05; + + @include break-small() { + margin-right: $grid-unit-15; + } + } + + .edit-widgets-more-menu .components-button, + .interface-pinned-items .components-button { + margin-right: 0; + } } .edit-widgets-header-toolbar { From 0521fb39a6a0364852b30beabd195e60b9c63c61 Mon Sep 17 00:00:00 2001 From: Ramon Date: Thu, 10 Jun 2021 11:05:23 +1000 Subject: [PATCH 08/20] Editor Breadcrumb: add a `rootLabelText` prop (#32528) --- packages/block-editor/README.md | 5 +++ .../src/components/block-breadcrumb/README.md | 9 +++++ .../src/components/block-breadcrumb/index.js | 11 ++++-- .../test/__snapshots__/index.js.snap | 16 ++++++++ .../components/block-breadcrumb/test/index.js | 37 +++++++++++++++++++ 5 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 packages/block-editor/src/components/block-breadcrumb/test/__snapshots__/index.js.snap create mode 100644 packages/block-editor/src/components/block-breadcrumb/test/index.js diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index 9ecd72ea0cb307..8d2a07876a9fa8 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -104,6 +104,11 @@ Undocumented declaration. Block breadcrumb component, displaying the hierarchy of the current block selection as a breadcrumb. +_Parameters_ + +- _props_ `Object`: Component props. +- _props.rootLabelText_ `string`: Translated label for the root element of the breadcrumb trail. + _Returns_ - `WPElement`: Block Breadcrumb. diff --git a/packages/block-editor/src/components/block-breadcrumb/README.md b/packages/block-editor/src/components/block-breadcrumb/README.md index 98b432973b33d9..298ff8fdf5ea61 100644 --- a/packages/block-editor/src/components/block-breadcrumb/README.md +++ b/packages/block-editor/src/components/block-breadcrumb/README.md @@ -13,6 +13,15 @@ The block breadcrumb trail displays the hierarchy of the current block selection ## Development guidelines +#### Props + +##### rootLabelText + +Label text for the root element (the first `
  • `) of the breadcrumb trail. + +- Type: `String` +- Required: No + ### Usage Renders a block breadcrumb with default style. diff --git a/packages/block-editor/src/components/block-breadcrumb/index.js b/packages/block-editor/src/components/block-breadcrumb/index.js index 422fbeffc0ed5d..bfc4b45303889d 100644 --- a/packages/block-editor/src/components/block-breadcrumb/index.js +++ b/packages/block-editor/src/components/block-breadcrumb/index.js @@ -14,9 +14,11 @@ import { store as blockEditorStore } from '../../store'; /** * Block breadcrumb component, displaying the hierarchy of the current block selection as a breadcrumb. * - * @return {WPElement} Block Breadcrumb. + * @param {Object} props Component props. + * @param {string} props.rootLabelText Translated label for the root element of the breadcrumb trail. + * @return {WPElement} Block Breadcrumb. */ -function BlockBreadcrumb() { +function BlockBreadcrumb( { rootLabelText } ) { const { selectBlock, clearSelectedBlock } = useDispatch( blockEditorStore ); const { clientId, parents, hasSelection } = useSelect( ( select ) => { const { @@ -31,6 +33,7 @@ function BlockBreadcrumb() { hasSelection: !! getSelectionStart().clientId, }; }, [] ); + const rootLabel = rootLabelText || __( 'Document' ); /* * Disable reason: The `list` ARIA role is redundant but @@ -57,10 +60,10 @@ function BlockBreadcrumb() { isTertiary onClick={ clearSelectedBlock } > - { __( 'Document' ) } + { rootLabel } ) } - { ! hasSelection && __( 'Document' ) } + { ! hasSelection && rootLabel }
  • { parents.map( ( parentClientId ) => (
  • diff --git a/packages/block-editor/src/components/block-breadcrumb/test/__snapshots__/index.js.snap b/packages/block-editor/src/components/block-breadcrumb/test/__snapshots__/index.js.snap new file mode 100644 index 00000000000000..85dd26bc0a7f3b --- /dev/null +++ b/packages/block-editor/src/components/block-breadcrumb/test/__snapshots__/index.js.snap @@ -0,0 +1,16 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`BlockBreadcrumb should render correctly 1`] = ` +
      +
    • + Document +
    • +
    +`; diff --git a/packages/block-editor/src/components/block-breadcrumb/test/index.js b/packages/block-editor/src/components/block-breadcrumb/test/index.js new file mode 100644 index 00000000000000..a46392920b5fcb --- /dev/null +++ b/packages/block-editor/src/components/block-breadcrumb/test/index.js @@ -0,0 +1,37 @@ +/** + * External dependencies + */ +import { render, screen } from '@testing-library/react'; + +/** + * Internal dependencies + */ +import BlockBreadcrumb from '../'; + +describe( 'BlockBreadcrumb', () => { + it( 'should render correctly', () => { + const { container } = render( ); + + expect( container.firstChild ).toMatchSnapshot(); + } ); + + describe( 'Root label text', () => { + test( 'should display default label of "Document"', () => { + render( ); + + const rootLabelTextDefault = screen.getByText( 'Document' ); + + expect( rootLabelTextDefault ).toBeInTheDocument(); + } ); + + test( 'should display `rootLabelText` value', () => { + render( ); + + const rootLabelText = screen.getByText( 'Tuhinga' ); + const rootLabelTextDefault = screen.queryByText( 'Document' ); + + expect( rootLabelTextDefault ).toBeNull(); + expect( rootLabelText ).toBeInTheDocument(); + } ); + } ); +} ); From 0f1bec8566efd496df312165d3f2db37a0a1dc15 Mon Sep 17 00:00:00 2001 From: tellthemachines Date: Fri, 11 Jun 2021 16:36:41 +1000 Subject: [PATCH 09/20] [Widgets screen] Don't add undo levels when editing records on save (#32572) * Don't add undo levels when saving widgets. * Add e2e test for undoing widget deletion. * Update failing snapshot --- .../specs/widgets/editing-widgets.test.js | 57 +++++++++++++++++++ packages/edit-widgets/src/store/actions.js | 6 +- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/packages/e2e-tests/specs/widgets/editing-widgets.test.js b/packages/e2e-tests/specs/widgets/editing-widgets.test.js index 9eab5544c04097..b5d7e480d9d8de 100644 --- a/packages/e2e-tests/specs/widgets/editing-widgets.test.js +++ b/packages/e2e-tests/specs/widgets/editing-widgets.test.js @@ -9,6 +9,7 @@ import { showBlockToolbar, visitAdminPage, deleteAllWidgets, + pressKeyWithModifier, } from '@wordpress/e2e-test-utils'; /** @@ -694,6 +695,62 @@ describe( 'Widgets screen', () => { } ` ); } ); + + it( 'Allows widget deletion to be undone', async () => { + const [ firstWidgetArea ] = await findAll( { + role: 'group', + name: 'Block: Widget Area', + } ); + + let addParagraphBlock = await getBlockInGlobalInserter( 'Paragraph' ); + await addParagraphBlock.click(); + + let addedParagraphBlockInFirstWidgetArea = await find( + { + name: /^Empty block/, + selector: '[data-block][data-type="core/paragraph"]', + }, + { + root: firstWidgetArea, + } + ); + await addedParagraphBlockInFirstWidgetArea.focus(); + await page.keyboard.type( 'First Paragraph' ); + + addParagraphBlock = await getBlockInGlobalInserter( 'Paragraph' ); + await addParagraphBlock.click(); + + addedParagraphBlockInFirstWidgetArea = await firstWidgetArea.$( + '[data-block][data-type="core/paragraph"][aria-label^="Empty block"]' + ); + await addedParagraphBlockInFirstWidgetArea.focus(); + await page.keyboard.type( 'Second Paragraph' ); + + await saveWidgets(); + + // Delete the last block and save again. + await pressKeyWithModifier( 'access', 'z' ); + await saveWidgets(); + + // Undo block deletion and save again + await pressKeyWithModifier( 'primary', 'z' ); + await saveWidgets(); + + // Reload the page to make sure changes were actually saved. + await page.reload(); + + const serializedWidgetAreas = await getSerializedWidgetAreas(); + expect( serializedWidgetAreas ).toMatchInlineSnapshot( ` + Object { + "sidebar-1": "
    +

    First Paragraph

    +
    +
    +

    Second Paragraph

    +
    ", + } + ` ); + } ); } ); /** diff --git a/packages/edit-widgets/src/store/actions.js b/packages/edit-widgets/src/store/actions.js index c3ae54eb619aeb..179723a85488e2 100644 --- a/packages/edit-widgets/src/store/actions.js +++ b/packages/edit-widgets/src/store/actions.js @@ -152,7 +152,8 @@ export function* saveWidgetArea( widgetAreaId ) { { ...widget, sidebar: widgetAreaId, - } + }, + { undoIgnore: true } ); const hasEdits = yield select( @@ -242,7 +243,8 @@ export function* saveWidgetArea( widgetAreaId ) { widgetAreaId, { widgets: sidebarWidgetsIds, - } + }, + { undoIgnore: true } ); yield* trySaveWidgetArea( widgetAreaId ); From 9921f4ef9b25500e593fb09aa6bc17ab7994b697 Mon Sep 17 00:00:00 2001 From: Robert Anderson Date: Fri, 11 Jun 2021 15:46:28 +1000 Subject: [PATCH 10/20] Move Legacy Widget block to @wordpress/widgets (#32501) --- .../widgets/legacy-widget-block.md | 46 +++++ lib/blocks.php | 27 +-- lib/client-assets.php | 12 +- lib/widgets-page.php | 56 ++++++ lib/widgets.php | 164 ++---------------- package-lock.json | 10 +- packages/block-library/CHANGELOG.md | 5 + packages/block-library/src/editor.scss | 1 - packages/block-library/src/index.js | 2 - packages/customize-widgets/src/index.js | 8 +- .../fixtures/blocks/core__legacy-widget.html | 1 - .../fixtures/blocks/core__legacy-widget.json | 18 -- .../blocks/core__legacy-widget.parsed.json | 16 -- .../core__legacy-widget.serialized.html | 1 - .../wp-editor-meta-box.test.js.snap | 2 +- packages/edit-widgets/src/index.js | 6 +- packages/widgets/package.json | 10 +- .../src/blocks}/legacy-widget/README.md | 0 .../src/blocks}/legacy-widget/block.json | 0 .../src/blocks}/legacy-widget/edit/control.js | 0 .../edit/convert-to-blocks-button.js | 0 .../src/blocks}/legacy-widget/edit/form.js | 0 .../src/blocks}/legacy-widget/edit/index.js | 0 .../legacy-widget/edit/inspector-card.js | 0 .../blocks}/legacy-widget/edit/no-preview.js | 0 .../src/blocks}/legacy-widget/edit/preview.js | 0 .../edit/widget-type-selector.js | 0 .../src/blocks}/legacy-widget/editor.scss | 3 +- .../src/blocks}/legacy-widget/index.js | 0 .../src/blocks}/legacy-widget/index.php | 0 .../src/blocks}/legacy-widget/transforms.js | 0 packages/widgets/src/index.js | 26 ++- packages/widgets/src/style.scss | 1 + webpack.config.js | 1 + 34 files changed, 192 insertions(+), 224 deletions(-) delete mode 100644 packages/e2e-tests/fixtures/blocks/core__legacy-widget.html delete mode 100644 packages/e2e-tests/fixtures/blocks/core__legacy-widget.json delete mode 100644 packages/e2e-tests/fixtures/blocks/core__legacy-widget.parsed.json delete mode 100644 packages/e2e-tests/fixtures/blocks/core__legacy-widget.serialized.html rename packages/{block-library/src => widgets/src/blocks}/legacy-widget/README.md (100%) rename packages/{block-library/src => widgets/src/blocks}/legacy-widget/block.json (100%) rename packages/{block-library/src => widgets/src/blocks}/legacy-widget/edit/control.js (100%) rename packages/{block-library/src => widgets/src/blocks}/legacy-widget/edit/convert-to-blocks-button.js (100%) rename packages/{block-library/src => widgets/src/blocks}/legacy-widget/edit/form.js (100%) rename packages/{block-library/src => widgets/src/blocks}/legacy-widget/edit/index.js (100%) rename packages/{block-library/src => widgets/src/blocks}/legacy-widget/edit/inspector-card.js (100%) rename packages/{block-library/src => widgets/src/blocks}/legacy-widget/edit/no-preview.js (100%) rename packages/{block-library/src => widgets/src/blocks}/legacy-widget/edit/preview.js (100%) rename packages/{block-library/src => widgets/src/blocks}/legacy-widget/edit/widget-type-selector.js (100%) rename packages/{block-library/src => widgets/src/blocks}/legacy-widget/editor.scss (98%) rename packages/{block-library/src => widgets/src/blocks}/legacy-widget/index.js (100%) rename packages/{block-library/src => widgets/src/blocks}/legacy-widget/index.php (100%) rename packages/{block-library/src => widgets/src/blocks}/legacy-widget/transforms.js (100%) create mode 100644 packages/widgets/src/style.scss diff --git a/docs/how-to-guides/widgets/legacy-widget-block.md b/docs/how-to-guides/widgets/legacy-widget-block.md index c32136a10e4fef..21d22561d1509c 100644 --- a/docs/how-to-guides/widgets/legacy-widget-block.md +++ b/docs/how-to-guides/widgets/legacy-widget-block.md @@ -123,3 +123,49 @@ function hide_example_widget( $widget_types ) { } add_filter( 'widget_types_to_hide_from_legacy_widget_block', 'hide_example_widget' ); ``` + +## Using the Legacy Widget block in other block editors (Advanced) + +You may optionally allow the Legacy Widget block in other block editors such as +the WordPress post editor. This is not enabled by default. + +First, ensure that any styles and scripts required by the legacy widgets are +loaded onto the page. A convenient way of doing this is to manually perform all +of the hooks that ordinarily run when a user browses to the widgets WP Admin +screen. + +```php +add_action( 'admin_print_styles', function() { + if ( get_current_screen()->is_block_editor() ) { + do_action( 'admin_print_styles-widgets.php' ); + } +} ); +add_action( 'admin_print_scripts', function() { + if ( get_current_screen()->is_block_editor() ) { + do_action( 'load-widgets.php' ); + do_action( 'widgets.php' ); + do_action( 'sidebar_admin_setup' ); + do_action( 'admin_print_scripts-widgets.php' ); + } +} ); +add_action( 'admin_print_footer_scripts', function() { + if ( get_current_screen()->is_block_editor() ) { + do_action( 'admin_print_footer_scripts-widgets.php' ); + } +} ); +add_action( 'admin_footer', function() { + if ( get_current_screen()->is_block_editor() ) { + do_action( 'admin_footer-widgets.php' ); + } +} ); +``` + +Then, register the Legacy Widget block using `registerLegacyWidgetBlock` which +is defined in the `@wordpress/widgets` package. + +```php +add_action( 'enqueue_block_editor_assets', function() { + wp_enqueue_script( 'wp-widgets' ); + wp_add_inline_script( 'wp-widgets', 'wp.widgets.registerLegacyWidgetBlock()' ); +} ); +``` diff --git a/lib/blocks.php b/lib/blocks.php index 8f838b24fff7fb..e6e2968a23fd4d 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -5,24 +5,6 @@ * @package gutenberg */ -/* - * Fixes the priority of register_block_core_legacy_widget(). - * - * This hook was incorrectly added to Core with priority 20. #32300 fixes this - * but causes block registration warnings in the Gutenberg plugin until the - * changes are made in Core. - * - * This temporary fix can be removed after the changes to - * @wordpress/block-library in #32300 have been published to npm and updated in - * Core. - * - * See https://github.com/WordPress/gutenberg/pull/32300. - */ -if ( 20 === has_action( 'init', 'register_block_core_legacy_widget' ) ) { - remove_action( 'init', 'register_block_core_legacy_widget', 20 ); - add_action( 'init', 'register_block_core_legacy_widget', 10 ); -} - /** * Substitutes the implementation of a core-registered block type, if exists, * with the built result from the plugin. @@ -74,7 +56,6 @@ function gutenberg_reregister_core_block_types() { 'file.php' => 'core/file', 'latest-comments.php' => 'core/latest-comments', 'latest-posts.php' => 'core/latest-posts', - 'legacy-widget.php' => 'core/legacy-widget', 'loginout.php' => 'core/loginout', 'navigation.php' => 'core/navigation', 'navigation-link.php' => 'core/navigation-link', @@ -120,8 +101,14 @@ function gutenberg_reregister_core_block_types() { 'block_folders' => array( 'widget-area', ), + 'block_names' => array(), + ), + __DIR__ . '/../build/widgets/blocks/' => array( + 'block_folders' => array( + 'legacy-widget', + ), 'block_names' => array( - 'widget-area.php' => 'core/widget-area', + 'legacy-widget.php' => 'core/legacy-widget', ), ), ); diff --git a/lib/client-assets.php b/lib/client-assets.php index c52c5ae04f2b04..3a366796d6218c 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -447,7 +447,7 @@ function gutenberg_register_packages_styles( $styles ) { $styles, 'wp-edit-widgets', gutenberg_url( 'build/edit-widgets/style.css' ), - array( 'wp-components', 'wp-block-editor', 'wp-edit-blocks', 'wp-reusable-blocks' ), + array( 'wp-components', 'wp-block-editor', 'wp-edit-blocks', 'wp-reusable-blocks', 'wp-widgets' ), $version ); $styles->add_data( 'wp-edit-widgets', 'rtl', 'replace' ); @@ -465,7 +465,7 @@ function gutenberg_register_packages_styles( $styles ) { $styles, 'wp-customize-widgets', gutenberg_url( 'build/customize-widgets/style.css' ), - array( 'wp-components', 'wp-block-editor', 'wp-edit-blocks' ), + array( 'wp-components', 'wp-block-editor', 'wp-edit-blocks', 'wp-widgets' ), $version ); $styles->add_data( 'wp-customize-widgets', 'rtl', 'replace' ); @@ -478,6 +478,14 @@ function gutenberg_register_packages_styles( $styles ) { $version ); $styles->add_data( 'wp-reusable-block', 'rtl', 'replace' ); + + gutenberg_override_style( + $styles, + 'wp-widgets', + gutenberg_url( 'build/widgets/style.css' ), + array( 'wp-components' ) + ); + $styles->add_data( 'wp-widgets', 'rtl', 'replace' ); } add_action( 'wp_default_styles', 'gutenberg_register_packages_styles' ); diff --git a/lib/widgets-page.php b/lib/widgets-page.php index 06376c2c71e396..1a4089eea66fd7 100644 --- a/lib/widgets-page.php +++ b/lib/widgets-page.php @@ -103,3 +103,59 @@ function gutenberg_widgets_editor_load_block_editor_scripts_and_styles( $is_bloc function gutenberg_widgets_editor_add_admin_body_classes( $classes ) { return "$classes block-editor-page wp-embed-responsive"; } + +/** + * Emulates the Widgets screen `admin_print_styles` when at the block editor + * screen. + */ +function gutenberg_block_editor_admin_print_styles() { + if ( is_callable( 'get_current_screen' ) && 'appearance_page_gutenberg-widgets' === get_current_screen()->base ) { + /** This action is documented in wp-admin/admin-footer.php */ + // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores + do_action( 'admin_print_styles-widgets.php' ); + } +} +add_action( 'admin_print_styles', 'gutenberg_block_editor_admin_print_styles' ); + +/** + * Emulates the Widgets screen `admin_print_scripts` when at the block editor + * screen. + */ +function gutenberg_block_editor_admin_print_scripts() { + if ( is_callable( 'get_current_screen' ) && 'appearance_page_gutenberg-widgets' === get_current_screen()->base ) { + /** This action is documented in wp-admin/includes/ajax-actions.php */ + do_action( 'load-widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores + /** This action is documented in wp-admin/includes/ajax-actions.php */ + do_action( 'widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores + /** This action is documented in wp-admin/widgets.php */ + do_action( 'sidebar_admin_setup' ); + // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores + do_action( 'admin_print_scripts-widgets.php' ); + } +} +add_action( 'admin_print_scripts', 'gutenberg_block_editor_admin_print_scripts' ); + +/** + * Emulates the Widgets screen `admin_print_footer_scripts` when at the block + * editor screen. + */ +function gutenberg_block_editor_admin_print_footer_scripts() { + if ( is_callable( 'get_current_screen' ) && 'appearance_page_gutenberg-widgets' === get_current_screen()->base ) { + /** This action is documented in wp-admin/admin-footer.php */ + // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores + do_action( 'admin_print_footer_scripts-widgets.php' ); + } +} +add_action( 'admin_print_footer_scripts', 'gutenberg_block_editor_admin_print_footer_scripts' ); + +/** + * Emulates the Widgets screen `admin_footer` when at the block editor screen. + */ +function gutenberg_block_editor_admin_footer() { + if ( is_callable( 'get_current_screen' ) && 'appearance_page_gutenberg-widgets' === get_current_screen()->base ) { + /** This action is documented in wp-admin/admin-footer.php */ + // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores + do_action( 'admin_footer-widgets.php' ); + } +} +add_action( 'admin_footer', 'gutenberg_block_editor_admin_footer' ); diff --git a/lib/widgets.php b/lib/widgets.php index c61d2c1106edc6..314b4f30c2ff8b 100644 --- a/lib/widgets.php +++ b/lib/widgets.php @@ -11,6 +11,12 @@ * @return boolean True if a screen containing the block editor is being loaded. */ function gutenberg_is_block_editor() { + _deprecated_function( + 'gutenberg_is_block_editor', + '10.8', + 'WP_Screen::is_block_editor' + ); + // If get_current_screen does not exist, we are neither in the standard block editor for posts, or the widget block editor. // We can safely return false. if ( ! function_exists( 'get_current_screen' ) ) { @@ -44,79 +50,6 @@ function gutenberg_use_widgets_block_editor() { ); } -/** - * Emulates the Widgets screen `admin_print_styles` when at the block editor - * screen. - */ -function gutenberg_block_editor_admin_print_styles() { - if ( gutenberg_is_block_editor() ) { - /** This action is documented in wp-admin/admin-footer.php */ - // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores - do_action( 'admin_print_styles-widgets.php' ); - } -} -add_action( 'admin_print_styles', 'gutenberg_block_editor_admin_print_styles' ); - -/** - * Emulates the Widgets screen `admin_print_scripts` when at the block editor - * screen. - */ -function gutenberg_block_editor_admin_print_scripts() { - if ( gutenberg_is_block_editor() ) { - /** This action is documented in wp-admin/includes/ajax-actions.php */ - do_action( 'load-widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores - /** This action is documented in wp-admin/includes/ajax-actions.php */ - do_action( 'widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores - /** This action is documented in wp-admin/widgets.php */ - do_action( 'sidebar_admin_setup' ); - // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores - do_action( 'admin_print_scripts-widgets.php' ); - } -} -add_action( 'admin_print_scripts', 'gutenberg_block_editor_admin_print_scripts' ); - -/** - * Emulates the Widgets screen `admin_print_footer_scripts` when at the block - * editor screen. - */ -function gutenberg_block_editor_admin_print_footer_scripts() { - if ( gutenberg_is_block_editor() ) { - /** This action is documented in wp-admin/admin-footer.php */ - // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores - do_action( 'admin_print_footer_scripts-widgets.php' ); - } -} -add_action( 'admin_print_footer_scripts', 'gutenberg_block_editor_admin_print_footer_scripts' ); - -/** - * Emulates the Widgets screen `admin_footer` when at the block editor screen. - */ -function gutenberg_block_editor_admin_footer() { - if ( gutenberg_is_block_editor() ) { - /** This action is documented in wp-admin/admin-footer.php */ - // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores - do_action( 'admin_footer-widgets.php' ); - } -} -add_action( 'admin_footer', 'gutenberg_block_editor_admin_footer' ); - -/** - * Adds a save widgets nonce required by the legacy widgets block. - */ -function gutenberg_print_save_widgets_nonce() { - // The function wpWidgets.save needs this nonce to work as expected. - echo implode( - "\n", - array( - '
    ', - wp_nonce_field( 'save-sidebar-widgets', '_wpnonce_widgets', false ), - '
    ', - ) - ); -} -add_action( 'admin_footer-widgets.php', 'gutenberg_print_save_widgets_nonce' ); - - /** * Returns the settings required by legacy widgets blocks. * @@ -137,7 +70,6 @@ function gutenberg_get_legacy_widget_settings() { 'media_image', 'media_gallery', 'media_video', - 'meta', 'search', 'text', 'categories', @@ -151,90 +83,11 @@ function gutenberg_get_legacy_widget_settings() { ) ); - // Backwards compatibility. Remove this in or after Gutenberg 10.5. - if ( has_filter( 'widgets_to_exclude_from_legacy_widget_block' ) ) { - /** - * Filters the list of widget classes that should **not** be offered by the legacy widget block. - * - * Returning an empty array will make all the widgets available. - * - * @param array $widgets An array of excluded widgets classnames. - * - * @since 5.6.0 - */ - $widgets_to_exclude_from_legacy_widget_block = apply_filters( - 'widgets_to_exclude_from_legacy_widget_block', - array( - 'WP_Widget_Block', - 'WP_Widget_Pages', - 'WP_Widget_Calendar', - 'WP_Widget_Archives', - 'WP_Widget_Media_Audio', - 'WP_Widget_Media_Image', - 'WP_Widget_Media_Gallery', - 'WP_Widget_Media_Video', - 'WP_Widget_Meta', - 'WP_Widget_Search', - 'WP_Widget_Text', - 'WP_Widget_Categories', - 'WP_Widget_Recent_Posts', - 'WP_Widget_Recent_Comments', - 'WP_Widget_RSS', - 'WP_Widget_Tag_Cloud', - 'WP_Nav_Menu_Widget', - 'WP_Widget_Custom_HTML', - ) - ); - - _deprecated_hook( - 'widgets_to_exclude_from_legacy_widget_block', - '10.3', - "wp.hooks.addFilter( 'legacyWidget.isWidgetTypeHidden', ... )" - ); - - foreach ( $wp_widget_factory->widgets as $widget ) { - if ( - in_array( get_class( $widget ), $widgets_to_exclude_from_legacy_widget_block, true ) && - ! in_array( $widget->id_base, $widget_types_to_hide_from_legacy_widget_block, true ) - ) { - $widget_types_to_hide_from_legacy_widget_block[] = $widget->id_base; - } - } - } - $settings['widgetTypesToHideFromLegacyWidgetBlock'] = $widget_types_to_hide_from_legacy_widget_block; return $settings; } -/** - * Extends default editor settings with values supporting legacy widgets. - * - * This can be removed when plugin support requires WordPress 5.8.0+. - * - * @param array $settings Default editor settings. - * - * @return array Filtered editor settings. - */ -function gutenberg_legacy_widget_settings( $settings ) { - return array_merge( $settings, gutenberg_get_legacy_widget_settings() ); -} -// This can be removed when plugin support requires WordPress 5.8.0+. -if ( function_exists( 'get_block_editor_settings' ) ) { - add_filter( 'block_editor_settings_all', 'gutenberg_legacy_widget_settings' ); -} else { - add_filter( 'block_editor_settings', 'gutenberg_legacy_widget_settings' ); -} - -/** - * Function to enqueue admin-widgets as part of the block editor assets. - */ -function gutenberg_enqueue_widget_scripts() { - wp_enqueue_script( 'admin-widgets' ); -} - -add_action( 'enqueue_block_editor_assets', 'gutenberg_enqueue_widget_scripts' ); - /** * Overrides dynamic_sidebar_params to make sure Blocks are not wrapped in
    tag. * @@ -308,4 +161,7 @@ function gutenberg_set_show_instance_in_rest_on_core_widgets() { } } } -add_action( 'widgets_init', 'gutenberg_set_show_instance_in_rest_on_core_widgets' ); + +if ( ! function_exists( 'wp_use_widgets_block_editor' ) ) { + add_action( 'widgets_init', 'gutenberg_set_show_instance_in_rest_on_core_widgets' ); +} diff --git a/package-lock.json b/package-lock.json index 5254251b971ef4..a6961d1e495acc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14279,12 +14279,20 @@ "version": "file:packages/widgets", "requires": { "@babel/runtime": "^7.13.10", + "@wordpress/api-fetch": "file:packages/api-fetch", + "@wordpress/block-editor": "file:packages/block-editor", "@wordpress/blocks": "file:packages/blocks", "@wordpress/components": "file:packages/components", + "@wordpress/compose": "file:packages/compose", "@wordpress/core-data": "file:packages/core-data", "@wordpress/data": "file:packages/data", + "@wordpress/element": "file:packages/element", "@wordpress/i18n": "file:packages/i18n", - "@wordpress/icons": "file:packages/icons" + "@wordpress/icons": "file:packages/icons", + "@wordpress/notices": "file:packages/notices", + "@wordpress/url": "file:packages/url", + "classnames": "^2.2.5", + "lodash": "^4.17.21" } }, "@wordpress/wordcount": { diff --git a/packages/block-library/CHANGELOG.md b/packages/block-library/CHANGELOG.md index 46b6aa9443a5ee..62ed002f5d028e 100644 --- a/packages/block-library/CHANGELOG.md +++ b/packages/block-library/CHANGELOG.md @@ -2,6 +2,11 @@ ## Unreleased +## Breaking Changes + +- Removes the `core/legacy-widget` block. This is now in `@wordpress/widgets` + via `registerLegacyWidgetBlock()`. + ## 3.2.0 (2021-05-24) ### New Features diff --git a/packages/block-library/src/editor.scss b/packages/block-library/src/editor.scss index 4118213572e232..49d89ff9e7c3f9 100644 --- a/packages/block-library/src/editor.scss +++ b/packages/block-library/src/editor.scss @@ -20,7 +20,6 @@ @import "./html/editor.scss"; @import "./image/editor.scss"; @import "./latest-posts/editor.scss"; -@import "./legacy-widget/editor.scss"; @import "./media-text/editor.scss"; @import "./more/editor.scss"; @import "./navigation/editor.scss"; diff --git a/packages/block-library/src/index.js b/packages/block-library/src/index.js index 73713305c10308..0716373e244b8b 100644 --- a/packages/block-library/src/index.js +++ b/packages/block-library/src/index.js @@ -38,7 +38,6 @@ import * as navigationLink from './navigation-link'; import * as homeLink from './home-link'; import * as latestComments from './latest-comments'; import * as latestPosts from './latest-posts'; -import * as legacyWidget from './legacy-widget'; import * as logInOut from './loginout'; import * as list from './list'; import * as missing from './missing'; @@ -148,7 +147,6 @@ export const __experimentalGetCoreBlocks = () => [ mediaText, latestComments, latestPosts, - legacyWidget, missing, more, nextpage, diff --git a/packages/customize-widgets/src/index.js b/packages/customize-widgets/src/index.js index 1b2d02b3c81fd9..3a725ccdda2ba6 100644 --- a/packages/customize-widgets/src/index.js +++ b/packages/customize-widgets/src/index.js @@ -7,7 +7,10 @@ import { __experimentalGetCoreBlocks, __experimentalRegisterExperimentalCoreBlocks, } from '@wordpress/block-library'; -import { registerLegacyWidgetVariations } from '@wordpress/widgets'; +import { + registerLegacyWidgetBlock, + registerLegacyWidgetVariations, +} from '@wordpress/widgets'; /** * Internal dependencies @@ -30,11 +33,10 @@ export function initialize( editorName, blockEditorSettings ) { ( block ) => ! [ 'core/more' ].includes( block.name ) ); registerCoreBlocks( coreBlocks ); - + registerLegacyWidgetBlock(); if ( process.env.GUTENBERG_PHASE === 2 ) { __experimentalRegisterExperimentalCoreBlocks(); } - registerLegacyWidgetVariations( blockEditorSettings ); const SidebarControl = getSidebarControl( blockEditorSettings ); diff --git a/packages/e2e-tests/fixtures/blocks/core__legacy-widget.html b/packages/e2e-tests/fixtures/blocks/core__legacy-widget.html deleted file mode 100644 index 293a884c37414f..00000000000000 --- a/packages/e2e-tests/fixtures/blocks/core__legacy-widget.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/packages/e2e-tests/fixtures/blocks/core__legacy-widget.json b/packages/e2e-tests/fixtures/blocks/core__legacy-widget.json deleted file mode 100644 index fc919a1597d6ca..00000000000000 --- a/packages/e2e-tests/fixtures/blocks/core__legacy-widget.json +++ /dev/null @@ -1,18 +0,0 @@ -[ - { - "clientId": "_clientId_0", - "name": "core/legacy-widget", - "isValid": true, - "attributes": { - "id": null, - "idBase": "search", - "instance": { - "encoded": "YTowOnt9", - "hash": "b9b82f721929717273108125217fbcd9", - "raw": {} - } - }, - "innerBlocks": [], - "originalContent": "" - } -] diff --git a/packages/e2e-tests/fixtures/blocks/core__legacy-widget.parsed.json b/packages/e2e-tests/fixtures/blocks/core__legacy-widget.parsed.json deleted file mode 100644 index e97d26c0f43b22..00000000000000 --- a/packages/e2e-tests/fixtures/blocks/core__legacy-widget.parsed.json +++ /dev/null @@ -1,16 +0,0 @@ -[ - { - "blockName": "core/legacy-widget", - "attrs": { - "idBase": "search", - "instance": { - "encoded": "YTowOnt9", - "hash": "b9b82f721929717273108125217fbcd9", - "raw": {} - } - }, - "innerBlocks": [], - "innerHTML": "", - "innerContent": [] - } -] diff --git a/packages/e2e-tests/fixtures/blocks/core__legacy-widget.serialized.html b/packages/e2e-tests/fixtures/blocks/core__legacy-widget.serialized.html deleted file mode 100644 index 293a884c37414f..00000000000000 --- a/packages/e2e-tests/fixtures/blocks/core__legacy-widget.serialized.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/packages/e2e-tests/specs/editor/plugins/__snapshots__/wp-editor-meta-box.test.js.snap b/packages/e2e-tests/specs/editor/plugins/__snapshots__/wp-editor-meta-box.test.js.snap index 485862873b648d..29a3d82f5f0685 100644 --- a/packages/e2e-tests/specs/editor/plugins/__snapshots__/wp-editor-meta-box.test.js.snap +++ b/packages/e2e-tests/specs/editor/plugins/__snapshots__/wp-editor-meta-box.test.js.snap @@ -1,3 +1,3 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`WP Editor Meta Boxes Should save the changes 1`] = `"

    Typing in a metabox

    "`; +exports[`WP Editor Meta Boxes Should save the changes 1`] = `"Typing in a metabox"`; diff --git a/packages/edit-widgets/src/index.js b/packages/edit-widgets/src/index.js index c1582396ddef25..b69edb7b2fc132 100644 --- a/packages/edit-widgets/src/index.js +++ b/packages/edit-widgets/src/index.js @@ -12,7 +12,10 @@ import { __experimentalRegisterExperimentalCoreBlocks, } from '@wordpress/block-library'; import { __experimentalFetchLinkSuggestions as fetchLinkSuggestions } from '@wordpress/core-data'; -import { registerLegacyWidgetVariations } from '@wordpress/widgets'; +import { + registerLegacyWidgetBlock, + registerLegacyWidgetVariations, +} from '@wordpress/widgets'; /** * Internal dependencies @@ -33,6 +36,7 @@ export function initialize( id, settings ) { ( block ) => ! [ 'core/more' ].includes( block.name ) ); registerCoreBlocks( coreBlocks ); + registerLegacyWidgetBlock(); if ( process.env.GUTENBERG_PHASE === 2 ) { __experimentalRegisterExperimentalCoreBlocks(); } diff --git a/packages/widgets/package.json b/packages/widgets/package.json index 728213cd52ff16..fe46cb0f44d96c 100644 --- a/packages/widgets/package.json +++ b/packages/widgets/package.json @@ -21,12 +21,20 @@ "react-native": "src/index", "dependencies": { "@babel/runtime": "^7.13.10", + "@wordpress/api-fetch": "file:../api-fetch", + "@wordpress/block-editor": "file:../block-editor", "@wordpress/blocks": "file:../blocks", "@wordpress/components": "file:../components", + "@wordpress/compose": "file:../compose", "@wordpress/core-data": "file:../core-data", "@wordpress/data": "file:../data", + "@wordpress/element": "file:../element", "@wordpress/i18n": "file:../i18n", - "@wordpress/icons": "file:../icons" + "@wordpress/icons": "file:../icons", + "@wordpress/notices": "file:../notices", + "@wordpress/url": "file:../url", + "classnames": "^2.2.5", + "lodash": "^4.17.21" }, "publishConfig": { "access": "public" diff --git a/packages/block-library/src/legacy-widget/README.md b/packages/widgets/src/blocks/legacy-widget/README.md similarity index 100% rename from packages/block-library/src/legacy-widget/README.md rename to packages/widgets/src/blocks/legacy-widget/README.md diff --git a/packages/block-library/src/legacy-widget/block.json b/packages/widgets/src/blocks/legacy-widget/block.json similarity index 100% rename from packages/block-library/src/legacy-widget/block.json rename to packages/widgets/src/blocks/legacy-widget/block.json diff --git a/packages/block-library/src/legacy-widget/edit/control.js b/packages/widgets/src/blocks/legacy-widget/edit/control.js similarity index 100% rename from packages/block-library/src/legacy-widget/edit/control.js rename to packages/widgets/src/blocks/legacy-widget/edit/control.js diff --git a/packages/block-library/src/legacy-widget/edit/convert-to-blocks-button.js b/packages/widgets/src/blocks/legacy-widget/edit/convert-to-blocks-button.js similarity index 100% rename from packages/block-library/src/legacy-widget/edit/convert-to-blocks-button.js rename to packages/widgets/src/blocks/legacy-widget/edit/convert-to-blocks-button.js diff --git a/packages/block-library/src/legacy-widget/edit/form.js b/packages/widgets/src/blocks/legacy-widget/edit/form.js similarity index 100% rename from packages/block-library/src/legacy-widget/edit/form.js rename to packages/widgets/src/blocks/legacy-widget/edit/form.js diff --git a/packages/block-library/src/legacy-widget/edit/index.js b/packages/widgets/src/blocks/legacy-widget/edit/index.js similarity index 100% rename from packages/block-library/src/legacy-widget/edit/index.js rename to packages/widgets/src/blocks/legacy-widget/edit/index.js diff --git a/packages/block-library/src/legacy-widget/edit/inspector-card.js b/packages/widgets/src/blocks/legacy-widget/edit/inspector-card.js similarity index 100% rename from packages/block-library/src/legacy-widget/edit/inspector-card.js rename to packages/widgets/src/blocks/legacy-widget/edit/inspector-card.js diff --git a/packages/block-library/src/legacy-widget/edit/no-preview.js b/packages/widgets/src/blocks/legacy-widget/edit/no-preview.js similarity index 100% rename from packages/block-library/src/legacy-widget/edit/no-preview.js rename to packages/widgets/src/blocks/legacy-widget/edit/no-preview.js diff --git a/packages/block-library/src/legacy-widget/edit/preview.js b/packages/widgets/src/blocks/legacy-widget/edit/preview.js similarity index 100% rename from packages/block-library/src/legacy-widget/edit/preview.js rename to packages/widgets/src/blocks/legacy-widget/edit/preview.js diff --git a/packages/block-library/src/legacy-widget/edit/widget-type-selector.js b/packages/widgets/src/blocks/legacy-widget/edit/widget-type-selector.js similarity index 100% rename from packages/block-library/src/legacy-widget/edit/widget-type-selector.js rename to packages/widgets/src/blocks/legacy-widget/edit/widget-type-selector.js diff --git a/packages/block-library/src/legacy-widget/editor.scss b/packages/widgets/src/blocks/legacy-widget/editor.scss similarity index 98% rename from packages/block-library/src/legacy-widget/editor.scss rename to packages/widgets/src/blocks/legacy-widget/editor.scss index 710e4d905879cf..0d9a2164754207 100644 --- a/packages/block-library/src/legacy-widget/editor.scss +++ b/packages/widgets/src/blocks/legacy-widget/editor.scss @@ -63,8 +63,9 @@ .wp-block-legacy-widget__edit-no-preview { background: $gray-100; - padding: $grid-unit-10 $grid-unit-15; + font-family: $default-font; font-size: $default-font-size; + padding: $grid-unit-10 $grid-unit-15; h3 { font-size: 14px; diff --git a/packages/block-library/src/legacy-widget/index.js b/packages/widgets/src/blocks/legacy-widget/index.js similarity index 100% rename from packages/block-library/src/legacy-widget/index.js rename to packages/widgets/src/blocks/legacy-widget/index.js diff --git a/packages/block-library/src/legacy-widget/index.php b/packages/widgets/src/blocks/legacy-widget/index.php similarity index 100% rename from packages/block-library/src/legacy-widget/index.php rename to packages/widgets/src/blocks/legacy-widget/index.php diff --git a/packages/block-library/src/legacy-widget/transforms.js b/packages/widgets/src/blocks/legacy-widget/transforms.js similarity index 100% rename from packages/block-library/src/legacy-widget/transforms.js rename to packages/widgets/src/blocks/legacy-widget/transforms.js diff --git a/packages/widgets/src/index.js b/packages/widgets/src/index.js index 03f11440474a82..c02afc7a3f57cf 100644 --- a/packages/widgets/src/index.js +++ b/packages/widgets/src/index.js @@ -1,3 +1,27 @@ +/** + * WordPress dependencies + */ +import { registerBlockType } from '@wordpress/blocks'; + +/** + * Internal dependencies + */ +import * as legacyWidget from './blocks/legacy-widget'; + export * from './components'; -export { default as registerLegacyWidgetVariations } from './register-legacy-widget-variations'; export * from './utils'; + +/** + * Registers the Legacy Widget block. + * + * Note that for the block to be useful, any scripts required by a widget must + * be loaded into the page. + * + * @see https://developer.wordpress.org/block-editor/how-to-guides/widgets/legacy-widget-block/ + */ +export function registerLegacyWidgetBlock() { + const { metadata, settings, name } = legacyWidget; + registerBlockType( { name, ...metadata }, settings ); +} + +export { default as registerLegacyWidgetVariations } from './register-legacy-widget-variations'; diff --git a/packages/widgets/src/style.scss b/packages/widgets/src/style.scss new file mode 100644 index 00000000000000..4ba09348938568 --- /dev/null +++ b/packages/widgets/src/style.scss @@ -0,0 +1 @@ +@import "./blocks/legacy-widget/editor.scss"; diff --git a/webpack.config.js b/webpack.config.js index e319703d77d5a8..acb2e7a1f405c6 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -248,6 +248,7 @@ module.exports = { './packages/block-library/src/': 'build/block-library/blocks/', './packages/edit-widgets/src/blocks/': 'build/edit-widgets/blocks/', + './packages/widgets/src/blocks/': 'build/widgets/blocks/', } ).flatMap( ( [ from, to ] ) => [ { from: `${ from }/**/index.php`, From 388b7e387a9b759dab4f3f2c5d4ff8a1a61383a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ella=20van=C2=A0Durpe?= <4710635+ellatrix@users.noreply.github.com> Date: Fri, 11 Jun 2021 10:55:50 +0300 Subject: [PATCH 11/20] Drop zone: fix horizontal indicator (#32589) --- .../src/components/use-block-drop-zone/index.js | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/packages/block-editor/src/components/use-block-drop-zone/index.js b/packages/block-editor/src/components/use-block-drop-zone/index.js index 019f80af6d59da..62e13c9b6b0af9 100644 --- a/packages/block-editor/src/components/use-block-drop-zone/index.js +++ b/packages/block-editor/src/components/use-block-drop-zone/index.js @@ -89,20 +89,15 @@ export default function useBlockDropZone( { } = {} ) { const [ targetBlockIndex, setTargetBlockIndex ] = useState( null ); - const { isLockedAll, orientation } = useSelect( + const isLockedAll = useSelect( ( select ) => { - const { getBlockListSettings, getTemplateLock } = select( - blockEditorStore - ); - return { - isLockedAll: getTemplateLock( targetRootClientId ) === 'all', - orientation: getBlockListSettings( targetRootClientId ) - ?.orientation, - }; + const { getTemplateLock } = select( blockEditorStore ); + return getTemplateLock( targetRootClientId ) === 'all'; }, [ targetRootClientId ] ); + const { getBlockListSettings } = useSelect( blockEditorStore ); const { showInsertionPoint, hideInsertionPoint } = useDispatch( blockEditorStore ); @@ -114,7 +109,7 @@ export default function useBlockDropZone( { const targetIndex = getNearestBlockIndex( blockElements, { x: event.clientX, y: event.clientY }, - orientation + getBlockListSettings( targetRootClientId )?.orientation ); setTargetBlockIndex( targetIndex === undefined ? 0 : targetIndex ); From 622b612bfd1a6b3e0db5237808afe2fa7845852f Mon Sep 17 00:00:00 2001 From: Joen A <1204802+jasmussen@users.noreply.github.com> Date: Fri, 11 Jun 2021 12:36:03 +0200 Subject: [PATCH 12/20] Fix Safari 13 issue. (#32581) * Fix Safari 13 issue. * Another fix. --- packages/edit-post/src/components/visual-editor/index.js | 2 +- packages/edit-post/src/components/visual-editor/style.scss | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/edit-post/src/components/visual-editor/index.js b/packages/edit-post/src/components/visual-editor/index.js index 9164bdfd2c9549..f4b89f28679179 100644 --- a/packages/edit-post/src/components/visual-editor/index.js +++ b/packages/edit-post/src/components/visual-editor/index.js @@ -119,7 +119,7 @@ export default function VisualEditor( { styles } ) { const { clearSelectedBlock } = useDispatch( blockEditorStore ); const { setIsEditingTemplate } = useDispatch( editPostStore ); const desktopCanvasStyles = { - height: '100%', + minHeight: '100%', width: '100%', margin: 0, display: 'flex', diff --git a/packages/edit-post/src/components/visual-editor/style.scss b/packages/edit-post/src/components/visual-editor/style.scss index 9631ae92f5597b..207388691d25d7 100644 --- a/packages/edit-post/src/components/visual-editor/style.scss +++ b/packages/edit-post/src/components/visual-editor/style.scss @@ -61,6 +61,9 @@ .edit-post-visual-editor__content-area { width: 100%; - height: 100%; + // If this is set to height: 100%; it breaks in Safari 13, which calculates the height relatively to the incorrect flex container. + // By setting it as a min-height instead, it appears to work in all cases. + min-height: 100%; position: relative; + display: flex; } From a68b766dae7581bf0f2f23200be14588f77587f6 Mon Sep 17 00:00:00 2001 From: Joen A <1204802+jasmussen@users.noreply.github.com> Date: Fri, 11 Jun 2021 17:48:55 +0200 Subject: [PATCH 13/20] Widgets: Try to fix color inheritance for social links. (#32625) --- .../block-library/src/social-links/style.scss | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/packages/block-library/src/social-links/style.scss b/packages/block-library/src/social-links/style.scss index eb1d5bc57934c3..eee1000a913f24 100644 --- a/packages/block-library/src/social-links/style.scss +++ b/packages/block-library/src/social-links/style.scss @@ -69,7 +69,7 @@ } } -.wp-social-link { +.wp-block-social-link { display: block; border-radius: 9999px; // This makes it pill-shaped instead of oval, in cases where the image fed is not perfectly sized. transition: transform 0.1s ease; @@ -84,20 +84,22 @@ transition: transform 0.1s ease; } - a, - a:hover, - a:active, - a:visited, - svg { - color: currentColor; - fill: currentColor; - } - &:hover { transform: scale(1.1); } } +// This needs specificity because themes usually override it with things like .widget-area a. +.wp-block-social-links .wp-block-social-link .wp-block-social-link-anchor { + &, + &:hover, + &:active, + &:visited, + svg { + color: currentColor; + fill: currentColor; + } +} // Provide colors for a range of icons. .wp-block-social-links:not(.is-style-logos-only) { From 207ceec1859ac790ddacd4e841f79e590fa96c39 Mon Sep 17 00:00:00 2001 From: Kai Hao Date: Fri, 11 Jun 2021 18:04:25 +0800 Subject: [PATCH 14/20] Use button block appender in widget areas (#32580) --- packages/block-editor/CHANGELOG.md | 4 ++++ packages/block-editor/README.md | 8 +++++++- .../src/components/block-list/index.js | 4 ++-- .../components/button-block-appender/index.js | 14 +++++++++++++ packages/block-editor/src/components/index.js | 6 +++++- .../components/sidebar-block-editor/index.js | 5 ++++- .../specs/widgets/editing-widgets.test.js | 20 ++++++++++--------- .../blocks/widget-area/edit/inner-blocks.js | 2 +- 8 files changed, 48 insertions(+), 15 deletions(-) diff --git a/packages/block-editor/CHANGELOG.md b/packages/block-editor/CHANGELOG.md index 73badf8f522fab..d143158c96b437 100644 --- a/packages/block-editor/CHANGELOG.md +++ b/packages/block-editor/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### New Features + +- `ButtonBlockerAppender` is now `ButtonBlockAppender`, the original name was a typo, but is still being exported for backward compatibility. + ## 6.1.0 (2021-05-20) ## 6.0.0 (2021-05-14) diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index 8d2a07876a9fa8..a8a19f6f830211 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -253,12 +253,18 @@ Undocumented declaration. Undocumented declaration. -# **ButtonBlockerAppender** +# **ButtonBlockAppender** _Related_ - +# **ButtonBlockerAppender** + +> **Deprecated** + +Use `ButtonBlockAppender` instead. + # **ColorPalette** Undocumented declaration. diff --git a/packages/block-editor/src/components/block-list/index.js b/packages/block-editor/src/components/block-list/index.js index 96e46284d6b95d..87784cef2fbf53 100644 --- a/packages/block-editor/src/components/block-list/index.js +++ b/packages/block-editor/src/components/block-list/index.js @@ -69,12 +69,12 @@ function Root( { className, children } ) { ); } -export default function BlockList( { className, __experimentalLayout } ) { +export default function BlockList( { className, ...props } ) { usePreParsePatterns(); return ( - + ); diff --git a/packages/block-editor/src/components/button-block-appender/index.js b/packages/block-editor/src/components/button-block-appender/index.js index eecd1bf51af174..6fa49f5f614252 100644 --- a/packages/block-editor/src/components/button-block-appender/index.js +++ b/packages/block-editor/src/components/button-block-appender/index.js @@ -10,6 +10,7 @@ import { Button, Tooltip, VisuallyHidden } from '@wordpress/components'; import { forwardRef } from '@wordpress/element'; import { _x, sprintf } from '@wordpress/i18n'; import { Icon, plus } from '@wordpress/icons'; +import deprecated from '@wordpress/deprecated'; /** * Internal dependencies @@ -81,6 +82,19 @@ function ButtonBlockAppender( ); } +/** + * Use `ButtonBlockAppender` instead. + * + * @deprecated + */ +export const ButtonBlockerAppender = forwardRef( ( props, ref ) => { + deprecated( `wp.blockEditor.ButtonBlockerAppender`, { + alternative: 'wp.blockEditor.ButtonBlockAppender', + } ); + + return ButtonBlockAppender( props, ref ); +} ); + /** * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/button-block-appender/README.md */ diff --git a/packages/block-editor/src/components/index.js b/packages/block-editor/src/components/index.js index 51d9ba8c1a0dbe..bf906202779fee 100644 --- a/packages/block-editor/src/components/index.js +++ b/packages/block-editor/src/components/index.js @@ -34,7 +34,11 @@ export { BlockVerticalAlignmentControl, } from './block-vertical-alignment-control'; export { default as __experimentalBorderStyleControl } from './border-style-control'; -export { default as ButtonBlockerAppender } from './button-block-appender'; +export { + // This is a typo, but kept here for back-compat. + ButtonBlockerAppender, + default as ButtonBlockAppender, +} from './button-block-appender'; export { default as ColorPalette } from './color-palette'; export { default as ColorPaletteControl } from './color-palette/control'; export { default as ContrastChecker } from './contrast-checker'; diff --git a/packages/customize-widgets/src/components/sidebar-block-editor/index.js b/packages/customize-widgets/src/components/sidebar-block-editor/index.js index 8ba9182a9209dd..40592021000aff 100644 --- a/packages/customize-widgets/src/components/sidebar-block-editor/index.js +++ b/packages/customize-widgets/src/components/sidebar-block-editor/index.js @@ -18,6 +18,7 @@ import { WritingFlow, BlockEditorKeyboardShortcuts, __unstableBlockSettingsMenuFirstItem, + ButtonBlockAppender, } from '@wordpress/block-editor'; import { uploadMedia } from '@wordpress/media-utils'; @@ -116,7 +117,9 @@ export default function SidebarBlockEditor( { - + diff --git a/packages/e2e-tests/specs/widgets/editing-widgets.test.js b/packages/e2e-tests/specs/widgets/editing-widgets.test.js index b5d7e480d9d8de..4471506c317a6f 100644 --- a/packages/e2e-tests/specs/widgets/editing-widgets.test.js +++ b/packages/e2e-tests/specs/widgets/editing-widgets.test.js @@ -123,13 +123,6 @@ describe( 'Widgets screen', () => { ).toBe( true ); } - async function getInlineInserterButton() { - return await find( { - role: 'combobox', - name: 'Add block', - } ); - } - it( 'Should insert content using the global inserter', async () => { const updateButton = await find( { role: 'button', @@ -274,7 +267,10 @@ describe( 'Widgets screen', () => { 10 ); - let inlineInserterButton = await getInlineInserterButton(); + let inlineInserterButton = await find( { + role: 'combobox', + name: 'Add block', + } ); await inlineInserterButton.click(); let inlineQuickInserter = await find( { @@ -334,7 +330,13 @@ describe( 'Widgets screen', () => { secondParagraphBlockBoundingBox.y - 10 ); - inlineInserterButton = await getInlineInserterButton(); + // There will be 2 matches here. + // One is the in-between inserter, + // and the other one is the button block appender. + [ inlineInserterButton ] = await findAll( { + role: 'combobox', + name: 'Add block', + } ); await inlineInserterButton.click(); // TODO: Convert to find() API from puppeteer-testing-library. diff --git a/packages/edit-widgets/src/blocks/widget-area/edit/inner-blocks.js b/packages/edit-widgets/src/blocks/widget-area/edit/inner-blocks.js index 7b27a404a2f6c8..15ca45640a4c1a 100644 --- a/packages/edit-widgets/src/blocks/widget-area/edit/inner-blocks.js +++ b/packages/edit-widgets/src/blocks/widget-area/edit/inner-blocks.js @@ -15,7 +15,7 @@ export default function WidgetAreaInnerBlocks() { onInput={ onInput } onChange={ onChange } templateLock={ false } - renderAppender={ InnerBlocks.DefaultBlockAppender } + renderAppender={ InnerBlocks.ButtonBlockAppender } /> ); } From ad119ad734ef2f6ec7807bbc93f873c1d635319c Mon Sep 17 00:00:00 2001 From: Kerry Liu Date: Fri, 11 Jun 2021 08:06:28 -0700 Subject: [PATCH 15/20] Performance: Remove `is-typing` root class (#32567) --- .../src/components/block-list/index.js | 34 ++++++++----------- .../src/components/block-list/style.scss | 2 +- .../use-block-props/use-block-class-names.js | 3 ++ 3 files changed, 18 insertions(+), 21 deletions(-) diff --git a/packages/block-editor/src/components/block-list/index.js b/packages/block-editor/src/components/block-list/index.js index 87784cef2fbf53..46e5d56f9f0317 100644 --- a/packages/block-editor/src/components/block-list/index.js +++ b/packages/block-editor/src/components/block-list/index.js @@ -27,25 +27,20 @@ export const IntersectionObserver = createContext(); function Root( { className, children } ) { const isLargeViewport = useViewportMatch( 'medium' ); - const { - isTyping, - isOutlineMode, - isFocusMode, - isNavigationMode, - } = useSelect( ( select ) => { - const { - isTyping: _isTyping, - getSettings, - isNavigationMode: _isNavigationMode, - } = select( blockEditorStore ); - const { outlineMode, focusMode } = getSettings(); - return { - isTyping: _isTyping(), - isOutlineMode: outlineMode, - isFocusMode: focusMode, - isNavigationMode: _isNavigationMode(), - }; - }, [] ); + const { isOutlineMode, isFocusMode, isNavigationMode } = useSelect( + ( select ) => { + const { getSettings, isNavigationMode: _isNavigationMode } = select( + blockEditorStore + ); + const { outlineMode, focusMode } = getSettings(); + return { + isOutlineMode: outlineMode, + isFocusMode: focusMode, + isNavigationMode: _isNavigationMode(), + }; + }, + [] + ); return (
    Date: Mon, 14 Jun 2021 07:25:36 +0100 Subject: [PATCH 16/20] Update the template creation modal (#32427) * Update copy and styling * Formatting * Two column layout * formatting * Polish. Co-authored-by: jasmussen --- .../components/sidebar/template/actions.js | 25 +++++++++++------ .../components/sidebar/template/style.scss | 28 ++++++++++++++++++- 2 files changed, 44 insertions(+), 9 deletions(-) diff --git a/packages/edit-post/src/components/sidebar/template/actions.js b/packages/edit-post/src/components/sidebar/template/actions.js index b7a0ccec82e7b1..968ead9b810012 100644 --- a/packages/edit-post/src/components/sidebar/template/actions.js +++ b/packages/edit-post/src/components/sidebar/template/actions.js @@ -67,7 +67,7 @@ function PostTemplateActions() {
    { isModalOpen && ( { setIsModalOpen( false ); @@ -98,18 +98,27 @@ function PostTemplateActions() { setIsModalOpen( false ); } } > - + + + + + +